@@ -110,7 +110,7 @@ struct ffa_drv_info {
110
110
struct work_struct sched_recv_irq_work ;
111
111
struct xarray partition_info ;
112
112
DECLARE_HASHTABLE (notifier_hash , ilog2 (FFA_MAX_NOTIFICATIONS ));
113
- struct mutex notify_lock ; /* lock to protect notifier hashtable */
113
+ rwlock_t notify_lock ; /* lock to protect notifier hashtable */
114
114
};
115
115
116
116
static struct ffa_drv_info * drv_info ;
@@ -1250,13 +1250,12 @@ notifier_hnode_get_by_type(u16 notify_id, enum notify_type type)
1250
1250
return NULL ;
1251
1251
}
1252
1252
1253
- static int
1254
- update_notifier_cb (struct ffa_device * dev , int notify_id , void * cb ,
1255
- void * cb_data , bool is_registration , bool is_framework )
1253
+ static int update_notifier_cb (struct ffa_device * dev , int notify_id ,
1254
+ struct notifier_cb_info * cb , bool is_framework )
1256
1255
{
1257
1256
struct notifier_cb_info * cb_info = NULL ;
1258
1257
enum notify_type type = ffa_notify_type_get (dev -> vm_id );
1259
- bool cb_found ;
1258
+ bool cb_found , is_registration = !! cb ;
1260
1259
1261
1260
if (is_framework )
1262
1261
cb_info = notifier_hnode_get_by_vmid_uuid (notify_id , dev -> vm_id ,
@@ -1270,20 +1269,10 @@ update_notifier_cb(struct ffa_device *dev, int notify_id, void *cb,
1270
1269
return - EINVAL ;
1271
1270
1272
1271
if (is_registration ) {
1273
- cb_info = kzalloc (sizeof (* cb_info ), GFP_KERNEL );
1274
- if (!cb_info )
1275
- return - ENOMEM ;
1276
-
1277
- cb_info -> dev = dev ;
1278
- cb_info -> cb_data = cb_data ;
1279
- if (is_framework )
1280
- cb_info -> fwk_cb = cb ;
1281
- else
1282
- cb_info -> cb = cb ;
1283
-
1284
- hash_add (drv_info -> notifier_hash , & cb_info -> hnode , notify_id );
1272
+ hash_add (drv_info -> notifier_hash , & cb -> hnode , notify_id );
1285
1273
} else {
1286
1274
hash_del (& cb_info -> hnode );
1275
+ kfree (cb_info );
1287
1276
}
1288
1277
1289
1278
return 0 ;
@@ -1300,20 +1289,19 @@ static int __ffa_notify_relinquish(struct ffa_device *dev, int notify_id,
1300
1289
if (notify_id >= FFA_MAX_NOTIFICATIONS )
1301
1290
return - EINVAL ;
1302
1291
1303
- mutex_lock (& drv_info -> notify_lock );
1292
+ write_lock (& drv_info -> notify_lock );
1304
1293
1305
- rc = update_notifier_cb (dev , notify_id , NULL , NULL , false,
1306
- is_framework );
1294
+ rc = update_notifier_cb (dev , notify_id , NULL , is_framework );
1307
1295
if (rc ) {
1308
1296
pr_err ("Could not unregister notification callback\n" );
1309
- mutex_unlock (& drv_info -> notify_lock );
1297
+ write_unlock (& drv_info -> notify_lock );
1310
1298
return rc ;
1311
1299
}
1312
1300
1313
1301
if (!is_framework )
1314
1302
rc = ffa_notification_unbind (dev -> vm_id , BIT (notify_id ));
1315
1303
1316
- mutex_unlock (& drv_info -> notify_lock );
1304
+ write_unlock (& drv_info -> notify_lock );
1317
1305
1318
1306
return rc ;
1319
1307
}
@@ -1334,35 +1322,48 @@ static int __ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
1334
1322
{
1335
1323
int rc ;
1336
1324
u32 flags = 0 ;
1325
+ struct notifier_cb_info * cb_info = NULL ;
1337
1326
1338
1327
if (ffa_notifications_disabled ())
1339
1328
return - EOPNOTSUPP ;
1340
1329
1341
1330
if (notify_id >= FFA_MAX_NOTIFICATIONS )
1342
1331
return - EINVAL ;
1343
1332
1344
- mutex_lock (& drv_info -> notify_lock );
1333
+ cb_info = kzalloc (sizeof (* cb_info ), GFP_KERNEL );
1334
+ if (!cb_info )
1335
+ return - ENOMEM ;
1336
+
1337
+ cb_info -> dev = dev ;
1338
+ cb_info -> cb_data = cb_data ;
1339
+ if (is_framework )
1340
+ cb_info -> fwk_cb = cb ;
1341
+ else
1342
+ cb_info -> cb = cb ;
1343
+
1344
+ write_lock (& drv_info -> notify_lock );
1345
1345
1346
1346
if (!is_framework ) {
1347
1347
if (is_per_vcpu )
1348
1348
flags = PER_VCPU_NOTIFICATION_FLAG ;
1349
1349
1350
1350
rc = ffa_notification_bind (dev -> vm_id , BIT (notify_id ), flags );
1351
- if (rc ) {
1352
- mutex_unlock (& drv_info -> notify_lock );
1353
- return rc ;
1354
- }
1351
+ if (rc )
1352
+ goto out_unlock_free ;
1355
1353
}
1356
1354
1357
- rc = update_notifier_cb (dev , notify_id , cb , cb_data , true,
1358
- is_framework );
1355
+ rc = update_notifier_cb (dev , notify_id , cb_info , is_framework );
1359
1356
if (rc ) {
1360
1357
pr_err ("Failed to register callback for %d - %d\n" ,
1361
1358
notify_id , rc );
1362
1359
if (!is_framework )
1363
1360
ffa_notification_unbind (dev -> vm_id , BIT (notify_id ));
1364
1361
}
1365
- mutex_unlock (& drv_info -> notify_lock );
1362
+
1363
+ out_unlock_free :
1364
+ write_unlock (& drv_info -> notify_lock );
1365
+ if (rc )
1366
+ kfree (cb_info );
1366
1367
1367
1368
return rc ;
1368
1369
}
@@ -1406,9 +1407,9 @@ static void handle_notif_callbacks(u64 bitmap, enum notify_type type)
1406
1407
if (!(bitmap & 1 ))
1407
1408
continue ;
1408
1409
1409
- mutex_lock (& drv_info -> notify_lock );
1410
+ read_lock (& drv_info -> notify_lock );
1410
1411
cb_info = notifier_hnode_get_by_type (notify_id , type );
1411
- mutex_unlock (& drv_info -> notify_lock );
1412
+ read_unlock (& drv_info -> notify_lock );
1412
1413
1413
1414
if (cb_info && cb_info -> cb )
1414
1415
cb_info -> cb (notify_id , cb_info -> cb_data );
@@ -1446,9 +1447,9 @@ static void handle_fwk_notif_callbacks(u32 bitmap)
1446
1447
1447
1448
ffa_rx_release ();
1448
1449
1449
- mutex_lock (& drv_info -> notify_lock );
1450
+ read_lock (& drv_info -> notify_lock );
1450
1451
cb_info = notifier_hnode_get_by_vmid_uuid (notify_id , target , & uuid );
1451
- mutex_unlock (& drv_info -> notify_lock );
1452
+ read_unlock (& drv_info -> notify_lock );
1452
1453
1453
1454
if (cb_info && cb_info -> fwk_cb )
1454
1455
cb_info -> fwk_cb (notify_id , cb_info -> cb_data , buf );
@@ -1973,7 +1974,7 @@ static void ffa_notifications_setup(void)
1973
1974
goto cleanup ;
1974
1975
1975
1976
hash_init (drv_info -> notifier_hash );
1976
- mutex_init (& drv_info -> notify_lock );
1977
+ rwlock_init (& drv_info -> notify_lock );
1977
1978
1978
1979
drv_info -> notif_enabled = true;
1979
1980
return ;
0 commit comments