kernel/net/ethtool/rhel.h

149 lines
4.8 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* net/core/rhel.h - RHEL specific helpers for preserving KABI
*
* Copyright (c) 2020 Ivan Vecera <ivecera@redhat.com>
*
* This file contains stuff used for backward compatibility with
* older binary drivers.
*/
#ifndef _NET_ETHTOOL_RHEL_H
#define _NET_ETHTOOL_RHEL_H
#include <linux/types.h>
#include <linux/bitmap.h>
#include <linux/errno.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
/* RHEL: RHEL-8.0 knows only 51 link modes so its bitmaps used
* in ethtool_link_ksettings are array of longs with just 1 item.
* The RHEL code uses more link modes so the size of fields
* supported, advertising and lp_advertising are larger so
* the current struct ethtool_link_ksettings cannot be used
* for drivers compiled against RHEL-8.0.
* We need to declare a compatibility structure that will
* be used for these old drivers.
*/
#define __ETHTOOL_DECLARE_LINK_MODE_MASK_RH80(name) \
DECLARE_BITMAP(name, __ETHTOOL_LINK_MODE_LAST_RH80 + 1)
struct ethtool_link_ksettings_rh80 {
struct ethtool_link_settings base;
struct {
__ETHTOOL_DECLARE_LINK_MODE_MASK_RH80(supported);
__ETHTOOL_DECLARE_LINK_MODE_MASK_RH80(advertising);
__ETHTOOL_DECLARE_LINK_MODE_MASK_RH80(lp_advertising);
} link_modes;
};
/* RHEL: Helper function to check whether a driver implements
* ethtool_ops->get_link_ksettings() callback or its older
* variant used in RHEL-8.0.
*/
static inline
bool __rh_has_get_link_ksettings(struct net_device *dev)
{
return (dev->ethtool_ops->get_link_ksettings ||
dev->ethtool_ops->get_link_ksettings_rh80);
}
/* RHEL: Helper function to check whether a driver implements
* ethtool_ops->set_link_ksettings() callback or its older
* variant used in RHEL-8.0.
*/
static inline
bool __rh_has_set_link_ksettings(struct net_device *dev)
{
return (dev->ethtool_ops->set_link_ksettings ||
dev->ethtool_ops->set_link_ksettings_rh80);
}
/* RHEL: Helper function to call ethtool_ops->get_link_ksettings()
* callback or its older variant used RHEL-8.0 depending on what
* the driver implements.
*
* Newer callback is called directly and link_ksettings parameter
* is passed through.
* For older callback a temporary storage is used and its content
* is then translated for caller.
*/
static inline
int __rh_call_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *link_ksettings)
{
int err = -ENOTSUPP;
if (dev->ethtool_ops->get_link_ksettings) {
err = dev->ethtool_ops->get_link_ksettings(dev, link_ksettings);
} else if (dev->ethtool_ops->get_link_ksettings_rh80) {
struct ethtool_link_ksettings_rh80 tmp;
memset(&tmp, 0, sizeof(tmp));
err = dev->ethtool_ops->get_link_ksettings_rh80(dev, &tmp);
if (!err) {
link_ksettings->base = tmp.base;
bitmap_zero(link_ksettings->link_modes.supported,
__ETHTOOL_LINK_MODE_MASK_NBITS - 1);
bitmap_copy(link_ksettings->link_modes.supported,
tmp.link_modes.supported,
__ETHTOOL_LINK_MODE_LAST_RH80);
bitmap_zero(link_ksettings->link_modes.advertising,
__ETHTOOL_LINK_MODE_MASK_NBITS - 1);
bitmap_copy(link_ksettings->link_modes.advertising,
tmp.link_modes.advertising,
__ETHTOOL_LINK_MODE_LAST_RH80);
bitmap_zero(link_ksettings->link_modes.lp_advertising,
__ETHTOOL_LINK_MODE_MASK_NBITS - 1);
bitmap_copy(link_ksettings->link_modes.lp_advertising,
tmp.link_modes.lp_advertising,
__ETHTOOL_LINK_MODE_LAST_RH80);
}
}
return err;
}
/* RHEL: Helper function to call ethtool_ops->set_link_ksettings()
* callback or its older variant used RHEL-8.0 depending on what
* the driver implements.
*
* Newer callback is called directly and link_ksettings parameter
* is passed through.
* For older callback a temporary storage is used and its content
* is filled from input buffer (link modes bitmaps truncated).
*/
static inline
int __rh_call_set_link_ksettings(struct net_device *dev,
const struct ethtool_link_ksettings *link_ksettings)
{
int err = -ENOTSUPP;
if (dev->ethtool_ops->set_link_ksettings) {
err = dev->ethtool_ops->set_link_ksettings(dev, link_ksettings);
} else if (dev->ethtool_ops->set_link_ksettings_rh80) {
struct ethtool_link_ksettings_rh80 tmp;
/* Copy only link modes that are known for RHEL-8.0 based
* drivers.
*/
tmp.base = link_ksettings->base;
bitmap_copy(tmp.link_modes.supported,
link_ksettings->link_modes.supported,
__ETHTOOL_LINK_MODE_LAST_RH80);
bitmap_copy(tmp.link_modes.advertising,
link_ksettings->link_modes.advertising,
__ETHTOOL_LINK_MODE_LAST_RH80);
bitmap_copy(tmp.link_modes.lp_advertising,
link_ksettings->link_modes.lp_advertising,
__ETHTOOL_LINK_MODE_LAST_RH80);
err = dev->ethtool_ops->set_link_ksettings_rh80(dev, &tmp);
}
return err;
}
#endif /* _NET_ETHTOOL_RHEL_H */