Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
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