Synchronize with Feral CVS repository:

Go for the gusto and merge multichan_development into the head branch. This
will break FreeBSD and NetBSD ports for a while (yawn) and solaris is dubious
anyway.


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@260 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Stanislaw Gruszka
2008-02-12 09:18:28 +00:00
parent 75428f7e2d
commit 698091ebcb
20 changed files with 16524 additions and 13741 deletions
+156 -171
View File
@@ -1,4 +1,4 @@
/* $Id: isp_linux.h,v 1.143 2007/11/15 18:41:47 mjacob Exp $ */
/* $Id: isp_linux.h,v 1.144 2007/12/02 22:02:06 mjacob Exp $ */
/*
* Copyright (c) 1997-2007 by Matthew Jacob
* All rights reserved.
@@ -71,8 +71,8 @@
#define KERNEL_VERSION(v,p,s) (((v)<<16)+(p<<8)+s)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
#error "Only Linux 2.6 kernels are supported with this driver"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(2,7,0)
#error "Only Linux 2.5/2.6 kernels are supported with this driver"
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
@@ -166,13 +166,13 @@ typedef struct scsi_host_template Scsi_Host_Template;
#define ISP_SBUS_SUPPORTED 0
#endif
#define ISP_PLATFORM_VERSION_MAJOR 6
#define ISP_PLATFORM_VERSION_MINOR 0
#ifndef ISP_NAME
#define ISP_NAME "isp"
#endif
#define ISP_PLATFORM_VERSION_MAJOR 5
#define ISP_PLATFORM_VERSION_MINOR 0
#ifndef BIG_ENDIAN
#define BIG_ENDIAN 4321
#endif
@@ -220,6 +220,15 @@ typedef struct scsi_host_template Scsi_Host_Template;
#define u_char unsigned char
typedef u_long vm_offset_t;
/* bit map using 8 bit arrays */
typedef uint8_t isp_bmap_t;
#define _ISP_WIX(isp, ix) (ix >> 3)
#define _ISP_BIX(isp, ix) (1 << (ix & 0x7))
#define ISP_NBPIDX(x) ((x + 7) / 8) /* index width from bits */
#define ISP_BTST(map, ix) (((map)[_ISP_WIX(isp, ix)] & _ISP_BIX(isp, ix)) != 0)
#define ISP_BSET(map, ix) (map)[_ISP_WIX(isp, ix)] |= _ISP_BIX(isp, ix)
#define ISP_BCLR(map, ix) (map)[_ISP_WIX(isp, ix)] &= ~_ISP_BIX(isp, ix)
#ifdef ISP_TARGET_MODE
#include "isp_tpublic.h"
@@ -231,13 +240,6 @@ typedef u_long vm_offset_t;
#define N_NOTIFIES 256
#define DEFAULT_INQSIZE 32
#define WIX(ix) (ix >> 5)
#define BIX(ix) (1 << (ix & 0x1f))
#define LUN_BTST(bmap, ix) ((bmap[WIX(ix)] & BIX(ix)) != 0)
#define LUN_BSET(bmap, ix) bmap[WIX(ix)] |= BIX(ix)
#define LUN_BCLR(bmap, ix) bmap[WIX(ix)] &= ~BIX(ix)
typedef struct isp_notify isp_notify_t;
#define cd_action cd_lreserved[0].shorts[0]
@@ -269,6 +271,7 @@ typedef struct {
} tgt_auxcmd_t;
#define N_TGT_AUX 32
#define ISP_CT_TIMEOUT 120
#endif /* ISP_TARGET_MODE */
typedef struct {
@@ -280,22 +283,27 @@ typedef struct {
ISP_THREAD_LOGOUT,
ISP_THREAD_FINDIID,
ISP_THREAD_TERMINATE,
ISP_THREAD_RESTART_AT7,
ISP_THREAD_FC_PUTBACK,
ISP_THREAD_EXIT=99
} thread_action;
void * arg;
struct semaphore * thread_waiter;
int count;
} isp_thread_action_t;
#define MAX_THREAD_ACTION 32
#define MAX_THREAD_ACTION 128
#define MAX_FC_CHAN 128
#define ISP_HOST2ISP(host) (ispsoftc_t *) host->hostdata
union pstore;
struct isposinfo {
struct Scsi_Host * host;
u32 mcorig; /* original maxcmds */
void *device; /* hardware device structure */
Scsi_Cmnd *wqnext, *wqtail;
Scsi_Cmnd *dqnext, *dqtail;
union pstore *storep;
void * storep;
size_t storep_amt;
size_t param_amt;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *pdp;
#endif
@@ -304,46 +312,41 @@ struct isposinfo {
u16 wqcnt;
u16 wqhiwater;
u16 hiwater;
int role;
struct timer_list timer;
struct timer_list _mbtimer;
struct semaphore _mbox_sem;
struct semaphore _mbox_c_sem;
struct semaphore _fcs_sem;
struct timer_list mbtimer;
struct semaphore mbox_sem;
struct semaphore mbox_c_sem;
struct semaphore fcs_sem;
spinlock_t slock;
unsigned volatile int
_downcnt : 8,
: 2,
_qfdelay : 6,
: 5,
_isopen : 1,
_deadloop : 1,
_draining : 1,
_blocked : 1,
_fcrswdog : 1,
_fcrspend : 1,
_dogactive : 1,
_mboxcmd_done : 1,
_mbox_waiting : 1,
_mbintsok : 1,
_intsok : 1;
void * misc[8]; /* private platform variant usage */
struct task_struct * task_thread;
struct semaphore * task_request;
struct semaphore * task_ctl_sem;
: 20,
dogcnt : 5,
isopen : 1,
task_active : 1,
dogactive : 1,
mboxcmd_done : 1,
mbox_waiting : 1,
mbintsok : 1,
intsok : 1;
u16 frame_size;
u16 exec_throttle;
struct semaphore trq;
struct semaphore tcs;
spinlock_t tlock;
unsigned int nt_actions;
unsigned int device_id;
isp_thread_action_t t_actions[MAX_THREAD_ACTION];
#ifdef ISP_TARGET_MODE
uint32_t rollinfo : 16,
u32 isget : 16,
rstatus : 8,
: 6,
isget : 1,
: 7,
hcb : 1;
struct semaphore tgt_inisem;
struct semaphore * rsemap;
tgt_enalun_t * luns; /* enabled { lun, port } tuples */
struct tmd_cmd * pending_t; /* pending list of commands going upstream */
struct tmd_cmd * waiting_t; /* pending list of commands waiting to be fleshed out */
struct tmd_cmd * tfreelist; /* freelist head */
struct tmd_cmd * bfreelist; /* freelist tail */
struct tmd_cmd * pool; /* pool itself */
@@ -357,75 +360,56 @@ struct isposinfo {
* to manage those commands.
*/
tgt_auxcmd_t auxinfo[N_TGT_AUX];
uint32_t auxbmap[N_TGT_AUX >> 5];
uint8_t inqdata[DEFAULT_INQSIZE];
isp_bmap_t auxbmap[ISP_NBPIDX(N_TGT_AUX)];
u8 inqdata[DEFAULT_INQSIZE];
uint64_t cmds_started;
uint64_t cmds_completed;
struct {
uint32_t portid;
uint32_t nphdl;
uint64_t iid;
#define TM_CS 256
} tgt_cache[TM_CS];
u64 cmds_started;
u64 cmds_completed;
#endif
};
#define mbtimer isp_osinfo._mbtimer
#define dogactive isp_osinfo._dogactive
#define mbox_sem isp_osinfo._mbox_sem
#define mbox_c_sem isp_osinfo._mbox_c_sem
#define fcs_sem isp_osinfo._fcs_sem
#define mbintsok isp_osinfo._mbintsok
#define intsok isp_osinfo._intsok
#define mbox_waiting isp_osinfo._mbox_waiting
#define mboxcmd_done isp_osinfo._mboxcmd_done
#define isp_pbuf isp_osinfo._pbuf
#define isp_fcrspend isp_osinfo._fcrspend
#define isp_fcrswdog isp_osinfo._fcrswdog
#define isp_qfdelay isp_osinfo._qfdelay
#define isp_blocked isp_osinfo._blocked
#define isp_draining isp_osinfo._draining
#define isp_downcnt isp_osinfo._downcnt
#define isp_isopen isp_osinfo._isopen
#define isp_deadloop isp_osinfo._deadloop
#define mbtimer isp_osinfo.mbtimer
#define dogactive isp_osinfo.dogactive
#define mbox_sem isp_osinfo.mbox_sem
#define mbox_c_sem isp_osinfo.mbox_c_sem
#define fcs_sem isp_osinfo.fcs_sem
#define mbintsok isp_osinfo.mbintsok
#define intsok isp_osinfo.intsok
#define mbox_waiting isp_osinfo.mbox_waiting
#define mboxcmd_done isp_osinfo.mboxcmd_done
#define isp_isopen isp_osinfo.isopen
#define SEND_THREAD_EVENT(isp, action, a, dowait, file, line) \
if (isp->isp_osinfo.task_request) { \
unsigned long flags; \
spin_lock_irqsave(&isp->isp_osinfo.tlock, flags); \
if (isp->isp_osinfo.nt_actions >= MAX_THREAD_ACTION) { \
spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); \
isp_prt(isp, ISP_LOGERR, "thread event overflow"); \
} else if (action == ISP_THREAD_FC_RESCAN && isp->isp_fcrspend) { \
spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); \
} else { \
DECLARE_MUTEX_LOCKED(sem); \
isp_thread_action_t *tap; \
tap = &isp->isp_osinfo.t_actions[isp->isp_osinfo.nt_actions++]; \
tap->thread_action = action; \
tap->arg = a; \
if (dowait) { \
tap->thread_waiter = &sem; \
} else { \
tap->thread_waiter = 0; \
} \
if (action == ISP_THREAD_FC_RESCAN) { \
isp->isp_fcrspend = 1; \
} \
up(isp->isp_osinfo.task_request); \
if (dowait) { \
isp_prt(isp, ISP_LOGDEBUG1, \
"action %d sent from %s:%d and now waiting on %p", action, file, line, &sem); \
spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); \
down(&sem); \
isp_prt(isp, ISP_LOGDEBUG1, \
"action %d done from %p", action, &sem); \
} else { \
isp_prt(isp, ISP_LOGDEBUG1, "action %d from %s:%d sent", action, file, line); \
spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); \
} \
} \
}
#define ISP_THREAD_EXEC(x) \
sema_init(&(x)->isp_osinfo.tcs, 0); \
kernel_thread(isp_task_thread, (x), 0); \
down(&isp->isp_osinfo.tcs)
#define ISP_THREAD_IACK(x) \
sema_init(&(x)->isp_osinfo.trq, 0); \
(x)->isp_osinfo.task_active = 1; \
up(&(x)->isp_osinfo.tcs)
#define ISP_THREAD_WAIT(x) down_interruptible(&(x)->isp_osinfo.trq)
#define ISP_THREAD_EVENT isp_thread_event
#define ISP_THREAD_WAKE(x) up(&(x)->isp_osinfo.trq)
#define ISP_THREAD_KILL(x) \
{ \
unsigned long _fl; \
spin_lock_irqsave(&(x)->isp_osinfo.tlock, _fl); \
if ((x)->isp_osinfo.task_active) { \
sema_init(&(x)->isp_osinfo.tcs, 0); \
(x)->isp_osinfo.task_active = 0; \
up(&(x)->isp_osinfo.trq); \
spin_unlock_irqrestore(&(x)->isp_osinfo.tlock, _fl); \
down(&(x)->isp_osinfo.tcs); \
} else { \
spin_unlock_irqrestore(&(x)->isp_osinfo.tlock, _fl); \
} \
}
#define ISP_THREAD_XACK(x) up(&(x)->isp_osinfo.tcs)
/*
* Locking macros...
@@ -455,11 +439,11 @@ if (isp->isp_osinfo.task_request) { \
* Required Macros/Defines
*/
#if defined(CONFIG_HIGHMEM64G) || defined(CONFIG_X86_64)
#if defined(CONFIG_HIGHMEM64G) || defined(CONFIG_X86_64) /* BOGUS */
#define ISP_DAC_SUPPORTED 1
#endif
#define ISP2100_SCRLEN 0x1000
#define ISP_FC_SCRLEN 0x1000
#define MEMZERO(b, a) memset(b, 0, a)
#define MEMCPY memcpy
@@ -499,7 +483,7 @@ if (isp->isp_osinfo.task_request) { \
isp->mboxcmd_done = 1
#define MBOX_RELEASE(isp) up(&isp->mbox_sem)
#define FC_SCRATCH_ACQUIRE(isp) \
#define FC_SCRATCH_ACQUIRE(isp, chan) \
/* \
* Try and acquire semaphore the easy way first- \
* with our lock already held. \
@@ -516,7 +500,7 @@ if (isp->isp_osinfo.task_request) { \
ISP_IGET_LK_SOFTC(isp); \
}
#define FC_SCRATCH_RELEASE(isp) up(&isp->fcs_sem)
#define FC_SCRATCH_RELEASE(isp, chan) up(&isp->fcs_sem)
#ifndef SCSI_GOOD
@@ -591,14 +575,16 @@ if (isp->isp_osinfo.task_request) { \
#define XS_SET_STATE_STAT(a, b, c)
#define DEFAULT_IID isplinux_default_id
#define DEFAULT_LOOPID isplinux_default_id
#define DEFAULT_NODEWWN(isp) (isp)->isp_defwwnn
#define DEFAULT_PORTWWN(isp) (isp)->isp_defwwpn
#define DEFAULT_FRAME_SIZE(isp) (IS_SCSI(isp)? 0 : isp->isp_osinfo.storep->fibre_scsi.default_frame_size)
#define DEFAULT_EXEC_ALLOC(isp) (IS_SCSI(isp)? 0 : isp->isp_osinfo.storep->fibre_scsi.default_exec_alloc)
#define ISP_NODEWWN(isp) (isp)->isp_actvwwnn
#define ISP_PORTWWN(isp) (isp)->isp_actvwwpn
#define GET_DEFAULT_ROLE isplinux_get_default_role
#define SET_DEFAULT_ROLE isplinux_set_default_role
#define DEFAULT_IID isplinux_get_default_id
#define DEFAULT_LOOPID isplinux_get_default_id
#define DEFAULT_FRAMESIZE(isp) isp->isp_osinfo.frame_size
#define DEFAULT_EXEC_THROTTLE(isp) isp->isp_osinfo.exec_throttle
#define DEFAULT_NODEWWN(isp, chan) isplinux_default_wwn(isp, chan, 0, 1)
#define DEFAULT_PORTWWN(isp, chan) isplinux_default_wwn(isp, chan, 0, 0)
#define ACTIVE_NODEWWN(isp, chan) isplinux_default_wwn(isp, chan, 1, 1)
#define ACTIVE_PORTWWN(isp, chan) isplinux_default_wwn(isp, chan, 1, 0)
#define ISP_IOXPUT_8(isp, s, d) *(d) = s
#define ISP_IOXPUT_16(isp, s, d) *(d) = cpu_to_le16(s)
@@ -655,34 +641,28 @@ void isp_prt(ispsoftc_t *, int level, const char *, ...);
*/
/*
* Parameter storage. The order of tags is important- sdparam && fcp
* must come first because isp->isp_params is set to point there...
* Parameter and platform per-channel storage.
*/
union pstore {
struct {
sdparam _sdp[2]; /* they need to be sequential */
u_char psc_opts[2][MAX_TARGETS];
u_char dutydone;
} parallel_scsi;
struct {
fcparam fcp;
uint64_t def_wwnn;
uint64_t def_wwpn;
uint64_t actv_wwnn;
uint64_t actv_wwpn;
uint16_t default_frame_size;
uint16_t default_exec_throttle;
} fibre_scsi;
};
typedef struct {
uint64_t def_wwnn;
uint64_t def_wwpn;
uint32_t
tgts_tested : 16,
: 10,
fcrswdog : 1,
: 1,
blocked : 1,
deadloop : 1,
role : 2;
unsigned int downcount;
unsigned int qfdelay;
} isp_data;
#define ISP_DATA(isp, chan) (&((isp_data *)((isp)->isp_osinfo.storep))[chan])
#define isp_name isp_osinfo.hbaname
#define isp_host isp_osinfo.host
#define isp_unit isp_osinfo.host->unique_id
#define isp_psco isp_osinfo.storep->parallel_scsi.psc_opts
#define isp_dutydone isp_osinfo.storep->parallel_scsi.dutydone
#define isp_defwwnn isp_osinfo.storep->fibre_scsi.def_wwnn
#define isp_defwwpn isp_osinfo.storep->fibre_scsi.def_wwpn
#define isp_actvwwnn isp_osinfo.storep->fibre_scsi.actv_wwnn
#define isp_actvwwpn isp_osinfo.storep->fibre_scsi.actv_wwpn
/*
* Driver prototypes..
@@ -702,22 +682,25 @@ void isplinux_undo_proc(ispsoftc_t *);
int isplinux_reinit(ispsoftc_t *);
void isplinux_sqd(struct Scsi_Host *, struct scsi_device *);
int isp_drain_reset(ispsoftc_t *, char *);
int isp_drain(ispsoftc_t *, char *);
void isp_thread_event(ispsoftc_t *, int, void *, int, const char *, const int line);
static __inline uint64_t _isp_microtime_sub(struct timeval *, struct timeval *);
static __inline void _isp_usec_delay(unsigned int);
static __inline unsigned long _usec_to_jiffies(unsigned int);
static __inline unsigned long _jiffies_to_usec(unsigned long);
static __inline int isplinux_tagtype(Scsi_Cmnd *);
static __inline int mbox_acquire(ispsoftc_t *);
static __inline void mbox_wait_complete(ispsoftc_t *, mbreg_t *);
static inline uint64_t _isp_microtime_sub(struct timeval *, struct timeval *);
static inline void _isp_usec_delay(unsigned int);
static inline unsigned long _usec_to_jiffies(unsigned int);
static inline unsigned long _jiffies_to_usec(unsigned long);
static inline int isplinux_tagtype(Scsi_Cmnd *);
static inline int mbox_acquire(ispsoftc_t *);
static inline void mbox_wait_complete(ispsoftc_t *, mbreg_t *);
int isplinux_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
const char *isplinux_info(struct Scsi_Host *);
int isplinux_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
int isplinux_biosparam(struct scsi_device *, struct block_device *, sector_t, int[]);
int isplinux_default_id(ispsoftc_t *);
int isplinux_get_default_id(ispsoftc_t *, int);
int isplinux_get_default_role(ispsoftc_t *, int);
void isplinux_set_default_role(ispsoftc_t *, int, int);
uint64_t isplinux_default_wwn(ispsoftc_t *, int, int, int);
/*
* Driver wide data...
@@ -731,17 +714,19 @@ extern int isp_fcduplex;
extern int isp_maxsectors;
extern struct scsi_host_template *isp_template;
extern const char *class3_roles[4];
extern int isp_vports;
extern dev_t isp_dev;
extern struct cdev isp_cdev;
extern struct file_operations isp_ioctl_operations;
extern ISP_CLASS *isp_class;
/*
* This used to be considered bad form, but locking crasp made it more attractive.
* This used to be considered bad form, but locking crap made it more attractive.
*/
#define MAX_ISP 32
extern ispsoftc_t *isplist[MAX_ISP];
extern ispsoftc_t *api_isp;
extern int api_channel;
/*
* Platform private flags
@@ -781,7 +766,7 @@ extern ispsoftc_t *api_isp;
#define _SBSWAP(a, b, c)
#endif
static __inline uint64_t
static inline uint64_t
_isp_microtime_sub(struct timeval *b, struct timeval *a)
{
uint64_t elapsed;
@@ -804,7 +789,7 @@ _isp_microtime_sub(struct timeval *b, struct timeval *a)
return (elapsed * 1000);
}
static __inline void
static inline void
_isp_usec_delay(unsigned int usecs)
{
while (usecs > 1000) {
@@ -815,7 +800,7 @@ _isp_usec_delay(unsigned int usecs)
udelay(usecs);
}
static __inline unsigned long
static inline unsigned long
_usec_to_jiffies(unsigned int usecs)
{
struct timespec lt;
@@ -826,7 +811,7 @@ _usec_to_jiffies(unsigned int usecs)
return (timespec_to_jiffies(&lt));
}
static __inline unsigned long
static inline unsigned long
_jiffies_to_usec(unsigned long jiffies)
{
unsigned long usecs;
@@ -848,7 +833,7 @@ _jiffies_to_usec(unsigned long jiffies)
#define MSG_ORDERED_TAG 0x22
#endif
static __inline int
static inline int
isplinux_tagtype(Scsi_Cmnd *Cmnd)
{
switch (Cmnd->tag) {
@@ -863,7 +848,7 @@ isplinux_tagtype(Scsi_Cmnd *Cmnd)
}
}
static __inline int
static inline int
mbox_acquire(ispsoftc_t *isp)
{
/*
@@ -882,7 +867,7 @@ mbox_acquire(ispsoftc_t *isp)
return (0);
}
static __inline void
static inline void
mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
{
uint32_t lim = mbp->timeout;
@@ -947,11 +932,11 @@ mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
/*
* Note that these allocators aren't interrupt safe
*/
static __inline void * isp_kalloc(size_t, int);
static __inline void isp_kfree(void *, size_t);
static __inline void * isp_kzalloc(size_t, int);
static inline void * isp_kalloc(size_t, int);
static inline void isp_kfree(void *, size_t);
static inline void * isp_kzalloc(size_t, int);
static __inline void *
static inline void *
isp_kalloc(size_t size, int flags)
{
void *ptr;
@@ -963,7 +948,7 @@ isp_kalloc(size_t size, int flags)
return (ptr);
}
static __inline void
static inline void
isp_kfree(void *ptr, size_t size)
{
if (size >= PAGE_SIZE) {
@@ -973,12 +958,12 @@ isp_kfree(void *ptr, size_t size)
}
}
static __inline void *
static inline void *
isp_kzalloc(size_t size, int flags)
{
void *ptr = isp_kalloc(size, flags);
if (ptr != NULL){
memset(ptr, 0, size);
MEMZERO(ptr, size);
}
return (ptr);
}
@@ -1001,8 +986,8 @@ void isp_deinit_target(ispsoftc_t *);
void isp_detach_target(ispsoftc_t *);
int isp_target_async(ispsoftc_t *, int, int);
int isp_target_notify(ispsoftc_t *, void *, uint32_t *);
int isp_enable_lun(ispsoftc_t *, uint16_t, uint64_t, uint16_t);
int isp_disable_lun(ispsoftc_t *, uint16_t, uint64_t, uint16_t);
int isp_enable_lun(ispsoftc_t *, uint16_t, uint16_t);
int isp_disable_lun(ispsoftc_t *, uint16_t, uint16_t);
struct isp_notify {
tmd_notify_t notify;