diff options
Diffstat (limited to 'drivers/net/ethernet/microchip/lan966x/lan966x_main.c')
| -rw-r--r-- | drivers/net/ethernet/microchip/lan966x/lan966x_main.c | 92 |
1 files changed, 53 insertions, 39 deletions
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index fbb0bb4594cd..47752d3fde0b 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -5,9 +5,10 @@ #include <linux/if_vlan.h> #include <linux/iopoll.h> #include <linux/ip.h> -#include <linux/of_platform.h> +#include <linux/of.h> #include <linux/of_net.h> #include <linux/phy/phy.h> +#include <linux/platform_device.h> #include <linux/reset.h> #include <net/addrconf.h> @@ -275,7 +276,7 @@ static int lan966x_port_ifh_xmit(struct sk_buff *skb, ++i; } - /* Inidcate EOF and valid bytes in the last word */ + /* Indicate EOF and valid bytes in the last word */ lan_wr(QS_INJ_CTRL_GAP_SIZE_SET(1) | QS_INJ_CTRL_VLD_BYTES_SET(skb->len < LAN966X_BUFFER_MIN_SZ ? 0 : last) | @@ -352,6 +353,11 @@ static void lan966x_ifh_set_rew_op(void *ifh, u64 rew_op) lan966x_ifh_set(ifh, rew_op, IFH_POS_REW_CMD, IFH_WID_REW_CMD); } +static void lan966x_ifh_set_oam_type(void *ifh, u64 oam_type) +{ + lan966x_ifh_set(ifh, oam_type, IFH_POS_PDU_TYPE, IFH_WID_PDU_TYPE); +} + static void lan966x_ifh_set_timestamp(void *ifh, u64 timestamp) { lan966x_ifh_set(ifh, timestamp, IFH_POS_TIMESTAMP, IFH_WID_TIMESTAMP); @@ -379,6 +385,7 @@ static netdev_tx_t lan966x_port_xmit(struct sk_buff *skb, return err; lan966x_ifh_set_rew_op(ifh, LAN966X_SKB_CB(skb)->rew_op); + lan966x_ifh_set_oam_type(ifh, LAN966X_SKB_CB(skb)->pdu_type); lan966x_ifh_set_timestamp(ifh, LAN966X_SKB_CB(skb)->ts_id); } @@ -401,7 +408,7 @@ static int lan966x_port_change_mtu(struct net_device *dev, int new_mtu) lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(LAN966X_HW_MTU(new_mtu)), lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port)); - dev->mtu = new_mtu; + WRITE_ONCE(dev->mtu, new_mtu); if (!lan966x->fdma) return 0; @@ -449,39 +456,46 @@ static int lan966x_port_get_parent_id(struct net_device *dev, return 0; } -static int lan966x_port_ioctl(struct net_device *dev, struct ifreq *ifr, - int cmd) +static int lan966x_port_hwtstamp_get(struct net_device *dev, + struct kernel_hwtstamp_config *cfg) +{ + struct lan966x_port *port = netdev_priv(dev); + + if (!port->lan966x->ptp) + return -EOPNOTSUPP; + + lan966x_ptp_hwtstamp_get(port, cfg); + + return 0; +} + +static int lan966x_port_hwtstamp_set(struct net_device *dev, + struct kernel_hwtstamp_config *cfg, + struct netlink_ext_ack *extack) { struct lan966x_port *port = netdev_priv(dev); int err; - if (cmd == SIOCSHWTSTAMP) { - err = lan966x_ptp_setup_traps(port, ifr); - if (err) - return err; - } + if (cfg->source != HWTSTAMP_SOURCE_NETDEV && + cfg->source != HWTSTAMP_SOURCE_PHYLIB) + return -EOPNOTSUPP; - if (!phy_has_hwtstamp(dev->phydev) && port->lan966x->ptp) { - switch (cmd) { - case SIOCSHWTSTAMP: - err = lan966x_ptp_hwtstamp_set(port, ifr); - if (err) - lan966x_ptp_del_traps(port); + if (cfg->source == HWTSTAMP_SOURCE_NETDEV && !port->lan966x->ptp) + return -EOPNOTSUPP; + + err = lan966x_ptp_setup_traps(port, cfg); + if (err) + return err; + if (cfg->source == HWTSTAMP_SOURCE_NETDEV) { + err = lan966x_ptp_hwtstamp_set(port, cfg, extack); + if (err) { + lan966x_ptp_del_traps(port); return err; - case SIOCGHWTSTAMP: - return lan966x_ptp_hwtstamp_get(port, ifr); } } - if (!dev->phydev) - return -ENODEV; - - err = phy_mii_ioctl(dev->phydev, ifr, cmd); - if (err && cmd == SIOCSHWTSTAMP) - lan966x_ptp_del_traps(port); - - return err; + return 0; } static const struct net_device_ops lan966x_port_netdev_ops = { @@ -494,10 +508,12 @@ static const struct net_device_ops lan966x_port_netdev_ops = { .ndo_get_stats64 = lan966x_stats_get, .ndo_set_mac_address = lan966x_port_set_mac_address, .ndo_get_port_parent_id = lan966x_port_get_parent_id, - .ndo_eth_ioctl = lan966x_port_ioctl, + .ndo_eth_ioctl = phy_do_ioctl, .ndo_setup_tc = lan966x_tc_setup, .ndo_bpf = lan966x_xdp, .ndo_xdp_xmit = lan966x_xdp_xmit, + .ndo_hwtstamp_get = lan966x_port_hwtstamp_get, + .ndo_hwtstamp_set = lan966x_port_hwtstamp_set, }; bool lan966x_netdevice_check(const struct net_device *dev) @@ -510,7 +526,7 @@ bool lan966x_hw_offload(struct lan966x *lan966x, u32 port, struct sk_buff *skb) u32 val; /* The IGMP and MLD frames are not forward by the HW if - * multicast snooping is enabled, therefor don't mark as + * multicast snooping is enabled, therefore don't mark as * offload to allow the SW to forward the frames accordingly. */ val = lan_rd(lan966x, ANA_CPU_FWD_CFG(port)); @@ -661,7 +677,6 @@ static irqreturn_t lan966x_xtr_irq_handler(int irq, void *args) skb = netdev_alloc_skb(dev, len); if (unlikely(!skb)) { netdev_err(dev, "Unable to allocate sk_buff\n"); - err = -ENOMEM; break; } buf_len = len - ETH_FCS_LEN; @@ -807,6 +822,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p, NETIF_F_HW_VLAN_STAG_TX | NETIF_F_HW_TC; dev->hw_features |= NETIF_F_HW_TC; + dev->see_all_hwtstamp_requests = true; dev->needed_headroom = IFH_LEN_BYTES; eth_hw_addr_gen(dev, lan966x->base_mac, p + 1); @@ -818,7 +834,6 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p, port->phylink_config.type = PHYLINK_NETDEV; port->phylink_pcs.poll = true; port->phylink_pcs.ops = &lan966x_phylink_pcs_ops; - port->phylink_pcs.neg_mode = true; port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD; @@ -864,6 +879,7 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p, lan966x_vlan_port_set_vlan_aware(port, 0); lan966x_vlan_port_set_vid(port, HOST_PVID, false, false); lan966x_vlan_port_apply(port); + lan966x_vlan_port_rew_host(port); return 0; } @@ -1077,8 +1093,6 @@ static int lan966x_probe(struct platform_device *pdev) platform_set_drvdata(pdev, lan966x); lan966x->dev = &pdev->dev; - lan966x->debugfs_root = debugfs_create_dir("lan966x", NULL); - if (!device_get_mac_address(&pdev->dev, mac_addr)) { ether_addr_copy(lan966x->base_mac, mac_addr); } else { @@ -1108,8 +1122,8 @@ static int lan966x_probe(struct platform_device *pdev) /* set irq */ lan966x->xtr_irq = platform_get_irq_byname(pdev, "xtr"); - if (lan966x->xtr_irq <= 0) - return -EINVAL; + if (lan966x->xtr_irq < 0) + return lan966x->xtr_irq; err = devm_request_threaded_irq(&pdev->dev, lan966x->xtr_irq, NULL, lan966x_xtr_irq_handler, IRQF_ONESHOT, @@ -1169,6 +1183,8 @@ static int lan966x_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, -ENODEV, "no ethernet-ports child found\n"); + lan966x->debugfs_root = debugfs_create_dir("lan966x", NULL); + /* init switch */ lan966x_init(lan966x); lan966x_stats_init(lan966x); @@ -1245,12 +1261,13 @@ cleanup_ports: cancel_delayed_work_sync(&lan966x->stats_work); destroy_workqueue(lan966x->stats_queue); - mutex_destroy(&lan966x->stats_lock); + + debugfs_remove_recursive(lan966x->debugfs_root); return err; } -static int lan966x_remove(struct platform_device *pdev) +static void lan966x_remove(struct platform_device *pdev) { struct lan966x *lan966x = platform_get_drvdata(pdev); @@ -1261,7 +1278,6 @@ static int lan966x_remove(struct platform_device *pdev) cancel_delayed_work_sync(&lan966x->stats_work); destroy_workqueue(lan966x->stats_queue); - mutex_destroy(&lan966x->stats_lock); lan966x_mac_purge_entries(lan966x); lan966x_mdb_deinit(lan966x); @@ -1269,8 +1285,6 @@ static int lan966x_remove(struct platform_device *pdev) lan966x_ptp_deinit(lan966x); debugfs_remove_recursive(lan966x->debugfs_root); - - return 0; } static struct platform_driver lan966x_driver = { |
