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
5237662f
Commit
5237662f
authored
Nov 20, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linux-scsi.bkbits.net/scsi-bugfixes-2.6
into home.osdl.org:/home/torvalds/v2.5/linux
parents
03f78a19
d177ca18
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
305 additions
and
236 deletions
+305
-236
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.c
+7
-2
drivers/scsi/53c700.c
drivers/scsi/53c700.c
+2
-2
drivers/scsi/NCR53C9x.c
drivers/scsi/NCR53C9x.c
+13
-15
drivers/scsi/arm/acornscsi.c
drivers/scsi/arm/acornscsi.c
+4
-2
drivers/scsi/esp.c
drivers/scsi/esp.c
+18
-19
drivers/scsi/fcal.c
drivers/scsi/fcal.c
+1
-1
drivers/scsi/hosts.c
drivers/scsi/hosts.c
+16
-21
drivers/scsi/hosts.h
drivers/scsi/hosts.h
+1
-48
drivers/scsi/lasi700.c
drivers/scsi/lasi700.c
+2
-1
drivers/scsi/scsi.c
drivers/scsi/scsi.c
+103
-28
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_lib.c
+24
-18
drivers/scsi/scsi_proc.c
drivers/scsi/scsi_proc.c
+7
-9
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_scan.c
+32
-20
drivers/scsi/scsi_syms.c
drivers/scsi/scsi_syms.c
+4
-5
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_sysfs.c
+7
-24
drivers/scsi/sg.c
drivers/scsi/sg.c
+4
-3
drivers/scsi/sim710.c
drivers/scsi/sim710.c
+1
-0
drivers/scsi/st.c
drivers/scsi/st.c
+1
-1
include/scsi/scsi_device.h
include/scsi/scsi_device.h
+42
-7
include/scsi/scsi_driver.h
include/scsi/scsi_driver.h
+1
-0
include/scsi/scsi_host.h
include/scsi/scsi_host.h
+15
-10
No files found.
drivers/ieee1394/sbp2.c
View file @
5237662f
...
...
@@ -991,7 +991,7 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
static
void
sbp2_remove_device
(
struct
scsi_id_instance_data
*
scsi_id
)
{
struct
sbp2scsi_host_info
*
hi
=
scsi_id
->
hi
;
struct
scsi_device
*
sdev
=
scsi_find_device
(
hi
->
scsi_host
,
0
,
scsi_id
->
id
,
0
)
;
struct
scsi_device
*
sdev
;
SBP2_DEBUG
(
"sbp2_remove_device"
);
...
...
@@ -999,8 +999,13 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
sbp2scsi_complete_all_commands
(
scsi_id
,
DID_NO_CONNECT
);
/* Remove it from the scsi layer now */
if
(
sdev
)
/* XXX(hch): why can't we simply cache the scsi_device
in struct scsi_id_instance_data? */
sdev
=
scsi_device_lookup
(
hi
->
scsi_host
,
0
,
scsi_id
->
id
,
0
);
if
(
sdev
)
{
scsi_remove_device
(
sdev
);
scsi_device_put
(
sdev
);
}
sbp2util_remove_command_orb_pool
(
scsi_id
);
...
...
drivers/scsi/53c700.c
View file @
5237662f
...
...
@@ -1065,7 +1065,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, Scsi_Cmnd *SCp,
DEBUG
((
"scsi%d: (%d:%d) RESELECTED!
\n
"
,
host
->
host_no
,
reselection_id
,
lun
));
/* clear the reselection indicator */
SDp
=
scsi_find_device
(
host
,
0
,
reselection_id
,
lun
);
SDp
=
__scsi_device_lookup
(
host
,
0
,
reselection_id
,
lun
);
if
(
unlikely
(
SDp
==
NULL
))
{
printk
(
KERN_ERR
"scsi%d: (%d:%d) HAS NO device
\n
"
,
host
->
host_no
,
reselection_id
,
lun
);
...
...
@@ -1498,7 +1498,7 @@ NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs)
host
->
host_no
,
SCp
,
SCp
==
NULL
?
NULL
:
SCp
->
host_scribble
,
dsp
,
dsp
-
hostdata
->
pScript
);
/* clear all the negotiated parameters */
list_for_each_entry
(
SDp
,
&
host
->
my_devices
,
siblings
)
__shost_for_each_device
(
SDp
,
host
)
SDp
->
hostdata
=
0
;
/* clear all the slots and their pending commands */
...
...
drivers/scsi/NCR53C9x.c
View file @
5237662f
...
...
@@ -815,6 +815,7 @@ static int copy_info(struct info_str *info, char *fmt, ...)
static
int
esp_host_info
(
struct
NCR_ESP
*
esp
,
char
*
ptr
,
off_t
offset
,
int
len
)
{
struct
scsi_device
*
sdev
;
struct
info_str
info
;
int
i
;
...
...
@@ -867,23 +868,20 @@ static int esp_host_info(struct NCR_ESP *esp, char *ptr, off_t offset, int len)
/* Now describe the state of each existing target. */
copy_info
(
&
info
,
"Target #
\t
config3
\t\t
Sync Capabilities
\t
Disconnect
\n
"
);
for
(
i
=
0
;
i
<
15
;
i
++
)
{
if
(
esp
->
targets_present
&
(
1
<<
i
))
{
Scsi_Device
*
SDptr
;
struct
esp_device
*
esp_dev
;
list_for_each_entry
(
SDptr
,
&
esp
->
ehost
->
my_devices
,
siblings
)
if
(
SDptr
->
id
==
i
)
break
;
shost_for_each_device
(
sdev
,
esp
->
ehost
)
{
struct
esp_device
*
esp_dev
=
sdev
->
hostdata
;
uint
id
=
sdev
->
id
;
esp_dev
=
SDptr
->
hostdata
;
copy_info
(
&
info
,
"%d
\t\t
"
,
i
);
copy_info
(
&
info
,
"%08lx
\t
"
,
esp
->
config3
[
i
]);
copy_info
(
&
info
,
"[%02lx,%02lx]
\t\t\t
"
,
esp_dev
->
sync_max_offset
,
esp_dev
->
sync_min_period
);
copy_info
(
&
info
,
"%s
\n
"
,
esp_dev
->
disconnect
?
"yes"
:
"no"
);
}
if
(
!
(
esp
->
targets_present
&
(
1
<<
id
)))
continue
;
copy_info
(
&
info
,
"%d
\t\t
"
,
id
);
copy_info
(
&
info
,
"%08lx
\t
"
,
esp
->
config3
[
id
]);
copy_info
(
&
info
,
"[%02lx,%02lx]
\t\t\t
"
,
esp_dev
->
sync_max_offset
,
esp_dev
->
sync_min_period
);
copy_info
(
&
info
,
"%s
\n
"
,
esp_dev
->
disconnect
?
"yes"
:
"no"
);
}
return
info
.
pos
>
info
.
offset
?
info
.
pos
-
info
.
offset
:
0
;
...
...
drivers/scsi/arm/acornscsi.c
View file @
5237662f
...
...
@@ -2930,7 +2930,7 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
p
+=
sprintf
(
p
,
"
\n
Attached devices:
\n
"
);
list_for_each_entry
(
scd
,
&
instance
->
my_devices
,
siblings
)
{
shost_for_each_device
(
scd
,
instance
)
{
p
+=
sprintf
(
p
,
"Device/Lun TaggedQ Sync
\n
"
);
p
+=
sprintf
(
p
,
" %d/%d "
,
scd
->
id
,
scd
->
lun
);
if
(
scd
->
tagged_supported
)
...
...
@@ -2953,8 +2953,10 @@ int acornscsi_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
p
=
buffer
;
}
pos
=
p
-
buffer
;
if
(
pos
+
begin
>
offset
+
length
)
if
(
pos
+
begin
>
offset
+
length
)
{
scsi_device_put
(
scd
);
break
;
}
}
pos
=
p
-
buffer
;
...
...
drivers/scsi/esp.c
View file @
5237662f
...
...
@@ -1309,6 +1309,7 @@ static int copy_info(struct info_str *info, char *fmt, ...)
static
int
esp_host_info
(
struct
esp
*
esp
,
char
*
ptr
,
off_t
offset
,
int
len
)
{
struct
scsi_device
*
sdev
;
struct
info_str
info
;
int
i
;
...
...
@@ -1384,25 +1385,23 @@ static int esp_host_info(struct esp *esp, char *ptr, off_t offset, int len)
/* Now describe the state of each existing target. */
copy_info
(
&
info
,
"Target #
\t
config3
\t\t
Sync Capabilities
\t
Disconnect
\t
Wide
\n
"
);
for
(
i
=
0
;
i
<
15
;
i
++
)
{
if
(
esp
->
targets_present
&
(
1
<<
i
))
{
Scsi_Device
*
SDptr
;
struct
esp_device
*
esp_dev
;
list_for_each_entry
(
SDptr
,
&
esp
->
ehost
->
my_devices
,
siblings
)
if
(
SDptr
->
id
==
i
)
break
;
esp_dev
=
SDptr
->
hostdata
;
copy_info
(
&
info
,
"%d
\t\t
"
,
i
);
copy_info
(
&
info
,
"%08lx
\t
"
,
esp
->
config3
[
i
]);
copy_info
(
&
info
,
"[%02lx,%02lx]
\t\t\t
"
,
esp_dev
->
sync_max_offset
,
esp_dev
->
sync_min_period
);
copy_info
(
&
info
,
"%s
\t\t
"
,
esp_dev
->
disconnect
?
"yes"
:
"no"
);
copy_info
(
&
info
,
"%s
\n
"
,
(
esp
->
config3
[
i
]
&
ESP_CONFIG3_EWIDE
)
?
"yes"
:
"no"
);
}
shost_for_each_device
(
sdev
,
esp
->
ehost
)
{
struct
esp_device
*
esp_dev
=
sdev
->
hostdata
;
uint
id
=
sdev
->
id
;
if
(
!
(
esp
->
targets_present
&
(
1
<<
id
)))
continue
;
copy_info
(
&
info
,
"%d
\t\t
"
,
id
);
copy_info
(
&
info
,
"%08lx
\t
"
,
esp
->
config3
[
id
]);
copy_info
(
&
info
,
"[%02lx,%02lx]
\t\t\t
"
,
esp_dev
->
sync_max_offset
,
esp_dev
->
sync_min_period
);
copy_info
(
&
info
,
"%s
\t\t
"
,
esp_dev
->
disconnect
?
"yes"
:
"no"
);
copy_info
(
&
info
,
"%s
\n
"
,
(
esp
->
config3
[
id
]
&
ESP_CONFIG3_EWIDE
)
?
"yes"
:
"no"
);
}
return
info
.
pos
>
info
.
offset
?
info
.
pos
-
info
.
offset
:
0
;
}
...
...
drivers/scsi/fcal.c
View file @
5237662f
...
...
@@ -228,7 +228,7 @@ int fcal_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t of
#endif
SPRINTF
(
"Initiator AL-PA: %02x
\n
"
,
fc
->
sid
);
SPRINTF
(
"
\n
Attached devices:
%s
\n
"
,
!
list_empty
(
&
host
->
my_devices
)
?
""
:
"none
"
);
SPRINTF
(
"
\n
Attached devices:
\n
"
);
for
(
i
=
0
;
i
<
fc
->
posmap
->
len
;
i
++
)
{
unsigned
char
alpa
=
fc
->
posmap
->
list
[
i
];
...
...
drivers/scsi/hosts.c
View file @
5237662f
/*
* hosts.c Copyright (C) 1992 Drew Eckhardt
* Copyright (C) 1993, 1994, 1995 Eric Youngdale
* Copyright (C) 2002-2003 Christoph Hellwig
*
* mid to lowlevel SCSI driver interface
* Initial versions: Drew Eckhardt
...
...
@@ -30,8 +31,8 @@
#include <linux/completion.h>
#include <linux/unistd.h>
#include <scsi/scsi_host.h>
#include "scsi.h"
#include "hosts.h"
#include "scsi_priv.h"
#include "scsi_logging.h"
...
...
@@ -50,6 +51,11 @@ static struct class shost_class = {
.
release
=
scsi_host_cls_release
,
};
static
int
scsi_device_cancel_cb
(
struct
device
*
dev
,
void
*
data
)
{
return
scsi_device_cancel
(
to_scsi_device
(
dev
),
*
(
int
*
)
data
);
}
/**
* scsi_host_cancel - cancel outstanding IO to this host
* @shost: pointer to struct Scsi_Host
...
...
@@ -57,11 +63,7 @@ static struct class shost_class = {
**/
void
scsi_host_cancel
(
struct
Scsi_Host
*
shost
,
int
recovery
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
set_bit
(
SHOST_CANCEL
,
&
shost
->
shost_state
);
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
device_for_each_child
(
&
shost
->
shost_gendev
,
&
recovery
,
scsi_device_cancel_cb
);
wait_event
(
shost
->
host_wait
,
(
!
test_bit
(
SHOST_RECOVERY
,
...
...
@@ -74,15 +76,11 @@ void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
**/
void
scsi_remove_host
(
struct
Scsi_Host
*
shost
)
{
unsigned
long
flags
;
scsi_host_cancel
(
shost
,
0
);
scsi_proc_host_rm
(
shost
);
scsi_forget_host
(
shost
);
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
set_bit
(
SHOST_DEL
,
&
shost
->
shost_state
);
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
class_device_unregister
(
&
shost
->
shost_classdev
);
device_del
(
&
shost
->
shost_gendev
);
...
...
@@ -209,7 +207,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
spin_lock_init
(
&
shost
->
default_lock
);
scsi_assign_lock
(
shost
,
&
shost
->
default_lock
);
INIT_LIST_HEAD
(
&
shost
->
my
_devices
);
INIT_LIST_HEAD
(
&
shost
->
_
_devices
);
INIT_LIST_HEAD
(
&
shost
->
eh_cmd_q
);
INIT_LIST_HEAD
(
&
shost
->
starved_list
);
init_waitqueue_head
(
&
shost
->
host_wait
);
...
...
@@ -323,23 +321,20 @@ void scsi_unregister(struct Scsi_Host *shost)
**/
struct
Scsi_Host
*
scsi_host_lookup
(
unsigned
short
hostnum
)
{
struct
class
*
class
=
class_get
(
&
shost_class
)
;
struct
class
*
class
=
&
shost_class
;
struct
class_device
*
cdev
;
struct
Scsi_Host
*
shost
=
ERR_PTR
(
-
ENXIO
),
*
p
;
if
(
class
)
{
down_read
(
&
class
->
subsys
.
rwsem
);
list_for_each_entry
(
cdev
,
&
class
->
children
,
node
)
{
p
=
class_to_shost
(
cdev
);
if
(
p
->
host_no
==
hostnum
)
{
shost
=
scsi_host_get
(
p
);
break
;
}
down_read
(
&
class
->
subsys
.
rwsem
);
list_for_each_entry
(
cdev
,
&
class
->
children
,
node
)
{
p
=
class_to_shost
(
cdev
);
if
(
p
->
host_no
==
hostnum
)
{
shost
=
scsi_host_get
(
p
);
break
;
}
up_read
(
&
class
->
subsys
.
rwsem
);
}
up_read
(
&
class
->
subsys
.
rwsem
);
class_put
(
&
shost_class
);
return
shost
;
}
...
...
drivers/scsi/hosts.h
View file @
5237662f
/*
* hosts.h Copyright (C) 1992 Drew Eckhardt
* Copyright (C) 1993, 1994, 1995, 1998, 1999 Eric Youngdale
*
* mid to low-level SCSI driver interface header
* Initial versions: Drew Eckhardt
* Subsequent revisions: Eric Youngdale
*
* <drew@colorado.edu>
*
* Modified by Eric Youngdale eric@andante.org to
* add scatter-gather, multiple outstanding request, and other
* enhancements.
*
* Further modified by Eric Youngdale to support multiple host adapters
* 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
#include <linux/config.h>
// #warning "This file is obsolete, please use <scsi/scsi_host.h> instead"
#include <scsi/scsi_host.h>
/**
* 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
struct
scsi_device
*
scsi_find_device
(
struct
Scsi_Host
*
shost
,
int
channel
,
int
pun
,
int
lun
)
{
struct
scsi_device
*
sdev
;
list_for_each_entry
(
sdev
,
&
shost
->
my_devices
,
siblings
)
if
(
sdev
->
channel
==
channel
&&
sdev
->
id
==
pun
&&
sdev
->
lun
==
lun
)
return
sdev
;
return
NULL
;
}
#endif
drivers/scsi/lasi700.c
View file @
5237662f
...
...
@@ -69,8 +69,9 @@ static Scsi_Host_Template lasi700_template = {
.
name
=
"LASI SCSI 53c700"
,
.
proc_name
=
"lasi700"
,
.
this_id
=
7
,
.
module
=
THIS_MODULE
,
};
MODULE_DEVICE_TABLE
(
parisc
,
lasi700_
scsi_tbl
);
MODULE_DEVICE_TABLE
(
parisc
,
lasi700_
ids
);
static
int
__init
lasi700_probe
(
struct
parisc_device
*
dev
)
...
...
drivers/scsi/scsi.c
View file @
5237662f
/*
* scsi.c Copyright (C) 1992 Drew Eckhardt
* Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale
* Copyright (C) 2002, 2003 Christoph Hellwig
*
* generic mid-level SCSI driver
* Initial versions: Drew Eckhardt
...
...
@@ -36,7 +37,6 @@
* out_of_space hacks, D. Gilbert (dpg) 990608
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
...
...
@@ -54,8 +54,8 @@
#include <linux/kmod.h>
#include <linux/interrupt.h>
#include <scsi/scsi_host.h>
#include "scsi.h"
#include "hosts.h"
#include "scsi_priv.h"
#include "scsi_logging.h"
...
...
@@ -883,49 +883,124 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth)
return
depth
;
}
/**
* scsi_device_get - get an addition reference to a scsi_device
* @sdev: device to get a reference to
*
* Gets a reference to the scsi_device and increments the use count
* of the underlying LLDD module. You must hold host_lock of the
* parent Scsi_Host or already have a reference when calling this.
*/
int
scsi_device_get
(
struct
scsi_device
*
sdev
)
{
struct
class
*
class
=
class_get
(
&
sdev_class
);
if
(
!
class
)
goto
out
;
if
(
test_bit
(
SDEV_DEL
,
&
sdev
->
sdev_state
))
goto
out
;
if
(
!
try_module_get
(
sdev
->
host
->
hostt
->
module
))
goto
out
;
return
-
ENXIO
;
if
(
!
get_device
(
&
sdev
->
sdev_gendev
))
goto
out_put_module
;
atomic_inc
(
&
sdev
->
access_count
);
class_put
(
&
sdev_class
);
return
-
ENXIO
;
if
(
!
try_module_get
(
sdev
->
host
->
hostt
->
module
))
{
put_device
(
&
sdev
->
sdev_gendev
);
return
-
ENXIO
;
}
return
0
;
}
EXPORT_SYMBOL
(
scsi_device_get
);
out_put_module:
/**
* scsi_device_put - release a reference to a scsi_device
* @sdev: device to release a reference on.
*
* Release a reference to the scsi_device and decrements the use count
* of the underlying LLDD module. The device is freed once the last
* user vanishes.
*/
void
scsi_device_put
(
struct
scsi_device
*
sdev
)
{
module_put
(
sdev
->
host
->
hostt
->
module
);
out:
class_put
(
&
sdev_class
);
return
-
ENXIO
;
put_device
(
&
sdev
->
sdev_gendev
);
}
EXPORT_SYMBOL
(
scsi_device_put
);
void
scsi_device_put
(
struct
scsi_device
*
sdev
)
/* helper for shost_for_each_device, thus not documented */
struct
scsi_device
*
__scsi_iterate_devices
(
struct
Scsi_Host
*
shost
,
struct
scsi_device
*
prev
)
{
struct
class
*
class
=
class_get
(
&
sdev_class
);
struct
list_head
*
list
=
(
prev
?
&
prev
->
siblings
:
&
shost
->
__devices
);
struct
scsi_device
*
next
=
NULL
;
unsigned
long
flags
;
if
(
!
class
)
return
;
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
while
(
list
->
next
!=
&
shost
->
__devices
)
{
next
=
list_entry
(
list
->
next
,
struct
scsi_device
,
siblings
);
/* skip devices that we can't get a reference to */
if
(
!
scsi_device_get
(
next
))
break
;
list
=
list
->
next
;
}
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
module_put
(
sdev
->
host
->
hostt
->
module
);
atomic_dec
(
&
sdev
->
access_count
);
put_device
(
&
sdev
->
sdev_gendev
);
class_put
(
&
sdev_class
);
if
(
prev
)
scsi_device_put
(
prev
);
return
next
;
}
EXPORT_SYMBOL
(
__scsi_iterate_devices
);
int
scsi_device_cancel_cb
(
struct
device
*
dev
,
void
*
data
)
/**
* scsi_device_lookup - find a device given the host (UNLOCKED)
* @shost: SCSI host pointer
* @channel: SCSI channel (zero if only one channel)
* @pun: SCSI target number (physical unit number)
* @lun: SCSI Logical Unit Number
*
* Looks up the scsi_device with the specified @channel, @id, @lun for a
* give host. The returned scsi_device does not have an additional reference.
* You must hold the host's host_lock over this call and any access to the
* returned scsi_device.
*
* Note: The only reason why drivers would want to use this is because
* they're need to access the device list in irq context. Otherwise you
* really want to use scsi_device_lookup instead.
**/
struct
scsi_device
*
__scsi_device_lookup
(
struct
Scsi_Host
*
shost
,
uint
channel
,
uint
id
,
uint
lun
)
{
struct
scsi_device
*
sdev
=
to_scsi_device
(
dev
);
int
recovery
=
*
(
int
*
)
data
;
struct
scsi_device
*
sdev
;
list_for_each_entry
(
sdev
,
&
shost
->
__devices
,
siblings
)
{
if
(
sdev
->
channel
==
channel
&&
sdev
->
id
==
id
&&
sdev
->
lun
==
lun
)
return
sdev
;
}
return
NULL
;
}
EXPORT_SYMBOL
(
__scsi_device_lookup
);
/**
* scsi_device_lookup - find a device given the host
* @shost: SCSI host pointer
* @channel: SCSI channel (zero if only one channel)
* @id: SCSI target number (physical unit number)
* @lun: SCSI Logical Unit Number
*
* Looks up the scsi_device with the specified @channel, @id, @lun for a
* give host. The returned scsi_device has an additional reference that
* needs to be release with scsi_host_put once you're done with it.
**/
struct
scsi_device
*
scsi_device_lookup
(
struct
Scsi_Host
*
shost
,
uint
channel
,
uint
id
,
uint
lun
)
{
struct
scsi_device
*
sdev
;
unsigned
long
flags
;
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
sdev
=
__scsi_device_lookup
(
shost
,
channel
,
id
,
lun
);
if
(
sdev
&&
scsi_device_get
(
sdev
))
sdev
=
NULL
;
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
return
s
csi_device_cancel
(
sdev
,
recovery
)
;
return
s
dev
;
}
EXPORT_SYMBOL
(
scsi_device_lookup
);
/**
* scsi_device_cancel - cancel outstanding IO to this device
...
...
drivers/scsi/scsi_lib.c
View file @
5237662f
...
...
@@ -16,9 +16,9 @@
#include <linux/init.h>
#include <linux/pci.h>
#include "scsi.h"
#include "hosts.h"
#include <scsi/scsi_driver.h>
#include <scsi/scsi_host.h>
#include "scsi.h"
#include "scsi_priv.h"
#include "scsi_logging.h"
...
...
@@ -335,13 +335,14 @@ void scsi_device_unbusy(struct scsi_device *sdev)
*/
static
void
scsi_single_lun_run
(
struct
scsi_device
*
current_sdev
)
{
struct
scsi_device
*
sdev
;
struct
Scsi_Host
*
shost
=
current_sdev
->
host
;
struct
scsi_device
*
sdev
,
*
tmp
;
unsigned
long
flags
;
spin_lock_irqsave
(
current_sdev
->
host
->
host_lock
,
flags
);
spin_lock_irqsave
(
s
host
->
host_lock
,
flags
);
WARN_ON
(
!
current_sdev
->
sdev_target
->
starget_sdev_user
);
current_sdev
->
sdev_target
->
starget_sdev_user
=
NULL
;
spin_unlock_irqrestore
(
current_sdev
->
host
->
host_lock
,
flags
);
spin_unlock_irqrestore
(
s
host
->
host_lock
,
flags
);
/*
* Call blk_run_queue for all LUNs on the target, starting with
...
...
@@ -351,21 +352,26 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)
*/
blk_run_queue
(
current_sdev
->
request_queue
);
spin_lock_irqsave
(
current_sdev
->
host
->
host_lock
,
flags
);
if
(
current_sdev
->
sdev_target
->
starget_sdev_user
)
{
/*
* After unlock, this races with anyone clearing
* starget_sdev_user, but we (should) always enter this
* function again, avoiding any problems.
*/
spin_unlock_irqrestore
(
current_sdev
->
host
->
host_lock
,
flags
);
return
;
}
spin_unlock_irqrestore
(
current_sdev
->
host
->
host_lock
,
flags
)
;
/*
* After unlock, this races with anyone clearing starget_sdev_user,
* but we always enter this function again, avoiding any problems.
*/
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
if
(
current_sdev
->
sdev_target
->
starget_sdev_user
)
goto
out
;
list_for_each_entry_safe
(
sdev
,
tmp
,
&
current_sdev
->
same_target_siblings
,
same_target_siblings
)
{
if
(
scsi_device_get
(
sdev
))
continue
;
list_for_each_entry
(
sdev
,
&
current_sdev
->
same_target_siblings
,
same_target_siblings
)
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
blk_run_queue
(
sdev
->
request_queue
);
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
scsi_device_put
(
sdev
);
}
out:
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
}
/*
...
...
drivers/scsi/scsi_proc.c
View file @
5237662f
...
...
@@ -27,8 +27,8 @@
#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include <scsi/scsi_host.h>
#include "scsi.h"
#include "hosts.h"
#include "scsi_priv.h"
#include "scsi_logging.h"
...
...
@@ -212,15 +212,13 @@ static int scsi_remove_single_device(uint host, uint channel, uint id, uint lun)
shost
=
scsi_host_lookup
(
host
);
if
(
IS_ERR
(
shost
))
return
PTR_ERR
(
shost
);
sdev
=
scsi_find_device
(
shost
,
channel
,
id
,
lun
);
if
(
!
sdev
)
goto
out
;
if
(
atomic_read
(
&
sdev
->
access_count
))
goto
out
;
sdev
=
scsi_device_lookup
(
shost
,
channel
,
id
,
lun
);
if
(
sdev
)
{
scsi_remove_device
(
sdev
);
scsi_device_put
(
sdev
);
error
=
0
;
}
scsi_remove_device
(
sdev
);
error
=
0
;
out:
scsi_host_put
(
shost
);
return
error
;
}
...
...
drivers/scsi/scsi_scan.c
View file @
5237662f
...
...
@@ -32,10 +32,10 @@
#include <linux/blkdev.h>
#include <asm/semaphore.h>
#include "scsi.h"
#include "hosts.h"
#include <scsi/scsi_driver.h>
#include <scsi/scsi_devinfo.h>
#include <scsi/scsi_host.h>
#include "scsi.h"
#include "scsi_priv.h"
#include "scsi_logging.h"
...
...
@@ -190,13 +190,13 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
uint
channel
,
uint
id
,
uint
lun
)
{
struct
scsi_device
*
sdev
,
*
device
;
unsigned
long
flags
;
sdev
=
kmalloc
(
sizeof
(
*
sdev
),
GFP_ATOMIC
);
if
(
!
sdev
)
goto
out
;
memset
(
sdev
,
0
,
sizeof
(
*
sdev
));
atomic_set
(
&
sdev
->
access_count
,
0
);
sdev
->
vendor
=
scsi_null_device_strs
;
sdev
->
model
=
scsi_null_device_strs
;
sdev
->
rev
=
scsi_null_device_strs
;
...
...
@@ -240,7 +240,8 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
* If there are any same target siblings, add this to the
* sibling list
*/
list_for_each_entry
(
device
,
&
shost
->
my_devices
,
siblings
)
{
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
list_for_each_entry
(
device
,
&
shost
->
__devices
,
siblings
)
{
if
(
device
->
id
==
sdev
->
id
&&
device
->
channel
==
sdev
->
channel
)
{
list_add_tail
(
&
sdev
->
same_target_siblings
,
...
...
@@ -258,10 +259,8 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
if
(
!
sdev
->
scsi_level
)
sdev
->
scsi_level
=
SCSI_2
;
/*
* Add it to the end of the shost->my_devices list.
*/
list_add_tail
(
&
sdev
->
siblings
,
&
shost
->
my_devices
);
list_add_tail
(
&
sdev
->
siblings
,
&
shost
->
__devices
);
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
return
sdev
;
out_free_queue:
...
...
@@ -285,21 +284,21 @@ void scsi_free_sdev(struct scsi_device *sdev)
{
unsigned
long
flags
;
spin_lock_irqsave
(
sdev
->
host
->
host_lock
,
flags
);
list_del
(
&
sdev
->
siblings
);
list_del
(
&
sdev
->
same_target_siblings
);
spin_unlock_irqrestore
(
sdev
->
host
->
host_lock
,
flags
);
if
(
sdev
->
request_queue
)
scsi_free_queue
(
sdev
->
request_queue
);
if
(
sdev
->
inquiry
)
kfree
(
sdev
->
inquiry
);
spin_lock_irqsave
(
sdev
->
host
->
host_lock
,
flags
);
list_del
(
&
sdev
->
starved_entry
);
if
(
sdev
->
single_lun
)
{
if
(
--
sdev
->
sdev_target
->
starget_refcnt
==
0
)
kfree
(
sdev
->
sdev_target
);
}
if
(
sdev
->
single_lun
&&
--
sdev
->
sdev_target
->
starget_refcnt
==
0
)
kfree
(
sdev
->
sdev_target
);
spin_unlock_irqrestore
(
sdev
->
host
->
host_lock
,
flags
);
kfree
(
sdev
->
inquiry
);
kfree
(
sdev
);
}
...
...
@@ -678,7 +677,7 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host,
* host adapter calls into here with rescan == 0.
*/
if
(
rescan
)
{
sdev
=
scsi_
find_device
(
host
,
channel
,
id
,
lun
);
sdev
=
scsi_
device_lookup
(
host
,
channel
,
id
,
lun
);
if
(
sdev
)
{
SCSI_LOG_SCAN_BUS
(
3
,
printk
(
KERN_INFO
"scsi scan: device exists on <%d:%d:%d:%d>
\n
"
,
...
...
@@ -689,6 +688,8 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host,
*
bflagsp
=
scsi_get_device_flags
(
sdev
,
sdev
->
vendor
,
sdev
->
model
);
/* XXX: bandaid until callers do refcounting */
scsi_device_put
(
sdev
);
return
SCSI_SCAN_LUN_PRESENT
;
}
}
...
...
@@ -1232,14 +1233,25 @@ void scsi_scan_host(struct Scsi_Host *shost)
void
scsi_forget_host
(
struct
Scsi_Host
*
shost
)
{
struct
list_head
*
le
,
*
lh
;
struct
scsi_device
*
sdev
;
struct
scsi_device
*
sdev
,
*
tmp
;
unsigned
long
flags
;
list_for_each_safe
(
le
,
lh
,
&
shost
->
my_devices
)
{
sdev
=
list_entry
(
le
,
struct
scsi_device
,
siblings
);
/*
* Ok, this look a bit strange. We always look for the first device
* on the list as scsi_remove_device removes them from it - thus we
* also have to release the lock.
* We don't need to get another reference to the device before
* releasing the lock as we already own the reference from
* scsi_register_device that's release in scsi_remove_device. And
* after that we don't look at sdev anymore.
*/
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
list_for_each_entry_safe
(
sdev
,
tmp
,
&
shost
->
__devices
,
siblings
)
{
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
scsi_remove_device
(
sdev
);
spin_lock_irqsave
(
shost
->
host_lock
,
flags
);
}
spin_unlock_irqrestore
(
shost
->
host_lock
,
flags
);
}
/*
...
...
drivers/scsi/scsi_syms.c
View file @
5237662f
...
...
@@ -18,13 +18,14 @@
#include <asm/irq.h>
#include <asm/dma.h>
#include "scsi.h"
#include <scsi/scsi_driver.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
#include "hosts.h"
#include <scsi/scsicam.h>
#include "scsi.h"
#include "scsi_logging.h"
#include <scsi/scsicam.h>
/*
* This source file contains the symbol table used by scsi loadable
...
...
@@ -82,8 +83,6 @@ EXPORT_SYMBOL(scsi_sleep);
EXPORT_SYMBOL
(
scsi_io_completion
);
EXPORT_SYMBOL
(
scsi_device_get
);
EXPORT_SYMBOL
(
scsi_device_put
);
EXPORT_SYMBOL
(
scsi_add_device
);
EXPORT_SYMBOL
(
scsi_remove_device
);
EXPORT_SYMBOL
(
scsi_device_cancel
);
...
...
drivers/scsi/scsi_sysfs.c
View file @
5237662f
...
...
@@ -11,8 +11,9 @@
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/device.h>
#include <scsi/scsi_host.h>
#include "scsi.h"
#include "hosts.h"
#include "scsi_priv.h"
#include "scsi_logging.h"
...
...
@@ -257,20 +258,12 @@ store_rescan_field (struct device *dev, const char *buf, size_t count)
scsi_rescan_device
(
dev
);
return
count
;
}
static
DEVICE_ATTR
(
rescan
,
S_IWUSR
,
NULL
,
store_rescan_field
)
static
ssize_t
sdev_store_delete
(
struct
device
*
dev
,
const
char
*
buf
,
size_t
count
)
{
struct
scsi_device
*
sdev
=
to_scsi_device
(
dev
);
/*
* FIXME and scsi_proc.c: racey use of access_count,
*/
if
(
atomic_read
(
&
sdev
->
access_count
))
return
-
EBUSY
;
scsi_remove_device
(
sdev
);
scsi_remove_device
(
to_scsi_device
(
dev
));
return
count
;
};
static
DEVICE_ATTR
(
delete
,
S_IWUSR
,
NULL
,
sdev_store_delete
);
...
...
@@ -403,22 +396,12 @@ int scsi_device_register(struct scsi_device *sdev)
**/
void
scsi_remove_device
(
struct
scsi_device
*
sdev
)
{
struct
class
*
class
=
class_get
(
&
sdev_class
);
class_device_unregister
(
&
sdev
->
sdev_classdev
);
if
(
class
)
{
down_write
(
&
class
->
subsys
.
rwsem
);
set_bit
(
SDEV_DEL
,
&
sdev
->
sdev_state
);
if
(
sdev
->
host
->
hostt
->
slave_destroy
)
sdev
->
host
->
hostt
->
slave_destroy
(
sdev
);
device_del
(
&
sdev
->
sdev_gendev
);
up_write
(
&
class
->
subsys
.
rwsem
);
}
set_bit
(
SDEV_DEL
,
&
sdev
->
sdev_state
);
if
(
sdev
->
host
->
hostt
->
slave_destroy
)
sdev
->
host
->
hostt
->
slave_destroy
(
sdev
);
device_del
(
&
sdev
->
sdev_gendev
);
put_device
(
&
sdev
->
sdev_gendev
);
class_put
(
&
sdev_class
);
}
int
scsi_register_driver
(
struct
device_driver
*
drv
)
...
...
drivers/scsi/sg.c
View file @
5237662f
...
...
@@ -914,7 +914,8 @@ sg_ioctl(struct inode *inode, struct file *filp,
case
SG_GET_VERSION_NUM
:
return
put_user
(
sg_version_num
,
(
int
*
)
arg
);
case
SG_GET_ACCESS_COUNT
:
val
=
(
sdp
->
device
?
atomic_read
(
&
sdp
->
device
->
access_count
)
:
0
);
/* faked - we don't have a real access count anymore */
val
=
(
sdp
->
device
?
1
:
0
);
return
put_user
(
val
,
(
int
*
)
arg
);
case
SG_GET_REQUEST_TABLE
:
result
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
...
...
@@ -1627,7 +1628,7 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
unsigned
int
nr_pages
;
struct
page
**
pages
;
nr_pages
=
((
uaddr
&
~
PAGE_MASK
)
+
count
-
1
+
~
PAGE_MASK
)
>>
PAGE_SHIFT
;
nr_pages
=
((
uaddr
&
~
PAGE_MASK
)
+
count
+
~
PAGE_MASK
)
>>
PAGE_SHIFT
;
/* User attempted Overflow! */
if
((
uaddr
+
count
)
<
uaddr
)
...
...
@@ -2903,7 +2904,7 @@ sg_proc_dev_info(char *buffer, int *len, off_t * begin, off_t offset, int size)
PRINT_PROC
(
"%d
\t
%d
\t
%d
\t
%d
\t
%d
\t
%d
\t
%d
\t
%d
\t
%d
\n
"
,
scsidp
->
host
->
host_no
,
scsidp
->
channel
,
scsidp
->
id
,
scsidp
->
lun
,
(
int
)
scsidp
->
type
,
(
int
)
atomic_read
(
&
scsidp
->
access_count
)
,
1
,
(
int
)
scsidp
->
queue_depth
,
(
int
)
scsidp
->
device_busy
,
(
int
)
scsidp
->
online
);
...
...
drivers/scsi/sim710.c
View file @
5237662f
...
...
@@ -90,6 +90,7 @@ static Scsi_Host_Template sim710_driver_template = {
.
name
=
"LSI (Symbios) 710 MCA/EISA"
,
.
proc_name
=
"sim710"
,
.
this_id
=
7
,
.
module
=
THIS_MODULE
,
};
static
__devinit
int
...
...
drivers/scsi/st.c
View file @
5237662f
...
...
@@ -4036,7 +4036,7 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa
unsigned
int
nr_pages
;
struct
page
**
pages
;
nr_pages
=
((
uaddr
&
~
PAGE_MASK
)
+
count
-
1
+
~
PAGE_MASK
)
>>
PAGE_SHIFT
;
nr_pages
=
((
uaddr
&
~
PAGE_MASK
)
+
count
+
~
PAGE_MASK
)
>>
PAGE_SHIFT
;
/* User attempted Overflow! */
if
((
uaddr
+
count
)
<
uaddr
)
...
...
include/scsi/scsi_device.h
View file @
5237662f
...
...
@@ -22,10 +22,13 @@ enum {
};
struct
scsi_device
{
struct
list_head
siblings
;
/* list of all devices on this host */
struct
list_head
same_target_siblings
;
/* just the devices sharing same target id */
struct
Scsi_Host
*
host
;
struct
request_queue
*
request_queue
;
/* the next two are protected by the host->host_lock */
struct
list_head
siblings
;
/* list of all devices on this host */
struct
list_head
same_target_siblings
;
/* just the devices sharing same target id */
volatile
unsigned
short
device_busy
;
/* commands actually active on low-level */
spinlock_t
sdev_lock
;
/* also the request queue_lock */
spinlock_t
list_lock
;
...
...
@@ -45,8 +48,6 @@ struct scsi_device {
* vendor-specific cmd's */
unsigned
sector_size
;
/* size in bytes */
atomic_t
access_count
;
/* Count of open channels/mounts */
void
*
hostdata
;
/* available to low-level driver */
char
devfs_name
[
256
];
/* devfs junk */
char
type
;
...
...
@@ -108,14 +109,48 @@ struct scsi_device {
extern
struct
scsi_device
*
scsi_add_device
(
struct
Scsi_Host
*
,
uint
,
uint
,
uint
);
extern
void
scsi_remove_device
(
struct
scsi_device
*
);
extern
int
scsi_device_cancel_cb
(
struct
device
*
,
void
*
);
extern
int
scsi_device_cancel
(
struct
scsi_device
*
,
int
);
extern
int
scsi_device_get
(
struct
scsi_device
*
);
extern
void
scsi_device_put
(
struct
scsi_device
*
);
extern
struct
scsi_device
*
scsi_device_lookup
(
struct
Scsi_Host
*
,
uint
,
uint
,
uint
);
extern
struct
scsi_device
*
__scsi_device_lookup
(
struct
Scsi_Host
*
,
uint
,
uint
,
uint
);
/* only exposed to implement shost_for_each_device */
extern
struct
scsi_device
*
__scsi_iterate_devices
(
struct
Scsi_Host
*
,
struct
scsi_device
*
);
/**
* shost_for_each_device - iterate over all devices of a host
* @sdev: iterator
* @host: host whiches devices we want to iterate over
*
* This traverses over each devices of @shost. The devices have
* a reference that must be released by scsi_host_put when breaking
* out of the loop.
*/
#define shost_for_each_device(sdev, shost) \
list_for_each_entry((sdev), &((shost)->my_devices), siblings)
for ((sdev) = __scsi_iterate_devices((shost), NULL); \
(sdev); \
(sdev) = __scsi_iterate_devices((shost), (sdev)))
/**
* __shost_for_each_device - iterate over all devices of a host (UNLOCKED)
* @sdev: iterator
* @host: host whiches devices we want to iterate over
*
* This traverses over each devices of @shost. It does _not_ take a
* reference on the scsi_device, thus it the whole loop must be protected
* by shost->host_lock.
*
* Note: The only reason why drivers would want to use this is because
* they're need to access the device list in irq context. Otherwise you
* really want to use shost_for_each_device instead.
*/
#define __shost_for_each_device(sdev, shost) \
list_for_each_entry((sdev), &((shost)->__devices), siblings)
extern
void
scsi_adjust_queue_depth
(
struct
scsi_device
*
,
int
,
int
);
extern
int
scsi_track_queue_full
(
struct
scsi_device
*
,
int
);
...
...
include/scsi/scsi_driver.h
View file @
5237662f
...
...
@@ -4,6 +4,7 @@
#include <linux/device.h>
struct
module
;
struct
scsi_cmnd
;
struct
scsi_driver
{
...
...
include/scsi/scsi_host.h
View file @
5237662f
...
...
@@ -363,19 +363,30 @@ enum {
};
struct
Scsi_Host
{
struct
list_head
my_devices
;
/*
* __devices is protected by the host_lock, but you should
* usually use scsi_device_lookup / shost_for_each_device
* to access it and don't care about locking yourself.
* In the rare case of beeing in irq context you can use
* their __ prefixed variants with the lock held. NEVER
* access this list directly from a driver.
*/
struct
list_head
__devices
;
struct
scsi_host_cmd_pool
*
cmd_pool
;
spinlock_t
free_list_lock
;
struct
list_head
free_list
;
/* backup store of cmd structs */
struct
list_head
free_list
;
/* backup store of cmd structs */
struct
list_head
starved_list
;
spinlock_t
default_lock
;
spinlock_t
*
host_lock
;
struct
semaphore
scan_mutex
;
/* serialize scanning activity */
struct
list_head
eh_cmd_q
;
struct
task_struct
*
ehandler
;
/* Error recovery thread. */
struct
semaphore
*
eh_wait
;
/* The error recovery thread waits
on
this. */
struct
semaphore
*
eh_wait
;
/* The error recovery thread waits
on
this. */
struct
completion
*
eh_notify
;
/* wait for eh to begin or end */
struct
semaphore
*
eh_action
;
/* Wait for specific actions on the
host. */
...
...
@@ -478,12 +489,6 @@ struct Scsi_Host {
*/
struct
list_head
sht_legacy_list
;
/*
* This mutex serializes all scsi scanning activity from kernel- and
* userspace.
*/
struct
semaphore
scan_mutex
;
/*
* We should ensure that this is aligned, both for better performance
* and also because some compilers (m68k) don't automatically force
...
...
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