···3737 * $Id: agent.c 1389 2004-12-27 22:56:47Z roland $3838 */39394040-#include <linux/dma-mapping.h>4141-4242-#include <asm/bug.h>4343-4444-#include <rdma/ib_smi.h>4545-4646-#include "smi.h"4747-#include "agent_priv.h"4848-#include "mad_priv.h"4940#include "agent.h"4141+#include "smi.h"50425151-spinlock_t ib_agent_port_list_lock;4343+#define SPFX "ib_agent: "4444+4545+struct ib_agent_port_private {4646+ struct list_head port_list;4747+ struct ib_mad_agent *agent[2];4848+};4949+5050+static DEFINE_SPINLOCK(ib_agent_port_list_lock);5251static LIST_HEAD(ib_agent_port_list);53525454-/*5555- * Caller must hold ib_agent_port_list_lock5656- */5757-static inline struct ib_agent_port_private *5858-__ib_get_agent_port(struct ib_device *device, int port_num,5959- struct ib_mad_agent *mad_agent)5353+static struct ib_agent_port_private *5454+__ib_get_agent_port(struct ib_device *device, int port_num)6055{6156 struct ib_agent_port_private *entry;62576363- BUG_ON(!(!!device ^ !!mad_agent)); /* Exactly one MUST be (!NULL) */6464-6565- if (device) {6666- list_for_each_entry(entry, &ib_agent_port_list, port_list) {6767- if (entry->smp_agent->device == device &&6868- entry->port_num == port_num)6969- return entry;7070- }7171- } else {7272- list_for_each_entry(entry, &ib_agent_port_list, port_list) {7373- if ((entry->smp_agent == mad_agent) ||7474- (entry->perf_mgmt_agent == mad_agent))7575- return entry;7676- }5858+ list_for_each_entry(entry, &ib_agent_port_list, port_list) {5959+ if (entry->agent[0]->device == device &&6060+ entry->agent[0]->port_num == port_num)6161+ return entry;7762 }7863 return NULL;7964}80658181-static inline struct ib_agent_port_private *8282-ib_get_agent_port(struct ib_device *device, int port_num,8383- struct ib_mad_agent *mad_agent)6666+static struct ib_agent_port_private *6767+ib_get_agent_port(struct ib_device *device, int port_num)8468{8569 struct ib_agent_port_private *entry;8670 unsigned long flags;87718872 spin_lock_irqsave(&ib_agent_port_list_lock, flags);8989- entry = __ib_get_agent_port(device, port_num, mad_agent);7373+ entry = __ib_get_agent_port(device, port_num);9074 spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);9191-9275 return entry;9376}9477···8310084101 if (smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)85102 return 1;8686- port_priv = ib_get_agent_port(device, port_num, NULL);103103+104104+ port_priv = ib_get_agent_port(device, port_num);87105 if (!port_priv) {88106 printk(KERN_DEBUG SPFX "smi_check_local_dr_smp %s port %d "8989- "not open\n",9090- device->name, port_num);107107+ "not open\n", device->name, port_num);91108 return 1;92109 }931109494- return smi_check_local_smp(port_priv->smp_agent, smp);111111+ return smi_check_local_smp(port_priv->agent[0], smp);95112}961139797-static int agent_mad_send(struct ib_mad_agent *mad_agent,9898- struct ib_agent_port_private *port_priv,9999- struct ib_mad_private *mad_priv,100100- struct ib_grh *grh,101101- struct ib_wc *wc)102102-{103103- struct ib_agent_send_wr *agent_send_wr;104104- struct ib_sge gather_list;105105- struct ib_send_wr send_wr;106106- struct ib_send_wr *bad_send_wr;107107- struct ib_ah_attr ah_attr;108108- unsigned long flags;109109- int ret = 1;110110-111111- agent_send_wr = kmalloc(sizeof(*agent_send_wr), GFP_KERNEL);112112- if (!agent_send_wr)113113- goto out;114114- agent_send_wr->mad = mad_priv;115115-116116- gather_list.addr = dma_map_single(mad_agent->device->dma_device,117117- &mad_priv->mad,118118- sizeof(mad_priv->mad),119119- DMA_TO_DEVICE);120120- gather_list.length = sizeof(mad_priv->mad);121121- gather_list.lkey = mad_agent->mr->lkey;122122-123123- send_wr.next = NULL;124124- send_wr.opcode = IB_WR_SEND;125125- send_wr.sg_list = &gather_list;126126- send_wr.num_sge = 1;127127- send_wr.wr.ud.remote_qpn = wc->src_qp; /* DQPN */128128- send_wr.wr.ud.timeout_ms = 0;129129- send_wr.send_flags = IB_SEND_SIGNALED | IB_SEND_SOLICITED;130130-131131- ah_attr.dlid = wc->slid;132132- ah_attr.port_num = mad_agent->port_num;133133- ah_attr.src_path_bits = wc->dlid_path_bits;134134- ah_attr.sl = wc->sl;135135- ah_attr.static_rate = 0;136136- ah_attr.ah_flags = 0; /* No GRH */137137- if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {138138- if (wc->wc_flags & IB_WC_GRH) {139139- ah_attr.ah_flags = IB_AH_GRH;140140- /* Should sgid be looked up ? */141141- ah_attr.grh.sgid_index = 0;142142- ah_attr.grh.hop_limit = grh->hop_limit;143143- ah_attr.grh.flow_label = be32_to_cpu(144144- grh->version_tclass_flow) & 0xfffff;145145- ah_attr.grh.traffic_class = (be32_to_cpu(146146- grh->version_tclass_flow) >> 20) & 0xff;147147- memcpy(ah_attr.grh.dgid.raw,148148- grh->sgid.raw,149149- sizeof(ah_attr.grh.dgid));150150- }151151- }152152-153153- agent_send_wr->ah = ib_create_ah(mad_agent->qp->pd, &ah_attr);154154- if (IS_ERR(agent_send_wr->ah)) {155155- printk(KERN_ERR SPFX "No memory for address handle\n");156156- kfree(agent_send_wr);157157- goto out;158158- }159159-160160- send_wr.wr.ud.ah = agent_send_wr->ah;161161- if (mad_priv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT) {162162- send_wr.wr.ud.pkey_index = wc->pkey_index;163163- send_wr.wr.ud.remote_qkey = IB_QP1_QKEY;164164- } else { /* for SMPs */165165- send_wr.wr.ud.pkey_index = 0;166166- send_wr.wr.ud.remote_qkey = 0;167167- }168168- send_wr.wr.ud.mad_hdr = &mad_priv->mad.mad.mad_hdr;169169- send_wr.wr_id = (unsigned long)agent_send_wr;170170-171171- pci_unmap_addr_set(agent_send_wr, mapping, gather_list.addr);172172-173173- /* Send */174174- spin_lock_irqsave(&port_priv->send_list_lock, flags);175175- if (ib_post_send_mad(mad_agent, &send_wr, &bad_send_wr)) {176176- spin_unlock_irqrestore(&port_priv->send_list_lock, flags);177177- dma_unmap_single(mad_agent->device->dma_device,178178- pci_unmap_addr(agent_send_wr, mapping),179179- sizeof(mad_priv->mad),180180- DMA_TO_DEVICE);181181- ib_destroy_ah(agent_send_wr->ah);182182- kfree(agent_send_wr);183183- } else {184184- list_add_tail(&agent_send_wr->send_list,185185- &port_priv->send_posted_list);186186- spin_unlock_irqrestore(&port_priv->send_list_lock, flags);187187- ret = 0;188188- }189189-190190-out:191191- return ret;192192-}193193-194194-int agent_send(struct ib_mad_private *mad,195195- struct ib_grh *grh,196196- struct ib_wc *wc,197197- struct ib_device *device,198198- int port_num)114114+int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,115115+ struct ib_wc *wc, struct ib_device *device,116116+ int port_num, int qpn)199117{200118 struct ib_agent_port_private *port_priv;201201- struct ib_mad_agent *mad_agent;119119+ struct ib_mad_agent *agent;120120+ struct ib_mad_send_buf *send_buf;121121+ struct ib_ah *ah;122122+ int ret;202123203203- port_priv = ib_get_agent_port(device, port_num, NULL);124124+ port_priv = ib_get_agent_port(device, port_num);204125 if (!port_priv) {205205- printk(KERN_DEBUG SPFX "agent_send %s port %d not open\n",206206- device->name, port_num);207207- return 1;126126+ printk(KERN_ERR SPFX "Unable to find port agent\n");127127+ return -ENODEV;208128 }209129210210- /* Get mad agent based on mgmt_class in MAD */211211- switch (mad->mad.mad.mad_hdr.mgmt_class) {212212- case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:213213- case IB_MGMT_CLASS_SUBN_LID_ROUTED:214214- mad_agent = port_priv->smp_agent;215215- break;216216- case IB_MGMT_CLASS_PERF_MGMT:217217- mad_agent = port_priv->perf_mgmt_agent;218218- break;219219- default:220220- return 1;130130+ agent = port_priv->agent[qpn];131131+ ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num);132132+ if (IS_ERR(ah)) {133133+ ret = PTR_ERR(ah);134134+ printk(KERN_ERR SPFX "ib_create_ah_from_wc error:%d\n", ret);135135+ return ret;221136 }222137223223- return agent_mad_send(mad_agent, port_priv, mad, grh, wc);138138+ send_buf = ib_create_send_mad(agent, wc->src_qp, wc->pkey_index, 0,139139+ IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,140140+ GFP_KERNEL);141141+ if (IS_ERR(send_buf)) {142142+ ret = PTR_ERR(send_buf);143143+ printk(KERN_ERR SPFX "ib_create_send_mad error:%d\n", ret);144144+ goto err1;145145+ }146146+147147+ memcpy(send_buf->mad, mad, sizeof *mad);148148+ send_buf->ah = ah;149149+ if ((ret = ib_post_send_mad(send_buf, NULL))) {150150+ printk(KERN_ERR SPFX "ib_post_send_mad error:%d\n", ret);151151+ goto err2;152152+ }153153+ return 0;154154+err2:155155+ ib_free_send_mad(send_buf);156156+err1:157157+ ib_destroy_ah(ah);158158+ return ret;224159}225160226161static void agent_send_handler(struct ib_mad_agent *mad_agent,227162 struct ib_mad_send_wc *mad_send_wc)228163{229229- struct ib_agent_port_private *port_priv;230230- struct ib_agent_send_wr *agent_send_wr;231231- unsigned long flags;232232-233233- /* Find matching MAD agent */234234- port_priv = ib_get_agent_port(NULL, 0, mad_agent);235235- if (!port_priv) {236236- printk(KERN_ERR SPFX "agent_send_handler: no matching MAD "237237- "agent %p\n", mad_agent);238238- return;239239- }240240-241241- agent_send_wr = (struct ib_agent_send_wr *)(unsigned long)mad_send_wc->wr_id;242242- spin_lock_irqsave(&port_priv->send_list_lock, flags);243243- /* Remove completed send from posted send MAD list */244244- list_del(&agent_send_wr->send_list);245245- spin_unlock_irqrestore(&port_priv->send_list_lock, flags);246246-247247- dma_unmap_single(mad_agent->device->dma_device,248248- pci_unmap_addr(agent_send_wr, mapping),249249- sizeof(agent_send_wr->mad->mad),250250- DMA_TO_DEVICE);251251-252252- ib_destroy_ah(agent_send_wr->ah);253253-254254- /* Release allocated memory */255255- kmem_cache_free(ib_mad_cache, agent_send_wr->mad);256256- kfree(agent_send_wr);164164+ ib_destroy_ah(mad_send_wc->send_buf->ah);165165+ ib_free_send_mad(mad_send_wc->send_buf);257166}258167259168int ib_agent_port_open(struct ib_device *device, int port_num)260169{261261- int ret;262170 struct ib_agent_port_private *port_priv;263171 unsigned long flags;264264-265265- /* First, check if port already open for SMI */266266- port_priv = ib_get_agent_port(device, port_num, NULL);267267- if (port_priv) {268268- printk(KERN_DEBUG SPFX "%s port %d already open\n",269269- device->name, port_num);270270- return 0;271271- }172172+ int ret;272173273174 /* Create new device info */274175 port_priv = kmalloc(sizeof *port_priv, GFP_KERNEL);···161294 ret = -ENOMEM;162295 goto error1;163296 }164164-165297 memset(port_priv, 0, sizeof *port_priv);166166- port_priv->port_num = port_num;167167- spin_lock_init(&port_priv->send_list_lock);168168- INIT_LIST_HEAD(&port_priv->send_posted_list);169298170170- /* Obtain send only MAD agent for SM class (SMI QP) */171171- port_priv->smp_agent = ib_register_mad_agent(device, port_num,172172- IB_QPT_SMI,173173- NULL, 0,299299+ /* Obtain send only MAD agent for SMI QP */300300+ port_priv->agent[0] = ib_register_mad_agent(device, port_num,301301+ IB_QPT_SMI, NULL, 0,174302 &agent_send_handler,175175- NULL, NULL);176176-177177- if (IS_ERR(port_priv->smp_agent)) {178178- ret = PTR_ERR(port_priv->smp_agent);303303+ NULL, NULL);304304+ if (IS_ERR(port_priv->agent[0])) {305305+ ret = PTR_ERR(port_priv->agent[0]);179306 goto error2;180307 }181308182182- /* Obtain send only MAD agent for PerfMgmt class (GSI QP) */183183- port_priv->perf_mgmt_agent = ib_register_mad_agent(device, port_num,184184- IB_QPT_GSI,185185- NULL, 0,186186- &agent_send_handler,187187- NULL, NULL);188188- if (IS_ERR(port_priv->perf_mgmt_agent)) {189189- ret = PTR_ERR(port_priv->perf_mgmt_agent);309309+ /* Obtain send only MAD agent for GSI QP */310310+ port_priv->agent[1] = ib_register_mad_agent(device, port_num,311311+ IB_QPT_GSI, NULL, 0,312312+ &agent_send_handler,313313+ NULL, NULL);314314+ if (IS_ERR(port_priv->agent[1])) {315315+ ret = PTR_ERR(port_priv->agent[1]);190316 goto error3;191317 }192318···190330 return 0;191331192332error3:193193- ib_unregister_mad_agent(port_priv->smp_agent);333333+ ib_unregister_mad_agent(port_priv->agent[0]);194334error2:195335 kfree(port_priv);196336error1:···203343 unsigned long flags;204344205345 spin_lock_irqsave(&ib_agent_port_list_lock, flags);206206- port_priv = __ib_get_agent_port(device, port_num, NULL);346346+ port_priv = __ib_get_agent_port(device, port_num);207347 if (port_priv == NULL) {208348 spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);209349 printk(KERN_ERR SPFX "Port %d not found\n", port_num);···212352 list_del(&port_priv->port_list);213353 spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);214354215215- ib_unregister_mad_agent(port_priv->perf_mgmt_agent);216216- ib_unregister_mad_agent(port_priv->smp_agent);355355+ ib_unregister_mad_agent(port_priv->agent[1]);356356+ ib_unregister_mad_agent(port_priv->agent[0]);217357 kfree(port_priv);218218-219358 return 0;220359}
+5-8
drivers/infiniband/core/agent.h
···3939#ifndef __AGENT_H_4040#define __AGENT_H_41414242-extern spinlock_t ib_agent_port_list_lock;4242+#include <rdma/ib_mad.h>43434444-extern int ib_agent_port_open(struct ib_device *device,4545- int port_num);4444+extern int ib_agent_port_open(struct ib_device *device, int port_num);46454746extern int ib_agent_port_close(struct ib_device *device, int port_num);48474949-extern int agent_send(struct ib_mad_private *mad,5050- struct ib_grh *grh,5151- struct ib_wc *wc,5252- struct ib_device *device,5353- int port_num);4848+extern int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,4949+ struct ib_wc *wc, struct ib_device *device,5050+ int port_num, int qpn);54515552#endif /* __AGENT_H_ */
-62
drivers/infiniband/core/agent_priv.h
···11-/*22- * Copyright (c) 2004, 2005 Mellanox Technologies Ltd. All rights reserved.33- * Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.44- * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.55- * Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.66- * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.77- *88- * This software is available to you under a choice of one of two99- * licenses. You may choose to be licensed under the terms of the GNU1010- * General Public License (GPL) Version 2, available from the file1111- * COPYING in the main directory of this source tree, or the1212- * OpenIB.org BSD license below:1313- *1414- * Redistribution and use in source and binary forms, with or1515- * without modification, are permitted provided that the following1616- * conditions are met:1717- *1818- * - Redistributions of source code must retain the above1919- * copyright notice, this list of conditions and the following2020- * disclaimer.2121- *2222- * - Redistributions in binary form must reproduce the above2323- * copyright notice, this list of conditions and the following2424- * disclaimer in the documentation and/or other materials2525- * provided with the distribution.2626- *2727- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,2828- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF2929- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND3030- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS3131- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN3232- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN3333- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE3434- * SOFTWARE.3535- *3636- * $Id: agent_priv.h 1640 2005-01-24 22:39:02Z halr $3737- */3838-3939-#ifndef __IB_AGENT_PRIV_H__4040-#define __IB_AGENT_PRIV_H__4141-4242-#include <linux/pci.h>4343-4444-#define SPFX "ib_agent: "4545-4646-struct ib_agent_send_wr {4747- struct list_head send_list;4848- struct ib_ah *ah;4949- struct ib_mad_private *mad;5050- DECLARE_PCI_UNMAP_ADDR(mapping)5151-};5252-5353-struct ib_agent_port_private {5454- struct list_head port_list;5555- struct list_head send_posted_list;5656- spinlock_t send_list_lock;5757- int port_num;5858- struct ib_mad_agent *smp_agent; /* SM class */5959- struct ib_mad_agent *perf_mgmt_agent; /* PerfMgmt class */6060-};6161-6262-#endif /* __IB_AGENT_PRIV_H__ */
+98-119
drivers/infiniband/core/cm.c
···135135 __be64 tid;136136 __be32 local_qpn;137137 __be32 remote_qpn;138138+ enum ib_qp_type qp_type;138139 __be32 sq_psn;139140 __be32 rq_psn;140141 int timeout_ms;···176175177176 m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn, 178177 cm_id_priv->av.pkey_index,179179- ah, 0, sizeof(struct ib_mad_hdr),180180- sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),178178+ 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,181179 GFP_ATOMIC);182180 if (IS_ERR(m)) {183181 ib_destroy_ah(ah);···184184 }185185186186 /* Timeout set by caller if response is expected. */187187- m->send_wr.wr.ud.retries = cm_id_priv->max_cm_retries;187187+ m->ah = ah;188188+ m->retries = cm_id_priv->max_cm_retries;188189189190 atomic_inc(&cm_id_priv->refcount);190191 m->context[0] = cm_id_priv;···206205 return PTR_ERR(ah);207206208207 m = ib_create_send_mad(port->mad_agent, 1, mad_recv_wc->wc->pkey_index,209209- ah, 0, sizeof(struct ib_mad_hdr),210210- sizeof(struct ib_mad)-sizeof(struct ib_mad_hdr),208208+ 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA,211209 GFP_ATOMIC);212210 if (IS_ERR(m)) {213211 ib_destroy_ah(ah);214212 return PTR_ERR(m);215213 }214214+ m->ah = ah;216215 *msg = m;217216 return 0;218217}219218220219static void cm_free_msg(struct ib_mad_send_buf *msg)221220{222222- ib_destroy_ah(msg->send_wr.wr.ud.ah);221221+ ib_destroy_ah(msg->ah);223222 if (msg->context[0])224223 cm_deref_id(msg->context[0]);225224 ib_free_send_mad(msg);···367366 cur_cm_id_priv = rb_entry(parent, struct cm_id_private,368367 service_node);369368 if ((cur_cm_id_priv->id.service_mask & service_id) ==370370- (service_mask & cur_cm_id_priv->id.service_id))371371- return cm_id_priv;372372- if (service_id < cur_cm_id_priv->id.service_id)369369+ (service_mask & cur_cm_id_priv->id.service_id) &&370370+ (cm_id_priv->id.device == cur_cm_id_priv->id.device))371371+ return cur_cm_id_priv;372372+373373+ if (cm_id_priv->id.device < cur_cm_id_priv->id.device)374374+ link = &(*link)->rb_left;375375+ else if (cm_id_priv->id.device > cur_cm_id_priv->id.device)376376+ link = &(*link)->rb_right;377377+ else if (service_id < cur_cm_id_priv->id.service_id)373378 link = &(*link)->rb_left;374379 else375380 link = &(*link)->rb_right;···385378 return NULL;386379}387380388388-static struct cm_id_private * cm_find_listen(__be64 service_id)381381+static struct cm_id_private * cm_find_listen(struct ib_device *device,382382+ __be64 service_id)389383{390384 struct rb_node *node = cm.listen_service_table.rb_node;391385 struct cm_id_private *cm_id_priv;···394386 while (node) {395387 cm_id_priv = rb_entry(node, struct cm_id_private, service_node);396388 if ((cm_id_priv->id.service_mask & service_id) ==397397- (cm_id_priv->id.service_mask & cm_id_priv->id.service_id))389389+ cm_id_priv->id.service_id &&390390+ (cm_id_priv->id.device == device))398391 return cm_id_priv;399399- if (service_id < cm_id_priv->id.service_id)392392+393393+ if (device < cm_id_priv->id.device)394394+ node = node->rb_left;395395+ else if (device > cm_id_priv->id.device)396396+ node = node->rb_right;397397+ else if (service_id < cm_id_priv->id.service_id)400398 node = node->rb_left;401399 else402400 node = node->rb_right;···537523 ib_send_cm_sidr_rep(&cm_id_priv->id, ¶m);538524}539525540540-struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,526526+struct ib_cm_id *ib_create_cm_id(struct ib_device *device,527527+ ib_cm_handler cm_handler,541528 void *context)542529{543530 struct cm_id_private *cm_id_priv;···550535551536 memset(cm_id_priv, 0, sizeof *cm_id_priv);552537 cm_id_priv->id.state = IB_CM_IDLE;538538+ cm_id_priv->id.device = device;553539 cm_id_priv->id.cm_handler = cm_handler;554540 cm_id_priv->id.context = context;555541 cm_id_priv->id.remote_cm_qpn = 1;···678662 break;679663 case IB_CM_SIDR_REQ_SENT:680664 cm_id->state = IB_CM_IDLE;681681- ib_cancel_mad(cm_id_priv->av.port->mad_agent,682682- (unsigned long) cm_id_priv->msg);665665+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);683666 spin_unlock_irqrestore(&cm_id_priv->lock, flags);684667 break;685668 case IB_CM_SIDR_REQ_RCVD:···689674 case IB_CM_MRA_REQ_RCVD:690675 case IB_CM_REP_SENT:691676 case IB_CM_MRA_REP_RCVD:692692- ib_cancel_mad(cm_id_priv->av.port->mad_agent,693693- (unsigned long) cm_id_priv->msg);677677+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);694678 /* Fall through */695679 case IB_CM_REQ_RCVD:696680 case IB_CM_MRA_REQ_SENT:···706692 ib_send_cm_dreq(cm_id, NULL, 0);707693 goto retest;708694 case IB_CM_DREQ_SENT:709709- ib_cancel_mad(cm_id_priv->av.port->mad_agent,710710- (unsigned long) cm_id_priv->msg);695695+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);711696 cm_enter_timewait(cm_id_priv);712697 spin_unlock_irqrestore(&cm_id_priv->lock, flags);713698 break;···880867 struct ib_cm_req_param *param)881868{882869 struct cm_id_private *cm_id_priv;883883- struct ib_send_wr *bad_send_wr;884870 struct cm_req_msg *req_msg;885871 unsigned long flags;886872 int ret;···923911 cm_id_priv->responder_resources = param->responder_resources;924912 cm_id_priv->retry_count = param->retry_count;925913 cm_id_priv->path_mtu = param->primary_path->mtu;914914+ cm_id_priv->qp_type = param->qp_type;926915927916 ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg);928917 if (ret)···932919 req_msg = (struct cm_req_msg *) cm_id_priv->msg->mad;933920 cm_format_req(req_msg, cm_id_priv, param);934921 cm_id_priv->tid = req_msg->hdr.tid;935935- cm_id_priv->msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;922922+ cm_id_priv->msg->timeout_ms = cm_id_priv->timeout_ms;936923 cm_id_priv->msg->context[1] = (void *) (unsigned long) IB_CM_REQ_SENT;937924938925 cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg);···941928 cm_req_get_primary_local_ack_timeout(req_msg);942929943930 spin_lock_irqsave(&cm_id_priv->lock, flags);944944- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,945945- &cm_id_priv->msg->send_wr, &bad_send_wr);931931+ ret = ib_post_send_mad(cm_id_priv->msg, NULL);946932 if (ret) {947933 spin_unlock_irqrestore(&cm_id_priv->lock, flags);948934 goto error2;···964952 void *ari, u8 ari_length)965953{966954 struct ib_mad_send_buf *msg = NULL;967967- struct ib_send_wr *bad_send_wr;968955 struct cm_rej_msg *rej_msg, *rcv_msg;969956 int ret;970957···986975 memcpy(rej_msg->ari, ari, ari_length);987976 }988977989989- ret = ib_post_send_mad(port->mad_agent, &msg->send_wr, &bad_send_wr);978978+ ret = ib_post_send_mad(msg, NULL);990979 if (ret)991980 cm_free_msg(msg);992981···10581047 req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;10591048 param = &work->cm_event.param.req_rcvd;10601049 param->listen_id = listen_id;10611061- param->device = cm_id_priv->av.port->mad_agent->device;10621050 param->port = cm_id_priv->av.port->port_num;10631051 param->primary_path = &work->path[0];10641052 if (req_msg->alt_local_lid)···11661156 struct cm_id_private *cm_id_priv)11671157{11681158 struct ib_mad_send_buf *msg = NULL;11691169- struct ib_send_wr *bad_send_wr;11701159 unsigned long flags;11711160 int ret;11721161···11941185 }11951186 spin_unlock_irqrestore(&cm_id_priv->lock, flags);1196118711971197- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,11981198- &bad_send_wr);11881188+ ret = ib_post_send_mad(msg, NULL);11991189 if (ret)12001190 goto free;12011191 return;···12341226 }1235122712361228 /* Find matching listen request. */12371237- listen_cm_id_priv = cm_find_listen(req_msg->service_id);12291229+ listen_cm_id_priv = cm_find_listen(cm_id_priv->id.device,12301230+ req_msg->service_id);12381231 if (!listen_cm_id_priv) {12391232 spin_unlock_irqrestore(&cm.lock, flags);12401233 cm_issue_rej(work->port, work->mad_recv_wc,···1263125412641255 req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;1265125612661266- cm_id = ib_create_cm_id(NULL, NULL);12571257+ cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);12671258 if (IS_ERR(cm_id))12681259 return PTR_ERR(cm_id);12691260···13141305 cm_req_get_primary_local_ack_timeout(req_msg);13151306 cm_id_priv->retry_count = cm_req_get_retry_count(req_msg);13161307 cm_id_priv->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);13081308+ cm_id_priv->qp_type = cm_req_get_qp_type(req_msg);1317130913181310 cm_format_req_event(work, cm_id_priv, &listen_cm_id_priv->id);13191311 cm_process_work(cm_id_priv, work);···13591349 struct cm_id_private *cm_id_priv;13601350 struct ib_mad_send_buf *msg;13611351 struct cm_rep_msg *rep_msg;13621362- struct ib_send_wr *bad_send_wr;13631352 unsigned long flags;13641353 int ret;13651354···1380137113811372 rep_msg = (struct cm_rep_msg *) msg->mad;13821373 cm_format_rep(rep_msg, cm_id_priv, param);13831383- msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;13741374+ msg->timeout_ms = cm_id_priv->timeout_ms;13841375 msg->context[1] = (void *) (unsigned long) IB_CM_REP_SENT;1385137613861386- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,13871387- &msg->send_wr, &bad_send_wr);13771377+ ret = ib_post_send_mad(msg, NULL);13881378 if (ret) {13891379 spin_unlock_irqrestore(&cm_id_priv->lock, flags);13901380 cm_free_msg(msg);···14211413{14221414 struct cm_id_private *cm_id_priv;14231415 struct ib_mad_send_buf *msg;14241424- struct ib_send_wr *bad_send_wr;14251416 unsigned long flags;14261417 void *data;14271418 int ret;···14471440 cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,14481441 private_data, private_data_len);1449144214501450- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,14511451- &msg->send_wr, &bad_send_wr);14431443+ ret = ib_post_send_mad(msg, NULL);14521444 if (ret) {14531445 spin_unlock_irqrestore(&cm_id_priv->lock, flags);14541446 cm_free_msg(msg);···14921486 struct cm_id_private *cm_id_priv;14931487 struct cm_rep_msg *rep_msg;14941488 struct ib_mad_send_buf *msg = NULL;14951495- struct ib_send_wr *bad_send_wr;14961489 unsigned long flags;14971490 int ret;14981491···15191514 goto unlock;15201515 spin_unlock_irqrestore(&cm_id_priv->lock, flags);1521151615221522- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,15231523- &bad_send_wr);15171517+ ret = ib_post_send_mad(msg, NULL);15241518 if (ret)15251519 goto free;15261520 goto deref;···1587158315881584 /* todo: handle peer_to_peer */1589158515901590- ib_cancel_mad(cm_id_priv->av.port->mad_agent,15911591- (unsigned long) cm_id_priv->msg);15861586+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);15921587 ret = atomic_inc_and_test(&cm_id_priv->work_count);15931588 if (!ret)15941589 list_add_tail(&work->list, &cm_id_priv->work_list);···16211618 goto out;16221619 }1623162016241624- ib_cancel_mad(cm_id_priv->av.port->mad_agent,16251625- (unsigned long) cm_id_priv->msg);16211621+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);16261622 ret = atomic_inc_and_test(&cm_id_priv->work_count);16271623 if (!ret)16281624 list_add_tail(&work->list, &cm_id_priv->work_list);···16601658 }16611659 cm_id_priv->id.state = IB_CM_ESTABLISHED;1662166016631663- ib_cancel_mad(cm_id_priv->av.port->mad_agent,16641664- (unsigned long) cm_id_priv->msg);16611661+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);16651662 ret = atomic_inc_and_test(&cm_id_priv->work_count);16661663 if (!ret)16671664 list_add_tail(&work->list, &cm_id_priv->work_list);···16971696{16981697 struct cm_id_private *cm_id_priv;16991698 struct ib_mad_send_buf *msg;17001700- struct ib_send_wr *bad_send_wr;17011699 unsigned long flags;17021700 int ret;17031701···1718171817191719 cm_format_dreq((struct cm_dreq_msg *) msg->mad, cm_id_priv,17201720 private_data, private_data_len);17211721- msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;17211721+ msg->timeout_ms = cm_id_priv->timeout_ms;17221722 msg->context[1] = (void *) (unsigned long) IB_CM_DREQ_SENT;1723172317241724- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,17251725- &msg->send_wr, &bad_send_wr);17241724+ ret = ib_post_send_mad(msg, NULL);17261725 if (ret) {17271726 cm_enter_timewait(cm_id_priv);17281727 spin_unlock_irqrestore(&cm_id_priv->lock, flags);···17551756{17561757 struct cm_id_private *cm_id_priv;17571758 struct ib_mad_send_buf *msg;17581758- struct ib_send_wr *bad_send_wr;17591759 unsigned long flags;17601760 void *data;17611761 int ret;···17841786 cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv,17851787 private_data, private_data_len);1786178817871787- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent, &msg->send_wr,17881788- &bad_send_wr);17891789+ ret = ib_post_send_mad(msg, NULL);17891790 if (ret) {17901791 spin_unlock_irqrestore(&cm_id_priv->lock, flags);17911792 cm_free_msg(msg);···18011804 struct cm_id_private *cm_id_priv;18021805 struct cm_dreq_msg *dreq_msg;18031806 struct ib_mad_send_buf *msg = NULL;18041804- struct ib_send_wr *bad_send_wr;18051807 unsigned long flags;18061808 int ret;18071809···18191823 switch (cm_id_priv->id.state) {18201824 case IB_CM_REP_SENT:18211825 case IB_CM_DREQ_SENT:18221822- ib_cancel_mad(cm_id_priv->av.port->mad_agent,18231823- (unsigned long) cm_id_priv->msg);18261826+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);18241827 break;18251828 case IB_CM_ESTABLISHED:18261829 case IB_CM_MRA_REP_RCVD:···18331838 cm_id_priv->private_data_len);18341839 spin_unlock_irqrestore(&cm_id_priv->lock, flags);1835184018361836- if (ib_post_send_mad(cm_id_priv->av.port->mad_agent,18371837- &msg->send_wr, &bad_send_wr))18411841+ if (ib_post_send_mad(msg, NULL))18381842 cm_free_msg(msg);18391843 goto deref;18401844 default:···18801886 }18811887 cm_enter_timewait(cm_id_priv);1882188818831883- ib_cancel_mad(cm_id_priv->av.port->mad_agent,18841884- (unsigned long) cm_id_priv->msg);18891889+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);18851890 ret = atomic_inc_and_test(&cm_id_priv->work_count);18861891 if (!ret)18871892 list_add_tail(&work->list, &cm_id_priv->work_list);···19051912{19061913 struct cm_id_private *cm_id_priv;19071914 struct ib_mad_send_buf *msg;19081908- struct ib_send_wr *bad_send_wr;19091915 unsigned long flags;19101916 int ret;19111917···19481956 if (ret)19491957 goto out;1950195819511951- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,19521952- &msg->send_wr, &bad_send_wr);19591959+ ret = ib_post_send_mad(msg, NULL);19531960 if (ret)19541961 cm_free_msg(msg);19551962···20242033 case IB_CM_MRA_REQ_RCVD:20252034 case IB_CM_REP_SENT:20262035 case IB_CM_MRA_REP_RCVD:20272027- ib_cancel_mad(cm_id_priv->av.port->mad_agent,20282028- (unsigned long) cm_id_priv->msg);20362036+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);20292037 /* fall through */20302038 case IB_CM_REQ_RCVD:20312039 case IB_CM_MRA_REQ_SENT:···20342044 cm_reset_to_idle(cm_id_priv);20352045 break;20362046 case IB_CM_DREQ_SENT:20372037- ib_cancel_mad(cm_id_priv->av.port->mad_agent,20382038- (unsigned long) cm_id_priv->msg);20472047+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);20392048 /* fall through */20402049 case IB_CM_REP_RCVD:20412050 case IB_CM_MRA_REP_SENT:···20692080{20702081 struct cm_id_private *cm_id_priv;20712082 struct ib_mad_send_buf *msg;20722072- struct ib_send_wr *bad_send_wr;20732083 void *data;20742084 unsigned long flags;20752085 int ret;···20922104 cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,20932105 CM_MSG_RESPONSE_REQ, service_timeout,20942106 private_data, private_data_len);20952095- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,20962096- &msg->send_wr, &bad_send_wr);21072107+ ret = ib_post_send_mad(msg, NULL);20972108 if (ret)20982109 goto error2;20992110 cm_id->state = IB_CM_MRA_REQ_SENT;···21052118 cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,21062119 CM_MSG_RESPONSE_REP, service_timeout,21072120 private_data, private_data_len);21082108- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,21092109- &msg->send_wr, &bad_send_wr);21212121+ ret = ib_post_send_mad(msg, NULL);21102122 if (ret)21112123 goto error2;21122124 cm_id->state = IB_CM_MRA_REP_SENT;···21182132 cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,21192133 CM_MSG_RESPONSE_OTHER, service_timeout,21202134 private_data, private_data_len);21212121- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,21222122- &msg->send_wr, &bad_send_wr);21352135+ ret = ib_post_send_mad(msg, NULL);21232136 if (ret)21242137 goto error2;21252138 cm_id->lap_state = IB_CM_MRA_LAP_SENT;···21802195 case IB_CM_REQ_SENT:21812196 if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REQ ||21822197 ib_modify_mad(cm_id_priv->av.port->mad_agent,21832183- (unsigned long) cm_id_priv->msg, timeout))21982198+ cm_id_priv->msg, timeout))21842199 goto out;21852200 cm_id_priv->id.state = IB_CM_MRA_REQ_RCVD;21862201 break;21872202 case IB_CM_REP_SENT:21882203 if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REP ||21892204 ib_modify_mad(cm_id_priv->av.port->mad_agent,21902190- (unsigned long) cm_id_priv->msg, timeout))22052205+ cm_id_priv->msg, timeout))21912206 goto out;21922207 cm_id_priv->id.state = IB_CM_MRA_REP_RCVD;21932208 break;···21952210 if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_OTHER ||21962211 cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||21972212 ib_modify_mad(cm_id_priv->av.port->mad_agent,21982198- (unsigned long) cm_id_priv->msg, timeout))22132213+ cm_id_priv->msg, timeout))21992214 goto out;22002215 cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;22012216 break;···22582273{22592274 struct cm_id_private *cm_id_priv;22602275 struct ib_mad_send_buf *msg;22612261- struct ib_send_wr *bad_send_wr;22622276 unsigned long flags;22632277 int ret;22642278···2278229422792295 cm_format_lap((struct cm_lap_msg *) msg->mad, cm_id_priv,22802296 alternate_path, private_data, private_data_len);22812281- msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;22972297+ msg->timeout_ms = cm_id_priv->timeout_ms;22822298 msg->context[1] = (void *) (unsigned long) IB_CM_ESTABLISHED;2283229922842284- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,22852285- &msg->send_wr, &bad_send_wr);23002300+ ret = ib_post_send_mad(msg, NULL);22862301 if (ret) {22872302 spin_unlock_irqrestore(&cm_id_priv->lock, flags);22882303 cm_free_msg(msg);···23252342 struct cm_lap_msg *lap_msg;23262343 struct ib_cm_lap_event_param *param;23272344 struct ib_mad_send_buf *msg = NULL;23282328- struct ib_send_wr *bad_send_wr;23292345 unsigned long flags;23302346 int ret;23312347···23582376 cm_id_priv->private_data_len);23592377 spin_unlock_irqrestore(&cm_id_priv->lock, flags);2360237823612361- if (ib_post_send_mad(cm_id_priv->av.port->mad_agent,23622362- &msg->send_wr, &bad_send_wr))23792379+ if (ib_post_send_mad(msg, NULL))23632380 cm_free_msg(msg);23642381 goto deref;23652382 default:···24142433{24152434 struct cm_id_private *cm_id_priv;24162435 struct ib_mad_send_buf *msg;24172417- struct ib_send_wr *bad_send_wr;24182436 unsigned long flags;24192437 int ret;24202438···2436245624372457 cm_format_apr((struct cm_apr_msg *) msg->mad, cm_id_priv, status,24382458 info, info_length, private_data, private_data_len);24392439- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,24402440- &msg->send_wr, &bad_send_wr);24592459+ ret = ib_post_send_mad(msg, NULL);24412460 if (ret) {24422461 spin_unlock_irqrestore(&cm_id_priv->lock, flags);24432462 cm_free_msg(msg);···24752496 goto out;24762497 }24772498 cm_id_priv->id.lap_state = IB_CM_LAP_IDLE;24782478- ib_cancel_mad(cm_id_priv->av.port->mad_agent,24792479- (unsigned long) cm_id_priv->msg);24992499+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);24802500 cm_id_priv->msg = NULL;2481250124822502 ret = atomic_inc_and_test(&cm_id_priv->work_count);···25502572{25512573 struct cm_id_private *cm_id_priv;25522574 struct ib_mad_send_buf *msg;25532553- struct ib_send_wr *bad_send_wr;25542575 unsigned long flags;25552576 int ret;25562577···2572259525732596 cm_format_sidr_req((struct cm_sidr_req_msg *) msg->mad, cm_id_priv,25742597 param);25752575- msg->send_wr.wr.ud.timeout_ms = cm_id_priv->timeout_ms;25982598+ msg->timeout_ms = cm_id_priv->timeout_ms;25762599 msg->context[1] = (void *) (unsigned long) IB_CM_SIDR_REQ_SENT;2577260025782601 spin_lock_irqsave(&cm_id_priv->lock, flags);25792602 if (cm_id->state == IB_CM_IDLE)25802580- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,25812581- &msg->send_wr, &bad_send_wr);26032603+ ret = ib_post_send_mad(msg, NULL);25822604 else25832605 ret = -EINVAL;25842606···26052629 param = &work->cm_event.param.sidr_req_rcvd;26062630 param->pkey = __be16_to_cpu(sidr_req_msg->pkey);26072631 param->listen_id = listen_id;26082608- param->device = work->port->mad_agent->device;26092632 param->port = work->port->port_num;26102633 work->cm_event.private_data = &sidr_req_msg->private_data;26112634}···26172642 struct ib_wc *wc;26182643 unsigned long flags;2619264426202620- cm_id = ib_create_cm_id(NULL, NULL);26452645+ cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);26212646 if (IS_ERR(cm_id))26222647 return PTR_ERR(cm_id);26232648 cm_id_priv = container_of(cm_id, struct cm_id_private, id);···26412666 spin_unlock_irqrestore(&cm.lock, flags);26422667 goto out; /* Duplicate message. */26432668 }26442644- cur_cm_id_priv = cm_find_listen(sidr_req_msg->service_id);26692669+ cur_cm_id_priv = cm_find_listen(cm_id->device,26702670+ sidr_req_msg->service_id);26452671 if (!cur_cm_id_priv) {26462672 rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);26472673 spin_unlock_irqrestore(&cm.lock, flags);···26912715{26922716 struct cm_id_private *cm_id_priv;26932717 struct ib_mad_send_buf *msg;26942694- struct ib_send_wr *bad_send_wr;26952718 unsigned long flags;26962719 int ret;26972720···2712273727132738 cm_format_sidr_rep((struct cm_sidr_rep_msg *) msg->mad, cm_id_priv,27142739 param);27152715- ret = ib_post_send_mad(cm_id_priv->av.port->mad_agent,27162716- &msg->send_wr, &bad_send_wr);27402740+ ret = ib_post_send_mad(msg, NULL);27172741 if (ret) {27182742 spin_unlock_irqrestore(&cm_id_priv->lock, flags);27192743 cm_free_msg(msg);···27652791 goto out;27662792 }27672793 cm_id_priv->id.state = IB_CM_IDLE;27682768- ib_cancel_mad(cm_id_priv->av.port->mad_agent,27692769- (unsigned long) cm_id_priv->msg);27942794+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);27702795 spin_unlock_irqrestore(&cm_id_priv->lock, flags);2771279627722797 cm_format_sidr_rep_event(work);···28332860static void cm_send_handler(struct ib_mad_agent *mad_agent,28342861 struct ib_mad_send_wc *mad_send_wc)28352862{28362836- struct ib_mad_send_buf *msg;28372837-28382838- msg = (struct ib_mad_send_buf *)(unsigned long)mad_send_wc->wr_id;28632863+ struct ib_mad_send_buf *msg = mad_send_wc->send_buf;2839286428402865 switch (mad_send_wc->status) {28412866 case IB_WC_SUCCESS:···30353064 case IB_CM_ESTABLISHED:30363065 *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS |30373066 IB_QP_PKEY_INDEX | IB_QP_PORT;30383038- qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE;30673067+ qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE |30683068+ IB_ACCESS_REMOTE_WRITE;30393069 if (cm_id_priv->responder_resources)30403040- qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_WRITE |30413041- IB_ACCESS_REMOTE_READ;30703070+ qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_READ;30423071 qp_attr->pkey_index = cm_id_priv->av.pkey_index;30433072 qp_attr->port_num = cm_id_priv->av.port->port_num;30443073 ret = 0;···30683097 case IB_CM_MRA_REP_RCVD:30693098 case IB_CM_ESTABLISHED:30703099 *qp_attr_mask = IB_QP_STATE | IB_QP_AV | IB_QP_PATH_MTU |30713071- IB_QP_DEST_QPN | IB_QP_RQ_PSN |30723072- IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MIN_RNR_TIMER;31003100+ IB_QP_DEST_QPN | IB_QP_RQ_PSN;30733101 qp_attr->ah_attr = cm_id_priv->av.ah_attr;30743102 qp_attr->path_mtu = cm_id_priv->path_mtu;30753103 qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);30763104 qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);30773077- qp_attr->max_dest_rd_atomic = cm_id_priv->responder_resources;30783078- qp_attr->min_rnr_timer = 0;31053105+ if (cm_id_priv->qp_type == IB_QPT_RC) {31063106+ *qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC |31073107+ IB_QP_MIN_RNR_TIMER;31083108+ qp_attr->max_dest_rd_atomic =31093109+ cm_id_priv->responder_resources;31103110+ qp_attr->min_rnr_timer = 0;31113111+ }30793112 if (cm_id_priv->alt_av.ah_attr.dlid) {30803113 *qp_attr_mask |= IB_QP_ALT_PATH;30813114 qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;···31083133 case IB_CM_REP_SENT:31093134 case IB_CM_MRA_REP_RCVD:31103135 case IB_CM_ESTABLISHED:31113111- *qp_attr_mask = IB_QP_STATE | IB_QP_TIMEOUT | IB_QP_RETRY_CNT |31123112- IB_QP_RNR_RETRY | IB_QP_SQ_PSN |31133113- IB_QP_MAX_QP_RD_ATOMIC;31143114- qp_attr->timeout = cm_id_priv->local_ack_timeout;31153115- qp_attr->retry_cnt = cm_id_priv->retry_count;31163116- qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;31363136+ *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;31173137 qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);31183118- qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;31383138+ if (cm_id_priv->qp_type == IB_QPT_RC) {31393139+ *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |31403140+ IB_QP_RNR_RETRY |31413141+ IB_QP_MAX_QP_RD_ATOMIC;31423142+ qp_attr->timeout = cm_id_priv->local_ack_timeout;31433143+ qp_attr->retry_cnt = cm_id_priv->retry_count;31443144+ qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;31453145+ qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;31463146+ }31193147 if (cm_id_priv->alt_av.ah_attr.dlid) {31203148 *qp_attr_mask |= IB_QP_PATH_MIG_STATE;31213149 qp_attr->path_mig_state = IB_MIG_REARM;···33013323 flush_workqueue(cm.wq);33023324 destroy_workqueue(cm.wq);33033325 ib_unregister_client(&cm_client);33263326+ idr_destroy(&cm.local_id_table);33043327}3305332833063329module_init(ib_cm_init);
···11-/*22- * Copyright (c) 2005 Topspin Communications. All rights reserved.33- * Copyright (c) 2005 Intel Corporation. All rights reserved.44- *55- * This software is available to you under a choice of one of two66- * licenses. You may choose to be licensed under the terms of the GNU77- * General Public License (GPL) Version 2, available from the file88- * COPYING in the main directory of this source tree, or the99- * OpenIB.org BSD license below:1010- *1111- * Redistribution and use in source and binary forms, with or1212- * without modification, are permitted provided that the following1313- * conditions are met:1414- *1515- * - Redistributions of source code must retain the above1616- * copyright notice, this list of conditions and the following1717- * disclaimer.1818- *1919- * - Redistributions in binary form must reproduce the above2020- * copyright notice, this list of conditions and the following2121- * disclaimer in the documentation and/or other materials2222- * provided with the distribution.2323- *2424- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,2525- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF2626- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND2727- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS2828- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN2929- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN3030- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE3131- * SOFTWARE.3232- *3333- * $Id: ucm.h 2208 2005-04-22 23:24:31Z libor $3434- */3535-3636-#ifndef UCM_H3737-#define UCM_H3838-3939-#include <linux/fs.h>4040-#include <linux/device.h>4141-#include <linux/cdev.h>4242-#include <linux/idr.h>4343-4444-#include <rdma/ib_cm.h>4545-#include <rdma/ib_user_cm.h>4646-4747-struct ib_ucm_file {4848- struct semaphore mutex;4949- struct file *filp;5050-5151- struct list_head ctxs; /* list of active connections */5252- struct list_head events; /* list of pending events */5353- wait_queue_head_t poll_wait;5454-};5555-5656-struct ib_ucm_context {5757- int id;5858- wait_queue_head_t wait;5959- atomic_t ref;6060- int events_reported;6161-6262- struct ib_ucm_file *file;6363- struct ib_cm_id *cm_id;6464- __u64 uid;6565-6666- struct list_head events; /* list of pending events. */6767- struct list_head file_list; /* member in file ctx list */6868-};6969-7070-struct ib_ucm_event {7171- struct ib_ucm_context *ctx;7272- struct list_head file_list; /* member in file event list */7373- struct list_head ctx_list; /* member in ctx event list */7474-7575- struct ib_cm_id *cm_id;7676- struct ib_ucm_event_resp resp;7777- void *data;7878- void *info;7979- int data_len;8080- int info_len;8181-};8282-8383-#endif /* UCM_H */
+202-201
drivers/infiniband/core/user_mad.c
···6464 IB_UMAD_MINOR_BASE = 06565};66666767-struct ib_umad_port {6868- int devnum;6969- struct cdev dev;7070- struct class_device class_dev;6767+/*6868+ * Our lifetime rules for these structs are the following: each time a6969+ * device special file is opened, we look up the corresponding struct7070+ * ib_umad_port by minor in the umad_port[] table while holding the7171+ * port_lock. If this lookup succeeds, we take a reference on the7272+ * ib_umad_port's struct ib_umad_device while still holding the7373+ * port_lock; if the lookup fails, we fail the open(). We drop these7474+ * references in the corresponding close().7575+ *7676+ * In addition to references coming from open character devices, there7777+ * is one more reference to each ib_umad_device representing the7878+ * module's reference taken when allocating the ib_umad_device in7979+ * ib_umad_add_one().8080+ *8181+ * When destroying an ib_umad_device, we clear all of its8282+ * ib_umad_ports from umad_port[] while holding port_lock before8383+ * dropping the module's reference to the ib_umad_device. This is8484+ * always safe because any open() calls will either succeed and obtain8585+ * a reference before we clear the umad_port[] entries, or fail after8686+ * we clear the umad_port[] entries.8787+ */71887272- int sm_devnum;7373- struct cdev sm_dev;7474- struct class_device sm_class_dev;8989+struct ib_umad_port {9090+ struct cdev *dev;9191+ struct class_device *class_dev;9292+9393+ struct cdev *sm_dev;9494+ struct class_device *sm_class_dev;7595 struct semaphore sm_sem;76967797 struct ib_device *ib_dev;7898 struct ib_umad_device *umad_dev;9999+ int dev_num;79100 u8 port_num;80101};81102···11796};1189711998struct ib_umad_packet {120120- struct ib_ah *ah;12199 struct ib_mad_send_buf *msg;122100 struct list_head list;123101 int length;124124- DECLARE_PCI_UNMAP_ADDR(mapping)125102 struct ib_user_mad mad;126103};127104105105+static struct class *umad_class;106106+128107static const dev_t base_dev = MKDEV(IB_UMAD_MAJOR, IB_UMAD_MINOR_BASE);129129-static spinlock_t map_lock;108108+109109+static DEFINE_SPINLOCK(port_lock);110110+static struct ib_umad_port *umad_port[IB_UMAD_MAX_PORTS];130111static DECLARE_BITMAP(dev_map, IB_UMAD_MAX_PORTS * 2);131112132113static void ib_umad_add_one(struct ib_device *device);133114static void ib_umad_remove_one(struct ib_device *device);115115+116116+static void ib_umad_release_dev(struct kref *ref)117117+{118118+ struct ib_umad_device *dev =119119+ container_of(ref, struct ib_umad_device, ref);120120+121121+ kfree(dev);122122+}134123135124static int queue_packet(struct ib_umad_file *file,136125 struct ib_mad_agent *agent,···170139 struct ib_mad_send_wc *send_wc)171140{172141 struct ib_umad_file *file = agent->context;173173- struct ib_umad_packet *timeout, *packet =174174- (void *) (unsigned long) send_wc->wr_id;142142+ struct ib_umad_packet *timeout;143143+ struct ib_umad_packet *packet = send_wc->send_buf->context[0];175144176176- ib_destroy_ah(packet->msg->send_wr.wr.ud.ah);145145+ ib_destroy_ah(packet->msg->ah);177146 ib_free_send_mad(packet->msg);178147179148 if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) {180180- timeout = kmalloc(sizeof *timeout + sizeof (struct ib_mad_hdr),181181- GFP_KERNEL);149149+ timeout = kzalloc(sizeof *timeout + IB_MGMT_MAD_HDR, GFP_KERNEL);182150 if (!timeout)183151 goto out;184152185185- memset(timeout, 0, sizeof *timeout + sizeof (struct ib_mad_hdr));186186-187187- timeout->length = sizeof (struct ib_mad_hdr);188188- timeout->mad.hdr.id = packet->mad.hdr.id;153153+ timeout->length = IB_MGMT_MAD_HDR;154154+ timeout->mad.hdr.id = packet->mad.hdr.id;189155 timeout->mad.hdr.status = ETIMEDOUT;190156 memcpy(timeout->mad.data, packet->mad.data,191157 sizeof (struct ib_mad_hdr));···205177 goto out;206178207179 length = mad_recv_wc->mad_len;208208- packet = kmalloc(sizeof *packet + length, GFP_KERNEL);180180+ packet = kzalloc(sizeof *packet + length, GFP_KERNEL);209181 if (!packet)210182 goto out;211183212212- memset(packet, 0, sizeof *packet + length);213184 packet->length = length;214185215186 ib_coalesce_recv_mad(mad_recv_wc, packet->mad.data);···274247 else275248 ret = -ENOSPC;276249 } else if (copy_to_user(buf, &packet->mad,277277- packet->length + sizeof (struct ib_user_mad)))250250+ packet->length + sizeof (struct ib_user_mad)))278251 ret = -EFAULT;279252 else280253 ret = packet->length + sizeof (struct ib_user_mad);···295268 struct ib_umad_packet *packet;296269 struct ib_mad_agent *agent;297270 struct ib_ah_attr ah_attr;298298- struct ib_send_wr *bad_wr;271271+ struct ib_ah *ah;299272 struct ib_rmpp_mad *rmpp_mad;300273 u8 method;301274 __be64 *tid;302302- int ret, length, hdr_len, data_len, rmpp_hdr_size;275275+ int ret, length, hdr_len, copy_offset;303276 int rmpp_active = 0;304277305278 if (count < sizeof (struct ib_user_mad))306279 return -EINVAL;307280308281 length = count - sizeof (struct ib_user_mad);309309- packet = kmalloc(sizeof *packet + sizeof(struct ib_mad_hdr) +310310- sizeof(struct ib_rmpp_hdr), GFP_KERNEL);282282+ packet = kmalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL);311283 if (!packet)312284 return -ENOMEM;313285314286 if (copy_from_user(&packet->mad, buf,315315- sizeof (struct ib_user_mad) +316316- sizeof(struct ib_mad_hdr) +317317- sizeof(struct ib_rmpp_hdr))) {287287+ sizeof (struct ib_user_mad) + IB_MGMT_RMPP_HDR)) {318288 ret = -EFAULT;319289 goto err;320290 }···321297 ret = -EINVAL;322298 goto err;323299 }324324-325325- packet->length = length;326300327301 down_read(&file->agent_mutex);328302···343321 ah_attr.grh.traffic_class = packet->mad.hdr.traffic_class;344322 }345323346346- packet->ah = ib_create_ah(agent->qp->pd, &ah_attr);347347- if (IS_ERR(packet->ah)) {348348- ret = PTR_ERR(packet->ah);324324+ ah = ib_create_ah(agent->qp->pd, &ah_attr);325325+ if (IS_ERR(ah)) {326326+ ret = PTR_ERR(ah);349327 goto err_up;350328 }351329···359337360338 /* Validate that the management class can support RMPP */361339 if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {362362- hdr_len = offsetof(struct ib_sa_mad, data);363363- data_len = length - hdr_len;340340+ hdr_len = IB_MGMT_SA_HDR;364341 } else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&365342 (rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) {366366- hdr_len = offsetof(struct ib_vendor_mad, data);367367- data_len = length - hdr_len;343343+ hdr_len = IB_MGMT_VENDOR_HDR;368344 } else {369345 ret = -EINVAL;370346 goto err_ah;371347 }372348 rmpp_active = 1;349349+ copy_offset = IB_MGMT_RMPP_HDR;373350 } else {374374- if (length > sizeof(struct ib_mad)) {375375- ret = -EINVAL;376376- goto err_ah;377377- }378378- hdr_len = offsetof(struct ib_mad, data);379379- data_len = length - hdr_len;351351+ hdr_len = IB_MGMT_MAD_HDR;352352+ copy_offset = IB_MGMT_MAD_HDR;380353 }381354382355 packet->msg = ib_create_send_mad(agent,383356 be32_to_cpu(packet->mad.hdr.qpn),384384- 0, packet->ah, rmpp_active,385385- hdr_len, data_len,357357+ 0, rmpp_active,358358+ hdr_len, length - hdr_len,386359 GFP_KERNEL);387360 if (IS_ERR(packet->msg)) {388361 ret = PTR_ERR(packet->msg);389362 goto err_ah;390363 }391364392392- packet->msg->send_wr.wr.ud.timeout_ms = packet->mad.hdr.timeout_ms;393393- packet->msg->send_wr.wr.ud.retries = packet->mad.hdr.retries;365365+ packet->msg->ah = ah;366366+ packet->msg->timeout_ms = packet->mad.hdr.timeout_ms;367367+ packet->msg->retries = packet->mad.hdr.retries;368368+ packet->msg->context[0] = packet;394369395395- /* Override send WR WRID initialized in ib_create_send_mad */396396- packet->msg->send_wr.wr_id = (unsigned long) packet;397397-398398- if (!rmpp_active) {399399- /* Copy message from user into send buffer */400400- if (copy_from_user(packet->msg->mad,401401- buf + sizeof(struct ib_user_mad), length)) {402402- ret = -EFAULT;403403- goto err_msg;404404- }405405- } else {406406- rmpp_hdr_size = sizeof(struct ib_mad_hdr) +407407- sizeof(struct ib_rmpp_hdr);408408-409409- /* Only copy MAD headers (RMPP header in place) */410410- memcpy(packet->msg->mad, packet->mad.data,411411- sizeof(struct ib_mad_hdr));412412-413413- /* Now, copy rest of message from user into send buffer */414414- if (copy_from_user(((struct ib_rmpp_mad *) packet->msg->mad)->data,415415- buf + sizeof (struct ib_user_mad) + rmpp_hdr_size,416416- length - rmpp_hdr_size)) {417417- ret = -EFAULT;418418- goto err_msg;419419- }370370+ /* Copy MAD headers (RMPP header in place) */371371+ memcpy(packet->msg->mad, packet->mad.data, IB_MGMT_MAD_HDR);372372+ /* Now, copy rest of message from user into send buffer */373373+ if (copy_from_user(packet->msg->mad + copy_offset,374374+ buf + sizeof (struct ib_user_mad) + copy_offset,375375+ length - copy_offset)) {376376+ ret = -EFAULT;377377+ goto err_msg;420378 }421379422380 /*···405403 * transaction ID matches the agent being used to send the406404 * MAD.407405 */408408- method = packet->msg->mad->mad_hdr.method;406406+ method = ((struct ib_mad_hdr *) packet->msg->mad)->method;409407410408 if (!(method & IB_MGMT_METHOD_RESP) &&411409 method != IB_MGMT_METHOD_TRAP_REPRESS &&412410 method != IB_MGMT_METHOD_SEND) {413413- tid = &packet->msg->mad->mad_hdr.tid;411411+ tid = &((struct ib_mad_hdr *) packet->msg->mad)->tid;414412 *tid = cpu_to_be64(((u64) agent->hi_tid) << 32 |415413 (be64_to_cpup(tid) & 0xffffffff));416414 }417415418418- ret = ib_post_send_mad(agent, &packet->msg->send_wr, &bad_wr);416416+ ret = ib_post_send_mad(packet->msg, NULL);419417 if (ret)420418 goto err_msg;421419422420 up_read(&file->agent_mutex);423421424424- return sizeof (struct ib_user_mad_hdr) + packet->length;422422+ return count;425423426424err_msg:427425 ib_free_send_mad(packet->msg);428426429427err_ah:430430- ib_destroy_ah(packet->ah);428428+ ib_destroy_ah(ah);431429432430err_up:433431 up_read(&file->agent_mutex);···567565568566static int ib_umad_open(struct inode *inode, struct file *filp)569567{570570- struct ib_umad_port *port =571571- container_of(inode->i_cdev, struct ib_umad_port, dev);568568+ struct ib_umad_port *port;572569 struct ib_umad_file *file;573570574574- file = kmalloc(sizeof *file, GFP_KERNEL);575575- if (!file)576576- return -ENOMEM;571571+ spin_lock(&port_lock);572572+ port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE];573573+ if (port)574574+ kref_get(&port->umad_dev->ref);575575+ spin_unlock(&port_lock);577576578578- memset(file, 0, sizeof *file);577577+ if (!port)578578+ return -ENXIO;579579+580580+ file = kzalloc(sizeof *file, GFP_KERNEL);581581+ if (!file) {582582+ kref_put(&port->umad_dev->ref, ib_umad_release_dev);583583+ return -ENOMEM;584584+ }579585580586 spin_lock_init(&file->recv_lock);581587 init_rwsem(&file->agent_mutex);···599589static int ib_umad_close(struct inode *inode, struct file *filp)600590{601591 struct ib_umad_file *file = filp->private_data;592592+ struct ib_umad_device *dev = file->port->umad_dev;602593 struct ib_umad_packet *packet, *tmp;603594 int i;604595···613602 kfree(packet);614603615604 kfree(file);605605+606606+ kref_put(&dev->ref, ib_umad_release_dev);616607617608 return 0;618609}···632619633620static int ib_umad_sm_open(struct inode *inode, struct file *filp)634621{635635- struct ib_umad_port *port =636636- container_of(inode->i_cdev, struct ib_umad_port, sm_dev);622622+ struct ib_umad_port *port;637623 struct ib_port_modify props = {638624 .set_port_cap_mask = IB_PORT_SM639625 };640626 int ret;641627628628+ spin_lock(&port_lock);629629+ port = umad_port[iminor(inode) - IB_UMAD_MINOR_BASE - IB_UMAD_MAX_PORTS];630630+ if (port)631631+ kref_get(&port->umad_dev->ref);632632+ spin_unlock(&port_lock);633633+634634+ if (!port)635635+ return -ENXIO;636636+642637 if (filp->f_flags & O_NONBLOCK) {643643- if (down_trylock(&port->sm_sem))644644- return -EAGAIN;638638+ if (down_trylock(&port->sm_sem)) {639639+ ret = -EAGAIN;640640+ goto fail;641641+ }645642 } else {646646- if (down_interruptible(&port->sm_sem))647647- return -ERESTARTSYS;643643+ if (down_interruptible(&port->sm_sem)) {644644+ ret = -ERESTARTSYS;645645+ goto fail;646646+ }648647 }649648650649 ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);651650 if (ret) {652651 up(&port->sm_sem);653653- return ret;652652+ goto fail;654653 }655654656655 filp->private_data = port;657656658657 return 0;658658+659659+fail:660660+ kref_put(&port->umad_dev->ref, ib_umad_release_dev);661661+ return ret;659662}660663661664static int ib_umad_sm_close(struct inode *inode, struct file *filp)···684655685656 ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);686657 up(&port->sm_sem);658658+659659+ kref_put(&port->umad_dev->ref, ib_umad_release_dev);687660688661 return ret;689662}···702671 .remove = ib_umad_remove_one703672};704673705705-static ssize_t show_dev(struct class_device *class_dev, char *buf)706706-{707707- struct ib_umad_port *port = class_get_devdata(class_dev);708708-709709- if (class_dev == &port->class_dev)710710- return print_dev_t(buf, port->dev.dev);711711- else712712- return print_dev_t(buf, port->sm_dev.dev);713713-}714714-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);715715-716674static ssize_t show_ibdev(struct class_device *class_dev, char *buf)717675{718676 struct ib_umad_port *port = class_get_devdata(class_dev);677677+678678+ if (!port)679679+ return -ENODEV;719680720681 return sprintf(buf, "%s\n", port->ib_dev->name);721682}···717694{718695 struct ib_umad_port *port = class_get_devdata(class_dev);719696697697+ if (!port)698698+ return -ENODEV;699699+720700 return sprintf(buf, "%d\n", port->port_num);721701}722702static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);723723-724724-static void ib_umad_release_dev(struct kref *ref)725725-{726726- struct ib_umad_device *dev =727727- container_of(ref, struct ib_umad_device, ref);728728-729729- kfree(dev);730730-}731731-732732-static void ib_umad_release_port(struct class_device *class_dev)733733-{734734- struct ib_umad_port *port = class_get_devdata(class_dev);735735-736736- if (class_dev == &port->class_dev) {737737- cdev_del(&port->dev);738738- clear_bit(port->devnum, dev_map);739739- } else {740740- cdev_del(&port->sm_dev);741741- clear_bit(port->sm_devnum, dev_map);742742- }743743-744744- kref_put(&port->umad_dev->ref, ib_umad_release_dev);745745-}746746-747747-static struct class umad_class = {748748- .name = "infiniband_mad",749749- .release = ib_umad_release_port750750-};751703752704static ssize_t show_abi_version(struct class *class, char *buf)753705{···733735static int ib_umad_init_port(struct ib_device *device, int port_num,734736 struct ib_umad_port *port)735737{736736- spin_lock(&map_lock);737737- port->devnum = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);738738- if (port->devnum >= IB_UMAD_MAX_PORTS) {739739- spin_unlock(&map_lock);738738+ spin_lock(&port_lock);739739+ port->dev_num = find_first_zero_bit(dev_map, IB_UMAD_MAX_PORTS);740740+ if (port->dev_num >= IB_UMAD_MAX_PORTS) {741741+ spin_unlock(&port_lock);740742 return -1;741743 }742742- port->sm_devnum = find_next_zero_bit(dev_map, IB_UMAD_MAX_PORTS * 2, IB_UMAD_MAX_PORTS);743743- if (port->sm_devnum >= IB_UMAD_MAX_PORTS * 2) {744744- spin_unlock(&map_lock);745745- return -1;746746- }747747- set_bit(port->devnum, dev_map);748748- set_bit(port->sm_devnum, dev_map);749749- spin_unlock(&map_lock);744744+ set_bit(port->dev_num, dev_map);745745+ spin_unlock(&port_lock);750746751747 port->ib_dev = device;752748 port->port_num = port_num;753749 init_MUTEX(&port->sm_sem);754750755755- cdev_init(&port->dev, &umad_fops);756756- port->dev.owner = THIS_MODULE;757757- kobject_set_name(&port->dev.kobj, "umad%d", port->devnum);758758- if (cdev_add(&port->dev, base_dev + port->devnum, 1))751751+ port->dev = cdev_alloc();752752+ if (!port->dev)759753 return -1;760760-761761- port->class_dev.class = &umad_class;762762- port->class_dev.dev = device->dma_device;763763-764764- snprintf(port->class_dev.class_id, BUS_ID_SIZE, "umad%d", port->devnum);765765-766766- if (class_device_register(&port->class_dev))754754+ port->dev->owner = THIS_MODULE;755755+ port->dev->ops = &umad_fops;756756+ kobject_set_name(&port->dev->kobj, "umad%d", port->dev_num);757757+ if (cdev_add(port->dev, base_dev + port->dev_num, 1))767758 goto err_cdev;768759769769- class_set_devdata(&port->class_dev, port);770770- kref_get(&port->umad_dev->ref);760760+ port->class_dev = class_device_create(umad_class, NULL, port->dev->dev,761761+ device->dma_device,762762+ "umad%d", port->dev_num);763763+ if (IS_ERR(port->class_dev))764764+ goto err_cdev;771765772772- if (class_device_create_file(&port->class_dev, &class_device_attr_dev))766766+ if (class_device_create_file(port->class_dev, &class_device_attr_ibdev))773767 goto err_class;774774- if (class_device_create_file(&port->class_dev, &class_device_attr_ibdev))775775- goto err_class;776776- if (class_device_create_file(&port->class_dev, &class_device_attr_port))768768+ if (class_device_create_file(port->class_dev, &class_device_attr_port))777769 goto err_class;778770779779- cdev_init(&port->sm_dev, &umad_sm_fops);780780- port->sm_dev.owner = THIS_MODULE;781781- kobject_set_name(&port->dev.kobj, "issm%d", port->sm_devnum - IB_UMAD_MAX_PORTS);782782- if (cdev_add(&port->sm_dev, base_dev + port->sm_devnum, 1))783783- return -1;784784-785785- port->sm_class_dev.class = &umad_class;786786- port->sm_class_dev.dev = device->dma_device;787787-788788- snprintf(port->sm_class_dev.class_id, BUS_ID_SIZE, "issm%d", port->sm_devnum - IB_UMAD_MAX_PORTS);789789-790790- if (class_device_register(&port->sm_class_dev))771771+ port->sm_dev = cdev_alloc();772772+ if (!port->sm_dev)773773+ goto err_class;774774+ port->sm_dev->owner = THIS_MODULE;775775+ port->sm_dev->ops = &umad_sm_fops;776776+ kobject_set_name(&port->dev->kobj, "issm%d", port->dev_num);777777+ if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))791778 goto err_sm_cdev;792779793793- class_set_devdata(&port->sm_class_dev, port);794794- kref_get(&port->umad_dev->ref);780780+ port->sm_class_dev = class_device_create(umad_class, NULL, port->sm_dev->dev,781781+ device->dma_device,782782+ "issm%d", port->dev_num);783783+ if (IS_ERR(port->sm_class_dev))784784+ goto err_sm_cdev;795785796796- if (class_device_create_file(&port->sm_class_dev, &class_device_attr_dev))786786+ class_set_devdata(port->class_dev, port);787787+ class_set_devdata(port->sm_class_dev, port);788788+789789+ if (class_device_create_file(port->sm_class_dev, &class_device_attr_ibdev))797790 goto err_sm_class;798798- if (class_device_create_file(&port->sm_class_dev, &class_device_attr_ibdev))791791+ if (class_device_create_file(port->sm_class_dev, &class_device_attr_port))799792 goto err_sm_class;800800- if (class_device_create_file(&port->sm_class_dev, &class_device_attr_port))801801- goto err_sm_class;793793+794794+ spin_lock(&port_lock);795795+ umad_port[port->dev_num] = port;796796+ spin_unlock(&port_lock);802797803798 return 0;804799805800err_sm_class:806806- class_device_unregister(&port->sm_class_dev);801801+ class_device_destroy(umad_class, port->sm_dev->dev);807802808803err_sm_cdev:809809- cdev_del(&port->sm_dev);804804+ cdev_del(port->sm_dev);810805811806err_class:812812- class_device_unregister(&port->class_dev);807807+ class_device_destroy(umad_class, port->dev->dev);813808814809err_cdev:815815- cdev_del(&port->dev);816816- clear_bit(port->devnum, dev_map);810810+ cdev_del(port->dev);811811+ clear_bit(port->dev_num, dev_map);817812818813 return -1;814814+}815815+816816+static void ib_umad_kill_port(struct ib_umad_port *port)817817+{818818+ class_set_devdata(port->class_dev, NULL);819819+ class_set_devdata(port->sm_class_dev, NULL);820820+821821+ class_device_destroy(umad_class, port->dev->dev);822822+ class_device_destroy(umad_class, port->sm_dev->dev);823823+824824+ cdev_del(port->dev);825825+ cdev_del(port->sm_dev);826826+827827+ spin_lock(&port_lock);828828+ umad_port[port->dev_num] = NULL;829829+ spin_unlock(&port_lock);830830+831831+ clear_bit(port->dev_num, dev_map);819832}820833821834static void ib_umad_add_one(struct ib_device *device)···841832 e = device->phys_port_cnt;842833 }843834844844- umad_dev = kmalloc(sizeof *umad_dev +835835+ umad_dev = kzalloc(sizeof *umad_dev +845836 (e - s + 1) * sizeof (struct ib_umad_port),846837 GFP_KERNEL);847838 if (!umad_dev)848839 return;849849-850850- memset(umad_dev, 0, sizeof *umad_dev +851851- (e - s + 1) * sizeof (struct ib_umad_port));852840853841 kref_init(&umad_dev->ref);854842···864858 return;865859866860err:867867- while (--i >= s) {868868- class_device_unregister(&umad_dev->port[i - s].class_dev);869869- class_device_unregister(&umad_dev->port[i - s].sm_class_dev);870870- }861861+ while (--i >= s)862862+ ib_umad_kill_port(&umad_dev->port[i]);871863872864 kref_put(&umad_dev->ref, ib_umad_release_dev);873865}···878874 if (!umad_dev)879875 return;880876881881- for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i) {882882- class_device_unregister(&umad_dev->port[i].class_dev);883883- class_device_unregister(&umad_dev->port[i].sm_class_dev);884884- }877877+ for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i)878878+ ib_umad_kill_port(&umad_dev->port[i]);885879886880 kref_put(&umad_dev->ref, ib_umad_release_dev);887881}···888886{889887 int ret;890888891891- spin_lock_init(&map_lock);892892-893889 ret = register_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2,894890 "infiniband_mad");895891 if (ret) {···895895 goto out;896896 }897897898898- ret = class_register(&umad_class);899899- if (ret) {898898+ umad_class = class_create(THIS_MODULE, "infiniband_mad");899899+ if (IS_ERR(umad_class)) {900900+ ret = PTR_ERR(umad_class);900901 printk(KERN_ERR "user_mad: couldn't create class infiniband_mad\n");901902 goto out_chrdev;902903 }903904904904- ret = class_create_file(&umad_class, &class_attr_abi_version);905905+ ret = class_create_file(umad_class, &class_attr_abi_version);905906 if (ret) {906907 printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n");907908 goto out_class;···917916 return 0;918917919918out_class:920920- class_unregister(&umad_class);919919+ class_destroy(umad_class);921920922921out_chrdev:923922 unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);···929928static void __exit ib_umad_cleanup(void)930929{931930 ib_unregister_client(&umad_client);932932- class_unregister(&umad_class);931931+ class_destroy(umad_class);933932 unregister_chrdev_region(base_dev, IB_UMAD_MAX_PORTS * 2);934933}935934
+49-13
drivers/infiniband/core/uverbs.h
···33 * Copyright (c) 2005 Cisco Systems. All rights reserved.44 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.55 * Copyright (c) 2005 Voltaire, Inc. All rights reserved.66+ * Copyright (c) 2005 PathScale, Inc. All rights reserved.67 *78 * This software is available to you under a choice of one of two89 * licenses. You may choose to be licensed under the terms of the GNU···3938#ifndef UVERBS_H4039#define UVERBS_H41404242-/* Include device.h and fs.h until cdev.h is self-sufficient */4343-#include <linux/fs.h>4444-#include <linux/device.h>4545-#include <linux/cdev.h>4641#include <linux/kref.h>4742#include <linux/idr.h>48434944#include <rdma/ib_verbs.h>5045#include <rdma/ib_user_verbs.h>51464747+/*4848+ * Our lifetime rules for these structs are the following:4949+ *5050+ * struct ib_uverbs_device: One reference is held by the module and5151+ * released in ib_uverbs_remove_one(). Another reference is taken by5252+ * ib_uverbs_open() each time the character special file is opened,5353+ * and released in ib_uverbs_release_file() when the file is released.5454+ *5555+ * struct ib_uverbs_file: One reference is held by the VFS and5656+ * released when the file is closed. Another reference is taken when5757+ * an asynchronous event queue file is created and released when the5858+ * event file is closed.5959+ *6060+ * struct ib_uverbs_event_file: One reference is held by the VFS and6161+ * released when the file is closed. For asynchronous event files,6262+ * another reference is held by the corresponding main context file6363+ * and released when that file is closed. For completion event files,6464+ * a reference is taken when a CQ is created that uses the file, and6565+ * released when the CQ is destroyed.6666+ */6767+5268struct ib_uverbs_device {6969+ struct kref ref;5370 int devnum;5454- struct cdev dev;5555- struct class_device class_dev;7171+ struct cdev *dev;7272+ struct class_device *class_dev;5673 struct ib_device *ib_dev;5757- int num_comp;7474+ int num_comp_vectors;5875};59766077struct ib_uverbs_event_file {6178 struct kref ref;7979+ struct file *file;6280 struct ib_uverbs_file *uverbs_file;6381 spinlock_t lock;6464- int fd;6582 int is_async;6683 wait_queue_head_t poll_wait;6784 struct fasync_struct *async_queue;···9273 struct ib_uverbs_device *device;9374 struct ib_ucontext *ucontext;9475 struct ib_event_handler event_handler;9595- struct ib_uverbs_event_file async_file;9696- struct ib_uverbs_event_file comp_file[1];7676+ struct ib_uverbs_event_file *async_file;9777};98789979struct ib_uverbs_event {···128110extern struct idr ib_uverbs_qp_idr;129111extern struct idr ib_uverbs_srq_idr;130112113113+struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,114114+ int is_async, int *fd);115115+void ib_uverbs_release_event_file(struct kref *ref);116116+struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd);117117+118118+void ib_uverbs_release_ucq(struct ib_uverbs_file *file,119119+ struct ib_uverbs_event_file *ev_file,120120+ struct ib_ucq_object *uobj);121121+void ib_uverbs_release_uevent(struct ib_uverbs_file *file,122122+ struct ib_uevent_object *uobj);123123+131124void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);132125void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);133126void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);134127void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);128128+void ib_uverbs_event_handler(struct ib_event_handler *handler,129129+ struct ib_event *event);135130136131int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,137132 void *addr, size_t size, int write);···156125 const char __user *buf, int in_len, \157126 int out_len)158127159159-IB_UVERBS_DECLARE_CMD(query_params);160128IB_UVERBS_DECLARE_CMD(get_context);161129IB_UVERBS_DECLARE_CMD(query_device);162130IB_UVERBS_DECLARE_CMD(query_port);163163-IB_UVERBS_DECLARE_CMD(query_gid);164164-IB_UVERBS_DECLARE_CMD(query_pkey);165131IB_UVERBS_DECLARE_CMD(alloc_pd);166132IB_UVERBS_DECLARE_CMD(dealloc_pd);167133IB_UVERBS_DECLARE_CMD(reg_mr);168134IB_UVERBS_DECLARE_CMD(dereg_mr);135135+IB_UVERBS_DECLARE_CMD(create_comp_channel);169136IB_UVERBS_DECLARE_CMD(create_cq);137137+IB_UVERBS_DECLARE_CMD(poll_cq);138138+IB_UVERBS_DECLARE_CMD(req_notify_cq);170139IB_UVERBS_DECLARE_CMD(destroy_cq);171140IB_UVERBS_DECLARE_CMD(create_qp);172141IB_UVERBS_DECLARE_CMD(modify_qp);173142IB_UVERBS_DECLARE_CMD(destroy_qp);143143+IB_UVERBS_DECLARE_CMD(post_send);144144+IB_UVERBS_DECLARE_CMD(post_recv);145145+IB_UVERBS_DECLARE_CMD(post_srq_recv);146146+IB_UVERBS_DECLARE_CMD(create_ah);147147+IB_UVERBS_DECLARE_CMD(destroy_ah);174148IB_UVERBS_DECLARE_CMD(attach_mcast);175149IB_UVERBS_DECLARE_CMD(detach_mcast);176150IB_UVERBS_DECLARE_CMD(create_srq);
+677-181
drivers/infiniband/core/uverbs_cmd.c
···11/*22 * Copyright (c) 2005 Topspin Communications. All rights reserved.33 * Copyright (c) 2005 Cisco Systems. All rights reserved.44+ * Copyright (c) 2005 PathScale, Inc. All rights reserved.45 *56 * This software is available to you under a choice of one of two67 * licenses. You may choose to be licensed under the terms of the GNU···3433 * $Id: uverbs_cmd.c 2708 2005-06-24 17:27:21Z roland $3534 */36353636+#include <linux/file.h>3737+#include <linux/fs.h>3838+3739#include <asm/uaccess.h>38403941#include "uverbs.h"···4945 (udata)->outlen = (olen); \5046 } while (0)51475252-ssize_t ib_uverbs_query_params(struct ib_uverbs_file *file,5353- const char __user *buf,5454- int in_len, int out_len)5555-{5656- struct ib_uverbs_query_params cmd;5757- struct ib_uverbs_query_params_resp resp;5858-5959- if (out_len < sizeof resp)6060- return -ENOSPC;6161-6262- if (copy_from_user(&cmd, buf, sizeof cmd))6363- return -EFAULT;6464-6565- memset(&resp, 0, sizeof resp);6666-6767- resp.num_cq_events = file->device->num_comp;6868-6969- if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp))7070- return -EFAULT;7171-7272- return in_len;7373-}7474-7548ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,7649 const char __user *buf,7750 int in_len, int out_len)···5877 struct ib_udata udata;5978 struct ib_device *ibdev = file->device->ib_dev;6079 struct ib_ucontext *ucontext;6161- int i;8080+ struct file *filp;6281 int ret;63826483 if (out_len < sizeof resp)···91110 INIT_LIST_HEAD(&ucontext->srq_list);92111 INIT_LIST_HEAD(&ucontext->ah_list);931129494- resp.async_fd = file->async_file.fd;9595- for (i = 0; i < file->device->num_comp; ++i)9696- if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab +9797- i * sizeof (__u32),9898- &file->comp_file[i].fd, sizeof (__u32))) {9999- ret = -EFAULT;100100- goto err_free;101101- }113113+ resp.num_comp_vectors = file->device->num_comp_vectors;114114+115115+ filp = ib_uverbs_alloc_event_file(file, 1, &resp.async_fd);116116+ if (IS_ERR(filp)) {117117+ ret = PTR_ERR(filp);118118+ goto err_free;119119+ }102120103121 if (copy_to_user((void __user *) (unsigned long) cmd.response,104122 &resp, sizeof resp)) {105123 ret = -EFAULT;106106- goto err_free;124124+ goto err_file;107125 }108126127127+ file->async_file = filp->private_data;128128+129129+ INIT_IB_EVENT_HANDLER(&file->event_handler, file->device->ib_dev,130130+ ib_uverbs_event_handler);131131+ ret = ib_register_event_handler(&file->event_handler);132132+ if (ret)133133+ goto err_file;134134+135135+ kref_get(&file->async_file->ref);136136+ kref_get(&file->ref);109137 file->ucontext = ucontext;138138+139139+ fd_install(resp.async_fd, filp);140140+110141 up(&file->mutex);111142112143 return in_len;144144+145145+err_file:146146+ put_unused_fd(resp.async_fd);147147+ fput(filp);113148114149err_free:115150 ibdev->dealloc_ucontext(ucontext);···252255 return in_len;253256}254257255255-ssize_t ib_uverbs_query_gid(struct ib_uverbs_file *file,256256- const char __user *buf,257257- int in_len, int out_len)258258-{259259- struct ib_uverbs_query_gid cmd;260260- struct ib_uverbs_query_gid_resp resp;261261- int ret;262262-263263- if (out_len < sizeof resp)264264- return -ENOSPC;265265-266266- if (copy_from_user(&cmd, buf, sizeof cmd))267267- return -EFAULT;268268-269269- memset(&resp, 0, sizeof resp);270270-271271- ret = ib_query_gid(file->device->ib_dev, cmd.port_num, cmd.index,272272- (union ib_gid *) resp.gid);273273- if (ret)274274- return ret;275275-276276- if (copy_to_user((void __user *) (unsigned long) cmd.response,277277- &resp, sizeof resp))278278- return -EFAULT;279279-280280- return in_len;281281-}282282-283283-ssize_t ib_uverbs_query_pkey(struct ib_uverbs_file *file,284284- const char __user *buf,285285- int in_len, int out_len)286286-{287287- struct ib_uverbs_query_pkey cmd;288288- struct ib_uverbs_query_pkey_resp resp;289289- int ret;290290-291291- if (out_len < sizeof resp)292292- return -ENOSPC;293293-294294- if (copy_from_user(&cmd, buf, sizeof cmd))295295- return -EFAULT;296296-297297- memset(&resp, 0, sizeof resp);298298-299299- ret = ib_query_pkey(file->device->ib_dev, cmd.port_num, cmd.index,300300- &resp.pkey);301301- if (ret)302302- return ret;303303-304304- if (copy_to_user((void __user *) (unsigned long) cmd.response,305305- &resp, sizeof resp))306306- return -EFAULT;307307-308308- return in_len;309309-}310310-311258ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,312259 const char __user *buf,313260 int in_len, int out_len)···290349 pd->uobject = uobj;291350 atomic_set(&pd->usecnt, 0);292351352352+ down(&ib_uverbs_idr_mutex);353353+293354retry:294355 if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {295356 ret = -ENOMEM;296296- goto err_pd;357357+ goto err_up;297358 }298359299299- down(&ib_uverbs_idr_mutex);300360 ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id);301301- up(&ib_uverbs_idr_mutex);302361303362 if (ret == -EAGAIN)304363 goto retry;305364 if (ret)306306- goto err_pd;307307-308308- down(&file->mutex);309309- list_add_tail(&uobj->list, &file->ucontext->pd_list);310310- up(&file->mutex);365365+ goto err_up;311366312367 memset(&resp, 0, sizeof resp);313368 resp.pd_handle = uobj->id;···311374 if (copy_to_user((void __user *) (unsigned long) cmd.response,312375 &resp, sizeof resp)) {313376 ret = -EFAULT;314314- goto err_list;377377+ goto err_idr;315378 }379379+380380+ down(&file->mutex);381381+ list_add_tail(&uobj->list, &file->ucontext->pd_list);382382+ up(&file->mutex);383383+384384+ up(&ib_uverbs_idr_mutex);316385317386 return in_len;318387319319-err_list:320320- down(&file->mutex);321321- list_del(&uobj->list);322322- up(&file->mutex);323323-324324- down(&ib_uverbs_idr_mutex);388388+err_idr:325389 idr_remove(&ib_uverbs_pd_idr, uobj->id);326326- up(&ib_uverbs_idr_mutex);327390328328-err_pd:391391+err_up:392392+ up(&ib_uverbs_idr_mutex);329393 ib_dealloc_pd(pd);330394331395err:···397459 if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))398460 return -EINVAL;399461462462+ /*463463+ * Local write permission is required if remote write or464464+ * remote atomic permission is also requested.465465+ */466466+ if (cmd.access_flags & (IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_REMOTE_WRITE) &&467467+ !(cmd.access_flags & IB_ACCESS_LOCAL_WRITE))468468+ return -EINVAL;469469+400470 obj = kmalloc(sizeof *obj, GFP_KERNEL);401471 if (!obj)402472 return -ENOMEM;···470524471525 resp.mr_handle = obj->uobject.id;472526473473- down(&file->mutex);474474- list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);475475- up(&file->mutex);476476-477527 if (copy_to_user((void __user *) (unsigned long) cmd.response,478528 &resp, sizeof resp)) {479529 ret = -EFAULT;480480- goto err_list;530530+ goto err_idr;481531 }532532+533533+ down(&file->mutex);534534+ list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);535535+ up(&file->mutex);482536483537 up(&ib_uverbs_idr_mutex);484538485539 return in_len;486540487487-err_list:488488- down(&file->mutex);489489- list_del(&obj->uobject.list);490490- up(&file->mutex);541541+err_idr:542542+ idr_remove(&ib_uverbs_mr_idr, obj->uobject.id);491543492544err_unreg:493545 ib_dereg_mr(mr);···539595 return ret ? ret : in_len;540596}541597598598+ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,599599+ const char __user *buf, int in_len,600600+ int out_len)601601+{602602+ struct ib_uverbs_create_comp_channel cmd;603603+ struct ib_uverbs_create_comp_channel_resp resp;604604+ struct file *filp;605605+606606+ if (out_len < sizeof resp)607607+ return -ENOSPC;608608+609609+ if (copy_from_user(&cmd, buf, sizeof cmd))610610+ return -EFAULT;611611+612612+ filp = ib_uverbs_alloc_event_file(file, 0, &resp.fd);613613+ if (IS_ERR(filp))614614+ return PTR_ERR(filp);615615+616616+ if (copy_to_user((void __user *) (unsigned long) cmd.response,617617+ &resp, sizeof resp)) {618618+ put_unused_fd(resp.fd);619619+ fput(filp);620620+ return -EFAULT;621621+ }622622+623623+ fd_install(resp.fd, filp);624624+ return in_len;625625+}626626+542627ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,543628 const char __user *buf, int in_len,544629 int out_len)···576603 struct ib_uverbs_create_cq_resp resp;577604 struct ib_udata udata;578605 struct ib_ucq_object *uobj;606606+ struct ib_uverbs_event_file *ev_file = NULL;579607 struct ib_cq *cq;580608 int ret;581609···590616 (unsigned long) cmd.response + sizeof resp,591617 in_len - sizeof cmd, out_len - sizeof resp);592618593593- if (cmd.event_handler >= file->device->num_comp)619619+ if (cmd.comp_vector >= file->device->num_comp_vectors)594620 return -EINVAL;621621+622622+ if (cmd.comp_channel >= 0)623623+ ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel);595624596625 uobj = kmalloc(sizeof *uobj, GFP_KERNEL);597626 if (!uobj)···618641 cq->uobject = &uobj->uobject;619642 cq->comp_handler = ib_uverbs_comp_handler;620643 cq->event_handler = ib_uverbs_cq_event_handler;621621- cq->cq_context = file;644644+ cq->cq_context = ev_file;622645 atomic_set(&cq->usecnt, 0);646646+647647+ down(&ib_uverbs_idr_mutex);623648624649retry:625650 if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {626651 ret = -ENOMEM;627627- goto err_cq;652652+ goto err_up;628653 }629654630630- down(&ib_uverbs_idr_mutex);631655 ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);632632- up(&ib_uverbs_idr_mutex);633656634657 if (ret == -EAGAIN)635658 goto retry;636659 if (ret)637637- goto err_cq;638638-639639- down(&file->mutex);640640- list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);641641- up(&file->mutex);660660+ goto err_up;642661643662 memset(&resp, 0, sizeof resp);644663 resp.cq_handle = uobj->uobject.id;···643670 if (copy_to_user((void __user *) (unsigned long) cmd.response,644671 &resp, sizeof resp)) {645672 ret = -EFAULT;646646- goto err_list;673673+ goto err_idr;647674 }675675+676676+ down(&file->mutex);677677+ list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);678678+ up(&file->mutex);679679+680680+ up(&ib_uverbs_idr_mutex);648681649682 return in_len;650683651651-err_list:652652- down(&file->mutex);653653- list_del(&uobj->uobject.list);654654- up(&file->mutex);655655-656656- down(&ib_uverbs_idr_mutex);684684+err_idr:657685 idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);658658- up(&ib_uverbs_idr_mutex);659686660660-err_cq:687687+err_up:688688+ up(&ib_uverbs_idr_mutex);661689 ib_destroy_cq(cq);662690663691err:664692 kfree(uobj);693693+ return ret;694694+}695695+696696+ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,697697+ const char __user *buf, int in_len,698698+ int out_len)699699+{700700+ struct ib_uverbs_poll_cq cmd;701701+ struct ib_uverbs_poll_cq_resp *resp;702702+ struct ib_cq *cq;703703+ struct ib_wc *wc;704704+ int ret = 0;705705+ int i;706706+ int rsize;707707+708708+ if (copy_from_user(&cmd, buf, sizeof cmd))709709+ return -EFAULT;710710+711711+ wc = kmalloc(cmd.ne * sizeof *wc, GFP_KERNEL);712712+ if (!wc)713713+ return -ENOMEM;714714+715715+ rsize = sizeof *resp + cmd.ne * sizeof(struct ib_uverbs_wc);716716+ resp = kmalloc(rsize, GFP_KERNEL);717717+ if (!resp) {718718+ ret = -ENOMEM;719719+ goto out_wc;720720+ }721721+722722+ down(&ib_uverbs_idr_mutex);723723+ cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);724724+ if (!cq || cq->uobject->context != file->ucontext) {725725+ ret = -EINVAL;726726+ goto out;727727+ }728728+729729+ resp->count = ib_poll_cq(cq, cmd.ne, wc);730730+731731+ for (i = 0; i < resp->count; i++) {732732+ resp->wc[i].wr_id = wc[i].wr_id;733733+ resp->wc[i].status = wc[i].status;734734+ resp->wc[i].opcode = wc[i].opcode;735735+ resp->wc[i].vendor_err = wc[i].vendor_err;736736+ resp->wc[i].byte_len = wc[i].byte_len;737737+ resp->wc[i].imm_data = wc[i].imm_data;738738+ resp->wc[i].qp_num = wc[i].qp_num;739739+ resp->wc[i].src_qp = wc[i].src_qp;740740+ resp->wc[i].wc_flags = wc[i].wc_flags;741741+ resp->wc[i].pkey_index = wc[i].pkey_index;742742+ resp->wc[i].slid = wc[i].slid;743743+ resp->wc[i].sl = wc[i].sl;744744+ resp->wc[i].dlid_path_bits = wc[i].dlid_path_bits;745745+ resp->wc[i].port_num = wc[i].port_num;746746+ }747747+748748+ if (copy_to_user((void __user *) (unsigned long) cmd.response, resp, rsize))749749+ ret = -EFAULT;750750+751751+out:752752+ up(&ib_uverbs_idr_mutex);753753+ kfree(resp);754754+755755+out_wc:756756+ kfree(wc);757757+ return ret ? ret : in_len;758758+}759759+760760+ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,761761+ const char __user *buf, int in_len,762762+ int out_len)763763+{764764+ struct ib_uverbs_req_notify_cq cmd;765765+ struct ib_cq *cq;766766+ int ret = -EINVAL;767767+768768+ if (copy_from_user(&cmd, buf, sizeof cmd))769769+ return -EFAULT;770770+771771+ down(&ib_uverbs_idr_mutex);772772+ cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);773773+ if (cq && cq->uobject->context == file->ucontext) {774774+ ib_req_notify_cq(cq, cmd.solicited_only ?775775+ IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);776776+ ret = in_len;777777+ }778778+ up(&ib_uverbs_idr_mutex);779779+665780 return ret;666781}667782···761700 struct ib_uverbs_destroy_cq_resp resp;762701 struct ib_cq *cq;763702 struct ib_ucq_object *uobj;764764- struct ib_uverbs_event *evt, *tmp;703703+ struct ib_uverbs_event_file *ev_file;765704 u64 user_handle;766705 int ret = -EINVAL;767706···777716 goto out;778717779718 user_handle = cq->uobject->user_handle;780780- uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);719719+ uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);720720+ ev_file = cq->cq_context;781721782722 ret = ib_destroy_cq(cq);783723 if (ret)···790728 list_del(&uobj->uobject.list);791729 up(&file->mutex);792730793793- spin_lock_irq(&file->comp_file[0].lock);794794- list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {795795- list_del(&evt->list);796796- kfree(evt);797797- }798798- spin_unlock_irq(&file->comp_file[0].lock);799799-800800- spin_lock_irq(&file->async_file.lock);801801- list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {802802- list_del(&evt->list);803803- kfree(evt);804804- }805805- spin_unlock_irq(&file->async_file.lock);731731+ ib_uverbs_release_ucq(file, ev_file, uobj);806732807733 resp.comp_events_reported = uobj->comp_events_reported;808734 resp.async_events_reported = uobj->async_events_reported;···909859910860 resp.qp_handle = uobj->uobject.id;911861912912- down(&file->mutex);913913- list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);914914- up(&file->mutex);915915-916862 if (copy_to_user((void __user *) (unsigned long) cmd.response,917863 &resp, sizeof resp)) {918864 ret = -EFAULT;919919- goto err_list;865865+ goto err_idr;920866 }867867+868868+ down(&file->mutex);869869+ list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list);870870+ up(&file->mutex);921871922872 up(&ib_uverbs_idr_mutex);923873924874 return in_len;925875926926-err_list:927927- down(&file->mutex);928928- list_del(&uobj->uobject.list);929929- up(&file->mutex);876876+err_idr:877877+ idr_remove(&ib_uverbs_qp_idr, uobj->uobject.id);930878931879err_destroy:932880 ib_destroy_qp(qp);···1027979 struct ib_uverbs_destroy_qp_resp resp;1028980 struct ib_qp *qp;1029981 struct ib_uevent_object *uobj;10301030- struct ib_uverbs_event *evt, *tmp;1031982 int ret = -EINVAL;10329831033984 if (copy_from_user(&cmd, buf, sizeof cmd))···10521005 list_del(&uobj->uobject.list);10531006 up(&file->mutex);1054100710551055- spin_lock_irq(&file->async_file.lock);10561056- list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {10571057- list_del(&evt->list);10581058- kfree(evt);10591059- }10601060- spin_unlock_irq(&file->async_file.lock);10081008+ ib_uverbs_release_uevent(file, uobj);1061100910621010 resp.events_reported = uobj->events_reported;10631011···10611019 if (copy_to_user((void __user *) (unsigned long) cmd.response,10621020 &resp, sizeof resp))10631021 ret = -EFAULT;10221022+10231023+out:10241024+ up(&ib_uverbs_idr_mutex);10251025+10261026+ return ret ? ret : in_len;10271027+}10281028+10291029+ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,10301030+ const char __user *buf, int in_len,10311031+ int out_len)10321032+{10331033+ struct ib_uverbs_post_send cmd;10341034+ struct ib_uverbs_post_send_resp resp;10351035+ struct ib_uverbs_send_wr *user_wr;10361036+ struct ib_send_wr *wr = NULL, *last, *next, *bad_wr;10371037+ struct ib_qp *qp;10381038+ int i, sg_ind;10391039+ ssize_t ret = -EINVAL;10401040+10411041+ if (copy_from_user(&cmd, buf, sizeof cmd))10421042+ return -EFAULT;10431043+10441044+ if (in_len < sizeof cmd + cmd.wqe_size * cmd.wr_count +10451045+ cmd.sge_count * sizeof (struct ib_uverbs_sge))10461046+ return -EINVAL;10471047+10481048+ if (cmd.wqe_size < sizeof (struct ib_uverbs_send_wr))10491049+ return -EINVAL;10501050+10511051+ user_wr = kmalloc(cmd.wqe_size, GFP_KERNEL);10521052+ if (!user_wr)10531053+ return -ENOMEM;10541054+10551055+ down(&ib_uverbs_idr_mutex);10561056+10571057+ qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);10581058+ if (!qp || qp->uobject->context != file->ucontext)10591059+ goto out;10601060+10611061+ sg_ind = 0;10621062+ last = NULL;10631063+ for (i = 0; i < cmd.wr_count; ++i) {10641064+ if (copy_from_user(user_wr,10651065+ buf + sizeof cmd + i * cmd.wqe_size,10661066+ cmd.wqe_size)) {10671067+ ret = -EFAULT;10681068+ goto out;10691069+ }10701070+10711071+ if (user_wr->num_sge + sg_ind > cmd.sge_count) {10721072+ ret = -EINVAL;10731073+ goto out;10741074+ }10751075+10761076+ next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +10771077+ user_wr->num_sge * sizeof (struct ib_sge),10781078+ GFP_KERNEL);10791079+ if (!next) {10801080+ ret = -ENOMEM;10811081+ goto out;10821082+ }10831083+10841084+ if (!last)10851085+ wr = next;10861086+ else10871087+ last->next = next;10881088+ last = next;10891089+10901090+ next->next = NULL;10911091+ next->wr_id = user_wr->wr_id;10921092+ next->num_sge = user_wr->num_sge;10931093+ next->opcode = user_wr->opcode;10941094+ next->send_flags = user_wr->send_flags;10951095+ next->imm_data = user_wr->imm_data;10961096+10971097+ if (qp->qp_type == IB_QPT_UD) {10981098+ next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr,10991099+ user_wr->wr.ud.ah);11001100+ if (!next->wr.ud.ah) {11011101+ ret = -EINVAL;11021102+ goto out;11031103+ }11041104+ next->wr.ud.remote_qpn = user_wr->wr.ud.remote_qpn;11051105+ next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;11061106+ } else {11071107+ switch (next->opcode) {11081108+ case IB_WR_RDMA_WRITE:11091109+ case IB_WR_RDMA_WRITE_WITH_IMM:11101110+ case IB_WR_RDMA_READ:11111111+ next->wr.rdma.remote_addr =11121112+ user_wr->wr.rdma.remote_addr;11131113+ next->wr.rdma.rkey =11141114+ user_wr->wr.rdma.rkey;11151115+ break;11161116+ case IB_WR_ATOMIC_CMP_AND_SWP:11171117+ case IB_WR_ATOMIC_FETCH_AND_ADD:11181118+ next->wr.atomic.remote_addr =11191119+ user_wr->wr.atomic.remote_addr;11201120+ next->wr.atomic.compare_add =11211121+ user_wr->wr.atomic.compare_add;11221122+ next->wr.atomic.swap = user_wr->wr.atomic.swap;11231123+ next->wr.atomic.rkey = user_wr->wr.atomic.rkey;11241124+ break;11251125+ default:11261126+ break;11271127+ }11281128+ }11291129+11301130+ if (next->num_sge) {11311131+ next->sg_list = (void *) next +11321132+ ALIGN(sizeof *next, sizeof (struct ib_sge));11331133+ if (copy_from_user(next->sg_list,11341134+ buf + sizeof cmd +11351135+ cmd.wr_count * cmd.wqe_size +11361136+ sg_ind * sizeof (struct ib_sge),11371137+ next->num_sge * sizeof (struct ib_sge))) {11381138+ ret = -EFAULT;11391139+ goto out;11401140+ }11411141+ sg_ind += next->num_sge;11421142+ } else11431143+ next->sg_list = NULL;11441144+ }11451145+11461146+ resp.bad_wr = 0;11471147+ ret = qp->device->post_send(qp, wr, &bad_wr);11481148+ if (ret)11491149+ for (next = wr; next; next = next->next) {11501150+ ++resp.bad_wr;11511151+ if (next == bad_wr)11521152+ break;11531153+ }11541154+11551155+ if (copy_to_user((void __user *) (unsigned long) cmd.response,11561156+ &resp, sizeof resp))11571157+ ret = -EFAULT;11581158+11591159+out:11601160+ up(&ib_uverbs_idr_mutex);11611161+11621162+ while (wr) {11631163+ next = wr->next;11641164+ kfree(wr);11651165+ wr = next;11661166+ }11671167+11681168+ kfree(user_wr);11691169+11701170+ return ret ? ret : in_len;11711171+}11721172+11731173+static struct ib_recv_wr *ib_uverbs_unmarshall_recv(const char __user *buf,11741174+ int in_len,11751175+ u32 wr_count,11761176+ u32 sge_count,11771177+ u32 wqe_size)11781178+{11791179+ struct ib_uverbs_recv_wr *user_wr;11801180+ struct ib_recv_wr *wr = NULL, *last, *next;11811181+ int sg_ind;11821182+ int i;11831183+ int ret;11841184+11851185+ if (in_len < wqe_size * wr_count +11861186+ sge_count * sizeof (struct ib_uverbs_sge))11871187+ return ERR_PTR(-EINVAL);11881188+11891189+ if (wqe_size < sizeof (struct ib_uverbs_recv_wr))11901190+ return ERR_PTR(-EINVAL);11911191+11921192+ user_wr = kmalloc(wqe_size, GFP_KERNEL);11931193+ if (!user_wr)11941194+ return ERR_PTR(-ENOMEM);11951195+11961196+ sg_ind = 0;11971197+ last = NULL;11981198+ for (i = 0; i < wr_count; ++i) {11991199+ if (copy_from_user(user_wr, buf + i * wqe_size,12001200+ wqe_size)) {12011201+ ret = -EFAULT;12021202+ goto err;12031203+ }12041204+12051205+ if (user_wr->num_sge + sg_ind > sge_count) {12061206+ ret = -EINVAL;12071207+ goto err;12081208+ }12091209+12101210+ next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +12111211+ user_wr->num_sge * sizeof (struct ib_sge),12121212+ GFP_KERNEL);12131213+ if (!next) {12141214+ ret = -ENOMEM;12151215+ goto err;12161216+ }12171217+12181218+ if (!last)12191219+ wr = next;12201220+ else12211221+ last->next = next;12221222+ last = next;12231223+12241224+ next->next = NULL;12251225+ next->wr_id = user_wr->wr_id;12261226+ next->num_sge = user_wr->num_sge;12271227+12281228+ if (next->num_sge) {12291229+ next->sg_list = (void *) next +12301230+ ALIGN(sizeof *next, sizeof (struct ib_sge));12311231+ if (copy_from_user(next->sg_list,12321232+ buf + wr_count * wqe_size +12331233+ sg_ind * sizeof (struct ib_sge),12341234+ next->num_sge * sizeof (struct ib_sge))) {12351235+ ret = -EFAULT;12361236+ goto err;12371237+ }12381238+ sg_ind += next->num_sge;12391239+ } else12401240+ next->sg_list = NULL;12411241+ }12421242+12431243+ kfree(user_wr);12441244+ return wr;12451245+12461246+err:12471247+ kfree(user_wr);12481248+12491249+ while (wr) {12501250+ next = wr->next;12511251+ kfree(wr);12521252+ wr = next;12531253+ }12541254+12551255+ return ERR_PTR(ret);12561256+}12571257+12581258+ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,12591259+ const char __user *buf, int in_len,12601260+ int out_len)12611261+{12621262+ struct ib_uverbs_post_recv cmd;12631263+ struct ib_uverbs_post_recv_resp resp;12641264+ struct ib_recv_wr *wr, *next, *bad_wr;12651265+ struct ib_qp *qp;12661266+ ssize_t ret = -EINVAL;12671267+12681268+ if (copy_from_user(&cmd, buf, sizeof cmd))12691269+ return -EFAULT;12701270+12711271+ wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,12721272+ in_len - sizeof cmd, cmd.wr_count,12731273+ cmd.sge_count, cmd.wqe_size);12741274+ if (IS_ERR(wr))12751275+ return PTR_ERR(wr);12761276+12771277+ down(&ib_uverbs_idr_mutex);12781278+12791279+ qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);12801280+ if (!qp || qp->uobject->context != file->ucontext)12811281+ goto out;12821282+12831283+ resp.bad_wr = 0;12841284+ ret = qp->device->post_recv(qp, wr, &bad_wr);12851285+ if (ret)12861286+ for (next = wr; next; next = next->next) {12871287+ ++resp.bad_wr;12881288+ if (next == bad_wr)12891289+ break;12901290+ }12911291+12921292+12931293+ if (copy_to_user((void __user *) (unsigned long) cmd.response,12941294+ &resp, sizeof resp))12951295+ ret = -EFAULT;12961296+12971297+out:12981298+ up(&ib_uverbs_idr_mutex);12991299+13001300+ while (wr) {13011301+ next = wr->next;13021302+ kfree(wr);13031303+ wr = next;13041304+ }13051305+13061306+ return ret ? ret : in_len;13071307+}13081308+13091309+ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,13101310+ const char __user *buf, int in_len,13111311+ int out_len)13121312+{13131313+ struct ib_uverbs_post_srq_recv cmd;13141314+ struct ib_uverbs_post_srq_recv_resp resp;13151315+ struct ib_recv_wr *wr, *next, *bad_wr;13161316+ struct ib_srq *srq;13171317+ ssize_t ret = -EINVAL;13181318+13191319+ if (copy_from_user(&cmd, buf, sizeof cmd))13201320+ return -EFAULT;13211321+13221322+ wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,13231323+ in_len - sizeof cmd, cmd.wr_count,13241324+ cmd.sge_count, cmd.wqe_size);13251325+ if (IS_ERR(wr))13261326+ return PTR_ERR(wr);13271327+13281328+ down(&ib_uverbs_idr_mutex);13291329+13301330+ srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);13311331+ if (!srq || srq->uobject->context != file->ucontext)13321332+ goto out;13331333+13341334+ resp.bad_wr = 0;13351335+ ret = srq->device->post_srq_recv(srq, wr, &bad_wr);13361336+ if (ret)13371337+ for (next = wr; next; next = next->next) {13381338+ ++resp.bad_wr;13391339+ if (next == bad_wr)13401340+ break;13411341+ }13421342+13431343+13441344+ if (copy_to_user((void __user *) (unsigned long) cmd.response,13451345+ &resp, sizeof resp))13461346+ ret = -EFAULT;13471347+13481348+out:13491349+ up(&ib_uverbs_idr_mutex);13501350+13511351+ while (wr) {13521352+ next = wr->next;13531353+ kfree(wr);13541354+ wr = next;13551355+ }13561356+13571357+ return ret ? ret : in_len;13581358+}13591359+13601360+ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,13611361+ const char __user *buf, int in_len,13621362+ int out_len)13631363+{13641364+ struct ib_uverbs_create_ah cmd;13651365+ struct ib_uverbs_create_ah_resp resp;13661366+ struct ib_uobject *uobj;13671367+ struct ib_pd *pd;13681368+ struct ib_ah *ah;13691369+ struct ib_ah_attr attr;13701370+ int ret;13711371+13721372+ if (out_len < sizeof resp)13731373+ return -ENOSPC;13741374+13751375+ if (copy_from_user(&cmd, buf, sizeof cmd))13761376+ return -EFAULT;13771377+13781378+ uobj = kmalloc(sizeof *uobj, GFP_KERNEL);13791379+ if (!uobj)13801380+ return -ENOMEM;13811381+13821382+ down(&ib_uverbs_idr_mutex);13831383+13841384+ pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);13851385+ if (!pd || pd->uobject->context != file->ucontext) {13861386+ ret = -EINVAL;13871387+ goto err_up;13881388+ }13891389+13901390+ uobj->user_handle = cmd.user_handle;13911391+ uobj->context = file->ucontext;13921392+13931393+ attr.dlid = cmd.attr.dlid;13941394+ attr.sl = cmd.attr.sl;13951395+ attr.src_path_bits = cmd.attr.src_path_bits;13961396+ attr.static_rate = cmd.attr.static_rate;13971397+ attr.port_num = cmd.attr.port_num;13981398+ attr.grh.flow_label = cmd.attr.grh.flow_label;13991399+ attr.grh.sgid_index = cmd.attr.grh.sgid_index;14001400+ attr.grh.hop_limit = cmd.attr.grh.hop_limit;14011401+ attr.grh.traffic_class = cmd.attr.grh.traffic_class;14021402+ memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16);14031403+14041404+ ah = ib_create_ah(pd, &attr);14051405+ if (IS_ERR(ah)) {14061406+ ret = PTR_ERR(ah);14071407+ goto err_up;14081408+ }14091409+14101410+ ah->uobject = uobj;14111411+14121412+retry:14131413+ if (!idr_pre_get(&ib_uverbs_ah_idr, GFP_KERNEL)) {14141414+ ret = -ENOMEM;14151415+ goto err_destroy;14161416+ }14171417+14181418+ ret = idr_get_new(&ib_uverbs_ah_idr, ah, &uobj->id);14191419+14201420+ if (ret == -EAGAIN)14211421+ goto retry;14221422+ if (ret)14231423+ goto err_destroy;14241424+14251425+ resp.ah_handle = uobj->id;14261426+14271427+ if (copy_to_user((void __user *) (unsigned long) cmd.response,14281428+ &resp, sizeof resp)) {14291429+ ret = -EFAULT;14301430+ goto err_idr;14311431+ }14321432+14331433+ down(&file->mutex);14341434+ list_add_tail(&uobj->list, &file->ucontext->ah_list);14351435+ up(&file->mutex);14361436+14371437+ up(&ib_uverbs_idr_mutex);14381438+14391439+ return in_len;14401440+14411441+err_idr:14421442+ idr_remove(&ib_uverbs_ah_idr, uobj->id);14431443+14441444+err_destroy:14451445+ ib_destroy_ah(ah);14461446+14471447+err_up:14481448+ up(&ib_uverbs_idr_mutex);14491449+14501450+ kfree(uobj);14511451+ return ret;14521452+}14531453+14541454+ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,14551455+ const char __user *buf, int in_len, int out_len)14561456+{14571457+ struct ib_uverbs_destroy_ah cmd;14581458+ struct ib_ah *ah;14591459+ struct ib_uobject *uobj;14601460+ int ret = -EINVAL;14611461+14621462+ if (copy_from_user(&cmd, buf, sizeof cmd))14631463+ return -EFAULT;14641464+14651465+ down(&ib_uverbs_idr_mutex);14661466+14671467+ ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle);14681468+ if (!ah || ah->uobject->context != file->ucontext)14691469+ goto out;14701470+14711471+ uobj = ah->uobject;14721472+14731473+ ret = ib_destroy_ah(ah);14741474+ if (ret)14751475+ goto out;14761476+14771477+ idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle);14781478+14791479+ down(&file->mutex);14801480+ list_del(&uobj->list);14811481+ up(&file->mutex);14821482+14831483+ kfree(uobj);1064148410651485out:10661486 up(&ib_uverbs_idr_mutex);···1652114816531149 resp.srq_handle = uobj->uobject.id;1654115016551655- down(&file->mutex);16561656- list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);16571657- up(&file->mutex);16581658-16591151 if (copy_to_user((void __user *) (unsigned long) cmd.response,16601152 &resp, sizeof resp)) {16611153 ret = -EFAULT;16621662- goto err_list;11541154+ goto err_idr;16631155 }11561156+11571157+ down(&file->mutex);11581158+ list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);11591159+ up(&file->mutex);1664116016651161 up(&ib_uverbs_idr_mutex);1666116216671163 return in_len;1668116416691669-err_list:16701670- down(&file->mutex);16711671- list_del(&uobj->uobject.list);16721672- up(&file->mutex);11651165+err_idr:11661166+ idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id);1673116716741168err_destroy:16751169 ib_destroy_srq(srq);···17191217 struct ib_uverbs_destroy_srq_resp resp;17201218 struct ib_srq *srq;17211219 struct ib_uevent_object *uobj;17221722- struct ib_uverbs_event *evt, *tmp;17231220 int ret = -EINVAL;1724122117251222 if (copy_from_user(&cmd, buf, sizeof cmd))···17441243 list_del(&uobj->uobject.list);17451244 up(&file->mutex);1746124517471747- spin_lock_irq(&file->async_file.lock);17481748- list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {17491749- list_del(&evt->list);17501750- kfree(evt);17511751- }17521752- spin_unlock_irq(&file->async_file.lock);12461246+ ib_uverbs_release_uevent(file, uobj);1753124717541248 resp.events_reported = uobj->events_reported;17551249
+323-184
drivers/infiniband/core/uverbs_main.c
···33 * Copyright (c) 2005 Cisco Systems. All rights reserved.44 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.55 * Copyright (c) 2005 Voltaire, Inc. All rights reserved.66+ * Copyright (c) 2005 PathScale, Inc. All rights reserved.67 *78 * This software is available to you under a choice of one of two89 * licenses. You may choose to be licensed under the terms of the GNU···4443#include <linux/poll.h>4544#include <linux/file.h>4645#include <linux/mount.h>4646+#include <linux/cdev.h>47474848#include <asm/uaccess.h>4949···64626563#define IB_UVERBS_BASE_DEV MKDEV(IB_UVERBS_MAJOR, IB_UVERBS_BASE_MINOR)66646565+static struct class *uverbs_class;6666+6767DECLARE_MUTEX(ib_uverbs_idr_mutex);6868DEFINE_IDR(ib_uverbs_pd_idr);6969DEFINE_IDR(ib_uverbs_mr_idr);···7672DEFINE_IDR(ib_uverbs_srq_idr);77737874static spinlock_t map_lock;7575+static struct ib_uverbs_device *dev_table[IB_UVERBS_MAX_DEVICES];7976static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);80778178static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,8279 const char __user *buf, int in_len,8380 int out_len) = {8484- [IB_USER_VERBS_CMD_QUERY_PARAMS] = ib_uverbs_query_params,8585- [IB_USER_VERBS_CMD_GET_CONTEXT] = ib_uverbs_get_context,8686- [IB_USER_VERBS_CMD_QUERY_DEVICE] = ib_uverbs_query_device,8787- [IB_USER_VERBS_CMD_QUERY_PORT] = ib_uverbs_query_port,8888- [IB_USER_VERBS_CMD_QUERY_GID] = ib_uverbs_query_gid,8989- [IB_USER_VERBS_CMD_QUERY_PKEY] = ib_uverbs_query_pkey,9090- [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd,9191- [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd,9292- [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr,9393- [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr,9494- [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq,9595- [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq,9696- [IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp,9797- [IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp,9898- [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp,9999- [IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast,100100- [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast,101101- [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq,102102- [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,103103- [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,8181+ [IB_USER_VERBS_CMD_GET_CONTEXT] = ib_uverbs_get_context,8282+ [IB_USER_VERBS_CMD_QUERY_DEVICE] = ib_uverbs_query_device,8383+ [IB_USER_VERBS_CMD_QUERY_PORT] = ib_uverbs_query_port,8484+ [IB_USER_VERBS_CMD_ALLOC_PD] = ib_uverbs_alloc_pd,8585+ [IB_USER_VERBS_CMD_DEALLOC_PD] = ib_uverbs_dealloc_pd,8686+ [IB_USER_VERBS_CMD_REG_MR] = ib_uverbs_reg_mr,8787+ [IB_USER_VERBS_CMD_DEREG_MR] = ib_uverbs_dereg_mr,8888+ [IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL] = ib_uverbs_create_comp_channel,8989+ [IB_USER_VERBS_CMD_CREATE_CQ] = ib_uverbs_create_cq,9090+ [IB_USER_VERBS_CMD_POLL_CQ] = ib_uverbs_poll_cq,9191+ [IB_USER_VERBS_CMD_REQ_NOTIFY_CQ] = ib_uverbs_req_notify_cq,9292+ [IB_USER_VERBS_CMD_DESTROY_CQ] = ib_uverbs_destroy_cq,9393+ [IB_USER_VERBS_CMD_CREATE_QP] = ib_uverbs_create_qp,9494+ [IB_USER_VERBS_CMD_MODIFY_QP] = ib_uverbs_modify_qp,9595+ [IB_USER_VERBS_CMD_DESTROY_QP] = ib_uverbs_destroy_qp,9696+ [IB_USER_VERBS_CMD_POST_SEND] = ib_uverbs_post_send,9797+ [IB_USER_VERBS_CMD_POST_RECV] = ib_uverbs_post_recv,9898+ [IB_USER_VERBS_CMD_POST_SRQ_RECV] = ib_uverbs_post_srq_recv,9999+ [IB_USER_VERBS_CMD_CREATE_AH] = ib_uverbs_create_ah,100100+ [IB_USER_VERBS_CMD_DESTROY_AH] = ib_uverbs_destroy_ah,101101+ [IB_USER_VERBS_CMD_ATTACH_MCAST] = ib_uverbs_attach_mcast,102102+ [IB_USER_VERBS_CMD_DETACH_MCAST] = ib_uverbs_detach_mcast,103103+ [IB_USER_VERBS_CMD_CREATE_SRQ] = ib_uverbs_create_srq,104104+ [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,105105+ [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,104106};105107106108static struct vfsmount *uverbs_event_mnt;···114104static void ib_uverbs_add_one(struct ib_device *device);115105static void ib_uverbs_remove_one(struct ib_device *device);116106117117-static int ib_dealloc_ucontext(struct ib_ucontext *context)107107+static void ib_uverbs_release_dev(struct kref *ref)108108+{109109+ struct ib_uverbs_device *dev =110110+ container_of(ref, struct ib_uverbs_device, ref);111111+112112+ kfree(dev);113113+}114114+115115+void ib_uverbs_release_ucq(struct ib_uverbs_file *file,116116+ struct ib_uverbs_event_file *ev_file,117117+ struct ib_ucq_object *uobj)118118+{119119+ struct ib_uverbs_event *evt, *tmp;120120+121121+ if (ev_file) {122122+ spin_lock_irq(&ev_file->lock);123123+ list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) {124124+ list_del(&evt->list);125125+ kfree(evt);126126+ }127127+ spin_unlock_irq(&ev_file->lock);128128+129129+ kref_put(&ev_file->ref, ib_uverbs_release_event_file);130130+ }131131+132132+ spin_lock_irq(&file->async_file->lock);133133+ list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) {134134+ list_del(&evt->list);135135+ kfree(evt);136136+ }137137+ spin_unlock_irq(&file->async_file->lock);138138+}139139+140140+void ib_uverbs_release_uevent(struct ib_uverbs_file *file,141141+ struct ib_uevent_object *uobj)142142+{143143+ struct ib_uverbs_event *evt, *tmp;144144+145145+ spin_lock_irq(&file->async_file->lock);146146+ list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) {147147+ list_del(&evt->list);148148+ kfree(evt);149149+ }150150+ spin_unlock_irq(&file->async_file->lock);151151+}152152+153153+static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,154154+ struct ib_ucontext *context)118155{119156 struct ib_uobject *uobj, *tmp;120157···170113171114 down(&ib_uverbs_idr_mutex);172115173173- /* XXX Free AHs */116116+ list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {117117+ struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id);118118+ idr_remove(&ib_uverbs_ah_idr, uobj->id);119119+ ib_destroy_ah(ah);120120+ list_del(&uobj->list);121121+ kfree(uobj);122122+ }174123175124 list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {176125 struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id);126126+ struct ib_uevent_object *uevent =127127+ container_of(uobj, struct ib_uevent_object, uobject);177128 idr_remove(&ib_uverbs_qp_idr, uobj->id);178129 ib_destroy_qp(qp);179130 list_del(&uobj->list);180180- kfree(container_of(uobj, struct ib_uevent_object, uobject));131131+ ib_uverbs_release_uevent(file, uevent);132132+ kfree(uevent);181133 }182134183135 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {184136 struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id);137137+ struct ib_uverbs_event_file *ev_file = cq->cq_context;138138+ struct ib_ucq_object *ucq =139139+ container_of(uobj, struct ib_ucq_object, uobject);185140 idr_remove(&ib_uverbs_cq_idr, uobj->id);186141 ib_destroy_cq(cq);187142 list_del(&uobj->list);188188- kfree(container_of(uobj, struct ib_ucq_object, uobject));143143+ ib_uverbs_release_ucq(file, ev_file, ucq);144144+ kfree(ucq);189145 }190146191147 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {192148 struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);149149+ struct ib_uevent_object *uevent =150150+ container_of(uobj, struct ib_uevent_object, uobject);193151 idr_remove(&ib_uverbs_srq_idr, uobj->id);194152 ib_destroy_srq(srq);195153 list_del(&uobj->list);196196- kfree(container_of(uobj, struct ib_uevent_object, uobject));154154+ ib_uverbs_release_uevent(file, uevent);155155+ kfree(uevent);197156 }198157199158 /* XXX Free MWs */···248175 container_of(ref, struct ib_uverbs_file, ref);249176250177 module_put(file->device->ib_dev->owner);178178+ kref_put(&file->device->ref, ib_uverbs_release_dev);179179+251180 kfree(file);252181}253182···263188264189 spin_lock_irq(&file->lock);265190266266- while (list_empty(&file->event_list) && file->fd >= 0) {191191+ while (list_empty(&file->event_list)) {267192 spin_unlock_irq(&file->lock);268193269194 if (filp->f_flags & O_NONBLOCK)270195 return -EAGAIN;271196272197 if (wait_event_interruptible(file->poll_wait,273273- !list_empty(&file->event_list) ||274274- file->fd < 0))198198+ !list_empty(&file->event_list)))275199 return -ERESTARTSYS;276200277201 spin_lock_irq(&file->lock);278278- }279279-280280- if (file->fd < 0) {281281- spin_unlock_irq(&file->lock);282282- return -ENODEV;283202 }284203285204 event = list_entry(file->event_list.next, struct ib_uverbs_event, list);···317248 poll_wait(filp, &file->poll_wait, wait);318249319250 spin_lock_irq(&file->lock);320320- if (file->fd < 0)321321- pollflags = POLLERR;322322- else if (!list_empty(&file->event_list))251251+ if (!list_empty(&file->event_list))323252 pollflags = POLLIN | POLLRDNORM;324253 spin_unlock_irq(&file->lock);325254326255 return pollflags;327256}328257329329-static void ib_uverbs_event_release(struct ib_uverbs_event_file *file)258258+void ib_uverbs_release_event_file(struct kref *ref)330259{331331- struct ib_uverbs_event *entry, *tmp;260260+ struct ib_uverbs_event_file *file =261261+ container_of(ref, struct ib_uverbs_event_file, ref);332262333333- spin_lock_irq(&file->lock);334334- if (file->fd != -1) {335335- file->fd = -1;336336- list_for_each_entry_safe(entry, tmp, &file->event_list, list)337337- kfree(entry);338338- }339339- spin_unlock_irq(&file->lock);263263+ kfree(file);340264}341265342266static int ib_uverbs_event_fasync(int fd, struct file *filp, int on)···342280static int ib_uverbs_event_close(struct inode *inode, struct file *filp)343281{344282 struct ib_uverbs_event_file *file = filp->private_data;283283+ struct ib_uverbs_event *entry, *tmp;345284346346- ib_uverbs_event_release(file);285285+ spin_lock_irq(&file->lock);286286+ file->file = NULL;287287+ list_for_each_entry_safe(entry, tmp, &file->event_list, list) {288288+ if (entry->counter)289289+ list_del(&entry->obj_list);290290+ kfree(entry);291291+ }292292+ spin_unlock_irq(&file->lock);293293+347294 ib_uverbs_event_fasync(-1, filp, 0);348348- kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);295295+296296+ if (file->is_async) {297297+ ib_unregister_event_handler(&file->uverbs_file->event_handler);298298+ kref_put(&file->uverbs_file->ref, ib_uverbs_release_file);299299+ }300300+ kref_put(&file->ref, ib_uverbs_release_event_file);349301350302 return 0;351303}352304353305static struct file_operations uverbs_event_fops = {354354- /*355355- * No .owner field since we artificially create event files,356356- * so there is no increment to the module reference count in357357- * the open path. All event files come from a uverbs command358358- * file, which already takes a module reference, so this is OK.359359- */306306+ .owner = THIS_MODULE,360307 .read = ib_uverbs_event_read,361308 .poll = ib_uverbs_event_poll,362309 .release = ib_uverbs_event_close,···374303375304void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)376305{377377- struct ib_uverbs_file *file = cq_context;378378- struct ib_ucq_object *uobj;379379- struct ib_uverbs_event *entry;380380- unsigned long flags;306306+ struct ib_uverbs_event_file *file = cq_context;307307+ struct ib_ucq_object *uobj;308308+ struct ib_uverbs_event *entry;309309+ unsigned long flags;310310+311311+ if (!file)312312+ return;313313+314314+ spin_lock_irqsave(&file->lock, flags);315315+ if (!file->file) {316316+ spin_unlock_irqrestore(&file->lock, flags);317317+ return;318318+ }381319382320 entry = kmalloc(sizeof *entry, GFP_ATOMIC);383383- if (!entry)321321+ if (!entry) {322322+ spin_unlock_irqrestore(&file->lock, flags);384323 return;324324+ }385325386326 uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);387327388328 entry->desc.comp.cq_handle = cq->uobject->user_handle;389329 entry->counter = &uobj->comp_events_reported;390330391391- spin_lock_irqsave(&file->comp_file[0].lock, flags);392392- list_add_tail(&entry->list, &file->comp_file[0].event_list);331331+ list_add_tail(&entry->list, &file->event_list);393332 list_add_tail(&entry->obj_list, &uobj->comp_list);394394- spin_unlock_irqrestore(&file->comp_file[0].lock, flags);333333+ spin_unlock_irqrestore(&file->lock, flags);395334396396- wake_up_interruptible(&file->comp_file[0].poll_wait);397397- kill_fasync(&file->comp_file[0].async_queue, SIGIO, POLL_IN);335335+ wake_up_interruptible(&file->poll_wait);336336+ kill_fasync(&file->async_queue, SIGIO, POLL_IN);398337}399338400339static void ib_uverbs_async_handler(struct ib_uverbs_file *file,···415334 struct ib_uverbs_event *entry;416335 unsigned long flags;417336418418- entry = kmalloc(sizeof *entry, GFP_ATOMIC);419419- if (!entry)337337+ spin_lock_irqsave(&file->async_file->lock, flags);338338+ if (!file->async_file->file) {339339+ spin_unlock_irqrestore(&file->async_file->lock, flags);420340 return;341341+ }342342+343343+ entry = kmalloc(sizeof *entry, GFP_ATOMIC);344344+ if (!entry) {345345+ spin_unlock_irqrestore(&file->async_file->lock, flags);346346+ return;347347+ }421348422349 entry->desc.async.element = element;423350 entry->desc.async.event_type = event;424351 entry->counter = counter;425352426426- spin_lock_irqsave(&file->async_file.lock, flags);427427- list_add_tail(&entry->list, &file->async_file.event_list);353353+ list_add_tail(&entry->list, &file->async_file->event_list);428354 if (obj_list)429355 list_add_tail(&entry->obj_list, obj_list);430430- spin_unlock_irqrestore(&file->async_file.lock, flags);356356+ spin_unlock_irqrestore(&file->async_file->lock, flags);431357432432- wake_up_interruptible(&file->async_file.poll_wait);433433- kill_fasync(&file->async_file.async_queue, SIGIO, POLL_IN);358358+ wake_up_interruptible(&file->async_file->poll_wait);359359+ kill_fasync(&file->async_file->async_queue, SIGIO, POLL_IN);434360}435361436362void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)437363{364364+ struct ib_uverbs_event_file *ev_file = context_ptr;438365 struct ib_ucq_object *uobj;439366440367 uobj = container_of(event->element.cq->uobject,441368 struct ib_ucq_object, uobject);442369443443- ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,370370+ ib_uverbs_async_handler(ev_file->uverbs_file, uobj->uobject.user_handle,444371 event->event, &uobj->async_list,445372 &uobj->async_events_reported);446373···478389 &uobj->events_reported);479390}480391481481-static void ib_uverbs_event_handler(struct ib_event_handler *handler,482482- struct ib_event *event)392392+void ib_uverbs_event_handler(struct ib_event_handler *handler,393393+ struct ib_event *event)483394{484395 struct ib_uverbs_file *file =485396 container_of(handler, struct ib_uverbs_file, event_handler);···488399 NULL, NULL);489400}490401491491-static int ib_uverbs_event_init(struct ib_uverbs_event_file *file,492492- struct ib_uverbs_file *uverbs_file)402402+struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,403403+ int is_async, int *fd)493404{405405+ struct ib_uverbs_event_file *ev_file;494406 struct file *filp;407407+ int ret;495408496496- spin_lock_init(&file->lock);497497- INIT_LIST_HEAD(&file->event_list);498498- init_waitqueue_head(&file->poll_wait);499499- file->uverbs_file = uverbs_file;500500- file->async_queue = NULL;409409+ ev_file = kmalloc(sizeof *ev_file, GFP_KERNEL);410410+ if (!ev_file)411411+ return ERR_PTR(-ENOMEM);501412502502- file->fd = get_unused_fd();503503- if (file->fd < 0)504504- return file->fd;413413+ kref_init(&ev_file->ref);414414+ spin_lock_init(&ev_file->lock);415415+ INIT_LIST_HEAD(&ev_file->event_list);416416+ init_waitqueue_head(&ev_file->poll_wait);417417+ ev_file->uverbs_file = uverbs_file;418418+ ev_file->async_queue = NULL;419419+ ev_file->is_async = is_async;420420+421421+ *fd = get_unused_fd();422422+ if (*fd < 0) {423423+ ret = *fd;424424+ goto err;425425+ }505426506427 filp = get_empty_filp();507428 if (!filp) {508508- put_unused_fd(file->fd);509509- return -ENFILE;429429+ ret = -ENFILE;430430+ goto err_fd;510431 }511432512512- filp->f_op = &uverbs_event_fops;433433+ ev_file->file = filp;434434+435435+ /*436436+ * fops_get() can't fail here, because we're coming from a437437+ * system call on a uverbs file, which will already have a438438+ * module reference.439439+ */440440+ filp->f_op = fops_get(&uverbs_event_fops);513441 filp->f_vfsmnt = mntget(uverbs_event_mnt);514442 filp->f_dentry = dget(uverbs_event_mnt->mnt_root);515443 filp->f_mapping = filp->f_dentry->d_inode->i_mapping;516444 filp->f_flags = O_RDONLY;517445 filp->f_mode = FMODE_READ;518518- filp->private_data = file;446446+ filp->private_data = ev_file;519447520520- fd_install(file->fd, filp);448448+ return filp;521449522522- return 0;450450+err_fd:451451+ put_unused_fd(*fd);452452+453453+err:454454+ kfree(ev_file);455455+ return ERR_PTR(ret);456456+}457457+458458+/*459459+ * Look up a completion event file by FD. If lookup is successful,460460+ * takes a ref to the event file struct that it returns; if461461+ * unsuccessful, returns NULL.462462+ */463463+struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd)464464+{465465+ struct ib_uverbs_event_file *ev_file = NULL;466466+ struct file *filp;467467+468468+ filp = fget(fd);469469+ if (!filp)470470+ return NULL;471471+472472+ if (filp->f_op != &uverbs_event_fops)473473+ goto out;474474+475475+ ev_file = filp->private_data;476476+ if (ev_file->is_async) {477477+ ev_file = NULL;478478+ goto out;479479+ }480480+481481+ kref_get(&ev_file->ref);482482+483483+out:484484+ fput(filp);485485+ return ev_file;523486}524487525488static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,···591450592451 if (hdr.command < 0 ||593452 hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||594594- !uverbs_cmd_table[hdr.command])453453+ !uverbs_cmd_table[hdr.command] ||454454+ !(file->device->ib_dev->uverbs_cmd_mask & (1ull << hdr.command)))595455 return -EINVAL;596456597597- if (!file->ucontext &&598598- hdr.command != IB_USER_VERBS_CMD_QUERY_PARAMS &&457457+ if (!file->ucontext &&599458 hdr.command != IB_USER_VERBS_CMD_GET_CONTEXT)600459 return -EINVAL;601460···615474616475static int ib_uverbs_open(struct inode *inode, struct file *filp)617476{618618- struct ib_uverbs_device *dev =619619- container_of(inode->i_cdev, struct ib_uverbs_device, dev);477477+ struct ib_uverbs_device *dev;620478 struct ib_uverbs_file *file;621621- int i = 0;622479 int ret;623480624624- if (!try_module_get(dev->ib_dev->owner))625625- return -ENODEV;481481+ spin_lock(&map_lock);482482+ dev = dev_table[iminor(inode) - IB_UVERBS_BASE_MINOR];483483+ if (dev)484484+ kref_get(&dev->ref);485485+ spin_unlock(&map_lock);626486627627- file = kmalloc(sizeof *file +628628- (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file),629629- GFP_KERNEL);630630- if (!file) {631631- ret = -ENOMEM;487487+ if (!dev)488488+ return -ENXIO;489489+490490+ if (!try_module_get(dev->ib_dev->owner)) {491491+ ret = -ENODEV;632492 goto err;633493 }634494635635- file->device = dev;495495+ file = kmalloc(sizeof *file, GFP_KERNEL);496496+ if (!file) {497497+ ret = -ENOMEM;498498+ goto err_module;499499+ }500500+501501+ file->device = dev;502502+ file->ucontext = NULL;503503+ file->async_file = NULL;636504 kref_init(&file->ref);637505 init_MUTEX(&file->mutex);638506639639- file->ucontext = NULL;640640-641641- kref_get(&file->ref);642642- ret = ib_uverbs_event_init(&file->async_file, file);643643- if (ret)644644- goto err_kref;645645-646646- file->async_file.is_async = 1;647647-648648- for (i = 0; i < dev->num_comp; ++i) {649649- kref_get(&file->ref);650650- ret = ib_uverbs_event_init(&file->comp_file[i], file);651651- if (ret)652652- goto err_async;653653- file->comp_file[i].is_async = 0;654654- }655655-656656-657507 filp->private_data = file;658658-659659- INIT_IB_EVENT_HANDLER(&file->event_handler, dev->ib_dev,660660- ib_uverbs_event_handler);661661- if (ib_register_event_handler(&file->event_handler))662662- goto err_async;663508664509 return 0;665510666666-err_async:667667- while (i--)668668- ib_uverbs_event_release(&file->comp_file[i]);669669-670670- ib_uverbs_event_release(&file->async_file);671671-672672-err_kref:673673- /*674674- * One extra kref_put() because we took a reference before the675675- * event file creation that failed and got us here.676676- */677677- kref_put(&file->ref, ib_uverbs_release_file);678678- kref_put(&file->ref, ib_uverbs_release_file);511511+err_module:512512+ module_put(dev->ib_dev->owner);679513680514err:681681- module_put(dev->ib_dev->owner);515515+ kref_put(&dev->ref, ib_uverbs_release_dev);516516+682517 return ret;683518}684519685520static int ib_uverbs_close(struct inode *inode, struct file *filp)686521{687522 struct ib_uverbs_file *file = filp->private_data;688688- int i;689523690690- ib_unregister_event_handler(&file->event_handler);691691- ib_uverbs_event_release(&file->async_file);692692- ib_dealloc_ucontext(file->ucontext);524524+ ib_uverbs_cleanup_ucontext(file, file->ucontext);693525694694- for (i = 0; i < file->device->num_comp; ++i)695695- ib_uverbs_event_release(&file->comp_file[i]);526526+ if (file->async_file)527527+ kref_put(&file->async_file->ref, ib_uverbs_release_event_file);696528697529 kref_put(&file->ref, ib_uverbs_release_file);698530···695581696582static ssize_t show_ibdev(struct class_device *class_dev, char *buf)697583{698698- struct ib_uverbs_device *dev =699699- container_of(class_dev, struct ib_uverbs_device, class_dev);584584+ struct ib_uverbs_device *dev = class_get_devdata(class_dev);585585+586586+ if (!dev)587587+ return -ENODEV;700588701589 return sprintf(buf, "%s\n", dev->ib_dev->name);702590}703591static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);704592705705-static void ib_uverbs_release_class_dev(struct class_device *class_dev)593593+static ssize_t show_dev_abi_version(struct class_device *class_dev, char *buf)706594{707707- struct ib_uverbs_device *dev =708708- container_of(class_dev, struct ib_uverbs_device, class_dev);595595+ struct ib_uverbs_device *dev = class_get_devdata(class_dev);709596710710- cdev_del(&dev->dev);711711- clear_bit(dev->devnum, dev_map);712712- kfree(dev);597597+ if (!dev)598598+ return -ENODEV;599599+600600+ return sprintf(buf, "%d\n", dev->ib_dev->uverbs_abi_ver);713601}714714-715715-static struct class uverbs_class = {716716- .name = "infiniband_verbs",717717- .release = ib_uverbs_release_class_dev718718-};602602+static CLASS_DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);719603720604static ssize_t show_abi_version(struct class *class, char *buf)721605{···734622735623 memset(uverbs_dev, 0, sizeof *uverbs_dev);736624625625+ kref_init(&uverbs_dev->ref);626626+737627 spin_lock(&map_lock);738628 uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);739629 if (uverbs_dev->devnum >= IB_UVERBS_MAX_DEVICES) {···745631 set_bit(uverbs_dev->devnum, dev_map);746632 spin_unlock(&map_lock);747633748748- uverbs_dev->ib_dev = device;749749- uverbs_dev->num_comp = 1;634634+ uverbs_dev->ib_dev = device;635635+ uverbs_dev->num_comp_vectors = 1;750636751751- if (device->mmap)752752- cdev_init(&uverbs_dev->dev, &uverbs_mmap_fops);753753- else754754- cdev_init(&uverbs_dev->dev, &uverbs_fops);755755- uverbs_dev->dev.owner = THIS_MODULE;756756- kobject_set_name(&uverbs_dev->dev.kobj, "uverbs%d", uverbs_dev->devnum);757757- if (cdev_add(&uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))637637+ uverbs_dev->dev = cdev_alloc();638638+ if (!uverbs_dev->dev)758639 goto err;759759-760760- uverbs_dev->class_dev.class = &uverbs_class;761761- uverbs_dev->class_dev.dev = device->dma_device;762762- uverbs_dev->class_dev.devt = uverbs_dev->dev.dev;763763- snprintf(uverbs_dev->class_dev.class_id, BUS_ID_SIZE, "uverbs%d", uverbs_dev->devnum);764764- if (class_device_register(&uverbs_dev->class_dev))640640+ uverbs_dev->dev->owner = THIS_MODULE;641641+ uverbs_dev->dev->ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;642642+ kobject_set_name(&uverbs_dev->dev->kobj, "uverbs%d", uverbs_dev->devnum);643643+ if (cdev_add(uverbs_dev->dev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))765644 goto err_cdev;766645767767- if (class_device_create_file(&uverbs_dev->class_dev, &class_device_attr_ibdev))646646+ uverbs_dev->class_dev = class_device_create(uverbs_class, NULL,647647+ uverbs_dev->dev->dev,648648+ device->dma_device,649649+ "uverbs%d", uverbs_dev->devnum);650650+ if (IS_ERR(uverbs_dev->class_dev))651651+ goto err_cdev;652652+653653+ class_set_devdata(uverbs_dev->class_dev, uverbs_dev);654654+655655+ if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_ibdev))768656 goto err_class;657657+ if (class_device_create_file(uverbs_dev->class_dev, &class_device_attr_abi_version))658658+ goto err_class;659659+660660+ spin_lock(&map_lock);661661+ dev_table[uverbs_dev->devnum] = uverbs_dev;662662+ spin_unlock(&map_lock);769663770664 ib_set_client_data(device, &uverbs_client, uverbs_dev);771665772666 return;773667774668err_class:775775- class_device_unregister(&uverbs_dev->class_dev);669669+ class_device_destroy(uverbs_class, uverbs_dev->dev->dev);776670777671err_cdev:778778- cdev_del(&uverbs_dev->dev);672672+ cdev_del(uverbs_dev->dev);779673 clear_bit(uverbs_dev->devnum, dev_map);780674781675err:782782- kfree(uverbs_dev);676676+ kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);783677 return;784678}785679···798676 if (!uverbs_dev)799677 return;800678801801- class_device_unregister(&uverbs_dev->class_dev);679679+ class_set_devdata(uverbs_dev->class_dev, NULL);680680+ class_device_destroy(uverbs_class, uverbs_dev->dev->dev);681681+ cdev_del(uverbs_dev->dev);682682+683683+ spin_lock(&map_lock);684684+ dev_table[uverbs_dev->devnum] = NULL;685685+ spin_unlock(&map_lock);686686+687687+ clear_bit(uverbs_dev->devnum, dev_map);688688+ kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);802689}803690804691static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags,···837706 goto out;838707 }839708840840- ret = class_register(&uverbs_class);841841- if (ret) {709709+ uverbs_class = class_create(THIS_MODULE, "infiniband_verbs");710710+ if (IS_ERR(uverbs_class)) {711711+ ret = PTR_ERR(uverbs_class);842712 printk(KERN_ERR "user_verbs: couldn't create class infiniband_verbs\n");843713 goto out_chrdev;844714 }845715846846- ret = class_create_file(&uverbs_class, &class_attr_abi_version);716716+ ret = class_create_file(uverbs_class, &class_attr_abi_version);847717 if (ret) {848718 printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n");849719 goto out_class;···878746 unregister_filesystem(&uverbs_event_fs);879747880748out_class:881881- class_unregister(&uverbs_class);749749+ class_destroy(uverbs_class);882750883751out_chrdev:884752 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);···892760 ib_unregister_client(&uverbs_client);893761 mntput(uverbs_event_mnt);894762 unregister_filesystem(&uverbs_event_fs);895895- class_unregister(&uverbs_class);763763+ class_destroy(uverbs_class);896764 unregister_chrdev_region(IB_UVERBS_BASE_DEV, IB_UVERBS_MAX_DEVICES);765765+ idr_destroy(&ib_uverbs_pd_idr);766766+ idr_destroy(&ib_uverbs_mr_idr);767767+ idr_destroy(&ib_uverbs_mw_idr);768768+ idr_destroy(&ib_uverbs_ah_idr);769769+ idr_destroy(&ib_uverbs_cq_idr);770770+ idr_destroy(&ib_uverbs_qp_idr);771771+ idr_destroy(&ib_uverbs_srq_idr);897772}898773899774module_init(ib_uverbs_init);
···11+/*22+ * Copyright (c) 2005 Cisco Systems. All rights reserved.33+ *44+ * This software is available to you under a choice of one of two55+ * licenses. You may choose to be licensed under the terms of the GNU66+ * General Public License (GPL) Version 2, available from the file77+ * COPYING in the main directory of this source tree, or the88+ * OpenIB.org BSD license below:99+ *1010+ * Redistribution and use in source and binary forms, with or1111+ * without modification, are permitted provided that the following1212+ * conditions are met:1313+ *1414+ * - Redistributions of source code must retain the above1515+ * copyright notice, this list of conditions and the following1616+ * disclaimer.1717+ *1818+ * - Redistributions in binary form must reproduce the above1919+ * copyright notice, this list of conditions and the following2020+ * disclaimer in the documentation and/or other materials2121+ * provided with the distribution.2222+ *2323+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,2424+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF2525+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND2626+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS2727+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN2828+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN2929+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE3030+ * SOFTWARE.3131+ *3232+ * $Id$3333+ */3434+3535+#include "mthca_dev.h"3636+3737+enum {3838+ MTHCA_CATAS_POLL_INTERVAL = 5 * HZ,3939+4040+ MTHCA_CATAS_TYPE_INTERNAL = 0,4141+ MTHCA_CATAS_TYPE_UPLINK = 3,4242+ MTHCA_CATAS_TYPE_DDR = 4,4343+ MTHCA_CATAS_TYPE_PARITY = 5,4444+};4545+4646+static DEFINE_SPINLOCK(catas_lock);4747+4848+static void handle_catas(struct mthca_dev *dev)4949+{5050+ struct ib_event event;5151+ const char *type;5252+ int i;5353+5454+ event.device = &dev->ib_dev;5555+ event.event = IB_EVENT_DEVICE_FATAL;5656+ event.element.port_num = 0;5757+5858+ ib_dispatch_event(&event);5959+6060+ switch (swab32(readl(dev->catas_err.map)) >> 24) {6161+ case MTHCA_CATAS_TYPE_INTERNAL:6262+ type = "internal error";6363+ break;6464+ case MTHCA_CATAS_TYPE_UPLINK:6565+ type = "uplink bus error";6666+ break;6767+ case MTHCA_CATAS_TYPE_DDR:6868+ type = "DDR data error";6969+ break;7070+ case MTHCA_CATAS_TYPE_PARITY:7171+ type = "internal parity error";7272+ break;7373+ default:7474+ type = "unknown error";7575+ break;7676+ }7777+7878+ mthca_err(dev, "Catastrophic error detected: %s\n", type);7979+ for (i = 0; i < dev->catas_err.size; ++i)8080+ mthca_err(dev, " buf[%02x]: %08x\n",8181+ i, swab32(readl(dev->catas_err.map + i)));8282+}8383+8484+static void poll_catas(unsigned long dev_ptr)8585+{8686+ struct mthca_dev *dev = (struct mthca_dev *) dev_ptr;8787+ unsigned long flags;8888+ int i;8989+9090+ for (i = 0; i < dev->catas_err.size; ++i)9191+ if (readl(dev->catas_err.map + i)) {9292+ handle_catas(dev);9393+ return;9494+ }9595+9696+ spin_lock_irqsave(&catas_lock, flags);9797+ if (dev->catas_err.stop)9898+ mod_timer(&dev->catas_err.timer,9999+ jiffies + MTHCA_CATAS_POLL_INTERVAL);100100+ spin_unlock_irqrestore(&catas_lock, flags);101101+102102+ return;103103+}104104+105105+void mthca_start_catas_poll(struct mthca_dev *dev)106106+{107107+ unsigned long addr;108108+109109+ init_timer(&dev->catas_err.timer);110110+ dev->catas_err.stop = 0;111111+ dev->catas_err.map = NULL;112112+113113+ addr = pci_resource_start(dev->pdev, 0) +114114+ ((pci_resource_len(dev->pdev, 0) - 1) &115115+ dev->catas_err.addr);116116+117117+ if (!request_mem_region(addr, dev->catas_err.size * 4,118118+ DRV_NAME)) {119119+ mthca_warn(dev, "couldn't request catastrophic error region "120120+ "at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4);121121+ return;122122+ }123123+124124+ dev->catas_err.map = ioremap(addr, dev->catas_err.size * 4);125125+ if (!dev->catas_err.map) {126126+ mthca_warn(dev, "couldn't map catastrophic error region "127127+ "at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4);128128+ release_mem_region(addr, dev->catas_err.size * 4);129129+ return;130130+ }131131+132132+ dev->catas_err.timer.data = (unsigned long) dev;133133+ dev->catas_err.timer.function = poll_catas;134134+ dev->catas_err.timer.expires = jiffies + MTHCA_CATAS_POLL_INTERVAL;135135+ add_timer(&dev->catas_err.timer);136136+}137137+138138+void mthca_stop_catas_poll(struct mthca_dev *dev)139139+{140140+ spin_lock_irq(&catas_lock);141141+ dev->catas_err.stop = 1;142142+ spin_unlock_irq(&catas_lock);143143+144144+ del_timer_sync(&dev->catas_err.timer);145145+146146+ if (dev->catas_err.map) {147147+ iounmap(dev->catas_err.map);148148+ release_mem_region(pci_resource_start(dev->pdev, 0) +149149+ ((pci_resource_len(dev->pdev, 0) - 1) &150150+ dev->catas_err.addr),151151+ dev->catas_err.size * 4);152152+ }153153+}
+9-2
drivers/infiniband/hw/mthca/mthca_cmd.c
···11/*22 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.33 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.44+ * Copyright (c) 2005 Cisco Systems. All rights reserved.45 *56 * This software is available to you under a choice of one of two67 * licenses. You may choose to be licensed under the terms of the GNU···707706708707 MTHCA_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);709708 dev->cmd.max_cmds = 1 << lg;709709+ MTHCA_GET(dev->catas_err.addr, outbox, QUERY_FW_ERR_START_OFFSET);710710+ MTHCA_GET(dev->catas_err.size, outbox, QUERY_FW_ERR_SIZE_OFFSET);710711711712 mthca_dbg(dev, "FW version %012llx, max commands %d\n",712713 (unsigned long long) dev->fw_ver, dev->cmd.max_cmds);714714+ mthca_dbg(dev, "Catastrophic error buffer at 0x%llx, size 0x%x\n",715715+ (unsigned long long) dev->catas_err.addr, dev->catas_err.size);713716714717 if (mthca_is_memfree(dev)) {715718 MTHCA_GET(dev->fw.arbel.fw_pages, outbox, QUERY_FW_SIZE_OFFSET);···938933 goto out;939934940935 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);941941- dev_lim->max_srq_sz = 1 << field;936936+ dev_lim->max_srq_sz = (1 << field) - 1;942937 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET);943943- dev_lim->max_qp_sz = 1 << field;938938+ dev_lim->max_qp_sz = (1 << field) - 1;944939 MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET);945940 dev_lim->reserved_qps = 1 << (field & 0xf);946941 MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET);···10501045 dev_lim->max_pds, dev_lim->reserved_pds, dev_lim->reserved_uars);10511046 mthca_dbg(dev, "Max QP/MCG: %d, reserved MGMs: %d\n",10521047 dev_lim->max_pds, dev_lim->reserved_mgms);10481048+ mthca_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",10491049+ dev_lim->max_cq_sz, dev_lim->max_qp_sz, dev_lim->max_srq_sz);1053105010541051 mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags);10551052
+22
drivers/infiniband/hw/mthca/mthca_dev.h
···8383 /* Arbel FW gives us these, but we need them for Tavor */8484 MTHCA_MPT_ENTRY_SIZE = 0x40,8585 MTHCA_MTT_SEG_SIZE = 0x40,8686+8787+ MTHCA_QP_PER_MGM = 4 * (MTHCA_MGM_ENTRY_SIZE / 16 - 2)8688};87898890enum {···130128 int num_uars;131129 int max_sg;132130 int num_qps;131131+ int max_wqes;132132+ int max_qp_init_rdma;133133 int reserved_qps;134134 int num_srqs;135135+ int max_srq_wqes;135136 int reserved_srqs;136137 int num_eecs;137138 int reserved_eecs;138139 int num_cqs;140140+ int max_cqes;139141 int reserved_cqs;140142 int num_eqs;141143 int reserved_eqs;···154148 int reserved_mcgs;155149 int num_pds;156150 int reserved_pds;151151+ u32 flags;157152 u8 port_width_cap;158153};159154···258251 struct mthca_icm_table *table;259252};260253254254+struct mthca_catas_err {255255+ u64 addr;256256+ u32 __iomem *map;257257+ unsigned long stop;258258+ u32 size;259259+ struct timer_list timer;260260+};261261+261262struct mthca_dev {262263 struct ib_device ib_dev;263264 struct pci_dev *pdev;···325310 struct mthca_qp_table qp_table;326311 struct mthca_av_table av_table;327312 struct mthca_mcg_table mcg_table;313313+314314+ struct mthca_catas_err catas_err;328315329316 struct mthca_uar driver_uar;330317 struct mthca_db_table *db_tab;···415398int mthca_register_device(struct mthca_dev *dev);416399void mthca_unregister_device(struct mthca_dev *dev);417400401401+void mthca_start_catas_poll(struct mthca_dev *dev);402402+void mthca_stop_catas_poll(struct mthca_dev *dev);403403+418404int mthca_uar_alloc(struct mthca_dev *dev, struct mthca_uar *uar);419405void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar);420406···467447int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,468448 struct ib_srq_attr *attr, struct mthca_srq *srq);469449void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq);450450+int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,451451+ enum ib_srq_attr_mask attr_mask);470452void mthca_srq_event(struct mthca_dev *dev, u32 srqn,471453 enum ib_event_type event_type);472454void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr);
···3838#include <linux/types.h>39394040/*4141+ * Increment this value if any changes that break userspace ABI4242+ * compatibility are made.4343+ */4444+#define MTHCA_UVERBS_ABI_VERSION 14545+4646+/*4147 * Make sure that all structs defined in this file remain laid out so4248 * that they pack the same way on 32-bit and 64-bit architectures (to4349 * avoid incompatibility between 32-bit userspace and 64-bit kernels).
···11/*22- * Copyright (c) 2004 Intel Corporation. All rights reserved.22+ * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.33 * Copyright (c) 2004 Topspin Corporation. All rights reserved.44 * Copyright (c) 2004 Voltaire Corporation. All rights reserved.55 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.···109109110110struct ib_cm_req_event_param {111111 struct ib_cm_id *listen_id;112112- struct ib_device *device;113112 u8 port;114113115114 struct ib_sa_path_rec *primary_path;···219220220221struct ib_cm_sidr_req_event_param {221222 struct ib_cm_id *listen_id;222222- struct ib_device *device;223223 u8 port;224224 u16 pkey;225225};···282284struct ib_cm_id {283285 ib_cm_handler cm_handler;284286 void *context;287287+ struct ib_device *device;285288 __be64 service_id;286289 __be64 service_mask;287290 enum ib_cm_state state; /* internal CM/debug use */···294295295296/**296297 * ib_create_cm_id - Allocate a communication identifier.298298+ * @device: Device associated with the cm_id. All related communication will299299+ * be associated with the specified device.297300 * @cm_handler: Callback invoked to notify the user of CM events.298301 * @context: User specified context associated with the communication299302 * identifier.···303302 * Communication identifiers are used to track connection states, service304303 * ID resolution requests, and listen requests.305304 */306306-struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,305305+struct ib_cm_id *ib_create_cm_id(struct ib_device *device,306306+ ib_cm_handler cm_handler,307307 void *context);308308309309/**
+34-32
include/rdma/ib_mad.h
···109109#define IB_QP_SET_QKEY 0x80000000110110111111enum {112112+ IB_MGMT_MAD_HDR = 24,112113 IB_MGMT_MAD_DATA = 232,114114+ IB_MGMT_RMPP_HDR = 36,113115 IB_MGMT_RMPP_DATA = 220,116116+ IB_MGMT_VENDOR_HDR = 40,114117 IB_MGMT_VENDOR_DATA = 216,115115- IB_MGMT_SA_DATA = 200118118+ IB_MGMT_SA_HDR = 56,119119+ IB_MGMT_SA_DATA = 200,116120};117121118122struct ib_mad_hdr {···207203208204/**209205 * ib_mad_send_buf - MAD data buffer and work request for sends.210210- * @mad: References an allocated MAD data buffer. The size of the data211211- * buffer is specified in the @send_wr.length field.212212- * @mapping: DMA mapping information.206206+ * @next: A pointer used to chain together MADs for posting.207207+ * @mad: References an allocated MAD data buffer.213208 * @mad_agent: MAD agent that allocated the buffer.209209+ * @ah: The address handle to use when sending the MAD.214210 * @context: User-controlled context fields.215215- * @send_wr: An initialized work request structure used when sending the MAD.216216- * The wr_id field of the work request is initialized to reference this217217- * data structure.218218- * @sge: A scatter-gather list referenced by the work request.211211+ * @timeout_ms: Time to wait for a response.212212+ * @retries: Number of times to retry a request for a response.219213 *220214 * Users are responsible for initializing the MAD buffer itself, with the221215 * exception of specifying the payload length field in any RMPP MAD.222216 */223217struct ib_mad_send_buf {224224- struct ib_mad *mad;225225- DECLARE_PCI_UNMAP_ADDR(mapping)218218+ struct ib_mad_send_buf *next;219219+ void *mad;226220 struct ib_mad_agent *mad_agent;221221+ struct ib_ah *ah;227222 void *context[2];228228- struct ib_send_wr send_wr;229229- struct ib_sge sge;223223+ int timeout_ms;224224+ int retries;230225};231226232227/**···290287 * or @mad_send_wc.291288 */292289typedef void (*ib_mad_snoop_handler)(struct ib_mad_agent *mad_agent,293293- struct ib_send_wr *send_wr,290290+ struct ib_mad_send_buf *send_buf,294291 struct ib_mad_send_wc *mad_send_wc);295292296293/**···337334338335/**339336 * ib_mad_send_wc - MAD send completion information.340340- * @wr_id: Work request identifier associated with the send MAD request.337337+ * @send_buf: Send MAD data buffer associated with the send MAD request.341338 * @status: Completion status.342339 * @vendor_err: Optional vendor error information returned with a failed343340 * request.344341 */345342struct ib_mad_send_wc {346346- u64 wr_id;343343+ struct ib_mad_send_buf *send_buf;347344 enum ib_wc_status status;348345 u32 vendor_err;349346};···369366 * @rmpp_list: Specifies a list of RMPP reassembled received MAD buffers.370367 * @mad_len: The length of the received MAD, without duplicated headers.371368 *372372- * For received response, the wr_id field of the wc is set to the wr_id369369+ * For received response, the wr_id contains a pointer to the ib_mad_send_buf373370 * for the corresponding send request.374371 */375372struct ib_mad_recv_wc {···466463/**467464 * ib_post_send_mad - Posts MAD(s) to the send queue of the QP associated468465 * with the registered client.469469- * @mad_agent: Specifies the associated registration to post the send to.470470- * @send_wr: Specifies the information needed to send the MAD(s).471471- * @bad_send_wr: Specifies the MAD on which an error was encountered.466466+ * @send_buf: Specifies the information needed to send the MAD(s).467467+ * @bad_send_buf: Specifies the MAD on which an error was encountered. This468468+ * parameter is optional if only a single MAD is posted.472469 *473470 * Sent MADs are not guaranteed to complete in the order that they were posted.474471 *···482479 * defined data being transferred. The paylen_newwin field should be483480 * specified in network-byte order.484481 */485485-int ib_post_send_mad(struct ib_mad_agent *mad_agent,486486- struct ib_send_wr *send_wr,487487- struct ib_send_wr **bad_send_wr);482482+int ib_post_send_mad(struct ib_mad_send_buf *send_buf,483483+ struct ib_mad_send_buf **bad_send_buf);488484489485/**490486 * ib_coalesce_recv_mad - Coalesces received MAD data into a single buffer.···509507/**510508 * ib_cancel_mad - Cancels an outstanding send MAD operation.511509 * @mad_agent: Specifies the registration associated with sent MAD.512512- * @wr_id: Indicates the work request identifier of the MAD to cancel.510510+ * @send_buf: Indicates the MAD to cancel.513511 *514512 * MADs will be returned to the user through the corresponding515513 * ib_mad_send_handler.516514 */517517-void ib_cancel_mad(struct ib_mad_agent *mad_agent, u64 wr_id);515515+void ib_cancel_mad(struct ib_mad_agent *mad_agent,516516+ struct ib_mad_send_buf *send_buf);518517519518/**520519 * ib_modify_mad - Modifies an outstanding send MAD operation.521520 * @mad_agent: Specifies the registration associated with sent MAD.522522- * @wr_id: Indicates the work request identifier of the MAD to modify.521521+ * @send_buf: Indicates the MAD to modify.523522 * @timeout_ms: New timeout value for sent MAD.524523 *525524 * This call will reset the timeout value for a sent MAD to the specified526525 * value.527526 */528528-int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms);527527+int ib_modify_mad(struct ib_mad_agent *mad_agent,528528+ struct ib_mad_send_buf *send_buf, u32 timeout_ms);529529530530/**531531 * ib_redirect_mad_qp - Registers a QP for MAD services.···576572 * @remote_qpn: Specifies the QPN of the receiving node.577573 * @pkey_index: Specifies which PKey the MAD will be sent using. This field578574 * is valid only if the remote_qpn is QP 1.579579- * @ah: References the address handle used to transfer to the remote node.580575 * @rmpp_active: Indicates if the send will enable RMPP.581576 * @hdr_len: Indicates the size of the data header of the MAD. This length582577 * should include the common MAD header, RMPP header, plus any class···585582 * additional padding that may be necessary.586583 * @gfp_mask: GFP mask used for the memory allocation.587584 *588588- * This is a helper routine that may be used to allocate a MAD. Users are589589- * not required to allocate outbound MADs using this call. The returned590590- * MAD send buffer will reference a data buffer usable for sending a MAD, along585585+ * This routine allocates a MAD for sending. The returned MAD send buffer586586+ * will reference a data buffer usable for sending a MAD, along591587 * with an initialized work request structure. Users may modify the returned592592- * MAD data buffer or work request before posting the send.588588+ * MAD data buffer before posting the send.593589 *594590 * The returned data buffer will be cleared. Users are responsible for595591 * initializing the common MAD and any class specific headers. If @rmpp_active···596594 */597595struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,598596 u32 remote_qpn, u16 pkey_index,599599- struct ib_ah *ah, int rmpp_active,597597+ int rmpp_active,600598 int hdr_len, int data_len,601599 gfp_t gfp_mask);602600
···11/*22 * Copyright (c) 2005 Topspin Communications. All rights reserved.33 * Copyright (c) 2005 Cisco Systems. All rights reserved.44+ * Copyright (c) 2005 PathScale, Inc. All rights reserved.45 *56 * This software is available to you under a choice of one of two67 * licenses. You may choose to be licensed under the terms of the GNU···4342 * Increment this value if any changes that break userspace ABI4443 * compatibility are made.4544 */4646-#define IB_USER_VERBS_ABI_VERSION 24545+#define IB_USER_VERBS_ABI_VERSION 347464847enum {4949- IB_USER_VERBS_CMD_QUERY_PARAMS,5048 IB_USER_VERBS_CMD_GET_CONTEXT,5149 IB_USER_VERBS_CMD_QUERY_DEVICE,5250 IB_USER_VERBS_CMD_QUERY_PORT,5353- IB_USER_VERBS_CMD_QUERY_GID,5454- IB_USER_VERBS_CMD_QUERY_PKEY,5551 IB_USER_VERBS_CMD_ALLOC_PD,5652 IB_USER_VERBS_CMD_DEALLOC_PD,5753 IB_USER_VERBS_CMD_CREATE_AH,···6365 IB_USER_VERBS_CMD_ALLOC_MW,6466 IB_USER_VERBS_CMD_BIND_MW,6567 IB_USER_VERBS_CMD_DEALLOC_MW,6868+ IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL,6669 IB_USER_VERBS_CMD_CREATE_CQ,6770 IB_USER_VERBS_CMD_RESIZE_CQ,6871 IB_USER_VERBS_CMD_DESTROY_CQ,···8990 * Make sure that all structs defined in this file remain laid out so9091 * that they pack the same way on 32-bit and 64-bit architectures (to9192 * avoid incompatibility between 32-bit userspace and 64-bit kernels).9292- * In particular do not use pointer types -- pass pointers in __u649393- * instead.9393+ * Specifically:9494+ * - Do not use pointer types -- pass pointers in __u64 instead.9595+ * - Make sure that any structure larger than 4 bytes is padded to a9696+ * multiple of 8 bytes. Otherwise the structure size will be9797+ * different between 32-bit and 64-bit architectures.9498 */959996100struct ib_uverbs_async_event_desc {···120118 __u16 out_words;121119};122120123123-/*124124- * No driver_data for "query params" command, since this is intended125125- * to be a core function with no possible device dependence.126126- */127127-struct ib_uverbs_query_params {128128- __u64 response;129129-};130130-131131-struct ib_uverbs_query_params_resp {132132- __u32 num_cq_events;133133-};134134-135121struct ib_uverbs_get_context {136122 __u64 response;137137- __u64 cq_fd_tab;138123 __u64 driver_data[0];139124};140125141126struct ib_uverbs_get_context_resp {142127 __u32 async_fd;143143- __u32 reserved;128128+ __u32 num_comp_vectors;144129};145130146131struct ib_uverbs_query_device {···209220 __u8 reserved[3];210221};211222212212-struct ib_uverbs_query_gid {213213- __u64 response;214214- __u8 port_num;215215- __u8 index;216216- __u8 reserved[6];217217- __u64 driver_data[0];218218-};219219-220220-struct ib_uverbs_query_gid_resp {221221- __u8 gid[16];222222-};223223-224224-struct ib_uverbs_query_pkey {225225- __u64 response;226226- __u8 port_num;227227- __u8 index;228228- __u8 reserved[6];229229- __u64 driver_data[0];230230-};231231-232232-struct ib_uverbs_query_pkey_resp {233233- __u16 pkey;234234- __u16 reserved;235235-};236236-237223struct ib_uverbs_alloc_pd {238224 __u64 response;239225 __u64 driver_data[0];···242278 __u32 mr_handle;243279};244280281281+struct ib_uverbs_create_comp_channel {282282+ __u64 response;283283+};284284+285285+struct ib_uverbs_create_comp_channel_resp {286286+ __u32 fd;287287+};288288+245289struct ib_uverbs_create_cq {246290 __u64 response;247291 __u64 user_handle;248292 __u32 cqe;249249- __u32 event_handler;293293+ __u32 comp_vector;294294+ __s32 comp_channel;295295+ __u32 reserved;250296 __u64 driver_data[0];251297};252298253299struct ib_uverbs_create_cq_resp {254300 __u32 cq_handle;255301 __u32 cqe;302302+};303303+304304+struct ib_uverbs_poll_cq {305305+ __u64 response;306306+ __u32 cq_handle;307307+ __u32 ne;308308+};309309+310310+struct ib_uverbs_wc {311311+ __u64 wr_id;312312+ __u32 status;313313+ __u32 opcode;314314+ __u32 vendor_err;315315+ __u32 byte_len;316316+ __u32 imm_data;317317+ __u32 qp_num;318318+ __u32 src_qp;319319+ __u32 wc_flags;320320+ __u16 pkey_index;321321+ __u16 slid;322322+ __u8 sl;323323+ __u8 dlid_path_bits;324324+ __u8 port_num;325325+ __u8 reserved;326326+};327327+328328+struct ib_uverbs_poll_cq_resp {329329+ __u32 count;330330+ __u32 reserved;331331+ struct ib_uverbs_wc wc[0];332332+};333333+334334+struct ib_uverbs_req_notify_cq {335335+ __u32 cq_handle;336336+ __u32 solicited_only;256337};257338258339struct ib_uverbs_destroy_cq {···395386396387struct ib_uverbs_destroy_qp_resp {397388 __u32 events_reported;389389+};390390+391391+/*392392+ * The ib_uverbs_sge structure isn't used anywhere, since we assume393393+ * the ib_sge structure is packed the same way on 32-bit and 64-bit394394+ * architectures in both kernel and user space. It's just here to395395+ * document the ABI.396396+ */397397+struct ib_uverbs_sge {398398+ __u64 addr;399399+ __u32 length;400400+ __u32 lkey;401401+};402402+403403+struct ib_uverbs_send_wr {404404+ __u64 wr_id; 405405+ __u32 num_sge;406406+ __u32 opcode;407407+ __u32 send_flags;408408+ __u32 imm_data;409409+ union {410410+ struct {411411+ __u64 remote_addr;412412+ __u32 rkey;413413+ __u32 reserved;414414+ } rdma;415415+ struct {416416+ __u64 remote_addr;417417+ __u64 compare_add;418418+ __u64 swap;419419+ __u32 rkey;420420+ __u32 reserved;421421+ } atomic;422422+ struct {423423+ __u32 ah;424424+ __u32 remote_qpn;425425+ __u32 remote_qkey;426426+ __u32 reserved;427427+ } ud;428428+ } wr;429429+};430430+431431+struct ib_uverbs_post_send {432432+ __u64 response;433433+ __u32 qp_handle;434434+ __u32 wr_count;435435+ __u32 sge_count;436436+ __u32 wqe_size;437437+ struct ib_uverbs_send_wr send_wr[0];438438+};439439+440440+struct ib_uverbs_post_send_resp {441441+ __u32 bad_wr;442442+};443443+444444+struct ib_uverbs_recv_wr {445445+ __u64 wr_id;446446+ __u32 num_sge;447447+ __u32 reserved;448448+};449449+450450+struct ib_uverbs_post_recv {451451+ __u64 response;452452+ __u32 qp_handle;453453+ __u32 wr_count;454454+ __u32 sge_count;455455+ __u32 wqe_size;456456+ struct ib_uverbs_recv_wr recv_wr[0];457457+};458458+459459+struct ib_uverbs_post_recv_resp {460460+ __u32 bad_wr;461461+};462462+463463+struct ib_uverbs_post_srq_recv {464464+ __u64 response;465465+ __u32 srq_handle;466466+ __u32 wr_count;467467+ __u32 sge_count;468468+ __u32 wqe_size;469469+ struct ib_uverbs_recv_wr recv[0];470470+};471471+472472+struct ib_uverbs_post_srq_recv_resp {473473+ __u32 bad_wr;474474+};475475+476476+struct ib_uverbs_global_route {477477+ __u8 dgid[16];478478+ __u32 flow_label; 479479+ __u8 sgid_index;480480+ __u8 hop_limit;481481+ __u8 traffic_class;482482+ __u8 reserved;483483+};484484+485485+struct ib_uverbs_ah_attr {486486+ struct ib_uverbs_global_route grh;487487+ __u16 dlid;488488+ __u8 sl;489489+ __u8 src_path_bits;490490+ __u8 static_rate;491491+ __u8 is_global;492492+ __u8 port_num;493493+ __u8 reserved;494494+};495495+496496+struct ib_uverbs_create_ah {497497+ __u64 response;498498+ __u64 user_handle;499499+ __u32 pd_handle;500500+ __u32 reserved;501501+ struct ib_uverbs_ah_attr attr;502502+};503503+504504+struct ib_uverbs_create_ah_resp {505505+ __u32 ah_handle;506506+};507507+508508+struct ib_uverbs_destroy_ah {509509+ __u32 ah_handle;398510};399511400512struct ib_uverbs_attach_mcast {
+3-3
include/rdma/ib_verbs.h
···595595 } atomic;596596 struct {597597 struct ib_ah *ah;598598- struct ib_mad_hdr *mad_hdr;599598 u32 remote_qpn;600599 u32 remote_qkey;601601- int timeout_ms; /* valid for MADs only */602602- int retries; /* valid for MADs only */603600 u16 pkey_index; /* valid for GSI only */604601 u8 port_num; /* valid for DR SMPs on switch only */605602 } ud;···947950 IB_DEV_REGISTERED,948951 IB_DEV_UNREGISTERED949952 } reg_state;953953+954954+ u64 uverbs_cmd_mask;955955+ int uverbs_abi_ver;950956951957 u8 node_type;952958 u8 phys_port_cnt;