diff options
author | gibbs <gibbs@FreeBSD.org> | 1998-09-25 22:35:56 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 1998-09-25 22:35:56 +0000 |
commit | 49939b416d5ce932640b6557c232a69a54761dfc (patch) | |
tree | 2c09a1ecfbdcaf6decb26d896e9002d04249054e /sys/cam | |
parent | 0189e207a1ddcc20d9050d386fc1ee609afcd95c (diff) | |
download | FreeBSD-src-49939b416d5ce932640b6557c232a69a54761dfc.zip FreeBSD-src-49939b416d5ce932640b6557c232a69a54761dfc.tar.gz |
Correct problems with xpt_set_transfer_settings and async transfer
negotiation changes with wildcarded paths.
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/cam_xpt.c | 124 |
1 files changed, 68 insertions, 56 deletions
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index b6e2216..c5e6837 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: cam_xpt.c,v 1.12 1998/09/23 03:03:19 gibbs Exp $ + * $Id: cam_xpt.c,v 1.13 1998/09/24 22:43:54 gibbs Exp $ */ #include <sys/param.h> #include <sys/systm.h> @@ -600,6 +600,7 @@ static void probedone(struct cam_periph *periph, union ccb *done_ccb); static void probecleanup(struct cam_periph *periph); static void xpt_find_quirk(struct cam_ed *device); static void xpt_set_transfer_settings(struct ccb_trans_settings *cts, + struct cam_ed *device, int async_update); static void xpt_toggle_tags(struct cam_path *path); static void xpt_start_tags(struct cam_path *path); @@ -2567,6 +2568,7 @@ xpt_action(union ccb *start_ccb) case XPT_SET_TRAN_SETTINGS: { xpt_set_transfer_settings(&start_ccb->cts, + start_ccb->ccb_h.path->device, /*async_update*/FALSE); break; } @@ -3872,14 +3874,6 @@ xpt_async(u_int32_t async_code, struct cam_path *path, void *async_arg) && path->target != NULL) continue; - if (async_code == AC_TRANSFER_NEG) { - struct ccb_trans_settings *settings; - - settings = (struct ccb_trans_settings *)async_arg; - xpt_set_transfer_settings(settings, - /*async_update*/TRUE); - } - for (device = TAILQ_FIRST(&target->ed_entries); device != NULL; device = next_device) { @@ -3960,8 +3954,17 @@ xpt_async(u_int32_t async_code, struct cam_path *path, void *async_arg) NULL); } xpt_release_path(&newpath); - } else if (async_code == AC_LOST_DEVICE) + } else if (async_code == AC_LOST_DEVICE) { device->flags |= CAM_DEV_UNCONFIGURED; + } else if (async_code == AC_TRANSFER_NEG) { + struct ccb_trans_settings *settings; + + settings = + (struct ccb_trans_settings *)async_arg; + xpt_set_transfer_settings(settings, device, + /*async_update*/TRUE); + } + xpt_async_bcast(&device->asyncs, async_code, @@ -5240,19 +5243,23 @@ xpt_find_quirk(struct cam_ed *device) } static void -xpt_set_transfer_settings(struct ccb_trans_settings *cts, int async_update) +xpt_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device, + int async_update) { - struct cam_ed *device; struct cam_sim *sim; int qfrozen; - int device_tagenb; - device = cts->ccb_h.path->device; sim = cts->ccb_h.path->bus->sim; if (async_update == FALSE) { struct scsi_inquiry_data *inq_data; struct ccb_pathinq cpi; + if (device == NULL) { + cts->ccb_h.status = CAM_PATH_INVALID; + xpt_done((union ccb *)cts); + return; + } + /* * Perform sanity checking against what the * controller and device can do. @@ -5308,50 +5315,53 @@ xpt_set_transfer_settings(struct ccb_trans_settings *cts, int async_update) } } - /* - * If we are transitioning from tags to no-tags or - * vice-versa, we need to carefully freeze and restart - * the queue so that we don't overlap tagged and non-tagged - * commands. We also temporarily stop tags if there is - * a change in transfer negotiation settings to allow - * "tag-less" negotiation. - */ qfrozen = FALSE; - if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 - || (device->inq_flags & SID_CmdQue) != 0) - device_tagenb = TRUE; - else - device_tagenb = FALSE; + if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) { + int device_tagenb; - if ((cts->valid & CCB_TRANS_TQ_VALID) != 0 - && (((cts->flags & CCB_TRANS_TAG_ENB) != 0 - && device_tagenb == FALSE) - || ((cts->flags & CCB_TRANS_TAG_ENB) == 0 - && device_tagenb == TRUE))) { + /* + * If we are transitioning from tags to no-tags or + * vice-versa, we need to carefully freeze and restart + * the queue so that we don't overlap tagged and non-tagged + * commands. We also temporarily stop tags if there is + * a change in transfer negotiation settings to allow + * "tag-less" negotiation. + */ + if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 + || (device->inq_flags & SID_CmdQue) != 0) + device_tagenb = TRUE; + else + device_tagenb = FALSE; - if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) { - /* - * Delay change to use tags until after a - * few commands have gone to this device so - * the controller has time to perform transfer - * negotiations without tagged messages getting - * in the way. - */ - device->tag_delay_count = CAM_TAG_DELAY_COUNT; - device->flags |= CAM_DEV_TAG_AFTER_COUNT; - } else { - xpt_freeze_devq(cts->ccb_h.path, /*count*/1); - qfrozen = TRUE; - device->inq_flags &= ~SID_CmdQue; - xpt_dev_ccbq_resize(cts->ccb_h.path, - sim->max_dev_openings); - device->flags &= ~CAM_DEV_TAG_AFTER_COUNT; - device->tag_delay_count = 0; + if (((cts->flags & CCB_TRANS_TAG_ENB) != 0 + && device_tagenb == FALSE) + || ((cts->flags & CCB_TRANS_TAG_ENB) == 0 + && device_tagenb == TRUE)) { + + if ((cts->flags & CCB_TRANS_TAG_ENB) != 0) { + /* + * Delay change to use tags until after a + * few commands have gone to this device so + * the controller has time to perform transfer + * negotiations without tagged messages getting + * in the way. + */ + device->tag_delay_count = CAM_TAG_DELAY_COUNT; + device->flags |= CAM_DEV_TAG_AFTER_COUNT; + } else { + xpt_freeze_devq(cts->ccb_h.path, /*count*/1); + qfrozen = TRUE; + device->inq_flags &= ~SID_CmdQue; + xpt_dev_ccbq_resize(cts->ccb_h.path, + sim->max_dev_openings); + device->flags &= ~CAM_DEV_TAG_AFTER_COUNT; + device->tag_delay_count = 0; + } + } else if ((cts->flags & (CCB_TRANS_SYNC_RATE_VALID| + CCB_TRANS_SYNC_OFFSET_VALID| + CCB_TRANS_BUS_WIDTH_VALID)) != 0) { + xpt_toggle_tags(cts->ccb_h.path); } - } else if ((cts->flags & (CCB_TRANS_SYNC_RATE_VALID| - CCB_TRANS_SYNC_OFFSET_VALID| - CCB_TRANS_BUS_WIDTH_VALID)) != 0) { - xpt_toggle_tags(cts->ccb_h.path); } if (async_update == FALSE) @@ -5389,9 +5399,11 @@ xpt_toggle_tags(struct cam_path *path) xpt_setup_ccb(&cts.ccb_h, path, 1); cts.flags = 0; cts.valid = CCB_TRANS_TQ_VALID; - xpt_set_transfer_settings(&cts, /*async_update*/TRUE); + xpt_set_transfer_settings(&cts, path->device, + /*async_update*/TRUE); cts.flags = CCB_TRANS_TAG_ENB; - xpt_set_transfer_settings(&cts, /*async_update*/TRUE); + xpt_set_transfer_settings(&cts, path->device, + /*async_update*/TRUE); } } |