aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc/mcdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/sfc/mcdi.c')
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c352
1 files changed, 233 insertions, 119 deletions
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 1c8bf81bdc03..67b07de2c599 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -811,125 +811,6 @@ fail:
811 return rc; 811 return rc;
812} 812}
813 813
814int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type)
815{
816 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_IN_LEN);
817 int rc;
818
819 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_START_IN_TYPE, type);
820
821 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_START_OUT_LEN != 0);
822
823 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf),
824 NULL, 0, NULL);
825 if (rc)
826 goto fail;
827
828 return 0;
829
830fail:
831 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
832 return rc;
833}
834
835int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
836 loff_t offset, u8 *buffer, size_t length)
837{
838 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_LEN);
839 MCDI_DECLARE_BUF(outbuf,
840 MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX));
841 size_t outlen;
842 int rc;
843
844 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type);
845 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset);
846 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length);
847
848 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf),
849 outbuf, sizeof(outbuf), &outlen);
850 if (rc)
851 goto fail;
852
853 memcpy(buffer, MCDI_PTR(outbuf, NVRAM_READ_OUT_READ_BUFFER), length);
854 return 0;
855
856fail:
857 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
858 return rc;
859}
860
861int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
862 loff_t offset, const u8 *buffer, size_t length)
863{
864 MCDI_DECLARE_BUF(inbuf,
865 MC_CMD_NVRAM_WRITE_IN_LEN(EFX_MCDI_NVRAM_LEN_MAX));
866 int rc;
867
868 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_TYPE, type);
869 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_OFFSET, offset);
870 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_LENGTH, length);
871 memcpy(MCDI_PTR(inbuf, NVRAM_WRITE_IN_WRITE_BUFFER), buffer, length);
872
873 BUILD_BUG_ON(MC_CMD_NVRAM_WRITE_OUT_LEN != 0);
874
875 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf,
876 ALIGN(MC_CMD_NVRAM_WRITE_IN_LEN(length), 4),
877 NULL, 0, NULL);
878 if (rc)
879 goto fail;
880
881 return 0;
882
883fail:
884 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
885 return rc;
886}
887
888int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
889 loff_t offset, size_t length)
890{
891 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_ERASE_IN_LEN);
892 int rc;
893
894 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_TYPE, type);
895 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_OFFSET, offset);
896 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_LENGTH, length);
897
898 BUILD_BUG_ON(MC_CMD_NVRAM_ERASE_OUT_LEN != 0);
899
900 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_ERASE, inbuf, sizeof(inbuf),
901 NULL, 0, NULL);
902 if (rc)
903 goto fail;
904
905 return 0;
906
907fail:
908 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
909 return rc;
910}
911
912int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type)
913{
914 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN);
915 int rc;
916
917 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_FINISH_IN_TYPE, type);
918
919 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN != 0);
920
921 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf),
922 NULL, 0, NULL);
923 if (rc)
924 goto fail;
925
926 return 0;
927
928fail:
929 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
930 return rc;
931}
932
933static int efx_mcdi_nvram_test(struct efx_nic *efx, unsigned int type) 814static int efx_mcdi_nvram_test(struct efx_nic *efx, unsigned int type)
934{ 815{
935 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_TEST_IN_LEN); 816 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_TEST_IN_LEN);
@@ -1272,3 +1153,236 @@ fail:
1272 return rc; 1153 return rc;
1273} 1154}
1274 1155
1156#ifdef CONFIG_SFC_MTD
1157
1158#define EFX_MCDI_NVRAM_LEN_MAX 128
1159
1160static int efx_mcdi_nvram_update_start(struct efx_nic *efx, unsigned int type)
1161{
1162 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_START_IN_LEN);
1163 int rc;
1164
1165 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_START_IN_TYPE, type);
1166
1167 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_START_OUT_LEN != 0);
1168
1169 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_START, inbuf, sizeof(inbuf),
1170 NULL, 0, NULL);
1171 if (rc)
1172 goto fail;
1173
1174 return 0;
1175
1176fail:
1177 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
1178 return rc;
1179}
1180
1181static int efx_mcdi_nvram_read(struct efx_nic *efx, unsigned int type,
1182 loff_t offset, u8 *buffer, size_t length)
1183{
1184 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_READ_IN_LEN);
1185 MCDI_DECLARE_BUF(outbuf,
1186 MC_CMD_NVRAM_READ_OUT_LEN(EFX_MCDI_NVRAM_LEN_MAX));
1187 size_t outlen;
1188 int rc;
1189
1190 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_TYPE, type);
1191 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_OFFSET, offset);
1192 MCDI_SET_DWORD(inbuf, NVRAM_READ_IN_LENGTH, length);
1193
1194 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_READ, inbuf, sizeof(inbuf),
1195 outbuf, sizeof(outbuf), &outlen);
1196 if (rc)
1197 goto fail;
1198
1199 memcpy(buffer, MCDI_PTR(outbuf, NVRAM_READ_OUT_READ_BUFFER), length);
1200 return 0;
1201
1202fail:
1203 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
1204 return rc;
1205}
1206
1207static int efx_mcdi_nvram_write(struct efx_nic *efx, unsigned int type,
1208 loff_t offset, const u8 *buffer, size_t length)
1209{
1210 MCDI_DECLARE_BUF(inbuf,
1211 MC_CMD_NVRAM_WRITE_IN_LEN(EFX_MCDI_NVRAM_LEN_MAX));
1212 int rc;
1213
1214 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_TYPE, type);
1215 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_OFFSET, offset);
1216 MCDI_SET_DWORD(inbuf, NVRAM_WRITE_IN_LENGTH, length);
1217 memcpy(MCDI_PTR(inbuf, NVRAM_WRITE_IN_WRITE_BUFFER), buffer, length);
1218
1219 BUILD_BUG_ON(MC_CMD_NVRAM_WRITE_OUT_LEN != 0);
1220
1221 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_WRITE, inbuf,
1222 ALIGN(MC_CMD_NVRAM_WRITE_IN_LEN(length), 4),
1223 NULL, 0, NULL);
1224 if (rc)
1225 goto fail;
1226
1227 return 0;
1228
1229fail:
1230 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
1231 return rc;
1232}
1233
1234static int efx_mcdi_nvram_erase(struct efx_nic *efx, unsigned int type,
1235 loff_t offset, size_t length)
1236{
1237 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_ERASE_IN_LEN);
1238 int rc;
1239
1240 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_TYPE, type);
1241 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_OFFSET, offset);
1242 MCDI_SET_DWORD(inbuf, NVRAM_ERASE_IN_LENGTH, length);
1243
1244 BUILD_BUG_ON(MC_CMD_NVRAM_ERASE_OUT_LEN != 0);
1245
1246 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_ERASE, inbuf, sizeof(inbuf),
1247 NULL, 0, NULL);
1248 if (rc)
1249 goto fail;
1250
1251 return 0;
1252
1253fail:
1254 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
1255 return rc;
1256}
1257
1258static int efx_mcdi_nvram_update_finish(struct efx_nic *efx, unsigned int type)
1259{
1260 MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN);
1261 int rc;
1262
1263 MCDI_SET_DWORD(inbuf, NVRAM_UPDATE_FINISH_IN_TYPE, type);
1264
1265 BUILD_BUG_ON(MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN != 0);
1266
1267 rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_UPDATE_FINISH, inbuf, sizeof(inbuf),
1268 NULL, 0, NULL);
1269 if (rc)
1270 goto fail;
1271
1272 return 0;
1273
1274fail:
1275 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
1276 return rc;
1277}
1278
1279int efx_mcdi_mtd_read(struct mtd_info *mtd, loff_t start,
1280 size_t len, size_t *retlen, u8 *buffer)
1281{
1282 struct efx_mcdi_mtd_partition *part = to_efx_mcdi_mtd_partition(mtd);
1283 struct efx_nic *efx = mtd->priv;
1284 loff_t offset = start;
1285 loff_t end = min_t(loff_t, start + len, mtd->size);
1286 size_t chunk;
1287 int rc = 0;
1288
1289 while (offset < end) {
1290 chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX);
1291 rc = efx_mcdi_nvram_read(efx, part->nvram_type, offset,
1292 buffer, chunk);
1293 if (rc)
1294 goto out;
1295 offset += chunk;
1296 buffer += chunk;
1297 }
1298out:
1299 *retlen = offset - start;
1300 return rc;
1301}
1302
1303int efx_mcdi_mtd_erase(struct mtd_info *mtd, loff_t start, size_t len)
1304{
1305 struct efx_mcdi_mtd_partition *part = to_efx_mcdi_mtd_partition(mtd);
1306 struct efx_nic *efx = mtd->priv;
1307 loff_t offset = start & ~((loff_t)(mtd->erasesize - 1));
1308 loff_t end = min_t(loff_t, start + len, mtd->size);
1309 size_t chunk = part->common.mtd.erasesize;
1310 int rc = 0;
1311
1312 if (!part->updating) {
1313 rc = efx_mcdi_nvram_update_start(efx, part->nvram_type);
1314 if (rc)
1315 goto out;
1316 part->updating = true;
1317 }
1318
1319 /* The MCDI interface can in fact do multiple erase blocks at once;
1320 * but erasing may be slow, so we make multiple calls here to avoid
1321 * tripping the MCDI RPC timeout. */
1322 while (offset < end) {
1323 rc = efx_mcdi_nvram_erase(efx, part->nvram_type, offset,
1324 chunk);
1325 if (rc)
1326 goto out;
1327 offset += chunk;
1328 }
1329out:
1330 return rc;
1331}
1332
1333int efx_mcdi_mtd_write(struct mtd_info *mtd, loff_t start,
1334 size_t len, size_t *retlen, const u8 *buffer)
1335{
1336 struct efx_mcdi_mtd_partition *part = to_efx_mcdi_mtd_partition(mtd);
1337 struct efx_nic *efx = mtd->priv;
1338 loff_t offset = start;
1339 loff_t end = min_t(loff_t, start + len, mtd->size);
1340 size_t chunk;
1341 int rc = 0;
1342
1343 if (!part->updating) {
1344 rc = efx_mcdi_nvram_update_start(efx, part->nvram_type);
1345 if (rc)
1346 goto out;
1347 part->updating = true;
1348 }
1349
1350 while (offset < end) {
1351 chunk = min_t(size_t, end - offset, EFX_MCDI_NVRAM_LEN_MAX);
1352 rc = efx_mcdi_nvram_write(efx, part->nvram_type, offset,
1353 buffer, chunk);
1354 if (rc)
1355 goto out;
1356 offset += chunk;
1357 buffer += chunk;
1358 }
1359out:
1360 *retlen = offset - start;
1361 return rc;
1362}
1363
1364int efx_mcdi_mtd_sync(struct mtd_info *mtd)
1365{
1366 struct efx_mcdi_mtd_partition *part = to_efx_mcdi_mtd_partition(mtd);
1367 struct efx_nic *efx = mtd->priv;
1368 int rc = 0;
1369
1370 if (part->updating) {
1371 part->updating = false;
1372 rc = efx_mcdi_nvram_update_finish(efx, part->nvram_type);
1373 }
1374
1375 return rc;
1376}
1377
1378void efx_mcdi_mtd_rename(struct efx_mtd_partition *part)
1379{
1380 struct efx_mcdi_mtd_partition *mcdi_part =
1381 container_of(part, struct efx_mcdi_mtd_partition, common);
1382 struct efx_nic *efx = part->mtd.priv;
1383
1384 snprintf(part->name, sizeof(part->name), "%s %s:%02x",
1385 efx->name, part->type_name, mcdi_part->fw_subtype);
1386}
1387
1388#endif /* CONFIG_SFC_MTD */