All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
To: Mengyuan Lou <mengyuanlou@net-swift.com>
Cc: netdev@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com,
	horms@kernel.org, andrew+netdev@lunn.ch,
	duanqiangwen@net-swift.com, linglingzhang@trustnetic.com,
	jiawenwu@net-swift.com
Subject: Re: [PATCH net-next 01/12] net: libwx: add mailbox api for wangxun vf drivers
Date: Wed, 18 Jun 2025 11:46:33 +0200	[thread overview]
Message-ID: <aFKK+SiUG1jMXr10@mev-dev.igk.intel.com> (raw)
In-Reply-To: <20250611083559.14175-2-mengyuanlou@net-swift.com>

On Wed, Jun 11, 2025 at 04:35:48PM +0800, Mengyuan Lou wrote:
> Implements the mailbox interfaces for Wangxun vf drivers which
> will be used in txgbevf and ngbevf.
> 
> Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
> ---
>  drivers/net/ethernet/wangxun/libwx/wx_mbx.c  | 256 +++++++++++++++++++
>  drivers/net/ethernet/wangxun/libwx/wx_mbx.h  |  22 ++
>  drivers/net/ethernet/wangxun/libwx/wx_type.h |   3 +
>  3 files changed, 281 insertions(+)
> 
> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_mbx.c b/drivers/net/ethernet/wangxun/libwx/wx_mbx.c
> index 73af5f11c3bd..ebfa07d50bd2 100644
> --- a/drivers/net/ethernet/wangxun/libwx/wx_mbx.c
> +++ b/drivers/net/ethernet/wangxun/libwx/wx_mbx.c
> @@ -174,3 +174,259 @@ int wx_check_for_rst_pf(struct wx *wx, u16 vf)
>  
>  	return 0;
>  }
> +
> +static u32 wx_read_v2p_mailbox(struct wx *wx)
> +{
> +	u32 mailbox = rd32(wx, WX_VXMAILBOX);
> +
> +	mailbox |= wx->mbx.mailbox;
> +	wx->mbx.mailbox |= mailbox & WX_VXMAILBOX_R2C_BITS;
> +
> +	return mailbox;
> +}
> +
> +/**
> + *  wx_obtain_mbx_lock_vf - obtain mailbox lock
> + *  @wx: pointer to the HW structure
> + *
> + *  Return: return 0 on success and -EBUSY on failure
> + **/
> +static int wx_obtain_mbx_lock_vf(struct wx *wx)
> +{
> +	int count = 5;
> +	u32 mailbox;
> +
> +	while (count--) {
> +		/* Take ownership of the buffer */
> +		wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_VFU);
> +
> +		/* reserve mailbox for vf use */
> +		mailbox = wx_read_v2p_mailbox(wx);
> +		if (mailbox & WX_VXMAILBOX_VFU)
> +			return 0;
> +	}

You can try to use read_poll_timeout(). In other poll also.

> +
> +	wx_err(wx, "Failed to obtain mailbox lock for VF.\n");
> +
> +	return -EBUSY;
> +}
> +
> +static int wx_check_for_bit_vf(struct wx *wx, u32 mask)
> +{
> +	u32 mailbox = wx_read_v2p_mailbox(wx);
> +
> +	wx->mbx.mailbox &= ~mask;
> +
> +	return (mailbox & mask ? 0 : -EBUSY);
> +}
> +
> +/**
> + *  wx_check_for_ack_vf - checks to see if the PF has ACK'd
> + *  @wx: pointer to the HW structure
> + *
> + *  Return: return 0 if the PF has set the status bit or else -EBUSY
> + **/
> +static int wx_check_for_ack_vf(struct wx *wx)
> +{
> +	/* read clear the pf ack bit */
> +	return wx_check_for_bit_vf(wx, WX_VXMAILBOX_PFACK);
> +}
> +
> +/**
> + *  wx_check_for_msg_vf - checks to see if the PF has sent mail
> + *  @wx: pointer to the HW structure
> + *
> + *  Return: return 0 if the PF has got req bit or else -EBUSY
> + **/
> +int wx_check_for_msg_vf(struct wx *wx)
> +{
> +	/* read clear the pf sts bit */
> +	return wx_check_for_bit_vf(wx, WX_VXMAILBOX_PFSTS);
> +}
> +
> +/**
> + *  wx_check_for_rst_vf - checks to see if the PF has reset
> + *  @wx: pointer to the HW structure
> + *
> + *  Return: return 0 if the PF has set the reset done and -EBUSY on failure
> + **/
> +int wx_check_for_rst_vf(struct wx *wx)
> +{
> +	/* read clear the pf reset done bit */
> +	return wx_check_for_bit_vf(wx,
> +				   WX_VXMAILBOX_RSTD |
> +				   WX_VXMAILBOX_RSTI);
> +}
> +
> +/**
> + *  wx_poll_for_msg - Wait for message notification
> + *  @wx: pointer to the HW structure
> + *
> + *  Return: return 0 if the VF has successfully received a message notification
> + **/
> +static int wx_poll_for_msg(struct wx *wx)
> +{
> +	struct wx_mbx_info *mbx = &wx->mbx;
> +	int countdown = mbx->timeout;
> +
> +	while (countdown && wx_check_for_msg_vf(wx)) {
> +		countdown--;
> +		if (!countdown)
> +			break;
> +		udelay(mbx->udelay);
> +	}

Here

> +
> +	return countdown ? 0 : -EBUSY;
> +}
> +
> +/**
> + *  wx_poll_for_ack - Wait for message acknowledgment
> + *  @wx: pointer to the HW structure
> + *
> + *  Return: return 0 if the VF has successfully received a message ack
> + **/
> +static int wx_poll_for_ack(struct wx *wx)
> +{
> +	struct wx_mbx_info *mbx = &wx->mbx;
> +	int countdown = mbx->timeout;
> +
> +	while (countdown && wx_check_for_ack_vf(wx)) {
> +		countdown--;
> +		if (!countdown)
> +			break;
> +		udelay(mbx->udelay);
> +	}

And here

> +
> +	return countdown ? 0 : -EBUSY;
> +}
> +
> +/**
> + *  wx_read_posted_mbx - Wait for message notification and receive message
> + *  @wx: pointer to the HW structure
> + *  @msg: The message buffer
> + *  @size: Length of buffer
> + *
> + *  Return: returns 0 if it successfully received a message notification and
> + *  copied it into the receive buffer.
> + **/
> +int wx_read_posted_mbx(struct wx *wx, u32 *msg, u16 size)
> +{
> +	int ret;
> +
> +	ret = wx_poll_for_msg(wx);
> +	/* if ack received read message, otherwise we timed out */
> +	if (!ret)
> +		ret = wx_read_mbx_vf(wx, msg, size);
> +
> +	return ret;

Nit, but usuall error path is in if statement. Sth like:

if (ret)
	return ret;

return wx_read_mbx_vf();

can be more readable for someone.

> +}
> +
> +/**
> + *  wx_write_posted_mbx - Write a message to the mailbox, wait for ack
> + *  @wx: pointer to the HW structure
> + *  @msg: The message buffer
> + *  @size: Length of buffer
> + *
> + *  Return: returns 0 if it successfully copied message into the buffer and
> + *  received an ack to that message within delay * timeout period
> + **/
> +int wx_write_posted_mbx(struct wx *wx, u32 *msg, u16 size)
> +{
> +	int ret;
> +
> +	/* send msg */
> +	ret = wx_write_mbx_vf(wx, msg, size);
> +	/* if msg sent wait until we receive an ack */
> +	if (!ret)
> +		ret = wx_poll_for_ack(wx);
> +
> +	return ret;
> +}
> +
> +/**
> + *  wx_write_mbx_vf - Write a message to the mailbox
> + *  @wx: pointer to the HW structure
> + *  @msg: The message buffer
> + *  @size: Length of buffer
> + *
> + *  Return: returns 0 if it successfully copied message into the buffer
> + **/
> +int wx_write_mbx_vf(struct wx *wx, u32 *msg, u16 size)
> +{
> +	struct wx_mbx_info *mbx = &wx->mbx;
> +	int ret, i;
> +
> +	/* mbx->size is up to 15 */
> +	if (size > mbx->size) {
> +		wx_err(wx, "Invalid mailbox message size %d", size);
> +		return -EINVAL;
> +	}
> +
> +	/* lock the mailbox to prevent pf/vf race condition */
> +	ret = wx_obtain_mbx_lock_vf(wx);
> +	if (ret)
> +		return ret;
> +
> +	/* flush msg and acks as we are overwriting the message buffer */
> +	wx_check_for_msg_vf(wx);
> +	wx_check_for_ack_vf(wx);

Isn't checking returned value needed here?

> +
> +	/* copy the caller specified message to the mailbox memory buffer */
> +	for (i = 0; i < size; i++)
> +		wr32a(wx, WX_VXMBMEM, i, msg[i]);
> +
> +	/* Drop VFU and interrupt the PF to tell it a message has been sent */
> +	wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_REQ);

It isn't clear that it drops lock, maybe do it in a function like
wx_drop_mbx_lock_vf()? (just preference)

> +
> +	return 0;
> +}
> +
> +/**
> + *  wx_read_mbx_vf - Reads a message from the inbox intended for vf
> + *  @wx: pointer to the HW structure
> + *  @msg: The message buffer
> + *  @size: Length of buffer
> + *
> + *  Return: returns 0 if it successfully copied message into the buffer
> + **/
> +int wx_read_mbx_vf(struct wx *wx, u32 *msg, u16 size)
> +{
> +	struct wx_mbx_info *mbx = &wx->mbx;
> +	int ret;
> +	u16 i;

int ret, i; like in previous function

> +
> +	/* limit read to size of mailbox and mbx->size is up to 15 */
> +	if (size > mbx->size)
> +		size = mbx->size;
> +
> +	/* lock the mailbox to prevent pf/vf race condition */
> +	ret = wx_obtain_mbx_lock_vf(wx);
> +	if (ret)
> +		return ret;
> +
> +	/* copy the message from the mailbox memory buffer */
> +	for (i = 0; i < size; i++)
> +		msg[i] = rd32a(wx, WX_VXMBMEM, i);
> +
> +	/* Acknowledge receipt and release mailbox, then we're done */
> +	wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_ACK);

Oh, so any value written into WX_VXMAILVOX drop the lock. Ignore my
comment about function for that.

> +
> +	return 0;
> +}
> +
> +int wx_init_mbx_params_vf(struct wx *wx)
> +{
> +	wx->vfinfo = kcalloc(1, sizeof(struct vf_data_storage),
> +			     GFP_KERNEL);

Why kcalloc() for 1 element?

> +	if (!wx->vfinfo)
> +		return -ENOMEM;
> +
> +	/* Initialize mailbox parameters */
> +	wx->mbx.size = WX_VXMAILBOX_SIZE;
> +	wx->mbx.mailbox = WX_VXMAILBOX;
> +	wx->mbx.udelay = 10;
> +	wx->mbx.timeout = 1000;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(wx_init_mbx_params_vf);
> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_mbx.h b/drivers/net/ethernet/wangxun/libwx/wx_mbx.h
> index 05aae138dbc3..82df9218490a 100644
> --- a/drivers/net/ethernet/wangxun/libwx/wx_mbx.h
> +++ b/drivers/net/ethernet/wangxun/libwx/wx_mbx.h
> @@ -11,6 +11,20 @@
>  #define WX_PXMAILBOX_ACK     BIT(1) /* Ack message recv'd from VF */
>  #define WX_PXMAILBOX_PFU     BIT(3) /* PF owns the mailbox buffer */
>  
> +/* VF Registers */
> +#define WX_VXMAILBOX         0x600
> +#define WX_VXMAILBOX_REQ     BIT(0) /* Request for PF Ready bit */
> +#define WX_VXMAILBOX_ACK     BIT(1) /* Ack PF message received */
> +#define WX_VXMAILBOX_VFU     BIT(2) /* VF owns the mailbox buffer */
> +#define WX_VXMAILBOX_PFU     BIT(3) /* PF owns the mailbox buffer */
> +#define WX_VXMAILBOX_PFSTS   BIT(4) /* PF wrote a message in the MB */
> +#define WX_VXMAILBOX_PFACK   BIT(5) /* PF ack the previous VF msg */
> +#define WX_VXMAILBOX_RSTI    BIT(6) /* PF has reset indication */
> +#define WX_VXMAILBOX_RSTD    BIT(7) /* PF has indicated reset done */
> +#define WX_VXMAILBOX_R2C_BITS (WX_VXMAILBOX_RSTD | \
> +	    WX_VXMAILBOX_PFSTS | WX_VXMAILBOX_PFACK)
> +
> +#define WX_VXMBMEM           0x00C00 /* 16*4B */
>  #define WX_PXMBMEM(i)        (0x5000 + (64 * (i))) /* i=[0,63] */
>  
>  #define WX_VFLRE(i)          (0x4A0 + (4 * (i))) /* i=[0,1] */
> @@ -74,4 +88,12 @@ int wx_check_for_rst_pf(struct wx *wx, u16 mbx_id);
>  int wx_check_for_msg_pf(struct wx *wx, u16 mbx_id);
>  int wx_check_for_ack_pf(struct wx *wx, u16 mbx_id);
>  
> +int wx_read_posted_mbx(struct wx *wx, u32 *msg, u16 size);
> +int wx_write_posted_mbx(struct wx *wx, u32 *msg, u16 size);
> +int wx_check_for_rst_vf(struct wx *wx);
> +int wx_check_for_msg_vf(struct wx *wx);
> +int wx_read_mbx_vf(struct wx *wx, u32 *msg, u16 size);
> +int wx_write_mbx_vf(struct wx *wx, u32 *msg, u16 size);
> +int wx_init_mbx_params_vf(struct wx *wx);
> +
>  #endif /* _WX_MBX_H_ */
> diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
> index 7730c9fc3e02..f2061c893358 100644
> --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
> +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
> @@ -825,6 +825,9 @@ struct wx_bus_info {
>  
>  struct wx_mbx_info {
>  	u16 size;
> +	u32 mailbox;
> +	u32 udelay;
> +	u32 timeout;
>  };
>  
>  struct wx_thermal_sensor_data {
> -- 
> 2.30.1

  reply	other threads:[~2025-06-18  9:47 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-11  8:35 [PATCH net-next 00/12] Add vf drivers for wangxun virtual functions Mengyuan Lou
2025-06-11  8:35 ` [PATCH net-next 01/12] net: libwx: add mailbox api for wangxun vf drivers Mengyuan Lou
2025-06-18  9:46   ` Michal Swiatkowski [this message]
2025-06-20  8:32     ` mengyuanlou
2025-06-11  8:35 ` [PATCH net-next 02/12] net: libwx: add base vf api for " Mengyuan Lou
2025-06-18 11:28   ` Michal Swiatkowski
2025-06-20 10:27     ` mengyuanlou
2025-06-11  8:35 ` [PATCH net-next 03/12] net: libwx: add wangxun vf common api Mengyuan Lou
2025-06-17 15:11   ` Simon Horman
2025-06-20  8:02     ` mengyuanlou
2025-06-11  8:35 ` [PATCH net-next 04/12] net: wangxun: add txgbevf build Mengyuan Lou
2025-06-11  8:35 ` [PATCH net-next 05/12] net: txgbevf: add sw init pci info and reset hardware Mengyuan Lou
2025-06-11  8:35 ` [PATCH net-next 06/12] net: txgbevf: init interrupts and request irqs Mengyuan Lou
2025-06-11 22:39   ` kernel test robot
2025-06-11  8:35 ` [PATCH net-next 07/12] net: txgbevf: Support Rx and Tx process path Mengyuan Lou
2025-06-11  8:35 ` [PATCH net-next 08/12] net: txgbevf: add phylink check flow Mengyuan Lou
2025-06-11  8:35 ` [PATCH net-next 09/12] net: wangxun: add ngbevf build Mengyuan Lou
2025-06-11  8:35 ` [PATCH net-next 10/12] net: ngbevf: add sw init pci info and reset hardware Mengyuan Lou
2025-06-11  8:35 ` [PATCH net-next 11/12] net: ngbevf: init interrupts and request irqs Mengyuan Lou
2025-06-11  8:35 ` [PATCH net-next 12/12] net: ngbevf: add phylink check flow Mengyuan Lou

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=aFKK+SiUG1jMXr10@mev-dev.igk.intel.com \
    --to=michal.swiatkowski@linux.intel.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=duanqiangwen@net-swift.com \
    --cc=horms@kernel.org \
    --cc=jiawenwu@net-swift.com \
    --cc=kuba@kernel.org \
    --cc=linglingzhang@trustnetic.com \
    --cc=mengyuanlou@net-swift.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /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.