This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Can only enable 1 MSI with PCIe Keystone II

I am re-posting the question because it was asked a year ago and then was forgotten about:

I am trying to write a kernel module that will handle multiple different MSI interrupts generated from a single EP. During boot I see this:

[   16.741897] keystone-pcie: pcie - number of legacy irqs = 4
[   16.741940] keystone-pcie: pcie - number of MSI host irqs = 8, msi_irqs = 32

I do not necessarily need 32 MSI irqs but why does it show MSI host irqs = 8?

In my kernel module, I call pci_enable_msi_block(dev, 32) and it returns 4 to me. I assume this means that I should then call pci_enable_msi_block(dev, 4) in order to enable 4 MSI interrupts, unfortunately this call returns 1. Which I assume means that the device can only enable 1 MSI interrupts (why would it return 4 before?). I then call pci_enable_block(dev, 1) and sucesfully enable 1 MSI. How do I go about enabling more MSI? Am I correct that since I am enabling host side interrupts, it should not matter how many MSI are enabled on the EP?

Here is a link to the previous post:

e2e.ti.com/.../350070

  • Hi,

    The MSI scheme supports multiple interrupts and each device can request up to 32 interrupt vectors even though the allotted interrupts may be less than the requested number.

    For example, C6678 device have 8 cores, each core will receive separate MSI INTs, that only C6678 have exactly eight MSI group. CorePac 0 will only receive interrupt from MSI_0 (vectors 0/8/16/24). Similarly, Core1 will receive MSI_1 (vectors 1/9/17/25), Core 7 will receive MSI_7, etc.

    PCIExpress_MSI_INTn is connected to CorePac_n in C6678. MSI0 is connected to CorePac0 and only, In software you need to enable the enabled MSI INT and determine the number of MSI vectors allocated (and the number requested) to the device.

    Thanks,
  • I am trying to enable the Interrupts from the ARMs and would like to allocate more than 1. According to the Linux PCIe driver documentation, I should be able to call pci_enable_msi_block() to enable multiple MSI interrupts. If I request 32 MSI interrupts using pci_enable_msi_block(dev, 32) and am unable to get 32 MSI interrupts, then it is supposed to return the number of MSIs that I am able to get. The call to pci_enable_msi_block(dev, 32) returns 4. That should mean that a second call to pci_enable_msi_block(dev, 4) should return success and I should have enabled 4 MSIs. Unfortunately the result to that call returns 1. The following call to pci_enable_msi_block(dev, 1) returns a success and I enable a single MSI, but I would like to enable more than 1 MSI. How would I go about doing this in linux. Again, looking at the previous post from almost a year ago, there is a comment in the kernel driver code that says:

    /*
    * If an architecture wants to support multiple MSI, it needs to
    * override arch_setup_msi_irqs()
    */

    This function is not overridden. Does this mean that TI does not support multiple MSIs from the ARMs in Linux?
  • Hi, Bill,

    Each host irq can be multiplexed to 4 devices, so up to 32 devices.

    In the linux kernel document, MSI-HOWTO.txt, it describes the behavior of pci_enable_msi_block():

    "If this function returns a positive number, it is less than 'count' and indicates the number of interrupts that could have
    been allocated.  In neither case is the irq value updated or the device switched into MSI mode.

    The device driver must decide what action to take if pci_enable_msi_block() returns a value less than the number requested. For instance, the driver could still make use of fewer interrupts; in this case the driver should call pci_enable_msi_block() again.  Note that it is not guaranteed to succeed, even when the 'count' has been reduced to the value returned from a previous call to pci_enable_msi_block().  This is because there are multiple constraints
    on the number of vectors that can be allocated; pci_enable_msi_block() returns as soon as it finds any constraint that doesn't allow the call to succeed."

    In keystone-II implementation, only 1 interrupt per device is supported. Please see drivers/pci/host/pcie-keystone.c in which arch_setup_msi_irq() calls get_free_msi(). get_free_msi() finds the first zero bit and returns it as the interrupt to be used. To allocate multiple interrupts for the device, the application can try to make multiple calls into pci_enable_msi_block() to get multiple interrupts.

    Rex

  • Thanks Rex, I have been looking for this answer for a long time. Why do you think that pci_enable_msi_block() would return 4 the first call, and then fail again on the second call by returning 1?