Commit 286ef9d6 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

bnxt_en: Enhance autoneg support.

On some dual port NICs, the speed setting on one port can affect the
available speed on the other port.  Add logic to detect these changes
and adjust the advertised speed settings when necessary.
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 16d663a6
...@@ -1499,6 +1499,7 @@ static int bnxt_async_event_process(struct bnxt *bp, ...@@ -1499,6 +1499,7 @@ static int bnxt_async_event_process(struct bnxt *bp,
netdev_warn(bp->dev, "Link speed %d no longer supported\n", netdev_warn(bp->dev, "Link speed %d no longer supported\n",
speed); speed);
} }
set_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT, &bp->sp_event);
/* fall thru */ /* fall thru */
} }
case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
...@@ -5095,6 +5096,7 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state) ...@@ -5095,6 +5096,7 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
struct hwrm_port_phy_qcfg_input req = {0}; struct hwrm_port_phy_qcfg_input req = {0};
struct hwrm_port_phy_qcfg_output *resp = bp->hwrm_cmd_resp_addr; struct hwrm_port_phy_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
u8 link_up = link_info->link_up; u8 link_up = link_info->link_up;
u16 diff;
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_QCFG, -1, -1); bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_QCFG, -1, -1);
...@@ -5182,6 +5184,23 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state) ...@@ -5182,6 +5184,23 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
link_info->link_up = 0; link_info->link_up = 0;
} }
mutex_unlock(&bp->hwrm_cmd_lock); mutex_unlock(&bp->hwrm_cmd_lock);
diff = link_info->support_auto_speeds ^ link_info->advertising;
if ((link_info->support_auto_speeds | diff) !=
link_info->support_auto_speeds) {
/* An advertised speed is no longer supported, so we need to
* update the advertisement settings. See bnxt_reset() for
* comments about the rtnl_lock() sequence below.
*/
clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
rtnl_lock();
link_info->advertising = link_info->support_auto_speeds;
if (test_bit(BNXT_STATE_OPEN, &bp->state) &&
(link_info->autoneg & BNXT_AUTONEG_SPEED))
bnxt_hwrm_set_link_setting(bp, true, false);
set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
rtnl_unlock();
}
return 0; return 0;
} }
...@@ -6108,6 +6127,10 @@ static void bnxt_sp_task(struct work_struct *work) ...@@ -6108,6 +6127,10 @@ static void bnxt_sp_task(struct work_struct *work)
if (test_and_clear_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event)) if (test_and_clear_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event))
bnxt_cfg_ntp_filters(bp); bnxt_cfg_ntp_filters(bp);
if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) { if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
if (test_and_clear_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT,
&bp->sp_event))
bnxt_hwrm_phy_qcaps(bp);
rc = bnxt_update_link(bp, true); rc = bnxt_update_link(bp, true);
if (rc) if (rc)
netdev_err(bp->dev, "SP task can't update link (rc: %x)\n", netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
......
...@@ -1089,6 +1089,7 @@ struct bnxt { ...@@ -1089,6 +1089,7 @@ struct bnxt {
#define BNXT_RESET_TASK_SILENT_SP_EVENT 11 #define BNXT_RESET_TASK_SILENT_SP_EVENT 11
#define BNXT_GENEVE_ADD_PORT_SP_EVENT 12 #define BNXT_GENEVE_ADD_PORT_SP_EVENT 12
#define BNXT_GENEVE_DEL_PORT_SP_EVENT 13 #define BNXT_GENEVE_DEL_PORT_SP_EVENT 13
#define BNXT_LINK_SPEED_CHNG_SP_EVENT 14
struct bnxt_pf_info pf; struct bnxt_pf_info pf;
#ifdef CONFIG_BNXT_SRIOV #ifdef CONFIG_BNXT_SRIOV
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment