Commit 3b631e52 authored by David S. Miller's avatar David S. Miller

Merge branch 'mediatek-fixes'

Sean Wang says:

====================
net: ethernet: mediatek: a couple of fixes

a couple of fixes come out from integrating with linux-4.8 rc1
they all are verified and workable on linux-4.8 rc1

Changes since v1:
- usage of loops to work out if all required clock are ready instead
of tedious coding
- remove redundant pinctrl setup that is already done by core driver
thanks for careful and patient reviewing by Andrew Lunn
- splitting distinct changes into the separate patches
- change variable naming from err to ret for readable coding

Changes since v2:
- restore to original clock disabling sequence that is changed
accidentally in the last version
- refine the commit log that would cause misunderstanding what has
been done in the changes
- refine the commit log that would cause footnote losing due to
improper delimiter use

Changes since v3:
- fix git rejects caused by mixing a change from net-next, so
remake the patch set based on the current net branch again.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9264251e aa6e8a54
...@@ -50,6 +50,10 @@ static const struct mtk_ethtool_stats { ...@@ -50,6 +50,10 @@ static const struct mtk_ethtool_stats {
MTK_ETHTOOL_STAT(rx_flow_control_packets), MTK_ETHTOOL_STAT(rx_flow_control_packets),
}; };
static const char * const mtk_clks_source_name[] = {
"ethif", "esw", "gp1", "gp2"
};
void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg) void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
{ {
__raw_writel(val, eth->base + reg); __raw_writel(val, eth->base + reg);
...@@ -291,7 +295,7 @@ static int mtk_phy_connect(struct mtk_mac *mac) ...@@ -291,7 +295,7 @@ static int mtk_phy_connect(struct mtk_mac *mac)
static int mtk_mdio_init(struct mtk_eth *eth) static int mtk_mdio_init(struct mtk_eth *eth)
{ {
struct device_node *mii_np; struct device_node *mii_np;
int err; int ret;
mii_np = of_get_child_by_name(eth->dev->of_node, "mdio-bus"); mii_np = of_get_child_by_name(eth->dev->of_node, "mdio-bus");
if (!mii_np) { if (!mii_np) {
...@@ -300,13 +304,13 @@ static int mtk_mdio_init(struct mtk_eth *eth) ...@@ -300,13 +304,13 @@ static int mtk_mdio_init(struct mtk_eth *eth)
} }
if (!of_device_is_available(mii_np)) { if (!of_device_is_available(mii_np)) {
err = 0; ret = -ENODEV;
goto err_put_node; goto err_put_node;
} }
eth->mii_bus = mdiobus_alloc(); eth->mii_bus = devm_mdiobus_alloc(eth->dev);
if (!eth->mii_bus) { if (!eth->mii_bus) {
err = -ENOMEM; ret = -ENOMEM;
goto err_put_node; goto err_put_node;
} }
...@@ -317,19 +321,11 @@ static int mtk_mdio_init(struct mtk_eth *eth) ...@@ -317,19 +321,11 @@ static int mtk_mdio_init(struct mtk_eth *eth)
eth->mii_bus->parent = eth->dev; eth->mii_bus->parent = eth->dev;
snprintf(eth->mii_bus->id, MII_BUS_ID_SIZE, "%s", mii_np->name); snprintf(eth->mii_bus->id, MII_BUS_ID_SIZE, "%s", mii_np->name);
err = of_mdiobus_register(eth->mii_bus, mii_np); ret = of_mdiobus_register(eth->mii_bus, mii_np);
if (err)
goto err_free_bus;
return 0;
err_free_bus:
mdiobus_free(eth->mii_bus);
err_put_node: err_put_node:
of_node_put(mii_np); of_node_put(mii_np);
eth->mii_bus = NULL; return ret;
return err;
} }
static void mtk_mdio_cleanup(struct mtk_eth *eth) static void mtk_mdio_cleanup(struct mtk_eth *eth)
...@@ -338,8 +334,6 @@ static void mtk_mdio_cleanup(struct mtk_eth *eth) ...@@ -338,8 +334,6 @@ static void mtk_mdio_cleanup(struct mtk_eth *eth)
return; return;
mdiobus_unregister(eth->mii_bus); mdiobus_unregister(eth->mii_bus);
of_node_put(eth->mii_bus->dev.of_node);
mdiobus_free(eth->mii_bus);
} }
static inline void mtk_irq_disable(struct mtk_eth *eth, u32 mask) static inline void mtk_irq_disable(struct mtk_eth *eth, u32 mask)
...@@ -588,14 +582,15 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, ...@@ -588,14 +582,15 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
dma_addr_t mapped_addr; dma_addr_t mapped_addr;
unsigned int nr_frags; unsigned int nr_frags;
int i, n_desc = 1; int i, n_desc = 1;
u32 txd4 = 0; u32 txd4 = 0, fport;
itxd = ring->next_free; itxd = ring->next_free;
if (itxd == ring->last_free) if (itxd == ring->last_free)
return -ENOMEM; return -ENOMEM;
/* set the forward port */ /* set the forward port */
txd4 |= (mac->id + 1) << TX_DMA_FPORT_SHIFT; fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT;
txd4 |= fport;
tx_buf = mtk_desc_to_tx_buf(ring, itxd); tx_buf = mtk_desc_to_tx_buf(ring, itxd);
memset(tx_buf, 0, sizeof(*tx_buf)); memset(tx_buf, 0, sizeof(*tx_buf));
...@@ -653,7 +648,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev, ...@@ -653,7 +648,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
WRITE_ONCE(txd->txd3, (TX_DMA_SWC | WRITE_ONCE(txd->txd3, (TX_DMA_SWC |
TX_DMA_PLEN0(frag_map_size) | TX_DMA_PLEN0(frag_map_size) |
last_frag * TX_DMA_LS0)); last_frag * TX_DMA_LS0));
WRITE_ONCE(txd->txd4, 0); WRITE_ONCE(txd->txd4, fport);
tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC; tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
tx_buf = mtk_desc_to_tx_buf(ring, txd); tx_buf = mtk_desc_to_tx_buf(ring, txd);
...@@ -865,7 +860,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, ...@@ -865,7 +860,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
/* receive data */ /* receive data */
skb = build_skb(data, ring->frag_size); skb = build_skb(data, ring->frag_size);
if (unlikely(!skb)) { if (unlikely(!skb)) {
put_page(virt_to_head_page(new_data)); skb_free_frag(new_data);
netdev->stats.rx_dropped++; netdev->stats.rx_dropped++;
goto release_desc; goto release_desc;
} }
...@@ -1506,10 +1501,7 @@ static void mtk_uninit(struct net_device *dev) ...@@ -1506,10 +1501,7 @@ static void mtk_uninit(struct net_device *dev)
struct mtk_eth *eth = mac->hw; struct mtk_eth *eth = mac->hw;
phy_disconnect(mac->phy_dev); phy_disconnect(mac->phy_dev);
mtk_mdio_cleanup(eth);
mtk_irq_disable(eth, ~0); mtk_irq_disable(eth, ~0);
free_irq(eth->irq[1], dev);
free_irq(eth->irq[2], dev);
} }
static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
...@@ -1813,6 +1805,7 @@ static int mtk_probe(struct platform_device *pdev) ...@@ -1813,6 +1805,7 @@ static int mtk_probe(struct platform_device *pdev)
if (!eth) if (!eth)
return -ENOMEM; return -ENOMEM;
eth->dev = &pdev->dev;
eth->base = devm_ioremap_resource(&pdev->dev, res); eth->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(eth->base)) if (IS_ERR(eth->base))
return PTR_ERR(eth->base); return PTR_ERR(eth->base);
...@@ -1847,21 +1840,21 @@ static int mtk_probe(struct platform_device *pdev) ...@@ -1847,21 +1840,21 @@ static int mtk_probe(struct platform_device *pdev)
return -ENXIO; return -ENXIO;
} }
} }
for (i = 0; i < ARRAY_SIZE(eth->clks); i++) {
eth->clk_ethif = devm_clk_get(&pdev->dev, "ethif"); eth->clks[i] = devm_clk_get(eth->dev,
eth->clk_esw = devm_clk_get(&pdev->dev, "esw"); mtk_clks_source_name[i]);
eth->clk_gp1 = devm_clk_get(&pdev->dev, "gp1"); if (IS_ERR(eth->clks[i])) {
eth->clk_gp2 = devm_clk_get(&pdev->dev, "gp2"); if (PTR_ERR(eth->clks[i]) == -EPROBE_DEFER)
if (IS_ERR(eth->clk_esw) || IS_ERR(eth->clk_gp1) || return -EPROBE_DEFER;
IS_ERR(eth->clk_gp2) || IS_ERR(eth->clk_ethif))
return -ENODEV; return -ENODEV;
}
}
clk_prepare_enable(eth->clk_ethif); clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
clk_prepare_enable(eth->clk_esw); clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
clk_prepare_enable(eth->clk_gp1); clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
clk_prepare_enable(eth->clk_gp2); clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
eth->dev = &pdev->dev;
eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE); eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE);
INIT_WORK(&eth->pending_work, mtk_pending_work); INIT_WORK(&eth->pending_work, mtk_pending_work);
...@@ -1903,15 +1896,24 @@ static int mtk_probe(struct platform_device *pdev) ...@@ -1903,15 +1896,24 @@ static int mtk_probe(struct platform_device *pdev)
static int mtk_remove(struct platform_device *pdev) static int mtk_remove(struct platform_device *pdev)
{ {
struct mtk_eth *eth = platform_get_drvdata(pdev); struct mtk_eth *eth = platform_get_drvdata(pdev);
int i;
clk_disable_unprepare(eth->clk_ethif); /* stop all devices to make sure that dma is properly shut down */
clk_disable_unprepare(eth->clk_esw); for (i = 0; i < MTK_MAC_COUNT; i++) {
clk_disable_unprepare(eth->clk_gp1); if (!eth->netdev[i])
clk_disable_unprepare(eth->clk_gp2); continue;
mtk_stop(eth->netdev[i]);
}
clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
netif_napi_del(&eth->tx_napi); netif_napi_del(&eth->tx_napi);
netif_napi_del(&eth->rx_napi); netif_napi_del(&eth->rx_napi);
mtk_cleanup(eth); mtk_cleanup(eth);
mtk_mdio_cleanup(eth);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
return 0; return 0;
......
...@@ -290,6 +290,17 @@ enum mtk_tx_flags { ...@@ -290,6 +290,17 @@ enum mtk_tx_flags {
MTK_TX_FLAGS_PAGE0 = 0x02, MTK_TX_FLAGS_PAGE0 = 0x02,
}; };
/* This enum allows us to identify how the clock is defined on the array of the
* clock in the order
*/
enum mtk_clks_map {
MTK_CLK_ETHIF,
MTK_CLK_ESW,
MTK_CLK_GP1,
MTK_CLK_GP2,
MTK_CLK_MAX
};
/* struct mtk_tx_buf - This struct holds the pointers to the memory pointed at /* struct mtk_tx_buf - This struct holds the pointers to the memory pointed at
* by the TX descriptor s * by the TX descriptor s
* @skb: The SKB pointer of the packet being sent * @skb: The SKB pointer of the packet being sent
...@@ -370,10 +381,7 @@ struct mtk_rx_ring { ...@@ -370,10 +381,7 @@ struct mtk_rx_ring {
* @scratch_ring: Newer SoCs need memory for a second HW managed TX ring * @scratch_ring: Newer SoCs need memory for a second HW managed TX ring
* @phy_scratch_ring: physical address of scratch_ring * @phy_scratch_ring: physical address of scratch_ring
* @scratch_head: The scratch memory that scratch_ring points to. * @scratch_head: The scratch memory that scratch_ring points to.
* @clk_ethif: The ethif clock * @clks: clock array for all clocks required
* @clk_esw: The switch clock
* @clk_gp1: The gmac1 clock
* @clk_gp2: The gmac2 clock
* @mii_bus: If there is a bus we need to create an instance for it * @mii_bus: If there is a bus we need to create an instance for it
* @pending_work: The workqueue used to reset the dma ring * @pending_work: The workqueue used to reset the dma ring
*/ */
...@@ -400,10 +408,8 @@ struct mtk_eth { ...@@ -400,10 +408,8 @@ struct mtk_eth {
struct mtk_tx_dma *scratch_ring; struct mtk_tx_dma *scratch_ring;
dma_addr_t phy_scratch_ring; dma_addr_t phy_scratch_ring;
void *scratch_head; void *scratch_head;
struct clk *clk_ethif; struct clk *clks[MTK_CLK_MAX];
struct clk *clk_esw;
struct clk *clk_gp1;
struct clk *clk_gp2;
struct mii_bus *mii_bus; struct mii_bus *mii_bus;
struct work_struct pending_work; struct work_struct pending_work;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment