net: libwx: Add mailbox api for wangxun pf drivers
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>
This commit is contained in:
committed by
Jakub Kicinski
parent
6a07e3af49
commit
29264a372d
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user