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

📄 sa_query.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2004 Topspin Communications.  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: sa_query.c 1389 2004-12-27 22:56:47Z roland $ */#include <linux/module.h>#include <linux/init.h>#include <linux/err.h>#include <linux/random.h>#include <linux/spinlock.h>#include <linux/slab.h>#include <linux/pci.h>#include <linux/dma-mapping.h>#include <linux/kref.h>#include <linux/idr.h>#include <ib_pack.h>#include <ib_sa.h>MODULE_AUTHOR("Roland Dreier");MODULE_DESCRIPTION("InfiniBand subnet administration query support");MODULE_LICENSE("Dual BSD/GPL");/* * These two structures must be packed because they have 64-bit fields * that are only 32-bit aligned.  64-bit architectures will lay them * out wrong otherwise.  (And unfortunately they are sent on the wire * so we can't change the layout) */struct ib_sa_hdr {	u64			sm_key;	u16			attr_offset;	u16			reserved;	ib_sa_comp_mask		comp_mask;} __attribute__ ((packed));struct ib_sa_mad {	struct ib_mad_hdr	mad_hdr;	struct ib_rmpp_hdr	rmpp_hdr;	struct ib_sa_hdr	sa_hdr;	u8			data[200];} __attribute__ ((packed));struct ib_sa_sm_ah {	struct ib_ah        *ah;	struct kref          ref;};struct ib_sa_port {	struct ib_mad_agent *agent;	struct ib_mr        *mr;	struct ib_sa_sm_ah  *sm_ah;	struct work_struct   update_task;	spinlock_t           ah_lock;	u8                   port_num;};struct ib_sa_device {	int                     start_port, end_port;	struct ib_event_handler event_handler;	struct ib_sa_port port[0];};struct ib_sa_query {	void (*callback)(struct ib_sa_query *, int, struct ib_sa_mad *);	void (*release)(struct ib_sa_query *);	struct ib_sa_port  *port;	struct ib_sa_mad   *mad;	struct ib_sa_sm_ah *sm_ah;	DECLARE_PCI_UNMAP_ADDR(mapping)	int                 id;};struct ib_sa_path_query {	void (*callback)(int, struct ib_sa_path_rec *, void *);	void *context;	struct ib_sa_query sa_query;};struct ib_sa_mcmember_query {	void (*callback)(int, struct ib_sa_mcmember_rec *, void *);	void *context;	struct ib_sa_query sa_query;};static void ib_sa_add_one(struct ib_device *device);static void ib_sa_remove_one(struct ib_device *device);static struct ib_client sa_client = {	.name   = "sa",	.add    = ib_sa_add_one,	.remove = ib_sa_remove_one};static spinlock_t idr_lock;static DEFINE_IDR(query_idr);static spinlock_t tid_lock;static u32 tid;enum {	IB_SA_ATTR_CLASS_PORTINFO    = 0x01,	IB_SA_ATTR_NOTICE	     = 0x02,	IB_SA_ATTR_INFORM_INFO	     = 0x03,	IB_SA_ATTR_NODE_REC	     = 0x11,	IB_SA_ATTR_PORT_INFO_REC     = 0x12,	IB_SA_ATTR_SL2VL_REC	     = 0x13,	IB_SA_ATTR_SWITCH_REC	     = 0x14,	IB_SA_ATTR_LINEAR_FDB_REC    = 0x15,	IB_SA_ATTR_RANDOM_FDB_REC    = 0x16,	IB_SA_ATTR_MCAST_FDB_REC     = 0x17,	IB_SA_ATTR_SM_INFO_REC	     = 0x18,	IB_SA_ATTR_LINK_REC	     = 0x20,	IB_SA_ATTR_GUID_INFO_REC     = 0x30,	IB_SA_ATTR_SERVICE_REC	     = 0x31,	IB_SA_ATTR_PARTITION_REC     = 0x33,	IB_SA_ATTR_RANGE_REC	     = 0x34,	IB_SA_ATTR_PATH_REC	     = 0x35,	IB_SA_ATTR_VL_ARB_REC	     = 0x36,	IB_SA_ATTR_MC_GROUP_REC	     = 0x37,	IB_SA_ATTR_MC_MEMBER_REC     = 0x38,	IB_SA_ATTR_TRACE_REC	     = 0x39,	IB_SA_ATTR_MULTI_PATH_REC    = 0x3a,	IB_SA_ATTR_SERVICE_ASSOC_REC = 0x3b};#define PATH_REC_FIELD(field) \	.struct_offset_bytes = offsetof(struct ib_sa_path_rec, field),		\	.struct_size_bytes   = sizeof ((struct ib_sa_path_rec *) 0)->field,	\	.field_name          = "sa_path_rec:" #fieldstatic const struct ib_field path_rec_table[] = {	{ RESERVED,	  .offset_words = 0,	  .offset_bits  = 0,	  .size_bits    = 32 },	{ RESERVED,	  .offset_words = 1,	  .offset_bits  = 0,	  .size_bits    = 32 },	{ PATH_REC_FIELD(dgid),	  .offset_words = 2,	  .offset_bits  = 0,	  .size_bits    = 128 },	{ PATH_REC_FIELD(sgid),	  .offset_words = 6,	  .offset_bits  = 0,	  .size_bits    = 128 },	{ PATH_REC_FIELD(dlid),	  .offset_words = 10,	  .offset_bits  = 0,	  .size_bits    = 16 },	{ PATH_REC_FIELD(slid),	  .offset_words = 10,	  .offset_bits  = 16,	  .size_bits    = 16 },	{ PATH_REC_FIELD(raw_traffic),	  .offset_words = 11,	  .offset_bits  = 0,	  .size_bits    = 1 },	{ RESERVED,	  .offset_words = 11,	  .offset_bits  = 1,	  .size_bits    = 3 },	{ PATH_REC_FIELD(flow_label),	  .offset_words = 11,	  .offset_bits  = 4,	  .size_bits    = 20 },	{ PATH_REC_FIELD(hop_limit),	  .offset_words = 11,	  .offset_bits  = 24,	  .size_bits    = 8 },	{ PATH_REC_FIELD(traffic_class),	  .offset_words = 12,	  .offset_bits  = 0,	  .size_bits    = 8 },	{ PATH_REC_FIELD(reversible),	  .offset_words = 12,	  .offset_bits  = 8,	  .size_bits    = 1 },	{ PATH_REC_FIELD(numb_path),	  .offset_words = 12,	  .offset_bits  = 9,	  .size_bits    = 7 },	{ PATH_REC_FIELD(pkey),	  .offset_words = 12,	  .offset_bits  = 16,	  .size_bits    = 16 },	{ RESERVED,	  .offset_words = 13,	  .offset_bits  = 0,	  .size_bits    = 12 },	{ PATH_REC_FIELD(sl),	  .offset_words = 13,	  .offset_bits  = 12,	  .size_bits    = 4 },	{ PATH_REC_FIELD(mtu_selector),	  .offset_words = 13,	  .offset_bits  = 16,	  .size_bits    = 2 },	{ PATH_REC_FIELD(mtu),	  .offset_words = 13,	  .offset_bits  = 18,	  .size_bits    = 6 },	{ PATH_REC_FIELD(rate_selector),	  .offset_words = 13,	  .offset_bits  = 24,	  .size_bits    = 2 },	{ PATH_REC_FIELD(rate),	  .offset_words = 13,	  .offset_bits  = 26,	  .size_bits    = 6 },	{ PATH_REC_FIELD(packet_life_time_selector),	  .offset_words = 14,	  .offset_bits  = 0,	  .size_bits    = 2 },	{ PATH_REC_FIELD(packet_life_time),	  .offset_words = 14,	  .offset_bits  = 2,	  .size_bits    = 6 },	{ PATH_REC_FIELD(preference),	  .offset_words = 14,	  .offset_bits  = 8,	  .size_bits    = 8 },	{ RESERVED,	  .offset_words = 14,	  .offset_bits  = 16,	  .size_bits    = 48 },};#define MCMEMBER_REC_FIELD(field) \	.struct_offset_bytes = offsetof(struct ib_sa_mcmember_rec, field),	\	.struct_size_bytes   = sizeof ((struct ib_sa_mcmember_rec *) 0)->field,	\	.field_name          = "sa_mcmember_rec:" #fieldstatic const struct ib_field mcmember_rec_table[] = {	{ MCMEMBER_REC_FIELD(mgid),	  .offset_words = 0,	  .offset_bits  = 0,	  .size_bits    = 128 },	{ MCMEMBER_REC_FIELD(port_gid),	  .offset_words = 4,	  .offset_bits  = 0,	  .size_bits    = 128 },	{ MCMEMBER_REC_FIELD(qkey),	  .offset_words = 8,	  .offset_bits  = 0,	  .size_bits    = 32 },	{ MCMEMBER_REC_FIELD(mlid),	  .offset_words = 9,	  .offset_bits  = 0,	  .size_bits    = 16 },	{ MCMEMBER_REC_FIELD(mtu_selector),	  .offset_words = 9,	  .offset_bits  = 16,	  .size_bits    = 2 },	{ MCMEMBER_REC_FIELD(mtu),	  .offset_words = 9,	  .offset_bits  = 18,	  .size_bits    = 6 },	{ MCMEMBER_REC_FIELD(traffic_class),	  .offset_words = 9,	  .offset_bits  = 24,	  .size_bits    = 8 },	{ MCMEMBER_REC_FIELD(pkey),	  .offset_words = 10,	  .offset_bits  = 0,	  .size_bits    = 16 },	{ MCMEMBER_REC_FIELD(rate_selector),	  .offset_words = 10,	  .offset_bits  = 16,	  .size_bits    = 2 },	{ MCMEMBER_REC_FIELD(rate),	  .offset_words = 10,	  .offset_bits  = 18,	  .size_bits    = 6 },	{ MCMEMBER_REC_FIELD(packet_life_time_selector),	  .offset_words = 10,	  .offset_bits  = 24,	  .size_bits    = 2 },	{ MCMEMBER_REC_FIELD(packet_life_time),	  .offset_words = 10,	  .offset_bits  = 26,	  .size_bits    = 6 },	{ MCMEMBER_REC_FIELD(sl),	  .offset_words = 11,	  .offset_bits  = 0,	  .size_bits    = 4 },	{ MCMEMBER_REC_FIELD(flow_label),	  .offset_words = 11,	  .offset_bits  = 4,	  .size_bits    = 20 },	{ MCMEMBER_REC_FIELD(hop_limit),	  .offset_words = 11,	  .offset_bits  = 24,	  .size_bits    = 8 },	{ MCMEMBER_REC_FIELD(scope),	  .offset_words = 12,	  .offset_bits  = 0,	  .size_bits    = 4 },	{ MCMEMBER_REC_FIELD(join_state),	  .offset_words = 12,	  .offset_bits  = 4,	  .size_bits    = 4 },	{ MCMEMBER_REC_FIELD(proxy_join),	  .offset_words = 12,	  .offset_bits  = 8,	  .size_bits    = 1 },	{ RESERVED,	  .offset_words = 12,	  .offset_bits  = 9,	  .size_bits    = 23 },};static void free_sm_ah(struct kref *kref){	struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref);	ib_destroy_ah(sm_ah->ah);	kfree(sm_ah);}static void update_sm_ah(void *port_ptr){	struct ib_sa_port *port = port_ptr;	struct ib_sa_sm_ah *new_ah, *old_ah;	struct ib_port_attr port_attr;	struct ib_ah_attr   ah_attr;	if (ib_query_port(port->agent->device, port->port_num, &port_attr)) {		printk(KERN_WARNING "Couldn't query port\n");		return;	}	new_ah = kmalloc(sizeof *new_ah, GFP_KERNEL);	if (!new_ah) {		printk(KERN_WARNING "Couldn't allocate new SM AH\n");		return;	}	kref_init(&new_ah->ref);	memset(&ah_attr, 0, sizeof ah_attr);	ah_attr.dlid     = port_attr.sm_lid;	ah_attr.sl       = port_attr.sm_sl;	ah_attr.port_num = port->port_num;	new_ah->ah = ib_create_ah(port->agent->qp->pd, &ah_attr);	if (IS_ERR(new_ah->ah)) {		printk(KERN_WARNING "Couldn't create new SM AH\n");		kfree(new_ah);		return;	}	spin_lock_irq(&port->ah_lock);	old_ah = port->sm_ah;	port->sm_ah = new_ah;	spin_unlock_irq(&port->ah_lock);	if (old_ah)		kref_put(&old_ah->ref, free_sm_ah);}static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event){	if (event->event == IB_EVENT_PORT_ERR    ||	    event->event == IB_EVENT_PORT_ACTIVE ||	    event->event == IB_EVENT_LID_CHANGE  ||	    event->event == IB_EVENT_PKEY_CHANGE ||	    event->event == IB_EVENT_SM_CHANGE) {		struct ib_sa_device *sa_dev =			ib_get_client_data(event->device, &sa_client);		schedule_work(&sa_dev->port[event->element.port_num -					    sa_dev->start_port].update_task);	}}/** * ib_sa_cancel_query - try to cancel an SA query * @id:ID of query to cancel * @query:query pointer to cancel * * Try to cancel an SA query.  If the id and query don't match up or * the query has already completed, nothing is done.  Otherwise the * query is canceled and will complete with a status of -EINTR. */void ib_sa_cancel_query(int id, struct ib_sa_query *query){	unsigned long flags;	struct ib_mad_agent *agent;	spin_lock_irqsave(&idr_lock, flags);	if (idr_find(&query_idr, id) != query) {		spin_unlock_irqrestore(&idr_lock, flags);		return;	}	agent = query->port->agent;	spin_unlock_irqrestore(&idr_lock, flags);	ib_cancel_mad(agent, id);}EXPORT_SYMBOL(ib_sa_cancel_query);static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)

⌨️ 快捷键说明

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