diff options
author | achim <achim@FreeBSD.org> | 2014-03-11 14:59:34 +0000 |
---|---|---|
committer | achim <achim@FreeBSD.org> | 2014-03-11 14:59:34 +0000 |
commit | d9fd2797e53e8b8f1e593c3fbce42a5ed3bc71dc (patch) | |
tree | dcbd9d4a8e6e84967084386895540b8c6403831c /sys/dev | |
parent | c157604f42c4e16d9aa5752902f75fdc5c38dfe3 (diff) | |
download | FreeBSD-src-d9fd2797e53e8b8f1e593c3fbce42a5ed3bc71dc.zip FreeBSD-src-d9fd2797e53e8b8f1e593c3fbce42a5ed3bc71dc.tar.gz |
MFC r257847, r260243: Update aacraid to version 3.2.5.
Approved by: emaste (co-mentor)
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/aacraid/aacraid.c | 603 | ||||
-rw-r--r-- | sys/dev/aacraid/aacraid_cam.c | 30 | ||||
-rw-r--r-- | sys/dev/aacraid/aacraid_reg.h | 104 | ||||
-rw-r--r-- | sys/dev/aacraid/aacraid_var.h | 46 |
4 files changed, 623 insertions, 160 deletions
diff --git a/sys/dev/aacraid/aacraid.c b/sys/dev/aacraid/aacraid.c index 22a3644..70e3270 100644 --- a/sys/dev/aacraid/aacraid.c +++ b/sys/dev/aacraid/aacraid.c @@ -98,8 +98,11 @@ static int aac_alloc(struct aac_softc *sc); static void aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error); static int aac_check_firmware(struct aac_softc *sc); +static void aac_define_int_mode(struct aac_softc *sc); static int aac_init(struct aac_softc *sc); +static int aac_find_pci_capability(struct aac_softc *sc, int cap); static int aac_setup_intr(struct aac_softc *sc); +static int aac_check_config(struct aac_softc *sc); /* PMC SRC interface */ static int aac_src_get_fwstatus(struct aac_softc *sc); @@ -110,7 +113,7 @@ static void aac_src_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3); static int aac_src_get_mailbox(struct aac_softc *sc, int mb); -static void aac_src_set_interrupts(struct aac_softc *sc, int enable); +static void aac_src_access_devreg(struct aac_softc *sc, int mode); static int aac_src_send_command(struct aac_softc *sc, struct aac_command *cm); static int aac_src_get_outb_queue(struct aac_softc *sc); static void aac_src_set_outb_queue(struct aac_softc *sc, int index); @@ -122,7 +125,7 @@ struct aac_interface aacraid_src_interface = { aac_src_clear_istatus, aac_src_set_mailbox, aac_src_get_mailbox, - aac_src_set_interrupts, + aac_src_access_devreg, aac_src_send_command, aac_src_get_outb_queue, aac_src_set_outb_queue @@ -141,7 +144,7 @@ struct aac_interface aacraid_srcv_interface = { aac_src_clear_istatus, aac_srcv_set_mailbox, aac_srcv_get_mailbox, - aac_src_set_interrupts, + aac_src_access_devreg, aac_src_send_command, aac_src_get_outb_queue, aac_src_set_outb_queue @@ -258,6 +261,7 @@ aacraid_attach(struct aac_softc *sc) /* * Check that the firmware on the card is supported. */ + sc->msi_enabled = FALSE; if ((error = aac_check_firmware(sc)) != 0) return(error); @@ -278,6 +282,7 @@ aacraid_attach(struct aac_softc *sc) if ((error = aac_alloc(sc)) != 0) return(error); if (!(sc->flags & AAC_FLAGS_SYNC_MODE)) { + aac_define_int_mode(sc); if ((error = aac_init(sc)) != 0) return(error); } @@ -341,7 +346,7 @@ aacraid_attach(struct aac_softc *sc) sc->aac_state &= ~AAC_STATE_SUSPEND; /* enable interrupts now */ - AAC_UNMASK_INTERRUPTS(sc); + AAC_ACCESS_DEVREG(sc, AAC_ENABLE_INTERRUPT); #if __FreeBSD_version >= 800000 mtx_lock(&sc->aac_io_lock); @@ -442,6 +447,7 @@ aac_get_container_info(struct aac_softc *sc, struct aac_fib *sync_fib, int cid, struct aac_fib *fib; struct aac_mntinfo *mi; struct aac_cnt_config *ccfg; + int rval; if (sync_fib == NULL) { if (aacraid_alloc_command(sc, &cm)) { @@ -499,9 +505,10 @@ aac_get_container_info(struct aac_softc *sc, struct aac_fib *sync_fib, int cid, *uid = cid; if (mir->MntTable[0].VolType != CT_NONE && !(mir->MntTable[0].ContentState & AAC_FSCS_HIDDEN)) { - if (!(sc->aac_support_opt2 & AAC_SUPPORTED_VARIABLE_BLOCK_SIZE)) - mir->MntTable[0].ObjExtension.BlockSize = 0x200; - + if (!(sc->aac_support_opt2 & AAC_SUPPORTED_VARIABLE_BLOCK_SIZE)) { + mir->MntTable[0].ObjExtension.BlockDevice.BlockSize = 0x200; + mir->MntTable[0].ObjExtension.BlockDevice.bdLgclPhysMap = 0; + } ccfg = (struct aac_cnt_config *)&fib->data[0]; bzero(ccfg, sizeof (*ccfg) - CT_PACKET_SIZE); ccfg->Command = VM_ContainerConfig; @@ -509,9 +516,10 @@ aac_get_container_info(struct aac_softc *sc, struct aac_fib *sync_fib, int cid, ccfg->CTCommand.param[0] = cid; if (sync_fib) { - if (aac_sync_fib(sc, ContainerCommand, 0, fib, - sizeof(struct aac_cnt_config) == 0) && - ccfg->CTCommand.param[0] == ST_OK && + rval = aac_sync_fib(sc, ContainerCommand, 0, fib, + sizeof(struct aac_cnt_config)); + if (rval == 0 && ccfg->Command == ST_OK && + ccfg->CTCommand.param[0] == CT_OK && mir->MntTable[0].VolType != CT_PASSTHRU) *uid = ccfg->CTCommand.param[1]; } else { @@ -527,8 +535,9 @@ aac_get_container_info(struct aac_softc *sc, struct aac_fib *sync_fib, int cid, AAC_FIBSTATE_ASYNC | AAC_FIBSTATE_FAST_RESPONSE; fib->Header.Command = ContainerCommand; - if (aacraid_wait_command(cm) == 0 && - ccfg->CTCommand.param[0] == ST_OK && + rval = aacraid_wait_command(cm); + if (rval == 0 && ccfg->Command == ST_OK && + ccfg->CTCommand.param[0] == CT_OK && mir->MntTable[0].VolType != CT_PASSTHRU) *uid = ccfg->CTCommand.param[1]; aacraid_release_command(cm); @@ -681,6 +690,8 @@ aac_alloc(struct aac_softc *sc) void aacraid_free(struct aac_softc *sc) { + int i; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* remove the control device */ @@ -704,11 +715,18 @@ aacraid_free(struct aac_softc *sc) bus_dma_tag_destroy(sc->aac_common_dmat); /* disconnect the interrupt handler */ - if (sc->aac_intr) - bus_teardown_intr(sc->aac_dev, sc->aac_irq, sc->aac_intr); - if (sc->aac_irq != NULL) - bus_release_resource(sc->aac_dev, SYS_RES_IRQ, sc->aac_irq_rid, - sc->aac_irq); + for (i = 0; i < AAC_MAX_MSIX; ++i) { + if (sc->aac_intr[i]) + bus_teardown_intr(sc->aac_dev, + sc->aac_irq[i], sc->aac_intr[i]); + if (sc->aac_irq[i]) + bus_release_resource(sc->aac_dev, SYS_RES_IRQ, + sc->aac_irq_rid[i], sc->aac_irq[i]); + else + break; + } + if (sc->msi_enabled) + pci_release_msi(sc->aac_dev); /* destroy data-transfer DMA tag */ if (sc->aac_buffer_dmat) @@ -815,14 +833,14 @@ aacraid_shutdown(device_t dev) bzero(cc, sizeof(struct aac_close_command)); cc->Command = VM_CloseAll; - cc->ContainerId = 0xffffffff; + cc->ContainerId = 0xfffffffe; if (aac_sync_fib(sc, ContainerCommand, 0, fib, sizeof(struct aac_close_command))) printf("FAILED.\n"); else printf("done\n"); - AAC_MASK_INTERRUPTS(sc); + AAC_ACCESS_DEVREG(sc, AAC_DISABLE_INTERRUPT); aac_release_sync_fib(sc); mtx_unlock(&sc->aac_io_lock); @@ -842,7 +860,7 @@ aacraid_suspend(device_t dev) fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); sc->aac_state |= AAC_STATE_SUSPEND; - AAC_MASK_INTERRUPTS(sc); + AAC_ACCESS_DEVREG(sc, AAC_DISABLE_INTERRUPT); return(0); } @@ -858,7 +876,7 @@ aacraid_resume(device_t dev) fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); sc->aac_state &= ~AAC_STATE_SUSPEND; - AAC_UNMASK_INTERRUPTS(sc); + AAC_ACCESS_DEVREG(sc, AAC_ENABLE_INTERRUPT); return(0); } @@ -868,23 +886,75 @@ aacraid_resume(device_t dev) void aacraid_new_intr_type1(void *arg) { + struct aac_msix_ctx *ctx; struct aac_softc *sc; + int vector_no; struct aac_command *cm; struct aac_fib *fib; u_int32_t bellbits, bellbits_shifted, index, handle; - int isFastResponse, isAif, noMoreAif; + int isFastResponse, isAif, noMoreAif, mode; - sc = (struct aac_softc *)arg; + ctx = (struct aac_msix_ctx *)arg; + sc = ctx->sc; + vector_no = ctx->vector_no; fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); mtx_lock(&sc->aac_io_lock); - bellbits = AAC_MEM0_GETREG4(sc, AAC_SRC_ODBR_R); - if (bellbits & AAC_DB_RESPONSE_SENT_NS) { - bellbits = AAC_DB_RESPONSE_SENT_NS; - AAC_MEM0_SETREG4(sc, AAC_SRC_ODBR_C, bellbits); - AAC_MEM0_GETREG4(sc, AAC_SRC_ODBR_R); /* ODR readback,Prep #238630 */ + + if (sc->msi_enabled) { + mode = AAC_INT_MODE_MSI; + if (vector_no == 0) { + bellbits = AAC_MEM0_GETREG4(sc, AAC_SRC_ODBR_MSI); + if (bellbits & 0x40000) + mode |= AAC_INT_MODE_AIF; + else if (bellbits & 0x1000) + mode |= AAC_INT_MODE_SYNC; + } + } else { + mode = AAC_INT_MODE_INTX; + bellbits = AAC_MEM0_GETREG4(sc, AAC_SRC_ODBR_R); + if (bellbits & AAC_DB_RESPONSE_SENT_NS) { + bellbits = AAC_DB_RESPONSE_SENT_NS; + AAC_MEM0_SETREG4(sc, AAC_SRC_ODBR_C, bellbits); + } else { + bellbits_shifted = (bellbits >> AAC_SRC_ODR_SHIFT); + AAC_MEM0_SETREG4(sc, AAC_SRC_ODBR_C, bellbits); + if (bellbits_shifted & AAC_DB_AIF_PENDING) + mode |= AAC_INT_MODE_AIF; + else if (bellbits_shifted & AAC_DB_SYNC_COMMAND) + mode |= AAC_INT_MODE_SYNC; + } + /* ODR readback, Prep #238630 */ + AAC_MEM0_GETREG4(sc, AAC_SRC_ODBR_R); + } + + if (mode & AAC_INT_MODE_SYNC) { + if (sc->aac_sync_cm) { + cm = sc->aac_sync_cm; + cm->cm_flags |= AAC_CMD_COMPLETED; + /* is there a completion handler? */ + if (cm->cm_complete != NULL) { + cm->cm_complete(cm); + } else { + /* assume that someone is sleeping on this command */ + wakeup(cm); + } + sc->flags &= ~AAC_QUEUE_FRZN; + sc->aac_sync_cm = NULL; + } + mode = 0; + } + + if (mode & AAC_INT_MODE_AIF) { + if (mode & AAC_INT_MODE_INTX) { + aac_request_aif(sc); + mode = 0; + } + } + + if (mode) { /* handle async. status */ - index = sc->aac_host_rrq_idx; + index = sc->aac_host_rrq_idx[vector_no]; for (;;) { isFastResponse = isAif = noMoreAif = 0; /* remove toggle bit (31) */ @@ -901,6 +971,7 @@ aacraid_new_intr_type1(void *arg) cm = sc->aac_commands + (handle - 1); fib = cm->cm_fib; + sc->aac_rrq_outstanding[vector_no]--; if (isAif) { noMoreAif = (fib->Header.XferState & AAC_FIBSTATE_NOMOREAIF) ? 1:0; if (!noMoreAif) @@ -928,34 +999,19 @@ aacraid_new_intr_type1(void *arg) } sc->aac_common->ac_host_rrq[index++] = 0; - if (index == sc->aac_max_fibs) - index = 0; - sc->aac_host_rrq_idx = index; + if (index == (vector_no + 1) * sc->aac_vector_cap) + index = vector_no * sc->aac_vector_cap; + sc->aac_host_rrq_idx[vector_no] = index; if ((isAif && !noMoreAif) || sc->aif_pending) aac_request_aif(sc); } - } else { - bellbits_shifted = (bellbits >> AAC_SRC_ODR_SHIFT); - AAC_MEM0_SETREG4(sc, AAC_SRC_ODBR_C, bellbits); - if (bellbits_shifted & AAC_DB_AIF_PENDING) { - /* handle AIF */ - aac_request_aif(sc); - } else if (bellbits_shifted & AAC_DB_SYNC_COMMAND) { - if (sc->aac_sync_cm) { - cm = sc->aac_sync_cm; - cm->cm_flags |= AAC_CMD_COMPLETED; - /* is there a completion handler? */ - if (cm->cm_complete != NULL) { - cm->cm_complete(cm); - } else { - /* assume that someone is sleeping on this command */ - wakeup(cm); - } - sc->flags &= ~AAC_QUEUE_FRZN; - sc->aac_sync_cm = NULL; - } - } + } + + if (mode & AAC_INT_MODE_AIF) { + aac_request_aif(sc); + AAC_ACCESS_DEVREG(sc, AAC_CLEAR_AIF_BIT); + mode = 0; } /* see if we can start some more I/O */ @@ -1479,32 +1535,47 @@ static int aac_check_firmware(struct aac_softc *sc) { u_int32_t code, major, minor, maxsize; - u_int32_t options = 0, atu_size = 0, status; + u_int32_t options = 0, atu_size = 0, status, waitCount; time_t then; fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + + /* check if flash update is running */ + if (AAC_GET_FWSTATUS(sc) & AAC_FLASH_UPD_PENDING) { + then = time_uptime; + do { + code = AAC_GET_FWSTATUS(sc); + if (time_uptime > (then + AAC_FWUPD_TIMEOUT)) { + device_printf(sc->aac_dev, + "FATAL: controller not coming ready, " + "status %x\n", code); + return(ENXIO); + } + } while (!(code & AAC_FLASH_UPD_SUCCESS) && !(code & AAC_FLASH_UPD_FAILED)); + /* + * Delay 10 seconds. Because right now FW is doing a soft reset, + * do not read scratch pad register at this time + */ + waitCount = 10 * 10000; + while (waitCount) { + DELAY(100); /* delay 100 microseconds */ + waitCount--; + } + } + /* * Wait for the adapter to come ready. */ then = time_uptime; do { code = AAC_GET_FWSTATUS(sc); - if (code & AAC_SELF_TEST_FAILED) { - device_printf(sc->aac_dev, "FATAL: selftest failed\n"); - return(ENXIO); - } - if (code & AAC_KERNEL_PANIC) { - device_printf(sc->aac_dev, - "FATAL: controller kernel panic"); - return(ENXIO); - } if (time_uptime > (then + AAC_BOOT_TIMEOUT)) { device_printf(sc->aac_dev, "FATAL: controller not coming ready, " "status %x\n", code); return(ENXIO); } - } while (!(code & AAC_UP_AND_RUNNING)); + } while (!(code & AAC_UP_AND_RUNNING) || code == 0xffffffff); /* * Retrieve the firmware version numbers. Dell PERC2/QC cards with @@ -1629,9 +1700,13 @@ aac_check_firmware(struct aac_softc *sc) options = AAC_GET_MAILBOX(sc, 2); sc->aac_sg_tablesize = (options >> 16); options = AAC_GET_MAILBOX(sc, 3); - sc->aac_max_fibs = (options & 0xFFFF); + sc->aac_max_fibs = ((options >> 16) & 0xFFFF); + if (sc->aac_max_fibs == 0 || sc->aac_hwif != AAC_HWIF_SRCV) + sc->aac_max_fibs = (options & 0xFFFF); options = AAC_GET_MAILBOX(sc, 4); sc->aac_max_aif = (options & 0xFFFF); + options = AAC_GET_MAILBOX(sc, 5); + sc->aac_max_msix =(sc->flags & AAC_FLAGS_NEW_COMM_TYPE2) ? options : 0; } maxsize = sc->aac_max_fib_size + 31; @@ -1653,7 +1728,9 @@ aac_check_firmware(struct aac_softc *sc) device_printf(sc->aac_dev, "Enable 64-bit array\n"); } +#ifdef AACRAID_DEBUG aacraid_get_fw_debug_buffer(sc); +#endif return (0); } @@ -1661,12 +1738,14 @@ static int aac_init(struct aac_softc *sc) { struct aac_adapter_init *ip; - int error; + int i, error; fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* reset rrq index */ - sc->aac_host_rrq_idx = 0; + sc->aac_fibs_pushed_no = 0; + for (i = 0; i < sc->aac_max_msix; i++) + sc->aac_host_rrq_idx[i] = i * sc->aac_vector_cap; /* * Fill in the init structure. This tells the adapter about the @@ -1678,7 +1757,7 @@ aac_init(struct aac_softc *sc) ip->InitStructRevision = AAC_INIT_STRUCT_REVISION_4; sc->flags |= AAC_FLAGS_RAW_IO; } - ip->MiniPortRevision = AAC_INIT_STRUCT_MINIPORT_REVISION; + ip->NoOfMSIXVectors = sc->aac_max_msix; ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr + offsetof(struct aac_common, ac_fibs); @@ -1708,7 +1787,6 @@ aac_init(struct aac_softc *sc) ip->InitStructRevision = AAC_INIT_STRUCT_REVISION_6; ip->InitFlags |= (AAC_INITFLAGS_NEW_COMM_TYPE1_SUPPORTED | AAC_INITFLAGS_FAST_JBOD_SUPPORTED); - ip->MiniPortRevision = 0L; device_printf(sc->aac_dev, "New comm. interface type1 enabled\n"); } else if (sc->flags & AAC_FLAGS_NEW_COMM_TYPE2) { ip->InitStructRevision = AAC_INIT_STRUCT_REVISION_7; @@ -1750,31 +1828,209 @@ aac_init(struct aac_softc *sc) goto out; } + /* + * Check configuration issues + */ + if ((error = aac_check_config(sc)) != 0) + goto out; + error = 0; out: return(error); } +static void +aac_define_int_mode(struct aac_softc *sc) +{ + device_t dev; + int cap, msi_count, error = 0; + uint32_t val; + + dev = sc->aac_dev; + + /* max. vectors from AAC_MONKER_GETCOMMPREF */ + if (sc->aac_max_msix == 0) { + sc->aac_max_msix = 1; + sc->aac_vector_cap = sc->aac_max_fibs; + return; + } + + /* OS capability */ + msi_count = pci_msix_count(dev); + if (msi_count > AAC_MAX_MSIX) + msi_count = AAC_MAX_MSIX; + if (msi_count > sc->aac_max_msix) + msi_count = sc->aac_max_msix; + if (msi_count == 0 || (error = pci_alloc_msix(dev, &msi_count)) != 0) { + device_printf(dev, "alloc msix failed - msi_count=%d, err=%d; " + "will try MSI\n", msi_count, error); + pci_release_msi(dev); + } else { + sc->msi_enabled = TRUE; + device_printf(dev, "using MSI-X interrupts (%u vectors)\n", + msi_count); + } + + if (!sc->msi_enabled) { + msi_count = 1; + if ((error = pci_alloc_msi(dev, &msi_count)) != 0) { + device_printf(dev, "alloc msi failed - err=%d; " + "will use INTx\n", error); + pci_release_msi(dev); + } else { + sc->msi_enabled = TRUE; + device_printf(dev, "using MSI interrupts\n"); + } + } + + if (sc->msi_enabled) { + /* now read controller capability from PCI config. space */ + cap = aac_find_pci_capability(sc, PCIY_MSIX); + val = (cap != 0 ? pci_read_config(dev, cap + 2, 2) : 0); + if (!(val & AAC_PCI_MSI_ENABLE)) { + pci_release_msi(dev); + sc->msi_enabled = FALSE; + } + } + + if (!sc->msi_enabled) { + device_printf(dev, "using legacy interrupts\n"); + sc->aac_max_msix = 1; + } else { + AAC_ACCESS_DEVREG(sc, AAC_ENABLE_MSIX); + if (sc->aac_max_msix > msi_count) + sc->aac_max_msix = msi_count; + } + sc->aac_vector_cap = sc->aac_max_fibs / sc->aac_max_msix; + + fwprintf(sc, HBA_FLAGS_DBG_DEBUG_B, "msi_enabled %d vector_cap %d max_fibs %d max_msix %d", + sc->msi_enabled,sc->aac_vector_cap, sc->aac_max_fibs, sc->aac_max_msix); +} + static int -aac_setup_intr(struct aac_softc *sc) +aac_find_pci_capability(struct aac_softc *sc, int cap) { - sc->aac_irq_rid = 0; - if ((sc->aac_irq = bus_alloc_resource_any(sc->aac_dev, SYS_RES_IRQ, - &sc->aac_irq_rid, - RF_SHAREABLE | - RF_ACTIVE)) == NULL) { - device_printf(sc->aac_dev, "can't allocate interrupt\n"); - return (EINVAL); + device_t dev; + uint32_t status; + uint8_t ptr; + + dev = sc->aac_dev; + + status = pci_read_config(dev, PCIR_STATUS, 2); + if (!(status & PCIM_STATUS_CAPPRESENT)) + return (0); + + status = pci_read_config(dev, PCIR_HDRTYPE, 1); + switch (status & PCIM_HDRTYPE) { + case 0: + case 1: + ptr = PCIR_CAP_PTR; + break; + case 2: + ptr = PCIR_CAP_PTR_2; + break; + default: + return (0); + break; } - if (aac_bus_setup_intr(sc->aac_dev, sc->aac_irq, - INTR_MPSAFE|INTR_TYPE_BIO, NULL, - aacraid_new_intr_type1, sc, &sc->aac_intr)) { - device_printf(sc->aac_dev, "can't set up interrupt\n"); - return (EINVAL); + ptr = pci_read_config(dev, ptr, 1); + + while (ptr != 0) { + int next, val; + next = pci_read_config(dev, ptr + PCICAP_NEXTPTR, 1); + val = pci_read_config(dev, ptr + PCICAP_ID, 1); + if (val == cap) + return (ptr); + ptr = next; } + return (0); } +static int +aac_setup_intr(struct aac_softc *sc) +{ + int i, msi_count, rid; + struct resource *res; + void *tag; + + msi_count = sc->aac_max_msix; + rid = (sc->msi_enabled ? 1:0); + + for (i = 0; i < msi_count; i++, rid++) { + if ((res = bus_alloc_resource_any(sc->aac_dev,SYS_RES_IRQ, &rid, + RF_SHAREABLE | RF_ACTIVE)) == NULL) { + device_printf(sc->aac_dev,"can't allocate interrupt\n"); + return (EINVAL); + } + sc->aac_irq_rid[i] = rid; + sc->aac_irq[i] = res; + if (aac_bus_setup_intr(sc->aac_dev, res, + INTR_MPSAFE | INTR_TYPE_BIO, NULL, + aacraid_new_intr_type1, &sc->aac_msix[i], &tag)) { + device_printf(sc->aac_dev, "can't set up interrupt\n"); + return (EINVAL); + } + sc->aac_msix[i].vector_no = i; + sc->aac_msix[i].sc = sc; + sc->aac_intr[i] = tag; + } + + return (0); +} + +static int +aac_check_config(struct aac_softc *sc) +{ + struct aac_fib *fib; + struct aac_cnt_config *ccfg; + struct aac_cf_status_hdr *cf_shdr; + int rval; + + mtx_lock(&sc->aac_io_lock); + aac_alloc_sync_fib(sc, &fib); + + ccfg = (struct aac_cnt_config *)&fib->data[0]; + bzero(ccfg, sizeof (*ccfg) - CT_PACKET_SIZE); + ccfg->Command = VM_ContainerConfig; + ccfg->CTCommand.command = CT_GET_CONFIG_STATUS; + ccfg->CTCommand.param[CNT_SIZE] = sizeof(struct aac_cf_status_hdr); + + rval = aac_sync_fib(sc, ContainerCommand, 0, fib, + sizeof (struct aac_cnt_config)); + cf_shdr = (struct aac_cf_status_hdr *)ccfg->CTCommand.data; + if (rval == 0 && ccfg->Command == ST_OK && + ccfg->CTCommand.param[0] == CT_OK) { + if (cf_shdr->action <= CFACT_PAUSE) { + bzero(ccfg, sizeof (*ccfg) - CT_PACKET_SIZE); + ccfg->Command = VM_ContainerConfig; + ccfg->CTCommand.command = CT_COMMIT_CONFIG; + + rval = aac_sync_fib(sc, ContainerCommand, 0, fib, + sizeof (struct aac_cnt_config)); + if (rval == 0 && ccfg->Command == ST_OK && + ccfg->CTCommand.param[0] == CT_OK) { + /* successful completion */ + rval = 0; + } else { + /* auto commit aborted due to error(s) */ + rval = -2; + } + } else { + /* auto commit aborted due to adapter indicating + config. issues too dangerous to auto commit */ + rval = -3; + } + } else { + /* error */ + rval = -1; + } + + aac_release_sync_fib(sc); + mtx_unlock(&sc->aac_io_lock); + return(rval); +} + /* * Send a synchronous command to the controller and wait for a result. * Indicate if the controller completed the command with an error status. @@ -1793,7 +2049,8 @@ aacraid_sync_command(struct aac_softc *sc, u_int32_t command, AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3); /* ensure the sync command doorbell flag is cleared */ - AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); + if (!sc->msi_enabled) + AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); /* then set it to signal the adapter */ AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND); @@ -1802,7 +2059,7 @@ aacraid_sync_command(struct aac_softc *sc, u_int32_t command, /* spin waiting for the command to complete */ then = time_uptime; do { - if (time_uptime > (then + AAC_IMMEDIATE_TIMEOUT)) { + if (time_uptime > (then + AAC_SYNC_TIMEOUT)) { fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, "timed out"); return(EIO); } @@ -1849,14 +2106,13 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, fib->Header.SenderSize = sizeof(struct aac_fib); fib->Header.SenderFibAddress = 0; /* Not needed */ fib->Header.u.ReceiverFibAddress = sc->aac_common_busaddr + - offsetof(struct aac_common, - ac_sync_fib); + offsetof(struct aac_common, ac_sync_fib); /* * Give the FIB to the controller, wait for a response. */ if (aacraid_sync_command(sc, AAC_MONKER_SYNCFIB, - fib->Header.u.ReceiverFibAddress, 0, 0, 0, NULL, NULL)) { + fib->Header.u.ReceiverFibAddress, 0, 0, 0, NULL, NULL)) { fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, "IO error"); return(EIO); } @@ -1873,7 +2129,7 @@ aac_timeout(struct aac_softc *sc) { struct aac_command *cm; time_t deadline; - int timedout, code; + int timedout; fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* @@ -1883,9 +2139,7 @@ aac_timeout(struct aac_softc *sc) timedout = 0; deadline = time_uptime - AAC_CMD_TIMEOUT; TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) { - if ((cm->cm_timestamp < deadline) - /* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) { - cm->cm_flags |= AAC_CMD_TIMEDOUT; + if (cm->cm_timestamp < deadline) { device_printf(sc->aac_dev, "COMMAND %p TIMEOUT AFTER %d SECONDS\n", cm, (int)(time_uptime-cm->cm_timestamp)); @@ -1894,14 +2148,8 @@ aac_timeout(struct aac_softc *sc) } } - if (timedout) { - code = AAC_GET_FWSTATUS(sc); - if (code != AAC_UP_AND_RUNNING) { - device_printf(sc->aac_dev, "WARNING! Controller is no " - "longer running! code= 0x%x\n", code); - aac_reset_adapter(sc); - } - } + if (timedout) + aac_reset_adapter(sc); aacraid_print_queues(sc); } @@ -1937,9 +2185,20 @@ aac_src_qnotify(struct aac_softc *sc, int qbit) static int aac_src_get_istatus(struct aac_softc *sc) { + int val; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - return(AAC_MEM0_GETREG4(sc, AAC_SRC_ODBR_R) >> AAC_SRC_ODR_SHIFT); + if (sc->msi_enabled) { + val = AAC_MEM0_GETREG4(sc, AAC_SRC_ODBR_MSI); + if (val & AAC_MSI_SYNC_STATUS) + val = AAC_DB_SYNC_COMMAND; + else + val = 0; + } else { + val = AAC_MEM0_GETREG4(sc, AAC_SRC_ODBR_R) >> AAC_SRC_ODR_SHIFT; + } + return(val); } /* @@ -1950,7 +2209,12 @@ aac_src_clear_istatus(struct aac_softc *sc, int mask) { fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_MEM0_SETREG4(sc, AAC_SRC_ODBR_C, mask << AAC_SRC_ODR_SHIFT); + if (sc->msi_enabled) { + if (mask == AAC_DB_SYNC_COMMAND) + AAC_ACCESS_DEVREG(sc, AAC_CLEAR_SYNC_BIT); + } else { + AAC_MEM0_SETREG4(sc, AAC_SRC_ODBR_C, mask << AAC_SRC_ODR_SHIFT); + } } /* @@ -2005,14 +2269,77 @@ aac_srcv_get_mailbox(struct aac_softc *sc, int mb) * Set/clear interrupt masks */ static void -aac_src_set_interrupts(struct aac_softc *sc, int enable) +aac_src_access_devreg(struct aac_softc *sc, int mode) { - fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "%sable interrupts", enable ? "en" : "dis"); + u_int32_t val; - if (enable) { - AAC_MEM0_SETREG4(sc, AAC_SRC_OIMR, ~AAC_DB_INT_NEW_COMM_TYPE1); - } else { - AAC_MEM0_SETREG4(sc, AAC_SRC_OIMR, ~0); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + + switch (mode) { + case AAC_ENABLE_INTERRUPT: + AAC_MEM0_SETREG4(sc, AAC_SRC_OIMR, + (sc->msi_enabled ? AAC_INT_ENABLE_TYPE1_MSIX : + AAC_INT_ENABLE_TYPE1_INTX)); + break; + + case AAC_DISABLE_INTERRUPT: + AAC_MEM0_SETREG4(sc, AAC_SRC_OIMR, AAC_INT_DISABLE_ALL); + break; + + case AAC_ENABLE_MSIX: + /* set bit 6 */ + val = AAC_MEM0_GETREG4(sc, AAC_SRC_IDBR); + val |= 0x40; + AAC_MEM0_SETREG4(sc, AAC_SRC_IDBR, val); + AAC_MEM0_GETREG4(sc, AAC_SRC_IDBR); + /* unmask int. */ + val = PMC_ALL_INTERRUPT_BITS; + AAC_MEM0_SETREG4(sc, AAC_SRC_IOAR, val); + val = AAC_MEM0_GETREG4(sc, AAC_SRC_OIMR); + AAC_MEM0_SETREG4(sc, AAC_SRC_OIMR, + val & (~(PMC_GLOBAL_INT_BIT2 | PMC_GLOBAL_INT_BIT0))); + break; + + case AAC_DISABLE_MSIX: + /* reset bit 6 */ + val = AAC_MEM0_GETREG4(sc, AAC_SRC_IDBR); + val &= ~0x40; + AAC_MEM0_SETREG4(sc, AAC_SRC_IDBR, val); + AAC_MEM0_GETREG4(sc, AAC_SRC_IDBR); + break; + + case AAC_CLEAR_AIF_BIT: + /* set bit 5 */ + val = AAC_MEM0_GETREG4(sc, AAC_SRC_IDBR); + val |= 0x20; + AAC_MEM0_SETREG4(sc, AAC_SRC_IDBR, val); + AAC_MEM0_GETREG4(sc, AAC_SRC_IDBR); + break; + + case AAC_CLEAR_SYNC_BIT: + /* set bit 4 */ + val = AAC_MEM0_GETREG4(sc, AAC_SRC_IDBR); + val |= 0x10; + AAC_MEM0_SETREG4(sc, AAC_SRC_IDBR, val); + AAC_MEM0_GETREG4(sc, AAC_SRC_IDBR); + break; + + case AAC_ENABLE_INTX: + /* set bit 7 */ + val = AAC_MEM0_GETREG4(sc, AAC_SRC_IDBR); + val |= 0x80; + AAC_MEM0_SETREG4(sc, AAC_SRC_IDBR, val); + AAC_MEM0_GETREG4(sc, AAC_SRC_IDBR); + /* unmask int. */ + val = PMC_ALL_INTERRUPT_BITS; + AAC_MEM0_SETREG4(sc, AAC_SRC_IOAR, val); + val = AAC_MEM0_GETREG4(sc, AAC_SRC_OIMR); + AAC_MEM0_SETREG4(sc, AAC_SRC_OIMR, + val & (~(PMC_GLOBAL_INT_BIT2))); + break; + + default: + break; } } @@ -2028,6 +2355,34 @@ aac_src_send_command(struct aac_softc *sc, struct aac_command *cm) fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "send command (new comm. type1)"); + if (sc->msi_enabled && cm->cm_fib->Header.Command != AifRequest && + sc->aac_max_msix > 1) { + u_int16_t vector_no, first_choice = 0xffff; + + vector_no = sc->aac_fibs_pushed_no % sc->aac_max_msix; + do { + vector_no += 1; + if (vector_no == sc->aac_max_msix) + vector_no = 1; + if (sc->aac_rrq_outstanding[vector_no] < + sc->aac_vector_cap) + break; + if (0xffff == first_choice) + first_choice = vector_no; + else if (vector_no == first_choice) + break; + } while (1); + if (vector_no == first_choice) + vector_no = 0; + sc->aac_rrq_outstanding[vector_no]++; + if (sc->aac_fibs_pushed_no == 0xffffffff) + sc->aac_fibs_pushed_no = 0; + else + sc->aac_fibs_pushed_no++; + + cm->cm_fib->Header.Handle += (vector_no << 16); + } + if (sc->flags & AAC_FLAGS_NEW_COMM_TYPE2) { /* Calculate the amount to the fibsize bits */ fibsize = (cm->cm_fib->Header.Size + 127) / 128 - 1; @@ -3364,9 +3719,11 @@ aac_reset_adapter(struct aac_softc *sc) struct aac_command *cm; struct aac_fib *fib; struct aac_pause_command *pc; - u_int32_t status, old_flags, reset_mask, waitCount; + u_int32_t status, reset_mask, waitCount, max_msix_orig; + int msi_enabled_orig; fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + mtx_assert(&sc->aac_io_lock, MA_OWNED); if (sc->aac_state & AAC_STATE_RESET) { device_printf(sc->aac_dev, "aac_reset_adapter() already in progress\n"); @@ -3375,7 +3732,7 @@ aac_reset_adapter(struct aac_softc *sc) sc->aac_state |= AAC_STATE_RESET; /* disable interrupt */ - AAC_MASK_INTERRUPTS(sc); + AAC_ACCESS_DEVREG(sc, AAC_DISABLE_INTERRUPT); /* * Abort all pending commands: @@ -3458,35 +3815,39 @@ aac_reset_adapter(struct aac_softc *sc) } } else if (sc->aac_support_opt2 & AAC_SUPPORTED_DOORBELL_RESET) { AAC_MEM0_SETREG4(sc, AAC_SRC_IDBR, reset_mask); - /* We need to wait for 5 seconds before accessing the doorbell again - * 10000 * 100us = 1000,000us = 1000ms = 1s + /* + * We need to wait for 5 seconds before accessing the doorbell + * again, 10000 * 100us = 1000,000us = 1000ms = 1s */ waitCount = 5 * 10000; while (waitCount) { - DELAY(100); /* delay 100 microseconds */ + DELAY(100); /* delay 100 microseconds */ waitCount--; } } /* - * Re-read and renegotiate the FIB parameters, as one of the actions - * that can result from an IOP reset is the running of a new firmware - * image. - */ - old_flags = sc->flags; - /* * Initialize the adapter. */ + max_msix_orig = sc->aac_max_msix; + msi_enabled_orig = sc->msi_enabled; + sc->msi_enabled = FALSE; if (aac_check_firmware(sc) != 0) goto finish; if (!(sc->flags & AAC_FLAGS_SYNC_MODE)) { - if (aac_init(sc) != 0) - goto finish; + sc->aac_max_msix = max_msix_orig; + if (msi_enabled_orig) { + sc->msi_enabled = msi_enabled_orig; + AAC_ACCESS_DEVREG(sc, AAC_ENABLE_MSIX); + } + mtx_unlock(&sc->aac_io_lock); + aac_init(sc); + mtx_lock(&sc->aac_io_lock); } finish: sc->aac_state &= ~AAC_STATE_RESET; - AAC_UNMASK_INTERRUPTS(sc); + AAC_ACCESS_DEVREG(sc, AAC_ENABLE_INTERRUPT); aacraid_startio(sc); return (0); } diff --git a/sys/dev/aacraid/aacraid_cam.c b/sys/dev/aacraid/aacraid_cam.c index 602e961..56eaac0 100644 --- a/sys/dev/aacraid/aacraid_cam.c +++ b/sys/dev/aacraid/aacraid_cam.c @@ -709,7 +709,7 @@ aac_container_special_command(struct cam_sim *sim, union ccb *ccb, "Container READ_CAPACITY id %d lun %d len %d", ccb->ccb_h.target_id, ccb->ccb_h.target_lun, ccb->csio.dxfer_len); - scsi_ulto4b(co->co_mntobj.ObjExtension.BlockSize, p->length); + scsi_ulto4b(co->co_mntobj.ObjExtension.BlockDevice.BlockSize, p->length); /* check if greater than 2TB */ if (co->co_mntobj.CapacityHigh) { if (sc->flags & AAC_FLAGS_LBA_64BIT) @@ -737,9 +737,20 @@ aac_container_special_command(struct cam_sim *sim, union ccb *ccb, xpt_done(ccb); return; } - scsi_ulto4b(co->co_mntobj.ObjExtension.BlockSize, p->length); + scsi_ulto4b(co->co_mntobj.ObjExtension.BlockDevice.BlockSize, p->length); scsi_ulto4b(co->co_mntobj.CapacityHigh, p->addr); scsi_ulto4b(co->co_mntobj.Capacity-1, &p->addr[4]); + + if (ccb->csio.dxfer_len >= 14) { + u_int32_t mapping = co->co_mntobj.ObjExtension.BlockDevice.bdLgclPhysMap; + p->prot_lbppbe = 0; + while (mapping > 1) { + mapping >>= 1; + p->prot_lbppbe++; + } + p->prot_lbppbe &= 0x0f; + } + ccb->ccb_h.status = CAM_REQ_CMP; break; } @@ -769,7 +780,7 @@ aac_container_special_command(struct cam_sim *sim, union ccb *ccb, p->hd.block_descr_len = sizeof(struct scsi_mode_block_descr); p->hd.datalen += p->hd.block_descr_len; - scsi_ulto3b(co->co_mntobj.ObjExtension.BlockSize, p->bd.block_len); + scsi_ulto3b(co->co_mntobj.ObjExtension.BlockDevice.BlockSize, p->bd.block_len); if (co->co_mntobj.Capacity > 0xffffff || co->co_mntobj.CapacityHigh) { p->bd.num_blocks[0] = 0xff; @@ -1213,11 +1224,20 @@ aac_cam_complete(struct aac_command *cm) */ if ((device == T_DIRECT && !(sc->aac_feature_bits & AAC_SUPPL_SUPPORTED_JBOD)) || - (device == T_PROCESSOR) || - (sc->flags & AAC_FLAGS_CAM_PASSONLY)) + (device == T_PROCESSOR)) ccb->csio.data_ptr[0] = ((device & 0xe0) | T_NODEVICE); + /* handle phys. components of a log. drive */ + if (ccb->csio.data_ptr[0] & 0x20) { + if (sc->hint_flags & 8) { + /* expose phys. device (daXX) */ + ccb->csio.data_ptr[0] &= 0xdf; + } else { + /* phys. device only visible through pass device (passXX) */ + ccb->csio.data_ptr[0] |= 0x10; + } + } } else if (ccb->ccb_h.status == CAM_SEL_TIMEOUT && ccb->ccb_h.target_lun != 0) { /* fix for INQUIRYs on Lun>0 */ diff --git a/sys/dev/aacraid/aacraid_reg.h b/sys/dev/aacraid/aacraid_reg.h index 988520c..682d400 100644 --- a/sys/dev/aacraid/aacraid_reg.h +++ b/sys/dev/aacraid/aacraid_reg.h @@ -230,8 +230,7 @@ struct aac_adapter_init { #define AAC_INIT_STRUCT_REVISION_4 4 #define AAC_INIT_STRUCT_REVISION_6 6 #define AAC_INIT_STRUCT_REVISION_7 7 - u_int32_t MiniPortRevision; -#define AAC_INIT_STRUCT_MINIPORT_REVISION 1 + u_int32_t NoOfMSIXVectors; u_int32_t FilesystemRevision; u_int32_t CommHeaderAddress; u_int32_t FastIoCommAreaAddress; @@ -677,6 +676,13 @@ struct aac_supplement_adapter_info { #define AAC_KERNEL_PANIC 0x00000100 /* + * for dual FW image support + */ +#define AAC_FLASH_UPD_PENDING 0x00002000 +#define AAC_FLASH_UPD_SUCCESS 0x00004000 +#define AAC_FLASH_UPD_FAILED 0x00008000 + +/* * Data types relating to control and monitoring of the NVRAM/WriteCache * subsystem. */ @@ -1147,6 +1153,9 @@ typedef enum _VM_COMMANDS { #define CT_CID_TO_32BITS_UID 165 #define CT_PM_DRIVER_SUPPORT 245 +/* General CT_xxx return status */ +#define CT_OK 218 + /* CT_PM_DRIVER_SUPPORT parameter */ typedef enum { AAC_PM_DRIVERSUP_GET_STATUS = 1, @@ -1188,7 +1197,10 @@ struct aac_mntobj { u_int32_t ContentState; union { u_int32_t pad[8]; - u_int32_t BlockSize; + struct { + u_int32_t BlockSize; + u_int32_t bdLgclPhysMap; + } BlockDevice; } ObjExtension; u_int32_t AlterEgoId; u_int32_t CapacityHigh; @@ -1334,6 +1346,7 @@ typedef enum { #define CT_PACKET_SIZE \ (AAC_FIB_DATASIZE - sizeof (u_int32_t) - \ ((sizeof (u_int32_t)) * (MAX_FIB_PARAMS + 1))) +#define CNT_SIZE 5 struct aac_fsa_ctm { u_int32_t command; @@ -1346,6 +1359,19 @@ struct aac_cnt_config { struct aac_fsa_ctm CTCommand; }; +/* check config. */ +enum { + CFACT_CONTINUE = 0, /* continue without pause */ + CFACT_PAUSE, /* pause, then continue */ + CFACT_ABORT /* abort */ +}; + +struct aac_cf_status_hdr { + u_int32_t action; + u_int32_t flags; + u_int32_t recordcount; +}; + /* * Block read/write operations. * These structures are packed into the 'data' area in the FIB. @@ -1540,7 +1566,8 @@ enum { * Register definitions for the Adaptec PMC SRC/SRCv adapters. */ /* accessible via BAR0 */ -#define AAC_SRC_OMR 0xbc /* outbound message register */ +#define AAC_SRC_OMR 0xbc /* outbound message register */ +#define AAC_SRC_IOAR 0x18 /* IOA->host interrupt register */ #define AAC_SRC_IDBR 0x20 /* inbound doorbell register */ #define AAC_SRC_IISR 0x24 /* inbound interrupt status register */ #define AAC_SRC_ODBR_R 0x9c /* outbound doorbell register read */ @@ -1548,7 +1575,8 @@ enum { #define AAC_SRC_OIMR 0x34 /* outbound interrupt mask register */ #define AAC_SRC_IQUE32 0x40 /* inbound queue address 32-bit */ #define AAC_SRC_IQUE64_L 0xc0 /* inbound queue address 64-bit (low) */ -#define AAC_SRC_IQUE64_H 0xc4 /* inbound queue address 64-bit (high) */ +#define AAC_SRC_IQUE64_H 0xc4 /* inbound queue address 64-bit (high)*/ +#define AAC_SRC_ODBR_MSI 0xc8 /* MSI register for sync./AIF */ #define AAC_SRC_MAILBOX 0x7fc60 /* mailbox (20 bytes) */ #define AAC_SRCV_MAILBOX 0x1000 /* mailbox (20 bytes) */ @@ -1569,13 +1597,9 @@ enum { * Status bits in the doorbell registers. */ #define AAC_DB_SYNC_COMMAND (1<<0) /* send/completed synchronous FIB */ -#define AAC_DB_COMMAND_READY (1<<1) /* posted one or more commands */ -#define AAC_DB_RESPONSE_READY (1<<2) /* one or more commands complete */ -#define AAC_DB_COMMAND_NOT_FULL (1<<3) /* command queue not full */ -#define AAC_DB_RESPONSE_NOT_FULL (1<<4) /* response queue not full */ -#define AAC_DB_AIF_PENDING (1<<6) /* pending AIF (new comm. type1) */ +#define AAC_DB_AIF_PENDING (1<<6) /* pending AIF (new comm. type1) */ /* PMC specific outbound doorbell bits */ -#define AAC_DB_RESPONSE_SENT_NS (1<<1) /* response sent (not shifted) */ +#define AAC_DB_RESPONSE_SENT_NS (1<<1) /* response sent (not shifted)*/ /* * The adapter can request the host print a message by setting the @@ -1588,11 +1612,55 @@ enum { #define AAC_PRINTF_DONE (1<<5) /* Host completed printf processing */ /* - * Mask containing the interrupt bits we care about. We don't anticipate (or - * want) interrupts not in this mask. + * Interrupts */ -#define AAC_DB_INTERRUPTS (AAC_DB_COMMAND_READY | \ - AAC_DB_RESPONSE_READY | \ - AAC_DB_PRINTF) -#define AAC_DB_INT_NEW_COMM 0x08 -#define AAC_DB_INT_NEW_COMM_TYPE1 0x04 +#define AAC_MAX_MSIX 32 /* vectors */ +#define AAC_PCI_MSI_ENABLE 0x8000 +#define AAC_MSI_SYNC_STATUS 0x1000 + +enum { + AAC_ENABLE_INTERRUPT = 0x0, + AAC_DISABLE_INTERRUPT, + AAC_ENABLE_MSIX, + AAC_DISABLE_MSIX, + AAC_CLEAR_AIF_BIT, + AAC_CLEAR_SYNC_BIT, + AAC_ENABLE_INTX +}; + +#define AAC_INT_MODE_INTX (1<<0) +#define AAC_INT_MODE_MSI (1<<1) +#define AAC_INT_MODE_AIF (1<<2) +#define AAC_INT_MODE_SYNC (1<<3) + +#define AAC_INT_ENABLE_TYPE1_INTX 0xfffffffb +#define AAC_INT_ENABLE_TYPE1_MSIX 0xfffffffa +#define AAC_INT_DISABLE_ALL 0xffffffff + +/* Bit definitions in IOA->Host Interrupt Register */ +#define PMC_TRANSITION_TO_OPERATIONAL (0x80000000 >> 0) +#define PMC_IOARCB_TRANSFER_FAILED (0x80000000 >> 3) +#define PMC_IOA_UNIT_CHECK (0x80000000 >> 4) +#define PMC_NO_HOST_RRQ_FOR_CMD_RESPONSE (0x80000000 >> 5) +#define PMC_CRITICAL_IOA_OP_IN_PROGRESS (0x80000000 >> 6) +#define PMC_IOARRIN_LOST (0x80000000 >> 27) +#define PMC_SYSTEM_BUS_MMIO_ERROR (0x80000000 >> 28) +#define PMC_IOA_PROCESSOR_IN_ERROR_STATE (0x80000000 >> 29) +#define PMC_HOST_RRQ_VALID (0x80000000 >> 30) +#define PMC_OPERATIONAL_STATUS (0x80000000 >> 0) +#define PMC_ALLOW_MSIX_VECTOR0 (0x80000000 >> 31) + +#define PMC_IOA_ERROR_INTERRUPTS (PMC_IOARCB_TRANSFER_FAILED | \ + PMC_IOA_UNIT_CHECK | \ + PMC_NO_HOST_RRQ_FOR_CMD_RESPONSE | \ + PMC_IOARRIN_LOST | \ + PMC_SYSTEM_BUS_MMIO_ERROR | \ + PMC_IOA_PROCESSOR_IN_ERROR_STATE) + +#define PMC_ALL_INTERRUPT_BITS (PMC_IOA_ERROR_INTERRUPTS | \ + PMC_HOST_RRQ_VALID | \ + PMC_TRANSITION_TO_OPERATIONAL | \ + PMC_ALLOW_MSIX_VECTOR0) + +#define PMC_GLOBAL_INT_BIT2 0x00000004 +#define PMC_GLOBAL_INT_BIT0 0x00000001 diff --git a/sys/dev/aacraid/aacraid_var.h b/sys/dev/aacraid/aacraid_var.h index 07546ff..55035a9 100644 --- a/sys/dev/aacraid/aacraid_var.h +++ b/sys/dev/aacraid/aacraid_var.h @@ -46,8 +46,8 @@ #define AAC_TYPE_RELEASE 4 #define AAC_DRIVER_MAJOR_VERSION 3 -#define AAC_DRIVER_MINOR_VERSION 1 -#define AAC_DRIVER_BUGFIX_LEVEL 1 +#define AAC_DRIVER_MINOR_VERSION 2 +#define AAC_DRIVER_BUGFIX_LEVEL 5 #define AAC_DRIVER_TYPE AAC_TYPE_RELEASE #ifndef AAC_DRIVER_BUILD @@ -114,14 +114,20 @@ #define AAC_BOOT_TIMEOUT (3 * 60) /* - * Timeout for immediate commands. + * We wait this many seconds for the adapter to come ready + * after flash update */ -#define AAC_IMMEDIATE_TIMEOUT 30 /* seconds */ +#define AAC_FWUPD_TIMEOUT (5 * 60) + +/* + * Timeout for sync. commands. + */ +#define AAC_SYNC_TIMEOUT 180 /* seconds */ /* * Timeout for normal commands */ -#define AAC_CMD_TIMEOUT 120 /* seconds */ +#define AAC_CMD_TIMEOUT 180 /* seconds */ /* * Rate at which we periodically check for timed out commands and kick the @@ -271,7 +277,7 @@ struct aac_interface u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3); int (*aif_get_mailbox)(struct aac_softc *sc, int mb); - void (*aif_set_interrupts)(struct aac_softc *sc, int enable); + void (*aif_access_devreg)(struct aac_softc *sc, int enable); int (*aif_send_command)(struct aac_softc *sc, struct aac_command *cm); int (*aif_get_outb_queue)(struct aac_softc *sc); void (*aif_set_outb_queue)(struct aac_softc *sc, int index); @@ -289,10 +295,8 @@ extern struct aac_interface aacraid_srcv_interface; (arg3))) #define AAC_GET_MAILBOX(sc, mb) ((sc)->aac_if.aif_get_mailbox((sc), \ (mb))) -#define AAC_MASK_INTERRUPTS(sc) ((sc)->aac_if.aif_set_interrupts((sc), \ - 0)) -#define AAC_UNMASK_INTERRUPTS(sc) ((sc)->aac_if.aif_set_interrupts((sc), \ - 1)) +#define AAC_ACCESS_DEVREG(sc, mode) ((sc)->aac_if.aif_access_devreg((sc), \ + mode)) #define AAC_SEND_COMMAND(sc, cm) ((sc)->aac_if.aif_send_command((sc), (cm))) #define AAC_GET_OUTB_QUEUE(sc) ((sc)->aac_if.aif_get_outb_queue((sc))) #define AAC_SET_OUTB_QUEUE(sc, idx) ((sc)->aac_if.aif_set_outb_queue((sc), (idx))) @@ -331,6 +335,12 @@ struct aac_fib_context { struct aac_fib_context *next, *prev; }; +/* MSIX context */ +struct aac_msix_ctx { + int vector_no; + struct aac_softc *sc; +}; + /* * Per-controller structure. */ @@ -345,9 +355,10 @@ struct aac_softc bus_dma_tag_t aac_parent_dmat; /* parent DMA tag */ bus_dma_tag_t aac_buffer_dmat; /* data buffer/command * DMA tag */ - struct resource *aac_irq; /* interrupt */ - int aac_irq_rid; - void *aac_intr; /* interrupt handle */ + struct resource *aac_irq[AAC_MAX_MSIX]; /* interrupt */ + int aac_irq_rid[AAC_MAX_MSIX]; + void *aac_intr[AAC_MAX_MSIX]; /* interrupt handle */ + struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */ eventhandler_tag eh; #if __FreeBSD_version >= 800000 struct callout aac_daemontime; /* clock daemon callout */ @@ -375,7 +386,9 @@ struct aac_softc * DMA map */ struct aac_common *aac_common; u_int32_t aac_common_busaddr; - u_int32_t aac_host_rrq_idx; + u_int32_t aac_host_rrq_idx[AAC_MAX_MSIX]; + u_int32_t aac_rrq_outstanding[AAC_MAX_MSIX]; + u_int32_t aac_fibs_pushed_no; struct aac_interface aac_if; /* command/fib resources */ @@ -466,6 +479,9 @@ struct aac_softc u_int32_t aac_feature_bits; /* feature bits from suppl. info */ u_int32_t aac_support_opt2; /* supp. options from suppl. info */ u_int32_t aac_max_aif; /* max. AIF count */ + u_int32_t aac_max_msix; /* max. MSI-X vectors */ + u_int32_t aac_vector_cap; /* MSI-X vector capab.*/ + int msi_enabled; /* MSI/MSI-X enabled */ #define AAC_CAM_TARGET_WILDCARD ~0 void (*cam_rescan_cb)(struct aac_softc *, uint32_t, uint32_t); @@ -515,8 +531,6 @@ extern void aacraid_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error); extern int aacraid_wait_command(struct aac_command *cmp); -/* #define AACRAID_DEBUG */ - #ifdef AACRAID_DEBUG # define fwprintf(sc, flags, fmt, args...) \ aacraid_fw_printf(sc, flags, "%s: " fmt, __func__, ##args); |