netxen_nic: Fix estimation of recv MSS in case of LRO
authorRajesh Borundia <rajesh.borundia@qlogic.com>
Wed, 9 May 2012 05:55:30 +0000 (05:55 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 10 May 2012 02:53:04 +0000 (22:53 -0400)
o Linux stack estimates MSS from skb->len or skb_shinfo(skb)->gso_size.
In case of LRO skb->len is aggregate of len of number of packets hence MSS
obtained using skb->len would be incorrect. Incorrect estimation of recv MSS
would lead to delayed acks in some traffic patterns (which sends two or three
packets and wait for ack and only then send remaining packets). This leads to
drop in performance. Hence we need to set gso_size to MSS obtained from firmware.

o This is fixed recently in firmware hence the MSS is obtained based on
capability. If fw is capable of sending the MSS then only driver sets the gso_size.

Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/netxen/netxen_nic.h
drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h
drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c

index 11b4922a1781b2257d839c6519ccfcf6cfb7a858..37ccbe54e62dd0dfc0e31a57fbba7e6e6952fe9a 100644 (file)
@@ -53,8 +53,8 @@
 
 #define _NETXEN_NIC_LINUX_MAJOR 4
 #define _NETXEN_NIC_LINUX_MINOR 0
-#define _NETXEN_NIC_LINUX_SUBVERSION 78
-#define NETXEN_NIC_LINUX_VERSIONID  "4.0.78"
+#define _NETXEN_NIC_LINUX_SUBVERSION 79
+#define NETXEN_NIC_LINUX_VERSIONID  "4.0.79"
 
 #define NETXEN_VERSION_CODE(a, b, c)   (((a) << 24) + ((b) << 16) + (c))
 #define _major(v)      (((v) >> 24) & 0xff)
@@ -419,6 +419,8 @@ struct rcv_desc {
        (((sts_data) >> 52) & 0x1)
 #define netxen_get_lro_sts_seq_number(sts_data)                \
        ((sts_data) & 0x0FFFFFFFF)
+#define netxen_get_lro_sts_mss(sts_data1)              \
+       ((sts_data1 >> 32) & 0x0FFFF)
 
 
 struct status_desc {
@@ -794,6 +796,7 @@ struct netxen_cmd_args {
 #define NX_CAP0_JUMBO_CONTIGUOUS       NX_CAP_BIT(0, 7)
 #define NX_CAP0_LRO_CONTIGUOUS         NX_CAP_BIT(0, 8)
 #define NX_CAP0_HW_LRO                 NX_CAP_BIT(0, 10)
+#define NX_CAP0_HW_LRO_MSS             NX_CAP_BIT(0, 21)
 
 /*
  * Context state
@@ -1073,6 +1076,8 @@ typedef struct {
 #define NX_FW_CAPABILITY_FVLANTX               (1 << 9)
 #define NX_FW_CAPABILITY_HW_LRO                        (1 << 10)
 #define NX_FW_CAPABILITY_GBE_LINK_CFG          (1 << 11)
+#define NX_FW_CAPABILITY_MORE_CAPS             (1 << 31)
+#define NX_FW_CAPABILITY_2_LRO_MAX_TCP_SEG     (1 << 2)
 
 /* module types */
 #define LINKEVENT_MODULE_NOT_PRESENT                   1
@@ -1155,6 +1160,7 @@ typedef struct {
 #define NETXEN_NIC_BRIDGE_ENABLED       0X10
 #define NETXEN_NIC_DIAG_ENABLED                0x20
 #define NETXEN_FW_RESET_OWNER           0x40
+#define NETXEN_FW_MSS_CAP              0x80
 #define NETXEN_IS_MSI_FAMILY(adapter) \
        ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED))
 
index c86ea12dbf8768ea5da2265b3cd9d257f523dfbe..7f556a84925d5677c6b87dd3e1cb72678c634243 100644 (file)
@@ -328,6 +328,9 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
        cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
        cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS);
 
+       if (adapter->flags & NETXEN_FW_MSS_CAP)
+               cap |= NX_CAP0_HW_LRO_MSS;
+
        prq->capabilities[0] = cpu_to_le32(cap);
        prq->host_int_crb_mode =
                cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED);
index a41106ba9719b414fd9bc21172473b3d55eb5383..28e076960bcb5c8400e13eb62ac8d29c7d2f0841 100644 (file)
@@ -776,6 +776,7 @@ enum {
 #define CRB_SW_INT_MASK_3              (NETXEN_NIC_REG(0x1e8))
 
 #define CRB_FW_CAPABILITIES_1          (NETXEN_CAM_RAM(0x128))
+#define CRB_FW_CAPABILITIES_2          (NETXEN_CAM_RAM(0x12c))
 #define CRB_MAC_BLOCK_START            (NETXEN_CAM_RAM(0x1c0))
 
 /*
index 718b274403511c600fb43aae956c9adf46a274e9..0d725dc91bcb701a1a91a30405f1425f5f42eef2 100644 (file)
@@ -1131,7 +1131,6 @@ netxen_validate_firmware(struct netxen_adapter *adapter)
                 _build(file_fw_ver));
                return -EINVAL;
        }
-
        val = nx_get_bios_version(adapter);
        netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios);
        if ((__force u32)val != bios) {
@@ -1661,6 +1660,9 @@ netxen_process_lro(struct netxen_adapter *adapter,
 
        length = skb->len;
 
+       if (adapter->flags & NETXEN_FW_MSS_CAP)
+               skb_shinfo(skb)->gso_size  =  netxen_get_lro_sts_mss(sts_data1);
+
        netif_receive_skb(skb);
 
        adapter->stats.lro_pkts++;
index d03619cab8dd3086cf537f878b4e30a797f5434d..342b3a79bd0fd7a6a6bde8860446c20c78595ef2 100644 (file)
@@ -1184,6 +1184,7 @@ netxen_nic_attach(struct netxen_adapter *adapter)
        int err, ring;
        struct nx_host_rds_ring *rds_ring;
        struct nx_host_tx_ring *tx_ring;
+       u32 capab2;
 
        if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
                return 0;
@@ -1192,6 +1193,13 @@ netxen_nic_attach(struct netxen_adapter *adapter)
        if (err)
                return err;
 
+       adapter->flags &= ~NETXEN_FW_MSS_CAP;
+       if (adapter->capabilities & NX_FW_CAPABILITY_MORE_CAPS) {
+               capab2 = NXRD32(adapter, CRB_FW_CAPABILITIES_2);
+               if (capab2 & NX_FW_CAPABILITY_2_LRO_MAX_TCP_SEG)
+                       adapter->flags |= NETXEN_FW_MSS_CAP;
+       }
+
        err = netxen_napi_add(adapter, netdev);
        if (err)
                return err;
@@ -1810,7 +1818,6 @@ netxen_tso_check(struct net_device *netdev,
                flags = FLAGS_VLAN_TAGGED;
 
        } else if (vlan_tx_tag_present(skb)) {
-
                flags = FLAGS_VLAN_OOB;
                vid = vlan_tx_tag_get(skb);
                netxen_set_tx_vlan_tci(first_desc, vid);