Skip to content

Commit

Permalink
Merge branch 'net-ethernet-mtk_wed-introduce-reset-support'
Browse files Browse the repository at this point in the history
Lorenzo Bianconi says:

====================
net: ethernet: mtk_wed: introduce reset support

Introduce proper reset integration between ethernet and wlan drivers in order
to schedule wlan driver reset when ethernet/wed driver is resetting.
Introduce mtk_hw_reset_monitor work in order to detect possible DMA hangs.
====================

Link: https://lore.kernel.org/r/cover.1673715298.git.lorenzo@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Paolo Abeni committed Jan 17, 2023
2 parents 05cb8b3 + 08a764a commit 7875c01
Show file tree
Hide file tree
Showing 8 changed files with 383 additions and 39 deletions.
297 changes: 258 additions & 39 deletions drivers/net/ethernet/mediatek/mtk_eth_soc.c

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions drivers/net/ethernet/mediatek/mtk_eth_soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,24 @@
#define MTK_HW_LRO_REPLACE_DELTA 1000
#define MTK_HW_LRO_SDL_REMAIN_ROOM 1522

/* Frame Engine Global Configuration */
#define MTK_FE_GLO_CFG 0x00
#define MTK_FE_LINK_DOWN_P3 BIT(11)
#define MTK_FE_LINK_DOWN_P4 BIT(12)

/* Frame Engine Global Reset Register */
#define MTK_RST_GL 0x04
#define RST_GL_PSE BIT(0)

/* Frame Engine Interrupt Status Register */
#define MTK_INT_STATUS2 0x08
#define MTK_FE_INT_ENABLE 0x0c
#define MTK_FE_INT_FQ_EMPTY BIT(8)
#define MTK_FE_INT_TSO_FAIL BIT(12)
#define MTK_FE_INT_TSO_ILLEGAL BIT(13)
#define MTK_FE_INT_TSO_ALIGN BIT(14)
#define MTK_FE_INT_RFIFO_OV BIT(18)
#define MTK_FE_INT_RFIFO_UF BIT(19)
#define MTK_GDM1_AF BIT(28)
#define MTK_GDM2_AF BIT(29)

Expand Down Expand Up @@ -272,6 +284,8 @@

#define MTK_RX_DONE_INT_V2 BIT(14)

#define MTK_CDM_TXFIFO_RDY BIT(7)

/* QDMA Interrupt grouping registers */
#define MTK_RLS_DONE_INT BIT(0)

Expand Down Expand Up @@ -562,6 +576,17 @@
#define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c)
#define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110)

#define MTK_FE_CDM1_FSM 0x220
#define MTK_FE_CDM2_FSM 0x224
#define MTK_FE_CDM3_FSM 0x238
#define MTK_FE_CDM4_FSM 0x298
#define MTK_FE_CDM5_FSM 0x318
#define MTK_FE_CDM6_FSM 0x328
#define MTK_FE_GDM1_FSM 0x228
#define MTK_FE_GDM2_FSM 0x22C

#define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100))

struct mtk_rx_dma {
unsigned int rxd1;
unsigned int rxd2;
Expand Down Expand Up @@ -958,6 +983,7 @@ struct mtk_reg_map {
u32 delay_irq; /* delay interrupt */
u32 irq_status; /* interrupt status */
u32 irq_mask; /* interrupt mask */
u32 adma_rx_dbg0;
u32 int_grp;
} pdma;
struct {
Expand Down Expand Up @@ -986,6 +1012,8 @@ struct mtk_reg_map {
u32 gdma_to_ppe;
u32 ppe_base;
u32 wdma_base[2];
u32 pse_iq_sta;
u32 pse_oq_sta;
};

/* struct mtk_eth_data - This is the structure holding all differences
Expand Down Expand Up @@ -1028,6 +1056,8 @@ struct mtk_soc_data {
} txrx;
};

#define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000)

/* currently no SoC has more than 2 macs */
#define MTK_MAX_DEVS 2

Expand Down Expand Up @@ -1152,6 +1182,14 @@ struct mtk_eth {
struct rhashtable flow_table;

struct bpf_prog __rcu *prog;

struct {
struct delayed_work monitor_work;
u32 wdidx;
u8 wdma_hang_count;
u8 qdma_hang_count;
u8 adma_hang_count;
} reset;
};

/* struct mtk_mac - the structure that holds the info about the MACs of the
Expand Down
27 changes: 27 additions & 0 deletions drivers/net/ethernet/mediatek/mtk_ppe.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,33 @@ int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
return __mtk_foe_entry_idle_time(ppe, entry->data.ib1);
}

int mtk_ppe_prepare_reset(struct mtk_ppe *ppe)
{
if (!ppe)
return -EINVAL;

/* disable KA */
ppe_clear(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_KEEPALIVE);
ppe_clear(ppe, MTK_PPE_BIND_LMT1, MTK_PPE_NTU_KEEPALIVE);
ppe_w32(ppe, MTK_PPE_KEEPALIVE, 0);
usleep_range(10000, 11000);

/* set KA timer to maximum */
ppe_set(ppe, MTK_PPE_BIND_LMT1, MTK_PPE_NTU_KEEPALIVE);
ppe_w32(ppe, MTK_PPE_KEEPALIVE, 0xffffffff);

/* set KA tick select */
ppe_set(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_TICK_SEL);
ppe_set(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_KEEPALIVE);
usleep_range(10000, 11000);

/* disable scan mode */
ppe_clear(ppe, MTK_PPE_TB_CFG, MTK_PPE_TB_CFG_SCAN_MODE);
usleep_range(10000, 11000);

return mtk_ppe_wait_busy(ppe);
}

struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
int version, int index)
{
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mediatek/mtk_ppe.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base,
void mtk_ppe_deinit(struct mtk_eth *eth);
void mtk_ppe_start(struct mtk_ppe *ppe);
int mtk_ppe_stop(struct mtk_ppe *ppe);
int mtk_ppe_prepare_reset(struct mtk_ppe *ppe);

void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash);

Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/mediatek/mtk_ppe_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@
#define MTK_PPE_TB_CFG_SCAN_MODE GENMASK(17, 16)
#define MTK_PPE_TB_CFG_HASH_DEBUG GENMASK(19, 18)
#define MTK_PPE_TB_CFG_INFO_SEL BIT(20)
#define MTK_PPE_TB_TICK_SEL BIT(24)

#define MTK_PPE_BIND_LMT1 0x230
#define MTK_PPE_NTU_KEEPALIVE GENMASK(23, 16)

#define MTK_PPE_KEEPALIVE 0x234

enum {
MTK_PPE_SCAN_MODE_DISABLED,
Expand Down
42 changes: 42 additions & 0 deletions drivers/net/ethernet/mediatek/mtk_wed.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,48 @@ mtk_wed_wo_reset(struct mtk_wed_device *dev)
iounmap(reg);
}

void mtk_wed_fe_reset(void)
{
int i;

mutex_lock(&hw_lock);

for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
struct mtk_wed_hw *hw = hw_list[i];
struct mtk_wed_device *dev = hw->wed_dev;
int err;

if (!dev || !dev->wlan.reset)
continue;

/* reset callback blocks until WLAN reset is completed */
err = dev->wlan.reset(dev);
if (err)
dev_err(dev->dev, "wlan reset failed: %d\n", err);
}

mutex_unlock(&hw_lock);
}

void mtk_wed_fe_reset_complete(void)
{
int i;

mutex_lock(&hw_lock);

for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
struct mtk_wed_hw *hw = hw_list[i];
struct mtk_wed_device *dev = hw->wed_dev;

if (!dev || !dev->wlan.reset_complete)
continue;

dev->wlan.reset_complete(dev);
}

mutex_unlock(&hw_lock);
}

static struct mtk_wed_hw *
mtk_wed_assign(struct mtk_wed_device *dev)
{
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/mediatek/mtk_wed.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ void mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
void mtk_wed_exit(void);
int mtk_wed_flow_add(int index);
void mtk_wed_flow_remove(int index);
void mtk_wed_fe_reset(void);
void mtk_wed_fe_reset_complete(void);
#else
static inline void
mtk_wed_add_hw(struct device_node *np, struct mtk_eth *eth,
Expand All @@ -147,6 +149,13 @@ static inline void mtk_wed_flow_remove(int index)
{
}

static inline void mtk_wed_fe_reset(void)
{
}

static inline void mtk_wed_fe_reset_complete(void)
{
}
#endif

#ifdef CONFIG_DEBUG_FS
Expand Down
2 changes: 2 additions & 0 deletions include/linux/soc/mediatek/mtk_wed.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ struct mtk_wed_device {
void (*release_rx_buf)(struct mtk_wed_device *wed);
void (*update_wo_rx_stats)(struct mtk_wed_device *wed,
struct mtk_wed_wo_rx_stats *stats);
int (*reset)(struct mtk_wed_device *wed);
void (*reset_complete)(struct mtk_wed_device *wed);
} wlan;
#endif
};
Expand Down

0 comments on commit 7875c01

Please sign in to comment.