Skip to content

Commit

Permalink
Merge branch 'stmmac-next'
Browse files Browse the repository at this point in the history
Jose Abreu says:

====================
net: stmmac: Improvements for -next

Improvements for -next. More info in commit logs.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 6, 2019
2 parents 04c1b4c + dc07f5f commit 056ddc3
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 46 deletions.
21 changes: 21 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwmac4.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
#define GMAC_ARP_ADDR 0x00000210
#define GMAC_ADDR_HIGH(reg) (0x300 + reg * 8)
#define GMAC_ADDR_LOW(reg) (0x304 + reg * 8)
#define GMAC_L3L4_CTRL(reg) (0x900 + (reg) * 0x30)
#define GMAC_L4_ADDR(reg) (0x904 + (reg) * 0x30)
#define GMAC_L3_ADDR0(reg) (0x910 + (reg) * 0x30)
#define GMAC_L3_ADDR1(reg) (0x914 + (reg) * 0x30)

/* RX Queues Routing */
#define GMAC_RXQCTRL_AVCPQ_MASK GENMASK(2, 0)
Expand All @@ -67,6 +71,7 @@
#define GMAC_PACKET_FILTER_PCF BIT(7)
#define GMAC_PACKET_FILTER_HPF BIT(10)
#define GMAC_PACKET_FILTER_VTFE BIT(16)
#define GMAC_PACKET_FILTER_IPFE BIT(20)

#define GMAC_MAX_PERFECT_ADDRESSES 128

Expand Down Expand Up @@ -202,6 +207,7 @@ enum power_event {
#define GMAC_HW_FEAT_MIISEL BIT(0)

/* MAC HW features1 bitmap */
#define GMAC_HW_FEAT_L3L4FNUM GENMASK(30, 27)
#define GMAC_HW_HASH_TB_SZ GENMASK(25, 24)
#define GMAC_HW_FEAT_AVSEL BIT(20)
#define GMAC_HW_TSOEN BIT(18)
Expand All @@ -228,6 +234,21 @@ enum power_event {
#define GMAC_HI_DCS_SHIFT 16
#define GMAC_HI_REG_AE BIT(31)

/* L3/L4 Filters regs */
#define GMAC_L4DPIM0 BIT(21)
#define GMAC_L4DPM0 BIT(20)
#define GMAC_L4SPIM0 BIT(19)
#define GMAC_L4SPM0 BIT(18)
#define GMAC_L4PEN0 BIT(16)
#define GMAC_L3DAIM0 BIT(5)
#define GMAC_L3DAM0 BIT(4)
#define GMAC_L3SAIM0 BIT(3)
#define GMAC_L3SAM0 BIT(2)
#define GMAC_L3PEN0 BIT(0)
#define GMAC_L4DP0 GENMASK(31, 16)
#define GMAC_L4DP0_SHIFT 16
#define GMAC_L4SP0 GENMASK(15, 0)

/* MTL registers */
#define MTL_OPERATION_MODE 0x00000c00
#define MTL_FRPE BIT(15)
Expand Down
118 changes: 117 additions & 1 deletion drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ static void dwmac4_set_mac_loopback(void __iomem *ioaddr, bool enable)
}

static void dwmac4_update_vlan_hash(struct mac_device_info *hw, u32 hash,
bool is_double)
u16 perfect_match, bool is_double)
{
void __iomem *ioaddr = hw->pcsr;

Expand All @@ -748,6 +748,16 @@ static void dwmac4_update_vlan_hash(struct mac_device_info *hw, u32 hash,
}

writel(value, ioaddr + GMAC_VLAN_TAG);
} else if (perfect_match) {
u32 value = GMAC_VLAN_ETV;

if (is_double) {
value |= GMAC_VLAN_EDVLP;
value |= GMAC_VLAN_ESVL;
value |= GMAC_VLAN_DOVLTC;
}

writel(value | perfect_match, ioaddr + GMAC_VLAN_TAG);
} else {
u32 value = readl(ioaddr + GMAC_VLAN_TAG);

Expand Down Expand Up @@ -799,6 +809,106 @@ static void dwmac4_set_arp_offload(struct mac_device_info *hw, bool en,
writel(value, ioaddr + GMAC_CONFIG);
}

static int dwmac4_config_l3_filter(struct mac_device_info *hw, u32 filter_no,
bool en, bool ipv6, bool sa, bool inv,
u32 match)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;

value = readl(ioaddr + GMAC_PACKET_FILTER);
value |= GMAC_PACKET_FILTER_IPFE;
writel(value, ioaddr + GMAC_PACKET_FILTER);

value = readl(ioaddr + GMAC_L3L4_CTRL(filter_no));

/* For IPv6 not both SA/DA filters can be active */
if (ipv6) {
value |= GMAC_L3PEN0;
value &= ~(GMAC_L3SAM0 | GMAC_L3SAIM0);
value &= ~(GMAC_L3DAM0 | GMAC_L3DAIM0);
if (sa) {
value |= GMAC_L3SAM0;
if (inv)
value |= GMAC_L3SAIM0;
} else {
value |= GMAC_L3DAM0;
if (inv)
value |= GMAC_L3DAIM0;
}
} else {
value &= ~GMAC_L3PEN0;
if (sa) {
value |= GMAC_L3SAM0;
if (inv)
value |= GMAC_L3SAIM0;
} else {
value |= GMAC_L3DAM0;
if (inv)
value |= GMAC_L3DAIM0;
}
}

writel(value, ioaddr + GMAC_L3L4_CTRL(filter_no));

if (sa) {
writel(match, ioaddr + GMAC_L3_ADDR0(filter_no));
} else {
writel(match, ioaddr + GMAC_L3_ADDR1(filter_no));
}

if (!en)
writel(0, ioaddr + GMAC_L3L4_CTRL(filter_no));

return 0;
}

static int dwmac4_config_l4_filter(struct mac_device_info *hw, u32 filter_no,
bool en, bool udp, bool sa, bool inv,
u32 match)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;

value = readl(ioaddr + GMAC_PACKET_FILTER);
value |= GMAC_PACKET_FILTER_IPFE;
writel(value, ioaddr + GMAC_PACKET_FILTER);

value = readl(ioaddr + GMAC_L3L4_CTRL(filter_no));
if (udp) {
value |= GMAC_L4PEN0;
} else {
value &= ~GMAC_L4PEN0;
}

value &= ~(GMAC_L4SPM0 | GMAC_L4SPIM0);
value &= ~(GMAC_L4DPM0 | GMAC_L4DPIM0);
if (sa) {
value |= GMAC_L4SPM0;
if (inv)
value |= GMAC_L4SPIM0;
} else {
value |= GMAC_L4DPM0;
if (inv)
value |= GMAC_L4DPIM0;
}

writel(value, ioaddr + GMAC_L3L4_CTRL(filter_no));

if (sa) {
value = match & GMAC_L4SP0;
} else {
value = (match << GMAC_L4DP0_SHIFT) & GMAC_L4DP0;
}

writel(value, ioaddr + GMAC_L4_ADDR(filter_no));

if (!en)
writel(0, ioaddr + GMAC_L3L4_CTRL(filter_no));

return 0;
}

const struct stmmac_ops dwmac4_ops = {
.core_init = dwmac4_core_init,
.set_mac = stmmac_set_mac,
Expand Down Expand Up @@ -833,6 +943,8 @@ const struct stmmac_ops dwmac4_ops = {
.sarc_configure = dwmac4_sarc_configure,
.enable_vlan = dwmac4_enable_vlan,
.set_arp_offload = dwmac4_set_arp_offload,
.config_l3_filter = dwmac4_config_l3_filter,
.config_l4_filter = dwmac4_config_l4_filter,
};

const struct stmmac_ops dwmac410_ops = {
Expand Down Expand Up @@ -869,6 +981,8 @@ const struct stmmac_ops dwmac410_ops = {
.sarc_configure = dwmac4_sarc_configure,
.enable_vlan = dwmac4_enable_vlan,
.set_arp_offload = dwmac4_set_arp_offload,
.config_l3_filter = dwmac4_config_l3_filter,
.config_l4_filter = dwmac4_config_l4_filter,
};

const struct stmmac_ops dwmac510_ops = {
Expand Down Expand Up @@ -910,6 +1024,8 @@ const struct stmmac_ops dwmac510_ops = {
.sarc_configure = dwmac4_sarc_configure,
.enable_vlan = dwmac4_enable_vlan,
.set_arp_offload = dwmac4_set_arp_offload,
.config_l3_filter = dwmac4_config_l3_filter,
.config_l4_filter = dwmac4_config_l4_filter,
};

int dwmac4_setup(struct stmmac_priv *priv)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,

/* MAC HW feature1 */
hw_cap = readl(ioaddr + GMAC_HW_FEATURE1);
dma_cap->l3l4fnum = (hw_cap & GMAC_HW_FEAT_L3L4FNUM) >> 27;
dma_cap->hash_tb_sz = (hw_cap & GMAC_HW_HASH_TB_SZ) >> 24;
dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20;
dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18;
Expand Down
17 changes: 16 additions & 1 deletion drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ static int dwxgmac2_rss_configure(struct mac_device_info *hw,
}

static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
bool is_double)
u16 perfect_match, bool is_double)
{
void __iomem *ioaddr = hw->pcsr;

Expand All @@ -576,6 +576,21 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
}

writel(value, ioaddr + XGMAC_VLAN_TAG);
} else if (perfect_match) {
u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);

value |= XGMAC_FILTER_VTFE;

writel(value, ioaddr + XGMAC_PACKET_FILTER);

value = XGMAC_VLAN_ETV;
if (is_double) {
value |= XGMAC_VLAN_EDVLP;
value |= XGMAC_VLAN_ESVL;
value |= XGMAC_VLAN_DOVLTC;
}

writel(value | perfect_match, ioaddr + XGMAC_VLAN_TAG);
} else {
u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/stmicro/stmmac/hwif.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ struct stmmac_ops {
struct stmmac_rss *cfg, u32 num_rxq);
/* VLAN */
void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash,
bool is_double);
u16 perfect_match, bool is_double);
void (*enable_vlan)(struct mac_device_info *hw, u32 type);
/* TX Timestamp */
int (*get_mac_tx_timestamp)(struct mac_device_info *hw, u64 *ts);
Expand Down
18 changes: 12 additions & 6 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4207,15 +4207,25 @@ static u32 stmmac_vid_crc32_le(__le16 vid_le)
static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
{
u32 crc, hash = 0;
u16 vid;
int count = 0;
u16 vid = 0;

for_each_set_bit(vid, priv->active_vlans, VLAN_N_VID) {
__le16 vid_le = cpu_to_le16(vid);
crc = bitrev32(~stmmac_vid_crc32_le(vid_le)) >> 28;
hash |= (1 << crc);
count++;
}

if (!priv->dma_cap.vlhash) {
if (count > 2) /* VID = 0 always passes filter */
return -EOPNOTSUPP;

vid = cpu_to_le16(vid);
hash = 0;
}

return stmmac_update_vlan_hash(priv, priv->hw, hash, is_double);
return stmmac_update_vlan_hash(priv, priv->hw, hash, vid, is_double);
}

static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
Expand All @@ -4224,8 +4234,6 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
bool is_double = false;
int ret;

if (!priv->dma_cap.vlhash)
return -EOPNOTSUPP;
if (be16_to_cpu(proto) == ETH_P_8021AD)
is_double = true;

Expand All @@ -4244,8 +4252,6 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
struct stmmac_priv *priv = netdev_priv(ndev);
bool is_double = false;

if (!priv->dma_cap.vlhash)
return -EOPNOTSUPP;
if (be16_to_cpu(proto) == ETH_P_8021AD)
is_double = true;

Expand Down
Loading

0 comments on commit 056ddc3

Please sign in to comment.