Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] pcmcia: yenta TI: align irq of func1 to func0 if INTRTIE is set

Make sure that if the INTRTIE bit is set both functions of the cardbus
bridge use the same IRQ before doing any probing...

[ yes i hate the TI bridges for the fact that they are very flexible
so that so many BIOS vendors get it wrong. ]

Signed-off-by: Daniel Ritz <daniel.ritz@gmx.ch>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Daniel Ritz and committed by
Linus Torvalds
c835a388 c35e66a4

+30 -10
+30 -10
drivers/pcmcia/ti113x.h
··· 442 442 } 443 443 444 444 445 + /* changes the irq of func1 to match that of func0 */ 446 + static int ti12xx_align_irqs(struct yenta_socket *socket, int *old_irq) 447 + { 448 + struct pci_dev *func0; 449 + 450 + /* find func0 device */ 451 + func0 = pci_get_slot(socket->dev->bus, socket->dev->devfn & ~0x07); 452 + if (!func0) 453 + return 0; 454 + 455 + if (old_irq) 456 + *old_irq = socket->cb_irq; 457 + socket->cb_irq = socket->dev->irq = func0->irq; 458 + 459 + pci_dev_put(func0); 460 + 461 + return 1; 462 + } 463 + 445 464 /* 446 465 * ties INTA and INTB together. also changes the devices irq to that of 447 466 * the function 0 device. call from func1 only. ··· 468 449 */ 469 450 static int ti12xx_tie_interrupts(struct yenta_socket *socket, int *old_irq) 470 451 { 471 - struct pci_dev *func0; 472 452 u32 sysctl; 453 + int ret; 473 454 474 455 sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL); 475 456 if (sysctl & TI122X_SCR_INTRTIE) 476 457 return 0; 477 458 478 - /* find func0 device */ 479 - func0 = pci_get_slot(socket->dev->bus, socket->dev->devfn & ~0x07); 480 - if (!func0) 459 + /* align */ 460 + ret = ti12xx_align_irqs(socket, old_irq); 461 + if (!ret) 481 462 return 0; 482 463 483 - /* change the interrupt to match func0, tie 'em up */ 484 - *old_irq = socket->cb_irq; 485 - socket->cb_irq = socket->dev->irq = func0->irq; 464 + /* tie */ 486 465 sysctl |= TI122X_SCR_INTRTIE; 487 466 config_writel(socket, TI113X_SYSTEM_CONTROL, sysctl); 488 - 489 - pci_dev_put(func0); 490 467 491 468 return 1; 492 469 } ··· 504 489 */ 505 490 static void ti12xx_irqroute_func1(struct yenta_socket *socket) 506 491 { 507 - u32 mfunc, mfunc_old, devctl; 492 + u32 mfunc, mfunc_old, devctl, sysctl; 508 493 int pci_irq_status; 509 494 510 495 mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC); 511 496 devctl = config_readb(socket, TI113X_DEVICE_CONTROL); 512 497 printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n", 513 498 pci_name(socket->dev), mfunc, devctl); 499 + 500 + /* if IRQs are configured as tied, align irq of func1 with func0 */ 501 + sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL); 502 + if (sysctl & TI122X_SCR_INTRTIE) 503 + ti12xx_align_irqs(socket, NULL); 514 504 515 505 /* make sure PCI interrupts are enabled before probing */ 516 506 ti_init(socket);