[Skiboot] [PATCH RFC v2 10/12] opal-prd: Add firmware_request & firmware_notify implementations

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Fri May 26 21:21:51 AEST 2017


On 05/26/2017 08:24 AM, Jeremy Kerr wrote:
> This change adds the implementation of firmware_request() and
> firmware_notify(). To do this, we need to add a message queue, so that
> we can properly handle out-of-order messages coming from firmware.
>
> Signed-off-by: Jeremy Kerr <jk at ozlabs.org>
> ---

.../...

>
> +uint64_t hservice_firmware_request(uint64_t req_len, void *req,
> +		uint64_t *resp_lenp, void *resp)
> +{
> +	struct opal_prd_msg *msg = ctx->msg;
> +	uint64_t resp_len;
> +	size_t size;
> +	int rc, n;
> +
> +	resp_len = be64_to_cpu(*resp_lenp);
> +
> +	pr_log(LOG_DEBUG,
> +			"HBRT: firmware request: %lu bytes req, %lu bytes resp",
> +			req_len, resp_len);
> +
> +	/* sanity check for potential overflows */
> +	if (req_len > 0xffff || resp_len > 0xffff)

Sorry. I missed to comment on this one earlier.
I think we should log error message here so that it becomes easy to debug.

> +		return -1;
> +
> +	size = sizeof(msg->hdr) + sizeof(msg->token) +
> +		sizeof(msg->fw_req) + req_len;
> +
> +	/* we need the entire message to fit within the 2-byte size field */
> +	if (size > 0xffff)

ditto.

> +		return -1;
> +


.../...

> +
> +	/* We have an "inner" poll loop here, as we want to ensure that the
> +	 * next entry into HBRT is the return from this function. So, only
> +	 * read from the prd fd, and queue anything that isn't a response
> +	 * to this request
> +	 */

This logic works fine for most cases. In worst case we may endup waiting for 
max_msgq_len messages before returning error. How about having timer here ? Say:
   run timer for 1 minute, if we don't get response then error out?


-Vasant

> +	n = 0;
> +	for (;;) {
> +		struct prd_msgq_item *item;
> +
> +		rc = read_prd_msg(ctx);
> +		if (rc)
> +			return -1;
> +
> +		msg = ctx->msg;
> +		if (msg->hdr.type == OPAL_PRD_MSG_TYPE_FIRMWARE_RESPONSE) {
> +			size = be64toh(msg->fw_resp.len);
> +			if (size > resp_len)
> +				return -1;
> +
> +			/* success! a valid response that fits into HBRT's
> +			 * resp buffer */
> +			memcpy(resp, msg->fw_resp.data, size);
> +			*resp_lenp = htobe64(size);
> +			return 0;
> +		}
> +
> +		/* not a response? queue up for later consumption */
> +		if (++n > max_msgq_len) {
> +			pr_log(LOG_ERR,
> +				"FW: too many messages queued (%d) while "
> +				"waiting for FIRMWARE_RESPONSE", n);
> +			return -1;
> +		}
> +		size = be16toh(msg->hdr.size);
> +		item = malloc(sizeof(*item) + size);
> +		memcpy(&item->msg, msg, size);
> +		list_add_tail(&ctx->msgq, &item->list);
> +	}
> +}
> +



More information about the Skiboot mailing list