| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From c91f8c8c94c5e8a25d0d46d6cb26c0c48ba04f8f Mon Sep 17 00:00:00 2001 |
| 2 | From: Roy Pledge <roy.pledge@nxp.com> |
| 3 | Date: Wed, 4 Oct 2017 15:36:06 -0400 |
| 4 | Subject: [PATCH] soc: fsl: dpio: Add Support for Order Restoration |
| 5 | |
| 6 | Add DPIO support for HW assisted order restoration |
| 7 | |
| 8 | Signed-off-by: Roy Pledge <roy.pledge@nxp.com> |
| 9 | --- |
| 10 | drivers/soc/fsl/dpio/dpio-service.c | 105 ++++++++++++++++++++++++++++++++++++ |
| 11 | drivers/soc/fsl/dpio/qbman-portal.c | 37 +++++++++++++ |
| 12 | drivers/soc/fsl/dpio/qbman-portal.h | 3 ++ |
| 13 | include/soc/fsl/dpaa2-io.h | 14 ++++- |
| 14 | 4 files changed, 158 insertions(+), 1 deletion(-) |
| 15 | |
| 16 | --- a/drivers/soc/fsl/dpio/dpio-service.c |
| 17 | +++ b/drivers/soc/fsl/dpio/dpio-service.c |
| 18 | @@ -707,3 +707,108 @@ int dpaa2_io_query_bp_count(struct dpaa2 |
| 19 | return 0; |
| 20 | } |
| 21 | EXPORT_SYMBOL_GPL(dpaa2_io_query_bp_count); |
| 22 | + |
| 23 | +/** |
| 24 | + * dpaa2_io_service_enqueue_orp_fq() - Enqueue a frame to a frame queue with |
| 25 | + * order restoration |
| 26 | + * @d: the given DPIO service. |
| 27 | + * @fqid: the given frame queue id. |
| 28 | + * @fd: the frame descriptor which is enqueued. |
| 29 | + * @orpid: the order restoration point ID |
| 30 | + * @seqnum: the order sequence number |
| 31 | + * @last: must be set for the final frame if seqnum is shared (spilt frame) |
| 32 | + * |
| 33 | + * Performs an enqueue to a frame queue using the specified order restoration |
| 34 | + * point. The QMan device will ensure the order of frames placed on the |
| 35 | + * queue will be ordered as per the sequence number. |
| 36 | + * |
| 37 | + * In the case a frame is split it is possible to enqueue using the same |
| 38 | + * sequence number more than once. The final frame in a shared sequence number |
| 39 | + * most be indicated by setting last = 1. For non shared sequence numbers |
| 40 | + * last = 1 must always be set. |
| 41 | + * |
| 42 | + * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready, |
| 43 | + * or -ENODEV if there is no dpio service. |
| 44 | + */ |
| 45 | +int dpaa2_io_service_enqueue_orp_fq(struct dpaa2_io *d, u32 fqid, |
| 46 | + const struct dpaa2_fd *fd, u16 orpid, |
| 47 | + u16 seqnum, int last) |
| 48 | +{ |
| 49 | + struct qbman_eq_desc ed; |
| 50 | + |
| 51 | + d = service_select(d); |
| 52 | + if (!d) |
| 53 | + return -ENODEV; |
| 54 | + qbman_eq_desc_clear(&ed); |
| 55 | + qbman_eq_desc_set_orp(&ed, 0, orpid, seqnum, !last); |
| 56 | + qbman_eq_desc_set_fq(&ed, fqid); |
| 57 | + return qbman_swp_enqueue(d->swp, &ed, fd); |
| 58 | +} |
| 59 | +EXPORT_SYMBOL(dpaa2_io_service_enqueue_orp_fq); |
| 60 | + |
| 61 | +/** |
| 62 | + * dpaa2_io_service_enqueue_orp_qd() - Enqueue a frame to a queueing destination |
| 63 | + * with order restoration |
| 64 | + * @d: the given DPIO service. |
| 65 | + * @qdid: the given queuing destination id. |
| 66 | + * @fd: the frame descriptor which is enqueued. |
| 67 | + * @orpid: the order restoration point ID |
| 68 | + * @seqnum: the order sequence number |
| 69 | + * @last: must be set for the final frame if seqnum is shared (spilt frame) |
| 70 | + * |
| 71 | + * Performs an enqueue to a frame queue using the specified order restoration |
| 72 | + * point. The QMan device will ensure the order of frames placed on the |
| 73 | + * queue will be ordered as per the sequence number. |
| 74 | + * |
| 75 | + * In the case a frame is split it is possible to enqueue using the same |
| 76 | + * sequence number more than once. The final frame in a shared sequence number |
| 77 | + * most be indicated by setting last = 1. For non shared sequence numbers |
| 78 | + * last = 1 must always be set. |
| 79 | + * |
| 80 | + * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready, |
| 81 | + * or -ENODEV if there is no dpio service. |
| 82 | + */ |
| 83 | +int dpaa2_io_service_enqueue_orp_qd(struct dpaa2_io *d, u32 qdid, u8 prio, |
| 84 | + u16 qdbin, const struct dpaa2_fd *fd, |
| 85 | + u16 orpid, u16 seqnum, int last) |
| 86 | +{ |
| 87 | + struct qbman_eq_desc ed; |
| 88 | + |
| 89 | + d = service_select(d); |
| 90 | + if (!d) |
| 91 | + return -ENODEV; |
| 92 | + qbman_eq_desc_clear(&ed); |
| 93 | + qbman_eq_desc_set_orp(&ed, 0, orpid, seqnum, !last); |
| 94 | + qbman_eq_desc_set_qd(&ed, qdid, qdbin, prio); |
| 95 | + return qbman_swp_enqueue(d->swp, &ed, fd); |
| 96 | +} |
| 97 | +EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_orp_qd); |
| 98 | + |
| 99 | +/** |
| 100 | + * dpaa2_io_service_orp_seqnum_drop() - Remove a sequence number from |
| 101 | + * an order restoration list |
| 102 | + * @d: the given DPIO service. |
| 103 | + * @orpid: Order restoration point to remove a sequence number from |
| 104 | + * @seqnum: Sequence number to remove |
| 105 | + * |
| 106 | + * Removes a frames sequence number from an order restoration point without |
| 107 | + * enqueing the frame. Used to indicate that the order restoration hardware |
| 108 | + * should not expect to see this sequence number. Typically used to indicate |
| 109 | + * a frame was terminated or dropped from a flow. |
| 110 | + * |
| 111 | + * Return 0 for successful enqueue, or -EBUSY if the enqueue ring is not ready, |
| 112 | + * or -ENODEV if there is no dpio service. |
| 113 | + */ |
| 114 | +int dpaa2_io_service_orp_seqnum_drop(struct dpaa2_io *d, u16 orpid, u16 seqnum) |
| 115 | +{ |
| 116 | + struct qbman_eq_desc ed; |
| 117 | + struct dpaa2_fd fd; |
| 118 | + |
| 119 | + d = service_select(d); |
| 120 | + if (!d) |
| 121 | + return -ENODEV; |
| 122 | + qbman_eq_desc_clear(&ed); |
| 123 | + qbman_eq_desc_set_orp_hole(&ed, orpid, seqnum); |
| 124 | + return qbman_swp_enqueue(d->swp, &ed, &fd); |
| 125 | +} |
| 126 | +EXPORT_SYMBOL_GPL(dpaa2_io_service_orp_seqnum_drop); |
| 127 | --- a/drivers/soc/fsl/dpio/qbman-portal.c |
| 128 | +++ b/drivers/soc/fsl/dpio/qbman-portal.c |
| 129 | @@ -413,6 +413,43 @@ void qbman_eq_desc_set_no_orp(struct qbm |
| 130 | d->verb |= enqueue_rejects_to_fq; |
| 131 | } |
| 132 | |
| 133 | +/** |
| 134 | + * qbman_eq_desc_set_orp() - Set order-restoration in the enqueue descriptor |
| 135 | + * @d: the enqueue descriptor. |
| 136 | + * @response_success: 1 = enqueue with response always; 0 = enqueue with |
| 137 | + * rejections returned on a FQ. |
| 138 | + * @oprid: the order point record id. |
| 139 | + * @seqnum: the order restoration sequence number. |
| 140 | + * @incomplete: indicates whether this is the last fragments using the same |
| 141 | + * sequence number. |
| 142 | + */ |
| 143 | +void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success, |
| 144 | + u16 oprid, u16 seqnum, int incomplete) |
| 145 | +{ |
| 146 | + d->verb |= (1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT); |
| 147 | + if (respond_success) |
| 148 | + d->verb |= enqueue_response_always; |
| 149 | + else |
| 150 | + d->verb |= enqueue_rejects_to_fq; |
| 151 | + d->orpid = cpu_to_le16(oprid); |
| 152 | + d->seqnum = cpu_to_le16((!!incomplete << 14) | seqnum); |
| 153 | +} |
| 154 | + |
| 155 | +/** |
| 156 | + * qbman_eq_desc_set_orp_hole() - fill a hole in the order-restoration sequence |
| 157 | + * without any enqueue |
| 158 | + * @d: the enqueue descriptor. |
| 159 | + * @oprid: the order point record id. |
| 160 | + * @seqnum: the order restoration sequence number. |
| 161 | + */ |
| 162 | +void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, u16 oprid, |
| 163 | + u16 seqnum) |
| 164 | +{ |
| 165 | + d->verb |= (1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT) | enqueue_empty; |
| 166 | + d->orpid = cpu_to_le16(oprid); |
| 167 | + d->seqnum = cpu_to_le16(seqnum); |
| 168 | +} |
| 169 | + |
| 170 | /* |
| 171 | * Exactly one of the following descriptor "targets" should be set. (Calling any |
| 172 | * one of these will replace the effect of any prior call to one of these.) |
| 173 | --- a/drivers/soc/fsl/dpio/qbman-portal.h |
| 174 | +++ b/drivers/soc/fsl/dpio/qbman-portal.h |
| 175 | @@ -167,6 +167,9 @@ int qbman_result_has_new_result(struct q |
| 176 | |
| 177 | void qbman_eq_desc_clear(struct qbman_eq_desc *d); |
| 178 | void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success); |
| 179 | +void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success, |
| 180 | + u16 oprid, u16 seqnum, int incomplete); |
| 181 | +void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, u16 oprid, u16 seqnum); |
| 182 | void qbman_eq_desc_set_token(struct qbman_eq_desc *d, u8 token); |
| 183 | void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid); |
| 184 | void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid, |
| 185 | --- a/include/soc/fsl/dpaa2-io.h |
| 186 | +++ b/include/soc/fsl/dpaa2-io.h |
| 187 | @@ -1,7 +1,7 @@ |
| 188 | /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ |
| 189 | /* |
| 190 | * Copyright 2014-2016 Freescale Semiconductor Inc. |
| 191 | - * Copyright NXP |
| 192 | + * Copyright 2017 NXP |
| 193 | * |
| 194 | */ |
| 195 | #ifndef __FSL_DPAA2_IO_H |
| 196 | @@ -121,6 +121,18 @@ struct dpaa2_io_store *dpaa2_io_store_cr |
| 197 | void dpaa2_io_store_destroy(struct dpaa2_io_store *s); |
| 198 | struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last); |
| 199 | |
| 200 | +/* Order Restoration Support */ |
| 201 | +int dpaa2_io_service_enqueue_orp_fq(struct dpaa2_io *d, u32 fqid, |
| 202 | + const struct dpaa2_fd *fd, u16 orpid, |
| 203 | + u16 seqnum, int last); |
| 204 | + |
| 205 | +int dpaa2_io_service_enqueue_orp_qd(struct dpaa2_io *d, u32 qdid, u8 prio, |
| 206 | + u16 qdbin, const struct dpaa2_fd *fd, |
| 207 | + u16 orpid, u16 seqnum, int last); |
| 208 | + |
| 209 | +int dpaa2_io_service_orp_seqnum_drop(struct dpaa2_io *d, u16 orpid, |
| 210 | + u16 seqnum); |
| 211 | + |
| 212 | int dpaa2_io_query_fq_count(struct dpaa2_io *d, u32 fqid, |
| 213 | u32 *fcnt, u32 *bcnt); |
| 214 | int dpaa2_io_query_bp_count(struct dpaa2_io *d, u16 bpid, |