Commit c1e85c6c authored by Claudiu Beznea's avatar Claudiu Beznea Committed by David S. Miller

net: macb: save/restore the remaining registers and features

SAMA5D2 SoC has a suspend mode where SoC's power is cut off. Due to this
the registers content is lost after a suspend/resume cycle. The current
suspend/resume implementation covers some of these registers. However
there are few which were not treated (e.g. SCRT2 and USRIO). Apart
from this, netdev features are not restored. Treat these issues.
Signed-off-by: default avatarClaudiu Beznea <claudiu.beznea@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8f073036
......@@ -1080,6 +1080,11 @@ struct macb_ptp_info {
struct ifreq *ifr, int cmd);
};
struct macb_pm_data {
u32 scrt2;
u32 usrio;
};
struct macb_config {
u32 caps;
unsigned int dma_burst_length;
......@@ -1220,6 +1225,8 @@ struct macb {
int tx_bd_rd_prefetch;
u32 rx_intr_mask;
struct macb_pm_data pm_data;
};
#ifdef CONFIG_MACB_USE_HWSTAMP
......
......@@ -2849,10 +2849,14 @@ static int macb_get_ts_info(struct net_device *netdev,
static void gem_enable_flow_filters(struct macb *bp, bool enable)
{
struct net_device *netdev = bp->dev;
struct ethtool_rx_fs_item *item;
u32 t2_scr;
int num_t2_scr;
if (!(netdev->features & NETIF_F_NTUPLE))
return;
num_t2_scr = GEM_BFEXT(T2SCR, gem_readl(bp, DCFG8));
list_for_each_entry(item, &bp->rx_fs_list.list, list) {
......@@ -3012,7 +3016,6 @@ static int gem_add_flow_filter(struct net_device *netdev,
gem_prog_cmp_regs(bp, fs);
bp->rx_fs_list.count++;
/* enable filtering if NTUPLE on */
if (netdev->features & NETIF_F_NTUPLE)
gem_enable_flow_filters(bp, 1);
spin_unlock_irqrestore(&bp->rx_fs_lock, flags);
......@@ -3201,46 +3204,86 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
}
static int macb_set_features(struct net_device *netdev,
static inline void macb_set_txcsum_feature(struct macb *bp,
netdev_features_t features)
{
struct macb *bp = netdev_priv(netdev);
netdev_features_t changed = features ^ netdev->features;
u32 val;
/* TX checksum offload */
if ((changed & NETIF_F_HW_CSUM) && macb_is_gem(bp)) {
u32 dmacfg;
if (!macb_is_gem(bp))
return;
dmacfg = gem_readl(bp, DMACFG);
val = gem_readl(bp, DMACFG);
if (features & NETIF_F_HW_CSUM)
dmacfg |= GEM_BIT(TXCOEN);
val |= GEM_BIT(TXCOEN);
else
dmacfg &= ~GEM_BIT(TXCOEN);
gem_writel(bp, DMACFG, dmacfg);
}
val &= ~GEM_BIT(TXCOEN);
/* RX checksum offload */
if ((changed & NETIF_F_RXCSUM) && macb_is_gem(bp)) {
u32 netcfg;
gem_writel(bp, DMACFG, val);
}
static inline void macb_set_rxcsum_feature(struct macb *bp,
netdev_features_t features)
{
struct net_device *netdev = bp->dev;
u32 val;
if (!macb_is_gem(bp))
return;
netcfg = gem_readl(bp, NCFGR);
if (features & NETIF_F_RXCSUM &&
!(netdev->flags & IFF_PROMISC))
netcfg |= GEM_BIT(RXCOEN);
val = gem_readl(bp, NCFGR);
if ((features & NETIF_F_RXCSUM) && !(netdev->flags & IFF_PROMISC))
val |= GEM_BIT(RXCOEN);
else
netcfg &= ~GEM_BIT(RXCOEN);
gem_writel(bp, NCFGR, netcfg);
}
val &= ~GEM_BIT(RXCOEN);
gem_writel(bp, NCFGR, val);
}
static inline void macb_set_rxflow_feature(struct macb *bp,
netdev_features_t features)
{
if (!macb_is_gem(bp))
return;
gem_enable_flow_filters(bp, !!(features & NETIF_F_NTUPLE));
}
static int macb_set_features(struct net_device *netdev,
netdev_features_t features)
{
struct macb *bp = netdev_priv(netdev);
netdev_features_t changed = features ^ netdev->features;
/* TX checksum offload */
if (changed & NETIF_F_HW_CSUM)
macb_set_txcsum_feature(bp, features);
/* RX checksum offload */
if (changed & NETIF_F_RXCSUM)
macb_set_rxcsum_feature(bp, features);
/* RX Flow Filters */
if ((changed & NETIF_F_NTUPLE) && macb_is_gem(bp)) {
bool turn_on = features & NETIF_F_NTUPLE;
if (changed & NETIF_F_NTUPLE)
macb_set_rxflow_feature(bp, features);
gem_enable_flow_filters(bp, turn_on);
}
return 0;
}
static void macb_restore_features(struct macb *bp)
{
struct net_device *netdev = bp->dev;
netdev_features_t features = netdev->features;
/* TX checksum offload */
macb_set_txcsum_feature(bp, features);
/* RX checksum offload */
macb_set_rxcsum_feature(bp, features);
/* RX Flow Filters */
macb_set_rxflow_feature(bp, features);
}
static const struct net_device_ops macb_netdev_ops = {
.ndo_open = macb_open,
.ndo_stop = macb_close,
......@@ -4273,6 +4316,12 @@ static int __maybe_unused macb_suspend(struct device *dev)
spin_lock_irqsave(&bp->lock, flags);
macb_reset_hw(bp);
spin_unlock_irqrestore(&bp->lock, flags);
if (!(bp->caps & MACB_CAPS_USRIO_DISABLED))
bp->pm_data.usrio = macb_or_gem_readl(bp, USRIO);
if (netdev->hw_features & NETIF_F_NTUPLE)
bp->pm_data.scrt2 = gem_readl_n(bp, ETHT, SCRT2_ETHT);
}
netif_carrier_off(netdev);
......@@ -4301,6 +4350,13 @@ static int __maybe_unused macb_resume(struct device *dev)
disable_irq_wake(bp->queues[0].irq);
} else {
macb_writel(bp, NCR, MACB_BIT(MPE));
if (netdev->hw_features & NETIF_F_NTUPLE)
gem_writel_n(bp, ETHT, SCRT2_ETHT, bp->pm_data.scrt2);
if (!(bp->caps & MACB_CAPS_USRIO_DISABLED))
macb_or_gem_writel(bp, USRIO, bp->pm_data.usrio);
for (q = 0, queue = bp->queues; q < bp->num_queues;
++q, ++queue)
napi_enable(&queue->napi);
......@@ -4312,6 +4368,7 @@ static int __maybe_unused macb_resume(struct device *dev)
bp->macbgem_ops.mog_init_rings(bp);
macb_init_hw(bp);
macb_set_rx_mode(netdev);
macb_restore_features(bp);
netif_device_attach(netdev);
if (bp->ptp_info)
bp->ptp_info->ptp_init(netdev);
......
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