Sync to -current Scott's Mega Update, fixes and Linux ioctl wrapper.
Mega update to the LSI MegaRAID driver: 1. Implement a large set of ioctl shims so that the Linux management apps from LSI will work. This includes infrastructure to support adding, deleting and rescanning arrays at runtime. This is based on work from Doug Ambrosko, heavily augmented by LSI and Yahoo. 2. Implement full 64-bit DMA support. Systems with more than 4GB of RAM can now operate without the cost of bounce buffers. Cards that cannot do 64-bit DMA will automatically revert to using bounce buffers. This option can be forced off by setting the 'hw.amr.force_sg32" tunable in the loader. It should only be turned off for debugging purposes. This work was sponsored by Yahoo. 3. Streamline the command delivery and interrupt handler paths after much discussion with Dell and LSI. The logic now closely matches the intended design, making it both more robust and much faster. Certain i/o failures under heavy load should be fixed with this. 4. Optimize the locking. In the interrupt handler, the card can be checked for completed commands without any locks held, due to the handler being implicitely serialized and there being no need to look at any shared data. Only grab the lock to return the command structure to the free pool. A small optimization can still be made to collect all of the completions together and then free them together under a single lock. Items 3 and 4 significantly increase the performance of the driver. On an LSI 320-2X card, transactions per second went from 13,000 to 31,000 in my testing with these changes. However, these changes are still fairly experimental and shouldn't be merged to 6.x until there is more testing. Thanks to Doug Ambrisko, LSI, Dell, and Yahoo for contributing towards this. These have now had more testing and Scott requested them to be merged before the freeze.
This commit is contained in:
parent
7fcb1e9c3c
commit
1cb251eec8
File diff suppressed because it is too large
Load Diff
@ -62,7 +62,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <dev/amr/amr_compat.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/stat.h>
|
||||
@ -94,33 +94,24 @@ static void amr_cam_complete_extcdb(struct amr_command *ac);
|
||||
static __inline void
|
||||
amr_enqueue_ccb(struct amr_softc *sc, union ccb *ccb)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
TAILQ_INSERT_TAIL(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
amr_requeue_ccb(struct amr_softc *sc, union ccb *ccb)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
TAILQ_INSERT_HEAD(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static __inline union ccb *
|
||||
amr_dequeue_ccb(struct amr_softc *sc)
|
||||
{
|
||||
union ccb *ccb;
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
if ((ccb = (union ccb *)TAILQ_FIRST(&sc->amr_cam_ccbq)) != NULL)
|
||||
TAILQ_REMOVE(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
|
||||
splx(s);
|
||||
return(ccb);
|
||||
}
|
||||
|
||||
@ -262,10 +253,10 @@ amr_cam_action(struct cam_sim *sim, union ccb *ccb)
|
||||
/* save the channel number in the ccb */
|
||||
csio->ccb_h.sim_priv.entries[0].field = cam_sim_bus(sim);
|
||||
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
mtx_lock(&sc->amr_list_lock);
|
||||
amr_enqueue_ccb(sc, ccb);
|
||||
amr_startio(sc);
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
mtx_unlock(&sc->amr_list_lock);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -465,11 +456,17 @@ amr_cam_command(struct amr_softc *sc, struct amr_command **acp)
|
||||
ac->ac_length = sizeof(*aep);
|
||||
ac->ac_complete = amr_cam_complete_extcdb;
|
||||
ac->ac_mailbox.mb_command = AMR_CMD_EXTPASS;
|
||||
if (AMR_IS_SG64(sc))
|
||||
ac->ac_flags |= AMR_CMD_SG64;
|
||||
} else {
|
||||
ac->ac_data = ap;
|
||||
ac->ac_length = sizeof(*ap);
|
||||
ac->ac_complete = amr_cam_complete;
|
||||
ac->ac_mailbox.mb_command = AMR_CMD_PASS;
|
||||
if (AMR_IS_SG64(sc)) {
|
||||
ac->ac_mailbox.mb_command = AMR_CMD_PASS_64;
|
||||
ac->ac_flags |= AMR_CMD_SG64;
|
||||
} else
|
||||
ac->ac_mailbox.mb_command = AMR_CMD_PASS;
|
||||
}
|
||||
|
||||
out:
|
||||
@ -493,11 +490,8 @@ out:
|
||||
static void
|
||||
amr_cam_poll(struct cam_sim *sim)
|
||||
{
|
||||
struct amr_softc *sc = cam_sim_softc(sim);
|
||||
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
amr_done(cam_sim_softc(sim));
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
|
@ -1,108 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2000 Michael Smith
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Copyright (c) 2002 Eric Moore
|
||||
* Copyright (c) 2002 LSI Logic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The party using or redistributing the source code and binary forms
|
||||
* agrees to the disclaimer below and the terms and conditions set forth
|
||||
* herein.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
/*
|
||||
* Backwards compatibility support.
|
||||
*/
|
||||
|
||||
#if __FreeBSD_version < 500003 /* old buf style */
|
||||
# include <sys/buf.h>
|
||||
# include <machine/clock.h>
|
||||
# define INTR_ENTROPY 0
|
||||
|
||||
# define FREEBSD_4
|
||||
# define bio buf
|
||||
# define bioq_init(x) bufq_init(x)
|
||||
# define bioq_insert_tail(x, y) bufq_insert_tail(x, y)
|
||||
# define bioq_remove(x, y) bufq_remove(x, y)
|
||||
# define bioq_first(x) bufq_first(x)
|
||||
# define bio_queue_head buf_queue_head
|
||||
# define bio_bcount b_bcount
|
||||
# define bio_blkno b_blkno
|
||||
# define bio_caller1 b_caller1
|
||||
# define bio_data b_data
|
||||
# define bio_dev b_dev
|
||||
# define bio_driver1 b_driver1
|
||||
# define bio_driver2 b_driver2
|
||||
# define bio_error b_error
|
||||
# define bio_flags b_flags
|
||||
# define bio_pblkno b_pblkno
|
||||
# define bio_resid b_resid
|
||||
# define BIO_ERROR B_ERROR
|
||||
# define devstat_end_transaction_bio(x, y) devstat_end_transaction_buf(x, y)
|
||||
# define BIO_IS_READ(x) ((x)->b_flags & B_READ)
|
||||
# define AMR_BIO_FINISH(x) devstat_end_transaction_bio(&sc->amrd_stats, x);\
|
||||
biodone(x)
|
||||
|
||||
#else
|
||||
# include <sys/bio.h>
|
||||
# define BIO_IS_READ(x) ((x)->bio_cmd == BIO_READ)
|
||||
# define AMR_BIO_FINISH(x) biodone(x)
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
* Compatibility with older versions of FreeBSD
|
||||
*/
|
||||
#if __FreeBSD_version < 440001
|
||||
typedef struct proc d_thread_t;
|
||||
#define M_ZERO 0x0008 /* bzero the allocation */
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __packed
|
||||
#define __packed __attribute__ ((packed))
|
||||
#endif
|
@ -67,7 +67,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <dev/amr/amr_compat.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
|
||||
@ -89,7 +89,7 @@ static disk_strategy_t amrd_strategy;
|
||||
|
||||
static devclass_t amrd_devclass;
|
||||
#ifdef FREEBSD_4
|
||||
static int disks_registered = 0;
|
||||
int amr_disks_registered = 0;
|
||||
#endif
|
||||
|
||||
static device_method_t amrd_methods[] = {
|
||||
@ -111,9 +111,6 @@ static int
|
||||
amrd_open(struct disk *dp)
|
||||
{
|
||||
struct amrd_softc *sc = (struct amrd_softc *)dp->d_drv1;
|
||||
#if __FreeBSD_version < 500000 /* old buf style */
|
||||
struct disklabel *label;
|
||||
#endif
|
||||
|
||||
debug_called(1);
|
||||
|
||||
@ -124,23 +121,6 @@ amrd_open(struct disk *dp)
|
||||
if (sc->amrd_controller->amr_state & AMR_STATE_SHUTDOWN)
|
||||
return(ENXIO);
|
||||
|
||||
#if __FreeBSD_version < 500000 /* old buf style */
|
||||
label = &sc->amrd_disk.d_label;
|
||||
bzero(label, sizeof(*label));
|
||||
label->d_type = DTYPE_SCSI;
|
||||
label->d_secsize = AMR_BLKSIZE;
|
||||
label->d_nsectors = sc->amrd_drive->al_sectors;
|
||||
label->d_ntracks = sc->amrd_drive->al_heads;
|
||||
label->d_ncylinders = sc->amrd_drive->al_cylinders;
|
||||
label->d_secpercyl = sc->amrd_drive->al_sectors * sc->amrd_drive->al_heads;
|
||||
label->d_secperunit = sc->amrd_drive->al_size;
|
||||
#else
|
||||
sc->amrd_disk->d_sectorsize = AMR_BLKSIZE;
|
||||
sc->amrd_disk->d_mediasize = (off_t)sc->amrd_drive->al_size * AMR_BLKSIZE;
|
||||
sc->amrd_disk->d_fwsectors = sc->amrd_drive->al_sectors;
|
||||
sc->amrd_disk->d_fwheads = sc->amrd_drive->al_heads;
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
/********************************************************************************
|
||||
@ -216,7 +196,7 @@ amrd_intr(void *data)
|
||||
bio->bio_resid = 0;
|
||||
}
|
||||
|
||||
AMR_BIO_FINISH(bio);
|
||||
biodone(bio);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -257,10 +237,11 @@ amrd_attach(device_t dev)
|
||||
sc->amrd_disk->d_dump = (dumper_t *)amrd_dump;
|
||||
sc->amrd_disk->d_unit = sc->amrd_unit;
|
||||
sc->amrd_disk->d_flags = 0;
|
||||
sc->amrd_disk->d_sectorsize = AMR_BLKSIZE;
|
||||
sc->amrd_disk->d_mediasize = (off_t)sc->amrd_drive->al_size * AMR_BLKSIZE;
|
||||
sc->amrd_disk->d_fwsectors = sc->amrd_drive->al_sectors;
|
||||
sc->amrd_disk->d_fwheads = sc->amrd_drive->al_heads;
|
||||
disk_create(sc->amrd_disk, DISK_VERSION);
|
||||
#ifdef FREEBSD_4
|
||||
disks_registered++;
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -276,7 +257,7 @@ amrd_detach(device_t dev)
|
||||
return(EBUSY);
|
||||
|
||||
#ifdef FREEBSD_4
|
||||
if (--disks_registered == 0)
|
||||
if (--amr_disks_registered == 0)
|
||||
cdevsw_remove(&amrddisk_cdevsw);
|
||||
#else
|
||||
disk_destroy(sc->amrd_disk);
|
||||
|
@ -61,8 +61,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <dev/amr/amr_compat.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
|
||||
@ -90,6 +91,12 @@ static int amr_sglist_map(struct amr_softc *sc);
|
||||
static void amr_setup_mbox_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error);
|
||||
static int amr_setup_mbox(struct amr_softc *sc);
|
||||
|
||||
static u_int amr_force_sg32 = 0;
|
||||
TUNABLE_INT("hw.amr.force_sg32", &amr_force_sg32);
|
||||
SYSCTL_DECL(_hw_amr);
|
||||
SYSCTL_UINT(_hw_amr, OID_AUTO, force_sg32, CTLFLAG_RDTUN, &amr_force_sg32, 0,
|
||||
"Force the AMR driver to use 32bit scatter gather");
|
||||
|
||||
static device_method_t amr_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, amr_pci_probe),
|
||||
@ -113,48 +120,61 @@ static driver_t amr_pci_driver = {
|
||||
static devclass_t amr_devclass;
|
||||
DRIVER_MODULE(amr, pci, amr_pci_driver, amr_devclass, 0, 0);
|
||||
|
||||
static struct
|
||||
static struct amr_ident
|
||||
{
|
||||
int vendor;
|
||||
int device;
|
||||
int flag;
|
||||
#define PROBE_SIGNATURE (1<<0)
|
||||
int flags;
|
||||
#define AMR_ID_PROBE_SIG (1<<0) /* generic i960RD, check signature */
|
||||
#define AMR_ID_DO_SG64 (1<<1)
|
||||
#define AMR_ID_QUARTZ (1<<2)
|
||||
} amr_device_ids[] = {
|
||||
{0x101e, 0x9010, 0},
|
||||
{0x101e, 0x9060, 0},
|
||||
{0x8086, 0x1960, PROBE_SIGNATURE},/* generic i960RD, check for signature */
|
||||
{0x101e, 0x1960, 0},
|
||||
{0x1000, 0x1960, PROBE_SIGNATURE},
|
||||
{0x1000, 0x0407, 0},
|
||||
{0x1000, 0x0408, 0},
|
||||
{0x1000, 0x0409, 0},
|
||||
{0x1028, 0x000e, PROBE_SIGNATURE}, /* perc4/di i960 */
|
||||
{0x1028, 0x000f, 0}, /* perc4/di Verde*/
|
||||
{0x1028, 0x0013, 0}, /* perc4/di */
|
||||
{0x8086, 0x1960, AMR_ID_QUARTZ | AMR_ID_PROBE_SIG},
|
||||
{0x101e, 0x1960, AMR_ID_QUARTZ},
|
||||
{0x1000, 0x1960, AMR_ID_QUARTZ | AMR_ID_PROBE_SIG},
|
||||
{0x1000, 0x0407, AMR_ID_QUARTZ | AMR_ID_DO_SG64},
|
||||
{0x1000, 0x0408, AMR_ID_QUARTZ | AMR_ID_DO_SG64},
|
||||
{0x1000, 0x0409, AMR_ID_QUARTZ | AMR_ID_DO_SG64},
|
||||
{0x1028, 0x000e, AMR_ID_QUARTZ | AMR_ID_DO_SG64 | AMR_ID_PROBE_SIG}, /* perc4/di i960 */
|
||||
{0x1028, 0x000f, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, /* perc4/di Verde*/
|
||||
{0x1028, 0x0013, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, /* perc4/di */
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
static int
|
||||
amr_pci_probe(device_t dev)
|
||||
static struct amr_ident *
|
||||
amr_find_ident(device_t dev)
|
||||
{
|
||||
int i, sig;
|
||||
struct amr_ident *id;
|
||||
int sig;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
for (i = 0; amr_device_ids[i].vendor != 0; i++) {
|
||||
if ((pci_get_vendor(dev) == amr_device_ids[i].vendor) &&
|
||||
(pci_get_device(dev) == amr_device_ids[i].device)) {
|
||||
for (id = amr_device_ids; id->vendor != 0; id++) {
|
||||
if ((pci_get_vendor(dev) == id->vendor) &&
|
||||
(pci_get_device(dev) == id->device)) {
|
||||
|
||||
/* do we need to test for a signature? */
|
||||
if (amr_device_ids[i].flag & PROBE_SIGNATURE) {
|
||||
if (id->flags & AMR_ID_PROBE_SIG) {
|
||||
sig = pci_read_config(dev, AMR_CFG_SIG, 2);
|
||||
if ((sig != AMR_SIGNATURE_1) && (sig != AMR_SIGNATURE_2))
|
||||
continue;
|
||||
}
|
||||
device_set_desc(dev, LSI_DESC_PCI);
|
||||
return(BUS_PROBE_DEFAULT);
|
||||
return (id);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
amr_pci_probe(device_t dev)
|
||||
{
|
||||
|
||||
debug_called(1);
|
||||
|
||||
if (amr_find_ident(dev) != NULL) {
|
||||
device_set_desc(dev, LSI_DESC_PCI);
|
||||
return(BUS_PROBE_DEFAULT);
|
||||
}
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
@ -162,6 +182,7 @@ static int
|
||||
amr_pci_attach(device_t dev)
|
||||
{
|
||||
struct amr_softc *sc;
|
||||
struct amr_ident *id;
|
||||
int rid, rtype, error;
|
||||
u_int32_t command;
|
||||
|
||||
@ -173,7 +194,6 @@ amr_pci_attach(device_t dev)
|
||||
sc = device_get_softc(dev);
|
||||
bzero(sc, sizeof(*sc));
|
||||
sc->amr_dev = dev;
|
||||
mtx_init(&sc->amr_io_lock, "AMR IO Lock", NULL, MTX_DEF);
|
||||
|
||||
/* assume failure is 'not configured' */
|
||||
error = ENXIO;
|
||||
@ -181,30 +201,35 @@ amr_pci_attach(device_t dev)
|
||||
/*
|
||||
* Determine board type.
|
||||
*/
|
||||
if ((id = amr_find_ident(dev)) == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
command = pci_read_config(dev, PCIR_COMMAND, 1);
|
||||
if ((pci_get_device(dev) == 0x1960) || (pci_get_device(dev) == 0x0407) ||
|
||||
(pci_get_device(dev) == 0x0408) || (pci_get_device(dev) == 0x0409) ||
|
||||
(pci_get_device(dev) == 0x000e) || (pci_get_device(dev) == 0x000f) ||
|
||||
(pci_get_device(dev) == 0x0013)) {
|
||||
if (id->flags & AMR_ID_QUARTZ) {
|
||||
/*
|
||||
* Make sure we are going to be able to talk to this board.
|
||||
*/
|
||||
if ((command & PCIM_CMD_MEMEN) == 0) {
|
||||
device_printf(dev, "memory window not available\n");
|
||||
goto out;
|
||||
return (ENXIO);
|
||||
}
|
||||
sc->amr_type |= AMR_TYPE_QUARTZ;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Make sure we are going to be able to talk to this board.
|
||||
*/
|
||||
if ((command & PCIM_CMD_PORTEN) == 0) {
|
||||
device_printf(dev, "I/O window not available\n");
|
||||
goto out;
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
if ((amr_force_sg32 == 0) && (id->flags & AMR_ID_DO_SG64) &&
|
||||
(sizeof(vm_paddr_t) > 4)) {
|
||||
device_printf(dev, "Using 64-bit DMA\n");
|
||||
sc->amr_type |= AMR_TYPE_SG64;
|
||||
}
|
||||
|
||||
/* force the busmaster enable bit on */
|
||||
if (!(command & PCIM_CMD_BUSMASTEREN)) {
|
||||
device_printf(dev, "busmaster bit not set, enabling\n");
|
||||
@ -235,7 +260,9 @@ amr_pci_attach(device_t dev)
|
||||
device_printf(sc->amr_dev, "can't allocate interrupt\n");
|
||||
goto out;
|
||||
}
|
||||
if (bus_setup_intr(sc->amr_dev, sc->amr_irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, amr_pci_intr, sc, &sc->amr_intr)) {
|
||||
if (bus_setup_intr(sc->amr_dev, sc->amr_irq,
|
||||
INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, amr_pci_intr,
|
||||
sc, &sc->amr_intr)) {
|
||||
device_printf(sc->amr_dev, "can't set up interrupt\n");
|
||||
goto out;
|
||||
}
|
||||
@ -249,7 +276,9 @@ amr_pci_attach(device_t dev)
|
||||
* Allocate the parent bus DMA tag appropriate for PCI.
|
||||
*/
|
||||
if (bus_dma_tag_create(NULL, /* parent */
|
||||
1, 0, /* alignment, boundary */
|
||||
1, 0, /* alignment,boundary */
|
||||
AMR_IS_SG64(sc) ?
|
||||
BUS_SPACE_MAXADDR :
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
@ -266,24 +295,42 @@ amr_pci_attach(device_t dev)
|
||||
* Create DMA tag for mapping buffers into controller-addressable space.
|
||||
*/
|
||||
if (bus_dma_tag_create(sc->amr_parent_dmat, /* parent */
|
||||
1, 0, /* alignment, boundary */
|
||||
1, 0, /* alignment,boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
MAXBSIZE, AMR_NSEG, /* maxsize, nsegments */
|
||||
MAXBSIZE, /* maxsegsize */
|
||||
BUS_DMA_ALLOCNOW, /* flags */
|
||||
busdma_lock_mutex, &sc->amr_io_lock, /* lockfunc, lockarg */
|
||||
busdma_lock_mutex, /* lockfunc */
|
||||
&sc->amr_list_lock, /* lockarg */
|
||||
&sc->amr_buffer_dmat)) {
|
||||
device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bus_dma_tag_create(sc->amr_parent_dmat, /* parent */
|
||||
1, 0, /* alignment,boundary */
|
||||
BUS_SPACE_MAXADDR, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
MAXBSIZE, AMR_NSEG, /* maxsize, nsegments */
|
||||
MAXBSIZE, /* maxsegsize */
|
||||
BUS_DMA_ALLOCNOW, /* flags */
|
||||
busdma_lock_mutex, /* lockfunc */
|
||||
&sc->amr_list_lock, /* lockarg */
|
||||
&sc->amr_buffer64_dmat)) {
|
||||
device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
debug(2, "dma tag done");
|
||||
|
||||
/*
|
||||
* Allocate and set up mailbox in a bus-visible fashion.
|
||||
*/
|
||||
mtx_init(&sc->amr_list_lock, "AMR List Lock", NULL, MTX_DEF);
|
||||
mtx_init(&sc->amr_hw_lock, "AMR HW Lock", NULL, MTX_DEF);
|
||||
if ((error = amr_setup_mbox(sc)) != 0)
|
||||
goto out;
|
||||
|
||||
@ -344,7 +391,7 @@ static int
|
||||
amr_pci_shutdown(device_t dev)
|
||||
{
|
||||
struct amr_softc *sc = device_get_softc(dev);
|
||||
int i,error,s;
|
||||
int i,error;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
@ -356,7 +403,6 @@ amr_pci_shutdown(device_t dev)
|
||||
device_printf(sc->amr_dev, "flushing cache...");
|
||||
printf("%s\n", amr_flush(sc) ? "failed" : "done");
|
||||
|
||||
s = splbio();
|
||||
error = 0;
|
||||
|
||||
/* delete all our child devices */
|
||||
@ -371,7 +417,6 @@ amr_pci_shutdown(device_t dev)
|
||||
/* XXX disable interrupts? */
|
||||
|
||||
shutdown_out:
|
||||
splx(s);
|
||||
return(error);
|
||||
}
|
||||
|
||||
@ -425,9 +470,7 @@ amr_pci_intr(void *arg)
|
||||
debug_called(2);
|
||||
|
||||
/* collect finished commands, queue anything waiting */
|
||||
mtx_lock(&sc->amr_io_lock);
|
||||
amr_done(sc);
|
||||
mtx_unlock(&sc->amr_io_lock);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
@ -438,8 +481,8 @@ amr_pci_intr(void *arg)
|
||||
static void
|
||||
amr_pci_free(struct amr_softc *sc)
|
||||
{
|
||||
u_int8_t *p;
|
||||
|
||||
u_int8_t *p
|
||||
|
||||
debug_called(1);
|
||||
|
||||
amr_free(sc);
|
||||
@ -447,6 +490,8 @@ amr_pci_free(struct amr_softc *sc)
|
||||
/* destroy data-transfer DMA tag */
|
||||
if (sc->amr_buffer_dmat)
|
||||
bus_dma_tag_destroy(sc->amr_buffer_dmat);
|
||||
if (sc->amr_buffer64_dmat)
|
||||
bus_dma_tag_destroy(sc->amr_buffer64_dmat);
|
||||
|
||||
/* free and destroy DMA memory and tag for s/g lists */
|
||||
if (sc->amr_sgtable)
|
||||
@ -455,9 +500,10 @@ amr_pci_free(struct amr_softc *sc)
|
||||
bus_dma_tag_destroy(sc->amr_sg_dmat);
|
||||
|
||||
/* free and destroy DMA memory and tag for mailbox */
|
||||
/* XXX Brain damaged GCC Alert! */
|
||||
p = (u_int8_t *)(uintptr_t)(volatile void *)sc->amr_mailbox64;
|
||||
if (sc->amr_mailbox) {
|
||||
p = (u_int8_t *)(uintptr_t)(volatile void *)sc->amr_mailbox;
|
||||
bus_dmamem_free(sc->amr_mailbox_dmat, p - 16, sc->amr_mailbox_dmamap);
|
||||
bus_dmamem_free(sc->amr_mailbox_dmat, p, sc->amr_mailbox_dmamap);
|
||||
}
|
||||
if (sc->amr_mailbox_dmat)
|
||||
bus_dma_tag_destroy(sc->amr_mailbox_dmat);
|
||||
@ -497,6 +543,7 @@ static int
|
||||
amr_sglist_map(struct amr_softc *sc)
|
||||
{
|
||||
size_t segsize;
|
||||
u_int8_t *p;
|
||||
int error;
|
||||
|
||||
debug_called(1);
|
||||
@ -505,19 +552,23 @@ amr_sglist_map(struct amr_softc *sc)
|
||||
* Create a single tag describing a region large enough to hold all of
|
||||
* the s/g lists we will need.
|
||||
*
|
||||
* Note that we could probably use AMR_LIMITCMD here, but that may become tunable.
|
||||
* Note that we could probably use AMR_LIMITCMD here, but that may become
|
||||
* tunable.
|
||||
*/
|
||||
segsize = sizeof(struct amr_sgentry) * AMR_NSEG * AMR_MAXCMD;
|
||||
if (AMR_IS_SG64(sc))
|
||||
segsize = sizeof(struct amr_sg64entry) * AMR_NSEG * AMR_MAXCMD;
|
||||
else
|
||||
segsize = sizeof(struct amr_sgentry) * AMR_NSEG * AMR_MAXCMD;
|
||||
|
||||
error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */
|
||||
1, 0, /* alignment, boundary */
|
||||
1, 0, /* alignment,boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
segsize, 1, /* maxsize, nsegments */
|
||||
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
|
||||
0, /* flags */
|
||||
busdma_lock_mutex, /* lockfunc */
|
||||
&Giant, /* lockarg */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&sc->amr_sg_dmat);
|
||||
if (error != 0) {
|
||||
device_printf(sc->amr_dev, "can't allocate scatter/gather DMA tag\n");
|
||||
@ -529,25 +580,32 @@ amr_sglist_map(struct amr_softc *sc)
|
||||
* controller-visible space.
|
||||
*
|
||||
* XXX this assumes we can get enough space for all the s/g maps in one
|
||||
* contiguous slab. We may need to switch to a more complex arrangement where
|
||||
* we allocate in smaller chunks and keep a lookup table from slot to bus address.
|
||||
* contiguous slab. We may need to switch to a more complex arrangement
|
||||
* where we allocate in smaller chunks and keep a lookup table from slot
|
||||
* to bus address.
|
||||
*
|
||||
* XXX HACK ALERT: at least some controllers don't like the s/g memory being
|
||||
* allocated below 0x2000. We leak some memory if we get some
|
||||
* below this mark and allocate again. We should be able to
|
||||
* avoid this with the tag setup, but that does't seem to work.
|
||||
* XXX HACK ALERT: at least some controllers don't like the s/g memory
|
||||
* being allocated below 0x2000. We leak some memory if
|
||||
* we get some below this mark and allocate again. We
|
||||
* should be able to avoid this with the tag setup, but
|
||||
* that does't seem to work.
|
||||
*/
|
||||
retry:
|
||||
error = bus_dmamem_alloc(sc->amr_sg_dmat, (void **)&sc->amr_sgtable, BUS_DMA_NOWAIT, &sc->amr_sg_dmamap);
|
||||
error = bus_dmamem_alloc(sc->amr_sg_dmat, (void **)&p, BUS_DMA_NOWAIT, &sc->amr_sg_dmamap);
|
||||
if (error) {
|
||||
device_printf(sc->amr_dev, "can't allocate s/g table\n");
|
||||
return(ENOMEM);
|
||||
}
|
||||
bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, sc->amr_sgtable, segsize, amr_sglist_map_helper, sc, 0);
|
||||
bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, p, segsize, amr_sglist_map_helper, sc, 0);
|
||||
if (sc->amr_sgbusaddr < 0x2000) {
|
||||
debug(1, "s/g table too low (0x%x), reallocating\n", sc->amr_sgbusaddr);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (AMR_IS_SG64(sc))
|
||||
sc->amr_sg64table = (struct amr_sg64entry *)p;
|
||||
sc->amr_sgtable = (struct amr_sgentry *)p;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -565,7 +623,7 @@ amr_setup_mbox_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
||||
debug_called(1);
|
||||
|
||||
/* save phsyical base of the basic mailbox structure */
|
||||
sc->amr_mailboxphys = segs->ds_addr + 16;
|
||||
sc->amr_mailboxphys = segs->ds_addr + offsetof(struct amr_mailbox64, mb);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -581,15 +639,15 @@ amr_setup_mbox(struct amr_softc *sc)
|
||||
* mailbox.
|
||||
*/
|
||||
error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */
|
||||
16, 0, /* alignment, boundary */
|
||||
16, 0, /* alignment,boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
sizeof(struct amr_mailbox) + 16, 1, /* maxsize, nsegments */
|
||||
sizeof(struct amr_mailbox64), /* maxsize */
|
||||
1, /* nsegments */
|
||||
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
|
||||
0, /* flags */
|
||||
busdma_lock_mutex, /* lockfunc */
|
||||
&Giant, /* lockarg */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&sc->amr_mailbox_dmat);
|
||||
if (error != 0) {
|
||||
device_printf(sc->amr_dev, "can't allocate mailbox tag\n");
|
||||
@ -612,8 +670,8 @@ amr_setup_mbox(struct amr_softc *sc)
|
||||
* Conventional mailbox is inside the mailbox64 region.
|
||||
*/
|
||||
bzero(p, sizeof(struct amr_mailbox64));
|
||||
sc->amr_mailbox64 = (struct amr_mailbox64 *)(p + 12);
|
||||
sc->amr_mailbox = (struct amr_mailbox *)(p + 16);
|
||||
sc->amr_mailbox64 = (struct amr_mailbox64 *)p;
|
||||
sc->amr_mailbox = &sc->amr_mailbox64->mb;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -65,7 +65,7 @@
|
||||
/*
|
||||
* Fetch the driver's interface version.
|
||||
*/
|
||||
#define AMR_IO_VERSION_NUMBER 0x01
|
||||
#define AMR_IO_VERSION_NUMBER 153
|
||||
#define AMR_IO_VERSION _IOR('A', 0x200, int)
|
||||
|
||||
/*
|
||||
|
@ -119,12 +119,26 @@
|
||||
#define AMR_CMD_GET_MACHINEID 0x36
|
||||
#define AMR_CMD_GET_INITIATOR 0x7d /* returns one byte */
|
||||
#define AMR_CMD_CONFIG 0xa1
|
||||
#define AMR_CMD_LREAD64 0xa7
|
||||
#define AMR_CMD_LWRITE64 0xa8
|
||||
#define AMR_CMD_PASS_64 0xc3
|
||||
#define AMR_CMD_EXTPASS 0xe3
|
||||
|
||||
#define AMR_CONFIG_READ_NVRAM_CONFIG 0x04
|
||||
#define AMR_CONFIG_WRITE_NVRAM_CONFIG 0x0d
|
||||
#define AMR_CONFIG_PRODUCT_INFO 0x0e
|
||||
#define AMR_CONFIG_ENQ3 0x0f
|
||||
#define AMR_CONFIG_ENQ3_SOLICITED_NOTIFY 0x01
|
||||
#define AMR_CONFIG_ENQ3_SOLICITED_FULL 0x02
|
||||
#define AMR_CONFIG_ENQ3_UNSOLICITED 0x03
|
||||
#define AMR_CMD_EXTPASS 0xe3
|
||||
|
||||
/*
|
||||
* Command for random deletion of logical drives
|
||||
*/
|
||||
#define FC_DEL_LOGDRV 0xA4
|
||||
#define OP_SUP_DEL_LOGDRV 0x2A
|
||||
#define OP_GET_LDID_MAP 0x18
|
||||
#define OP_DEL_LOGDRV 0x1C
|
||||
|
||||
/*
|
||||
* Command results
|
||||
@ -377,8 +391,9 @@ struct amr_enquiry3
|
||||
u_int16_t ae_opstatus[AMR_40LD_MAXDRIVES / 8]; /* operation status per drive */
|
||||
u_int32_t ae_drivesize[AMR_40LD_MAXDRIVES]; /* logical drive size */
|
||||
u_int8_t ae_driveprop[AMR_40LD_MAXDRIVES]; /* logical drive properties */
|
||||
u_int8_t ae_drivestate[AMR_40LD_MAXDRIVES]; /* physical drive state */
|
||||
u_int16_t ae_driveformat[AMR_40LD_MAXPHYSDRIVES];
|
||||
u_int8_t ae_drivestate[AMR_40LD_MAXDRIVES]; /* logical drive state */
|
||||
u_int8_t ae_pdrivestate[AMR_40LD_MAXPHYSDRIVES]; /* physical drive state */
|
||||
u_int16_t ae_pdriveformat[AMR_40LD_MAXPHYSDRIVES / 16];
|
||||
u_int8_t ae_targxfer[80]; /* physical drive transfer rates */
|
||||
|
||||
u_int8_t res1[263]; /* pad to 1024 bytes */
|
||||
@ -397,13 +412,14 @@ struct amr_mailbox
|
||||
{
|
||||
u_int8_t mb_command;
|
||||
u_int8_t mb_ident;
|
||||
u_int16_t mb_blkcount;
|
||||
u_int16_t mb_blkcount; /* u_int8_t opcode */
|
||||
/* u_int8_t subopcode */
|
||||
u_int32_t mb_lba;
|
||||
u_int32_t mb_physaddr;
|
||||
u_int8_t mb_drive;
|
||||
u_int8_t mb_nsgelem;
|
||||
u_int8_t res1;
|
||||
u_int8_t mb_busy;
|
||||
u_int8_t mb_nsgelem; /* u_int8_t rserv[0] */
|
||||
u_int8_t res1; /* u_int8_t rserv[1] */
|
||||
u_int8_t mb_busy; /* u_int8_t rserv[2] */
|
||||
u_int8_t mb_nstatus;
|
||||
u_int8_t mb_status;
|
||||
u_int8_t mb_completed[46];
|
||||
@ -414,7 +430,9 @@ struct amr_mailbox
|
||||
|
||||
struct amr_mailbox64
|
||||
{
|
||||
u_int32_t mb64_segment; /* for 64-bit controllers */
|
||||
u_int8_t pad[8]; /* Needed for alignment */
|
||||
u_int32_t sg64_lo; /* S/G pointer for 64-bit commands */
|
||||
u_int32_t sg64_hi; /* S/G pointer for 64-bit commands */
|
||||
struct amr_mailbox mb;
|
||||
} __packed;
|
||||
|
||||
@ -443,6 +461,12 @@ struct amr_sgentry
|
||||
u_int32_t sg_count;
|
||||
} __packed;
|
||||
|
||||
struct amr_sg64entry
|
||||
{
|
||||
u_int64_t sg_addr;
|
||||
u_int32_t sg_count;
|
||||
} __packed;
|
||||
|
||||
struct amr_passthrough
|
||||
{
|
||||
u_int8_t ap_timeout:3;
|
||||
@ -489,6 +513,26 @@ struct amr_ext_passthrough
|
||||
u_int32_t ap_data_transfer_length;
|
||||
} __packed;
|
||||
|
||||
struct amr_linux_ioctl {
|
||||
u_int32_t inlen;
|
||||
u_int32_t outlen;
|
||||
union {
|
||||
u_int8_t fca[16];
|
||||
struct {
|
||||
u_int8_t opcode;
|
||||
u_int8_t subopcode;
|
||||
u_int16_t adapno;
|
||||
u_int32_t buffer;
|
||||
u_int8_t pad[4];
|
||||
u_int32_t length;
|
||||
} __packed fcs;
|
||||
} __packed ui;
|
||||
u_int8_t mbox[18];
|
||||
struct amr_passthrough pthru;
|
||||
u_int32_t data;
|
||||
u_int8_t pad[4];
|
||||
} __packed;
|
||||
|
||||
#ifdef _KERNEL
|
||||
/********************************************************************************
|
||||
********************************************************************************
|
||||
|
@ -56,13 +56,11 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#if __FreeBSD_version >= 500005
|
||||
# include <geom/geom_disk.h>
|
||||
# include <sys/lock.h>
|
||||
# include <sys/mutex.h>
|
||||
#endif
|
||||
#include <geom/geom_disk.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
|
||||
#define LSI_DESC_PCI "LSILogic MegaRAID 1.51"
|
||||
#define LSI_DESC_PCI "LSILogic MegaRAID 1.53"
|
||||
|
||||
#ifdef AMR_DEBUG
|
||||
# define debug(level, fmt, args...) do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);} while(0)
|
||||
@ -112,6 +110,13 @@ struct amr_command
|
||||
struct amr_softc *ac_sc;
|
||||
u_int8_t ac_slot;
|
||||
int ac_status; /* command completion status */
|
||||
union {
|
||||
struct amr_sgentry *sg32;
|
||||
struct amr_sg64entry *sg64;
|
||||
} ac_sg;
|
||||
u_int32_t ac_sgbusaddr;
|
||||
u_int32_t ac_sg64_lo;
|
||||
u_int32_t ac_sg64_hi;
|
||||
struct amr_mailbox ac_mailbox;
|
||||
int ac_flags;
|
||||
#define AMR_CMD_DATAIN (1<<0)
|
||||
@ -122,21 +127,23 @@ struct amr_command
|
||||
#define AMR_CMD_MAPPED (1<<5)
|
||||
#define AMR_CMD_SLEEP (1<<6)
|
||||
#define AMR_CMD_BUSY (1<<7)
|
||||
#define AMR_CMD_SG64 (1<<8)
|
||||
#define AC_IS_SG64(ac) ((ac)->ac_flags & AMR_CMD_SG64)
|
||||
|
||||
struct bio *ac_bio;
|
||||
void (* ac_complete)(struct amr_command *ac);
|
||||
void *ac_private;
|
||||
|
||||
void *ac_data;
|
||||
size_t ac_length;
|
||||
bus_dmamap_t ac_dmamap;
|
||||
u_int32_t ac_dataphys;
|
||||
bus_dmamap_t ac_dma64map;
|
||||
|
||||
void *ac_ccb_data;
|
||||
size_t ac_ccb_length;
|
||||
bus_dmamap_t ac_ccb_dmamap;
|
||||
u_int32_t ac_ccb_dataphys;
|
||||
bus_dmamap_t ac_ccb_dma64map;
|
||||
|
||||
void (* ac_complete)(struct amr_command *ac);
|
||||
void *ac_private;
|
||||
};
|
||||
|
||||
struct amr_command_cluster
|
||||
@ -160,6 +167,7 @@ struct amr_softc
|
||||
bus_space_tag_t amr_btag;
|
||||
bus_dma_tag_t amr_parent_dmat; /* parent DMA tag */
|
||||
bus_dma_tag_t amr_buffer_dmat; /* data buffer DMA tag */
|
||||
bus_dma_tag_t amr_buffer64_dmat;
|
||||
struct resource *amr_irq; /* interrupt */
|
||||
void *amr_intr;
|
||||
|
||||
@ -172,6 +180,7 @@ struct amr_softc
|
||||
|
||||
/* scatter/gather lists and their controller-visible mappings */
|
||||
struct amr_sgentry *amr_sgtable; /* s/g lists */
|
||||
struct amr_sg64entry *amr_sg64table; /* 64bit s/g lists */
|
||||
u_int32_t amr_sgbusaddr; /* s/g table base address in bus space */
|
||||
bus_dma_tag_t amr_sg_dmat; /* s/g buffer DMA tag */
|
||||
bus_dmamap_t amr_sg_dmamap; /* map for s/g buffers */
|
||||
@ -193,6 +202,8 @@ struct amr_softc
|
||||
#define AMR_STATE_SHUTDOWN (1<<3)
|
||||
#define AMR_STATE_CRASHDUMP (1<<4)
|
||||
#define AMR_STATE_QUEUE_FRZN (1<<5)
|
||||
#define AMR_STATE_LD_DELETE (1<<6)
|
||||
#define AMR_STATE_REMAP_LD (1<<7)
|
||||
|
||||
/* per-controller queues */
|
||||
struct bio_queue_head amr_bioq; /* pending I/O with no commands */
|
||||
@ -209,7 +220,8 @@ struct amr_softc
|
||||
struct cam_devq *amr_cam_devq;
|
||||
|
||||
/* control device */
|
||||
struct cdev *amr_dev_t;
|
||||
struct cdev *amr_dev_t;
|
||||
struct mtx amr_list_lock;
|
||||
|
||||
/* controller type-specific support */
|
||||
int amr_type;
|
||||
@ -217,6 +229,8 @@ struct amr_softc
|
||||
#define AMR_IS_QUARTZ(sc) ((sc)->amr_type & AMR_TYPE_QUARTZ)
|
||||
#define AMR_TYPE_40LD (1<<1)
|
||||
#define AMR_IS_40LD(sc) ((sc)->amr_type & AMR_TYPE_40LD)
|
||||
#define AMR_TYPE_SG64 (1<<2)
|
||||
#define AMR_IS_SG64(sc) ((sc)->amr_type & AMR_TYPE_SG64)
|
||||
int (* amr_submit_command)(struct amr_softc *sc);
|
||||
int (* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
|
||||
int (*amr_poll_command)(struct amr_command *ac);
|
||||
@ -226,7 +240,10 @@ struct amr_softc
|
||||
/* misc glue */
|
||||
struct intr_config_hook amr_ich; /* wait-for-interrupts probe hook */
|
||||
struct callout_handle amr_timeout; /* periodic status check */
|
||||
struct mtx amr_io_lock;
|
||||
int amr_allow_vol_config;
|
||||
int amr_linux_no_adapters;
|
||||
int amr_ld_del_supported;
|
||||
struct mtx amr_hw_lock;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -237,6 +254,8 @@ extern void amr_free(struct amr_softc *sc);
|
||||
extern int amr_flush(struct amr_softc *sc);
|
||||
extern int amr_done(struct amr_softc *sc);
|
||||
extern void amr_startio(struct amr_softc *sc);
|
||||
extern int amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr,
|
||||
int32_t flag, d_thread_t *td);
|
||||
|
||||
/*
|
||||
* Command buffer allocation.
|
||||
@ -276,101 +295,74 @@ extern void amrd_intr(void *data);
|
||||
static __inline void
|
||||
amr_enqueue_bio(struct amr_softc *sc, struct bio *bio)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
bioq_insert_tail(&sc->amr_bioq, bio);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static __inline struct bio *
|
||||
amr_dequeue_bio(struct amr_softc *sc)
|
||||
{
|
||||
struct bio *bio;
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
if ((bio = bioq_first(&sc->amr_bioq)) != NULL)
|
||||
bioq_remove(&sc->amr_bioq, bio);
|
||||
splx(s);
|
||||
return(bio);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
amr_enqueue_ready(struct amr_command *ac)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
TAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
amr_requeue_ready(struct amr_command *ac)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
TAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static __inline struct amr_command *
|
||||
amr_dequeue_ready(struct amr_softc *sc)
|
||||
{
|
||||
struct amr_command *ac;
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
if ((ac = TAILQ_FIRST(&sc->amr_ready)) != NULL)
|
||||
TAILQ_REMOVE(&sc->amr_ready, ac, ac_link);
|
||||
splx(s);
|
||||
return(ac);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
amr_enqueue_completed(struct amr_command *ac)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
TAILQ_INSERT_TAIL(&ac->ac_sc->amr_completed, ac, ac_link);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static __inline struct amr_command *
|
||||
amr_dequeue_completed(struct amr_softc *sc)
|
||||
{
|
||||
struct amr_command *ac;
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
if ((ac = TAILQ_FIRST(&sc->amr_completed)) != NULL)
|
||||
TAILQ_REMOVE(&sc->amr_completed, ac, ac_link);
|
||||
splx(s);
|
||||
return(ac);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
amr_enqueue_free(struct amr_command *ac)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
TAILQ_INSERT_TAIL(&ac->ac_sc->amr_freecmds, ac, ac_link);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static __inline struct amr_command *
|
||||
amr_dequeue_free(struct amr_softc *sc)
|
||||
{
|
||||
struct amr_command *ac;
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
if ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL)
|
||||
TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link);
|
||||
splx(s);
|
||||
return(ac);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user