net: libwx: Add mailbox api for wangxun pf drivers
authorMengyuan Lou <mengyuanlou@net-swift.com>
Tue, 8 Apr 2025 09:15:51 +0000 (17:15 +0800)
committerJakub Kicinski <kuba@kernel.org>
Thu, 10 Apr 2025 02:29:05 +0000 (19:29 -0700)
Implements the mailbox interfaces for wangxun pf drivers
ngbe and txgbe.

Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com>
Link: https://patch.msgid.link/70017BD4D67614A4+20250408091556.9640-2-mengyuanlou@net-swift.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/wangxun/libwx/Makefile
drivers/net/ethernet/wangxun/libwx/wx_mbx.c [new file with mode: 0644]
drivers/net/ethernet/wangxun/libwx/wx_mbx.h [new file with mode: 0644]
drivers/net/ethernet/wangxun/libwx/wx_type.h

index e9f0f1f2309bf0c596d5a755126a89b96601aac0..cd1675ef32531de782b0065df09d89ad95d4ef32 100644 (file)
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_LIBWX) += libwx.o
 
-libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_ptp.o
+libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_ptp.o wx_mbx.o
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_mbx.c b/drivers/net/ethernet/wangxun/libwx/wx_mbx.c
new file mode 100644 (file)
index 0000000..73af5f1
--- /dev/null
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
+
+#include <linux/pci.h>
+#include "wx_type.h"
+#include "wx_mbx.h"
+
+/**
+ *  wx_obtain_mbx_lock_pf - obtain mailbox lock
+ *  @wx: pointer to the HW structure
+ *  @vf: the VF index
+ *
+ *  Return: return 0 on success and -EBUSY on failure
+ **/
+static int wx_obtain_mbx_lock_pf(struct wx *wx, u16 vf)
+{
+       int count = 5;
+       u32 mailbox;
+
+       while (count--) {
+               /* Take ownership of the buffer */
+               wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_PFU);
+
+               /* reserve mailbox for vf use */
+               mailbox = rd32(wx, WX_PXMAILBOX(vf));
+               if (mailbox & WX_PXMAILBOX_PFU)
+                       return 0;
+               else if (count)
+                       udelay(10);
+       }
+       wx_err(wx, "Failed to obtain mailbox lock for PF%d", vf);
+
+       return -EBUSY;
+}
+
+static int wx_check_for_bit_pf(struct wx *wx, u32 mask, int index)
+{
+       u32 mbvficr = rd32(wx, WX_MBVFICR(index));
+
+       if (!(mbvficr & mask))
+               return -EBUSY;
+       wr32(wx, WX_MBVFICR(index), mask);
+
+       return 0;
+}
+
+/**
+ *  wx_check_for_ack_pf - checks to see if the VF has acked
+ *  @wx: pointer to the HW structure
+ *  @vf: the VF index
+ *
+ *  Return: return 0 if the VF has set the status bit or else -EBUSY
+ **/
+int wx_check_for_ack_pf(struct wx *wx, u16 vf)
+{
+       u32 index = vf / 16, vf_bit = vf % 16;
+
+       return wx_check_for_bit_pf(wx,
+                                  FIELD_PREP(WX_MBVFICR_VFACK_MASK,
+                                             BIT(vf_bit)),
+                                  index);
+}
+
+/**
+ *  wx_check_for_msg_pf - checks to see if the VF has sent mail
+ *  @wx: pointer to the HW structure
+ *  @vf: the VF index
+ *
+ *  Return: return 0 if the VF has got req bit or else -EBUSY
+ **/
+int wx_check_for_msg_pf(struct wx *wx, u16 vf)
+{
+       u32 index = vf / 16, vf_bit = vf % 16;
+
+       return wx_check_for_bit_pf(wx,
+                                  FIELD_PREP(WX_MBVFICR_VFREQ_MASK,
+                                             BIT(vf_bit)),
+                                  index);
+}
+
+/**
+ *  wx_write_mbx_pf - Places a message in the mailbox
+ *  @wx: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @vf: the VF index
+ *
+ *  Return: return 0 on success and -EINVAL/-EBUSY on failure
+ **/
+int wx_write_mbx_pf(struct wx *wx, u32 *msg, u16 size, u16 vf)
+{
+       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_pf(wx, vf);
+       if (ret)
+               return ret;
+
+       /* flush msg and acks as we are overwriting the message buffer */
+       wx_check_for_msg_pf(wx, vf);
+       wx_check_for_ack_pf(wx, vf);
+
+       /* copy the caller specified message to the mailbox memory buffer */
+       for (i = 0; i < size; i++)
+               wr32a(wx, WX_PXMBMEM(vf), i, msg[i]);
+
+       /* Interrupt VF to tell it a message has been sent and release buffer */
+       /* set mirrored mailbox flags */
+       wr32a(wx, WX_PXMBMEM(vf), WX_VXMAILBOX_SIZE, WX_PXMAILBOX_STS);
+       wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_STS);
+
+       return 0;
+}
+
+/**
+ *  wx_read_mbx_pf - Read a message from the mailbox
+ *  @wx: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @vf: the VF index
+ *
+ *  Return: return 0 on success and -EBUSY on failure
+ **/
+int wx_read_mbx_pf(struct wx *wx, u32 *msg, u16 size, u16 vf)
+{
+       struct wx_mbx_info *mbx = &wx->mbx;
+       int ret;
+       u16 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_pf(wx, vf);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < size; i++)
+               msg[i] = rd32a(wx, WX_PXMBMEM(vf), i);
+
+       /* Acknowledge the message and release buffer */
+       /* set mirrored mailbox flags */
+       wr32a(wx, WX_PXMBMEM(vf), WX_VXMAILBOX_SIZE, WX_PXMAILBOX_ACK);
+       wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_ACK);
+
+       return 0;
+}
+
+/**
+ *  wx_check_for_rst_pf - checks to see if the VF has reset
+ *  @wx: pointer to the HW structure
+ *  @vf: the VF index
+ *
+ *  Return: return 0 on success and -EBUSY on failure
+ **/
+int wx_check_for_rst_pf(struct wx *wx, u16 vf)
+{
+       u32 reg_offset = WX_VF_REG_OFFSET(vf);
+       u32 vf_shift = WX_VF_IND_SHIFT(vf);
+       u32 vflre = 0;
+
+       vflre = rd32(wx, WX_VFLRE(reg_offset));
+       if (!(vflre & BIT(vf_shift)))
+               return -EBUSY;
+       wr32(wx, WX_VFLREC(reg_offset), BIT(vf_shift));
+
+       return 0;
+}
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_mbx.h b/drivers/net/ethernet/wangxun/libwx/wx_mbx.h
new file mode 100644 (file)
index 0000000..c09b25f
--- /dev/null
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
+#ifndef _WX_MBX_H_
+#define _WX_MBX_H_
+
+#define WX_VXMAILBOX_SIZE    15
+
+/* PF Registers */
+#define WX_PXMAILBOX(i)      (0x600 + (4 * (i))) /* i=[0,63] */
+#define WX_PXMAILBOX_STS     BIT(0) /* Initiate message send to VF */
+#define WX_PXMAILBOX_ACK     BIT(1) /* Ack message recv'd from VF */
+#define WX_PXMAILBOX_PFU     BIT(3) /* PF owns the mailbox buffer */
+
+#define WX_PXMBMEM(i)        (0x5000 + (64 * (i))) /* i=[0,63] */
+
+#define WX_VFLRE(i)          (0x4A0 + (4 * (i))) /* i=[0,1] */
+#define WX_VFLREC(i)         (0x4A8 + (4 * (i))) /* i=[0,1] */
+
+/* SR-IOV specific macros */
+#define WX_MBVFICR(i)         (0x480 + (4 * (i))) /* i=[0,3] */
+#define WX_MBVFICR_VFREQ_MASK GENMASK(15, 0)
+#define WX_MBVFICR_VFACK_MASK GENMASK(31, 16)
+
+#define WX_VT_MSGINFO_MASK    GENMASK(23, 16)
+
+int wx_write_mbx_pf(struct wx *wx, u32 *msg, u16 size, u16 vf);
+int wx_read_mbx_pf(struct wx *wx, u32 *msg, u16 size, u16 vf);
+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);
+
+#endif /* _WX_MBX_H_ */
index 5b230ecbbabb5179327a31238a5c62ac608e3cdc..18287b0ee04013e668948f2c63e2237f9cd2251d 100644 (file)
@@ -22,6 +22,9 @@
 #define WX_PCI_LINK_STATUS                      0xB2
 
 /**************** Global Registers ****************************/
+#define WX_VF_REG_OFFSET(_v)         FIELD_GET(GENMASK(15, 5), (_v))
+#define WX_VF_IND_SHIFT(_v)          FIELD_GET(GENMASK(4, 0), (_v))
+
 /* chip control Registers */
 #define WX_MIS_PWR                   0x10000
 #define WX_MIS_RST                   0x1000C
@@ -779,6 +782,10 @@ struct wx_bus_info {
        u16 device;
 };
 
+struct wx_mbx_info {
+       u16 size;
+};
+
 struct wx_thermal_sensor_data {
        s16 temp;
        s16 alarm_thresh;
@@ -1129,6 +1136,7 @@ struct wx {
        struct pci_dev *pdev;
        struct net_device *netdev;
        struct wx_bus_info bus;
+       struct wx_mbx_info mbx;
        struct wx_mac_info mac;
        enum em_mac_type mac_type;
        enum sp_media_type media_type;