diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2009-04-07 10:30:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 11:44:06 -0400 |
commit | 51dcdfec6a274afc1c6fce180d582add9ff512c0 (patch) | |
tree | 51442c7adc06f36977859e8133b645c6c42ea0c9 | |
parent | 8e7d91c97570ba1a16c0b4f984c04f04f039a231 (diff) |
parport: Use the PCI IRQ if offered
PCI parallel port devices can IRQ share so we should stop them hogging
the line and making a mess on modern PC systems. We know the sharing
side works as the PCMCIA driver has shared the parallel port IRQ for
some time.
Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/parport/parport_cs.c | 3 | ||||
-rw-r--r-- | drivers/parport/parport_pc.c | 57 | ||||
-rw-r--r-- | drivers/parport/parport_serial.c | 20 | ||||
-rw-r--r-- | include/linux/parport_pc.h | 11 |
4 files changed, 60 insertions, 31 deletions
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 0cd5fbc7f2c2..8fdfa4f537a6 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/timer.h> | 43 | #include <linux/timer.h> |
44 | #include <linux/ioport.h> | 44 | #include <linux/ioport.h> |
45 | #include <linux/major.h> | 45 | #include <linux/major.h> |
46 | #include <linux/interrupt.h> | ||
46 | 47 | ||
47 | #include <linux/parport.h> | 48 | #include <linux/parport.h> |
48 | #include <linux/parport_pc.h> | 49 | #include <linux/parport_pc.h> |
@@ -192,7 +193,7 @@ static int parport_config(struct pcmcia_device *link) | |||
192 | 193 | ||
193 | p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2, | 194 | p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2, |
194 | link->irq.AssignedIRQ, PARPORT_DMA_NONE, | 195 | link->irq.AssignedIRQ, PARPORT_DMA_NONE, |
195 | &link->dev); | 196 | &link->dev, IRQF_SHARED); |
196 | if (p == NULL) { | 197 | if (p == NULL) { |
197 | printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at " | 198 | printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at " |
198 | "0x%3x, irq %u failed\n", link->io.BasePort1, | 199 | "0x%3x, irq %u failed\n", link->io.BasePort1, |
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 96f3bdf0ec4b..4e63cc9e2778 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
@@ -2170,10 +2170,11 @@ static int parport_dma_probe (struct parport *p) | |||
2170 | static LIST_HEAD(ports_list); | 2170 | static LIST_HEAD(ports_list); |
2171 | static DEFINE_SPINLOCK(ports_lock); | 2171 | static DEFINE_SPINLOCK(ports_lock); |
2172 | 2172 | ||
2173 | struct parport *parport_pc_probe_port (unsigned long int base, | 2173 | struct parport *parport_pc_probe_port(unsigned long int base, |
2174 | unsigned long int base_hi, | 2174 | unsigned long int base_hi, |
2175 | int irq, int dma, | 2175 | int irq, int dma, |
2176 | struct device *dev) | 2176 | struct device *dev, |
2177 | int irqflags) | ||
2177 | { | 2178 | { |
2178 | struct parport_pc_private *priv; | 2179 | struct parport_pc_private *priv; |
2179 | struct parport_operations *ops; | 2180 | struct parport_operations *ops; |
@@ -2194,11 +2195,11 @@ struct parport *parport_pc_probe_port (unsigned long int base, | |||
2194 | dev = &pdev->dev; | 2195 | dev = &pdev->dev; |
2195 | } | 2196 | } |
2196 | 2197 | ||
2197 | ops = kmalloc(sizeof (struct parport_operations), GFP_KERNEL); | 2198 | ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); |
2198 | if (!ops) | 2199 | if (!ops) |
2199 | goto out1; | 2200 | goto out1; |
2200 | 2201 | ||
2201 | priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL); | 2202 | priv = kmalloc(sizeof(struct parport_pc_private), GFP_KERNEL); |
2202 | if (!priv) | 2203 | if (!priv) |
2203 | goto out2; | 2204 | goto out2; |
2204 | 2205 | ||
@@ -2325,8 +2326,8 @@ struct parport *parport_pc_probe_port (unsigned long int base, | |||
2325 | EPP_res = NULL; | 2326 | EPP_res = NULL; |
2326 | } | 2327 | } |
2327 | if (p->irq != PARPORT_IRQ_NONE) { | 2328 | if (p->irq != PARPORT_IRQ_NONE) { |
2328 | if (request_irq (p->irq, parport_irq_handler, | 2329 | if (request_irq(p->irq, parport_irq_handler, |
2329 | 0, p->name, p)) { | 2330 | irqflags, p->name, p)) { |
2330 | printk (KERN_WARNING "%s: irq %d in use, " | 2331 | printk (KERN_WARNING "%s: irq %d in use, " |
2331 | "resorting to polled operation\n", | 2332 | "resorting to polled operation\n", |
2332 | p->name, p->irq); | 2333 | p->name, p->irq); |
@@ -2530,7 +2531,7 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq, | |||
2530 | */ | 2531 | */ |
2531 | release_resource(base_res); | 2532 | release_resource(base_res); |
2532 | if (parport_pc_probe_port (ite8872_lpt, ite8872_lpthi, | 2533 | if (parport_pc_probe_port (ite8872_lpt, ite8872_lpthi, |
2533 | irq, PARPORT_DMA_NONE, &pdev->dev)) { | 2534 | irq, PARPORT_DMA_NONE, &pdev->dev, 0)) { |
2534 | printk (KERN_INFO | 2535 | printk (KERN_INFO |
2535 | "parport_pc: ITE 8872 parallel port: io=0x%X", | 2536 | "parport_pc: ITE 8872 parallel port: io=0x%X", |
2536 | ite8872_lpt); | 2537 | ite8872_lpt); |
@@ -2713,7 +2714,7 @@ static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq, | |||
2713 | } | 2714 | } |
2714 | 2715 | ||
2715 | /* finally, do the probe with values obtained */ | 2716 | /* finally, do the probe with values obtained */ |
2716 | if (parport_pc_probe_port (port1, port2, irq, dma, &pdev->dev)) { | 2717 | if (parport_pc_probe_port (port1, port2, irq, dma, &pdev->dev, 0)) { |
2717 | printk (KERN_INFO | 2718 | printk (KERN_INFO |
2718 | "parport_pc: VIA parallel port: io=0x%X", port1); | 2719 | "parport_pc: VIA parallel port: io=0x%X", port1); |
2719 | if (irq != PARPORT_IRQ_NONE) | 2720 | if (irq != PARPORT_IRQ_NONE) |
@@ -3018,6 +3019,7 @@ static int parport_pc_pci_probe (struct pci_dev *dev, | |||
3018 | for (n = 0; n < cards[i].numports; n++) { | 3019 | for (n = 0; n < cards[i].numports; n++) { |
3019 | int lo = cards[i].addr[n].lo; | 3020 | int lo = cards[i].addr[n].lo; |
3020 | int hi = cards[i].addr[n].hi; | 3021 | int hi = cards[i].addr[n].hi; |
3022 | int irq; | ||
3021 | unsigned long io_lo, io_hi; | 3023 | unsigned long io_lo, io_hi; |
3022 | io_lo = pci_resource_start (dev, lo); | 3024 | io_lo = pci_resource_start (dev, lo); |
3023 | io_hi = 0; | 3025 | io_hi = 0; |
@@ -3028,13 +3030,25 @@ static int parport_pc_pci_probe (struct pci_dev *dev, | |||
3028 | "hi" as an offset (see SYBA | 3030 | "hi" as an offset (see SYBA |
3029 | def.) */ | 3031 | def.) */ |
3030 | /* TODO: test if sharing interrupts works */ | 3032 | /* TODO: test if sharing interrupts works */ |
3031 | printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, " | 3033 | irq = dev->irq; |
3032 | "I/O at %#lx(%#lx)\n", | 3034 | if (irq == IRQ_NONE) { |
3033 | parport_pc_pci_tbl[i + last_sio].vendor, | 3035 | printk (KERN_DEBUG |
3034 | parport_pc_pci_tbl[i + last_sio].device, io_lo, io_hi); | 3036 | "PCI parallel port detected: %04x:%04x, I/O at %#lx(%#lx)\n", |
3037 | parport_pc_pci_tbl[i + last_sio].vendor, | ||
3038 | parport_pc_pci_tbl[i + last_sio].device, | ||
3039 | io_lo, io_hi); | ||
3040 | irq = PARPORT_IRQ_NONE; | ||
3041 | } else { | ||
3042 | printk (KERN_DEBUG | ||
3043 | "PCI parallel port detected: %04x:%04x, I/O at %#lx(%#lx), IRQ %d\n", | ||
3044 | parport_pc_pci_tbl[i + last_sio].vendor, | ||
3045 | parport_pc_pci_tbl[i + last_sio].device, | ||
3046 | io_lo, io_hi, irq); | ||
3047 | } | ||
3035 | data->ports[count] = | 3048 | data->ports[count] = |
3036 | parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE, | 3049 | parport_pc_probe_port(io_lo, io_hi, irq, |
3037 | PARPORT_DMA_NONE, &dev->dev); | 3050 | PARPORT_DMA_NONE, &dev->dev, |
3051 | IRQF_SHARED); | ||
3038 | if (data->ports[count]) | 3052 | if (data->ports[count]) |
3039 | count++; | 3053 | count++; |
3040 | } | 3054 | } |
@@ -3143,7 +3157,8 @@ static int parport_pc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id | |||
3143 | dma = PARPORT_DMA_NONE; | 3157 | dma = PARPORT_DMA_NONE; |
3144 | 3158 | ||
3145 | dev_info(&dev->dev, "reported by %s\n", dev->protocol->name); | 3159 | dev_info(&dev->dev, "reported by %s\n", dev->protocol->name); |
3146 | if (!(pdata = parport_pc_probe_port (io_lo, io_hi, irq, dma, &dev->dev))) | 3160 | if (!(pdata = parport_pc_probe_port(io_lo, io_hi, |
3161 | irq, dma, &dev->dev, 0))) | ||
3147 | return -ENODEV; | 3162 | return -ENODEV; |
3148 | 3163 | ||
3149 | pnp_set_drvdata(dev,pdata); | 3164 | pnp_set_drvdata(dev,pdata); |
@@ -3192,11 +3207,11 @@ parport_pc_find_isa_ports (int autoirq, int autodma) | |||
3192 | { | 3207 | { |
3193 | int count = 0; | 3208 | int count = 0; |
3194 | 3209 | ||
3195 | if (parport_pc_probe_port(0x3bc, 0x7bc, autoirq, autodma, NULL)) | 3210 | if (parport_pc_probe_port(0x3bc, 0x7bc, autoirq, autodma, NULL, 0)) |
3196 | count++; | 3211 | count++; |
3197 | if (parport_pc_probe_port(0x378, 0x778, autoirq, autodma, NULL)) | 3212 | if (parport_pc_probe_port(0x378, 0x778, autoirq, autodma, NULL, 0)) |
3198 | count++; | 3213 | count++; |
3199 | if (parport_pc_probe_port(0x278, 0x678, autoirq, autodma, NULL)) | 3214 | if (parport_pc_probe_port(0x278, 0x678, autoirq, autodma, NULL, 0)) |
3200 | count++; | 3215 | count++; |
3201 | 3216 | ||
3202 | return count; | 3217 | return count; |
@@ -3481,7 +3496,7 @@ static int __init parport_pc_init(void) | |||
3481 | if ((io_hi[i]) == PARPORT_IOHI_AUTO) | 3496 | if ((io_hi[i]) == PARPORT_IOHI_AUTO) |
3482 | io_hi[i] = 0x400 + io[i]; | 3497 | io_hi[i] = 0x400 + io[i]; |
3483 | parport_pc_probe_port(io[i], io_hi[i], | 3498 | parport_pc_probe_port(io[i], io_hi[i], |
3484 | irqval[i], dmaval[i], NULL); | 3499 | irqval[i], dmaval[i], NULL, 0); |
3485 | } | 3500 | } |
3486 | } else | 3501 | } else |
3487 | parport_pc_find_ports (irqval[0], dmaval[0]); | 3502 | parport_pc_find_ports (irqval[0], dmaval[0]); |
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index f3492110b1ad..c3bb84ac931e 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/interrupt.h> | ||
24 | #include <linux/parport.h> | 25 | #include <linux/parport.h> |
25 | #include <linux/parport_pc.h> | 26 | #include <linux/parport_pc.h> |
26 | #include <linux/8250_pci.h> | 27 | #include <linux/8250_pci.h> |
@@ -311,6 +312,7 @@ static int __devinit parport_register (struct pci_dev *dev, | |||
311 | int lo = card->addr[n].lo; | 312 | int lo = card->addr[n].lo; |
312 | int hi = card->addr[n].hi; | 313 | int hi = card->addr[n].hi; |
313 | unsigned long io_lo, io_hi; | 314 | unsigned long io_lo, io_hi; |
315 | int irq; | ||
314 | 316 | ||
315 | if (priv->num_par == ARRAY_SIZE (priv->port)) { | 317 | if (priv->num_par == ARRAY_SIZE (priv->port)) { |
316 | printk (KERN_WARNING | 318 | printk (KERN_WARNING |
@@ -329,10 +331,20 @@ static int __devinit parport_register (struct pci_dev *dev, | |||
329 | "hi" as an offset (see SYBA | 331 | "hi" as an offset (see SYBA |
330 | def.) */ | 332 | def.) */ |
331 | /* TODO: test if sharing interrupts works */ | 333 | /* TODO: test if sharing interrupts works */ |
332 | dev_dbg(&dev->dev, "PCI parallel port detected: I/O at " | 334 | irq = dev->irq; |
333 | "%#lx(%#lx)\n", io_lo, io_hi); | 335 | if (irq == IRQ_NONE) { |
334 | port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE, | 336 | dev_dbg(&dev->dev, |
335 | PARPORT_DMA_NONE, &dev->dev); | 337 | "PCI parallel port detected: I/O at %#lx(%#lx)\n", |
338 | io_lo, io_hi); | ||
339 | irq = PARPORT_IRQ_NONE; | ||
340 | } else { | ||
341 | dev_dbg(&dev->dev, | ||
342 | "PCI parallel port detected: I/O at %#lx(%#lx), IRQ %d\n", | ||
343 | io_lo, io_hi, irq); | ||
344 | irq = PARPORT_IRQ_NONE; | ||
345 | } | ||
346 | port = parport_pc_probe_port (io_lo, io_hi, irq, | ||
347 | PARPORT_DMA_NONE, &dev->dev, IRQF_SHARED); | ||
336 | if (port) { | 348 | if (port) { |
337 | priv->port[priv->num_par++] = port; | 349 | priv->port[priv->num_par++] = port; |
338 | success = 1; | 350 | success = 1; |
diff --git a/include/linux/parport_pc.h b/include/linux/parport_pc.h index ea8c6d84996d..cc1767f5cca8 100644 --- a/include/linux/parport_pc.h +++ b/include/linux/parport_pc.h | |||
@@ -228,10 +228,11 @@ extern void parport_pc_release_resources(struct parport *p); | |||
228 | extern int parport_pc_claim_resources(struct parport *p); | 228 | extern int parport_pc_claim_resources(struct parport *p); |
229 | 229 | ||
230 | /* PCMCIA code will want to get us to look at a port. Provide a mechanism. */ | 230 | /* PCMCIA code will want to get us to look at a port. Provide a mechanism. */ |
231 | extern struct parport *parport_pc_probe_port (unsigned long base, | 231 | extern struct parport *parport_pc_probe_port(unsigned long base, |
232 | unsigned long base_hi, | 232 | unsigned long base_hi, |
233 | int irq, int dma, | 233 | int irq, int dma, |
234 | struct device *dev); | 234 | struct device *dev, |
235 | extern void parport_pc_unregister_port (struct parport *p); | 235 | int irqflags); |
236 | extern void parport_pc_unregister_port(struct parport *p); | ||
236 | 237 | ||
237 | #endif | 238 | #endif |