diff options
Diffstat (limited to 'drivers/net/ethernet/cortina/gemini.c')
-rw-r--r-- | drivers/net/ethernet/cortina/gemini.c | 167 |
1 files changed, 80 insertions, 87 deletions
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c index f30fa8e6ef80..fdf10318758b 100644 --- a/drivers/net/ethernet/cortina/gemini.c +++ b/drivers/net/ethernet/cortina/gemini.c @@ -44,7 +44,6 @@ #include "gemini.h" #define DRV_NAME "gmac-gemini" -#define DRV_VERSION "1.0" #define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) static int debug = -1; @@ -69,7 +68,6 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); #define DEFAULT_GMAC_RXQ_ORDER 9 #define DEFAULT_GMAC_TXQ_ORDER 8 #define DEFAULT_RX_BUF_ORDER 11 -#define DEFAULT_NAPI_WEIGHT 64 #define TX_MAX_FRAGS 16 #define TX_QUEUE_NUM 1 /* max: 6 */ #define RX_MAX_ALLOC_ORDER 2 @@ -86,6 +84,8 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); /** * struct gmac_queue_page - page buffer per-page info + * @page: the page struct + * @mapping: the dma address handle */ struct gmac_queue_page { struct page *page; @@ -304,21 +304,21 @@ static void gmac_speed_set(struct net_device *netdev) switch (phydev->speed) { case 1000: status.bits.speed = GMAC_SPEED_1000; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII) + if (phy_interface_mode_is_rgmii(phydev->interface)) status.bits.mii_rmii = GMAC_PHY_RGMII_1000; netdev_dbg(netdev, "connect %s to RGMII @ 1Gbit\n", phydev_name(phydev)); break; case 100: status.bits.speed = GMAC_SPEED_100; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII) + if (phy_interface_mode_is_rgmii(phydev->interface)) status.bits.mii_rmii = GMAC_PHY_RGMII_100_10; netdev_dbg(netdev, "connect %s to RGMII @ 100 Mbit\n", phydev_name(phydev)); break; case 10: status.bits.speed = GMAC_SPEED_10; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII) + if (phy_interface_mode_is_rgmii(phydev->interface)) status.bits.mii_rmii = GMAC_PHY_RGMII_100_10; netdev_dbg(netdev, "connect %s to RGMII @ 10 Mbit\n", phydev_name(phydev)); @@ -388,6 +388,9 @@ static int gmac_setup_phy(struct net_device *netdev) status.bits.mii_rmii = GMAC_PHY_GMII; break; case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_TXID: + case PHY_INTERFACE_MODE_RGMII_RXID: netdev_dbg(netdev, "RGMII: set GMAC0 and GMAC1 to MII/RGMII mode\n"); status.bits.mii_rmii = GMAC_PHY_RGMII_100_10; @@ -510,7 +513,6 @@ static int gmac_init(struct net_device *netdev) .rel_threshold = 0, } }; union gmac_config0 tmp; - u32 val; config0.bits.max_len = gmac_pick_rx_max_len(netdev->mtu); tmp.bits32 = readl(port->gmac_base + GMAC_CONFIG0); @@ -520,7 +522,7 @@ static int gmac_init(struct net_device *netdev) writel(config2.bits32, port->gmac_base + GMAC_CONFIG2); writel(config3.bits32, port->gmac_base + GMAC_CONFIG3); - val = readl(port->dma_base + GMAC_AHB_WEIGHT_REG); + readl(port->dma_base + GMAC_AHB_WEIGHT_REG); writel(ahb_weight.bits32, port->dma_base + GMAC_AHB_WEIGHT_REG); writel(hw_weigh.bits32, @@ -540,12 +542,6 @@ static int gmac_init(struct net_device *netdev) return 0; } -static void gmac_uninit(struct net_device *netdev) -{ - if (netdev->phydev) - phy_disconnect(netdev->phydev); -} - static int gmac_setup_txqs(struct net_device *netdev) { struct gemini_ethernet_port *port = netdev_priv(netdev); @@ -1225,7 +1221,8 @@ map_error: return -ENOMEM; } -static int gmac_start_xmit(struct sk_buff *skb, struct net_device *netdev) +static netdev_tx_t gmac_start_xmit(struct sk_buff *skb, + struct net_device *netdev) { struct gemini_ethernet_port *port = netdev_priv(netdev); unsigned short m = (1 << port->txq_order) - 1; @@ -1768,15 +1765,6 @@ static int gmac_open(struct net_device *netdev) struct gemini_ethernet_port *port = netdev_priv(netdev); int err; - if (!netdev->phydev) { - err = gmac_setup_phy(netdev); - if (err) { - netif_err(port, ifup, netdev, - "PHY init failed: %d\n", err); - return err; - } - } - err = request_irq(netdev->irq, gmac_irq, IRQF_SHARED, netdev->name, netdev); if (err) { @@ -1903,7 +1891,7 @@ static int gmac_set_mac_address(struct net_device *netdev, void *addr) { struct sockaddr *sa = addr; - memcpy(netdev->dev_addr, sa->sa_data, ETH_ALEN); + eth_hw_addr_set(netdev, sa->sa_data); gmac_write_mac_address(netdev); return 0; @@ -1931,7 +1919,7 @@ static void gmac_get_stats64(struct net_device *netdev, /* Racing with RX NAPI */ do { - start = u64_stats_fetch_begin(&port->rx_stats_syncp); + start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp); stats->rx_packets = port->stats.rx_packets; stats->rx_bytes = port->stats.rx_bytes; @@ -1943,11 +1931,11 @@ static void gmac_get_stats64(struct net_device *netdev, stats->rx_crc_errors = port->stats.rx_crc_errors; stats->rx_frame_errors = port->stats.rx_frame_errors; - } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start)); + } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start)); /* Racing with MIB and TX completion interrupts */ do { - start = u64_stats_fetch_begin(&port->ir_stats_syncp); + start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp); stats->tx_errors = port->stats.tx_errors; stats->tx_packets = port->stats.tx_packets; @@ -1957,15 +1945,15 @@ static void gmac_get_stats64(struct net_device *netdev, stats->rx_missed_errors = port->stats.rx_missed_errors; stats->rx_fifo_errors = port->stats.rx_fifo_errors; - } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start)); + } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start)); /* Racing with hard_start_xmit */ do { - start = u64_stats_fetch_begin(&port->tx_stats_syncp); + start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp); stats->tx_dropped = port->stats.tx_dropped; - } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start)); + } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start)); stats->rx_dropped += stats->rx_missed_errors; } @@ -2043,18 +2031,18 @@ static void gmac_get_ethtool_stats(struct net_device *netdev, /* Racing with MIB interrupt */ do { p = values; - start = u64_stats_fetch_begin(&port->ir_stats_syncp); + start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp); for (i = 0; i < RX_STATS_NUM; i++) *p++ = port->hw_stats[i]; - } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start)); + } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start)); values = p; /* Racing with RX NAPI */ do { p = values; - start = u64_stats_fetch_begin(&port->rx_stats_syncp); + start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp); for (i = 0; i < RX_STATUS_NUM; i++) *p++ = port->rx_stats[i]; @@ -2062,13 +2050,13 @@ static void gmac_get_ethtool_stats(struct net_device *netdev, *p++ = port->rx_csum_stats[i]; *p++ = port->rx_napi_exits; - } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start)); + } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start)); values = p; /* Racing with TX start_xmit */ do { p = values; - start = u64_stats_fetch_begin(&port->tx_stats_syncp); + start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp); for (i = 0; i < TX_MAX_FRAGS; i++) { *values++ = port->tx_frag_stats[i]; @@ -2077,7 +2065,7 @@ static void gmac_get_ethtool_stats(struct net_device *netdev, *values++ = port->tx_frags_linearized; *values++ = port->tx_hw_csummed; - } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start)); + } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start)); } static int gmac_get_ksettings(struct net_device *netdev, @@ -2119,12 +2107,13 @@ static void gmac_get_pauseparam(struct net_device *netdev, } static void gmac_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *rp) + struct ethtool_ringparam *rp, + struct kernel_ethtool_ringparam *kernel_rp, + struct netlink_ext_ack *extack) { struct gemini_ethernet_port *port = netdev_priv(netdev); - union gmac_config0 config0; - config0.bits32 = readl(port->gmac_base + GMAC_CONFIG0); + readl(port->gmac_base + GMAC_CONFIG0); rp->rx_max_pending = 1 << 15; rp->rx_mini_max_pending = 0; @@ -2138,7 +2127,9 @@ static void gmac_get_ringparam(struct net_device *netdev, } static int gmac_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *rp) + struct ethtool_ringparam *rp, + struct kernel_ethtool_ringparam *kernel_rp, + struct netlink_ext_ack *extack) { struct gemini_ethernet_port *port = netdev_priv(netdev); int err = 0; @@ -2159,7 +2150,9 @@ static int gmac_set_ringparam(struct net_device *netdev, } static int gmac_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ecmd) + struct ethtool_coalesce *ecmd, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) { struct gemini_ethernet_port *port = netdev_priv(netdev); @@ -2171,7 +2164,9 @@ static int gmac_get_coalesce(struct net_device *netdev, } static int gmac_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ecmd) + struct ethtool_coalesce *ecmd, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) { struct gemini_ethernet_port *port = netdev_priv(netdev); @@ -2204,13 +2199,11 @@ static void gmac_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) { strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); strcpy(info->bus_info, netdev->dev_id ? "1" : "0"); } static const struct net_device_ops gmac_351x_ops = { .ndo_init = gmac_init, - .ndo_uninit = gmac_uninit, .ndo_open = gmac_open, .ndo_stop = gmac_stop, .ndo_start_xmit = gmac_start_xmit, @@ -2224,6 +2217,8 @@ static const struct net_device_ops gmac_351x_ops = { }; static const struct ethtool_ops gmac_351x_ethtool_ops = { + .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS | + ETHTOOL_COALESCE_MAX_FRAMES, .get_sset_count = gmac_get_sset_count, .get_strings = gmac_get_strings, .get_ethtool_stats = gmac_get_ethtool_stats, @@ -2294,8 +2289,10 @@ static irqreturn_t gemini_port_irq(int irq, void *data) static void gemini_port_remove(struct gemini_ethernet_port *port) { - if (port->netdev) + if (port->netdev) { + phy_disconnect(port->netdev->phydev); unregister_netdev(port->netdev); + } clk_disable_unprepare(port->pclk); geth_cleanup_freeq(port->geth); } @@ -2365,13 +2362,13 @@ static void gemini_port_save_mac_addr(struct gemini_ethernet_port *port) static int gemini_ethernet_port_probe(struct platform_device *pdev) { char *port_names[2] = { "ethernet0", "ethernet1" }; + struct device_node *np = pdev->dev.of_node; struct gemini_ethernet_port *port; struct device *dev = &pdev->dev; struct gemini_ethernet *geth; struct net_device *netdev; - struct resource *gmacres; - struct resource *dmares; struct device *parent; + u8 mac[ETH_ALEN]; unsigned int id; int irq; int ret; @@ -2388,7 +2385,7 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev) dev_info(dev, "probe %s ID %d\n", dev_name(dev), id); - netdev = alloc_etherdev_mq(sizeof(*port), TX_QUEUE_NUM); + netdev = devm_alloc_etherdev_mqs(dev, sizeof(*port), TX_QUEUE_NUM, TX_QUEUE_NUM); if (!netdev) { dev_err(dev, "Can't allocate ethernet device #%d\n", id); return -ENOMEM; @@ -2403,24 +2400,18 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev) port->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); /* DMA memory */ - dmares = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!dmares) { - dev_err(dev, "no DMA resource\n"); - return -ENODEV; - } - port->dma_base = devm_ioremap_resource(dev, dmares); - if (IS_ERR(port->dma_base)) + port->dma_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); + if (IS_ERR(port->dma_base)) { + dev_err(dev, "get DMA address failed\n"); return PTR_ERR(port->dma_base); + } /* GMAC config memory */ - gmacres = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!gmacres) { - dev_err(dev, "no GMAC resource\n"); - return -ENODEV; - } - port->gmac_base = devm_ioremap_resource(dev, gmacres); - if (IS_ERR(port->gmac_base)) + port->gmac_base = devm_platform_get_and_ioremap_resource(pdev, 1, NULL); + if (IS_ERR(port->gmac_base)) { + dev_err(dev, "get GMAC address failed\n"); return PTR_ERR(port->gmac_base); + } /* Interrupt */ irq = platform_get_irq(pdev, 0); @@ -2445,7 +2436,8 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev) port->reset = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(port->reset)) { dev_err(dev, "no reset\n"); - return PTR_ERR(port->reset); + ret = PTR_ERR(port->reset); + goto unprepare; } reset_control_reset(port->reset); usleep_range(100, 500); @@ -2479,17 +2471,22 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev) netdev->max_mtu = 10236 - VLAN_ETH_HLEN; port->freeq_refill = 0; - netif_napi_add(netdev, &port->napi, gmac_napi_poll, - DEFAULT_NAPI_WEIGHT); + netif_napi_add(netdev, &port->napi, gmac_napi_poll); + + ret = of_get_mac_address(np, mac); + if (!ret) { + dev_info(dev, "Setting macaddr from DT %pM\n", mac); + memcpy(port->mac_addr, mac, ETH_ALEN); + } if (is_valid_ether_addr((void *)port->mac_addr)) { - memcpy(netdev->dev_addr, port->mac_addr, ETH_ALEN); + eth_hw_addr_set(netdev, (u8 *)port->mac_addr); } else { dev_dbg(dev, "ethernet address 0x%08x%08x%08x invalid\n", port->mac_addr[0], port->mac_addr[1], port->mac_addr[2]); dev_info(dev, "using a random ethernet address\n"); - eth_random_addr(netdev->dev_addr); + eth_hw_addr_random(netdev); } gmac_write_mac_address(netdev); @@ -2501,23 +2498,23 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev) port_names[port->id], port); if (ret) - return ret; + goto unprepare; - ret = register_netdev(netdev); - if (!ret) { - netdev_info(netdev, - "irq %d, DMA @ 0x%pap, GMAC @ 0x%pap\n", - port->irq, &dmares->start, - &gmacres->start); - ret = gmac_setup_phy(netdev); - if (ret) - netdev_info(netdev, - "PHY init failed, deferring to ifup time\n"); - return 0; + ret = gmac_setup_phy(netdev); + if (ret) { + netdev_err(netdev, + "PHY init failed\n"); + goto unprepare; } - port->netdev = NULL; - free_netdev(netdev); + ret = register_netdev(netdev); + if (ret) + goto unprepare; + + return 0; + +unprepare: + clk_disable_unprepare(port->pclk); return ret; } @@ -2526,7 +2523,7 @@ static int gemini_ethernet_port_remove(struct platform_device *pdev) struct gemini_ethernet_port *port = platform_get_drvdata(pdev); gemini_port_remove(port); - free_netdev(port->netdev); + return 0; } @@ -2552,17 +2549,13 @@ static int gemini_ethernet_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct gemini_ethernet *geth; unsigned int retry = 5; - struct resource *res; u32 val; /* Global registers */ geth = devm_kzalloc(dev, sizeof(*geth), GFP_KERNEL); if (!geth) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - geth->base = devm_ioremap_resource(dev, res); + geth->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); if (IS_ERR(geth->base)) return PTR_ERR(geth->base); geth->dev = dev; |