Netdev List
 help / color / mirror / Atom feed
* Re: Kernel panic nf_nat_setup_info+0x5b3/0x6e0
From: Eric Dumazet @ 2011-04-01  5:30 UTC (permalink / raw)
  To: Changli Gao
  Cc: "Oleg A. Arkhangelsky", Patrick McHardy, netfilter-devel,
	netdev, Paul E McKenney
In-Reply-To: <AANLkTinBn+dKCaHN2Hq7kOocfMsvCO8wBpOgWd3VBV3g@mail.gmail.com>

Le vendredi 01 avril 2011 à 10:02 +0800, Changli Gao a écrit :
> On Thu, Mar 31, 2011 at 10:47 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> >
> > I wonder if this is not hiding another bug.
> >
> > Adding an RCU grace period might reduce the probability window.
> 
> What bug? This one?
> 

Yes. I am saying your patch is a brown paper bag.

Real bug is elsewhere, and we must find it, not make it happen less
frequently.

Maybe its a missing barrier, and adding a full RCU grace period is a
waste (of cpu caches space, since call_rcu() fill a potential big list)

> >
> > By the time nf_conntrack_free(ct) is called, no other cpu/thread
> > could/should use ct, or ct->ext ?
> 
> nat->ct may refer it.
> 

conntrack must have a real problem of refcounting then.

Each time an object A has a reference to object B, we should increase B
refcount, so B cannot disappear.

nat->ct _cannot_ refer ct if we are freeing ct. Thats quite simple rule.

> >
> > Sure, another thread can find/pass_on ct in a lookup but should not use
> > it, since its refcount (ct_general.use) should be 0.
> >
> >
> 
> As SLAB_DESTROY_BY_RCU is used, we should validate ct->orig_tuple too.
> 
> There is another minor problem.
> 

minor or serious ?


> nf_nat_core.c:
> 
> 133         rcu_read_lock();
> 134         hlist_for_each_entry_rcu(nat, n,
> &net->ipv4.nat_bysource[h], bysourc    e) {
> 135                 ct = nat->ct;
> 136                 if (same_src(ct, tuple) && nf_ct_zone(ct) == zone) {
> 137                         /* Copy source part from reply tuple. */
> 138                         nf_ct_invert_tuplepr(result,
> 139
> &ct->tuplehash[IP_CT_DIR_REPLY].tuple    );
> 140                         result->dst = tuple->dst;
> 141
> 142                         if (in_range(result, range)) {
> 143                                 rcu_read_unlock();
> 144                                 return 1;
> 145                         }
> 146                 }
> 147         }
> 148         rcu_read_unlock();
> 
> If the ct is reused, NAT mapping will be wrong. It isn't a serious
> problem, and can't be fixed, even though we check the reference
> counter before using it, but we can't validate it with the original
> tuple.
> 

I call this a serious problem. netfilter is not a fuzzy logic.

> Maybe we can do it in this way
> 
>                 ct = nat->ct;
>                 if (!nf_ct_is_dying(ct) &&
> atomic_inc_not_zero(&ct->ct_general.use))) {
>                                if (nf_ct_ext_find(ct, NF_CT_EXT_NAT) == nat) {
>                                         /* ct is valid, do sth... */
>                                }
>                                nf_ct_put(ct);
>                 }
> 
> I think two additional atomic operations are expensive. It isn't a good idea.
> 

It depends. This is better than taking the conntrack lock.

SLAB_DESTROY_BY_RCU is not allowing for fuzzy logic. Rules are we _must_
take a reference on object after finding it, and _recheck_ validity of
the object before using it.

Another way to avoid atomic operations in find_appropriate_src() is to
use a seqcount (or seqlock), and change the seqcount every time
something is changed in ct.



--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 9/9 net-next-2.6] qlcnic: Updated version number to 5.0.16
From: Anirban Chakraborty @ 2011-04-01  4:41 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.7.4.1


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 8/9 net-next-2.6] qlcnic: Fix LRO disable
From: Anirban Chakraborty @ 2011-04-01  4:41 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.7.4.1


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-04-01  4:40 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.7.4.1


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: Removed unused interrupt coalesce data structures
From: Anirban Chakraborty @ 2011-04-01  4:38 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver


Cleaned up unused code for interrupt coalescence settings

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.7.4.1


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-04-01  4:37 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.7.4.1


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-04-01  4:36 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

Optimized code that resulted in achieving lower
CPU utilization on transmit path 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.7.4.1


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: Cleanup patch
From: Anirban Chakraborty @ 2011-04-01  4:35 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.7.4.1


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: mem free bug fix in error path
From: Anirban Chakraborty @ 2011-04-01  4:34 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

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

Fix a memory leak in error path.

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.7.4.1


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 to other function modes
From: Anirban Chakraborty @ 2011-04-01  4:32 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.7.4.1


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 fixes
From: Anirban Chakraborty @ 2011-04-01  4:31 UTC (permalink / raw)
  To: David Miller, netdev@vger.kernel.org; +Cc: Dept_NX_Linux_NIC_Driver

Please apply.

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

* [PATCH] net/bridge: Fix wrong return-no-vaule
From: namei.unix @ 2011-04-01  4:24 UTC (permalink / raw)
  To: shemminger, davem
  Cc: Liu Yuan, open list:ETHERNET BRIDGE, open list:ETHERNET BRIDGE,
	open list

From: Liu Yuan <tailai.ly@taobao.com>

In br_stp_if.c/br_stp_recalculate_bridge_id, it should return
false, which indicates that there is no change when we find
that user has chosen a value.

Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
---
 net/bridge/br_stp_if.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 5593f5a..9b61d09 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -213,7 +213,7 @@ bool br_stp_recalculate_bridge_id(struct net_bridge *br)
 
 	/* user has chosen a value so keep it */
 	if (br->flags & BR_SET_MAC_ADDR)
-		return;
+		return false;
 
 	list_for_each_entry(p, &br->port_list, list) {
 		if (addr == br_mac_zero ||
-- 
1.7.1

^ permalink raw reply related

* Re: [PATCH v3] net: Allow no-cache copy from user on transmit
From: Tom Herbert @ 2011-04-01  4:05 UTC (permalink / raw)
  To: Michał Mirosław; +Cc: davem, netdev
In-Reply-To: <AANLkTimJR+SxeoiZnyP3_vyuK7Z+w_2G2gtUp7pZGZiR@mail.gmail.com>

> BTW, the checks should take protocol into account. If, for example,
> device has NOCACHE_COPY and CSUM_IPV4, but not CSUM_IPV6, then it will
> take a hit for every IPv6 packet that needs checksumming in software.

If the HW does not do checksum for a protocol, then the checksum-copy
path is taken for packets so there should be no hit.  The logic of the
default setting is that if HW does not checksum offload, then there is
likely no benefit to turning on no cache copy; all the packets would
go through copy checksum.

> Maybe this can be taken into account when sk_route_caps are set?
>
> [...]
>> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
>> index 1a6e9eb..59b6ce9 100644
>> --- a/drivers/net/bonding/bond_main.c
>> +++ b/drivers/net/bonding/bond_main.c
>> @@ -1407,7 +1407,7 @@ static int bond_compute_features(struct bonding *bond)
>>        int i;
>>
>>        features &= ~(NETIF_F_ALL_CSUM | BOND_VLAN_FEATURES);
>> -       features |=  NETIF_F_GSO_MASK | NETIF_F_NO_CSUM;
>> +       features |=  NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_NOCACHE_COPY;
>>
>>        if (!bond->first_slave)
>>                goto done;
> [...]
>> diff --git a/net/core/dev.c b/net/core/dev.c
>> index 0b88eba..454abfd 100644
>> --- a/net/core/dev.c
>> +++ b/net/core/dev.c
>> @@ -5444,6 +5444,13 @@ int register_netdevice(struct net_device *dev)
>>                dev->features &= ~NETIF_F_GSO;
>>        }
>>
>> +       /* Turn no cache copy off if HW isn't doing checksum */
>> +       if (!(dev->features & NETIF_F_ALL_CSUM) ||
>> +           (dev->features & NETIF_F_NO_CSUM)) {
>> +               dev->wanted_features &= ~NETIF_F_NOCACHE_COPY;
>> +               dev->features &= ~NETIF_F_NOCACHE_COPY;
>> +       }
>> +
>>        /* Enable GRO and NETIF_F_HIGHDMA for vlans by default,
>>         * vlan_dev_init() will do the dev->features check, so these features
>>         * are enabled only if supported by underlying device.
>
> Why NO_CSUM is disabling NOCACHE_COPY? You combine those features in
> bonding code anyway.
>
This is likely loopback in which case no cache copy probably does not
help.  For bonding, no cache copy is only enabled when all slaves are
doing it.

> You didn't add netdev_fix_features() checks, so NOCACHE_COPY might be
> enabled via ethtool after device is registered even if driver doesn't
> support checksum offloads.
>
I don't see a reason to strictly enforce this.  It's not guaranteed
that if a driver doesn't support csum offload then no cache copy is
bad (again it's probably noop anyway because of copy-csum path).
Turning it on for loopback is a benefit if sender and receiver are in
different cache domains is good.

I do need to send another patch.  The skb_add_data function can also
use this.  I will create skb_do_copy_data_nocache and
skb_add_data_nocache to make the use of this explicit in each protocol
(TCP being the first supported).

Tom

^ permalink raw reply

* Re: [RFC PATCH] rtl8187: Fix led support for rfkill
From: wu zhangjin @ 2011-04-01  3:12 UTC (permalink / raw)
  To: Herton Ronaldo Krzesinski
  Cc: Larry Finger, Hin-Tak Leung, Herton Ronaldo Krzesinski,
	linux-wireless, netdev, Roman Mamedov
In-Reply-To: <20110331171902.GA4010@herton-IdeaPad-Y430>

On 4/1/11, Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com> wrote:
> On Fri, Apr 01, 2011 at 12:22:51AM +0800, wu zhangjin wrote:
>> On Mon, Mar 28, 2011 at 11:40 PM, Herton Ronaldo Krzesinski
>> <herton.krzesinski@canonical.com> wrote:
>> [...]
>> >>
>> >> My rtl8187 devices are both external USB sticks, thus they have no
>> >> interaction with a radio-kill switch. I will test your patch to make
>> >> sure it does no harm to my system.
>> >>
>> >> I think the commit message should be revised. A simple statement
>> >> like "the LED does not turn off when the rfkill switch is off"
>> >> should be sufficient.
>> >
>> > The patch should work, but I wonder if we should be fiddling with
>> > priv->vif
>> > for this, perhaps we should not assume vif to be valid after
>> > rtl8187_remove_interface (I don't see problems with current
>> > rtl8187/mac80211 code on a quick look, but...)
>> >
>>
>> Yes, but seems only two places have touched the vif pointer.
>>
>> $ grep "vif =" -ur drivers/net/wireless/rtl818x/rtl8187/
>> drivers/net/wireless/rtl818x/rtl8187/dev.c:	priv->vif = NULL;
>> drivers/net/wireless/rtl818x/rtl8187/dev.c:	priv->vif = vif;
>>
>> > I cleaner solution may be to use a priv->mode like p54.
>>
>> Yep, then, we may need to add a 'mode' member to rtl8187_priv and
>> update it properly like p54.
>>
>> So, What do you prefer? I will prepare a new patch asap.
>
> In the led code we dereference priv->vif, checking for priv->vif->type.
> vif is a pointer from mac80211, and after rtl8187_remove_interface is
> called by it, at least from my POV can do anything it wants with vif,
> like freeing the sdata vif points to. From what I checked, it doesn't
> free currently and your patch don't have issues, but may be it's better
> to be safe and add a new "future proof" mode field.
>
> And as your bug shows, the led code access priv->vif after
> rtl8187_remove_interface, so we hit the case where vif could be
> considered invalid.
>
> So because of this and being cleaner I would go adding 'mode'.

Ok, thanks ;-)

Best Regards,
Wu Zhangjin

>
>>
>> Best Regards,
>> Wu Zhangjin
>>
>> >
>> >>
>> >> Larry
>> >>
>> >
>> > --
>> > []'s
>> > Herton
>> >
>>
>
> --
> []'s
> Herton
>

^ permalink raw reply

* Re: [PATCH net-next-2.6 v1] sctp: Add Auto-ASCONF support
From: Michio Honda @ 2011-04-01  2:41 UTC (permalink / raw)
  To: Wei Yongjun; +Cc: netdev, lksctp-developers
In-Reply-To: <4D95299C.6020507@cn.fujitsu.com>


On Apr 1, 2011, at 10:25 , Wei Yongjun wrote:

> 
>> Hi, 
>> 
>> Thanks for your comments.  
>> I would like to discuss some of them in-line before resubmission.  
>> 
>> Cheers,
>> - Michio
>> 
>> On Mar 31, 2011, at 15:45 , Wei Yongjun wrote:
>> 
>>> Hi Michio Honda
>>> 
>>> I try to understand what you are doing now, and some comments inline.
>>> 
>>> And
>>> 
>>> this patch is too big for review, you'd better to split it to a patchset:
>>> the improve on orig asconf code, the auto-asconf support, the socket
>>> option etc.
>>> 
>>>> @@ -599,6 +597,28 @@ static int sctp_send_asconf_add_ip(struct sock		*sk,
>>>> 						    SCTP_ADDR_NEW, GFP_ATOMIC);
>>>> 			addr_buf += af->sockaddr_len;
>>>> 		}
>>>> +		list_for_each_entry(trans, &asoc->peer.transport_addr_list,
>>>> +		    transports) {
>>>> +			if (asoc->asconf_addr_del_pending != NULL)
>>>> +				/* This ADDIP ASCONF piggybacks DELIP for the
>>>> +				 * last address, so need to select src addr
>>>> +				 * from the out_of_asoc addrs
>>>> +				 */
>>>> +				asoc->src_out_of_asoc_ok = 1;
>>>> +			/* Clear the source and route cache in the path */
>>>> +			memset(&trans->saddr, 0, sizeof(union sctp_addr));
>>>> +			dst_release(trans->dst);
>>>> +			trans->cwnd = min(4*asoc->pathmtu, max_t(__u32,
>>>> +			    2*asoc->pathmtu, 4380));
>>>> +			trans->ssthresh = asoc->peer.i.a_rwnd;
>>>> +			trans->rto = asoc->rto_initial;
>>>> +			trans->rtt = 0;
>>>> +			trans->srtt = 0;
>>>> +			trans->rttvar = 0;
>>>> +			sctp_transport_route(trans, NULL,
>>>> +			    sctp_sk(asoc->base.sk));
>>>> +		}
>>>> +		retval = sctp_send_asconf(asoc, chunk);
>>> We need to do this really?
>> We have to reset path information before transmitting ASCONF from the new source address.  
>> Because when we obviously change the source address (i.e., deletion of the last local address), we don't know any information of the path (e.g., RTT) between the new source address and the existing destination address.  
> 
> Do you means we deleted all of the local address? This is prohibit
> by rfc5061. If we have other address, we can use it.
> 
>   F5)  An endpoint MUST NOT delete its last remaining IP address from
>        an association.  In other words, if an endpoint is NOT multi-
>        homed, it MUST NOT use the delete IP address without an Add IP
>        Address preceding the delete parameter in the ASCONF Chunk.  Or,
>        if an endpoint sends multiple requests to delete IP addresses,
>        it MUST NOT delete all of the IP addresses that the peer has
>        listed for the requester.
> 
> 
> But the rfc does not said what we should do if all of the local addresses
> are invalid.
Sorry for my bad description, I mean, suppose the host having one local IP address changes the IP address to new one.   
The host will remove the old address, and configure the new IP address.  
Then, I believe following steps in SCTP implementation could make sense.  
1. When the host removes the local address, SCTP implementation postpones to remove the local address from the association, because it is the last local address in the association.    
2. After the configuration of the new IP address, the SCTP implementation tries to send an ASCONF with ADD_IP_ADDRESS from the newly configured address.  This address can be used for ASCONF while it cannot be used for the other chunks.  This ASCONF also contains DELETE_IP_ADDRESS for the old address.  (This is allowed as Sec.5.3 F5 describes)
Then, the path where the ASCONF goes is obviously new path because of the new source address, thus we should reset old path parameters, otherwise the SCTP implementation might set wrong RTO and estimate wrong RTT for that ASCONF.    


> 
> 
>>>> @@ -3341,6 +3587,44 @@ static int sctp_setsockopt_del_key(struct sock *sk,
>>>> 
>>>> +static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
>>>> +					unsigned int optlen)
>>>> +{
>>>> +	int val;
>>>> +	struct sctp_ep_common *epb;
>>>> +
>>>> +	if (optlen < sizeof(int))
>>>> +		return -EINVAL;
>>>> +	if (get_user(val, (int __user *)optval))
>>>> +		return -EFAULT;
>>>> +	if (!sctp_is_ep_boundall(sk) && val)
>>>> +		return -EINVAL;
>>>> +	list_for_each_entry(epb, &sctp_auto_asconf_eplist, auto_asconf_list) {
>>>> +		if (epb->sk == sk) {
>>>> +			if (val == 0)
>>>> +				list_del(&epb->auto_asconf_list);
>>>> +			return 0;
>>>> +		}
>>>> +	}
>>>> +	if (val)
>>>> +		list_add_tail(&sctp_sk(sk)->ep->base.auto_asconf_list,
>>>> +		    &sctp_auto_asconf_eplist);
>>>> +	return 0;
>>>> +}
>>> The sctp_setsockopt_auto_asconf is not correct, if we enable this option
>>> twice, the list will be broken.
>> Oops, I fix, thanks!
>>> We'd better to introcude a auto_asconf flag to ep, and then, we do not
>>> need to scanf the asconf_list.
>>> If auto_asconf flag is true, it is exists in the list, otherwise, not.
>> Agreed, it's more simple.   
>>> All of the sctp sockets are added to sctp_auto_asconf_eplist.
>>> I think none of the sockets should exists in this list by default,
>>> only after we enable AUTO_ASCONF, we should add it to this list.
>> Sockets are added to auto_asconf_eplist only when the sysctl parameter is on.   
> 
> If so, the SCTP_AUTO_ASCONF will be broken.
> 
> I think before SCTP_AUTO_ASCONF be document, the sysctl parameter
> is used to enable/disable the auto asconf, but after SCTP_AUTO_ASCONF
> defined, sysctl parameter should be deprecated.
Mmm, not sure, we should ask Randy and Michael.  I'll send separate email soon.  
> 
>>> Is the sysctl parameter necessary, since auto_asconf is disabled
>>> by default, and we need to set the option to enabled it.
>> I believe auto_asconf should be enabled by both of sysctl and setsockopt as well as FreeBSD implementation does.  
>> Adopting the same methods could be helpful for applications concerning auto_asconf availability.  
>> I agree to set the sysctl parameter to 0 by default.    
>> 
>>> 
>>> 
>> 
>> 


^ permalink raw reply

* Re: Kernel panic nf_nat_setup_info+0x5b3/0x6e0
From: Changli Gao @ 2011-04-01  2:02 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: "Oleg A. Arkhangelsky", Patrick McHardy, netfilter-devel,
	netdev, Paul E McKenney
In-Reply-To: <1301582872.3169.44.camel@edumazet-laptop>

On Thu, Mar 31, 2011 at 10:47 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>
> I wonder if this is not hiding another bug.
>
> Adding an RCU grace period might reduce the probability window.

What bug? This one?

>
> By the time nf_conntrack_free(ct) is called, no other cpu/thread
> could/should use ct, or ct->ext ?

nat->ct may refer it.

>
> Sure, another thread can find/pass_on ct in a lookup but should not use
> it, since its refcount (ct_general.use) should be 0.
>
>

As SLAB_DESTROY_BY_RCU is used, we should validate ct->orig_tuple too.

There is another minor problem.

nf_nat_core.c:

133         rcu_read_lock();
134         hlist_for_each_entry_rcu(nat, n,
&net->ipv4.nat_bysource[h], bysourc    e) {
135                 ct = nat->ct;
136                 if (same_src(ct, tuple) && nf_ct_zone(ct) == zone) {
137                         /* Copy source part from reply tuple. */
138                         nf_ct_invert_tuplepr(result,
139
&ct->tuplehash[IP_CT_DIR_REPLY].tuple    );
140                         result->dst = tuple->dst;
141
142                         if (in_range(result, range)) {
143                                 rcu_read_unlock();
144                                 return 1;
145                         }
146                 }
147         }
148         rcu_read_unlock();

If the ct is reused, NAT mapping will be wrong. It isn't a serious
problem, and can't be fixed, even though we check the reference
counter before using it, but we can't validate it with the original
tuple.

Maybe we can do it in this way

                ct = nat->ct;
                if (!nf_ct_is_dying(ct) &&
atomic_inc_not_zero(&ct->ct_general.use))) {
                               if (nf_ct_ext_find(ct, NF_CT_EXT_NAT) == nat) {
                                        /* ct is valid, do sth... */
                               }
                               nf_ct_put(ct);
                }

I think two additional atomic operations are expensive. It isn't a good idea.

-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* Re: appletalk oops.
From: David Miller @ 2011-04-01  1:58 UTC (permalink / raw)
  To: davej; +Cc: netdev, arnd
In-Reply-To: <20110331200525.GA17516@redhat.com>

From: Dave Jones <davej@redhat.com>
Date: Thu, 31 Mar 2011 16:05:26 -0400

> Just hit this on current git head while fuzzing syscalls.
> I suspect we need to check somewhere for null sock's being passed in from userspace
> I'm not sure yet this is appletalk specific, or it belongs somewhere further up
> in accept.

Turns out atalk_release() is completely awesome after the
lock_kernel() conversion.

It grabs a reference to a socket, then checks if that socket is NULL,
right afterwards!

And this NULL socket case is exactly what happens if you try to do an
accept() on an Appletalk socket, since it hooks up sock_no_accept().

This is the second regression in this function due to commit
60d9f461a20ba59219fdcdc30cbf8e3a4ad3f625 ("appletalk: remove the
BKL"):

--------------------
appletalk: Fix OOPS in atalk_release().

Commit 60d9f461a20ba59219fdcdc30cbf8e3a4ad3f625 ("appletalk: remove
the BKL") added a dereference of "sk" before checking for NULL in
atalk_release().

Guard the code block completely, rather than partially, with the
NULL check.

Reported-by: Dave Jones <davej@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 206e771..956a530 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1051,16 +1051,17 @@ static int atalk_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
 
-	sock_hold(sk);
-	lock_sock(sk);
 	if (sk) {
+		sock_hold(sk);
+		lock_sock(sk);
+
 		sock_orphan(sk);
 		sock->sk = NULL;
 		atalk_destroy_socket(sk);
-	}
-	release_sock(sk);
-	sock_put(sk);
 
+		release_sock(sk);
+		sock_put(sk);
+	}
 	return 0;
 }
 

^ permalink raw reply related

* Re: [PATCH net-next-2.6 v1] sctp: Add Auto-ASCONF support
From: Wei Yongjun @ 2011-04-01  1:25 UTC (permalink / raw)
  To: Michio Honda; +Cc: netdev, lksctp-developers
In-Reply-To: <5A16054A-EC79-4157-89E4-DC3BEE4124B4@sfc.wide.ad.jp>


> Hi, 
>
> Thanks for your comments.  
> I would like to discuss some of them in-line before resubmission.  
>
> Cheers,
> - Michio
>
> On Mar 31, 2011, at 15:45 , Wei Yongjun wrote:
>
>> Hi Michio Honda
>>
>> I try to understand what you are doing now, and some comments inline.
>>
>> And
>>
>> this patch is too big for review, you'd better to split it to a patchset:
>> the improve on orig asconf code, the auto-asconf support, the socket
>> option etc.
>>
>>> @@ -599,6 +597,28 @@ static int sctp_send_asconf_add_ip(struct sock		*sk,
>>> 						    SCTP_ADDR_NEW, GFP_ATOMIC);
>>> 			addr_buf += af->sockaddr_len;
>>> 		}
>>> +		list_for_each_entry(trans, &asoc->peer.transport_addr_list,
>>> +		    transports) {
>>> +			if (asoc->asconf_addr_del_pending != NULL)
>>> +				/* This ADDIP ASCONF piggybacks DELIP for the
>>> +				 * last address, so need to select src addr
>>> +				 * from the out_of_asoc addrs
>>> +				 */
>>> +				asoc->src_out_of_asoc_ok = 1;
>>> +			/* Clear the source and route cache in the path */
>>> +			memset(&trans->saddr, 0, sizeof(union sctp_addr));
>>> +			dst_release(trans->dst);
>>> +			trans->cwnd = min(4*asoc->pathmtu, max_t(__u32,
>>> +			    2*asoc->pathmtu, 4380));
>>> +			trans->ssthresh = asoc->peer.i.a_rwnd;
>>> +			trans->rto = asoc->rto_initial;
>>> +			trans->rtt = 0;
>>> +			trans->srtt = 0;
>>> +			trans->rttvar = 0;
>>> +			sctp_transport_route(trans, NULL,
>>> +			    sctp_sk(asoc->base.sk));
>>> +		}
>>> +		retval = sctp_send_asconf(asoc, chunk);
>> We need to do this really?
> We have to reset path information before transmitting ASCONF from the new source address.  
> Because when we obviously change the source address (i.e., deletion of the last local address), we don't know any information of the path (e.g., RTT) between the new source address and the existing destination address.  

Do you means we deleted all of the local address? This is prohibit
by rfc5061. If we have other address, we can use it.

   F5)  An endpoint MUST NOT delete its last remaining IP address from
        an association.  In other words, if an endpoint is NOT multi-
        homed, it MUST NOT use the delete IP address without an Add IP
        Address preceding the delete parameter in the ASCONF Chunk.  Or,
        if an endpoint sends multiple requests to delete IP addresses,
        it MUST NOT delete all of the IP addresses that the peer has
        listed for the requester.


But the rfc does not said what we should do if all of the local addresses
are invalid.


>>> @@ -3341,6 +3587,44 @@ static int sctp_setsockopt_del_key(struct sock *sk,
>>>
>>> +static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
>>> +					unsigned int optlen)
>>> +{
>>> +	int val;
>>> +	struct sctp_ep_common *epb;
>>> +
>>> +	if (optlen < sizeof(int))
>>> +		return -EINVAL;
>>> +	if (get_user(val, (int __user *)optval))
>>> +		return -EFAULT;
>>> +	if (!sctp_is_ep_boundall(sk) && val)
>>> +		return -EINVAL;
>>> +	list_for_each_entry(epb, &sctp_auto_asconf_eplist, auto_asconf_list) {
>>> +		if (epb->sk == sk) {
>>> +			if (val == 0)
>>> +				list_del(&epb->auto_asconf_list);
>>> +			return 0;
>>> +		}
>>> +	}
>>> +	if (val)
>>> +		list_add_tail(&sctp_sk(sk)->ep->base.auto_asconf_list,
>>> +		    &sctp_auto_asconf_eplist);
>>> +	return 0;
>>> +}
>> The sctp_setsockopt_auto_asconf is not correct, if we enable this option
>> twice, the list will be broken.
> Oops, I fix, thanks!
>> We'd better to introcude a auto_asconf flag to ep, and then, we do not
>> need to scanf the asconf_list.
>> If auto_asconf flag is true, it is exists in the list, otherwise, not.
> Agreed, it's more simple.   
>> All of the sctp sockets are added to sctp_auto_asconf_eplist.
>> I think none of the sockets should exists in this list by default,
>> only after we enable AUTO_ASCONF, we should add it to this list.
> Sockets are added to auto_asconf_eplist only when the sysctl parameter is on.   

If so, the SCTP_AUTO_ASCONF will be broken.

I think before SCTP_AUTO_ASCONF be document, the sysctl parameter
is used to enable/disable the auto asconf, but after SCTP_AUTO_ASCONF
defined, sysctl parameter should be deprecated.

>> Is the sysctl parameter necessary, since auto_asconf is disabled
>> by default, and we need to set the option to enabled it.
> I believe auto_asconf should be enabled by both of sysctl and setsockopt as well as FreeBSD implementation does.  
> Adopting the same methods could be helpful for applications concerning auto_asconf availability.  
> I agree to set the sysctl parameter to 0 by default.    
>
>>
>>
>
>

^ permalink raw reply

* [PATCH 7/7] ipv4: Use flowi4_init_output() in udp_sendmsg()
From: David Miller @ 2011-04-01  0:13 UTC (permalink / raw)
  To: netdev


Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/ipv4/udp.c |   18 ++++++------------
 1 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 588f47a..ac66132 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -909,20 +909,14 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		rt = (struct rtable *)sk_dst_check(sk, 0);
 
 	if (rt == NULL) {
-		struct flowi4 fl4 = {
-			.flowi4_oif = ipc.oif,
-			.flowi4_mark = sk->sk_mark,
-			.daddr = faddr,
-			.saddr = saddr,
-			.flowi4_tos = tos,
-			.flowi4_proto = sk->sk_protocol,
-			.flowi4_flags = (inet_sk_flowi_flags(sk) |
-					 FLOWI_FLAG_CAN_SLEEP),
-			.fl4_sport = inet->inet_sport,
-			.fl4_dport = dport,
-		};
+		struct flowi4 fl4;
 		struct net *net = sock_net(sk);
 
+		flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
+				   RT_SCOPE_UNIVERSE, sk->sk_protocol,
+				   inet_sk_flowi_flags(sk)|FLOWI_FLAG_CAN_SLEEP,
+				   faddr, saddr, dport, inet->inet_sport);
+
 		security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
 		rt = ip_route_output_flow(net, &fl4, sk);
 		if (IS_ERR(rt)) {
-- 
1.7.4.2


^ permalink raw reply related

* [PATCH 6/7] ipv4: Use flowi4_init_output() in cookie_v4_check()
From: David Miller @ 2011-04-01  0:12 UTC (permalink / raw)
  To: netdev


Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/ipv4/syncookies.c |   18 +++++++-----------
 1 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 8b44c6d..71e0296 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -345,17 +345,13 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 	 * no easy way to do this.
 	 */
 	{
-		struct flowi4 fl4 = {
-			.flowi4_mark = sk->sk_mark,
-			.daddr = ((opt && opt->srr) ?
-				  opt->faddr : ireq->rmt_addr),
-			.saddr = ireq->loc_addr,
-			.flowi4_tos = RT_CONN_FLAGS(sk),
-			.flowi4_proto = IPPROTO_TCP,
-			.flowi4_flags = inet_sk_flowi_flags(sk),
-			.fl4_sport = th->dest,
-			.fl4_dport = th->source,
-		};
+		struct flowi4 fl4;
+
+		flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk),
+				   RT_SCOPE_UNIVERSE, IPPROTO_TCP,
+				   inet_sk_flowi_flags(sk),
+				   (opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
+				   ireq->loc_addr, th->source, th->dest);
 		security_req_classify_flow(req, flowi4_to_flowi(&fl4));
 		rt = ip_route_output_key(sock_net(sk), &fl4);
 		if (IS_ERR(rt)) {
-- 
1.7.4.2


^ permalink raw reply related

* [PATCH 5/7] ipv4: Use flowi4_init_output() in raw_sendmsg()
From: David Miller @ 2011-04-01  0:12 UTC (permalink / raw)
  To: netdev


Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/ipv4/raw.c |   18 +++++++-----------
 1 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 2d3c72e..7d32d9d 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -548,17 +548,13 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 	}
 
 	{
-		struct flowi4 fl4 = {
-			.flowi4_oif = ipc.oif,
-			.flowi4_mark = sk->sk_mark,
-			.daddr = daddr,
-			.saddr = saddr,
-			.flowi4_tos = tos,
-			.flowi4_proto = (inet->hdrincl ?
-					 IPPROTO_RAW :
-					 sk->sk_protocol),
-			.flowi4_flags = FLOWI_FLAG_CAN_SLEEP,
-		};
+		struct flowi4 fl4;
+
+		flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
+				   RT_SCOPE_UNIVERSE,
+				   inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
+				   FLOWI_FLAG_CAN_SLEEP, daddr, saddr, 0, 0);
+
 		if (!inet->hdrincl) {
 			err = raw_probe_proto_opt(&fl4, msg);
 			if (err)
-- 
1.7.4.2


^ permalink raw reply related

* [PATCH 4/7] ipv4: Use flowi4_init_output() in ip_send_reply()
From: David Miller @ 2011-04-01  0:12 UTC (permalink / raw)
  To: netdev


Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/ipv4/ip_output.c |   18 ++++++++----------
 1 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 67f241b..86a2843 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1474,16 +1474,14 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
 	}
 
 	{
-		struct flowi4 fl4 = {
-			.flowi4_oif = arg->bound_dev_if,
-			.daddr = daddr,
-			.saddr = rt->rt_spec_dst,
-			.flowi4_tos = RT_TOS(ip_hdr(skb)->tos),
-			.fl4_sport = tcp_hdr(skb)->dest,
-			.fl4_dport = tcp_hdr(skb)->source,
-			.flowi4_proto = sk->sk_protocol,
-			.flowi4_flags = ip_reply_arg_flowi_flags(arg),
-		};
+		struct flowi4 fl4;
+
+		flowi4_init_output(&fl4, arg->bound_dev_if, 0,
+				   RT_TOS(ip_hdr(skb)->tos),
+				   RT_SCOPE_UNIVERSE, sk->sk_protocol,
+				   ip_reply_arg_flowi_flags(arg),
+				   daddr, rt->rt_spec_dst,
+				   tcp_hdr(skb)->source, tcp_hdr(skb)->dest);
 		security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
 		rt = ip_route_output_key(sock_net(sk), &fl4);
 		if (IS_ERR(rt))
-- 
1.7.4.2


^ permalink raw reply related

* [PATCH 3/7] ipv4: Use flowi4_init_output() in inet_connection_sock.c
From: David Miller @ 2011-04-01  0:12 UTC (permalink / raw)
  To: netdev


Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/ipv4/inet_connection_sock.c |   18 ++++++------------
 1 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 6c0b7f4..f784608 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -356,20 +356,14 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,
 	struct rtable *rt;
 	const struct inet_request_sock *ireq = inet_rsk(req);
 	struct ip_options *opt = inet_rsk(req)->opt;
-	struct flowi4 fl4 = {
-		.flowi4_oif = sk->sk_bound_dev_if,
-		.flowi4_mark = sk->sk_mark,
-		.daddr = ((opt && opt->srr) ?
-			  opt->faddr : ireq->rmt_addr),
-		.saddr = ireq->loc_addr,
-		.flowi4_tos = RT_CONN_FLAGS(sk),
-		.flowi4_proto = sk->sk_protocol,
-		.flowi4_flags = inet_sk_flowi_flags(sk),
-		.fl4_sport = inet_sk(sk)->inet_sport,
-		.fl4_dport = ireq->rmt_port,
-	};
 	struct net *net = sock_net(sk);
+	struct flowi4 fl4;
 
+	flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark,
+			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
+			   sk->sk_protocol, inet_sk_flowi_flags(sk),
+			   (opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
+			   ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport);
 	security_req_classify_flow(req, flowi4_to_flowi(&fl4));
 	rt = ip_route_output_flow(net, &fl4, sk);
 	if (IS_ERR(rt))
-- 
1.7.4.2


^ permalink raw reply related

* [PATCH 2/7] ipv4: Use flowi4_init_output() in net/route.h
From: David Miller @ 2011-04-01  0:12 UTC (permalink / raw)
  To: netdev


Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/route.h |   60 ++++++++++++++++++++------------------------------
 1 files changed, 24 insertions(+), 36 deletions(-)

diff --git a/include/net/route.h b/include/net/route.h
index f88429c..b242885 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -149,17 +149,12 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct sock
 						   __be16 dport, __be16 sport,
 						   __u8 proto, __u8 tos, int oif)
 {
-	struct flowi4 fl4 = {
-		.flowi4_oif = oif,
-		.flowi4_flags = sk ? inet_sk_flowi_flags(sk) : 0,
-		.flowi4_mark = sk ? sk->sk_mark : 0,
-		.daddr = daddr,
-		.saddr = saddr,
-		.flowi4_tos = tos,
-		.flowi4_proto = proto,
-		.fl4_dport = dport,
-		.fl4_sport = sport,
-	};
+	struct flowi4 fl4;
+
+	flowi4_init_output(&fl4, oif, sk ? sk->sk_mark : 0, tos,
+			   RT_SCOPE_UNIVERSE, proto,
+			   sk ? inet_sk_flowi_flags(sk) : 0,
+			   daddr, saddr, dport, sport);
 	if (sk)
 		security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
 	return ip_route_output_flow(net, &fl4, sk);
@@ -229,25 +224,21 @@ static inline struct rtable *ip_route_connect(__be32 dst, __be32 src, u32 tos,
 					      __be16 sport, __be16 dport,
 					      struct sock *sk, bool can_sleep)
 {
-	struct flowi4 fl4 = {
-		.flowi4_oif = oif,
-		.flowi4_mark = sk->sk_mark,
-		.daddr = dst,
-		.saddr = src,
-		.flowi4_tos = tos,
-		.flowi4_proto = protocol,
-		.fl4_sport = sport,
-		.fl4_dport = dport,
-	};
 	struct net *net = sock_net(sk);
 	struct rtable *rt;
+	struct flowi4 fl4;
+	__u8 flow_flags;
 
+	flow_flags = 0;
 	if (inet_sk(sk)->transparent)
-		fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+		flow_flags |= FLOWI_FLAG_ANYSRC;
 	if (protocol == IPPROTO_TCP)
-		fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS;
+		flow_flags |= FLOWI_FLAG_PRECOW_METRICS;
 	if (can_sleep)
-		fl4.flowi4_flags |= FLOWI_FLAG_CAN_SLEEP;
+		flow_flags |= FLOWI_FLAG_CAN_SLEEP;
+
+	flowi4_init_output(&fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
+			   protocol, flow_flags, dst, src, dport, sport);
 
 	if (!dst || !src) {
 		rt = __ip_route_output_key(net, &fl4);
@@ -267,20 +258,17 @@ static inline struct rtable *ip_route_newports(struct rtable *rt,
 					       __be16 dport, struct sock *sk)
 {
 	if (sport != orig_sport || dport != orig_dport) {
-		struct flowi4 fl4 = {
-			.flowi4_oif = rt->rt_oif,
-			.flowi4_mark = rt->rt_mark,
-			.daddr = rt->rt_dst,
-			.saddr = rt->rt_src,
-			.flowi4_tos = rt->rt_tos,
-			.flowi4_proto = protocol,
-			.fl4_sport = sport,
-			.fl4_dport = dport
-		};
+		struct flowi4 fl4;
+		__u8 flow_flags;
+
+		flow_flags = 0;
 		if (inet_sk(sk)->transparent)
-			fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+			flow_flags |= FLOWI_FLAG_ANYSRC;
 		if (protocol == IPPROTO_TCP)
-			fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS;
+			flow_flags |= FLOWI_FLAG_PRECOW_METRICS;
+		flowi4_init_output(&fl4, rt->rt_oif, rt->rt_mark, rt->rt_tos,
+				   RT_SCOPE_UNIVERSE, protocol, flow_flags,
+				   rt->rt_dst, rt->rt_src, dport, sport);
 		ip_rt_put(rt);
 		security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
 		return ip_route_output_flow(sock_net(sk), &fl4, sk);
-- 
1.7.4.2


^ permalink raw reply related

* [PATCH 1/7] net: Add helper flowi4_init_output().
From: David Miller @ 2011-04-01  0:12 UTC (permalink / raw)
  To: netdev


On-stack initialization via assignment of flow structures are
expensive because GCC emits a memset() to clear the entire
structure out no matter what.

Add a helper for ipv4 output flow key setup which we can use to avoid
the memset.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/flow.h |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/include/net/flow.h b/include/net/flow.h
index 7fe5a0f..37e77d6 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -70,6 +70,27 @@ struct flowi4 {
 #define fl4_gre_key		uli.gre_key
 };
 
+static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
+				      __u32 mark, __u8 tos, __u8 scope,
+				      __u8 proto, __u8 flags,
+				      __be32 daddr, __be32 saddr,
+				      __be16 dport, __be32 sport)
+{
+	fl4->flowi4_oif = oif;
+	fl4->flowi4_iif = 0;
+	fl4->flowi4_mark = mark;
+	fl4->flowi4_tos = tos;
+	fl4->flowi4_scope = scope;
+	fl4->flowi4_proto = proto;
+	fl4->flowi4_flags = flags;
+	fl4->flowi4_secid = 0;
+	fl4->daddr = daddr;
+	fl4->saddr = saddr;
+	fl4->fl4_sport = sport;
+	fl4->fl4_dport = dport;
+}
+				      
+
 struct flowi6 {
 	struct flowi_common	__fl_common;
 #define flowi6_oif		__fl_common.flowic_oif
-- 
1.7.4.2


^ permalink raw reply related


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