Merge branch 'for-linus' of git://git.infradead.org/~dedekind/ubi-2.6
[sfrench/cifs-2.6.git] / drivers / ata / libata-scsi.c
index 14daf4848f09add8d0e7e90659251fd25afcc649..8f0e8f2bc628a283c0000b5cab3e43287aa4bb58 100644 (file)
@@ -517,7 +517,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
                qc->scsicmd = cmd;
                qc->scsidone = done;
 
-               qc->__sg = scsi_sglist(cmd);
+               qc->sg = scsi_sglist(cmd);
                qc->n_elem = scsi_sg_count(cmd);
        } else {
                cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1);
@@ -826,23 +826,62 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
        sdev->max_device_blocked = 1;
 }
 
-static void ata_scsi_dev_config(struct scsi_device *sdev,
-                               struct ata_device *dev)
+/**
+ *     atapi_drain_needed - Check whether data transfer may overflow
+ *     @rq: request to be checked
+ *
+ *     ATAPI commands which transfer variable length data to host
+ *     might overflow due to application error or hardare bug.  This
+ *     function checks whether overflow should be drained and ignored
+ *     for @request.
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     1 if ; otherwise, 0.
+ */
+static int atapi_drain_needed(struct request *rq)
+{
+       if (likely(!blk_pc_request(rq)))
+               return 0;
+
+       if (!rq->data_len || (rq->cmd_flags & REQ_RW))
+               return 0;
+
+       return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC;
+}
+
+static int ata_scsi_dev_config(struct scsi_device *sdev,
+                              struct ata_device *dev)
 {
        /* configure max sectors */
        blk_queue_max_sectors(sdev->request_queue, dev->max_sectors);
 
-       /* SATA DMA transfers must be multiples of 4 byte, so
-        * we need to pad ATAPI transfers using an extra sg.
-        * Decrement max hw segments accordingly.
-        */
        if (dev->class == ATA_DEV_ATAPI) {
                struct request_queue *q = sdev->request_queue;
-               blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
-       }
+               void *buf;
+
+               /* set the min alignment and padding */
+               blk_queue_update_dma_alignment(sdev->request_queue,
+                                              ATA_DMA_PAD_SZ - 1);
+               blk_queue_dma_pad(sdev->request_queue, ATA_DMA_PAD_SZ - 1);
+
+               /* configure draining */
+               buf = kmalloc(ATAPI_MAX_DRAIN, q->bounce_gfp | GFP_KERNEL);
+               if (!buf) {
+                       ata_dev_printk(dev, KERN_ERR,
+                                      "drain buffer allocation failed\n");
+                       return -ENOMEM;
+               }
 
-       if (dev->class == ATA_DEV_ATA)
+               blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN);
+       } else {
+               /* ATA devices must be sector aligned */
+               blk_queue_update_dma_alignment(sdev->request_queue,
+                                              ATA_SECT_SIZE - 1);
                sdev->manage_start_stop = 1;
+       }
 
        if (dev->flags & ATA_DFLAG_AN)
                set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events);
@@ -854,6 +893,8 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
                depth = min(ATA_MAX_QUEUE - 1, depth);
                scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
        }
+
+       return 0;
 }
 
 /**
@@ -872,13 +913,14 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
 {
        struct ata_port *ap = ata_shost_to_port(sdev->host);
        struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
+       int rc = 0;
 
        ata_scsi_sdev_config(sdev);
 
        if (dev)
-               ata_scsi_dev_config(sdev, dev);
+               rc = ata_scsi_dev_config(sdev, dev);
 
-       return 0;       /* scsi layer doesn't check return value, sigh */
+       return rc;
 }
 
 /**
@@ -898,6 +940,7 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
 void ata_scsi_slave_destroy(struct scsi_device *sdev)
 {
        struct ata_port *ap = ata_shost_to_port(sdev->host);
+       struct request_queue *q = sdev->request_queue;
        unsigned long flags;
        struct ata_device *dev;
 
@@ -913,6 +956,10 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
                ata_port_schedule_eh(ap);
        }
        spin_unlock_irqrestore(ap->lock, flags);
+
+       kfree(q->dma_drain_buffer);
+       q->dma_drain_buffer = NULL;
+       q->dma_drain_size = 0;
 }
 
 /**
@@ -1648,12 +1695,17 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
        u8 *rbuf;
        unsigned int buflen, rc;
        struct scsi_cmnd *cmd = args->cmd;
+       unsigned long flags;
+
+       local_irq_save(flags);
 
        buflen = ata_scsi_rbuf_get(cmd, &rbuf);
        memset(rbuf, 0, buflen);
        rc = actor(args, rbuf, buflen);
        ata_scsi_rbuf_put(cmd, rbuf);
 
+       local_irq_restore(flags);
+
        if (rc == 0)
                cmd->result = SAM_STAT_GOOD;
        args->done(cmd);
@@ -1855,7 +1907,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
  *     spin_lock_irqsave(host lock)
  */
 
-unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
+static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
                              unsigned int buflen)
 {
        u8 pbuf[60];
@@ -2210,7 +2262,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
 
                /* sector size */
                ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8);
-               ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE);
+               ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE & 0xff);
        } else {
                /* sector count, 64-bit */
                ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7));
@@ -2224,7 +2276,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
 
                /* sector size */
                ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8);
-               ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE);
+               ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE & 0xff);
        }
 
        return 0;
@@ -2331,7 +2383,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
        DPRINTK("ATAPI request sense\n");
 
        /* FIXME: is this needed? */
-       memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
+       memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 
        ap->ops->tf_read(ap, &qc->tf);
 
@@ -2341,7 +2393,9 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
 
        ata_qc_reinit(qc);
 
-       ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
+       /* setup sg table and init transfer direction */
+       sg_init_one(&qc->sgent, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
+       ata_sg_init(qc, &qc->sgent, 1);
        qc->dma_dir = DMA_FROM_DEVICE;
 
        memset(&qc->cdb, 0, qc->dev->cdb_len);
@@ -2352,10 +2406,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
        qc->tf.command = ATA_CMD_PACKET;
 
        if (ata_pio_use_silly(ap)) {
-               qc->tf.protocol = ATA_PROT_ATAPI_DMA;
+               qc->tf.protocol = ATAPI_PROT_DMA;
                qc->tf.feature |= ATAPI_PKT_DMA;
        } else {
-               qc->tf.protocol = ATA_PROT_ATAPI;
+               qc->tf.protocol = ATAPI_PROT_PIO;
                qc->tf.lbam = SCSI_SENSE_BUFFERSIZE;
                qc->tf.lbah = 0;
        }
@@ -2425,6 +2479,9 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
                if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
                        u8 *buf = NULL;
                        unsigned int buflen;
+                       unsigned long flags;
+
+                       local_irq_save(flags);
 
                        buflen = ata_scsi_rbuf_get(cmd, &buf);
 
@@ -2442,6 +2499,8 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
                        }
 
                        ata_scsi_rbuf_put(cmd, buf);
+
+                       local_irq_restore(flags);
                }
 
                cmd->result = SAM_STAT_GOOD;
@@ -2480,7 +2539,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
        }
 
        qc->tf.command = ATA_CMD_PACKET;
-       qc->nbytes = scsi_bufflen(scmd);
+       qc->nbytes = scsi_bufflen(scmd) + scmd->request->extra_len;
 
        /* check whether ATAPI DMA is safe */
        if (!using_pio && ata_check_atapi_dma(qc))
@@ -2491,7 +2550,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
         * want to set it properly, and for DMA where it is
         * effectively meaningless.
         */
-       nbytes = min(qc->nbytes, (unsigned int)63 * 1024);
+       nbytes = min(scmd->request->data_len, (unsigned int)63 * 1024);
 
        /* Most ATAPI devices which honor transfer chunk size don't
         * behave according to the spec when odd chunk size which
@@ -2526,15 +2585,16 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
        if (using_pio || nodata) {
                /* no data, or PIO data xfer */
                if (nodata)
-                       qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
+                       qc->tf.protocol = ATAPI_PROT_NODATA;
                else
-                       qc->tf.protocol = ATA_PROT_ATAPI;
+                       qc->tf.protocol = ATAPI_PROT_PIO;
        } else {
                /* DMA data xfer */
-               qc->tf.protocol = ATA_PROT_ATAPI_DMA;
+               qc->tf.protocol = ATAPI_PROT_DMA;
                qc->tf.feature |= ATAPI_PKT_DMA;
 
-               if (atapi_dmadir && (scmd->sc_data_direction != DMA_TO_DEVICE))
+               if ((dev->flags & ATA_DFLAG_DMADIR) &&
+                   (scmd->sc_data_direction != DMA_TO_DEVICE))
                        /* some SATA bridges need us to indicate data xfer direction */
                        qc->tf.feature |= ATAPI_DMADIR;
        }
@@ -2690,6 +2750,24 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
        if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN)
                goto invalid_fld;
 
+       /*
+        * Filter TPM commands by default. These provide an
+        * essentially uncontrolled encrypted "back door" between
+        * applications and the disk. Set libata.allow_tpm=1 if you
+        * have a real reason for wanting to use them. This ensures
+        * that installed software cannot easily mess stuff up without
+        * user intent. DVR type users will probably ship with this enabled
+        * for movie content management.
+        *
+        * Note that for ATA8 we can issue a DCS change and DCS freeze lock
+        * for this and should do in future but that it is not sufficient as
+        * DCS is an optional feature set. Thus we also do the software filter
+        * so that we comply with the TC consortium stated goal that the user
+        * can turn off TC features of their system.
+        */
+       if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm)
+               goto invalid_fld;
+
        /* We may not issue DMA commands if no DMA mode is set */
        if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
                goto invalid_fld;
@@ -2798,7 +2876,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
         * TODO: find out if we need to do more here to
         *       cover scatter/gather case.
         */
-       qc->nbytes = scsi_bufflen(scmd);
+       qc->nbytes = scsi_bufflen(scmd) + scmd->request->extra_len;
 
        /* request result TF and be quiet about device error */
        qc->flags |= ATA_QCFLAG_RESULT_TF | ATA_QCFLAG_QUIET;
@@ -3528,7 +3606,7 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
  *     @ap: Port to initialize
  *
  *     Called just after data structures for each port are
- *     initialized.  Allocates DMA pad.
+ *     initialized.
  *
  *     May be used as the port_start() entry in ata_port_operations.
  *
@@ -3537,7 +3615,7 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
  */
 int ata_sas_port_start(struct ata_port *ap)
 {
-       return ata_pad_alloc(ap, ap->dev);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(ata_sas_port_start);
 
@@ -3545,8 +3623,6 @@ EXPORT_SYMBOL_GPL(ata_sas_port_start);
  *     ata_port_stop - Undo ata_sas_port_start()
  *     @ap: Port to shut down
  *
- *     Frees the DMA pad.
- *
  *     May be used as the port_stop() entry in ata_port_operations.
  *
  *     LOCKING:
@@ -3555,7 +3631,6 @@ EXPORT_SYMBOL_GPL(ata_sas_port_start);
 
 void ata_sas_port_stop(struct ata_port *ap)
 {
-       ata_pad_free(ap, ap->dev);
 }
 EXPORT_SYMBOL_GPL(ata_sas_port_stop);