Index: aac.c =================================================================== RCS file: /home/ncvs/src/sys/dev/aac/aac.c,v retrieving revision 1.118 diff -u -p -r1.118 aac.c --- aac.c 8 Apr 2006 06:05:29 -0000 1.118 +++ aac.c 18 Dec 2006 06:30:44 -0000 @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sys/dev/aac/aac. /* * 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 int aac_ioctl_sendfib(struct aac 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 @@ aac_attach(struct aac_softc *sc) 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 @@ aac_check_firmware(struct aac_softc *sc) 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,7 @@ aac_open(struct cdev *dev, int flags, in 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->aac_open_cnt++; sc->aac_state |= AAC_STATE_OPEN; return 0; @@ -2839,9 +2833,10 @@ aac_close(struct cdev *dev, int flags, i debug_called(2); sc = dev->si_drv1; - + sc->aac_open_cnt--; /* Mark this unit as no longer open */ - sc->aac_state &= ~AAC_STATE_OPEN; + if (sc->aac_open_cnt == 0) + sc->aac_state &= ~AAC_STATE_OPEN; return 0; } @@ -2852,7 +2847,6 @@ aac_ioctl(struct cdev *dev, u_long cmd, union aac_statrequest *as; struct aac_softc *sc; int error = 0; - uint32_t cookie; debug_called(2); @@ -2890,20 +2884,7 @@ aac_ioctl(struct cdev *dev, u_long cmd, 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 +2893,10 @@ aac_ioctl(struct cdev *dev, u_long cmd, 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 +2944,7 @@ aac_poll(struct cdev *dev, int poll_even 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 +3070,11 @@ aac_handle_aif(struct aac_softc *sc, str { 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 +3205,26 @@ aac_handle_aif(struct aac_softc *sc, str /* 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; - - /* 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); - } + 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 +3270,144 @@ aac_rev_check(struct aac_softc *sc, cadd } /* + * 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 == NULL) + 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)) { - 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); - } - sc->aac_state &= ~AAC_STATE_AIF_SLEEPER; + 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, 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], 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: aac_linux.c =================================================================== RCS file: /home/ncvs/src/sys/dev/aac/aac_linux.c,v retrieving revision 1.3 diff -u -p -r1.3 aac_linux.c --- aac_linux.c 30 May 2004 20:08:23 -0000 1.3 +++ aac_linux.c 18 Dec 2006 01:39:54 -0000 @@ -38,8 +38,13 @@ __FBSDID("$FreeBSD: src/sys/dev/aac/aac_ #include #include #include +#ifdef __amd64__ +#include +#include +#else #include #include +#endif #include /* There are multiple ioctl number ranges that need to be handled */ Index: aac_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/aac/aac_pci.c,v retrieving revision 1.61 diff -u -p -r1.61 aac_pci.c --- aac_pci.c 11 Dec 2006 18:28:28 -0000 1.61 +++ aac_pci.c 18 Dec 2006 06:09:38 -0000 @@ -168,14 +168,14 @@ struct aac_ident "ICP ICP9014RO SCSI 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, @@ -194,8 +194,36 @@ struct aac_ident "ICP ICP9047MA SATA RAID"}, {0x9005, 0x0286, 0x9005, 0x02a1, AAC_HWIF_RKT, 0, "ICP ICP9087MA SATA RAID"}, + {0x9005, 0x0286, 0x9005, 0x02a2, AAC_HWIF_RKT, 0, + "Adaptec SAS RAID 3800SAS"}, + {0x9005, 0x0286, 0x9005, 0x02a3, AAC_HWIF_RKT, 0, + "ICP ICP5445AU SAS RAID"}, + {0x9005, 0x0286, 0x9005, 0x02a6, AAC_HWIF_RKT, 0, + "ICP 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, + "ICP ICP5085AU SAS RAID"}, + {0x9005, 0x0286, 0x9005, 0x02aa, AAC_HWIF_RKT, 0, + "ICP 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, + "ICP 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} }; Index: aacvar.h =================================================================== RCS file: /home/ncvs/src/sys/dev/aac/aacvar.h,v retrieving revision 1.47 diff -u -p -r1.47 aacvar.h --- aacvar.h 8 Oct 2005 15:55:09 -0000 1.47 +++ aacvar.h 18 Dec 2006 06:38:29 -0000 @@ -272,6 +272,14 @@ extern struct aac_interface aac_rkt_inte #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,7 +306,8 @@ struct aac_softc #define AAC_STATE_OPEN (1<<1) #define AAC_STATE_INTERRUPTS_ON (1<<2) #define AAC_STATE_AIF_SLEEPER (1<<3) - struct FsaRevision aac_revision; + int aac_open_cnt; + struct FsaRevision aac_revision; /* controller hardware interface */ int aac_hwif; @@ -356,9 +365,10 @@ struct aac_softc /* 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;