@@ -134,6 +134,101 @@ int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
134
134
return 0 ;
135
135
}
136
136
137
+ /**
138
+ * mii_ethtool_get_link_ksettings - get settings that are specified in @cmd
139
+ * @mii: MII interface
140
+ * @cmd: requested ethtool_link_ksettings
141
+ *
142
+ * The @cmd parameter is expected to have been cleared before calling
143
+ * mii_ethtool_get_link_ksettings().
144
+ *
145
+ * Returns 0 for success, negative on error.
146
+ */
147
+ int mii_ethtool_get_link_ksettings (struct mii_if_info * mii ,
148
+ struct ethtool_link_ksettings * cmd )
149
+ {
150
+ struct net_device * dev = mii -> dev ;
151
+ u16 bmcr , bmsr , ctrl1000 = 0 , stat1000 = 0 ;
152
+ u32 nego , supported , advertising , lp_advertising ;
153
+
154
+ supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
155
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
156
+ SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII );
157
+ if (mii -> supports_gmii )
158
+ supported |= SUPPORTED_1000baseT_Half |
159
+ SUPPORTED_1000baseT_Full ;
160
+
161
+ /* only supports twisted-pair */
162
+ cmd -> base .port = PORT_MII ;
163
+
164
+ /* this isn't fully supported at higher layers */
165
+ cmd -> base .phy_address = mii -> phy_id ;
166
+ cmd -> base .mdio_support = ETH_MDIO_SUPPORTS_C22 ;
167
+
168
+ advertising = ADVERTISED_TP | ADVERTISED_MII ;
169
+
170
+ bmcr = mii -> mdio_read (dev , mii -> phy_id , MII_BMCR );
171
+ bmsr = mii -> mdio_read (dev , mii -> phy_id , MII_BMSR );
172
+ if (mii -> supports_gmii ) {
173
+ ctrl1000 = mii -> mdio_read (dev , mii -> phy_id , MII_CTRL1000 );
174
+ stat1000 = mii -> mdio_read (dev , mii -> phy_id , MII_STAT1000 );
175
+ }
176
+ if (bmcr & BMCR_ANENABLE ) {
177
+ advertising |= ADVERTISED_Autoneg ;
178
+ cmd -> base .autoneg = AUTONEG_ENABLE ;
179
+
180
+ advertising |= mii_get_an (mii , MII_ADVERTISE );
181
+ if (mii -> supports_gmii )
182
+ advertising |= mii_ctrl1000_to_ethtool_adv_t (ctrl1000 );
183
+
184
+ if (bmsr & BMSR_ANEGCOMPLETE ) {
185
+ lp_advertising = mii_get_an (mii , MII_LPA );
186
+ lp_advertising |=
187
+ mii_stat1000_to_ethtool_lpa_t (stat1000 );
188
+ } else {
189
+ lp_advertising = 0 ;
190
+ }
191
+
192
+ nego = advertising & lp_advertising ;
193
+
194
+ if (nego & (ADVERTISED_1000baseT_Full |
195
+ ADVERTISED_1000baseT_Half )) {
196
+ cmd -> base .speed = SPEED_1000 ;
197
+ cmd -> base .duplex = !!(nego & ADVERTISED_1000baseT_Full );
198
+ } else if (nego & (ADVERTISED_100baseT_Full |
199
+ ADVERTISED_100baseT_Half )) {
200
+ cmd -> base .speed = SPEED_100 ;
201
+ cmd -> base .duplex = !!(nego & ADVERTISED_100baseT_Full );
202
+ } else {
203
+ cmd -> base .speed = SPEED_10 ;
204
+ cmd -> base .duplex = !!(nego & ADVERTISED_10baseT_Full );
205
+ }
206
+ } else {
207
+ cmd -> base .autoneg = AUTONEG_DISABLE ;
208
+
209
+ cmd -> base .speed = ((bmcr & BMCR_SPEED1000 &&
210
+ (bmcr & BMCR_SPEED100 ) == 0 ) ?
211
+ SPEED_1000 :
212
+ ((bmcr & BMCR_SPEED100 ) ?
213
+ SPEED_100 : SPEED_10 ));
214
+ cmd -> base .duplex = (bmcr & BMCR_FULLDPLX ) ?
215
+ DUPLEX_FULL : DUPLEX_HALF ;
216
+ }
217
+
218
+ mii -> full_duplex = cmd -> base .duplex ;
219
+
220
+ ethtool_convert_legacy_u32_to_link_mode (cmd -> link_modes .supported ,
221
+ supported );
222
+ ethtool_convert_legacy_u32_to_link_mode (cmd -> link_modes .advertising ,
223
+ advertising );
224
+ ethtool_convert_legacy_u32_to_link_mode (cmd -> link_modes .lp_advertising ,
225
+ lp_advertising );
226
+
227
+ /* ignore maxtxpkt, maxrxpkt for now */
228
+
229
+ return 0 ;
230
+ }
231
+
137
232
/**
138
233
* mii_ethtool_sset - set settings that are specified in @ecmd
139
234
* @mii: MII interface
@@ -226,6 +321,104 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
226
321
return 0 ;
227
322
}
228
323
324
+ /**
325
+ * mii_ethtool_set_link_ksettings - set settings that are specified in @cmd
326
+ * @mii: MII interfaces
327
+ * @cmd: requested ethtool_link_ksettings
328
+ *
329
+ * Returns 0 for success, negative on error.
330
+ */
331
+ int mii_ethtool_set_link_ksettings (struct mii_if_info * mii ,
332
+ const struct ethtool_link_ksettings * cmd )
333
+ {
334
+ struct net_device * dev = mii -> dev ;
335
+ u32 speed = cmd -> base .speed ;
336
+
337
+ if (speed != SPEED_10 &&
338
+ speed != SPEED_100 &&
339
+ speed != SPEED_1000 )
340
+ return - EINVAL ;
341
+ if (cmd -> base .duplex != DUPLEX_HALF && cmd -> base .duplex != DUPLEX_FULL )
342
+ return - EINVAL ;
343
+ if (cmd -> base .port != PORT_MII )
344
+ return - EINVAL ;
345
+ if (cmd -> base .phy_address != mii -> phy_id )
346
+ return - EINVAL ;
347
+ if (cmd -> base .autoneg != AUTONEG_DISABLE &&
348
+ cmd -> base .autoneg != AUTONEG_ENABLE )
349
+ return - EINVAL ;
350
+ if ((speed == SPEED_1000 ) && (!mii -> supports_gmii ))
351
+ return - EINVAL ;
352
+
353
+ /* ignore supported, maxtxpkt, maxrxpkt */
354
+
355
+ if (cmd -> base .autoneg == AUTONEG_ENABLE ) {
356
+ u32 bmcr , advert , tmp ;
357
+ u32 advert2 = 0 , tmp2 = 0 ;
358
+ u32 advertising ;
359
+
360
+ ethtool_convert_link_mode_to_legacy_u32 (
361
+ & advertising , cmd -> link_modes .advertising );
362
+
363
+ if ((advertising & (ADVERTISED_10baseT_Half |
364
+ ADVERTISED_10baseT_Full |
365
+ ADVERTISED_100baseT_Half |
366
+ ADVERTISED_100baseT_Full |
367
+ ADVERTISED_1000baseT_Half |
368
+ ADVERTISED_1000baseT_Full )) == 0 )
369
+ return - EINVAL ;
370
+
371
+ /* advertise only what has been requested */
372
+ advert = mii -> mdio_read (dev , mii -> phy_id , MII_ADVERTISE );
373
+ tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4 );
374
+ if (mii -> supports_gmii ) {
375
+ advert2 = mii -> mdio_read (dev , mii -> phy_id ,
376
+ MII_CTRL1000 );
377
+ tmp2 = advert2 &
378
+ ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL );
379
+ }
380
+ tmp |= ethtool_adv_to_mii_adv_t (advertising );
381
+
382
+ if (mii -> supports_gmii )
383
+ tmp2 |= ethtool_adv_to_mii_ctrl1000_t (advertising );
384
+ if (advert != tmp ) {
385
+ mii -> mdio_write (dev , mii -> phy_id , MII_ADVERTISE , tmp );
386
+ mii -> advertising = tmp ;
387
+ }
388
+ if ((mii -> supports_gmii ) && (advert2 != tmp2 ))
389
+ mii -> mdio_write (dev , mii -> phy_id , MII_CTRL1000 , tmp2 );
390
+
391
+ /* turn on autonegotiation, and force a renegotiate */
392
+ bmcr = mii -> mdio_read (dev , mii -> phy_id , MII_BMCR );
393
+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART );
394
+ mii -> mdio_write (dev , mii -> phy_id , MII_BMCR , bmcr );
395
+
396
+ mii -> force_media = 0 ;
397
+ } else {
398
+ u32 bmcr , tmp ;
399
+
400
+ /* turn off auto negotiation, set speed and duplexity */
401
+ bmcr = mii -> mdio_read (dev , mii -> phy_id , MII_BMCR );
402
+ tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 |
403
+ BMCR_SPEED1000 | BMCR_FULLDPLX );
404
+ if (speed == SPEED_1000 )
405
+ tmp |= BMCR_SPEED1000 ;
406
+ else if (speed == SPEED_100 )
407
+ tmp |= BMCR_SPEED100 ;
408
+ if (cmd -> base .duplex == DUPLEX_FULL ) {
409
+ tmp |= BMCR_FULLDPLX ;
410
+ mii -> full_duplex = 1 ;
411
+ } else {
412
+ mii -> full_duplex = 0 ;
413
+ }
414
+ if (bmcr != tmp )
415
+ mii -> mdio_write (dev , mii -> phy_id , MII_BMCR , tmp );
416
+
417
+ mii -> force_media = 1 ;
418
+ }
419
+ return 0 ;
420
+ }
421
+
229
422
/**
230
423
* mii_check_gmii_support - check if the MII supports Gb interfaces
231
424
* @mii: the MII interface
@@ -466,7 +659,9 @@ MODULE_LICENSE("GPL");
466
659
EXPORT_SYMBOL (mii_link_ok );
467
660
EXPORT_SYMBOL (mii_nway_restart );
468
661
EXPORT_SYMBOL (mii_ethtool_gset );
662
+ EXPORT_SYMBOL (mii_ethtool_get_link_ksettings );
469
663
EXPORT_SYMBOL (mii_ethtool_sset );
664
+ EXPORT_SYMBOL (mii_ethtool_set_link_ksettings );
470
665
EXPORT_SYMBOL (mii_check_link );
471
666
EXPORT_SYMBOL (mii_check_media );
472
667
EXPORT_SYMBOL (mii_check_gmii_support );
0 commit comments