|
@@ -126,8 +126,8 @@ static inline void tdma_port_write_desc_addr(struct bcm_sysport_priv *priv,
|
|
|
}
|
|
|
|
|
|
/* Ethtool operations */
|
|
|
-static int bcm_sysport_set_rx_csum(struct net_device *dev,
|
|
|
- netdev_features_t wanted)
|
|
|
+static void bcm_sysport_set_rx_csum(struct net_device *dev,
|
|
|
+ netdev_features_t wanted)
|
|
|
{
|
|
|
struct bcm_sysport_priv *priv = netdev_priv(dev);
|
|
|
u32 reg;
|
|
@@ -157,12 +157,10 @@ static int bcm_sysport_set_rx_csum(struct net_device *dev,
|
|
|
reg &= ~RXCHK_BRCM_TAG_EN;
|
|
|
|
|
|
rxchk_writel(priv, reg, RXCHK_CONTROL);
|
|
|
-
|
|
|
- return 0;
|
|
|
}
|
|
|
|
|
|
-static int bcm_sysport_set_tx_csum(struct net_device *dev,
|
|
|
- netdev_features_t wanted)
|
|
|
+static void bcm_sysport_set_tx_csum(struct net_device *dev,
|
|
|
+ netdev_features_t wanted)
|
|
|
{
|
|
|
struct bcm_sysport_priv *priv = netdev_priv(dev);
|
|
|
u32 reg;
|
|
@@ -177,23 +175,24 @@ static int bcm_sysport_set_tx_csum(struct net_device *dev,
|
|
|
else
|
|
|
reg &= ~tdma_control_bit(priv, TSB_EN);
|
|
|
tdma_writel(priv, reg, TDMA_CONTROL);
|
|
|
-
|
|
|
- return 0;
|
|
|
}
|
|
|
|
|
|
static int bcm_sysport_set_features(struct net_device *dev,
|
|
|
netdev_features_t features)
|
|
|
{
|
|
|
- netdev_features_t changed = features ^ dev->features;
|
|
|
- netdev_features_t wanted = dev->wanted_features;
|
|
|
- int ret = 0;
|
|
|
+ struct bcm_sysport_priv *priv = netdev_priv(dev);
|
|
|
+
|
|
|
+ /* Read CRC forward */
|
|
|
+ if (!priv->is_lite)
|
|
|
+ priv->crc_fwd = !!(umac_readl(priv, UMAC_CMD) & CMD_CRC_FWD);
|
|
|
+ else
|
|
|
+ priv->crc_fwd = !((gib_readl(priv, GIB_CONTROL) &
|
|
|
+ GIB_FCS_STRIP) >> GIB_FCS_STRIP_SHIFT);
|
|
|
|
|
|
- if (changed & NETIF_F_RXCSUM)
|
|
|
- ret = bcm_sysport_set_rx_csum(dev, wanted);
|
|
|
- if (changed & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM))
|
|
|
- ret = bcm_sysport_set_tx_csum(dev, wanted);
|
|
|
+ bcm_sysport_set_rx_csum(dev, features);
|
|
|
+ bcm_sysport_set_tx_csum(dev, features);
|
|
|
|
|
|
- return ret;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/* Hardware counters must be kept in sync because the order/offset
|
|
@@ -285,6 +284,8 @@ static const struct bcm_sysport_stats bcm_sysport_gstrings_stats[] = {
|
|
|
STAT_MIB_SOFT("alloc_rx_buff_failed", mib.alloc_rx_buff_failed),
|
|
|
STAT_MIB_SOFT("rx_dma_failed", mib.rx_dma_failed),
|
|
|
STAT_MIB_SOFT("tx_dma_failed", mib.tx_dma_failed),
|
|
|
+ STAT_MIB_SOFT("tx_realloc_tsb", mib.tx_realloc_tsb),
|
|
|
+ STAT_MIB_SOFT("tx_realloc_tsb_failed", mib.tx_realloc_tsb_failed),
|
|
|
/* Per TX-queue statistics are dynamically appended */
|
|
|
};
|
|
|
|
|
@@ -1221,6 +1222,7 @@ static void bcm_sysport_poll_controller(struct net_device *dev)
|
|
|
static struct sk_buff *bcm_sysport_insert_tsb(struct sk_buff *skb,
|
|
|
struct net_device *dev)
|
|
|
{
|
|
|
+ struct bcm_sysport_priv *priv = netdev_priv(dev);
|
|
|
struct sk_buff *nskb;
|
|
|
struct bcm_tsb *tsb;
|
|
|
u32 csum_info;
|
|
@@ -1231,13 +1233,16 @@ static struct sk_buff *bcm_sysport_insert_tsb(struct sk_buff *skb,
|
|
|
/* Re-allocate SKB if needed */
|
|
|
if (unlikely(skb_headroom(skb) < sizeof(*tsb))) {
|
|
|
nskb = skb_realloc_headroom(skb, sizeof(*tsb));
|
|
|
- dev_kfree_skb(skb);
|
|
|
if (!nskb) {
|
|
|
+ dev_kfree_skb_any(skb);
|
|
|
+ priv->mib.tx_realloc_tsb_failed++;
|
|
|
dev->stats.tx_errors++;
|
|
|
dev->stats.tx_dropped++;
|
|
|
return NULL;
|
|
|
}
|
|
|
+ dev_consume_skb_any(skb);
|
|
|
skb = nskb;
|
|
|
+ priv->mib.tx_realloc_tsb++;
|
|
|
}
|
|
|
|
|
|
tsb = skb_push(skb, sizeof(*tsb));
|
|
@@ -1973,16 +1978,14 @@ static int bcm_sysport_open(struct net_device *dev)
|
|
|
else
|
|
|
gib_set_pad_extension(priv);
|
|
|
|
|
|
+ /* Apply features again in case we changed them while interface was
|
|
|
+ * down
|
|
|
+ */
|
|
|
+ bcm_sysport_set_features(dev, dev->features);
|
|
|
+
|
|
|
/* Set MAC address */
|
|
|
umac_set_hw_addr(priv, dev->dev_addr);
|
|
|
|
|
|
- /* Read CRC forward */
|
|
|
- if (!priv->is_lite)
|
|
|
- priv->crc_fwd = !!(umac_readl(priv, UMAC_CMD) & CMD_CRC_FWD);
|
|
|
- else
|
|
|
- priv->crc_fwd = !((gib_readl(priv, GIB_CONTROL) &
|
|
|
- GIB_FCS_STRIP) >> GIB_FCS_STRIP_SHIFT);
|
|
|
-
|
|
|
phydev = of_phy_connect(dev, priv->phy_dn, bcm_sysport_adj_link,
|
|
|
0, priv->phy_interface);
|
|
|
if (!phydev) {
|
|
@@ -2511,9 +2514,10 @@ static int bcm_sysport_probe(struct platform_device *pdev)
|
|
|
dev->netdev_ops = &bcm_sysport_netdev_ops;
|
|
|
netif_napi_add(dev, &priv->napi, bcm_sysport_poll, 64);
|
|
|
|
|
|
- /* HW supported features, none enabled by default */
|
|
|
- dev->hw_features |= NETIF_F_RXCSUM | NETIF_F_HIGHDMA |
|
|
|
- NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
|
|
|
+ dev->features |= NETIF_F_RXCSUM | NETIF_F_HIGHDMA |
|
|
|
+ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
|
|
|
+ dev->hw_features |= dev->features;
|
|
|
+ dev->vlan_features |= dev->features;
|
|
|
|
|
|
/* Request the WOL interrupt and advertise suspend if available */
|
|
|
priv->wol_irq_disabled = 1;
|
|
@@ -2716,7 +2720,6 @@ static int __maybe_unused bcm_sysport_resume(struct device *d)
|
|
|
struct net_device *dev = dev_get_drvdata(d);
|
|
|
struct bcm_sysport_priv *priv = netdev_priv(dev);
|
|
|
unsigned int i;
|
|
|
- u32 reg;
|
|
|
int ret;
|
|
|
|
|
|
if (!netif_running(dev))
|
|
@@ -2760,12 +2763,8 @@ static int __maybe_unused bcm_sysport_resume(struct device *d)
|
|
|
goto out_free_rx_ring;
|
|
|
}
|
|
|
|
|
|
- /* Enable rxhck */
|
|
|
- if (priv->rx_chk_en) {
|
|
|
- reg = rxchk_readl(priv, RXCHK_CONTROL);
|
|
|
- reg |= RXCHK_EN;
|
|
|
- rxchk_writel(priv, reg, RXCHK_CONTROL);
|
|
|
- }
|
|
|
+ /* Restore enabled features */
|
|
|
+ bcm_sysport_set_features(dev, dev->features);
|
|
|
|
|
|
rbuf_init(priv);
|
|
|
|