32
32
#include <generated/utsrelease.h>
33
33
#include "common.h"
34
34
35
+ /* State held across locks and calls for commands which have devlink fallback */
36
+ struct ethtool_devlink_compat {
37
+ struct devlink * devlink ;
38
+ union {
39
+ struct ethtool_flash efl ;
40
+ struct ethtool_drvinfo info ;
41
+ };
42
+ };
43
+
44
+ static struct devlink * netdev_to_devlink_get (struct net_device * dev )
45
+ {
46
+ struct devlink_port * devlink_port ;
47
+
48
+ if (!dev -> netdev_ops -> ndo_get_devlink_port )
49
+ return NULL ;
50
+
51
+ devlink_port = dev -> netdev_ops -> ndo_get_devlink_port (dev );
52
+ if (!devlink_port )
53
+ return NULL ;
54
+
55
+ return devlink_try_get (devlink_port -> devlink );
56
+ }
57
+
35
58
/*
36
59
* Some useful ethtool_ops methods that're device independent.
37
60
* If we find that all drivers want to do the same thing here,
@@ -697,22 +720,20 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
697
720
return ret ;
698
721
}
699
722
700
- static noinline_for_stack int ethtool_get_drvinfo ( struct net_device * dev ,
701
- void __user * useraddr )
723
+ static int
724
+ ethtool_get_drvinfo ( struct net_device * dev , struct ethtool_devlink_compat * rsp )
702
725
{
703
- struct ethtool_drvinfo info ;
704
726
const struct ethtool_ops * ops = dev -> ethtool_ops ;
705
727
706
- memset (& info , 0 , sizeof (info ));
707
- info .cmd = ETHTOOL_GDRVINFO ;
708
- strlcpy (info .version , UTS_RELEASE , sizeof (info .version ));
728
+ rsp -> info .cmd = ETHTOOL_GDRVINFO ;
729
+ strlcpy (rsp -> info .version , UTS_RELEASE , sizeof (rsp -> info .version ));
709
730
if (ops -> get_drvinfo ) {
710
- ops -> get_drvinfo (dev , & info );
731
+ ops -> get_drvinfo (dev , & rsp -> info );
711
732
} else if (dev -> dev .parent && dev -> dev .parent -> driver ) {
712
- strlcpy (info .bus_info , dev_name (dev -> dev .parent ),
713
- sizeof (info .bus_info ));
714
- strlcpy (info .driver , dev -> dev .parent -> driver -> name ,
715
- sizeof (info .driver ));
733
+ strlcpy (rsp -> info .bus_info , dev_name (dev -> dev .parent ),
734
+ sizeof (rsp -> info .bus_info ));
735
+ strlcpy (rsp -> info .driver , dev -> dev .parent -> driver -> name ,
736
+ sizeof (rsp -> info .driver ));
716
737
} else {
717
738
return - EOPNOTSUPP ;
718
739
}
@@ -726,30 +747,27 @@ static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev,
726
747
727
748
rc = ops -> get_sset_count (dev , ETH_SS_TEST );
728
749
if (rc >= 0 )
729
- info .testinfo_len = rc ;
750
+ rsp -> info .testinfo_len = rc ;
730
751
rc = ops -> get_sset_count (dev , ETH_SS_STATS );
731
752
if (rc >= 0 )
732
- info .n_stats = rc ;
753
+ rsp -> info .n_stats = rc ;
733
754
rc = ops -> get_sset_count (dev , ETH_SS_PRIV_FLAGS );
734
755
if (rc >= 0 )
735
- info .n_priv_flags = rc ;
756
+ rsp -> info .n_priv_flags = rc ;
736
757
}
737
758
if (ops -> get_regs_len ) {
738
759
int ret = ops -> get_regs_len (dev );
739
760
740
761
if (ret > 0 )
741
- info .regdump_len = ret ;
762
+ rsp -> info .regdump_len = ret ;
742
763
}
743
764
744
765
if (ops -> get_eeprom_len )
745
- info .eedump_len = ops -> get_eeprom_len (dev );
766
+ rsp -> info .eedump_len = ops -> get_eeprom_len (dev );
746
767
747
- if (!info .fw_version [0 ])
748
- devlink_compat_running_version (dev , info .fw_version ,
749
- sizeof (info .fw_version ));
768
+ if (!rsp -> info .fw_version [0 ])
769
+ rsp -> devlink = netdev_to_devlink_get (dev );
750
770
751
- if (copy_to_user (useraddr , & info , sizeof (info )))
752
- return - EFAULT ;
753
771
return 0 ;
754
772
}
755
773
@@ -2178,19 +2196,15 @@ static int ethtool_set_value(struct net_device *dev, char __user *useraddr,
2178
2196
return actor (dev , edata .data );
2179
2197
}
2180
2198
2181
- static noinline_for_stack int ethtool_flash_device ( struct net_device * dev ,
2182
- char __user * useraddr )
2199
+ static int
2200
+ ethtool_flash_device ( struct net_device * dev , struct ethtool_devlink_compat * req )
2183
2201
{
2184
- struct ethtool_flash efl ;
2185
-
2186
- if (copy_from_user (& efl , useraddr , sizeof (efl )))
2187
- return - EFAULT ;
2188
- efl .data [ETHTOOL_FLASH_MAX_FILENAME - 1 ] = 0 ;
2189
-
2190
- if (!dev -> ethtool_ops -> flash_device )
2191
- return devlink_compat_flash_update (dev , efl .data );
2202
+ if (!dev -> ethtool_ops -> flash_device ) {
2203
+ req -> devlink = netdev_to_devlink_get (dev );
2204
+ return 0 ;
2205
+ }
2192
2206
2193
- return dev -> ethtool_ops -> flash_device (dev , & efl );
2207
+ return dev -> ethtool_ops -> flash_device (dev , & req -> efl );
2194
2208
}
2195
2209
2196
2210
static int ethtool_set_dump (struct net_device * dev ,
@@ -2700,19 +2714,19 @@ static int ethtool_set_fecparam(struct net_device *dev, void __user *useraddr)
2700
2714
2701
2715
/* The main entry point in this file. Called from net/core/dev_ioctl.c */
2702
2716
2703
- int dev_ethtool (struct net * net , struct ifreq * ifr , void __user * useraddr )
2717
+ static int
2718
+ __dev_ethtool (struct net * net , struct ifreq * ifr , void __user * useraddr ,
2719
+ u32 ethcmd , struct ethtool_devlink_compat * devlink_state )
2704
2720
{
2705
- struct net_device * dev = __dev_get_by_name ( net , ifr -> ifr_name ) ;
2706
- u32 ethcmd , sub_cmd ;
2721
+ struct net_device * dev ;
2722
+ u32 sub_cmd ;
2707
2723
int rc ;
2708
2724
netdev_features_t old_features ;
2709
2725
2726
+ dev = __dev_get_by_name (net , ifr -> ifr_name );
2710
2727
if (!dev )
2711
2728
return - ENODEV ;
2712
2729
2713
- if (copy_from_user (& ethcmd , useraddr , sizeof (ethcmd )))
2714
- return - EFAULT ;
2715
-
2716
2730
if (ethcmd == ETHTOOL_PERQUEUE ) {
2717
2731
if (copy_from_user (& sub_cmd , useraddr + sizeof (ethcmd ), sizeof (sub_cmd )))
2718
2732
return - EFAULT ;
@@ -2786,7 +2800,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr)
2786
2800
rc = ethtool_set_settings (dev , useraddr );
2787
2801
break ;
2788
2802
case ETHTOOL_GDRVINFO :
2789
- rc = ethtool_get_drvinfo (dev , useraddr );
2803
+ rc = ethtool_get_drvinfo (dev , devlink_state );
2790
2804
break ;
2791
2805
case ETHTOOL_GREGS :
2792
2806
rc = ethtool_get_regs (dev , useraddr );
@@ -2888,7 +2902,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr)
2888
2902
rc = ethtool_set_rxnfc (dev , ethcmd , useraddr );
2889
2903
break ;
2890
2904
case ETHTOOL_FLASHDEV :
2891
- rc = ethtool_flash_device (dev , useraddr );
2905
+ rc = ethtool_flash_device (dev , devlink_state );
2892
2906
break ;
2893
2907
case ETHTOOL_RESET :
2894
2908
rc = ethtool_reset (dev , useraddr );
@@ -3000,6 +3014,60 @@ int dev_ethtool(struct net *net, struct ifreq *ifr, void __user *useraddr)
3000
3014
return rc ;
3001
3015
}
3002
3016
3017
+ int dev_ethtool (struct net * net , struct ifreq * ifr , void __user * useraddr )
3018
+ {
3019
+ struct ethtool_devlink_compat * state ;
3020
+ u32 ethcmd ;
3021
+ int rc ;
3022
+
3023
+ if (copy_from_user (& ethcmd , useraddr , sizeof (ethcmd )))
3024
+ return - EFAULT ;
3025
+
3026
+ state = kzalloc (sizeof (* state ), GFP_KERNEL );
3027
+ if (!state )
3028
+ return - ENOMEM ;
3029
+
3030
+ switch (ethcmd ) {
3031
+ case ETHTOOL_FLASHDEV :
3032
+ if (copy_from_user (& state -> efl , useraddr , sizeof (state -> efl ))) {
3033
+ rc = - EFAULT ;
3034
+ goto exit_free ;
3035
+ }
3036
+ state -> efl .data [ETHTOOL_FLASH_MAX_FILENAME - 1 ] = 0 ;
3037
+ break ;
3038
+ }
3039
+
3040
+ rtnl_lock ();
3041
+ rc = __dev_ethtool (net , ifr , useraddr , ethcmd , state );
3042
+ rtnl_unlock ();
3043
+ if (rc )
3044
+ goto exit_free ;
3045
+
3046
+ switch (ethcmd ) {
3047
+ case ETHTOOL_FLASHDEV :
3048
+ if (state -> devlink )
3049
+ rc = devlink_compat_flash_update (state -> devlink ,
3050
+ state -> efl .data );
3051
+ break ;
3052
+ case ETHTOOL_GDRVINFO :
3053
+ if (state -> devlink )
3054
+ devlink_compat_running_version (state -> devlink ,
3055
+ state -> info .fw_version ,
3056
+ sizeof (state -> info .fw_version ));
3057
+ if (copy_to_user (useraddr , & state -> info , sizeof (state -> info ))) {
3058
+ rc = - EFAULT ;
3059
+ goto exit_free ;
3060
+ }
3061
+ break ;
3062
+ }
3063
+
3064
+ exit_free :
3065
+ if (state -> devlink )
3066
+ devlink_put (state -> devlink );
3067
+ kfree (state );
3068
+ return rc ;
3069
+ }
3070
+
3003
3071
struct ethtool_rx_flow_key {
3004
3072
struct flow_dissector_key_basic basic ;
3005
3073
union {
0 commit comments