diff options
author | scottl <scottl@FreeBSD.org> | 2007-10-09 17:43:57 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2007-10-09 17:43:57 +0000 |
commit | 14e26607a4e9b3c0e753e6147f5c694a3852681a (patch) | |
tree | 0a6f47e0b56078f5f11728ccdc3d57a67da1375f /sys/dev/twa | |
parent | f415c5c6969c1dce8c2f39f697a61c2efe489fea (diff) | |
download | FreeBSD-src-14e26607a4e9b3c0e753e6147f5c694a3852681a.zip FreeBSD-src-14e26607a4e9b3c0e753e6147f5c694a3852681a.tar.gz |
Update to version 3.70.03.007 from the vendor. This adds support for new
SAS-enabled cards. It also makes the driver MPSAFE, eliminating some
problems that resulted from CAM becoming MPSAFE. Many thanks to 3Ware/AMCC
for continuing to support FreeBSD.
Submitted by: Manjunath Ranganathaiah
Approved by: re
Diffstat (limited to 'sys/dev/twa')
-rw-r--r-- | sys/dev/twa/tw_cl_init.c | 8 | ||||
-rw-r--r-- | sys/dev/twa/tw_cl_intr.c | 6 | ||||
-rw-r--r-- | sys/dev/twa/tw_cl_io.c | 15 | ||||
-rw-r--r-- | sys/dev/twa/tw_cl_misc.c | 12 | ||||
-rw-r--r-- | sys/dev/twa/tw_cl_share.h | 2 | ||||
-rw-r--r-- | sys/dev/twa/tw_osl.h | 5 | ||||
-rw-r--r-- | sys/dev/twa/tw_osl_cam.c | 88 | ||||
-rw-r--r-- | sys/dev/twa/tw_osl_freebsd.c | 14 | ||||
-rw-r--r-- | sys/dev/twa/tw_osl_share.h | 2 |
9 files changed, 89 insertions, 63 deletions
diff --git a/sys/dev/twa/tw_cl_init.c b/sys/dev/twa/tw_cl_init.c index c7ac898..52864b2 100644 --- a/sys/dev/twa/tw_cl_init.c +++ b/sys/dev/twa/tw_cl_init.c @@ -32,6 +32,7 @@ * * Author: Vinod Kashyap * Modifications by: Adam Radford + * Modifications by: Manjunath Ranganathaiah */ @@ -65,7 +66,8 @@ tw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id) if ((vendor_id == TW_CL_VENDOR_ID) && ((device_id == TW_CL_DEVICE_ID_9K) || (device_id == TW_CL_DEVICE_ID_9K_X) || - (device_id == TW_CL_DEVICE_ID_9K_E))) + (device_id == TW_CL_DEVICE_ID_9K_E) || + (device_id == TW_CL_DEVICE_ID_9K_SA))) return(TW_CL_TRUE); return(TW_CL_FALSE); } @@ -116,6 +118,7 @@ tw_cl_get_pci_bar_info(TW_INT32 device_id, TW_INT32 bar_type, case TW_CL_DEVICE_ID_9K_X: case TW_CL_DEVICE_ID_9K_E: + case TW_CL_DEVICE_ID_9K_SA: switch(bar_type) { case TW_CL_BAR_TYPE_IO: *bar_num = 2; @@ -332,7 +335,8 @@ tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags, if ((ctlr->flags & TW_CL_64BIT_ADDRESSES) && ((ctlr->device_id == TW_CL_DEVICE_ID_9K) || (ctlr->device_id == TW_CL_DEVICE_ID_9K_X) || - (ctlr->device_id == TW_CL_DEVICE_ID_9K_E))) { + (ctlr->device_id == TW_CL_DEVICE_ID_9K_E) || + (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA))) { ctlr->state |= TW_CLI_CTLR_STATE_G66_WORKAROUND_NEEDED; ctlr->intr_lock = ctlr->io_lock; } else { diff --git a/sys/dev/twa/tw_cl_intr.c b/sys/dev/twa/tw_cl_intr.c index 864af35..44b4c14 100644 --- a/sys/dev/twa/tw_cl_intr.c +++ b/sys/dev/twa/tw_cl_intr.c @@ -32,6 +32,7 @@ * * Author: Vinod Kashyap * Modifications by: Adam Radford + * Modifications by: Manjunath Ranganathaiah */ @@ -74,6 +75,11 @@ tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle) if (ctlr == NULL) goto out; + /* If we get an interrupt while resetting, it is a shared + one for another device, so just bail */ + if (ctlr->state & TW_CLI_CTLR_STATE_RESET_IN_PROGRESS) + goto out; + /* * Synchronize access between writes to command and control registers * in 64-bit environments, on G66. diff --git a/sys/dev/twa/tw_cl_io.c b/sys/dev/twa/tw_cl_io.c index 49ffbe3..162b1ea 100644 --- a/sys/dev/twa/tw_cl_io.c +++ b/sys/dev/twa/tw_cl_io.c @@ -32,6 +32,7 @@ * * Author: Vinod Kashyap * Modifications by: Adam Radford + * Modifications by: Manjunath Ranganathaiah */ @@ -178,7 +179,8 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req) tw_osl_get_lock(ctlr_handle, ctlr->io_lock); /* For 9650SE first write low 4 bytes */ - if (ctlr->device_id == TW_CL_DEVICE_ID_9K_E) + if ((ctlr->device_id == TW_CL_DEVICE_ID_9K_E) || + (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA)) tw_osl_write_reg(ctlr_handle, TWA_COMMAND_QUEUE_OFFSET_LOW, (TW_UINT32)(req->cmd_pkt_phys + sizeof(struct tw_cl_command_header)), 4); @@ -220,7 +222,8 @@ tw_cli_submit_cmd(struct tw_cli_req_context *req) req->state = TW_CLI_REQ_STATE_BUSY; tw_cli_req_q_insert_tail(req, TW_CLI_BUSY_Q); - if (ctlr->device_id == TW_CL_DEVICE_ID_9K_E) { + if ((ctlr->device_id == TW_CL_DEVICE_ID_9K_E) || + (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA)) { /* Now write the high 4 bytes */ tw_osl_write_reg(ctlr_handle, TWA_COMMAND_QUEUE_OFFSET_HIGH, @@ -352,7 +355,10 @@ tw_cl_fw_passthru(struct tw_cl_ctlr_handle *ctlr_handle, (TW_UINT8)(TW_CL_SWAP16(req->request_id)); if ((sgl_offset = GET_SGL_OFF(cmd_7k->generic.sgl_off__opcode))) { - sgl = (((TW_UINT32 *)cmd_7k) + sgl_offset); + if (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA) + sgl = (((TW_UINT32 *)cmd_7k) + cmd_7k->generic.size); + else + sgl = (((TW_UINT32 *)cmd_7k) + sgl_offset); cmd_7k->generic.size += pt_req->sgl_entries * ((ctlr->flags & TW_CL_64BIT_ADDRESSES) ? 3 : 2); } @@ -1173,7 +1179,8 @@ tw_cli_soft_reset(struct tw_cli_ctlr_context *ctlr) TW_CLI_SOFT_RESET(ctlr_handle); if ((ctlr->device_id == TW_CL_DEVICE_ID_9K_X) || - (ctlr->device_id == TW_CL_DEVICE_ID_9K_E)) { + (ctlr->device_id == TW_CL_DEVICE_ID_9K_E) || + (ctlr->device_id == TW_CL_DEVICE_ID_9K_SA)) { /* * There's a hardware bug in the G133 ASIC, which can lead to * PCI parity errors and hangs, if the host accesses any diff --git a/sys/dev/twa/tw_cl_misc.c b/sys/dev/twa/tw_cl_misc.c index 5948b1d..1ee8120 100644 --- a/sys/dev/twa/tw_cl_misc.c +++ b/sys/dev/twa/tw_cl_misc.c @@ -32,6 +32,7 @@ * * Author: Vinod Kashyap * Modifications by: Adam Radford + * Modifications by: Manjunath Ranganathaiah */ @@ -760,6 +761,12 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg) TW_INT8 desc[200]; tw_osl_memzero(desc, 200); + + /* Skip queue error msgs during 9650SE/9690SA reset */ + if (((ctlr->device_id != TW_CL_DEVICE_ID_9K_E) && + (ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) || + ((ctlr->state & TW_CLI_CTLR_STATE_RESET_IN_PROGRESS) == 0) || + ((status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) == 0)) tw_cl_create_event(ctlr_handle, TW_CL_TRUE, TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT, 0x1302, 0x1, TW_CL_SEVERITY_ERROR_STRING, @@ -809,7 +816,10 @@ tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg) } if (status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) { - if (ctlr->device_id != TW_CL_DEVICE_ID_9K_E) + /* Skip queue error msgs during 9650SE/9690SA reset */ + if (((ctlr->device_id != TW_CL_DEVICE_ID_9K_E) && + (ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) || + ((ctlr->state & TW_CLI_CTLR_STATE_RESET_IN_PROGRESS) == 0)) tw_cl_create_event(ctlr_handle, TW_CL_TRUE, TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT, 0x1305, 0x1, TW_CL_SEVERITY_ERROR_STRING, diff --git a/sys/dev/twa/tw_cl_share.h b/sys/dev/twa/tw_cl_share.h index bb9daa4..265ff77 100644 --- a/sys/dev/twa/tw_cl_share.h +++ b/sys/dev/twa/tw_cl_share.h @@ -32,6 +32,7 @@ * * Author: Vinod Kashyap * Modifications by: Adam Radford + * Modifications by: Manjunath Ranganathaiah */ @@ -54,6 +55,7 @@ #define TW_CL_DEVICE_ID_9K 0x1002 /* 9000 PCI series device id */ #define TW_CL_DEVICE_ID_9K_X 0x1003 /* 9000 PCI-X series device id */ #define TW_CL_DEVICE_ID_9K_E 0x1004 /* 9000 PCIe series device id */ +#define TW_CL_DEVICE_ID_9K_SA 0x1005 /* 9000 PCIe SAS series device id */ #define TW_CL_BAR_TYPE_IO 1 /* I/O base address */ #define TW_CL_BAR_TYPE_MEM 2 /* memory base address */ diff --git a/sys/dev/twa/tw_osl.h b/sys/dev/twa/tw_osl.h index 7c26828..5718311 100644 --- a/sys/dev/twa/tw_osl.h +++ b/sys/dev/twa/tw_osl.h @@ -32,6 +32,7 @@ * * Author: Vinod Kashyap * Modifications by: Adam Radford + * Modifications by: Manjunath Ranganathaiah */ @@ -52,7 +53,7 @@ #define TW_OSLI_MAX_NUM_IOS TW_CL_MAX_SIMULTANEOUS_REQUESTS #define TW_OSLI_MAX_NUM_AENS 0x100 -//#define TW_OSLI_DEFERRED_INTR_USED +#define TW_OSLI_DEFERRED_INTR_USED /* Possible values of req->state. */ #define TW_OSLI_REQ_STATE_INIT 0x0 /* being initialized */ @@ -143,6 +144,8 @@ struct twa_softc { struct mtx *io_lock;/* ptr to general purpose lock */ struct mtx q_lock_handle; /* queue manipulation lock */ struct mtx *q_lock;/* ptr to queue manipulation lock */ + struct mtx sim_lock_handle;/* sim lock shared with cam */ + struct mtx *sim_lock;/* ptr to sim lock */ #ifdef TW_OSL_DEBUG struct tw_osli_q_stats q_stats[TW_OSLI_Q_COUNT];/* queue statistics */ diff --git a/sys/dev/twa/tw_osl_cam.c b/sys/dev/twa/tw_osl_cam.c index aaa1d51..b7a085f 100644 --- a/sys/dev/twa/tw_osl_cam.c +++ b/sys/dev/twa/tw_osl_cam.c @@ -32,6 +32,7 @@ * * Author: Vinod Kashyap * Modifications by: Adam Radford + * Modifications by: Manjunath Ranganathaiah */ @@ -54,8 +55,6 @@ static TW_VOID twa_action(struct cam_sim *sim, union ccb *ccb); static TW_VOID twa_poll(struct cam_sim *sim); -static TW_VOID twa_async(TW_VOID *callback_arg, TW_UINT32 code, - struct cam_path *path, TW_VOID *arg); static TW_VOID twa_timeout(TW_VOID *arg); static TW_VOID twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb); @@ -77,7 +76,6 @@ TW_INT32 tw_osli_cam_attach(struct twa_softc *sc) { struct cam_devq *devq; - struct ccb_setasync csa; TW_INT32 error; tw_osli_dbg_dprintf(3, sc, "entered"); @@ -103,7 +101,7 @@ tw_osli_cam_attach(struct twa_softc *sc) */ tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc"); sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc, - device_get_unit(sc->bus_dev), &Giant, + device_get_unit(sc->bus_dev), sc->sim_lock, TW_OSLI_MAX_NUM_IOS - 1, 1, devq); if (sc->sim == NULL) { cam_simq_free(devq); @@ -120,7 +118,7 @@ tw_osli_cam_attach(struct twa_softc *sc) * Register the bus. */ tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register"); - mtx_lock(&Giant); + mtx_lock(sc->sim_lock); if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) { cam_sim_free(sc->sim, TRUE); sc->sim = NULL; /* so cam_detach will not try to free it */ @@ -130,7 +128,7 @@ tw_osli_cam_attach(struct twa_softc *sc) 0x2102, "Failed to register the bus", ENXIO); - mtx_unlock(&Giant); + mtx_unlock(sc->sim_lock); return(ENXIO); } @@ -148,18 +146,12 @@ tw_osli_cam_attach(struct twa_softc *sc) 0x2103, "Failed to create path", ENXIO); - mtx_unlock(&Giant); + mtx_unlock(sc->sim_lock); return(ENXIO); } tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb"); - xpt_setup_ccb(&csa.ccb_h, sc->path, 5); - csa.ccb_h.func_code = XPT_SASYNC_CB; - csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE; - csa.callback = twa_async; - csa.callback_arg = sc; - xpt_action((union ccb *)&csa); - mtx_unlock(&Giant); + mtx_unlock(sc->sim_lock); tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan"); /* @@ -193,7 +185,16 @@ tw_osli_cam_detach(struct twa_softc *sc) { tw_osli_dbg_dprintf(3, sc, "entered"); - mtx_lock(&Giant); +#ifdef TW_OSLI_DEFERRED_INTR_USED + /* - drain the taskqueue + Ctrl is already went down so, no more enqueuetask will + happen . Don't hold any locks, that task might need. + */ + + taskqueue_drain(taskqueue_fast, &(sc->deferred_intr_callback)); +#endif + mtx_lock(sc->sim_lock); + if (sc->path) xpt_free_path(sc->path); if (sc->sim) { @@ -201,7 +202,8 @@ tw_osli_cam_detach(struct twa_softc *sc) /* Passing TRUE to cam_sim_free will free the devq as well. */ cam_sim_free(sc->sim, TRUE); } - mtx_unlock(&Giant); + /* It's ok have 1 hold count while destroying the mutex */ + mtx_destroy(sc->sim_lock); } @@ -395,6 +397,7 @@ twa_action(struct cam_sim *sim, union ccb *ccb) "Received Reset Bus request from CAM", " "); + mtx_unlock(sc->sim_lock); if (tw_cl_reset_ctlr(&sc->ctlr_handle)) { tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE, TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, @@ -406,6 +409,7 @@ twa_action(struct cam_sim *sim, union ccb *ccb) else ccb_h->status = CAM_REQ_CMP; + mtx_lock(sc->sim_lock); xpt_done(ccb); break; @@ -521,33 +525,6 @@ twa_poll(struct cam_sim *sim) /* - * Function name: twa_async - * Description: Driver entry point for CAM to notify driver of special - * events. We don't use this for now. - * - * Input: callback_arg -- ptr to per ctlr structure - * code -- code associated with the event - * path -- cam path - * arg -- - * Output: None - * Return value: 0 -- success - * non-zero-- failure - */ -TW_VOID -twa_async(TW_VOID *callback_arg, TW_UINT32 code, - struct cam_path *path, TW_VOID *arg) -{ -#ifdef TW_OSL_DEBUG - struct twa_softc *sc = (struct twa_softc *)callback_arg; -#endif /* TW_OSL_DEBUG */ - - tw_osli_dbg_dprintf(3, sc, "sc = %p, code = %x, path = %p, arg = %p", - sc, code, path, arg); -} - - - -/* * Function name: twa_timeout * Description: Driver entry point for being alerted on a request * timing out. @@ -595,20 +572,26 @@ tw_osli_request_bus_scan(struct twa_softc *sc) if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL) return(ENOMEM); bzero(ccb, sizeof(union ccb)); - mtx_lock(&Giant); + mtx_lock(sc->sim_lock); if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { free(ccb, M_TEMP); - mtx_unlock(&Giant); + mtx_unlock(sc->sim_lock); return(EIO); } + /* Release simq at the end of a reset */ + if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) { + xpt_release_simq(sc->sim, 1); + sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN; + } + xpt_setup_ccb(&ccb->ccb_h, path, 5); ccb->ccb_h.func_code = XPT_SCAN_BUS; ccb->ccb_h.cbfcnp = twa_bus_scan_cb; ccb->crcn.flags = CAM_FLAG_NONE; xpt_action(ccb); - mtx_unlock(&Giant); + mtx_unlock(sc->sim_lock); return(0); } @@ -673,10 +656,13 @@ tw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb) TW_VOID tw_osli_disallow_new_requests(struct twa_softc *sc) { - mtx_lock(&Giant); - xpt_freeze_simq(sc->sim, 1); - mtx_unlock(&Giant); - sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN; + /* Don't double freeze if already frozen */ + if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) == 0) { + mtx_lock(sc->sim_lock); + xpt_freeze_simq(sc->sim, 1); + mtx_unlock(sc->sim_lock); + sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN; + } } @@ -813,7 +799,9 @@ tw_osl_complete_io(struct tw_cl_req_handle *req_handle) } ccb->ccb_h.status &= ~CAM_SIM_QUEUED; + mtx_lock(sc->sim_lock); xpt_done(ccb); + mtx_unlock(sc->sim_lock); if (! req->error_code) /* twa_action will free the request otherwise */ tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q); diff --git a/sys/dev/twa/tw_osl_freebsd.c b/sys/dev/twa/tw_osl_freebsd.c index 98ac6cc..4b098ae 100644 --- a/sys/dev/twa/tw_osl_freebsd.c +++ b/sys/dev/twa/tw_osl_freebsd.c @@ -34,6 +34,7 @@ * * Author: Vinod Kashyap * Modifications by: Adam Radford + * Modifications by: Manjunath Ranganathaiah */ @@ -281,6 +282,8 @@ twa_attach(device_t dev) mtx_init(sc->io_lock, "tw_osl_io_lock", NULL, MTX_SPIN); sc->q_lock = &(sc->q_lock_handle); mtx_init(sc->q_lock, "tw_osl_q_lock", NULL, MTX_SPIN); + sc->sim_lock = &(sc->sim_lock_handle); + mtx_init(sc->sim_lock, "tw_osl_sim_lock", NULL, MTX_DEF | MTX_RECURSE); sysctl_ctx_init(&sc->sysctl_ctxt); sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctxt, @@ -359,10 +362,11 @@ twa_attach(device_t dev) return(ENXIO); } if ((error = bus_setup_intr(sc->bus_dev, sc->irq_res, - INTR_TYPE_CAM, #ifdef TW_OSLI_DEFERRED_INTR_USED + INTR_TYPE_CAM | INTR_FAST, twa_pci_intr_fast, NULL, #else + INTR_TYPE_CAM | INTR_MPSAFE, NULL, twa_pci_intr, #endif sc, &sc->intr_handle))) { @@ -877,7 +881,8 @@ twa_pci_intr_fast(TW_VOID *arg) tw_osli_dbg_dprintf(10, sc, "entered"); if (tw_cl_interrupt(&(sc->ctlr_handle))) { - tw_cl_deferred_interrupt(&(sc->ctlr_handle)); + taskqueue_enqueue_fast(taskqueue_fast, + &(sc->deferred_intr_callback)); return(FILTER_HANDLED); } return(FILTER_STRAY); @@ -1051,10 +1056,11 @@ tw_osli_fw_passthru(struct twa_softc *sc, TW_INT8 *buf) /* * Don't touch req after a reset. It (and any * associated data) will already have been - * freed by the callback. Just return. + * unmapped by the callback. */ user_buf->driver_pkt.os_status = error; - return(ETIMEDOUT); + error = ETIMEDOUT; + goto fw_passthru_err; } /* * Either the request got completed, or we were woken up by a diff --git a/sys/dev/twa/tw_osl_share.h b/sys/dev/twa/tw_osl_share.h index 0cfc90d..08276d0 100644 --- a/sys/dev/twa/tw_osl_share.h +++ b/sys/dev/twa/tw_osl_share.h @@ -75,7 +75,7 @@ #define TW_OSL_ENCLOSURE_SUPPORT #endif -#define TW_OSL_DRIVER_VERSION_STRING "3.70.03.007" +#define TW_OSL_DRIVER_VERSION_STRING "3.70.05.001" #define TW_OSL_CAN_SLEEP |