summaryrefslogtreecommitdiffstats
path: root/sys/dev/aacraid
diff options
context:
space:
mode:
authorachim <achim@FreeBSD.org>2014-03-11 14:59:34 +0000
committerachim <achim@FreeBSD.org>2014-03-11 14:59:34 +0000
commitd9fd2797e53e8b8f1e593c3fbce42a5ed3bc71dc (patch)
treedcbd9d4a8e6e84967084386895540b8c6403831c /sys/dev/aacraid
parentc157604f42c4e16d9aa5752902f75fdc5c38dfe3 (diff)
downloadFreeBSD-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/aacraid')
-rw-r--r--sys/dev/aacraid/aacraid.c603
-rw-r--r--sys/dev/aacraid/aacraid_cam.c30
-rw-r--r--sys/dev/aacraid/aacraid_reg.h104
-rw-r--r--sys/dev/aacraid/aacraid_var.h46
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);
OpenPOWER on IntegriCloud