Commit 29264a37 authored by Mengyuan Lou's avatar Mengyuan Lou Committed by Jakub Kicinski
Browse files

net: libwx: Add mailbox api for wangxun pf drivers



Implements the mailbox interfaces for wangxun pf drivers
ngbe and txgbe.

Signed-off-by: default avatarMengyuan Lou <mengyuanlou@net-swift.com>
Link: https://patch.msgid.link/70017BD4D67614A4+20250408091556.9640-2-mengyuanlou@net-swift.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 6a07e3af
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+176 −0
Original line number Diff line number Diff line
// 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;
}
+32 −0
Original line number Diff line number Diff line
/* 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_ */
+8 −0
Original line number Diff line number Diff line
@@ -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;