diff options
author | Mike Smith <msmith@FreeBSD.org> | 2000-08-30 07:52:50 +0000 |
---|---|---|
committer | Mike Smith <msmith@FreeBSD.org> | 2000-08-30 07:52:50 +0000 |
commit | 9f1776230d63537648a5174e3dac7a18c7ffdbca (patch) | |
tree | 3130d6b7c48e164dc29c8ce2a7de16a42cff3581 /sys/dev/amr/amrvar.h | |
parent | 429a82acc661b83cceaaae92f4ba169dfe5aaa04 (diff) | |
download | src-9f1776230d63537648a5174e3dac7a18c7ffdbca.tar.gz src-9f1776230d63537648a5174e3dac7a18c7ffdbca.zip |
Major update to the AMI MegaRAID driver.
- New support for 40LD firmware found in Series 475 and 471 adapters.
- Better support for 8LD firmware adapters
- Ioctl passthrough interface for userland utilities.
- Improved error handling and queueing.
- Several bugfixes (including the 'still open' shutdown bug and
closing some small race conditions).
- Zone-style command allocator, reducing memory wasted under heavy
load conditions.
- CAM interface (disabled and not fully working) for SCSI passthrough
access to non-disk devices
Thanks to AMI for supplying a pile of new adapters and various other
help in making this happen.
Notes
Notes:
svn path=/head/; revision=65245
Diffstat (limited to 'sys/dev/amr/amrvar.h')
-rw-r--r-- | sys/dev/amr/amrvar.h | 292 |
1 files changed, 194 insertions, 98 deletions
diff --git a/sys/dev/amr/amrvar.h b/sys/dev/amr/amrvar.h index 5edfb1fb93f0..159a4e8231ad 100644 --- a/sys/dev/amr/amrvar.h +++ b/sys/dev/amr/amrvar.h @@ -1,5 +1,6 @@ /*- - * Copyright (c) 1999 Michael Smith + * Copyright (c) 1999,2000 Michael Smith + * Copyright (c) 2000 BSDi * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,24 +27,18 @@ * $FreeBSD$ */ -/* - * We could actually use all 17 segments, but using only 16 means that - * each scatter/gather map is 128 bytes in size, and thus we don't have to worry about - * maps crossing page boundaries. - */ -#define AMR_NSEG 16 - -#define AMR_CFG_BASE 0x10 -#define AMR_CFG_SIG 0xa0 -#define AMR_SIGNATURE 0x3344 - -#define AMR_MAXCMD 255 /* ident = 0 not allowed */ -#define AMR_LIMITCMD 120 /* maximum count of outstanding commands */ -#define AMR_MAXLD 40 - -#define AMR_BLKSIZE 512 +#if __FreeBSD_version >= 500005 +# include <sys/taskqueue.h> +#endif -struct amr_softc; +#ifdef AMR_DEBUG +# define debug(level, fmt, args...) do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __FUNCTION__ , ##args);} while(0) +# define debug_called(level) do {if (level <= AMR_DEBUG) printf("%s: called\n", __FUNCTION__);} while(0) +#else +# define debug(level, fmt, args...) +# define debug_called(level) +#endif +#define xdebug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args) /* * Per-logical-drive datastructure @@ -63,6 +58,16 @@ struct amr_logdrive device_t al_disk; }; +/* + * Due to the difficulty of using the zone allocator to create a new + * zone from within a module, we use our own clustering to reduce + * memory wastage due to allocating lots of these small structures. + * + * 16k gives us a little under 200 command structures, which should + * normally be plenty. We will grab more if we need them. + */ + +#define AMR_CMD_CLUSTERSIZE (16 * 1024) /* * Per-command control structure. @@ -73,28 +78,45 @@ struct amr_command struct amr_softc *ac_sc; u_int8_t ac_slot; - int ac_status; -#define AMR_STATUS_BUSY 0xffff -#define AMR_STATUS_WEDGED 0xdead -#define AMR_STATUS_LATE 0xdeed + int ac_status; /* command completion status */ struct amr_mailbox ac_mailbox; - u_int32_t ac_sgphys; - int ac_nsgent; int ac_flags; #define AMR_CMD_DATAIN (1<<0) #define AMR_CMD_DATAOUT (1<<1) -#define AMR_CMD_PRIORITY (1<<2) - time_t ac_stamp; +#define AMR_CMD_CCB_DATAIN (1<<2) +#define AMR_CMD_CCB_DATAOUT (1<<3) +#define AMR_CMD_PRIORITY (1<<4) +#define AMR_CMD_MAPPED (1<<5) +#define AMR_CMD_SLEEP (1<<6) +#define AMR_CMD_BUSY (1<<7) + + struct bio *ac_bio; void *ac_data; size_t ac_length; bus_dmamap_t ac_dmamap; u_int32_t ac_dataphys; + void *ac_ccb_data; + size_t ac_ccb_length; + bus_dmamap_t ac_ccb_dmamap; + u_int32_t ac_ccb_dataphys; + void (* ac_complete)(struct amr_command *ac); - void *ac_private; }; +struct amr_command_cluster +{ + TAILQ_ENTRY(amr_command_cluster) acc_link; + struct amr_command acc_command[0]; +}; + +#define AMR_CMD_CLUSTERCOUNT ((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) / \ + sizeof(struct amr_command)) + +/* + * Per-controller-instance data + */ struct amr_softc { /* bus attachments */ @@ -123,101 +145,74 @@ struct amr_softc /* controller limits and features */ int amr_maxio; /* maximum number of I/O transactions */ int amr_maxdrives; /* max number of logical drives */ + int amr_maxchan; /* count of SCSI channels */ /* connected logical drives */ struct amr_logdrive amr_drive[AMR_MAXLD]; - /* controller status */ + /* controller state */ int amr_state; #define AMR_STATE_OPEN (1<<0) #define AMR_STATE_SUSPEND (1<<1) #define AMR_STATE_INTEN (1<<2) #define AMR_STATE_SHUTDOWN (1<<3) - struct callout_handle amr_timeout; /* periodic status check */ /* per-controller queues */ - struct bio_queue_head amr_bioq; /* pending I/O */ - int amr_waitbufs; + struct bio_queue_head amr_bioq; /* pending I/O with no commands */ + TAILQ_HEAD(,amr_command) amr_ready; /* commands ready to be submitted */ struct amr_command *amr_busycmd[AMR_MAXCMD]; - int amr_busycmdcount; - TAILQ_HEAD(,amr_command) amr_work; - int amr_workcount; + int amr_busyslots; + TAILQ_HEAD(,amr_command) amr_completed; TAILQ_HEAD(,amr_command) amr_freecmds; + TAILQ_HEAD(,amr_command_cluster) amr_cmd_clusters; + + /* CAM attachments for passthrough */ + struct cam_sim *amr_cam_sim[AMR_MAX_CHANNELS]; + TAILQ_HEAD(, ccb_hdr) amr_cam_ccbq; - int amr_locks; /* reentrancy avoidance */ + /* control device */ + dev_t amr_dev_t; /* controller type-specific support */ int amr_type; -#define AMR_TYPE_STD 0 -#define AMR_TYPE_QUARTZ 1 - void (* amr_submit_command)(struct amr_softc *sc); +#define AMR_TYPE_QUARTZ (1<<0) +#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) + int (* amr_submit_command)(struct amr_softc *sc); int (* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave); - void (* amr_attach_mailbox)(struct amr_softc *sc); + + /* misc glue */ + struct intr_config_hook amr_ich; /* wait-for-interrupts probe hook */ + struct callout_handle amr_timeout; /* periodic status check */ +#if __FreeBSD_version >= 500005 + struct task amr_task_complete; /* deferred-completion task */ +#endif }; /* - * Simple (stupid) locks. - * - * Note that these are designed to avoid reentrancy, not concurrency, and will - * need to be replaced with something better. + * Interface between bus connections and driver core. */ -#define AMR_LOCK_COMPLETING (1<<0) -#define AMR_LOCK_STARTING (1<<1) - -static __inline int -amr_lock_tas(struct amr_softc *sc, int lock) -{ - if ((sc)->amr_locks & (lock)) - return(1); - atomic_set_int(&sc->amr_locks, lock); - return(0); -} +extern int amr_attach(struct amr_softc *sc); +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); -static __inline void -amr_lock_clr(struct amr_softc *sc, int lock) -{ - atomic_clear_int(&sc->amr_locks, lock); -} +extern devclass_t amr_devclass; /* - * I/O primitives + * Command buffer allocation. */ -/* Quartz */ -#define AMR_QPUT_IDB(sc, val) bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QIDB, val) -#define AMR_QGET_IDB(sc) bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QIDB) -#define AMR_QPUT_ODB(sc, val) bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QODB, val) -#define AMR_QGET_ODB(sc) bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QODB) - -/* Standard */ -#define AMR_SPUT_ISTAT(sc, val) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SINTR, val) -#define AMR_SGET_ISTAT(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SINTR) -#define AMR_SACK_INTERRUPT(sc) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_ACKINTR) -#define AMR_SPOST_COMMAND(sc) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_POST) -#define AMR_SGET_MBSTAT(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_BUSY) -#define AMR_SENABLE_INTR(sc) \ - bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, \ - bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) | AMR_STOGL_IENABLE) -#define AMR_SDISABLE_INTR(sc) \ - bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, \ - bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) & ~AMR_STOGL_IENABLE) -#define AMR_SBYTE_SET(sc, reg, val) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, reg, val) +extern struct amr_command *amr_alloccmd(struct amr_softc *sc); +extern void amr_releasecmd(struct amr_command *ac); /* - * Interface between bus connections and driver core. + * CAM interface */ -extern void amr_free(struct amr_softc *sc); -extern int amr_attach(struct amr_softc *sc); -extern void amr_startup(struct amr_softc *sc); -extern void amr_intr(void *data); -extern int amr_detach(device_t dev); -extern int amr_shutdown(device_t dev); -extern int amr_suspend(device_t dev); -extern int amr_resume(device_t dev); -extern d_open_t amr_open; -extern d_close_t amr_close; -extern d_ioctl_t amr_ioctl; - -extern devclass_t amr_devclass; +extern int amr_cam_attach(struct amr_softc *sc); +extern void amr_cam_detach(struct amr_softc *sc); +extern int amr_cam_command(struct amr_softc *sc, struct amr_command **acp); /* * MegaRAID logical disk driver @@ -233,15 +228,116 @@ struct amrd_softc struct disklabel amrd_label; int amrd_unit; int amrd_flags; -#define AMRD_OPEN (1<<0) /* drive is open (can't shut down) */ +#define AMRD_OPEN (1<<0) /* drive is open (can't detach) */ }; /* * Interface between driver core and disk driver (should be using a bus?) */ -extern int amr_submit_buf(struct amr_softc *sc, struct bio *bp); -extern int amr_submit_ioctl(struct amr_softc *sc, struct amr_logdrive *drive, u_long cmd, - caddr_t addr, int32_t flag, struct proc *p); +extern int amr_submit_bio(struct amr_softc *sc, struct bio *bio); extern void amrd_intr(void *data); -extern void amr_report(void); +/******************************************************************************** + * Enqueue/dequeue functions + */ +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); +} |