aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h5
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c21
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h7
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c7
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c24
5 files changed, 45 insertions, 19 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 995198d72b84..cbdec2536da6 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -299,6 +299,8 @@ struct be_vf_cfg {
299 u32 tx_rate; 299 u32 tx_rate;
300}; 300};
301 301
302#define BE_FLAGS_LINK_STATUS_INIT 1
303
302struct be_adapter { 304struct be_adapter {
303 struct pci_dev *pdev; 305 struct pci_dev *pdev;
304 struct net_device *netdev; 306 struct net_device *netdev;
@@ -347,6 +349,7 @@ struct be_adapter {
347 struct delayed_work work; 349 struct delayed_work work;
348 u16 work_counter; 350 u16 work_counter;
349 351
352 u32 flags;
350 /* Ethtool knobs and info */ 353 /* Ethtool knobs and info */
351 char fw_ver[FW_VER_LEN]; 354 char fw_ver[FW_VER_LEN];
352 int if_handle; /* Used to configure filtering */ 355 int if_handle; /* Used to configure filtering */
@@ -538,7 +541,7 @@ static inline bool be_error(struct be_adapter *adapter)
538 541
539extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, 542extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
540 u16 num_popped); 543 u16 num_popped);
541extern void be_link_status_update(struct be_adapter *adapter, u32 link_status); 544extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
542extern void be_parse_stats(struct be_adapter *adapter); 545extern void be_parse_stats(struct be_adapter *adapter);
543extern int be_load_fw(struct be_adapter *adapter, u8 *func); 546extern int be_load_fw(struct be_adapter *adapter, u8 *func);
544#endif /* BE_H */ 547#endif /* BE_H */
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 62868ea48295..0fcb45624796 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -125,7 +125,14 @@ done:
125static void be_async_link_state_process(struct be_adapter *adapter, 125static void be_async_link_state_process(struct be_adapter *adapter,
126 struct be_async_event_link_state *evt) 126 struct be_async_event_link_state *evt)
127{ 127{
128 be_link_status_update(adapter, evt->port_link_status); 128 /* When link status changes, link speed must be re-queried from FW */
129 adapter->link_speed = -1;
130
131 /* For the initial link status do not rely on the ASYNC event as
132 * it may not be received in some cases.
133 */
134 if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT)
135 be_link_status_update(adapter, evt->port_link_status);
129} 136}
130 137
131/* Grp5 CoS Priority evt */ 138/* Grp5 CoS Priority evt */
@@ -1232,7 +1239,7 @@ err:
1232 1239
1233/* Uses synchronous mcc */ 1240/* Uses synchronous mcc */
1234int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, 1241int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
1235 u16 *link_speed, u32 dom) 1242 u16 *link_speed, u8 *link_status, u32 dom)
1236{ 1243{
1237 struct be_mcc_wrb *wrb; 1244 struct be_mcc_wrb *wrb;
1238 struct be_cmd_req_link_status *req; 1245 struct be_cmd_req_link_status *req;
@@ -1240,6 +1247,9 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
1240 1247
1241 spin_lock_bh(&adapter->mcc_lock); 1248 spin_lock_bh(&adapter->mcc_lock);
1242 1249
1250 if (link_status)
1251 *link_status = LINK_DOWN;
1252
1243 wrb = wrb_from_mccq(adapter); 1253 wrb = wrb_from_mccq(adapter);
1244 if (!wrb) { 1254 if (!wrb) {
1245 status = -EBUSY; 1255 status = -EBUSY;
@@ -1247,7 +1257,7 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
1247 } 1257 }
1248 req = embedded_payload(wrb); 1258 req = embedded_payload(wrb);
1249 1259
1250 if (lancer_chip(adapter)) 1260 if (adapter->generation == BE_GEN3 || lancer_chip(adapter))
1251 req->hdr.version = 1; 1261 req->hdr.version = 1;
1252 1262
1253 be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 1263 be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
@@ -1257,10 +1267,13 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
1257 if (!status) { 1267 if (!status) {
1258 struct be_cmd_resp_link_status *resp = embedded_payload(wrb); 1268 struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
1259 if (resp->mac_speed != PHY_LINK_SPEED_ZERO) { 1269 if (resp->mac_speed != PHY_LINK_SPEED_ZERO) {
1260 *link_speed = le16_to_cpu(resp->link_speed); 1270 if (link_speed)
1271 *link_speed = le16_to_cpu(resp->link_speed);
1261 if (mac_speed) 1272 if (mac_speed)
1262 *mac_speed = resp->mac_speed; 1273 *mac_speed = resp->mac_speed;
1263 } 1274 }
1275 if (link_status)
1276 *link_status = resp->logical_link_status;
1264 } 1277 }
1265 1278
1266err: 1279err:
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 0b694c640642..dca89249088f 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -960,7 +960,8 @@ struct be_cmd_resp_link_status {
960 u8 mgmt_mac_duplex; 960 u8 mgmt_mac_duplex;
961 u8 mgmt_mac_speed; 961 u8 mgmt_mac_speed;
962 u16 link_speed; 962 u16 link_speed;
963 u32 rsvd0; 963 u8 logical_link_status;
964 u8 rsvd1[3];
964} __packed; 965} __packed;
965 966
966/******************** Port Identification ***************************/ 967/******************** Port Identification ***************************/
@@ -1507,8 +1508,8 @@ extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
1507 int type); 1508 int type);
1508extern int be_cmd_rxq_destroy(struct be_adapter *adapter, 1509extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
1509 struct be_queue_info *q); 1510 struct be_queue_info *q);
1510extern int be_cmd_link_status_query(struct be_adapter *adapter, 1511extern int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
1511 u8 *mac_speed, u16 *link_speed, u32 dom); 1512 u16 *link_speed, u8 *link_status, u32 dom);
1512extern int be_cmd_reset(struct be_adapter *adapter); 1513extern int be_cmd_reset(struct be_adapter *adapter);
1513extern int be_cmd_get_stats(struct be_adapter *adapter, 1514extern int be_cmd_get_stats(struct be_adapter *adapter,
1514 struct be_dma_mem *nonemb_cmd); 1515 struct be_dma_mem *nonemb_cmd);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index 6ba2dc6bdf7b..6db6b6ae5e9b 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -429,11 +429,14 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
429 struct be_phy_info phy_info; 429 struct be_phy_info phy_info;
430 u8 mac_speed = 0; 430 u8 mac_speed = 0;
431 u16 link_speed = 0; 431 u16 link_speed = 0;
432 u8 link_status;
432 int status; 433 int status;
433 434
434 if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) { 435 if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
435 status = be_cmd_link_status_query(adapter, &mac_speed, 436 status = be_cmd_link_status_query(adapter, &mac_speed,
436 &link_speed, 0); 437 &link_speed, &link_status, 0);
438 if (!status)
439 be_link_status_update(adapter, link_status);
437 440
438 /* link_speed is in units of 10 Mbps */ 441 /* link_speed is in units of 10 Mbps */
439 if (link_speed) { 442 if (link_speed) {
@@ -700,7 +703,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
700 } 703 }
701 704
702 if (be_cmd_link_status_query(adapter, &mac_speed, 705 if (be_cmd_link_status_query(adapter, &mac_speed,
703 &qos_link_speed, 0) != 0) { 706 &qos_link_speed, NULL, 0) != 0) {
704 test->flags |= ETH_TEST_FL_FAILED; 707 test->flags |= ETH_TEST_FL_FAILED;
705 data[4] = -1; 708 data[4] = -1;
706 } else if (!mac_speed) { 709 } else if (!mac_speed) {
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index fe702c1c866d..6c46753aeb43 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -496,19 +496,19 @@ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
496 return stats; 496 return stats;
497} 497}
498 498
499void be_link_status_update(struct be_adapter *adapter, u32 link_status) 499void be_link_status_update(struct be_adapter *adapter, u8 link_status)
500{ 500{
501 struct net_device *netdev = adapter->netdev; 501 struct net_device *netdev = adapter->netdev;
502 502
503 /* when link status changes, link speed must be re-queried from card */ 503 if (!(adapter->flags & BE_FLAGS_LINK_STATUS_INIT)) {
504 adapter->link_speed = -1;
505 if ((link_status & LINK_STATUS_MASK) == LINK_UP) {
506 netif_carrier_on(netdev);
507 dev_info(&adapter->pdev->dev, "%s: Link up\n", netdev->name);
508 } else {
509 netif_carrier_off(netdev); 504 netif_carrier_off(netdev);
510 dev_info(&adapter->pdev->dev, "%s: Link down\n", netdev->name); 505 adapter->flags |= BE_FLAGS_LINK_STATUS_INIT;
511 } 506 }
507
508 if ((link_status & LINK_STATUS_MASK) == LINK_UP)
509 netif_carrier_on(netdev);
510 else
511 netif_carrier_off(netdev);
512} 512}
513 513
514static void be_tx_stats_update(struct be_tx_obj *txo, 514static void be_tx_stats_update(struct be_tx_obj *txo,
@@ -2414,6 +2414,7 @@ static int be_open(struct net_device *netdev)
2414 struct be_adapter *adapter = netdev_priv(netdev); 2414 struct be_adapter *adapter = netdev_priv(netdev);
2415 struct be_eq_obj *tx_eq = &adapter->tx_eq; 2415 struct be_eq_obj *tx_eq = &adapter->tx_eq;
2416 struct be_rx_obj *rxo; 2416 struct be_rx_obj *rxo;
2417 u8 link_status;
2417 int status, i; 2418 int status, i;
2418 2419
2419 status = be_rx_queues_setup(adapter); 2420 status = be_rx_queues_setup(adapter);
@@ -2437,6 +2438,11 @@ static int be_open(struct net_device *netdev)
2437 /* Now that interrupts are on we can process async mcc */ 2438 /* Now that interrupts are on we can process async mcc */
2438 be_async_mcc_enable(adapter); 2439 be_async_mcc_enable(adapter);
2439 2440
2441 status = be_cmd_link_status_query(adapter, NULL, NULL,
2442 &link_status, 0);
2443 if (!status)
2444 be_link_status_update(adapter, link_status);
2445
2440 return 0; 2446 return 0;
2441err: 2447err:
2442 be_close(adapter->netdev); 2448 be_close(adapter->netdev);
@@ -2584,7 +2590,7 @@ static int be_vf_setup(struct be_adapter *adapter)
2584 2590
2585 for_all_vfs(adapter, vf_cfg, vf) { 2591 for_all_vfs(adapter, vf_cfg, vf) {
2586 status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, 2592 status = be_cmd_link_status_query(adapter, NULL, &lnk_speed,
2587 vf + 1); 2593 NULL, vf + 1);
2588 if (status) 2594 if (status)
2589 goto err; 2595 goto err;
2590 vf_cfg->tx_rate = lnk_speed * 10; 2596 vf_cfg->tx_rate = lnk_speed * 10;