diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c index 8c45177bb5b..2c8416e52f4 100644 --- a/sys/dev/mpt/mpt.c +++ b/sys/dev/mpt/mpt.c @@ -665,6 +665,7 @@ mpt_intr(void *arg) int ntrips = 0; mpt = (struct mpt_softc *)arg; + mpt_lprt(mpt, MPT_PRT_DEBUG2, "enter mpt_intr\n"); while ((reply_desc = mpt_pop_reply_queue(mpt)) != MPT_REPLY_EMPTY) { request_t *req; MSG_DEFAULT_REPLY *reply_frame; @@ -789,6 +790,7 @@ mpt_intr(void *arg) break; } } + mpt_lprt(mpt, MPT_PRT_DEBUG2, "exit mpt_intr\n"); } /******************************* Error Recovery *******************************/ @@ -1138,18 +1140,29 @@ mpt_free_request(struct mpt_softc *mpt, request_t *req) req->chain = NULL; mpt_free_request(mpt, nxt); /* NB: recursion */ } - KASSERT(req->state != REQ_STATE_FREE, ("freeing free request")); KASSERT(!(req->state & REQ_STATE_LOCKED), ("freeing locked request")); + KASSERT(MPT_OWNED(mpt), ("mpt_free_request: mpt not locked\n")); + KASSERT(mpt_req_on_free_list(mpt, req) == 0, + ("mpt_free_request: req %p:%u func %x already on freelist", + req, req->serno, ((MSG_REQUEST_HEADER *)req->req_vbuf)->Function)); + KASSERT(mpt_req_on_pending_list(mpt, req) == 0, + ("mpt_free_request: req %p:%u func %x on pending list", + req, req->serno, ((MSG_REQUEST_HEADER *)req->req_vbuf)->Function)); +#ifdef INVARIANTS + mpt_req_not_spcl(mpt, req, "mpt_free_request", __LINE__); +#endif req->ccb = NULL; - if (LIST_EMPTY(&mpt->ack_frames)) { /* * Insert free ones at the tail */ req->serno = 0; req->state = REQ_STATE_FREE; +#ifdef INVARIANTS + memset(req->req_vbuf, 0xff, sizeof (MSG_REQUEST_HEADER)); +#endif TAILQ_INSERT_TAIL(&mpt->request_free_list, req, links); if (mpt->getreqwaiter != 0) { mpt->getreqwaiter = 0; @@ -1164,9 +1177,7 @@ mpt_free_request(struct mpt_softc *mpt, request_t *req) record = LIST_FIRST(&mpt->ack_frames); LIST_REMOVE(record, links); req->state = REQ_STATE_ALLOCATED; - if ((req->serno = mpt->sequence++) == 0) { - req->serno = mpt->sequence++; - } + mpt_assign_serno(mpt, req); mpt_send_event_ack(mpt, req, &record->reply, record->context); reply_baddr = (uint32_t)((uint8_t *)record - mpt->reply) + (mpt->reply_phys & 0xFFFFFFFF); @@ -1180,18 +1191,19 @@ mpt_get_request(struct mpt_softc *mpt, int sleep_ok) request_t *req; retry: + KASSERT(MPT_OWNED(mpt), ("mpt_get_request: mpt not locked\n")); req = TAILQ_FIRST(&mpt->request_free_list); if (req != NULL) { KASSERT(req == &mpt->request_pool[req->index], ("mpt_get_request: corrupted request free list\n")); KASSERT(req->state == REQ_STATE_FREE, - ("req not free on free list %x", req->state)); + ("req %p:%u not free on free list %x index %d function %x", + req, req->serno, req->state, req->index, + ((MSG_REQUEST_HEADER *)req->req_vbuf)->Function)); TAILQ_REMOVE(&mpt->request_free_list, req, links); req->state = REQ_STATE_ALLOCATED; req->chain = NULL; - if ((req->serno = mpt->sequence++) == 0) { - req->serno = mpt->sequence++; - } + mpt_assign_serno(mpt, req); } else if (sleep_ok != 0) { mpt->getreqwaiter = 1; mpt_sleep(mpt, &mpt->request_free_list, PUSER, "mptgreq", 0); @@ -1228,6 +1240,12 @@ mpt_send_cmd(struct mpt_softc *mpt, request_t *req) bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap, BUS_DMASYNC_PREWRITE); req->state |= REQ_STATE_QUEUED; + KASSERT(mpt_req_on_free_list(mpt, req) == 0, + ("req %p:%u func %x on freelist list in mpt_send_cmd", + req, req->serno, ((MSG_REQUEST_HEADER *)req->req_vbuf)->Function)); + KASSERT(mpt_req_on_pending_list(mpt, req) == 0, + ("req %p:%u func %x already on pending list in mpt_send_cmd", + req, req->serno, ((MSG_REQUEST_HEADER *)req->req_vbuf)->Function)); TAILQ_INSERT_HEAD(&mpt->request_pending_list, req, links); mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (uint32_t) req->req_pbuf); } @@ -1867,8 +1885,7 @@ mpt_send_port_enable(struct mpt_softc *mpt, int port) mpt_send_cmd(mpt, req); error = mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, - /*sleep_ok*/FALSE, - /*time_ms*/(mpt->is_sas || mpt->is_fc)? 30000 : 3000); + FALSE, (mpt->is_sas || mpt->is_fc)? 30000 : 3000); if (error != 0) { mpt_prt(mpt, "port %d enable timed out\n", port); return (-1); @@ -2113,7 +2130,7 @@ mpt_core_enable(struct mpt_softc *mpt) mpt_intr(mpt); /* - * Enable the port- but only if we are not MPT_ROLE_NONE. + * Enable the port. */ if (mpt_send_port_enable(mpt, 0) != MPT_OK) { mpt_prt(mpt, "failed to enable port 0\n"); @@ -2446,38 +2463,22 @@ mpt_configure_ioc(struct mpt_softc *mpt) mpt->mpt_max_devices = pfp.MaxDevices; /* - * Match our expected role with what this port supports. - * - * We only do this to meet expectations. That is, if the - * user has specified they want initiator role, and we - * don't support it, that's an error we return back upstream. + * Set our expected role with what this port supports. */ - mpt->cap = MPT_ROLE_NONE; + mpt->role = MPT_ROLE_NONE; if (pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { - mpt->cap |= MPT_ROLE_INITIATOR; + mpt->role |= MPT_ROLE_INITIATOR; } if (pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { - mpt->cap |= MPT_ROLE_TARGET; + mpt->role |= MPT_ROLE_TARGET; } - if (mpt->cap == MPT_ROLE_NONE) { + if (mpt->role == MPT_ROLE_NONE) { mpt_prt(mpt, "port does not support either target or " "initiator role\n"); return (ENXIO); } - if ((mpt->role & MPT_ROLE_INITIATOR) && - (mpt->cap & MPT_ROLE_INITIATOR) == 0) { - mpt_prt(mpt, "port does not support initiator role\n"); - return (ENXIO); - } - - if ((mpt->role & MPT_ROLE_TARGET) && - (mpt->cap & MPT_ROLE_TARGET) == 0) { - mpt_prt(mpt, "port does not support target 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 b2921b50aaf..a13986e7e82 100644 --- a/sys/dev/mpt/mpt.h +++ b/sys/dev/mpt/mpt.h @@ -294,7 +294,8 @@ struct req_entry { mpt_req_state_t state; /* Request State Information */ uint16_t index; /* Index of this entry */ uint16_t IOCStatus; /* Completion status */ - uint32_t serno; /* serial number */ + uint16_t ResponseCode; /* TMF Reponse Code */ + uint16_t serno; /* serial number */ union ccb *ccb; /* CAM request */ void *req_vbuf; /* Virtual Address of Entry */ void *sense_vbuf; /* Virtual Address of sense data */ @@ -355,7 +356,7 @@ typedef struct { struct mpt_hdr_stailq inots; int enabled; } tgt_resource_t; -#define MPT_MAX_ELS 8 +#define MPT_MAX_ELS 64 /**************************** Handler Registration ****************************/ /* @@ -478,10 +479,11 @@ LIST_HEAD(mpt_evtf_list, mpt_evtf_record); struct mpt_softc { device_t dev; #if __FreeBSD_version < 500000 - int mpt_splsaved; uint32_t mpt_islocked; + int mpt_splsaved; #else struct mtx mpt_lock; + int mpt_locksetup; #endif uint32_t mpt_pers_mask; uint32_t : 8, @@ -489,14 +491,14 @@ struct mpt_softc { : 1, twildcard : 1, tenabled : 1, - cap : 2, /* none, ini, target, both */ + : 2, role : 2, /* none, ini, target, both */ raid_mwce_set : 1, getreqwaiter : 1, shutdwn_raid : 1, shutdwn_recovery: 1, outofbeer : 1, - mpt_locksetup : 1, + : 1, disabled : 1, is_sas : 1, is_fc : 1; @@ -534,8 +536,6 @@ struct mpt_softc { CONFIG_PAGE_SCSI_DEVICE_1 _dev_page1[16]; uint16_t _tag_enable; uint16_t _disc_enable; - uint16_t _update_params0; - uint16_t _update_params1; } spi; #define mpt_port_page0 cfg.spi._port_page0 #define mpt_port_page1 cfg.spi._port_page1 @@ -544,8 +544,6 @@ struct mpt_softc { #define mpt_dev_page1 cfg.spi._dev_page1 #define mpt_tag_enable cfg.spi._tag_enable #define mpt_disc_enable cfg.spi._disc_enable -#define mpt_update_params0 cfg.spi._update_params0 -#define mpt_update_params1 cfg.spi._update_params1 struct mpi_fc_cfg { CONFIG_PAGE_FC_PORT_0 _port_page0; #define mpt_fcport_page0 cfg.fc._port_page0 @@ -637,6 +635,7 @@ struct mpt_softc { */ uint32_t scsi_tgt_handler_id; request_t ** tgt_cmd_ptrs; + request_t ** els_cmd_ptrs; /* FC only */ /* * *snork*- this is chosen to be here *just in case* somebody @@ -646,11 +645,12 @@ struct mpt_softc { tgt_resource_t trt_wildcard; /* wildcard luns */ tgt_resource_t trt[MPT_MAX_LUNS]; uint16_t tgt_cmds_allocated; - uint16_t padding1; + uint16_t els_cmds_allocated; /* FC only */ uint16_t timeouts; /* timeout count */ uint16_t success; /* successes afer timeout */ - uint32_t sequence; /* Sequence Number */ + uint16_t sequence; /* Sequence Number */ + uint16_t pad3; /* Opposing port in a 929 or 1030, or NULL */ @@ -669,11 +669,22 @@ struct mpt_softc { TAILQ_ENTRY(mpt_softc) links; }; +static __inline void mpt_assign_serno(struct mpt_softc *, request_t *); + +static __inline void +mpt_assign_serno(struct mpt_softc *mpt, request_t *req) +{ + if ((req->serno = mpt->sequence++) == 0) { + req->serno = mpt->sequence++; + } +} + /***************************** Locking Primitives *****************************/ #if __FreeBSD_version < 500000 #define MPT_IFLAGS INTR_TYPE_CAM #define MPT_LOCK(mpt) mpt_lockspl(mpt) #define MPT_UNLOCK(mpt) mpt_unlockspl(mpt) +#define MPT_OWNED(mpt) mpt->mpt_islocked #define MPTLOCK_2_CAMLOCK MPT_UNLOCK #define CAMLOCK_2_MPTLOCK MPT_LOCK #define MPT_LOCK_SETUP(mpt) @@ -741,22 +752,56 @@ mpt_sleep(struct mpt_softc *mpt, void *ident, int priority, #define MPT_LOCK(mpt) mtx_lock(&(mpt)->mpt_lock) #define MPT_UNLOCK(mpt) mtx_unlock(&(mpt)->mpt_lock) +#define MPT_OWNED(mpt) mtx_owned(&(mpt)->mpt_lock) #define MPTLOCK_2_CAMLOCK(mpt) \ mtx_unlock(&(mpt)->mpt_lock); mtx_lock(&Giant) #define CAMLOCK_2_MPTLOCK(mpt) \ mtx_unlock(&Giant); mtx_lock(&(mpt)->mpt_lock) #define mpt_sleep(mpt, ident, priority, wmesg, timo) \ msleep(ident, &(mpt)->mpt_lock, priority, wmesg, timo) + #else + #define MPT_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY #define MPT_LOCK_SETUP(mpt) do { } while (0) #define MPT_LOCK_DESTROY(mpt) do { } while (0) -#define MPT_LOCK(mpt) do { } while (0) -#define MPT_UNLOCK(mpt) do { } while (0) -#define MPTLOCK_2_CAMLOCK(mpt) do { } while (0) -#define CAMLOCK_2_MPTLOCK(mpt) do { } while (0) -#define mpt_sleep(mpt, ident, priority, wmesg, timo) \ - tsleep(ident, priority, wmesg, timo) +#if 0 +#define MPT_LOCK(mpt) \ + device_printf(mpt->dev, "LOCK %s:%d\n", __FILE__, __LINE__); \ + KASSERT(mpt->mpt_locksetup == 0, \ + ("recursive lock acquire at %s:%d", __FILE__, __LINE__)); \ + mpt->mpt_locksetup = 1 +#define MPT_UNLOCK(mpt) \ + device_printf(mpt->dev, "UNLK %s:%d\n", __FILE__, __LINE__); \ + KASSERT(mpt->mpt_locksetup == 1, \ + ("release unowned lock at %s:%d", __FILE__, __LINE__)); \ + mpt->mpt_locksetup = 0 +#else +#define MPT_LOCK(mpt) \ + KASSERT(mpt->mpt_locksetup == 0, \ + ("recursive lock acquire at %s:%d", __FILE__, __LINE__)); \ + mpt->mpt_locksetup = 1 +#define MPT_UNLOCK(mpt) \ + KASSERT(mpt->mpt_locksetup == 1, \ + ("release unowned lock at %s:%d", __FILE__, __LINE__)); \ + mpt->mpt_locksetup = 0 +#endif +#define MPT_OWNED(mpt) mpt->mpt_locksetup +#define MPTLOCK_2_CAMLOCK(mpt) MPT_UNLOCK(mpt) +#define CAMLOCK_2_MPTLOCK(mpt) MPT_LOCK(mpt) + +static __inline int +mpt_sleep(struct mpt_softc *, void *, int, const char *, int); + +static __inline int +mpt_sleep(struct mpt_softc *mpt, void *i, int p, const char *w, int t) +{ + int r; + MPT_UNLOCK(mpt); + r = tsleep(i, p, w, t); + MPT_LOCK(mpt); + return (r); +} #endif #endif @@ -902,6 +947,11 @@ enum { MPT_PRT_TRACE, MPT_PRT_NONE=100 }; +#ifdef INVARIANTS +#define MPT_PRT_INVARIANT MPT_PRT_ALWAYS +#else +#define MPT_PRT_INVARIANT MPT_PRT_DEBUG +#endif #if __FreeBSD_version > 500000 #define mpt_lprt(mpt, level, ...) \ @@ -955,6 +1005,93 @@ mpt_tag_2_req(struct mpt_softc *mpt, uint32_t tag) KASSERT(mpt->tgt_cmd_ptrs[rtg], ("no cmd backpointer")); return (mpt->tgt_cmd_ptrs[rtg]); } + + +static __inline int +mpt_req_on_free_list(struct mpt_softc *, request_t *); +static __inline int +mpt_req_on_pending_list(struct mpt_softc *, request_t *); + +static __inline void +mpt_req_spcl(struct mpt_softc *, request_t *, const char *, int); +static __inline void +mpt_req_not_spcl(struct mpt_softc *, request_t *, const char *, int); + + +/* + * Is request on freelist? + */ +static __inline int +mpt_req_on_free_list(struct mpt_softc *mpt, request_t *req) +{ + request_t *lrq; + + TAILQ_FOREACH(lrq, &mpt->request_free_list, links) { + if (lrq == req) { + return (1); + } + } + return (0); +} + +/* + * Is request on pending list? + */ +static __inline int +mpt_req_on_pending_list(struct mpt_softc *mpt, request_t *req) +{ + request_t *lrq; + + TAILQ_FOREACH(lrq, &mpt->request_pending_list, links) { + if (lrq == req) { + return (1); + } + } + return (0); +} + +/* + * Make sure that req *is* part of one of the special lists + */ +static __inline void +mpt_req_spcl(struct mpt_softc *mpt, request_t *req, const char *s, int line) +{ + int i; + for (i = 0; i < mpt->els_cmds_allocated; i++) { + if (req == mpt->els_cmd_ptrs[i]) { + return; + } + } + for (i = 0; i < mpt->tgt_cmds_allocated; i++) { + if (req == mpt->tgt_cmd_ptrs[i]) { + return; + } + } + panic("%s(%d): req %p:%u function %x not in els or tgt ptrs\n", + s, line, req, req->serno, + ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function); +} + +/* + * Make sure that req is *not* part of one of the special lists. + */ +static __inline void +mpt_req_not_spcl(struct mpt_softc *mpt, request_t *req, const char *s, int line) +{ + int i; + for (i = 0; i < mpt->els_cmds_allocated; i++) { + KASSERT(req != mpt->els_cmd_ptrs[i], + ("%s(%d): req %p:%u func %x in els ptrs at ioindex %d\n", + s, line, req, req->serno, + ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function, i)); + } + for (i = 0; i < mpt->tgt_cmds_allocated; i++) { + KASSERT(req != mpt->tgt_cmd_ptrs[i], + ("%s(%d): req %p:%u func %x in tgt ptrs at ioindex %d\n", + s, line, req, req->serno, + ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function, i)); + } +} #endif typedef enum { diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c index 7b7888b7a99..6399d40fc6e 100644 --- a/sys/dev/mpt/mpt_cam.c +++ b/sys/dev/mpt/mpt_cam.c @@ -108,8 +108,11 @@ __FBSDID("$FreeBSD$"); static void mpt_poll(struct cam_sim *); static timeout_t mpt_timeout; static void mpt_action(struct cam_sim *, union ccb *); -static int mpt_setwidth(struct mpt_softc *, int, int); -static int mpt_setsync(struct mpt_softc *, int, int, int); +static int +mpt_get_spi_settings(struct mpt_softc *, struct ccb_trans_settings *); +static void mpt_setwidth(struct mpt_softc *, int, int); +static void mpt_setsync(struct mpt_softc *, int, int, int); +static int mpt_update_spi_config(struct mpt_softc *, int); static void mpt_calc_geometry(struct ccb_calc_geometry *ccg, int extended); static mpt_reply_handler_t mpt_scsi_reply_handler; static mpt_reply_handler_t mpt_scsi_tmf_reply_handler; @@ -127,9 +130,12 @@ static void mpt_recover_commands(struct mpt_softc *mpt); static int mpt_scsi_send_tmf(struct mpt_softc *, u_int, u_int, u_int, u_int, u_int, u_int, int); -static void mpt_fc_add_els(struct mpt_softc *mpt, request_t *); +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 void mpt_add_target_commands(struct mpt_softc *mpt); +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 *); @@ -199,64 +205,45 @@ mpt_cam_attach(struct mpt_softc *mpt) error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, &scsi_io_handler_id); if (error != 0) { - goto cleanup; + goto cleanup0; } handler.reply_handler = mpt_scsi_tmf_reply_handler; error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, &scsi_tmf_handler_id); if (error != 0) { - goto cleanup; + goto cleanup0; } /* - * We keep two requests reserved for ELS replies/responses - * if we're fibre channel and target mode. + * If we're fibre channel and could support target mode, we register + * an ELS reply handler and give it resources. */ if (mpt->is_fc && (mpt->role & MPT_ROLE_TARGET) != 0) { - request_t *req; - int i; - handler.reply_handler = mpt_fc_els_reply_handler; error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler, &fc_els_handler_id); if (error != 0) { - goto cleanup; + goto cleanup0; } - - /* - * Feed the chip some ELS buffer resources - */ - for (i = 0; i < MPT_MAX_ELS; i++) { - req = mpt_get_request(mpt, FALSE); - if (req == NULL) { - break; - } - mpt_fc_add_els(mpt, req); + if (mpt_add_els_buffers(mpt) == FALSE) { + error = ENOMEM; + goto cleanup0; } - if (i == 0) { - mpt_prt(mpt, "Unable to add ELS buffer resources\n"); - goto cleanup; - } - maxq -= i; + maxq -= mpt->els_cmds_allocated; } /* - * If we're in target mode, register a reply - * handler for it and add some commands. + * If we support target mode, we register a reply handler for it, + * but don't add resources until we actually enable target mode. */ if ((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); if (error != 0) { - goto cleanup; + goto cleanup0; } - - /* - * Add some target command resources - */ - mpt_add_target_commands(mpt); } /* @@ -266,7 +253,7 @@ mpt_cam_attach(struct mpt_softc *mpt) if (mpt->tmf_req == NULL) { mpt_prt(mpt, "Unable to allocate dedicated TMF request!\n"); error = ENOMEM; - goto cleanup; + goto cleanup0; } /* @@ -281,9 +268,14 @@ mpt_cam_attach(struct mpt_softc *mpt) if (mpt_spawn_recovery_thread(mpt) != 0) { mpt_prt(mpt, "Unable to spawn recovery thread!\n"); error = ENOMEM; - goto cleanup; + goto cleanup0; } + /* + * The rest of this is CAM foo, for which we need to drop our lock + */ + MPTLOCK_2_CAMLOCK(mpt); + /* * Create the device queue for our SIM(s). */ @@ -327,6 +319,7 @@ mpt_cam_attach(struct mpt_softc *mpt) * devices if the controller supports RAID. */ if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) { + CAMLOCK_2_MPTLOCK(mpt); return (0); } @@ -357,8 +350,12 @@ mpt_cam_attach(struct mpt_softc *mpt) error = ENOMEM; goto cleanup; } + CAMLOCK_2_MPTLOCK(mpt); return (0); + cleanup: + CAMLOCK_2_MPTLOCK(mpt); +cleanup0: mpt_cam_detach(mpt); return (error); } @@ -461,16 +458,6 @@ mpt_set_initial_config_fc(struct mpt_softc *mpt) fl |= MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID; doit = 1; } - if ((fl & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT) && - (mpt->role & MPT_ROLE_INITIATOR) == 0) { - fl &= ~MPI_FCPORTPAGE1_FLAGS_PROT_FCP_INIT; - doit = 1; - } - if ((fl & MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG) && - (mpt->role & MPT_ROLE_TARGET) == 0) { - fl &= ~MPI_FCPORTPAGE1_FLAGS_PROT_FCP_TARG; - doit = 1; - } if (doit) { const char *cc; @@ -487,12 +474,8 @@ mpt_set_initial_config_fc(struct mpt_softc *mpt) } mpt_prt(mpt, cc); } -#else - if ((mpt->role & MPT_ROLE_TARGET) == 0) { - return (0); - } #endif - return (mpt_fc_reset_link(mpt, 1)); + return (0); } /* @@ -521,69 +504,63 @@ mpt_read_config_info_spi(struct mpt_softc *mpt) { int rv, i; - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0, - 0, &mpt->mpt_port_page0.Header, - /*sleep_ok*/FALSE, /*timeout_ms*/5000); - if (rv) + rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0, 0, + &mpt->mpt_port_page0.Header, FALSE, 5000); + if (rv) { return (-1); - mpt_lprt(mpt, MPT_PRT_DEBUG, - "SPI Port Page 0 Header: %x %x %x %x\n", - mpt->mpt_port_page0.Header.PageVersion, - mpt->mpt_port_page0.Header.PageLength, - mpt->mpt_port_page0.Header.PageNumber, - mpt->mpt_port_page0.Header.PageType); + } + mpt_lprt(mpt, MPT_PRT_DEBUG, "SPI Port Page 0 Header: %x %x %x %x\n", + mpt->mpt_port_page0.Header.PageVersion, + mpt->mpt_port_page0.Header.PageLength, + mpt->mpt_port_page0.Header.PageNumber, + mpt->mpt_port_page0.Header.PageType); - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1, - 0, &mpt->mpt_port_page1.Header, - /*sleep_ok*/FALSE, /*timeout_ms*/5000); - if (rv) + rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1, 0, + &mpt->mpt_port_page1.Header, FALSE, 5000); + if (rv) { return (-1); - + } mpt_lprt(mpt, MPT_PRT_DEBUG, "SPI Port Page 1 Header: %x %x %x %x\n", - mpt->mpt_port_page1.Header.PageVersion, - mpt->mpt_port_page1.Header.PageLength, - mpt->mpt_port_page1.Header.PageNumber, - mpt->mpt_port_page1.Header.PageType); + mpt->mpt_port_page1.Header.PageVersion, + mpt->mpt_port_page1.Header.PageLength, + mpt->mpt_port_page1.Header.PageNumber, + mpt->mpt_port_page1.Header.PageType); - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, - /*PageAddress*/0, &mpt->mpt_port_page2.Header, - /*sleep_ok*/FALSE, /*timeout_ms*/5000); - if (rv) + rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 0, + &mpt->mpt_port_page2.Header, FALSE, 5000); + if (rv) { return (-1); - - mpt_lprt(mpt, MPT_PRT_DEBUG, - "SPI Port Page 2 Header: %x %x %x %x\n", - mpt->mpt_port_page1.Header.PageVersion, - mpt->mpt_port_page1.Header.PageLength, - mpt->mpt_port_page1.Header.PageNumber, - mpt->mpt_port_page1.Header.PageType); + } + mpt_lprt(mpt, MPT_PRT_DEBUG, "SPI Port Page 2 Header: %x %x %x %x\n", + mpt->mpt_port_page2.Header.PageVersion, + mpt->mpt_port_page2.Header.PageLength, + mpt->mpt_port_page2.Header.PageNumber, + mpt->mpt_port_page2.Header.PageType); for (i = 0; i < 16; i++) { rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, - 0, i, &mpt->mpt_dev_page0[i].Header, - /*sleep_ok*/FALSE, /*timeout_ms*/5000); - if (rv) + 0, i, &mpt->mpt_dev_page0[i].Header, FALSE, 5000); + if (rv) { return (-1); - + } mpt_lprt(mpt, MPT_PRT_DEBUG, - "SPI Target %d Device Page 0 Header: %x %x %x %x\n", - i, mpt->mpt_dev_page0[i].Header.PageVersion, - mpt->mpt_dev_page0[i].Header.PageLength, - mpt->mpt_dev_page0[i].Header.PageNumber, - mpt->mpt_dev_page0[i].Header.PageType); + "SPI Target %d Device Page 0 Header: %x %x %x %x\n", i, + mpt->mpt_dev_page0[i].Header.PageVersion, + mpt->mpt_dev_page0[i].Header.PageLength, + mpt->mpt_dev_page0[i].Header.PageNumber, + mpt->mpt_dev_page0[i].Header.PageType); rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, - 1, i, &mpt->mpt_dev_page1[i].Header, - /*sleep_ok*/FALSE, /*timeout_ms*/5000); - if (rv) + 1, i, &mpt->mpt_dev_page1[i].Header, FALSE, 5000); + if (rv) { return (-1); - + } mpt_lprt(mpt, MPT_PRT_DEBUG, - "SPI Target %d Device Page 1 Header: %x %x %x %x\n", - i, mpt->mpt_dev_page1[i].Header.PageVersion, - mpt->mpt_dev_page1[i].Header.PageLength, - mpt->mpt_dev_page1[i].Header.PageNumber, - mpt->mpt_dev_page1[i].Header.PageType); + "SPI Target %d Device Page 1 Header: %x %x %x %x\n", i, + mpt->mpt_dev_page1[i].Header.PageVersion, + mpt->mpt_dev_page1[i].Header.PageLength, + mpt->mpt_dev_page1[i].Header.PageNumber, + mpt->mpt_dev_page1[i].Header.PageType); } /* @@ -592,10 +569,8 @@ mpt_read_config_info_spi(struct mpt_softc *mpt) * along. */ - rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, - &mpt->mpt_port_page0.Header, - sizeof(mpt->mpt_port_page0), - /*sleep_ok*/FALSE, /*timeout_ms*/5000); + rv = mpt_read_cur_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header, + sizeof(mpt->mpt_port_page0), FALSE, 5000); if (rv) { mpt_prt(mpt, "failed to read SPI Port Page 0\n"); } else { @@ -605,10 +580,8 @@ mpt_read_config_info_spi(struct mpt_softc *mpt) mpt->mpt_port_page0.PhysicalInterface); } - rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, - &mpt->mpt_port_page1.Header, - sizeof(mpt->mpt_port_page1), - /*sleep_ok*/FALSE, /*timeout_ms*/5000); + rv = mpt_read_cur_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header, + sizeof(mpt->mpt_port_page1), FALSE, 5000); if (rv) { mpt_prt(mpt, "failed to read SPI Port Page 1\n"); } else { @@ -618,10 +591,8 @@ mpt_read_config_info_spi(struct mpt_softc *mpt) mpt->mpt_port_page1.OnBusTimerValue); } - rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, - &mpt->mpt_port_page2.Header, - sizeof(mpt->mpt_port_page2), - /*sleep_ok*/FALSE, /*timeout_ms*/5000); + rv = mpt_read_cur_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header, + sizeof(mpt->mpt_port_page2), FALSE, 5000); if (rv) { mpt_prt(mpt, "failed to read SPI Port Page 2\n"); } else { @@ -639,35 +610,31 @@ mpt_read_config_info_spi(struct mpt_softc *mpt) } for (i = 0; i < 16; i++) { - rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/i, - &mpt->mpt_dev_page0[i].Header, - sizeof(*mpt->mpt_dev_page0), - /*sleep_ok*/FALSE, - /*timeout_ms*/5000); + rv = mpt_read_cur_cfg_page(mpt, i, + &mpt->mpt_dev_page0[i].Header, sizeof(*mpt->mpt_dev_page0), + FALSE, 5000); if (rv) { mpt_prt(mpt, - "cannot read SPI Tgt %d Device Page 0\n", i); + "cannot read SPI Target %d Device Page 0\n", i); continue; } mpt_lprt(mpt, MPT_PRT_DEBUG, - "SPI Tgt %d Page 0: NParms %x Information %x", - i, mpt->mpt_dev_page0[i].NegotiatedParameters, - mpt->mpt_dev_page0[i].Information); + "SPI Tgt %d Page 0: NParms %x Information %x", i, + mpt->mpt_dev_page0[i].NegotiatedParameters, + mpt->mpt_dev_page0[i].Information); - rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/i, - &mpt->mpt_dev_page1[i].Header, - sizeof(*mpt->mpt_dev_page1), - /*sleep_ok*/FALSE, - /*timeout_ms*/5000); + rv = mpt_read_cur_cfg_page(mpt, i, + &mpt->mpt_dev_page1[i].Header, sizeof(*mpt->mpt_dev_page1), + FALSE, 5000); if (rv) { mpt_prt(mpt, - "cannot read SPI Tgt %d Device Page 1\n", i); + "cannot read SPI Target %d Device Page 1\n", i); continue; } mpt_lprt(mpt, MPT_PRT_DEBUG, - "SPI Tgt %d Page 1: RParms %x Configuration %x\n", - i, mpt->mpt_dev_page1[i].RequestedParameters, - mpt->mpt_dev_page1[i].Configuration); + "SPI Tgt %d Page 1: RParms %x Configuration %x\n", i, + mpt->mpt_dev_page1[i].RequestedParameters, + mpt->mpt_dev_page1[i].Configuration); } return (0); } @@ -689,23 +656,20 @@ mpt_set_initial_config_spi(struct mpt_softc *mpt) if (mpt->mpt_port_page1.Configuration != pp1val) { CONFIG_PAGE_SCSI_PORT_1 tmp; - mpt_prt(mpt, - "SPI Port Page 1 Config value bad (%x)- should be %x\n", - mpt->mpt_port_page1.Configuration, pp1val); + mpt_prt(mpt, "SPI Port Page 1 Config value bad (%x)- should " + "be %x\n", mpt->mpt_port_page1.Configuration, pp1val); tmp = mpt->mpt_port_page1; tmp.Configuration = pp1val; - error = mpt_write_cur_cfg_page(mpt, /*PageAddress*/0, - &tmp.Header, sizeof(tmp), - /*sleep_ok*/FALSE, - /*timeout_ms*/5000); - if (error) + error = mpt_write_cur_cfg_page(mpt, 0, + &tmp.Header, sizeof(tmp), FALSE, 5000); + if (error) { return (-1); - error = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, - &tmp.Header, sizeof(tmp), - /*sleep_ok*/FALSE, - /*timeout_ms*/5000); - if (error) + } + error = mpt_read_cur_cfg_page(mpt, 0, + &tmp.Header, sizeof(tmp), FALSE, 5000); + if (error) { return (-1); + } if (tmp.Configuration != pp1val) { mpt_prt(mpt, "failed to reset SPI Port Page 1 Config value\n"); @@ -714,31 +678,23 @@ mpt_set_initial_config_spi(struct mpt_softc *mpt) mpt->mpt_port_page1 = tmp; } + /* + * The purpose of this exercise is to get + * all targets back to async/narrow. + * + * We skip this if the BIOS has already negotiated speeds with targets. + */ + i = mpt->mpt_port_page2.PortSettings & + MPI_SCSIPORTPAGE2_PORT_MASK_NEGO_MASTER_SETTINGS; + if (i == MPI_SCSIPORTPAGE2_PORT_ALL_MASTER_SETTINGS) { + mpt_lprt(mpt, MPT_PRT_INFO, + "honoring BIOS transfer negotiation for all targets\n"); + return (0); + } for (i = 0; i < 16; i++) { - CONFIG_PAGE_SCSI_DEVICE_1 tmp; - tmp = mpt->mpt_dev_page1[i]; - tmp.RequestedParameters = 0; - tmp.Configuration = 0; - mpt_lprt(mpt, MPT_PRT_DEBUG, - "Set Tgt %d SPI DevicePage 1 values to %x 0 %x\n", - i, tmp.RequestedParameters, tmp.Configuration); - error = mpt_write_cur_cfg_page(mpt, /*PageAddress*/i, - &tmp.Header, sizeof(tmp), - /*sleep_ok*/FALSE, - /*timeout_ms*/5000); - if (error) - return (-1); - error = mpt_read_cur_cfg_page(mpt, /*PageAddress*/i, - &tmp.Header, sizeof(tmp), - /*sleep_ok*/FALSE, - /*timeout_ms*/5000); - if (error) - return (-1); - mpt->mpt_dev_page1[i] = tmp; - mpt_lprt(mpt, MPT_PRT_DEBUG, - "SPI Tgt %d Page 1: RParm %x Configuration %x\n", i, - mpt->mpt_dev_page1[i].RequestedParameters, - mpt->mpt_dev_page1[i].Configuration); + mpt->mpt_dev_page1[i].RequestedParameters = 0; + mpt->mpt_dev_page1[i].Configuration = 0; + (void) mpt_update_spi_config(mpt, i); } return (0); } @@ -792,22 +748,27 @@ mpt_cam_detach(struct mpt_softc *mpt) mpt->scsi_tgt_handler_id); if (mpt->tmf_req != NULL) { + mpt->tmf_req->state = REQ_STATE_ALLOCATED; mpt_free_request(mpt, mpt->tmf_req); mpt->tmf_req = NULL; } if (mpt->sim != NULL) { + MPTLOCK_2_CAMLOCK(mpt); xpt_free_path(mpt->path); xpt_bus_deregister(cam_sim_path(mpt->sim)); cam_sim_free(mpt->sim, TRUE); mpt->sim = NULL; + CAMLOCK_2_MPTLOCK(mpt); } if (mpt->phydisk_sim != NULL) { + MPTLOCK_2_CAMLOCK(mpt); xpt_free_path(mpt->phydisk_path); xpt_bus_deregister(cam_sim_path(mpt->phydisk_sim)); cam_sim_free(mpt->phydisk_sim, TRUE); mpt->phydisk_sim = NULL; + CAMLOCK_2_MPTLOCK(mpt); } } @@ -841,6 +802,7 @@ mpt_timeout(void *arg) req = ccb->ccb_h.ccb_req_ptr; mpt_prt(mpt, "request %p:%u timed out for ccb %p (req->ccb %p)\n", req, req->serno, ccb, req->ccb); +/* XXX: WHAT ARE WE TRYING TO DO HERE? */ if ((req->state & REQ_STATE_QUEUED) == REQ_STATE_QUEUED) { TAILQ_REMOVE(&mpt->request_pending_list, req, links); TAILQ_INSERT_TAIL(&mpt->request_timeout_list, req, links); @@ -1144,7 +1106,11 @@ bad: * and chain to that. */ if (seg < nseg && nxt_off >= MPT_REQUEST_AREA) { - request_t *nrq = mpt_get_request(mpt, FALSE); + request_t *nrq; + + CAMLOCK_2_MPTLOCK(mpt); + nrq = mpt_get_request(mpt, FALSE); + MPTLOCK_2_CAMLOCK(mpt); if (nrq == NULL) { error = ENOMEM; @@ -1508,7 +1474,11 @@ bad: * and chain to that. */ if (seg < nseg && nxt_off >= MPT_REQUEST_AREA) { - request_t *nrq = mpt_get_request(mpt, FALSE); + request_t *nrq; + + CAMLOCK_2_MPTLOCK(mpt); + nrq = mpt_get_request(mpt, FALSE); + MPTLOCK_2_CAMLOCK(mpt); if (nrq == NULL) { error = ENOMEM; @@ -1624,6 +1594,9 @@ mpt_start(struct cam_sim *sim, union ccb *ccb) xpt_done(ccb); return; } +#ifdef INVARIANTS + mpt_req_not_spcl(mpt, req, "mpt_start", __LINE__); +#endif MPTLOCK_2_CAMLOCK(mpt); if (sizeof (bus_addr_t) > 4) { @@ -1794,7 +1767,8 @@ static int mpt_bus_reset(struct mpt_softc *mpt, int sleep_ok) { int error; - u_int status; + uint16_t status; + uint8_t response; error = mpt_scsi_send_tmf(mpt, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, mpt->is_fc ? MPI_SCSITASKMGMT_MSGFLAGS_LIP_RESET_OPTION : 0, @@ -1815,16 +1789,28 @@ mpt_bus_reset(struct mpt_softc *mpt, int sleep_ok) REQ_STATE_DONE, sleep_ok, 5000); status = mpt->tmf_req->IOCStatus; + response = mpt->tmf_req->ResponseCode; mpt->tmf_req->state = REQ_STATE_FREE; + if (error) { - mpt_prt(mpt, "mpt_bus_reset: Reset timed-out." - "Resetting controller.\n"); - mpt_reset(mpt, /*reinit*/TRUE); + mpt_prt(mpt, "mpt_bus_reset: Reset timed-out. " + "Resetting controller.\n"); + mpt_reset(mpt, TRUE); return (ETIMEDOUT); - } else if ((status & MPI_IOCSTATUS_MASK) != MPI_SCSI_STATUS_SUCCESS) { - mpt_prt(mpt, "mpt_bus_reset: TMF Status %d." - "Resetting controller.\n", status); - mpt_reset(mpt, /*reinit*/TRUE); + } + + if ((status & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { + mpt_prt(mpt, "mpt_bus_reset: TMF IOC Status 0x%x. " + "Resetting controller.\n", status); + mpt_reset(mpt, TRUE); + return (EIO); + } + + if (response != MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED && + response != MPI_SCSITASKMGMT_RSP_TM_COMPLETE) { + mpt_prt(mpt, "mpt_bus_reset: TMF Response 0x%x. " + "Resetting controller.\n", response); + mpt_reset(mpt, TRUE); return (EIO); } return (0); @@ -1886,8 +1872,7 @@ mpt_cam_event(struct mpt_softc *mpt, request_t *req, case MPI_EVENT_RESCAN: /* - * In general this means a device has been added - * to the loop. + * In general this means a device has been added to the loop. */ mpt_prt(mpt, "Rescan Port: %d\n", (msg->Data[0] >> 8) & 0xff); /* xpt_async(AC_FOUND_DEVICE, path, NULL); */ @@ -2064,16 +2049,21 @@ mpt_scsi_reply_handler(struct mpt_softc *mpt, request_t *req, if ((req->state & REQ_STATE_TIMEDOUT) == 0) { TAILQ_REMOVE(&mpt->request_pending_list, req, links); } else { + mpt_prt(mpt, "completing timedout/aborted req %p:%u\n", + req, req->serno); TAILQ_REMOVE(&mpt->request_timeout_list, req, links); } if ((req->state & REQ_STATE_NEED_WAKEUP) == 0) { +#ifdef INVARIANTS + mpt_req_not_spcl(mpt, req, "mpt_scsi_reply_handler", __LINE__); +#endif mpt_free_request(mpt, req); - return (/*free_reply*/TRUE); + return (TRUE); } req->state &= ~REQ_STATE_QUEUED; req->state |= REQ_STATE_DONE; wakeup(req); - return (/*free_reply*/TRUE); + return (TRUE); } static int @@ -2081,17 +2071,18 @@ mpt_scsi_tmf_reply_handler(struct mpt_softc *mpt, request_t *req, uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame) { MSG_SCSI_TASK_MGMT_REPLY *tmf_reply; - uint16_t status; KASSERT(req == mpt->tmf_req, ("TMF Reply not using mpt->tmf_req")); - +#ifdef INVARIANTS + mpt_req_not_spcl(mpt, req, "mpt_scsi_tmf_reply_handler", __LINE__); +#endif tmf_reply = (MSG_SCSI_TASK_MGMT_REPLY *)reply_frame; + /* Record IOC Status and Response Code of TMF for any waiters. */ + req->IOCStatus = le16toh(tmf_reply->IOCStatus); + req->ResponseCode = tmf_reply->ResponseCode; - /* Record status of TMF for any waiters. */ - req->IOCStatus = tmf_reply->IOCStatus; - status = le16toh(tmf_reply->IOCStatus); mpt_lprt(mpt, MPT_PRT_INFO, "TMF complete: req %p:%u status 0x%x\n", - req, req->serno, status); + req, req->serno, le16toh(tmf_reply->IOCStatus)); TAILQ_REMOVE(&mpt->request_pending_list, req, links); if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) { req->state |= REQ_STATE_DONE; @@ -2193,10 +2184,22 @@ mpt_fc_els_reply_handler(struct mpt_softc *mpt, request_t *req, U8 cmd; U16 status = le16toh(reply_frame->IOCStatus); U32 *elsbuf; + int ioindex; int do_refresh = TRUE; - mpt_lprt(mpt, MPT_PRT_DEBUG, "FC_ELS Complete: req %p:%u, reply %p\n", - req, req->serno, reply_frame); +#ifdef INVARIANTS + KASSERT(mpt_req_on_free_list(mpt, req) == 0, + ("fc_els_reply_handler: req %p:%u for function %x on freelist!", + req, req->serno, rp->Function)); + if (rp->Function != MPI_FUNCTION_FC_PRIMITIVE_SEND) { + mpt_req_spcl(mpt, req, "fc_els_reply_handler", __LINE__); + } else { + mpt_req_not_spcl(mpt, req, "fc_els_reply_handler", __LINE__); + } +#endif + mpt_lprt(mpt, MPT_PRT_INVARIANT, + "FC_ELS Complete: req %p:%u, reply %p function %x\n", + req, req->serno, reply_frame, reply_frame->Function); if (status != MPI_IOCSTATUS_SUCCESS) { mpt_prt(mpt, "ELS REPLY STATUS 0x%x for Function %x\n", @@ -2214,18 +2217,38 @@ mpt_fc_els_reply_handler(struct mpt_softc *mpt, request_t *req, /* * If the function of a link service response, we recycle the * response to be a refresh for a new link service request. + * + * The request pointer is bogus in this case and we have to fetch + * it based upon the TransactionContext. */ if (rp->Function == MPI_FUNCTION_FC_LINK_SRVC_RSP) { - mpt_fc_add_els(mpt, req); + /* Freddie Uncle Charlie Katie */ + /* We don't get the IOINDEX as part of the Link Svc Rsp */ + for (ioindex = 0; ioindex < mpt->els_cmds_allocated; ioindex++) + if (mpt->els_cmd_ptrs[ioindex] == req) { + break; + } + + KASSERT(ioindex < mpt->els_cmds_allocated, + ("can't find my mommie!")); + + /* remove from active list as we're going to re-post it */ + TAILQ_REMOVE(&mpt->request_pending_list, req, links); + req->state &= ~REQ_STATE_QUEUED; + req->state |= REQ_STATE_DONE; + mpt_fc_post_els(mpt, req, ioindex); return (TRUE); } if (rp->Function == MPI_FUNCTION_FC_PRIMITIVE_SEND) { + /* remove from active list as we're done */ + 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) { 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, @@ -2246,8 +2269,8 @@ mpt_fc_els_reply_handler(struct mpt_softc *mpt, request_t *req, /* * This is just a ack of an original ELS buffer post */ - mpt_lprt(mpt, MPT_PRT_DEBUG, - "Recv'd ACK of FC_ELS buf post %p:%u\n", req, req->serno); + mpt_lprt(mpt, MPT_PRT_INVARIANT, + "RECV'd ACK of FC_ELS buf post %p:%u\n", req, req->serno); return (TRUE); } @@ -2263,6 +2286,8 @@ mpt_fc_els_reply_handler(struct mpt_softc *mpt, request_t *req, return (TRUE); } + ioindex = le32toh(rp->TransactionContext); + req = mpt->els_cmd_ptrs[ioindex]; if (rctl == ELS && type == 1) { switch (cmd) { @@ -2280,6 +2305,10 @@ mpt_fc_els_reply_handler(struct mpt_softc *mpt, request_t *req, elsbuf[4] |= htobe32(0x00000010); if (mpt->role & MPT_ROLE_INITIATOR) elsbuf[4] |= htobe32(0x00000020); + /* remove from active list as we're done */ + TAILQ_REMOVE(&mpt->request_pending_list, req, links); + req->state &= ~REQ_STATE_QUEUED; + req->state |= REQ_STATE_DONE; mpt_fc_els_send_response(mpt, req, rp, 20); do_refresh = FALSE; break; @@ -2290,6 +2319,10 @@ mpt_fc_els_reply_handler(struct mpt_softc *mpt, request_t *req, mpt_prt(mpt, "PRLO from 0x%08x%08x\n", le32toh(rp->Wwn.PortNameHigh), le32toh(rp->Wwn.PortNameLow)); + /* remove from active list as we're done */ + TAILQ_REMOVE(&mpt->request_pending_list, req, links); + req->state &= ~REQ_STATE_QUEUED; + req->state |= REQ_STATE_DONE; mpt_fc_els_send_response(mpt, req, rp, 20); do_refresh = FALSE; break; @@ -2367,13 +2400,21 @@ mpt_fc_els_reply_handler(struct mpt_softc *mpt, request_t *req, * will be correct. */ rp->Rctl_Did += ((BA_ACC - ABTS) << MPI_FC_RCTL_SHIFT); + /* remove from active list as we're done */ + TAILQ_REMOVE(&mpt->request_pending_list, req, links); + req->state &= ~REQ_STATE_QUEUED; + req->state |= REQ_STATE_DONE; mpt_fc_els_send_response(mpt, req, rp, 12); do_refresh = FALSE; } else { mpt_prt(mpt, "ELS: RCTL %x TYPE %x CMD %x\n", rctl, type, cmd); } if (do_refresh == TRUE) { - mpt_fc_add_els(mpt, req); + /* remove from active list as we're done */ + TAILQ_REMOVE(&mpt->request_pending_list, req, links); + req->state &= ~REQ_STATE_QUEUED; + req->state |= REQ_STATE_DONE; + mpt_fc_post_els(mpt, req, ioindex); } return (TRUE); } @@ -2393,6 +2434,10 @@ mpt_cam_ioc_reset(struct mpt_softc *mpt, int type) mpt_complete_request_chain(mpt, &mpt->request_timeout_list, MPI_IOCSTATUS_INVALID_STATE); + /* + * XXX: We need to repost ELS and Target Command Buffers? + */ + /* * Inform the XPT that a bus reset has occurred. */ @@ -2572,6 +2617,7 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mpt_action\n")); mpt = (struct mpt_softc *)cam_sim_softc(sim); + KASSERT(MPT_OWNED(mpt) == 0, ("mpt owned on entrance to mpt_action")); raid_passthru = (sim == mpt->phydisk_sim); tgt = ccb->ccb_h.target_id; @@ -2587,7 +2633,6 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) } MPTLOCK_2_CAMLOCK(mpt); } - ccb->ccb_h.ccb_mpt_ptr = mpt; switch (ccb->ccb_h.func_code) { @@ -2678,121 +2723,125 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) #define DP_SYNC 0x40 case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */ + { +#ifdef CAM_NEW_TRAN_CODE + struct ccb_trans_settings_scsi *scsi; + struct ccb_trans_settings_spi *spi; +#endif + uint8_t dval; + u_int period; + u_int offset; + int m; + cts = &ccb->cts; if (!IS_CURRENT_SETTINGS(cts)) { mpt_prt(mpt, "Attempt to set User settings\n"); - ccb->ccb_h.status &= ~CAM_SIM_QUEUED; mpt_set_ccb_status(ccb, CAM_REQ_INVALID); xpt_done(ccb); break; } - if (mpt->is_fc == 0 && mpt->is_sas == 0) { - uint8_t dval = 0; - u_int period = 0, offset = 0; -#ifndef CAM_NEW_TRAN_CODE - if (cts->valid & CCB_TRANS_DISC_VALID) { - dval |= DP_DISC_ENABLE; - } - if (cts->valid & CCB_TRANS_TQ_VALID) { - dval |= DP_TQING_ENABLE; - } - if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) { - if (cts->bus_width) - dval |= DP_WIDE; - else - dval |= DP_NARROW; - } - /* - * Any SYNC RATE of nonzero and SYNC_OFFSET - * of nonzero will cause us to go to the - * selected (from NVRAM) maximum value for - * this device. At a later point, we'll - * allow finer control. - */ - if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) && - (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)) { - dval |= DP_SYNC; - period = cts->sync_period; - offset = cts->sync_offset; - } -#else - struct ccb_trans_settings_scsi *scsi = - &cts->proto_specific.scsi; - struct ccb_trans_settings_spi *spi = - &cts->xport_specific.spi; - - if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { - if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) - dval |= DP_DISC_ENABLE; - else - dval |= DP_DISC_DISABL; - } - - if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { - if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) - dval |= DP_TQING_ENABLE; - else - dval |= DP_TQING_DISABL; - } - - if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { - if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT) - dval |= DP_WIDE; - else - dval |= DP_NARROW; - } - - if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) && - (spi->valid & CTS_SPI_VALID_SYNC_RATE) && - (spi->sync_period && spi->sync_offset)) { - dval |= DP_SYNC; - period = spi->sync_period; - offset = spi->sync_offset; - } -#endif - CAMLOCK_2_MPTLOCK(mpt); - if (dval & DP_DISC_ENABLE) { - mpt->mpt_disc_enable |= (1 << tgt); - } else if (dval & DP_DISC_DISABL) { - mpt->mpt_disc_enable &= ~(1 << tgt); - } - if (dval & DP_TQING_ENABLE) { - mpt->mpt_tag_enable |= (1 << tgt); - } else if (dval & DP_TQING_DISABL) { - mpt->mpt_tag_enable &= ~(1 << tgt); - } - if (dval & DP_WIDTH) { - if (mpt_setwidth(mpt, tgt, dval & DP_WIDE)) { - mpt_prt(mpt, "Set width Failed!\n"); - ccb->ccb_h.status &= ~CAM_SIM_QUEUED; - mpt_set_ccb_status(ccb, - CAM_REQ_CMP_ERR); - MPTLOCK_2_CAMLOCK(mpt); - xpt_done(ccb); - break; - } - } - if (dval & DP_SYNC) { - if (mpt_setsync(mpt, tgt, period, offset)) { - mpt_prt(mpt, "Set sync Failed!\n"); - ccb->ccb_h.status &= ~CAM_SIM_QUEUED; - mpt_set_ccb_status(ccb, - CAM_REQ_CMP_ERR); - MPTLOCK_2_CAMLOCK(mpt); - xpt_done(ccb); - break; - } - } - MPTLOCK_2_CAMLOCK(mpt); - mpt_lprt(mpt, MPT_PRT_DEBUG, - "SET tgt %d flags %x period %x off %x\n", - tgt, dval, period, offset); + if (mpt->is_fc || mpt->is_sas) { + mpt_set_ccb_status(ccb, CAM_REQ_CMP); + xpt_done(ccb); + break; } - ccb->ccb_h.status &= ~CAM_SIM_QUEUED; + + m = mpt->mpt_port_page2.PortSettings; + if ((m & MPI_SCSIPORTPAGE2_PORT_MASK_NEGO_MASTER_SETTINGS) == + MPI_SCSIPORTPAGE2_PORT_ALL_MASTER_SETTINGS) { + mpt_set_ccb_status(ccb, CAM_REQ_CMP); + xpt_done(ccb); + break; + } + + dval = 0; + period = 0; + offset = 0; + +#ifndef CAM_NEW_TRAN_CODE + if (cts->valid & CCB_TRANS_DISC_VALID) { + dval |= DP_DISC_ENABLE; + } + if (cts->valid & CCB_TRANS_TQ_VALID) { + dval |= DP_TQING_ENABLE; + } + if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) { + if (cts->bus_width) + dval |= DP_WIDE; + else + dval |= DP_NARROW; + } + /* + * Any SYNC RATE of nonzero and SYNC_OFFSET + * of nonzero will cause us to go to the + * selected (from NVRAM) maximum value for + * this device. At a later point, we'll + * allow finer control. + */ + if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) && + (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)) { + dval |= DP_SYNC; + period = cts->sync_period; + offset = cts->sync_offset; + } +#else + scsi = &cts->proto_specific.scsi; + spi = &cts->xport_specific.spi; + + if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { + if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) + dval |= DP_DISC_ENABLE; + else + dval |= DP_DISC_DISABL; + } + + if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { + if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) + dval |= DP_TQING_ENABLE; + else + dval |= DP_TQING_DISABL; + } + + if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { + if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT) + dval |= DP_WIDE; + else + dval |= DP_NARROW; + } + + if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) && + (spi->valid & CTS_SPI_VALID_SYNC_RATE) && + (spi->sync_period && spi->sync_offset)) { + dval |= DP_SYNC; + period = spi->sync_period; + offset = spi->sync_offset; + } +#endif + CAMLOCK_2_MPTLOCK(mpt); + if (dval & DP_DISC_ENABLE) { + mpt->mpt_disc_enable |= (1 << tgt); + } else if (dval & DP_DISC_DISABL) { + mpt->mpt_disc_enable &= ~(1 << tgt); + } + if (dval & DP_TQING_ENABLE) { + mpt->mpt_tag_enable |= (1 << tgt); + } else if (dval & DP_TQING_DISABL) { + mpt->mpt_tag_enable &= ~(1 << tgt); + } + if (dval & DP_WIDTH) { + mpt_setwidth(mpt, tgt, 1); + } + if (dval & DP_SYNC) { + mpt_setsync(mpt, tgt, period, offset); + } + MPTLOCK_2_CAMLOCK(mpt); + mpt_lprt(mpt, MPT_PRT_DEBUG, + "SET tgt %d flags %x period %x off %x\n", + tgt, dval, period, offset); mpt_set_ccb_status(ccb, CAM_REQ_CMP); xpt_done(ccb); break; - + } case XPT_GET_TRAN_SETTINGS: cts = &ccb->cts; if (mpt->is_fc) { @@ -2848,128 +2897,12 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) sas->bitrate = 300000; /* XXX: Default 3Gbps */ #endif } else { -#ifdef CAM_NEW_TRAN_CODE - struct ccb_trans_settings_scsi *scsi = - &cts->proto_specific.scsi; - struct ccb_trans_settings_spi *spi = - &cts->xport_specific.spi; -#endif - uint8_t dval, pval, oval; - int rv; - - /* - * We aren't going off of Port PAGE2 params for - * tagged queuing or disconnect capabilities - * for current settings. For goal settings, - * we assert all capabilities- we've had some - * problems with reading NVRAM data. - */ - if (IS_CURRENT_SETTINGS(cts)) { - CONFIG_PAGE_SCSI_DEVICE_0 tmp; - dval = 0; - - tmp = mpt->mpt_dev_page0[tgt]; - CAMLOCK_2_MPTLOCK(mpt); - rv = mpt_read_cur_cfg_page(mpt, tgt, - &tmp.Header, - sizeof(tmp), - /*sleep_ok*/FALSE, - /*timeout_ms*/5000); - if (rv) { - mpt_prt(mpt, - "cannot get target %d DP0\n", tgt); - } - mpt_lprt(mpt, MPT_PRT_DEBUG, - "SPI Tgt %d Page 0: NParms %x " - "Information %x\n", tgt, - tmp.NegotiatedParameters, - tmp.Information); - MPTLOCK_2_CAMLOCK(mpt); - - if (tmp.NegotiatedParameters & - MPI_SCSIDEVPAGE0_NP_WIDE) - dval |= DP_WIDE; - - if (mpt->mpt_disc_enable & (1 << tgt)) { - dval |= DP_DISC_ENABLE; - } - if (mpt->mpt_tag_enable & (1 << tgt)) { - dval |= DP_TQING_ENABLE; - } - oval = (tmp.NegotiatedParameters >> 16) & 0xff; - pval = (tmp.NegotiatedParameters >> 8) & 0xff; - } else { - /* - * XXX: Fix wrt NVRAM someday. Attempts - * XXX: to read port page2 device data - * XXX: just returns zero in these areas. - */ - dval = DP_WIDE|DP_DISC|DP_TQING; - oval = (mpt->mpt_port_page0.Capabilities >> 16); - pval = (mpt->mpt_port_page0.Capabilities >> 8); + if (mpt_get_spi_settings(mpt, cts) != 0) { + mpt_set_ccb_status(ccb, CAM_REQ_CMP_ERR); + xpt_done(ccb); + return; } -#ifndef CAM_NEW_TRAN_CODE - cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); - if (dval & DP_DISC_ENABLE) { - cts->flags |= CCB_TRANS_DISC_ENB; - } - if (dval & DP_TQING_ENABLE) { - cts->flags |= CCB_TRANS_TAG_ENB; - } - if (dval & DP_WIDE) { - cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; - } else { - cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; - } - cts->valid = CCB_TRANS_BUS_WIDTH_VALID | - CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; - if (oval) { - cts->sync_period = pval; - cts->sync_offset = oval; - cts->valid |= - CCB_TRANS_SYNC_RATE_VALID | - CCB_TRANS_SYNC_OFFSET_VALID; - } -#else - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_SPI; - cts->transport_version = 2; - - scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; - spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; - if (dval & DP_DISC_ENABLE) { - spi->flags |= CTS_SPI_FLAGS_DISC_ENB; - } - if (dval & DP_TQING_ENABLE) { - scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; - } - if (oval && pval) { - spi->sync_offset = oval; - spi->sync_period = pval; - spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; - spi->valid |= CTS_SPI_VALID_SYNC_RATE; - } - spi->valid |= CTS_SPI_VALID_BUS_WIDTH; - if (dval & DP_WIDE) { - spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; - } else { - spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; - } - if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { - scsi->valid = CTS_SCSI_VALID_TQ; - spi->valid |= CTS_SPI_VALID_DISC; - } else { - scsi->valid = 0; - } -#endif - mpt_lprt(mpt, MPT_PRT_DEBUG, - "GET %s tgt %d flags %x period %x offset %x\n", - IS_CURRENT_SETTINGS(cts) - ? "ACTIVE" : "NVRAM", - tgt, dval, pval, oval); } - ccb->ccb_h.status &= ~CAM_SIM_QUEUED; mpt_set_ccb_status(ccb, CAM_REQ_CMP); xpt_done(ccb); break; @@ -3127,49 +3060,153 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) } static int -mpt_setwidth(struct mpt_softc *mpt, int tgt, int onoff) +mpt_get_spi_settings(struct mpt_softc *mpt, struct ccb_trans_settings *cts) { - CONFIG_PAGE_SCSI_DEVICE_1 tmp; +#ifdef CAM_NEW_TRAN_CODE + struct ccb_trans_settings_scsi *scsi = + &cts->proto_specific.scsi; + struct ccb_trans_settings_spi *spi = + &cts->xport_specific.spi; +#endif + int tgt; + uint8_t dval, pval, oval; int rv; - tmp = mpt->mpt_dev_page1[tgt]; - if (onoff) { - tmp.RequestedParameters |= MPI_SCSIDEVPAGE1_RP_WIDE; + + tgt = cts->ccb_h.target_id; + + /* + * We aren't going off of Port PAGE2 params for + * tagged queuing or disconnect capabilities + * for current settings. For goal settings, + * we assert all capabilities- we've had some + * problems with reading NVRAM data. + */ + if (IS_CURRENT_SETTINGS(cts)) { + CONFIG_PAGE_SCSI_DEVICE_0 tmp; + dval = 0; + + CAMLOCK_2_MPTLOCK(mpt); + tmp = mpt->mpt_dev_page0[tgt]; + rv = mpt_read_cur_cfg_page(mpt, tgt, &tmp.Header, + sizeof(tmp), FALSE, 5000); + if (rv) { + MPTLOCK_2_CAMLOCK(mpt); + mpt_prt(mpt, "can't get tgt %d config page 0\n", tgt); + return (rv); + } + MPTLOCK_2_CAMLOCK(mpt); + + mpt_lprt(mpt, MPT_PRT_DEBUG, + "mpt_get_spi: SPI Tgt %d Page 0: NParms %x Info %x\n", + tgt, tmp.NegotiatedParameters, tmp.Information); + if (tmp.NegotiatedParameters & MPI_SCSIDEVPAGE0_NP_WIDE) { + dval |= DP_WIDE; + } + if (mpt->mpt_disc_enable & (1 << tgt)) { + dval |= DP_DISC_ENABLE; + } + if (mpt->mpt_tag_enable & (1 << tgt)) { + dval |= DP_TQING_ENABLE; + } + oval = (tmp.NegotiatedParameters >> 16) & 0xff; + pval = (tmp.NegotiatedParameters >> 8) & 0xff; } else { - tmp.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_WIDE; + /* + * XXX: Fix wrt NVRAM someday. Attempts + * XXX: to read port page2 device data + * XXX: just returns zero in these areas. + */ + dval = DP_WIDE|DP_DISC|DP_TQING; + oval = (mpt->mpt_port_page0.Capabilities >> 16); + pval = (mpt->mpt_port_page0.Capabilities >> 8); } - rv = mpt_write_cur_cfg_page(mpt, tgt, &tmp.Header, sizeof(tmp), - /*sleep_ok*/FALSE, /*timeout_ms*/5000); - if (rv) { - mpt_prt(mpt, "mpt_setwidth: write cur page failed\n"); - return (-1); +#ifndef CAM_NEW_TRAN_CODE + cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); + if (dval & DP_DISC_ENABLE) { + cts->flags |= CCB_TRANS_DISC_ENB; } - rv = mpt_read_cur_cfg_page(mpt, tgt, &tmp.Header, sizeof(tmp), - /*sleep_ok*/FALSE, /*timeout_ms*/5000); - if (rv) { - mpt_prt(mpt, "mpt_setwidth: read cur page failed\n"); - return (-1); + if (dval & DP_TQING_ENABLE) { + cts->flags |= CCB_TRANS_TAG_ENB; } - mpt->mpt_dev_page1[tgt] = tmp; + if (dval & DP_WIDE) { + cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; + } else { + cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; + } + cts->valid = CCB_TRANS_BUS_WIDTH_VALID | + CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; + if (oval) { + cts->sync_period = pval; + cts->sync_offset = oval; + cts->valid |= + CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID; + } +#else + cts->protocol = PROTO_SCSI; + cts->protocol_version = SCSI_REV_2; + cts->transport = XPORT_SPI; + cts->transport_version = 2; + + scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; + spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; + if (dval & DP_DISC_ENABLE) { + spi->flags |= CTS_SPI_FLAGS_DISC_ENB; + } + if (dval & DP_TQING_ENABLE) { + scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; + } + if (oval && pval) { + spi->sync_offset = oval; + spi->sync_period = pval; + spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; + spi->valid |= CTS_SPI_VALID_SYNC_RATE; + } + spi->valid |= CTS_SPI_VALID_BUS_WIDTH; + if (dval & DP_WIDE) { + spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; + } else { + spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; + } + if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { + scsi->valid = CTS_SCSI_VALID_TQ; + spi->valid |= CTS_SPI_VALID_DISC; + } else { + scsi->valid = 0; + } +#endif mpt_lprt(mpt, MPT_PRT_DEBUG, - "SPI Target %d Page 1: RequestedParameters %x Config %x\n", - tgt, mpt->mpt_dev_page1[tgt].RequestedParameters, - mpt->mpt_dev_page1[tgt].Configuration); + "mpt_get_spi: tgt %d %s settings flags %x period %x offset %x\n", + tgt, IS_CURRENT_SETTINGS(cts)? "ACTIVE" : "NVRAM", + dval, pval, oval); return (0); } -static int +static void +mpt_setwidth(struct mpt_softc *mpt, int tgt, int onoff) +{ + PTR_CONFIG_PAGE_SCSI_DEVICE_1 tmp; + + tmp = &mpt->mpt_dev_page1[tgt]; + if (onoff) { + tmp->RequestedParameters |= MPI_SCSIDEVPAGE1_RP_WIDE; + } else { + tmp->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_WIDE; + } +} + +static void mpt_setsync(struct mpt_softc *mpt, int tgt, int period, int offset) { - CONFIG_PAGE_SCSI_DEVICE_1 tmp; - int rv; + PTR_CONFIG_PAGE_SCSI_DEVICE_1 tmp; + + tmp = &mpt->mpt_dev_page1[tgt]; + tmp->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK; + tmp->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK; + tmp->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_DT; + tmp->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_QAS; + tmp->RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_IU; - tmp = mpt->mpt_dev_page1[tgt]; - tmp.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK; - tmp.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK; - tmp.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_DT; - tmp.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_QAS; - tmp.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_IU; /* * XXX: For now, we're ignoring specific settings */ @@ -3186,25 +3223,34 @@ mpt_setsync(struct mpt_softc *mpt, int tgt, int period, int offset) np |= MPI_SCSIDEVPAGE1_RP_DT; } np |= (factor << 8) | (offset << 16); - tmp.RequestedParameters |= np; + tmp->RequestedParameters |= np; } - rv = mpt_write_cur_cfg_page(mpt, tgt, &tmp.Header, sizeof(tmp), - /*sleep_ok*/FALSE, /*timeout_ms*/5000); +} + +static int +mpt_update_spi_config(struct mpt_softc *mpt, int tgt) +{ + CONFIG_PAGE_SCSI_DEVICE_1 tmp; + int rv; + + tmp = mpt->mpt_dev_page1[tgt]; + rv = mpt_write_cur_cfg_page(mpt, tgt, + &tmp.Header, sizeof(tmp), FALSE, 5000); if (rv) { - mpt_prt(mpt, "mpt_setsync: write cur page failed\n"); + mpt_prt(mpt, "mpt_update_spi_config: write cur page failed\n"); return (-1); } - rv = mpt_read_cur_cfg_page(mpt, tgt, &tmp.Header, sizeof(tmp), - /*sleep_ok*/FALSE, /*timeout_ms*/500); + rv = mpt_read_cur_cfg_page(mpt, tgt, + &tmp.Header, sizeof(tmp), FALSE, 500); if (rv) { - mpt_prt(mpt, "mpt_setsync: read cur page failed\n"); + mpt_prt(mpt, "mpt_update_spi_config: read cur page failed\n"); return (-1); } mpt->mpt_dev_page1[tgt] = tmp; mpt_lprt(mpt, MPT_PRT_DEBUG, - "SPI Target %d Page 1: RParams %x Config %x\n", - tgt, mpt->mpt_dev_page1[tgt].RequestedParameters, - mpt->mpt_dev_page1[tgt].Configuration); + "mpt_update_spi_config[%d]: Page 1: RParams %x Config %x\n", tgt, + mpt->mpt_dev_page1[tgt].RequestedParameters, + mpt->mpt_dev_page1[tgt].Configuration); return (0); } @@ -3273,11 +3319,11 @@ mpt_recovery_thread(void *arg) mpt = (struct mpt_softc *)arg; MPT_LOCK(mpt); for (;;) { - - if (TAILQ_EMPTY(&mpt->request_timeout_list) != 0 - && mpt->shutdwn_recovery == 0) - mpt_sleep(mpt, mpt, PUSER, "idle", 0); - + if (TAILQ_EMPTY(&mpt->request_timeout_list) != 0) { + if (mpt->shutdwn_recovery == 0) { + mpt_sleep(mpt, mpt, PUSER, "idle", 0); + } + } if (mpt->shutdwn_recovery != 0) { break; } @@ -3303,18 +3349,15 @@ mpt_scsi_send_tmf(struct mpt_softc *mpt, u_int type, u_int flags, * Wait for any current TMF request to complete. * We're only allowed to issue one TMF at a time. */ - error = mpt_wait_req(mpt, mpt->tmf_req, REQ_STATE_FREE, REQ_STATE_MASK, + error = mpt_wait_req(mpt, mpt->tmf_req, REQ_STATE_FREE, REQ_STATE_FREE, sleep_ok, MPT_TMF_MAX_TIMEOUT); if (error != 0) { mpt_reset(mpt, TRUE); return (ETIMEDOUT); } - if ((mpt->tmf_req->serno = mpt->sequence++) == 0) { - mpt->tmf_req->serno = mpt->sequence++; - } + mpt_assign_serno(mpt, mpt->tmf_req); mpt->tmf_req->state = REQ_STATE_ALLOCATED|REQ_STATE_QUEUED; - TAILQ_INSERT_HEAD(&mpt->request_pending_list, mpt->tmf_req, links); tmf_req = (MSG_SCSI_TASK_MGMT *)mpt->tmf_req->req_vbuf; memset(tmf_req, 0, sizeof(*tmf_req)); @@ -3341,15 +3384,14 @@ mpt_scsi_send_tmf(struct mpt_softc *mpt, u_int type, u_int flags, mpt_lprt(mpt, MPT_PRT_INFO, "Issuing TMF %p:%u with MsgContext of 0x%x\n", mpt->tmf_req, mpt->tmf_req->serno, tmf_req->MsgContext); - if (mpt->verbose > MPT_PRT_DEBUG) + if (mpt->verbose > MPT_PRT_DEBUG) { mpt_print_request(tmf_req); - - if (mpt->is_fc || mpt->is_sas) { - mpt_send_cmd(mpt, mpt->tmf_req); - error = MPT_OK; - } else { - error = mpt_send_handshake_cmd(mpt, sizeof(*tmf_req), tmf_req); } + + KASSERT(mpt_req_on_pending_list(mpt, mpt->tmf_req) == 0, + ("mpt_scsi_send_tmf: tmf_req already on pending list")); + TAILQ_INSERT_HEAD(&mpt->request_pending_list, mpt->tmf_req, links); + error = mpt_send_handshake_cmd(mpt, sizeof(*tmf_req), tmf_req); if (error != MPT_OK) { mpt_reset(mpt, TRUE); } @@ -3402,15 +3444,44 @@ mpt_recover_commands(struct mpt_softc *mpt) /* * We have no visibility into the current state of the * controller, so attempt to abort the commands in the - * order they timed-out. + * order they timed-out. For initiator commands, we + * depend on the reply handler pulling requests off + * the timeout list. */ while ((req = TAILQ_FIRST(&mpt->request_timeout_list)) != NULL) { - u_int status; + uint16_t status; + uint8_t response; + MSG_REQUEST_HEADER *hdrp = req->req_vbuf; - mpt_prt(mpt, - "Attempting to abort req %p:%u\n", req, req->serno); + mpt_prt(mpt, "attempting to abort req %p:%u function %x\n", + req, req->serno, hdrp->Function); ccb = req->ccb; + if (ccb == NULL) { + mpt_prt(mpt, "null ccb in timed out request. " + "Resetting Controller.\n"); + mpt_reset(mpt, TRUE); + continue; + } mpt_set_ccb_status(ccb, CAM_CMD_TIMEOUT); + + /* + * Check to see if this is not an initiator command and + * deal with it differently if it is. + */ + switch (hdrp->Function) { + case MPI_FUNCTION_SCSI_IO_REQUEST: + break; + default: + /* + * XXX: FIX ME: need to abort target assists... + */ + mpt_prt(mpt, "just putting it back on the pend q\n"); + TAILQ_REMOVE(&mpt->request_timeout_list, req, links); + TAILQ_INSERT_HEAD(&mpt->request_pending_list, req, + links); + continue; + } + error = mpt_scsi_send_tmf(mpt, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, 0, 0, ccb->ccb_h.target_id, ccb->ccb_h.target_lun, @@ -3428,46 +3499,41 @@ mpt_recover_commands(struct mpt_softc *mpt) error = mpt_wait_req(mpt, mpt->tmf_req, REQ_STATE_DONE, REQ_STATE_DONE, TRUE, 500); + status = mpt->tmf_req->IOCStatus; + response = mpt->tmf_req->ResponseCode; + mpt->tmf_req->state = REQ_STATE_FREE; + if (error != 0) { /* - * If we've errored out and the transaction is still - * pending, reset the controller. + * If we've errored out,, reset the controller. */ mpt_prt(mpt, "mpt_recover_commands: abort timed-out. " - "Resetting controller\n"); + "Resetting controller\n"); mpt_reset(mpt, TRUE); continue; } - /* - * TMF is complete. - */ - TAILQ_REMOVE(&mpt->request_timeout_list, req, links); - mpt->tmf_req->state = REQ_STATE_FREE; - - status = mpt->tmf_req->IOCStatus; - if ((status & MPI_IOCSTATUS_MASK) == MPI_SCSI_STATUS_SUCCESS) { - mpt_prt(mpt, "abort of req %p:%u completed\n", - req, req->serno); + if ((status & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { + mpt_prt(mpt, "mpt_recover_commands: IOC Status 0x%x. " + "Resetting controller.\n", status); + mpt_reset(mpt, TRUE); continue; } - mpt_lprt(mpt, MPT_PRT_DEBUG, "mpt_recover_commands: abort of " - "%p:%u failed with status 0x%x\n. Resetting controller.", - req, req->serno, status); - - /* - * If the abort attempt fails for any reason, reset the bus. - * We should find all of the timed-out commands on our - * list are in the done state after this completes. - */ - mpt_bus_reset(mpt, TRUE); + if (response != MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED && + response != MPI_SCSITASKMGMT_RSP_TM_COMPLETE) { + mpt_prt(mpt, "mpt_recover_commands: TMF Response 0x%x. " + "Resetting controller.\n", response); + mpt_reset(mpt, TRUE); + continue; + } + mpt_prt(mpt, "abort of req %p:%u completed\n", req, req->serno); } } /************************ Target Mode Support ****************************/ static void -mpt_fc_add_els(struct mpt_softc *mpt, request_t *req) +mpt_fc_post_els(struct mpt_softc *mpt, request_t *req, int ioindex) { MSG_LINK_SERVICE_BUFFER_POST_REQUEST *fc; PTR_SGE_TRANSACTION32 tep; @@ -3494,7 +3560,7 @@ mpt_fc_add_els(struct mpt_softc *mpt, request_t *req) tep->ContextSize = 4; tep->Flags = 0; - tep->TransactionContext[0] = htole32(req->index | fc_els_handler_id); + tep->TransactionContext[0] = htole32(ioindex); se = (PTR_SGE_SIMPLE32) &tep->TransactionDetails[0]; se->FlagsLength = @@ -3506,7 +3572,11 @@ mpt_fc_add_els(struct mpt_softc *mpt, request_t *req) se->FlagsLength <<= MPI_SGE_FLAGS_SHIFT; se->FlagsLength |= (MPT_NRFM(mpt) - MPT_RQSL(mpt)); se->Address = (uint32_t) paddr; - mpt_check_doorbell(mpt); + mpt_lprt(mpt, MPT_PRT_INVARIANT, + "add ELS index %d ioindex %d for %p:%u\n", + req->index, ioindex, req, req->serno); + KASSERT(((req->state & REQ_STATE_LOCKED) != 0), + ("mpt_fc_post_els: request not locked")); mpt_send_cmd(mpt, req); } @@ -3535,13 +3605,60 @@ mpt_post_target_command(struct mpt_softc *mpt, request_t *req, int ioindex) mpt_send_cmd(mpt, req); } -static void +static int +mpt_add_els_buffers(struct mpt_softc *mpt) +{ + int i; + + if (mpt->is_fc == 0) { + return (TRUE); + } + + if (mpt->els_cmds_allocated) { + return (TRUE); + } + + mpt->els_cmd_ptrs = malloc(MPT_MAX_ELS * sizeof (request_t *), + M_DEVBUF, M_NOWAIT | M_ZERO); + + if (mpt->els_cmd_ptrs == NULL) { + return (FALSE); + } + + /* + * Feed the chip some ELS buffer resources + */ + for (i = 0; i < MPT_MAX_ELS; i++) { + request_t *req = mpt_get_request(mpt, FALSE); + if (req == NULL) { + break; + } + req->state |= REQ_STATE_LOCKED; + mpt->els_cmd_ptrs[i] = req; + mpt_fc_post_els(mpt, req, i); + } + + if (i == 0) { + mpt_prt(mpt, "unable to add ELS buffer resources\n"); + free(mpt->els_cmd_ptrs, M_DEVBUF); + mpt->els_cmd_ptrs = NULL; + return (FALSE); + } + if (i != MPT_MAX_ELS) { + mpt_lprt(mpt, MPT_PRT_INFO, + "only added %d of %d ELS buffers\n", i, MPT_MAX_ELS); + } + mpt->els_cmds_allocated = i; + return(TRUE); +} + +static int mpt_add_target_commands(struct mpt_softc *mpt) { int i, max; if (mpt->tgt_cmd_ptrs) { - return; + return (TRUE); } max = MPT_MAX_REQUESTS(mpt) >> 1; @@ -3549,12 +3666,12 @@ mpt_add_target_commands(struct mpt_softc *mpt) max = mpt->mpt_max_tgtcmds; } mpt->tgt_cmd_ptrs = - malloc(max * sizeof (void *), M_DEVBUF, M_NOWAIT | M_ZERO); + malloc(max * sizeof (request_t *), M_DEVBUF, M_NOWAIT | M_ZERO); if (mpt->tgt_cmd_ptrs == NULL) { - mpt_prt(mpt, "could not allocate cmdptrs\n"); - return; + mpt_prt(mpt, + "mpt_add_target_commands: could not allocate cmd ptrs\n"); + return (FALSE); } - mpt->tgt_cmds_allocated = max; for (i = 0; i < max; i++) { request_t *req; @@ -3568,17 +3685,36 @@ mpt_add_target_commands(struct mpt_softc *mpt) mpt_post_target_command(mpt, req, i); } + if (i == 0) { mpt_lprt(mpt, MPT_PRT_ERROR, "could not add any target bufs\n"); free(mpt->tgt_cmd_ptrs, M_DEVBUF); mpt->tgt_cmd_ptrs = NULL; - mpt->tgt_cmds_allocated = 0; - } else if (i < max) { - mpt_lprt(mpt, MPT_PRT_WARN, "added %d of %d target bufs\n", - i, max); + return (FALSE); } + + mpt->tgt_cmds_allocated = i; + + if (i < max) { + mpt_lprt(mpt, MPT_PRT_INFO, + "added %d of %d target bufs\n", i, max); + } + 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) { @@ -3590,11 +3726,16 @@ mpt_enable_lun(struct mpt_softc *mpt, target_id_t tgt, lun_id_t lun) return (EINVAL); } if (mpt->tenabled == 0) { -#if 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); } -#endif mpt->tenabled = 1; } if (lun == CAM_LUN_WILDCARD) { @@ -3627,12 +3768,12 @@ mpt_disable_lun(struct mpt_softc *mpt, target_id_t tgt, lun_id_t lun) } } if (i == MPT_MAX_LUNS && mpt->twildcard == 0) { - mpt->tenabled = 0; -#if 0 + mpt_free_els_buffers(mpt); + mpt_free_target_commands(mpt); if (mpt->is_fc) { (void) mpt_fc_reset_link(mpt, 0); } -#endif + mpt->tenabled = 0; } return (0); } @@ -3647,9 +3788,21 @@ mpt_target_start_io(struct mpt_softc *mpt, union ccb *ccb) request_t *cmd_req = MPT_TAG_2_REQ(mpt, csio->tag_id); mpt_tgt_state_t *tgt = MPT_TGT_STATE(mpt, cmd_req); - if (tgt->state != TGT_STATE_IN_CAM) { - mpt_prt(mpt, "ccb flags 0x%x tag 0x%08x had bad request " - "starting I/O\n", csio->ccb_h.flags, csio->tag_id); + switch (tgt->state) { + case TGT_STATE_IN_CAM: + break; + case TGT_STATE_MOVING_DATA: + mpt_set_ccb_status(ccb, CAM_REQUEUE_REQ); + xpt_freeze_simq(mpt->sim, 1); + ccb->ccb_h.status &= ~CAM_SIM_QUEUED; + tgt->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; + MPTLOCK_2_CAMLOCK(mpt); + xpt_done(ccb); + CAMLOCK_2_MPTLOCK(mpt); + return; + default: + mpt_prt(mpt, "ccb %p flags 0x%x tag 0x%08x had bad request " + "starting I/O\n", ccb, csio->ccb_h.flags, csio->tag_id); mpt_tgt_dump_req_state(mpt, cmd_req); mpt_set_ccb_status(ccb, CAM_REQ_CMP_ERR); MPTLOCK_2_CAMLOCK(mpt); @@ -3988,7 +4141,7 @@ mpt_scsi_tgt_status(struct mpt_softc *mpt, union ccb *ccb, request_t *cmd_req, rsp[2] = status; if (tgt->resid) { - rsp[2] |= 0x800; + rsp[2] |= 0x800; /* XXXX NEED MNEMONIC!!!! */ rsp[3] = htobe32(tgt->resid); #ifdef WE_TRUST_AUTO_GOOD_STATUS resplen = sizeof (MPI_TARGET_FCP_RSP_BUFFER); @@ -3997,7 +4150,7 @@ mpt_scsi_tgt_status(struct mpt_softc *mpt, union ccb *ccb, request_t *cmd_req, if (status == SCSI_STATUS_CHECK_COND) { int i; - rsp[2] |= 0x200; + rsp[2] |= 0x200; /* XXXX NEED MNEMONIC!!!! */ rsp[4] = htobe32(MPT_SENSE_SIZE); memcpy(&rsp[8], sense_data, MPT_SENSE_SIZE); for (i = 8; i < (8 + (MPT_SENSE_SIZE >> 2)); i++) { @@ -4049,7 +4202,7 @@ mpt_scsi_tgt_status(struct mpt_softc *mpt, union ccb *ccb, request_t *cmd_req, req->serno, tgt->resid); if (ccb) { ccb->ccb_h.status = CAM_SIM_QUEUED | CAM_REQ_INPROG; - ccb->ccb_h.timeout_ch = timeout(mpt_timeout, (caddr_t)ccb, hz); + ccb->ccb_h.timeout_ch = timeout(mpt_timeout, ccb, 60 * hz); } mpt_send_cmd(mpt, req); } @@ -4318,7 +4471,7 @@ mpt_tgt_dump_tgt_state(struct mpt_softc *mpt, request_t *req) mpt_tgt_state_t *tgt = MPT_TGT_STATE(mpt, req); mpt_prt(mpt, "req %p:%u tgt:rdesc 0x%x resid %u xfrd %u ccb %p treq %p " - "nx %d tag %08x state=%d\n", req, req->serno, tgt->reply_desc, + "nx %d tag 0x%08x state=%d\n", req, req->serno, tgt->reply_desc, tgt->resid, tgt->bytes_xfered, tgt->ccb, tgt->req, tgt->nxfers, tgt->tag_id, tgt->state); } @@ -4341,20 +4494,22 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, if (reply_frame == NULL) { /* - * Figure out if this is a new command or a target assist - * completing. + * Figure out what the state of the command is. */ mpt_tgt_state_t *tgt = MPT_TGT_STATE(mpt, req); - char serno[8]; +#ifdef INVARIANTS + mpt_req_spcl(mpt, req, "turbo scsi_tgt_reply", __LINE__); if (tgt->req) { - snprintf(serno, 8, "%u", tgt->req->serno); - } else { - strncpy(serno, "??", 8); + mpt_req_not_spcl(mpt, tgt->req, + "turbo scsi_tgt_reply associated req", __LINE__); } - +#endif switch(tgt->state) { case TGT_STATE_LOADED: + /* + * This is a new command starting. + */ mpt_scsi_tgt_atio(mpt, req, reply_desc); break; case TGT_STATE_MOVING_DATA: @@ -4362,20 +4517,33 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, uint8_t *sp = NULL, sense[MPT_SENSE_SIZE]; ccb = tgt->ccb; + if (tgt->req == NULL) { + panic("mpt: turbo target reply with null " + "associated request moving data"); + /* NOTREACHED */ + } + if (ccb == NULL) { + panic("mpt: turbo target reply with null " + "associated ccb moving data"); + /* NOTREACHED */ + } tgt->ccb = NULL; tgt->nxfers++; untimeout(mpt_timeout, ccb, ccb->ccb_h.timeout_ch); mpt_lprt(mpt, MPT_PRT_DEBUG, - "TARGET_ASSIST %p (req %p:%s) done tag 0x%x\n", - ccb, tgt->req, serno, ccb->csio.tag_id); + "TARGET_ASSIST %p (req %p:%u) done tag 0x%x\n", + ccb, tgt->req, tgt->req->serno, ccb->csio.tag_id); /* * Free the Target Assist Request */ - KASSERT(tgt->req && tgt->req->ccb == ccb, - ("tgt->req %p:%s tgt->req->ccb %p", tgt->req, - serno, tgt->req? tgt->req->ccb : NULL)); + KASSERT(tgt->req->ccb == ccb, + ("tgt->req %p:%u tgt->req->ccb %p", tgt->req, + tgt->req->serno, tgt->req->ccb)); + TAILQ_REMOVE(&mpt->request_pending_list, + tgt->req, links); mpt_free_request(mpt, tgt->req); tgt->req = NULL; + /* * Do we need to send status now? That is, are * we done with all our data transfers? @@ -4396,6 +4564,9 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, CAMLOCK_2_MPTLOCK(mpt); break; } + /* + * Otherwise, send status (and sense) + */ if (ccb->ccb_h.flags & CAM_SEND_SENSE) { sp = sense; memcpy(sp, &ccb->csio.sense_data, @@ -4411,9 +4582,18 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, int ioindex; ccb = tgt->ccb; + if (tgt->req == NULL) { + panic("mpt: turbo target reply with null " + "associated request sending status"); + /* NOTREACHED */ + } + if (ccb) { tgt->ccb = NULL; - tgt->nxfers++; + if (tgt->state == + TGT_STATE_MOVING_DATA_AND_STATUS) { + tgt->nxfers++; + } untimeout(mpt_timeout, ccb, ccb->ccb_h.timeout_ch); if (ccb->ccb_h.flags & CAM_SEND_SENSE) { @@ -4426,10 +4606,9 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, /* * Free the Target Send Status Request */ - KASSERT(tgt->req && tgt->req->ccb == ccb, - ("tgt->req %p:%s tgt->req->ccb %p", - tgt->req, serno, - tgt->req? tgt->req->ccb : NULL)); + KASSERT(tgt->req->ccb == ccb, + ("tgt->req %p:%u tgt->req->ccb %p", + tgt->req, tgt->req->serno, tgt->req->ccb)); /* * Notify CAM that we're done */ @@ -4440,16 +4619,20 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, tgt->ccb = NULL; } else { mpt_lprt(mpt, MPT_PRT_DEBUG, - "TARGET_STATUS non-CAM for req %p:%s\n", - tgt->req, serno); + "TARGET_STATUS non-CAM for req %p:%u\n", + tgt->req, tgt->req->serno); } + TAILQ_REMOVE(&mpt->request_pending_list, + tgt->req, links); mpt_free_request(mpt, tgt->req); tgt->req = NULL; /* * And re-post the Command Buffer. + * This wil reset the state. */ ioindex = GET_IO_INDEX(reply_desc); + TAILQ_REMOVE(&mpt->request_pending_list, req, links); mpt_post_target_command(mpt, req, ioindex); /* @@ -4491,19 +4674,37 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, switch (reply_frame->Function) { case MPI_FUNCTION_TARGET_CMD_BUFFER_POST: { - mpt_tgt_state_t *tgt = MPT_TGT_STATE(mpt, req); - KASSERT(tgt->state == TGT_STATE_LOADING, - ("bad state 0%x on reply to buffer post\n", tgt->state)); - if ((req->serno = mpt->sequence++) == 0) { - req->serno = mpt->sequence++; + mpt_tgt_state_t *tgt; +#ifdef INVARIANTS + mpt_req_spcl(mpt, req, "tgt reply BUFFER POST", __LINE__); +#endif + if (status != MPI_IOCSTATUS_SUCCESS) { + /* + * XXX What to do? + */ + break; } + tgt = MPT_TGT_STATE(mpt, req); + KASSERT(tgt->state == TGT_STATE_LOADING, + ("bad state 0x%x on reply to buffer post\n", tgt->state)); + mpt_assign_serno(mpt, req); tgt->state = TGT_STATE_LOADED; break; } case MPI_FUNCTION_TARGET_ASSIST: +#ifdef INVARIANTS + mpt_req_not_spcl(mpt, req, "tgt reply TARGET ASSIST", __LINE__); +#endif + mpt_prt(mpt, "target assist completion\n"); + TAILQ_REMOVE(&mpt->request_pending_list, req, links); mpt_free_request(mpt, req); break; case MPI_FUNCTION_TARGET_STATUS_SEND: +#ifdef INVARIANTS + mpt_req_not_spcl(mpt, req, "tgt reply STATUS SEND", __LINE__); +#endif + mpt_prt(mpt, "status send completion\n"); + TAILQ_REMOVE(&mpt->request_pending_list, req, links); mpt_free_request(mpt, req); break; case MPI_FUNCTION_TARGET_MODE_ABORT: @@ -4513,8 +4714,12 @@ mpt_scsi_tgt_reply_handler(struct mpt_softc *mpt, request_t *req, PTR_MSG_TARGET_MODE_ABORT abtp = (PTR_MSG_TARGET_MODE_ABORT) req->req_vbuf; uint32_t cc = GET_IO_INDEX(le32toh(abtp->ReplyWord)); +#ifdef INVARIANTS + mpt_req_not_spcl(mpt, req, "tgt reply TMODE ABORT", __LINE__); +#endif mpt_prt(mpt, "ABORT RX_ID 0x%x Complete; status 0x%x cnt %u\n", cc, le16toh(abtrp->IOCStatus), le32toh(abtrp->AbortCount)); + TAILQ_REMOVE(&mpt->request_pending_list, req, links); mpt_free_request(mpt, req); break; } diff --git a/sys/dev/mpt/mpt_pci.c b/sys/dev/mpt/mpt_pci.c index 9be1bc57bad..1f07379aed3 100644 --- a/sys/dev/mpt/mpt_pci.c +++ b/sys/dev/mpt/mpt_pci.c @@ -254,7 +254,6 @@ mpt_set_options(struct mpt_softc *mpt) mpt->disabled = 1; } } - bitmap = 0; if (getenv_int("mpt_debug", &bitmap)) { if (bitmap & (1 << mpt->unit)) { @@ -262,21 +261,21 @@ mpt_set_options(struct mpt_softc *mpt) } } bitmap = 0; - if (getenv_int("mpt_target", &bitmap)) { + if (getenv_int("mpt_debug1", &bitmap)) { if (bitmap & (1 << mpt->unit)) { - mpt->role = MPT_ROLE_TARGET; + mpt->verbose = MPT_PRT_DEBUG1; } } bitmap = 0; - if (getenv_int("mpt_none", &bitmap)) { + if (getenv_int("mpt_debug2", &bitmap)) { if (bitmap & (1 << mpt->unit)) { - mpt->role = MPT_ROLE_NONE; + mpt->verbose = MPT_PRT_DEBUG2; } } bitmap = 0; - if (getenv_int("mpt_initiator", &bitmap)) { + if (getenv_int("mpt_debug3", &bitmap)) { if (bitmap & (1 << mpt->unit)) { - mpt->role = MPT_ROLE_INITIATOR; + mpt->verbose = MPT_PRT_DEBUG3; } } } @@ -311,9 +310,9 @@ mpt_link_peer(struct mpt_softc *mpt) { struct mpt_softc *mpt2; - if (mpt->unit == 0) + if (mpt->unit == 0) { return; - + } /* * XXX: depends on probe order */ @@ -336,6 +335,14 @@ mpt_link_peer(struct mpt_softc *mpt) } } +static void +mpt_unlink_peer(struct mpt_softc *mpt) +{ + if (mpt->mpt2) { + mpt->mpt2->mpt2 = NULL; + } +} + static int mpt_pci_attach(device_t dev) @@ -377,7 +384,7 @@ mpt_pci_attach(device_t dev) mpt->raid_mwce_setting = MPT_RAID_MWCE_DEFAULT; mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT; mpt->verbose = MPT_PRT_NONE; - mpt->role = MPT_ROLE_DEFAULT; + mpt->role = MPT_ROLE_NONE; mpt_set_options(mpt); if (mpt->verbose == MPT_PRT_NONE) { mpt->verbose = MPT_PRT_WARN; @@ -388,7 +395,7 @@ mpt_pci_attach(device_t dev) cmd = pci_read_config(dev, PCIR_COMMAND, 2); if ((cmd & PCIM_CMD_MEMEN) == 0) { device_printf(dev, "Memory accesses disabled"); - goto bad; + return (ENXIO); } /* @@ -498,21 +505,6 @@ mpt_pci_attach(device_t dev) */ pci_disable_io(dev, SYS_RES_IOPORT); - switch (mpt->role) { - case MPT_ROLE_TARGET: - break; - case MPT_ROLE_INITIATOR: - break; - case MPT_ROLE_TARGET|MPT_ROLE_INITIATOR: - mpt->disabled = 1; - mpt_prt(mpt, "dual roles unsupported\n"); - goto bad; - case MPT_ROLE_NONE: - device_printf(dev, "role of NONE same as disable\n"); - mpt->disabled = 1; - goto bad; - } - /* Initialize the hardware */ if (mpt->disabled == 0) { MPT_LOCK(mpt); @@ -536,11 +528,15 @@ mpt_pci_attach(device_t dev) MPT_UNLOCK(mpt); goto bad; } + KASSERT(MPT_OWNED(mpt) == 0, ("leaving attach with device locked")); return (0); bad: mpt_dma_mem_free(mpt); mpt_free_bus_resources(mpt); + mpt_unlink_peer(mpt); + + MPT_LOCK_DESTROY(mpt); /* * but return zero to preserve unit numbering diff --git a/sys/dev/mpt/mpt_raid.c b/sys/dev/mpt/mpt_raid.c index da25979e3eb..812f276c926 100644 --- a/sys/dev/mpt/mpt_raid.c +++ b/sys/dev/mpt/mpt_raid.c @@ -277,7 +277,9 @@ mpt_raid_attach(struct mpt_softc *mpt) csa.event_enable = AC_FOUND_DEVICE; csa.callback = mpt_raid_async; csa.callback_arg = mpt; + MPTLOCK_2_CAMLOCK(mpt); xpt_action((union ccb *)&csa); + CAMLOCK_2_MPTLOCK(mpt); if (csa.ccb_h.status != CAM_REQ_CMP) { mpt_prt(mpt, "mpt_raid_attach: Unable to register " "CAM async handler.\n"); @@ -307,7 +309,9 @@ mpt_raid_detach(struct mpt_softc *mpt) csa.event_enable = 0; csa.callback = mpt_raid_async; csa.callback_arg = mpt; + MPTLOCK_2_CAMLOCK(mpt); xpt_action((union ccb *)&csa); + CAMLOCK_2_MPTLOCK(mpt); } static void