@@ -173,6 +173,9 @@ struct nfit_test_fw {
173
173
u64 version ;
174
174
u32 size_received ;
175
175
u64 end_time ;
176
+ bool armed ;
177
+ bool missed_activate ;
178
+ unsigned long last_activate ;
176
179
};
177
180
178
181
struct nfit_test {
@@ -345,7 +348,7 @@ static int nd_intel_test_finish_fw(struct nfit_test *t,
345
348
__func__ , t , nd_cmd , buf_len , idx );
346
349
347
350
if (fw -> state == FW_STATE_UPDATED ) {
348
- /* update already done, need cold boot */
351
+ /* update already done, need activation */
349
352
nd_cmd -> status = 0x20007 ;
350
353
return 0 ;
351
354
}
@@ -430,6 +433,7 @@ static int nd_intel_test_finish_query(struct nfit_test *t,
430
433
}
431
434
dev_dbg (dev , "%s: transition out verify\n" , __func__ );
432
435
fw -> state = FW_STATE_UPDATED ;
436
+ fw -> missed_activate = false;
433
437
/* fall through */
434
438
case FW_STATE_UPDATED :
435
439
nd_cmd -> status = 0 ;
@@ -1178,6 +1182,134 @@ static int nd_intel_test_cmd_master_secure_erase(struct nfit_test *t,
1178
1182
return 0 ;
1179
1183
}
1180
1184
1185
+ static unsigned long last_activate ;
1186
+
1187
+ static int nvdimm_bus_intel_fw_activate_businfo (struct nfit_test * t ,
1188
+ struct nd_intel_bus_fw_activate_businfo * nd_cmd ,
1189
+ unsigned int buf_len )
1190
+ {
1191
+ int i , armed = 0 ;
1192
+ int state ;
1193
+ u64 tmo ;
1194
+
1195
+ for (i = 0 ; i < NUM_DCR ; i ++ ) {
1196
+ struct nfit_test_fw * fw = & t -> fw [i ];
1197
+
1198
+ if (fw -> armed )
1199
+ armed ++ ;
1200
+ }
1201
+
1202
+ /*
1203
+ * Emulate 3 second activation max, and 1 second incremental
1204
+ * quiesce time per dimm requiring multiple activates to get all
1205
+ * DIMMs updated.
1206
+ */
1207
+ if (armed )
1208
+ state = ND_INTEL_FWA_ARMED ;
1209
+ else if (!last_activate || time_after (jiffies , last_activate + 3 * HZ ))
1210
+ state = ND_INTEL_FWA_IDLE ;
1211
+ else
1212
+ state = ND_INTEL_FWA_BUSY ;
1213
+
1214
+ tmo = armed * USEC_PER_SEC ;
1215
+ * nd_cmd = (struct nd_intel_bus_fw_activate_businfo ) {
1216
+ .capability = ND_INTEL_BUS_FWA_CAP_FWQUIESCE
1217
+ | ND_INTEL_BUS_FWA_CAP_OSQUIESCE
1218
+ | ND_INTEL_BUS_FWA_CAP_RESET ,
1219
+ .state = state ,
1220
+ .activate_tmo = tmo ,
1221
+ .cpu_quiesce_tmo = tmo ,
1222
+ .io_quiesce_tmo = tmo ,
1223
+ .max_quiesce_tmo = 3 * USEC_PER_SEC ,
1224
+ };
1225
+
1226
+ return 0 ;
1227
+ }
1228
+
1229
+ static int nvdimm_bus_intel_fw_activate (struct nfit_test * t ,
1230
+ struct nd_intel_bus_fw_activate * nd_cmd ,
1231
+ unsigned int buf_len )
1232
+ {
1233
+ struct nd_intel_bus_fw_activate_businfo info ;
1234
+ u32 status = 0 ;
1235
+ int i ;
1236
+
1237
+ nvdimm_bus_intel_fw_activate_businfo (t , & info , sizeof (info ));
1238
+ if (info .state == ND_INTEL_FWA_BUSY )
1239
+ status = ND_INTEL_BUS_FWA_STATUS_BUSY ;
1240
+ else if (info .activate_tmo > info .max_quiesce_tmo )
1241
+ status = ND_INTEL_BUS_FWA_STATUS_TMO ;
1242
+ else if (info .state == ND_INTEL_FWA_IDLE )
1243
+ status = ND_INTEL_BUS_FWA_STATUS_NOARM ;
1244
+
1245
+ dev_dbg (& t -> pdev .dev , "status: %d\n" , status );
1246
+ nd_cmd -> status = status ;
1247
+ if (status && status != ND_INTEL_BUS_FWA_STATUS_TMO )
1248
+ return 0 ;
1249
+
1250
+ last_activate = jiffies ;
1251
+ for (i = 0 ; i < NUM_DCR ; i ++ ) {
1252
+ struct nfit_test_fw * fw = & t -> fw [i ];
1253
+
1254
+ if (!fw -> armed )
1255
+ continue ;
1256
+ if (fw -> state != FW_STATE_UPDATED )
1257
+ fw -> missed_activate = true;
1258
+ else
1259
+ fw -> state = FW_STATE_NEW ;
1260
+ fw -> armed = false;
1261
+ fw -> last_activate = last_activate ;
1262
+ }
1263
+
1264
+ return 0 ;
1265
+ }
1266
+
1267
+ static int nd_intel_test_cmd_fw_activate_dimminfo (struct nfit_test * t ,
1268
+ struct nd_intel_fw_activate_dimminfo * nd_cmd ,
1269
+ unsigned int buf_len , int dimm )
1270
+ {
1271
+ struct nd_intel_bus_fw_activate_businfo info ;
1272
+ struct nfit_test_fw * fw = & t -> fw [dimm ];
1273
+ u32 result , state ;
1274
+
1275
+ nvdimm_bus_intel_fw_activate_businfo (t , & info , sizeof (info ));
1276
+
1277
+ if (info .state == ND_INTEL_FWA_BUSY )
1278
+ state = ND_INTEL_FWA_BUSY ;
1279
+ else if (info .state == ND_INTEL_FWA_IDLE )
1280
+ state = ND_INTEL_FWA_IDLE ;
1281
+ else if (fw -> armed )
1282
+ state = ND_INTEL_FWA_ARMED ;
1283
+ else
1284
+ state = ND_INTEL_FWA_IDLE ;
1285
+
1286
+ result = ND_INTEL_DIMM_FWA_NONE ;
1287
+ if (last_activate && fw -> last_activate == last_activate &&
1288
+ state == ND_INTEL_FWA_IDLE ) {
1289
+ if (fw -> missed_activate )
1290
+ result = ND_INTEL_DIMM_FWA_NOTSTAGED ;
1291
+ else
1292
+ result = ND_INTEL_DIMM_FWA_SUCCESS ;
1293
+ }
1294
+
1295
+ * nd_cmd = (struct nd_intel_fw_activate_dimminfo ) {
1296
+ .result = result ,
1297
+ .state = state ,
1298
+ };
1299
+
1300
+ return 0 ;
1301
+ }
1302
+
1303
+ static int nd_intel_test_cmd_fw_activate_arm (struct nfit_test * t ,
1304
+ struct nd_intel_fw_activate_arm * nd_cmd ,
1305
+ unsigned int buf_len , int dimm )
1306
+ {
1307
+ struct nfit_test_fw * fw = & t -> fw [dimm ];
1308
+
1309
+ fw -> armed = nd_cmd -> activate_arm == ND_INTEL_DIMM_FWA_ARM ;
1310
+ nd_cmd -> status = 0 ;
1311
+ return 0 ;
1312
+ }
1181
1313
1182
1314
static int get_dimm (struct nfit_mem * nfit_mem , unsigned int func )
1183
1315
{
@@ -1296,6 +1428,14 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
1296
1428
rc = nd_intel_test_cmd_master_secure_erase (t ,
1297
1429
buf , buf_len , i );
1298
1430
break ;
1431
+ case NVDIMM_INTEL_FW_ACTIVATE_DIMMINFO :
1432
+ rc = nd_intel_test_cmd_fw_activate_dimminfo (
1433
+ t , buf , buf_len , i );
1434
+ break ;
1435
+ case NVDIMM_INTEL_FW_ACTIVATE_ARM :
1436
+ rc = nd_intel_test_cmd_fw_activate_arm (
1437
+ t , buf , buf_len , i );
1438
+ break ;
1299
1439
case ND_INTEL_ENABLE_LSS_STATUS :
1300
1440
rc = nd_intel_test_cmd_set_lss_status (t ,
1301
1441
buf , buf_len );
@@ -1380,9 +1520,9 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
1380
1520
if (!nd_desc )
1381
1521
return - ENOTTY ;
1382
1522
1383
- if (cmd == ND_CMD_CALL ) {
1523
+ if (cmd == ND_CMD_CALL && call_pkg -> nd_family
1524
+ == NVDIMM_BUS_FAMILY_NFIT ) {
1384
1525
func = call_pkg -> nd_command ;
1385
-
1386
1526
buf_len = call_pkg -> nd_size_in + call_pkg -> nd_size_out ;
1387
1527
buf = (void * ) call_pkg -> nd_payload ;
1388
1528
@@ -1406,7 +1546,26 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
1406
1546
default :
1407
1547
return - ENOTTY ;
1408
1548
}
1409
- }
1549
+ } else if (cmd == ND_CMD_CALL && call_pkg -> nd_family
1550
+ == NVDIMM_BUS_FAMILY_INTEL ) {
1551
+ func = call_pkg -> nd_command ;
1552
+ buf_len = call_pkg -> nd_size_in + call_pkg -> nd_size_out ;
1553
+ buf = (void * ) call_pkg -> nd_payload ;
1554
+
1555
+ switch (func ) {
1556
+ case NVDIMM_BUS_INTEL_FW_ACTIVATE_BUSINFO :
1557
+ rc = nvdimm_bus_intel_fw_activate_businfo (t ,
1558
+ buf , buf_len );
1559
+ return rc ;
1560
+ case NVDIMM_BUS_INTEL_FW_ACTIVATE :
1561
+ rc = nvdimm_bus_intel_fw_activate (t , buf ,
1562
+ buf_len );
1563
+ return rc ;
1564
+ default :
1565
+ return - ENOTTY ;
1566
+ }
1567
+ } else if (cmd == ND_CMD_CALL )
1568
+ return - ENOTTY ;
1410
1569
1411
1570
if (!nd_desc || !test_bit (cmd , & nd_desc -> cmd_mask ))
1412
1571
return - ENOTTY ;
@@ -1832,6 +1991,7 @@ static void nfit_test0_setup(struct nfit_test *t)
1832
1991
struct acpi_nfit_flush_address * flush ;
1833
1992
struct acpi_nfit_capabilities * pcap ;
1834
1993
unsigned int offset = 0 , i ;
1994
+ unsigned long * acpi_mask ;
1835
1995
1836
1996
/*
1837
1997
* spa0 (interleave first half of dimm0 and dimm1, note storage
@@ -2558,6 +2718,12 @@ static void nfit_test0_setup(struct nfit_test *t)
2558
2718
& acpi_desc -> dimm_cmd_force_en );
2559
2719
set_bit (NVDIMM_INTEL_MASTER_SECURE_ERASE ,
2560
2720
& acpi_desc -> dimm_cmd_force_en );
2721
+ set_bit (NVDIMM_INTEL_FW_ACTIVATE_DIMMINFO , & acpi_desc -> dimm_cmd_force_en );
2722
+ set_bit (NVDIMM_INTEL_FW_ACTIVATE_ARM , & acpi_desc -> dimm_cmd_force_en );
2723
+
2724
+ acpi_mask = & acpi_desc -> family_dsm_mask [NVDIMM_BUS_FAMILY_INTEL ];
2725
+ set_bit (NVDIMM_BUS_INTEL_FW_ACTIVATE_BUSINFO , acpi_mask );
2726
+ set_bit (NVDIMM_BUS_INTEL_FW_ACTIVATE , acpi_mask );
2561
2727
}
2562
2728
2563
2729
static void nfit_test1_setup (struct nfit_test * t )
@@ -2733,6 +2899,7 @@ static int nfit_ctl_test(struct device *dev)
2733
2899
struct nd_cmd_clear_error clear_err ;
2734
2900
struct nd_cmd_ars_status ars_stat ;
2735
2901
struct nd_cmd_ars_cap ars_cap ;
2902
+ struct nd_intel_bus_fw_activate_businfo fwa_info ;
2736
2903
char buf [sizeof (struct nd_cmd_ars_status )
2737
2904
+ sizeof (struct nd_ars_record )];
2738
2905
};
@@ -2761,11 +2928,15 @@ static int nfit_ctl_test(struct device *dev)
2761
2928
.module = THIS_MODULE ,
2762
2929
.provider_name = "ACPI.NFIT" ,
2763
2930
.ndctl = acpi_nfit_ctl ,
2931
+ .bus_family_mask = 1UL << NVDIMM_BUS_FAMILY_NFIT
2932
+ | 1UL << NVDIMM_BUS_FAMILY_INTEL ,
2764
2933
},
2765
2934
.bus_dsm_mask = 1UL << NFIT_CMD_TRANSLATE_SPA
2766
2935
| 1UL << NFIT_CMD_ARS_INJECT_SET
2767
2936
| 1UL << NFIT_CMD_ARS_INJECT_CLEAR
2768
2937
| 1UL << NFIT_CMD_ARS_INJECT_GET ,
2938
+ .family_dsm_mask [NVDIMM_BUS_FAMILY_INTEL ] =
2939
+ NVDIMM_BUS_INTEL_FW_ACTIVATE_CMDMASK ,
2769
2940
.dev = & adev -> dev ,
2770
2941
};
2771
2942
@@ -2932,6 +3103,36 @@ static int nfit_ctl_test(struct device *dev)
2932
3103
return - EIO ;
2933
3104
}
2934
3105
3106
+ /* test firmware activate bus info */
3107
+ cmd_size = sizeof (cmd .fwa_info );
3108
+ cmd = (struct nfit_ctl_test_cmd ) {
3109
+ .pkg = {
3110
+ .nd_command = NVDIMM_BUS_INTEL_FW_ACTIVATE_BUSINFO ,
3111
+ .nd_family = NVDIMM_BUS_FAMILY_INTEL ,
3112
+ .nd_size_out = cmd_size ,
3113
+ .nd_fw_size = cmd_size ,
3114
+ },
3115
+ .fwa_info = {
3116
+ .state = ND_INTEL_FWA_IDLE ,
3117
+ .capability = ND_INTEL_BUS_FWA_CAP_FWQUIESCE
3118
+ | ND_INTEL_BUS_FWA_CAP_OSQUIESCE ,
3119
+ .activate_tmo = 1 ,
3120
+ .cpu_quiesce_tmo = 1 ,
3121
+ .io_quiesce_tmo = 1 ,
3122
+ .max_quiesce_tmo = 1 ,
3123
+ },
3124
+ };
3125
+ rc = setup_result (cmd .buf , cmd_size );
3126
+ if (rc )
3127
+ return rc ;
3128
+ rc = acpi_nfit_ctl (& acpi_desc -> nd_desc , NULL , ND_CMD_CALL ,
3129
+ & cmd , sizeof (cmd .pkg ) + cmd_size , & cmd_rc );
3130
+ if (rc < 0 || cmd_rc ) {
3131
+ dev_dbg (dev , "%s: failed at: %d rc: %d cmd_rc: %d\n" ,
3132
+ __func__ , __LINE__ , rc , cmd_rc );
3133
+ return - EIO ;
3134
+ }
3135
+
2935
3136
return 0 ;
2936
3137
}
2937
3138
0 commit comments