Loading drivers/infiniband/core/user_mad.c +76 −53 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * $Id: user_mad.c 2814 2005-07-06 19:14:09Z halr $ * $Id: user_mad.c 4010 2005-11-09 23:11:56Z roland $ */ #include <linux/module.h> Loading Loading @@ -116,7 +116,7 @@ struct ib_umad_file { spinlock_t recv_lock; wait_queue_head_t recv_wait; struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS]; struct ib_mr *mr[IB_UMAD_MAX_AGENTS]; int agents_dead; }; struct ib_umad_packet { Loading Loading @@ -145,6 +145,12 @@ static void ib_umad_release_dev(struct kref *ref) kfree(dev); } /* caller must hold port->mutex at least for reading */ static struct ib_mad_agent *__get_agent(struct ib_umad_file *file, int id) { return file->agents_dead ? NULL : file->agent[id]; } static int queue_packet(struct ib_umad_file *file, struct ib_mad_agent *agent, struct ib_umad_packet *packet) Loading @@ -152,10 +158,11 @@ static int queue_packet(struct ib_umad_file *file, int ret = 1; down_read(&file->port->mutex); for (packet->mad.hdr.id = 0; packet->mad.hdr.id < IB_UMAD_MAX_AGENTS; packet->mad.hdr.id++) if (agent == file->agent[packet->mad.hdr.id]) { if (agent == __get_agent(file, packet->mad.hdr.id)) { spin_lock_irq(&file->recv_lock); list_add_tail(&packet->list, &file->recv_list); spin_unlock_irq(&file->recv_lock); Loading Loading @@ -327,7 +334,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, down_read(&file->port->mutex); agent = file->agent[packet->mad.hdr.id]; agent = __get_agent(file, packet->mad.hdr.id); if (!agent) { ret = -EINVAL; goto err_up; Loading Loading @@ -481,7 +488,7 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg) } for (agent_id = 0; agent_id < IB_UMAD_MAX_AGENTS; ++agent_id) if (!file->agent[agent_id]) if (!__get_agent(file, agent_id)) goto found; ret = -ENOMEM; Loading @@ -505,29 +512,15 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg) goto out; } file->agent[agent_id] = agent; file->mr[agent_id] = ib_get_dma_mr(agent->qp->pd, IB_ACCESS_LOCAL_WRITE); if (IS_ERR(file->mr[agent_id])) { ret = -ENOMEM; goto err; } if (put_user(agent_id, (u32 __user *) (arg + offsetof(struct ib_user_mad_reg_req, id)))) { ret = -EFAULT; goto err_mr; ib_unregister_mad_agent(agent); goto out; } file->agent[agent_id] = agent; ret = 0; goto out; err_mr: ib_dereg_mr(file->mr[agent_id]); err: file->agent[agent_id] = NULL; ib_unregister_mad_agent(agent); out: up_write(&file->port->mutex); Loading @@ -536,27 +529,29 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg) static int ib_umad_unreg_agent(struct ib_umad_file *file, unsigned long arg) { struct ib_mad_agent *agent = NULL; u32 id; int ret = 0; down_write(&file->port->mutex); if (get_user(id, (u32 __user *) arg)) return -EFAULT; if (get_user(id, (u32 __user *) arg)) { ret = -EFAULT; goto out; } down_write(&file->port->mutex); if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !file->agent[id]) { if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) { ret = -EINVAL; goto out; } ib_dereg_mr(file->mr[id]); ib_unregister_mad_agent(file->agent[id]); agent = file->agent[id]; file->agent[id] = NULL; out: up_write(&file->port->mutex); if (agent) ib_unregister_mad_agent(agent); return ret; } Loading Loading @@ -621,23 +616,29 @@ static int ib_umad_close(struct inode *inode, struct file *filp) struct ib_umad_file *file = filp->private_data; struct ib_umad_device *dev = file->port->umad_dev; struct ib_umad_packet *packet, *tmp; int already_dead; int i; down_write(&file->port->mutex); for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i) if (file->agent[i]) { ib_dereg_mr(file->mr[i]); ib_unregister_mad_agent(file->agent[i]); } already_dead = file->agents_dead; file->agents_dead = 1; list_for_each_entry_safe(packet, tmp, &file->recv_list, list) kfree(packet); list_del(&file->port_list); up_write(&file->port->mutex); kfree(file); downgrade_write(&file->port->mutex); if (!already_dead) for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i) if (file->agent[i]) ib_unregister_mad_agent(file->agent[i]); up_read(&file->port->mutex); kfree(file); kref_put(&dev->ref, ib_umad_release_dev); return 0; Loading Loading @@ -801,7 +802,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num, goto err_class; port->sm_dev->owner = THIS_MODULE; port->sm_dev->ops = &umad_sm_fops; kobject_set_name(&port->dev->kobj, "issm%d", port->dev_num); kobject_set_name(&port->sm_dev->kobj, "issm%d", port->dev_num); if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1)) goto err_sm_cdev; Loading Loading @@ -863,13 +864,35 @@ static void ib_umad_kill_port(struct ib_umad_port *port) port->ib_dev = NULL; list_for_each_entry(file, &port->file_list, port_list) for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id) { if (!file->agent[id]) continue; ib_dereg_mr(file->mr[id]); /* * Now go through the list of files attached to this port and * unregister all of their MAD agents. We need to hold * port->mutex while doing this to avoid racing with * ib_umad_close(), but we can't hold the mutex for writing * while calling ib_unregister_mad_agent(), since that might * deadlock by calling back into queue_packet(). So we * downgrade our lock to a read lock, and then drop and * reacquire the write lock for the next iteration. * * We do list_del_init() on the file's list_head so that the * list_del in ib_umad_close() is still OK, even after the * file is removed from the list. */ while (!list_empty(&port->file_list)) { file = list_entry(port->file_list.next, struct ib_umad_file, port_list); file->agents_dead = 1; list_del_init(&file->port_list); downgrade_write(&port->mutex); for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id) if (file->agent[id]) ib_unregister_mad_agent(file->agent[id]); file->agent[id] = NULL; up_read(&port->mutex); down_write(&port->mutex); } up_write(&port->mutex); Loading Loading @@ -913,7 +936,7 @@ static void ib_umad_add_one(struct ib_device *device) err: while (--i >= s) ib_umad_kill_port(&umad_dev->port[i]); ib_umad_kill_port(&umad_dev->port[i - s]); kref_put(&umad_dev->ref, ib_umad_release_dev); } Loading drivers/infiniband/core/uverbs_cmd.c +8 −4 Original line number Diff line number Diff line Loading @@ -708,7 +708,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, resp->wc[i].opcode = wc[i].opcode; resp->wc[i].vendor_err = wc[i].vendor_err; resp->wc[i].byte_len = wc[i].byte_len; resp->wc[i].imm_data = wc[i].imm_data; resp->wc[i].imm_data = (__u32 __force) wc[i].imm_data; resp->wc[i].qp_num = wc[i].qp_num; resp->wc[i].src_qp = wc[i].src_qp; resp->wc[i].wc_flags = wc[i].wc_flags; Loading Loading @@ -909,6 +909,11 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, goto err_destroy; resp.qp_handle = uobj->uobject.id; resp.max_recv_sge = attr.cap.max_recv_sge; resp.max_send_sge = attr.cap.max_send_sge; resp.max_recv_wr = attr.cap.max_recv_wr; resp.max_send_wr = attr.cap.max_send_wr; resp.max_inline_data = attr.cap.max_inline_data; if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { Loading Loading @@ -1135,7 +1140,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, next->num_sge = user_wr->num_sge; next->opcode = user_wr->opcode; next->send_flags = user_wr->send_flags; next->imm_data = user_wr->imm_data; next->imm_data = (__be32 __force) user_wr->imm_data; if (qp->qp_type == IB_QPT_UD) { next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr, Loading Loading @@ -1701,7 +1706,6 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, } attr.max_wr = cmd.max_wr; attr.max_sge = cmd.max_sge; attr.srq_limit = cmd.srq_limit; ret = ib_modify_srq(srq, &attr, cmd.attr_mask); Loading drivers/infiniband/core/verbs.c +2 −10 Original line number Diff line number Diff line Loading @@ -325,16 +325,8 @@ EXPORT_SYMBOL(ib_destroy_cq); int ib_resize_cq(struct ib_cq *cq, int cqe) { int ret; if (!cq->device->resize_cq) return -ENOSYS; ret = cq->device->resize_cq(cq, &cqe); if (!ret) cq->cqe = cqe; return ret; return cq->device->resize_cq ? cq->device->resize_cq(cq, cqe) : -ENOSYS; } EXPORT_SYMBOL(ib_resize_cq); Loading drivers/infiniband/hw/mthca/mthca_catas.c +1 −1 Original line number Diff line number Diff line Loading @@ -97,7 +97,7 @@ static void poll_catas(unsigned long dev_ptr) } spin_lock_irqsave(&catas_lock, flags); if (dev->catas_err.stop) if (!dev->catas_err.stop) mod_timer(&dev->catas_err.timer, jiffies + MTHCA_CATAS_POLL_INTERVAL); spin_unlock_irqrestore(&catas_lock, flags); Loading drivers/infiniband/hw/mthca/mthca_cmd.c +2 −0 Original line number Diff line number Diff line Loading @@ -1060,6 +1060,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, dev_lim->hca.arbel.resize_srq = field & 1; MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET); dev_lim->max_sg = min_t(int, field, dev_lim->max_sg); MTHCA_GET(size, outbox, QUERY_DEV_LIM_MAX_DESC_SZ_RQ_OFFSET); dev_lim->max_desc_sz = min_t(int, size, dev_lim->max_desc_sz); MTHCA_GET(size, outbox, QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET); dev_lim->mpt_entry_sz = size; MTHCA_GET(field, outbox, QUERY_DEV_LIM_PBL_SZ_OFFSET); Loading Loading
drivers/infiniband/core/user_mad.c +76 −53 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * $Id: user_mad.c 2814 2005-07-06 19:14:09Z halr $ * $Id: user_mad.c 4010 2005-11-09 23:11:56Z roland $ */ #include <linux/module.h> Loading Loading @@ -116,7 +116,7 @@ struct ib_umad_file { spinlock_t recv_lock; wait_queue_head_t recv_wait; struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS]; struct ib_mr *mr[IB_UMAD_MAX_AGENTS]; int agents_dead; }; struct ib_umad_packet { Loading Loading @@ -145,6 +145,12 @@ static void ib_umad_release_dev(struct kref *ref) kfree(dev); } /* caller must hold port->mutex at least for reading */ static struct ib_mad_agent *__get_agent(struct ib_umad_file *file, int id) { return file->agents_dead ? NULL : file->agent[id]; } static int queue_packet(struct ib_umad_file *file, struct ib_mad_agent *agent, struct ib_umad_packet *packet) Loading @@ -152,10 +158,11 @@ static int queue_packet(struct ib_umad_file *file, int ret = 1; down_read(&file->port->mutex); for (packet->mad.hdr.id = 0; packet->mad.hdr.id < IB_UMAD_MAX_AGENTS; packet->mad.hdr.id++) if (agent == file->agent[packet->mad.hdr.id]) { if (agent == __get_agent(file, packet->mad.hdr.id)) { spin_lock_irq(&file->recv_lock); list_add_tail(&packet->list, &file->recv_list); spin_unlock_irq(&file->recv_lock); Loading Loading @@ -327,7 +334,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, down_read(&file->port->mutex); agent = file->agent[packet->mad.hdr.id]; agent = __get_agent(file, packet->mad.hdr.id); if (!agent) { ret = -EINVAL; goto err_up; Loading Loading @@ -481,7 +488,7 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg) } for (agent_id = 0; agent_id < IB_UMAD_MAX_AGENTS; ++agent_id) if (!file->agent[agent_id]) if (!__get_agent(file, agent_id)) goto found; ret = -ENOMEM; Loading @@ -505,29 +512,15 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg) goto out; } file->agent[agent_id] = agent; file->mr[agent_id] = ib_get_dma_mr(agent->qp->pd, IB_ACCESS_LOCAL_WRITE); if (IS_ERR(file->mr[agent_id])) { ret = -ENOMEM; goto err; } if (put_user(agent_id, (u32 __user *) (arg + offsetof(struct ib_user_mad_reg_req, id)))) { ret = -EFAULT; goto err_mr; ib_unregister_mad_agent(agent); goto out; } file->agent[agent_id] = agent; ret = 0; goto out; err_mr: ib_dereg_mr(file->mr[agent_id]); err: file->agent[agent_id] = NULL; ib_unregister_mad_agent(agent); out: up_write(&file->port->mutex); Loading @@ -536,27 +529,29 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg) static int ib_umad_unreg_agent(struct ib_umad_file *file, unsigned long arg) { struct ib_mad_agent *agent = NULL; u32 id; int ret = 0; down_write(&file->port->mutex); if (get_user(id, (u32 __user *) arg)) return -EFAULT; if (get_user(id, (u32 __user *) arg)) { ret = -EFAULT; goto out; } down_write(&file->port->mutex); if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !file->agent[id]) { if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) { ret = -EINVAL; goto out; } ib_dereg_mr(file->mr[id]); ib_unregister_mad_agent(file->agent[id]); agent = file->agent[id]; file->agent[id] = NULL; out: up_write(&file->port->mutex); if (agent) ib_unregister_mad_agent(agent); return ret; } Loading Loading @@ -621,23 +616,29 @@ static int ib_umad_close(struct inode *inode, struct file *filp) struct ib_umad_file *file = filp->private_data; struct ib_umad_device *dev = file->port->umad_dev; struct ib_umad_packet *packet, *tmp; int already_dead; int i; down_write(&file->port->mutex); for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i) if (file->agent[i]) { ib_dereg_mr(file->mr[i]); ib_unregister_mad_agent(file->agent[i]); } already_dead = file->agents_dead; file->agents_dead = 1; list_for_each_entry_safe(packet, tmp, &file->recv_list, list) kfree(packet); list_del(&file->port_list); up_write(&file->port->mutex); kfree(file); downgrade_write(&file->port->mutex); if (!already_dead) for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i) if (file->agent[i]) ib_unregister_mad_agent(file->agent[i]); up_read(&file->port->mutex); kfree(file); kref_put(&dev->ref, ib_umad_release_dev); return 0; Loading Loading @@ -801,7 +802,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num, goto err_class; port->sm_dev->owner = THIS_MODULE; port->sm_dev->ops = &umad_sm_fops; kobject_set_name(&port->dev->kobj, "issm%d", port->dev_num); kobject_set_name(&port->sm_dev->kobj, "issm%d", port->dev_num); if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1)) goto err_sm_cdev; Loading Loading @@ -863,13 +864,35 @@ static void ib_umad_kill_port(struct ib_umad_port *port) port->ib_dev = NULL; list_for_each_entry(file, &port->file_list, port_list) for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id) { if (!file->agent[id]) continue; ib_dereg_mr(file->mr[id]); /* * Now go through the list of files attached to this port and * unregister all of their MAD agents. We need to hold * port->mutex while doing this to avoid racing with * ib_umad_close(), but we can't hold the mutex for writing * while calling ib_unregister_mad_agent(), since that might * deadlock by calling back into queue_packet(). So we * downgrade our lock to a read lock, and then drop and * reacquire the write lock for the next iteration. * * We do list_del_init() on the file's list_head so that the * list_del in ib_umad_close() is still OK, even after the * file is removed from the list. */ while (!list_empty(&port->file_list)) { file = list_entry(port->file_list.next, struct ib_umad_file, port_list); file->agents_dead = 1; list_del_init(&file->port_list); downgrade_write(&port->mutex); for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id) if (file->agent[id]) ib_unregister_mad_agent(file->agent[id]); file->agent[id] = NULL; up_read(&port->mutex); down_write(&port->mutex); } up_write(&port->mutex); Loading Loading @@ -913,7 +936,7 @@ static void ib_umad_add_one(struct ib_device *device) err: while (--i >= s) ib_umad_kill_port(&umad_dev->port[i]); ib_umad_kill_port(&umad_dev->port[i - s]); kref_put(&umad_dev->ref, ib_umad_release_dev); } Loading
drivers/infiniband/core/uverbs_cmd.c +8 −4 Original line number Diff line number Diff line Loading @@ -708,7 +708,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, resp->wc[i].opcode = wc[i].opcode; resp->wc[i].vendor_err = wc[i].vendor_err; resp->wc[i].byte_len = wc[i].byte_len; resp->wc[i].imm_data = wc[i].imm_data; resp->wc[i].imm_data = (__u32 __force) wc[i].imm_data; resp->wc[i].qp_num = wc[i].qp_num; resp->wc[i].src_qp = wc[i].src_qp; resp->wc[i].wc_flags = wc[i].wc_flags; Loading Loading @@ -909,6 +909,11 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, goto err_destroy; resp.qp_handle = uobj->uobject.id; resp.max_recv_sge = attr.cap.max_recv_sge; resp.max_send_sge = attr.cap.max_send_sge; resp.max_recv_wr = attr.cap.max_recv_wr; resp.max_send_wr = attr.cap.max_send_wr; resp.max_inline_data = attr.cap.max_inline_data; if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { Loading Loading @@ -1135,7 +1140,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, next->num_sge = user_wr->num_sge; next->opcode = user_wr->opcode; next->send_flags = user_wr->send_flags; next->imm_data = user_wr->imm_data; next->imm_data = (__be32 __force) user_wr->imm_data; if (qp->qp_type == IB_QPT_UD) { next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr, Loading Loading @@ -1701,7 +1706,6 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, } attr.max_wr = cmd.max_wr; attr.max_sge = cmd.max_sge; attr.srq_limit = cmd.srq_limit; ret = ib_modify_srq(srq, &attr, cmd.attr_mask); Loading
drivers/infiniband/core/verbs.c +2 −10 Original line number Diff line number Diff line Loading @@ -325,16 +325,8 @@ EXPORT_SYMBOL(ib_destroy_cq); int ib_resize_cq(struct ib_cq *cq, int cqe) { int ret; if (!cq->device->resize_cq) return -ENOSYS; ret = cq->device->resize_cq(cq, &cqe); if (!ret) cq->cqe = cqe; return ret; return cq->device->resize_cq ? cq->device->resize_cq(cq, cqe) : -ENOSYS; } EXPORT_SYMBOL(ib_resize_cq); Loading
drivers/infiniband/hw/mthca/mthca_catas.c +1 −1 Original line number Diff line number Diff line Loading @@ -97,7 +97,7 @@ static void poll_catas(unsigned long dev_ptr) } spin_lock_irqsave(&catas_lock, flags); if (dev->catas_err.stop) if (!dev->catas_err.stop) mod_timer(&dev->catas_err.timer, jiffies + MTHCA_CATAS_POLL_INTERVAL); spin_unlock_irqrestore(&catas_lock, flags); Loading
drivers/infiniband/hw/mthca/mthca_cmd.c +2 −0 Original line number Diff line number Diff line Loading @@ -1060,6 +1060,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, dev_lim->hca.arbel.resize_srq = field & 1; MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET); dev_lim->max_sg = min_t(int, field, dev_lim->max_sg); MTHCA_GET(size, outbox, QUERY_DEV_LIM_MAX_DESC_SZ_RQ_OFFSET); dev_lim->max_desc_sz = min_t(int, size, dev_lim->max_desc_sz); MTHCA_GET(size, outbox, QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET); dev_lim->mpt_entry_sz = size; MTHCA_GET(field, outbox, QUERY_DEV_LIM_PBL_SZ_OFFSET); Loading