mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-08-30 13:03:01 +00:00
net: libwx: add wangxun vf common api
Add common wx_configure_vf and wx_set_mac_vf for ngbevf and txgbevf. Signed-off-by: Mengyuan Lou <mengyuanlou@net-swift.com> Link: https://patch.msgid.link/20250704094923.652-4-mengyuanlou@net-swift.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
ba3b8490bc
commit
eb4898fde1
@ -5,4 +5,4 @@
|
||||
obj-$(CONFIG_LIBWX) += libwx.o
|
||||
|
||||
libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_ptp.o wx_mbx.o wx_sriov.o
|
||||
libwx-objs += wx_vf.o
|
||||
libwx-objs += wx_vf.o wx_vf_lib.o wx_vf_common.o
|
||||
|
@ -1827,7 +1827,7 @@ void wx_disable_rx_queue(struct wx *wx, struct wx_ring *ring)
|
||||
}
|
||||
EXPORT_SYMBOL(wx_disable_rx_queue);
|
||||
|
||||
static void wx_enable_rx_queue(struct wx *wx, struct wx_ring *ring)
|
||||
void wx_enable_rx_queue(struct wx *wx, struct wx_ring *ring)
|
||||
{
|
||||
u8 reg_idx = ring->reg_idx;
|
||||
u32 rxdctl;
|
||||
@ -1843,6 +1843,7 @@ static void wx_enable_rx_queue(struct wx *wx, struct wx_ring *ring)
|
||||
reg_idx);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(wx_enable_rx_queue);
|
||||
|
||||
static void wx_configure_srrctl(struct wx *wx,
|
||||
struct wx_ring *rx_ring)
|
||||
|
@ -38,6 +38,7 @@ void wx_enable_sec_rx_path(struct wx *wx);
|
||||
void wx_set_rx_mode(struct net_device *netdev);
|
||||
int wx_change_mtu(struct net_device *netdev, int new_mtu);
|
||||
void wx_disable_rx_queue(struct wx *wx, struct wx_ring *ring);
|
||||
void wx_enable_rx_queue(struct wx *wx, struct wx_ring *ring);
|
||||
void wx_configure_rx(struct wx *wx);
|
||||
void wx_configure(struct wx *wx);
|
||||
void wx_start_hw(struct wx *wx);
|
||||
|
@ -828,6 +828,8 @@ struct wx_mbx_info {
|
||||
u32 mailbox;
|
||||
u32 udelay;
|
||||
u32 timeout;
|
||||
/* lock mbx access */
|
||||
spinlock_t mbx_lock;
|
||||
};
|
||||
|
||||
struct wx_thermal_sensor_data {
|
||||
@ -1289,6 +1291,8 @@ struct wx {
|
||||
u32 *isb_mem;
|
||||
u32 isb_tag[WX_ISB_MAX];
|
||||
bool misc_irq_domain;
|
||||
u32 eims_other;
|
||||
u32 eims_enable_mask;
|
||||
|
||||
#define WX_MAX_RETA_ENTRIES 128
|
||||
#define WX_RSS_INDIR_TBL_MAX 64
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define WX_VXMRQC 0x78
|
||||
#define WX_VXICR 0x100
|
||||
#define WX_VXIMS 0x108
|
||||
#define WX_VXIMC 0x10C
|
||||
#define WX_VF_IRQ_CLEAR_MASK 7
|
||||
#define WX_VF_MAX_TX_QUEUES 4
|
||||
#define WX_VF_MAX_RX_QUEUES 4
|
||||
@ -22,6 +23,12 @@
|
||||
#define WX_VXRXDCTL_ENABLE BIT(0)
|
||||
#define WX_VXTXDCTL_FLUSH BIT(26)
|
||||
|
||||
#define WX_VXITR(i) (0x200 + (4 * (i))) /* i=[0,1] */
|
||||
#define WX_VXITR_MASK GENMASK(8, 0)
|
||||
#define WX_VXITR_CNT_WDIS BIT(31)
|
||||
#define WX_VXIVAR_MISC 0x260
|
||||
#define WX_VXIVAR(i) (0x240 + (4 * (i))) /* i=[0,3] */
|
||||
|
||||
#define WX_VXRXDCTL_RSCMAX(f) FIELD_PREP(GENMASK(24, 23), f)
|
||||
#define WX_VXRXDCTL_BUFLEN(f) FIELD_PREP(GENMASK(6, 1), f)
|
||||
#define WX_VXRXDCTL_BUFSZ(f) FIELD_PREP(GENMASK(11, 8), f)
|
||||
@ -44,6 +51,49 @@
|
||||
#define WX_RX_HDR_SIZE 256
|
||||
#define WX_RX_BUF_SIZE 2048
|
||||
|
||||
#define WX_RXBUFFER_2048 (2048)
|
||||
#define WX_RXBUFFER_3072 3072
|
||||
|
||||
/* Receive Path */
|
||||
#define WX_VXRDBAL(r) (0x1000 + (0x40 * (r)))
|
||||
#define WX_VXRDBAH(r) (0x1004 + (0x40 * (r)))
|
||||
#define WX_VXRDT(r) (0x1008 + (0x40 * (r)))
|
||||
#define WX_VXRDH(r) (0x100C + (0x40 * (r)))
|
||||
|
||||
#define WX_VXRXDCTL_RSCEN BIT(29)
|
||||
#define WX_VXRXDCTL_DROP BIT(30)
|
||||
#define WX_VXRXDCTL_VLAN BIT(31)
|
||||
|
||||
#define WX_VXTDBAL(r) (0x3000 + (0x40 * (r)))
|
||||
#define WX_VXTDBAH(r) (0x3004 + (0x40 * (r)))
|
||||
#define WX_VXTDT(r) (0x3008 + (0x40 * (r)))
|
||||
#define WX_VXTDH(r) (0x300C + (0x40 * (r)))
|
||||
|
||||
#define WX_VXTXDCTL_ENABLE BIT(0)
|
||||
#define WX_VXTXDCTL_BUFLEN(f) FIELD_PREP(GENMASK(6, 1), f)
|
||||
#define WX_VXTXDCTL_PTHRESH(f) FIELD_PREP(GENMASK(11, 8), f)
|
||||
#define WX_VXTXDCTL_WTHRESH(f) FIELD_PREP(GENMASK(22, 16), f)
|
||||
|
||||
#define WX_VXMRQC_PSR(f) FIELD_PREP(GENMASK(5, 1), f)
|
||||
#define WX_VXMRQC_PSR_MASK GENMASK(5, 1)
|
||||
#define WX_VXMRQC_PSR_L4HDR BIT(0)
|
||||
#define WX_VXMRQC_PSR_L3HDR BIT(1)
|
||||
#define WX_VXMRQC_PSR_L2HDR BIT(2)
|
||||
#define WX_VXMRQC_PSR_TUNHDR BIT(3)
|
||||
#define WX_VXMRQC_PSR_TUNMAC BIT(4)
|
||||
|
||||
#define WX_VXRSSRK(i) (0x80 + ((i) * 4)) /* i=[0,9] */
|
||||
#define WX_VXRETA(i) (0xC0 + ((i) * 4)) /* i=[0,15] */
|
||||
|
||||
#define WX_VXMRQC_RSS(f) FIELD_PREP(GENMASK(31, 16), f)
|
||||
#define WX_VXMRQC_RSS_MASK GENMASK(31, 16)
|
||||
#define WX_VXMRQC_RSS_ALG_IPV4_TCP BIT(0)
|
||||
#define WX_VXMRQC_RSS_ALG_IPV4 BIT(1)
|
||||
#define WX_VXMRQC_RSS_ALG_IPV6 BIT(4)
|
||||
#define WX_VXMRQC_RSS_ALG_IPV6_TCP BIT(5)
|
||||
#define WX_VXMRQC_RSS_EN BIT(8)
|
||||
#define WX_VXMRQC_RSS_HASH(f) FIELD_PREP(GENMASK(15, 13), f)
|
||||
|
||||
void wx_init_hw_vf(struct wx *wx);
|
||||
int wx_reset_hw_vf(struct wx *wx);
|
||||
void wx_get_mac_addr_vf(struct wx *wx, u8 *mac_addr);
|
||||
|
196
drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
Normal file
196
drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
Normal file
@ -0,0 +1,196 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "wx_type.h"
|
||||
#include "wx_mbx.h"
|
||||
#include "wx_lib.h"
|
||||
#include "wx_vf.h"
|
||||
#include "wx_vf_lib.h"
|
||||
#include "wx_vf_common.h"
|
||||
|
||||
static irqreturn_t wx_msix_misc_vf(int __always_unused irq, void *data)
|
||||
{
|
||||
struct wx *wx = data;
|
||||
|
||||
/* Clear the interrupt */
|
||||
if (netif_running(wx->netdev))
|
||||
wr32(wx, WX_VXIMC, wx->eims_other);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int wx_request_msix_irqs_vf(struct wx *wx)
|
||||
{
|
||||
struct net_device *netdev = wx->netdev;
|
||||
int vector, err;
|
||||
|
||||
for (vector = 0; vector < wx->num_q_vectors; vector++) {
|
||||
struct wx_q_vector *q_vector = wx->q_vector[vector];
|
||||
struct msix_entry *entry = &wx->msix_q_entries[vector];
|
||||
|
||||
if (q_vector->tx.ring && q_vector->rx.ring)
|
||||
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
|
||||
"%s-TxRx-%d", netdev->name, entry->entry);
|
||||
else
|
||||
/* skip this unused q_vector */
|
||||
continue;
|
||||
|
||||
err = request_irq(entry->vector, wx_msix_clean_rings, 0,
|
||||
q_vector->name, q_vector);
|
||||
if (err) {
|
||||
wx_err(wx, "request_irq failed for MSIX interrupt %s Error: %d\n",
|
||||
q_vector->name, err);
|
||||
goto free_queue_irqs;
|
||||
}
|
||||
}
|
||||
|
||||
err = request_threaded_irq(wx->msix_entry->vector, NULL,
|
||||
wx_msix_misc_vf, IRQF_ONESHOT,
|
||||
netdev->name, wx);
|
||||
if (err) {
|
||||
wx_err(wx, "request_irq for msix_other failed: %d\n", err);
|
||||
goto free_queue_irqs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_queue_irqs:
|
||||
while (vector) {
|
||||
vector--;
|
||||
free_irq(wx->msix_q_entries[vector].vector,
|
||||
wx->q_vector[vector]);
|
||||
}
|
||||
wx_reset_interrupt_capability(wx);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(wx_request_msix_irqs_vf);
|
||||
|
||||
void wx_negotiate_api_vf(struct wx *wx)
|
||||
{
|
||||
int api[] = {
|
||||
wx_mbox_api_13,
|
||||
wx_mbox_api_null};
|
||||
int err = 0, idx = 0;
|
||||
|
||||
spin_lock_bh(&wx->mbx.mbx_lock);
|
||||
while (api[idx] != wx_mbox_api_null) {
|
||||
err = wx_negotiate_api_version(wx, api[idx]);
|
||||
if (!err)
|
||||
break;
|
||||
idx++;
|
||||
}
|
||||
spin_unlock_bh(&wx->mbx.mbx_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(wx_negotiate_api_vf);
|
||||
|
||||
void wx_reset_vf(struct wx *wx)
|
||||
{
|
||||
struct net_device *netdev = wx->netdev;
|
||||
int ret = 0;
|
||||
|
||||
ret = wx_reset_hw_vf(wx);
|
||||
if (!ret)
|
||||
wx_init_hw_vf(wx);
|
||||
wx_negotiate_api_vf(wx);
|
||||
if (is_valid_ether_addr(wx->mac.addr)) {
|
||||
eth_hw_addr_set(netdev, wx->mac.addr);
|
||||
ether_addr_copy(netdev->perm_addr, wx->mac.addr);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(wx_reset_vf);
|
||||
|
||||
void wx_set_rx_mode_vf(struct net_device *netdev)
|
||||
{
|
||||
struct wx *wx = netdev_priv(netdev);
|
||||
unsigned int flags = netdev->flags;
|
||||
int xcast_mode;
|
||||
|
||||
xcast_mode = (flags & IFF_ALLMULTI) ? WXVF_XCAST_MODE_ALLMULTI :
|
||||
(flags & (IFF_BROADCAST | IFF_MULTICAST)) ?
|
||||
WXVF_XCAST_MODE_MULTI : WXVF_XCAST_MODE_NONE;
|
||||
/* request the most inclusive mode we need */
|
||||
if (flags & IFF_PROMISC)
|
||||
xcast_mode = WXVF_XCAST_MODE_PROMISC;
|
||||
else if (flags & IFF_ALLMULTI)
|
||||
xcast_mode = WXVF_XCAST_MODE_ALLMULTI;
|
||||
else if (flags & (IFF_BROADCAST | IFF_MULTICAST))
|
||||
xcast_mode = WXVF_XCAST_MODE_MULTI;
|
||||
else
|
||||
xcast_mode = WXVF_XCAST_MODE_NONE;
|
||||
|
||||
spin_lock_bh(&wx->mbx.mbx_lock);
|
||||
wx_update_xcast_mode_vf(wx, xcast_mode);
|
||||
wx_update_mc_addr_list_vf(wx, netdev);
|
||||
wx_write_uc_addr_list_vf(netdev);
|
||||
spin_unlock_bh(&wx->mbx.mbx_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(wx_set_rx_mode_vf);
|
||||
|
||||
/**
|
||||
* wx_configure_rx_vf - Configure Receive Unit after Reset
|
||||
* @wx: board private structure
|
||||
*
|
||||
* Configure the Rx unit of the MAC after a reset.
|
||||
**/
|
||||
static void wx_configure_rx_vf(struct wx *wx)
|
||||
{
|
||||
struct net_device *netdev = wx->netdev;
|
||||
int i, ret;
|
||||
|
||||
wx_setup_psrtype_vf(wx);
|
||||
wx_setup_vfmrqc_vf(wx);
|
||||
|
||||
spin_lock_bh(&wx->mbx.mbx_lock);
|
||||
ret = wx_rlpml_set_vf(wx,
|
||||
netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
|
||||
spin_unlock_bh(&wx->mbx.mbx_lock);
|
||||
if (ret)
|
||||
wx_dbg(wx, "Failed to set MTU at %d\n", netdev->mtu);
|
||||
|
||||
/* Setup the HW Rx Head and Tail Descriptor Pointers and
|
||||
* the Base and Length of the Rx Descriptor Ring
|
||||
*/
|
||||
for (i = 0; i < wx->num_rx_queues; i++) {
|
||||
struct wx_ring *rx_ring = wx->rx_ring[i];
|
||||
#ifdef HAVE_SWIOTLB_SKIP_CPU_SYNC
|
||||
wx_set_rx_buffer_len_vf(wx, rx_ring);
|
||||
#endif
|
||||
wx_configure_rx_ring_vf(wx, rx_ring);
|
||||
}
|
||||
}
|
||||
|
||||
void wx_configure_vf(struct wx *wx)
|
||||
{
|
||||
wx_set_rx_mode_vf(wx->netdev);
|
||||
wx_configure_tx_vf(wx);
|
||||
wx_configure_rx_vf(wx);
|
||||
}
|
||||
EXPORT_SYMBOL(wx_configure_vf);
|
||||
|
||||
int wx_set_mac_vf(struct net_device *netdev, void *p)
|
||||
{
|
||||
struct wx *wx = netdev_priv(netdev);
|
||||
struct sockaddr *addr = p;
|
||||
int ret;
|
||||
|
||||
ret = eth_prepare_mac_addr_change(netdev, addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_bh(&wx->mbx.mbx_lock);
|
||||
ret = wx_set_rar_vf(wx, 1, (u8 *)addr->sa_data, 1);
|
||||
spin_unlock_bh(&wx->mbx.mbx_lock);
|
||||
|
||||
if (ret)
|
||||
return -EPERM;
|
||||
|
||||
memcpy(wx->mac.addr, addr->sa_data, netdev->addr_len);
|
||||
memcpy(wx->mac.perm_addr, addr->sa_data, netdev->addr_len);
|
||||
eth_hw_addr_set(netdev, addr->sa_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(wx_set_mac_vf);
|
14
drivers/net/ethernet/wangxun/libwx/wx_vf_common.h
Normal file
14
drivers/net/ethernet/wangxun/libwx/wx_vf_common.h
Normal file
@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
|
||||
|
||||
#ifndef _WX_VF_COMMON_H_
|
||||
#define _WX_VF_COMMON_H_
|
||||
|
||||
int wx_request_msix_irqs_vf(struct wx *wx);
|
||||
void wx_negotiate_api_vf(struct wx *wx);
|
||||
void wx_reset_vf(struct wx *wx);
|
||||
void wx_set_rx_mode_vf(struct net_device *netdev);
|
||||
void wx_configure_vf(struct wx *wx);
|
||||
int wx_set_mac_vf(struct net_device *netdev, void *p);
|
||||
|
||||
#endif /* _WX_VF_COMMON_H_ */
|
280
drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c
Normal file
280
drivers/net/ethernet/wangxun/libwx/wx_vf_lib.c
Normal file
@ -0,0 +1,280 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "wx_type.h"
|
||||
#include "wx_hw.h"
|
||||
#include "wx_lib.h"
|
||||
#include "wx_vf.h"
|
||||
#include "wx_vf_lib.h"
|
||||
|
||||
static void wx_write_eitr_vf(struct wx_q_vector *q_vector)
|
||||
{
|
||||
struct wx *wx = q_vector->wx;
|
||||
int v_idx = q_vector->v_idx;
|
||||
u32 itr_reg;
|
||||
|
||||
itr_reg = q_vector->itr & WX_VXITR_MASK;
|
||||
|
||||
/* set the WDIS bit to not clear the timer bits and cause an
|
||||
* immediate assertion of the interrupt
|
||||
*/
|
||||
itr_reg |= WX_VXITR_CNT_WDIS;
|
||||
|
||||
wr32(wx, WX_VXITR(v_idx), itr_reg);
|
||||
}
|
||||
|
||||
static void wx_set_ivar_vf(struct wx *wx, s8 direction, u8 queue,
|
||||
u8 msix_vector)
|
||||
{
|
||||
u32 ivar, index;
|
||||
|
||||
if (direction == -1) {
|
||||
/* other causes */
|
||||
msix_vector |= WX_PX_IVAR_ALLOC_VAL;
|
||||
ivar = rd32(wx, WX_VXIVAR_MISC);
|
||||
ivar &= ~0xFF;
|
||||
ivar |= msix_vector;
|
||||
wr32(wx, WX_VXIVAR_MISC, ivar);
|
||||
} else {
|
||||
/* tx or rx causes */
|
||||
msix_vector |= WX_PX_IVAR_ALLOC_VAL;
|
||||
index = ((16 * (queue & 1)) + (8 * direction));
|
||||
ivar = rd32(wx, WX_VXIVAR(queue >> 1));
|
||||
ivar &= ~(0xFF << index);
|
||||
ivar |= (msix_vector << index);
|
||||
wr32(wx, WX_VXIVAR(queue >> 1), ivar);
|
||||
}
|
||||
}
|
||||
|
||||
void wx_configure_msix_vf(struct wx *wx)
|
||||
{
|
||||
int v_idx;
|
||||
|
||||
wx->eims_enable_mask = 0;
|
||||
for (v_idx = 0; v_idx < wx->num_q_vectors; v_idx++) {
|
||||
struct wx_q_vector *q_vector = wx->q_vector[v_idx];
|
||||
struct wx_ring *ring;
|
||||
|
||||
wx_for_each_ring(ring, q_vector->rx)
|
||||
wx_set_ivar_vf(wx, 0, ring->reg_idx, v_idx);
|
||||
|
||||
wx_for_each_ring(ring, q_vector->tx)
|
||||
wx_set_ivar_vf(wx, 1, ring->reg_idx, v_idx);
|
||||
|
||||
/* add q_vector eims value to global eims_enable_mask */
|
||||
wx->eims_enable_mask |= BIT(v_idx);
|
||||
wx_write_eitr_vf(q_vector);
|
||||
}
|
||||
|
||||
wx_set_ivar_vf(wx, -1, 1, v_idx);
|
||||
|
||||
/* setup eims_other and add value to global eims_enable_mask */
|
||||
wx->eims_other = BIT(v_idx);
|
||||
wx->eims_enable_mask |= wx->eims_other;
|
||||
}
|
||||
|
||||
int wx_write_uc_addr_list_vf(struct net_device *netdev)
|
||||
{
|
||||
struct wx *wx = netdev_priv(netdev);
|
||||
int count = 0;
|
||||
|
||||
if (!netdev_uc_empty(netdev)) {
|
||||
struct netdev_hw_addr *ha;
|
||||
|
||||
netdev_for_each_uc_addr(ha, netdev)
|
||||
wx_set_uc_addr_vf(wx, ++count, ha->addr);
|
||||
} else {
|
||||
/*
|
||||
* If the list is empty then send message to PF driver to
|
||||
* clear all macvlans on this VF.
|
||||
*/
|
||||
wx_set_uc_addr_vf(wx, 0, NULL);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* wx_configure_tx_ring_vf - Configure Tx ring after Reset
|
||||
* @wx: board private structure
|
||||
* @ring: structure containing ring specific data
|
||||
*
|
||||
* Configure the Tx descriptor ring after a reset.
|
||||
**/
|
||||
static void wx_configure_tx_ring_vf(struct wx *wx, struct wx_ring *ring)
|
||||
{
|
||||
u8 reg_idx = ring->reg_idx;
|
||||
u64 tdba = ring->dma;
|
||||
u32 txdctl = 0;
|
||||
int ret;
|
||||
|
||||
/* disable queue to avoid issues while updating state */
|
||||
wr32(wx, WX_VXTXDCTL(reg_idx), WX_VXTXDCTL_FLUSH);
|
||||
wr32(wx, WX_VXTDBAL(reg_idx), tdba & DMA_BIT_MASK(32));
|
||||
wr32(wx, WX_VXTDBAH(reg_idx), tdba >> 32);
|
||||
|
||||
/* enable relaxed ordering */
|
||||
pcie_capability_clear_and_set_word(wx->pdev, PCI_EXP_DEVCTL,
|
||||
0, PCI_EXP_DEVCTL_RELAX_EN);
|
||||
|
||||
/* reset head and tail pointers */
|
||||
wr32(wx, WX_VXTDH(reg_idx), 0);
|
||||
wr32(wx, WX_VXTDT(reg_idx), 0);
|
||||
ring->tail = wx->hw_addr + WX_VXTDT(reg_idx);
|
||||
|
||||
/* reset ntu and ntc to place SW in sync with hardwdare */
|
||||
ring->next_to_clean = 0;
|
||||
ring->next_to_use = 0;
|
||||
|
||||
txdctl |= WX_VXTXDCTL_BUFLEN(wx_buf_len(ring->count));
|
||||
txdctl |= WX_VXTXDCTL_ENABLE;
|
||||
|
||||
/* reinitialize tx_buffer_info */
|
||||
memset(ring->tx_buffer_info, 0,
|
||||
sizeof(struct wx_tx_buffer) * ring->count);
|
||||
|
||||
wr32(wx, WX_VXTXDCTL(reg_idx), txdctl);
|
||||
/* poll to verify queue is enabled */
|
||||
ret = read_poll_timeout(rd32, txdctl, txdctl & WX_VXTXDCTL_ENABLE,
|
||||
1000, 10000, true, wx, WX_VXTXDCTL(reg_idx));
|
||||
if (ret == -ETIMEDOUT)
|
||||
wx_err(wx, "Could not enable Tx Queue %d\n", reg_idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* wx_configure_tx_vf - Configure Transmit Unit after Reset
|
||||
* @wx: board private structure
|
||||
*
|
||||
* Configure the Tx unit of the MAC after a reset.
|
||||
**/
|
||||
void wx_configure_tx_vf(struct wx *wx)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
/* Setup the HW Tx Head and Tail descriptor pointers */
|
||||
for (i = 0; i < wx->num_tx_queues; i++)
|
||||
wx_configure_tx_ring_vf(wx, wx->tx_ring[i]);
|
||||
}
|
||||
|
||||
static void wx_configure_srrctl_vf(struct wx *wx, struct wx_ring *ring,
|
||||
int index)
|
||||
{
|
||||
u32 srrctl;
|
||||
|
||||
srrctl = rd32m(wx, WX_VXRXDCTL(index),
|
||||
(u32)~(WX_VXRXDCTL_HDRSZ_MASK | WX_VXRXDCTL_BUFSZ_MASK));
|
||||
srrctl |= WX_VXRXDCTL_DROP;
|
||||
srrctl |= WX_VXRXDCTL_HDRSZ(wx_hdr_sz(WX_RX_HDR_SIZE));
|
||||
srrctl |= WX_VXRXDCTL_BUFSZ(wx_buf_sz(WX_RX_BUF_SIZE));
|
||||
|
||||
wr32(wx, WX_VXRXDCTL(index), srrctl);
|
||||
}
|
||||
|
||||
void wx_setup_psrtype_vf(struct wx *wx)
|
||||
{
|
||||
/* PSRTYPE must be initialized */
|
||||
u32 psrtype = WX_VXMRQC_PSR_L2HDR |
|
||||
WX_VXMRQC_PSR_L3HDR |
|
||||
WX_VXMRQC_PSR_L4HDR |
|
||||
WX_VXMRQC_PSR_TUNHDR |
|
||||
WX_VXMRQC_PSR_TUNMAC;
|
||||
|
||||
wr32m(wx, WX_VXMRQC, WX_VXMRQC_PSR_MASK, WX_VXMRQC_PSR(psrtype));
|
||||
}
|
||||
|
||||
void wx_setup_vfmrqc_vf(struct wx *wx)
|
||||
{
|
||||
u16 rss_i = wx->num_rx_queues;
|
||||
u32 vfmrqc = 0, vfreta = 0;
|
||||
u8 i, j;
|
||||
|
||||
/* Fill out hash function seeds */
|
||||
netdev_rss_key_fill(wx->rss_key, sizeof(wx->rss_key));
|
||||
for (i = 0; i < WX_RSS_KEY_SIZE / 4; i++)
|
||||
wr32(wx, WX_VXRSSRK(i), wx->rss_key[i]);
|
||||
|
||||
for (i = 0, j = 0; i < WX_MAX_RETA_ENTRIES; i++, j++) {
|
||||
if (j == rss_i)
|
||||
j = 0;
|
||||
|
||||
wx->rss_indir_tbl[i] = j;
|
||||
|
||||
vfreta |= j << (i & 0x3) * 8;
|
||||
if ((i & 3) == 3) {
|
||||
wr32(wx, WX_VXRETA(i >> 2), vfreta);
|
||||
vfreta = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform hash on these packet types */
|
||||
vfmrqc |= WX_VXMRQC_RSS_ALG_IPV4 |
|
||||
WX_VXMRQC_RSS_ALG_IPV4_TCP |
|
||||
WX_VXMRQC_RSS_ALG_IPV6 |
|
||||
WX_VXMRQC_RSS_ALG_IPV6_TCP;
|
||||
|
||||
vfmrqc |= WX_VXMRQC_RSS_EN;
|
||||
|
||||
if (wx->num_rx_queues > 3)
|
||||
vfmrqc |= WX_VXMRQC_RSS_HASH(2);
|
||||
else if (wx->num_rx_queues > 1)
|
||||
vfmrqc |= WX_VXMRQC_RSS_HASH(1);
|
||||
wr32m(wx, WX_VXMRQC, WX_VXMRQC_RSS_MASK, WX_VXMRQC_RSS(vfmrqc));
|
||||
}
|
||||
|
||||
void wx_configure_rx_ring_vf(struct wx *wx, struct wx_ring *ring)
|
||||
{
|
||||
u8 reg_idx = ring->reg_idx;
|
||||
union wx_rx_desc *rx_desc;
|
||||
u64 rdba = ring->dma;
|
||||
u32 rxdctl;
|
||||
|
||||
/* disable queue to avoid issues while updating state */
|
||||
rxdctl = rd32(wx, WX_VXRXDCTL(reg_idx));
|
||||
wx_disable_rx_queue(wx, ring);
|
||||
|
||||
wr32(wx, WX_VXRDBAL(reg_idx), rdba & DMA_BIT_MASK(32));
|
||||
wr32(wx, WX_VXRDBAH(reg_idx), rdba >> 32);
|
||||
|
||||
/* enable relaxed ordering */
|
||||
pcie_capability_clear_and_set_word(wx->pdev, PCI_EXP_DEVCTL,
|
||||
0, PCI_EXP_DEVCTL_RELAX_EN);
|
||||
|
||||
/* reset head and tail pointers */
|
||||
wr32(wx, WX_VXRDH(reg_idx), 0);
|
||||
wr32(wx, WX_VXRDT(reg_idx), 0);
|
||||
ring->tail = wx->hw_addr + WX_VXRDT(reg_idx);
|
||||
|
||||
/* initialize rx_buffer_info */
|
||||
memset(ring->rx_buffer_info, 0,
|
||||
sizeof(struct wx_rx_buffer) * ring->count);
|
||||
|
||||
/* initialize Rx descriptor 0 */
|
||||
rx_desc = WX_RX_DESC(ring, 0);
|
||||
rx_desc->wb.upper.length = 0;
|
||||
|
||||
/* reset ntu and ntc to place SW in sync with hardwdare */
|
||||
ring->next_to_clean = 0;
|
||||
ring->next_to_use = 0;
|
||||
ring->next_to_alloc = 0;
|
||||
|
||||
wx_configure_srrctl_vf(wx, ring, reg_idx);
|
||||
|
||||
/* allow any size packet since we can handle overflow */
|
||||
rxdctl &= ~WX_VXRXDCTL_BUFLEN_MASK;
|
||||
rxdctl |= WX_VXRXDCTL_BUFLEN(wx_buf_len(ring->count));
|
||||
rxdctl |= WX_VXRXDCTL_ENABLE | WX_VXRXDCTL_VLAN;
|
||||
|
||||
/* enable RSC */
|
||||
rxdctl &= ~WX_VXRXDCTL_RSCMAX_MASK;
|
||||
rxdctl |= WX_VXRXDCTL_RSCMAX(0);
|
||||
rxdctl |= WX_VXRXDCTL_RSCEN;
|
||||
|
||||
wr32(wx, WX_VXRXDCTL(reg_idx), rxdctl);
|
||||
|
||||
/* pf/vf reuse */
|
||||
wx_enable_rx_queue(wx, ring);
|
||||
wx_alloc_rx_buffers(ring, wx_desc_unused(ring));
|
||||
}
|
14
drivers/net/ethernet/wangxun/libwx/wx_vf_lib.h
Normal file
14
drivers/net/ethernet/wangxun/libwx/wx_vf_lib.h
Normal file
@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */
|
||||
|
||||
#ifndef _WX_VF_LIB_H_
|
||||
#define _WX_VF_LIB_H_
|
||||
|
||||
void wx_configure_msix_vf(struct wx *wx);
|
||||
int wx_write_uc_addr_list_vf(struct net_device *netdev);
|
||||
void wx_setup_psrtype_vf(struct wx *wx);
|
||||
void wx_setup_vfmrqc_vf(struct wx *wx);
|
||||
void wx_configure_tx_vf(struct wx *wx);
|
||||
void wx_configure_rx_ring_vf(struct wx *wx, struct wx_ring *ring);
|
||||
|
||||
#endif /* _WX_VF_LIB_H_ */
|
Loading…
Reference in New Issue
Block a user