@@ -75,6 +75,7 @@ struct phylink {
75
75
76
76
struct mutex state_mutex ;
77
77
struct phylink_link_state phy_state ;
78
+ unsigned int phy_ib_mode ;
78
79
struct work_struct resolve ;
79
80
unsigned int pcs_neg_mode ;
80
81
unsigned int pcs_state ;
@@ -1153,10 +1154,18 @@ static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs,
1153
1154
phy_interface_t interface ,
1154
1155
const unsigned long * advertising )
1155
1156
{
1157
+ unsigned int pcs_ib_caps = 0 ;
1158
+ unsigned int phy_ib_caps = 0 ;
1156
1159
unsigned int neg_mode , mode ;
1160
+ enum {
1161
+ INBAND_CISCO_SGMII ,
1162
+ INBAND_BASEX ,
1163
+ } type ;
1157
1164
1158
1165
mode = pl -> req_link_an_mode ;
1159
1166
1167
+ pl -> phy_ib_mode = 0 ;
1168
+
1160
1169
switch (interface ) {
1161
1170
case PHY_INTERFACE_MODE_SGMII :
1162
1171
case PHY_INTERFACE_MODE_QSGMII :
@@ -1168,10 +1177,7 @@ static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs,
1168
1177
* inband communication. Note: there exist PHYs that run
1169
1178
* with SGMII but do not send the inband data.
1170
1179
*/
1171
- if (!phylink_autoneg_inband (mode ))
1172
- neg_mode = PHYLINK_PCS_NEG_OUTBAND ;
1173
- else
1174
- neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED ;
1180
+ type = INBAND_CISCO_SGMII ;
1175
1181
break ;
1176
1182
1177
1183
case PHY_INTERFACE_MODE_1000BASEX :
@@ -1182,18 +1188,139 @@ static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs,
1182
1188
* as well, but drivers may not support this, so may
1183
1189
* need to override this.
1184
1190
*/
1185
- if (!phylink_autoneg_inband (mode ))
1191
+ type = INBAND_BASEX ;
1192
+ break ;
1193
+
1194
+ default :
1195
+ pl -> pcs_neg_mode = PHYLINK_PCS_NEG_NONE ;
1196
+ pl -> act_link_an_mode = mode ;
1197
+ return ;
1198
+ }
1199
+
1200
+ if (pcs )
1201
+ pcs_ib_caps = phylink_pcs_inband_caps (pcs , interface );
1202
+
1203
+ if (pl -> phydev )
1204
+ phy_ib_caps = phy_inband_caps (pl -> phydev , interface );
1205
+
1206
+ phylink_dbg (pl , "interface %s inband modes: pcs=%02x phy=%02x\n" ,
1207
+ phy_modes (interface ), pcs_ib_caps , phy_ib_caps );
1208
+
1209
+ if (!phylink_autoneg_inband (mode )) {
1210
+ bool pcs_ib_only = false;
1211
+ bool phy_ib_only = false;
1212
+
1213
+ if (pcs_ib_caps && pcs_ib_caps != LINK_INBAND_DISABLE ) {
1214
+ /* PCS supports reporting in-band capabilities, and
1215
+ * supports more than disable mode.
1216
+ */
1217
+ if (pcs_ib_caps & LINK_INBAND_DISABLE )
1218
+ neg_mode = PHYLINK_PCS_NEG_OUTBAND ;
1219
+ else if (pcs_ib_caps & LINK_INBAND_ENABLE )
1220
+ pcs_ib_only = true;
1221
+ }
1222
+
1223
+ if (phy_ib_caps && phy_ib_caps != LINK_INBAND_DISABLE ) {
1224
+ /* PHY supports in-band capabilities, and supports
1225
+ * more than disable mode.
1226
+ */
1227
+ if (phy_ib_caps & LINK_INBAND_DISABLE )
1228
+ pl -> phy_ib_mode = LINK_INBAND_DISABLE ;
1229
+ else if (phy_ib_caps & LINK_INBAND_BYPASS )
1230
+ pl -> phy_ib_mode = LINK_INBAND_BYPASS ;
1231
+ else if (phy_ib_caps & LINK_INBAND_ENABLE )
1232
+ phy_ib_only = true;
1233
+ }
1234
+
1235
+ /* If either the PCS or PHY requires inband to be enabled,
1236
+ * this is an invalid configuration. Provide a diagnostic
1237
+ * message for this case, but don't try to force the issue.
1238
+ */
1239
+ if (pcs_ib_only || phy_ib_only )
1240
+ phylink_warn (pl ,
1241
+ "firmware wants %s mode, but %s%s%s requires inband\n" ,
1242
+ phylink_an_mode_str (mode ),
1243
+ pcs_ib_only ? "PCS" : "" ,
1244
+ pcs_ib_only && phy_ib_only ? " and " : "" ,
1245
+ phy_ib_only ? "PHY" : "" );
1246
+
1247
+ neg_mode = PHYLINK_PCS_NEG_OUTBAND ;
1248
+ } else if (type == INBAND_CISCO_SGMII || pl -> phydev ) {
1249
+ /* For SGMII modes which are designed to be used with PHYs, or
1250
+ * Base-X with a PHY, we try to use in-band mode where-ever
1251
+ * possible. However, there are some PHYs e.g. BCM84881 which
1252
+ * do not support in-band.
1253
+ */
1254
+ const unsigned int inband_ok = LINK_INBAND_ENABLE |
1255
+ LINK_INBAND_BYPASS ;
1256
+ const unsigned int outband_ok = LINK_INBAND_DISABLE |
1257
+ LINK_INBAND_BYPASS ;
1258
+ /* PCS PHY
1259
+ * D E D E
1260
+ * 0 0 0 0 no information inband enabled
1261
+ * 1 0 0 0 pcs doesn't support outband
1262
+ * 0 1 0 0 pcs required inband enabled
1263
+ * 1 1 0 0 pcs optional inband enabled
1264
+ * 0 0 1 0 phy doesn't support outband
1265
+ * 1 0 1 0 pcs+phy doesn't support outband
1266
+ * 0 1 1 0 pcs required, phy doesn't support, invalid
1267
+ * 1 1 1 0 pcs optional, phy doesn't support, outband
1268
+ * 0 0 0 1 phy required inband enabled
1269
+ * 1 0 0 1 pcs doesn't support, phy required, invalid
1270
+ * 0 1 0 1 pcs+phy required inband enabled
1271
+ * 1 1 0 1 pcs optional, phy required inband enabled
1272
+ * 0 0 1 1 phy optional inband enabled
1273
+ * 1 0 1 1 pcs doesn't support, phy optional, outband
1274
+ * 0 1 1 1 pcs required, phy optional inband enabled
1275
+ * 1 1 1 1 pcs+phy optional inband enabled
1276
+ */
1277
+ if ((!pcs_ib_caps || pcs_ib_caps & inband_ok ) &&
1278
+ (!phy_ib_caps || phy_ib_caps & inband_ok )) {
1279
+ /* In-band supported or unknown at both ends. Enable
1280
+ * in-band mode with or without bypass at the PHY.
1281
+ */
1282
+ if (phy_ib_caps & LINK_INBAND_ENABLE )
1283
+ pl -> phy_ib_mode = LINK_INBAND_ENABLE ;
1284
+ else if (phy_ib_caps & LINK_INBAND_BYPASS )
1285
+ pl -> phy_ib_mode = LINK_INBAND_BYPASS ;
1286
+
1287
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED ;
1288
+ } else if ((!pcs_ib_caps || pcs_ib_caps & outband_ok ) &&
1289
+ (!phy_ib_caps || phy_ib_caps & outband_ok )) {
1290
+ /* Either in-band not supported at at least one end.
1291
+ * In-band bypass at the other end is possible.
1292
+ */
1293
+ if (phy_ib_caps & LINK_INBAND_DISABLE )
1294
+ pl -> phy_ib_mode = LINK_INBAND_DISABLE ;
1295
+ else if (phy_ib_caps & LINK_INBAND_BYPASS )
1296
+ pl -> phy_ib_mode = LINK_INBAND_BYPASS ;
1297
+
1186
1298
neg_mode = PHYLINK_PCS_NEG_OUTBAND ;
1299
+ if (pl -> phydev )
1300
+ mode = MLO_AN_PHY ;
1301
+ } else {
1302
+ /* invalid */
1303
+ phylink_warn (pl , "%s: incompatible in-band capabilities, trying in-band" ,
1304
+ phy_modes (interface ));
1305
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED ;
1306
+ }
1307
+ } else {
1308
+ /* For Base-X without a PHY */
1309
+ if (pcs_ib_caps == LINK_INBAND_DISABLE )
1310
+ /* If the PCS doesn't support inband, then inband must
1311
+ * be disabled.
1312
+ */
1313
+ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED ;
1314
+ else if (pcs_ib_caps == LINK_INBAND_ENABLE )
1315
+ /* If the PCS requires inband, then inband must always
1316
+ * be enabled.
1317
+ */
1318
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED ;
1187
1319
else if (linkmode_test_bit (ETHTOOL_LINK_MODE_Autoneg_BIT ,
1188
1320
advertising ))
1189
1321
neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED ;
1190
1322
else
1191
1323
neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED ;
1192
- break ;
1193
-
1194
- default :
1195
- neg_mode = PHYLINK_PCS_NEG_NONE ;
1196
- break ;
1197
1324
}
1198
1325
1199
1326
pl -> pcs_neg_mode = neg_mode ;
@@ -1292,6 +1419,13 @@ static void phylink_major_config(struct phylink *pl, bool restart,
1292
1419
ERR_PTR (err ));
1293
1420
}
1294
1421
1422
+ if (pl -> phydev && pl -> phy_ib_mode ) {
1423
+ err = phy_config_inband (pl -> phydev , pl -> phy_ib_mode );
1424
+ if (err < 0 )
1425
+ phylink_err (pl , "phy_config_inband: %pe\n" ,
1426
+ ERR_PTR (err ));
1427
+ }
1428
+
1295
1429
if (pl -> sfp_bus ) {
1296
1430
rate_kbd = phylink_interface_signal_rate (state -> interface );
1297
1431
if (rate_kbd )
0 commit comments