Commit 65abd74d authored by Yitchak Gertner's avatar Yitchak Gertner Committed by David S. Miller

bnx2x: NAPI and interrupts enable/disable

Fixing the order of enabling and disabling NAPI and the interrupts
Signed-off-by: default avatarYitchak Gertner <gertner@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d1014634
...@@ -6058,6 +6058,44 @@ static int bnx2x_req_irq(struct bnx2x *bp) ...@@ -6058,6 +6058,44 @@ static int bnx2x_req_irq(struct bnx2x *bp)
return rc; return rc;
} }
static void bnx2x_napi_enable(struct bnx2x *bp)
{
int i;
for_each_queue(bp, i)
napi_enable(&bnx2x_fp(bp, i, napi));
}
static void bnx2x_napi_disable(struct bnx2x *bp)
{
int i;
for_each_queue(bp, i)
napi_disable(&bnx2x_fp(bp, i, napi));
}
static void bnx2x_netif_start(struct bnx2x *bp)
{
if (atomic_dec_and_test(&bp->intr_sem)) {
if (netif_running(bp->dev)) {
if (bp->state == BNX2X_STATE_OPEN)
netif_wake_queue(bp->dev);
bnx2x_napi_enable(bp);
bnx2x_int_enable(bp);
}
}
}
static void bnx2x_netif_stop(struct bnx2x *bp)
{
bnx2x_int_disable_sync(bp);
if (netif_running(bp->dev)) {
bnx2x_napi_disable(bp);
netif_tx_disable(bp->dev);
bp->dev->trans_start = jiffies; /* prevent tx timeout */
}
}
/* /*
* Init service functions * Init service functions
*/ */
...@@ -6363,8 +6401,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) ...@@ -6363,8 +6401,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
/* Enable Rx interrupt handling before sending the ramrod /* Enable Rx interrupt handling before sending the ramrod
as it's completed on Rx FP queue */ as it's completed on Rx FP queue */
for_each_queue(bp, i) bnx2x_napi_enable(bp);
napi_enable(&bnx2x_fp(bp, i, napi));
/* Enable interrupt handling */ /* Enable interrupt handling */
atomic_set(&bp->intr_sem, 0); atomic_set(&bp->intr_sem, 0);
...@@ -6431,8 +6468,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) ...@@ -6431,8 +6468,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
return 0; return 0;
load_netif_stop: load_netif_stop:
for_each_queue(bp, i) bnx2x_napi_disable(bp);
napi_disable(&bnx2x_fp(bp, i, napi));
load_rings_free: load_rings_free:
/* Free SKBs, SGEs, TPA pool and driver internals */ /* Free SKBs, SGEs, TPA pool and driver internals */
bnx2x_free_skbs(bp); bnx2x_free_skbs(bp);
...@@ -6614,11 +6650,9 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) ...@@ -6614,11 +6650,9 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bp->rx_mode = BNX2X_RX_MODE_NONE; bp->rx_mode = BNX2X_RX_MODE_NONE;
bnx2x_set_storm_rx_mode(bp); bnx2x_set_storm_rx_mode(bp);
if (netif_running(bp->dev)) { bnx2x_netif_stop(bp);
netif_tx_disable(bp->dev); if (!netif_running(bp->dev))
bp->dev->trans_start = jiffies; /* prevent tx timeout */ bnx2x_napi_disable(bp);
}
del_timer_sync(&bp->timer); del_timer_sync(&bp->timer);
SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb, SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb,
(DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq)); (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
...@@ -6632,9 +6666,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) ...@@ -6632,9 +6666,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
smp_rmb(); smp_rmb();
while (BNX2X_HAS_TX_WORK(fp)) { while (BNX2X_HAS_TX_WORK(fp)) {
if (!netif_running(bp->dev))
bnx2x_tx_int(fp, 1000); bnx2x_tx_int(fp, 1000);
if (!cnt) { if (!cnt) {
BNX2X_ERR("timeout waiting for queue[%d]\n", BNX2X_ERR("timeout waiting for queue[%d]\n",
i); i);
...@@ -6650,46 +6682,12 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) ...@@ -6650,46 +6682,12 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
smp_rmb(); smp_rmb();
} }
} }
/* Give HW time to discard old tx messages */ /* Give HW time to discard old tx messages */
msleep(1); msleep(1);
for_each_queue(bp, i)
napi_disable(&bnx2x_fp(bp, i, napi));
/* Disable interrupts after Tx and Rx are disabled on stack level */
bnx2x_int_disable_sync(bp);
/* Release IRQs */ /* Release IRQs */
bnx2x_free_irq(bp); bnx2x_free_irq(bp);
if (unload_mode == UNLOAD_NORMAL)
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
else if (bp->flags & NO_WOL_FLAG) {
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP;
if (CHIP_IS_E1H(bp))
REG_WR(bp, MISC_REG_E1HMF_MODE, 0);
} else if (bp->wol) {
u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
u8 *mac_addr = bp->dev->dev_addr;
u32 val;
/* The mac address is written to entries 1-4 to
preserve entry 0 which is used by the PMF */
u8 entry = (BP_E1HVN(bp) + 1)*8;
val = (mac_addr[0] << 8) | mac_addr[1];
EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry, val);
val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
(mac_addr[4] << 8) | mac_addr[5];
EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val);
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN;
} else
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
if (CHIP_IS_E1(bp)) { if (CHIP_IS_E1(bp)) {
struct mac_configuration_cmd *config = struct mac_configuration_cmd *config =
bnx2x_sp(bp, mcast_config); bnx2x_sp(bp, mcast_config);
...@@ -6712,14 +6710,41 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) ...@@ -6712,14 +6710,41 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
U64_LO(bnx2x_sp_mapping(bp, mcast_config)), 0); U64_LO(bnx2x_sp_mapping(bp, mcast_config)), 0);
} else { /* E1H */ } else { /* E1H */
REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
bnx2x_set_mac_addr_e1h(bp, 0); bnx2x_set_mac_addr_e1h(bp, 0);
for (i = 0; i < MC_HASH_SIZE; i++) for (i = 0; i < MC_HASH_SIZE; i++)
REG_WR(bp, MC_HASH_OFFSET(bp, i), 0); REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
} }
if (unload_mode == UNLOAD_NORMAL)
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
else if (bp->flags & NO_WOL_FLAG) {
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP;
if (CHIP_IS_E1H(bp)) if (CHIP_IS_E1H(bp))
REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0); REG_WR(bp, MISC_REG_E1HMF_MODE, 0);
} else if (bp->wol) {
u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
u8 *mac_addr = bp->dev->dev_addr;
u32 val;
/* The mac address is written to entries 1-4 to
preserve entry 0 which is used by the PMF */
u8 entry = (BP_E1HVN(bp) + 1)*8;
val = (mac_addr[0] << 8) | mac_addr[1];
EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry, val);
val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
(mac_addr[4] << 8) | mac_addr[5];
EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val);
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN;
} else
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
/* Close multi and leading connections /* Close multi and leading connections
Completions for ramrods are collected in a synchronous way */ Completions for ramrods are collected in a synchronous way */
...@@ -8621,34 +8646,6 @@ test_mem_exit: ...@@ -8621,34 +8646,6 @@ test_mem_exit:
return rc; return rc;
} }
static void bnx2x_netif_start(struct bnx2x *bp)
{
int i;
if (atomic_dec_and_test(&bp->intr_sem)) {
if (netif_running(bp->dev)) {
bnx2x_int_enable(bp);
for_each_queue(bp, i)
napi_enable(&bnx2x_fp(bp, i, napi));
if (bp->state == BNX2X_STATE_OPEN)
netif_wake_queue(bp->dev);
}
}
}
static void bnx2x_netif_stop(struct bnx2x *bp)
{
int i;
if (netif_running(bp->dev)) {
netif_tx_disable(bp->dev);
bp->dev->trans_start = jiffies; /* prevent tx timeout */
for_each_queue(bp, i)
napi_disable(&bnx2x_fp(bp, i, napi));
}
bnx2x_int_disable_sync(bp);
}
static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up) static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up)
{ {
int cnt = 1000; int cnt = 1000;
......
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