Date: Fri, 29 Jun 2012 21:33:36 +0000 (UTC) From: "Kenneth D. Merry" <ken@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r237825 - in stable/9: share/examples/scsi_target sys/cam/ctl sys/dev/aic7xxx sys/dev/firewire sys/dev/mpt Message-ID: <201206292133.q5TLXaP1071567@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ken Date: Fri Jun 29 21:33:36 2012 New Revision: 237825 URL: http://svn.freebsd.org/changeset/base/237825 Log: MFC r237601: r237601 | ken | 2012-06-26 08:51:35 -0600 (Tue, 26 Jun 2012) | 38 lines Fix an issue that caused the kernel to panic inside CTL when trying to attach to target capable HBAs that implement the old immediate notify (XPT_IMMED_NOTIFY) and notify acknowledge (XPT_NOTIFY_ACK) CCBs. The new API has been in place since SVN change 196008 in 2009. The solution is two-fold: fix CTL to handle the responses from the HBAs, and convert the HBA drivers in question to use the new API. These drivers have not been tested with CTL, so how well they will interoperate with CTL is unknown. scsi_target.c:Update the userland target example code to use the new immediate notify API. scsi_ctl.c: Detect when an immediate notify CCB is returned with CAM_REQ_INVALID or CAM_PROVIDE_FAIL status, and just free it. Fix a duplicate assignment. aic79xx.c, aic79xx_osm.c:Update the aic79xx driver to use the new API. Target mode is not enabled on for this driver, so the changes will have no practical effect. aic7xxx.c, aic7xxx_osm.c:Update the aic7xxx driver to use the new API. sbp_targ.c: Update the firewire target code to work with the new API. mpt_cam.c: Update the mpt(4) driver to work with the new API. Target mode is only enabled for Fibre Channel mpt(4) devices. Modified: stable/9/share/examples/scsi_target/scsi_target.c stable/9/sys/cam/ctl/scsi_ctl.c stable/9/sys/dev/aic7xxx/aic79xx.c stable/9/sys/dev/aic7xxx/aic79xx_osm.c stable/9/sys/dev/aic7xxx/aic7xxx.c stable/9/sys/dev/aic7xxx/aic7xxx_osm.c stable/9/sys/dev/firewire/sbp_targ.c stable/9/sys/dev/mpt/mpt_cam.c Directory Properties: stable/9/share/examples/scsi_target/ (props changed) stable/9/sys/ (props changed) stable/9/sys/dev/ (props changed) Modified: stable/9/share/examples/scsi_target/scsi_target.c ============================================================================== --- stable/9/share/examples/scsi_target/scsi_target.c Fri Jun 29 21:27:37 2012 (r237824) +++ stable/9/share/examples/scsi_target/scsi_target.c Fri Jun 29 21:33:36 2012 (r237825) @@ -88,7 +88,7 @@ static void handle_read(void); /* static int work_atio(struct ccb_accept_tio *); */ static void queue_io(struct ccb_scsiio *); static int run_queue(struct ccb_accept_tio *); -static int work_inot(struct ccb_immed_notify *); +static int work_inot(struct ccb_immediate_notify *); static struct ccb_scsiio * get_ctio(void); /* static void free_ccb(union ccb *); */ @@ -393,7 +393,7 @@ init_ccbs() warn("malloc INOT"); return (-1); } - inot->ccb_h.func_code = XPT_IMMED_NOTIFY; + inot->ccb_h.func_code = XPT_IMMEDIATE_NOTIFY; send_ccb((union ccb *)inot, /*priority*/1); } @@ -501,8 +501,8 @@ request_loop() /* Start one more transfer. */ retval = work_atio(&ccb->atio); break; - case XPT_IMMED_NOTIFY: - retval = work_inot(&ccb->cin); + case XPT_IMMEDIATE_NOTIFY: + retval = work_inot(&ccb->cin1); break; default: warnx("Unhandled ccb type %#x on workq", @@ -657,7 +657,7 @@ work_atio(struct ccb_accept_tio *atio) warnx("ATIO with %u bytes sense received", atio->sense_len); } - sense = &atio->sense_data; + sense = (struct scsi_sense_data_fixed *)&atio->sense_data; tcmd_sense(ctio->init_id, ctio, sense->flags, sense->add_sense_code, sense->add_sense_code_qual); send_ccb((union ccb *)ctio, /*priority*/1); @@ -778,16 +778,14 @@ run_queue(struct ccb_accept_tio *atio) } static int -work_inot(struct ccb_immed_notify *inot) +work_inot(struct ccb_immediate_notify *inot) { cam_status status; - int sense; if (debug) warnx("Working on INOT %p", inot); status = inot->ccb_h.status; - sense = (status & CAM_AUTOSNS_VALID) != 0; status &= CAM_STATUS_MASK; switch (status) { @@ -800,7 +798,7 @@ work_inot(struct ccb_immed_notify *inot) abort_all_pending(); break; case CAM_MESSAGE_RECV: - switch (inot->message_args[0]) { + switch (inot->arg) { case MSG_TASK_COMPLETE: case MSG_INITIATOR_DET_ERR: case MSG_ABORT_TASK_SET: @@ -811,7 +809,7 @@ work_inot(struct ccb_immed_notify *inot) case MSG_ABORT_TASK: case MSG_CLEAR_TASK_SET: default: - warnx("INOT message %#x", inot->message_args[0]); + warnx("INOT message %#x", inot->arg); break; } break; @@ -823,17 +821,6 @@ work_inot(struct ccb_immed_notify *inot) break; } - /* If there is sense data, use it */ - if (sense != 0) { - struct scsi_sense_data_fixed *sense; - - sense = (struct scsi_sense_data_fixed *)&inot->sense_data; - tcmd_sense(inot->initiator_id, NULL, sense->flags, - sense->add_sense_code, sense->add_sense_code_qual); - if (debug) - warnx("INOT has sense: %#x", sense->flags); - } - /* Requeue on SIM */ TAILQ_REMOVE(&work_queue, &inot->ccb_h, periph_links.tqe); send_ccb((union ccb *)inot, /*priority*/1); Modified: stable/9/sys/cam/ctl/scsi_ctl.c ============================================================================== --- stable/9/sys/cam/ctl/scsi_ctl.c Fri Jun 29 21:27:37 2012 (r237824) +++ stable/9/sys/cam/ctl/scsi_ctl.c Fri Jun 29 21:33:36 2012 (r237825) @@ -558,7 +558,6 @@ ctlferegister(struct cam_periph *periph, TAILQ_INIT(&softc->work_queue); softc->periph = periph; - softc->parent_softc = bus_softc; callout_init_mtx(&softc->dma_callout, sim->mtx, /*flags*/ 0); periph->softc = softc; @@ -628,12 +627,22 @@ ctlferegister(struct cam_periph *periph, xpt_action(new_ccb); softc->inots_sent++; status = new_ccb->ccb_h.status; - if (status != CAM_REQ_INPROG) { - free(new_ccb, M_CTLFE); + if ((status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { + /* + * Note that we don't free the CCB here. If the + * status is not CAM_REQ_INPROG, then we're + * probably talking to a SIM that says it is + * target-capable but doesn't support the + * XPT_IMMEDIATE_NOTIFY CCB. i.e. it supports the + * older API. In that case, it'll call xpt_done() + * on the CCB, and we need to free it in our done + * routine as a result. + */ break; } } - if (i == 0) { + if ((i == 0) + || (status != CAM_REQ_INPROG)) { xpt_print(periph->path, "%s: could not allocate immediate " "notify CCBs, status 0x%x\n", __func__, status); return (CAM_REQ_CMP_ERR); @@ -1460,12 +1469,29 @@ ctlfedone(struct cam_periph *periph, uni */ send_ctl_io = 0; break; + case CAM_REQ_INVALID: + case CAM_PROVIDE_FAIL: default: - xpt_print(periph->path, "%s: " - "unsupported CAM status 0x%x\n", - __func__, status); - send_ctl_io = 0; - break; + /* + * We should only get here if we're talking + * to a talking to a SIM that is target + * capable but supports the old API. In + * that case, we need to just free the CCB. + * If we actually send a notify acknowledge, + * it will send that back with an error as + * well. + */ + + if ((status != CAM_REQ_INVALID) + && (status != CAM_PROVIDE_FAIL)) + xpt_print(periph->path, "%s: " + "unsupported CAM status " + "0x%x\n", __func__, status); + + ctl_free_io(io); + ctlfe_free_ccb(periph, done_ccb); + + return; } if (send_ctl_io != 0) { ctl_queue(io); Modified: stable/9/sys/dev/aic7xxx/aic79xx.c ============================================================================== --- stable/9/sys/dev/aic7xxx/aic79xx.c Fri Jun 29 21:27:37 2012 (r237824) +++ stable/9/sys/dev/aic7xxx/aic79xx.c Fri Jun 29 21:33:36 2012 (r237825) @@ -8561,7 +8561,7 @@ void ahd_send_lstate_events(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate) { struct ccb_hdr *ccbh; - struct ccb_immed_notify *inot; + struct ccb_immediate_notify *inot; while (lstate->event_r_idx != lstate->event_w_idx && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) { @@ -8569,19 +8569,18 @@ ahd_send_lstate_events(struct ahd_softc event = &lstate->event_buffer[lstate->event_r_idx]; SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle); - inot = (struct ccb_immed_notify *)ccbh; + inot = (struct ccb_immediate_notify *)ccbh; switch (event->event_type) { case EVENT_TYPE_BUS_RESET: ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN; break; default: ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN; - inot->message_args[0] = event->event_type; - inot->message_args[1] = event->event_arg; + inot->arg = event->event_type; + inot->seq_id = event->event_arg; break; } inot->initiator_id = event->initiator_id; - inot->sense_len = 0; xpt_done((union ccb *)inot); lstate->event_r_idx++; if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE) Modified: stable/9/sys/dev/aic7xxx/aic79xx_osm.c ============================================================================== --- stable/9/sys/dev/aic7xxx/aic79xx_osm.c Fri Jun 29 21:27:37 2012 (r237824) +++ stable/9/sys/dev/aic7xxx/aic79xx_osm.c Fri Jun 29 21:33:36 2012 (r237825) @@ -601,8 +601,8 @@ ahd_action(struct cam_sim *sim, union cc break; } #ifdef AHD_TARGET_MODE - case XPT_NOTIFY_ACK: - case XPT_IMMED_NOTIFY: + case XPT_NOTIFY_ACKNOWLEDGE: + case XPT_IMMEDIATE_NOTIFY: { struct ahd_tmode_tstate *tstate; struct ahd_tmode_lstate *lstate; @@ -1189,7 +1189,7 @@ ahd_abort_ccb(struct ahd_softc *ahd, str switch (abort_ccb->ccb_h.func_code) { #ifdef AHD_TARGET_MODE case XPT_ACCEPT_TARGET_IO: - case XPT_IMMED_NOTIFY: + case XPT_IMMEDIATE_NOTIFY: case XPT_CONT_TARGET_IO: { struct ahd_tmode_tstate *tstate; @@ -1207,7 +1207,7 @@ ahd_abort_ccb(struct ahd_softc *ahd, str if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) list = &lstate->accept_tios; - else if (abort_ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) + else if (abort_ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) list = &lstate->immed_notifies; else list = NULL; Modified: stable/9/sys/dev/aic7xxx/aic7xxx.c ============================================================================== --- stable/9/sys/dev/aic7xxx/aic7xxx.c Fri Jun 29 21:27:37 2012 (r237824) +++ stable/9/sys/dev/aic7xxx/aic7xxx.c Fri Jun 29 21:33:36 2012 (r237825) @@ -6368,7 +6368,7 @@ void ahc_send_lstate_events(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate) { struct ccb_hdr *ccbh; - struct ccb_immed_notify *inot; + struct ccb_immediate_notify *inot; while (lstate->event_r_idx != lstate->event_w_idx && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) { @@ -6376,19 +6376,18 @@ ahc_send_lstate_events(struct ahc_softc event = &lstate->event_buffer[lstate->event_r_idx]; SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle); - inot = (struct ccb_immed_notify *)ccbh; + inot = (struct ccb_immediate_notify *)ccbh; switch (event->event_type) { case EVENT_TYPE_BUS_RESET: ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN; break; default: ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN; - inot->message_args[0] = event->event_type; - inot->message_args[1] = event->event_arg; + inot->arg = event->event_type; + inot->seq_id = event->event_arg; break; } inot->initiator_id = event->initiator_id; - inot->sense_len = 0; xpt_done((union ccb *)inot); lstate->event_r_idx++; if (lstate->event_r_idx == AHC_TMODE_EVENT_BUFFER_SIZE) Modified: stable/9/sys/dev/aic7xxx/aic7xxx_osm.c ============================================================================== --- stable/9/sys/dev/aic7xxx/aic7xxx_osm.c Fri Jun 29 21:27:37 2012 (r237824) +++ stable/9/sys/dev/aic7xxx/aic7xxx_osm.c Fri Jun 29 21:33:36 2012 (r237825) @@ -568,8 +568,8 @@ ahc_action(struct cam_sim *sim, union cc } break; } - case XPT_NOTIFY_ACK: - case XPT_IMMED_NOTIFY: + case XPT_NOTIFY_ACKNOWLEDGE: + case XPT_IMMEDIATE_NOTIFY: { struct ahc_tmode_tstate *tstate; struct ahc_tmode_lstate *lstate; @@ -1248,7 +1248,7 @@ ahc_abort_ccb(struct ahc_softc *ahc, str abort_ccb = ccb->cab.abort_ccb; switch (abort_ccb->ccb_h.func_code) { case XPT_ACCEPT_TARGET_IO: - case XPT_IMMED_NOTIFY: + case XPT_IMMEDIATE_NOTIFY: case XPT_CONT_TARGET_IO: { struct ahc_tmode_tstate *tstate; @@ -1266,7 +1266,7 @@ ahc_abort_ccb(struct ahc_softc *ahc, str if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) list = &lstate->accept_tios; - else if (abort_ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) + else if (abort_ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) list = &lstate->immed_notifies; else list = NULL; Modified: stable/9/sys/dev/firewire/sbp_targ.c ============================================================================== --- stable/9/sys/dev/firewire/sbp_targ.c Fri Jun 29 21:27:37 2012 (r237824) +++ stable/9/sys/dev/firewire/sbp_targ.c Fri Jun 29 21:33:36 2012 (r237825) @@ -488,7 +488,7 @@ sbp_targ_send_lstate_events(struct sbp_t { #if 0 struct ccb_hdr *ccbh; - struct ccb_immed_notify *inot; + struct ccb_immediate_notify *inot; printf("%s: not implemented yet\n", __func__); #endif @@ -822,7 +822,7 @@ sbp_targ_abort_ccb(struct sbp_targ_softc if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) list = &lstate->accept_tios; - else if (accb->ccb_h.func_code == XPT_IMMED_NOTIFY) + else if (accb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) list = &lstate->immed_notifies; else return (CAM_UA_ABORT); @@ -1100,8 +1100,8 @@ sbp_targ_action1(struct cam_sim *sim, un } } break; - case XPT_NOTIFY_ACK: /* recycle notify ack */ - case XPT_IMMED_NOTIFY: /* Add Immediate Notify Resource */ + case XPT_NOTIFY_ACKNOWLEDGE: /* recycle notify ack */ + case XPT_IMMEDIATE_NOTIFY: /* Add Immediate Notify Resource */ if (status != CAM_REQ_CMP) { ccb->ccb_h.status = status; xpt_done(ccb); @@ -1147,7 +1147,7 @@ sbp_targ_action1(struct cam_sim *sim, un switch (accb->ccb_h.func_code) { case XPT_ACCEPT_TARGET_IO: - case XPT_IMMED_NOTIFY: + case XPT_IMMEDIATE_NOTIFY: ccb->ccb_h.status = sbp_targ_abort_ccb(sc, ccb); break; case XPT_CONT_TARGET_IO: Modified: stable/9/sys/dev/mpt/mpt_cam.c ============================================================================== --- stable/9/sys/dev/mpt/mpt_cam.c Fri Jun 29 21:27:37 2012 (r237824) +++ stable/9/sys/dev/mpt/mpt_cam.c Fri Jun 29 21:33:36 2012 (r237825) @@ -3411,7 +3411,7 @@ mpt_action(struct cam_sim *sim, union cc CAMLOCK_2_MPTLOCK(mpt); switch (accb->ccb_h.func_code) { case XPT_ACCEPT_TARGET_IO: - case XPT_IMMED_NOTIFY: + case XPT_IMMEDIATE_NOTIFY: ccb->ccb_h.status = mpt_abort_target_ccb(mpt, ccb); break; case XPT_CONT_TARGET_IO: @@ -3785,8 +3785,8 @@ mpt_action(struct cam_sim *sim, union cc } break; } - case XPT_NOTIFY_ACK: /* recycle notify ack */ - case XPT_IMMED_NOTIFY: /* Add Immediate Notify Resource */ + case XPT_NOTIFY_ACKNOWLEDGE: /* recycle notify ack */ + case XPT_IMMEDIATE_NOTIFY: /* Add Immediate Notify Resource */ case XPT_ACCEPT_TARGET_IO: /* Add Accept Target IO Resource */ { tgt_resource_t *trtp; @@ -3813,7 +3813,7 @@ mpt_action(struct cam_sim *sim, union cc "Put FREE ATIO %p lun %d\n", ccb, lun); STAILQ_INSERT_TAIL(&trtp->atios, &ccb->ccb_h, sim_links.stqe); - } else if (ccb->ccb_h.func_code == XPT_IMMED_NOTIFY) { + } else if (ccb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) { mpt_lprt(mpt, MPT_PRT_DEBUG1, "Put FREE INOT lun %d\n", lun); STAILQ_INSERT_TAIL(&trtp->inots, &ccb->ccb_h, @@ -4822,7 +4822,7 @@ mpt_abort_target_ccb(struct mpt_softc *m if (accb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) { lp = &trtp->atios; - } else if (accb->ccb_h.func_code == XPT_IMMED_NOTIFY) { + } else if (accb->ccb_h.func_code == XPT_IMMEDIATE_NOTIFY) { lp = &trtp->inots; } else { return (CAM_REQ_INVALID); @@ -5043,11 +5043,11 @@ static void mpt_scsi_tgt_tsk_mgmt(struct mpt_softc *mpt, request_t *req, mpt_task_mgmt_t fc, tgt_resource_t *trtp, int init_id) { - struct ccb_immed_notify *inot; + struct ccb_immediate_notify *inot; mpt_tgt_state_t *tgt; tgt = MPT_TGT_STATE(mpt, req); - inot = (struct ccb_immed_notify *) STAILQ_FIRST(&trtp->inots); + inot = (struct ccb_immediate_notify *) STAILQ_FIRST(&trtp->inots); if (inot == NULL) { mpt_lprt(mpt, MPT_PRT_WARN, "no INOTSs- sending back BSY\n"); mpt_scsi_tgt_status(mpt, NULL, req, SCSI_STATUS_BUSY, NULL); @@ -5057,35 +5057,35 @@ mpt_scsi_tgt_tsk_mgmt(struct mpt_softc * mpt_lprt(mpt, MPT_PRT_DEBUG1, "Get FREE INOT %p lun %d\n", inot, inot->ccb_h.target_lun); - memset(&inot->sense_data, 0, sizeof (inot->sense_data)); - inot->sense_len = 0; - memset(inot->message_args, 0, sizeof (inot->message_args)); inot->initiator_id = init_id; /* XXX */ - /* * This is a somewhat grotesque attempt to map from task management * to old style SCSI messages. God help us all. */ switch (fc) { case MPT_ABORT_TASK_SET: - inot->message_args[0] = MSG_ABORT_TAG; + inot->arg = MSG_ABORT_TAG; break; case MPT_CLEAR_TASK_SET: - inot->message_args[0] = MSG_CLEAR_TASK_SET; + inot->arg = MSG_CLEAR_TASK_SET; break; case MPT_TARGET_RESET: - inot->message_args[0] = MSG_TARGET_RESET; + inot->arg = MSG_TARGET_RESET; break; case MPT_CLEAR_ACA: - inot->message_args[0] = MSG_CLEAR_ACA; + inot->arg = MSG_CLEAR_ACA; break; case MPT_TERMINATE_TASK: - inot->message_args[0] = MSG_ABORT_TAG; + inot->arg = MSG_ABORT_TAG; break; default: - inot->message_args[0] = MSG_NOOP; + inot->arg = MSG_NOOP; break; } + /* + * XXX KDM we need the sequence/tag number for the target of the + * task management operation, especially if it is an abort. + */ tgt->ccb = (union ccb *) inot; inot->ccb_h.status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN; MPTLOCK_2_CAMLOCK(mpt);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206292133.q5TLXaP1071567>