mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
SCSI: libsas: fix taskfile corruption in sas_ata_qc_fill_rtf
commit 6ef1b512f4
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
5a89aae808
commit
76c6b958de
3 changed files with 11 additions and 9 deletions
|
@ -201,7 +201,7 @@ static void asd_get_response_tasklet(struct asd_ascb *ascb,
|
||||||
|
|
||||||
if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
|
if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
|
||||||
resp->frame_len = le16_to_cpu(*(__le16 *)(r+6));
|
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);
|
ts->buf_valid_size = sizeof(*resp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,12 +139,12 @@ static void sas_ata_task_done(struct sas_task *task)
|
||||||
if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD ||
|
if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD ||
|
||||||
((stat->stat == SAM_STAT_CHECK_CONDITION &&
|
((stat->stat == SAM_STAT_CHECK_CONDITION &&
|
||||||
dev->sata_dev.command_set == ATAPI_COMMAND_SET))) {
|
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) {
|
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 {
|
} 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))
|
if (unlikely(link->eh_info.err_mask))
|
||||||
qc->flags |= ATA_QCFLAG_FAILED;
|
qc->flags |= ATA_QCFLAG_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -161,8 +161,8 @@ static void sas_ata_task_done(struct sas_task *task)
|
||||||
qc->flags |= ATA_QCFLAG_FAILED;
|
qc->flags |= ATA_QCFLAG_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->sata_dev.tf.feature = 0x04; /* status err */
|
dev->sata_dev.fis[3] = 0x04; /* status err */
|
||||||
dev->sata_dev.tf.command = ATA_ERR;
|
dev->sata_dev.fis[2] = ATA_ERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
struct domain_device *dev = qc->ap->private_data;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,6 +163,8 @@ enum ata_command_set {
|
||||||
ATAPI_COMMAND_SET = 1,
|
ATAPI_COMMAND_SET = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ATA_RESP_FIS_SIZE 24
|
||||||
|
|
||||||
struct sata_device {
|
struct sata_device {
|
||||||
enum ata_command_set command_set;
|
enum ata_command_set command_set;
|
||||||
struct smp_resp rps_resp; /* report_phy_sata_resp */
|
struct smp_resp rps_resp; /* report_phy_sata_resp */
|
||||||
|
@ -171,7 +173,7 @@ struct sata_device {
|
||||||
|
|
||||||
struct ata_port *ap;
|
struct ata_port *ap;
|
||||||
struct ata_host ata_host;
|
struct ata_host ata_host;
|
||||||
struct ata_taskfile tf;
|
u8 fis[ATA_RESP_FIS_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -537,7 +539,7 @@ enum exec_status {
|
||||||
*/
|
*/
|
||||||
struct ata_task_resp {
|
struct ata_task_resp {
|
||||||
u16 frame_len;
|
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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SAS_STATUS_BUF_SIZE 96
|
#define SAS_STATUS_BUF_SIZE 96
|
||||||
|
|
Loading…
Reference in a new issue