Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Add support for dynamically attaching and detach...



details:   https://anonhg.NetBSD.org/src/rev/075a43482bc7
branches:  trunk
changeset: 552274:075a43482bc7
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Mon Sep 22 18:31:10 2003 +0000

description:
Add support for dynamically attaching and detaching RAID array units.

diffstat:

 sys/dev/pci/ld_twe.c |   36 ++++++-
 sys/dev/pci/twe.c    |  244 ++++++++++++++++++++++++++++++++++++--------------
 sys/dev/pci/twevar.h |   12 ++-
 3 files changed, 217 insertions(+), 75 deletions(-)

diffs (truncated from 441 to 300 lines):

diff -r feff2c522f5a -r 075a43482bc7 sys/dev/pci/ld_twe.c
--- a/sys/dev/pci/ld_twe.c      Mon Sep 22 18:29:05 2003 +0000
+++ b/sys/dev/pci/ld_twe.c      Mon Sep 22 18:31:10 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ld_twe.c,v 1.15 2003/09/21 19:33:10 thorpej Exp $      */
+/*     $NetBSD: ld_twe.c,v 1.16 2003/09/22 18:31:10 thorpej Exp $      */
 
 /*-
  * Copyright (c) 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ld_twe.c,v 1.15 2003/09/21 19:33:10 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ld_twe.c,v 1.16 2003/09/22 18:31:10 thorpej Exp $");
 
 #include "rnd.h"
 
@@ -72,6 +72,7 @@
 };
 
 static void    ld_twe_attach(struct device *, struct device *, void *);
+static int     ld_twe_detach(struct device *, int);
 static int     ld_twe_dobio(struct ld_twe_softc *, void *, int, int, int,
                             struct buf *);
 static int     ld_twe_dump(struct ld_softc *, void *, int, int);
@@ -79,8 +80,14 @@
 static int     ld_twe_match(struct device *, struct cfdata *, void *);
 static int     ld_twe_start(struct ld_softc *, struct buf *);
 
+static void    ld_twe_adjqparam(struct device *, int);
+
 CFATTACH_DECL(ld_twe, sizeof(struct ld_twe_softc),
-    ld_twe_match, ld_twe_attach, NULL, NULL);
+    ld_twe_match, ld_twe_attach, ld_twe_detach, NULL);
+
+static const struct twe_callbacks ld_twe_callbacks = {
+       ld_twe_adjqparam,
+};
 
 static int
 ld_twe_match(struct device *parent, struct cfdata *match, void *aux)
@@ -108,12 +115,14 @@
        twea = aux;
        td = &twe->sc_units[twea->twea_unit];
 
+       twe_register_callbacks(twe, twea->twea_unit, &ld_twe_callbacks);
+
        sc->sc_hwunit = twea->twea_unit;
        ld->sc_flags = LDF_ENABLED;
        ld->sc_maxxfer = twe_get_maxxfer(twe_get_maxsegs());
        ld->sc_secperunit = td->td_size;
        ld->sc_secsize = TWE_SECTOR_SIZE;
-       ld->sc_maxqueuecnt = (TWE_MAX_QUEUECNT - 1) / twe->sc_nunits;
+       ld->sc_maxqueuecnt = twe->sc_openings;
        ld->sc_start = ld_twe_start;
        ld->sc_dump = ld_twe_dump;
 
@@ -156,6 +165,18 @@
 }
 
 static int
+ld_twe_detach(struct device *self, int flags)
+{
+       int rv;
+
+       if ((rv = ldbegindetach((struct ld_softc *)self, flags)) != 0)
+               return (rv);
+       ldenddetach((struct ld_softc *)self);
+
+       return (0);
+}
+
+static int
 ld_twe_dobio(struct ld_twe_softc *sc, void *data, int datasize, int blkno,
             int dowrite, struct buf *bp)
 {
@@ -253,3 +274,10 @@
        return (ld_twe_dobio((struct ld_twe_softc *)ld, data,
            blkcnt * ld->sc_secsize, blkno, 1, NULL));
 }
+
+static void
+ld_twe_adjqparam(struct device *self, int openings)
+{
+
+       ldadjqparam((struct ld_softc *)self, openings);
+}
diff -r feff2c522f5a -r 075a43482bc7 sys/dev/pci/twe.c
--- a/sys/dev/pci/twe.c Mon Sep 22 18:29:05 2003 +0000
+++ b/sys/dev/pci/twe.c Mon Sep 22 18:31:10 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: twe.c,v 1.45 2003/09/22 01:13:02 thorpej Exp $ */
+/*     $NetBSD: twe.c,v 1.46 2003/09/22 18:31:11 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: twe.c,v 1.45 2003/09/22 01:13:02 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: twe.c,v 1.46 2003/09/22 18:31:11 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -115,6 +115,9 @@
 static int     twe_status_wait(struct twe_softc *, u_int, int);
 static void    twe_describe_controller(struct twe_softc *);
 
+static int     twe_add_unit(struct twe_softc *, int);
+static int     twe_del_unit(struct twe_softc *, int);
+
 static inline u_int32_t        twe_inl(struct twe_softc *, int);
 static inline void twe_outl(struct twe_softc *, int, u_int32_t);
 
@@ -302,14 +305,9 @@
        const char *intrstr;
        int size, i, rv, rseg;
        size_t max_segs, max_xfer;
-       struct twe_param *dtp, *atp;
-       struct twe_array_descriptor *ad;
-       struct twe_drive *td;
        bus_dma_segment_t seg;
        struct twe_cmd *tc;
-       struct twe_attach_args twea;
        struct twe_ccb *ccb;
-       uint16_t dsize;
 
        sc = (struct twe_softc *)self;
        pa = aux;
@@ -435,86 +433,184 @@
                return;
        }
 
+       /* Initialise connection with controller. */
+       twe_init_connection(sc);
+
+       twe_describe_controller(sc);
+
+       /* Find and attach RAID array units. */
+       sc->sc_nunits = 0;
+       for (i = 0; i < TWE_MAX_UNITS; i++)
+               (void) twe_add_unit(sc, i);
+
+       /* ...and finally, enable interrupts. */
+       twe_outl(sc, TWE_REG_CTL, TWE_CTL_CLEAR_ATTN_INTR |
+           TWE_CTL_UNMASK_RESP_INTR |
+           TWE_CTL_ENABLE_INTRS);
+}
+
+void
+twe_register_callbacks(struct twe_softc *sc, int unit,
+    const struct twe_callbacks *tcb)
+{
+
+       sc->sc_units[unit].td_callbacks = tcb;
+}
+
+static void
+twe_recompute_openings(struct twe_softc *sc)
+{
+       struct twe_drive *td;
+       int unit, openings;
+
+       if (sc->sc_nunits != 0)
+               openings = (TWE_MAX_QUEUECNT - 1) / sc->sc_nunits;
+       else
+               openings = 0;
+       if (openings == sc->sc_openings)
+               return;
+       sc->sc_openings = openings;
+
+#ifdef TWE_DEBUG
+       printf("%s: %d array%s, %d openings per array\n",
+           sc->sc_dv.dv_xname, sc->sc_nunits,
+           sc->sc_nunits == 1 ? "" : "s", sc->sc_openings);
+#endif
+
+       for (unit = 0; unit < TWE_MAX_UNITS; unit++) {
+               td = &sc->sc_units[unit];
+               if (td->td_dev != NULL)
+                       (*td->td_callbacks->tcb_openings)(td->td_dev,
+                           sc->sc_openings);
+       }
+}
+
+static int
+twe_add_unit(struct twe_softc *sc, int unit)
+{
+       struct twe_param *dtp, *atp;
+       struct twe_array_descriptor *ad;
+       struct twe_drive *td;
+       struct twe_attach_args twea;
+       uint32_t newsize;
+       int rv;
+       uint16_t dsize;
+       uint8_t newtype, newstripe;
+
+       if (unit < 0 || unit >= TWE_MAX_UNITS)
+               return (EINVAL);
+
        /* Find attached units. */ 
        rv = twe_param_get(sc, TWE_PARAM_UNITSUMMARY,
            TWE_PARAM_UNITSUMMARY_Status, TWE_MAX_UNITS, NULL, &dtp);
        if (rv != 0) {
-               aprint_error("%s: can't detect attached units (%d)\n",
+               aprint_error("%s: error %d fetching unit summary\n",
                    sc->sc_dv.dv_xname, rv);
-               return;
+               return (rv);
        }
 
        /* For each detected unit, collect size and store in an array. */
-       for (i = 0, sc->sc_nunits = 0; i < TWE_MAX_UNITS; i++) {
-               td = &sc->sc_units[i];
+       td = &sc->sc_units[unit];
 
-               /* Unit present? */
-               if ((dtp->tp_data[i] & TWE_PARAM_UNITSTATUS_Online) == 0) {
-                       td->td_size = 0;
-                       td->td_type = 0;
-                       td->td_stripe = 0;
-                       continue;
-               }
+       /* Unit present? */
+       if ((dtp->tp_data[unit] & TWE_PARAM_UNITSTATUS_Online) == 0) {
+               /*
+                * XXX Should we check to see if a device has been
+                * XXX attached at this index and detach it if it
+                * XXX has?  ("rescan" semantics)
+                */
+               rv = 0;
+               goto out;
+       }
+
+       rv = twe_param_get_2(sc, TWE_PARAM_UNITINFO + unit,
+           TWE_PARAM_UNITINFO_DescriptorSize, &dsize);
+       if (rv != 0) {
+               aprint_error("%s: error %d fetching descriptor size "
+                   "for unit %d\n", sc->sc_dv.dv_xname, rv, unit);
+               goto out;
+       }
 
-               rv = twe_param_get_2(sc, TWE_PARAM_UNITINFO + i,
-                   TWE_PARAM_UNITINFO_DescriptorSize, &dsize);
-               if (rv != 0) {
-                       aprint_error("%s: error %d fetching descriptor size "
-                           "for unit %d\n", sc->sc_dv.dv_xname, rv, i);
-                       td->td_size = 0;
-                       td->td_type = 0;
-                       td->td_stripe = 0;
-                       continue;
-               }
+       rv = twe_param_get(sc, TWE_PARAM_UNITINFO + unit,
+           TWE_PARAM_UNITINFO_Descriptor, dsize - 3, NULL, &atp);
+       if (rv != 0) {
+               aprint_error("%s: error %d fetching array descriptor "
+                   "for unit %d\n", sc->sc_dv.dv_xname, rv, unit);
+               goto out;
+       }
+
+       ad = (struct twe_array_descriptor *)atp->tp_data;
+       newtype = ad->configuration;
+       newstripe = ad->stripe_size;
+       free(atp, M_DEVBUF);
+
+       rv = twe_param_get_4(sc, TWE_PARAM_UNITINFO + unit,
+           TWE_PARAM_UNITINFO_Capacity, &newsize);
+       if (rv != 0) {
+               aprint_error(
+                   "%s: error %d fetching capacity for unit %d\n",
+                   sc->sc_dv.dv_xname, rv, unit);
+               goto out;
+       }
 
-               rv = twe_param_get(sc, TWE_PARAM_UNITINFO + i,
-                   TWE_PARAM_UNITINFO_Descriptor, dsize - 3, NULL, &atp);
-               if (rv != 0) {
-                       aprint_error("%s: error %d fetching array descriptor "
-                           "for unit %d\n", sc->sc_dv.dv_xname, rv, i);
-                       td->td_size = 0;
-                       td->td_type = 0;
-                       td->td_stripe = 0;
-                       continue;
-               }
-               ad = (struct twe_array_descriptor *)atp->tp_data;
-               td->td_type = ad->configuration;
-               td->td_stripe = ad->stripe_size;
-               free(atp, M_DEVBUF);
+       /*
+        * Have a device, so we need to attach it.  If there is currently
+        * something sitting at the slot, and the parameters are different,
+        * then we detach the old device before attaching the new one.
+        */
+       if (td->td_dev != NULL &&
+           td->td_size == newsize &&
+           td->td_type == newtype &&
+           td->td_stripe == newstripe) {
+               /* Same as the old device; just keep using it. */



Home | Main Index | Thread Index | Old Index