Author: emaste
Date: Wed Sep 29 14:22:00 2010
New Revision: 213272
URL: http://svn.freebsd.org/changeset/base/213272

Log:
  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>

Modified:
  head/sys/dev/aac/aac.c
  head/sys/dev/aac/aac_cam.c
  head/sys/dev/aac/aacreg.h
  head/sys/dev/aac/aacvar.h

Modified: head/sys/dev/aac/aac.c
==============================================================================
--- head/sys/dev/aac/aac.c      Wed Sep 29 13:24:56 2010        (r213271)
+++ head/sys/dev/aac/aac.c      Wed Sep 29 14:22:00 2010        (r213272)
@@ -3216,6 +3216,7 @@ aac_handle_aif(struct aac_softc *sc, str
        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, str
 
                        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;
                }

Modified: head/sys/dev/aac/aac_cam.c
==============================================================================
--- head/sys/dev/aac/aac_cam.c  Wed Sep 29 13:24:56 2010        (r213271)
+++ head/sys/dev/aac/aac_cam.c  Wed Sep 29 14:22:00 2010        (r213272)
@@ -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;

Modified: head/sys/dev/aac/aacreg.h
==============================================================================
--- head/sys/dev/aac/aacreg.h   Wed Sep 29 13:24:56 2010        (r213271)
+++ head/sys/dev/aac/aacreg.h   Wed Sep 29 14:22:00 2010        (r213272)
@@ -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 */

Modified: head/sys/dev/aac/aacvar.h
==============================================================================
--- head/sys/dev/aac/aacvar.h   Wed Sep 29 13:24:56 2010        (r213271)
+++ head/sys/dev/aac/aacvar.h   Wed Sep 29 14:22:00 2010        (r213272)
@@ -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);
 };
 
 /*
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to