int ssb_pcicore_dev_irqvecs_enable()

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;
}