diff options
author | gibbs <gibbs@FreeBSD.org> | 2005-03-23 16:43:29 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 2005-03-23 16:43:29 +0000 |
commit | 15f1e17020c1c7659c29f2dea0d6c2aec289132f (patch) | |
tree | b477bb8ac279bc453d958209ed720d69e249fac4 /sys/cam | |
parent | b6830526cfeff7d52446ded6d8ca5f52d1ef73aa (diff) | |
download | FreeBSD-src-15f1e17020c1c7659c29f2dea0d6c2aec289132f.zip FreeBSD-src-15f1e17020c1c7659c29f2dea0d6c2aec289132f.tar.gz |
Restore queue depth settings across tag disable events. The system often
disables tag queuing temporarily in order to allow controllers a window
to safely perform transfer negotiation with non-compliant devices. Before
this change, CAM would restore the queue depth to the controller specified
maximum or device quirk level rather than any depth determined by reactions
to QUEUE FULL/BUSY events or an explicit user setting.
During device probe, initialize the flags field for XPT_SCAN_BUS.
The uninitialized value often confused CAM into not bothering to
issue an AC_FOUND_DEVICE async event for new devices. The reason
this bug wasn't reported earlier is that CAM manually announces
devices after the initial system bus scans.
MFC: 3 days
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/cam_xpt.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index 53f9d0e..fb96d11 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -152,6 +152,7 @@ struct cam_ed { #define CAM_DEV_INQUIRY_DATA_VALID 0x40 u_int32_t tag_delay_count; #define CAM_TAG_DELAY_COUNT 5 + u_int32_t tag_saved_openings; u_int32_t refcount; struct callout_handle c_handle; }; @@ -5040,6 +5041,7 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) device->qfrozen_cnt = 0; device->flags = CAM_DEV_UNCONFIGURED; device->tag_delay_count = 0; + device->tag_saved_openings = 0; device->refcount = 1; callout_handle_init(&device->c_handle); @@ -5127,6 +5129,9 @@ xpt_dev_ccbq_resize(struct cam_path *path, int newopenings) if (result == CAM_REQ_CMP && (diff < 0)) { dev->flags |= CAM_DEV_RESIZE_QUEUE_NEEDED; } + if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 + || (dev->inq_flags & SID_CmdQue) != 0) + dev->tag_saved_openings = newopenings; /* Adjust the global limit */ xpt_max_ccbs += diff; splx(s); @@ -6057,7 +6062,8 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) done_ccb->ccb_h.func_code = XPT_GDEV_TYPE; xpt_action(done_ccb); - xpt_async(AC_FOUND_DEVICE, xpt_periph->path, done_ccb); + xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path, + done_ccb); } xpt_release_ccb(done_ccb); break; @@ -6710,7 +6716,11 @@ xpt_start_tags(struct cam_path *path) device->flags &= ~CAM_DEV_TAG_AFTER_COUNT; xpt_freeze_devq(path, /*count*/1); device->inq_flags |= SID_CmdQue; - newopenings = min(device->quirk->maxtags, sim->max_tagged_dev_openings); + if (device->tag_saved_openings != 0) + newopenings = device->tag_saved_openings; + else + newopenings = min(device->quirk->maxtags, + sim->max_tagged_dev_openings); xpt_dev_ccbq_resize(path, newopenings); xpt_setup_ccb(&crs.ccb_h, path, /*priority*/1); crs.ccb_h.func_code = XPT_REL_SIMQ; @@ -6888,6 +6898,7 @@ xpt_finishconfig(struct cam_periph *periph, union ccb *done_ccb) if (done_ccb->ccb_h.status == CAM_REQ_CMP) { done_ccb->ccb_h.func_code = XPT_SCAN_BUS; done_ccb->ccb_h.cbfcnp = xpt_finishconfig; + done_ccb->crcn.flags = 0; xpt_action(done_ccb); return; } |