aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen
diff options
context:
space:
mode:
authorDhananjay Phadke <dhananjay@netxen.com>2008-07-21 22:44:09 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-07-22 17:52:54 -0400
commitcd1f8160e015cd1538701b7de216cbeaefc6b0a8 (patch)
treeda264cfcbca7c5cc2989349a4536021204aa5c46 /drivers/net/netxen
parentd9e651bc06690c5a5326e8d019fa7668409bc819 (diff)
netxen: enable tso6, intr coalescing.
Enable tso6 and ipv6 checksum, interrupt coalescing for NX3031. Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/netxen')
-rw-r--r--drivers/net/netxen/netxen_nic.h40
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c116
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c47
-rw-r--r--drivers/net/netxen/netxen_nic_main.c38
4 files changed, 213 insertions, 28 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 705fdf10f95d..bcc551ef8519 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -1133,6 +1133,40 @@ typedef struct nx_mac_list_s {
1133 uint8_t mac_addr[MAX_ADDR_LEN]; 1133 uint8_t mac_addr[MAX_ADDR_LEN];
1134} nx_mac_list_t; 1134} nx_mac_list_t;
1135 1135
1136/*
1137 * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is
1138 * adjusted based on configured MTU.
1139 */
1140#define NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US 3
1141#define NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS 256
1142#define NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS 64
1143#define NETXEN_DEFAULT_INTR_COALESCE_TX_TIME_US 4
1144
1145#define NETXEN_NIC_INTR_DEFAULT 0x04
1146
1147typedef union {
1148 struct {
1149 uint16_t rx_packets;
1150 uint16_t rx_time_us;
1151 uint16_t tx_packets;
1152 uint16_t tx_time_us;
1153 } data;
1154 uint64_t word;
1155} nx_nic_intr_coalesce_data_t;
1156
1157typedef struct {
1158 uint16_t stats_time_us;
1159 uint16_t rate_sample_time;
1160 uint16_t flags;
1161 uint16_t rsvd_1;
1162 uint32_t low_threshold;
1163 uint32_t high_threshold;
1164 nx_nic_intr_coalesce_data_t normal;
1165 nx_nic_intr_coalesce_data_t low;
1166 nx_nic_intr_coalesce_data_t high;
1167 nx_nic_intr_coalesce_data_t irq;
1168} nx_nic_intr_coalesce_t;
1169
1136typedef struct { 1170typedef struct {
1137 u64 qhdr; 1171 u64 qhdr;
1138 u64 req_hdr; 1172 u64 req_hdr;
@@ -1158,6 +1192,10 @@ typedef struct {
1158 1192
1159#define NETXEN_DB_MAPSIZE_BYTES 0x1000 1193#define NETXEN_DB_MAPSIZE_BYTES 0x1000
1160 1194
1195#define NETXEN_NETDEV_WEIGHT 120
1196#define NETXEN_ADAPTER_UP_MAGIC 777
1197#define NETXEN_NIC_PEG_TUNE 0
1198
1161struct netxen_dummy_dma { 1199struct netxen_dummy_dma {
1162 void *addr; 1200 void *addr;
1163 dma_addr_t phys_addr; 1201 dma_addr_t phys_addr;
@@ -1236,6 +1274,7 @@ struct netxen_adapter {
1236 1274
1237 int is_up; 1275 int is_up;
1238 struct netxen_dummy_dma dummy_dma; 1276 struct netxen_dummy_dma dummy_dma;
1277 nx_nic_intr_coalesce_t coal;
1239 1278
1240 /* Context interface shared between card and host */ 1279 /* Context interface shared between card and host */
1241 struct netxen_ring_ctx *ctx_desc; 1280 struct netxen_ring_ctx *ctx_desc;
@@ -1423,6 +1462,7 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter);
1423u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); 1462u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
1424void netxen_p2_nic_set_multi(struct net_device *netdev); 1463void netxen_p2_nic_set_multi(struct net_device *netdev);
1425void netxen_p3_nic_set_multi(struct net_device *netdev); 1464void netxen_p3_nic_set_multi(struct net_device *netdev);
1465int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
1426 1466
1427u32 nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu); 1467u32 nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu);
1428int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); 1468int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 381d55a52162..48ee06b6f4e9 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -752,6 +752,117 @@ static int netxen_nic_set_rx_csum(struct net_device *dev, u32 data)
752 return 0; 752 return 0;
753} 753}
754 754
755static u32 netxen_nic_get_tso(struct net_device *dev)
756{
757 struct netxen_adapter *adapter = netdev_priv(dev);
758
759 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
760 return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0;
761
762 return (dev->features & NETIF_F_TSO) != 0;
763}
764
765static int netxen_nic_set_tso(struct net_device *dev, u32 data)
766{
767 if (data) {
768 struct netxen_adapter *adapter = netdev_priv(dev);
769
770 dev->features |= NETIF_F_TSO;
771 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
772 dev->features |= NETIF_F_TSO6;
773 } else
774 dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
775
776 return 0;
777}
778
779/*
780 * Set the coalescing parameters. Currently only normal is supported.
781 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
782 * firmware coalescing to default.
783 */
784static int netxen_set_intr_coalesce(struct net_device *netdev,
785 struct ethtool_coalesce *ethcoal)
786{
787 struct netxen_adapter *adapter = netdev_priv(netdev);
788
789 if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
790 return -EINVAL;
791
792 if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
793 return -EINVAL;
794
795 /*
796 * Return Error if unsupported values or
797 * unsupported parameters are set.
798 */
799 if (ethcoal->rx_coalesce_usecs > 0xffff ||
800 ethcoal->rx_max_coalesced_frames > 0xffff ||
801 ethcoal->tx_coalesce_usecs > 0xffff ||
802 ethcoal->tx_max_coalesced_frames > 0xffff ||
803 ethcoal->rx_coalesce_usecs_irq ||
804 ethcoal->rx_max_coalesced_frames_irq ||
805 ethcoal->tx_coalesce_usecs_irq ||
806 ethcoal->tx_max_coalesced_frames_irq ||
807 ethcoal->stats_block_coalesce_usecs ||
808 ethcoal->use_adaptive_rx_coalesce ||
809 ethcoal->use_adaptive_tx_coalesce ||
810 ethcoal->pkt_rate_low ||
811 ethcoal->rx_coalesce_usecs_low ||
812 ethcoal->rx_max_coalesced_frames_low ||
813 ethcoal->tx_coalesce_usecs_low ||
814 ethcoal->tx_max_coalesced_frames_low ||
815 ethcoal->pkt_rate_high ||
816 ethcoal->rx_coalesce_usecs_high ||
817 ethcoal->rx_max_coalesced_frames_high ||
818 ethcoal->tx_coalesce_usecs_high ||
819 ethcoal->tx_max_coalesced_frames_high)
820 return -EINVAL;
821
822 if (!ethcoal->rx_coalesce_usecs ||
823 !ethcoal->rx_max_coalesced_frames) {
824 adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
825 adapter->coal.normal.data.rx_time_us =
826 NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
827 adapter->coal.normal.data.rx_packets =
828 NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
829 } else {
830 adapter->coal.flags = 0;
831 adapter->coal.normal.data.rx_time_us =
832 ethcoal->rx_coalesce_usecs;
833 adapter->coal.normal.data.rx_packets =
834 ethcoal->rx_max_coalesced_frames;
835 }
836 adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
837 adapter->coal.normal.data.tx_packets =
838 ethcoal->tx_max_coalesced_frames;
839
840 netxen_config_intr_coalesce(adapter);
841
842 return 0;
843}
844
845static int netxen_get_intr_coalesce(struct net_device *netdev,
846 struct ethtool_coalesce *ethcoal)
847{
848 struct netxen_adapter *adapter = netdev_priv(netdev);
849
850 if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
851 return -EINVAL;
852
853 if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
854 return -EINVAL;
855
856 ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
857 ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
858 ethcoal->rx_max_coalesced_frames =
859 adapter->coal.normal.data.rx_packets;
860 ethcoal->tx_max_coalesced_frames =
861 adapter->coal.normal.data.tx_packets;
862
863 return 0;
864}
865
755struct ethtool_ops netxen_nic_ethtool_ops = { 866struct ethtool_ops netxen_nic_ethtool_ops = {
756 .get_settings = netxen_nic_get_settings, 867 .get_settings = netxen_nic_get_settings,
757 .set_settings = netxen_nic_set_settings, 868 .set_settings = netxen_nic_set_settings,
@@ -769,11 +880,14 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
769 .set_pauseparam = netxen_nic_set_pauseparam, 880 .set_pauseparam = netxen_nic_set_pauseparam,
770 .set_tx_csum = ethtool_op_set_tx_csum, 881 .set_tx_csum = ethtool_op_set_tx_csum,
771 .set_sg = ethtool_op_set_sg, 882 .set_sg = ethtool_op_set_sg,
772 .set_tso = ethtool_op_set_tso, 883 .get_tso = netxen_nic_get_tso,
884 .set_tso = netxen_nic_set_tso,
773 .self_test = netxen_nic_diag_test, 885 .self_test = netxen_nic_diag_test,
774 .get_strings = netxen_nic_get_strings, 886 .get_strings = netxen_nic_get_strings,
775 .get_ethtool_stats = netxen_nic_get_ethtool_stats, 887 .get_ethtool_stats = netxen_nic_get_ethtool_stats,
776 .get_sset_count = netxen_get_sset_count, 888 .get_sset_count = netxen_get_sset_count,
777 .get_rx_csum = netxen_nic_get_rx_csum, 889 .get_rx_csum = netxen_nic_get_rx_csum,
778 .set_rx_csum = netxen_nic_set_rx_csum, 890 .set_rx_csum = netxen_nic_set_rx_csum,
891 .get_coalesce = netxen_get_intr_coalesce,
892 .set_coalesce = netxen_set_intr_coalesce,
779}; 893};
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 9d4e9c9dbe0a..ed8aa5ab2668 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -615,6 +615,33 @@ void netxen_p3_nic_set_multi(struct net_device *netdev)
615 } 615 }
616} 616}
617 617
618#define NETXEN_CONFIG_INTR_COALESCE 3
619
620/*
621 * Send the interrupt coalescing parameter set by ethtool to the card.
622 */
623int netxen_config_intr_coalesce(struct netxen_adapter *adapter)
624{
625 nx_nic_req_t req;
626 int rv;
627
628 memset(&req, 0, sizeof(nx_nic_req_t));
629
630 req.qhdr |= (NIC_REQUEST << 23);
631 req.req_hdr |= NETXEN_CONFIG_INTR_COALESCE;
632 req.req_hdr |= ((u64)adapter->portnum << 16);
633
634 memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal));
635
636 rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
637 if (rv != 0) {
638 printk(KERN_ERR "ERROR. Could not send "
639 "interrupt coalescing parameters\n");
640 }
641
642 return rv;
643}
644
618/* 645/*
619 * netxen_nic_change_mtu - Change the Maximum Transfer Unit 646 * netxen_nic_change_mtu - Change the Maximum Transfer Unit
620 * @returns 0 on success, negative on failure 647 * @returns 0 on success, negative on failure
@@ -651,26 +678,6 @@ int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
651 return 0; 678 return 0;
652} 679}
653 680
654void netxen_tso_check(struct netxen_adapter *adapter,
655 struct cmd_desc_type0 *desc, struct sk_buff *skb)
656{
657 if (desc->mss) {
658 desc->total_hdr_length = (sizeof(struct ethhdr) +
659 ip_hdrlen(skb) + tcp_hdrlen(skb));
660 netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
661 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
662 if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
663 netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
664 } else if (ip_hdr(skb)->protocol == IPPROTO_UDP) {
665 netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
666 } else {
667 return;
668 }
669 }
670 desc->tcp_hdr_offset = skb_transport_offset(skb);
671 desc->ip_hdr_offset = skb_network_offset(skb);
672}
673
674int netxen_is_flash_supported(struct netxen_adapter *adapter) 681int netxen_is_flash_supported(struct netxen_adapter *adapter)
675{ 682{
676 const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 }; 683 const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 };
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index b3c084f0c751..91d209a8f6cb 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -58,10 +58,6 @@ static int use_msi = 1;
58 58
59static int use_msi_x = 1; 59static int use_msi_x = 1;
60 60
61#define NETXEN_NETDEV_WEIGHT 120
62#define NETXEN_ADAPTER_UP_MAGIC 777
63#define NETXEN_NIC_PEG_TUNE 0
64
65/* Local functions to NetXen NIC driver */ 61/* Local functions to NetXen NIC driver */
66static int __devinit netxen_nic_probe(struct pci_dev *pdev, 62static int __devinit netxen_nic_probe(struct pci_dev *pdev,
67 const struct pci_device_id *ent); 63 const struct pci_device_id *ent);
@@ -735,8 +731,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
735 netdev->features = NETIF_F_SG; 731 netdev->features = NETIF_F_SG;
736 netdev->features |= NETIF_F_IP_CSUM; 732 netdev->features |= NETIF_F_IP_CSUM;
737 netdev->features |= NETIF_F_TSO; 733 netdev->features |= NETIF_F_TSO;
738 if (NX_IS_REVISION_P3(revision_id)) 734 if (NX_IS_REVISION_P3(revision_id)) {
735 netdev->features |= NETIF_F_IPV6_CSUM;
739 netdev->features |= NETIF_F_TSO6; 736 netdev->features |= NETIF_F_TSO6;
737 }
740 738
741 if (adapter->pci_using_dac) 739 if (adapter->pci_using_dac)
742 netdev->features |= NETIF_F_HIGHDMA; 740 netdev->features |= NETIF_F_HIGHDMA;
@@ -1164,6 +1162,31 @@ static int netxen_nic_close(struct net_device *netdev)
1164 return 0; 1162 return 0;
1165} 1163}
1166 1164
1165void netxen_tso_check(struct netxen_adapter *adapter,
1166 struct cmd_desc_type0 *desc, struct sk_buff *skb)
1167{
1168 if (desc->mss) {
1169 desc->total_hdr_length = (sizeof(struct ethhdr) +
1170 ip_hdrlen(skb) + tcp_hdrlen(skb));
1171
1172 if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) &&
1173 (skb->protocol == htons(ETH_P_IPV6)))
1174 netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6);
1175 else
1176 netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
1177
1178 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
1179 if (ip_hdr(skb)->protocol == IPPROTO_TCP)
1180 netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
1181 else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
1182 netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
1183 else
1184 return;
1185 }
1186 desc->tcp_hdr_offset = skb_transport_offset(skb);
1187 desc->ip_hdr_offset = skb_network_offset(skb);
1188}
1189
1167static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) 1190static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1168{ 1191{
1169 struct netxen_adapter *adapter = netdev_priv(netdev); 1192 struct netxen_adapter *adapter = netdev_priv(netdev);
@@ -1185,7 +1208,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1185 1208
1186 /* There 4 fragments per descriptor */ 1209 /* There 4 fragments per descriptor */
1187 no_of_desc = (frag_count + 3) >> 2; 1210 no_of_desc = (frag_count + 3) >> 2;
1188 if (netdev->features & NETIF_F_TSO) { 1211 if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) {
1189 if (skb_shinfo(skb)->gso_size > 0) { 1212 if (skb_shinfo(skb)->gso_size > 0) {
1190 1213
1191 no_of_desc++; 1214 no_of_desc++;
@@ -1212,7 +1235,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
1212 memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); 1235 memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
1213 /* Take skb->data itself */ 1236 /* Take skb->data itself */
1214 pbuf = &adapter->cmd_buf_arr[producer]; 1237 pbuf = &adapter->cmd_buf_arr[producer];
1215 if ((netdev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size > 0) { 1238 if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
1239 skb_shinfo(skb)->gso_size > 0) {
1216 pbuf->mss = skb_shinfo(skb)->gso_size; 1240 pbuf->mss = skb_shinfo(skb)->gso_size;
1217 hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); 1241 hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
1218 } else { 1242 } else {