Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148118504
D49748.id154375.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D49748.id154375.diff
View Options
diff --git a/sys/dev/mpi3mr/mpi3mr.h b/sys/dev/mpi3mr/mpi3mr.h
--- a/sys/dev/mpi3mr/mpi3mr.h
+++ b/sys/dev/mpi3mr/mpi3mr.h
@@ -141,6 +141,7 @@
#define MPI3MR_HOSTTAG_PELABORT 3
#define MPI3MR_HOSTTAG_PELWAIT 4
#define MPI3MR_HOSTTAG_TMS 5
+#define MPI3MR_HOSTTAG_CFGCMDS 6
#define MAX_MGMT_ADAPTERS 8
#define MPI3MR_WAIT_BEFORE_CTRL_RESET 5
@@ -163,7 +164,7 @@
raw_os_ver[3], raw_os_ver[4], raw_os_ver[5],\
raw_os_ver[6]);
#define MPI3MR_NUM_DEVRMCMD 1
-#define MPI3MR_HOSTTAG_DEVRMCMD_MIN (MPI3MR_HOSTTAG_TMS + 1)
+#define MPI3MR_HOSTTAG_DEVRMCMD_MIN (MPI3MR_HOSTTAG_CFGCMDS + 1)
#define MPI3MR_HOSTTAG_DEVRMCMD_MAX (MPI3MR_HOSTTAG_DEVRMCMD_MIN + \
MPI3MR_NUM_DEVRMCMD - 1)
#define MPI3MR_INTERNALCMDS_RESVD MPI3MR_HOSTTAG_DEVRMCMD_MAX
@@ -237,6 +238,8 @@
#define WRITE_SAME_32 0x0d
+#define MPI3MR_TSUPDATE_INTERVAL 900
+
struct completion {
unsigned int done;
struct mtx lock;
@@ -313,6 +316,7 @@
MPI3MR_RESET_FROM_SCSIIO_TIMEOUT = 26,
MPI3MR_RESET_FROM_FIRMWARE = 27,
MPI3MR_DEFAULT_RESET_REASON = 28,
+ MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT = 29,
MPI3MR_RESET_REASON_COUNT,
};
@@ -555,6 +559,7 @@
char driver_name[MPI3MR_NAME_LENGTH];
int bars;
bus_addr_t dma_loaddr;
+ bus_addr_t dma_hiaddr;
u_int mpi3mr_debug;
struct mpi3mr_reset reset;
int max_msix_vectors;
@@ -688,6 +693,7 @@
struct mpi3mr_drvr_cmd host_tm_cmds;
struct mpi3mr_drvr_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD];
struct mpi3mr_drvr_cmd evtack_cmds[MPI3MR_NUM_EVTACKCMD];
+ struct mpi3mr_drvr_cmd cfg_cmds;
U16 devrem_bitmap_sz;
void *devrem_bitmap;
@@ -765,6 +771,10 @@
struct dma_memory_desc ioctl_chain_sge;
struct dma_memory_desc ioctl_resp_sge;
bool ioctl_sges_allocated;
+ struct proc *timestamp_thread_proc;
+ void *timestamp_chan;
+ u_int8_t timestamp_thread_active;
+ U32 ts_update_interval;
};
static __inline uint64_t
@@ -977,6 +987,7 @@
mpi3mrsas_release_simq_reinit(struct mpi3mr_cam_softc *cam_sc);
void
mpi3mr_watchdog_thread(void *arg);
+void mpi3mr_timestamp_thread(void *arg);
void mpi3mr_add_device(struct mpi3mr_softc *sc, U16 per_id);
int mpi3mr_remove_device(struct mpi3mr_softc *sc, U16 handle);
int
@@ -996,4 +1007,5 @@
void int_to_lun(unsigned int lun, U8 *req_lun);
void trigger_reset_from_watchdog(struct mpi3mr_softc *sc, U8 reset_type, U16 reset_reason);
void mpi3mr_alloc_ioctl_dma_memory(struct mpi3mr_softc *sc);
+int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_softc *sc);
#endif /*MPI3MR_H_INCLUDED*/
diff --git a/sys/dev/mpi3mr/mpi3mr.c b/sys/dev/mpi3mr/mpi3mr.c
--- a/sys/dev/mpi3mr/mpi3mr.c
+++ b/sys/dev/mpi3mr/mpi3mr.c
@@ -1338,6 +1338,7 @@
"diagnostic buffer post timeout"
},
{ MPI3MR_RESET_FROM_FIRMWARE, "firmware asynchronus reset" },
+ { MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT, "configuration request timeout" },
{ MPI3MR_RESET_REASON_COUNT, "Reset reason count" },
};
@@ -1915,6 +1916,15 @@
goto out_failed;
}
+ sc->cfg_cmds.reply = malloc(sc->reply_sz,
+ M_MPI3MR, M_NOWAIT | M_ZERO);
+
+ if (!sc->cfg_cmds.reply) {
+ printf(IOCNAME "Cannot allocate memory for cfg_cmds.reply\n",
+ sc->name);
+ goto out_failed;
+ }
+
sc->ioctl_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO);
if (!sc->ioctl_cmds.reply) {
printf(IOCNAME "Cannot allocate memory for ioctl_cmds.reply\n",
@@ -2877,6 +2887,12 @@
sc->init_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE;
sc->init_cmds.host_tag = MPI3MR_HOSTTAG_INITCMDS;
+ mtx_init(&sc->cfg_cmds.completion.lock, "CFG commands lock", NULL, MTX_DEF);
+ sc->cfg_cmds.reply = NULL;
+ sc->cfg_cmds.state = MPI3MR_CMD_NOTUSED;
+ sc->cfg_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE;
+ sc->cfg_cmds.host_tag = MPI3MR_HOSTTAG_CFGCMDS;
+
mtx_init(&sc->ioctl_cmds.completion.lock, "IOCTL commands lock", NULL, MTX_DEF);
sc->ioctl_cmds.reply = NULL;
sc->ioctl_cmds.state = MPI3MR_CMD_NOTUSED;
@@ -3042,6 +3058,9 @@
goto err;
}
+ if (mpi3mr_cfg_get_driver_pg1(sc) != 0)
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to get the cfg driver page1\n");
+
return retval;
err_retry:
@@ -3119,6 +3138,116 @@
return retval;
}
+static int mpi3mr_timestamp_sync(struct mpi3mr_softc *sc)
+{
+ int retval = 0;
+ struct timeval current_time;
+ int64_t time_in_msec;
+ Mpi3IoUnitControlRequest_t iou_ctrl = {0};
+
+ mtx_lock(&sc->init_cmds.completion.lock);
+ if (sc->init_cmds.state & MPI3MR_CMD_PENDING) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue timestamp sync: command is in use\n");
+ mtx_unlock(&sc->init_cmds.completion.lock);
+ return -1;
+ }
+
+ sc->init_cmds.state = MPI3MR_CMD_PENDING;
+ sc->init_cmds.is_waiting = 1;
+ sc->init_cmds.callback = NULL;
+ iou_ctrl.HostTag = htole64(MPI3MR_HOSTTAG_INITCMDS);
+ iou_ctrl.Function = MPI3_FUNCTION_IO_UNIT_CONTROL;
+ iou_ctrl.Operation = MPI3_CTRL_OP_UPDATE_TIMESTAMP;
+ getmicrotime(¤t_time);
+ time_in_msec = (int64_t)current_time.tv_sec * 1000 + current_time.tv_usec/1000;
+ iou_ctrl.Param64[0] = htole64(time_in_msec);
+
+ init_completion(&sc->init_cmds.completion);
+
+ retval = mpi3mr_submit_admin_cmd(sc, &iou_ctrl, sizeof(iou_ctrl));
+ if (retval) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "timestamp sync: Admin Post failed\n");
+ goto out_unlock;
+ }
+
+ wait_for_completion_timeout(&sc->init_cmds.completion,
+ (MPI3MR_INTADMCMD_TIMEOUT));
+
+ if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue timestamp sync: command timed out\n");
+ sc->init_cmds.is_waiting = 0;
+
+ if (!(sc->init_cmds.state & MPI3MR_CMD_RESET))
+ mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_TSU_TIMEOUT);
+
+ retval = -1;
+ goto out_unlock;
+ }
+
+ if (((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) != MPI3_IOCSTATUS_SUCCESS) &&
+ (sc->init_cmds.ioc_status != MPI3_IOCSTATUS_SUPERVISOR_ONLY)) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue timestamp sync: Failed IOCStatus(0x%04x) "
+ " Loginfo(0x%08x) \n", (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK),
+ sc->init_cmds.ioc_loginfo);
+ retval = -1;
+ }
+
+out_unlock:
+ sc->init_cmds.state = MPI3MR_CMD_NOTUSED;
+ mtx_unlock(&sc->init_cmds.completion.lock);
+
+ return retval;
+}
+
+void
+mpi3mr_timestamp_thread(void *arg)
+{
+ struct mpi3mr_softc *sc = (struct mpi3mr_softc *)arg;
+ U64 elapsed_time = 0;
+
+ sc->timestamp_thread_active = 1;
+ mtx_lock(&sc->reset_mutex);
+ while (1) {
+
+ if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN ||
+ (sc->unrecoverable == 1)) {
+ mpi3mr_dprint(sc, MPI3MR_INFO,
+ "Exit due to %s from %s\n",
+ sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN ? "Shutdown" :
+ "Hardware critical error", __func__);
+ break;
+ }
+ mtx_unlock(&sc->reset_mutex);
+
+ while (sc->reset_in_progress) {
+ if (elapsed_time)
+ elapsed_time = 0;
+ if (sc->unrecoverable)
+ break;
+ pause("mpi3mr_timestamp_thread", hz / 5);
+ }
+
+ if (elapsed_time++ >= sc->ts_update_interval * 60) {
+ mpi3mr_timestamp_sync(sc);
+ elapsed_time = 0;
+ }
+
+ /*
+ * Sleep for 1 second if we're not exiting, then loop to top
+ * to poll exit status and hardware health.
+ */
+ mtx_lock(&sc->reset_mutex);
+ if (((sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) == 0) &&
+ (!sc->unrecoverable) && (!sc->reset_in_progress)) {
+ msleep(&sc->timestamp_chan, &sc->reset_mutex, PRIBIO,
+ "mpi3mr_timestamp", 1 * hz);
+ }
+ }
+ mtx_unlock(&sc->reset_mutex);
+ sc->timestamp_thread_active = 0;
+ kproc_exit(0);
+}
+
void
mpi3mr_watchdog_thread(void *arg)
{
@@ -4398,6 +4527,9 @@
case MPI3MR_HOSTTAG_INITCMDS:
cmdptr = &sc->init_cmds;
break;
+ case MPI3MR_HOSTTAG_CFGCMDS:
+ cmdptr = &sc->cfg_cmds;
+ break;
case MPI3MR_HOSTTAG_IOCTLCMDS:
cmdptr = &sc->ioctl_cmds;
break;
@@ -5303,6 +5435,184 @@
mpi3mr_free_ioctl_dma_memory(sc);
}
+static void inline
+mpi3mr_free_dma_mem(struct mpi3mr_softc *sc,
+ struct dma_memory_desc *mem_desc)
+{
+ if (mem_desc->dma_addr)
+ bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap);
+
+ if (mem_desc->addr != NULL) {
+ bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap);
+ mem_desc->addr = NULL;
+ }
+
+ if (mem_desc->tag != NULL)
+ bus_dma_tag_destroy(mem_desc->tag);
+}
+
+static int
+mpi3mr_alloc_dma_mem(struct mpi3mr_softc *sc,
+ struct dma_memory_desc *mem_desc)
+{
+ int retval;
+
+ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */
+ 4, 0, /* algnmnt, boundary */
+ sc->dma_loaddr, /* lowaddr */
+ sc->dma_hiaddr, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ mem_desc->size, /* maxsize */
+ 1, /* nsegments */
+ mem_desc->size, /* maxsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &mem_desc->tag)) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate DMA tag\n", __func__);
+ return ENOMEM;
+ }
+
+ if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr,
+ BUS_DMA_NOWAIT, &mem_desc->dmamap)) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate DMA memory\n", __func__);
+ retval = ENOMEM;
+ goto out;
+ }
+
+ bzero(mem_desc->addr, mem_desc->size);
+
+ bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size,
+ mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT);
+
+ if (!mem_desc->addr) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot load DMA map\n", __func__);
+ retval = ENOMEM;
+ goto out;
+ }
+ return 0;
+out:
+ mpi3mr_free_dma_mem(sc, mem_desc);
+ return retval;
+}
+
+static int
+mpi3mr_post_cfg_req(struct mpi3mr_softc *sc, Mpi3ConfigRequest_t *cfg_req)
+{
+ int retval;
+
+ mtx_lock(&sc->cfg_cmds.completion.lock);
+ if (sc->cfg_cmds.state & MPI3MR_CMD_PENDING) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue cfg request: cfg command is in use\n");
+ mtx_unlock(&sc->cfg_cmds.completion.lock);
+ return -1;
+ }
+
+ sc->cfg_cmds.state = MPI3MR_CMD_PENDING;
+ sc->cfg_cmds.is_waiting = 1;
+ sc->cfg_cmds.callback = NULL;
+ sc->cfg_cmds.ioc_status = 0;
+ sc->cfg_cmds.ioc_loginfo = 0;
+
+ cfg_req->HostTag = htole16(MPI3MR_HOSTTAG_CFGCMDS);
+ cfg_req->Function = MPI3_FUNCTION_CONFIG;
+ cfg_req->PageType = MPI3_CONFIG_PAGETYPE_DRIVER;
+ cfg_req->PageNumber = 1;
+ cfg_req->PageAddress = 0;
+
+ init_completion(&sc->cfg_cmds.completion);
+
+ retval = mpi3mr_submit_admin_cmd(sc, cfg_req, sizeof(*cfg_req));
+ if (retval) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue cfg request: Admin Post failed\n");
+ goto out;
+ }
+
+ wait_for_completion_timeout(&sc->cfg_cmds.completion,
+ (MPI3MR_INTADMCMD_TIMEOUT));
+
+ if (!(sc->cfg_cmds.state & MPI3MR_CMD_COMPLETE)) {
+ if (!(sc->cfg_cmds.state & MPI3MR_CMD_RESET)) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "config request command timed out\n");
+ mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_CFG_REQ_TIMEOUT);
+ }
+ retval = -1;
+ sc->cfg_cmds.is_waiting = 0;
+ goto out;
+ }
+
+ if ((sc->cfg_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) !=
+ MPI3_IOCSTATUS_SUCCESS ) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "config request failed, IOCStatus(0x%04x) "
+ " Loginfo(0x%08x) \n",(sc->cfg_cmds.ioc_status &
+ MPI3_IOCSTATUS_STATUS_MASK), sc->cfg_cmds.ioc_loginfo);
+ retval = -1;
+ }
+
+out:
+ sc->cfg_cmds.state = MPI3MR_CMD_NOTUSED;
+ mtx_unlock(&sc->cfg_cmds.completion.lock);
+ return retval;
+}
+
+static int mpi3mr_process_cfg_req(struct mpi3mr_softc *sc,
+ Mpi3ConfigRequest_t *cfg_req,
+ Mpi3ConfigPageHeader_t *cfg_hdr,
+ void *cfg_buf, U32 cfg_buf_sz)
+{
+ int retval;
+ struct dma_memory_desc mem_desc = {0};
+
+ if (cfg_req->Action == MPI3_CONFIG_ACTION_PAGE_HEADER)
+ mem_desc.size = sizeof(Mpi3ConfigPageHeader_t);
+ else {
+ mem_desc.size = le16toh(cfg_hdr->PageLength) * 4;
+ cfg_req->PageLength = cfg_hdr->PageLength;
+ cfg_req->PageVersion = cfg_hdr->PageVersion;
+ }
+
+ retval = mpi3mr_alloc_dma_mem(sc, &mem_desc);
+ if (retval) {
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Failed to allocate DMA memory\n", __func__);
+ return retval;
+ }
+
+ mpi3mr_add_sg_single(&cfg_req->SGL, MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST,
+ mem_desc.size, mem_desc.dma_addr);
+
+ retval = mpi3mr_post_cfg_req(sc, cfg_req);
+ if (retval)
+ mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Failed to post config request\n", __func__);
+ else
+ memcpy(cfg_buf, mem_desc.addr, min(mem_desc.size, cfg_buf_sz));
+
+ mpi3mr_free_dma_mem(sc, &mem_desc);
+ return retval;
+}
+
+int mpi3mr_cfg_get_driver_pg1(struct mpi3mr_softc *sc)
+{
+ int retval;
+ Mpi3DriverPage1_t driver_pg1 = {0};
+ Mpi3ConfigPageHeader_t cfg_hdr = {0};
+ Mpi3ConfigRequest_t cfg_req = {0};
+
+ cfg_req.Action = MPI3_CONFIG_ACTION_PAGE_HEADER;
+ retval = mpi3mr_process_cfg_req(sc, &cfg_req, NULL, &cfg_hdr, sizeof(cfg_hdr));
+ if (retval)
+ goto error;
+
+ cfg_req.Action = MPI3_CONFIG_ACTION_READ_CURRENT;
+ retval = mpi3mr_process_cfg_req(sc, &cfg_req, &cfg_hdr, &driver_pg1, sizeof(driver_pg1));
+
+error:
+ if (!retval && driver_pg1.TimeStampUpdate)
+ sc->ts_update_interval = driver_pg1.TimeStampUpdate;
+ else
+ sc->ts_update_interval = MPI3MR_TSUPDATE_INTERVAL;
+
+ return retval;
+}
+
void
mpi3mr_destory_mtx(struct mpi3mr_softc *sc)
{
@@ -5334,6 +5644,9 @@
if (mtx_initialized(&sc->init_cmds.completion.lock))
mtx_destroy(&sc->init_cmds.completion.lock);
+ if (mtx_initialized(&sc->cfg_cmds.completion.lock))
+ mtx_destroy(&sc->cfg_cmds.completion.lock);
+
if (mtx_initialized(&sc->ioctl_cmds.completion.lock))
mtx_destroy(&sc->ioctl_cmds.completion.lock);
@@ -5512,6 +5825,11 @@
sc->init_cmds.reply = NULL;
}
+ if (sc->cfg_cmds.reply) {
+ free(sc->cfg_cmds.reply, M_MPI3MR);
+ sc->cfg_cmds.reply = NULL;
+ }
+
if (sc->ioctl_cmds.reply) {
free(sc->ioctl_cmds.reply, M_MPI3MR);
sc->ioctl_cmds.reply = NULL;
@@ -5629,6 +5947,9 @@
cmdptr = &sc->init_cmds;
mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
+ cmdptr = &sc->cfg_cmds;
+ mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
+
cmdptr = &sc->ioctl_cmds;
mpi3mr_drv_cmd_comp_reset(sc, cmdptr);
@@ -5672,6 +5993,7 @@
memset(sc->admin_reply, 0, sc->admin_reply_q_sz);
memset(sc->init_cmds.reply, 0, sc->reply_sz);
+ memset(sc->cfg_cmds.reply, 0, sc->reply_sz);
memset(sc->ioctl_cmds.reply, 0, sc->reply_sz);
memset(sc->host_tm_cmds.reply, 0, sc->reply_sz);
memset(sc->pel_cmds.reply, 0, sc->reply_sz);
@@ -6014,6 +6336,9 @@
sc->reset_in_progress = 1;
sc->block_ioctls = 1;
+ if (sc->timestamp_thread_active)
+ wakeup(&sc->timestamp_chan);
+
while (mpi3mr_atomic_read(&sc->pend_ioctls) && (i < PEND_IOCTLS_COMP_WAIT_TIME)) {
ioc_state = mpi3mr_get_iocstate(sc);
if (ioc_state == MRIOC_STATE_FAULT)
diff --git a/sys/dev/mpi3mr/mpi3mr_pci.c b/sys/dev/mpi3mr/mpi3mr_pci.c
--- a/sys/dev/mpi3mr/mpi3mr_pci.c
+++ b/sys/dev/mpi3mr/mpi3mr_pci.c
@@ -332,6 +332,13 @@
mtx_unlock(&sc->mpi3mr_mtx);
+ error = mpi3mr_kproc_create(mpi3mr_timestamp_thread, sc,
+ &sc->timestamp_thread_proc, 0, 0,
+ "mpi3mr_timestamp_thread%d",
+ device_get_unit(sc->mpi3mr_dev));
+ if (error)
+ device_printf(sc->mpi3mr_dev, "Error %d starting timestamp thread\n", error);
+
error = mpi3mr_kproc_create(mpi3mr_watchdog_thread, sc,
&sc->watchdog_thread, 0, 0, "mpi3mr_watchdog%d",
device_get_unit(sc->mpi3mr_dev));
@@ -474,7 +481,7 @@
mpi3mr_dprint(sc, MPI3MR_ERROR, "CAM attach failed\n");
goto load_failed;
}
-
+
sc->mpi3mr_ich.ich_func = mpi3mr_ich_startup;
sc->mpi3mr_ich.ich_arg = sc;
if (config_intrhook_establish(&sc->mpi3mr_ich) != 0) {
@@ -664,10 +671,26 @@
mtx_lock(&sc->reset_mutex);
sc->mpi3mr_flags |= MPI3MR_FLAGS_SHUTDOWN;
+ if (sc->timestamp_thread_active)
+ wakeup(&sc->timestamp_chan);
+
if (sc->watchdog_thread_active)
wakeup(&sc->watchdog_chan);
mtx_unlock(&sc->reset_mutex);
+ i = 0;
+ while (sc->timestamp_thread_active && (i < 180)) {
+ i++;
+ if (!(i % 5)) {
+ mpi3mr_dprint(sc, MPI3MR_INFO,
+ "[%2d]waiting for "
+ "timestamp thread to quit reset %d\n", i,
+ sc->timestamp_thread_active);
+ }
+ pause("mpi3mr_shutdown", hz);
+ }
+
+ i = 0;
while (sc->reset_in_progress && (i < PEND_IOCTLS_COMP_WAIT_TIME)) {
i++;
if (!(i % 5)) {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 16, 10:15 PM (17 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29790375
Default Alt Text
D49748.id154375.diff (15 KB)
Attached To
Mode
D49748: mpi3mr: Add NVData Parameter for Host Timestamp Synchronization
Attached
Detach File
Event Timeline
Log In to Comment