Before debugging a pci-e MSI interrupt, you need to ensure that the traditional interrupt is tuned before debugging this. MSI interrupts the nature of a memory read-write event. The MSI address is set to one of the addresses in memory (which can be 64 bits), and the interrupt source writes MSI Data at the address where the MSI addresses are generated when an MSI interrupt occurs. That is, if there are four of the MSI disconnected, it will be written to Data, Data+1, data+2, data+3 in memory, in turn, to differentiate the interrupt source device.
Device-side definition
The device defines its own capabilities list in its own configuration space. If the device supports MSI interrupts, in this capabilities list there must be a node in the capabilities id=0x5d (0X5D indicates an MSI interrupt node and its location is customized by the device)
Master Controller
The 1> Master controller's job is to scan the device and then follow through and find the MSI interrupt node along the capabilities list.
2> the host controller assigns values to the address register and the data register registers on the device (for example, in mpc8548e, which is the MSI interrupt register definition decision for the interrupt controller);
Equipment
MSI interrupts, essentially a memory write transaction, where the payload part of the transaction consists of the value of the MSI capabilities register.
The key points here are:
1> Device prepare the capabilities list and the MSI node
2> Controller Assign a value to the address register, which is inside the MSI capability node, and the value assign Ed is the kernel virtual address of the MSI interrupt description register inside the interrupt controller.
3> as, the value assigned to the data register is defined by the MSI registers inside the interrupt controller.
The capabilites list pointer is at the 0x34 offset of config space, which is the root node of all capabilities nodes.
and legacy interrupts are automatically assigned a different interrupt number to the device when the system initializes the scan for PCI bus tree, and MSI interrupts are invoked Pci_enable_msi () kernel API when the device driver initializes When the interrupt number is allocated. So if you use traditional interrupts, you can register the device interrupt handler function directly in the device driver by calling REQUEST_IRQ (PDEV->IRQ, Handler,...). Using MSI interrupts, you first call Pci_enable_msi () initialize the device MSI structure, assign the MSI interrupt number, replace the INTX interrupt number, and then call REQUEST_IRQ (PDEV->IRQ, Handler,...) Registers the device interrupt handler function. Except that the uninstall interrupt handler function needs to call Pci_diable_msi () appropriately, the other processing is exactly the same. The following Linux kernel code describes this process in detail:
int pci_enable_msi (struct pci_dev* dev) {int status;
Status = Pci_msi_check_device (Dev, 1, pci_cap_id_msi);
if (status) return status; WARN_ON (!!)
dev->msi_enabled); if (dev->msix_enabled) {dev_info (&dev->dev, "can ' t enable MSI" "(msi-x already enabled) \ n
");
Return-einval;
Status = Msi_capability_init (dev);//This function configures the device MSI structure and assigns replacement MSI interrupt number} static int msi_capability_init (struct Pci_dev *dev)
{struct MSI_DESC *entry;
int POS, ret;
U16 Control;
... msi_set_enable (dev, 0);
Pci_intx_for_msi (Dev, 0);//Disable Intx interrupts msi_set_enable (Dev, 1);
dev->msi_enabled = 1;
DEV->IRQ = entry->irq;
return 0; }