Skip to contentSkip to conversation

PCI legacy I/O port free driver - Making Intel e1000 driver legacy I/O port free

PATCH In review Tomohiro Kusumi 3 participants 6 messages May 10, 2007 – May 24, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 PCI legacy I/O port free driver - Making Intel e1000 driver legacy I/O port free

Hi

As you can see in the "10. pci_enable_device_bars() and Legacy I/O Port space" of the Documentation/pci.txt, the latest kernel has interfaces for PCI device drivers to tell the kernel which resource the driver want to use, ex. I/O port or MMIO.

I've made a patch which makes Intel e1000 driver legacy I/O port free by using the PCI core changes I mentioned above. The Intel e1000 driver can handle some of its devices without using I/O port. So this patch changes the driver not to enable/request I/O port region depending on the device id.

As a result, the driver can handle its device even when there are huge number of PCI devices being used on the system and no I/O port region assigned to the device.

Tomohiro Kusumi

---
 e1000.h      |    6 +-
 e1000_main.c |  152 +++++++++++++++++++++++++++++++----------------------------
 2 files changed, 86 insertions(+), 72 deletions(-)
drivers/net/e1000/e1000.h +4 -2
diff -uprN linux-2.6.21.orig/drivers/net/e1000/e1000.h linux-2.6.21/drivers/net/e1000/e1000.h
@@ -74,8 +74,9 @@
 #define BAR_1		1
 #define BAR_5		5
 
-#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
-	PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
+#define E1000_USE_IOPORT       (1 << 0)
+#define INTEL_E1000_ETHERNET_DEVICE(device_id, flags) {\
+       PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id), .driver_data = flags}
 
 struct e1000_adapter;
 
@@ -347,6 +348,7 @@ struct e1000_adapter {
 	boolean_t quad_port_a;
 	unsigned long flags;
 	uint32_t eeprom_wol;
+	int bars;               /* BARs to be enabled */
 };
 
 enum e1000_state_t {
drivers/net/e1000/e1000_main.c +82 -70

200 lines not on this page · raw message

#1 lore raw
Quoted 13 lines · Tomohiro Kusumi

Hi

As you can see in the "10. pci_enable_device_bars() and Legacy I/O Port space" of the Documentation/pci.txt, the latest kernel has interfaces for PCI device drivers to tell the kernel which resource the driver want to use, ex. I/O port or MMIO.

I've made a patch which makes Intel e1000 driver legacy I/O port free by using the PCI core changes I mentioned above. The Intel e1000 driver can handle some of its devices without using I/O port. So this patch changes the driver not to enable/request I/O port region depending on the device id.

Quoted 3 lines

As a result, the driver can handle its device even when there are huge number of PCI devices being used on the system and no I/O port region assigned to the device.

Tomohiro,

I'm ok with the bottom part of the patch, but I do not like the modification of the pci device ID table in this way. As Arjan van der Ven previously commented as well, this makes it hard for future device ID's to be bound to the driver.

On top of that, there is no logical correlation between the mapping and chipsets, so a lot of information is lost in that table. It really does not show which _chipsets_ support this functionality.

I think if we want to work with this, we need some way of mapping the device ID's back to chipsets, and enable the feature on that basis.

Auke

Quoted 244 lines

Tomohiro Kusumi

---
 e1000.h      |    6 +-
 e1000_main.c |  152 +++++++++++++++++++++++++++++++----------------------------
 2 files changed, 86 insertions(+), 72 deletions(-)

diff -uprN linux-2.6.21.orig/drivers/net/e1000/e1000.h linux-2.6.21/drivers/net/e1000/e1000.h

drivers/net/e1000/e1000.h +4 -2
@@ -74,8 +74,9 @@
 #define BAR_1		1
 #define BAR_5		5
 
-#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
-	PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
+#define E1000_USE_IOPORT       (1 << 0)
+#define INTEL_E1000_ETHERNET_DEVICE(device_id, flags) {\
+       PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id), .driver_data = flags}
 
 struct e1000_adapter;
 
@@ -347,6 +348,7 @@ struct e1000_adapter {
 	boolean_t quad_port_a;
 	unsigned long flags;
 	uint32_t eeprom_wol;
+	int bars;               /* BARs to be enabled */
 };
 
 enum e1000_state_t {

diff -uprN linux-2.6.21.orig/drivers/net/e1000/e1000_main.c linux-2.6.21/drivers/net/e1000/e1000_main.c

drivers/net/e1000/e1000_main.c +82 -70
@@ -48,65 +48,65 @@ static char e1000_copyright[] = "Copyrig
  *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
  */
 static struct pci_device_id e1000_pci_tbl[] = {
-	INTEL_E1000_ETHERNET_DEVICE(0x1000),
-	INTEL_E1000_ETHERNET_DEVICE(0x1001),
-	INTEL_E1000_ETHERNET_DEVICE(0x1004),
-	INTEL_E1000_ETHERNET_DEVICE(0x1008),
-	INTEL_E1000_ETHERNET_DEVICE(0x1009),
-	INTEL_E1000_ETHERNET_DEVICE(0x100C),
-	INTEL_E1000_ETHERNET_DEVICE(0x100D),
-	INTEL_E1000_ETHERNET_DEVICE(0x100E),
-	INTEL_E1000_ETHERNET_DEVICE(0x100F),
-	INTEL_E1000_ETHERNET_DEVICE(0x1010),
-	INTEL_E1000_ETHERNET_DEVICE(0x1011),
-	INTEL_E1000_ETHERNET_DEVICE(0x1012),
-	INTEL_E1000_ETHERNET_DEVICE(0x1013),
-	INTEL_E1000_ETHERNET_DEVICE(0x1014),
-	INTEL_E1000_ETHERNET_DEVICE(0x1015),
-	INTEL_E1000_ETHERNET_DEVICE(0x1016),
-	INTEL_E1000_ETHERNET_DEVICE(0x1017),
-	INTEL_E1000_ETHERNET_DEVICE(0x1018),
-	INTEL_E1000_ETHERNET_DEVICE(0x1019),
-	INTEL_E1000_ETHERNET_DEVICE(0x101A),
-	INTEL_E1000_ETHERNET_DEVICE(0x101D),
-	INTEL_E1000_ETHERNET_DEVICE(0x101E),
-	INTEL_E1000_ETHERNET_DEVICE(0x1026),
-	INTEL_E1000_ETHERNET_DEVICE(0x1027),
-	INTEL_E1000_ETHERNET_DEVICE(0x1028),
-	INTEL_E1000_ETHERNET_DEVICE(0x1049),
-	INTEL_E1000_ETHERNET_DEVICE(0x104A),
-	INTEL_E1000_ETHERNET_DEVICE(0x104B),
-	INTEL_E1000_ETHERNET_DEVICE(0x104C),
-	INTEL_E1000_ETHERNET_DEVICE(0x104D),
-	INTEL_E1000_ETHERNET_DEVICE(0x105E),
-	INTEL_E1000_ETHERNET_DEVICE(0x105F),
-	INTEL_E1000_ETHERNET_DEVICE(0x1060),
-	INTEL_E1000_ETHERNET_DEVICE(0x1075),
-	INTEL_E1000_ETHERNET_DEVICE(0x1076),
-	INTEL_E1000_ETHERNET_DEVICE(0x1077),
-	INTEL_E1000_ETHERNET_DEVICE(0x1078),
-	INTEL_E1000_ETHERNET_DEVICE(0x1079),
-	INTEL_E1000_ETHERNET_DEVICE(0x107A),
-	INTEL_E1000_ETHERNET_DEVICE(0x107B),
-	INTEL_E1000_ETHERNET_DEVICE(0x107C),
-	INTEL_E1000_ETHERNET_DEVICE(0x107D),
-	INTEL_E1000_ETHERNET_DEVICE(0x107E),
-	INTEL_E1000_ETHERNET_DEVICE(0x107F),
-	INTEL_E1000_ETHERNET_DEVICE(0x108A),
-	INTEL_E1000_ETHERNET_DEVICE(0x108B),
-	INTEL_E1000_ETHERNET_DEVICE(0x108C),
-	INTEL_E1000_ETHERNET_DEVICE(0x1096),
-	INTEL_E1000_ETHERNET_DEVICE(0x1098),
-	INTEL_E1000_ETHERNET_DEVICE(0x1099),
-	INTEL_E1000_ETHERNET_DEVICE(0x109A),
-	INTEL_E1000_ETHERNET_DEVICE(0x10A4),
-	INTEL_E1000_ETHERNET_DEVICE(0x10B5),
-	INTEL_E1000_ETHERNET_DEVICE(0x10B9),
-	INTEL_E1000_ETHERNET_DEVICE(0x10BA),
-	INTEL_E1000_ETHERNET_DEVICE(0x10BB),
-	INTEL_E1000_ETHERNET_DEVICE(0x10BC),
-	INTEL_E1000_ETHERNET_DEVICE(0x10C4),
-	INTEL_E1000_ETHERNET_DEVICE(0x10C5),
+	INTEL_E1000_ETHERNET_DEVICE(0x1000, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1001, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1004, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1008, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1009, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x100C, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x100D, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x100E, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x100F, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1010, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1011, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1012, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1013, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1014, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1015, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1016, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1017, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1018, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1019, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x101A, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x101D, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x101E, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1026, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1027, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1028, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1049, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x104A, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x104B, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x104C, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x104D, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x105E, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x105F, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1060, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1075, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1076, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1077, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1078, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x1079, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x107A, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x107B, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x107C, E1000_USE_IOPORT),
+	INTEL_E1000_ETHERNET_DEVICE(0x107D, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x107E, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x107F, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x108A, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x108B, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x108C, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1096, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1098, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x1099, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x109A, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x10A4, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x10B5, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x10B9, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x10BA, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x10BB, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x10BC, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x10C4, 0),
+	INTEL_E1000_ETHERNET_DEVICE(0x10C5, 0),
 	/* required last entry */
 	{0,}
 };
@@ -879,7 +879,14 @@ e1000_probe(struct pci_dev *pdev,
 	int i, err, pci_using_dac;
 	uint16_t eeprom_data = 0;
 	uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
-	if ((err = pci_enable_device(pdev)))
+	int bars;
+
+	if (ent->driver_data & E1000_USE_IOPORT)
+		bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
+	else
+		bars = pci_select_bars(pdev, IORESOURCE_MEM);
+
+	if ((err = pci_enable_device_bars(pdev, bars)))
 		return err;
 
 	if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
@@ -894,7 +901,8 @@ e1000_probe(struct pci_dev *pdev,
 		pci_using_dac = 0;
 	}
 
-	if ((err = pci_request_regions(pdev, e1000_driver_name)))
+	err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
+	if (err)
 		goto err_pci_reg;
 
 	pci_set_master(pdev);
@@ -913,6 +921,7 @@ e1000_probe(struct pci_dev *pdev,
 	adapter->pdev = pdev;
 	adapter->hw.back = adapter;
 	adapter->msg_enable = (1 << debug) - 1;
+	adapter->bars = bars;
 
 	mmio_start = pci_resource_start(pdev, BAR_0);
 	mmio_len = pci_resource_len(pdev, BAR_0);
@@ -922,12 +931,15 @@ e1000_probe(struct pci_dev *pdev,
 	if (!adapter->hw.hw_addr)
 		goto err_ioremap;
 
-	for (i = BAR_1; i <= BAR_5; i++) {
-		if (pci_resource_len(pdev, i) == 0)
-			continue;
-		if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
-			adapter->hw.io_base = pci_resource_start(pdev, i);
-			break;
+	if (ent->driver_data & E1000_USE_IOPORT) {
+		for (i = BAR_1; i <= BAR_5; i++) {
+			if (pci_resource_len(pdev, i) == 0)
+				continue;
+			if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+				adapter->hw.io_base =
+					pci_resource_start(pdev, i);
+				break;
+			}
 		}
 	}
 
@@ -1190,7 +1202,7 @@ err_sw_init:
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
-	pci_release_regions(pdev);
+	pci_release_selected_regions(pdev, bars);
 err_pci_reg:
 err_dma:
 	pci_disable_device(pdev);
@@ -1242,7 +1254,7 @@ e1000_remove(struct pci_dev *pdev)
 	iounmap(adapter->hw.hw_addr);
 	if (adapter->hw.flash_address)
 		iounmap(adapter->hw.flash_address);
-	pci_release_regions(pdev);
+	pci_release_selected_regions(pdev, adapter->bars);
 
 	free_netdev(netdev);
 
@@ -5172,7 +5184,7 @@ e1000_resume(struct pci_dev *pdev)
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
-	if ((err = pci_enable_device(pdev))) {
+	if ((err = pci_enable_device_bars(pdev, adapter->bars))) {
 		printk(KERN_ERR "e1000: Cannot enable PCI device from suspend\n");
 		return err;
 	}
#2 lore raw

Dear Auke

Quoted 4 lines

I'm ok with the bottom part of the patch, but I do not like the modification of the pci device ID table in this way. As Arjan van der Ven previously commented as well, this makes it hard for future device ID's to be bound to the driver.

I googled the previous comment by Arjan. Now I understand that the patch makes it difficult to add PCI ID's to the driver at runtime.

Quoted 4 lines

On top of that, there is no logical correlation between the mapping and chipsets, so a lot of information is lost in that table. It really does not show which _chipsets_ support this functionality.

Thanks for pointing out the problem, but I can't quite understand what you are trying to say. What do you mean by the chipset? Are you talking about the chipset of the NIC? or the South bridge? I'd be glad if you can explain it to me.

Tomohiro Kusumi

Quoted 280 lines · Auke
Quoted 13 lines · Tomohiro Kusumi

Hi

As you can see in the "10. pci_enable_device_bars() and Legacy I/O Port space" of the Documentation/pci.txt, the latest kernel has interfaces for PCI device drivers to tell the kernel which resource the driver want to use, ex. I/O port or MMIO.

I've made a patch which makes Intel e1000 driver legacy I/O port free by using the PCI core changes I mentioned above. The Intel e1000 driver can handle some of its devices without using I/O port. So this patch changes the driver not to enable/request I/O port region depending on the device id.

Quoted 3 lines

As a result, the driver can handle its device even when there are huge number of PCI devices being used on the system and no I/O port region assigned to the device.

Tomohiro,

I'm ok with the bottom part of the patch, but I do not like the modification of the pci device ID table in this way. As Arjan van der Ven previously commented as well, this makes it hard for future device ID's to be bound to the driver.

On top of that, there is no logical correlation between the mapping and chipsets, so a lot of information is lost in that table. It really does not show which _chipsets_ support this functionality.

I think if we want to work with this, we need some way of mapping the device ID's back to chipsets, and enable the feature on that basis.

Auke

Quoted 250 lines

Tomohiro Kusumi

---
 e1000.h      |    6 +-
 e1000_main.c |  152 
+++++++++++++++++++++++++++++++----------------------------
 2 files changed, 86 insertions(+), 72 deletions(-)

diff -uprN linux-2.6.21.orig/drivers/net/e1000/e1000.h linux-2.6.21/drivers/net/e1000/e1000.h
--- linux-2.6.21.orig/drivers/net/e1000/e1000.h 2007-05-09
18:02:26.000000000 +0900
+++ linux-2.6.21/drivers/net/e1000/e1000.h 2007-05-09
18:02:59.000000000 +0900

drivers/net/e1000/e1000.h +4 -2
@@ -74,8 +74,9 @@
 #define BAR_1        1
 #define BAR_5        5
 
-#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
-    PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
+#define E1000_USE_IOPORT       (1 << 0)
+#define INTEL_E1000_ETHERNET_DEVICE(device_id, flags) {\
+       PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id), .driver_data = flags}
 
 struct e1000_adapter;
 
@@ -347,6 +348,7 @@ struct e1000_adapter {
     boolean_t quad_port_a;
     unsigned long flags;
     uint32_t eeprom_wol;
+    int bars;               /* BARs to be enabled */
 };
 
 enum e1000_state_t {

diff -uprN linux-2.6.21.orig/drivers/net/e1000/e1000_main.c linux-2.6.21/drivers/net/e1000/e1000_main.c
--- linux-2.6.21.orig/drivers/net/e1000/e1000_main.c 2007-05-09
18:02:27.000000000 +0900
+++ linux-2.6.21/drivers/net/e1000/e1000_main.c 2007-05-09
18:03:00.000000000 +0900

drivers/net/e1000/e1000_main.c +82 -70
@@ -48,65 +48,65 @@ static char e1000_copyright[] = "Copyrig
  *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
  */
 static struct pci_device_id e1000_pci_tbl[] = {
-    INTEL_E1000_ETHERNET_DEVICE(0x1000),
-    INTEL_E1000_ETHERNET_DEVICE(0x1001),
-    INTEL_E1000_ETHERNET_DEVICE(0x1004),
-    INTEL_E1000_ETHERNET_DEVICE(0x1008),
-    INTEL_E1000_ETHERNET_DEVICE(0x1009),
-    INTEL_E1000_ETHERNET_DEVICE(0x100C),
-    INTEL_E1000_ETHERNET_DEVICE(0x100D),
-    INTEL_E1000_ETHERNET_DEVICE(0x100E),
-    INTEL_E1000_ETHERNET_DEVICE(0x100F),
-    INTEL_E1000_ETHERNET_DEVICE(0x1010),
-    INTEL_E1000_ETHERNET_DEVICE(0x1011),
-    INTEL_E1000_ETHERNET_DEVICE(0x1012),
-    INTEL_E1000_ETHERNET_DEVICE(0x1013),
-    INTEL_E1000_ETHERNET_DEVICE(0x1014),
-    INTEL_E1000_ETHERNET_DEVICE(0x1015),
-    INTEL_E1000_ETHERNET_DEVICE(0x1016),
-    INTEL_E1000_ETHERNET_DEVICE(0x1017),
-    INTEL_E1000_ETHERNET_DEVICE(0x1018),
-    INTEL_E1000_ETHERNET_DEVICE(0x1019),
-    INTEL_E1000_ETHERNET_DEVICE(0x101A),
-    INTEL_E1000_ETHERNET_DEVICE(0x101D),
-    INTEL_E1000_ETHERNET_DEVICE(0x101E),
-    INTEL_E1000_ETHERNET_DEVICE(0x1026),
-    INTEL_E1000_ETHERNET_DEVICE(0x1027),
-    INTEL_E1000_ETHERNET_DEVICE(0x1028),
-    INTEL_E1000_ETHERNET_DEVICE(0x1049),
-    INTEL_E1000_ETHERNET_DEVICE(0x104A),
-    INTEL_E1000_ETHERNET_DEVICE(0x104B),
-    INTEL_E1000_ETHERNET_DEVICE(0x104C),
-    INTEL_E1000_ETHERNET_DEVICE(0x104D),
-    INTEL_E1000_ETHERNET_DEVICE(0x105E),
-    INTEL_E1000_ETHERNET_DEVICE(0x105F),
-    INTEL_E1000_ETHERNET_DEVICE(0x1060),
-    INTEL_E1000_ETHERNET_DEVICE(0x1075),
-    INTEL_E1000_ETHERNET_DEVICE(0x1076),
-    INTEL_E1000_ETHERNET_DEVICE(0x1077),
-    INTEL_E1000_ETHERNET_DEVICE(0x1078),
-    INTEL_E1000_ETHERNET_DEVICE(0x1079),
-    INTEL_E1000_ETHERNET_DEVICE(0x107A),
-    INTEL_E1000_ETHERNET_DEVICE(0x107B),
-    INTEL_E1000_ETHERNET_DEVICE(0x107C),
-    INTEL_E1000_ETHERNET_DEVICE(0x107D),
-    INTEL_E1000_ETHERNET_DEVICE(0x107E),
-    INTEL_E1000_ETHERNET_DEVICE(0x107F),
-    INTEL_E1000_ETHERNET_DEVICE(0x108A),
-    INTEL_E1000_ETHERNET_DEVICE(0x108B),
-    INTEL_E1000_ETHERNET_DEVICE(0x108C),
-    INTEL_E1000_ETHERNET_DEVICE(0x1096),
-    INTEL_E1000_ETHERNET_DEVICE(0x1098),
-    INTEL_E1000_ETHERNET_DEVICE(0x1099),
-    INTEL_E1000_ETHERNET_DEVICE(0x109A),
-    INTEL_E1000_ETHERNET_DEVICE(0x10A4),
-    INTEL_E1000_ETHERNET_DEVICE(0x10B5),
-    INTEL_E1000_ETHERNET_DEVICE(0x10B9),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BA),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BB),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BC),
-    INTEL_E1000_ETHERNET_DEVICE(0x10C4),
-    INTEL_E1000_ETHERNET_DEVICE(0x10C5),
+    INTEL_E1000_ETHERNET_DEVICE(0x1000, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1001, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1004, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1008, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1009, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100C, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100D, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100E, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100F, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1010, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1011, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1012, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1013, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1014, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1015, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1016, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1017, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1018, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1019, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x101A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x101D, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x101E, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1026, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1027, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1028, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1049, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104C, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104D, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x105E, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x105F, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1060, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1075, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1076, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1077, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1078, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1079, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107C, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x107D, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107E, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107F, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108C, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1096, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1098, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1099, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x109A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10A4, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10B5, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10B9, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BA, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BB, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BC, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10C4, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10C5, 0),
     /* required last entry */
     {0,}
 };
@@ -879,7 +879,14 @@ e1000_probe(struct pci_dev *pdev,
     int i, err, pci_using_dac;
     uint16_t eeprom_data = 0;
     uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
-    if ((err = pci_enable_device(pdev)))
+    int bars;
+
+    if (ent->driver_data & E1000_USE_IOPORT)
+        bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
+    else
+        bars = pci_select_bars(pdev, IORESOURCE_MEM);
+
+    if ((err = pci_enable_device_bars(pdev, bars)))
         return err;
 
     if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
@@ -894,7 +901,8 @@ e1000_probe(struct pci_dev *pdev,
         pci_using_dac = 0;
     }
 
-    if ((err = pci_request_regions(pdev, e1000_driver_name)))
+    err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
+    if (err)
         goto err_pci_reg;
 
     pci_set_master(pdev);
@@ -913,6 +921,7 @@ e1000_probe(struct pci_dev *pdev,
     adapter->pdev = pdev;
     adapter->hw.back = adapter;
     adapter->msg_enable = (1 << debug) - 1;
+    adapter->bars = bars;
 
     mmio_start = pci_resource_start(pdev, BAR_0);
     mmio_len = pci_resource_len(pdev, BAR_0);
@@ -922,12 +931,15 @@ e1000_probe(struct pci_dev *pdev,
     if (!adapter->hw.hw_addr)
         goto err_ioremap;
 
-    for (i = BAR_1; i <= BAR_5; i++) {
-        if (pci_resource_len(pdev, i) == 0)
-            continue;
-        if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
-            adapter->hw.io_base = pci_resource_start(pdev, i);
-            break;
+    if (ent->driver_data & E1000_USE_IOPORT) {
+        for (i = BAR_1; i <= BAR_5; i++) {
+            if (pci_resource_len(pdev, i) == 0)
+                continue;
+            if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+                adapter->hw.io_base =
+                    pci_resource_start(pdev, i);
+                break;
+            }
         }
     }
 
@@ -1190,7 +1202,7 @@ err_sw_init:
 err_ioremap:
     free_netdev(netdev);
 err_alloc_etherdev:
-    pci_release_regions(pdev);
+    pci_release_selected_regions(pdev, bars);
 err_pci_reg:
 err_dma:
     pci_disable_device(pdev);
@@ -1242,7 +1254,7 @@ e1000_remove(struct pci_dev *pdev)
     iounmap(adapter->hw.hw_addr);
     if (adapter->hw.flash_address)
         iounmap(adapter->hw.flash_address);
-    pci_release_regions(pdev);
+    pci_release_selected_regions(pdev, adapter->bars);
 
     free_netdev(netdev);
 
@@ -5172,7 +5184,7 @@ e1000_resume(struct pci_dev *pdev)
 
     pci_set_power_state(pdev, PCI_D0);
     pci_restore_state(pdev);
-    if ((err = pci_enable_device(pdev))) {
+    if ((err = pci_enable_device_bars(pdev, adapter->bars))) {
         printk(KERN_ERR "e1000: Cannot enable PCI device from 
 suspend\n");
         return err;
     }
#3 lore raw
Quoted 16 lines · Tomohiro Kusumi

Dear Auke

Quoted 4 lines

I'm ok with the bottom part of the patch, but I do not like the modification of the pci device ID table in this way. As Arjan van der Ven previously commented as well, this makes it hard for future device ID's to be bound to the driver.

I googled the previous comment by Arjan. Now I understand that the patch makes it difficult to add PCI ID's to the driver at runtime.

Quoted 4 lines

On top of that, there is no logical correlation between the mapping and chipsets, so a lot of information is lost in that table. It really does not show which _chipsets_ support this functionality.

Quoted 4 lines

Thanks for pointing out the problem, but I can't quite understand what you are trying to say. What do you mean by the chipset? Are you talking about the chipset of the NIC? or the South bridge? I'd be glad if you can explain it to me.

perhaps my wording was poor. I was referring to the NIC chip. Since there are about 12 different physical e1000 NIC chips (and lots of different pci IDs per e1000 NIC chip), it would be best to correlate the capability of each NIC chip number to be able to work without legacy IO mode instead of providing this mapping based on the PCI device ID.

It would serve two purposes: new pci id's for a chipset of which we already know that it can work without legacy IO can automatically inherit this property from the NIC chipset properties, and new e1000 chips would automatically get a default property for this value.

I will (time permitting) try to reverse your matrix to chip numbers and see if we can add this property in a much easier way.

Auke

Quoted 282 lines

Tomohiro Kusumi

Quoted 277 lines · Auke
Quoted 13 lines · Tomohiro Kusumi

Hi

As you can see in the "10. pci_enable_device_bars() and Legacy I/O Port space" of the Documentation/pci.txt, the latest kernel has interfaces for PCI device drivers to tell the kernel which resource the driver want to use, ex. I/O port or MMIO.

I've made a patch which makes Intel e1000 driver legacy I/O port free by using the PCI core changes I mentioned above. The Intel e1000 driver can handle some of its devices without using I/O port. So this patch changes the driver not to enable/request I/O port region depending on the device id.

Quoted 3 lines

As a result, the driver can handle its device even when there are huge number of PCI devices being used on the system and no I/O port region assigned to the device.

Tomohiro,

I'm ok with the bottom part of the patch, but I do not like the modification of the pci device ID table in this way. As Arjan van der Ven previously commented as well, this makes it hard for future device ID's to be bound to the driver.

On top of that, there is no logical correlation between the mapping and chipsets, so a lot of information is lost in that table. It really does not show which _chipsets_ support this functionality.

I think if we want to work with this, we need some way of mapping the device ID's back to chipsets, and enable the feature on that basis.

Auke

Quoted 249 lines

Tomohiro Kusumi

---
 e1000.h      |    6 +-
 e1000_main.c |  152 
+++++++++++++++++++++++++++++++----------------------------
 2 files changed, 86 insertions(+), 72 deletions(-)

diff -uprN linux-2.6.21.orig/drivers/net/e1000/e1000.h linux-2.6.21/drivers/net/e1000/e1000.h
--- linux-2.6.21.orig/drivers/net/e1000/e1000.h 2007-05-09
18:02:26.000000000 +0900
+++ linux-2.6.21/drivers/net/e1000/e1000.h 2007-05-09
18:02:59.000000000 +0900

drivers/net/e1000/e1000.h +4 -2
@@ -74,8 +74,9 @@
 #define BAR_1        1
 #define BAR_5        5
 
-#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
-    PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
+#define E1000_USE_IOPORT       (1 << 0)
+#define INTEL_E1000_ETHERNET_DEVICE(device_id, flags) {\
+       PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id), .driver_data = flags}
 
 struct e1000_adapter;
 
@@ -347,6 +348,7 @@ struct e1000_adapter {
     boolean_t quad_port_a;
     unsigned long flags;
     uint32_t eeprom_wol;
+    int bars;               /* BARs to be enabled */
 };
 
 enum e1000_state_t {

diff -uprN linux-2.6.21.orig/drivers/net/e1000/e1000_main.c linux-2.6.21/drivers/net/e1000/e1000_main.c
--- linux-2.6.21.orig/drivers/net/e1000/e1000_main.c 2007-05-09
18:02:27.000000000 +0900
+++ linux-2.6.21/drivers/net/e1000/e1000_main.c 2007-05-09
18:03:00.000000000 +0900

drivers/net/e1000/e1000_main.c +82 -70
@@ -48,65 +48,65 @@ static char e1000_copyright[] = "Copyrig
  *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
  */
 static struct pci_device_id e1000_pci_tbl[] = {
-    INTEL_E1000_ETHERNET_DEVICE(0x1000),
-    INTEL_E1000_ETHERNET_DEVICE(0x1001),
-    INTEL_E1000_ETHERNET_DEVICE(0x1004),
-    INTEL_E1000_ETHERNET_DEVICE(0x1008),
-    INTEL_E1000_ETHERNET_DEVICE(0x1009),
-    INTEL_E1000_ETHERNET_DEVICE(0x100C),
-    INTEL_E1000_ETHERNET_DEVICE(0x100D),
-    INTEL_E1000_ETHERNET_DEVICE(0x100E),
-    INTEL_E1000_ETHERNET_DEVICE(0x100F),
-    INTEL_E1000_ETHERNET_DEVICE(0x1010),
-    INTEL_E1000_ETHERNET_DEVICE(0x1011),
-    INTEL_E1000_ETHERNET_DEVICE(0x1012),
-    INTEL_E1000_ETHERNET_DEVICE(0x1013),
-    INTEL_E1000_ETHERNET_DEVICE(0x1014),
-    INTEL_E1000_ETHERNET_DEVICE(0x1015),
-    INTEL_E1000_ETHERNET_DEVICE(0x1016),
-    INTEL_E1000_ETHERNET_DEVICE(0x1017),
-    INTEL_E1000_ETHERNET_DEVICE(0x1018),
-    INTEL_E1000_ETHERNET_DEVICE(0x1019),
-    INTEL_E1000_ETHERNET_DEVICE(0x101A),
-    INTEL_E1000_ETHERNET_DEVICE(0x101D),
-    INTEL_E1000_ETHERNET_DEVICE(0x101E),
-    INTEL_E1000_ETHERNET_DEVICE(0x1026),
-    INTEL_E1000_ETHERNET_DEVICE(0x1027),
-    INTEL_E1000_ETHERNET_DEVICE(0x1028),
-    INTEL_E1000_ETHERNET_DEVICE(0x1049),
-    INTEL_E1000_ETHERNET_DEVICE(0x104A),
-    INTEL_E1000_ETHERNET_DEVICE(0x104B),
-    INTEL_E1000_ETHERNET_DEVICE(0x104C),
-    INTEL_E1000_ETHERNET_DEVICE(0x104D),
-    INTEL_E1000_ETHERNET_DEVICE(0x105E),
-    INTEL_E1000_ETHERNET_DEVICE(0x105F),
-    INTEL_E1000_ETHERNET_DEVICE(0x1060),
-    INTEL_E1000_ETHERNET_DEVICE(0x1075),
-    INTEL_E1000_ETHERNET_DEVICE(0x1076),
-    INTEL_E1000_ETHERNET_DEVICE(0x1077),
-    INTEL_E1000_ETHERNET_DEVICE(0x1078),
-    INTEL_E1000_ETHERNET_DEVICE(0x1079),
-    INTEL_E1000_ETHERNET_DEVICE(0x107A),
-    INTEL_E1000_ETHERNET_DEVICE(0x107B),
-    INTEL_E1000_ETHERNET_DEVICE(0x107C),
-    INTEL_E1000_ETHERNET_DEVICE(0x107D),
-    INTEL_E1000_ETHERNET_DEVICE(0x107E),
-    INTEL_E1000_ETHERNET_DEVICE(0x107F),
-    INTEL_E1000_ETHERNET_DEVICE(0x108A),
-    INTEL_E1000_ETHERNET_DEVICE(0x108B),
-    INTEL_E1000_ETHERNET_DEVICE(0x108C),
-    INTEL_E1000_ETHERNET_DEVICE(0x1096),
-    INTEL_E1000_ETHERNET_DEVICE(0x1098),
-    INTEL_E1000_ETHERNET_DEVICE(0x1099),
-    INTEL_E1000_ETHERNET_DEVICE(0x109A),
-    INTEL_E1000_ETHERNET_DEVICE(0x10A4),
-    INTEL_E1000_ETHERNET_DEVICE(0x10B5),
-    INTEL_E1000_ETHERNET_DEVICE(0x10B9),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BA),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BB),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BC),
-    INTEL_E1000_ETHERNET_DEVICE(0x10C4),
-    INTEL_E1000_ETHERNET_DEVICE(0x10C5),
+    INTEL_E1000_ETHERNET_DEVICE(0x1000, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1001, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1004, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1008, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1009, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100C, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100D, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100E, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100F, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1010, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1011, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1012, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1013, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1014, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1015, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1016, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1017, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1018, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1019, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x101A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x101D, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x101E, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1026, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1027, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1028, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1049, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104C, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104D, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x105E, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x105F, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1060, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1075, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1076, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1077, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1078, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1079, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107C, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x107D, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107E, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107F, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108C, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1096, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1098, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1099, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x109A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10A4, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10B5, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10B9, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BA, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BB, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BC, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10C4, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10C5, 0),
     /* required last entry */
     {0,}
 };
@@ -879,7 +879,14 @@ e1000_probe(struct pci_dev *pdev,
     int i, err, pci_using_dac;
     uint16_t eeprom_data = 0;
     uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
-    if ((err = pci_enable_device(pdev)))
+    int bars;
+
+    if (ent->driver_data & E1000_USE_IOPORT)
+        bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
+    else
+        bars = pci_select_bars(pdev, IORESOURCE_MEM);
+
+    if ((err = pci_enable_device_bars(pdev, bars)))
         return err;
 
     if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
@@ -894,7 +901,8 @@ e1000_probe(struct pci_dev *pdev,
         pci_using_dac = 0;
     }
 
-    if ((err = pci_request_regions(pdev, e1000_driver_name)))
+    err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
+    if (err)
         goto err_pci_reg;
 
     pci_set_master(pdev);
@@ -913,6 +921,7 @@ e1000_probe(struct pci_dev *pdev,
     adapter->pdev = pdev;
     adapter->hw.back = adapter;
     adapter->msg_enable = (1 << debug) - 1;
+    adapter->bars = bars;
 
     mmio_start = pci_resource_start(pdev, BAR_0);
     mmio_len = pci_resource_len(pdev, BAR_0);
@@ -922,12 +931,15 @@ e1000_probe(struct pci_dev *pdev,
     if (!adapter->hw.hw_addr)
         goto err_ioremap;
 
-    for (i = BAR_1; i <= BAR_5; i++) {
-        if (pci_resource_len(pdev, i) == 0)
-            continue;
-        if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
-            adapter->hw.io_base = pci_resource_start(pdev, i);
-            break;
+    if (ent->driver_data & E1000_USE_IOPORT) {
+        for (i = BAR_1; i <= BAR_5; i++) {
+            if (pci_resource_len(pdev, i) == 0)
+                continue;
+            if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+                adapter->hw.io_base =
+                    pci_resource_start(pdev, i);
+                break;
+            }
         }
     }
 
@@ -1190,7 +1202,7 @@ err_sw_init:
 err_ioremap:
     free_netdev(netdev);
 err_alloc_etherdev:
-    pci_release_regions(pdev);
+    pci_release_selected_regions(pdev, bars);
 err_pci_reg:
 err_dma:
     pci_disable_device(pdev);
@@ -1242,7 +1254,7 @@ e1000_remove(struct pci_dev *pdev)
     iounmap(adapter->hw.hw_addr);
     if (adapter->hw.flash_address)
         iounmap(adapter->hw.flash_address);
-    pci_release_regions(pdev);
+    pci_release_selected_regions(pdev, adapter->bars);
 
     free_netdev(netdev);
 
@@ -5172,7 +5184,7 @@ e1000_resume(struct pci_dev *pdev)
 
     pci_set_power_state(pdev, PCI_D0);
     pci_restore_state(pdev);
-    if ((err = pci_enable_device(pdev))) {
+    if ((err = pci_enable_device_bars(pdev, adapter->bars))) {
         printk(KERN_ERR "e1000: Cannot enable PCI device from 
 suspend\n");
         return err;
     }
#4 lore raw
Quoted 22 lines · Auke
Quoted 16 lines · Tomohiro Kusumi

Dear Auke

Quoted 4 lines

I'm ok with the bottom part of the patch, but I do not like the modification of the pci device ID table in this way. As Arjan van der Ven previously commented as well, this makes it hard for future device ID's to be bound to the driver.

I googled the previous comment by Arjan. Now I understand that the patch makes it difficult to add PCI ID's to the driver at runtime.

Quoted 4 lines

On top of that, there is no logical correlation between the mapping and chipsets, so a lot of information is lost in that table. It really does not show which _chipsets_ support this functionality.

Quoted 4 lines

Thanks for pointing out the problem, but I can't quite understand what you are trying to say. What do you mean by the chipset? Are you talking about the chipset of the NIC? or the South bridge? I'd be glad if you can explain it to me.

Quoted 5 lines

perhaps my wording was poor. I was referring to the NIC chip. Since there are about 12 different physical e1000 NIC chips (and lots of different pci IDs per e1000 NIC chip), it would be best to correlate the capability of each NIC chip number to be able to work without legacy IO mode instead of providing this mapping based on the PCI device ID.

It would serve two purposes: new pci id's for a chipset of which we already know that it can work without legacy IO can automatically inherit this property from the NIC chipset properties, and new e1000 chips would automatically get a default property for this value.

I will (time permitting) try to reverse your matrix to chip numbers and see if we can add this property in a much easier way.

Okay, you appear to enable io for the following chipsets:

82540 chips:
82540EM
82540EM_LOM
82540EP
82540EP_LOM
82540EP_LP
those are all the 82540's, OK

82541 chips:
82541EI
82541EI_MOBILE
82541ER
82541ER_LOM
82541GI
82541GI_LF
82541GI_MOBILE
Those are all the 82541's, OK too

82544 chips:
82544EI_COPPER
82544EI_FIBER
82544GC_COPPER
82544GC_LOM
Those are all the 82543's, OK too

82545's:
82545EM_COPPER
82545EM_FIBER
Here you skip 3 other 82545 device ID's, was that intentional?

82546's:
82546EB_COPPER
82546EB_FIBER
82546EB_QUAD_COPPER
Here you skip over 9 82546 device ID's... same question.

It appears that probably the 82543's would also work under ioport, 82547 might be the odd one out that might work without IOport. I think 82542 definately needs it...

can you tell me how you created the initial list?

Summarizing, it appears that we should condense the list to: (sketch)

switch (adapter->hw.mac.type) {
case e1000_82542 ... e1000_82541_rev_2:

        adapter->ioport_capable = 1;
	break;
 default:
	break;

}

I also would like this option to be non-default, IOW use legacy IO by default, and allow the user to specify a module load option to disable use of this feature:

static unsigned int use_ioport = 1;
module_param(use_ioport, uint, 0644); MODULE_PARM_DESC(use_ioport, "Use Legacy IO port mapping (default: 1)");

or something like this to allow the feature to be tested before we turn legacy ioport off for all adapters and everyone.

Do you think you can accomodate these changes?

Cheers,

Auke

Quoted 288 lines

Auke

Quoted 272 lines

Tomohiro Kusumi

Quoted 268 lines · Auke
Quoted 13 lines · Tomohiro Kusumi

Hi

As you can see in the "10. pci_enable_device_bars() and Legacy I/O Port space" of the Documentation/pci.txt, the latest kernel has interfaces for PCI device drivers to tell the kernel which resource the driver want to use, ex. I/O port or MMIO.

I've made a patch which makes Intel e1000 driver legacy I/O port free by using the PCI core changes I mentioned above. The Intel e1000 driver can handle some of its devices without using I/O port. So this patch changes the driver not to enable/request I/O port region depending on the device id.

Quoted 3 lines

As a result, the driver can handle its device even when there are huge number of PCI devices being used on the system and no I/O port region assigned to the device.

Tomohiro,

I'm ok with the bottom part of the patch, but I do not like the modification of the pci device ID table in this way. As Arjan van der Ven previously commented as well, this makes it hard for future device ID's to be bound to the driver.

On top of that, there is no logical correlation between the mapping and chipsets, so a lot of information is lost in that table. It really does not show which _chipsets_ support this functionality.

I think if we want to work with this, we need some way of mapping the device ID's back to chipsets, and enable the feature on that basis.

Auke

Quoted 241 lines

Tomohiro Kusumi

---
 e1000.h      |    6 +-
 e1000_main.c |  152 
+++++++++++++++++++++++++++++++----------------------------
 2 files changed, 86 insertions(+), 72 deletions(-)

diff -uprN linux-2.6.21.orig/drivers/net/e1000/e1000.h linux-2.6.21/drivers/net/e1000/e1000.h
--- linux-2.6.21.orig/drivers/net/e1000/e1000.h 2007-05-09
18:02:26.000000000 +0900
+++ linux-2.6.21/drivers/net/e1000/e1000.h 2007-05-09
18:02:59.000000000 +0900

drivers/net/e1000/e1000.h +4 -2
@@ -74,8 +74,9 @@
 #define BAR_1        1
 #define BAR_5        5
 
-#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
-    PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
+#define E1000_USE_IOPORT       (1 << 0)
+#define INTEL_E1000_ETHERNET_DEVICE(device_id, flags) {\
+       PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id), .driver_data = flags}
 
 struct e1000_adapter;
 
@@ -347,6 +348,7 @@ struct e1000_adapter {
     boolean_t quad_port_a;
     unsigned long flags;
     uint32_t eeprom_wol;
+    int bars;               /* BARs to be enabled */
 };
 
 enum e1000_state_t {

diff -uprN linux-2.6.21.orig/drivers/net/e1000/e1000_main.c linux-2.6.21/drivers/net/e1000/e1000_main.c
--- linux-2.6.21.orig/drivers/net/e1000/e1000_main.c 2007-05-09
18:02:27.000000000 +0900
+++ linux-2.6.21/drivers/net/e1000/e1000_main.c 2007-05-09
18:03:00.000000000 +0900

drivers/net/e1000/e1000_main.c +81 -69
@@ -48,65 +48,65 @@ static char e1000_copyright[] = "Copyrig
  *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
  */
 static struct pci_device_id e1000_pci_tbl[] = {
-    INTEL_E1000_ETHERNET_DEVICE(0x1000),
-    INTEL_E1000_ETHERNET_DEVICE(0x1001),
-    INTEL_E1000_ETHERNET_DEVICE(0x1004),
-    INTEL_E1000_ETHERNET_DEVICE(0x1008),
-    INTEL_E1000_ETHERNET_DEVICE(0x1009),
-    INTEL_E1000_ETHERNET_DEVICE(0x100C),
-    INTEL_E1000_ETHERNET_DEVICE(0x100D),
-    INTEL_E1000_ETHERNET_DEVICE(0x100E),
-    INTEL_E1000_ETHERNET_DEVICE(0x100F),
-    INTEL_E1000_ETHERNET_DEVICE(0x1010),
-    INTEL_E1000_ETHERNET_DEVICE(0x1011),
-    INTEL_E1000_ETHERNET_DEVICE(0x1012),
-    INTEL_E1000_ETHERNET_DEVICE(0x1013),
-    INTEL_E1000_ETHERNET_DEVICE(0x1014),
-    INTEL_E1000_ETHERNET_DEVICE(0x1015),
-    INTEL_E1000_ETHERNET_DEVICE(0x1016),
-    INTEL_E1000_ETHERNET_DEVICE(0x1017),
-    INTEL_E1000_ETHERNET_DEVICE(0x1018),
-    INTEL_E1000_ETHERNET_DEVICE(0x1019),
-    INTEL_E1000_ETHERNET_DEVICE(0x101A),
-    INTEL_E1000_ETHERNET_DEVICE(0x101D),
-    INTEL_E1000_ETHERNET_DEVICE(0x101E),
-    INTEL_E1000_ETHERNET_DEVICE(0x1026),
-    INTEL_E1000_ETHERNET_DEVICE(0x1027),
-    INTEL_E1000_ETHERNET_DEVICE(0x1028),
-    INTEL_E1000_ETHERNET_DEVICE(0x1049),
-    INTEL_E1000_ETHERNET_DEVICE(0x104A),
-    INTEL_E1000_ETHERNET_DEVICE(0x104B),
-    INTEL_E1000_ETHERNET_DEVICE(0x104C),
-    INTEL_E1000_ETHERNET_DEVICE(0x104D),
-    INTEL_E1000_ETHERNET_DEVICE(0x105E),
-    INTEL_E1000_ETHERNET_DEVICE(0x105F),
-    INTEL_E1000_ETHERNET_DEVICE(0x1060),
-    INTEL_E1000_ETHERNET_DEVICE(0x1075),
-    INTEL_E1000_ETHERNET_DEVICE(0x1076),
-    INTEL_E1000_ETHERNET_DEVICE(0x1077),
-    INTEL_E1000_ETHERNET_DEVICE(0x1078),
-    INTEL_E1000_ETHERNET_DEVICE(0x1079),
-    INTEL_E1000_ETHERNET_DEVICE(0x107A),
-    INTEL_E1000_ETHERNET_DEVICE(0x107B),
-    INTEL_E1000_ETHERNET_DEVICE(0x107C),
-    INTEL_E1000_ETHERNET_DEVICE(0x107D),
-    INTEL_E1000_ETHERNET_DEVICE(0x107E),
-    INTEL_E1000_ETHERNET_DEVICE(0x107F),
-    INTEL_E1000_ETHERNET_DEVICE(0x108A),
-    INTEL_E1000_ETHERNET_DEVICE(0x108B),
-    INTEL_E1000_ETHERNET_DEVICE(0x108C),
-    INTEL_E1000_ETHERNET_DEVICE(0x1096),
-    INTEL_E1000_ETHERNET_DEVICE(0x1098),
-    INTEL_E1000_ETHERNET_DEVICE(0x1099),
-    INTEL_E1000_ETHERNET_DEVICE(0x109A),
-    INTEL_E1000_ETHERNET_DEVICE(0x10A4),
-    INTEL_E1000_ETHERNET_DEVICE(0x10B5),
-    INTEL_E1000_ETHERNET_DEVICE(0x10B9),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BA),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BB),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BC),
-    INTEL_E1000_ETHERNET_DEVICE(0x10C4),
-    INTEL_E1000_ETHERNET_DEVICE(0x10C5),
+    INTEL_E1000_ETHERNET_DEVICE(0x1000, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1001, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1004, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1008, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1009, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100C, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100D, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100E, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100F, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1010, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1011, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1012, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1013, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1014, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1015, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1016, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1017, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1018, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1019, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x101A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x101D, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x101E, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1026, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1027, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1028, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1049, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104C, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104D, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x105E, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x105F, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1060, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1075, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1076, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1077, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1078, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1079, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107C, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x107D, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107E, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107F, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108C, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1096, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1098, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1099, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x109A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10A4, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10B5, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10B9, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BA, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BB, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BC, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10C4, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10C5, 0),
     /* required last entry */
     {0,}
 };
@@ -879,7 +879,14 @@ e1000_probe(struct pci_dev *pdev,
     int i, err, pci_using_dac;
     uint16_t eeprom_data = 0;
     uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
-    if ((err = pci_enable_device(pdev)))
+    int bars;
+
+    if (ent->driver_data & E1000_USE_IOPORT)
+        bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
+    else
+        bars = pci_select_bars(pdev, IORESOURCE_MEM);
+
+    if ((err = pci_enable_device_bars(pdev, bars)))
         return err;
 
     if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
@@ -894,7 +901,8 @@ e1000_probe(struct pci_dev *pdev,
         pci_using_dac = 0;
     }
 
-    if ((err = pci_request_regions(pdev, e1000_driver_name)))
+    err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
+    if (err)
         goto err_pci_reg;
 
     pci_set_master(pdev);
@@ -913,6 +921,7 @@ e1000_probe(struct pci_dev *pdev,
     adapter->pdev = pdev;
     adapter->hw.back = adapter;
     adapter->msg_enable = (1 << debug) - 1;
+    adapter->bars = bars;
 
     mmio_start = pci_resource_start(pdev, BAR_0);
     mmio_len = pci_resource_len(pdev, BAR_0);
@@ -922,12 +931,15 @@ e1000_probe(struct pci_dev *pdev,
     if (!adapter->hw.hw_addr)
         goto err_ioremap;
 
-    for (i = BAR_1; i <= BAR_5; i++) {
-        if (pci_resource_len(pdev, i) == 0)
-            continue;
-        if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
-            adapter->hw.io_base = pci_resource_start(pdev, i);
-            break;
+    if (ent->driver_data & E1000_USE_IOPORT) {
+        for (i = BAR_1; i <= BAR_5; i++) {
+            if (pci_resource_len(pdev, i) == 0)
+                continue;
+            if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+                adapter->hw.io_base =
+                    pci_resource_start(pdev, i);
+                break;
+            }
         }
     }
 
@@ -1190,7 +1202,7 @@ err_sw_init:
 err_ioremap:
     free_netdev(netdev);
 err_alloc_etherdev:
-    pci_release_regions(pdev);
+    pci_release_selected_regions(pdev, bars);
 err_pci_reg:
 err_dma:
     pci_disable_device(pdev);
@@ -1242,7 +1254,7 @@ e1000_remove(struct pci_dev *pdev)
     iounmap(adapter->hw.hw_addr);
     if (adapter->hw.flash_address)
         iounmap(adapter->hw.flash_address);
-    pci_release_regions(pdev);
+    pci_release_selected_regions(pdev, adapter->bars);
 
     free_netdev(netdev);
 
@@ -5172,7 +5184,7 @@ e1000_resume(struct pci_dev *pdev)
 
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/net/e1000/e1000_main.c +1 -1
     pci_set_power_state(pdev, PCI_D0);
     pci_restore_state(pdev);
-    if ((err = pci_enable_device(pdev))) {
+    if ((err = pci_enable_device_bars(pdev, adapter->bars))) {
         printk(KERN_ERR "e1000: Cannot enable PCI device from 
 suspend\n");
         return err;
     }

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#5 lore raw

Dear Auke

I'm sorry for being so late. Let me answer your questions.

Quoted 4 lines

82545's:
82545EM_COPPER
82545EM_FIBER
Here you skip 3 other 82545 device ID's, was that intentional?

Maybe my understanding on the e1000 driver was wrong. I looked up the following code, and thought the device IDs whose chipset are 82545 rev3 do not use I/O port. That's why I only put the first two device IDs on the USE_IOPORT list I submitted previously.

Quoted 5 lines

82546's:
82546EB_COPPER
82546EB_FIBER
82546EB_QUAD_COPPER
Here you skip over 9 82546 device ID's... same question.

Same answer for the 82546. From the following code, I thought the device IDs whose chipset are 82546 rev3 do not use I/O port.

Quoted 1 line

Do you think you can accomodate these changes?

Yes I'll try it. But before I accomodate those changes, could you just tell me which device IDs I should use for this function?
You said 82540, 82541, 82544 are okay, and I'm gonna add those 3 IDs for 82545, and 6 IDs for 82546. Are there any other IDs that I'm missing?

Thanks
Tomohiro Kusumi

  drivers/net/e1000/e1000_hw.c
    303 /******************************************************************************
    304  * Set the mac type member in the hw struct.
    305  *
    306  * hw - Struct containing variables accessed by shared code
    307  *****************************************************************************/
    308 int32_t
    309 e1000_set_mac_type(struct e1000_hw *hw)
    310 {
    ...
    344         case E1000_DEV_ID_82545EM_COPPER:
    345         case E1000_DEV_ID_82545EM_FIBER:
    346                 hw->mac_type = e1000_82545;
    347                 break;
    348         case E1000_DEV_ID_82545GM_COPPER:  /* skipped */
    349         case E1000_DEV_ID_82545GM_FIBER:   /* skipped */
    350         case E1000_DEV_ID_82545GM_SERDES:  /* skipped */
    351                 hw->mac_type = e1000_82545_rev_3;
    352                 break;
    353         case E1000_DEV_ID_82546EB_COPPER:
    354         case E1000_DEV_ID_82546EB_FIBER:
    355         case E1000_DEV_ID_82546EB_QUAD_COPPER:
    356                 hw->mac_type = e1000_82546;
    357                 break;
    358         case E1000_DEV_ID_82546GB_COPPER:           /* skipped */
    359         case E1000_DEV_ID_82546GB_FIBER:            /* skipped */
    360         case E1000_DEV_ID_82546GB_SERDES:           /* skipped */
    361         case E1000_DEV_ID_82546GB_PCIE:             /* skipped */
    362         case E1000_DEV_ID_82546GB_QUAD_COPPER:      /* skipped */
    363         case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: /* skipped */
    364                 hw->mac_type = e1000_82546_rev_3;
    365                 break;

drivers/net/e1000/e1000_hw.c

    519 /******************************************************************************
    520  * Reset the transmit and receive units; mask and clear all interrupts.
    521  *
    522  * hw - Struct containing variables accessed by shared code
    523  *****************************************************************************/
    524 int32_t
    525 e1000_reset_hw(struct e1000_hw *hw)
    526 {
    ...
    618     switch (hw->mac_type) {
    619         case e1000_82544:
    620         case e1000_82540:
    621         case e1000_82545:
    622         case e1000_82546:
    623         case e1000_82541:
    624         case e1000_82541_rev_2:
    625             /* These controllers can't ack the 64-bit write when issuing the
    626              * reset, so use IO-mapping as a workaround to issue the reset */
    627             E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                /* Are these the ones using the I/O port? */

    628             break;
    629         case e1000_82545_rev_3:
    630         case e1000_82546_rev_3:
    631             /* Reset is performed on a shadow of the control register */
    632             E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST));
    633             break;

drivers/net/e1000/e1000_hw.h

    451 #define E1000_DEV_ID_82545EM_COPPER      0x100F
    452 #define E1000_DEV_ID_82545EM_FIBER       0x1011
    453 #define E1000_DEV_ID_82545GM_COPPER      0x1026
    454 #define E1000_DEV_ID_82545GM_FIBER       0x1027
    455 #define E1000_DEV_ID_82545GM_SERDES      0x1028
    456 #define E1000_DEV_ID_82546EB_COPPER      0x1010
    457 #define E1000_DEV_ID_82546EB_FIBER       0x1012
    458 #define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D
    ...
    467 #define E1000_DEV_ID_82546GB_COPPER      0x1079
    468 #define E1000_DEV_ID_82546GB_FIBER       0x107A
    469 #define E1000_DEV_ID_82546GB_SERDES      0x107B
    470 #define E1000_DEV_ID_82546GB_PCIE        0x108A
    471 #define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
    ...
    486 #define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
Quoted 390 lines · Auke
Quoted 22 lines · Auke
Quoted 16 lines · Tomohiro Kusumi

Dear Auke

Quoted 4 lines

I'm ok with the bottom part of the patch, but I do not like the modification of the pci device ID table in this way. As Arjan van der Ven previously commented as well, this makes it hard for future device ID's to be bound to the driver.

I googled the previous comment by Arjan. Now I understand that the patch makes it difficult to add PCI ID's to the driver at runtime.

Quoted 4 lines

On top of that, there is no logical correlation between the mapping and chipsets, so a lot of information is lost in that table. It really does not show which _chipsets_ support this functionality.

Quoted 4 lines

Thanks for pointing out the problem, but I can't quite understand what you are trying to say. What do you mean by the chipset? Are you talking about the chipset of the NIC? or the South bridge? I'd be glad if you can explain it to me.

Quoted 5 lines

perhaps my wording was poor. I was referring to the NIC chip. Since there are about 12 different physical e1000 NIC chips (and lots of different pci IDs per e1000 NIC chip), it would be best to correlate the capability of each NIC chip number to be able to work without legacy IO mode instead of providing this mapping based on the PCI device ID.

It would serve two purposes: new pci id's for a chipset of which we already know that it can work without legacy IO can automatically inherit this property from the NIC chipset properties, and new e1000 chips would automatically get a default property for this value.

I will (time permitting) try to reverse your matrix to chip numbers and see if we can add this property in a much easier way.

Okay, you appear to enable io for the following chipsets:

82540 chips:
82540EM
82540EM_LOM
82540EP
82540EP_LOM
82540EP_LP
those are all the 82540's, OK

82541 chips:
82541EI
82541EI_MOBILE
82541ER
82541ER_LOM
82541GI
82541GI_LF
82541GI_MOBILE
Those are all the 82541's, OK too

82544 chips:
82544EI_COPPER
82544EI_FIBER
82544GC_COPPER
82544GC_LOM
Those are all the 82543's, OK too

82545's:
82545EM_COPPER
82545EM_FIBER
Here you skip 3 other 82545 device ID's, was that intentional?

82546's:
82546EB_COPPER
82546EB_FIBER
82546EB_QUAD_COPPER
Here you skip over 9 82546 device ID's... same question.

It appears that probably the 82543's would also work under ioport, 82547 might be the odd one out that might work without IOport. I think 82542 definately needs it...

can you tell me how you created the initial list?

Summarizing, it appears that we should condense the list to: (sketch)

switch (adapter->hw.mac.type) {
case e1000_82542 ... e1000_82541_rev_2:

        adapter->ioport_capable = 1;
    break;
 default:
    break;

}

I also would like this option to be non-default, IOW use legacy IO by default, and allow the user to specify a module load option to disable use of this feature:

static unsigned int use_ioport = 1;
module_param(use_ioport, uint, 0644); MODULE_PARM_DESC(use_ioport, "Use Legacy IO port mapping (default: 1)");

or something like this to allow the feature to be tested before we turn legacy ioport off for all adapters and everyone.

Do you think you can accomodate these changes?

Cheers,

Auke

Quoted 290 lines

Auke

Quoted 274 lines

Tomohiro Kusumi

Quoted 270 lines · Auke
Quoted 13 lines · Tomohiro Kusumi

Hi

As you can see in the "10. pci_enable_device_bars() and Legacy I/O Port space" of the Documentation/pci.txt, the latest kernel has interfaces for PCI device drivers to tell the kernel which resource the driver want to use, ex. I/O port or MMIO.

I've made a patch which makes Intel e1000 driver legacy I/O port free by using the PCI core changes I mentioned above. The Intel e1000 driver can handle some of its devices without using I/O port. So this patch changes the driver not to enable/request I/O port region depending on the device id.

Quoted 3 lines

As a result, the driver can handle its device even when there are huge number of PCI devices being used on the system and no I/O port region assigned to the device.

Tomohiro,

I'm ok with the bottom part of the patch, but I do not like the modification of the pci device ID table in this way. As Arjan van der Ven previously commented as well, this makes it hard for future device ID's to be bound to the driver.

On top of that, there is no logical correlation between the mapping and chipsets, so a lot of information is lost in that table. It really does not show which _chipsets_ support this functionality.

I think if we want to work with this, we need some way of mapping the device ID's back to chipsets, and enable the feature on that basis.

Auke

Quoted 243 lines

Tomohiro Kusumi

---
 e1000.h      |    6 +-
 e1000_main.c |  152 
+++++++++++++++++++++++++++++++----------------------------
 2 files changed, 86 insertions(+), 72 deletions(-)

diff -uprN linux-2.6.21.orig/drivers/net/e1000/e1000.h linux-2.6.21/drivers/net/e1000/e1000.h
--- linux-2.6.21.orig/drivers/net/e1000/e1000.h 2007-05-09
18:02:26.000000000 +0900
+++ linux-2.6.21/drivers/net/e1000/e1000.h 2007-05-09
18:02:59.000000000 +0900

drivers/net/e1000/e1000.h +4 -2
@@ -74,8 +74,9 @@
 #define BAR_1        1
 #define BAR_5        5
 
-#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
-    PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
+#define E1000_USE_IOPORT       (1 << 0)
+#define INTEL_E1000_ETHERNET_DEVICE(device_id, flags) {\
+       PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id), .driver_data = 
 flags}
 
 struct e1000_adapter;
@@ -347,6 +348,7 @@ struct e1000_adapter {
     boolean_t quad_port_a;
     unsigned long flags;
     uint32_t eeprom_wol;
+    int bars;               /* BARs to be enabled */
 };
 
 enum e1000_state_t {

diff -uprN linux-2.6.21.orig/drivers/net/e1000/e1000_main.c linux-2.6.21/drivers/net/e1000/e1000_main.c
--- linux-2.6.21.orig/drivers/net/e1000/e1000_main.c 2007-05-09
18:02:27.000000000 +0900
+++ linux-2.6.21/drivers/net/e1000/e1000_main.c 2007-05-09
18:03:00.000000000 +0900

drivers/net/e1000/e1000_main.c +69 -61
@@ -48,65 +48,65 @@ static char e1000_copyright[] = "Copyrig
  *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
  */
 static struct pci_device_id e1000_pci_tbl[] = {
-    INTEL_E1000_ETHERNET_DEVICE(0x1000),
-    INTEL_E1000_ETHERNET_DEVICE(0x1001),
-    INTEL_E1000_ETHERNET_DEVICE(0x1004),
-    INTEL_E1000_ETHERNET_DEVICE(0x1008),
-    INTEL_E1000_ETHERNET_DEVICE(0x1009),
-    INTEL_E1000_ETHERNET_DEVICE(0x100C),
-    INTEL_E1000_ETHERNET_DEVICE(0x100D),
-    INTEL_E1000_ETHERNET_DEVICE(0x100E),
-    INTEL_E1000_ETHERNET_DEVICE(0x100F),
-    INTEL_E1000_ETHERNET_DEVICE(0x1010),
-    INTEL_E1000_ETHERNET_DEVICE(0x1011),
-    INTEL_E1000_ETHERNET_DEVICE(0x1012),
-    INTEL_E1000_ETHERNET_DEVICE(0x1013),
-    INTEL_E1000_ETHERNET_DEVICE(0x1014),
-    INTEL_E1000_ETHERNET_DEVICE(0x1015),
-    INTEL_E1000_ETHERNET_DEVICE(0x1016),
-    INTEL_E1000_ETHERNET_DEVICE(0x1017),
-    INTEL_E1000_ETHERNET_DEVICE(0x1018),
-    INTEL_E1000_ETHERNET_DEVICE(0x1019),
-    INTEL_E1000_ETHERNET_DEVICE(0x101A),
-    INTEL_E1000_ETHERNET_DEVICE(0x101D),
-    INTEL_E1000_ETHERNET_DEVICE(0x101E),
-    INTEL_E1000_ETHERNET_DEVICE(0x1026),
-    INTEL_E1000_ETHERNET_DEVICE(0x1027),
-    INTEL_E1000_ETHERNET_DEVICE(0x1028),
-    INTEL_E1000_ETHERNET_DEVICE(0x1049),
-    INTEL_E1000_ETHERNET_DEVICE(0x104A),
-    INTEL_E1000_ETHERNET_DEVICE(0x104B),
-    INTEL_E1000_ETHERNET_DEVICE(0x104C),
-    INTEL_E1000_ETHERNET_DEVICE(0x104D),
-    INTEL_E1000_ETHERNET_DEVICE(0x105E),
-    INTEL_E1000_ETHERNET_DEVICE(0x105F),
-    INTEL_E1000_ETHERNET_DEVICE(0x1060),
-    INTEL_E1000_ETHERNET_DEVICE(0x1075),
-    INTEL_E1000_ETHERNET_DEVICE(0x1076),
-    INTEL_E1000_ETHERNET_DEVICE(0x1077),
-    INTEL_E1000_ETHERNET_DEVICE(0x1078),
-    INTEL_E1000_ETHERNET_DEVICE(0x1079),
-    INTEL_E1000_ETHERNET_DEVICE(0x107A),
-    INTEL_E1000_ETHERNET_DEVICE(0x107B),
-    INTEL_E1000_ETHERNET_DEVICE(0x107C),
-    INTEL_E1000_ETHERNET_DEVICE(0x107D),
-    INTEL_E1000_ETHERNET_DEVICE(0x107E),
-    INTEL_E1000_ETHERNET_DEVICE(0x107F),
-    INTEL_E1000_ETHERNET_DEVICE(0x108A),
-    INTEL_E1000_ETHERNET_DEVICE(0x108B),
-    INTEL_E1000_ETHERNET_DEVICE(0x108C),
-    INTEL_E1000_ETHERNET_DEVICE(0x1096),
-    INTEL_E1000_ETHERNET_DEVICE(0x1098),
-    INTEL_E1000_ETHERNET_DEVICE(0x1099),
-    INTEL_E1000_ETHERNET_DEVICE(0x109A),
-    INTEL_E1000_ETHERNET_DEVICE(0x10A4),
-    INTEL_E1000_ETHERNET_DEVICE(0x10B5),
-    INTEL_E1000_ETHERNET_DEVICE(0x10B9),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BA),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BB),
-    INTEL_E1000_ETHERNET_DEVICE(0x10BC),
-    INTEL_E1000_ETHERNET_DEVICE(0x10C4),
-    INTEL_E1000_ETHERNET_DEVICE(0x10C5),
+    INTEL_E1000_ETHERNET_DEVICE(0x1000, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1001, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1004, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1008, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1009, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100C, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100D, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100E, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x100F, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1010, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1011, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1012, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1013, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1014, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1015, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1016, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1017, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1018, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1019, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x101A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x101D, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x101E, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1026, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1027, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1028, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1049, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104C, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x104D, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x105E, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x105F, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1060, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1075, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1076, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1077, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1078, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x1079, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107C, E1000_USE_IOPORT),
+    INTEL_E1000_ETHERNET_DEVICE(0x107D, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107E, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x107F, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108B, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x108C, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1096, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1098, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x1099, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x109A, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10A4, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10B5, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10B9, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BA, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BB, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10BC, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10C4, 0),
+    INTEL_E1000_ETHERNET_DEVICE(0x10C5, 0),
     /* required last entry */
     {0,}
 };
@@ -879,7 +879,14 @@ e1000_probe(struct pci_dev *pdev,
     int i, err, pci_using_dac;
     uint16_t eeprom_data = 0;
     uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
-    if ((err = pci_enable_device(pdev)))
+    int bars;
+
+    if (ent->driver_data & E1000_USE_IOPORT)
+        bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
+    else
+        bars = pci_select_bars(pdev, IORESOURCE_MEM);
+
+    if ((err = pci_enable_device_bars(pdev, bars)))
         return err;
 
     if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) &&
@@ -894,7 +901,8 @@ e1000_probe(struct pci_dev *pdev,
         pci_using_dac = 0;
     }
 
-    if ((err = pci_request_regions(pdev, e1000_driver_name)))
+    err = pci_request_selected_regions(pdev, bars, 
 e1000_driver_name);
+    if (err)
         goto err_pci_reg;
 
     pci_set_master(pdev);
drivers/net/e1000/e1000_main.c +12 -8
@@ -913,6 +921,7 @@ e1000_probe(struct pci_dev *pdev,
     adapter->pdev = pdev;
     adapter->hw.back = adapter;
     adapter->msg_enable = (1 << debug) - 1;
+    adapter->bars = bars;
 
     mmio_start = pci_resource_start(pdev, BAR_0);
     mmio_len = pci_resource_len(pdev, BAR_0);
@@ -922,12 +931,15 @@ e1000_probe(struct pci_dev *pdev,
     if (!adapter->hw.hw_addr)
         goto err_ioremap;
 
-    for (i = BAR_1; i <= BAR_5; i++) {
-        if (pci_resource_len(pdev, i) == 0)
-            continue;
-        if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
-            adapter->hw.io_base = pci_resource_start(pdev, i);
-            break;
+    if (ent->driver_data & E1000_USE_IOPORT) {
+        for (i = BAR_1; i <= BAR_5; i++) {
+            if (pci_resource_len(pdev, i) == 0)
+                continue;
+            if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+                adapter->hw.io_base =
+                    pci_resource_start(pdev, i);
+                break;
+            }
         }
     }
 
@@ -1190,7 +1202,7 @@ err_sw_init:
 err_ioremap:
     free_netdev(netdev);
 err_alloc_etherdev:
-    pci_release_regions(pdev);
+    pci_release_selected_regions(pdev, bars);
 err_pci_reg:
 err_dma:
     pci_disable_device(pdev);
@@ -1242,7 +1254,7 @@ e1000_remove(struct pci_dev *pdev)
     iounmap(adapter->hw.hw_addr);
     if (adapter->hw.flash_address)
         iounmap(adapter->hw.flash_address);
-    pci_release_regions(pdev);
+    pci_release_selected_regions(pdev, adapter->bars);
 
     free_netdev(netdev);
 
@@ -5172,7 +5184,7 @@ e1000_resume(struct pci_dev *pdev)
 
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/net/e1000/e1000_main.c +1 -1
     pci_set_power_state(pdev, PCI_D0);
     pci_restore_state(pdev);
-    if ((err = pci_enable_device(pdev))) {
+    if ((err = pci_enable_device_bars(pdev, adapter->bars))) {
         printk(KERN_ERR "e1000: Cannot enable PCI device from 
 suspend\n");
         return err;
     }

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/