]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/netxen/netxen_nic_main.c
Merge git://git.infradead.org/users/cbou/battery-2.6.29
[linux-2.6-omap-h63xx.git] / drivers / net / netxen / netxen_nic_main.c
index d854f07ef4d307b1e9caac919aadcbe487123d72..3b17a79361478fa29fdd75107254ee49986cc9ea 100644 (file)
@@ -76,6 +76,7 @@ static void netxen_nic_poll_controller(struct net_device *netdev);
 #endif
 static irqreturn_t netxen_intr(int irq, void *data);
 static irqreturn_t netxen_msi_intr(int irq, void *data);
+static irqreturn_t netxen_msix_intr(int irq, void *data);
 
 /*  PCI Device ID Table  */
 #define ENTRY(device) \
@@ -735,17 +736,18 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
 
-       /* ScatterGather support */
-       netdev->features = NETIF_F_SG;
-       netdev->features |= NETIF_F_IP_CSUM;
-       netdev->features |= NETIF_F_TSO;
+       netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
+       netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
+
        if (NX_IS_REVISION_P3(revision_id)) {
-               netdev->features |= NETIF_F_IPV6_CSUM;
-               netdev->features |= NETIF_F_TSO6;
+               netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
+               netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
        }
 
-       if (adapter->pci_using_dac)
+       if (adapter->pci_using_dac) {
                netdev->features |= NETIF_F_HIGHDMA;
+               netdev->vlan_features |= NETIF_F_HIGHDMA;
+       }
 
        /*
         * Set the CRB window to invalid. If any register in window 0 is
@@ -1083,7 +1085,9 @@ static int netxen_nic_open(struct net_device *netdev)
                        for (ring = 0; ring < adapter->max_rds_rings; ring++)
                                netxen_post_rx_buffers(adapter, ctx, ring);
                }
-               if (NETXEN_IS_MSI_FAMILY(adapter))
+               if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+                       handler = netxen_msix_intr;
+               else if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
                        handler = netxen_msi_intr;
                else {
                        flags |= IRQF_SHARED;
@@ -1166,6 +1170,14 @@ static bool netxen_tso_check(struct net_device *netdev,
 {
        bool tso = false;
        u8 opcode = TX_ETHER_PKT;
+       __be16 protocol = skb->protocol;
+       u16 flags = 0;
+
+       if (protocol == __constant_htons(ETH_P_8021Q)) {
+               struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data;
+               protocol = vh->h_vlan_encapsulated_proto;
+               flags = FLAGS_VLAN_TAGGED;
+       }
 
        if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
                        skb_shinfo(skb)->gso_size > 0) {
@@ -1174,21 +1186,21 @@ static bool netxen_tso_check(struct net_device *netdev,
                desc->total_hdr_length =
                        skb_transport_offset(skb) + tcp_hdrlen(skb);
 
-               opcode = (skb->protocol == htons(ETH_P_IPV6)) ?
+               opcode = (protocol == __constant_htons(ETH_P_IPV6)) ?
                                TX_TCP_LSO6 : TX_TCP_LSO;
                tso = true;
 
        } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                u8 l4proto;
 
-               if (skb->protocol == htons(ETH_P_IP)) {
+               if (protocol == __constant_htons(ETH_P_IP)) {
                        l4proto = ip_hdr(skb)->protocol;
 
                        if (l4proto == IPPROTO_TCP)
                                opcode = TX_TCP_PKT;
                        else if(l4proto == IPPROTO_UDP)
                                opcode = TX_UDP_PKT;
-               } else if (skb->protocol == htons(ETH_P_IPV6)) {
+               } else if (protocol == __constant_htons(ETH_P_IPV6)) {
                        l4proto = ipv6_hdr(skb)->nexthdr;
 
                        if (l4proto == IPPROTO_TCP)
@@ -1199,7 +1211,7 @@ static bool netxen_tso_check(struct net_device *netdev,
        }
        desc->tcp_hdr_offset = skb_transport_offset(skb);
        desc->ip_hdr_offset = skb_network_offset(skb);
-       netxen_set_tx_flags_opcode(desc, 0, opcode);
+       netxen_set_tx_flags_opcode(desc, flags, opcode);
        return tso;
 }
 
@@ -1603,6 +1615,14 @@ static irqreturn_t netxen_msi_intr(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t netxen_msix_intr(int irq, void *data)
+{
+       struct netxen_adapter *adapter = data;
+
+       napi_schedule(&adapter->napi);
+       return IRQ_HANDLED;
+}
+
 static int netxen_nic_poll(struct napi_struct *napi, int budget)
 {
        struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi);