mirror of
https://github.com/torvalds/linux.git
synced 2026-06-06 21:45:45 +02:00
net: stmmac: fix get_hw_feature() on old hardware
commit075da584baupstream. 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 commitf10a6a3541("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:f10a6a3541("stmmac: rework get_hw_feature function") Signed-off-by: Herve Codina <herve.codina@bootlin.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
12da46cb6a
commit
9053c5b459
|
|
@ -218,11 +218,18 @@ static void dwmac1000_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
|
||||||
readl(ioaddr + DMA_BUS_MODE + i * 4);
|
readl(ioaddr + DMA_BUS_MODE + i * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
|
static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
|
||||||
struct dma_features *dma_cap)
|
struct dma_features *dma_cap)
|
||||||
{
|
{
|
||||||
u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
|
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_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
|
||||||
dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
|
dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
|
||||||
dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
|
dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
|
||||||
|
|
@ -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;
|
dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
|
||||||
/* Alternate (enhanced) DESC mode */
|
/* Alternate (enhanced) DESC mode */
|
||||||
dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
|
dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt,
|
static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt,
|
||||||
|
|
|
||||||
|
|
@ -337,8 +337,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));
|
writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwmac4_get_hw_feature(void __iomem *ioaddr,
|
static int dwmac4_get_hw_feature(void __iomem *ioaddr,
|
||||||
struct dma_features *dma_cap)
|
struct dma_features *dma_cap)
|
||||||
{
|
{
|
||||||
u32 hw_cap = readl(ioaddr + GMAC_HW_FEATURE0);
|
u32 hw_cap = readl(ioaddr + GMAC_HW_FEATURE0);
|
||||||
|
|
||||||
|
|
@ -425,6 +425,8 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
|
||||||
dma_cap->frpbs = (hw_cap & GMAC_HW_FEAT_FRPBS) >> 11;
|
dma_cap->frpbs = (hw_cap & GMAC_HW_FEAT_FRPBS) >> 11;
|
||||||
dma_cap->frpsel = (hw_cap & GMAC_HW_FEAT_FRPSEL) >> 10;
|
dma_cap->frpsel = (hw_cap & GMAC_HW_FEAT_FRPSEL) >> 10;
|
||||||
dma_cap->dvlan = (hw_cap & GMAC_HW_FEAT_DVLAN) >> 5;
|
dma_cap->dvlan = (hw_cap & GMAC_HW_FEAT_DVLAN) >> 5;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable/disable TSO feature and set MSS */
|
/* Enable/disable TSO feature and set MSS */
|
||||||
|
|
|
||||||
|
|
@ -365,8 +365,8 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
|
static int dwxgmac2_get_hw_feature(void __iomem *ioaddr,
|
||||||
struct dma_features *dma_cap)
|
struct dma_features *dma_cap)
|
||||||
{
|
{
|
||||||
u32 hw_cap;
|
u32 hw_cap;
|
||||||
|
|
||||||
|
|
@ -439,6 +439,8 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
|
||||||
dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11;
|
dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11;
|
||||||
dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9;
|
dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9;
|
||||||
dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3;
|
dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwxgmac2_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 nchan)
|
static void dwxgmac2_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 nchan)
|
||||||
|
|
|
||||||
|
|
@ -203,8 +203,8 @@ struct stmmac_dma_ops {
|
||||||
int (*dma_interrupt) (void __iomem *ioaddr,
|
int (*dma_interrupt) (void __iomem *ioaddr,
|
||||||
struct stmmac_extra_stats *x, u32 chan);
|
struct stmmac_extra_stats *x, u32 chan);
|
||||||
/* If supported then get the optional core features */
|
/* If supported then get the optional core features */
|
||||||
void (*get_hw_feature)(void __iomem *ioaddr,
|
int (*get_hw_feature)(void __iomem *ioaddr,
|
||||||
struct dma_features *dma_cap);
|
struct dma_features *dma_cap);
|
||||||
/* Program the HW RX Watchdog */
|
/* Program the HW RX Watchdog */
|
||||||
void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt, u32 number_chan);
|
void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt, u32 number_chan);
|
||||||
void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len, u32 chan);
|
void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len, u32 chan);
|
||||||
|
|
@ -255,7 +255,7 @@ struct stmmac_dma_ops {
|
||||||
#define stmmac_dma_interrupt_status(__priv, __args...) \
|
#define stmmac_dma_interrupt_status(__priv, __args...) \
|
||||||
stmmac_do_callback(__priv, dma, dma_interrupt, __args)
|
stmmac_do_callback(__priv, dma, dma_interrupt, __args)
|
||||||
#define stmmac_get_hw_feature(__priv, __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...) \
|
#define stmmac_rx_watchdog(__priv, __args...) \
|
||||||
stmmac_do_void_callback(__priv, dma, rx_watchdog, __args)
|
stmmac_do_void_callback(__priv, dma, rx_watchdog, __args)
|
||||||
#define stmmac_set_tx_ring_len(__priv, __args...) \
|
#define stmmac_set_tx_ring_len(__priv, __args...) \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user