diff options
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 6 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 8 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 103 |
3 files changed, 107 insertions, 10 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f744d291218a..196b660e1d91 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h | |||
@@ -940,6 +940,11 @@ typedef struct nx_mac_list_s { | |||
940 | uint8_t mac_addr[ETH_ALEN+2]; | 940 | uint8_t mac_addr[ETH_ALEN+2]; |
941 | } nx_mac_list_t; | 941 | } nx_mac_list_t; |
942 | 942 | ||
943 | struct nx_vlan_ip_list { | ||
944 | struct list_head list; | ||
945 | u32 ip_addr; | ||
946 | }; | ||
947 | |||
943 | /* | 948 | /* |
944 | * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is | 949 | * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is |
945 | * adjusted based on configured MTU. | 950 | * adjusted based on configured MTU. |
@@ -1165,6 +1170,7 @@ struct netxen_adapter { | |||
1165 | struct net_device *netdev; | 1170 | struct net_device *netdev; |
1166 | struct pci_dev *pdev; | 1171 | struct pci_dev *pdev; |
1167 | struct list_head mac_list; | 1172 | struct list_head mac_list; |
1173 | struct list_head vlan_ip_list; | ||
1168 | 1174 | ||
1169 | spinlock_t tx_clean_lock; | 1175 | spinlock_t tx_clean_lock; |
1170 | 1176 | ||
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index e8993a76a080..d6c6357de6aa 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/if_vlan.h> | ||
29 | #include "netxen_nic.h" | 30 | #include "netxen_nic.h" |
30 | #include "netxen_nic_hw.h" | 31 | #include "netxen_nic_hw.h" |
31 | 32 | ||
@@ -1619,6 +1620,7 @@ netxen_process_lro(struct netxen_adapter *adapter, | |||
1619 | int index; | 1620 | int index; |
1620 | u16 lro_length, length, data_offset; | 1621 | u16 lro_length, length, data_offset; |
1621 | u32 seq_number; | 1622 | u32 seq_number; |
1623 | u8 vhdr_len; | ||
1622 | 1624 | ||
1623 | if (unlikely(ring > adapter->max_rds_rings)) | 1625 | if (unlikely(ring > adapter->max_rds_rings)) |
1624 | return NULL; | 1626 | return NULL; |
@@ -1652,8 +1654,10 @@ netxen_process_lro(struct netxen_adapter *adapter, | |||
1652 | skb_pull(skb, l2_hdr_offset); | 1654 | skb_pull(skb, l2_hdr_offset); |
1653 | skb->protocol = eth_type_trans(skb, netdev); | 1655 | skb->protocol = eth_type_trans(skb, netdev); |
1654 | 1656 | ||
1655 | iph = (struct iphdr *)skb->data; | 1657 | if (skb->protocol == htons(ETH_P_8021Q)) |
1656 | th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); | 1658 | vhdr_len = VLAN_HLEN; |
1659 | iph = (struct iphdr *)(skb->data + vhdr_len); | ||
1660 | th = (struct tcphdr *)((skb->data + vhdr_len) + (iph->ihl << 2)); | ||
1657 | 1661 | ||
1658 | length = (iph->ihl << 2) + (th->doff << 2) + lro_length; | 1662 | length = (iph->ihl << 2) + (th->doff << 2) + lro_length; |
1659 | iph->tot_len = htons(length); | 1663 | iph->tot_len = htons(length); |
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index f574edff7fcb..8c7fc32d781f 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -91,7 +91,8 @@ static irqreturn_t netxen_intr(int irq, void *data); | |||
91 | static irqreturn_t netxen_msi_intr(int irq, void *data); | 91 | static irqreturn_t netxen_msi_intr(int irq, void *data); |
92 | static irqreturn_t netxen_msix_intr(int irq, void *data); | 92 | static irqreturn_t netxen_msix_intr(int irq, void *data); |
93 | 93 | ||
94 | static void netxen_config_indev_addr(struct net_device *dev, unsigned long); | 94 | static void netxen_free_vlan_ip_list(struct netxen_adapter *); |
95 | static void netxen_restore_indev_addr(struct net_device *dev, unsigned long); | ||
95 | static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *dev, | 96 | static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *dev, |
96 | struct rtnl_link_stats64 *stats); | 97 | struct rtnl_link_stats64 *stats); |
97 | static int netxen_nic_set_mac(struct net_device *netdev, void *p); | 98 | static int netxen_nic_set_mac(struct net_device *netdev, void *p); |
@@ -1359,6 +1360,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1359 | 1360 | ||
1360 | spin_lock_init(&adapter->tx_clean_lock); | 1361 | spin_lock_init(&adapter->tx_clean_lock); |
1361 | INIT_LIST_HEAD(&adapter->mac_list); | 1362 | INIT_LIST_HEAD(&adapter->mac_list); |
1363 | INIT_LIST_HEAD(&adapter->vlan_ip_list); | ||
1362 | 1364 | ||
1363 | err = netxen_setup_pci_map(adapter); | 1365 | err = netxen_setup_pci_map(adapter); |
1364 | if (err) | 1366 | if (err) |
@@ -1481,6 +1483,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) | |||
1481 | 1483 | ||
1482 | cancel_work_sync(&adapter->tx_timeout_task); | 1484 | cancel_work_sync(&adapter->tx_timeout_task); |
1483 | 1485 | ||
1486 | netxen_free_vlan_ip_list(adapter); | ||
1484 | netxen_nic_detach(adapter); | 1487 | netxen_nic_detach(adapter); |
1485 | 1488 | ||
1486 | nx_decr_dev_ref_cnt(adapter); | 1489 | nx_decr_dev_ref_cnt(adapter); |
@@ -1563,7 +1566,7 @@ static int netxen_nic_attach_func(struct pci_dev *pdev) | |||
1563 | if (err) | 1566 | if (err) |
1564 | goto err_out_detach; | 1567 | goto err_out_detach; |
1565 | 1568 | ||
1566 | netxen_config_indev_addr(netdev, NETDEV_UP); | 1569 | netxen_restore_indev_addr(netdev, NETDEV_UP); |
1567 | } | 1570 | } |
1568 | 1571 | ||
1569 | netif_device_attach(netdev); | 1572 | netif_device_attach(netdev); |
@@ -2374,7 +2377,7 @@ netxen_attach_work(struct work_struct *work) | |||
2374 | goto done; | 2377 | goto done; |
2375 | } | 2378 | } |
2376 | 2379 | ||
2377 | netxen_config_indev_addr(netdev, NETDEV_UP); | 2380 | netxen_restore_indev_addr(netdev, NETDEV_UP); |
2378 | } | 2381 | } |
2379 | 2382 | ||
2380 | netif_device_attach(netdev); | 2383 | netif_device_attach(netdev); |
@@ -2848,10 +2851,70 @@ netxen_destip_supported(struct netxen_adapter *adapter) | |||
2848 | } | 2851 | } |
2849 | 2852 | ||
2850 | static void | 2853 | static void |
2851 | netxen_config_indev_addr(struct net_device *dev, unsigned long event) | 2854 | netxen_free_vlan_ip_list(struct netxen_adapter *adapter) |
2855 | { | ||
2856 | struct nx_vlan_ip_list *cur; | ||
2857 | struct list_head *head = &adapter->vlan_ip_list; | ||
2858 | |||
2859 | while (!list_empty(head)) { | ||
2860 | cur = list_entry(head->next, struct nx_vlan_ip_list, list); | ||
2861 | netxen_config_ipaddr(adapter, cur->ip_addr, NX_IP_DOWN); | ||
2862 | list_del(&cur->list); | ||
2863 | kfree(cur); | ||
2864 | } | ||
2865 | |||
2866 | } | ||
2867 | static void | ||
2868 | netxen_list_config_vlan_ip(struct netxen_adapter *adapter, | ||
2869 | struct in_ifaddr *ifa, unsigned long event) | ||
2870 | { | ||
2871 | struct net_device *dev; | ||
2872 | struct nx_vlan_ip_list *cur, *tmp_cur; | ||
2873 | struct list_head *head; | ||
2874 | |||
2875 | dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL; | ||
2876 | |||
2877 | if (dev == NULL) | ||
2878 | return; | ||
2879 | |||
2880 | if (!is_vlan_dev(dev)) | ||
2881 | return; | ||
2882 | |||
2883 | switch (event) { | ||
2884 | case NX_IP_UP: | ||
2885 | list_for_each(head, &adapter->vlan_ip_list) { | ||
2886 | cur = list_entry(head, struct nx_vlan_ip_list, list); | ||
2887 | |||
2888 | if (cur->ip_addr == ifa->ifa_address) | ||
2889 | return; | ||
2890 | } | ||
2891 | |||
2892 | cur = kzalloc(sizeof(struct nx_vlan_ip_list), GFP_ATOMIC); | ||
2893 | if (cur == NULL) { | ||
2894 | printk(KERN_ERR "%s: failed to add vlan ip to list\n", | ||
2895 | adapter->netdev->name); | ||
2896 | return; | ||
2897 | } | ||
2898 | |||
2899 | cur->ip_addr = ifa->ifa_address; | ||
2900 | list_add_tail(&cur->list, &adapter->vlan_ip_list); | ||
2901 | break; | ||
2902 | case NX_IP_DOWN: | ||
2903 | list_for_each_entry_safe(cur, tmp_cur, | ||
2904 | &adapter->vlan_ip_list, list) { | ||
2905 | if (cur->ip_addr == ifa->ifa_address) { | ||
2906 | list_del(&cur->list); | ||
2907 | kfree(cur); | ||
2908 | break; | ||
2909 | } | ||
2910 | } | ||
2911 | } | ||
2912 | } | ||
2913 | static void | ||
2914 | netxen_config_indev_addr(struct netxen_adapter *adapter, | ||
2915 | struct net_device *dev, unsigned long event) | ||
2852 | { | 2916 | { |
2853 | struct in_device *indev; | 2917 | struct in_device *indev; |
2854 | struct netxen_adapter *adapter = netdev_priv(dev); | ||
2855 | 2918 | ||
2856 | if (!netxen_destip_supported(adapter)) | 2919 | if (!netxen_destip_supported(adapter)) |
2857 | return; | 2920 | return; |
@@ -2865,10 +2928,12 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event) | |||
2865 | case NETDEV_UP: | 2928 | case NETDEV_UP: |
2866 | netxen_config_ipaddr(adapter, | 2929 | netxen_config_ipaddr(adapter, |
2867 | ifa->ifa_address, NX_IP_UP); | 2930 | ifa->ifa_address, NX_IP_UP); |
2931 | netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP); | ||
2868 | break; | 2932 | break; |
2869 | case NETDEV_DOWN: | 2933 | case NETDEV_DOWN: |
2870 | netxen_config_ipaddr(adapter, | 2934 | netxen_config_ipaddr(adapter, |
2871 | ifa->ifa_address, NX_IP_DOWN); | 2935 | ifa->ifa_address, NX_IP_DOWN); |
2936 | netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN); | ||
2872 | break; | 2937 | break; |
2873 | default: | 2938 | default: |
2874 | break; | 2939 | break; |
@@ -2878,11 +2943,28 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event) | |||
2878 | in_dev_put(indev); | 2943 | in_dev_put(indev); |
2879 | } | 2944 | } |
2880 | 2945 | ||
2946 | static void | ||
2947 | netxen_restore_indev_addr(struct net_device *netdev, unsigned long event) | ||
2948 | |||
2949 | { | ||
2950 | struct netxen_adapter *adapter = netdev_priv(netdev); | ||
2951 | struct nx_vlan_ip_list *pos, *tmp_pos; | ||
2952 | unsigned long ip_event; | ||
2953 | |||
2954 | ip_event = (event == NETDEV_UP) ? NX_IP_UP : NX_IP_DOWN; | ||
2955 | netxen_config_indev_addr(adapter, netdev, event); | ||
2956 | |||
2957 | list_for_each_entry_safe(pos, tmp_pos, &adapter->vlan_ip_list, list) { | ||
2958 | netxen_config_ipaddr(adapter, pos->ip_addr, ip_event); | ||
2959 | } | ||
2960 | } | ||
2961 | |||
2881 | static int netxen_netdev_event(struct notifier_block *this, | 2962 | static int netxen_netdev_event(struct notifier_block *this, |
2882 | unsigned long event, void *ptr) | 2963 | unsigned long event, void *ptr) |
2883 | { | 2964 | { |
2884 | struct netxen_adapter *adapter; | 2965 | struct netxen_adapter *adapter; |
2885 | struct net_device *dev = (struct net_device *)ptr; | 2966 | struct net_device *dev = (struct net_device *)ptr; |
2967 | struct net_device *orig_dev = dev; | ||
2886 | 2968 | ||
2887 | recheck: | 2969 | recheck: |
2888 | if (dev == NULL) | 2970 | if (dev == NULL) |
@@ -2904,7 +2986,7 @@ recheck: | |||
2904 | if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) | 2986 | if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) |
2905 | goto done; | 2987 | goto done; |
2906 | 2988 | ||
2907 | netxen_config_indev_addr(dev, event); | 2989 | netxen_config_indev_addr(adapter, orig_dev, event); |
2908 | done: | 2990 | done: |
2909 | return NOTIFY_DONE; | 2991 | return NOTIFY_DONE; |
2910 | } | 2992 | } |
@@ -2921,7 +3003,7 @@ netxen_inetaddr_event(struct notifier_block *this, | |||
2921 | dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL; | 3003 | dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL; |
2922 | 3004 | ||
2923 | recheck: | 3005 | recheck: |
2924 | if (dev == NULL || !netif_running(dev)) | 3006 | if (dev == NULL) |
2925 | goto done; | 3007 | goto done; |
2926 | 3008 | ||
2927 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | 3009 | if (dev->priv_flags & IFF_802_1Q_VLAN) { |
@@ -2943,9 +3025,11 @@ recheck: | |||
2943 | switch (event) { | 3025 | switch (event) { |
2944 | case NETDEV_UP: | 3026 | case NETDEV_UP: |
2945 | netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP); | 3027 | netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP); |
3028 | netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP); | ||
2946 | break; | 3029 | break; |
2947 | case NETDEV_DOWN: | 3030 | case NETDEV_DOWN: |
2948 | netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN); | 3031 | netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN); |
3032 | netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN); | ||
2949 | break; | 3033 | break; |
2950 | default: | 3034 | default: |
2951 | break; | 3035 | break; |
@@ -2964,7 +3048,10 @@ static struct notifier_block netxen_inetaddr_cb = { | |||
2964 | }; | 3048 | }; |
2965 | #else | 3049 | #else |
2966 | static void | 3050 | static void |
2967 | netxen_config_indev_addr(struct net_device *dev, unsigned long event) | 3051 | netxen_restore_indev_addr(struct net_device *dev, unsigned long event) |
3052 | { } | ||
3053 | static void | ||
3054 | netxen_free_vlan_ip_list(struct netxen_adapter *adapter) | ||
2968 | { } | 3055 | { } |
2969 | #endif | 3056 | #endif |
2970 | 3057 | ||