Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f9ae7e4b authored by John Fastabend's avatar John Fastabend Committed by David S. Miller
Browse files

dcb: Add ieee_dcb_delapp() and dcb op to delete app entry



Now that we allow multiple IEEE App entries we need a way
to remove specific entries. To do this add the ieee_dcb_delapp()
routine.

Additionaly drivers may need to remove the APP entry from
their firmware tables. Add dcb ops routine to handle this.

Signed-off-by: default avatarJohn Fastabend <john.r.fastabend@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b6db2174
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -203,6 +203,7 @@ struct dcbmsg {
 * @DCB_CMD_GFEATCFG: get DCBX features flags
 * @DCB_CMD_SFEATCFG: set DCBX features negotiation flags
 * @DCB_CMD_CEE_GET: get CEE aggregated configuration
 * @DCB_CMD_IEEE_DEL: delete IEEE 802.1Qaz configuration
 */
enum dcbnl_commands {
	DCB_CMD_UNDEFINED,
@@ -246,6 +247,7 @@ enum dcbnl_commands {
	DCB_CMD_SFEATCFG,

	DCB_CMD_CEE_GET,
	DCB_CMD_IEEE_DEL,

	__DCB_CMD_ENUM_MAX,
	DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1,
+2 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ struct dcb_app_type {
u8 dcb_setapp(struct net_device *, struct dcb_app *);
u8 dcb_getapp(struct net_device *, struct dcb_app *);
int dcb_ieee_setapp(struct net_device *, struct dcb_app *);
int dcb_ieee_delapp(struct net_device *, struct dcb_app *);

int dcbnl_notify(struct net_device *dev, int event, int cmd, u32 seq, u32 pid);

@@ -46,6 +47,7 @@ struct dcbnl_rtnl_ops {
	int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *);
	int (*ieee_getapp) (struct net_device *, struct dcb_app *);
	int (*ieee_setapp) (struct net_device *, struct dcb_app *);
	int (*ieee_delapp) (struct net_device *, struct dcb_app *);
	int (*ieee_peer_getets) (struct net_device *, struct ieee_ets *);
	int (*ieee_peer_getpfc) (struct net_device *, struct ieee_pfc *);

+88 −2
Original line number Diff line number Diff line
@@ -1451,6 +1451,52 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,

	return err;
}

static int dcbnl_ieee_del(struct net_device *netdev, struct nlattr **tb,
			  u32 pid, u32 seq, u16 flags)
{
	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
	struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1];
	int err = -EOPNOTSUPP;

	if (!ops)
		return -EOPNOTSUPP;

	if (!tb[DCB_ATTR_IEEE])
		return -EINVAL;

	err = nla_parse_nested(ieee, DCB_ATTR_IEEE_MAX,
			       tb[DCB_ATTR_IEEE], dcbnl_ieee_policy);
	if (err)
		return err;

	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
		struct nlattr *attr;
		int rem;

		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
			struct dcb_app *app_data;

			if (nla_type(attr) != DCB_ATTR_IEEE_APP)
				continue;
			app_data = nla_data(attr);
			if (ops->ieee_delapp)
				err = ops->ieee_delapp(netdev, app_data);
			else
				err = dcb_ieee_delapp(netdev, app_data);
			if (err)
				goto err;
		}
	}

err:
	dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_DEL, DCB_ATTR_IEEE,
		    pid, seq, flags);
	dcbnl_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0);
	return err;
}


/* DCBX configuration */
static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb,
			 u32 pid, u32 seq, u16 flags)
@@ -1771,6 +1817,10 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
		ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq,
				     nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_IEEE_DEL:
		ret = dcbnl_ieee_del(netdev, tb, pid, nlh->nlmsg_seq,
				     nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_GDCBX:
		ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq,
				    nlh->nlmsg_flags);
@@ -1924,6 +1974,42 @@ out:
}
EXPORT_SYMBOL(dcb_ieee_setapp);

/**
 * dcb_ieee_delapp - delete IEEE dcb application data from list
 *
 * This removes a matching APP data from the APP list
 */
int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del)
{
	struct dcb_app_type *itr;
	struct dcb_app_type event;
	int err = -ENOENT;

	memcpy(&event.name, dev->name, sizeof(event.name));
	memcpy(&event.app, del, sizeof(event.app));

	spin_lock(&dcb_lock);
	/* Search for existing match and remove it. */
	list_for_each_entry(itr, &dcb_app_list, list) {
		if (itr->app.selector == del->selector &&
		    itr->app.protocol == del->protocol &&
		    itr->app.priority == del->priority &&
		    (strncmp(itr->name, dev->name, IFNAMSIZ) == 0)) {
			list_del(&itr->list);
			kfree(itr);
			err = 0;
			goto out;
		}
	}

out:
	spin_unlock(&dcb_lock);
	if (!err)
		call_dcbevent_notifiers(DCB_APP_EVENT, &event);
	return err;
}
EXPORT_SYMBOL(dcb_ieee_delapp);

static void dcb_flushapp(void)
{
	struct dcb_app_type *app;