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
This commit is contained in:
Scott Long 2007-10-09 17:43:57 +00:00
parent 1e9f27406f
commit a4820cd2f6
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=172496
9 changed files with 89 additions and 63 deletions

View File

@ -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 {

View File

@ -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.

View File

@ -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

View File

@ -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,

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
@ -520,33 +524,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
@ -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);

View File

@ -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

View File

@ -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