summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavidcs <davidcs@FreeBSD.org>2015-06-30 17:44:44 +0000
committerdavidcs <davidcs@FreeBSD.org>2015-06-30 17:44:44 +0000
commit61a04dd60987043feef0118220c55539ae2bcce6 (patch)
tree4ae2a1539273ed24333dc5598b99df237cb2dd97
parent8a1f7539e018d12ca23dd879dbe8ff857eae5f90 (diff)
downloadFreeBSD-src-61a04dd60987043feef0118220c55539ae2bcce6.zip
FreeBSD-src-61a04dd60987043feef0118220c55539ae2bcce6.tar.gz
MFC r284335
PHY LOCK acquires the hardware lock via bxe_acquire_phy_lock() and releases it via bxe_release_phy_lock(). It was simply acquiring a mutex earlier which can cause the PHY to use bogus values. Fixes intermittent link failures. bxe_ioctl() completes all functions within its context as opposed to a taskqueue earlier. bxe_handle_rx_mode_tq() no longer required. bxe_set_rx_mode() handles the functionality within its context Submitted by: gary.zambrano@qlogic.com
-rw-r--r--sys/dev/bxe/bxe.c119
-rw-r--r--sys/dev/bxe/bxe.h6
-rw-r--r--sys/dev/bxe/ecore_reg.h1
3 files changed, 47 insertions, 79 deletions
diff --git a/sys/dev/bxe/bxe.c b/sys/dev/bxe/bxe.c
index 130cfbd..b7a1c3e 100644
--- a/sys/dev/bxe/bxe.c
+++ b/sys/dev/bxe/bxe.c
@@ -737,7 +737,6 @@ static __noinline int bxe_nic_unload(struct bxe_softc *sc,
uint8_t keep_link);
static void bxe_handle_sp_tq(void *context, int pending);
-static void bxe_handle_rx_mode_tq(void *context, int pending);
static void bxe_handle_fp_tq(void *context, int pending);
@@ -1185,7 +1184,17 @@ bxe_release_hw_lock(struct bxe_softc *sc,
REG_WR(sc, hw_lock_control_reg, resource_bit);
return (0);
}
+static void bxe_acquire_phy_lock(struct bxe_softc *sc)
+{
+ BXE_PHY_LOCK(sc);
+ bxe_acquire_hw_lock(sc,HW_LOCK_RESOURCE_MDIO);
+}
+static void bxe_release_phy_lock(struct bxe_softc *sc)
+{
+ bxe_release_hw_lock(sc,HW_LOCK_RESOURCE_MDIO);
+ BXE_PHY_UNLOCK(sc);
+}
/*
* Per pf misc lock must be acquired before the per port mcp lock. Otherwise,
* had we done things the other way around, if two pfs from the same port
@@ -4775,29 +4784,6 @@ bxe_handle_chip_tq(void *context,
switch (work)
{
- case CHIP_TQ_START:
- if ((sc->ifnet->if_flags & IFF_UP) &&
- !(sc->ifnet->if_drv_flags & IFF_DRV_RUNNING)) {
- /* start the interface */
- BLOGD(sc, DBG_LOAD, "Starting the interface...\n");
- BXE_CORE_LOCK(sc);
- bxe_init_locked(sc);
- BXE_CORE_UNLOCK(sc);
- }
- break;
-
- case CHIP_TQ_STOP:
- if (!(sc->ifnet->if_flags & IFF_UP) &&
- (sc->ifnet->if_drv_flags & IFF_DRV_RUNNING)) {
- /* bring down the interface */
- BLOGD(sc, DBG_LOAD, "Stopping the interface...\n");
- bxe_periodic_stop(sc);
- BXE_CORE_LOCK(sc);
- bxe_stop_locked(sc);
- BXE_CORE_UNLOCK(sc);
- }
- break;
-
case CHIP_TQ_REINIT:
if (sc->ifnet->if_drv_flags & IFF_DRV_RUNNING) {
/* restart the interface */
@@ -4867,21 +4853,22 @@ bxe_ioctl(struct ifnet *ifp,
/* toggle the interface state up or down */
BLOGD(sc, DBG_IOCTL, "Received SIOCSIFFLAGS ioctl\n");
+ BXE_CORE_LOCK(sc);
/* check if the interface is up */
if (ifp->if_flags & IFF_UP) {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
/* set the receive mode flags */
bxe_set_rx_mode(sc);
} else {
- atomic_store_rel_long(&sc->chip_tq_flags, CHIP_TQ_START);
- taskqueue_enqueue(sc->chip_tq, &sc->chip_tq_task);
+ bxe_init_locked(sc);
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- atomic_store_rel_long(&sc->chip_tq_flags, CHIP_TQ_STOP);
- taskqueue_enqueue(sc->chip_tq, &sc->chip_tq_task);
+ bxe_periodic_stop(sc);
+ bxe_stop_locked(sc);
}
}
+ BXE_CORE_UNLOCK(sc);
break;
@@ -4893,7 +4880,9 @@ bxe_ioctl(struct ifnet *ifp,
/* check if the interface is up */
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
/* set the receive mode flags */
+ BXE_CORE_LOCK(sc);
bxe_set_rx_mode(sc);
+ BXE_CORE_UNLOCK(sc);
}
break;
@@ -5051,8 +5040,11 @@ bxe_ioctl(struct ifnet *ifp,
if (reinit && (sc->ifnet->if_drv_flags & IFF_DRV_RUNNING)) {
BLOGD(sc, DBG_LOAD | DBG_IOCTL,
"Re-initializing hardware from IOCTL change\n");
- atomic_store_rel_long(&sc->chip_tq_flags, CHIP_TQ_REINIT);
- taskqueue_enqueue(sc->chip_tq, &sc->chip_tq_task);
+ bxe_periodic_stop(sc);
+ BXE_CORE_LOCK(sc);
+ bxe_stop_locked(sc);
+ bxe_init_locked(sc);
+ BXE_CORE_UNLOCK(sc);
}
return (error);
@@ -7494,8 +7486,7 @@ bxe_attn_int_asserted(struct bxe_softc *sc,
if (asserted & ATTN_HARD_WIRED_MASK) {
if (asserted & ATTN_NIG_FOR_FUNC) {
- BXE_PHY_LOCK(sc);
-
+ bxe_acquire_phy_lock(sc);
/* save nig interrupt mask */
nig_mask = REG_RD(sc, nig_int_mask_addr);
@@ -7588,7 +7579,7 @@ bxe_attn_int_asserted(struct bxe_softc *sc,
REG_WR(sc, nig_int_mask_addr, nig_mask);
- BXE_PHY_UNLOCK(sc);
+ bxe_release_phy_lock(sc);
}
}
@@ -8346,10 +8337,10 @@ bxe_attn_int_deasserted3(struct bxe_softc *sc,
if (sc->link_vars.periodic_flags &
ELINK_PERIODIC_FLAGS_LINK_EVENT) {
/* sync with link */
- BXE_PHY_LOCK(sc);
+ bxe_acquire_phy_lock(sc);
sc->link_vars.periodic_flags &=
~ELINK_PERIODIC_FLAGS_LINK_EVENT;
- BXE_PHY_UNLOCK(sc);
+ bxe_release_phy_lock(sc);
if (IS_MF(sc))
; // XXX bxe_link_sync_notify(sc);
bxe_link_report(sc);
@@ -8542,9 +8533,9 @@ bxe_attn_int_deasserted0(struct bxe_softc *sc,
}
if ((attn & sc->link_vars.aeu_int_mask) && sc->port.pmf) {
- BXE_PHY_LOCK(sc);
+ bxe_acquire_phy_lock(sc);
elink_handle_module_detect_int(&sc->link_params);
- BXE_PHY_UNLOCK(sc);
+ bxe_release_phy_lock(sc);
}
if (attn & HW_INTERRUT_ASSERT_SET_0) {
@@ -9571,11 +9562,6 @@ bxe_interrupt_detach(struct bxe_softc *sc)
}
}
- if (sc->rx_mode_tq) {
- taskqueue_drain(sc->rx_mode_tq, &sc->rx_mode_tq_task);
- taskqueue_free(sc->rx_mode_tq);
- sc->rx_mode_tq = NULL;
- }
if (sc->sp_tq) {
taskqueue_drain(sc->sp_tq, &sc->sp_tq_task);
@@ -9609,14 +9595,6 @@ bxe_interrupt_attach(struct bxe_softc *sc)
taskqueue_start_threads(&sc->sp_tq, 1, PWAIT, /* lower priority */
"%s", sc->sp_tq_name);
- snprintf(sc->rx_mode_tq_name, sizeof(sc->rx_mode_tq_name),
- "bxe%d_rx_mode_tq", sc->unit);
- TASK_INIT(&sc->rx_mode_tq_task, 0, bxe_handle_rx_mode_tq, sc);
- sc->rx_mode_tq = taskqueue_create_fast(sc->rx_mode_tq_name, M_NOWAIT,
- taskqueue_thread_enqueue,
- &sc->rx_mode_tq);
- taskqueue_start_threads(&sc->rx_mode_tq, 1, PWAIT, /* lower priority */
- "%s", sc->rx_mode_tq_name);
for (i = 0; i < sc->num_queues; i++) {
fp = &sc->fp[i];
@@ -12370,9 +12348,9 @@ bxe_link_report_locked(struct bxe_softc *sc)
static void
bxe_link_report(struct bxe_softc *sc)
{
- BXE_PHY_LOCK(sc);
+ bxe_acquire_phy_lock(sc);
bxe_link_report_locked(sc);
- BXE_PHY_UNLOCK(sc);
+ bxe_release_phy_lock(sc);
}
static void
@@ -12488,7 +12466,7 @@ bxe_initial_phy_init(struct bxe_softc *sc,
sc->link_params.feature_config_flags |= feat;
}
- BXE_PHY_LOCK(sc);
+ bxe_acquire_phy_lock(sc);
if (load_mode == LOAD_DIAG) {
lp->loopback_mode = ELINK_LOOPBACK_XGXS;
@@ -12509,7 +12487,7 @@ bxe_initial_phy_init(struct bxe_softc *sc,
rc = elink_phy_init(&sc->link_params, &sc->link_vars);
- BXE_PHY_UNLOCK(sc);
+ bxe_release_phy_lock(sc);
bxe_calc_fc_adv(sc);
@@ -12697,18 +12675,13 @@ bxe_set_uc_list(struct bxe_softc *sc)
}
static void
-bxe_handle_rx_mode_tq(void *context,
- int pending)
+bxe_set_rx_mode(struct bxe_softc *sc)
{
- struct bxe_softc *sc = (struct bxe_softc *)context;
struct ifnet *ifp = sc->ifnet;
uint32_t rx_mode = BXE_RX_MODE_NORMAL;
- BXE_CORE_LOCK(sc);
-
if (sc->state != BXE_STATE_OPEN) {
BLOGD(sc, DBG_SP, "state is %x, returning\n", sc->state);
- BXE_CORE_UNLOCK(sc);
return;
}
@@ -12750,7 +12723,6 @@ bxe_handle_rx_mode_tq(void *context,
if (bxe_test_bit(ECORE_FILTER_RX_MODE_PENDING, &sc->sp_state)) {
BLOGD(sc, DBG_LOAD, "Scheduled setting rx_mode with ECORE...\n");
bxe_set_bit(ECORE_FILTER_RX_MODE_SCHED, &sc->sp_state);
- BXE_CORE_UNLOCK(sc);
return;
}
@@ -12770,14 +12742,8 @@ bxe_handle_rx_mode_tq(void *context,
}
#endif
- BXE_CORE_UNLOCK(sc);
}
-static void
-bxe_set_rx_mode(struct bxe_softc *sc)
-{
- taskqueue_enqueue(sc->rx_mode_tq, &sc->rx_mode_tq_task);
-}
/* update flags in shmem */
static void
@@ -12848,13 +12814,13 @@ bxe_periodic_callout_func(void *xsc)
*/
mb();
if (sc->port.pmf) {
- BXE_PHY_LOCK(sc);
+ bxe_acquire_phy_lock(sc);
elink_period_func(&sc->link_params, &sc->link_vars);
- BXE_PHY_UNLOCK(sc);
+ bxe_release_phy_lock(sc);
}
}
- if (IS_PF(sc) && !BXE_NOMCP(sc)) {
+ if (IS_PF(sc) && !(sc->flags & BXE_NO_PULSE)) {
int mb_idx = SC_FW_MB_IDX(sc);
uint32_t drv_pulse;
uint32_t mcp_pulse;
@@ -12998,6 +12964,11 @@ bxe_nic_load(struct bxe_softc *sc,
}
}
+ /* set ALWAYS_ALIVE bit in shmem */
+ sc->fw_drv_pulse_wr_seq |= DRV_PULSE_ALWAYS_ALIVE;
+ bxe_drv_pulse(sc);
+ sc->flags |= BXE_NO_PULSE;
+
/* attach interrupts */
if (bxe_interrupt_attach(sc) != 0) {
sc->state = BXE_STATE_CLOSED;
@@ -16755,10 +16726,10 @@ bxe_common_init_phy(struct bxe_softc *sc)
shmem2_base[1] = SHMEM2_RD(sc, other_shmem2_base_addr);
}
- BXE_PHY_LOCK(sc);
+ bxe_acquire_phy_lock(sc);
elink_common_init_phy(sc, shmem_base, shmem2_base,
sc->devinfo.chip_id, 0);
- BXE_PHY_UNLOCK(sc);
+ bxe_release_phy_lock(sc);
}
static void
@@ -18635,9 +18606,9 @@ static void
bxe_link_reset(struct bxe_softc *sc)
{
if (!BXE_NOMCP(sc)) {
- BXE_PHY_LOCK(sc);
+ bxe_acquire_phy_lock(sc);
elink_lfa_reset(&sc->link_params, &sc->link_vars);
- BXE_PHY_UNLOCK(sc);
+ bxe_release_phy_lock(sc);
} else {
if (!CHIP_REV_IS_SLOW(sc)) {
BLOGW(sc, "Bootcode is missing - cannot reset link\n");
diff --git a/sys/dev/bxe/bxe.h b/sys/dev/bxe/bxe.h
index 8c5a142..173a164 100644
--- a/sys/dev/bxe/bxe.h
+++ b/sys/dev/bxe/bxe.h
@@ -1400,6 +1400,7 @@ struct bxe_softc {
//#define BXE_SAFC_TX_FLAG 0x00000400
#define BXE_MF_FUNC_DIS 0x00000800
#define BXE_TX_SWITCHING 0x00001000
+#define BXE_NO_PULSE 0x00002000
unsigned long debug; /* per-instance debug logging config */
@@ -1429,11 +1430,6 @@ struct bxe_softc {
struct taskqueue *sp_tq;
char sp_tq_name[32];
- /* set rx_mode asynchronous taskqueue */
- struct task rx_mode_tq_task;
- struct taskqueue *rx_mode_tq;
- char rx_mode_tq_name[32];
-
struct bxe_fastpath fp[MAX_RSS_CHAINS];
struct bxe_sp_objs sp_objs[MAX_RSS_CHAINS];
diff --git a/sys/dev/bxe/ecore_reg.h b/sys/dev/bxe/ecore_reg.h
index b256e78..850390c 100644
--- a/sys/dev/bxe/ecore_reg.h
+++ b/sys/dev/bxe/ecore_reg.h
@@ -1965,6 +1965,7 @@ __FBSDID("$FreeBSD$");
#define MISC_SPIO_SPIO5 0x20
#define HW_LOCK_MAX_RESOURCE_VALUE 31
#define HW_LOCK_RESOURCE_DRV_FLAGS 10
+#define HW_LOCK_RESOURCE_MDIO 0
#define HW_LOCK_RESOURCE_GPIO 1
#define HW_LOCK_RESOURCE_NVRAM 12
#define HW_LOCK_RESOURCE_PORT0_ATT_MASK 3
OpenPOWER on IntegriCloud