From 2e61752fe6b66cca380e3c7c49ab9567587a16c2 Mon Sep 17 00:00:00 2001 From: Matt Jacob Date: Thu, 5 Oct 2006 16:00:08 +0000 Subject: MFC the current state of mpt. --- sys/dev/mpt/mpt.c | 85 ++++++++-- sys/dev/mpt/mpt.h | 36 +++- sys/dev/mpt/mpt_cam.c | 424 +++++++++++++++++++++++++++++++++++++++--------- sys/dev/mpt/mpt_debug.c | 15 ++ sys/dev/mpt/mpt_pci.c | 57 +++++-- sys/dev/mpt/mpt_raid.c | 18 +- sys/dev/mpt/mpt_raid.h | 2 + 7 files changed, 518 insertions(+), 119 deletions(-) (limited to 'sys/dev') diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c index 2c289d3a76f4..0e8376142924 100644 --- a/sys/dev/mpt/mpt.c +++ b/sys/dev/mpt/mpt.c @@ -116,7 +116,7 @@ static int maxwait_ack = 0; static int maxwait_int = 0; static int maxwait_state = 0; -TAILQ_HEAD(, mpt_softc) mpt_tailq = TAILQ_HEAD_INITIALIZER(mpt_tailq); +static TAILQ_HEAD(, mpt_softc) mpt_tailq = TAILQ_HEAD_INITIALIZER(mpt_tailq); mpt_reply_handler_t *mpt_reply_handlers[MPT_NUM_REPLY_HANDLERS]; static mpt_reply_handler_t mpt_default_reply_handler; @@ -186,6 +186,7 @@ static mpt_load_handler_t mpt_stdload; static mpt_probe_handler_t mpt_stdprobe; static mpt_attach_handler_t mpt_stdattach; static mpt_enable_handler_t mpt_stdenable; +static mpt_ready_handler_t mpt_stdready; static mpt_event_handler_t mpt_stdevent; static mpt_reset_handler_t mpt_stdreset; static mpt_shutdown_handler_t mpt_stdshutdown; @@ -197,6 +198,7 @@ static struct mpt_personality mpt_default_personality = .probe = mpt_stdprobe, .attach = mpt_stdattach, .enable = mpt_stdenable, + .ready = mpt_stdready, .event = mpt_stdevent, .reset = mpt_stdreset, .shutdown = mpt_stdshutdown, @@ -238,7 +240,6 @@ MODULE_VERSION(mpt_core, 1); #define MPT_PERS_ATTACHED(pers, mpt) ((mpt)->mpt_pers_mask & (0x1 << pers->id)) - int mpt_modevent(module_t mod, int type, void *data) { @@ -326,6 +327,12 @@ mpt_stdenable(struct mpt_softc *mpt) return (0); } +void +mpt_stdready(struct mpt_softc *mpt) +{ +} + + int mpt_stdevent(struct mpt_softc *mpt, request_t *req, MSG_EVENT_NOTIFY_REPLY *msg) { @@ -356,6 +363,25 @@ mpt_stdunload(struct mpt_personality *pers) return (0); } +/* + * Post driver attachment, we may want to perform some global actions. + * Here is the hook to do so. + */ + +static void +mpt_postattach(void *unused) +{ + struct mpt_softc *mpt; + struct mpt_personality *pers; + + TAILQ_FOREACH(mpt, &mpt_tailq, links) { + MPT_PERS_FOREACH(mpt, pers) + pers->ready(mpt); + } +} +SYSINIT(mptdev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, mpt_postattach, NULL); + + /******************************* Bus DMA Support ******************************/ void mpt_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error) @@ -483,6 +509,11 @@ mpt_config_reply_handler(struct mpt_softc *mpt, request_t *req, TAILQ_REMOVE(&mpt->request_pending_list, req, links); if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) { wakeup(req); + } else if ((req->state & REQ_STATE_TIMEDOUT) != 0) { + /* + * Whew- we can free this request (late completion) + */ + mpt_free_request(mpt, req); } } @@ -1282,6 +1313,7 @@ mpt_wait_req(struct mpt_softc *mpt, request_t *req, } if (time_ms && timeout <= 0) { MSG_REQUEST_HEADER *msg_hdr = req->req_vbuf; + req->state |= REQ_STATE_TIMEDOUT; mpt_prt(mpt, "mpt_wait_req(%x) timed out\n", msg_hdr->Function); return (ETIMEDOUT); } @@ -1560,7 +1592,12 @@ mpt_read_cfg_header(struct mpt_softc *mpt, int PageType, int PageNumber, PageType, PageAddress, /*addr*/0, /*len*/0, sleep_ok, timeout_ms); if (error != 0) { - mpt_free_request(mpt, req); + /* + * Leave the request. Without resetting the chip, it's + * still owned by it and we'll just get into trouble + * freeing it now. Mark it as abandoned so that if it + * shows up later it can be freed. + */ mpt_prt(mpt, "read_cfg_header timed out\n"); return (ETIMEDOUT); } @@ -1640,13 +1677,26 @@ mpt_write_cfg_page(struct mpt_softc *mpt, int Action, uint32_t PageAddress, hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); return (-1); } - hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK, + +#if 0 + /* + * We shouldn't mask off other bits here. + */ + hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK; +#endif req = mpt_get_request(mpt, sleep_ok); if (req == NULL) return (-1); - memcpy(((caddr_t)req->req_vbuf)+MPT_RQSL(mpt), hdr, len); + memcpy(((caddr_t)req->req_vbuf) + MPT_RQSL(mpt), hdr, len); + + /* + * There isn't any point in restoring stripped out attributes + * if you then mask them going down to issue the request. + */ + +#if 0 /* Restore stripped out attributes */ hdr->PageType |= hdr_attr; @@ -1655,6 +1705,13 @@ mpt_write_cfg_page(struct mpt_softc *mpt, int Action, uint32_t PageAddress, hdr->PageType & MPI_CONFIG_PAGETYPE_MASK, PageAddress, req->req_pbuf + MPT_RQSL(mpt), len, sleep_ok, timeout_ms); +#else + error = mpt_issue_cfg_req(mpt, req, Action, hdr->PageVersion, + hdr->PageLength, hdr->PageNumber, + hdr->PageType, PageAddress, + req->req_pbuf + MPT_RQSL(mpt), + len, sleep_ok, timeout_ms); +#endif if (error != 0) { mpt_prt(mpt, "mpt_write_cfg_page timed out\n"); return (-1); @@ -1936,6 +1993,9 @@ mpt_sysctl_attach(struct mpt_softc *mpt) SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "debug", CTLFLAG_RW, &mpt->verbose, 0, "Debugging/Verbose level"); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "role", CTLFLAG_RD, &mpt->role, 0, + "HBA role"); #endif } @@ -1946,6 +2006,7 @@ mpt_attach(struct mpt_softc *mpt) int i; int error; + TAILQ_INSERT_TAIL(&mpt_tailq, mpt, links); for (i = 0; i < MPT_MAX_PERSONALITIES; i++) { pers = mpt_personalities[i]; if (pers == NULL) { @@ -2004,7 +2065,7 @@ mpt_detach(struct mpt_softc *mpt) mpt->mpt_pers_mask &= ~(0x1 << pers->id); pers->use_count--; } - + TAILQ_REMOVE(&mpt_tailq, mpt, links); return (0); } @@ -2454,9 +2515,11 @@ mpt_configure_ioc(struct mpt_softc *mpt) mpt->mpt_max_devices = pfp.MaxDevices; /* - * Set our expected role with what this port supports. + * Set our role with what this port supports. + * + * Note this might be changed later in different modules + * if this is different from what is wanted. */ - mpt->role = MPT_ROLE_NONE; if (pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { mpt->role |= MPT_ROLE_INITIATOR; @@ -2464,12 +2527,6 @@ mpt_configure_ioc(struct mpt_softc *mpt) if (pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { mpt->role |= MPT_ROLE_TARGET; } - if (mpt->role == MPT_ROLE_NONE) { - mpt_prt(mpt, "port does not support either target or " - "initiator role\n"); - return (ENXIO); - } - if (mpt_enable_ioc(mpt, 0) != MPT_OK) { mpt_prt(mpt, "unable to initialize IOC\n"); return (ENXIO); diff --git a/sys/dev/mpt/mpt.h b/sys/dev/mpt/mpt.h index bfc134949d43..f27c397b58a0 100644 --- a/sys/dev/mpt/mpt.h +++ b/sys/dev/mpt/mpt.h @@ -177,6 +177,7 @@ typedef int mpt_load_handler_t(struct mpt_personality *); typedef int mpt_probe_handler_t(struct mpt_softc *); typedef int mpt_attach_handler_t(struct mpt_softc *); typedef int mpt_enable_handler_t(struct mpt_softc *); +typedef void mpt_ready_handler_t(struct mpt_softc *); typedef int mpt_event_handler_t(struct mpt_softc *, request_t *, MSG_EVENT_NOTIFY_REPLY *); typedef void mpt_reset_handler_t(struct mpt_softc *, int /*type*/); @@ -195,6 +196,7 @@ struct mpt_personality mpt_probe_handler_t *probe; /* configure personailty */ mpt_attach_handler_t *attach; /* initialize device instance */ mpt_enable_handler_t *enable; /* enable device */ + mpt_ready_handler_t *ready; /* final open for business */ mpt_event_handler_t *event; /* Handle MPI event. */ mpt_reset_handler_t *reset; /* Re-init after reset. */ mpt_shutdown_handler_t *shutdown; /* Shutdown instance. */ @@ -317,7 +319,9 @@ typedef struct { uint32_t bytes_xfered; /* current relative offset */ union ccb *ccb; /* pointer to currently active ccb */ request_t *req; /* pointer to currently active assist request */ - int nxfers; + uint32_t + is_local : 1, + nxfers : 31; uint32_t tag_id; enum { TGT_STATE_NIL, @@ -490,13 +494,12 @@ struct mpt_softc { int mpt_locksetup; #endif uint32_t mpt_pers_mask; - uint32_t : 8, + uint32_t unit : 8, - : 1, + : 3, twildcard : 1, tenabled : 1, - role : 2, /* none, ini, target, both */ - : 1, + do_cfg_role : 1, raid_enabled : 1, raid_mwce_set : 1, getreqwaiter : 1, @@ -508,6 +511,9 @@ struct mpt_softc { is_sas : 1, is_fc : 1; + u_int cfg_role; + u_int role; /* role: none, ini, target, both */ + u_int verbose; /* @@ -556,6 +562,20 @@ struct mpt_softc { #define mpt_fcport_speed cfg.fc._port_speed } fc; } cfg; +#if __FreeBSD_version >= 500000 + /* + * Device config information stored up for sysctl to access + */ + union { + struct { + unsigned int initiator_id; + } spi; + struct { + char wwnn[19]; + char wwpn[19]; + } fc; + } scinfo; +#endif /* Controller Info for RAID information */ CONFIG_PAGE_IOC_2 * ioc_page2; @@ -650,7 +670,7 @@ struct mpt_softc { * forgets to point to it exactly and we index off of trt with * CAM_LUN_WILDCARD. */ - tgt_resource_t trt_wildcard; /* wildcard luns */ + tgt_resource_t trt_wildcard; /* wildcard luns */ tgt_resource_t trt[MPT_MAX_LUNS]; uint16_t tgt_cmds_allocated; uint16_t els_cmds_allocated; /* FC only */ @@ -942,6 +962,7 @@ int mpt_decode_value(mpt_decode_entry_t *table, u_int num_entries, const char *name, u_int value, u_int *cur_column, u_int wrap_point); +void mpt_dump_data(struct mpt_softc *, const char *, void *, int); void mpt_dump_request(struct mpt_softc *, request_t *); enum { @@ -1100,6 +1121,9 @@ mpt_req_not_spcl(struct mpt_softc *mpt, request_t *req, const char *s, int line) } #endif +/* + * Task Management Types, purely for internal consumption + */ typedef enum { MPT_ABORT_TASK_SET=1234, MPT_CLEAR_TASK_SET, diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c index 1a53679683ab..8beaa408fa68 100644 --- a/sys/dev/mpt/mpt_cam.c +++ b/sys/dev/mpt/mpt_cam.c @@ -104,7 +104,9 @@ __FBSDID("$FreeBSD$"); #include "dev/mpt/mpilib/mpi_init.h" #include "dev/mpt/mpilib/mpi_targ.h" #include "dev/mpt/mpilib/mpi_fc.h" - +#if __FreeBSD_version >= 500000 +#include +#endif #include #include @@ -138,8 +140,6 @@ static void mpt_fc_post_els(struct mpt_softc *mpt, request_t *, int); static void mpt_post_target_command(struct mpt_softc *, request_t *, int); static int mpt_add_els_buffers(struct mpt_softc *mpt); static int mpt_add_target_commands(struct mpt_softc *mpt); -static void mpt_free_els_buffers(struct mpt_softc *mpt); -static void mpt_free_target_commands(struct mpt_softc *mpt); static int mpt_enable_lun(struct mpt_softc *, target_id_t, lun_id_t); static int mpt_disable_lun(struct mpt_softc *, target_id_t, lun_id_t); static void mpt_target_start_io(struct mpt_softc *, union ccb *); @@ -161,6 +161,7 @@ static uint32_t fc_els_handler_id = MPT_HANDLER_ID_NONE; static mpt_probe_handler_t mpt_cam_probe; static mpt_attach_handler_t mpt_cam_attach; static mpt_enable_handler_t mpt_cam_enable; +static mpt_ready_handler_t mpt_cam_ready; static mpt_event_handler_t mpt_cam_event; static mpt_reset_handler_t mpt_cam_ioc_reset; static mpt_detach_handler_t mpt_cam_detach; @@ -171,6 +172,7 @@ static struct mpt_personality mpt_cam_personality = .probe = mpt_cam_probe, .attach = mpt_cam_attach, .enable = mpt_cam_enable, + .ready = mpt_cam_ready, .event = mpt_cam_event, .reset = mpt_cam_ioc_reset, .detach = mpt_cam_detach, @@ -181,13 +183,20 @@ DECLARE_MPT_PERSONALITY(mpt_cam, SI_ORDER_SECOND); int mpt_cam_probe(struct mpt_softc *mpt) { + int role; + /* - * Only attach to nodes that support the initiator or target - * role or have RAID physical devices that need CAM pass-thru support. + * Only attach to nodes that support the initiator or target role + * (or want to) or have RAID physical devices that need CAM pass-thru + * support. */ - if ((mpt->mpt_proto_flags & MPI_PORTFACTS_PROTOCOL_INITIATOR) != 0 - || (mpt->mpt_proto_flags & MPI_PORTFACTS_PROTOCOL_TARGET) != 0 - || (mpt->ioc_page2 != NULL && mpt->ioc_page2->MaxPhysDisks != 0)) { + if (mpt->do_cfg_role) { + role = mpt->cfg_role; + } else { + role = mpt->role; + } + if ((role & (MPT_ROLE_TARGET|MPT_ROLE_INITIATOR)) != 0 || + (mpt->ioc_page2 != NULL && mpt->ioc_page2->MaxPhysDisks != 0)) { return (0); } return (ENODEV); @@ -239,9 +248,10 @@ mpt_cam_attach(struct mpt_softc *mpt) /* * If we support target mode, we register a reply handler for it, - * but don't add resources until we actually enable target mode. + * but don't add command resources until we actually enable target + * mode. */ - if ((mpt->role & MPT_ROLE_TARGET) != 0) { + if (mpt->is_fc && (mpt->role & MPT_ROLE_TARGET) != 0) { handler.reply_handler = mpt_scsi_tgt_reply_handler; error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, &mpt->scsi_tgt_handler_id); @@ -355,6 +365,7 @@ mpt_cam_attach(struct mpt_softc *mpt) goto cleanup; } CAMLOCK_2_MPTLOCK(mpt); + mpt_lprt(mpt, MPT_PRT_DEBUG, "attached cam\n"); return (0); cleanup: @@ -426,7 +437,31 @@ mpt_read_config_info_fc(struct mpt_softc *mpt) mpt->mpt_fcport_page0.WWPN.High, mpt->mpt_fcport_page0.WWPN.Low, mpt->mpt_fcport_speed); +#if __FreeBSD_version >= 500000 + { + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(mpt->dev); + struct sysctl_oid *tree = device_get_sysctl_tree(mpt->dev); + + snprintf(mpt->scinfo.fc.wwnn, + sizeof (mpt->scinfo.fc.wwnn), "0x%08x%08x", + mpt->mpt_fcport_page0.WWNN.High, + mpt->mpt_fcport_page0.WWNN.Low); + snprintf(mpt->scinfo.fc.wwpn, + sizeof (mpt->scinfo.fc.wwpn), "0x%08x%08x", + mpt->mpt_fcport_page0.WWPN.High, + mpt->mpt_fcport_page0.WWPN.Low); + + SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "wwnn", CTLFLAG_RD, mpt->scinfo.fc.wwnn, 0, + "World Wide Node Name"); + + SYSCTL_ADD_STRING(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "wwpn", CTLFLAG_RD, mpt->scinfo.fc.wwpn, 0, + "World Wide Port Name"); + + } +#endif return (0); } @@ -436,49 +471,96 @@ mpt_read_config_info_fc(struct mpt_softc *mpt) static int mpt_set_initial_config_fc(struct mpt_softc *mpt) { -#if 0 + CONFIG_PAGE_FC_PORT_1 fc; U32 fl; int r, doit = 0; - - if ((mpt->role & MPT_ROLE_TARGET) == 0) { - return (0); - } + int role; r = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_FC_PORT, 1, 0, &fc.Header, FALSE, 5000); if (r) { + mpt_prt(mpt, "failed to read FC page 1 header\n"); return (mpt_fc_reset_link(mpt, 1)); } - r = mpt_read_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT, 0, + r = mpt_read_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_NVRAM, 0, &fc.Header, sizeof (fc), FALSE, 5000); if (r) { + mpt_prt(mpt, "failed to read FC page 1\n"); return (mpt_fc_reset_link(mpt, 1)); } - fl = le32toh(fc.Flags); - if ((fl & MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID) == 0) { - fl |= MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID; - doit = 1; + /* + * Check our flags to make sure we support the role we want. + */ + doit = 0; + role = 0; + fl = le32toh(fc.Flags);; + + if (fl & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT) { + role |= MPT_ROLE_INITIATOR; + } + if (fl & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG) { + role |= MPT_ROLE_TARGET; } - if (doit) { - const char *cc; - mpt_lprt(mpt, MPT_PRT_INFO, - "FC Port Page 1: New Flags %x \n", fl); + fl &= ~MPI_FCPORTPAGE1_FLAGS_PROT_MASK; + + if (mpt->do_cfg_role == 0) { + role = mpt->cfg_role; + } else { + mpt->do_cfg_role = 0; + } + + if (role != mpt->cfg_role) { + if (mpt->cfg_role & MPT_ROLE_INITIATOR) { + if ((role & MPT_ROLE_INITIATOR) == 0) { + mpt_prt(mpt, "adding initiator role\n"); + fl |= MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT; + doit++; + } else { + mpt_prt(mpt, "keeping initiator role\n"); + } + } else if (role & MPT_ROLE_INITIATOR) { + mpt_prt(mpt, "removing initiator role\n"); + doit++; + } + if (mpt->cfg_role & MPT_ROLE_TARGET) { + if ((role & MPT_ROLE_TARGET) == 0) { + mpt_prt(mpt, "adding target role\n"); + fl |= MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG; + doit++; + } else { + mpt_prt(mpt, "keeping target role\n"); + } + } else if (role & MPT_ROLE_TARGET) { + mpt_prt(mpt, "removing target role\n"); + doit++; + } + mpt->role = mpt->cfg_role; + } + + if (fl & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG) { + if ((fl & MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID) == 0) { + mpt_prt(mpt, "adding OXID option\n"); + fl |= MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID; + doit++; + } + } + + if (doit) { fc.Flags = htole32(fl); r = mpt_write_cfg_page(mpt, - MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT, 0, &fc.Header, + MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM, 0, &fc.Header, sizeof(fc), FALSE, 5000); if (r != 0) { - cc = "FC PORT PAGE1 UPDATE: FAILED\n"; - } else { - cc = "FC PORT PAGE1 UPDATED: SYSTEM NEEDS RESET\n"; + mpt_prt(mpt, "failed to update NVRAM with changes\n"); + return (0); } - mpt_prt(mpt, cc); + mpt_prt(mpt, "NOTE: NVRAM changes will not take " + "effect until next reboot or IOC reset\n"); } -#endif return (0); } @@ -736,6 +818,25 @@ mpt_cam_enable(struct mpt_softc *mpt) return (0); } +void +mpt_cam_ready(struct mpt_softc *mpt) +{ + /* + * If we're in target mode, hang out resources now + * so we don't cause the world to hang talking to us. + */ + if (mpt->is_fc && (mpt->role & MPT_ROLE_TARGET)) { + /* + * Try to add some target command resources + */ + MPT_LOCK(mpt); + if (mpt_add_target_commands(mpt) == FALSE) { + mpt_prt(mpt, "failed to add target commands\n"); + } + MPT_UNLOCK(mpt); + } +} + void mpt_cam_detach(struct mpt_softc *mpt) { @@ -1937,15 +2038,16 @@ static int mpt_cam_event(struct mpt_softc *mpt, request_t *req, MSG_EVENT_NOTIFY_REPLY *msg) { + switch(msg->Event & 0xFF) { case MPI_EVENT_UNIT_ATTENTION: - mpt_prt(mpt, "Bus: 0x%02x TargetID: 0x%02x\n", + mpt_prt(mpt, "UNIT ATTENTION: Bus: 0x%02x TargetID: 0x%02x\n", (msg->Data[0] >> 8) & 0xff, msg->Data[0] & 0xff); break; case MPI_EVENT_IOC_BUS_RESET: /* We generated a bus reset */ - mpt_prt(mpt, "IOC Bus Reset Port: %d\n", + mpt_prt(mpt, "IOC Generated Bus Reset Port: %d\n", (msg->Data[0] >> 8) & 0xff); xpt_async(AC_BUS_RESET, mpt->path, NULL); break; @@ -2044,13 +2146,56 @@ mpt_cam_event(struct mpt_softc *mpt, request_t *req, mpt_lprt(mpt, MPT_PRT_DEBUG, "mpt_cam_event: MPI_EVENT_EVENT_CHANGE\n"); break; + case MPI_EVENT_QUEUE_FULL: + { + struct cam_sim *sim; + struct cam_path *tmppath; + struct ccb_relsim crs; + PTR_EVENT_DATA_QUEUE_FULL pqf = + (PTR_EVENT_DATA_QUEUE_FULL) msg->Data; + lun_id_t lun_id; + + mpt_prt(mpt, "QUEUE FULL EVENT: Bus 0x%02x Target 0x%02x Depth " + "%d\n", pqf->Bus, pqf->TargetID, pqf->CurrentDepth); + if (mpt->phydisk_sim) { + sim = mpt->phydisk_sim; + } else { + sim = mpt->sim; + } + MPTLOCK_2_CAMLOCK(mpt); + for (lun_id = 0; lun_id < MPT_MAX_LUNS; lun_id++) { + if (xpt_create_path(&tmppath, NULL, cam_sim_path(sim), + pqf->TargetID, lun_id) != CAM_REQ_CMP) { + mpt_prt(mpt, "unable to create a path to send " + "XPT_REL_SIMQ"); + CAMLOCK_2_MPTLOCK(mpt); + break; + } + xpt_setup_ccb(&crs.ccb_h, tmppath, 5); + crs.ccb_h.func_code = XPT_REL_SIMQ; + crs.release_flags = RELSIM_ADJUST_OPENINGS; + crs.openings = pqf->CurrentDepth - 1; + xpt_action((union ccb *)&crs); + if (crs.ccb_h.status != CAM_REQ_CMP) { + mpt_prt(mpt, "XPT_REL_SIMQ failed\n"); + } + xpt_free_path(tmppath); + } + CAMLOCK_2_MPTLOCK(mpt); + break; + } case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: - /* - * Devices are attachin'..... - */ - mpt_prt(mpt, - "mpt_cam_event: MPI_EVENT_SAS_DEVICE_STATUS_CHANGE\n"); + { + mpt_lprt(mpt, MPT_PRT_DEBUG, + "mpt_cam_event: SAS_DEVICE_STATUS_CHANGE\n"); break; + } + case MPI_EVENT_SAS_SES: + { + mpt_lprt(mpt, MPT_PRT_DEBUG, + "mpt_cam_event: MPI_EVENT_SAS_SES\n"); + break; + } default: mpt_lprt(mpt, MPT_PRT_WARN, "mpt_cam_event: 0x%x\n", msg->Event & 0xFF); @@ -2336,14 +2481,17 @@ mpt_fc_els_reply_handler(struct mpt_softc *mpt, request_t *req, TAILQ_REMOVE(&mpt->request_pending_list, req, links); req->state &= ~REQ_STATE_QUEUED; req->state |= REQ_STATE_DONE; - if ((req->state & REQ_STATE_NEED_WAKEUP) == 0) { + if (req->state & REQ_STATE_TIMEDOUT) { + mpt_lprt(mpt, MPT_PRT_DEBUG, + "Sync Primitive Send Completed After Timeout\n"); + mpt_free_request(mpt, req); + } else if ((req->state & REQ_STATE_NEED_WAKEUP) == 0) { mpt_lprt(mpt, MPT_PRT_DEBUG, "Async Primitive Send Complete\n"); - TAILQ_REMOVE(&mpt->request_pending_list, req, links); mpt_free_request(mpt, req); } else { mpt_lprt(mpt, MPT_PRT_DEBUG, - "Sync Primitive Send Complete\n"); + "Sync Primitive Send Complete- Waking Waiter\n"); wakeup(req); } return (TRUE); @@ -3072,7 +3220,7 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) if ((mpt->role & MPT_ROLE_INITIATOR) == 0) { cpi->hba_misc |= PIM_NOINITIATOR; } - if ((mpt->role & MPT_ROLE_TARGET) != 0) { + if (mpt->is_fc && (mpt->role & MPT_ROLE_TARGET)) { cpi->target_sprt = PIT_PROCESSOR | PIT_DISCONNECT | PIT_TERM_IO; } else { @@ -3776,19 +3924,6 @@ mpt_add_target_commands(struct mpt_softc *mpt) return (i); } -static void -mpt_free_els_buffers(struct mpt_softc *mpt) -{ - mpt_prt(mpt, "fix me! need to implement mpt_free_els_buffers"); -} - -static void -mpt_free_target_commands(struct mpt_softc *mpt) -{ - mpt_prt(mpt, "fix me! need to implement mpt_free_target_commands"); -} - - static int mpt_enable_lun(struct mpt_softc *mpt, target_id_t tgt, lun_id_t lun) { @@ -3800,13 +3935,6 @@ mpt_enable_lun(struct mpt_softc *mpt, target_id_t tgt, lun_id_t lun) return (EINVAL); } if (mpt->tenabled == 0) { - /* - * Try to add some target command resources - */ - if (mpt_add_target_commands(mpt) == FALSE) { - mpt_free_els_buffers(mpt); - return (ENOMEM); - } if (mpt->is_fc) { (void) mpt_fc_reset_link(mpt, 0); } @@ -3842,8 +3970,6 @@ mpt_disable_lun(struct mpt_softc *mpt, target_id_t tgt, lun_id_t lun) } } if (i == MPT_MAX_LUNS && mpt->twildcard == 0) { - mpt_free_els_buffers(mpt); - mpt_free_target_commands(mpt); if (mpt->is_fc) { (void) mpt_fc_reset_link(mpt, 0); } @@ -3926,7 +4052,7 @@ mpt_target_start_io(struct mpt_softc *mpt, union ccb *ccb) memset(req->req_vbuf, 0, MPT_RQSL(mpt)); ta = req->req_vbuf; - if (mpt->is_sas == 0) { + if (mpt->is_sas) { PTR_MPI_TARGET_SSP_CMD_BUFFER ssp = cmd_req->req_vbuf; ta->QueueTag = ssp->InitiatorTag; @@ -4048,6 +4174,85 @@ mpt_target_start_io(struct mpt_softc *mpt, union ccb *ccb) } } +static void +mpt_scsi_tgt_local(struct mpt_softc *mpt, request_t *cmd_req, + uint32_t lun, int send, uint8_t *data, size_t length) +{ + mpt_tgt_state_t *tgt; + PTR_MSG_TARGET_ASSIST_REQUEST ta; + SGE_SIMPLE32 *se; + uint32_t flags; + uint8_t *dptr; + bus_addr_t pptr; + request_t *req; + + if (length == 0) { + mpt_scsi_tgt_status(mpt, NULL, cmd_req, 0, NULL); + return; + } + + tgt = MPT_TGT_STATE(mpt, cmd_req); + if ((req = mpt_get_request(mpt, FALSE)) == NULL) { + mpt_prt(mpt, "out of resources- dropping local response\n"); + return; + } + tgt->is_local = 1; + + + memset(req->req_vbuf, 0, MPT_RQSL(mpt)); + ta = req->req_vbuf; + + if (mpt->is_sas) { + PTR_MPI_TARGET_SSP_CMD_BUFFER ssp = cmd_req->req_vbuf; + ta->QueueTag = ssp->InitiatorTag; + } else if (mpt->is_spi) { + PTR_MPI_TARGET_SCSI_SPI_CMD_BUFFER sp = cmd_req->req_vbuf; + ta->QueueTag = sp->Tag; + } + ta->Function = MPI_FUNCTION_TARGET_ASSIST; + ta->MsgContext = htole32(req->index | mpt->scsi_tgt_handler_id); + ta->ReplyWord = htole32(tgt->reply_desc); + if (lun > 256) { + ta->LUN[0] = 0x40 | ((lun >> 8) & 0x3f); + ta->LUN[1] = lun & 0xff; + } else { + ta->LUN[1] = lun; + } + ta->RelativeOffset = 0; + ta->DataLength = length; + + dptr = req->req_vbuf; + dptr += MPT_RQSL(mpt); + pptr = req->req_pbuf; + pptr += MPT_RQSL(mpt); + memcpy(dptr, data, min(length, MPT_RQSL(mpt))); + + se = (SGE_SIMPLE32 *) &ta->SGL[0]; + memset(se, 0,sizeof (*se)); + + flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT; + if (send) { + ta->TargetAssistFlags |= TARGET_ASSIST_FLAGS_DATA_DIRECTION; + flags |= MPI_SGE_FLAGS_HOST_TO_IOC; + } + se->Address = pptr; + MPI_pSGE_SET_LENGTH(se, length); + flags |= MPI_SGE_FLAGS_LAST_ELEMENT; + flags |= MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_END_OF_BUFFER; + MPI_pSGE_SET_FLAGS(se, flags); + + tgt->ccb = NULL; + tgt->req = req; + tgt->resid = 0; + tgt->bytes_xfered = length; +#ifdef WE_TRUST_AUTO_GOOD_STATUS + tgt->state = TGT_STATE_MOVING_DATA_AND_STATUS; +#else + tgt->state = TGT_STATE_MOVING_DATA; +#endif + mpt_send_cmd(mpt, req); +} + /* * Abort queued up CCBs */ @@ -4163,7 +4368,7 @@ mpt_scsi_tgt_status(struct mpt_softc *mpt, union ccb *ccb, request_t *cmd_req, CAMLOCK_2_MPTLOCK(mpt); } else { mpt_prt(mpt, - "XXXX could not allocate status req- dropping\n"); + "could not allocate status request- dropping\n"); } return; } @@ -4355,8 +4560,9 @@ mpt_scsi_tgt_atio(struct mpt_softc *mpt, request_t *req, uint32_t reply_desc) uint8_t *cdbp; /* - * First, DMA sync the received command- which is in the *request* - * phys area. + * First, DMA sync the received command- + * which is in the *request* * phys area. + * * XXX: We could optimize this for a range */ bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap, @@ -4471,14 +4677,66 @@ mpt_scsi_tgt_atio(struct mpt_softc *mpt, request_t *req, uint32_t reply_desc) mpt->trt[lun].enabled == 0) { if (mpt->twildcard) { trtp = &mpt->trt_wildcard; - } else if (fct != MPT_NIL_TMT_VALUE) { - const uint8_t sp[MPT_SENSE_SIZE] = { - 0xf0, 0, 0x5, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0x25 - }; - mpt_scsi_tgt_status(mpt, NULL, req, - SCSI_STATUS_CHECK_COND, sp); + } else if (fct == MPT_NIL_TMT_VALUE) { + /* + * In this case, we haven't got an upstream listener + * for either a specific lun or wildcard luns. We + * have to make some sensible response. For regular + * inquiry, just return some NOT HERE inquiry data. + * For VPD inquiry, report illegal field in cdb. + * For REQUEST SENSE, just return NO SENSE data. + * REPORT LUNS gets illegal command. + * All other commands get 'no such device'. + */ + + uint8_t *sp, cond, buf[MPT_SENSE_SIZE]; + + mpt_prt(mpt, "CMD 0x%x to unmanaged lun %u\n", + cdbp[0], lun); + + memset(buf, 0, MPT_SENSE_SIZE); + cond = SCSI_STATUS_CHECK_COND; + buf[0] = 0xf0; + buf[2] = 0x5; + buf[7] = 0x8; + sp = buf; + tgt->tag_id = MPT_MAKE_TAGID(mpt, req, ioindex); + + switch (cdbp[0]) { + case INQUIRY: + { + static uint8_t iqd[8] = { + 0x7f, 0x0, 0x4, 0x12, 0x0 + }; + if (cdbp[1] != 0) { + buf[12] = 0x26; + buf[13] = 0x01; + break; + } + mpt_prt(mpt, "local inquiry\n"); + mpt_scsi_tgt_local(mpt, req, lun, 1, + iqd, sizeof (iqd)); + return; + } + case REQUEST_SENSE: + { + buf[2] = 0x0; + mpt_prt(mpt, "local request sense\n"); + mpt_scsi_tgt_local(mpt, req, lun, 1, + buf, sizeof (buf)); + return; + } + case REPORT_LUNS: + buf[12] = 0x26; + break; + default: + buf[12] = 0x25; + break; + } + mpt_scsi_tgt_status(mpt, NULL, req, cond, sp); return; } + /* otherwise, leave trtp NULL */ } else { trtp = &mpt->trt[lun]; } @@ -4609,9 +4867,20 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, /* NOTREACHED */ } if (ccb == NULL) { - panic("mpt: turbo target reply with null " - "associated ccb moving data"); - /* NOTREACHED */ + if (tgt->is_local == 0) { + panic("mpt: turbo target reply with " + "null associated ccb moving data"); + /* NOTREACHED */ + } + mpt_lprt(mpt, MPT_PRT_DEBUG, + "TARGET_ASSIST local done\n"); + TAILQ_REMOVE(&mpt->request_pending_list, + tgt->req, links); + mpt_free_request(mpt, tgt->req); + tgt->req = NULL; + mpt_scsi_tgt_status(mpt, NULL, req, + 0, NULL); + return (TRUE); } tgt->ccb = NULL; tgt->nxfers++; @@ -4715,10 +4984,11 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, /* * And re-post the Command Buffer. - * This wil reset the state. + * This will reset the state. */ ioindex = GET_IO_INDEX(reply_desc); TAILQ_REMOVE(&mpt->request_pending_list, req, links); + tgt->is_local = 0; mpt_post_target_command(mpt, req, ioindex); /* diff --git a/sys/dev/mpt/mpt_debug.c b/sys/dev/mpt/mpt_debug.c index f5546ad0303b..53b0c26431c7 100644 --- a/sys/dev/mpt/mpt_debug.c +++ b/sys/dev/mpt/mpt_debug.c @@ -800,6 +800,21 @@ mpt_dump_sgl(SGE_IO_UNION *su, int offset) } while ((flags & MPI_SGE_FLAGS_END_OF_LIST) == 0 && nxtaddr < lim); } +void +mpt_dump_data(struct mpt_softc *mpt, const char *msg, void *addr, int len) +{ + int offset; + uint8_t *cp = addr; + mpt_prt(mpt, "%s:", msg); + for (offset = 0; offset < len; offset++) { + if ((offset & 0xf) == 0) { + mpt_prtc(mpt, "\n"); + } + mpt_prtc(mpt, " %02x", cp[offset]); + } + mpt_prtc(mpt, "\n"); +} + void mpt_dump_request(struct mpt_softc *mpt, request_t *req) { diff --git a/sys/dev/mpt/mpt_pci.c b/sys/dev/mpt/mpt_pci.c index 32f2ebe0b6d8..7b5668f7bc22 100644 --- a/sys/dev/mpt/mpt_pci.c +++ b/sys/dev/mpt/mpt_pci.c @@ -138,6 +138,10 @@ __FBSDID("$FreeBSD$"); #define PCI_PRODUCT_LSI_FC7X04X 0x0640 #endif +#ifndef PCI_PRODUCT_LSI_FC646 +#define PCI_PRODUCT_LSI_FC646 0x0646 +#endif + #ifndef PCI_PRODUCT_LSI_1030 #define PCI_PRODUCT_LSI_1030 0x0030 #endif @@ -213,8 +217,9 @@ mpt_pci_probe(device_t dev) { char *desc; - if (pci_get_vendor(dev) != PCI_VENDOR_LSI) + if (pci_get_vendor(dev) != PCI_VENDOR_LSI) { return (ENXIO); + } switch ((pci_get_device(dev) & ~1)) { case PCI_PRODUCT_LSI_FC909: @@ -227,16 +232,19 @@ mpt_pci_probe(device_t dev) desc = "LSILogic FC919 FC Adapter"; break; case PCI_PRODUCT_LSI_FC929: - desc = "LSILogic FC929 FC Adapter"; + desc = "Dual LSILogic FC929 FC Adapter"; break; case PCI_PRODUCT_LSI_FC919X: - desc = "LSILogic FC919X FC Adapter"; + desc = "LSILogic FC919 FC PCI-X Adapter"; break; case PCI_PRODUCT_LSI_FC929X: - desc = "LSILogic FC929X 2Gb/s FC Adapter"; + desc = "Dual LSILogic FC929X 2Gb/s FC PCI-X Adapter"; + break; + case PCI_PRODUCT_LSI_FC646: + desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-Express Adapter"; break; case PCI_PRODUCT_LSI_FC7X04X: - desc = "LSILogic FC7X04X 4Gb/s FC Adapter"; + desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-X Adapter"; break; case PCI_PRODUCT_LSI_1030: desc = "LSILogic 1030 Ultra4 Adapter"; @@ -249,7 +257,7 @@ mpt_pci_probe(device_t dev) case PCI_PRODUCT_LSI_SAS1068: case PCI_PRODUCT_LSI_SAS1068E: case PCI_PRODUCT_LSI_SAS1078: - desc = "LSILogic SAS Adapter"; + desc = "LSILogic SAS/SATA Adapter"; break; default: return (ENXIO); @@ -295,6 +303,29 @@ mpt_set_options(struct mpt_softc *mpt) mpt->verbose = MPT_PRT_DEBUG3; } } + + mpt->cfg_role = MPT_ROLE_DEFAULT; + bitmap = 0; + if (getenv_int("mpt_nil_role", &bitmap)) { + if (bitmap & (1 << mpt->unit)) { + mpt->cfg_role = 0; + } + mpt->do_cfg_role = 1; + } + bitmap = 0; + if (getenv_int("mpt_tgt_role", &bitmap)) { + if (bitmap & (1 << mpt->unit)) { + mpt->cfg_role |= MPT_ROLE_TARGET; + } + mpt->do_cfg_role = 1; + } + bitmap = 0; + if (getenv_int("mpt_ini_role", &bitmap)) { + if (bitmap & (1 << mpt->unit)) { + mpt->cfg_role |= MPT_ROLE_INITIATOR; + } + mpt->do_cfg_role = 1; + } } #else static void @@ -312,11 +343,12 @@ mpt_set_options(struct mpt_softc *mpt) device_get_unit(mpt->dev), "debug", &tval) == 0 && tval != 0) { mpt->verbose = tval; } - tval = 0; + tval = -1; if (resource_int_value(device_get_name(mpt->dev), - device_get_unit(mpt->dev), "role", &tval) == 0 && tval != 0 && + device_get_unit(mpt->dev), "role", &tval) == 0 && tval >= 0 && tval <= 3) { - mpt->role = tval; + mpt->cfg_role = tval; + mpt->do_cfg_role = 1; } } #endif @@ -381,6 +413,7 @@ mpt_pci_attach(device_t dev) case PCI_PRODUCT_LSI_FC919: case PCI_PRODUCT_LSI_FC929: case PCI_PRODUCT_LSI_FC919X: + case PCI_PRODUCT_LSI_FC646: case PCI_PRODUCT_LSI_FC7X04X: mpt->is_fc = 1; break; @@ -438,6 +471,7 @@ mpt_pci_attach(device_t dev) * If so, link with our partner (around yet) */ if ((pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC929 || + (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC646 || (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC7X04X || (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_1030) { mpt_link_peer(mpt); @@ -478,13 +512,8 @@ mpt_pci_attach(device_t dev) /* Get a handle to the interrupt */ iqd = 0; -#if __FreeBSD_version < 500000 - mpt->pci_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &iqd, 0, ~0, 1, - RF_ACTIVE | RF_SHAREABLE); -#else mpt->pci_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, RF_ACTIVE | RF_SHAREABLE); -#endif if (mpt->pci_irq == NULL) { device_printf(dev, "could not allocate interrupt\n"); goto bad; diff --git a/sys/dev/mpt/mpt_raid.c b/sys/dev/mpt/mpt_raid.c index 201cc0d1a5af..7448572ad981 100644 --- a/sys/dev/mpt/mpt_raid.c +++ b/sys/dev/mpt/mpt_raid.c @@ -112,7 +112,6 @@ static int mpt_spawn_raid_thread(struct mpt_softc *mpt); static void mpt_terminate_raid_thread(struct mpt_softc *mpt); static void mpt_raid_thread(void *arg); static timeout_t mpt_raid_timer; -static timeout_t mpt_raid_quiesce_timeout; #if 0 static void mpt_enable_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol, int enable); @@ -724,6 +723,15 @@ mpt_raid_thread(void *arg) kthread_exit(0); } +#if 0 +static void +mpt_raid_quiesce_timeout(void *arg) +{ + /* Complete the CCB with error */ + /* COWWWW */ +} + +static timeout_t mpt_raid_quiesce_timeout; cam_status mpt_raid_quiesce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk, request_t *req) @@ -773,6 +781,7 @@ mpt_raid_quiesce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk, } return (CAM_REQUEUE_REQ); } +#endif /* XXX Ignores that there may be multiple busses/IOCs involved. */ cam_status @@ -1505,13 +1514,6 @@ mpt_raid_timer(void *arg) MPT_UNLOCK(mpt); } -static void -mpt_raid_quiesce_timeout(void *arg) -{ - /* Complete the CCB with error */ - /* COWWWW */ -} - void mpt_schedule_raid_refresh(struct mpt_softc *mpt) { diff --git a/sys/dev/mpt/mpt_raid.h b/sys/dev/mpt/mpt_raid.h index 1bd41018ef9c..bc5aa7dd9fe2 100644 --- a/sys/dev/mpt/mpt_raid.h +++ b/sys/dev/mpt/mpt_raid.h @@ -69,8 +69,10 @@ mpt_issue_raid_req(struct mpt_softc *, struct mpt_raid_volume *, cam_status mpt_map_physdisk(struct mpt_softc *, union ccb *, target_id_t *); int mpt_is_raid_volume(struct mpt_softc *, int); +#if 0 cam_status mpt_raid_quiesce_disk(struct mpt_softc *, struct mpt_raid_disk *, request_t *); +#endif int mpt_refresh_raid_data(struct mpt_softc *); void mpt_schedule_raid_refresh(struct mpt_softc *); -- cgit v1.3