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    [from the cache]
©2003-2011 Jasper Spaans