[SCSI] mpt2sas: Copy sense buffer instead of working on direct memory location
(1) driver was not setting the sense data size prior to sending SCSI_IO,
resulting in the 0x31190000 loginfo
(2) The driver needs to copy the sense data to local buffer prior
to releasing the request message frame. If not, the sense buffer gets
overwritten by the next SCSI_IO request.
Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index d848744..1f22a76 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -3668,12 +3668,14 @@
/* ctl module internal command bits */
ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+ ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
mutex_init(&ioc->ctl_cmds.mutex);
if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply ||
!ioc->scsih_cmds.reply || !ioc->tm_cmds.reply ||
- !ioc->config_cmds.reply || !ioc->ctl_cmds.reply) {
+ !ioc->config_cmds.reply || !ioc->ctl_cmds.reply ||
+ !ioc->ctl_cmds.sense) {
r = -ENOMEM;
goto out_free_resources;
}
@@ -3722,6 +3724,7 @@
kfree(ioc->config_cmds.reply);
kfree(ioc->base_cmds.reply);
kfree(ioc->ctl_cmds.reply);
+ kfree(ioc->ctl_cmds.sense);
kfree(ioc->pfacts);
ioc->ctl_cmds.reply = NULL;
ioc->base_cmds.reply = NULL;
@@ -3754,6 +3757,7 @@
kfree(ioc->pd_handles);
kfree(ioc->pfacts);
kfree(ioc->ctl_cmds.reply);
+ kfree(ioc->ctl_cmds.sense);
kfree(ioc->base_cmds.reply);
kfree(ioc->tm_cmds.reply);
kfree(ioc->transport_cmds.reply);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 6fdee16..2bbb870 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -247,6 +247,7 @@
* @mutex: mutex
* @done: completion
* @reply: reply message pointer
+ * @sense: sense data
* @status: MPT2_CMD_XXX status
* @smid: system message id
*/
@@ -254,6 +255,7 @@
struct mutex mutex;
struct completion done;
void *reply;
+ void *sense;
u16 status;
u16 smid;
};
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
index ce63a4a..c3f34a7 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -275,6 +275,9 @@
u32 reply)
{
MPI2DefaultReply_t *mpi_reply;
+ Mpi2SCSIIOReply_t *scsiio_reply;
+ const void *sense_data;
+ u32 sz;
if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED)
return 1;
@@ -285,6 +288,20 @@
if (mpi_reply) {
memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
ioc->ctl_cmds.status |= MPT2_CMD_REPLY_VALID;
+ /* get sense data */
+ if (mpi_reply->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
+ mpi_reply->Function ==
+ MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
+ scsiio_reply = (Mpi2SCSIIOReply_t *)mpi_reply;
+ if (scsiio_reply->SCSIState &
+ MPI2_SCSI_STATE_AUTOSENSE_VALID) {
+ sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
+ le32_to_cpu(scsiio_reply->SenseCount));
+ sense_data = mpt2sas_base_get_sense_buffer(ioc,
+ smid);
+ memcpy(ioc->ctl_cmds.sense, sense_data, sz);
+ }
+ }
}
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
_ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
@@ -618,7 +635,6 @@
u8 issue_reset;
u32 sz;
void *psge;
- void *priv_sense = NULL;
void *data_out = NULL;
dma_addr_t data_out_dma;
size_t data_out_sz = 0;
@@ -782,10 +798,10 @@
{
Mpi2SCSIIORequest_t *scsiio_request =
(Mpi2SCSIIORequest_t *)mpi_request;
+ scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
scsiio_request->SenseBufferLowAddress =
mpt2sas_base_get_sense_buffer_dma(ioc, smid);
- priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid);
- memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE);
+ memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE);
if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)
mpt2sas_base_put_smid_scsi_io(ioc, smid,
le16_to_cpu(mpi_request->FunctionDependent1));
@@ -929,7 +945,8 @@
MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function ==
MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE);
- if (copy_to_user(karg.sense_data_ptr, priv_sense, sz)) {
+ if (copy_to_user(karg.sense_data_ptr,
+ ioc->ctl_cmds.sense, sz)) {
printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
__LINE__, __func__);
ret = -ENODATA;