Date: Wed, 16 Sep 2009 23:27:14 +0000 (UTC) From: Scott Long <scottl@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r197263 - head/sys/dev/ciss Message-ID: <200909162327.n8GNREaC038896@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: scottl Date: Wed Sep 16 23:27:14 2009 New Revision: 197263 URL: http://svn.freebsd.org/changeset/base/197263 Log: Sync driver with Yahoo: - Implement MSI support (MSIX support was already there) - Use a table to drive MSI/MSIX exceptions - Pre-calculate the command address instead of wasting cycles doing the calculation on every i/o. Modified: head/sys/dev/ciss/ciss.c head/sys/dev/ciss/cissreg.h head/sys/dev/ciss/cissvar.h Modified: head/sys/dev/ciss/ciss.c ============================================================================== --- head/sys/dev/ciss/ciss.c Wed Sep 16 23:17:22 2009 (r197262) +++ head/sys/dev/ciss/ciss.c Wed Sep 16 23:27:14 2009 (r197263) @@ -279,8 +279,10 @@ TUNABLE_INT("hw.ciss.force_interrupt", & * stick with matching against subvendor/subdevice, and thus have to * be updated for every new CISS adapter that appears. */ -#define CISS_BOARD_SA5 (1<<0) -#define CISS_BOARD_SA5B (1<<1) +#define CISS_BOARD_UNKNWON 0 +#define CISS_BOARD_SA5 1 +#define CISS_BOARD_SA5B 2 +#define CISS_BOARD_NOMSI (1<<4) static struct { @@ -289,10 +291,10 @@ static struct int flags; char *desc; } ciss_vendor_data[] = { - { 0x0e11, 0x4070, CISS_BOARD_SA5, "Compaq Smart Array 5300" }, - { 0x0e11, 0x4080, CISS_BOARD_SA5B, "Compaq Smart Array 5i" }, - { 0x0e11, 0x4082, CISS_BOARD_SA5B, "Compaq Smart Array 532" }, - { 0x0e11, 0x4083, CISS_BOARD_SA5B, "HP Smart Array 5312" }, + { 0x0e11, 0x4070, CISS_BOARD_SA5|CISS_BOARD_NOMSI, "Compaq Smart Array 5300" }, + { 0x0e11, 0x4080, CISS_BOARD_SA5B|CISS_BOARD_NOMSI, "Compaq Smart Array 5i" }, + { 0x0e11, 0x4082, CISS_BOARD_SA5B|CISS_BOARD_NOMSI, "Compaq Smart Array 532" }, + { 0x0e11, 0x4083, CISS_BOARD_SA5B|CISS_BOARD_NOMSI, "HP Smart Array 5312" }, { 0x0e11, 0x4091, CISS_BOARD_SA5, "HP Smart Array 6i" }, { 0x0e11, 0x409A, CISS_BOARD_SA5, "HP Smart Array 641" }, { 0x0e11, 0x409B, CISS_BOARD_SA5, "HP Smart Array 642" }, @@ -661,7 +663,6 @@ ciss_init_pci(struct ciss_softc *sc) (CISS_TRANSPORT_METHOD_SIMPLE | CISS_TRANSPORT_METHOD_PERF))) { ciss_printf(sc, "No supported transport layers: 0x%x\n", sc->ciss_cfg->supported_methods); - return(ENXIO); } switch (ciss_force_transport) { @@ -677,7 +678,7 @@ ciss_init_pci(struct ciss_softc *sc) } setup: - if (supported_methods & CISS_TRANSPORT_METHOD_PERF) { + if ((supported_methods & CISS_TRANSPORT_METHOD_PERF) != 0) { method = CISS_TRANSPORT_METHOD_PERF; sc->ciss_perf = (struct ciss_perf_config *)(cbase + cofs + sc->ciss_cfg->transport_offset); @@ -744,7 +745,7 @@ setup: * controller. Hopefully enabling this bit universally will work OK. * It seems to work fine for SA6i controllers. */ - sc->ciss_interrupt_mask = CISS_TL_PERF_INTR_OPQ | CISS_TL_PERF_INTR_MSI; + sc->ciss_interrupt_mask = CISS_TL_PERF_INTR_OPQ | CISS_TL_PERF_INTR_MSI; } else { ciss_printf(sc, "SIMPLE Transport\n"); @@ -792,7 +793,7 @@ setup: BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ - CISS_COMMAND_SG_LENGTH, /* nsegments */ + CISS_MAX_SG_ELEMENTS, /* nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ @@ -810,7 +811,7 @@ setup: BUS_SPACE_MAXADDR, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ - MAXBSIZE, CISS_COMMAND_SG_LENGTH, /* maxsize, nsegments */ + MAXBSIZE, CISS_MAX_SG_ELEMENTS, /* maxsize, nsegments */ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ busdma_lock_mutex, &sc->ciss_mtx, /* lockfunc, lockarg */ @@ -823,32 +824,42 @@ setup: /************************************************************************ * Setup MSI/MSIX operation (Performant only) - * Four interrupts are available, but we only use 1 right now. + * Four interrupts are available, but we only use 1 right now. If MSI-X + * isn't avaialble, try using MSI instead. */ static int ciss_setup_msix(struct ciss_softc *sc) { - uint32_t id; int val, i; /* Weed out devices that don't actually support MSI */ - id = (pci_get_subvendor(sc->ciss_dev) << 16) | - pci_get_subdevice(sc->ciss_dev); - if ((id == 0x0e114070) || (id == 0x0e114080) || (id == 0x0e114082) || - (id == 0x0e114083)) + i = ciss_lookup(sc->ciss_dev); + if (ciss_vendor_data[i].flags & CISS_BOARD_NOMSI) return (EINVAL); + /* + * Only need to use the minimum number of MSI vectors, as the driver + * doesn't support directed MSIX interrupts. + */ val = pci_msix_count(sc->ciss_dev); - if (val < CISS_MSI_COUNT) - return (EINVAL); + if (val < CISS_MSI_COUNT) { + val = pci_msi_count(sc->ciss_dev); + device_printf(sc->ciss_dev, "got %d MSI messages]\n", val); + if (val < CISS_MSI_COUNT) + return (EINVAL); + } val = MIN(val, CISS_MSI_COUNT); - if (pci_alloc_msix(sc->ciss_dev, &val) != 0) - return (EINVAL); + if (pci_alloc_msix(sc->ciss_dev, &val) != 0) { + if (pci_alloc_msi(sc->ciss_dev, &val) != 0) + return (EINVAL); + } sc->ciss_msi = val; - ciss_printf(sc, "Using MSIX interrupt\n"); + if (bootverbose) + ciss_printf(sc, "Using %d MSIX interrupt%s\n", val, + (val != 1) ? "s" : ""); - for (i = 0; i < CISS_MSI_COUNT; i++) + for (i = 0; i < val; i++) sc->ciss_irq_rid[i] = i + 1; return (0); @@ -1031,7 +1042,7 @@ ciss_soft_reset(struct ciss_softc *sc) NULL, 0)) != 0) break; - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cc->header.address = sc->ciss_controllers[i]; if ((error = ciss_synch_request(cr, 60 * 1000)) != 0) @@ -1104,6 +1115,9 @@ ciss_init_requests(struct ciss_softc *sc cr = &sc->ciss_request[i]; cr->cr_sc = sc; cr->cr_tag = i; + cr->cr_cc = (struct ciss_command *)((uintptr_t)sc->ciss_command + + CISS_COMMAND_ALLOC_SIZE * i); + cr->cr_ccphys = sc->ciss_command_phys + CISS_COMMAND_ALLOC_SIZE * i; bus_dmamap_create(sc->ciss_buffer_dmat, 0, &cr->cr_datamap); ciss_enqueue_free(cr); } @@ -1257,7 +1271,7 @@ ciss_report_luns(struct ciss_softc *sc, /* * Build the Report Logical/Physical LUNs command. */ - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cr->cr_data = cll; cr->cr_length = report_size; cr->cr_flags = CISS_REQ_DATAIN; @@ -1582,7 +1596,7 @@ ciss_inquiry_logical(struct ciss_softc * if ((error = ciss_get_request(sc, &cr)) != 0) goto out; - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cr->cr_data = &ld->cl_geometry; cr->cr_length = sizeof(ld->cl_geometry); cr->cr_flags = CISS_REQ_DATAIN; @@ -1646,7 +1660,7 @@ ciss_identify_logical(struct ciss_softc (void **)&ld->cl_ldrive, sizeof(*ld->cl_ldrive))) != 0) goto out; - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cc->header.address = *ld->cl_controller; /* target controller */ cbc = (struct ciss_bmic_cdb *)&(cc->cdb.cdb[0]); cbc->log_drive = CISS_LUN_TO_TARGET(ld->cl_address.logical.lun); @@ -1742,7 +1756,7 @@ ciss_get_ldrive_status(struct ciss_softc (void **)&ld->cl_lstatus, sizeof(*ld->cl_lstatus))) != 0) goto out; - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cc->header.address = *ld->cl_controller; /* target controller */ cbc = (struct ciss_bmic_cdb *)&(cc->cdb.cdb[0]); cbc->log_drive = CISS_LUN_TO_TARGET(ld->cl_address.logical.lun); @@ -1832,7 +1846,7 @@ ciss_accept_media(struct ciss_softc *sc, if ((error = ciss_get_bmic_request(sc, &cr, CISS_BMIC_ACCEPT_MEDIA, NULL, 0)) != 0) goto out; - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cc->header.address = *ld->cl_controller; /* target controller */ cbc = (struct ciss_bmic_cdb *)&(cc->cdb.cdb[0]); cbc->log_drive = ldrive; @@ -2000,7 +2014,7 @@ ciss_start(struct ciss_request *cr) struct ciss_command *cc; /* XXX debugging only */ int error; - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; debug(2, "post command %d tag %d ", cr->cr_tag, cc->header.host_tag); /* @@ -2056,7 +2070,7 @@ ciss_done(struct ciss_softc *sc, cr_qhea continue; } cr = &(sc->ciss_request[index]); - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cc->header.host_tag = tag; /* not updated by adapter */ ciss_enqueue_complete(cr, qh); } @@ -2085,7 +2099,7 @@ ciss_perf_done(struct ciss_softc *sc, cr (tag & CISS_HDR_HOST_TAG_ERROR) ? " with error" : ""); if (index < sc->ciss_max_requests) { cr = &(sc->ciss_request[index]); - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cc->header.host_tag = tag; /* not updated by adapter */ ciss_enqueue_complete(cr, qh); } else { @@ -2222,7 +2236,7 @@ _ciss_report_request(struct ciss_request debug_called(2); - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; ce = (struct ciss_error_info *)&(cc->sg[0]); /* @@ -2369,7 +2383,7 @@ ciss_abort_request(struct ciss_request * return(error); /* build the abort command */ - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cc->header.address.mode.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL; /* addressing? */ cc->header.address.physical.target = 0; cc->header.address.physical.bus = 0; @@ -2438,12 +2452,12 @@ ciss_preen_command(struct ciss_request * * Note that we set up the error_info structure here, since the * length can be overwritten by any command. */ - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cc->header.sg_in_list = 0; /* kinda inefficient this way */ cc->header.sg_total = 0; cc->header.host_tag = cr->cr_tag << 2; cc->header.host_tag_zeroes = 0; - cmdphys = CISS_FIND_COMMANDPHYS(cr); + cmdphys = cr->cr_ccphys; cc->error_info.error_info_address = cmdphys + sizeof(struct ciss_command); cc->error_info.error_info_length = CISS_COMMAND_ALLOC_SIZE - sizeof(struct ciss_command); } @@ -2514,7 +2528,7 @@ ciss_get_bmic_request(struct ciss_softc if (!dataout) cr->cr_flags = CISS_REQ_DATAIN; - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cc->header.address.physical.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL; cc->header.address.physical.bus = 0; cc->header.address.physical.target = 0; @@ -2562,7 +2576,7 @@ ciss_user_command(struct ciss_softc *sc, */ while (ciss_get_request(sc, &cr) != 0) msleep(sc, &sc->ciss_mtx, PPAUSE, "cissREQ", hz); - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; /* * Allocate an in-kernel databuffer if required, copy in user data. @@ -2667,7 +2681,7 @@ ciss_map_request(struct ciss_request *cr if (sc->ciss_perf) CISS_TL_PERF_POST_CMD(sc, cr); else - CISS_TL_SIMPLE_POST_CMD(sc, CISS_FIND_COMMANDPHYS(cr)); + CISS_TL_SIMPLE_POST_CMD(sc, cr->cr_ccphys); } return(0); @@ -2685,7 +2699,7 @@ ciss_request_map_helper(void *arg, bus_d cr = (struct ciss_request *)arg; sc = cr->cr_sc; - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; for (i = 0; i < nseg; i++) { cc->sg[i].address = segs[i].ds_addr; @@ -2725,7 +2739,7 @@ ciss_request_map_helper(void *arg, bus_d if (sc->ciss_perf) CISS_TL_PERF_POST_CMD(sc, cr); else - CISS_TL_SIMPLE_POST_CMD(sc, CISS_FIND_COMMANDPHYS(cr)); + CISS_TL_SIMPLE_POST_CMD(sc, cr->cr_ccphys); } /************************************************************************ @@ -3091,7 +3105,7 @@ ciss_cam_action_io(struct cam_sim *sim, /* * Build the command. */ - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cr->cr_data = csio->data_ptr; cr->cr_length = csio->dxfer_len; cr->cr_complete = ciss_cam_complete; @@ -3235,7 +3249,7 @@ ciss_cam_complete(struct ciss_request *c debug_called(2); sc = cr->cr_sc; - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; ce = (struct ciss_error_info *)&(cc->sg[0]); csio = (struct ccb_scsiio *)cr->cr_private; @@ -3414,7 +3428,7 @@ ciss_periodic(void *arg) * Send the NOP message and wait for a response. */ if (ciss_nop_message_heartbeat != 0 && (error = ciss_get_request(sc, &cr)) == 0) { - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cr->cr_complete = ciss_nop_complete; cc->cdb.cdb_length = 1; cc->cdb.type = CISS_CDB_TYPE_MESSAGE; @@ -3484,7 +3498,7 @@ ciss_disable_adapter(struct ciss_softc * if ((cr->cr_flags & CISS_REQ_BUSY) == 0) continue; - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; ce = (struct ciss_error_info *)&(cc->sg[0]); ce->command_status = CISS_CMD_STATUS_HARDWARE_ERROR; ciss_enqueue_complete(cr, &qh); @@ -3561,7 +3575,7 @@ ciss_notify_event(struct ciss_softc *sc) ciss_preen_command(cr); /* (re)build the notify event command */ - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cc->header.address.physical.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL; cc->header.address.physical.bus = 0; cc->header.address.physical.target = 0; @@ -3615,7 +3629,7 @@ ciss_notify_complete(struct ciss_request int command_status; debug_called(1); - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cn = (struct ciss_notify *)cr->cr_data; sc = cr->cr_sc; @@ -3715,7 +3729,7 @@ ciss_notify_abort(struct ciss_softc *sc) cr->cr_length = CISS_NOTIFY_DATA_SIZE; /* build the CDB */ - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; cc->header.address.physical.mode = CISS_HDR_ADDRESS_MODE_PERIPHERAL; cc->header.address.physical.bus = 0; cc->header.address.physical.target = 0; @@ -4174,7 +4188,7 @@ ciss_print_request(struct ciss_request * int i; sc = cr->cr_sc; - cc = CISS_FIND_COMMAND(cr); + cc = cr->cr_cc; ciss_printf(sc, "REQUEST @ %p\n", cr); ciss_printf(sc, " data %p/%d tag %d flags %b\n", Modified: head/sys/dev/ciss/cissreg.h ============================================================================== --- head/sys/dev/ciss/cissreg.h Wed Sep 16 23:17:22 2009 (r197262) +++ head/sys/dev/ciss/cissreg.h Wed Sep 16 23:27:14 2009 (r197263) @@ -731,7 +731,7 @@ struct ciss_bmic_flush_cache { #define CISS_TL_PERF_INTR_OPQ (CISS_TL_SIMPLE_INTR_OPQ_SA5 | CISS_TL_SIMPLE_INTR_OPQ_SA5B) #define CISS_TL_PERF_INTR_MSI 0x01 -#define CISS_TL_PERF_POST_CMD(sc, cr) CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IPQ, CISS_FIND_COMMANDPHYS(cr) | (cr)->cr_sg_tag) +#define CISS_TL_PERF_POST_CMD(sc, cr) CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_IPQ, cr->cr_ccphys | (cr)->cr_sg_tag) #define CISS_TL_PERF_FLUSH_INT(sc) CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_OSR) #define CISS_TL_PERF_CLEAR_INT(sc) CISS_TL_SIMPLE_WRITE(sc, CISS_TL_SIMPLE_ODC, CISS_TL_SIMPLE_ODC_CLEAR) #define CISS_CYCLE_MASK 0x00000001 @@ -747,4 +747,5 @@ struct ciss_bmic_flush_cache { CISS_TL_SIMPLE_READ(sc, CISS_TL_SIMPLE_IMR) & ~(sc)->ciss_interrupt_mask) + #endif /* _KERNEL */ Modified: head/sys/dev/ciss/cissvar.h ============================================================================== --- head/sys/dev/ciss/cissvar.h Wed Sep 16 23:17:22 2009 (r197262) +++ head/sys/dev/ciss/cissvar.h Wed Sep 16 23:27:14 2009 (r197263) @@ -103,6 +103,8 @@ struct ciss_request void *cr_data; /* data buffer */ u_int32_t cr_length; /* data length */ bus_dmamap_t cr_datamap; /* DMA map for data */ + struct ciss_command *cr_cc; + uint32_t cr_ccphys; int cr_tag; int cr_flags; #define CISS_REQ_MAPPED (1<<0) /* data mapped */ @@ -131,18 +133,16 @@ struct ciss_request * scatter-gather list, and we also want to avoid having commands * cross page boundaries. * - * Note that 512 bytes yields 28 scatter/gather entries, or the - * ability to map (26 * PAGE_SIZE) + 2 bytes of data. On x86, this is - * 104kB. 256 bytes would only yield 12 entries, giving a mere 40kB, - * too small. + * The size of the ciss_command is 52 bytes. 65 s/g elements are reserved + * to allow a max i/o size of 256k. This gives a total command size of + * 1120 bytes, including the 32 byte alignment padding. Modern controllers + * seem to saturate nicely at this value. */ -#define CISS_COMMAND_ALLOC_SIZE 512 /* XXX tune to get sensible s/g list length */ -#define CISS_COMMAND_SG_LENGTH ((CISS_COMMAND_ALLOC_SIZE - sizeof(struct ciss_command)) \ - / sizeof(struct ciss_sg_entry)) - -/* XXX Prep for increasing max i/o */ -#define CISS_MAX_SG_ELEMENTS 17 +#define CISS_MAX_SG_ELEMENTS 65 +#define CISS_COMMAND_ALIGN 32 +#define CISS_COMMAND_SG_LENGTH (sizeof(struct ciss_sg_entry) * CISS_MAX_SG_ELEMENTS) +#define CISS_COMMAND_ALLOC_SIZE (roundup2(sizeof(struct ciss_command) + CISS_COMMAND_SG_LENGTH, CISS_COMMAND_ALIGN)) /* * Per-logical-drive data. @@ -259,20 +259,6 @@ struct ciss_softc struct ciss_qstat ciss_qstat[CISSQ_COUNT]; /* queue statistics */ }; -/* - * Given a request tag, find the corresponding command in virtual or - * physical space. - * - * The arithmetic here is due to the allocation of ciss_command structures - * inside CISS_COMMAND_ALLOC_SIZE blocks. See the comment at the definition - * of CISS_COMMAND_ALLOC_SIZE above. - */ -#define CISS_FIND_COMMAND(cr) \ - (struct ciss_command *)((u_int8_t *)(cr)->cr_sc->ciss_command + \ - ((cr)->cr_tag * CISS_COMMAND_ALLOC_SIZE)) -#define CISS_FIND_COMMANDPHYS(cr) ((cr)->cr_sc->ciss_command_phys + \ - ((cr)->cr_tag * CISS_COMMAND_ALLOC_SIZE)) - /************************************************************************ * Debugging/diagnostic output. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200909162327.n8GNREaC038896>