@@ -1051,6 +1051,14 @@ static struct ptp_clock_info ocelot_ptp_clock_info = {
1051
1051
.enable = ocelot_ptp_enable ,
1052
1052
};
1053
1053
1054
+ static void mscc_ocelot_teardown_devlink_ports (struct ocelot * ocelot )
1055
+ {
1056
+ int port ;
1057
+
1058
+ for (port = 0 ; port < ocelot -> num_phys_ports ; port ++ )
1059
+ ocelot_port_devlink_teardown (ocelot , port );
1060
+ }
1061
+
1054
1062
static void mscc_ocelot_release_ports (struct ocelot * ocelot )
1055
1063
{
1056
1064
int port ;
@@ -1078,28 +1086,44 @@ static int mscc_ocelot_init_ports(struct platform_device *pdev,
1078
1086
{
1079
1087
struct ocelot * ocelot = platform_get_drvdata (pdev );
1080
1088
struct device_node * portnp ;
1081
- int err ;
1089
+ bool * registered_ports ;
1090
+ int port , err ;
1091
+ u32 reg ;
1082
1092
1083
1093
ocelot -> ports = devm_kcalloc (ocelot -> dev , ocelot -> num_phys_ports ,
1084
1094
sizeof (struct ocelot_port * ), GFP_KERNEL );
1085
1095
if (!ocelot -> ports )
1086
1096
return - ENOMEM ;
1087
1097
1098
+ ocelot -> devlink_ports = devm_kcalloc (ocelot -> dev ,
1099
+ ocelot -> num_phys_ports ,
1100
+ sizeof (* ocelot -> devlink_ports ),
1101
+ GFP_KERNEL );
1102
+ if (!ocelot -> devlink_ports )
1103
+ return - ENOMEM ;
1104
+
1105
+ registered_ports = kcalloc (ocelot -> num_phys_ports , sizeof (bool ),
1106
+ GFP_KERNEL );
1107
+ if (!registered_ports )
1108
+ return - ENOMEM ;
1109
+
1088
1110
for_each_available_child_of_node (ports , portnp ) {
1089
1111
struct ocelot_port_private * priv ;
1090
1112
struct ocelot_port * ocelot_port ;
1091
1113
struct device_node * phy_node ;
1114
+ struct devlink_port * dlp ;
1092
1115
phy_interface_t phy_mode ;
1093
1116
struct phy_device * phy ;
1094
1117
struct regmap * target ;
1095
1118
struct resource * res ;
1096
1119
struct phy * serdes ;
1097
1120
char res_name [8 ];
1098
- u32 port ;
1099
1121
1100
- if (of_property_read_u32 (portnp , "reg" , & port ))
1122
+ if (of_property_read_u32 (portnp , "reg" , & reg ))
1101
1123
continue ;
1102
1124
1125
+ port = reg ;
1126
+
1103
1127
snprintf (res_name , sizeof (res_name ), "port%d" , port );
1104
1128
1105
1129
res = platform_get_resource_byname (pdev , IORESOURCE_MEM ,
@@ -1117,15 +1141,26 @@ static int mscc_ocelot_init_ports(struct platform_device *pdev,
1117
1141
if (!phy )
1118
1142
continue ;
1119
1143
1144
+ err = ocelot_port_devlink_init (ocelot , port ,
1145
+ DEVLINK_PORT_FLAVOUR_PHYSICAL );
1146
+ if (err ) {
1147
+ of_node_put (portnp );
1148
+ goto out_teardown ;
1149
+ }
1150
+
1120
1151
err = ocelot_probe_port (ocelot , port , target , phy );
1121
1152
if (err ) {
1122
1153
of_node_put (portnp );
1123
- return err ;
1154
+ goto out_teardown ;
1124
1155
}
1125
1156
1157
+ registered_ports [port ] = true;
1158
+
1126
1159
ocelot_port = ocelot -> ports [port ];
1127
1160
priv = container_of (ocelot_port , struct ocelot_port_private ,
1128
1161
port );
1162
+ dlp = & ocelot -> devlink_ports [port ];
1163
+ devlink_port_type_eth_set (dlp , priv -> dev );
1129
1164
1130
1165
of_get_phy_mode (portnp , & phy_mode );
1131
1166
@@ -1150,7 +1185,8 @@ static int mscc_ocelot_init_ports(struct platform_device *pdev,
1150
1185
"invalid phy mode for port%d, (Q)SGMII only\n" ,
1151
1186
port );
1152
1187
of_node_put (portnp );
1153
- return - EINVAL ;
1188
+ err = - EINVAL ;
1189
+ goto out_teardown ;
1154
1190
}
1155
1191
1156
1192
serdes = devm_of_phy_get (ocelot -> dev , portnp , NULL );
@@ -1164,20 +1200,54 @@ static int mscc_ocelot_init_ports(struct platform_device *pdev,
1164
1200
port );
1165
1201
1166
1202
of_node_put (portnp );
1167
- return err ;
1203
+ goto out_teardown ;
1168
1204
}
1169
1205
1170
1206
priv -> serdes = serdes ;
1171
1207
}
1172
1208
1209
+ /* Initialize unused devlink ports at the end */
1210
+ for (port = 0 ; port < ocelot -> num_phys_ports ; port ++ ) {
1211
+ if (registered_ports [port ])
1212
+ continue ;
1213
+
1214
+ err = ocelot_port_devlink_init (ocelot , port ,
1215
+ DEVLINK_PORT_FLAVOUR_UNUSED );
1216
+ if (err ) {
1217
+ while (port -- >= 0 ) {
1218
+ if (!registered_ports [port ])
1219
+ continue ;
1220
+ ocelot_port_devlink_teardown (ocelot , port );
1221
+ }
1222
+
1223
+ goto out_teardown ;
1224
+ }
1225
+ }
1226
+
1227
+ kfree (registered_ports );
1228
+
1173
1229
return 0 ;
1230
+
1231
+ out_teardown :
1232
+ /* Unregister the network interfaces */
1233
+ mscc_ocelot_release_ports (ocelot );
1234
+ /* Tear down devlink ports for the registered network interfaces */
1235
+ for (port = 0 ; port < ocelot -> num_phys_ports ; port ++ ) {
1236
+ if (!registered_ports [port ])
1237
+ continue ;
1238
+
1239
+ ocelot_port_devlink_teardown (ocelot , port );
1240
+ }
1241
+ kfree (registered_ports );
1242
+ return err ;
1174
1243
}
1175
1244
1176
1245
static int mscc_ocelot_probe (struct platform_device * pdev )
1177
1246
{
1178
1247
struct device_node * np = pdev -> dev .of_node ;
1179
1248
int err , irq_xtr , irq_ptp_rdy ;
1180
1249
struct device_node * ports ;
1250
+ struct devlink * devlink ;
1181
1251
struct ocelot * ocelot ;
1182
1252
struct regmap * hsio ;
1183
1253
unsigned int i ;
@@ -1201,10 +1271,12 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
1201
1271
if (!np && !pdev -> dev .platform_data )
1202
1272
return - ENODEV ;
1203
1273
1204
- ocelot = devm_kzalloc ( & pdev -> dev , sizeof (* ocelot ), GFP_KERNEL );
1205
- if (!ocelot )
1274
+ devlink = devlink_alloc ( & ocelot_devlink_ops , sizeof (* ocelot ));
1275
+ if (!devlink )
1206
1276
return - ENOMEM ;
1207
1277
1278
+ ocelot = devlink_priv (devlink );
1279
+ ocelot -> devlink = priv_to_devlink (ocelot );
1208
1280
platform_set_drvdata (pdev , ocelot );
1209
1281
ocelot -> dev = & pdev -> dev ;
1210
1282
@@ -1221,7 +1293,8 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
1221
1293
ocelot -> targets [io_target [i ].id ] = NULL ;
1222
1294
continue ;
1223
1295
}
1224
- return PTR_ERR (target );
1296
+ err = PTR_ERR (target );
1297
+ goto out_free_devlink ;
1225
1298
}
1226
1299
1227
1300
ocelot -> targets [io_target [i ].id ] = target ;
@@ -1230,24 +1303,25 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
1230
1303
hsio = syscon_regmap_lookup_by_compatible ("mscc,ocelot-hsio" );
1231
1304
if (IS_ERR (hsio )) {
1232
1305
dev_err (& pdev -> dev , "missing hsio syscon\n" );
1233
- return PTR_ERR (hsio );
1306
+ err = PTR_ERR (hsio );
1307
+ goto out_free_devlink ;
1234
1308
}
1235
1309
1236
1310
ocelot -> targets [HSIO ] = hsio ;
1237
1311
1238
1312
err = ocelot_chip_init (ocelot , & ocelot_ops );
1239
1313
if (err )
1240
- return err ;
1314
+ goto out_free_devlink ;
1241
1315
1242
1316
irq_xtr = platform_get_irq_byname (pdev , "xtr" );
1243
1317
if (irq_xtr < 0 )
1244
- return - ENODEV ;
1318
+ goto out_free_devlink ;
1245
1319
1246
1320
err = devm_request_threaded_irq (& pdev -> dev , irq_xtr , NULL ,
1247
1321
ocelot_xtr_irq_handler , IRQF_ONESHOT ,
1248
1322
"frame extraction" , ocelot );
1249
1323
if (err )
1250
- return err ;
1324
+ goto out_free_devlink ;
1251
1325
1252
1326
irq_ptp_rdy = platform_get_irq_byname (pdev , "ptp_rdy" );
1253
1327
if (irq_ptp_rdy > 0 && ocelot -> targets [PTP ]) {
@@ -1256,7 +1330,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
1256
1330
IRQF_ONESHOT , "ptp ready" ,
1257
1331
ocelot );
1258
1332
if (err )
1259
- return err ;
1333
+ goto out_free_devlink ;
1260
1334
1261
1335
/* Both the PTP interrupt and the PTP bank are available */
1262
1336
ocelot -> ptp = 1 ;
@@ -1265,7 +1339,8 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
1265
1339
ports = of_get_child_by_name (np , "ethernet-ports" );
1266
1340
if (!ports ) {
1267
1341
dev_err (ocelot -> dev , "no ethernet-ports child node found\n" );
1268
- return - ENODEV ;
1342
+ err = - ENODEV ;
1343
+ goto out_free_devlink ;
1269
1344
}
1270
1345
1271
1346
ocelot -> num_phys_ports = of_get_child_count (ports );
@@ -1280,10 +1355,14 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
1280
1355
if (err )
1281
1356
goto out_put_ports ;
1282
1357
1283
- err = mscc_ocelot_init_ports ( pdev , ports );
1358
+ err = devlink_register ( devlink , ocelot -> dev );
1284
1359
if (err )
1285
1360
goto out_ocelot_deinit ;
1286
1361
1362
+ err = mscc_ocelot_init_ports (pdev , ports );
1363
+ if (err )
1364
+ goto out_ocelot_devlink_unregister ;
1365
+
1287
1366
if (ocelot -> ptp ) {
1288
1367
err = ocelot_init_timestamp (ocelot , & ocelot_ptp_clock_info );
1289
1368
if (err ) {
@@ -1303,10 +1382,14 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
1303
1382
1304
1383
return 0 ;
1305
1384
1385
+ out_ocelot_devlink_unregister :
1386
+ devlink_unregister (devlink );
1306
1387
out_ocelot_deinit :
1307
1388
ocelot_deinit (ocelot );
1308
1389
out_put_ports :
1309
1390
of_node_put (ports );
1391
+ out_free_devlink :
1392
+ devlink_free (devlink );
1310
1393
return err ;
1311
1394
}
1312
1395
@@ -1316,10 +1399,13 @@ static int mscc_ocelot_remove(struct platform_device *pdev)
1316
1399
1317
1400
ocelot_deinit_timestamp (ocelot );
1318
1401
mscc_ocelot_release_ports (ocelot );
1402
+ mscc_ocelot_teardown_devlink_ports (ocelot );
1403
+ devlink_unregister (ocelot -> devlink );
1319
1404
ocelot_deinit (ocelot );
1320
1405
unregister_switchdev_blocking_notifier (& ocelot_switchdev_blocking_nb );
1321
1406
unregister_switchdev_notifier (& ocelot_switchdev_nb );
1322
1407
unregister_netdevice_notifier (& ocelot_netdevice_nb );
1408
+ devlink_free (ocelot -> devlink );
1323
1409
1324
1410
return 0 ;
1325
1411
}
0 commit comments