summaryrefslogtreecommitdiffstats
path: root/sys/cam/scsi/scsi_da.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/scsi/scsi_da.c')
-rw-r--r--sys/cam/scsi/scsi_da.c305
1 files changed, 222 insertions, 83 deletions
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 07a6435..d97e99d 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <cam/cam_periph.h>
#include <cam/cam_xpt_periph.h>
#include <cam/cam_sim.h>
+#include <cam/cam_iosched.h>
#include <cam/scsi/scsi_message.h>
@@ -199,21 +200,19 @@ struct disk_params {
#define ATA_TRIM_MAX_RANGES ((UNMAP_BUF_SIZE / \
(ATA_DSM_RANGE_SIZE * ATA_DSM_BLK_SIZE)) * ATA_DSM_BLK_SIZE)
+#define DA_WORK_TUR (1 << 16)
+
struct da_softc {
- struct bio_queue_head bio_queue;
- struct bio_queue_head delete_queue;
+ struct cam_iosched_softc *cam_iosched;
struct bio_queue_head delete_run_queue;
LIST_HEAD(, ccb_hdr) pending_ccbs;
- int tur; /* TEST UNIT READY should be sent */
int refcount; /* Active xpt_action() calls */
da_state state;
da_flags flags;
da_quirks quirks;
- int sort_io_queue;
int minimum_cmd_size;
int error_inject;
int trim_max_ranges;
- int delete_running;
int delete_available; /* Delete methods possibly available */
u_int maxio;
uint32_t unmap_max_ranges;
@@ -222,6 +221,8 @@ struct da_softc {
da_delete_methods delete_method_pref;
da_delete_methods delete_method;
da_delete_func_t *delete_func;
+ int unmappedio;
+ int rotating;
struct disk_params params;
struct disk *disk;
union ccb saved_ccb;
@@ -233,6 +234,13 @@ struct da_softc {
uint8_t unmap_buf[UNMAP_BUF_SIZE];
struct scsi_read_capacity_data_long rcaplong;
struct callout mediapoll_c;
+#ifdef CAM_IO_STATS
+ struct sysctl_ctx_list sysctl_stats_ctx;
+ struct sysctl_oid *sysctl_stats_tree;
+ u_int errors;
+ u_int timeouts;
+ u_int invalidations;
+#endif
};
#define dadeleteflag(softc, delete_method, enable) \
@@ -1193,6 +1201,7 @@ static periph_init_t dainit;
static void daasync(void *callback_arg, u_int32_t code,
struct cam_path *path, void *arg);
static void dasysctlinit(void *context, int pending);
+static int dasysctlsofttimeout(SYSCTL_HANDLER_ARGS);
static int dacmdsizesysctl(SYSCTL_HANDLER_ARGS);
static int dadeletemethodsysctl(SYSCTL_HANDLER_ARGS);
static int dadeletemaxsysctl(SYSCTL_HANDLER_ARGS);
@@ -1230,6 +1239,10 @@ static timeout_t damediapoll;
#define DA_DEFAULT_TIMEOUT 60 /* Timeout in seconds */
#endif
+#ifndef DA_DEFAULT_SOFTTIMEOUT
+#define DA_DEFAULT_SOFTTIMEOUT 0
+#endif
+
#ifndef DA_DEFAULT_RETRY
#define DA_DEFAULT_RETRY 4
#endif
@@ -1238,12 +1251,10 @@ static timeout_t damediapoll;
#define DA_DEFAULT_SEND_ORDERED 1
#endif
-#define DA_SIO (softc->sort_io_queue >= 0 ? \
- softc->sort_io_queue : cam_sort_io_queues)
-
static int da_poll_period = DA_DEFAULT_POLL_PERIOD;
static int da_retry_count = DA_DEFAULT_RETRY;
static int da_default_timeout = DA_DEFAULT_TIMEOUT;
+static sbintime_t da_default_softtimeout = DA_DEFAULT_SOFTTIMEOUT;
static int da_send_ordered = DA_DEFAULT_SEND_ORDERED;
static SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD, 0,
@@ -1257,6 +1268,11 @@ SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RWTUN,
SYSCTL_INT(_kern_cam_da, OID_AUTO, send_ordered, CTLFLAG_RWTUN,
&da_send_ordered, 0, "Send Ordered Tags");
+SYSCTL_PROC(_kern_cam_da, OID_AUTO, default_softtimeout,
+ CTLTYPE_UINT | CTLFLAG_RW, NULL, 0, dasysctlsofttimeout, "I",
+ "Soft I/O timeout (ms)");
+TUNABLE_INT64("kern.cam.da.default_softtimeout", &da_default_softtimeout);
+
/*
* DA_ORDEREDTAG_INTERVAL determines how often, relative
* to the default timeout, we check to see whether an ordered
@@ -1400,12 +1416,7 @@ daschedule(struct cam_periph *periph)
if (softc->state != DA_STATE_NORMAL)
return;
- /* Check if we have more work to do. */
- if (bioq_first(&softc->bio_queue) ||
- (!softc->delete_running && bioq_first(&softc->delete_queue)) ||
- softc->tur) {
- xpt_schedule(periph, CAM_PRIORITY_NORMAL);
- }
+ cam_iosched_schedule(softc->cam_iosched, periph);
}
/*
@@ -1438,13 +1449,7 @@ dastrategy(struct bio *bp)
/*
* Place it in the queue of disk activities for this disk
*/
- if (bp->bio_cmd == BIO_DELETE) {
- bioq_disksort(&softc->delete_queue, bp);
- } else if (DA_SIO) {
- bioq_disksort(&softc->bio_queue, bp);
- } else {
- bioq_insert_tail(&softc->bio_queue, bp);
- }
+ cam_iosched_queue_work(softc->cam_iosched, bp);
/*
* Schedule ourselves for performing the work.
@@ -1519,7 +1524,7 @@ dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t leng
/*begin_lba*/0,/* Cover the whole disk */
/*lb_count*/0,
SSD_FULL_SIZE,
- 5 * 60 * 1000);
+ 5 * 1000);
xpt_polled_action((union ccb *)&csio);
error = cam_periph_error((union ccb *)&csio,
@@ -1599,14 +1604,16 @@ daoninvalidate(struct cam_periph *periph)
xpt_register_async(0, daasync, periph, periph->path);
softc->flags |= DA_FLAG_PACK_INVALID;
+#ifdef CAM_IO_STATS
+ softc->invalidations++;
+#endif
/*
* Return all queued I/O with ENXIO.
* XXX Handle any transactions queued to the card
* with XPT_ABORT_CCB.
*/
- bioq_flush(&softc->bio_queue, NULL, ENXIO);
- bioq_flush(&softc->delete_queue, NULL, ENXIO);
+ cam_iosched_flush(softc->cam_iosched, NULL, ENXIO);
/*
* Tell GEOM that we've gone away, we'll get a callback when it is
@@ -1624,12 +1631,20 @@ dacleanup(struct cam_periph *periph)
cam_periph_unlock(periph);
+ cam_iosched_fini(softc->cam_iosched);
+
/*
* If we can't free the sysctl tree, oh well...
*/
- if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
- && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
- xpt_print(periph->path, "can't remove sysctl context\n");
+ if ((softc->flags & DA_FLAG_SCTX_INIT) != 0) {
+#ifdef CAM_IO_STATS
+ if (sysctl_ctx_free(&softc->sysctl_stats_ctx) != 0)
+ xpt_print(periph->path,
+ "can't remove sysctl stats context\n");
+#endif
+ if (sysctl_ctx_free(&softc->sysctl_ctx) != 0)
+ xpt_print(periph->path,
+ "can't remove sysctl context\n");
}
callout_drain(&softc->mediapoll_c);
@@ -1732,9 +1747,9 @@ daasync(void *callback_arg, u_int32_t code,
}
case AC_SCSI_AEN:
softc = (struct da_softc *)periph->softc;
- if (!softc->tur) {
+ if (!cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
- softc->tur = 1;
+ cam_iosched_set_work_flags(softc->cam_iosched, DA_WORK_TUR);
daschedule(periph);
}
}
@@ -1808,9 +1823,6 @@ dasysctlinit(void *context, int pending)
OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
&softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
"Minimum CDB size");
- SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
- OID_AUTO, "sort_io_queue", CTLFLAG_RW, &softc->sort_io_queue, 0,
- "Sort IO queue to try and optimise disk access patterns");
SYSCTL_ADD_INT(&softc->sysctl_ctx,
SYSCTL_CHILDREN(softc->sysctl_tree),
@@ -1821,6 +1833,23 @@ dasysctlinit(void *context, int pending)
0,
"error_inject leaf");
+ SYSCTL_ADD_INT(&softc->sysctl_ctx,
+ SYSCTL_CHILDREN(softc->sysctl_tree),
+ OID_AUTO,
+ "unmapped_io",
+ CTLFLAG_RD,
+ &softc->unmappedio,
+ 0,
+ "Unmapped I/O leaf");
+
+ SYSCTL_ADD_INT(&softc->sysctl_ctx,
+ SYSCTL_CHILDREN(softc->sysctl_tree),
+ OID_AUTO,
+ "rotating",
+ CTLFLAG_RD,
+ &softc->rotating,
+ 0,
+ "Rotating media");
/*
* Add some addressing info.
@@ -1846,6 +1875,44 @@ dasysctlinit(void *context, int pending)
&softc->wwpn, "World Wide Port Name");
}
}
+
+#ifdef CAM_IO_STATS
+ /*
+ * Now add some useful stats.
+ * XXX These should live in cam_periph and be common to all periphs
+ */
+ softc->sysctl_stats_tree = SYSCTL_ADD_NODE(&softc->sysctl_stats_ctx,
+ SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO, "stats",
+ CTLFLAG_RD, 0, "Statistics");
+ SYSCTL_ADD_INT(&softc->sysctl_stats_ctx,
+ SYSCTL_CHILDREN(softc->sysctl_stats_tree),
+ OID_AUTO,
+ "errors",
+ CTLFLAG_RD,
+ &softc->errors,
+ 0,
+ "Transport errors reported by the SIM");
+ SYSCTL_ADD_INT(&softc->sysctl_stats_ctx,
+ SYSCTL_CHILDREN(softc->sysctl_stats_tree),
+ OID_AUTO,
+ "timeouts",
+ CTLFLAG_RD,
+ &softc->timeouts,
+ 0,
+ "Device timeouts reported by the SIM");
+ SYSCTL_ADD_INT(&softc->sysctl_stats_ctx,
+ SYSCTL_CHILDREN(softc->sysctl_stats_tree),
+ OID_AUTO,
+ "pack_invalidations",
+ CTLFLAG_RD,
+ &softc->invalidations,
+ 0,
+ "Device pack invalidations");
+#endif
+
+ cam_iosched_sysctl_init(softc->cam_iosched, &softc->sysctl_ctx,
+ softc->sysctl_tree);
+
cam_periph_release(periph);
}
@@ -1904,6 +1971,26 @@ dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
return (0);
}
+static int
+dasysctlsofttimeout(SYSCTL_HANDLER_ARGS)
+{
+ sbintime_t value;
+ int error;
+
+ value = da_default_softtimeout / SBT_1MS;
+
+ error = sysctl_handle_int(oidp, (int *)&value, 0, req);
+ if ((error != 0) || (req->newptr == NULL))
+ return (error);
+
+ /* XXX Should clip this to a reasonable level */
+ if (value > da_default_timeout * 1000)
+ return (EINVAL);
+
+ da_default_softtimeout = value * SBT_1MS;
+ return (0);
+}
+
static void
dadeletemethodset(struct da_softc *softc, da_delete_methods delete_method)
{
@@ -2075,14 +2162,18 @@ daregister(struct cam_periph *periph, void *arg)
if (softc == NULL) {
printf("daregister: Unable to probe new device. "
- "Unable to allocate softc\n");
+ "Unable to allocate softc\n");
return(CAM_REQ_CMP_ERR);
}
+ if (cam_iosched_init(&softc->cam_iosched, periph) != 0) {
+ printf("daregister: Unable to probe new device. "
+ "Unable to allocate iosched memory\n");
+ return(CAM_REQ_CMP_ERR);
+ }
+
LIST_INIT(&softc->pending_ccbs);
softc->state = DA_STATE_PROBE_RC;
- bioq_init(&softc->bio_queue);
- bioq_init(&softc->delete_queue);
bioq_init(&softc->delete_run_queue);
if (SID_IS_REMOVABLE(&cgd->inq_data))
softc->flags |= DA_FLAG_PACK_REMOVABLE;
@@ -2090,7 +2181,7 @@ daregister(struct cam_periph *periph, void *arg)
softc->unmap_max_lba = UNMAP_RANGE_MAX;
softc->ws_max_blks = WS16_MAX_BLKS;
softc->trim_max_ranges = ATA_TRIM_MAX_RANGES;
- softc->sort_io_queue = -1;
+ softc->rotating = 1;
periph->softc = softc;
@@ -2199,8 +2290,11 @@ daregister(struct cam_periph *periph, void *arg)
softc->disk->d_flags = DISKFLAG_DIRECT_COMPLETION;
if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
- if ((cpi.hba_misc & PIM_UNMAPPED) != 0)
+ if ((cpi.hba_misc & PIM_UNMAPPED) != 0) {
+ softc->unmappedio = 1;
softc->disk->d_flags |= DISKFLAG_UNMAPPED_BIO;
+ xpt_print(periph->path, "UNMAPPED\n");
+ }
cam_strvis(softc->disk->d_descr, cgd->inq_data.vendor,
sizeof(cgd->inq_data.vendor), sizeof(softc->disk->d_descr));
strlcat(softc->disk->d_descr, " ", sizeof(softc->disk->d_descr));
@@ -2277,23 +2371,11 @@ skipstate:
struct bio *bp;
uint8_t tag_code;
- /* Run BIO_DELETE if not running yet. */
- if (!softc->delete_running &&
- (bp = bioq_first(&softc->delete_queue)) != NULL) {
- if (softc->delete_func != NULL) {
- softc->delete_func(periph, start_ccb, bp);
- goto out;
- } else {
- bioq_flush(&softc->delete_queue, NULL, 0);
- /* FALLTHROUGH */
- }
- }
-
- /* Run regular command. */
- bp = bioq_takefirst(&softc->bio_queue);
+more:
+ bp = cam_iosched_next_bio(softc->cam_iosched);
if (bp == NULL) {
- if (softc->tur) {
- softc->tur = 0;
+ if (cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) {
+ cam_iosched_clr_work_flags(softc->cam_iosched, DA_WORK_TUR);
scsi_test_unit_ready(&start_ccb->csio,
/*retries*/ da_retry_count,
dadone,
@@ -2307,9 +2389,21 @@ skipstate:
xpt_release_ccb(start_ccb);
break;
}
- if (softc->tur) {
- softc->tur = 0;
- cam_periph_release_locked(periph);
+
+ if (bp->bio_cmd == BIO_DELETE) {
+ if (softc->delete_func != NULL) {
+ softc->delete_func(periph, start_ccb, bp);
+ goto out;
+ } else {
+ /* Not sure this is possible, but failsafe by lying and saying "sure, done." */
+ biofinish(bp, NULL, 0);
+ goto more;
+ }
+ }
+
+ if (cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) {
+ cam_iosched_clr_work_flags(softc->cam_iosched, DA_WORK_TUR);
+ cam_periph_release_locked(periph); /* XXX is this still valid? I think so but unverified */
}
if ((bp->bio_flags & BIO_ORDERED) != 0 ||
@@ -2377,6 +2471,7 @@ skipstate:
}
start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
start_ccb->ccb_h.flags |= CAM_UNLOCKED;
+ start_ccb->ccb_h.softtimeout = sbttotv(da_default_softtimeout);
out:
LIST_INSERT_HEAD(&softc->pending_ccbs,
@@ -2625,11 +2720,19 @@ da_delete_unmap(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
* fewer LBA's than requested.
*/
- softc->delete_running = 1;
bzero(softc->unmap_buf, sizeof(softc->unmap_buf));
bp1 = bp;
do {
- bioq_remove(&softc->delete_queue, bp1);
+ /*
+ * Note: ada and da are different in how they store the
+ * pending bp's in a trim. ada stores all of them in the
+ * trim_req.bps. da stores all but the first one in the
+ * delete_run_queue. ada then completes all the bps in
+ * its adadone() loop. da completes all the bps in the
+ * delete_run_queue in dadone, and relies on the biodone
+ * after to complete. This should be reconciled since there's
+ * no real reason to do it differently. XXX
+ */
if (bp1 != bp)
bioq_insert_tail(&softc->delete_run_queue, bp1);
lba = bp1->bio_pblkno;
@@ -2669,11 +2772,15 @@ da_delete_unmap(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
lastcount = c;
}
lastlba = lba;
- bp1 = bioq_first(&softc->delete_queue);
- if (bp1 == NULL || ranges >= softc->unmap_max_ranges ||
+ bp1 = cam_iosched_next_trim(softc->cam_iosched);
+ if (bp1 == NULL)
+ break;
+ if (ranges >= softc->unmap_max_ranges ||
totalcount + bp1->bio_bcount /
- softc->params.secsize > softc->unmap_max_lba)
+ softc->params.secsize > softc->unmap_max_lba) {
+ cam_iosched_put_back_trim(softc->cam_iosched, bp1);
break;
+ }
} while (1);
scsi_ulto2b(ranges * 16 + 6, &buf[0]);
scsi_ulto2b(ranges * 16, &buf[2]);
@@ -2689,6 +2796,7 @@ da_delete_unmap(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
da_default_timeout * 1000);
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
ccb->ccb_h.flags |= CAM_UNLOCKED;
+ cam_iosched_submit_trim(softc->cam_iosched);
}
static void
@@ -2703,12 +2811,10 @@ da_delete_trim(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
uint32_t lastcount = 0, c, requestcount;
int ranges = 0, off, block_count;
- softc->delete_running = 1;
bzero(softc->unmap_buf, sizeof(softc->unmap_buf));
bp1 = bp;
do {
- bioq_remove(&softc->delete_queue, bp1);
- if (bp1 != bp)
+ if (bp1 != bp)//XXX imp XXX
bioq_insert_tail(&softc->delete_run_queue, bp1);
lba = bp1->bio_pblkno;
count = bp1->bio_bcount / softc->params.secsize;
@@ -2752,10 +2858,14 @@ da_delete_trim(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
}
}
lastlba = lba;
- bp1 = bioq_first(&softc->delete_queue);
- if (bp1 == NULL || bp1->bio_bcount / softc->params.secsize >
- (softc->trim_max_ranges - ranges) * ATA_DSM_RANGE_MAX)
+ bp1 = cam_iosched_next_trim(softc->cam_iosched);
+ if (bp1 == NULL)
+ break;
+ if (bp1->bio_bcount / softc->params.secsize >
+ (softc->trim_max_ranges - ranges) * ATA_DSM_RANGE_MAX) {
+ cam_iosched_put_back_trim(softc->cam_iosched, bp1);
break;
+ }
} while (1);
block_count = (ranges + ATA_DSM_BLK_RANGES - 1) / ATA_DSM_BLK_RANGES;
@@ -2770,6 +2880,7 @@ da_delete_trim(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
da_default_timeout * 1000);
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
ccb->ccb_h.flags |= CAM_UNLOCKED;
+ cam_iosched_submit_trim(softc->cam_iosched);
}
/*
@@ -2788,13 +2899,11 @@ da_delete_ws(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
softc = (struct da_softc *)periph->softc;
ws_max_blks = softc->disk->d_delmaxsize / softc->params.secsize;
- softc->delete_running = 1;
lba = bp->bio_pblkno;
count = 0;
bp1 = bp;
do {
- bioq_remove(&softc->delete_queue, bp1);
- if (bp1 != bp)
+ if (bp1 != bp)//XXX imp XXX
bioq_insert_tail(&softc->delete_run_queue, bp1);
count += bp1->bio_bcount / softc->params.secsize;
if (count > ws_max_blks) {
@@ -2805,11 +2914,15 @@ da_delete_ws(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
count = omin(count, ws_max_blks);
break;
}
- bp1 = bioq_first(&softc->delete_queue);
- if (bp1 == NULL || lba + count != bp1->bio_pblkno ||
+ bp1 = cam_iosched_next_trim(softc->cam_iosched);
+ if (bp1 == NULL)
+ break;
+ if (lba + count != bp1->bio_pblkno ||
count + bp1->bio_bcount /
- softc->params.secsize > ws_max_blks)
+ softc->params.secsize > ws_max_blks) {
+ cam_iosched_put_back_trim(softc->cam_iosched, bp1);
break;
+ }
} while (1);
scsi_write_same(&ccb->csio,
@@ -2827,6 +2940,7 @@ da_delete_ws(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
da_default_timeout * 1000);
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
ccb->ccb_h.flags |= CAM_UNLOCKED;
+ cam_iosched_submit_trim(softc->cam_iosched);
}
static int
@@ -2870,8 +2984,8 @@ cmd6workaround(union ccb *ccb)
da_delete_method_desc[softc->delete_method]);
while ((bp = bioq_takefirst(&softc->delete_run_queue)) != NULL)
- bioq_disksort(&softc->delete_queue, bp);
- bioq_disksort(&softc->delete_queue,
+ cam_iosched_queue_work(softc->cam_iosched, bp);
+ cam_iosched_queue_work(softc->cam_iosched,
(struct bio *)ccb->ccb_h.ccb_bp);
ccb->ccb_h.ccb_bp = NULL;
return (0);
@@ -2998,9 +3112,12 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
xpt_print(periph->path,
"Invalidating pack\n");
softc->flags |= DA_FLAG_PACK_INVALID;
+#ifdef CAM_IO_STATS
+ softc->invalidations++;
+#endif
queued_error = ENXIO;
}
- bioq_flush(&softc->bio_queue, NULL,
+ cam_iosched_flush(softc->cam_iosched, NULL,
queued_error);
if (bp != NULL) {
bp->bio_error = error;
@@ -3043,6 +3160,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
if (LIST_EMPTY(&softc->pending_ccbs))
softc->flags |= DA_FLAG_WAS_OTAG;
+ cam_iosched_bio_complete(softc->cam_iosched, bp, done_ccb);
xpt_release_ccb(done_ccb);
if (state == DA_CCB_DELETE) {
TAILQ_HEAD(, bio) queue;
@@ -3060,7 +3178,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* and call daschedule again so that we don't stall if
* there are no other I/Os pending apart from BIO_DELETEs.
*/
- softc->delete_running = 0;
+ cam_iosched_trim_done(softc->cam_iosched);
daschedule(periph);
cam_periph_unlock(periph);
while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
@@ -3073,8 +3191,10 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
bp1->bio_resid = 0;
biodone(bp1);
}
- } else
+ } else {
+ daschedule(periph);
cam_periph_unlock(periph);
+ }
if (bp != NULL)
biodone(bp);
return;
@@ -3459,7 +3579,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
scsi_2btoul(bdc->medium_rotation_rate);
if (softc->disk->d_rotation_rate ==
SVPD_BDC_RATE_NON_ROTATING) {
- softc->sort_io_queue = 0;
+ cam_iosched_set_sort_queue(softc->cam_iosched, 0);
+ softc->rotating = 0;
}
if (softc->disk->d_rotation_rate != old_rate) {
disk_attr_changed(softc->disk,
@@ -3521,9 +3642,9 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
ata_params->media_rotation_rate;
if (softc->disk->d_rotation_rate ==
ATA_RATE_NON_ROTATING) {
- softc->sort_io_queue = 0;
+ cam_iosched_set_sort_queue(softc->cam_iosched, 0);
+ softc->rotating = 0;
}
-
if (softc->disk->d_rotation_rate != old_rate) {
disk_attr_changed(softc->disk,
"GEOM::rotation_rate", M_NOWAIT);
@@ -3652,6 +3773,23 @@ daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
if (error == ERESTART)
return (ERESTART);
+#ifdef CAM_IO_STATS
+ switch (ccb->ccb_h.status & CAM_STATUS_MASK) {
+ case CAM_CMD_TIMEOUT:
+ softc->timeouts++;
+ break;
+ case CAM_REQ_ABORTED:
+ case CAM_REQ_CMP_ERR:
+ case CAM_REQ_TERMIO:
+ case CAM_UNREC_HBA_ERROR:
+ case CAM_DATA_RUN_ERR:
+ softc->errors++;
+ break;
+ default:
+ break;
+ }
+#endif
+
/*
* XXX
* Until we have a better way of doing pack validation,
@@ -3671,9 +3809,10 @@ damediapoll(void *arg)
struct cam_periph *periph = arg;
struct da_softc *softc = periph->softc;
- if (!softc->tur && LIST_EMPTY(&softc->pending_ccbs)) {
+ if (!cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR) &&
+ LIST_EMPTY(&softc->pending_ccbs)) {
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
- softc->tur = 1;
+ cam_iosched_set_work_flags(softc->cam_iosched, DA_WORK_TUR);
daschedule(periph);
}
}
OpenPOWER on IntegriCloud