aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/netxen/netxen_nic.h108
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c32
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c22
-rw-r--r--drivers/net/netxen/netxen_nic_init.c102
-rw-r--r--drivers/net/netxen/netxen_nic_main.c55
-rw-r--r--drivers/net/netxen/netxen_nic_phan_reg.h1
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
385struct status_desc { 391struct 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
1149typedef struct {
1150 union {
1151 struct {
1152 u64 hdr;
1153 u64 body[7];
1154 };
1155 u64 words[8];
1156 };
1157} nx_fw_msg_t;
1158
1117typedef struct { 1159typedef 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);
1398int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32); 1446int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32);
1399int netxen_config_intr_coalesce(struct netxen_adapter *adapter); 1447int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
1400int netxen_config_rss(struct netxen_adapter *adapter, int enable); 1448int netxen_config_rss(struct netxen_adapter *adapter, int enable);
1449int netxen_linkevent_request(struct netxen_adapter *adapter, int enable);
1450void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup);
1401 1451
1402int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu); 1452int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu);
1403int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); 1453int 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
110netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) 110netxen_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
171skip:
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
734int 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
806static void
807netxen_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
846static void
847netxen_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
801static int 873static int
802netxen_alloc_rx_skb(struct netxen_adapter *adapter, 874netxen_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); 1031skip:
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
1496static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) 1499void 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
1529static 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
1540static void netxen_watchdog(unsigned long v) 1552static 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