diff options
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r-- | drivers/ata/libata-scsi.c | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 14daf4848f09..c02c490122dc 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -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); @@ -839,7 +839,14 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, if (dev->class == ATA_DEV_ATAPI) { struct request_queue *q = sdev->request_queue; blk_queue_max_hw_segments(q, q->max_hw_segments - 1); - } + + /* set the min alignment */ + blk_queue_update_dma_alignment(sdev->request_queue, + ATA_DMA_PAD_SZ - 1); + } else + /* ATA devices must be sector aligned */ + blk_queue_update_dma_alignment(sdev->request_queue, + ATA_SECT_SIZE - 1); if (dev->class == ATA_DEV_ATA) sdev->manage_start_stop = 1; @@ -878,7 +885,7 @@ int ata_scsi_slave_config(struct scsi_device *sdev) if (dev) ata_scsi_dev_config(sdev, dev); - return 0; /* scsi layer doesn't check return value, sigh */ + return 0; } /** @@ -2210,7 +2217,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 +2231,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 +2338,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 +2348,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 +2361,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; } @@ -2526,12 +2535,12 @@ 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)) @@ -2690,6 +2699,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; |