[vbox-dev] Fixes for API changes in kernel 4.20

Larry Finger Larry.Finger at lwfinger.net
Wed Nov 21 01:24:13 GMT 2018


On 11/20/18 6:37 AM, Michael Thayer wrote:
> 08.11.18 21:27, Larry Finger wrote:
>> Hi,
>>
>> There are a number of changes in kernel 4.20 that affect building the VB
>> modules. These are as follows:
>>
>> 1. In struct ethtool_ops, the get_settings member is renamed
>> get_link_ksettings, and the callback method is changed. To satisfy the
>> new method, routine convert_link_ksettings_to_legacy_settings(), which
>> is not exported by the kernel, had to be duplicated.
>>
>> 2. Routine ktime_get_real_ts() must be replaced by ktime_get_real_ts64()
>> and there are other places where 64-bit names have to be used.
>>
>> 3. In the drm routines, info->flags no longer accepts
>> FBINFO_CAN_FORCE_OUTPUT. According to the kernel commit message, this
>> flag was unused and it can be deleted without any harmful effects.
>>
>> The patch file for these changes is attached.
> 
> Hello Larry,
> 
> Still waiting for input from the "owner" of the VBoxNetAdp code, but
> does this slightly adjusted version (patch against trunk) look alright
> to you?
> 
> Index: include/iprt/time.h
> ===================================================================
> --- include/iprt/time.h	(revision 126767)
> +++ include/iprt/time.h	(working copy)
> @@ -428,6 +428,14 @@
>   {
>       return RTTimeSpecAddNano(RTTimeSpecSetSeconds(pTime,
> pTimespec->tv_sec), pTimespec->tv_nsec);
>   }
> +
> +
> +# ifdef _LINUX_TIME64_H
> +DECLINLINE(PRTTIMESPEC) RTTimeSpecSetTimespec64(PRTTIMESPEC pTime,
> const struct timespec64 *pTimeval)
> +{
> +    return RTTimeSpecAddNano(RTTimeSpecSetSeconds(pTime,
> pTimeval->tv_sec), pTimeval->tv_nsec);
> +}
> +# endif
>   #endif /* various ways of detecting struct timespec */
> 
> 
> Index: src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c
> ===================================================================
> --- src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c	(revision 126767)
> +++ src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c	(working copy)
> @@ -171,11 +171,20 @@
>   {
>       IPRT_LINUX_SAVE_EFL_AC();
>   #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
> +/* On Linux 4.20, time.h includes time64.h and we have to use 64-bit
> times. */
> +# ifdef _LINUX_TIME64_H
> +    struct timespec64 Ts;
> +    ktime_get_real_ts64(&Ts);
> +# else
>       struct timespec Ts;
>       ktime_get_real_ts(&Ts);
> +# endif
>       IPRT_LINUX_RESTORE_EFL_AC();
> +# ifdef _LINUX_TIME64_H
> +    return RTTimeSpecSetTimespec64(pTime, &Ts);
> +#else
>       return RTTimeSpecSetTimespec(pTime, &Ts);
> -
> +#endif
>   #else   /* < 2.6.16 */
>       struct timeval Tv;
>       do_gettimeofday(&Tv);
> Index: src/VBox/Additions/linux/drm/vbox_fb.c
> ===================================================================
> --- src/VBox/Additions/linux/drm/vbox_fb.c	(revision 126767)
> +++ src/VBox/Additions/linux/drm/vbox_fb.c	(working copy)
> @@ -325,8 +325,7 @@
>   	 * The last flag forces a mode set on VT switches even if the kernel
>   	 * does not think it is needed.
>   	 */
> -	info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT |
> -		      FBINFO_MISC_ALWAYS_SETPAR;
> +	info->flags = FBINFO_DEFAULT | FBINFO_MISC_ALWAYS_SETPAR;
>   	info->fbops = &vboxfb_ops;
> 
>   	/*
> Index: src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c
> ===================================================================
> --- src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c	(revision
> 126767)
> +++ src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c	(working copy)
> @@ -84,9 +84,12 @@
>   #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) */
> 
>   static void vboxNetAdpEthGetDrvinfo(struct net_device *dev, struct
> ethtool_drvinfo *info);
> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
> +static int vboxNetAdpEthGetSettings(struct net_device *pNetDev, struct
> ethtool_link_ksettings *link_ksettings);
> +#else
>   static int vboxNetAdpEthGetSettings(struct net_device *dev, struct
> ethtool_cmd *cmd);
> +#endif
> 
> -
>   /*********************************************************************************************************************************
>   *   Global Variables
>                                                            *
>   *********************************************************************************************************************************/
> @@ -133,7 +136,11 @@
>   # endif
>   {
>       .get_drvinfo        = vboxNetAdpEthGetDrvinfo,
> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
> +    .get_link_ksettings = vboxNetAdpEthGetSettings,
> +#else
>       .get_settings       = vboxNetAdpEthGetSettings,
> +#endif
>       .get_link           = ethtool_op_get_link,
>   };
> 
> @@ -204,10 +211,64 @@
>                   "N/A");
>   }
> 
> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
> +static bool
> +convert_link_ksettings_to_legacy_settings(
> +	struct ethtool_cmd *legacy_settings,
> +	const struct ethtool_link_ksettings *link_ksettings)
> +{
> +	bool retval = true;
> 
> +	memset(legacy_settings, 0, sizeof(*legacy_settings));
> +	/* this also clears the deprecated fields in legacy structure:
> +	 * __u8		transceiver;
> +	 * __u32	maxtxpkt;
> +	 * __u32	maxrxpkt;
> +	 */
> +
> +	retval &= ethtool_convert_link_mode_to_legacy_u32(
> +		&legacy_settings->supported,
> +		link_ksettings->link_modes.supported);
> +	retval &= ethtool_convert_link_mode_to_legacy_u32(
> +		&legacy_settings->advertising,
> +		link_ksettings->link_modes.advertising);
> +	retval &= ethtool_convert_link_mode_to_legacy_u32(
> +		&legacy_settings->lp_advertising,
> +		link_ksettings->link_modes.lp_advertising);
> +	ethtool_cmd_speed_set(legacy_settings, link_ksettings->base.speed);
> +	legacy_settings->duplex
> +		= link_ksettings->base.duplex;
> +	legacy_settings->port
> +		= link_ksettings->base.port;
> +	legacy_settings->phy_address
> +		= link_ksettings->base.phy_address;
> +	legacy_settings->autoneg
> +		= link_ksettings->base.autoneg;
> +	legacy_settings->mdio_support
> +		= link_ksettings->base.mdio_support;
> +	legacy_settings->eth_tp_mdix
> +		= link_ksettings->base.eth_tp_mdix;
> +	legacy_settings->eth_tp_mdix_ctrl
> +		= link_ksettings->base.eth_tp_mdix_ctrl;
> +	legacy_settings->transceiver
> +		= link_ksettings->base.transceiver;
> +	return retval;
> +}
> +#endif
> +
>   /* ethtool_ops::get_settings */
> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
> +static int vboxNetAdpEthGetSettings(struct net_device *pNetDev, struct
> ethtool_link_ksettings *link_ksettings)
> +#else
>   static int vboxNetAdpEthGetSettings(struct net_device *pNetDev, struct
> ethtool_cmd *cmd)
> +#endif
>   {
> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
> +    struct ethtool_cmd *cmd = kzalloc(sizeof(struct ethtool_cmd),
> GFP_KERNEL);
> +    if (!cmd)
> +    	return 1;
> +    convert_link_ksettings_to_legacy_settings(cmd, link_ksettings);
> +#endif
>       cmd->supported      = 0;
>       cmd->advertising    = 0;
>   #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
> @@ -222,6 +283,9 @@
>       cmd->autoneg        = AUTONEG_DISABLE;
>       cmd->maxtxpkt       = 0;
>       cmd->maxrxpkt       = 0;
> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
> +    kfree(cmd);
> +#endif
>       return 0;
>   }
> 
> --
>>
>> Larry--

Michael,

I really like your approach to testing for features in a manner that will be 
less affected by distros backporting API changes. Unfortunately, code patched 
using your version fails to build under kernel 4.20.0-rcX. As I noted, the 
get_settings member of struct ethtool_ops, is renamed get_link_ksettings, and 
the callback method is changed. Your patch does not handle this change. This 
results in the error

/usr/src/kernel-modules/virtualbox/src/vboxnetadp/linux/VBoxNetAdp-linux.c:135:6: 
error: ‘const struct ethtool_ops’ has no member named ‘get_settings’; did you 
mean ‘get_strings’?
      .get_settings       = vboxNetAdpEthGetSettings,
       ^~~~~~~~~~~~
       get_strings

Of course, others follow.

Larry






More information about the vbox-dev mailing list