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
Kirill Smelkov
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
Hide 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
);
Scsi_Host_Template
*
scsi_hosts
;
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
);
/*
* Our semaphores and timeout counters, where size depends on
* MAX_SCSI_HOSTS here.
*/
return
0
;
}
Scsi_Host_Name
*
scsi_host_no_list
;
struct
Scsi_Host
*
scsi_hostlist
;
struct
Scsi_Device_Template
*
scsi_devicelist
;
/**
* 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
;
/*
* 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 */
}
}
int
max_scsi_hosts
;
int
next_scsi_host
;
void
scsi_unregister
(
struct
Scsi_Host
*
sh
){
struct
Scsi_Host
*
shpnt
;
Scsi_Host_Name
*
shn
;
if
(
scsi_hostlist
==
sh
)
scsi_hostlist
=
sh
->
next
;
else
{
shpnt
=
scsi_hostlist
;
while
(
shpnt
->
next
!=
sh
)
shpnt
=
shpnt
->
next
;
shpnt
->
next
=
shpnt
->
next
->
next
;
}
/*
* 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).
*/
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
;
/*
* 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
;
}
if
(
shost
->
hostt
->
slave_detach
)
(
*
shost
->
hostt
->
slave_detach
)
(
sdev
);
devfs_unregister
(
sdev
->
de
);
device_unregister
(
&
sdev
->
sdev_driverfs_dev
);
}
/* 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
);
}
/* Remove the instance of the individual hosts */
pcount
=
scsi_hosts_registered
;
if
(
shost
->
hostt
->
release
)
(
*
shost
->
hostt
->
release
)
(
shost
);
else
{
scsi_host_generic_release
(
shost
);
}
}
next_scsi_host
--
;
kfree
((
char
*
)
sh
);
if
(
pcount
==
scsi_hosts_registered
)
scsi_unregister
(
shost
);
return
0
;
}
/* 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_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
;
}
/*
* Next, kill the kernel error recovery thread for this host.
*/
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
;
}
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
;
}
/**
* 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
;
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
"
);
return
NULL
;
}
memset
(
retval
,
0
,
sizeof
(
struct
Scsi_Host
)
+
j
);
/* trying to find a reserved entry (host_no) */
hname
=
(
tpnt
->
proc_name
)
?
tpnt
->
proc_name
:
""
;
hname_len
=
strlen
(
hname
);
for
(
shn
=
scsi_host_no_list
;
shn
;
shn
=
shn
->
next
)
{
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
;
break
;
struct
Scsi_Host
*
shost
,
*
shost_scr
;
Scsi_Host_Name
*
shost_name
=
NULL
;
Scsi_Host_Name
*
shn
=
NULL
;
char
*
hname
;
size_t
hname_len
;
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
;
}
}
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
"
);
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
;
memset
(
shost
,
0
,
sizeof
(
struct
Scsi_Host
)
+
xtr_bytes
);
/*
* Determine host number. Check reserved first before allocating
* new one
*/
hname
=
(
shost_tp
->
proc_name
)
?
shost_tp
->
proc_name
:
""
;
hname_len
=
strlen
(
hname
);
if
(
hname_len
)
list_for_each
(
lh
,
&
scsi_host_hn_list
)
{
shn
=
list_entry
(
lh
,
Scsi_Host_Name
,
shn_list
);
if
(
!
(
shn
->
host_registered
)
&&
!
strncmp
(
hname
,
shn
->
name
,
hname_len
))
{
shost_name
=
shn
;
break
;
}
}
if
(
!
shost_name
)
{
shost_name
=
scsi_host_hn_add
(
hname
);
if
(
!
shost_name
)
{
kfree
(
shost
);
return
NULL
;
}
}
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
;
/* These three are default values which can be overridden */
retval
->
max_channel
=
0
;
retval
->
max_id
=
8
;
retval
->
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.
*/
retval
->
max_cmd_len
=
12
;
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. */
retval
->
max_host_blocked
=
tpnt
->
max_host_blocked
?
tpnt
->
max_host_blocked
:
SCSI_DEFAULT_HOST_BLOCKED
;
retval
->
host_blocked
=
0
;
retval
->
host_self_blocked
=
FALSE
;
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 */
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.
*/
shost
->
max_cmd_len
=
12
;
shost
->
hostt
=
shost_tp
;
shost
->
host_blocked
=
FALSE
;
shost
->
host_self_blocked
=
FALSE
;
#ifdef DEBUG
printk
(
"Register %x %x: %d
\n
"
,
(
int
)
retval
,
(
int
)
retval
->
hostt
,
j
);
printk
(
"%s: %x %x: %d
\n
"
,
__FUNCTION_
(
int
)
shost
,
(
int
)
shost
->
hostt
,
xtr_bytes
);
#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
;
retval
->
max_sectors
=
tpnt
->
max_sectors
;
retval
->
use_blk_tcq
=
tpnt
->
use_blk_tcq
;
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
;
/*
* 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
;
shost
->
max_sectors
=
shost_tp
->
max_sectors
;
shost
->
use_blk_tcq
=
shost_tp
->
use_blk_tcq
;
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
;
}
}
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
;
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
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
);
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
;
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
;
}
/*
* 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
);
}
}
for
(
sdev_tp
=
scsi_devicelist
;
sdev_tp
;
sdev_tp
=
sdev_tp
->
next
)
{
if
(
sdev_tp
->
init
&&
sdev_tp
->
dev_noticed
)
(
*
sdev_tp
->
init
)
();
}
/*
* 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
)
();
}
}
}
if
(
!
shpnt
)
o_shp
->
next
=
retval
;
}
}
return
retval
;
}
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
;
unsigned
short
host_no
;
unsigned
short
host_registered
;
}
Scsi_Host_Name
;
{
struct
list_head
shn_lis
t
;
char
*
name
;
unsigned
short
host_no
;
unsigned
short
host_registered
;
}
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
;
hpnt
=
scsi_hostlist
;
while
(
hpnt
)
{
if
(
tpnt
==
hpnt
->
hostt
)
{
struct
proc_dir_entry
*
p
;
sprintf
(
name
,
"%d"
,
hpnt
->
host_no
);
p
=
create_proc_read_entry
(
name
,
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
tpnt
->
proc_dir
,
proc_scsi_read
,
(
void
*
)
hpnt
);
if
(
!
p
)
panic
(
"Not enough memory to register SCSI HBA in /proc/scsi !
\n
"
);
p
->
write_proc
=
proc_scsi_write
;
p
->
owner
=
tpnt
->
module
;
}
hpnt
=
hpnt
->
next
;
shost_tp
->
proc_dir
->
owner
=
shost_tp
->
module
;
}
void
scsi_proc_host_add
(
struct
Scsi_Host
*
shost
)
{
char
name
[
10
];
struct
proc_dir_entry
*
p
;
sprintf
(
name
,
"%d"
,
shost
->
host_no
);
p
=
create_proc_read_entry
(
name
,
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
shost
->
hostt
->
proc_dir
,
proc_scsi_read
,
(
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
=
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