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>
This commit is contained in:
Alan Cox 2009-04-07 15:30:57 +01:00 коммит произвёл Linus Torvalds
Родитель 8e7d91c975
Коммит 51dcdfec6a
4 изменённых файлов: 60 добавлений и 31 удалений

Просмотреть файл

@ -43,6 +43,7 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/interrupt.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/parport_pc.h> #include <linux/parport_pc.h>
@ -192,7 +193,7 @@ static int parport_config(struct pcmcia_device *link)
p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2, p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,
link->irq.AssignedIRQ, PARPORT_DMA_NONE, link->irq.AssignedIRQ, PARPORT_DMA_NONE,
&link->dev); &link->dev, IRQF_SHARED);
if (p == NULL) { if (p == NULL) {
printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at " printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at "
"0x%3x, irq %u failed\n", link->io.BasePort1, "0x%3x, irq %u failed\n", link->io.BasePort1,

Просмотреть файл

@ -2170,10 +2170,11 @@ static int parport_dma_probe (struct parport *p)
static LIST_HEAD(ports_list); static LIST_HEAD(ports_list);
static DEFINE_SPINLOCK(ports_lock); static DEFINE_SPINLOCK(ports_lock);
struct parport *parport_pc_probe_port (unsigned long int base, struct parport *parport_pc_probe_port(unsigned long int base,
unsigned long int base_hi, unsigned long int base_hi,
int irq, int dma, int irq, int dma,
struct device *dev) struct device *dev,
int irqflags)
{ {
struct parport_pc_private *priv; struct parport_pc_private *priv;
struct parport_operations *ops; struct parport_operations *ops;
@ -2194,11 +2195,11 @@ struct parport *parport_pc_probe_port (unsigned long int base,
dev = &pdev->dev; dev = &pdev->dev;
} }
ops = kmalloc(sizeof (struct parport_operations), GFP_KERNEL); ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL);
if (!ops) if (!ops)
goto out1; goto out1;
priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL); priv = kmalloc(sizeof(struct parport_pc_private), GFP_KERNEL);
if (!priv) if (!priv)
goto out2; goto out2;
@ -2325,8 +2326,8 @@ struct parport *parport_pc_probe_port (unsigned long int base,
EPP_res = NULL; EPP_res = NULL;
} }
if (p->irq != PARPORT_IRQ_NONE) { if (p->irq != PARPORT_IRQ_NONE) {
if (request_irq (p->irq, parport_irq_handler, if (request_irq(p->irq, parport_irq_handler,
0, p->name, p)) { irqflags, p->name, p)) {
printk (KERN_WARNING "%s: irq %d in use, " printk (KERN_WARNING "%s: irq %d in use, "
"resorting to polled operation\n", "resorting to polled operation\n",
p->name, p->irq); p->name, p->irq);
@ -2530,7 +2531,7 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
*/ */
release_resource(base_res); release_resource(base_res);
if (parport_pc_probe_port (ite8872_lpt, ite8872_lpthi, if (parport_pc_probe_port (ite8872_lpt, ite8872_lpthi,
irq, PARPORT_DMA_NONE, &pdev->dev)) { irq, PARPORT_DMA_NONE, &pdev->dev, 0)) {
printk (KERN_INFO printk (KERN_INFO
"parport_pc: ITE 8872 parallel port: io=0x%X", "parport_pc: ITE 8872 parallel port: io=0x%X",
ite8872_lpt); ite8872_lpt);
@ -2713,7 +2714,7 @@ static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq,
} }
/* finally, do the probe with values obtained */ /* finally, do the probe with values obtained */
if (parport_pc_probe_port (port1, port2, irq, dma, &pdev->dev)) { if (parport_pc_probe_port (port1, port2, irq, dma, &pdev->dev, 0)) {
printk (KERN_INFO printk (KERN_INFO
"parport_pc: VIA parallel port: io=0x%X", port1); "parport_pc: VIA parallel port: io=0x%X", port1);
if (irq != PARPORT_IRQ_NONE) if (irq != PARPORT_IRQ_NONE)
@ -3018,6 +3019,7 @@ static int parport_pc_pci_probe (struct pci_dev *dev,
for (n = 0; n < cards[i].numports; n++) { for (n = 0; n < cards[i].numports; n++) {
int lo = cards[i].addr[n].lo; int lo = cards[i].addr[n].lo;
int hi = cards[i].addr[n].hi; int hi = cards[i].addr[n].hi;
int irq;
unsigned long io_lo, io_hi; unsigned long io_lo, io_hi;
io_lo = pci_resource_start (dev, lo); io_lo = pci_resource_start (dev, lo);
io_hi = 0; io_hi = 0;
@ -3028,13 +3030,25 @@ static int parport_pc_pci_probe (struct pci_dev *dev,
"hi" as an offset (see SYBA "hi" as an offset (see SYBA
def.) */ def.) */
/* TODO: test if sharing interrupts works */ /* TODO: test if sharing interrupts works */
printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, " irq = dev->irq;
"I/O at %#lx(%#lx)\n", if (irq == IRQ_NONE) {
parport_pc_pci_tbl[i + last_sio].vendor, printk (KERN_DEBUG
parport_pc_pci_tbl[i + last_sio].device, io_lo, io_hi); "PCI parallel port detected: %04x:%04x, I/O at %#lx(%#lx)\n",
parport_pc_pci_tbl[i + last_sio].vendor,
parport_pc_pci_tbl[i + last_sio].device,
io_lo, io_hi);
irq = PARPORT_IRQ_NONE;
} else {
printk (KERN_DEBUG
"PCI parallel port detected: %04x:%04x, I/O at %#lx(%#lx), IRQ %d\n",
parport_pc_pci_tbl[i + last_sio].vendor,
parport_pc_pci_tbl[i + last_sio].device,
io_lo, io_hi, irq);
}
data->ports[count] = data->ports[count] =
parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE, parport_pc_probe_port(io_lo, io_hi, irq,
PARPORT_DMA_NONE, &dev->dev); PARPORT_DMA_NONE, &dev->dev,
IRQF_SHARED);
if (data->ports[count]) if (data->ports[count])
count++; count++;
} }
@ -3143,7 +3157,8 @@ static int parport_pc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id
dma = PARPORT_DMA_NONE; dma = PARPORT_DMA_NONE;
dev_info(&dev->dev, "reported by %s\n", dev->protocol->name); dev_info(&dev->dev, "reported by %s\n", dev->protocol->name);
if (!(pdata = parport_pc_probe_port (io_lo, io_hi, irq, dma, &dev->dev))) if (!(pdata = parport_pc_probe_port(io_lo, io_hi,
irq, dma, &dev->dev, 0)))
return -ENODEV; return -ENODEV;
pnp_set_drvdata(dev,pdata); pnp_set_drvdata(dev,pdata);
@ -3192,11 +3207,11 @@ parport_pc_find_isa_ports (int autoirq, int autodma)
{ {
int count = 0; int count = 0;
if (parport_pc_probe_port(0x3bc, 0x7bc, autoirq, autodma, NULL)) if (parport_pc_probe_port(0x3bc, 0x7bc, autoirq, autodma, NULL, 0))
count++; count++;
if (parport_pc_probe_port(0x378, 0x778, autoirq, autodma, NULL)) if (parport_pc_probe_port(0x378, 0x778, autoirq, autodma, NULL, 0))
count++; count++;
if (parport_pc_probe_port(0x278, 0x678, autoirq, autodma, NULL)) if (parport_pc_probe_port(0x278, 0x678, autoirq, autodma, NULL, 0))
count++; count++;
return count; return count;
@ -3481,7 +3496,7 @@ static int __init parport_pc_init(void)
if ((io_hi[i]) == PARPORT_IOHI_AUTO) if ((io_hi[i]) == PARPORT_IOHI_AUTO)
io_hi[i] = 0x400 + io[i]; io_hi[i] = 0x400 + io[i];
parport_pc_probe_port(io[i], io_hi[i], parport_pc_probe_port(io[i], io_hi[i],
irqval[i], dmaval[i], NULL); irqval[i], dmaval[i], NULL, 0);
} }
} else } else
parport_pc_find_ports (irqval[0], dmaval[0]); parport_pc_find_ports (irqval[0], dmaval[0]);

Просмотреть файл

@ -21,6 +21,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/parport.h> #include <linux/parport.h>
#include <linux/parport_pc.h> #include <linux/parport_pc.h>
#include <linux/8250_pci.h> #include <linux/8250_pci.h>
@ -311,6 +312,7 @@ static int __devinit parport_register (struct pci_dev *dev,
int lo = card->addr[n].lo; int lo = card->addr[n].lo;
int hi = card->addr[n].hi; int hi = card->addr[n].hi;
unsigned long io_lo, io_hi; unsigned long io_lo, io_hi;
int irq;
if (priv->num_par == ARRAY_SIZE (priv->port)) { if (priv->num_par == ARRAY_SIZE (priv->port)) {
printk (KERN_WARNING printk (KERN_WARNING
@ -329,10 +331,20 @@ static int __devinit parport_register (struct pci_dev *dev,
"hi" as an offset (see SYBA "hi" as an offset (see SYBA
def.) */ def.) */
/* TODO: test if sharing interrupts works */ /* TODO: test if sharing interrupts works */
dev_dbg(&dev->dev, "PCI parallel port detected: I/O at " irq = dev->irq;
"%#lx(%#lx)\n", io_lo, io_hi); if (irq == IRQ_NONE) {
port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE, dev_dbg(&dev->dev,
PARPORT_DMA_NONE, &dev->dev); "PCI parallel port detected: I/O at %#lx(%#lx)\n",
io_lo, io_hi);
irq = PARPORT_IRQ_NONE;
} else {
dev_dbg(&dev->dev,
"PCI parallel port detected: I/O at %#lx(%#lx), IRQ %d\n",
io_lo, io_hi, irq);
irq = PARPORT_IRQ_NONE;
}
port = parport_pc_probe_port (io_lo, io_hi, irq,
PARPORT_DMA_NONE, &dev->dev, IRQF_SHARED);
if (port) { if (port) {
priv->port[priv->num_par++] = port; priv->port[priv->num_par++] = port;
success = 1; success = 1;

Просмотреть файл

@ -228,10 +228,11 @@ extern void parport_pc_release_resources(struct parport *p);
extern int parport_pc_claim_resources(struct parport *p); extern int parport_pc_claim_resources(struct parport *p);
/* PCMCIA code will want to get us to look at a port. Provide a mechanism. */ /* PCMCIA code will want to get us to look at a port. Provide a mechanism. */
extern struct parport *parport_pc_probe_port (unsigned long base, extern struct parport *parport_pc_probe_port(unsigned long base,
unsigned long base_hi, unsigned long base_hi,
int irq, int dma, int irq, int dma,
struct device *dev); struct device *dev,
extern void parport_pc_unregister_port (struct parport *p); int irqflags);
extern void parport_pc_unregister_port(struct parport *p);
#endif #endif