Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
8428b10d
Commit
8428b10d
authored
Oct 17, 2002
by
James Bottomley
Browse files
Options
Browse Files
Download
Plain Diff
Merge mulgrave.(none):/home/jejb/BK/scsi-host-list-2.5
into mulgrave.(none):/home/jejb/BK/scsi-for-linus-2.5
parents
40ea4c83
209287fb
Changes
22
Show whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
820 additions
and
781 deletions
+820
-781
drivers/acorn/scsi/acornscsi.c
drivers/acorn/scsi/acornscsi.c
+2
-4
drivers/acorn/scsi/arxescsi.c
drivers/acorn/scsi/arxescsi.c
+2
-6
drivers/acorn/scsi/cumana_2.c
drivers/acorn/scsi/cumana_2.c
+2
-6
drivers/acorn/scsi/eesox.c
drivers/acorn/scsi/eesox.c
+2
-6
drivers/acorn/scsi/powertec.c
drivers/acorn/scsi/powertec.c
+2
-6
drivers/block/cciss_scsi.c
drivers/block/cciss_scsi.c
+2
-19
drivers/scsi/53c700.c
drivers/scsi/53c700.c
+2
-4
drivers/scsi/aic7xxx/aic7xxx_linux_host.h
drivers/scsi/aic7xxx/aic7xxx_linux_host.h
+0
-1
drivers/scsi/cpqfcTSinit.c
drivers/scsi/cpqfcTSinit.c
+1
-3
drivers/scsi/fcal.c
drivers/scsi/fcal.c
+1
-3
drivers/scsi/hosts.c
drivers/scsi/hosts.c
+682
-202
drivers/scsi/hosts.h
drivers/scsi/hosts.h
+49
-48
drivers/scsi/ips.h
drivers/scsi/ips.h
+0
-3
drivers/scsi/pcmcia/aha152x_stub.c
drivers/scsi/pcmcia/aha152x_stub.c
+2
-1
drivers/scsi/pcmcia/fdomain_stub.c
drivers/scsi/pcmcia/fdomain_stub.c
+2
-1
drivers/scsi/pcmcia/nsp_cs.c
drivers/scsi/pcmcia/nsp_cs.c
+2
-1
drivers/scsi/pcmcia/qlogic_stub.c
drivers/scsi/pcmcia/qlogic_stub.c
+2
-1
drivers/scsi/scsi.c
drivers/scsi/scsi.c
+23
-433
drivers/scsi/scsi_proc.c
drivers/scsi/scsi_proc.c
+34
-25
drivers/scsi/scsi_syms.c
drivers/scsi/scsi_syms.c
+3
-2
drivers/scsi/sg.c
drivers/scsi/sg.c
+4
-2
drivers/scsi/wd33c93.c
drivers/scsi/wd33c93.c
+1
-4
No files found.
drivers/acorn/scsi/acornscsi.c
View file @
8428b10d
...
...
@@ -3010,14 +3010,12 @@ int acornscsi_proc_info(char *buffer, char **start, off_t offset,
int
length
,
int
host_no
,
int
inout
)
{
int
pos
,
begin
=
0
,
devidx
;
struct
Scsi_Host
*
instance
=
scsi_hostlist
;
struct
Scsi_Host
*
instance
;
Scsi_Device
*
scd
;
AS_Host
*
host
;
char
*
p
=
buffer
;
for
(
instance
=
scsi_hostlist
;
instance
&&
instance
->
host_no
!=
host_no
;
instance
=
instance
->
next
);
instance
=
scsi_host_hn_get
(
host_no
);
if
(
inout
==
1
||
!
instance
)
return
-
EINVAL
;
...
...
drivers/acorn/scsi/arxescsi.c
View file @
8428b10d
...
...
@@ -384,15 +384,11 @@ int arxescsi_proc_info(char *buffer, char **start, off_t offset,
int
length
,
int
host_no
,
int
inout
)
{
int
pos
,
begin
;
struct
Scsi_Host
*
host
=
scsi_hostlist
;
struct
Scsi_Host
*
host
;
ARXEScsi_Info
*
info
;
Scsi_Device
*
scd
;
while
(
host
)
{
if
(
host
->
host_no
==
host_no
)
break
;
host
=
host
->
next
;
}
host
=
scsi_host_hn_get
(
host_no
);
if
(
!
host
)
return
0
;
...
...
drivers/acorn/scsi/cumana_2.c
View file @
8428b10d
...
...
@@ -498,15 +498,11 @@ int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset,
int
length
,
int
host_no
,
int
inout
)
{
int
pos
,
begin
;
struct
Scsi_Host
*
host
=
scsi_hostlist
;
struct
Scsi_Host
*
host
;
CumanaScsi2_Info
*
info
;
Scsi_Device
*
scd
;
while
(
host
)
{
if
(
host
->
host_no
==
host_no
)
break
;
host
=
host
->
next
;
}
host
=
scsi_host_hn_get
(
host_no
);
if
(
!
host
)
return
0
;
...
...
drivers/acorn/scsi/eesox.c
View file @
8428b10d
...
...
@@ -499,15 +499,11 @@ int eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
int
length
,
int
host_no
,
int
inout
)
{
int
pos
,
begin
;
struct
Scsi_Host
*
host
=
scsi_hostlist
;
struct
Scsi_Host
*
host
;
EESOXScsi_Info
*
info
;
Scsi_Device
*
scd
;
while
(
host
)
{
if
(
host
->
host_no
==
host_no
)
break
;
host
=
host
->
next
;
}
host
=
scsi_host_hn_get
(
host_no
);
if
(
!
host
)
return
0
;
...
...
drivers/acorn/scsi/powertec.c
View file @
8428b10d
...
...
@@ -404,15 +404,11 @@ int powertecscsi_proc_info(char *buffer, char **start, off_t offset,
int
length
,
int
host_no
,
int
inout
)
{
int
pos
,
begin
;
struct
Scsi_Host
*
host
=
scsi_hostlist
;
struct
Scsi_Host
*
host
;
PowerTecScsi_Info
*
info
;
Scsi_Device
*
scd
;
while
(
host
)
{
if
(
host
->
host_no
==
host_no
)
break
;
host
=
host
->
next
;
}
host
=
scsi_host_hn_get
(
host_no
);
if
(
!
host
)
return
0
;
...
...
drivers/block/cciss_scsi.c
View file @
8428b10d
...
...
@@ -1250,8 +1250,6 @@ cciss_scsi_user_command(int ctlr, int hostno, char *buffer, int length)
return
length
;
}
/* It's a pity that we need this, but, we do... */
extern
struct
Scsi_Host
*
scsi_hostlist
;
/* from ../scsi/hosts.c */
int
cciss_scsi_proc_info
(
char
*
buffer
,
/* data buffer */
...
...
@@ -1268,24 +1266,9 @@ cciss_scsi_proc_info(char *buffer, /* data buffer */
ctlr_info_t
*
ci
;
int
cntl_num
;
/* Lets see if we can find our Scsi_Host...
this might be kind of "bad", searching scis_hostlist this way
but how else can we find the scsi host? I think I've seen
this coded both ways, (circular list and null terminated list)
I coded it to work either way, since I wasn't sure. */
sh
=
scsi_hostlist
;
found
=
0
;
do
{
if
(
sh
==
NULL
)
break
;
if
(
sh
->
host_no
==
hostnum
)
{
found
++
;
break
;
}
sh
=
sh
->
next
;
}
while
(
sh
!=
scsi_hostlist
&&
sh
!=
NULL
);
if
(
sh
==
NULL
||
found
==
0
)
/* This really shouldn't ever happen. */
sh
=
scsi_host_hn_get
(
hostnum
);
if
(
sh
==
NULL
)
/* This really shouldn't ever happen. */
return
-
EINVAL
;
ci
=
(
ctlr_info_t
*
)
sh
->
hostdata
[
0
];
...
...
drivers/scsi/53c700.c
View file @
8428b10d
...
...
@@ -1723,13 +1723,11 @@ NCR_700_proc_directory_info(char *proc_buf, char **startp,
{
static
char
buf
[
4096
];
/* 1 page should be sufficient */
int
len
=
0
;
struct
Scsi_Host
*
host
=
scsi_hostlist
;
struct
Scsi_Host
*
host
;
struct
NCR_700_Host_Parameters
*
hostdata
;
Scsi_Device
*
SDp
;
while
(
host
!=
NULL
&&
host
->
host_no
!=
host_no
)
host
=
host
->
next
;
host
=
scsi_host_hn_get
(
host_no
);
if
(
host
==
NULL
)
return
0
;
...
...
drivers/scsi/aic7xxx/aic7xxx_linux_host.h
View file @
8428b10d
...
...
@@ -63,7 +63,6 @@ int ahc_linux_abort(Scsi_Cmnd *);
* to do with card config are filled in after the card is detected.
*/
#define AIC7XXX { \
next: NULL, \
module: NULL, \
proc_dir: NULL, \
proc_info: ahc_linux_proc_info, \
...
...
drivers/scsi/cpqfcTSinit.c
View file @
8428b10d
...
...
@@ -938,9 +938,7 @@ int cpqfcTS_proc_info (char *buffer, char **start, off_t offset, int length,
char
buf
[
81
];
// Search the Scsi host list for our controller
for
(
host
=
scsi_hostlist
;
host
;
host
=
host
->
next
)
if
(
host
->
host_no
==
hostno
)
break
;
host
=
scsi_host_hn_get
(
hostno
);
if
(
!
host
)
return
-
ESRCH
;
...
...
drivers/scsi/fcal.c
View file @
8428b10d
...
...
@@ -213,9 +213,7 @@ int fcal_proc_info (char *buffer, char **start, off_t offset, int length, int ho
char
*
pos
=
buffer
;
int
i
,
j
;
for
(
host
=
scsi_hostlist
;
host
;
host
=
host
->
next
)
if
(
host
->
host_no
==
hostno
)
break
;
host
=
scsi_host_hn_get
(
hostno
);
if
(
!
host
)
return
-
ESRCH
;
...
...
drivers/scsi/hosts.c
View file @
8428b10d
...
...
@@ -15,12 +15,15 @@
* Updated to reflect the new initialization scheme for the higher
* level of scsi drivers (sd/sr/st)
* September 17, 2000 Torben Mathiasen <tmm@image.dk>
*
* Restructured scsi_host lists and associated functions.
* September 04, 2002 Mike Anderson (andmike@us.ibm.com)
*/
/*
* This file contains the medium level SCSI
* host interface initialization, as well as the scsi_hosts
array
of SCSI
* host interface initialization, as well as the scsi_hosts
list
of SCSI
* hosts currently present in the system.
*/
...
...
@@ -31,232 +34,711 @@
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/smp_lock.h>
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
#include <asm/dma.h>
#include "scsi.h"
#include "hosts.h"
/*
static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/hosts.c,v 1.20 1996/12/12 19:18:32 davem Exp $";
*/
LIST_HEAD
(
scsi_host_tmpl_list
);
LIST_HEAD
(
scsi_host_hn_list
);
/*
* The scsi host entries should be in the order you wish the
* cards to be detected. A driver may appear more than once IFF
* it can deal with being detected (and therefore initialized)
* with more than one simultaneous host number, can handle being
* reentrant, etc.
LIST_HEAD
(
scsi_host_list
);
spinlock_t
scsi_host_list_lock
=
SPIN_LOCK_UNLOCKED
;
struct
Scsi_Device_Template
*
scsi_devicelist
;
static
int
scsi_host_next_hn
;
/* host_no for next new host */
static
int
scsi_hosts_registered
;
/* cnt of registered scsi hosts */
/**
* scsi_tp_for_each_host - call function for each scsi host off a template
* @shost_tp: a pointer to a scsi host template
* @callback: a pointer to callback function
*
* They may appear in any order, as each SCSI host is told which host
* number it is during detection.
*/
* Return value:
* 0 on Success / 1 on Failure
**/
int
scsi_tp_for_each_host
(
Scsi_Host_Template
*
shost_tp
,
int
(
*
callback
)(
struct
Scsi_Host
*
shost
))
{
struct
list_head
*
lh
,
*
lh_sf
;
struct
Scsi_Host
*
shost
;
/*
* When figure is run, we don't want to link to any object code. Since
* the macro for each host will contain function pointers, we cannot
* use it and instead must use a "blank" that does no such
* idiocy.
spin_lock
(
&
scsi_host_list_lock
);
list_for_each_safe
(
lh
,
lh_sf
,
&
scsi_host_list
)
{
shost
=
list_entry
(
lh
,
struct
Scsi_Host
,
sh_list
);
if
(
shost
->
hostt
==
shost_tp
)
{
spin_unlock
(
&
scsi_host_list_lock
);
callback
(
shost
);
spin_lock
(
&
scsi_host_list_lock
);
}
}
spin_unlock
(
&
scsi_host_list_lock
);
return
0
;
}
/**
* scsi_host_generic_release - default release function for hosts
* @shost:
*
* Description:
* This is the default case for the release function. It should do
* the right thing for most correctly written host adapters.
**/
static
void
scsi_host_generic_release
(
struct
Scsi_Host
*
shost
)
{
if
(
shost
->
irq
)
free_irq
(
shost
->
irq
,
NULL
);
if
(
shost
->
dma_channel
!=
0xff
)
free_dma
(
shost
->
dma_channel
);
if
(
shost
->
io_port
&&
shost
->
n_io_port
)
release_region
(
shost
->
io_port
,
shost
->
n_io_port
);
}
/**
* scsi_host_chk_and_release - check a scsi host for release and release
* @shost: a pointer to a scsi host to release
*
* Return value:
* 0 on Success / 1 on Failure
**/
int
scsi_host_chk_and_release
(
struct
Scsi_Host
*
shost
)
{
int
pcount
;
Scsi_Device
*
sdev
;
struct
Scsi_Device_Template
*
sdev_tp
;
Scsi_Cmnd
*
scmd
;
/*
* Current policy is all shosts go away on unregister.
*/
if
(
shost
->
hostt
->
module
&&
GET_USE_COUNT
(
shost
->
hostt
->
module
))
return
1
;
Scsi_Host_Template
*
scsi_hosts
;
/*
* FIXME Do ref counting. We force all of the devices offline to
* help prevent race conditions where other hosts/processors could
* try and get in and queue a command.
*/
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
sdev
->
online
=
FALSE
;
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
/*
* Loop over all of the commands associated with the
* device. If any of them are busy, then set the state
* back to inactive and bail.
*/
for
(
scmd
=
sdev
->
device_queue
;
scmd
;
scmd
=
scmd
->
next
)
{
if
(
scmd
->
request
&&
scmd
->
request
->
rq_status
!=
RQ_INACTIVE
)
{
printk
(
KERN_ERR
"SCSI device not inactive"
"- rq_status=%d, target=%d, pid=%ld,"
"state=%d, owner=%d.
\n
"
,
scmd
->
request
->
rq_status
,
scmd
->
target
,
scmd
->
pid
,
scmd
->
state
,
scmd
->
owner
);
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
for
(
scmd
=
sdev
->
device_queue
;
scmd
;
scmd
=
scmd
->
next
)
if
(
scmd
->
request
->
rq_status
==
RQ_SCSI_DISCONNECTING
)
scmd
->
request
->
rq_status
=
RQ_INACTIVE
;
}
printk
(
KERN_ERR
"Device busy???
\n
"
);
return
1
;
}
/*
* No, this device is really free. Mark it as such, and
* continue on.
*/
scmd
->
state
=
SCSI_STATE_DISCONNECTING
;
if
(
scmd
->
request
)
scmd
->
request
->
rq_status
=
RQ_SCSI_DISCONNECTING
;
/* Mark as
busy */
}
}
/*
* Our semaphores and timeout counters, where size depends on
* MAX_SCSI_HOSTS here.
/*
* Next we detach the high level drivers from the Scsi_Device
* structures
*/
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
{
for
(
sdev_tp
=
scsi_devicelist
;
sdev_tp
;
sdev_tp
=
sdev_tp
->
next
)
if
(
sdev_tp
->
detach
)
(
*
sdev_tp
->
detach
)
(
sdev
);
/* If something still attached, punt */
if
(
sdev
->
attached
)
{
printk
(
KERN_ERR
"Attached usage count = %d
\n
"
,
sdev
->
attached
);
return
1
;
}
Scsi_Host_Name
*
scsi_host_no_list
;
struct
Scsi_Host
*
scsi_hostlist
;
struct
Scsi_Device_Template
*
scsi_devicelist
;
if
(
shost
->
hostt
->
slave_detach
)
(
*
shost
->
hostt
->
slave_detach
)
(
sdev
);
int
max_scsi_hosts
;
int
next_scsi_host
;
devfs_unregister
(
sdev
->
de
);
device_unregister
(
&
sdev
->
sdev_driverfs_dev
);
}
void
scsi_unregister
(
struct
Scsi_Host
*
sh
){
struct
Scsi_Host
*
shpnt
;
Scsi_Host_Name
*
shn
;
/* Next we free up the Scsi_Cmnd structures for this host */
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
shost
->
host_queue
)
{
scsi_release_commandblocks
(
sdev
);
blk_cleanup_queue
(
&
sdev
->
request_queue
);
/* Next free up the Scsi_Device structures for this host */
shost
->
host_queue
=
sdev
->
next
;
if
(
sdev
->
inquiry
)
kfree
(
sdev
->
inquiry
);
kfree
(
sdev
);
}
if
(
scsi_hostlist
==
sh
)
scsi_hostlist
=
sh
->
next
;
/* Remove the instance of the individual hosts */
pcount
=
scsi_hosts_registered
;
if
(
shost
->
hostt
->
release
)
(
*
shost
->
hostt
->
release
)
(
shost
);
else
{
shpnt
=
scsi_hostlist
;
while
(
shpnt
->
next
!=
sh
)
shpnt
=
shpnt
->
next
;
shpnt
->
next
=
shpnt
->
next
->
next
;
scsi_host_generic_release
(
shost
);
}
if
(
pcount
==
scsi_hosts_registered
)
scsi_unregister
(
shost
);
return
0
;
}
/**
* scsi_unregister - unregister a scsi host
* @shost: scsi host to be unregistered
**/
void
scsi_unregister
(
struct
Scsi_Host
*
shost
)
{
struct
list_head
*
lh
;
Scsi_Host_Name
*
shost_name
;
/* Remove shost from scsi_host_list */
spin_lock
(
&
scsi_host_list_lock
);
list_del
(
&
shost
->
sh_list
);
spin_unlock
(
&
scsi_host_list_lock
);
/* Unregister from scsi_host_hn_list */
list_for_each
(
lh
,
&
scsi_host_hn_list
)
{
shost_name
=
list_entry
(
lh
,
Scsi_Host_Name
,
shn_list
);
if
(
shost
->
host_no
==
shost_name
->
host_no
)
shost_name
->
host_registered
=
0
;
}
/*
* We have to unregister the host from the scsi_host_no_list as well.
* Decide by the host_no not by the name because most host drivers are
* able to handle more than one adapters from the same kind (or family).
*/
for
(
shn
=
scsi_host_no_list
;
shn
&&
(
sh
->
host_no
!=
shn
->
host_no
);
shn
=
shn
->
next
);
if
(
shn
)
shn
->
host_registered
=
0
;
/* else {} : This should not happen, we should panic here... */
/* If we are removing the last host registered, it is safe to reuse
* its host number (this avoids "holes" at boot time) (DB)
* It is also safe to reuse those of numbers directly below which have
* been released earlier (to avoid some holes in numbering).
* Next, kill the kernel error recovery thread for this host.
*/
if
(
sh
->
host_no
==
max_scsi_hosts
-
1
)
{
while
(
--
max_scsi_hosts
>=
next_scsi_host
)
{
shpnt
=
scsi_hostlist
;
while
(
shpnt
&&
shpnt
->
host_no
!=
max_scsi_hosts
-
1
)
shpnt
=
shpnt
->
next
;
if
(
shpnt
)
break
;
if
(
shost
->
ehandler
)
{
DECLARE_MUTEX_LOCKED
(
sem
);
shost
->
eh_notify
=
&
sem
;
send_sig
(
SIGHUP
,
shost
->
ehandler
,
1
);
down
(
&
sem
);
shost
->
eh_notify
=
NULL
;
}
scsi_hosts_registered
--
;
shost
->
hostt
->
present
--
;
/* Cleanup proc and driverfs */
#ifdef CONFIG_PROC_FS
scsi_proc_host_rm
(
shost
);
if
(
!
shost
->
hostt
->
present
)
remove_proc_entry
(
shost
->
hostt
->
proc_name
,
proc_scsi
);
#endif
device_unregister
(
&
shost
->
host_driverfs_dev
);
kfree
(
shost
);
}
/**
* scsi_host_hn_add - allocate and add new Scsi_Host_Name
* @name: String to store in name field
*
* Return value:
* Pointer to a new Scsi_Host_Name
**/
Scsi_Host_Name
*
scsi_host_hn_add
(
char
*
name
)
{
Scsi_Host_Name
*
shost_name
;
int
len
;
len
=
strlen
(
name
);
shost_name
=
kmalloc
(
sizeof
(
*
shost_name
),
GFP_KERNEL
);
if
(
!
shost_name
)
{
printk
(
KERN_ERR
"%s: out of memory at line %d.
\n
"
,
__FUNCTION__
,
__LINE__
);
return
NULL
;
}
shost_name
->
name
=
kmalloc
(
len
+
1
,
GFP_KERNEL
);
if
(
!
shost_name
->
name
)
{
kfree
(
shost_name
);
printk
(
KERN_ERR
"%s: out of memory at line %d.
\n
"
,
__FUNCTION__
,
__LINE__
);
return
NULL
;
}
next_scsi_host
--
;
kfree
((
char
*
)
sh
);
if
(
len
)
strncpy
(
shost_name
->
name
,
name
,
len
);
shost_name
->
name
[
len
]
=
0
;
shost_name
->
host_no
=
scsi_host_next_hn
++
;
shost_name
->
host_registered
=
0
;
list_add_tail
(
&
shost_name
->
shn_list
,
&
scsi_host_hn_list
);
return
shost_name
;
}
/* We call this when we come across a new host adapter. We only do this
* once we are 100% sure that we want to use this host adapter - it is a
* pain to reverse this, so we try to avoid it
*/
/**
* scsi_register - register a scsi host adapter instance.
* @shost_tp: pointer to scsi host template
* @xtr_bytes: extra bytes to allocate for driver
*
* Note:
* We call this when we come across a new host adapter. We only do
* this once we are 100% sure that we want to use this host adapter -
* it is a pain to reverse this, so we try to avoid it
*
* Return value:
* Pointer to a new Scsi_Host
**/
extern
int
blk_nohighio
;
struct
Scsi_Host
*
scsi_register
(
Scsi_Host_Template
*
tpnt
,
int
j
)
struct
Scsi_Host
*
scsi_register
(
Scsi_Host_Template
*
shost_tp
,
int
xtr_bytes
)
{
struct
Scsi_Host
*
retval
,
*
shpnt
,
*
o_shp
;
Scsi_Host_Name
*
shn
,
*
shn2
;
int
flag_new
=
1
;
const
char
*
hname
;
struct
Scsi_Host
*
shost
,
*
shost_scr
;
Scsi_Host_Name
*
shost_name
=
NULL
;
Scsi_Host_Name
*
shn
=
NULL
;
char
*
hname
;
size_t
hname_len
;
retval
=
(
struct
Scsi_Host
*
)
kmalloc
(
sizeof
(
struct
Scsi_Host
)
+
j
,
(
tpnt
->
unchecked_isa_dma
&&
j
?
GFP_DMA
:
0
)
|
GFP_ATOMIC
);
if
(
retval
==
NULL
)
{
printk
(
"scsi: out of memory in scsi_register.
\n
"
);
struct
list_head
*
lh
;
int
gfp_mask
;
DECLARE_MUTEX_LOCKED
(
sem
);
gfp_mask
=
GFP_KERNEL
;
if
(
shost_tp
->
unchecked_isa_dma
&&
xtr_bytes
)
gfp_mask
|=
__GFP_DMA
;
shost
=
kmalloc
(
sizeof
(
struct
Scsi_Host
)
+
xtr_bytes
,
gfp_mask
);
if
(
!
shost
)
{
printk
(
KERN_ERR
"%s: out of memory.
\n
"
,
__FUNCTION__
);
return
NULL
;
}
memset
(
retval
,
0
,
sizeof
(
struct
Scsi_Host
)
+
j
);
memset
(
shost
,
0
,
sizeof
(
struct
Scsi_Host
)
+
xtr_bytes
);
/* trying to find a reserved entry (host_no) */
hname
=
(
tpnt
->
proc_name
)
?
tpnt
->
proc_name
:
""
;
/*
* Determine host number. Check reserved first before allocating
* new one
*/
hname
=
(
shost_tp
->
proc_name
)
?
shost_tp
->
proc_name
:
""
;
hname_len
=
strlen
(
hname
);
for
(
shn
=
scsi_host_no_list
;
shn
;
shn
=
shn
->
next
)
{
if
(
hname_len
)
list_for_each
(
lh
,
&
scsi_host_hn_list
)
{
shn
=
list_entry
(
lh
,
Scsi_Host_Name
,
shn_list
);
if
(
!
(
shn
->
host_registered
)
&&
(
hname_len
>
0
)
&&
(
0
==
strncmp
(
hname
,
shn
->
name
,
hname_len
)))
{
flag_new
=
0
;
retval
->
host_no
=
shn
->
host_no
;
shn
->
host_registered
=
1
;
!
strncmp
(
hname
,
shn
->
name
,
hname_len
))
{
shost_name
=
shn
;
break
;
}
}
spin_lock_init
(
&
retval
->
default_lock
);
scsi_assign_lock
(
retval
,
&
retval
->
default_lock
);
atomic_set
(
&
retval
->
host_active
,
0
);
retval
->
host_busy
=
0
;
retval
->
host_failed
=
0
;
if
(
flag_new
)
{
shn
=
(
Scsi_Host_Name
*
)
kmalloc
(
sizeof
(
Scsi_Host_Name
),
GFP_ATOMIC
);
if
(
!
shn
)
{
kfree
(
retval
);
printk
(
KERN_ERR
"scsi: out of memory(2) in scsi_register.
\n
"
);
if
(
!
shost_name
)
{
shost_name
=
scsi_host_hn_add
(
hname
);
if
(
!
shost_name
)
{
kfree
(
shost
);
return
NULL
;
}
shn
->
name
=
kmalloc
(
hname_len
+
1
,
GFP_ATOMIC
);
if
(
hname_len
>
0
)
strncpy
(
shn
->
name
,
hname
,
hname_len
);
shn
->
name
[
hname_len
]
=
0
;
shn
->
host_no
=
max_scsi_hosts
++
;
shn
->
host_registered
=
1
;
shn
->
next
=
NULL
;
if
(
scsi_host_no_list
)
{
for
(
shn2
=
scsi_host_no_list
;
shn2
->
next
;
shn2
=
shn2
->
next
)
;
shn2
->
next
=
shn
;
}
else
scsi_host_no_list
=
shn
;
retval
->
host_no
=
shn
->
host_no
;
}
next_scsi_host
++
;
retval
->
host_queue
=
NULL
;
init_waitqueue_head
(
&
retval
->
host_wait
);
retval
->
resetting
=
0
;
retval
->
last_reset
=
0
;
retval
->
irq
=
0
;
retval
->
dma_channel
=
0xff
;
shost
->
host_no
=
shost_name
->
host_no
;
shost_name
->
host_registered
=
1
;
scsi_hosts_registered
++
;
spin_lock_init
(
&
shost
->
default_lock
)
;
scsi_assign_lock
(
shost
,
&
shost
->
default_lock
);
atomic_set
(
&
shost
->
host_active
,
0
)
;
init_waitqueue_head
(
&
shost
->
host_wait
)
;
shost
->
dma_channel
=
0xff
;
/* These three are default values which can be overridden */
retval
->
max_channel
=
0
;
retval
->
max_id
=
8
;
retval
->
max_lun
=
8
;
shost
->
max_channel
=
0
;
shost
->
max_id
=
8
;
shost
->
max_lun
=
8
;
/*
* All drivers right now should be able to handle 12 byte commands.
* Every so often there are requests for 16 byte commands, but individual
* low-level drivers need to certify that they actually do something
*
sensible with such commands.
* All drivers right now should be able to handle 12 byte
* commands. Every so often there are requests for 16 byte
* commands, but individual low-level drivers need to certify that
* they actually do something
sensible with such commands.
*/
retval
->
max_cmd_len
=
12
;
shost
->
max_cmd_len
=
12
;
shost
->
hostt
=
shost_tp
;
shost
->
host_blocked
=
FALSE
;
shost
->
host_self_blocked
=
FALSE
;
retval
->
unique_id
=
0
;
retval
->
io_port
=
0
;
retval
->
hostt
=
tpnt
;
retval
->
next
=
NULL
;
retval
->
in_recovery
=
0
;
retval
->
ehandler
=
NULL
;
/* Initial value until the thing starts up. */
retval
->
eh_notify
=
NULL
;
/* Who we notify when we exit. */
#ifdef DEBUG
printk
(
"%s: %x %x: %d
\n
"
,
__FUNCTION_
(
int
)
shost
,
(
int
)
shost
->
hostt
,
xtr_bytes
);
#endif
retval
->
max_host_blocked
=
tpnt
->
max_host_blocked
?
tpnt
->
max_host_blocked
:
SCSI_DEFAULT_HOST_BLOCKED
;
/*
* The next six are the default values which can be overridden if
* need be
*/
shost
->
this_id
=
shost_tp
->
this_id
;
shost
->
can_queue
=
shost_tp
->
can_queue
;
shost
->
sg_tablesize
=
shost_tp
->
sg_tablesize
;
shost
->
cmd_per_lun
=
shost_tp
->
cmd_per_lun
;
shost
->
unchecked_isa_dma
=
shost_tp
->
unchecked_isa_dma
;
shost
->
use_clustering
=
shost_tp
->
use_clustering
;
if
(
!
blk_nohighio
)
shost
->
highmem_io
=
shost_tp
->
highmem_io
;
retval
->
host_blocked
=
0
;
retval
->
host_self_blocked
=
FALSE
;
shost
->
max_sectors
=
shost_tp
->
max_sectors
;
shost
->
use_blk_tcq
=
shost_tp
->
use_blk_tcq
;
#ifdef DEBUG
printk
(
"Register %x %x: %d
\n
"
,
(
int
)
retval
,
(
int
)
retval
->
hostt
,
j
);
spin_lock
(
&
scsi_host_list_lock
);
/*
* FIXME When device naming is complete remove this step that
* orders the scsi_host_list by host number and just do a
* list_add_tail.
*/
list_for_each
(
lh
,
&
scsi_host_list
)
{
shost_scr
=
list_entry
(
lh
,
struct
Scsi_Host
,
sh_list
);
if
(
shost
->
host_no
<
shost_scr
->
host_no
)
{
__list_add
(
&
shost
->
sh_list
,
shost_scr
->
sh_list
.
prev
,
&
shost_scr
->
sh_list
);
goto
found
;
}
}
list_add_tail
(
&
shost
->
sh_list
,
&
scsi_host_list
);
found:
spin_unlock
(
&
scsi_host_list_lock
);
#ifdef CONFIG_PROC_FS
/* Add the new driver to /proc/scsi if not already there */
if
(
!
shost_tp
->
proc_dir
)
scsi_proc_host_mkdir
(
shost_tp
);
scsi_proc_host_add
(
shost
);
#endif
/* The next six are the default values which can be overridden
* if need be */
retval
->
this_id
=
tpnt
->
this_id
;
retval
->
can_queue
=
tpnt
->
can_queue
;
retval
->
sg_tablesize
=
tpnt
->
sg_tablesize
;
retval
->
cmd_per_lun
=
tpnt
->
cmd_per_lun
;
retval
->
unchecked_isa_dma
=
tpnt
->
unchecked_isa_dma
;
retval
->
use_clustering
=
tpnt
->
use_clustering
;
if
(
!
blk_nohighio
)
retval
->
highmem_io
=
tpnt
->
highmem_io
;
strncpy
(
shost
->
host_driverfs_dev
.
name
,
shost_tp
->
proc_name
,
DEVICE_NAME_SIZE
-
1
);
sprintf
(
shost
->
host_driverfs_dev
.
bus_id
,
"scsi%d"
,
shost
->
host_no
);
retval
->
max_sectors
=
tpnt
->
max_sectors
;
retval
->
use_blk_tcq
=
tpnt
->
use_blk_tcq
;
shost
->
eh_notify
=
&
sem
;
kernel_thread
((
int
(
*
)(
void
*
))
scsi_error_handler
,
(
void
*
)
shost
,
0
);
/*
* Now wait for the kernel error thread to initialize itself
* as it might be needed when we scan the bus.
*/
down
(
&
sem
);
shost
->
eh_notify
=
NULL
;
if
(
!
scsi_hostlist
)
scsi_hostlist
=
retval
;
else
{
shpnt
=
scsi_hostlist
;
if
(
retval
->
host_no
<
shpnt
->
host_no
)
{
retval
->
next
=
shpnt
;
wmb
();
/* want all to see these writes in this order */
scsi_hostlist
=
retval
;
shost
->
hostt
->
present
++
;
return
shost
;
}
/**
* scsi_register_host - register a low level host driver
* @shost_tp: pointer to a scsi host driver template
*
* Return value:
* 0 on Success / 1 on Failure.
**/
int
scsi_register_host
(
Scsi_Host_Template
*
shost_tp
)
{
int
cur_cnt
;
Scsi_Device
*
sdev
;
struct
Scsi_Device_Template
*
sdev_tp
;
struct
list_head
*
lh
;
struct
Scsi_Host
*
shost
;
/*
* Check no detect routine.
*/
if
(
!
shost_tp
->
detect
)
return
1
;
/* If max_sectors isn't set, default to max */
if
(
!
shost_tp
->
max_sectors
)
shost_tp
->
max_sectors
=
1024
;
cur_cnt
=
scsi_hosts_registered
;
MOD_INC_USE_COUNT
;
/*
* The detect routine must carefully spinunlock/spinlock if it
* enables interrupts, since all interrupt handlers do spinlock as
* well.
*/
/*
* detect should do its own locking
* FIXME present is now set is scsi_register which breaks manual
* registration code below.
*/
shost_tp
->
detect
(
shost_tp
);
if
(
shost_tp
->
present
)
{
/*
* FIXME Who needs manual registration and why???
*/
if
(
cur_cnt
==
scsi_hosts_registered
)
{
if
(
shost_tp
->
present
>
1
)
{
printk
(
KERN_ERR
"scsi: Failure to register"
"low-level scsi driver"
);
scsi_unregister_host
(
shost_tp
);
return
1
;
}
else
{
for
(
o_shp
=
shpnt
,
shpnt
=
shpnt
->
next
;
shpnt
;
o_shp
=
shpnt
,
shpnt
=
shpnt
->
next
)
{
if
(
retval
->
host_no
<
shpnt
->
host_no
)
{
retval
->
next
=
shpnt
;
wmb
();
o_shp
->
next
=
retval
;
break
;
/*
* The low-level driver failed to register a driver.
* We can do this now.
*/
if
(
scsi_register
(
shost_tp
,
0
)
==
NULL
)
{
printk
(
KERN_ERR
"scsi: register failed.
\n
"
);
scsi_unregister_host
(
shost_tp
);
return
1
;
}
}
list_add_tail
(
&
shost_tp
->
shtp_list
,
&
scsi_host_tmpl_list
);
/* The next step is to call scan_scsis here. This generates the
* Scsi_Devices entries
*/
list_for_each
(
lh
,
&
scsi_host_list
)
{
shost
=
list_entry
(
lh
,
struct
Scsi_Host
,
sh_list
);
if
(
shost
->
hostt
==
shost_tp
)
{
const
char
*
dm_name
;
if
(
shost_tp
->
info
)
{
dm_name
=
shost_tp
->
info
(
shost
);
}
else
{
dm_name
=
shost_tp
->
name
;
}
printk
(
KERN_INFO
"scsi%d : %s
\n
"
,
shost
->
host_no
,
dm_name
);
/* first register parent with driverfs */
device_register
(
&
shost
->
host_driverfs_dev
);
scan_scsis
(
shost
,
0
,
0
,
0
,
0
);
}
if
(
!
shpnt
)
o_shp
->
next
=
retval
;
}
for
(
sdev_tp
=
scsi_devicelist
;
sdev_tp
;
sdev_tp
=
sdev_tp
->
next
)
{
if
(
sdev_tp
->
init
&&
sdev_tp
->
dev_noticed
)
(
*
sdev_tp
->
init
)
();
}
return
retval
;
/*
* Next we create the Scsi_Cmnd structures for this host
*/
list_for_each
(
lh
,
&
scsi_host_list
)
{
shost
=
list_entry
(
lh
,
struct
Scsi_Host
,
sh_list
);
for
(
sdev
=
shost
->
host_queue
;
sdev
;
sdev
=
sdev
->
next
)
if
(
sdev
->
host
->
hostt
==
shost_tp
)
{
for
(
sdev_tp
=
scsi_devicelist
;
sdev_tp
;
sdev_tp
=
sdev_tp
->
next
)
if
(
sdev_tp
->
attach
)
(
*
sdev_tp
->
attach
)
(
sdev
);
if
(
sdev
->
attached
)
{
scsi_build_commandblocks
(
sdev
);
if
(
sdev
->
current_queue_depth
==
0
)
goto
out_of_space
;
}
}
}
/* This does any final handling that is required. */
for
(
sdev_tp
=
scsi_devicelist
;
sdev_tp
;
sdev_tp
=
sdev_tp
->
next
)
{
if
(
sdev_tp
->
finish
&&
sdev_tp
->
nr_dev
)
{
(
*
sdev_tp
->
finish
)
();
}
}
}
return
0
;
out_of_space:
scsi_unregister_host
(
shost_tp
);
/* easiest way to clean up?? */
return
1
;
}
/**
* scsi_unregister_host - unregister a low level host adapter driver
* @shost_tp: scsi host template to unregister.
*
* Description:
* Similarly, this entry point should be called by a loadable module
* if it is trying to remove a low level scsi driver from the system.
*
* Return value:
* 0 on Success / 1 on Failure
*
* Notes:
* rmmod does not care what we return here the module will be
* removed.
**/
int
scsi_unregister_host
(
Scsi_Host_Template
*
shost_tp
)
{
int
pcount
;
/* get the big kernel lock, so we don't race with open() */
lock_kernel
();
pcount
=
scsi_hosts_registered
;
scsi_tp_for_each_host
(
shost_tp
,
scsi_host_chk_and_release
);
if
(
pcount
!=
scsi_hosts_registered
)
printk
(
KERN_INFO
"scsi : %d host%s left.
\n
"
,
scsi_hosts_registered
,
(
scsi_hosts_registered
==
1
)
?
""
:
"s"
);
/*
* Remove it from the list if all
* hosts were successfully removed (ie preset == 0)
*/
if
(
!
shost_tp
->
present
)
{
list_del
(
&
shost_tp
->
shtp_list
);
}
MOD_DEC_USE_COUNT
;
unlock_kernel
();
return
0
;
}
/**
* *scsi_host_get_next - get scsi host and inc ref count
* @shost: pointer to a Scsi_Host or NULL to start.
*
* Return value:
* A pointer to next Scsi_Host in list or NULL.
**/
struct
Scsi_Host
*
scsi_host_get_next
(
struct
Scsi_Host
*
shost
)
{
struct
list_head
*
lh
=
NULL
;
spin_lock
(
&
scsi_host_list_lock
);
if
(
shost
)
{
/* XXX Dec ref on cur shost */
lh
=
shost
->
sh_list
.
next
;
}
else
{
lh
=
scsi_host_list
.
next
;
}
if
(
lh
==
&
scsi_host_list
)
{
shost
=
(
struct
Scsi_Host
*
)
NULL
;
goto
done
;
}
shost
=
list_entry
(
lh
,
struct
Scsi_Host
,
sh_list
);
/* XXX Inc ref count */
done:
spin_unlock
(
&
scsi_host_list_lock
);
return
shost
;
}
/**
* scsi_host_hn_get - get a Scsi_Host by host no and inc ref count
* @host_no: host number to locate
*
* Return value:
* A pointer to located Scsi_Host or NULL.
**/
struct
Scsi_Host
*
scsi_host_hn_get
(
unsigned
short
host_no
)
{
struct
list_head
*
lh
;
struct
Scsi_Host
*
shost
;
spin_lock
(
&
scsi_host_list_lock
);
list_for_each
(
lh
,
&
scsi_host_list
)
{
shost
=
list_entry
(
lh
,
struct
Scsi_Host
,
sh_list
);
if
(
shost
->
host_no
==
host_no
)
{
/* XXX Inc ref count */
goto
done
;
}
}
shost
=
(
struct
Scsi_Host
*
)
NULL
;
done:
spin_unlock
(
&
scsi_host_list_lock
);
return
shost
;
}
/**
* *scsi_host_put - dec a Scsi_Host ref count
* @shost: Pointer to Scsi_Host to dec.
**/
void
scsi_host_put
(
struct
Scsi_Host
*
shost
)
{
/* XXX Get list lock */
/* XXX dec ref count */
/* XXX Release list lock */
return
;
}
/**
* scsi_host_hn_init - init scsi host number list from string
* @shost_hn: string of scsi host driver names.
**/
void
__init
scsi_host_hn_init
(
char
*
shost_hn
)
{
char
*
temp
=
shost_hn
;
while
(
temp
)
{
while
(
*
temp
&&
(
*
temp
!=
':'
)
&&
(
*
temp
!=
','
))
temp
++
;
if
(
!*
temp
)
temp
=
NULL
;
else
*
temp
++
=
0
;
(
void
)
scsi_host_hn_add
(
shost_hn
);
shost_hn
=
temp
;
}
}
/**
* scsi_host_no_release - free all entries in scsi host number list
**/
void
__exit
scsi_host_hn_release
()
{
struct
list_head
*
lh
,
*
next
;
Scsi_Host_Name
*
shn
;
list_for_each_safe
(
lh
,
next
,
&
scsi_host_hn_list
)
{
shn
=
list_entry
(
lh
,
Scsi_Host_Name
,
shn_list
);
if
(
shn
->
name
)
kfree
(
shn
->
name
);
kfree
(
shn
);
}
}
void
scsi_host_busy_inc
(
struct
Scsi_Host
*
shost
,
Scsi_Device
*
sdev
)
...
...
@@ -279,8 +761,7 @@ void scsi_host_busy_dec_and_test(struct Scsi_Host *shost, Scsi_Device *sdev)
if
(
shost
->
in_recovery
&&
(
shost
->
host_busy
==
shost
->
host_failed
))
{
up
(
shost
->
eh_wait
);
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"Waking error handler"
"thread (%d)
\n
"
,
atomic_read
(
&
shost
->
eh_wait
->
count
)));
" thread
\n
"
));
}
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
}
...
...
@@ -295,8 +776,7 @@ void scsi_host_failed_inc_and_test(struct Scsi_Host *shost)
if
(
shost
->
host_busy
==
shost
->
host_failed
)
{
up
(
shost
->
eh_wait
);
SCSI_LOG_ERROR_RECOVERY
(
5
,
printk
(
"Waking error handler"
"thread (%d)
\n
"
,
atomic_read
(
&
shost
->
eh_wait
->
count
)));
" thread
\n
"
));
}
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
}
...
...
drivers/scsi/hosts.h
View file @
8428b10d
...
...
@@ -16,15 +16,14 @@
* of the same type.
*
* Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
*
* Restructured scsi_host lists and associated functions.
* September 04, 2002 Mike Anderson (andmike@us.ibm.com)
*/
#ifndef _HOSTS_H
#define _HOSTS_H
/*
$Header: /vger/u4/cvs/linux/drivers/scsi/hosts.h,v 1.6 1997/01/19 23:07:13 davem Exp $
*/
#include <linux/config.h>
#include <linux/proc_fs.h>
#include <linux/pci.h>
...
...
@@ -58,8 +57,7 @@ typedef struct scsi_disk Disk;
typedef
struct
SHT
{
/* Used with loadable modules so we can construct a linked list. */
struct
SHT
*
next
;
struct
list_head
shtp_list
;
/* Used with loadable modules so that we know when it is safe to unload */
struct
module
*
module
;
...
...
@@ -374,7 +372,7 @@ struct Scsi_Host
* This information is private to the scsi mid-layer. Wrapping it in a
* struct private is a way of marking it in a sort of C++ type of way.
*/
struct
Scsi_Host
*
nex
t
;
struct
list_head
sh_lis
t
;
Scsi_Device
*
host_queue
;
struct
list_head
all_scsi_hosts
;
struct
list_head
my_devices
;
...
...
@@ -510,28 +508,26 @@ struct Scsi_Host
* thing. This physical pseudo-device isn't real and won't be available
* from any high-level drivers.
*/
extern
void
scsi_free_host_dev
(
Scsi_Device
*
SDpnt
);
extern
Scsi_Device
*
scsi_get_host_dev
(
struct
Scsi_Host
*
SHpnt
);
extern
void
scsi_free_host_dev
(
Scsi_Device
*
);
extern
Scsi_Device
*
scsi_get_host_dev
(
struct
Scsi_Host
*
);
extern
void
scsi_unblock_requests
(
struct
Scsi_Host
*
SHpnt
);
extern
void
scsi_block_requests
(
struct
Scsi_Host
*
SHpnt
);
extern
void
scsi_report_bus_reset
(
struct
Scsi_Host
*
SHpnt
,
int
channel
);
extern
void
scsi_unblock_requests
(
struct
Scsi_Host
*
);
extern
void
scsi_block_requests
(
struct
Scsi_Host
*
);
extern
void
scsi_report_bus_reset
(
struct
Scsi_Host
*
,
int
);
typedef
struct
SHN
{
struct
SHN
*
nex
t
;
char
*
name
;
{
struct
list_head
shn_lis
t
;
char
*
name
;
unsigned
short
host_no
;
unsigned
short
host_registered
;
}
Scsi_Host_Name
;
}
Scsi_Host_Name
;
extern
Scsi_Host_Name
*
scsi_host_no_list
;
extern
struct
Scsi_Host
*
scsi_hostlist
;
extern
struct
Scsi_Device_Template
*
scsi_devicelist
;
extern
Scsi_Host_Template
*
scsi_hosts
;
extern
void
build_proc_dir_entries
(
Scsi_Host_Template
*
);
extern
void
scsi_proc_host_mkdir
(
Scsi_Host_Template
*
)
;
extern
void
scsi_proc_host_add
(
struct
Scsi_Host
*
);
extern
void
scsi_proc_host_rm
(
struct
Scsi_Host
*
);
/*
* scsi_init initializes the scsi hosts.
...
...
@@ -540,34 +536,33 @@ extern void build_proc_dir_entries(Scsi_Host_Template *);
extern
int
next_scsi_host
;
unsigned
int
scsi_init
(
void
);
extern
struct
Scsi_Host
*
scsi_register
(
Scsi_Host_Template
*
,
int
j
);
extern
void
scsi_unregister
(
struct
Scsi_Host
*
i
);
extern
void
scsi_register_blocked_host
(
struct
Scsi_Host
*
SHpnt
);
extern
void
scsi_deregister_blocked_host
(
struct
Scsi_Host
*
SHpnt
);
extern
struct
Scsi_Host
*
scsi_register
(
Scsi_Host_Template
*
,
int
);
extern
void
scsi_unregister
(
struct
Scsi_Host
*
);
extern
void
scsi_register_blocked_host
(
struct
Scsi_Host
*
);
extern
void
scsi_deregister_blocked_host
(
struct
Scsi_Host
*
);
static
inline
void
scsi_assign_lock
(
struct
Scsi_Host
*
host
,
spinlock_t
*
lock
)
static
inline
void
scsi_assign_lock
(
struct
Scsi_Host
*
s
host
,
spinlock_t
*
lock
)
{
host
->
host_lock
=
lock
;
s
host
->
host_lock
=
lock
;
}
static
inline
void
scsi_set_pci_device
(
struct
Scsi_Host
*
SHpn
t
,
static
inline
void
scsi_set_pci_device
(
struct
Scsi_Host
*
shos
t
,
struct
pci_dev
*
pdev
)
{
SHpnt
->
pci_dev
=
pdev
;
SHpnt
->
host_driverfs_dev
.
parent
=&
pdev
->
dev
;
shost
->
pci_dev
=
pdev
;
shost
->
host_driverfs_dev
.
parent
=&
pdev
->
dev
;
/* register parent with driverfs */
device_register
(
&
shost
->
host_driverfs_dev
);
}
/*
* Prototypes for functions/data in scsi_scan.c
*/
extern
void
scan_scsis
(
struct
Scsi_Host
*
shpnt
,
uint
hardcoded
,
uint
hchannel
,
uint
hid
,
uint
hlun
);
extern
void
scan_scsis
(
struct
Scsi_Host
*
,
uint
,
uint
,
uint
,
uint
);
extern
void
scsi_mark_host_reset
(
struct
Scsi_Host
*
Host
);
extern
void
scsi_mark_host_reset
(
struct
Scsi_Host
*
);
#define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
...
...
@@ -596,7 +591,7 @@ struct Scsi_Device_Template
struct
device_driver
scsi_driverfs_driver
;
};
void
scsi_initialize_queue
(
Scsi_Device
*
SDpnt
,
struct
Scsi_Host
*
SHpnt
);
void
scsi_initialize_queue
(
Scsi_Device
*
,
struct
Scsi_Host
*
);
/*
...
...
@@ -607,6 +602,12 @@ extern int scsi_unregister_device(struct Scsi_Device_Template *);
extern
int
scsi_register_host
(
Scsi_Host_Template
*
);
extern
int
scsi_unregister_host
(
Scsi_Host_Template
*
);
extern
struct
Scsi_Host
*
scsi_host_get_next
(
struct
Scsi_Host
*
);
extern
struct
Scsi_Host
*
scsi_host_hn_get
(
unsigned
short
);
extern
void
scsi_host_put
(
struct
Scsi_Host
*
);
extern
void
scsi_host_hn_init
(
char
*
);
extern
void
scsi_host_hn_release
(
void
);
/*
* host_busy inc/dec/test functions
*/
...
...
@@ -614,7 +615,6 @@ extern void scsi_host_busy_inc(struct Scsi_Host *, Scsi_Device *);
extern
void
scsi_host_busy_dec_and_test
(
struct
Scsi_Host
*
,
Scsi_Device
*
);
extern
void
scsi_host_failed_inc_and_test
(
struct
Scsi_Host
*
);
/*
* This is an ugly hack. If we expect to be able to load devices at run time,
* we need to leave extra room in some of the data structures. Doing a
...
...
@@ -643,21 +643,22 @@ extern void scsi_host_failed_inc_and_test(struct Scsi_Host *);
/**
* scsi_find_device - find a device given the host
* @shost: SCSI host pointer
* @channel: SCSI channel (zero if only one channel)
* @pun: SCSI target number (physical unit number)
* @lun: SCSI Logical Unit Number
**/
static
inline
Scsi_Device
*
scsi_find_device
(
struct
Scsi_Host
*
host
,
static
inline
Scsi_Device
*
scsi_find_device
(
struct
Scsi_Host
*
s
host
,
int
channel
,
int
pun
,
int
lun
)
{
Scsi_Device
*
SDpnt
;
Scsi_Device
*
sdev
;
for
(
SDpnt
=
host
->
host_queue
;
SDpnt
!=
NULL
;
SDpnt
=
SDpnt
->
next
)
if
(
SDpnt
->
channel
==
channel
&&
SDpnt
->
id
==
pun
&&
SDpnt
->
lun
==
lun
)
for
(
sdev
=
s
host
->
host_queue
;
sdev
!=
NULL
;
sdev
=
sdev
->
next
)
if
(
sdev
->
channel
==
channel
&&
sdev
->
id
==
pun
&&
sdev
->
lun
==
lun
)
break
;
return
SDpnt
;
return
sdev
;
}
#endif
...
...
drivers/scsi/ips.h
View file @
8428b10d
...
...
@@ -407,7 +407,6 @@
*/
#if LINUX_VERSION_CODE < LinuxVersionCode(2,4,0)
#define IPS { \
next : NULL, \
module : NULL, \
proc_info : NULL, \
proc_dir : NULL, \
...
...
@@ -437,7 +436,6 @@
}
#elif LINUX_VERSION_CODE < LinuxVersionCode(2,5,0)
#define IPS { \
next : NULL, \
module : NULL, \
proc_info : NULL, \
name : NULL, \
...
...
@@ -466,7 +464,6 @@
}
#else
#define IPS { \
next : NULL, \
module : NULL, \
proc_info : NULL, \
name : NULL, \
...
...
drivers/scsi/pcmcia/aha152x_stub.c
View file @
8428b10d
...
...
@@ -294,7 +294,8 @@ static void aha152x_config_cs(dev_link_t *link)
tail
=
&
link
->
dev
;
info
->
ndev
=
0
;
for
(
host
=
scsi_hostlist
;
host
;
host
=
host
->
next
)
for
(
host
=
scsi_host_get_next
(
NULL
);
host
;
host
=
scsi_host_get_next
(
host
))
if
(
host
->
hostt
==
&
driver_template
)
for
(
dev
=
host
->
host_queue
;
dev
;
dev
=
dev
->
next
)
{
u_long
arg
[
2
],
id
;
...
...
drivers/scsi/pcmcia/fdomain_stub.c
View file @
8428b10d
...
...
@@ -258,7 +258,8 @@ static void fdomain_config(dev_link_t *link)
tail
=
&
link
->
dev
;
info
->
ndev
=
0
;
for
(
host
=
scsi_hostlist
;
host
;
host
=
host
->
next
)
for
(
host
=
scsi_host_get_next
(
NULL
);
host
;
host
=
scsi_host_get_next
(
host
))
if
(
host
->
hostt
==
&
driver_template
)
for
(
dev
=
host
->
host_queue
;
dev
;
dev
=
dev
->
next
)
{
u_long
arg
[
2
],
id
;
...
...
drivers/scsi/pcmcia/nsp_cs.c
View file @
8428b10d
...
...
@@ -1520,7 +1520,8 @@ static void nsp_cs_config(dev_link_t *link)
DEBUG
(
0
,
"GET_SCSI_INFO
\n
"
);
tail
=
&
link
->
dev
;
info
->
ndev
=
0
;
for
(
host
=
scsi_hostlist
;
host
!=
NULL
;
host
=
host
->
next
)
{
for
(
host
=
scsi_host_get_next
(
NULL
);
host
;
host
=
scsi_host_get_next
(
host
))
if
(
host
->
hostt
==
&
driver_template
)
{
for
(
dev
=
host
->
host_queue
;
dev
!=
NULL
;
dev
=
dev
->
next
)
{
u_long
arg
[
2
],
id
;
...
...
drivers/scsi/pcmcia/qlogic_stub.c
View file @
8428b10d
...
...
@@ -281,7 +281,8 @@ static void qlogic_config(dev_link_t *link)
tail
=
&
link
->
dev
;
info
->
ndev
=
0
;
for
(
host
=
scsi_hostlist
;
host
;
host
=
host
->
next
)
for
(
host
=
scsi_host_get_next
(
NULL
);
host
;
host
=
scsi_host_get_next
(
host
))
if
(
host
->
hostt
==
&
driver_template
)
for
(
dev
=
host
->
host_queue
;
dev
;
dev
=
dev
->
next
)
{
u_long
arg
[
2
],
id
;
...
...
drivers/scsi/scsi.c
View file @
8428b10d
...
...
@@ -1659,33 +1659,6 @@ void scsi_adjust_queue_depth(Scsi_Device *SDpnt, int tagged, int tags)
}
}
void
__init
scsi_host_no_insert
(
char
*
str
,
int
n
)
{
Scsi_Host_Name
*
shn
,
*
shn2
;
int
len
;
len
=
strlen
(
str
);
if
(
len
&&
(
shn
=
(
Scsi_Host_Name
*
)
kmalloc
(
sizeof
(
Scsi_Host_Name
),
GFP_ATOMIC
)))
{
if
((
shn
->
name
=
kmalloc
(
len
+
1
,
GFP_ATOMIC
)))
{
strncpy
(
shn
->
name
,
str
,
len
);
shn
->
name
[
len
]
=
0
;
shn
->
host_no
=
n
;
shn
->
host_registered
=
0
;
shn
->
next
=
NULL
;
if
(
scsi_host_no_list
)
{
for
(
shn2
=
scsi_host_no_list
;
shn2
->
next
;
shn2
=
shn2
->
next
)
;
shn2
->
next
=
shn
;
}
else
scsi_host_no_list
=
shn
;
max_scsi_hosts
=
n
+
1
;
}
else
kfree
((
char
*
)
shn
);
}
}
#ifdef CONFIG_PROC_FS
static
int
scsi_proc_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
{
...
...
@@ -1698,7 +1671,8 @@ static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
/*
* First, see if there are any attached devices or not.
*/
for
(
HBA_ptr
=
scsi_hostlist
;
HBA_ptr
;
HBA_ptr
=
HBA_ptr
->
next
)
{
for
(
HBA_ptr
=
scsi_host_get_next
(
NULL
);
HBA_ptr
;
HBA_ptr
=
scsi_host_get_next
(
HBA_ptr
))
{
if
(
HBA_ptr
->
host_queue
!=
NULL
)
{
break
;
}
...
...
@@ -1706,7 +1680,8 @@ static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
size
=
sprintf
(
buffer
+
len
,
"Attached devices: %s
\n
"
,
(
HBA_ptr
)
?
""
:
"none"
);
len
+=
size
;
pos
=
begin
+
len
;
for
(
HBA_ptr
=
scsi_hostlist
;
HBA_ptr
;
HBA_ptr
=
HBA_ptr
->
next
)
{
for
(
HBA_ptr
=
scsi_host_get_next
(
NULL
);
HBA_ptr
;
HBA_ptr
=
scsi_host_get_next
(
HBA_ptr
))
{
#if 0
size += sprintf(buffer + len, "scsi%2d: %s\n", (int) HBA_ptr->host_no,
HBA_ptr->hostt->procname);
...
...
@@ -1873,7 +1848,8 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
printk
(
KERN_INFO
"scsi singledevice %d %d %d %d
\n
"
,
host
,
channel
,
id
,
lun
);
for
(
HBA_ptr
=
scsi_hostlist
;
HBA_ptr
;
HBA_ptr
=
HBA_ptr
->
next
)
{
for
(
HBA_ptr
=
scsi_host_get_next
(
NULL
);
HBA_ptr
;
HBA_ptr
=
scsi_host_get_next
(
HBA_ptr
))
{
if
(
HBA_ptr
->
host_no
==
host
)
{
break
;
}
...
...
@@ -1918,7 +1894,8 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
lun
=
simple_strtoul
(
p
+
1
,
&
p
,
0
);
for
(
HBA_ptr
=
scsi_hostlist
;
HBA_ptr
;
HBA_ptr
=
HBA_ptr
->
next
)
{
for
(
HBA_ptr
=
scsi_host_get_next
(
NULL
);
HBA_ptr
;
HBA_ptr
=
scsi_host_get_next
(
HBA_ptr
))
{
if
(
HBA_ptr
->
host_no
==
host
)
{
break
;
}
...
...
@@ -1987,369 +1964,6 @@ static int proc_scsi_gen_write(struct file * file, const char * buf,
}
#endif
/*
* This entry point should be called by a driver if it is trying
* to add a low level scsi driver to the system.
*/
int
scsi_register_host
(
Scsi_Host_Template
*
tpnt
)
{
int
pcount
;
struct
Scsi_Host
*
shpnt
;
Scsi_Device
*
SDpnt
;
struct
Scsi_Device_Template
*
sdtpnt
;
const
char
*
name
;
int
out_of_space
=
0
;
if
(
tpnt
->
next
||
!
tpnt
->
detect
)
return
1
;
/* Must be already loaded, or
* no detect routine available
*/
/* If max_sectors isn't set, default to max */
if
(
!
tpnt
->
max_sectors
)
tpnt
->
max_sectors
=
1024
;
pcount
=
next_scsi_host
;
MOD_INC_USE_COUNT
;
/* The detect routine must carefully spinunlock/spinlock if
it enables interrupts, since all interrupt handlers do
spinlock as well. */
/*
* detect should do its own locking
*/
tpnt
->
present
=
tpnt
->
detect
(
tpnt
);
if
(
tpnt
->
present
)
{
if
(
pcount
==
next_scsi_host
)
{
if
(
tpnt
->
present
>
1
)
{
printk
(
KERN_ERR
"scsi: Failure to register low-level scsi driver"
);
scsi_unregister_host
(
tpnt
);
return
1
;
}
/*
* The low-level driver failed to register a driver.
* We can do this now.
*/
if
(
scsi_register
(
tpnt
,
0
)
==
NULL
)
{
printk
(
KERN_ERR
"scsi: register failed.
\n
"
);
scsi_unregister_host
(
tpnt
);
return
1
;
}
}
tpnt
->
next
=
scsi_hosts
;
/* Add to the linked list */
scsi_hosts
=
tpnt
;
/* Add the new driver to /proc/scsi */
#ifdef CONFIG_PROC_FS
build_proc_dir_entries
(
tpnt
);
#endif
/*
* Add the kernel threads for each host adapter that will
* handle error correction.
*/
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
if
(
shpnt
->
hostt
==
tpnt
)
{
DECLARE_MUTEX_LOCKED
(
sem
);
shpnt
->
eh_notify
=
&
sem
;
kernel_thread
((
int
(
*
)(
void
*
))
scsi_error_handler
,
(
void
*
)
shpnt
,
0
);
/*
* Now wait for the kernel error thread to initialize itself
* as it might be needed when we scan the bus.
*/
down
(
&
sem
);
shpnt
->
eh_notify
=
NULL
;
}
}
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
if
(
shpnt
->
hostt
==
tpnt
)
{
if
(
tpnt
->
info
)
{
name
=
tpnt
->
info
(
shpnt
);
}
else
{
name
=
tpnt
->
name
;
}
printk
(
KERN_INFO
"scsi%d : %s
\n
"
,
/* And print a little message */
shpnt
->
host_no
,
name
);
strncpy
(
shpnt
->
host_driverfs_dev
.
name
,
name
,
DEVICE_NAME_SIZE
-
1
);
sprintf
(
shpnt
->
host_driverfs_dev
.
bus_id
,
"scsi%d"
,
shpnt
->
host_no
);
}
}
/* The next step is to call scan_scsis here. This generates the
* Scsi_Devices entries
*/
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
if
(
shpnt
->
hostt
==
tpnt
)
{
/* first register parent with driverfs */
device_register
(
&
shpnt
->
host_driverfs_dev
);
scan_scsis
(
shpnt
,
0
,
0
,
0
,
0
);
}
}
for
(
sdtpnt
=
scsi_devicelist
;
sdtpnt
;
sdtpnt
=
sdtpnt
->
next
)
{
if
(
sdtpnt
->
init
&&
sdtpnt
->
dev_noticed
)
(
*
sdtpnt
->
init
)
();
}
/*
* Next we create the Scsi_Cmnd structures for this host
*/
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
if
(
SDpnt
->
host
->
hostt
==
tpnt
)
{
for
(
sdtpnt
=
scsi_devicelist
;
sdtpnt
;
sdtpnt
=
sdtpnt
->
next
)
if
(
sdtpnt
->
attach
)
(
*
sdtpnt
->
attach
)
(
SDpnt
);
if
(
SDpnt
->
attached
)
{
scsi_build_commandblocks
(
SDpnt
);
if
(
SDpnt
->
current_queue_depth
==
0
)
out_of_space
=
1
;
}
}
}
/* This does any final handling that is required. */
for
(
sdtpnt
=
scsi_devicelist
;
sdtpnt
;
sdtpnt
=
sdtpnt
->
next
)
{
if
(
sdtpnt
->
finish
&&
sdtpnt
->
nr_dev
)
{
(
*
sdtpnt
->
finish
)
();
}
}
}
if
(
out_of_space
)
{
scsi_unregister_host
(
tpnt
);
/* easiest way to clean up?? */
return
1
;
}
else
return
0
;
}
/*
* Similarly, this entry point should be called by a loadable module if it
* is trying to remove a low level scsi driver from the system.
*/
int
scsi_unregister_host
(
Scsi_Host_Template
*
tpnt
)
{
int
online_status
;
int
pcount0
,
pcount
;
Scsi_Cmnd
*
SCpnt
;
Scsi_Device
*
SDpnt
;
Scsi_Device
*
SDpnt1
;
struct
Scsi_Device_Template
*
sdtpnt
;
struct
Scsi_Host
*
sh1
;
struct
Scsi_Host
*
shpnt
;
char
name
[
10
];
/* host_no>=10^9? I don't think so. */
/* get the big kernel lock, so we don't race with open() */
lock_kernel
();
/*
* First verify that this host adapter is completely free with no pending
* commands
*/
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
{
if
(
SDpnt
->
host
->
hostt
==
tpnt
&&
SDpnt
->
host
->
hostt
->
module
&&
GET_USE_COUNT
(
SDpnt
->
host
->
hostt
->
module
))
goto
err_out
;
/*
* FIXME(eric) - We need to find a way to notify the
* low level driver that we are shutting down - via the
* special device entry that still needs to get added.
*
* Is detach interface below good enough for this?
*/
}
}
/*
* FIXME(eric) put a spinlock on this. We force all of the devices offline
* to help prevent race conditions where other hosts/processors could try and
* get in and queue a command.
*/
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
{
if
(
SDpnt
->
host
->
hostt
==
tpnt
)
SDpnt
->
online
=
FALSE
;
}
}
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
if
(
shpnt
->
hostt
!=
tpnt
)
{
continue
;
}
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
{
/*
* Loop over all of the commands associated with the device. If any of
* them are busy, then set the state back to inactive and bail.
*/
for
(
SCpnt
=
SDpnt
->
device_queue
;
SCpnt
;
SCpnt
=
SCpnt
->
next
)
{
online_status
=
SDpnt
->
online
;
SDpnt
->
online
=
FALSE
;
if
(
SCpnt
->
request
&&
SCpnt
->
request
->
rq_status
!=
RQ_INACTIVE
)
{
printk
(
KERN_ERR
"SCSI device not inactive - rq_status=%d, target=%d, pid=%ld, state=%d, owner=%d.
\n
"
,
SCpnt
->
request
->
rq_status
,
SCpnt
->
target
,
SCpnt
->
pid
,
SCpnt
->
state
,
SCpnt
->
owner
);
for
(
SDpnt1
=
shpnt
->
host_queue
;
SDpnt1
;
SDpnt1
=
SDpnt1
->
next
)
{
for
(
SCpnt
=
SDpnt1
->
device_queue
;
SCpnt
;
SCpnt
=
SCpnt
->
next
)
if
(
SCpnt
->
request
->
rq_status
==
RQ_SCSI_DISCONNECTING
)
SCpnt
->
request
->
rq_status
=
RQ_INACTIVE
;
}
SDpnt
->
online
=
online_status
;
printk
(
KERN_ERR
"Device busy???
\n
"
);
goto
err_out
;
}
/*
* No, this device is really free. Mark it as such, and
* continue on.
*/
SCpnt
->
state
=
SCSI_STATE_DISCONNECTING
;
if
(
SCpnt
->
request
)
SCpnt
->
request
->
rq_status
=
RQ_SCSI_DISCONNECTING
;
/* Mark as busy */
}
}
}
/* Next we detach the high level drivers from the Scsi_Device structures */
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
if
(
shpnt
->
hostt
!=
tpnt
)
{
continue
;
}
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
{
for
(
sdtpnt
=
scsi_devicelist
;
sdtpnt
;
sdtpnt
=
sdtpnt
->
next
)
if
(
sdtpnt
->
detach
)
(
*
sdtpnt
->
detach
)
(
SDpnt
);
/* If something still attached, punt */
if
(
SDpnt
->
attached
)
{
printk
(
KERN_ERR
"Attached usage count = %d
\n
"
,
SDpnt
->
attached
);
goto
err_out
;
}
if
(
shpnt
->
hostt
->
slave_detach
)
(
*
shpnt
->
hostt
->
slave_detach
)
(
SDpnt
);
devfs_unregister
(
SDpnt
->
de
);
put_device
(
&
SDpnt
->
sdev_driverfs_dev
);
}
}
/*
* Next, kill the kernel error recovery thread for this host.
*/
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
if
(
shpnt
->
hostt
==
tpnt
&&
shpnt
->
ehandler
!=
NULL
)
{
DECLARE_MUTEX_LOCKED
(
sem
);
shpnt
->
eh_notify
=
&
sem
;
send_sig
(
SIGHUP
,
shpnt
->
ehandler
,
1
);
down
(
&
sem
);
shpnt
->
eh_notify
=
NULL
;
}
}
/* Next we free up the Scsi_Cmnd structures for this host */
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
if
(
shpnt
->
hostt
!=
tpnt
)
{
continue
;
}
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
shpnt
->
host_queue
)
{
scsi_release_commandblocks
(
SDpnt
);
blk_cleanup_queue
(
&
SDpnt
->
request_queue
);
/* Next free up the Scsi_Device structures for this host */
shpnt
->
host_queue
=
SDpnt
->
next
;
if
(
SDpnt
->
inquiry
)
kfree
(
SDpnt
->
inquiry
);
kfree
((
char
*
)
SDpnt
);
}
}
/* Next we go through and remove the instances of the individual hosts
* that were detected */
pcount0
=
next_scsi_host
;
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
sh1
)
{
sh1
=
shpnt
->
next
;
if
(
shpnt
->
hostt
!=
tpnt
)
continue
;
pcount
=
next_scsi_host
;
/* Remove the /proc/scsi directory entry */
sprintf
(
name
,
"%d"
,
shpnt
->
host_no
);
remove_proc_entry
(
name
,
tpnt
->
proc_dir
);
put_device
(
&
shpnt
->
host_driverfs_dev
);
if
(
tpnt
->
release
)
(
*
tpnt
->
release
)
(
shpnt
);
else
{
/* This is the default case for the release function.
* It should do the right thing for most correctly
* written host adapters.
*/
if
(
shpnt
->
irq
)
free_irq
(
shpnt
->
irq
,
NULL
);
if
(
shpnt
->
dma_channel
!=
0xff
)
free_dma
(
shpnt
->
dma_channel
);
if
(
shpnt
->
io_port
&&
shpnt
->
n_io_port
)
release_region
(
shpnt
->
io_port
,
shpnt
->
n_io_port
);
}
if
(
pcount
==
next_scsi_host
)
scsi_unregister
(
shpnt
);
tpnt
->
present
--
;
}
if
(
pcount0
!=
next_scsi_host
)
printk
(
KERN_INFO
"scsi : %d host%s left.
\n
"
,
next_scsi_host
,
(
next_scsi_host
==
1
)
?
""
:
"s"
);
/*
* Remove it from the linked list and /proc if all
* hosts were successfully removed (ie preset == 0)
*/
if
(
!
tpnt
->
present
)
{
Scsi_Host_Template
**
SHTp
=
&
scsi_hosts
;
Scsi_Host_Template
*
SHT
;
while
((
SHT
=
*
SHTp
)
!=
NULL
)
{
if
(
SHT
==
tpnt
)
{
*
SHTp
=
SHT
->
next
;
remove_proc_entry
(
tpnt
->
proc_name
,
proc_scsi
);
break
;
}
SHTp
=
&
SHT
->
next
;
}
}
MOD_DEC_USE_COUNT
;
unlock_kernel
();
return
0
;
err_out:
unlock_kernel
();
return
-
1
;
}
/*
* This entry point should be called by a loadable module if it is trying
* add a high level scsi driver to the system.
...
...
@@ -2361,7 +1975,7 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
int
out_of_space
=
0
;
#ifdef CONFIG_KMOD
if
(
scsi_host
s
==
NULL
)
if
(
scsi_host
_get_next
(
NULL
)
==
NULL
)
request_module
(
"scsi_hostadapter"
);
#endif
...
...
@@ -2375,7 +1989,8 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
* First scan the devices that we know about, and see if we notice them.
*/
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
for
(
shpnt
=
scsi_host_get_next
(
NULL
);
shpnt
;
shpnt
=
scsi_host_get_next
(
shpnt
))
{
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
{
if
(
tpnt
->
detect
)
...
...
@@ -2394,7 +2009,8 @@ int scsi_register_device(struct Scsi_Device_Template *tpnt)
/*
* Now actually connect the devices to the new driver.
*/
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
for
(
shpnt
=
scsi_host_get_next
(
NULL
);
shpnt
;
shpnt
=
scsi_host_get_next
(
shpnt
))
{
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
{
if
(
tpnt
->
attach
)
...
...
@@ -2444,7 +2060,8 @@ int scsi_unregister_device(struct Scsi_Device_Template *tpnt)
* Next, detach the devices from the driver.
*/
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
for
(
shpnt
=
scsi_host_get_next
(
NULL
);
shpnt
;
shpnt
=
scsi_host_get_next
(
shpnt
))
{
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
{
if
(
tpnt
->
detach
)
...
...
@@ -2516,7 +2133,8 @@ static void scsi_dump_status(int level)
Scsi_Device
*
SDpnt
;
printk
(
KERN_INFO
"Dump of scsi host parameters:
\n
"
);
i
=
0
;
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
for
(
shpnt
=
scsi_host_get_next
(
NULL
);
shpnt
;
shpnt
=
scsi_host_get_next
(
shpnt
))
{
printk
(
KERN_INFO
" %d %d %d : %d %d
\n
"
,
shpnt
->
host_failed
,
shpnt
->
host_busy
,
...
...
@@ -2527,7 +2145,8 @@ static void scsi_dump_status(int level)
printk
(
KERN_INFO
"
\n\n
"
);
printk
(
KERN_INFO
"Dump of scsi command parameters:
\n
"
);
for
(
shpnt
=
scsi_hostlist
;
shpnt
;
shpnt
=
shpnt
->
next
)
{
for
(
shpnt
=
scsi_host_get_next
(
NULL
);
shpnt
;
shpnt
=
scsi_host_get_next
(
shpnt
))
{
printk
(
KERN_INFO
"h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result
\n
"
);
for
(
SDpnt
=
shpnt
->
host_queue
;
SDpnt
;
SDpnt
=
SDpnt
->
next
)
{
for
(
SCpnt
=
SDpnt
->
device_queue
;
SCpnt
;
SCpnt
=
SCpnt
->
next
)
{
...
...
@@ -2565,26 +2184,6 @@ static void scsi_dump_status(int level)
}
#endif
/* CONFIG_PROC_FS */
static
int
__init
scsi_host_no_init
(
char
*
str
)
{
static
int
next_no
=
0
;
char
*
temp
;
while
(
str
)
{
temp
=
str
;
while
(
*
temp
&&
(
*
temp
!=
':'
)
&&
(
*
temp
!=
','
))
temp
++
;
if
(
!*
temp
)
temp
=
NULL
;
else
*
temp
++
=
0
;
scsi_host_no_insert
(
str
,
next_no
);
str
=
temp
;
next_no
++
;
}
return
1
;
}
static
char
*
scsihosts
;
MODULE_PARM
(
scsihosts
,
"s"
);
...
...
@@ -2724,9 +2323,8 @@ static int __init init_scsi(void)
#endif
scsi_devfs_handle
=
devfs_mk_dir
(
NULL
,
"scsi"
,
NULL
);
if
(
scsihosts
)
printk
(
KERN_INFO
"scsi: host order: %s
\n
"
,
scsihosts
);
scsi_host_no_init
(
scsihosts
);
scsi_host_hn_init
(
scsihosts
);
bus_register
(
&
scsi_driverfs_bus_type
);
...
...
@@ -2738,19 +2336,11 @@ static int __init init_scsi(void)
static
void
__exit
exit_scsi
(
void
)
{
Scsi_Host_Name
*
shn
,
*
shn2
=
NULL
;
int
i
;
devfs_unregister
(
scsi_devfs_handle
);
for
(
shn
=
scsi_host_no_list
;
shn
;
shn
=
shn
->
next
)
{
if
(
shn
->
name
)
kfree
(
shn
->
name
);
if
(
shn2
)
kfree
(
shn2
);
shn2
=
shn
;
}
if
(
shn2
)
kfree
(
shn2
);
scsi_host_hn_release
();
#ifdef CONFIG_PROC_FS
/* No, we're not here anymore. Don't show the /proc/scsi files. */
...
...
drivers/scsi/scsi_proc.c
View file @
8428b10d
...
...
@@ -119,35 +119,44 @@ static int proc_scsi_write(struct file * file, const char * buf,
return
(
ret
);
}
void
build_proc_dir_entries
(
Scsi_Host_Template
*
tpnt
)
void
scsi_proc_host_mkdir
(
Scsi_Host_Template
*
shost_tp
)
{
struct
Scsi_Host
*
hpnt
;
char
name
[
10
];
/* see scsi_unregister_host() */
tpnt
->
proc_dir
=
proc_mkdir
(
tpnt
->
proc_name
,
proc_scsi
);
if
(
!
tpnt
->
proc_dir
)
{
printk
(
KERN_ERR
"Unable to proc_mkdir in scsi.c/build_proc_dir_entries"
);
shost_tp
->
proc_dir
=
proc_mkdir
(
shost_tp
->
proc_name
,
proc_scsi
);
if
(
!
shost_tp
->
proc_dir
)
{
printk
(
KERN_ERR
"%s: proc_mkdir failed for %s
\n
"
,
__FUNCTION__
,
shost_tp
->
proc_name
);
return
;
}
tpnt
->
proc_dir
->
owner
=
tpnt
->
module
;
shost_tp
->
proc_dir
->
owner
=
shost_tp
->
module
;
}
hpnt
=
scsi_hostlist
;
while
(
hpnt
)
{
if
(
tpnt
==
hpnt
->
hostt
)
{
void
scsi_proc_host_add
(
struct
Scsi_Host
*
shost
)
{
char
name
[
10
];
struct
proc_dir_entry
*
p
;
sprintf
(
name
,
"%d"
,
hpnt
->
host_no
);
sprintf
(
name
,
"%d"
,
shost
->
host_no
);
p
=
create_proc_read_entry
(
name
,
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
tpn
t
->
proc_dir
,
shost
->
host
t
->
proc_dir
,
proc_scsi_read
,
(
void
*
)
hpnt
);
if
(
!
p
)
panic
(
"Not enough memory to register SCSI HBA in /proc/scsi !
\n
"
);
(
void
*
)
shost
);
if
(
!
p
)
{
printk
(
KERN_ERR
"%s: Failed to register host %d in"
"%s
\n
"
,
__FUNCTION__
,
shost
->
host_no
,
shost
->
hostt
->
proc_name
);
}
else
{
p
->
write_proc
=
proc_scsi_write
;
p
->
owner
=
tpnt
->
module
;
}
hpnt
=
hpnt
->
next
;
p
->
owner
=
shost
->
hostt
->
module
;
}
}
void
scsi_proc_host_rm
(
struct
Scsi_Host
*
shost
)
{
char
name
[
10
];
sprintf
(
name
,
"%d"
,
shost
->
host_no
);
remove_proc_entry
(
name
,
shost
->
hostt
->
proc_dir
);
}
/*
...
...
drivers/scsi/scsi_syms.c
View file @
8428b10d
...
...
@@ -91,8 +91,9 @@ EXPORT_SYMBOL(scsi_reset_provider);
/*
* These are here only while I debug the rest of the scsi stuff.
*/
EXPORT_SYMBOL
(
scsi_hostlist
);
EXPORT_SYMBOL
(
scsi_hosts
);
EXPORT_SYMBOL
(
scsi_host_get_next
);
EXPORT_SYMBOL
(
scsi_host_hn_get
);
EXPORT_SYMBOL
(
scsi_host_put
);
EXPORT_SYMBOL
(
scsi_devicelist
);
EXPORT_SYMBOL
(
scsi_device_types
);
...
...
drivers/scsi/sg.c
View file @
8428b10d
...
...
@@ -3103,7 +3103,8 @@ sg_proc_host_info(char *buffer, int *len, off_t * begin, off_t offset, int size)
struct
Scsi_Host
*
shp
;
int
k
;
for
(
k
=
0
,
shp
=
scsi_hostlist
;
shp
;
shp
=
shp
->
next
,
++
k
)
{
for
(
k
=
0
,
shp
=
scsi_host_get_next
(
NULL
);
shp
;
shp
=
scsi_host_get_next
(
shp
),
++
k
)
{
for
(;
k
<
shp
->
host_no
;
++
k
)
PRINT_PROC
(
"-1
\t
-1
\t
-1
\t
-1
\t
-1
\t
-1
\n
"
);
PRINT_PROC
(
"%u
\t
%hu
\t
%hd
\t
%hu
\t
%d
\t
%d
\n
"
,
...
...
@@ -3147,7 +3148,8 @@ sg_proc_hoststrs_info(char *buffer, int *len, off_t * begin,
char
buff
[
SG_MAX_HOST_STR_LEN
];
char
*
cp
;
for
(
k
=
0
,
shp
=
scsi_hostlist
;
shp
;
shp
=
shp
->
next
,
++
k
)
{
for
(
k
=
0
,
shp
=
scsi_host_get_next
(
NULL
);
shp
;
shp
=
scsi_host_get_next
(
shp
),
++
k
)
{
for
(;
k
<
shp
->
host_no
;
++
k
)
PRINT_PROC
(
"<no active host>
\n
"
);
strncpy
(
buff
,
shp
->
hostt
->
info
?
shp
->
hostt
->
info
(
shp
)
:
...
...
drivers/scsi/wd33c93.c
View file @
8428b10d
...
...
@@ -1871,10 +1871,7 @@ Scsi_Cmnd *cmd;
int
x
,
i
;
static
int
stop
=
0
;
for
(
instance
=
scsi_hostlist
;
instance
;
instance
=
instance
->
next
)
{
if
(
instance
->
host_no
==
hn
)
break
;
}
instance
=
scsi_host_hn_get
(
hn
);
if
(
!
instance
)
{
printk
(
"*** Hmm... Can't find host #%d!
\n
"
,
hn
);
return
(
-
ESRCH
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment