Skip to content

Commit

Permalink
net: stmmac: fix get_hw_feature() on old hardware
Browse files Browse the repository at this point in the history
Some old IPs do not provide the hardware feature register.
On these IPs, this register is read 0x00000000.

In old driver version, this feature was handled but a regression came
with the commit f10a6a3 ("stmmac: rework get_hw_feature function").
Indeed, this commit removes the return value in dma->get_hw_feature().
This return value was used to indicate the validity of retrieved
information and used later on in stmmac_hw_init() to override
priv->plat data if this hardware feature were valid.

This patch restores the return code in ->get_hw_feature() in order
to indicate the hardware feature validity and override priv->plat
data only if this hardware feature is valid.

Fixes: f10a6a3 ("stmmac: rework get_hw_feature function")
Signed-off-by: Herve Codina <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
hcodina authored and davem330 committed Oct 8, 2021
1 parent 612f71d commit 075da58
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 9 deletions.
13 changes: 11 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,18 @@ static void dwmac1000_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
readl(ioaddr + DMA_BUS_MODE + i * 4);
}

static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
struct dma_features *dma_cap)
static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
struct dma_features *dma_cap)
{
u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);

if (!hw_cap) {
/* 0x00000000 is the value read on old hardware that does not
* implement this register
*/
return -EOPNOTSUPP;
}

dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
Expand Down Expand Up @@ -252,6 +259,8 @@ static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
/* Alternate (enhanced) DESC mode */
dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;

return 0;
}

static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt,
Expand Down
6 changes: 4 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,8 @@ static void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode,
writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel));
}

static void dwmac4_get_hw_feature(void __iomem *ioaddr,
struct dma_features *dma_cap)
static int dwmac4_get_hw_feature(void __iomem *ioaddr,
struct dma_features *dma_cap)
{
u32 hw_cap = readl(ioaddr + GMAC_HW_FEATURE0);

Expand Down Expand Up @@ -437,6 +437,8 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
dma_cap->frpbs = (hw_cap & GMAC_HW_FEAT_FRPBS) >> 11;
dma_cap->frpsel = (hw_cap & GMAC_HW_FEAT_FRPSEL) >> 10;
dma_cap->dvlan = (hw_cap & GMAC_HW_FEAT_DVLAN) >> 5;

return 0;
}

/* Enable/disable TSO feature and set MSS */
Expand Down
6 changes: 4 additions & 2 deletions drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,8 +371,8 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
return ret;
}

static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
struct dma_features *dma_cap)
static int dwxgmac2_get_hw_feature(void __iomem *ioaddr,
struct dma_features *dma_cap)
{
u32 hw_cap;

Expand Down Expand Up @@ -445,6 +445,8 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11;
dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9;
dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3;

return 0;
}

static void dwxgmac2_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 queue)
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/ethernet/stmicro/stmmac/hwif.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ struct stmmac_dma_ops {
int (*dma_interrupt) (void __iomem *ioaddr,
struct stmmac_extra_stats *x, u32 chan, u32 dir);
/* If supported then get the optional core features */
void (*get_hw_feature)(void __iomem *ioaddr,
struct dma_features *dma_cap);
int (*get_hw_feature)(void __iomem *ioaddr,
struct dma_features *dma_cap);
/* Program the HW RX Watchdog */
void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt, u32 queue);
void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len, u32 chan);
Expand Down Expand Up @@ -255,7 +255,7 @@ struct stmmac_dma_ops {
#define stmmac_dma_interrupt_status(__priv, __args...) \
stmmac_do_callback(__priv, dma, dma_interrupt, __args)
#define stmmac_get_hw_feature(__priv, __args...) \
stmmac_do_void_callback(__priv, dma, get_hw_feature, __args)
stmmac_do_callback(__priv, dma, get_hw_feature, __args)
#define stmmac_rx_watchdog(__priv, __args...) \
stmmac_do_void_callback(__priv, dma, rx_watchdog, __args)
#define stmmac_set_tx_ring_len(__priv, __args...) \
Expand Down

0 comments on commit 075da58

Please sign in to comment.