for (i = 0; i < ring_size; i++)
if (ring->buf[i].rx_buf) {
- dma_unmap_single(&ag->dev->dev, ring->buf[i].dma_addr,
+ dma_unmap_single(&ag->pdev->dev, ring->buf[i].dma_addr,
ag->rx_buf_size, DMA_FROM_DEVICE);
skb_free_frag(ring->buf[i].rx_buf);
}
return false;
buf->rx_buf = data;
- buf->dma_addr = dma_map_single(&ag->dev->dev, data, ag->rx_buf_size,
+ buf->dma_addr = dma_map_single(&ag->pdev->dev, data, ag->rx_buf_size,
DMA_FROM_DEVICE);
desc->data = (u32) buf->dma_addr + offset;
return true;
if (!tx->buf)
return -ENOMEM;
- tx->descs_cpu = dma_alloc_coherent(NULL, ring_size * AG71XX_DESC_SIZE,
+ tx->descs_cpu = dma_alloc_coherent(&ag->pdev->dev, ring_size * AG71XX_DESC_SIZE,
&tx->descs_dma, GFP_ATOMIC);
if (!tx->descs_cpu) {
kfree(tx->buf);
int ring_size = BIT(tx->order) + BIT(rx->order);
if (tx->descs_cpu)
- dma_free_coherent(NULL, ring_size * AG71XX_DESC_SIZE,
+ dma_free_coherent(&ag->pdev->dev, ring_size * AG71XX_DESC_SIZE,
tx->descs_cpu, tx->descs_dma);
kfree(tx->buf);
udelay(20);
reset_control_assert(ag->mac_reset);
+ if (ag->mdio_reset)
+ reset_control_assert(ag->mdio_reset);
msleep(100);
reset_control_deassert(ag->mac_reset);
+ if (ag->mdio_reset)
+ reset_control_deassert(ag->mdio_reset);
msleep(200);
ag71xx_hw_setup(ag);
mii_if = AR71XX_MII0_CTRL_IF_GMII;
break;
case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
mii_if = AR71XX_MII0_CTRL_IF_RGMII;
break;
case PHY_INTERFACE_MODE_RMII:
mii_if = AR71XX_MII1_CTRL_IF_RMII;
break;
case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
mii_if = AR71XX_MII1_CTRL_IF_RGMII;
break;
default:
static void ag71xx_hw_disable(struct ag71xx *ag)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ag->lock, flags);
-
netif_stop_queue(ag->dev);
ag71xx_hw_stop(ag);
napi_disable(&ag->napi);
del_timer_sync(&ag->oom_timer);
- spin_unlock_irqrestore(&ag->lock, flags);
-
ag71xx_rings_cleanup(ag);
}
goto err_drop;
}
- dma_addr = dma_map_single(&dev->dev, skb->data, skb->len,
+ dma_addr = dma_map_single(&ag->pdev->dev, skb->data, skb->len,
DMA_TO_DEVICE);
i = ring->curr & ring_mask;
return NETDEV_TX_OK;
err_drop_unmap:
- dma_unmap_single(&dev->dev, dma_addr, skb->len, DMA_TO_DEVICE);
+ dma_unmap_single(&ag->pdev->dev, dma_addr, skb->len, DMA_TO_DEVICE);
err_drop:
dev->stats.tx_dropped++;
static int ag71xx_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct ag71xx *ag = netdev_priv(dev);
- int ret;
- switch (cmd) {
- case SIOCETHTOOL:
- if (ag->phy_dev == NULL)
- break;
-
- spin_lock_irq(&ag->lock);
- ret = phy_ethtool_ioctl(ag->phy_dev, (void *) ifr->ifr_data);
- spin_unlock_irq(&ag->lock);
- return ret;
+ switch (cmd) {
case SIOCSIFHWADDR:
if (copy_from_user
(dev->dev_addr, ifr->ifr_data, sizeof(dev->dev_addr)))
return -EOPNOTSUPP;
}
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
static void ag71xx_oom_timer_handler(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
struct ag71xx *ag = netdev_priv(dev);
+#else
+static void ag71xx_oom_timer_handler(struct timer_list *t)
+{
+ struct ag71xx *ag = from_timer(ag, t, oom_timer);
+#endif
napi_schedule(&ag->napi);
}
pktlen = desc->ctrl & pktlen_mask;
pktlen -= ETH_FCS_LEN;
- dma_unmap_single(&dev->dev, ring->buf[i].dma_addr,
+ dma_unmap_single(&ag->pdev->dev, ring->buf[i].dma_addr,
ag->rx_buf_size, DMA_FROM_DEVICE);
dev->stats.rx_packets++;
return IRQ_HANDLED;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-static void ag71xx_netpoll(struct net_device *dev)
-{
- disable_irq(dev->irq);
- ag71xx_interrupt(dev->irq, dev);
- enable_irq(dev->irq);
-}
-#endif
-
static int ag71xx_change_mtu(struct net_device *dev, int new_mtu)
{
struct ag71xx *ag = netdev_priv(dev);
.ndo_change_mtu = ag71xx_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = ag71xx_netpoll,
-#endif
};
static int ag71xx_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- struct device_node *mdio_node;
struct net_device *dev;
struct resource *res;
struct ag71xx *ag;
AG71XX_DEFAULT_MSG_ENABLE);
spin_lock_init(&ag->lock);
- ag->mac_reset = devm_reset_control_get(&pdev->dev, "mac");
+ ag->mac_reset = devm_reset_control_get_exclusive(&pdev->dev, "mac");
if (IS_ERR(ag->mac_reset)) {
dev_err(&pdev->dev, "missing mac reset\n");
return PTR_ERR(ag->mac_reset);
}
+ ag->mdio_reset = devm_reset_control_get_optional_exclusive(&pdev->dev, "mdio");
+
if (of_property_read_u32_array(np, "fifo-data", ag->fifodata, 3)) {
if (of_device_is_compatible(np, "qca,ar9130-eth") ||
of_device_is_compatible(np, "qca,ar7100-eth")) {
INIT_DELAYED_WORK(&ag->restart_work, ag71xx_restart_work_func);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
init_timer(&ag->oom_timer);
ag->oom_timer.data = (unsigned long) dev;
ag->oom_timer.function = ag71xx_oom_timer_handler;
+#else
+ timer_setup(&ag->oom_timer, ag71xx_oom_timer_handler, 0);
+#endif
tx_size = AG71XX_TX_RING_SIZE_DEFAULT;
ag->rx_ring.order = ag71xx_ring_size_order(AG71XX_RX_RING_SIZE_DEFAULT);
dev->min_mtu = 68;
dev->max_mtu = max_frame_len - ag71xx_max_frame_len(0);
- if (of_device_is_compatible(np, "qca,ar7240-eth"))
+ if (of_device_is_compatible(np, "qca,ar7240-eth") ||
+ of_device_is_compatible(np, "qca,ar7241-eth") ||
+ of_device_is_compatible(np, "qca,ar7242-eth") ||
+ of_device_is_compatible(np, "qca,ar9330-eth") ||
+ of_device_is_compatible(np, "qca,ar9340-eth") ||
+ of_device_is_compatible(np, "qca,qca9530-eth") ||
+ of_device_is_compatible(np, "qca,qca9550-eth") ||
+ of_device_is_compatible(np, "qca,qca9560-eth"))
ag->tx_hang_workaround = 1;
ag->rx_buf_offset = NET_SKB_PAD;
ag71xx_dump_regs(ag);
- if (!of_device_is_compatible(np, "simple-mfd")) {
- mdio_node = of_get_child_by_name(np, "mdio-bus");
- if (!IS_ERR(mdio_node))
- of_platform_device_create(mdio_node, NULL, NULL);
+ /*
+ * populate current node to register mdio-bus as a subdevice.
+ * the mdio bus works independently on ar7241 and later chips
+ * and we need to load mdio1 before gmac0, which can be done
+ * by adding a "simple-mfd" compatible to gmac node. The
+ * following code checks OF_POPULATED_BUS flag before populating
+ * to avoid duplicated population.
+ */
+ if (!of_node_check_flag(np, OF_POPULATED_BUS)) {
+ err = of_platform_populate(np, NULL, NULL, &pdev->dev);
+ if (err)
+ return err;
}
err = ag71xx_phy_connect(ag);