149 lines
4.8 KiB
C
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 */
|