public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* hotplug e1000 failed after 32 times
@ 2004-09-17  4:53 Li Shaohua
  2004-09-17  5:14 ` Andrew Morton
  0 siblings, 1 reply; 14+ messages in thread
From: Li Shaohua @ 2004-09-17  4:53 UTC (permalink / raw)
  To: Andrew Morton; +Cc: lkml

[-- Attachment #1: Type: text/plain, Size: 3541 bytes --]

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);
+}


[-- Attachment #2: e1000.patch --]
[-- Type: text/x-patch, Size: 3055 bytes --]

===== 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);
+}

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2004-09-20  4:42 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-17  4:53 hotplug e1000 failed after 32 times Li Shaohua
2004-09-17  5:14 ` Andrew Morton
2004-09-17  5:48   ` Li Shaohua
2004-09-17  9:05   ` Li Shaohua
2004-09-17 23:19     ` Andrew Morton
2004-09-17 23:34       ` Jeff Garzik
2004-09-19 16:04         ` Jonathan Lundell
2004-09-19 16:50           ` Dr. David Alan Gilbert
2004-09-20  0:30             ` Jonathan Lundell
2004-09-20  0:51         ` Li Shaohua
2004-09-20  2:55           ` Jeff Garzik
2004-09-20  4:15             ` Chris Leech
2004-09-20  4:35               ` Li Shaohua
2004-09-17  9:06   ` Li Shaohua

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox