mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
Merge branch 'net-macb-implement-context-swapping'
says: ==================== net: macb: implement context swapping MACB has a pretty primitive approach to buffer management. They are all stored in `struct macb *bp`. On operations that require buffer realloc (set_ringparam & change_mtu at the moment), the only option is to close the interface, change our global state and re-open the interface. Two issues: - It doesn't fly on memory pressured systems; we free our precious buffers and don't manage to reallocate fully, meaning our machine just lost its network access. - Anecdotally, it is pretty slow because it implies a full PHY reinit. Instead, we shall: - allocate a new context (including buffers) first - if it fails, early return without any impact to the interface - stop interface - update global state (bp, netdev, etc) - pass newly allocated buffer pointers to the hardware - start interface - free old context This is what we implement here. Both .set_ringparam() and .ndo_change_mtu() are covered by this series. In the future, at least .set_channels() [0], XDP [1] and XSK [2] would benefit. Tested-by: Nicolai Buchwitz <nb@tipi-net.de> # RPi CM5 with RP1 GEM --- I wonder if we can get those changes in before the next merge window? The idea being that we can restart iterating on XDP [1] & XSK [2] during the next kernel cycle, bringing those long awaited features into MACB. [0]: https://lore.kernel.org/netdev/20260317-macb-set-channels-v4-0-1bd4f4ffcfca@bootlin.com/ [1]: https://lore.kernel.org/netdev/20260323221047.2749577-1-pvalerio@redhat.com/ [2]: https://lore.kernel.org/netdev/20260304-macb-xsk-v1-0-ba2ebe2bdaa3@bootlin.com/ [3]: https://lore.kernel.org/all/DJXGIM9EGPT8.4UHNYP2Y0GOP@bootlin.com/ [4]: https://lore.kernel.org/netdev/20260930-macb-irq-v1-1-8994a4c8f3bb@bootlin.com/ [5]: https://lore.kernel.org/netdev/20260918-macb-ncr-rmw-v1-1-30c3494f93cd@bootlin.com/ - v10: https://patch.msgid.link/20261001-macb-context-v10-0-beb541bbb7df@bootlin.com - v9: https://patch.msgid.link/20260812-macb-context-v9-0-7ddbf5f715e0@bootlin.com - v8: https://patch.msgid.link/20260805-macb-context-v8-0-bc302ffd1174@bootlin.com - v7: https://patch.msgid.link/20260803-macb-context-v7-0-4d7d4af04849@bootlin.com - v6: https://patch.msgid.link/20260731-macb-context-v6-0-49d5a1439d48@bootlin.com - v5: https://patch.msgid.link/20260724-macb-context-v5-0-569b1852bc7f@bootlin.com - v4: https://patch.msgid.link/20260717-macb-context-v4-0-0acbe7f10cdb@bootlin.com - v3: https://patch.msgid.link/20260701-macb-context-v3-0-00268d5b1502@bootlin.com - v2: https://patch.msgid.link/20260410-macb-context-v2-0-af39f71d40b6@bootlin.com - v1: https://patch.msgid.link/20260401-macb-context-v1-0-9590c5ab7272@bootlin.com ==================== Link: https://patch.msgid.link/20261013-macb-context-v11-0-b27785167566@bootlin.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
f34e7e8875
|
|
@ -834,7 +834,7 @@
|
|||
*/
|
||||
#define macb_or_gem_writel(__bp, __reg, __value) \
|
||||
({ \
|
||||
if (macb_is_gem((__bp))) \
|
||||
if (macb_is_gem(&(__bp)->info)) \
|
||||
gem_writel((__bp), __reg, __value); \
|
||||
else \
|
||||
macb_writel((__bp), __reg, __value); \
|
||||
|
|
@ -843,7 +843,7 @@
|
|||
#define macb_or_gem_readl(__bp, __reg) \
|
||||
({ \
|
||||
u32 __v; \
|
||||
if (macb_is_gem((__bp))) \
|
||||
if (macb_is_gem(&(__bp)->info)) \
|
||||
__v = gem_readl((__bp), __reg); \
|
||||
else \
|
||||
__v = macb_readl((__bp), __reg); \
|
||||
|
|
@ -1193,11 +1193,12 @@ static const struct gem_statistic queue_statistics[] = {
|
|||
|
||||
struct macb;
|
||||
struct macb_queue;
|
||||
struct macb_context;
|
||||
|
||||
struct macb_or_gem_ops {
|
||||
int (*mog_alloc_rx_buffers)(struct macb *bp);
|
||||
void (*mog_free_rx_buffers)(struct macb *bp);
|
||||
int (*mog_init_rings)(struct macb *bp);
|
||||
int (*mog_alloc_rx_buffers)(struct macb_context *ctx);
|
||||
void (*mog_free_rx_buffers)(struct macb_context *ctx);
|
||||
int (*mog_init_rings)(struct macb_context *ctx);
|
||||
int (*mog_rx)(struct macb_queue *queue, struct napi_struct *napi,
|
||||
int budget);
|
||||
};
|
||||
|
|
@ -1267,23 +1268,12 @@ struct macb_queue {
|
|||
unsigned int ENST_ON_TIME;
|
||||
unsigned int ENST_OFF_TIME;
|
||||
|
||||
/* Lock to protect tx_head and tx_tail */
|
||||
/* Lock to protect ctx->txq[q].head and ctx->txq[q].tail */
|
||||
spinlock_t tx_ptr_lock;
|
||||
unsigned int tx_head, tx_tail;
|
||||
struct macb_dma_desc *tx_ring;
|
||||
struct macb_tx_skb *tx_skb;
|
||||
dma_addr_t tx_ring_dma;
|
||||
struct work_struct tx_error_task;
|
||||
bool txubr_pending;
|
||||
struct napi_struct napi_tx;
|
||||
|
||||
dma_addr_t rx_ring_dma;
|
||||
dma_addr_t rx_buffers_dma;
|
||||
unsigned int rx_tail;
|
||||
unsigned int rx_prepared_head;
|
||||
struct macb_dma_desc *rx_ring;
|
||||
struct sk_buff **rx_skbuff;
|
||||
void *rx_buffers;
|
||||
struct napi_struct napi_rx;
|
||||
struct queue_stats stats;
|
||||
};
|
||||
|
|
@ -1298,6 +1288,45 @@ struct ethtool_rx_fs_list {
|
|||
unsigned int count;
|
||||
};
|
||||
|
||||
struct macb_info {
|
||||
struct platform_device *pdev;
|
||||
struct net_device *netdev;
|
||||
struct macb_or_gem_ops macbgem_ops;
|
||||
unsigned int num_queues;
|
||||
u32 caps;
|
||||
int rx_bd_rd_prefetch;
|
||||
int tx_bd_rd_prefetch;
|
||||
struct queue_stats *queue_stats[MACB_MAX_QUEUES];
|
||||
};
|
||||
|
||||
struct macb_rxq {
|
||||
struct macb_dma_desc *ring; /* MACB & GEM */
|
||||
dma_addr_t ring_dma; /* MACB & GEM */
|
||||
unsigned int tail; /* MACB & GEM */
|
||||
unsigned int prepared_head; /* GEM */
|
||||
struct sk_buff **skbuff; /* GEM */
|
||||
dma_addr_t buffers_dma; /* MACB */
|
||||
void *buffers; /* MACB */
|
||||
};
|
||||
|
||||
struct macb_txq {
|
||||
unsigned int head;
|
||||
unsigned int tail;
|
||||
struct macb_dma_desc *ring;
|
||||
dma_addr_t ring_dma;
|
||||
struct macb_tx_skb *skb;
|
||||
};
|
||||
|
||||
struct macb_context {
|
||||
const struct macb_info *info;
|
||||
|
||||
unsigned int rx_buffer_size;
|
||||
unsigned int rx_ring_size;
|
||||
unsigned int tx_ring_size;
|
||||
struct macb_rxq rxq[MACB_MAX_QUEUES];
|
||||
struct macb_txq txq[MACB_MAX_QUEUES];
|
||||
};
|
||||
|
||||
struct macb {
|
||||
void __iomem *regs;
|
||||
bool native_io;
|
||||
|
|
@ -1306,24 +1335,36 @@ struct macb {
|
|||
u32 (*macb_reg_readl)(struct macb *bp, int offset);
|
||||
void (*macb_reg_writel)(struct macb *bp, int offset, u32 value);
|
||||
|
||||
/*
|
||||
* Give direct access (bp->caps) and
|
||||
* allow taking a pointer to it (&bp->info) for contexts.
|
||||
*/
|
||||
union {
|
||||
struct macb_info;
|
||||
struct macb_info info;
|
||||
};
|
||||
|
||||
/*
|
||||
* Context stores all its parameters.
|
||||
* But we must remember them across closure.
|
||||
*/
|
||||
unsigned int configured_rx_ring_size;
|
||||
unsigned int configured_tx_ring_size;
|
||||
struct macb_context *ctx;
|
||||
|
||||
struct macb_dma_desc *rx_ring_tieoff;
|
||||
dma_addr_t rx_ring_tieoff_dma;
|
||||
size_t rx_buffer_size;
|
||||
|
||||
unsigned int rx_ring_size;
|
||||
unsigned int tx_ring_size;
|
||||
|
||||
unsigned int num_queues;
|
||||
struct macb_queue queues[MACB_MAX_QUEUES];
|
||||
|
||||
spinlock_t lock;
|
||||
struct platform_device *pdev;
|
||||
/* Serializes context swap against phylink MAC callbacks. */
|
||||
struct mutex mac_cfg_lock;
|
||||
struct clk *pclk;
|
||||
struct clk *hclk;
|
||||
struct clk *tx_clk;
|
||||
struct clk *rx_clk;
|
||||
struct clk *tsu_clk;
|
||||
struct net_device *netdev;
|
||||
/* Protects hw_stats and ethtool_stats */
|
||||
spinlock_t stats_lock;
|
||||
union {
|
||||
|
|
@ -1331,15 +1372,12 @@ struct macb {
|
|||
struct gem_stats gem;
|
||||
} hw_stats;
|
||||
|
||||
struct macb_or_gem_ops macbgem_ops;
|
||||
|
||||
struct mii_bus *mii_bus;
|
||||
struct phylink *phylink;
|
||||
struct phylink_config phylink_config;
|
||||
struct phylink_pcs phylink_usx_pcs;
|
||||
struct phylink_pcs phylink_sgmii_pcs;
|
||||
|
||||
u32 caps;
|
||||
unsigned int dma_burst_length;
|
||||
|
||||
phy_interface_t phy_interface;
|
||||
|
|
@ -1383,12 +1421,12 @@ struct macb {
|
|||
u32 tx_lpi_timer;
|
||||
|
||||
/* ISR must not drive NAPI & BH mechanisms. True when the interface
|
||||
* is closed. Protected by bp->lock.
|
||||
* is closed or during context-swap. Protected by bp->lock.
|
||||
*/
|
||||
bool irq_quiesced;
|
||||
|
||||
int rx_bd_rd_prefetch;
|
||||
int tx_bd_rd_prefetch;
|
||||
/* Redundant to netif_carrier_ok(), but set under bp->mac_cfg_lock. */
|
||||
bool link_up;
|
||||
|
||||
u32 rx_intr_mask;
|
||||
|
||||
|
|
@ -1441,14 +1479,15 @@ static inline void gem_ptp_do_txstamp(struct macb *bp, struct sk_buff *skb, stru
|
|||
static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc) { }
|
||||
#endif
|
||||
|
||||
static inline bool macb_is_gem(struct macb *bp)
|
||||
static inline bool macb_is_gem(const struct macb_info *info)
|
||||
{
|
||||
return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);
|
||||
return !!(info->caps & MACB_CAPS_MACB_IS_GEM);
|
||||
}
|
||||
|
||||
static inline bool gem_has_ptp(struct macb *bp)
|
||||
static inline bool gem_has_ptp(const struct macb_info *info)
|
||||
{
|
||||
return IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) && (bp->caps & MACB_CAPS_GEM_HAS_PTP);
|
||||
return IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) &&
|
||||
(info->caps & MACB_CAPS_GEM_HAS_PTP);
|
||||
}
|
||||
|
||||
/* ENST Helper functions */
|
||||
|
|
@ -1464,16 +1503,16 @@ static inline u64 enst_max_hw_interval(u32 speed_mbps)
|
|||
ENST_TIME_GRANULARITY_NS * 1000, (speed_mbps));
|
||||
}
|
||||
|
||||
static inline bool macb_dma64(struct macb *bp)
|
||||
static inline bool macb_dma64(const struct macb_info *info)
|
||||
{
|
||||
return IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) &&
|
||||
bp->caps & MACB_CAPS_DMA_64B;
|
||||
info->caps & MACB_CAPS_DMA_64B;
|
||||
}
|
||||
|
||||
static inline bool macb_dma_ptp(struct macb *bp)
|
||||
static inline bool macb_dma_ptp(const struct macb_info *info)
|
||||
{
|
||||
return IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) &&
|
||||
bp->caps & MACB_CAPS_DMA_PTP;
|
||||
info->caps & MACB_CAPS_DMA_PTP;
|
||||
}
|
||||
|
||||
static inline void macb_queue_isr_clear(struct macb *bp,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -28,10 +28,10 @@
|
|||
static struct macb_dma_desc_ptp *macb_ptp_desc(struct macb *bp,
|
||||
struct macb_dma_desc *desc)
|
||||
{
|
||||
if (!macb_dma_ptp(bp))
|
||||
if (!macb_dma_ptp(&bp->info))
|
||||
return NULL;
|
||||
|
||||
if (macb_dma64(bp))
|
||||
if (macb_dma64(&bp->info))
|
||||
return (struct macb_dma_desc_ptp *)
|
||||
((u8 *)desc + sizeof(struct macb_dma_desc)
|
||||
+ sizeof(struct macb_dma_desc_64));
|
||||
|
|
@ -380,7 +380,7 @@ int gem_get_hwtst(struct net_device *netdev,
|
|||
struct macb *bp = netdev_priv(netdev);
|
||||
|
||||
*tstamp_config = bp->tstamp_config;
|
||||
if (!macb_dma_ptp(bp))
|
||||
if (!macb_dma_ptp(&bp->info))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
|
|
@ -399,7 +399,7 @@ int gem_set_hwtst(struct net_device *netdev,
|
|||
u32 ncr_bits = 0;
|
||||
u32 regval;
|
||||
|
||||
if (!macb_dma_ptp(bp))
|
||||
if (!macb_dma_ptp(&bp->info))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (tstamp_config->tx_type) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user