Index: sys/cam/ata/ata_da.c =================================================================== --- sys/cam/ata/ata_da.c +++ sys/cam/ata/ata_da.c @@ -1294,6 +1294,30 @@ softc->delete_method = ADA_DELETE_NONE; } +/* + * Reprobe the device because something might have changed. + * If there's nothing we need to probe, we don't do anything. + * + * Returns true if we've restarted the a probe, and false + * if we have not. + */ +static bool +ada_reprobe(struct ada_softc *softc) +{ + if (ADA_RA >= 0 && softc->flags & ADA_FLAG_CAN_RAHEAD) + softc->state = ADA_STATE_RAHEAD; + else if (ADA_WC >= 0 && softc->flags & ADA_FLAG_CAN_WCACHE) + softc->state = ADA_STATE_WCACHE; + else if ((softc->flags & ADA_FLAG_CAN_LOG) + && (softc->zone_mode != ADA_ZONE_NONE)) + softc->state = ADA_STATE_LOGDIR; + else + softc->state = ADA_STATE_NORMAL; + + return (softc->state != ADA_STATE_NORMAL); +} + + static void adaasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg) @@ -1372,19 +1396,13 @@ cam_periph_async(periph, code, path, arg); if (softc->state != ADA_STATE_NORMAL) break; - if (ADA_RA >= 0 && softc->flags & ADA_FLAG_CAN_RAHEAD) - softc->state = ADA_STATE_RAHEAD; - else if (ADA_WC >= 0 && softc->flags & ADA_FLAG_CAN_WCACHE) - softc->state = ADA_STATE_WCACHE; - else if ((softc->flags & ADA_FLAG_CAN_LOG) - && (softc->zone_mode != ADA_ZONE_NONE)) - softc->state = ADA_STATE_LOGDIR; - else - break; - if (cam_periph_acquire(periph) != 0) - softc->state = ADA_STATE_NORMAL; - else - xpt_schedule(periph, CAM_PRIORITY_DEV); + if (ada_reprobe(softc)) { + if (cam_periph_acquire(periph) != 0) { + softc->state = ADA_STATE_NORMAL; + } else { + xpt_schedule(periph, CAM_PRIORITY_DEV); + } + } } default: cam_periph_async(periph, code, path, arg); @@ -1937,42 +1955,38 @@ taskqueue_enqueue(taskqueue_thread, &softc->sysctl_task); /* - * Add async callbacks for bus reset and - * bus device reset calls. I don't bother - * checking if this fails as, in most cases, - * the system will function just fine without - * them and the only alternative would be to - * not attach the device on failure. + * Add async callbacks for bus reset and bus device reset calls. I + * don't bother checking if this fails as, in most cases, the system + * will function just fine without them and the only alternative would + * be to not attach the device on failure. */ xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE | AC_GETDEV_CHANGED | AC_ADVINFO_CHANGED, adaasync, periph, periph->path); /* - * Schedule a periodic event to occasionally send an - * ordered tag to a device. + * Schedule a periodic event to occasionally send an ordered tag to a + * device. */ callout_init_mtx(&softc->sendordered_c, cam_periph_mtx(periph), 0); callout_reset_sbt(&softc->sendordered_c, SBT_1S / ADA_ORDEREDTAG_INTERVAL * ada_default_timeout, 0, adasendorderedtag, softc, C_PREL(1)); - if (ADA_RA >= 0 && softc->flags & ADA_FLAG_CAN_RAHEAD) { - softc->state = ADA_STATE_RAHEAD; - } else if (ADA_WC >= 0 && softc->flags & ADA_FLAG_CAN_WCACHE) { - softc->state = ADA_STATE_WCACHE; - } else if ((softc->flags & ADA_FLAG_CAN_LOG) - && (softc->zone_mode != ADA_ZONE_NONE)) { - softc->state = ADA_STATE_LOGDIR; - } else { + if (!ada_reprobe(softc)) { /* - * Nothing to probe, so we can just transition to the - * normal state. + * Nothing to probe, so we can just transition to the normal + * state. */ adaprobedone(periph, NULL); return(CAM_REQ_CMP); } + /* + * Do the probing. We do this single stepped at elevated priority, if + * possible, to constrain what we're sending to the device when + * attempting to do recovery. + */ xpt_schedule(periph, CAM_PRIORITY_DEV); return(CAM_REQ_CMP);