[Skiboot] [PATCH 26/32] xive: Add xive_get/set_queue_info
Benjamin Herrenschmidt
benh at kernel.crashing.org
Tue Nov 22 13:13:28 AEDT 2016
This adds the two calls necessary to configure queues
Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
hw/xive.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 140 insertions(+)
diff --git a/hw/xive.c b/hw/xive.c
index 266e259..489b848 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -409,6 +409,7 @@ static uint32_t xive_block_count;
#define GIRQ_TO_IDX(__g) ((__g) & 0x000fffff)
#define BLKIDX_TO_GIRQ(__b,__i) (((uint32_t)(__b)) << 20 | (__i))
#define GIRQ_IS_ESCALATION(__g) ((__g) & 0x01000000)
+#define MAKE_ESCALATION_GIRQ(__g)((__g) | 0x01000000)
/* Block/IRQ to chip# conversions */
#define PC_BLK_TO_CHIP(__b) (xive_block_to_chip[__b])
@@ -2885,6 +2886,143 @@ static int64_t opal_xive_set_irq_config(uint32_t girq,
return OPAL_SUCCESS;
}
+static int64_t opal_xive_get_queue_info(uint64_t vp, uint32_t prio,
+ uint64_t *out_qpage,
+ uint64_t *out_qsize,
+ uint64_t *out_qeoi_page,
+ uint32_t *out_escalate_irq,
+ uint64_t *out_qflags)
+{
+ uint32_t blk, idx;
+ struct xive *x;
+ struct xive_eq *eq;
+
+ if (xive_mode != XIVE_MODE_EXPL)
+ return OPAL_WRONG_STATE;
+
+ if (!xive_eq_for_target(vp, prio, &blk, &idx))
+ return OPAL_PARAMETER;
+
+ x = xive_from_vc_blk(blk);
+ if (!x)
+ return OPAL_PARAMETER;
+
+ eq = xive_get_eq(x, idx);
+ if (!eq)
+ return OPAL_PARAMETER;
+
+ if (out_escalate_irq) {
+ *out_escalate_irq =
+ MAKE_ESCALATION_GIRQ(BLKIDX_TO_GIRQ(blk, idx));
+ }
+ if (out_qpage) {
+ if (eq->w0 & EQ_W0_ENQUEUE)
+ *out_qpage =
+ (((uint64_t)(eq->w2 & 0x0fffffff)) << 32) | eq->w3;
+ else
+ *out_qpage = 0;
+ }
+ if (out_qsize) {
+ if (eq->w0 & EQ_W0_ENQUEUE)
+ *out_qsize = GETFIELD(EQ_W0_QSIZE, eq->w0) + 12;
+ else
+ *out_qsize = 0;
+ }
+ if (out_qeoi_page) {
+ *out_qeoi_page =
+ (uint64_t)x->eq_mmio + idx * 0x20000;
+ }
+ if (out_qflags) {
+ *out_qflags = 0;
+ if (eq->w0 & EQ_W0_VALID)
+ *out_qflags |= OPAL_XIVE_EQ_ENABLED;
+ if (eq->w0 & EQ_W0_UCOND_NOTIFY)
+ *out_qflags |= OPAL_XIVE_EQ_ALWAYS_NOTIFY;
+ if (eq->w0 & EQ_W0_ESCALATE_CTL)
+ *out_qflags |= OPAL_XIVE_EQ_ESCALATE;
+ }
+
+ return OPAL_SUCCESS;
+}
+
+static int64_t opal_xive_set_queue_info(uint64_t vp, uint32_t prio,
+ uint64_t qpage,
+ uint64_t qsize,
+ uint64_t qflags)
+{
+ uint32_t blk, idx;
+ struct xive *x;
+ struct xive_eq *old_eq;
+ struct xive_eq eq;
+ uint32_t vp_blk, vp_idx;
+ bool group;
+ int64_t rc;
+
+ if (!xive_eq_for_target(vp, prio, &blk, &idx))
+ return OPAL_PARAMETER;
+
+ x = xive_from_vc_blk(blk);
+ if (!x)
+ return OPAL_PARAMETER;
+
+ old_eq = xive_get_eq(x, idx);
+ if (!old_eq)
+ return OPAL_PARAMETER;
+
+ /* This shouldn't fail or xive_eq_for_target would have
+ * failed already
+ */
+ if (!xive_decode_vp(vp, &vp_blk, &vp_idx, NULL, &group))
+ return OPAL_PARAMETER;
+
+ /* Make a local copy which we will later try to commit using
+ * the cache watch facility
+ */
+ 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 */
+
+ /* Check enable transitionn */
+ if ((qflags & OPAL_XIVE_EQ_ENABLED) && !(eq.w0 & EQ_W0_VALID)) {
+ /* Clear PQ bits, set G, clear offset */
+ eq.w1 = EQ_W1_GENERATION;
+ eq.w0 |= EQ_W0_VALID;
+ } else if (!(qflags & OPAL_XIVE_EQ_ENABLED))
+ eq.w0 &= ~EQ_W0_VALID;
+
+ /* Update EQ, non-synchronous */
+ lock(&x->lock);
+ rc = xive_eqc_cache_update(x, blk, idx, 0, 4, &eq, false, false);
+ unlock(&x->lock);
+
+ return rc;
+}
+
static int64_t opal_xive_donate_page(uint32_t chip_id, uint64_t addr)
{
struct proc_chip *c = get_chip(chip_id);
@@ -2960,6 +3098,8 @@ void init_xive(void)
opal_register(OPAL_XIVE_GET_IRQ_INFO, opal_xive_get_irq_info, 6);
opal_register(OPAL_XIVE_GET_IRQ_CONFIG, opal_xive_get_irq_config, 4);
opal_register(OPAL_XIVE_SET_IRQ_CONFIG, opal_xive_set_irq_config, 4);
+ opal_register(OPAL_XIVE_GET_QUEUE_INFO, opal_xive_get_queue_info, 7);
+ opal_register(OPAL_XIVE_SET_QUEUE_INFO, opal_xive_set_queue_info, 5);
opal_register(OPAL_XIVE_DONATE_PAGE, opal_xive_donate_page, 2);
}
--
2.7.4
More information about the Skiboot
mailing list