]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/scsi/mpt2sas/mpt2sas_ctl.c
Merge branch 'wmi' into release
[mv-sheeva.git] / drivers / scsi / mpt2sas / mpt2sas_ctl.c
index 57d7246339067992792a5b24b81d3cdb0a2e0692..84a124f8e21f040a0313cdd037c156233ebc00b0 100644 (file)
@@ -740,7 +740,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                Mpi2SCSIIORequest_t *scsiio_request =
                    (Mpi2SCSIIORequest_t *)mpi_request;
                scsiio_request->SenseBufferLowAddress =
-                   (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid);
+                   mpt2sas_base_get_sense_buffer_dma(ioc, smid);
                priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid);
                memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE);
                mpt2sas_base_put_smid_scsi_io(ioc, smid,
@@ -848,8 +848,9 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: "
                    "IOCStatus(0x%04x), IOCLogInfo(0x%08x), "
                    "TerminationCount(0x%08x)\n", ioc->name,
-                   tm_reply->IOCStatus, tm_reply->IOCLogInfo,
-                   tm_reply->TerminationCount);
+                   le16_to_cpu(tm_reply->IOCStatus),
+                   le32_to_cpu(tm_reply->IOCLogInfo),
+                   le32_to_cpu(tm_reply->TerminationCount));
        }
 #endif
        /* copy out xdata to user */
@@ -896,6 +897,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                        printk(MPT2SAS_INFO_FMT "issue target reset: handle "
                            "= (0x%04x)\n", ioc->name,
                            mpi_request->FunctionDependent1);
+                       mpt2sas_halt_firmware(ioc);
                        mutex_lock(&ioc->tm_cmds.mutex);
                        mpt2sas_scsih_issue_tm(ioc,
                            mpi_request->FunctionDependent1, 0,
@@ -1229,7 +1231,7 @@ _ctl_btdh_mapping(void __user *arg)
 /**
  * _ctl_diag_capability - return diag buffer capability
  * @ioc: per adapter object
- * @buffer_type: specifies either TRACE or SNAPSHOT
+ * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED
  *
  * returns 1 when diag buffer support is enabled in firmware
  */
@@ -1249,24 +1251,25 @@ _ctl_diag_capability(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type)
                    MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
                        rc = 1;
                break;
+       case MPI2_DIAG_BUF_TYPE_EXTENDED:
+               if (ioc->facts.IOCCapabilities &
+                   MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER)
+                       rc = 1;
        }
 
        return rc;
 }
 
 /**
- * _ctl_diag_register - application register with driver
- * @arg - user space buffer containing ioctl content
- * @state - NON_BLOCKING or BLOCKING
+ * _ctl_diag_register_2 - wrapper for registering diag buffer support
+ * @ioc: per adapter object
+ * @diag_register: the diag_register struct passed in from user space
  *
- * This will allow the driver to setup any required buffers that will be
- * needed by firmware to communicate with the driver.
  */
 static long
-_ctl_diag_register(void __user *arg, enum block_state state)
+_ctl_diag_register_2(struct MPT2SAS_ADAPTER *ioc,
+    struct mpt2_diag_register *diag_register)
 {
-       struct mpt2_diag_register karg;
-       struct MPT2SAS_ADAPTER *ioc;
        int rc, i;
        void *request_data = NULL;
        dma_addr_t request_data_dma;
@@ -1279,18 +1282,17 @@ _ctl_diag_register(void __user *arg, enum block_state state)
        u16 ioc_status;
        u8 issue_reset = 0;
 
-       if (copy_from_user(&karg, arg, sizeof(karg))) {
-               printk(KERN_ERR "failure at %s:%d/%s()!\n",
-                   __FILE__, __LINE__, __func__);
-               return -EFAULT;
-       }
-       if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
-               return -ENODEV;
-
        dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
            __func__));
 
-       buffer_type = karg.buffer_type;
+       if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
+               printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
+                   ioc->name, __func__);
+               rc = -EAGAIN;
+               goto out;
+       }
+
+       buffer_type = diag_register->buffer_type;
        if (!_ctl_diag_capability(ioc, buffer_type)) {
                printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
                    "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
@@ -1305,24 +1307,12 @@ _ctl_diag_register(void __user *arg, enum block_state state)
                return -EINVAL;
        }
 
-       if (karg.requested_buffer_size % 4)  {
+       if (diag_register->requested_buffer_size % 4)  {
                printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size "
                    "is not 4 byte aligned\n", ioc->name, __func__);
                return -EINVAL;
        }
 
-       if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
-               return -EAGAIN;
-       else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
-               return -ERESTARTSYS;
-
-       if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
-               printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
-                   ioc->name, __func__);
-               rc = -EAGAIN;
-               goto out;
-       }
-
        smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
        if (!smid) {
                printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
@@ -1338,12 +1328,12 @@ _ctl_diag_register(void __user *arg, enum block_state state)
        ioc->ctl_cmds.smid = smid;
 
        request_data = ioc->diag_buffer[buffer_type];
-       request_data_sz = karg.requested_buffer_size;
-       ioc->unique_id[buffer_type] = karg.unique_id;
+       request_data_sz = diag_register->requested_buffer_size;
+       ioc->unique_id[buffer_type] = diag_register->unique_id;
        ioc->diag_buffer_status[buffer_type] = 0;
-       memcpy(ioc->product_specific[buffer_type], karg.product_specific,
-           MPT2_PRODUCT_SPECIFIC_DWORDS);
-       ioc->diagnostic_flags[buffer_type] = karg.diagnostic_flags;
+       memcpy(ioc->product_specific[buffer_type],
+           diag_register->product_specific, MPT2_PRODUCT_SPECIFIC_DWORDS);
+       ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags;
 
        if (request_data) {
                request_data_dma = ioc->diag_buffer_dma[buffer_type];
@@ -1373,8 +1363,8 @@ _ctl_diag_register(void __user *arg, enum block_state state)
        }
 
        mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
-       mpi_request->BufferType = karg.buffer_type;
-       mpi_request->Flags = cpu_to_le32(karg.diagnostic_flags);
+       mpi_request->BufferType = diag_register->buffer_type;
+       mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags);
        mpi_request->BufferAddress = cpu_to_le64(request_data_dma);
        mpi_request->BufferLength = cpu_to_le32(request_data_sz);
        mpi_request->VF_ID = 0; /* TODO */
@@ -1422,7 +1412,7 @@ _ctl_diag_register(void __user *arg, enum block_state state)
        } else {
                printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
                    "log_info(0x%08x)\n", ioc->name, __func__,
-                   ioc_status, mpi_reply->IOCLogInfo);
+                   ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
                rc = -EFAULT;
        }
 
@@ -1438,6 +1428,83 @@ _ctl_diag_register(void __user *arg, enum block_state state)
                    request_data, request_data_dma);
 
        ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
+       return rc;
+}
+
+/**
+ * mpt2sas_enable_diag_buffer - enabling diag_buffers support driver load time
+ * @ioc: per adapter object
+ * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1
+ *
+ * This is called when command line option diag_buffer_enable is enabled
+ * at driver load time.
+ */
+void
+mpt2sas_enable_diag_buffer(struct MPT2SAS_ADAPTER *ioc, u8 bits_to_register)
+{
+       struct mpt2_diag_register diag_register;
+
+       memset(&diag_register, 0, sizeof(struct mpt2_diag_register));
+
+       if (bits_to_register & 1) {
+               printk(MPT2SAS_INFO_FMT "registering trace buffer support\n",
+                   ioc->name);
+               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
+               /* register for 1MB buffers  */
+               diag_register.requested_buffer_size = (1024 * 1024);
+               diag_register.unique_id = 0x7075900;
+               _ctl_diag_register_2(ioc,  &diag_register);
+       }
+
+       if (bits_to_register & 2) {
+               printk(MPT2SAS_INFO_FMT "registering snapshot buffer support\n",
+                   ioc->name);
+               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT;
+               /* register for 2MB buffers  */
+               diag_register.requested_buffer_size = 2 * (1024 * 1024);
+               diag_register.unique_id = 0x7075901;
+               _ctl_diag_register_2(ioc,  &diag_register);
+       }
+
+       if (bits_to_register & 4) {
+               printk(MPT2SAS_INFO_FMT "registering extended buffer support\n",
+                   ioc->name);
+               diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED;
+               /* register for 2MB buffers  */
+               diag_register.requested_buffer_size = 2 * (1024 * 1024);
+               diag_register.unique_id = 0x7075901;
+               _ctl_diag_register_2(ioc,  &diag_register);
+       }
+}
+
+/**
+ * _ctl_diag_register - application register with driver
+ * @arg - user space buffer containing ioctl content
+ * @state - NON_BLOCKING or BLOCKING
+ *
+ * This will allow the driver to setup any required buffers that will be
+ * needed by firmware to communicate with the driver.
+ */
+static long
+_ctl_diag_register(void __user *arg, enum block_state state)
+{
+       struct mpt2_diag_register karg;
+       struct MPT2SAS_ADAPTER *ioc;
+       long rc;
+
+       if (copy_from_user(&karg, arg, sizeof(karg))) {
+               printk(KERN_ERR "failure at %s:%d/%s()!\n",
+                   __FILE__, __LINE__, __func__);
+               return -EFAULT;
+       }
+       if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+               return -ENODEV;
+
+       if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
+               return -EAGAIN;
+       else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
+               return -ERESTARTSYS;
+       rc = _ctl_diag_register_2(ioc, &karg);
        mutex_unlock(&ioc->ctl_cmds.mutex);
        return rc;
 }
@@ -1600,7 +1667,7 @@ _ctl_diag_query(void __user *arg)
 /**
  * _ctl_send_release - Diag Release Message
  * @ioc: per adapter object
- * @buffer_type - specifies either TRACE or SNAPSHOT
+ * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED
  * @issue_reset - specifies whether host reset is required.
  *
  */
@@ -1690,7 +1757,7 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
        } else {
                printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
                    "log_info(0x%08x)\n", ioc->name, __func__,
-                   ioc_status, mpi_reply->IOCLogInfo);
+                   ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
                rc = -EFAULT;
        }
 
@@ -1951,7 +2018,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
        } else {
                printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
                    "log_info(0x%08x)\n", ioc->name, __func__,
-                   ioc_status, mpi_reply->IOCLogInfo);
+                   ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo));
                rc = -EFAULT;
        }
 
@@ -2474,6 +2541,43 @@ _ctl_logging_level_store(struct device *cdev, struct device_attribute *attr,
 static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR,
     _ctl_logging_level_show, _ctl_logging_level_store);
 
+/* device attributes */
+/*
+ * _ctl_fwfault_debug_show - show/store fwfault_debug
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * mpt2sas_fwfault_debug is command line option
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_fwfault_debug_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, "%d\n", ioc->fwfault_debug);
+}
+static ssize_t
+_ctl_fwfault_debug_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->fwfault_debug = val;
+       printk(MPT2SAS_INFO_FMT "fwfault_debug=%d\n", ioc->name,
+           ioc->fwfault_debug);
+       return strlen(buf);
+}
+static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR,
+    _ctl_fwfault_debug_show, _ctl_fwfault_debug_store);
+
 struct device_attribute *mpt2sas_host_attrs[] = {
        &dev_attr_version_fw,
        &dev_attr_version_bios,
@@ -2487,13 +2591,12 @@ struct device_attribute *mpt2sas_host_attrs[] = {
        &dev_attr_io_delay,
        &dev_attr_device_delay,
        &dev_attr_logging_level,
+       &dev_attr_fwfault_debug,
        &dev_attr_fw_queue_depth,
        &dev_attr_host_sas_address,
        NULL,
 };
 
-/* device attributes */
-
 /**
  * _ctl_device_sas_address_show - sas address
  * @cdev - pointer to embedded class device