Skip to content

Commit 9053c5b

Browse files
hcodinagregkh
authored andcommitted
net: stmmac: fix get_hw_feature() on old hardware
commit 075da58 upstream. 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]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 12da46c commit 9053c5b

File tree

4 files changed

+22
-9
lines changed

4 files changed

+22
-9
lines changed

drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,18 @@ static void dwmac1000_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space)
218218
readl(ioaddr + DMA_BUS_MODE + i * 4);
219219
}
220220

221-
static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
222-
struct dma_features *dma_cap)
221+
static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
222+
struct dma_features *dma_cap)
223223
{
224224
u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
225225

226+
if (!hw_cap) {
227+
/* 0x00000000 is the value read on old hardware that does not
228+
* implement this register
229+
*/
230+
return -EOPNOTSUPP;
231+
}
232+
226233
dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
227234
dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
228235
dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
@@ -252,6 +259,8 @@ static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
252259
dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
253260
/* Alternate (enhanced) DESC mode */
254261
dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
262+
263+
return 0;
255264
}
256265

257266
static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt,

drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,8 @@ static void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode,
337337
writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel));
338338
}
339339

340-
static void dwmac4_get_hw_feature(void __iomem *ioaddr,
341-
struct dma_features *dma_cap)
340+
static int dwmac4_get_hw_feature(void __iomem *ioaddr,
341+
struct dma_features *dma_cap)
342342
{
343343
u32 hw_cap = readl(ioaddr + GMAC_HW_FEATURE0);
344344

@@ -425,6 +425,8 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
425425
dma_cap->frpbs = (hw_cap & GMAC_HW_FEAT_FRPBS) >> 11;
426426
dma_cap->frpsel = (hw_cap & GMAC_HW_FEAT_FRPSEL) >> 10;
427427
dma_cap->dvlan = (hw_cap & GMAC_HW_FEAT_DVLAN) >> 5;
428+
429+
return 0;
428430
}
429431

430432
/* Enable/disable TSO feature and set MSS */

drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,8 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
365365
return ret;
366366
}
367367

368-
static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
369-
struct dma_features *dma_cap)
368+
static int dwxgmac2_get_hw_feature(void __iomem *ioaddr,
369+
struct dma_features *dma_cap)
370370
{
371371
u32 hw_cap;
372372

@@ -439,6 +439,8 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
439439
dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11;
440440
dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9;
441441
dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3;
442+
443+
return 0;
442444
}
443445

444446
static void dwxgmac2_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 nchan)

drivers/net/ethernet/stmicro/stmmac/hwif.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ struct stmmac_dma_ops {
203203
int (*dma_interrupt) (void __iomem *ioaddr,
204204
struct stmmac_extra_stats *x, u32 chan);
205205
/* If supported then get the optional core features */
206-
void (*get_hw_feature)(void __iomem *ioaddr,
207-
struct dma_features *dma_cap);
206+
int (*get_hw_feature)(void __iomem *ioaddr,
207+
struct dma_features *dma_cap);
208208
/* Program the HW RX Watchdog */
209209
void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt, u32 number_chan);
210210
void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len, u32 chan);
@@ -255,7 +255,7 @@ struct stmmac_dma_ops {
255255
#define stmmac_dma_interrupt_status(__priv, __args...) \
256256
stmmac_do_callback(__priv, dma, dma_interrupt, __args)
257257
#define stmmac_get_hw_feature(__priv, __args...) \
258-
stmmac_do_void_callback(__priv, dma, get_hw_feature, __args)
258+
stmmac_do_callback(__priv, dma, get_hw_feature, __args)
259259
#define stmmac_rx_watchdog(__priv, __args...) \
260260
stmmac_do_void_callback(__priv, dma, rx_watchdog, __args)
261261
#define stmmac_set_tx_ring_len(__priv, __args...) \

0 commit comments

Comments
 (0)