Index: src/sys/dev/aac/aac.c =================================================================== RCS file: /home/ncvs/src/sys/dev/aac/aac.c,v retrieving revision 1.118 diff -u -b -r1.118 aac.c --- src/sys/dev/aac/aac.c 8 Apr 2006 06:05:29 -0000 1.118 +++ src/sys/dev/aac/aac.c 31 Oct 2006 20:06:09 -0000 @@ -33,7 +33,7 @@ /* * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters. */ -#define AAC_DRIVER_VERSION 0x02000000 +#define AAC_DRIVER_VERSION 0x02000007 #define AAC_DRIVERNAME "aac" #include "opt_aac.h" @@ -216,8 +216,11 @@ static void aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib); static int aac_rev_check(struct aac_softc *sc, caddr_t udata); +static int aac_open_aif(struct aac_softc *sc, caddr_t arg); +static int aac_close_aif(struct aac_softc *sc, caddr_t arg); static int aac_getnext_aif(struct aac_softc *sc, caddr_t arg); -static int aac_return_aif(struct aac_softc *sc, caddr_t uptr); +static int aac_return_aif(struct aac_softc *sc, + struct aac_fib_context *ctx, caddr_t uptr); static int aac_query_disk(struct aac_softc *sc, caddr_t uptr); static int aac_get_pci_info(struct aac_softc *sc, caddr_t uptr); static void aac_ioctl_event(struct aac_softc *sc, @@ -283,9 +286,6 @@ TAILQ_INIT(&sc->aac_container_tqh); TAILQ_INIT(&sc->aac_ev_cmfree); - /* Initialize the local AIF queue pointers */ - sc->aac_aifq_head = sc->aac_aifq_tail = AAC_AIFQ_LENGTH; - /* * Initialise the adapter. */ @@ -1668,14 +1668,12 @@ sc->aac_max_sectors = 128; /* 64KB */ if (sc->flags & AAC_FLAGS_SG_64BIT) sc->aac_sg_tablesize = (AAC_FIB_DATASIZE - - sizeof(struct aac_blockwrite64) - + sizeof(struct aac_sg_table64)) - / sizeof(struct aac_sg_table64); + - sizeof(struct aac_blockwrite64)) + / sizeof(struct aac_sg_entry64); else sc->aac_sg_tablesize = (AAC_FIB_DATASIZE - - sizeof(struct aac_blockwrite) - + sizeof(struct aac_sg_table)) - / sizeof(struct aac_sg_table); + - sizeof(struct aac_blockwrite)) + / sizeof(struct aac_sg_entry); if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) { options = AAC_GET_MAILBOX(sc, 1); @@ -2821,11 +2819,8 @@ debug_called(2); sc = dev->si_drv1; - - /* Check to make sure the device isn't already open */ - if (sc->aac_state & AAC_STATE_OPEN) { - return EBUSY; - } + sc = dev->si_drv1; + sc->aac_open_cnt++; sc->aac_state |= AAC_STATE_OPEN; return 0; @@ -2839,8 +2834,9 @@ debug_called(2); sc = dev->si_drv1; - + sc->aac_open_cnt--; /* Mark this unit as no longer open */ + if (sc->aac_open_cnt == 0) sc->aac_state &= ~AAC_STATE_OPEN; return 0; @@ -2852,7 +2848,6 @@ union aac_statrequest *as; struct aac_softc *sc; int error = 0; - uint32_t cookie; debug_called(2); @@ -2890,20 +2885,7 @@ arg = *(caddr_t*)arg; case FSACTL_LNX_OPEN_GET_ADAPTER_FIB: debug(1, "FSACTL_OPEN_GET_ADAPTER_FIB"); - /* - * Pass the caller out an AdapterFibContext. - * - * Note that because we only support one opener, we - * basically ignore this. Set the caller's context to a magic - * number just in case. - * - * The Linux code hands the driver a pointer into kernel space, - * and then trusts it when the caller hands it back. Aiee! - * Here, we give it the proc pointer of the per-adapter aif - * thread. It's only used as a sanity check in other calls. - */ - cookie = (uint32_t)(uintptr_t)sc->aifthread; - error = copyout(&cookie, arg, sizeof(cookie)); + error = aac_open_aif(sc, arg); break; case FSACTL_GET_NEXT_ADAPTER_FIB: arg = *(caddr_t*)arg; @@ -2912,9 +2894,10 @@ error = aac_getnext_aif(sc, arg); break; case FSACTL_CLOSE_GET_ADAPTER_FIB: + arg = *(caddr_t*)arg; case FSACTL_LNX_CLOSE_GET_ADAPTER_FIB: debug(1, "FSACTL_CLOSE_GET_ADAPTER_FIB"); - /* don't do anything here */ + error = aac_close_aif(sc, arg); break; case FSACTL_MINIPORT_REV_CHECK: arg = *(caddr_t*)arg; @@ -2962,7 +2945,7 @@ mtx_lock(&sc->aac_aifq_lock); if ((poll_events & (POLLRDNORM | POLLIN)) != 0) { - if (sc->aac_aifq_tail != sc->aac_aifq_head) + if (sc->aifq_idx != 0 || sc->aifq_filled) revents |= poll_events & (POLLIN | POLLRDNORM); } mtx_unlock(&sc->aac_aifq_lock); @@ -3088,10 +3071,11 @@ { struct aac_aif_command *aif; struct aac_container *co, *co_next; + struct aac_fib_context *ctx; struct aac_mntinfo *mi; struct aac_mntinforesp *mir = NULL; u_int16_t rsize; - int next, found; + int next, current, found; int count = 0, added = 0, i = 0; debug_called(2); @@ -3222,17 +3206,26 @@ /* Copy the AIF data to the AIF queue for ioctl retrieval */ mtx_lock(&sc->aac_aifq_lock); - next = (sc->aac_aifq_head + 1) % AAC_AIFQ_LENGTH; - if (next != sc->aac_aifq_tail) { - bcopy(aif, &sc->aac_aifq[next], sizeof(struct aac_aif_command)); - sc->aac_aifq_head = next; - + current = sc->aifq_idx; + next = (current + 1) % AAC_AIFQ_LENGTH; + if (next == 0) + sc->aifq_filled = 1; + bcopy(fib, &sc->aac_aifq[current], sizeof (struct aac_fib)); + /* modify AIF contexts */ + if (sc->aifq_filled) { + for (ctx = sc->fibctx; ctx; ctx = ctx->next) { + if (next == ctx->ctx_idx) + ctx->ctx_wrap = 1; + else if (current == ctx->ctx_idx && ctx->ctx_wrap) + ctx->ctx_idx = next; + } + } + sc->aifq_idx = next; /* On the off chance that someone is sleeping for an aif... */ if (sc->aac_state & AAC_STATE_AIF_SLEEPER) wakeup(sc->aac_aifq); /* Wakeup any poll()ers */ selwakeuppri(&sc->rcv_select, PRIBIO); - } mtx_unlock(&sc->aac_aifq_lock); return; @@ -3278,68 +3271,144 @@ } /* + * Pass the fib context to the caller + */ +static int +aac_open_aif(struct aac_softc *sc, caddr_t arg) +{ + struct aac_fib_context *fibctx, *ctx; + int error = 0; + + debug_called(2); + + fibctx = malloc(sizeof(struct aac_fib_context), M_AACBUF, M_NOWAIT|M_ZERO); + if (fibctx == NULL) + return (ENOMEM); + + mtx_lock(&sc->aac_aifq_lock); + /* all elements are already 0, add to queue */ + if (sc->fibctx == NULL) + sc->fibctx = fibctx; + else { + for (ctx = sc->fibctx; ctx->next; ctx = ctx->next) + ; + ctx->next = fibctx; + fibctx->prev = ctx; + } + + /* evaluate unique value */ + fibctx->unique = (*(u_int32_t *)&fibctx & 0xffffffff); + ctx = sc->fibctx; + while (ctx != fibctx) { + if (ctx->unique == fibctx->unique) { + fibctx->unique++; + ctx = sc->fibctx; + } else { + ctx = ctx->next; + } + } + mtx_unlock(&sc->aac_aifq_lock); + + error = copyout(&fibctx->unique, (void *)arg, sizeof(u_int32_t)); + if (error) + aac_close_aif(sc, (caddr_t)ctx); + return (error); +} + +/* + * Close the caller's fib context + */ +static int +aac_close_aif(struct aac_softc *sc, caddr_t arg) +{ + struct aac_fib_context *ctx; + + debug_called(2); + + mtx_lock(&sc->aac_aifq_lock); + for (ctx = sc->fibctx; ctx; ctx = ctx->next) { + if (ctx->unique == *(uint32_t *)&arg) { + if (ctx == sc->fibctx) + sc->fibctx = NULL; + else { + ctx->prev->next = ctx->next; + if (ctx->next) + ctx->next->prev = ctx->prev; + } + break; + } + } + mtx_unlock(&sc->aac_aifq_lock); + if (ctx) + free(ctx, M_AACBUF); + + return (0); +} + +/* * Pass the caller the next AIF in their queue */ static int aac_getnext_aif(struct aac_softc *sc, caddr_t arg) { struct get_adapter_fib_ioctl agf; + struct aac_fib_context *ctx; int error; debug_called(2); if ((error = copyin(arg, &agf, sizeof(agf))) == 0) { + for (ctx = sc->fibctx; ctx; ctx = ctx->next) { + if (agf.AdapterFibContext == ctx->unique) + break; + } + if (!ctx) + return (EFAULT); - /* - * Check the magic number that we gave the caller. - */ - if (agf.AdapterFibContext != (int)(uintptr_t)sc->aifthread) { - error = EFAULT; - } else { - error = aac_return_aif(sc, agf.AifFib); - if ((error == EAGAIN) && (agf.Wait)) { + error = aac_return_aif(sc, ctx, agf.AifFib); + if (error == EAGAIN && agf.Wait) { + debug(2, "aac_getnext_aif(): waiting for AIF"); sc->aac_state |= AAC_STATE_AIF_SLEEPER; while (error == EAGAIN) { error = tsleep(sc->aac_aifq, PRIBIO | PCATCH, "aacaif", 0); if (error == 0) - error = aac_return_aif(sc, - agf.AifFib); + error = aac_return_aif(sc, ctx, agf.AifFib); } sc->aac_state &= ~AAC_STATE_AIF_SLEEPER; } } - } - return(error); + return (error); } /* * Hand the next AIF off the top of the queue out to userspace. */ static int -aac_return_aif(struct aac_softc *sc, caddr_t uptr) +aac_return_aif(struct aac_softc *sc, struct aac_fib_context *ctx, caddr_t uptr) { - int next, error; + int current, error; debug_called(2); mtx_lock(&sc->aac_aifq_lock); - if (sc->aac_aifq_tail == sc->aac_aifq_head) { + current = ctx->ctx_idx; + if (current == sc->aifq_idx && !ctx->ctx_wrap) { + /* empty */ mtx_unlock(&sc->aac_aifq_lock); return (EAGAIN); } - - next = (sc->aac_aifq_tail + 1) % AAC_AIFQ_LENGTH; - error = copyout(&sc->aac_aifq[next], uptr, - sizeof(struct aac_aif_command)); + error = + copyout(&sc->aac_aifq[current], (void *)uptr, sizeof(struct aac_fib)); if (error) device_printf(sc->aac_dev, "aac_return_aif: copyout returned %d\n", error); - else - sc->aac_aifq_tail = next; - + else { + ctx->ctx_wrap = 0; + ctx->ctx_idx = (current + 1) % AAC_AIFQ_LENGTH; + } mtx_unlock(&sc->aac_aifq_lock); - return(error); + return (error); } static int Index: src/sys/dev/aac/aac_linux.c =================================================================== RCS file: /home/ncvs/src/sys/dev/aac/aac_linux.c,v retrieving revision 1.3 diff -u -b -r1.3 aac_linux.c --- src/sys/dev/aac/aac_linux.c 30 May 2004 20:08:23 -0000 1.3 +++ src/sys/dev/aac/aac_linux.c 31 Oct 2006 20:06:09 -0000 @@ -38,8 +38,13 @@ #include #include #include +#ifdef __amd64__ +#include +#include +#else #include #include +#endif #include /* There are multiple ioctl number ranges that need to be handled */ Index: src/sys/dev/aac/aac_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/aac/aac_pci.c,v retrieving revision 1.59 diff -u -b -r1.59 aac_pci.c --- src/sys/dev/aac/aac_pci.c 17 Jun 2006 18:42:26 -0000 1.59 +++ src/sys/dev/aac/aac_pci.c 31 Oct 2006 20:06:10 -0000 @@ -126,13 +126,13 @@ {0x9005, 0x0285, 0x9005, 0x0286, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB | AAC_FLAGS_256FIBS, "Adaptec SCSI RAID 2120S"}, {0x9005, 0x0285, 0x9005, 0x0290, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB, - "Adaptec SATA RAID 2410SA"}, + "Adaptec SCSI RAID 2410SA"}, {0x9005, 0x0285, 0x1028, 0x0291, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB, "Dell CERC SATA RAID 2"}, {0x9005, 0x0285, 0x9005, 0x0292, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB, - "Adaptec SATA RAID 2810SA"}, + "Adaptec SCSI RAID 2810SA"}, {0x9005, 0x0285, 0x9005, 0x0293, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB, - "Adaptec SATA RAID 21610SA"}, + "Adaptec SCSI RAID 21610SA"}, {0x9005, 0x0285, 0x103c, 0x3227, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB, "HP ML110 G2 (Adaptec 2610SA)"}, {0x9005, 0x0286, 0x9005, 0x028c, AAC_HWIF_RKT, 0, @@ -161,19 +161,19 @@ {0x9005, 0x0286, 0x9005, 0x029d, AAC_HWIF_RKT, 0, "Adaptec SATA RAID 2420SA"}, {0x9005, 0x0286, 0x9005, 0x029e, AAC_HWIF_RKT, 0, - "ICP ICP9024RO SCSI RAID"}, + "ICP9024RO SATA RAID"}, {0x9005, 0x0286, 0x9005, 0x029f, AAC_HWIF_RKT, 0, - "ICP ICP9014RO SCSI RAID"}, + "ICP9014RO SATA RAID"}, {0x9005, 0x0285, 0x9005, 0x0294, AAC_HWIF_I960RX, 0, "Adaptec SATA RAID 2026ZCR"}, - {0x9005, 0x0285, 0x103c, 0x3227, AAC_HWIF_I960RX, 0, - "Adaptec SATA RAID 2610SA"}, {0x9005, 0x0285, 0x9005, 0x0296, AAC_HWIF_I960RX, 0, "Adaptec SCSI RAID 2240S"}, {0x9005, 0x0285, 0x9005, 0x0297, AAC_HWIF_I960RX, 0, "Adaptec SAS RAID 4005SAS"}, {0x9005, 0x0285, 0x1014, 0x02f2, AAC_HWIF_I960RX, 0, "IBM ServeRAID 8i"}, + {0x9005, 0x0285, 0x1014, 0x0312, AAC_HWIF_I960RX, 0, + "IBM ServeRAID 8i"}, {0x9005, 0x0285, 0x9005, 0x0298, AAC_HWIF_I960RX, 0, "Adaptec SAS RAID 4000SAS"}, {0x9005, 0x0285, 0x9005, 0x0299, AAC_HWIF_I960RX, 0, @@ -185,13 +185,43 @@ {0x9005, 0x0285, 0x9005, 0x028f, AAC_HWIF_I960RX, 0, "Adaptec SATA RAID 2025SA ZCR"}, {0x9005, 0x0285, 0x9005, 0x02a4, AAC_HWIF_I960RX, 0, - "ICP ICP9085LI SAS RAID"}, + "ICP 9085LI SAS RAID"}, {0x9005, 0x0285, 0x9005, 0x02a5, AAC_HWIF_I960RX, 0, - "ICP ICP5085BR SAS RAID"}, + "ICP 5085BR SAS RAID"}, {0x9005, 0x0286, 0x9005, 0x02a0, AAC_HWIF_RKT, 0, - "ICP ICP9047MA SATA RAID"}, + "ICP9047MA SATA RAID"}, {0x9005, 0x0286, 0x9005, 0x02a1, AAC_HWIF_RKT, 0, - "ICP ICP9087MA SATA RAID"}, + "ICP9087MA SATA RAID"}, + {0x9005, 0x0286, 0x9005, 0x02a2, AAC_HWIF_RKT, 0, + "Adaptec SAS RAID 3800SAS"}, + {0x9005, 0x0286, 0x9005, 0x02a3, AAC_HWIF_RKT, 0, + "ICP5445AU SAS RAID"}, + {0x9005, 0x0286, 0x9005, 0x02a6, AAC_HWIF_RKT, 0, + "ICP9067MA SATA RAID"}, + {0x9005, 0x0286, 0x9005, 0x02a7, AAC_HWIF_RKT, 0, + "Adaptec SAS RAID 3805SAS"}, + {0x9005, 0x0286, 0x9005, 0x02a8, AAC_HWIF_RKT, 0, + "Adaptec SAS RAID 3400SAS"}, + {0x9005, 0x0286, 0x9005, 0x02a9, AAC_HWIF_RKT, 0, + "ICP5085AU SAS RAID"}, + {0x9005, 0x0286, 0x9005, 0x02aa, AAC_HWIF_RKT, 0, + "ICP5045AU SAS RAID"}, + {0x9005, 0x0286, 0x9005, 0x02ac, AAC_HWIF_RKT, 0, + "Adaptec SAS RAID 1800SAS"}, + {0x9005, 0x0286, 0x9005, 0x02b3, AAC_HWIF_RKT, 0, + "Adaptec SAS RAID 2400SAS"}, + {0x9005, 0x0286, 0x9005, 0x02b4, AAC_HWIF_RKT, 0, + "ICP5045AL SAS RAID"}, + {0x9005, 0x0285, 0x9005, 0x02b5, AAC_HWIF_I960RX, 0, + "Adaptec RAID ASR5800"}, + {0x9005, 0x0285, 0x9005, 0x02b6, AAC_HWIF_I960RX, 0, + "Adaptec RAID ASR5805"}, + {0x9005, 0x0285, 0x9005, 0x02b7, AAC_HWIF_I960RX, 0, + "Adaptec RAID ASR5808"}, + {0x9005, 0x0286, 0x1014, 0x9580, AAC_HWIF_RKT, 0, + "IBM ServeRAID 8k"}, + {0x9005, 0x0286, 0x1014, 0x034d, AAC_HWIF_RKT, 0, + "IBM ServeRAID 8s"}, {0, 0, 0, 0, 0, 0, 0} }; @@ -223,7 +253,7 @@ if ((id = aac_find_ident(dev)) != NULL) { device_set_desc(dev, id->desc); - return(BUS_PROBE_DEFAULT); + return (BUS_PROBE_SPECIFIC); } return(ENXIO); } Index: src/sys/dev/aac/aacvar.h =================================================================== RCS file: /home/ncvs/src/sys/dev/aac/aacvar.h,v retrieving revision 1.47 diff -u -b -r1.47 aacvar.h --- src/sys/dev/aac/aacvar.h 8 Oct 2005 15:55:09 -0000 1.47 +++ src/sys/dev/aac/aacvar.h 31 Oct 2006 20:06:12 -0000 @@ -272,6 +272,14 @@ #define AAC_GETREG1(sc, reg) bus_space_read_1 (sc->aac_btag, \ sc->aac_bhandle, reg) +/* fib context (IOCTL) */ +struct aac_fib_context { + u_int32_t unique; + int ctx_idx; + int ctx_wrap; + struct aac_fib_context *next, *prev; +}; + /* * Per-controller structure. */ @@ -298,6 +306,7 @@ #define AAC_STATE_OPEN (1<<1) #define AAC_STATE_INTERRUPTS_ON (1<<2) #define AAC_STATE_AIF_SLEEPER (1<<3) + int aac_open_cnt; struct FsaRevision aac_revision; /* controller hardware interface */ @@ -356,9 +365,10 @@ /* management interface */ struct cdev *aac_dev_t; struct mtx aac_aifq_lock; - struct aac_aif_command aac_aifq[AAC_AIFQ_LENGTH]; - int aac_aifq_head; - int aac_aifq_tail; + struct aac_fib aac_aifq[AAC_AIFQ_LENGTH]; + int aifq_idx; + int aifq_filled; + struct aac_fib_context *fibctx; struct selinfo rcv_select; struct proc *aifthread; int aifflags;