Merge current mainline tree into linux-omap tree
[pandora-kernel.git] / drivers / scsi / qlogicpti.c
index 5948872..9053508 100644 (file)
@@ -310,8 +310,6 @@ static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti)
                }
                qpti->dev_param[i].device_enable = 1;
        }
-       /* this is very important to set! */
-       qpti->sbits = 1 << qpti->scsi_id;
 }
 
 static int qlogicpti_reset_hardware(struct Scsi_Host *host)
@@ -653,7 +651,7 @@ static int qlogicpti_verify_tmon(struct qlogicpti *qpti)
 
 static irqreturn_t qpti_intr(int irq, void *dev_id);
 
-static void __init qpti_chain_add(struct qlogicpti *qpti)
+static void __devinit qpti_chain_add(struct qlogicpti *qpti)
 {
        spin_lock_irq(&qptichain_lock);
        if (qptichain != NULL) {
@@ -669,7 +667,7 @@ static void __init qpti_chain_add(struct qlogicpti *qpti)
        spin_unlock_irq(&qptichain_lock);
 }
 
-static void __init qpti_chain_del(struct qlogicpti *qpti)
+static void __devexit qpti_chain_del(struct qlogicpti *qpti)
 {
        spin_lock_irq(&qptichain_lock);
        if (qptichain == qpti) {
@@ -684,7 +682,7 @@ static void __init qpti_chain_del(struct qlogicpti *qpti)
        spin_unlock_irq(&qptichain_lock);
 }
 
-static int __init qpti_map_regs(struct qlogicpti *qpti)
+static int __devinit qpti_map_regs(struct qlogicpti *qpti)
 {
        struct sbus_dev *sdev = qpti->sdev;
 
@@ -707,7 +705,7 @@ static int __init qpti_map_regs(struct qlogicpti *qpti)
        return 0;
 }
 
-static int __init qpti_register_irq(struct qlogicpti *qpti)
+static int __devinit qpti_register_irq(struct qlogicpti *qpti)
 {
        struct sbus_dev *sdev = qpti->sdev;
 
@@ -732,7 +730,7 @@ fail:
        return -1;
 }
 
-static void __init qpti_get_scsi_id(struct qlogicpti *qpti)
+static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti)
 {
        qpti->scsi_id = prom_getintdefault(qpti->prom_node,
                                           "initiator-id",
@@ -785,7 +783,7 @@ static void qpti_get_clock(struct qlogicpti *qpti)
 /* The request and response queues must each be aligned
  * on a page boundary.
  */
-static int __init qpti_map_queues(struct qlogicpti *qpti)
+static int __devinit qpti_map_queues(struct qlogicpti *qpti)
 {
        struct sbus_dev *sdev = qpti->sdev;
 
@@ -870,14 +868,15 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
                           struct qlogicpti *qpti, u_int in_ptr, u_int out_ptr)
 {
        struct dataseg *ds;
-       struct scatterlist *sg;
+       struct scatterlist *sg, *s;
        int i, n;
 
-       if (Cmnd->use_sg) {
+       if (scsi_bufflen(Cmnd)) {
                int sg_count;
 
-               sg = (struct scatterlist *) Cmnd->request_buffer;
-               sg_count = sbus_map_sg(qpti->sdev, sg, Cmnd->use_sg, Cmnd->sc_data_direction);
+               sg = scsi_sglist(Cmnd);
+               sg_count = sbus_map_sg(qpti->sdev, sg, scsi_sg_count(Cmnd),
+                                                     Cmnd->sc_data_direction);
 
                ds = cmd->dataseg;
                cmd->segment_cnt = sg_count;
@@ -886,11 +885,12 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
                n = sg_count;
                if (n > 4)
                        n = 4;
-               for (i = 0; i < n; i++, sg++) {
-                       ds[i].d_base = sg_dma_address(sg);
-                       ds[i].d_count = sg_dma_len(sg);
+               for_each_sg(sg, s, n, i) {
+                       ds[i].d_base = sg_dma_address(s);
+                       ds[i].d_count = sg_dma_len(s);
                }
                sg_count -= 4;
+               sg = s;
                while (sg_count > 0) {
                        struct Continuation_Entry *cont;
 
@@ -909,22 +909,13 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd,
                        n = sg_count;
                        if (n > 7)
                                n = 7;
-                       for (i = 0; i < n; i++, sg++) {
-                               ds[i].d_base = sg_dma_address(sg);
-                               ds[i].d_count = sg_dma_len(sg);
+                       for_each_sg(sg, s, n, i) {
+                               ds[i].d_base = sg_dma_address(s);
+                               ds[i].d_count = sg_dma_len(s);
                        }
                        sg_count -= n;
+                       sg = s;
                }
-       } else if (Cmnd->request_bufflen) {
-               Cmnd->SCp.ptr = (char *)(unsigned long)
-                       sbus_map_single(qpti->sdev,
-                                       Cmnd->request_buffer,
-                                       Cmnd->request_bufflen,
-                                       Cmnd->sc_data_direction);
-
-               cmd->dataseg[0].d_base = (u32) ((unsigned long)Cmnd->SCp.ptr);
-               cmd->dataseg[0].d_count = Cmnd->request_bufflen;
-               cmd->segment_cnt = 1;
        } else {
                cmd->dataseg[0].d_base = 0;
                cmd->dataseg[0].d_count = 0;
@@ -951,153 +942,35 @@ static inline void update_can_queue(struct Scsi_Host *host, u_int in_ptr, u_int
        host->sg_tablesize = QLOGICPTI_MAX_SG(num_free);
 }
 
-static unsigned int scsi_rbuf_get(struct scsi_cmnd *cmd, unsigned char **buf_out)
+static int qlogicpti_slave_configure(struct scsi_device *sdev)
 {
-       unsigned char *buf;
-       unsigned int buflen;
-
-       if (cmd->use_sg) {
-               struct scatterlist *sg;
+       struct qlogicpti *qpti = shost_priv(sdev->host);
+       int tgt = sdev->id;
+       u_short param[6];
 
-               sg = (struct scatterlist *) cmd->request_buffer;
-               buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
-               buflen = sg->length;
+       /* tags handled in midlayer */
+       /* enable sync mode? */
+       if (sdev->sdtr) {
+               qpti->dev_param[tgt].device_flags |= 0x10;
        } else {
-               buf = cmd->request_buffer;
-               buflen = cmd->request_bufflen;
-       }
-
-       *buf_out = buf;
-       return buflen;
-}
-
-static void scsi_rbuf_put(struct scsi_cmnd *cmd, unsigned char *buf)
-{
-       if (cmd->use_sg) {
-               struct scatterlist *sg;
-
-               sg = (struct scatterlist *) cmd->request_buffer;
-               kunmap_atomic(buf - sg->offset, KM_IRQ0);
-       }
-}
-
-/*
- * Until we scan the entire bus with inquiries, go throught this fella...
- */
-static void ourdone(struct scsi_cmnd *Cmnd)
-{
-       struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata;
-       int tgt = Cmnd->device->id;
-       void (*done) (struct scsi_cmnd *);
-
-       /* This grot added by DaveM, blame him for ugliness.
-        * The issue is that in the 2.3.x driver we use the
-        * host_scribble portion of the scsi command as a
-        * completion linked list at interrupt service time,
-        * so we have to store the done function pointer elsewhere.
-        */
-       done = (void (*)(struct scsi_cmnd *))
-               (((unsigned long) Cmnd->SCp.Message)
-#ifdef __sparc_v9__
-                | ((unsigned long) Cmnd->SCp.Status << 32UL)
-#endif
-                );
-
-       if ((qpti->sbits & (1 << tgt)) == 0) {
-               int ok = host_byte(Cmnd->result) == DID_OK;
-               if (Cmnd->cmnd[0] == 0x12 && ok) {
-                       unsigned char *iqd;
-                       unsigned int iqd_len;
-
-                       iqd_len = scsi_rbuf_get(Cmnd, &iqd);
-
-                       /* tags handled in midlayer */
-                       /* enable sync mode? */
-                       if (iqd[7] & 0x10) {
-                               qpti->dev_param[tgt].device_flags |= 0x10;
-                       } else {
-                               qpti->dev_param[tgt].synchronous_offset = 0;
-                               qpti->dev_param[tgt].synchronous_period = 0;
-                       }
-                       /* are we wide capable? */
-                       if (iqd[7] & 0x20) {
-                               qpti->dev_param[tgt].device_flags |= 0x20;
-                       }
-
-                       scsi_rbuf_put(Cmnd, iqd);
-
-                       qpti->sbits |= (1 << tgt);
-               } else if (!ok) {
-                       qpti->sbits |= (1 << tgt);
-               }
+               qpti->dev_param[tgt].synchronous_offset = 0;
+               qpti->dev_param[tgt].synchronous_period = 0;
        }
-       done(Cmnd);
-}
-
-static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct scsi_cmnd *));
-
-static int qlogicpti_queuecommand_slow(struct scsi_cmnd *Cmnd,
-                                      void (*done)(struct scsi_cmnd *))
-{
-       struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata;
-
-       /*
-        * done checking this host adapter?
-        * If not, then rewrite the command
-        * to finish through ourdone so we
-        * can peek at Inquiry data results.
-        */
-       if (qpti->sbits && qpti->sbits != 0xffff) {
-               /* See above about in ourdone this ugliness... */
-               Cmnd->SCp.Message = ((unsigned long)done) & 0xffffffff;
-#ifdef CONFIG_SPARC64
-               Cmnd->SCp.Status = ((unsigned long)done >> 32UL) & 0xffffffff;
-#endif
-               return qlogicpti_queuecommand(Cmnd, ourdone);
-       }
-
-       /*
-        * We've peeked at all targets for this bus- time
-        * to set parameters for devices for real now.
-        */
-       if (qpti->sbits == 0xffff) {
-               int i;
-               for(i = 0; i < MAX_TARGETS; i++) {
-                       u_short param[6];
-                       param[0] = MBOX_SET_TARGET_PARAMS;
-                       param[1] = (i << 8);
-                       param[2] = (qpti->dev_param[i].device_flags << 8);
-                       if (qpti->dev_param[i].device_flags & 0x10) {
-                               param[3] = (qpti->dev_param[i].synchronous_offset << 8) |
-                                       qpti->dev_param[i].synchronous_period;
-                       } else {
-                               param[3] = 0;
-                       }
-                       (void) qlogicpti_mbox_command(qpti, param, 0);
-               }
-               /*
-                * set to zero so any traverse through ourdone
-                * doesn't start the whole process again,
-                */
-               qpti->sbits = 0;
-       }
-
-       /* check to see if we're done with all adapters... */
-       for (qpti = qptichain; qpti != NULL; qpti = qpti->next) {
-               if (qpti->sbits) {
-                       break;
-               }
+       /* are we wide capable? */
+       if (sdev->wdtr)
+               qpti->dev_param[tgt].device_flags |= 0x20;
+
+       param[0] = MBOX_SET_TARGET_PARAMS;
+       param[1] = (tgt << 8);
+       param[2] = (qpti->dev_param[tgt].device_flags << 8);
+       if (qpti->dev_param[tgt].device_flags & 0x10) {
+               param[3] = (qpti->dev_param[tgt].synchronous_offset << 8) |
+                       qpti->dev_param[tgt].synchronous_period;
+       } else {
+               param[3] = 0;
        }
-
-       /*
-        * if we hit the end of the chain w/o finding adapters still
-        * capability-configuring, then we're done with all adapters
-        * and can rock on..
-        */
-       if (qpti == NULL)
-               Cmnd->device->host->hostt->queuecommand = qlogicpti_queuecommand;
-
-       return qlogicpti_queuecommand(Cmnd, done);
+       qlogicpti_mbox_command(qpti, param, 0);
+       return 0;
 }
 
 /*
@@ -1270,7 +1143,7 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti)
 
                if (sts->state_flags & SF_GOT_SENSE)
                        memcpy(Cmnd->sense_buffer, sts->req_sense_data,
-                              sizeof(Cmnd->sense_buffer));
+                              SCSI_SENSE_BUFFERSIZE);
 
                if (sts->hdr.entry_type == ENTRY_STATUS)
                        Cmnd->result =
@@ -1278,17 +1151,11 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti)
                else
                        Cmnd->result = DID_ERROR << 16;
 
-               if (Cmnd->use_sg) {
+               if (scsi_bufflen(Cmnd))
                        sbus_unmap_sg(qpti->sdev,
-                                     (struct scatterlist *)Cmnd->request_buffer,
-                                     Cmnd->use_sg,
+                                     scsi_sglist(Cmnd), scsi_sg_count(Cmnd),
                                      Cmnd->sc_data_direction);
-               } else if (Cmnd->request_bufflen) {
-                       sbus_unmap_single(qpti->sdev,
-                                         (__u32)((unsigned long)Cmnd->SCp.ptr),
-                                         Cmnd->request_bufflen,
-                                         Cmnd->sc_data_direction);
-               }
+
                qpti->cmd_count[Cmnd->device->id]--;
                sbus_writew(out_ptr, qpti->qregs + MBOX5);
                Cmnd->host_scribble = (unsigned char *) done_queue;
@@ -1390,7 +1257,8 @@ static struct scsi_host_template qpti_template = {
        .module                 = THIS_MODULE,
        .name                   = "qlogicpti",
        .info                   = qlogicpti_info,
-       .queuecommand           = qlogicpti_queuecommand_slow,
+       .queuecommand           = qlogicpti_queuecommand,
+       .slave_configure        = qlogicpti_slave_configure,
        .eh_abort_handler       = qlogicpti_abort,
        .eh_bus_reset_handler   = qlogicpti_reset,
        .can_queue              = QLOGICPTI_REQ_QUEUE_LEN,