Lines Matching +full:max +full:- +full:rx +full:- +full:timeout +full:- +full:ms
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
152 (&((_sc)->trs->inflight_ht[(_tk) & (_sc)->trs->inflight_mask]))
199 sc->dev = dev; in scmi_attach()
202 if (node == -1) in scmi_attach()
211 device_printf(dev, "Transport - max_msg:%d max_payld_sz:%lu reply_timo_ms:%d\n", in scmi_attach()
214 sc->sysctl_root = SYSCTL_ADD_NODE(NULL, SYSCTL_STATIC_CHILDREN(_hw), in scmi_attach()
216 sysctl_trans = SYSCTL_ADD_NODE(NULL, SYSCTL_CHILDREN(sc->sysctl_root), in scmi_attach()
219 CTLFLAG_RD, &sc->trs_desc.max_msg, 0, "SCMI Max number of inflight messages"); in scmi_attach()
221 CTLFLAG_RD, &sc->trs_desc.max_payld_sz, 0, "SCMI Max message payload size"); in scmi_attach()
223 CTLFLAG_RD, &sc->trs_desc.reply_timo_ms, 0, "SCMI Max message RX timeout ms"); in scmi_attach()
231 * Now walk the OFW tree and attach top-level devices. in scmi_attach()
234 simplebus_add_device(dev, node, 0, NULL, -1, NULL); in scmi_attach()
273 LIST_INIT(&rp->head); in scmi_reqs_pool_allocate()
278 req->dev = dev; in scmi_reqs_pool_allocate()
279 req->tsk.ta_context = &req->tsk; in scmi_reqs_pool_allocate()
280 req->tsk.ta_func = scmi_req_async_waiter; in scmi_reqs_pool_allocate()
282 mtx_init(&req->mtx, "req", "SCMI", MTX_SPIN); in scmi_reqs_pool_allocate()
283 LIST_INSERT_HEAD(&rp->head, req, next); in scmi_reqs_pool_allocate()
286 mtx_init(&rp->mtx, "reqs_pool", "SCMI", MTX_SPIN); in scmi_reqs_pool_allocate()
296 LIST_FOREACH_SAFE(req, &rp->head, next, tmp) { in scmi_reqs_pool_free()
297 mtx_destroy(&req->mtx); in scmi_reqs_pool_free()
301 mtx_destroy(&rp->mtx); in scmi_reqs_pool_free()
308 if (OF_getencprop(node, "arm,max-msg", &td->max_msg, sizeof(td->max_msg)) == -1) in scmi_transport_configure()
309 td->max_msg = SCMI_DEF_MAX_MSG; in scmi_transport_configure()
311 if (OF_getencprop(node, "arm,max-msg-size", &td->max_payld_sz, in scmi_transport_configure()
312 sizeof(td->max_payld_sz)) == -1) in scmi_transport_configure()
313 td->max_payld_sz = SCMI_DEF_MAX_MSG_PAYLD_SIZE; in scmi_transport_configure()
319 struct scmi_transport_desc *td = &sc->trs_desc; in scmi_transport_init()
327 BIT_FILL(SCMI_MAX_TOKEN, &trs->avail_tokens); in scmi_transport_init()
328 mtx_init(&trs->mtx, "tokens", "SCMI", MTX_SPIN); in scmi_transport_init()
330 trs->inflight_ht = hashinit(td->max_msg, M_DEVBUF, &trs->inflight_mask); in scmi_transport_init()
332 trs->chans[SCMI_CHAN_A2P] = in scmi_transport_init()
333 scmi_reqs_pool_allocate(sc->dev, td->max_msg, td->max_payld_sz); in scmi_transport_init()
334 if (trs->chans[SCMI_CHAN_A2P] == NULL) { in scmi_transport_init()
339 trs->chans[SCMI_CHAN_P2A] = in scmi_transport_init()
340 scmi_reqs_pool_allocate(sc->dev, td->max_msg, td->max_payld_sz); in scmi_transport_init()
341 if (trs->chans[SCMI_CHAN_P2A] == NULL) { in scmi_transport_init()
342 scmi_reqs_pool_free(trs->chans[SCMI_CHAN_A2P]); in scmi_transport_init()
347 sc->trs = trs; in scmi_transport_init()
348 ret = SCMI_TRANSPORT_INIT(sc->dev); in scmi_transport_init()
350 scmi_reqs_pool_free(trs->chans[SCMI_CHAN_A2P]); in scmi_transport_init()
351 scmi_reqs_pool_free(trs->chans[SCMI_CHAN_P2A]); in scmi_transport_init()
356 /* Use default transport timeout if not overridden by OF */ in scmi_transport_init()
357 OF_getencprop(node, "arm,max-rx-timeout-ms", &td->reply_timo_ms, in scmi_transport_init()
358 sizeof(td->reply_timo_ms)); in scmi_transport_init()
367 SCMI_TRANSPORT_CLEANUP(sc->dev); in scmi_transport_cleanup()
368 mtx_destroy(&sc->trs->mtx); in scmi_transport_cleanup()
369 hashdestroy(sc->trs->inflight_ht, M_DEVBUF, sc->trs->inflight_mask); in scmi_transport_cleanup()
370 scmi_reqs_pool_free(sc->trs->chans[SCMI_CHAN_A2P]); in scmi_transport_cleanup()
371 scmi_reqs_pool_free(sc->trs->chans[SCMI_CHAN_P2A]); in scmi_transport_cleanup()
372 free(sc->trs, M_DEVBUF); in scmi_transport_cleanup()
394 req->msg.tx_len = sizeof(req->msg.hdr) + tx_payld_sz; in scmi_req_initialized_alloc()
395 req->msg.rx_len = rx_payld_sz ? in scmi_req_initialized_alloc()
407 rp = sc->trs->chans[ch_idx]; in scmi_req_alloc()
408 mtx_lock_spin(&rp->mtx); in scmi_req_alloc()
409 if (!LIST_EMPTY(&rp->head)) { in scmi_req_alloc()
410 req = LIST_FIRST(&rp->head); in scmi_req_alloc()
411 LIST_REMOVE_HEAD(&rp->head, next); in scmi_req_alloc()
413 mtx_unlock_spin(&rp->mtx); in scmi_req_alloc()
416 refcount_init(&req->cnt, 1); in scmi_req_alloc()
418 req, refcount_load(&req->cnt), -1); in scmi_req_alloc()
430 rp = sc->trs->chans[ch_idx]; in scmi_req_free_unlocked()
431 mtx_lock_spin(&rp->mtx); in scmi_req_free_unlocked()
432 req->timed_out = false; in scmi_req_free_unlocked()
433 req->done = false; in scmi_req_free_unlocked()
434 req->is_raw = false; in scmi_req_free_unlocked()
435 refcount_init(&req->cnt, 0); in scmi_req_free_unlocked()
436 LIST_INSERT_HEAD(&rp->head, req, next); in scmi_req_free_unlocked()
437 mtx_unlock_spin(&rp->mtx); in scmi_req_free_unlocked()
440 req, refcount_load(&req->cnt), -1); in scmi_req_free_unlocked()
448 mtx_lock_spin(&req->mtx); in scmi_req_get()
449 ok = refcount_acquire_if_not_zero(&req->cnt); in scmi_req_get()
450 mtx_unlock_spin(&req->mtx); in scmi_req_get()
453 device_printf(sc->dev, "%s() -- BAD REFCOUNT\n", __func__); in scmi_req_get()
456 req, refcount_load(&req->cnt), SCMI_MSG_TOKEN(req->msg.hdr)); in scmi_req_get()
464 mtx_lock_spin(&req->mtx); in scmi_req_put()
465 if (!refcount_release_if_not_last(&req->cnt)) { in scmi_req_put()
466 req->protocol_id = 0; in scmi_req_put()
467 req->message_id = 0; in scmi_req_put()
468 req->token = 0; in scmi_req_put()
469 req->header = 0; in scmi_req_put()
470 bzero(&req->msg, sizeof(req->msg) + SCMI_MAX_MSG_PAYLD_SIZE(sc)); in scmi_req_put()
474 req, refcount_load(&req->cnt), SCMI_MSG_TOKEN(req->msg.hdr)); in scmi_req_put()
476 mtx_unlock_spin(&req->mtx); in scmi_req_put()
484 mtx_lock_spin(&sc->trs->mtx); in scmi_token_pick()
487 * for tracing purposes; next_msg_id is a 10-bit sequence number derived in scmi_token_pick()
490 next_msg_id = sc->trs->next_id++ & SCMI_HDR_TOKEN_BF; in scmi_token_pick()
491 token = BIT_FFS_AT(SCMI_MAX_TOKEN, &sc->trs->avail_tokens, next_msg_id); in scmi_token_pick()
493 BIT_CLR(SCMI_MAX_TOKEN, token - 1, &sc->trs->avail_tokens); in scmi_token_pick()
494 mtx_unlock_spin(&sc->trs->mtx); in scmi_token_pick()
497 * BIT_FFS_AT returns 1-indexed values, so 0 means failure to find a in scmi_token_pick()
498 * free slot: all possible SCMI messages are in-flight using all of the in scmi_token_pick()
502 return (-EBUSY); in scmi_token_pick()
504 return ((int)(token - 1)); in scmi_token_pick()
510 int token = -EBUSY, retries = 3; in scmi_token_reserve()
513 mtx_lock_spin(&sc->trs->mtx); in scmi_token_reserve()
514 if (BIT_ISSET(SCMI_MAX_TOKEN, candidate, &sc->trs->avail_tokens)) { in scmi_token_reserve()
515 BIT_CLR(SCMI_MAX_TOKEN, candidate, &sc->trs->avail_tokens); in scmi_token_reserve()
517 sc->trs->next_id++; in scmi_token_reserve()
519 mtx_unlock_spin(&sc->trs->mtx); in scmi_token_reserve()
520 if (token == candidate || retries-- == 0) in scmi_token_reserve()
533 BIT_SET(SCMI_MAX_TOKEN, token, &sc->trs->avail_tokens); in scmi_token_release_unlocked()
539 if (!req->is_raw) in scmi_finalize_req()
540 req->token = scmi_token_pick(sc); in scmi_finalize_req()
542 req->token = scmi_token_reserve(sc, SCMI_MSG_TOKEN(req->msg.hdr)); in scmi_finalize_req()
544 if (req->token < 0) in scmi_finalize_req()
547 if (!req->is_raw) { in scmi_finalize_req()
548 req->msg.hdr = req->message_id; in scmi_finalize_req()
549 req->msg.hdr |= SCMI_MSG_TYPE_CMD << SCMI_HDR_MESSAGE_TYPE_S; in scmi_finalize_req()
550 req->msg.hdr |= req->protocol_id << SCMI_HDR_PROTOCOL_ID_S; in scmi_finalize_req()
551 req->msg.hdr |= req->token << SCMI_HDR_TOKEN_S; in scmi_finalize_req()
555 req->header = req->msg.hdr; in scmi_finalize_req()
570 /* Bump refcount to get hold of this in-flight transaction */ in scmi_req_track_inflight()
573 mtx_lock_spin(&sc->trs->mtx); in scmi_req_track_inflight()
574 LIST_INSERT_HEAD(REQHASH(sc, req->token), req, next); in scmi_req_track_inflight()
575 mtx_unlock_spin(&sc->trs->mtx); in scmi_req_track_inflight()
585 mtx_lock_spin(&sc->trs->mtx); in scmi_req_drop_inflight()
587 scmi_token_release_unlocked(sc, req->token); in scmi_req_drop_inflight()
588 mtx_unlock_spin(&sc->trs->mtx); in scmi_req_drop_inflight()
602 mtx_lock_spin(&sc->trs->mtx); in scmi_req_lookup_inflight()
604 if (req->token == token) in scmi_req_lookup_inflight()
607 mtx_unlock_spin(&sc->trs->mtx); in scmi_req_lookup_inflight()
620 device_printf(sc->dev, in scmi_process_response()
621 "Unexpected reply with header |%X| - token: 0x%X Drop.\n", in scmi_process_response()
627 SCMI_MSG_PROTOCOL_ID(req->msg.hdr), SCMI_MSG_MESSAGE_ID(req->msg.hdr), in scmi_process_response()
628 SCMI_MSG_TOKEN(req->msg.hdr), req->timed_out); in scmi_process_response()
630 mtx_lock_spin(&req->mtx); in scmi_process_response()
631 req->done = true; in scmi_process_response()
632 req->msg.rx_len = rx_len; in scmi_process_response()
633 if (!req->timed_out) { in scmi_process_response()
639 if (!req->msg.polling) in scmi_process_response()
642 atomic_store_rel_int(&req->msg.poll_done, 1); in scmi_process_response()
646 mtx_unlock_spin(&req->mtx); in scmi_process_response()
649 device_printf(sc->dev, in scmi_process_response()
650 "Late reply for timed-out request - token: 0x%X. Ignore.\n", in scmi_process_response()
651 req->token); in scmi_process_response()
654 * In case of a late reply to a timed-out transaction this will in scmi_process_response()
685 SCMI_MSG_PROTOCOL_ID(req->msg.hdr), SCMI_MSG_MESSAGE_ID(req->msg.hdr), in scmi_wait_for_response()
686 SCMI_MSG_TOKEN(req->msg.hdr), reply_timo_ms); in scmi_wait_for_response()
688 if (req->msg.polling) { in scmi_wait_for_response()
691 ret = SCMI_POLL_MSG(sc->dev, &req->msg, reply_timo_ms); in scmi_wait_for_response()
695 * Addresses a possible race-condition between polling and in scmi_wait_for_response()
698 mtx_lock_spin(&req->mtx); in scmi_wait_for_response()
699 needs_drop = (ret == 0) && !req->done; in scmi_wait_for_response()
700 req->timed_out = ret != 0; in scmi_wait_for_response()
701 mtx_unlock_spin(&req->mtx); in scmi_wait_for_response()
704 if (ret == 0 && req->msg.hdr != req->header) { in scmi_wait_for_response()
705 device_printf(sc->dev, in scmi_wait_for_response()
707 le32toh(req->msg.hdr), le32toh(req->header)); in scmi_wait_for_response()
712 mtx_lock_spin(&req->mtx); in scmi_wait_for_response()
713 if (ret != 0 && req->done) in scmi_wait_for_response()
715 req->timed_out = ret != 0; in scmi_wait_for_response()
716 mtx_unlock_spin(&req->mtx); in scmi_wait_for_response()
720 SCMI_COLLECT_REPLY(sc->dev, &req->msg); in scmi_wait_for_response()
721 if (req->msg.payld[0] != 0) in scmi_wait_for_response()
722 ret = req->msg.payld[0]; in scmi_wait_for_response()
724 *out = &req->msg.payld[SCMI_MSG_HDR_SIZE]; in scmi_wait_for_response()
726 device_printf(sc->dev, in scmi_wait_for_response()
727 "Request for token 0x%X timed-out.\n", req->token); in scmi_wait_for_response()
730 SCMI_TX_COMPLETE(sc->dev, NULL); in scmi_wait_for_response()
733 SCMI_MSG_PROTOCOL_ID(req->msg.hdr), SCMI_MSG_MESSAGE_ID(req->msg.hdr), in scmi_wait_for_response()
734 SCMI_MSG_TOKEN(req->msg.hdr), req->timed_out); in scmi_wait_for_response()
745 /* Pick a pre-built req */ in scmi_buf_get()
750 req->protocol_id = protocol_id & SCMI_HDR_PROTOCOL_ID_BF; in scmi_buf_get()
751 req->message_id = message_id & SCMI_HDR_MESSAGE_ID_BF; in scmi_buf_get()
753 return (&req->msg.payld[0]); in scmi_buf_get()
773 /* Pick a pre-built req */ in scmi_msg_get()
778 req->is_raw = true; in scmi_msg_get()
780 return (&req->msg); in scmi_msg_get()
791 sc = device_get_softc(req->dev); in scmi_req_async_waiter()
794 scmi_msg_put(req->dev, &req->msg); in scmi_req_async_waiter()
821 req->msg.polling = in scmi_request_tx()
822 (cold || sc->trs_desc.no_completion_irq || req->use_polling); in scmi_request_tx()
824 /* Set inflight and send using transport specific method - refc-2 */ in scmi_request_tx()
828 req->msg.hdr); in scmi_request_tx()
832 error = SCMI_XFER_MSG(sc->dev, &req->msg); in scmi_request_tx()
839 SCMI_MSG_PROTOCOL_ID(req->msg.hdr), SCMI_MSG_MESSAGE_ID(req->msg.hdr), in scmi_request_tx()
840 SCMI_MSG_TOKEN(req->msg.hdr), req->msg.polling); in scmi_request_tx()
869 return taskqueue_enqueue_flags(taskqueue_thread, &req->tsk, in scmi_msg_async_enqueue()