]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/sd.c
[SCSI] sd: fix computation of the full size of the device
[linux-2.6-omap-h63xx.git] / drivers / scsi / sd.c
index e5e7d78564545543925fc6136c6e7c7fc994c028..7ba70bef8b5d03e8f5cd41ab35e2906123381e56 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/blkpg.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
+#include <linux/string_helpers.h>
 #include <asm/uaccess.h>
 
 #include <scsi/scsi.h>
@@ -86,6 +87,12 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK);
 MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD);
 MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 
+#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
+#define SD_MINORS      16
+#else
+#define SD_MINORS      0
+#endif
+
 static int  sd_revalidate_disk(struct gendisk *);
 static int  sd_probe(struct device *);
 static int  sd_remove(struct device *);
@@ -159,7 +166,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr,
                        sd_print_sense_hdr(sdkp, &sshdr);
                return -EINVAL;
        }
-       sd_revalidate_disk(sdkp->disk);
+       revalidate_disk(sdkp->disk);
        return count;
 }
 
@@ -377,8 +384,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
        sector_t block = rq->sector;
        sector_t threshold;
        unsigned int this_count = rq->nr_sectors;
-       unsigned int timeout = sdp->timeout;
-       int ret;
+       int ret, host_dif;
 
        if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
                ret = scsi_setup_blk_pc_cmnd(sdp, rq);
@@ -509,7 +515,8 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
                                        rq->nr_sectors));
 
        /* Set RDPROTECT/WRPROTECT if disk is formatted with DIF */
-       if (scsi_host_dif_capable(sdp->host, sdkp->protection_type))
+       host_dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type);
+       if (host_dif)
                SCpnt->cmnd[1] = 1 << 5;
        else
                SCpnt->cmnd[1] = 0;
@@ -567,8 +574,9 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
        SCpnt->sdb.length = this_count * sdp->sector_size;
 
        /* If DIF or DIX is enabled, tell HBA how to handle request */
-       if (sdkp->protection_type || scsi_prot_sg_count(SCpnt))
-               sd_dif_op(SCpnt, sdkp->protection_type, scsi_prot_sg_count(SCpnt));
+       if (host_dif || scsi_prot_sg_count(SCpnt))
+               sd_dif_op(SCpnt, host_dif, scsi_prot_sg_count(SCpnt),
+                         sdkp->protection_type);
 
        /*
         * We shouldn't disconnect in the middle of a sector, so with a dumb
@@ -578,7 +586,6 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
        SCpnt->transfersize = sdp->sector_size;
        SCpnt->underflow = this_count << 9;
        SCpnt->allowed = SD_MAX_RETRIES;
-       SCpnt->timeout_per_command = timeout;
 
        /*
         * This indicates that the command is ready from our end to be
@@ -910,7 +917,7 @@ static void sd_rescan(struct device *dev)
        struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
 
        if (sdkp) {
-               sd_revalidate_disk(sdkp->disk);
+               revalidate_disk(sdkp->disk);
                scsi_disk_put(sdkp);
        }
 }
@@ -1047,7 +1054,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                good_bytes = sd_completed_bytes(SCpnt);
                break;
        case RECOVERED_ERROR:
-       case NO_SENSE:
                /* Inform the user, but make sure that it's not treated
                 * as a hard error.
                 */
@@ -1056,6 +1062,15 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
                good_bytes = scsi_bufflen(SCpnt);
                break;
+       case NO_SENSE:
+               /* This indicates a false check condition, so ignore it.  An
+                * unknown amount of data was transferred so treat it as an
+                * error.
+                */
+               scsi_print_sense("sd", SCpnt);
+               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);
@@ -1069,15 +1084,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                        scsi_print_sense("sd", SCpnt);
                        good_bytes = sd_completed_bytes(SCpnt);
                }
-               if (!scsi_device_protection(SCpnt->device) &&
-                   SCpnt->device->use_10_for_rw &&
-                   (SCpnt->cmnd[0] == READ_10 ||
-                    SCpnt->cmnd[0] == WRITE_10))
-                       SCpnt->device->use_10_for_rw = 0;
-               if (SCpnt->device->use_10_for_ms &&
-                   (SCpnt->cmnd[0] == MODE_SENSE_10 ||
-                    SCpnt->cmnd[0] == MODE_SELECT_10))
-                       SCpnt->device->use_10_for_ms = 0;
                break;
        default:
                break;
@@ -1247,14 +1253,12 @@ void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer)
        else
                type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
 
+       sdkp->protection_type = type;
+
        switch (type) {
        case SD_DIF_TYPE0_PROTECTION:
-               sdkp->protection_type = 0;
-               break;
-
        case SD_DIF_TYPE1_PROTECTION:
        case SD_DIF_TYPE3_PROTECTION:
-               sdkp->protection_type = type;
                break;
 
        case SD_DIF_TYPE2_PROTECTION:
@@ -1272,7 +1276,6 @@ void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer)
        return;
 
 disable:
-       sdkp->protection_type = 0;
        sdkp->capacity = 0;
 }
 
@@ -1429,27 +1432,21 @@ got_data:
                 */
                sector_size = 512;
        }
+       blk_queue_hardsect_size(sdp->request_queue, sector_size);
+
        {
-               /*
-                * The msdos fs needs to know the hardware sector size
-                * So I have created this table. See ll_rw_blk.c
-                * Jacques Gelinas (Jacques@solucorp.qc.ca)
-                */
-               int hard_sector = sector_size;
-               sector_t sz = (sdkp->capacity/2) * (hard_sector/256);
-               struct request_queue *queue = sdp->request_queue;
-               sector_t mb = sz;
+               char cap_str_2[10], cap_str_10[10];
+               u64 sz = (u64)sdkp->capacity << ilog2(sector_size);
 
-               blk_queue_hardsect_size(queue, hard_sector);
-               /* avoid 64-bit division on 32-bit platforms */
-               sector_div(sz, 625);
-               mb -= sz - 974;
-               sector_div(mb, 1950);
+               string_get_size(sz, STRING_UNITS_2, cap_str_2,
+                               sizeof(cap_str_2));
+               string_get_size(sz, STRING_UNITS_10, cap_str_10,
+                               sizeof(cap_str_10));
 
                sd_printk(KERN_NOTICE, sdkp,
-                         "%llu %d-byte hardware sectors (%llu MB)\n",
+                         "%llu %d-byte hardware sectors: (%s/%s)\n",
                          (unsigned long long)sdkp->capacity,
-                         hard_sector, (unsigned long long)mb);
+                         sector_size, cap_str_10, cap_str_2);
        }
 
        /* Rescale capacity to 512-byte units */
@@ -1763,6 +1760,52 @@ static int sd_revalidate_disk(struct gendisk *disk)
        return 0;
 }
 
+/**
+ *     sd_format_disk_name - format disk name
+ *     @prefix: name prefix - ie. "sd" for SCSI disks
+ *     @index: index of the disk to format name for
+ *     @buf: output buffer
+ *     @buflen: length of the output buffer
+ *
+ *     SCSI disk names starts at sda.  The 26th device is sdz and the
+ *     27th is sdaa.  The last one for two lettered suffix is sdzz
+ *     which is followed by sdaaa.
+ *
+ *     This is basically 26 base counting with one extra 'nil' entry
+ *     at the beggining 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.
+ *
+ *     CONTEXT:
+ *     Don't care.
+ *
+ *     RETURNS:
+ *     0 on success, -errno on failure.
+ */
+static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen)
+{
+       const int base = 'z' - 'a' + 1;
+       char *begin = buf + strlen(prefix);
+       char *end = buf + buflen;
+       char *p;
+       int unit;
+
+       p = end - 1;
+       *p = '\0';
+       unit = base;
+       do {
+               if (p == begin)
+                       return -EINVAL;
+               *--p = 'a' + (index % unit);
+               index = (index / unit) - 1;
+       } while (index >= 0);
+
+       memmove(begin, p, end - p);
+       memcpy(buf, prefix, strlen(prefix));
+
+       return 0;
+}
+
 /**
  *     sd_probe - called during driver initialization and whenever a
  *     new scsi device is attached to the system. It is called once
@@ -1801,7 +1844,7 @@ static int sd_probe(struct device *dev)
        if (!sdkp)
                goto out;
 
-       gd = alloc_disk(16);
+       gd = alloc_disk(SD_MINORS);
        if (!gd)
                goto out_free;
 
@@ -1815,8 +1858,8 @@ static int sd_probe(struct device *dev)
        if (error)
                goto out_put;
 
-       error = -EBUSY;
-       if (index >= SD_MAX_DISKS)
+       error = sd_format_disk_name("sd", index, gd->disk_name, DISK_NAME_LEN);
+       if (error)
                goto out_free_index;
 
        sdkp->device = sdp;
@@ -1826,11 +1869,12 @@ static int sd_probe(struct device *dev)
        sdkp->openers = 0;
        sdkp->previous_state = 1;
 
-       if (!sdp->timeout) {
+       if (!sdp->request_queue->rq_timeout) {
                if (sdp->type != TYPE_MOD)
-                       sdp->timeout = SD_TIMEOUT;
+                       blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT);
                else
-                       sdp->timeout = SD_MOD_TIMEOUT;
+                       blk_queue_rq_timeout(sdp->request_queue,
+                                            SD_MOD_TIMEOUT);
        }
 
        device_initialize(&sdkp->dev);
@@ -1843,24 +1887,12 @@ static int sd_probe(struct device *dev)
 
        get_device(&sdp->sdev_gendev);
 
-       gd->major = sd_major((index & 0xf0) >> 4);
-       gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
-       gd->minors = 16;
-       gd->fops = &sd_fops;
-
-       if (index < 26) {
-               sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
-       } else if (index < (26 + 1) * 26) {
-               sprintf(gd->disk_name, "sd%c%c",
-                       'a' + index / 26 - 1,'a' + index % 26);
-       } else {
-               const unsigned int m1 = (index / 26 - 1) / 26 - 1;
-               const unsigned int m2 = (index / 26 - 1) % 26;
-               const unsigned int m3 =  index % 26;
-               sprintf(gd->disk_name, "sd%c%c%c",
-                       'a' + m1, 'a' + m2, 'a' + m3);
+       if (index < SD_MAX_DISKS) {
+               gd->major = sd_major((index & 0xf0) >> 4);
+               gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
+               gd->minors = SD_MINORS;
        }
-
+       gd->fops = &sd_fops;
        gd->private_data = &sdkp->driver;
        gd->queue = sdkp->device->request_queue;
 
@@ -1869,7 +1901,7 @@ static int sd_probe(struct device *dev)
        blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
 
        gd->driverfs_dev = &sdp->sdev_gendev;
-       gd->flags = GENHD_FL_DRIVERFS;
+       gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS;
        if (sdp->removable)
                gd->flags |= GENHD_FL_REMOVABLE;