summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-04 12:30:30 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-04 12:30:30 -0700
commit84cbd7222b2b00dcddef3103203986b3d59c836a (patch)
treecdbe55ec410f853d4d532ed3252334cb110d5985 /drivers/scsi/sd.c
parent80cc38b16389849a6e06441ace4530f6b2497c3c (diff)
parenta3fda7dd5179989dd0ead820dcebd13f956ddec1 (diff)
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull first round of SCSI updates from James Bottomley: "The patch set is mostly driver updates (usf, zfcp, lpfc, mpt2sas, megaraid_sas, bfa, ipr) and a few bug fixes. Also of note is that the Buslogic driver has been rewritten to a better coding style and 64 bit support added. We also removed the libsas limitation on 16 bytes for the command size (currently no drivers make use of this)" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (101 commits) [SCSI] megaraid: minor cut and paste error fixed. [SCSI] ufshcd-pltfrm: remove unnecessary dma_set_coherent_mask() call [SCSI] ufs: fix register address in UIC error interrupt handling [SCSI] ufshcd-pltfrm: add missing empty slot in ufs_of_match[] [SCSI] ufs: use devres functions for ufshcd [SCSI] ufs: Fix the response UPIU length setting [SCSI] ufs: rework link start-up process [SCSI] ufs: remove version check before IS reg clear [SCSI] ufs: amend interrupt configuration [SCSI] ufs: wrap the i/o access operations [SCSI] storvsc: Update the storage protocol to win8 level [SCSI] storvsc: Increase the value of scsi timeout for storvsc devices [SCSI] MAINTAINERS: Add myself as the maintainer for BusLogic SCSI driver [SCSI] BusLogic: Port driver to 64-bit. [SCSI] BusLogic: Fix style issues [SCSI] libiscsi: Added new boot entries in the session sysfs [SCSI] aacraid: Fix for arrays are going offline in the system. System hangs [SCSI] ipr: IOA Status Code(IOASC) update [SCSI] sd: Update WRITE SAME heuristics [SCSI] fnic: potential dead lock in fnic_is_abts_pending() ...
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r--drivers/scsi/sd.c77
1 files changed, 58 insertions, 19 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8fa3d0b73ad..80f39b8b022 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -142,7 +142,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
char *buffer_data;
struct scsi_mode_data data;
struct scsi_sense_hdr sshdr;
- const char *temp = "temporary ";
+ static const char temp[] = "temporary ";
int len;
if (sdp->type != TYPE_DISK)
@@ -442,8 +442,10 @@ sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
if (max == 0)
sdp->no_write_same = 1;
- else if (max <= SD_MAX_WS16_BLOCKS)
+ else if (max <= SD_MAX_WS16_BLOCKS) {
+ sdp->no_write_same = 0;
sdkp->max_ws_blocks = max;
+ }
sd_config_write_same(sdkp);
@@ -504,6 +506,16 @@ static struct scsi_driver sd_template = {
};
/*
+ * Dummy kobj_map->probe function.
+ * The default ->probe function will call modprobe, which is
+ * pointless as this module is already loaded.
+ */
+static struct kobject *sd_default_probe(dev_t devt, int *partno, void *data)
+{
+ return NULL;
+}
+
+/*
* Device no to disk mapping:
*
* major disc2 disc p1
@@ -740,7 +752,6 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
{
struct request_queue *q = sdkp->disk->queue;
unsigned int logical_block_size = sdkp->device->sector_size;
- unsigned int blocks = 0;
if (sdkp->device->no_write_same) {
sdkp->max_ws_blocks = 0;
@@ -752,18 +763,20 @@ static void sd_config_write_same(struct scsi_disk *sdkp)
* blocks per I/O unless the device explicitly advertises a
* bigger limit.
*/
- if (sdkp->max_ws_blocks == 0)
- sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS;
-
- if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
- blocks = min_not_zero(sdkp->max_ws_blocks,
- (u32)SD_MAX_WS16_BLOCKS);
- else
- blocks = min_not_zero(sdkp->max_ws_blocks,
- (u32)SD_MAX_WS10_BLOCKS);
+ if (sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
+ sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks,
+ (u32)SD_MAX_WS16_BLOCKS);
+ else if (sdkp->ws16 || sdkp->ws10 || sdkp->device->no_report_opcodes)
+ sdkp->max_ws_blocks = min_not_zero(sdkp->max_ws_blocks,
+ (u32)SD_MAX_WS10_BLOCKS);
+ else {
+ sdkp->device->no_write_same = 1;
+ sdkp->max_ws_blocks = 0;
+ }
out:
- blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9));
+ blk_queue_max_write_same_sectors(q, sdkp->max_ws_blocks *
+ (logical_block_size >> 9));
}
/**
@@ -2635,9 +2648,24 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp)
static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
{
- if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE,
- WRITE_SAME_16))
+ struct scsi_device *sdev = sdkp->device;
+
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) {
+ sdev->no_report_opcodes = 1;
+
+ /* Disable WRITE SAME if REPORT SUPPORTED OPERATION
+ * CODES is unsupported and the device has an ATA
+ * Information VPD page (SAT).
+ */
+ if (!scsi_get_vpd_page(sdev, 0x89, buffer, SD_BUF_SIZE))
+ sdev->no_write_same = 1;
+ }
+
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME_16) == 1)
sdkp->ws16 = 1;
+
+ if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, WRITE_SAME) == 1)
+ sdkp->ws10 = 1;
}
static int sd_try_extended_inquiry(struct scsi_device *sdp)
@@ -2970,8 +2998,10 @@ static int sd_probe(struct device *dev)
static int sd_remove(struct device *dev)
{
struct scsi_disk *sdkp;
+ dev_t devt;
sdkp = dev_get_drvdata(dev);
+ devt = disk_devt(sdkp->disk);
scsi_autopm_get_device(sdkp->device);
async_synchronize_full_domain(&scsi_sd_probe_domain);
@@ -2981,6 +3011,9 @@ static int sd_remove(struct device *dev)
del_gendisk(sdkp->disk);
sd_shutdown(dev);
+ blk_register_region(devt, SD_MINORS, NULL,
+ sd_default_probe, NULL, NULL);
+
mutex_lock(&sd_ref_mutex);
dev_set_drvdata(dev, NULL);
put_device(&sdkp->dev);
@@ -3124,9 +3157,13 @@ static int __init init_sd(void)
SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
- for (i = 0; i < SD_MAJORS; i++)
- if (register_blkdev(sd_major(i), "sd") == 0)
- majors++;
+ for (i = 0; i < SD_MAJORS; i++) {
+ if (register_blkdev(sd_major(i), "sd") != 0)
+ continue;
+ majors++;
+ blk_register_region(sd_major(i), SD_MINORS, NULL,
+ sd_default_probe, NULL, NULL);
+ }
if (!majors)
return -ENODEV;
@@ -3185,8 +3222,10 @@ static void __exit exit_sd(void)
class_unregister(&sd_disk_class);
- for (i = 0; i < SD_MAJORS; i++)
+ for (i = 0; i < SD_MAJORS; i++) {
+ blk_unregister_region(sd_major(i), SD_MINORS);
unregister_blkdev(sd_major(i), "sd");
+ }
}
module_init(init_sd);