Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci - Fix the mailbox protocol. Not tested with newe...



details:   https://anonhg.NetBSD.org/src/rev/15c8fdfb39b5
branches:  trunk
changeset: 546708:15c8fdfb39b5
user:      ad <ad%NetBSD.org@localhost>
date:      Sun May 04 16:15:35 2003 +0000

description:
- Fix the mailbox protocol. Not tested with newer 'Quartz' controllers.
- Handle failure during initalisation more gracefully.
- Create a watchdog thread to poke the board and check for status changes.
- Make ready for > 64kB transfers.

diffstat:

 sys/dev/pci/amr.c    |  513 +++++++++++++++++++++++++++++++++++++++-----------
 sys/dev/pci/amrreg.h |   29 +-
 sys/dev/pci/amrvar.h |   52 +++-
 sys/dev/pci/ld_amr.c |   45 +--
 4 files changed, 460 insertions(+), 179 deletions(-)

diffs (truncated from 1255 to 300 lines):

diff -r 82e46bd4fdcc -r 15c8fdfb39b5 sys/dev/pci/amr.c
--- a/sys/dev/pci/amr.c Sun May 04 15:09:45 2003 +0000
+++ b/sys/dev/pci/amr.c Sun May 04 16:15:35 2003 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: amr.c,v 1.8 2003/01/31 00:07:40 thorpej Exp $  */
+/*     $NetBSD: amr.c,v 1.9 2003/05/04 16:15:35 ad Exp $       */
 
 /*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amr.c,v 1.8 2003/01/31 00:07:40 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amr.c,v 1.9 2003/05/04 16:15:35 ad Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -81,6 +81,7 @@
 #include <sys/proc.h>
 #include <sys/buf.h>
 #include <sys/malloc.h>
+#include <sys/kthread.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -92,15 +93,8 @@
 #include <dev/pci/amrreg.h>
 #include <dev/pci/amrvar.h>
 
-#if AMR_MAX_SEGS > 32
-#error AMR_MAX_SEGS too high
-#endif
-
-#define        AMR_ENQUIRY_BUFSIZE     2048
-#define        AMR_SGL_SIZE            (sizeof(struct amr_sgentry) * 32)
-
 void   amr_attach(struct device *, struct device *, void *);
-void   *amr_enquire(struct amr_softc *, u_int8_t, u_int8_t, u_int8_t);
+void   *amr_enquire(struct amr_softc *, u_int8_t, u_int8_t, u_int8_t, void *);
 int    amr_init(struct amr_softc *, const char *,
                         struct pci_attach_args *pa);
 int    amr_intr(void *);
@@ -108,11 +102,14 @@
 int    amr_print(void *, const char *);
 void   amr_shutdown(void *);
 int    amr_submatch(struct device *, struct cfdata *, void *);
+void   amr_teardown(struct amr_softc *);
+void   amr_thread(void *);
+void   amr_thread_create(void *);
 
 int    amr_mbox_wait(struct amr_softc *);
-int    amr_quartz_get_work(struct amr_softc *, struct amr_mailbox *);
+int    amr_quartz_get_work(struct amr_softc *, struct amr_mailbox_resp *);
 int    amr_quartz_submit(struct amr_softc *, struct amr_ccb *);
-int    amr_std_get_work(struct amr_softc *, struct amr_mailbox *);
+int    amr_std_get_work(struct amr_softc *, struct amr_mailbox_resp *);
 int    amr_std_submit(struct amr_softc *, struct amr_ccb *);
 
 static inline u_int8_t amr_inb(struct amr_softc *, int);
@@ -130,7 +127,7 @@
        u_short apt_vendor;
        u_short apt_product;
        u_short apt_flags;
-} static const amr_pci_type[] = {
+} const amr_pci_type[] = {
        { PCI_VENDOR_AMI,   PCI_PRODUCT_AMI_MEGARAID,  0 },
        { PCI_VENDOR_AMI,   PCI_PRODUCT_AMI_MEGARAID2, 0 },
        { PCI_VENDOR_AMI,   PCI_PRODUCT_AMI_MEGARAID3, AT_QUARTZ },
@@ -140,7 +137,7 @@
 struct amr_typestr {
        const char      *at_str;
        int             at_sig;
-} static const amr_typestr[] = {
+} const amr_typestr[] = {
        { "Series 431",                 AMR_SIG_431 },
        { "Series 438",                 AMR_SIG_438 },
        { "Series 466",                 AMR_SIG_466 },
@@ -151,7 +148,22 @@
        { "HP NetRAID (T7)",            AMR_SIG_T7 },
 };
 
-static void    *amr_sdh;
+struct {
+       const char      *ds_descr;
+       int     ds_happy;
+} const amr_dstate[] = {
+       { "offline",    0 },
+       { "degraded",   1 },
+       { "optimal",    1 },
+       { "online",     1 },
+       { "failed",     0 },
+       { "rebuilding", 1 },
+       { "hotspare",   0 },
+};
+
+void   *amr_sdh;
+int    amr_max_segs;
+int    amr_max_xfer;
 
 static inline u_int8_t
 amr_inb(struct amr_softc *amr, int off)
@@ -224,8 +236,7 @@
 }
 
 /*
- * Attach a supported device.  XXX This doesn't fail gracefully, and may
- * over-allocate resources.
+ * Attach a supported device.
  */
 void
 amr_attach(struct device *parent, struct device *self, void *aux)
@@ -240,8 +251,8 @@
        pci_intr_handle_t ih;
        const char *intrstr;
        pcireg_t reg;
-       int rseg, i, size, rv, memreg, ioreg;
-        bus_dma_segment_t seg;
+       int rseg, i, j, size, rv, memreg, ioreg;
+       bus_size_t memsize, iosize;
         struct amr_ccb *ac;
 
        aprint_naive(": RAID controller\n");
@@ -261,11 +272,11 @@
                reg = pci_conf_read(pc, pa->pa_tag, i);
                switch (PCI_MAPREG_TYPE(reg)) {
                case PCI_MAPREG_TYPE_MEM:
-                       if (PCI_MAPREG_MEM_SIZE(reg) != 0)
+                       if ((memsize = PCI_MAPREG_MEM_SIZE(reg)) != 0)
                                memreg = i;
                        break;
                case PCI_MAPREG_TYPE_IO:
-                       if (PCI_MAPREG_IO_SIZE(reg) != 0)
+                       if ((iosize = PCI_MAPREG_IO_SIZE(reg)) != 0)
                                ioreg = i;
                        break;
                }
@@ -283,15 +294,20 @@
        if (memreg) {
                amr->amr_iot = memt;
                amr->amr_ioh = memh;
+               amr->amr_ios = memsize;
        } else if (ioreg) {
                amr->amr_iot = iot;
                amr->amr_ioh = ioh;
+               amr->amr_ios = iosize;
        } else {
                aprint_error("can't map control registers\n");
+               amr_teardown(amr);
                return;
        }
 
+       amr->amr_flags |= AMRF_PCI_REGS;
        amr->amr_dmat = pa->pa_dmat;
+       amr->amr_pc = pa->pa_pc;
 
        /* Enable the device. */
        reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
@@ -301,6 +317,7 @@
        /* Map and establish the interrupt. */
        if (pci_intr_map(pa, &ih)) {
                aprint_error("can't map interrupt\n");
+               amr_teardown(amr);
                return;
        }
        intrstr = pci_intr_string(pc, ih);
@@ -310,8 +327,10 @@
                if (intrstr != NULL)
                        aprint_normal(" at %s", intrstr);
                aprint_normal("\n");
+               amr_teardown(amr);
                return;
        }
+       amr->amr_flags |= AMRF_PCI_INTR;
 
        /*
         * Allocate space for the mailbox and S/G lists.  Some controllers
@@ -323,43 +342,51 @@
         * size, which preceeds the standard mailbox.
         */
        size = AMR_SGL_SIZE * AMR_MAX_CMDS + 0x2000;
+       amr->amr_dmasize = size;
 
-       if ((rv = bus_dmamem_alloc(amr->amr_dmat, size, PAGE_SIZE, NULL, &seg,
-           1, &rseg, BUS_DMA_NOWAIT)) != 0) {
+       if ((rv = bus_dmamem_alloc(amr->amr_dmat, size, PAGE_SIZE, NULL,
+           &amr->amr_dmaseg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
                aprint_error("%s: unable to allocate buffer, rv = %d\n",
                    amr->amr_dv.dv_xname, rv);
+               amr_teardown(amr);
                return;
        }
+       amr->amr_flags |= AMRF_DMA_ALLOC;
 
-       if ((rv = bus_dmamem_map(amr->amr_dmat, &seg, rseg, size, 
+       if ((rv = bus_dmamem_map(amr->amr_dmat, &amr->amr_dmaseg, rseg, size, 
            (caddr_t *)&amr->amr_mbox,
            BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
                aprint_error("%s: unable to map buffer, rv = %d\n",
                    amr->amr_dv.dv_xname, rv);
+               amr_teardown(amr);
                return;
        }
+       amr->amr_flags |= AMRF_DMA_MAP;
 
        if ((rv = bus_dmamap_create(amr->amr_dmat, size, 1, size, 0, 
            BUS_DMA_NOWAIT, &amr->amr_dmamap)) != 0) {
                aprint_error("%s: unable to create buffer DMA map, rv = %d\n",
                    amr->amr_dv.dv_xname, rv);
+               amr_teardown(amr);
                return;
        }
+       amr->amr_flags |= AMRF_DMA_CREATE;
 
        if ((rv = bus_dmamap_load(amr->amr_dmat, amr->amr_dmamap,
            amr->amr_mbox, size, NULL, BUS_DMA_NOWAIT)) != 0) {
                aprint_error("%s: unable to load buffer DMA map, rv = %d\n",
                    amr->amr_dv.dv_xname, rv);
+               amr_teardown(amr);
                return;
        }
+       amr->amr_flags |= AMRF_DMA_LOAD;
 
        memset(amr->amr_mbox, 0, size);
 
-       amr->amr_mbox_paddr = amr->amr_dmamap->dm_segs[0].ds_addr + 16;
+       amr->amr_mbox_paddr = amr->amr_dmamap->dm_segs[0].ds_addr;
        amr->amr_sgls_paddr = (amr->amr_mbox_paddr + 0x1fff) & ~0x1fff;
        amr->amr_sgls = (struct amr_sgentry *)((caddr_t)amr->amr_mbox +
            amr->amr_sgls_paddr - amr->amr_dmamap->dm_segs[0].ds_addr);
-       amr->amr_mbox = (struct amr_mailbox *)((caddr_t)amr->amr_mbox + 16);
 
        /*
         * Allocate and initalise the command control blocks.
@@ -367,21 +394,28 @@
        ac = malloc(sizeof(*ac) * AMR_MAX_CMDS, M_DEVBUF, M_NOWAIT | M_ZERO);
        amr->amr_ccbs = ac;
        SLIST_INIT(&amr->amr_ccb_freelist);
+       amr->amr_flags |= AMRF_CCBS;
+
+       if (amr_max_xfer == 0) {
+               amr_max_xfer = min(((AMR_MAX_SEGS - 1) * PAGE_SIZE), MAXPHYS);
+               amr_max_segs = (amr_max_xfer + (PAGE_SIZE * 2) - 1) / PAGE_SIZE;
+       }
 
        for (i = 0; i < AMR_MAX_CMDS; i++, ac++) {
-               rv = bus_dmamap_create(amr->amr_dmat, AMR_MAX_XFER,
-                   AMR_MAX_SEGS, AMR_MAX_XFER, 0,
-                   BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
-                   &ac->ac_xfer_map);
+               rv = bus_dmamap_create(amr->amr_dmat, amr_max_xfer,
+                   amr_max_segs, amr_max_xfer, 0,
+                   BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_xfer_map);
                if (rv != 0)
                        break;
 
                ac->ac_ident = i;
-               SLIST_INSERT_HEAD(&amr->amr_ccb_freelist, ac, ac_chain.slist);
+               amr_ccb_free(amr, ac);
        }
-       if (i != AMR_MAX_CMDS)
-               aprint_error("%s: %d/%d CCBs created\n", amr->amr_dv.dv_xname,
-                   i, AMR_MAX_CMDS);
+       if (i != AMR_MAX_CMDS) {
+               aprint_error("%s: memory exhausted\n", amr->amr_dv.dv_xname);
+               amr_teardown(amr);
+               return;
+       }
 
        /*
         * Take care of model-specific tasks.
@@ -394,7 +428,7 @@
                amr->amr_get_work = amr_std_get_work;
 
                /* Notify the controller of the mailbox location. */
-               amr_outl(amr, AMR_SREG_MBOX, amr->amr_mbox_paddr);
+               amr_outl(amr, AMR_SREG_MBOX, (u_int32_t)amr->amr_mbox_paddr + 16);
                amr_outb(amr, AMR_SREG_MBOX_ENABLE, AMR_SMBOX_ENABLE_ADDR);
 
                /* Clear outstanding interrupts and enable interrupts. */
@@ -406,10 +440,14 @@
        /*
         * Retrieve parameters, and tell the world about us.
         */
+       amr->amr_enqbuf = malloc(AMR_ENQUIRY_BUFSIZE, M_DEVBUF, M_NOWAIT);
+       amr->amr_flags |= AMRF_ENQBUF;
        amr->amr_maxqueuecnt = i;
        aprint_normal(": AMI RAID ");
-       if (amr_init(amr, intrstr, pa) != 0)
+       if (amr_init(amr, intrstr, pa) != 0) {
+               amr_teardown(amr);
                return;
+       }
 
        /* 
         * Cap the maximum number of outstanding commands.  AMI's Linux



Home | Main Index | Thread Index | Old Index