📄 ucm.c
字号:
} } if (uevent->info) { if (cmd.info_len < uevent->info_len) { result = -ENOMEM; goto done; } if (copy_to_user((void __user *)(unsigned long)cmd.info, uevent->info, uevent->info_len)) { result = -EFAULT; goto done; } } list_del(&uevent->file_list); list_del(&uevent->ctx_list); uevent->ctx->events_reported++; kfree(uevent->data); kfree(uevent->info); kfree(uevent);done: up(&file->mutex); return result;}static ssize_t ib_ucm_create_id(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_ucm_create_id cmd; struct ib_ucm_create_id_resp resp; struct ib_ucm_context *ctx; int result; if (out_len < sizeof(resp)) return -ENOSPC; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; down(&file->mutex); ctx = ib_ucm_ctx_alloc(file); up(&file->mutex); if (!ctx) return -ENOMEM; ctx->uid = cmd.uid; ctx->cm_id = ib_create_cm_id(file->device->ib_dev, ib_ucm_event_handler, ctx); if (IS_ERR(ctx->cm_id)) { result = PTR_ERR(ctx->cm_id); goto err1; } resp.id = ctx->id; if (copy_to_user((void __user *)(unsigned long)cmd.response, &resp, sizeof(resp))) { result = -EFAULT; goto err2; } return 0;err2: ib_destroy_cm_id(ctx->cm_id);err1: down(&ctx_id_mutex); idr_remove(&ctx_id_table, ctx->id); up(&ctx_id_mutex); kfree(ctx); return result;}static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_ucm_destroy_id cmd; struct ib_ucm_destroy_id_resp resp; struct ib_ucm_context *ctx; int result = 0; if (out_len < sizeof(resp)) return -ENOSPC; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; down(&ctx_id_mutex); ctx = idr_find(&ctx_id_table, cmd.id); if (!ctx) ctx = ERR_PTR(-ENOENT); else if (ctx->file != file) ctx = ERR_PTR(-EINVAL); else idr_remove(&ctx_id_table, ctx->id); up(&ctx_id_mutex); if (IS_ERR(ctx)) return PTR_ERR(ctx); atomic_dec(&ctx->ref); wait_event(ctx->wait, !atomic_read(&ctx->ref)); /* No new events will be generated after destroying the cm_id. */ ib_destroy_cm_id(ctx->cm_id); /* Cleanup events not yet reported to the user. */ ib_ucm_cleanup_events(ctx); resp.events_reported = ctx->events_reported; if (copy_to_user((void __user *)(unsigned long)cmd.response, &resp, sizeof(resp))) result = -EFAULT; kfree(ctx); return result;}static ssize_t ib_ucm_attr_id(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_ucm_attr_id_resp resp; struct ib_ucm_attr_id cmd; struct ib_ucm_context *ctx; int result = 0; if (out_len < sizeof(resp)) return -ENOSPC; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; ctx = ib_ucm_ctx_get(file, cmd.id); if (IS_ERR(ctx)) return PTR_ERR(ctx); resp.service_id = ctx->cm_id->service_id; resp.service_mask = ctx->cm_id->service_mask; resp.local_id = ctx->cm_id->local_id; resp.remote_id = ctx->cm_id->remote_id; if (copy_to_user((void __user *)(unsigned long)cmd.response, &resp, sizeof(resp))) result = -EFAULT; ib_ucm_ctx_put(ctx); return result;}static void ib_ucm_copy_ah_attr(struct ib_ucm_ah_attr *dest_attr, struct ib_ah_attr *src_attr){ memcpy(dest_attr->grh_dgid, src_attr->grh.dgid.raw, sizeof src_attr->grh.dgid); dest_attr->grh_flow_label = src_attr->grh.flow_label; dest_attr->grh_sgid_index = src_attr->grh.sgid_index; dest_attr->grh_hop_limit = src_attr->grh.hop_limit; dest_attr->grh_traffic_class = src_attr->grh.traffic_class; dest_attr->dlid = src_attr->dlid; dest_attr->sl = src_attr->sl; dest_attr->src_path_bits = src_attr->src_path_bits; dest_attr->static_rate = src_attr->static_rate; dest_attr->is_global = (src_attr->ah_flags & IB_AH_GRH); dest_attr->port_num = src_attr->port_num;}static void ib_ucm_copy_qp_attr(struct ib_ucm_init_qp_attr_resp *dest_attr, struct ib_qp_attr *src_attr){ dest_attr->cur_qp_state = src_attr->cur_qp_state; dest_attr->path_mtu = src_attr->path_mtu; dest_attr->path_mig_state = src_attr->path_mig_state; dest_attr->qkey = src_attr->qkey; dest_attr->rq_psn = src_attr->rq_psn; dest_attr->sq_psn = src_attr->sq_psn; dest_attr->dest_qp_num = src_attr->dest_qp_num; dest_attr->qp_access_flags = src_attr->qp_access_flags; dest_attr->max_send_wr = src_attr->cap.max_send_wr; dest_attr->max_recv_wr = src_attr->cap.max_recv_wr; dest_attr->max_send_sge = src_attr->cap.max_send_sge; dest_attr->max_recv_sge = src_attr->cap.max_recv_sge; dest_attr->max_inline_data = src_attr->cap.max_inline_data; ib_ucm_copy_ah_attr(&dest_attr->ah_attr, &src_attr->ah_attr); ib_ucm_copy_ah_attr(&dest_attr->alt_ah_attr, &src_attr->alt_ah_attr); dest_attr->pkey_index = src_attr->pkey_index; dest_attr->alt_pkey_index = src_attr->alt_pkey_index; dest_attr->en_sqd_async_notify = src_attr->en_sqd_async_notify; dest_attr->sq_draining = src_attr->sq_draining; dest_attr->max_rd_atomic = src_attr->max_rd_atomic; dest_attr->max_dest_rd_atomic = src_attr->max_dest_rd_atomic; dest_attr->min_rnr_timer = src_attr->min_rnr_timer; dest_attr->port_num = src_attr->port_num; dest_attr->timeout = src_attr->timeout; dest_attr->retry_cnt = src_attr->retry_cnt; dest_attr->rnr_retry = src_attr->rnr_retry; dest_attr->alt_port_num = src_attr->alt_port_num; dest_attr->alt_timeout = src_attr->alt_timeout;}static ssize_t ib_ucm_init_qp_attr(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_ucm_init_qp_attr_resp resp; struct ib_ucm_init_qp_attr cmd; struct ib_ucm_context *ctx; struct ib_qp_attr qp_attr; int result = 0; if (out_len < sizeof(resp)) return -ENOSPC; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; ctx = ib_ucm_ctx_get(file, cmd.id); if (IS_ERR(ctx)) return PTR_ERR(ctx); resp.qp_attr_mask = 0; memset(&qp_attr, 0, sizeof qp_attr); qp_attr.qp_state = cmd.qp_state; result = ib_cm_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask); if (result) goto out; ib_ucm_copy_qp_attr(&resp, &qp_attr); if (copy_to_user((void __user *)(unsigned long)cmd.response, &resp, sizeof(resp))) result = -EFAULT;out: ib_ucm_ctx_put(ctx); return result;}static ssize_t ib_ucm_listen(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_ucm_listen cmd; struct ib_ucm_context *ctx; int result; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; ctx = ib_ucm_ctx_get(file, cmd.id); if (IS_ERR(ctx)) return PTR_ERR(ctx); result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask); ib_ucm_ctx_put(ctx); return result;}static ssize_t ib_ucm_establish(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_ucm_establish cmd; struct ib_ucm_context *ctx; int result; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; ctx = ib_ucm_ctx_get(file, cmd.id); if (IS_ERR(ctx)) return PTR_ERR(ctx); result = ib_cm_establish(ctx->cm_id); ib_ucm_ctx_put(ctx); return result;}static int ib_ucm_alloc_data(const void **dest, u64 src, u32 len){ void *data; *dest = NULL; if (!len) return 0; data = kmalloc(len, GFP_KERNEL); if (!data) return -ENOMEM; if (copy_from_user(data, (void __user *)(unsigned long)src, len)) { kfree(data); return -EFAULT; } *dest = data; return 0;}static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src){ struct ib_ucm_path_rec ucm_path; struct ib_sa_path_rec *sa_path; *path = NULL; if (!src) return 0; sa_path = kmalloc(sizeof(*sa_path), GFP_KERNEL); if (!sa_path) return -ENOMEM; if (copy_from_user(&ucm_path, (void __user *)(unsigned long)src, sizeof(ucm_path))) { kfree(sa_path); return -EFAULT; } memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof sa_path->dgid); memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof sa_path->sgid); sa_path->dlid = ucm_path.dlid; sa_path->slid = ucm_path.slid; sa_path->raw_traffic = ucm_path.raw_traffic; sa_path->flow_label = ucm_path.flow_label; sa_path->hop_limit = ucm_path.hop_limit; sa_path->traffic_class = ucm_path.traffic_class; sa_path->reversible = ucm_path.reversible; sa_path->numb_path = ucm_path.numb_path; sa_path->pkey = ucm_path.pkey; sa_path->sl = ucm_path.sl; sa_path->mtu_selector = ucm_path.mtu_selector; sa_path->mtu = ucm_path.mtu; sa_path->rate_selector = ucm_path.rate_selector; sa_path->rate = ucm_path.rate; sa_path->packet_life_time = ucm_path.packet_life_time; sa_path->preference = ucm_path.preference; sa_path->packet_life_time_selector = ucm_path.packet_life_time_selector; *path = sa_path; return 0;}static ssize_t ib_ucm_send_req(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_cm_req_param param; struct ib_ucm_context *ctx; struct ib_ucm_req cmd; int result; param.private_data = NULL; param.primary_path = NULL; param.alternate_path = NULL; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; result = ib_ucm_alloc_data(¶m.private_data, cmd.data, cmd.len); if (result) goto done; result = ib_ucm_path_get(¶m.primary_path, cmd.primary_path); if (result) goto done; result = ib_ucm_path_get(¶m.alternate_path, cmd.alternate_path); if (result) goto done; param.private_data_len = cmd.len; param.service_id = cmd.sid; param.qp_num = cmd.qpn; param.qp_type = cmd.qp_type; param.starting_psn = cmd.psn; param.peer_to_peer = cmd.peer_to_peer; param.responder_resources = cmd.responder_resources; param.initiator_depth = cmd.initiator_depth; param.remote_cm_response_timeout = cmd.remote_cm_response_timeout; param.flow_control = cmd.flow_control; param.local_cm_response_timeout = cmd.local_cm_response_timeout; param.retry_count = cmd.retry_count; param.rnr_retry_count = cmd.rnr_retry_count; param.max_cm_retries = cmd.max_cm_retries; param.srq = cmd.srq; ctx = ib_ucm_ctx_get(file, cmd.id); if (!IS_ERR(ctx)) { result = ib_send_cm_req(ctx->cm_id, ¶m); ib_ucm_ctx_put(ctx); } else result = PTR_ERR(ctx);done: kfree(param.private_data); kfree(param.primary_path); kfree(param.alternate_path); return result;}static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){ struct ib_cm_rep_param param; struct ib_ucm_context *ctx; struct ib_ucm_rep cmd; int result; param.private_data = NULL; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; result = ib_ucm_alloc_data(¶m.private_data, cmd.data, cmd.len); if (result) return result; param.qp_num = cmd.qpn; param.starting_psn = cmd.psn; param.private_data_len = cmd.len; param.responder_resources = cmd.responder_resources; param.initiator_depth = cmd.initiator_depth; param.target_ack_delay = cmd.target_ack_delay; param.failover_accepted = cmd.failover_accepted; param.flow_control = cmd.flow_control; param.rnr_retry_count = cmd.rnr_retry_count; param.srq = cmd.srq; ctx = ib_ucm_ctx_get(file, cmd.id); if (!IS_ERR(ctx)) { ctx->uid = cmd.uid; result = ib_send_cm_rep(ctx->cm_id, ¶m); ib_ucm_ctx_put(ctx); } else result = PTR_ERR(ctx); kfree(param.private_data); return result;}static ssize_t ib_ucm_send_private_data(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int (*func)(struct ib_cm_id *cm_id, const void *private_data, u8 private_data_len)){ struct ib_ucm_private_data cmd; struct ib_ucm_context *ctx; const void *private_data = NULL; int result; if (copy_from_user(&cmd, inbuf, sizeof(cmd))) return -EFAULT; result = ib_ucm_alloc_data(&private_data, cmd.data, cmd.len); if (result) return result; ctx = ib_ucm_ctx_get(file, cmd.id); if (!IS_ERR(ctx)) { result = func(ctx->cm_id, private_data, cmd.len); ib_ucm_ctx_put(ctx); } else result = PTR_ERR(ctx); kfree(private_data); return result;}static ssize_t ib_ucm_send_rtu(struct ib_ucm_file *file, const char __user *inbuf, int in_len, int out_len){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -