diff options
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 40 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_ethtool.c | 116 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 47 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 38 |
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 | |||
1147 | typedef 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 | |||
1157 | typedef 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 | |||
1136 | typedef struct { | 1170 | typedef 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 | |||
1161 | struct netxen_dummy_dma { | 1199 | struct 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); | |||
1423 | u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); | 1462 | u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); |
1424 | void netxen_p2_nic_set_multi(struct net_device *netdev); | 1463 | void netxen_p2_nic_set_multi(struct net_device *netdev); |
1425 | void netxen_p3_nic_set_multi(struct net_device *netdev); | 1464 | void netxen_p3_nic_set_multi(struct net_device *netdev); |
1465 | int netxen_config_intr_coalesce(struct netxen_adapter *adapter); | ||
1426 | 1466 | ||
1427 | u32 nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu); | 1467 | u32 nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu); |
1428 | int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); | 1468 | int 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 | ||
755 | static 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 | |||
765 | static 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 | */ | ||
784 | static 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 | |||
845 | static 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 | |||
755 | struct ethtool_ops netxen_nic_ethtool_ops = { | 866 | struct 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 | */ | ||
623 | int 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 | ||
654 | void 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 | |||
674 | int netxen_is_flash_supported(struct netxen_adapter *adapter) | 681 | int 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 | ||
59 | static int use_msi_x = 1; | 59 | static 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 */ |
66 | static int __devinit netxen_nic_probe(struct pci_dev *pdev, | 62 | static 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 | ||
1165 | void 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 | |||
1167 | static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | 1190 | static 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 { |