aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuval Mintz <yuvalmin@broadcom.com>2013-04-21 22:53:03 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-25 04:00:56 -0400
commitecf01c22be034690b621d92c9ff488d607a9995a (patch)
treee05899b77655c080a421f33fddebc396c582d6b8
parente56db277684895184bc74fcf74f7ef993e3a5b6c (diff)
bnx2x: Prevent NULL pointer dereference in kdump
In scenarios in which a previous driver was removed without proper cleanup (e.g., kdump), it is possible for the chip to generate an interrupt without any apparent reason once interrupts are requested. Due to an erroneous initialization of resources, some of the bnx2x structs which are required for interrupt handling are initialized only after an interface's interrupt is requested from the OS. As a result, once such a spurious interrupt occurs, it will cause a NULL pointer dereference - the driver will access those structs in its interrupt handling routine. This patch change the interrupt request scheme so that bnx2x would only request interrupts from the kernel after it has finished initializing all the inner structs required for interrupt handling. Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com> Signed-off-by: Ariel Elior <ariele@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c11
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h19
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c32
3 files changed, 39 insertions, 23 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 57619dd4a92b..51a6030138e3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1037,6 +1037,7 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
1037 DP(NETIF_MSG_INTR, 1037 DP(NETIF_MSG_INTR,
1038 "got an MSI-X interrupt on IDX:SB [fp %d fw_sd %d igusb %d]\n", 1038 "got an MSI-X interrupt on IDX:SB [fp %d fw_sd %d igusb %d]\n",
1039 fp->index, fp->fw_sb_id, fp->igu_sb_id); 1039 fp->index, fp->fw_sb_id, fp->igu_sb_id);
1040
1040 bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0); 1041 bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0);
1041 1042
1042#ifdef BNX2X_STOP_ON_ERROR 1043#ifdef BNX2X_STOP_ON_ERROR
@@ -1718,7 +1719,7 @@ static int bnx2x_req_irq(struct bnx2x *bp)
1718 return request_irq(irq, bnx2x_interrupt, flags, bp->dev->name, bp->dev); 1719 return request_irq(irq, bnx2x_interrupt, flags, bp->dev->name, bp->dev);
1719} 1720}
1720 1721
1721static int bnx2x_setup_irqs(struct bnx2x *bp) 1722int bnx2x_setup_irqs(struct bnx2x *bp)
1722{ 1723{
1723 int rc = 0; 1724 int rc = 0;
1724 if (bp->flags & USING_MSIX_FLAG && 1725 if (bp->flags & USING_MSIX_FLAG &&
@@ -2574,6 +2575,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
2574 } 2575 }
2575 } 2576 }
2576 2577
2578 bnx2x_pre_irq_nic_init(bp);
2579
2577 /* Connect to IRQs */ 2580 /* Connect to IRQs */
2578 rc = bnx2x_setup_irqs(bp); 2581 rc = bnx2x_setup_irqs(bp);
2579 if (rc) { 2582 if (rc) {
@@ -2583,11 +2586,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
2583 LOAD_ERROR_EXIT(bp, load_error2); 2586 LOAD_ERROR_EXIT(bp, load_error2);
2584 } 2587 }
2585 2588
2586 /* Setup NIC internals and enable interrupts */
2587 bnx2x_nic_init(bp, load_code);
2588
2589 /* Init per-function objects */ 2589 /* Init per-function objects */
2590 if (IS_PF(bp)) { 2590 if (IS_PF(bp)) {
2591 /* Setup NIC internals and enable interrupts */
2592 bnx2x_post_irq_nic_init(bp, load_code);
2593
2591 bnx2x_init_bp_objs(bp); 2594 bnx2x_init_bp_objs(bp);
2592 bnx2x_iov_nic_init(bp); 2595 bnx2x_iov_nic_init(bp);
2593 2596
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index aee7671ff4c1..c3a65d04c8c9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -295,16 +295,29 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
295void bnx2x_nic_init_cnic(struct bnx2x *bp); 295void bnx2x_nic_init_cnic(struct bnx2x *bp);
296 296
297/** 297/**
298 * bnx2x_nic_init - init driver internals. 298 * bnx2x_preirq_nic_init - init driver internals.
299 * 299 *
300 * @bp: driver handle 300 * @bp: driver handle
301 * 301 *
302 * Initializes: 302 * Initializes:
303 * - rings 303 * - fastpath object
304 * - fastpath rings
305 * etc.
306 */
307void bnx2x_pre_irq_nic_init(struct bnx2x *bp);
308
309/**
310 * bnx2x_postirq_nic_init - init driver internals.
311 *
312 * @bp: driver handle
313 * @load_code: COMMON, PORT or FUNCTION
314 *
315 * Initializes:
304 * - status blocks 316 * - status blocks
317 * - slowpath rings
305 * - etc. 318 * - etc.
306 */ 319 */
307void bnx2x_nic_init(struct bnx2x *bp, u32 load_code); 320void bnx2x_post_irq_nic_init(struct bnx2x *bp, u32 load_code);
308/** 321/**
309 * bnx2x_alloc_mem_cnic - allocate driver's memory for cnic. 322 * bnx2x_alloc_mem_cnic - allocate driver's memory for cnic.
310 * 323 *
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index c50696b396f1..a8f1ee31de77 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -6018,10 +6018,11 @@ void bnx2x_nic_init_cnic(struct bnx2x *bp)
6018 mmiowb(); 6018 mmiowb();
6019} 6019}
6020 6020
6021void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) 6021void bnx2x_pre_irq_nic_init(struct bnx2x *bp)
6022{ 6022{
6023 int i; 6023 int i;
6024 6024
6025 /* Setup NIC internals and enable interrupts */
6025 for_each_eth_queue(bp, i) 6026 for_each_eth_queue(bp, i)
6026 bnx2x_init_eth_fp(bp, i); 6027 bnx2x_init_eth_fp(bp, i);
6027 6028
@@ -6030,17 +6031,21 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
6030 bnx2x_init_rx_rings(bp); 6031 bnx2x_init_rx_rings(bp);
6031 bnx2x_init_tx_rings(bp); 6032 bnx2x_init_tx_rings(bp);
6032 6033
6033 if (IS_VF(bp)) 6034 if (IS_PF(bp)) {
6034 return; 6035 /* Initialize MOD_ABS interrupts */
6036 bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id,
6037 bp->common.shmem_base,
6038 bp->common.shmem2_base, BP_PORT(bp));
6035 6039
6036 /* Initialize MOD_ABS interrupts */ 6040 /* initialize the default status block and sp ring */
6037 bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id, 6041 bnx2x_init_def_sb(bp);
6038 bp->common.shmem_base, bp->common.shmem2_base, 6042 bnx2x_update_dsb_idx(bp);
6039 BP_PORT(bp)); 6043 bnx2x_init_sp_ring(bp);
6044 }
6045}
6040 6046
6041 bnx2x_init_def_sb(bp); 6047void bnx2x_post_irq_nic_init(struct bnx2x *bp, u32 load_code)
6042 bnx2x_update_dsb_idx(bp); 6048{
6043 bnx2x_init_sp_ring(bp);
6044 bnx2x_init_eq_ring(bp); 6049 bnx2x_init_eq_ring(bp);
6045 bnx2x_init_internal(bp, load_code); 6050 bnx2x_init_internal(bp, load_code);
6046 bnx2x_pf_init(bp); 6051 bnx2x_pf_init(bp);
@@ -6058,12 +6063,7 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
6058 AEU_INPUTS_ATTN_BITS_SPIO5); 6063 AEU_INPUTS_ATTN_BITS_SPIO5);
6059} 6064}
6060 6065
6061/* end of nic init */ 6066/* gzip service functions */
6062
6063/*
6064 * gzip service functions
6065 */
6066
6067static int bnx2x_gunzip_init(struct bnx2x *bp) 6067static int bnx2x_gunzip_init(struct bnx2x *bp)
6068{ 6068{
6069 bp->gunzip_buf = dma_alloc_coherent(&bp->pdev->dev, FW_BUF_SIZE, 6069 bp->gunzip_buf = dma_alloc_coherent(&bp->pdev->dev, FW_BUF_SIZE,