scsi: libsas: fix ata xfer length
[pandora-kernel.git] / drivers / scsi / 3w-9xxx.c
index 3868ab2..d7a90c3 100644 (file)
@@ -149,7 +149,6 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
 static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg);
 static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id);
 static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
 
 /* Functions */
 
@@ -226,6 +225,17 @@ static const struct file_operations twa_fops = {
        .llseek         = noop_llseek,
 };
 
+/*
+ * The controllers use an inline buffer instead of a mapped SGL for small,
+ * single entry buffers.  Note that we treat a zero-length transfer like
+ * a mapped SGL.
+ */
+static bool twa_command_mapped(struct scsi_cmnd *cmd)
+{
+       return scsi_sg_count(cmd) != 1 ||
+               scsi_bufflen(cmd) >= TW_MIN_SGL_LENGTH;
+}
+
 /* This function will complete an aen request from the isr */
 static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id)
 {
@@ -1352,11 +1362,12 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
                                }
 
                                /* Now complete the io */
+                               if (twa_command_mapped(cmd))
+                                       scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                                tw_dev->state[request_id] = TW_S_COMPLETED;
                                twa_free_request_id(tw_dev, request_id);
                                tw_dev->posted_request_count--;
-                               tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-                               twa_unmap_scsi_data(tw_dev, request_id);
                        }
 
                        /* Check for valid status after each drain */
@@ -1414,26 +1425,6 @@ static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm
        }
 } /* End twa_load_sgl() */
 
-/* This function will perform a pci-dma mapping for a scatter gather list */
-static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       int use_sg;
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       use_sg = scsi_dma_map(cmd);
-       if (!use_sg)
-               return 0;
-       else if (use_sg < 0) {
-               TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
-               return 0;
-       }
-
-       cmd->SCp.phase = TW_PHASE_SGLIST;
-       cmd->SCp.have_data_in = use_sg;
-
-       return use_sg;
-} /* End twa_map_scsi_sg_data() */
-
 /* This function will poll for a response interrupt of a request */
 static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
 {
@@ -1612,9 +1603,12 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
                    (tw_dev->state[i] != TW_S_INITIAL) &&
                    (tw_dev->state[i] != TW_S_COMPLETED)) {
                        if (tw_dev->srb[i]) {
-                               tw_dev->srb[i]->result = (DID_RESET << 16);
-                               tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-                               twa_unmap_scsi_data(tw_dev, i);
+                               struct scsi_cmnd *cmd = tw_dev->srb[i];
+
+                               cmd->result = (DID_RESET << 16);
+                               if (twa_command_mapped(cmd))
+                                       scsi_dma_unmap(cmd);
+                               cmd->scsi_done(cmd);
                        }
                }
        }
@@ -1793,21 +1787,20 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
        /* Save the scsi command for use by the ISR */
        tw_dev->srb[request_id] = SCpnt;
 
-       /* Initialize phase to zero */
-       SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
        retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
        switch (retval) {
        case SCSI_MLQUEUE_HOST_BUSY:
+               if (twa_command_mapped(SCpnt))
+                       scsi_dma_unmap(SCpnt);
                twa_free_request_id(tw_dev, request_id);
-               twa_unmap_scsi_data(tw_dev, request_id);
                break;
        case 1:
-               tw_dev->state[request_id] = TW_S_COMPLETED;
-               twa_free_request_id(tw_dev, request_id);
-               twa_unmap_scsi_data(tw_dev, request_id);
                SCpnt->result = (DID_ERROR << 16);
+               if (twa_command_mapped(SCpnt))
+                       scsi_dma_unmap(SCpnt);
                done(SCpnt);
+               tw_dev->state[request_id] = TW_S_COMPLETED;
+               twa_free_request_id(tw_dev, request_id);
                retval = 0;
        }
 out:
@@ -1865,8 +1858,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
                /* Map sglist from scsi layer to cmd packet */
 
                if (scsi_sg_count(srb)) {
-                       if ((scsi_sg_count(srb) == 1) &&
-                           (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
+                       if (!twa_command_mapped(srb)) {
                                if (srb->sc_data_direction == DMA_TO_DEVICE ||
                                    srb->sc_data_direction == DMA_BIDIRECTIONAL)
                                        scsi_sg_copy_to_buffer(srb,
@@ -1875,8 +1867,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
                                command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
                                command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
                        } else {
-                               sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
-                               if (sg_count == 0)
+                               sg_count = scsi_dma_map(srb);
+                               if (sg_count < 0)
                                        goto out;
 
                                scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1939,7 +1931,7 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
 {
        struct scsi_cmnd *cmd = tw_dev->srb[request_id];
 
-       if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH &&
+       if (!twa_command_mapped(cmd) &&
            (cmd->sc_data_direction == DMA_FROM_DEVICE ||
             cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
                if (scsi_sg_count(cmd) == 1) {
@@ -1991,15 +1983,6 @@ static char *twa_string_lookup(twa_message_type *table, unsigned int code)
        return(table[index].text);
 } /* End twa_string_lookup() */
 
-/* This function will perform a pci-dma unmap */
-static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
-{
-       struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-       if (cmd->SCp.phase == TW_PHASE_SGLIST)
-               scsi_dma_unmap(cmd);
-} /* End twa_unmap_scsi_data() */
-
 /* This function gets called when a disk is coming on-line */
 static int twa_slave_configure(struct scsi_device *sdev)
 {