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
384cce6d
Commit
384cce6d
authored
Mar 15, 2003
by
James Bottomley
Browse files
Options
Browse Files
Download
Plain Diff
Merge raven.il.steeleye.com:/home/jejb/BK/scsi-misc-2.5
into raven.il.steeleye.com:/home/jejb/BK/scsi-for-linus-2.5
parents
bda2dabe
39beef0b
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
807 additions
and
578 deletions
+807
-578
drivers/scsi/aacraid/linit.c
drivers/scsi/aacraid/linit.c
+20
-21
drivers/scsi/hosts.h
drivers/scsi/hosts.h
+1
-0
drivers/scsi/osst.c
drivers/scsi/osst.c
+6
-6
drivers/scsi/qlogicfc.c
drivers/scsi/qlogicfc.c
+41
-31
drivers/scsi/scsi.c
drivers/scsi/scsi.c
+123
-125
drivers/scsi/scsi.h
drivers/scsi/scsi.h
+1
-2
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_debug.c
+384
-251
drivers/scsi/scsi_debug.h
drivers/scsi/scsi_debug.h
+3
-1
drivers/scsi/scsi_error.c
drivers/scsi/scsi_error.c
+0
-22
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_lib.c
+0
-1
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_scan.c
+74
-65
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_sysfs.c
+20
-0
drivers/scsi/sd.c
drivers/scsi/sd.c
+36
-1
drivers/scsi/sg.c
drivers/scsi/sg.c
+98
-52
No files found.
drivers/scsi/aacraid/linit.c
View file @
384cce6d
...
...
@@ -679,27 +679,26 @@ static int aac_cfg_ioctl(struct inode * inode, struct file * file, unsigned int
*/
static
Scsi_Host_Template
driver_template
=
{
module:
THIS_MODULE
,
name:
"AAC"
,
proc_info:
aac_procinfo
,
detect:
aac_detect
,
release:
aac_release
,
info:
aac_driverinfo
,
ioctl:
aac_ioctl
,
queuecommand:
aac_queuecommand
,
bios_param:
aac_biosparm
,
slave_configure:
aac_slave_configure
,
can_queue:
AAC_NUM_IO_FIB
,
this_id:
16
,
sg_tablesize:
16
,
max_sectors:
128
,
cmd_per_lun:
AAC_NUM_IO_FIB
,
eh_abort_handler:
aac_eh_abort
,
eh_device_reset_handler:
aac_eh_device_reset
,
eh_bus_reset_handler:
aac_eh_bus_reset
,
eh_host_reset_handler:
aac_eh_reset
,
use_clustering:
ENABLE_CLUSTERING
,
.
module
=
THIS_MODULE
,
.
name
=
"AAC"
,
.
proc_info
=
aac_procinfo
,
.
detect
=
aac_detect
,
.
release
=
aac_release
,
.
info
=
aac_driverinfo
,
.
ioctl
=
aac_ioctl
,
.
queuecommand
=
aac_queuecommand
,
.
bios_param
=
aac_biosparm
,
.
slave_configure
=
aac_slave_configure
,
.
can_queue
=
AAC_NUM_IO_FIB
,
.
this_id
=
16
,
.
sg_tablesize
=
16
,
.
max_sectors
=
128
,
.
cmd_per_lun
=
1
,
.
eh_abort_handler
=
aac_eh_abort
,
.
eh_device_reset_handler
=
aac_eh_device_reset
,
.
eh_bus_reset_handler
=
aac_eh_bus_reset
,
.
eh_host_reset_handler
=
aac_eh_reset
,
.
use_clustering
=
ENABLE_CLUSTERING
,
};
#include "scsi_module.c"
...
...
drivers/scsi/hosts.h
View file @
384cce6d
...
...
@@ -549,6 +549,7 @@ struct Scsi_Device_Template
void
(
*
detach
)(
Scsi_Device
*
);
int
(
*
init_command
)(
Scsi_Cmnd
*
);
/* Used by new queueing code.
Selects command for blkdevs */
void
(
*
rescan
)(
Scsi_Device
*
);
struct
device_driver
scsi_driverfs_driver
;
};
...
...
drivers/scsi/osst.c
View file @
384cce6d
...
...
@@ -606,7 +606,7 @@ static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned
{
unsigned
char
cmd
[
MAX_COMMAND_SIZE
];
Scsi_Request
*
SRpnt
;
long
startwait
=
jiffies
;
unsigned
long
startwait
=
jiffies
;
#if DEBUG
int
dbg
=
debugging
;
char
*
name
=
tape_name
(
STp
);
...
...
@@ -673,7 +673,7 @@ static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsi
{
unsigned
char
cmd
[
MAX_COMMAND_SIZE
];
Scsi_Request
*
SRpnt
;
long
startwait
=
jiffies
;
unsigned
long
startwait
=
jiffies
;
#if DEBUG
int
dbg
=
debugging
;
char
*
name
=
tape_name
(
STp
);
...
...
@@ -777,8 +777,8 @@ static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
#define OSST_POLL_PER_SEC 10
static
int
osst_wait_frame
(
OS_Scsi_Tape
*
STp
,
Scsi_Request
**
aSRpnt
,
int
curr
,
int
minlast
,
int
to
)
{
long
startwait
=
jiffies
;
char
*
name
=
tape_name
(
STp
);
unsigned
long
startwait
=
jiffies
;
char
*
name
=
tape_name
(
STp
);
#if DEBUG
char
notyetprinted
=
1
;
#endif
...
...
@@ -1288,7 +1288,7 @@ static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request **
int
logical_blk_num
=
ntohl
(
STp
->
buffer
->
aux
->
logical_blk_num
)
-
(
nframes
+
pending
-
1
)
*
blks_per_frame
;
char
*
name
=
tape_name
(
STp
);
long
startwait
=
jiffies
;
unsigned
long
startwait
=
jiffies
;
#if DEBUG
int
dbg
=
debugging
;
#endif
...
...
@@ -1477,7 +1477,7 @@ static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
int
expected
=
0
;
int
attempts
=
1000
/
skip
;
int
flag
=
1
;
long
startwait
=
jiffies
;
unsigned
long
startwait
=
jiffies
;
#if DEBUG
int
dbg
=
debugging
;
#endif
...
...
drivers/scsi/qlogicfc.c
View file @
384cce6d
...
...
@@ -836,14 +836,22 @@ static int isp2x00_make_portdb(struct Scsi_Host *host)
short
param
[
8
];
int
i
,
j
;
struct
id_name_map
temp
[
QLOGICFC_MAX_ID
+
1
];
struct
id_name_map
*
map
;
/* base of array [QLOGICFC_MAX_ID + 1] */
struct
id_name_map
*
mapx
;
/* array entry pointer */
struct
isp2x00_hostdata
*
hostdata
;
isp2x00_disable_irqs
(
host
);
memset
(
temp
,
0
,
sizeof
(
temp
));
hostdata
=
(
struct
isp2x00_hostdata
*
)
host
->
hostdata
;
map
=
kmalloc
((
QLOGICFC_MAX_ID
+
1
)
*
sizeof
(
struct
id_name_map
),
GFP_ATOMIC
);
if
(
!
map
)
{
printk
(
"qlogicfc%d : error getting memory -- cannot make port database.
\n
"
,
hostdata
->
host_id
);
goto
fini
;
}
memset
(
map
,
0
,
(
QLOGICFC_MAX_ID
+
1
)
*
sizeof
(
struct
id_name_map
));
isp2x00_disable_irqs
(
host
);
#if ISP2x00_FABRIC
for
(
i
=
0x81
;
i
<
QLOGICFC_MAX_ID
;
i
++
)
{
param
[
0
]
=
MBOX_PORT_LOGOUT
;
...
...
@@ -868,72 +876,74 @@ static int isp2x00_make_portdb(struct Scsi_Host *host)
if
(
param
[
0
]
==
MBOX_COMMAND_COMPLETE
)
{
hostdata
->
port_id
=
((
u_int
)
param
[
3
])
<<
16
;
hostdata
->
port_id
|=
param
[
2
];
temp
[
0
].
loop_id
=
param
[
1
];
temp
[
0
].
wwn
=
hostdata
->
wwn
;
map
->
loop_id
=
param
[
1
];
map
->
wwn
=
hostdata
->
wwn
;
}
else
{
printk
(
"qlogicfc%d : error getting scsi id.
\n
"
,
hostdata
->
host_id
);
}
for
(
i
=
0
;
i
<=
QLOGICFC_MAX_ID
;
i
++
)
temp
[
i
].
loop_id
=
temp
[
0
].
loop_id
;
for
(
i
=
0
,
mapx
=
map
;
i
<=
QLOGICFC_MAX_ID
;
i
++
,
mapx
++
)
mapx
->
loop_id
=
map
->
loop_id
;
for
(
i
=
0
,
j
=
1
;
i
<=
QLOGICFC_MAX_LOOP_ID
;
i
++
)
{
for
(
i
=
0
,
j
=
1
,
mapx
=
map
+
1
;
i
<=
QLOGICFC_MAX_LOOP_ID
;
i
++
)
{
param
[
0
]
=
MBOX_GET_PORT_NAME
;
param
[
1
]
=
(
i
<<
8
)
&
0xff00
;
isp2x00_mbox_command
(
host
,
param
);
if
(
param
[
0
]
==
MBOX_COMMAND_COMPLETE
)
{
temp
[
j
].
loop_id
=
i
;
temp
[
j
].
wwn
=
((
u64
)
(
param
[
2
]
&
0xff
))
<<
56
;
temp
[
j
].
wwn
|=
((
u64
)
((
param
[
2
]
>>
8
)
&
0xff
))
<<
48
;
temp
[
j
].
wwn
|=
((
u64
)
(
param
[
3
]
&
0xff
))
<<
40
;
temp
[
j
].
wwn
|=
((
u64
)
((
param
[
3
]
>>
8
)
&
0xff
))
<<
32
;
temp
[
j
].
wwn
|=
((
u64
)
(
param
[
6
]
&
0xff
))
<<
24
;
temp
[
j
].
wwn
|=
((
u64
)
((
param
[
6
]
>>
8
)
&
0xff
))
<<
16
;
temp
[
j
].
wwn
|=
((
u64
)
(
param
[
7
]
&
0xff
))
<<
8
;
temp
[
j
].
wwn
|=
((
u64
)
((
param
[
7
]
>>
8
)
&
0xff
));
mapx
->
loop_id
=
i
;
mapx
->
wwn
=
((
u64
)
(
param
[
2
]
&
0xff
))
<<
56
;
mapx
->
wwn
|=
((
u64
)
((
param
[
2
]
>>
8
)
&
0xff
))
<<
48
;
mapx
->
wwn
|=
((
u64
)
(
param
[
3
]
&
0xff
))
<<
40
;
mapx
->
wwn
|=
((
u64
)
((
param
[
3
]
>>
8
)
&
0xff
))
<<
32
;
mapx
->
wwn
|=
((
u64
)
(
param
[
6
]
&
0xff
))
<<
24
;
mapx
->
wwn
|=
((
u64
)
((
param
[
6
]
>>
8
)
&
0xff
))
<<
16
;
mapx
->
wwn
|=
((
u64
)
(
param
[
7
]
&
0xff
))
<<
8
;
mapx
->
wwn
|=
((
u64
)
((
param
[
7
]
>>
8
)
&
0xff
));
j
++
;
mapx
++
;
}
}
#if ISP2x00_FABRIC
isp2x00_init_fabric
(
host
,
tem
p
,
j
);
isp2x00_init_fabric
(
host
,
ma
p
,
j
);
#endif
for
(
i
=
0
;
i
<=
QLOGICFC_MAX_ID
;
i
++
)
{
if
(
temp
[
i
].
wwn
!=
hostdata
->
port_db
[
i
].
wwn
)
{
for
(
j
=
0
;
j
<=
QLOGICFC_MAX_ID
;
j
++
)
{
if
(
temp
[
j
].
wwn
==
hostdata
->
port_db
[
i
].
wwn
)
{
hostdata
->
port_db
[
i
].
loop_id
=
temp
[
j
].
loop_id
;
for
(
i
=
0
,
mapx
=
map
;
i
<=
QLOGICFC_MAX_ID
;
i
++
,
mapx
++
)
{
struct
id_name_map
*
tmap
;
/* second array entry pointer */
if
(
mapx
->
wwn
!=
hostdata
->
port_db
[
i
].
wwn
)
{
for
(
j
=
0
,
tmap
=
map
;
j
<=
QLOGICFC_MAX_ID
;
j
++
,
tmap
++
)
{
if
(
tmap
->
wwn
==
hostdata
->
port_db
[
i
].
wwn
)
{
hostdata
->
port_db
[
i
].
loop_id
=
tmap
->
loop_id
;
break
;
}
}
if
(
j
==
QLOGICFC_MAX_ID
+
1
)
hostdata
->
port_db
[
i
].
loop_id
=
temp
[
0
].
loop_id
;
hostdata
->
port_db
[
i
].
loop_id
=
map
->
loop_id
;
for
(
j
=
0
;
j
<=
QLOGICFC_MAX_ID
;
j
++
)
{
if
(
hostdata
->
port_db
[
j
].
wwn
==
temp
[
i
].
wwn
||
!
hostdata
->
port_db
[
j
].
wwn
)
{
if
(
hostdata
->
port_db
[
j
].
wwn
==
mapx
->
wwn
||
!
hostdata
->
port_db
[
j
].
wwn
)
{
break
;
}
}
if
(
j
==
QLOGICFC_MAX_ID
+
1
)
printk
(
"qlogicfc%d : Too many scsi devices, no more room in port map.
\n
"
,
hostdata
->
host_id
);
if
(
!
hostdata
->
port_db
[
j
].
wwn
)
{
hostdata
->
port_db
[
j
].
loop_id
=
temp
[
i
].
loop_id
;
hostdata
->
port_db
[
j
].
wwn
=
temp
[
i
].
wwn
;
hostdata
->
port_db
[
j
].
loop_id
=
mapx
->
loop_id
;
hostdata
->
port_db
[
j
].
wwn
=
mapx
->
wwn
;
}
}
else
hostdata
->
port_db
[
i
].
loop_id
=
temp
[
i
].
loop_id
;
hostdata
->
port_db
[
i
].
loop_id
=
mapx
->
loop_id
;
}
isp2x00_enable_irqs
(
host
);
kfree
(
map
);
fini:
return
0
;
}
...
...
drivers/scsi/scsi.c
View file @
384cce6d
...
...
@@ -96,12 +96,7 @@ unsigned long scsi_pid;
Scsi_Cmnd
*
last_cmnd
;
static
unsigned
long
serial_number
;
struct
softscsi_data
{
Scsi_Cmnd
*
head
;
Scsi_Cmnd
*
tail
;
};
static
struct
softscsi_data
softscsi_data
[
NR_CPUS
]
__cacheline_aligned
;
static
struct
list_head
done_q
[
NR_CPUS
]
__cacheline_aligned
;
/*
* List of all highlevel drivers.
...
...
@@ -637,79 +632,60 @@ void scsi_init_cmd_from_req(Scsi_Cmnd * SCpnt, Scsi_Request * SRpnt)
}
/**
* scsi_done - Mark this command as done
* @SCpnt: The SCSI Command which we think we've completed.
* scsi_done - Enqueue the finished SCSI command into the done queue.
* @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
* ownership back to SCSI Core -- i.e. the LLDD has finished with it.
*
* This function is the mid-level
interrupt routine, which decides how
*
to handle error conditions. Each invocation of this function must
*
do one and *only* one of the following:
* This function is the mid-level
's (SCSI Core) interrupt routine, which
*
regains ownership of the SCSI command (de facto) from a LLDD, and enqueues
*
the command to the done queue for further processing.
*
* 1) Insert command in BH queue.
* 2) Activate error handler for host.
* This is the producer of the done queue who enqueues at the tail.
*
* There is no longer a problem with stack overflow. Interrupts queue
* Scsi_Cmnd on a per-CPU queue and the softirq handler removes them
* from the queue one at a time.
*
* This function is sometimes called from interrupt context, but sometimes
* from task context.
* This function is interrupt context safe.
*/
void
scsi_done
(
Scsi_Cmnd
*
SCpnt
)
void
scsi_done
(
struct
scsi_cmnd
*
cmd
)
{
int
cpu
;
unsigned
long
flags
;
int
cpu
,
tstatus
;
struct
softscsi_data
*
queue
;
struct
list_head
*
pdone_q
;
/*
* We don't have to worry about this one timing out any more.
*/
tstatus
=
scsi_delete_timer
(
SCpnt
);
/*
* If we are unable to remove the timer, it means that the command
* has already timed out. In this case, we have no choice but to
* If we are unable to remove the timer, then the command
* has already timed out. In which case, we have no choice but to
* let the timeout function run, as we have no idea where in fact
* that function could really be. It might be on another processor,
* etc, etc.
*/
if
(
!
tstatus
)
{
if
(
!
scsi_delete_timer
(
cmd
))
return
;
}
/* Set the serial numbers back to zero */
SCpnt
->
serial_number
=
0
;
SCpnt
->
serial_number_at_timeout
=
0
;
SCpnt
->
state
=
SCSI_STATE_BHQUEUE
;
SCpnt
->
owner
=
SCSI_OWNER_BH_HANDLER
;
SCpnt
->
bh_next
=
NULL
;
cmd
->
serial_number
=
0
;
cmd
->
serial_number_at_timeout
=
0
;
cmd
->
state
=
SCSI_STATE_BHQUEUE
;
cmd
->
owner
=
SCSI_OWNER_BH_HANDLER
;
/*
* Next, put this command in the softirq queue.
*
* This is a per-CPU queue, so we just disable local interrupts
* Next, enqueue the command into the done queue.
* It is a per-CPU queue, so we just disable local interrupts
* and need no spinlock.
*/
local_irq_save
(
flags
);
cpu
=
smp_processor_id
();
queue
=
&
softscsi_data
[
cpu
];
if
(
!
queue
->
head
)
{
queue
->
head
=
SCpnt
;
queue
->
tail
=
SCpnt
;
}
else
{
queue
->
tail
->
bh_next
=
SCpnt
;
queue
->
tail
=
SCpnt
;
}
pdone_q
=
&
done_q
[
cpu
];
list_add_tail
(
&
cmd
->
eh_entry
,
pdone_q
);
cpu_raise_softirq
(
cpu
,
SCSI_SOFTIRQ
);
local_irq_restore
(
flags
);
}
/**
* scsi_softirq - Perform post-interrupt handling for completed commands
* scsi_softirq - Perform post-interrupt processing of finished SCSI commands.
*
* This is the consumer of the done queue.
*
* This is called with all interrupts enabled. This should reduce
* interrupt latency, stack depth, and reentrancy of the low-level
...
...
@@ -717,88 +693,92 @@ void scsi_done(Scsi_Cmnd * SCpnt)
*/
static
void
scsi_softirq
(
struct
softirq_action
*
h
)
{
int
cpu
=
smp_processor_id
();
struct
softscsi_data
*
queue
=
&
softscsi_data
[
cpu
];
LIST_HEAD
(
local_q
);
while
(
queue
->
head
)
{
Scsi_Cmnd
*
SCpnt
,
*
SCnext
;
local_irq_disable
();
list_splice_init
(
&
done_q
[
smp_processor_id
()],
&
local_q
);
local_irq_enable
();
local_irq_disable
();
SCpnt
=
queue
->
head
;
queue
->
head
=
NULL
;
l
ocal_irq_enable
(
);
while
(
!
list_empty
(
&
local_q
))
{
struct
scsi_cmnd
*
cmd
=
list_entry
(
local_q
.
next
,
struct
scsi_cmnd
,
eh_entry
)
;
l
ist_del_init
(
&
cmd
->
eh_entry
);
for
(;
SCpnt
;
SCpnt
=
SCnext
)
{
SCnext
=
SCpnt
->
bh_next
;
switch
(
scsi_decide_disposition
(
cmd
))
{
case
SUCCESS
:
/*
* Add to BH queue.
*/
SCSI_LOG_MLCOMPLETE
(
3
,
printk
(
"Command finished %d %d "
"0x%x
\n
"
,
cmd
->
device
->
host
->
host_busy
,
cmd
->
device
->
host
->
host_failed
,
cmd
->
result
));
scsi_finish_command
(
cmd
);
break
;
case
NEEDS_RETRY
:
/*
* We only come in here if we want to retry a
* command. The test to see whether the
* command should be retried should be keeping
* track of the number of tries, so we don't
* end up looping, of course.
*/
SCSI_LOG_MLCOMPLETE
(
3
,
printk
(
"Command needs retry "
"%d %d 0x%x
\n
"
,
cmd
->
device
->
host
->
host_busy
,
cmd
->
device
->
host
->
host_failed
,
cmd
->
result
));
switch
(
scsi_decide_disposition
(
SCpnt
))
{
case
SUCCESS
:
/*
* Add to BH queue.
*/
SCSI_LOG_MLCOMPLETE
(
3
,
printk
(
"Command finished %d %d 0x%x
\n
"
,
SCpnt
->
device
->
host
->
host_busy
,
SCpnt
->
device
->
host
->
host_failed
,
SCpnt
->
result
));
scsi_retry_command
(
cmd
);
break
;
case
ADD_TO_MLQUEUE
:
/*
* This typically happens for a QUEUE_FULL
* message - typically only when the queue
* depth is only approximate for a given
* device. Adding a command to the queue for
* the device will prevent further commands
* from being sent to the device, so we
* shouldn't end up with tons of things being
* sent down that shouldn't be.
*/
SCSI_LOG_MLCOMPLETE
(
3
,
printk
(
"Command rejected as "
"device queue full, "
"put on ml queue %p
\n
"
,
cmd
));
scsi_queue_insert
(
cmd
,
SCSI_MLQUEUE_DEVICE_BUSY
);
break
;
default:
/*
* Here we have a fatal error of some sort.
* Turn it over to the error handler.
*/
SCSI_LOG_MLCOMPLETE
(
3
,
printk
(
"Command failed %p %x "
"busy=%d failed=%d
\n
"
,
cmd
,
cmd
->
result
,
cmd
->
device
->
host
->
host_busy
,
cmd
->
device
->
host
->
host_failed
));
scsi_finish_command
(
SCpnt
);
break
;
case
NEEDS_RETRY
:
/*
* We only come in here if we want to retry a
* command. The test to see whether the
* command should be retried should be keeping
* track of the number of tries, so we don't
* end up looping, of course.
*/
SCSI_LOG_MLCOMPLETE
(
3
,
printk
(
"Command needs retry %d %d 0x%x
\n
"
,
SCpnt
->
device
->
host
->
host_busy
,
SCpnt
->
device
->
host
->
host_failed
,
SCpnt
->
result
));
scsi_retry_command
(
SCpnt
);
break
;
case
ADD_TO_MLQUEUE
:
/*
* This typically happens for a QUEUE_FULL
* message - typically only when the queue
* depth is only approximate for a given
* device. Adding a command to the queue for
* the device will prevent further commands
* from being sent to the device, so we
* shouldn't end up with tons of things being
* sent down that shouldn't be.
*/
SCSI_LOG_MLCOMPLETE
(
3
,
printk
(
"Command rejected as device queue full, put on ml queue %p
\n
"
,
SCpnt
));
scsi_queue_insert
(
SCpnt
,
SCSI_MLQUEUE_DEVICE_BUSY
);
break
;
default:
/*
* Here we have a fatal error of some sort.
* Turn it over to the error handler.
*/
SCSI_LOG_MLCOMPLETE
(
3
,
printk
(
"Command failed %p %x busy=%d failed=%d
\n
"
,
SCpnt
,
SCpnt
->
result
,
SCpnt
->
device
->
host
->
host_busy
,
SCpnt
->
device
->
host
->
host_failed
));
/*
* Dump the sense information too.
*/
if
((
status_byte
(
cmd
->
result
)
&
CHECK_CONDITION
)
!=
0
)
{
SCSI_LOG_MLCOMPLETE
(
3
,
print_sense
(
"bh"
,
cmd
));
}
if
(
!
scsi_eh_scmd_add
(
cmd
,
0
))
{
/*
* Dump the sense information too.
* We only get here if the error
* recovery thread has died.
*/
if
((
status_byte
(
SCpnt
->
result
)
&
CHECK_CONDITION
)
!=
0
)
{
SCSI_LOG_MLCOMPLETE
(
3
,
print_sense
(
"bh"
,
SCpnt
));
}
if
(
!
scsi_eh_scmd_add
(
SCpnt
,
0
))
{
/*
* We only get here if the error
* recovery thread has died.
*/
scsi_finish_command
(
SCpnt
);
}
}
/* switch */
}
/* for(; SCpnt...) */
}
/* while(queue->head) */
scsi_finish_command
(
cmd
);
}
}
}
}
/*
...
...
@@ -1284,6 +1264,21 @@ void scsi_detach_device(struct scsi_device *sdev)
up_read
(
&
scsi_devicelist_mutex
);
}
void
scsi_rescan_device
(
struct
scsi_device
*
sdev
)
{
struct
Scsi_Device_Template
*
sdt
;
down_read
(
&
scsi_devicelist_mutex
);
list_for_each_entry
(
sdt
,
&
scsi_devicelist
,
list
)
{
if
(
!
try_module_get
(
sdt
->
module
))
continue
;
if
(
*
sdt
->
rescan
)
(
*
sdt
->
rescan
)(
sdev
);
module_put
(
sdt
->
module
);
}
up_read
(
&
scsi_devicelist_mutex
);
}
int
scsi_device_get
(
struct
scsi_device
*
sdev
)
{
if
(
!
try_module_get
(
sdev
->
host
->
hostt
->
module
))
...
...
@@ -1481,7 +1476,7 @@ __setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags);
static
int
__init
init_scsi
(
void
)
{
int
error
;
int
error
,
i
;
error
=
scsi_init_queue
();
if
(
error
)
...
...
@@ -1496,6 +1491,9 @@ static int __init init_scsi(void)
if
(
error
)
goto
cleanup_devlist
;
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
INIT_LIST_HEAD
(
&
done_q
[
i
]);
scsi_host_init
();
devfs_mk_dir
(
NULL
,
"scsi"
,
NULL
);
open_softirq
(
SCSI_SOFTIRQ
,
scsi_softirq
,
NULL
);
...
...
drivers/scsi/scsi.h
View file @
384cce6d
...
...
@@ -741,8 +741,7 @@ struct scsi_cmnd {
* abort, etc are in process.
*/
unsigned
volatile
char
internal_timeout
;
struct
scsi_cmnd
*
bh_next
;
/* To enumerate the commands waiting
to be processed. */
unsigned
char
cmd_len
;
unsigned
char
old_cmd_len
;
unsigned
char
sc_data_direction
;
...
...
drivers/scsi/scsi_debug.c
View file @
384cce6d
...
...
@@ -11,7 +11,7 @@
* (or disk like devices) sharing a common amount of RAM
*
*
* For documentation see http://www.torque.net/sg/sdebug.html
* For documentation see http://www.torque.net/sg/sdebug
25
.html
*
* D. Gilbert (dpg) work for Magneto-Optical device test [20010421]
* dpg: work for devfs large number of disks [20010809]
...
...
@@ -54,38 +54,37 @@
#include "scsi_debug.h"
static
const
char
*
scsi_debug_version_str
=
"Version: 1.67 (20021221)"
;
#ifndef SCSI_CMD_READ_16
#define SCSI_CMD_READ_16 0x88
#endif
#ifndef SCSI_CMD_WRITE_16
#define SCSI_CMD_WRITE_16 0x8a
#endif
static
const
char
*
scsi_debug_version_str
=
"Version: 1.68 (20030314)"
;
#define SDEBUG_TAGGED_QUEUING 0
/* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */
/* Default values for driver parameters */
#define DEF_NUM_DEVS 1
#define DEF_DEV_SIZE_MB 8
#define DEF_EVERY_NTH
10
0
#define DEF_EVERY_NTH 0
#define DEF_DELAY 1
#define DEF_MAX_LUNS 2
#define DEF_SCSI_LEVEL 3
#define DEF_NUM_HOST 1
#define DEF_OPTS 0
#define MAX_NUM_HOSTS 128
/* bit mask values for scsi_debug_opts */
#define SCSI_DEBUG_OPT_NOISE 1
#define SCSI_DEBUG_OPT_MEDIUM_ERR 2
#define SCSI_DEBUG_OPT_EVERY_NTH 4
#define SCSI_DEBUG_OPT_TIMEOUT 4
#define SCSI_DEBUG_OPT_RECOVERED_ERR 8
/* When "every_nth" > 0 then modulo "every_nth" commands:
* - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
* - a RECOVERED_ERROR is simulated on successful read and write
* commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
*/
#define OPT_MEDIUM_ERR_ADDR 0x1234
/* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
* sector on read commands: */
#define OPT_MEDIUM_ERR_ADDR 0x1234
/* that's sector 4660 in decimal */
static
int
scsi_debug_dev_size_mb
=
DEF_DEV_SIZE_MB
;
static
int
scsi_debug_num_devs
=
DEF_NUM_DEVS
;
static
int
scsi_debug_num_devs
=
DEF_NUM_DEVS
;
/* max devs per host */
static
int
scsi_debug_opts
=
DEF_OPTS
;
static
int
scsi_debug_every_nth
=
DEF_EVERY_NTH
;
static
int
scsi_debug_cmnd_count
=
0
;
...
...
@@ -112,25 +111,28 @@ static int sdebug_sectors_per; /* sectors per cylinder */
#define SECT_SIZE (1 << POW2_SECT_SIZE)
#define SECT_SIZE_PER(TGT) SECT_SIZE
struct
sdebug_host_info
{
struct
Scsi_Host
*
shost
;
struct
device
*
dev
;
};
struct
sdebug_host_info
*
scsi_debug_hosts
;
#define SDEBUG_SENSE_LEN 32
struct
sdebug_dev_info
{
struct
list_head
dev_list
;
unsigned
char
sense_buff
[
SDEBUG_SENSE_LEN
];
/* weak nexus */
unsigned
int
channel
;
unsigned
int
target
;
unsigned
int
lun
;
struct
Scsi_Host
*
host
;
struct
sdebug_host_info
*
sdbg_
host
;
char
reset
;
char
used
;
};
static
struct
sdebug_dev_info
*
devInfop
;
struct
sdebug_host_info
{
struct
list_head
host_list
;
struct
Scsi_Host
*
shost
;
struct
device
*
dev
;
struct
list_head
dev_info_list
;
};
static
LIST_HEAD
(
sdebug_host_list
);
static
spinlock_t
sdebug_host_list_lock
=
SPIN_LOCK_UNLOCKED
;
typedef
void
(
*
done_funct_t
)
(
struct
scsi_cmnd
*
);
...
...
@@ -156,11 +158,20 @@ static spinlock_t queued_arr_lock = SPIN_LOCK_UNLOCKED;
static
rwlock_t
atomic_rw
=
RW_LOCK_UNLOCKED
;
static
char
sdebug_proc_name
[]
=
"scsi_debug"
;
static
int
sdebug_driver_probe
(
struct
device
*
);
static
int
sdebug_driver_remove
(
struct
device
*
);
static
struct
device_driver
sdebug_driverfs_driver
=
{
.
name
=
sdebug_proc_name
,
.
devclass
=
&
shost_devclass
,
.
name
=
sdebug_proc_name
,
.
probe
=
sdebug_driver_probe
,
.
remove
=
sdebug_driver_remove
,
.
devclass
=
&
shost_devclass
,
};
static
const
int
check_condition_result
=
(
DRIVER_SENSE
<<
24
)
|
SAM_STAT_CHECK_CONDITION
;
/* function declarations */
static
int
resp_inquiry
(
unsigned
char
*
cmd
,
int
target
,
unsigned
char
*
buff
,
int
bufflen
,
struct
sdebug_dev_info
*
devip
);
...
...
@@ -174,7 +185,7 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
static
int
resp_report_luns
(
unsigned
char
*
cmd
,
unsigned
char
*
buff
,
int
bufflen
,
struct
sdebug_dev_info
*
devip
);
static
void
timer_intr_handler
(
unsigned
long
);
static
struct
sdebug_dev_info
*
devInfoReg
(
struct
scsi_
cmnd
*
scmd
);
static
struct
sdebug_dev_info
*
devInfoReg
(
struct
scsi_
device
*
sdev
);
static
void
mk_sense_buffer
(
struct
sdebug_dev_info
*
devip
,
int
key
,
int
asc
,
int
asq
,
int
inbandLen
);
static
int
check_reset
(
struct
scsi_cmnd
*
SCpnt
,
...
...
@@ -189,15 +200,29 @@ static int inquiry_evpd_83(unsigned char * arr, int dev_id_num,
const
char
*
dev_id_str
,
int
dev_id_str_len
);
static
void
do_create_driverfs_files
(
void
);
static
void
do_remove_driverfs_files
(
void
);
static
void
sdebug_add_shost
(
int
num
);
static
void
sdebug_remove_shost
(
int
num
);
static
int
sdebug_add_adapter
(
int
num
);
static
void
sdebug_remove_adapter
(
int
num
);
static
int
sdebug_add_adapter
(
void
);
static
void
sdebug_remove_adapter
(
void
);
static
struct
device
pseudo_primary
;
static
struct
bus_type
pseudo_lld_bus
;
int
scsi_debug_register_driver
(
struct
device_driver
*
);
int
scsi_debug_unregister_driver
(
struct
device_driver
*
);
static
int
scsi_debug_register_driver
(
struct
device_driver
*
);
static
int
scsi_debug_unregister_driver
(
struct
device_driver
*
);
static
struct
sdebug_host_info
*
sdebug_shost_to_host_info
(
struct
Scsi_Host
*
shost
)
{
struct
sdebug_host_info
*
sdbg_host
,
*
found
=
NULL
;
spin_lock
(
&
sdebug_host_list_lock
);
list_for_each_entry
(
sdbg_host
,
&
sdebug_host_list
,
host_list
)
{
if
(
sdbg_host
->
shost
==
shost
)
{
found
=
sdbg_host
;
break
;
}
}
spin_unlock
(
&
sdebug_host_list_lock
);
return
found
;
}
static
unsigned
char
*
scatg2virt
(
const
struct
scatterlist
*
sclp
)
{
...
...
@@ -222,6 +247,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
unsigned
long
capac
;
struct
sdebug_dev_info
*
devip
=
NULL
;
unsigned
char
*
sbuff
;
int
inj_recovered
=
0
;
if
(
done
==
NULL
)
return
0
;
/* assume mid level reprocessing command */
...
...
@@ -250,16 +276,18 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
if
(
SCpnt
->
device
->
lun
>=
scsi_debug_max_luns
)
return
schedule_resp
(
SCpnt
,
NULL
,
done
,
DID_NO_CONNECT
<<
16
,
0
);
devip
=
devInfoReg
(
SCpnt
);
devip
=
devInfoReg
(
SCpnt
->
device
);
if
(
NULL
==
devip
)
return
schedule_resp
(
SCpnt
,
NULL
,
done
,
DID_NO_CONNECT
<<
16
,
0
);
if
((
SCSI_DEBUG_OPT_EVERY_NTH
&
scsi_debug_opts
)
&&
(
scsi_debug_every_nth
>
0
)
&&
if
((
scsi_debug_every_nth
>
0
)
&&
(
++
scsi_debug_cmnd_count
>=
scsi_debug_every_nth
))
{
scsi_debug_cmnd_count
=
0
;
return
0
;
/* ignore command causing timeout */
if
(
SCSI_DEBUG_OPT_TIMEOUT
&
scsi_debug_opts
)
return
0
;
/* ignore command causing timeout */
else
if
(
SCSI_DEBUG_OPT_RECOVERED_ERR
&
scsi_debug_opts
)
inj_recovered
=
1
;
/* to reads and writes below */
}
switch
(
*
cmd
)
{
...
...
@@ -269,8 +297,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
case
REQUEST_SENSE
:
/* mandatory */
/* Since this driver indicates autosense by placing the
* sense buffer in the scsi_cmnd structure in the response
* (when
CHECK_CONDITION is set), the mid level shouldn't
* need to call REQUEST_SENSE */
* (when
SAM_STAT_CHECK_CONDITION is set), the mid level
*
shouldn't
need to call REQUEST_SENSE */
if
(
devip
)
{
sbuff
=
devip
->
sense_buff
;
memcpy
(
buff
,
sbuff
,
(
bufflen
<
SDEBUG_SENSE_LEN
)
?
...
...
@@ -326,14 +354,14 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
buff
[
7
]
=
SECT_SIZE_PER
(
target
)
&
0xff
;
}
break
;
case
SCSI_CMD_READ_16
:
/* SBC-2 */
case
READ_16
:
case
READ_12
:
case
READ_10
:
case
READ_6
:
if
((
errsts
=
check_reset
(
SCpnt
,
devip
)))
break
;
upper_blk
=
0
;
if
((
*
cmd
)
==
SCSI_CMD_
READ_16
)
{
if
((
*
cmd
)
==
READ_16
)
{
upper_blk
=
cmd
[
5
]
+
(
cmd
[
4
]
<<
8
)
+
(
cmd
[
3
]
<<
16
)
+
(
cmd
[
2
]
<<
24
);
block
=
cmd
[
9
]
+
(
cmd
[
8
]
<<
8
)
+
...
...
@@ -355,18 +383,22 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
num
=
cmd
[
4
];
}
errsts
=
resp_read
(
SCpnt
,
upper_blk
,
block
,
num
,
devip
);
if
(
inj_recovered
&&
(
0
==
errsts
))
{
mk_sense_buffer
(
devip
,
RECOVERED_ERROR
,
0x5d
,
0
,
14
);
errsts
=
check_condition_result
;
}
break
;
case
REPORT_LUNS
:
errsts
=
resp_report_luns
(
cmd
,
buff
,
bufflen
,
devip
);
break
;
case
SCSI_CMD_WRITE_16
:
/* SBC-2 */
case
WRITE_16
:
case
WRITE_12
:
case
WRITE_10
:
case
WRITE_6
:
if
((
errsts
=
check_reset
(
SCpnt
,
devip
)))
break
;
upper_blk
=
0
;
if
((
*
cmd
)
==
SCSI_CMD_
WRITE_16
)
{
if
((
*
cmd
)
==
WRITE_16
)
{
upper_blk
=
cmd
[
5
]
+
(
cmd
[
4
]
<<
8
)
+
(
cmd
[
3
]
<<
16
)
+
(
cmd
[
2
]
<<
24
);
block
=
cmd
[
9
]
+
(
cmd
[
8
]
<<
8
)
+
...
...
@@ -388,6 +420,10 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
num
=
cmd
[
4
];
}
errsts
=
resp_write
(
SCpnt
,
upper_blk
,
block
,
num
,
devip
);
if
(
inj_recovered
&&
(
0
==
errsts
))
{
mk_sense_buffer
(
devip
,
RECOVERED_ERROR
,
0x5d
,
0
,
14
);
errsts
=
check_condition_result
;
}
break
;
case
MODE_SENSE
:
case
MODE_SENSE_10
:
...
...
@@ -400,7 +436,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
if
((
errsts
=
check_reset
(
SCpnt
,
devip
)))
break
;
mk_sense_buffer
(
devip
,
ILLEGAL_REQUEST
,
0x20
,
0
,
14
);
errsts
=
(
DRIVER_SENSE
<<
24
)
|
(
CHECK_CONDITION
<<
1
)
;
errsts
=
check_condition_result
;
break
;
}
return
schedule_resp
(
SCpnt
,
devip
,
done
,
errsts
,
scsi_debug_delay
);
...
...
@@ -420,7 +456,7 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip)
if
(
devip
->
reset
)
{
devip
->
reset
=
0
;
mk_sense_buffer
(
devip
,
UNIT_ATTENTION
,
0x29
,
0
,
14
);
return
(
DRIVER_SENSE
<<
24
)
|
(
CHECK_CONDITION
<<
1
)
;
return
check_condition_result
;
}
return
0
;
}
...
...
@@ -481,12 +517,12 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
arr
[
0
]
=
pq_pdt
;
if
(
0x2
&
cmd
[
1
])
{
/* CMDDT bit set */
mk_sense_buffer
(
devip
,
ILLEGAL_REQUEST
,
0x24
,
0
,
14
);
return
(
DRIVER_SENSE
<<
24
)
|
(
CHECK_CONDITION
<<
1
)
;
return
check_condition_result
;
}
else
if
(
0x1
&
cmd
[
1
])
{
/* EVPD bit set */
int
dev_id_num
,
len
;
char
dev_id_str
[
6
];
dev_id_num
=
((
devip
->
host
->
host_no
+
1
)
*
2000
)
+
dev_id_num
=
((
devip
->
sdbg_host
->
s
host
->
host_no
+
1
)
*
2000
)
+
(
devip
->
target
*
1000
)
+
devip
->
lun
;
len
=
snprintf
(
dev_id_str
,
6
,
"%d"
,
dev_id_num
);
len
=
(
len
>
6
)
?
6
:
len
;
...
...
@@ -506,7 +542,7 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
}
else
{
/* Illegal request, invalid field in cdb */
mk_sense_buffer
(
devip
,
ILLEGAL_REQUEST
,
0x24
,
0
,
14
);
return
(
DRIVER_SENSE
<<
24
)
|
(
CHECK_CONDITION
<<
1
)
;
return
check_condition_result
;
}
memcpy
(
buff
,
arr
,
min_len
);
return
0
;
...
...
@@ -619,7 +655,7 @@ static int resp_mode_sense(unsigned char * cmd, int target,
memset
(
arr
,
0
,
SDEBUG_MAX_MSENSE_SZ
);
if
(
0x3
==
pcontrol
)
{
/* Saving values not supported */
mk_sense_buffer
(
devip
,
ILLEGAL_REQUEST
,
0x39
,
0
,
14
);
return
(
DRIVER_SENSE
<<
24
)
|
(
CHECK_CONDITION
<<
1
)
;
return
check_condition_result
;
}
dev_spec
=
DEV_READONLY
(
target
)
?
0x80
:
0x0
;
if
(
msense_6
)
{
...
...
@@ -662,7 +698,7 @@ static int resp_mode_sense(unsigned char * cmd, int target,
break
;
default:
mk_sense_buffer
(
devip
,
ILLEGAL_REQUEST
,
0x24
,
0
,
14
);
return
(
DRIVER_SENSE
<<
24
)
|
(
CHECK_CONDITION
<<
1
)
;
return
check_condition_result
;
}
if
(
msense_6
)
arr
[
0
]
=
offset
-
1
;
...
...
@@ -686,14 +722,14 @@ static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block,
if
(
upper_blk
||
(
block
+
num
>
sdebug_capacity
))
{
mk_sense_buffer
(
devip
,
ILLEGAL_REQUEST
,
0x21
,
0
,
14
);
return
(
DRIVER_SENSE
<<
24
)
|
(
CHECK_CONDITION
<<
1
)
;
return
check_condition_result
;
}
if
((
SCSI_DEBUG_OPT_MEDIUM_ERR
&
scsi_debug_opts
)
&&
(
block
>
=
OPT_MEDIUM_ERR_ADDR
)
&&
(
block
<
(
OPT_MEDIUM_ERR_ADDR
+
num
)
))
{
(
block
<
=
OPT_MEDIUM_ERR_ADDR
)
&&
(
(
block
+
num
)
>
OPT_MEDIUM_ERR_ADDR
))
{
mk_sense_buffer
(
devip
,
MEDIUM_ERROR
,
0x11
,
0
,
14
);
/* claim unrecoverable read error */
return
(
DRIVER_SENSE
<<
24
)
|
(
CHECK_CONDITION
<<
1
)
;
return
check_condition_result
;
}
read_lock_irqsave
(
&
atomic_rw
,
iflags
);
sgcount
=
0
;
...
...
@@ -735,7 +771,7 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
if
(
upper_blk
||
(
block
+
num
>
sdebug_capacity
))
{
mk_sense_buffer
(
devip
,
ILLEGAL_REQUEST
,
0x21
,
0
,
14
);
return
(
DRIVER_SENSE
<<
24
)
|
(
CHECK_CONDITION
<<
1
)
;
return
check_condition_result
;
}
write_lock_irqsave
(
&
atomic_rw
,
iflags
);
...
...
@@ -776,7 +812,7 @@ static int resp_report_luns(unsigned char * cmd, unsigned char * buff,
alloc_len
=
cmd
[
9
]
+
(
cmd
[
8
]
<<
8
)
+
(
cmd
[
7
]
<<
16
)
+
(
cmd
[
6
]
<<
24
);
if
((
alloc_len
<
16
)
||
(
select_report
>
2
))
{
mk_sense_buffer
(
devip
,
ILLEGAL_REQUEST
,
0x24
,
0
,
14
);
return
(
DRIVER_SENSE
<<
24
)
|
(
CHECK_CONDITION
<<
1
)
;
return
check_condition_result
;
}
if
(
bufflen
>
3
)
{
lun_cnt
=
min
((
int
)(
bufflen
/
sizeof
(
ScsiLun
)),
...
...
@@ -810,15 +846,24 @@ static void timer_intr_handler(unsigned long indx)
return
;
}
sqcp
->
in_use
=
0
;
if
(
sqcp
->
done_funct
)
if
(
sqcp
->
done_funct
)
{
sqcp
->
a_cmnd
->
result
=
sqcp
->
scsi_result
;
sqcp
->
done_funct
(
sqcp
->
a_cmnd
);
/* callback to mid level */
}
sqcp
->
done_funct
=
NULL
;
spin_unlock_irqrestore
(
&
queued_arr_lock
,
iflags
);
}
static
int
scsi_debug_slave_alloc
(
struct
scsi_device
*
sdp
)
{
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
printk
(
KERN_INFO
"scsi_debug: slave_alloc <%u %u %u %u>
\n
"
,
sdp
->
host
->
host_no
,
sdp
->
channel
,
sdp
->
id
,
sdp
->
lun
);
return
0
;
}
static
int
scsi_debug_slave_configure
(
struct
scsi_device
*
sdp
)
{
int
k
;
struct
sdebug_dev_info
*
devip
;
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
...
...
@@ -826,16 +871,8 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp)
sdp
->
host
->
host_no
,
sdp
->
channel
,
sdp
->
id
,
sdp
->
lun
);
if
(
sdp
->
host
->
max_cmd_len
!=
SCSI_DEBUG_MAX_CMD_LEN
)
sdp
->
host
->
max_cmd_len
=
SCSI_DEBUG_MAX_CMD_LEN
;
for
(
k
=
0
;
k
<
scsi_debug_num_devs
;
++
k
)
{
devip
=
&
devInfop
[
k
];
if
((
devip
->
channel
==
sdp
->
channel
)
&&
(
devip
->
target
==
sdp
->
id
)
&&
(
devip
->
lun
==
sdp
->
lun
)
&&
(
devip
->
host
==
sdp
->
host
))
{
sdp
->
hostdata
=
devip
;
break
;
}
}
devip
=
devInfoReg
(
sdp
);
sdp
->
hostdata
=
devip
;
if
(
sdp
->
host
->
cmd_per_lun
)
scsi_adjust_queue_depth
(
sdp
,
SDEBUG_TAGGED_QUEUING
,
sdp
->
host
->
cmd_per_lun
);
...
...
@@ -852,43 +889,47 @@ static void scsi_debug_slave_destroy(struct scsi_device * sdp)
sdp
->
host
->
host_no
,
sdp
->
channel
,
sdp
->
id
,
sdp
->
lun
);
if
(
devip
)
{
/* make this slot avaliable for re-use */
memset
(
devip
,
0
,
sizeof
(
struct
sdebug_dev_info
))
;
devip
->
used
=
0
;
sdp
->
hostdata
=
NULL
;
}
}
static
struct
sdebug_dev_info
*
devInfoReg
(
struct
scsi_
cmnd
*
scmd
)
static
struct
sdebug_dev_info
*
devInfoReg
(
struct
scsi_
device
*
sdev
)
{
int
k
;
struct
s
csi_device
*
sdp
=
scmd
->
device
;
struct
sdebug_host_info
*
sdbg_host
;
struct
s
debug_dev_info
*
open_devip
=
NULL
;
struct
sdebug_dev_info
*
devip
=
(
struct
sdebug_dev_info
*
)
sd
p
->
hostdata
;
(
struct
sdebug_dev_info
*
)
sd
ev
->
hostdata
;
if
(
devip
)
return
devip
;
for
(
k
=
0
;
k
<
scsi_debug_num_devs
;
++
k
)
{
devip
=
&
devInfop
[
k
];
if
((
devip
->
channel
==
scmd
->
device
->
channel
)
&&
(
devip
->
target
==
scmd
->
device
->
id
)
&&
(
devip
->
lun
==
scmd
->
device
->
lun
)
&&
(
devip
->
host
==
scmd
->
device
->
host
))
return
devip
;
}
for
(
k
=
0
;
k
<
scsi_debug_num_devs
;
++
k
)
{
devip
=
&
devInfop
[
k
];
if
(
!
devip
->
used
)
{
devip
->
channel
=
scmd
->
device
->
channel
;
devip
->
target
=
scmd
->
device
->
id
;
devip
->
lun
=
scmd
->
device
->
lun
;
devip
->
host
=
scmd
->
device
->
host
;
devip
->
reset
=
1
;
devip
->
used
=
1
;
memset
(
devip
->
sense_buff
,
0
,
SDEBUG_SENSE_LEN
);
devip
->
sense_buff
[
0
]
=
0x70
;
return
devip
;
sdbg_host
=
sdebug_shost_to_host_info
(
sdev
->
host
);
if
(
!
sdbg_host
)
{
printk
(
KERN_ERR
"Unable to locate host info
\n
"
);
return
NULL
;
}
list_for_each_entry
(
devip
,
&
sdbg_host
->
dev_info_list
,
dev_list
)
{
if
((
devip
->
used
)
&&
(
devip
->
channel
==
sdev
->
channel
)
&&
(
devip
->
target
==
sdev
->
id
)
&&
(
devip
->
lun
==
sdev
->
lun
))
return
devip
;
else
{
if
((
!
devip
->
used
)
&&
(
!
open_devip
))
open_devip
=
devip
;
}
}
return
NULL
;
if
(
open_devip
)
{
open_devip
->
channel
=
sdev
->
channel
;
open_devip
->
target
=
sdev
->
id
;
open_devip
->
lun
=
sdev
->
lun
;
open_devip
->
sdbg_host
=
sdbg_host
;
open_devip
->
reset
=
1
;
open_devip
->
used
=
1
;
memset
(
open_devip
->
sense_buff
,
0
,
SDEBUG_SENSE_LEN
);
open_devip
->
sense_buff
[
0
]
=
0x70
;
return
open_devip
;
}
return
NULL
;
}
static
void
mk_sense_buffer
(
struct
sdebug_dev_info
*
devip
,
int
key
,
...
...
@@ -946,7 +987,7 @@ static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
printk
(
KERN_INFO
"scsi_debug: device_reset
\n
"
);
++
num_dev_resets
;
if
(
SCpnt
)
{
devip
=
devInfoReg
(
SCpnt
);
devip
=
devInfoReg
(
SCpnt
->
device
);
if
(
devip
)
devip
->
reset
=
1
;
}
...
...
@@ -955,17 +996,21 @@ static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt)
static
int
scsi_debug_bus_reset
(
struct
scsi_cmnd
*
SCpnt
)
{
struct
scsi_device
*
sdp
;
struct
Scsi_Host
*
hp
;
int
k
;
struct
sdebug_host_info
*
sdbg_host
;
struct
sdebug_dev_info
*
dev_info
;
struct
scsi_device
*
sdp
;
struct
Scsi_Host
*
hp
;
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
printk
(
KERN_INFO
"scsi_debug: bus_reset
\n
"
);
++
num_bus_resets
;
if
(
SCpnt
&&
((
sdp
=
SCpnt
->
device
))
&&
((
hp
=
SCpnt
->
device
->
host
)))
{
for
(
k
=
0
;
k
<
scsi_debug_num_devs
;
++
k
)
{
if
(
hp
==
devInfop
[
k
].
host
)
devInfop
[
k
].
reset
=
1
;
if
(
SCpnt
&&
((
sdp
=
SCpnt
->
device
))
&&
((
hp
=
sdp
->
host
)))
{
sdbg_host
=
sdebug_shost_to_host_info
(
hp
);
if
(
sdbg_host
)
{
list_for_each_entry
(
dev_info
,
&
sdbg_host
->
dev_info_list
,
dev_list
)
dev_info
->
reset
=
1
;
}
}
return
SUCCESS
;
...
...
@@ -973,15 +1018,20 @@ static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt)
static
int
scsi_debug_host_reset
(
struct
scsi_cmnd
*
SCpnt
)
{
int
k
;
struct
sdebug_host_info
*
sdbg_host
;
struct
sdebug_dev_info
*
dev_info
;
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
printk
(
KERN_INFO
"scsi_debug: host_reset
\n
"
);
++
num_host_resets
;
for
(
k
=
0
;
k
<
scsi_debug_num_devs
;
++
k
)
devInfop
[
k
].
reset
=
1
;
spin_lock
(
&
sdebug_host_list_lock
);
list_for_each_entry
(
sdbg_host
,
&
sdebug_host_list
,
host_list
)
{
list_for_each_entry
(
dev_info
,
&
sdbg_host
->
dev_info_list
,
dev_list
)
dev_info
->
reset
=
1
;
}
spin_unlock
(
&
sdebug_host_list_lock
);
stop_all_queued
();
return
SUCCESS
;
}
...
...
@@ -1063,7 +1113,7 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
}
if
(
cmnd
&&
devip
)
{
/* simulate autosense by this driver */
if
(
CHECK_CONDITION
==
status_byte
(
scsi_result
))
if
(
SAM_STAT_CHECK_CONDITION
==
(
scsi_result
&
0xff
))
memcpy
(
cmnd
->
sense_buffer
,
devip
->
sense_buff
,
(
SCSI_SENSE_BUFFERSIZE
>
SDEBUG_SENSE_LEN
)
?
SDEBUG_SENSE_LEN
:
SCSI_SENSE_BUFFERSIZE
);
...
...
@@ -1099,6 +1149,8 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
sqcp
->
cmnd_timer
.
expires
=
jiffies
+
delta_jiff
;
add_timer
(
&
sqcp
->
cmnd_timer
);
spin_unlock_irqrestore
(
&
queued_arr_lock
,
iflags
);
if
(
cmnd
)
cmnd
->
result
=
0
;
return
0
;
}
}
...
...
@@ -1120,7 +1172,7 @@ MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
MODULE_DESCRIPTION
(
"SCSI debug adapter driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM_DESC
(
num_devs
,
"number of SCSI devices to simulate"
);
MODULE_PARM_DESC
(
num_devs
,
"number of SCSI devices
per host
to simulate"
);
MODULE_PARM_DESC
(
max_luns
,
"number of SCSI LUNs per target to simulate"
);
MODULE_PARM_DESC
(
scsi_level
,
"SCSI level to simulate"
);
MODULE_PARM_DESC
(
dev_size_mb
,
"size in MB of ram shared by devs"
);
...
...
@@ -1163,7 +1215,7 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
if
(
1
!=
sscanf
(
arr
,
"%d"
,
&
pos
))
return
-
EINVAL
;
scsi_debug_opts
=
pos
;
if
(
SCSI_DEBUG_OPT_EVERY_NTH
&
scsi_debug_opts
)
if
(
scsi_debug_every_nth
>
0
)
scsi_debug_cmnd_count
=
0
;
return
length
;
}
...
...
@@ -1192,12 +1244,12 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
return
len
;
}
static
ssize_t
sdebug_delay_
read
(
struct
device_driver
*
ddp
,
char
*
buf
)
static
ssize_t
sdebug_delay_
show
(
struct
device_driver
*
ddp
,
char
*
buf
)
{
return
s
printf
(
buf
,
"%d
\n
"
,
scsi_debug_delay
);
return
s
nprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
scsi_debug_delay
);
}
static
ssize_t
sdebug_delay_
writ
e
(
struct
device_driver
*
ddp
,
static
ssize_t
sdebug_delay_
stor
e
(
struct
device_driver
*
ddp
,
const
char
*
buf
,
size_t
count
)
{
int
delay
;
...
...
@@ -1211,15 +1263,15 @@ static ssize_t sdebug_delay_write(struct device_driver * ddp,
}
return
-
EINVAL
;
}
DRIVER_ATTR
(
delay
,
S_IRUGO
|
S_IWUSR
,
sdebug_delay_
read
,
sdebug_delay_
writ
e
)
DRIVER_ATTR
(
delay
,
S_IRUGO
|
S_IWUSR
,
sdebug_delay_
show
,
sdebug_delay_
stor
e
)
static
ssize_t
sdebug_opts_
read
(
struct
device_driver
*
ddp
,
char
*
buf
)
static
ssize_t
sdebug_opts_
show
(
struct
device_driver
*
ddp
,
char
*
buf
)
{
return
s
printf
(
buf
,
"0x%x
\n
"
,
scsi_debug_opts
);
return
s
nprintf
(
buf
,
PAGE_SIZE
,
"0x%x
\n
"
,
scsi_debug_opts
);
}
static
ssize_t
sdebug_opts_
writ
e
(
struct
device_driver
*
ddp
,
static
ssize_t
sdebug_opts_
stor
e
(
struct
device_driver
*
ddp
,
const
char
*
buf
,
size_t
count
)
{
int
opts
;
...
...
@@ -1237,50 +1289,76 @@ static ssize_t sdebug_opts_write(struct device_driver * ddp,
return
-
EINVAL
;
opts_done:
scsi_debug_opts
=
opts
;
scsi_debug_cmnd_count
=
0
;
return
count
;
}
DRIVER_ATTR
(
opts
,
S_IRUGO
|
S_IWUSR
,
sdebug_opts_
read
,
sdebug_opts_
writ
e
)
DRIVER_ATTR
(
opts
,
S_IRUGO
|
S_IWUSR
,
sdebug_opts_
show
,
sdebug_opts_
stor
e
)
static
ssize_t
sdebug_num_devs_
read
(
struct
device_driver
*
ddp
,
char
*
buf
)
static
ssize_t
sdebug_num_devs_
show
(
struct
device_driver
*
ddp
,
char
*
buf
)
{
return
s
printf
(
buf
,
"%d
\n
"
,
scsi_debug_num_devs
);
return
s
nprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
scsi_debug_num_devs
);
}
DRIVER_ATTR
(
num_devs
,
S_IRUGO
,
sdebug_num_devs_read
,
NULL
)
static
ssize_t
sdebug_num_devs_store
(
struct
device_driver
*
ddp
,
const
char
*
buf
,
size_t
count
)
{
int
n
;
if
((
count
>
0
)
&&
(
1
==
sscanf
(
buf
,
"%d"
,
&
n
))
&&
(
n
>=
0
))
{
scsi_debug_num_devs
=
n
;
return
count
;
}
return
-
EINVAL
;
}
DRIVER_ATTR
(
num_devs
,
S_IRUGO
|
S_IWUSR
,
sdebug_num_devs_show
,
sdebug_num_devs_store
)
static
ssize_t
sdebug_dev_size_mb_
read
(
struct
device_driver
*
ddp
,
char
*
buf
)
static
ssize_t
sdebug_dev_size_mb_
show
(
struct
device_driver
*
ddp
,
char
*
buf
)
{
return
s
printf
(
buf
,
"%d
\n
"
,
scsi_debug_dev_size_mb
);
return
s
nprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
scsi_debug_dev_size_mb
);
}
DRIVER_ATTR
(
dev_size_mb
,
S_IRUGO
,
sdebug_dev_size_mb_
read
,
NULL
)
DRIVER_ATTR
(
dev_size_mb
,
S_IRUGO
,
sdebug_dev_size_mb_
show
,
NULL
)
static
ssize_t
sdebug_every_nth_read
(
struct
device_driver
*
ddp
,
char
*
buf
)
static
ssize_t
sdebug_every_nth_show
(
struct
device_driver
*
ddp
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
scsi_debug_every_nth
);
}
static
ssize_t
sdebug_every_nth_store
(
struct
device_driver
*
ddp
,
const
char
*
buf
,
size_t
count
)
{
return
sprintf
(
buf
,
"%d
\n
"
,
scsi_debug_every_nth
);
int
nth
;
if
((
count
>
0
)
&&
(
1
==
sscanf
(
buf
,
"%d"
,
&
nth
))
&&
(
nth
>=
0
))
{
scsi_debug_every_nth
=
nth
;
scsi_debug_cmnd_count
=
0
;
return
count
;
}
return
-
EINVAL
;
}
DRIVER_ATTR
(
every_nth
,
S_IRUGO
,
sdebug_every_nth_read
,
NULL
)
DRIVER_ATTR
(
every_nth
,
S_IRUGO
|
S_IWUSR
,
sdebug_every_nth_show
,
sdebug_every_nth_store
)
static
ssize_t
sdebug_max_luns_
read
(
struct
device_driver
*
ddp
,
char
*
buf
)
static
ssize_t
sdebug_max_luns_
show
(
struct
device_driver
*
ddp
,
char
*
buf
)
{
return
s
printf
(
buf
,
"%d
\n
"
,
scsi_debug_max_luns
);
return
s
nprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
scsi_debug_max_luns
);
}
DRIVER_ATTR
(
max_luns
,
S_IRUGO
,
sdebug_max_luns_
read
,
NULL
)
DRIVER_ATTR
(
max_luns
,
S_IRUGO
,
sdebug_max_luns_
show
,
NULL
)
static
ssize_t
sdebug_scsi_level_
read
(
struct
device_driver
*
ddp
,
char
*
buf
)
static
ssize_t
sdebug_scsi_level_
show
(
struct
device_driver
*
ddp
,
char
*
buf
)
{
return
s
printf
(
buf
,
"%d
\n
"
,
scsi_debug_scsi_level
);
return
s
nprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
scsi_debug_scsi_level
);
}
DRIVER_ATTR
(
scsi_level
,
S_IRUGO
,
sdebug_scsi_level_
read
,
NULL
)
DRIVER_ATTR
(
scsi_level
,
S_IRUGO
,
sdebug_scsi_level_
show
,
NULL
)
static
ssize_t
sdebug_add_host_
read
(
struct
device_driver
*
ddp
,
char
*
buf
)
static
ssize_t
sdebug_add_host_
show
(
struct
device_driver
*
ddp
,
char
*
buf
)
{
return
s
printf
(
buf
,
"%d
\n
"
,
scsi_debug_add_host
);
return
s
nprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
scsi_debug_add_host
);
}
static
ssize_t
sdebug_add_host_
writ
e
(
struct
device_driver
*
ddp
,
const
char
*
buf
,
size_t
count
)
static
ssize_t
sdebug_add_host_
stor
e
(
struct
device_driver
*
ddp
,
const
char
*
buf
,
size_t
count
)
{
int
delta_hosts
,
k
;
int
delta_hosts
;
char
work
[
20
];
if
(
1
!=
sscanf
(
buf
,
"%10s"
,
work
))
...
...
@@ -1297,33 +1375,17 @@ static ssize_t sdebug_add_host_write(struct device_driver * ddp,
}
if
(
delta_hosts
>
0
)
{
do
{
for
(
k
=
0
;
k
<
MAX_NUM_HOSTS
;
++
k
)
{
if
(
NULL
==
scsi_debug_hosts
[
k
].
shost
)
{
sdebug_add_shost
(
k
);
break
;
}
}
if
(
k
==
MAX_NUM_HOSTS
)
break
;
++
scsi_debug_add_host
;
sdebug_add_adapter
();
}
while
(
--
delta_hosts
);
}
else
if
(
delta_hosts
<
0
)
{
do
{
for
(
k
=
MAX_NUM_HOSTS
-
1
;
k
>=
0
;
--
k
)
{
if
(
scsi_debug_hosts
[
k
].
shost
)
{
sdebug_remove_shost
(
k
);
break
;
}
}
if
(
k
<
0
)
break
;
--
scsi_debug_add_host
;
sdebug_remove_adapter
();
}
while
(
++
delta_hosts
);
}
return
count
;
}
DRIVER_ATTR
(
add_host
,
S_IRUGO
|
S_IWUSR
,
sdebug_add_host_
read
,
sdebug_add_host_
writ
e
)
DRIVER_ATTR
(
add_host
,
S_IRUGO
|
S_IWUSR
,
sdebug_add_host_
show
,
sdebug_add_host_
stor
e
)
static
void
do_create_driverfs_files
()
{
...
...
@@ -1349,44 +1411,10 @@ static void do_remove_driverfs_files()
driver_remove_file
(
&
sdebug_driverfs_driver
,
&
driver_attr_delay
);
}
static
void
sdebug_add_shost
(
int
num
)
{
struct
Scsi_Host
*
hpnt
;
int
err
;
if
(
sdebug_add_adapter
(
num
)){
printk
(
KERN_ERR
"sdebug_add_shost: sdebug_add_adapter failed
\n
"
);
return
;
}
hpnt
=
scsi_register
(
&
sdebug_driver_template
,
0
);
if
(
NULL
==
hpnt
)
{
sdebug_remove_adapter
(
num
);
printk
(
KERN_ERR
"sdebug_add_shost: scsi_register failed
\n
"
);
return
;
}
err
=
scsi_add_host
(
hpnt
,
scsi_debug_hosts
[
num
].
dev
);
if
(
err
)
{
printk
(
KERN_ERR
"sdebug_add_shost: scsi_add_host failed
\n
"
);
scsi_unregister
(
hpnt
);
sdebug_remove_adapter
(
num
);
return
;
}
hpnt
->
max_lun
=
scsi_debug_max_luns
;
scsi_debug_hosts
[
num
].
shost
=
hpnt
;
}
static
void
sdebug_remove_shost
(
int
num
)
{
scsi_remove_host
(
scsi_debug_hosts
[
num
].
shost
);
scsi_unregister
(
scsi_debug_hosts
[
num
].
shost
);
sdebug_remove_adapter
(
num
);
scsi_debug_hosts
[
num
].
shost
=
NULL
;
}
static
int
__init
scsi_debug_init
(
void
)
{
unsigned
long
sz
;
int
host_to_add
;
int
k
;
sdebug_store_size
=
(
unsigned
long
)
scsi_debug_dev_size_mb
*
1048576
;
...
...
@@ -1409,30 +1437,10 @@ static int __init scsi_debug_init(void)
(
sdebug_sectors_per
*
sdebug_heads
);
}
if
(
scsi_debug_num_devs
>
0
)
{
sz
=
sizeof
(
struct
sdebug_dev_info
)
*
scsi_debug_num_devs
;
devInfop
=
vmalloc
(
sz
);
if
(
NULL
==
devInfop
)
{
printk
(
KERN_ERR
"scsi_debug_init: out of memory
\n
"
);
return
-
ENOMEM
;
}
memset
(
devInfop
,
0
,
sz
);
}
sz
=
sizeof
(
struct
sdebug_host_info
)
*
MAX_NUM_HOSTS
;
scsi_debug_hosts
=
vmalloc
(
sz
);
if
(
NULL
==
scsi_debug_hosts
)
{
printk
(
KERN_ERR
"scsi_debug_init: out of memory 1
\n
"
);
return
-
ENOMEM
;
}
memset
(
scsi_debug_hosts
,
0
,
sz
);
sz
=
sdebug_store_size
;
fake_storep
=
vmalloc
(
sz
);
if
(
NULL
==
fake_storep
)
{
printk
(
KERN_ERR
"scsi_debug_init: out of memory, 1
\n
"
);
if
(
devInfop
)
vfree
(
devInfop
);
return
-
ENOMEM
;
}
memset
(
fake_storep
,
0
,
sz
);
...
...
@@ -1446,15 +1454,16 @@ static int __init scsi_debug_init(void)
sdebug_driver_template
.
proc_name
=
(
char
*
)
sdebug_proc_name
;
for
(
k
=
0
;
(
k
<
scsi_debug_add_host
)
&&
(
k
<
MAX_NUM_HOSTS
);
k
++
)
{
sdebug_add_shost
(
k
);
if
(
NULL
==
scsi_debug_hosts
[
k
].
shost
)
{
printk
(
KERN_ERR
"scsi_debug_init: "
"sdebug_add_shost failed k=%d
\n
"
,
k
);
break
;
}
}
scsi_debug_add_host
=
k
;
// number of hosts actually present
host_to_add
=
scsi_debug_add_host
;
scsi_debug_add_host
=
0
;
for
(
k
=
0
;
k
<
host_to_add
;
k
++
)
{
if
(
sdebug_add_adapter
())
{
printk
(
KERN_ERR
"scsi_debug_init: "
"sdebug_add_adapter failed k=%d
\n
"
,
k
);
break
;
}
}
if
(
SCSI_DEBUG_OPT_NOISE
&
scsi_debug_opts
)
{
printk
(
KERN_INFO
"scsi_debug: ... built %d host(s)
\n
"
,
...
...
@@ -1465,13 +1474,7 @@ static int __init scsi_debug_init(void)
static
void
__exit
scsi_debug_exit
(
void
)
{
int
k
;
for
(
k
=
MAX_NUM_HOSTS
-
1
;
k
>=
0
;
--
k
)
{
if
(
scsi_debug_hosts
[
k
].
shost
)
{
sdebug_remove_shost
(
k
);
}
}
/* free up adapters here ?? */
stop_all_queued
();
do_remove_driverfs_files
();
scsi_debug_unregister_driver
(
&
sdebug_driverfs_driver
);
...
...
@@ -1479,8 +1482,6 @@ static void __exit scsi_debug_exit(void)
device_unregister
(
&
pseudo_primary
);
vfree
(
fake_storep
);
if
(
devInfop
)
vfree
(
devInfop
);
}
device_initcall
(
scsi_debug_init
);
...
...
@@ -1502,7 +1503,7 @@ static struct bus_type pseudo_lld_bus = {
.
match
=
pseudo_lld_bus_match
,
};
int
scsi_debug_register_driver
(
struct
device_driver
*
dev_driver
)
static
int
scsi_debug_register_driver
(
struct
device_driver
*
dev_driver
)
{
dev_driver
->
bus
=
&
pseudo_lld_bus
;
driver_register
(
dev_driver
);
...
...
@@ -1510,36 +1511,168 @@ int scsi_debug_register_driver(struct device_driver *dev_driver)
return
0
;
}
int
scsi_debug_unregister_driver
(
struct
device_driver
*
dev_driver
)
static
int
scsi_debug_unregister_driver
(
struct
device_driver
*
dev_driver
)
{
driver_unregister
(
dev_driver
);
return
0
;
}
static
int
sdebug_add_adapter
(
int
num
)
static
void
sdebug_release_adapter
(
struct
device
*
dev
)
{
struct
device
*
dev
;
kfree
(
dev
);
}
dev
=
kmalloc
(
sizeof
(
*
dev
),
GFP_KERNEL
);
if
(
NULL
==
dev
)
{
printk
(
KERN_ERR
"%s: out of memory
\n
"
,
__FUNCTION__
);
return
1
;
}
static
int
sdebug_add_adapter
()
{
struct
device
*
dev
;
int
error
;
dev
=
kmalloc
(
sizeof
(
*
dev
),
GFP_KERNEL
);
if
(
NULL
==
dev
)
{
printk
(
KERN_ERR
"%s: out of memory at line %d
\n
"
,
__FUNCTION__
,
__LINE__
);
return
-
ENOMEM
;
}
memset
(
dev
,
0
,
sizeof
(
*
dev
));
memset
(
dev
,
0
,
sizeof
(
*
dev
))
;
dev
->
bus
=
&
pseudo_lld_bus
;
dev
->
parent
=
&
pseudo_primary
;
sprintf
(
dev
->
name
,
"scsi debug adapter"
);
sprintf
(
dev
->
bus_id
,
"adapter%d"
,
num
);
dev
->
bus
=
&
pseudo_lld_bus
;
dev
->
parent
=
&
pseudo_primary
;
dev
->
release
=
&
sdebug_release_adapter
;
sprintf
(
dev
->
name
,
"scsi debug adapter"
);
sprintf
(
dev
->
bus_id
,
"adapter%d"
,
scsi_debug_add_host
);
device_register
(
dev
);
error
=
device_register
(
dev
);
scsi_debug_hosts
[
num
].
dev
=
dev
;
if
(
error
)
kfree
(
dev
);
else
++
scsi_debug_add_host
;
return
0
;
return
error
;
}
static
void
sdebug_remove_adapter
(
int
num
)
static
void
sdebug_remove_adapter
()
{
device_unregister
(
scsi_debug_hosts
[
num
].
dev
);
struct
sdebug_host_info
*
sdbg_host
=
NULL
;
spin_lock
(
&
sdebug_host_list_lock
);
if
(
!
list_empty
(
&
sdebug_host_list
))
sdbg_host
=
list_entry
(
sdebug_host_list
.
prev
,
struct
sdebug_host_info
,
host_list
);
spin_unlock
(
&
sdebug_host_list_lock
);
device_unregister
(
sdbg_host
->
dev
);
--
scsi_debug_add_host
;
}
static
int
sdebug_driver_probe
(
struct
device
*
dev
)
{
int
k
;
int
error
=
0
;
struct
sdebug_host_info
*
sdbg_host
;
struct
sdebug_dev_info
*
sdbg_devinfo
;
struct
list_head
*
lh
,
*
lh_sf
;
struct
Scsi_Host
*
hpnt
;
sdbg_host
=
kmalloc
(
sizeof
(
*
sdbg_host
),
GFP_KERNEL
);
if
(
NULL
==
sdbg_host
)
{
printk
(
KERN_ERR
"%s: out of memory at line %d
\n
"
,
__FUNCTION__
,
__LINE__
);
return
-
ENOMEM
;
}
memset
(
sdbg_host
,
0
,
sizeof
(
*
sdbg_host
));
INIT_LIST_HEAD
(
&
sdbg_host
->
dev_info_list
);
for
(
k
=
0
;
k
<
scsi_debug_num_devs
;
k
++
)
{
sdbg_devinfo
=
kmalloc
(
sizeof
(
*
sdbg_devinfo
),
GFP_KERNEL
);
if
(
NULL
==
sdbg_devinfo
)
{
printk
(
KERN_ERR
"%s: out of memory at line %d
\n
"
,
__FUNCTION__
,
__LINE__
);
error
=
-
ENOMEM
;
}
memset
(
sdbg_devinfo
,
0
,
sizeof
(
*
sdbg_devinfo
));
sdbg_devinfo
->
sdbg_host
=
sdbg_host
;
list_add_tail
(
&
sdbg_devinfo
->
dev_list
,
&
sdbg_host
->
dev_info_list
);
}
list_add_tail
(
&
sdbg_host
->
host_list
,
&
sdebug_host_list
);
hpnt
=
scsi_register
(
&
sdebug_driver_template
,
0
);
if
(
NULL
==
hpnt
)
{
printk
(
KERN_ERR
"%s: scsi_register failed
\n
"
,
__FUNCTION__
);
error
=
-
ENODEV
;
goto
clean1
;
}
sdbg_host
->
shost
=
hpnt
;
sdbg_host
->
dev
=
dev
;
hpnt
->
max_lun
=
scsi_debug_max_luns
;
error
=
scsi_add_host
(
hpnt
,
sdbg_host
->
dev
);
if
(
error
)
{
printk
(
KERN_ERR
"%s: scsi_add_host failed
\n
"
,
__FUNCTION__
);
error
=
-
ENODEV
;
goto
clean2
;
}
return
0
;
clean2:
scsi_unregister
(
hpnt
);
clean1:
list_for_each_safe
(
lh
,
lh_sf
,
&
sdbg_host
->
dev_info_list
)
{
sdbg_devinfo
=
list_entry
(
lh
,
struct
sdebug_dev_info
,
dev_list
);
list_del
(
&
sdbg_devinfo
->
dev_list
);
kfree
(
sdbg_devinfo
);
}
kfree
(
sdbg_host
);
return
error
;
}
static
int
sdebug_driver_remove
(
struct
device
*
dev
)
{
struct
list_head
*
lh
,
*
lh_sf
;
struct
sdebug_dev_info
*
sdbg_devinfo
;
struct
sdebug_host_info
*
sdbg_host
,
*
found
=
NULL
;
spin_lock
(
&
sdebug_host_list_lock
);
list_for_each_entry
(
sdbg_host
,
&
sdebug_host_list
,
host_list
)
{
if
(
sdbg_host
->
dev
==
dev
)
{
list_del
(
&
sdbg_host
->
host_list
);
found
=
sdbg_host
;
break
;
}
}
spin_unlock
(
&
sdebug_host_list_lock
);
if
(
!
found
)
{
printk
(
KERN_ERR
"%s: sdebug_host_info not found
\n
"
,
__FUNCTION__
);
return
-
ENODEV
;
}
if
(
scsi_remove_host
(
sdbg_host
->
shost
))
{
printk
(
KERN_ERR
"%s: scsi_remove_host failed
\n
"
,
__FUNCTION__
);
return
-
EBUSY
;
}
scsi_unregister
(
sdbg_host
->
shost
);
list_for_each_safe
(
lh
,
lh_sf
,
&
sdbg_host
->
dev_info_list
)
{
sdbg_devinfo
=
list_entry
(
lh
,
struct
sdebug_dev_info
,
dev_list
);
list_del
(
&
sdbg_devinfo
->
dev_list
);
kfree
(
sdbg_devinfo
);
}
kfree
(
sdbg_host
);
return
0
;
}
drivers/scsi/scsi_debug.h
View file @
384cce6d
...
...
@@ -2,6 +2,7 @@
#include <linux/types.h>
static
int
scsi_debug_slave_alloc
(
struct
scsi_device
*
);
static
int
scsi_debug_slave_configure
(
struct
scsi_device
*
);
static
void
scsi_debug_slave_destroy
(
struct
scsi_device
*
);
static
int
scsi_debug_queuecommand
(
struct
scsi_cmnd
*
,
...
...
@@ -27,8 +28,9 @@ static Scsi_Host_Template sdebug_driver_template = {
.
proc_info
=
scsi_debug_proc_info
,
.
name
=
"SCSI DEBUG"
,
.
info
=
scsi_debug_info
,
.
slave_alloc
=
scsi_debug_slave_alloc
,
.
slave_configure
=
scsi_debug_slave_configure
,
.
slave_destroy
=
scsi_debug_slave_destroy
,
.
slave_destroy
=
scsi_debug_slave_destroy
,
.
ioctl
=
scsi_debug_ioctl
,
.
queuecommand
=
scsi_debug_queuecommand
,
.
eh_abort_handler
=
scsi_debug_abort
,
...
...
drivers/scsi/scsi_error.c
View file @
384cce6d
...
...
@@ -596,28 +596,6 @@ static int scsi_request_sense(struct scsi_cmnd *scmd)
return
rtn
;
}
/**
* scsi_eh_retry_cmd - Retry the original command
* @scmd: Original failed SCSI cmd.
*
* Notes:
* This function will *not* return until the command either times out,
* or it completes.
**/
static
int
scsi_eh_retry_cmd
(
struct
scsi_cmnd
*
scmd
)
{
int
rtn
=
SUCCESS
;
for
(;
scmd
->
retries
<
scmd
->
allowed
;
scmd
->
retries
++
)
{
scsi_setup_cmd_retry
(
scmd
);
rtn
=
scsi_send_eh_cmnd
(
scmd
,
scmd
->
timeout_per_command
);
if
(
rtn
!=
NEEDS_RETRY
)
break
;
}
return
rtn
;
}
/**
* scsi_eh_finish_cmd - Handle a cmd that eh is finished with.
* @scmd: Original SCSI cmd that eh has finished.
...
...
drivers/scsi/scsi_lib.c
View file @
384cce6d
...
...
@@ -125,7 +125,6 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
*/
cmd
->
state
=
SCSI_STATE_MLQUEUE
;
cmd
->
owner
=
SCSI_OWNER_MIDLEVEL
;
cmd
->
bh_next
=
NULL
;
/*
* Decrement the counters, since these commands are no longer
...
...
drivers/scsi/scsi_scan.c
View file @
384cce6d
...
...
@@ -385,83 +385,92 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
struct
scsi_device
*
sdev
,
*
device
;
sdev
=
kmalloc
(
sizeof
(
*
sdev
),
GFP_ATOMIC
);
if
(
sdev
!=
NULL
)
{
memset
(
sdev
,
0
,
sizeof
(
Scsi_Device
));
sdev
->
vendor
=
scsi_null_device_strs
;
sdev
->
model
=
scsi_null_device_strs
;
sdev
->
rev
=
scsi_null_device_strs
;
sdev
->
host
=
shost
;
sdev
->
id
=
id
;
sdev
->
lun
=
lun
;
sdev
->
channel
=
channel
;
sdev
->
online
=
TRUE
;
INIT_LIST_HEAD
(
&
sdev
->
siblings
);
INIT_LIST_HEAD
(
&
sdev
->
same_target_siblings
);
INIT_LIST_HEAD
(
&
sdev
->
cmd_list
);
spin_lock_init
(
&
sdev
->
list_lock
);
/*
* Some low level driver could use device->type
*/
sdev
->
type
=
-
1
;
/*
* Assume that the device will have handshaking problems,
* and then fix this field later if it turns out it
* doesn't
*/
sdev
->
borken
=
1
;
if
(
!
sdev
)
goto
out
;
if
(
!
q
||
*
q
==
NULL
)
{
sdev
->
request_queue
=
scsi_alloc_queue
(
shost
);
if
(
!
sdev
->
request_queue
)
goto
out_bail
;
}
else
{
sdev
->
request_queue
=
*
q
;
*
q
=
NULL
;
}
memset
(
sdev
,
0
,
sizeof
(
*
sdev
));
sdev
->
vendor
=
scsi_null_device_strs
;
sdev
->
model
=
scsi_null_device_strs
;
sdev
->
rev
=
scsi_null_device_strs
;
sdev
->
host
=
shost
;
sdev
->
id
=
id
;
sdev
->
lun
=
lun
;
sdev
->
channel
=
channel
;
sdev
->
online
=
TRUE
;
INIT_LIST_HEAD
(
&
sdev
->
siblings
);
INIT_LIST_HEAD
(
&
sdev
->
same_target_siblings
);
INIT_LIST_HEAD
(
&
sdev
->
cmd_list
);
spin_lock_init
(
&
sdev
->
list_lock
);
sdev
->
request_queue
->
queuedata
=
sdev
;
scsi_adjust_queue_depth
(
sdev
,
0
,
sdev
->
host
->
cmd_per_lun
);
init_waitqueue_head
(
&
sdev
->
scpnt_wait
);
/*
* Some low level driver could use device->type
*/
sdev
->
type
=
-
1
;
if
(
shost
->
hostt
->
slave_alloc
)
if
(
shost
->
hostt
->
slave_alloc
(
sdev
))
{
goto
out_bail
;
}
/*
* If there are any same target siblings, add this to the
* sibling list
*/
list_for_each_entry
(
device
,
&
shost
->
my_devices
,
siblings
)
{
if
(
device
->
id
==
sdev
->
id
&&
device
->
channel
==
sdev
->
channel
)
{
list_add_tail
(
&
sdev
->
same_target_siblings
,
&
device
->
same_target_siblings
);
sdev
->
scsi_level
=
device
->
scsi_level
;
break
;
}
/*
* Assume that the device will have handshaking problems,
* and then fix this field later if it turns out it
* doesn't
*/
sdev
->
borken
=
1
;
if
(
!
q
||
*
q
==
NULL
)
{
sdev
->
request_queue
=
scsi_alloc_queue
(
shost
);
if
(
!
sdev
->
request_queue
)
goto
out_free_dev
;
}
else
{
sdev
->
request_queue
=
*
q
;
*
q
=
NULL
;
}
sdev
->
request_queue
->
queuedata
=
sdev
;
scsi_adjust_queue_depth
(
sdev
,
0
,
sdev
->
host
->
cmd_per_lun
);
init_waitqueue_head
(
&
sdev
->
scpnt_wait
);
if
(
shost
->
hostt
->
slave_alloc
)
{
if
(
shost
->
hostt
->
slave_alloc
(
sdev
))
goto
out_free_queue
;
}
/*
* If there are any same target siblings, add this to the
* sibling list
*/
list_for_each_entry
(
device
,
&
shost
->
my_devices
,
siblings
)
{
if
(
device
->
id
==
sdev
->
id
&&
device
->
channel
==
sdev
->
channel
)
{
list_add_tail
(
&
sdev
->
same_target_siblings
,
&
device
->
same_target_siblings
);
sdev
->
scsi_level
=
device
->
scsi_level
;
break
;
}
/*
* If there wasn't another lun already configured at this
* target, then default this device to SCSI_2 until we
* know better
*/
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
);
return
(
sdev
);
}
out_bail:
printk
(
ALLOC_FAILURE_MSG
,
__FUNCTION__
);
/*
* If there wasn't another lun already configured at this
* target, then default this device to SCSI_2 until we
* know better
*/
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
);
return
sdev
;
out_free_queue:
if
(
q
&&
sdev
->
request_queue
)
{
*
q
=
sdev
->
request_queue
;
sdev
->
request_queue
=
NULL
;
}
else
if
(
sdev
->
request_queue
)
scsi_free_queue
(
sdev
->
request_queue
);
out_free_dev:
kfree
(
sdev
);
out:
printk
(
ALLOC_FAILURE_MSG
,
__FUNCTION__
);
return
NULL
;
}
...
...
drivers/scsi/scsi_sysfs.c
View file @
384cce6d
...
...
@@ -266,6 +266,25 @@ sdev_rd_attr (model, "%.16s\n");
sdev_rd_attr
(
rev
,
"%.4s
\n
"
);
sdev_rw_attr_bit
(
online
);
static
ssize_t
show_rescan_field
(
struct
device
*
dev
,
char
*
buf
)
{
return
0
;
}
static
ssize_t
store_rescan_field
(
struct
device
*
dev
,
const
char
*
buf
,
size_t
count
)
{
int
ret
=
ENODEV
;
struct
scsi_device
*
sdev
;
sdev
=
to_scsi_device
(
dev
);
if
(
sdev
)
ret
=
scsi_rescan_device
(
sdev
);
return
ret
;
}
static
DEVICE_ATTR
(
rescan
,
S_IRUGO
|
S_IWUSR
,
show_rescan_field
,
store_rescan_field
)
static
struct
device_attribute
*
const
sdev_attrs
[]
=
{
&
dev_attr_device_blocked
,
&
dev_attr_queue_depth
,
...
...
@@ -276,6 +295,7 @@ static struct device_attribute * const sdev_attrs[] = {
&
dev_attr_model
,
&
dev_attr_rev
,
&
dev_attr_online
,
&
dev_attr_rescan
,
};
/**
...
...
drivers/scsi/sd.c
View file @
384cce6d
...
...
@@ -93,10 +93,12 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt);
static
int
sd_attach
(
struct
scsi_device
*
);
static
void
sd_detach
(
struct
scsi_device
*
);
static
void
sd_rescan
(
struct
scsi_device
*
);
static
int
sd_init_command
(
struct
scsi_cmnd
*
);
static
int
sd_synchronize_cache
(
struct
scsi_disk
*
,
int
);
static
int
sd_notifier
(
struct
notifier_block
*
,
unsigned
long
,
void
*
);
static
void
sd_read_capacity
(
struct
scsi_disk
*
sdkp
,
char
*
diskname
,
struct
scsi_request
*
SRpnt
,
unsigned
char
*
buffer
);
static
struct
notifier_block
sd_notifier_block
=
{
sd_notifier
,
NULL
,
0
};
static
struct
Scsi_Device_Template
sd_template
=
{
...
...
@@ -106,6 +108,7 @@ static struct Scsi_Device_Template sd_template = {
.
scsi_type
=
TYPE_DISK
,
.
attach
=
sd_attach
,
.
detach
=
sd_detach
,
.
rescan
=
sd_rescan
,
.
init_command
=
sd_init_command
,
.
scsi_driverfs_driver
=
{
.
name
=
"sd"
,
...
...
@@ -629,6 +632,38 @@ static int sd_media_changed(struct gendisk *disk)
return
1
;
}
static
void
sd_rescan
(
struct
scsi_device
*
sdp
)
{
unsigned
char
*
buffer
;
struct
scsi_disk
*
sdkp
=
sd_find_by_sdev
(
sdp
);
struct
gendisk
*
gd
;
struct
scsi_request
*
SRpnt
;
if
(
!
sdkp
||
sdp
->
online
==
FALSE
||
!
sdkp
->
media_present
)
return
;
gd
=
sdkp
->
disk
;
SCSI_LOG_HLQUEUE
(
3
,
printk
(
"sd_rescan: disk=%s
\n
"
,
gd
->
disk_name
));
SRpnt
=
scsi_allocate_request
(
sdp
);
if
(
!
SRpnt
)
{
printk
(
KERN_WARNING
"(sd_rescan:) Request allocation "
"failure.
\n
"
);
return
;
}
if
(
sdkp
->
device
->
host
->
unchecked_isa_dma
)
buffer
=
kmalloc
(
512
,
GFP_DMA
);
else
buffer
=
kmalloc
(
512
,
GFP_KERNEL
);
sd_read_capacity
(
sdkp
,
gd
->
disk_name
,
SRpnt
,
buffer
);
set_capacity
(
gd
,
sdkp
->
capacity
);
scsi_release_request
(
SRpnt
);
kfree
(
buffer
);
}
static
int
sd_revalidate_disk
(
struct
gendisk
*
disk
)
{
struct
scsi_disk
*
sdkp
=
scsi_disk
(
disk
);
...
...
drivers/scsi/sg.c
View file @
384cce6d
...
...
@@ -18,10 +18,8 @@
*
*/
#include <linux/config.h>
#ifdef CONFIG_PROC_FS
static
char
*
sg_version_str
=
"Version: 3.5.27 (20030130)"
;
#endif
static
int
sg_version_num
=
30527
;
/* 2 digits for each component */
static
char
*
sg_version_str
=
"3.5.28 [20030308]"
;
static
int
sg_version_num
=
30528
;
/* 2 digits for each component */
/*
* D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
* - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
...
...
@@ -56,6 +54,7 @@ static int sg_version_num = 30527; /* 2 digits for each component */
#include <linux/poll.h>
#include <linux/vmalloc.h>
#include <linux/smp_lock.h>
#include <linux/moduleparam.h>
#include <asm/io.h>
#include <asm/uaccess.h>
...
...
@@ -1327,27 +1326,6 @@ static struct file_operations sg_fops = {
.
fasync
=
sg_fasync
,
};
#ifndef MODULE
static
int
__init
sg_def_reserved_size_setup
(
char
*
str
)
{
int
tmp
;
if
(
get_option
(
&
str
,
&
tmp
)
==
1
)
{
def_reserved_size
=
tmp
;
if
(
tmp
>=
0
)
sg_big_buff
=
tmp
;
return
1
;
}
else
{
printk
(
KERN_WARNING
"sg_def_reserved_size : usage "
"sg_def_reserved_size=n (n could be 65536, 131072 or 262144)
\n
"
);
return
0
;
}
}
__setup
(
"sg_def_reserved_size="
,
sg_def_reserved_size_setup
);
#endif
/* Driverfs file support */
static
ssize_t
sg_device_kdev_read
(
struct
device
*
driverfs_dev
,
char
*
page
)
...
...
@@ -1564,16 +1542,77 @@ sg_detach(Scsi_Device * scsidp)
scsi_sleep
(
2
);
/* dirty detach so delay device destruction */
}
/* Set 'perm' (4th argument) to 0 to disable module_param's definition
* of sysfs parameters (which module_param doesn't yet support).
* Sysfs parameters defined explicitly below.
*/
module_param_named
(
def_reserved_size
,
def_reserved_size
,
int
,
0
);
module_param_named
(
allow_dio
,
sg_allow_dio
,
int
,
0
);
MODULE_AUTHOR
(
"Douglas Gilbert"
);
MODULE_DESCRIPTION
(
"SCSI generic (sg) driver"
);
#ifdef MODULE_LICENSE
MODULE_LICENSE
(
"GPL"
);
#endif
MODULE_PARM
(
def_reserved_size
,
"i"
);
MODULE_PARM_DESC
(
def_reserved_size
,
"size of buffer reserved for each fd"
);
static
ssize_t
sg_allow_dio_show
(
struct
device_driver
*
ddp
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
sg_allow_dio
);
}
static
ssize_t
sg_allow_dio_store
(
struct
device_driver
*
ddp
,
const
char
*
buf
,
size_t
count
)
{
if
(
1
==
sscanf
(
buf
,
"%d"
,
&
sg_allow_dio
))
{
sg_allow_dio
=
sg_allow_dio
?
1
:
0
;
return
count
;
}
return
-
EINVAL
;
}
DRIVER_ATTR
(
allow_dio
,
S_IRUGO
|
S_IWUSR
,
sg_allow_dio_show
,
sg_allow_dio_store
)
static
ssize_t
sg_def_reserved_show
(
struct
device_driver
*
ddp
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%d
\n
"
,
sg_big_buff
);
}
static
ssize_t
sg_def_reserved_store
(
struct
device_driver
*
ddp
,
const
char
*
buf
,
size_t
count
)
{
if
(
1
==
sscanf
(
buf
,
"%d"
,
&
def_reserved_size
))
{
if
(
def_reserved_size
>=
0
)
{
sg_big_buff
=
def_reserved_size
;
return
count
;
}
}
return
-
EINVAL
;
}
DRIVER_ATTR
(
def_reserved_size
,
S_IRUGO
|
S_IWUSR
,
sg_def_reserved_show
,
sg_def_reserved_store
)
static
ssize_t
sg_version_show
(
struct
device_driver
*
ddp
,
char
*
buf
)
{
return
snprintf
(
buf
,
PAGE_SIZE
,
"%s
\n
"
,
sg_version_str
);
}
DRIVER_ATTR
(
version
,
S_IRUGO
,
sg_version_show
,
NULL
)
static
void
do_create_driverfs_files
(
void
)
{
struct
device_driver
*
driverfs
=
&
sg_template
.
scsi_driverfs_driver
;
driver_create_file
(
driverfs
,
&
driver_attr_allow_dio
);
driver_create_file
(
driverfs
,
&
driver_attr_def_reserved_size
);
driver_create_file
(
driverfs
,
&
driver_attr_version
);
}
static
void
do_remove_driverfs_files
(
void
)
{
struct
device_driver
*
driverfs
=
&
sg_template
.
scsi_driverfs_driver
;
driver_remove_file
(
driverfs
,
&
driver_attr_version
);
driver_remove_file
(
driverfs
,
&
driver_attr_def_reserved_size
);
driver_remove_file
(
driverfs
,
&
driver_attr_allow_dio
);
}
static
int
__init
init_sg
(
void
)
{
...
...
@@ -1591,12 +1630,14 @@ init_sg(void)
#ifdef CONFIG_PROC_FS
sg_proc_init
();
#endif
/* CONFIG_PROC_FS */
do_create_driverfs_files
();
return
0
;
}
static
void
__exit
exit_sg
(
void
)
{
do_remove_driverfs_files
();
#ifdef CONFIG_PROC_FS
sg_proc_cleanup
();
#endif
/* CONFIG_PROC_FS */
...
...
@@ -2656,10 +2697,6 @@ sg_get_dev(int dev)
static
struct
proc_dir_entry
*
sg_proc_sgp
=
NULL
;
static
char
sg_proc_sg_dirname
[]
=
"sg"
;
static
const
char
*
sg_proc_leaf_names
[]
=
{
"allow_dio"
,
"def_reserved_size"
,
"debug"
,
"devices"
,
"device_hdr"
,
"device_strs"
,
"hosts"
,
"host_hdr"
,
"host_strs"
,
"version"
};
static
int
sg_proc_adio_read
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
size
,
int
*
eof
,
void
*
data
);
...
...
@@ -2693,13 +2730,21 @@ static int sg_proc_version_read(char *buffer, char **start, off_t offset,
int
size
,
int
*
eof
,
void
*
data
);
static
int
sg_proc_version_info
(
char
*
buffer
,
int
*
len
,
off_t
*
begin
,
off_t
offset
,
int
size
);
static
read_proc_t
*
sg_proc_leaf_reads
[]
=
{
sg_proc_adio_read
,
sg_proc_dressz_read
,
sg_proc_debug_read
,
sg_proc_dev_read
,
sg_proc_devhdr_read
,
sg_proc_devstrs_read
,
sg_proc_version_read
struct
sg_proc_leaf
{
const
char
*
name
;
read_proc_t
*
rf
;
write_proc_t
*
wf
;
};
static
write_proc_t
*
sg_proc_leaf_writes
[]
=
{
sg_proc_adio_write
,
sg_proc_dressz_write
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
static
struct
sg_proc_leaf
sg_proc_leaf_arr
[]
=
{
{
"allow_dio"
,
sg_proc_adio_read
,
sg_proc_adio_write
},
{
"def_reserved_size"
,
sg_proc_dressz_read
,
sg_proc_dressz_write
},
{
"debug"
,
sg_proc_debug_read
,
NULL
},
{
"devices"
,
sg_proc_dev_read
,
NULL
},
{
"device_hdr"
,
sg_proc_devhdr_read
,
NULL
},
{
"device_strs"
,
sg_proc_devstrs_read
,
NULL
},
{
"version"
,
sg_proc_version_read
,
NULL
}
};
#define PRINT_PROC(fmt,args...) \
...
...
@@ -2729,9 +2774,10 @@ static int
sg_proc_init
()
{
int
k
,
mask
;
int
leaves
=
sizeof
(
sg_proc_leaf_
names
)
/
sizeof
(
sg_proc_leaf_names
[
0
]);
int
num_
leaves
=
sizeof
(
sg_proc_leaf_
arr
)
/
sizeof
(
sg_proc_leaf_arr
[
0
]);
struct
proc_dir_entry
*
pdep
;
struct
sg_proc_leaf
*
leaf
;
if
(
!
proc_scsi
)
return
1
;
...
...
@@ -2739,14 +2785,14 @@ sg_proc_init()
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
proc_scsi
);
if
(
!
sg_proc_sgp
)
return
1
;
for
(
k
=
0
;
k
<
leaves
;
++
k
)
{
mask
=
sg_proc_leaf_writes
[
k
]
?
S_IRUGO
|
S_IWUSR
:
S_IRUGO
;
pdep
=
create_proc_entry
(
sg_proc_leaf_names
[
k
]
,
mask
,
sg_proc_sgp
);
for
(
k
=
0
;
k
<
num_
leaves
;
++
k
)
{
leaf
=
&
sg_proc_leaf_arr
[
k
]
;
mask
=
leaf
->
wf
?
S_IRUGO
|
S_IWUSR
:
S_IRUGO
;
pdep
=
create_proc_entry
(
leaf
->
name
,
mask
,
sg_proc_sgp
);
if
(
pdep
)
{
pdep
->
read_proc
=
sg_proc_leaf_reads
[
k
]
;
if
(
sg_proc_leaf_writes
[
k
]
)
pdep
->
write_proc
=
sg_proc_leaf_writes
[
k
]
;
pdep
->
read_proc
=
leaf
->
rf
;
if
(
leaf
->
wf
)
pdep
->
write_proc
=
leaf
->
wf
;
}
}
return
0
;
...
...
@@ -2756,13 +2802,13 @@ static void
sg_proc_cleanup
()
{
int
k
;
int
leaves
=
sizeof
(
sg_proc_leaf_
names
)
/
sizeof
(
sg_proc_leaf_names
[
0
]);
int
num_
leaves
=
sizeof
(
sg_proc_leaf_
arr
)
/
sizeof
(
sg_proc_leaf_arr
[
0
]);
if
((
!
proc_scsi
)
||
(
!
sg_proc_sgp
))
return
;
for
(
k
=
0
;
k
<
leaves
;
++
k
)
remove_proc_entry
(
sg_proc_leaf_
names
[
k
]
,
sg_proc_sgp
);
for
(
k
=
0
;
k
<
num_
leaves
;
++
k
)
remove_proc_entry
(
sg_proc_leaf_
arr
[
k
].
name
,
sg_proc_sgp
);
remove_proc_entry
(
sg_proc_sg_dirname
,
proc_scsi
);
}
...
...
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