Commit 3b83fa94 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'dpaa2-switch-small-improvements'



Ioana Ciornei says:

====================
dpaa2-switch: small improvements

This patch set consists of a series of small improvements on the
dpaa2-switch driver ranging from adding some more verbosity when
encountering errors to reorganizing code to be easily extensible.

Changes in v3:
- 4/8: removed the fixes tag and moved it to the commit message
- 5/8: specified that there is no user-visible effect
- 6/8: removed the initialization of the err variable

Changes in v2:
- No changes to the actual diff, only rephrased some commit messages and
  added more information.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d11db8ad 71150d94
Loading
Loading
Loading
Loading
+84 −48
Original line number Diff line number Diff line
@@ -289,7 +289,7 @@ static int dpaa2_switch_port_add_vlan(struct ethsw_port_priv *port_priv,
	int err;

	if (port_priv->vlans[vid]) {
		netdev_warn(netdev, "VLAN %d already configured\n", vid);
		netdev_err(netdev, "VLAN %d already configured\n", vid);
		return -EEXIST;
	}

@@ -1509,9 +1509,9 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
	struct device *dev = (struct device *)arg;
	struct ethsw_core *ethsw = dev_get_drvdata(dev);
	struct ethsw_port_priv *port_priv;
	u32 status = ~0;
	int err, if_id;
	bool had_mac;
	u32 status;

	err = dpsw_get_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle,
				  DPSW_IRQ_INDEX_IF, &status);
@@ -1523,12 +1523,11 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
	if_id = (status & 0xFFFF0000) >> 16;
	port_priv = ethsw->ports[if_id];

	if (status & DPSW_IRQ_EVENT_LINK_CHANGED) {
	if (status & DPSW_IRQ_EVENT_LINK_CHANGED)
		dpaa2_switch_port_link_state_update(port_priv->netdev);
		dpaa2_switch_port_set_mac_addr(port_priv);
	}

	if (status & DPSW_IRQ_EVENT_ENDPOINT_CHANGED) {
		dpaa2_switch_port_set_mac_addr(port_priv);
		/* We can avoid locking because the "endpoint changed" IRQ
		 * handler is the only one who changes priv->mac at runtime,
		 * so we are not racing with anyone.
@@ -1540,20 +1539,20 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
			dpaa2_switch_port_connect_mac(port_priv);
	}

out:
	err = dpsw_clear_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle,
				    DPSW_IRQ_INDEX_IF, status);
	if (err)
		dev_err(dev, "Can't clear irq status (err %d)\n", err);

out:
	return IRQ_HANDLED;
}

static int dpaa2_switch_setup_irqs(struct fsl_mc_device *sw_dev)
{
	u32 mask = DPSW_IRQ_EVENT_LINK_CHANGED | DPSW_IRQ_EVENT_ENDPOINT_CHANGED;
	struct device *dev = &sw_dev->dev;
	struct ethsw_core *ethsw = dev_get_drvdata(dev);
	u32 mask = DPSW_IRQ_EVENT_LINK_CHANGED;
	struct fsl_mc_device_irq *irq;
	int err;

@@ -1775,8 +1774,10 @@ int dpaa2_switch_port_vlans_add(struct net_device *netdev,
	/* Make sure that the VLAN is not already configured
	 * on the switch port
	 */
	if (port_priv->vlans[vlan->vid] & ETHSW_VLAN_MEMBER)
	if (port_priv->vlans[vlan->vid] & ETHSW_VLAN_MEMBER) {
		netdev_err(netdev, "VLAN %d already configured\n", vlan->vid);
		return -EEXIST;
	}

	/* Check if there is space for a new VLAN */
	err = dpsw_get_attributes(ethsw->mc_io, 0, ethsw->dpsw_handle,
@@ -2003,25 +2004,11 @@ static int dpaa2_switch_port_bridge_join(struct net_device *netdev,
					 struct netlink_ext_ack *extack)
{
	struct ethsw_port_priv *port_priv = netdev_priv(netdev);
	struct dpaa2_switch_fdb *old_fdb = port_priv->fdb;
	struct ethsw_core *ethsw = port_priv->ethsw_data;
	struct ethsw_port_priv *other_port_priv;
	struct net_device *other_dev;
	struct list_head *iter;
	bool learn_ena;
	int err;

	netdev_for_each_lower_dev(upper_dev, other_dev, iter) {
		if (!dpaa2_switch_port_dev_check(other_dev))
			continue;

		other_port_priv = netdev_priv(other_dev);
		if (other_port_priv->ethsw_data != port_priv->ethsw_data) {
			NL_SET_ERR_MSG_MOD(extack,
					   "Interface from a different DPSW is in the bridge already");
			return -EINVAL;
		}
	}

	/* Delete the previously manually installed VLAN 1 */
	err = dpaa2_switch_port_del_vlan(port_priv, 1);
	if (err)
@@ -2039,6 +2026,11 @@ static int dpaa2_switch_port_bridge_join(struct net_device *netdev,
	if (err)
		goto err_egress_flood;

	/* Recreate the egress flood domain of the FDB that we just left. */
	err = dpaa2_switch_fdb_set_egress_flood(ethsw, old_fdb->fdb_id);
	if (err)
		goto err_egress_flood;

	err = switchdev_bridge_port_offload(netdev, netdev, NULL,
					    NULL, NULL, false, extack);
	if (err)
@@ -2155,6 +2147,10 @@ dpaa2_switch_prechangeupper_sanity_checks(struct net_device *netdev,
					  struct net_device *upper_dev,
					  struct netlink_ext_ack *extack)
{
	struct ethsw_port_priv *port_priv = netdev_priv(netdev);
	struct ethsw_port_priv *other_port_priv;
	struct net_device *other_dev;
	struct list_head *iter;
	int err;

	if (!br_vlan_enabled(upper_dev)) {
@@ -2169,54 +2165,93 @@ dpaa2_switch_prechangeupper_sanity_checks(struct net_device *netdev,
		return 0;
	}

	netdev_for_each_lower_dev(upper_dev, other_dev, iter) {
		if (!dpaa2_switch_port_dev_check(other_dev))
			continue;

		other_port_priv = netdev_priv(other_dev);
		if (other_port_priv->ethsw_data != port_priv->ethsw_data) {
			NL_SET_ERR_MSG_MOD(extack,
					   "Interface from a different DPSW is in the bridge already");
			return -EINVAL;
		}
	}

	return 0;
}

static int dpaa2_switch_port_netdevice_event(struct notifier_block *nb,
					     unsigned long event, void *ptr)
static int dpaa2_switch_port_prechangeupper(struct net_device *netdev,
					    struct netdev_notifier_changeupper_info *info)
{
	struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
	struct netdev_notifier_changeupper_info *info = ptr;
	struct netlink_ext_ack *extack;
	struct net_device *upper_dev;
	int err = 0;
	int err;

	if (!dpaa2_switch_port_dev_check(netdev))
		return NOTIFY_DONE;
		return 0;

	extack = netdev_notifier_info_to_extack(&info->info);

	switch (event) {
	case NETDEV_PRECHANGEUPPER:
	upper_dev = info->upper_dev;
		if (!netif_is_bridge_master(upper_dev))
			break;

	if (netif_is_bridge_master(upper_dev)) {
		err = dpaa2_switch_prechangeupper_sanity_checks(netdev,
								upper_dev,
								extack);
		if (err)
			goto out;
			return err;

		if (!info->linking)
			dpaa2_switch_port_pre_bridge_leave(netdev);
	}

	return 0;
}

static int dpaa2_switch_port_changeupper(struct net_device *netdev,
					 struct netdev_notifier_changeupper_info *info)
{
	struct netlink_ext_ack *extack;
	struct net_device *upper_dev;

	if (!dpaa2_switch_port_dev_check(netdev))
		return 0;

	extack = netdev_notifier_info_to_extack(&info->info);

		break;
	case NETDEV_CHANGEUPPER:
	upper_dev = info->upper_dev;
	if (netif_is_bridge_master(upper_dev)) {
		if (info->linking)
				err = dpaa2_switch_port_bridge_join(netdev,
			return dpaa2_switch_port_bridge_join(netdev,
							     upper_dev,
							     extack);
		else
				err = dpaa2_switch_port_bridge_leave(netdev);
			return dpaa2_switch_port_bridge_leave(netdev);
	}
		break;

	return 0;
}

out:
static int dpaa2_switch_port_netdevice_event(struct notifier_block *nb,
					     unsigned long event, void *ptr)
{
	struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
	int err = 0;

	switch (event) {
	case NETDEV_PRECHANGEUPPER:
		err = dpaa2_switch_port_prechangeupper(netdev, ptr);
		if (err)
			return notifier_from_errno(err);

		break;
	case NETDEV_CHANGEUPPER:
		err = dpaa2_switch_port_changeupper(netdev, ptr);
		if (err)
			return notifier_from_errno(err);

		break;
	}

	return NOTIFY_DONE;
}

struct ethsw_switchdev_event_work {
@@ -3294,6 +3329,7 @@ static int dpaa2_switch_probe_port(struct ethsw_core *ethsw,
	port_netdev->features = NETIF_F_HW_VLAN_CTAG_FILTER |
				NETIF_F_HW_VLAN_STAG_FILTER |
				NETIF_F_HW_TC;
	port_netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;

	err = dpaa2_switch_port_init(port_priv, port_idx);
	if (err)