AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/08/05 19:15 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": [
    "MACB",
    "MACB_PCI"
  ],
  "FocusSymbols": [
    "macb_change_mtu",
    "macb_set_ringparam",
    "macb_context_swap_start",
    "macb_context_swap_end"
  ],
  "Reasoning": "The patch introduces a new `macb_context` structure to the Cadence MACB/GEM ethernet driver, enabling context swapping for dynamic MTU and ring parameter changes without fully stopping the device. It also refactors the driver's queue and ring management to use this context. The driver can be fuzzed via its PCI wrapper (`CONFIG_MACB_PCI`), which allows syzkaller to instantiate it using virtual PCI devices. The focus should be on the newly introduced context swapping logic triggered by MTU and ring parameter changes.",
  "WorthFuzzing": true
}

1/1 2026/08/05 19:15 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit f28c5413d02745f373e50617d569151a91ef9c6f\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Wed Aug 5 19:15:08 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h\nindex 2de56017ee0d6..24559ff2ab6ff 100644\n--- a/drivers/net/ethernet/cadence/macb.h\n+++ b/drivers/net/ethernet/cadence/macb.h\n@@ -840,7 +840,7 @@\n  */\n #define macb_or_gem_writel(__bp, __reg, __value) \\\n \t({ \\\n-\t\tif (macb_is_gem((__bp))) \\\n+\t\tif (macb_is_gem(\u0026(__bp)-\u003einfo)) \\\n \t\t\tgem_writel((__bp), __reg, __value); \\\n \t\telse \\\n \t\t\tmacb_writel((__bp), __reg, __value); \\\n@@ -849,7 +849,7 @@\n #define macb_or_gem_readl(__bp, __reg) \\\n \t({ \\\n \t\tu32 __v; \\\n-\t\tif (macb_is_gem((__bp))) \\\n+\t\tif (macb_is_gem(\u0026(__bp)-\u003einfo)) \\\n \t\t\t__v = gem_readl((__bp), __reg); \\\n \t\telse \\\n \t\t\t__v = macb_readl((__bp), __reg); \\\n@@ -1196,22 +1196,23 @@ static const struct gem_statistic queue_statistics[] = {\n \n struct macb;\n struct macb_queue;\n+struct macb_context;\n \n struct macb_or_gem_ops {\n-\tint\t(*mog_alloc_rx_buffers)(struct macb *bp);\n-\tvoid\t(*mog_free_rx_buffers)(struct macb *bp);\n-\tvoid\t(*mog_init_rings)(struct macb *bp);\n+\tint\t(*mog_alloc_rx_buffers)(struct macb_context *ctx);\n+\tvoid\t(*mog_free_rx_buffers)(struct macb_context *ctx);\n+\tvoid\t(*mog_init_rings)(struct macb_context *ctx);\n \tint\t(*mog_rx)(struct macb_queue *queue, struct napi_struct *napi,\n \t\t\t  int budget);\n };\n \n /* MACB-PTP interface: adapt to platform needs. */\n struct macb_ptp_info {\n-\tvoid (*ptp_init)(struct net_device *ndev);\n-\tvoid (*ptp_remove)(struct net_device *ndev);\n+\tvoid (*ptp_init)(struct net_device *netdev);\n+\tvoid (*ptp_remove)(struct net_device *netdev);\n \ts32 (*get_ptp_max_adj)(void);\n \tunsigned int (*get_tsu_rate)(struct macb *bp);\n-\tint (*get_ts_info)(struct net_device *dev,\n+\tint (*get_ts_info)(struct net_device *netdev,\n \t\t\t   struct kernel_ethtool_ts_info *info);\n \tint (*get_hwtst)(struct net_device *netdev,\n \t\t\t struct kernel_hwtstamp_config *tstamp_config);\n@@ -1270,23 +1271,12 @@ struct macb_queue {\n \tunsigned int\t\tENST_ON_TIME;\n \tunsigned int\t\tENST_OFF_TIME;\n \n-\t/* Lock to protect tx_head and tx_tail */\n+\t/* Lock to protect ctx-\u003etxq[q].head and ctx-\u003etxq[q].tail */\n \tspinlock_t\t\ttx_ptr_lock;\n-\tunsigned int\t\ttx_head, tx_tail;\n-\tstruct macb_dma_desc\t*tx_ring;\n-\tstruct macb_tx_skb\t*tx_skb;\n-\tdma_addr_t\t\ttx_ring_dma;\n \tstruct work_struct\ttx_error_task;\n \tbool\t\t\ttxubr_pending;\n \tstruct napi_struct\tnapi_tx;\n \n-\tdma_addr_t\t\trx_ring_dma;\n-\tdma_addr_t\t\trx_buffers_dma;\n-\tunsigned int\t\trx_tail;\n-\tunsigned int\t\trx_prepared_head;\n-\tstruct macb_dma_desc\t*rx_ring;\n-\tstruct sk_buff\t\t**rx_skbuff;\n-\tvoid\t\t\t*rx_buffers;\n \tstruct napi_struct\tnapi_rx;\n \tstruct queue_stats stats;\n };\n@@ -1301,6 +1291,45 @@ struct ethtool_rx_fs_list {\n \tunsigned int count;\n };\n \n+struct macb_info {\n+\tstruct platform_device\t*pdev;\n+\tstruct net_device\t*netdev;\n+\tstruct macb_or_gem_ops\tmacbgem_ops;\n+\tunsigned int\t\tnum_queues;\n+\tu32\t\t\tcaps;\n+\tint\t\t\trx_bd_rd_prefetch;\n+\tint\t\t\ttx_bd_rd_prefetch;\n+\tstruct queue_stats\t*queue_stats[MACB_MAX_QUEUES];\n+};\n+\n+struct macb_rxq {\n+\tstruct macb_dma_desc\t*ring;\t\t/* MACB \u0026 GEM */\n+\tdma_addr_t\t\tring_dma;\t/* MACB \u0026 GEM */\n+\tunsigned int\t\ttail;\t\t/* MACB \u0026 GEM */\n+\tunsigned int\t\tprepared_head;\t/* GEM */\n+\tstruct sk_buff\t\t**skbuff;\t/* GEM */\n+\tdma_addr_t\t\tbuffers_dma;\t/* MACB */\n+\tvoid\t\t\t*buffers;\t/* MACB */\n+};\n+\n+struct macb_txq {\n+\tunsigned int\t\thead;\n+\tunsigned int\t\ttail;\n+\tstruct macb_dma_desc\t*ring;\n+\tdma_addr_t\t\tring_dma;\n+\tstruct macb_tx_skb\t*skb;\n+};\n+\n+struct macb_context {\n+\tconst struct macb_info\t*info;\n+\n+\tunsigned int\t\trx_buffer_size;\n+\tunsigned int\t\trx_ring_size;\n+\tunsigned int\t\ttx_ring_size;\n+\tstruct macb_rxq\t\trxq[MACB_MAX_QUEUES];\n+\tstruct macb_txq\t\ttxq[MACB_MAX_QUEUES];\n+};\n+\n struct macb {\n \tvoid __iomem\t\t*regs;\n \tbool\t\t\tnative_io;\n@@ -1309,24 +1338,36 @@ struct macb {\n \tu32\t(*macb_reg_readl)(struct macb *bp, int offset);\n \tvoid\t(*macb_reg_writel)(struct macb *bp, int offset, u32 value);\n \n+\t/*\n+\t * Give direct access (bp-\u003ecaps) and\n+\t * allow taking a pointer to it (\u0026bp-\u003einfo) for contexts.\n+\t */\n+\tunion {\n+\t\tstruct macb_info;\n+\t\tstruct macb_info info;\n+\t};\n+\n+\t/*\n+\t * Context stores all its parameters.\n+\t * But we must remember them across closure.\n+\t */\n+\tunsigned int\t\tconfigured_rx_ring_size;\n+\tunsigned int\t\tconfigured_tx_ring_size;\n+\tstruct macb_context\t*ctx;\n+\n \tstruct macb_dma_desc\t*rx_ring_tieoff;\n \tdma_addr_t\t\trx_ring_tieoff_dma;\n-\tsize_t\t\t\trx_buffer_size;\n-\n-\tunsigned int\t\trx_ring_size;\n-\tunsigned int\t\ttx_ring_size;\n \n-\tunsigned int\t\tnum_queues;\n \tstruct macb_queue\tqueues[MACB_MAX_QUEUES];\n \n \tspinlock_t\t\tlock;\n-\tstruct platform_device\t*pdev;\n+\t/* Serializes context swap against phylink MAC callbacks. */\n+\tstruct mutex\t\tmac_cfg_lock;\n \tstruct clk\t\t*pclk;\n \tstruct clk\t\t*hclk;\n \tstruct clk\t\t*tx_clk;\n \tstruct clk\t\t*rx_clk;\n \tstruct clk\t\t*tsu_clk;\n-\tstruct net_device\t*dev;\n \t/* Protects hw_stats and ethtool_stats */\n \tspinlock_t\t\tstats_lock;\n \tunion {\n@@ -1334,15 +1375,12 @@ struct macb {\n \t\tstruct gem_stats\tgem;\n \t}\t\t\thw_stats;\n \n-\tstruct macb_or_gem_ops\tmacbgem_ops;\n-\n \tstruct mii_bus\t\t*mii_bus;\n \tstruct phylink\t\t*phylink;\n \tstruct phylink_config\tphylink_config;\n \tstruct phylink_pcs\tphylink_usx_pcs;\n \tstruct phylink_pcs\tphylink_sgmii_pcs;\n \n-\tu32\t\t\tcaps;\n \tunsigned int\t\tdma_burst_length;\n \n \tphy_interface_t\t\tphy_interface;\n@@ -1385,8 +1423,11 @@ struct macb {\n \tstruct delayed_work\ttx_lpi_work;\n \tu32\t\t\ttx_lpi_timer;\n \n-\tint\trx_bd_rd_prefetch;\n-\tint\ttx_bd_rd_prefetch;\n+\t/* ISR must not drive NAPI \u0026 BH mechanisms. Protected by bp-\u003elock. */\n+\tbool\t\t\tctx_swap;\n+\n+\t/* Redundant to netif_carrier_ok(), but set under bp-\u003emac_cfg_lock. */\n+\tbool\t\t\tlink_up;\n \n \tu32\trx_intr_mask;\n \n@@ -1406,8 +1447,8 @@ enum macb_bd_control {\n \tTSTAMP_ALL_FRAMES,\n };\n \n-void gem_ptp_init(struct net_device *ndev);\n-void gem_ptp_remove(struct net_device *ndev);\n+void gem_ptp_init(struct net_device *netdev);\n+void gem_ptp_remove(struct net_device *netdev);\n void gem_ptp_txstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc);\n void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc);\n static inline void gem_ptp_do_txstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc)\n@@ -1426,27 +1467,28 @@ static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff *skb, stru\n \tgem_ptp_rxstamp(bp, skb, desc);\n }\n \n-int gem_get_hwtst(struct net_device *dev,\n+int gem_get_hwtst(struct net_device *netdev,\n \t\t  struct kernel_hwtstamp_config *tstamp_config);\n-int gem_set_hwtst(struct net_device *dev,\n+int gem_set_hwtst(struct net_device *netdev,\n \t\t  struct kernel_hwtstamp_config *tstamp_config,\n \t\t  struct netlink_ext_ack *extack);\n #else\n-static inline void gem_ptp_init(struct net_device *ndev) { }\n-static inline void gem_ptp_remove(struct net_device *ndev) { }\n+static inline void gem_ptp_init(struct net_device *netdev) { }\n+static inline void gem_ptp_remove(struct net_device *netdev) { }\n \n static inline void gem_ptp_do_txstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc) { }\n static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc) { }\n #endif\n \n-static inline bool macb_is_gem(struct macb *bp)\n+static inline bool macb_is_gem(const struct macb_info *info)\n {\n-\treturn !!(bp-\u003ecaps \u0026 MACB_CAPS_MACB_IS_GEM);\n+\treturn !!(info-\u003ecaps \u0026 MACB_CAPS_MACB_IS_GEM);\n }\n \n-static inline bool gem_has_ptp(struct macb *bp)\n+static inline bool gem_has_ptp(const struct macb_info *info)\n {\n-\treturn IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) \u0026\u0026 (bp-\u003ecaps \u0026 MACB_CAPS_GEM_HAS_PTP);\n+\treturn IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) \u0026\u0026\n+\t       (info-\u003ecaps \u0026 MACB_CAPS_GEM_HAS_PTP);\n }\n \n /* ENST Helper functions */\n@@ -1462,16 +1504,16 @@ static inline u64 enst_max_hw_interval(u32 speed_mbps)\n \t\t\t    ENST_TIME_GRANULARITY_NS * 1000, (speed_mbps));\n }\n \n-static inline bool macb_dma64(struct macb *bp)\n+static inline bool macb_dma64(const struct macb_info *info)\n {\n \treturn IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) \u0026\u0026\n-\t       bp-\u003ecaps \u0026 MACB_CAPS_DMA_64B;\n+\t       info-\u003ecaps \u0026 MACB_CAPS_DMA_64B;\n }\n \n-static inline bool macb_dma_ptp(struct macb *bp)\n+static inline bool macb_dma_ptp(const struct macb_info *info)\n {\n \treturn IS_ENABLED(CONFIG_MACB_USE_HWSTAMP) \u0026\u0026\n-\t       bp-\u003ecaps \u0026 MACB_CAPS_DMA_PTP;\n+\t       info-\u003ecaps \u0026 MACB_CAPS_DMA_PTP;\n }\n \n static inline void macb_queue_isr_clear(struct macb *bp,\ndiff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c\nindex d394f1f43b685..b3d84a65078f8 100644\n--- a/drivers/net/ethernet/cadence/macb_main.c\n+++ b/drivers/net/ethernet/cadence/macb_main.c\n@@ -61,7 +61,7 @@ struct sifive_fu540_macb_mgmt {\n #define MAX_TX_RING_SIZE\t4096\n \n /* level of occupied TX descriptors under which we wake up TX process */\n-#define MACB_TX_WAKEUP_THRESH(bp)\t(3 * (bp)-\u003etx_ring_size / 4)\n+#define MACB_TX_WAKEUP_THRESH(bp)\t(3 * (bp)-\u003ectx-\u003etx_ring_size / 4)\n \n #define MACB_RX_INT_FLAGS\t(MACB_BIT(RCOMP) | MACB_BIT(ISR_ROVR))\n #define MACB_TX_ERR_FLAGS\t(MACB_BIT(ISR_TUND)\t\t\t\\\n@@ -126,75 +126,104 @@ struct sifive_fu540_macb_mgmt {\n  *    word 5: timestamp word 1\n  *    word 6: timestamp word 2\n  */\n-static unsigned int macb_dma_desc_get_size(struct macb *bp)\n+static unsigned int macb_dma_desc_get_size(const struct macb_info *info)\n {\n \tunsigned int desc_size = sizeof(struct macb_dma_desc);\n \n-\tif (macb_dma64(bp))\n+\tif (macb_dma64(info))\n \t\tdesc_size += sizeof(struct macb_dma_desc_64);\n-\tif (macb_dma_ptp(bp))\n+\tif (macb_dma_ptp(info))\n \t\tdesc_size += sizeof(struct macb_dma_desc_ptp);\n \n \treturn desc_size;\n }\n \n-static unsigned int macb_adj_dma_desc_idx(struct macb *bp, unsigned int desc_idx)\n+static unsigned int macb_adj_dma_desc_idx(struct macb_context *ctx,\n+\t\t\t\t\t  unsigned int desc_idx)\n {\n-\treturn desc_idx * (1 + macb_dma64(bp) + macb_dma_ptp(bp));\n+\treturn desc_idx * (1 + macb_dma64(ctx-\u003einfo) +\n+\t\t\t       macb_dma_ptp(ctx-\u003einfo));\n }\n \n-static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct macb_dma_desc *desc)\n+static struct macb_dma_desc_64 *macb_64b_desc(struct macb_dma_desc *desc)\n {\n \treturn (struct macb_dma_desc_64 *)((void *)desc\n \t\t+ sizeof(struct macb_dma_desc));\n }\n \n /* Ring buffer accessors */\n-static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)\n+static unsigned int macb_tx_ring_wrap(struct macb_context *ctx,\n+\t\t\t\t      unsigned int index)\n {\n-\treturn index \u0026 (bp-\u003etx_ring_size - 1);\n+\treturn index \u0026 (ctx-\u003etx_ring_size - 1);\n }\n \n-static struct macb_dma_desc *macb_tx_desc(struct macb_queue *queue,\n+static struct macb_txq *macb_txq(struct macb_queue *queue)\n+{\n+\tstruct macb *bp = queue-\u003ebp;\n+\tunsigned int q = queue - bp-\u003equeues;\n+\n+\treturn \u0026bp-\u003ectx-\u003etxq[q];\n+}\n+\n+static struct macb_rxq *macb_rxq(struct macb_queue *queue)\n+{\n+\tstruct macb *bp = queue-\u003ebp;\n+\tunsigned int q = queue - bp-\u003equeues;\n+\n+\treturn \u0026bp-\u003ectx-\u003erxq[q];\n+}\n+\n+static struct macb_dma_desc *macb_tx_desc(struct macb_context *ctx,\n+\t\t\t\t\t  unsigned int q,\n \t\t\t\t\t  unsigned int index)\n {\n-\tindex = macb_tx_ring_wrap(queue-\u003ebp, index);\n-\tindex = macb_adj_dma_desc_idx(queue-\u003ebp, index);\n-\treturn \u0026queue-\u003etx_ring[index];\n+\tindex = macb_tx_ring_wrap(ctx, index);\n+\tindex = macb_adj_dma_desc_idx(ctx, index);\n+\treturn \u0026ctx-\u003etxq[q].ring[index];\n }\n \n static struct macb_tx_skb *macb_tx_skb(struct macb_queue *queue,\n \t\t\t\t       unsigned int index)\n {\n-\treturn \u0026queue-\u003etx_skb[macb_tx_ring_wrap(queue-\u003ebp, index)];\n+\tstruct macb_txq *txq = macb_txq(queue);\n+\n+\treturn \u0026txq-\u003eskb[macb_tx_ring_wrap(queue-\u003ebp-\u003ectx, index)];\n }\n \n static dma_addr_t macb_tx_dma(struct macb_queue *queue, unsigned int index)\n {\n+\tstruct macb_context *ctx = queue-\u003ebp-\u003ectx;\n+\tstruct macb_txq *txq = macb_txq(queue);\n \tdma_addr_t offset;\n \n-\toffset = macb_tx_ring_wrap(queue-\u003ebp, index) *\n-\t\t\tmacb_dma_desc_get_size(queue-\u003ebp);\n+\toffset = macb_tx_ring_wrap(ctx, index) *\n+\t\t\tmacb_dma_desc_get_size(\u0026queue-\u003ebp-\u003einfo);\n \n-\treturn queue-\u003etx_ring_dma + offset;\n+\treturn txq-\u003ering_dma + offset;\n }\n \n-static unsigned int macb_rx_ring_wrap(struct macb *bp, unsigned int index)\n+static unsigned int macb_rx_ring_wrap(struct macb_context *ctx,\n+\t\t\t\t      unsigned int index)\n {\n-\treturn index \u0026 (bp-\u003erx_ring_size - 1);\n+\treturn index \u0026 (ctx-\u003erx_ring_size - 1);\n }\n \n-static struct macb_dma_desc *macb_rx_desc(struct macb_queue *queue, unsigned int index)\n+static struct macb_dma_desc *macb_rx_desc(struct macb_context *ctx,\n+\t\t\t\t\t  unsigned int q, unsigned int index)\n {\n-\tindex = macb_rx_ring_wrap(queue-\u003ebp, index);\n-\tindex = macb_adj_dma_desc_idx(queue-\u003ebp, index);\n-\treturn \u0026queue-\u003erx_ring[index];\n+\tindex = macb_rx_ring_wrap(ctx, index);\n+\tindex = macb_adj_dma_desc_idx(ctx, index);\n+\treturn \u0026ctx-\u003erxq[q].ring[index];\n }\n \n static void *macb_rx_buffer(struct macb_queue *queue, unsigned int index)\n {\n-\treturn queue-\u003erx_buffers + queue-\u003ebp-\u003erx_buffer_size *\n-\t       macb_rx_ring_wrap(queue-\u003ebp, index);\n+\tstruct macb_context *ctx = queue-\u003ebp-\u003ectx;\n+\tstruct macb_rxq *rxq = macb_rxq(queue);\n+\n+\treturn rxq-\u003ebuffers + ctx-\u003erx_buffer_size *\n+\t       macb_rx_ring_wrap(ctx, index);\n }\n \n /* I/O accessors */\n@@ -252,12 +281,12 @@ static void macb_set_hwaddr(struct macb *bp)\n \tu32 bottom;\n \tu16 top;\n \n-\tbottom = get_unaligned_le32(bp-\u003edev-\u003edev_addr);\n+\tbottom = get_unaligned_le32(bp-\u003enetdev-\u003edev_addr);\n \tmacb_or_gem_writel(bp, SA1B, bottom);\n-\ttop = get_unaligned_le16(bp-\u003edev-\u003edev_addr + 4);\n+\ttop = get_unaligned_le16(bp-\u003enetdev-\u003edev_addr + 4);\n \tmacb_or_gem_writel(bp, SA1T, top);\n \n-\tif (gem_has_ptp(bp)) {\n+\tif (gem_has_ptp(\u0026bp-\u003einfo)) {\n \t\tgem_writel(bp, RXPTPUNI, bottom);\n \t\tgem_writel(bp, TXPTPUNI, bottom);\n \t}\n@@ -291,13 +320,13 @@ static void macb_get_hwaddr(struct macb *bp)\n \t\taddr[5] = (top \u003e\u003e 8) \u0026 0xff;\n \n \t\tif (is_valid_ether_addr(addr)) {\n-\t\t\teth_hw_addr_set(bp-\u003edev, addr);\n+\t\t\teth_hw_addr_set(bp-\u003enetdev, addr);\n \t\t\treturn;\n \t\t}\n \t}\n \n \tdev_info(\u0026bp-\u003epdev-\u003edev, \"invalid hw address, using random\\n\");\n-\teth_hw_addr_random(bp-\u003edev);\n+\teth_hw_addr_random(bp-\u003enetdev);\n }\n \n static int macb_mdio_wait_for_idle(struct macb *bp)\n@@ -463,19 +492,23 @@ static int macb_mdio_write_c45(struct mii_bus *bus, int mii_id,\n static void macb_init_buffers(struct macb *bp)\n {\n \tstruct macb_queue *queue;\n+\tstruct macb_rxq *rxq;\n+\tstruct macb_txq *txq;\n \tunsigned int q;\n \n \t/* Single register for all queues' high 32 bits. */\n-\tif (macb_dma64(bp)) {\n-\t\tmacb_writel(bp, RBQPH,\n-\t\t\t    upper_32_bits(bp-\u003equeues[0].rx_ring_dma));\n-\t\tmacb_writel(bp, TBQPH,\n-\t\t\t    upper_32_bits(bp-\u003equeues[0].tx_ring_dma));\n+\tif (macb_dma64(\u0026bp-\u003einfo)) {\n+\t\trxq = \u0026bp-\u003ectx-\u003erxq[0];\n+\t\ttxq = \u0026bp-\u003ectx-\u003etxq[0];\n+\t\tmacb_writel(bp, RBQPH, upper_32_bits(rxq-\u003ering_dma));\n+\t\tmacb_writel(bp, TBQPH, upper_32_bits(txq-\u003ering_dma));\n \t}\n \n \tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n-\t\tqueue_writel(queue, RBQP, lower_32_bits(queue-\u003erx_ring_dma));\n-\t\tqueue_writel(queue, TBQP, lower_32_bits(queue-\u003etx_ring_dma));\n+\t\trxq = \u0026bp-\u003ectx-\u003erxq[q];\n+\t\ttxq = \u0026bp-\u003ectx-\u003etxq[q];\n+\t\tqueue_writel(queue, RBQP, lower_32_bits(rxq-\u003ering_dma));\n+\t\tqueue_writel(queue, TBQP, lower_32_bits(txq-\u003ering_dma));\n \t}\n }\n \n@@ -509,12 +542,12 @@ static void macb_set_tx_clk(struct macb *bp, int speed)\n \tferr = abs(rate_rounded - rate);\n \tferr = DIV_ROUND_UP(ferr, rate / 100000);\n \tif (ferr \u003e 5)\n-\t\tnetdev_warn(bp-\u003edev,\n+\t\tnetdev_warn(bp-\u003enetdev,\n \t\t\t    \"unable to generate target frequency: %ld Hz\\n\",\n \t\t\t    rate);\n \n \tif (clk_set_rate(bp-\u003etx_clk, rate_rounded))\n-\t\tnetdev_err(bp-\u003edev, \"adjusting tx_clk failed.\\n\");\n+\t\tnetdev_err(bp-\u003enetdev, \"adjusting tx_clk failed.\\n\");\n }\n \n static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,\n@@ -648,11 +681,12 @@ static bool macb_tx_lpi_set(struct macb *bp, bool enable)\n \n static bool macb_tx_all_queues_idle(struct macb *bp)\n {\n-\tstruct macb_queue *queue;\n+\tstruct macb_txq *txq;\n \tunsigned int q;\n \n-\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n-\t\tif (READ_ONCE(queue-\u003etx_head) != READ_ONCE(queue-\u003etx_tail))\n+\tfor (q = 0; q \u003c bp-\u003enum_queues; ++q) {\n+\t\ttxq = \u0026bp-\u003ectx-\u003etxq[q];\n+\t\tif (READ_ONCE(txq-\u003ehead) != READ_ONCE(txq-\u003etail))\n \t\t\treturn false;\n \t}\n \treturn true;\n@@ -697,34 +731,49 @@ static void macb_tx_lpi_wake(struct macb *bp)\n \n static void macb_mac_disable_tx_lpi(struct phylink_config *config)\n {\n-\tstruct net_device *ndev = to_net_dev(config-\u003edev);\n-\tstruct macb *bp = netdev_priv(ndev);\n+\tstruct net_device *netdev = to_net_dev(config-\u003edev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tunsigned long flags;\n \n+\tmutex_lock(\u0026bp-\u003emac_cfg_lock);\n+\n \tcancel_delayed_work_sync(\u0026bp-\u003etx_lpi_work);\n \n \tspin_lock_irqsave(\u0026bp-\u003elock, flags);\n \tbp-\u003eeee_active = false;\n \tmacb_tx_lpi_set(bp, false);\n \tspin_unlock_irqrestore(\u0026bp-\u003elock, flags);\n+\n+\tmutex_unlock(\u0026bp-\u003emac_cfg_lock);\n+}\n+\n+static void macb_txp_lpi_initial_defer(struct macb *bp)\n+{\n+\tlockdep_assert_held(\u0026bp-\u003emac_cfg_lock);\n+\n+\t/* Defer initial LPI entry by 1 second after link-up per\n+\t * IEEE 802.3az section 22.7a.\n+\t */\n+\tmod_delayed_work(system_wq, \u0026bp-\u003etx_lpi_work, msecs_to_jiffies(1000));\n }\n \n static int macb_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,\n \t\t\t\t  bool tx_clk_stop)\n {\n-\tstruct net_device *ndev = to_net_dev(config-\u003edev);\n-\tstruct macb *bp = netdev_priv(ndev);\n+\tstruct net_device *netdev = to_net_dev(config-\u003edev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tunsigned long flags;\n \n+\tmutex_lock(\u0026bp-\u003emac_cfg_lock);\n+\n \tspin_lock_irqsave(\u0026bp-\u003elock, flags);\n \tbp-\u003etx_lpi_timer = timer;\n \tbp-\u003eeee_active = true;\n \tspin_unlock_irqrestore(\u0026bp-\u003elock, flags);\n \n-\t/* Defer initial LPI entry by 1 second after link-up per\n-\t * IEEE 802.3az section 22.7a.\n-\t */\n-\tmod_delayed_work(system_wq, \u0026bp-\u003etx_lpi_work, msecs_to_jiffies(1000));\n+\tmacb_txp_lpi_initial_defer(bp);\n+\n+\tmutex_unlock(\u0026bp-\u003emac_cfg_lock);\n \n \treturn 0;\n }\n@@ -732,12 +781,13 @@ static int macb_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,\n static void macb_mac_config(struct phylink_config *config, unsigned int mode,\n \t\t\t    const struct phylink_link_state *state)\n {\n-\tstruct net_device *ndev = to_net_dev(config-\u003edev);\n-\tstruct macb *bp = netdev_priv(ndev);\n+\tstruct net_device *netdev = to_net_dev(config-\u003edev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tunsigned long flags;\n \tu32 old_ctrl, ctrl;\n \tu32 old_ncr, ncr;\n \n+\tmutex_lock(\u0026bp-\u003emac_cfg_lock);\n \tspin_lock_irqsave(\u0026bp-\u003elock, flags);\n \n \told_ctrl = ctrl = macb_or_gem_readl(bp, NCFGR);\n@@ -746,7 +796,7 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,\n \tif (bp-\u003ecaps \u0026 MACB_CAPS_MACB_IS_EMAC) {\n \t\tif (state-\u003einterface == PHY_INTERFACE_MODE_RMII)\n \t\t\tctrl |= MACB_BIT(RM9200_RMII);\n-\t} else if (macb_is_gem(bp)) {\n+\t} else if (macb_is_gem(\u0026bp-\u003einfo)) {\n \t\tctrl \u0026= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));\n \t\tncr \u0026= ~GEM_BIT(ENABLE_HS_MAC);\n \n@@ -769,17 +819,22 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,\n \t\tmacb_or_gem_writel(bp, NCR, ncr);\n \n \tspin_unlock_irqrestore(\u0026bp-\u003elock, flags);\n+\tmutex_unlock(\u0026bp-\u003emac_cfg_lock);\n }\n \n static void macb_mac_link_down(struct phylink_config *config, unsigned int mode,\n \t\t\t       phy_interface_t interface)\n {\n-\tstruct net_device *ndev = to_net_dev(config-\u003edev);\n-\tstruct macb *bp = netdev_priv(ndev);\n+\tstruct net_device *netdev = to_net_dev(config-\u003edev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_queue *queue;\n \tunsigned int q;\n \tu32 ctrl;\n \n+\tmutex_lock(\u0026bp-\u003emac_cfg_lock);\n+\n+\tbp-\u003elink_up = false;\n+\n \tif (!(bp-\u003ecaps \u0026 MACB_CAPS_MACB_IS_EMAC))\n \t\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue)\n \t\t\tqueue_writel(queue, IDR,\n@@ -789,7 +844,9 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode,\n \tctrl = macb_readl(bp, NCR) \u0026 ~(MACB_BIT(RE) | MACB_BIT(TE));\n \tmacb_writel(bp, NCR, ctrl);\n \n-\tnetif_tx_stop_all_queues(ndev);\n+\tnetif_tx_stop_all_queues(netdev);\n+\n+\tmutex_unlock(\u0026bp-\u003emac_cfg_lock);\n }\n \n /* Use juggling algorithm to left rotate tx ring and tx skb array */\n@@ -798,28 +855,30 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)\n \tunsigned int head, tail, count, ring_size, desc_size;\n \tstruct macb_tx_skb tx_skb, *skb_curr, *skb_next;\n \tstruct macb_dma_desc *desc_curr, *desc_next;\n+\tunsigned int q = queue - queue-\u003ebp-\u003equeues;\n \tunsigned int i, cycles, shift, curr, next;\n-\tstruct macb *bp = queue-\u003ebp;\n+\tstruct macb_context *ctx = queue-\u003ebp-\u003ectx;\n+\tstruct macb_txq *txq = macb_txq(queue);\n \tunsigned char desc[24];\n \tunsigned long flags;\n \n-\tdesc_size = macb_dma_desc_get_size(bp);\n+\tdesc_size = macb_dma_desc_get_size(\u0026queue-\u003ebp-\u003einfo);\n \n \tif (WARN_ON_ONCE(desc_size \u003e ARRAY_SIZE(desc)))\n \t\treturn;\n \n \tspin_lock_irqsave(\u0026queue-\u003etx_ptr_lock, flags);\n-\thead = queue-\u003etx_head;\n-\ttail = queue-\u003etx_tail;\n-\tring_size = bp-\u003etx_ring_size;\n+\thead = txq-\u003ehead;\n+\ttail = txq-\u003etail;\n+\tring_size = ctx-\u003etx_ring_size;\n \tcount = CIRC_CNT(head, tail, ring_size);\n \n \tif (!(tail % ring_size))\n \t\tgoto unlock;\n \n \tif (!count) {\n-\t\tqueue-\u003etx_head = 0;\n-\t\tqueue-\u003etx_tail = 0;\n+\t\ttxq-\u003ehead = 0;\n+\t\ttxq-\u003etail = 0;\n \t\tgoto unlock;\n \t}\n \n@@ -827,7 +886,7 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)\n \tcycles = gcd(ring_size, shift);\n \n \tfor (i = 0; i \u003c cycles; i++) {\n-\t\tmemcpy(\u0026desc, macb_tx_desc(queue, i), desc_size);\n+\t\tmemcpy(\u0026desc, macb_tx_desc(ctx, q, i), desc_size);\n \t\tmemcpy(\u0026tx_skb, macb_tx_skb(queue, i),\n \t\t       sizeof(struct macb_tx_skb));\n \n@@ -835,8 +894,8 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)\n \t\tnext = (curr + shift) % ring_size;\n \n \t\twhile (next != i) {\n-\t\t\tdesc_curr = macb_tx_desc(queue, curr);\n-\t\t\tdesc_next = macb_tx_desc(queue, next);\n+\t\t\tdesc_curr = macb_tx_desc(ctx, q, curr);\n+\t\t\tdesc_next = macb_tx_desc(ctx, q, next);\n \n \t\t\tmemcpy(desc_curr, desc_next, desc_size);\n \n@@ -853,7 +912,7 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)\n \t\t\tnext = (curr + shift) % ring_size;\n \t\t}\n \n-\t\tdesc_curr = macb_tx_desc(queue, curr);\n+\t\tdesc_curr = macb_tx_desc(ctx, q, curr);\n \t\tmemcpy(desc_curr, \u0026desc, desc_size);\n \t\tif (i == ring_size - 1)\n \t\t\tdesc_curr-\u003ectrl \u0026= ~MACB_BIT(TX_WRAP);\n@@ -863,8 +922,8 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)\n \t\t       sizeof(struct macb_tx_skb));\n \t}\n \n-\tqueue-\u003etx_head = count;\n-\tqueue-\u003etx_tail = 0;\n+\ttxq-\u003ehead = count;\n+\ttxq-\u003etail = 0;\n \n \t/* Make descriptor updates visible to hardware */\n \twmb();\n@@ -877,27 +936,30 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)\n static void gem_shuffle_tx_rings(struct macb *bp)\n {\n \tstruct macb_queue *queue;\n-\tint q;\n+\tunsigned int q;\n \n \tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; q++, queue++)\n \t\tgem_shuffle_tx_one_ring(queue);\n }\n \n static void macb_mac_link_up(struct phylink_config *config,\n-\t\t\t     struct phy_device *phy,\n+\t\t\t     struct phy_device *phydev,\n \t\t\t     unsigned int mode, phy_interface_t interface,\n \t\t\t     int speed, int duplex,\n \t\t\t     bool tx_pause, bool rx_pause)\n {\n-\tstruct net_device *ndev = to_net_dev(config-\u003edev);\n-\tstruct macb *bp = netdev_priv(ndev);\n+\tstruct net_device *netdev = to_net_dev(config-\u003edev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_queue *queue;\n \tunsigned long flags;\n \tunsigned int q;\n \tu32 ctrl;\n \n+\tmutex_lock(\u0026bp-\u003emac_cfg_lock);\n \tspin_lock_irqsave(\u0026bp-\u003elock, flags);\n \n+\tbp-\u003elink_up = true;\n+\n \tctrl = macb_or_gem_readl(bp, NCFGR);\n \n \tctrl \u0026= ~(MACB_BIT(SPD) | MACB_BIT(FD));\n@@ -910,7 +972,7 @@ static void macb_mac_link_up(struct phylink_config *config,\n \n \tif (!(bp-\u003ecaps \u0026 MACB_CAPS_MACB_IS_EMAC)) {\n \t\tctrl \u0026= ~MACB_BIT(PAE);\n-\t\tif (macb_is_gem(bp)) {\n+\t\tif (macb_is_gem(\u0026bp-\u003einfo)) {\n \t\t\tctrl \u0026= ~GEM_BIT(GBE);\n \n \t\t\tif (speed == SPEED_1000)\n@@ -941,19 +1003,21 @@ static void macb_mac_link_up(struct phylink_config *config,\n \n \t/* Enable Rx and Tx; Enable PTP unicast */\n \tctrl = macb_readl(bp, NCR);\n-\tif (gem_has_ptp(bp))\n+\tif (gem_has_ptp(\u0026bp-\u003einfo))\n \t\tctrl |= MACB_BIT(PTPUNI);\n \n \tmacb_writel(bp, NCR, ctrl | MACB_BIT(RE) | MACB_BIT(TE));\n \n-\tnetif_tx_wake_all_queues(ndev);\n+\tnetif_tx_wake_all_queues(netdev);\n+\n+\tmutex_unlock(\u0026bp-\u003emac_cfg_lock);\n }\n \n static struct phylink_pcs *macb_mac_select_pcs(struct phylink_config *config,\n \t\t\t\t\t       phy_interface_t interface)\n {\n-\tstruct net_device *ndev = to_net_dev(config-\u003edev);\n-\tstruct macb *bp = netdev_priv(ndev);\n+\tstruct net_device *netdev = to_net_dev(config-\u003edev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \tif (interface == PHY_INTERFACE_MODE_10GBASER)\n \t\treturn \u0026bp-\u003ephylink_usx_pcs;\n@@ -982,7 +1046,7 @@ static bool macb_phy_handle_exists(struct device_node *dn)\n static int macb_phylink_connect(struct macb *bp)\n {\n \tstruct device_node *dn = bp-\u003epdev-\u003edev.of_node;\n-\tstruct net_device *dev = bp-\u003edev;\n+\tstruct net_device *netdev = bp-\u003enetdev;\n \tstruct phy_device *phydev;\n \tint ret;\n \n@@ -992,7 +1056,7 @@ static int macb_phylink_connect(struct macb *bp)\n \tif (!dn || (ret \u0026\u0026 !macb_phy_handle_exists(dn))) {\n \t\tphydev = phy_find_first(bp-\u003emii_bus);\n \t\tif (!phydev) {\n-\t\t\tnetdev_err(dev, \"no PHY found\\n\");\n+\t\t\tnetdev_err(netdev, \"no PHY found\\n\");\n \t\t\treturn -ENXIO;\n \t\t}\n \n@@ -1001,7 +1065,7 @@ static int macb_phylink_connect(struct macb *bp)\n \t}\n \n \tif (ret) {\n-\t\tnetdev_err(dev, \"Could not attach PHY (%d)\\n\", ret);\n+\t\tnetdev_err(netdev, \"Could not attach PHY (%d)\\n\", ret);\n \t\treturn ret;\n \t}\n \n@@ -1013,21 +1077,21 @@ static int macb_phylink_connect(struct macb *bp)\n static void macb_get_pcs_fixed_state(struct phylink_config *config,\n \t\t\t\t     struct phylink_link_state *state)\n {\n-\tstruct net_device *ndev = to_net_dev(config-\u003edev);\n-\tstruct macb *bp = netdev_priv(ndev);\n+\tstruct net_device *netdev = to_net_dev(config-\u003edev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \tstate-\u003elink = (macb_readl(bp, NSR) \u0026 MACB_BIT(NSR_LINK)) != 0;\n }\n \n /* based on au1000_eth. c*/\n-static int macb_mii_probe(struct net_device *dev)\n+static int macb_mii_probe(struct net_device *netdev)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \tbp-\u003ephylink_sgmii_pcs.ops = \u0026macb_phylink_pcs_ops;\n \tbp-\u003ephylink_usx_pcs.ops = \u0026macb_phylink_usx_pcs_ops;\n \n-\tbp-\u003ephylink_config.dev = \u0026dev-\u003edev;\n+\tbp-\u003ephylink_config.dev = \u0026netdev-\u003edev;\n \tbp-\u003ephylink_config.type = PHYLINK_NETDEV;\n \tbp-\u003ephylink_config.mac_managed_pm = true;\n \n@@ -1051,7 +1115,8 @@ static int macb_mii_probe(struct net_device *dev)\n \t\t  bp-\u003ephylink_config.supported_interfaces);\n \n \t/* Determine what modes are supported */\n-\tif (macb_is_gem(bp) \u0026\u0026 (bp-\u003ecaps \u0026 MACB_CAPS_GIGABIT_MODE_AVAILABLE)) {\n+\tif (macb_is_gem(\u0026bp-\u003einfo) \u0026\u0026\n+\t    (bp-\u003ecaps \u0026 MACB_CAPS_GIGABIT_MODE_AVAILABLE)) {\n \t\tbp-\u003ephylink_config.mac_capabilities |= MAC_1000FD;\n \t\tif (!(bp-\u003ecaps \u0026 MACB_CAPS_NO_GIGABIT_HALF))\n \t\t\tbp-\u003ephylink_config.mac_capabilities |= MAC_1000HD;\n@@ -1086,7 +1151,7 @@ static int macb_mii_probe(struct net_device *dev)\n \tbp-\u003ephylink = phylink_create(\u0026bp-\u003ephylink_config, bp-\u003epdev-\u003edev.fwnode,\n \t\t\t\t     bp-\u003ephy_interface, \u0026macb_phylink_ops);\n \tif (IS_ERR(bp-\u003ephylink)) {\n-\t\tnetdev_err(dev, \"Could not create a phylink instance (%ld)\\n\",\n+\t\tnetdev_err(netdev, \"Could not create a phylink instance (%ld)\\n\",\n \t\t\t   PTR_ERR(bp-\u003ephylink));\n \t\treturn PTR_ERR(bp-\u003ephylink);\n \t}\n@@ -1133,7 +1198,7 @@ static int macb_mii_init(struct macb *bp)\n \t */\n \tmdio_np = of_get_child_by_name(np, \"mdio\");\n \tif (!mdio_np \u0026\u0026 of_phy_is_fixed_link(np))\n-\t\treturn macb_mii_probe(bp-\u003edev);\n+\t\treturn macb_mii_probe(bp-\u003enetdev);\n \n \t/* Enable management port */\n \tmacb_writel(bp, NCR, MACB_BIT(MPE));\n@@ -1154,13 +1219,13 @@ static int macb_mii_init(struct macb *bp)\n \tbp-\u003emii_bus-\u003epriv = bp;\n \tbp-\u003emii_bus-\u003eparent = \u0026bp-\u003epdev-\u003edev;\n \n-\tdev_set_drvdata(\u0026bp-\u003edev-\u003edev, bp-\u003emii_bus);\n+\tdev_set_drvdata(\u0026bp-\u003enetdev-\u003edev, bp-\u003emii_bus);\n \n \terr = macb_mdiobus_register(bp, mdio_np);\n \tif (err)\n \t\tgoto err_out_free_mdiobus;\n \n-\terr = macb_mii_probe(bp-\u003edev);\n+\terr = macb_mii_probe(bp-\u003enetdev);\n \tif (err)\n \t\tgoto err_out_unregister_bus;\n \n@@ -1201,14 +1266,15 @@ static int macb_halt_tx(struct macb *bp)\n \t\t\t\t\tbp, TSR);\n }\n \n-static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb, int budget)\n+static void macb_tx_unmap(const struct macb_info *info,\n+\t\t\t  struct macb_tx_skb *tx_skb, int budget)\n {\n \tif (tx_skb-\u003emapping) {\n \t\tif (tx_skb-\u003emapped_as_page)\n-\t\t\tdma_unmap_page(\u0026bp-\u003epdev-\u003edev, tx_skb-\u003emapping,\n+\t\t\tdma_unmap_page(\u0026info-\u003epdev-\u003edev, tx_skb-\u003emapping,\n \t\t\t\t       tx_skb-\u003esize, DMA_TO_DEVICE);\n \t\telse\n-\t\t\tdma_unmap_single(\u0026bp-\u003epdev-\u003edev, tx_skb-\u003emapping,\n+\t\t\tdma_unmap_single(\u0026info-\u003epdev-\u003edev, tx_skb-\u003emapping,\n \t\t\t\t\t tx_skb-\u003esize, DMA_TO_DEVICE);\n \t\ttx_skb-\u003emapping = 0;\n \t}\n@@ -1219,12 +1285,13 @@ static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb, int budge\n \t}\n }\n \n-static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_t addr)\n+static void macb_set_addr(const struct macb_info *info,\n+\t\t\t  struct macb_dma_desc *desc, dma_addr_t addr)\n {\n-\tif (macb_dma64(bp)) {\n+\tif (macb_dma64(info)) {\n \t\tstruct macb_dma_desc_64 *desc_64;\n \n-\t\tdesc_64 = macb_64b_desc(bp, desc);\n+\t\tdesc_64 = macb_64b_desc(desc);\n \t\tdesc_64-\u003eaddrh = upper_32_bits(addr);\n \t\t/* The low bits of RX address contain the RX_USED bit, clearing\n \t\t * of which allows packet RX. Make sure the high bits are also\n@@ -1236,40 +1303,43 @@ static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_\n \tdesc-\u003eaddr = lower_32_bits(addr);\n }\n \n-static dma_addr_t macb_get_addr(struct macb *bp, struct macb_dma_desc *desc)\n+static dma_addr_t macb_get_addr(struct macb_context *ctx,\n+\t\t\t\tstruct macb_dma_desc *desc)\n {\n \tdma_addr_t addr = 0;\n \n-\tif (macb_dma64(bp)) {\n+\tif (macb_dma64(ctx-\u003einfo)) {\n \t\tstruct macb_dma_desc_64 *desc_64;\n \n-\t\tdesc_64 = macb_64b_desc(bp, desc);\n+\t\tdesc_64 = macb_64b_desc(desc);\n \t\taddr = ((u64)(desc_64-\u003eaddrh) \u003c\u003c 32);\n \t}\n \taddr |= MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc-\u003eaddr));\n-\tif (macb_dma_ptp(bp))\n+\tif (macb_dma_ptp(ctx-\u003einfo))\n \t\taddr \u0026= ~GEM_BIT(DMA_RXVALID);\n \treturn addr;\n }\n \n static void macb_tx_error_task(struct work_struct *work)\n {\n-\tstruct macb_queue\t*queue = container_of(work, struct macb_queue,\n-\t\t\t\t\t\t      tx_error_task);\n-\tbool\t\t\thalt_timeout = false;\n-\tstruct macb\t\t*bp = queue-\u003ebp;\n-\tu32\t\t\tqueue_index;\n-\tu32\t\t\tpackets = 0;\n-\tu32\t\t\tbytes = 0;\n-\tstruct macb_tx_skb\t*tx_skb;\n-\tstruct macb_dma_desc\t*desc;\n-\tstruct sk_buff\t\t*skb;\n-\tunsigned int\t\ttail;\n-\tunsigned long\t\tflags;\n-\n-\tqueue_index = queue - bp-\u003equeues;\n-\tnetdev_vdbg(bp-\u003edev, \"macb_tx_error_task: q = %u, t = %u, h = %u\\n\",\n-\t\t    queue_index, queue-\u003etx_tail, queue-\u003etx_head);\n+\tstruct macb_queue *queue = container_of(work, struct macb_queue,\n+\t\t\t\t\t\ttx_error_task);\n+\tunsigned int q = queue - queue-\u003ebp-\u003equeues;\n+\tstruct macb_context *ctx = queue-\u003ebp-\u003ectx;\n+\tstruct macb_txq *txq = macb_txq(queue);\n+\tstruct macb *bp = queue-\u003ebp;\n+\tstruct macb_tx_skb *tx_skb;\n+\tstruct macb_dma_desc *desc;\n+\tbool halt_timeout = false;\n+\tbool buggy_driver = false;\n+\tstruct sk_buff *skb;\n+\tunsigned long flags;\n+\tunsigned int tail;\n+\tu32 packets = 0;\n+\tu32 bytes = 0;\n+\n+\tnetdev_vdbg(bp-\u003enetdev, \"%s: q = %u, t = %u, h = %u\\n\",\n+\t\t    __func__, q, txq-\u003etail, txq-\u003ehead);\n \n \t/* Prevent the queue NAPI TX poll from running, as it calls\n \t * macb_tx_complete(), which in turn may call netif_wake_subqueue().\n@@ -1281,14 +1351,13 @@ static void macb_tx_error_task(struct work_struct *work)\n \tspin_lock_irqsave(\u0026bp-\u003elock, flags);\n \n \t/* Make sure nobody is trying to queue up new packets */\n-\tnetif_tx_stop_all_queues(bp-\u003edev);\n+\tnetif_tx_stop_all_queues(bp-\u003enetdev);\n \n \t/* Stop transmission now\n \t * (in case we have just queued new packets)\n \t * macb/gem must be halted to write TBQP register\n \t */\n \tif (macb_halt_tx(bp)) {\n-\t\tnetdev_err(bp-\u003edev, \"BUG: halt tx timed out\\n\");\n \t\tmacb_writel(bp, NCR, macb_readl(bp, NCR) \u0026 (~MACB_BIT(TE)));\n \t\thalt_timeout = true;\n \t}\n@@ -1296,10 +1365,10 @@ static void macb_tx_error_task(struct work_struct *work)\n \t/* Treat frames in TX queue including the ones that caused the error.\n \t * Free transmit buffers in upper layer.\n \t */\n-\tfor (tail = queue-\u003etx_tail; tail != queue-\u003etx_head; tail++) {\n+\tfor (tail = txq-\u003etail; tail != txq-\u003ehead; tail++) {\n \t\tu32\tctrl;\n \n-\t\tdesc = macb_tx_desc(queue, tail);\n+\t\tdesc = macb_tx_desc(ctx, q, tail);\n \t\tctrl = desc-\u003ectrl;\n \t\ttx_skb = macb_tx_skb(queue, tail);\n \t\tskb = tx_skb-\u003eskb;\n@@ -1307,7 +1376,7 @@ static void macb_tx_error_task(struct work_struct *work)\n \t\tif (ctrl \u0026 MACB_BIT(TX_USED)) {\n \t\t\t/* skb is set for the last buffer of the frame */\n \t\t\twhile (!skb) {\n-\t\t\t\tmacb_tx_unmap(bp, tx_skb, 0);\n+\t\t\t\tmacb_tx_unmap(\u0026bp-\u003einfo, tx_skb, 0);\n \t\t\t\ttail++;\n \t\t\t\ttx_skb = macb_tx_skb(queue, tail);\n \t\t\t\tskb = tx_skb-\u003eskb;\n@@ -1317,13 +1386,13 @@ static void macb_tx_error_task(struct work_struct *work)\n \t\t\t * since it's the only one written back by the hardware\n \t\t\t */\n \t\t\tif (!(ctrl \u0026 MACB_BIT(TX_BUF_EXHAUSTED))) {\n-\t\t\t\tnetdev_vdbg(bp-\u003edev, \"txerr skb %u (data %p) TX complete\\n\",\n-\t\t\t\t\t    macb_tx_ring_wrap(bp, tail),\n+\t\t\t\tnetdev_vdbg(bp-\u003enetdev, \"txerr skb %u (data %p) TX complete\\n\",\n+\t\t\t\t\t    macb_tx_ring_wrap(ctx, tail),\n \t\t\t\t\t    skb-\u003edata);\n-\t\t\t\tbp-\u003edev-\u003estats.tx_packets++;\n+\t\t\t\tbp-\u003enetdev-\u003estats.tx_packets++;\n \t\t\t\tqueue-\u003estats.tx_packets++;\n \t\t\t\tpackets++;\n-\t\t\t\tbp-\u003edev-\u003estats.tx_bytes += skb-\u003elen;\n+\t\t\t\tbp-\u003enetdev-\u003estats.tx_bytes += skb-\u003elen;\n \t\t\t\tqueue-\u003estats.tx_bytes += skb-\u003elen;\n \t\t\t\tbytes += skb-\u003elen;\n \t\t\t}\n@@ -1333,31 +1402,30 @@ static void macb_tx_error_task(struct work_struct *work)\n \t\t\t * those. Statistics are updated by hardware.\n \t\t\t */\n \t\t\tif (ctrl \u0026 MACB_BIT(TX_BUF_EXHAUSTED))\n-\t\t\t\tnetdev_err(bp-\u003edev,\n-\t\t\t\t\t   \"BUG: TX buffers exhausted mid-frame\\n\");\n+\t\t\t\tbuggy_driver = true;\n \n \t\t\tdesc-\u003ectrl = ctrl | MACB_BIT(TX_USED);\n \t\t}\n \n-\t\tmacb_tx_unmap(bp, tx_skb, 0);\n+\t\tmacb_tx_unmap(\u0026bp-\u003einfo, tx_skb, 0);\n \t}\n \n-\tnetdev_tx_completed_queue(netdev_get_tx_queue(bp-\u003edev, queue_index),\n+\tnetdev_tx_completed_queue(netdev_get_tx_queue(bp-\u003enetdev, q),\n \t\t\t\t  packets, bytes);\n \n \t/* Set end of TX queue */\n-\tdesc = macb_tx_desc(queue, 0);\n-\tmacb_set_addr(bp, desc, 0);\n+\tdesc = macb_tx_desc(ctx, q, 0);\n+\tmacb_set_addr(\u0026bp-\u003einfo, desc, 0);\n \tdesc-\u003ectrl = MACB_BIT(TX_USED);\n \n \t/* Make descriptor updates visible to hardware */\n \twmb();\n \n \t/* Reinitialize the TX desc queue */\n-\tqueue_writel(queue, TBQP, lower_32_bits(queue-\u003etx_ring_dma));\n+\tqueue_writel(queue, TBQP, lower_32_bits(txq-\u003ering_dma));\n \t/* Make TX ring reflect state of hardware */\n-\tqueue-\u003etx_head = 0;\n-\tqueue-\u003etx_tail = 0;\n+\ttxq-\u003ehead = 0;\n+\ttxq-\u003etail = 0;\n \n \t/* Housework before enabling TX IRQ */\n \tmacb_writel(bp, TSR, macb_readl(bp, TSR));\n@@ -1367,11 +1435,18 @@ static void macb_tx_error_task(struct work_struct *work)\n \t\tmacb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE));\n \n \t/* Now we are ready to start transmission again */\n-\tnetif_tx_start_all_queues(bp-\u003edev);\n+\tnetif_tx_start_all_queues(bp-\u003enetdev);\n \tmacb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));\n \n \tspin_unlock_irqrestore(\u0026bp-\u003elock, flags);\n+\n \tnapi_enable(\u0026queue-\u003enapi_tx);\n+\n+\tif (halt_timeout)\n+\t\tnetdev_err(bp-\u003enetdev, \"BUG: halt tx timed out, we ignored it\\n\");\n+\n+\tif (buggy_driver)\n+\t\tnetdev_err(bp-\u003enetdev, \"BUG: TX buffers exhausted mid-frame\\n\");\n }\n \n static bool ptp_one_step_sync(struct sk_buff *skb)\n@@ -1407,7 +1482,9 @@ static bool ptp_one_step_sync(struct sk_buff *skb)\n static int macb_tx_complete(struct macb_queue *queue, int budget)\n {\n \tstruct macb *bp = queue-\u003ebp;\n-\tu16 queue_index = queue - bp-\u003equeues;\n+\tstruct macb_txq *txq = macb_txq(queue);\n+\tunsigned int q = queue - bp-\u003equeues;\n+\tstruct macb_context *ctx = bp-\u003ectx;\n \tunsigned long flags;\n \tunsigned int tail;\n \tunsigned int head;\n@@ -1415,14 +1492,14 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)\n \tu32 bytes = 0;\n \n \tspin_lock_irqsave(\u0026queue-\u003etx_ptr_lock, flags);\n-\thead = queue-\u003etx_head;\n-\tfor (tail = queue-\u003etx_tail; tail != head \u0026\u0026 packets \u003c budget; tail++) {\n+\thead = txq-\u003ehead;\n+\tfor (tail = txq-\u003etail; tail != head \u0026\u0026 packets \u003c budget; tail++) {\n \t\tstruct macb_tx_skb\t*tx_skb;\n \t\tstruct sk_buff\t\t*skb;\n \t\tstruct macb_dma_desc\t*desc;\n \t\tu32\t\t\tctrl;\n \n-\t\tdesc = macb_tx_desc(queue, tail);\n+\t\tdesc = macb_tx_desc(ctx, q, tail);\n \n \t\t/* Make hw descriptor updates visible to CPU */\n \t\trmb();\n@@ -1446,19 +1523,19 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)\n \t\t\t\t    !ptp_one_step_sync(skb))\n \t\t\t\t\tgem_ptp_do_txstamp(bp, skb, desc);\n \n-\t\t\t\tnetdev_vdbg(bp-\u003edev, \"skb %u (data %p) TX complete\\n\",\n-\t\t\t\t\t    macb_tx_ring_wrap(bp, tail),\n+\t\t\t\tnetdev_vdbg(bp-\u003enetdev, \"skb %u (data %p) TX complete\\n\",\n+\t\t\t\t\t    macb_tx_ring_wrap(ctx, tail),\n \t\t\t\t\t    skb-\u003edata);\n-\t\t\t\tbp-\u003edev-\u003estats.tx_packets++;\n+\t\t\t\tbp-\u003enetdev-\u003estats.tx_packets++;\n \t\t\t\tqueue-\u003estats.tx_packets++;\n-\t\t\t\tbp-\u003edev-\u003estats.tx_bytes += skb-\u003elen;\n+\t\t\t\tbp-\u003enetdev-\u003estats.tx_bytes += skb-\u003elen;\n \t\t\t\tqueue-\u003estats.tx_bytes += skb-\u003elen;\n \t\t\t\tpackets++;\n \t\t\t\tbytes += skb-\u003elen;\n \t\t\t}\n \n \t\t\t/* Now we can safely release resources */\n-\t\t\tmacb_tx_unmap(bp, tx_skb, budget);\n+\t\t\tmacb_tx_unmap(\u0026bp-\u003einfo, tx_skb, budget);\n \n \t\t\t/* skb is set only for the last buffer of the frame.\n \t\t\t * WARNING: at this point skb has been freed by\n@@ -1469,14 +1546,14 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)\n \t\t}\n \t}\n \n-\tnetdev_tx_completed_queue(netdev_get_tx_queue(bp-\u003edev, queue_index),\n+\tnetdev_tx_completed_queue(netdev_get_tx_queue(bp-\u003enetdev, q),\n \t\t\t\t  packets, bytes);\n \n-\tqueue-\u003etx_tail = tail;\n-\tif (__netif_subqueue_stopped(bp-\u003edev, queue_index) \u0026\u0026\n-\t    CIRC_CNT(queue-\u003etx_head, queue-\u003etx_tail,\n-\t\t     bp-\u003etx_ring_size) \u003c= MACB_TX_WAKEUP_THRESH(bp))\n-\t\tnetif_wake_subqueue(bp-\u003edev, queue_index);\n+\ttxq-\u003etail = tail;\n+\tif (__netif_subqueue_stopped(bp-\u003enetdev, q) \u0026\u0026\n+\t    CIRC_CNT(txq-\u003ehead, txq-\u003etail,\n+\t\t     bp-\u003ectx-\u003etx_ring_size) \u003c= MACB_TX_WAKEUP_THRESH(bp))\n+\t\tnetif_wake_subqueue(bp-\u003enetdev, q);\n \tspin_unlock_irqrestore(\u0026queue-\u003etx_ptr_lock, flags);\n \n \tif (packets)\n@@ -1485,51 +1562,53 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)\n \treturn packets;\n }\n \n-static void gem_rx_refill(struct macb_queue *queue)\n+static void gem_rx_refill(struct macb_context *ctx, unsigned int q)\n {\n-\tunsigned int\t\tentry;\n-\tstruct sk_buff\t\t*skb;\n-\tdma_addr_t\t\tpaddr;\n-\tstruct macb *bp = queue-\u003ebp;\n+\tstruct device *dev = \u0026ctx-\u003einfo-\u003epdev-\u003edev;\n+\tstruct macb_rxq *rxq = \u0026ctx-\u003erxq[q];\n \tstruct macb_dma_desc *desc;\n+\tstruct sk_buff *skb;\n+\tunsigned int entry;\n+\tdma_addr_t paddr;\n \n-\twhile (CIRC_SPACE(queue-\u003erx_prepared_head, queue-\u003erx_tail,\n-\t\t\tbp-\u003erx_ring_size) \u003e 0) {\n-\t\tentry = macb_rx_ring_wrap(bp, queue-\u003erx_prepared_head);\n+\twhile (CIRC_SPACE(rxq-\u003eprepared_head, rxq-\u003etail,\n+\t\t\t  ctx-\u003erx_ring_size) \u003e 0) {\n+\t\tentry = macb_rx_ring_wrap(ctx, rxq-\u003eprepared_head);\n \n \t\t/* Make hw descriptor updates visible to CPU */\n \t\trmb();\n \n-\t\tdesc = macb_rx_desc(queue, entry);\n+\t\tdesc = macb_rx_desc(ctx, q, entry);\n \n-\t\tif (!queue-\u003erx_skbuff[entry]) {\n+\t\tif (!rxq-\u003eskbuff[entry]) {\n \t\t\t/* allocate sk_buff for this free entry in ring */\n-\t\t\tskb = netdev_alloc_skb(bp-\u003edev, bp-\u003erx_buffer_size);\n+\t\t\tskb = netdev_alloc_skb(ctx-\u003einfo-\u003enetdev,\n+\t\t\t\t\t       ctx-\u003erx_buffer_size);\n \t\t\tif (unlikely(!skb)) {\n-\t\t\t\tnetdev_err(bp-\u003edev,\n+\t\t\t\tnetdev_err(ctx-\u003einfo-\u003enetdev,\n \t\t\t\t\t   \"Unable to allocate sk_buff\\n\");\n \t\t\t\tbreak;\n \t\t\t}\n \n \t\t\t/* now fill corresponding descriptor entry */\n-\t\t\tpaddr = dma_map_single(\u0026bp-\u003epdev-\u003edev, skb-\u003edata,\n-\t\t\t\t\t       bp-\u003erx_buffer_size,\n+\t\t\tpaddr = dma_map_single(dev, skb-\u003edata,\n+\t\t\t\t\t       ctx-\u003erx_buffer_size,\n \t\t\t\t\t       DMA_FROM_DEVICE);\n-\t\t\tif (dma_mapping_error(\u0026bp-\u003epdev-\u003edev, paddr)) {\n+\t\t\tif (dma_mapping_error(dev, paddr)) {\n \t\t\t\tdev_kfree_skb(skb);\n \t\t\t\tbreak;\n \t\t\t}\n \n-\t\t\tqueue-\u003erx_skbuff[entry] = skb;\n+\t\t\trxq-\u003eskbuff[entry] = skb;\n \n-\t\t\tif (entry == bp-\u003erx_ring_size - 1)\n+\t\t\tif (entry == ctx-\u003erx_ring_size - 1)\n \t\t\t\tpaddr |= MACB_BIT(RX_WRAP);\n \t\t\tdesc-\u003ectrl = 0;\n \t\t\t/* Setting addr clears RX_USED and allows reception,\n \t\t\t * make sure ctrl is cleared first to avoid a race.\n \t\t\t */\n \t\t\tdma_wmb();\n-\t\t\tmacb_set_addr(bp, desc, paddr);\n+\t\t\tmacb_set_addr(ctx-\u003einfo, desc, paddr);\n \n \t\t\t/* Properly align Ethernet header.\n \t\t\t *\n@@ -1542,31 +1621,34 @@ static void gem_rx_refill(struct macb_queue *queue)\n \t\t\t * setting the low 2/3 bits.\n \t\t\t * It is 3 bits if HW_DMA_CAP_PTP, else 2 bits.\n \t\t\t */\n-\t\t\tif (!(bp-\u003ecaps \u0026 MACB_CAPS_RSC))\n+\t\t\tif (!(ctx-\u003einfo-\u003ecaps \u0026 MACB_CAPS_RSC))\n \t\t\t\tskb_reserve(skb, NET_IP_ALIGN);\n \t\t} else {\n \t\t\tdesc-\u003ectrl = 0;\n \t\t\tdma_wmb();\n \t\t\tdesc-\u003eaddr \u0026= ~MACB_BIT(RX_USED);\n \t\t}\n-\t\tqueue-\u003erx_prepared_head++;\n+\t\trxq-\u003eprepared_head++;\n \t}\n \n \t/* Make descriptor updates visible to hardware */\n \twmb();\n \n-\tnetdev_vdbg(bp-\u003edev, \"rx ring: queue: %p, prepared head %d, tail %d\\n\",\n-\t\t\tqueue, queue-\u003erx_prepared_head, queue-\u003erx_tail);\n+\tnetdev_vdbg(ctx-\u003einfo-\u003enetdev,\n+\t\t    \"rx ring: queue: %u, prepared head %d, tail %d\\n\",\n+\t\t    q, rxq-\u003eprepared_head, rxq-\u003etail);\n }\n \n /* Mark DMA descriptors from begin up to and not including end as unused */\n static void discard_partial_frame(struct macb_queue *queue, unsigned int begin,\n \t\t\t\t  unsigned int end)\n {\n+\tunsigned int q = queue - queue-\u003ebp-\u003equeues;\n+\tstruct macb_context *ctx = queue-\u003ebp-\u003ectx;\n \tunsigned int frag;\n \n \tfor (frag = begin; frag != end; frag++) {\n-\t\tstruct macb_dma_desc *desc = macb_rx_desc(queue, frag);\n+\t\tstruct macb_dma_desc *desc = macb_rx_desc(ctx, q, frag);\n \n \t\tdesc-\u003eaddr \u0026= ~MACB_BIT(RX_USED);\n \t}\n@@ -1583,26 +1665,29 @@ static void discard_partial_frame(struct macb_queue *queue, unsigned int begin,\n static int gem_rx(struct macb_queue *queue, struct napi_struct *napi,\n \t\t  int budget)\n {\n+\tunsigned int q = queue - queue-\u003ebp-\u003equeues;\n+\tstruct macb_context *ctx = queue-\u003ebp-\u003ectx;\n+\tstruct macb_rxq *rxq = macb_rxq(queue);\n \tstruct macb *bp = queue-\u003ebp;\n-\tunsigned int\t\tlen;\n-\tunsigned int\t\tentry;\n-\tstruct sk_buff\t\t*skb;\n-\tstruct macb_dma_desc\t*desc;\n-\tint\t\t\tcount = 0;\n+\tstruct macb_dma_desc *desc;\n+\tstruct sk_buff *skb;\n+\tunsigned int entry;\n+\tunsigned int len;\n+\tint count = 0;\n \n \twhile (count \u003c budget) {\n \t\tu32 ctrl;\n \t\tdma_addr_t addr;\n \t\tbool rxused;\n \n-\t\tentry = macb_rx_ring_wrap(bp, queue-\u003erx_tail);\n-\t\tdesc = macb_rx_desc(queue, entry);\n+\t\tentry = macb_rx_ring_wrap(ctx, rxq-\u003etail);\n+\t\tdesc = macb_rx_desc(ctx, q, entry);\n \n \t\t/* Make hw descriptor updates visible to CPU */\n \t\trmb();\n \n \t\trxused = (desc-\u003eaddr \u0026 MACB_BIT(RX_USED)) ? true : false;\n-\t\taddr = macb_get_addr(bp, desc);\n+\t\taddr = macb_get_addr(ctx, desc);\n \n \t\tif (!rxused)\n \t\t\tbreak;\n@@ -1612,50 +1697,51 @@ static int gem_rx(struct macb_queue *queue, struct napi_struct *napi,\n \n \t\tctrl = desc-\u003ectrl;\n \n-\t\tqueue-\u003erx_tail++;\n+\t\trxq-\u003etail++;\n \t\tcount++;\n \n \t\tif (!(ctrl \u0026 MACB_BIT(RX_SOF) \u0026\u0026 ctrl \u0026 MACB_BIT(RX_EOF))) {\n-\t\t\tnetdev_err(bp-\u003edev,\n+\t\t\tnetdev_err(bp-\u003enetdev,\n \t\t\t\t   \"not whole frame pointed by descriptor\\n\");\n-\t\t\tbp-\u003edev-\u003estats.rx_dropped++;\n+\t\t\tbp-\u003enetdev-\u003estats.rx_dropped++;\n \t\t\tqueue-\u003estats.rx_dropped++;\n \t\t\tbreak;\n \t\t}\n-\t\tskb = queue-\u003erx_skbuff[entry];\n+\t\tskb = rxq-\u003eskbuff[entry];\n \t\tif (unlikely(!skb)) {\n-\t\t\tnetdev_err(bp-\u003edev,\n+\t\t\tnetdev_err(bp-\u003enetdev,\n \t\t\t\t   \"inconsistent Rx descriptor chain\\n\");\n-\t\t\tbp-\u003edev-\u003estats.rx_dropped++;\n+\t\t\tbp-\u003enetdev-\u003estats.rx_dropped++;\n \t\t\tqueue-\u003estats.rx_dropped++;\n \t\t\tbreak;\n \t\t}\n \t\t/* now everything is ready for receiving packet */\n-\t\tqueue-\u003erx_skbuff[entry] = NULL;\n+\t\trxq-\u003eskbuff[entry] = NULL;\n \t\tlen = ctrl \u0026 bp-\u003erx_frm_len_mask;\n \n-\t\tnetdev_vdbg(bp-\u003edev, \"gem_rx %u (len %u)\\n\", entry, len);\n+\t\tnetdev_vdbg(bp-\u003enetdev, \"%s %u (len %u)\\n\",\n+\t\t\t    __func__, entry, len);\n \n \t\tskb_put(skb, len);\n \t\tdma_unmap_single(\u0026bp-\u003epdev-\u003edev, addr,\n-\t\t\t\t bp-\u003erx_buffer_size, DMA_FROM_DEVICE);\n+\t\t\t\t bp-\u003ectx-\u003erx_buffer_size, DMA_FROM_DEVICE);\n \n-\t\tskb-\u003eprotocol = eth_type_trans(skb, bp-\u003edev);\n+\t\tskb-\u003eprotocol = eth_type_trans(skb, bp-\u003enetdev);\n \t\tskb_checksum_none_assert(skb);\n-\t\tif (bp-\u003edev-\u003efeatures \u0026 NETIF_F_RXCSUM \u0026\u0026\n-\t\t    !(bp-\u003edev-\u003eflags \u0026 IFF_PROMISC) \u0026\u0026\n+\t\tif (bp-\u003enetdev-\u003efeatures \u0026 NETIF_F_RXCSUM \u0026\u0026\n+\t\t    !(bp-\u003enetdev-\u003eflags \u0026 IFF_PROMISC) \u0026\u0026\n \t\t    GEM_BFEXT(RX_CSUM, ctrl) \u0026 GEM_RX_CSUM_CHECKED_MASK)\n \t\t\tskb-\u003eip_summed = CHECKSUM_UNNECESSARY;\n \n-\t\tbp-\u003edev-\u003estats.rx_packets++;\n+\t\tbp-\u003enetdev-\u003estats.rx_packets++;\n \t\tqueue-\u003estats.rx_packets++;\n-\t\tbp-\u003edev-\u003estats.rx_bytes += skb-\u003elen;\n+\t\tbp-\u003enetdev-\u003estats.rx_bytes += skb-\u003elen;\n \t\tqueue-\u003estats.rx_bytes += skb-\u003elen;\n \n \t\tgem_ptp_do_rxstamp(bp, skb, desc);\n \n #if defined(DEBUG) \u0026\u0026 defined(VERBOSE_DEBUG)\n-\t\tnetdev_vdbg(bp-\u003edev, \"received skb of length %u, csum: %08x\\n\",\n+\t\tnetdev_vdbg(bp-\u003enetdev, \"received skb of length %u, csum: %08x\\n\",\n \t\t\t    skb-\u003elen, skb-\u003ecsum);\n \t\tprint_hex_dump(KERN_DEBUG, \" mac: \", DUMP_PREFIX_ADDRESS, 16, 1,\n \t\t\t       skb_mac_header(skb), 16, true);\n@@ -1666,7 +1752,7 @@ static int gem_rx(struct macb_queue *queue, struct napi_struct *napi,\n \t\tnapi_gro_receive(napi, skb);\n \t}\n \n-\tgem_rx_refill(queue);\n+\tgem_rx_refill(ctx, q);\n \n \treturn count;\n }\n@@ -1674,19 +1760,22 @@ static int gem_rx(struct macb_queue *queue, struct napi_struct *napi,\n static int macb_rx_frame(struct macb_queue *queue, struct napi_struct *napi,\n \t\t\t unsigned int first_frag, unsigned int last_frag)\n {\n-\tunsigned int len;\n-\tunsigned int frag;\n+\tunsigned int q = queue - queue-\u003ebp-\u003equeues;\n+\tstruct macb_context *ctx = queue-\u003ebp-\u003ectx;\n+\tstruct macb *bp = queue-\u003ebp;\n+\tstruct macb_dma_desc *desc;\n \tunsigned int offset;\n \tstruct sk_buff *skb;\n-\tstruct macb_dma_desc *desc;\n-\tstruct macb *bp = queue-\u003ebp;\n+\tunsigned int frag;\n+\tunsigned int len;\n \n-\tdesc = macb_rx_desc(queue, last_frag);\n+\tdesc = macb_rx_desc(ctx, q, last_frag);\n \tlen = desc-\u003ectrl \u0026 bp-\u003erx_frm_len_mask;\n \n-\tnetdev_vdbg(bp-\u003edev, \"macb_rx_frame frags %u - %u (len %u)\\n\",\n-\t\tmacb_rx_ring_wrap(bp, first_frag),\n-\t\tmacb_rx_ring_wrap(bp, last_frag), len);\n+\tnetdev_vdbg(bp-\u003enetdev, \"%s frags %u - %u (len %u)\\n\",\n+\t\t    __func__,\n+\t\t    macb_rx_ring_wrap(ctx, first_frag),\n+\t\t    macb_rx_ring_wrap(ctx, last_frag), len);\n \n \t/* The ethernet header starts NET_IP_ALIGN bytes into the\n \t * first buffer. Since the header is 14 bytes, this makes the\n@@ -1696,11 +1785,11 @@ static int macb_rx_frame(struct macb_queue *queue, struct napi_struct *napi,\n \t * the two padding bytes into the skb so that we avoid hitting\n \t * the slowpath in memcpy(), and pull them off afterwards.\n \t */\n-\tskb = netdev_alloc_skb(bp-\u003edev, len + NET_IP_ALIGN);\n+\tskb = netdev_alloc_skb(bp-\u003enetdev, len + NET_IP_ALIGN);\n \tif (!skb) {\n-\t\tbp-\u003edev-\u003estats.rx_dropped++;\n+\t\tbp-\u003enetdev-\u003estats.rx_dropped++;\n \t\tfor (frag = first_frag; ; frag++) {\n-\t\t\tdesc = macb_rx_desc(queue, frag);\n+\t\t\tdesc = macb_rx_desc(ctx, q, frag);\n \t\t\tdesc-\u003eaddr \u0026= ~MACB_BIT(RX_USED);\n \t\t\tif (frag == last_frag)\n \t\t\t\tbreak;\n@@ -1718,7 +1807,7 @@ static int macb_rx_frame(struct macb_queue *queue, struct napi_struct *napi,\n \tskb_put(skb, len);\n \n \tfor (frag = first_frag; ; frag++) {\n-\t\tunsigned int frag_len = bp-\u003erx_buffer_size;\n+\t\tunsigned int frag_len = bp-\u003ectx-\u003erx_buffer_size;\n \n \t\tif (offset + frag_len \u003e len) {\n \t\t\tif (unlikely(frag != last_frag)) {\n@@ -1730,8 +1819,8 @@ static int macb_rx_frame(struct macb_queue *queue, struct napi_struct *napi,\n \t\tskb_copy_to_linear_data_offset(skb, offset,\n \t\t\t\t\t       macb_rx_buffer(queue, frag),\n \t\t\t\t\t       frag_len);\n-\t\toffset += bp-\u003erx_buffer_size;\n-\t\tdesc = macb_rx_desc(queue, frag);\n+\t\toffset += bp-\u003ectx-\u003erx_buffer_size;\n+\t\tdesc = macb_rx_desc(ctx, q, frag);\n \t\tdesc-\u003eaddr \u0026= ~MACB_BIT(RX_USED);\n \n \t\tif (frag == last_frag)\n@@ -1742,46 +1831,49 @@ static int macb_rx_frame(struct macb_queue *queue, struct napi_struct *napi,\n \twmb();\n \n \t__skb_pull(skb, NET_IP_ALIGN);\n-\tskb-\u003eprotocol = eth_type_trans(skb, bp-\u003edev);\n+\tskb-\u003eprotocol = eth_type_trans(skb, bp-\u003enetdev);\n \n-\tbp-\u003edev-\u003estats.rx_packets++;\n-\tbp-\u003edev-\u003estats.rx_bytes += skb-\u003elen;\n-\tnetdev_vdbg(bp-\u003edev, \"received skb of length %u, csum: %08x\\n\",\n+\tbp-\u003enetdev-\u003estats.rx_packets++;\n+\tbp-\u003enetdev-\u003estats.rx_bytes += skb-\u003elen;\n+\tnetdev_vdbg(bp-\u003enetdev, \"received skb of length %u, csum: %08x\\n\",\n \t\t    skb-\u003elen, skb-\u003ecsum);\n \tnapi_gro_receive(napi, skb);\n \n \treturn 0;\n }\n \n-static inline void macb_init_rx_ring(struct macb_queue *queue)\n+static inline void macb_init_rx_ring(struct macb_context *ctx, unsigned int q)\n {\n-\tstruct macb *bp = queue-\u003ebp;\n-\tdma_addr_t addr;\n+\tstruct macb_rxq *rxq = \u0026ctx-\u003erxq[q];\n \tstruct macb_dma_desc *desc = NULL;\n+\tdma_addr_t addr;\n \tint i;\n \n-\taddr = queue-\u003erx_buffers_dma;\n-\tfor (i = 0; i \u003c bp-\u003erx_ring_size; i++) {\n-\t\tdesc = macb_rx_desc(queue, i);\n-\t\tmacb_set_addr(bp, desc, addr);\n+\taddr = rxq-\u003ebuffers_dma;\n+\tfor (i = 0; i \u003c ctx-\u003erx_ring_size; i++) {\n+\t\tdesc = macb_rx_desc(ctx, q, i);\n+\t\tmacb_set_addr(ctx-\u003einfo, desc, addr);\n \t\tdesc-\u003ectrl = 0;\n-\t\taddr += bp-\u003erx_buffer_size;\n+\t\taddr += ctx-\u003erx_buffer_size;\n \t}\n \tdesc-\u003eaddr |= MACB_BIT(RX_WRAP);\n-\tqueue-\u003erx_tail = 0;\n+\trxq-\u003etail = 0;\n }\n \n static int macb_rx(struct macb_queue *queue, struct napi_struct *napi,\n \t\t   int budget)\n {\n+\tunsigned int q = queue - queue-\u003ebp-\u003equeues;\n+\tstruct macb_context *ctx = queue-\u003ebp-\u003ectx;\n+\tstruct macb_rxq *rxq = macb_rxq(queue);\n \tstruct macb *bp = queue-\u003ebp;\n \tbool reset_rx_queue = false;\n-\tint received = 0;\n-\tunsigned int tail;\n \tint first_frag = -1;\n+\tunsigned int tail;\n+\tint received = 0;\n \n-\tfor (tail = queue-\u003erx_tail; budget \u003e 0; tail++) {\n-\t\tstruct macb_dma_desc *desc = macb_rx_desc(queue, tail);\n+\tfor (tail = rxq-\u003etail; budget \u003e 0; tail++) {\n+\t\tstruct macb_dma_desc *desc = macb_rx_desc(ctx, q, tail);\n \t\tu32 ctrl;\n \n \t\t/* Make hw descriptor updates visible to CPU */\n@@ -1826,15 +1918,15 @@ static int macb_rx(struct macb_queue *queue, struct napi_struct *napi,\n \t\tunsigned long flags;\n \t\tu32 ctrl;\n \n-\t\tnetdev_err(bp-\u003edev, \"RX queue corruption: reset it\\n\");\n+\t\tnetdev_err(bp-\u003enetdev, \"RX queue corruption: reset it\\n\");\n \n \t\tspin_lock_irqsave(\u0026bp-\u003elock, flags);\n \n \t\tctrl = macb_readl(bp, NCR);\n \t\tmacb_writel(bp, NCR, ctrl \u0026 ~MACB_BIT(RE));\n \n-\t\tmacb_init_rx_ring(queue);\n-\t\tqueue_writel(queue, RBQP, queue-\u003erx_ring_dma);\n+\t\tmacb_init_rx_ring(ctx, q);\n+\t\tqueue_writel(queue, RBQP, rxq-\u003ering_dma);\n \n \t\tmacb_writel(bp, NCR, ctrl | MACB_BIT(RE));\n \n@@ -1843,21 +1935,23 @@ static int macb_rx(struct macb_queue *queue, struct napi_struct *napi,\n \t}\n \n \tif (first_frag != -1)\n-\t\tqueue-\u003erx_tail = first_frag;\n+\t\trxq-\u003etail = first_frag;\n \telse\n-\t\tqueue-\u003erx_tail = tail;\n+\t\trxq-\u003etail = tail;\n \n \treturn received;\n }\n \n static bool macb_rx_pending(struct macb_queue *queue)\n {\n-\tstruct macb *bp = queue-\u003ebp;\n-\tunsigned int\t\tentry;\n-\tstruct macb_dma_desc\t*desc;\n+\tunsigned int q = queue - queue-\u003ebp-\u003equeues;\n+\tstruct macb_context *ctx = queue-\u003ebp-\u003ectx;\n+\tstruct macb_rxq *rxq = macb_rxq(queue);\n+\tstruct macb_dma_desc *desc;\n+\tunsigned int entry;\n \n-\tentry = macb_rx_ring_wrap(bp, queue-\u003erx_tail);\n-\tdesc = macb_rx_desc(queue, entry);\n+\tentry = macb_rx_ring_wrap(ctx, rxq-\u003etail);\n+\tdesc = macb_rx_desc(ctx, q, entry);\n \n \t/* Make hw descriptor updates visible to CPU */\n \trmb();\n@@ -1873,7 +1967,7 @@ static int macb_rx_poll(struct napi_struct *napi, int budget)\n \n \twork_done = bp-\u003emacbgem_ops.mog_rx(queue, napi, budget);\n \n-\tnetdev_vdbg(bp-\u003edev, \"RX poll: queue = %u, work_done = %d, budget = %d\\n\",\n+\tnetdev_vdbg(bp-\u003enetdev, \"RX poll: queue = %u, work_done = %d, budget = %d\\n\",\n \t\t    (unsigned int)(queue - bp-\u003equeues), work_done, budget);\n \n \tif (work_done \u003c budget \u0026\u0026 napi_complete_done(napi, work_done)) {\n@@ -1892,7 +1986,7 @@ static int macb_rx_poll(struct napi_struct *napi, int budget)\n \t\tif (macb_rx_pending(queue)) {\n \t\t\tqueue_writel(queue, IDR, bp-\u003erx_intr_mask);\n \t\t\tmacb_queue_isr_clear(bp, queue, MACB_BIT(RCOMP));\n-\t\t\tnetdev_vdbg(bp-\u003edev, \"poll: packets pending, reschedule\\n\");\n+\t\t\tnetdev_vdbg(bp-\u003enetdev, \"poll: packets pending, reschedule\\n\");\n \t\t\tnapi_schedule(napi);\n \t\t}\n \t}\n@@ -1904,18 +1998,20 @@ static int macb_rx_poll(struct napi_struct *napi, int budget)\n \n static void macb_tx_restart(struct macb_queue *queue)\n {\n+\tstruct macb_context *ctx = queue-\u003ebp-\u003ectx;\n+\tstruct macb_txq *txq = macb_txq(queue);\n \tstruct macb *bp = queue-\u003ebp;\n \tunsigned int head_idx, tbqp;\n \tunsigned long flags;\n \n \tspin_lock_irqsave(\u0026queue-\u003etx_ptr_lock, flags);\n \n-\tif (queue-\u003etx_head == queue-\u003etx_tail)\n+\tif (txq-\u003ehead == txq-\u003etail)\n \t\tgoto out_tx_ptr_unlock;\n \n-\ttbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(bp);\n-\ttbqp = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, tbqp));\n-\thead_idx = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, queue-\u003etx_head));\n+\ttbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(ctx-\u003einfo);\n+\ttbqp = macb_adj_dma_desc_idx(ctx, macb_tx_ring_wrap(ctx, tbqp));\n+\thead_idx = macb_adj_dma_desc_idx(ctx, macb_tx_ring_wrap(ctx, txq-\u003ehead));\n \n \tif (tbqp == head_idx)\n \t\tgoto out_tx_ptr_unlock;\n@@ -1930,15 +2026,18 @@ static void macb_tx_restart(struct macb_queue *queue)\n \n static bool macb_tx_complete_pending(struct macb_queue *queue)\n {\n+\tunsigned int q = queue - queue-\u003ebp-\u003equeues;\n+\tstruct macb_context *ctx = queue-\u003ebp-\u003ectx;\n+\tstruct macb_txq *txq = macb_txq(queue);\n \tbool retval = false;\n \tunsigned long flags;\n \n \tspin_lock_irqsave(\u0026queue-\u003etx_ptr_lock, flags);\n-\tif (queue-\u003etx_head != queue-\u003etx_tail) {\n+\tif (txq-\u003ehead != txq-\u003etail) {\n \t\t/* Make hw descriptor updates visible to CPU */\n \t\trmb();\n \n-\t\tif (macb_tx_desc(queue, queue-\u003etx_tail)-\u003ectrl \u0026 MACB_BIT(TX_USED))\n+\t\tif (macb_tx_desc(ctx, q, txq-\u003etail)-\u003ectrl \u0026 MACB_BIT(TX_USED))\n \t\t\tretval = true;\n \t}\n \tspin_unlock_irqrestore(\u0026queue-\u003etx_ptr_lock, flags);\n@@ -1956,11 +2055,11 @@ static int macb_tx_poll(struct napi_struct *napi, int budget)\n \trmb(); // ensure txubr_pending is up to date\n \tif (queue-\u003etxubr_pending) {\n \t\tqueue-\u003etxubr_pending = false;\n-\t\tnetdev_vdbg(bp-\u003edev, \"poll: tx restart\\n\");\n+\t\tnetdev_vdbg(bp-\u003enetdev, \"poll: tx restart\\n\");\n \t\tmacb_tx_restart(queue);\n \t}\n \n-\tnetdev_vdbg(bp-\u003edev, \"TX poll: queue = %u, work_done = %d, budget = %d\\n\",\n+\tnetdev_vdbg(bp-\u003enetdev, \"TX poll: queue = %u, work_done = %d, budget = %d\\n\",\n \t\t    (unsigned int)(queue - bp-\u003equeues), work_done, budget);\n \n \tif (work_done \u003c budget \u0026\u0026 napi_complete_done(napi, work_done)) {\n@@ -1979,7 +2078,7 @@ static int macb_tx_poll(struct napi_struct *napi, int budget)\n \t\tif (macb_tx_complete_pending(queue)) {\n \t\t\tqueue_writel(queue, IDR, MACB_BIT(TCOMP));\n \t\t\tmacb_queue_isr_clear(bp, queue, MACB_BIT(TCOMP));\n-\t\t\tnetdev_vdbg(bp-\u003edev, \"TX poll: packets pending, reschedule\\n\");\n+\t\t\tnetdev_vdbg(bp-\u003enetdev, \"TX poll: packets pending, reschedule\\n\");\n \t\t\tnapi_schedule(napi);\n \t\t}\n \t}\n@@ -1990,7 +2089,8 @@ static int macb_tx_poll(struct napi_struct *napi, int budget)\n static void macb_hresp_error_task(struct work_struct *work)\n {\n \tstruct macb *bp = from_work(bp, work, hresp_err_bh_work);\n-\tstruct net_device *dev = bp-\u003edev;\n+\tstruct net_device *netdev = bp-\u003enetdev;\n+\tstruct macb_context *ctx = bp-\u003ectx;\n \tstruct macb_queue *queue;\n \tunsigned int q;\n \tu32 ctrl;\n@@ -2004,10 +2104,10 @@ static void macb_hresp_error_task(struct work_struct *work)\n \tctrl \u0026= ~(MACB_BIT(RE) | MACB_BIT(TE));\n \tmacb_writel(bp, NCR, ctrl);\n \n-\tnetif_tx_stop_all_queues(dev);\n-\tnetif_carrier_off(dev);\n+\tnetif_tx_stop_all_queues(netdev);\n+\tnetif_carrier_off(netdev);\n \n-\tbp-\u003emacbgem_ops.mog_init_rings(bp);\n+\tbp-\u003emacbgem_ops.mog_init_rings(ctx);\n \n \t/* Initialize TX and RX buffers */\n \tmacb_init_buffers(bp);\n@@ -2022,8 +2122,8 @@ static void macb_hresp_error_task(struct work_struct *work)\n \tctrl |= MACB_BIT(RE) | MACB_BIT(TE);\n \tmacb_writel(bp, NCR, ctrl);\n \n-\tnetif_carrier_on(dev);\n-\tnetif_tx_start_all_queues(dev);\n+\tnetif_carrier_on(netdev);\n+\tnetif_tx_start_all_queues(netdev);\n }\n \n static void macb_wol_interrupt(struct macb_queue *queue, u32 status)\n@@ -2032,7 +2132,7 @@ static void macb_wol_interrupt(struct macb_queue *queue, u32 status)\n \n \tqueue_writel(queue, IDR, MACB_BIT(WOL));\n \tmacb_writel(bp, WOL, 0);\n-\tnetdev_vdbg(bp-\u003edev, \"MACB WoL: queue = %u, isr = 0x%08lx\\n\",\n+\tnetdev_vdbg(bp-\u003enetdev, \"MACB WoL: queue = %u, isr = 0x%08lx\\n\",\n \t\t    (unsigned int)(queue - bp-\u003equeues),\n \t\t    (unsigned long)status);\n \tmacb_queue_isr_clear(bp, queue, MACB_BIT(WOL));\n@@ -2045,7 +2145,7 @@ static void gem_wol_interrupt(struct macb_queue *queue, u32 status)\n \n \tqueue_writel(queue, IDR, GEM_BIT(WOL));\n \tgem_writel(bp, WOL, 0);\n-\tnetdev_vdbg(bp-\u003edev, \"GEM WoL: queue = %u, isr = 0x%08lx\\n\",\n+\tnetdev_vdbg(bp-\u003enetdev, \"GEM WoL: queue = %u, isr = 0x%08lx\\n\",\n \t\t    (unsigned int)(queue - bp-\u003equeues),\n \t\t    (unsigned long)status);\n \tmacb_queue_isr_clear(bp, queue, GEM_BIT(WOL));\n@@ -2055,10 +2155,10 @@ static void gem_wol_interrupt(struct macb_queue *queue, u32 status)\n static int macb_interrupt_misc(struct macb_queue *queue, u32 status)\n {\n \tstruct macb *bp = queue-\u003ebp;\n-\tstruct net_device *dev;\n+\tstruct net_device *netdev;\n \tu32 ctrl;\n \n-\tdev = bp-\u003edev;\n+\tnetdev = bp-\u003enetdev;\n \n \tif (unlikely(status \u0026 (MACB_TX_ERR_FLAGS))) {\n \t\tqueue_writel(queue, IDR, MACB_TX_INT_FLAGS);\n@@ -2089,7 +2189,7 @@ static int macb_interrupt_misc(struct macb_queue *queue, u32 status)\n \tif (status \u0026 MACB_BIT(ISR_ROVR)) {\n \t\t/* We missed at least one packet */\n \t\tspin_lock(\u0026bp-\u003estats_lock);\n-\t\tif (macb_is_gem(bp))\n+\t\tif (macb_is_gem(\u0026bp-\u003einfo))\n \t\t\tbp-\u003ehw_stats.gem.rx_overruns++;\n \t\telse\n \t\t\tbp-\u003ehw_stats.macb.rx_overruns++;\n@@ -2099,11 +2199,10 @@ static int macb_interrupt_misc(struct macb_queue *queue, u32 status)\n \n \tif (status \u0026 MACB_BIT(HRESP)) {\n \t\tqueue_work(system_bh_wq, \u0026bp-\u003ehresp_err_bh_work);\n-\t\tnetdev_err(dev, \"DMA bus error: HRESP not OK\\n\");\n \t\tmacb_queue_isr_clear(bp, queue, MACB_BIT(HRESP));\n \t}\n \n-\tif (macb_is_gem(bp)) {\n+\tif (macb_is_gem(\u0026bp-\u003einfo)) {\n \t\tif (status \u0026 GEM_BIT(WOL))\n \t\t\tgem_wol_interrupt(queue, status);\n \t} else {\n@@ -2118,25 +2217,29 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)\n {\n \tstruct macb_queue *queue = dev_id;\n \tstruct macb *bp = queue-\u003ebp;\n-\tstruct net_device *dev = bp-\u003edev;\n+\tstruct net_device *netdev = bp-\u003enetdev;\n+\tbool hresp_err = false;\n \tu32 status;\n \n-\tstatus = queue_readl(queue, ISR);\n+\tspin_lock(\u0026bp-\u003elock);\n \n-\tif (unlikely(!status))\n+\tstatus = queue_readl(queue, ISR);\n+\tif (unlikely(!status)) {\n+\t\tspin_unlock(\u0026bp-\u003elock);\n \t\treturn IRQ_NONE;\n-\n-\tspin_lock(\u0026bp-\u003elock);\n+\t}\n \n \twhile (status) {\n-\t\t/* close possible race with dev_close */\n-\t\tif (unlikely(!netif_running(dev))) {\n+\t\t/* close possible race with dev_close, and with context-swap\n+\t\t * teardown\n+\t\t */\n+\t\tif (unlikely(!netif_running(netdev) || bp-\u003ectx_swap)) {\n \t\t\tqueue_writel(queue, IDR, -1);\n \t\t\tmacb_queue_isr_clear(bp, queue, -1);\n \t\t\tbreak;\n \t\t}\n \n-\t\tnetdev_vdbg(bp-\u003edev, \"queue = %u, isr = 0x%08lx\\n\",\n+\t\tnetdev_vdbg(netdev, \"queue = %u, isr = 0x%08lx\\n\",\n \t\t\t    (unsigned int)(queue - bp-\u003equeues),\n \t\t\t    (unsigned long)status);\n \n@@ -2165,15 +2268,22 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)\n \t\t\tnapi_schedule_irqoff(\u0026queue-\u003enapi_tx);\n \t\t}\n \n-\t\tif (unlikely(status \u0026 MACB_INT_MISC_FLAGS))\n+\t\tif (unlikely(status \u0026 MACB_INT_MISC_FLAGS)) {\n \t\t\tif (macb_interrupt_misc(queue, status))\n \t\t\t\tbreak;\n \n+\t\t\tif (status \u0026 MACB_BIT(HRESP))\n+\t\t\t\thresp_err = true;\n+\t\t}\n+\n \t\tstatus = queue_readl(queue, ISR);\n \t}\n \n \tspin_unlock(\u0026bp-\u003elock);\n \n+\tif (hresp_err)\n+\t\tnetdev_err(netdev, \"DMA bus error: HRESP not OK\\n\");\n+\n \treturn IRQ_HANDLED;\n }\n \n@@ -2181,16 +2291,16 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)\n /* Polling receive - used by netconsole and other diagnostic tools\n  * to allow network i/o with interrupts disabled.\n  */\n-static void macb_poll_controller(struct net_device *dev)\n+static void macb_poll_controller(struct net_device *netdev)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_queue *queue;\n \tunsigned long flags;\n \tunsigned int q;\n \n \tlocal_irq_save(flags);\n \tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue)\n-\t\tmacb_interrupt(dev-\u003eirq, queue);\n+\t\tmacb_interrupt(netdev-\u003eirq, queue);\n \tlocal_irq_restore(flags);\n }\n #endif\n@@ -2200,9 +2310,12 @@ static unsigned int macb_tx_map(struct macb *bp,\n \t\t\t\tstruct sk_buff *skb,\n \t\t\t\tunsigned int hdrlen)\n {\n+\tstruct macb_txq *txq = macb_txq(queue);\n \tunsigned int f, nr_frags = skb_shinfo(skb)-\u003enr_frags;\n-\tunsigned int len, i, tx_head = queue-\u003etx_head;\n+\tunsigned int len, i, tx_head = txq-\u003ehead;\n \tu32 ctrl, lso_ctrl = 0, seq_ctrl = 0;\n+\tunsigned int q = queue - bp-\u003equeues;\n+\tstruct macb_context *ctx = bp-\u003ectx;\n \tunsigned int eof = 1, mss_mfs = 0;\n \tstruct macb_tx_skb *tx_skb = NULL;\n \tstruct macb_dma_desc *desc;\n@@ -2277,7 +2390,7 @@ static unsigned int macb_tx_map(struct macb *bp,\n \n \t/* Should never happen */\n \tif (unlikely(!tx_skb)) {\n-\t\tnetdev_err(bp-\u003edev, \"BUG! empty skb!\\n\");\n+\t\tnetdev_err(bp-\u003enetdev, \"BUG! empty skb!\\n\");\n \t\treturn 0;\n \t}\n \n@@ -2293,7 +2406,7 @@ static unsigned int macb_tx_map(struct macb *bp,\n \t */\n \ti = tx_head;\n \tctrl = MACB_BIT(TX_USED);\n-\tdesc = macb_tx_desc(queue, i);\n+\tdesc = macb_tx_desc(ctx, q, i);\n \tdesc-\u003ectrl = ctrl;\n \n \tif (lso_ctrl) {\n@@ -2314,21 +2427,22 @@ static unsigned int macb_tx_map(struct macb *bp,\n \tdo {\n \t\ti--;\n \t\ttx_skb = macb_tx_skb(queue, i);\n-\t\tdesc = macb_tx_desc(queue, i);\n+\t\tdesc = macb_tx_desc(ctx, q, i);\n \n \t\tctrl = (u32)tx_skb-\u003esize;\n \t\tif (eof) {\n \t\t\tctrl |= MACB_BIT(TX_LAST);\n \t\t\teof = 0;\n \t\t}\n-\t\tif (unlikely(macb_tx_ring_wrap(bp, i) == bp-\u003etx_ring_size - 1))\n+\t\tif (unlikely(macb_tx_ring_wrap(ctx, i) ==\n+\t\t\t\tbp-\u003ectx-\u003etx_ring_size - 1))\n \t\t\tctrl |= MACB_BIT(TX_WRAP);\n \n \t\t/* First descriptor is header descriptor */\n-\t\tif (i == queue-\u003etx_head) {\n+\t\tif (i == txq-\u003ehead) {\n \t\t\tctrl |= MACB_BF(TX_LSO, lso_ctrl);\n \t\t\tctrl |= MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl);\n-\t\t\tif ((bp-\u003edev-\u003efeatures \u0026 NETIF_F_HW_CSUM) \u0026\u0026\n+\t\t\tif ((bp-\u003enetdev-\u003efeatures \u0026 NETIF_F_HW_CSUM) \u0026\u0026\n \t\t\t    skb-\u003eip_summed != CHECKSUM_PARTIAL \u0026\u0026 !lso_ctrl \u0026\u0026\n \t\t\t    !ptp_one_step_sync(skb))\n \t\t\t\tctrl |= MACB_BIT(TX_NOCRC);\n@@ -2339,32 +2453,32 @@ static unsigned int macb_tx_map(struct macb *bp,\n \t\t\tctrl |= MACB_BF(MSS_MFS, mss_mfs);\n \n \t\t/* Set TX buffer descriptor */\n-\t\tmacb_set_addr(bp, desc, tx_skb-\u003emapping);\n+\t\tmacb_set_addr(\u0026bp-\u003einfo, desc, tx_skb-\u003emapping);\n \t\t/* desc-\u003eaddr must be visible to hardware before clearing\n \t\t * 'TX_USED' bit in desc-\u003ectrl.\n \t\t */\n \t\twmb();\n \t\tdesc-\u003ectrl = ctrl;\n-\t} while (i != queue-\u003etx_head);\n+\t} while (i != txq-\u003ehead);\n \n-\tqueue-\u003etx_head = tx_head;\n+\ttxq-\u003ehead = tx_head;\n \n \treturn 0;\n \n dma_error:\n-\tnetdev_err(bp-\u003edev, \"TX DMA map failed\\n\");\n+\tnetdev_err(bp-\u003enetdev, \"TX DMA map failed\\n\");\n \n-\tfor (i = queue-\u003etx_head; i != tx_head; i++) {\n+\tfor (i = txq-\u003ehead; i != tx_head; i++) {\n \t\ttx_skb = macb_tx_skb(queue, i);\n \n-\t\tmacb_tx_unmap(bp, tx_skb, 0);\n+\t\tmacb_tx_unmap(\u0026bp-\u003einfo, tx_skb, 0);\n \t}\n \n \treturn -ENOMEM;\n }\n \n static netdev_features_t macb_features_check(struct sk_buff *skb,\n-\t\t\t\t\t     struct net_device *dev,\n+\t\t\t\t\t     struct net_device *netdev,\n \t\t\t\t\t     netdev_features_t features)\n {\n \tunsigned int nr_frags, f;\n@@ -2416,7 +2530,7 @@ static inline int macb_clear_csum(struct sk_buff *skb)\n \treturn 0;\n }\n \n-static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)\n+static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *netdev)\n {\n \tbool cloned = skb_cloned(*skb) || skb_header_cloned(*skb) ||\n \t\t      skb_is_nonlinear(*skb);\n@@ -2425,7 +2539,7 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)\n \tstruct sk_buff *nskb;\n \tu32 fcs;\n \n-\tif (!(ndev-\u003efeatures \u0026 NETIF_F_HW_CSUM) ||\n+\tif (!(netdev-\u003efeatures \u0026 NETIF_F_HW_CSUM) ||\n \t    !((*skb)-\u003eip_summed != CHECKSUM_PARTIAL) ||\n \t    skb_shinfo(*skb)-\u003egso_size || ptp_one_step_sync(*skb))\n \t\treturn 0;\n@@ -2467,28 +2581,30 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)\n \treturn 0;\n }\n \n-static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)\n+static netdev_tx_t macb_start_xmit(struct sk_buff *skb,\n+\t\t\t\t   struct net_device *netdev)\n {\n-\tu16 queue_index = skb_get_queue_mapping(skb);\n-\tstruct macb *bp = netdev_priv(dev);\n-\tstruct macb_queue *queue = \u0026bp-\u003equeues[queue_index];\n+\tstruct macb *bp = netdev_priv(netdev);\n+\tunsigned int q = skb_get_queue_mapping(skb);\n \tunsigned int desc_cnt, nr_frags, frag_size, f;\n+\tstruct macb_queue *queue = \u0026bp-\u003equeues[q];\n+\tstruct macb_txq *txq = macb_txq(queue);\n+\tnetdev_tx_t ret = NETDEV_TX_OK;\n \tunsigned int hdrlen;\n \tunsigned long flags;\n \tbool is_lso;\n-\tnetdev_tx_t ret = NETDEV_TX_OK;\n \n \tif (macb_clear_csum(skb)) {\n \t\tdev_kfree_skb_any(skb);\n \t\treturn ret;\n \t}\n \n-\tif (macb_pad_and_fcs(\u0026skb, dev)) {\n+\tif (macb_pad_and_fcs(\u0026skb, netdev)) {\n \t\tdev_kfree_skb_any(skb);\n \t\treturn ret;\n \t}\n \n-\tif (macb_dma_ptp(bp) \u0026\u0026\n+\tif (macb_dma_ptp(\u0026bp-\u003einfo) \u0026\u0026\n \t    (skb_shinfo(skb)-\u003etx_flags \u0026 SKBTX_HW_TSTAMP))\n \t\tskb_shinfo(skb)-\u003etx_flags |= SKBTX_IN_PROGRESS;\n \n@@ -2502,7 +2618,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\telse\n \t\t\thdrlen = skb_tcp_all_headers(skb);\n \t\tif (skb_headlen(skb) \u003c hdrlen) {\n-\t\t\tnetdev_err(bp-\u003edev, \"Error - LSO headers fragmented!!!\\n\");\n+\t\t\tnetdev_err(bp-\u003enetdev, \"Error - LSO headers fragmented!!!\\n\");\n \t\t\t/* if this is required, would need to copy to single buffer */\n \t\t\treturn NETDEV_TX_BUSY;\n \t\t}\n@@ -2510,9 +2626,9 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\thdrlen = umin(skb_headlen(skb), bp-\u003emax_tx_length);\n \n #if defined(DEBUG) \u0026\u0026 defined(VERBOSE_DEBUG)\n-\tnetdev_vdbg(bp-\u003edev,\n-\t\t    \"start_xmit: queue %hu len %u head %p data %p tail %p end %p\\n\",\n-\t\t    queue_index, skb-\u003elen, skb-\u003ehead, skb-\u003edata,\n+\tnetdev_vdbg(bp-\u003enetdev,\n+\t\t    \"start_xmit: queue %u len %u head %p data %p tail %p end %p\\n\",\n+\t\t    q, skb-\u003elen, skb-\u003ehead, skb-\u003edata,\n \t\t    skb_tail_pointer(skb), skb_end_pointer(skb));\n \tprint_hex_dump(KERN_DEBUG, \"data: \", DUMP_PREFIX_OFFSET, 16, 1,\n \t\t       skb-\u003edata, 16, true);\n@@ -2536,11 +2652,11 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)\n \tspin_lock_irqsave(\u0026queue-\u003etx_ptr_lock, flags);\n \n \t/* This is a hard error, log it. */\n-\tif (CIRC_SPACE(queue-\u003etx_head, queue-\u003etx_tail,\n-\t\t       bp-\u003etx_ring_size) \u003c desc_cnt) {\n-\t\tnetif_stop_subqueue(dev, queue_index);\n-\t\tnetdev_dbg(bp-\u003edev, \"tx_head = %u, tx_tail = %u\\n\",\n-\t\t\t   queue-\u003etx_head, queue-\u003etx_tail);\n+\tif (CIRC_SPACE(txq-\u003ehead, txq-\u003etail,\n+\t\t       bp-\u003ectx-\u003etx_ring_size) \u003c desc_cnt) {\n+\t\tnetif_stop_subqueue(netdev, q);\n+\t\tnetdev_dbg(netdev, \"txq head = %u, txq tail = %u\\n\",\n+\t\t\t   txq-\u003ehead, txq-\u003etail);\n \t\tret = NETDEV_TX_BUSY;\n \t\tgoto unlock;\n \t}\n@@ -2554,7 +2670,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)\n \t/* Make newly initialized descriptor visible to hardware */\n \twmb();\n \tskb_tx_timestamp(skb);\n-\tnetdev_tx_sent_queue(netdev_get_tx_queue(bp-\u003edev, queue_index),\n+\tnetdev_tx_sent_queue(netdev_get_tx_queue(bp-\u003enetdev, q),\n \t\t\t     skb-\u003elen);\n \n \tspin_lock(\u0026bp-\u003elock);\n@@ -2562,8 +2678,8 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)\n \tmacb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));\n \tspin_unlock(\u0026bp-\u003elock);\n \n-\tif (CIRC_SPACE(queue-\u003etx_head, queue-\u003etx_tail, bp-\u003etx_ring_size) \u003c 1)\n-\t\tnetif_stop_subqueue(dev, queue_index);\n+\tif (CIRC_SPACE(txq-\u003ehead, txq-\u003etail, bp-\u003ectx-\u003etx_ring_size) \u003c 1)\n+\t\tnetif_stop_subqueue(netdev, q);\n \n unlock:\n \tspin_unlock_irqrestore(\u0026queue-\u003etx_ptr_lock, flags);\n@@ -2571,168 +2687,179 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)\n \treturn ret;\n }\n \n-static void macb_init_rx_buffer_size(struct macb *bp, size_t size)\n+static unsigned int macb_rx_buffer_size(struct macb *bp, unsigned int mtu)\n {\n-\tif (!macb_is_gem(bp)) {\n-\t\tbp-\u003erx_buffer_size = MACB_RX_BUFFER_SIZE;\n+\tunsigned int size;\n+\n+\tif (!macb_is_gem(\u0026bp-\u003einfo)) {\n+\t\tsize = MACB_RX_BUFFER_SIZE;\n \t} else {\n-\t\tbp-\u003erx_buffer_size = MIN(size, RX_BUFFER_MAX);\n+\t\tsize = mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN;\n+\t\tsize = MIN(size, RX_BUFFER_MAX);\n \n-\t\tif (bp-\u003erx_buffer_size % RX_BUFFER_MULTIPLE) {\n-\t\t\tnetdev_dbg(bp-\u003edev,\n+\t\tif (size % RX_BUFFER_MULTIPLE) {\n+\t\t\tnetdev_dbg(bp-\u003enetdev,\n \t\t\t\t   \"RX buffer must be multiple of %d bytes, expanding\\n\",\n \t\t\t\t   RX_BUFFER_MULTIPLE);\n-\t\t\tbp-\u003erx_buffer_size =\n-\t\t\t\troundup(bp-\u003erx_buffer_size, RX_BUFFER_MULTIPLE);\n+\t\t\tsize = roundup(size, RX_BUFFER_MULTIPLE);\n \t\t}\n \t}\n \n-\tnetdev_dbg(bp-\u003edev, \"mtu [%u] rx_buffer_size [%zu]\\n\",\n-\t\t   bp-\u003edev-\u003emtu, bp-\u003erx_buffer_size);\n+\tnetdev_dbg(bp-\u003enetdev, \"mtu [%u] rx_buffer_size [%u]\\n\", mtu, size);\n+\treturn size;\n }\n \n-static void gem_free_rx_buffers(struct macb *bp)\n+static void gem_free_rx_buffers(struct macb_context *ctx)\n {\n-\tstruct sk_buff\t\t*skb;\n-\tstruct macb_dma_desc\t*desc;\n-\tstruct macb_queue *queue;\n-\tdma_addr_t\t\taddr;\n+\tstruct device *dev = \u0026ctx-\u003einfo-\u003epdev-\u003edev;\n+\tstruct macb_dma_desc *desc;\n+\tstruct macb_rxq *rxq;\n+\tstruct sk_buff *skb;\n+\tdma_addr_t addr;\n \tunsigned int q;\n \tint i;\n \n-\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n-\t\tif (!queue-\u003erx_skbuff)\n+\tfor (q = 0; q \u003c ctx-\u003einfo-\u003enum_queues; ++q) {\n+\t\trxq = \u0026ctx-\u003erxq[q];\n+\n+\t\tif (!rxq-\u003eskbuff)\n \t\t\tcontinue;\n \n-\t\tfor (i = 0; i \u003c bp-\u003erx_ring_size; i++) {\n-\t\t\tskb = queue-\u003erx_skbuff[i];\n+\t\tfor (i = 0; i \u003c ctx-\u003erx_ring_size; i++) {\n+\t\t\tskb = rxq-\u003eskbuff[i];\n \n \t\t\tif (!skb)\n \t\t\t\tcontinue;\n \n-\t\t\tdesc = macb_rx_desc(queue, i);\n-\t\t\taddr = macb_get_addr(bp, desc);\n+\t\t\tdesc = macb_rx_desc(ctx, q, i);\n+\t\t\taddr = macb_get_addr(ctx, desc);\n \n-\t\t\tdma_unmap_single(\u0026bp-\u003epdev-\u003edev, addr, bp-\u003erx_buffer_size,\n-\t\t\t\t\tDMA_FROM_DEVICE);\n+\t\t\tdma_unmap_single(dev, addr, ctx-\u003erx_buffer_size,\n+\t\t\t\t\t DMA_FROM_DEVICE);\n \t\t\tdev_kfree_skb_any(skb);\n \t\t\tskb = NULL;\n \t\t}\n \n-\t\tkfree(queue-\u003erx_skbuff);\n-\t\tqueue-\u003erx_skbuff = NULL;\n+\t\tkfree(rxq-\u003eskbuff);\n+\t\trxq-\u003eskbuff = NULL;\n \t}\n }\n \n-static void macb_free_rx_buffers(struct macb *bp)\n+static void macb_free_rx_buffers(struct macb_context *ctx)\n {\n-\tstruct macb_queue *queue = \u0026bp-\u003equeues[0];\n+\tstruct device *dev = \u0026ctx-\u003einfo-\u003epdev-\u003edev;\n+\tstruct macb_rxq *rxq = \u0026ctx-\u003erxq[0];\n \n-\tif (queue-\u003erx_buffers) {\n-\t\tdma_free_coherent(\u0026bp-\u003epdev-\u003edev,\n-\t\t\t\t  bp-\u003erx_ring_size * bp-\u003erx_buffer_size,\n-\t\t\t\t  queue-\u003erx_buffers, queue-\u003erx_buffers_dma);\n-\t\tqueue-\u003erx_buffers = NULL;\n+\tif (rxq-\u003ebuffers) {\n+\t\tdma_free_coherent(dev,\n+\t\t\t\t  ctx-\u003erx_ring_size * ctx-\u003erx_buffer_size,\n+\t\t\t\t  rxq-\u003ebuffers, rxq-\u003ebuffers_dma);\n+\t\trxq-\u003ebuffers = NULL;\n \t}\n }\n \n-static unsigned int macb_tx_ring_size_per_queue(struct macb *bp)\n+static unsigned int macb_tx_ring_size_per_queue(struct macb_context *ctx)\n {\n-\treturn macb_dma_desc_get_size(bp) * bp-\u003etx_ring_size + bp-\u003etx_bd_rd_prefetch;\n+\treturn macb_dma_desc_get_size(ctx-\u003einfo) * ctx-\u003etx_ring_size +\n+\t\t\tctx-\u003einfo-\u003etx_bd_rd_prefetch;\n }\n \n-static unsigned int macb_rx_ring_size_per_queue(struct macb *bp)\n+static unsigned int macb_rx_ring_size_per_queue(struct macb_context *ctx)\n {\n-\treturn macb_dma_desc_get_size(bp) * bp-\u003erx_ring_size + bp-\u003erx_bd_rd_prefetch;\n+\treturn macb_dma_desc_get_size(ctx-\u003einfo) * ctx-\u003erx_ring_size +\n+\t\t\tctx-\u003einfo-\u003erx_bd_rd_prefetch;\n }\n \n-static void macb_free_consistent(struct macb *bp)\n+static void macb_free(struct macb_context *ctx)\n {\n-\tstruct device *dev = \u0026bp-\u003epdev-\u003edev;\n-\tstruct macb_queue *queue;\n+\tstruct device *dev = \u0026ctx-\u003einfo-\u003epdev-\u003edev;\n+\tstruct macb_txq *txq;\n+\tstruct macb_rxq *rxq;\n \tunsigned int q;\n \tsize_t size;\n \n-\tif (bp-\u003erx_ring_tieoff) {\n-\t\tdma_free_coherent(dev, macb_dma_desc_get_size(bp),\n-\t\t\t\t  bp-\u003erx_ring_tieoff, bp-\u003erx_ring_tieoff_dma);\n-\t\tbp-\u003erx_ring_tieoff = NULL;\n-\t}\n+\tctx-\u003einfo-\u003emacbgem_ops.mog_free_rx_buffers(ctx);\n \n-\tbp-\u003emacbgem_ops.mog_free_rx_buffers(bp);\n+\ttxq = \u0026ctx-\u003etxq[0];\n+\tsize = ctx-\u003einfo-\u003enum_queues * macb_tx_ring_size_per_queue(ctx);\n+\tdma_free_coherent(dev, size, txq-\u003ering, txq-\u003ering_dma);\n \n-\tsize = bp-\u003enum_queues * macb_tx_ring_size_per_queue(bp);\n-\tdma_free_coherent(dev, size, bp-\u003equeues[0].tx_ring, bp-\u003equeues[0].tx_ring_dma);\n+\trxq = \u0026ctx-\u003erxq[0];\n+\tsize = ctx-\u003einfo-\u003enum_queues * macb_rx_ring_size_per_queue(ctx);\n+\tdma_free_coherent(dev, size, rxq-\u003ering, rxq-\u003ering_dma);\n \n-\tsize = bp-\u003enum_queues * macb_rx_ring_size_per_queue(bp);\n-\tdma_free_coherent(dev, size, bp-\u003equeues[0].rx_ring, bp-\u003equeues[0].rx_ring_dma);\n+\tfor (q = 0; q \u003c ctx-\u003einfo-\u003enum_queues; ++q) {\n+\t\ttxq = \u0026ctx-\u003etxq[q];\n+\t\trxq = \u0026ctx-\u003erxq[q];\n \n-\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n-\t\tif (queue-\u003etx_skb) {\n+\t\tif (txq-\u003eskb) {\n \t\t\tunsigned int dropped = 0, tail;\n \n-\t\t\tfor (tail = queue-\u003etx_tail; tail != queue-\u003etx_head;\n-\t\t\t     tail++) {\n-\t\t\t\tif (macb_tx_skb(queue, tail)-\u003eskb)\n+\t\t\tfor (tail = txq-\u003etail; tail != txq-\u003ehead; tail++) {\n+\t\t\t\tif (txq-\u003eskb[macb_tx_ring_wrap(ctx, tail)].skb)\n \t\t\t\t\tdropped++;\n-\t\t\t\tmacb_tx_unmap(bp, macb_tx_skb(queue, tail), 0);\n+\t\t\t\tmacb_tx_unmap(ctx-\u003einfo,\n+\t\t\t\t\t      \u0026txq-\u003eskb[macb_tx_ring_wrap(ctx, tail)],\n+\t\t\t\t\t      0);\n \t\t\t}\n \n-\t\t\tqueue-\u003estats.tx_dropped += dropped;\n-\t\t\tbp-\u003edev-\u003estats.tx_dropped += dropped;\n+\t\t\tctx-\u003einfo-\u003equeue_stats[q]-\u003etx_dropped += dropped;\n+\t\t\tctx-\u003einfo-\u003enetdev-\u003estats.tx_dropped += dropped;\n \n-\t\t\tkfree(queue-\u003etx_skb);\n-\t\t\tqueue-\u003etx_skb = NULL;\n+\t\t\tkfree(txq-\u003eskb);\n+\t\t\ttxq-\u003eskb = NULL;\n \t\t}\n \n-\t\tqueue-\u003etx_head = 0;\n-\t\tqueue-\u003etx_tail = 0;\n-\t\tqueue-\u003etx_ring = NULL;\n-\t\tqueue-\u003erx_ring = NULL;\n+\t\ttxq-\u003ering = NULL;\n+\t\trxq-\u003ering = NULL;\n \t}\n }\n \n-static int gem_alloc_rx_buffers(struct macb *bp)\n+static int gem_alloc_rx_buffers(struct macb_context *ctx)\n {\n-\tstruct macb_queue *queue;\n+\tstruct macb_rxq *rxq;\n \tunsigned int q;\n \tint size;\n \n-\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n-\t\tsize = bp-\u003erx_ring_size * sizeof(struct sk_buff *);\n-\t\tqueue-\u003erx_skbuff = kzalloc(size, GFP_KERNEL);\n-\t\tif (!queue-\u003erx_skbuff)\n+\tfor (q = 0; q \u003c ctx-\u003einfo-\u003enum_queues; ++q) {\n+\t\trxq = \u0026ctx-\u003erxq[q];\n+\t\tsize = ctx-\u003erx_ring_size * sizeof(struct sk_buff *);\n+\t\trxq-\u003eskbuff = kzalloc(size, GFP_KERNEL);\n+\t\tif (!rxq-\u003eskbuff)\n \t\t\treturn -ENOMEM;\n \t\telse\n-\t\t\tnetdev_dbg(bp-\u003edev,\n+\t\t\tnetdev_dbg(ctx-\u003einfo-\u003enetdev,\n \t\t\t\t   \"Allocated %d RX struct sk_buff entries at %p\\n\",\n-\t\t\t\t   bp-\u003erx_ring_size, queue-\u003erx_skbuff);\n+\t\t\t\t   ctx-\u003erx_ring_size, rxq-\u003eskbuff);\n \t}\n \treturn 0;\n }\n \n-static int macb_alloc_rx_buffers(struct macb *bp)\n+static int macb_alloc_rx_buffers(struct macb_context *ctx)\n {\n-\tstruct macb_queue *queue = \u0026bp-\u003equeues[0];\n+\tstruct device *dev = \u0026ctx-\u003einfo-\u003epdev-\u003edev;\n+\tstruct macb_rxq *rxq = \u0026ctx-\u003erxq[0];\n \tint size;\n \n-\tsize = bp-\u003erx_ring_size * bp-\u003erx_buffer_size;\n-\tqueue-\u003erx_buffers = dma_alloc_coherent(\u0026bp-\u003epdev-\u003edev, size,\n-\t\t\t\t\t    \u0026queue-\u003erx_buffers_dma, GFP_KERNEL);\n-\tif (!queue-\u003erx_buffers)\n+\tsize = ctx-\u003erx_ring_size * ctx-\u003erx_buffer_size;\n+\trxq-\u003ebuffers = dma_alloc_coherent(dev, size,\n+\t\t\t\t\t  \u0026rxq-\u003ebuffers_dma, GFP_KERNEL);\n+\tif (!rxq-\u003ebuffers)\n \t\treturn -ENOMEM;\n \n-\tnetdev_dbg(bp-\u003edev,\n+\tnetdev_dbg(ctx-\u003einfo-\u003enetdev,\n \t\t   \"Allocated RX buffers of %d bytes at %08lx (mapped %p)\\n\",\n-\t\t   size, (unsigned long)queue-\u003erx_buffers_dma, queue-\u003erx_buffers);\n+\t\t   size, (unsigned long)rxq-\u003ebuffers_dma, rxq-\u003ebuffers);\n \treturn 0;\n }\n \n-static int macb_alloc_consistent(struct macb *bp)\n+static int macb_alloc(struct macb_context *ctx)\n {\n-\tstruct device *dev = \u0026bp-\u003epdev-\u003edev;\n+\tunsigned int num_queues = ctx-\u003einfo-\u003enum_queues;\n+\tstruct device *dev = \u0026ctx-\u003einfo-\u003epdev-\u003edev;\n \tdma_addr_t tx_dma, rx_dma;\n-\tstruct macb_queue *queue;\n+\tstruct macb_txq *txq;\n+\tstruct macb_rxq *rxq;\n \tunsigned int q;\n \tvoid *tx, *rx;\n \tsize_t size;\n@@ -2744,113 +2871,125 @@ static int macb_alloc_consistent(struct macb *bp)\n \t * natural alignment of physical addresses.\n \t */\n \n-\tsize = bp-\u003enum_queues * macb_tx_ring_size_per_queue(bp);\n+\tsize = num_queues * macb_tx_ring_size_per_queue(ctx);\n \ttx = dma_alloc_coherent(dev, size, \u0026tx_dma, GFP_KERNEL);\n \tif (!tx || upper_32_bits(tx_dma) != upper_32_bits(tx_dma + size - 1))\n \t\tgoto out_err;\n-\tnetdev_dbg(bp-\u003edev, \"Allocated %zu bytes for %u TX rings at %08lx (mapped %p)\\n\",\n-\t\t   size, bp-\u003enum_queues, (unsigned long)tx_dma, tx);\n+\tnetdev_dbg(ctx-\u003einfo-\u003enetdev,\n+\t\t   \"Allocated %zu bytes for %u TX rings at %08lx (mapped %p)\\n\",\n+\t\t   size, num_queues, (unsigned long)tx_dma, tx);\n \n-\tsize = bp-\u003enum_queues * macb_rx_ring_size_per_queue(bp);\n+\tsize = num_queues * macb_rx_ring_size_per_queue(ctx);\n \trx = dma_alloc_coherent(dev, size, \u0026rx_dma, GFP_KERNEL);\n \tif (!rx || upper_32_bits(rx_dma) != upper_32_bits(rx_dma + size - 1))\n \t\tgoto out_err;\n-\tnetdev_dbg(bp-\u003edev, \"Allocated %zu bytes for %u RX rings at %08lx (mapped %p)\\n\",\n-\t\t   size, bp-\u003enum_queues, (unsigned long)rx_dma, rx);\n+\tnetdev_dbg(ctx-\u003einfo-\u003enetdev,\n+\t\t   \"Allocated %zu bytes for %u RX rings at %08lx (mapped %p)\\n\",\n+\t\t   size, num_queues, (unsigned long)rx_dma, rx);\n \n-\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n-\t\tqueue-\u003etx_ring = tx + macb_tx_ring_size_per_queue(bp) * q;\n-\t\tqueue-\u003etx_ring_dma = tx_dma + macb_tx_ring_size_per_queue(bp) * q;\n+\tfor (q = 0; q \u003c num_queues; ++q) {\n+\t\ttxq = \u0026ctx-\u003etxq[q];\n+\t\trxq = \u0026ctx-\u003erxq[q];\n \n-\t\tqueue-\u003erx_ring = rx + macb_rx_ring_size_per_queue(bp) * q;\n-\t\tqueue-\u003erx_ring_dma = rx_dma + macb_rx_ring_size_per_queue(bp) * q;\n+\t\ttxq-\u003ering = tx + macb_tx_ring_size_per_queue(ctx) * q;\n+\t\ttxq-\u003ering_dma = tx_dma + macb_tx_ring_size_per_queue(ctx) * q;\n \n-\t\tsize = bp-\u003etx_ring_size * sizeof(struct macb_tx_skb);\n-\t\tqueue-\u003etx_skb = kmalloc(size, GFP_KERNEL);\n-\t\tif (!queue-\u003etx_skb)\n-\t\t\tgoto out_err;\n-\t}\n-\tif (bp-\u003emacbgem_ops.mog_alloc_rx_buffers(bp))\n-\t\tgoto out_err;\n+\t\trxq-\u003ering = rx + macb_rx_ring_size_per_queue(ctx) * q;\n+\t\trxq-\u003ering_dma = rx_dma + macb_rx_ring_size_per_queue(ctx) * q;\n \n-\t/* Required for tie off descriptor for PM cases */\n-\tif (!(bp-\u003ecaps \u0026 MACB_CAPS_QUEUE_DISABLE)) {\n-\t\tbp-\u003erx_ring_tieoff = dma_alloc_coherent(\u0026bp-\u003epdev-\u003edev,\n-\t\t\t\t\t\t\tmacb_dma_desc_get_size(bp),\n-\t\t\t\t\t\t\t\u0026bp-\u003erx_ring_tieoff_dma,\n-\t\t\t\t\t\t\tGFP_KERNEL);\n-\t\tif (!bp-\u003erx_ring_tieoff)\n+\t\tsize = ctx-\u003etx_ring_size * sizeof(struct macb_tx_skb);\n+\t\ttxq-\u003eskb = kmalloc(size, GFP_KERNEL);\n+\t\tif (!txq-\u003eskb)\n \t\t\tgoto out_err;\n \t}\n+\tif (ctx-\u003einfo-\u003emacbgem_ops.mog_alloc_rx_buffers(ctx))\n+\t\tgoto out_err;\n \n \treturn 0;\n \n out_err:\n-\tmacb_free_consistent(bp);\n+\tmacb_free(ctx);\n \treturn -ENOMEM;\n }\n \n-static void macb_init_tieoff(struct macb *bp)\n+static struct macb_context *macb_context_alloc(struct macb *bp,\n+\t\t\t\t\t       unsigned int mtu,\n+\t\t\t\t\t       unsigned int rx_ring_size,\n+\t\t\t\t\t       unsigned int tx_ring_size)\n {\n-\tstruct macb_dma_desc *desc = bp-\u003erx_ring_tieoff;\n+\tstruct macb_context *ctx;\n+\tint err;\n \n-\tif (bp-\u003ecaps \u0026 MACB_CAPS_QUEUE_DISABLE)\n-\t\treturn;\n-\t/* Setup a wrapping descriptor with no free slots\n-\t * (WRAP and USED) to tie off/disable unused RX queues.\n-\t */\n-\tmacb_set_addr(bp, desc, MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED));\n-\tdesc-\u003ectrl = 0;\n+\tctx = kzalloc_obj(*ctx);\n+\tif (!ctx)\n+\t\treturn ERR_PTR(-ENOMEM);\n+\n+\tctx-\u003einfo = \u0026bp-\u003einfo;\n+\tctx-\u003erx_buffer_size = macb_rx_buffer_size(bp, mtu);\n+\tctx-\u003erx_ring_size = rx_ring_size;\n+\tctx-\u003etx_ring_size = tx_ring_size;\n+\n+\terr = macb_alloc(ctx);\n+\tif (err) {\n+\t\tnetdev_err(bp-\u003enetdev,\n+\t\t\t   \"Unable to allocate DMA memory (error %d)\\n\", err);\n+\t\tkfree(ctx);\n+\t\treturn ERR_PTR(err);\n+\t}\n+\n+\tbp-\u003emacbgem_ops.mog_init_rings(ctx);\n+\n+\treturn ctx;\n }\n \n-static void gem_init_rx_ring(struct macb_queue *queue)\n+static void gem_init_rx_ring(struct macb_context *ctx, unsigned int q)\n {\n-\tqueue-\u003erx_tail = 0;\n-\tqueue-\u003erx_prepared_head = 0;\n+\tstruct macb_rxq *rxq = \u0026ctx-\u003erxq[q];\n \n-\tgem_rx_refill(queue);\n+\trxq-\u003etail = 0;\n+\trxq-\u003eprepared_head = 0;\n+\n+\tgem_rx_refill(ctx, q);\n }\n \n-static void gem_init_rings(struct macb *bp)\n+static void gem_init_rings(struct macb_context *ctx)\n {\n-\tstruct macb_queue *queue;\n \tstruct macb_dma_desc *desc = NULL;\n+\tstruct macb_txq *txq;\n \tunsigned int q;\n \tint i;\n \n-\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n-\t\tfor (i = 0; i \u003c bp-\u003etx_ring_size; i++) {\n-\t\t\tdesc = macb_tx_desc(queue, i);\n-\t\t\tmacb_set_addr(bp, desc, 0);\n+\tfor (q = 0; q \u003c ctx-\u003einfo-\u003enum_queues; ++q) {\n+\t\ttxq = \u0026ctx-\u003etxq[q];\n+\t\tfor (i = 0; i \u003c ctx-\u003etx_ring_size; i++) {\n+\t\t\tdesc = macb_tx_desc(ctx, q, i);\n+\t\t\tmacb_set_addr(ctx-\u003einfo, desc, 0);\n \t\t\tdesc-\u003ectrl = MACB_BIT(TX_USED);\n \t\t}\n \t\tdesc-\u003ectrl |= MACB_BIT(TX_WRAP);\n-\t\tqueue-\u003etx_head = 0;\n-\t\tqueue-\u003etx_tail = 0;\n+\t\ttxq-\u003ehead = 0;\n+\t\ttxq-\u003etail = 0;\n \n-\t\tgem_init_rx_ring(queue);\n+\t\tgem_init_rx_ring(ctx, q);\n \t}\n-\n-\tmacb_init_tieoff(bp);\n }\n \n-static void macb_init_rings(struct macb *bp)\n+static void macb_init_rings(struct macb_context *ctx)\n {\n-\tint i;\n+\tstruct macb_txq *txq = \u0026ctx-\u003etxq[0];\n \tstruct macb_dma_desc *desc = NULL;\n+\tint i;\n \n-\tmacb_init_rx_ring(\u0026bp-\u003equeues[0]);\n+\tmacb_init_rx_ring(ctx, 0);\n \n-\tfor (i = 0; i \u003c bp-\u003etx_ring_size; i++) {\n-\t\tdesc = macb_tx_desc(\u0026bp-\u003equeues[0], i);\n-\t\tmacb_set_addr(bp, desc, 0);\n+\tfor (i = 0; i \u003c ctx-\u003etx_ring_size; i++) {\n+\t\tdesc = macb_tx_desc(ctx, 0, i);\n+\t\tmacb_set_addr(ctx-\u003einfo, desc, 0);\n \t\tdesc-\u003ectrl = MACB_BIT(TX_USED);\n \t}\n-\tbp-\u003equeues[0].tx_head = 0;\n-\tbp-\u003equeues[0].tx_tail = 0;\n+\ttxq-\u003ehead = 0;\n+\ttxq-\u003etail = 0;\n \tdesc-\u003ectrl |= MACB_BIT(TX_WRAP);\n-\n-\tmacb_init_tieoff(bp);\n }\n \n static void macb_reset_hw(struct macb *bp)\n@@ -2914,7 +3053,7 @@ static u32 macb_mdc_clk_div(struct macb *bp)\n \tu32 config;\n \tunsigned long pclk_hz;\n \n-\tif (macb_is_gem(bp))\n+\tif (macb_is_gem(\u0026bp-\u003einfo))\n \t\treturn gem_mdc_clk_div(bp);\n \n \tpclk_hz = clk_get_rate(bp-\u003epclk);\n@@ -2936,7 +3075,7 @@ static u32 macb_mdc_clk_div(struct macb *bp)\n  */\n static u32 macb_dbw(struct macb *bp)\n {\n-\tif (!macb_is_gem(bp))\n+\tif (!macb_is_gem(\u0026bp-\u003einfo))\n \t\treturn 0;\n \n \tswitch (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1))) {\n@@ -2964,8 +3103,8 @@ static void macb_configure_dma(struct macb *bp)\n \tunsigned int q;\n \tu32 dmacfg;\n \n-\tbuffer_size = bp-\u003erx_buffer_size / RX_BUFFER_MULTIPLE;\n-\tif (macb_is_gem(bp)) {\n+\tbuffer_size = bp-\u003ectx-\u003erx_buffer_size / RX_BUFFER_MULTIPLE;\n+\tif (macb_is_gem(\u0026bp-\u003einfo)) {\n \t\tdmacfg = gem_readl(bp, DMACFG) \u0026 ~GEM_BF(RXBS, -1L);\n \t\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n \t\t\tif (q)\n@@ -2983,22 +3122,150 @@ static void macb_configure_dma(struct macb *bp)\n \t\telse\n \t\t\tdmacfg |= GEM_BIT(ENDIA_DESC); /* CPU in big endian */\n \n-\t\tif (bp-\u003edev-\u003efeatures \u0026 NETIF_F_HW_CSUM)\n+\t\tif (bp-\u003enetdev-\u003efeatures \u0026 NETIF_F_HW_CSUM)\n \t\t\tdmacfg |= GEM_BIT(TXCOEN);\n \t\telse\n \t\t\tdmacfg \u0026= ~GEM_BIT(TXCOEN);\n \n \t\tdmacfg \u0026= ~GEM_BIT(ADDR64);\n-\t\tif (macb_dma64(bp))\n+\t\tif (macb_dma64(\u0026bp-\u003einfo))\n \t\t\tdmacfg |= GEM_BIT(ADDR64);\n-\t\tif (macb_dma_ptp(bp))\n+\t\tif (macb_dma_ptp(\u0026bp-\u003einfo))\n \t\t\tdmacfg |= GEM_BIT(RXEXT) | GEM_BIT(TXEXT);\n-\t\tnetdev_dbg(bp-\u003edev, \"Cadence configure DMA with 0x%08x\\n\",\n+\t\tnetdev_dbg(bp-\u003enetdev, \"Cadence configure DMA with 0x%08x\\n\",\n \t\t\t   dmacfg);\n \t\tgem_writel(bp, DMACFG, dmacfg);\n \t}\n }\n \n+static void macb_context_swap_start(struct macb *bp)\n+{\n+\tstruct macb_queue *queue;\n+\tunsigned long flags;\n+\tunsigned int q;\n+\tu32 ctrl;\n+\n+\tmutex_lock(\u0026bp-\u003emac_cfg_lock);\n+\n+\t/* We cannot mask IRQs because they'll get re-armed by BH. So instead we\n+\t * signal to IRQ handler it shouldn't drive BH features and should\n+\t * self-disarm.\n+\t */\n+\tspin_lock_irqsave(\u0026bp-\u003elock, flags);\n+\tbp-\u003ectx_swap = true;\n+\tspin_unlock_irqrestore(\u0026bp-\u003elock, flags);\n+\n+\t/* Drain BH features. HW is still active and usable at this point but\n+\t * IRQs are being ignored.\n+\t */\n+\n+\tcancel_work_sync(\u0026bp-\u003ehresp_err_bh_work);\n+\n+\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n+\t\t/* Must be done before NAPI is disabled. */\n+\t\tcancel_work_sync(\u0026queue-\u003etx_error_task);\n+\n+\t\tnapi_disable(\u0026queue-\u003enapi_rx);\n+\t\tnapi_disable(\u0026queue-\u003enapi_tx);\n+\t}\n+\n+\t/* Must be done after napi_tx is disabled. */\n+\tcancel_delayed_work_sync(\u0026bp-\u003etx_lpi_work);\n+\n+\t/* Can finally disable software Tx; need to wait until napi_tx and\n+\t * tx_error_task cannot be scheduled as either might wakeup Tx.\n+\t */\n+\tnetif_tx_disable(bp-\u003enetdev);\n+\n+\t/* Now that everything is stopped, clear DQL. */\n+\tfor (q = 0; q \u003c bp-\u003enum_queues; ++q)\n+\t\tnetdev_tx_reset_queue(netdev_get_tx_queue(bp-\u003enetdev, q));\n+\n+\t/* Safe to call outside bp-\u003elock because bp-\u003ectx_swap ensures the IRQ\n+\t * handling is a no-op and all BH features are disabled.\n+\t *\n+\t * Whether it fails or not we'll disable TE/RE next.\n+\t * We were just trying to be nice.\n+\t */\n+\tmacb_halt_tx(bp);\n+\n+\tspin_lock_irqsave(\u0026bp-\u003elock, flags);\n+\n+\tctrl = macb_readl(bp, NCR);\n+\tmacb_writel(bp, NCR, ctrl \u0026 ~(MACB_BIT(RE) | MACB_BIT(TE)));\n+\n+\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n+\t\tqueue_writel(queue, IDR, -1);\n+\t\tqueue_readl(queue, ISR);\n+\t\tmacb_queue_isr_clear(bp, queue, -1);\n+\t}\n+\n+\tmacb_writel(bp, TSR, -1);\n+\tmacb_writel(bp, RSR, -1);\n+\n+\tspin_unlock_irqrestore(\u0026bp-\u003elock, flags);\n+}\n+\n+static void macb_context_swap_end(struct macb *bp,\n+\t\t\t\t  struct macb_context *new_ctx)\n+{\n+\tstruct macb_context *old_ctx;\n+\tstruct macb_queue *queue;\n+\tunsigned long flags;\n+\tunsigned int q;\n+\tu32 ctrl;\n+\n+\tlockdep_assert_held(\u0026bp-\u003emac_cfg_lock);\n+\n+\t/* Swap contexts \u0026 give buffer pointers to HW. */\n+\n+\told_ctx = bp-\u003ectx;\n+\tbp-\u003ectx = new_ctx;\n+\tmacb_init_buffers(bp);\n+\n+\t/* Start NAPI, HW Tx/Rx and software Tx. */\n+\n+\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n+\t\tnapi_enable(\u0026queue-\u003enapi_rx);\n+\t\tnapi_enable(\u0026queue-\u003enapi_tx);\n+\t}\n+\n+\tspin_lock_irqsave(\u0026bp-\u003elock, flags);\n+\n+\t/* Re-arm normal interrupt processing before enabling IRQs. */\n+\tbp-\u003ectx_swap = false;\n+\n+\tmacb_configure_dma(bp);\n+\n+\tif (bp-\u003elink_up) {\n+\t\tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n+\t\t\tqueue_writel(queue, IER,\n+\t\t\t\t     bp-\u003erx_intr_mask |\n+\t\t\t\t     MACB_TX_INT_FLAGS |\n+\t\t\t\t     MACB_BIT(HRESP));\n+\t\t}\n+\n+\t\tctrl = macb_readl(bp, NCR);\n+\t\tmacb_writel(bp, NCR, ctrl | MACB_BIT(RE) | MACB_BIT(TE));\n+\t}\n+\n+\tspin_unlock_irqrestore(\u0026bp-\u003elock, flags);\n+\n+\tif (bp-\u003elink_up) {\n+\t\tnetif_tx_wake_all_queues(bp-\u003enetdev);\n+\n+\t\tif (bp-\u003eeee_active)\n+\t\t\tmacb_txp_lpi_initial_defer(bp);\n+\t}\n+\n+\tmutex_unlock(\u0026bp-\u003emac_cfg_lock);\n+\n+\t/* Free old context. */\n+\n+\tmacb_free(old_ctx);\n+\tkfree(old_ctx);\n+}\n+\n static void macb_init_hw(struct macb *bp)\n {\n \tu32 config;\n@@ -3017,11 +3284,12 @@ static void macb_init_hw(struct macb *bp)\n \t\tconfig |= MACB_BIT(JFRAME);\t/* Enable jumbo frames */\n \telse\n \t\tconfig |= MACB_BIT(BIG);\t/* Receive oversized frames */\n-\tif (bp-\u003edev-\u003eflags \u0026 IFF_PROMISC)\n+\tif (bp-\u003enetdev-\u003eflags \u0026 IFF_PROMISC)\n \t\tconfig |= MACB_BIT(CAF);\t/* Copy All Frames */\n-\telse if (macb_is_gem(bp) \u0026\u0026 bp-\u003edev-\u003efeatures \u0026 NETIF_F_RXCSUM)\n+\telse if (macb_is_gem(\u0026bp-\u003einfo) \u0026\u0026\n+\t\t bp-\u003enetdev-\u003efeatures \u0026 NETIF_F_RXCSUM)\n \t\tconfig |= GEM_BIT(RXCOEN);\n-\tif (!(bp-\u003edev-\u003eflags \u0026 IFF_BROADCAST))\n+\tif (!(bp-\u003enetdev-\u003eflags \u0026 IFF_BROADCAST))\n \t\tconfig |= MACB_BIT(NBC);\t/* No BroadCast */\n \tconfig |= macb_dbw(bp);\n \tmacb_writel(bp, NCFGR, config);\n@@ -3095,17 +3363,17 @@ static int hash_get_index(__u8 *addr)\n }\n \n /* Add multicast addresses to the internal multicast-hash table. */\n-static void macb_sethashtable(struct net_device *dev)\n+static void macb_sethashtable(struct net_device *netdev)\n {\n \tstruct netdev_hw_addr *ha;\n \tunsigned long mc_filter[2];\n \tunsigned int bitnr;\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \tmc_filter[0] = 0;\n \tmc_filter[1] = 0;\n \n-\tnetdev_for_each_mc_addr(ha, dev) {\n+\tnetdev_for_each_mc_addr(ha, netdev) {\n \t\tbitnr = hash_get_index(ha-\u003eaddr);\n \t\tmc_filter[bitnr \u003e\u003e 5] |= 1 \u003c\u003c (bitnr \u0026 31);\n \t}\n@@ -3115,39 +3383,39 @@ static void macb_sethashtable(struct net_device *dev)\n }\n \n /* Enable/Disable promiscuous and multicast modes. */\n-static void macb_set_rx_mode(struct net_device *dev)\n+static void macb_set_rx_mode(struct net_device *netdev)\n {\n \tunsigned long cfg;\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \tcfg = macb_readl(bp, NCFGR);\n \n-\tif (dev-\u003eflags \u0026 IFF_PROMISC) {\n+\tif (netdev-\u003eflags \u0026 IFF_PROMISC) {\n \t\t/* Enable promiscuous mode */\n \t\tcfg |= MACB_BIT(CAF);\n \n \t\t/* Disable RX checksum offload */\n-\t\tif (macb_is_gem(bp))\n+\t\tif (macb_is_gem(\u0026bp-\u003einfo))\n \t\t\tcfg \u0026= ~GEM_BIT(RXCOEN);\n \t} else {\n \t\t/* Disable promiscuous mode */\n \t\tcfg \u0026= ~MACB_BIT(CAF);\n \n \t\t/* Enable RX checksum offload only if requested */\n-\t\tif (macb_is_gem(bp) \u0026\u0026 dev-\u003efeatures \u0026 NETIF_F_RXCSUM)\n+\t\tif (macb_is_gem(\u0026bp-\u003einfo) \u0026\u0026 netdev-\u003efeatures \u0026 NETIF_F_RXCSUM)\n \t\t\tcfg |= GEM_BIT(RXCOEN);\n \t}\n \n-\tif (dev-\u003eflags \u0026 IFF_ALLMULTI) {\n+\tif (netdev-\u003eflags \u0026 IFF_ALLMULTI) {\n \t\t/* Enable all multicast mode */\n \t\tmacb_or_gem_writel(bp, HRB, -1);\n \t\tmacb_or_gem_writel(bp, HRT, -1);\n \t\tcfg |= MACB_BIT(NCFGR_MTI);\n-\t} else if (!netdev_mc_empty(dev)) {\n+\t} else if (!netdev_mc_empty(netdev)) {\n \t\t/* Enable specific multicasts */\n-\t\tmacb_sethashtable(dev);\n+\t\tmacb_sethashtable(netdev);\n \t\tcfg |= MACB_BIT(NCFGR_MTI);\n-\t} else if (dev-\u003eflags \u0026 (~IFF_ALLMULTI)) {\n+\t} else if (netdev-\u003eflags \u0026 (~IFF_ALLMULTI)) {\n \t\t/* Disable all multicast mode */\n \t\tmacb_or_gem_writel(bp, HRB, 0);\n \t\tmacb_or_gem_writel(bp, HRT, 0);\n@@ -3157,31 +3425,28 @@ static void macb_set_rx_mode(struct net_device *dev)\n \tmacb_writel(bp, NCFGR, cfg);\n }\n \n-static int macb_open(struct net_device *dev)\n+static int macb_open(struct net_device *netdev)\n {\n-\tsize_t bufsz = dev-\u003emtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN;\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_queue *queue;\n \tunsigned int q;\n \tint err;\n \n-\tnetdev_dbg(bp-\u003edev, \"open\\n\");\n+\tnetdev_dbg(bp-\u003enetdev, \"open\\n\");\n \n \terr = pm_runtime_resume_and_get(\u0026bp-\u003epdev-\u003edev);\n \tif (err \u003c 0)\n \t\treturn err;\n \n-\t/* RX buffers initialization */\n-\tmacb_init_rx_buffer_size(bp, bufsz);\n-\n-\terr = macb_alloc_consistent(bp);\n-\tif (err) {\n-\t\tnetdev_err(dev, \"Unable to allocate DMA memory (error %d)\\n\",\n-\t\t\t   err);\n+\tbp-\u003ectx = macb_context_alloc(bp, netdev-\u003emtu,\n+\t\t\t\t     bp-\u003econfigured_rx_ring_size,\n+\t\t\t\t     bp-\u003econfigured_tx_ring_size);\n+\tif (IS_ERR(bp-\u003ectx)) {\n+\t\terr = PTR_ERR(bp-\u003ectx);\n+\t\tbp-\u003ectx = NULL;\n \t\tgoto pm_exit;\n \t}\n \n-\tbp-\u003emacbgem_ops.mog_init_rings(bp);\n \tmacb_init_buffers(bp);\n \n \tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n@@ -3203,10 +3468,10 @@ static int macb_open(struct net_device *dev)\n \tif (err)\n \t\tgoto phy_off;\n \n-\tnetif_tx_start_all_queues(dev);\n+\tnetif_tx_start_all_queues(netdev);\n \n \tif (bp-\u003eptp_info)\n-\t\tbp-\u003eptp_info-\u003eptp_init(dev);\n+\t\tbp-\u003eptp_info-\u003eptp_init(netdev);\n \n \treturn 0;\n \n@@ -3219,25 +3484,27 @@ static int macb_open(struct net_device *dev)\n \t\tnapi_disable(\u0026queue-\u003enapi_rx);\n \t\tnapi_disable(\u0026queue-\u003enapi_tx);\n \t}\n-\tmacb_free_consistent(bp);\n+\tmacb_free(bp-\u003ectx);\n+\tkfree(bp-\u003ectx);\n+\tbp-\u003ectx = NULL;\n pm_exit:\n \tpm_runtime_put_sync(\u0026bp-\u003epdev-\u003edev);\n \treturn err;\n }\n \n-static int macb_close(struct net_device *dev)\n+static int macb_close(struct net_device *netdev)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_queue *queue;\n \tunsigned long flags;\n \tunsigned int q;\n \n-\tnetif_tx_stop_all_queues(dev);\n+\tnetif_tx_stop_all_queues(netdev);\n \n \tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues; ++q, ++queue) {\n \t\tnapi_disable(\u0026queue-\u003enapi_rx);\n \t\tnapi_disable(\u0026queue-\u003enapi_tx);\n-\t\tnetdev_tx_reset_queue(netdev_get_tx_queue(dev, q));\n+\t\tnetdev_tx_reset_queue(netdev_get_tx_queue(netdev, q));\n \t}\n \n \tcancel_delayed_work_sync(\u0026bp-\u003etx_lpi_work);\n@@ -3249,38 +3516,58 @@ static int macb_close(struct net_device *dev)\n \n \tspin_lock_irqsave(\u0026bp-\u003elock, flags);\n \tmacb_reset_hw(bp);\n-\tnetif_carrier_off(dev);\n+\tnetif_carrier_off(netdev);\n \tspin_unlock_irqrestore(\u0026bp-\u003elock, flags);\n \n-\tmacb_free_consistent(bp);\n+\tmacb_free(bp-\u003ectx);\n+\tkfree(bp-\u003ectx);\n+\tbp-\u003ectx = NULL;\n \n \tif (bp-\u003eptp_info)\n-\t\tbp-\u003eptp_info-\u003eptp_remove(dev);\n+\t\tbp-\u003eptp_info-\u003eptp_remove(netdev);\n \n \tpm_runtime_put(\u0026bp-\u003epdev-\u003edev);\n \n \treturn 0;\n }\n \n-static int macb_change_mtu(struct net_device *dev, int new_mtu)\n+static int macb_change_mtu(struct net_device *netdev, int new_mtu)\n {\n-\tif (netif_running(dev))\n-\t\treturn -EBUSY;\n+\tstruct macb *bp = netdev_priv(netdev);\n+\tbool running = netif_running(netdev);\n+\tstruct macb_context *new_ctx;\n+\n+\tif (running) {\n+\t\t/* Context swapping is not supported for AT91. */\n+\t\tif (bp-\u003ecaps \u0026 MACB_CAPS_MACB_IS_EMAC)\n+\t\t\treturn -EBUSY;\n \n-\tWRITE_ONCE(dev-\u003emtu, new_mtu);\n+\t\tnew_ctx = macb_context_alloc(bp, new_mtu,\n+\t\t\t\t\t     bp-\u003econfigured_rx_ring_size,\n+\t\t\t\t\t     bp-\u003econfigured_tx_ring_size);\n+\t\tif (IS_ERR(new_ctx))\n+\t\t\treturn PTR_ERR(new_ctx);\n+\n+\t\tmacb_context_swap_start(bp);\n+\t}\n+\n+\tWRITE_ONCE(netdev-\u003emtu, new_mtu);\n+\n+\tif (running)\n+\t\tmacb_context_swap_end(bp, new_ctx);\n \n \treturn 0;\n }\n \n-static int macb_set_mac_addr(struct net_device *dev, void *addr)\n+static int macb_set_mac_addr(struct net_device *netdev, void *addr)\n {\n \tint err;\n \n-\terr = eth_mac_addr(dev, addr);\n+\terr = eth_mac_addr(netdev, addr);\n \tif (err \u003c 0)\n \t\treturn err;\n \n-\tmacb_set_hwaddr(netdev_priv(dev));\n+\tmacb_set_hwaddr(netdev_priv(netdev));\n \treturn 0;\n }\n \n@@ -3318,7 +3605,7 @@ static void gem_get_stats(struct macb *bp, struct rtnl_link_stats64 *nstat)\n \tstruct gem_stats *hwstat = \u0026bp-\u003ehw_stats.gem;\n \n \tspin_lock_irq(\u0026bp-\u003estats_lock);\n-\tif (netif_running(bp-\u003edev))\n+\tif (netif_running(bp-\u003enetdev))\n \t\tgem_update_stats(bp);\n \n \tnstat-\u003erx_errors = (hwstat-\u003erx_frame_check_sequence_errors +\n@@ -3351,10 +3638,10 @@ static void gem_get_stats(struct macb *bp, struct rtnl_link_stats64 *nstat)\n \tspin_unlock_irq(\u0026bp-\u003estats_lock);\n }\n \n-static void gem_get_ethtool_stats(struct net_device *dev,\n+static void gem_get_ethtool_stats(struct net_device *netdev,\n \t\t\t\t  struct ethtool_stats *stats, u64 *data)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \tspin_lock_irq(\u0026bp-\u003estats_lock);\n \tgem_update_stats(bp);\n@@ -3363,9 +3650,9 @@ static void gem_get_ethtool_stats(struct net_device *dev,\n \tspin_unlock_irq(\u0026bp-\u003estats_lock);\n }\n \n-static int gem_get_sset_count(struct net_device *dev, int sset)\n+static int gem_get_sset_count(struct net_device *netdev, int sset)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \tswitch (sset) {\n \tcase ETH_SS_STATS:\n@@ -3375,9 +3662,9 @@ static int gem_get_sset_count(struct net_device *dev, int sset)\n \t}\n }\n \n-static void gem_get_ethtool_strings(struct net_device *dev, u32 sset, u8 *p)\n+static void gem_get_ethtool_strings(struct net_device *netdev, u32 sset, u8 *p)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_queue *queue;\n \tunsigned int i;\n \tunsigned int q;\n@@ -3396,14 +3683,14 @@ static void gem_get_ethtool_strings(struct net_device *dev, u32 sset, u8 *p)\n \t}\n }\n \n-static void macb_get_stats(struct net_device *dev,\n+static void macb_get_stats(struct net_device *netdev,\n \t\t\t   struct rtnl_link_stats64 *nstat)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_stats *hwstat = \u0026bp-\u003ehw_stats.macb;\n \n-\tnetdev_stats_to_stats64(nstat, \u0026bp-\u003edev-\u003estats);\n-\tif (macb_is_gem(bp)) {\n+\tnetdev_stats_to_stats64(nstat, \u0026bp-\u003enetdev-\u003estats);\n+\tif (macb_is_gem(\u0026bp-\u003einfo)) {\n \t\tgem_get_stats(bp, nstat);\n \t\treturn;\n \t}\n@@ -3446,10 +3733,10 @@ static void macb_get_stats(struct net_device *dev,\n \tspin_unlock_irq(\u0026bp-\u003estats_lock);\n }\n \n-static void macb_get_pause_stats(struct net_device *dev,\n+static void macb_get_pause_stats(struct net_device *netdev,\n \t\t\t\t struct ethtool_pause_stats *pause_stats)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_stats *hwstat = \u0026bp-\u003ehw_stats.macb;\n \n \tspin_lock_irq(\u0026bp-\u003estats_lock);\n@@ -3459,10 +3746,10 @@ static void macb_get_pause_stats(struct net_device *dev,\n \tspin_unlock_irq(\u0026bp-\u003estats_lock);\n }\n \n-static void gem_get_pause_stats(struct net_device *dev,\n+static void gem_get_pause_stats(struct net_device *netdev,\n \t\t\t\tstruct ethtool_pause_stats *pause_stats)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct gem_stats *hwstat = \u0026bp-\u003ehw_stats.gem;\n \n \tspin_lock_irq(\u0026bp-\u003estats_lock);\n@@ -3472,10 +3759,10 @@ static void gem_get_pause_stats(struct net_device *dev,\n \tspin_unlock_irq(\u0026bp-\u003estats_lock);\n }\n \n-static void macb_get_eth_mac_stats(struct net_device *dev,\n+static void macb_get_eth_mac_stats(struct net_device *netdev,\n \t\t\t\t   struct ethtool_eth_mac_stats *mac_stats)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_stats *hwstat = \u0026bp-\u003ehw_stats.macb;\n \n \tspin_lock_irq(\u0026bp-\u003estats_lock);\n@@ -3497,10 +3784,10 @@ static void macb_get_eth_mac_stats(struct net_device *dev,\n \tspin_unlock_irq(\u0026bp-\u003estats_lock);\n }\n \n-static void gem_get_eth_mac_stats(struct net_device *dev,\n+static void gem_get_eth_mac_stats(struct net_device *netdev,\n \t\t\t\t  struct ethtool_eth_mac_stats *mac_stats)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct gem_stats *hwstat = \u0026bp-\u003ehw_stats.gem;\n \n \tspin_lock_irq(\u0026bp-\u003estats_lock);\n@@ -3530,10 +3817,10 @@ static void gem_get_eth_mac_stats(struct net_device *dev,\n }\n \n /* TODO: Report SQE test errors when added to phy_stats */\n-static void macb_get_eth_phy_stats(struct net_device *dev,\n+static void macb_get_eth_phy_stats(struct net_device *netdev,\n \t\t\t\t   struct ethtool_eth_phy_stats *phy_stats)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_stats *hwstat = \u0026bp-\u003ehw_stats.macb;\n \n \tspin_lock_irq(\u0026bp-\u003estats_lock);\n@@ -3542,10 +3829,10 @@ static void macb_get_eth_phy_stats(struct net_device *dev,\n \tspin_unlock_irq(\u0026bp-\u003estats_lock);\n }\n \n-static void gem_get_eth_phy_stats(struct net_device *dev,\n+static void gem_get_eth_phy_stats(struct net_device *netdev,\n \t\t\t\t  struct ethtool_eth_phy_stats *phy_stats)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct gem_stats *hwstat = \u0026bp-\u003ehw_stats.gem;\n \n \tspin_lock_irq(\u0026bp-\u003estats_lock);\n@@ -3554,11 +3841,11 @@ static void gem_get_eth_phy_stats(struct net_device *dev,\n \tspin_unlock_irq(\u0026bp-\u003estats_lock);\n }\n \n-static void macb_get_rmon_stats(struct net_device *dev,\n+static void macb_get_rmon_stats(struct net_device *netdev,\n \t\t\t\tstruct ethtool_rmon_stats *rmon_stats,\n \t\t\t\tconst struct ethtool_rmon_hist_range **ranges)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_stats *hwstat = \u0026bp-\u003ehw_stats.macb;\n \n \tspin_lock_irq(\u0026bp-\u003estats_lock);\n@@ -3580,11 +3867,11 @@ static const struct ethtool_rmon_hist_range gem_rmon_ranges[] = {\n \t{ },\n };\n \n-static void gem_get_rmon_stats(struct net_device *dev,\n+static void gem_get_rmon_stats(struct net_device *netdev,\n \t\t\t       struct ethtool_rmon_stats *rmon_stats,\n \t\t\t       const struct ethtool_rmon_hist_range **ranges)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct gem_stats *hwstat = \u0026bp-\u003ehw_stats.gem;\n \n \tspin_lock_irq(\u0026bp-\u003estats_lock);\n@@ -3615,18 +3902,25 @@ static int macb_get_regs_len(struct net_device *netdev)\n \treturn MACB_GREGS_NBR * sizeof(u32);\n }\n \n-static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,\n+static void macb_get_regs(struct net_device *netdev, struct ethtool_regs *regs,\n \t\t\t  void *p)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n-\tunsigned int tail, head;\n+\tdma_addr_t tx_dma_tail = 0, tx_dma_head = 0;\n+\tstruct macb *bp = netdev_priv(netdev);\n+\tunsigned int tail = 0, head = 0;\n+\tstruct macb_txq *txq;\n \tu32 *regs_buff = p;\n \n \tregs-\u003eversion = (macb_readl(bp, MID) \u0026 ((1 \u003c\u003c MACB_REV_SIZE) - 1))\n \t\t\t| MACB_GREGS_VERSION;\n \n-\ttail = macb_tx_ring_wrap(bp, bp-\u003equeues[0].tx_tail);\n-\thead = macb_tx_ring_wrap(bp, bp-\u003equeues[0].tx_head);\n+\tif (bp-\u003ectx) {\n+\t\ttxq = \u0026bp-\u003ectx-\u003etxq[0];\n+\t\ttail = macb_tx_ring_wrap(bp-\u003ectx, txq-\u003etail);\n+\t\thead = macb_tx_ring_wrap(bp-\u003ectx, txq-\u003ehead);\n+\t\ttx_dma_tail = macb_tx_dma(\u0026bp-\u003equeues[0], tail);\n+\t\ttx_dma_head = macb_tx_dma(\u0026bp-\u003equeues[0], head);\n+\t}\n \n \tregs_buff[0]  = macb_readl(bp, NCR);\n \tregs_buff[1]  = macb_or_gem_readl(bp, NCFGR);\n@@ -3639,12 +3933,12 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,\n \n \tregs_buff[8]  = tail;\n \tregs_buff[9]  = head;\n-\tregs_buff[10] = macb_tx_dma(\u0026bp-\u003equeues[0], tail);\n-\tregs_buff[11] = macb_tx_dma(\u0026bp-\u003equeues[0], head);\n+\tregs_buff[10] = tx_dma_tail;\n+\tregs_buff[11] = tx_dma_head;\n \n \tif (!(bp-\u003ecaps \u0026 MACB_CAPS_USRIO_DISABLED))\n \t\tregs_buff[12] = macb_or_gem_readl(bp, USRIO);\n-\tif (macb_is_gem(bp))\n+\tif (macb_is_gem(\u0026bp-\u003einfo))\n \t\tregs_buff[13] = gem_readl(bp, DMACFG);\n }\n \n@@ -3705,8 +3999,8 @@ static void macb_get_ringparam(struct net_device *netdev,\n \tring-\u003erx_max_pending = MAX_RX_RING_SIZE;\n \tring-\u003etx_max_pending = MAX_TX_RING_SIZE;\n \n-\tring-\u003erx_pending = bp-\u003erx_ring_size;\n-\tring-\u003etx_pending = bp-\u003etx_ring_size;\n+\tring-\u003erx_pending = bp-\u003econfigured_rx_ring_size;\n+\tring-\u003etx_pending = bp-\u003econfigured_tx_ring_size;\n }\n \n static int macb_set_ringparam(struct net_device *netdev,\n@@ -3714,9 +4008,13 @@ static int macb_set_ringparam(struct net_device *netdev,\n \t\t\t      struct kernel_ethtool_ringparam *kernel_ring,\n \t\t\t      struct netlink_ext_ack *extack)\n {\n+\tunsigned int new_rx_size, new_tx_size;\n \tstruct macb *bp = netdev_priv(netdev);\n-\tu32 new_rx_size, new_tx_size;\n-\tunsigned int reset = 0;\n+\tbool running = netif_running(netdev);\n+\tstruct macb_context *new_ctx;\n+\n+\tif (bp-\u003ecaps \u0026 MACB_CAPS_MACB_IS_EMAC)\n+\t\treturn -EOPNOTSUPP;\n \n \tif ((ring-\u003erx_mini_pending) || (ring-\u003erx_jumbo_pending))\n \t\treturn -EINVAL;\n@@ -3729,22 +4027,26 @@ static int macb_set_ringparam(struct net_device *netdev,\n \t\t\t      MIN_TX_RING_SIZE, MAX_TX_RING_SIZE);\n \tnew_tx_size = roundup_pow_of_two(new_tx_size);\n \n-\tif ((new_tx_size == bp-\u003etx_ring_size) \u0026\u0026\n-\t    (new_rx_size == bp-\u003erx_ring_size)) {\n+\tif (new_tx_size == bp-\u003econfigured_tx_ring_size \u0026\u0026\n+\t    new_rx_size == bp-\u003econfigured_rx_ring_size) {\n \t\t/* nothing to do */\n \t\treturn 0;\n \t}\n \n-\tif (netif_running(bp-\u003edev)) {\n-\t\treset = 1;\n-\t\tmacb_close(bp-\u003edev);\n+\tif (running) {\n+\t\tnew_ctx = macb_context_alloc(bp, netdev-\u003emtu,\n+\t\t\t\t\t     new_rx_size, new_tx_size);\n+\t\tif (IS_ERR(new_ctx))\n+\t\t\treturn PTR_ERR(new_ctx);\n+\n+\t\tmacb_context_swap_start(bp);\n \t}\n \n-\tbp-\u003erx_ring_size = new_rx_size;\n-\tbp-\u003etx_ring_size = new_tx_size;\n+\tbp-\u003econfigured_rx_ring_size = new_rx_size;\n+\tbp-\u003econfigured_tx_ring_size = new_tx_size;\n \n-\tif (reset)\n-\t\tmacb_open(bp-\u003edev);\n+\tif (running)\n+\t\tmacb_context_swap_end(bp, new_ctx);\n \n \treturn 0;\n }\n@@ -3771,13 +4073,13 @@ static s32 gem_get_ptp_max_adj(void)\n \treturn 64000000;\n }\n \n-static int gem_get_ts_info(struct net_device *dev,\n+static int gem_get_ts_info(struct net_device *netdev,\n \t\t\t   struct kernel_ethtool_ts_info *info)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n-\tif (!macb_dma_ptp(bp)) {\n-\t\tethtool_op_get_ts_info(dev, info);\n+\tif (!macb_dma_ptp(\u0026bp-\u003einfo)) {\n+\t\tethtool_op_get_ts_info(netdev, info);\n \t\treturn 0;\n \t}\n \n@@ -3824,7 +4126,7 @@ static int macb_get_ts_info(struct net_device *netdev,\n \n static void gem_enable_flow_filters(struct macb *bp, bool enable)\n {\n-\tstruct net_device *netdev = bp-\u003edev;\n+\tstruct net_device *netdev = bp-\u003enetdev;\n \tstruct ethtool_rx_fs_item *item;\n \tu32 t2_scr;\n \tint num_t2_scr;\n@@ -3877,7 +4179,7 @@ static void gem_prog_cmp_regs(struct macb *bp, struct ethtool_rx_flow_spec *fs)\n \tbool cmp_b = false;\n \tbool cmp_c = false;\n \n-\tif (!macb_is_gem(bp))\n+\tif (!macb_is_gem(\u0026bp-\u003einfo))\n \t\treturn;\n \n \ttp4sp_v = \u0026(fs-\u003eh_u.tcp_ip4_spec);\n@@ -4154,16 +4456,16 @@ static const struct ethtool_ops macb_ethtool_ops = {\n \t.set_ringparam\t\t= macb_set_ringparam,\n };\n \n-static int macb_get_eee(struct net_device *dev, struct ethtool_keee *eee)\n+static int macb_get_eee(struct net_device *netdev, struct ethtool_keee *eee)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \treturn phylink_ethtool_get_eee(bp-\u003ephylink, eee);\n }\n \n-static int macb_set_eee(struct net_device *dev, struct ethtool_keee *eee)\n+static int macb_set_eee(struct net_device *netdev, struct ethtool_keee *eee)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \treturn phylink_ethtool_set_eee(bp-\u003ephylink, eee);\n }\n@@ -4194,43 +4496,43 @@ static const struct ethtool_ops gem_ethtool_ops = {\n \t.set_eee\t\t= macb_set_eee,\n };\n \n-static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)\n+static int macb_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n-\tif (!netif_running(dev))\n+\tif (!netif_running(netdev))\n \t\treturn -EINVAL;\n \n \treturn phylink_mii_ioctl(bp-\u003ephylink, rq, cmd);\n }\n \n-static int macb_hwtstamp_get(struct net_device *dev,\n+static int macb_hwtstamp_get(struct net_device *netdev,\n \t\t\t     struct kernel_hwtstamp_config *cfg)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n-\tif (!netif_running(dev))\n+\tif (!netif_running(netdev))\n \t\treturn -EINVAL;\n \n \tif (!bp-\u003eptp_info)\n \t\treturn -EOPNOTSUPP;\n \n-\treturn bp-\u003eptp_info-\u003eget_hwtst(dev, cfg);\n+\treturn bp-\u003eptp_info-\u003eget_hwtst(netdev, cfg);\n }\n \n-static int macb_hwtstamp_set(struct net_device *dev,\n+static int macb_hwtstamp_set(struct net_device *netdev,\n \t\t\t     struct kernel_hwtstamp_config *cfg,\n \t\t\t     struct netlink_ext_ack *extack)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n-\tif (!netif_running(dev))\n+\tif (!netif_running(netdev))\n \t\treturn -EINVAL;\n \n \tif (!bp-\u003eptp_info)\n \t\treturn -EOPNOTSUPP;\n \n-\treturn bp-\u003eptp_info-\u003eset_hwtst(dev, cfg, extack);\n+\treturn bp-\u003eptp_info-\u003eset_hwtst(netdev, cfg, extack);\n }\n \n static inline void macb_set_txcsum_feature(struct macb *bp,\n@@ -4238,7 +4540,7 @@ static inline void macb_set_txcsum_feature(struct macb *bp,\n {\n \tu32 val;\n \n-\tif (!macb_is_gem(bp))\n+\tif (!macb_is_gem(\u0026bp-\u003einfo))\n \t\treturn;\n \n \tval = gem_readl(bp, DMACFG);\n@@ -4253,10 +4555,10 @@ static inline void macb_set_txcsum_feature(struct macb *bp,\n static inline void macb_set_rxcsum_feature(struct macb *bp,\n \t\t\t\t\t   netdev_features_t features)\n {\n-\tstruct net_device *netdev = bp-\u003edev;\n+\tstruct net_device *netdev = bp-\u003enetdev;\n \tu32 val;\n \n-\tif (!macb_is_gem(bp))\n+\tif (!macb_is_gem(\u0026bp-\u003einfo))\n \t\treturn;\n \n \tval = gem_readl(bp, NCFGR);\n@@ -4271,7 +4573,7 @@ static inline void macb_set_rxcsum_feature(struct macb *bp,\n static inline void macb_set_rxflow_feature(struct macb *bp,\n \t\t\t\t\t   netdev_features_t features)\n {\n-\tif (!macb_is_gem(bp))\n+\tif (!macb_is_gem(\u0026bp-\u003einfo))\n \t\treturn;\n \n \tgem_enable_flow_filters(bp, !!(features \u0026 NETIF_F_NTUPLE));\n@@ -4300,7 +4602,7 @@ static int macb_set_features(struct net_device *netdev,\n \n static void macb_restore_features(struct macb *bp)\n {\n-\tstruct net_device *netdev = bp-\u003edev;\n+\tstruct net_device *netdev = bp-\u003enetdev;\n \tnetdev_features_t features = netdev-\u003efeatures;\n \tstruct ethtool_rx_fs_item *item;\n \n@@ -4317,14 +4619,14 @@ static void macb_restore_features(struct macb *bp)\n \tmacb_set_rxflow_feature(bp, features);\n }\n \n-static int macb_taprio_setup_replace(struct net_device *ndev,\n+static int macb_taprio_setup_replace(struct net_device *netdev,\n \t\t\t\t     struct tc_taprio_qopt_offload *conf)\n {\n \tu64 total_on_time = 0, start_time_sec = 0, start_time = conf-\u003ebase_time;\n \tu32 configured_queues = 0, speed = 0, start_time_nsec;\n \tstruct macb_queue_enst_config *enst_queue;\n \tstruct tc_taprio_sched_entry *entry;\n-\tstruct macb *bp = netdev_priv(ndev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct ethtool_link_ksettings kset;\n \tstruct macb_queue *queue;\n \tu32 queue_mask;\n@@ -4333,13 +4635,13 @@ static int macb_taprio_setup_replace(struct net_device *ndev,\n \tint err;\n \n \tif (conf-\u003enum_entries \u003e bp-\u003enum_queues) {\n-\t\tnetdev_err(ndev, \"Too many TAPRIO entries: %zu \u003e %d queues\\n\",\n+\t\tnetdev_err(netdev, \"Too many TAPRIO entries: %zu \u003e %d queues\\n\",\n \t\t\t   conf-\u003enum_entries, bp-\u003enum_queues);\n \t\treturn -EINVAL;\n \t}\n \n \tif (conf-\u003ebase_time \u003c 0) {\n-\t\tnetdev_err(ndev, \"Invalid base_time: must be 0 or positive, got %lld\\n\",\n+\t\tnetdev_err(netdev, \"Invalid base_time: must be 0 or positive, got %lld\\n\",\n \t\t\t   conf-\u003ebase_time);\n \t\treturn -ERANGE;\n \t}\n@@ -4347,13 +4649,13 @@ static int macb_taprio_setup_replace(struct net_device *ndev,\n \t/* Get the current link speed */\n \terr = phylink_ethtool_ksettings_get(bp-\u003ephylink, \u0026kset);\n \tif (unlikely(err)) {\n-\t\tnetdev_err(ndev, \"Failed to get link settings: %d\\n\", err);\n+\t\tnetdev_err(netdev, \"Failed to get link settings: %d\\n\", err);\n \t\treturn err;\n \t}\n \n \tspeed = kset.base.speed;\n \tif (unlikely(speed \u003c= 0)) {\n-\t\tnetdev_err(ndev, \"Invalid speed: %d\\n\", speed);\n+\t\tnetdev_err(netdev, \"Invalid speed: %d\\n\", speed);\n \t\treturn -EINVAL;\n \t}\n \n@@ -4366,7 +4668,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,\n \t\tentry = \u0026conf-\u003eentries[i];\n \n \t\tif (entry-\u003ecommand != TC_TAPRIO_CMD_SET_GATES) {\n-\t\t\tnetdev_err(ndev, \"Entry %zu: unsupported command %d\\n\",\n+\t\t\tnetdev_err(netdev, \"Entry %zu: unsupported command %d\\n\",\n \t\t\t\t   i, entry-\u003ecommand);\n \t\t\terr = -EOPNOTSUPP;\n \t\t\tgoto cleanup;\n@@ -4374,7 +4676,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,\n \n \t\t/* Validate gate_mask: must be nonzero, single queue, and within range */\n \t\tif (!is_power_of_2(entry-\u003egate_mask)) {\n-\t\t\tnetdev_err(ndev, \"Entry %zu: gate_mask 0x%x is not a power of 2 (only one queue per entry allowed)\\n\",\n+\t\t\tnetdev_err(netdev, \"Entry %zu: gate_mask 0x%x is not a power of 2 (only one queue per entry allowed)\\n\",\n \t\t\t\t   i, entry-\u003egate_mask);\n \t\t\terr = -EINVAL;\n \t\t\tgoto cleanup;\n@@ -4383,7 +4685,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,\n \t\t/* gate_mask must not select queues outside the valid queues */\n \t\tqueue_id = order_base_2(entry-\u003egate_mask);\n \t\tif (queue_id \u003e= bp-\u003enum_queues) {\n-\t\t\tnetdev_err(ndev, \"Entry %zu: gate_mask 0x%x exceeds queue range (max_queues=%d)\\n\",\n+\t\t\tnetdev_err(netdev, \"Entry %zu: gate_mask 0x%x exceeds queue range (max_queues=%d)\\n\",\n \t\t\t\t   i, entry-\u003egate_mask, bp-\u003enum_queues);\n \t\t\terr = -EINVAL;\n \t\t\tgoto cleanup;\n@@ -4393,7 +4695,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,\n \t\tstart_time_sec = start_time;\n \t\tstart_time_nsec = do_div(start_time_sec, NSEC_PER_SEC);\n \t\tif (start_time_sec \u003e GENMASK(GEM_START_TIME_SEC_SIZE - 1, 0)) {\n-\t\t\tnetdev_err(ndev, \"Entry %zu: Start time %llu s exceeds hardware limit\\n\",\n+\t\t\tnetdev_err(netdev, \"Entry %zu: Start time %llu s exceeds hardware limit\\n\",\n \t\t\t\t   i, start_time_sec);\n \t\t\terr = -ERANGE;\n \t\t\tgoto cleanup;\n@@ -4401,7 +4703,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,\n \n \t\t/* Check for on time limit */\n \t\tif (entry-\u003einterval \u003e enst_max_hw_interval(speed)) {\n-\t\t\tnetdev_err(ndev, \"Entry %zu: interval %u ns exceeds hardware limit %llu ns\\n\",\n+\t\t\tnetdev_err(netdev, \"Entry %zu: interval %u ns exceeds hardware limit %llu ns\\n\",\n \t\t\t\t   i, entry-\u003einterval, enst_max_hw_interval(speed));\n \t\t\terr = -ERANGE;\n \t\t\tgoto cleanup;\n@@ -4409,7 +4711,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,\n \n \t\t/* Check for off time limit*/\n \t\tif ((conf-\u003ecycle_time - entry-\u003einterval) \u003e enst_max_hw_interval(speed)) {\n-\t\t\tnetdev_err(ndev, \"Entry %zu: off_time %llu ns exceeds hardware limit %llu ns\\n\",\n+\t\t\tnetdev_err(netdev, \"Entry %zu: off_time %llu ns exceeds hardware limit %llu ns\\n\",\n \t\t\t\t   i, conf-\u003ecycle_time - entry-\u003einterval,\n \t\t\t\t   enst_max_hw_interval(speed));\n \t\t\terr = -ERANGE;\n@@ -4432,13 +4734,13 @@ static int macb_taprio_setup_replace(struct net_device *ndev,\n \n \t/* Check total interval doesn't exceed cycle time */\n \tif (total_on_time \u003e conf-\u003ecycle_time) {\n-\t\tnetdev_err(ndev, \"Total ON %llu ns exceeds cycle time %llu ns\\n\",\n+\t\tnetdev_err(netdev, \"Total ON %llu ns exceeds cycle time %llu ns\\n\",\n \t\t\t   total_on_time, conf-\u003ecycle_time);\n \t\terr = -EINVAL;\n \t\tgoto cleanup;\n \t}\n \n-\tnetdev_dbg(ndev, \"TAPRIO setup: %zu entries, base_time=%lld ns, cycle_time=%llu ns\\n\",\n+\tnetdev_dbg(netdev, \"TAPRIO setup: %zu entries, base_time=%lld ns, cycle_time=%llu ns\\n\",\n \t\t   conf-\u003enum_entries, conf-\u003ebase_time, conf-\u003ecycle_time);\n \n \t/* All validations passed - proceed with hardware configuration */\n@@ -4463,7 +4765,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,\n \t\tgem_writel(bp, ENST_CONTROL, configured_queues);\n \t}\n \n-\tnetdev_info(ndev, \"TAPRIO configuration completed successfully: %zu entries, %d queues configured\\n\",\n+\tnetdev_info(netdev, \"TAPRIO configuration completed successfully: %zu entries, %d queues configured\\n\",\n \t\t    conf-\u003enum_entries, hweight32(configured_queues));\n \n cleanup:\n@@ -4471,14 +4773,14 @@ static int macb_taprio_setup_replace(struct net_device *ndev,\n \treturn err;\n }\n \n-static void macb_taprio_destroy(struct net_device *ndev)\n+static void macb_taprio_destroy(struct net_device *netdev)\n {\n-\tstruct macb *bp = netdev_priv(ndev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_queue *queue;\n \tu32 queue_mask;\n \tunsigned int q;\n \n-\tnetdev_reset_tc(ndev);\n+\tnetdev_reset_tc(netdev);\n \tqueue_mask = BIT_U32(bp-\u003enum_queues) - 1;\n \n \tscoped_guard(spinlock_irqsave, \u0026bp-\u003elock) {\n@@ -4493,30 +4795,30 @@ static void macb_taprio_destroy(struct net_device *ndev)\n \t\t\tqueue_writel(queue, ENST_OFF_TIME, 0);\n \t\t}\n \t}\n-\tnetdev_info(ndev, \"TAPRIO destroy: All gates disabled\\n\");\n+\tnetdev_info(netdev, \"TAPRIO destroy: All gates disabled\\n\");\n }\n \n-static int macb_setup_taprio(struct net_device *ndev,\n+static int macb_setup_taprio(struct net_device *netdev,\n \t\t\t     struct tc_taprio_qopt_offload *taprio)\n {\n-\tstruct macb *bp = netdev_priv(ndev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tint err = 0;\n \n-\tif (unlikely(!(ndev-\u003ehw_features \u0026 NETIF_F_HW_TC)))\n+\tif (unlikely(!(netdev-\u003ehw_features \u0026 NETIF_F_HW_TC)))\n \t\treturn -EOPNOTSUPP;\n \n \t/* Check if Device is in runtime suspend */\n \tif (unlikely(pm_runtime_suspended(\u0026bp-\u003epdev-\u003edev))) {\n-\t\tnetdev_err(ndev, \"Device is in runtime suspend\\n\");\n+\t\tnetdev_err(netdev, \"Device is in runtime suspend\\n\");\n \t\treturn -EOPNOTSUPP;\n \t}\n \n \tswitch (taprio-\u003ecmd) {\n \tcase TAPRIO_CMD_REPLACE:\n-\t\terr = macb_taprio_setup_replace(ndev, taprio);\n+\t\terr = macb_taprio_setup_replace(netdev, taprio);\n \t\tbreak;\n \tcase TAPRIO_CMD_DESTROY:\n-\t\tmacb_taprio_destroy(ndev);\n+\t\tmacb_taprio_destroy(netdev);\n \t\tbreak;\n \tdefault:\n \t\terr = -EOPNOTSUPP;\n@@ -4525,23 +4827,23 @@ static int macb_setup_taprio(struct net_device *ndev,\n \treturn err;\n }\n \n-static int macb_setup_tc(struct net_device *dev, enum tc_setup_type type,\n+static int macb_setup_tc(struct net_device *netdev, enum tc_setup_type type,\n \t\t\t void *type_data)\n {\n-\tif (!dev || !type_data)\n+\tif (!netdev || !type_data)\n \t\treturn -EINVAL;\n \n \tswitch (type) {\n \tcase TC_SETUP_QDISC_TAPRIO:\n-\t\treturn macb_setup_taprio(dev, type_data);\n+\t\treturn macb_setup_taprio(netdev, type_data);\n \tdefault:\n \t\treturn -EOPNOTSUPP;\n \t}\n }\n \n-static void macb_tx_timeout(struct net_device *dev, unsigned int q)\n+static void macb_tx_timeout(struct net_device *netdev, unsigned int q)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \tmacb_tx_restart(\u0026bp-\u003equeues[q]);\n }\n@@ -4598,7 +4900,7 @@ static void macb_configure_caps(struct macb *bp,\n \t\t\tbp-\u003ecaps |= MACB_CAPS_FIFO_MODE;\n \t\tif (GEM_BFEXT(PBUF_RSC, gem_readl(bp, DCFG6)))\n \t\t\tbp-\u003ecaps |= MACB_CAPS_RSC;\n-\t\tif (gem_has_ptp(bp)) {\n+\t\tif (gem_has_ptp(\u0026bp-\u003einfo)) {\n \t\t\tif (!GEM_BFEXT(TSU, gem_readl(bp, DCFG5)))\n \t\t\t\tdev_err(\u0026bp-\u003epdev-\u003edev,\n \t\t\t\t\t\"GEM doesn't support hardware ptp.\\n\");\n@@ -4749,16 +5051,13 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,\n \n static int macb_init_dflt(struct platform_device *pdev)\n {\n-\tstruct net_device *dev = platform_get_drvdata(pdev);\n+\tstruct net_device *netdev = platform_get_drvdata(pdev);\n \tunsigned int hw_q, q;\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tstruct macb_queue *queue;\n \tint err;\n \tu32 val, reg;\n \n-\tbp-\u003etx_ring_size = DEFAULT_TX_RING_SIZE;\n-\tbp-\u003erx_ring_size = DEFAULT_RX_RING_SIZE;\n-\n \t/* set the queue register mapping once for all: queue0 has a special\n \t * register mapping but we don't want to test the queue index then\n \t * compute the corresponding register offset at run time.\n@@ -4767,8 +5066,8 @@ static int macb_init_dflt(struct platform_device *pdev)\n \t\tqueue = \u0026bp-\u003equeues[q];\n \t\tqueue-\u003ebp = bp;\n \t\tspin_lock_init(\u0026queue-\u003etx_ptr_lock);\n-\t\tnetif_napi_add(dev, \u0026queue-\u003enapi_rx, macb_rx_poll);\n-\t\tnetif_napi_add_tx(dev, \u0026queue-\u003enapi_tx, macb_tx_poll);\n+\t\tnetif_napi_add(netdev, \u0026queue-\u003enapi_rx, macb_rx_poll);\n+\t\tnetif_napi_add_tx(netdev, \u0026queue-\u003enapi_tx, macb_tx_poll);\n \t\tif (hw_q) {\n \t\t\tqueue-\u003eISR  = GEM_ISR(hw_q - 1);\n \t\t\tqueue-\u003eIER  = GEM_IER(hw_q - 1);\n@@ -4798,7 +5097,7 @@ static int macb_init_dflt(struct platform_device *pdev)\n \t\t */\n \t\tqueue-\u003eirq = platform_get_irq(pdev, q);\n \t\terr = devm_request_irq(\u0026pdev-\u003edev, queue-\u003eirq, macb_interrupt,\n-\t\t\t\t       IRQF_SHARED, dev-\u003ename, queue);\n+\t\t\t\t       IRQF_SHARED, netdev-\u003ename, queue);\n \t\tif (err) {\n \t\t\tdev_err(\u0026pdev-\u003edev,\n \t\t\t\t\"Unable to request IRQ %d (error %d)\\n\",\n@@ -4810,47 +5109,47 @@ static int macb_init_dflt(struct platform_device *pdev)\n \t\tq++;\n \t}\n \n-\tdev-\u003enetdev_ops = \u0026macb_netdev_ops;\n+\tnetdev-\u003enetdev_ops = \u0026macb_netdev_ops;\n \n \t/* setup appropriated routines according to adapter type */\n-\tif (macb_is_gem(bp)) {\n+\tif (macb_is_gem(\u0026bp-\u003einfo)) {\n \t\tbp-\u003emacbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers;\n \t\tbp-\u003emacbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers;\n \t\tbp-\u003emacbgem_ops.mog_init_rings = gem_init_rings;\n \t\tbp-\u003emacbgem_ops.mog_rx = gem_rx;\n-\t\tdev-\u003eethtool_ops = \u0026gem_ethtool_ops;\n+\t\tnetdev-\u003eethtool_ops = \u0026gem_ethtool_ops;\n \t} else {\n \t\tbp-\u003emacbgem_ops.mog_alloc_rx_buffers = macb_alloc_rx_buffers;\n \t\tbp-\u003emacbgem_ops.mog_free_rx_buffers = macb_free_rx_buffers;\n \t\tbp-\u003emacbgem_ops.mog_init_rings = macb_init_rings;\n \t\tbp-\u003emacbgem_ops.mog_rx = macb_rx;\n-\t\tdev-\u003eethtool_ops = \u0026macb_ethtool_ops;\n+\t\tnetdev-\u003eethtool_ops = \u0026macb_ethtool_ops;\n \t}\n \n-\tnetdev_sw_irq_coalesce_default_on(dev);\n+\tnetdev_sw_irq_coalesce_default_on(netdev);\n \n-\tdev-\u003epriv_flags |= IFF_LIVE_ADDR_CHANGE;\n+\tnetdev-\u003epriv_flags |= IFF_LIVE_ADDR_CHANGE;\n \n \t/* Set features */\n-\tdev-\u003ehw_features = NETIF_F_SG;\n+\tnetdev-\u003ehw_features = NETIF_F_SG;\n \n \t/* Check LSO capability; runtime detection can be overridden by a cap\n \t * flag if the hardware is known to be buggy\n \t */\n \tif (!(bp-\u003ecaps \u0026 MACB_CAPS_NO_LSO) \u0026\u0026\n \t    GEM_BFEXT(PBUF_LSO, gem_readl(bp, DCFG6)))\n-\t\tdev-\u003ehw_features |= MACB_NETIF_LSO;\n+\t\tnetdev-\u003ehw_features |= MACB_NETIF_LSO;\n \n \t/* Checksum offload is only available on gem with packet buffer */\n-\tif (macb_is_gem(bp) \u0026\u0026 !(bp-\u003ecaps \u0026 MACB_CAPS_FIFO_MODE))\n-\t\tdev-\u003ehw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;\n+\tif (macb_is_gem(\u0026bp-\u003einfo) \u0026\u0026 !(bp-\u003ecaps \u0026 MACB_CAPS_FIFO_MODE))\n+\t\tnetdev-\u003ehw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;\n \tif (bp-\u003ecaps \u0026 MACB_CAPS_SG_DISABLED)\n-\t\tdev-\u003ehw_features \u0026= ~NETIF_F_SG;\n+\t\tnetdev-\u003ehw_features \u0026= ~NETIF_F_SG;\n \t/* Enable HW_TC if hardware supports QBV */\n \tif (bp-\u003ecaps \u0026 MACB_CAPS_QBV)\n-\t\tdev-\u003ehw_features |= NETIF_F_HW_TC;\n+\t\tnetdev-\u003ehw_features |= NETIF_F_HW_TC;\n \n-\tdev-\u003efeatures = dev-\u003ehw_features;\n+\tnetdev-\u003efeatures = netdev-\u003ehw_features;\n \n \t/* Check RX Flow Filters support.\n \t * Max Rx flows set by availability of screeners \u0026 compare regs:\n@@ -4868,7 +5167,7 @@ static int macb_init_dflt(struct platform_device *pdev)\n \t\t\treg = GEM_BFINS(ETHTCMP, (uint16_t)ETH_P_IP, reg);\n \t\t\tgem_writel_n(bp, ETHT, SCRT2_ETHT, reg);\n \t\t\t/* Filtering is supported in hw but don't enable it in kernel now */\n-\t\t\tdev-\u003ehw_features |= NETIF_F_NTUPLE;\n+\t\t\tnetdev-\u003ehw_features |= NETIF_F_NTUPLE;\n \t\t\t/* init Rx flow definitions */\n \t\t\tbp-\u003erx_fs_list.count = 0;\n \t\t\tspin_lock_init(\u0026bp-\u003erx_fs_lock);\n@@ -4954,79 +5253,81 @@ static const struct macb_usrio_config at91_default_usrio = {\n \t.clken = MACB_BIT(CLKEN),\n };\n \n+/* max number of receive buffers */\n+#define AT91ETHER_MAX_RX_DESCR\t9\n+\n #if defined(CONFIG_OF)\n /* 1518 rounded up */\n #define AT91ETHER_MAX_RBUFF_SZ\t0x600\n-/* max number of receive buffers */\n-#define AT91ETHER_MAX_RX_DESCR\t9\n \n static struct sifive_fu540_macb_mgmt *mgmt;\n \n-static int at91ether_alloc_coherent(struct macb *lp)\n+static int at91ether_alloc_coherent(struct macb *bp)\n {\n-\tstruct macb_queue *q = \u0026lp-\u003equeues[0];\n+\tstruct macb_rxq *rxq = \u0026bp-\u003ectx-\u003erxq[0];\n \n-\tq-\u003erx_ring = dma_alloc_coherent(\u0026lp-\u003epdev-\u003edev,\n-\t\t\t\t\t (AT91ETHER_MAX_RX_DESCR *\n-\t\t\t\t\t  macb_dma_desc_get_size(lp)),\n-\t\t\t\t\t \u0026q-\u003erx_ring_dma, GFP_KERNEL);\n-\tif (!q-\u003erx_ring)\n+\trxq-\u003ering = dma_alloc_coherent(\u0026bp-\u003epdev-\u003edev,\n+\t\t\t\t       (AT91ETHER_MAX_RX_DESCR *\n+\t\t\t\t\tmacb_dma_desc_get_size(\u0026bp-\u003einfo)),\n+\t\t\t\t       \u0026rxq-\u003ering_dma, GFP_KERNEL);\n+\tif (!rxq-\u003ering)\n \t\treturn -ENOMEM;\n \n-\tq-\u003erx_buffers = dma_alloc_coherent(\u0026lp-\u003epdev-\u003edev,\n-\t\t\t\t\t    AT91ETHER_MAX_RX_DESCR *\n-\t\t\t\t\t    AT91ETHER_MAX_RBUFF_SZ,\n-\t\t\t\t\t    \u0026q-\u003erx_buffers_dma, GFP_KERNEL);\n-\tif (!q-\u003erx_buffers) {\n-\t\tdma_free_coherent(\u0026lp-\u003epdev-\u003edev,\n+\trxq-\u003ebuffers = dma_alloc_coherent(\u0026bp-\u003epdev-\u003edev,\n+\t\t\t\t\t  AT91ETHER_MAX_RX_DESCR *\n+\t\t\t\t\t  AT91ETHER_MAX_RBUFF_SZ,\n+\t\t\t\t\t  \u0026rxq-\u003ebuffers_dma,\n+\t\t\t\t\t  GFP_KERNEL);\n+\tif (!rxq-\u003ebuffers) {\n+\t\tdma_free_coherent(\u0026bp-\u003epdev-\u003edev,\n \t\t\t\t  AT91ETHER_MAX_RX_DESCR *\n-\t\t\t\t  macb_dma_desc_get_size(lp),\n-\t\t\t\t  q-\u003erx_ring, q-\u003erx_ring_dma);\n-\t\tq-\u003erx_ring = NULL;\n+\t\t\t\t  macb_dma_desc_get_size(\u0026bp-\u003einfo),\n+\t\t\t\t  rxq-\u003ering, rxq-\u003ering_dma);\n+\t\trxq-\u003ering = NULL;\n \t\treturn -ENOMEM;\n \t}\n \n \treturn 0;\n }\n \n-static void at91ether_free_coherent(struct macb *lp)\n+static void at91ether_free_coherent(struct macb *bp)\n {\n-\tstruct macb_queue *q = \u0026lp-\u003equeues[0];\n+\tstruct macb_rxq *rxq = \u0026bp-\u003ectx-\u003erxq[0];\n \n-\tif (q-\u003erx_ring) {\n-\t\tdma_free_coherent(\u0026lp-\u003epdev-\u003edev,\n+\tif (rxq-\u003ering) {\n+\t\tdma_free_coherent(\u0026bp-\u003epdev-\u003edev,\n \t\t\t\t  AT91ETHER_MAX_RX_DESCR *\n-\t\t\t\t  macb_dma_desc_get_size(lp),\n-\t\t\t\t  q-\u003erx_ring, q-\u003erx_ring_dma);\n-\t\tq-\u003erx_ring = NULL;\n+\t\t\t\t  macb_dma_desc_get_size(\u0026bp-\u003einfo),\n+\t\t\t\t  rxq-\u003ering, rxq-\u003ering_dma);\n+\t\trxq-\u003ering = NULL;\n \t}\n \n-\tif (q-\u003erx_buffers) {\n-\t\tdma_free_coherent(\u0026lp-\u003epdev-\u003edev,\n+\tif (rxq-\u003ebuffers) {\n+\t\tdma_free_coherent(\u0026bp-\u003epdev-\u003edev,\n \t\t\t\t  AT91ETHER_MAX_RX_DESCR *\n \t\t\t\t  AT91ETHER_MAX_RBUFF_SZ,\n-\t\t\t\t  q-\u003erx_buffers, q-\u003erx_buffers_dma);\n-\t\tq-\u003erx_buffers = NULL;\n+\t\t\t\t  rxq-\u003ebuffers, rxq-\u003ebuffers_dma);\n+\t\trxq-\u003ebuffers = NULL;\n \t}\n }\n \n /* Initialize and start the Receiver and Transmit subsystems */\n-static int at91ether_start(struct macb *lp)\n+static int at91ether_start(struct macb *bp)\n {\n-\tstruct macb_queue *q = \u0026lp-\u003equeues[0];\n+\tstruct macb_rxq *rxq = \u0026bp-\u003ectx-\u003erxq[0];\n \tstruct macb_dma_desc *desc;\n \tdma_addr_t addr;\n \tu32 ctl;\n \tint i, ret;\n \n-\tret = at91ether_alloc_coherent(lp);\n+\tret = at91ether_alloc_coherent(bp);\n \tif (ret)\n \t\treturn ret;\n \n-\taddr = q-\u003erx_buffers_dma;\n+\taddr = rxq-\u003ebuffers_dma;\n \tfor (i = 0; i \u003c AT91ETHER_MAX_RX_DESCR; i++) {\n-\t\tdesc = macb_rx_desc(q, i);\n-\t\tmacb_set_addr(lp, desc, addr);\n+\t\tdesc = macb_rx_desc(bp-\u003ectx, 0, i);\n+\t\tmacb_set_addr(\u0026bp-\u003einfo, desc, addr);\n \t\tdesc-\u003ectrl = 0;\n \t\taddr += AT91ETHER_MAX_RBUFF_SZ;\n \t}\n@@ -5035,17 +5336,17 @@ static int at91ether_start(struct macb *lp)\n \tdesc-\u003eaddr |= MACB_BIT(RX_WRAP);\n \n \t/* Reset buffer index */\n-\tq-\u003erx_tail = 0;\n+\trxq-\u003etail = 0;\n \n \t/* Program address of descriptor list in Rx Buffer Queue register */\n-\tmacb_writel(lp, RBQP, q-\u003erx_ring_dma);\n+\tmacb_writel(bp, RBQP, rxq-\u003ering_dma);\n \n \t/* Enable Receive and Transmit */\n-\tctl = macb_readl(lp, NCR);\n-\tmacb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));\n+\tctl = macb_readl(bp, NCR);\n+\tmacb_writel(bp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));\n \n \t/* Enable MAC interrupts */\n-\tmacb_writel(lp, IER, MACB_BIT(RCOMP)\t|\n+\tmacb_writel(bp, IER, MACB_BIT(RCOMP)\t|\n \t\t\t     MACB_BIT(RXUBR)\t|\n \t\t\t     MACB_BIT(ISR_TUND)\t|\n \t\t\t     MACB_BIT(ISR_RLE)\t|\n@@ -5056,12 +5357,12 @@ static int at91ether_start(struct macb *lp)\n \treturn 0;\n }\n \n-static void at91ether_stop(struct macb *lp)\n+static void at91ether_stop(struct macb *bp)\n {\n \tu32 ctl;\n \n \t/* Disable MAC interrupts */\n-\tmacb_writel(lp, IDR, MACB_BIT(RCOMP)\t|\n+\tmacb_writel(bp, IDR, MACB_BIT(RCOMP)\t|\n \t\t\t     MACB_BIT(RXUBR)\t|\n \t\t\t     MACB_BIT(ISR_TUND)\t|\n \t\t\t     MACB_BIT(ISR_RLE)\t|\n@@ -5070,96 +5371,114 @@ static void at91ether_stop(struct macb *lp)\n \t\t\t     MACB_BIT(HRESP));\n \n \t/* Disable Receiver and Transmitter */\n-\tctl = macb_readl(lp, NCR);\n-\tmacb_writel(lp, NCR, ctl \u0026 ~(MACB_BIT(TE) | MACB_BIT(RE)));\n+\tctl = macb_readl(bp, NCR);\n+\tmacb_writel(bp, NCR, ctl \u0026 ~(MACB_BIT(TE) | MACB_BIT(RE)));\n+\n+\tsynchronize_irq(bp-\u003enetdev-\u003eirq);\n \n \t/* Free resources. */\n-\tat91ether_free_coherent(lp);\n+\tat91ether_free_coherent(bp);\n }\n \n /* Open the ethernet interface */\n-static int at91ether_open(struct net_device *dev)\n+static int at91ether_open(struct net_device *netdev)\n {\n-\tstruct macb *lp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tu32 ctl;\n \tint ret;\n \n-\tret = pm_runtime_resume_and_get(\u0026lp-\u003epdev-\u003edev);\n+\tret = pm_runtime_resume_and_get(\u0026bp-\u003epdev-\u003edev);\n \tif (ret \u003c 0)\n \t\treturn ret;\n \n+\tbp-\u003ectx = kzalloc_obj(*bp-\u003ectx);\n+\tif (!bp-\u003ectx) {\n+\t\tret = -ENOMEM;\n+\t\tgoto pm_exit;\n+\t}\n+\tbp-\u003ectx-\u003einfo = \u0026bp-\u003einfo;\n+\n \t/* Clear internal statistics */\n-\tctl = macb_readl(lp, NCR);\n-\tmacb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));\n+\tctl = macb_readl(bp, NCR);\n+\tmacb_writel(bp, NCR, ctl | MACB_BIT(CLRSTAT));\n \n-\tmacb_set_hwaddr(lp);\n+\tmacb_set_hwaddr(bp);\n \n-\tret = at91ether_start(lp);\n+\tret = at91ether_start(bp);\n \tif (ret)\n-\t\tgoto pm_exit;\n+\t\tgoto free_ctx;\n \n-\tret = macb_phylink_connect(lp);\n+\tret = macb_phylink_connect(bp);\n \tif (ret)\n \t\tgoto stop;\n \n-\tnetif_start_queue(dev);\n+\tnetif_start_queue(netdev);\n \n \treturn 0;\n \n stop:\n-\tat91ether_stop(lp);\n+\tat91ether_stop(bp);\n+free_ctx:\n+\tkfree(bp-\u003ectx);\n+\tbp-\u003ectx = NULL;\n pm_exit:\n-\tpm_runtime_put_sync(\u0026lp-\u003epdev-\u003edev);\n+\tpm_runtime_put_sync(\u0026bp-\u003epdev-\u003edev);\n \treturn ret;\n }\n \n /* Close the interface */\n-static int at91ether_close(struct net_device *dev)\n+static int at91ether_close(struct net_device *netdev)\n {\n-\tstruct macb *lp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n-\tnetif_stop_queue(dev);\n+\tnetif_stop_queue(netdev);\n \n-\tphylink_stop(lp-\u003ephylink);\n-\tphylink_disconnect_phy(lp-\u003ephylink);\n+\tphylink_stop(bp-\u003ephylink);\n+\tphylink_disconnect_phy(bp-\u003ephylink);\n \n-\tat91ether_stop(lp);\n+\tat91ether_stop(bp);\n \n-\tpm_runtime_put(\u0026lp-\u003epdev-\u003edev);\n+\tkfree(bp-\u003ectx);\n+\tbp-\u003ectx = NULL;\n+\n+\tpm_runtime_put(\u0026bp-\u003epdev-\u003edev);\n \n \treturn 0;\n }\n \n /* Transmit packet */\n static netdev_tx_t at91ether_start_xmit(struct sk_buff *skb,\n-\t\t\t\t\tstruct net_device *dev)\n+\t\t\t\t\tstruct net_device *netdev)\n {\n-\tstruct macb *lp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n+\tstruct device *dev = \u0026bp-\u003epdev-\u003edev;\n \n-\tif (macb_readl(lp, TSR) \u0026 MACB_BIT(RM9200_BNQ)) {\n+\tif (macb_readl(bp, TSR) \u0026 MACB_BIT(RM9200_BNQ)) {\n \t\tint desc = 0;\n \n-\t\tnetif_stop_queue(dev);\n+\t\tnetif_stop_queue(netdev);\n \n \t\t/* Store packet information (to free when Tx completed) */\n-\t\tlp-\u003erm9200_txq[desc].skb = skb;\n-\t\tlp-\u003erm9200_txq[desc].size = skb-\u003elen;\n-\t\tlp-\u003erm9200_txq[desc].mapping = dma_map_single(\u0026lp-\u003epdev-\u003edev, skb-\u003edata,\n-\t\t\t\t\t\t\t      skb-\u003elen, DMA_TO_DEVICE);\n-\t\tif (dma_mapping_error(\u0026lp-\u003epdev-\u003edev, lp-\u003erm9200_txq[desc].mapping)) {\n+\t\tbp-\u003erm9200_txq[desc].skb = skb;\n+\t\tbp-\u003erm9200_txq[desc].size = skb-\u003elen;\n+\t\tbp-\u003erm9200_txq[desc].mapping = dma_map_single(dev, skb-\u003edata,\n+\t\t\t\t\t\t\t      skb-\u003elen,\n+\t\t\t\t\t\t\t      DMA_TO_DEVICE);\n+\t\tif (dma_mapping_error(dev, bp-\u003erm9200_txq[desc].mapping)) {\n \t\t\tdev_kfree_skb_any(skb);\n-\t\t\tdev-\u003estats.tx_dropped++;\n-\t\t\tnetdev_err(dev, \"%s: DMA mapping error\\n\", __func__);\n+\t\t\tnetdev-\u003estats.tx_dropped++;\n+\t\t\tnetdev_err(netdev, \"%s: DMA mapping error\\n\", __func__);\n \t\t\treturn NETDEV_TX_OK;\n \t\t}\n \n \t\t/* Set address of the data in the Transmit Address register */\n-\t\tmacb_writel(lp, TAR, lp-\u003erm9200_txq[desc].mapping);\n+\t\tmacb_writel(bp, TAR, bp-\u003erm9200_txq[desc].mapping);\n \t\t/* Set length of the packet in the Transmit Control register */\n-\t\tmacb_writel(lp, TCR, skb-\u003elen);\n+\t\tmacb_writel(bp, TCR, skb-\u003elen);\n \n \t} else {\n-\t\tnetdev_err(dev, \"%s called, but device is busy!\\n\", __func__);\n+\t\tnetdev_err(netdev, \"%s called, but device is busy!\\n\",\n+\t\t\t   __func__);\n \t\treturn NETDEV_TX_BUSY;\n \t}\n \n@@ -5169,104 +5488,106 @@ static netdev_tx_t at91ether_start_xmit(struct sk_buff *skb,\n /* Extract received frame from buffer descriptors and sent to upper layers.\n  * (Called from interrupt context)\n  */\n-static void at91ether_rx(struct net_device *dev)\n+static void at91ether_rx(struct net_device *netdev)\n {\n-\tstruct macb *lp = netdev_priv(dev);\n-\tstruct macb_queue *q = \u0026lp-\u003equeues[0];\n+\tstruct macb *bp = netdev_priv(netdev);\n+\tstruct macb_rxq *rxq = \u0026bp-\u003ectx-\u003erxq[0];\n \tstruct macb_dma_desc *desc;\n \tunsigned char *p_recv;\n \tstruct sk_buff *skb;\n \tunsigned int pktlen;\n \n-\tdesc = macb_rx_desc(q, q-\u003erx_tail);\n+\tdesc = macb_rx_desc(bp-\u003ectx, 0, rxq-\u003etail);\n \twhile (desc-\u003eaddr \u0026 MACB_BIT(RX_USED)) {\n-\t\tp_recv = q-\u003erx_buffers + q-\u003erx_tail * AT91ETHER_MAX_RBUFF_SZ;\n+\t\tp_recv = rxq-\u003ebuffers + rxq-\u003etail * AT91ETHER_MAX_RBUFF_SZ;\n \t\tpktlen = MACB_BF(RX_FRMLEN, desc-\u003ectrl);\n-\t\tskb = netdev_alloc_skb(dev, pktlen + 2);\n+\t\tskb = netdev_alloc_skb(netdev, pktlen + 2);\n \t\tif (skb) {\n \t\t\tskb_reserve(skb, 2);\n \t\t\tskb_put_data(skb, p_recv, pktlen);\n \n-\t\t\tskb-\u003eprotocol = eth_type_trans(skb, dev);\n-\t\t\tdev-\u003estats.rx_packets++;\n-\t\t\tdev-\u003estats.rx_bytes += pktlen;\n+\t\t\tskb-\u003eprotocol = eth_type_trans(skb, netdev);\n+\t\t\tnetdev-\u003estats.rx_packets++;\n+\t\t\tnetdev-\u003estats.rx_bytes += pktlen;\n \t\t\tnetif_rx(skb);\n \t\t} else {\n-\t\t\tdev-\u003estats.rx_dropped++;\n+\t\t\tnetdev-\u003estats.rx_dropped++;\n \t\t}\n \n \t\tif (desc-\u003ectrl \u0026 MACB_BIT(RX_MHASH_MATCH))\n-\t\t\tdev-\u003estats.multicast++;\n+\t\t\tnetdev-\u003estats.multicast++;\n \n \t\t/* reset ownership bit */\n \t\tdesc-\u003eaddr \u0026= ~MACB_BIT(RX_USED);\n \n \t\t/* wrap after last buffer */\n-\t\tif (q-\u003erx_tail == AT91ETHER_MAX_RX_DESCR - 1)\n-\t\t\tq-\u003erx_tail = 0;\n+\t\tif (rxq-\u003etail == AT91ETHER_MAX_RX_DESCR - 1)\n+\t\t\trxq-\u003etail = 0;\n \t\telse\n-\t\t\tq-\u003erx_tail++;\n+\t\t\trxq-\u003etail++;\n \n-\t\tdesc = macb_rx_desc(q, q-\u003erx_tail);\n+\t\tdesc = macb_rx_desc(bp-\u003ectx, 0, rxq-\u003etail);\n \t}\n }\n \n /* MAC interrupt handler */\n static irqreturn_t at91ether_interrupt(int irq, void *dev_id)\n {\n-\tstruct net_device *dev = dev_id;\n-\tstruct macb *lp = netdev_priv(dev);\n+\tstruct net_device *netdev = dev_id;\n+\tstruct macb *bp = netdev_priv(netdev);\n \tu32 intstatus, ctl;\n \tunsigned int desc;\n \n \t/* MAC Interrupt Status register indicates what interrupts are pending.\n \t * It is automatically cleared once read.\n \t */\n-\tintstatus = macb_readl(lp, ISR);\n+\tintstatus = macb_readl(bp, ISR);\n \n \t/* Receive complete */\n \tif (intstatus \u0026 MACB_BIT(RCOMP))\n-\t\tat91ether_rx(dev);\n+\t\tat91ether_rx(netdev);\n \n \t/* Transmit complete */\n \tif (intstatus \u0026 MACB_BIT(TCOMP)) {\n \t\t/* The TCOM bit is set even if the transmission failed */\n \t\tif (intstatus \u0026 (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE)))\n-\t\t\tdev-\u003estats.tx_errors++;\n+\t\t\tnetdev-\u003estats.tx_errors++;\n \n \t\tdesc = 0;\n-\t\tif (lp-\u003erm9200_txq[desc].skb) {\n-\t\t\tdev_consume_skb_irq(lp-\u003erm9200_txq[desc].skb);\n-\t\t\tlp-\u003erm9200_txq[desc].skb = NULL;\n-\t\t\tdma_unmap_single(\u0026lp-\u003epdev-\u003edev, lp-\u003erm9200_txq[desc].mapping,\n-\t\t\t\t\t lp-\u003erm9200_txq[desc].size, DMA_TO_DEVICE);\n-\t\t\tdev-\u003estats.tx_packets++;\n-\t\t\tdev-\u003estats.tx_bytes += lp-\u003erm9200_txq[desc].size;\n+\t\tif (bp-\u003erm9200_txq[desc].skb) {\n+\t\t\tdev_consume_skb_irq(bp-\u003erm9200_txq[desc].skb);\n+\t\t\tbp-\u003erm9200_txq[desc].skb = NULL;\n+\t\t\tdma_unmap_single(\u0026bp-\u003epdev-\u003edev,\n+\t\t\t\t\t bp-\u003erm9200_txq[desc].mapping,\n+\t\t\t\t\t bp-\u003erm9200_txq[desc].size,\n+\t\t\t\t\t DMA_TO_DEVICE);\n+\t\t\tnetdev-\u003estats.tx_packets++;\n+\t\t\tnetdev-\u003estats.tx_bytes += bp-\u003erm9200_txq[desc].size;\n \t\t}\n-\t\tnetif_wake_queue(dev);\n+\t\tnetif_wake_queue(netdev);\n \t}\n \n \t/* Work-around for EMAC Errata section 41.3.1 */\n \tif (intstatus \u0026 MACB_BIT(RXUBR)) {\n-\t\tctl = macb_readl(lp, NCR);\n-\t\tmacb_writel(lp, NCR, ctl \u0026 ~MACB_BIT(RE));\n+\t\tctl = macb_readl(bp, NCR);\n+\t\tmacb_writel(bp, NCR, ctl \u0026 ~MACB_BIT(RE));\n \t\twmb();\n-\t\tmacb_writel(lp, NCR, ctl | MACB_BIT(RE));\n+\t\tmacb_writel(bp, NCR, ctl | MACB_BIT(RE));\n \t}\n \n \tif (intstatus \u0026 MACB_BIT(ISR_ROVR))\n-\t\tnetdev_err(dev, \"ROVR error\\n\");\n+\t\tnetdev_err(netdev, \"ROVR error\\n\");\n \n \treturn IRQ_HANDLED;\n }\n \n #ifdef CONFIG_NET_POLL_CONTROLLER\n-static void at91ether_poll_controller(struct net_device *dev)\n+static void at91ether_poll_controller(struct net_device *netdev)\n {\n \tunsigned long flags;\n \n \tlocal_irq_save(flags);\n-\tat91ether_interrupt(dev-\u003eirq, dev);\n+\tat91ether_interrupt(netdev-\u003eirq, netdev);\n \tlocal_irq_restore(flags);\n }\n #endif\n@@ -5313,17 +5634,17 @@ static int at91ether_clk_init(struct platform_device *pdev, struct clk **pclk,\n \n static int at91ether_init(struct platform_device *pdev)\n {\n-\tstruct net_device *dev = platform_get_drvdata(pdev);\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct net_device *netdev = platform_get_drvdata(pdev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tint err;\n \n \tbp-\u003equeues[0].bp = bp;\n \n-\tdev-\u003enetdev_ops = \u0026at91ether_netdev_ops;\n-\tdev-\u003eethtool_ops = \u0026macb_ethtool_ops;\n+\tnetdev-\u003enetdev_ops = \u0026at91ether_netdev_ops;\n+\tnetdev-\u003eethtool_ops = \u0026macb_ethtool_ops;\n \n-\terr = devm_request_irq(\u0026pdev-\u003edev, dev-\u003eirq, at91ether_interrupt,\n-\t\t\t       0, dev-\u003ename, dev);\n+\terr = devm_request_irq(\u0026pdev-\u003edev, netdev-\u003eirq, at91ether_interrupt,\n+\t\t\t       0, netdev-\u003ename, netdev);\n \tif (err)\n \t\treturn err;\n \n@@ -5452,8 +5773,8 @@ static int fu540_c000_init(struct platform_device *pdev)\n \n static int init_reset_optional(struct platform_device *pdev)\n {\n-\tstruct net_device *dev = platform_get_drvdata(pdev);\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct net_device *netdev = platform_get_drvdata(pdev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tint ret;\n \n \tif (bp-\u003ephy_interface == PHY_INTERFACE_MODE_SGMII) {\n@@ -5528,6 +5849,38 @@ static int eyeq5_init(struct platform_device *pdev)\n \treturn ret;\n }\n \n+static int macb_alloc_tieoff(struct macb *bp)\n+{\n+\t/* Tieoff is a workaround in case HW cannot disable queues, for PM. */\n+\tif (bp-\u003ecaps \u0026 MACB_CAPS_QUEUE_DISABLE)\n+\t\treturn 0;\n+\n+\tbp-\u003erx_ring_tieoff = dma_alloc_coherent(\u0026bp-\u003epdev-\u003edev,\n+\t\t\t\t\t\tmacb_dma_desc_get_size(\u0026bp-\u003einfo),\n+\t\t\t\t\t\t\u0026bp-\u003erx_ring_tieoff_dma,\n+\t\t\t\t\t\tGFP_KERNEL);\n+\tif (!bp-\u003erx_ring_tieoff)\n+\t\treturn -ENOMEM;\n+\n+\tmacb_set_addr(\u0026bp-\u003einfo, bp-\u003erx_ring_tieoff,\n+\t\t      MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED));\n+\n+\tbp-\u003erx_ring_tieoff-\u003ectrl = 0;\n+\n+\treturn 0;\n+}\n+\n+static void macb_free_tieoff(struct macb *bp)\n+{\n+\tif (!bp-\u003erx_ring_tieoff)\n+\t\treturn;\n+\n+\tdma_free_coherent(\u0026bp-\u003epdev-\u003edev, macb_dma_desc_get_size(\u0026bp-\u003einfo),\n+\t\t\t  bp-\u003erx_ring_tieoff,\n+\t\t\t  bp-\u003erx_ring_tieoff_dma);\n+\tbp-\u003erx_ring_tieoff = NULL;\n+}\n+\n static const struct macb_usrio_config mpfs_usrio = {\n \t.tsu_source = 0,\n };\n@@ -5761,11 +6114,12 @@ static int macb_probe(struct platform_device *pdev)\n \tconst struct macb_config *macb_config;\n \tstruct clk *tsu_clk = NULL;\n \tphy_interface_t interface;\n-\tstruct net_device *dev;\n+\tstruct net_device *netdev;\n \tstruct resource *regs;\n \tu32 wtrmrk_rst_val;\n \tvoid __iomem *mem;\n \tstruct macb *bp;\n+\tunsigned int q;\n \tint num_queues;\n \tbool native_io;\n \tint err, val;\n@@ -5796,21 +6150,23 @@ static int macb_probe(struct platform_device *pdev)\n \t\tgoto err_disable_clocks;\n \t}\n \n-\tdev = alloc_etherdev_mq(sizeof(*bp), num_queues);\n-\tif (!dev) {\n+\tnetdev = alloc_etherdev_mq(sizeof(*bp), num_queues);\n+\tif (!netdev) {\n \t\terr = -ENOMEM;\n \t\tgoto err_disable_clocks;\n \t}\n \n-\tdev-\u003ebase_addr = regs-\u003estart;\n+\tnetdev-\u003ebase_addr = regs-\u003estart;\n \n-\tSET_NETDEV_DEV(dev, \u0026pdev-\u003edev);\n+\tSET_NETDEV_DEV(netdev, \u0026pdev-\u003edev);\n \n-\tbp = netdev_priv(dev);\n+\tbp = netdev_priv(netdev);\n \tbp-\u003epdev = pdev;\n-\tbp-\u003edev = dev;\n+\tbp-\u003enetdev = netdev;\n \tbp-\u003eregs = mem;\n \tbp-\u003enative_io = native_io;\n+\tfor (q = 0; q \u003c MACB_MAX_QUEUES; q++)\n+\t\tbp-\u003einfo.queue_stats[q] = \u0026bp-\u003equeues[q].stats;\n \tif (native_io) {\n \t\tbp-\u003emacb_reg_readl = hw_readl_native;\n \t\tbp-\u003emacb_reg_writel = hw_writel_native;\n@@ -5867,10 +6223,20 @@ static int macb_probe(struct platform_device *pdev)\n \t}\n \tspin_lock_init(\u0026bp-\u003elock);\n \tspin_lock_init(\u0026bp-\u003estats_lock);\n+\tmutex_init(\u0026bp-\u003emac_cfg_lock);\n \n \t/* setup capabilities */\n \tmacb_configure_caps(bp, macb_config);\n \n+\tif (bp-\u003ecaps \u0026 MACB_CAPS_MACB_IS_EMAC) {\n+\t\t/* The name is lying on EMAC: sizes aren't configurable. */\n+\t\tbp-\u003econfigured_rx_ring_size = AT91ETHER_MAX_RX_DESCR;\n+\t\tbp-\u003econfigured_tx_ring_size = 1; /* tiny ring buffer */\n+\t} else {\n+\t\tbp-\u003econfigured_rx_ring_size = DEFAULT_RX_RING_SIZE;\n+\t\tbp-\u003econfigured_tx_ring_size = DEFAULT_TX_RING_SIZE;\n+\t}\n+\n #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT\n \tif (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {\n \t\terr = dma_set_mask_and_coherent(\u0026pdev-\u003edev, DMA_BIT_MASK(44));\n@@ -5881,39 +6247,39 @@ static int macb_probe(struct platform_device *pdev)\n \t\tbp-\u003ecaps |= MACB_CAPS_DMA_64B;\n \t}\n #endif\n-\tplatform_set_drvdata(pdev, dev);\n+\tplatform_set_drvdata(pdev, netdev);\n \n-\tdev-\u003eirq = platform_get_irq(pdev, 0);\n-\tif (dev-\u003eirq \u003c 0) {\n-\t\terr = dev-\u003eirq;\n+\tnetdev-\u003eirq = platform_get_irq(pdev, 0);\n+\tif (netdev-\u003eirq \u003c 0) {\n+\t\terr = netdev-\u003eirq;\n \t\tgoto err_out_free_netdev;\n \t}\n \n \t/* MTU range: 68 - 1518 or 10240 */\n-\tdev-\u003emin_mtu = GEM_MTU_MIN_SIZE;\n+\tnetdev-\u003emin_mtu = GEM_MTU_MIN_SIZE;\n \tif ((bp-\u003ecaps \u0026 MACB_CAPS_JUMBO) \u0026\u0026 bp-\u003ejumbo_max_len)\n-\t\tdev-\u003emax_mtu = MIN(bp-\u003ejumbo_max_len, RX_BUFFER_MAX) -\n+\t\tnetdev-\u003emax_mtu = MIN(bp-\u003ejumbo_max_len, RX_BUFFER_MAX) -\n \t\t\t\tETH_HLEN - ETH_FCS_LEN;\n \telse\n-\t\tdev-\u003emax_mtu = 1536 - ETH_HLEN - ETH_FCS_LEN;\n+\t\tnetdev-\u003emax_mtu = 1536 - ETH_HLEN - ETH_FCS_LEN;\n \n \tif (bp-\u003ecaps \u0026 MACB_CAPS_BD_RD_PREFETCH) {\n \t\tval = GEM_BFEXT(RXBD_RDBUFF, gem_readl(bp, DCFG10));\n \t\tif (val)\n \t\t\tbp-\u003erx_bd_rd_prefetch = (2 \u003c\u003c (val - 1)) *\n-\t\t\t\t\t\tmacb_dma_desc_get_size(bp);\n+\t\t\t\t\t\tmacb_dma_desc_get_size(\u0026bp-\u003einfo);\n \n \t\tval = GEM_BFEXT(TXBD_RDBUFF, gem_readl(bp, DCFG10));\n \t\tif (val)\n \t\t\tbp-\u003etx_bd_rd_prefetch = (2 \u003c\u003c (val - 1)) *\n-\t\t\t\t\t\tmacb_dma_desc_get_size(bp);\n+\t\t\t\t\t\tmacb_dma_desc_get_size(\u0026bp-\u003einfo);\n \t}\n \n \tbp-\u003erx_intr_mask = MACB_RX_INT_FLAGS;\n \tif (bp-\u003ecaps \u0026 MACB_CAPS_NEEDS_RSTONUBR)\n \t\tbp-\u003erx_intr_mask |= MACB_BIT(RXUBR);\n \n-\terr = of_get_ethdev_address(np, bp-\u003edev);\n+\terr = of_get_ethdev_address(np, bp-\u003enetdev);\n \tif (err == -EPROBE_DEFER)\n \t\tgoto err_out_free_netdev;\n \telse if (err)\n@@ -5935,25 +6301,33 @@ static int macb_probe(struct platform_device *pdev)\n \tif (err)\n \t\tgoto err_out_phy_exit;\n \n-\tnetif_carrier_off(dev);\n+\tnetif_carrier_off(netdev);\n \n-\terr = register_netdev(dev);\n+\terr = macb_alloc_tieoff(bp);\n+\tif (err)\n+\t\tgoto err_out_unregister_mdio;\n+\n+\terr = register_netdev(netdev);\n \tif (err) {\n \t\tdev_err(\u0026pdev-\u003edev, \"Cannot register net device, aborting.\\n\");\n-\t\tgoto err_out_unregister_mdio;\n+\t\tgoto err_out_free_tieoff;\n \t}\n \n \tINIT_WORK(\u0026bp-\u003ehresp_err_bh_work, macb_hresp_error_task);\n \tINIT_DELAYED_WORK(\u0026bp-\u003etx_lpi_work, macb_tx_lpi_work_fn);\n \n-\tnetdev_info(dev, \"Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\\n\",\n-\t\t    macb_is_gem(bp) ? \"GEM\" : \"MACB\", macb_readl(bp, MID),\n-\t\t    dev-\u003ebase_addr, dev-\u003eirq, dev-\u003edev_addr);\n+\tnetdev_info(netdev, \"Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\\n\",\n+\t\t    macb_is_gem(\u0026bp-\u003einfo) ? \"GEM\" : \"MACB\",\n+\t\t    macb_readl(bp, MID), netdev-\u003ebase_addr, netdev-\u003eirq,\n+\t\t    netdev-\u003edev_addr);\n \n \tpm_runtime_put_autosuspend(\u0026bp-\u003epdev-\u003edev);\n \n \treturn 0;\n \n+err_out_free_tieoff:\n+\tmacb_free_tieoff(bp);\n+\n err_out_unregister_mdio:\n \tmdiobus_unregister(bp-\u003emii_bus);\n \tmdiobus_free(bp-\u003emii_bus);\n@@ -5962,7 +6336,7 @@ static int macb_probe(struct platform_device *pdev)\n \tphy_exit(bp-\u003ephy);\n \n err_out_free_netdev:\n-\tfree_netdev(dev);\n+\tfree_netdev(netdev);\n \n err_disable_clocks:\n \tmacb_clks_disable(pclk, hclk, tx_clk, rx_clk, tsu_clk);\n@@ -5975,14 +6349,15 @@ static int macb_probe(struct platform_device *pdev)\n \n static void macb_remove(struct platform_device *pdev)\n {\n-\tstruct net_device *dev;\n+\tstruct net_device *netdev;\n \tstruct macb *bp;\n \n-\tdev = platform_get_drvdata(pdev);\n+\tnetdev = platform_get_drvdata(pdev);\n \n-\tif (dev) {\n-\t\tbp = netdev_priv(dev);\n-\t\tunregister_netdev(dev);\n+\tif (netdev) {\n+\t\tbp = netdev_priv(netdev);\n+\t\tunregister_netdev(netdev);\n+\t\tmacb_free_tieoff(bp);\n \t\tphy_exit(bp-\u003ephy);\n \t\tmdiobus_unregister(bp-\u003emii_bus);\n \t\tmdiobus_free(bp-\u003emii_bus);\n@@ -5994,7 +6369,7 @@ static void macb_remove(struct platform_device *pdev)\n \t\tpm_runtime_dont_use_autosuspend(\u0026pdev-\u003edev);\n \t\tpm_runtime_set_suspended(\u0026pdev-\u003edev);\n \t\tphylink_destroy(bp-\u003ephylink);\n-\t\tfree_netdev(dev);\n+\t\tfree_netdev(netdev);\n \t}\n }\n \n@@ -6009,7 +6384,7 @@ static int __maybe_unused macb_suspend(struct device *dev)\n \tu32 tmp, ifa_local;\n \tunsigned int q;\n \n-\tif (!device_may_wakeup(\u0026bp-\u003edev-\u003edev))\n+\tif (!device_may_wakeup(\u0026bp-\u003enetdev-\u003edev))\n \t\tphy_exit(bp-\u003ephy);\n \n \tif (!netif_running(netdev))\n@@ -6019,7 +6394,7 @@ static int __maybe_unused macb_suspend(struct device *dev)\n \t\tif (bp-\u003ewolopts \u0026 WAKE_ARP) {\n \t\t\t/* Check for IP address in WOL ARP mode */\n \t\t\trcu_read_lock();\n-\t\t\tidev = __in_dev_get_rcu(bp-\u003edev);\n+\t\t\tidev = __in_dev_get_rcu(bp-\u003enetdev);\n \t\t\tif (idev)\n \t\t\t\tifa = rcu_dereference(idev-\u003eifa_list);\n \t\t\tif (!ifa) {\n@@ -6071,7 +6446,7 @@ static int __maybe_unused macb_suspend(struct device *dev)\n \t\t\ttmp |= MACB_BFEXT(IP, ifa_local);\n \t\t}\n \n-\t\tif (macb_is_gem(bp)) {\n+\t\tif (macb_is_gem(\u0026bp-\u003einfo)) {\n \t\t\tqueue_writel(bp-\u003equeues, IER, GEM_BIT(WOL));\n \t\t\tgem_writel(bp, WOL, tmp);\n \t\t} else {\n@@ -6117,11 +6492,12 @@ static int __maybe_unused macb_resume(struct device *dev)\n {\n \tstruct net_device *netdev = dev_get_drvdata(dev);\n \tstruct macb *bp = netdev_priv(netdev);\n+\tstruct macb_context *ctx = bp-\u003ectx;\n \tstruct macb_queue *queue;\n \tunsigned long flags;\n \tunsigned int q;\n \n-\tif (!device_may_wakeup(\u0026bp-\u003edev-\u003edev))\n+\tif (!device_may_wakeup(\u0026bp-\u003enetdev-\u003edev))\n \t\tphy_init(bp-\u003ephy);\n \n \tif (!netif_running(netdev))\n@@ -6133,7 +6509,7 @@ static int __maybe_unused macb_resume(struct device *dev)\n \tif (bp-\u003ewol \u0026 MACB_WOL_ENABLED) {\n \t\tspin_lock_irqsave(\u0026bp-\u003elock, flags);\n \t\t/* Disable WoL */\n-\t\tif (macb_is_gem(bp)) {\n+\t\tif (macb_is_gem(\u0026bp-\u003einfo)) {\n \t\t\tqueue_writel(bp-\u003equeues, IDR, GEM_BIT(WOL));\n \t\t\tgem_writel(bp, WOL, 0);\n \t\t} else {\n@@ -6161,10 +6537,10 @@ static int __maybe_unused macb_resume(struct device *dev)\n \tfor (q = 0, queue = bp-\u003equeues; q \u003c bp-\u003enum_queues;\n \t     ++q, ++queue) {\n \t\tif (!(bp-\u003ecaps \u0026 MACB_CAPS_MACB_IS_EMAC)) {\n-\t\t\tif (macb_is_gem(bp))\n-\t\t\t\tgem_init_rx_ring(queue);\n+\t\t\tif (macb_is_gem(\u0026bp-\u003einfo))\n+\t\t\t\tgem_init_rx_ring(ctx, q);\n \t\t\telse\n-\t\t\t\tmacb_init_rx_ring(queue);\n+\t\t\t\tmacb_init_rx_ring(ctx, q);\n \t\t}\n \n \t\tnapi_enable(\u0026queue-\u003enapi_rx);\ndiff --git a/drivers/net/ethernet/cadence/macb_pci.c b/drivers/net/ethernet/cadence/macb_pci.c\nindex b79dec17e6b09..ac009007118f3 100644\n--- a/drivers/net/ethernet/cadence/macb_pci.c\n+++ b/drivers/net/ethernet/cadence/macb_pci.c\n@@ -24,48 +24,48 @@\n #define GEM_PCLK_RATE 50000000\n #define GEM_HCLK_RATE 50000000\n \n-static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n+static int macb_probe(struct pci_dev *pci, const struct pci_device_id *id)\n {\n \tint err;\n-\tstruct platform_device *plat_dev;\n+\tstruct platform_device *pdev;\n \tstruct platform_device_info plat_info;\n \tstruct macb_platform_data plat_data;\n \tstruct resource res[2];\n \n \t/* enable pci device */\n-\terr = pcim_enable_device(pdev);\n+\terr = pcim_enable_device(pci);\n \tif (err \u003c 0) {\n-\t\tdev_err(\u0026pdev-\u003edev, \"Enabling PCI device has failed: %d\", err);\n+\t\tdev_err(\u0026pci-\u003edev, \"Enabling PCI device has failed: %d\", err);\n \t\treturn err;\n \t}\n \n-\tpci_set_master(pdev);\n+\tpci_set_master(pci);\n \n \t/* set up resources */\n \tmemset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));\n-\tres[0].start = pci_resource_start(pdev, 0);\n-\tres[0].end = pci_resource_end(pdev, 0);\n+\tres[0].start = pci_resource_start(pci, 0);\n+\tres[0].end = pci_resource_end(pci, 0);\n \tres[0].name = PCI_DRIVER_NAME;\n \tres[0].flags = IORESOURCE_MEM;\n-\tres[1].start = pci_irq_vector(pdev, 0);\n+\tres[1].start = pci_irq_vector(pci, 0);\n \tres[1].name = PCI_DRIVER_NAME;\n \tres[1].flags = IORESOURCE_IRQ;\n \n-\tdev_info(\u0026pdev-\u003edev, \"EMAC physical base addr: %pa\\n\",\n+\tdev_info(\u0026pci-\u003edev, \"EMAC physical base addr: %pa\\n\",\n \t\t \u0026res[0].start);\n \n \t/* set up macb platform data */\n \tmemset(\u0026plat_data, 0, sizeof(plat_data));\n \n \t/* initialize clocks */\n-\tplat_data.pclk = clk_register_fixed_rate(\u0026pdev-\u003edev, \"pclk\", NULL, 0,\n+\tplat_data.pclk = clk_register_fixed_rate(\u0026pci-\u003edev, \"pclk\", NULL, 0,\n \t\t\t\t\t\t GEM_PCLK_RATE);\n \tif (IS_ERR(plat_data.pclk)) {\n \t\terr = PTR_ERR(plat_data.pclk);\n \t\tgoto err_pclk_register;\n \t}\n \n-\tplat_data.hclk = clk_register_fixed_rate(\u0026pdev-\u003edev, \"hclk\", NULL, 0,\n+\tplat_data.hclk = clk_register_fixed_rate(\u0026pci-\u003edev, \"hclk\", NULL, 0,\n \t\t\t\t\t\t GEM_HCLK_RATE);\n \tif (IS_ERR(plat_data.hclk)) {\n \t\terr = PTR_ERR(plat_data.hclk);\n@@ -74,24 +74,24 @@ static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n \n \t/* set up platform device info */\n \tmemset(\u0026plat_info, 0, sizeof(plat_info));\n-\tplat_info.parent = \u0026pdev-\u003edev;\n-\tplat_info.fwnode = pdev-\u003edev.fwnode;\n+\tplat_info.parent = \u0026pci-\u003edev;\n+\tplat_info.fwnode = pci-\u003edev.fwnode;\n \tplat_info.name = PLAT_DRIVER_NAME;\n-\tplat_info.id = pdev-\u003edevfn;\n+\tplat_info.id = pci-\u003edevfn;\n \tplat_info.res = res;\n \tplat_info.num_res = ARRAY_SIZE(res);\n \tplat_info.data = \u0026plat_data;\n \tplat_info.size_data = sizeof(plat_data);\n-\tplat_info.dma_mask = pdev-\u003edma_mask;\n+\tplat_info.dma_mask = pci-\u003edma_mask;\n \n \t/* register platform device */\n-\tplat_dev = platform_device_register_full(\u0026plat_info);\n-\tif (IS_ERR(plat_dev)) {\n-\t\terr = PTR_ERR(plat_dev);\n+\tpdev = platform_device_register_full(\u0026plat_info);\n+\tif (IS_ERR(pdev)) {\n+\t\terr = PTR_ERR(pdev);\n \t\tgoto err_plat_dev_register;\n \t}\n \n-\tpci_set_drvdata(pdev, plat_dev);\n+\tpci_set_drvdata(pci, pdev);\n \n \treturn 0;\n \n@@ -105,14 +105,14 @@ static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n \treturn err;\n }\n \n-static void macb_remove(struct pci_dev *pdev)\n+static void macb_remove(struct pci_dev *pci)\n {\n-\tstruct platform_device *plat_dev = pci_get_drvdata(pdev);\n-\tstruct macb_platform_data *plat_data = dev_get_platdata(\u0026plat_dev-\u003edev);\n+\tstruct platform_device *pdev = pci_get_drvdata(pci);\n+\tstruct macb_platform_data *plat_data = dev_get_platdata(\u0026pdev-\u003edev);\n \tstruct clk *pclk = plat_data-\u003epclk;\n \tstruct clk *hclk = plat_data-\u003ehclk;\n \n-\tplatform_device_unregister(plat_dev);\n+\tplatform_device_unregister(pdev);\n \tclk_unregister_fixed_rate(pclk);\n \tclk_unregister_fixed_rate(hclk);\n }\ndiff --git a/drivers/net/ethernet/cadence/macb_ptp.c b/drivers/net/ethernet/cadence/macb_ptp.c\nindex d91f7b1aa39ca..8765c4782509c 100644\n--- a/drivers/net/ethernet/cadence/macb_ptp.c\n+++ b/drivers/net/ethernet/cadence/macb_ptp.c\n@@ -28,10 +28,10 @@\n static struct macb_dma_desc_ptp *macb_ptp_desc(struct macb *bp,\n \t\t\t\t\t       struct macb_dma_desc *desc)\n {\n-\tif (!macb_dma_ptp(bp))\n+\tif (!macb_dma_ptp(\u0026bp-\u003einfo))\n \t\treturn NULL;\n \n-\tif (macb_dma64(bp))\n+\tif (macb_dma64(\u0026bp-\u003einfo))\n \t\treturn (struct macb_dma_desc_ptp *)\n \t\t\t\t((u8 *)desc + sizeof(struct macb_dma_desc)\n \t\t\t\t+ sizeof(struct macb_dma_desc_64));\n@@ -324,9 +324,9 @@ void gem_ptp_txstamp(struct macb *bp, struct sk_buff *skb,\n \tskb_tstamp_tx(skb, \u0026shhwtstamps);\n }\n \n-void gem_ptp_init(struct net_device *dev)\n+void gem_ptp_init(struct net_device *netdev)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \tbp-\u003eptp_clock_info = gem_ptp_caps_template;\n \n@@ -334,7 +334,7 @@ void gem_ptp_init(struct net_device *dev)\n \tbp-\u003etsu_rate = bp-\u003eptp_info-\u003eget_tsu_rate(bp);\n \tbp-\u003eptp_clock_info.max_adj = bp-\u003eptp_info-\u003eget_ptp_max_adj();\n \tgem_ptp_init_timer(bp);\n-\tbp-\u003eptp_clock = ptp_clock_register(\u0026bp-\u003eptp_clock_info, \u0026dev-\u003edev);\n+\tbp-\u003eptp_clock = ptp_clock_register(\u0026bp-\u003eptp_clock_info, \u0026netdev-\u003edev);\n \tif (IS_ERR(bp-\u003eptp_clock)) {\n \t\tpr_err(\"ptp clock register failed: %ld\\n\",\n \t\t\tPTR_ERR(bp-\u003eptp_clock));\n@@ -353,9 +353,9 @@ void gem_ptp_init(struct net_device *dev)\n \t\t GEM_PTP_TIMER_NAME);\n }\n \n-void gem_ptp_remove(struct net_device *ndev)\n+void gem_ptp_remove(struct net_device *netdev)\n {\n-\tstruct macb *bp = netdev_priv(ndev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \tif (bp-\u003eptp_clock) {\n \t\tptp_clock_unregister(bp-\u003eptp_clock);\n@@ -378,13 +378,13 @@ static int gem_ptp_set_ts_mode(struct macb *bp,\n \treturn 0;\n }\n \n-int gem_get_hwtst(struct net_device *dev,\n+int gem_get_hwtst(struct net_device *netdev,\n \t\t  struct kernel_hwtstamp_config *tstamp_config)\n {\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \n \t*tstamp_config = bp-\u003etstamp_config;\n-\tif (!macb_dma_ptp(bp))\n+\tif (!macb_dma_ptp(\u0026bp-\u003einfo))\n \t\treturn -EOPNOTSUPP;\n \n \treturn 0;\n@@ -402,16 +402,16 @@ static void gem_ptp_set_one_step_sync(struct macb *bp, u8 enable)\n \t\tmacb_writel(bp, NCR, reg_val \u0026 ~MACB_BIT(OSSMODE));\n }\n \n-int gem_set_hwtst(struct net_device *dev,\n+int gem_set_hwtst(struct net_device *netdev,\n \t\t  struct kernel_hwtstamp_config *tstamp_config,\n \t\t  struct netlink_ext_ack *extack)\n {\n \tenum macb_bd_control tx_bd_control = TSTAMP_DISABLED;\n \tenum macb_bd_control rx_bd_control = TSTAMP_DISABLED;\n-\tstruct macb *bp = netdev_priv(dev);\n+\tstruct macb *bp = netdev_priv(netdev);\n \tu32 regval;\n \n-\tif (!macb_dma_ptp(bp))\n+\tif (!macb_dma_ptp(\u0026bp-\u003einfo))\n \t\treturn -EOPNOTSUPP;\n \n \tswitch (tstamp_config-\u003etx_type) {\n"
}

2/1 2026/08/05 19:15 agent patch-evaluator
0m Model:
best-expensive

Args:
null

Results:
{
  "EnableConfigs": [
    "MACB",
    "MACB_PCI"
  ],
  "FocusSymbols": [
    "macb_change_mtu",
    "macb_set_ringparam",
    "macb_context_swap_start",
    "macb_context_swap_end"
  ],
  "Reasoning": "The patch introduces a new `macb_context` structure to the Cadence MACB/GEM ethernet driver, enabling context swapping for dynamic MTU and ring parameter changes without fully stopping the device. It also refactors the driver's queue and ring management to use this context. The driver can be fuzzed via its PCI wrapper (`CONFIG_MACB_PCI`), which allows syzkaller to instantiate it using virtual PCI devices. The focus should be on the newly introduced context swapping logic triggered by MTU and ring parameter changes.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
  even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).
- Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed,
  ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU.
- Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove)
  that are executed only during PCI hot-unplug or sysfs driver unbind operations.

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
   Prefer non-static, non-inlined API entrypoint functions over internal static helper functions
   (which are inlined by the compiler and do not have distinct symbol addresses).
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs
   needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs
   output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit f28c5413d02745f373e50617d569151a91ef9c6f
Author: syz-cluster <triage@syzkaller.com>
Date:   Wed Aug 5 19:15:08 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 2de56017ee0d6..24559ff2ab6ff 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -840,7 +840,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); \
@@ -849,7 +849,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); \
@@ -1196,22 +1196,23 @@ 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);
-	void	(*mog_init_rings)(struct macb *bp);
+	int	(*mog_alloc_rx_buffers)(struct macb_context *ctx);
+	void	(*mog_free_rx_buffers)(struct macb_context *ctx);
+	void	(*mog_init_rings)(struct macb_context *ctx);
 	int	(*mog_rx)(struct macb_queue *queue, struct napi_struct *napi,
 			  int budget);
 };
 
 /* MACB-PTP interface: adapt to platform needs. */
 struct macb_ptp_info {
-	void (*ptp_init)(struct net_device *ndev);
-	void (*ptp_remove)(struct net_device *ndev);
+	void (*ptp_init)(struct net_device *netdev);
+	void (*ptp_remove)(struct net_device *netdev);
 	s32 (*get_ptp_max_adj)(void);
 	unsigned int (*get_tsu_rate)(struct macb *bp);
-	int (*get_ts_info)(struct net_device *dev,
+	int (*get_ts_info)(struct net_device *netdev,
 			   struct kernel_ethtool_ts_info *info);
 	int (*get_hwtst)(struct net_device *netdev,
 			 struct kernel_hwtstamp_config *tstamp_config);
@@ -1270,23 +1271,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;
 };
@@ -1301,6 +1291,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;
@@ -1309,24 +1338,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	*dev;
 	/* Protects hw_stats and ethtool_stats */
 	spinlock_t		stats_lock;
 	union {
@@ -1334,15 +1375,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;
@@ -1385,8 +1423,11 @@ struct macb {
 	struct delayed_work	tx_lpi_work;
 	u32			tx_lpi_timer;
 
-	int	rx_bd_rd_prefetch;
-	int	tx_bd_rd_prefetch;
+	/* ISR must not drive NAPI & BH mechanisms. Protected by bp->lock. */
+	bool			ctx_swap;
+
+	/* Redundant to netif_carrier_ok(), but set under bp->mac_cfg_lock. */
+	bool			link_up;
 
 	u32	rx_intr_mask;
 
@@ -1406,8 +1447,8 @@ enum macb_bd_control {
 	TSTAMP_ALL_FRAMES,
 };
 
-void gem_ptp_init(struct net_device *ndev);
-void gem_ptp_remove(struct net_device *ndev);
+void gem_ptp_init(struct net_device *netdev);
+void gem_ptp_remove(struct net_device *netdev);
 void gem_ptp_txstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc);
 void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc);
 static inline void gem_ptp_do_txstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc)
@@ -1426,27 +1467,28 @@ static inline void gem_ptp_do_rxstamp(struct macb *bp, struct sk_buff *skb, stru
 	gem_ptp_rxstamp(bp, skb, desc);
 }
 
-int gem_get_hwtst(struct net_device *dev,
+int gem_get_hwtst(struct net_device *netdev,
 		  struct kernel_hwtstamp_config *tstamp_config);
-int gem_set_hwtst(struct net_device *dev,
+int gem_set_hwtst(struct net_device *netdev,
 		  struct kernel_hwtstamp_config *tstamp_config,
 		  struct netlink_ext_ack *extack);
 #else
-static inline void gem_ptp_init(struct net_device *ndev) { }
-static inline void gem_ptp_remove(struct net_device *ndev) { }
+static inline void gem_ptp_init(struct net_device *netdev) { }
+static inline void gem_ptp_remove(struct net_device *netdev) { }
 
 static inline void gem_ptp_do_txstamp(struct macb *bp, struct sk_buff *skb, struct macb_dma_desc *desc) { }
 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 */
@@ -1462,16 +1504,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,
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index d394f1f43b685..b3d84a65078f8 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -61,7 +61,7 @@ struct sifive_fu540_macb_mgmt {
 #define MAX_TX_RING_SIZE	4096
 
 /* level of occupied TX descriptors under which we wake up TX process */
-#define MACB_TX_WAKEUP_THRESH(bp)	(3 * (bp)->tx_ring_size / 4)
+#define MACB_TX_WAKEUP_THRESH(bp)	(3 * (bp)->ctx->tx_ring_size / 4)
 
 #define MACB_RX_INT_FLAGS	(MACB_BIT(RCOMP) | MACB_BIT(ISR_ROVR))
 #define MACB_TX_ERR_FLAGS	(MACB_BIT(ISR_TUND)			\
@@ -126,75 +126,104 @@ struct sifive_fu540_macb_mgmt {
  *    word 5: timestamp word 1
  *    word 6: timestamp word 2
  */
-static unsigned int macb_dma_desc_get_size(struct macb *bp)
+static unsigned int macb_dma_desc_get_size(const struct macb_info *info)
 {
 	unsigned int desc_size = sizeof(struct macb_dma_desc);
 
-	if (macb_dma64(bp))
+	if (macb_dma64(info))
 		desc_size += sizeof(struct macb_dma_desc_64);
-	if (macb_dma_ptp(bp))
+	if (macb_dma_ptp(info))
 		desc_size += sizeof(struct macb_dma_desc_ptp);
 
 	return desc_size;
 }
 
-static unsigned int macb_adj_dma_desc_idx(struct macb *bp, unsigned int desc_idx)
+static unsigned int macb_adj_dma_desc_idx(struct macb_context *ctx,
+					  unsigned int desc_idx)
 {
-	return desc_idx * (1 + macb_dma64(bp) + macb_dma_ptp(bp));
+	return desc_idx * (1 + macb_dma64(ctx->info) +
+			       macb_dma_ptp(ctx->info));
 }
 
-static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct macb_dma_desc *desc)
+static struct macb_dma_desc_64 *macb_64b_desc(struct macb_dma_desc *desc)
 {
 	return (struct macb_dma_desc_64 *)((void *)desc
 		+ sizeof(struct macb_dma_desc));
 }
 
 /* Ring buffer accessors */
-static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)
+static unsigned int macb_tx_ring_wrap(struct macb_context *ctx,
+				      unsigned int index)
 {
-	return index & (bp->tx_ring_size - 1);
+	return index & (ctx->tx_ring_size - 1);
 }
 
-static struct macb_dma_desc *macb_tx_desc(struct macb_queue *queue,
+static struct macb_txq *macb_txq(struct macb_queue *queue)
+{
+	struct macb *bp = queue->bp;
+	unsigned int q = queue - bp->queues;
+
+	return &bp->ctx->txq[q];
+}
+
+static struct macb_rxq *macb_rxq(struct macb_queue *queue)
+{
+	struct macb *bp = queue->bp;
+	unsigned int q = queue - bp->queues;
+
+	return &bp->ctx->rxq[q];
+}
+
+static struct macb_dma_desc *macb_tx_desc(struct macb_context *ctx,
+					  unsigned int q,
 					  unsigned int index)
 {
-	index = macb_tx_ring_wrap(queue->bp, index);
-	index = macb_adj_dma_desc_idx(queue->bp, index);
-	return &queue->tx_ring[index];
+	index = macb_tx_ring_wrap(ctx, index);
+	index = macb_adj_dma_desc_idx(ctx, index);
+	return &ctx->txq[q].ring[index];
 }
 
 static struct macb_tx_skb *macb_tx_skb(struct macb_queue *queue,
 				       unsigned int index)
 {
-	return &queue->tx_skb[macb_tx_ring_wrap(queue->bp, index)];
+	struct macb_txq *txq = macb_txq(queue);
+
+	return &txq->skb[macb_tx_ring_wrap(queue->bp->ctx, index)];
 }
 
 static dma_addr_t macb_tx_dma(struct macb_queue *queue, unsigned int index)
 {
+	struct macb_context *ctx = queue->bp->ctx;
+	struct macb_txq *txq = macb_txq(queue);
 	dma_addr_t offset;
 
-	offset = macb_tx_ring_wrap(queue->bp, index) *
-			macb_dma_desc_get_size(queue->bp);
+	offset = macb_tx_ring_wrap(ctx, index) *
+			macb_dma_desc_get_size(&queue->bp->info);
 
-	return queue->tx_ring_dma + offset;
+	return txq->ring_dma + offset;
 }
 
-static unsigned int macb_rx_ring_wrap(struct macb *bp, unsigned int index)
+static unsigned int macb_rx_ring_wrap(struct macb_context *ctx,
+				      unsigned int index)
 {
-	return index & (bp->rx_ring_size - 1);
+	return index & (ctx->rx_ring_size - 1);
 }
 
-static struct macb_dma_desc *macb_rx_desc(struct macb_queue *queue, unsigned int index)
+static struct macb_dma_desc *macb_rx_desc(struct macb_context *ctx,
+					  unsigned int q, unsigned int index)
 {
-	index = macb_rx_ring_wrap(queue->bp, index);
-	index = macb_adj_dma_desc_idx(queue->bp, index);
-	return &queue->rx_ring[index];
+	index = macb_rx_ring_wrap(ctx, index);
+	index = macb_adj_dma_desc_idx(ctx, index);
+	return &ctx->rxq[q].ring[index];
 }
 
 static void *macb_rx_buffer(struct macb_queue *queue, unsigned int index)
 {
-	return queue->rx_buffers + queue->bp->rx_buffer_size *
-	       macb_rx_ring_wrap(queue->bp, index);
+	struct macb_context *ctx = queue->bp->ctx;
+	struct macb_rxq *rxq = macb_rxq(queue);
+
+	return rxq->buffers + ctx->rx_buffer_size *
+	       macb_rx_ring_wrap(ctx, index);
 }
 
 /* I/O accessors */
@@ -252,12 +281,12 @@ static void macb_set_hwaddr(struct macb *bp)
 	u32 bottom;
 	u16 top;
 
-	bottom = get_unaligned_le32(bp->dev->dev_addr);
+	bottom = get_unaligned_le32(bp->netdev->dev_addr);
 	macb_or_gem_writel(bp, SA1B, bottom);
-	top = get_unaligned_le16(bp->dev->dev_addr + 4);
+	top = get_unaligned_le16(bp->netdev->dev_addr + 4);
 	macb_or_gem_writel(bp, SA1T, top);
 
-	if (gem_has_ptp(bp)) {
+	if (gem_has_ptp(&bp->info)) {
 		gem_writel(bp, RXPTPUNI, bottom);
 		gem_writel(bp, TXPTPUNI, bottom);
 	}
@@ -291,13 +320,13 @@ static void macb_get_hwaddr(struct macb *bp)
 		addr[5] = (top >> 8) & 0xff;
 
 		if (is_valid_ether_addr(addr)) {
-			eth_hw_addr_set(bp->dev, addr);
+			eth_hw_addr_set(bp->netdev, addr);
 			return;
 		}
 	}
 
 	dev_info(&bp->pdev->dev, "invalid hw address, using random\n");
-	eth_hw_addr_random(bp->dev);
+	eth_hw_addr_random(bp->netdev);
 }
 
 static int macb_mdio_wait_for_idle(struct macb *bp)
@@ -463,19 +492,23 @@ static int macb_mdio_write_c45(struct mii_bus *bus, int mii_id,
 static void macb_init_buffers(struct macb *bp)
 {
 	struct macb_queue *queue;
+	struct macb_rxq *rxq;
+	struct macb_txq *txq;
 	unsigned int q;
 
 	/* Single register for all queues' high 32 bits. */
-	if (macb_dma64(bp)) {
-		macb_writel(bp, RBQPH,
-			    upper_32_bits(bp->queues[0].rx_ring_dma));
-		macb_writel(bp, TBQPH,
-			    upper_32_bits(bp->queues[0].tx_ring_dma));
+	if (macb_dma64(&bp->info)) {
+		rxq = &bp->ctx->rxq[0];
+		txq = &bp->ctx->txq[0];
+		macb_writel(bp, RBQPH, upper_32_bits(rxq->ring_dma));
+		macb_writel(bp, TBQPH, upper_32_bits(txq->ring_dma));
 	}
 
 	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-		queue_writel(queue, RBQP, lower_32_bits(queue->rx_ring_dma));
-		queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
+		rxq = &bp->ctx->rxq[q];
+		txq = &bp->ctx->txq[q];
+		queue_writel(queue, RBQP, lower_32_bits(rxq->ring_dma));
+		queue_writel(queue, TBQP, lower_32_bits(txq->ring_dma));
 	}
 }
 
@@ -509,12 +542,12 @@ static void macb_set_tx_clk(struct macb *bp, int speed)
 	ferr = abs(rate_rounded - rate);
 	ferr = DIV_ROUND_UP(ferr, rate / 100000);
 	if (ferr > 5)
-		netdev_warn(bp->dev,
+		netdev_warn(bp->netdev,
 			    "unable to generate target frequency: %ld Hz\n",
 			    rate);
 
 	if (clk_set_rate(bp->tx_clk, rate_rounded))
-		netdev_err(bp->dev, "adjusting tx_clk failed.\n");
+		netdev_err(bp->netdev, "adjusting tx_clk failed.\n");
 }
 
 static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
@@ -648,11 +681,12 @@ static bool macb_tx_lpi_set(struct macb *bp, bool enable)
 
 static bool macb_tx_all_queues_idle(struct macb *bp)
 {
-	struct macb_queue *queue;
+	struct macb_txq *txq;
 	unsigned int q;
 
-	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-		if (READ_ONCE(queue->tx_head) != READ_ONCE(queue->tx_tail))
+	for (q = 0; q < bp->num_queues; ++q) {
+		txq = &bp->ctx->txq[q];
+		if (READ_ONCE(txq->head) != READ_ONCE(txq->tail))
 			return false;
 	}
 	return true;
@@ -697,34 +731,49 @@ static void macb_tx_lpi_wake(struct macb *bp)
 
 static void macb_mac_disable_tx_lpi(struct phylink_config *config)
 {
-	struct net_device *ndev = to_net_dev(config->dev);
-	struct macb *bp = netdev_priv(ndev);
+	struct net_device *netdev = to_net_dev(config->dev);
+	struct macb *bp = netdev_priv(netdev);
 	unsigned long flags;
 
+	mutex_lock(&bp->mac_cfg_lock);
+
 	cancel_delayed_work_sync(&bp->tx_lpi_work);
 
 	spin_lock_irqsave(&bp->lock, flags);
 	bp->eee_active = false;
 	macb_tx_lpi_set(bp, false);
 	spin_unlock_irqrestore(&bp->lock, flags);
+
+	mutex_unlock(&bp->mac_cfg_lock);
+}
+
+static void macb_txp_lpi_initial_defer(struct macb *bp)
+{
+	lockdep_assert_held(&bp->mac_cfg_lock);
+
+	/* Defer initial LPI entry by 1 second after link-up per
+	 * IEEE 802.3az section 22.7a.
+	 */
+	mod_delayed_work(system_wq, &bp->tx_lpi_work, msecs_to_jiffies(1000));
 }
 
 static int macb_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
 				  bool tx_clk_stop)
 {
-	struct net_device *ndev = to_net_dev(config->dev);
-	struct macb *bp = netdev_priv(ndev);
+	struct net_device *netdev = to_net_dev(config->dev);
+	struct macb *bp = netdev_priv(netdev);
 	unsigned long flags;
 
+	mutex_lock(&bp->mac_cfg_lock);
+
 	spin_lock_irqsave(&bp->lock, flags);
 	bp->tx_lpi_timer = timer;
 	bp->eee_active = true;
 	spin_unlock_irqrestore(&bp->lock, flags);
 
-	/* Defer initial LPI entry by 1 second after link-up per
-	 * IEEE 802.3az section 22.7a.
-	 */
-	mod_delayed_work(system_wq, &bp->tx_lpi_work, msecs_to_jiffies(1000));
+	macb_txp_lpi_initial_defer(bp);
+
+	mutex_unlock(&bp->mac_cfg_lock);
 
 	return 0;
 }
@@ -732,12 +781,13 @@ static int macb_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
 static void macb_mac_config(struct phylink_config *config, unsigned int mode,
 			    const struct phylink_link_state *state)
 {
-	struct net_device *ndev = to_net_dev(config->dev);
-	struct macb *bp = netdev_priv(ndev);
+	struct net_device *netdev = to_net_dev(config->dev);
+	struct macb *bp = netdev_priv(netdev);
 	unsigned long flags;
 	u32 old_ctrl, ctrl;
 	u32 old_ncr, ncr;
 
+	mutex_lock(&bp->mac_cfg_lock);
 	spin_lock_irqsave(&bp->lock, flags);
 
 	old_ctrl = ctrl = macb_or_gem_readl(bp, NCFGR);
@@ -746,7 +796,7 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,
 	if (bp->caps & MACB_CAPS_MACB_IS_EMAC) {
 		if (state->interface == PHY_INTERFACE_MODE_RMII)
 			ctrl |= MACB_BIT(RM9200_RMII);
-	} else if (macb_is_gem(bp)) {
+	} else if (macb_is_gem(&bp->info)) {
 		ctrl &= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
 		ncr &= ~GEM_BIT(ENABLE_HS_MAC);
 
@@ -769,17 +819,22 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,
 		macb_or_gem_writel(bp, NCR, ncr);
 
 	spin_unlock_irqrestore(&bp->lock, flags);
+	mutex_unlock(&bp->mac_cfg_lock);
 }
 
 static void macb_mac_link_down(struct phylink_config *config, unsigned int mode,
 			       phy_interface_t interface)
 {
-	struct net_device *ndev = to_net_dev(config->dev);
-	struct macb *bp = netdev_priv(ndev);
+	struct net_device *netdev = to_net_dev(config->dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_queue *queue;
 	unsigned int q;
 	u32 ctrl;
 
+	mutex_lock(&bp->mac_cfg_lock);
+
+	bp->link_up = false;
+
 	if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC))
 		for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
 			queue_writel(queue, IDR,
@@ -789,7 +844,9 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode,
 	ctrl = macb_readl(bp, NCR) & ~(MACB_BIT(RE) | MACB_BIT(TE));
 	macb_writel(bp, NCR, ctrl);
 
-	netif_tx_stop_all_queues(ndev);
+	netif_tx_stop_all_queues(netdev);
+
+	mutex_unlock(&bp->mac_cfg_lock);
 }
 
 /* Use juggling algorithm to left rotate tx ring and tx skb array */
@@ -798,28 +855,30 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)
 	unsigned int head, tail, count, ring_size, desc_size;
 	struct macb_tx_skb tx_skb, *skb_curr, *skb_next;
 	struct macb_dma_desc *desc_curr, *desc_next;
+	unsigned int q = queue - queue->bp->queues;
 	unsigned int i, cycles, shift, curr, next;
-	struct macb *bp = queue->bp;
+	struct macb_context *ctx = queue->bp->ctx;
+	struct macb_txq *txq = macb_txq(queue);
 	unsigned char desc[24];
 	unsigned long flags;
 
-	desc_size = macb_dma_desc_get_size(bp);
+	desc_size = macb_dma_desc_get_size(&queue->bp->info);
 
 	if (WARN_ON_ONCE(desc_size > ARRAY_SIZE(desc)))
 		return;
 
 	spin_lock_irqsave(&queue->tx_ptr_lock, flags);
-	head = queue->tx_head;
-	tail = queue->tx_tail;
-	ring_size = bp->tx_ring_size;
+	head = txq->head;
+	tail = txq->tail;
+	ring_size = ctx->tx_ring_size;
 	count = CIRC_CNT(head, tail, ring_size);
 
 	if (!(tail % ring_size))
 		goto unlock;
 
 	if (!count) {
-		queue->tx_head = 0;
-		queue->tx_tail = 0;
+		txq->head = 0;
+		txq->tail = 0;
 		goto unlock;
 	}
 
@@ -827,7 +886,7 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)
 	cycles = gcd(ring_size, shift);
 
 	for (i = 0; i < cycles; i++) {
-		memcpy(&desc, macb_tx_desc(queue, i), desc_size);
+		memcpy(&desc, macb_tx_desc(ctx, q, i), desc_size);
 		memcpy(&tx_skb, macb_tx_skb(queue, i),
 		       sizeof(struct macb_tx_skb));
 
@@ -835,8 +894,8 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)
 		next = (curr + shift) % ring_size;
 
 		while (next != i) {
-			desc_curr = macb_tx_desc(queue, curr);
-			desc_next = macb_tx_desc(queue, next);
+			desc_curr = macb_tx_desc(ctx, q, curr);
+			desc_next = macb_tx_desc(ctx, q, next);
 
 			memcpy(desc_curr, desc_next, desc_size);
 
@@ -853,7 +912,7 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)
 			next = (curr + shift) % ring_size;
 		}
 
-		desc_curr = macb_tx_desc(queue, curr);
+		desc_curr = macb_tx_desc(ctx, q, curr);
 		memcpy(desc_curr, &desc, desc_size);
 		if (i == ring_size - 1)
 			desc_curr->ctrl &= ~MACB_BIT(TX_WRAP);
@@ -863,8 +922,8 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)
 		       sizeof(struct macb_tx_skb));
 	}
 
-	queue->tx_head = count;
-	queue->tx_tail = 0;
+	txq->head = count;
+	txq->tail = 0;
 
 	/* Make descriptor updates visible to hardware */
 	wmb();
@@ -877,27 +936,30 @@ static void gem_shuffle_tx_one_ring(struct macb_queue *queue)
 static void gem_shuffle_tx_rings(struct macb *bp)
 {
 	struct macb_queue *queue;
-	int q;
+	unsigned int q;
 
 	for (q = 0, queue = bp->queues; q < bp->num_queues; q++, queue++)
 		gem_shuffle_tx_one_ring(queue);
 }
 
 static void macb_mac_link_up(struct phylink_config *config,
-			     struct phy_device *phy,
+			     struct phy_device *phydev,
 			     unsigned int mode, phy_interface_t interface,
 			     int speed, int duplex,
 			     bool tx_pause, bool rx_pause)
 {
-	struct net_device *ndev = to_net_dev(config->dev);
-	struct macb *bp = netdev_priv(ndev);
+	struct net_device *netdev = to_net_dev(config->dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_queue *queue;
 	unsigned long flags;
 	unsigned int q;
 	u32 ctrl;
 
+	mutex_lock(&bp->mac_cfg_lock);
 	spin_lock_irqsave(&bp->lock, flags);
 
+	bp->link_up = true;
+
 	ctrl = macb_or_gem_readl(bp, NCFGR);
 
 	ctrl &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
@@ -910,7 +972,7 @@ static void macb_mac_link_up(struct phylink_config *config,
 
 	if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) {
 		ctrl &= ~MACB_BIT(PAE);
-		if (macb_is_gem(bp)) {
+		if (macb_is_gem(&bp->info)) {
 			ctrl &= ~GEM_BIT(GBE);
 
 			if (speed == SPEED_1000)
@@ -941,19 +1003,21 @@ static void macb_mac_link_up(struct phylink_config *config,
 
 	/* Enable Rx and Tx; Enable PTP unicast */
 	ctrl = macb_readl(bp, NCR);
-	if (gem_has_ptp(bp))
+	if (gem_has_ptp(&bp->info))
 		ctrl |= MACB_BIT(PTPUNI);
 
 	macb_writel(bp, NCR, ctrl | MACB_BIT(RE) | MACB_BIT(TE));
 
-	netif_tx_wake_all_queues(ndev);
+	netif_tx_wake_all_queues(netdev);
+
+	mutex_unlock(&bp->mac_cfg_lock);
 }
 
 static struct phylink_pcs *macb_mac_select_pcs(struct phylink_config *config,
 					       phy_interface_t interface)
 {
-	struct net_device *ndev = to_net_dev(config->dev);
-	struct macb *bp = netdev_priv(ndev);
+	struct net_device *netdev = to_net_dev(config->dev);
+	struct macb *bp = netdev_priv(netdev);
 
 	if (interface == PHY_INTERFACE_MODE_10GBASER)
 		return &bp->phylink_usx_pcs;
@@ -982,7 +1046,7 @@ static bool macb_phy_handle_exists(struct device_node *dn)
 static int macb_phylink_connect(struct macb *bp)
 {
 	struct device_node *dn = bp->pdev->dev.of_node;
-	struct net_device *dev = bp->dev;
+	struct net_device *netdev = bp->netdev;
 	struct phy_device *phydev;
 	int ret;
 
@@ -992,7 +1056,7 @@ static int macb_phylink_connect(struct macb *bp)
 	if (!dn || (ret && !macb_phy_handle_exists(dn))) {
 		phydev = phy_find_first(bp->mii_bus);
 		if (!phydev) {
-			netdev_err(dev, "no PHY found\n");
+			netdev_err(netdev, "no PHY found\n");
 			return -ENXIO;
 		}
 
@@ -1001,7 +1065,7 @@ static int macb_phylink_connect(struct macb *bp)
 	}
 
 	if (ret) {
-		netdev_err(dev, "Could not attach PHY (%d)\n", ret);
+		netdev_err(netdev, "Could not attach PHY (%d)\n", ret);
 		return ret;
 	}
 
@@ -1013,21 +1077,21 @@ static int macb_phylink_connect(struct macb *bp)
 static void macb_get_pcs_fixed_state(struct phylink_config *config,
 				     struct phylink_link_state *state)
 {
-	struct net_device *ndev = to_net_dev(config->dev);
-	struct macb *bp = netdev_priv(ndev);
+	struct net_device *netdev = to_net_dev(config->dev);
+	struct macb *bp = netdev_priv(netdev);
 
 	state->link = (macb_readl(bp, NSR) & MACB_BIT(NSR_LINK)) != 0;
 }
 
 /* based on au1000_eth. c*/
-static int macb_mii_probe(struct net_device *dev)
+static int macb_mii_probe(struct net_device *netdev)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
 	bp->phylink_sgmii_pcs.ops = &macb_phylink_pcs_ops;
 	bp->phylink_usx_pcs.ops = &macb_phylink_usx_pcs_ops;
 
-	bp->phylink_config.dev = &dev->dev;
+	bp->phylink_config.dev = &netdev->dev;
 	bp->phylink_config.type = PHYLINK_NETDEV;
 	bp->phylink_config.mac_managed_pm = true;
 
@@ -1051,7 +1115,8 @@ static int macb_mii_probe(struct net_device *dev)
 		  bp->phylink_config.supported_interfaces);
 
 	/* Determine what modes are supported */
-	if (macb_is_gem(bp) && (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)) {
+	if (macb_is_gem(&bp->info) &&
+	    (bp->caps & MACB_CAPS_GIGABIT_MODE_AVAILABLE)) {
 		bp->phylink_config.mac_capabilities |= MAC_1000FD;
 		if (!(bp->caps & MACB_CAPS_NO_GIGABIT_HALF))
 			bp->phylink_config.mac_capabilities |= MAC_1000HD;
@@ -1086,7 +1151,7 @@ static int macb_mii_probe(struct net_device *dev)
 	bp->phylink = phylink_create(&bp->phylink_config, bp->pdev->dev.fwnode,
 				     bp->phy_interface, &macb_phylink_ops);
 	if (IS_ERR(bp->phylink)) {
-		netdev_err(dev, "Could not create a phylink instance (%ld)\n",
+		netdev_err(netdev, "Could not create a phylink instance (%ld)\n",
 			   PTR_ERR(bp->phylink));
 		return PTR_ERR(bp->phylink);
 	}
@@ -1133,7 +1198,7 @@ static int macb_mii_init(struct macb *bp)
 	 */
 	mdio_np = of_get_child_by_name(np, "mdio");
 	if (!mdio_np && of_phy_is_fixed_link(np))
-		return macb_mii_probe(bp->dev);
+		return macb_mii_probe(bp->netdev);
 
 	/* Enable management port */
 	macb_writel(bp, NCR, MACB_BIT(MPE));
@@ -1154,13 +1219,13 @@ static int macb_mii_init(struct macb *bp)
 	bp->mii_bus->priv = bp;
 	bp->mii_bus->parent = &bp->pdev->dev;
 
-	dev_set_drvdata(&bp->dev->dev, bp->mii_bus);
+	dev_set_drvdata(&bp->netdev->dev, bp->mii_bus);
 
 	err = macb_mdiobus_register(bp, mdio_np);
 	if (err)
 		goto err_out_free_mdiobus;
 
-	err = macb_mii_probe(bp->dev);
+	err = macb_mii_probe(bp->netdev);
 	if (err)
 		goto err_out_unregister_bus;
 
@@ -1201,14 +1266,15 @@ static int macb_halt_tx(struct macb *bp)
 					bp, TSR);
 }
 
-static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb, int budget)
+static void macb_tx_unmap(const struct macb_info *info,
+			  struct macb_tx_skb *tx_skb, int budget)
 {
 	if (tx_skb->mapping) {
 		if (tx_skb->mapped_as_page)
-			dma_unmap_page(&bp->pdev->dev, tx_skb->mapping,
+			dma_unmap_page(&info->pdev->dev, tx_skb->mapping,
 				       tx_skb->size, DMA_TO_DEVICE);
 		else
-			dma_unmap_single(&bp->pdev->dev, tx_skb->mapping,
+			dma_unmap_single(&info->pdev->dev, tx_skb->mapping,
 					 tx_skb->size, DMA_TO_DEVICE);
 		tx_skb->mapping = 0;
 	}
@@ -1219,12 +1285,13 @@ static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb, int budge
 	}
 }
 
-static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_t addr)
+static void macb_set_addr(const struct macb_info *info,
+			  struct macb_dma_desc *desc, dma_addr_t addr)
 {
-	if (macb_dma64(bp)) {
+	if (macb_dma64(info)) {
 		struct macb_dma_desc_64 *desc_64;
 
-		desc_64 = macb_64b_desc(bp, desc);
+		desc_64 = macb_64b_desc(desc);
 		desc_64->addrh = upper_32_bits(addr);
 		/* The low bits of RX address contain the RX_USED bit, clearing
 		 * of which allows packet RX. Make sure the high bits are also
@@ -1236,40 +1303,43 @@ static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_
 	desc->addr = lower_32_bits(addr);
 }
 
-static dma_addr_t macb_get_addr(struct macb *bp, struct macb_dma_desc *desc)
+static dma_addr_t macb_get_addr(struct macb_context *ctx,
+				struct macb_dma_desc *desc)
 {
 	dma_addr_t addr = 0;
 
-	if (macb_dma64(bp)) {
+	if (macb_dma64(ctx->info)) {
 		struct macb_dma_desc_64 *desc_64;
 
-		desc_64 = macb_64b_desc(bp, desc);
+		desc_64 = macb_64b_desc(desc);
 		addr = ((u64)(desc_64->addrh) << 32);
 	}
 	addr |= MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
-	if (macb_dma_ptp(bp))
+	if (macb_dma_ptp(ctx->info))
 		addr &= ~GEM_BIT(DMA_RXVALID);
 	return addr;
 }
 
 static void macb_tx_error_task(struct work_struct *work)
 {
-	struct macb_queue	*queue = container_of(work, struct macb_queue,
-						      tx_error_task);
-	bool			halt_timeout = false;
-	struct macb		*bp = queue->bp;
-	u32			queue_index;
-	u32			packets = 0;
-	u32			bytes = 0;
-	struct macb_tx_skb	*tx_skb;
-	struct macb_dma_desc	*desc;
-	struct sk_buff		*skb;
-	unsigned int		tail;
-	unsigned long		flags;
-
-	queue_index = queue - bp->queues;
-	netdev_vdbg(bp->dev, "macb_tx_error_task: q = %u, t = %u, h = %u\n",
-		    queue_index, queue->tx_tail, queue->tx_head);
+	struct macb_queue *queue = container_of(work, struct macb_queue,
+						tx_error_task);
+	unsigned int q = queue - queue->bp->queues;
+	struct macb_context *ctx = queue->bp->ctx;
+	struct macb_txq *txq = macb_txq(queue);
+	struct macb *bp = queue->bp;
+	struct macb_tx_skb *tx_skb;
+	struct macb_dma_desc *desc;
+	bool halt_timeout = false;
+	bool buggy_driver = false;
+	struct sk_buff *skb;
+	unsigned long flags;
+	unsigned int tail;
+	u32 packets = 0;
+	u32 bytes = 0;
+
+	netdev_vdbg(bp->netdev, "%s: q = %u, t = %u, h = %u\n",
+		    __func__, q, txq->tail, txq->head);
 
 	/* Prevent the queue NAPI TX poll from running, as it calls
 	 * macb_tx_complete(), which in turn may call netif_wake_subqueue().
@@ -1281,14 +1351,13 @@ static void macb_tx_error_task(struct work_struct *work)
 	spin_lock_irqsave(&bp->lock, flags);
 
 	/* Make sure nobody is trying to queue up new packets */
-	netif_tx_stop_all_queues(bp->dev);
+	netif_tx_stop_all_queues(bp->netdev);
 
 	/* Stop transmission now
 	 * (in case we have just queued new packets)
 	 * macb/gem must be halted to write TBQP register
 	 */
 	if (macb_halt_tx(bp)) {
-		netdev_err(bp->dev, "BUG: halt tx timed out\n");
 		macb_writel(bp, NCR, macb_readl(bp, NCR) & (~MACB_BIT(TE)));
 		halt_timeout = true;
 	}
@@ -1296,10 +1365,10 @@ static void macb_tx_error_task(struct work_struct *work)
 	/* Treat frames in TX queue including the ones that caused the error.
 	 * Free transmit buffers in upper layer.
 	 */
-	for (tail = queue->tx_tail; tail != queue->tx_head; tail++) {
+	for (tail = txq->tail; tail != txq->head; tail++) {
 		u32	ctrl;
 
-		desc = macb_tx_desc(queue, tail);
+		desc = macb_tx_desc(ctx, q, tail);
 		ctrl = desc->ctrl;
 		tx_skb = macb_tx_skb(queue, tail);
 		skb = tx_skb->skb;
@@ -1307,7 +1376,7 @@ static void macb_tx_error_task(struct work_struct *work)
 		if (ctrl & MACB_BIT(TX_USED)) {
 			/* skb is set for the last buffer of the frame */
 			while (!skb) {
-				macb_tx_unmap(bp, tx_skb, 0);
+				macb_tx_unmap(&bp->info, tx_skb, 0);
 				tail++;
 				tx_skb = macb_tx_skb(queue, tail);
 				skb = tx_skb->skb;
@@ -1317,13 +1386,13 @@ static void macb_tx_error_task(struct work_struct *work)
 			 * since it's the only one written back by the hardware
 			 */
 			if (!(ctrl & MACB_BIT(TX_BUF_EXHAUSTED))) {
-				netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
-					    macb_tx_ring_wrap(bp, tail),
+				netdev_vdbg(bp->netdev, "txerr skb %u (data %p) TX complete\n",
+					    macb_tx_ring_wrap(ctx, tail),
 					    skb->data);
-				bp->dev->stats.tx_packets++;
+				bp->netdev->stats.tx_packets++;
 				queue->stats.tx_packets++;
 				packets++;
-				bp->dev->stats.tx_bytes += skb->len;
+				bp->netdev->stats.tx_bytes += skb->len;
 				queue->stats.tx_bytes += skb->len;
 				bytes += skb->len;
 			}
@@ -1333,31 +1402,30 @@ static void macb_tx_error_task(struct work_struct *work)
 			 * those. Statistics are updated by hardware.
 			 */
 			if (ctrl & MACB_BIT(TX_BUF_EXHAUSTED))
-				netdev_err(bp->dev,
-					   "BUG: TX buffers exhausted mid-frame\n");
+				buggy_driver = true;
 
 			desc->ctrl = ctrl | MACB_BIT(TX_USED);
 		}
 
-		macb_tx_unmap(bp, tx_skb, 0);
+		macb_tx_unmap(&bp->info, tx_skb, 0);
 	}
 
-	netdev_tx_completed_queue(netdev_get_tx_queue(bp->dev, queue_index),
+	netdev_tx_completed_queue(netdev_get_tx_queue(bp->netdev, q),
 				  packets, bytes);
 
 	/* Set end of TX queue */
-	desc = macb_tx_desc(queue, 0);
-	macb_set_addr(bp, desc, 0);
+	desc = macb_tx_desc(ctx, q, 0);
+	macb_set_addr(&bp->info, desc, 0);
 	desc->ctrl = MACB_BIT(TX_USED);
 
 	/* Make descriptor updates visible to hardware */
 	wmb();
 
 	/* Reinitialize the TX desc queue */
-	queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
+	queue_writel(queue, TBQP, lower_32_bits(txq->ring_dma));
 	/* Make TX ring reflect state of hardware */
-	queue->tx_head = 0;
-	queue->tx_tail = 0;
+	txq->head = 0;
+	txq->tail = 0;
 
 	/* Housework before enabling TX IRQ */
 	macb_writel(bp, TSR, macb_readl(bp, TSR));
@@ -1367,11 +1435,18 @@ static void macb_tx_error_task(struct work_struct *work)
 		macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE));
 
 	/* Now we are ready to start transmission again */
-	netif_tx_start_all_queues(bp->dev);
+	netif_tx_start_all_queues(bp->netdev);
 	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
 
 	spin_unlock_irqrestore(&bp->lock, flags);
+
 	napi_enable(&queue->napi_tx);
+
+	if (halt_timeout)
+		netdev_err(bp->netdev, "BUG: halt tx timed out, we ignored it\n");
+
+	if (buggy_driver)
+		netdev_err(bp->netdev, "BUG: TX buffers exhausted mid-frame\n");
 }
 
 static bool ptp_one_step_sync(struct sk_buff *skb)
@@ -1407,7 +1482,9 @@ static bool ptp_one_step_sync(struct sk_buff *skb)
 static int macb_tx_complete(struct macb_queue *queue, int budget)
 {
 	struct macb *bp = queue->bp;
-	u16 queue_index = queue - bp->queues;
+	struct macb_txq *txq = macb_txq(queue);
+	unsigned int q = queue - bp->queues;
+	struct macb_context *ctx = bp->ctx;
 	unsigned long flags;
 	unsigned int tail;
 	unsigned int head;
@@ -1415,14 +1492,14 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)
 	u32 bytes = 0;
 
 	spin_lock_irqsave(&queue->tx_ptr_lock, flags);
-	head = queue->tx_head;
-	for (tail = queue->tx_tail; tail != head && packets < budget; tail++) {
+	head = txq->head;
+	for (tail = txq->tail; tail != head && packets < budget; tail++) {
 		struct macb_tx_skb	*tx_skb;
 		struct sk_buff		*skb;
 		struct macb_dma_desc	*desc;
 		u32			ctrl;
 
-		desc = macb_tx_desc(queue, tail);
+		desc = macb_tx_desc(ctx, q, tail);
 
 		/* Make hw descriptor updates visible to CPU */
 		rmb();
@@ -1446,19 +1523,19 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)
 				    !ptp_one_step_sync(skb))
 					gem_ptp_do_txstamp(bp, skb, desc);
 
-				netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
-					    macb_tx_ring_wrap(bp, tail),
+				netdev_vdbg(bp->netdev, "skb %u (data %p) TX complete\n",
+					    macb_tx_ring_wrap(ctx, tail),
 					    skb->data);
-				bp->dev->stats.tx_packets++;
+				bp->netdev->stats.tx_packets++;
 				queue->stats.tx_packets++;
-				bp->dev->stats.tx_bytes += skb->len;
+				bp->netdev->stats.tx_bytes += skb->len;
 				queue->stats.tx_bytes += skb->len;
 				packets++;
 				bytes += skb->len;
 			}
 
 			/* Now we can safely release resources */
-			macb_tx_unmap(bp, tx_skb, budget);
+			macb_tx_unmap(&bp->info, tx_skb, budget);
 
 			/* skb is set only for the last buffer of the frame.
 			 * WARNING: at this point skb has been freed by
@@ -1469,14 +1546,14 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)
 		}
 	}
 
-	netdev_tx_completed_queue(netdev_get_tx_queue(bp->dev, queue_index),
+	netdev_tx_completed_queue(netdev_get_tx_queue(bp->netdev, q),
 				  packets, bytes);
 
-	queue->tx_tail = tail;
-	if (__netif_subqueue_stopped(bp->dev, queue_index) &&
-	    CIRC_CNT(queue->tx_head, queue->tx_tail,
-		     bp->tx_ring_size) <= MACB_TX_WAKEUP_THRESH(bp))
-		netif_wake_subqueue(bp->dev, queue_index);
+	txq->tail = tail;
+	if (__netif_subqueue_stopped(bp->netdev, q) &&
+	    CIRC_CNT(txq->head, txq->tail,
+		     bp->ctx->tx_ring_size) <= MACB_TX_WAKEUP_THRESH(bp))
+		netif_wake_subqueue(bp->netdev, q);
 	spin_unlock_irqrestore(&queue->tx_ptr_lock, flags);
 
 	if (packets)
@@ -1485,51 +1562,53 @@ static int macb_tx_complete(struct macb_queue *queue, int budget)
 	return packets;
 }
 
-static void gem_rx_refill(struct macb_queue *queue)
+static void gem_rx_refill(struct macb_context *ctx, unsigned int q)
 {
-	unsigned int		entry;
-	struct sk_buff		*skb;
-	dma_addr_t		paddr;
-	struct macb *bp = queue->bp;
+	struct device *dev = &ctx->info->pdev->dev;
+	struct macb_rxq *rxq = &ctx->rxq[q];
 	struct macb_dma_desc *desc;
+	struct sk_buff *skb;
+	unsigned int entry;
+	dma_addr_t paddr;
 
-	while (CIRC_SPACE(queue->rx_prepared_head, queue->rx_tail,
-			bp->rx_ring_size) > 0) {
-		entry = macb_rx_ring_wrap(bp, queue->rx_prepared_head);
+	while (CIRC_SPACE(rxq->prepared_head, rxq->tail,
+			  ctx->rx_ring_size) > 0) {
+		entry = macb_rx_ring_wrap(ctx, rxq->prepared_head);
 
 		/* Make hw descriptor updates visible to CPU */
 		rmb();
 
-		desc = macb_rx_desc(queue, entry);
+		desc = macb_rx_desc(ctx, q, entry);
 
-		if (!queue->rx_skbuff[entry]) {
+		if (!rxq->skbuff[entry]) {
 			/* allocate sk_buff for this free entry in ring */
-			skb = netdev_alloc_skb(bp->dev, bp->rx_buffer_size);
+			skb = netdev_alloc_skb(ctx->info->netdev,
+					       ctx->rx_buffer_size);
 			if (unlikely(!skb)) {
-				netdev_err(bp->dev,
+				netdev_err(ctx->info->netdev,
 					   "Unable to allocate sk_buff\n");
 				break;
 			}
 
 			/* now fill corresponding descriptor entry */
-			paddr = dma_map_single(&bp->pdev->dev, skb->data,
-					       bp->rx_buffer_size,
+			paddr = dma_map_single(dev, skb->data,
+					       ctx->rx_buffer_size,
 					       DMA_FROM_DEVICE);
-			if (dma_mapping_error(&bp->pdev->dev, paddr)) {
+			if (dma_mapping_error(dev, paddr)) {
 				dev_kfree_skb(skb);
 				break;
 			}
 
-			queue->rx_skbuff[entry] = skb;
+			rxq->skbuff[entry] = skb;
 
-			if (entry == bp->rx_ring_size - 1)
+			if (entry == ctx->rx_ring_size - 1)
 				paddr |= MACB_BIT(RX_WRAP);
 			desc->ctrl = 0;
 			/* Setting addr clears RX_USED and allows reception,
 			 * make sure ctrl is cleared first to avoid a race.
 			 */
 			dma_wmb();
-			macb_set_addr(bp, desc, paddr);
+			macb_set_addr(ctx->info, desc, paddr);
 
 			/* Properly align Ethernet header.
 			 *
@@ -1542,31 +1621,34 @@ static void gem_rx_refill(struct macb_queue *queue)
 			 * setting the low 2/3 bits.
 			 * It is 3 bits if HW_DMA_CAP_PTP, else 2 bits.
 			 */
-			if (!(bp->caps & MACB_CAPS_RSC))
+			if (!(ctx->info->caps & MACB_CAPS_RSC))
 				skb_reserve(skb, NET_IP_ALIGN);
 		} else {
 			desc->ctrl = 0;
 			dma_wmb();
 			desc->addr &= ~MACB_BIT(RX_USED);
 		}
-		queue->rx_prepared_head++;
+		rxq->prepared_head++;
 	}
 
 	/* Make descriptor updates visible to hardware */
 	wmb();
 
-	netdev_vdbg(bp->dev, "rx ring: queue: %p, prepared head %d, tail %d\n",
-			queue, queue->rx_prepared_head, queue->rx_tail);
+	netdev_vdbg(ctx->info->netdev,
+		    "rx ring: queue: %u, prepared head %d, tail %d\n",
+		    q, rxq->prepared_head, rxq->tail);
 }
 
 /* Mark DMA descriptors from begin up to and not including end as unused */
 static void discard_partial_frame(struct macb_queue *queue, unsigned int begin,
 				  unsigned int end)
 {
+	unsigned int q = queue - queue->bp->queues;
+	struct macb_context *ctx = queue->bp->ctx;
 	unsigned int frag;
 
 	for (frag = begin; frag != end; frag++) {
-		struct macb_dma_desc *desc = macb_rx_desc(queue, frag);
+		struct macb_dma_desc *desc = macb_rx_desc(ctx, q, frag);
 
 		desc->addr &= ~MACB_BIT(RX_USED);
 	}
@@ -1583,26 +1665,29 @@ static void discard_partial_frame(struct macb_queue *queue, unsigned int begin,
 static int gem_rx(struct macb_queue *queue, struct napi_struct *napi,
 		  int budget)
 {
+	unsigned int q = queue - queue->bp->queues;
+	struct macb_context *ctx = queue->bp->ctx;
+	struct macb_rxq *rxq = macb_rxq(queue);
 	struct macb *bp = queue->bp;
-	unsigned int		len;
-	unsigned int		entry;
-	struct sk_buff		*skb;
-	struct macb_dma_desc	*desc;
-	int			count = 0;
+	struct macb_dma_desc *desc;
+	struct sk_buff *skb;
+	unsigned int entry;
+	unsigned int len;
+	int count = 0;
 
 	while (count < budget) {
 		u32 ctrl;
 		dma_addr_t addr;
 		bool rxused;
 
-		entry = macb_rx_ring_wrap(bp, queue->rx_tail);
-		desc = macb_rx_desc(queue, entry);
+		entry = macb_rx_ring_wrap(ctx, rxq->tail);
+		desc = macb_rx_desc(ctx, q, entry);
 
 		/* Make hw descriptor updates visible to CPU */
 		rmb();
 
 		rxused = (desc->addr & MACB_BIT(RX_USED)) ? true : false;
-		addr = macb_get_addr(bp, desc);
+		addr = macb_get_addr(ctx, desc);
 
 		if (!rxused)
 			break;
@@ -1612,50 +1697,51 @@ static int gem_rx(struct macb_queue *queue, struct napi_struct *napi,
 
 		ctrl = desc->ctrl;
 
-		queue->rx_tail++;
+		rxq->tail++;
 		count++;
 
 		if (!(ctrl & MACB_BIT(RX_SOF) && ctrl & MACB_BIT(RX_EOF))) {
-			netdev_err(bp->dev,
+			netdev_err(bp->netdev,
 				   "not whole frame pointed by descriptor\n");
-			bp->dev->stats.rx_dropped++;
+			bp->netdev->stats.rx_dropped++;
 			queue->stats.rx_dropped++;
 			break;
 		}
-		skb = queue->rx_skbuff[entry];
+		skb = rxq->skbuff[entry];
 		if (unlikely(!skb)) {
-			netdev_err(bp->dev,
+			netdev_err(bp->netdev,
 				   "inconsistent Rx descriptor chain\n");
-			bp->dev->stats.rx_dropped++;
+			bp->netdev->stats.rx_dropped++;
 			queue->stats.rx_dropped++;
 			break;
 		}
 		/* now everything is ready for receiving packet */
-		queue->rx_skbuff[entry] = NULL;
+		rxq->skbuff[entry] = NULL;
 		len = ctrl & bp->rx_frm_len_mask;
 
-		netdev_vdbg(bp->dev, "gem_rx %u (len %u)\n", entry, len);
+		netdev_vdbg(bp->netdev, "%s %u (len %u)\n",
+			    __func__, entry, len);
 
 		skb_put(skb, len);
 		dma_unmap_single(&bp->pdev->dev, addr,
-				 bp->rx_buffer_size, DMA_FROM_DEVICE);
+				 bp->ctx->rx_buffer_size, DMA_FROM_DEVICE);
 
-		skb->protocol = eth_type_trans(skb, bp->dev);
+		skb->protocol = eth_type_trans(skb, bp->netdev);
 		skb_checksum_none_assert(skb);
-		if (bp->dev->features & NETIF_F_RXCSUM &&
-		    !(bp->dev->flags & IFF_PROMISC) &&
+		if (bp->netdev->features & NETIF_F_RXCSUM &&
+		    !(bp->netdev->flags & IFF_PROMISC) &&
 		    GEM_BFEXT(RX_CSUM, ctrl) & GEM_RX_CSUM_CHECKED_MASK)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-		bp->dev->stats.rx_packets++;
+		bp->netdev->stats.rx_packets++;
 		queue->stats.rx_packets++;
-		bp->dev->stats.rx_bytes += skb->len;
+		bp->netdev->stats.rx_bytes += skb->len;
 		queue->stats.rx_bytes += skb->len;
 
 		gem_ptp_do_rxstamp(bp, skb, desc);
 
 #if defined(DEBUG) && defined(VERBOSE_DEBUG)
-		netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n",
+		netdev_vdbg(bp->netdev, "received skb of length %u, csum: %08x\n",
 			    skb->len, skb->csum);
 		print_hex_dump(KERN_DEBUG, " mac: ", DUMP_PREFIX_ADDRESS, 16, 1,
 			       skb_mac_header(skb), 16, true);
@@ -1666,7 +1752,7 @@ static int gem_rx(struct macb_queue *queue, struct napi_struct *napi,
 		napi_gro_receive(napi, skb);
 	}
 
-	gem_rx_refill(queue);
+	gem_rx_refill(ctx, q);
 
 	return count;
 }
@@ -1674,19 +1760,22 @@ static int gem_rx(struct macb_queue *queue, struct napi_struct *napi,
 static int macb_rx_frame(struct macb_queue *queue, struct napi_struct *napi,
 			 unsigned int first_frag, unsigned int last_frag)
 {
-	unsigned int len;
-	unsigned int frag;
+	unsigned int q = queue - queue->bp->queues;
+	struct macb_context *ctx = queue->bp->ctx;
+	struct macb *bp = queue->bp;
+	struct macb_dma_desc *desc;
 	unsigned int offset;
 	struct sk_buff *skb;
-	struct macb_dma_desc *desc;
-	struct macb *bp = queue->bp;
+	unsigned int frag;
+	unsigned int len;
 
-	desc = macb_rx_desc(queue, last_frag);
+	desc = macb_rx_desc(ctx, q, last_frag);
 	len = desc->ctrl & bp->rx_frm_len_mask;
 
-	netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
-		macb_rx_ring_wrap(bp, first_frag),
-		macb_rx_ring_wrap(bp, last_frag), len);
+	netdev_vdbg(bp->netdev, "%s frags %u - %u (len %u)\n",
+		    __func__,
+		    macb_rx_ring_wrap(ctx, first_frag),
+		    macb_rx_ring_wrap(ctx, last_frag), len);
 
 	/* The ethernet header starts NET_IP_ALIGN bytes into the
 	 * first buffer. Since the header is 14 bytes, this makes the
@@ -1696,11 +1785,11 @@ static int macb_rx_frame(struct macb_queue *queue, struct napi_struct *napi,
 	 * the two padding bytes into the skb so that we avoid hitting
 	 * the slowpath in memcpy(), and pull them off afterwards.
 	 */
-	skb = netdev_alloc_skb(bp->dev, len + NET_IP_ALIGN);
+	skb = netdev_alloc_skb(bp->netdev, len + NET_IP_ALIGN);
 	if (!skb) {
-		bp->dev->stats.rx_dropped++;
+		bp->netdev->stats.rx_dropped++;
 		for (frag = first_frag; ; frag++) {
-			desc = macb_rx_desc(queue, frag);
+			desc = macb_rx_desc(ctx, q, frag);
 			desc->addr &= ~MACB_BIT(RX_USED);
 			if (frag == last_frag)
 				break;
@@ -1718,7 +1807,7 @@ static int macb_rx_frame(struct macb_queue *queue, struct napi_struct *napi,
 	skb_put(skb, len);
 
 	for (frag = first_frag; ; frag++) {
-		unsigned int frag_len = bp->rx_buffer_size;
+		unsigned int frag_len = bp->ctx->rx_buffer_size;
 
 		if (offset + frag_len > len) {
 			if (unlikely(frag != last_frag)) {
@@ -1730,8 +1819,8 @@ static int macb_rx_frame(struct macb_queue *queue, struct napi_struct *napi,
 		skb_copy_to_linear_data_offset(skb, offset,
 					       macb_rx_buffer(queue, frag),
 					       frag_len);
-		offset += bp->rx_buffer_size;
-		desc = macb_rx_desc(queue, frag);
+		offset += bp->ctx->rx_buffer_size;
+		desc = macb_rx_desc(ctx, q, frag);
 		desc->addr &= ~MACB_BIT(RX_USED);
 
 		if (frag == last_frag)
@@ -1742,46 +1831,49 @@ static int macb_rx_frame(struct macb_queue *queue, struct napi_struct *napi,
 	wmb();
 
 	__skb_pull(skb, NET_IP_ALIGN);
-	skb->protocol = eth_type_trans(skb, bp->dev);
+	skb->protocol = eth_type_trans(skb, bp->netdev);
 
-	bp->dev->stats.rx_packets++;
-	bp->dev->stats.rx_bytes += skb->len;
-	netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n",
+	bp->netdev->stats.rx_packets++;
+	bp->netdev->stats.rx_bytes += skb->len;
+	netdev_vdbg(bp->netdev, "received skb of length %u, csum: %08x\n",
 		    skb->len, skb->csum);
 	napi_gro_receive(napi, skb);
 
 	return 0;
 }
 
-static inline void macb_init_rx_ring(struct macb_queue *queue)
+static inline void macb_init_rx_ring(struct macb_context *ctx, unsigned int q)
 {
-	struct macb *bp = queue->bp;
-	dma_addr_t addr;
+	struct macb_rxq *rxq = &ctx->rxq[q];
 	struct macb_dma_desc *desc = NULL;
+	dma_addr_t addr;
 	int i;
 
-	addr = queue->rx_buffers_dma;
-	for (i = 0; i < bp->rx_ring_size; i++) {
-		desc = macb_rx_desc(queue, i);
-		macb_set_addr(bp, desc, addr);
+	addr = rxq->buffers_dma;
+	for (i = 0; i < ctx->rx_ring_size; i++) {
+		desc = macb_rx_desc(ctx, q, i);
+		macb_set_addr(ctx->info, desc, addr);
 		desc->ctrl = 0;
-		addr += bp->rx_buffer_size;
+		addr += ctx->rx_buffer_size;
 	}
 	desc->addr |= MACB_BIT(RX_WRAP);
-	queue->rx_tail = 0;
+	rxq->tail = 0;
 }
 
 static int macb_rx(struct macb_queue *queue, struct napi_struct *napi,
 		   int budget)
 {
+	unsigned int q = queue - queue->bp->queues;
+	struct macb_context *ctx = queue->bp->ctx;
+	struct macb_rxq *rxq = macb_rxq(queue);
 	struct macb *bp = queue->bp;
 	bool reset_rx_queue = false;
-	int received = 0;
-	unsigned int tail;
 	int first_frag = -1;
+	unsigned int tail;
+	int received = 0;
 
-	for (tail = queue->rx_tail; budget > 0; tail++) {
-		struct macb_dma_desc *desc = macb_rx_desc(queue, tail);
+	for (tail = rxq->tail; budget > 0; tail++) {
+		struct macb_dma_desc *desc = macb_rx_desc(ctx, q, tail);
 		u32 ctrl;
 
 		/* Make hw descriptor updates visible to CPU */
@@ -1826,15 +1918,15 @@ static int macb_rx(struct macb_queue *queue, struct napi_struct *napi,
 		unsigned long flags;
 		u32 ctrl;
 
-		netdev_err(bp->dev, "RX queue corruption: reset it\n");
+		netdev_err(bp->netdev, "RX queue corruption: reset it\n");
 
 		spin_lock_irqsave(&bp->lock, flags);
 
 		ctrl = macb_readl(bp, NCR);
 		macb_writel(bp, NCR, ctrl & ~MACB_BIT(RE));
 
-		macb_init_rx_ring(queue);
-		queue_writel(queue, RBQP, queue->rx_ring_dma);
+		macb_init_rx_ring(ctx, q);
+		queue_writel(queue, RBQP, rxq->ring_dma);
 
 		macb_writel(bp, NCR, ctrl | MACB_BIT(RE));
 
@@ -1843,21 +1935,23 @@ static int macb_rx(struct macb_queue *queue, struct napi_struct *napi,
 	}
 
 	if (first_frag != -1)
-		queue->rx_tail = first_frag;
+		rxq->tail = first_frag;
 	else
-		queue->rx_tail = tail;
+		rxq->tail = tail;
 
 	return received;
 }
 
 static bool macb_rx_pending(struct macb_queue *queue)
 {
-	struct macb *bp = queue->bp;
-	unsigned int		entry;
-	struct macb_dma_desc	*desc;
+	unsigned int q = queue - queue->bp->queues;
+	struct macb_context *ctx = queue->bp->ctx;
+	struct macb_rxq *rxq = macb_rxq(queue);
+	struct macb_dma_desc *desc;
+	unsigned int entry;
 
-	entry = macb_rx_ring_wrap(bp, queue->rx_tail);
-	desc = macb_rx_desc(queue, entry);
+	entry = macb_rx_ring_wrap(ctx, rxq->tail);
+	desc = macb_rx_desc(ctx, q, entry);
 
 	/* Make hw descriptor updates visible to CPU */
 	rmb();
@@ -1873,7 +1967,7 @@ static int macb_rx_poll(struct napi_struct *napi, int budget)
 
 	work_done = bp->macbgem_ops.mog_rx(queue, napi, budget);
 
-	netdev_vdbg(bp->dev, "RX poll: queue = %u, work_done = %d, budget = %d\n",
+	netdev_vdbg(bp->netdev, "RX poll: queue = %u, work_done = %d, budget = %d\n",
 		    (unsigned int)(queue - bp->queues), work_done, budget);
 
 	if (work_done < budget && napi_complete_done(napi, work_done)) {
@@ -1892,7 +1986,7 @@ static int macb_rx_poll(struct napi_struct *napi, int budget)
 		if (macb_rx_pending(queue)) {
 			queue_writel(queue, IDR, bp->rx_intr_mask);
 			macb_queue_isr_clear(bp, queue, MACB_BIT(RCOMP));
-			netdev_vdbg(bp->dev, "poll: packets pending, reschedule\n");
+			netdev_vdbg(bp->netdev, "poll: packets pending, reschedule\n");
 			napi_schedule(napi);
 		}
 	}
@@ -1904,18 +1998,20 @@ static int macb_rx_poll(struct napi_struct *napi, int budget)
 
 static void macb_tx_restart(struct macb_queue *queue)
 {
+	struct macb_context *ctx = queue->bp->ctx;
+	struct macb_txq *txq = macb_txq(queue);
 	struct macb *bp = queue->bp;
 	unsigned int head_idx, tbqp;
 	unsigned long flags;
 
 	spin_lock_irqsave(&queue->tx_ptr_lock, flags);
 
-	if (queue->tx_head == queue->tx_tail)
+	if (txq->head == txq->tail)
 		goto out_tx_ptr_unlock;
 
-	tbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(bp);
-	tbqp = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, tbqp));
-	head_idx = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, queue->tx_head));
+	tbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(ctx->info);
+	tbqp = macb_adj_dma_desc_idx(ctx, macb_tx_ring_wrap(ctx, tbqp));
+	head_idx = macb_adj_dma_desc_idx(ctx, macb_tx_ring_wrap(ctx, txq->head));
 
 	if (tbqp == head_idx)
 		goto out_tx_ptr_unlock;
@@ -1930,15 +2026,18 @@ static void macb_tx_restart(struct macb_queue *queue)
 
 static bool macb_tx_complete_pending(struct macb_queue *queue)
 {
+	unsigned int q = queue - queue->bp->queues;
+	struct macb_context *ctx = queue->bp->ctx;
+	struct macb_txq *txq = macb_txq(queue);
 	bool retval = false;
 	unsigned long flags;
 
 	spin_lock_irqsave(&queue->tx_ptr_lock, flags);
-	if (queue->tx_head != queue->tx_tail) {
+	if (txq->head != txq->tail) {
 		/* Make hw descriptor updates visible to CPU */
 		rmb();
 
-		if (macb_tx_desc(queue, queue->tx_tail)->ctrl & MACB_BIT(TX_USED))
+		if (macb_tx_desc(ctx, q, txq->tail)->ctrl & MACB_BIT(TX_USED))
 			retval = true;
 	}
 	spin_unlock_irqrestore(&queue->tx_ptr_lock, flags);
@@ -1956,11 +2055,11 @@ static int macb_tx_poll(struct napi_struct *napi, int budget)
 	rmb(); // ensure txubr_pending is up to date
 	if (queue->txubr_pending) {
 		queue->txubr_pending = false;
-		netdev_vdbg(bp->dev, "poll: tx restart\n");
+		netdev_vdbg(bp->netdev, "poll: tx restart\n");
 		macb_tx_restart(queue);
 	}
 
-	netdev_vdbg(bp->dev, "TX poll: queue = %u, work_done = %d, budget = %d\n",
+	netdev_vdbg(bp->netdev, "TX poll: queue = %u, work_done = %d, budget = %d\n",
 		    (unsigned int)(queue - bp->queues), work_done, budget);
 
 	if (work_done < budget && napi_complete_done(napi, work_done)) {
@@ -1979,7 +2078,7 @@ static int macb_tx_poll(struct napi_struct *napi, int budget)
 		if (macb_tx_complete_pending(queue)) {
 			queue_writel(queue, IDR, MACB_BIT(TCOMP));
 			macb_queue_isr_clear(bp, queue, MACB_BIT(TCOMP));
-			netdev_vdbg(bp->dev, "TX poll: packets pending, reschedule\n");
+			netdev_vdbg(bp->netdev, "TX poll: packets pending, reschedule\n");
 			napi_schedule(napi);
 		}
 	}
@@ -1990,7 +2089,8 @@ static int macb_tx_poll(struct napi_struct *napi, int budget)
 static void macb_hresp_error_task(struct work_struct *work)
 {
 	struct macb *bp = from_work(bp, work, hresp_err_bh_work);
-	struct net_device *dev = bp->dev;
+	struct net_device *netdev = bp->netdev;
+	struct macb_context *ctx = bp->ctx;
 	struct macb_queue *queue;
 	unsigned int q;
 	u32 ctrl;
@@ -2004,10 +2104,10 @@ static void macb_hresp_error_task(struct work_struct *work)
 	ctrl &= ~(MACB_BIT(RE) | MACB_BIT(TE));
 	macb_writel(bp, NCR, ctrl);
 
-	netif_tx_stop_all_queues(dev);
-	netif_carrier_off(dev);
+	netif_tx_stop_all_queues(netdev);
+	netif_carrier_off(netdev);
 
-	bp->macbgem_ops.mog_init_rings(bp);
+	bp->macbgem_ops.mog_init_rings(ctx);
 
 	/* Initialize TX and RX buffers */
 	macb_init_buffers(bp);
@@ -2022,8 +2122,8 @@ static void macb_hresp_error_task(struct work_struct *work)
 	ctrl |= MACB_BIT(RE) | MACB_BIT(TE);
 	macb_writel(bp, NCR, ctrl);
 
-	netif_carrier_on(dev);
-	netif_tx_start_all_queues(dev);
+	netif_carrier_on(netdev);
+	netif_tx_start_all_queues(netdev);
 }
 
 static void macb_wol_interrupt(struct macb_queue *queue, u32 status)
@@ -2032,7 +2132,7 @@ static void macb_wol_interrupt(struct macb_queue *queue, u32 status)
 
 	queue_writel(queue, IDR, MACB_BIT(WOL));
 	macb_writel(bp, WOL, 0);
-	netdev_vdbg(bp->dev, "MACB WoL: queue = %u, isr = 0x%08lx\n",
+	netdev_vdbg(bp->netdev, "MACB WoL: queue = %u, isr = 0x%08lx\n",
 		    (unsigned int)(queue - bp->queues),
 		    (unsigned long)status);
 	macb_queue_isr_clear(bp, queue, MACB_BIT(WOL));
@@ -2045,7 +2145,7 @@ static void gem_wol_interrupt(struct macb_queue *queue, u32 status)
 
 	queue_writel(queue, IDR, GEM_BIT(WOL));
 	gem_writel(bp, WOL, 0);
-	netdev_vdbg(bp->dev, "GEM WoL: queue = %u, isr = 0x%08lx\n",
+	netdev_vdbg(bp->netdev, "GEM WoL: queue = %u, isr = 0x%08lx\n",
 		    (unsigned int)(queue - bp->queues),
 		    (unsigned long)status);
 	macb_queue_isr_clear(bp, queue, GEM_BIT(WOL));
@@ -2055,10 +2155,10 @@ static void gem_wol_interrupt(struct macb_queue *queue, u32 status)
 static int macb_interrupt_misc(struct macb_queue *queue, u32 status)
 {
 	struct macb *bp = queue->bp;
-	struct net_device *dev;
+	struct net_device *netdev;
 	u32 ctrl;
 
-	dev = bp->dev;
+	netdev = bp->netdev;
 
 	if (unlikely(status & (MACB_TX_ERR_FLAGS))) {
 		queue_writel(queue, IDR, MACB_TX_INT_FLAGS);
@@ -2089,7 +2189,7 @@ static int macb_interrupt_misc(struct macb_queue *queue, u32 status)
 	if (status & MACB_BIT(ISR_ROVR)) {
 		/* We missed at least one packet */
 		spin_lock(&bp->stats_lock);
-		if (macb_is_gem(bp))
+		if (macb_is_gem(&bp->info))
 			bp->hw_stats.gem.rx_overruns++;
 		else
 			bp->hw_stats.macb.rx_overruns++;
@@ -2099,11 +2199,10 @@ static int macb_interrupt_misc(struct macb_queue *queue, u32 status)
 
 	if (status & MACB_BIT(HRESP)) {
 		queue_work(system_bh_wq, &bp->hresp_err_bh_work);
-		netdev_err(dev, "DMA bus error: HRESP not OK\n");
 		macb_queue_isr_clear(bp, queue, MACB_BIT(HRESP));
 	}
 
-	if (macb_is_gem(bp)) {
+	if (macb_is_gem(&bp->info)) {
 		if (status & GEM_BIT(WOL))
 			gem_wol_interrupt(queue, status);
 	} else {
@@ -2118,25 +2217,29 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
 {
 	struct macb_queue *queue = dev_id;
 	struct macb *bp = queue->bp;
-	struct net_device *dev = bp->dev;
+	struct net_device *netdev = bp->netdev;
+	bool hresp_err = false;
 	u32 status;
 
-	status = queue_readl(queue, ISR);
+	spin_lock(&bp->lock);
 
-	if (unlikely(!status))
+	status = queue_readl(queue, ISR);
+	if (unlikely(!status)) {
+		spin_unlock(&bp->lock);
 		return IRQ_NONE;
-
-	spin_lock(&bp->lock);
+	}
 
 	while (status) {
-		/* close possible race with dev_close */
-		if (unlikely(!netif_running(dev))) {
+		/* close possible race with dev_close, and with context-swap
+		 * teardown
+		 */
+		if (unlikely(!netif_running(netdev) || bp->ctx_swap)) {
 			queue_writel(queue, IDR, -1);
 			macb_queue_isr_clear(bp, queue, -1);
 			break;
 		}
 
-		netdev_vdbg(bp->dev, "queue = %u, isr = 0x%08lx\n",
+		netdev_vdbg(netdev, "queue = %u, isr = 0x%08lx\n",
 			    (unsigned int)(queue - bp->queues),
 			    (unsigned long)status);
 
@@ -2165,15 +2268,22 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
 			napi_schedule_irqoff(&queue->napi_tx);
 		}
 
-		if (unlikely(status & MACB_INT_MISC_FLAGS))
+		if (unlikely(status & MACB_INT_MISC_FLAGS)) {
 			if (macb_interrupt_misc(queue, status))
 				break;
 
+			if (status & MACB_BIT(HRESP))
+				hresp_err = true;
+		}
+
 		status = queue_readl(queue, ISR);
 	}
 
 	spin_unlock(&bp->lock);
 
+	if (hresp_err)
+		netdev_err(netdev, "DMA bus error: HRESP not OK\n");
+
 	return IRQ_HANDLED;
 }
 
@@ -2181,16 +2291,16 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
 /* Polling receive - used by netconsole and other diagnostic tools
  * to allow network i/o with interrupts disabled.
  */
-static void macb_poll_controller(struct net_device *dev)
+static void macb_poll_controller(struct net_device *netdev)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_queue *queue;
 	unsigned long flags;
 	unsigned int q;
 
 	local_irq_save(flags);
 	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
-		macb_interrupt(dev->irq, queue);
+		macb_interrupt(netdev->irq, queue);
 	local_irq_restore(flags);
 }
 #endif
@@ -2200,9 +2310,12 @@ static unsigned int macb_tx_map(struct macb *bp,
 				struct sk_buff *skb,
 				unsigned int hdrlen)
 {
+	struct macb_txq *txq = macb_txq(queue);
 	unsigned int f, nr_frags = skb_shinfo(skb)->nr_frags;
-	unsigned int len, i, tx_head = queue->tx_head;
+	unsigned int len, i, tx_head = txq->head;
 	u32 ctrl, lso_ctrl = 0, seq_ctrl = 0;
+	unsigned int q = queue - bp->queues;
+	struct macb_context *ctx = bp->ctx;
 	unsigned int eof = 1, mss_mfs = 0;
 	struct macb_tx_skb *tx_skb = NULL;
 	struct macb_dma_desc *desc;
@@ -2277,7 +2390,7 @@ static unsigned int macb_tx_map(struct macb *bp,
 
 	/* Should never happen */
 	if (unlikely(!tx_skb)) {
-		netdev_err(bp->dev, "BUG! empty skb!\n");
+		netdev_err(bp->netdev, "BUG! empty skb!\n");
 		return 0;
 	}
 
@@ -2293,7 +2406,7 @@ static unsigned int macb_tx_map(struct macb *bp,
 	 */
 	i = tx_head;
 	ctrl = MACB_BIT(TX_USED);
-	desc = macb_tx_desc(queue, i);
+	desc = macb_tx_desc(ctx, q, i);
 	desc->ctrl = ctrl;
 
 	if (lso_ctrl) {
@@ -2314,21 +2427,22 @@ static unsigned int macb_tx_map(struct macb *bp,
 	do {
 		i--;
 		tx_skb = macb_tx_skb(queue, i);
-		desc = macb_tx_desc(queue, i);
+		desc = macb_tx_desc(ctx, q, i);
 
 		ctrl = (u32)tx_skb->size;
 		if (eof) {
 			ctrl |= MACB_BIT(TX_LAST);
 			eof = 0;
 		}
-		if (unlikely(macb_tx_ring_wrap(bp, i) == bp->tx_ring_size - 1))
+		if (unlikely(macb_tx_ring_wrap(ctx, i) ==
+				bp->ctx->tx_ring_size - 1))
 			ctrl |= MACB_BIT(TX_WRAP);
 
 		/* First descriptor is header descriptor */
-		if (i == queue->tx_head) {
+		if (i == txq->head) {
 			ctrl |= MACB_BF(TX_LSO, lso_ctrl);
 			ctrl |= MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl);
-			if ((bp->dev->features & NETIF_F_HW_CSUM) &&
+			if ((bp->netdev->features & NETIF_F_HW_CSUM) &&
 			    skb->ip_summed != CHECKSUM_PARTIAL && !lso_ctrl &&
 			    !ptp_one_step_sync(skb))
 				ctrl |= MACB_BIT(TX_NOCRC);
@@ -2339,32 +2453,32 @@ static unsigned int macb_tx_map(struct macb *bp,
 			ctrl |= MACB_BF(MSS_MFS, mss_mfs);
 
 		/* Set TX buffer descriptor */
-		macb_set_addr(bp, desc, tx_skb->mapping);
+		macb_set_addr(&bp->info, desc, tx_skb->mapping);
 		/* desc->addr must be visible to hardware before clearing
 		 * 'TX_USED' bit in desc->ctrl.
 		 */
 		wmb();
 		desc->ctrl = ctrl;
-	} while (i != queue->tx_head);
+	} while (i != txq->head);
 
-	queue->tx_head = tx_head;
+	txq->head = tx_head;
 
 	return 0;
 
 dma_error:
-	netdev_err(bp->dev, "TX DMA map failed\n");
+	netdev_err(bp->netdev, "TX DMA map failed\n");
 
-	for (i = queue->tx_head; i != tx_head; i++) {
+	for (i = txq->head; i != tx_head; i++) {
 		tx_skb = macb_tx_skb(queue, i);
 
-		macb_tx_unmap(bp, tx_skb, 0);
+		macb_tx_unmap(&bp->info, tx_skb, 0);
 	}
 
 	return -ENOMEM;
 }
 
 static netdev_features_t macb_features_check(struct sk_buff *skb,
-					     struct net_device *dev,
+					     struct net_device *netdev,
 					     netdev_features_t features)
 {
 	unsigned int nr_frags, f;
@@ -2416,7 +2530,7 @@ static inline int macb_clear_csum(struct sk_buff *skb)
 	return 0;
 }
 
-static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
+static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *netdev)
 {
 	bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb) ||
 		      skb_is_nonlinear(*skb);
@@ -2425,7 +2539,7 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
 	struct sk_buff *nskb;
 	u32 fcs;
 
-	if (!(ndev->features & NETIF_F_HW_CSUM) ||
+	if (!(netdev->features & NETIF_F_HW_CSUM) ||
 	    !((*skb)->ip_summed != CHECKSUM_PARTIAL) ||
 	    skb_shinfo(*skb)->gso_size || ptp_one_step_sync(*skb))
 		return 0;
@@ -2467,28 +2581,30 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
 	return 0;
 }
 
-static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t macb_start_xmit(struct sk_buff *skb,
+				   struct net_device *netdev)
 {
-	u16 queue_index = skb_get_queue_mapping(skb);
-	struct macb *bp = netdev_priv(dev);
-	struct macb_queue *queue = &bp->queues[queue_index];
+	struct macb *bp = netdev_priv(netdev);
+	unsigned int q = skb_get_queue_mapping(skb);
 	unsigned int desc_cnt, nr_frags, frag_size, f;
+	struct macb_queue *queue = &bp->queues[q];
+	struct macb_txq *txq = macb_txq(queue);
+	netdev_tx_t ret = NETDEV_TX_OK;
 	unsigned int hdrlen;
 	unsigned long flags;
 	bool is_lso;
-	netdev_tx_t ret = NETDEV_TX_OK;
 
 	if (macb_clear_csum(skb)) {
 		dev_kfree_skb_any(skb);
 		return ret;
 	}
 
-	if (macb_pad_and_fcs(&skb, dev)) {
+	if (macb_pad_and_fcs(&skb, netdev)) {
 		dev_kfree_skb_any(skb);
 		return ret;
 	}
 
-	if (macb_dma_ptp(bp) &&
+	if (macb_dma_ptp(&bp->info) &&
 	    (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 
@@ -2502,7 +2618,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		else
 			hdrlen = skb_tcp_all_headers(skb);
 		if (skb_headlen(skb) < hdrlen) {
-			netdev_err(bp->dev, "Error - LSO headers fragmented!!!\n");
+			netdev_err(bp->netdev, "Error - LSO headers fragmented!!!\n");
 			/* if this is required, would need to copy to single buffer */
 			return NETDEV_TX_BUSY;
 		}
@@ -2510,9 +2626,9 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		hdrlen = umin(skb_headlen(skb), bp->max_tx_length);
 
 #if defined(DEBUG) && defined(VERBOSE_DEBUG)
-	netdev_vdbg(bp->dev,
-		    "start_xmit: queue %hu len %u head %p data %p tail %p end %p\n",
-		    queue_index, skb->len, skb->head, skb->data,
+	netdev_vdbg(bp->netdev,
+		    "start_xmit: queue %u len %u head %p data %p tail %p end %p\n",
+		    q, skb->len, skb->head, skb->data,
 		    skb_tail_pointer(skb), skb_end_pointer(skb));
 	print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_OFFSET, 16, 1,
 		       skb->data, 16, true);
@@ -2536,11 +2652,11 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	spin_lock_irqsave(&queue->tx_ptr_lock, flags);
 
 	/* This is a hard error, log it. */
-	if (CIRC_SPACE(queue->tx_head, queue->tx_tail,
-		       bp->tx_ring_size) < desc_cnt) {
-		netif_stop_subqueue(dev, queue_index);
-		netdev_dbg(bp->dev, "tx_head = %u, tx_tail = %u\n",
-			   queue->tx_head, queue->tx_tail);
+	if (CIRC_SPACE(txq->head, txq->tail,
+		       bp->ctx->tx_ring_size) < desc_cnt) {
+		netif_stop_subqueue(netdev, q);
+		netdev_dbg(netdev, "txq head = %u, txq tail = %u\n",
+			   txq->head, txq->tail);
 		ret = NETDEV_TX_BUSY;
 		goto unlock;
 	}
@@ -2554,7 +2670,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Make newly initialized descriptor visible to hardware */
 	wmb();
 	skb_tx_timestamp(skb);
-	netdev_tx_sent_queue(netdev_get_tx_queue(bp->dev, queue_index),
+	netdev_tx_sent_queue(netdev_get_tx_queue(bp->netdev, q),
 			     skb->len);
 
 	spin_lock(&bp->lock);
@@ -2562,8 +2678,8 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
 	spin_unlock(&bp->lock);
 
-	if (CIRC_SPACE(queue->tx_head, queue->tx_tail, bp->tx_ring_size) < 1)
-		netif_stop_subqueue(dev, queue_index);
+	if (CIRC_SPACE(txq->head, txq->tail, bp->ctx->tx_ring_size) < 1)
+		netif_stop_subqueue(netdev, q);
 
 unlock:
 	spin_unlock_irqrestore(&queue->tx_ptr_lock, flags);
@@ -2571,168 +2687,179 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return ret;
 }
 
-static void macb_init_rx_buffer_size(struct macb *bp, size_t size)
+static unsigned int macb_rx_buffer_size(struct macb *bp, unsigned int mtu)
 {
-	if (!macb_is_gem(bp)) {
-		bp->rx_buffer_size = MACB_RX_BUFFER_SIZE;
+	unsigned int size;
+
+	if (!macb_is_gem(&bp->info)) {
+		size = MACB_RX_BUFFER_SIZE;
 	} else {
-		bp->rx_buffer_size = MIN(size, RX_BUFFER_MAX);
+		size = mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN;
+		size = MIN(size, RX_BUFFER_MAX);
 
-		if (bp->rx_buffer_size % RX_BUFFER_MULTIPLE) {
-			netdev_dbg(bp->dev,
+		if (size % RX_BUFFER_MULTIPLE) {
+			netdev_dbg(bp->netdev,
 				   "RX buffer must be multiple of %d bytes, expanding\n",
 				   RX_BUFFER_MULTIPLE);
-			bp->rx_buffer_size =
-				roundup(bp->rx_buffer_size, RX_BUFFER_MULTIPLE);
+			size = roundup(size, RX_BUFFER_MULTIPLE);
 		}
 	}
 
-	netdev_dbg(bp->dev, "mtu [%u] rx_buffer_size [%zu]\n",
-		   bp->dev->mtu, bp->rx_buffer_size);
+	netdev_dbg(bp->netdev, "mtu [%u] rx_buffer_size [%u]\n", mtu, size);
+	return size;
 }
 
-static void gem_free_rx_buffers(struct macb *bp)
+static void gem_free_rx_buffers(struct macb_context *ctx)
 {
-	struct sk_buff		*skb;
-	struct macb_dma_desc	*desc;
-	struct macb_queue *queue;
-	dma_addr_t		addr;
+	struct device *dev = &ctx->info->pdev->dev;
+	struct macb_dma_desc *desc;
+	struct macb_rxq *rxq;
+	struct sk_buff *skb;
+	dma_addr_t addr;
 	unsigned int q;
 	int i;
 
-	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-		if (!queue->rx_skbuff)
+	for (q = 0; q < ctx->info->num_queues; ++q) {
+		rxq = &ctx->rxq[q];
+
+		if (!rxq->skbuff)
 			continue;
 
-		for (i = 0; i < bp->rx_ring_size; i++) {
-			skb = queue->rx_skbuff[i];
+		for (i = 0; i < ctx->rx_ring_size; i++) {
+			skb = rxq->skbuff[i];
 
 			if (!skb)
 				continue;
 
-			desc = macb_rx_desc(queue, i);
-			addr = macb_get_addr(bp, desc);
+			desc = macb_rx_desc(ctx, q, i);
+			addr = macb_get_addr(ctx, desc);
 
-			dma_unmap_single(&bp->pdev->dev, addr, bp->rx_buffer_size,
-					DMA_FROM_DEVICE);
+			dma_unmap_single(dev, addr, ctx->rx_buffer_size,
+					 DMA_FROM_DEVICE);
 			dev_kfree_skb_any(skb);
 			skb = NULL;
 		}
 
-		kfree(queue->rx_skbuff);
-		queue->rx_skbuff = NULL;
+		kfree(rxq->skbuff);
+		rxq->skbuff = NULL;
 	}
 }
 
-static void macb_free_rx_buffers(struct macb *bp)
+static void macb_free_rx_buffers(struct macb_context *ctx)
 {
-	struct macb_queue *queue = &bp->queues[0];
+	struct device *dev = &ctx->info->pdev->dev;
+	struct macb_rxq *rxq = &ctx->rxq[0];
 
-	if (queue->rx_buffers) {
-		dma_free_coherent(&bp->pdev->dev,
-				  bp->rx_ring_size * bp->rx_buffer_size,
-				  queue->rx_buffers, queue->rx_buffers_dma);
-		queue->rx_buffers = NULL;
+	if (rxq->buffers) {
+		dma_free_coherent(dev,
+				  ctx->rx_ring_size * ctx->rx_buffer_size,
+				  rxq->buffers, rxq->buffers_dma);
+		rxq->buffers = NULL;
 	}
 }
 
-static unsigned int macb_tx_ring_size_per_queue(struct macb *bp)
+static unsigned int macb_tx_ring_size_per_queue(struct macb_context *ctx)
 {
-	return macb_dma_desc_get_size(bp) * bp->tx_ring_size + bp->tx_bd_rd_prefetch;
+	return macb_dma_desc_get_size(ctx->info) * ctx->tx_ring_size +
+			ctx->info->tx_bd_rd_prefetch;
 }
 
-static unsigned int macb_rx_ring_size_per_queue(struct macb *bp)
+static unsigned int macb_rx_ring_size_per_queue(struct macb_context *ctx)
 {
-	return macb_dma_desc_get_size(bp) * bp->rx_ring_size + bp->rx_bd_rd_prefetch;
+	return macb_dma_desc_get_size(ctx->info) * ctx->rx_ring_size +
+			ctx->info->rx_bd_rd_prefetch;
 }
 
-static void macb_free_consistent(struct macb *bp)
+static void macb_free(struct macb_context *ctx)
 {
-	struct device *dev = &bp->pdev->dev;
-	struct macb_queue *queue;
+	struct device *dev = &ctx->info->pdev->dev;
+	struct macb_txq *txq;
+	struct macb_rxq *rxq;
 	unsigned int q;
 	size_t size;
 
-	if (bp->rx_ring_tieoff) {
-		dma_free_coherent(dev, macb_dma_desc_get_size(bp),
-				  bp->rx_ring_tieoff, bp->rx_ring_tieoff_dma);
-		bp->rx_ring_tieoff = NULL;
-	}
+	ctx->info->macbgem_ops.mog_free_rx_buffers(ctx);
 
-	bp->macbgem_ops.mog_free_rx_buffers(bp);
+	txq = &ctx->txq[0];
+	size = ctx->info->num_queues * macb_tx_ring_size_per_queue(ctx);
+	dma_free_coherent(dev, size, txq->ring, txq->ring_dma);
 
-	size = bp->num_queues * macb_tx_ring_size_per_queue(bp);
-	dma_free_coherent(dev, size, bp->queues[0].tx_ring, bp->queues[0].tx_ring_dma);
+	rxq = &ctx->rxq[0];
+	size = ctx->info->num_queues * macb_rx_ring_size_per_queue(ctx);
+	dma_free_coherent(dev, size, rxq->ring, rxq->ring_dma);
 
-	size = bp->num_queues * macb_rx_ring_size_per_queue(bp);
-	dma_free_coherent(dev, size, bp->queues[0].rx_ring, bp->queues[0].rx_ring_dma);
+	for (q = 0; q < ctx->info->num_queues; ++q) {
+		txq = &ctx->txq[q];
+		rxq = &ctx->rxq[q];
 
-	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-		if (queue->tx_skb) {
+		if (txq->skb) {
 			unsigned int dropped = 0, tail;
 
-			for (tail = queue->tx_tail; tail != queue->tx_head;
-			     tail++) {
-				if (macb_tx_skb(queue, tail)->skb)
+			for (tail = txq->tail; tail != txq->head; tail++) {
+				if (txq->skb[macb_tx_ring_wrap(ctx, tail)].skb)
 					dropped++;
-				macb_tx_unmap(bp, macb_tx_skb(queue, tail), 0);
+				macb_tx_unmap(ctx->info,
+					      &txq->skb[macb_tx_ring_wrap(ctx, tail)],
+					      0);
 			}
 
-			queue->stats.tx_dropped += dropped;
-			bp->dev->stats.tx_dropped += dropped;
+			ctx->info->queue_stats[q]->tx_dropped += dropped;
+			ctx->info->netdev->stats.tx_dropped += dropped;
 
-			kfree(queue->tx_skb);
-			queue->tx_skb = NULL;
+			kfree(txq->skb);
+			txq->skb = NULL;
 		}
 
-		queue->tx_head = 0;
-		queue->tx_tail = 0;
-		queue->tx_ring = NULL;
-		queue->rx_ring = NULL;
+		txq->ring = NULL;
+		rxq->ring = NULL;
 	}
 }
 
-static int gem_alloc_rx_buffers(struct macb *bp)
+static int gem_alloc_rx_buffers(struct macb_context *ctx)
 {
-	struct macb_queue *queue;
+	struct macb_rxq *rxq;
 	unsigned int q;
 	int size;
 
-	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-		size = bp->rx_ring_size * sizeof(struct sk_buff *);
-		queue->rx_skbuff = kzalloc(size, GFP_KERNEL);
-		if (!queue->rx_skbuff)
+	for (q = 0; q < ctx->info->num_queues; ++q) {
+		rxq = &ctx->rxq[q];
+		size = ctx->rx_ring_size * sizeof(struct sk_buff *);
+		rxq->skbuff = kzalloc(size, GFP_KERNEL);
+		if (!rxq->skbuff)
 			return -ENOMEM;
 		else
-			netdev_dbg(bp->dev,
+			netdev_dbg(ctx->info->netdev,
 				   "Allocated %d RX struct sk_buff entries at %p\n",
-				   bp->rx_ring_size, queue->rx_skbuff);
+				   ctx->rx_ring_size, rxq->skbuff);
 	}
 	return 0;
 }
 
-static int macb_alloc_rx_buffers(struct macb *bp)
+static int macb_alloc_rx_buffers(struct macb_context *ctx)
 {
-	struct macb_queue *queue = &bp->queues[0];
+	struct device *dev = &ctx->info->pdev->dev;
+	struct macb_rxq *rxq = &ctx->rxq[0];
 	int size;
 
-	size = bp->rx_ring_size * bp->rx_buffer_size;
-	queue->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size,
-					    &queue->rx_buffers_dma, GFP_KERNEL);
-	if (!queue->rx_buffers)
+	size = ctx->rx_ring_size * ctx->rx_buffer_size;
+	rxq->buffers = dma_alloc_coherent(dev, size,
+					  &rxq->buffers_dma, GFP_KERNEL);
+	if (!rxq->buffers)
 		return -ENOMEM;
 
-	netdev_dbg(bp->dev,
+	netdev_dbg(ctx->info->netdev,
 		   "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n",
-		   size, (unsigned long)queue->rx_buffers_dma, queue->rx_buffers);
+		   size, (unsigned long)rxq->buffers_dma, rxq->buffers);
 	return 0;
 }
 
-static int macb_alloc_consistent(struct macb *bp)
+static int macb_alloc(struct macb_context *ctx)
 {
-	struct device *dev = &bp->pdev->dev;
+	unsigned int num_queues = ctx->info->num_queues;
+	struct device *dev = &ctx->info->pdev->dev;
 	dma_addr_t tx_dma, rx_dma;
-	struct macb_queue *queue;
+	struct macb_txq *txq;
+	struct macb_rxq *rxq;
 	unsigned int q;
 	void *tx, *rx;
 	size_t size;
@@ -2744,113 +2871,125 @@ static int macb_alloc_consistent(struct macb *bp)
 	 * natural alignment of physical addresses.
 	 */
 
-	size = bp->num_queues * macb_tx_ring_size_per_queue(bp);
+	size = num_queues * macb_tx_ring_size_per_queue(ctx);
 	tx = dma_alloc_coherent(dev, size, &tx_dma, GFP_KERNEL);
 	if (!tx || upper_32_bits(tx_dma) != upper_32_bits(tx_dma + size - 1))
 		goto out_err;
-	netdev_dbg(bp->dev, "Allocated %zu bytes for %u TX rings at %08lx (mapped %p)\n",
-		   size, bp->num_queues, (unsigned long)tx_dma, tx);
+	netdev_dbg(ctx->info->netdev,
+		   "Allocated %zu bytes for %u TX rings at %08lx (mapped %p)\n",
+		   size, num_queues, (unsigned long)tx_dma, tx);
 
-	size = bp->num_queues * macb_rx_ring_size_per_queue(bp);
+	size = num_queues * macb_rx_ring_size_per_queue(ctx);
 	rx = dma_alloc_coherent(dev, size, &rx_dma, GFP_KERNEL);
 	if (!rx || upper_32_bits(rx_dma) != upper_32_bits(rx_dma + size - 1))
 		goto out_err;
-	netdev_dbg(bp->dev, "Allocated %zu bytes for %u RX rings at %08lx (mapped %p)\n",
-		   size, bp->num_queues, (unsigned long)rx_dma, rx);
+	netdev_dbg(ctx->info->netdev,
+		   "Allocated %zu bytes for %u RX rings at %08lx (mapped %p)\n",
+		   size, num_queues, (unsigned long)rx_dma, rx);
 
-	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-		queue->tx_ring = tx + macb_tx_ring_size_per_queue(bp) * q;
-		queue->tx_ring_dma = tx_dma + macb_tx_ring_size_per_queue(bp) * q;
+	for (q = 0; q < num_queues; ++q) {
+		txq = &ctx->txq[q];
+		rxq = &ctx->rxq[q];
 
-		queue->rx_ring = rx + macb_rx_ring_size_per_queue(bp) * q;
-		queue->rx_ring_dma = rx_dma + macb_rx_ring_size_per_queue(bp) * q;
+		txq->ring = tx + macb_tx_ring_size_per_queue(ctx) * q;
+		txq->ring_dma = tx_dma + macb_tx_ring_size_per_queue(ctx) * q;
 
-		size = bp->tx_ring_size * sizeof(struct macb_tx_skb);
-		queue->tx_skb = kmalloc(size, GFP_KERNEL);
-		if (!queue->tx_skb)
-			goto out_err;
-	}
-	if (bp->macbgem_ops.mog_alloc_rx_buffers(bp))
-		goto out_err;
+		rxq->ring = rx + macb_rx_ring_size_per_queue(ctx) * q;
+		rxq->ring_dma = rx_dma + macb_rx_ring_size_per_queue(ctx) * q;
 
-	/* Required for tie off descriptor for PM cases */
-	if (!(bp->caps & MACB_CAPS_QUEUE_DISABLE)) {
-		bp->rx_ring_tieoff = dma_alloc_coherent(&bp->pdev->dev,
-							macb_dma_desc_get_size(bp),
-							&bp->rx_ring_tieoff_dma,
-							GFP_KERNEL);
-		if (!bp->rx_ring_tieoff)
+		size = ctx->tx_ring_size * sizeof(struct macb_tx_skb);
+		txq->skb = kmalloc(size, GFP_KERNEL);
+		if (!txq->skb)
 			goto out_err;
 	}
+	if (ctx->info->macbgem_ops.mog_alloc_rx_buffers(ctx))
+		goto out_err;
 
 	return 0;
 
 out_err:
-	macb_free_consistent(bp);
+	macb_free(ctx);
 	return -ENOMEM;
 }
 
-static void macb_init_tieoff(struct macb *bp)
+static struct macb_context *macb_context_alloc(struct macb *bp,
+					       unsigned int mtu,
+					       unsigned int rx_ring_size,
+					       unsigned int tx_ring_size)
 {
-	struct macb_dma_desc *desc = bp->rx_ring_tieoff;
+	struct macb_context *ctx;
+	int err;
 
-	if (bp->caps & MACB_CAPS_QUEUE_DISABLE)
-		return;
-	/* Setup a wrapping descriptor with no free slots
-	 * (WRAP and USED) to tie off/disable unused RX queues.
-	 */
-	macb_set_addr(bp, desc, MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED));
-	desc->ctrl = 0;
+	ctx = kzalloc_obj(*ctx);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	ctx->info = &bp->info;
+	ctx->rx_buffer_size = macb_rx_buffer_size(bp, mtu);
+	ctx->rx_ring_size = rx_ring_size;
+	ctx->tx_ring_size = tx_ring_size;
+
+	err = macb_alloc(ctx);
+	if (err) {
+		netdev_err(bp->netdev,
+			   "Unable to allocate DMA memory (error %d)\n", err);
+		kfree(ctx);
+		return ERR_PTR(err);
+	}
+
+	bp->macbgem_ops.mog_init_rings(ctx);
+
+	return ctx;
 }
 
-static void gem_init_rx_ring(struct macb_queue *queue)
+static void gem_init_rx_ring(struct macb_context *ctx, unsigned int q)
 {
-	queue->rx_tail = 0;
-	queue->rx_prepared_head = 0;
+	struct macb_rxq *rxq = &ctx->rxq[q];
 
-	gem_rx_refill(queue);
+	rxq->tail = 0;
+	rxq->prepared_head = 0;
+
+	gem_rx_refill(ctx, q);
 }
 
-static void gem_init_rings(struct macb *bp)
+static void gem_init_rings(struct macb_context *ctx)
 {
-	struct macb_queue *queue;
 	struct macb_dma_desc *desc = NULL;
+	struct macb_txq *txq;
 	unsigned int q;
 	int i;
 
-	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-		for (i = 0; i < bp->tx_ring_size; i++) {
-			desc = macb_tx_desc(queue, i);
-			macb_set_addr(bp, desc, 0);
+	for (q = 0; q < ctx->info->num_queues; ++q) {
+		txq = &ctx->txq[q];
+		for (i = 0; i < ctx->tx_ring_size; i++) {
+			desc = macb_tx_desc(ctx, q, i);
+			macb_set_addr(ctx->info, desc, 0);
 			desc->ctrl = MACB_BIT(TX_USED);
 		}
 		desc->ctrl |= MACB_BIT(TX_WRAP);
-		queue->tx_head = 0;
-		queue->tx_tail = 0;
+		txq->head = 0;
+		txq->tail = 0;
 
-		gem_init_rx_ring(queue);
+		gem_init_rx_ring(ctx, q);
 	}
-
-	macb_init_tieoff(bp);
 }
 
-static void macb_init_rings(struct macb *bp)
+static void macb_init_rings(struct macb_context *ctx)
 {
-	int i;
+	struct macb_txq *txq = &ctx->txq[0];
 	struct macb_dma_desc *desc = NULL;
+	int i;
 
-	macb_init_rx_ring(&bp->queues[0]);
+	macb_init_rx_ring(ctx, 0);
 
-	for (i = 0; i < bp->tx_ring_size; i++) {
-		desc = macb_tx_desc(&bp->queues[0], i);
-		macb_set_addr(bp, desc, 0);
+	for (i = 0; i < ctx->tx_ring_size; i++) {
+		desc = macb_tx_desc(ctx, 0, i);
+		macb_set_addr(ctx->info, desc, 0);
 		desc->ctrl = MACB_BIT(TX_USED);
 	}
-	bp->queues[0].tx_head = 0;
-	bp->queues[0].tx_tail = 0;
+	txq->head = 0;
+	txq->tail = 0;
 	desc->ctrl |= MACB_BIT(TX_WRAP);
-
-	macb_init_tieoff(bp);
 }
 
 static void macb_reset_hw(struct macb *bp)
@@ -2914,7 +3053,7 @@ static u32 macb_mdc_clk_div(struct macb *bp)
 	u32 config;
 	unsigned long pclk_hz;
 
-	if (macb_is_gem(bp))
+	if (macb_is_gem(&bp->info))
 		return gem_mdc_clk_div(bp);
 
 	pclk_hz = clk_get_rate(bp->pclk);
@@ -2936,7 +3075,7 @@ static u32 macb_mdc_clk_div(struct macb *bp)
  */
 static u32 macb_dbw(struct macb *bp)
 {
-	if (!macb_is_gem(bp))
+	if (!macb_is_gem(&bp->info))
 		return 0;
 
 	switch (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1))) {
@@ -2964,8 +3103,8 @@ static void macb_configure_dma(struct macb *bp)
 	unsigned int q;
 	u32 dmacfg;
 
-	buffer_size = bp->rx_buffer_size / RX_BUFFER_MULTIPLE;
-	if (macb_is_gem(bp)) {
+	buffer_size = bp->ctx->rx_buffer_size / RX_BUFFER_MULTIPLE;
+	if (macb_is_gem(&bp->info)) {
 		dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
 		for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
 			if (q)
@@ -2983,22 +3122,150 @@ static void macb_configure_dma(struct macb *bp)
 		else
 			dmacfg |= GEM_BIT(ENDIA_DESC); /* CPU in big endian */
 
-		if (bp->dev->features & NETIF_F_HW_CSUM)
+		if (bp->netdev->features & NETIF_F_HW_CSUM)
 			dmacfg |= GEM_BIT(TXCOEN);
 		else
 			dmacfg &= ~GEM_BIT(TXCOEN);
 
 		dmacfg &= ~GEM_BIT(ADDR64);
-		if (macb_dma64(bp))
+		if (macb_dma64(&bp->info))
 			dmacfg |= GEM_BIT(ADDR64);
-		if (macb_dma_ptp(bp))
+		if (macb_dma_ptp(&bp->info))
 			dmacfg |= GEM_BIT(RXEXT) | GEM_BIT(TXEXT);
-		netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
+		netdev_dbg(bp->netdev, "Cadence configure DMA with 0x%08x\n",
 			   dmacfg);
 		gem_writel(bp, DMACFG, dmacfg);
 	}
 }
 
+static void macb_context_swap_start(struct macb *bp)
+{
+	struct macb_queue *queue;
+	unsigned long flags;
+	unsigned int q;
+	u32 ctrl;
+
+	mutex_lock(&bp->mac_cfg_lock);
+
+	/* We cannot mask IRQs because they'll get re-armed by BH. So instead we
+	 * signal to IRQ handler it shouldn't drive BH features and should
+	 * self-disarm.
+	 */
+	spin_lock_irqsave(&bp->lock, flags);
+	bp->ctx_swap = true;
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	/* Drain BH features. HW is still active and usable at this point but
+	 * IRQs are being ignored.
+	 */
+
+	cancel_work_sync(&bp->hresp_err_bh_work);
+
+	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
+		/* Must be done before NAPI is disabled. */
+		cancel_work_sync(&queue->tx_error_task);
+
+		napi_disable(&queue->napi_rx);
+		napi_disable(&queue->napi_tx);
+	}
+
+	/* Must be done after napi_tx is disabled. */
+	cancel_delayed_work_sync(&bp->tx_lpi_work);
+
+	/* Can finally disable software Tx; need to wait until napi_tx and
+	 * tx_error_task cannot be scheduled as either might wakeup Tx.
+	 */
+	netif_tx_disable(bp->netdev);
+
+	/* Now that everything is stopped, clear DQL. */
+	for (q = 0; q < bp->num_queues; ++q)
+		netdev_tx_reset_queue(netdev_get_tx_queue(bp->netdev, q));
+
+	/* Safe to call outside bp->lock because bp->ctx_swap ensures the IRQ
+	 * handling is a no-op and all BH features are disabled.
+	 *
+	 * Whether it fails or not we'll disable TE/RE next.
+	 * We were just trying to be nice.
+	 */
+	macb_halt_tx(bp);
+
+	spin_lock_irqsave(&bp->lock, flags);
+
+	ctrl = macb_readl(bp, NCR);
+	macb_writel(bp, NCR, ctrl & ~(MACB_BIT(RE) | MACB_BIT(TE)));
+
+	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
+		queue_writel(queue, IDR, -1);
+		queue_readl(queue, ISR);
+		macb_queue_isr_clear(bp, queue, -1);
+	}
+
+	macb_writel(bp, TSR, -1);
+	macb_writel(bp, RSR, -1);
+
+	spin_unlock_irqrestore(&bp->lock, flags);
+}
+
+static void macb_context_swap_end(struct macb *bp,
+				  struct macb_context *new_ctx)
+{
+	struct macb_context *old_ctx;
+	struct macb_queue *queue;
+	unsigned long flags;
+	unsigned int q;
+	u32 ctrl;
+
+	lockdep_assert_held(&bp->mac_cfg_lock);
+
+	/* Swap contexts & give buffer pointers to HW. */
+
+	old_ctx = bp->ctx;
+	bp->ctx = new_ctx;
+	macb_init_buffers(bp);
+
+	/* Start NAPI, HW Tx/Rx and software Tx. */
+
+	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
+		napi_enable(&queue->napi_rx);
+		napi_enable(&queue->napi_tx);
+	}
+
+	spin_lock_irqsave(&bp->lock, flags);
+
+	/* Re-arm normal interrupt processing before enabling IRQs. */
+	bp->ctx_swap = false;
+
+	macb_configure_dma(bp);
+
+	if (bp->link_up) {
+		for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
+			queue_writel(queue, IER,
+				     bp->rx_intr_mask |
+				     MACB_TX_INT_FLAGS |
+				     MACB_BIT(HRESP));
+		}
+
+		ctrl = macb_readl(bp, NCR);
+		macb_writel(bp, NCR, ctrl | MACB_BIT(RE) | MACB_BIT(TE));
+	}
+
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	if (bp->link_up) {
+		netif_tx_wake_all_queues(bp->netdev);
+
+		if (bp->eee_active)
+			macb_txp_lpi_initial_defer(bp);
+	}
+
+	mutex_unlock(&bp->mac_cfg_lock);
+
+	/* Free old context. */
+
+	macb_free(old_ctx);
+	kfree(old_ctx);
+}
+
 static void macb_init_hw(struct macb *bp)
 {
 	u32 config;
@@ -3017,11 +3284,12 @@ static void macb_init_hw(struct macb *bp)
 		config |= MACB_BIT(JFRAME);	/* Enable jumbo frames */
 	else
 		config |= MACB_BIT(BIG);	/* Receive oversized frames */
-	if (bp->dev->flags & IFF_PROMISC)
+	if (bp->netdev->flags & IFF_PROMISC)
 		config |= MACB_BIT(CAF);	/* Copy All Frames */
-	else if (macb_is_gem(bp) && bp->dev->features & NETIF_F_RXCSUM)
+	else if (macb_is_gem(&bp->info) &&
+		 bp->netdev->features & NETIF_F_RXCSUM)
 		config |= GEM_BIT(RXCOEN);
-	if (!(bp->dev->flags & IFF_BROADCAST))
+	if (!(bp->netdev->flags & IFF_BROADCAST))
 		config |= MACB_BIT(NBC);	/* No BroadCast */
 	config |= macb_dbw(bp);
 	macb_writel(bp, NCFGR, config);
@@ -3095,17 +3363,17 @@ static int hash_get_index(__u8 *addr)
 }
 
 /* Add multicast addresses to the internal multicast-hash table. */
-static void macb_sethashtable(struct net_device *dev)
+static void macb_sethashtable(struct net_device *netdev)
 {
 	struct netdev_hw_addr *ha;
 	unsigned long mc_filter[2];
 	unsigned int bitnr;
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
 	mc_filter[0] = 0;
 	mc_filter[1] = 0;
 
-	netdev_for_each_mc_addr(ha, dev) {
+	netdev_for_each_mc_addr(ha, netdev) {
 		bitnr = hash_get_index(ha->addr);
 		mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
 	}
@@ -3115,39 +3383,39 @@ static void macb_sethashtable(struct net_device *dev)
 }
 
 /* Enable/Disable promiscuous and multicast modes. */
-static void macb_set_rx_mode(struct net_device *dev)
+static void macb_set_rx_mode(struct net_device *netdev)
 {
 	unsigned long cfg;
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
 	cfg = macb_readl(bp, NCFGR);
 
-	if (dev->flags & IFF_PROMISC) {
+	if (netdev->flags & IFF_PROMISC) {
 		/* Enable promiscuous mode */
 		cfg |= MACB_BIT(CAF);
 
 		/* Disable RX checksum offload */
-		if (macb_is_gem(bp))
+		if (macb_is_gem(&bp->info))
 			cfg &= ~GEM_BIT(RXCOEN);
 	} else {
 		/* Disable promiscuous mode */
 		cfg &= ~MACB_BIT(CAF);
 
 		/* Enable RX checksum offload only if requested */
-		if (macb_is_gem(bp) && dev->features & NETIF_F_RXCSUM)
+		if (macb_is_gem(&bp->info) && netdev->features & NETIF_F_RXCSUM)
 			cfg |= GEM_BIT(RXCOEN);
 	}
 
-	if (dev->flags & IFF_ALLMULTI) {
+	if (netdev->flags & IFF_ALLMULTI) {
 		/* Enable all multicast mode */
 		macb_or_gem_writel(bp, HRB, -1);
 		macb_or_gem_writel(bp, HRT, -1);
 		cfg |= MACB_BIT(NCFGR_MTI);
-	} else if (!netdev_mc_empty(dev)) {
+	} else if (!netdev_mc_empty(netdev)) {
 		/* Enable specific multicasts */
-		macb_sethashtable(dev);
+		macb_sethashtable(netdev);
 		cfg |= MACB_BIT(NCFGR_MTI);
-	} else if (dev->flags & (~IFF_ALLMULTI)) {
+	} else if (netdev->flags & (~IFF_ALLMULTI)) {
 		/* Disable all multicast mode */
 		macb_or_gem_writel(bp, HRB, 0);
 		macb_or_gem_writel(bp, HRT, 0);
@@ -3157,31 +3425,28 @@ static void macb_set_rx_mode(struct net_device *dev)
 	macb_writel(bp, NCFGR, cfg);
 }
 
-static int macb_open(struct net_device *dev)
+static int macb_open(struct net_device *netdev)
 {
-	size_t bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN;
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_queue *queue;
 	unsigned int q;
 	int err;
 
-	netdev_dbg(bp->dev, "open\n");
+	netdev_dbg(bp->netdev, "open\n");
 
 	err = pm_runtime_resume_and_get(&bp->pdev->dev);
 	if (err < 0)
 		return err;
 
-	/* RX buffers initialization */
-	macb_init_rx_buffer_size(bp, bufsz);
-
-	err = macb_alloc_consistent(bp);
-	if (err) {
-		netdev_err(dev, "Unable to allocate DMA memory (error %d)\n",
-			   err);
+	bp->ctx = macb_context_alloc(bp, netdev->mtu,
+				     bp->configured_rx_ring_size,
+				     bp->configured_tx_ring_size);
+	if (IS_ERR(bp->ctx)) {
+		err = PTR_ERR(bp->ctx);
+		bp->ctx = NULL;
 		goto pm_exit;
 	}
 
-	bp->macbgem_ops.mog_init_rings(bp);
 	macb_init_buffers(bp);
 
 	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
@@ -3203,10 +3468,10 @@ static int macb_open(struct net_device *dev)
 	if (err)
 		goto phy_off;
 
-	netif_tx_start_all_queues(dev);
+	netif_tx_start_all_queues(netdev);
 
 	if (bp->ptp_info)
-		bp->ptp_info->ptp_init(dev);
+		bp->ptp_info->ptp_init(netdev);
 
 	return 0;
 
@@ -3219,25 +3484,27 @@ static int macb_open(struct net_device *dev)
 		napi_disable(&queue->napi_rx);
 		napi_disable(&queue->napi_tx);
 	}
-	macb_free_consistent(bp);
+	macb_free(bp->ctx);
+	kfree(bp->ctx);
+	bp->ctx = NULL;
 pm_exit:
 	pm_runtime_put_sync(&bp->pdev->dev);
 	return err;
 }
 
-static int macb_close(struct net_device *dev)
+static int macb_close(struct net_device *netdev)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_queue *queue;
 	unsigned long flags;
 	unsigned int q;
 
-	netif_tx_stop_all_queues(dev);
+	netif_tx_stop_all_queues(netdev);
 
 	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
 		napi_disable(&queue->napi_rx);
 		napi_disable(&queue->napi_tx);
-		netdev_tx_reset_queue(netdev_get_tx_queue(dev, q));
+		netdev_tx_reset_queue(netdev_get_tx_queue(netdev, q));
 	}
 
 	cancel_delayed_work_sync(&bp->tx_lpi_work);
@@ -3249,38 +3516,58 @@ static int macb_close(struct net_device *dev)
 
 	spin_lock_irqsave(&bp->lock, flags);
 	macb_reset_hw(bp);
-	netif_carrier_off(dev);
+	netif_carrier_off(netdev);
 	spin_unlock_irqrestore(&bp->lock, flags);
 
-	macb_free_consistent(bp);
+	macb_free(bp->ctx);
+	kfree(bp->ctx);
+	bp->ctx = NULL;
 
 	if (bp->ptp_info)
-		bp->ptp_info->ptp_remove(dev);
+		bp->ptp_info->ptp_remove(netdev);
 
 	pm_runtime_put(&bp->pdev->dev);
 
 	return 0;
 }
 
-static int macb_change_mtu(struct net_device *dev, int new_mtu)
+static int macb_change_mtu(struct net_device *netdev, int new_mtu)
 {
-	if (netif_running(dev))
-		return -EBUSY;
+	struct macb *bp = netdev_priv(netdev);
+	bool running = netif_running(netdev);
+	struct macb_context *new_ctx;
+
+	if (running) {
+		/* Context swapping is not supported for AT91. */
+		if (bp->caps & MACB_CAPS_MACB_IS_EMAC)
+			return -EBUSY;
 
-	WRITE_ONCE(dev->mtu, new_mtu);
+		new_ctx = macb_context_alloc(bp, new_mtu,
+					     bp->configured_rx_ring_size,
+					     bp->configured_tx_ring_size);
+		if (IS_ERR(new_ctx))
+			return PTR_ERR(new_ctx);
+
+		macb_context_swap_start(bp);
+	}
+
+	WRITE_ONCE(netdev->mtu, new_mtu);
+
+	if (running)
+		macb_context_swap_end(bp, new_ctx);
 
 	return 0;
 }
 
-static int macb_set_mac_addr(struct net_device *dev, void *addr)
+static int macb_set_mac_addr(struct net_device *netdev, void *addr)
 {
 	int err;
 
-	err = eth_mac_addr(dev, addr);
+	err = eth_mac_addr(netdev, addr);
 	if (err < 0)
 		return err;
 
-	macb_set_hwaddr(netdev_priv(dev));
+	macb_set_hwaddr(netdev_priv(netdev));
 	return 0;
 }
 
@@ -3318,7 +3605,7 @@ static void gem_get_stats(struct macb *bp, struct rtnl_link_stats64 *nstat)
 	struct gem_stats *hwstat = &bp->hw_stats.gem;
 
 	spin_lock_irq(&bp->stats_lock);
-	if (netif_running(bp->dev))
+	if (netif_running(bp->netdev))
 		gem_update_stats(bp);
 
 	nstat->rx_errors = (hwstat->rx_frame_check_sequence_errors +
@@ -3351,10 +3638,10 @@ static void gem_get_stats(struct macb *bp, struct rtnl_link_stats64 *nstat)
 	spin_unlock_irq(&bp->stats_lock);
 }
 
-static void gem_get_ethtool_stats(struct net_device *dev,
+static void gem_get_ethtool_stats(struct net_device *netdev,
 				  struct ethtool_stats *stats, u64 *data)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
 	spin_lock_irq(&bp->stats_lock);
 	gem_update_stats(bp);
@@ -3363,9 +3650,9 @@ static void gem_get_ethtool_stats(struct net_device *dev,
 	spin_unlock_irq(&bp->stats_lock);
 }
 
-static int gem_get_sset_count(struct net_device *dev, int sset)
+static int gem_get_sset_count(struct net_device *netdev, int sset)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
 	switch (sset) {
 	case ETH_SS_STATS:
@@ -3375,9 +3662,9 @@ static int gem_get_sset_count(struct net_device *dev, int sset)
 	}
 }
 
-static void gem_get_ethtool_strings(struct net_device *dev, u32 sset, u8 *p)
+static void gem_get_ethtool_strings(struct net_device *netdev, u32 sset, u8 *p)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_queue *queue;
 	unsigned int i;
 	unsigned int q;
@@ -3396,14 +3683,14 @@ static void gem_get_ethtool_strings(struct net_device *dev, u32 sset, u8 *p)
 	}
 }
 
-static void macb_get_stats(struct net_device *dev,
+static void macb_get_stats(struct net_device *netdev,
 			   struct rtnl_link_stats64 *nstat)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_stats *hwstat = &bp->hw_stats.macb;
 
-	netdev_stats_to_stats64(nstat, &bp->dev->stats);
-	if (macb_is_gem(bp)) {
+	netdev_stats_to_stats64(nstat, &bp->netdev->stats);
+	if (macb_is_gem(&bp->info)) {
 		gem_get_stats(bp, nstat);
 		return;
 	}
@@ -3446,10 +3733,10 @@ static void macb_get_stats(struct net_device *dev,
 	spin_unlock_irq(&bp->stats_lock);
 }
 
-static void macb_get_pause_stats(struct net_device *dev,
+static void macb_get_pause_stats(struct net_device *netdev,
 				 struct ethtool_pause_stats *pause_stats)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_stats *hwstat = &bp->hw_stats.macb;
 
 	spin_lock_irq(&bp->stats_lock);
@@ -3459,10 +3746,10 @@ static void macb_get_pause_stats(struct net_device *dev,
 	spin_unlock_irq(&bp->stats_lock);
 }
 
-static void gem_get_pause_stats(struct net_device *dev,
+static void gem_get_pause_stats(struct net_device *netdev,
 				struct ethtool_pause_stats *pause_stats)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct gem_stats *hwstat = &bp->hw_stats.gem;
 
 	spin_lock_irq(&bp->stats_lock);
@@ -3472,10 +3759,10 @@ static void gem_get_pause_stats(struct net_device *dev,
 	spin_unlock_irq(&bp->stats_lock);
 }
 
-static void macb_get_eth_mac_stats(struct net_device *dev,
+static void macb_get_eth_mac_stats(struct net_device *netdev,
 				   struct ethtool_eth_mac_stats *mac_stats)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_stats *hwstat = &bp->hw_stats.macb;
 
 	spin_lock_irq(&bp->stats_lock);
@@ -3497,10 +3784,10 @@ static void macb_get_eth_mac_stats(struct net_device *dev,
 	spin_unlock_irq(&bp->stats_lock);
 }
 
-static void gem_get_eth_mac_stats(struct net_device *dev,
+static void gem_get_eth_mac_stats(struct net_device *netdev,
 				  struct ethtool_eth_mac_stats *mac_stats)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct gem_stats *hwstat = &bp->hw_stats.gem;
 
 	spin_lock_irq(&bp->stats_lock);
@@ -3530,10 +3817,10 @@ static void gem_get_eth_mac_stats(struct net_device *dev,
 }
 
 /* TODO: Report SQE test errors when added to phy_stats */
-static void macb_get_eth_phy_stats(struct net_device *dev,
+static void macb_get_eth_phy_stats(struct net_device *netdev,
 				   struct ethtool_eth_phy_stats *phy_stats)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_stats *hwstat = &bp->hw_stats.macb;
 
 	spin_lock_irq(&bp->stats_lock);
@@ -3542,10 +3829,10 @@ static void macb_get_eth_phy_stats(struct net_device *dev,
 	spin_unlock_irq(&bp->stats_lock);
 }
 
-static void gem_get_eth_phy_stats(struct net_device *dev,
+static void gem_get_eth_phy_stats(struct net_device *netdev,
 				  struct ethtool_eth_phy_stats *phy_stats)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct gem_stats *hwstat = &bp->hw_stats.gem;
 
 	spin_lock_irq(&bp->stats_lock);
@@ -3554,11 +3841,11 @@ static void gem_get_eth_phy_stats(struct net_device *dev,
 	spin_unlock_irq(&bp->stats_lock);
 }
 
-static void macb_get_rmon_stats(struct net_device *dev,
+static void macb_get_rmon_stats(struct net_device *netdev,
 				struct ethtool_rmon_stats *rmon_stats,
 				const struct ethtool_rmon_hist_range **ranges)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_stats *hwstat = &bp->hw_stats.macb;
 
 	spin_lock_irq(&bp->stats_lock);
@@ -3580,11 +3867,11 @@ static const struct ethtool_rmon_hist_range gem_rmon_ranges[] = {
 	{ },
 };
 
-static void gem_get_rmon_stats(struct net_device *dev,
+static void gem_get_rmon_stats(struct net_device *netdev,
 			       struct ethtool_rmon_stats *rmon_stats,
 			       const struct ethtool_rmon_hist_range **ranges)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct gem_stats *hwstat = &bp->hw_stats.gem;
 
 	spin_lock_irq(&bp->stats_lock);
@@ -3615,18 +3902,25 @@ static int macb_get_regs_len(struct net_device *netdev)
 	return MACB_GREGS_NBR * sizeof(u32);
 }
 
-static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+static void macb_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
 			  void *p)
 {
-	struct macb *bp = netdev_priv(dev);
-	unsigned int tail, head;
+	dma_addr_t tx_dma_tail = 0, tx_dma_head = 0;
+	struct macb *bp = netdev_priv(netdev);
+	unsigned int tail = 0, head = 0;
+	struct macb_txq *txq;
 	u32 *regs_buff = p;
 
 	regs->version = (macb_readl(bp, MID) & ((1 << MACB_REV_SIZE) - 1))
 			| MACB_GREGS_VERSION;
 
-	tail = macb_tx_ring_wrap(bp, bp->queues[0].tx_tail);
-	head = macb_tx_ring_wrap(bp, bp->queues[0].tx_head);
+	if (bp->ctx) {
+		txq = &bp->ctx->txq[0];
+		tail = macb_tx_ring_wrap(bp->ctx, txq->tail);
+		head = macb_tx_ring_wrap(bp->ctx, txq->head);
+		tx_dma_tail = macb_tx_dma(&bp->queues[0], tail);
+		tx_dma_head = macb_tx_dma(&bp->queues[0], head);
+	}
 
 	regs_buff[0]  = macb_readl(bp, NCR);
 	regs_buff[1]  = macb_or_gem_readl(bp, NCFGR);
@@ -3639,12 +3933,12 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 
 	regs_buff[8]  = tail;
 	regs_buff[9]  = head;
-	regs_buff[10] = macb_tx_dma(&bp->queues[0], tail);
-	regs_buff[11] = macb_tx_dma(&bp->queues[0], head);
+	regs_buff[10] = tx_dma_tail;
+	regs_buff[11] = tx_dma_head;
 
 	if (!(bp->caps & MACB_CAPS_USRIO_DISABLED))
 		regs_buff[12] = macb_or_gem_readl(bp, USRIO);
-	if (macb_is_gem(bp))
+	if (macb_is_gem(&bp->info))
 		regs_buff[13] = gem_readl(bp, DMACFG);
 }
 
@@ -3705,8 +3999,8 @@ static void macb_get_ringparam(struct net_device *netdev,
 	ring->rx_max_pending = MAX_RX_RING_SIZE;
 	ring->tx_max_pending = MAX_TX_RING_SIZE;
 
-	ring->rx_pending = bp->rx_ring_size;
-	ring->tx_pending = bp->tx_ring_size;
+	ring->rx_pending = bp->configured_rx_ring_size;
+	ring->tx_pending = bp->configured_tx_ring_size;
 }
 
 static int macb_set_ringparam(struct net_device *netdev,
@@ -3714,9 +4008,13 @@ static int macb_set_ringparam(struct net_device *netdev,
 			      struct kernel_ethtool_ringparam *kernel_ring,
 			      struct netlink_ext_ack *extack)
 {
+	unsigned int new_rx_size, new_tx_size;
 	struct macb *bp = netdev_priv(netdev);
-	u32 new_rx_size, new_tx_size;
-	unsigned int reset = 0;
+	bool running = netif_running(netdev);
+	struct macb_context *new_ctx;
+
+	if (bp->caps & MACB_CAPS_MACB_IS_EMAC)
+		return -EOPNOTSUPP;
 
 	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 		return -EINVAL;
@@ -3729,22 +4027,26 @@ static int macb_set_ringparam(struct net_device *netdev,
 			      MIN_TX_RING_SIZE, MAX_TX_RING_SIZE);
 	new_tx_size = roundup_pow_of_two(new_tx_size);
 
-	if ((new_tx_size == bp->tx_ring_size) &&
-	    (new_rx_size == bp->rx_ring_size)) {
+	if (new_tx_size == bp->configured_tx_ring_size &&
+	    new_rx_size == bp->configured_rx_ring_size) {
 		/* nothing to do */
 		return 0;
 	}
 
-	if (netif_running(bp->dev)) {
-		reset = 1;
-		macb_close(bp->dev);
+	if (running) {
+		new_ctx = macb_context_alloc(bp, netdev->mtu,
+					     new_rx_size, new_tx_size);
+		if (IS_ERR(new_ctx))
+			return PTR_ERR(new_ctx);
+
+		macb_context_swap_start(bp);
 	}
 
-	bp->rx_ring_size = new_rx_size;
-	bp->tx_ring_size = new_tx_size;
+	bp->configured_rx_ring_size = new_rx_size;
+	bp->configured_tx_ring_size = new_tx_size;
 
-	if (reset)
-		macb_open(bp->dev);
+	if (running)
+		macb_context_swap_end(bp, new_ctx);
 
 	return 0;
 }
@@ -3771,13 +4073,13 @@ static s32 gem_get_ptp_max_adj(void)
 	return 64000000;
 }
 
-static int gem_get_ts_info(struct net_device *dev,
+static int gem_get_ts_info(struct net_device *netdev,
 			   struct kernel_ethtool_ts_info *info)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
-	if (!macb_dma_ptp(bp)) {
-		ethtool_op_get_ts_info(dev, info);
+	if (!macb_dma_ptp(&bp->info)) {
+		ethtool_op_get_ts_info(netdev, info);
 		return 0;
 	}
 
@@ -3824,7 +4126,7 @@ static int macb_get_ts_info(struct net_device *netdev,
 
 static void gem_enable_flow_filters(struct macb *bp, bool enable)
 {
-	struct net_device *netdev = bp->dev;
+	struct net_device *netdev = bp->netdev;
 	struct ethtool_rx_fs_item *item;
 	u32 t2_scr;
 	int num_t2_scr;
@@ -3877,7 +4179,7 @@ static void gem_prog_cmp_regs(struct macb *bp, struct ethtool_rx_flow_spec *fs)
 	bool cmp_b = false;
 	bool cmp_c = false;
 
-	if (!macb_is_gem(bp))
+	if (!macb_is_gem(&bp->info))
 		return;
 
 	tp4sp_v = &(fs->h_u.tcp_ip4_spec);
@@ -4154,16 +4456,16 @@ static const struct ethtool_ops macb_ethtool_ops = {
 	.set_ringparam		= macb_set_ringparam,
 };
 
-static int macb_get_eee(struct net_device *dev, struct ethtool_keee *eee)
+static int macb_get_eee(struct net_device *netdev, struct ethtool_keee *eee)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
 	return phylink_ethtool_get_eee(bp->phylink, eee);
 }
 
-static int macb_set_eee(struct net_device *dev, struct ethtool_keee *eee)
+static int macb_set_eee(struct net_device *netdev, struct ethtool_keee *eee)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
 	return phylink_ethtool_set_eee(bp->phylink, eee);
 }
@@ -4194,43 +4496,43 @@ static const struct ethtool_ops gem_ethtool_ops = {
 	.set_eee		= macb_set_eee,
 };
 
-static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int macb_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
-	if (!netif_running(dev))
+	if (!netif_running(netdev))
 		return -EINVAL;
 
 	return phylink_mii_ioctl(bp->phylink, rq, cmd);
 }
 
-static int macb_hwtstamp_get(struct net_device *dev,
+static int macb_hwtstamp_get(struct net_device *netdev,
 			     struct kernel_hwtstamp_config *cfg)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
-	if (!netif_running(dev))
+	if (!netif_running(netdev))
 		return -EINVAL;
 
 	if (!bp->ptp_info)
 		return -EOPNOTSUPP;
 
-	return bp->ptp_info->get_hwtst(dev, cfg);
+	return bp->ptp_info->get_hwtst(netdev, cfg);
 }
 
-static int macb_hwtstamp_set(struct net_device *dev,
+static int macb_hwtstamp_set(struct net_device *netdev,
 			     struct kernel_hwtstamp_config *cfg,
 			     struct netlink_ext_ack *extack)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
-	if (!netif_running(dev))
+	if (!netif_running(netdev))
 		return -EINVAL;
 
 	if (!bp->ptp_info)
 		return -EOPNOTSUPP;
 
-	return bp->ptp_info->set_hwtst(dev, cfg, extack);
+	return bp->ptp_info->set_hwtst(netdev, cfg, extack);
 }
 
 static inline void macb_set_txcsum_feature(struct macb *bp,
@@ -4238,7 +4540,7 @@ static inline void macb_set_txcsum_feature(struct macb *bp,
 {
 	u32 val;
 
-	if (!macb_is_gem(bp))
+	if (!macb_is_gem(&bp->info))
 		return;
 
 	val = gem_readl(bp, DMACFG);
@@ -4253,10 +4555,10 @@ static inline void macb_set_txcsum_feature(struct macb *bp,
 static inline void macb_set_rxcsum_feature(struct macb *bp,
 					   netdev_features_t features)
 {
-	struct net_device *netdev = bp->dev;
+	struct net_device *netdev = bp->netdev;
 	u32 val;
 
-	if (!macb_is_gem(bp))
+	if (!macb_is_gem(&bp->info))
 		return;
 
 	val = gem_readl(bp, NCFGR);
@@ -4271,7 +4573,7 @@ static inline void macb_set_rxcsum_feature(struct macb *bp,
 static inline void macb_set_rxflow_feature(struct macb *bp,
 					   netdev_features_t features)
 {
-	if (!macb_is_gem(bp))
+	if (!macb_is_gem(&bp->info))
 		return;
 
 	gem_enable_flow_filters(bp, !!(features & NETIF_F_NTUPLE));
@@ -4300,7 +4602,7 @@ static int macb_set_features(struct net_device *netdev,
 
 static void macb_restore_features(struct macb *bp)
 {
-	struct net_device *netdev = bp->dev;
+	struct net_device *netdev = bp->netdev;
 	netdev_features_t features = netdev->features;
 	struct ethtool_rx_fs_item *item;
 
@@ -4317,14 +4619,14 @@ static void macb_restore_features(struct macb *bp)
 	macb_set_rxflow_feature(bp, features);
 }
 
-static int macb_taprio_setup_replace(struct net_device *ndev,
+static int macb_taprio_setup_replace(struct net_device *netdev,
 				     struct tc_taprio_qopt_offload *conf)
 {
 	u64 total_on_time = 0, start_time_sec = 0, start_time = conf->base_time;
 	u32 configured_queues = 0, speed = 0, start_time_nsec;
 	struct macb_queue_enst_config *enst_queue;
 	struct tc_taprio_sched_entry *entry;
-	struct macb *bp = netdev_priv(ndev);
+	struct macb *bp = netdev_priv(netdev);
 	struct ethtool_link_ksettings kset;
 	struct macb_queue *queue;
 	u32 queue_mask;
@@ -4333,13 +4635,13 @@ static int macb_taprio_setup_replace(struct net_device *ndev,
 	int err;
 
 	if (conf->num_entries > bp->num_queues) {
-		netdev_err(ndev, "Too many TAPRIO entries: %zu > %d queues\n",
+		netdev_err(netdev, "Too many TAPRIO entries: %zu > %d queues\n",
 			   conf->num_entries, bp->num_queues);
 		return -EINVAL;
 	}
 
 	if (conf->base_time < 0) {
-		netdev_err(ndev, "Invalid base_time: must be 0 or positive, got %lld\n",
+		netdev_err(netdev, "Invalid base_time: must be 0 or positive, got %lld\n",
 			   conf->base_time);
 		return -ERANGE;
 	}
@@ -4347,13 +4649,13 @@ static int macb_taprio_setup_replace(struct net_device *ndev,
 	/* Get the current link speed */
 	err = phylink_ethtool_ksettings_get(bp->phylink, &kset);
 	if (unlikely(err)) {
-		netdev_err(ndev, "Failed to get link settings: %d\n", err);
+		netdev_err(netdev, "Failed to get link settings: %d\n", err);
 		return err;
 	}
 
 	speed = kset.base.speed;
 	if (unlikely(speed <= 0)) {
-		netdev_err(ndev, "Invalid speed: %d\n", speed);
+		netdev_err(netdev, "Invalid speed: %d\n", speed);
 		return -EINVAL;
 	}
 
@@ -4366,7 +4668,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,
 		entry = &conf->entries[i];
 
 		if (entry->command != TC_TAPRIO_CMD_SET_GATES) {
-			netdev_err(ndev, "Entry %zu: unsupported command %d\n",
+			netdev_err(netdev, "Entry %zu: unsupported command %d\n",
 				   i, entry->command);
 			err = -EOPNOTSUPP;
 			goto cleanup;
@@ -4374,7 +4676,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,
 
 		/* Validate gate_mask: must be nonzero, single queue, and within range */
 		if (!is_power_of_2(entry->gate_mask)) {
-			netdev_err(ndev, "Entry %zu: gate_mask 0x%x is not a power of 2 (only one queue per entry allowed)\n",
+			netdev_err(netdev, "Entry %zu: gate_mask 0x%x is not a power of 2 (only one queue per entry allowed)\n",
 				   i, entry->gate_mask);
 			err = -EINVAL;
 			goto cleanup;
@@ -4383,7 +4685,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,
 		/* gate_mask must not select queues outside the valid queues */
 		queue_id = order_base_2(entry->gate_mask);
 		if (queue_id >= bp->num_queues) {
-			netdev_err(ndev, "Entry %zu: gate_mask 0x%x exceeds queue range (max_queues=%d)\n",
+			netdev_err(netdev, "Entry %zu: gate_mask 0x%x exceeds queue range (max_queues=%d)\n",
 				   i, entry->gate_mask, bp->num_queues);
 			err = -EINVAL;
 			goto cleanup;
@@ -4393,7 +4695,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,
 		start_time_sec = start_time;
 		start_time_nsec = do_div(start_time_sec, NSEC_PER_SEC);
 		if (start_time_sec > GENMASK(GEM_START_TIME_SEC_SIZE - 1, 0)) {
-			netdev_err(ndev, "Entry %zu: Start time %llu s exceeds hardware limit\n",
+			netdev_err(netdev, "Entry %zu: Start time %llu s exceeds hardware limit\n",
 				   i, start_time_sec);
 			err = -ERANGE;
 			goto cleanup;
@@ -4401,7 +4703,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,
 
 		/* Check for on time limit */
 		if (entry->interval > enst_max_hw_interval(speed)) {
-			netdev_err(ndev, "Entry %zu: interval %u ns exceeds hardware limit %llu ns\n",
+			netdev_err(netdev, "Entry %zu: interval %u ns exceeds hardware limit %llu ns\n",
 				   i, entry->interval, enst_max_hw_interval(speed));
 			err = -ERANGE;
 			goto cleanup;
@@ -4409,7 +4711,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,
 
 		/* Check for off time limit*/
 		if ((conf->cycle_time - entry->interval) > enst_max_hw_interval(speed)) {
-			netdev_err(ndev, "Entry %zu: off_time %llu ns exceeds hardware limit %llu ns\n",
+			netdev_err(netdev, "Entry %zu: off_time %llu ns exceeds hardware limit %llu ns\n",
 				   i, conf->cycle_time - entry->interval,
 				   enst_max_hw_interval(speed));
 			err = -ERANGE;
@@ -4432,13 +4734,13 @@ static int macb_taprio_setup_replace(struct net_device *ndev,
 
 	/* Check total interval doesn't exceed cycle time */
 	if (total_on_time > conf->cycle_time) {
-		netdev_err(ndev, "Total ON %llu ns exceeds cycle time %llu ns\n",
+		netdev_err(netdev, "Total ON %llu ns exceeds cycle time %llu ns\n",
 			   total_on_time, conf->cycle_time);
 		err = -EINVAL;
 		goto cleanup;
 	}
 
-	netdev_dbg(ndev, "TAPRIO setup: %zu entries, base_time=%lld ns, cycle_time=%llu ns\n",
+	netdev_dbg(netdev, "TAPRIO setup: %zu entries, base_time=%lld ns, cycle_time=%llu ns\n",
 		   conf->num_entries, conf->base_time, conf->cycle_time);
 
 	/* All validations passed - proceed with hardware configuration */
@@ -4463,7 +4765,7 @@ static int macb_taprio_setup_replace(struct net_device *ndev,
 		gem_writel(bp, ENST_CONTROL, configured_queues);
 	}
 
-	netdev_info(ndev, "TAPRIO configuration completed successfully: %zu entries, %d queues configured\n",
+	netdev_info(netdev, "TAPRIO configuration completed successfully: %zu entries, %d queues configured\n",
 		    conf->num_entries, hweight32(configured_queues));
 
 cleanup:
@@ -4471,14 +4773,14 @@ static int macb_taprio_setup_replace(struct net_device *ndev,
 	return err;
 }
 
-static void macb_taprio_destroy(struct net_device *ndev)
+static void macb_taprio_destroy(struct net_device *netdev)
 {
-	struct macb *bp = netdev_priv(ndev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_queue *queue;
 	u32 queue_mask;
 	unsigned int q;
 
-	netdev_reset_tc(ndev);
+	netdev_reset_tc(netdev);
 	queue_mask = BIT_U32(bp->num_queues) - 1;
 
 	scoped_guard(spinlock_irqsave, &bp->lock) {
@@ -4493,30 +4795,30 @@ static void macb_taprio_destroy(struct net_device *ndev)
 			queue_writel(queue, ENST_OFF_TIME, 0);
 		}
 	}
-	netdev_info(ndev, "TAPRIO destroy: All gates disabled\n");
+	netdev_info(netdev, "TAPRIO destroy: All gates disabled\n");
 }
 
-static int macb_setup_taprio(struct net_device *ndev,
+static int macb_setup_taprio(struct net_device *netdev,
 			     struct tc_taprio_qopt_offload *taprio)
 {
-	struct macb *bp = netdev_priv(ndev);
+	struct macb *bp = netdev_priv(netdev);
 	int err = 0;
 
-	if (unlikely(!(ndev->hw_features & NETIF_F_HW_TC)))
+	if (unlikely(!(netdev->hw_features & NETIF_F_HW_TC)))
 		return -EOPNOTSUPP;
 
 	/* Check if Device is in runtime suspend */
 	if (unlikely(pm_runtime_suspended(&bp->pdev->dev))) {
-		netdev_err(ndev, "Device is in runtime suspend\n");
+		netdev_err(netdev, "Device is in runtime suspend\n");
 		return -EOPNOTSUPP;
 	}
 
 	switch (taprio->cmd) {
 	case TAPRIO_CMD_REPLACE:
-		err = macb_taprio_setup_replace(ndev, taprio);
+		err = macb_taprio_setup_replace(netdev, taprio);
 		break;
 	case TAPRIO_CMD_DESTROY:
-		macb_taprio_destroy(ndev);
+		macb_taprio_destroy(netdev);
 		break;
 	default:
 		err = -EOPNOTSUPP;
@@ -4525,23 +4827,23 @@ static int macb_setup_taprio(struct net_device *ndev,
 	return err;
 }
 
-static int macb_setup_tc(struct net_device *dev, enum tc_setup_type type,
+static int macb_setup_tc(struct net_device *netdev, enum tc_setup_type type,
 			 void *type_data)
 {
-	if (!dev || !type_data)
+	if (!netdev || !type_data)
 		return -EINVAL;
 
 	switch (type) {
 	case TC_SETUP_QDISC_TAPRIO:
-		return macb_setup_taprio(dev, type_data);
+		return macb_setup_taprio(netdev, type_data);
 	default:
 		return -EOPNOTSUPP;
 	}
 }
 
-static void macb_tx_timeout(struct net_device *dev, unsigned int q)
+static void macb_tx_timeout(struct net_device *netdev, unsigned int q)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
 	macb_tx_restart(&bp->queues[q]);
 }
@@ -4598,7 +4900,7 @@ static void macb_configure_caps(struct macb *bp,
 			bp->caps |= MACB_CAPS_FIFO_MODE;
 		if (GEM_BFEXT(PBUF_RSC, gem_readl(bp, DCFG6)))
 			bp->caps |= MACB_CAPS_RSC;
-		if (gem_has_ptp(bp)) {
+		if (gem_has_ptp(&bp->info)) {
 			if (!GEM_BFEXT(TSU, gem_readl(bp, DCFG5)))
 				dev_err(&bp->pdev->dev,
 					"GEM doesn't support hardware ptp.\n");
@@ -4749,16 +5051,13 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
 
 static int macb_init_dflt(struct platform_device *pdev)
 {
-	struct net_device *dev = platform_get_drvdata(pdev);
+	struct net_device *netdev = platform_get_drvdata(pdev);
 	unsigned int hw_q, q;
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	struct macb_queue *queue;
 	int err;
 	u32 val, reg;
 
-	bp->tx_ring_size = DEFAULT_TX_RING_SIZE;
-	bp->rx_ring_size = DEFAULT_RX_RING_SIZE;
-
 	/* set the queue register mapping once for all: queue0 has a special
 	 * register mapping but we don't want to test the queue index then
 	 * compute the corresponding register offset at run time.
@@ -4767,8 +5066,8 @@ static int macb_init_dflt(struct platform_device *pdev)
 		queue = &bp->queues[q];
 		queue->bp = bp;
 		spin_lock_init(&queue->tx_ptr_lock);
-		netif_napi_add(dev, &queue->napi_rx, macb_rx_poll);
-		netif_napi_add_tx(dev, &queue->napi_tx, macb_tx_poll);
+		netif_napi_add(netdev, &queue->napi_rx, macb_rx_poll);
+		netif_napi_add_tx(netdev, &queue->napi_tx, macb_tx_poll);
 		if (hw_q) {
 			queue->ISR  = GEM_ISR(hw_q - 1);
 			queue->IER  = GEM_IER(hw_q - 1);
@@ -4798,7 +5097,7 @@ static int macb_init_dflt(struct platform_device *pdev)
 		 */
 		queue->irq = platform_get_irq(pdev, q);
 		err = devm_request_irq(&pdev->dev, queue->irq, macb_interrupt,
-				       IRQF_SHARED, dev->name, queue);
+				       IRQF_SHARED, netdev->name, queue);
 		if (err) {
 			dev_err(&pdev->dev,
 				"Unable to request IRQ %d (error %d)\n",
@@ -4810,47 +5109,47 @@ static int macb_init_dflt(struct platform_device *pdev)
 		q++;
 	}
 
-	dev->netdev_ops = &macb_netdev_ops;
+	netdev->netdev_ops = &macb_netdev_ops;
 
 	/* setup appropriated routines according to adapter type */
-	if (macb_is_gem(bp)) {
+	if (macb_is_gem(&bp->info)) {
 		bp->macbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers;
 		bp->macbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers;
 		bp->macbgem_ops.mog_init_rings = gem_init_rings;
 		bp->macbgem_ops.mog_rx = gem_rx;
-		dev->ethtool_ops = &gem_ethtool_ops;
+		netdev->ethtool_ops = &gem_ethtool_ops;
 	} else {
 		bp->macbgem_ops.mog_alloc_rx_buffers = macb_alloc_rx_buffers;
 		bp->macbgem_ops.mog_free_rx_buffers = macb_free_rx_buffers;
 		bp->macbgem_ops.mog_init_rings = macb_init_rings;
 		bp->macbgem_ops.mog_rx = macb_rx;
-		dev->ethtool_ops = &macb_ethtool_ops;
+		netdev->ethtool_ops = &macb_ethtool_ops;
 	}
 
-	netdev_sw_irq_coalesce_default_on(dev);
+	netdev_sw_irq_coalesce_default_on(netdev);
 
-	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+	netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
 	/* Set features */
-	dev->hw_features = NETIF_F_SG;
+	netdev->hw_features = NETIF_F_SG;
 
 	/* Check LSO capability; runtime detection can be overridden by a cap
 	 * flag if the hardware is known to be buggy
 	 */
 	if (!(bp->caps & MACB_CAPS_NO_LSO) &&
 	    GEM_BFEXT(PBUF_LSO, gem_readl(bp, DCFG6)))
-		dev->hw_features |= MACB_NETIF_LSO;
+		netdev->hw_features |= MACB_NETIF_LSO;
 
 	/* Checksum offload is only available on gem with packet buffer */
-	if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE))
-		dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+	if (macb_is_gem(&bp->info) && !(bp->caps & MACB_CAPS_FIFO_MODE))
+		netdev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
 	if (bp->caps & MACB_CAPS_SG_DISABLED)
-		dev->hw_features &= ~NETIF_F_SG;
+		netdev->hw_features &= ~NETIF_F_SG;
 	/* Enable HW_TC if hardware supports QBV */
 	if (bp->caps & MACB_CAPS_QBV)
-		dev->hw_features |= NETIF_F_HW_TC;
+		netdev->hw_features |= NETIF_F_HW_TC;
 
-	dev->features = dev->hw_features;
+	netdev->features = netdev->hw_features;
 
 	/* Check RX Flow Filters support.
 	 * Max Rx flows set by availability of screeners & compare regs:
@@ -4868,7 +5167,7 @@ static int macb_init_dflt(struct platform_device *pdev)
 			reg = GEM_BFINS(ETHTCMP, (uint16_t)ETH_P_IP, reg);
 			gem_writel_n(bp, ETHT, SCRT2_ETHT, reg);
 			/* Filtering is supported in hw but don't enable it in kernel now */
-			dev->hw_features |= NETIF_F_NTUPLE;
+			netdev->hw_features |= NETIF_F_NTUPLE;
 			/* init Rx flow definitions */
 			bp->rx_fs_list.count = 0;
 			spin_lock_init(&bp->rx_fs_lock);
@@ -4954,79 +5253,81 @@ static const struct macb_usrio_config at91_default_usrio = {
 	.clken = MACB_BIT(CLKEN),
 };
 
+/* max number of receive buffers */
+#define AT91ETHER_MAX_RX_DESCR	9
+
 #if defined(CONFIG_OF)
 /* 1518 rounded up */
 #define AT91ETHER_MAX_RBUFF_SZ	0x600
-/* max number of receive buffers */
-#define AT91ETHER_MAX_RX_DESCR	9
 
 static struct sifive_fu540_macb_mgmt *mgmt;
 
-static int at91ether_alloc_coherent(struct macb *lp)
+static int at91ether_alloc_coherent(struct macb *bp)
 {
-	struct macb_queue *q = &lp->queues[0];
+	struct macb_rxq *rxq = &bp->ctx->rxq[0];
 
-	q->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
-					 (AT91ETHER_MAX_RX_DESCR *
-					  macb_dma_desc_get_size(lp)),
-					 &q->rx_ring_dma, GFP_KERNEL);
-	if (!q->rx_ring)
+	rxq->ring = dma_alloc_coherent(&bp->pdev->dev,
+				       (AT91ETHER_MAX_RX_DESCR *
+					macb_dma_desc_get_size(&bp->info)),
+				       &rxq->ring_dma, GFP_KERNEL);
+	if (!rxq->ring)
 		return -ENOMEM;
 
-	q->rx_buffers = dma_alloc_coherent(&lp->pdev->dev,
-					    AT91ETHER_MAX_RX_DESCR *
-					    AT91ETHER_MAX_RBUFF_SZ,
-					    &q->rx_buffers_dma, GFP_KERNEL);
-	if (!q->rx_buffers) {
-		dma_free_coherent(&lp->pdev->dev,
+	rxq->buffers = dma_alloc_coherent(&bp->pdev->dev,
+					  AT91ETHER_MAX_RX_DESCR *
+					  AT91ETHER_MAX_RBUFF_SZ,
+					  &rxq->buffers_dma,
+					  GFP_KERNEL);
+	if (!rxq->buffers) {
+		dma_free_coherent(&bp->pdev->dev,
 				  AT91ETHER_MAX_RX_DESCR *
-				  macb_dma_desc_get_size(lp),
-				  q->rx_ring, q->rx_ring_dma);
-		q->rx_ring = NULL;
+				  macb_dma_desc_get_size(&bp->info),
+				  rxq->ring, rxq->ring_dma);
+		rxq->ring = NULL;
 		return -ENOMEM;
 	}
 
 	return 0;
 }
 
-static void at91ether_free_coherent(struct macb *lp)
+static void at91ether_free_coherent(struct macb *bp)
 {
-	struct macb_queue *q = &lp->queues[0];
+	struct macb_rxq *rxq = &bp->ctx->rxq[0];
 
-	if (q->rx_ring) {
-		dma_free_coherent(&lp->pdev->dev,
+	if (rxq->ring) {
+		dma_free_coherent(&bp->pdev->dev,
 				  AT91ETHER_MAX_RX_DESCR *
-				  macb_dma_desc_get_size(lp),
-				  q->rx_ring, q->rx_ring_dma);
-		q->rx_ring = NULL;
+				  macb_dma_desc_get_size(&bp->info),
+				  rxq->ring, rxq->ring_dma);
+		rxq->ring = NULL;
 	}
 
-	if (q->rx_buffers) {
-		dma_free_coherent(&lp->pdev->dev,
+	if (rxq->buffers) {
+		dma_free_coherent(&bp->pdev->dev,
 				  AT91ETHER_MAX_RX_DESCR *
 				  AT91ETHER_MAX_RBUFF_SZ,
-				  q->rx_buffers, q->rx_buffers_dma);
-		q->rx_buffers = NULL;
+				  rxq->buffers, rxq->buffers_dma);
+		rxq->buffers = NULL;
 	}
 }
 
 /* Initialize and start the Receiver and Transmit subsystems */
-static int at91ether_start(struct macb *lp)
+static int at91ether_start(struct macb *bp)
 {
-	struct macb_queue *q = &lp->queues[0];
+	struct macb_rxq *rxq = &bp->ctx->rxq[0];
 	struct macb_dma_desc *desc;
 	dma_addr_t addr;
 	u32 ctl;
 	int i, ret;
 
-	ret = at91ether_alloc_coherent(lp);
+	ret = at91ether_alloc_coherent(bp);
 	if (ret)
 		return ret;
 
-	addr = q->rx_buffers_dma;
+	addr = rxq->buffers_dma;
 	for (i = 0; i < AT91ETHER_MAX_RX_DESCR; i++) {
-		desc = macb_rx_desc(q, i);
-		macb_set_addr(lp, desc, addr);
+		desc = macb_rx_desc(bp->ctx, 0, i);
+		macb_set_addr(&bp->info, desc, addr);
 		desc->ctrl = 0;
 		addr += AT91ETHER_MAX_RBUFF_SZ;
 	}
@@ -5035,17 +5336,17 @@ static int at91ether_start(struct macb *lp)
 	desc->addr |= MACB_BIT(RX_WRAP);
 
 	/* Reset buffer index */
-	q->rx_tail = 0;
+	rxq->tail = 0;
 
 	/* Program address of descriptor list in Rx Buffer Queue register */
-	macb_writel(lp, RBQP, q->rx_ring_dma);
+	macb_writel(bp, RBQP, rxq->ring_dma);
 
 	/* Enable Receive and Transmit */
-	ctl = macb_readl(lp, NCR);
-	macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));
+	ctl = macb_readl(bp, NCR);
+	macb_writel(bp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));
 
 	/* Enable MAC interrupts */
-	macb_writel(lp, IER, MACB_BIT(RCOMP)	|
+	macb_writel(bp, IER, MACB_BIT(RCOMP)	|
 			     MACB_BIT(RXUBR)	|
 			     MACB_BIT(ISR_TUND)	|
 			     MACB_BIT(ISR_RLE)	|
@@ -5056,12 +5357,12 @@ static int at91ether_start(struct macb *lp)
 	return 0;
 }
 
-static void at91ether_stop(struct macb *lp)
+static void at91ether_stop(struct macb *bp)
 {
 	u32 ctl;
 
 	/* Disable MAC interrupts */
-	macb_writel(lp, IDR, MACB_BIT(RCOMP)	|
+	macb_writel(bp, IDR, MACB_BIT(RCOMP)	|
 			     MACB_BIT(RXUBR)	|
 			     MACB_BIT(ISR_TUND)	|
 			     MACB_BIT(ISR_RLE)	|
@@ -5070,96 +5371,114 @@ static void at91ether_stop(struct macb *lp)
 			     MACB_BIT(HRESP));
 
 	/* Disable Receiver and Transmitter */
-	ctl = macb_readl(lp, NCR);
-	macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE)));
+	ctl = macb_readl(bp, NCR);
+	macb_writel(bp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE)));
+
+	synchronize_irq(bp->netdev->irq);
 
 	/* Free resources. */
-	at91ether_free_coherent(lp);
+	at91ether_free_coherent(bp);
 }
 
 /* Open the ethernet interface */
-static int at91ether_open(struct net_device *dev)
+static int at91ether_open(struct net_device *netdev)
 {
-	struct macb *lp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	u32 ctl;
 	int ret;
 
-	ret = pm_runtime_resume_and_get(&lp->pdev->dev);
+	ret = pm_runtime_resume_and_get(&bp->pdev->dev);
 	if (ret < 0)
 		return ret;
 
+	bp->ctx = kzalloc_obj(*bp->ctx);
+	if (!bp->ctx) {
+		ret = -ENOMEM;
+		goto pm_exit;
+	}
+	bp->ctx->info = &bp->info;
+
 	/* Clear internal statistics */
-	ctl = macb_readl(lp, NCR);
-	macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));
+	ctl = macb_readl(bp, NCR);
+	macb_writel(bp, NCR, ctl | MACB_BIT(CLRSTAT));
 
-	macb_set_hwaddr(lp);
+	macb_set_hwaddr(bp);
 
-	ret = at91ether_start(lp);
+	ret = at91ether_start(bp);
 	if (ret)
-		goto pm_exit;
+		goto free_ctx;
 
-	ret = macb_phylink_connect(lp);
+	ret = macb_phylink_connect(bp);
 	if (ret)
 		goto stop;
 
-	netif_start_queue(dev);
+	netif_start_queue(netdev);
 
 	return 0;
 
 stop:
-	at91ether_stop(lp);
+	at91ether_stop(bp);
+free_ctx:
+	kfree(bp->ctx);
+	bp->ctx = NULL;
 pm_exit:
-	pm_runtime_put_sync(&lp->pdev->dev);
+	pm_runtime_put_sync(&bp->pdev->dev);
 	return ret;
 }
 
 /* Close the interface */
-static int at91ether_close(struct net_device *dev)
+static int at91ether_close(struct net_device *netdev)
 {
-	struct macb *lp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
-	netif_stop_queue(dev);
+	netif_stop_queue(netdev);
 
-	phylink_stop(lp->phylink);
-	phylink_disconnect_phy(lp->phylink);
+	phylink_stop(bp->phylink);
+	phylink_disconnect_phy(bp->phylink);
 
-	at91ether_stop(lp);
+	at91ether_stop(bp);
 
-	pm_runtime_put(&lp->pdev->dev);
+	kfree(bp->ctx);
+	bp->ctx = NULL;
+
+	pm_runtime_put(&bp->pdev->dev);
 
 	return 0;
 }
 
 /* Transmit packet */
 static netdev_tx_t at91ether_start_xmit(struct sk_buff *skb,
-					struct net_device *dev)
+					struct net_device *netdev)
 {
-	struct macb *lp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
+	struct device *dev = &bp->pdev->dev;
 
-	if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) {
+	if (macb_readl(bp, TSR) & MACB_BIT(RM9200_BNQ)) {
 		int desc = 0;
 
-		netif_stop_queue(dev);
+		netif_stop_queue(netdev);
 
 		/* Store packet information (to free when Tx completed) */
-		lp->rm9200_txq[desc].skb = skb;
-		lp->rm9200_txq[desc].size = skb->len;
-		lp->rm9200_txq[desc].mapping = dma_map_single(&lp->pdev->dev, skb->data,
-							      skb->len, DMA_TO_DEVICE);
-		if (dma_mapping_error(&lp->pdev->dev, lp->rm9200_txq[desc].mapping)) {
+		bp->rm9200_txq[desc].skb = skb;
+		bp->rm9200_txq[desc].size = skb->len;
+		bp->rm9200_txq[desc].mapping = dma_map_single(dev, skb->data,
+							      skb->len,
+							      DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, bp->rm9200_txq[desc].mapping)) {
 			dev_kfree_skb_any(skb);
-			dev->stats.tx_dropped++;
-			netdev_err(dev, "%s: DMA mapping error\n", __func__);
+			netdev->stats.tx_dropped++;
+			netdev_err(netdev, "%s: DMA mapping error\n", __func__);
 			return NETDEV_TX_OK;
 		}
 
 		/* Set address of the data in the Transmit Address register */
-		macb_writel(lp, TAR, lp->rm9200_txq[desc].mapping);
+		macb_writel(bp, TAR, bp->rm9200_txq[desc].mapping);
 		/* Set length of the packet in the Transmit Control register */
-		macb_writel(lp, TCR, skb->len);
+		macb_writel(bp, TCR, skb->len);
 
 	} else {
-		netdev_err(dev, "%s called, but device is busy!\n", __func__);
+		netdev_err(netdev, "%s called, but device is busy!\n",
+			   __func__);
 		return NETDEV_TX_BUSY;
 	}
 
@@ -5169,104 +5488,106 @@ static netdev_tx_t at91ether_start_xmit(struct sk_buff *skb,
 /* Extract received frame from buffer descriptors and sent to upper layers.
  * (Called from interrupt context)
  */
-static void at91ether_rx(struct net_device *dev)
+static void at91ether_rx(struct net_device *netdev)
 {
-	struct macb *lp = netdev_priv(dev);
-	struct macb_queue *q = &lp->queues[0];
+	struct macb *bp = netdev_priv(netdev);
+	struct macb_rxq *rxq = &bp->ctx->rxq[0];
 	struct macb_dma_desc *desc;
 	unsigned char *p_recv;
 	struct sk_buff *skb;
 	unsigned int pktlen;
 
-	desc = macb_rx_desc(q, q->rx_tail);
+	desc = macb_rx_desc(bp->ctx, 0, rxq->tail);
 	while (desc->addr & MACB_BIT(RX_USED)) {
-		p_recv = q->rx_buffers + q->rx_tail * AT91ETHER_MAX_RBUFF_SZ;
+		p_recv = rxq->buffers + rxq->tail * AT91ETHER_MAX_RBUFF_SZ;
 		pktlen = MACB_BF(RX_FRMLEN, desc->ctrl);
-		skb = netdev_alloc_skb(dev, pktlen + 2);
+		skb = netdev_alloc_skb(netdev, pktlen + 2);
 		if (skb) {
 			skb_reserve(skb, 2);
 			skb_put_data(skb, p_recv, pktlen);
 
-			skb->protocol = eth_type_trans(skb, dev);
-			dev->stats.rx_packets++;
-			dev->stats.rx_bytes += pktlen;
+			skb->protocol = eth_type_trans(skb, netdev);
+			netdev->stats.rx_packets++;
+			netdev->stats.rx_bytes += pktlen;
 			netif_rx(skb);
 		} else {
-			dev->stats.rx_dropped++;
+			netdev->stats.rx_dropped++;
 		}
 
 		if (desc->ctrl & MACB_BIT(RX_MHASH_MATCH))
-			dev->stats.multicast++;
+			netdev->stats.multicast++;
 
 		/* reset ownership bit */
 		desc->addr &= ~MACB_BIT(RX_USED);
 
 		/* wrap after last buffer */
-		if (q->rx_tail == AT91ETHER_MAX_RX_DESCR - 1)
-			q->rx_tail = 0;
+		if (rxq->tail == AT91ETHER_MAX_RX_DESCR - 1)
+			rxq->tail = 0;
 		else
-			q->rx_tail++;
+			rxq->tail++;
 
-		desc = macb_rx_desc(q, q->rx_tail);
+		desc = macb_rx_desc(bp->ctx, 0, rxq->tail);
 	}
 }
 
 /* MAC interrupt handler */
 static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
 {
-	struct net_device *dev = dev_id;
-	struct macb *lp = netdev_priv(dev);
+	struct net_device *netdev = dev_id;
+	struct macb *bp = netdev_priv(netdev);
 	u32 intstatus, ctl;
 	unsigned int desc;
 
 	/* MAC Interrupt Status register indicates what interrupts are pending.
 	 * It is automatically cleared once read.
 	 */
-	intstatus = macb_readl(lp, ISR);
+	intstatus = macb_readl(bp, ISR);
 
 	/* Receive complete */
 	if (intstatus & MACB_BIT(RCOMP))
-		at91ether_rx(dev);
+		at91ether_rx(netdev);
 
 	/* Transmit complete */
 	if (intstatus & MACB_BIT(TCOMP)) {
 		/* The TCOM bit is set even if the transmission failed */
 		if (intstatus & (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE)))
-			dev->stats.tx_errors++;
+			netdev->stats.tx_errors++;
 
 		desc = 0;
-		if (lp->rm9200_txq[desc].skb) {
-			dev_consume_skb_irq(lp->rm9200_txq[desc].skb);
-			lp->rm9200_txq[desc].skb = NULL;
-			dma_unmap_single(&lp->pdev->dev, lp->rm9200_txq[desc].mapping,
-					 lp->rm9200_txq[desc].size, DMA_TO_DEVICE);
-			dev->stats.tx_packets++;
-			dev->stats.tx_bytes += lp->rm9200_txq[desc].size;
+		if (bp->rm9200_txq[desc].skb) {
+			dev_consume_skb_irq(bp->rm9200_txq[desc].skb);
+			bp->rm9200_txq[desc].skb = NULL;
+			dma_unmap_single(&bp->pdev->dev,
+					 bp->rm9200_txq[desc].mapping,
+					 bp->rm9200_txq[desc].size,
+					 DMA_TO_DEVICE);
+			netdev->stats.tx_packets++;
+			netdev->stats.tx_bytes += bp->rm9200_txq[desc].size;
 		}
-		netif_wake_queue(dev);
+		netif_wake_queue(netdev);
 	}
 
 	/* Work-around for EMAC Errata section 41.3.1 */
 	if (intstatus & MACB_BIT(RXUBR)) {
-		ctl = macb_readl(lp, NCR);
-		macb_writel(lp, NCR, ctl & ~MACB_BIT(RE));
+		ctl = macb_readl(bp, NCR);
+		macb_writel(bp, NCR, ctl & ~MACB_BIT(RE));
 		wmb();
-		macb_writel(lp, NCR, ctl | MACB_BIT(RE));
+		macb_writel(bp, NCR, ctl | MACB_BIT(RE));
 	}
 
 	if (intstatus & MACB_BIT(ISR_ROVR))
-		netdev_err(dev, "ROVR error\n");
+		netdev_err(netdev, "ROVR error\n");
 
 	return IRQ_HANDLED;
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-static void at91ether_poll_controller(struct net_device *dev)
+static void at91ether_poll_controller(struct net_device *netdev)
 {
 	unsigned long flags;
 
 	local_irq_save(flags);
-	at91ether_interrupt(dev->irq, dev);
+	at91ether_interrupt(netdev->irq, netdev);
 	local_irq_restore(flags);
 }
 #endif
@@ -5313,17 +5634,17 @@ static int at91ether_clk_init(struct platform_device *pdev, struct clk **pclk,
 
 static int at91ether_init(struct platform_device *pdev)
 {
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct macb *bp = netdev_priv(dev);
+	struct net_device *netdev = platform_get_drvdata(pdev);
+	struct macb *bp = netdev_priv(netdev);
 	int err;
 
 	bp->queues[0].bp = bp;
 
-	dev->netdev_ops = &at91ether_netdev_ops;
-	dev->ethtool_ops = &macb_ethtool_ops;
+	netdev->netdev_ops = &at91ether_netdev_ops;
+	netdev->ethtool_ops = &macb_ethtool_ops;
 
-	err = devm_request_irq(&pdev->dev, dev->irq, at91ether_interrupt,
-			       0, dev->name, dev);
+	err = devm_request_irq(&pdev->dev, netdev->irq, at91ether_interrupt,
+			       0, netdev->name, netdev);
 	if (err)
 		return err;
 
@@ -5452,8 +5773,8 @@ static int fu540_c000_init(struct platform_device *pdev)
 
 static int init_reset_optional(struct platform_device *pdev)
 {
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct macb *bp = netdev_priv(dev);
+	struct net_device *netdev = platform_get_drvdata(pdev);
+	struct macb *bp = netdev_priv(netdev);
 	int ret;
 
 	if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) {
@@ -5528,6 +5849,38 @@ static int eyeq5_init(struct platform_device *pdev)
 	return ret;
 }
 
+static int macb_alloc_tieoff(struct macb *bp)
+{
+	/* Tieoff is a workaround in case HW cannot disable queues, for PM. */
+	if (bp->caps & MACB_CAPS_QUEUE_DISABLE)
+		return 0;
+
+	bp->rx_ring_tieoff = dma_alloc_coherent(&bp->pdev->dev,
+						macb_dma_desc_get_size(&bp->info),
+						&bp->rx_ring_tieoff_dma,
+						GFP_KERNEL);
+	if (!bp->rx_ring_tieoff)
+		return -ENOMEM;
+
+	macb_set_addr(&bp->info, bp->rx_ring_tieoff,
+		      MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED));
+
+	bp->rx_ring_tieoff->ctrl = 0;
+
+	return 0;
+}
+
+static void macb_free_tieoff(struct macb *bp)
+{
+	if (!bp->rx_ring_tieoff)
+		return;
+
+	dma_free_coherent(&bp->pdev->dev, macb_dma_desc_get_size(&bp->info),
+			  bp->rx_ring_tieoff,
+			  bp->rx_ring_tieoff_dma);
+	bp->rx_ring_tieoff = NULL;
+}
+
 static const struct macb_usrio_config mpfs_usrio = {
 	.tsu_source = 0,
 };
@@ -5761,11 +6114,12 @@ static int macb_probe(struct platform_device *pdev)
 	const struct macb_config *macb_config;
 	struct clk *tsu_clk = NULL;
 	phy_interface_t interface;
-	struct net_device *dev;
+	struct net_device *netdev;
 	struct resource *regs;
 	u32 wtrmrk_rst_val;
 	void __iomem *mem;
 	struct macb *bp;
+	unsigned int q;
 	int num_queues;
 	bool native_io;
 	int err, val;
@@ -5796,21 +6150,23 @@ static int macb_probe(struct platform_device *pdev)
 		goto err_disable_clocks;
 	}
 
-	dev = alloc_etherdev_mq(sizeof(*bp), num_queues);
-	if (!dev) {
+	netdev = alloc_etherdev_mq(sizeof(*bp), num_queues);
+	if (!netdev) {
 		err = -ENOMEM;
 		goto err_disable_clocks;
 	}
 
-	dev->base_addr = regs->start;
+	netdev->base_addr = regs->start;
 
-	SET_NETDEV_DEV(dev, &pdev->dev);
+	SET_NETDEV_DEV(netdev, &pdev->dev);
 
-	bp = netdev_priv(dev);
+	bp = netdev_priv(netdev);
 	bp->pdev = pdev;
-	bp->dev = dev;
+	bp->netdev = netdev;
 	bp->regs = mem;
 	bp->native_io = native_io;
+	for (q = 0; q < MACB_MAX_QUEUES; q++)
+		bp->info.queue_stats[q] = &bp->queues[q].stats;
 	if (native_io) {
 		bp->macb_reg_readl = hw_readl_native;
 		bp->macb_reg_writel = hw_writel_native;
@@ -5867,10 +6223,20 @@ static int macb_probe(struct platform_device *pdev)
 	}
 	spin_lock_init(&bp->lock);
 	spin_lock_init(&bp->stats_lock);
+	mutex_init(&bp->mac_cfg_lock);
 
 	/* setup capabilities */
 	macb_configure_caps(bp, macb_config);
 
+	if (bp->caps & MACB_CAPS_MACB_IS_EMAC) {
+		/* The name is lying on EMAC: sizes aren't configurable. */
+		bp->configured_rx_ring_size = AT91ETHER_MAX_RX_DESCR;
+		bp->configured_tx_ring_size = 1; /* tiny ring buffer */
+	} else {
+		bp->configured_rx_ring_size = DEFAULT_RX_RING_SIZE;
+		bp->configured_tx_ring_size = DEFAULT_TX_RING_SIZE;
+	}
+
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
 	if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
 		err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(44));
@@ -5881,39 +6247,39 @@ static int macb_probe(struct platform_device *pdev)
 		bp->caps |= MACB_CAPS_DMA_64B;
 	}
 #endif
-	platform_set_drvdata(pdev, dev);
+	platform_set_drvdata(pdev, netdev);
 
-	dev->irq = platform_get_irq(pdev, 0);
-	if (dev->irq < 0) {
-		err = dev->irq;
+	netdev->irq = platform_get_irq(pdev, 0);
+	if (netdev->irq < 0) {
+		err = netdev->irq;
 		goto err_out_free_netdev;
 	}
 
 	/* MTU range: 68 - 1518 or 10240 */
-	dev->min_mtu = GEM_MTU_MIN_SIZE;
+	netdev->min_mtu = GEM_MTU_MIN_SIZE;
 	if ((bp->caps & MACB_CAPS_JUMBO) && bp->jumbo_max_len)
-		dev->max_mtu = MIN(bp->jumbo_max_len, RX_BUFFER_MAX) -
+		netdev->max_mtu = MIN(bp->jumbo_max_len, RX_BUFFER_MAX) -
 				ETH_HLEN - ETH_FCS_LEN;
 	else
-		dev->max_mtu = 1536 - ETH_HLEN - ETH_FCS_LEN;
+		netdev->max_mtu = 1536 - ETH_HLEN - ETH_FCS_LEN;
 
 	if (bp->caps & MACB_CAPS_BD_RD_PREFETCH) {
 		val = GEM_BFEXT(RXBD_RDBUFF, gem_readl(bp, DCFG10));
 		if (val)
 			bp->rx_bd_rd_prefetch = (2 << (val - 1)) *
-						macb_dma_desc_get_size(bp);
+						macb_dma_desc_get_size(&bp->info);
 
 		val = GEM_BFEXT(TXBD_RDBUFF, gem_readl(bp, DCFG10));
 		if (val)
 			bp->tx_bd_rd_prefetch = (2 << (val - 1)) *
-						macb_dma_desc_get_size(bp);
+						macb_dma_desc_get_size(&bp->info);
 	}
 
 	bp->rx_intr_mask = MACB_RX_INT_FLAGS;
 	if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR)
 		bp->rx_intr_mask |= MACB_BIT(RXUBR);
 
-	err = of_get_ethdev_address(np, bp->dev);
+	err = of_get_ethdev_address(np, bp->netdev);
 	if (err == -EPROBE_DEFER)
 		goto err_out_free_netdev;
 	else if (err)
@@ -5935,25 +6301,33 @@ static int macb_probe(struct platform_device *pdev)
 	if (err)
 		goto err_out_phy_exit;
 
-	netif_carrier_off(dev);
+	netif_carrier_off(netdev);
 
-	err = register_netdev(dev);
+	err = macb_alloc_tieoff(bp);
+	if (err)
+		goto err_out_unregister_mdio;
+
+	err = register_netdev(netdev);
 	if (err) {
 		dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
-		goto err_out_unregister_mdio;
+		goto err_out_free_tieoff;
 	}
 
 	INIT_WORK(&bp->hresp_err_bh_work, macb_hresp_error_task);
 	INIT_DELAYED_WORK(&bp->tx_lpi_work, macb_tx_lpi_work_fn);
 
-	netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n",
-		    macb_is_gem(bp) ? "GEM" : "MACB", macb_readl(bp, MID),
-		    dev->base_addr, dev->irq, dev->dev_addr);
+	netdev_info(netdev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n",
+		    macb_is_gem(&bp->info) ? "GEM" : "MACB",
+		    macb_readl(bp, MID), netdev->base_addr, netdev->irq,
+		    netdev->dev_addr);
 
 	pm_runtime_put_autosuspend(&bp->pdev->dev);
 
 	return 0;
 
+err_out_free_tieoff:
+	macb_free_tieoff(bp);
+
 err_out_unregister_mdio:
 	mdiobus_unregister(bp->mii_bus);
 	mdiobus_free(bp->mii_bus);
@@ -5962,7 +6336,7 @@ static int macb_probe(struct platform_device *pdev)
 	phy_exit(bp->phy);
 
 err_out_free_netdev:
-	free_netdev(dev);
+	free_netdev(netdev);
 
 err_disable_clocks:
 	macb_clks_disable(pclk, hclk, tx_clk, rx_clk, tsu_clk);
@@ -5975,14 +6349,15 @@ static int macb_probe(struct platform_device *pdev)
 
 static void macb_remove(struct platform_device *pdev)
 {
-	struct net_device *dev;
+	struct net_device *netdev;
 	struct macb *bp;
 
-	dev = platform_get_drvdata(pdev);
+	netdev = platform_get_drvdata(pdev);
 
-	if (dev) {
-		bp = netdev_priv(dev);
-		unregister_netdev(dev);
+	if (netdev) {
+		bp = netdev_priv(netdev);
+		unregister_netdev(netdev);
+		macb_free_tieoff(bp);
 		phy_exit(bp->phy);
 		mdiobus_unregister(bp->mii_bus);
 		mdiobus_free(bp->mii_bus);
@@ -5994,7 +6369,7 @@ static void macb_remove(struct platform_device *pdev)
 		pm_runtime_dont_use_autosuspend(&pdev->dev);
 		pm_runtime_set_suspended(&pdev->dev);
 		phylink_destroy(bp->phylink);
-		free_netdev(dev);
+		free_netdev(netdev);
 	}
 }
 
@@ -6009,7 +6384,7 @@ static int __maybe_unused macb_suspend(struct device *dev)
 	u32 tmp, ifa_local;
 	unsigned int q;
 
-	if (!device_may_wakeup(&bp->dev->dev))
+	if (!device_may_wakeup(&bp->netdev->dev))
 		phy_exit(bp->phy);
 
 	if (!netif_running(netdev))
@@ -6019,7 +6394,7 @@ static int __maybe_unused macb_suspend(struct device *dev)
 		if (bp->wolopts & WAKE_ARP) {
 			/* Check for IP address in WOL ARP mode */
 			rcu_read_lock();
-			idev = __in_dev_get_rcu(bp->dev);
+			idev = __in_dev_get_rcu(bp->netdev);
 			if (idev)
 				ifa = rcu_dereference(idev->ifa_list);
 			if (!ifa) {
@@ -6071,7 +6446,7 @@ static int __maybe_unused macb_suspend(struct device *dev)
 			tmp |= MACB_BFEXT(IP, ifa_local);
 		}
 
-		if (macb_is_gem(bp)) {
+		if (macb_is_gem(&bp->info)) {
 			queue_writel(bp->queues, IER, GEM_BIT(WOL));
 			gem_writel(bp, WOL, tmp);
 		} else {
@@ -6117,11 +6492,12 @@ static int __maybe_unused macb_resume(struct device *dev)
 {
 	struct net_device *netdev = dev_get_drvdata(dev);
 	struct macb *bp = netdev_priv(netdev);
+	struct macb_context *ctx = bp->ctx;
 	struct macb_queue *queue;
 	unsigned long flags;
 	unsigned int q;
 
-	if (!device_may_wakeup(&bp->dev->dev))
+	if (!device_may_wakeup(&bp->netdev->dev))
 		phy_init(bp->phy);
 
 	if (!netif_running(netdev))
@@ -6133,7 +6509,7 @@ static int __maybe_unused macb_resume(struct device *dev)
 	if (bp->wol & MACB_WOL_ENABLED) {
 		spin_lock_irqsave(&bp->lock, flags);
 		/* Disable WoL */
-		if (macb_is_gem(bp)) {
+		if (macb_is_gem(&bp->info)) {
 			queue_writel(bp->queues, IDR, GEM_BIT(WOL));
 			gem_writel(bp, WOL, 0);
 		} else {
@@ -6161,10 +6537,10 @@ static int __maybe_unused macb_resume(struct device *dev)
 	for (q = 0, queue = bp->queues; q < bp->num_queues;
 	     ++q, ++queue) {
 		if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) {
-			if (macb_is_gem(bp))
-				gem_init_rx_ring(queue);
+			if (macb_is_gem(&bp->info))
+				gem_init_rx_ring(ctx, q);
 			else
-				macb_init_rx_ring(queue);
+				macb_init_rx_ring(ctx, q);
 		}
 
 		napi_enable(&queue->napi_rx);
diff --git a/drivers/net/ethernet/cadence/macb_pci.c b/drivers/net/ethernet/cadence/macb_pci.c
index b79dec17e6b09..ac009007118f3 100644
--- a/drivers/net/ethernet/cadence/macb_pci.c
+++ b/drivers/net/ethernet/cadence/macb_pci.c
@@ -24,48 +24,48 @@
 #define GEM_PCLK_RATE 50000000
 #define GEM_HCLK_RATE 50000000
 
-static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int macb_probe(struct pci_dev *pci, const struct pci_device_id *id)
 {
 	int err;
-	struct platform_device *plat_dev;
+	struct platform_device *pdev;
 	struct platform_device_info plat_info;
 	struct macb_platform_data plat_data;
 	struct resource res[2];
 
 	/* enable pci device */
-	err = pcim_enable_device(pdev);
+	err = pcim_enable_device(pci);
 	if (err < 0) {
-		dev_err(&pdev->dev, "Enabling PCI device has failed: %d", err);
+		dev_err(&pci->dev, "Enabling PCI device has failed: %d", err);
 		return err;
 	}
 
-	pci_set_master(pdev);
+	pci_set_master(pci);
 
 	/* set up resources */
 	memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
-	res[0].start = pci_resource_start(pdev, 0);
-	res[0].end = pci_resource_end(pdev, 0);
+	res[0].start = pci_resource_start(pci, 0);
+	res[0].end = pci_resource_end(pci, 0);
 	res[0].name = PCI_DRIVER_NAME;
 	res[0].flags = IORESOURCE_MEM;
-	res[1].start = pci_irq_vector(pdev, 0);
+	res[1].start = pci_irq_vector(pci, 0);
 	res[1].name = PCI_DRIVER_NAME;
 	res[1].flags = IORESOURCE_IRQ;
 
-	dev_info(&pdev->dev, "EMAC physical base addr: %pa\n",
+	dev_info(&pci->dev, "EMAC physical base addr: %pa\n",
 		 &res[0].start);
 
 	/* set up macb platform data */
 	memset(&plat_data, 0, sizeof(plat_data));
 
 	/* initialize clocks */
-	plat_data.pclk = clk_register_fixed_rate(&pdev->dev, "pclk", NULL, 0,
+	plat_data.pclk = clk_register_fixed_rate(&pci->dev, "pclk", NULL, 0,
 						 GEM_PCLK_RATE);
 	if (IS_ERR(plat_data.pclk)) {
 		err = PTR_ERR(plat_data.pclk);
 		goto err_pclk_register;
 	}
 
-	plat_data.hclk = clk_register_fixed_rate(&pdev->dev, "hclk", NULL, 0,
+	plat_data.hclk = clk_register_fixed_rate(&pci->dev, "hclk", NULL, 0,
 						 GEM_HCLK_RATE);
 	if (IS_ERR(plat_data.hclk)) {
 		err = PTR_ERR(plat_data.hclk);
@@ -74,24 +74,24 @@ static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	/* set up platform device info */
 	memset(&plat_info, 0, sizeof(plat_info));
-	plat_info.parent = &pdev->dev;
-	plat_info.fwnode = pdev->dev.fwnode;
+	plat_info.parent = &pci->dev;
+	plat_info.fwnode = pci->dev.fwnode;
 	plat_info.name = PLAT_DRIVER_NAME;
-	plat_info.id = pdev->devfn;
+	plat_info.id = pci->devfn;
 	plat_info.res = res;
 	plat_info.num_res = ARRAY_SIZE(res);
 	plat_info.data = &plat_data;
 	plat_info.size_data = sizeof(plat_data);
-	plat_info.dma_mask = pdev->dma_mask;
+	plat_info.dma_mask = pci->dma_mask;
 
 	/* register platform device */
-	plat_dev = platform_device_register_full(&plat_info);
-	if (IS_ERR(plat_dev)) {
-		err = PTR_ERR(plat_dev);
+	pdev = platform_device_register_full(&plat_info);
+	if (IS_ERR(pdev)) {
+		err = PTR_ERR(pdev);
 		goto err_plat_dev_register;
 	}
 
-	pci_set_drvdata(pdev, plat_dev);
+	pci_set_drvdata(pci, pdev);
 
 	return 0;
 
@@ -105,14 +105,14 @@ static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	return err;
 }
 
-static void macb_remove(struct pci_dev *pdev)
+static void macb_remove(struct pci_dev *pci)
 {
-	struct platform_device *plat_dev = pci_get_drvdata(pdev);
-	struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev);
+	struct platform_device *pdev = pci_get_drvdata(pci);
+	struct macb_platform_data *plat_data = dev_get_platdata(&pdev->dev);
 	struct clk *pclk = plat_data->pclk;
 	struct clk *hclk = plat_data->hclk;
 
-	platform_device_unregister(plat_dev);
+	platform_device_unregister(pdev);
 	clk_unregister_fixed_rate(pclk);
 	clk_unregister_fixed_rate(hclk);
 }
diff --git a/drivers/net/ethernet/cadence/macb_ptp.c b/drivers/net/ethernet/cadence/macb_ptp.c
index d91f7b1aa39ca..8765c4782509c 100644
--- a/drivers/net/ethernet/cadence/macb_ptp.c
+++ b/drivers/net/ethernet/cadence/macb_ptp.c
@@ -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));
@@ -324,9 +324,9 @@ void gem_ptp_txstamp(struct macb *bp, struct sk_buff *skb,
 	skb_tstamp_tx(skb, &shhwtstamps);
 }
 
-void gem_ptp_init(struct net_device *dev)
+void gem_ptp_init(struct net_device *netdev)
 {
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 
 	bp->ptp_clock_info = gem_ptp_caps_template;
 
@@ -334,7 +334,7 @@ void gem_ptp_init(struct net_device *dev)
 	bp->tsu_rate = bp->ptp_info->get_tsu_rate(bp);
 	bp->ptp_clock_info.max_adj = bp->ptp_info->get_ptp_max_adj();
 	gem_ptp_init_timer(bp);
-	bp->ptp_clock = ptp_clock_register(&bp->ptp_clock_info, &dev->dev);
+	bp->ptp_clock = ptp_clock_register(&bp->ptp_clock_info, &netdev->dev);
 	if (IS_ERR(bp->ptp_clock)) {
 		pr_err("ptp clock register failed: %ld\n",
 			PTR_ERR(bp->ptp_clock));
@@ -353,9 +353,9 @@ void gem_ptp_init(struct net_device *dev)
 		 GEM_PTP_TIMER_NAME);
 }
 
-void gem_ptp_remove(struct net_device *ndev)
+void gem_ptp_remove(struct net_device *netdev)
 {
-	struct macb *bp = netdev_priv(ndev);
+	struct macb *bp = netdev_priv(netdev);
 
 	if (bp->ptp_clock) {
 		ptp_clock_unregister(bp->ptp_clock);
@@ -378,13 +378,13 @@ static int gem_ptp_set_ts_mode(struct macb *bp,
 	return 0;
 }
 
-int gem_get_hwtst(struct net_device *dev,
+int gem_get_hwtst(struct net_device *netdev,
 		  struct kernel_hwtstamp_config *tstamp_config)
 {
-	struct macb *bp = netdev_priv(dev);
+	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;
@@ -402,16 +402,16 @@ static void gem_ptp_set_one_step_sync(struct macb *bp, u8 enable)
 		macb_writel(bp, NCR, reg_val & ~MACB_BIT(OSSMODE));
 }
 
-int gem_set_hwtst(struct net_device *dev,
+int gem_set_hwtst(struct net_device *netdev,
 		  struct kernel_hwtstamp_config *tstamp_config,
 		  struct netlink_ext_ack *extack)
 {
 	enum macb_bd_control tx_bd_control = TSTAMP_DISABLED;
 	enum macb_bd_control rx_bd_control = TSTAMP_DISABLED;
-	struct macb *bp = netdev_priv(dev);
+	struct macb *bp = netdev_priv(netdev);
 	u32 regval;
 
-	if (!macb_dma_ptp(bp))
+	if (!macb_dma_ptp(&bp->info))
 		return -EOPNOTSUPP;
 
 	switch (tstamp_config->tx_type) {

3/2 2026/08/05 19:15 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 67482
							output: 35
							thoughts: 648
						

Thoughts:
**Analyzing the MACB Ethernet Driver Patch**

Okay, so I'm looking at this patch series for the `macb` ethernet driver, specifically within `drivers/net/ethernet/cadence/`. It seems the core change is the introduction of a `struct macb_context`. This new structure is designed to hold the ring sizes and queue configurations. The really interesting part is the context swapping functionality. The idea is to enable MTU changes without requiring the network interface to be completely brought down if `netif_running` is true, although it does perform an internal stop/start via context swap.

The patch modifies `macb_change_mtu` significantly. Specifically, this block:

```c
-static int macb_change_mtu(struct net_device *dev, int new_mtu)
+static int macb_change_mtu(struct net_device *netdev, int new_mtu)
 {
-	if (netif_running(dev))
-		return -EBUSY;
+	struct macb *bp = netdev_priv(netdev);
+	bool running = netif_running(netdev);
+	struct macb_context *new_ctx;
+
+	if (running) {
+		/* Context swapping is not supported for AT91. */
+		if (bp->caps & MACB_CAPS_MACB_IS_EMAC)
+			return -EBUSY;
 
-	WRITE_ONCE(dev->mtu, new_mtu);
+		new_ctx = macb_context_alloc(bp, new_mtu,
+					     bp->configured_rx_ring_size,
+					     bp->configured_tx_ring_size);
+		if (IS_ERR(new_ctx))
+			return PTR_ERR(new_ctx);
+
+		macb_context_swap_start(bp);
+	}
+
+	WRITE_ONCE(netdev->mtu, new_mtu);
+
+	if (running)
+		macb_context_swap_end(bp, new_ctx);
 
 	return 0;
 }
```

It looks like the change is to enable context swapping for MTU and ring size changes. That's a functional change, a pretty significant one. My initial thought is to figure out if this is something we can test easily with our existing infrastructure. Does QEMU have an emulated version of this driver?

Let's see... the Cadence MACB/GEM is a popular IP core, used in platforms like Xilinx Zynq, Sifive FU540, and Microchip PolarFire. But, wait, I recall QEMU having `cadence_gem` emulation! Yes, it's there: `hw/net/cadence_gem.c`. Okay, so it looks like QEMU emulates it, and it's used in `xilinx_zynq`, `xilinx_zynqmp`, and `sifive_u`. Now, the critical question: can we fuzz this? If we enable the driver, we should be able to. The driver config is `CONFIG_MACB`. Let me just check the `Kconfig` file in the driver directory to be certain...



4/2 2026/08/05 19:15 tool grepper
0m Args:
{
  "Expression": "config MACB",
  "PathPrefix": "drivers/net/ethernet/cadence/Kconfig"
}

Results:
{
  "Output": "drivers/net/ethernet/cadence/Kconfig=20=if NET_VENDOR_CADENCE\ndrivers/net/ethernet/cadence/Kconfig-21-\ndrivers/net/ethernet/cadence/Kconfig:22:config MACB\ndrivers/net/ethernet/cadence/Kconfig-23-\ttristate \"Cadence MACB/GEM support\"\n--\ndrivers/net/ethernet/cadence/Kconfig-36-\ndrivers/net/ethernet/cadence/Kconfig:37:config MACB_USE_HWSTAMP\ndrivers/net/ethernet/cadence/Kconfig-38-\tbool \"Use IEEE 1588 hwstamp\"\n--\ndrivers/net/ethernet/cadence/Kconfig-44-\ndrivers/net/ethernet/cadence/Kconfig:45:config MACB_PCI\ndrivers/net/ethernet/cadence/Kconfig-46-\ttristate \"Cadence PCI MACB/GEM support\"\n"
}

5/2 2026/08/05 19:15 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 69155
							output: 37
							thoughts: 183
						

Thoughts:
**Analyzing the MACB Network Driver Configuration**

Okay, so I'm looking at this configuration and I see both `MACB` and `MACB_PCI`. The fact that we have `MACB_PCI` immediately jumps out at me because that hints that this can be probed as a PCI device. And, if that's the case, we're talking about a significantly easier fuzzing target for something like syzkaller because we can leverage virtual PCI and the `syz_pci_assign` system call, assuming there are no issues.

Let's quickly confirm this. I need to check the code, so let me look in `macb_pci.c`. Ah, perfect, here's what I expected:

```c
static const struct pci_device_id macb_pci_ids[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_MACB) },
	{ 0, }
};
```

Confirmed! This clearly defines the PCI device ID, which means syzkaller can definitely interact with this hardware through the PCI interface. This is a game-changer for fuzzing, given syzkaller's strengths in this area.

However, I need to make sure this is properly set up. Let me think a bit further. The configuration option `MACB_PCI` is likely dependent on the PCI subsystem being enabled. So, to ensure this is properly enabled in our build I'll need to check the `Kconfig` files. Specifically, I need to look in `drivers/net/ethernet/cadence/Kconfig` to see if that's true. I have to make sure the PCI dependency is there. Then, I can start fuzzing.



6/2 2026/08/05 19:15 tool grepper
0m Args:
{
  "Expression": "config MACB_PCI",
  "PathPrefix": "drivers/net/ethernet/cadence/Kconfig"
}

Results:
{
  "Output": "drivers/net/ethernet/cadence/Kconfig=37=config MACB_USE_HWSTAMP\n--\ndrivers/net/ethernet/cadence/Kconfig-44-\ndrivers/net/ethernet/cadence/Kconfig:45:config MACB_PCI\ndrivers/net/ethernet/cadence/Kconfig-46-\ttristate \"Cadence PCI MACB/GEM support\"\n"
}

7/2 2026/08/05 19:15 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 69865
							output: 39
							thoughts: 24
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Diving into the Cadence Ethernet Kconfig**

Alright, let's get down to brass tacks. I need to understand the configuration options for the Cadence Ethernet driver. Specifically, I'm thinking I should start digging into the `Kconfig` file, located in `drivers/net/ethernet/cadence/`. I seem to recall that some key options related to, say, PHY interface selection or specific hardware features, tend to be defined around line 45. That's a good starting point to hone in on the relevant sections and understand the dependencies and default settings for different Cadence Ethernet controller variants. I expect I will see options for MII, GMII, RGMII and SGMII and the supporting hardware platform dependencies and chip revisions, given that this is a Cadence specific Kconfig file. Let's see what we find!



8/2 2026/08/05 19:15 tool read-file
0m Args:
{
  "File": "drivers/net/ethernet/cadence/Kconfig",
  "FirstLine": 40,
  "LineCount": 20
}

Results:
{
  "Contents": "  40:\t\tdepends on PTP_1588_CLOCK\n  41:\t\tdefault y\n  42:\t\thelp\n  43:\t\t  Enable IEEE 1588 Precision Time Protocol (PTP) support for MACB.\n  44:\t\n  45:\tconfig MACB_PCI\n  46:\t\ttristate \"Cadence PCI MACB/GEM support\"\n  47:\t\tdepends on MACB \u0026\u0026 PCI\n  48:\t\thelp\n  49:\t\t  This is PCI wrapper for MACB driver.\n  50:\t\n  51:\t\t  To compile this driver as a module, choose M here: the module\n  52:\t\t  will be called macb_pci.\n  53:\t\n  54:\tendif # NET_VENDOR_CADENCE\n"
}

9/2 2026/08/05 19:15 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 70332
							output: 76
							thoughts: 187
						

Thoughts:
**Fuzzing MACB_PCI: A Strategic Approach**

Okay, so I've got `MACB_PCI` here, and it's pretty clear it's built on top of both `MACB` and `PCI`. That means a PCI-focused fuzzing strategy should be fruitful. Let's see, the goal is to identify the functions that are going to be most interesting for the fuzzing campaign.

Looking at the patch, the modifications are centered around: `macb_change_mtu`, `macb_set_ringparam`, `macb_context_swap_start`, `macb_context_swap_end`, and `macb_context_alloc`. Alright, let me just make sure I have the list: `macb_change_mtu`, `macb_set_ringparam`, `macb_context_swap_start`, `macb_context_swap_end`, and `macb_context_alloc`.

Now, before I dig in too deep, let's just confirm that `macb_change_mtu` and `macb_set_ringparam` are indeed within `macb_main.c`. This is essential to ensure a clear understanding of the module's structure and its integration within the larger codebase.



10/2 2026/08/05 19:15 tool grepper
0m Args:
{
  "Expression": "macb_change_mtu|macb_set_ringparam|macb_context_swap_start|macb_context_swap_end|macb_context_alloc",
  "PathPrefix": "drivers/net/ethernet/cadence/macb_main.c"
}

Results:
{
  "Output": "drivers/net/ethernet/cadence/macb_main.c=2856=static int macb_alloc(struct macb_context *ctx)\n--\ndrivers/net/ethernet/cadence/macb_main.c-2914-\ndrivers/net/ethernet/cadence/macb_main.c:2915:static struct macb_context *macb_context_alloc(struct macb *bp,\ndrivers/net/ethernet/cadence/macb_main.c-2916-\t\t\t\t\t       unsigned int mtu,\n--\ndrivers/net/ethernet/cadence/macb_main.c=3099=static void macb_configure_dma(struct macb *bp)\n--\ndrivers/net/ethernet/cadence/macb_main.c-3140-\ndrivers/net/ethernet/cadence/macb_main.c:3141:static void macb_context_swap_start(struct macb *bp)\ndrivers/net/ethernet/cadence/macb_main.c-3142-{\n--\ndrivers/net/ethernet/cadence/macb_main.c-3208-\ndrivers/net/ethernet/cadence/macb_main.c:3209:static void macb_context_swap_end(struct macb *bp,\ndrivers/net/ethernet/cadence/macb_main.c-3210-\t\t\t\t  struct macb_context *new_ctx)\n--\ndrivers/net/ethernet/cadence/macb_main.c=3428=static int macb_open(struct net_device *netdev)\n--\ndrivers/net/ethernet/cadence/macb_main.c-3440-\ndrivers/net/ethernet/cadence/macb_main.c:3441:\tbp-\u003ectx = macb_context_alloc(bp, netdev-\u003emtu,\ndrivers/net/ethernet/cadence/macb_main.c-3442-\t\t\t\t     bp-\u003econfigured_rx_ring_size,\n--\ndrivers/net/ethernet/cadence/macb_main.c=3495=static int macb_close(struct net_device *netdev)\n--\ndrivers/net/ethernet/cadence/macb_main.c-3533-\ndrivers/net/ethernet/cadence/macb_main.c:3534:static int macb_change_mtu(struct net_device *netdev, int new_mtu)\ndrivers/net/ethernet/cadence/macb_main.c-3535-{\n--\ndrivers/net/ethernet/cadence/macb_main.c-3544-\ndrivers/net/ethernet/cadence/macb_main.c:3545:\t\tnew_ctx = macb_context_alloc(bp, new_mtu,\ndrivers/net/ethernet/cadence/macb_main.c-3546-\t\t\t\t\t     bp-\u003econfigured_rx_ring_size,\n--\ndrivers/net/ethernet/cadence/macb_main.c-3550-\ndrivers/net/ethernet/cadence/macb_main.c:3551:\t\tmacb_context_swap_start(bp);\ndrivers/net/ethernet/cadence/macb_main.c-3552-\t}\n--\ndrivers/net/ethernet/cadence/macb_main.c-3556-\tif (running)\ndrivers/net/ethernet/cadence/macb_main.c:3557:\t\tmacb_context_swap_end(bp, new_ctx);\ndrivers/net/ethernet/cadence/macb_main.c-3558-\n--\ndrivers/net/ethernet/cadence/macb_main.c=3992=static void macb_get_ringparam(struct net_device *netdev,\n--\ndrivers/net/ethernet/cadence/macb_main.c-4005-\ndrivers/net/ethernet/cadence/macb_main.c:4006:static int macb_set_ringparam(struct net_device *netdev,\ndrivers/net/ethernet/cadence/macb_main.c-4007-\t\t\t      struct ethtool_ringparam *ring,\n--\ndrivers/net/ethernet/cadence/macb_main.c-4036-\tif (running) {\ndrivers/net/ethernet/cadence/macb_main.c:4037:\t\tnew_ctx = macb_context_alloc(bp, netdev-\u003emtu,\ndrivers/net/ethernet/cadence/macb_main.c-4038-\t\t\t\t\t     new_rx_size, new_tx_size);\n--\ndrivers/net/ethernet/cadence/macb_main.c-4041-\ndrivers/net/ethernet/cadence/macb_main.c:4042:\t\tmacb_context_swap_start(bp);\ndrivers/net/ethernet/cadence/macb_main.c-4043-\t}\n--\ndrivers/net/ethernet/cadence/macb_main.c-4048-\tif (running)\ndrivers/net/ethernet/cadence/macb_main.c:4049:\t\tmacb_context_swap_end(bp, new_ctx);\ndrivers/net/ethernet/cadence/macb_main.c-4050-\n--\ndrivers/net/ethernet/cadence/macb_main.c=4442=static const struct ethtool_ops macb_ethtool_ops = {\n--\ndrivers/net/ethernet/cadence/macb_main.c-4455-\t.get_ringparam\t\t= macb_get_ringparam,\ndrivers/net/ethernet/cadence/macb_main.c:4456:\t.set_ringparam\t\t= macb_set_ringparam,\ndrivers/net/ethernet/cadence/macb_main.c-4457-};\n--\ndrivers/net/ethernet/cadence/macb_main.c=4473=static const struct ethtool_ops gem_ethtool_ops = {\n--\ndrivers/net/ethernet/cadence/macb_main.c-4489-\t.get_ringparam\t\t= macb_get_ringparam,\ndrivers/net/ethernet/cadence/macb_main.c:4490:\t.set_ringparam\t\t= macb_set_ringparam,\ndrivers/net/ethernet/cadence/macb_main.c-4491-\t.get_rxnfc\t\t\t= gem_get_rxnfc,\n--\ndrivers/net/ethernet/cadence/macb_main.c=4851=static const struct net_device_ops macb_netdev_ops = {\n--\ndrivers/net/ethernet/cadence/macb_main.c-4858-\t.ndo_validate_addr\t= eth_validate_addr,\ndrivers/net/ethernet/cadence/macb_main.c:4859:\t.ndo_change_mtu\t\t= macb_change_mtu,\ndrivers/net/ethernet/cadence/macb_main.c-4860-\t.ndo_set_mac_address\t= macb_set_mac_addr,\n"
}

11/2 2026/08/05 19:15 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 72711
							output: 192
							thoughts: 953
						

Thoughts:
**Fuzzing Strategy for the Cadence MACB/GEM Ethernet Driver Context Swap Patch**

Okay, so I'm looking at this patch and immediately, my thought process zeroes in on how we can effectively fuzz the new context swapping logic. First, let's identify the key entry points. I see `macb_change_mtu` and `macb_set_ringparam` as critical. They're the functions directly involved in triggering context swaps – perfect for fuzzing. Then there are internal functions, `macb_context_swap_start` and `macb_context_swap_end`. These are the core of the context swapping operation itself, so they're definitely important, even if they're not direct entry points. I'm noting that while `macb_context_alloc` is also internal, it plays a key part in the new functionality.

I'm initially listing a bunch of other modified functions, but I'm mentally filtering out the hot paths like `macb_start_xmit` and `macb_rx` to avoid overwhelming the fuzzer with common, well-tested code. The error handling and workqueue functions, like `macb_tx_error_task`, `macb_hresp_error_task`, and `macb_tx_lpi_work_fn` are interesting, but maybe not the *primary* focus here. `macb_taprio_setup_replace` is intriguing too, because of the `tc` taprio offload interaction. I'll flag that for potential follow-up if time allows.

Now, let's nail down the configuration requirements. Looks like we need `MACB` and `MACB_PCI`. I see that `MACB_PCI` depends on `MACB` and `PCI`, so that's the base requirement. Then, there's `CONFIG_MACB_USE_HWSTAMP`, but I don't believe that's critical to test the core functionality.

I double-check to confirm that `macb_change_mtu` and `macb_set_ringparam` are, even though static, not inlined, since they are assigned to function pointers and will act as API entry points. This confirms their suitability as fuzzing targets.

So, here's my plan: the core fuzzing symbols are `macb_change_mtu`, `macb_set_ringparam`, `macb_context_swap_start`, and `macb_context_swap_end`. We'll enable `MACB` and `MACB_PCI`. The overall goal is to stress the context swapping logic, and these are the best hooks for that. The key reasoning is that the patch fundamentally changes how the driver handles MTU and ring parameter changes, so we need to ensure the new context management is robust.



12/2 2026/08/05 19:15 tool set-results
0m Args:
{
  "EnableConfigs": [
    "MACB",
    "MACB_PCI"
  ],
  "FocusSymbols": [
    "macb_change_mtu",
    "macb_set_ringparam",
    "macb_context_swap_start",
    "macb_context_swap_end"
  ],
  "Reasoning": "The patch introduces a new `macb_context` structure to the Cadence MACB/GEM ethernet driver, enabling context swapping for dynamic MTU and ring parameter changes without fully stopping the device. It also refactors the driver's queue and ring management to use this context. The driver can be fuzzed via its PCI wrapper (`CONFIG_MACB_PCI`), which allows syzkaller to instantiate it using virtual PCI devices. The focus should be on the newly introduced context swapping logic triggered by MTU and ring parameter changes.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "MACB",
    "MACB_PCI"
  ],
  "FocusSymbols": [
    "macb_change_mtu",
    "macb_set_ringparam",
    "macb_context_swap_start",
    "macb_context_swap_end"
  ],
  "Reasoning": "The patch introduces a new `macb_context` structure to the Cadence MACB/GEM ethernet driver, enabling context swapping for dynamic MTU and ring parameter changes without fully stopping the device. It also refactors the driver's queue and ring management to use this context. The driver can be fuzzed via its PCI wrapper (`CONFIG_MACB_PCI`), which allows syzkaller to instantiate it using virtual PCI devices. The focus should be on the newly introduced context swapping logic triggered by MTU and ring parameter changes.",
  "WorthFuzzing": true
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)