All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vadim Fedorenko <vadim.fedorenko@linux.dev>
To: Lee Trager <lee@trager.us>,
	Alexander Duyck <alexanderduyck@fb.com>,
	Jakub Kicinski <kuba@kernel.org>,
	kernel-team@meta.com, "David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Paolo Abeni <pabeni@redhat.com>, Jonathan Corbet <corbet@lwn.net>,
	Mohsin Bashir <mohsin.bashr@gmail.com>,
	Simon Horman <horms@kernel.org>,
	Sanman Pradhan <sanmanpradhan@meta.com>,
	Al Viro <viro@zeniv.linux.org.uk>
Cc: netdev@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH net-next 1/2] eth: fbnic: Add mailbox support for PLDM updates
Date: Mon, 14 Oct 2024 12:05:42 +0100	[thread overview]
Message-ID: <ece8648c-e555-4a7a-9b73-8a8e7afd7b05@linux.dev> (raw)
In-Reply-To: <20241012023646.3124717-2-lee@trager.us>

On 12/10/2024 03:34, Lee Trager wrote:
> This adds driver support to utilize the kernel completion API. This allows
> the driver to block on a response from firmware. Initially
> fbnic_fw_completion only has support for updates, future patches will add
> additional features.
> 
> Signed-off-by: Lee Trager <lee@trager.us>
> ---
>   drivers/net/ethernet/meta/fbnic/fbnic.h    |   1 +
>   drivers/net/ethernet/meta/fbnic/fbnic_fw.c | 263 +++++++++++++++++++++
>   drivers/net/ethernet/meta/fbnic/fbnic_fw.h |  59 +++++
>   3 files changed, 323 insertions(+)
> 
> diff --git a/drivers/net/ethernet/meta/fbnic/fbnic.h b/drivers/net/ethernet/meta/fbnic/fbnic.h
> index ca59261f0155..f58727e6e45a 100644
> --- a/drivers/net/ethernet/meta/fbnic/fbnic.h
> +++ b/drivers/net/ethernet/meta/fbnic/fbnic.h
> @@ -31,6 +31,7 @@ struct fbnic_dev {
> 
>   	struct fbnic_fw_mbx mbx[FBNIC_IPC_MBX_INDICES];
>   	struct fbnic_fw_cap fw_cap;
> +	struct fbnic_fw_completion *cmpl_data;
>   	/* Lock protecting Tx Mailbox queue to prevent possible races */
>   	spinlock_t fw_tx_lock;
> 
> diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c
> index 8f7a2a19ddf8..deebff3b6821 100644
> --- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c
> +++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c
> @@ -207,6 +207,38 @@ static int fbnic_mbx_map_tlv_msg(struct fbnic_dev *fbd,
>   	return err;
>   }
> 
> +static int fbnic_mbx_map_req_w_cmpl(struct fbnic_dev *fbd,
> +				    struct fbnic_tlv_msg *msg,
> +				    struct fbnic_fw_completion *cmpl_data)
> +{
> +	unsigned long flags;
> +	int err;
> +
> +	spin_lock_irqsave(&fbd->fw_tx_lock, flags);
> +
> +	/* If we are already waiting on a completion then abort */
> +	if (cmpl_data && fbd->cmpl_data) {
> +		err = -EBUSY;
> +		goto unlock_mbx;
> +	}
> +
> +	/* Record completion location and submit request */
> +	if (cmpl_data)
> +		fbd->cmpl_data = cmpl_data;
> +
> +	err = fbnic_mbx_map_msg(fbd, FBNIC_IPC_MBX_TX_IDX, msg,
> +				le16_to_cpu(msg->hdr.len) * sizeof(u32), 1);
> +
> +	/* If msg failed then clear completion data for next caller */
> +	if (err && cmpl_data)
> +		fbd->cmpl_data = NULL;
> +
> +unlock_mbx:
> +	spin_unlock_irqrestore(&fbd->fw_tx_lock, flags);
> +
> +	return err;
> +}
> +
>   static void fbnic_mbx_process_tx_msgs(struct fbnic_dev *fbd)
>   {
>   	struct fbnic_fw_mbx *tx_mbx = &fbd->mbx[FBNIC_IPC_MBX_TX_IDX];
> @@ -651,6 +683,225 @@ void fbnic_fw_check_heartbeat(struct fbnic_dev *fbd)
>   		dev_warn(fbd->dev, "Failed to send heartbeat message\n");
>   }
> 
> +/**
> + * fbnic_fw_xmit_fw_start_upgrade - Create and transmit a start update message
> + * @fbd: FBNIC device structure
> + * @cmpl_data: Completion data for upgrade process
> + * @id: Component ID
> + * @len: Length of FW update package data
> + *
> + * Return: zero on success, negative value on failure
> + *
> + * Asks the FW to prepare for starting a firmware upgrade
> + */
> +int fbnic_fw_xmit_fw_start_upgrade(struct fbnic_dev *fbd,
> +				   struct fbnic_fw_completion *cmpl_data,
> +				   unsigned int id, unsigned int len)
> +{
> +	struct fbnic_tlv_msg *msg;
> +	int err;
> +
> +	if (!len)
> +		return -EINVAL;
> +
> +	msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_FW_START_UPGRADE_REQ);
> +	if (!msg)
> +		return -ENOMEM;
> +
> +	err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_START_UPGRADE_SECTION, id);
> +	if (err)
> +		goto free_message;
> +
> +	err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_START_UPGRADE_IMAGE_LENGTH,
> +				     len);
> +	if (err)
> +		goto free_message;
> +
> +	err = fbnic_mbx_map_req_w_cmpl(fbd, msg, cmpl_data);
> +	if (err)
> +		goto free_message;
> +
> +	return 0;
> +
> +free_message:
> +	free_page((unsigned long)msg);
> +	return err;
> +}
> +
> +static const struct fbnic_tlv_index fbnic_fw_start_upgrade_resp_index[] = {
> +	FBNIC_TLV_ATTR_S32(FBNIC_FW_START_UPGRADE_ERROR),
> +	FBNIC_TLV_ATTR_LAST
> +};
> +
> +static int fbnic_fw_parse_fw_start_upgrade_resp(void *opaque,
> +						struct fbnic_tlv_msg **results)
> +{
> +	struct fbnic_dev *fbd = opaque;
> +	struct fbnic_fw_completion *cmpl_data;

Hi Lee!

Looks like you didn't follow reverse Xmas tree for variables here and
in several functions later, all about cmpl_data variable.

> +	int err = 0;
> +
> +	/* Verify we have a completion pointer */
> +	cmpl_data = READ_ONCE(fbd->cmpl_data);
> +	if (!cmpl_data ||
> +	    cmpl_data->msg_type != FBNIC_TLV_MSG_ID_FW_WRITE_CHUNK_REQ)
> +		return -ENOSPC;
> +
> +	/* Check for errors */
> +	get_signed_result(FBNIC_FW_START_UPGRADE_ERROR, err);
> +
> +	cmpl_data->result = err;
> +	complete(&cmpl_data->done);
> +
> +	return 0;
> +}
> +
> +static const struct fbnic_tlv_index fbnic_fw_write_chunk_req_index[] = {
> +	FBNIC_TLV_ATTR_U32(FBNIC_FW_WRITE_CHUNK_OFFSET),
> +	FBNIC_TLV_ATTR_U32(FBNIC_FW_WRITE_CHUNK_LENGTH),
> +	FBNIC_TLV_ATTR_LAST
> +};
> +
> +static int fbnic_fw_parse_fw_write_chunk_req(void *opaque,
> +					     struct fbnic_tlv_msg **results)
> +{
> +	struct fbnic_dev *fbd = opaque;
> +	struct fbnic_fw_completion *cmpl_data;

here again...

> +	u32 length = 0, offset = 0;
> +	struct fbnic_tlv_msg *msg;
> +	int err;
> +
> +	/* Start by attempting to allocate a response to the message */
> +	msg = fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_FW_WRITE_CHUNK_RESP);
> +	if (!msg)
> +		return -ENOMEM;
> +
> +	/* Verify we have a completion pointer */
> +	cmpl_data = READ_ONCE(fbd->cmpl_data);
> +	if (!cmpl_data ||
> +	    cmpl_data->msg_type != FBNIC_TLV_MSG_ID_FW_WRITE_CHUNK_REQ) {
> +		err = -ENOSPC;
> +		goto msg_err;
> +	}
> +
> +	/* Notify FW if the data link has been severed */
> +	if (!cmpl_data->fw_update.data) {
> +		err = -ECANCELED;
> +		goto msg_err;
> +	}
> +
> +	/* Pull length/offset pair and mark it as complete */
> +	get_unsigned_result(FBNIC_FW_WRITE_CHUNK_OFFSET, offset);
> +	get_unsigned_result(FBNIC_FW_WRITE_CHUNK_LENGTH, length);
> +
> +	/* Record offset and length for the response */
> +	if (offset) {
> +		err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_WRITE_CHUNK_OFFSET,
> +					     offset);
> +		if (err)
> +			goto msg_err;
> +	}
> +
> +	err = fbnic_tlv_attr_put_int(msg, FBNIC_FW_WRITE_CHUNK_LENGTH,
> +				     length);
> +	if (err)
> +		goto msg_err;
> +
> +	/* Verify length */
> +	if (!length || length > TLV_MAX_DATA) {
> +		err = -EINVAL;
> +		goto msg_err;
> +	}
> +
> +	/* Verify offset and length are within bounds */
> +	if (offset >= cmpl_data->fw_update.size ||
> +	    offset + length > cmpl_data->fw_update.size) {
> +		err = -EFAULT;
> +		goto msg_err;
> +	}
> +
> +	/* Add outbound data to message */
> +	err = fbnic_tlv_attr_put_value(msg, FBNIC_FW_WRITE_CHUNK_DATA,
> +				       cmpl_data->fw_update.data + offset,
> +				       length);
> +
> +	/* Notify the waiting thread that we processed a message */
> +	if (!err)
> +		cmpl_data->fw_update.last_offset = offset;
> +
> +	cmpl_data->result = err;
> +	complete(&cmpl_data->done);
> +
> +msg_err:
> +	/* Report error to FW if one occurred */
> +	if (err)
> +		fbnic_tlv_attr_put_int(msg, FBNIC_FW_WRITE_CHUNK_ERROR, err);
> +
> +	/* Map and send the response */
> +	err = fbnic_mbx_map_tlv_msg(fbd, msg);
> +	if (err)
> +		free_page((unsigned long)msg);
> +
> +	return err;
> +}
> +
> +static const struct fbnic_tlv_index fbnic_fw_verify_image_resp_index[] = {
> +	FBNIC_TLV_ATTR_S32(FBNIC_FW_VERIFY_IMAGE_ERROR),
> +	FBNIC_TLV_ATTR_LAST
> +};
> +
> +static int fbnic_fw_parse_fw_verify_image_resp(void *opaque,
> +					       struct fbnic_tlv_msg **results)
> +{
> +	struct fbnic_dev *fbd = opaque;
> +	struct fbnic_fw_completion *cmpl_data;

.. and again..

> +	int err = 0;
> +
> +	/* Verify we have a completion pointer */
> +	cmpl_data = READ_ONCE(fbd->cmpl_data);
> +	if (!cmpl_data ||
> +	    cmpl_data->msg_type != FBNIC_TLV_MSG_ID_FW_VERIFY_IMAGE_RESP)
> +		return -ENOSPC;
> +
> +	/* Check for errors */
> +	get_signed_result(FBNIC_FW_VERIFY_IMAGE_ERROR, err);
> +
> +	cmpl_data->result = err;
> +	complete(&cmpl_data->done);
> +
> +	return err;
> +}
> +
> +static const struct fbnic_tlv_index fbnic_fw_finish_upgrade_req_index[] = {
> +	FBNIC_TLV_ATTR_S32(FBNIC_FW_FINISH_UPGRADE_ERROR),
> +	FBNIC_TLV_ATTR_LAST
> +};
> +
> +static int fbnic_fw_parse_fw_finish_upgrade_req(void *opaque,
> +						struct fbnic_tlv_msg **results)
> +{
> +	struct fbnic_dev *fbd = opaque;
> +	struct fbnic_fw_completion *cmpl_data;

...and again...

> +	int err = 0;
> +
> +	/* Verify we have a completion pointer */
> +	cmpl_data = READ_ONCE(fbd->cmpl_data);
> +	if (!cmpl_data ||
> +	    cmpl_data->msg_type != FBNIC_TLV_MSG_ID_FW_WRITE_CHUNK_REQ)
> +		return -ENOSPC;
> +
> +	/* Check for errors */
> +	get_signed_result(FBNIC_FW_FINISH_UPGRADE_ERROR, err);
> +
> +	/* Close out update by clearing data pointer */
> +	cmpl_data->fw_update.last_offset = cmpl_data->fw_update.size;
> +	cmpl_data->fw_update.data = NULL;
> +
> +	cmpl_data->result = err;
> +	complete(&cmpl_data->done);
> +
> +	return 0;
> +}
> +
>   static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {
>   	FBNIC_TLV_PARSER(FW_CAP_RESP, fbnic_fw_cap_resp_index,
>   			 fbnic_fw_parse_cap_resp),
> @@ -658,6 +909,18 @@ static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] = {
>   			 fbnic_fw_parse_ownership_resp),
>   	FBNIC_TLV_PARSER(HEARTBEAT_RESP, fbnic_heartbeat_resp_index,
>   			 fbnic_fw_parse_heartbeat_resp),
> +	FBNIC_TLV_PARSER(FW_START_UPGRADE_RESP,
> +			 fbnic_fw_start_upgrade_resp_index,
> +			 fbnic_fw_parse_fw_start_upgrade_resp),
> +	FBNIC_TLV_PARSER(FW_WRITE_CHUNK_REQ,
> +			 fbnic_fw_write_chunk_req_index,
> +			 fbnic_fw_parse_fw_write_chunk_req),
> +	FBNIC_TLV_PARSER(FW_VERIFY_IMAGE_RESP,
> +			 fbnic_fw_verify_image_resp_index,
> +			 fbnic_fw_parse_fw_verify_image_resp),
> +	FBNIC_TLV_PARSER(FW_FINISH_UPGRADE_REQ,
> +			 fbnic_fw_finish_upgrade_req_index,
> +			 fbnic_fw_parse_fw_finish_upgrade_req),
>   	FBNIC_TLV_MSG_ERROR
>   };
> 
> diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
> index 221faf8c6756..a638d73d2da5 100644
> --- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
> +++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
> @@ -44,6 +44,19 @@ struct fbnic_fw_cap {
>   	u8	link_fec;
>   };
> 
> +struct fbnic_fw_completion {
> +	u32 msg_type;
> +	struct completion done;
> +	int result;
> +	union {
> +		struct {
> +			u32 size;
> +			u32 last_offset;
> +			const u8 *data;
> +		} fw_update;
> +	};
> +};
> +
>   void fbnic_mbx_init(struct fbnic_dev *fbd);
>   void fbnic_mbx_clean(struct fbnic_dev *fbd);
>   void fbnic_mbx_poll(struct fbnic_dev *fbd);
> @@ -52,6 +65,9 @@ void fbnic_mbx_flush_tx(struct fbnic_dev *fbd);
>   int fbnic_fw_xmit_ownership_msg(struct fbnic_dev *fbd, bool take_ownership);
>   int fbnic_fw_init_heartbeat(struct fbnic_dev *fbd, bool poll);
>   void fbnic_fw_check_heartbeat(struct fbnic_dev *fbd);
> +int fbnic_fw_xmit_fw_start_upgrade(struct fbnic_dev *fbd,
> +				   struct fbnic_fw_completion *cmpl_data,
> +				   unsigned int id, unsigned int len);
> 
>   #define fbnic_mk_full_fw_ver_str(_rev_id, _delim, _commit, _str, _str_sz) \
>   do {									\
> @@ -67,6 +83,15 @@ do {									\
>   #define fbnic_mk_fw_ver_str(_rev_id, _str) \
>   	fbnic_mk_full_fw_ver_str(_rev_id, "", "", _str, sizeof(_str))
> 
> +enum {
> +	QSPI_SECTION_CMRT			= 0,
> +	QSPI_SECTION_CONTROL_FW			= 1,
> +	QSPI_SECTION_UCODE			= 2,
> +	QSPI_SECTION_OPTION_ROM			= 3,
> +	QSPI_SECTION_USER			= 4,
> +	QSPI_SECTION_INVALID,
> +};
> +
>   #define FW_HEARTBEAT_PERIOD		(10 * HZ)
> 
>   enum {
> @@ -76,6 +101,14 @@ enum {
>   	FBNIC_TLV_MSG_ID_OWNERSHIP_RESP			= 0x13,
>   	FBNIC_TLV_MSG_ID_HEARTBEAT_REQ			= 0x14,
>   	FBNIC_TLV_MSG_ID_HEARTBEAT_RESP			= 0x15,
> +	FBNIC_TLV_MSG_ID_FW_START_UPGRADE_REQ		= 0x22,
> +	FBNIC_TLV_MSG_ID_FW_START_UPGRADE_RESP		= 0x23,
> +	FBNIC_TLV_MSG_ID_FW_WRITE_CHUNK_REQ		= 0x24,
> +	FBNIC_TLV_MSG_ID_FW_WRITE_CHUNK_RESP		= 0x25,
> +	FBNIC_TLV_MSG_ID_FW_VERIFY_IMAGE_REQ		= 0x26,
> +	FBNIC_TLV_MSG_ID_FW_VERIFY_IMAGE_RESP		= 0x27,
> +	FBNIC_TLV_MSG_ID_FW_FINISH_UPGRADE_REQ		= 0x28,
> +	FBNIC_TLV_MSG_ID_FW_FINISH_UPGRADE_RESP		= 0x29,
>   };
> 
>   #define FBNIC_FW_CAP_RESP_VERSION_MAJOR		CSR_GENMASK(31, 24)
> @@ -121,4 +154,30 @@ enum {
>   	FBNIC_FW_OWNERSHIP_FLAG			= 0x0,
>   	FBNIC_FW_OWNERSHIP_MSG_MAX
>   };
> +
> +enum {
> +	FBNIC_FW_START_UPGRADE_ERROR		= 0x0,
> +	FBNIC_FW_START_UPGRADE_SECTION		= 0x1,
> +	FBNIC_FW_START_UPGRADE_IMAGE_LENGTH	= 0x2,
> +	FBNIC_FW_START_UPGRADE_MSG_MAX
> +};
> +
> +enum {
> +	FBNIC_FW_WRITE_CHUNK_OFFSET		= 0x0,
> +	FBNIC_FW_WRITE_CHUNK_LENGTH		= 0x1,
> +	FBNIC_FW_WRITE_CHUNK_DATA		= 0x2,
> +	FBNIC_FW_WRITE_CHUNK_ERROR		= 0x3,
> +	FBNIC_FW_WRITE_CHUNK_MSG_MAX
> +};
> +
> +enum {
> +	FBNIC_FW_VERIFY_IMAGE_ERROR		= 0x0,
> +	FBNIC_FW_VERIFY_IMAGE_MSG_MAX
> +};
> +
> +enum {
> +	FBNIC_FW_FINISH_UPGRADE_ERROR		= 0x0,
> +	FBNIC_FW_FINISH_UPGRADE_MSG_MAX
> +};
> +
>   #endif /* _FBNIC_FW_H_ */
> --
> 2.43.5


  reply	other threads:[~2024-10-14 11:05 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-12  2:34 [PATCH net-next 0/2] eth: fbnic: Add devlink dev flash support Lee Trager
2024-10-12  2:34 ` [PATCH net-next 1/2] eth: fbnic: Add mailbox support for PLDM updates Lee Trager
2024-10-14 11:05   ` Vadim Fedorenko [this message]
2024-10-12  2:34 ` [PATCH net-next 2/2] eth: fbnic: Add devlink dev flash support Lee Trager
2024-10-14 11:18   ` Vadim Fedorenko
2024-10-15 10:43     ` Simon Horman
2024-10-18 22:48       ` Lee Trager
2024-10-19  9:34         ` Simon Horman
2024-10-22  1:37 ` [PATCH net-next v2 0/2] " Lee Trager
2024-10-22  1:37 ` [PATCH net-next v2 1/2] eth: fbnic: Add mailbox support for PLDM updates Lee Trager
2024-10-26 15:12   ` Simon Horman
2024-10-22  1:42 ` [PATCH net-next v2 2/2] eth: fbnic: Add devlink dev flash support Lee Trager
2024-10-24  9:10   ` Simon Horman
2024-10-25 22:32     ` Lee Trager
2024-10-26 15:12       ` Simon Horman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ece8648c-e555-4a7a-9b73-8a8e7afd7b05@linux.dev \
    --to=vadim.fedorenko@linux.dev \
    --cc=alexanderduyck@fb.com \
    --cc=corbet@lwn.net \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kernel-team@meta.com \
    --cc=kuba@kernel.org \
    --cc=lee@trager.us \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mohsin.bashr@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=sanmanpradhan@meta.com \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.