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
532533static 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)
18391843static 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 );
0 commit comments