Message ID | 78F07A41FB029765+20240804124841.71177-2-mengyuanlou@net-swift.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net-next,v5,01/10] net: libwx: Add malibox api for wangxun pf drivers | expand |
On Sun, Aug 04, 2024 at 08:48:32PM +0800, Mengyuan Lou wrote: > Implements the mailbox interfaces for wangxun pf drivers > ngbe and txgbe. > > Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com> ... > diff --git a/drivers/net/ethernet/wangxun/libwx/wx_mbx.c b/drivers/net/ethernet/wangxun/libwx/wx_mbx.c > new file mode 100644 > index 000000000000..5062ddb2ce39 > --- /dev/null > +++ b/drivers/net/ethernet/wangxun/libwx/wx_mbx.c > @@ -0,0 +1,175 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* Copyright (c) 2015 - 2024 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 != 1) Should this be 'else if (count)' in order to skip the delay on the last rather than 2nd to last iteration without success? > + udelay(10); > + } > + wx_err(wx, "Failed to obtain mailbox lock for PF%d", vf); > + > + return -EBUSY; > +} ...
On 8/4/24 14:48, Mengyuan Lou wrote: > Implements the mailbox interfaces for wangxun pf drivers > ngbe and txgbe. > > Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com> it would be great to have a cover letter over the series > --- > drivers/net/ethernet/wangxun/libwx/Makefile | 2 +- > drivers/net/ethernet/wangxun/libwx/wx_mbx.c | 175 +++++++++++++++++++ > drivers/net/ethernet/wangxun/libwx/wx_mbx.h | 32 ++++ > drivers/net/ethernet/wangxun/libwx/wx_type.h | 8 + > 4 files changed, 216 insertions(+), 1 deletion(-) > create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_mbx.c > create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_mbx.h > > diff --git a/drivers/net/ethernet/wangxun/libwx/Makefile b/drivers/net/ethernet/wangxun/libwx/Makefile > index 42ccd6e4052e..913a978c9032 100644 > --- a/drivers/net/ethernet/wangxun/libwx/Makefile > +++ b/drivers/net/ethernet/wangxun/libwx/Makefile > @@ -4,4 +4,4 @@ > > obj-$(CONFIG_LIBWX) += libwx.o > > -libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o > +libwx-objs := wx_hw.o wx_lib.o wx_ethtool.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 > index 000000000000..5062ddb2ce39 > --- /dev/null > +++ b/drivers/net/ethernet/wangxun/libwx/wx_mbx.c > @@ -0,0 +1,175 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */ > +#include <linux/pci.h> typically you put a newline between different subsystems and another one prior to your own headers (this case) > +#include "wx_type.h" > +#include "wx_mbx.h" and it's good to start with include list sorted > + > +/** > + * 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 capitalize the first return word > + **/ > +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 != 1) you should exclude count == 0, not == 1 > + udelay(10); > + } > + wx_err(wx, "Failed to obtain mailbox lock for PF%d", vf); would be good to ratelimit that > + > + 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) == 0) the preferred style is to simply write !cond instead of cond == 0 > + return -EBUSY; > + wr32(wx, WX_MBVFICR(index), mask); > + > + return 0; > +} > + > +/** > + * wx_check_for_ack_pf - checks to see if the VF has acked I would rephrase to: check if PF was acked by VF > + * @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)), double check: do you want to set just one bit, in the upper half of the u32 word, that will be passed as @mask to wx_check_for_bit_pf()? > + 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) typically function parameters should not be limited to smaller sizes than 4B > +{ > + struct wx_mbx_info *mbx = &wx->mbx; > + int ret, i; best place to declare variable @i is inside the for statement > + > + /* 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 */ should the buffer be already empty? that's a bad smell > + 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*/ missing space before "*/", and your are releasing the lock, not a 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) I would spell "reset" fully > +{ > + 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; > +} please apply all my feedback in analogous places through whole series
diff --git a/drivers/net/ethernet/wangxun/libwx/Makefile b/drivers/net/ethernet/wangxun/libwx/Makefile index 42ccd6e4052e..913a978c9032 100644 --- a/drivers/net/ethernet/wangxun/libwx/Makefile +++ b/drivers/net/ethernet/wangxun/libwx/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_LIBWX) += libwx.o -libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o +libwx-objs := wx_hw.o wx_lib.o wx_ethtool.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 index 000000000000..5062ddb2ce39 --- /dev/null +++ b/drivers/net/ethernet/wangxun/libwx/wx_mbx.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2015 - 2024 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 != 1) + 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) == 0) + 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 index 000000000000..1579096fb6ad --- /dev/null +++ b/drivers/net/ethernet/wangxun/libwx/wx_mbx.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2015 - 2024 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_ */ diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index 1d57b047817b..5b9d5fd7033d 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -20,6 +20,9 @@ #define WX_PCI_LINK_STATUS 0xB2 /**************** Global Registers ****************************/ +#define WX_VF_REG_OFFSET(_v) ((_v) >> 5) +#define WX_VF_IND_SHIFT(_v) ((_v) & 0x1f) + /* chip control Registers */ #define WX_MIS_PWR 0x10000 #define WX_MIS_RST 0x1000C @@ -707,6 +710,10 @@ struct wx_bus_info { u16 device; }; +struct wx_mbx_info { + u16 size; +}; + struct wx_thermal_sensor_data { s16 temp; s16 alarm_thresh; @@ -1046,6 +1053,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;
Implements the mailbox interfaces for wangxun pf drivers ngbe and txgbe. Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com> --- drivers/net/ethernet/wangxun/libwx/Makefile | 2 +- drivers/net/ethernet/wangxun/libwx/wx_mbx.c | 175 +++++++++++++++++++ drivers/net/ethernet/wangxun/libwx/wx_mbx.h | 32 ++++ drivers/net/ethernet/wangxun/libwx/wx_type.h | 8 + 4 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_mbx.c create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_mbx.h