Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Oct 2008 17:53:26 +0000 (10:53 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Oct 2008 17:53:26 +0000 (10:53 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (37 commits)
  [SCSI] zfcp: fix double dbf id usage
  [SCSI] zfcp: wait on SCSI work to be finished before proceeding with init dev
  [SCSI] zfcp: fix erp list usage without using locks
  [SCSI] zfcp: prevent fc_remote_port_delete calls for unregistered rport
  [SCSI] zfcp: fix deadlock caused by shared work queue tasks
  [SCSI] zfcp: put threshold data in hba trace
  [SCSI] zfcp: Simplify zfcp data structures
  [SCSI] zfcp: Simplify get_adapter_by_busid
  [SCSI] zfcp: remove all typedefs and replace them with standards
  [SCSI] zfcp: attach and release SAN nameserver port on demand
  [SCSI] zfcp: remove unused references, declarations and flags
  [SCSI] zfcp: Update message with input from review
  [SCSI] zfcp: add queue_full sysfs attribute
  [SCSI] scsi_dh: suppress comparison warning
  [SCSI] scsi_dh: add Dell product information into rdac device handler
  [SCSI] qla2xxx: remove the unused SCSI_QLOGIC_FC_FIRMWARE option
  [SCSI] qla2xxx: fix printk format warnings
  [SCSI] qla2xxx: Update version number to 8.02.01-k8.
  [SCSI] qla2xxx: Ignore payload reserved-bits during RSCN processing.
  [SCSI] qla2xxx: Additional residual-count corrections during UNDERRUN handling.
  ...

1  2 
drivers/mmc/card/block.c
drivers/scsi/libiscsi.c
drivers/scsi/scsi.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_tgt_lib.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/sd.c

diff --combined drivers/mmc/card/block.c
@@@ -29,6 -29,7 +29,7 @@@
  #include <linux/blkdev.h>
  #include <linux/mutex.h>
  #include <linux/scatterlist.h>
+ #include <linux/string_helpers.h>
  
  #include <linux/mmc/card.h>
  #include <linux/mmc/host.h>
@@@ -83,7 -84,7 +84,7 @@@ static void mmc_blk_put(struct mmc_blk_
        mutex_lock(&open_lock);
        md->usage--;
        if (md->usage == 0) {
 -              int devidx = md->disk->first_minor >> MMC_SHIFT;
 +              int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT;
                __clear_bit(devidx, dev_use);
  
                put_disk(md->disk);
@@@ -532,6 -533,8 +533,8 @@@ static int mmc_blk_probe(struct mmc_car
        struct mmc_blk_data *md;
        int err;
  
+       char cap_str[10];
        /*
         * Check that the card supports the command class(es) we need.
         */
        if (err)
                goto out;
  
-       printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
+       string_get_size(get_capacity(md->disk) << 9, STRING_UNITS_2,
+                       cap_str, sizeof(cap_str));
+       printk(KERN_INFO "%s: %s %s %s %s\n",
                md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
-               (unsigned long long)(get_capacity(md->disk) >> 1),
-               md->read_only ? "(ro)" : "");
+               cap_str, md->read_only ? "(ro)" : "");
  
        mmc_set_drvdata(card, md);
        add_disk(md->disk);
diff --combined drivers/scsi/libiscsi.c
@@@ -1456,7 -1456,7 +1456,7 @@@ static void fail_all_commands(struct is
                if (lun == task->sc->device->lun || lun == -1) {
                        debug_scsi("failing in progress sc %p itt 0x%x\n",
                                   task->sc, task->itt);
-                       fail_command(conn, task, DID_BUS_BUSY << 16);
+                       fail_command(conn, task, error << 16);
                }
        }
  }
@@@ -1476,12 -1476,12 +1476,12 @@@ static void iscsi_start_tx(struct iscsi
                scsi_queue_work(conn->session->host, &conn->xmitwork);
  }
  
 -static enum scsi_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
 +static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
  {
        struct iscsi_cls_session *cls_session;
        struct iscsi_session *session;
        struct iscsi_conn *conn;
 -      enum scsi_eh_timer_return rc = EH_NOT_HANDLED;
 +      enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
  
        cls_session = starget_to_session(scsi_target(scmd->device));
        session = cls_session->dd_data;
                 * We are probably in the middle of iscsi recovery so let
                 * that complete and handle the error.
                 */
 -              rc = EH_RESET_TIMER;
 +              rc = BLK_EH_RESET_TIMER;
                goto done;
        }
  
        conn = session->leadconn;
        if (!conn) {
                /* In the middle of shuting down */
 -              rc = EH_RESET_TIMER;
 +              rc = BLK_EH_RESET_TIMER;
                goto done;
        }
  
         */
        if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
                            (conn->ping_timeout * HZ), jiffies))
 -              rc = EH_RESET_TIMER;
 +              rc = BLK_EH_RESET_TIMER;
        /*
         * if we are about to check the transport then give the command
         * more time
         */
        if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ),
                           jiffies))
 -              rc = EH_RESET_TIMER;
 +              rc = BLK_EH_RESET_TIMER;
        /* if in the middle of checking the transport then give us more time */
        if (conn->ping_task)
 -              rc = EH_RESET_TIMER;
 +              rc = BLK_EH_RESET_TIMER;
  done:
        spin_unlock(&session->lock);
 -      debug_scsi("return %s\n", rc == EH_RESET_TIMER ? "timer reset" : "nh");
 +      debug_scsi("return %s\n", rc == BLK_EH_RESET_TIMER ?
 +                                      "timer reset" : "nh");
        return rc;
  }
  
diff --combined drivers/scsi/scsi.c
@@@ -291,6 -291,7 +291,6 @@@ struct scsi_cmnd *scsi_get_command(stru
                unsigned long flags;
  
                cmd->device = dev;
 -              init_timer(&cmd->eh_timeout);
                INIT_LIST_HEAD(&cmd->list);
                spin_lock_irqsave(&dev->list_lock, flags);
                list_add_tail(&cmd->list, &dev->cmd_list);
@@@ -651,32 -652,27 +651,33 @@@ int scsi_dispatch_cmd(struct scsi_cmnd 
        unsigned long timeout;
        int rtn = 0;
  
 +      /*
 +       * We will use a queued command if possible, otherwise we will
 +       * emulate the queuing and calling of completion function ourselves.
 +       */
 +      atomic_inc(&cmd->device->iorequest_cnt);
 +
        /* check if the device is still usable */
        if (unlikely(cmd->device->sdev_state == SDEV_DEL)) {
                /* in SDEV_DEL we error all commands. DID_NO_CONNECT
                 * returns an immediate error upwards, and signals
                 * that the device is no longer present */
                cmd->result = DID_NO_CONNECT << 16;
 -              atomic_inc(&cmd->device->iorequest_cnt);
 -              __scsi_done(cmd);
 +              scsi_done(cmd);
                /* return 0 (because the command has been processed) */
                goto out;
        }
  
-       /* Check to see if the scsi lld put this device into state SDEV_BLOCK. */
-       if (unlikely(cmd->device->sdev_state == SDEV_BLOCK)) {
+       /* Check to see if the scsi lld made this device blocked. */
+       if (unlikely(scsi_device_blocked(cmd->device))) {
                /* 
-                * in SDEV_BLOCK, the command is just put back on the device
-                * queue.  The suspend state has already blocked the queue so
-                * future requests should not occur until the device 
-                * transitions out of the suspend state.
+                * in blocked state, the command is just put back on
+                * the device queue.  The suspend state has already
+                * blocked the queue so future requests should not
+                * occur until the device transitions out of the
+                * suspend state.
                 */
 +
                scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
  
                SCSI_LOG_MLQUEUE(3, printk("queuecommand : device blocked \n"));
                host->resetting = 0;
        }
  
 -      /* 
 -       * AK: unlikely race here: for some reason the timer could
 -       * expire before the serial number is set up below.
 -       */
 -      scsi_add_timer(cmd, cmd->timeout_per_command, scsi_times_out);
 -
        scsi_log_send(cmd);
  
 -      /*
 -       * We will use a queued command if possible, otherwise we will
 -       * emulate the queuing and calling of completion function ourselves.
 -       */
 -      atomic_inc(&cmd->device->iorequest_cnt);
 -
        /*
         * Before we queue this command, check if the command
         * length exceeds what the host adapter can handle.
        }
  
        spin_lock_irqsave(host->host_lock, flags);
 +      /*
 +       * AK: unlikely race here: for some reason the timer could
 +       * expire before the serial number is set up below.
 +       *
 +       * TODO: kill serial or move to blk layer
 +       */
        scsi_cmd_get_serial(host, cmd); 
  
        if (unlikely(host->shost_state == SHOST_DEL)) {
        }
        spin_unlock_irqrestore(host->host_lock, flags);
        if (rtn) {
 -              if (scsi_delete_timer(cmd)) {
 -                      atomic_inc(&cmd->device->iodone_cnt);
 -                      scsi_queue_insert(cmd,
 -                                        (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
 -                                        rtn : SCSI_MLQUEUE_HOST_BUSY);
 -              }
 +              scsi_queue_insert(cmd, (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
 +                                              rtn : SCSI_MLQUEUE_HOST_BUSY);
                SCSI_LOG_MLQUEUE(3,
                    printk("queuecommand : request rejected\n"));
        }
        return rtn;
  }
  
 -/**
 - * scsi_req_abort_cmd -- Request command recovery for the specified command
 - * @cmd: pointer to the SCSI command of interest
 - *
 - * This function requests that SCSI Core start recovery for the
 - * command by deleting the timer and adding the command to the eh
 - * queue.  It can be called by either LLDDs or SCSI Core.  LLDDs who
 - * implement their own error recovery MAY ignore the timeout event if
 - * they generated scsi_req_abort_cmd.
 - */
 -void scsi_req_abort_cmd(struct scsi_cmnd *cmd)
 -{
 -      if (!scsi_delete_timer(cmd))
 -              return;
 -      scsi_times_out(cmd);
 -}
 -EXPORT_SYMBOL(scsi_req_abort_cmd);
 -
  /**
   * scsi_done - Enqueue the finished SCSI command into the done queue.
   * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
   */
  static void scsi_done(struct scsi_cmnd *cmd)
  {
 -      /*
 -       * We don't have to worry about this one timing out anymore.
 -       * If we are unable to remove the timer, then the command
 -       * has already timed out.  In which case, we have no choice but to
 -       * let the timeout function run, as we have no idea where in fact
 -       * that function could really be.  It might be on another processor,
 -       * etc, etc.
 -       */
 -      if (!scsi_delete_timer(cmd))
 -              return;
 -      __scsi_done(cmd);
 -}
 -
 -/* Private entry to scsi_done() to complete a command when the timer
 - * isn't running --- used by scsi_times_out */
 -void __scsi_done(struct scsi_cmnd *cmd)
 -{
 -      struct request *rq = cmd->request;
 -
 -      /*
 -       * Set the serial numbers back to zero
 -       */
 -      cmd->serial_number = 0;
 -
 -      atomic_inc(&cmd->device->iodone_cnt);
 -      if (cmd->result)
 -              atomic_inc(&cmd->device->ioerr_cnt);
 -
 -      BUG_ON(!rq);
 -
 -      /*
 -       * The uptodate/nbytes values don't matter, as we allow partial
 -       * completes and thus will check this in the softirq callback
 -       */
 -      rq->completion_data = cmd;
 -      blk_complete_request(rq);
 +      blk_complete_request(cmd->request);
  }
  
  /* Move this to a header if it becomes more generally useful */
diff --combined drivers/scsi/scsi_lib.c
@@@ -1181,6 -1181,7 +1181,6 @@@ int scsi_setup_blk_pc_cmnd(struct scsi_
        
        cmd->transfersize = req->data_len;
        cmd->allowed = req->retries;
 -      cmd->timeout_per_command = req->timeout;
        return BLKPREP_OK;
  }
  EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd);
@@@ -1250,6 -1251,7 +1250,7 @@@ int scsi_prep_state_check(struct scsi_d
                        break;
                case SDEV_QUIESCE:
                case SDEV_BLOCK:
+               case SDEV_CREATED_BLOCK:
                        /*
                         * If the devices is blocked we defer normal commands.
                         */
@@@ -1415,26 -1417,17 +1416,26 @@@ static void scsi_kill_request(struct re
        spin_unlock(shost->host_lock);
        spin_lock(sdev->request_queue->queue_lock);
  
 -      __scsi_done(cmd);
 +      blk_complete_request(req);
  }
  
  static void scsi_softirq_done(struct request *rq)
  {
 -      struct scsi_cmnd *cmd = rq->completion_data;
 -      unsigned long wait_for = (cmd->allowed + 1) * cmd->timeout_per_command;
 +      struct scsi_cmnd *cmd = rq->special;
 +      unsigned long wait_for = (cmd->allowed + 1) * rq->timeout;
        int disposition;
  
        INIT_LIST_HEAD(&cmd->eh_entry);
  
 +      /*
 +       * Set the serial numbers back to zero
 +       */
 +      cmd->serial_number = 0;
 +
 +      atomic_inc(&cmd->device->iodone_cnt);
 +      if (cmd->result)
 +              atomic_inc(&cmd->device->ioerr_cnt);
 +
        disposition = scsi_decide_disposition(cmd);
        if (disposition != SUCCESS &&
            time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
@@@ -1683,7 -1676,6 +1684,7 @@@ struct request_queue *scsi_alloc_queue(
  
        blk_queue_prep_rq(q, scsi_prep_fn);
        blk_queue_softirq_done(q, scsi_softirq_done);
 +      blk_queue_rq_timed_out(q, scsi_times_out);
        return q;
  }
  
@@@ -2073,10 -2065,13 +2074,13 @@@ scsi_device_set_state(struct scsi_devic
  
        switch (state) {
        case SDEV_CREATED:
-               /* There are no legal states that come back to
-                * created.  This is the manually initialised start
-                * state */
-               goto illegal;
+               switch (oldstate) {
+               case SDEV_CREATED_BLOCK:
+                       break;
+               default:
+                       goto illegal;
+               }
+               break;
                        
        case SDEV_RUNNING:
                switch (oldstate) {
  
        case SDEV_BLOCK:
                switch (oldstate) {
-               case SDEV_CREATED:
                case SDEV_RUNNING:
+               case SDEV_CREATED_BLOCK:
+                       break;
+               default:
+                       goto illegal;
+               }
+               break;
+       case SDEV_CREATED_BLOCK:
+               switch (oldstate) {
+               case SDEV_CREATED:
                        break;
                default:
                        goto illegal;
@@@ -2403,8 -2407,12 +2416,12 @@@ scsi_internal_device_block(struct scsi_
        int err = 0;
  
        err = scsi_device_set_state(sdev, SDEV_BLOCK);
-       if (err)
-               return err;
+       if (err) {
+               err = scsi_device_set_state(sdev, SDEV_CREATED_BLOCK);
+               if (err)
+                       return err;
+       }
  
        /* 
         * The device has transitioned to SDEV_BLOCK.  Stop the
@@@ -2447,8 -2455,12 +2464,12 @@@ scsi_internal_device_unblock(struct scs
         * and goose the device queue if successful.  
         */
        err = scsi_device_set_state(sdev, SDEV_RUNNING);
-       if (err)
-               return err;
+       if (err) {
+               err = scsi_device_set_state(sdev, SDEV_CREATED);
+               if (err)
+                       return err;
+       }
  
        spin_lock_irqsave(q->queue_lock, flags);
        blk_start_queue(q);
@@@ -34,6 -34,7 +34,7 @@@ static const struct 
        { SDEV_QUIESCE, "quiesce" },
        { SDEV_OFFLINE, "offline" },
        { SDEV_BLOCK,   "blocked" },
+       { SDEV_CREATED_BLOCK, "created-blocked" },
  };
  
  const char *scsi_device_state_name(enum scsi_device_state state)
@@@ -560,15 -561,12 +561,15 @@@ sdev_rd_attr (vendor, "%.8s\n")
  sdev_rd_attr (model, "%.16s\n");
  sdev_rd_attr (rev, "%.4s\n");
  
 +/*
 + * TODO: can we make these symlinks to the block layer ones?
 + */
  static ssize_t
  sdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf)
  {
        struct scsi_device *sdev;
        sdev = to_scsi_device(dev);
 -      return snprintf (buf, 20, "%d\n", sdev->timeout / HZ);
 +      return snprintf(buf, 20, "%d\n", sdev->request_queue->rq_timeout / HZ);
  }
  
  static ssize_t
@@@ -579,7 -577,7 +580,7 @@@ sdev_store_timeout (struct device *dev
        int timeout;
        sdev = to_scsi_device(dev);
        sscanf (buf, "%d\n", &timeout);
 -      sdev->timeout = timeout * HZ;
 +      blk_queue_rq_timeout(sdev->request_queue, timeout * HZ);
        return count;
  }
  static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
@@@ -362,7 -362,7 +362,7 @@@ static int scsi_map_user_pages(struct s
        int err;
  
        dprintk("%lx %u\n", uaddr, len);
 -      err = blk_rq_map_user(q, rq, (void *)uaddr, len);
 +      err = blk_rq_map_user(q, rq, NULL, (void *)uaddr, len, GFP_KERNEL);
        if (err) {
                /*
                 * TODO: need to fixup sg_tablesize, max_segment_size,
@@@ -460,7 -460,7 +460,7 @@@ int scsi_tgt_kspace_exec(int host_no, u
  
        /* TODO: replace with a O(1) alg */
        shost = scsi_host_lookup(host_no);
-       if (IS_ERR(shost)) {
+       if (!shost) {
                printk(KERN_ERR "Could not find host no %d\n", host_no);
                return -EINVAL;
        }
@@@ -550,7 -550,7 +550,7 @@@ int scsi_tgt_kspace_tsk_mgmt(int host_n
        dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);
  
        shost = scsi_host_lookup(host_no);
-       if (IS_ERR(shost)) {
+       if (!shost) {
                printk(KERN_ERR "Could not find host no %d\n", host_no);
                return err;
        }
@@@ -603,7 -603,7 +603,7 @@@ int scsi_tgt_kspace_it_nexus_rsp(int ho
        dprintk("%d %d%llx\n", host_no, result, (unsigned long long)itn_id);
  
        shost = scsi_host_lookup(host_no);
-       if (IS_ERR(shost)) {
+       if (!shost) {
                printk(KERN_ERR "Could not find host no %d\n", host_no);
                return err;
        }
  
  static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
  static void fc_vport_sched_delete(struct work_struct *work);
- /*
-  * This is a temporary carrier for creating a vport. It will eventually
-  * be replaced  by a real message definition for sgio or netlink.
-  *
-  * fc_vport_identifiers: This set of data contains all elements
-  * to uniquely identify and instantiate a FC virtual port.
-  *
-  * Notes:
-  *   symbolic_name: The driver is to append the symbolic_name string data
-  *      to the symbolic_node_name data that it generates by default.
-  *      the resulting combination should then be registered with the switch.
-  *      It is expected that things like Xen may stuff a VM title into
-  *      this field.
-  */
- struct fc_vport_identifiers {
-       u64 node_name;
-       u64 port_name;
-       u32 roles;
-       bool disable;
-       enum fc_port_type vport_type;   /* only FC_PORTTYPE_NPIV allowed */
-       char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN];
- };
- static int fc_vport_create(struct Scsi_Host *shost, int channel,
+ static int fc_vport_setup(struct Scsi_Host *shost, int channel,
        struct device *pdev, struct fc_vport_identifiers  *ids,
        struct fc_vport **vport);
  
@@@ -1760,7 -1736,7 +1736,7 @@@ store_fc_host_vport_create(struct devic
        vid.disable = false;            /* always enabled */
  
        /* we only allow support on Channel 0 !!! */
-       stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport);
+       stat = fc_vport_setup(shost, 0, &shost->shost_gendev, &vid, &vport);
        return stat ? stat : count;
  }
  static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL,
@@@ -1950,15 -1926,15 +1926,15 @@@ static int fc_vport_match(struct attrib
   * Notes:
   *    This routine assumes no locks are held on entry.
   */
 -static enum scsi_eh_timer_return
 +static enum blk_eh_timer_return
  fc_timed_out(struct scsi_cmnd *scmd)
  {
        struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device));
  
        if (rport->port_state == FC_PORTSTATE_BLOCKED)
 -              return EH_RESET_TIMER;
 +              return BLK_EH_RESET_TIMER;
  
 -      return EH_NOT_HANDLED;
 +      return BLK_EH_NOT_HANDLED;
  }
  
  /*
@@@ -3103,7 -3079,7 +3079,7 @@@ fc_scsi_scan_rport(struct work_struct *
  
  
  /**
-  * fc_vport_create - allocates and creates a FC virtual port.
+  * fc_vport_setup - allocates and creates a FC virtual port.
   * @shost:    scsi host the virtual port is connected to.
   * @channel:  Channel on shost port connected to.
   * @pdev:     parent device for vport
   *    This routine assumes no locks are held on entry.
   */
  static int
- fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
+ fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev,
        struct fc_vport_identifiers  *ids, struct fc_vport **ret_vport)
  {
        struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
@@@ -3231,6 -3207,28 +3207,28 @@@ delete_vport
        return error;
  }
  
+ /**
+  * fc_vport_create - Admin App or LLDD requests creation of a vport
+  * @shost:    scsi host the virtual port is connected to.
+  * @channel:  channel on shost port connected to.
+  * @ids:      The world wide names, FC4 port roles, etc for
+  *              the virtual port.
+  *
+  * Notes:
+  *    This routine assumes no locks are held on entry.
+  */
+ struct fc_vport *
+ fc_vport_create(struct Scsi_Host *shost, int channel,
+       struct fc_vport_identifiers *ids)
+ {
+       int stat;
+       struct fc_vport *vport;
+       stat = fc_vport_setup(shost, channel, &shost->shost_gendev,
+                ids, &vport);
+       return stat ? NULL : vport;
+ }
+ EXPORT_SYMBOL(fc_vport_create);
  
  /**
   * fc_vport_terminate - Admin App or LLDD requests termination of a vport
diff --combined drivers/scsi/sd.c
@@@ -47,6 -47,7 +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,12 -87,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 *);
@@@ -165,7 -160,7 +166,7 @@@ sd_store_cache_type(struct device *dev
                        sd_print_sense_hdr(sdkp, &sshdr);
                return -EINVAL;
        }
 -      sd_revalidate_disk(sdkp->disk);
 +      revalidate_disk(sdkp->disk);
        return count;
  }
  
@@@ -383,6 -378,7 +384,6 @@@ static int sd_prep_fn(struct request_qu
        sector_t block = rq->sector;
        sector_t threshold;
        unsigned int this_count = rq->nr_sectors;
 -      unsigned int timeout = sdp->timeout;
        int ret;
  
        if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
        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
@@@ -914,7 -911,7 +915,7 @@@ static void sd_rescan(struct device *de
        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);
        }
  }
@@@ -1433,27 -1430,21 +1434,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 = sdkp->capacity << ffz(~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 */
@@@ -1767,52 -1758,6 +1762,52 @@@ static int sd_revalidate_disk(struct ge
        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
@@@ -1851,7 -1796,7 +1846,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;
  
        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;
        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);
  
        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;
  
        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;