@@ -1248,6 +1248,43 @@ static struct nvdimm *acpi_nfit_dimm_by_handle(struct acpi_nfit_desc *acpi_desc,
1248
1248
return NULL ;
1249
1249
}
1250
1250
1251
+ static void __acpi_nvdimm_notify (struct device * dev , u32 event )
1252
+ {
1253
+ struct nfit_mem * nfit_mem ;
1254
+ struct acpi_nfit_desc * acpi_desc ;
1255
+
1256
+ dev_dbg (dev -> parent , "%s: %s: event: %d\n" , dev_name (dev ), __func__ ,
1257
+ event );
1258
+
1259
+ if (event != NFIT_NOTIFY_DIMM_HEALTH ) {
1260
+ dev_dbg (dev -> parent , "%s: unknown event: %d\n" , dev_name (dev ),
1261
+ event );
1262
+ return ;
1263
+ }
1264
+
1265
+ acpi_desc = dev_get_drvdata (dev -> parent );
1266
+ if (!acpi_desc )
1267
+ return ;
1268
+
1269
+ /*
1270
+ * If we successfully retrieved acpi_desc, then we know nfit_mem data
1271
+ * is still valid.
1272
+ */
1273
+ nfit_mem = dev_get_drvdata (dev );
1274
+ if (nfit_mem && nfit_mem -> flags_attr )
1275
+ sysfs_notify_dirent (nfit_mem -> flags_attr );
1276
+ }
1277
+
1278
+ static void acpi_nvdimm_notify (acpi_handle handle , u32 event , void * data )
1279
+ {
1280
+ struct acpi_device * adev = data ;
1281
+ struct device * dev = & adev -> dev ;
1282
+
1283
+ device_lock (dev -> parent );
1284
+ __acpi_nvdimm_notify (dev , event );
1285
+ device_unlock (dev -> parent );
1286
+ }
1287
+
1251
1288
static int acpi_nfit_add_dimm (struct acpi_nfit_desc * acpi_desc ,
1252
1289
struct nfit_mem * nfit_mem , u32 device_handle )
1253
1290
{
@@ -1272,6 +1309,13 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
1272
1309
return force_enable_dimms ? 0 : - ENODEV ;
1273
1310
}
1274
1311
1312
+ if (ACPI_FAILURE (acpi_install_notify_handler (adev_dimm -> handle ,
1313
+ ACPI_DEVICE_NOTIFY , acpi_nvdimm_notify , adev_dimm ))) {
1314
+ dev_err (dev , "%s: notification registration failed\n" ,
1315
+ dev_name (& adev_dimm -> dev ));
1316
+ return - ENXIO ;
1317
+ }
1318
+
1275
1319
/*
1276
1320
* Until standardization materializes we need to consider 4
1277
1321
* different command sets. Note, that checking for function0 (bit0)
@@ -1310,18 +1354,38 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
1310
1354
return 0 ;
1311
1355
}
1312
1356
1357
+ static void shutdown_dimm_notify (void * data )
1358
+ {
1359
+ struct acpi_nfit_desc * acpi_desc = data ;
1360
+ struct nfit_mem * nfit_mem ;
1361
+
1362
+ mutex_lock (& acpi_desc -> init_mutex );
1363
+ /*
1364
+ * Clear out the nfit_mem->flags_attr and shut down dimm event
1365
+ * notifications.
1366
+ */
1367
+ list_for_each_entry (nfit_mem , & acpi_desc -> dimms , list ) {
1368
+ if (nfit_mem -> flags_attr ) {
1369
+ sysfs_put (nfit_mem -> flags_attr );
1370
+ nfit_mem -> flags_attr = NULL ;
1371
+ }
1372
+ acpi_remove_notify_handler (nfit_mem -> adev -> handle ,
1373
+ ACPI_DEVICE_NOTIFY , acpi_nvdimm_notify );
1374
+ }
1375
+ mutex_unlock (& acpi_desc -> init_mutex );
1376
+ }
1377
+
1313
1378
static int acpi_nfit_register_dimms (struct acpi_nfit_desc * acpi_desc )
1314
1379
{
1315
1380
struct nfit_mem * nfit_mem ;
1316
- int dimm_count = 0 ;
1381
+ int dimm_count = 0 , rc ;
1382
+ struct nvdimm * nvdimm ;
1317
1383
1318
1384
list_for_each_entry (nfit_mem , & acpi_desc -> dimms , list ) {
1319
1385
struct acpi_nfit_flush_address * flush ;
1320
1386
unsigned long flags = 0 , cmd_mask ;
1321
- struct nvdimm * nvdimm ;
1322
1387
u32 device_handle ;
1323
1388
u16 mem_flags ;
1324
- int rc ;
1325
1389
1326
1390
device_handle = __to_nfit_memdev (nfit_mem )-> device_handle ;
1327
1391
nvdimm = acpi_nfit_dimm_by_handle (acpi_desc , device_handle );
@@ -1374,7 +1438,30 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
1374
1438
1375
1439
}
1376
1440
1377
- return nvdimm_bus_check_dimm_count (acpi_desc -> nvdimm_bus , dimm_count );
1441
+ rc = nvdimm_bus_check_dimm_count (acpi_desc -> nvdimm_bus , dimm_count );
1442
+ if (rc )
1443
+ return rc ;
1444
+
1445
+ /*
1446
+ * Now that dimms are successfully registered, and async registration
1447
+ * is flushed, attempt to enable event notification.
1448
+ */
1449
+ list_for_each_entry (nfit_mem , & acpi_desc -> dimms , list ) {
1450
+ struct kernfs_node * nfit_kernfs ;
1451
+
1452
+ nvdimm = nfit_mem -> nvdimm ;
1453
+ nfit_kernfs = sysfs_get_dirent (nvdimm_kobj (nvdimm )-> sd , "nfit" );
1454
+ if (nfit_kernfs )
1455
+ nfit_mem -> flags_attr = sysfs_get_dirent (nfit_kernfs ,
1456
+ "flags" );
1457
+ sysfs_put (nfit_kernfs );
1458
+ if (!nfit_mem -> flags_attr )
1459
+ dev_warn (acpi_desc -> dev , "%s: notifications disabled\n" ,
1460
+ nvdimm_name (nvdimm ));
1461
+ }
1462
+
1463
+ return devm_add_action_or_reset (acpi_desc -> dev , shutdown_dimm_notify ,
1464
+ acpi_desc );
1378
1465
}
1379
1466
1380
1467
static void acpi_nfit_init_dsms (struct acpi_nfit_desc * acpi_desc )
0 commit comments