diff options
author | emaste <emaste@FreeBSD.org> | 2010-09-29 14:22:00 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2010-09-29 14:22:00 +0000 |
commit | 08029b22656860a865efdfc4fa8f9813c94e1071 (patch) | |
tree | e88aabbff4cbf8600ce2dc3bf368d01232416e86 | |
parent | caf0cb880211fe703d13207bde78d9225453bf96 (diff) | |
download | FreeBSD-src-08029b22656860a865efdfc4fa8f9813c94e1071.zip FreeBSD-src-08029b22656860a865efdfc4fa8f9813c94e1071.tar.gz |
Previously, the aac driver did not handle enclosure management AIFs,
which were raised during hot-swap events. Now such events trigger cam
rescans, as is done in the mps driver.
Submitted by: Mark Johnston <mjohnston at sandvine dot com>
-rw-r--r-- | sys/dev/aac/aac.c | 22 | ||||
-rw-r--r-- | sys/dev/aac/aac_cam.c | 48 | ||||
-rw-r--r-- | sys/dev/aac/aacreg.h | 5 | ||||
-rw-r--r-- | sys/dev/aac/aacvar.h | 5 |
4 files changed, 80 insertions, 0 deletions
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c index 59b1394..e3f47ed 100644 --- a/sys/dev/aac/aac.c +++ b/sys/dev/aac/aac.c @@ -3216,6 +3216,7 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) struct aac_mntinforesp *mir; int next, current, found; int count = 0, added = 0, i = 0; + uint32_t channel; fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); @@ -3324,6 +3325,27 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) break; + case AifEnEnclosureManagement: + switch (aif->data.EN.data.EEE.eventType) { + case AIF_EM_DRIVE_INSERTION: + case AIF_EM_DRIVE_REMOVAL: + channel = aif->data.EN.data.EEE.unitID; + if (sc->cam_rescan_cb != NULL) + sc->cam_rescan_cb(sc, + (channel >> 24) & 0xF, + (channel & 0xFFFF)); + break; + } + break; + + case AifEnAddJBOD: + case AifEnDeleteJBOD: + channel = aif->data.EN.data.ECE.container; + if (sc->cam_rescan_cb != NULL) + sc->cam_rescan_cb(sc, (channel >> 24) & 0xF, + AAC_CAM_TARGET_WILDCARD); + break; + default: break; } diff --git a/sys/dev/aac/aac_cam.c b/sys/dev/aac/aac_cam.c index 2e5a659..44f4e19 100644 --- a/sys/dev/aac/aac_cam.c +++ b/sys/dev/aac/aac_cam.c @@ -37,12 +37,15 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/kernel.h> #include <sys/sysctl.h> +#include <sys/lock.h> #include <sys/malloc.h> #include <sys/module.h> +#include <sys/mutex.h> #include <cam/cam.h> #include <cam/cam_ccb.h> #include <cam/cam_debug.h> +#include <cam/cam_periph.h> #include <cam/cam_sim.h> #include <cam/cam_xpt_sim.h> #include <cam/scsi/scsi_all.h> @@ -76,6 +79,9 @@ static int aac_cam_detach(device_t dev); static void aac_cam_action(struct cam_sim *, union ccb *); static void aac_cam_poll(struct cam_sim *); static void aac_cam_complete(struct aac_command *); +static void aac_cam_rescan(struct aac_softc *sc, uint32_t channel, + uint32_t target_id); + static u_int32_t aac_cam_reset_bus(struct cam_sim *, union ccb *); static u_int32_t aac_cam_abort_ccb(struct cam_sim *, union ccb *); static u_int32_t aac_cam_term_io(struct cam_sim *, union ccb *); @@ -101,6 +107,43 @@ MODULE_DEPEND(aacp, cam, 1, 1, 1); MALLOC_DEFINE(M_AACCAM, "aaccam", "AAC CAM info"); static void +aac_cam_rescan(struct aac_softc *sc, uint32_t channel, uint32_t target_id) +{ + union ccb *ccb; + struct aac_sim *sim; + struct aac_cam *camsc; + + if (target_id == AAC_CAM_TARGET_WILDCARD) + target_id = CAM_TARGET_WILDCARD; + + TAILQ_FOREACH(sim, &sc->aac_sim_tqh, sim_link) { + camsc = sim->aac_cam; + if (camsc == NULL || camsc->inf == NULL || + camsc->inf->BusNumber != channel) + continue; + + ccb = xpt_alloc_ccb_nowait(); + if (ccb == NULL) { + device_printf(sc->aac_dev, + "Cannot allocate ccb for bus rescan.\n"); + return; + } + + if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, + cam_sim_path(camsc->sim), + target_id, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + xpt_free_ccb(ccb); + device_printf(sc->aac_dev, + "Cannot create path for bus rescan.\n"); + return; + } + xpt_rescan(ccb); + break; + } +} + + +static void aac_cam_event(struct aac_softc *sc, struct aac_event *event, void *arg) { union ccb *ccb; @@ -141,6 +184,7 @@ aac_cam_detach(device_t dev) camsc = (struct aac_cam *)device_get_softc(dev); sc = camsc->inf->aac_sc; + camsc->inf->aac_cam = NULL; mtx_lock(&sc->aac_io_lock); @@ -149,6 +193,8 @@ aac_cam_detach(device_t dev) xpt_bus_deregister(cam_sim_path(camsc->sim)); cam_sim_free(camsc->sim, /*free_devq*/TRUE); + sc->cam_rescan_cb = NULL; + mtx_unlock(&sc->aac_io_lock); return (0); @@ -171,6 +217,7 @@ aac_cam_attach(device_t dev) camsc = (struct aac_cam *)device_get_softc(dev); inf = (struct aac_sim *)device_get_ivars(dev); camsc->inf = inf; + camsc->inf->aac_cam = camsc; devq = cam_simq_alloc(inf->TargetsPerBus); if (devq == NULL) @@ -198,6 +245,7 @@ aac_cam_attach(device_t dev) mtx_unlock(&inf->aac_sc->aac_io_lock); return (EIO); } + inf->aac_sc->cam_rescan_cb = aac_cam_rescan; mtx_unlock(&inf->aac_sc->aac_io_lock); camsc->sim = sim; diff --git a/sys/dev/aac/aacreg.h b/sys/dev/aac/aacreg.h index 1030dbc..9959778 100644 --- a/sys/dev/aac/aacreg.h +++ b/sys/dev/aac/aacreg.h @@ -935,6 +935,11 @@ struct aac_AifEnsEnclosureEvent { u_int32_t eventType; /* event type */ } __packed; +typedef enum { + AIF_EM_DRIVE_INSERTION=31, + AIF_EM_DRIVE_REMOVAL +} aac_AifEMEventType; + struct aac_AifEnsBatteryEvent { AAC_NVBATT_TRANSITION transition_type; /* eg from low to ok */ AAC_NVBATTSTATUS current_state; /* current batt state */ diff --git a/sys/dev/aac/aacvar.h b/sys/dev/aac/aacvar.h index 192616b..2371ad2 100644 --- a/sys/dev/aac/aacvar.h +++ b/sys/dev/aac/aacvar.h @@ -113,6 +113,7 @@ struct aac_container /* * Per-SIM data structure */ +struct aac_cam; struct aac_sim { device_t sim_dev; @@ -120,6 +121,7 @@ struct aac_sim int BusNumber; int InitiatorBusId; struct aac_softc *aac_sc; + struct aac_cam *aac_cam; TAILQ_ENTRY(aac_sim) sim_link; }; @@ -420,6 +422,9 @@ struct aac_softc u_int32_t aac_max_fib_size; /* max. FIB size */ u_int32_t aac_sg_tablesize; /* max. sg count from host */ u_int32_t aac_max_sectors; /* max. I/O size from host (blocks) */ +#define AAC_CAM_TARGET_WILDCARD ~0 + void (*cam_rescan_cb)(struct aac_softc *, uint32_t, + uint32_t); }; /* |