⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mad.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved. * Copyright (c) 2005 Intel Corporation.  All rights reserved. * Copyright (c) 2005 Mellanox Technologies Ltd.  All rights reserved. * * This software is available to you under a choice of one of two * licenses.  You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * *     Redistribution and use in source and binary forms, with or *     without modification, are permitted provided that the following *     conditions are met: * *      - Redistributions of source code must retain the above *        copyright notice, this list of conditions and the following *        disclaimer. * *      - Redistributions in binary form must reproduce the above *        copyright notice, this list of conditions and the following *        disclaimer in the documentation and/or other materials *        provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * $Id: mad.c 2817 2005-07-07 11:29:26Z halr $ */#include <linux/dma-mapping.h>#include "mad_priv.h"#include "mad_rmpp.h"#include "smi.h"#include "agent.h"MODULE_LICENSE("Dual BSD/GPL");MODULE_DESCRIPTION("kernel IB MAD API");MODULE_AUTHOR("Hal Rosenstock");MODULE_AUTHOR("Sean Hefty");kmem_cache_t *ib_mad_cache;static struct list_head ib_mad_port_list;static u32 ib_mad_client_id = 0;/* Port list lock */static spinlock_t ib_mad_port_list_lock;/* Forward declarations */static int method_in_use(struct ib_mad_mgmt_method_table **method,			 struct ib_mad_reg_req *mad_reg_req);static void remove_mad_reg_req(struct ib_mad_agent_private *priv);static struct ib_mad_agent_private *find_mad_agent(					struct ib_mad_port_private *port_priv,					struct ib_mad *mad);static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,				    struct ib_mad_private *mad);static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv);static void timeout_sends(void *data);static void local_completions(void *data);static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req,			      struct ib_mad_agent_private *agent_priv,			      u8 mgmt_class);static int add_oui_reg_req(struct ib_mad_reg_req *mad_reg_req,			   struct ib_mad_agent_private *agent_priv);/* * Returns a ib_mad_port_private structure or NULL for a device/port * Assumes ib_mad_port_list_lock is being held */static inline struct ib_mad_port_private *__ib_get_mad_port(struct ib_device *device, int port_num){	struct ib_mad_port_private *entry;	list_for_each_entry(entry, &ib_mad_port_list, port_list) {		if (entry->device == device && entry->port_num == port_num)			return entry;	}	return NULL;}/* * Wrapper function to return a ib_mad_port_private structure or NULL * for a device/port */static inline struct ib_mad_port_private *ib_get_mad_port(struct ib_device *device, int port_num){	struct ib_mad_port_private *entry;	unsigned long flags;	spin_lock_irqsave(&ib_mad_port_list_lock, flags);	entry = __ib_get_mad_port(device, port_num);	spin_unlock_irqrestore(&ib_mad_port_list_lock, flags);	return entry;}static inline u8 convert_mgmt_class(u8 mgmt_class){	/* Alias IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE to 0 */	return mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE ?		0 : mgmt_class;}static int get_spl_qp_index(enum ib_qp_type qp_type){	switch (qp_type)	{	case IB_QPT_SMI:		return 0;	case IB_QPT_GSI:		return 1;	default:		return -1;	}}static int vendor_class_index(u8 mgmt_class){	return mgmt_class - IB_MGMT_CLASS_VENDOR_RANGE2_START;}static int is_vendor_class(u8 mgmt_class){	if ((mgmt_class < IB_MGMT_CLASS_VENDOR_RANGE2_START) ||	    (mgmt_class > IB_MGMT_CLASS_VENDOR_RANGE2_END))		return 0;	return 1;}static int is_vendor_oui(char *oui){	if (oui[0] || oui[1] || oui[2])		return 1;	return 0;}static int is_vendor_method_in_use(		struct ib_mad_mgmt_vendor_class *vendor_class,		struct ib_mad_reg_req *mad_reg_req){	struct ib_mad_mgmt_method_table *method;	int i;	for (i = 0; i < MAX_MGMT_OUI; i++) {		if (!memcmp(vendor_class->oui[i], mad_reg_req->oui, 3)) {			method = vendor_class->method_table[i];			if (method) {				if (method_in_use(&method, mad_reg_req))					return 1;				else					break;			}		}	}	return 0;}/* * ib_register_mad_agent - Register to send/receive MADs */struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,					   u8 port_num,					   enum ib_qp_type qp_type,					   struct ib_mad_reg_req *mad_reg_req,					   u8 rmpp_version,					   ib_mad_send_handler send_handler,					   ib_mad_recv_handler recv_handler,					   void *context){	struct ib_mad_port_private *port_priv;	struct ib_mad_agent *ret = ERR_PTR(-EINVAL);	struct ib_mad_agent_private *mad_agent_priv;	struct ib_mad_reg_req *reg_req = NULL;	struct ib_mad_mgmt_class_table *class;	struct ib_mad_mgmt_vendor_class_table *vendor;	struct ib_mad_mgmt_vendor_class *vendor_class;	struct ib_mad_mgmt_method_table *method;	int ret2, qpn;	unsigned long flags;	u8 mgmt_class, vclass;	/* Validate parameters */	qpn = get_spl_qp_index(qp_type);	if (qpn == -1)		goto error1;	if (rmpp_version && rmpp_version != IB_MGMT_RMPP_VERSION)		goto error1;	/* Validate MAD registration request if supplied */	if (mad_reg_req) {		if (mad_reg_req->mgmt_class_version >= MAX_MGMT_VERSION)			goto error1;		if (!recv_handler)			goto error1;		if (mad_reg_req->mgmt_class >= MAX_MGMT_CLASS) {			/*			 * IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE is the only			 * one in this range currently allowed			 */			if (mad_reg_req->mgmt_class !=			    IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)				goto error1;		} else if (mad_reg_req->mgmt_class == 0) {			/*			 * Class 0 is reserved in IBA and is used for			 * aliasing of IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE			 */			goto error1;		} else if (is_vendor_class(mad_reg_req->mgmt_class)) {			/*			 * If class is in "new" vendor range,			 * ensure supplied OUI is not zero			 */			if (!is_vendor_oui(mad_reg_req->oui))				goto error1;		}		/* Make sure class supplied is consistent with QP type */		if (qp_type == IB_QPT_SMI) {			if ((mad_reg_req->mgmt_class !=					IB_MGMT_CLASS_SUBN_LID_ROUTED) &&			    (mad_reg_req->mgmt_class !=					IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE))				goto error1;		} else {			if ((mad_reg_req->mgmt_class ==					IB_MGMT_CLASS_SUBN_LID_ROUTED) ||			    (mad_reg_req->mgmt_class ==					IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE))				goto error1;		}	} else {		/* No registration request supplied */		if (!send_handler)			goto error1;	}	/* Validate device and port */	port_priv = ib_get_mad_port(device, port_num);	if (!port_priv) {		ret = ERR_PTR(-ENODEV);		goto error1;	}	/* Allocate structures */	mad_agent_priv = kzalloc(sizeof *mad_agent_priv, GFP_KERNEL);	if (!mad_agent_priv) {		ret = ERR_PTR(-ENOMEM);		goto error1;	}	mad_agent_priv->agent.mr = ib_get_dma_mr(port_priv->qp_info[qpn].qp->pd,						 IB_ACCESS_LOCAL_WRITE);	if (IS_ERR(mad_agent_priv->agent.mr)) {		ret = ERR_PTR(-ENOMEM);		goto error2;	}	if (mad_reg_req) {		reg_req = kmalloc(sizeof *reg_req, GFP_KERNEL);		if (!reg_req) {			ret = ERR_PTR(-ENOMEM);			goto error3;		}		/* Make a copy of the MAD registration request */		memcpy(reg_req, mad_reg_req, sizeof *reg_req);	}	/* Now, fill in the various structures */	mad_agent_priv->qp_info = &port_priv->qp_info[qpn];	mad_agent_priv->reg_req = reg_req;	mad_agent_priv->agent.rmpp_version = rmpp_version;	mad_agent_priv->agent.device = device;	mad_agent_priv->agent.recv_handler = recv_handler;	mad_agent_priv->agent.send_handler = send_handler;	mad_agent_priv->agent.context = context;	mad_agent_priv->agent.qp = port_priv->qp_info[qpn].qp;	mad_agent_priv->agent.port_num = port_num;	spin_lock_irqsave(&port_priv->reg_lock, flags);	mad_agent_priv->agent.hi_tid = ++ib_mad_client_id;	/*	 * Make sure MAD registration (if supplied)	 * is non overlapping with any existing ones	 */	if (mad_reg_req) {		mgmt_class = convert_mgmt_class(mad_reg_req->mgmt_class);		if (!is_vendor_class(mgmt_class)) {			class = port_priv->version[mad_reg_req->						   mgmt_class_version].class;			if (class) {				method = class->method_table[mgmt_class];				if (method) {					if (method_in_use(&method,							   mad_reg_req))						goto error4;				}			}			ret2 = add_nonoui_reg_req(mad_reg_req, mad_agent_priv,						  mgmt_class);		} else {			/* "New" vendor class range */			vendor = port_priv->version[mad_reg_req->						    mgmt_class_version].vendor;			if (vendor) {				vclass = vendor_class_index(mgmt_class);				vendor_class = vendor->vendor_class[vclass];				if (vendor_class) {					if (is_vendor_method_in_use(							vendor_class,							mad_reg_req))						goto error4;				}			}			ret2 = add_oui_reg_req(mad_reg_req, mad_agent_priv);		}		if (ret2) {			ret = ERR_PTR(ret2);			goto error4;		}	}	/* Add mad agent into port's agent list */	list_add_tail(&mad_agent_priv->agent_list, &port_priv->agent_list);	spin_unlock_irqrestore(&port_priv->reg_lock, flags);	spin_lock_init(&mad_agent_priv->lock);	INIT_LIST_HEAD(&mad_agent_priv->send_list);	INIT_LIST_HEAD(&mad_agent_priv->wait_list);	INIT_LIST_HEAD(&mad_agent_priv->done_list);	INIT_LIST_HEAD(&mad_agent_priv->rmpp_list);	INIT_WORK(&mad_agent_priv->timed_work, timeout_sends, mad_agent_priv);	INIT_LIST_HEAD(&mad_agent_priv->local_list);	INIT_WORK(&mad_agent_priv->local_work, local_completions,		   mad_agent_priv);	atomic_set(&mad_agent_priv->refcount, 1);	init_waitqueue_head(&mad_agent_priv->wait);	return &mad_agent_priv->agent;error4:	spin_unlock_irqrestore(&port_priv->reg_lock, flags);	kfree(reg_req);error3:	ib_dereg_mr(mad_agent_priv->agent.mr);error2:	kfree(mad_agent_priv);error1:	return ret;}EXPORT_SYMBOL(ib_register_mad_agent);static inline int is_snooping_sends(int mad_snoop_flags){	return (mad_snoop_flags &		(/*IB_MAD_SNOOP_POSTED_SENDS |		 IB_MAD_SNOOP_RMPP_SENDS |*/		 IB_MAD_SNOOP_SEND_COMPLETIONS /*|		 IB_MAD_SNOOP_RMPP_SEND_COMPLETIONS*/));}static inline int is_snooping_recvs(int mad_snoop_flags){	return (mad_snoop_flags &		(IB_MAD_SNOOP_RECVS /*|		 IB_MAD_SNOOP_RMPP_RECVS*/));}static int register_snoop_agent(struct ib_mad_qp_info *qp_info,				struct ib_mad_snoop_private *mad_snoop_priv){	struct ib_mad_snoop_private **new_snoop_table;	unsigned long flags;	int i;	spin_lock_irqsave(&qp_info->snoop_lock, flags);	/* Check for empty slot in array. */	for (i = 0; i < qp_info->snoop_table_size; i++)		if (!qp_info->snoop_table[i])			break;	if (i == qp_info->snoop_table_size) {		/* Grow table. */		new_snoop_table = kmalloc(sizeof mad_snoop_priv *					  qp_info->snoop_table_size + 1,					  GFP_ATOMIC);		if (!new_snoop_table) {			i = -ENOMEM;			goto out;		}		if (qp_info->snoop_table) {			memcpy(new_snoop_table, qp_info->snoop_table,			       sizeof mad_snoop_priv *			       qp_info->snoop_table_size);			kfree(qp_info->snoop_table);		}		qp_info->snoop_table = new_snoop_table;		qp_info->snoop_table_size++;	}	qp_info->snoop_table[i] = mad_snoop_priv;	atomic_inc(&qp_info->snoop_count);out:	spin_unlock_irqrestore(&qp_info->snoop_lock, flags);	return i;}struct ib_mad_agent *ib_register_mad_snoop(struct ib_device *device,					   u8 port_num,					   enum ib_qp_type qp_type,					   int mad_snoop_flags,					   ib_mad_snoop_handler snoop_handler,					   ib_mad_recv_handler recv_handler,					   void *context){	struct ib_mad_port_private *port_priv;	struct ib_mad_agent *ret;	struct ib_mad_snoop_private *mad_snoop_priv;	int qpn;	/* Validate parameters */	if ((is_snooping_sends(mad_snoop_flags) && !snoop_handler) ||	    (is_snooping_recvs(mad_snoop_flags) && !recv_handler)) {		ret = ERR_PTR(-EINVAL);		goto error1;	}	qpn = get_spl_qp_index(qp_type);	if (qpn == -1) {		ret = ERR_PTR(-EINVAL);		goto error1;	}	port_priv = ib_get_mad_port(device, port_num);	if (!port_priv) {		ret = ERR_PTR(-ENODEV);		goto error1;	}	/* Allocate structures */	mad_snoop_priv = kzalloc(sizeof *mad_snoop_priv, GFP_KERNEL);	if (!mad_snoop_priv) {		ret = ERR_PTR(-ENOMEM);		goto error1;	}	/* Now, fill in the various structures */	mad_snoop_priv->qp_info = &port_priv->qp_info[qpn];	mad_snoop_priv->agent.device = device;	mad_snoop_priv->agent.recv_handler = recv_handler;	mad_snoop_priv->agent.snoop_handler = snoop_handler;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -