in driver_pcicore.c [682:741]
int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
struct ssb_device *dev)
{
struct ssb_device *pdev = pc->dev;
struct ssb_bus *bus;
int err = 0;
u32 tmp;
if (dev->bus->bustype != SSB_BUSTYPE_PCI) {
/* This SSB device is not on a PCI host-bus. So the IRQs are
* not routed through the PCI core.
* So we must not enable routing through the PCI core.
*/
goto out;
}
if (!pdev)
goto out;
bus = pdev->bus;
might_sleep_if(pdev->id.coreid != SSB_DEV_PCI);
/* Enable interrupts for this device. */
if ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE)) {
u32 coremask;
/* Calculate the "coremask" for the device. */
coremask = (1 << dev->core_index);
WARN_ON(bus->bustype != SSB_BUSTYPE_PCI);
err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp);
if (err)
goto out;
tmp |= coremask << 8;
err = pci_write_config_dword(bus->host_pci, SSB_PCI_IRQMASK, tmp);
if (err)
goto out;
} else {
u32 intvec;
intvec = ssb_read32(pdev, SSB_INTVEC);
tmp = ssb_read32(dev, SSB_TPSFLAG);
tmp &= SSB_TPSFLAG_BPFLAG;
intvec |= (1 << tmp);
ssb_write32(pdev, SSB_INTVEC, intvec);
}
/* Setup PCIcore operation. */
if (pc->setup_done)
goto out;
if (pdev->id.coreid == SSB_DEV_PCI) {
ssb_pcicore_pci_setup_workarounds(pc);
} else {
WARN_ON(pdev->id.coreid != SSB_DEV_PCIE);
ssb_pcicore_pcie_setup_workarounds(pc);
}
pc->setup_done = 1;
out:
return err;
}