mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-29 08:08:37 +00:00
PCIe updates for XLS.
Fix interrupt routing so that the irq returned is correct for XLR and XLS. This also updates the MSI hack we had earlier - we still don't really support MSI, but we support some drivers that use MSI, by providing support for allocating one MSI per pci link - this MSI is directly mapped to the link IRQ.
This commit is contained in:
parent
3434740df2
commit
36a7e25854
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=212285
@ -326,51 +326,77 @@ xlr_pcib_identify(driver_t * driver, device_t parent)
|
||||
BUS_ADD_CHILD(parent, 0, "pcib", 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* XLS PCIe can have upto 4 links, and each link has its on IRQ
|
||||
* Find the link on which the device is on
|
||||
*/
|
||||
static int
|
||||
xlr_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
|
||||
xls_pcie_link(device_t pcib, device_t dev)
|
||||
{
|
||||
int pciirq;
|
||||
int i;
|
||||
device_t parent, tmp;
|
||||
|
||||
/* find the lane on which the slot is connected to */
|
||||
printf("xls_pcie_link : bus %s dev %s\n", device_get_nameunit(pcib),
|
||||
device_get_nameunit(dev));
|
||||
tmp = dev;
|
||||
while (1) {
|
||||
parent = device_get_parent(tmp);
|
||||
if (parent == NULL || parent == pcib) {
|
||||
device_printf(dev, "Cannot find parent bus\n");
|
||||
return (ENXIO);
|
||||
return (-1);
|
||||
}
|
||||
if (strcmp(device_get_nameunit(parent), "pci0") == 0)
|
||||
break;
|
||||
tmp = parent;
|
||||
}
|
||||
return (pci_get_slot(tmp));
|
||||
}
|
||||
|
||||
switch (pci_get_slot(tmp)) {
|
||||
/*
|
||||
* Find the IRQ for the link, each link has a different interrupt
|
||||
* at the XLS pic
|
||||
*/
|
||||
static int
|
||||
xls_pcie_link_irq(int link)
|
||||
{
|
||||
|
||||
switch (link) {
|
||||
case 0:
|
||||
pciirq = PIC_PCIE_LINK0_IRQ;
|
||||
break;
|
||||
return (PIC_PCIE_LINK0_IRQ);
|
||||
case 1:
|
||||
pciirq = PIC_PCIE_LINK1_IRQ;
|
||||
break;
|
||||
return (PIC_PCIE_LINK1_IRQ);
|
||||
case 2:
|
||||
pciirq = PIC_PCIE_LINK2_IRQ;
|
||||
break;
|
||||
return (PIC_PCIE_LINK2_IRQ);
|
||||
case 3:
|
||||
pciirq = PIC_PCIE_LINK3_IRQ;
|
||||
break;
|
||||
default:
|
||||
return (ENXIO);
|
||||
return (PIC_PCIE_LINK3_IRQ);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
xlr_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
|
||||
{
|
||||
int i, link;
|
||||
|
||||
irqs[0] = pciirq;
|
||||
/*
|
||||
* For now put in some fixed values for the other requested MSI,
|
||||
* TODO handle multiple messages
|
||||
* Each link has 32 MSIs that can be allocated, but for now
|
||||
* we only support one device per link.
|
||||
* msi_alloc() equivalent is needed when we start supporting
|
||||
* bridges on the PCIe link.
|
||||
*/
|
||||
for (i = 1; i < count; i++)
|
||||
irqs[i] = pciirq + 64 * i;
|
||||
link = xls_pcie_link(pcib, dev);
|
||||
if (link == -1)
|
||||
return (ENXIO);
|
||||
|
||||
/*
|
||||
* encode the irq so that we know it is a MSI interrupt when we
|
||||
* setup interrupts
|
||||
*/
|
||||
for (i = 0; i < count; i++)
|
||||
irqs[i] = 64 + link * 32 + i;
|
||||
|
||||
device_printf(dev, "Alloc MSI count %d maxcount %d irq %d link %d\n",
|
||||
count, maxcount, i, link);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -383,20 +409,18 @@ xlr_release_msi(device_t pcib, device_t dev, int count, int *irqs)
|
||||
}
|
||||
|
||||
static int
|
||||
xlr_map_msi(device_t pcib, device_t dev, int irq, uint64_t * addr,
|
||||
uint32_t * data)
|
||||
xlr_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
|
||||
uint32_t *data)
|
||||
{
|
||||
int msi;
|
||||
|
||||
switch (irq) {
|
||||
case PIC_PCIE_LINK0_IRQ:
|
||||
case PIC_PCIE_LINK1_IRQ:
|
||||
case PIC_PCIE_LINK2_IRQ:
|
||||
case PIC_PCIE_LINK3_IRQ:
|
||||
device_printf(dev, "MAP MSI irq %d\n", irq);
|
||||
if (irq >= 64) {
|
||||
msi = irq - 64;
|
||||
*addr = MIPS_MSI_ADDR(0);
|
||||
*data = MIPS_MSI_DATA(irq);
|
||||
*data = MIPS_MSI_DATA(msi);
|
||||
return (0);
|
||||
|
||||
default:
|
||||
} else {
|
||||
device_printf(dev, "%s: map_msi for irq %d - ignored",
|
||||
device_get_nameunit(pcib), irq);
|
||||
return (ENXIO);
|
||||
@ -437,10 +461,8 @@ bridge_pcie_ack(int irq)
|
||||
|
||||
static int
|
||||
mips_platform_pci_setup_intr(device_t dev, device_t child,
|
||||
struct resource *irq, int flags,
|
||||
driver_filter_t * filt,
|
||||
driver_intr_t * intr, void *arg,
|
||||
void **cookiep)
|
||||
struct resource *irq, int flags, driver_filter_t *filt,
|
||||
driver_intr_t *intr, void *arg, void **cookiep)
|
||||
{
|
||||
int error = 0;
|
||||
int xlrirq;
|
||||
@ -454,6 +476,8 @@ mips_platform_pci_setup_intr(device_t dev, device_t child,
|
||||
return (EINVAL);
|
||||
}
|
||||
xlrirq = rman_get_start(irq);
|
||||
device_printf(dev, "%s: setup intr %d\n", device_get_nameunit(child),
|
||||
xlrirq);
|
||||
|
||||
if (strcmp(device_get_name(dev), "pcib") != 0)
|
||||
return (0);
|
||||
@ -463,6 +487,18 @@ mips_platform_pci_setup_intr(device_t dev, device_t child,
|
||||
intr, arg, PIC_PCIX_IRQ, flags, cookiep, bridge_pcix_ack);
|
||||
pic_setup_intr(PIC_IRT_PCIX_INDEX, PIC_PCIX_IRQ, 0x1, 1);
|
||||
} else {
|
||||
/*
|
||||
* temporary hack for MSI, we support just one device per
|
||||
* link, and assign the link interrupt to the device interrupt
|
||||
*/
|
||||
if (xlrirq >= 64) {
|
||||
xlrirq -= 64;
|
||||
if (xlrirq % 32 != 0)
|
||||
return (0);
|
||||
xlrirq = xls_pcie_link_irq(xlrirq / 32);
|
||||
if (xlrirq == -1)
|
||||
return (EINVAL);
|
||||
}
|
||||
xlr_establish_intr(device_get_name(child), filt,
|
||||
intr, arg, xlrirq, flags, cookiep, bridge_pcie_ack);
|
||||
pic_setup_intr(xlrirq - PIC_IRQ_BASE, xlrirq, 0x1, 1);
|
||||
@ -492,6 +528,9 @@ xlr_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
vm_offset_t va;
|
||||
int needactivate = flags & RF_ACTIVE;
|
||||
|
||||
device_printf(child, "Alloc res type %d, rid %d, start %lx, end %lx, count %lx flags %u\n",
|
||||
type, *rid, start, end, count, flags);
|
||||
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
rm = &irq_rman;
|
||||
@ -559,28 +598,24 @@ xlr_pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
|
||||
static int
|
||||
mips_pci_route_interrupt(device_t bus, device_t dev, int pin)
|
||||
{
|
||||
int irq, link;
|
||||
|
||||
/*
|
||||
* Validate requested pin number.
|
||||
*/
|
||||
device_printf(dev, "route intr pin %d (bus %d, slot %d)\n",
|
||||
pin, pci_get_bus(dev), pci_get_slot(dev));
|
||||
if ((pin < 1) || (pin > 4))
|
||||
return (255);
|
||||
|
||||
if (xlr_board_info.is_xls) {
|
||||
switch (pin) {
|
||||
case 1:
|
||||
return (PIC_PCIE_LINK0_IRQ);
|
||||
case 2:
|
||||
return (PIC_PCIE_LINK1_IRQ);
|
||||
case 3:
|
||||
return (PIC_PCIE_LINK2_IRQ);
|
||||
case 4:
|
||||
return (PIC_PCIE_LINK3_IRQ);
|
||||
}
|
||||
link = xls_pcie_link(bus, dev);
|
||||
irq = xls_pcie_link_irq(link);
|
||||
if (irq != -1)
|
||||
return (irq);
|
||||
} else {
|
||||
if (pin == 1) {
|
||||
return (16);
|
||||
}
|
||||
if (pin == 1)
|
||||
return (PIC_PCIX_IRQ);
|
||||
}
|
||||
|
||||
return (255);
|
||||
|
Loading…
Reference in New Issue
Block a user