net/bnx2x: fix to add PHY lock
This patch adds phy_lock, acquire/release the lock when performing
PHY transactions. Without this fix driver can run into synchronization
issues with management FW when modifying PHY settings.
Fixes: 540a211084
("bnx2x: driver core")
Cc: stable@dpdk.org
Signed-off-by: Rasesh Mody <rasesh.mody@cavium.com>
This commit is contained in:
parent
0f6ebeee24
commit
a9b58b15ed
@ -112,6 +112,7 @@ static void bnx2x_pf_disable(struct bnx2x_softc *sc);
|
|||||||
static void bnx2x_update_rx_prod(struct bnx2x_softc *sc,
|
static void bnx2x_update_rx_prod(struct bnx2x_softc *sc,
|
||||||
struct bnx2x_fastpath *fp,
|
struct bnx2x_fastpath *fp,
|
||||||
uint16_t rx_bd_prod, uint16_t rx_cq_prod);
|
uint16_t rx_bd_prod, uint16_t rx_cq_prod);
|
||||||
|
static void bnx2x_link_report_locked(struct bnx2x_softc *sc);
|
||||||
static void bnx2x_link_report(struct bnx2x_softc *sc);
|
static void bnx2x_link_report(struct bnx2x_softc *sc);
|
||||||
void bnx2x_link_status_update(struct bnx2x_softc *sc);
|
void bnx2x_link_status_update(struct bnx2x_softc *sc);
|
||||||
static int bnx2x_alloc_mem(struct bnx2x_softc *sc);
|
static int bnx2x_alloc_mem(struct bnx2x_softc *sc);
|
||||||
@ -198,7 +199,8 @@ static int bnx2x_acquire_hw_lock(struct bnx2x_softc *sc, uint32_t resource)
|
|||||||
uint32_t hw_lock_control_reg;
|
uint32_t hw_lock_control_reg;
|
||||||
int cnt;
|
int cnt;
|
||||||
|
|
||||||
PMD_INIT_FUNC_TRACE(sc);
|
if (resource)
|
||||||
|
PMD_INIT_FUNC_TRACE(sc);
|
||||||
|
|
||||||
/* validate the resource is within range */
|
/* validate the resource is within range */
|
||||||
if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
|
if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
|
||||||
@ -234,7 +236,8 @@ static int bnx2x_acquire_hw_lock(struct bnx2x_softc *sc, uint32_t resource)
|
|||||||
DELAY(5000);
|
DELAY(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
PMD_DRV_LOG(NOTICE, sc, "Resource lock timeout!");
|
PMD_DRV_LOG(NOTICE, sc, "Resource 0x%x resource_bit 0x%x lock timeout!",
|
||||||
|
resource, resource_bit);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,13 +248,14 @@ static int bnx2x_release_hw_lock(struct bnx2x_softc *sc, uint32_t resource)
|
|||||||
int func = SC_FUNC(sc);
|
int func = SC_FUNC(sc);
|
||||||
uint32_t hw_lock_control_reg;
|
uint32_t hw_lock_control_reg;
|
||||||
|
|
||||||
PMD_INIT_FUNC_TRACE(sc);
|
if (resource)
|
||||||
|
PMD_INIT_FUNC_TRACE(sc);
|
||||||
|
|
||||||
/* validate the resource is within range */
|
/* validate the resource is within range */
|
||||||
if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
|
if (resource > HW_LOCK_MAX_RESOURCE_VALUE) {
|
||||||
PMD_DRV_LOG(NOTICE, sc,
|
PMD_DRV_LOG(NOTICE, sc,
|
||||||
"resource 0x%x > HW_LOCK_MAX_RESOURCE_VALUE",
|
"(resource 0x%x > HW_LOCK_MAX_RESOURCE_VALUE)"
|
||||||
resource);
|
" resource_bit 0x%x", resource, resource_bit);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,6 +279,18 @@ static int bnx2x_release_hw_lock(struct bnx2x_softc *sc, uint32_t resource)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bnx2x_acquire_phy_lock(struct bnx2x_softc *sc)
|
||||||
|
{
|
||||||
|
BNX2X_PHY_LOCK(sc);
|
||||||
|
bnx2x_acquire_hw_lock(sc, HW_LOCK_RESOURCE_MDIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bnx2x_release_phy_lock(struct bnx2x_softc *sc)
|
||||||
|
{
|
||||||
|
bnx2x_release_hw_lock(sc, HW_LOCK_RESOURCE_MDIO);
|
||||||
|
BNX2X_PHY_UNLOCK(sc);
|
||||||
|
}
|
||||||
|
|
||||||
/* copy command into DMAE command memory and set DMAE command Go */
|
/* copy command into DMAE command memory and set DMAE command Go */
|
||||||
void bnx2x_post_dmae(struct bnx2x_softc *sc, struct dmae_command *dmae, int idx)
|
void bnx2x_post_dmae(struct bnx2x_softc *sc, struct dmae_command *dmae, int idx)
|
||||||
{
|
{
|
||||||
@ -2903,7 +2919,7 @@ static void bnx2x_link_attn(struct bnx2x_softc *sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bnx2x_link_report(sc);
|
bnx2x_link_report_locked(sc);
|
||||||
|
|
||||||
if (IS_MF(sc)) {
|
if (IS_MF(sc)) {
|
||||||
bnx2x_link_sync_notify(sc);
|
bnx2x_link_sync_notify(sc);
|
||||||
@ -2942,6 +2958,7 @@ static void bnx2x_attn_int_asserted(struct bnx2x_softc *sc, uint32_t asserted)
|
|||||||
if (asserted & ATTN_HARD_WIRED_MASK) {
|
if (asserted & ATTN_HARD_WIRED_MASK) {
|
||||||
if (asserted & ATTN_NIG_FOR_FUNC) {
|
if (asserted & ATTN_NIG_FOR_FUNC) {
|
||||||
|
|
||||||
|
bnx2x_acquire_phy_lock(sc);
|
||||||
/* save nig interrupt mask */
|
/* save nig interrupt mask */
|
||||||
nig_mask = REG_RD(sc, nig_int_mask_addr);
|
nig_mask = REG_RD(sc, nig_int_mask_addr);
|
||||||
|
|
||||||
@ -3039,6 +3056,7 @@ static void bnx2x_attn_int_asserted(struct bnx2x_softc *sc, uint32_t asserted)
|
|||||||
|
|
||||||
REG_WR(sc, nig_int_mask_addr, nig_mask);
|
REG_WR(sc, nig_int_mask_addr, nig_mask);
|
||||||
|
|
||||||
|
bnx2x_release_phy_lock(sc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3838,8 +3856,10 @@ static void bnx2x_attn_int_deasserted3(struct bnx2x_softc *sc, uint32_t attn)
|
|||||||
if (sc->link_vars.periodic_flags &
|
if (sc->link_vars.periodic_flags &
|
||||||
ELINK_PERIODIC_FLAGS_LINK_EVENT) {
|
ELINK_PERIODIC_FLAGS_LINK_EVENT) {
|
||||||
/* sync with link */
|
/* sync with link */
|
||||||
|
bnx2x_acquire_phy_lock(sc);
|
||||||
sc->link_vars.periodic_flags &=
|
sc->link_vars.periodic_flags &=
|
||||||
~ELINK_PERIODIC_FLAGS_LINK_EVENT;
|
~ELINK_PERIODIC_FLAGS_LINK_EVENT;
|
||||||
|
bnx2x_release_phy_lock(sc);
|
||||||
if (IS_MF(sc)) {
|
if (IS_MF(sc)) {
|
||||||
bnx2x_link_sync_notify(sc);
|
bnx2x_link_sync_notify(sc);
|
||||||
}
|
}
|
||||||
@ -4029,7 +4049,9 @@ static void bnx2x_attn_int_deasserted0(struct bnx2x_softc *sc, uint32_t attn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((attn & sc->link_vars.aeu_int_mask) && sc->port.pmf) {
|
if ((attn & sc->link_vars.aeu_int_mask) && sc->port.pmf) {
|
||||||
|
bnx2x_acquire_phy_lock(sc);
|
||||||
elink_handle_module_detect_int(&sc->link_params);
|
elink_handle_module_detect_int(&sc->link_params);
|
||||||
|
bnx2x_release_phy_lock(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attn & HW_INTERRUT_ASSERT_SET_0) {
|
if (attn & HW_INTERRUT_ASSERT_SET_0) {
|
||||||
@ -6867,7 +6889,7 @@ bnx2x_fill_report_data(struct bnx2x_softc *sc, struct bnx2x_link_report_data *da
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* report link status to OS, should be called under phy_lock */
|
/* report link status to OS, should be called under phy_lock */
|
||||||
static void bnx2x_link_report(struct bnx2x_softc *sc)
|
static void bnx2x_link_report_locked(struct bnx2x_softc *sc)
|
||||||
{
|
{
|
||||||
struct bnx2x_link_report_data cur_data;
|
struct bnx2x_link_report_data cur_data;
|
||||||
|
|
||||||
@ -6888,8 +6910,13 @@ static void bnx2x_link_report(struct bnx2x_softc *sc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PMD_DRV_LOG(INFO, sc, "Change in link status : cur_data = %lx, last_reported_link = %lx\n",
|
||||||
|
cur_data.link_report_flags,
|
||||||
|
sc->last_reported_link.link_report_flags);
|
||||||
|
|
||||||
sc->link_cnt++;
|
sc->link_cnt++;
|
||||||
|
|
||||||
|
PMD_DRV_LOG(INFO, sc, "link status change count = %x\n", sc->link_cnt);
|
||||||
/* report new link params and remember the state for the next time */
|
/* report new link params and remember the state for the next time */
|
||||||
rte_memcpy(&sc->last_reported_link, &cur_data, sizeof(cur_data));
|
rte_memcpy(&sc->last_reported_link, &cur_data, sizeof(cur_data));
|
||||||
|
|
||||||
@ -6941,6 +6968,14 @@ static void bnx2x_link_report(struct bnx2x_softc *sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bnx2x_link_report(struct bnx2x_softc *sc)
|
||||||
|
{
|
||||||
|
bnx2x_acquire_phy_lock(sc);
|
||||||
|
bnx2x_link_report_locked(sc);
|
||||||
|
bnx2x_release_phy_lock(sc);
|
||||||
|
}
|
||||||
|
|
||||||
void bnx2x_link_status_update(struct bnx2x_softc *sc)
|
void bnx2x_link_status_update(struct bnx2x_softc *sc)
|
||||||
{
|
{
|
||||||
if (sc->state != BNX2X_STATE_OPEN) {
|
if (sc->state != BNX2X_STATE_OPEN) {
|
||||||
@ -7019,6 +7054,8 @@ static int bnx2x_initial_phy_init(struct bnx2x_softc *sc, int load_mode)
|
|||||||
|
|
||||||
bnx2x_set_requested_fc(sc);
|
bnx2x_set_requested_fc(sc);
|
||||||
|
|
||||||
|
bnx2x_acquire_phy_lock(sc);
|
||||||
|
|
||||||
if (load_mode == LOAD_DIAG) {
|
if (load_mode == LOAD_DIAG) {
|
||||||
lp->loopback_mode = ELINK_LOOPBACK_XGXS;
|
lp->loopback_mode = ELINK_LOOPBACK_XGXS;
|
||||||
/* Prefer doing PHY loopback at 10G speed, if possible */
|
/* Prefer doing PHY loopback at 10G speed, if possible */
|
||||||
@ -7038,6 +7075,8 @@ static int bnx2x_initial_phy_init(struct bnx2x_softc *sc, int load_mode)
|
|||||||
|
|
||||||
rc = elink_phy_init(&sc->link_params, &sc->link_vars);
|
rc = elink_phy_init(&sc->link_params, &sc->link_vars);
|
||||||
|
|
||||||
|
bnx2x_release_phy_lock(sc);
|
||||||
|
|
||||||
bnx2x_calc_fc_adv(sc);
|
bnx2x_calc_fc_adv(sc);
|
||||||
|
|
||||||
if (sc->link_vars.link_up) {
|
if (sc->link_vars.link_up) {
|
||||||
@ -7088,7 +7127,9 @@ void bnx2x_periodic_callout(struct bnx2x_softc *sc)
|
|||||||
*/
|
*/
|
||||||
mb();
|
mb();
|
||||||
if (sc->port.pmf) {
|
if (sc->port.pmf) {
|
||||||
|
bnx2x_acquire_phy_lock(sc);
|
||||||
elink_period_func(&sc->link_params, &sc->link_vars);
|
elink_period_func(&sc->link_params, &sc->link_vars);
|
||||||
|
bnx2x_release_phy_lock(sc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef BNX2X_PULSE
|
#ifdef BNX2X_PULSE
|
||||||
@ -9840,8 +9881,10 @@ static void bnx2x_common_init_phy(struct bnx2x_softc *sc)
|
|||||||
shmem2_base[1] = SHMEM2_RD(sc, other_shmem2_base_addr);
|
shmem2_base[1] = SHMEM2_RD(sc, other_shmem2_base_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bnx2x_acquire_phy_lock(sc);
|
||||||
elink_common_init_phy(sc, shmem_base, shmem2_base,
|
elink_common_init_phy(sc, shmem_base, shmem2_base,
|
||||||
sc->devinfo.chip_id, 0);
|
sc->devinfo.chip_id, 0);
|
||||||
|
bnx2x_release_phy_lock(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bnx2x_pf_disable(struct bnx2x_softc *sc)
|
static void bnx2x_pf_disable(struct bnx2x_softc *sc)
|
||||||
@ -11320,7 +11363,9 @@ static int bnx2x_init_hw_func(struct bnx2x_softc *sc)
|
|||||||
static void bnx2x_link_reset(struct bnx2x_softc *sc)
|
static void bnx2x_link_reset(struct bnx2x_softc *sc)
|
||||||
{
|
{
|
||||||
if (!BNX2X_NOMCP(sc)) {
|
if (!BNX2X_NOMCP(sc)) {
|
||||||
|
bnx2x_acquire_phy_lock(sc);
|
||||||
elink_lfa_reset(&sc->link_params, &sc->link_vars);
|
elink_lfa_reset(&sc->link_params, &sc->link_vars);
|
||||||
|
bnx2x_release_phy_lock(sc);
|
||||||
} else {
|
} else {
|
||||||
if (!CHIP_REV_IS_SLOW(sc)) {
|
if (!CHIP_REV_IS_SLOW(sc)) {
|
||||||
PMD_DRV_LOG(WARNING, sc,
|
PMD_DRV_LOG(WARNING, sc,
|
||||||
|
@ -725,6 +725,13 @@ struct bnx2x_port {
|
|||||||
|
|
||||||
uint32_t phy_addr;
|
uint32_t phy_addr;
|
||||||
|
|
||||||
|
/* Used to synchronize phy accesses. */
|
||||||
|
rte_spinlock_t phy_mtx;
|
||||||
|
char phy_mtx_name[32];
|
||||||
|
|
||||||
|
#define BNX2X_PHY_LOCK(sc) rte_spinlock_lock(&sc->port.phy_mtx)
|
||||||
|
#define BNX2X_PHY_UNLOCK(sc) rte_spinlock_unlock(&sc->port.phy_mtx)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MCP scratchpad address for port specific statistics.
|
* MCP scratchpad address for port specific statistics.
|
||||||
* The device is responsible for writing statistcss
|
* The device is responsible for writing statistcss
|
||||||
|
@ -1967,6 +1967,7 @@
|
|||||||
#define HW_LOCK_MAX_RESOURCE_VALUE 31
|
#define HW_LOCK_MAX_RESOURCE_VALUE 31
|
||||||
#define HW_LOCK_RESOURCE_DRV_FLAGS 10
|
#define HW_LOCK_RESOURCE_DRV_FLAGS 10
|
||||||
#define HW_LOCK_RESOURCE_GPIO 1
|
#define HW_LOCK_RESOURCE_GPIO 1
|
||||||
|
#define HW_LOCK_RESOURCE_MDIO 0
|
||||||
#define HW_LOCK_RESOURCE_NVRAM 12
|
#define HW_LOCK_RESOURCE_NVRAM 12
|
||||||
#define HW_LOCK_RESOURCE_PORT0_ATT_MASK 3
|
#define HW_LOCK_RESOURCE_PORT0_ATT_MASK 3
|
||||||
#define HW_LOCK_RESOURCE_RECOVERY_LEADER_0 8
|
#define HW_LOCK_RESOURCE_RECOVERY_LEADER_0 8
|
||||||
|
Loading…
Reference in New Issue
Block a user