Commit d21d2c7f authored by Jiawen Wu's avatar Jiawen Wu Committed by David S. Miller
Browse files

net: txgbe: Set MAC address and register netdev



Add MAC address related operations, and register netdev.

Signed-off-by: default avatarJiawen Wu <jiawenwu@trustnetic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b0801256
Loading
Loading
Loading
Loading
+229 −2
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2015 - 2022 Beijing WangXun Technology Co., Ltd. */

#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <linux/iopoll.h>
#include <linux/pci.h>

@@ -71,7 +73,230 @@ int wx_check_flash_load(struct wx_hw *hw, u32 check_bit)
}
EXPORT_SYMBOL(wx_check_flash_load);

static void wx_disable_rx(struct wx_hw *wxhw)
/**
 *  wx_get_mac_addr - Generic get MAC address
 *  @wxhw: pointer to hardware structure
 *  @mac_addr: Adapter MAC address
 *
 *  Reads the adapter's MAC address from first Receive Address Register (RAR0)
 *  A reset of the adapter must be performed prior to calling this function
 *  in order for the MAC address to have been loaded from the EEPROM into RAR0
 **/
void wx_get_mac_addr(struct wx_hw *wxhw, u8 *mac_addr)
{
	u32 rar_high;
	u32 rar_low;
	u16 i;

	wr32(wxhw, WX_PSR_MAC_SWC_IDX, 0);
	rar_high = rd32(wxhw, WX_PSR_MAC_SWC_AD_H);
	rar_low = rd32(wxhw, WX_PSR_MAC_SWC_AD_L);

	for (i = 0; i < 2; i++)
		mac_addr[i] = (u8)(rar_high >> (1 - i) * 8);

	for (i = 0; i < 4; i++)
		mac_addr[i + 2] = (u8)(rar_low >> (3 - i) * 8);
}
EXPORT_SYMBOL(wx_get_mac_addr);

/**
 *  wx_set_rar - Set Rx address register
 *  @wxhw: pointer to hardware structure
 *  @index: Receive address register to write
 *  @addr: Address to put into receive address register
 *  @pools: VMDq "set" or "pool" index
 *  @enable_addr: set flag that address is active
 *
 *  Puts an ethernet address into a receive address register.
 **/
int wx_set_rar(struct wx_hw *wxhw, u32 index, u8 *addr, u64 pools,
	       u32 enable_addr)
{
	u32 rar_entries = wxhw->mac.num_rar_entries;
	u32 rar_low, rar_high;

	/* Make sure we are using a valid rar index range */
	if (index >= rar_entries) {
		wx_err(wxhw, "RAR index %d is out of range.\n", index);
		return -EINVAL;
	}

	/* select the MAC address */
	wr32(wxhw, WX_PSR_MAC_SWC_IDX, index);

	/* setup VMDq pool mapping */
	wr32(wxhw, WX_PSR_MAC_SWC_VM_L, pools & 0xFFFFFFFF);
	if (wxhw->mac.type == wx_mac_sp)
		wr32(wxhw, WX_PSR_MAC_SWC_VM_H, pools >> 32);

	/* HW expects these in little endian so we reverse the byte
	 * order from network order (big endian) to little endian
	 *
	 * Some parts put the VMDq setting in the extra RAH bits,
	 * so save everything except the lower 16 bits that hold part
	 * of the address and the address valid bit.
	 */
	rar_low = ((u32)addr[5] |
		  ((u32)addr[4] << 8) |
		  ((u32)addr[3] << 16) |
		  ((u32)addr[2] << 24));
	rar_high = ((u32)addr[1] |
		   ((u32)addr[0] << 8));
	if (enable_addr != 0)
		rar_high |= WX_PSR_MAC_SWC_AD_H_AV;

	wr32(wxhw, WX_PSR_MAC_SWC_AD_L, rar_low);
	wr32m(wxhw, WX_PSR_MAC_SWC_AD_H,
	      (WX_PSR_MAC_SWC_AD_H_AD(~0) |
	       WX_PSR_MAC_SWC_AD_H_ADTYPE(~0) |
	       WX_PSR_MAC_SWC_AD_H_AV),
	      rar_high);

	return 0;
}
EXPORT_SYMBOL(wx_set_rar);

/**
 *  wx_clear_rar - Remove Rx address register
 *  @wxhw: pointer to hardware structure
 *  @index: Receive address register to write
 *
 *  Clears an ethernet address from a receive address register.
 **/
int wx_clear_rar(struct wx_hw *wxhw, u32 index)
{
	u32 rar_entries = wxhw->mac.num_rar_entries;

	/* Make sure we are using a valid rar index range */
	if (index >= rar_entries) {
		wx_err(wxhw, "RAR index %d is out of range.\n", index);
		return -EINVAL;
	}

	/* Some parts put the VMDq setting in the extra RAH bits,
	 * so save everything except the lower 16 bits that hold part
	 * of the address and the address valid bit.
	 */
	wr32(wxhw, WX_PSR_MAC_SWC_IDX, index);

	wr32(wxhw, WX_PSR_MAC_SWC_VM_L, 0);
	wr32(wxhw, WX_PSR_MAC_SWC_VM_H, 0);

	wr32(wxhw, WX_PSR_MAC_SWC_AD_L, 0);
	wr32m(wxhw, WX_PSR_MAC_SWC_AD_H,
	      (WX_PSR_MAC_SWC_AD_H_AD(~0) |
	       WX_PSR_MAC_SWC_AD_H_ADTYPE(~0) |
	       WX_PSR_MAC_SWC_AD_H_AV),
	      0);

	return 0;
}
EXPORT_SYMBOL(wx_clear_rar);

/**
 *  wx_clear_vmdq - Disassociate a VMDq pool index from a rx address
 *  @wxhw: pointer to hardware struct
 *  @rar: receive address register index to disassociate
 *  @vmdq: VMDq pool index to remove from the rar
 **/
static int wx_clear_vmdq(struct wx_hw *wxhw, u32 rar, u32 __maybe_unused vmdq)
{
	u32 rar_entries = wxhw->mac.num_rar_entries;
	u32 mpsar_lo, mpsar_hi;

	/* Make sure we are using a valid rar index range */
	if (rar >= rar_entries) {
		wx_err(wxhw, "RAR index %d is out of range.\n", rar);
		return -EINVAL;
	}

	wr32(wxhw, WX_PSR_MAC_SWC_IDX, rar);
	mpsar_lo = rd32(wxhw, WX_PSR_MAC_SWC_VM_L);
	mpsar_hi = rd32(wxhw, WX_PSR_MAC_SWC_VM_H);

	if (!mpsar_lo && !mpsar_hi)
		return 0;

	/* was that the last pool using this rar? */
	if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
		wx_clear_rar(wxhw, rar);

	return 0;
}

/**
 *  wx_init_uta_tables - Initialize the Unicast Table Array
 *  @wxhw: pointer to hardware structure
 **/
static void wx_init_uta_tables(struct wx_hw *wxhw)
{
	int i;

	wx_dbg(wxhw, " Clearing UTA\n");

	for (i = 0; i < 128; i++)
		wr32(wxhw, WX_PSR_UC_TBL(i), 0);
}

/**
 *  wx_init_rx_addrs - Initializes receive address filters.
 *  @wxhw: pointer to hardware structure
 *
 *  Places the MAC address in receive address register 0 and clears the rest
 *  of the receive address registers. Clears the multicast table. Assumes
 *  the receiver is in reset when the routine is called.
 **/
void wx_init_rx_addrs(struct wx_hw *wxhw)
{
	u32 rar_entries = wxhw->mac.num_rar_entries;
	u32 psrctl;
	int i;

	/* If the current mac address is valid, assume it is a software override
	 * to the permanent address.
	 * Otherwise, use the permanent address from the eeprom.
	 */
	if (!is_valid_ether_addr(wxhw->mac.addr)) {
		/* Get the MAC address from the RAR0 for later reference */
		wx_get_mac_addr(wxhw, wxhw->mac.addr);
		wx_dbg(wxhw, "Keeping Current RAR0 Addr = %pM\n", wxhw->mac.addr);
	} else {
		/* Setup the receive address. */
		wx_dbg(wxhw, "Overriding MAC Address in RAR[0]\n");
		wx_dbg(wxhw, "New MAC Addr = %pM\n", wxhw->mac.addr);

		wx_set_rar(wxhw, 0, wxhw->mac.addr, 0, WX_PSR_MAC_SWC_AD_H_AV);

		if (wxhw->mac.type == wx_mac_sp) {
			/* clear VMDq pool/queue selection for RAR 0 */
			wx_clear_vmdq(wxhw, 0, WX_CLEAR_VMDQ_ALL);
		}
	}

	/* Zero out the other receive addresses. */
	wx_dbg(wxhw, "Clearing RAR[1-%d]\n", rar_entries - 1);
	for (i = 1; i < rar_entries; i++) {
		wr32(wxhw, WX_PSR_MAC_SWC_IDX, i);
		wr32(wxhw, WX_PSR_MAC_SWC_AD_L, 0);
		wr32(wxhw, WX_PSR_MAC_SWC_AD_H, 0);
	}

	/* Clear the MTA */
	wxhw->addr_ctrl.mta_in_use = 0;
	psrctl = rd32(wxhw, WX_PSR_CTL);
	psrctl &= ~(WX_PSR_CTL_MO | WX_PSR_CTL_MFE);
	psrctl |= wxhw->mac.mc_filter_type << WX_PSR_CTL_MO_SHIFT;
	wr32(wxhw, WX_PSR_CTL, psrctl);
	wx_dbg(wxhw, " Clearing MTA\n");
	for (i = 0; i < wxhw->mac.mcft_size; i++)
		wr32(wxhw, WX_PSR_MC_TBL(i), 0);

	wx_init_uta_tables(wxhw);
}
EXPORT_SYMBOL(wx_init_rx_addrs);

void wx_disable_rx(struct wx_hw *wxhw)
{
	u32 pfdtxgswc;
	u32 rxctrl;
@@ -97,6 +322,7 @@ static void wx_disable_rx(struct wx_hw *wxhw)
		}
	}
}
EXPORT_SYMBOL(wx_disable_rx);

/**
 *  wx_disable_pcie_master - Disable PCI-express master access
@@ -105,7 +331,7 @@ static void wx_disable_rx(struct wx_hw *wxhw)
 *  Disables PCI-Express master access and verifies there are no pending
 *  requests.
 **/
static int wx_disable_pcie_master(struct wx_hw *wxhw)
int wx_disable_pcie_master(struct wx_hw *wxhw)
{
	int status = 0;
	u32 val;
@@ -125,6 +351,7 @@ static int wx_disable_pcie_master(struct wx_hw *wxhw)

	return status;
}
EXPORT_SYMBOL(wx_disable_pcie_master);

/**
 *  wx_stop_adapter - Generic stop Tx/Rx units
+6 −0
Original line number Diff line number Diff line
@@ -5,6 +5,12 @@
#define _WX_HW_H_

int wx_check_flash_load(struct wx_hw *hw, u32 check_bit);
void wx_get_mac_addr(struct wx_hw *wxhw, u8 *mac_addr);
int wx_set_rar(struct wx_hw *wxhw, u32 index, u8 *addr, u64 pools, u32 enable_addr);
int wx_clear_rar(struct wx_hw *wxhw, u32 index);
void wx_init_rx_addrs(struct wx_hw *wxhw);
void wx_disable_rx(struct wx_hw *wxhw);
int wx_disable_pcie_master(struct wx_hw *wxhw);
int wx_stop_adapter(struct wx_hw *wxhw);
void wx_reset_misc(struct wx_hw *wxhw);
int wx_sw_init(struct wx_hw *wxhw);
+37 −0
Original line number Diff line number Diff line
@@ -51,6 +51,12 @@
#define WX_TS_ALARM_ST_DALARM        BIT(1)
#define WX_TS_ALARM_ST_ALARM         BIT(0)

/*********************** Transmit DMA registers **************************/
/* transmit global control */
#define WX_TDM_CTL                   0x18000
/* TDM CTL BIT */
#define WX_TDM_CTL_TE                BIT(0) /* Transmit Enable */

/***************************** RDB registers *********************************/
/* receive packet buffer */
#define WX_RDB_PB_CTL                0x19000
@@ -76,6 +82,9 @@
#define WX_PSR_CTL_MO_SHIFT          5
#define WX_PSR_CTL_MO                (0x3 << WX_PSR_CTL_MO_SHIFT)
#define WX_PSR_CTL_TPE               BIT(4)
/* mcasst/ucast overflow tbl */
#define WX_PSR_MC_TBL(_i)            (0x15200  + ((_i) * 4))
#define WX_PSR_UC_TBL(_i)            (0x15400 + ((_i) * 4))

/* Management */
#define WX_PSR_MNG_FLEX_SEL          0x1582C
@@ -87,7 +96,20 @@
#define WX_PSR_LAN_FLEX_DW_H(_i)     (0x15C04 + ((_i) * 16))
#define WX_PSR_LAN_FLEX_MSK(_i)      (0x15C08 + ((_i) * 16))

/* mac switcher */
#define WX_PSR_MAC_SWC_AD_L          0x16200
#define WX_PSR_MAC_SWC_AD_H          0x16204
#define WX_PSR_MAC_SWC_AD_H_AD(v)       (((v) & 0xFFFF))
#define WX_PSR_MAC_SWC_AD_H_ADTYPE(v)   (((v) & 0x1) << 30)
#define WX_PSR_MAC_SWC_AD_H_AV       BIT(31)
#define WX_PSR_MAC_SWC_VM_L          0x16208
#define WX_PSR_MAC_SWC_VM_H          0x1620C
#define WX_PSR_MAC_SWC_IDX           0x16210
#define WX_CLEAR_VMDQ_ALL            0xFFFFFFFFU

/************************************* ETH MAC *****************************/
#define WX_MAC_TX_CFG                0x11000
#define WX_MAC_TX_CFG_TE             BIT(0)
#define WX_MAC_RX_CFG                0x11004
#define WX_MAC_RX_CFG_RE             BIT(0)
#define WX_MAC_RX_CFG_JE             BIT(8)
@@ -143,16 +165,28 @@ enum wx_mac_type {
struct wx_mac_info {
	enum wx_mac_type type;
	bool set_lben;
	u8 addr[ETH_ALEN];
	u8 perm_addr[ETH_ALEN];
	s32 mc_filter_type;
	u32 mcft_size;
	u32 num_rar_entries;
	u32 max_tx_queues;
	u32 max_rx_queues;
	struct wx_thermal_sensor_data sensor;
};

struct wx_addr_filter_info {
	u32 num_mc_addrs;
	u32 mta_in_use;
	bool user_set_promisc;
};

struct wx_hw {
	u8 __iomem *hw_addr;
	struct pci_dev *pdev;
	struct wx_bus_info bus;
	struct wx_mac_info mac;
	struct wx_addr_filter_info addr_ctrl;
	u16 device_id;
	u16 vendor_id;
	u16 subsystem_device_id;
@@ -197,4 +231,7 @@ wr32m(struct wx_hw *wxhw, u32 reg, u32 mask, u32 field)
#define wx_err(wxhw, fmt, arg...) \
	dev_err(&(wxhw)->pdev->dev, fmt, ##arg)

#define wx_dbg(wxhw, fmt, arg...) \
	dev_dbg(&(wxhw)->pdev->dev, fmt, ##arg)

#endif /* _WX_TYPE_H_ */
+13 −0
Original line number Diff line number Diff line
@@ -11,6 +11,18 @@

#define TXGBE_SP_MAX_TX_QUEUES  128
#define TXGBE_SP_MAX_RX_QUEUES  128
#define TXGBE_SP_RAR_ENTRIES    128
#define TXGBE_SP_MC_TBL_SIZE    128

struct txgbe_mac_addr {
	u8 addr[ETH_ALEN];
	u16 state; /* bitmask */
	u64 pools;
};

#define TXGBE_MAC_STATE_DEFAULT         0x1
#define TXGBE_MAC_STATE_MODIFIED        0x2
#define TXGBE_MAC_STATE_IN_USE          0x4

/* board specific private data structure */
struct txgbe_adapter {
@@ -22,6 +34,7 @@ struct txgbe_adapter {
	/* structs defined in txgbe_type.h */
	struct txgbe_hw hw;
	u16 msg_enable;
	struct txgbe_mac_addr *mac_table;
};

extern char txgbe_driver_name[];
+13 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2015 - 2022 Beijing WangXun Technology Co., Ltd. */

#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <linux/string.h>
#include <linux/iopoll.h>
#include <linux/types.h>
@@ -80,6 +82,17 @@ int txgbe_reset_hw(struct txgbe_hw *hw)
		return status;

	txgbe_reset_misc(hw);

	/* Store the permanent mac address */
	wx_get_mac_addr(wxhw, wxhw->mac.perm_addr);

	/* Store MAC address from RAR0, clear receive address registers, and
	 * clear the multicast table.  Also reset num_rar_entries to 128,
	 * since we modify this value when programming the SAN MAC address.
	 */
	wxhw->mac.num_rar_entries = TXGBE_SP_RAR_ENTRIES;
	wx_init_rx_addrs(wxhw);

	pci_set_master(wxhw->pdev);

	return 0;
Loading