Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
a2cf79d1
Commit
a2cf79d1
authored
Mar 16, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://linux-scsi.bkbits.net/scsi-for-linus-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
5d6893e6
384cce6d
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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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 @
a2cf79d1
...
...
@@ -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