diff options
author | Michal Schmidt <mschmidt@redhat.com> | 2009-10-01 04:13:23 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-01 18:14:54 -0400 |
commit | 415e69e6574ab740e5db56152055eb899e7ac86e (patch) | |
tree | 970ca864f2187dbd3a32164f44eb5f9e2ac24af5 /drivers | |
parent | 89e95a613c8a045ce0c5b992ba19f10613f6ab2f (diff) |
skge: use unique IRQ name
Most network drivers request their IRQ when the interface is activated.
skge does it in ->probe() instead, because it can work with two-port
cards where the two net_devices use the same IRQ. This works fine most
of the time, except in some situations when the interface gets renamed.
Consider this example:
1. modprobe skge
The card is detected as eth0 and requests IRQ 17. Directory
/proc/irq/17/eth0 is created.
2. There is an udev rule which says this interface should be called
eth1, so udev renames eth0 -> eth1.
3. modprobe 8139too
The Realtek card is detected as eth0. It will be using IRQ 17 too.
4. ip link set eth0 up
Now 8139too requests IRQ 17.
The result is:
WARNING: at fs/proc/generic.c:590 proc_register ...
proc_dir_entry '17/eth0' already registered
...
And "ls /proc/irq/17" shows two subdirectories, both called eth0.
Fix it by using a unique name for skge's IRQ, based on the PCI address.
The naming from the example then looks like this:
$ grep skge /proc/interrupts
17: 169 IO-APIC-fasteoi skge@pci:0000:00:0a.0, eth0
irqbalance daemon will have to be taught to recognize "skge@" as an
Ethernet interrupt. This will be a one-liner addition in classify.c. I
will send a patch to irqbalance if this change is accepted.
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
Acked-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/skge.c | 7 | ||||
-rw-r--r-- | drivers/net/skge.h | 2 |
2 files changed, 7 insertions, 2 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 2bb21ffbde3a..01f6811f1324 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -3935,11 +3935,14 @@ static int __devinit skge_probe(struct pci_dev *pdev, | |||
3935 | #endif | 3935 | #endif |
3936 | 3936 | ||
3937 | err = -ENOMEM; | 3937 | err = -ENOMEM; |
3938 | hw = kzalloc(sizeof(*hw), GFP_KERNEL); | 3938 | /* space for skge@pci:0000:04:00.0 */ |
3939 | hw = kzalloc(sizeof(*hw) + strlen(DRV_NAME "@pci:" ) | ||
3940 | + strlen(pci_name(pdev)) + 1, GFP_KERNEL); | ||
3939 | if (!hw) { | 3941 | if (!hw) { |
3940 | dev_err(&pdev->dev, "cannot allocate hardware struct\n"); | 3942 | dev_err(&pdev->dev, "cannot allocate hardware struct\n"); |
3941 | goto err_out_free_regions; | 3943 | goto err_out_free_regions; |
3942 | } | 3944 | } |
3945 | sprintf(hw->irq_name, DRV_NAME "@pci:%s", pci_name(pdev)); | ||
3943 | 3946 | ||
3944 | hw->pdev = pdev; | 3947 | hw->pdev = pdev; |
3945 | spin_lock_init(&hw->hw_lock); | 3948 | spin_lock_init(&hw->hw_lock); |
@@ -3974,7 +3977,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, | |||
3974 | goto err_out_free_netdev; | 3977 | goto err_out_free_netdev; |
3975 | } | 3978 | } |
3976 | 3979 | ||
3977 | err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, dev->name, hw); | 3980 | err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, hw->irq_name, hw); |
3978 | if (err) { | 3981 | if (err) { |
3979 | dev_err(&pdev->dev, "%s: cannot assign irq %d\n", | 3982 | dev_err(&pdev->dev, "%s: cannot assign irq %d\n", |
3980 | dev->name, pdev->irq); | 3983 | dev->name, pdev->irq); |
diff --git a/drivers/net/skge.h b/drivers/net/skge.h index 17caccbb7685..831de1b6e96e 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h | |||
@@ -2423,6 +2423,8 @@ struct skge_hw { | |||
2423 | u16 phy_addr; | 2423 | u16 phy_addr; |
2424 | spinlock_t phy_lock; | 2424 | spinlock_t phy_lock; |
2425 | struct tasklet_struct phy_task; | 2425 | struct tasklet_struct phy_task; |
2426 | |||
2427 | char irq_name[0]; /* skge@pci:000:04:00.0 */ | ||
2426 | }; | 2428 | }; |
2427 | 2429 | ||
2428 | enum pause_control { | 2430 | enum pause_control { |