Date: Tue, 3 Jul 2001 22:31:15 -0700 (PDT) From: Matthew Jacob <mjacob@feral.com> To: scsi@freebsd.org Subject: target mode patches review Message-ID: <Pine.BSF.4.21.0107032228020.8572-100000@beppo>
next in thread | raw e-mail | index | archive | help
I've some changes to target mode- if folks could take a quick look... I'm starting to migrate target more toward a model of the user application driving more. These fix some cases with propagation of disconnects disabled and these also us to set Inquiry data for a device. Index: scsi_targ_bh.c =================================================================== RCS file: /home/ncvs/src/sys/cam/scsi/scsi_targ_bh.c,v retrieving revision 1.12 diff -u -r1.12 scsi_targ_bh.c --- scsi_targ_bh.c 2001/02/07 07:05:59 1.12 +++ scsi_targ_bh.c 2001/07/04 05:27:18 @@ -1,7 +1,7 @@ /* * Implementation of the Target Mode 'Black Hole device' for CAM. * - * Copyright (c) 1999 Justin T. Gibbs. + * Copyright (c) 1999, 2001 Justin T. Gibbs. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -487,7 +487,8 @@ desc = (struct targbh_cmd_desc *)atio->ccb_h.ccb_descr; /* Is this a tagged request? */ - flags = atio->ccb_h.flags & (CAM_TAG_ACTION_VALID|CAM_DIR_MASK); + flags = atio->ccb_h.flags & + (CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK); csio = &start_ccb->csio; /* @@ -510,7 +511,7 @@ /*retries*/2, targbhdone, flags, - (flags & CAM_TAG_ACTION_VALID)? + (flags & CAM_TAG_ACTION_VALID) ? MSG_SIMPLE_Q_TAG : 0, atio->tag_id, atio->init_id, @@ -529,6 +530,19 @@ CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, ("Sending a CTIO\n")); xpt_action(start_ccb); + /* + * If the queue was frozen waiting for the response + * to this ATIO (for instance disconnection was disallowed), + * then release it now that our response has been queued. + */ + if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) { + cam_release_devq(periph->path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + atio->ccb_h.status &= ~CAM_DEV_QFRZN; + } s = splbio(); ccbh = TAILQ_FIRST(&softc->work_queue); splx(s); @@ -556,6 +570,7 @@ struct ccb_accept_tio *atio; struct targbh_cmd_desc *descr; u_int8_t *cdb; + int priority; atio = &done_ccb->atio; descr = (struct targbh_cmd_desc*)atio->ccb_h.ccb_descr; @@ -645,9 +660,16 @@ } /* Queue us up to receive a Continue Target I/O ccb. */ - TAILQ_INSERT_TAIL(&softc->work_queue, &atio->ccb_h, - periph_links.tqe); - xpt_schedule(periph, /*priority*/1); + if ((atio->ccb_h.flags & CAM_DIS_DISCONNECT) != 0) { + TAILQ_INSERT_HEAD(&softc->work_queue, &atio->ccb_h, + periph_links.tqe); + priority = 0; + } else { + TAILQ_INSERT_TAIL(&softc->work_queue, &atio->ccb_h, + periph_links.tqe); + priority = 1; + } + xpt_schedule(periph, priority); break; } case XPT_CONT_TARGET_IO: @@ -672,7 +694,22 @@ done_ccb->ccb_h.flags &= ~CAM_SEND_SENSE; done_ccb->ccb_h.status &= ~CAM_SENT_SENSE; - /* XXX Check for errors */ + /* + * Any errors will not change the data we return, + * so make sure the queue is not left frozen. + * XXX - At some point there may be errors that + * leave us in a connected state with the + * initiator... + */ + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { + printf("Releasing Queue\n"); + cam_release_devq(done_ccb->ccb_h.path, + /*relsim_flags*/0, + /*reduction*/0, + /*timeout*/0, + /*getcount_only*/0); + done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; + } desc->data_resid -= desc->data_increment; xpt_release_ccb(done_ccb); if (softc->state != TARGBH_STATE_TEARDOWN) { @@ -696,11 +733,23 @@ } case XPT_IMMED_NOTIFY: { + int frozen; + + frozen = (done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0; if (softc->state == TARGBH_STATE_TEARDOWN || done_ccb->ccb_h.status == CAM_REQ_ABORTED) { printf("Freed an immediate notify\n"); free(done_ccb, M_DEVBUF); + } else { + /* Requeue for another immediate event */ + xpt_action(done_ccb); } + if (frozen != 0) + cam_release_devq(periph->path, + /*relsim_flags*/0, + /*opening reduction*/0, + /*timeout*/0, + /*getcount_only*/0); break; } default: Index: scsi_target.c =================================================================== RCS file: /home/ncvs/src/sys/cam/scsi/scsi_target.c,v retrieving revision 1.40 diff -u -r1.40 scsi_target.c --- scsi_target.c 2001/05/08 08:30:48 1.40 +++ scsi_target.c 2001/07/04 05:27:19 @@ -1,7 +1,7 @@ /* * Implementation of a simple Target Mode SCSI Proccessor Target driver for CAM. * - * Copyright (c) 1998, 1999 Justin T. Gibbs. + * Copyright (c) 1998, 1999, 2001 Justin T. Gibbs. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -93,6 +93,11 @@ /* We stick a pointer to the originating accept TIO in each continue I/O CCB */ #define ccb_atio ppriv_ptr1 +/* + * When we're constructing a unit, we point to passed in user inquiry data here. + */ +#define ccb_inq ppriv_ptr1 + struct targ_softc { /* CTIOs pending on the controller */ struct ccb_queue pending_queue; @@ -154,7 +159,9 @@ struct bio *bp; /* Buffer for this transfer */ u_int max_size; /* Size of backing_store */ u_int32_t timeout; - u_int8_t status; /* Status to return to initiator */ + u_int32_t + user_atio : 1, /* user ATIO (will define last CTIO) */ + status : 8; /* Status to return to initiator */ }; static d_open_t targopen; @@ -187,8 +194,8 @@ static periph_init_t targinit; static void targasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); -static int targallocinstance(struct ioc_alloc_unit *alloc_unit); -static int targfreeinstance(struct ioc_alloc_unit *alloc_unit); +static int targallocinstance(void *, u_long); +static int targfreeinstance(struct ioc_alloc_unit *); static cam_status targenlun(struct cam_periph *periph); static cam_status targdislun(struct cam_periph *periph); static periph_ctor_t targctor; @@ -472,8 +479,8 @@ softc->istate[i].pending_ua = UA_POWER_ON; /* - * Allocate an initial inquiry data buffer. We might allow the - * user to override this later via an ioctl. + * Allocate an inquiry data buffer. + * We let the user to override this if desired. */ softc->inq_data_len = sizeof(*softc->inq_data); softc->inq_data = malloc(softc->inq_data_len, M_DEVBUF, M_NOWAIT); @@ -482,19 +489,35 @@ targdtor(periph); return (CAM_RESRC_UNAVAIL); } - bzero(softc->inq_data, softc->inq_data_len); - softc->inq_data->device = T_PROCESSOR | (SID_QUAL_LU_CONNECTED << 5); - softc->inq_data->version = 2; - softc->inq_data->response_format = 2; /* SCSI2 Inquiry Format */ - softc->inq_data->flags = - cpi->hba_inquiry & (PI_SDTR_ABLE|PI_WIDE_16|PI_WIDE_32|PI_TAG_ABLE); - softc->inq_data->additional_length = softc->inq_data_len - 4; - strncpy(softc->inq_data->vendor, "FreeBSD ", SID_VENDOR_SIZE); - strncpy(softc->inq_data->product, "TM-PT ", SID_PRODUCT_SIZE); - strncpy(softc->inq_data->revision, "0.0 ", SID_REVISION_SIZE); + if (cpi->ccb_h.ccb_inq) { + bcopy(cpi->ccb_h.ccb_inq, softc->inq_data, softc->inq_data_len); + } else { + bzero(softc->inq_data, softc->inq_data_len); + softc->inq_data->device = + T_PROCESSOR | (SID_QUAL_LU_CONNECTED << 5); + softc->inq_data->version = 2; + softc->inq_data->response_format = 2; /* SCSI2 Inquiry Format */ + softc->inq_data->additional_length = softc->inq_data_len - 4; + strncpy(softc->inq_data->vendor, "FreeBSD ", SID_VENDOR_SIZE); + strncpy(softc->inq_data->product, + "TM-PT ", SID_PRODUCT_SIZE); + strncpy(softc->inq_data->revision, "0.0 ", SID_REVISION_SIZE); + } + + /* + * Preserve the SIM's capabilities here. Don't let user applications + * do something dumb. + */ + if (softc->inq_data->version >= 2) { + softc->inq_data->flags &= + ~(PI_SDTR_ABLE|PI_WIDE_16|PI_WIDE_32|PI_TAG_ABLE); + softc->inq_data->flags |= (cpi->hba_inquiry & + (PI_SDTR_ABLE|PI_WIDE_16|PI_WIDE_32|PI_TAG_ABLE)); + } softc->targ_dev = make_dev(&targ_cdevsw, periph->unit_number, UID_ROOT, GID_OPERATOR, 0600, "%s%d", periph->periph_name, periph->unit_number); + softc->init_level++; return (CAM_REQ_CMP); } @@ -621,8 +644,10 @@ } static int -targallocinstance(struct ioc_alloc_unit *alloc_unit) +targallocinstance(void *arg, u_long cmd) { + struct ioc_alloc_unit *alloc_unit = arg; + struct scsi_inquiry_data local; struct ccb_pathinq cpi; struct cam_path *path; struct cam_periph *periph; @@ -642,7 +667,6 @@ free_path_on_return++; - xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); @@ -655,7 +679,8 @@ /* Can only alloc units on controllers that support target mode */ if ((cpi.target_sprt & PIT_PROCESSOR) == 0) { - printf("Controller does not support target mode%x\n", status); + printf("Controller does not support target mode - status %x\n", + status); status = CAM_PATH_INVALID; goto fail; } @@ -666,6 +691,16 @@ goto fail; } + if (cmd == TARGCTLIOALLOCUNIT) { + status = copyin(alloc_unit->inquiry_data, &local, sizeof local); + if (status) + goto fail; + cpi.ccb_h.ccb_inq = &local; + } else { + cpi.ccb_h.ccb_inq = NULL; + } + + /* * Allocate a peripheral instance for * this target instance. @@ -783,10 +818,17 @@ error = 0; if (TARG_IS_CONTROL_DEV(unit)) { switch (cmd) { + case OTARGCTLIOALLOCUNIT: case TARGCTLIOALLOCUNIT: - error = targallocinstance((struct ioc_alloc_unit*)addr); + error = targallocinstance(addr, cmd); break; + case OTARGCTLIOFREEUNIT: case TARGCTLIOFREEUNIT: + /* + * Old_ioc_alloc_unit and ioc_alloc_unit are the + * same with respect to what we need from the structure + * for this function. + */ error = targfreeinstance((struct ioc_alloc_unit*)addr); break; default: @@ -888,9 +930,9 @@ } break; } -#ifdef CAMDEBUG case TARGIODEBUG: { +#ifdef CAMDEBUG union ccb ccb; bzero (&ccb, sizeof ccb); if (xpt_create_path(&ccb.ccb_h.path, periph, @@ -918,9 +960,11 @@ error = 0; } xpt_free_path(ccb.ccb_h.path); +#else + error = 0; +#endif break; } -#endif default: error = ENOTTY; break; @@ -1337,22 +1381,24 @@ desc = (struct targ_cmd_desc *)atio->ccb_h.ccb_descr; /* Is this a tagged request? */ - flags = atio->ccb_h.flags & - (CAM_DIS_DISCONNECT|CAM_TAG_ACTION_VALID|CAM_DIR_MASK); + flags = atio->ccb_h.flags & (CAM_DIS_DISCONNECT | + CAM_TAG_ACTION_VALID | CAM_DIR_MASK | CAM_SEND_STATUS); /* * If we are done with the transaction, tell the * controller to send status and perform a CMD_CMPLT. */ - if (desc->data_resid == desc->data_increment) + if (desc->user_atio == 0 && + desc->data_resid == desc->data_increment) { flags |= CAM_SEND_STATUS; + } csio = &start_ccb->csio; cam_fill_ctio(csio, /*retries*/2, targdone, flags, - (flags & CAM_TAG_ACTION_VALID)? + (flags & CAM_TAG_ACTION_VALID) ? MSG_SIMPLE_Q_TAG : 0, atio->tag_id, atio->init_id, @@ -1390,13 +1436,13 @@ * to this ATIO (for instance disconnection was disallowed), * then release it now that our response has been queued. */ - if ((atio->ccb_h.flags & CAM_DEV_QFRZN) != 0) { + if ((atio->ccb_h.status & CAM_DEV_QFRZN) != 0) { cam_release_devq(periph->path, /*relsim_flags*/0, /*reduction*/0, /*timeout*/0, /*getcount_only*/0); - atio->ccb_h.flags &= ~CAM_DEV_QFRZN; + atio->ccb_h.status &= ~CAM_DEV_QFRZN; } s = splbio(); ccbh = TAILQ_FIRST(&softc->work_queue); @@ -1441,6 +1487,9 @@ free(done_ccb, M_DEVBUF); return; } + descr->data_resid = 0; + descr->data_increment = 0; + descr->user_atio = 0; #ifdef CAMDEBUG { @@ -1450,8 +1499,8 @@ snprintf(dcb, sizeof dcb, "%s %02x", dcb, cdb[i] & 0xff); } - CAM_DEBUG(periph->path, - CAM_DEBUG_PERIPH, ("cdb:%s\n", dcb)); + CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, + ("flags %x cdb:%s\n", atio->ccb_h.flags, dcb)); } #endif if (atio->sense_len != 0) { @@ -1464,8 +1513,6 @@ */ atio->ccb_h.flags &= ~CAM_DIR_MASK; atio->ccb_h.flags |= CAM_DIR_NONE; - descr->data_resid = 0; - descr->data_increment = 0; descr->timeout = 5 * 1000; descr->status = SCSI_STATUS_CHECK_COND; copy_sense(softc, istate, (u_int8_t *)&atio->sense_data, @@ -1483,8 +1530,6 @@ /* Direction is always relative to the initator */ atio->ccb_h.flags &= ~CAM_DIR_MASK; atio->ccb_h.flags |= CAM_DIR_NONE; - descr->data_resid = 0; - descr->data_increment = 0; descr->timeout = 5 * 1000; descr->status = SCSI_STATUS_CHECK_COND; fill_sense(softc, atio->init_id, @@ -1538,8 +1583,6 @@ || inq->page_code != 0) { atio->ccb_h.flags &= ~CAM_DIR_MASK; atio->ccb_h.flags |= CAM_DIR_NONE; - descr->data_resid = 0; - descr->data_increment = 0; descr->timeout = 5 * 1000; descr->status = SCSI_STATUS_CHECK_COND; fill_sense(softc, atio->init_id, @@ -1591,8 +1634,6 @@ case TEST_UNIT_READY: atio->ccb_h.flags &= ~CAM_DIR_MASK; atio->ccb_h.flags |= CAM_DIR_NONE; - descr->data_resid = 0; - descr->data_increment = 0; descr->timeout = 5 * 1000; descr->status = SCSI_STATUS_OK; break; @@ -1633,7 +1674,7 @@ } case RECEIVE: case SEND: - { + if (SID_TYPE(softc->inq_data) == T_PROCESSOR) { struct scsi_send_receive *sr; sr = (struct scsi_send_receive *)cdb; @@ -1679,6 +1720,9 @@ * counterpart and transition to the exception * state. */ + descr->data_resid = 0; + descr->data_increment = 0; + descr->user_atio = 1; TAILQ_INSERT_TAIL(&softc->unknown_atio_queue, &atio->ccb_h, periph_links.tqe); @@ -1707,7 +1751,7 @@ struct ccb_accept_tio *atio; struct targ_cmd_desc *desc; struct bio *bp; - int error; + int error, lastctio; CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Received completed CTIO\n")); @@ -1725,7 +1769,9 @@ break; /* * Right now we don't need to do anything - * prior to unfreezing the queue... + * prior to unfreezing the queue. This may + * change if certain errors are reported while + * we are in a connected state. */ if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { printf("Releasing Queue\n"); @@ -1734,6 +1780,7 @@ /*reduction*/0, /*timeout*/0, /*getcount_only*/0); + done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN; } } else error = 0; @@ -1753,8 +1800,22 @@ done_ccb->ccb_h.status &= ~CAM_SENT_SENSE; CAM_DEBUG(periph->path, CAM_DEBUG_PERIPH, ("Sent Sense\n")); + done_ccb->ccb_h.flags &= ~CAM_SEND_SENSE; + } + + if (done_ccb->ccb_h.status & CAM_AUTOSNS_VALID) { + struct initiator_state *istate; + + istate = &softc->istate[csio->init_id]; + copy_sense(softc, istate, (u_int8_t *)&csio->sense_data, + csio->sense_len); + set_ca_condition(periph, csio->init_id, CA_CMD_SENSE); + done_ccb->ccb_h.status &= ~CAM_AUTOSNS_VALID; } - done_ccb->ccb_h.flags &= ~CAM_SEND_SENSE; + /* + * Was this the last CTIO? + */ + lastctio = done_ccb->ccb_h.status & CAM_SEND_STATUS; desc->data_increment -= csio->resid; desc->data_resid -= desc->data_increment; @@ -1785,10 +1846,11 @@ } } + if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) + atio->ccb_h.status |= CAM_DEV_QFRZN; xpt_release_ccb(done_ccb); if (softc->state != TARG_STATE_TEARDOWN) { - - if (desc->data_resid == 0) { + if (lastctio) { /* * Send the original accept TIO back to the * controller to handle more work. @@ -1800,25 +1862,25 @@ break; } - /* Queue us up for another buffer */ - if (atio->cdb_io.cdb_bytes[0] == SEND) { - if (desc->bp != NULL) - TAILQ_INSERT_HEAD( - &softc->snd_bio_queue.queue, - bp, bio_queue); + if (SID_TYPE(softc->inq_data) == T_PROCESSOR) { + /* Queue us up for another buffer */ + if (atio->cdb_io.cdb_bytes[0] == SEND) { + if (desc->bp != NULL) + TAILQ_INSERT_HEAD(&softc->snd_bio_queue.queue, + bp, bio_queue); TAILQ_INSERT_HEAD(&softc->snd_ccb_queue, &atio->ccb_h, periph_links.tqe); - } else { - if (desc->bp != NULL) - TAILQ_INSERT_HEAD( - &softc->rcv_bio_queue.queue, - bp, bio_queue); + } else { + if (desc->bp != NULL) + TAILQ_INSERT_HEAD(&softc->rcv_bio_queue.queue, + bp, bio_queue); TAILQ_INSERT_HEAD(&softc->rcv_ccb_queue, &atio->ccb_h, periph_links.tqe); + } + desc->bp = NULL; } - desc->bp = NULL; targrunqueue(periph, softc); } else { if (desc->bp != NULL) { Index: scsi_targetio.h =================================================================== RCS file: /home/ncvs/src/sys/cam/scsi/scsi_targetio.h,v retrieving revision 1.8 diff -u -r1.8 scsi_targetio.h --- scsi_targetio.h 2000/07/14 19:42:47 1.8 +++ scsi_targetio.h 2001/07/04 05:27:20 @@ -106,11 +106,19 @@ #define TARGIOCGETISTATE _IOWR('C', 6, struct ioc_initiator_state) #define TARGIOCSETISTATE _IOW('C', 5, struct ioc_initiator_state) +struct old_ioc_alloc_unit { + path_id_t path_id; + target_id_t target_id; + lun_id_t lun_id; + u_int unit; +}; + struct ioc_alloc_unit { path_id_t path_id; target_id_t target_id; lun_id_t lun_id; u_int unit; + struct scsi_inquiry_data *inquiry_data; }; /* @@ -120,6 +128,8 @@ * newly created instance. For de-allocation, all fields must match * an instance in the inactive (i.e. closed) state. */ +#define OTARGCTLIOALLOCUNIT _IOWR('C', 7, struct old_ioc_alloc_unit) +#define OTARGCTLIOFREEUNIT _IOW('C', 8, struct old_ioc_alloc_unit) #define TARGCTLIOALLOCUNIT _IOWR('C', 7, struct ioc_alloc_unit) #define TARGCTLIOFREEUNIT _IOW('C', 8, struct ioc_alloc_unit) To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-scsi" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0107032228020.8572-100000>