]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/scsi/mpt2sas/mpt2sas_ctl.c
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
[mv-sheeva.git] / drivers / scsi / mpt2sas / mpt2sas_ctl.c
index d88e9756d8f5259ce156ee434ca7d3b2303816e0..b774973f07658a3346fa10239846ee74fc3783cf 100644 (file)
@@ -80,6 +80,32 @@ enum block_state {
        BLOCKING,
 };
 
+/**
+ * _ctl_sas_device_find_by_handle - sas device search
+ * @ioc: per adapter object
+ * @handle: sas device handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->sas_device_lock
+ *
+ * This searches for sas_device based on sas_address, then return sas_device
+ * object.
+ */
+static struct _sas_device *
+_ctl_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+       struct _sas_device *sas_device, *r;
+
+       r = NULL;
+       list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
+               if (sas_device->handle != handle)
+                       continue;
+               r = sas_device;
+               goto out;
+       }
+
+ out:
+       return r;
+}
+
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 /**
  * _ctl_display_some_debug - debug routine
@@ -188,14 +214,14 @@ _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
        if (!desc)
                return;
 
-       printk(MPT2SAS_DEBUG_FMT "%s: %s, smid(%d)\n",
+       printk(MPT2SAS_INFO_FMT "%s: %s, smid(%d)\n",
            ioc->name, calling_function_name, desc, smid);
 
        if (!mpi_reply)
                return;
 
        if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
-               printk(MPT2SAS_DEBUG_FMT
+               printk(MPT2SAS_INFO_FMT
                    "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
                    ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
                    le32_to_cpu(mpi_reply->IOCLogInfo));
@@ -205,8 +231,24 @@ _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
            MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
                Mpi2SCSIIOReply_t *scsi_reply =
                    (Mpi2SCSIIOReply_t *)mpi_reply;
+               struct _sas_device *sas_device = NULL;
+               unsigned long flags;
+
+               spin_lock_irqsave(&ioc->sas_device_lock, flags);
+               sas_device = _ctl_sas_device_find_by_handle(ioc,
+                   le16_to_cpu(scsi_reply->DevHandle));
+               if (sas_device) {
+                       printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), "
+                           "phy(%d)\n", ioc->name, (unsigned long long)
+                           sas_device->sas_address, sas_device->phy);
+                       printk(MPT2SAS_WARN_FMT
+                           "\tenclosure_logical_id(0x%016llx), slot(%d)\n",
+                           ioc->name, sas_device->enclosure_logical_id,
+                           sas_device->slot);
+               }
+               spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
                if (scsi_reply->SCSIState || scsi_reply->SCSIStatus)
-                       printk(MPT2SAS_DEBUG_FMT
+                       printk(MPT2SAS_INFO_FMT
                            "\tscsi_state(0x%02x), scsi_status"
                            "(0x%02x)\n", ioc->name,
                            scsi_reply->SCSIState,
@@ -233,6 +275,9 @@ mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
        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;
@@ -243,6 +288,20 @@ mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
        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);
@@ -392,7 +451,7 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
 
        switch (reset_phase) {
        case MPT2_IOC_PRE_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
                    "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
                for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
                        if (!(ioc->diag_buffer_status[i] &
@@ -405,7 +464,7 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
                }
                break;
        case MPT2_IOC_AFTER_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
                    "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
                if (ioc->ctl_cmds.status & MPT2_CMD_PENDING) {
                        ioc->ctl_cmds.status |= MPT2_CMD_RESET;
@@ -414,7 +473,7 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
                }
                break;
        case MPT2_IOC_DONE_RESET:
-               dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
                    "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
 
                for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
@@ -531,7 +590,7 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg,
        spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
 
        if (!found) {
-               dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
                    "handle(0x%04x), lun(%d), no active mid!!\n", ioc->name,
                    desc, le16_to_cpu(tm_request->DevHandle), lun));
                tm_reply = ioc->ctl_cmds.reply;
@@ -549,7 +608,7 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg,
                return 1;
        }
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
            "handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name,
            desc, le16_to_cpu(tm_request->DevHandle), lun,
             le16_to_cpu(tm_request->TaskMID)));
@@ -567,7 +626,7 @@ static long
 _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
     struct mpt2_ioctl_command karg, void __user *mf, enum block_state state)
 {
-       MPI2RequestHeader_t *mpi_request;
+       MPI2RequestHeader_t *mpi_request = NULL, *request;
        MPI2DefaultReply_t *mpi_reply;
        u32 ioc_state;
        u16 ioc_status;
@@ -576,7 +635,6 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
        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;
@@ -621,31 +679,50 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
                    ioc->name, __func__);
 
-       smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL);
-       if (!smid) {
-               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
-                   ioc->name, __func__);
-               ret = -EAGAIN;
+       mpi_request = kzalloc(ioc->request_sz, GFP_KERNEL);
+       if (!mpi_request) {
+               printk(MPT2SAS_ERR_FMT "%s: failed obtaining a memory for "
+                   "mpi_request\n", ioc->name, __func__);
+               ret = -ENOMEM;
                goto out;
        }
 
-       ret = 0;
-       ioc->ctl_cmds.status = MPT2_CMD_PENDING;
-       memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
-       mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
-       ioc->ctl_cmds.smid = smid;
-       data_out_sz = karg.data_out_size;
-       data_in_sz = karg.data_in_size;
-
        /* copy in request message frame from user */
        if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
                printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__,
                    __func__);
                ret = -EFAULT;
-               mpt2sas_base_free_smid(ioc, smid);
                goto out;
        }
 
+       if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
+               smid = mpt2sas_base_get_smid_hpr(ioc, ioc->ctl_cb_idx);
+               if (!smid) {
+                       printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+                           ioc->name, __func__);
+                       ret = -EAGAIN;
+                       goto out;
+               }
+       } else {
+
+               smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL);
+               if (!smid) {
+                       printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+                           ioc->name, __func__);
+                       ret = -EAGAIN;
+                       goto out;
+               }
+       }
+
+       ret = 0;
+       ioc->ctl_cmds.status = MPT2_CMD_PENDING;
+       memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
+       request = mpt2sas_base_get_msg_frame(ioc, smid);
+       memcpy(request, mpi_request, karg.data_sge_offset*4);
+       ioc->ctl_cmds.smid = smid;
+       data_out_sz = karg.data_out_size;
+       data_in_sz = karg.data_in_size;
+
        if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
            mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
                if (!le16_to_cpu(mpi_request->FunctionDependent1) ||
@@ -691,7 +768,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
        }
 
        /* add scatter gather elements */
-       psge = (void *)mpi_request + (karg.data_sge_offset*4);
+       psge = (void *)request + (karg.data_sge_offset*4);
 
        if (!data_out_sz && !data_in_sz) {
                mpt2sas_base_build_zero_len_sge(ioc, psge);
@@ -739,11 +816,11 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
        case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
        {
                Mpi2SCSIIORequest_t *scsiio_request =
-                   (Mpi2SCSIIORequest_t *)mpi_request;
+                   (Mpi2SCSIIORequest_t *)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));
@@ -754,9 +831,9 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
        case MPI2_FUNCTION_SCSI_TASK_MGMT:
        {
                Mpi2SCSITaskManagementRequest_t *tm_request =
-                   (Mpi2SCSITaskManagementRequest_t *)mpi_request;
+                   (Mpi2SCSITaskManagementRequest_t *)request;
 
-               dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: "
+               dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "TASK_MGMT: "
                    "handle(0x%04x), task_type(0x%02x)\n", ioc->name,
                    le16_to_cpu(tm_request->DevHandle), tm_request->TaskType));
 
@@ -851,7 +928,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                Mpi2SCSITaskManagementReply_t *tm_reply =
                    (Mpi2SCSITaskManagementReply_t *)mpi_reply;
 
-               printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: "
+               printk(MPT2SAS_INFO_FMT "TASK_MGMT: "
                    "IOCStatus(0x%04x), IOCLogInfo(0x%08x), "
                    "TerminationCount(0x%08x)\n", ioc->name,
                    le16_to_cpu(tm_reply->IOCStatus),
@@ -887,7 +964,8 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
            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;
@@ -926,6 +1004,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                pci_free_consistent(ioc->pdev, data_out_sz, data_out,
                    data_out_dma);
 
+       kfree(mpi_request);
        ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
        mutex_unlock(&ioc->ctl_cmds.mutex);
        return ret;
@@ -950,7 +1029,7 @@ _ctl_getiocinfo(void __user *arg)
        if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
            __func__));
 
        memset(&karg, 0 , sizeof(karg));
@@ -998,7 +1077,7 @@ _ctl_eventquery(void __user *arg)
        if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
            __func__));
 
        karg.event_entries = MPT2SAS_CTL_EVENT_LOG_SIZE;
@@ -1031,7 +1110,7 @@ _ctl_eventenable(void __user *arg)
        if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
            __func__));
 
        if (ioc->event_log)
@@ -1073,7 +1152,7 @@ _ctl_eventreport(void __user *arg)
        if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
            __func__));
 
        number_bytes = karg.hdr.max_data_size -
@@ -1118,7 +1197,7 @@ _ctl_do_reset(void __user *arg)
        if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
            __func__));
 
        retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
@@ -1219,7 +1298,7 @@ _ctl_btdh_mapping(void __user *arg)
        if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
            __func__));
 
        rc = _ctl_btdh_search_sas_device(ioc, &karg);
@@ -1288,7 +1367,7 @@ _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc,
        u16 ioc_status;
        u8 issue_reset = 0;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
            __func__));
 
        if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
@@ -1376,7 +1455,7 @@ _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc,
        mpi_request->VF_ID = 0; /* TODO */
        mpi_request->VP_ID = 0;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(0x%p), "
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(0x%p), "
            "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data,
            (unsigned long long)request_data_dma,
            le32_to_cpu(mpi_request->BufferLength)));
@@ -1414,10 +1493,10 @@ _ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc,
        if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
                ioc->diag_buffer_status[buffer_type] |=
                        MPT2_DIAG_BUFFER_IS_REGISTERED;
-               dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n",
+               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
                    ioc->name, __func__));
        } else {
-               printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
+               printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
                    "log_info(0x%08x)\n", ioc->name, __func__,
                    ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
                rc = -EFAULT;
@@ -1541,7 +1620,7 @@ _ctl_diag_unregister(void __user *arg)
        if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
            __func__));
 
        buffer_type = karg.unique_id & 0x000000ff;
@@ -1611,7 +1690,7 @@ _ctl_diag_query(void __user *arg)
        if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
            __func__));
 
        karg.application_flags = 0;
@@ -1689,7 +1768,7 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
        int rc;
        unsigned long timeleft;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
            __func__));
 
        rc = 0;
@@ -1697,7 +1776,7 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
 
        ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
        if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-               dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
                    "skipping due to FAULT state\n", ioc->name,
                    __func__));
                rc = -EAGAIN;
@@ -1759,10 +1838,10 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
        if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
                ioc->diag_buffer_status[buffer_type] |=
                    MPT2_DIAG_BUFFER_IS_RELEASED;
-               dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n",
+               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
                    ioc->name, __func__));
        } else {
-               printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
+               printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
                    "log_info(0x%08x)\n", ioc->name, __func__,
                    ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
                rc = -EFAULT;
@@ -1800,7 +1879,7 @@ _ctl_diag_release(void __user *arg, enum block_state state)
        if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
            __func__));
 
        buffer_type = karg.unique_id & 0x000000ff;
@@ -1896,7 +1975,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
        if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
            __func__));
 
        buffer_type = karg.unique_id & 0x000000ff;
@@ -1927,7 +2006,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
        }
 
        diag_data = (void *)(request_data + karg.starting_offset);
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(%p), "
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), "
            "offset(%d), sz(%d)\n", ioc->name, __func__,
            diag_data, karg.starting_offset, karg.bytes_to_read));
 
@@ -1942,11 +2021,11 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
        if ((karg.flags & MPT2_FLAGS_REREGISTER) == 0)
                return 0;
 
-       dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: Reregister "
+       dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: Reregister "
                "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type));
        if ((ioc->diag_buffer_status[buffer_type] &
            MPT2_DIAG_BUFFER_IS_RELEASED) == 0) {
-               dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
                    "buffer_type(0x%02x) is still registered\n", ioc->name,
                     __func__, buffer_type));
                return 0;
@@ -2020,10 +2099,10 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
        if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
                ioc->diag_buffer_status[buffer_type] |=
                    MPT2_DIAG_BUFFER_IS_REGISTERED;
-               dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n",
+               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: success\n",
                    ioc->name, __func__));
        } else {
-               printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
+               printk(MPT2SAS_INFO_FMT "%s: ioc_status(0x%04x) "
                    "log_info(0x%08x)\n", ioc->name, __func__,
                    ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
                rc = -EFAULT;
@@ -2077,7 +2156,7 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
                    !ioc)
                        return -ENODEV;
 
-               if (ioc->shost_recovery)
+               if (ioc->shost_recovery || ioc->pci_error_recovery)
                        return -EAGAIN;
 
                if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
@@ -2140,7 +2219,7 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
                    !ioc)
                        return -ENODEV;
 
-               dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+               dctlprintk(ioc, printk(MPT2SAS_INFO_FMT
                    "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd));
                break;
        }
@@ -2196,7 +2275,7 @@ _ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
        if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc)
                return -ENODEV;
 
-       if (ioc->shost_recovery)
+       if (ioc->shost_recovery || ioc->pci_error_recovery)
                return -EAGAIN;
 
        memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
@@ -2581,6 +2660,218 @@ _ctl_fwfault_debug_store(struct device *cdev,
 static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR,
     _ctl_fwfault_debug_show, _ctl_fwfault_debug_store);
 
+
+/**
+ * _ctl_ioc_reset_count_show - ioc reset count
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is firmware queue depth limit
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr,
+    char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+       return snprintf(buf, PAGE_SIZE, "%08d\n", ioc->ioc_reset_count);
+}
+static DEVICE_ATTR(ioc_reset_count, S_IRUGO,
+    _ctl_ioc_reset_count_show, NULL);
+
+struct DIAG_BUFFER_START {
+       u32 Size;
+       u32 DiagVersion;
+       u8 BufferType;
+       u8 Reserved[3];
+       u32 Reserved1;
+       u32 Reserved2;
+       u32 Reserved3;
+};
+/**
+ * _ctl_host_trace_buffer_size_show - host buffer size (trace only)
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_host_trace_buffer_size_show(struct device *cdev,
+    struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+       u32 size = 0;
+       struct DIAG_BUFFER_START *request_data;
+
+       if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
+               printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
+                   "registered\n", ioc->name, __func__);
+               return 0;
+       }
+
+       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
+               printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
+                   "registered\n", ioc->name, __func__);
+               return 0;
+       }
+
+       request_data = (struct DIAG_BUFFER_START *)
+           ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE];
+       if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 ||
+           le32_to_cpu(request_data->DiagVersion) == 0x01000000) &&
+           le32_to_cpu(request_data->Reserved3) == 0x4742444c)
+               size = le32_to_cpu(request_data->Size);
+
+       ioc->ring_buffer_sz = size;
+       return snprintf(buf, PAGE_SIZE, "%d\n", size);
+}
+static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO,
+        _ctl_host_trace_buffer_size_show, NULL);
+
+/**
+ * _ctl_host_trace_buffer_show - firmware ring buffer (trace only)
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ *
+ * You will only be able to read 4k bytes of ring buffer at a time.
+ * In order to read beyond 4k bytes, you will have to write out the
+ * offset to the same attribute, it will move the pointer.
+ */
+static ssize_t
+_ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr,
+     char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+       void *request_data;
+       u32 size;
+
+       if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) {
+               printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
+                   "registered\n", ioc->name, __func__);
+               return 0;
+       }
+
+       if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
+               printk(MPT2SAS_ERR_FMT "%s: host_trace_buffer is not "
+                   "registered\n", ioc->name, __func__);
+               return 0;
+       }
+
+       if (ioc->ring_buffer_offset > ioc->ring_buffer_sz)
+               return 0;
+
+       size = ioc->ring_buffer_sz - ioc->ring_buffer_offset;
+       size = (size > PAGE_SIZE) ? PAGE_SIZE : size;
+       request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset;
+       memcpy(buf, request_data, size);
+       return size;
+}
+
+static ssize_t
+_ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr,
+    const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+       int val = 0;
+
+       if (sscanf(buf, "%d", &val) != 1)
+               return -EINVAL;
+
+       ioc->ring_buffer_offset = val;
+       return strlen(buf);
+}
+static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR,
+    _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store);
+
+/*****************************************/
+
+/**
+ * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only)
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ *
+ * This is a mechnism to post/release host_trace_buffers
+ */
+static ssize_t
+_ctl_host_trace_buffer_enable_show(struct device *cdev,
+    struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+       if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) ||
+          ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT2_DIAG_BUFFER_IS_REGISTERED) == 0))
+               return snprintf(buf, PAGE_SIZE, "off\n");
+       else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+           MPT2_DIAG_BUFFER_IS_RELEASED))
+               return snprintf(buf, PAGE_SIZE, "release\n");
+       else
+               return snprintf(buf, PAGE_SIZE, "post\n");
+}
+
+static ssize_t
+_ctl_host_trace_buffer_enable_store(struct device *cdev,
+    struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(cdev);
+       struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+       char str[10] = "";
+       struct mpt2_diag_register diag_register;
+       u8 issue_reset = 0;
+
+       if (sscanf(buf, "%s", str) != 1)
+               return -EINVAL;
+
+       if (!strcmp(str, "post")) {
+               /* exit out if host buffers are already posted */
+               if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) &&
+                   (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+                   MPT2_DIAG_BUFFER_IS_REGISTERED) &&
+                   ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+                   MPT2_DIAG_BUFFER_IS_RELEASED) == 0))
+                       goto out;
+               memset(&diag_register, 0, sizeof(struct mpt2_diag_register));
+               printk(MPT2SAS_INFO_FMT "posting host trace buffers\n",
+                   ioc->name);
+               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
+               diag_register.requested_buffer_size = (1024 * 1024);
+               diag_register.unique_id = 0x7075900;
+               ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
+               _ctl_diag_register_2(ioc,  &diag_register);
+       } else if (!strcmp(str, "release")) {
+               /* exit out if host buffers are already released */
+               if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE])
+                       goto out;
+               if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+                   MPT2_DIAG_BUFFER_IS_REGISTERED) == 0)
+                       goto out;
+               if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] &
+                   MPT2_DIAG_BUFFER_IS_RELEASED))
+                       goto out;
+               printk(MPT2SAS_INFO_FMT "releasing host trace buffer\n",
+                   ioc->name);
+               _ctl_send_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, &issue_reset);
+       }
+
+ out:
+       return strlen(buf);
+}
+static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR,
+    _ctl_host_trace_buffer_enable_show, _ctl_host_trace_buffer_enable_store);
+
 struct device_attribute *mpt2sas_host_attrs[] = {
        &dev_attr_version_fw,
        &dev_attr_version_bios,
@@ -2597,6 +2888,10 @@ struct device_attribute *mpt2sas_host_attrs[] = {
        &dev_attr_fwfault_debug,
        &dev_attr_fw_queue_depth,
        &dev_attr_host_sas_address,
+       &dev_attr_ioc_reset_count,
+       &dev_attr_host_trace_buffer_size,
+       &dev_attr_host_trace_buffer,
+       &dev_attr_host_trace_buffer_enable,
        NULL,
 };