From patchwork Sun Aug 7 02:46:44 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: amit salecha X-Patchwork-Id: 108808 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 90814B6F71 for ; Sun, 7 Aug 2011 13:00:04 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756852Ab1HGC4e (ORCPT ); Sat, 6 Aug 2011 22:56:34 -0400 Received: from ch1ehsobe006.messaging.microsoft.com ([216.32.181.186]:15572 "EHLO ch1outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756338Ab1HGC4d (ORCPT ); Sat, 6 Aug 2011 22:56:33 -0400 Received: from mail177-ch1-R.bigfish.com (216.32.181.173) by CH1EHSOBE016.bigfish.com (10.43.70.66) with Microsoft SMTP Server id 14.1.225.22; Sun, 7 Aug 2011 02:56:31 +0000 Received: from mail177-ch1 (localhost.localdomain [127.0.0.1]) by mail177-ch1-R.bigfish.com (Postfix) with ESMTP id C3BC18F01CC; Sun, 7 Aug 2011 02:56:31 +0000 (UTC) X-SpamScore: 0 X-BigFish: VPS0(zzzz1202hzz8275bhz2fh2a8h668h839h61h) X-Spam-TCS-SCL: 0:0 X-Forefront-Antispam-Report: CIP:198.70.193.61; KIP:(null); UIP:(null); IPVD:NLI; H:avexcashub1.qlogic.com; RD:avexcashub1.qlogic.com; EFVD:NLI Received-SPF: pass (mail177-ch1: domain of qlogic.com designates 198.70.193.61 as permitted sender) client-ip=198.70.193.61; envelope-from=amit.salecha@qlogic.com; helo=avexcashub1.qlogic.com ; 1.qlogic.com ; Received: from mail177-ch1 (localhost.localdomain [127.0.0.1]) by mail177-ch1 (MessageSwitch) id 1312685791149866_1076; Sun, 7 Aug 2011 02:56:31 +0000 (UTC) Received: from CH1EHSMHS021.bigfish.com (snatpool1.int.messaging.microsoft.com [10.43.68.244]) by mail177-ch1.bigfish.com (Postfix) with ESMTP id 21E5F1838052; Sun, 7 Aug 2011 02:56:31 +0000 (UTC) Received: from avexcashub1.qlogic.com (198.70.193.61) by CH1EHSMHS021.bigfish.com (10.43.70.21) with Microsoft SMTP Server (TLS) id 14.1.225.22; Sun, 7 Aug 2011 02:56:22 +0000 Received: from mx.mv.qlogic.com (10.29.3.18) by avexcashub1.qlc.com (10.1.4.161) with Microsoft SMTP Server id 8.3.192.1; Sat, 6 Aug 2011 19:56:19 -0700 Received: from lnxdev-sm-001.mv.qlogic.com (dut6217.mv.qlogic.com [172.29.56.217]) by mx.mv.qlogic.com (Postfix) with ESMTP id 9F30DF115B; Sat, 6 Aug 2011 19:56:19 -0700 (PDT) Received: by lnxdev-sm-001.mv.qlogic.com (Postfix, from userid 0) id BA0B314A6FC; Sat, 6 Aug 2011 19:46:44 -0700 (PDT) From: To: CC: , , Rajesh Borundia , Amit Kumar Salecha Subject: [PATCHv3 NEXT 1/1] netxen: add vlan LRO support Date: Sat, 6 Aug 2011 19:46:44 -0700 Message-ID: <1312685204-19800-1-git-send-email-amit.salecha@qlogic.com> X-Mailer: git-send-email 1.6.0.2 MIME-Version: 1.0 X-OriginatorOrg: qlogic.com Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Rajesh Borundia o To support vlan lro, driver need to program ip address in device. o Same ip addresses need to be program after fw recovery, so sotre them in list. o In case of vlan packet, include vlan header length while calculating ip and tcp headers. Signed-off-by: Rajesh Borundia Signed-off-by: Amit Kumar Salecha --- drivers/net/netxen/netxen_nic.h | 6 ++ drivers/net/netxen/netxen_nic_init.c | 8 ++- 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 f744d29..196b660 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 { uint8_t mac_addr[ETH_ALEN+2]; } nx_mac_list_t; +struct nx_vlan_ip_list { + struct list_head list; + u32 ip_addr; +}; + /* * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is * adjusted based on configured MTU. @@ -1165,6 +1170,7 @@ struct netxen_adapter { struct net_device *netdev; struct pci_dev *pdev; struct list_head mac_list; + struct list_head vlan_ip_list; spinlock_t tx_clean_lock; diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index e8993a7..d6c6357 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "netxen_nic.h" #include "netxen_nic_hw.h" @@ -1619,6 +1620,7 @@ netxen_process_lro(struct netxen_adapter *adapter, int index; u16 lro_length, length, data_offset; u32 seq_number; + u8 vhdr_len; if (unlikely(ring > adapter->max_rds_rings)) return NULL; @@ -1652,8 +1654,10 @@ netxen_process_lro(struct netxen_adapter *adapter, skb_pull(skb, l2_hdr_offset); skb->protocol = eth_type_trans(skb, netdev); - iph = (struct iphdr *)skb->data; - th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); + if (skb->protocol == htons(ETH_P_8021Q)) + vhdr_len = VLAN_HLEN; + iph = (struct iphdr *)(skb->data + vhdr_len); + th = (struct tcphdr *)((skb->data + vhdr_len) + (iph->ihl << 2)); length = (iph->ihl << 2) + (th->doff << 2) + lro_length; iph->tot_len = htons(length); diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index f574edf..8c7fc32 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); static irqreturn_t netxen_msi_intr(int irq, void *data); static irqreturn_t netxen_msix_intr(int irq, void *data); -static void netxen_config_indev_addr(struct net_device *dev, unsigned long); +static void netxen_free_vlan_ip_list(struct netxen_adapter *); +static void netxen_restore_indev_addr(struct net_device *dev, unsigned long); static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats); 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) spin_lock_init(&adapter->tx_clean_lock); INIT_LIST_HEAD(&adapter->mac_list); + INIT_LIST_HEAD(&adapter->vlan_ip_list); err = netxen_setup_pci_map(adapter); if (err) @@ -1481,6 +1483,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) cancel_work_sync(&adapter->tx_timeout_task); + netxen_free_vlan_ip_list(adapter); netxen_nic_detach(adapter); nx_decr_dev_ref_cnt(adapter); @@ -1563,7 +1566,7 @@ static int netxen_nic_attach_func(struct pci_dev *pdev) if (err) goto err_out_detach; - netxen_config_indev_addr(netdev, NETDEV_UP); + netxen_restore_indev_addr(netdev, NETDEV_UP); } netif_device_attach(netdev); @@ -2374,7 +2377,7 @@ netxen_attach_work(struct work_struct *work) goto done; } - netxen_config_indev_addr(netdev, NETDEV_UP); + netxen_restore_indev_addr(netdev, NETDEV_UP); } netif_device_attach(netdev); @@ -2848,10 +2851,70 @@ netxen_destip_supported(struct netxen_adapter *adapter) } static void -netxen_config_indev_addr(struct net_device *dev, unsigned long event) +netxen_free_vlan_ip_list(struct netxen_adapter *adapter) +{ + struct nx_vlan_ip_list *cur; + struct list_head *head = &adapter->vlan_ip_list; + + while (!list_empty(head)) { + cur = list_entry(head->next, struct nx_vlan_ip_list, list); + netxen_config_ipaddr(adapter, cur->ip_addr, NX_IP_DOWN); + list_del(&cur->list); + kfree(cur); + } + +} +static void +netxen_list_config_vlan_ip(struct netxen_adapter *adapter, + struct in_ifaddr *ifa, unsigned long event) +{ + struct net_device *dev; + struct nx_vlan_ip_list *cur, *tmp_cur; + struct list_head *head; + + dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL; + + if (dev == NULL) + return; + + if (!is_vlan_dev(dev)) + return; + + switch (event) { + case NX_IP_UP: + list_for_each(head, &adapter->vlan_ip_list) { + cur = list_entry(head, struct nx_vlan_ip_list, list); + + if (cur->ip_addr == ifa->ifa_address) + return; + } + + cur = kzalloc(sizeof(struct nx_vlan_ip_list), GFP_ATOMIC); + if (cur == NULL) { + printk(KERN_ERR "%s: failed to add vlan ip to list\n", + adapter->netdev->name); + return; + } + + cur->ip_addr = ifa->ifa_address; + list_add_tail(&cur->list, &adapter->vlan_ip_list); + break; + case NX_IP_DOWN: + list_for_each_entry_safe(cur, tmp_cur, + &adapter->vlan_ip_list, list) { + if (cur->ip_addr == ifa->ifa_address) { + list_del(&cur->list); + kfree(cur); + break; + } + } + } +} +static void +netxen_config_indev_addr(struct netxen_adapter *adapter, + struct net_device *dev, unsigned long event) { struct in_device *indev; - struct netxen_adapter *adapter = netdev_priv(dev); if (!netxen_destip_supported(adapter)) return; @@ -2865,10 +2928,12 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event) case NETDEV_UP: netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP); + netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP); break; case NETDEV_DOWN: netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN); + netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN); break; default: break; @@ -2878,11 +2943,28 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event) in_dev_put(indev); } +static void +netxen_restore_indev_addr(struct net_device *netdev, unsigned long event) + +{ + struct netxen_adapter *adapter = netdev_priv(netdev); + struct nx_vlan_ip_list *pos, *tmp_pos; + unsigned long ip_event; + + ip_event = (event == NETDEV_UP) ? NX_IP_UP : NX_IP_DOWN; + netxen_config_indev_addr(adapter, netdev, event); + + list_for_each_entry_safe(pos, tmp_pos, &adapter->vlan_ip_list, list) { + netxen_config_ipaddr(adapter, pos->ip_addr, ip_event); + } +} + static int netxen_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { struct netxen_adapter *adapter; struct net_device *dev = (struct net_device *)ptr; + struct net_device *orig_dev = dev; recheck: if (dev == NULL) @@ -2904,7 +2986,7 @@ recheck: if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) goto done; - netxen_config_indev_addr(dev, event); + netxen_config_indev_addr(adapter, orig_dev, event); done: return NOTIFY_DONE; } @@ -2921,7 +3003,7 @@ netxen_inetaddr_event(struct notifier_block *this, dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL; recheck: - if (dev == NULL || !netif_running(dev)) + if (dev == NULL) goto done; if (dev->priv_flags & IFF_802_1Q_VLAN) { @@ -2943,9 +3025,11 @@ recheck: switch (event) { case NETDEV_UP: netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP); + netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP); break; case NETDEV_DOWN: netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN); + netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN); break; default: break; @@ -2964,7 +3048,10 @@ static struct notifier_block netxen_inetaddr_cb = { }; #else static void -netxen_config_indev_addr(struct net_device *dev, unsigned long event) +netxen_restore_indev_addr(struct net_device *dev, unsigned long event) +{ } +static void +netxen_free_vlan_ip_list(struct netxen_adapter *adapter) { } #endif