Skip to content

Commit d9f6c64

Browse files
committed
firewire: core: use xarray instead of idr to maintain client resource
In core function, the instances of some client resource structures are maintained by IDR. As of kernel v6.0, IDR has been superseded by XArray and deprecated. This commit replaces the usage of IDR with XArray to maintain the resource instances. The instance of XArray is allocated per client with XA_FLAGS_ALLOC1 so that the index of allocated entry is greater than zero and returns to user space client as handle of the resource. Link: https://lore.kernel.org/r/20240812235210.28458-6-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
1 parent 6ec9e92 commit d9f6c64

2 files changed

Lines changed: 35 additions & 32 deletions

File tree

drivers/firewire/core-cdev.c

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <linux/errno.h>
1515
#include <linux/firewire.h>
1616
#include <linux/firewire-cdev.h>
17-
#include <linux/idr.h>
1817
#include <linux/irqflags.h>
1918
#include <linux/jiffies.h>
2019
#include <linux/kernel.h>
@@ -54,7 +53,7 @@ struct client {
5453

5554
spinlock_t lock;
5655
bool in_shutdown;
57-
struct idr resource_idr;
56+
struct xarray resource_xa;
5857
struct list_head event_list;
5958
wait_queue_head_t wait;
6059
wait_queue_head_t tx_flush_wait;
@@ -297,7 +296,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
297296

298297
client->device = device;
299298
spin_lock_init(&client->lock);
300-
idr_init(&client->resource_idr);
299+
xa_init_flags(&client->resource_xa, XA_FLAGS_ALLOC1 | XA_FLAGS_LOCK_BH);
301300
INIT_LIST_HEAD(&client->event_list);
302301
init_waitqueue_head(&client->wait);
303302
init_waitqueue_head(&client->tx_flush_wait);
@@ -407,7 +406,7 @@ static void queue_bus_reset_event(struct client *client)
407406
{
408407
struct bus_reset_event *e;
409408
struct client_resource *resource;
410-
int id;
409+
unsigned long index;
411410

412411
e = kzalloc(sizeof(*e), GFP_KERNEL);
413412
if (e == NULL)
@@ -420,7 +419,7 @@ static void queue_bus_reset_event(struct client *client)
420419

421420
guard(spinlock_irq)(&client->lock);
422421

423-
idr_for_each_entry(&client->resource_idr, resource, id) {
422+
xa_for_each(&client->resource_xa, index, resource) {
424423
if (is_iso_resource(resource))
425424
schedule_iso_resource(to_iso_resource(resource), 0);
426425
}
@@ -501,49 +500,52 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
501500
return ret ? -EFAULT : 0;
502501
}
503502

504-
static int add_client_resource(struct client *client,
505-
struct client_resource *resource, gfp_t gfp_mask)
503+
static int add_client_resource(struct client *client, struct client_resource *resource,
504+
gfp_t gfp_mask)
506505
{
507-
bool preload = gfpflags_allow_blocking(gfp_mask);
508506
int ret;
509507

510-
if (preload)
511-
idr_preload(gfp_mask);
512-
513508
scoped_guard(spinlock_irqsave, &client->lock) {
514-
if (client->in_shutdown)
509+
u32 index;
510+
511+
if (client->in_shutdown) {
515512
ret = -ECANCELED;
516-
else
517-
ret = idr_alloc(&client->resource_idr, resource, 0, 0, GFP_NOWAIT);
513+
} else {
514+
if (gfpflags_allow_blocking(gfp_mask)) {
515+
ret = xa_alloc(&client->resource_xa, &index, resource, xa_limit_32b,
516+
GFP_NOWAIT);
517+
} else {
518+
ret = xa_alloc_bh(&client->resource_xa, &index, resource,
519+
xa_limit_32b, GFP_NOWAIT);
520+
}
521+
}
518522
if (ret >= 0) {
519-
resource->handle = ret;
523+
resource->handle = index;
520524
client_get(client);
521525
if (is_iso_resource(resource))
522526
schedule_iso_resource(to_iso_resource(resource), 0);
523527
}
524528
}
525529

526-
if (preload)
527-
idr_preload_end();
528-
529530
return ret < 0 ? ret : 0;
530531
}
531532

532533
static int release_client_resource(struct client *client, u32 handle,
533534
client_resource_release_fn_t release,
534535
struct client_resource **return_resource)
535536
{
537+
unsigned long index = handle;
536538
struct client_resource *resource;
537539

538540
scoped_guard(spinlock_irq, &client->lock) {
539541
if (client->in_shutdown)
540542
return -EINVAL;
541543

542-
resource = idr_find(&client->resource_idr, handle);
544+
resource = xa_load(&client->resource_xa, index);
543545
if (!resource || resource->release != release)
544546
return -EINVAL;
545547

546-
idr_remove(&client->resource_idr, handle);
548+
xa_erase(&client->resource_xa, handle);
547549
}
548550

549551
if (return_resource)
@@ -566,9 +568,10 @@ static void complete_transaction(struct fw_card *card, int rcode, u32 request_ts
566568
{
567569
struct outbound_transaction_event *e = data;
568570
struct client *client = e->client;
571+
unsigned long index = e->r.resource.handle;
569572

570573
scoped_guard(spinlock_irqsave, &client->lock) {
571-
idr_remove(&client->resource_idr, e->r.resource.handle);
574+
xa_erase(&client->resource_xa, index);
572575
if (client->in_shutdown)
573576
wake_up(&client->tx_flush_wait);
574577
}
@@ -619,7 +622,7 @@ static void complete_transaction(struct fw_card *card, int rcode, u32 request_ts
619622
break;
620623
}
621624

622-
/* Drop the idr's reference */
625+
// Drop the xarray's reference.
623626
client_put(client);
624627
}
625628

@@ -1317,6 +1320,7 @@ static void iso_resource_work(struct work_struct *work)
13171320
struct iso_resource *r =
13181321
container_of(work, struct iso_resource, work.work);
13191322
struct client *client = r->client;
1323+
unsigned long index = r->resource.handle;
13201324
int generation, channel, bandwidth, todo;
13211325
bool skip, free, success;
13221326

@@ -1351,7 +1355,7 @@ static void iso_resource_work(struct work_struct *work)
13511355
todo == ISO_RES_ALLOC_ONCE);
13521356
/*
13531357
* Is this generation outdated already? As long as this resource sticks
1354-
* in the idr, it will be scheduled again for a newer generation or at
1358+
* in the xarray, it will be scheduled again for a newer generation or at
13551359
* shutdown.
13561360
*/
13571361
if (channel == -EAGAIN &&
@@ -1366,10 +1370,10 @@ static void iso_resource_work(struct work_struct *work)
13661370
if (r->todo == ISO_RES_ALLOC)
13671371
r->todo = ISO_RES_REALLOC;
13681372
// Allocation or reallocation failure? Pull this resource out of the
1369-
// idr and prepare for deletion, unless the client is shutting down.
1373+
// xarray and prepare for deletion, unless the client is shutting down.
13701374
if (r->todo == ISO_RES_REALLOC && !success &&
13711375
!client->in_shutdown &&
1372-
idr_remove(&client->resource_idr, r->resource.handle)) {
1376+
xa_erase(&client->resource_xa, index)) {
13731377
client_put(client);
13741378
free = true;
13751379
}
@@ -1839,11 +1843,11 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
18391843
static bool has_outbound_transactions(struct client *client)
18401844
{
18411845
struct client_resource *resource;
1842-
int id;
1846+
unsigned long index;
18431847

18441848
guard(spinlock_irq)(&client->lock);
18451849

1846-
idr_for_each_entry(&client->resource_idr, resource, id) {
1850+
xa_for_each(&client->resource_xa, index, resource) {
18471851
if (is_outbound_transaction_resource(resource))
18481852
return true;
18491853
}
@@ -1856,7 +1860,7 @@ static int fw_device_op_release(struct inode *inode, struct file *file)
18561860
struct client *client = file->private_data;
18571861
struct event *event, *next_event;
18581862
struct client_resource *resource;
1859-
int id;
1863+
unsigned long index;
18601864

18611865
scoped_guard(spinlock_irq, &client->device->card->lock)
18621866
list_del(&client->phy_receiver_link);
@@ -1870,17 +1874,17 @@ static int fw_device_op_release(struct inode *inode, struct file *file)
18701874
if (client->buffer.pages)
18711875
fw_iso_buffer_destroy(&client->buffer, client->device->card);
18721876

1873-
/* Freeze client->resource_idr and client->event_list */
1877+
// Freeze client->resource_xa and client->event_list.
18741878
scoped_guard(spinlock_irq, &client->lock)
18751879
client->in_shutdown = true;
18761880

18771881
wait_event(client->tx_flush_wait, !has_outbound_transactions(client));
18781882

1879-
idr_for_each_entry(&client->resource_idr, resource, id) {
1883+
xa_for_each(&client->resource_xa, index, resource) {
18801884
resource->release(client, resource);
18811885
client_put(client);
18821886
}
1883-
idr_destroy(&client->resource_idr);
1887+
xa_destroy(&client->resource_xa);
18841888

18851889
list_for_each_entry_safe(event, next_event, &client->event_list, link)
18861890
kfree(event);

drivers/firewire/core.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#include <linux/dma-mapping.h>
88
#include <linux/fs.h>
99
#include <linux/list.h>
10-
#include <linux/idr.h>
1110
#include <linux/xarray.h>
1211
#include <linux/mm_types.h>
1312
#include <linux/rwsem.h>

0 commit comments

Comments
 (0)