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
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
Hide 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
);
}
hdr
.
status
=
rq
->
errors
;
/* 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
)
{
dev
->
class_data
=
shost
;
shost
->
host_gendev
=
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
(
!
result
)
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,7 +565,8 @@ 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
));
req
->
errors
=
0
;
if
(
clear_errors
)
req
->
errors
=
0
;
/*
* If multiple sectors are requested in one buffer, then
* they will have been finished off by the first command.
...
...
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