| 227 | } |
| 228 | |
| 229 | static int |
| 230 | ionic_adminq_wait_for_completion(struct ionic_lif *lif, |
| 231 | struct ionic_admin_ctx *ctx, unsigned long max_wait) |
| 232 | { |
| 233 | struct ionic_queue *q = &lif->adminqcq->qcq.q; |
| 234 | unsigned long step_usec = IONIC_DEVCMD_CHECK_PERIOD_US; |
| 235 | unsigned long step_deadline; |
| 236 | unsigned long max_wait_usec = max_wait * 1000000L; |
| 237 | unsigned long elapsed_usec = 0; |
| 238 | int budget = 8; |
| 239 | uint16_t idx; |
| 240 | void **info; |
| 241 | |
| 242 | step_deadline = IONIC_ADMINQ_WDOG_MS * 1000 / step_usec; |
| 243 | |
| 244 | while (ctx->pending_work && elapsed_usec < max_wait_usec) { |
| 245 | /* |
| 246 | * Locking here as adminq is served inline and could be |
| 247 | * called from multiple places |
| 248 | */ |
| 249 | rte_spinlock_lock(&lif->adminq_service_lock); |
| 250 | |
| 251 | ionic_qcq_service(&lif->adminqcq->qcq, budget, |
| 252 | ionic_adminq_service, NULL); |
| 253 | |
| 254 | /* |
| 255 | * Ring the doorbell again if work is pending after deadline. |
| 256 | */ |
| 257 | if (ctx->pending_work && !step_deadline) { |
| 258 | step_deadline = IONIC_ADMINQ_WDOG_MS * |
| 259 | 1000 / step_usec; |
| 260 | |
| 261 | rte_spinlock_lock(&lif->adminq_lock); |
| 262 | idx = Q_NEXT_TO_POST(q, -1); |
| 263 | info = IONIC_INFO_PTR(q, idx); |
| 264 | if (info[0] == ctx) |
| 265 | ionic_q_flush(q); |
| 266 | rte_spinlock_unlock(&lif->adminq_lock); |
| 267 | } |
| 268 | |
| 269 | rte_spinlock_unlock(&lif->adminq_service_lock); |
| 270 | |
| 271 | rte_delay_us_block(step_usec); |
| 272 | elapsed_usec += step_usec; |
| 273 | step_deadline--; |
| 274 | } |
| 275 | |
| 276 | return (!ctx->pending_work); |
| 277 | } |
| 278 | |
| 279 | int |
| 280 | ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) |
no test coverage detected