aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2017-11-21 20:32:23 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-11-28 20:39:07 -0600
commitd7e26801905f40d807ce60bc99ed511e91549f1e (patch)
tree856716595f019ad0312f2902973324193f960212
parent9ce34f369ce2412cb68052717e457d1e78eedb75 (diff)
downloadskiboot-d7e26801905f40d807ce60bc99ed511e91549f1e.zip
skiboot-d7e26801905f40d807ce60bc99ed511e91549f1e.tar.gz
skiboot-d7e26801905f40d807ce60bc99ed511e91549f1e.tar.bz2
xive: When disabling an EQ, wipe all of its settings
This avoids having configuration bits left over Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--doc/xive.rst10
-rw-r--r--hw/xive.c101
2 files changed, 58 insertions, 53 deletions
diff --git a/doc/xive.rst b/doc/xive.rst
index c4f4950..85fe111 100644
--- a/doc/xive.rst
+++ b/doc/xive.rst
@@ -565,14 +565,18 @@ and priority and adjust the behaviour of the queue via flags.
.. note:: This call will reset the generation bit to 1 and the queue
production pointer to 0.
- .. note:: The PQ bits of the escalation interrupts will be set to 00
- when OPAL_XIVE_EQ_ENABLED is set, and to 01 (masked) when
- disabling it.
+ .. note:: The PQ bits of the escalation interrupts and of the queue
+ notification will be set to 00 when OPAL_XIVE_EQ_ENABLED is
+ set, and to 01 (masked) when disabling it.
.. note:: This must be called at least once on a queue with the flag
OPAL_XIVE_EQ_ENABLED in order to enable it after it has been
allocated (along with its owner VP).
+ .. note:: When the queue is disabled (flag OPAL_XIVE_EQ_ENABLED cleared)
+ all other flags and arguments are ignored and the queue
+ configuration is wiped.
+
OPAL_XIVE_DONATE_PAGE
^^^^^^^^^^^^^^^^^^^^^
.. code-block:: c
diff --git a/hw/xive.c b/hw/xive.c
index df38074..2f1ad57 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -3983,61 +3983,62 @@ static int64_t opal_xive_set_queue_info(uint64_t vp, uint32_t prio,
*/
eq = *old_eq;
- switch(qsize) {
- /* Supported sizes */
- case 12:
- case 16:
- case 21:
- case 24:
- eq.w3 = ((uint64_t)qpage) & 0xffffffff;
- eq.w2 = (((uint64_t)qpage)) >> 32 & 0x0fffffff;
- eq.w0 |= EQ_W0_ENQUEUE;
- eq.w0 = SETFIELD(EQ_W0_QSIZE, eq.w0, qsize - 12);
- break;
- case 0:
- eq.w2 = eq.w3 = 0;
- eq.w0 &= ~EQ_W0_ENQUEUE;
- break;
- default:
- return OPAL_PARAMETER;
- }
-
- /* Ensure the priority and target are correctly set (they will
- * not be right after allocation
- */
- eq.w6 = SETFIELD(EQ_W6_NVT_BLOCK, 0ul, vp_blk) |
- SETFIELD(EQ_W6_NVT_INDEX, 0ul, vp_idx);
- eq.w7 = SETFIELD(EQ_W7_F0_PRIORITY, 0ul, prio);
- /* XXX Handle group i bit when needed */
+ if (qflags & OPAL_XIVE_EQ_ENABLED) {
+ switch(qsize) {
+ /* Supported sizes */
+ case 12:
+ case 16:
+ case 21:
+ case 24:
+ eq.w3 = ((uint64_t)qpage) & 0xffffffff;
+ eq.w2 = (((uint64_t)qpage)) >> 32 & 0x0fffffff;
+ eq.w0 |= EQ_W0_ENQUEUE;
+ eq.w0 = SETFIELD(EQ_W0_QSIZE, eq.w0, qsize - 12);
+ break;
+ case 0:
+ eq.w2 = eq.w3 = 0;
+ eq.w0 &= ~EQ_W0_ENQUEUE;
+ break;
+ default:
+ return OPAL_PARAMETER;
+ }
- /* Always notify flag */
- if (qflags & OPAL_XIVE_EQ_ALWAYS_NOTIFY)
- eq.w0 |= EQ_W0_UCOND_NOTIFY;
- else
- eq.w0 &= ~EQ_W0_UCOND_NOTIFY;
+ /* Ensure the priority and target are correctly set (they will
+ * not be right after allocation
+ */
+ eq.w6 = SETFIELD(EQ_W6_NVT_BLOCK, 0ul, vp_blk) |
+ SETFIELD(EQ_W6_NVT_INDEX, 0ul, vp_idx);
+ eq.w7 = SETFIELD(EQ_W7_F0_PRIORITY, 0ul, prio);
+ /* XXX Handle group i bit when needed */
+
+ /* Always notify flag */
+ if (qflags & OPAL_XIVE_EQ_ALWAYS_NOTIFY)
+ eq.w0 |= EQ_W0_UCOND_NOTIFY;
+ else
+ eq.w0 &= ~EQ_W0_UCOND_NOTIFY;
- /* Escalation flag */
- if (qflags & OPAL_XIVE_EQ_ESCALATE)
- eq.w0 |= EQ_W0_ESCALATE_CTL;
- else
- eq.w0 &= ~EQ_W0_ESCALATE_CTL;
+ /* Escalation flag */
+ if (qflags & OPAL_XIVE_EQ_ESCALATE)
+ eq.w0 |= EQ_W0_ESCALATE_CTL;
+ else
+ eq.w0 &= ~EQ_W0_ESCALATE_CTL;
- /* Unconditionally clear the current queue pointer, set
- * generation to 1 and disable escalation interrupts.
- */
- eq.w1 = EQ_W1_GENERATION |
- (old_eq->w1 & (EQ_W1_ESe_P | EQ_W1_ESe_Q |
- EQ_W1_ESn_P | EQ_W1_ESn_Q));
+ /* Unconditionally clear the current queue pointer, set
+ * generation to 1 and disable escalation interrupts.
+ */
+ eq.w1 = EQ_W1_GENERATION |
+ (old_eq->w1 & (EQ_W1_ESe_P | EQ_W1_ESe_Q |
+ EQ_W1_ESn_P | EQ_W1_ESn_Q));
- /* Enable or disable. We always enable backlog for an
- * enabled queue otherwise escalations won't work.
- */
- if (qflags & OPAL_XIVE_EQ_ENABLED)
+ /* Enable. We always enable backlog for an enabled queue
+ * otherwise escalations won't work.
+ */
eq.w0 |= EQ_W0_VALID | EQ_W0_BACKLOG;
- else {
- eq.w0 &= ~EQ_W0_VALID;
- eq.w1 &= ~(EQ_W1_ESe_P | EQ_W1_ESn_P);
- eq.w1 |= EQ_W1_ESe_Q | EQ_W1_ESn_Q;
+ } else {
+ /* Clear everything and set PQ bits to 01 */
+ eq.w0 = old_eq->w0 & EQ_W0_FIRMWARE;
+ eq.w1 = EQ_W1_ESe_Q | EQ_W1_ESn_Q;
+ eq.w2 = eq.w3 = eq.w4 = eq.w5 = eq.w6 = eq.w7 = 0;
}
/* Update EQ, non-synchronous */