| .. | .. |
|---|
| 100 | 100 | atomic_t refcount; |
|---|
| 101 | 101 | u32 num_comp_vectors; |
|---|
| 102 | 102 | struct completion comp; |
|---|
| 103 | | - struct device *dev; |
|---|
| 103 | + struct device dev; |
|---|
| 104 | + /* First group for device attributes, NULL terminated array */ |
|---|
| 105 | + const struct attribute_group *groups[2]; |
|---|
| 104 | 106 | struct ib_device __rcu *ib_dev; |
|---|
| 105 | 107 | int devnum; |
|---|
| 106 | 108 | struct cdev cdev; |
|---|
| 107 | 109 | struct rb_root xrcd_tree; |
|---|
| 108 | 110 | struct mutex xrcd_tree_mutex; |
|---|
| 109 | | - struct kobject kobj; |
|---|
| 110 | 111 | struct srcu_struct disassociate_srcu; |
|---|
| 111 | 112 | struct mutex lists_mutex; /* protect lists */ |
|---|
| 112 | 113 | struct list_head uverbs_file_list; |
|---|
| 113 | | - struct list_head uverbs_events_file_list; |
|---|
| 114 | 114 | struct uverbs_api *uapi; |
|---|
| 115 | 115 | }; |
|---|
| 116 | 116 | |
|---|
| .. | .. |
|---|
| 123 | 123 | }; |
|---|
| 124 | 124 | |
|---|
| 125 | 125 | struct ib_uverbs_async_event_file { |
|---|
| 126 | + struct ib_uobject uobj; |
|---|
| 126 | 127 | struct ib_uverbs_event_queue ev_queue; |
|---|
| 127 | | - struct ib_uverbs_file *uverbs_file; |
|---|
| 128 | | - struct kref ref; |
|---|
| 129 | | - struct list_head list; |
|---|
| 128 | + struct ib_event_handler event_handler; |
|---|
| 130 | 129 | }; |
|---|
| 131 | 130 | |
|---|
| 132 | 131 | struct ib_uverbs_completion_event_file { |
|---|
| .. | .. |
|---|
| 143 | 142 | * ucontext_lock held |
|---|
| 144 | 143 | */ |
|---|
| 145 | 144 | struct ib_ucontext *ucontext; |
|---|
| 146 | | - struct ib_event_handler event_handler; |
|---|
| 147 | | - struct ib_uverbs_async_event_file *async_file; |
|---|
| 145 | + struct ib_uverbs_async_event_file *default_async_file; |
|---|
| 148 | 146 | struct list_head list; |
|---|
| 149 | | - int is_closed; |
|---|
| 150 | 147 | |
|---|
| 151 | 148 | /* |
|---|
| 152 | 149 | * To access the uobjects list hw_destroy_rwsem must be held for write |
|---|
| .. | .. |
|---|
| 158 | 155 | spinlock_t uobjects_lock; |
|---|
| 159 | 156 | struct list_head uobjects; |
|---|
| 160 | 157 | |
|---|
| 161 | | - u64 uverbs_cmd_mask; |
|---|
| 162 | | - u64 uverbs_ex_cmd_mask; |
|---|
| 158 | + struct mutex umap_lock; |
|---|
| 159 | + struct list_head umaps; |
|---|
| 160 | + struct page *disassociate_page; |
|---|
| 163 | 161 | |
|---|
| 164 | | - struct idr idr; |
|---|
| 165 | | - /* spinlock protects write access to idr */ |
|---|
| 166 | | - spinlock_t idr_lock; |
|---|
| 162 | + struct xarray idr; |
|---|
| 167 | 163 | }; |
|---|
| 168 | 164 | |
|---|
| 169 | 165 | struct ib_uverbs_event { |
|---|
| .. | .. |
|---|
| 184 | 180 | |
|---|
| 185 | 181 | struct ib_uevent_object { |
|---|
| 186 | 182 | struct ib_uobject uobject; |
|---|
| 183 | + struct ib_uverbs_async_event_file *event_file; |
|---|
| 184 | + /* List member for ib_uverbs_async_event_file list */ |
|---|
| 187 | 185 | struct list_head event_list; |
|---|
| 188 | 186 | u32 events_reported; |
|---|
| 189 | 187 | }; |
|---|
| .. | .. |
|---|
| 211 | 209 | }; |
|---|
| 212 | 210 | |
|---|
| 213 | 211 | struct ib_ucq_object { |
|---|
| 214 | | - struct ib_uobject uobject; |
|---|
| 212 | + struct ib_uevent_object uevent; |
|---|
| 215 | 213 | struct list_head comp_list; |
|---|
| 216 | | - struct list_head async_list; |
|---|
| 217 | 214 | u32 comp_events_reported; |
|---|
| 218 | | - u32 async_events_reported; |
|---|
| 219 | | -}; |
|---|
| 220 | | - |
|---|
| 221 | | -struct ib_uflow_resources; |
|---|
| 222 | | -struct ib_uflow_object { |
|---|
| 223 | | - struct ib_uobject uobject; |
|---|
| 224 | | - struct ib_uflow_resources *resources; |
|---|
| 225 | 215 | }; |
|---|
| 226 | 216 | |
|---|
| 227 | 217 | extern const struct file_operations uverbs_event_fops; |
|---|
| 218 | +extern const struct file_operations uverbs_async_event_fops; |
|---|
| 228 | 219 | void ib_uverbs_init_event_queue(struct ib_uverbs_event_queue *ev_queue); |
|---|
| 229 | | -struct file *ib_uverbs_alloc_async_event_file(struct ib_uverbs_file *uverbs_file, |
|---|
| 230 | | - struct ib_device *ib_dev); |
|---|
| 231 | | -void ib_uverbs_free_async_event_file(struct ib_uverbs_file *uverbs_file); |
|---|
| 220 | +void ib_uverbs_init_async_event_file(struct ib_uverbs_async_event_file *ev_file); |
|---|
| 221 | +void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue); |
|---|
| 232 | 222 | void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res); |
|---|
| 223 | +int uverbs_async_event_release(struct inode *inode, struct file *filp); |
|---|
| 233 | 224 | |
|---|
| 234 | | -void ib_uverbs_release_ucq(struct ib_uverbs_file *file, |
|---|
| 235 | | - struct ib_uverbs_completion_event_file *ev_file, |
|---|
| 225 | +int ib_alloc_ucontext(struct uverbs_attr_bundle *attrs); |
|---|
| 226 | +int ib_init_ucontext(struct uverbs_attr_bundle *attrs); |
|---|
| 227 | + |
|---|
| 228 | +void ib_uverbs_release_ucq(struct ib_uverbs_completion_event_file *ev_file, |
|---|
| 236 | 229 | struct ib_ucq_object *uobj); |
|---|
| 237 | | -void ib_uverbs_release_uevent(struct ib_uverbs_file *file, |
|---|
| 238 | | - struct ib_uevent_object *uobj); |
|---|
| 230 | +void ib_uverbs_release_uevent(struct ib_uevent_object *uobj); |
|---|
| 239 | 231 | void ib_uverbs_release_file(struct kref *ref); |
|---|
| 232 | +void ib_uverbs_async_handler(struct ib_uverbs_async_event_file *async_file, |
|---|
| 233 | + __u64 element, __u64 event, |
|---|
| 234 | + struct list_head *obj_list, u32 *counter); |
|---|
| 240 | 235 | |
|---|
| 241 | 236 | void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context); |
|---|
| 242 | 237 | void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr); |
|---|
| 243 | 238 | void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr); |
|---|
| 244 | 239 | void ib_uverbs_wq_event_handler(struct ib_event *event, void *context_ptr); |
|---|
| 245 | 240 | void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr); |
|---|
| 246 | | -void ib_uverbs_event_handler(struct ib_event_handler *handler, |
|---|
| 247 | | - struct ib_event *event); |
|---|
| 248 | 241 | int ib_uverbs_dealloc_xrcd(struct ib_uobject *uobject, struct ib_xrcd *xrcd, |
|---|
| 249 | | - enum rdma_remove_reason why); |
|---|
| 242 | + enum rdma_remove_reason why, |
|---|
| 243 | + struct uverbs_attr_bundle *attrs); |
|---|
| 250 | 244 | |
|---|
| 251 | 245 | int uverbs_dealloc_mw(struct ib_mw *mw); |
|---|
| 252 | 246 | void ib_uverbs_detach_umcast(struct ib_qp *qp, |
|---|
| 253 | 247 | struct ib_uqp_object *uobj); |
|---|
| 254 | 248 | |
|---|
| 255 | | -void create_udata(struct uverbs_attr_bundle *ctx, struct ib_udata *udata); |
|---|
| 256 | 249 | long ib_uverbs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); |
|---|
| 257 | 250 | |
|---|
| 258 | 251 | struct ib_uverbs_flow_spec { |
|---|
| .. | .. |
|---|
| 283 | 276 | size_t kern_filter_sz, |
|---|
| 284 | 277 | union ib_flow_spec *ib_spec); |
|---|
| 285 | 278 | |
|---|
| 286 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_DEVICE); |
|---|
| 287 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_PD); |
|---|
| 288 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_MR); |
|---|
| 289 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_COMP_CHANNEL); |
|---|
| 290 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_CQ); |
|---|
| 291 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_QP); |
|---|
| 292 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_AH); |
|---|
| 293 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_MW); |
|---|
| 294 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_SRQ); |
|---|
| 295 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_FLOW); |
|---|
| 296 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_WQ); |
|---|
| 297 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_RWQ_IND_TBL); |
|---|
| 298 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_XRCD); |
|---|
| 299 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_FLOW_ACTION); |
|---|
| 300 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_DM); |
|---|
| 301 | | -extern const struct uverbs_object_def UVERBS_OBJECT(UVERBS_OBJECT_COUNTERS); |
|---|
| 279 | +/* |
|---|
| 280 | + * ib_uverbs_query_port_resp.port_cap_flags started out as just a copy of the |
|---|
| 281 | + * PortInfo CapabilityMask, but was extended with unique bits. |
|---|
| 282 | + */ |
|---|
| 283 | +static inline u32 make_port_cap_flags(const struct ib_port_attr *attr) |
|---|
| 284 | +{ |
|---|
| 285 | + u32 res; |
|---|
| 302 | 286 | |
|---|
| 303 | | -#define IB_UVERBS_DECLARE_CMD(name) \ |
|---|
| 304 | | - ssize_t ib_uverbs_##name(struct ib_uverbs_file *file, \ |
|---|
| 305 | | - const char __user *buf, int in_len, \ |
|---|
| 306 | | - int out_len) |
|---|
| 287 | + /* All IBA CapabilityMask bits are passed through here, except bit 26, |
|---|
| 288 | + * which is overridden with IP_BASED_GIDS. This is due to a historical |
|---|
| 289 | + * mistake in the implementation of IP_BASED_GIDS. Otherwise all other |
|---|
| 290 | + * bits match the IBA definition across all kernel versions. |
|---|
| 291 | + */ |
|---|
| 292 | + res = attr->port_cap_flags & ~(u32)IB_UVERBS_PCF_IP_BASED_GIDS; |
|---|
| 307 | 293 | |
|---|
| 308 | | -IB_UVERBS_DECLARE_CMD(get_context); |
|---|
| 309 | | -IB_UVERBS_DECLARE_CMD(query_device); |
|---|
| 310 | | -IB_UVERBS_DECLARE_CMD(query_port); |
|---|
| 311 | | -IB_UVERBS_DECLARE_CMD(alloc_pd); |
|---|
| 312 | | -IB_UVERBS_DECLARE_CMD(dealloc_pd); |
|---|
| 313 | | -IB_UVERBS_DECLARE_CMD(reg_mr); |
|---|
| 314 | | -IB_UVERBS_DECLARE_CMD(rereg_mr); |
|---|
| 315 | | -IB_UVERBS_DECLARE_CMD(dereg_mr); |
|---|
| 316 | | -IB_UVERBS_DECLARE_CMD(alloc_mw); |
|---|
| 317 | | -IB_UVERBS_DECLARE_CMD(dealloc_mw); |
|---|
| 318 | | -IB_UVERBS_DECLARE_CMD(create_comp_channel); |
|---|
| 319 | | -IB_UVERBS_DECLARE_CMD(create_cq); |
|---|
| 320 | | -IB_UVERBS_DECLARE_CMD(resize_cq); |
|---|
| 321 | | -IB_UVERBS_DECLARE_CMD(poll_cq); |
|---|
| 322 | | -IB_UVERBS_DECLARE_CMD(req_notify_cq); |
|---|
| 323 | | -IB_UVERBS_DECLARE_CMD(destroy_cq); |
|---|
| 324 | | -IB_UVERBS_DECLARE_CMD(create_qp); |
|---|
| 325 | | -IB_UVERBS_DECLARE_CMD(open_qp); |
|---|
| 326 | | -IB_UVERBS_DECLARE_CMD(query_qp); |
|---|
| 327 | | -IB_UVERBS_DECLARE_CMD(modify_qp); |
|---|
| 328 | | -IB_UVERBS_DECLARE_CMD(destroy_qp); |
|---|
| 329 | | -IB_UVERBS_DECLARE_CMD(post_send); |
|---|
| 330 | | -IB_UVERBS_DECLARE_CMD(post_recv); |
|---|
| 331 | | -IB_UVERBS_DECLARE_CMD(post_srq_recv); |
|---|
| 332 | | -IB_UVERBS_DECLARE_CMD(create_ah); |
|---|
| 333 | | -IB_UVERBS_DECLARE_CMD(destroy_ah); |
|---|
| 334 | | -IB_UVERBS_DECLARE_CMD(attach_mcast); |
|---|
| 335 | | -IB_UVERBS_DECLARE_CMD(detach_mcast); |
|---|
| 336 | | -IB_UVERBS_DECLARE_CMD(create_srq); |
|---|
| 337 | | -IB_UVERBS_DECLARE_CMD(modify_srq); |
|---|
| 338 | | -IB_UVERBS_DECLARE_CMD(query_srq); |
|---|
| 339 | | -IB_UVERBS_DECLARE_CMD(destroy_srq); |
|---|
| 340 | | -IB_UVERBS_DECLARE_CMD(create_xsrq); |
|---|
| 341 | | -IB_UVERBS_DECLARE_CMD(open_xrcd); |
|---|
| 342 | | -IB_UVERBS_DECLARE_CMD(close_xrcd); |
|---|
| 294 | + if (attr->ip_gids) |
|---|
| 295 | + res |= IB_UVERBS_PCF_IP_BASED_GIDS; |
|---|
| 343 | 296 | |
|---|
| 344 | | -#define IB_UVERBS_DECLARE_EX_CMD(name) \ |
|---|
| 345 | | - int ib_uverbs_ex_##name(struct ib_uverbs_file *file, \ |
|---|
| 346 | | - struct ib_udata *ucore, \ |
|---|
| 347 | | - struct ib_udata *uhw) |
|---|
| 297 | + return res; |
|---|
| 298 | +} |
|---|
| 348 | 299 | |
|---|
| 349 | | -IB_UVERBS_DECLARE_EX_CMD(create_flow); |
|---|
| 350 | | -IB_UVERBS_DECLARE_EX_CMD(destroy_flow); |
|---|
| 351 | | -IB_UVERBS_DECLARE_EX_CMD(query_device); |
|---|
| 352 | | -IB_UVERBS_DECLARE_EX_CMD(create_cq); |
|---|
| 353 | | -IB_UVERBS_DECLARE_EX_CMD(create_qp); |
|---|
| 354 | | -IB_UVERBS_DECLARE_EX_CMD(create_wq); |
|---|
| 355 | | -IB_UVERBS_DECLARE_EX_CMD(modify_wq); |
|---|
| 356 | | -IB_UVERBS_DECLARE_EX_CMD(destroy_wq); |
|---|
| 357 | | -IB_UVERBS_DECLARE_EX_CMD(create_rwq_ind_table); |
|---|
| 358 | | -IB_UVERBS_DECLARE_EX_CMD(destroy_rwq_ind_table); |
|---|
| 359 | | -IB_UVERBS_DECLARE_EX_CMD(modify_qp); |
|---|
| 360 | | -IB_UVERBS_DECLARE_EX_CMD(modify_cq); |
|---|
| 300 | +static inline struct ib_uverbs_async_event_file * |
|---|
| 301 | +ib_uverbs_get_async_event(struct uverbs_attr_bundle *attrs, |
|---|
| 302 | + u16 id) |
|---|
| 303 | +{ |
|---|
| 304 | + struct ib_uobject *async_ev_file_uobj; |
|---|
| 305 | + struct ib_uverbs_async_event_file *async_ev_file; |
|---|
| 361 | 306 | |
|---|
| 307 | + async_ev_file_uobj = uverbs_attr_get_uobject(attrs, id); |
|---|
| 308 | + if (IS_ERR(async_ev_file_uobj)) |
|---|
| 309 | + async_ev_file = READ_ONCE(attrs->ufile->default_async_file); |
|---|
| 310 | + else |
|---|
| 311 | + async_ev_file = container_of(async_ev_file_uobj, |
|---|
| 312 | + struct ib_uverbs_async_event_file, |
|---|
| 313 | + uobj); |
|---|
| 314 | + if (async_ev_file) |
|---|
| 315 | + uverbs_uobject_get(&async_ev_file->uobj); |
|---|
| 316 | + return async_ev_file; |
|---|
| 317 | +} |
|---|
| 318 | + |
|---|
| 319 | +void copy_port_attr_to_resp(struct ib_port_attr *attr, |
|---|
| 320 | + struct ib_uverbs_query_port_resp *resp, |
|---|
| 321 | + struct ib_device *ib_dev, u8 port_num); |
|---|
| 362 | 322 | #endif /* UVERBS_H */ |
|---|