提交 b236916a 编写于 作者: A Ajit Khaparde 提交者: David S. Miller

be2net: query link status in be_open()

be2net gets an async link status notification from the FW when it creates
an MCC queue. There are some cases in which this gratuitous notification
is not received from FW. To cover this explicitly query the link status
in be_open().
Signed-off-by: NVasundhara Volam <vasundhara.volam@emulex.com>
Signed-off-by: NSathya Perla <sathya.perla@emulex.com>
Signed-off-by: NAjit Khaparde <ajit.khaparde@emulex.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 94f434c2
...@@ -299,6 +299,8 @@ struct be_vf_cfg { ...@@ -299,6 +299,8 @@ struct be_vf_cfg {
u32 tx_rate; u32 tx_rate;
}; };
#define BE_FLAGS_LINK_STATUS_INIT 1
struct be_adapter { struct be_adapter {
struct pci_dev *pdev; struct pci_dev *pdev;
struct net_device *netdev; struct net_device *netdev;
...@@ -347,6 +349,7 @@ struct be_adapter { ...@@ -347,6 +349,7 @@ struct be_adapter {
struct delayed_work work; struct delayed_work work;
u16 work_counter; u16 work_counter;
u32 flags;
/* Ethtool knobs and info */ /* Ethtool knobs and info */
char fw_ver[FW_VER_LEN]; char fw_ver[FW_VER_LEN];
int if_handle; /* Used to configure filtering */ int if_handle; /* Used to configure filtering */
...@@ -538,7 +541,7 @@ static inline bool be_error(struct be_adapter *adapter) ...@@ -538,7 +541,7 @@ static inline bool be_error(struct be_adapter *adapter)
extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
u16 num_popped); u16 num_popped);
extern void be_link_status_update(struct be_adapter *adapter, u32 link_status); extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
extern void be_parse_stats(struct be_adapter *adapter); extern void be_parse_stats(struct be_adapter *adapter);
extern int be_load_fw(struct be_adapter *adapter, u8 *func); extern int be_load_fw(struct be_adapter *adapter, u8 *func);
#endif /* BE_H */ #endif /* BE_H */
...@@ -125,7 +125,14 @@ static int be_mcc_compl_process(struct be_adapter *adapter, ...@@ -125,7 +125,14 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
static void be_async_link_state_process(struct be_adapter *adapter, static void be_async_link_state_process(struct be_adapter *adapter,
struct be_async_event_link_state *evt) struct be_async_event_link_state *evt)
{ {
be_link_status_update(adapter, evt->port_link_status); /* When link status changes, link speed must be re-queried from FW */
adapter->link_speed = -1;
/* For the initial link status do not rely on the ASYNC event as
* it may not be received in some cases.
*/
if (adapter->flags & BE_FLAGS_LINK_STATUS_INIT)
be_link_status_update(adapter, evt->port_link_status);
} }
/* Grp5 CoS Priority evt */ /* Grp5 CoS Priority evt */
...@@ -1232,7 +1239,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, ...@@ -1232,7 +1239,7 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
/* Uses synchronous mcc */ /* Uses synchronous mcc */
int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
u16 *link_speed, u32 dom) u16 *link_speed, u8 *link_status, u32 dom)
{ {
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_cmd_req_link_status *req; 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,6 +1247,9 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
spin_lock_bh(&adapter->mcc_lock); spin_lock_bh(&adapter->mcc_lock);
if (link_status)
*link_status = LINK_DOWN;
wrb = wrb_from_mccq(adapter); wrb = wrb_from_mccq(adapter);
if (!wrb) { if (!wrb) {
status = -EBUSY; status = -EBUSY;
...@@ -1247,7 +1257,7 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, ...@@ -1247,7 +1257,7 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
} }
req = embedded_payload(wrb); req = embedded_payload(wrb);
if (lancer_chip(adapter)) if (adapter->generation == BE_GEN3 || lancer_chip(adapter))
req->hdr.version = 1; req->hdr.version = 1;
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, 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,10 +1267,13 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
if (!status) { if (!status) {
struct be_cmd_resp_link_status *resp = embedded_payload(wrb); struct be_cmd_resp_link_status *resp = embedded_payload(wrb);
if (resp->mac_speed != PHY_LINK_SPEED_ZERO) { if (resp->mac_speed != PHY_LINK_SPEED_ZERO) {
*link_speed = le16_to_cpu(resp->link_speed); if (link_speed)
*link_speed = le16_to_cpu(resp->link_speed);
if (mac_speed) if (mac_speed)
*mac_speed = resp->mac_speed; *mac_speed = resp->mac_speed;
} }
if (link_status)
*link_status = resp->logical_link_status;
} }
err: err:
......
...@@ -960,7 +960,8 @@ struct be_cmd_resp_link_status { ...@@ -960,7 +960,8 @@ struct be_cmd_resp_link_status {
u8 mgmt_mac_duplex; u8 mgmt_mac_duplex;
u8 mgmt_mac_speed; u8 mgmt_mac_speed;
u16 link_speed; u16 link_speed;
u32 rsvd0; u8 logical_link_status;
u8 rsvd1[3];
} __packed; } __packed;
/******************** Port Identification ***************************/ /******************** Port Identification ***************************/
...@@ -1507,8 +1508,8 @@ extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, ...@@ -1507,8 +1508,8 @@ extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
int type); int type);
extern int be_cmd_rxq_destroy(struct be_adapter *adapter, extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
struct be_queue_info *q); struct be_queue_info *q);
extern int be_cmd_link_status_query(struct be_adapter *adapter, extern int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed,
u8 *mac_speed, u16 *link_speed, u32 dom); u16 *link_speed, u8 *link_status, u32 dom);
extern int be_cmd_reset(struct be_adapter *adapter); extern int be_cmd_reset(struct be_adapter *adapter);
extern int be_cmd_get_stats(struct be_adapter *adapter, extern int be_cmd_get_stats(struct be_adapter *adapter,
struct be_dma_mem *nonemb_cmd); struct be_dma_mem *nonemb_cmd);
......
...@@ -429,11 +429,14 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ...@@ -429,11 +429,14 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
struct be_phy_info phy_info; struct be_phy_info phy_info;
u8 mac_speed = 0; u8 mac_speed = 0;
u16 link_speed = 0; u16 link_speed = 0;
u8 link_status;
int status; int status;
if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) { if ((adapter->link_speed < 0) || (!(netdev->flags & IFF_UP))) {
status = be_cmd_link_status_query(adapter, &mac_speed, status = be_cmd_link_status_query(adapter, &mac_speed,
&link_speed, 0); &link_speed, &link_status, 0);
if (!status)
be_link_status_update(adapter, link_status);
/* link_speed is in units of 10 Mbps */ /* link_speed is in units of 10 Mbps */
if (link_speed) { if (link_speed) {
...@@ -700,7 +703,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) ...@@ -700,7 +703,7 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
} }
if (be_cmd_link_status_query(adapter, &mac_speed, if (be_cmd_link_status_query(adapter, &mac_speed,
&qos_link_speed, 0) != 0) { &qos_link_speed, NULL, 0) != 0) {
test->flags |= ETH_TEST_FL_FAILED; test->flags |= ETH_TEST_FL_FAILED;
data[4] = -1; data[4] = -1;
} else if (!mac_speed) { } else if (!mac_speed) {
......
...@@ -496,19 +496,19 @@ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev, ...@@ -496,19 +496,19 @@ static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
return stats; return stats;
} }
void be_link_status_update(struct be_adapter *adapter, u32 link_status) void be_link_status_update(struct be_adapter *adapter, u8 link_status)
{ {
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
/* when link status changes, link speed must be re-queried from card */ if (!(adapter->flags & BE_FLAGS_LINK_STATUS_INIT)) {
adapter->link_speed = -1;
if ((link_status & LINK_STATUS_MASK) == LINK_UP) {
netif_carrier_on(netdev);
dev_info(&adapter->pdev->dev, "%s: Link up\n", netdev->name);
} else {
netif_carrier_off(netdev); netif_carrier_off(netdev);
dev_info(&adapter->pdev->dev, "%s: Link down\n", netdev->name); adapter->flags |= BE_FLAGS_LINK_STATUS_INIT;
} }
if ((link_status & LINK_STATUS_MASK) == LINK_UP)
netif_carrier_on(netdev);
else
netif_carrier_off(netdev);
} }
static void be_tx_stats_update(struct be_tx_obj *txo, static void be_tx_stats_update(struct be_tx_obj *txo,
...@@ -2414,6 +2414,7 @@ static int be_open(struct net_device *netdev) ...@@ -2414,6 +2414,7 @@ static int be_open(struct net_device *netdev)
struct be_adapter *adapter = netdev_priv(netdev); struct be_adapter *adapter = netdev_priv(netdev);
struct be_eq_obj *tx_eq = &adapter->tx_eq; struct be_eq_obj *tx_eq = &adapter->tx_eq;
struct be_rx_obj *rxo; struct be_rx_obj *rxo;
u8 link_status;
int status, i; int status, i;
status = be_rx_queues_setup(adapter); status = be_rx_queues_setup(adapter);
...@@ -2437,6 +2438,11 @@ static int be_open(struct net_device *netdev) ...@@ -2437,6 +2438,11 @@ static int be_open(struct net_device *netdev)
/* Now that interrupts are on we can process async mcc */ /* Now that interrupts are on we can process async mcc */
be_async_mcc_enable(adapter); be_async_mcc_enable(adapter);
status = be_cmd_link_status_query(adapter, NULL, NULL,
&link_status, 0);
if (!status)
be_link_status_update(adapter, link_status);
return 0; return 0;
err: err:
be_close(adapter->netdev); be_close(adapter->netdev);
...@@ -2584,7 +2590,7 @@ static int be_vf_setup(struct be_adapter *adapter) ...@@ -2584,7 +2590,7 @@ static int be_vf_setup(struct be_adapter *adapter)
for_all_vfs(adapter, vf_cfg, vf) { for_all_vfs(adapter, vf_cfg, vf) {
status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, status = be_cmd_link_status_query(adapter, NULL, &lnk_speed,
vf + 1); NULL, vf + 1);
if (status) if (status)
goto err; goto err;
vf_cfg->tx_rate = lnk_speed * 10; vf_cfg->tx_rate = lnk_speed * 10;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册