~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/sunrpc/xprtrdma/ib_client.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  2 /*
  3  * Copyright (c) 2024 Oracle.  All rights reserved.
  4  */
  5 
  6 /* #include <linux/module.h>
  7 #include <linux/slab.h> */
  8 #include <linux/xarray.h>
  9 #include <linux/types.h>
 10 #include <linux/kref.h>
 11 #include <linux/completion.h>
 12 
 13 #include <linux/sunrpc/svc_rdma.h>
 14 #include <linux/sunrpc/rdma_rn.h>
 15 
 16 #include "xprt_rdma.h"
 17 #include <trace/events/rpcrdma.h>
 18 
 19 /* Per-ib_device private data for rpcrdma */
 20 struct rpcrdma_device {
 21         struct kref             rd_kref;
 22         unsigned long           rd_flags;
 23         struct ib_device        *rd_device;
 24         struct xarray           rd_xa;
 25         struct completion       rd_done;
 26 };
 27 
 28 #define RPCRDMA_RD_F_REMOVING   (0)
 29 
 30 static struct ib_client rpcrdma_ib_client;
 31 
 32 /*
 33  * Listeners have no associated device, so we never register them.
 34  * Note that ib_get_client_data() does not check if @device is
 35  * NULL for us.
 36  */
 37 static struct rpcrdma_device *rpcrdma_get_client_data(struct ib_device *device)
 38 {
 39         if (!device)
 40                 return NULL;
 41         return ib_get_client_data(device, &rpcrdma_ib_client);
 42 }
 43 
 44 /**
 45  * rpcrdma_rn_register - register to get device removal notifications
 46  * @device: device to monitor
 47  * @rn: notification object that wishes to be notified
 48  * @done: callback to notify caller of device removal
 49  *
 50  * Returns zero on success. The callback in rn_done is guaranteed
 51  * to be invoked when the device is removed, unless this notification
 52  * is unregistered first.
 53  *
 54  * On failure, a negative errno is returned.
 55  */
 56 int rpcrdma_rn_register(struct ib_device *device,
 57                         struct rpcrdma_notification *rn,
 58                         void (*done)(struct rpcrdma_notification *rn))
 59 {
 60         struct rpcrdma_device *rd = rpcrdma_get_client_data(device);
 61 
 62         if (!rd || test_bit(RPCRDMA_RD_F_REMOVING, &rd->rd_flags))
 63                 return -ENETUNREACH;
 64 
 65         kref_get(&rd->rd_kref);
 66         if (xa_alloc(&rd->rd_xa, &rn->rn_index, rn, xa_limit_32b, GFP_KERNEL) < 0)
 67                 return -ENOMEM;
 68         rn->rn_done = done;
 69         return 0;
 70 }
 71 
 72 static void rpcrdma_rn_release(struct kref *kref)
 73 {
 74         struct rpcrdma_device *rd = container_of(kref, struct rpcrdma_device,
 75                                                  rd_kref);
 76 
 77         trace_rpcrdma_client_completion(rd->rd_device);
 78         complete(&rd->rd_done);
 79 }
 80 
 81 /**
 82  * rpcrdma_rn_unregister - stop device removal notifications
 83  * @device: monitored device
 84  * @rn: notification object that no longer wishes to be notified
 85  */
 86 void rpcrdma_rn_unregister(struct ib_device *device,
 87                            struct rpcrdma_notification *rn)
 88 {
 89         struct rpcrdma_device *rd = rpcrdma_get_client_data(device);
 90 
 91         if (!rd)
 92                 return;
 93 
 94         xa_erase(&rd->rd_xa, rn->rn_index);
 95         kref_put(&rd->rd_kref, rpcrdma_rn_release);
 96 }
 97 
 98 /**
 99  * rpcrdma_add_one - ib_client device insertion callback
100  * @device: device about to be inserted
101  *
102  * Returns zero on success. xprtrdma private data has been allocated
103  * for this device. On failure, a negative errno is returned.
104  */
105 static int rpcrdma_add_one(struct ib_device *device)
106 {
107         struct rpcrdma_device *rd;
108 
109         rd = kzalloc(sizeof(*rd), GFP_KERNEL);
110         if (!rd)
111                 return -ENOMEM;
112 
113         kref_init(&rd->rd_kref);
114         xa_init_flags(&rd->rd_xa, XA_FLAGS_ALLOC1);
115         rd->rd_device = device;
116         init_completion(&rd->rd_done);
117         ib_set_client_data(device, &rpcrdma_ib_client, rd);
118 
119         trace_rpcrdma_client_add_one(device);
120         return 0;
121 }
122 
123 /**
124  * rpcrdma_remove_one - ib_client device removal callback
125  * @device: device about to be removed
126  * @client_data: this module's private per-device data
127  *
128  * Upon return, all transports associated with @device have divested
129  * themselves from IB hardware resources.
130  */
131 static void rpcrdma_remove_one(struct ib_device *device,
132                                void *client_data)
133 {
134         struct rpcrdma_device *rd = client_data;
135         struct rpcrdma_notification *rn;
136         unsigned long index;
137 
138         trace_rpcrdma_client_remove_one(device);
139 
140         set_bit(RPCRDMA_RD_F_REMOVING, &rd->rd_flags);
141         xa_for_each(&rd->rd_xa, index, rn)
142                 rn->rn_done(rn);
143 
144         /*
145          * Wait only if there are still outstanding notification
146          * registrants for this device.
147          */
148         if (!refcount_dec_and_test(&rd->rd_kref.refcount)) {
149                 trace_rpcrdma_client_wait_on(device);
150                 wait_for_completion(&rd->rd_done);
151         }
152 
153         trace_rpcrdma_client_remove_one_done(device);
154         kfree(rd);
155 }
156 
157 static struct ib_client rpcrdma_ib_client = {
158         .name           = "rpcrdma",
159         .add            = rpcrdma_add_one,
160         .remove         = rpcrdma_remove_one,
161 };
162 
163 /**
164  * rpcrdma_ib_client_unregister - unregister ib_client for xprtrdma
165  *
166  * cel: watch for orphaned rpcrdma_device objects on module unload
167  */
168 void rpcrdma_ib_client_unregister(void)
169 {
170         ib_unregister_client(&rpcrdma_ib_client);
171 }
172 
173 /**
174  * rpcrdma_ib_client_register - register ib_client for rpcrdma
175  *
176  * Returns zero on success, or a negative errno.
177  */
178 int rpcrdma_ib_client_register(void)
179 {
180         return ib_register_client(&rpcrdma_ib_client);
181 }
182 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php