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
Expand all
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
This diff is collapsed.
Click to expand it.
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