]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: libwx: add mailbox api for wangxun vf drivers
authorMengyuan Lou <mengyuanlou@net-swift.com>
Fri, 4 Jul 2025 09:49:12 +0000 (17:49 +0800)
committerJakub Kicinski <kuba@kernel.org>
Thu, 10 Jul 2025 01:39:12 +0000 (18:39 -0700)
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>
Link: https://patch.msgid.link/20250704094923.652-2-mengyuanlou@net-swift.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/wangxun/libwx/wx_mbx.c
drivers/net/ethernet/wangxun/libwx/wx_mbx.h
drivers/net/ethernet/wangxun/libwx/wx_type.h

index 73af5f11c3bdcd9b5b62add924e508b5fa6cb7b3..2aa03eadf064e16aa3fb0345aa7bab2ee3193f5c 100644 (file)
@@ -174,3 +174,246 @@ 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;
+}
+
+static u32 wx_mailbox_get_lock_vf(struct wx *wx)
+{
+       wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_VFU);
+       return wx_read_v2p_mailbox(wx);
+}
+
+/**
+ *  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, ret;
+       u32 mailbox;
+
+       ret = readx_poll_timeout_atomic(wx_mailbox_get_lock_vf, wx, mailbox,
+                                       (mailbox & WX_VXMAILBOX_VFU),
+                                       1, count);
+       if (ret)
+               wx_err(wx, "Failed to obtain mailbox lock for VF.\n");
+
+       return ret;
+}
+
+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;
+       u32 val;
+
+       return readx_poll_timeout_atomic(wx_check_for_msg_vf, wx, val,
+                                        (val == 0), mbx->udelay, mbx->timeout);
+}
+
+/**
+ *  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;
+       u32 val;
+
+       return readx_poll_timeout_atomic(wx_check_for_ack_vf, wx, val,
+                                        (val == 0), mbx->udelay, mbx->timeout);
+}
+
+/**
+ *  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)
+               return ret;
+
+       return wx_read_mbx_vf(wx, msg, size);
+}
+
+/**
+ *  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)
+               return ret;
+
+       return wx_poll_for_ack(wx);
+}
+
+/**
+ *  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);
+
+       /* 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);
+
+       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, i;
+
+       /* 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);
+
+       return 0;
+}
+
+int wx_init_mbx_params_vf(struct wx *wx)
+{
+       wx->vfinfo = kzalloc(sizeof(struct vf_data_storage),
+                            GFP_KERNEL);
+       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);
index 05aae138dbc317e77e00acb49197cf9c71f6a99d..82df9218490a0d1b3f0b16bd62de856921f027ab 100644 (file)
 #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_ */
index c363379126c040d2c6519e5472f6cb76ec484621..3d4785865bb22491fc85be121f3d1813cf8c21e9 100644 (file)
@@ -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 {