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
1b4c4bcb
Commit
1b4c4bcb
authored
Jan 13, 2003
by
James Bottomley
Browse files
Options
Browse Files
Download
Plain Diff
Merge raven.il.steeleye.com:/home/jejb/BK/scsi-misc-2.5
into raven.il.steeleye.com:/home/jejb/BK/scsi-for-linus-2.5
parents
9e535055
52f97cf3
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
166 additions
and
143 deletions
+166
-143
drivers/block/scsi_ioctl.c
drivers/block/scsi_ioctl.c
+29
-13
drivers/scsi/hosts.c
drivers/scsi/hosts.c
+11
-8
drivers/scsi/hosts.h
drivers/scsi/hosts.h
+2
-1
drivers/scsi/scsi_error.c
drivers/scsi/scsi_error.c
+13
-32
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_lib.c
+18
-4
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_sysfs.c
+2
-0
drivers/scsi/sd.c
drivers/scsi/sd.c
+91
-85
No files found.
drivers/block/scsi_ioctl.c
View file @
1b4c4bcb
...
...
@@ -40,6 +40,11 @@ const unsigned char scsi_command_size[8] =
#define BLK_DEFAULT_TIMEOUT (60 * HZ)
/* defined in ../scsi/scsi.h ... should it be included? */
#ifndef SCSI_SENSE_BUFFERSIZE
#define SCSI_SENSE_BUFFERSIZE 64
#endif
int
blk_do_rq
(
request_queue_t
*
q
,
struct
block_device
*
bdev
,
struct
request
*
rq
)
{
DECLARE_COMPLETION
(
wait
);
...
...
@@ -126,11 +131,11 @@ static int sg_io(request_queue_t *q, struct block_device *bdev,
struct
sg_io_hdr
*
uptr
)
{
unsigned
long
uaddr
,
start_time
;
int
err
,
reading
,
writing
,
nr_sectors
;
int
reading
,
writing
,
nr_sectors
;
struct
sg_io_hdr
hdr
;
struct
request
*
rq
;
struct
bio
*
bio
;
char
sense
[
24
];
char
sense
[
SCSI_SENSE_BUFFERSIZE
];
void
*
buffer
;
if
(
!
access_ok
(
VERIFY_WRITE
,
uptr
,
sizeof
(
*
uptr
)))
...
...
@@ -265,26 +270,36 @@ static int sg_io(request_queue_t *q, struct block_device *bdev,
start_time
=
jiffies
;
/*
*
return -EIO if we didn't transfer all data, caller can look at
*
residual count to find out how much did succeed
/*
ignore return value. All information is passed back to caller
*
(if he doesn't check that is his problem).
*
N.B. a non-zero SCSI status is _not_ necessarily an error.
*/
err
=
blk_do_rq
(
q
,
bdev
,
rq
);
if
(
rq
->
data_len
>
0
)
err
=
-
EIO
;
blk_do_rq
(
q
,
bdev
,
rq
);
if
(
bio
)
{
bio_unmap_user
(
bio
,
reading
);
bio_put
(
bio
);
}
/* write to all output members */
hdr
.
status
=
rq
->
errors
;
hdr
.
masked_status
=
(
hdr
.
status
>>
1
)
&
0x1f
;
hdr
.
msg_status
=
0
;
hdr
.
host_status
=
0
;
hdr
.
driver_status
=
0
;
hdr
.
info
=
0
;
if
(
hdr
.
masked_status
||
hdr
.
host_status
||
hdr
.
driver_status
)
hdr
.
info
|=
SG_INFO_CHECK
;
hdr
.
resid
=
rq
->
data_len
;
hdr
.
duration
=
(
jiffies
-
start_time
)
*
(
1000
/
HZ
);
hdr
.
sb_len_wr
=
0
;
if
(
rq
->
sense_len
&&
hdr
.
sbp
)
{
if
(
!
copy_to_user
(
hdr
.
sbp
,
rq
->
sense
,
rq
->
sense_len
))
hdr
.
sb_len_wr
=
rq
->
sense_len
;
int
len
=
(
hdr
.
mx_sb_len
<
rq
->
sense_len
)
?
hdr
.
mx_sb_len
:
rq
->
sense_len
;
if
(
!
copy_to_user
(
hdr
.
sbp
,
rq
->
sense
,
len
))
hdr
.
sb_len_wr
=
len
;
}
blk_put_request
(
rq
);
...
...
@@ -297,8 +312,9 @@ static int sg_io(request_queue_t *q, struct block_device *bdev,
kfree
(
buffer
);
}
return
err
;
/* may not have succeeded, but output values written to control
* structure (struct sg_io_hdr). */
return
0
;
}
#define FORMAT_UNIT_TIMEOUT (2 * 60 * 60 * HZ)
...
...
drivers/scsi/hosts.c
View file @
1b4c4bcb
...
...
@@ -36,6 +36,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/completion.h>
#define __KERNEL_SYSCALLS__
...
...
@@ -314,9 +315,10 @@ int __scsi_add_host(struct Scsi_Host *shost)
**/
int
scsi_add_host
(
struct
Scsi_Host
*
shost
,
struct
device
*
dev
)
{
if
(
dev
)
{
dev
->
class_data
=
shost
;
shost
->
host_gendev
=
dev
;
}
return
__scsi_add_host
(
shost
);
}
...
...
@@ -335,10 +337,11 @@ void scsi_unregister(struct Scsi_Host *shost)
* Next, kill the kernel error recovery thread for this host.
*/
if
(
shost
->
ehandler
)
{
DECLARE_
MUTEX_LOCKED
(
sem
);
DECLARE_
COMPLETION
(
sem
);
shost
->
eh_notify
=
&
sem
;
send_sig
(
SIGHUP
,
shost
->
ehandler
,
1
);
down
(
&
sem
);
shost
->
eh_kill
=
1
;
up
(
shost
->
eh_wait
);
wait_for_completion
(
&
sem
);
shost
->
eh_notify
=
NULL
;
}
...
...
@@ -368,7 +371,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
{
struct
Scsi_Host
*
shost
,
*
shost_scr
;
int
gfp_mask
;
DECLARE_
MUTEX_LOCKED
(
sem
);
DECLARE_
COMPLETION
(
sem
);
/* Check to see if this host has any error handling facilities */
if
(
shost_tp
->
eh_strategy_handler
==
NULL
&&
...
...
@@ -464,7 +467,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template *shost_tp, int xtr_bytes)
* Now wait for the kernel error thread to initialize itself
* as it might be needed when we scan the bus.
*/
dow
n
(
&
sem
);
wait_for_completio
n
(
&
sem
);
shost
->
eh_notify
=
NULL
;
shost
->
hostt
->
present
++
;
...
...
drivers/scsi/hosts.h
View file @
1b4c4bcb
...
...
@@ -381,11 +381,12 @@ struct Scsi_Host
struct
task_struct
*
ehandler
;
/* Error recovery thread. */
struct
semaphore
*
eh_wait
;
/* The error recovery thread waits on
this. */
struct
semaphore
*
eh_notify
;
/* wait for eh to begin
*/
struct
completion
*
eh_notify
;
/* wait for eh to begin or end
*/
struct
semaphore
*
eh_action
;
/* Wait for specific actions on the
host. */
unsigned
int
eh_active
:
1
;
/* Indicates the eh thread is awake and active if
this is true. */
unsigned
int
eh_kill
:
1
;
/* set when killing the eh thread */
wait_queue_head_t
host_wait
;
Scsi_Host_Template
*
hostt
;
atomic_t
host_active
;
/* commands checked out */
...
...
drivers/scsi/scsi_error.c
View file @
1b4c4bcb
...
...
@@ -27,6 +27,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#define __KERNEL_SYSCALLS__
...
...
@@ -41,20 +42,6 @@
#include <scsi/scsi_ioctl.h>
/* grr */
/*
* We must always allow SHUTDOWN_SIGS. Even if we are not a module,
* the host drivers that we are using may be loaded as modules, and
* when we unload these, we need to ensure that the error handler thread
* can be shut down.
*
* Note - when we unload a module, we send a SIGHUP. We mustn't
* enable SIGTERM, as this is how the init shuts things down when you
* go to single-user mode. For that matter, init also sends SIGKILL,
* so we mustn't enable that one either. We use SIGHUP instead. Other
* options would be SIGPWR, I suppose.
*/
#define SHUTDOWN_SIGS (sigmask(SIGHUP))
#ifdef DEBUG
#define SENSE_TIMEOUT SCSI_TIMEOUT
#else
...
...
@@ -1589,12 +1576,10 @@ void scsi_error_handler(void *data)
int
rtn
;
DECLARE_MUTEX_LOCKED
(
sem
);
/*
* We only listen to signals if the HA was loaded as a module.
* If the HA was compiled into the kernel, then we don't listen
* to any signals.
*/
siginitsetinv
(
&
current
->
blocked
,
SHUTDOWN_SIGS
);
spin_lock_irq
(
&
current
->
sig
->
siglock
);
sigfillset
(
&
current
->
blocked
);
recalc_sigpending
();
spin_unlock_irq
(
&
current
->
sig
->
siglock
);
lock_kernel
();
...
...
@@ -1618,9 +1603,9 @@ void scsi_error_handler(void *data)
/*
* Wake up the thread that created us.
*/
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"Wake up parent
\n
"
));
SCSI_LOG_ERROR_RECOVERY
(
3
,
printk
(
"Wake up parent
of scsi_eh_%d
\n
"
,
shost
->
host_no
));
up
(
shost
->
eh_notify
);
complete
(
shost
->
eh_notify
);
while
(
1
)
{
/*
...
...
@@ -1628,7 +1613,7 @@ void scsi_error_handler(void *data)
* away and die. This typically happens if the user is
* trying to unload a module.
*/
SCSI_LOG_ERROR_RECOVERY
(
1
,
printk
(
"Error handler s
leeping
\n
"
));
SCSI_LOG_ERROR_RECOVERY
(
1
,
printk
(
"Error handler s
csi_eh_%d sleeping
\n
"
,
shost
->
host_no
));
/*
* Note - we always use down_interruptible with the semaphore
...
...
@@ -1640,10 +1625,10 @@ void scsi_error_handler(void *data)
* semaphores isn't unreasonable.
*/
down_interruptible
(
&
sem
);
if
(
s
ignal_pending
(
current
)
)
if
(
s
host
->
eh_kill
)
break
;
SCSI_LOG_ERROR_RECOVERY
(
1
,
printk
(
"Error handler
waking up
\n
"
));
SCSI_LOG_ERROR_RECOVERY
(
1
,
printk
(
"Error handler
scsi_eh_%d waking up
\n
"
,
shost
->
host_no
));
shost
->
eh_active
=
1
;
...
...
@@ -1671,7 +1656,7 @@ void scsi_error_handler(void *data)
}
SCSI_LOG_ERROR_RECOVERY
(
1
,
printk
(
"Error handler
exiting
\n
"
));
SCSI_LOG_ERROR_RECOVERY
(
1
,
printk
(
"Error handler
scsi_eh_%d exiting
\n
"
,
shost
->
host_no
));
/*
* Make sure that nobody tries to wake us up again.
...
...
@@ -1691,13 +1676,9 @@ void scsi_error_handler(void *data)
/*
* If anyone is waiting for us to exit (i.e. someone trying to unload
* a driver), then wake up that process to let them know we are on
* the way out the door. This may be overkill - I *think* that we
* could probably just unload the driver and send the signal, and when
* the error handling thread wakes up that it would just exit without
* needing to touch any memory associated with the driver itself.
* the way out the door.
*/
if
(
shost
->
eh_notify
!=
NULL
)
up
(
shost
->
eh_notify
);
complete_and_exit
(
shost
->
eh_notify
,
0
);
}
/**
...
...
drivers/scsi/scsi_lib.c
View file @
1b4c4bcb
...
...
@@ -495,6 +495,7 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
int
this_count
=
SCpnt
->
bufflen
>>
9
;
request_queue_t
*
q
=
SCpnt
->
device
->
request_queue
;
struct
request
*
req
=
SCpnt
->
request
;
int
clear_errors
=
1
;
/*
* We must do one of several things here:
...
...
@@ -528,10 +529,22 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
kfree
(
SCpnt
->
buffer
);
}
if
(
blk_pc_request
(
req
))
{
req
->
errors
=
result
&
0xff
;
if
(
blk_pc_request
(
req
))
{
/* SG_IO ioctl from block level */
req
->
errors
=
(
driver_byte
(
result
)
&
DRIVER_SENSE
)
?
(
CHECK_CONDITION
<<
1
)
:
(
result
&
0xff
);
if
(
!
result
)
req
->
data_len
-=
SCpnt
->
bufflen
;
else
{
clear_errors
=
0
;
if
(
SCpnt
->
sense_buffer
[
0
]
&
0x70
)
{
int
len
=
8
+
SCpnt
->
sense_buffer
[
7
];
if
(
len
>
SCSI_SENSE_BUFFERSIZE
)
len
=
SCSI_SENSE_BUFFERSIZE
;
memcpy
(
req
->
sense
,
SCpnt
->
sense_buffer
,
len
);
req
->
sense_len
=
len
;
}
}
}
/*
...
...
@@ -552,6 +565,7 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
req
->
nr_sectors
,
good_sectors
));
SCSI_LOG_HLCOMPLETE
(
1
,
printk
(
"use_sg is %d
\n
"
,
SCpnt
->
use_sg
));
if
(
clear_errors
)
req
->
errors
=
0
;
/*
* If multiple sectors are requested in one buffer, then
...
...
drivers/scsi/scsi_sysfs.c
View file @
1b4c4bcb
...
...
@@ -213,6 +213,7 @@ sdev_rd_attr (device_blocked, "%d\n");
sdev_rd_attr
(
current_queue_depth
,
"%d
\n
"
);
sdev_rd_attr
(
new_queue_depth
,
"%d
\n
"
);
sdev_rd_attr
(
type
,
"%d
\n
"
);
sdev_rd_attr
(
scsi_level
,
"%d
\n
"
);
sdev_rd_attr
(
access_count
,
"%d
\n
"
);
sdev_rd_attr
(
vendor
,
"%.8s
\n
"
);
sdev_rd_attr
(
model
,
"%.16s
\n
"
);
...
...
@@ -224,6 +225,7 @@ static struct device_attribute * const sdev_attrs[] = {
&
dev_attr_current_queue_depth
,
&
dev_attr_new_queue_depth
,
&
dev_attr_type
,
&
dev_attr_scsi_level
,
&
dev_attr_access_count
,
&
dev_attr_vendor
,
&
dev_attr_model
,
...
...
drivers/scsi/sd.c
View file @
1b4c4bcb
...
...
@@ -79,7 +79,7 @@ struct scsi_disk {
u8
media_present
;
u8
write_prot
;
unsigned
WCE
:
1
;
/* state of disk WCE bit */
unsigned
RCD
:
1
;
/* state of disk RCD bit */
unsigned
RCD
:
1
;
/* state of disk RCD bit
, unused
*/
};
static
LIST_HEAD
(
sd_devlist
);
...
...
@@ -217,7 +217,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
block
=
SCpnt
->
request
->
sector
;
this_count
=
SCpnt
->
request_bufflen
>>
9
;
SCSI_LOG_HLQUEUE
(
1
,
printk
(
"sd_
command_init
: disk=%s, block=%llu, "
SCSI_LOG_HLQUEUE
(
1
,
printk
(
"sd_
init_command
: disk=%s, block=%llu, "
"count=%d
\n
"
,
disk
->
disk_name
,
(
unsigned
long
long
)
block
,
this_count
));
if
(
!
sdp
||
!
sdp
->
online
||
...
...
@@ -809,9 +809,22 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
if
(
media_not_present
(
sdkp
,
SRpnt
))
return
;
/* Look for devices that return NOT_READY.
* Issue command to spin up drive for these cases. */
if
(
the_result
&&
SRpnt
->
sr_sense_buffer
[
2
]
==
NOT_READY
)
{
if
(
the_result
==
0
)
break
;
/* all is well now */
/*
* If manual intervention is required, or this is an
* absent USB storage device, a spinup is meaningless.
*/
if
(
SRpnt
->
sr_sense_buffer
[
2
]
==
NOT_READY
&&
SRpnt
->
sr_sense_buffer
[
12
]
==
4
/* not ready */
&&
SRpnt
->
sr_sense_buffer
[
13
]
==
3
)
break
;
/* manual intervention required */
/*
* Issue command to spin up drive when not ready
*/
if
(
SRpnt
->
sr_sense_buffer
[
2
]
==
NOT_READY
)
{
unsigned
long
time1
;
if
(
!
spintime
)
{
printk
(
KERN_NOTICE
"%s: Spinning up disk..."
,
...
...
@@ -839,7 +852,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
}
while
(
time1
);
printk
(
"."
);
}
}
while
(
the_result
&&
spintime
&&
}
while
(
spintime
&&
time_after
(
spintime_value
+
100
*
HZ
,
jiffies
));
if
(
spintime
)
{
...
...
@@ -850,80 +863,6 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname,
}
}
/*
* sd_read_cache_type - called only from sd_init_onedisk()
*/
static
void
sd_read_cache_type
(
struct
scsi_disk
*
sdkp
,
char
*
diskname
,
struct
scsi_request
*
SRpnt
,
unsigned
char
*
buffer
)
{
unsigned
char
cmd
[
10
];
int
the_result
,
retries
;
retries
=
3
;
do
{
memset
((
void
*
)
&
cmd
[
0
],
0
,
10
);
cmd
[
0
]
=
MODE_SENSE
;
cmd
[
1
]
=
0x08
;
/* DBD */
cmd
[
2
]
=
0x08
;
/* current values, cache page */
cmd
[
4
]
=
128
;
/* allocation length */
memset
((
void
*
)
buffer
,
0
,
24
);
SRpnt
->
sr_cmd_len
=
0
;
SRpnt
->
sr_sense_buffer
[
0
]
=
0
;
SRpnt
->
sr_sense_buffer
[
2
]
=
0
;
SRpnt
->
sr_data_direction
=
SCSI_DATA_READ
;
scsi_wait_req
(
SRpnt
,
(
void
*
)
cmd
,
(
void
*
)
buffer
,
128
,
SD_TIMEOUT
,
SD_MAX_RETRIES
);
the_result
=
SRpnt
->
sr_result
;
retries
--
;
}
while
(
the_result
&&
retries
);
if
(
the_result
)
{
if
(
status_byte
(
the_result
)
==
CHECK_CONDITION
&&
(
SRpnt
->
sr_sense_buffer
[
0
]
&
0x70
)
==
0x70
&&
(
SRpnt
->
sr_sense_buffer
[
2
]
&
0x0f
)
==
ILLEGAL_REQUEST
/* The next are ASC 0x24 ASCQ 0x00: Invalid field in CDB */
&&
SRpnt
->
sr_sense_buffer
[
12
]
==
0x24
&&
SRpnt
->
sr_sense_buffer
[
13
]
==
0x00
)
{
printk
(
KERN_NOTICE
"SCSI device %s: cache data unavailable
\n
"
,
diskname
);
}
else
{
printk
(
KERN_ERR
"%s : MODE SENSE failed.
\n
"
"%s : status = %x, message = %02x, host = %d, driver = %02x
\n
"
,
diskname
,
diskname
,
status_byte
(
the_result
),
msg_byte
(
the_result
),
host_byte
(
the_result
),
driver_byte
(
the_result
)
);
if
(
driver_byte
(
the_result
)
&
DRIVER_SENSE
)
print_req_sense
(
"sd"
,
SRpnt
);
else
printk
(
KERN_ERR
"%s : sense not available.
\n
"
,
diskname
);
printk
(
KERN_ERR
"%s : assuming drive cache: write through
\n
"
,
diskname
);
}
sdkp
->
WCE
=
0
;
sdkp
->
RCD
=
0
;
}
else
{
const
char
*
types
[]
=
{
"write through"
,
"none"
,
"write back"
,
"write back, no read (daft)"
};
int
ct
=
0
;
int
offset
=
buffer
[
3
]
+
4
;
/* offset to start of mode page */
sdkp
->
WCE
=
(
buffer
[
offset
+
2
]
&
0x04
)
==
0x04
;
sdkp
->
RCD
=
(
buffer
[
offset
+
2
]
&
0x01
)
==
0x01
;
ct
=
sdkp
->
RCD
+
2
*
sdkp
->
WCE
;
printk
(
KERN_NOTICE
"SCSI device %s: drive cache: %s
\n
"
,
diskname
,
types
[
ct
]);
}
}
/*
* read disk capacity - called only in sd_init_onedisk()
*/
...
...
@@ -1102,11 +1041,12 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
static
int
sd_do_mode_sense6
(
struct
scsi_device
*
sdp
,
struct
scsi_request
*
SRpnt
,
int
modepage
,
unsigned
char
*
buffer
,
int
len
)
{
int
dbd
,
int
modepage
,
unsigned
char
*
buffer
,
int
len
)
{
unsigned
char
cmd
[
8
];
memset
((
void
*
)
&
cmd
[
0
],
0
,
8
);
cmd
[
0
]
=
MODE_SENSE
;
cmd
[
1
]
=
dbd
;
cmd
[
2
]
=
modepage
;
cmd
[
4
]
=
len
;
...
...
@@ -1115,6 +1055,8 @@ sd_do_mode_sense6(struct scsi_device *sdp, struct scsi_request *SRpnt,
SRpnt
->
sr_sense_buffer
[
2
]
=
0
;
SRpnt
->
sr_data_direction
=
SCSI_DATA_READ
;
memset
((
void
*
)
buffer
,
0
,
len
);
scsi_wait_req
(
SRpnt
,
(
void
*
)
cmd
,
(
void
*
)
buffer
,
len
,
SD_TIMEOUT
,
SD_MAX_RETRIES
);
...
...
@@ -1135,7 +1077,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
* We have to start carefully: some devices hang if we ask
* for more than is available.
*/
res
=
sd_do_mode_sense6
(
sdp
,
SRpnt
,
0x3F
,
buffer
,
4
);
res
=
sd_do_mode_sense6
(
sdp
,
SRpnt
,
0
,
0
x3F
,
buffer
,
4
);
/*
* Second attempt: ask for page 0
...
...
@@ -1143,13 +1085,13 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
* Sense Key 5: Illegal Request, Sense Code 24: Invalid field in CDB.
*/
if
(
res
)
res
=
sd_do_mode_sense6
(
sdp
,
SRpnt
,
0
,
buffer
,
4
);
res
=
sd_do_mode_sense6
(
sdp
,
SRpnt
,
0
,
0
,
buffer
,
4
);
/*
* Third attempt: ask 255 bytes, as we did earlier.
*/
if
(
res
)
res
=
sd_do_mode_sense6
(
sdp
,
SRpnt
,
0x3F
,
buffer
,
255
);
res
=
sd_do_mode_sense6
(
sdp
,
SRpnt
,
0
,
0
x3F
,
buffer
,
255
);
if
(
res
)
{
printk
(
KERN_WARNING
...
...
@@ -1163,6 +1105,65 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
}
}
/*
* sd_read_cache_type - called only from sd_init_onedisk()
*/
static
void
sd_read_cache_type
(
struct
scsi_disk
*
sdkp
,
char
*
diskname
,
struct
scsi_request
*
SRpnt
,
unsigned
char
*
buffer
)
{
struct
scsi_device
*
sdp
=
sdkp
->
device
;
int
len
=
0
,
res
;
const
int
dbd
=
0x08
;
/* DBD */
const
int
modepage
=
0x08
;
/* current values, cache page */
/* cautiously ask */
res
=
sd_do_mode_sense6
(
sdp
,
SRpnt
,
dbd
,
modepage
,
buffer
,
4
);
if
(
res
==
0
)
{
/* that went OK, now ask for the proper length */
len
=
buffer
[
0
]
+
1
;
if
(
len
>
128
)
len
=
128
;
res
=
sd_do_mode_sense6
(
sdp
,
SRpnt
,
dbd
,
modepage
,
buffer
,
len
);
}
if
(
res
==
0
&&
buffer
[
3
]
+
6
<
len
)
{
const
char
*
types
[]
=
{
"write through"
,
"none"
,
"write back"
,
"write back, no read (daft)"
};
int
ct
=
0
;
int
offset
=
buffer
[
3
]
+
4
;
/* start of mode page */
sdkp
->
WCE
=
((
buffer
[
offset
+
2
]
&
0x04
)
!=
0
);
sdkp
->
RCD
=
((
buffer
[
offset
+
2
]
&
0x01
)
!=
0
);
ct
=
sdkp
->
RCD
+
2
*
sdkp
->
WCE
;
printk
(
KERN_NOTICE
"SCSI device %s: drive cache: %s
\n
"
,
diskname
,
types
[
ct
]);
}
else
{
if
(
res
==
0
||
(
status_byte
(
res
)
==
CHECK_CONDITION
&&
(
SRpnt
->
sr_sense_buffer
[
0
]
&
0x70
)
==
0x70
&&
(
SRpnt
->
sr_sense_buffer
[
2
]
&
0x0f
)
==
ILLEGAL_REQUEST
/* ASC 0x24 ASCQ 0x00: Invalid field in CDB */
&&
SRpnt
->
sr_sense_buffer
[
12
]
==
0x24
&&
SRpnt
->
sr_sense_buffer
[
13
]
==
0x00
))
{
printk
(
KERN_NOTICE
"%s: cache data unavailable
\n
"
,
diskname
);
}
else
{
printk
(
KERN_ERR
"%s: asking for cache data failed
\n
"
,
diskname
);
}
printk
(
KERN_ERR
"%s: assuming drive cache: write through
\n
"
,
diskname
);
sdkp
->
WCE
=
0
;
sdkp
->
RCD
=
0
;
}
}
/**
* sd_init_onedisk - called the first time a new disk is seen,
* performs disk spin up, read_capacity, etc.
...
...
@@ -1208,15 +1209,20 @@ sd_init_onedisk(struct scsi_disk * sdkp, struct gendisk *disk)
sdkp
->
device
->
sector_size
=
512
;
sdkp
->
media_present
=
1
;
sdkp
->
write_prot
=
0
;
sdkp
->
WCE
=
0
;
sdkp
->
RCD
=
0
;
sd_spinup_disk
(
sdkp
,
disk
->
disk_name
,
SRpnt
,
buffer
);
sd_read_cache_type
(
sdkp
,
disk
->
disk_name
,
SRpnt
,
buffer
);
if
(
sdkp
->
media_present
)
sd_read_capacity
(
sdkp
,
disk
->
disk_name
,
SRpnt
,
buffer
);
if
(
sdp
->
removable
&&
sdkp
->
media_present
)
sd_read_write_protect_flag
(
sdkp
,
disk
->
disk_name
,
SRpnt
,
buffer
);
/* without media there is no reason to ask;
moreover, some devices react badly if we do */
if
(
sdkp
->
media_present
)
sd_read_cache_type
(
sdkp
,
disk
->
disk_name
,
SRpnt
,
buffer
);
SRpnt
->
sr_device
->
ten
=
1
;
SRpnt
->
sr_device
->
remap
=
1
;
...
...
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