git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
[SCSI] Merge scsi-misc-2.6 into scsi-rc-fixes-2.6
[safe/jmp/linux-2.6]
/
drivers
/
scsi
/
sd.c
diff --git
a/drivers/scsi/sd.c
b/drivers/scsi/sd.c
index
255da53
..
829cc37
100644
(file)
--- a/
drivers/scsi/sd.c
+++ b/
drivers/scsi/sd.c
@@
-49,6
+49,7
@@
#include <linux/mutex.h>
#include <linux/string_helpers.h>
#include <linux/async.h>
#include <linux/mutex.h>
#include <linux/string_helpers.h>
#include <linux/async.h>
+#include <linux/slab.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
@@
-1039,6
+1040,7
@@
static void sd_prepare_flush(struct request_queue *q, struct request *rq)
{
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->timeout = SD_TIMEOUT;
{
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->timeout = SD_TIMEOUT;
+ rq->retries = SD_MAX_RETRIES;
rq->cmd[0] = SYNCHRONIZE_CACHE;
rq->cmd_len = 10;
}
rq->cmd[0] = SYNCHRONIZE_CACHE;
rq->cmd_len = 10;
}
@@
-1196,19
+1198,10
@@
static int sd_done(struct scsi_cmnd *SCpnt)
SCpnt->result = 0;
memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
break;
SCpnt->result = 0;
memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
break;
- case ABORTED_COMMAND:
- if (sshdr.asc == 0x10) { /* DIF: Disk detected corruption */
- scsi_print_result(SCpnt);
- scsi_print_sense("sd", SCpnt);
+ case ABORTED_COMMAND: /* DIF: Target detected corruption */
+ case ILLEGAL_REQUEST: /* DIX: Host detected corruption */
+ if (sshdr.asc == 0x10)
good_bytes = sd_completed_bytes(SCpnt);
good_bytes = sd_completed_bytes(SCpnt);
- }
- break;
- case ILLEGAL_REQUEST:
- if (sshdr.asc == 0x10) { /* DIX: HBA detected corruption */
- scsi_print_result(SCpnt);
- scsi_print_sense("sd", SCpnt);
- good_bytes = sd_completed_bytes(SCpnt);
- }
break;
default:
break;
break;
default:
break;
@@
-1218,8
+1211,19
@@
static int sd_done(struct scsi_cmnd *SCpnt)
sd_dif_complete(SCpnt, good_bytes);
if (scsi_host_dif_capable(sdkp->device->host, sdkp->protection_type)
sd_dif_complete(SCpnt, good_bytes);
if (scsi_host_dif_capable(sdkp->device->host, sdkp->protection_type)
- == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd)
+ == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd) {
+
+ /* We have to print a failed command here as the
+ * extended CDB gets freed before scsi_io_completion()
+ * is called.
+ */
+ if (result)
+ scsi_print_command(SCpnt);
+
mempool_free(SCpnt->cmnd, sd_cdb_pool);
mempool_free(SCpnt->cmnd, sd_cdb_pool);
+ SCpnt->cmnd = NULL;
+ SCpnt->cmd_len = 0;
+ }
return good_bytes;
}
return good_bytes;
}
@@
-1430,6
+1434,8
@@
static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
#error RC16_LEN must not be more than SD_BUF_SIZE
#endif
#error RC16_LEN must not be more than SD_BUF_SIZE
#endif
+#define READ_CAPACITY_RETRIES_ON_RESET 10
+
static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
unsigned char *buffer)
{
static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
unsigned char *buffer)
{
@@
-1437,7
+1443,7
@@
static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
int the_result;
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
int the_result;
- int retries = 3;
+ int retries = 3
, reset_retries = READ_CAPACITY_RETRIES_ON_RESET
;
unsigned int alignment;
unsigned long long lba;
unsigned sector_size;
unsigned int alignment;
unsigned long long lba;
unsigned sector_size;
@@
-1466,6
+1472,13
@@
static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
* Invalid Field in CDB, just retry
* silently with RC10 */
return -EINVAL;
* Invalid Field in CDB, just retry
* silently with RC10 */
return -EINVAL;
+ if (sense_valid &&
+ sshdr.sense_key == UNIT_ATTENTION &&
+ sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+ /* Device reset might occur several times,
+ * give it one more chance */
+ if (--reset_retries > 0)
+ continue;
}
retries--;
}
retries--;
@@
-1524,7
+1537,7
@@
static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
int the_result;
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
int the_result;
- int retries = 3;
+ int retries = 3
, reset_retries = READ_CAPACITY_RETRIES_ON_RESET
;
sector_t lba;
unsigned sector_size;
sector_t lba;
unsigned sector_size;
@@
-1540,8
+1553,16
@@
static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
if (media_not_present(sdkp, &sshdr))
return -ENODEV;
if (media_not_present(sdkp, &sshdr))
return -ENODEV;
- if (the_result)
+ if (the_result)
{
sense_valid = scsi_sense_valid(&sshdr);
sense_valid = scsi_sense_valid(&sshdr);
+ if (sense_valid &&
+ sshdr.sense_key == UNIT_ATTENTION &&
+ sshdr.asc == 0x29 && sshdr.ascq == 0x00)
+ /* Device reset might occur several times,
+ * give it one more chance */
+ if (--reset_retries > 0)
+ continue;
+ }
retries--;
} while (the_result && retries);
retries--;
} while (the_result && retries);
@@
-1570,6
+1591,8
@@
static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
static int sd_try_rc16_first(struct scsi_device *sdp)
{
static int sd_try_rc16_first(struct scsi_device *sdp)
{
+ if (sdp->host->max_cmd_len < 16)
+ return 0;
if (sdp->scsi_level > SCSI_SPC_2)
return 1;
if (scsi_device_protection(sdp))
if (sdp->scsi_level > SCSI_SPC_2)
return 1;
if (scsi_device_protection(sdp))
@@
-1946,13
+1969,13
@@
static void sd_read_block_limits(struct scsi_disk *sdkp)
{
struct request_queue *q = sdkp->disk->queue;
unsigned int sector_sz = sdkp->device->sector_size;
{
struct request_queue *q = sdkp->disk->queue;
unsigned int sector_sz = sdkp->device->sector_size;
- char *buffer;
+ const int vpd_len = 64;
+ unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
- /* Block Limits VPD */
- buffer = scsi_get_vpd_page(sdkp->device, 0xb0);
-
- if (buffer == NULL)
- return;
+ if (!buffer ||
+ /* Block Limits VPD */
+ scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len))
+ goto out;
blk_queue_io_min(sdkp->disk->queue,
get_unaligned_be16(&buffer[6]) * sector_sz);
blk_queue_io_min(sdkp->disk->queue,
get_unaligned_be16(&buffer[6]) * sector_sz);
@@
-1984,6
+2007,7
@@
static void sd_read_block_limits(struct scsi_disk *sdkp)
get_unaligned_be32(&buffer[32]) & ~(1 << 31);
}
get_unaligned_be32(&buffer[32]) & ~(1 << 31);
}
+ out:
kfree(buffer);
}
kfree(buffer);
}
@@
-1993,20
+2017,23
@@
static void sd_read_block_limits(struct scsi_disk *sdkp)
*/
static void sd_read_block_characteristics(struct scsi_disk *sdkp)
{
*/
static void sd_read_block_characteristics(struct scsi_disk *sdkp)
{
- char *buffer;
+
unsigned
char *buffer;
u16 rot;
u16 rot;
+ const int vpd_len = 64;
- /* Block Device Characteristics VPD */
- buffer = scsi_get_vpd_page(sdkp->device, 0xb1);
+ buffer = kmalloc(vpd_len, GFP_KERNEL);
- if (buffer == NULL)
- return;
+ if (!buffer ||
+ /* Block Device Characteristics VPD */
+ scsi_get_vpd_page(sdkp->device, 0xb1, buffer, vpd_len))
+ goto out;
rot = get_unaligned_be16(&buffer[4]);
if (rot == 1)
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, sdkp->disk->queue);
rot = get_unaligned_be16(&buffer[4]);
if (rot == 1)
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, sdkp->disk->queue);
+ out:
kfree(buffer);
}
kfree(buffer);
}
@@
-2105,7
+2132,7
@@
static int sd_revalidate_disk(struct gendisk *disk)
* which is followed by sdaaa.
*
* This is basically 26 base counting with one extra 'nil' entry
* which is followed by sdaaa.
*
* This is basically 26 base counting with one extra 'nil' entry
- * at the beg
gi
ning from the second digit on and can be
+ * at the beg
in
ning from the second digit on and can be
* determined using similar method as 26 base conversion with the
* index shifted -1 after each digit is computed.
*
* determined using similar method as 26 base conversion with the
* index shifted -1 after each digit is computed.
*
@@
-2179,7
+2206,7
@@
static void sd_probe_async(void *data, async_cookie_t cookie)
blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
gd->driverfs_dev = &sdp->sdev_gendev;
blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
gd->driverfs_dev = &sdp->sdev_gendev;
- gd->flags = GENHD_FL_EXT_DEVT
| GENHD_FL_DRIVERFS
;
+ gd->flags = GENHD_FL_EXT_DEVT;
if (sdp->removable)
gd->flags |= GENHD_FL_REMOVABLE;
if (sdp->removable)
gd->flags |= GENHD_FL_REMOVABLE;