Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH 1/1] atm/solos-pci: Don't flap VCs when carrier state changes
From: David Miller @ 2011-03-30 23:56 UTC (permalink / raw)
  To: philipp_subx; +Cc: netdev
In-Reply-To: <1301527024-28875-1-git-send-email-philipp_subx@redfish-solutions.com>


All 3 patches applied, thanks.

^ permalink raw reply

* loading sctp fails an order 10 allocation.
From: Dave Jones @ 2011-03-30 23:40 UTC (permalink / raw)
  To: netdev; +Cc: Linux Kernel

modprobe sctp on my laptop does this which looks crazy..


[28106.742435] modprobe: page allocation failure. order:10, mode:0x20
[28106.742744] Pid: 8839, comm: modprobe Not tainted 2.6.38-09065-g89078d5-dirty #6
[28106.743129] Call Trace:
[28106.743262]  [<ffffffff810f6811>] __alloc_pages_nodemask+0x7f6/0x885
[28106.743578]  [<ffffffff81193604>] ? proc_register+0x129/0x1ad
[28106.743864]  [<ffffffff81121e29>] alloc_pages_current+0xb1/0xca
[28106.744175]  [<ffffffff8126b35d>] ? __raw_spin_lock_init+0x31/0x50
[28106.744478]  [<ffffffff810f2a21>] __get_free_pages+0x16/0x53
[28106.744766]  [<ffffffffa03061a0>] sctp_init+0x1a0/0x7d5 [sctp]
[28106.745066]  [<ffffffff8103403f>] ? set_memory_ro+0x21/0x23
[28106.745349]  [<ffffffffa0306000>] ? 0xffffffffa0305fff
[28106.745607]  [<ffffffff81002193>] do_one_initcall+0x7f/0x13c
[28106.745889]  [<ffffffff81096ffb>] sys_init_module+0xe2/0x231
[28106.746184]  [<ffffffff814d6bc2>] system_call_fastpath+0x16/0x1b
[28106.746478] Mem-Info:
[28106.746595] Node 0 DMA per-cpu:
[28106.746762] CPU    0: hi:    0, btch:   1 usd:   0
[28106.746998] CPU    1: hi:    0, btch:   1 usd:   0
[28106.747256] Node 0 DMA32 per-cpu:
[28106.747433] CPU    0: hi:  186, btch:  31 usd: 164
[28106.747672] CPU    1: hi:  186, btch:  31 usd: 156
[28106.747909] Node 0 Normal per-cpu:
[28106.748103] CPU    0: hi:  186, btch:  31 usd:  93
[28106.748341] CPU    1: hi:  186, btch:  31 usd: 162
[28106.748582] active_anon:198288 inactive_anon:25897 isolated_anon:0
[28106.748584]  active_file:118670 inactive_file:224764 isolated_file:0
[28106.748585]  unevictable:4 dirty:39 writeback:0 unstable:0
[28106.748586]  free:309311 slab_reclaimable:56405 slab_unreclaimable:38498
[28106.748587]  mapped:59632 shmem:28756 pagetables:8080 bounce:0
[28106.750099] Node 0 DMA free:15900kB min:256kB low:320kB high:384kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15676kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:0kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[28106.751887] lowmem_reserve[]: 0 2959 3969 3969
[28106.752167] Node 0 DMA32 free:1208204kB min:50192kB low:62740kB high:75288kB active_anon:635892kB inactive_anon:83536kB active_file:268160kB inactive_file:620756kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:3030584kB mlocked:0kB dirty:24kB writeback:0kB mapped:150448kB shmem:90868kB slab_reclaimable:152208kB slab_unreclaimable:22560kB kernel_stack:288kB pagetables:4496kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:32 all_unreclaimable? no
[28106.754183] lowmem_reserve[]: 0 0 1010 1010
[28106.754437] Node 0 Normal free:21944kB min:17128kB low:21408kB high:25692kB active_anon:154572kB inactive_anon:22740kB active_file:206520kB inactive_file:269424kB unevictable:16kB isolated(anon):0kB isolated(file):0kB present:1034240kB mlocked:16kB dirty:132kB writeback:0kB mapped:88080kB shmem:24156kB slab_reclaimable:73412kB slab_unreclaimable:131432kB kernel_stack:2352kB pagetables:27824kB unstable:0kB bounce:0kB writeback_tmp:0kB pages_scanned:39 all_unreclaimable? no
[28106.756463] lowmem_reserve[]: 0 0 0 0
[28106.756693] Node 0 DMA: 1*4kB 1*8kB 1*16kB 0*32kB 2*64kB 1*128kB 1*256kB 0*512kB 1*1024kB 1*2048kB 3*4096kB = 15900kB
[28106.757336] Node 0 DMA32: 27*4kB 46*8kB 15*16kB 170*32kB 2428*64kB 1505*128kB 894*256kB 427*512kB 377*1024kB 6*2048kB 2*4096kB = 1208204kB
[28106.758068] Node 0 Normal: 280*4kB 390*8kB 139*16kB 80*32kB 53*64kB 36*128kB 14*256kB 2*512kB 0*1024kB 1*2048kB 0*4096kB = 23680kB
[28106.758757] 369501 total pagecache pages
[28106.758950] 0 pages in swap cache
[28106.759131] Swap cache stats: add 0, delete 0, find 0/0
[28106.759388] Free swap  = 6127612kB
[28106.759558] Total swap = 6127612kB
[28106.779675] 1048560 pages RAM
[28106.779830] 47810 pages reserved
[28106.779996] 252000 pages shared
[28106.780169] 512980 pages non-shared
[28106.785199] sctp: Hash tables configured (established 26214 bind 26214)


it doesn't look like the hashtable allocation code has changed in ages, so I'm 
not sure why I've never triggered this before.

	Dave

^ permalink raw reply

* [PATCH 1/2] atm/solos-pci: Use VPI.VCI notation uniformly.
From: Philip Prindeville @ 2011-03-30 23:22 UTC (permalink / raw)
  To: netdev

From: Philip A. Prindeville <philipp@redfish-solutions.com>

Use VPI.VCI notation consistently throughout the module. This is the
one remaining place where the VCI is used before the VPI in any output.

Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
---
 drivers/atm/solos-pci.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 25ef1a4..2c4146a 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -710,8 +710,8 @@ void solos_bh(unsigned long card_arg)
 					       le16_to_cpu(header->vci));
 				if (!vcc) {
 					if (net_ratelimit())
-						dev_warn(&card->dev->dev, "Received packet for unknown VCI.VPI %d.%d on port %d\n",
-							 le16_to_cpu(header->vci), le16_to_cpu(header->vpi),
+						dev_warn(&card->dev->dev, "Received packet for unknown VPI.VCI %d.%d on port %d\n",
+							 le16_to_cpu(header->vpi), le16_to_cpu(header->vci),
 							 port);
 					continue;
 				}
-- 
1.7.4


^ permalink raw reply related

* Re: [PATCH 1/2] Use VPI.VCI notation uniformly.
From: Philip Prindeville @ 2011-03-30 23:17 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20110330.160358.55865087.davem@davemloft.net>

On 3/30/11 5:03 PM, David Miller wrote:
> From: Philip Prindeville <philipp_subx@redfish-solutions.com>
> Date: Wed, 30 Mar 2011 16:56:27 -0600
>
>> From: Philip A. Prindeville <philipp@redfish-solutions.com>
>>
>> Use VPI.VCI notation consistently throughout the module. This is the
>> one remaining place where the VCI is used before the VPI in any output.
>>
>> Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
>> ---
>>  drivers/atm/solos-pci.c |    4 ++--
>>  1 files changed, 2 insertions(+), 2 deletions(-)
> Why do your subject lines not have an appropriate prefix?
>
> How will someone scanning the commit header lines in the tree know
> that this is a change to the solos-pci driver unless you prefix
> them with "solos-pci: " or similar?

It was an oversight.  Want me to resubmit?


^ permalink raw reply

* [PATCH 1/1] atm/solos-pci: Don't flap VCs when carrier state changes
From: Philip Prindeville @ 2011-03-30 23:17 UTC (permalink / raw)
  To: netdev

From: Philip A. Prindeville <philipp@redfish-solutions.com>

Don't flap VCs when carrier state changes; higher-level protocols
can detect loss of connectivity and act accordingly. This is more
consistent with how other network interfaces work.

We no longer use release_vccs() so we can delete it.

release_vccs() was duplicated from net/atm/common.c; make the
corresponding function exported, since other code duplicates it
and could leverage it if it were public.

Signed-off-by: Philip A. Prindeville <philipp@redfish-solutions.com>
---
 drivers/atm/solos-pci.c |   26 +-------------------------
 include/linux/atmdev.h  |    1 +
 net/atm/common.c        |    1 +
 3 files changed, 3 insertions(+), 25 deletions(-)

diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 968f022..cd0ff66 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -165,7 +165,6 @@ static uint32_t fpga_tx(struct solos_card *);
 static irqreturn_t solos_irq(int irq, void *dev_id);
 static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
 static int list_vccs(int vci);
-static void release_vccs(struct atm_dev *dev);
 static int atm_init(struct solos_card *, struct device *);
 static void atm_remove(struct solos_card *);
 static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
@@ -384,7 +383,6 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
 	/* Anything but 'Showtime' is down */
 	if (strcmp(state_str, "Showtime")) {
 		atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_LOST);
-		release_vccs(card->atmdev[port]);
 		dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str);
 		return 0;
 	}
@@ -830,28 +828,6 @@ static int list_vccs(int vci)
 	return num_found;
 }
 
-static void release_vccs(struct atm_dev *dev)
-{
-        int i;
-
-        write_lock_irq(&vcc_sklist_lock);
-        for (i = 0; i < VCC_HTABLE_SIZE; i++) {
-                struct hlist_head *head = &vcc_hash[i];
-                struct hlist_node *node, *tmp;
-                struct sock *s;
-                struct atm_vcc *vcc;
-
-                sk_for_each_safe(s, node, tmp, head) {
-                        vcc = atm_sk(s);
-                        if (vcc->dev == dev) {
-                                vcc_release_async(vcc, -EPIPE);
-                                sk_del_node_init(s);
-                        }
-                }
-        }
-        write_unlock_irq(&vcc_sklist_lock);
-}
-
 
 static int popen(struct atm_vcc *vcc)
 {
@@ -1269,7 +1245,7 @@ static int atm_init(struct solos_card *card, struct device *parent)
 		card->atmdev[i]->ci_range.vci_bits = 16;
 		card->atmdev[i]->dev_data = card;
 		card->atmdev[i]->phy_data = (void *)(unsigned long)i;
-		atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_UNKNOWN);
+		atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND);
 
 		skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
 		if (!skb) {
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 475f8c4..381f4ce 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -443,6 +443,7 @@ void atm_dev_signal_change(struct atm_dev *dev, char signal);
 
 void vcc_insert_socket(struct sock *sk);
 
+void atm_dev_release_vccs(struct atm_dev *dev);
 
 /*
  * This is approximately the algorithm used by alloc_skb.
diff --git a/net/atm/common.c b/net/atm/common.c
index 1b9c52a..22b963d 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -252,6 +252,7 @@ void atm_dev_release_vccs(struct atm_dev *dev)
 	}
 	write_unlock_irq(&vcc_sklist_lock);
 }
+EXPORT_SYMBOL(atm_dev_release_vccs);
 
 static int adjust_tp(struct atm_trafprm *tp, unsigned char aal)
 {
-- 
1.7.4


^ permalink raw reply related

* Re: [PATCH 1/2] Use VPI.VCI notation uniformly.
From: David Miller @ 2011-03-30 23:03 UTC (permalink / raw)
  To: philipp_subx; +Cc: netdev
In-Reply-To: <1301525787-28447-1-git-send-email-philipp_subx@redfish-solutions.com>

From: Philip Prindeville <philipp_subx@redfish-solutions.com>
Date: Wed, 30 Mar 2011 16:56:27 -0600

> From: Philip A. Prindeville <philipp@redfish-solutions.com>
> 
> Use VPI.VCI notation consistently throughout the module. This is the
> one remaining place where the VCI is used before the VPI in any output.
> 
> Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
> ---
>  drivers/atm/solos-pci.c |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)

Why do your subject lines not have an appropriate prefix?

How will someone scanning the commit header lines in the tree know
that this is a change to the solos-pci driver unless you prefix
them with "solos-pci: " or similar?

^ permalink raw reply

* [PATCH 2/2] atm/solos-pci: Don't include frame pseudo-header on transmit hex-dump
From: Philip Prindeville @ 2011-03-30 22:59 UTC (permalink / raw)
  To: netdev

From: Philip A. Prindeville <philipp@redfish-solutions.com>

Omit pkt_hdr preamble when dumping transmitted packet as hex-dump;
we can pull this up because the frame has already been sent, and
dumping it is the last thing we do with it before freeing it.

Also include the size, vpi, and vci in the debug as is done on
receive.

Use "port" consistently instead of "device" intermittently.

Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
---
 drivers/atm/solos-pci.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 2c4146a..968f022 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -697,7 +697,7 @@ void solos_bh(unsigned long card_arg)
 					      size);
 			}
 			if (atmdebug) {
-				dev_info(&card->dev->dev, "Received: device %d\n", port);
+				dev_info(&card->dev->dev, "Received: port %d\n", port);
 				dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
 					 size, le16_to_cpu(header->vpi),
 					 le16_to_cpu(header->vci));
@@ -1018,8 +1018,15 @@ static uint32_t fpga_tx(struct solos_card *card)
 
 			/* Clean up and free oldskb now it's gone */
 			if (atmdebug) {
+				struct pkt_hdr *header = (void *)oldskb->data;
+				int size = le16_to_cpu(header->size);
+
+				skb_pull(oldskb, sizeof(*header));
 				dev_info(&card->dev->dev, "Transmitted: port %d\n",
 					 port);
+				dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
+					 size, le16_to_cpu(header->vpi),
+					 le16_to_cpu(header->vci));
 				print_buffer(oldskb);
 			}
 
-- 
1.7.4


^ permalink raw reply related

* [PATCH 1/2] Use VPI.VCI notation uniformly.
From: Philip Prindeville @ 2011-03-30 22:56 UTC (permalink / raw)
  To: netdev

From: Philip A. Prindeville <philipp@redfish-solutions.com>

Use VPI.VCI notation consistently throughout the module. This is the
one remaining place where the VCI is used before the VPI in any output.

Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
---
 drivers/atm/solos-pci.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 25ef1a4..2c4146a 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -710,8 +710,8 @@ void solos_bh(unsigned long card_arg)
 					       le16_to_cpu(header->vci));
 				if (!vcc) {
 					if (net_ratelimit())
-						dev_warn(&card->dev->dev, "Received packet for unknown VCI.VPI %d.%d on port %d\n",
-							 le16_to_cpu(header->vci), le16_to_cpu(header->vpi),
+						dev_warn(&card->dev->dev, "Received packet for unknown VPI.VCI %d.%d on port %d\n",
+							 le16_to_cpu(header->vpi), le16_to_cpu(header->vci),
 							 port);
 					continue;
 				}
-- 
1.7.4


^ permalink raw reply related

* atl1c fails to force 100 full duplex
From: Ben Hutchings @ 2011-03-30 22:10 UTC (permalink / raw)
  To: Jay Cliburn, Chris Snook, Jie Yang; +Cc: luca boncompagni, 616081, netdev
In-Reply-To: <AANLkTi=JDec_BTNLEX5AFnK6+BvjDPEN5PZw=QJ3M5XG@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 613 bytes --]

On Wed, 2011-03-02 at 12:46 +0100, luca boncompagni wrote:
> I can't get more 100FD from my network card when running on 2.6.37, if
> I boot on 2.6.32 it works fine.
> 
> If i try to use mii-tool eth1 -F 100baseTx-FD I get the warning at the
> end of dmesg.

This is the usual TX watchdog warning.

> If I try to use ethtool I get no warning but it does not set full duplex.
[...]

Luca later reported that this is still broken in 2.6.38.  His full bug
report is at <http://bugs.debian.org/616081>.

Ben.

-- 
Ben Hutchings
Once a job is fouled up, anything done to improve it makes it worse.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply

* [PATCH 8/9 net-next-2.6] qlcnic: Fix LRO disable
From: Anirban Chakraborty @ 2011-03-30 20:23 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

From: Rajesh Borundia <rajesh.borundia@qlogic.com>

o In dev->open LRO was enabled by default, enable it depending
  upon netdev->features , kernel may have disabled it.
o Configure LRO when interface is up.

Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
---
 drivers/net/qlcnic/qlcnic_ethtool.c |   26 ++++++++++++++++----------
 drivers/net/qlcnic/qlcnic_hw.c      |    6 ++++++
 drivers/net/qlcnic/qlcnic_main.c    |    3 ++-
 3 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index e03108a..2656ec9 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -998,22 +998,28 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data)
        if (data & ~ETH_FLAG_LRO)
                return -EINVAL;

-       if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
-               return -EINVAL;
+       if (data & ETH_FLAG_LRO) {

-       if (!adapter->rx_csum) {
-               dev_info(&adapter->pdev->dev, "rx csum is off, "
-                       "cannot toggle lro\n");
-               return -EINVAL;
-       }
+               if (netdev->features & NETIF_F_LRO)
+                       return 0;

-       if ((data & ETH_FLAG_LRO) && (netdev->features & NETIF_F_LRO))
-               return 0;
+               if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
+                       return -EINVAL;
+
+               if (!adapter->rx_csum) {
+                       dev_info(&adapter->pdev->dev, "rx csum is off, "
+                               "cannot toggle lro\n");
+                       return -EINVAL;
+               }

-       if (data & ETH_FLAG_LRO) {
                hw_lro = QLCNIC_LRO_ENABLED;
                netdev->features |= NETIF_F_LRO;
+
        } else {
+
+               if (!(netdev->features & NETIF_F_LRO))
+                       return 0;
+
                hw_lro = 0;
                netdev->features &= ~NETIF_F_LRO;
        }
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 3901be8..498cca9 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -566,6 +566,9 @@ int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
        u64 word;
        int rv;

+       if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
+               return 0;
+
        memset(&req, 0, sizeof(struct qlcnic_nic_req));

        req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
@@ -711,6 +714,9 @@ int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter)
        u64 word;
        int rv;

+       if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
+               return 0;
+
        memset(&req, 0, sizeof(struct qlcnic_nic_req));
        req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);

diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 8bf9a96..7f9edb2 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -773,7 +773,8 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
                features |= (NETIF_F_TSO | NETIF_F_TSO6);
                vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
        }
-       if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+
+       if (netdev->features & NETIF_F_LRO)
                features |= NETIF_F_LRO;

        if (esw_cfg->offload_flags & BIT_0) {
--
1.6.5.2


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply related

* [PATCH 6/9 net-next-2.6] qlcnic: Remove unused cde
From: Anirban Chakraborty @ 2011-03-30 20:23 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

Removed unused data structures related to interrupt coalescence

Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
---
 drivers/net/qlcnic/qlcnic.h         |   56 +++++++++++++----------------------
 drivers/net/qlcnic/qlcnic_ethtool.c |   30 +++++++------------
 drivers/net/qlcnic/qlcnic_hw.c      |   20 +++++-------
 drivers/net/qlcnic/qlcnic_main.c    |   21 +++----------
 4 files changed, 46 insertions(+), 81 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index be9c329..9d2e630 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -392,6 +392,25 @@ struct qlcnic_rx_buffer {
 #define        QLCNIC_XGBE     0x02

 /*
+ * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is
+ * adjusted based on configured MTU.
+ */
+#define QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US        3
+#define QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS        256
+
+#define QLCNIC_INTR_DEFAULT                    0x04
+#define QLCNIC_CONFIG_INTR_COALESCE            3
+
+struct qlcnic_nic_intr_coalesce {
+       u8      type;
+       u8      sts_ring_mask;
+       u16     rx_packets;
+       u16     rx_time_us;
+       u16     flag;
+       u32     timer_out;
+};
+
+/*
  * One hardware_context{} per adapter
  * contains interrupt info as well shared hardware info.
  */
@@ -409,6 +428,8 @@ struct qlcnic_hardware_context {
        u8 linkup;
        u16 port_type;
        u16 board_type;
+
+       struct qlcnic_nic_intr_coalesce coal;
 };

 struct qlcnic_adapter_stats {
@@ -721,40 +742,6 @@ struct qlcnic_mac_list_s {
        uint8_t mac_addr[ETH_ALEN+2];
 };

-/*
- * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is
- * adjusted based on configured MTU.
- */
-#define QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US        3
-#define QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS        256
-#define QLCNIC_DEFAULT_INTR_COALESCE_TX_PACKETS        64
-#define QLCNIC_DEFAULT_INTR_COALESCE_TX_TIME_US        4
-
-#define QLCNIC_INTR_DEFAULT                    0x04
-
-union qlcnic_nic_intr_coalesce_data {
-       struct {
-               u16     rx_packets;
-               u16     rx_time_us;
-               u16     tx_packets;
-               u16     tx_time_us;
-       } data;
-       u64             word;
-};
-
-struct qlcnic_nic_intr_coalesce {
-       u16             stats_time_us;
-       u16             rate_sample_time;
-       u16             flags;
-       u16             rsvd_1;
-       u32             low_threshold;
-       u32             high_threshold;
-       union qlcnic_nic_intr_coalesce_data     normal;
-       union qlcnic_nic_intr_coalesce_data     low;
-       union qlcnic_nic_intr_coalesce_data     high;
-       union qlcnic_nic_intr_coalesce_data     irq;
-};
-
 #define QLCNIC_HOST_REQUEST    0x13
 #define QLCNIC_REQUEST         0x14

@@ -1002,7 +989,6 @@ struct qlcnic_adapter {

        struct delayed_work fw_work;

-       struct qlcnic_nic_intr_coalesce coal;

        struct qlcnic_filter_hash fhash;

diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index b446045..e03108a 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -936,8 +936,8 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,
        */
        if (ethcoal->rx_coalesce_usecs > 0xffff ||
                ethcoal->rx_max_coalesced_frames > 0xffff ||
-               ethcoal->tx_coalesce_usecs > 0xffff ||
-               ethcoal->tx_max_coalesced_frames > 0xffff ||
+               ethcoal->tx_coalesce_usecs ||
+               ethcoal->tx_max_coalesced_frames ||
                ethcoal->rx_coalesce_usecs_irq ||
                ethcoal->rx_max_coalesced_frames_irq ||
                ethcoal->tx_coalesce_usecs_irq ||
@@ -959,21 +959,17 @@ static int qlcnic_set_intr_coalesce(struct net_device *netdev,

        if (!ethcoal->rx_coalesce_usecs ||
                !ethcoal->rx_max_coalesced_frames) {
-               adapter->coal.flags = QLCNIC_INTR_DEFAULT;
-               adapter->coal.normal.data.rx_time_us =
+               adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
+               adapter->ahw->coal.rx_time_us =
                        QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
-               adapter->coal.normal.data.rx_packets =
+               adapter->ahw->coal.rx_packets =
                        QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
        } else {
-               adapter->coal.flags = 0;
-               adapter->coal.normal.data.rx_time_us =
-               ethcoal->rx_coalesce_usecs;
-               adapter->coal.normal.data.rx_packets =
-               ethcoal->rx_max_coalesced_frames;
+               adapter->ahw->coal.flag = 0;
+               adapter->ahw->coal.rx_time_us = ethcoal->rx_coalesce_usecs;
+               adapter->ahw->coal.rx_packets =
+                       ethcoal->rx_max_coalesced_frames;
        }
-       adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
-       adapter->coal.normal.data.tx_packets =
-       ethcoal->tx_max_coalesced_frames;

        qlcnic_config_intr_coalesce(adapter);

@@ -988,12 +984,8 @@ static int qlcnic_get_intr_coalesce(struct net_device *netdev,
        if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
                return -EINVAL;

-       ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
-       ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
-       ethcoal->rx_max_coalesced_frames =
-               adapter->coal.normal.data.rx_packets;
-       ethcoal->tx_max_coalesced_frames =
-               adapter->coal.normal.data.tx_packets;
+       ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us;
+       ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets;

        return 0;
 }
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 7e3f526..3901be8 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -532,33 +532,31 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
        }
 }

-#define        QLCNIC_CONFIG_INTR_COALESCE     3
-
 /*
  * Send the interrupt coalescing parameter set by ethtool to the card.
  */
 int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_nic_req req;
-       u64 word[6];
-       int rv, i;
+       int rv;

        memset(&req, 0, sizeof(struct qlcnic_nic_req));

        req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);

-       word[0] = QLCNIC_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16);
-       req.req_hdr = cpu_to_le64(word[0]);
-
-       memcpy(&word[0], &adapter->coal, sizeof(adapter->coal));
-       for (i = 0; i < 6; i++)
-               req.words[i] = cpu_to_le64(word[i]);
+       req.req_hdr = cpu_to_le64(QLCNIC_CONFIG_INTR_COALESCE |
+               ((u64) adapter->portnum << 16));

+       req.words[0] = cpu_to_le64(((u64) adapter->ahw->coal.flag) << 32);
+       req.words[2] = cpu_to_le64(adapter->ahw->coal.rx_packets |
+                       ((u64) adapter->ahw->coal.rx_time_us) << 16);
+       req.words[5] = cpu_to_le64(adapter->ahw->coal.timer_out |
+                       ((u64) adapter->ahw->coal.type) << 32 |
+                       ((u64) adapter->ahw->coal.sts_ring_mask) << 40);
        rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
        if (rv != 0)
                dev_err(&adapter->netdev->dev,
                        "Could not send interrupt coalescing parameters\n");
-
        return rv;
 }

diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index b75aef0..8bf9a96 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1097,20 +1097,6 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter)
        }
 }

-static void
-qlcnic_init_coalesce_defaults(struct qlcnic_adapter *adapter)
-{
-       adapter->coal.flags = QLCNIC_INTR_DEFAULT;
-       adapter->coal.normal.data.rx_time_us =
-               QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
-       adapter->coal.normal.data.rx_packets =
-               QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
-       adapter->coal.normal.data.tx_time_us =
-               QLCNIC_DEFAULT_INTR_COALESCE_TX_TIME_US;
-       adapter->coal.normal.data.tx_packets =
-               QLCNIC_DEFAULT_INTR_COALESCE_TX_PACKETS;
-}
-
 static int
 __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
 {
@@ -1244,8 +1230,6 @@ qlcnic_attach(struct qlcnic_adapter *adapter)
                goto err_out_free_hw;
        }

-       qlcnic_init_coalesce_defaults(adapter);
-
        qlcnic_create_sysfs_entries(adapter);

        adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC;
@@ -1326,7 +1310,12 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
                kfree(adapter->ahw);
                adapter->ahw = NULL;
                err = -ENOMEM;
+               goto err_out;
        }
+       /* Initialize interrupt coalesce parameters */
+       adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
+       adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
+       adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
 err_out:
        return err;
 }
--
1.6.5.2


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply related

* [PATCH 7/9 net-next-2.6] qlcnic: Use flt method to determine flash fw region
From: Anirban Chakraborty @ 2011-03-30 20:23 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

From: Sritej Velaga <sritej.velaga@qlogic.com>

Use flash layout table to get flash fw starting address and its size. If that
fails, use legacy method.

Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
---
 drivers/net/qlcnic/qlcnic.h      |    3 ++-
 drivers/net/qlcnic/qlcnic_init.c |   17 ++++++++++++++---
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 9d2e630..d9dd2c4 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -292,6 +292,7 @@ struct uni_data_desc{
 /* Flash Defines and Structures */
 #define QLCNIC_FLT_LOCATION    0x3F1000
 #define QLCNIC_FW_IMAGE_REGION 0x74
+#define QLCNIC_BOOTLD_REGION    0X72
 struct qlcnic_flt_header {
        u16 version;
        u16 len;
@@ -306,7 +307,7 @@ struct qlcnic_flt_entry {
        u8 reserved1;
        u32 size;
        u32 start_addr;
-       u32 end_add;
+       u32 end_addr;
 };

 /* Magic number to let user know flash is programmed */
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 74ec96d..4ec0eeb 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -1130,9 +1130,20 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
        } else {
                u64 data;
                u32 hi, lo;
-
-               size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
-               flashaddr = QLCNIC_BOOTLD_START;
+               int ret;
+               struct qlcnic_flt_entry bootld_entry;
+
+               ret = qlcnic_get_flt_entry(adapter, QLCNIC_BOOTLD_REGION,
+                                       &bootld_entry);
+               if (!ret) {
+                       size = bootld_entry.size / 8;
+                       flashaddr = bootld_entry.start_addr;
+               } else {
+                       size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
+                       flashaddr = QLCNIC_BOOTLD_START;
+                       dev_info(&pdev->dev,
+                               "using legacy method to get flash fw region");
+               }

                for (i = 0; i < size; i++) {
                        if (qlcnic_rom_fast_read(adapter,
--
1.6.5.2


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply related

* [PATCH 9/9 net-next-2.6] qlcnic: Update version number to 5.0.16
From: Anirban Chakraborty @ 2011-03-30 20:23 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

Bumped up version number to 5.0.16

Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
---
 drivers/net/qlcnic/qlcnic.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index d9dd2c4..dc6f7c6 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -36,8 +36,8 @@

 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 15
-#define QLCNIC_LINUX_VERSIONID  "5.0.15"
+#define _QLCNIC_LINUX_SUBVERSION 16
+#define QLCNIC_LINUX_VERSIONID  "5.0.16"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
                 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
--
1.6.5.2


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply related

* [PATCH 5/9 net-next-2.6] qlcnic: Changes to VLAN code
From: Anirban Chakraborty @ 2011-03-30 20:23 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

Incorporated changes to comply with reworked VLAN infrastructure in kernel.

Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
---
 drivers/net/qlcnic/qlcnic.h      |    4 ++-
 drivers/net/qlcnic/qlcnic_init.c |   15 ++++++-------
 drivers/net/qlcnic/qlcnic_main.c |   42 ++++++++++++++++++++++---------------
 3 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index a5b28d1..be9c329 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -29,6 +29,8 @@

 #include <linux/io.h>
 #include <asm/byteorder.h>
+#include <linux/bitops.h>
+#include <linux/if_vlan.h>

 #include "qlcnic_hdr.h"

@@ -982,8 +984,8 @@ struct qlcnic_adapter {
        u8 mac_addr[ETH_ALEN];

        u64 dev_rst_time;
+       unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];

-       struct vlan_group *vlgrp;
        struct qlcnic_npar_info *npars;
        struct qlcnic_eswitch *eswitch;
        struct qlcnic_nic_template *nic_ops;
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 476ea14..74ec96d 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -1467,10 +1467,10 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter,

        skb->protocol = eth_type_trans(skb, netdev);

-       if ((vid != 0xffff) && adapter->vlgrp)
-               vlan_gro_receive(&sds_ring->napi, adapter->vlgrp, vid, skb);
-       else
-               napi_gro_receive(&sds_ring->napi, skb);
+       if (vid != 0xffff)
+               __vlan_hwaccel_put_tag(skb, vid);
+
+       napi_gro_receive(&sds_ring->napi, skb);

        adapter->stats.rx_pkts++;
        adapter->stats.rxbytes += length;
@@ -1552,10 +1552,9 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,

        length = skb->len;

-       if ((vid != 0xffff) && adapter->vlgrp)
-               vlan_hwaccel_receive_skb(skb, adapter->vlgrp, vid);
-       else
-               netif_receive_skb(skb);
+       if (vid != 0xffff)
+               __vlan_hwaccel_put_tag(skb, vid);
+       netif_receive_skb(skb);

        adapter->stats.lro_pkts++;
        adapter->stats.lrobytes += length;
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 3b740f5..b75aef0 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -13,7 +13,6 @@

 #include <linux/swab.h>
 #include <linux/dma-mapping.h>
-#include <linux/if_vlan.h>
 #include <net/ip.h>
 #include <linux/ipv6.h>
 #include <linux/inetdevice.h>
@@ -98,6 +97,9 @@ static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
 static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
 static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
                                struct qlcnic_esw_func_cfg *);
+static void qlcnic_vlan_rx_add(struct net_device *, u16);
+static void qlcnic_vlan_rx_del(struct net_device *, u16);
+
 /*  PCI Device ID Table  */
 #define ENTRY(device) \
        {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
@@ -317,13 +319,6 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
        return 0;
 }

-static void qlcnic_vlan_rx_register(struct net_device *netdev,
-               struct vlan_group *grp)
-{
-       struct qlcnic_adapter *adapter = netdev_priv(netdev);
-       adapter->vlgrp = grp;
-}
-
 static const struct net_device_ops qlcnic_netdev_ops = {
        .ndo_open          = qlcnic_open,
        .ndo_stop          = qlcnic_close,
@@ -334,7 +329,8 @@ static const struct net_device_ops qlcnic_netdev_ops = {
        .ndo_set_mac_address    = qlcnic_set_mac,
        .ndo_change_mtu    = qlcnic_change_mtu,
        .ndo_tx_timeout    = qlcnic_tx_timeout,
-       .ndo_vlan_rx_register = qlcnic_vlan_rx_register,
+       .ndo_vlan_rx_add_vid    = qlcnic_vlan_rx_add,
+       .ndo_vlan_rx_kill_vid   = qlcnic_vlan_rx_del,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = qlcnic_poll_controller,
 #endif
@@ -710,6 +706,22 @@ qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
 }

 static void
+qlcnic_vlan_rx_add(struct net_device *netdev, u16 vid)
+{
+       struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       set_bit(vid, adapter->vlans);
+}
+
+static void
+qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid)
+{
+       struct qlcnic_adapter *adapter = netdev_priv(netdev);
+
+       qlcnic_restore_indev_addr(netdev, NETDEV_DOWN);
+       clear_bit(vid, adapter->vlans);
+}
+
+static void
 qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
                struct qlcnic_esw_func_cfg *esw_cfg)
 {
@@ -755,7 +767,7 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
        features = (NETIF_F_SG | NETIF_F_IP_CSUM |
                        NETIF_F_IPV6_CSUM | NETIF_F_GRO);
        vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
-                       NETIF_F_IPV6_CSUM);
+                       NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER);

        if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
                features |= (NETIF_F_TSO | NETIF_F_TSO6);
@@ -1448,7 +1460,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
        netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
                NETIF_F_IPV6_CSUM | NETIF_F_GRO | NETIF_F_HW_VLAN_RX);
        netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM |
-               NETIF_F_IPV6_CSUM);
+               NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER);

        if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
                netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
@@ -4068,14 +4080,10 @@ qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event)

        qlcnic_config_indev_addr(adapter, netdev, event);

-       if (!adapter->vlgrp)
-               return;
-
-       for (vid = 0; vid < VLAN_N_VID; vid++) {
-               dev = vlan_group_get_device(adapter->vlgrp, vid);
+       for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) {
+               dev = vlan_find_dev(netdev, vid);
                if (!dev)
                        continue;
-
                qlcnic_config_indev_addr(adapter, dev, event);
        }
 }
--
1.6.5.2


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply related

* [PATCH 2/9 net-next-2.6] qlcnic: Fix memory leak bug in error path
From: Anirban Chakraborty @ 2011-03-30 20:22 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

From: Sony Chacko <sony.chacko@qlogic.com>

A memory leak exists in the error path of getting PCI info code. Fix it by
going via the memory free path before returning.

Signed-off-by: Sony Chacko <sony.chacko@qlogic.com
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
---
 drivers/net/qlcnic/qlcnic_main.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index d230fdd..de6f866 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -464,8 +464,10 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)

        for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
                pfn = pci_info[i].id;
-               if (pfn > QLCNIC_MAX_PCI_FUNC)
-                       return QL_STATUS_INVALID_PARAM;
+               if (pfn > QLCNIC_MAX_PCI_FUNC) {
+                       ret = QL_STATUS_INVALID_PARAM;
+                       goto err_eswitch;
+               }
                adapter->npars[pfn].active = (u8)pci_info[i].active;
                adapter->npars[pfn].type = (u8)pci_info[i].type;
                adapter->npars[pfn].phy_port = (u8)pci_info[i].default_port;
--
1.6.5.2


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply related

* [PATCH 4/9 net-next-2.6] qlcnic: Code changes to improve performance
From: Anirban Chakraborty @ 2011-03-30 20:22 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

Code optimization resulted in achieving lower CPU utilization on transmit path
on ppc and higher throughput for small packet sizes (64 bytes).

Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
---
 drivers/net/qlcnic/qlcnic.h      |   30 +++---
 drivers/net/qlcnic/qlcnic_main.c |  210 ++++++++++++++++++--------------------
 2 files changed, 115 insertions(+), 125 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 15d950a..a5b28d1 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -434,50 +434,49 @@ struct qlcnic_adapter_stats {
  * be one Rcv Descriptor for normal packets, one for jumbo and may be others.
  */
 struct qlcnic_host_rds_ring {
-       u32 producer;
+       void __iomem *crb_rcv_producer;
+       struct rcv_desc *desc_head;
+       struct qlcnic_rx_buffer *rx_buf_arr;
        u32 num_desc;
+       u32 producer;
        u32 dma_size;
        u32 skb_size;
        u32 flags;
-       void __iomem *crb_rcv_producer;
-       struct rcv_desc *desc_head;
-       struct qlcnic_rx_buffer *rx_buf_arr;
        struct list_head free_list;
        spinlock_t lock;
        dma_addr_t phys_addr;
-};
+} ____cacheline_internodealigned_in_smp;

 struct qlcnic_host_sds_ring {
        u32 consumer;
        u32 num_desc;
        void __iomem *crb_sts_consumer;
-       void __iomem *crb_intr_mask;

        struct status_desc *desc_head;
        struct qlcnic_adapter *adapter;
        struct napi_struct napi;
        struct list_head free_list[NUM_RCV_DESC_RINGS];

+       void __iomem *crb_intr_mask;
        int irq;

        dma_addr_t phys_addr;
        char name[IFNAMSIZ+4];
-};
+} ____cacheline_internodealigned_in_smp;

 struct qlcnic_host_tx_ring {
        u32 producer;
-       __le32 *hw_consumer;
        u32 sw_consumer;
-       void __iomem *crb_cmd_producer;
        u32 num_desc;
-
-       struct netdev_queue *txq;
-
-       struct qlcnic_cmd_buffer *cmd_buf_arr;
+       void __iomem *crb_cmd_producer;
        struct cmd_desc_type0 *desc_head;
+       struct qlcnic_cmd_buffer *cmd_buf_arr;
+       __le32 *hw_consumer;
+
        dma_addr_t phys_addr;
        dma_addr_t hw_cons_phys_addr;
-};
+       struct netdev_queue *txq;
+} ____cacheline_internodealigned_in_smp;

 /*
  * Receive context. There is one such structure per instance of the
@@ -1328,8 +1327,7 @@ static const struct qlcnic_brdinfo qlcnic_boards[] = {

 static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
 {
-       smp_mb();
-       if (tx_ring->producer < tx_ring->sw_consumer)
+       if (likely(tx_ring->producer < tx_ring->sw_consumer))
                return tx_ring->sw_consumer - tx_ring->producer;
        else
                return tx_ring->sw_consumer + tx_ring->num_desc -
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index dde7e44..3b740f5 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1861,6 +1861,7 @@ static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
        vlan_req->vlan_id = vlan_id;

        tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
+       smp_mb();
 }

 #define QLCNIC_MAC_HASH(MAC)\
@@ -1921,58 +1922,122 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter,
        spin_unlock(&adapter->mac_learn_lock);
 }

-static void
-qlcnic_tso_check(struct net_device *netdev,
-               struct qlcnic_host_tx_ring *tx_ring,
+static int
+qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
                struct cmd_desc_type0 *first_desc,
                struct sk_buff *skb)
 {
-       u8 opcode = TX_ETHER_PKT;
-       __be16 protocol = skb->protocol;
-       u16 flags = 0;
-       int copied, offset, copy_len, hdr_len = 0, tso = 0;
+       u8 opcode = 0, hdr_len = 0;
+       u16 flags = 0, vlan_tci = 0;
+       int copied, offset, copy_len;
        struct cmd_desc_type0 *hwdesc;
        struct vlan_ethhdr *vh;
-       struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+       u16 protocol = ntohs(skb->protocol);
        u32 producer = tx_ring->producer;
-       __le16 vlan_oob = first_desc->flags_opcode &
-                               cpu_to_le16(FLAGS_VLAN_OOB);
+
+       if (protocol == ETH_P_8021Q) {
+               vh = (struct vlan_ethhdr *)skb->data;
+               flags = FLAGS_VLAN_TAGGED;
+               vlan_tci = vh->h_vlan_TCI;
+       } else if (vlan_tx_tag_present(skb)) {
+               flags = FLAGS_VLAN_OOB;
+               vlan_tci = vlan_tx_tag_get(skb);
+       }
+       if (unlikely(adapter->pvid)) {
+               if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
+                       return -EIO;
+               if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
+                       goto set_flags;
+
+               flags = FLAGS_VLAN_OOB;
+               vlan_tci = adapter->pvid;
+       }
+set_flags:
+       qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
+       qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);

        if (*(skb->data) & BIT_0) {
                flags |= BIT_0;
                memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
        }
-
-       if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
+       opcode = TX_ETHER_PKT;
+       if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
                        skb_shinfo(skb)->gso_size > 0) {

                hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);

                first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
                first_desc->total_hdr_length = hdr_len;
-               if (vlan_oob) {
+
+               opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO;
+
+               /* For LSO, we need to copy the MAC/IP/TCP headers into
+               * the descriptor ring */
+               copied = 0;
+               offset = 2;
+
+               if (flags & FLAGS_VLAN_OOB) {
                        first_desc->total_hdr_length += VLAN_HLEN;
                        first_desc->tcp_hdr_offset = VLAN_HLEN;
                        first_desc->ip_hdr_offset = VLAN_HLEN;
                        /* Only in case of TSO on vlan device */
                        flags |= FLAGS_VLAN_TAGGED;
+
+                       /* Create a TSO vlan header template for firmware */
+
+                       hwdesc = &tx_ring->desc_head[producer];
+                       tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+                       copy_len = min((int)sizeof(struct cmd_desc_type0) -
+                               offset, hdr_len + VLAN_HLEN);
+
+                       vh = (struct vlan_ethhdr *)((char *) hwdesc + 2);
+                       skb_copy_from_linear_data(skb, vh, 12);
+                       vh->h_vlan_proto = htons(ETH_P_8021Q);
+                       vh->h_vlan_TCI = htons(vlan_tci);
+
+                       skb_copy_from_linear_data_offset(skb, 12,
+                               (char *)vh + 16, copy_len - 16);
+
+                       copied = copy_len - VLAN_HLEN;
+                       offset = 0;
+
+                       producer = get_next_index(producer, tx_ring->num_desc);
                }

-               opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ?
-                               TX_TCP_LSO6 : TX_TCP_LSO;
-               tso = 1;
+               while (copied < hdr_len) {
+
+                       copy_len = min((int)sizeof(struct cmd_desc_type0) -
+                               offset, (hdr_len - copied));
+
+                       hwdesc = &tx_ring->desc_head[producer];
+                       tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+                       skb_copy_from_linear_data_offset(skb, copied,
+                                (char *) hwdesc + offset, copy_len);
+
+                       copied += copy_len;
+                       offset = 0;
+
+                       producer = get_next_index(producer, tx_ring->num_desc);
+               }
+
+               tx_ring->producer = producer;
+               smp_mb();
+               adapter->stats.lso_frames++;

        } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                u8 l4proto;

-               if (protocol == cpu_to_be16(ETH_P_IP)) {
+               if (protocol == 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 (protocol == cpu_to_be16(ETH_P_IPV6)) {
+               } else if (protocol == ETH_P_IPV6) {
                        l4proto = ipv6_hdr(skb)->nexthdr;

                        if (l4proto == IPPROTO_TCP)
@@ -1981,63 +2046,11 @@ qlcnic_tso_check(struct net_device *netdev,
                                opcode = TX_UDPV6_PKT;
                }
        }
-
        first_desc->tcp_hdr_offset += skb_transport_offset(skb);
        first_desc->ip_hdr_offset += skb_network_offset(skb);
        qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);

-       if (!tso)
-               return;
-
-       /* For LSO, we need to copy the MAC/IP/TCP headers into
-        * the descriptor ring
-        */
-       copied = 0;
-       offset = 2;
-
-       if (vlan_oob) {
-               /* Create a TSO vlan header template for firmware */
-
-               hwdesc = &tx_ring->desc_head[producer];
-               tx_ring->cmd_buf_arr[producer].skb = NULL;
-
-               copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,
-                               hdr_len + VLAN_HLEN);
-
-               vh = (struct vlan_ethhdr *)((char *)hwdesc + 2);
-               skb_copy_from_linear_data(skb, vh, 12);
-               vh->h_vlan_proto = htons(ETH_P_8021Q);
-               vh->h_vlan_TCI = (__be16)swab16((u16)first_desc->vlan_TCI);
-
-               skb_copy_from_linear_data_offset(skb, 12,
-                               (char *)vh + 16, copy_len - 16);
-
-               copied = copy_len - VLAN_HLEN;
-               offset = 0;
-
-               producer = get_next_index(producer, tx_ring->num_desc);
-       }
-
-       while (copied < hdr_len) {
-
-               copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,
-                               (hdr_len - copied));
-
-               hwdesc = &tx_ring->desc_head[producer];
-               tx_ring->cmd_buf_arr[producer].skb = NULL;
-
-               skb_copy_from_linear_data_offset(skb, copied,
-                                (char *)hwdesc + offset, copy_len);
-
-               copied += copy_len;
-               offset = 0;
-
-               producer = get_next_index(producer, tx_ring->num_desc);
-       }
-
-       tx_ring->producer = producer;
-       barrier();
-       adapter->stats.lso_frames++;
+       return 0;
 }

 static int
@@ -2088,39 +2101,21 @@ out_err:
        return -ENOMEM;
 }

-static int
-qlcnic_check_tx_tagging(struct qlcnic_adapter *adapter,
-                       struct sk_buff *skb,
-                       struct cmd_desc_type0 *first_desc)
+static void
+qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb,
+                       struct qlcnic_cmd_buffer *pbuf)
 {
-       u8 opcode = 0;
-       u16 flags = 0;
-       __be16 protocol = skb->protocol;
-       struct vlan_ethhdr *vh;
+       struct qlcnic_skb_frag *nf = &pbuf->frag_array[0];
+       int nr_frags = skb_shinfo(skb)->nr_frags;
+       int i;

-       if (protocol == cpu_to_be16(ETH_P_8021Q)) {
-               vh = (struct vlan_ethhdr *)skb->data;
-               protocol = vh->h_vlan_encapsulated_proto;
-               flags = FLAGS_VLAN_TAGGED;
-               qlcnic_set_tx_vlan_tci(first_desc, ntohs(vh->h_vlan_TCI));
-       } else if (vlan_tx_tag_present(skb)) {
-               flags = FLAGS_VLAN_OOB;
-               qlcnic_set_tx_vlan_tci(first_desc, vlan_tx_tag_get(skb));
+       for (i = 0; i < nr_frags; i++) {
+               nf = &pbuf->frag_array[i+1];
+               pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
        }
-       if (unlikely(adapter->pvid)) {
-               if (first_desc->vlan_TCI &&
-                               !(adapter->flags & QLCNIC_TAGGING_ENABLED))
-                       return -EIO;
-               if (first_desc->vlan_TCI &&
-                               (adapter->flags & QLCNIC_TAGGING_ENABLED))
-                       goto set_flags;

-               flags = FLAGS_VLAN_OOB;
-               qlcnic_set_tx_vlan_tci(first_desc, adapter->pvid);
-       }
-set_flags:
-       qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
-       return 0;
+       nf = &pbuf->frag_array[0];
+       pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
 }

 static inline void
@@ -2144,7 +2139,7 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        int i, k;

        u32 producer;
-       int frag_count, no_of_desc;
+       int frag_count;
        u32 num_txd = tx_ring->num_desc;

        if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
@@ -2161,12 +2156,8 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)

        frag_count = skb_shinfo(skb)->nr_frags + 1;

-       /* 4 fragments per cmd des */
-       no_of_desc = (frag_count + 3) >> 2;
-
        if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
                netif_stop_queue(netdev);
-               smp_mb();
                if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH)
                        netif_start_queue(netdev);
                else {
@@ -2183,9 +2174,6 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        first_desc = hwdesc = &tx_ring->desc_head[producer];
        qlcnic_clear_cmddesc((u64 *)hwdesc);

-       if (qlcnic_check_tx_tagging(adapter, skb, first_desc))
-               goto drop_packet;
-
        if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
                adapter->stats.tx_dma_map_error++;
                goto drop_packet;
@@ -2229,8 +2217,10 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        }

        tx_ring->producer = get_next_index(producer, num_txd);
+       smp_mb();

-       qlcnic_tso_check(netdev, tx_ring, first_desc, skb);
+       if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb)))
+               goto unwind_buff;

        if (qlcnic_mac_learn)
                qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
@@ -2242,6 +2232,8 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)

        return NETDEV_TX_OK;

+unwind_buff:
+       qlcnic_unmap_buffers(pdev, skb, pbuf);
 drop_packet:
        adapter->stats.txdropped++;
        dev_kfree_skb_any(skb);
--
1.6.5.2


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply related

* [PATCH 3/9 net-next-2.6] qlcnic: Code cleanup
From: Anirban Chakraborty @ 2011-03-30 20:22 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver


 1. Changed adapter structure to move away from embedding hardware and
    receive context structs and use pointers to those objects
 2. Packed all the structs that interface with FW
 3. Removed unused code and structs

Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
---
 drivers/net/qlcnic/qlcnic.h         |  126 +++++++++-------------------
 drivers/net/qlcnic/qlcnic_ctx.c     |  135 +++++++++++++++---------------
 drivers/net/qlcnic/qlcnic_ethtool.c |   40 +++++-----
 drivers/net/qlcnic/qlcnic_hw.c      |   56 ++++++------
 drivers/net/qlcnic/qlcnic_init.c    |   26 +++---
 drivers/net/qlcnic/qlcnic_main.c    |  158 ++++++++++++++++++++++-------------
 6 files changed, 268 insertions(+), 273 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index dc44564..15d950a 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -93,8 +93,6 @@
 #define TX_IP_PKT      0x04
 #define TX_TCP_LSO     0x05
 #define TX_TCP_LSO6    0x06
-#define TX_IPSEC       0x07
-#define TX_IPSEC_CMD   0x0a
 #define TX_TCPV6_PKT   0x0b
 #define TX_UDPV6_PKT   0x0c

@@ -200,7 +198,7 @@ struct rcv_desc {
        __le16 reserved;
        __le32 buffer_length;   /* allocated buffer length (usually 2K) */
        __le64 addr_buffer;
-};
+} __packed;

 /* opcode field in status_desc */
 #define QLCNIC_SYN_OFFLOAD     0x03
@@ -365,12 +363,6 @@ struct qlcnic_skb_frag {
        u64 length;
 };

-struct qlcnic_recv_crb {
-       u32 crb_rcv_producer[NUM_RCV_DESC_RINGS];
-       u32 crb_sts_consumer[NUM_STS_DESC_RINGS];
-       u32 sw_int_mask[NUM_STS_DESC_RINGS];
-};
-
 /*    Following defines are for the state of the buffers    */
 #define        QLCNIC_BUFFER_FREE      0
 #define        QLCNIC_BUFFER_BUSY      1
@@ -387,10 +379,10 @@ struct qlcnic_cmd_buffer {

 /* In rx_buffer, we do not need multiple fragments as is a single buffer */
 struct qlcnic_rx_buffer {
-       struct list_head list;
+       u16 ref_handle;
        struct sk_buff *skb;
+       struct list_head list;
        u64 dma;
-       u16 ref_handle;
 };

 /* Board types */
@@ -494,12 +486,12 @@ struct qlcnic_host_tx_ring {
  * present elsewhere.
  */
 struct qlcnic_recv_context {
+       struct qlcnic_host_rds_ring *rds_rings;
+       struct qlcnic_host_sds_ring *sds_rings;
        u32 state;
        u16 context_id;
        u16 virt_port;

-       struct qlcnic_host_rds_ring *rds_rings;
-       struct qlcnic_host_sds_ring *sds_rings;
 };

 /* HW context creation */
@@ -538,9 +530,6 @@ struct qlcnic_recv_context {
 #define QLCNIC_CDRP_CMD_DESTROY_RX_CTX          0x00000008
 #define QLCNIC_CDRP_CMD_CREATE_TX_CTX           0x00000009
 #define QLCNIC_CDRP_CMD_DESTROY_TX_CTX          0x0000000a
-#define QLCNIC_CDRP_CMD_SETUP_STATISTICS        0x0000000e
-#define QLCNIC_CDRP_CMD_GET_STATISTICS          0x0000000f
-#define QLCNIC_CDRP_CMD_DELETE_STATISTICS       0x00000010
 #define QLCNIC_CDRP_CMD_SET_MTU                 0x00000012
 #define QLCNIC_CDRP_CMD_READ_PHY               0x00000013
 #define QLCNIC_CDRP_CMD_WRITE_PHY              0x00000014
@@ -549,17 +538,11 @@ struct qlcnic_recv_context {
 #define QLCNIC_CDRP_CMD_SET_FLOW_CTL           0x00000017
 #define QLCNIC_CDRP_CMD_READ_MAX_MTU           0x00000018
 #define QLCNIC_CDRP_CMD_READ_MAX_LRO           0x00000019
-#define QLCNIC_CDRP_CMD_CONFIGURE_TOE          0x0000001a
-#define QLCNIC_CDRP_CMD_FUNC_ATTRIB            0x0000001b
-#define QLCNIC_CDRP_CMD_READ_PEXQ_PARAMETERS   0x0000001c
-#define QLCNIC_CDRP_CMD_GET_LIC_CAPABILITIES   0x0000001d
-#define QLCNIC_CDRP_CMD_READ_MAX_LRO_PER_BOARD 0x0000001e
 #define QLCNIC_CDRP_CMD_MAC_ADDRESS            0x0000001f

 #define QLCNIC_CDRP_CMD_GET_PCI_INFO           0x00000020
 #define QLCNIC_CDRP_CMD_GET_NIC_INFO           0x00000021
 #define QLCNIC_CDRP_CMD_SET_NIC_INFO           0x00000022
-#define QLCNIC_CDRP_CMD_RESET_NPAR             0x00000023
 #define QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY 0x00000024
 #define QLCNIC_CDRP_CMD_TOGGLE_ESWITCH         0x00000025
 #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS     0x00000026
@@ -597,14 +580,14 @@ struct qlcnic_hostrq_sds_ring {
        __le32 ring_size;               /* Ring entries */
        __le16 msi_index;
        __le16 rsvd;            /* Padding */
-};
+} __packed;

 struct qlcnic_hostrq_rds_ring {
        __le64 host_phys_addr;  /* Ring base addr */
        __le64 buff_size;               /* Packet buffer size */
        __le32 ring_size;               /* Ring entries */
        __le32 ring_kind;               /* Class of ring */
-};
+} __packed;

 struct qlcnic_hostrq_rx_ctx {
        __le64 host_rsp_dma_addr;       /* Response dma'd here */
@@ -625,17 +608,17 @@ struct qlcnic_hostrq_rx_ctx {
           - N hostrq_rds_rings
           - N hostrq_sds_rings */
        char data[0];
-};
+} __packed;

 struct qlcnic_cardrsp_rds_ring{
        __le32 host_producer_crb;       /* Crb to use */
        __le32 rsvd1;           /* Padding */
-};
+} __packed;

 struct qlcnic_cardrsp_sds_ring {
        __le32 host_consumer_crb;       /* Crb to use */
        __le32 interrupt_crb;   /* Crb to use */
-};
+} __packed;

 struct qlcnic_cardrsp_rx_ctx {
        /* These ring offsets are relative to data[0] below */
@@ -654,7 +637,7 @@ struct qlcnic_cardrsp_rx_ctx {
           - N cardrsp_rds_rings
           - N cardrs_sds_rings */
        char data[0];
-};
+} __packed;

 #define SIZEOF_HOSTRQ_RX(HOSTRQ_RX, rds_rings, sds_rings)      \
        (sizeof(HOSTRQ_RX) +                                    \
@@ -674,7 +657,7 @@ struct qlcnic_hostrq_cds_ring {
        __le64 host_phys_addr;  /* Ring base addr */
        __le32 ring_size;               /* Ring entries */
        __le32 rsvd;            /* Padding */
-};
+} __packed;

 struct qlcnic_hostrq_tx_ctx {
        __le64 host_rsp_dma_addr;       /* Response dma'd here */
@@ -689,12 +672,12 @@ struct qlcnic_hostrq_tx_ctx {
        __le16 rsvd3;           /* Padding */
        struct qlcnic_hostrq_cds_ring cds_ring; /* Desc of cds ring */
        u8  reserved[128];      /* future expansion */
-};
+} __packed;

 struct qlcnic_cardrsp_cds_ring {
        __le32 host_producer_crb;       /* Crb to use */
        __le32 interrupt_crb;   /* Crb to use */
-};
+} __packed;

 struct qlcnic_cardrsp_tx_ctx {
        __le32 host_ctx_state;  /* Starting state */
@@ -703,7 +686,7 @@ struct qlcnic_cardrsp_tx_ctx {
        u8  virt_port;          /* Virtual/Logical id of port */
        struct qlcnic_cardrsp_cds_ring cds_ring;        /* Card cds settings */
        u8  reserved[128];      /* future expansion */
-};
+} __packed;

 #define SIZEOF_HOSTRQ_TX(HOSTRQ_TX)    (sizeof(HOSTRQ_TX))
 #define SIZEOF_CARDRSP_TX(CARDRSP_TX)  (sizeof(CARDRSP_TX))
@@ -782,50 +765,20 @@ struct qlcnic_nic_intr_coalesce {
 /*
  * Driver --> Firmware
  */
-#define QLCNIC_H2C_OPCODE_START                        0
-#define QLCNIC_H2C_OPCODE_CONFIG_RSS                   1
-#define QLCNIC_H2C_OPCODE_CONFIG_RSS_TBL               2
-#define QLCNIC_H2C_OPCODE_CONFIG_INTR_COALESCE         3
-#define QLCNIC_H2C_OPCODE_CONFIG_LED                   4
-#define QLCNIC_H2C_OPCODE_CONFIG_PROMISCUOUS           5
-#define QLCNIC_H2C_OPCODE_CONFIG_L2_MAC                6
-#define QLCNIC_H2C_OPCODE_LRO_REQUEST                  7
-#define QLCNIC_H2C_OPCODE_GET_SNMP_STATS               8
-#define QLCNIC_H2C_OPCODE_PROXY_START_REQUEST          9
-#define QLCNIC_H2C_OPCODE_PROXY_STOP_REQUEST           10
-#define QLCNIC_H2C_OPCODE_PROXY_SET_MTU                11
-#define QLCNIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE    12
-#define QLCNIC_H2C_OPCODE_GET_FINGER_PRINT_REQUEST     13
-#define QLCNIC_H2C_OPCODE_INSTALL_LICENSE_REQUEST      14
-#define QLCNIC_H2C_OPCODE_GET_LICENSE_CAPABILITY_REQUEST       15
-#define QLCNIC_H2C_OPCODE_GET_NET_STATS                16
-#define QLCNIC_H2C_OPCODE_PROXY_UPDATE_P2V             17
-#define QLCNIC_H2C_OPCODE_CONFIG_IPADDR                18
-#define QLCNIC_H2C_OPCODE_PROXY_STOP_DONE              20
-#define QLCNIC_H2C_OPCODE_GET_LINKEVENT                21
-#define QLCNIC_C2C_OPCODE                              22
-#define QLCNIC_H2C_OPCODE_CONFIG_BRIDGING              23
-#define QLCNIC_H2C_OPCODE_CONFIG_HW_LRO                24
-#define QLCNIC_H2C_OPCODE_LAST                         25
+#define QLCNIC_H2C_OPCODE_CONFIG_RSS                   0x1
+#define QLCNIC_H2C_OPCODE_CONFIG_INTR_COALESCE         0x3
+#define QLCNIC_H2C_OPCODE_CONFIG_LED                   0x4
+#define QLCNIC_H2C_OPCODE_LRO_REQUEST                  0x7
+#define QLCNIC_H2C_OPCODE_SET_MAC_RECEIVE_MODE         0xc
+#define QLCNIC_H2C_OPCODE_CONFIG_IPADDR                0x12
+#define QLCNIC_H2C_OPCODE_GET_LINKEVENT                0x15
+#define QLCNIC_H2C_OPCODE_CONFIG_BRIDGING              0x17
+#define QLCNIC_H2C_OPCODE_CONFIG_HW_LRO                0x18
 /*
  * Firmware --> Driver
  */

-#define QLCNIC_C2H_OPCODE_START                        128
-#define QLCNIC_C2H_OPCODE_CONFIG_RSS_RESPONSE          129
-#define QLCNIC_C2H_OPCODE_CONFIG_RSS_TBL_RESPONSE      130
-#define QLCNIC_C2H_OPCODE_CONFIG_MAC_RESPONSE          131
-#define QLCNIC_C2H_OPCODE_CONFIG_PROMISCUOUS_RESPONSE  132
-#define QLCNIC_C2H_OPCODE_CONFIG_L2_MAC_RESPONSE       133
-#define QLCNIC_C2H_OPCODE_LRO_DELETE_RESPONSE          134
-#define QLCNIC_C2H_OPCODE_LRO_ADD_FAILURE_RESPONSE     135
-#define QLCNIC_C2H_OPCODE_GET_SNMP_STATS               136
-#define QLCNIC_C2H_OPCODE_GET_FINGER_PRINT_REPLY       137
-#define QLCNIC_C2H_OPCODE_INSTALL_LICENSE_REPLY        138
-#define QLCNIC_C2H_OPCODE_GET_LICENSE_CAPABILITIES_REPLY 139
-#define QLCNIC_C2H_OPCODE_GET_NET_STATS_RESPONSE       140
 #define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE       141
-#define QLCNIC_C2H_OPCODE_LAST                         142

 #define VPORT_MISS_MODE_DROP           0 /* drop all unmatched */
 #define VPORT_MISS_MODE_ACCEPT_ALL     1 /* accept all packets */
@@ -894,7 +847,7 @@ struct qlcnic_nic_req {
        __le64 qhdr;
        __le64 req_hdr;
        __le64 words[6];
-};
+} __packed;

 struct qlcnic_mac_req {
        u8 op;
@@ -905,7 +858,7 @@ struct qlcnic_mac_req {
 struct qlcnic_vlan_req {
        __le16 vlan_id;
        __le16 rsvd[3];
-};
+} __packed;

 struct qlcnic_ipaddr {
        __be32 ipv4;
@@ -964,14 +917,14 @@ struct qlcnic_filter_hash {
 };

 struct qlcnic_adapter {
-       struct qlcnic_hardware_context ahw;
-
+       struct qlcnic_hardware_context *ahw;
+       struct qlcnic_recv_context *recv_ctx;
+       struct qlcnic_host_tx_ring *tx_ring;
        struct net_device *netdev;
        struct pci_dev *pdev;
-       struct list_head mac_list;

-       spinlock_t tx_clean_lock;
-       spinlock_t mac_learn_lock;
+       unsigned long state;
+       u32 flags;

        u16 num_txd;
        u16 num_rxd;
@@ -989,7 +942,6 @@ struct qlcnic_adapter {

        u8 mc_enabled;
        u8 max_mc_count;
-       u8 rss_supported;
        u8 fw_wait_cnt;
        u8 fw_fail_cnt;
        u8 tx_timeo_cnt;
@@ -1014,7 +966,6 @@ struct qlcnic_adapter {

        u32 fw_hal_version;
        u32 capabilities;
-       u32 flags;
        u32 irq;
        u32 temp;

@@ -1039,9 +990,7 @@ struct qlcnic_adapter {
        struct qlcnic_nic_template *nic_ops;

        struct qlcnic_adapter_stats stats;
-
-       struct qlcnic_recv_context recv_ctx;
-       struct qlcnic_host_tx_ring *tx_ring;
+       struct list_head mac_list;

        void __iomem    *tgt_mask_reg;
        void __iomem    *tgt_status_reg;
@@ -1056,7 +1005,8 @@ struct qlcnic_adapter {

        struct qlcnic_filter_hash fhash;

-       unsigned long state;
+       spinlock_t tx_clean_lock;
+       spinlock_t mac_learn_lock;
        __le32 file_prd_off;    /*File fw product offset*/
        u32 fw_version;
        const struct firmware *fw;
@@ -1078,7 +1028,7 @@ struct qlcnic_info {
        __le16  min_tx_bw;
        __le16  max_tx_bw;
        u8      reserved2[104];
-};
+} __packed;

 struct qlcnic_pci_info {
        __le16  id; /* pci function id */
@@ -1092,7 +1042,7 @@ struct qlcnic_pci_info {

        u8      mac[ETH_ALEN];
        u8      reserved2[106];
-};
+} __packed;

 struct qlcnic_npar_info {
        u16     pvid;
@@ -1209,7 +1159,7 @@ struct __qlcnic_esw_statistics {
        __le64 local_frames;
        __le64 numbytes;
        __le64 rsvd[3];
-};
+} __packed;

 struct qlcnic_esw_statistics {
        struct __qlcnic_esw_statistics rx;
@@ -1293,7 +1243,7 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter);

 int qlcnic_check_fw_status(struct qlcnic_adapter *adapter);
 void qlcnic_watchdog_task(struct work_struct *work);
-void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid,
+void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
                struct qlcnic_host_rds_ring *rds_ring);
 int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max);
 void qlcnic_set_multi(struct net_device *netdev);
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index 27631f2..050fa5a 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -67,11 +67,11 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
 int
 qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
 {
-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;

        if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) {
                if (qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        recv_ctx->context_id,
                        mtu,
@@ -102,12 +102,12 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
        dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
        u64 phys_addr;

-       int i, nrds_rings, nsds_rings;
+       u8 i, nrds_rings, nsds_rings;
        size_t rq_size, rsp_size;
        u32 cap, reg, val, reg2;
        int err;

-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;

        nrds_rings = adapter->max_rds_rings;
        nsds_rings = adapter->max_sds_rings;
@@ -119,14 +119,14 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
                SIZEOF_CARDRSP_RX(struct qlcnic_cardrsp_rx_ctx, nrds_rings,
                                                nsds_rings);

-       addr = pci_alloc_consistent(adapter->pdev,
-                               rq_size, &hostrq_phys_addr);
+       addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
+                       &hostrq_phys_addr, GFP_KERNEL);
        if (addr == NULL)
                return -ENOMEM;
        prq = (struct qlcnic_hostrq_rx_ctx *)addr;

-       addr = pci_alloc_consistent(adapter->pdev,
-                       rsp_size, &cardrsp_phys_addr);
+       addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
+                       &cardrsp_phys_addr, GFP_KERNEL);
        if (addr == NULL) {
                err = -ENOMEM;
                goto out_free_rq;
@@ -151,7 +151,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)

        prq->num_rds_rings = cpu_to_le16(nrds_rings);
        prq->num_sds_rings = cpu_to_le16(nsds_rings);
-       prq->rds_ring_offset = cpu_to_le32(0);
+       prq->rds_ring_offset = 0;

        val = le32_to_cpu(prq->rds_ring_offset) +
                (sizeof(struct qlcnic_hostrq_rds_ring) * nrds_rings);
@@ -187,7 +187,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)

        phys_addr = hostrq_phys_addr;
        err = qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        (u32)(phys_addr >> 32),
                        (u32)(phys_addr & 0xffffffff),
@@ -207,7 +207,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
                rds_ring = &recv_ctx->rds_rings[i];

                reg = le32_to_cpu(prsp_rds[i].host_producer_crb);
-               rds_ring->crb_rcv_producer = adapter->ahw.pci_base0 + reg;
+               rds_ring->crb_rcv_producer = adapter->ahw->pci_base0 + reg;
        }

        prsp_sds = ((struct qlcnic_cardrsp_sds_ring *)
@@ -219,8 +219,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
                reg = le32_to_cpu(prsp_sds[i].host_consumer_crb);
                reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb);

-               sds_ring->crb_sts_consumer = adapter->ahw.pci_base0 + reg;
-               sds_ring->crb_intr_mask = adapter->ahw.pci_base0 + reg2;
+               sds_ring->crb_sts_consumer = adapter->ahw->pci_base0 + reg;
+               sds_ring->crb_intr_mask = adapter->ahw->pci_base0 + reg2;
        }

        recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
@@ -228,19 +228,20 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
        recv_ctx->virt_port = prsp->virt_port;

 out_free_rsp:
-       pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr);
+       dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp,
+               cardrsp_phys_addr);
 out_free_rq:
-       pci_free_consistent(adapter->pdev, rq_size, prq, hostrq_phys_addr);
+       dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr);
        return err;
 }

 static void
 qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter)
 {
-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;

        if (qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        recv_ctx->context_id,
                        QLCNIC_DESTROY_CTX_RESET,
@@ -274,14 +275,14 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
        *(tx_ring->hw_consumer) = 0;

        rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
-       rq_addr = pci_alloc_consistent(adapter->pdev,
-               rq_size, &rq_phys_addr);
+       rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
+                       &rq_phys_addr, GFP_KERNEL);
        if (!rq_addr)
                return -ENOMEM;

        rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx);
-       rsp_addr = pci_alloc_consistent(adapter->pdev,
-               rsp_size, &rsp_phys_addr);
+       rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
+                       &rsp_phys_addr, GFP_KERNEL);
        if (!rsp_addr) {
                err = -ENOMEM;
                goto out_free_rq;
@@ -313,7 +314,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)

        phys_addr = rq_phys_addr;
        err = qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        (u32)(phys_addr >> 32),
                        ((u32)phys_addr & 0xffffffff),
@@ -322,7 +323,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)

        if (err == QLCNIC_RCODE_SUCCESS) {
                temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
-               tx_ring->crb_cmd_producer = adapter->ahw.pci_base0 + temp;
+               tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp;

                adapter->tx_context_id =
                        le16_to_cpu(prsp->context_id);
@@ -332,10 +333,11 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
                err = -EIO;
        }

-       pci_free_consistent(adapter->pdev, rsp_size, rsp_addr, rsp_phys_addr);
+       dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr,
+               rsp_phys_addr);

 out_free_rq:
-       pci_free_consistent(adapter->pdev, rq_size, rq_addr, rq_phys_addr);
+       dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr);

        return err;
 }
@@ -344,7 +346,7 @@ static void
 qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter)
 {
        if (qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        adapter->tx_context_id,
                        QLCNIC_DESTROY_CTX_RESET,
@@ -361,7 +363,7 @@ qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val)
 {

        if (qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        reg,
                        0,
@@ -378,7 +380,7 @@ int
 qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val)
 {
        return qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        reg,
                        val,
@@ -398,20 +400,19 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)

        struct pci_dev *pdev = adapter->pdev;

-       recv_ctx = &adapter->recv_ctx;
+       recv_ctx = adapter->recv_ctx;
        tx_ring = adapter->tx_ring;

-       tx_ring->hw_consumer = (__le32 *)pci_alloc_consistent(pdev, sizeof(u32),
-                                               &tx_ring->hw_cons_phys_addr);
+       tx_ring->hw_consumer = (__le32 *) dma_alloc_coherent(&pdev->dev,
+               sizeof(u32), &tx_ring->hw_cons_phys_addr, GFP_KERNEL);
        if (tx_ring->hw_consumer == NULL) {
                dev_err(&pdev->dev, "failed to allocate tx consumer\n");
                return -ENOMEM;
        }
-       *(tx_ring->hw_consumer) = 0;

        /* cmd desc ring */
-       addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring),
-                       &tx_ring->phys_addr);
+       addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring),
+                       &tx_ring->phys_addr, GFP_KERNEL);

        if (addr == NULL) {
                dev_err(&pdev->dev, "failed to allocate tx desc ring\n");
@@ -423,9 +424,9 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)

        for (ring = 0; ring < adapter->max_rds_rings; ring++) {
                rds_ring = &recv_ctx->rds_rings[ring];
-               addr = pci_alloc_consistent(adapter->pdev,
+               addr = dma_alloc_coherent(&adapter->pdev->dev,
                                RCV_DESC_RINGSIZE(rds_ring),
-                               &rds_ring->phys_addr);
+                               &rds_ring->phys_addr, GFP_KERNEL);
                if (addr == NULL) {
                        dev_err(&pdev->dev,
                                "failed to allocate rds ring [%d]\n", ring);
@@ -439,9 +440,9 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
        for (ring = 0; ring < adapter->max_sds_rings; ring++) {
                sds_ring = &recv_ctx->sds_rings[ring];

-               addr = pci_alloc_consistent(adapter->pdev,
+               addr = dma_alloc_coherent(&adapter->pdev->dev,
                                STATUS_DESC_RINGSIZE(sds_ring),
-                               &sds_ring->phys_addr);
+                               &sds_ring->phys_addr, GFP_KERNEL);
                if (addr == NULL) {
                        dev_err(&pdev->dev,
                                "failed to allocate sds ring [%d]\n", ring);
@@ -501,11 +502,11 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
        struct qlcnic_host_tx_ring *tx_ring;
        int ring;

-       recv_ctx = &adapter->recv_ctx;
+       recv_ctx = adapter->recv_ctx;

        tx_ring = adapter->tx_ring;
        if (tx_ring->hw_consumer != NULL) {
-               pci_free_consistent(adapter->pdev,
+               dma_free_coherent(&adapter->pdev->dev,
                                sizeof(u32),
                                tx_ring->hw_consumer,
                                tx_ring->hw_cons_phys_addr);
@@ -513,7 +514,7 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
        }

        if (tx_ring->desc_head != NULL) {
-               pci_free_consistent(adapter->pdev,
+               dma_free_coherent(&adapter->pdev->dev,
                                TX_DESC_RINGSIZE(tx_ring),
                                tx_ring->desc_head, tx_ring->phys_addr);
                tx_ring->desc_head = NULL;
@@ -523,7 +524,7 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
                rds_ring = &recv_ctx->rds_rings[ring];

                if (rds_ring->desc_head != NULL) {
-                       pci_free_consistent(adapter->pdev,
+                       dma_free_coherent(&adapter->pdev->dev,
                                        RCV_DESC_RINGSIZE(rds_ring),
                                        rds_ring->desc_head,
                                        rds_ring->phys_addr);
@@ -535,7 +536,7 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
                sds_ring = &recv_ctx->sds_rings[ring];

                if (sds_ring->desc_head != NULL) {
-                       pci_free_consistent(adapter->pdev,
+                       dma_free_coherent(&adapter->pdev->dev,
                                STATUS_DESC_RINGSIZE(sds_ring),
                                sds_ring->desc_head,
                                sds_ring->phys_addr);
@@ -551,9 +552,9 @@ int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
        int err;
        u32 arg1;

-       arg1 = adapter->ahw.pci_func | BIT_8;
+       arg1 = adapter->ahw->pci_func | BIT_8;
        err = qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        arg1,
                        0,
@@ -582,15 +583,15 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
        void *nic_info_addr;
        size_t  nic_size = sizeof(struct qlcnic_info);

-       nic_info_addr = pci_alloc_consistent(adapter->pdev,
-               nic_size, &nic_dma_t);
+       nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
+                               &nic_dma_t, GFP_KERNEL);
        if (!nic_info_addr)
                return -ENOMEM;
        memset(nic_info_addr, 0, nic_size);

        nic_info = (struct qlcnic_info *) nic_info_addr;
        err = qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        MSD(nic_dma_t),
                        LSD(nic_dma_t),
@@ -623,7 +624,8 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
                err = -EIO;
        }

-       pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t);
+       dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
+               nic_dma_t);
        return err;
 }

@@ -639,8 +641,8 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
        if (adapter->op_mode != QLCNIC_MGMT_FUNC)
                return err;

-       nic_info_addr = pci_alloc_consistent(adapter->pdev, nic_size,
-                       &nic_dma_t);
+       nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
+                       &nic_dma_t, GFP_KERNEL);
        if (!nic_info_addr)
                return -ENOMEM;

@@ -659,7 +661,7 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
        nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw);

        err = qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        MSD(nic_dma_t),
                        LSD(nic_dma_t),
@@ -672,7 +674,8 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
                err = -EIO;
        }

-       pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t);
+       dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
+               nic_dma_t);
        return err;
 }

@@ -687,15 +690,15 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
        size_t npar_size = sizeof(struct qlcnic_pci_info);
        size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;

-       pci_info_addr = pci_alloc_consistent(adapter->pdev, pci_size,
-                       &pci_info_dma_t);
+       pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
+                       &pci_info_dma_t, GFP_KERNEL);
        if (!pci_info_addr)
                return -ENOMEM;
        memset(pci_info_addr, 0, pci_size);

        npar = (struct qlcnic_pci_info *) pci_info_addr;
        err = qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        MSD(pci_info_dma_t),
                        LSD(pci_info_dma_t),
@@ -721,7 +724,7 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
                err = -EIO;
        }

-       pci_free_consistent(adapter->pdev, pci_size, pci_info_addr,
+       dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr,
                pci_info_dma_t);
        return err;
 }
@@ -741,7 +744,7 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
        arg1 |= pci_func << 8;

        err = qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        arg1,
                        0,
@@ -775,14 +778,14 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
                return -ENOMEM;

        if (adapter->op_mode != QLCNIC_MGMT_FUNC &&
-           func != adapter->ahw.pci_func) {
+           func != adapter->ahw->pci_func) {
                dev_err(&adapter->pdev->dev,
                        "Not privilege to query stats for func=%d", func);
                return -EIO;
        }

-       stats_addr = pci_alloc_consistent(adapter->pdev, stats_size,
-                       &stats_dma_t);
+       stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
+                       &stats_dma_t, GFP_KERNEL);
        if (!stats_addr) {
                dev_err(&adapter->pdev->dev, "Unable to allocate memory\n");
                return -ENOMEM;
@@ -793,7 +796,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
        arg1 |= rx_tx << 15 | stats_size << 16;

        err = qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        arg1,
                        MSD(stats_dma_t),
@@ -816,7 +819,7 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
                esw_stats->numbytes = le64_to_cpu(stats->numbytes);
        }

-       pci_free_consistent(adapter->pdev, stats_size, stats_addr,
+       dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
                stats_dma_t);
        return err;
 }
@@ -900,7 +903,7 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
        arg1 |= BIT_14 | rx_tx << 15;

        return qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        arg1,
                        0,
@@ -921,7 +924,7 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
        u8 pci_func;
        pci_func = (*arg1 >> 8);
        err = qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        *arg1,
                        0,
@@ -999,7 +1002,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
        }

        err = qlcnic_issue_cmd(adapter,
-                       adapter->ahw.pci_func,
+                       adapter->ahw->pci_func,
                        adapter->fw_hal_version,
                        arg1,
                        arg2,
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index 4c14510..b446045 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -150,10 +150,10 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
        struct qlcnic_adapter *adapter = netdev_priv(dev);
        int check_sfp_module = 0;
-       u16 pcifn = adapter->ahw.pci_func;
+       u16 pcifn = adapter->ahw->pci_func;

        /* read which mode */
-       if (adapter->ahw.port_type == QLCNIC_GBE) {
+       if (adapter->ahw->port_type == QLCNIC_GBE) {
                ecmd->supported = (SUPPORTED_10baseT_Half |
                                   SUPPORTED_10baseT_Full |
                                   SUPPORTED_100baseT_Half |
@@ -170,7 +170,7 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                ecmd->duplex = adapter->link_duplex;
                ecmd->autoneg = adapter->link_autoneg;

-       } else if (adapter->ahw.port_type == QLCNIC_XGBE) {
+       } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
                u32 val;

                val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
@@ -201,7 +201,7 @@ skip:
        ecmd->phy_address = adapter->physical_port;
        ecmd->transceiver = XCVR_EXTERNAL;

-       switch (adapter->ahw.board_type) {
+       switch (adapter->ahw->board_type) {
        case QLCNIC_BRDTYPE_P3P_REF_QG:
        case QLCNIC_BRDTYPE_P3P_4_GB:
        case QLCNIC_BRDTYPE_P3P_4_GB_MM:
@@ -238,7 +238,7 @@ skip:
                ecmd->autoneg = AUTONEG_DISABLE;
                break;
        case QLCNIC_BRDTYPE_P3P_10G_TP:
-               if (adapter->ahw.port_type == QLCNIC_XGBE) {
+               if (adapter->ahw->port_type == QLCNIC_XGBE) {
                        ecmd->autoneg = AUTONEG_DISABLE;
                        ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
                        ecmd->advertising |=
@@ -256,7 +256,7 @@ skip:
                break;
        default:
                dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
-                       adapter->ahw.board_type);
+                       adapter->ahw->board_type);
                return -EIO;
        }

@@ -288,7 +288,7 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
        __u32 status;

        /* read which mode */
-       if (adapter->ahw.port_type == QLCNIC_GBE) {
+       if (adapter->ahw->port_type == QLCNIC_GBE) {
                /* autonegotiation */
                if (qlcnic_fw_cmd_set_phy(adapter,
                               QLCNIC_NIU_GB_MII_MGMT_ADDR_AUTONEG,
@@ -340,14 +340,14 @@ static void
 qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
 {
        struct qlcnic_adapter *adapter = netdev_priv(dev);
-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
        struct qlcnic_host_sds_ring *sds_ring;
        u32 *regs_buff = p;
        int ring, i = 0, j = 0;

        memset(p, 0, qlcnic_get_regs_len(dev));
        regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
-               (adapter->ahw.revision_id << 16) | (adapter->pdev)->device;
+               (adapter->ahw->revision_id << 16) | (adapter->pdev)->device;

        regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
        regs_buff[1] = QLCNIC_MGMT_API_VERSION;
@@ -382,7 +382,7 @@ static u32 qlcnic_test_link(struct net_device *dev)
        u32 val;

        val = QLCRD32(adapter, CRB_XG_STATE_P3P);
-       val = XG_LINK_STATE_P3P(adapter->ahw.pci_func, val);
+       val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
        return (val == XG_LINK_UP_P3P) ? 0 : 1;
 }

@@ -482,7 +482,7 @@ qlcnic_get_pauseparam(struct net_device *netdev,
        int port = adapter->physical_port;
        __u32 val;

-       if (adapter->ahw.port_type == QLCNIC_GBE) {
+       if (adapter->ahw->port_type == QLCNIC_GBE) {
                if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
                        return;
                /* get flow control settings */
@@ -504,7 +504,7 @@ qlcnic_get_pauseparam(struct net_device *netdev,
                        pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val));
                        break;
                }
-       } else if (adapter->ahw.port_type == QLCNIC_XGBE) {
+       } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
                if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
                        return;
                pause->rx_pause = 1;
@@ -515,7 +515,7 @@ qlcnic_get_pauseparam(struct net_device *netdev,
                        pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val));
        } else {
                dev_err(&netdev->dev, "Unknown board type: %x\n",
-                                       adapter->ahw.port_type);
+                                       adapter->ahw->port_type);
        }
 }

@@ -528,7 +528,7 @@ qlcnic_set_pauseparam(struct net_device *netdev,
        __u32 val;

        /* read mode */
-       if (adapter->ahw.port_type == QLCNIC_GBE) {
+       if (adapter->ahw->port_type == QLCNIC_GBE) {
                if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
                        return -EIO;
                /* set flow control */
@@ -571,7 +571,7 @@ qlcnic_set_pauseparam(struct net_device *netdev,
                        break;
                }
                QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
-       } else if (adapter->ahw.port_type == QLCNIC_XGBE) {
+       } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
                if (!pause->rx_pause || pause->autoneg)
                        return -EOPNOTSUPP;

@@ -593,7 +593,7 @@ qlcnic_set_pauseparam(struct net_device *netdev,
                QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val);
        } else {
                dev_err(&netdev->dev, "Unknown board type: %x\n",
-                               adapter->ahw.port_type);
+                               adapter->ahw->port_type);
        }
        return 0;
 }
@@ -639,8 +639,8 @@ static int qlcnic_irq_test(struct net_device *netdev)
                goto clear_it;

        adapter->diag_cnt = 0;
-       ret = qlcnic_issue_cmd(adapter, adapter->ahw.pci_func,
-                       adapter->fw_hal_version, adapter->portnum,
+       ret = qlcnic_issue_cmd(adapter, adapter->ahw->pci_func,
+                       adapter->fw_hal_version, adapter->ahw->pci_func,
                        0, 0, 0x00000011);
        if (ret)
                goto done;
@@ -749,14 +749,14 @@ qlcnic_get_ethtool_stats(struct net_device *dev,
                return;

        memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
-       ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func,
+       ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
                        QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
        if (ret)
                return;

        qlcnic_fill_device_stats(&index, data, &port_stats.rx);

-       ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func,
+       ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
                        QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
        if (ret)
                return;
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 616940f..7e3f526 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -457,7 +457,7 @@ int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)

        req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);

-       word = QLCNIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE |
+       word = QLCNIC_H2C_OPCODE_SET_MAC_RECEIVE_MODE |
                        ((u64)adapter->portnum << 16);
        req.req_hdr = cpu_to_le64(word);

@@ -780,7 +780,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter,
        m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)];

        if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) {
-               *addr = adapter->ahw.pci_base0 + m->start_2M +
+               *addr = adapter->ahw->pci_base0 + m->start_2M +
                        (off - m->start_128M);
                return 0;
        }
@@ -788,7 +788,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter,
        /*
         * Not in direct map, use crb window
         */
-       *addr = adapter->ahw.pci_base0 + CRB_INDIRECT_2M + (off & MASK(16));
+       *addr = adapter->ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16));
        return 1;
 }

@@ -801,7 +801,7 @@ static int
 qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off)
 {
        u32 window;
-       void __iomem *addr = adapter->ahw.pci_base0 + CRB_WINDOW_2M;
+       void __iomem *addr = adapter->ahw->pci_base0 + CRB_WINDOW_2M;

        off -= QLCNIC_PCI_CRBSPACE;

@@ -838,13 +838,13 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data)

        if (rv > 0) {
                /* indirect access */
-               write_lock_irqsave(&adapter->ahw.crb_lock, flags);
+               write_lock_irqsave(&adapter->ahw->crb_lock, flags);
                crb_win_lock(adapter);
                rv = qlcnic_pci_set_crbwindow_2M(adapter, off);
                if (!rv)
                        writel(data, addr);
                crb_win_unlock(adapter);
-               write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);
+               write_unlock_irqrestore(&adapter->ahw->crb_lock, flags);
                return rv;
        }

@@ -869,12 +869,12 @@ qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)

        if (rv > 0) {
                /* indirect access */
-               write_lock_irqsave(&adapter->ahw.crb_lock, flags);
+               write_lock_irqsave(&adapter->ahw->crb_lock, flags);
                crb_win_lock(adapter);
                if (!qlcnic_pci_set_crbwindow_2M(adapter, off))
                        data = readl(addr);
                crb_win_unlock(adapter);
-               write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);
+               write_unlock_irqrestore(&adapter->ahw->crb_lock, flags);
                return data;
        }

@@ -904,9 +904,9 @@ qlcnic_pci_set_window_2M(struct qlcnic_adapter *adapter,

        window = OCM_WIN_P3P(addr);

-       writel(window, adapter->ahw.ocm_win_crb);
+       writel(window, adapter->ahw->ocm_win_crb);
        /* read back to flush */
-       readl(adapter->ahw.ocm_win_crb);
+       readl(adapter->ahw->ocm_win_crb);

        *start = QLCNIC_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr);
        return 0;
@@ -920,13 +920,13 @@ qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off,
        int ret;
        u32 start;

-       mutex_lock(&adapter->ahw.mem_lock);
+       mutex_lock(&adapter->ahw->mem_lock);

        ret = qlcnic_pci_set_window_2M(adapter, off, &start);
        if (ret != 0)
                goto unlock;

-       addr = adapter->ahw.pci_base0 + start;
+       addr = adapter->ahw->pci_base0 + start;

        if (op == 0)    /* read */
                *data = readq(addr);
@@ -934,7 +934,7 @@ qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off,
                writeq(*data, addr);

 unlock:
-       mutex_unlock(&adapter->ahw.mem_lock);
+       mutex_unlock(&adapter->ahw->mem_lock);

        return ret;
 }
@@ -942,23 +942,23 @@ unlock:
 void
 qlcnic_pci_camqm_read_2M(struct qlcnic_adapter *adapter, u64 off, u64 *data)
 {
-       void __iomem *addr = adapter->ahw.pci_base0 +
+       void __iomem *addr = adapter->ahw->pci_base0 +
                QLCNIC_PCI_CAMQM_2M_BASE + (off - QLCNIC_PCI_CAMQM);

-       mutex_lock(&adapter->ahw.mem_lock);
+       mutex_lock(&adapter->ahw->mem_lock);
        *data = readq(addr);
-       mutex_unlock(&adapter->ahw.mem_lock);
+       mutex_unlock(&adapter->ahw->mem_lock);
 }

 void
 qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data)
 {
-       void __iomem *addr = adapter->ahw.pci_base0 +
+       void __iomem *addr = adapter->ahw->pci_base0 +
                QLCNIC_PCI_CAMQM_2M_BASE + (off - QLCNIC_PCI_CAMQM);

-       mutex_lock(&adapter->ahw.mem_lock);
+       mutex_lock(&adapter->ahw->mem_lock);
        writeq(data, addr);
-       mutex_unlock(&adapter->ahw.mem_lock);
+       mutex_unlock(&adapter->ahw->mem_lock);
 }

 #define MAX_CTL_CHECK   1000
@@ -997,7 +997,7 @@ qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter,
 correct:
        off8 = off & ~0xf;

-       mutex_lock(&adapter->ahw.mem_lock);
+       mutex_lock(&adapter->ahw->mem_lock);

        writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
        writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
@@ -1049,7 +1049,7 @@ correct:
                ret = 0;

 done:
-       mutex_unlock(&adapter->ahw.mem_lock);
+       mutex_unlock(&adapter->ahw->mem_lock);

        return ret;
 }
@@ -1091,7 +1091,7 @@ qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter,
 correct:
        off8 = off & ~0xf;

-       mutex_lock(&adapter->ahw.mem_lock);
+       mutex_lock(&adapter->ahw->mem_lock);

        writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
        writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
@@ -1121,7 +1121,7 @@ correct:
                ret = 0;
        }

-       mutex_unlock(&adapter->ahw.mem_lock);
+       mutex_unlock(&adapter->ahw->mem_lock);

        return ret;
 }
@@ -1145,7 +1145,7 @@ int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
        if (qlcnic_rom_fast_read(adapter, offset, &board_type))
                return -EIO;

-       adapter->ahw.board_type = board_type;
+       adapter->ahw->board_type = board_type;

        if (board_type == QLCNIC_BRDTYPE_P3P_4_GB_MM) {
                u32 gpio = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_PAD_GPIO_I);
@@ -1164,20 +1164,20 @@ int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
        case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
        case QLCNIC_BRDTYPE_P3P_10G_XFP:
        case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
-               adapter->ahw.port_type = QLCNIC_XGBE;
+               adapter->ahw->port_type = QLCNIC_XGBE;
                break;
        case QLCNIC_BRDTYPE_P3P_REF_QG:
        case QLCNIC_BRDTYPE_P3P_4_GB:
        case QLCNIC_BRDTYPE_P3P_4_GB_MM:
-               adapter->ahw.port_type = QLCNIC_GBE;
+               adapter->ahw->port_type = QLCNIC_GBE;
                break;
        case QLCNIC_BRDTYPE_P3P_10G_TP:
-               adapter->ahw.port_type = (adapter->portnum < 2) ?
+               adapter->ahw->port_type = (adapter->portnum < 2) ?
                        QLCNIC_XGBE : QLCNIC_GBE;
                break;
        default:
                dev_err(&pdev->dev, "unknown board type %x\n", board_type);
-               adapter->ahw.port_type = QLCNIC_XGBE;
+               adapter->ahw->port_type = QLCNIC_XGBE;
                break;
        }

diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index a7f1d5b..476ea14 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -94,7 +94,7 @@ void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter)
        struct qlcnic_rx_buffer *rx_buf;
        int i, ring;

-       recv_ctx = &adapter->recv_ctx;
+       recv_ctx = adapter->recv_ctx;
        for (ring = 0; ring < adapter->max_rds_rings; ring++) {
                rds_ring = &recv_ctx->rds_rings[ring];
                for (i = 0; i < rds_ring->num_desc; ++i) {
@@ -119,7 +119,7 @@ void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter)
        struct qlcnic_rx_buffer *rx_buf;
        int i, ring;

-       recv_ctx = &adapter->recv_ctx;
+       recv_ctx = adapter->recv_ctx;
        for (ring = 0; ring < adapter->max_rds_rings; ring++) {
                rds_ring = &recv_ctx->rds_rings[ring];

@@ -173,7 +173,7 @@ void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
        struct qlcnic_host_tx_ring *tx_ring;
        int ring;

-       recv_ctx = &adapter->recv_ctx;
+       recv_ctx = adapter->recv_ctx;

        if (recv_ctx->rds_rings == NULL)
                goto skip_rds;
@@ -226,7 +226,7 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
        }
        tx_ring->cmd_buf_arr = cmd_buf_arr;

-       recv_ctx = &adapter->recv_ctx;
+       recv_ctx = adapter->recv_ctx;

        size = adapter->max_rds_rings * sizeof(struct qlcnic_host_rds_ring);
        rds_ring = kzalloc(size, GFP_KERNEL);
@@ -864,7 +864,7 @@ nomn:
        for (i = 0; i < entries; i++) {

                __le32 flags, file_chiprev, offs;
-               u8 chiprev = adapter->ahw.revision_id;
+               u8 chiprev = adapter->ahw->revision_id;
                u32 flagbit;

                offs = cpu_to_le32(ptab_descr->findex) +
@@ -1394,7 +1394,7 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
        return skb;
 }

-static int
+static inline int
 qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb,
                        u16 *vlan_tag)
 {
@@ -1425,7 +1425,7 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter,
                int ring, u64 sts_data0)
 {
        struct net_device *netdev = adapter->netdev;
-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
        struct qlcnic_rx_buffer *buffer;
        struct sk_buff *skb;
        struct qlcnic_host_rds_ring *rds_ring;
@@ -1488,7 +1488,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,
                int ring, u64 sts_data0, u64 sts_data1)
 {
        struct net_device *netdev = adapter->netdev;
-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
        struct qlcnic_rx_buffer *buffer;
        struct sk_buff *skb;
        struct qlcnic_host_rds_ring *rds_ring;
@@ -1625,7 +1625,7 @@ skip:

        for (ring = 0; ring < adapter->max_rds_rings; ring++) {
                struct qlcnic_host_rds_ring *rds_ring =
-                       &adapter->recv_ctx.rds_rings[ring];
+                       &adapter->recv_ctx->rds_rings[ring];

                if (!list_empty(&sds_ring->free_list[ring])) {
                        list_for_each(cur, &sds_ring->free_list[ring]) {
@@ -1651,12 +1651,13 @@ skip:
 }

 void
-qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, u32 ringid,
+qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
        struct qlcnic_host_rds_ring *rds_ring)
 {
        struct rcv_desc *pdesc;
        struct qlcnic_rx_buffer *buffer;
-       int producer, count = 0;
+       int count = 0;
+       u32 producer;
        struct list_head *head;

        producer = rds_ring->producer;
@@ -1696,7 +1697,8 @@ qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
 {
        struct rcv_desc *pdesc;
        struct qlcnic_rx_buffer *buffer;
-       int producer, count = 0;
+       int  count = 0;
+       uint32_t producer;
        struct list_head *head;

        if (!spin_trylock(&rds_ring->lock))
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index de6f866..dde7e44 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -113,7 +113,7 @@ static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
 MODULE_DEVICE_TABLE(pci, qlcnic_pci_tbl);


-void
+inline void
 qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
                struct qlcnic_host_tx_ring *tx_ring)
 {
@@ -169,7 +169,7 @@ qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
 {
        int ring;
        struct qlcnic_host_sds_ring *sds_ring;
-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;

        if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
                return -ENOMEM;
@@ -193,14 +193,14 @@ qlcnic_napi_del(struct qlcnic_adapter *adapter)
 {
        int ring;
        struct qlcnic_host_sds_ring *sds_ring;
-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;

        for (ring = 0; ring < adapter->max_sds_rings; ring++) {
                sds_ring = &recv_ctx->sds_rings[ring];
                netif_napi_del(&sds_ring->napi);
        }

-       qlcnic_free_sds_rings(&adapter->recv_ctx);
+       qlcnic_free_sds_rings(adapter->recv_ctx);
 }

 static void
@@ -208,7 +208,7 @@ qlcnic_napi_enable(struct qlcnic_adapter *adapter)
 {
        int ring;
        struct qlcnic_host_sds_ring *sds_ring;
-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;

        if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
                return;
@@ -225,7 +225,7 @@ qlcnic_napi_disable(struct qlcnic_adapter *adapter)
 {
        int ring;
        struct qlcnic_host_sds_ring *sds_ring;
-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;

        if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
                return;
@@ -359,7 +359,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter)
        struct pci_dev *pdev = adapter->pdev;
        int err, num_msix;

-       if (adapter->rss_supported) {
+       if (adapter->msix_supported) {
                num_msix = (num_online_cpus() >= MSIX_ENTRIES_PER_ADAPTER) ?
                        MSIX_ENTRIES_PER_ADAPTER : 2;
        } else
@@ -369,7 +369,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter)

        adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED);

-       legacy_intrp = &legacy_intr[adapter->ahw.pci_func];
+       legacy_intrp = &legacy_intr[adapter->ahw->pci_func];

        adapter->int_vec_bit = legacy_intrp->int_vec_bit;
        adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
@@ -391,8 +391,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter)
                        adapter->flags |= QLCNIC_MSIX_ENABLED;
                        qlcnic_set_msix_bit(pdev, 1);

-                       if (adapter->rss_supported)
-                               adapter->max_sds_rings = num_msix;
+                       adapter->max_sds_rings = num_msix;

                        dev_info(&pdev->dev, "using msi-x interrupts\n");
                        return;
@@ -407,7 +406,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter)
        if (use_msi && !pci_enable_msi(pdev)) {
                adapter->flags |= QLCNIC_MSI_ENABLED;
                adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
-                               msi_tgt_status[adapter->ahw.pci_func]);
+                               msi_tgt_status[adapter->ahw->pci_func]);
                dev_info(&pdev->dev, "using msi interrupts\n");
                adapter->msix_entries[0].vector = pdev->irq;
                return;
@@ -429,8 +428,8 @@ qlcnic_teardown_intr(struct qlcnic_adapter *adapter)
 static void
 qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
 {
-       if (adapter->ahw.pci_base0 != NULL)
-               iounmap(adapter->ahw.pci_base0);
+       if (adapter->ahw->pci_base0 != NULL)
+               iounmap(adapter->ahw->pci_base0);
 }

 static int
@@ -500,7 +499,7 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
        u32 ref_count;
        int i, ret = 1;
        u32 data = QLCNIC_MGMT_FUNC;
-       void __iomem *priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
+       void __iomem *priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE;

        /* If other drivers are not in use set their privilege level */
        ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
@@ -512,16 +511,16 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
                for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
                        id = i;
                        if (adapter->npars[i].type != QLCNIC_TYPE_NIC ||
-                               id == adapter->ahw.pci_func)
+                               id == adapter->ahw->pci_func)
                                continue;
                        data |= (qlcnic_config_npars &
                                        QLC_DEV_SET_DRV(0xf, id));
                }
        } else {
                data = readl(priv_op);
-               data = (data & ~QLC_DEV_SET_DRV(0xf, adapter->ahw.pci_func)) |
+               data = (data & ~QLC_DEV_SET_DRV(0xf, adapter->ahw->pci_func)) |
                        (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC,
-                       adapter->ahw.pci_func));
+                       adapter->ahw->pci_func));
        }
        writel(data, priv_op);
        qlcnic_api_unlock(adapter);
@@ -539,22 +538,23 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter)
        u32 op_mode, priv_level;

        /* Determine FW API version */
-       adapter->fw_hal_version = readl(adapter->ahw.pci_base0 + QLCNIC_FW_API);
+       adapter->fw_hal_version = readl(adapter->ahw->pci_base0 +
+                                       QLCNIC_FW_API);

        /* Find PCI function number */
        pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
-       msix_base_addr = adapter->ahw.pci_base0 + QLCNIC_MSIX_BASE;
+       msix_base_addr = adapter->ahw->pci_base0 + QLCNIC_MSIX_BASE;
        msix_base = readl(msix_base_addr);
        func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE;
-       adapter->ahw.pci_func = func;
+       adapter->ahw->pci_func = func;

        /* Determine function privilege level */
-       priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
+       priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
        op_mode = readl(priv_op);
        if (op_mode == QLC_DEV_DRV_DEFAULT)
                priv_level = QLCNIC_MGMT_FUNC;
        else
-               priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
+               priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);

        if (priv_level == QLCNIC_NON_PRIV_FUNC) {
                adapter->op_mode = QLCNIC_NON_PRIV_FUNC;
@@ -593,13 +593,14 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)

        dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));

-       adapter->ahw.pci_base0 = mem_ptr0;
-       adapter->ahw.pci_len0 = pci_len0;
+       adapter->ahw->pci_base0 = mem_ptr0;
+       adapter->ahw->pci_len0 = pci_len0;

        qlcnic_check_vf(adapter);

-       adapter->ahw.ocm_win_crb = qlcnic_get_ioaddr(adapter,
-               QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(adapter->ahw.pci_func)));
+       adapter->ahw->ocm_win_crb = qlcnic_get_ioaddr(adapter,
+               QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(
+                       adapter->ahw->pci_func)));

        return 0;
 }
@@ -641,7 +642,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)

        dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
                        fw_major, fw_minor, fw_build);
-       if (adapter->ahw.port_type == QLCNIC_XGBE) {
+       if (adapter->ahw->port_type == QLCNIC_XGBE) {
                if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
                        adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF;
                        adapter->max_rxd = MAX_RCV_DESCRIPTORS_VF;
@@ -653,7 +654,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
                adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
                adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;

-       } else if (adapter->ahw.port_type == QLCNIC_GBE) {
+       } else if (adapter->ahw->port_type == QLCNIC_GBE) {
                adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
                adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
                adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
@@ -661,7 +662,6 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
        }

        adapter->msix_supported = !!use_msi_x;
-       adapter->rss_supported = !!use_msi_x;

        adapter->num_txd = MAX_CMD_DESCRIPTORS;

@@ -674,7 +674,7 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
        int err;
        struct qlcnic_info nic_info;

-       err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func);
+       err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func);
        if (err)
                return err;

@@ -736,7 +736,7 @@ qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
        if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
                return 0;

-       esw_cfg.pci_func = adapter->ahw.pci_func;
+       esw_cfg.pci_func = adapter->ahw->pci_func;
        if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg))
                        return -EIO;
        qlcnic_set_vlan_config(adapter, &esw_cfg);
@@ -793,14 +793,14 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
        if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED)
                return 0;

-       priv_op = adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE;
+       priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
        op_mode = readl(priv_op);
-       priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
+       priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);

        if (op_mode == QLC_DEV_DRV_DEFAULT)
                priv_level = QLCNIC_MGMT_FUNC;
        else
-               priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
+               priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);

        if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
                if (priv_level == QLCNIC_MGMT_FUNC) {
@@ -1040,7 +1040,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)

        unsigned long flags = 0;
        struct net_device *netdev = adapter->netdev;
-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;

        if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
                handler = qlcnic_tmp_intr;
@@ -1077,7 +1077,7 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter)
        int ring;
        struct qlcnic_host_sds_ring *sds_ring;

-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;

        for (ring = 0; ring < adapter->max_sds_rings; ring++) {
                sds_ring = &recv_ctx->sds_rings[ring];
@@ -1117,14 +1117,14 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
                return -EIO;

        for (ring = 0; ring < adapter->max_rds_rings; ring++) {
-               rds_ring = &adapter->recv_ctx.rds_rings[ring];
-               qlcnic_post_rx_buffers(adapter, ring, rds_ring);
+               rds_ring = &adapter->recv_ctx->rds_rings[ring];
+               qlcnic_post_rx_buffers(adapter, rds_ring);
        }

        qlcnic_set_multi(netdev);
        qlcnic_fw_cmd_set_mtu(adapter, netdev->mtu);

-       adapter->ahw.linkup = 0;
+       adapter->ahw->linkup = 0;

        if (adapter->max_sds_rings > 1)
                qlcnic_config_rss(adapter, 1);
@@ -1274,7 +1274,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
        clear_bit(__QLCNIC_DEV_UP, &adapter->state);
        if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-                       sds_ring = &adapter->recv_ctx.sds_rings[ring];
+                       sds_ring = &adapter->recv_ctx->sds_rings[ring];
                        qlcnic_disable_int(sds_ring);
                }
        }
@@ -1295,6 +1295,39 @@ out:
        netif_device_attach(netdev);
 }

+static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter)
+{
+       int err = 0;
+       adapter->ahw = kzalloc(sizeof(struct qlcnic_hardware_context),
+                               GFP_KERNEL);
+       if (!adapter->ahw) {
+               dev_err(&adapter->pdev->dev,
+                       "Failed to allocate recv ctx resources for adapter\n");
+               err = -ENOMEM;
+               goto err_out;
+       }
+       adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context),
+                               GFP_KERNEL);
+       if (!adapter->recv_ctx) {
+               dev_err(&adapter->pdev->dev,
+                       "Failed to allocate recv ctx resources for adapter\n");
+               kfree(adapter->ahw);
+               adapter->ahw = NULL;
+               err = -ENOMEM;
+       }
+err_out:
+       return err;
+}
+
+static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter)
+{
+       kfree(adapter->recv_ctx);
+       adapter->recv_ctx = NULL;
+
+       kfree(adapter->ahw);
+       adapter->ahw = NULL;
+}
+
 int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
@@ -1327,13 +1360,13 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
        }

        for (ring = 0; ring < adapter->max_rds_rings; ring++) {
-               rds_ring = &adapter->recv_ctx.rds_rings[ring];
-               qlcnic_post_rx_buffers(adapter, ring, rds_ring);
+               rds_ring = &adapter->recv_ctx->rds_rings[ring];
+               qlcnic_post_rx_buffers(adapter, rds_ring);
        }

        if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-                       sds_ring = &adapter->recv_ctx.sds_rings[ring];
+                       sds_ring = &adapter->recv_ctx->sds_rings[ring];
                        qlcnic_enable_int(sds_ring);
                }
        }
@@ -1503,23 +1536,26 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        adapter = netdev_priv(netdev);
        adapter->netdev  = netdev;
        adapter->pdev    = pdev;
-       adapter->dev_rst_time = jiffies;

+       if (qlcnic_alloc_adapter_resources(adapter))
+               goto err_out_free_netdev;
+
+       adapter->dev_rst_time = jiffies;
        revision_id = pdev->revision;
-       adapter->ahw.revision_id = revision_id;
+       adapter->ahw->revision_id = revision_id;

-       rwlock_init(&adapter->ahw.crb_lock);
-       mutex_init(&adapter->ahw.mem_lock);
+       rwlock_init(&adapter->ahw->crb_lock);
+       mutex_init(&adapter->ahw->mem_lock);

        spin_lock_init(&adapter->tx_clean_lock);
        INIT_LIST_HEAD(&adapter->mac_list);

        err = qlcnic_setup_pci_map(adapter);
        if (err)
-               goto err_out_free_netdev;
+               goto err_out_free_hw;

        /* This will be reset for mezz cards  */
-       adapter->portnum = adapter->ahw.pci_func;
+       adapter->portnum = adapter->ahw->pci_func;

        err = qlcnic_get_board_info(adapter);
        if (err) {
@@ -1547,7 +1583,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

                pr_info("%s: %s Board Chip rev 0x%x\n",
                                module_name(THIS_MODULE),
-                               brd_name, adapter->ahw.revision_id);
+                               brd_name, adapter->ahw->revision_id);
        }

        qlcnic_clear_stats(adapter);
@@ -1562,7 +1598,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

        qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);

-       switch (adapter->ahw.port_type) {
+       switch (adapter->ahw->port_type) {
        case QLCNIC_GBE:
                dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
                                adapter->netdev->name);
@@ -1587,6 +1623,9 @@ err_out_decr_ref:
 err_out_iounmap:
        qlcnic_cleanup_pci_map(adapter);

+err_out_free_hw:
+       qlcnic_free_adapter_resources(adapter);
+
 err_out_free_netdev:
        free_netdev(netdev);

@@ -1640,6 +1679,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);

+       qlcnic_free_adapter_resources(adapter);
        free_netdev(netdev);
 }
 static int __qlcnic_shutdown(struct pci_dev *pdev)
@@ -2248,16 +2288,16 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
 {
        struct net_device *netdev = adapter->netdev;

-       if (adapter->ahw.linkup && !linkup) {
+       if (adapter->ahw->linkup && !linkup) {
                netdev_info(netdev, "NIC Link is down\n");
-               adapter->ahw.linkup = 0;
+               adapter->ahw->linkup = 0;
                if (netif_running(netdev)) {
                        netif_carrier_off(netdev);
                        netif_stop_queue(netdev);
                }
-       } else if (!adapter->ahw.linkup && linkup) {
+       } else if (!adapter->ahw->linkup && linkup) {
                netdev_info(netdev, "NIC Link is up\n");
-               adapter->ahw.linkup = 1;
+               adapter->ahw->linkup = 1;
                if (netif_running(netdev)) {
                        netif_carrier_on(netdev);
                        netif_wake_queue(netdev);
@@ -2493,7 +2533,7 @@ static void qlcnic_poll_controller(struct net_device *netdev)
        int ring;
        struct qlcnic_host_sds_ring *sds_ring;
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
-       struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;

        disable_irq(adapter->irq);
        for (ring = 0; ring < adapter->max_sds_rings; ring++) {
@@ -3503,7 +3543,7 @@ validate_esw_config(struct qlcnic_adapter *adapter,
        u8 pci_func;
        int i;

-       op_mode = readl(adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE);
+       op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);

        for (i = 0; i < count; i++) {
                pci_func = esw_cfg[i].pci_func;
@@ -3569,13 +3609,13 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
                        if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
                                return QL_STATUS_INVALID_PARAM;

-               if (adapter->ahw.pci_func != esw_cfg[i].pci_func)
+               if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
                        continue;

                op_mode = esw_cfg[i].op_mode;
                qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
                esw_cfg[i].op_mode = op_mode;
-               esw_cfg[i].pci_func = adapter->ahw.pci_func;
+               esw_cfg[i].pci_func = adapter->ahw->pci_func;

                switch (esw_cfg[i].op_mode) {
                case QLCNIC_PORT_DEFAULTS:
--
1.6.5.2


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply related

* [PATCH 1/9 net-next-2.6] qlcnic: make PCI info available in all modes
From: Anirban Chakraborty @ 2011-03-30 20:21 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

From: Sony Chacko <sony.chacko@qlogic.com>

Before this fix, PCI info was available only when multiple NIC functions were
present on a port.

Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
---
 drivers/net/qlcnic/qlcnic_main.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index cd88c7e..d230fdd 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -3954,14 +3954,14 @@ qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
                dev_info(dev, "failed to create crb sysfs entry\n");
        if (device_create_bin_file(dev, &bin_attr_mem))
                dev_info(dev, "failed to create mem sysfs entry\n");
+       if (device_create_bin_file(dev, &bin_attr_pci_config))
+               dev_info(dev, "failed to create pci config sysfs entry");
        if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
                return;
        if (device_create_bin_file(dev, &bin_attr_esw_config))
                dev_info(dev, "failed to create esw config sysfs entry");
        if (adapter->op_mode != QLCNIC_MGMT_FUNC)
                return;
-       if (device_create_bin_file(dev, &bin_attr_pci_config))
-               dev_info(dev, "failed to create pci config sysfs entry");
        if (device_create_bin_file(dev, &bin_attr_npar_config))
                dev_info(dev, "failed to create npar config sysfs entry");
        if (device_create_bin_file(dev, &bin_attr_pm_config))
@@ -3982,12 +3982,12 @@ qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
        device_remove_file(dev, &dev_attr_diag_mode);
        device_remove_bin_file(dev, &bin_attr_crb);
        device_remove_bin_file(dev, &bin_attr_mem);
+       device_remove_bin_file(dev, &bin_attr_pci_config);
        if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
                return;
        device_remove_bin_file(dev, &bin_attr_esw_config);
        if (adapter->op_mode != QLCNIC_MGMT_FUNC)
                return;
-       device_remove_bin_file(dev, &bin_attr_pci_config);
        device_remove_bin_file(dev, &bin_attr_npar_config);
        device_remove_bin_file(dev, &bin_attr_pm_config);
        device_remove_bin_file(dev, &bin_attr_esw_stats);
--
1.6.5.2


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply related

* [PATCH 0/9 net-next-2.6] qlcnic: Code cleanup and bug fixes
From: Anirban Chakraborty @ 2011-03-30 20:21 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

Please apply to net-next-2.6. Thanks.

-Anirban


This message and any attached documents contain information from QLogic Corporation or its wholly-owned subsidiaries that may be confidential. If you are not the intended recipient, you may not read, copy, distribute, or use this information. If you have received this transmission in error, please notify the sender immediately by reply e-mail and then delete this message.


^ permalink raw reply

* Re: [PATCH] BRIDGE: As per 802.1D clause 9.3.4 Added support to prevent processing port's own BPDU (If a loopback condition exists)
From: Sasikanth V @ 2011-03-30 19:26 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, bridge
In-Reply-To: <20110330092542.6344b324@s6510>


[-- Attachment #1.1: Type: text/plain, Size: 4952 bytes --]

On Wed, Mar 30, 2011 at 9:55 PM, Stephen Hemminger <shemminger@vyatta.com>wrote:

> On Wed, 30 Mar 2011 21:03:36 +0530
> Sasikanth V <sasikanth.v19@gmail.com> wrote:
>
> >
> > Signed-off-by: Sasikanth V <sasikanth.v19@gmail.com>
> > ---
> >  net/bridge/br_private.h   |    1 +
> >  net/bridge/br_stp.c       |   20 ++++++++++++++++++--
> >  net/bridge/br_stp_if.c    |    2 ++
> >  net/bridge/br_stp_timer.c |    1 +
> >  4 files changed, 22 insertions(+), 2 deletions(-)
> >
> > diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> > index 387013d..d9f79dd 100644
> > --- a/net/bridge/br_private.h
> > +++ b/net/bridge/br_private.h
> > @@ -149,6 +149,7 @@ struct net_bridge_port
> >  #ifdef CONFIG_NET_POLL_CONTROLLER
> >       struct netpoll                  *np;
> >  #endif
> > +     u8                              is_own_bpdu; /*Port recvd its own
> BPDU*/
> >  };
> >
> >  #define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
> > diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
> > index 7370d14..491d9c6 100644
> > --- a/net/bridge/br_stp.c
> > +++ b/net/bridge/br_stp.c
> > @@ -107,6 +107,12 @@ static void br_root_selection(struct net_bridge *br)
> >       u16 root_port = 0;
> >
> >       list_for_each_entry(p, &br->port_list, list) {
> > +             /*Don't consider the Port for root selection
> > +               which rx'd its own bpdu because of loopback
> > +               in the bridge
> > +              */
> > +             if (p->is_own_bpdu)
> > +                     continue;
> >               if (br_should_become_root_port(p, root_port))
> >                       root_port = p->port_no;
> >
> > @@ -278,8 +284,16 @@ static int br_supersedes_port_info(struct
> net_bridge_port *p, struct br_config_b
> >       if (memcmp(&bpdu->bridge_id, &p->br->bridge_id, 8))
> >               return 1;
> >
> > -     if (bpdu->port_id <= p->designated_port)
> > +     if (bpdu->port_id <= p->designated_port) {
> > +             /*802.1D 9.3.4 Validation of received BPDUs
> > +              NOTE 1—If the Bridge Identifier and Port Identifier both
> > +              match the values that would be transmitted in a
> Configuration
> > +              BPDU, the BPDU is discarded to prevent processing of the
> Port’s
> > +              own BPDUs;*/
> > +             if (bpdu->port_id == p->designated_port)
> > +                     p->is_own_bpdu = 1;
> >               return 1;
> > +     }
> >
> >       return 0;
> >  }
> > @@ -411,7 +425,7 @@ void br_port_state_selection(struct net_bridge *br)
> >                       p->config_pending = 0;
> >                       p->topology_change_ack = 0;
> >                       br_make_forwarding(p);
> > -             } else if (br_is_designated_port(p)) {
> > +             } else if (!p->is_own_bpdu && br_is_designated_port(p)) {
> >                       del_timer(&p->message_age_timer);
> >                       br_make_forwarding(p);
> >               } else {
> > @@ -446,6 +460,8 @@ void br_received_config_bpdu(struct net_bridge_port
> *p, struct br_config_bpdu *b
> >       br = p->br;
> >       was_root = br_is_root_bridge(br);
> >
> > +     p->is_own_bpdu = 0;
> > +
> >       if (br_supersedes_port_info(p, bpdu)) {
> >               br_record_config_information(p, bpdu);
> >               br_configuration_update(br);
> > diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
> > index 5593f5a..fc4ec63 100644
> > --- a/net/bridge/br_stp_if.c
> > +++ b/net/bridge/br_stp_if.c
> > @@ -37,6 +37,7 @@ void br_init_port(struct net_bridge_port *p)
> >       p->state = BR_STATE_BLOCKING;
> >       p->topology_change_ack = 0;
> >       p->config_pending = 0;
> > +     p->is_own_bpdu = 0;
> >  }
> >
> >  /* called under bridge lock */
> > @@ -101,6 +102,7 @@ void br_stp_disable_port(struct net_bridge_port *p)
> >       p->state = BR_STATE_DISABLED;
> >       p->topology_change_ack = 0;
> >       p->config_pending = 0;
> > +     p->is_own_bpdu = 0;
> >
> >       del_timer(&p->message_age_timer);
> >       del_timer(&p->forward_delay_timer);
> > diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
> > index 3e96514..99ea288 100644
> > --- a/net/bridge/br_stp_timer.c
> > +++ b/net/bridge/br_stp_timer.c
> > @@ -67,6 +67,7 @@ static void br_message_age_timer_expired(unsigned long
> arg)
> >       spin_lock(&br->lock);
> >       if (p->state == BR_STATE_DISABLED)
> >               goto unlock;
> > +     p->is_own_bpdu = 0;
> >       was_root = br_is_root_bridge(br);
> >
> >       br_become_designated_port(p);
>
>
> The idea is valid, but putting state variable per port is an
> ugly way to solve it.
>

  Stephen, Thanks for looking at the patch. Will resend you the patch
without the per port state variable.
  Thanks (in my previous mail i missed out CC bridge and netdev group)

[-- Attachment #1.2: Type: text/html, Size: 6061 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Bridge mailing list
Bridge@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/bridge

^ permalink raw reply

* Re: [PATCH] BRIDGE: As per 802.1D clause 9.3.4 Added support to prevent processing port's own BPDU (If a loopback condition exists)
From: Stephen Hemminger @ 2011-03-30 16:25 UTC (permalink / raw)
  To: Sasikanth V; +Cc: shemminger, netdev, bridge
In-Reply-To: <1301499216-3836-1-git-send-email-sasikanth.v19@gmail.com>

On Wed, 30 Mar 2011 21:03:36 +0530
Sasikanth V <sasikanth.v19@gmail.com> wrote:

> 
> Signed-off-by: Sasikanth V <sasikanth.v19@gmail.com>
> ---
>  net/bridge/br_private.h   |    1 +
>  net/bridge/br_stp.c       |   20 ++++++++++++++++++--
>  net/bridge/br_stp_if.c    |    2 ++
>  net/bridge/br_stp_timer.c |    1 +
>  4 files changed, 22 insertions(+), 2 deletions(-)
> 
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 387013d..d9f79dd 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -149,6 +149,7 @@ struct net_bridge_port
>  #ifdef CONFIG_NET_POLL_CONTROLLER
>  	struct netpoll			*np;
>  #endif
> +	u8                              is_own_bpdu; /*Port recvd its own BPDU*/
>  };
>  
>  #define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
> diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
> index 7370d14..491d9c6 100644
> --- a/net/bridge/br_stp.c
> +++ b/net/bridge/br_stp.c
> @@ -107,6 +107,12 @@ static void br_root_selection(struct net_bridge *br)
>  	u16 root_port = 0;
>  
>  	list_for_each_entry(p, &br->port_list, list) {
> +		/*Don't consider the Port for root selection
> +  		  which rx'd its own bpdu because of loopback
> +		  in the bridge
> +  		 */
> +		if (p->is_own_bpdu)
> +			continue;
>  		if (br_should_become_root_port(p, root_port))
>  			root_port = p->port_no;
>  
> @@ -278,8 +284,16 @@ static int br_supersedes_port_info(struct net_bridge_port *p, struct br_config_b
>  	if (memcmp(&bpdu->bridge_id, &p->br->bridge_id, 8))
>  		return 1;
>  
> -	if (bpdu->port_id <= p->designated_port)
> +	if (bpdu->port_id <= p->designated_port) {
> +		/*802.1D 9.3.4 Validation of received BPDUs
> + 		 NOTE 1—If the Bridge Identifier and Port Identifier both 
> + 		 match the values that would be transmitted in a Configuration
> +		 BPDU, the BPDU is discarded to prevent processing of the Port’s 
> +		 own BPDUs;*/
> +		if (bpdu->port_id == p->designated_port)
> +			p->is_own_bpdu = 1;
>  		return 1;
> +	}
>  
>  	return 0;
>  }
> @@ -411,7 +425,7 @@ void br_port_state_selection(struct net_bridge *br)
>  			p->config_pending = 0;
>  			p->topology_change_ack = 0;
>  			br_make_forwarding(p);
> -		} else if (br_is_designated_port(p)) {
> +		} else if (!p->is_own_bpdu && br_is_designated_port(p)) {
>  			del_timer(&p->message_age_timer);
>  			br_make_forwarding(p);
>  		} else {
> @@ -446,6 +460,8 @@ void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *b
>  	br = p->br;
>  	was_root = br_is_root_bridge(br);
>  
> +	p->is_own_bpdu = 0;
> +
>  	if (br_supersedes_port_info(p, bpdu)) {
>  		br_record_config_information(p, bpdu);
>  		br_configuration_update(br);
> diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
> index 5593f5a..fc4ec63 100644
> --- a/net/bridge/br_stp_if.c
> +++ b/net/bridge/br_stp_if.c
> @@ -37,6 +37,7 @@ void br_init_port(struct net_bridge_port *p)
>  	p->state = BR_STATE_BLOCKING;
>  	p->topology_change_ack = 0;
>  	p->config_pending = 0;
> +	p->is_own_bpdu = 0;
>  }
>  
>  /* called under bridge lock */
> @@ -101,6 +102,7 @@ void br_stp_disable_port(struct net_bridge_port *p)
>  	p->state = BR_STATE_DISABLED;
>  	p->topology_change_ack = 0;
>  	p->config_pending = 0;
> +	p->is_own_bpdu = 0;
>  
>  	del_timer(&p->message_age_timer);
>  	del_timer(&p->forward_delay_timer);
> diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
> index 3e96514..99ea288 100644
> --- a/net/bridge/br_stp_timer.c
> +++ b/net/bridge/br_stp_timer.c
> @@ -67,6 +67,7 @@ static void br_message_age_timer_expired(unsigned long arg)
>  	spin_lock(&br->lock);
>  	if (p->state == BR_STATE_DISABLED)
>  		goto unlock;
> +	p->is_own_bpdu = 0;
>  	was_root = br_is_root_bridge(br);
>  
>  	br_become_designated_port(p);


The idea is valid, but putting state variable per port is an
ugly way to solve it.

^ permalink raw reply

* [PATCH] BRIDGE: As per 802.1D clause 9.3.4 Added support to prevent processing port's own BPDU (If a loopback condition exists)
From: Sasikanth V @ 2011-03-30 15:33 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, bridge, Sasikanth V


Signed-off-by: Sasikanth V <sasikanth.v19@gmail.com>
---
 net/bridge/br_private.h   |    1 +
 net/bridge/br_stp.c       |   20 ++++++++++++++++++--
 net/bridge/br_stp_if.c    |    2 ++
 net/bridge/br_stp_timer.c |    1 +
 4 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 387013d..d9f79dd 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -149,6 +149,7 @@ struct net_bridge_port
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	struct netpoll			*np;
 #endif
+	u8                              is_own_bpdu; /*Port recvd its own BPDU*/
 };
 
 #define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 7370d14..491d9c6 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -107,6 +107,12 @@ static void br_root_selection(struct net_bridge *br)
 	u16 root_port = 0;
 
 	list_for_each_entry(p, &br->port_list, list) {
+		/*Don't consider the Port for root selection
+  		  which rx'd its own bpdu because of loopback
+		  in the bridge
+  		 */
+		if (p->is_own_bpdu)
+			continue;
 		if (br_should_become_root_port(p, root_port))
 			root_port = p->port_no;
 
@@ -278,8 +284,16 @@ static int br_supersedes_port_info(struct net_bridge_port *p, struct br_config_b
 	if (memcmp(&bpdu->bridge_id, &p->br->bridge_id, 8))
 		return 1;
 
-	if (bpdu->port_id <= p->designated_port)
+	if (bpdu->port_id <= p->designated_port) {
+		/*802.1D 9.3.4 Validation of received BPDUs
+ 		 NOTE 1—If the Bridge Identifier and Port Identifier both 
+ 		 match the values that would be transmitted in a Configuration
+		 BPDU, the BPDU is discarded to prevent processing of the Port’s 
+		 own BPDUs;*/
+		if (bpdu->port_id == p->designated_port)
+			p->is_own_bpdu = 1;
 		return 1;
+	}
 
 	return 0;
 }
@@ -411,7 +425,7 @@ void br_port_state_selection(struct net_bridge *br)
 			p->config_pending = 0;
 			p->topology_change_ack = 0;
 			br_make_forwarding(p);
-		} else if (br_is_designated_port(p)) {
+		} else if (!p->is_own_bpdu && br_is_designated_port(p)) {
 			del_timer(&p->message_age_timer);
 			br_make_forwarding(p);
 		} else {
@@ -446,6 +460,8 @@ void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *b
 	br = p->br;
 	was_root = br_is_root_bridge(br);
 
+	p->is_own_bpdu = 0;
+
 	if (br_supersedes_port_info(p, bpdu)) {
 		br_record_config_information(p, bpdu);
 		br_configuration_update(br);
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 5593f5a..fc4ec63 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -37,6 +37,7 @@ void br_init_port(struct net_bridge_port *p)
 	p->state = BR_STATE_BLOCKING;
 	p->topology_change_ack = 0;
 	p->config_pending = 0;
+	p->is_own_bpdu = 0;
 }
 
 /* called under bridge lock */
@@ -101,6 +102,7 @@ void br_stp_disable_port(struct net_bridge_port *p)
 	p->state = BR_STATE_DISABLED;
 	p->topology_change_ack = 0;
 	p->config_pending = 0;
+	p->is_own_bpdu = 0;
 
 	del_timer(&p->message_age_timer);
 	del_timer(&p->forward_delay_timer);
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index 3e96514..99ea288 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -67,6 +67,7 @@ static void br_message_age_timer_expired(unsigned long arg)
 	spin_lock(&br->lock);
 	if (p->state == BR_STATE_DISABLED)
 		goto unlock;
+	p->is_own_bpdu = 0;
 	was_root = br_is_root_bridge(br);
 
 	br_become_designated_port(p);
-- 
1.7.3.4


^ permalink raw reply related

* [PATCH] ipv6: Add support for RTA_PREFSRC
From: Daniel Walter @ 2011-03-30 15:29 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 15360 bytes --]

From: Daniel Walter <dwalter@barracuda.com>

[ipv6] Add support for RTA_PREFSRC

This patch allows a user to select the preferred source address
for a specific IPv6-Route. It can be set via a netlink message
setting RTA_PREFSRC to a valid IPv6 address which must be
up on the device the route will be bound to. 
 
Signed-off-by: Daniel Walter <dwalter@barracuda.com>
---

patch should apply clean against linux-2.3.39 HEAD

 include/linux/ipv6_route.h |    1 +
 include/net/ip6_fib.h      |    2 +
 include/net/ip6_route.h    |    1 +
 net/ipv6/addrconf.c        |    2 +
 net/ipv6/ip6_output.c      |   12 +++++--
 net/ipv6/route.c           |   68 ++++++++++++++++++++++++++++++++++++++++++--
 6 files changed, 79 insertions(+), 7 deletions(-)

diff --git a/include/linux/ipv6_route.h b/include/linux/ipv6_route.h
index 1e7d8af..9845953 100644
--- a/include/linux/ipv6_route.h
+++ b/include/linux/ipv6_route.h
@@ -44,6 +44,7 @@
 struct in6_rtmsg {
 	struct in6_addr		rtmsg_dst;
 	struct in6_addr		rtmsg_src;
+	struct in6_addr		rtmsg_prefsrc;
 	struct in6_addr		rtmsg_gateway;
 	__u32			rtmsg_type;
 	__u16			rtmsg_dst_len;
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index bc3cde0..98348d5 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -42,6 +42,7 @@ struct fib6_config {
 
 	struct in6_addr	fc_dst;
 	struct in6_addr	fc_src;
+	struct in6_addr	fc_prefsrc;
 	struct in6_addr	fc_gateway;
 
 	unsigned long	fc_expires;
@@ -107,6 +108,7 @@ struct rt6_info {
 	struct rt6key			rt6i_dst ____cacheline_aligned_in_smp;
 	u32				rt6i_flags;
 	struct rt6key			rt6i_src;
+	struct rt6key			rt6i_prefsrc;
 	u32				rt6i_metric;
 	u32				rt6i_peer_genid;
 
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index c850e5f..2b37c20 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -141,6 +141,7 @@ struct rt6_rtnl_dump_arg {
 extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
 extern void rt6_ifdown(struct net *net, struct net_device *dev);
 extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
+extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
 

 /*
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3daaf3c..26f9e14 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -825,6 +825,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
 		dst_release(&rt->dst);
 	}
 
+	/* clean up prefsrc entries */
+	rt6_remove_prefsrc(ifp);
 out:
 	in6_ifa_put(ifp);
 }
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 1820887..e2d8463 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -930,10 +930,14 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 		goto out_err_release;
 
 	if (ipv6_addr_any(&fl6->saddr)) {
-		err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
-					 &fl6->daddr,
-					 sk ? inet6_sk(sk)->srcprefs : 0,
-					 &fl6->saddr);
+		struct rt6_info *rt = (struct rt6_info *) *dst;
+		if (rt->rt6i_prefsrc.plen)
+			ipv6_addr_copy(&fl6->saddr, &rt->rt6i_prefsrc.addr);
+		else
+			err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
+						 &fl6->daddr,
+						 sk ? inet6_sk(sk)->srcprefs : 0,
+						 &fl6->saddr);
 		if (err)
 			goto out_err_release;
 	}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 843406f..b53089d 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1325,6 +1325,20 @@ int ip6_route_add(struct fib6_config *cfg)
 	if (dev == NULL)
 		goto out;
 
+	/* check if prefsrc is set */
+	if (!ipv6_addr_any(&cfg->fc_prefsrc)) {
+		struct in6_addr saddr_buf;
+		ipv6_addr_copy(&saddr_buf, &cfg->fc_prefsrc);
+		if (!ipv6_chk_addr(net, &saddr_buf, dev, 0)) {
+			printk(KERN_DEBUG "invalid pref_src\n");
+			err = -EINVAL;
+			goto out;
+		}
+		ipv6_addr_copy(&rt->rt6i_prefsrc.addr, &cfg->fc_prefsrc);
+		rt->rt6i_prefsrc.plen = 128;
+	} else
+		rt->rt6i_prefsrc.plen = 0;
+
 	if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
 		rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
 		if (IS_ERR(rt->rt6i_nexthop)) {
@@ -1893,6 +1907,7 @@ static void rtmsg_to_fib6_config(struct net *net,
 	ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst);
 	ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src);
 	ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway);
+	ipv6_addr_copy(&cfg->fc_prefsrc, &rtmsg->rtmsg_prefsrc);
 }
 
 int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
@@ -2037,6 +2052,39 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 	return rt;
 }
 
+/* remove deleted ip from prefsrc entries */
+struct arg_dev_net_ip {
+	struct net_device *dev;
+	struct net *net;
+	struct in6_addr *addr;
+};
+
+static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg)
+{
+	struct net_device *dev = ((struct arg_dev_net_ip *)arg)->dev;
+	struct net *net = ((struct arg_dev_net_ip *)arg)->net;
+	struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr;
+
+	if (((void *)rt->rt6i_dev == dev || dev == NULL) &&
+	    rt != net->ipv6.ip6_null_entry &&
+	    ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) {
+		/* remove prefsrc entry */
+		rt->rt6i_prefsrc.plen = 0;
+	}
+	return 0;
+}
+
+void rt6_remove_prefsrc(struct inet6_ifaddr *ifp)
+{
+	struct net *net = dev_net(ifp->idev->dev);
+	struct arg_dev_net_ip adni = {
+		.dev = ifp->idev->dev,
+		.net = net,
+		.addr = &ifp->addr,
+	};
+	fib6_clean_all(net, fib6_remove_prefsrc, 0, &adni);
+}
+
 struct arg_dev_net {
 	struct net_device *dev;
 	struct net *net;
@@ -2183,6 +2231,9 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
 		nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen);
 	}
 
+	if (tb[RTA_PREFSRC])
+		nla_memcpy(&cfg->fc_prefsrc, tb[RTA_PREFSRC], 16);
+
 	if (tb[RTA_OIF])
 		cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]);
 
@@ -2325,11 +2376,22 @@ static int rt6_fill_node(struct net *net,
 #endif
 			NLA_PUT_U32(skb, RTA_IIF, iif);
 	} else if (dst) {
-		struct inet6_dev *idev = ip6_dst_idev(&rt->dst);
 		struct in6_addr saddr_buf;
-		if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
-				       dst, 0, &saddr_buf) == 0)
+		if (rt->rt6i_prefsrc.plen) {
+			ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr);
 			NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
+		} else {
+			struct inet6_dev *idev = ip6_dst_idev(&rt->dst);
+			if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
+					       dst, 0, &saddr_buf) == 0)
+				NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
+		}
+	}
+
+	if (rt->rt6i_prefsrc.plen) {
+		struct in6_addr saddr_buf;
+		ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr);
+		NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
 	}
 
 	if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)











From: Daniel Walter <dwalter@barracuda.com>

[ipv6] Add support for RTA_PREFSRC

This patch allows a user to select the preferred source address
for a specific IPv6-Route. It can be set via a netlink message
setting RTA_PREFSRC to a valid IPv6 address which must be
up on the device the route will be bound to. 
 
Signed-off-by: Daniel Walter <dwalter@barracuda.com>
---

patch should apply clean against linux-2.3.39 HEAD

 include/linux/ipv6_route.h |    1 +
 include/net/ip6_fib.h      |    2 +
 include/net/ip6_route.h    |    1 +
 net/ipv6/addrconf.c        |    2 +
 net/ipv6/ip6_output.c      |   12 +++++--
 net/ipv6/route.c           |   68 ++++++++++++++++++++++++++++++++++++++++++--
 6 files changed, 79 insertions(+), 7 deletions(-)

diff --git a/include/linux/ipv6_route.h b/include/linux/ipv6_route.h
index 1e7d8af..9845953 100644
--- a/include/linux/ipv6_route.h
+++ b/include/linux/ipv6_route.h
@@ -44,6 +44,7 @@
 struct in6_rtmsg {
 	struct in6_addr		rtmsg_dst;
 	struct in6_addr		rtmsg_src;
+	struct in6_addr		rtmsg_prefsrc;
 	struct in6_addr		rtmsg_gateway;
 	__u32			rtmsg_type;
 	__u16			rtmsg_dst_len;
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index bc3cde0..98348d5 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -42,6 +42,7 @@ struct fib6_config {
 
 	struct in6_addr	fc_dst;
 	struct in6_addr	fc_src;
+	struct in6_addr	fc_prefsrc;
 	struct in6_addr	fc_gateway;
 
 	unsigned long	fc_expires;
@@ -107,6 +108,7 @@ struct rt6_info {
 	struct rt6key			rt6i_dst ____cacheline_aligned_in_smp;
 	u32				rt6i_flags;
 	struct rt6key			rt6i_src;
+	struct rt6key			rt6i_prefsrc;
 	u32				rt6i_metric;
 	u32				rt6i_peer_genid;
 
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index c850e5f..2b37c20 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -141,6 +141,7 @@ struct rt6_rtnl_dump_arg {
 extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
 extern void rt6_ifdown(struct net *net, struct net_device *dev);
 extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
+extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
 

 /*
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3daaf3c..26f9e14 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -825,6 +825,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
 		dst_release(&rt->dst);
 	}
 
+	/* clean up prefsrc entries */
+	rt6_remove_prefsrc(ifp);
 out:
 	in6_ifa_put(ifp);
 }
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 1820887..e2d8463 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -930,10 +930,14 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 		goto out_err_release;
 
 	if (ipv6_addr_any(&fl6->saddr)) {
-		err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
-					 &fl6->daddr,
-					 sk ? inet6_sk(sk)->srcprefs : 0,
-					 &fl6->saddr);
+		struct rt6_info *rt = (struct rt6_info *) *dst;
+		if (rt->rt6i_prefsrc.plen)
+			ipv6_addr_copy(&fl6->saddr, &rt->rt6i_prefsrc.addr);
+		else
+			err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
+						 &fl6->daddr,
+						 sk ? inet6_sk(sk)->srcprefs : 0,
+						 &fl6->saddr);
 		if (err)
 			goto out_err_release;
 	}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 843406f..b53089d 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1325,6 +1325,20 @@ int ip6_route_add(struct fib6_config *cfg)
 	if (dev == NULL)
 		goto out;
 
+	/* check if prefsrc is set */
+	if (!ipv6_addr_any(&cfg->fc_prefsrc)) {
+		struct in6_addr saddr_buf;
+		ipv6_addr_copy(&saddr_buf, &cfg->fc_prefsrc);
+		if (!ipv6_chk_addr(net, &saddr_buf, dev, 0)) {
+			printk(KERN_DEBUG "invalid pref_src\n");
+			err = -EINVAL;
+			goto out;
+		}
+		ipv6_addr_copy(&rt->rt6i_prefsrc.addr, &cfg->fc_prefsrc);
+		rt->rt6i_prefsrc.plen = 128;
+	} else
+		rt->rt6i_prefsrc.plen = 0;
+
 	if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
 		rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
 		if (IS_ERR(rt->rt6i_nexthop)) {
@@ -1893,6 +1907,7 @@ static void rtmsg_to_fib6_config(struct net *net,
 	ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst);
 	ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src);
 	ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway);
+	ipv6_addr_copy(&cfg->fc_prefsrc, &rtmsg->rtmsg_prefsrc);
 }
 
 int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
@@ -2037,6 +2052,39 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 	return rt;
 }
 
+/* remove deleted ip from prefsrc entries */
+struct arg_dev_net_ip {
+	struct net_device *dev;
+	struct net *net;
+	struct in6_addr *addr;
+};
+
+static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg)
+{
+	struct net_device *dev = ((struct arg_dev_net_ip *)arg)->dev;
+	struct net *net = ((struct arg_dev_net_ip *)arg)->net;
+	struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr;
+
+	if (((void *)rt->rt6i_dev == dev || dev == NULL) &&
+	    rt != net->ipv6.ip6_null_entry &&
+	    ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) {
+		/* remove prefsrc entry */
+		rt->rt6i_prefsrc.plen = 0;
+	}
+	return 0;
+}
+
+void rt6_remove_prefsrc(struct inet6_ifaddr *ifp)
+{
+	struct net *net = dev_net(ifp->idev->dev);
+	struct arg_dev_net_ip adni = {
+		.dev = ifp->idev->dev,
+		.net = net,
+		.addr = &ifp->addr,
+	};
+	fib6_clean_all(net, fib6_remove_prefsrc, 0, &adni);
+}
+
 struct arg_dev_net {
 	struct net_device *dev;
 	struct net *net;
@@ -2183,6 +2231,9 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
 		nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen);
 	}
 
+	if (tb[RTA_PREFSRC])
+		nla_memcpy(&cfg->fc_prefsrc, tb[RTA_PREFSRC], 16);
+
 	if (tb[RTA_OIF])
 		cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]);
 
@@ -2325,11 +2376,22 @@ static int rt6_fill_node(struct net *net,
 #endif
 			NLA_PUT_U32(skb, RTA_IIF, iif);
 	} else if (dst) {
-		struct inet6_dev *idev = ip6_dst_idev(&rt->dst);
 		struct in6_addr saddr_buf;
-		if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
-				       dst, 0, &saddr_buf) == 0)
+		if (rt->rt6i_prefsrc.plen) {
+			ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr);
 			NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
+		} else {
+			struct inet6_dev *idev = ip6_dst_idev(&rt->dst);
+			if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
+					       dst, 0, &saddr_buf) == 0)
+				NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
+		}
+	}
+
+	if (rt->rt6i_prefsrc.plen) {
+		struct in6_addr saddr_buf;
+		ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr);
+		NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
 	}
 
 	if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)











Daniel Walter
Software Engineer

Barracuda Networks AG
Eduard-Bodem-Gasse 1
6020 Innsbruck
Austria

Phone: +43 (0) 508 100
Fax: +43 508 100 20
eMail: mailto:DWalter@barracuda.com
Web: www.barracudanetworks.com, www.phion.com







Barracuda Networks AG
Vorsitzender des Aufsichtsrates/ Chairman of the supervisory board: Dean Drako
Vorstand/ Executive Board: Dr. Wieland Alge, Mag. Guenter Klausner
Sitz der Gesellschaft/ Registered office: 6020 Innsbruck, Austria
Handelsgericht Innsbruck Firmenbuch/ Registration Number: 184392s
UID-Nr/ VAT Number: ATU47509003

Diese Nachricht und allfaellige angehaengte Dokumente sind vertraulich und nur fuer den/die Adressaten bestimmt. Sollten Sie nicht der beabsichtigte Adressat sein, ist jede Offenlegung, Weiterleitung oder sonstige Verwendung dieser Information nicht gestattet. In diesem Fall bitten wir, den Absender zu verstaendigen und die Information zu vernichten. Fuer Uebermittlungsfehler oder sonstige Irrtuemer bei Uebermittlung besteht keine Haftung.

This message and any attached files are confidential and intended solely for the addressee(s). Any publication, transmission or other use of the information by a person or entity other than the intended addressee is prohibited. If you receive this in error please contact the sender and delete the material. The sender does not accept liability for any errors or omissions as a result of the transmission.


Barracuda Networks solutions are now available as virtual appliances. 
Visit www.barracudanetworks.com/vx for more information.




[-- Attachment #2: linux-ipv6-prefsrc-selection.patch --]
[-- Type: text/x-patch, Size: 5905 bytes --]

diff --git a/include/linux/ipv6_route.h b/include/linux/ipv6_route.h
index 1e7d8af..9845953 100644
--- a/include/linux/ipv6_route.h
+++ b/include/linux/ipv6_route.h
@@ -44,6 +44,7 @@
 struct in6_rtmsg {
 	struct in6_addr		rtmsg_dst;
 	struct in6_addr		rtmsg_src;
+	struct in6_addr		rtmsg_prefsrc;
 	struct in6_addr		rtmsg_gateway;
 	__u32			rtmsg_type;
 	__u16			rtmsg_dst_len;
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index bc3cde0..98348d5 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -42,6 +42,7 @@ struct fib6_config {
 
 	struct in6_addr	fc_dst;
 	struct in6_addr	fc_src;
+	struct in6_addr	fc_prefsrc;
 	struct in6_addr	fc_gateway;
 
 	unsigned long	fc_expires;
@@ -107,6 +108,7 @@ struct rt6_info {
 	struct rt6key			rt6i_dst ____cacheline_aligned_in_smp;
 	u32				rt6i_flags;
 	struct rt6key			rt6i_src;
+	struct rt6key			rt6i_prefsrc;
 	u32				rt6i_metric;
 	u32				rt6i_peer_genid;
 
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index c850e5f..2b37c20 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -141,6 +141,7 @@ struct rt6_rtnl_dump_arg {
 extern int rt6_dump_route(struct rt6_info *rt, void *p_arg);
 extern void rt6_ifdown(struct net *net, struct net_device *dev);
 extern void rt6_mtu_change(struct net_device *dev, unsigned mtu);
+extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp);
 
 
 /*
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 3daaf3c..26f9e14 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -825,6 +825,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
 		dst_release(&rt->dst);
 	}
 
+	/* clean up prefsrc entries */
+	rt6_remove_prefsrc(ifp);
 out:
 	in6_ifa_put(ifp);
 }
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 1820887..e2d8463 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -930,10 +930,14 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 		goto out_err_release;
 
 	if (ipv6_addr_any(&fl6->saddr)) {
-		err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
-					 &fl6->daddr,
-					 sk ? inet6_sk(sk)->srcprefs : 0,
-					 &fl6->saddr);
+		struct rt6_info *rt = (struct rt6_info *) *dst;
+		if (rt->rt6i_prefsrc.plen)
+			ipv6_addr_copy(&fl6->saddr, &rt->rt6i_prefsrc.addr);
+		else
+			err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
+						 &fl6->daddr,
+						 sk ? inet6_sk(sk)->srcprefs : 0,
+						 &fl6->saddr);
 		if (err)
 			goto out_err_release;
 	}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 843406f..b53089d 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1325,6 +1325,20 @@ int ip6_route_add(struct fib6_config *cfg)
 	if (dev == NULL)
 		goto out;
 
+	/* check if prefsrc is set */
+	if (!ipv6_addr_any(&cfg->fc_prefsrc)) {
+		struct in6_addr saddr_buf;
+		ipv6_addr_copy(&saddr_buf, &cfg->fc_prefsrc);
+		if (!ipv6_chk_addr(net, &saddr_buf, dev, 0)) {
+			printk(KERN_DEBUG "invalid pref_src\n");
+			err = -EINVAL;
+			goto out;
+		}
+		ipv6_addr_copy(&rt->rt6i_prefsrc.addr, &cfg->fc_prefsrc);
+		rt->rt6i_prefsrc.plen = 128;
+	} else
+		rt->rt6i_prefsrc.plen = 0;
+
 	if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
 		rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
 		if (IS_ERR(rt->rt6i_nexthop)) {
@@ -1893,6 +1907,7 @@ static void rtmsg_to_fib6_config(struct net *net,
 	ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst);
 	ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src);
 	ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway);
+	ipv6_addr_copy(&cfg->fc_prefsrc, &rtmsg->rtmsg_prefsrc);
 }
 
 int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
@@ -2037,6 +2052,39 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 	return rt;
 }
 
+/* remove deleted ip from prefsrc entries */
+struct arg_dev_net_ip {
+	struct net_device *dev;
+	struct net *net;
+	struct in6_addr *addr;
+};
+
+static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg)
+{
+	struct net_device *dev = ((struct arg_dev_net_ip *)arg)->dev;
+	struct net *net = ((struct arg_dev_net_ip *)arg)->net;
+	struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr;
+
+	if (((void *)rt->rt6i_dev == dev || dev == NULL) &&
+	    rt != net->ipv6.ip6_null_entry &&
+	    ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) {
+		/* remove prefsrc entry */
+		rt->rt6i_prefsrc.plen = 0;
+	}
+	return 0;
+}
+
+void rt6_remove_prefsrc(struct inet6_ifaddr *ifp)
+{
+	struct net *net = dev_net(ifp->idev->dev);
+	struct arg_dev_net_ip adni = {
+		.dev = ifp->idev->dev,
+		.net = net,
+		.addr = &ifp->addr,
+	};
+	fib6_clean_all(net, fib6_remove_prefsrc, 0, &adni);
+}
+
 struct arg_dev_net {
 	struct net_device *dev;
 	struct net *net;
@@ -2183,6 +2231,9 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
 		nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen);
 	}
 
+	if (tb[RTA_PREFSRC])
+		nla_memcpy(&cfg->fc_prefsrc, tb[RTA_PREFSRC], 16);
+
 	if (tb[RTA_OIF])
 		cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]);
 
@@ -2325,11 +2376,22 @@ static int rt6_fill_node(struct net *net,
 #endif
 			NLA_PUT_U32(skb, RTA_IIF, iif);
 	} else if (dst) {
-		struct inet6_dev *idev = ip6_dst_idev(&rt->dst);
 		struct in6_addr saddr_buf;
-		if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
-				       dst, 0, &saddr_buf) == 0)
+		if (rt->rt6i_prefsrc.plen) {
+			ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr);
 			NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
+		} else {
+			struct inet6_dev *idev = ip6_dst_idev(&rt->dst);
+			if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
+					       dst, 0, &saddr_buf) == 0)
+				NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
+		}
+	}
+
+	if (rt->rt6i_prefsrc.plen) {
+		struct in6_addr saddr_buf;
+		ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr);
+		NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
 	}
 
 	if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)

^ permalink raw reply related

* [PATCH] IPVS Bug, Null ptr in ip_vs_ctl.c ip_vs_genl_dump_daemons().
From: Hans Schillstrom @ 2011-03-30 14:36 UTC (permalink / raw)
  To: horms, ja, wensong, lvs-devel, netdev, netfilter-devel
  Cc: hans, Hans Schillstrom

ipvsadm -ln --daemon will trigger a Null pointer exception because
ip_vs_genl_dump_daemons() uses skb_net() instead of skb_sknet().

To prevent others from NULL ptr a check is made in ip_vs.h skb_net().

This patches is based on net-2.6

Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
---
 include/net/ip_vs.h            |    2 +-
 net/netfilter/ipvs/ip_vs_ctl.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 30b49ed..4d1b71a 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -52,7 +52,7 @@ static inline struct net *skb_net(const struct sk_buff *skb)
 	 */
 	if (likely(skb->dev && skb->dev->nd_net))
 		return dev_net(skb->dev);
-	if (skb_dst(skb)->dev)
+	if (skb_dst(skb) && skb_dst(skb)->dev)
 		return dev_net(skb_dst(skb)->dev);
 	WARN(skb->sk, "Maybe skb_sknet should be used in %s() at line:%d\n",
 		      __func__, __LINE__);
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 33733c8..ae47090 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3120,7 +3120,7 @@ nla_put_failure:
 static int ip_vs_genl_dump_daemons(struct sk_buff *skb,
 				   struct netlink_callback *cb)
 {
-	struct net *net = skb_net(skb);
+	struct net *net = skb_sknet(skb);
 	struct netns_ipvs *ipvs = net_ipvs(net);
 
 	mutex_lock(&__ip_vs_mutex);
-- 
1.6.0.2


^ permalink raw reply related

* Re: connector: convert to synchronous netlink message processing
From: Evgeniy Polyakov @ 2011-03-30 13:39 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Linux Netdev List
In-Reply-To: <4D90D5E8.4080002@trash.net>

Hi Patrick

On Mon, Mar 28, 2011 at 08:39:36PM +0200, Patrick McHardy (kaber@trash.net) wrote:
> This patch fixes up connector to work properly with the recent
> netlink changes that require synchronous netlink message processing.
> 
> The patch is so far only compile tested since I'm still looking
> for a good way to test it. If you could point me to some software
> using the proc events that would be appreciated.

There is test module in Documentation/connector/ and/or samples/ which I
used for tests. It was quite for a while when it was used last time
though.

Your patch looks very good and I definitely ack this :)
Thank you.

> commit 21c40e4675954b42c939334e3ed15e1bd0a4da29
> Author: Patrick McHardy <kaber@trash.net>
> Date:   Mon Mar 28 20:20:26 2011 +0200
> 
>     connector: convert to synchronous netlink message processing
>     
>     Commits 01a16b21 (netlink: kill eff_cap from struct netlink_skb_parms)
>     and c53fa1ed (netlink: kill loginuid/sessionid/sid members from struct
>     netlink_skb_parms) removed some members from struct netlink_skb_parms
>     that depend on the current context, all netlink users are now required
>     to do synchronous message processing.
>     
>     connector however queues received messages and processes them in a work
>     queue, which is not valid anymore. This patch converts connector to do
>     synchronous message processing by invoking the registered callback handler
>     directly from the netlink receive function.
>     
>     In order to avoid invoking the callback with connector locks held, a
>     reference count is added to struct cn_callback_entry, the reference
>     is taken when finding a matching callback entry on the device's queue_list
>     and released after the callback handler has been invoked.
>     
>     Signed-off-by: Patrick McHardy <kaber@trash.net>

Acked-by: Evgeniy Polyakov <zbr@ioremap.net>


-- 
	Evgeniy Polyakov

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox