lkml.org 
[lkml]   [2004]   [Sep]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patches in this message
    /
    Subjecthotplug e1000 failed after 32 times
    From
    Date
    Hi,
    I'm testing a hotplug driver. In my test, I will hot add/remove an e1000
    NIC frequently. The result is my hot add failed after 32 times hotadd.
    After looking at the code of e1000 driver, I found
    e1000_adapter->bd_number has maxium limitation of 32, and it increased
    one every hot add. Looks like the remove driver routine didn't free the
    'bd_number', so hot add failed after 32 times. Below patch fixes this
    issue.

    thanks,
    Shaohua

    Signed-off-by Li Shaohua <shaohua.li@intel.com>
    ===== drivers/net/e1000/e1000_main.c 1.134 vs edited =====
    --- 1.134/drivers/net/e1000/e1000_main.c 2004-09-13 07:52:48 +08:00
    +++ edited/drivers/net/e1000/e1000_main.c 2004-09-17 12:01:08 +08:00
    @@ -180,6 +180,8 @@ struct notifier_block e1000_notifier_reb
    /* Exported from other modules */

    extern void e1000_check_options(struct e1000_adapter *adapter);
    +extern int e1000_alloc_bd_number(void);
    +extern void e1000_free_bd_number(int);

    static struct pci_driver e1000_driver = {
    .name = e1000_driver_name,
    @@ -380,7 +382,6 @@ e1000_probe(struct pci_dev *pdev,
    {
    struct net_device *netdev;
    struct e1000_adapter *adapter;
    - static int cards_found = 0;
    unsigned long mmio_start;
    int mmio_len;
    int pci_using_dac;
    @@ -471,7 +472,7 @@ e1000_probe(struct pci_dev *pdev,
    netdev->mem_end = mmio_start + mmio_len;
    netdev->base_addr = adapter->hw.io_base;

    - adapter->bd_number = cards_found;
    + adapter->bd_number = e1000_alloc_bd_number();;

    /* setup the private structure */

    @@ -590,13 +591,13 @@ e1000_probe(struct pci_dev *pdev,
    if((err = register_netdevice(netdev)))
    goto err_register;

    - cards_found++;
    rtnl_unlock();
    return 0;

    err_register:
    err_sw_init:
    err_eeprom:
    + e1000_free_bd_number(adapter->bd_number);
    iounmap(adapter->hw.hw_addr);
    err_ioremap:
    err_free_unlock:
    @@ -638,6 +639,7 @@ e1000_remove(struct pci_dev *pdev)
    e1000_phy_hw_reset(&adapter->hw);

    iounmap(adapter->hw.hw_addr);
    + e1000_free_bd_number(adapter->bd_number);
    pci_release_regions(pdev);

    free_netdev(netdev);
    ===== drivers/net/e1000/e1000_param.c 1.31 vs edited =====
    --- 1.31/drivers/net/e1000/e1000_param.c 2004-08-29 06:55:39 +08:00
    +++ edited/drivers/net/e1000/e1000_param.c 2004-09-17 12:37:41 +08:00
    @@ -56,7 +56,7 @@
    */

    #define E1000_PARAM(X, S) \
    -static const int __devinitdata X[E1000_MAX_NIC + 1] = E1000_PARAM_INIT;
    \
    +static int __devinitdata X[E1000_MAX_NIC + 1] = E1000_PARAM_INIT; \
    MODULE_PARM(X, "1-" __MODULE_STRING(E1000_MAX_NIC) "i"); \
    MODULE_PARM_DESC(X, S);

    @@ -703,3 +703,40 @@ e1000_check_copper_options(struct e1000_
    }
    }

    +#define BD_NUMBER_BITS (E1000_MAX_NIC + 1)
    +#if BITS_PER_LONG > BD_NUMBER_BITS
    +static unsigned long bd_number_bits;
    +#else
    +static unsigned long bd_number_bits[(E1000_MAX_NIC * 2)/BITS_PER_LONG];
    +#endif
    +
    +int e1000_alloc_bd_number(void)
    +{
    + int ret;
    +
    + ret = find_first_zero_bit(&bd_number_bits, BD_NUMBER_BITS);
    + if (ret >= E1000_MAX_NIC)
    + ret = E1000_MAX_NIC;
    + __set_bit(ret, &bd_number_bits);
    + return ret;
    +}
    +
    +void e1000_free_bd_number(int bd_number)
    +{
    + if ((bd_number < 0) || (bd_number > E1000_MAX_NIC) ||
    + !test_bit(bd_number, &bd_number_bits))
    + return;
    + TxDescriptors[bd_number] =
    + RxDescriptors[bd_number] =
    + Speed[bd_number] =
    + Duplex[bd_number] =
    + AutoNeg[bd_number] =
    + FlowControl[bd_number] =
    + XsumRX[bd_number] =
    + TxIntDelay[bd_number] =
    + TxAbsIntDelay[bd_number] =
    + RxIntDelay[bd_number] =
    + RxAbsIntDelay[bd_number] =
    + InterruptThrottleRate[bd_number] = OPTION_UNSET;
    + __clear_bit(bd_number, &bd_number_bits);
    +}
    ===== drivers/net/e1000/e1000_main.c 1.134 vs edited =====
    --- 1.134/drivers/net/e1000/e1000_main.c 2004-09-13 07:52:48 +08:00
    +++ edited/drivers/net/e1000/e1000_main.c 2004-09-17 12:01:08 +08:00
    @@ -180,6 +180,8 @@ struct notifier_block e1000_notifier_reb
    /* Exported from other modules */

    extern void e1000_check_options(struct e1000_adapter *adapter);
    +extern int e1000_alloc_bd_number(void);
    +extern void e1000_free_bd_number(int);

    static struct pci_driver e1000_driver = {
    .name = e1000_driver_name,
    @@ -380,7 +382,6 @@ e1000_probe(struct pci_dev *pdev,
    {
    struct net_device *netdev;
    struct e1000_adapter *adapter;
    - static int cards_found = 0;
    unsigned long mmio_start;
    int mmio_len;
    int pci_using_dac;
    @@ -471,7 +472,7 @@ e1000_probe(struct pci_dev *pdev,
    netdev->mem_end = mmio_start + mmio_len;
    netdev->base_addr = adapter->hw.io_base;

    - adapter->bd_number = cards_found;
    + adapter->bd_number = e1000_alloc_bd_number();;

    /* setup the private structure */

    @@ -590,13 +591,13 @@ e1000_probe(struct pci_dev *pdev,
    if((err = register_netdevice(netdev)))
    goto err_register;

    - cards_found++;
    rtnl_unlock();
    return 0;

    err_register:
    err_sw_init:
    err_eeprom:
    + e1000_free_bd_number(adapter->bd_number);
    iounmap(adapter->hw.hw_addr);
    err_ioremap:
    err_free_unlock:
    @@ -638,6 +639,7 @@ e1000_remove(struct pci_dev *pdev)
    e1000_phy_hw_reset(&adapter->hw);

    iounmap(adapter->hw.hw_addr);
    + e1000_free_bd_number(adapter->bd_number);
    pci_release_regions(pdev);

    free_netdev(netdev);
    ===== drivers/net/e1000/e1000_param.c 1.31 vs edited =====
    --- 1.31/drivers/net/e1000/e1000_param.c 2004-08-29 06:55:39 +08:00
    +++ edited/drivers/net/e1000/e1000_param.c 2004-09-17 12:37:41 +08:00
    @@ -56,7 +56,7 @@
    */

    #define E1000_PARAM(X, S) \
    -static const int __devinitdata X[E1000_MAX_NIC + 1] = E1000_PARAM_INIT; \
    +static int __devinitdata X[E1000_MAX_NIC + 1] = E1000_PARAM_INIT; \
    MODULE_PARM(X, "1-" __MODULE_STRING(E1000_MAX_NIC) "i"); \
    MODULE_PARM_DESC(X, S);

    @@ -703,3 +703,40 @@ e1000_check_copper_options(struct e1000_
    }
    }

    +#define BD_NUMBER_BITS (E1000_MAX_NIC + 1)
    +#if BITS_PER_LONG > BD_NUMBER_BITS
    +static unsigned long bd_number_bits;
    +#else
    +static unsigned long bd_number_bits[(E1000_MAX_NIC * 2)/BITS_PER_LONG];
    +#endif
    +
    +int e1000_alloc_bd_number(void)
    +{
    + int ret;
    +
    + ret = find_first_zero_bit(&bd_number_bits, BD_NUMBER_BITS);
    + if (ret >= E1000_MAX_NIC)
    + ret = E1000_MAX_NIC;
    + __set_bit(ret, &bd_number_bits);
    + return ret;
    +}
    +
    +void e1000_free_bd_number(int bd_number)
    +{
    + if ((bd_number < 0) || (bd_number > E1000_MAX_NIC) ||
    + !test_bit(bd_number, &bd_number_bits))
    + return;
    + TxDescriptors[bd_number] =
    + RxDescriptors[bd_number] =
    + Speed[bd_number] =
    + Duplex[bd_number] =
    + AutoNeg[bd_number] =
    + FlowControl[bd_number] =
    + XsumRX[bd_number] =
    + TxIntDelay[bd_number] =
    + TxAbsIntDelay[bd_number] =
    + RxIntDelay[bd_number] =
    + RxAbsIntDelay[bd_number] =
    + InterruptThrottleRate[bd_number] = OPTION_UNSET;
    + __clear_bit(bd_number, &bd_number_bits);
    +}
    \
     
     \ /
      Last update: 2005-03-22 14:06    [W:0.035 / U:60.352 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site