Call ata_legacy() only once on attach and save it's result.
authorHasso Tepper <hasso@estpak.ee>
Thu, 18 Dec 2008 03:03:47 +0000 (05:03 +0200)
committerHasso Tepper <hasso@estpak.ee>
Thu, 18 Dec 2008 03:11:23 +0000 (05:11 +0200)
Scanning PCI configuration registers (which are not going to change) on
every interrupt looks expensive, especially when interrupt is shared.
Profiling (in FreeBSD) shows 3% of time spent by atapci0 on pure network
load due to IRQ sharing with em0.

Obtained-from: FreeBSD

sys/dev/disk/nata/ata-chipset.c
sys/dev/disk/nata/ata-pci.c
sys/dev/disk/nata/ata-pci.h

index 5750548..be764ea 100644 (file)
@@ -5747,7 +5747,7 @@ ata_setup_interrupt(device_t dev)
     struct ata_pci_controller *ctlr = device_get_softc(dev);
     int rid = ATA_IRQ_RID;
 
-    if (!ata_legacy(dev)) {
+    if (!ctlr->legacy) {
        if (!(ctlr->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
                                                   RF_SHAREABLE | RF_ACTIVE))) {
            device_printf(dev, "unable to map interrupt\n");
index f0cd3cf..cd7a5cd 100644 (file)
@@ -214,7 +214,8 @@ ata_pci_attach(device_t dev)
     int unit;
 
     /* do chipset specific setups only needed once */
-    if (ata_legacy(dev) || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK)
+    ctlr->legacy = ata_legacy(dev);
+    if (ctlr->legacy || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK)
        ctlr->channels = 2;
     else
        ctlr->channels = 1;
@@ -244,7 +245,7 @@ ata_pci_attach(device_t dev)
     /* attach all channels on this controller */
     for (unit = 0; unit < ctlr->channels; unit++) {
        int freeunit = 2;
-       if ((unit == 0 || unit == 1) && ata_legacy(dev)) {
+       if ((unit == 0 || unit == 1) && ctlr->legacy) {
            device_add_child(dev, "ata", unit);
            continue;
        }
@@ -296,7 +297,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
     if (type == SYS_RES_IOPORT) {
        switch (*rid) {
        case ATA_IOADDR_RID:
-           if (ata_legacy(dev)) {
+           if (controller->legacy) {
                start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
                count = ATA_IOSIZE;
                end = start + count - 1;
@@ -308,7 +309,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
            break;
 
        case ATA_CTLADDR_RID:
-           if (ata_legacy(dev)) {
+           if (controller->legacy) {
                start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_CTLOFFSET;
                count = ATA_CTLIOSIZE;
                end = start + count - 1;
@@ -321,7 +322,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
        }
     }
     if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
-       if (ata_legacy(dev)) {
+       if (controller->legacy) {
            int irq = (unit == 0 ? 14 : 15);
            
            res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
@@ -337,6 +338,7 @@ int
 ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
                         struct resource *r)
 {
+    struct ata_pci_controller *controller = device_get_softc(dev);
     int unit = ((struct ata_channel *)device_get_softc(child))->unit;
 
     if (type == SYS_RES_IOPORT) {
@@ -360,7 +362,7 @@ ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
        if (rid != ATA_IRQ_RID)
            return ENOENT;
 
-       if (ata_legacy(dev)) {
+       if (controller->legacy) {
            return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
                                        SYS_RES_IRQ, rid, r);
        }
@@ -375,7 +377,9 @@ ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
                   int flags, driver_intr_t *function, void *argument,
                   void **cookiep)
 {
-    if (ata_legacy(dev)) {
+    struct ata_pci_controller *controller = device_get_softc(dev);
+
+    if (controller->legacy) {
        return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
                              flags, function, argument, cookiep, NULL);
     }
@@ -394,7 +398,9 @@ int
 ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
                      void *cookie)
 {
-    if (ata_legacy(dev)) {
+    struct ata_pci_controller *controller = device_get_softc(dev);
+
+    if (controller->legacy) {
        return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie);
     }
     else {
@@ -430,7 +436,7 @@ ata_pci_allocate(device_t dev)
        ch->r_io[i].offset = i;
     }
     ch->r_io[ATA_CONTROL].res = ctlio;
-    ch->r_io[ATA_CONTROL].offset = ata_legacy(device_get_parent(dev)) ? 0 : 2;
+    ch->r_io[ATA_CONTROL].offset = ctlr->legacy ? 0 : 2;
     ch->r_io[ATA_IDX_ADDR].res = io;
     ata_default_registers(dev);
     if (ctlr->r_res1) {
@@ -456,9 +462,11 @@ ata_pci_hw(device_t dev)
 int
 ata_pci_status(device_t dev)
 {
+    struct ata_pci_controller *controller =
+       device_get_softc(device_get_parent(dev));
     struct ata_channel *ch = device_get_softc(dev);
 
-    if ((dumping || !ata_legacy(device_get_parent(dev))) &&
+    if ((dumping || !controller->legacy) &&
        ch->dma && ((ch->flags & ATA_ALWAYS_DMASTAT) ||
                    (ch->dma->flags & ATA_DMA_ACTIVE))) {
        int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
index 5640fe9..04fff71 100644 (file)
@@ -54,6 +54,7 @@ struct ata_pci_controller {
     struct resource     *r_irq;
     void                *handle;
     struct ata_chip_id  *chip;
+    int                        legacy;
     int                 channels;
     int                 (*chipinit)(device_t);
     int                 (*allocate)(device_t);