diff options
author | Narender Kumar <narender.kumar@qlogic.com> | 2009-08-23 04:35:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-23 22:00:20 -0400 |
commit | 1bb482f8a46000f77577948ff1c350275bba7dc9 (patch) | |
tree | 3003df5a4414af44af0756f670531d9445bad397 | |
parent | 8fea0f0db87a4aaed41a93eed147af61cc5f9e3f (diff) |
netxen: ethtool statistics and control for LRO
Add ethtool -K knob to control LRO in firmware.
LRO path is completely separated from GRO, LRO packets
are still fed with netif_receive_skb().
Also fix ethtool statistics to include LRO packets.
Also use correct message type while configuring interrupt coalescing.
Signed-off-by: Narender Kumar <narender.kumar@qlogic.com>
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 22 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_ctx.c | 2 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_ethtool.c | 27 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 56 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 7 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 8 |
6 files changed, 114 insertions, 8 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 5abb41e2d02c..fa43aa059c43 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h | |||
@@ -576,7 +576,8 @@ struct netxen_adapter_stats { | |||
576 | u64 rxdropped; | 576 | u64 rxdropped; |
577 | u64 txdropped; | 577 | u64 txdropped; |
578 | u64 csummed; | 578 | u64 csummed; |
579 | u64 no_rcv; | 579 | u64 rx_pkts; |
580 | u64 lro_pkts; | ||
580 | u64 rxbytes; | 581 | u64 rxbytes; |
581 | u64 txbytes; | 582 | u64 txbytes; |
582 | }; | 583 | }; |
@@ -958,7 +959,8 @@ typedef struct { | |||
958 | #define NX_NIC_H2C_OPCODE_PROXY_STOP_DONE 20 | 959 | #define NX_NIC_H2C_OPCODE_PROXY_STOP_DONE 20 |
959 | #define NX_NIC_H2C_OPCODE_GET_LINKEVENT 21 | 960 | #define NX_NIC_H2C_OPCODE_GET_LINKEVENT 21 |
960 | #define NX_NIC_C2C_OPCODE 22 | 961 | #define NX_NIC_C2C_OPCODE 22 |
961 | #define NX_NIC_H2C_OPCODE_LAST 23 | 962 | #define NX_NIC_H2C_OPCODE_CONFIG_HW_LRO 24 |
963 | #define NX_NIC_H2C_OPCODE_LAST 25 | ||
962 | 964 | ||
963 | /* | 965 | /* |
964 | * Firmware --> Driver | 966 | * Firmware --> Driver |
@@ -984,6 +986,19 @@ typedef struct { | |||
984 | #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ | 986 | #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ |
985 | #define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */ | 987 | #define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */ |
986 | 988 | ||
989 | #define NX_NIC_LRO_REQUEST_FIRST 0 | ||
990 | #define NX_NIC_LRO_REQUEST_ADD_FLOW 1 | ||
991 | #define NX_NIC_LRO_REQUEST_DELETE_FLOW 2 | ||
992 | #define NX_NIC_LRO_REQUEST_TIMER 3 | ||
993 | #define NX_NIC_LRO_REQUEST_CLEANUP 4 | ||
994 | #define NX_NIC_LRO_REQUEST_ADD_FLOW_SCHEDULED 5 | ||
995 | #define NX_TOE_LRO_REQUEST_ADD_FLOW 6 | ||
996 | #define NX_TOE_LRO_REQUEST_ADD_FLOW_RESPONSE 7 | ||
997 | #define NX_TOE_LRO_REQUEST_DELETE_FLOW 8 | ||
998 | #define NX_TOE_LRO_REQUEST_DELETE_FLOW_RESPONSE 9 | ||
999 | #define NX_TOE_LRO_REQUEST_TIMER 10 | ||
1000 | #define NX_NIC_LRO_REQUEST_LAST 11 | ||
1001 | |||
987 | #define NX_FW_CAPABILITY_LINK_NOTIFICATION (1 << 5) | 1002 | #define NX_FW_CAPABILITY_LINK_NOTIFICATION (1 << 5) |
988 | #define NX_FW_CAPABILITY_SWITCHING (1 << 6) | 1003 | #define NX_FW_CAPABILITY_SWITCHING (1 << 6) |
989 | #define NX_FW_CAPABILITY_PEXQ (1 << 7) | 1004 | #define NX_FW_CAPABILITY_PEXQ (1 << 7) |
@@ -1064,6 +1079,7 @@ typedef struct { | |||
1064 | 1079 | ||
1065 | #define NETXEN_NIC_MSI_ENABLED 0x02 | 1080 | #define NETXEN_NIC_MSI_ENABLED 0x02 |
1066 | #define NETXEN_NIC_MSIX_ENABLED 0x04 | 1081 | #define NETXEN_NIC_MSIX_ENABLED 0x04 |
1082 | #define NETXEN_NIC_LRO_ENABLED 0x08 | ||
1067 | #define NETXEN_IS_MSI_FAMILY(adapter) \ | 1083 | #define NETXEN_IS_MSI_FAMILY(adapter) \ |
1068 | ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED)) | 1084 | ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED)) |
1069 | 1085 | ||
@@ -1290,6 +1306,8 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup); | |||
1290 | 1306 | ||
1291 | int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu); | 1307 | int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu); |
1292 | int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); | 1308 | int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); |
1309 | int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable); | ||
1310 | int netxen_send_lro_cleanup(struct netxen_adapter *adapter); | ||
1293 | 1311 | ||
1294 | int netxen_nic_set_mac(struct net_device *netdev, void *p); | 1312 | int netxen_nic_set_mac(struct net_device *netdev, void *p); |
1295 | struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); | 1313 | struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); |
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 412d65829d20..9e0469643d34 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c | |||
@@ -203,8 +203,6 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) | |||
203 | 203 | ||
204 | cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN); | 204 | cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN); |
205 | cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS); | 205 | cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS); |
206 | if (adapter->capabilities & NX_FW_CAPABILITY_HW_LRO) | ||
207 | cap |= NX_CAP0_HW_LRO; | ||
208 | 206 | ||
209 | prq->capabilities[0] = cpu_to_le32(cap); | 207 | prq->capabilities[0] = cpu_to_le32(cap); |
210 | prq->host_int_crb_mode = | 208 | prq->host_int_crb_mode = |
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 39a308c363c7..db66e7053b99 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c | |||
@@ -57,7 +57,8 @@ static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = { | |||
57 | {"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)}, | 57 | {"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)}, |
58 | {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)}, | 58 | {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)}, |
59 | {"csummed", NETXEN_NIC_STAT(stats.csummed)}, | 59 | {"csummed", NETXEN_NIC_STAT(stats.csummed)}, |
60 | {"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)}, | 60 | {"rx_pkts", NETXEN_NIC_STAT(stats.rx_pkts)}, |
61 | {"lro_pkts", NETXEN_NIC_STAT(stats.lro_pkts)}, | ||
61 | {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)}, | 62 | {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)}, |
62 | {"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)}, | 63 | {"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)}, |
63 | }; | 64 | }; |
@@ -941,6 +942,28 @@ static int netxen_get_intr_coalesce(struct net_device *netdev, | |||
941 | return 0; | 942 | return 0; |
942 | } | 943 | } |
943 | 944 | ||
945 | static int netxen_nic_set_flags(struct net_device *netdev, u32 data) | ||
946 | { | ||
947 | struct netxen_adapter *adapter = netdev_priv(netdev); | ||
948 | int hw_lro; | ||
949 | |||
950 | if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)) | ||
951 | return -EINVAL; | ||
952 | |||
953 | ethtool_op_set_flags(netdev, data); | ||
954 | |||
955 | hw_lro = (data & ETH_FLAG_LRO) ? NETXEN_NIC_LRO_ENABLED : 0; | ||
956 | |||
957 | if (netxen_config_hw_lro(adapter, hw_lro)) | ||
958 | return -EIO; | ||
959 | |||
960 | if ((hw_lro == 0) && netxen_send_lro_cleanup(adapter)) | ||
961 | return -EIO; | ||
962 | |||
963 | |||
964 | return 0; | ||
965 | } | ||
966 | |||
944 | struct ethtool_ops netxen_nic_ethtool_ops = { | 967 | struct ethtool_ops netxen_nic_ethtool_ops = { |
945 | .get_settings = netxen_nic_get_settings, | 968 | .get_settings = netxen_nic_get_settings, |
946 | .set_settings = netxen_nic_set_settings, | 969 | .set_settings = netxen_nic_set_settings, |
@@ -968,4 +991,6 @@ struct ethtool_ops netxen_nic_ethtool_ops = { | |||
968 | .set_rx_csum = netxen_nic_set_rx_csum, | 991 | .set_rx_csum = netxen_nic_set_rx_csum, |
969 | .get_coalesce = netxen_get_intr_coalesce, | 992 | .get_coalesce = netxen_get_intr_coalesce, |
970 | .set_coalesce = netxen_set_intr_coalesce, | 993 | .set_coalesce = netxen_set_intr_coalesce, |
994 | .get_flags = ethtool_op_get_flags, | ||
995 | .set_flags = netxen_nic_set_flags, | ||
971 | }; | 996 | }; |
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 673dcf5ea53d..965f783d39f2 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c | |||
@@ -643,7 +643,7 @@ int netxen_config_intr_coalesce(struct netxen_adapter *adapter) | |||
643 | 643 | ||
644 | memset(&req, 0, sizeof(nx_nic_req_t)); | 644 | memset(&req, 0, sizeof(nx_nic_req_t)); |
645 | 645 | ||
646 | req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23); | 646 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); |
647 | 647 | ||
648 | word = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); | 648 | word = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); |
649 | req.req_hdr = cpu_to_le64(word); | 649 | req.req_hdr = cpu_to_le64(word); |
@@ -659,6 +659,35 @@ int netxen_config_intr_coalesce(struct netxen_adapter *adapter) | |||
659 | return rv; | 659 | return rv; |
660 | } | 660 | } |
661 | 661 | ||
662 | int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable) | ||
663 | { | ||
664 | nx_nic_req_t req; | ||
665 | u64 word; | ||
666 | int rv = 0; | ||
667 | |||
668 | if ((adapter->flags & NETXEN_NIC_LRO_ENABLED) == enable) | ||
669 | return 0; | ||
670 | |||
671 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
672 | |||
673 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | ||
674 | |||
675 | word = NX_NIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16); | ||
676 | req.req_hdr = cpu_to_le64(word); | ||
677 | |||
678 | req.words[0] = cpu_to_le64(enable); | ||
679 | |||
680 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
681 | if (rv != 0) { | ||
682 | printk(KERN_ERR "ERROR. Could not send " | ||
683 | "configure hw lro request\n"); | ||
684 | } | ||
685 | |||
686 | adapter->flags ^= NETXEN_NIC_LRO_ENABLED; | ||
687 | |||
688 | return rv; | ||
689 | } | ||
690 | |||
662 | #define RSS_HASHTYPE_IP_TCP 0x3 | 691 | #define RSS_HASHTYPE_IP_TCP 0x3 |
663 | 692 | ||
664 | int netxen_config_rss(struct netxen_adapter *adapter, int enable) | 693 | int netxen_config_rss(struct netxen_adapter *adapter, int enable) |
@@ -752,6 +781,29 @@ int netxen_linkevent_request(struct netxen_adapter *adapter, int enable) | |||
752 | return rv; | 781 | return rv; |
753 | } | 782 | } |
754 | 783 | ||
784 | int netxen_send_lro_cleanup(struct netxen_adapter *adapter) | ||
785 | { | ||
786 | nx_nic_req_t req; | ||
787 | u64 word; | ||
788 | int rv; | ||
789 | |||
790 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
791 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | ||
792 | |||
793 | word = NX_NIC_H2C_OPCODE_LRO_REQUEST | | ||
794 | ((u64)adapter->portnum << 16) | | ||
795 | ((u64)NX_NIC_LRO_REQUEST_CLEANUP << 56) ; | ||
796 | |||
797 | req.req_hdr = cpu_to_le64(word); | ||
798 | |||
799 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
800 | if (rv != 0) { | ||
801 | printk(KERN_ERR "%s: could not cleanup lro flows\n", | ||
802 | adapter->netdev->name); | ||
803 | } | ||
804 | return rv; | ||
805 | } | ||
806 | |||
755 | /* | 807 | /* |
756 | * netxen_nic_change_mtu - Change the Maximum Transfer Unit | 808 | * netxen_nic_change_mtu - Change the Maximum Transfer Unit |
757 | * @returns 0 on success, negative on failure | 809 | * @returns 0 on success, negative on failure |
@@ -2066,6 +2118,8 @@ void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) | |||
2066 | 2118 | ||
2067 | if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) | 2119 | if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) |
2068 | adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1); | 2120 | adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1); |
2121 | |||
2122 | adapter->flags &= ~NETXEN_NIC_LRO_ENABLED; | ||
2069 | } | 2123 | } |
2070 | 2124 | ||
2071 | int | 2125 | int |
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index e8bdbf9fefbb..c3609e422876 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c | |||
@@ -1277,7 +1277,7 @@ netxen_process_rcv(struct netxen_adapter *adapter, | |||
1277 | 1277 | ||
1278 | napi_gro_receive(&sds_ring->napi, skb); | 1278 | napi_gro_receive(&sds_ring->napi, skb); |
1279 | 1279 | ||
1280 | adapter->stats.no_rcv++; | 1280 | adapter->stats.rx_pkts++; |
1281 | adapter->stats.rxbytes += length; | 1281 | adapter->stats.rxbytes += length; |
1282 | 1282 | ||
1283 | return buffer; | 1283 | return buffer; |
@@ -1350,8 +1350,13 @@ netxen_process_lro(struct netxen_adapter *adapter, | |||
1350 | th->psh = push; | 1350 | th->psh = push; |
1351 | th->seq = htonl(seq_number); | 1351 | th->seq = htonl(seq_number); |
1352 | 1352 | ||
1353 | length = skb->len; | ||
1354 | |||
1353 | netif_receive_skb(skb); | 1355 | netif_receive_skb(skb); |
1354 | 1356 | ||
1357 | adapter->stats.lro_pkts++; | ||
1358 | adapter->stats.rxbytes += length; | ||
1359 | |||
1355 | return buffer; | 1360 | return buffer; |
1356 | } | 1361 | } |
1357 | 1362 | ||
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 4e3fb30d66fe..de67e42a2971 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -892,6 +892,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) | |||
892 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | 892 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) |
893 | netxen_config_intr_coalesce(adapter); | 893 | netxen_config_intr_coalesce(adapter); |
894 | 894 | ||
895 | if (adapter->capabilities & NX_FW_CAPABILITY_HW_LRO) | ||
896 | netxen_config_hw_lro(adapter, NETXEN_NIC_LRO_ENABLED); | ||
897 | |||
895 | netxen_napi_enable(adapter); | 898 | netxen_napi_enable(adapter); |
896 | 899 | ||
897 | if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION) | 900 | if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION) |
@@ -1077,6 +1080,9 @@ netxen_setup_netdev(struct netxen_adapter *adapter, | |||
1077 | if (adapter->capabilities & NX_FW_CAPABILITY_FVLANTX) | 1080 | if (adapter->capabilities & NX_FW_CAPABILITY_FVLANTX) |
1078 | netdev->features |= (NETIF_F_HW_VLAN_TX); | 1081 | netdev->features |= (NETIF_F_HW_VLAN_TX); |
1079 | 1082 | ||
1083 | if (adapter->capabilities & NX_FW_CAPABILITY_HW_LRO) | ||
1084 | netdev->features |= NETIF_F_LRO; | ||
1085 | |||
1080 | netdev->irq = adapter->msix_entries[0].vector; | 1086 | netdev->irq = adapter->msix_entries[0].vector; |
1081 | 1087 | ||
1082 | err = netxen_napi_add(adapter, netdev); | 1088 | err = netxen_napi_add(adapter, netdev); |
@@ -1812,7 +1818,7 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) | |||
1812 | 1818 | ||
1813 | memset(stats, 0, sizeof(*stats)); | 1819 | memset(stats, 0, sizeof(*stats)); |
1814 | 1820 | ||
1815 | stats->rx_packets = adapter->stats.no_rcv; | 1821 | stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts; |
1816 | stats->tx_packets = adapter->stats.xmitfinished; | 1822 | stats->tx_packets = adapter->stats.xmitfinished; |
1817 | stats->rx_bytes = adapter->stats.rxbytes; | 1823 | stats->rx_bytes = adapter->stats.rxbytes; |
1818 | stats->tx_bytes = adapter->stats.txbytes; | 1824 | stats->tx_bytes = adapter->stats.txbytes; |