Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / scsi / qlogicpti.c
index a917ab7..c7e78dc 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/jiffies.h>
 
 #include <asm/byteorder.h>
 
@@ -1017,7 +1018,7 @@ static inline void cmd_frob(struct Command_Entry *cmd, struct scsi_cmnd *Cmnd,
        if (Cmnd->device->tagged_supported) {
                if (qpti->cmd_count[Cmnd->device->id] == 0)
                        qpti->tag_ages[Cmnd->device->id] = jiffies;
-               if ((jiffies - qpti->tag_ages[Cmnd->device->id]) > (5*HZ)) {
+               if (time_after(jiffies, qpti->tag_ages[Cmnd->device->id] + (5*HZ))) {
                        cmd->control_flags = CFLAG_ORDERED_TAG;
                        qpti->tag_ages[Cmnd->device->id] = jiffies;
                } else
@@ -1119,6 +1120,36 @@ 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)
+{
+       unsigned char *buf;
+       unsigned int buflen;
+
+       if (cmd->use_sg) {
+               struct scatterlist *sg;
+
+               sg = (struct scatterlist *) cmd->request_buffer;
+               buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
+               buflen = sg->length;
+       } 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...
  */
@@ -1145,11 +1176,9 @@ static void ourdone(struct scsi_cmnd *Cmnd)
                int ok = host_byte(Cmnd->result) == DID_OK;
                if (Cmnd->cmnd[0] == 0x12 && ok) {
                        unsigned char *iqd;
+                       unsigned int iqd_len;
 
-                       if (Cmnd->use_sg != 0)
-                               BUG();
-
-                       iqd = ((unsigned char *)Cmnd->buffer);
+                       iqd_len = scsi_rbuf_get(Cmnd, &iqd);
 
                        /* tags handled in midlayer */
                        /* enable sync mode? */
@@ -1163,6 +1192,9 @@ static void ourdone(struct scsi_cmnd *Cmnd)
                        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);