lkml.org 
[lkml]   [2012]   [Jul]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[ 035/108] [SCSI] libsas: fix taskfile corruption in sas_ata_qc_fill_rtf
    3.2-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Dan Williams <dan.j.williams@intel.com>

    commit 6ef1b512f4e6f936d89aa20be3d97a7ec7c290ac upstream.

    fill_result_tf() grabs the taskfile flags from the originating qc which
    sas_ata_qc_fill_rtf() promptly overwrites. The presence of an
    ata_taskfile in the sata_device makes it tempting to just copy the full
    contents in sas_ata_qc_fill_rtf(). However, libata really only wants
    the fis contents and expects the other portions of the taskfile to not
    be touched by ->qc_fill_rtf. To that end store a fis buffer in the
    sata_device and use ata_tf_from_fis() like every other ->qc_fill_rtf()
    implementation.

    Reported-by: Praveen Murali <pmurali@logicube.com>
    Tested-by: Praveen Murali <pmurali@logicube.com>
    Signed-off-by: Dan Williams <dan.j.williams@intel.com>
    Signed-off-by: James Bottomley <JBottomley@Parallels.com>
    [bwh: Backported to 3.2: adjust context]
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    drivers/scsi/aic94xx/aic94xx_task.c | 2 +-
    drivers/scsi/libsas/sas_ata.c | 12 ++++++------
    include/scsi/libsas.h | 6 ++++--
    3 files changed, 11 insertions(+), 9 deletions(-)

    --- a/drivers/scsi/aic94xx/aic94xx_task.c
    +++ b/drivers/scsi/aic94xx/aic94xx_task.c
    @@ -201,7 +201,7 @@ static void asd_get_response_tasklet(str

    if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
    resp->frame_len = le16_to_cpu(*(__le16 *)(r+6));
    - memcpy(&resp->ending_fis[0], r+16, 24);
    + memcpy(&resp->ending_fis[0], r+16, ATA_RESP_FIS_SIZE);
    ts->buf_valid_size = sizeof(*resp);
    }
    }
    --- a/drivers/scsi/libsas/sas_ata.c
    +++ b/drivers/scsi/libsas/sas_ata.c
    @@ -112,12 +112,12 @@ static void sas_ata_task_done(struct sas
    if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD ||
    ((stat->stat == SAM_STAT_CHECK_CONDITION &&
    dev->sata_dev.command_set == ATAPI_COMMAND_SET))) {
    - ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf);
    + memcpy(dev->sata_dev.fis, resp->ending_fis, ATA_RESP_FIS_SIZE);

    if (!link->sactive) {
    - qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command);
    + qc->err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
    } else {
    - link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.tf.command);
    + link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
    if (unlikely(link->eh_info.err_mask))
    qc->flags |= ATA_QCFLAG_FAILED;
    }
    @@ -138,8 +138,8 @@ static void sas_ata_task_done(struct sas
    qc->flags |= ATA_QCFLAG_FAILED;
    }

    - dev->sata_dev.tf.feature = 0x04; /* status err */
    - dev->sata_dev.tf.command = ATA_ERR;
    + dev->sata_dev.fis[3] = 0x04; /* status err */
    + dev->sata_dev.fis[2] = ATA_ERR;
    }
    }

    @@ -252,7 +252,7 @@ static bool sas_ata_qc_fill_rtf(struct a
    {
    struct domain_device *dev = qc->ap->private_data;

    - memcpy(&qc->result_tf, &dev->sata_dev.tf, sizeof(qc->result_tf));
    + ata_tf_from_fis(dev->sata_dev.fis, &qc->result_tf);
    return true;
    }

    --- a/include/scsi/libsas.h
    +++ b/include/scsi/libsas.h
    @@ -159,6 +159,8 @@ enum ata_command_set {
    ATAPI_COMMAND_SET = 1,
    };

    +#define ATA_RESP_FIS_SIZE 24
    +
    struct sata_device {
    enum ata_command_set command_set;
    struct smp_resp rps_resp; /* report_phy_sata_resp */
    @@ -170,7 +172,7 @@ struct sata_device {

    struct ata_port *ap;
    struct ata_host ata_host;
    - struct ata_taskfile tf;
    + u8 fis[ATA_RESP_FIS_SIZE];
    u32 sstatus;
    u32 serror;
    u32 scontrol;
    @@ -486,7 +488,7 @@ enum exec_status {
    */
    struct ata_task_resp {
    u16 frame_len;
    - u8 ending_fis[24]; /* dev to host or data-in */
    + u8 ending_fis[ATA_RESP_FIS_SIZE]; /* dev to host or data-in */
    u32 sstatus;
    u32 serror;
    u32 scontrol;



    \
     
     \ /
      Last update: 2012-07-23 04:42    [W:5.123 / U:0.080 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site