Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

BNX2: fix a Null Pointer for stats_blk

we have two processes to do:
P1#: ifconfig eth0 down; which will call bnx2_close, then will
, and set Null to stats_blk
P2#: ifconfig eth0; which will call bnx2_get_stats64, it will
use stats_blk.
In one case:
--P1#-- --P2#--
stats_blk(no null)
bnx2_free_mem
->bp->stats_blk = NULL
GET_64BIT_NET_STATS

then it will cause 'NULL Pointer' Problem.
it is as well with 'ethtool -S ethx'.

Allocate the statistics block at probe time so that this problem is
impossible

Signed-off-by: Wang Weidong <wangweidong1@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

wangweidong and committed by
David S. Miller
8fae307c e446f9df

+53 -27
+52 -27
drivers/net/ethernet/broadcom/bnx2.c
··· 813 813 } 814 814 815 815 static void 816 + bnx2_free_stats_blk(struct net_device *dev) 817 + { 818 + struct bnx2 *bp = netdev_priv(dev); 819 + 820 + if (bp->status_blk) { 821 + dma_free_coherent(&bp->pdev->dev, bp->status_stats_size, 822 + bp->status_blk, 823 + bp->status_blk_mapping); 824 + bp->status_blk = NULL; 825 + bp->stats_blk = NULL; 826 + } 827 + } 828 + 829 + static int 830 + bnx2_alloc_stats_blk(struct net_device *dev) 831 + { 832 + int status_blk_size; 833 + void *status_blk; 834 + struct bnx2 *bp = netdev_priv(dev); 835 + 836 + /* Combine status and statistics blocks into one allocation. */ 837 + status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block)); 838 + if (bp->flags & BNX2_FLAG_MSIX_CAP) 839 + status_blk_size = L1_CACHE_ALIGN(BNX2_MAX_MSIX_HW_VEC * 840 + BNX2_SBLK_MSIX_ALIGN_SIZE); 841 + bp->status_stats_size = status_blk_size + 842 + sizeof(struct statistics_block); 843 + status_blk = dma_zalloc_coherent(&bp->pdev->dev, bp->status_stats_size, 844 + &bp->status_blk_mapping, GFP_KERNEL); 845 + if (status_blk == NULL) 846 + return -ENOMEM; 847 + 848 + bp->status_blk = status_blk; 849 + bp->stats_blk = status_blk + status_blk_size; 850 + bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size; 851 + 852 + return 0; 853 + } 854 + 855 + static void 816 856 bnx2_free_mem(struct bnx2 *bp) 817 857 { 818 858 int i; ··· 869 829 bp->ctx_blk[i] = NULL; 870 830 } 871 831 } 872 - if (bnapi->status_blk.msi) { 873 - dma_free_coherent(&bp->pdev->dev, bp->status_stats_size, 874 - bnapi->status_blk.msi, 875 - bp->status_blk_mapping); 832 + 833 + if (bnapi->status_blk.msi) 876 834 bnapi->status_blk.msi = NULL; 877 - bp->stats_blk = NULL; 878 - } 879 835 } 880 836 881 837 static int 882 838 bnx2_alloc_mem(struct bnx2 *bp) 883 839 { 884 - int i, status_blk_size, err; 840 + int i, err; 885 841 struct bnx2_napi *bnapi; 886 - void *status_blk; 887 - 888 - /* Combine status and statistics blocks into one allocation. */ 889 - status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block)); 890 - if (bp->flags & BNX2_FLAG_MSIX_CAP) 891 - status_blk_size = L1_CACHE_ALIGN(BNX2_MAX_MSIX_HW_VEC * 892 - BNX2_SBLK_MSIX_ALIGN_SIZE); 893 - bp->status_stats_size = status_blk_size + 894 - sizeof(struct statistics_block); 895 - 896 - status_blk = dma_zalloc_coherent(&bp->pdev->dev, bp->status_stats_size, 897 - &bp->status_blk_mapping, GFP_KERNEL); 898 - if (status_blk == NULL) 899 - goto alloc_mem_err; 900 842 901 843 bnapi = &bp->bnx2_napi[0]; 902 - bnapi->status_blk.msi = status_blk; 844 + bnapi->status_blk.msi = bp->status_blk; 903 845 bnapi->hw_tx_cons_ptr = 904 846 &bnapi->status_blk.msi->status_tx_quick_consumer_index0; 905 847 bnapi->hw_rx_cons_ptr = ··· 892 870 893 871 bnapi = &bp->bnx2_napi[i]; 894 872 895 - sblk = (status_blk + BNX2_SBLK_MSIX_ALIGN_SIZE * i); 873 + sblk = (bp->status_blk + BNX2_SBLK_MSIX_ALIGN_SIZE * i); 896 874 bnapi->status_blk.msix = sblk; 897 875 bnapi->hw_tx_cons_ptr = 898 876 &sblk->status_tx_quick_consumer_index; ··· 901 879 bnapi->int_num = i << 24; 902 880 } 903 881 } 904 - 905 - bp->stats_blk = status_blk + status_blk_size; 906 - 907 - bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size; 908 882 909 883 if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { 910 884 bp->ctx_pages = 0x2000 / BNX2_PAGE_SIZE; ··· 8348 8330 8349 8331 bp->phy_addr = 1; 8350 8332 8333 + /* allocate stats_blk */ 8334 + rc = bnx2_alloc_stats_blk(dev); 8335 + if (rc) 8336 + goto err_out_unmap; 8337 + 8351 8338 /* Disable WOL support if we are running on a SERDES chip. */ 8352 8339 if (BNX2_CHIP(bp) == BNX2_CHIP_5709) 8353 8340 bnx2_get_5709_media(bp); ··· 8609 8586 pci_release_regions(pdev); 8610 8587 pci_disable_device(pdev); 8611 8588 err_free: 8589 + bnx2_free_stats_blk(dev); 8612 8590 free_netdev(dev); 8613 8591 return rc; 8614 8592 } ··· 8627 8603 8628 8604 pci_iounmap(bp->pdev, bp->regview); 8629 8605 8606 + bnx2_free_stats_blk(dev); 8630 8607 kfree(bp->temp_stats_blk); 8631 8608 8632 8609 if (bp->flags & BNX2_FLAG_AER_ENABLED) {
+1
drivers/net/ethernet/broadcom/bnx2.h
··· 6928 6928 6929 6929 dma_addr_t status_blk_mapping; 6930 6930 6931 + void *status_blk; 6931 6932 struct statistics_block *stats_blk; 6932 6933 struct statistics_block *temp_stats_blk; 6933 6934 dma_addr_t stats_blk_mapping;