Ejemplo n.º 1
0
static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
{
    struct msi_desc *entry;
    struct msg_address address;
    unsigned int irq = vector;
    unsigned int dest_cpu = first_cpu(cpu_mask);

    entry = (struct msi_desc *)msi_desc[vector];
    if (!entry || !entry->dev)
        return;

    switch (entry->msi_attrib.type) {
    case PCI_CAP_ID_MSI:
    {
        int pos;

        if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI)))
            return;

        pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
                              &address.lo_address.value);
        address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
        address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
                                     MSI_TARGET_CPU_SHIFT);
        entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
        pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
                               address.lo_address.value);
        set_native_irq_info(irq, cpu_mask);
        break;
    }
    case PCI_CAP_ID_MSIX:
    {
        int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
                     PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;

        address.lo_address.value = readl(entry->mask_base + offset);
        address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
        address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
                                     MSI_TARGET_CPU_SHIFT);
        entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
        writel(address.lo_address.value, entry->mask_base + offset);
        set_native_irq_info(irq, cpu_mask);
        break;
    }
    default:
        break;
    }
}
Ejemplo n.º 2
0
static int msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
{
	int status;
	u32 address_hi;
	u32 address_lo;
	u32 data;
	int pos, vector = dev->irq;
	u16 control;

   	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
	pci_read_config_word(dev, msi_control_reg(pos), &control);

	/* Configure MSI capability structure */
	status = msi_ops->setup(dev, vector, &address_hi, &address_lo, &data);
	if (status < 0)
		return status;

	pci_write_config_dword(dev, msi_lower_address_reg(pos), address_lo);
	if (is_64bit_address(control)) {
		pci_write_config_dword(dev,
			msi_upper_address_reg(pos), address_hi);
		pci_write_config_word(dev,
			msi_data_reg(pos, 1), data);
	} else
		pci_write_config_word(dev,
			msi_data_reg(pos, 0), data);
	if (entry->msi_attrib.maskbit) {
		unsigned int maskbits, temp;
		/* All MSIs are unmasked by default, Mask them all */
		pci_read_config_dword(dev,
			msi_mask_bits_reg(pos, is_64bit_address(control)),
			&maskbits);
		temp = (1 << multi_msi_capable(control));
		temp = ((temp - 1) & ~temp);
		maskbits |= temp;
		pci_write_config_dword(dev,
			msi_mask_bits_reg(pos, is_64bit_address(control)),
			maskbits);
	}

	return 0;
}
Ejemplo n.º 3
0
static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
{
	struct msi_desc *entry;
	u32 address_hi, address_lo;
	unsigned int irq = vector;
	unsigned int dest_cpu = first_cpu(cpu_mask);
	unsigned long flags;

	spin_lock_irqsave(&msi_lock, flags);

	entry = (struct msi_desc *)msi_desc[vector];
	if (!entry || !entry->dev)
		goto out_unlock;

	if (entry->msi_attrib.state == 0)
		goto out_unlock;

	switch (entry->msi_attrib.type) {
	case PCI_CAP_ID_MSI:
	{
		int pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI);

		if (!pos)
			goto out_unlock;

		pci_read_config_dword(entry->dev, msi_upper_address_reg(pos),
			&address_hi);
		pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
			&address_lo);

		msi_ops->target(vector, dest_cpu, &address_hi, &address_lo);

		pci_write_config_dword(entry->dev, msi_upper_address_reg(pos),
			address_hi);
		pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
			address_lo);
		set_native_irq_info(irq, cpu_mask);
		break;
	}
	case PCI_CAP_ID_MSIX:
	{
		int offset_hi =
			entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
				PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET;
		int offset_lo =
			entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
				PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;

		address_hi = readl(entry->mask_base + offset_hi);
		address_lo = readl(entry->mask_base + offset_lo);

		msi_ops->target(vector, dest_cpu, &address_hi, &address_lo);

		writel(address_hi, entry->mask_base + offset_hi);
		writel(address_lo, entry->mask_base + offset_lo);
		set_native_irq_info(irq, cpu_mask);
		break;
	}
	default:
		break;
	}

out_unlock:
	spin_unlock_irqrestore(&msi_lock, flags);
}
Ejemplo n.º 4
0
/**
 * msi_capability_init - configure device's MSI capability structure
 * @dev: pointer to the pci_dev data structure of MSI device function
 *
 * Setup the MSI capability structure of device function with a single
 * MSI vector, regardless of device function is capable of handling
 * multiple messages. A return of zero indicates the successful setup
 * of an entry zero with the new MSI vector or non-zero for otherwise.
 **/
static int msi_capability_init(struct pci_dev *dev)
{
    struct msi_desc *entry;
    struct msg_address address;
    struct msg_data data;
    int pos, vector;
    u16 control;

    pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
    pci_read_config_word(dev, msi_control_reg(pos), &control);
    /* MSI Entry Initialization */
    if (!(entry = alloc_msi_entry()))
        return -ENOMEM;

    if ((vector = get_msi_vector(dev)) < 0) {
        kmem_cache_free(msi_cachep, entry);
        return -EBUSY;
    }
    entry->link.head = vector;
    entry->link.tail = vector;
    entry->msi_attrib.type = PCI_CAP_ID_MSI;
    entry->msi_attrib.state = 0;			/* Mark it not active */
    entry->msi_attrib.entry_nr = 0;
    entry->msi_attrib.maskbit = is_mask_bit_support(control);
    entry->msi_attrib.default_vector = dev->irq;	/* Save IOAPIC IRQ */
    dev->irq = vector;
    entry->dev = dev;
    if (is_mask_bit_support(control)) {
        entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
                           is_64bit_address(control));
    }
    /* Replace with MSI handler */
    irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
    /* Configure MSI capability structure */
    msi_address_init(&address);
    msi_data_init(&data, vector);
    entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
                                      MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
    pci_write_config_dword(dev, msi_lower_address_reg(pos),
                           address.lo_address.value);
    if (is_64bit_address(control)) {
        pci_write_config_dword(dev,
                               msi_upper_address_reg(pos), address.hi_address);
        pci_write_config_word(dev,
                              msi_data_reg(pos, 1), *((u32*)&data));
    } else
        pci_write_config_word(dev,
                              msi_data_reg(pos, 0), *((u32*)&data));
    if (entry->msi_attrib.maskbit) {
        unsigned int maskbits, temp;
        /* All MSIs are unmasked by default, Mask them all */
        pci_read_config_dword(dev,
                              msi_mask_bits_reg(pos, is_64bit_address(control)),
                              &maskbits);
        temp = (1 << multi_msi_capable(control));
        temp = ((temp - 1) & ~temp);
        maskbits |= temp;
        pci_write_config_dword(dev,
                               msi_mask_bits_reg(pos, is_64bit_address(control)),
                               maskbits);
    }
    attach_msi_entry(entry, vector);
    /* Set MSI enabled bits	 */
    enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);

    return 0;
}