From owner-svn-src-head@FreeBSD.ORG Tue Sep 7 07:31:58 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8B5461065693; Tue, 7 Sep 2010 07:31:58 +0000 (UTC) (envelope-from jchandra@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7A29F8FC08; Tue, 7 Sep 2010 07:31:58 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o877Vwpn086529; Tue, 7 Sep 2010 07:31:58 GMT (envelope-from jchandra@svn.freebsd.org) Received: (from jchandra@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o877VwfN086527; Tue, 7 Sep 2010 07:31:58 GMT (envelope-from jchandra@svn.freebsd.org) Message-Id: <201009070731.o877VwfN086527@svn.freebsd.org> From: "Jayachandran C." Date: Tue, 7 Sep 2010 07:31:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212285 - head/sys/mips/rmi X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Sep 2010 07:31:58 -0000 Author: jchandra Date: Tue Sep 7 07:31:58 2010 New Revision: 212285 URL: http://svn.freebsd.org/changeset/base/212285 Log: 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. Modified: head/sys/mips/rmi/xlr_pci.c Modified: head/sys/mips/rmi/xlr_pci.c ============================================================================== --- head/sys/mips/rmi/xlr_pci.c Tue Sep 7 06:02:43 2010 (r212284) +++ head/sys/mips/rmi/xlr_pci.c Tue Sep 7 07:31:58 2010 (r212285) @@ -326,51 +326,77 @@ xlr_pcib_identify(driver_t * driver, dev 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)); +} + +/* + * 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 (pci_get_slot(tmp)) { + 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 } 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 de 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 de 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, dev 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 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);