From owner-p4-projects@FreeBSD.ORG Mon Jun 8 10:29:27 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 54EE71065679; Mon, 8 Jun 2009 10:29:27 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0DBF1106564A for ; Mon, 8 Jun 2009 10:29:27 +0000 (UTC) (envelope-from mav@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 980068FC18 for ; Mon, 8 Jun 2009 10:29:26 +0000 (UTC) (envelope-from mav@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n58ATQok011478 for ; Mon, 8 Jun 2009 10:29:26 GMT (envelope-from mav@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n58ATQ6w011476 for perforce@freebsd.org; Mon, 8 Jun 2009 10:29:26 GMT (envelope-from mav@freebsd.org) Date: Mon, 8 Jun 2009 10:29:26 GMT Message-Id: <200906081029.n58ATQ6w011476@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to mav@freebsd.org using -f From: Alexander Motin To: Perforce Change Reviews Cc: Subject: PERFORCE change 163771 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 08 Jun 2009 10:29:28 -0000 http://perforce.freebsd.org/chv.cgi?CH=163771 Change 163771 by mav@mav_mavbook on 2009/06/08 10:29:12 Add multi-vector MSI mode support.. Affected files ... .. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#19 edit .. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#7 edit Differences ... ==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#19 (text+ko) ==== @@ -57,6 +57,7 @@ /* local prototypes */ static int ahci_setup_interrupt(device_t dev); static void ahci_intr(void *data); +static void ahci_intr_one(void *data); static int ahci_suspend(device_t dev); static int ahci_resume(device_t dev); static int ahci_ch_suspend(device_t dev); @@ -138,12 +139,6 @@ return (error); } - if (ahci_setup_interrupt(dev)) { - bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); - rman_fini(&ctlr->sc_iomem); - return ENXIO; - } - /* reset controller */ if ((error = ahci_ctlr_reset(dev)) != 0) { bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); @@ -156,6 +151,12 @@ ctlr->channels = MAX(flsl(ctlr->ichannels), (ATA_INL(ctlr->r_mem, AHCI_CAP) & AHCI_CAP_NPMASK) + 1); + if (ahci_setup_interrupt(dev)) { + bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); + rman_fini(&ctlr->sc_iomem); + return ENXIO; + } + /* announce we support the HW */ version = ATA_INL(ctlr->r_mem, AHCI_VS); caps = ATA_INL(ctlr->r_mem, AHCI_CAP); @@ -223,12 +224,15 @@ free(children, M_TEMP); } - if (ctlr->r_irq) { - bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle); - bus_release_resource(dev, SYS_RES_IRQ, ctlr->r_irq_rid, ctlr->r_irq); - if (ctlr->r_irq_rid != ATA_IRQ_RID) - pci_release_msi(dev); + for (i = 0; i < ctlr->numirqs; i++) { + if (ctlr->irqs[i].r_irq) { + bus_teardown_intr(dev, ctlr->irqs[i].r_irq, + ctlr->irqs[i].handle); + bus_release_resource(dev, SYS_RES_IRQ, + ctlr->irqs[i].r_irq_rid, ctlr->irqs[i].r_irq); + } } + pci_release_msi(dev); rman_fini(&ctlr->sc_iomem); if (ctlr->r_mem) @@ -303,23 +307,44 @@ int i, msi = 0; if (resource_int_value(device_get_name(dev), - device_get_unit(dev), "msi", &i) == 0 && i != 0) - msi = 1; - if (msi && pci_msi_count(dev) > 0 && pci_alloc_msi(dev, &msi) == 0) { - ctlr->r_irq_rid = 0x1; + device_get_unit(dev), "msi", &i) == 0) { + if (i == 1) + msi = min(1, pci_msi_count(dev)); + else if (i > 1) + msi = pci_msi_count(dev); + } + if (msi && pci_alloc_msi(dev, &msi) == 0) { + ctlr->numirqs = msi; } else { - ctlr->r_irq_rid = ATA_IRQ_RID; + msi = 0; + ctlr->numirqs = 1; } - if (!(ctlr->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &ctlr->r_irq_rid, RF_SHAREABLE | RF_ACTIVE))) { - device_printf(dev, "unable to map interrupt\n"); - return ENXIO; + if (ctlr->numirqs > 1 && + (ATA_INL(ctlr->r_mem, AHCI_GHC) & AHCI_GHC_MRSM) != 0) { + device_printf(dev, "Falling back to one MSI\n"); + ctlr->numirqs = 1; } - if ((bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS, NULL, - ahci_intr, ctlr, &ctlr->handle))) { - /* SOS XXX release r_irq */ - device_printf(dev, "unable to setup interrupt\n"); - return ENXIO; + for (i = 0; i < ctlr->numirqs; i++) { + ctlr->irqs[i].ctlr = ctlr; + ctlr->irqs[i].r_irq_rid = i + (msi ? 1 : 0); + if (ctlr->numirqs == 1 || i >= ctlr->channels) + ctlr->irqs[i].mode = AHCI_IRQ_MODE_ALL; + else if (i == ctlr->numirqs - 1) + ctlr->irqs[i].mode = AHCI_IRQ_MODE_AFTER; + else + ctlr->irqs[i].mode = AHCI_IRQ_MODE_ONE; + if (!(ctlr->irqs[i].r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &ctlr->irqs[i].r_irq_rid, RF_SHAREABLE | RF_ACTIVE))) { + device_printf(dev, "unable to map interrupt\n"); + return ENXIO; + } + if ((bus_setup_intr(dev, ctlr->irqs[i].r_irq, ATA_INTR_FLAGS, NULL, + (ctlr->irqs[i].mode == AHCI_IRQ_MODE_ONE) ? ahci_intr_one : ahci_intr, + &ctlr->irqs[i], &ctlr->irqs[i].handle))) { + /* SOS XXX release r_irq */ + device_printf(dev, "unable to setup interrupt\n"); + return ENXIO; + } } return (0); } @@ -327,19 +352,41 @@ static void ahci_intr(void *data) { - struct ahci_controller *ctlr = data; - u_int32_t is = ATA_INL(ctlr->r_mem, AHCI_IS); - void *arg; - int unit; + struct ahci_controller_irq *irq = data; + struct ahci_controller *ctlr = irq->ctlr; + u_int32_t is; + void *arg; + int unit; -//device_printf(ctlr->dev, "%s is %08x\n", __func__, is); - for (unit = 0; unit < ctlr->channels; unit++) { - if ((is & (1 << unit)) != 0 && - (arg = ctlr->interrupt[unit].argument)) { - ctlr->interrupt[unit].function(arg); - ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit); + is = ATA_INL(ctlr->r_mem, AHCI_IS); +//device_printf(ctlr->dev, "%s is %08x inum %d\n", __func__, is, irq->r_irq_rid); + if (irq->mode == AHCI_IRQ_MODE_ALL) + unit = 0; + else /* AHCI_IRQ_MODE_AFTER */ + unit = irq->r_irq_rid - 1; + for (; unit < ctlr->channels; unit++) { + if ((is & (1 << unit)) != 0 && + (arg = ctlr->interrupt[unit].argument)) { + ctlr->interrupt[unit].function(arg); + ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit); + } } - } +} + +static void +ahci_intr_one(void *data) +{ + struct ahci_controller_irq *irq = data; + struct ahci_controller *ctlr = irq->ctlr; +// u_int32_t is; + void *arg; + int unit; + + unit = irq->r_irq_rid - 1; +// is = ATA_INL(ctlr->r_mem, AHCI_IS); +//device_printf(ctlr->dev, "%s is %08x one %d\n", __func__, is, irq->r_irq_rid); + if ((arg = ctlr->interrupt[unit].argument)) + ctlr->interrupt[unit].function(arg); } static struct resource * @@ -369,7 +416,7 @@ break; case SYS_RES_IRQ: if (*rid == ATA_IRQ_RID) - res = ctlr->r_irq; + res = ctlr->irqs[0].r_irq; break; } return (res); @@ -807,15 +854,14 @@ int i, ccs; mtx_lock(&ch->mtx); - /* Read interrupt and command statuses. */ + /* Read and clear interrupt statuses. */ istatus = ATA_INL(ch->r_mem, AHCI_P_IS); + ATA_OUTL(ch->r_mem, AHCI_P_IS, istatus); + /* Read command statuses. */ cstatus = ATA_INL(ch->r_mem, AHCI_P_CI); sstatus = ATA_INL(ch->r_mem, AHCI_P_SACT); //device_printf(dev, "%s is %08x cs %08x ss %08x rslots %08x\n", __func__, istatus, cstatus, sstatus, ch->rslots); - /* Clear interrupt(s) */ - ATA_OUTL(ch->r_mem, AHCI_P_IS, istatus); - /* Process PHY events */ if (istatus & (AHCI_P_IX_PRC | AHCI_P_IX_PC)) ahci_phy_check_events(dev); ==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#7 (text+ko) ==== @@ -168,6 +168,7 @@ #define AHCI_GHC 0x04 #define AHCI_GHC_AE 0x80000000 +#define AHCI_GHC_MRSM 0x00000004 #define AHCI_GHC_IE 0x00000002 #define AHCI_GHC_HR 0x00000001 @@ -306,7 +307,6 @@ /* structure holding DMA related information */ struct ata_dma { - bus_dma_tag_t dmatag; /* parent DMA tag */ bus_dma_tag_t work_tag; /* workspace DMA tag */ bus_dmamap_t work_map; /* workspace DMA map */ u_int8_t *work; /* workspace */ @@ -383,18 +383,26 @@ /* structure describing a AHCI controller */ struct ahci_controller { - device_t dev; - int r_rid; - struct resource *r_mem; - int r_irq_rid; - struct resource *r_irq; - void *handle; + device_t dev; + int r_rid; + struct resource *r_mem; struct rman sc_iomem; - int channels; + struct ahci_controller_irq { + struct ahci_controller *ctlr; + struct resource *r_irq; + void *handle; + int r_irq_rid; + int mode; +#define AHCI_IRQ_MODE_ALL 0 +#define AHCI_IRQ_MODE_AFTER 1 +#define AHCI_IRQ_MODE_ONE 2 + } irqs[16]; + int numirqs; + int channels; int ichannels; struct { - void (*function)(void *); - void *argument; + void (*function)(void *); + void *argument; } interrupt[AHCI_MAX_PORTS]; };