diff options
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 108 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_ethtool.c | 32 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 22 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 102 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 55 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_phan_reg.h | 1 |
6 files changed, 263 insertions, 57 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 7e208b31a27e..f4d7e2db700b 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h | |||
@@ -354,6 +354,7 @@ struct rcv_desc { | |||
354 | /* opcode field in status_desc */ | 354 | /* opcode field in status_desc */ |
355 | #define NETXEN_NIC_RXPKT_DESC 0x04 | 355 | #define NETXEN_NIC_RXPKT_DESC 0x04 |
356 | #define NETXEN_OLD_RXPKT_DESC 0x3f | 356 | #define NETXEN_OLD_RXPKT_DESC 0x3f |
357 | #define NETXEN_NIC_RESPONSE_DESC 0x05 | ||
357 | 358 | ||
358 | /* for status field in status_desc */ | 359 | /* for status field in status_desc */ |
359 | #define STATUS_NEED_CKSUM (1) | 360 | #define STATUS_NEED_CKSUM (1) |
@@ -363,8 +364,11 @@ struct rcv_desc { | |||
363 | #define STATUS_OWNER_HOST (0x1ULL << 56) | 364 | #define STATUS_OWNER_HOST (0x1ULL << 56) |
364 | #define STATUS_OWNER_PHANTOM (0x2ULL << 56) | 365 | #define STATUS_OWNER_PHANTOM (0x2ULL << 56) |
365 | 366 | ||
366 | /* Note: sizeof(status_desc) should always be a mutliple of 2 */ | 367 | /* Status descriptor: |
367 | 368 | 0-3 port, 4-7 status, 8-11 type, 12-27 total_length | |
369 | 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset | ||
370 | 53-55 desc_cnt, 56-57 owner, 58-63 opcode | ||
371 | */ | ||
368 | #define netxen_get_sts_port(sts_data) \ | 372 | #define netxen_get_sts_port(sts_data) \ |
369 | ((sts_data) & 0x0F) | 373 | ((sts_data) & 0x0F) |
370 | #define netxen_get_sts_status(sts_data) \ | 374 | #define netxen_get_sts_status(sts_data) \ |
@@ -379,35 +383,13 @@ struct rcv_desc { | |||
379 | (((sts_data) >> 44) & 0x0F) | 383 | (((sts_data) >> 44) & 0x0F) |
380 | #define netxen_get_sts_pkt_offset(sts_data) \ | 384 | #define netxen_get_sts_pkt_offset(sts_data) \ |
381 | (((sts_data) >> 48) & 0x1F) | 385 | (((sts_data) >> 48) & 0x1F) |
386 | #define netxen_get_sts_desc_cnt(sts_data) \ | ||
387 | (((sts_data) >> 53) & 0x7) | ||
382 | #define netxen_get_sts_opcode(sts_data) \ | 388 | #define netxen_get_sts_opcode(sts_data) \ |
383 | (((sts_data) >> 58) & 0x03F) | 389 | (((sts_data) >> 58) & 0x03F) |
384 | 390 | ||
385 | struct status_desc { | 391 | struct status_desc { |
386 | /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length | 392 | __le64 status_desc_data[2]; |
387 | 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset | ||
388 | 53-55 desc_cnt, 56-57 owner, 58-63 opcode | ||
389 | */ | ||
390 | __le64 status_desc_data; | ||
391 | union { | ||
392 | struct { | ||
393 | __le32 hash_value; | ||
394 | u8 hash_type; | ||
395 | u8 msg_type; | ||
396 | u8 unused; | ||
397 | union { | ||
398 | /* Bit pattern: 0-6 lro_count indicates frag | ||
399 | * sequence, 7 last_frag indicates last frag | ||
400 | */ | ||
401 | u8 lro; | ||
402 | |||
403 | /* chained buffers */ | ||
404 | u8 nr_frags; | ||
405 | }; | ||
406 | }; | ||
407 | struct { | ||
408 | __le16 frag_handles[4]; | ||
409 | }; | ||
410 | }; | ||
411 | } __attribute__ ((aligned(16))); | 393 | } __attribute__ ((aligned(16))); |
412 | 394 | ||
413 | /* The version of the main data structure */ | 395 | /* The version of the main data structure */ |
@@ -1114,6 +1096,66 @@ typedef struct { | |||
1114 | #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ | 1096 | #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ |
1115 | #define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */ | 1097 | #define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */ |
1116 | 1098 | ||
1099 | #define NX_FW_CAPABILITY_LINK_NOTIFICATION (1 << 5) | ||
1100 | #define NX_FW_CAPABILITY_SWITCHING (1 << 6) | ||
1101 | |||
1102 | /* module types */ | ||
1103 | #define LINKEVENT_MODULE_NOT_PRESENT 1 | ||
1104 | #define LINKEVENT_MODULE_OPTICAL_UNKNOWN 2 | ||
1105 | #define LINKEVENT_MODULE_OPTICAL_SRLR 3 | ||
1106 | #define LINKEVENT_MODULE_OPTICAL_LRM 4 | ||
1107 | #define LINKEVENT_MODULE_OPTICAL_SFP_1G 5 | ||
1108 | #define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE 6 | ||
1109 | #define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN 7 | ||
1110 | #define LINKEVENT_MODULE_TWINAX 8 | ||
1111 | |||
1112 | #define LINKSPEED_10GBPS 10000 | ||
1113 | #define LINKSPEED_1GBPS 1000 | ||
1114 | #define LINKSPEED_100MBPS 100 | ||
1115 | #define LINKSPEED_10MBPS 10 | ||
1116 | |||
1117 | #define LINKSPEED_ENCODED_10MBPS 0 | ||
1118 | #define LINKSPEED_ENCODED_100MBPS 1 | ||
1119 | #define LINKSPEED_ENCODED_1GBPS 2 | ||
1120 | |||
1121 | #define LINKEVENT_AUTONEG_DISABLED 0 | ||
1122 | #define LINKEVENT_AUTONEG_ENABLED 1 | ||
1123 | |||
1124 | #define LINKEVENT_HALF_DUPLEX 0 | ||
1125 | #define LINKEVENT_FULL_DUPLEX 1 | ||
1126 | |||
1127 | #define LINKEVENT_LINKSPEED_MBPS 0 | ||
1128 | #define LINKEVENT_LINKSPEED_ENCODED 1 | ||
1129 | |||
1130 | /* firmware response header: | ||
1131 | * 63:58 - message type | ||
1132 | * 57:56 - owner | ||
1133 | * 55:53 - desc count | ||
1134 | * 52:48 - reserved | ||
1135 | * 47:40 - completion id | ||
1136 | * 39:32 - opcode | ||
1137 | * 31:16 - error code | ||
1138 | * 15:00 - reserved | ||
1139 | */ | ||
1140 | #define netxen_get_nic_msgtype(msg_hdr) \ | ||
1141 | ((msg_hdr >> 58) & 0x3F) | ||
1142 | #define netxen_get_nic_msg_compid(msg_hdr) \ | ||
1143 | ((msg_hdr >> 40) & 0xFF) | ||
1144 | #define netxen_get_nic_msg_opcode(msg_hdr) \ | ||
1145 | ((msg_hdr >> 32) & 0xFF) | ||
1146 | #define netxen_get_nic_msg_errcode(msg_hdr) \ | ||
1147 | ((msg_hdr >> 16) & 0xFFFF) | ||
1148 | |||
1149 | typedef struct { | ||
1150 | union { | ||
1151 | struct { | ||
1152 | u64 hdr; | ||
1153 | u64 body[7]; | ||
1154 | }; | ||
1155 | u64 words[8]; | ||
1156 | }; | ||
1157 | } nx_fw_msg_t; | ||
1158 | |||
1117 | typedef struct { | 1159 | typedef struct { |
1118 | __le64 qhdr; | 1160 | __le64 qhdr; |
1119 | __le64 req_hdr; | 1161 | __le64 req_hdr; |
@@ -1177,15 +1219,21 @@ struct netxen_adapter { | |||
1177 | 1219 | ||
1178 | u8 mc_enabled; | 1220 | u8 mc_enabled; |
1179 | u8 max_mc_count; | 1221 | u8 max_mc_count; |
1222 | u16 resv2; | ||
1223 | u32 resv3; | ||
1224 | |||
1225 | u8 has_link_events; | ||
1226 | u8 resv1; | ||
1180 | u16 tx_context_id; | 1227 | u16 tx_context_id; |
1181 | u16 mtu; | 1228 | u16 mtu; |
1182 | u16 is_up; | 1229 | u16 is_up; |
1230 | |||
1183 | u16 link_speed; | 1231 | u16 link_speed; |
1184 | u16 link_duplex; | 1232 | u16 link_duplex; |
1185 | u16 link_autoneg; | 1233 | u16 link_autoneg; |
1186 | u16 resv1; | 1234 | u16 module_type; |
1187 | 1235 | ||
1188 | u32 resv2; | 1236 | u32 capabilities; |
1189 | u32 flags; | 1237 | u32 flags; |
1190 | u32 irq; | 1238 | u32 irq; |
1191 | u32 temp; | 1239 | u32 temp; |
@@ -1398,6 +1446,8 @@ void netxen_p3_free_mac_list(struct netxen_adapter *adapter); | |||
1398 | int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32); | 1446 | int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32); |
1399 | int netxen_config_intr_coalesce(struct netxen_adapter *adapter); | 1447 | int netxen_config_intr_coalesce(struct netxen_adapter *adapter); |
1400 | int netxen_config_rss(struct netxen_adapter *adapter, int enable); | 1448 | int netxen_config_rss(struct netxen_adapter *adapter, int enable); |
1449 | int netxen_linkevent_request(struct netxen_adapter *adapter, int enable); | ||
1450 | void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup); | ||
1401 | 1451 | ||
1402 | int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu); | 1452 | int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu); |
1403 | int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); | 1453 | 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 fe910c1715d6..5fde9e088a94 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c | |||
@@ -110,6 +110,7 @@ static int | |||
110 | netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | 110 | netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) |
111 | { | 111 | { |
112 | struct netxen_adapter *adapter = netdev_priv(dev); | 112 | struct netxen_adapter *adapter = netdev_priv(dev); |
113 | int check_sfp_module = 0; | ||
113 | 114 | ||
114 | /* read which mode */ | 115 | /* read which mode */ |
115 | if (adapter->ahw.port_type == NETXEN_NIC_GBE) { | 116 | if (adapter->ahw.port_type == NETXEN_NIC_GBE) { |
@@ -143,6 +144,13 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
143 | ecmd->advertising = ADVERTISED_10000baseT_Full; | 144 | ecmd->advertising = ADVERTISED_10000baseT_Full; |
144 | } | 145 | } |
145 | 146 | ||
147 | if (netif_running(dev) && adapter->has_link_events) { | ||
148 | ecmd->speed = adapter->link_speed; | ||
149 | ecmd->autoneg = adapter->link_autoneg; | ||
150 | ecmd->duplex = adapter->link_duplex; | ||
151 | goto skip; | ||
152 | } | ||
153 | |||
146 | ecmd->port = PORT_TP; | 154 | ecmd->port = PORT_TP; |
147 | 155 | ||
148 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { | 156 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { |
@@ -160,6 +168,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
160 | } else | 168 | } else |
161 | return -EIO; | 169 | return -EIO; |
162 | 170 | ||
171 | skip: | ||
163 | ecmd->phy_address = adapter->physical_port; | 172 | ecmd->phy_address = adapter->physical_port; |
164 | ecmd->transceiver = XCVR_EXTERNAL; | 173 | ecmd->transceiver = XCVR_EXTERNAL; |
165 | 174 | ||
@@ -190,7 +199,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
190 | case NETXEN_BRDTYPE_P3_HMEZ: | 199 | case NETXEN_BRDTYPE_P3_HMEZ: |
191 | ecmd->supported |= SUPPORTED_MII; | 200 | ecmd->supported |= SUPPORTED_MII; |
192 | ecmd->advertising |= ADVERTISED_MII; | 201 | ecmd->advertising |= ADVERTISED_MII; |
193 | ecmd->port = PORT_FIBRE; | 202 | ecmd->port = PORT_MII; |
194 | ecmd->autoneg = AUTONEG_DISABLE; | 203 | ecmd->autoneg = AUTONEG_DISABLE; |
195 | break; | 204 | break; |
196 | case NETXEN_BRDTYPE_P3_10G_SFP_PLUS: | 205 | case NETXEN_BRDTYPE_P3_10G_SFP_PLUS: |
@@ -198,6 +207,8 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
198 | case NETXEN_BRDTYPE_P3_10G_SFP_QT: | 207 | case NETXEN_BRDTYPE_P3_10G_SFP_QT: |
199 | ecmd->advertising |= ADVERTISED_TP; | 208 | ecmd->advertising |= ADVERTISED_TP; |
200 | ecmd->supported |= SUPPORTED_TP; | 209 | ecmd->supported |= SUPPORTED_TP; |
210 | check_sfp_module = netif_running(dev) && | ||
211 | adapter->has_link_events; | ||
201 | case NETXEN_BRDTYPE_P2_SB31_10G: | 212 | case NETXEN_BRDTYPE_P2_SB31_10G: |
202 | case NETXEN_BRDTYPE_P3_10G_XFP: | 213 | case NETXEN_BRDTYPE_P3_10G_XFP: |
203 | ecmd->supported |= SUPPORTED_FIBRE; | 214 | ecmd->supported |= SUPPORTED_FIBRE; |
@@ -212,6 +223,8 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
212 | ecmd->advertising |= | 223 | ecmd->advertising |= |
213 | (ADVERTISED_FIBRE | ADVERTISED_TP); | 224 | (ADVERTISED_FIBRE | ADVERTISED_TP); |
214 | ecmd->port = PORT_FIBRE; | 225 | ecmd->port = PORT_FIBRE; |
226 | check_sfp_module = netif_running(dev) && | ||
227 | adapter->has_link_events; | ||
215 | } else { | 228 | } else { |
216 | ecmd->autoneg = AUTONEG_ENABLE; | 229 | ecmd->autoneg = AUTONEG_ENABLE; |
217 | ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg); | 230 | ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg); |
@@ -226,6 +239,23 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
226 | return -EIO; | 239 | return -EIO; |
227 | } | 240 | } |
228 | 241 | ||
242 | if (check_sfp_module) { | ||
243 | switch (adapter->module_type) { | ||
244 | case LINKEVENT_MODULE_OPTICAL_UNKNOWN: | ||
245 | case LINKEVENT_MODULE_OPTICAL_SRLR: | ||
246 | case LINKEVENT_MODULE_OPTICAL_LRM: | ||
247 | case LINKEVENT_MODULE_OPTICAL_SFP_1G: | ||
248 | ecmd->port = PORT_FIBRE; | ||
249 | break; | ||
250 | case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE: | ||
251 | case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN: | ||
252 | case LINKEVENT_MODULE_TWINAX: | ||
253 | ecmd->port = PORT_TP; | ||
254 | default: | ||
255 | ecmd->port = -1; | ||
256 | } | ||
257 | } | ||
258 | |||
229 | return 0; | 259 | return 0; |
230 | } | 260 | } |
231 | 261 | ||
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 8416962cc9ac..33444a20e4f7 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c | |||
@@ -731,6 +731,28 @@ int netxen_config_rss(struct netxen_adapter *adapter, int enable) | |||
731 | return rv; | 731 | return rv; |
732 | } | 732 | } |
733 | 733 | ||
734 | int netxen_linkevent_request(struct netxen_adapter *adapter, int enable) | ||
735 | { | ||
736 | nx_nic_req_t req; | ||
737 | u64 word; | ||
738 | int rv; | ||
739 | |||
740 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
741 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | ||
742 | |||
743 | word = NX_NIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16); | ||
744 | req.req_hdr = cpu_to_le64(word); | ||
745 | req.words[0] = cpu_to_le64(enable); | ||
746 | |||
747 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
748 | if (rv != 0) { | ||
749 | printk(KERN_ERR "%s: could not configure link notification\n", | ||
750 | adapter->netdev->name); | ||
751 | } | ||
752 | |||
753 | return rv; | ||
754 | } | ||
755 | |||
734 | /* | 756 | /* |
735 | * netxen_nic_change_mtu - Change the Maximum Transfer Unit | 757 | * netxen_nic_change_mtu - Change the Maximum Transfer Unit |
736 | * @returns 0 on success, negative on failure | 758 | * @returns 0 on success, negative on failure |
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 9991951e6e05..974783c45321 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c | |||
@@ -795,9 +795,81 @@ int netxen_init_firmware(struct netxen_adapter *adapter) | |||
795 | adapter->pci_write_normalize(adapter, | 795 | adapter->pci_write_normalize(adapter, |
796 | CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); | 796 | CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); |
797 | 797 | ||
798 | if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) { | ||
799 | adapter->capabilities = netxen_nic_reg_read(adapter, | ||
800 | CRB_FW_CAPABILITIES_1); | ||
801 | } | ||
802 | |||
798 | return err; | 803 | return err; |
799 | } | 804 | } |
800 | 805 | ||
806 | static void | ||
807 | netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg) | ||
808 | { | ||
809 | u32 cable_OUI; | ||
810 | u16 cable_len; | ||
811 | u16 link_speed; | ||
812 | u8 link_status, module, duplex, autoneg; | ||
813 | struct net_device *netdev = adapter->netdev; | ||
814 | |||
815 | adapter->has_link_events = 1; | ||
816 | |||
817 | cable_OUI = msg->body[1] & 0xffffffff; | ||
818 | cable_len = (msg->body[1] >> 32) & 0xffff; | ||
819 | link_speed = (msg->body[1] >> 48) & 0xffff; | ||
820 | |||
821 | link_status = msg->body[2] & 0xff; | ||
822 | duplex = (msg->body[2] >> 16) & 0xff; | ||
823 | autoneg = (msg->body[2] >> 24) & 0xff; | ||
824 | |||
825 | module = (msg->body[2] >> 8) & 0xff; | ||
826 | if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) { | ||
827 | printk(KERN_INFO "%s: unsupported cable: OUI 0x%x, length %d\n", | ||
828 | netdev->name, cable_OUI, cable_len); | ||
829 | } else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) { | ||
830 | printk(KERN_INFO "%s: unsupported cable length %d\n", | ||
831 | netdev->name, cable_len); | ||
832 | } | ||
833 | |||
834 | netxen_advert_link_change(adapter, link_status); | ||
835 | |||
836 | /* update link parameters */ | ||
837 | if (duplex == LINKEVENT_FULL_DUPLEX) | ||
838 | adapter->link_duplex = DUPLEX_FULL; | ||
839 | else | ||
840 | adapter->link_duplex = DUPLEX_HALF; | ||
841 | adapter->module_type = module; | ||
842 | adapter->link_autoneg = autoneg; | ||
843 | adapter->link_speed = link_speed; | ||
844 | } | ||
845 | |||
846 | static void | ||
847 | netxen_handle_fw_message(int desc_cnt, int index, | ||
848 | struct nx_host_sds_ring *sds_ring) | ||
849 | { | ||
850 | nx_fw_msg_t msg; | ||
851 | struct status_desc *desc; | ||
852 | int i = 0, opcode; | ||
853 | |||
854 | while (desc_cnt > 0 && i < 8) { | ||
855 | desc = &sds_ring->desc_head[index]; | ||
856 | msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]); | ||
857 | msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]); | ||
858 | |||
859 | index = get_next_index(index, sds_ring->num_desc); | ||
860 | desc_cnt--; | ||
861 | } | ||
862 | |||
863 | opcode = netxen_get_nic_msg_opcode(msg.body[0]); | ||
864 | switch (opcode) { | ||
865 | case NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE: | ||
866 | netxen_handle_linkevent(sds_ring->adapter, &msg); | ||
867 | break; | ||
868 | default: | ||
869 | break; | ||
870 | } | ||
871 | } | ||
872 | |||
801 | static int | 873 | static int |
802 | netxen_alloc_rx_skb(struct netxen_adapter *adapter, | 874 | netxen_alloc_rx_skb(struct netxen_adapter *adapter, |
803 | struct nx_host_rds_ring *rds_ring, | 875 | struct nx_host_rds_ring *rds_ring, |
@@ -916,21 +988,35 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) | |||
916 | 988 | ||
917 | int count = 0; | 989 | int count = 0; |
918 | u64 sts_data; | 990 | u64 sts_data; |
919 | int opcode, ring, index, length, cksum, pkt_offset; | 991 | int opcode, ring, index, length, cksum, pkt_offset, desc_cnt; |
920 | 992 | ||
921 | while (count < max) { | 993 | while (count < max) { |
922 | desc = &sds_ring->desc_head[consumer]; | 994 | desc = &sds_ring->desc_head[consumer]; |
923 | sts_data = le64_to_cpu(desc->status_desc_data); | 995 | sts_data = le64_to_cpu(desc->status_desc_data[0]); |
924 | 996 | ||
925 | if (!(sts_data & STATUS_OWNER_HOST)) | 997 | if (!(sts_data & STATUS_OWNER_HOST)) |
926 | break; | 998 | break; |
927 | 999 | ||
1000 | desc_cnt = netxen_get_sts_desc_cnt(sts_data); | ||
928 | ring = netxen_get_sts_type(sts_data); | 1001 | ring = netxen_get_sts_type(sts_data); |
1002 | |||
929 | if (ring > RCV_RING_JUMBO) | 1003 | if (ring > RCV_RING_JUMBO) |
930 | continue; | 1004 | goto skip; |
931 | 1005 | ||
932 | opcode = netxen_get_sts_opcode(sts_data); | 1006 | opcode = netxen_get_sts_opcode(sts_data); |
933 | 1007 | ||
1008 | switch (opcode) { | ||
1009 | case NETXEN_NIC_RXPKT_DESC: | ||
1010 | case NETXEN_OLD_RXPKT_DESC: | ||
1011 | break; | ||
1012 | case NETXEN_NIC_RESPONSE_DESC: | ||
1013 | netxen_handle_fw_message(desc_cnt, consumer, sds_ring); | ||
1014 | default: | ||
1015 | goto skip; | ||
1016 | } | ||
1017 | |||
1018 | WARN_ON(desc_cnt > 1); | ||
1019 | |||
934 | index = netxen_get_sts_refhandle(sts_data); | 1020 | index = netxen_get_sts_refhandle(sts_data); |
935 | length = netxen_get_sts_totallength(sts_data); | 1021 | length = netxen_get_sts_totallength(sts_data); |
936 | cksum = netxen_get_sts_status(sts_data); | 1022 | cksum = netxen_get_sts_status(sts_data); |
@@ -942,9 +1028,13 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) | |||
942 | if (rxbuf) | 1028 | if (rxbuf) |
943 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); | 1029 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); |
944 | 1030 | ||
945 | desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM); | 1031 | skip: |
946 | 1032 | for (; desc_cnt > 0; desc_cnt--) { | |
947 | consumer = get_next_index(consumer, sds_ring->num_desc); | 1033 | desc = &sds_ring->desc_head[consumer]; |
1034 | desc->status_desc_data[0] = | ||
1035 | cpu_to_le64(STATUS_OWNER_PHANTOM); | ||
1036 | consumer = get_next_index(consumer, sds_ring->num_desc); | ||
1037 | } | ||
948 | count++; | 1038 | count++; |
949 | } | 1039 | } |
950 | 1040 | ||
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 665fce561d4a..bd93296be4dd 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -787,6 +787,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) | |||
787 | if (adapter->max_sds_rings > 1) | 787 | if (adapter->max_sds_rings > 1) |
788 | netxen_config_rss(adapter, 1); | 788 | netxen_config_rss(adapter, 1); |
789 | 789 | ||
790 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
791 | netxen_linkevent_request(adapter, 1); | ||
792 | |||
790 | return 0; | 793 | return 0; |
791 | } | 794 | } |
792 | 795 | ||
@@ -1493,26 +1496,9 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter) | |||
1493 | return rv; | 1496 | return rv; |
1494 | } | 1497 | } |
1495 | 1498 | ||
1496 | static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) | 1499 | void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup) |
1497 | { | 1500 | { |
1498 | struct net_device *netdev = adapter->netdev; | 1501 | struct net_device *netdev = adapter->netdev; |
1499 | u32 val, port, linkup; | ||
1500 | |||
1501 | port = adapter->physical_port; | ||
1502 | |||
1503 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { | ||
1504 | val = adapter->pci_read_normalize(adapter, CRB_XG_STATE_P3); | ||
1505 | val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val); | ||
1506 | linkup = (val == XG_LINK_UP_P3); | ||
1507 | } else { | ||
1508 | val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); | ||
1509 | if (adapter->ahw.port_type == NETXEN_NIC_GBE) | ||
1510 | linkup = (val >> port) & 1; | ||
1511 | else { | ||
1512 | val = (val >> port*8) & 0xff; | ||
1513 | linkup = (val == XG_LINK_UP); | ||
1514 | } | ||
1515 | } | ||
1516 | 1502 | ||
1517 | if (adapter->ahw.linkup && !linkup) { | 1503 | if (adapter->ahw.linkup && !linkup) { |
1518 | printk(KERN_INFO "%s: %s NIC Link is down\n", | 1504 | printk(KERN_INFO "%s: %s NIC Link is down\n", |
@@ -1523,7 +1509,9 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) | |||
1523 | netif_stop_queue(netdev); | 1509 | netif_stop_queue(netdev); |
1524 | } | 1510 | } |
1525 | 1511 | ||
1526 | netxen_nic_set_link_parameters(adapter); | 1512 | if (!adapter->has_link_events) |
1513 | netxen_nic_set_link_parameters(adapter); | ||
1514 | |||
1527 | } else if (!adapter->ahw.linkup && linkup) { | 1515 | } else if (!adapter->ahw.linkup && linkup) { |
1528 | printk(KERN_INFO "%s: %s NIC Link is up\n", | 1516 | printk(KERN_INFO "%s: %s NIC Link is up\n", |
1529 | netxen_nic_driver_name, netdev->name); | 1517 | netxen_nic_driver_name, netdev->name); |
@@ -1533,10 +1521,34 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) | |||
1533 | netif_wake_queue(netdev); | 1521 | netif_wake_queue(netdev); |
1534 | } | 1522 | } |
1535 | 1523 | ||
1536 | netxen_nic_set_link_parameters(adapter); | 1524 | if (!adapter->has_link_events) |
1525 | netxen_nic_set_link_parameters(adapter); | ||
1537 | } | 1526 | } |
1538 | } | 1527 | } |
1539 | 1528 | ||
1529 | static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) | ||
1530 | { | ||
1531 | u32 val, port, linkup; | ||
1532 | |||
1533 | port = adapter->physical_port; | ||
1534 | |||
1535 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { | ||
1536 | val = adapter->pci_read_normalize(adapter, CRB_XG_STATE_P3); | ||
1537 | val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val); | ||
1538 | linkup = (val == XG_LINK_UP_P3); | ||
1539 | } else { | ||
1540 | val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); | ||
1541 | if (adapter->ahw.port_type == NETXEN_NIC_GBE) | ||
1542 | linkup = (val >> port) & 1; | ||
1543 | else { | ||
1544 | val = (val >> port*8) & 0xff; | ||
1545 | linkup = (val == XG_LINK_UP); | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | netxen_advert_link_change(adapter, linkup); | ||
1550 | } | ||
1551 | |||
1540 | static void netxen_watchdog(unsigned long v) | 1552 | static void netxen_watchdog(unsigned long v) |
1541 | { | 1553 | { |
1542 | struct netxen_adapter *adapter = (struct netxen_adapter *)v; | 1554 | struct netxen_adapter *adapter = (struct netxen_adapter *)v; |
@@ -1552,7 +1564,8 @@ void netxen_watchdog_task(struct work_struct *work) | |||
1552 | if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter)) | 1564 | if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter)) |
1553 | return; | 1565 | return; |
1554 | 1566 | ||
1555 | netxen_nic_handle_phy_intr(adapter); | 1567 | if (!adapter->has_link_events) |
1568 | netxen_nic_handle_phy_intr(adapter); | ||
1556 | 1569 | ||
1557 | if (netif_running(adapter->netdev)) | 1570 | if (netif_running(adapter->netdev)) |
1558 | mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); | 1571 | mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); |
diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index 18ea35d51160..ecd622ead0e9 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h | |||
@@ -134,6 +134,7 @@ | |||
134 | #define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) | 134 | #define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) |
135 | #define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270) | 135 | #define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270) |
136 | #define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) | 136 | #define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) |
137 | #define CRB_FW_CAPABILITIES_1 NETXEN_NIC_REG(0x128) | ||
137 | 138 | ||
138 | #define INTR_SCHEME_PERPORT 0x1 | 139 | #define INTR_SCHEME_PERPORT 0x1 |
139 | #define MSI_MODE_MULTIFUNC 0x1 | 140 | #define MSI_MODE_MULTIFUNC 0x1 |