Commit 7779f268 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-asp22-optimizations'



Justin Chen says:

====================
Support for ASP 2.2 and optimizations

ASP 2.2 adds some power savings during low power modes.

Also make various improvements when entering low power modes and
reduce MDIO traffic by hooking up interrupts.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents fc809e1e cc7f105e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -15,6 +15,10 @@ description: Broadcom Ethernet controller first introduced with 72165
properties:
  compatible:
    oneOf:
      - items:
          - enum:
              - brcm,bcm74165b0-asp
          - const: brcm,asp-v2.2
      - items:
          - enum:
              - brcm,bcm74165-asp
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ properties:
      - brcm,genet-mdio-v5
      - brcm,asp-v2.0-mdio
      - brcm,asp-v2.1-mdio
      - brcm,asp-v2.2-mdio
      - brcm,unimac-mdio

  reg:
+82 −8
Original line number Diff line number Diff line
@@ -31,6 +31,20 @@ static void _intr2_mask_set(struct bcmasp_priv *priv, u32 mask)
	priv->irq_mask |= mask;
}

void bcmasp_enable_phy_irq(struct bcmasp_intf *intf, int en)
{
	struct bcmasp_priv *priv = intf->parent;

	/* Only supported with internal phys */
	if (!intf->internal_phy)
		return;

	if (en)
		_intr2_mask_clear(priv, ASP_INTR2_PHY_EVENT(intf->channel));
	else
		_intr2_mask_set(priv, ASP_INTR2_PHY_EVENT(intf->channel));
}

void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en)
{
	struct bcmasp_priv *priv = intf->parent;
@@ -79,6 +93,9 @@ static void bcmasp_intr2_handling(struct bcmasp_intf *intf, u32 status)
			__napi_schedule_irqoff(&intf->tx_napi);
		}
	}

	if (status & ASP_INTR2_PHY_EVENT(intf->channel))
		phy_mac_interrupt(intf->ndev->phydev);
}

static irqreturn_t bcmasp_isr(int irq, void *data)
@@ -972,7 +989,26 @@ static void bcmasp_core_init(struct bcmasp_priv *priv)
		      ASP_INTR2_CLEAR);
}

static void bcmasp_core_clock_select(struct bcmasp_priv *priv, bool slow)
static void bcmasp_core_clock_select_many(struct bcmasp_priv *priv, bool slow)
{
	u32 reg;

	reg = ctrl2_core_rl(priv, ASP_CTRL2_CORE_CLOCK_SELECT);
	if (slow)
		reg &= ~ASP_CTRL2_CORE_CLOCK_SELECT_MAIN;
	else
		reg |= ASP_CTRL2_CORE_CLOCK_SELECT_MAIN;
	ctrl2_core_wl(priv, reg, ASP_CTRL2_CORE_CLOCK_SELECT);

	reg = ctrl2_core_rl(priv, ASP_CTRL2_CPU_CLOCK_SELECT);
	if (slow)
		reg &= ~ASP_CTRL2_CPU_CLOCK_SELECT_MAIN;
	else
		reg |= ASP_CTRL2_CPU_CLOCK_SELECT_MAIN;
	ctrl2_core_wl(priv, reg, ASP_CTRL2_CPU_CLOCK_SELECT);
}

static void bcmasp_core_clock_select_one(struct bcmasp_priv *priv, bool slow)
{
	u32 reg;

@@ -1166,6 +1202,24 @@ static void bcmasp_wol_irq_destroy_per_intf(struct bcmasp_priv *priv)
	}
}

static void bcmasp_eee_fixup(struct bcmasp_intf *intf, bool en)
{
	u32 reg, phy_lpi_overwrite;

	reg = rx_edpkt_core_rl(intf->parent, ASP_EDPKT_SPARE_REG);
	phy_lpi_overwrite = intf->internal_phy ? ASP_EDPKT_SPARE_REG_EPHY_LPI :
			    ASP_EDPKT_SPARE_REG_GPHY_LPI;

	if (en)
		reg |= phy_lpi_overwrite;
	else
		reg &= ~phy_lpi_overwrite;

	rx_edpkt_core_wl(intf->parent, reg, ASP_EDPKT_SPARE_REG);

	usleep_range(50, 100);
}

static struct bcmasp_hw_info v20_hw_info = {
	.rx_ctrl_flush = ASP_RX_CTRL_FLUSH,
	.umac2fb = UMAC2FB_OFFSET,
@@ -1178,6 +1232,7 @@ static const struct bcmasp_plat_data v20_plat_data = {
	.init_wol = bcmasp_init_wol_per_intf,
	.enable_wol = bcmasp_enable_wol_per_intf,
	.destroy_wol = bcmasp_wol_irq_destroy_per_intf,
	.core_clock_select = bcmasp_core_clock_select_one,
	.hw_info = &v20_hw_info,
};

@@ -1194,17 +1249,39 @@ static const struct bcmasp_plat_data v21_plat_data = {
	.init_wol = bcmasp_init_wol_shared,
	.enable_wol = bcmasp_enable_wol_shared,
	.destroy_wol = bcmasp_wol_irq_destroy_shared,
	.core_clock_select = bcmasp_core_clock_select_one,
	.hw_info = &v21_hw_info,
};

static const struct bcmasp_plat_data v22_plat_data = {
	.init_wol = bcmasp_init_wol_shared,
	.enable_wol = bcmasp_enable_wol_shared,
	.destroy_wol = bcmasp_wol_irq_destroy_shared,
	.core_clock_select = bcmasp_core_clock_select_many,
	.hw_info = &v21_hw_info,
	.eee_fixup = bcmasp_eee_fixup,
};

static void bcmasp_set_pdata(struct bcmasp_priv *priv, const struct bcmasp_plat_data *pdata)
{
	priv->init_wol = pdata->init_wol;
	priv->enable_wol = pdata->enable_wol;
	priv->destroy_wol = pdata->destroy_wol;
	priv->core_clock_select = pdata->core_clock_select;
	priv->eee_fixup = pdata->eee_fixup;
	priv->hw_info = pdata->hw_info;
}

static const struct of_device_id bcmasp_of_match[] = {
	{ .compatible = "brcm,asp-v2.0", .data = &v20_plat_data },
	{ .compatible = "brcm,asp-v2.1", .data = &v21_plat_data },
	{ .compatible = "brcm,asp-v2.2", .data = &v22_plat_data },
	{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, bcmasp_of_match);

static const struct of_device_id bcmasp_mdio_of_match[] = {
	{ .compatible = "brcm,asp-v2.2-mdio", },
	{ .compatible = "brcm,asp-v2.1-mdio", },
	{ .compatible = "brcm,asp-v2.0-mdio", },
	{ /* sentinel */ },
@@ -1265,16 +1342,13 @@ static int bcmasp_probe(struct platform_device *pdev)
	if (!pdata)
		return dev_err_probe(dev, -EINVAL, "unable to find platform data\n");

	priv->init_wol = pdata->init_wol;
	priv->enable_wol = pdata->enable_wol;
	priv->destroy_wol = pdata->destroy_wol;
	priv->hw_info = pdata->hw_info;
	bcmasp_set_pdata(priv, pdata);

	/* Enable all clocks to ensure successful probing */
	bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0);

	/* Switch to the main clock */
	bcmasp_core_clock_select(priv, false);
	priv->core_clock_select(priv, false);

	bcmasp_intr2_mask_set_all(priv);
	bcmasp_intr2_clear_all(priv);
@@ -1381,7 +1455,7 @@ static int __maybe_unused bcmasp_suspend(struct device *d)
	 */
	bcmasp_core_clock_set(priv, 0, ASP_CTRL_CLOCK_CTRL_ASP_TX_DISABLE);

	bcmasp_core_clock_select(priv, true);
	priv->core_clock_select(priv, true);

	clk_disable_unprepare(priv->clk);

@@ -1399,7 +1473,7 @@ static int __maybe_unused bcmasp_resume(struct device *d)
		return ret;

	/* Switch to the main clock domain */
	bcmasp_core_clock_select(priv, false);
	priv->core_clock_select(priv, false);

	/* Re-enable all clocks for re-initialization */
	bcmasp_core_clock_set(priv, ASP_CTRL_CLOCK_CTRL_ASP_ALL_DISABLE, 0);
+21 −2
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@
#define ASP_INTR2_TX_DESC(intr)			BIT((intr) + 14)
#define ASP_INTR2_UMC0_WAKE			BIT(22)
#define ASP_INTR2_UMC1_WAKE			BIT(28)
#define ASP_INTR2_PHY_EVENT(intr)		((intr) ? BIT(30) | BIT(31) : \
						BIT(24) | BIT(25))

#define ASP_WAKEUP_INTR2_OFFSET			0x1200
#define  ASP_WAKEUP_INTR2_STATUS		0x0
@@ -33,6 +35,12 @@
#define ASP_WAKEUP_INTR2_FILT_1			BIT(3)
#define ASP_WAKEUP_INTR2_FW			BIT(4)

#define ASP_CTRL2_OFFSET			0x2000
#define  ASP_CTRL2_CORE_CLOCK_SELECT		0x0
#define   ASP_CTRL2_CORE_CLOCK_SELECT_MAIN	BIT(0)
#define  ASP_CTRL2_CPU_CLOCK_SELECT		0x4
#define   ASP_CTRL2_CPU_CLOCK_SELECT_MAIN	BIT(0)

#define ASP_TX_ANALYTICS_OFFSET			0x4c000
#define  ASP_TX_ANALYTICS_CTRL			0x0

@@ -134,8 +142,11 @@ enum asp_rx_net_filter_block {
#define ASP_EDPKT_RX_PKT_CNT			0x138
#define ASP_EDPKT_HDR_EXTR_CNT			0x13c
#define ASP_EDPKT_HDR_OUT_CNT			0x140
#define ASP_EDPKT_SPARE_REG			0x174
#define  ASP_EDPKT_SPARE_REG_EPHY_LPI		BIT(4)
#define  ASP_EDPKT_SPARE_REG_GPHY_LPI		BIT(3)

#define ASP_CTRL				0x101000
#define ASP_CTRL_OFFSET				0x101000
#define  ASP_CTRL_ASP_SW_INIT			0x04
#define   ASP_CTRL_ASP_SW_INIT_ACPUSS_CORE	BIT(0)
#define   ASP_CTRL_ASP_SW_INIT_ASP_TX		BIT(1)
@@ -306,6 +317,7 @@ struct bcmasp_intf {
	struct bcmasp_desc		*rx_edpkt_cpu;
	dma_addr_t			rx_edpkt_dma_addr;
	dma_addr_t			rx_edpkt_dma_read;
	dma_addr_t			rx_edpkt_dma_valid;

	/* RX buffer prefetcher ring*/
	void				*rx_ring_cpu;
@@ -372,6 +384,8 @@ struct bcmasp_plat_data {
	void (*init_wol)(struct bcmasp_priv *priv);
	void (*enable_wol)(struct bcmasp_intf *intf, bool en);
	void (*destroy_wol)(struct bcmasp_priv *priv);
	void (*core_clock_select)(struct bcmasp_priv *priv, bool slow);
	void (*eee_fixup)(struct bcmasp_intf *priv, bool en);
	struct bcmasp_hw_info		*hw_info;
};

@@ -390,6 +404,8 @@ struct bcmasp_priv {
	void (*init_wol)(struct bcmasp_priv *priv);
	void (*enable_wol)(struct bcmasp_intf *intf, bool en);
	void (*destroy_wol)(struct bcmasp_priv *priv);
	void (*core_clock_select)(struct bcmasp_priv *priv, bool slow);
	void (*eee_fixup)(struct bcmasp_intf *intf, bool en);

	void __iomem			*base;
	struct	bcmasp_hw_info		*hw_info;
@@ -530,7 +546,8 @@ BCMASP_CORE_IO_MACRO(rx_analytics, ASP_RX_ANALYTICS_OFFSET);
BCMASP_CORE_IO_MACRO(rx_ctrl, ASP_RX_CTRL_OFFSET);
BCMASP_CORE_IO_MACRO(rx_filter, ASP_RX_FILTER_OFFSET);
BCMASP_CORE_IO_MACRO(rx_edpkt, ASP_EDPKT_OFFSET);
BCMASP_CORE_IO_MACRO(ctrl, ASP_CTRL);
BCMASP_CORE_IO_MACRO(ctrl, ASP_CTRL_OFFSET);
BCMASP_CORE_IO_MACRO(ctrl2, ASP_CTRL2_OFFSET);

struct bcmasp_intf *bcmasp_interface_create(struct bcmasp_priv *priv,
					    struct device_node *ndev_dn, int i);
@@ -541,6 +558,8 @@ void bcmasp_enable_tx_irq(struct bcmasp_intf *intf, int en);

void bcmasp_enable_rx_irq(struct bcmasp_intf *intf, int en);

void bcmasp_enable_phy_irq(struct bcmasp_intf *intf, int en);

void bcmasp_flush_rx_port(struct bcmasp_intf *intf);

extern const struct ethtool_ops bcmasp_ethtool_ops;
+95 −108
Original line number Diff line number Diff line
@@ -382,6 +382,7 @@ static void bcmasp_netif_start(struct net_device *dev)

	bcmasp_enable_rx_irq(intf, 1);
	bcmasp_enable_tx_irq(intf, 1);
	bcmasp_enable_phy_irq(intf, 1);

	phy_start(dev->phydev);
}
@@ -674,40 +675,78 @@ static void bcmasp_adj_link(struct net_device *dev)
		phy_print_status(phydev);
}

static int bcmasp_init_rx(struct bcmasp_intf *intf)
static int bcmasp_alloc_buffers(struct bcmasp_intf *intf)
{
	struct device *kdev = &intf->parent->pdev->dev;
	struct page *buffer_pg;
	dma_addr_t dma;
	void *p;
	u32 reg;
	int ret;

	/* Alloc RX */
	intf->rx_buf_order = get_order(RING_BUFFER_SIZE);
	buffer_pg = alloc_pages(GFP_KERNEL, intf->rx_buf_order);
	if (!buffer_pg)
		return -ENOMEM;

	dma = dma_map_page(kdev, buffer_pg, 0, RING_BUFFER_SIZE,
	intf->rx_ring_cpu = page_to_virt(buffer_pg);
	intf->rx_ring_dma = dma_map_page(kdev, buffer_pg, 0, RING_BUFFER_SIZE,
					 DMA_FROM_DEVICE);
	if (dma_mapping_error(kdev, dma)) {
	if (dma_mapping_error(kdev, intf->rx_ring_dma))
		goto free_rx_buffer;

	intf->rx_edpkt_cpu = dma_alloc_coherent(kdev, DESC_RING_SIZE,
						&intf->rx_edpkt_dma_addr, GFP_KERNEL);
	if (!intf->rx_edpkt_cpu)
		goto free_rx_buffer_dma;

	/* Alloc TX */
	intf->tx_spb_cpu = dma_alloc_coherent(kdev, DESC_RING_SIZE,
					      &intf->tx_spb_dma_addr, GFP_KERNEL);
	if (!intf->tx_spb_cpu)
		goto free_rx_edpkt_dma;

	intf->tx_cbs = kcalloc(DESC_RING_COUNT, sizeof(struct bcmasp_tx_cb),
			       GFP_KERNEL);
	if (!intf->tx_cbs)
		goto free_tx_spb_dma;

	return 0;

free_tx_spb_dma:
	dma_free_coherent(kdev, DESC_RING_SIZE, intf->tx_spb_cpu,
			  intf->tx_spb_dma_addr);
free_rx_edpkt_dma:
	dma_free_coherent(kdev, DESC_RING_SIZE, intf->rx_edpkt_cpu,
			  intf->rx_edpkt_dma_addr);
free_rx_buffer_dma:
	dma_unmap_page(kdev, intf->rx_ring_dma, RING_BUFFER_SIZE,
		       DMA_FROM_DEVICE);
free_rx_buffer:
	__free_pages(buffer_pg, intf->rx_buf_order);

	return -ENOMEM;
}
	intf->rx_ring_cpu = page_to_virt(buffer_pg);
	intf->rx_ring_dma = dma;
	intf->rx_ring_dma_valid = intf->rx_ring_dma + RING_BUFFER_SIZE - 1;

	p = dma_alloc_coherent(kdev, DESC_RING_SIZE, &intf->rx_edpkt_dma_addr,
			       GFP_KERNEL);
	if (!p) {
		ret = -ENOMEM;
		goto free_rx_ring;
	}
	intf->rx_edpkt_cpu = p;
static void bcmasp_reclaim_free_buffers(struct bcmasp_intf *intf)
{
	struct device *kdev = &intf->parent->pdev->dev;

	netif_napi_add(intf->ndev, &intf->rx_napi, bcmasp_rx_poll);
	/* RX buffers */
	dma_free_coherent(kdev, DESC_RING_SIZE, intf->rx_edpkt_cpu,
			  intf->rx_edpkt_dma_addr);
	dma_unmap_page(kdev, intf->rx_ring_dma, RING_BUFFER_SIZE,
		       DMA_FROM_DEVICE);
	__free_pages(virt_to_page(intf->rx_ring_cpu), intf->rx_buf_order);

	/* TX buffers */
	dma_free_coherent(kdev, DESC_RING_SIZE, intf->tx_spb_cpu,
			  intf->tx_spb_dma_addr);
	kfree(intf->tx_cbs);
}

static void bcmasp_init_rx(struct bcmasp_intf *intf)
{
	/* Restart from index 0 */
	intf->rx_ring_dma_valid = intf->rx_ring_dma + RING_BUFFER_SIZE - 1;
	intf->rx_edpkt_dma_valid = intf->rx_edpkt_dma_addr + (DESC_RING_SIZE - 1);
	intf->rx_edpkt_dma_read = intf->rx_edpkt_dma_addr;
	intf->rx_edpkt_index = 0;

@@ -733,64 +772,23 @@ static int bcmasp_init_rx(struct bcmasp_intf *intf)
	rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_WRITE);
	rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_READ);
	rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr, RX_EDPKT_DMA_BASE);
	rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr + (DESC_RING_SIZE - 1),
			RX_EDPKT_DMA_END);
	rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_addr + (DESC_RING_SIZE - 1),
			RX_EDPKT_DMA_VALID);

	reg = UMAC2FB_CFG_DEFAULT_EN |
	      ((intf->channel + 11) << UMAC2FB_CFG_CHID_SHIFT);
	reg |= (0xd << UMAC2FB_CFG_OK_SEND_SHIFT);
	umac2fb_wl(intf, reg, UMAC2FB_CFG);

	return 0;
	rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_valid, RX_EDPKT_DMA_END);
	rx_edpkt_dma_wq(intf, intf->rx_edpkt_dma_valid, RX_EDPKT_DMA_VALID);

free_rx_ring:
	dma_unmap_page(kdev, intf->rx_ring_dma, RING_BUFFER_SIZE,
		       DMA_FROM_DEVICE);
	__free_pages(virt_to_page(intf->rx_ring_cpu), intf->rx_buf_order);

	return ret;
	umac2fb_wl(intf, UMAC2FB_CFG_DEFAULT_EN | ((intf->channel + 11) <<
		   UMAC2FB_CFG_CHID_SHIFT) | (0xd << UMAC2FB_CFG_OK_SEND_SHIFT),
		   UMAC2FB_CFG);
}

static void bcmasp_reclaim_free_all_rx(struct bcmasp_intf *intf)
{
	struct device *kdev = &intf->parent->pdev->dev;

	dma_free_coherent(kdev, DESC_RING_SIZE, intf->rx_edpkt_cpu,
			  intf->rx_edpkt_dma_addr);
	dma_unmap_page(kdev, intf->rx_ring_dma, RING_BUFFER_SIZE,
		       DMA_FROM_DEVICE);
	__free_pages(virt_to_page(intf->rx_ring_cpu), intf->rx_buf_order);
}

static int bcmasp_init_tx(struct bcmasp_intf *intf)
static void bcmasp_init_tx(struct bcmasp_intf *intf)
{
	struct device *kdev = &intf->parent->pdev->dev;
	void *p;
	int ret;

	p = dma_alloc_coherent(kdev, DESC_RING_SIZE, &intf->tx_spb_dma_addr,
			       GFP_KERNEL);
	if (!p)
		return -ENOMEM;

	intf->tx_spb_cpu = p;
	/* Restart from index 0 */
	intf->tx_spb_dma_valid = intf->tx_spb_dma_addr + DESC_RING_SIZE - 1;
	intf->tx_spb_dma_read = intf->tx_spb_dma_addr;

	intf->tx_cbs = kcalloc(DESC_RING_COUNT, sizeof(struct bcmasp_tx_cb),
			       GFP_KERNEL);
	if (!intf->tx_cbs) {
		ret = -ENOMEM;
		goto free_tx_spb;
	}

	intf->tx_spb_index = 0;
	intf->tx_spb_clean_index = 0;

	netif_napi_add_tx(intf->ndev, &intf->tx_napi, bcmasp_tx_poll);

	/* Make sure channels are disabled */
	tx_spb_ctrl_wl(intf, 0x0, TX_SPB_CTRL_ENABLE);
	tx_epkt_core_wl(intf, 0x0, TX_EPKT_C_CFG_MISC);
@@ -806,26 +804,6 @@ static int bcmasp_init_tx(struct bcmasp_intf *intf)
	tx_spb_dma_wq(intf, intf->tx_spb_dma_addr, TX_SPB_DMA_BASE);
	tx_spb_dma_wq(intf, intf->tx_spb_dma_valid, TX_SPB_DMA_END);
	tx_spb_dma_wq(intf, intf->tx_spb_dma_valid, TX_SPB_DMA_VALID);

	return 0;

free_tx_spb:
	dma_free_coherent(kdev, DESC_RING_SIZE, intf->tx_spb_cpu,
			  intf->tx_spb_dma_addr);

	return ret;
}

static void bcmasp_reclaim_free_all_tx(struct bcmasp_intf *intf)
{
	struct device *kdev = &intf->parent->pdev->dev;

	/* Free descriptors */
	dma_free_coherent(kdev, DESC_RING_SIZE, intf->tx_spb_cpu,
			  intf->tx_spb_dma_addr);

	/* Free cbs */
	kfree(intf->tx_cbs);
}

static void bcmasp_ephy_enable_set(struct bcmasp_intf *intf, bool enable)
@@ -913,12 +891,10 @@ static void bcmasp_netif_deinit(struct net_device *dev)
	/* Disable interrupts */
	bcmasp_enable_tx_irq(intf, 0);
	bcmasp_enable_rx_irq(intf, 0);
	bcmasp_enable_phy_irq(intf, 0);

	netif_napi_del(&intf->tx_napi);
	bcmasp_reclaim_free_all_tx(intf);

	netif_napi_del(&intf->rx_napi);
	bcmasp_reclaim_free_all_rx(intf);
}

static int bcmasp_stop(struct net_device *dev)
@@ -932,6 +908,8 @@ static int bcmasp_stop(struct net_device *dev)

	bcmasp_netif_deinit(dev);

	bcmasp_reclaim_free_buffers(intf);

	phy_disconnect(dev->phydev);

	/* Disable internal EPHY or external PHY */
@@ -1052,6 +1030,9 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect)
			goto err_phy_disable;
		}

		if (intf->internal_phy)
			dev->phydev->irq = PHY_MAC_INTERRUPT;

		/* Indicate that the MAC is responsible for PHY PM */
		phydev->mac_managed_pm = true;
	} else if (!intf->wolopts) {
@@ -1073,17 +1054,12 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect)
	intf->old_link = -1;
	intf->old_pause = -1;

	ret = bcmasp_init_tx(intf);
	if (ret)
		goto err_phy_disconnect;

	/* Turn on asp */
	bcmasp_init_tx(intf);
	netif_napi_add_tx(intf->ndev, &intf->tx_napi, bcmasp_tx_poll);
	bcmasp_enable_tx(intf, 1);

	ret = bcmasp_init_rx(intf);
	if (ret)
		goto err_reclaim_tx;

	bcmasp_init_rx(intf);
	netif_napi_add(intf->ndev, &intf->rx_napi, bcmasp_rx_poll);
	bcmasp_enable_rx(intf, 1);

	/* Turn on UniMAC TX/RX */
@@ -1097,12 +1073,6 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect)

	return 0;

err_reclaim_tx:
	netif_napi_del(&intf->tx_napi);
	bcmasp_reclaim_free_all_tx(intf);
err_phy_disconnect:
	if (phydev)
		phy_disconnect(phydev);
err_phy_disable:
	if (intf->internal_phy)
		bcmasp_ephy_enable_set(intf, false);
@@ -1118,13 +1088,24 @@ static int bcmasp_open(struct net_device *dev)

	netif_dbg(intf, ifup, dev, "bcmasp open\n");

	ret = clk_prepare_enable(intf->parent->clk);
	ret = bcmasp_alloc_buffers(intf);
	if (ret)
		return ret;

	ret = bcmasp_netif_init(dev, true);
	ret = clk_prepare_enable(intf->parent->clk);
	if (ret)
		goto err_free_mem;

	ret = bcmasp_netif_init(dev, true);
	if (ret) {
		clk_disable_unprepare(intf->parent->clk);
		goto err_free_mem;
	}

	return ret;

err_free_mem:
	bcmasp_reclaim_free_buffers(intf);

	return ret;
}
@@ -1333,6 +1314,9 @@ static void bcmasp_suspend_to_wol(struct bcmasp_intf *intf)
				     ASP_WAKEUP_INTR2_MASK_CLEAR);
	}

	if (intf->eee.eee_enabled && intf->parent->eee_fixup)
		intf->parent->eee_fixup(intf, true);

	netif_dbg(intf, wol, ndev, "entered WOL mode\n");
}

@@ -1381,6 +1365,9 @@ static void bcmasp_resume_from_wol(struct bcmasp_intf *intf)
{
	u32 reg;

	if (intf->eee.eee_enabled && intf->parent->eee_fixup)
		intf->parent->eee_fixup(intf, false);

	reg = umac_rl(intf, UMC_MPD_CTRL);
	reg &= ~UMC_MPD_CTRL_MPD_EN;
	umac_wl(intf, reg, UMC_MPD_CTRL);
Loading