|
@@ -95,6 +95,9 @@ MODULE_PARM_DESC(disable_discovery, " disable discovery ");
|
|
|
static int
|
|
|
_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag);
|
|
|
|
|
|
+static int
|
|
|
+_base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag);
|
|
|
+
|
|
|
/**
|
|
|
* _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug.
|
|
|
*
|
|
@@ -3460,6 +3463,64 @@ _base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * _base_wait_for_iocstate - Wait until the card is in READY or OPERATIONAL
|
|
|
+ * @ioc: per adapter object
|
|
|
+ * @timeout:
|
|
|
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
|
|
|
+ *
|
|
|
+ * Returns 0 for success, non-zero for failure.
|
|
|
+ */
|
|
|
+static int
|
|
|
+_base_wait_for_iocstate(struct MPT2SAS_ADAPTER *ioc, int timeout,
|
|
|
+ int sleep_flag)
|
|
|
+{
|
|
|
+ u32 ioc_state, doorbell;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
|
|
|
+ __func__));
|
|
|
+
|
|
|
+ if (ioc->pci_error_recovery)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ doorbell = mpt2sas_base_get_iocstate(ioc, 0);
|
|
|
+ ioc_state = doorbell & MPI2_IOC_STATE_MASK;
|
|
|
+ dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: ioc_state(0x%08x)\n",
|
|
|
+ ioc->name, __func__, ioc_state));
|
|
|
+
|
|
|
+ switch (ioc_state) {
|
|
|
+ case MPI2_IOC_STATE_READY:
|
|
|
+ case MPI2_IOC_STATE_OPERATIONAL:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (doorbell & MPI2_DOORBELL_USED) {
|
|
|
+ dhsprintk(ioc, printk(MPT2SAS_INFO_FMT
|
|
|
+ "unexpected doorbell activ!e\n", ioc->name));
|
|
|
+ goto issue_diag_reset;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ioc_state == MPI2_IOC_STATE_FAULT) {
|
|
|
+ mpt2sas_base_fault_info(ioc, doorbell &
|
|
|
+ MPI2_DOORBELL_DATA_MASK);
|
|
|
+ goto issue_diag_reset;
|
|
|
+ }
|
|
|
+
|
|
|
+ ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
|
|
|
+ timeout, sleep_flag);
|
|
|
+ if (ioc_state) {
|
|
|
+ printk(MPT2SAS_ERR_FMT
|
|
|
+ "%s: failed going to ready state (ioc_state=0x%x)\n",
|
|
|
+ ioc->name, __func__, ioc_state);
|
|
|
+ return -EFAULT;
|
|
|
+ }
|
|
|
+
|
|
|
+ issue_diag_reset:
|
|
|
+ rc = _base_diag_reset(ioc, sleep_flag);
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* _base_get_ioc_facts - obtain ioc facts reply and save in ioc
|
|
|
* @ioc: per adapter object
|
|
@@ -3478,6 +3539,13 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
|
|
|
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
|
|
|
__func__));
|
|
|
|
|
|
+ r = _base_wait_for_iocstate(ioc, 10, sleep_flag);
|
|
|
+ if (r) {
|
|
|
+ printk(MPT2SAS_ERR_FMT "%s: failed getting to correct state\n",
|
|
|
+ ioc->name, __func__);
|
|
|
+ return r;
|
|
|
+ }
|
|
|
+
|
|
|
mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t);
|
|
|
mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t);
|
|
|
memset(&mpi_request, 0, mpi_request_sz);
|