summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>2005-03-23 16:43:29 +0000
committergibbs <gibbs@FreeBSD.org>2005-03-23 16:43:29 +0000
commit15f1e17020c1c7659c29f2dea0d6c2aec289132f (patch)
treeb477bb8ac279bc453d958209ed720d69e249fac4 /sys/cam
parentb6830526cfeff7d52446ded6d8ca5f52d1ef73aa (diff)
downloadFreeBSD-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.c15
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;
}
OpenPOWER on IntegriCloud