Merge faeb8e7a0a
("Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue") into android-mainline
Steps on the way to 5.16-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I9bb6e17af10deffeeada1f731a8c5f19e60c31ac
This commit is contained in:
commit
fad5093d2a
@ -41,6 +41,11 @@ In the message structure descriptions below, if an attribute name is suffixed
|
||||
with "+", parent nest can contain multiple attributes of the same type. This
|
||||
implements an array of entries.
|
||||
|
||||
Attributes that need to be filled-in by device drivers and that are dumped to
|
||||
user space based on whether they are valid or not should not use zero as a
|
||||
valid value. This avoids the need to explicitly signal the validity of the
|
||||
attribute in the device driver API.
|
||||
|
||||
|
||||
Request header
|
||||
==============
|
||||
@ -179,7 +184,7 @@ according to message purpose:
|
||||
|
||||
Userspace to kernel:
|
||||
|
||||
===================================== ================================
|
||||
===================================== =================================
|
||||
``ETHTOOL_MSG_STRSET_GET`` get string set
|
||||
``ETHTOOL_MSG_LINKINFO_GET`` get link settings
|
||||
``ETHTOOL_MSG_LINKINFO_SET`` set link settings
|
||||
@ -213,7 +218,9 @@ Userspace to kernel:
|
||||
``ETHTOOL_MSG_MODULE_EEPROM_GET`` read SFP module EEPROM
|
||||
``ETHTOOL_MSG_STATS_GET`` get standard statistics
|
||||
``ETHTOOL_MSG_PHC_VCLOCKS_GET`` get PHC virtual clocks info
|
||||
===================================== ================================
|
||||
``ETHTOOL_MSG_MODULE_SET`` set transceiver module parameters
|
||||
``ETHTOOL_MSG_MODULE_GET`` get transceiver module parameters
|
||||
===================================== =================================
|
||||
|
||||
Kernel to userspace:
|
||||
|
||||
@ -252,6 +259,7 @@ Kernel to userspace:
|
||||
``ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY`` read SFP module EEPROM
|
||||
``ETHTOOL_MSG_STATS_GET_REPLY`` standard statistics
|
||||
``ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY`` PHC virtual clocks info
|
||||
``ETHTOOL_MSG_MODULE_GET_REPLY`` transceiver module parameters
|
||||
======================================== =================================
|
||||
|
||||
``GET`` requests are sent by userspace applications to retrieve device
|
||||
@ -520,6 +528,8 @@ Link extended states:
|
||||
power required from cable or module
|
||||
|
||||
``ETHTOOL_LINK_EXT_STATE_OVERHEAT`` The module is overheated
|
||||
|
||||
``ETHTOOL_LINK_EXT_STATE_MODULE`` Transceiver module issue
|
||||
================================================ ============================================
|
||||
|
||||
Link extended substates:
|
||||
@ -613,6 +623,14 @@ Link extended substates:
|
||||
``ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE`` Cable test failure
|
||||
=================================================== ============================================
|
||||
|
||||
Transceiver module issue substates:
|
||||
|
||||
=================================================== ============================================
|
||||
``ETHTOOL_LINK_EXT_SUBSTATE_MODULE_CMIS_NOT_READY`` The CMIS Module State Machine did not reach
|
||||
the ModuleReady state. For example, if the
|
||||
module is stuck at ModuleFault state
|
||||
=================================================== ============================================
|
||||
|
||||
DEBUG_GET
|
||||
=========
|
||||
|
||||
@ -1521,6 +1539,63 @@ Kernel response contents:
|
||||
``ETHTOOL_A_PHC_VCLOCKS_INDEX`` s32 PHC index array
|
||||
==================================== ====== ==========================
|
||||
|
||||
MODULE_GET
|
||||
==========
|
||||
|
||||
Gets transceiver module parameters.
|
||||
|
||||
Request contents:
|
||||
|
||||
===================================== ====== ==========================
|
||||
``ETHTOOL_A_MODULE_HEADER`` nested request header
|
||||
===================================== ====== ==========================
|
||||
|
||||
Kernel response contents:
|
||||
|
||||
====================================== ====== ==========================
|
||||
``ETHTOOL_A_MODULE_HEADER`` nested reply header
|
||||
``ETHTOOL_A_MODULE_POWER_MODE_POLICY`` u8 power mode policy
|
||||
``ETHTOOL_A_MODULE_POWER_MODE`` u8 operational power mode
|
||||
====================================== ====== ==========================
|
||||
|
||||
The optional ``ETHTOOL_A_MODULE_POWER_MODE_POLICY`` attribute encodes the
|
||||
transceiver module power mode policy enforced by the host. The default policy
|
||||
is driver-dependent, but "auto" is the recommended default and it should be
|
||||
implemented by new drivers and drivers where conformance to a legacy behavior
|
||||
is not critical.
|
||||
|
||||
The optional ``ETHTHOOL_A_MODULE_POWER_MODE`` attribute encodes the operational
|
||||
power mode policy of the transceiver module. It is only reported when a module
|
||||
is plugged-in. Possible values are:
|
||||
|
||||
.. kernel-doc:: include/uapi/linux/ethtool.h
|
||||
:identifiers: ethtool_module_power_mode
|
||||
|
||||
MODULE_SET
|
||||
==========
|
||||
|
||||
Sets transceiver module parameters.
|
||||
|
||||
Request contents:
|
||||
|
||||
====================================== ====== ==========================
|
||||
``ETHTOOL_A_MODULE_HEADER`` nested request header
|
||||
``ETHTOOL_A_MODULE_POWER_MODE_POLICY`` u8 power mode policy
|
||||
====================================== ====== ==========================
|
||||
|
||||
When set, the optional ``ETHTOOL_A_MODULE_POWER_MODE_POLICY`` attribute is used
|
||||
to set the transceiver module power policy enforced by the host. Possible
|
||||
values are:
|
||||
|
||||
.. kernel-doc:: include/uapi/linux/ethtool.h
|
||||
:identifiers: ethtool_module_power_mode_policy
|
||||
|
||||
For SFF-8636 modules, low power mode is forced by the host according to table
|
||||
6-10 in revision 2.10a of the specification.
|
||||
|
||||
For CMIS modules, low power mode is forced by the host according to table 6-12
|
||||
in revision 5.0 of the specification.
|
||||
|
||||
Request translation
|
||||
===================
|
||||
|
||||
@ -1620,4 +1695,6 @@ are netlink only.
|
||||
n/a ``ETHTOOL_MSG_CABLE_TEST_TDR_ACT``
|
||||
n/a ``ETHTOOL_MSG_TUNNEL_INFO_GET``
|
||||
n/a ``ETHTOOL_MSG_PHC_VCLOCKS_GET``
|
||||
n/a ``ETHTOOL_MSG_MODULE_GET``
|
||||
n/a ``ETHTOOL_MSG_MODULE_SET``
|
||||
=================================== =====================================
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
struct fwnode_handle *dev_fwnode(struct device *dev)
|
||||
@ -935,68 +934,6 @@ int device_get_phy_mode(struct device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_get_phy_mode);
|
||||
|
||||
static void *fwnode_get_mac_addr(struct fwnode_handle *fwnode,
|
||||
const char *name, char *addr,
|
||||
int alen)
|
||||
{
|
||||
int ret = fwnode_property_read_u8_array(fwnode, name, addr, alen);
|
||||
|
||||
if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
|
||||
return addr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* fwnode_get_mac_address - Get the MAC from the firmware node
|
||||
* @fwnode: Pointer to the firmware node
|
||||
* @addr: Address of buffer to store the MAC in
|
||||
* @alen: Length of the buffer pointed to by addr, should be ETH_ALEN
|
||||
*
|
||||
* Search the firmware node for the best MAC address to use. 'mac-address' is
|
||||
* checked first, because that is supposed to contain to "most recent" MAC
|
||||
* address. If that isn't set, then 'local-mac-address' is checked next,
|
||||
* because that is the default address. If that isn't set, then the obsolete
|
||||
* 'address' is checked, just in case we're using an old device tree.
|
||||
*
|
||||
* Note that the 'address' property is supposed to contain a virtual address of
|
||||
* the register set, but some DTS files have redefined that property to be the
|
||||
* MAC address.
|
||||
*
|
||||
* All-zero MAC addresses are rejected, because those could be properties that
|
||||
* exist in the firmware tables, but were not updated by the firmware. For
|
||||
* example, the DTS could define 'mac-address' and 'local-mac-address', with
|
||||
* zero MAC addresses. Some older U-Boots only initialized 'local-mac-address'.
|
||||
* In this case, the real MAC is in 'local-mac-address', and 'mac-address'
|
||||
* exists but is all zeros.
|
||||
*/
|
||||
void *fwnode_get_mac_address(struct fwnode_handle *fwnode, char *addr, int alen)
|
||||
{
|
||||
char *res;
|
||||
|
||||
res = fwnode_get_mac_addr(fwnode, "mac-address", addr, alen);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
res = fwnode_get_mac_addr(fwnode, "local-mac-address", addr, alen);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
return fwnode_get_mac_addr(fwnode, "address", addr, alen);
|
||||
}
|
||||
EXPORT_SYMBOL(fwnode_get_mac_address);
|
||||
|
||||
/**
|
||||
* device_get_mac_address - Get the MAC for a given device
|
||||
* @dev: Pointer to the device
|
||||
* @addr: Address of buffer to store the MAC in
|
||||
* @alen: Length of the buffer pointed to by addr, should be ETH_ALEN
|
||||
*/
|
||||
void *device_get_mac_address(struct device *dev, char *addr, int alen)
|
||||
{
|
||||
return fwnode_get_mac_address(dev_fwnode(dev), addr, alen);
|
||||
}
|
||||
EXPORT_SYMBOL(device_get_mac_address);
|
||||
|
||||
/**
|
||||
* fwnode_irq_get - Get IRQ directly from a fwnode
|
||||
* @fwnode: Pointer to the firmware node
|
||||
|
@ -20,7 +20,7 @@ MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* contains the number the next bus should get. */
|
||||
static unsigned int bcma_bus_next_num = 0;
|
||||
static unsigned int bcma_bus_next_num;
|
||||
|
||||
/* bcma_buses_mutex locks the bcma_bus_next_num */
|
||||
static DEFINE_MUTEX(bcma_buses_mutex);
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/if_bridge.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
@ -42,9 +43,12 @@
|
||||
/* Port Enable Control register */
|
||||
#define RTL8366RB_PECR 0x0001
|
||||
|
||||
/* Switch Security Control registers */
|
||||
#define RTL8366RB_SSCR0 0x0002
|
||||
#define RTL8366RB_SSCR1 0x0003
|
||||
/* Switch per-port learning disablement register */
|
||||
#define RTL8366RB_PORT_LEARNDIS_CTRL 0x0002
|
||||
|
||||
/* Security control, actually aging register */
|
||||
#define RTL8366RB_SECURITY_CTRL 0x0003
|
||||
|
||||
#define RTL8366RB_SSCR2 0x0004
|
||||
#define RTL8366RB_SSCR2_DROP_UNKNOWN_DA BIT(0)
|
||||
|
||||
@ -106,6 +110,18 @@
|
||||
|
||||
#define RTL8366RB_POWER_SAVING_REG 0x0021
|
||||
|
||||
/* Spanning tree status (STP) control, two bits per port per FID */
|
||||
#define RTL8366RB_STP_STATE_BASE 0x0050 /* 0x0050..0x0057 */
|
||||
#define RTL8366RB_STP_STATE_DISABLED 0x0
|
||||
#define RTL8366RB_STP_STATE_BLOCKING 0x1
|
||||
#define RTL8366RB_STP_STATE_LEARNING 0x2
|
||||
#define RTL8366RB_STP_STATE_FORWARDING 0x3
|
||||
#define RTL8366RB_STP_MASK GENMASK(1, 0)
|
||||
#define RTL8366RB_STP_STATE(port, state) \
|
||||
((state) << ((port) * 2))
|
||||
#define RTL8366RB_STP_STATE_MASK(port) \
|
||||
RTL8366RB_STP_STATE((port), RTL8366RB_STP_MASK)
|
||||
|
||||
/* CPU port control reg */
|
||||
#define RTL8368RB_CPU_CTRL_REG 0x0061
|
||||
#define RTL8368RB_CPU_PORTS_MSK 0x00FF
|
||||
@ -230,6 +246,7 @@
|
||||
#define RTL8366RB_NUM_LEDGROUPS 4
|
||||
#define RTL8366RB_NUM_VIDS 4096
|
||||
#define RTL8366RB_PRIORITYMAX 7
|
||||
#define RTL8366RB_NUM_FIDS 8
|
||||
#define RTL8366RB_FIDMAX 7
|
||||
|
||||
#define RTL8366RB_PORT_1 BIT(0) /* In userspace port 0 */
|
||||
@ -927,13 +944,14 @@ static int rtl8366rb_setup(struct dsa_switch *ds)
|
||||
/* layer 2 size, see rtl8366rb_change_mtu() */
|
||||
rb->max_mtu[i] = 1532;
|
||||
|
||||
/* Enable learning for all ports */
|
||||
ret = regmap_write(smi->map, RTL8366RB_SSCR0, 0);
|
||||
/* Disable learning for all ports */
|
||||
ret = regmap_write(smi->map, RTL8366RB_PORT_LEARNDIS_CTRL,
|
||||
RTL8366RB_PORT_ALL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable auto ageing for all ports */
|
||||
ret = regmap_write(smi->map, RTL8366RB_SSCR1, 0);
|
||||
ret = regmap_write(smi->map, RTL8366RB_SECURITY_CTRL, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1272,6 +1290,84 @@ static int rtl8366rb_vlan_filtering(struct dsa_switch *ds, int port,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
rtl8366rb_port_pre_bridge_flags(struct dsa_switch *ds, int port,
|
||||
struct switchdev_brport_flags flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
/* We support enabling/disabling learning */
|
||||
if (flags.mask & ~(BR_LEARNING))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rtl8366rb_port_bridge_flags(struct dsa_switch *ds, int port,
|
||||
struct switchdev_brport_flags flags,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct realtek_smi *smi = ds->priv;
|
||||
int ret;
|
||||
|
||||
if (flags.mask & BR_LEARNING) {
|
||||
ret = regmap_update_bits(smi->map, RTL8366RB_PORT_LEARNDIS_CTRL,
|
||||
BIT(port),
|
||||
(flags.val & BR_LEARNING) ? 0 : BIT(port));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8366rb_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
|
||||
{
|
||||
struct realtek_smi *smi = ds->priv;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
switch (state) {
|
||||
case BR_STATE_DISABLED:
|
||||
val = RTL8366RB_STP_STATE_DISABLED;
|
||||
break;
|
||||
case BR_STATE_BLOCKING:
|
||||
case BR_STATE_LISTENING:
|
||||
val = RTL8366RB_STP_STATE_BLOCKING;
|
||||
break;
|
||||
case BR_STATE_LEARNING:
|
||||
val = RTL8366RB_STP_STATE_LEARNING;
|
||||
break;
|
||||
case BR_STATE_FORWARDING:
|
||||
val = RTL8366RB_STP_STATE_FORWARDING;
|
||||
break;
|
||||
default:
|
||||
dev_err(smi->dev, "unknown bridge state requested\n");
|
||||
return;
|
||||
};
|
||||
|
||||
/* Set the same status for the port on all the FIDs */
|
||||
for (i = 0; i < RTL8366RB_NUM_FIDS; i++) {
|
||||
regmap_update_bits(smi->map, RTL8366RB_STP_STATE_BASE + i,
|
||||
RTL8366RB_STP_STATE_MASK(port),
|
||||
RTL8366RB_STP_STATE(port, val));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rtl8366rb_port_fast_age(struct dsa_switch *ds, int port)
|
||||
{
|
||||
struct realtek_smi *smi = ds->priv;
|
||||
|
||||
/* This will age out any learned L2 entries */
|
||||
regmap_update_bits(smi->map, RTL8366RB_SECURITY_CTRL,
|
||||
BIT(port), BIT(port));
|
||||
/* Restore the normal state of things */
|
||||
regmap_update_bits(smi->map, RTL8366RB_SECURITY_CTRL,
|
||||
BIT(port), 0);
|
||||
}
|
||||
|
||||
static int rtl8366rb_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
|
||||
{
|
||||
struct realtek_smi *smi = ds->priv;
|
||||
@ -1682,6 +1778,10 @@ static const struct dsa_switch_ops rtl8366rb_switch_ops = {
|
||||
.port_vlan_del = rtl8366_vlan_del,
|
||||
.port_enable = rtl8366rb_port_enable,
|
||||
.port_disable = rtl8366rb_port_disable,
|
||||
.port_pre_bridge_flags = rtl8366rb_port_pre_bridge_flags,
|
||||
.port_bridge_flags = rtl8366rb_port_bridge_flags,
|
||||
.port_stp_state_set = rtl8366rb_port_stp_state_set,
|
||||
.port_fast_age = rtl8366rb_port_fast_age,
|
||||
.port_change_mtu = rtl8366rb_change_mtu,
|
||||
.port_max_mtu = rtl8366rb_max_mtu,
|
||||
};
|
||||
|
@ -852,7 +852,7 @@ static int emac_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Read MAC-address from DT */
|
||||
ret = of_get_mac_address(np, ndev->dev_addr);
|
||||
ret = of_get_ethdev_address(np, ndev);
|
||||
if (ret) {
|
||||
/* if the MAC address is invalid get a random one */
|
||||
eth_hw_addr_random(ndev);
|
||||
|
@ -1524,7 +1524,7 @@ static int altera_tse_probe(struct platform_device *pdev)
|
||||
priv->rx_dma_buf_sz = ALTERA_RXDMABUFFER_SIZE;
|
||||
|
||||
/* get default MAC address from device tree */
|
||||
ret = of_get_mac_address(pdev->dev.of_node, ndev->dev_addr);
|
||||
ret = of_get_ethdev_address(pdev->dev.of_node, ndev);
|
||||
if (ret)
|
||||
eth_hw_addr_random(ndev);
|
||||
|
||||
|
@ -168,7 +168,7 @@ config SUNLANCE
|
||||
|
||||
config AMD_XGBE
|
||||
tristate "AMD 10GbE Ethernet driver"
|
||||
depends on ((OF_NET && OF_ADDRESS) || ACPI || PCI) && HAS_IOMEM
|
||||
depends on (OF_ADDRESS || ACPI || PCI) && HAS_IOMEM
|
||||
depends on X86 || ARM64 || COMPILE_TEST
|
||||
depends on PTP_1588_CLOCK_OPTIONAL
|
||||
select BITREVERSE
|
||||
|
@ -36,7 +36,7 @@ static int xge_get_resources(struct xge_pdata *pdata)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!device_get_mac_address(dev, ndev->dev_addr, ETH_ALEN))
|
||||
if (device_get_ethdev_address(dev, ndev))
|
||||
eth_hw_addr_random(ndev);
|
||||
|
||||
memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
|
||||
|
@ -1731,7 +1731,7 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata)
|
||||
xgene_get_port_id_acpi(dev, pdata);
|
||||
#endif
|
||||
|
||||
if (!device_get_mac_address(dev, ndev->dev_addr, ETH_ALEN))
|
||||
if (device_get_ethdev_address(dev, ndev))
|
||||
eth_hw_addr_random(ndev);
|
||||
|
||||
memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
|
||||
|
@ -26,7 +26,7 @@ config ARC_EMAC_CORE
|
||||
config ARC_EMAC
|
||||
tristate "ARC EMAC support"
|
||||
select ARC_EMAC_CORE
|
||||
depends on OF_IRQ && OF_NET
|
||||
depends on OF_IRQ
|
||||
depends on ARC || COMPILE_TEST
|
||||
help
|
||||
On some legacy ARC (Synopsys) FPGA boards such as ARCAngel4/ML50x
|
||||
@ -36,7 +36,7 @@ config ARC_EMAC
|
||||
config EMAC_ROCKCHIP
|
||||
tristate "Rockchip EMAC support"
|
||||
select ARC_EMAC_CORE
|
||||
depends on OF_IRQ && OF_NET && REGULATOR
|
||||
depends on OF_IRQ && REGULATOR
|
||||
depends on ARCH_ROCKCHIP || COMPILE_TEST
|
||||
help
|
||||
Support for Rockchip RK3036/RK3066/RK3188 EMAC ethernet controllers.
|
||||
|
@ -941,7 +941,7 @@ int arc_emac_probe(struct net_device *ndev, int interface)
|
||||
}
|
||||
|
||||
/* Get MAC address from device tree */
|
||||
err = of_get_mac_address(dev->of_node, ndev->dev_addr);
|
||||
err = of_get_ethdev_address(dev->of_node, ndev);
|
||||
if (err)
|
||||
eth_hw_addr_random(ndev);
|
||||
|
||||
|
@ -1968,7 +1968,7 @@ static int ag71xx_probe(struct platform_device *pdev)
|
||||
ag->stop_desc->ctrl = 0;
|
||||
ag->stop_desc->next = (u32)ag->stop_desc_dma;
|
||||
|
||||
err = of_get_mac_address(np, ndev->dev_addr);
|
||||
err = of_get_ethdev_address(np, ndev);
|
||||
if (err) {
|
||||
netif_err(ag, probe, ndev, "invalid MAC address, using random address\n");
|
||||
eth_random_addr(ndev->dev_addr);
|
||||
|
@ -170,7 +170,7 @@ static int bcm4908_dma_alloc_buf_descs(struct bcm4908_enet *enet,
|
||||
goto err_free_buf_descs;
|
||||
}
|
||||
|
||||
ring->slots = kzalloc(ring->length * sizeof(*ring->slots), GFP_KERNEL);
|
||||
ring->slots = kcalloc(ring->length, sizeof(*ring->slots), GFP_KERNEL);
|
||||
if (!ring->slots)
|
||||
goto err_free_buf_descs;
|
||||
|
||||
@ -715,7 +715,7 @@ static int bcm4908_enet_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
|
||||
SET_NETDEV_DEV(netdev, &pdev->dev);
|
||||
err = of_get_mac_address(dev->of_node, netdev->dev_addr);
|
||||
err = of_get_ethdev_address(dev->of_node, netdev);
|
||||
if (err)
|
||||
eth_hw_addr_random(netdev);
|
||||
netdev->netdev_ops = &bcm4908_enet_netdev_ops;
|
||||
|
@ -2555,7 +2555,7 @@ static int bcm_sysport_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Initialize netdevice members */
|
||||
ret = of_get_mac_address(dn, dev->dev_addr);
|
||||
ret = of_get_ethdev_address(dn, dev);
|
||||
if (ret) {
|
||||
dev_warn(&pdev->dev, "using random Ethernet MAC\n");
|
||||
eth_hw_addr_random(dev);
|
||||
|
@ -140,7 +140,7 @@ static int bgmac_probe(struct bcma_device *core)
|
||||
|
||||
bcma_set_drvdata(core, bgmac);
|
||||
|
||||
err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr);
|
||||
err = of_get_ethdev_address(bgmac->dev->of_node, bgmac->net_dev);
|
||||
if (err == -EPROBE_DEFER)
|
||||
return err;
|
||||
|
||||
|
@ -191,7 +191,7 @@ static int bgmac_probe(struct platform_device *pdev)
|
||||
bgmac->dev = &pdev->dev;
|
||||
bgmac->dma_dev = &pdev->dev;
|
||||
|
||||
ret = of_get_mac_address(np, bgmac->net_dev->dev_addr);
|
||||
ret = of_get_ethdev_address(np, bgmac->net_dev);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
|
||||
|
@ -4084,7 +4084,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
||||
if (pd && !IS_ERR_OR_NULL(pd->mac_address))
|
||||
eth_hw_addr_set(dev, pd->mac_address);
|
||||
else
|
||||
if (!device_get_mac_address(&pdev->dev, dev->dev_addr, ETH_ALEN))
|
||||
if (device_get_ethdev_address(&pdev->dev, dev))
|
||||
if (has_acpi_companion(&pdev->dev))
|
||||
bcmgenet_get_hw_addr(priv, dev->dev_addr);
|
||||
|
||||
|
@ -11213,12 +11213,8 @@ static void tg3_reset_task(struct work_struct *work)
|
||||
}
|
||||
|
||||
tg3_netif_start(tp);
|
||||
|
||||
tg3_full_unlock(tp);
|
||||
|
||||
if (!err)
|
||||
tg3_phy_start(tp);
|
||||
|
||||
tg3_phy_start(tp);
|
||||
tg3_flag_clear(tp, RESET_TASK_PENDING);
|
||||
out:
|
||||
rtnl_unlock();
|
||||
|
@ -4774,7 +4774,7 @@ static int macb_probe(struct platform_device *pdev)
|
||||
if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR)
|
||||
bp->rx_intr_mask |= MACB_BIT(RXUBR);
|
||||
|
||||
err = of_get_mac_address(np, bp->dev->dev_addr);
|
||||
err = of_get_ethdev_address(np, bp->dev);
|
||||
if (err == -EPROBE_DEFER)
|
||||
goto err_out_free_netdev;
|
||||
else if (err)
|
||||
|
@ -1501,7 +1501,7 @@ static int octeon_mgmt_probe(struct platform_device *pdev)
|
||||
netdev->min_mtu = 64 - OCTEON_MGMT_RX_HEADROOM;
|
||||
netdev->max_mtu = 16383 - OCTEON_MGMT_RX_HEADROOM - VLAN_HLEN;
|
||||
|
||||
result = of_get_mac_address(pdev->dev.of_node, netdev->dev_addr);
|
||||
result = of_get_ethdev_address(pdev->dev.of_node, netdev);
|
||||
if (result)
|
||||
eth_hw_addr_random(netdev);
|
||||
|
||||
|
@ -1387,10 +1387,10 @@ static int acpi_get_mac_address(struct device *dev, struct acpi_device *adev,
|
||||
u8 *dst)
|
||||
{
|
||||
u8 mac[ETH_ALEN];
|
||||
u8 *addr;
|
||||
int ret;
|
||||
|
||||
addr = fwnode_get_mac_address(acpi_fwnode_handle(adev), mac, ETH_ALEN);
|
||||
if (!addr) {
|
||||
ret = fwnode_get_mac_address(acpi_fwnode_handle(adev), mac);
|
||||
if (ret) {
|
||||
dev_err(dev, "MAC address invalid: %pM\n", mac);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1147,7 +1147,7 @@ static int ethoc_probe(struct platform_device *pdev)
|
||||
eth_hw_addr_set(netdev, pdata->hwaddr);
|
||||
priv->phy_id = pdata->phy_id;
|
||||
} else {
|
||||
of_get_mac_address(pdev->dev.of_node, netdev->dev_addr);
|
||||
of_get_ethdev_address(pdev->dev.of_node, netdev);
|
||||
priv->phy_id = -1;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ if NET_VENDOR_EZCHIP
|
||||
|
||||
config EZCHIP_NPS_MANAGEMENT_ENET
|
||||
tristate "EZchip NPS management enet support"
|
||||
depends on OF_IRQ && OF_NET
|
||||
depends on OF_IRQ
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
Simple LAN device for debug or management purposes.
|
||||
|
@ -601,7 +601,7 @@ static s32 nps_enet_probe(struct platform_device *pdev)
|
||||
dev_dbg(dev, "Registers base address is 0x%p\n", priv->regs_base);
|
||||
|
||||
/* set kernel MAC address to dev */
|
||||
err = of_get_mac_address(dev->of_node, ndev->dev_addr);
|
||||
err = of_get_ethdev_address(dev->of_node, ndev);
|
||||
if (err)
|
||||
eth_hw_addr_random(ndev);
|
||||
|
||||
|
@ -182,13 +182,10 @@ static void ftgmac100_initial_mac(struct ftgmac100 *priv)
|
||||
u8 mac[ETH_ALEN];
|
||||
unsigned int m;
|
||||
unsigned int l;
|
||||
void *addr;
|
||||
|
||||
addr = device_get_mac_address(priv->dev, mac, ETH_ALEN);
|
||||
if (addr) {
|
||||
eth_hw_addr_set(priv->netdev, mac);
|
||||
if (!device_get_ethdev_address(priv->dev, priv->netdev)) {
|
||||
dev_info(priv->dev, "Read MAC address %pM from device tree\n",
|
||||
mac);
|
||||
priv->netdev->dev_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -890,7 +890,7 @@ static int mpc52xx_fec_probe(struct platform_device *op)
|
||||
*
|
||||
* First try to read MAC address from DT
|
||||
*/
|
||||
rv = of_get_mac_address(np, ndev->dev_addr);
|
||||
rv = of_get_ethdev_address(np, ndev);
|
||||
if (rv) {
|
||||
struct mpc52xx_fec __iomem *fec = priv->fec;
|
||||
|
||||
|
@ -1005,7 +1005,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
|
||||
spin_lock_init(&fep->lock);
|
||||
spin_lock_init(&fep->tx_lock);
|
||||
|
||||
of_get_mac_address(ofdev->dev.of_node, ndev->dev_addr);
|
||||
of_get_ethdev_address(ofdev->dev.of_node, ndev);
|
||||
|
||||
ret = fep->ops->allocate_bd(ndev);
|
||||
if (ret)
|
||||
|
@ -753,7 +753,7 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
|
||||
if (stash_len || stash_idx)
|
||||
priv->device_flags |= FSL_GIANFAR_DEV_HAS_BUF_STASHING;
|
||||
|
||||
err = of_get_mac_address(np, dev->dev_addr);
|
||||
err = of_get_ethdev_address(np, dev);
|
||||
if (err) {
|
||||
eth_hw_addr_random(dev);
|
||||
dev_info(&ofdev->dev, "Using random MAC address: %pM\n", dev->dev_addr);
|
||||
|
@ -3731,7 +3731,7 @@ static int ucc_geth_probe(struct platform_device* ofdev)
|
||||
goto err_free_netdev;
|
||||
}
|
||||
|
||||
of_get_mac_address(np, dev->dev_addr);
|
||||
of_get_ethdev_address(np, dev);
|
||||
|
||||
ugeth->ug_info = ug_info;
|
||||
ugeth->dev = device;
|
||||
|
@ -841,7 +841,7 @@ static int hisi_femac_drv_probe(struct platform_device *pdev)
|
||||
(unsigned long)phy->phy_id,
|
||||
phy_modes(phy->interface));
|
||||
|
||||
ret = of_get_mac_address(node, ndev->dev_addr);
|
||||
ret = of_get_ethdev_address(node, ndev);
|
||||
if (ret) {
|
||||
eth_hw_addr_random(ndev);
|
||||
dev_warn(dev, "using random MAC address %pM\n",
|
||||
|
@ -1219,7 +1219,7 @@ static int hix5hd2_dev_probe(struct platform_device *pdev)
|
||||
goto out_phy_node;
|
||||
}
|
||||
|
||||
ret = of_get_mac_address(node, ndev->dev_addr);
|
||||
ret = of_get_ethdev_address(node, ndev);
|
||||
if (ret) {
|
||||
eth_hw_addr_random(ndev);
|
||||
netdev_warn(ndev, "using random MAC address %pM\n",
|
||||
|
@ -1212,7 +1212,7 @@ static void hns_init_mac_addr(struct net_device *ndev)
|
||||
{
|
||||
struct hns_nic_priv *priv = netdev_priv(ndev);
|
||||
|
||||
if (!device_get_mac_address(priv->dev, ndev->dev_addr, ETH_ALEN)) {
|
||||
if (device_get_ethdev_address(priv->dev, ndev)) {
|
||||
eth_hw_addr_random(ndev);
|
||||
dev_warn(priv->dev, "No valid mac, use random mac %pM",
|
||||
ndev->dev_addr);
|
||||
|
@ -313,6 +313,20 @@ config ICE
|
||||
To compile this driver as a module, choose M here. The module
|
||||
will be called ice.
|
||||
|
||||
config ICE_SWITCHDEV
|
||||
bool "Switchdev Support"
|
||||
default y
|
||||
depends on ICE && NET_SWITCHDEV
|
||||
help
|
||||
Switchdev support provides internal SRIOV packet steering and switching.
|
||||
|
||||
To enable it on running kernel use devlink tool:
|
||||
#devlink dev eswitch set pci/0000:XX:XX.X mode switchdev
|
||||
|
||||
Say Y here if you want to use Switchdev in the driver.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config FM10K
|
||||
tristate "Intel(R) FM10000 Ethernet Switch Host Interface Support"
|
||||
default n
|
||||
|
@ -26,10 +26,12 @@ ice-y := ice_main.o \
|
||||
ice_devlink.o \
|
||||
ice_fw_update.o \
|
||||
ice_lag.o \
|
||||
ice_ethtool.o
|
||||
ice_ethtool.o \
|
||||
ice_repr.o
|
||||
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_allowlist.o
|
||||
ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o ice_virtchnl_fdir.o
|
||||
ice-$(CONFIG_PTP_1588_CLOCK) += ice_ptp.o ice_ptp_hw.o
|
||||
ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o
|
||||
ice-$(CONFIG_RFS_ACCEL) += ice_arfs.o
|
||||
ice-$(CONFIG_XDP_SOCKETS) += ice_xsk.o
|
||||
ice-$(CONFIG_ICE_SWITCHDEV) += ice_eswitch.o
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "ice_fdir.h"
|
||||
#include "ice_xsk.h"
|
||||
#include "ice_arfs.h"
|
||||
#include "ice_repr.h"
|
||||
#include "ice_lag.h"
|
||||
|
||||
#define ICE_BAR0 0
|
||||
@ -84,6 +85,7 @@
|
||||
#define ICE_FDIR_MSIX 2
|
||||
#define ICE_RDMA_NUM_AEQ_MSIX 4
|
||||
#define ICE_MIN_RDMA_MSIX 2
|
||||
#define ICE_ESWITCH_MSIX 1
|
||||
#define ICE_NO_VSI 0xffff
|
||||
#define ICE_VSI_MAP_CONTIG 0
|
||||
#define ICE_VSI_MAP_SCATTER 1
|
||||
@ -311,10 +313,6 @@ struct ice_vsi {
|
||||
spinlock_t arfs_lock; /* protects aRFS hash table and filter state */
|
||||
atomic_t *arfs_last_fltr_id;
|
||||
|
||||
/* devlink port data */
|
||||
struct devlink_port devlink_port;
|
||||
bool devlink_port_registered;
|
||||
|
||||
u16 max_frame;
|
||||
u16 rx_buf_len;
|
||||
|
||||
@ -354,6 +352,8 @@ struct ice_vsi {
|
||||
u16 num_xdp_txq; /* Used XDP queues */
|
||||
u8 xdp_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */
|
||||
|
||||
struct net_device **target_netdevs;
|
||||
|
||||
/* setup back reference, to which aggregator node this VSI
|
||||
* corresponds to
|
||||
*/
|
||||
@ -413,6 +413,12 @@ enum ice_pf_flags {
|
||||
ICE_PF_FLAGS_NBITS /* must be last */
|
||||
};
|
||||
|
||||
struct ice_switchdev_info {
|
||||
struct ice_vsi *control_vsi;
|
||||
struct ice_vsi *uplink_vsi;
|
||||
bool is_running;
|
||||
};
|
||||
|
||||
struct ice_agg_node {
|
||||
u32 agg_id;
|
||||
#define ICE_MAX_VSIS_IN_AGG_NODE 64
|
||||
@ -426,6 +432,9 @@ struct ice_pf {
|
||||
struct devlink_region *nvm_region;
|
||||
struct devlink_region *devcaps_region;
|
||||
|
||||
/* devlink port data */
|
||||
struct devlink_port devlink_port;
|
||||
|
||||
/* OS reserved IRQ details */
|
||||
struct msix_entry *msix_entries;
|
||||
struct ice_res_tracker *irq_tracker;
|
||||
@ -439,6 +448,7 @@ struct ice_pf {
|
||||
|
||||
struct ice_vsi **vsi; /* VSIs created by the driver */
|
||||
struct ice_sw *first_sw; /* first switch created by firmware */
|
||||
u16 eswitch_mode; /* current mode of eswitch */
|
||||
/* Virtchnl/SR-IOV config info */
|
||||
struct ice_vf *vf;
|
||||
u16 num_alloc_vfs; /* actual number of VFs allocated */
|
||||
@ -507,6 +517,8 @@ struct ice_pf {
|
||||
struct ice_link_default_override_tlv link_dflt_override;
|
||||
struct ice_lag *lag; /* Link Aggregation information */
|
||||
|
||||
struct ice_switchdev_info switchdev;
|
||||
|
||||
#define ICE_INVALID_AGG_NODE_ID 0
|
||||
#define ICE_PF_AGG_NODE_ID_START 1
|
||||
#define ICE_MAX_PF_AGG_NODES 32
|
||||
@ -518,6 +530,7 @@ struct ice_pf {
|
||||
|
||||
struct ice_netdev_priv {
|
||||
struct ice_vsi *vsi;
|
||||
struct ice_repr *repr;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -602,6 +615,19 @@ static inline struct ice_vsi *ice_get_main_vsi(struct ice_pf *pf)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_get_netdev_priv_vsi - return VSI associated with netdev priv.
|
||||
* @np: private netdev structure
|
||||
*/
|
||||
static inline struct ice_vsi *ice_get_netdev_priv_vsi(struct ice_netdev_priv *np)
|
||||
{
|
||||
/* In case of port representor return source port VSI. */
|
||||
if (np->repr)
|
||||
return np->repr->src_vsi;
|
||||
else
|
||||
return np->vsi;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_get_ctrl_vsi - Get the control VSI
|
||||
* @pf: PF instance
|
||||
@ -615,6 +641,18 @@ static inline struct ice_vsi *ice_get_ctrl_vsi(struct ice_pf *pf)
|
||||
return pf->vsi[pf->ctrl_vsi_idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_is_switchdev_running - check if switchdev is configured
|
||||
* @pf: pointer to PF structure
|
||||
*
|
||||
* Returns true if eswitch mode is set to DEVLINK_ESWITCH_MODE_SWITCHDEV
|
||||
* and switchdev is configured, false otherwise.
|
||||
*/
|
||||
static inline bool ice_is_switchdev_running(struct ice_pf *pf)
|
||||
{
|
||||
return pf->switchdev.is_running;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_set_sriov_cap - enable SRIOV in PF flags
|
||||
* @pf: PF struct
|
||||
@ -643,7 +681,9 @@ bool netif_is_ice(struct net_device *dev);
|
||||
int ice_vsi_setup_tx_rings(struct ice_vsi *vsi);
|
||||
int ice_vsi_setup_rx_rings(struct ice_vsi *vsi);
|
||||
int ice_vsi_open_ctrl(struct ice_vsi *vsi);
|
||||
int ice_vsi_open(struct ice_vsi *vsi);
|
||||
void ice_set_ethtool_ops(struct net_device *netdev);
|
||||
void ice_set_ethtool_repr_ops(struct net_device *netdev);
|
||||
void ice_set_ethtool_safe_mode_ops(struct net_device *netdev);
|
||||
u16 ice_get_avail_txq_count(struct ice_pf *pf);
|
||||
u16 ice_get_avail_rxq_count(struct ice_pf *pf);
|
||||
|
@ -217,6 +217,30 @@ static u16 ice_calc_q_handle(struct ice_vsi *vsi, struct ice_ring *ring, u8 tc)
|
||||
return ring->q_index - vsi->tc_cfg.tc_info[tc].qoffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_calc_q_handle
|
||||
* @ring: pointer to ring which unique index is needed
|
||||
*
|
||||
* To correctly work with many netdevs ring->q_index of Tx rings on switchdev
|
||||
* VSI can repeat. Hardware ring setup requires unique q_index. Calculate it
|
||||
* here by finding index in vsi->tx_rings of this ring.
|
||||
*
|
||||
* Return ICE_INVAL_Q_INDEX when index wasn't found. Should never happen,
|
||||
* because VSI is get from ring->vsi, so it has to be present in this VSI.
|
||||
*/
|
||||
static u16 ice_eswitch_calc_q_handle(struct ice_ring *ring)
|
||||
{
|
||||
struct ice_vsi *vsi = ring->vsi;
|
||||
int i;
|
||||
|
||||
ice_for_each_txq(vsi, i) {
|
||||
if (vsi->tx_rings[i] == ring)
|
||||
return i;
|
||||
}
|
||||
|
||||
return ICE_INVAL_Q_INDEX;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_cfg_xps_tx_ring - Configure XPS for a Tx ring
|
||||
* @ring: The Tx ring to configure
|
||||
@ -280,6 +304,9 @@ ice_setup_tx_ctx(struct ice_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf_q)
|
||||
tlan_ctx->vmvf_num = hw->func_caps.vf_base_id + vsi->vf_id;
|
||||
tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VF;
|
||||
break;
|
||||
case ICE_VSI_SWITCHDEV_CTRL:
|
||||
tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VMQ;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@ -746,7 +773,14 @@ ice_vsi_cfg_txq(struct ice_vsi *vsi, struct ice_ring *ring,
|
||||
/* Add unique software queue handle of the Tx queue per
|
||||
* TC into the VSI Tx ring
|
||||
*/
|
||||
ring->q_handle = ice_calc_q_handle(vsi, ring, tc);
|
||||
if (vsi->type == ICE_VSI_SWITCHDEV_CTRL) {
|
||||
ring->q_handle = ice_eswitch_calc_q_handle(ring);
|
||||
|
||||
if (ring->q_handle == ICE_INVAL_Q_INDEX)
|
||||
return -ENODEV;
|
||||
} else {
|
||||
ring->q_handle = ice_calc_q_handle(vsi, ring, tc);
|
||||
}
|
||||
|
||||
status = ice_ena_vsi_txq(vsi->port_info, vsi->idx, tc, ring->q_handle,
|
||||
1, qg_buf, buf_len, NULL);
|
||||
|
@ -683,6 +683,11 @@ void ice_pf_dcb_recfg(struct ice_pf *pf)
|
||||
vsi->idx);
|
||||
continue;
|
||||
}
|
||||
/* no need to proceed with remaining cfg if it is switchdev
|
||||
* VSI
|
||||
*/
|
||||
if (vsi->type == ICE_VSI_SWITCHDEV_CTRL)
|
||||
continue;
|
||||
|
||||
ice_vsi_map_rings_to_vectors(vsi);
|
||||
if (vsi->type == ICE_VSI_PF)
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "ice.h"
|
||||
#include "ice_lib.h"
|
||||
#include "ice_devlink.h"
|
||||
#include "ice_eswitch.h"
|
||||
#include "ice_fw_update.h"
|
||||
|
||||
/* context for devlink info version reporting */
|
||||
@ -423,6 +424,8 @@ ice_devlink_flash_update(struct devlink *devlink,
|
||||
|
||||
static const struct devlink_ops ice_devlink_ops = {
|
||||
.supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
|
||||
.eswitch_mode_get = ice_eswitch_mode_get,
|
||||
.eswitch_mode_set = ice_eswitch_mode_set,
|
||||
.info_get = ice_devlink_info_get,
|
||||
.flash_update = ice_devlink_flash_update,
|
||||
};
|
||||
@ -484,60 +487,115 @@ void ice_devlink_unregister(struct ice_pf *pf)
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_devlink_create_port - Create a devlink port for this VSI
|
||||
* @vsi: the VSI to create a port for
|
||||
* ice_devlink_create_pf_port - Create a devlink port for this PF
|
||||
* @pf: the PF to create a devlink port for
|
||||
*
|
||||
* Create and register a devlink_port for this VSI.
|
||||
* Create and register a devlink_port for this PF.
|
||||
*
|
||||
* Return: zero on success or an error code on failure.
|
||||
*/
|
||||
int ice_devlink_create_port(struct ice_vsi *vsi)
|
||||
int ice_devlink_create_pf_port(struct ice_pf *pf)
|
||||
{
|
||||
struct devlink_port_attrs attrs = {};
|
||||
struct ice_port_info *pi;
|
||||
struct devlink_port *devlink_port;
|
||||
struct devlink *devlink;
|
||||
struct ice_vsi *vsi;
|
||||
struct device *dev;
|
||||
struct ice_pf *pf;
|
||||
int err;
|
||||
|
||||
/* Currently we only create devlink_port instances for PF VSIs */
|
||||
if (vsi->type != ICE_VSI_PF)
|
||||
return -EINVAL;
|
||||
|
||||
pf = vsi->back;
|
||||
devlink = priv_to_devlink(pf);
|
||||
dev = ice_pf_to_dev(pf);
|
||||
pi = pf->hw.port_info;
|
||||
|
||||
devlink_port = &pf->devlink_port;
|
||||
|
||||
vsi = ice_get_main_vsi(pf);
|
||||
if (!vsi)
|
||||
return -EIO;
|
||||
|
||||
attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
|
||||
attrs.phys.port_number = pi->lport;
|
||||
devlink_port_attrs_set(&vsi->devlink_port, &attrs);
|
||||
err = devlink_port_register(devlink, &vsi->devlink_port, vsi->idx);
|
||||
attrs.phys.port_number = pf->hw.bus.func;
|
||||
devlink_port_attrs_set(devlink_port, &attrs);
|
||||
devlink = priv_to_devlink(pf);
|
||||
|
||||
err = devlink_port_register(devlink, devlink_port, vsi->idx);
|
||||
if (err) {
|
||||
dev_err(dev, "devlink_port_register failed: %d\n", err);
|
||||
dev_err(dev, "Failed to create devlink port for PF %d, error %d\n",
|
||||
pf->hw.pf_id, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
vsi->devlink_port_registered = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_devlink_destroy_port - Destroy the devlink_port for this VSI
|
||||
* @vsi: the VSI to cleanup
|
||||
* ice_devlink_destroy_pf_port - Destroy the devlink_port for this PF
|
||||
* @pf: the PF to cleanup
|
||||
*
|
||||
* Unregisters the devlink_port structure associated with this VSI.
|
||||
* Unregisters the devlink_port structure associated with this PF.
|
||||
*/
|
||||
void ice_devlink_destroy_port(struct ice_vsi *vsi)
|
||||
void ice_devlink_destroy_pf_port(struct ice_pf *pf)
|
||||
{
|
||||
if (!vsi->devlink_port_registered)
|
||||
return;
|
||||
struct devlink_port *devlink_port;
|
||||
|
||||
devlink_port_type_clear(&vsi->devlink_port);
|
||||
devlink_port_unregister(&vsi->devlink_port);
|
||||
devlink_port = &pf->devlink_port;
|
||||
|
||||
vsi->devlink_port_registered = false;
|
||||
devlink_port_type_clear(devlink_port);
|
||||
devlink_port_unregister(devlink_port);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_devlink_create_vf_port - Create a devlink port for this VF
|
||||
* @vf: the VF to create a port for
|
||||
*
|
||||
* Create and register a devlink_port for this VF.
|
||||
*
|
||||
* Return: zero on success or an error code on failure.
|
||||
*/
|
||||
int ice_devlink_create_vf_port(struct ice_vf *vf)
|
||||
{
|
||||
struct devlink_port_attrs attrs = {};
|
||||
struct devlink_port *devlink_port;
|
||||
struct devlink *devlink;
|
||||
struct ice_vsi *vsi;
|
||||
struct device *dev;
|
||||
struct ice_pf *pf;
|
||||
int err;
|
||||
|
||||
pf = vf->pf;
|
||||
dev = ice_pf_to_dev(pf);
|
||||
vsi = ice_get_vf_vsi(vf);
|
||||
devlink_port = &vf->devlink_port;
|
||||
|
||||
attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF;
|
||||
attrs.pci_vf.pf = pf->hw.bus.func;
|
||||
attrs.pci_vf.vf = vf->vf_id;
|
||||
|
||||
devlink_port_attrs_set(devlink_port, &attrs);
|
||||
devlink = priv_to_devlink(pf);
|
||||
|
||||
err = devlink_port_register(devlink, devlink_port, vsi->idx);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to create devlink port for VF %d, error %d\n",
|
||||
vf->vf_id, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_devlink_destroy_vf_port - Destroy the devlink_port for this VF
|
||||
* @vf: the VF to cleanup
|
||||
*
|
||||
* Unregisters the devlink_port structure associated with this VF.
|
||||
*/
|
||||
void ice_devlink_destroy_vf_port(struct ice_vf *vf)
|
||||
{
|
||||
struct devlink_port *devlink_port;
|
||||
|
||||
devlink_port = &vf->devlink_port;
|
||||
|
||||
devlink_port_type_clear(devlink_port);
|
||||
devlink_port_unregister(devlink_port);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,8 +8,10 @@ struct ice_pf *ice_allocate_pf(struct device *dev);
|
||||
|
||||
void ice_devlink_register(struct ice_pf *pf);
|
||||
void ice_devlink_unregister(struct ice_pf *pf);
|
||||
int ice_devlink_create_port(struct ice_vsi *vsi);
|
||||
void ice_devlink_destroy_port(struct ice_vsi *vsi);
|
||||
int ice_devlink_create_pf_port(struct ice_pf *pf);
|
||||
void ice_devlink_destroy_pf_port(struct ice_pf *pf);
|
||||
int ice_devlink_create_vf_port(struct ice_vf *vf);
|
||||
void ice_devlink_destroy_vf_port(struct ice_vf *vf);
|
||||
|
||||
void ice_devlink_init_regions(struct ice_pf *pf);
|
||||
void ice_devlink_destroy_regions(struct ice_pf *pf);
|
||||
|
657
drivers/net/ethernet/intel/ice/ice_eswitch.c
Normal file
657
drivers/net/ethernet/intel/ice/ice_eswitch.c
Normal file
@ -0,0 +1,657 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (C) 2019-2021, Intel Corporation. */
|
||||
|
||||
#include "ice.h"
|
||||
#include "ice_lib.h"
|
||||
#include "ice_eswitch.h"
|
||||
#include "ice_fltr.h"
|
||||
#include "ice_repr.h"
|
||||
#include "ice_devlink.h"
|
||||
|
||||
/**
|
||||
* ice_eswitch_setup_env - configure switchdev HW filters
|
||||
* @pf: pointer to PF struct
|
||||
*
|
||||
* This function adds HW filters configuration specific for switchdev
|
||||
* mode.
|
||||
*/
|
||||
static int ice_eswitch_setup_env(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_vsi *uplink_vsi = pf->switchdev.uplink_vsi;
|
||||
struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi;
|
||||
struct ice_port_info *pi = pf->hw.port_info;
|
||||
bool rule_added = false;
|
||||
|
||||
ice_vsi_manage_vlan_stripping(ctrl_vsi, false);
|
||||
|
||||
ice_remove_vsi_fltr(&pf->hw, uplink_vsi->idx);
|
||||
|
||||
if (ice_vsi_add_vlan(uplink_vsi, 0, ICE_FWD_TO_VSI))
|
||||
goto err_def_rx;
|
||||
|
||||
if (!ice_is_dflt_vsi_in_use(uplink_vsi->vsw)) {
|
||||
if (ice_set_dflt_vsi(uplink_vsi->vsw, uplink_vsi))
|
||||
goto err_def_rx;
|
||||
rule_added = true;
|
||||
}
|
||||
|
||||
if (ice_cfg_dflt_vsi(pi->hw, ctrl_vsi->idx, true, ICE_FLTR_TX))
|
||||
goto err_def_tx;
|
||||
|
||||
if (ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_set_allow_override))
|
||||
goto err_override_uplink;
|
||||
|
||||
if (ice_vsi_update_security(ctrl_vsi, ice_vsi_ctx_set_allow_override))
|
||||
goto err_override_control;
|
||||
|
||||
if (ice_fltr_update_flags_dflt_rule(ctrl_vsi, pi->dflt_tx_vsi_rule_id,
|
||||
ICE_FLTR_TX,
|
||||
ICE_SINGLE_ACT_LB_ENABLE))
|
||||
goto err_update_action;
|
||||
|
||||
return 0;
|
||||
|
||||
err_update_action:
|
||||
ice_vsi_update_security(ctrl_vsi, ice_vsi_ctx_clear_allow_override);
|
||||
err_override_control:
|
||||
ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);
|
||||
err_override_uplink:
|
||||
ice_cfg_dflt_vsi(pi->hw, ctrl_vsi->idx, false, ICE_FLTR_TX);
|
||||
err_def_tx:
|
||||
if (rule_added)
|
||||
ice_clear_dflt_vsi(uplink_vsi->vsw);
|
||||
err_def_rx:
|
||||
ice_fltr_add_mac_and_broadcast(uplink_vsi,
|
||||
uplink_vsi->port_info->mac.perm_addr,
|
||||
ICE_FWD_TO_VSI);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_remap_ring - reconfigure ring of switchdev ctrl VSI
|
||||
* @ring: pointer to ring
|
||||
* @q_vector: pointer of q_vector which is connected with this ring
|
||||
* @netdev: netdevice connected with this ring
|
||||
*/
|
||||
static void
|
||||
ice_eswitch_remap_ring(struct ice_ring *ring, struct ice_q_vector *q_vector,
|
||||
struct net_device *netdev)
|
||||
{
|
||||
ring->q_vector = q_vector;
|
||||
ring->next = NULL;
|
||||
ring->netdev = netdev;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_remap_rings_to_vectors - reconfigure rings of switchdev ctrl VSI
|
||||
* @pf: pointer to PF struct
|
||||
*
|
||||
* In switchdev number of allocated Tx/Rx rings is equal.
|
||||
*
|
||||
* This function fills q_vectors structures associated with representor and
|
||||
* move each ring pairs to port representor netdevs. Each port representor
|
||||
* will have dedicated 1 Tx/Rx ring pair, so number of rings pair is equal to
|
||||
* number of VFs.
|
||||
*/
|
||||
static void ice_eswitch_remap_rings_to_vectors(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_vsi *vsi = pf->switchdev.control_vsi;
|
||||
int q_id;
|
||||
|
||||
ice_for_each_txq(vsi, q_id) {
|
||||
struct ice_repr *repr = pf->vf[q_id].repr;
|
||||
struct ice_q_vector *q_vector = repr->q_vector;
|
||||
struct ice_ring *tx_ring = vsi->tx_rings[q_id];
|
||||
struct ice_ring *rx_ring = vsi->rx_rings[q_id];
|
||||
|
||||
q_vector->vsi = vsi;
|
||||
q_vector->reg_idx = vsi->q_vectors[0]->reg_idx;
|
||||
|
||||
q_vector->num_ring_tx = 1;
|
||||
q_vector->tx.ring = tx_ring;
|
||||
ice_eswitch_remap_ring(tx_ring, q_vector, repr->netdev);
|
||||
/* In switchdev mode, from OS stack perspective, there is only
|
||||
* one queue for given netdev, so it needs to be indexed as 0.
|
||||
*/
|
||||
tx_ring->q_index = 0;
|
||||
|
||||
q_vector->num_ring_rx = 1;
|
||||
q_vector->rx.ring = rx_ring;
|
||||
ice_eswitch_remap_ring(rx_ring, q_vector, repr->netdev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_setup_reprs - configure port reprs to run in switchdev mode
|
||||
* @pf: pointer to PF struct
|
||||
*/
|
||||
static int ice_eswitch_setup_reprs(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi;
|
||||
int max_vsi_num = 0;
|
||||
int i;
|
||||
|
||||
ice_for_each_vf(pf, i) {
|
||||
struct ice_vsi *vsi = pf->vf[i].repr->src_vsi;
|
||||
struct ice_vf *vf = &pf->vf[i];
|
||||
|
||||
ice_remove_vsi_fltr(&pf->hw, vsi->idx);
|
||||
vf->repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX,
|
||||
GFP_KERNEL);
|
||||
if (!vf->repr->dst) {
|
||||
ice_fltr_add_mac_and_broadcast(vsi,
|
||||
vf->hw_lan_addr.addr,
|
||||
ICE_FWD_TO_VSI);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ice_vsi_update_security(vsi, ice_vsi_ctx_clear_antispoof)) {
|
||||
ice_fltr_add_mac_and_broadcast(vsi,
|
||||
vf->hw_lan_addr.addr,
|
||||
ICE_FWD_TO_VSI);
|
||||
metadata_dst_free(vf->repr->dst);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ice_vsi_add_vlan(vsi, 0, ICE_FWD_TO_VSI)) {
|
||||
ice_fltr_add_mac_and_broadcast(vsi,
|
||||
vf->hw_lan_addr.addr,
|
||||
ICE_FWD_TO_VSI);
|
||||
metadata_dst_free(vf->repr->dst);
|
||||
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (max_vsi_num < vsi->vsi_num)
|
||||
max_vsi_num = vsi->vsi_num;
|
||||
|
||||
netif_napi_add(vf->repr->netdev, &vf->repr->q_vector->napi, ice_napi_poll,
|
||||
NAPI_POLL_WEIGHT);
|
||||
|
||||
netif_keep_dst(vf->repr->netdev);
|
||||
}
|
||||
|
||||
kfree(ctrl_vsi->target_netdevs);
|
||||
|
||||
ctrl_vsi->target_netdevs = kcalloc(max_vsi_num + 1,
|
||||
sizeof(*ctrl_vsi->target_netdevs),
|
||||
GFP_KERNEL);
|
||||
if (!ctrl_vsi->target_netdevs)
|
||||
goto err;
|
||||
|
||||
ice_for_each_vf(pf, i) {
|
||||
struct ice_repr *repr = pf->vf[i].repr;
|
||||
struct ice_vsi *vsi = repr->src_vsi;
|
||||
struct metadata_dst *dst;
|
||||
|
||||
ctrl_vsi->target_netdevs[vsi->vsi_num] = repr->netdev;
|
||||
|
||||
dst = repr->dst;
|
||||
dst->u.port_info.port_id = vsi->vsi_num;
|
||||
dst->u.port_info.lower_dev = repr->netdev;
|
||||
ice_repr_set_traffic_vsi(repr, ctrl_vsi);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
for (i = i - 1; i >= 0; i--) {
|
||||
struct ice_vsi *vsi = pf->vf[i].repr->src_vsi;
|
||||
struct ice_vf *vf = &pf->vf[i];
|
||||
|
||||
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
|
||||
metadata_dst_free(vf->repr->dst);
|
||||
ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr.addr,
|
||||
ICE_FWD_TO_VSI);
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_release_reprs - clear PR VSIs configuration
|
||||
* @pf: poiner to PF struct
|
||||
* @ctrl_vsi: pointer to switchdev control VSI
|
||||
*/
|
||||
static void
|
||||
ice_eswitch_release_reprs(struct ice_pf *pf, struct ice_vsi *ctrl_vsi)
|
||||
{
|
||||
int i;
|
||||
|
||||
kfree(ctrl_vsi->target_netdevs);
|
||||
ice_for_each_vf(pf, i) {
|
||||
struct ice_vsi *vsi = pf->vf[i].repr->src_vsi;
|
||||
struct ice_vf *vf = &pf->vf[i];
|
||||
|
||||
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
|
||||
metadata_dst_free(vf->repr->dst);
|
||||
ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr.addr,
|
||||
ICE_FWD_TO_VSI);
|
||||
|
||||
netif_napi_del(&vf->repr->q_vector->napi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_update_repr - reconfigure VF port representor
|
||||
* @vsi: VF VSI for which port representor is configured
|
||||
*/
|
||||
void ice_eswitch_update_repr(struct ice_vsi *vsi)
|
||||
{
|
||||
struct ice_pf *pf = vsi->back;
|
||||
struct ice_repr *repr;
|
||||
struct ice_vf *vf;
|
||||
int ret;
|
||||
|
||||
if (!ice_is_switchdev_running(pf))
|
||||
return;
|
||||
|
||||
vf = &pf->vf[vsi->vf_id];
|
||||
repr = vf->repr;
|
||||
repr->src_vsi = vsi;
|
||||
repr->dst->u.port_info.port_id = vsi->vsi_num;
|
||||
|
||||
ret = ice_vsi_update_security(vsi, ice_vsi_ctx_clear_antispoof);
|
||||
if (ret) {
|
||||
ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr.addr, ICE_FWD_TO_VSI);
|
||||
dev_err(ice_pf_to_dev(pf), "Failed to update VF %d port representor", vsi->vf_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_port_start_xmit - callback for packets transmit
|
||||
* @skb: send buffer
|
||||
* @netdev: network interface device structure
|
||||
*
|
||||
* Returns NETDEV_TX_OK if sent, else an error code
|
||||
*/
|
||||
netdev_tx_t
|
||||
ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
{
|
||||
struct ice_netdev_priv *np;
|
||||
struct ice_repr *repr;
|
||||
struct ice_vsi *vsi;
|
||||
|
||||
np = netdev_priv(netdev);
|
||||
vsi = np->vsi;
|
||||
|
||||
if (ice_is_reset_in_progress(vsi->back->state))
|
||||
return NETDEV_TX_BUSY;
|
||||
|
||||
repr = ice_netdev_to_repr(netdev);
|
||||
skb_dst_drop(skb);
|
||||
dst_hold((struct dst_entry *)repr->dst);
|
||||
skb_dst_set(skb, (struct dst_entry *)repr->dst);
|
||||
skb->queue_mapping = repr->vf->vf_id;
|
||||
|
||||
return ice_start_xmit(skb, netdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_set_target_vsi - set switchdev context in Tx context descriptor
|
||||
* @skb: pointer to send buffer
|
||||
* @off: pointer to offload struct
|
||||
*/
|
||||
void
|
||||
ice_eswitch_set_target_vsi(struct sk_buff *skb,
|
||||
struct ice_tx_offload_params *off)
|
||||
{
|
||||
struct metadata_dst *dst = skb_metadata_dst(skb);
|
||||
u64 cd_cmd, dst_vsi;
|
||||
|
||||
if (!dst) {
|
||||
cd_cmd = ICE_TX_CTX_DESC_SWTCH_UPLINK << ICE_TXD_CTX_QW1_CMD_S;
|
||||
off->cd_qw1 |= (cd_cmd | ICE_TX_DESC_DTYPE_CTX);
|
||||
} else {
|
||||
cd_cmd = ICE_TX_CTX_DESC_SWTCH_VSI << ICE_TXD_CTX_QW1_CMD_S;
|
||||
dst_vsi = ((u64)dst->u.port_info.port_id <<
|
||||
ICE_TXD_CTX_QW1_VSI_S) & ICE_TXD_CTX_QW1_VSI_M;
|
||||
off->cd_qw1 = cd_cmd | dst_vsi | ICE_TX_DESC_DTYPE_CTX;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_release_env - clear switchdev HW filters
|
||||
* @pf: pointer to PF struct
|
||||
*
|
||||
* This function removes HW filters configuration specific for switchdev
|
||||
* mode and restores default legacy mode settings.
|
||||
*/
|
||||
static void ice_eswitch_release_env(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_vsi *uplink_vsi = pf->switchdev.uplink_vsi;
|
||||
struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi;
|
||||
|
||||
ice_vsi_update_security(ctrl_vsi, ice_vsi_ctx_clear_allow_override);
|
||||
ice_vsi_update_security(uplink_vsi, ice_vsi_ctx_clear_allow_override);
|
||||
ice_cfg_dflt_vsi(&pf->hw, ctrl_vsi->idx, false, ICE_FLTR_TX);
|
||||
ice_clear_dflt_vsi(uplink_vsi->vsw);
|
||||
ice_fltr_add_mac_and_broadcast(uplink_vsi,
|
||||
uplink_vsi->port_info->mac.perm_addr,
|
||||
ICE_FWD_TO_VSI);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_vsi_setup - configure switchdev control VSI
|
||||
* @pf: pointer to PF structure
|
||||
* @pi: pointer to port_info structure
|
||||
*/
|
||||
static struct ice_vsi *
|
||||
ice_eswitch_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
|
||||
{
|
||||
return ice_vsi_setup(pf, pi, ICE_VSI_SWITCHDEV_CTRL, ICE_INVAL_VFID);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_napi_del - remove NAPI handle for all port representors
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
static void ice_eswitch_napi_del(struct ice_pf *pf)
|
||||
{
|
||||
int i;
|
||||
|
||||
ice_for_each_vf(pf, i)
|
||||
netif_napi_del(&pf->vf[i].repr->q_vector->napi);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_napi_enable - enable NAPI for all port representors
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
static void ice_eswitch_napi_enable(struct ice_pf *pf)
|
||||
{
|
||||
int i;
|
||||
|
||||
ice_for_each_vf(pf, i)
|
||||
napi_enable(&pf->vf[i].repr->q_vector->napi);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_napi_disable - disable NAPI for all port representors
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
static void ice_eswitch_napi_disable(struct ice_pf *pf)
|
||||
{
|
||||
int i;
|
||||
|
||||
ice_for_each_vf(pf, i)
|
||||
napi_disable(&pf->vf[i].repr->q_vector->napi);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_set_rxdid - configure rxdid on all Rx queues from VSI
|
||||
* @vsi: VSI to setup rxdid on
|
||||
* @rxdid: flex descriptor id
|
||||
*/
|
||||
static void ice_eswitch_set_rxdid(struct ice_vsi *vsi, u32 rxdid)
|
||||
{
|
||||
struct ice_hw *hw = &vsi->back->hw;
|
||||
int i;
|
||||
|
||||
ice_for_each_rxq(vsi, i) {
|
||||
struct ice_ring *ring = vsi->rx_rings[i];
|
||||
u16 pf_q = vsi->rxq_map[ring->q_index];
|
||||
|
||||
ice_write_qrxflxp_cntxt(hw, pf_q, rxdid, 0x3, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_enable_switchdev - configure eswitch in switchdev mode
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
static int ice_eswitch_enable_switchdev(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_vsi *ctrl_vsi;
|
||||
|
||||
pf->switchdev.control_vsi = ice_eswitch_vsi_setup(pf, pf->hw.port_info);
|
||||
if (!pf->switchdev.control_vsi)
|
||||
return -ENODEV;
|
||||
|
||||
ctrl_vsi = pf->switchdev.control_vsi;
|
||||
pf->switchdev.uplink_vsi = ice_get_main_vsi(pf);
|
||||
if (!pf->switchdev.uplink_vsi)
|
||||
goto err_vsi;
|
||||
|
||||
if (ice_eswitch_setup_env(pf))
|
||||
goto err_vsi;
|
||||
|
||||
if (ice_repr_add_for_all_vfs(pf))
|
||||
goto err_repr_add;
|
||||
|
||||
if (ice_eswitch_setup_reprs(pf))
|
||||
goto err_setup_reprs;
|
||||
|
||||
ice_eswitch_remap_rings_to_vectors(pf);
|
||||
|
||||
if (ice_vsi_open(ctrl_vsi))
|
||||
goto err_setup_reprs;
|
||||
|
||||
ice_eswitch_napi_enable(pf);
|
||||
|
||||
ice_eswitch_set_rxdid(ctrl_vsi, ICE_RXDID_FLEX_NIC_2);
|
||||
|
||||
return 0;
|
||||
|
||||
err_setup_reprs:
|
||||
ice_repr_rem_from_all_vfs(pf);
|
||||
err_repr_add:
|
||||
ice_eswitch_release_env(pf);
|
||||
err_vsi:
|
||||
ice_vsi_release(ctrl_vsi);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_disable_switchdev - disable switchdev resources
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
static void ice_eswitch_disable_switchdev(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi;
|
||||
|
||||
ice_eswitch_napi_disable(pf);
|
||||
ice_eswitch_release_env(pf);
|
||||
ice_eswitch_release_reprs(pf, ctrl_vsi);
|
||||
ice_vsi_release(ctrl_vsi);
|
||||
ice_repr_rem_from_all_vfs(pf);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_mode_set - set new eswitch mode
|
||||
* @devlink: pointer to devlink structure
|
||||
* @mode: eswitch mode to switch to
|
||||
* @extack: pointer to extack structure
|
||||
*/
|
||||
int
|
||||
ice_eswitch_mode_set(struct devlink *devlink, u16 mode,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct ice_pf *pf = devlink_priv(devlink);
|
||||
|
||||
if (pf->eswitch_mode == mode)
|
||||
return 0;
|
||||
|
||||
if (pf->num_alloc_vfs) {
|
||||
dev_info(ice_pf_to_dev(pf), "Changing eswitch mode is allowed only if there is no VFs created");
|
||||
NL_SET_ERR_MSG_MOD(extack, "Changing eswitch mode is allowed only if there is no VFs created");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case DEVLINK_ESWITCH_MODE_LEGACY:
|
||||
dev_info(ice_pf_to_dev(pf), "PF %d changed eswitch mode to legacy",
|
||||
pf->hw.pf_id);
|
||||
NL_SET_ERR_MSG_MOD(extack, "Changed eswitch mode to legacy");
|
||||
break;
|
||||
case DEVLINK_ESWITCH_MODE_SWITCHDEV:
|
||||
{
|
||||
dev_info(ice_pf_to_dev(pf), "PF %d changed eswitch mode to switchdev",
|
||||
pf->hw.pf_id);
|
||||
NL_SET_ERR_MSG_MOD(extack, "Changed eswitch mode to switchdev");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unknown eswitch mode");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pf->eswitch_mode = mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_get_target_netdev - return port representor netdev
|
||||
* @rx_ring: pointer to Rx ring
|
||||
* @rx_desc: pointer to Rx descriptor
|
||||
*
|
||||
* When working in switchdev mode context (when control VSI is used), this
|
||||
* function returns netdev of appropriate port representor. For non-switchdev
|
||||
* context, regular netdev associated with Rx ring is returned.
|
||||
*/
|
||||
struct net_device *
|
||||
ice_eswitch_get_target_netdev(struct ice_ring *rx_ring,
|
||||
union ice_32b_rx_flex_desc *rx_desc)
|
||||
{
|
||||
struct ice_32b_rx_flex_desc_nic_2 *desc;
|
||||
struct ice_vsi *vsi = rx_ring->vsi;
|
||||
struct ice_vsi *control_vsi;
|
||||
u16 target_vsi_id;
|
||||
|
||||
control_vsi = vsi->back->switchdev.control_vsi;
|
||||
if (vsi != control_vsi)
|
||||
return rx_ring->netdev;
|
||||
|
||||
desc = (struct ice_32b_rx_flex_desc_nic_2 *)rx_desc;
|
||||
target_vsi_id = le16_to_cpu(desc->src_vsi);
|
||||
|
||||
return vsi->target_netdevs[target_vsi_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_mode_get - get current eswitch mode
|
||||
* @devlink: pointer to devlink structure
|
||||
* @mode: output parameter for current eswitch mode
|
||||
*/
|
||||
int ice_eswitch_mode_get(struct devlink *devlink, u16 *mode)
|
||||
{
|
||||
struct ice_pf *pf = devlink_priv(devlink);
|
||||
|
||||
*mode = pf->eswitch_mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_is_eswitch_mode_switchdev - check if eswitch mode is set to switchdev
|
||||
* @pf: pointer to PF structure
|
||||
*
|
||||
* Returns true if eswitch mode is set to DEVLINK_ESWITCH_MODE_SWITCHDEV,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf)
|
||||
{
|
||||
return pf->eswitch_mode == DEVLINK_ESWITCH_MODE_SWITCHDEV;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_release - cleanup eswitch
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
void ice_eswitch_release(struct ice_pf *pf)
|
||||
{
|
||||
if (pf->eswitch_mode == DEVLINK_ESWITCH_MODE_LEGACY)
|
||||
return;
|
||||
|
||||
ice_eswitch_disable_switchdev(pf);
|
||||
pf->switchdev.is_running = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_configure - configure eswitch
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
int ice_eswitch_configure(struct ice_pf *pf)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (pf->eswitch_mode == DEVLINK_ESWITCH_MODE_LEGACY || pf->switchdev.is_running)
|
||||
return 0;
|
||||
|
||||
status = ice_eswitch_enable_switchdev(pf);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
pf->switchdev.is_running = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_start_all_tx_queues - start Tx queues of all port representors
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
static void ice_eswitch_start_all_tx_queues(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_repr *repr;
|
||||
int i;
|
||||
|
||||
if (test_bit(ICE_DOWN, pf->state))
|
||||
return;
|
||||
|
||||
ice_for_each_vf(pf, i) {
|
||||
repr = pf->vf[i].repr;
|
||||
if (repr)
|
||||
ice_repr_start_tx_queues(repr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_stop_all_tx_queues - stop Tx queues of all port representors
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_repr *repr;
|
||||
int i;
|
||||
|
||||
if (test_bit(ICE_DOWN, pf->state))
|
||||
return;
|
||||
|
||||
ice_for_each_vf(pf, i) {
|
||||
repr = pf->vf[i].repr;
|
||||
if (repr)
|
||||
ice_repr_stop_tx_queues(repr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_eswitch_rebuild - rebuild eswitch
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
int ice_eswitch_rebuild(struct ice_pf *pf)
|
||||
{
|
||||
struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi;
|
||||
int status;
|
||||
|
||||
ice_eswitch_napi_disable(pf);
|
||||
ice_eswitch_napi_del(pf);
|
||||
|
||||
status = ice_eswitch_setup_env(pf);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = ice_eswitch_setup_reprs(pf);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
ice_eswitch_remap_rings_to_vectors(pf);
|
||||
|
||||
status = ice_vsi_open(ctrl_vsi);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
ice_eswitch_napi_enable(pf);
|
||||
ice_eswitch_set_rxdid(ctrl_vsi, ICE_RXDID_FLEX_NIC_2);
|
||||
ice_eswitch_start_all_tx_queues(pf);
|
||||
|
||||
return 0;
|
||||
}
|
83
drivers/net/ethernet/intel/ice/ice_eswitch.h
Normal file
83
drivers/net/ethernet/intel/ice/ice_eswitch.h
Normal file
@ -0,0 +1,83 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2019-2021, Intel Corporation. */
|
||||
|
||||
#ifndef _ICE_ESWITCH_H_
|
||||
#define _ICE_ESWITCH_H_
|
||||
|
||||
#include <net/devlink.h>
|
||||
|
||||
#ifdef CONFIG_ICE_SWITCHDEV
|
||||
void ice_eswitch_release(struct ice_pf *pf);
|
||||
int ice_eswitch_configure(struct ice_pf *pf);
|
||||
int ice_eswitch_rebuild(struct ice_pf *pf);
|
||||
|
||||
int ice_eswitch_mode_get(struct devlink *devlink, u16 *mode);
|
||||
int
|
||||
ice_eswitch_mode_set(struct devlink *devlink, u16 mode,
|
||||
struct netlink_ext_ack *extack);
|
||||
bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf);
|
||||
|
||||
void ice_eswitch_update_repr(struct ice_vsi *vsi);
|
||||
|
||||
void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf);
|
||||
|
||||
struct net_device *
|
||||
ice_eswitch_get_target_netdev(struct ice_ring *rx_ring,
|
||||
union ice_32b_rx_flex_desc *rx_desc);
|
||||
|
||||
void ice_eswitch_set_target_vsi(struct sk_buff *skb,
|
||||
struct ice_tx_offload_params *off);
|
||||
netdev_tx_t
|
||||
ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev);
|
||||
#else /* CONFIG_ICE_SWITCHDEV */
|
||||
static inline void ice_eswitch_release(struct ice_pf *pf) { }
|
||||
|
||||
static inline void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf) { }
|
||||
|
||||
static inline void
|
||||
ice_eswitch_set_target_vsi(struct sk_buff *skb,
|
||||
struct ice_tx_offload_params *off) { }
|
||||
|
||||
static inline void ice_eswitch_update_repr(struct ice_vsi *vsi) { }
|
||||
|
||||
static inline int ice_eswitch_configure(struct ice_pf *pf)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int ice_eswitch_rebuild(struct ice_pf *pf)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int ice_eswitch_mode_get(struct devlink *devlink, u16 *mode)
|
||||
{
|
||||
return DEVLINK_ESWITCH_MODE_LEGACY;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ice_eswitch_mode_set(struct devlink *devlink, u16 mode,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline struct net_device *
|
||||
ice_eswitch_get_target_netdev(struct ice_ring *rx_ring,
|
||||
union ice_32b_rx_flex_desc *rx_desc)
|
||||
{
|
||||
return rx_ring->netdev;
|
||||
}
|
||||
|
||||
static inline netdev_tx_t
|
||||
ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev)
|
||||
{
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
#endif /* CONFIG_ICE_SWITCHDEV */
|
||||
#endif /* _ICE_ESWITCH_H_ */
|
@ -170,10 +170,9 @@ static const struct ice_priv_flag ice_gstrings_priv_flags[] = {
|
||||
#define ICE_PRIV_FLAG_ARRAY_SIZE ARRAY_SIZE(ice_gstrings_priv_flags)
|
||||
|
||||
static void
|
||||
ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
|
||||
__ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo,
|
||||
struct ice_vsi *vsi)
|
||||
{
|
||||
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||
struct ice_vsi *vsi = np->vsi;
|
||||
struct ice_pf *pf = vsi->back;
|
||||
struct ice_hw *hw = &pf->hw;
|
||||
struct ice_orom_info *orom;
|
||||
@ -196,6 +195,26 @@ ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
|
||||
drvinfo->n_priv_flags = ICE_PRIV_FLAG_ARRAY_SIZE;
|
||||
}
|
||||
|
||||
static void
|
||||
ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
|
||||
{
|
||||
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||
|
||||
__ice_get_drvinfo(netdev, drvinfo, np->vsi);
|
||||
}
|
||||
|
||||
static void
|
||||
ice_repr_get_drvinfo(struct net_device *netdev,
|
||||
struct ethtool_drvinfo *drvinfo)
|
||||
{
|
||||
struct ice_repr *repr = ice_netdev_to_repr(netdev);
|
||||
|
||||
if (ice_check_vf_ready_for_cfg(repr->vf))
|
||||
return;
|
||||
|
||||
__ice_get_drvinfo(netdev, drvinfo, repr->src_vsi);
|
||||
}
|
||||
|
||||
static int ice_get_regs_len(struct net_device __always_unused *netdev)
|
||||
{
|
||||
return sizeof(ice_regs_dump_list);
|
||||
@ -869,7 +888,7 @@ ice_self_test(struct net_device *netdev, struct ethtool_test *eth_test,
|
||||
static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
|
||||
{
|
||||
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||
struct ice_vsi *vsi = np->vsi;
|
||||
struct ice_vsi *vsi = ice_get_netdev_priv_vsi(np);
|
||||
unsigned int i;
|
||||
u8 *p = data;
|
||||
|
||||
@ -879,6 +898,9 @@ static void ice_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
|
||||
ethtool_sprintf(&p,
|
||||
ice_gstrings_vsi_stats[i].stat_string);
|
||||
|
||||
if (ice_is_port_repr_netdev(netdev))
|
||||
return;
|
||||
|
||||
ice_for_each_alloc_txq(vsi, i) {
|
||||
ethtool_sprintf(&p, "tx_queue_%u_packets", i);
|
||||
ethtool_sprintf(&p, "tx_queue_%u_bytes", i);
|
||||
@ -1308,6 +1330,9 @@ static int ice_get_sset_count(struct net_device *netdev, int sset)
|
||||
* order of strings will suffer from race conditions and are
|
||||
* not safe.
|
||||
*/
|
||||
if (ice_is_port_repr_netdev(netdev))
|
||||
return ICE_VSI_STATS_LEN;
|
||||
|
||||
return ICE_ALL_STATS_LEN(netdev);
|
||||
case ETH_SS_TEST:
|
||||
return ICE_TEST_LEN;
|
||||
@ -1323,7 +1348,7 @@ ice_get_ethtool_stats(struct net_device *netdev,
|
||||
struct ethtool_stats __always_unused *stats, u64 *data)
|
||||
{
|
||||
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||
struct ice_vsi *vsi = np->vsi;
|
||||
struct ice_vsi *vsi = ice_get_netdev_priv_vsi(np);
|
||||
struct ice_pf *pf = vsi->back;
|
||||
struct ice_ring *ring;
|
||||
unsigned int j;
|
||||
@ -1339,6 +1364,9 @@ ice_get_ethtool_stats(struct net_device *netdev,
|
||||
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
|
||||
}
|
||||
|
||||
if (ice_is_port_repr_netdev(netdev))
|
||||
return;
|
||||
|
||||
/* populate per queue stats */
|
||||
rcu_read_lock();
|
||||
|
||||
@ -4062,6 +4090,23 @@ void ice_set_ethtool_safe_mode_ops(struct net_device *netdev)
|
||||
netdev->ethtool_ops = &ice_ethtool_safe_mode_ops;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops ice_ethtool_repr_ops = {
|
||||
.get_drvinfo = ice_repr_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_strings = ice_get_strings,
|
||||
.get_ethtool_stats = ice_get_ethtool_stats,
|
||||
.get_sset_count = ice_get_sset_count,
|
||||
};
|
||||
|
||||
/**
|
||||
* ice_set_ethtool_repr_ops - setup VF's port representor ethtool ops
|
||||
* @netdev: network interface device structure
|
||||
*/
|
||||
void ice_set_ethtool_repr_ops(struct net_device *netdev)
|
||||
{
|
||||
netdev->ethtool_ops = &ice_ethtool_repr_ops;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_set_ethtool_ops - setup netdev ethtool ops
|
||||
* @netdev: network interface device structure
|
||||
|
@ -395,3 +395,83 @@ enum ice_status ice_fltr_remove_eth(struct ice_vsi *vsi, u16 ethertype,
|
||||
return ice_fltr_prepare_eth(vsi, ethertype, flag, action,
|
||||
ice_fltr_remove_eth_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_fltr_update_rule_flags - update lan_en/lb_en flags
|
||||
* @hw: pointer to hw
|
||||
* @rule_id: id of rule being updated
|
||||
* @recipe_id: recipe id of rule
|
||||
* @act: current action field
|
||||
* @type: Rx or Tx
|
||||
* @src: source VSI
|
||||
* @new_flags: combinations of lb_en and lan_en
|
||||
*/
|
||||
static enum ice_status
|
||||
ice_fltr_update_rule_flags(struct ice_hw *hw, u16 rule_id, u16 recipe_id,
|
||||
u32 act, u16 type, u16 src, u32 new_flags)
|
||||
{
|
||||
struct ice_aqc_sw_rules_elem *s_rule;
|
||||
enum ice_status err;
|
||||
u32 flags_mask;
|
||||
|
||||
s_rule = kzalloc(ICE_SW_RULE_RX_TX_NO_HDR_SIZE, GFP_KERNEL);
|
||||
if (!s_rule)
|
||||
return ICE_ERR_NO_MEMORY;
|
||||
|
||||
flags_mask = ICE_SINGLE_ACT_LB_ENABLE | ICE_SINGLE_ACT_LAN_ENABLE;
|
||||
act &= ~flags_mask;
|
||||
act |= (flags_mask & new_flags);
|
||||
|
||||
s_rule->pdata.lkup_tx_rx.recipe_id = cpu_to_le16(recipe_id);
|
||||
s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(rule_id);
|
||||
s_rule->pdata.lkup_tx_rx.act = cpu_to_le32(act);
|
||||
|
||||
if (type & ICE_FLTR_RX) {
|
||||
s_rule->pdata.lkup_tx_rx.src =
|
||||
cpu_to_le16(hw->port_info->lport);
|
||||
s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
|
||||
|
||||
} else {
|
||||
s_rule->pdata.lkup_tx_rx.src = cpu_to_le16(src);
|
||||
s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
|
||||
}
|
||||
|
||||
err = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1,
|
||||
ice_aqc_opc_update_sw_rules, NULL);
|
||||
|
||||
kfree(s_rule);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_fltr_build_action - build action for rule
|
||||
* @vsi_id: id of VSI which is use to build action
|
||||
*/
|
||||
static u32 ice_fltr_build_action(u16 vsi_id)
|
||||
{
|
||||
return ((vsi_id << ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M) |
|
||||
ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_fltr_update_flags_dflt_rule - update flags on default rule
|
||||
* @vsi: pointer to VSI
|
||||
* @rule_id: id of rule
|
||||
* @direction: Tx or Rx
|
||||
* @new_flags: flags to update
|
||||
*
|
||||
* Function updates flags on default rule with ICE_SW_LKUP_DFLT.
|
||||
*
|
||||
* Flags should be a combination of ICE_SINGLE_ACT_LB_ENABLE and
|
||||
* ICE_SINGLE_ACT_LAN_ENABLE.
|
||||
*/
|
||||
enum ice_status
|
||||
ice_fltr_update_flags_dflt_rule(struct ice_vsi *vsi, u16 rule_id, u8 direction,
|
||||
u32 new_flags)
|
||||
{
|
||||
u32 action = ice_fltr_build_action(vsi->vsi_num);
|
||||
struct ice_hw *hw = &vsi->back->hw;
|
||||
|
||||
return ice_fltr_update_rule_flags(hw, rule_id, ICE_SW_LKUP_DFLT, action,
|
||||
direction, vsi->vsi_num, new_flags);
|
||||
}
|
||||
|
@ -36,4 +36,11 @@ enum ice_status
|
||||
ice_fltr_remove_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,
|
||||
enum ice_sw_fwd_act_type action);
|
||||
void ice_fltr_remove_all(struct ice_vsi *vsi);
|
||||
|
||||
enum ice_status
|
||||
ice_fltr_update_flags(struct ice_vsi *vsi, u16 rule_id, u16 recipe_id,
|
||||
u32 new_flags);
|
||||
enum ice_status
|
||||
ice_fltr_update_flags_dflt_rule(struct ice_vsi *vsi, u16 rule_id, u8 direction,
|
||||
u32 new_flags);
|
||||
#endif
|
||||
|
@ -301,6 +301,46 @@ struct ice_32b_rx_flex_desc_nic {
|
||||
} flex_ts;
|
||||
};
|
||||
|
||||
/* Rx Flex Descriptor NIC Profile
|
||||
* RxDID Profile ID 6
|
||||
* Flex-field 0: RSS hash lower 16-bits
|
||||
* Flex-field 1: RSS hash upper 16-bits
|
||||
* Flex-field 2: Flow ID lower 16-bits
|
||||
* Flex-field 3: Source VSI
|
||||
* Flex-field 4: reserved, VLAN ID taken from L2Tag
|
||||
*/
|
||||
struct ice_32b_rx_flex_desc_nic_2 {
|
||||
/* Qword 0 */
|
||||
u8 rxdid;
|
||||
u8 mir_id_umb_cast;
|
||||
__le16 ptype_flexi_flags0;
|
||||
__le16 pkt_len;
|
||||
__le16 hdr_len_sph_flex_flags1;
|
||||
|
||||
/* Qword 1 */
|
||||
__le16 status_error0;
|
||||
__le16 l2tag1;
|
||||
__le32 rss_hash;
|
||||
|
||||
/* Qword 2 */
|
||||
__le16 status_error1;
|
||||
u8 flexi_flags2;
|
||||
u8 ts_low;
|
||||
__le16 l2tag2_1st;
|
||||
__le16 l2tag2_2nd;
|
||||
|
||||
/* Qword 3 */
|
||||
__le16 flow_id;
|
||||
__le16 src_vsi;
|
||||
union {
|
||||
struct {
|
||||
__le16 rsvd;
|
||||
__le16 flow_id_ipv6;
|
||||
} flex;
|
||||
__le32 ts_high;
|
||||
} flex_ts;
|
||||
};
|
||||
|
||||
/* Receive Flex Descriptor profile IDs: There are a total
|
||||
* of 64 profiles where profile IDs 0/1 are for legacy; and
|
||||
* profiles 2-63 are flex profiles that can be programmed
|
||||
@ -529,6 +569,9 @@ struct ice_tx_ctx_desc {
|
||||
|
||||
#define ICE_TXD_CTX_QW1_MSS_S 50
|
||||
|
||||
#define ICE_TXD_CTX_QW1_VSI_S 50
|
||||
#define ICE_TXD_CTX_QW1_VSI_M (0x3FFULL << ICE_TXD_CTX_QW1_VSI_S)
|
||||
|
||||
enum ice_tx_ctx_desc_cmd_bits {
|
||||
ICE_TX_CTX_DESC_TSO = 0x01,
|
||||
ICE_TX_CTX_DESC_TSYN = 0x02,
|
||||
|
@ -24,6 +24,8 @@ const char *ice_vsi_type_str(enum ice_vsi_type vsi_type)
|
||||
return "ICE_VSI_CTRL";
|
||||
case ICE_VSI_LB:
|
||||
return "ICE_VSI_LB";
|
||||
case ICE_VSI_SWITCHDEV_CTRL:
|
||||
return "ICE_VSI_SWITCHDEV_CTRL";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
@ -132,6 +134,7 @@ static void ice_vsi_set_num_desc(struct ice_vsi *vsi)
|
||||
{
|
||||
switch (vsi->type) {
|
||||
case ICE_VSI_PF:
|
||||
case ICE_VSI_SWITCHDEV_CTRL:
|
||||
case ICE_VSI_CTRL:
|
||||
case ICE_VSI_LB:
|
||||
/* a user could change the values of num_[tr]x_desc using
|
||||
@ -200,6 +203,14 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id)
|
||||
max_t(int, vsi->alloc_rxq,
|
||||
vsi->alloc_txq));
|
||||
break;
|
||||
case ICE_VSI_SWITCHDEV_CTRL:
|
||||
/* The number of queues for ctrl VSI is equal to number of VFs.
|
||||
* Each ring is associated to the corresponding VF_PR netdev.
|
||||
*/
|
||||
vsi->alloc_txq = pf->num_alloc_vfs;
|
||||
vsi->alloc_rxq = pf->num_alloc_vfs;
|
||||
vsi->num_q_vectors = 1;
|
||||
break;
|
||||
case ICE_VSI_VF:
|
||||
vf = &pf->vf[vsi->vf_id];
|
||||
if (vf->num_req_qs)
|
||||
@ -408,6 +419,21 @@ static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t ice_eswitch_msix_clean_rings(int __always_unused irq, void *data)
|
||||
{
|
||||
struct ice_q_vector *q_vector = (struct ice_q_vector *)data;
|
||||
struct ice_pf *pf = q_vector->vsi->back;
|
||||
int i;
|
||||
|
||||
if (!q_vector->tx.ring && !q_vector->rx.ring)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
ice_for_each_vf(pf, i)
|
||||
napi_schedule(&pf->vf[i].repr->q_vector->napi);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_vsi_alloc - Allocates the next available struct VSI in the PF
|
||||
* @pf: board private structure
|
||||
@ -448,6 +474,13 @@ ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type vsi_type, u16 vf_id)
|
||||
ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID);
|
||||
|
||||
switch (vsi->type) {
|
||||
case ICE_VSI_SWITCHDEV_CTRL:
|
||||
if (ice_vsi_alloc_arrays(vsi))
|
||||
goto err_rings;
|
||||
|
||||
/* Setup eswitch MSIX irq handler for VSI */
|
||||
vsi->irq_handler = ice_eswitch_msix_clean_rings;
|
||||
break;
|
||||
case ICE_VSI_PF:
|
||||
if (ice_vsi_alloc_arrays(vsi))
|
||||
goto err_rings;
|
||||
@ -707,6 +740,12 @@ static void ice_vsi_set_rss_params(struct ice_vsi *vsi)
|
||||
BIT(cap->rss_table_entry_width));
|
||||
vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF;
|
||||
break;
|
||||
case ICE_VSI_SWITCHDEV_CTRL:
|
||||
vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE;
|
||||
vsi->rss_size = min_t(u16, num_online_cpus(),
|
||||
BIT(cap->rss_table_entry_width));
|
||||
vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI;
|
||||
break;
|
||||
case ICE_VSI_VF:
|
||||
/* VF VSI will get a small RSS table.
|
||||
* For VSI_LUT, LUT size should be set to 64 bytes.
|
||||
@ -980,6 +1019,9 @@ static int ice_vsi_init(struct ice_vsi *vsi, bool init_vsi)
|
||||
case ICE_VSI_PF:
|
||||
ctxt->flags = ICE_AQ_VSI_TYPE_PF;
|
||||
break;
|
||||
case ICE_VSI_SWITCHDEV_CTRL:
|
||||
ctxt->flags = ICE_AQ_VSI_TYPE_VMDQ2;
|
||||
break;
|
||||
case ICE_VSI_VF:
|
||||
ctxt->flags = ICE_AQ_VSI_TYPE_VF;
|
||||
/* VF number here is the absolute VF number (0-255) */
|
||||
@ -2297,6 +2339,7 @@ static void ice_set_agg_vsi(struct ice_vsi *vsi)
|
||||
case ICE_VSI_CTRL:
|
||||
case ICE_VSI_LB:
|
||||
case ICE_VSI_PF:
|
||||
case ICE_VSI_SWITCHDEV_CTRL:
|
||||
max_agg_nodes = ICE_MAX_PF_AGG_NODES;
|
||||
agg_node_id_start = ICE_PF_AGG_NODE_ID_START;
|
||||
agg_node_iter = &pf->pf_agg_node[0];
|
||||
@ -2448,6 +2491,7 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
|
||||
|
||||
switch (vsi->type) {
|
||||
case ICE_VSI_CTRL:
|
||||
case ICE_VSI_SWITCHDEV_CTRL:
|
||||
case ICE_VSI_PF:
|
||||
ret = ice_vsi_alloc_q_vectors(vsi);
|
||||
if (ret)
|
||||
@ -2757,7 +2801,8 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked)
|
||||
} else {
|
||||
ice_vsi_close(vsi);
|
||||
}
|
||||
} else if (vsi->type == ICE_VSI_CTRL) {
|
||||
} else if (vsi->type == ICE_VSI_CTRL ||
|
||||
vsi->type == ICE_VSI_SWITCHDEV_CTRL) {
|
||||
ice_vsi_close(vsi);
|
||||
}
|
||||
}
|
||||
@ -2860,7 +2905,8 @@ int ice_vsi_release(struct ice_vsi *vsi)
|
||||
clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
|
||||
}
|
||||
|
||||
ice_devlink_destroy_port(vsi);
|
||||
if (vsi->type == ICE_VSI_PF)
|
||||
ice_devlink_destroy_pf_port(pf);
|
||||
|
||||
if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
|
||||
ice_rss_clean(vsi);
|
||||
@ -3144,6 +3190,7 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
|
||||
|
||||
switch (vtype) {
|
||||
case ICE_VSI_CTRL:
|
||||
case ICE_VSI_SWITCHDEV_CTRL:
|
||||
case ICE_VSI_PF:
|
||||
ret = ice_vsi_alloc_q_vectors(vsi);
|
||||
if (ret)
|
||||
@ -3629,3 +3676,64 @@ void ice_init_feature_support(struct ice_pf *pf)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_vsi_update_security - update security block in VSI
|
||||
* @vsi: pointer to VSI structure
|
||||
* @fill: function pointer to fill ctx
|
||||
*/
|
||||
int
|
||||
ice_vsi_update_security(struct ice_vsi *vsi, void (*fill)(struct ice_vsi_ctx *))
|
||||
{
|
||||
struct ice_vsi_ctx ctx = { 0 };
|
||||
|
||||
ctx.info = vsi->info;
|
||||
ctx.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
|
||||
fill(&ctx);
|
||||
|
||||
if (ice_update_vsi(&vsi->back->hw, vsi->idx, &ctx, NULL))
|
||||
return -ENODEV;
|
||||
|
||||
vsi->info = ctx.info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_vsi_ctx_set_antispoof - set antispoof function in VSI ctx
|
||||
* @ctx: pointer to VSI ctx structure
|
||||
*/
|
||||
void ice_vsi_ctx_set_antispoof(struct ice_vsi_ctx *ctx)
|
||||
{
|
||||
ctx->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF |
|
||||
(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
|
||||
ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_vsi_ctx_clear_antispoof - clear antispoof function in VSI ctx
|
||||
* @ctx: pointer to VSI ctx structure
|
||||
*/
|
||||
void ice_vsi_ctx_clear_antispoof(struct ice_vsi_ctx *ctx)
|
||||
{
|
||||
ctx->info.sec_flags &= ~ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF &
|
||||
~(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
|
||||
ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_vsi_ctx_set_allow_override - allow destination override on VSI
|
||||
* @ctx: pointer to VSI ctx structure
|
||||
*/
|
||||
void ice_vsi_ctx_set_allow_override(struct ice_vsi_ctx *ctx)
|
||||
{
|
||||
ctx->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_vsi_ctx_clear_allow_override - turn off destination override on VSI
|
||||
* @ctx: pointer to VSI ctx structure
|
||||
*/
|
||||
void ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx)
|
||||
{
|
||||
ctx->info.sec_flags &= ~ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD;
|
||||
}
|
||||
|
@ -116,6 +116,18 @@ bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi);
|
||||
int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi);
|
||||
|
||||
int ice_clear_dflt_vsi(struct ice_sw *sw);
|
||||
|
||||
int
|
||||
ice_vsi_update_security(struct ice_vsi *vsi, void (*fill)(struct ice_vsi_ctx *));
|
||||
|
||||
void ice_vsi_ctx_set_antispoof(struct ice_vsi_ctx *ctx);
|
||||
|
||||
void ice_vsi_ctx_clear_antispoof(struct ice_vsi_ctx *ctx);
|
||||
|
||||
void ice_vsi_ctx_set_allow_override(struct ice_vsi_ctx *ctx);
|
||||
|
||||
void ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx);
|
||||
|
||||
bool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f);
|
||||
void ice_init_feature_support(struct ice_pf *pf);
|
||||
#endif /* !_ICE_LIB_H_ */
|
||||
|
@ -19,6 +19,7 @@
|
||||
*/
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "ice_trace.h"
|
||||
#include "ice_eswitch.h"
|
||||
|
||||
#define DRV_SUMMARY "Intel(R) Ethernet Connection E800 Series Linux Driver"
|
||||
static const char ice_driver_string[] = DRV_SUMMARY;
|
||||
@ -46,7 +47,6 @@ static DEFINE_IDA(ice_aux_ida);
|
||||
static struct workqueue_struct *ice_wq;
|
||||
static const struct net_device_ops ice_netdev_safe_mode_ops;
|
||||
static const struct net_device_ops ice_netdev_ops;
|
||||
static int ice_vsi_open(struct ice_vsi *vsi);
|
||||
|
||||
static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type);
|
||||
|
||||
@ -3542,6 +3542,13 @@ static int ice_ena_msix_range(struct ice_pf *pf)
|
||||
v_left -= needed;
|
||||
}
|
||||
|
||||
/* reserve for switchdev */
|
||||
needed = ICE_ESWITCH_MSIX;
|
||||
if (v_left < needed)
|
||||
goto no_hw_vecs_left_err;
|
||||
v_budget += needed;
|
||||
v_left -= needed;
|
||||
|
||||
/* total used for non-traffic vectors */
|
||||
v_other = v_budget;
|
||||
|
||||
@ -4174,11 +4181,11 @@ static int ice_register_netdev(struct ice_pf *pf)
|
||||
set_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
|
||||
netif_carrier_off(vsi->netdev);
|
||||
netif_tx_stop_all_queues(vsi->netdev);
|
||||
err = ice_devlink_create_port(vsi);
|
||||
err = ice_devlink_create_pf_port(pf);
|
||||
if (err)
|
||||
goto err_devlink_create;
|
||||
|
||||
devlink_port_type_eth_set(&vsi->devlink_port, vsi->netdev);
|
||||
devlink_port_type_eth_set(&pf->devlink_port, vsi->netdev);
|
||||
|
||||
return 0;
|
||||
err_devlink_create:
|
||||
@ -5992,9 +5999,11 @@ int ice_down(struct ice_vsi *vsi)
|
||||
/* Caller of this function is expected to set the
|
||||
* vsi->state ICE_DOWN bit
|
||||
*/
|
||||
if (vsi->netdev) {
|
||||
if (vsi->netdev && vsi->type == ICE_VSI_PF) {
|
||||
netif_carrier_off(vsi->netdev);
|
||||
netif_tx_disable(vsi->netdev);
|
||||
} else if (vsi->type == ICE_VSI_SWITCHDEV_CTRL) {
|
||||
ice_eswitch_stop_all_tx_queues(vsi->back);
|
||||
}
|
||||
|
||||
ice_vsi_dis_irq(vsi);
|
||||
@ -6061,7 +6070,8 @@ int ice_vsi_setup_tx_rings(struct ice_vsi *vsi)
|
||||
if (!ring)
|
||||
return -EINVAL;
|
||||
|
||||
ring->netdev = vsi->netdev;
|
||||
if (vsi->netdev)
|
||||
ring->netdev = vsi->netdev;
|
||||
err = ice_setup_tx_ring(ring);
|
||||
if (err)
|
||||
break;
|
||||
@ -6092,7 +6102,8 @@ int ice_vsi_setup_rx_rings(struct ice_vsi *vsi)
|
||||
if (!ring)
|
||||
return -EINVAL;
|
||||
|
||||
ring->netdev = vsi->netdev;
|
||||
if (vsi->netdev)
|
||||
ring->netdev = vsi->netdev;
|
||||
err = ice_setup_rx_ring(ring);
|
||||
if (err)
|
||||
break;
|
||||
@ -6165,7 +6176,7 @@ int ice_vsi_open_ctrl(struct ice_vsi *vsi)
|
||||
*
|
||||
* Returns 0 on success, negative value on error
|
||||
*/
|
||||
static int ice_vsi_open(struct ice_vsi *vsi)
|
||||
int ice_vsi_open(struct ice_vsi *vsi)
|
||||
{
|
||||
char int_name[ICE_INT_NAME_STR_LEN];
|
||||
struct ice_pf *pf = vsi->back;
|
||||
@ -6190,14 +6201,16 @@ static int ice_vsi_open(struct ice_vsi *vsi)
|
||||
if (err)
|
||||
goto err_setup_rx;
|
||||
|
||||
/* Notify the stack of the actual queue counts. */
|
||||
err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq);
|
||||
if (err)
|
||||
goto err_set_qs;
|
||||
if (vsi->type == ICE_VSI_PF) {
|
||||
/* Notify the stack of the actual queue counts. */
|
||||
err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq);
|
||||
if (err)
|
||||
goto err_set_qs;
|
||||
|
||||
err = netif_set_real_num_rx_queues(vsi->netdev, vsi->num_rxq);
|
||||
if (err)
|
||||
goto err_set_qs;
|
||||
err = netif_set_real_num_rx_queues(vsi->netdev, vsi->num_rxq);
|
||||
if (err)
|
||||
goto err_set_qs;
|
||||
}
|
||||
|
||||
err = ice_up_complete(vsi);
|
||||
if (err)
|
||||
@ -6436,6 +6449,12 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
|
||||
goto err_vsi_rebuild;
|
||||
}
|
||||
|
||||
err = ice_vsi_rebuild_by_type(pf, ICE_VSI_SWITCHDEV_CTRL);
|
||||
if (err) {
|
||||
dev_err(dev, "Switchdev CTRL VSI rebuild failed: %d\n", err);
|
||||
goto err_vsi_rebuild;
|
||||
}
|
||||
|
||||
/* If Flow Director is active */
|
||||
if (test_bit(ICE_FLAG_FD_ENA, pf->flags)) {
|
||||
err = ice_vsi_rebuild_by_type(pf, ICE_VSI_CTRL);
|
||||
|
333
drivers/net/ethernet/intel/ice/ice_repr.c
Normal file
333
drivers/net/ethernet/intel/ice/ice_repr.c
Normal file
@ -0,0 +1,333 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (C) 2019-2021, Intel Corporation. */
|
||||
|
||||
#include "ice.h"
|
||||
#include "ice_eswitch.h"
|
||||
#include "ice_devlink.h"
|
||||
#include "ice_virtchnl_pf.h"
|
||||
|
||||
/**
|
||||
* ice_repr_get_sw_port_id - get port ID associated with representor
|
||||
* @repr: pointer to port representor
|
||||
*/
|
||||
static int ice_repr_get_sw_port_id(struct ice_repr *repr)
|
||||
{
|
||||
return repr->vf->pf->hw.port_info->lport;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_get_phys_port_name - get phys port name
|
||||
* @netdev: pointer to port representor netdev
|
||||
* @buf: write here port name
|
||||
* @len: max length of buf
|
||||
*/
|
||||
static int
|
||||
ice_repr_get_phys_port_name(struct net_device *netdev, char *buf, size_t len)
|
||||
{
|
||||
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||
struct ice_repr *repr = np->repr;
|
||||
int res;
|
||||
|
||||
/* Devlink port is registered and devlink core is taking care of name formatting. */
|
||||
if (repr->vf->devlink_port.devlink)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
res = snprintf(buf, len, "pf%dvfr%d", ice_repr_get_sw_port_id(repr),
|
||||
repr->vf->vf_id);
|
||||
if (res <= 0)
|
||||
return -EOPNOTSUPP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_get_stats64 - get VF stats for VFPR use
|
||||
* @netdev: pointer to port representor netdev
|
||||
* @stats: pointer to struct where stats can be stored
|
||||
*/
|
||||
static void
|
||||
ice_repr_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||
struct ice_eth_stats *eth_stats;
|
||||
struct ice_vsi *vsi;
|
||||
|
||||
if (ice_is_vf_disabled(np->repr->vf))
|
||||
return;
|
||||
vsi = np->repr->src_vsi;
|
||||
|
||||
ice_update_vsi_stats(vsi);
|
||||
eth_stats = &vsi->eth_stats;
|
||||
|
||||
stats->tx_packets = eth_stats->tx_unicast + eth_stats->tx_broadcast +
|
||||
eth_stats->tx_multicast;
|
||||
stats->rx_packets = eth_stats->rx_unicast + eth_stats->rx_broadcast +
|
||||
eth_stats->rx_multicast;
|
||||
stats->tx_bytes = eth_stats->tx_bytes;
|
||||
stats->rx_bytes = eth_stats->rx_bytes;
|
||||
stats->multicast = eth_stats->rx_multicast;
|
||||
stats->tx_errors = eth_stats->tx_errors;
|
||||
stats->tx_dropped = eth_stats->tx_discards;
|
||||
stats->rx_dropped = eth_stats->rx_discards;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_netdev_to_repr - Get port representor for given netdevice
|
||||
* @netdev: pointer to port representor netdev
|
||||
*/
|
||||
struct ice_repr *ice_netdev_to_repr(struct net_device *netdev)
|
||||
{
|
||||
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||
|
||||
return np->repr;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_open - Enable port representor's network interface
|
||||
* @netdev: network interface device structure
|
||||
*
|
||||
* The open entry point is called when a port representor's network
|
||||
* interface is made active by the system (IFF_UP). Corresponding
|
||||
* VF is notified about link status change.
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
static int ice_repr_open(struct net_device *netdev)
|
||||
{
|
||||
struct ice_repr *repr = ice_netdev_to_repr(netdev);
|
||||
struct ice_vf *vf;
|
||||
|
||||
vf = repr->vf;
|
||||
vf->link_forced = true;
|
||||
vf->link_up = true;
|
||||
ice_vc_notify_vf_link_state(vf);
|
||||
|
||||
netif_carrier_on(netdev);
|
||||
netif_tx_start_all_queues(netdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_stop - Disable port representor's network interface
|
||||
* @netdev: network interface device structure
|
||||
*
|
||||
* The stop entry point is called when a port representor's network
|
||||
* interface is de-activated by the system. Corresponding
|
||||
* VF is notified about link status change.
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
static int ice_repr_stop(struct net_device *netdev)
|
||||
{
|
||||
struct ice_repr *repr = ice_netdev_to_repr(netdev);
|
||||
struct ice_vf *vf;
|
||||
|
||||
vf = repr->vf;
|
||||
vf->link_forced = true;
|
||||
vf->link_up = false;
|
||||
ice_vc_notify_vf_link_state(vf);
|
||||
|
||||
netif_carrier_off(netdev);
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct devlink_port *
|
||||
ice_repr_get_devlink_port(struct net_device *netdev)
|
||||
{
|
||||
struct ice_repr *repr = ice_netdev_to_repr(netdev);
|
||||
|
||||
return &repr->vf->devlink_port;
|
||||
}
|
||||
|
||||
static const struct net_device_ops ice_repr_netdev_ops = {
|
||||
.ndo_get_phys_port_name = ice_repr_get_phys_port_name,
|
||||
.ndo_get_stats64 = ice_repr_get_stats64,
|
||||
.ndo_open = ice_repr_open,
|
||||
.ndo_stop = ice_repr_stop,
|
||||
.ndo_start_xmit = ice_eswitch_port_start_xmit,
|
||||
.ndo_get_devlink_port = ice_repr_get_devlink_port,
|
||||
};
|
||||
|
||||
/**
|
||||
* ice_is_port_repr_netdev - Check if a given netdevice is a port representor netdev
|
||||
* @netdev: pointer to netdev
|
||||
*/
|
||||
bool ice_is_port_repr_netdev(struct net_device *netdev)
|
||||
{
|
||||
return netdev && (netdev->netdev_ops == &ice_repr_netdev_ops);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_reg_netdev - register port representor netdev
|
||||
* @netdev: pointer to port representor netdev
|
||||
*/
|
||||
static int
|
||||
ice_repr_reg_netdev(struct net_device *netdev)
|
||||
{
|
||||
eth_hw_addr_random(netdev);
|
||||
netdev->netdev_ops = &ice_repr_netdev_ops;
|
||||
ice_set_ethtool_repr_ops(netdev);
|
||||
|
||||
netif_carrier_off(netdev);
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
|
||||
return register_netdev(netdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_add - add representor for VF
|
||||
* @vf: pointer to VF structure
|
||||
*/
|
||||
static int ice_repr_add(struct ice_vf *vf)
|
||||
{
|
||||
struct ice_q_vector *q_vector;
|
||||
struct ice_netdev_priv *np;
|
||||
struct ice_repr *repr;
|
||||
int err;
|
||||
|
||||
repr = kzalloc(sizeof(*repr), GFP_KERNEL);
|
||||
if (!repr)
|
||||
return -ENOMEM;
|
||||
|
||||
repr->netdev = alloc_etherdev(sizeof(struct ice_netdev_priv));
|
||||
if (!repr->netdev) {
|
||||
err = -ENOMEM;
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
repr->src_vsi = ice_get_vf_vsi(vf);
|
||||
repr->vf = vf;
|
||||
vf->repr = repr;
|
||||
np = netdev_priv(repr->netdev);
|
||||
np->repr = repr;
|
||||
|
||||
q_vector = kzalloc(sizeof(*q_vector), GFP_KERNEL);
|
||||
if (!q_vector) {
|
||||
err = -ENOMEM;
|
||||
goto err_alloc_q_vector;
|
||||
}
|
||||
repr->q_vector = q_vector;
|
||||
|
||||
err = ice_devlink_create_vf_port(vf);
|
||||
if (err)
|
||||
goto err_devlink;
|
||||
|
||||
err = ice_repr_reg_netdev(repr->netdev);
|
||||
if (err)
|
||||
goto err_netdev;
|
||||
|
||||
devlink_port_type_eth_set(&vf->devlink_port, repr->netdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_netdev:
|
||||
ice_devlink_destroy_vf_port(vf);
|
||||
err_devlink:
|
||||
kfree(repr->q_vector);
|
||||
vf->repr->q_vector = NULL;
|
||||
err_alloc_q_vector:
|
||||
free_netdev(repr->netdev);
|
||||
repr->netdev = NULL;
|
||||
err_alloc:
|
||||
kfree(repr);
|
||||
vf->repr = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_rem - remove representor from VF
|
||||
* @vf: pointer to VF structure
|
||||
*/
|
||||
static void ice_repr_rem(struct ice_vf *vf)
|
||||
{
|
||||
ice_devlink_destroy_vf_port(vf);
|
||||
kfree(vf->repr->q_vector);
|
||||
vf->repr->q_vector = NULL;
|
||||
unregister_netdev(vf->repr->netdev);
|
||||
free_netdev(vf->repr->netdev);
|
||||
vf->repr->netdev = NULL;
|
||||
kfree(vf->repr);
|
||||
vf->repr = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_add_for_all_vfs - add port representor for all VFs
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
int ice_repr_add_for_all_vfs(struct ice_pf *pf)
|
||||
{
|
||||
int err;
|
||||
int i;
|
||||
|
||||
ice_for_each_vf(pf, i) {
|
||||
struct ice_vf *vf = &pf->vf[i];
|
||||
|
||||
err = ice_repr_add(vf);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
ice_vc_change_ops_to_repr(&vf->vc_ops);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
for (i = i - 1; i >= 0; i--) {
|
||||
struct ice_vf *vf = &pf->vf[i];
|
||||
|
||||
ice_repr_rem(vf);
|
||||
ice_vc_set_dflt_vf_ops(&vf->vc_ops);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_rem_from_all_vfs - remove port representor for all VFs
|
||||
* @pf: pointer to PF structure
|
||||
*/
|
||||
void ice_repr_rem_from_all_vfs(struct ice_pf *pf)
|
||||
{
|
||||
int i;
|
||||
|
||||
ice_for_each_vf(pf, i) {
|
||||
struct ice_vf *vf = &pf->vf[i];
|
||||
|
||||
ice_repr_rem(vf);
|
||||
ice_vc_set_dflt_vf_ops(&vf->vc_ops);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_start_tx_queues - start Tx queues of port representor
|
||||
* @repr: pointer to repr structure
|
||||
*/
|
||||
void ice_repr_start_tx_queues(struct ice_repr *repr)
|
||||
{
|
||||
netif_carrier_on(repr->netdev);
|
||||
netif_tx_start_all_queues(repr->netdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_stop_tx_queues - stop Tx queues of port representor
|
||||
* @repr: pointer to repr structure
|
||||
*/
|
||||
void ice_repr_stop_tx_queues(struct ice_repr *repr)
|
||||
{
|
||||
netif_carrier_off(repr->netdev);
|
||||
netif_tx_stop_all_queues(repr->netdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_repr_set_traffic_vsi - set traffic VSI for port representor
|
||||
* @repr: repr on with VSI will be set
|
||||
* @vsi: pointer to VSI that will be used by port representor to pass traffic
|
||||
*/
|
||||
void ice_repr_set_traffic_vsi(struct ice_repr *repr, struct ice_vsi *vsi)
|
||||
{
|
||||
struct ice_netdev_priv *np = netdev_priv(repr->netdev);
|
||||
|
||||
np->vsi = vsi;
|
||||
}
|
28
drivers/net/ethernet/intel/ice/ice_repr.h
Normal file
28
drivers/net/ethernet/intel/ice/ice_repr.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2019-2021, Intel Corporation. */
|
||||
|
||||
#ifndef _ICE_REPR_H_
|
||||
#define _ICE_REPR_H_
|
||||
|
||||
#include <net/dst_metadata.h>
|
||||
#include "ice.h"
|
||||
|
||||
struct ice_repr {
|
||||
struct ice_vsi *src_vsi;
|
||||
struct ice_vf *vf;
|
||||
struct ice_q_vector *q_vector;
|
||||
struct net_device *netdev;
|
||||
struct metadata_dst *dst;
|
||||
};
|
||||
|
||||
int ice_repr_add_for_all_vfs(struct ice_pf *pf);
|
||||
void ice_repr_rem_from_all_vfs(struct ice_pf *pf);
|
||||
|
||||
void ice_repr_start_tx_queues(struct ice_repr *repr);
|
||||
void ice_repr_stop_tx_queues(struct ice_repr *repr);
|
||||
|
||||
void ice_repr_set_traffic_vsi(struct ice_repr *repr, struct ice_vsi *vsi);
|
||||
|
||||
struct ice_repr *ice_netdev_to_repr(struct net_device *netdev);
|
||||
bool ice_is_port_repr_netdev(struct net_device *netdev);
|
||||
#endif
|
@ -518,7 +518,7 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
|
||||
*
|
||||
* Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
|
||||
*/
|
||||
static enum ice_status
|
||||
enum ice_status
|
||||
ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
|
||||
u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
|
||||
{
|
||||
|
@ -14,6 +14,9 @@
|
||||
#define ICE_VSI_INVAL_ID 0xffff
|
||||
#define ICE_INVAL_Q_HANDLE 0xFFFF
|
||||
|
||||
#define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \
|
||||
(offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr))
|
||||
|
||||
/* VSI context structure for add/get/update/free operations */
|
||||
struct ice_vsi_ctx {
|
||||
u16 vsi_num;
|
||||
@ -251,4 +254,7 @@ u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle);
|
||||
enum ice_status ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle);
|
||||
void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw);
|
||||
|
||||
enum ice_status
|
||||
ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
|
||||
u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd);
|
||||
#endif /* _ICE_SWITCH_H_ */
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "ice_trace.h"
|
||||
#include "ice_dcb_lib.h"
|
||||
#include "ice_xsk.h"
|
||||
#include "ice_eswitch.h"
|
||||
|
||||
#define ICE_RX_HDR_SIZE 256
|
||||
|
||||
@ -2246,6 +2247,8 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_ring *tx_ring)
|
||||
ICE_TXD_CTX_QW1_CMD_S);
|
||||
|
||||
ice_tstamp(tx_ring, skb, first, &offload);
|
||||
if (ice_is_switchdev_running(vsi->back))
|
||||
ice_eswitch_set_target_vsi(skb, &offload);
|
||||
|
||||
if (offload.cd_qw1 & ICE_TX_DESC_DTYPE_CTX) {
|
||||
struct ice_tx_ctx_desc *cdesc;
|
||||
|
@ -2,6 +2,7 @@
|
||||
/* Copyright (c) 2019, Intel Corporation. */
|
||||
|
||||
#include "ice_txrx_lib.h"
|
||||
#include "ice_eswitch.h"
|
||||
|
||||
/**
|
||||
* ice_release_rx_desc - Store the new tail and head values
|
||||
@ -185,7 +186,8 @@ ice_process_skb_fields(struct ice_ring *rx_ring,
|
||||
ice_rx_hash(rx_ring, rx_desc, skb, ptype);
|
||||
|
||||
/* modifies the skb - consumes the enet header */
|
||||
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
|
||||
skb->protocol = eth_type_trans(skb, ice_eswitch_get_target_netdev
|
||||
(rx_ring, rx_desc));
|
||||
|
||||
ice_rx_csum(rx_ring, skb, rx_desc, ptype);
|
||||
|
||||
|
@ -139,6 +139,7 @@ enum ice_vsi_type {
|
||||
ICE_VSI_VF = 1,
|
||||
ICE_VSI_CTRL = 3, /* equates to ICE_VSI_PF with 1 queue pair */
|
||||
ICE_VSI_LB = 6,
|
||||
ICE_VSI_SWITCHDEV_CTRL = 7,
|
||||
};
|
||||
|
||||
struct ice_link_status {
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "ice_lib.h"
|
||||
#include "ice_fltr.h"
|
||||
#include "ice_flow.h"
|
||||
#include "ice_eswitch.h"
|
||||
#include "ice_virtchnl_allowlist.h"
|
||||
|
||||
#define FIELD_SELECTOR(proto_hdr_field) \
|
||||
@ -251,7 +252,7 @@ ice_vc_hash_field_match_type ice_vc_hash_field_list_comms[] = {
|
||||
* ice_get_vf_vsi - get VF's VSI based on the stored index
|
||||
* @vf: VF used to get VSI
|
||||
*/
|
||||
static struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf)
|
||||
struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf)
|
||||
{
|
||||
return vf->pf->vsi[vf->lan_vsi_idx];
|
||||
}
|
||||
@ -412,7 +413,7 @@ static bool ice_is_vf_link_up(struct ice_vf *vf)
|
||||
*
|
||||
* send a link status message to a single VF
|
||||
*/
|
||||
static void ice_vc_notify_vf_link_state(struct ice_vf *vf)
|
||||
void ice_vc_notify_vf_link_state(struct ice_vf *vf)
|
||||
{
|
||||
struct virtchnl_pf_event pfe = { 0 };
|
||||
struct ice_hw *hw = &vf->pf->hw;
|
||||
@ -620,6 +621,8 @@ void ice_free_vfs(struct ice_pf *pf)
|
||||
if (!pf->vf)
|
||||
return;
|
||||
|
||||
ice_eswitch_release(pf);
|
||||
|
||||
while (test_and_set_bit(ICE_VF_DIS, pf->state))
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
@ -932,6 +935,9 @@ static int ice_vf_rebuild_host_mac_cfg(struct ice_vf *vf)
|
||||
enum ice_status status;
|
||||
u8 broadcast[ETH_ALEN];
|
||||
|
||||
if (ice_is_eswitch_mode_switchdev(vf->pf))
|
||||
return 0;
|
||||
|
||||
eth_broadcast_addr(broadcast);
|
||||
status = ice_fltr_add_mac(vsi, broadcast, ICE_FWD_TO_VSI);
|
||||
if (status) {
|
||||
@ -1581,6 +1587,10 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr)
|
||||
ice_vf_post_vsi_rebuild(vf);
|
||||
}
|
||||
|
||||
if (ice_is_eswitch_mode_switchdev(pf))
|
||||
if (ice_eswitch_rebuild(pf))
|
||||
dev_warn(dev, "eswitch rebuild failed\n");
|
||||
|
||||
ice_flush(hw);
|
||||
clear_bit(ICE_VF_DIS, pf->state);
|
||||
|
||||
@ -1593,7 +1603,7 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr)
|
||||
*
|
||||
* Returns true if the PF or VF is disabled, false otherwise.
|
||||
*/
|
||||
static bool ice_is_vf_disabled(struct ice_vf *vf)
|
||||
bool ice_is_vf_disabled(struct ice_vf *vf)
|
||||
{
|
||||
struct ice_pf *pf = vf->pf;
|
||||
|
||||
@ -1711,6 +1721,8 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
|
||||
}
|
||||
|
||||
ice_vf_post_vsi_rebuild(vf);
|
||||
vsi = ice_get_vf_vsi(vf);
|
||||
ice_eswitch_update_repr(vsi);
|
||||
|
||||
/* if the VF has been reset allow it to come up again */
|
||||
if (ice_mbx_clear_malvf(&hw->mbx_snapshot, pf->malvfs, ICE_MAX_VF_COUNT, vf->vf_id))
|
||||
@ -1894,6 +1906,8 @@ static void ice_set_dflt_settings_vfs(struct ice_pf *pf)
|
||||
*/
|
||||
ice_vf_ctrl_invalidate_vsi(vf);
|
||||
ice_vf_fdir_init(vf);
|
||||
|
||||
ice_vc_set_dflt_vf_ops(&vf->vc_ops);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1960,6 +1974,10 @@ static int ice_ena_vfs(struct ice_pf *pf, u16 num_vfs)
|
||||
}
|
||||
|
||||
clear_bit(ICE_VF_DIS, pf->state);
|
||||
|
||||
if (ice_eswitch_configure(pf))
|
||||
goto err_unroll_sriov;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unroll_sriov:
|
||||
@ -2823,7 +2841,7 @@ static void ice_wait_on_vf_reset(struct ice_vf *vf)
|
||||
* disabled, and initialized so it can be configured and/or queried by a host
|
||||
* administrator.
|
||||
*/
|
||||
static int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
|
||||
int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
|
||||
{
|
||||
struct ice_pf *pf;
|
||||
|
||||
@ -3801,6 +3819,26 @@ static bool ice_is_legacy_umac_expired(struct ice_time_mac *last_added_umac)
|
||||
ICE_LEGACY_VF_MAC_CHANGE_EXPIRE_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_update_legacy_cached_mac - update cached hardware MAC for legacy VF
|
||||
* @vf: VF to update
|
||||
* @vc_ether_addr: structure from VIRTCHNL with MAC to check
|
||||
*
|
||||
* only update cached hardware MAC for legacy VF drivers on delete
|
||||
* because we cannot guarantee order/type of MAC from the VF driver
|
||||
*/
|
||||
static void
|
||||
ice_update_legacy_cached_mac(struct ice_vf *vf,
|
||||
struct virtchnl_ether_addr *vc_ether_addr)
|
||||
{
|
||||
if (!ice_is_vc_addr_legacy(vc_ether_addr) ||
|
||||
ice_is_legacy_umac_expired(&vf->legacy_last_added_umac))
|
||||
return;
|
||||
|
||||
ether_addr_copy(vf->dev_lan_addr.addr, vf->legacy_last_added_umac.addr);
|
||||
ether_addr_copy(vf->hw_lan_addr.addr, vf->legacy_last_added_umac.addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_vfhw_mac_del - update the VF's cached hardware MAC if allowed
|
||||
* @vf: VF to update
|
||||
@ -3822,16 +3860,7 @@ ice_vfhw_mac_del(struct ice_vf *vf, struct virtchnl_ether_addr *vc_ether_addr)
|
||||
*/
|
||||
eth_zero_addr(vf->dev_lan_addr.addr);
|
||||
|
||||
/* only update cached hardware MAC for legacy VF drivers on delete
|
||||
* because we cannot guarantee order/type of MAC from the VF driver
|
||||
*/
|
||||
if (ice_is_vc_addr_legacy(vc_ether_addr) &&
|
||||
!ice_is_legacy_umac_expired(&vf->legacy_last_added_umac)) {
|
||||
ether_addr_copy(vf->dev_lan_addr.addr,
|
||||
vf->legacy_last_added_umac.addr);
|
||||
ether_addr_copy(vf->hw_lan_addr.addr,
|
||||
vf->legacy_last_added_umac.addr);
|
||||
}
|
||||
ice_update_legacy_cached_mac(vf, vc_ether_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4400,6 +4429,133 @@ static int ice_vf_init_vlan_stripping(struct ice_vf *vf)
|
||||
return ice_vsi_manage_vlan_stripping(vsi, false);
|
||||
}
|
||||
|
||||
static struct ice_vc_vf_ops ice_vc_vf_dflt_ops = {
|
||||
.get_ver_msg = ice_vc_get_ver_msg,
|
||||
.get_vf_res_msg = ice_vc_get_vf_res_msg,
|
||||
.reset_vf = ice_vc_reset_vf_msg,
|
||||
.add_mac_addr_msg = ice_vc_add_mac_addr_msg,
|
||||
.del_mac_addr_msg = ice_vc_del_mac_addr_msg,
|
||||
.cfg_qs_msg = ice_vc_cfg_qs_msg,
|
||||
.ena_qs_msg = ice_vc_ena_qs_msg,
|
||||
.dis_qs_msg = ice_vc_dis_qs_msg,
|
||||
.request_qs_msg = ice_vc_request_qs_msg,
|
||||
.cfg_irq_map_msg = ice_vc_cfg_irq_map_msg,
|
||||
.config_rss_key = ice_vc_config_rss_key,
|
||||
.config_rss_lut = ice_vc_config_rss_lut,
|
||||
.get_stats_msg = ice_vc_get_stats_msg,
|
||||
.cfg_promiscuous_mode_msg = ice_vc_cfg_promiscuous_mode_msg,
|
||||
.add_vlan_msg = ice_vc_add_vlan_msg,
|
||||
.remove_vlan_msg = ice_vc_remove_vlan_msg,
|
||||
.ena_vlan_stripping = ice_vc_ena_vlan_stripping,
|
||||
.dis_vlan_stripping = ice_vc_dis_vlan_stripping,
|
||||
.handle_rss_cfg_msg = ice_vc_handle_rss_cfg,
|
||||
.add_fdir_fltr_msg = ice_vc_add_fdir_fltr,
|
||||
.del_fdir_fltr_msg = ice_vc_del_fdir_fltr,
|
||||
};
|
||||
|
||||
void ice_vc_set_dflt_vf_ops(struct ice_vc_vf_ops *ops)
|
||||
{
|
||||
*ops = ice_vc_vf_dflt_ops;
|
||||
}
|
||||
|
||||
static int
|
||||
ice_vc_repr_no_action_msg(struct ice_vf __always_unused *vf,
|
||||
u8 __always_unused *msg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_vc_repr_add_mac
|
||||
* @vf: pointer to VF
|
||||
* @msg: virtchannel message
|
||||
*
|
||||
* When port representors are created, we do not add MAC rule
|
||||
* to firmware, we store it so that PF could report same
|
||||
* MAC as VF.
|
||||
*/
|
||||
static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg)
|
||||
{
|
||||
enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
|
||||
struct virtchnl_ether_addr_list *al =
|
||||
(struct virtchnl_ether_addr_list *)msg;
|
||||
struct ice_vsi *vsi;
|
||||
struct ice_pf *pf;
|
||||
int i;
|
||||
|
||||
if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) ||
|
||||
!ice_vc_isvalid_vsi_id(vf, al->vsi_id)) {
|
||||
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
|
||||
goto handle_mac_exit;
|
||||
}
|
||||
|
||||
pf = vf->pf;
|
||||
|
||||
vsi = ice_get_vf_vsi(vf);
|
||||
if (!vsi) {
|
||||
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
|
||||
goto handle_mac_exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < al->num_elements; i++) {
|
||||
u8 *mac_addr = al->list[i].addr;
|
||||
|
||||
if (!is_unicast_ether_addr(mac_addr) ||
|
||||
ether_addr_equal(mac_addr, vf->hw_lan_addr.addr))
|
||||
continue;
|
||||
|
||||
if (vf->pf_set_mac) {
|
||||
dev_err(ice_pf_to_dev(pf), "VF attempting to override administratively set MAC address\n");
|
||||
v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED;
|
||||
goto handle_mac_exit;
|
||||
}
|
||||
|
||||
ice_vfhw_mac_add(vf, &al->list[i]);
|
||||
vf->num_mac++;
|
||||
break;
|
||||
}
|
||||
|
||||
handle_mac_exit:
|
||||
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_ETH_ADDR,
|
||||
v_ret, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_vc_repr_del_mac - response with success for deleting MAC
|
||||
* @vf: pointer to VF
|
||||
* @msg: virtchannel message
|
||||
*
|
||||
* Respond with success to not break normal VF flow.
|
||||
* For legacy VF driver try to update cached MAC address.
|
||||
*/
|
||||
static int
|
||||
ice_vc_repr_del_mac(struct ice_vf __always_unused *vf, u8 __always_unused *msg)
|
||||
{
|
||||
struct virtchnl_ether_addr_list *al =
|
||||
(struct virtchnl_ether_addr_list *)msg;
|
||||
|
||||
ice_update_legacy_cached_mac(vf, &al->list[0]);
|
||||
|
||||
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR,
|
||||
VIRTCHNL_STATUS_SUCCESS, NULL, 0);
|
||||
}
|
||||
|
||||
static int ice_vc_repr_no_action(struct ice_vf __always_unused *vf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ice_vc_change_ops_to_repr(struct ice_vc_vf_ops *ops)
|
||||
{
|
||||
ops->add_mac_addr_msg = ice_vc_repr_add_mac;
|
||||
ops->del_mac_addr_msg = ice_vc_repr_del_mac;
|
||||
ops->add_vlan_msg = ice_vc_repr_no_action_msg;
|
||||
ops->remove_vlan_msg = ice_vc_repr_no_action_msg;
|
||||
ops->ena_vlan_stripping = ice_vc_repr_no_action;
|
||||
ops->dis_vlan_stripping = ice_vc_repr_no_action;
|
||||
ops->cfg_promiscuous_mode_msg = ice_vc_repr_no_action_msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_vc_process_vf_msg - Process request from VF
|
||||
* @pf: pointer to the PF structure
|
||||
@ -4413,6 +4569,7 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
|
||||
u32 v_opcode = le32_to_cpu(event->desc.cookie_high);
|
||||
s16 vf_id = le16_to_cpu(event->desc.retval);
|
||||
u16 msglen = event->msg_len;
|
||||
struct ice_vc_vf_ops *ops;
|
||||
u8 *msg = event->msg_buf;
|
||||
struct ice_vf *vf = NULL;
|
||||
struct device *dev;
|
||||
@ -4436,6 +4593,8 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
|
||||
goto error_handler;
|
||||
}
|
||||
|
||||
ops = &vf->vc_ops;
|
||||
|
||||
/* Perform basic checks on the msg */
|
||||
err = virtchnl_vc_validate_vf_msg(&vf->vf_ver, v_opcode, msg, msglen);
|
||||
if (err) {
|
||||
@ -4463,75 +4622,75 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
|
||||
|
||||
switch (v_opcode) {
|
||||
case VIRTCHNL_OP_VERSION:
|
||||
err = ice_vc_get_ver_msg(vf, msg);
|
||||
err = ops->get_ver_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_GET_VF_RESOURCES:
|
||||
err = ice_vc_get_vf_res_msg(vf, msg);
|
||||
err = ops->get_vf_res_msg(vf, msg);
|
||||
if (ice_vf_init_vlan_stripping(vf))
|
||||
dev_err(dev, "Failed to initialize VLAN stripping for VF %d\n",
|
||||
vf->vf_id);
|
||||
ice_vc_notify_vf_link_state(vf);
|
||||
break;
|
||||
case VIRTCHNL_OP_RESET_VF:
|
||||
ice_vc_reset_vf_msg(vf);
|
||||
ops->reset_vf(vf);
|
||||
break;
|
||||
case VIRTCHNL_OP_ADD_ETH_ADDR:
|
||||
err = ice_vc_add_mac_addr_msg(vf, msg);
|
||||
err = ops->add_mac_addr_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_DEL_ETH_ADDR:
|
||||
err = ice_vc_del_mac_addr_msg(vf, msg);
|
||||
err = ops->del_mac_addr_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
|
||||
err = ice_vc_cfg_qs_msg(vf, msg);
|
||||
err = ops->cfg_qs_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_ENABLE_QUEUES:
|
||||
err = ice_vc_ena_qs_msg(vf, msg);
|
||||
err = ops->ena_qs_msg(vf, msg);
|
||||
ice_vc_notify_vf_link_state(vf);
|
||||
break;
|
||||
case VIRTCHNL_OP_DISABLE_QUEUES:
|
||||
err = ice_vc_dis_qs_msg(vf, msg);
|
||||
err = ops->dis_qs_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_REQUEST_QUEUES:
|
||||
err = ice_vc_request_qs_msg(vf, msg);
|
||||
err = ops->request_qs_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_CONFIG_IRQ_MAP:
|
||||
err = ice_vc_cfg_irq_map_msg(vf, msg);
|
||||
err = ops->cfg_irq_map_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_CONFIG_RSS_KEY:
|
||||
err = ice_vc_config_rss_key(vf, msg);
|
||||
err = ops->config_rss_key(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_CONFIG_RSS_LUT:
|
||||
err = ice_vc_config_rss_lut(vf, msg);
|
||||
err = ops->config_rss_lut(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_GET_STATS:
|
||||
err = ice_vc_get_stats_msg(vf, msg);
|
||||
err = ops->get_stats_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
|
||||
err = ice_vc_cfg_promiscuous_mode_msg(vf, msg);
|
||||
err = ops->cfg_promiscuous_mode_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_ADD_VLAN:
|
||||
err = ice_vc_add_vlan_msg(vf, msg);
|
||||
err = ops->add_vlan_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_DEL_VLAN:
|
||||
err = ice_vc_remove_vlan_msg(vf, msg);
|
||||
err = ops->remove_vlan_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
|
||||
err = ice_vc_ena_vlan_stripping(vf);
|
||||
err = ops->ena_vlan_stripping(vf);
|
||||
break;
|
||||
case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
|
||||
err = ice_vc_dis_vlan_stripping(vf);
|
||||
err = ops->dis_vlan_stripping(vf);
|
||||
break;
|
||||
case VIRTCHNL_OP_ADD_FDIR_FILTER:
|
||||
err = ice_vc_add_fdir_fltr(vf, msg);
|
||||
err = ops->add_fdir_fltr_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_DEL_FDIR_FILTER:
|
||||
err = ice_vc_del_fdir_fltr(vf, msg);
|
||||
err = ops->del_fdir_fltr_msg(vf, msg);
|
||||
break;
|
||||
case VIRTCHNL_OP_ADD_RSS_CFG:
|
||||
err = ice_vc_handle_rss_cfg(vf, msg, true);
|
||||
err = ops->handle_rss_cfg_msg(vf, msg, true);
|
||||
break;
|
||||
case VIRTCHNL_OP_DEL_RSS_CFG:
|
||||
err = ice_vc_handle_rss_cfg(vf, msg, false);
|
||||
err = ops->handle_rss_cfg_msg(vf, msg, false);
|
||||
break;
|
||||
case VIRTCHNL_OP_UNKNOWN:
|
||||
default:
|
||||
@ -4640,6 +4799,11 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
|
||||
struct ice_vf *vf;
|
||||
int ret;
|
||||
|
||||
if (ice_is_eswitch_mode_switchdev(pf)) {
|
||||
dev_info(ice_pf_to_dev(pf), "Trusted VF is forbidden in switchdev mode\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (ice_validate_vf_id(pf, vf_id))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -70,6 +70,32 @@ struct ice_mdd_vf_events {
|
||||
u16 last_printed;
|
||||
};
|
||||
|
||||
struct ice_vf;
|
||||
|
||||
struct ice_vc_vf_ops {
|
||||
int (*get_ver_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*get_vf_res_msg)(struct ice_vf *vf, u8 *msg);
|
||||
void (*reset_vf)(struct ice_vf *vf);
|
||||
int (*add_mac_addr_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*del_mac_addr_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*cfg_qs_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*ena_qs_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*dis_qs_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*request_qs_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*cfg_irq_map_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*config_rss_key)(struct ice_vf *vf, u8 *msg);
|
||||
int (*config_rss_lut)(struct ice_vf *vf, u8 *msg);
|
||||
int (*get_stats_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*cfg_promiscuous_mode_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*add_vlan_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*remove_vlan_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*ena_vlan_stripping)(struct ice_vf *vf);
|
||||
int (*dis_vlan_stripping)(struct ice_vf *vf);
|
||||
int (*handle_rss_cfg_msg)(struct ice_vf *vf, u8 *msg, bool add);
|
||||
int (*add_fdir_fltr_msg)(struct ice_vf *vf, u8 *msg);
|
||||
int (*del_fdir_fltr_msg)(struct ice_vf *vf, u8 *msg);
|
||||
};
|
||||
|
||||
/* VF information structure */
|
||||
struct ice_vf {
|
||||
struct ice_pf *pf;
|
||||
@ -111,9 +137,17 @@ struct ice_vf {
|
||||
struct ice_mdd_vf_events mdd_rx_events;
|
||||
struct ice_mdd_vf_events mdd_tx_events;
|
||||
DECLARE_BITMAP(opcodes_allowlist, VIRTCHNL_OP_MAX);
|
||||
|
||||
struct ice_repr *repr;
|
||||
|
||||
struct ice_vc_vf_ops vc_ops;
|
||||
|
||||
/* devlink port data */
|
||||
struct devlink_port devlink_port;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf);
|
||||
void ice_process_vflr_event(struct ice_pf *pf);
|
||||
int ice_sriov_configure(struct pci_dev *pdev, int num_vfs);
|
||||
int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac);
|
||||
@ -124,6 +158,9 @@ void ice_free_vfs(struct ice_pf *pf);
|
||||
void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event);
|
||||
void ice_vc_notify_link_state(struct ice_pf *pf);
|
||||
void ice_vc_notify_reset(struct ice_pf *pf);
|
||||
void ice_vc_notify_vf_link_state(struct ice_vf *vf);
|
||||
void ice_vc_change_ops_to_repr(struct ice_vc_vf_ops *ops);
|
||||
void ice_vc_set_dflt_vf_ops(struct ice_vc_vf_ops *ops);
|
||||
bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr);
|
||||
bool ice_reset_vf(struct ice_vf *vf, bool is_vflr);
|
||||
void ice_restore_all_vfs_msi_state(struct pci_dev *pdev);
|
||||
@ -139,6 +176,10 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted);
|
||||
|
||||
int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state);
|
||||
|
||||
int ice_check_vf_ready_for_cfg(struct ice_vf *vf);
|
||||
|
||||
bool ice_is_vf_disabled(struct ice_vf *vf);
|
||||
|
||||
int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena);
|
||||
|
||||
int ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector);
|
||||
@ -164,6 +205,9 @@ static inline
|
||||
void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event) { }
|
||||
static inline void ice_vc_notify_link_state(struct ice_pf *pf) { }
|
||||
static inline void ice_vc_notify_reset(struct ice_pf *pf) { }
|
||||
static inline void ice_vc_notify_vf_link_state(struct ice_vf *vf) { }
|
||||
static inline void ice_vc_change_ops_to_repr(struct ice_vc_vf_ops *ops) { }
|
||||
static inline void ice_vc_set_dflt_vf_ops(struct ice_vc_vf_ops *ops) { }
|
||||
static inline void ice_set_vf_state_qs_dis(struct ice_vf *vf) { }
|
||||
static inline
|
||||
void ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event) { }
|
||||
@ -171,6 +215,21 @@ static inline void ice_print_vfs_mdd_events(struct ice_pf *pf) { }
|
||||
static inline void ice_print_vf_rx_mdd_event(struct ice_vf *vf) { }
|
||||
static inline void ice_restore_all_vfs_msi_state(struct pci_dev *pdev) { }
|
||||
|
||||
static inline int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline bool ice_is_vf_disabled(struct ice_vf *vf)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline struct ice_vsi *ice_get_vf_vsi(struct ice_vf *vf)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ice_is_malicious_vf(struct ice_pf __always_unused *pf,
|
||||
struct ice_rq_event_info __always_unused *event,
|
||||
|
@ -1298,7 +1298,7 @@ static int korina_probe(struct platform_device *pdev)
|
||||
|
||||
if (mac_addr)
|
||||
eth_hw_addr_set(dev, mac_addr);
|
||||
else if (of_get_mac_address(pdev->dev.of_node, dev->dev_addr) < 0)
|
||||
else if (of_get_ethdev_address(pdev->dev.of_node, dev) < 0)
|
||||
eth_hw_addr_random(dev);
|
||||
|
||||
clk = devm_clk_get_optional(&pdev->dev, "mdioclk");
|
||||
|
@ -527,7 +527,7 @@ static int xrx200_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(priv->clk);
|
||||
}
|
||||
|
||||
err = of_get_mac_address(np, net_dev->dev_addr);
|
||||
err = of_get_ethdev_address(np, net_dev);
|
||||
if (err)
|
||||
eth_hw_addr_random(net_dev);
|
||||
|
||||
|
@ -17,7 +17,7 @@ if NET_VENDOR_LITEX
|
||||
|
||||
config LITEX_LITEETH
|
||||
tristate "LiteX Ethernet support"
|
||||
depends on OF_NET
|
||||
depends on OF
|
||||
help
|
||||
If you wish to compile a kernel for hardware with a LiteX LiteEth
|
||||
device then you should answer Y to this.
|
||||
|
@ -266,7 +266,7 @@ static int liteeth_probe(struct platform_device *pdev)
|
||||
priv->tx_base = buf_base + priv->num_rx_slots * priv->slot_size;
|
||||
priv->tx_slot = 0;
|
||||
|
||||
err = of_get_mac_address(pdev->dev.of_node, netdev->dev_addr);
|
||||
err = of_get_ethdev_address(pdev->dev.of_node, netdev);
|
||||
if (err)
|
||||
eth_hw_addr_random(netdev);
|
||||
|
||||
|
@ -5242,7 +5242,7 @@ static int mvneta_probe(struct platform_device *pdev)
|
||||
goto err_free_ports;
|
||||
}
|
||||
|
||||
err = of_get_mac_address(dn, dev->dev_addr);
|
||||
err = of_get_ethdev_address(dn, dev);
|
||||
if (!err) {
|
||||
mac_from = "device tree";
|
||||
} else {
|
||||
|
@ -6081,7 +6081,7 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
|
||||
char hw_mac_addr[ETH_ALEN] = {0};
|
||||
char fw_mac_addr[ETH_ALEN];
|
||||
|
||||
if (fwnode_get_mac_address(fwnode, fw_mac_addr, ETH_ALEN)) {
|
||||
if (!fwnode_get_mac_address(fwnode, fw_mac_addr)) {
|
||||
*mac_from = "firmware node";
|
||||
eth_hw_addr_set(dev, fw_mac_addr);
|
||||
return;
|
||||
|
@ -1434,7 +1434,7 @@ static int pxa168_eth_probe(struct platform_device *pdev)
|
||||
|
||||
INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task);
|
||||
|
||||
err = of_get_mac_address(pdev->dev.of_node, dev->dev_addr);
|
||||
err = of_get_ethdev_address(pdev->dev.of_node, dev);
|
||||
if (err) {
|
||||
/* try reading the mac address, if set by the bootloader */
|
||||
pxa168_eth_get_mac_address(dev, dev->dev_addr);
|
||||
|
@ -4720,7 +4720,7 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
|
||||
* 1) from device tree data
|
||||
* 2) from internal registers set by bootloader
|
||||
*/
|
||||
ret = of_get_mac_address(hw->pdev->dev.of_node, dev->dev_addr);
|
||||
ret = of_get_ethdev_address(hw->pdev->dev.of_node, dev);
|
||||
if (ret)
|
||||
memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8,
|
||||
ETH_ALEN);
|
||||
|
@ -2588,7 +2588,7 @@ static int __init mtk_init(struct net_device *dev)
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
int ret;
|
||||
|
||||
ret = of_get_mac_address(mac->of_node, dev->dev_addr);
|
||||
ret = of_get_ethdev_address(mac->of_node, dev);
|
||||
if (ret) {
|
||||
/* If the mac address is invalid, use random mac address */
|
||||
eth_hw_addr_random(dev);
|
||||
|
@ -17,6 +17,7 @@ struct mlxsw_env_module_info {
|
||||
bool is_overheat;
|
||||
int num_ports_mapped;
|
||||
int num_ports_up;
|
||||
enum ethtool_module_power_mode_policy power_mode_policy;
|
||||
};
|
||||
|
||||
struct mlxsw_env {
|
||||
@ -445,6 +446,152 @@ int mlxsw_env_reset_module(struct net_device *netdev,
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_reset_module);
|
||||
|
||||
int
|
||||
mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module,
|
||||
struct ethtool_module_power_mode_params *params,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
char mcion_pl[MLXSW_REG_MCION_LEN];
|
||||
u32 status_bits;
|
||||
int err;
|
||||
|
||||
if (WARN_ON_ONCE(module >= mlxsw_env->module_count))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
|
||||
params->policy = mlxsw_env->module_info[module].power_mode_policy;
|
||||
|
||||
mlxsw_reg_mcion_pack(mcion_pl, module);
|
||||
err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcion), mcion_pl);
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Failed to retrieve module's power mode");
|
||||
goto out;
|
||||
}
|
||||
|
||||
status_bits = mlxsw_reg_mcion_module_status_bits_get(mcion_pl);
|
||||
if (!(status_bits & MLXSW_REG_MCION_MODULE_STATUS_BITS_PRESENT_MASK))
|
||||
goto out;
|
||||
|
||||
if (status_bits & MLXSW_REG_MCION_MODULE_STATUS_BITS_LOW_POWER_MASK)
|
||||
params->mode = ETHTOOL_MODULE_POWER_MODE_LOW;
|
||||
else
|
||||
params->mode = ETHTOOL_MODULE_POWER_MODE_HIGH;
|
||||
|
||||
out:
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_get_module_power_mode);
|
||||
|
||||
static int mlxsw_env_module_enable_set(struct mlxsw_core *mlxsw_core,
|
||||
u8 module, bool enable)
|
||||
{
|
||||
enum mlxsw_reg_pmaos_admin_status admin_status;
|
||||
char pmaos_pl[MLXSW_REG_PMAOS_LEN];
|
||||
|
||||
mlxsw_reg_pmaos_pack(pmaos_pl, module);
|
||||
admin_status = enable ? MLXSW_REG_PMAOS_ADMIN_STATUS_ENABLED :
|
||||
MLXSW_REG_PMAOS_ADMIN_STATUS_DISABLED;
|
||||
mlxsw_reg_pmaos_admin_status_set(pmaos_pl, admin_status);
|
||||
mlxsw_reg_pmaos_ase_set(pmaos_pl, true);
|
||||
|
||||
return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl);
|
||||
}
|
||||
|
||||
static int mlxsw_env_module_low_power_set(struct mlxsw_core *mlxsw_core,
|
||||
u8 module, bool low_power)
|
||||
{
|
||||
u16 eeprom_override_mask, eeprom_override;
|
||||
char pmmp_pl[MLXSW_REG_PMMP_LEN];
|
||||
|
||||
mlxsw_reg_pmmp_pack(pmmp_pl, module);
|
||||
mlxsw_reg_pmmp_sticky_set(pmmp_pl, true);
|
||||
/* Mask all the bits except low power mode. */
|
||||
eeprom_override_mask = ~MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK;
|
||||
mlxsw_reg_pmmp_eeprom_override_mask_set(pmmp_pl, eeprom_override_mask);
|
||||
eeprom_override = low_power ? MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK :
|
||||
0;
|
||||
mlxsw_reg_pmmp_eeprom_override_set(pmmp_pl, eeprom_override);
|
||||
|
||||
return mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmmp), pmmp_pl);
|
||||
}
|
||||
|
||||
static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core,
|
||||
u8 module, bool low_power,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mlxsw_env_module_enable_set(mlxsw_core, module, false);
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Failed to disable module");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mlxsw_env_module_low_power_set(mlxsw_core, module, low_power);
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Failed to set module's power mode");
|
||||
goto err_module_low_power_set;
|
||||
}
|
||||
|
||||
err = mlxsw_env_module_enable_set(mlxsw_core, module, true);
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Failed to enable module");
|
||||
goto err_module_enable_set;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_module_enable_set:
|
||||
mlxsw_env_module_low_power_set(mlxsw_core, module, !low_power);
|
||||
err_module_low_power_set:
|
||||
mlxsw_env_module_enable_set(mlxsw_core, module, true);
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module,
|
||||
enum ethtool_module_power_mode_policy policy,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
bool low_power;
|
||||
int err = 0;
|
||||
|
||||
if (WARN_ON_ONCE(module >= mlxsw_env->module_count))
|
||||
return -EINVAL;
|
||||
|
||||
if (policy != ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH &&
|
||||
policy != ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unsupported power mode policy");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
|
||||
if (mlxsw_env->module_info[module].power_mode_policy == policy)
|
||||
goto out;
|
||||
|
||||
/* If any ports are up, we are already in high power mode. */
|
||||
if (mlxsw_env->module_info[module].num_ports_up)
|
||||
goto out_set_policy;
|
||||
|
||||
low_power = policy == ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO;
|
||||
err = __mlxsw_env_set_module_power_mode(mlxsw_core, module, low_power,
|
||||
extack);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
out_set_policy:
|
||||
mlxsw_env->module_info[module].power_mode_policy = policy;
|
||||
out:
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_set_module_power_mode);
|
||||
|
||||
static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core,
|
||||
u8 module,
|
||||
bool *p_has_temp_sensor)
|
||||
@ -794,15 +941,33 @@ EXPORT_SYMBOL(mlxsw_env_module_port_unmap);
|
||||
int mlxsw_env_module_port_up(struct mlxsw_core *mlxsw_core, u8 module)
|
||||
{
|
||||
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
|
||||
int err = 0;
|
||||
|
||||
if (WARN_ON_ONCE(module >= mlxsw_env->module_count))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
mlxsw_env->module_info[module].num_ports_up++;
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
|
||||
return 0;
|
||||
if (mlxsw_env->module_info[module].power_mode_policy !=
|
||||
ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO)
|
||||
goto out_inc;
|
||||
|
||||
if (mlxsw_env->module_info[module].num_ports_up != 0)
|
||||
goto out_inc;
|
||||
|
||||
/* Transition to high power mode following first port using the module
|
||||
* being put administratively up.
|
||||
*/
|
||||
err = __mlxsw_env_set_module_power_mode(mlxsw_core, module, false,
|
||||
NULL);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
out_inc:
|
||||
mlxsw_env->module_info[module].num_ports_up++;
|
||||
out_unlock:
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_module_port_up);
|
||||
|
||||
@ -814,7 +979,22 @@ void mlxsw_env_module_port_down(struct mlxsw_core *mlxsw_core, u8 module)
|
||||
return;
|
||||
|
||||
mutex_lock(&mlxsw_env->module_info_lock);
|
||||
|
||||
mlxsw_env->module_info[module].num_ports_up--;
|
||||
|
||||
if (mlxsw_env->module_info[module].power_mode_policy !=
|
||||
ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO)
|
||||
goto out_unlock;
|
||||
|
||||
if (mlxsw_env->module_info[module].num_ports_up != 0)
|
||||
goto out_unlock;
|
||||
|
||||
/* Transition to low power mode following last port using the module
|
||||
* being put administratively down.
|
||||
*/
|
||||
__mlxsw_env_set_module_power_mode(mlxsw_core, module, true, NULL);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&mlxsw_env->module_info_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_env_module_port_down);
|
||||
@ -824,7 +1004,7 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env)
|
||||
char mgpir_pl[MLXSW_REG_MGPIR_LEN];
|
||||
struct mlxsw_env *env;
|
||||
u8 module_count;
|
||||
int err;
|
||||
int i, err;
|
||||
|
||||
mlxsw_reg_mgpir_pack(mgpir_pl);
|
||||
err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mgpir), mgpir_pl);
|
||||
@ -837,6 +1017,13 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env)
|
||||
if (!env)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Firmware defaults to high power mode policy where modules are
|
||||
* transitioned to high power mode following plug-in.
|
||||
*/
|
||||
for (i = 0; i < module_count; i++)
|
||||
env->module_info[i].power_mode_policy =
|
||||
ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH;
|
||||
|
||||
mutex_init(&env->module_info_lock);
|
||||
env->core = mlxsw_core;
|
||||
env->module_count = module_count;
|
||||
|
@ -28,6 +28,16 @@ int mlxsw_env_reset_module(struct net_device *netdev,
|
||||
struct mlxsw_core *mlxsw_core, u8 module,
|
||||
u32 *flags);
|
||||
|
||||
int
|
||||
mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module,
|
||||
struct ethtool_module_power_mode_params *params,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
int
|
||||
mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core, u8 module,
|
||||
enum ethtool_module_power_mode_policy policy,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
int
|
||||
mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module,
|
||||
u64 *p_counter);
|
||||
|
@ -145,12 +145,38 @@ static int mlxsw_m_reset(struct net_device *netdev, u32 *flags)
|
||||
flags);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_m_get_module_power_mode(struct net_device *netdev,
|
||||
struct ethtool_module_power_mode_params *params,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
|
||||
struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
|
||||
|
||||
return mlxsw_env_get_module_power_mode(core, mlxsw_m_port->module,
|
||||
params, extack);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_m_set_module_power_mode(struct net_device *netdev,
|
||||
const struct ethtool_module_power_mode_params *params,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
|
||||
struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
|
||||
|
||||
return mlxsw_env_set_module_power_mode(core, mlxsw_m_port->module,
|
||||
params->policy, extack);
|
||||
}
|
||||
|
||||
static const struct ethtool_ops mlxsw_m_port_ethtool_ops = {
|
||||
.get_drvinfo = mlxsw_m_module_get_drvinfo,
|
||||
.get_module_info = mlxsw_m_get_module_info,
|
||||
.get_module_eeprom = mlxsw_m_get_module_eeprom,
|
||||
.get_module_eeprom_by_page = mlxsw_m_get_module_eeprom_by_page,
|
||||
.reset = mlxsw_m_reset,
|
||||
.get_module_power_mode = mlxsw_m_get_module_power_mode,
|
||||
.set_module_power_mode = mlxsw_m_set_module_power_mode,
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -5946,6 +5946,55 @@ static inline void mlxsw_reg_pddr_pack(char *payload, u8 local_port,
|
||||
mlxsw_reg_pddr_page_select_set(payload, page_select);
|
||||
}
|
||||
|
||||
/* PMMP - Port Module Memory Map Properties Register
|
||||
* -------------------------------------------------
|
||||
* The PMMP register allows to override the module memory map advertisement.
|
||||
* The register can only be set when the module is disabled by PMAOS register.
|
||||
*/
|
||||
#define MLXSW_REG_PMMP_ID 0x5044
|
||||
#define MLXSW_REG_PMMP_LEN 0x2C
|
||||
|
||||
MLXSW_REG_DEFINE(pmmp, MLXSW_REG_PMMP_ID, MLXSW_REG_PMMP_LEN);
|
||||
|
||||
/* reg_pmmp_module
|
||||
* Module number.
|
||||
* Access: Index
|
||||
*/
|
||||
MLXSW_ITEM32(reg, pmmp, module, 0x00, 16, 8);
|
||||
|
||||
/* reg_pmmp_sticky
|
||||
* When set, will keep eeprom_override values after plug-out event.
|
||||
* Access: OP
|
||||
*/
|
||||
MLXSW_ITEM32(reg, pmmp, sticky, 0x00, 0, 1);
|
||||
|
||||
/* reg_pmmp_eeprom_override_mask
|
||||
* Write mask bit (negative polarity).
|
||||
* 0 - Allow write
|
||||
* 1 - Ignore write
|
||||
* On write, indicates which of the bits from eeprom_override field are
|
||||
* updated.
|
||||
* Access: WO
|
||||
*/
|
||||
MLXSW_ITEM32(reg, pmmp, eeprom_override_mask, 0x04, 16, 16);
|
||||
|
||||
enum {
|
||||
/* Set module to low power mode */
|
||||
MLXSW_REG_PMMP_EEPROM_OVERRIDE_LOW_POWER_MASK = BIT(8),
|
||||
};
|
||||
|
||||
/* reg_pmmp_eeprom_override
|
||||
* Override / ignore EEPROM advertisement properties bitmask
|
||||
* Access: RW
|
||||
*/
|
||||
MLXSW_ITEM32(reg, pmmp, eeprom_override, 0x04, 0, 16);
|
||||
|
||||
static inline void mlxsw_reg_pmmp_pack(char *payload, u8 module)
|
||||
{
|
||||
MLXSW_REG_ZERO(pmmp, payload);
|
||||
mlxsw_reg_pmmp_module_set(payload, module);
|
||||
}
|
||||
|
||||
/* PLLP - Port Local port to Label Port mapping Register
|
||||
* -----------------------------------------------------
|
||||
* The PLLP register returns the mapping from Local Port into Label Port.
|
||||
@ -10353,6 +10402,39 @@ static inline void mlxsw_reg_mlcr_pack(char *payload, u8 local_port,
|
||||
MLXSW_REG_MLCR_DURATION_MAX : 0);
|
||||
}
|
||||
|
||||
/* MCION - Management Cable IO and Notifications Register
|
||||
* ------------------------------------------------------
|
||||
* The MCION register is used to query transceiver modules' IO pins and other
|
||||
* notifications.
|
||||
*/
|
||||
#define MLXSW_REG_MCION_ID 0x9052
|
||||
#define MLXSW_REG_MCION_LEN 0x18
|
||||
|
||||
MLXSW_REG_DEFINE(mcion, MLXSW_REG_MCION_ID, MLXSW_REG_MCION_LEN);
|
||||
|
||||
/* reg_mcion_module
|
||||
* Module number.
|
||||
* Access: Index
|
||||
*/
|
||||
MLXSW_ITEM32(reg, mcion, module, 0x00, 16, 8);
|
||||
|
||||
enum {
|
||||
MLXSW_REG_MCION_MODULE_STATUS_BITS_PRESENT_MASK = BIT(0),
|
||||
MLXSW_REG_MCION_MODULE_STATUS_BITS_LOW_POWER_MASK = BIT(8),
|
||||
};
|
||||
|
||||
/* reg_mcion_module_status_bits
|
||||
* Module IO status as defined by SFF.
|
||||
* Access: RO
|
||||
*/
|
||||
MLXSW_ITEM32(reg, mcion, module_status_bits, 0x04, 0, 16);
|
||||
|
||||
static inline void mlxsw_reg_mcion_pack(char *payload, u8 module)
|
||||
{
|
||||
MLXSW_REG_ZERO(mcion, payload);
|
||||
mlxsw_reg_mcion_module_set(payload, module);
|
||||
}
|
||||
|
||||
/* MTPPS - Management Pulse Per Second Register
|
||||
* --------------------------------------------
|
||||
* This register provides the device PPS capabilities, configure the PPS in and
|
||||
@ -12348,6 +12430,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
|
||||
MLXSW_REG(pmtdb),
|
||||
MLXSW_REG(pmpe),
|
||||
MLXSW_REG(pddr),
|
||||
MLXSW_REG(pmmp),
|
||||
MLXSW_REG(pllp),
|
||||
MLXSW_REG(htgt),
|
||||
MLXSW_REG(hpkt),
|
||||
@ -12396,6 +12479,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
|
||||
MLXSW_REG(mgir),
|
||||
MLXSW_REG(mrsr),
|
||||
MLXSW_REG(mlcr),
|
||||
MLXSW_REG(mcion),
|
||||
MLXSW_REG(mtpps),
|
||||
MLXSW_REG(mtutc),
|
||||
MLXSW_REG(mpsc),
|
||||
|
@ -1583,7 +1583,7 @@ int mlxsw_sp_sb_occ_snapshot(struct mlxsw_core *mlxsw_core,
|
||||
{
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
|
||||
struct mlxsw_sp_sb_sr_occ_query_cb_ctx cb_ctx;
|
||||
unsigned long cb_priv;
|
||||
unsigned long cb_priv = 0;
|
||||
LIST_HEAD(bulk_list);
|
||||
char *sbsr_pl;
|
||||
u8 masked_count;
|
||||
|
@ -96,6 +96,9 @@ mlxsw_sp_link_ext_state_opcode_map[] = {
|
||||
{1032, ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED, 0},
|
||||
|
||||
{1030, ETHTOOL_LINK_EXT_STATE_OVERHEAT, 0},
|
||||
|
||||
{1042, ETHTOOL_LINK_EXT_STATE_MODULE,
|
||||
ETHTOOL_LINK_EXT_SUBSTATE_MODULE_CMIS_NOT_READY},
|
||||
};
|
||||
|
||||
static void
|
||||
@ -124,6 +127,10 @@ mlxsw_sp_port_set_link_ext_state(struct mlxsw_sp_ethtool_link_ext_state_opcode_m
|
||||
link_ext_state_info->cable_issue =
|
||||
link_ext_state_mapping.link_ext_substate;
|
||||
break;
|
||||
case ETHTOOL_LINK_EXT_STATE_MODULE:
|
||||
link_ext_state_info->module =
|
||||
link_ext_state_mapping.link_ext_substate;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1206,6 +1213,32 @@ static int mlxsw_sp_reset(struct net_device *dev, u32 *flags)
|
||||
return mlxsw_env_reset_module(dev, mlxsw_sp->core, module, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_get_module_power_mode(struct net_device *dev,
|
||||
struct ethtool_module_power_mode_params *params,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
||||
u8 module = mlxsw_sp_port->mapping.module;
|
||||
|
||||
return mlxsw_env_get_module_power_mode(mlxsw_sp->core, module, params,
|
||||
extack);
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_sp_set_module_power_mode(struct net_device *dev,
|
||||
const struct ethtool_module_power_mode_params *params,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
|
||||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
||||
u8 module = mlxsw_sp_port->mapping.module;
|
||||
|
||||
return mlxsw_env_set_module_power_mode(mlxsw_sp->core, module,
|
||||
params->policy, extack);
|
||||
}
|
||||
|
||||
const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
|
||||
.cap_link_lanes_supported = true,
|
||||
.get_drvinfo = mlxsw_sp_port_get_drvinfo,
|
||||
@ -1228,6 +1261,8 @@ const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
|
||||
.get_eth_ctrl_stats = mlxsw_sp_get_eth_ctrl_stats,
|
||||
.get_rmon_stats = mlxsw_sp_get_rmon_stats,
|
||||
.reset = mlxsw_sp_reset,
|
||||
.get_module_power_mode = mlxsw_sp_get_module_power_mode,
|
||||
.set_module_power_mode = mlxsw_sp_set_module_power_mode,
|
||||
};
|
||||
|
||||
struct mlxsw_sp1_port_link_mode {
|
||||
|
@ -195,7 +195,7 @@ static void ks8851_init_mac(struct ks8851_net *ks, struct device_node *np)
|
||||
struct net_device *dev = ks->netdev;
|
||||
int ret;
|
||||
|
||||
ret = of_get_mac_address(np, dev->dev_addr);
|
||||
ret = of_get_ethdev_address(np, dev);
|
||||
if (!ret) {
|
||||
ks8851_write_mac_addr(dev);
|
||||
return;
|
||||
|
@ -1539,7 +1539,6 @@ static const struct net_device_ops enc28j60_netdev_ops = {
|
||||
|
||||
static int enc28j60_probe(struct spi_device *spi)
|
||||
{
|
||||
unsigned char macaddr[ETH_ALEN];
|
||||
struct net_device *dev;
|
||||
struct enc28j60_net *priv;
|
||||
int ret = 0;
|
||||
@ -1572,9 +1571,7 @@ static int enc28j60_probe(struct spi_device *spi)
|
||||
goto error_irq;
|
||||
}
|
||||
|
||||
if (device_get_mac_address(&spi->dev, macaddr, sizeof(macaddr)))
|
||||
eth_hw_addr_set(dev, macaddr);
|
||||
else
|
||||
if (device_get_ethdev_address(&spi->dev, dev))
|
||||
eth_hw_addr_random(dev);
|
||||
enc28j60_set_hw_macaddr(dev);
|
||||
|
||||
|
@ -363,7 +363,7 @@ static int mana_hwc_create_cq(struct hw_channel_context *hwc, u16 q_depth,
|
||||
}
|
||||
hwc_cq->gdma_cq = cq;
|
||||
|
||||
comp_buf = kcalloc(q_depth, sizeof(struct gdma_comp), GFP_KERNEL);
|
||||
comp_buf = kcalloc(q_depth, sizeof(*comp_buf), GFP_KERNEL);
|
||||
if (!comp_buf) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
@ -580,7 +580,7 @@ static int mana_hwc_test_channel(struct hw_channel_context *hwc, u16 q_depth,
|
||||
return err;
|
||||
}
|
||||
|
||||
ctx = kzalloc(q_depth * sizeof(struct hwc_caller_ctx), GFP_KERNEL);
|
||||
ctx = kcalloc(q_depth, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -28,7 +28,7 @@ config MSCC_OCELOT_SWITCH
|
||||
depends on BRIDGE || BRIDGE=n
|
||||
depends on NET_SWITCHDEV
|
||||
depends on HAS_IOMEM
|
||||
depends on OF_NET
|
||||
depends on OF
|
||||
select MSCC_OCELOT_SWITCH_LIB
|
||||
select GENERIC_PHY
|
||||
help
|
||||
|
@ -1349,7 +1349,7 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
|
||||
__lpc_get_mac(pldat, ndev->dev_addr);
|
||||
|
||||
if (!is_valid_ether_addr(ndev->dev_addr)) {
|
||||
of_get_mac_address(np, ndev->dev_addr);
|
||||
of_get_ethdev_address(np, ndev);
|
||||
}
|
||||
if (!is_valid_ether_addr(ndev->dev_addr))
|
||||
eth_hw_addr_random(ndev);
|
||||
|
@ -1654,7 +1654,7 @@ int qed_ll2_establish_connection(void *cxt, u8 connection_handle)
|
||||
|
||||
DP_VERBOSE(p_hwfn,
|
||||
QED_MSG_LL2,
|
||||
"Establishing ll2 queue. PF %d ctx_bsaed=%d abs qid=%d stats_id=%d\n",
|
||||
"Establishing ll2 queue. PF %d ctx_based=%d abs qid=%d stats_id=%d\n",
|
||||
p_hwfn->rel_pf_id,
|
||||
p_ll2_conn->input.rx_conn_type, qid, stats_id);
|
||||
|
||||
|
@ -545,13 +545,10 @@ static int emac_probe_resources(struct platform_device *pdev,
|
||||
struct emac_adapter *adpt)
|
||||
{
|
||||
struct net_device *netdev = adpt->netdev;
|
||||
char maddr[ETH_ALEN];
|
||||
int ret = 0;
|
||||
|
||||
/* get mac address */
|
||||
if (device_get_mac_address(&pdev->dev, maddr, ETH_ALEN))
|
||||
eth_hw_addr_set(netdev, maddr);
|
||||
else
|
||||
if (device_get_ethdev_address(&pdev->dev, netdev))
|
||||
eth_hw_addr_random(netdev);
|
||||
|
||||
/* Core 0 interrupt */
|
||||
|
@ -968,7 +968,7 @@ qca_spi_probe(struct spi_device *spi)
|
||||
|
||||
spi_set_drvdata(spi, qcaspi_devs);
|
||||
|
||||
ret = of_get_mac_address(spi->dev.of_node, qca->net_dev->dev_addr);
|
||||
ret = of_get_ethdev_address(spi->dev.of_node, qca->net_dev);
|
||||
if (ret) {
|
||||
eth_hw_addr_random(qca->net_dev);
|
||||
dev_info(&spi->dev, "Using random MAC address: %pM\n",
|
||||
|
@ -347,7 +347,7 @@ static int qca_uart_probe(struct serdev_device *serdev)
|
||||
|
||||
of_property_read_u32(serdev->dev.of_node, "current-speed", &speed);
|
||||
|
||||
ret = of_get_mac_address(serdev->dev.of_node, qca->net_dev->dev_addr);
|
||||
ret = of_get_ethdev_address(serdev->dev.of_node, qca->net_dev);
|
||||
if (ret) {
|
||||
eth_hw_addr_random(qca->net_dev);
|
||||
dev_info(&serdev->dev, "Using random MAC address: %pM\n",
|
||||
|
@ -132,7 +132,7 @@ static void ravb_read_mac_address(struct device_node *np,
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = of_get_mac_address(np, ndev->dev_addr);
|
||||
ret = of_get_ethdev_address(np, ndev);
|
||||
if (ret) {
|
||||
u32 mahr = ravb_read(ndev, MAHR);
|
||||
u32 malr = ravb_read(ndev, MALR);
|
||||
|
@ -118,7 +118,7 @@ static int sxgbe_platform_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Get MAC address if available (DT) */
|
||||
of_get_mac_address(node, priv->dev->dev_addr);
|
||||
of_get_ethdev_address(node, priv->dev);
|
||||
|
||||
/* Get the TX/RX IRQ numbers */
|
||||
for (i = 0, chan = 1; i < SXGBE_TX_QUEUES; i++) {
|
||||
|
@ -2375,7 +2375,7 @@ static int smsc911x_probe_config(struct smsc911x_platform_config *config,
|
||||
phy_interface = PHY_INTERFACE_MODE_NA;
|
||||
config->phy_interface = phy_interface;
|
||||
|
||||
device_get_mac_address(dev, config->mac, ETH_ALEN);
|
||||
device_get_mac_address(dev, config->mac);
|
||||
|
||||
err = device_property_read_u32(dev, "reg-io-width", &width);
|
||||
if (err == -ENXIO)
|
||||
|
@ -1978,7 +1978,6 @@ static int netsec_register_mdio(struct netsec_priv *priv, u32 phy_addr)
|
||||
static int netsec_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *mmio_res, *eeprom_res, *irq_res;
|
||||
u8 *mac, macbuf[ETH_ALEN];
|
||||
struct netsec_priv *priv;
|
||||
u32 hw_ver, phy_addr = 0;
|
||||
struct net_device *ndev;
|
||||
@ -2034,12 +2033,8 @@ static int netsec_probe(struct platform_device *pdev)
|
||||
goto free_ndev;
|
||||
}
|
||||
|
||||
mac = device_get_mac_address(&pdev->dev, macbuf, sizeof(macbuf));
|
||||
if (mac)
|
||||
eth_hw_addr_set(ndev, mac);
|
||||
|
||||
if (priv->eeprom_base &&
|
||||
(!mac || !is_valid_ether_addr(ndev->dev_addr))) {
|
||||
ret = device_get_ethdev_address(&pdev->dev, ndev);
|
||||
if (ret && priv->eeprom_base) {
|
||||
void __iomem *macp = priv->eeprom_base +
|
||||
NETSEC_EEPROM_MAC_ADDRESS;
|
||||
|
||||
|
@ -1599,7 +1599,7 @@ static int ave_probe(struct platform_device *pdev)
|
||||
|
||||
ndev->max_mtu = AVE_MAX_ETHFRAME - (ETH_HLEN + ETH_FCS_LEN);
|
||||
|
||||
ret = of_get_mac_address(np, ndev->dev_addr);
|
||||
ret = of_get_ethdev_address(np, ndev);
|
||||
if (ret) {
|
||||
/* if the mac address is invalid, use random mac address */
|
||||
eth_hw_addr_random(ndev);
|
||||
|
@ -1104,13 +1104,13 @@ static int stmmac_test_rxp(struct stmmac_priv *priv)
|
||||
goto cleanup_sel;
|
||||
}
|
||||
|
||||
actions = kzalloc(nk * sizeof(*actions), GFP_KERNEL);
|
||||
actions = kcalloc(nk, sizeof(*actions), GFP_KERNEL);
|
||||
if (!actions) {
|
||||
ret = -ENOMEM;
|
||||
goto cleanup_exts;
|
||||
}
|
||||
|
||||
act = kzalloc(nk * sizeof(*act), GFP_KERNEL);
|
||||
act = kcalloc(nk, sizeof(*act), GFP_KERNEL);
|
||||
if (!act) {
|
||||
ret = -ENOMEM;
|
||||
goto cleanup_actions;
|
||||
|
@ -669,10 +669,10 @@ static int cpts_of_mux_clk_setup(struct cpts *cpts, struct device_node *node)
|
||||
goto mux_fail;
|
||||
}
|
||||
|
||||
parent_names = devm_kzalloc(cpts->dev, (sizeof(char *) * num_parents),
|
||||
GFP_KERNEL);
|
||||
parent_names = devm_kcalloc(cpts->dev, num_parents,
|
||||
sizeof(*parent_names), GFP_KERNEL);
|
||||
|
||||
mux_table = devm_kzalloc(cpts->dev, sizeof(*mux_table) * num_parents,
|
||||
mux_table = devm_kcalloc(cpts->dev, num_parents, sizeof(*mux_table),
|
||||
GFP_KERNEL);
|
||||
if (!mux_table || !parent_names) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -2035,7 +2035,7 @@ static int netcp_create_interface(struct netcp_device *netcp_device,
|
||||
devm_iounmap(dev, efuse);
|
||||
devm_release_mem_region(dev, res.start, size);
|
||||
} else {
|
||||
ret = of_get_mac_address(node_interface, ndev->dev_addr);
|
||||
ret = of_get_ethdev_address(node_interface, ndev);
|
||||
if (ret)
|
||||
eth_random_addr(ndev->dev_addr);
|
||||
}
|
||||
|
@ -1477,7 +1477,7 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
|
||||
__func__, status);
|
||||
return -EINVAL;
|
||||
}
|
||||
eth_hw_addr_set(netdev, &v1);
|
||||
eth_hw_addr_set(netdev, (u8 *)&v1);
|
||||
|
||||
if (card->vlan_required) {
|
||||
netdev->hard_header_len += VLAN_HLEN;
|
||||
|
@ -1157,7 +1157,7 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
|
||||
lp->tx_ping_pong = get_bool(ofdev, "xlnx,tx-ping-pong");
|
||||
lp->rx_ping_pong = get_bool(ofdev, "xlnx,rx-ping-pong");
|
||||
|
||||
rc = of_get_mac_address(ofdev->dev.of_node, ndev->dev_addr);
|
||||
rc = of_get_ethdev_address(ofdev->dev.of_node, ndev);
|
||||
if (rc) {
|
||||
dev_warn(dev, "No MAC address found, using random\n");
|
||||
eth_hw_addr_random(ndev);
|
||||
|
@ -539,7 +539,7 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
|
||||
mtu = dst_mtu(&rt->dst);
|
||||
}
|
||||
|
||||
rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu, false);
|
||||
skb_dst_update_pmtu_no_confirm(skb, mtu);
|
||||
|
||||
if (!skb_is_gso(skb) && (iph->frag_off & htons(IP_DF)) &&
|
||||
mtu < ntohs(iph->tot_len)) {
|
||||
|
@ -153,6 +153,7 @@
|
||||
#define QCA8327_A_PHY_ID 0x004dd033
|
||||
#define QCA8327_B_PHY_ID 0x004dd034
|
||||
#define QCA8337_PHY_ID 0x004dd036
|
||||
#define QCA9561_PHY_ID 0x004dd042
|
||||
#define QCA8K_PHY_ID_MASK 0xffffffff
|
||||
|
||||
#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0)
|
||||
@ -1237,7 +1238,8 @@ static int at803x_cable_test_get_status(struct phy_device *phydev,
|
||||
int pair, ret;
|
||||
|
||||
if (phydev->phy_id == ATH9331_PHY_ID ||
|
||||
phydev->phy_id == ATH8032_PHY_ID)
|
||||
phydev->phy_id == ATH8032_PHY_ID ||
|
||||
phydev->phy_id == QCA9561_PHY_ID)
|
||||
pair_mask = 0x3;
|
||||
else
|
||||
pair_mask = 0xf;
|
||||
@ -1277,7 +1279,8 @@ static int at803x_cable_test_start(struct phy_device *phydev)
|
||||
phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
|
||||
phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA);
|
||||
if (phydev->phy_id != ATH9331_PHY_ID &&
|
||||
phydev->phy_id != ATH8032_PHY_ID)
|
||||
phydev->phy_id != ATH8032_PHY_ID &&
|
||||
phydev->phy_id != QCA9561_PHY_ID)
|
||||
phy_write(phydev, MII_CTRL1000, 0);
|
||||
|
||||
/* we do all the (time consuming) work later */
|
||||
@ -1408,6 +1411,21 @@ static struct phy_driver at803x_driver[] = {
|
||||
.read_status = at803x_read_status,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.config_aneg = at803x_config_aneg,
|
||||
}, {
|
||||
/* Qualcomm Atheros QCA9561 */
|
||||
PHY_ID_MATCH_EXACT(QCA9561_PHY_ID),
|
||||
.name = "Qualcomm Atheros QCA9561 built-in PHY",
|
||||
.suspend = at803x_suspend,
|
||||
.resume = at803x_resume,
|
||||
.flags = PHY_POLL_CABLE_TEST,
|
||||
/* PHY_BASIC_FEATURES */
|
||||
.config_intr = &at803x_config_intr,
|
||||
.handle_interrupt = at803x_handle_interrupt,
|
||||
.cable_test_start = at803x_cable_test_start,
|
||||
.cable_test_get_status = at803x_cable_test_get_status,
|
||||
.read_status = at803x_read_status,
|
||||
.soft_reset = genphy_soft_reset,
|
||||
.config_aneg = at803x_config_aneg,
|
||||
}, {
|
||||
/* QCA8337 */
|
||||
.phy_id = QCA8337_PHY_ID,
|
||||
@ -1466,6 +1484,7 @@ static struct mdio_device_id __maybe_unused atheros_tbl[] = {
|
||||
{ PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) },
|
||||
{ PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) },
|
||||
{ PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) },
|
||||
{ PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -936,6 +936,28 @@ int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mdiobus_modify);
|
||||
|
||||
/**
|
||||
* mdiobus_modify_changed - Convenience function for modifying a given mdio
|
||||
* device register and returning if it changed
|
||||
* @bus: the mii_bus struct
|
||||
* @addr: the phy address
|
||||
* @regnum: register number to write
|
||||
* @mask: bit mask of bits to clear
|
||||
* @set: bit mask of bits to set
|
||||
*/
|
||||
int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
|
||||
u16 mask, u16 set)
|
||||
{
|
||||
int err;
|
||||
|
||||
mutex_lock(&bus->mdio_lock);
|
||||
err = __mdiobus_modify_changed(bus, addr, regnum, mask, set);
|
||||
mutex_unlock(&bus->mdio_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mdiobus_modify_changed);
|
||||
|
||||
/**
|
||||
* mdio_bus_match - determine if given MDIO driver supports the given
|
||||
* MDIO device
|
||||
|
@ -2596,7 +2596,6 @@ int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs,
|
||||
{
|
||||
struct mii_bus *bus = pcs->bus;
|
||||
int addr = pcs->addr;
|
||||
int val, ret;
|
||||
u16 adv;
|
||||
|
||||
switch (interface) {
|
||||
@ -2610,32 +2609,12 @@ int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs,
|
||||
advertising))
|
||||
adv |= ADVERTISE_1000XPSE_ASYM;
|
||||
|
||||
val = mdiobus_read(bus, addr, MII_ADVERTISE);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
if (val == adv)
|
||||
return 0;
|
||||
|
||||
ret = mdiobus_write(bus, addr, MII_ADVERTISE, adv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 1;
|
||||
return mdiobus_modify_changed(bus, addr, MII_ADVERTISE,
|
||||
0xffff, adv);
|
||||
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
val = mdiobus_read(bus, addr, MII_ADVERTISE);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
if (val == 0x0001)
|
||||
return 0;
|
||||
|
||||
ret = mdiobus_write(bus, addr, MII_ADVERTISE, 0x0001);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 1;
|
||||
return mdiobus_modify_changed(bus, addr, MII_ADVERTISE,
|
||||
0xffff, 0x0001);
|
||||
|
||||
default:
|
||||
/* Nothing to do for other modes */
|
||||
|
@ -1772,9 +1772,8 @@ static const struct usb_device_id ar5523_id_table[] = {
|
||||
AR5523_DEVICE_UG(0x0846, 0x5f00), /* Netgear / WPN111 */
|
||||
AR5523_DEVICE_UG(0x083a, 0x4506), /* SMC / EZ Connect
|
||||
SMCWUSBT-G2 */
|
||||
AR5523_DEVICE_UG(0x157e, 0x3006), /* Umedia / AR5523_1 */
|
||||
AR5523_DEVICE_UG(0x157e, 0x3006), /* Umedia / AR5523_1, TEW444UBEU*/
|
||||
AR5523_DEVICE_UX(0x157e, 0x3205), /* Umedia / AR5523_2 */
|
||||
AR5523_DEVICE_UG(0x157e, 0x3006), /* Umedia / TEW444UBEU */
|
||||
AR5523_DEVICE_UG(0x1435, 0x0826), /* Wistronneweb / AR5523_1 */
|
||||
AR5523_DEVICE_UX(0x1435, 0x0828), /* Wistronneweb / AR5523_2 */
|
||||
AR5523_DEVICE_UG(0x0cde, 0x0012), /* Zcom / AR5523 */
|
||||
|
@ -3224,7 +3224,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
|
||||
ath10k_debug_print_board_info(ar);
|
||||
}
|
||||
|
||||
device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr));
|
||||
device_get_mac_address(ar->dev, ar->mac_addr);
|
||||
|
||||
ret = ath10k_core_init_firmware_features(ar);
|
||||
if (ret) {
|
||||
|
@ -993,8 +993,12 @@ static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif)
|
||||
ath10k_mac_vif_beacon_free(arvif);
|
||||
|
||||
if (arvif->beacon_buf) {
|
||||
dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
|
||||
arvif->beacon_buf, arvif->beacon_paddr);
|
||||
if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
|
||||
kfree(arvif->beacon_buf);
|
||||
else
|
||||
dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
|
||||
arvif->beacon_buf,
|
||||
arvif->beacon_paddr);
|
||||
arvif->beacon_buf = NULL;
|
||||
}
|
||||
}
|
||||
@ -5576,10 +5580,17 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC ||
|
||||
vif->type == NL80211_IFTYPE_MESH_POINT ||
|
||||
vif->type == NL80211_IFTYPE_AP) {
|
||||
arvif->beacon_buf = dma_alloc_coherent(ar->dev,
|
||||
IEEE80211_MAX_FRAME_LEN,
|
||||
&arvif->beacon_paddr,
|
||||
GFP_ATOMIC);
|
||||
if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) {
|
||||
arvif->beacon_buf = kmalloc(IEEE80211_MAX_FRAME_LEN,
|
||||
GFP_KERNEL);
|
||||
arvif->beacon_paddr = (dma_addr_t)arvif->beacon_buf;
|
||||
} else {
|
||||
arvif->beacon_buf =
|
||||
dma_alloc_coherent(ar->dev,
|
||||
IEEE80211_MAX_FRAME_LEN,
|
||||
&arvif->beacon_paddr,
|
||||
GFP_ATOMIC);
|
||||
}
|
||||
if (!arvif->beacon_buf) {
|
||||
ret = -ENOMEM;
|
||||
ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
|
||||
@ -5794,8 +5805,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
err:
|
||||
if (arvif->beacon_buf) {
|
||||
dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
|
||||
arvif->beacon_buf, arvif->beacon_paddr);
|
||||
if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
|
||||
kfree(arvif->beacon_buf);
|
||||
else
|
||||
dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
|
||||
arvif->beacon_buf,
|
||||
arvif->beacon_paddr);
|
||||
arvif->beacon_buf = NULL;
|
||||
}
|
||||
|
||||
|
@ -1363,8 +1363,11 @@ static void ath10k_rx_indication_async_work(struct work_struct *work)
|
||||
ep->ep_ops.ep_rx_complete(ar, skb);
|
||||
}
|
||||
|
||||
if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
|
||||
if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags)) {
|
||||
local_bh_disable();
|
||||
napi_schedule(&ar->napi);
|
||||
local_bh_enable();
|
||||
}
|
||||
}
|
||||
|
||||
static int ath10k_sdio_read_rtc_state(struct ath10k_sdio *ar_sdio, unsigned char *state)
|
||||
|
@ -2610,6 +2610,10 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
if (ieee80211_is_beacon(hdr->frame_control))
|
||||
ath10k_mac_handle_beacon(ar, skb);
|
||||
|
||||
if (ieee80211_is_beacon(hdr->frame_control) ||
|
||||
ieee80211_is_probe_resp(hdr->frame_control))
|
||||
status->boottime_ns = ktime_get_boottime_ns();
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MGMT,
|
||||
"event mgmt rx skb %pK len %d ftype %02x stype %02x\n",
|
||||
skb, skb->len,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user