Commit 50ee42b9 authored by David S. Miller's avatar David S. Miller

Merge branch 'WoL-filters'

Florian Fainelli says:

====================
net: Support Wake-on-LAN using filters

This is technically a v2, but this patch series builds on your feedback
and defines the following:

- a new WAKE_* bit: WAKE_FILTER which can be enabled alongside other type
  of Wake-on-LAN to support waking up on a programmed filter (match + action)
- a new RX_CLS_FLOW_WAKE flow action which can be specified by an user when
  inserting a flow using ethtool::rxnfc, similar to the existing RX_CLS_FLOW_DISC

The bcm_sf2 and bcmsysport drivers are updated accordingly to work in concert to
allow matching packets at the switch level, identified by their filter location
to be used as a match by the SYSTEM PORT (CPU/management controller) during
Wake-on-LAN.

Let me know if this looks better than the previous incarnation of the patch
series.

Attached is also the ethtool patch that I would be submitting once the uapi
changes are committed.

Thank you!

Changes in v2:

- bail out earlier in bcm_sf2_cfp's get_rxnfc if an error is
  encountered (Andrew)
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1ba98280 bb9051a2
...@@ -732,6 +732,8 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port, ...@@ -732,6 +732,8 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
struct ethtool_rx_flow_spec *fs) struct ethtool_rx_flow_spec *fs)
{ {
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
s8 cpu_port = ds->ports[port].cpu_dp->index;
__u64 ring_cookie = fs->ring_cookie;
unsigned int queue_num, port_num; unsigned int queue_num, port_num;
int ret = -EINVAL; int ret = -EINVAL;
...@@ -748,13 +750,19 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port, ...@@ -748,13 +750,19 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
fs->location > bcm_sf2_cfp_rule_size(priv)) fs->location > bcm_sf2_cfp_rule_size(priv))
return -EINVAL; return -EINVAL;
/* This rule is a Wake-on-LAN filter and we must specifically
* target the CPU port in order for it to be working.
*/
if (ring_cookie == RX_CLS_FLOW_WAKE)
ring_cookie = cpu_port * SF2_NUM_EGRESS_QUEUES;
/* We do not support discarding packets, check that the /* We do not support discarding packets, check that the
* destination port is enabled and that we are within the * destination port is enabled and that we are within the
* number of ports supported by the switch * number of ports supported by the switch
*/ */
port_num = fs->ring_cookie / SF2_NUM_EGRESS_QUEUES; port_num = ring_cookie / SF2_NUM_EGRESS_QUEUES;
if (fs->ring_cookie == RX_CLS_FLOW_DISC || if (ring_cookie == RX_CLS_FLOW_DISC ||
!(dsa_is_user_port(ds, port_num) || !(dsa_is_user_port(ds, port_num) ||
dsa_is_cpu_port(ds, port_num)) || dsa_is_cpu_port(ds, port_num)) ||
port_num >= priv->hw_params.num_ports) port_num >= priv->hw_params.num_ports)
...@@ -763,7 +771,7 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port, ...@@ -763,7 +771,7 @@ static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
* We have a small oddity where Port 6 just does not have a * We have a small oddity where Port 6 just does not have a
* valid bit here (so we substract by one). * valid bit here (so we substract by one).
*/ */
queue_num = fs->ring_cookie % SF2_NUM_EGRESS_QUEUES; queue_num = ring_cookie % SF2_NUM_EGRESS_QUEUES;
if (port_num >= 7) if (port_num >= 7)
port_num -= 1; port_num -= 1;
...@@ -1188,6 +1196,7 @@ static int bcm_sf2_cfp_rule_get_all(struct bcm_sf2_priv *priv, ...@@ -1188,6 +1196,7 @@ static int bcm_sf2_cfp_rule_get_all(struct bcm_sf2_priv *priv,
int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port, int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port,
struct ethtool_rxnfc *nfc, u32 *rule_locs) struct ethtool_rxnfc *nfc, u32 *rule_locs)
{ {
struct net_device *p = ds->ports[port].cpu_dp->master;
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
int ret = 0; int ret = 0;
...@@ -1214,12 +1223,23 @@ int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port, ...@@ -1214,12 +1223,23 @@ int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port,
mutex_unlock(&priv->cfp.lock); mutex_unlock(&priv->cfp.lock);
if (ret)
return ret;
/* Pass up the commands to the attached master network device */
if (p->ethtool_ops->get_rxnfc) {
ret = p->ethtool_ops->get_rxnfc(p, nfc, rule_locs);
if (ret == -EOPNOTSUPP)
ret = 0;
}
return ret; return ret;
} }
int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port, int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
struct ethtool_rxnfc *nfc) struct ethtool_rxnfc *nfc)
{ {
struct net_device *p = ds->ports[port].cpu_dp->master;
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
int ret = 0; int ret = 0;
...@@ -1240,6 +1260,23 @@ int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port, ...@@ -1240,6 +1260,23 @@ int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
mutex_unlock(&priv->cfp.lock); mutex_unlock(&priv->cfp.lock);
if (ret)
return ret;
/* Pass up the commands to the attached master network device.
* This can fail, so rollback the operation if we need to.
*/
if (p->ethtool_ops->set_rxnfc) {
ret = p->ethtool_ops->set_rxnfc(p, nfc);
if (ret && ret != -EOPNOTSUPP) {
mutex_lock(&priv->cfp.lock);
bcm_sf2_cfp_rule_del(priv, port, nfc->fs.location);
mutex_unlock(&priv->cfp.lock);
} else {
ret = 0;
}
}
return ret; return ret;
} }
......
...@@ -521,7 +521,7 @@ static void bcm_sysport_get_wol(struct net_device *dev, ...@@ -521,7 +521,7 @@ static void bcm_sysport_get_wol(struct net_device *dev,
struct bcm_sysport_priv *priv = netdev_priv(dev); struct bcm_sysport_priv *priv = netdev_priv(dev);
u32 reg; u32 reg;
wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE; wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
wol->wolopts = priv->wolopts; wol->wolopts = priv->wolopts;
if (!(priv->wolopts & WAKE_MAGICSECURE)) if (!(priv->wolopts & WAKE_MAGICSECURE))
...@@ -539,7 +539,7 @@ static int bcm_sysport_set_wol(struct net_device *dev, ...@@ -539,7 +539,7 @@ static int bcm_sysport_set_wol(struct net_device *dev,
{ {
struct bcm_sysport_priv *priv = netdev_priv(dev); struct bcm_sysport_priv *priv = netdev_priv(dev);
struct device *kdev = &priv->pdev->dev; struct device *kdev = &priv->pdev->dev;
u32 supported = WAKE_MAGIC | WAKE_MAGICSECURE; u32 supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
if (!device_can_wakeup(kdev)) if (!device_can_wakeup(kdev))
return -ENOTSUPP; return -ENOTSUPP;
...@@ -1043,7 +1043,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget) ...@@ -1043,7 +1043,7 @@ static int bcm_sysport_poll(struct napi_struct *napi, int budget)
static void mpd_enable_set(struct bcm_sysport_priv *priv, bool enable) static void mpd_enable_set(struct bcm_sysport_priv *priv, bool enable)
{ {
u32 reg; u32 reg, bit;
reg = umac_readl(priv, UMAC_MPD_CTRL); reg = umac_readl(priv, UMAC_MPD_CTRL);
if (enable) if (enable)
...@@ -1051,12 +1051,32 @@ static void mpd_enable_set(struct bcm_sysport_priv *priv, bool enable) ...@@ -1051,12 +1051,32 @@ static void mpd_enable_set(struct bcm_sysport_priv *priv, bool enable)
else else
reg &= ~MPD_EN; reg &= ~MPD_EN;
umac_writel(priv, reg, UMAC_MPD_CTRL); umac_writel(priv, reg, UMAC_MPD_CTRL);
if (priv->is_lite)
bit = RBUF_ACPI_EN_LITE;
else
bit = RBUF_ACPI_EN;
reg = rbuf_readl(priv, RBUF_CONTROL);
if (enable)
reg |= bit;
else
reg &= ~bit;
rbuf_writel(priv, reg, RBUF_CONTROL);
} }
static void bcm_sysport_resume_from_wol(struct bcm_sysport_priv *priv) static void bcm_sysport_resume_from_wol(struct bcm_sysport_priv *priv)
{ {
u32 reg;
/* Stop monitoring MPD interrupt */ /* Stop monitoring MPD interrupt */
intrl2_0_mask_set(priv, INTRL2_0_MPD); intrl2_0_mask_set(priv, INTRL2_0_MPD | INTRL2_0_BRCM_MATCH_TAG);
/* Disable RXCHK, active filters and Broadcom tag matching */
reg = rxchk_readl(priv, RXCHK_CONTROL);
reg &= ~(RXCHK_BRCM_TAG_MATCH_MASK <<
RXCHK_BRCM_TAG_MATCH_SHIFT | RXCHK_EN | RXCHK_BRCM_TAG_EN);
rxchk_writel(priv, reg, RXCHK_CONTROL);
/* Clear the MagicPacket detection logic */ /* Clear the MagicPacket detection logic */
mpd_enable_set(priv, false); mpd_enable_set(priv, false);
...@@ -1085,6 +1105,7 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id) ...@@ -1085,6 +1105,7 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
struct bcm_sysport_priv *priv = netdev_priv(dev); struct bcm_sysport_priv *priv = netdev_priv(dev);
struct bcm_sysport_tx_ring *txr; struct bcm_sysport_tx_ring *txr;
unsigned int ring, ring_bit; unsigned int ring, ring_bit;
u32 reg;
priv->irq0_stat = intrl2_0_readl(priv, INTRL2_CPU_STATUS) & priv->irq0_stat = intrl2_0_readl(priv, INTRL2_CPU_STATUS) &
~intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS); ~intrl2_0_readl(priv, INTRL2_CPU_MASK_STATUS);
...@@ -1111,7 +1132,14 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id) ...@@ -1111,7 +1132,14 @@ static irqreturn_t bcm_sysport_rx_isr(int irq, void *dev_id)
bcm_sysport_tx_reclaim_all(priv); bcm_sysport_tx_reclaim_all(priv);
if (priv->irq0_stat & INTRL2_0_MPD) if (priv->irq0_stat & INTRL2_0_MPD)
netdev_info(priv->netdev, "Wake-on-LAN interrupt!\n"); netdev_info(priv->netdev, "Wake-on-LAN (MPD) interrupt!\n");
if (priv->irq0_stat & INTRL2_0_BRCM_MATCH_TAG) {
reg = rxchk_readl(priv, RXCHK_BRCM_TAG_MATCH_STATUS) &
RXCHK_BRCM_TAG_MATCH_MASK;
netdev_info(priv->netdev,
"Wake-on-LAN (filters 0x%02x) interrupt!\n", reg);
}
if (!priv->is_lite) if (!priv->is_lite)
goto out; goto out;
...@@ -2096,6 +2124,132 @@ static int bcm_sysport_stop(struct net_device *dev) ...@@ -2096,6 +2124,132 @@ static int bcm_sysport_stop(struct net_device *dev)
return 0; return 0;
} }
static int bcm_sysport_rule_find(struct bcm_sysport_priv *priv,
u64 location)
{
unsigned int index;
u32 reg;
for_each_set_bit(index, priv->filters, RXCHK_BRCM_TAG_MAX) {
reg = rxchk_readl(priv, RXCHK_BRCM_TAG(index));
reg >>= RXCHK_BRCM_TAG_CID_SHIFT;
reg &= RXCHK_BRCM_TAG_CID_MASK;
if (reg == location)
return index;
}
return -EINVAL;
}
static int bcm_sysport_rule_get(struct bcm_sysport_priv *priv,
struct ethtool_rxnfc *nfc)
{
int index;
/* This is not a rule that we know about */
index = bcm_sysport_rule_find(priv, nfc->fs.location);
if (index < 0)
return -EOPNOTSUPP;
nfc->fs.ring_cookie = RX_CLS_FLOW_WAKE;
return 0;
}
static int bcm_sysport_rule_set(struct bcm_sysport_priv *priv,
struct ethtool_rxnfc *nfc)
{
unsigned int index;
u32 reg;
/* We cannot match locations greater than what the classification ID
* permits (256 entries)
*/
if (nfc->fs.location > RXCHK_BRCM_TAG_CID_MASK)
return -E2BIG;
/* We cannot support flows that are not destined for a wake-up */
if (nfc->fs.ring_cookie != RX_CLS_FLOW_WAKE)
return -EOPNOTSUPP;
/* All filters are already in use, we cannot match more rules */
if (bitmap_weight(priv->filters, RXCHK_BRCM_TAG_MAX) ==
RXCHK_BRCM_TAG_MAX)
return -ENOSPC;
index = find_first_zero_bit(priv->filters, RXCHK_BRCM_TAG_MAX);
if (index > RXCHK_BRCM_TAG_MAX)
return -ENOSPC;
/* Location is the classification ID, and index is the position
* within one of our 8 possible filters to be programmed
*/
reg = rxchk_readl(priv, RXCHK_BRCM_TAG(index));
reg &= ~(RXCHK_BRCM_TAG_CID_MASK << RXCHK_BRCM_TAG_CID_SHIFT);
reg |= nfc->fs.location << RXCHK_BRCM_TAG_CID_SHIFT;
rxchk_writel(priv, reg, RXCHK_BRCM_TAG(index));
rxchk_writel(priv, 0xff00ffff, RXCHK_BRCM_TAG_MASK(index));
set_bit(index, priv->filters);
return 0;
}
static int bcm_sysport_rule_del(struct bcm_sysport_priv *priv,
u64 location)
{
int index;
/* This is not a rule that we know about */
index = bcm_sysport_rule_find(priv, location);
if (index < 0)
return -EOPNOTSUPP;
/* No need to disable this filter if it was enabled, this will
* be taken care of during suspend time by bcm_sysport_suspend_to_wol
*/
clear_bit(index, priv->filters);
return 0;
}
static int bcm_sysport_get_rxnfc(struct net_device *dev,
struct ethtool_rxnfc *nfc, u32 *rule_locs)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
int ret = -EOPNOTSUPP;
switch (nfc->cmd) {
case ETHTOOL_GRXCLSRULE:
ret = bcm_sysport_rule_get(priv, nfc);
break;
default:
break;
}
return ret;
}
static int bcm_sysport_set_rxnfc(struct net_device *dev,
struct ethtool_rxnfc *nfc)
{
struct bcm_sysport_priv *priv = netdev_priv(dev);
int ret = -EOPNOTSUPP;
switch (nfc->cmd) {
case ETHTOOL_SRXCLSRLINS:
ret = bcm_sysport_rule_set(priv, nfc);
break;
case ETHTOOL_SRXCLSRLDEL:
ret = bcm_sysport_rule_del(priv, nfc->fs.location);
break;
default:
break;
}
return ret;
}
static const struct ethtool_ops bcm_sysport_ethtool_ops = { static const struct ethtool_ops bcm_sysport_ethtool_ops = {
.get_drvinfo = bcm_sysport_get_drvinfo, .get_drvinfo = bcm_sysport_get_drvinfo,
.get_msglevel = bcm_sysport_get_msglvl, .get_msglevel = bcm_sysport_get_msglvl,
...@@ -2110,6 +2264,8 @@ static const struct ethtool_ops bcm_sysport_ethtool_ops = { ...@@ -2110,6 +2264,8 @@ static const struct ethtool_ops bcm_sysport_ethtool_ops = {
.set_coalesce = bcm_sysport_set_coalesce, .set_coalesce = bcm_sysport_set_coalesce,
.get_link_ksettings = phy_ethtool_get_link_ksettings, .get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings, .set_link_ksettings = phy_ethtool_set_link_ksettings,
.get_rxnfc = bcm_sysport_get_rxnfc,
.set_rxnfc = bcm_sysport_set_rxnfc,
}; };
static u16 bcm_sysport_select_queue(struct net_device *dev, struct sk_buff *skb, static u16 bcm_sysport_select_queue(struct net_device *dev, struct sk_buff *skb,
...@@ -2434,16 +2590,39 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv) ...@@ -2434,16 +2590,39 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
{ {
struct net_device *ndev = priv->netdev; struct net_device *ndev = priv->netdev;
unsigned int timeout = 1000; unsigned int timeout = 1000;
unsigned int index, i = 0;
u32 reg; u32 reg;
/* Password has already been programmed */ /* Password has already been programmed */
reg = umac_readl(priv, UMAC_MPD_CTRL); reg = umac_readl(priv, UMAC_MPD_CTRL);
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE))
reg |= MPD_EN; reg |= MPD_EN;
reg &= ~PSW_EN; reg &= ~PSW_EN;
if (priv->wolopts & WAKE_MAGICSECURE) if (priv->wolopts & WAKE_MAGICSECURE)
reg |= PSW_EN; reg |= PSW_EN;
umac_writel(priv, reg, UMAC_MPD_CTRL); umac_writel(priv, reg, UMAC_MPD_CTRL);
if (priv->wolopts & WAKE_FILTER) {
/* Turn on ACPI matching to steal packets from RBUF */
reg = rbuf_readl(priv, RBUF_CONTROL);
if (priv->is_lite)
reg |= RBUF_ACPI_EN_LITE;
else
reg |= RBUF_ACPI_EN;
rbuf_writel(priv, reg, RBUF_CONTROL);
/* Enable RXCHK, active filters and Broadcom tag matching */
reg = rxchk_readl(priv, RXCHK_CONTROL);
reg &= ~(RXCHK_BRCM_TAG_MATCH_MASK <<
RXCHK_BRCM_TAG_MATCH_SHIFT);
for_each_set_bit(index, priv->filters, RXCHK_BRCM_TAG_MAX) {
reg |= BIT(RXCHK_BRCM_TAG_MATCH_SHIFT + i);
i++;
}
reg |= RXCHK_EN | RXCHK_BRCM_TAG_EN;
rxchk_writel(priv, reg, RXCHK_CONTROL);
}
/* Make sure RBUF entered WoL mode as result */ /* Make sure RBUF entered WoL mode as result */
do { do {
reg = rbuf_readl(priv, RBUF_STATUS); reg = rbuf_readl(priv, RBUF_STATUS);
...@@ -2464,7 +2643,7 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv) ...@@ -2464,7 +2643,7 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
umac_enable_set(priv, CMD_RX_EN, 1); umac_enable_set(priv, CMD_RX_EN, 1);
/* Enable the interrupt wake-up source */ /* Enable the interrupt wake-up source */
intrl2_0_mask_clear(priv, INTRL2_0_MPD); intrl2_0_mask_clear(priv, INTRL2_0_MPD | INTRL2_0_BRCM_MATCH_TAG);
netif_dbg(priv, wol, ndev, "entered WOL mode\n"); netif_dbg(priv, wol, ndev, "entered WOL mode\n");
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#ifndef __BCM_SYSPORT_H #ifndef __BCM_SYSPORT_H
#define __BCM_SYSPORT_H #define __BCM_SYSPORT_H
#include <linux/bitmap.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/net_dim.h> #include <linux/net_dim.h>
...@@ -155,14 +156,18 @@ struct bcm_rsb { ...@@ -155,14 +156,18 @@ struct bcm_rsb {
#define RXCHK_PARSE_AUTH (1 << 22) #define RXCHK_PARSE_AUTH (1 << 22)
#define RXCHK_BRCM_TAG0 0x04 #define RXCHK_BRCM_TAG0 0x04
#define RXCHK_BRCM_TAG(i) ((i) * RXCHK_BRCM_TAG0) #define RXCHK_BRCM_TAG(i) ((i) * 0x4 + RXCHK_BRCM_TAG0)
#define RXCHK_BRCM_TAG0_MASK 0x24 #define RXCHK_BRCM_TAG0_MASK 0x24
#define RXCHK_BRCM_TAG_MASK(i) ((i) * RXCHK_BRCM_TAG0_MASK) #define RXCHK_BRCM_TAG_MASK(i) ((i) * 0x4 + RXCHK_BRCM_TAG0_MASK)
#define RXCHK_BRCM_TAG_MATCH_STATUS 0x44 #define RXCHK_BRCM_TAG_MATCH_STATUS 0x44
#define RXCHK_ETHERTYPE 0x48 #define RXCHK_ETHERTYPE 0x48
#define RXCHK_BAD_CSUM_CNTR 0x4C #define RXCHK_BAD_CSUM_CNTR 0x4C
#define RXCHK_OTHER_DISC_CNTR 0x50 #define RXCHK_OTHER_DISC_CNTR 0x50
#define RXCHK_BRCM_TAG_MAX 8
#define RXCHK_BRCM_TAG_CID_SHIFT 16
#define RXCHK_BRCM_TAG_CID_MASK 0xff
/* TXCHCK offsets and defines */ /* TXCHCK offsets and defines */
#define SYS_PORT_TXCHK_OFFSET 0x380 #define SYS_PORT_TXCHK_OFFSET 0x380
#define TXCHK_PKT_RDY_THRESH 0x00 #define TXCHK_PKT_RDY_THRESH 0x00
...@@ -185,6 +190,7 @@ struct bcm_rsb { ...@@ -185,6 +190,7 @@ struct bcm_rsb {
#define RBUF_RSB_SWAP0 (1 << 22) #define RBUF_RSB_SWAP0 (1 << 22)
#define RBUF_RSB_SWAP1 (1 << 23) #define RBUF_RSB_SWAP1 (1 << 23)
#define RBUF_ACPI_EN (1 << 23) #define RBUF_ACPI_EN (1 << 23)
#define RBUF_ACPI_EN_LITE (1 << 24)
#define RBUF_PKT_RDY_THRESH 0x04 #define RBUF_PKT_RDY_THRESH 0x04
...@@ -777,6 +783,7 @@ struct bcm_sysport_priv { ...@@ -777,6 +783,7 @@ struct bcm_sysport_priv {
/* Ethtool */ /* Ethtool */
u32 msg_enable; u32 msg_enable;
DECLARE_BITMAP(filters, RXCHK_BRCM_TAG_MAX);
struct bcm_sysport_stats64 stats64; struct bcm_sysport_stats64 stats64;
......
...@@ -870,7 +870,8 @@ struct ethtool_flow_ext { ...@@ -870,7 +870,8 @@ struct ethtool_flow_ext {
* includes the %FLOW_EXT or %FLOW_MAC_EXT flag * includes the %FLOW_EXT or %FLOW_MAC_EXT flag
* (see &struct ethtool_flow_ext description). * (see &struct ethtool_flow_ext description).
* @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC
* if packets should be discarded * if packets should be discarded, or %RX_CLS_FLOW_WAKE if the
* packets should be used for Wake-on-LAN with %WAKE_FILTER
* @location: Location of rule in the table. Locations must be * @location: Location of rule in the table. Locations must be
* numbered such that a flow matching multiple rules will be * numbered such that a flow matching multiple rules will be
* classified according to the first (lowest numbered) rule. * classified according to the first (lowest numbered) rule.
...@@ -1634,6 +1635,7 @@ static inline int ethtool_validate_duplex(__u8 duplex) ...@@ -1634,6 +1635,7 @@ static inline int ethtool_validate_duplex(__u8 duplex)
#define WAKE_ARP (1 << 4) #define WAKE_ARP (1 << 4)
#define WAKE_MAGIC (1 << 5) #define WAKE_MAGIC (1 << 5)
#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ #define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */
#define WAKE_FILTER (1 << 7)
/* L2-L4 network traffic flow types */ /* L2-L4 network traffic flow types */
#define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */ #define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */
...@@ -1671,6 +1673,7 @@ static inline int ethtool_validate_duplex(__u8 duplex) ...@@ -1671,6 +1673,7 @@ static inline int ethtool_validate_duplex(__u8 duplex)
#define RXH_DISCARD (1 << 31) #define RXH_DISCARD (1 << 31)
#define RX_CLS_FLOW_DISC 0xffffffffffffffffULL #define RX_CLS_FLOW_DISC 0xffffffffffffffffULL
#define RX_CLS_FLOW_WAKE 0xfffffffffffffffeULL
/* Special RX classification rule insert location values */ /* Special RX classification rule insert location values */
#define RX_CLS_LOC_SPECIAL 0x80000000 /* flag */ #define RX_CLS_LOC_SPECIAL 0x80000000 /* flag */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment