linux/drivers/net/ethernet/broadcom
Jon Maxwell f37bd0cced cnic: call cp->stop_hw() in cnic_start_hw() on allocation failure
We recently had a system crash in the cnic module. Vmcore analysis confirmed
that "ip link up" was executed which failed due to an allocation failure
because of memory fragmentation. Futher analysis revealed that the cnic irq
vector was still allocated after the "ip link up" that failed. When
"ip link down" was executed it called free_msi_irqs() which crashed the system
because the cnic irq was still inuse.

PANIC: "kernel BUG at drivers/pci/msi.c:411!"

The code execution was:

cnic_netdev_event()
if (event == NETDEV_UP) {
.
.
       ▹       if (!cnic_start_hw(dev))
cnic_start_hw()
calls cnic_cm_open() which failed with -ENOMEM
cnic_start_hw() then took the err1 path:

err1:↩
       cp->free_resc(dev);↩ <---- frees resources but not irq vector
       pci_dev_put(dev->pcidev);↩
       return err;↩
}↩

This returns control back to cnic_netdev_event() but now the cnic irq vector
is still allocated even although cnic_cm_open() failed. The next
"ip link down" while trigger the crash.

The cnic_start_hw() routine is not handling the allocation failure correctly.
Fix this by checking whether CNIC_DRV_STATE_HANDLES_IRQ flag is set indicating
that the hardware has been started in cnic_start_hw(). If it has then call
cp->stop_hw() which frees the cnic irq vector and cnic resources. Otherwise
just maintain the previous behaviour and free cnic resources.

I reproduced this by injecting an ENOMEM error into cnic_cm_alloc_mem()s return
code.

# ip link set dev enpX down
# ip link set dev enpX up <--- hit's allocation failure
# ip link set dev enpX down <--- crashes here

With this patch I confirmed there was no crash in the reproducer.

Signed-off-by: Jon Maxwell <jmaxwell37@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-05-06 15:44:54 -04:00
..
bnx2x bnx2x: Prevent false warning for lack of FC NPIV 2016-03-18 19:17:16 -04:00
bnxt bnxt: Add support for segmentation of tunnels with outer checksums 2016-05-04 13:32:28 -04:00
genet treewide: replace dev->trans_start update with helper 2016-05-04 14:16:49 -04:00
Kconfig bnx2x: add a separate GENEVE Kconfig symbol 2016-02-24 22:48:54 -05:00
Makefile bnxt_en: New Broadcom ethernet driver. 2015-10-22 19:30:33 -07:00
b44.c phy: Add API for {un}registering an mdio device to a bus. 2016-01-07 14:31:26 -05:00
b44.h b44: Utilize BRCM_PSEUDO_PHY_ADDR 2015-06-10 23:33:58 -07:00
bcm63xx_enet.c mdio: Move allocation of interrupts into core 2016-01-07 14:31:26 -05:00
bcm63xx_enet.h bcm63xx_enet: add support Broadcom BCM6345 Ethernet 2013-06-13 17:22:08 -07:00
bcmsysport.c treewide: replace dev->trans_start update with helper 2016-05-04 14:16:49 -04:00
bcmsysport.h net: systemport: Pre-calculate and utilize cb->bd_addr 2015-05-30 23:51:09 -07:00
bgmac.c bgmac: reset & enable Ethernet core before using it 2016-04-14 17:15:55 -04:00
bgmac.h bgmac: fix MAC soft-reset bit for corerev > 4 2016-04-14 21:17:14 -04:00
bnx2.c BNX2: free temp_stats_blk on error path 2015-10-12 19:33:46 -07:00
bnx2.h BNX2: fix a Null Pointer for stats_blk 2015-10-11 05:06:21 -07:00
bnx2_fw.h bnx2-cnic: Driver Rebranding Changes 2015-02-20 15:46:49 -05:00
cnic.c cnic: call cp->stop_hw() in cnic_start_hw() on allocation failure 2016-05-06 15:44:54 -04:00
cnic.h cnic: Rebranding cnic driver. 2014-06-25 16:27:27 -07:00
cnic_defs.h cnic: Rebranding cnic driver. 2014-06-25 16:27:27 -07:00
cnic_if.h cnic: Add the interfaces to get FC-NPIV table. 2015-08-06 21:54:12 -07:00
sb1250-mac.c treewide: replace dev->trans_start update with helper 2016-05-04 14:16:49 -04:00
tg3.c treewide: replace dev->trans_start update with helper 2016-05-04 14:16:49 -04:00
tg3.h mdio: Move allocation of interrupts into core 2016-01-07 14:31:26 -05:00