]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
Merge https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
[mirror_ubuntu-jammy-kernel.git] / drivers / net / ethernet / freescale / dpaa2 / dpaa2-eth.c
index 55b73c1136cacaeeaafee5ccf3c9a777cbf0d08a..41e225baf5712a0d9b4c347e8f713b22a2628ee5 100644 (file)
@@ -1258,6 +1258,22 @@ static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
        percpu_stats->tx_errors++;
 }
 
+static int dpaa2_eth_set_rx_vlan_filtering(struct dpaa2_eth_priv *priv,
+                                          bool enable)
+{
+       int err;
+
+       err = dpni_enable_vlan_filter(priv->mc_io, 0, priv->mc_token, enable);
+
+       if (err) {
+               netdev_err(priv->net_dev,
+                          "dpni_enable_vlan_filter failed\n");
+               return err;
+       }
+
+       return 0;
+}
+
 static int dpaa2_eth_set_rx_csum(struct dpaa2_eth_priv *priv, bool enable)
 {
        int err;
@@ -1687,7 +1703,7 @@ static int dpaa2_eth_link_state_update(struct dpaa2_eth_priv *priv)
        /* When we manage the MAC/PHY using phylink there is no need
         * to manually update the netif_carrier.
         */
-       if (priv->mac)
+       if (dpaa2_eth_is_type_phy(priv))
                goto out;
 
        /* Chech link state; speed / duplex changes are not treated yet */
@@ -1726,7 +1742,7 @@ static int dpaa2_eth_open(struct net_device *net_dev)
                           priv->dpbp_dev->obj_desc.id, priv->bpid);
        }
 
-       if (!priv->mac) {
+       if (!dpaa2_eth_is_type_phy(priv)) {
                /* We'll only start the txqs when the link is actually ready;
                 * make sure we don't race against the link up notification,
                 * which may come immediately after dpni_enable();
@@ -1748,7 +1764,7 @@ static int dpaa2_eth_open(struct net_device *net_dev)
                goto enable_err;
        }
 
-       if (priv->mac)
+       if (dpaa2_eth_is_type_phy(priv))
                phylink_start(priv->mac->phylink);
 
        return 0;
@@ -1822,11 +1838,11 @@ static int dpaa2_eth_stop(struct net_device *net_dev)
        int dpni_enabled = 0;
        int retries = 10;
 
-       if (!priv->mac) {
+       if (dpaa2_eth_is_type_phy(priv)) {
+               phylink_stop(priv->mac->phylink);
+       } else {
                netif_tx_stop_all_queues(net_dev);
                netif_carrier_off(net_dev);
-       } else {
-               phylink_stop(priv->mac->phylink);
        }
 
        /* On dpni_disable(), the MC firmware will:
@@ -1948,6 +1964,43 @@ static void dpaa2_eth_add_mc_hw_addr(const struct net_device *net_dev,
        }
 }
 
+static int dpaa2_eth_rx_add_vid(struct net_device *net_dev,
+                               __be16 vlan_proto, u16 vid)
+{
+       struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+       int err;
+
+       err = dpni_add_vlan_id(priv->mc_io, 0, priv->mc_token,
+                              vid, 0, 0, 0);
+
+       if (err) {
+               netdev_warn(priv->net_dev,
+                           "Could not add the vlan id %u\n",
+                           vid);
+               return err;
+       }
+
+       return 0;
+}
+
+static int dpaa2_eth_rx_kill_vid(struct net_device *net_dev,
+                                __be16 vlan_proto, u16 vid)
+{
+       struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+       int err;
+
+       err = dpni_remove_vlan_id(priv->mc_io, 0, priv->mc_token, vid);
+
+       if (err) {
+               netdev_warn(priv->net_dev,
+                           "Could not remove the vlan id %u\n",
+                           vid);
+               return err;
+       }
+
+       return 0;
+}
+
 static void dpaa2_eth_set_rx_mode(struct net_device *net_dev)
 {
        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
@@ -2054,6 +2107,13 @@ static int dpaa2_eth_set_features(struct net_device *net_dev,
        bool enable;
        int err;
 
+       if (changed & NETIF_F_HW_VLAN_CTAG_FILTER) {
+               enable = !!(features & NETIF_F_HW_VLAN_CTAG_FILTER);
+               err = dpaa2_eth_set_rx_vlan_filtering(priv, enable);
+               if (err)
+                       return err;
+       }
+
        if (changed & NETIF_F_RXCSUM) {
                enable = !!(features & NETIF_F_RXCSUM);
                err = dpaa2_eth_set_rx_csum(priv, enable);
@@ -2111,7 +2171,7 @@ static int dpaa2_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        if (cmd == SIOCSHWTSTAMP)
                return dpaa2_eth_ts_ioctl(dev, rq, cmd);
 
-       if (priv->mac)
+       if (dpaa2_eth_is_type_phy(priv))
                return phylink_mii_ioctl(priv->mac->phylink, rq, cmd);
 
        return -EOPNOTSUPP;
@@ -2503,6 +2563,8 @@ static const struct net_device_ops dpaa2_eth_ops = {
        .ndo_bpf = dpaa2_eth_xdp,
        .ndo_xdp_xmit = dpaa2_eth_xdp_xmit,
        .ndo_setup_tc = dpaa2_eth_setup_tc,
+       .ndo_vlan_rx_add_vid = dpaa2_eth_rx_add_vid,
+       .ndo_vlan_rx_kill_vid = dpaa2_eth_rx_kill_vid
 };
 
 static void dpaa2_eth_cdan_cb(struct dpaa2_io_notification_ctx *ctx)
@@ -4011,6 +4073,9 @@ static int dpaa2_eth_netdev_init(struct net_device *net_dev)
                            NETIF_F_LLTX | NETIF_F_HW_TC;
        net_dev->hw_features = net_dev->features;
 
+       if (priv->dpni_attrs.vlan_filter_entries)
+               net_dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+
        return 0;
 }
 
@@ -4038,10 +4103,11 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv)
 
        dpni_dev = to_fsl_mc_device(priv->net_dev->dev.parent);
        dpmac_dev = fsl_mc_get_endpoint(dpni_dev);
-       if (IS_ERR_OR_NULL(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type)
-               return 0;
 
-       if (dpaa2_mac_is_type_fixed(dpmac_dev, priv->mc_io))
+       if (PTR_ERR(dpmac_dev) == -EPROBE_DEFER)
+               return PTR_ERR(dpmac_dev);
+
+       if (IS_ERR(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type)
                return 0;
 
        mac = kzalloc(sizeof(struct dpaa2_mac), GFP_KERNEL);
@@ -4052,23 +4118,38 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv)
        mac->mc_io = priv->mc_io;
        mac->net_dev = priv->net_dev;
 
-       err = dpaa2_mac_connect(mac);
-       if (err) {
-               netdev_err(priv->net_dev, "Error connecting to the MAC endpoint\n");
-               kfree(mac);
-               return err;
-       }
+       err = dpaa2_mac_open(mac);
+       if (err)
+               goto err_free_mac;
        priv->mac = mac;
 
+       if (dpaa2_eth_is_type_phy(priv)) {
+               err = dpaa2_mac_connect(mac);
+               if (err) {
+                       netdev_err(priv->net_dev, "Error connecting to the MAC endpoint\n");
+                       goto err_close_mac;
+               }
+       }
+
        return 0;
+
+err_close_mac:
+       dpaa2_mac_close(mac);
+       priv->mac = NULL;
+err_free_mac:
+       kfree(mac);
+       return err;
 }
 
 static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv)
 {
-       if (!priv->mac)
+       if (dpaa2_eth_is_type_phy(priv))
+               dpaa2_mac_disconnect(priv->mac);
+
+       if (!dpaa2_eth_has_mac(priv))
                return;
 
-       dpaa2_mac_disconnect(priv->mac);
+       dpaa2_mac_close(priv->mac);
        kfree(priv->mac);
        priv->mac = NULL;
 }
@@ -4097,7 +4178,7 @@ static irqreturn_t dpni_irq0_handler_thread(int irq_num, void *arg)
                dpaa2_eth_update_tx_fqids(priv);
 
                rtnl_lock();
-               if (priv->mac)
+               if (dpaa2_eth_has_mac(priv))
                        dpaa2_eth_disconnect_mac(priv);
                else
                        dpaa2_eth_connect_mac(priv);