/** * coalesce_put_profile - fill reply with a nla nest with four child nla nests. * @skb: socket buffer the message is stored in * @attr_type: nest attr type ETHTOOL_A_COALESCE_*X_PROFILE * @profile: data passed to userspace * @coal_flags: modifiable parameters supported by the driver * * Put a dim profile nest attribute. Refer to ETHTOOL_A_PROFILE_IRQ_MODERATION. * * Return: 0 on success or a negative error code.
*/ staticint coalesce_put_profile(struct sk_buff *skb, u16 attr_type, conststruct dim_cq_moder *profile,
u8 coal_flags)
{ struct nlattr *profile_attr, *moder_attr; int i, ret;
if (!profile || !coal_flags) return 0;
profile_attr = nla_nest_start(skb, attr_type); if (!profile_attr) return -EMSGSIZE;
for (i = 0; i < NET_DIM_PARAMS_NUM_PROFILES; i++) {
moder_attr = nla_nest_start(skb,
ETHTOOL_A_PROFILE_IRQ_MODERATION); if (!moder_attr) {
ret = -EMSGSIZE; goto cancel_profile;
}
if (coal_flags & DIM_COALESCE_USEC) {
ret = nla_put_u32(skb, ETHTOOL_A_IRQ_MODERATION_USEC,
profile[i].usec); if (ret) goto cancel_moder;
}
if (coal_flags & DIM_COALESCE_PKTS) {
ret = nla_put_u32(skb, ETHTOOL_A_IRQ_MODERATION_PKTS,
profile[i].pkts); if (ret) goto cancel_moder;
}
if (coal_flags & DIM_COALESCE_COMPS) {
ret = nla_put_u32(skb, ETHTOOL_A_IRQ_MODERATION_COMPS,
profile[i].comps); if (ret) goto cancel_moder;
}
if (!req_base->dev || !req_base->dev->irq_moder) return 0;
moder = req_base->dev->irq_moder;
rcu_read_lock(); if (moder->profile_flags & DIM_PROFILE_RX) {
ret = coalesce_put_profile(skb, ETHTOOL_A_COALESCE_RX_PROFILE,
rcu_dereference(moder->rx_profile),
moder->coal_flags); if (ret) goto out;
}
if (moder->profile_flags & DIM_PROFILE_TX)
ret = coalesce_put_profile(skb, ETHTOOL_A_COALESCE_TX_PROFILE,
rcu_dereference(moder->tx_profile),
moder->coal_flags);
if (!ops->get_coalesce || !ops->set_coalesce) return -EOPNOTSUPP;
/* make sure that only supported parameters are present */
supported_params = ops->supported_coalesce_params; if (irq_moder && irq_moder->profile_flags & DIM_PROFILE_RX)
supported_params |= ETHTOOL_COALESCE_RX_PROFILE;
if (irq_moder && irq_moder->profile_flags & DIM_PROFILE_TX)
supported_params |= ETHTOOL_COALESCE_TX_PROFILE;
for (a = ETHTOOL_A_COALESCE_RX_USECS; a < __ETHTOOL_A_COALESCE_CNT; a++) if (tb[a] && !(supported_params & attr_to_mask(a))) {
NL_SET_ERR_MSG_ATTR(info->extack, tb[a], "cannot modify an unsupported parameter"); return -EINVAL;
}
return 1;
}
/** * ethnl_update_irq_moder - update a specific field in the given profile * @irq_moder: place that collects dim related information * @irq_field: field in profile to modify * @attr_type: attr type ETHTOOL_A_IRQ_MODERATION_* * @tb: netlink attribute with new values or null * @coal_bit: DIM_COALESCE_* bit from coal_flags * @mod: pointer to bool for modification tracking * @extack: netlink extended ack * * Return: 0 on success or a negative error code.
*/ staticint ethnl_update_irq_moder(struct dim_irq_moder *irq_moder,
u16 *irq_field, u16 attr_type, struct nlattr **tb,
u8 coal_bit, bool *mod, struct netlink_ext_ack *extack)
{ int ret = 0;
u32 val;
if (!tb[attr_type]) return 0;
if (irq_moder->coal_flags & coal_bit) {
val = nla_get_u32(tb[attr_type]); if (*irq_field == val) return 0;
/** * ethnl_update_profile - get a profile nest with child nests from userspace. * @dev: netdevice to update the profile * @dst: profile get from the driver and modified by ethnl_update_profile. * @nests: nest attr ETHTOOL_A_COALESCE_*X_PROFILE to set profile. * @mod: pointer to bool for modification tracking * @extack: Netlink extended ack * * Layout of nests: * Nested ETHTOOL_A_COALESCE_*X_PROFILE attr * Nested ETHTOOL_A_PROFILE_IRQ_MODERATION attr * ETHTOOL_A_IRQ_MODERATION_USEC attr * ETHTOOL_A_IRQ_MODERATION_PKTS attr * ETHTOOL_A_IRQ_MODERATION_COMPS attr * ... * Nested ETHTOOL_A_PROFILE_IRQ_MODERATION attr * ETHTOOL_A_IRQ_MODERATION_USEC attr * ETHTOOL_A_IRQ_MODERATION_PKTS attr * ETHTOOL_A_IRQ_MODERATION_COMPS attr * * Return: 0 on success or a negative error code.
*/ staticint ethnl_update_profile(struct net_device *dev, struct dim_cq_moder __rcu **dst, conststruct nlattr *nests, bool *mod, struct netlink_ext_ack *extack)
{ int len_irq_moder = ARRAY_SIZE(coalesce_irq_moderation_policy); struct nlattr *tb[ARRAY_SIZE(coalesce_irq_moderation_policy)]; struct dim_irq_moder *irq_moder = dev->irq_moder; struct dim_cq_moder *new_profile, *old_profile; int ret, rem, i = 0, len; struct nlattr *nest;
if (!nests) return 0;
if (!*dst) return -EOPNOTSUPP;
old_profile = rtnl_dereference(*dst);
len = NET_DIM_PARAMS_NUM_PROFILES * sizeof(*old_profile);
new_profile = kmemdup(old_profile, len, GFP_KERNEL); if (!new_profile) return -ENOMEM;
nla_for_each_nested_type(nest, ETHTOOL_A_PROFILE_IRQ_MODERATION,
nests, rem) {
ret = nla_parse_nested(tb, len_irq_moder - 1, nest,
coalesce_irq_moderation_policy,
extack); if (ret) goto err_out;
ret = ethnl_update_irq_moder(irq_moder, &new_profile[i].usec,
ETHTOOL_A_IRQ_MODERATION_USEC,
tb, DIM_COALESCE_USEC,
mod, extack); if (ret) goto err_out;
ret = ethnl_update_irq_moder(irq_moder, &new_profile[i].pkts,
ETHTOOL_A_IRQ_MODERATION_PKTS,
tb, DIM_COALESCE_PKTS,
mod, extack); if (ret) goto err_out;
ret = ethnl_update_irq_moder(irq_moder, &new_profile[i].comps,
ETHTOOL_A_IRQ_MODERATION_COMPS,
tb, DIM_COALESCE_COMPS,
mod, extack); if (ret) goto err_out;
i++;
}
/* After the profile is modified, dim itself is a dynamic * mechanism and will quickly fit to the appropriate * coalescing parameters according to the new profile.
*/
rcu_assign_pointer(*dst, new_profile);
kfree_rcu(old_profile, rcu);
/* SET_COALESCE may change operation mode and parameters in one call. * Changing operation mode may cause the driver to reset the parameter * values, and therefore ignore user input (driver does not know which * parameters come from user and which are echoed back from ->get). * To not complicate the drivers if user tries to change both the mode * and parameters at once - call the driver twice.
*/
err = __ethnl_set_coalesce(req_info, info, &dual_change); if (err < 0) return err;
ret = err;
if (ret && dual_change) {
err = __ethnl_set_coalesce(req_info, info, &dual_change); if (err < 0) return err;
} return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.