|
@@ -6410,18 +6410,17 @@ static void lcb_shutdown(struct hfi1_devdata *dd, int abort)
|
|
|
*
|
|
|
* The expectation is that the caller of this routine would have taken
|
|
|
* care of properly transitioning the link into the correct state.
|
|
|
+ * NOTE: the caller needs to acquire the dd->dc8051_lock lock
|
|
|
+ * before calling this function.
|
|
|
*/
|
|
|
-static void dc_shutdown(struct hfi1_devdata *dd)
|
|
|
+static void _dc_shutdown(struct hfi1_devdata *dd)
|
|
|
{
|
|
|
- unsigned long flags;
|
|
|
+ lockdep_assert_held(&dd->dc8051_lock);
|
|
|
|
|
|
- spin_lock_irqsave(&dd->dc8051_lock, flags);
|
|
|
- if (dd->dc_shutdown) {
|
|
|
- spin_unlock_irqrestore(&dd->dc8051_lock, flags);
|
|
|
+ if (dd->dc_shutdown)
|
|
|
return;
|
|
|
- }
|
|
|
+
|
|
|
dd->dc_shutdown = 1;
|
|
|
- spin_unlock_irqrestore(&dd->dc8051_lock, flags);
|
|
|
/* Shutdown the LCB */
|
|
|
lcb_shutdown(dd, 1);
|
|
|
/*
|
|
@@ -6432,35 +6431,45 @@ static void dc_shutdown(struct hfi1_devdata *dd)
|
|
|
write_csr(dd, DC_DC8051_CFG_RST, 0x1);
|
|
|
}
|
|
|
|
|
|
+static void dc_shutdown(struct hfi1_devdata *dd)
|
|
|
+{
|
|
|
+ mutex_lock(&dd->dc8051_lock);
|
|
|
+ _dc_shutdown(dd);
|
|
|
+ mutex_unlock(&dd->dc8051_lock);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Calling this after the DC has been brought out of reset should not
|
|
|
* do any damage.
|
|
|
+ * NOTE: the caller needs to acquire the dd->dc8051_lock lock
|
|
|
+ * before calling this function.
|
|
|
*/
|
|
|
-static void dc_start(struct hfi1_devdata *dd)
|
|
|
+static void _dc_start(struct hfi1_devdata *dd)
|
|
|
{
|
|
|
- unsigned long flags;
|
|
|
- int ret;
|
|
|
+ lockdep_assert_held(&dd->dc8051_lock);
|
|
|
|
|
|
- spin_lock_irqsave(&dd->dc8051_lock, flags);
|
|
|
if (!dd->dc_shutdown)
|
|
|
- goto done;
|
|
|
- spin_unlock_irqrestore(&dd->dc8051_lock, flags);
|
|
|
+ return;
|
|
|
+
|
|
|
/* Take the 8051 out of reset */
|
|
|
write_csr(dd, DC_DC8051_CFG_RST, 0ull);
|
|
|
/* Wait until 8051 is ready */
|
|
|
- ret = wait_fm_ready(dd, TIMEOUT_8051_START);
|
|
|
- if (ret) {
|
|
|
+ if (wait_fm_ready(dd, TIMEOUT_8051_START))
|
|
|
dd_dev_err(dd, "%s: timeout starting 8051 firmware\n",
|
|
|
__func__);
|
|
|
- }
|
|
|
+
|
|
|
/* Take away reset for LCB and RX FPE (set in lcb_shutdown). */
|
|
|
write_csr(dd, DCC_CFG_RESET, 0x10);
|
|
|
/* lcb_shutdown() with abort=1 does not restore these */
|
|
|
write_csr(dd, DC_LCB_ERR_EN, dd->lcb_err_en);
|
|
|
- spin_lock_irqsave(&dd->dc8051_lock, flags);
|
|
|
dd->dc_shutdown = 0;
|
|
|
-done:
|
|
|
- spin_unlock_irqrestore(&dd->dc8051_lock, flags);
|
|
|
+}
|
|
|
+
|
|
|
+static void dc_start(struct hfi1_devdata *dd)
|
|
|
+{
|
|
|
+ mutex_lock(&dd->dc8051_lock);
|
|
|
+ _dc_start(dd);
|
|
|
+ mutex_unlock(&dd->dc8051_lock);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -8513,16 +8522,11 @@ static int do_8051_command(
|
|
|
{
|
|
|
u64 reg, completed;
|
|
|
int return_code;
|
|
|
- unsigned long flags;
|
|
|
unsigned long timeout;
|
|
|
|
|
|
hfi1_cdbg(DC8051, "type %d, data 0x%012llx", type, in_data);
|
|
|
|
|
|
- /*
|
|
|
- * Alternative to holding the lock for a long time:
|
|
|
- * - keep busy wait - have other users bounce off
|
|
|
- */
|
|
|
- spin_lock_irqsave(&dd->dc8051_lock, flags);
|
|
|
+ mutex_lock(&dd->dc8051_lock);
|
|
|
|
|
|
/* We can't send any commands to the 8051 if it's in reset */
|
|
|
if (dd->dc_shutdown) {
|
|
@@ -8548,10 +8552,8 @@ static int do_8051_command(
|
|
|
return_code = -ENXIO;
|
|
|
goto fail;
|
|
|
}
|
|
|
- spin_unlock_irqrestore(&dd->dc8051_lock, flags);
|
|
|
- dc_shutdown(dd);
|
|
|
- dc_start(dd);
|
|
|
- spin_lock_irqsave(&dd->dc8051_lock, flags);
|
|
|
+ _dc_shutdown(dd);
|
|
|
+ _dc_start(dd);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -8632,8 +8634,7 @@ static int do_8051_command(
|
|
|
write_csr(dd, DC_DC8051_CFG_HOST_CMD_0, 0);
|
|
|
|
|
|
fail:
|
|
|
- spin_unlock_irqrestore(&dd->dc8051_lock, flags);
|
|
|
-
|
|
|
+ mutex_unlock(&dd->dc8051_lock);
|
|
|
return return_code;
|
|
|
}
|
|
|
|
|
@@ -12007,6 +12008,10 @@ static void free_cntrs(struct hfi1_devdata *dd)
|
|
|
dd->scntrs = NULL;
|
|
|
kfree(dd->cntrnames);
|
|
|
dd->cntrnames = NULL;
|
|
|
+ if (dd->update_cntr_wq) {
|
|
|
+ destroy_workqueue(dd->update_cntr_wq);
|
|
|
+ dd->update_cntr_wq = NULL;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static u64 read_dev_port_cntr(struct hfi1_devdata *dd, struct cntr_entry *entry,
|
|
@@ -12162,7 +12167,7 @@ u64 write_port_cntr(struct hfi1_pportdata *ppd, int index, int vl, u64 data)
|
|
|
return write_dev_port_cntr(ppd->dd, entry, sval, ppd, vl, data);
|
|
|
}
|
|
|
|
|
|
-static void update_synth_timer(unsigned long opaque)
|
|
|
+static void do_update_synth_timer(struct work_struct *work)
|
|
|
{
|
|
|
u64 cur_tx;
|
|
|
u64 cur_rx;
|
|
@@ -12171,8 +12176,8 @@ static void update_synth_timer(unsigned long opaque)
|
|
|
int i, j, vl;
|
|
|
struct hfi1_pportdata *ppd;
|
|
|
struct cntr_entry *entry;
|
|
|
-
|
|
|
- struct hfi1_devdata *dd = (struct hfi1_devdata *)opaque;
|
|
|
+ struct hfi1_devdata *dd = container_of(work, struct hfi1_devdata,
|
|
|
+ update_cntr_work);
|
|
|
|
|
|
/*
|
|
|
* Rather than keep beating on the CSRs pick a minimal set that we can
|
|
@@ -12255,7 +12260,13 @@ static void update_synth_timer(unsigned long opaque)
|
|
|
} else {
|
|
|
hfi1_cdbg(CNTR, "[%d] No update necessary", dd->unit);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
+static void update_synth_timer(unsigned long opaque)
|
|
|
+{
|
|
|
+ struct hfi1_devdata *dd = (struct hfi1_devdata *)opaque;
|
|
|
+
|
|
|
+ queue_work(dd->update_cntr_wq, &dd->update_cntr_work);
|
|
|
mod_timer(&dd->synth_stats_timer, jiffies + HZ * SYNTH_CNT_TIME);
|
|
|
}
|
|
|
|
|
@@ -12491,6 +12502,13 @@ static int init_cntrs(struct hfi1_devdata *dd)
|
|
|
if (init_cpu_counters(dd))
|
|
|
goto bail;
|
|
|
|
|
|
+ dd->update_cntr_wq = alloc_ordered_workqueue("hfi1_update_cntr_%d",
|
|
|
+ WQ_MEM_RECLAIM, dd->unit);
|
|
|
+ if (!dd->update_cntr_wq)
|
|
|
+ goto bail;
|
|
|
+
|
|
|
+ INIT_WORK(&dd->update_cntr_work, do_update_synth_timer);
|
|
|
+
|
|
|
mod_timer(&dd->synth_stats_timer, jiffies + HZ * SYNTH_CNT_TIME);
|
|
|
return 0;
|
|
|
bail:
|