mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 11:41:38 -04:00
Merge /scratch/Ksrc/linux-git/
This commit is contained in:
commit
2868bd281f
628 changed files with 72452 additions and 6590 deletions
|
|
@ -1,15 +1,20 @@
|
|||
EXTRA_CFLAGS += -Idrivers/infiniband/include
|
||||
|
||||
obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o ib_umad.o
|
||||
obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \
|
||||
ib_cm.o ib_umad.o ib_ucm.o
|
||||
obj-$(CONFIG_INFINIBAND_USER_VERBS) += ib_uverbs.o
|
||||
|
||||
ib_core-y := packer.o ud_header.o verbs.o sysfs.o \
|
||||
device.o fmr_pool.o cache.o
|
||||
|
||||
ib_mad-y := mad.o smi.o agent.o
|
||||
ib_mad-y := mad.o smi.o agent.o mad_rmpp.o
|
||||
|
||||
ib_sa-y := sa_query.o
|
||||
|
||||
ib_cm-y := cm.o
|
||||
|
||||
ib_umad-y := user_mad.o
|
||||
|
||||
ib_ucm-y := ucm.o
|
||||
|
||||
ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_mem.o
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ static int agent_mad_send(struct ib_mad_agent *mad_agent,
|
|||
sizeof(mad_priv->mad),
|
||||
DMA_TO_DEVICE);
|
||||
gather_list.length = sizeof(mad_priv->mad);
|
||||
gather_list.lkey = (*port_priv->mr).lkey;
|
||||
gather_list.lkey = mad_agent->mr->lkey;
|
||||
|
||||
send_wr.next = NULL;
|
||||
send_wr.opcode = IB_WR_SEND;
|
||||
|
|
@ -156,10 +156,10 @@ static int agent_mad_send(struct ib_mad_agent *mad_agent,
|
|||
/* Should sgid be looked up ? */
|
||||
ah_attr.grh.sgid_index = 0;
|
||||
ah_attr.grh.hop_limit = grh->hop_limit;
|
||||
ah_attr.grh.flow_label = be32_to_cpup(
|
||||
&grh->version_tclass_flow) & 0xfffff;
|
||||
ah_attr.grh.traffic_class = (be32_to_cpup(
|
||||
&grh->version_tclass_flow) >> 20) & 0xff;
|
||||
ah_attr.grh.flow_label = be32_to_cpu(
|
||||
grh->version_tclass_flow) & 0xfffff;
|
||||
ah_attr.grh.traffic_class = (be32_to_cpu(
|
||||
grh->version_tclass_flow) >> 20) & 0xff;
|
||||
memcpy(ah_attr.grh.dgid.raw,
|
||||
grh->sgid.raw,
|
||||
sizeof(ah_attr.grh.dgid));
|
||||
|
|
@ -322,22 +322,12 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
|
|||
goto error3;
|
||||
}
|
||||
|
||||
port_priv->mr = ib_get_dma_mr(port_priv->smp_agent->qp->pd,
|
||||
IB_ACCESS_LOCAL_WRITE);
|
||||
if (IS_ERR(port_priv->mr)) {
|
||||
printk(KERN_ERR SPFX "Couldn't get DMA MR\n");
|
||||
ret = PTR_ERR(port_priv->mr);
|
||||
goto error4;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ib_agent_port_list_lock, flags);
|
||||
list_add_tail(&port_priv->port_list, &ib_agent_port_list);
|
||||
spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
|
||||
|
||||
return 0;
|
||||
|
||||
error4:
|
||||
ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
|
||||
error3:
|
||||
ib_unregister_mad_agent(port_priv->smp_agent);
|
||||
error2:
|
||||
|
|
@ -361,8 +351,6 @@ int ib_agent_port_close(struct ib_device *device, int port_num)
|
|||
list_del(&port_priv->port_list);
|
||||
spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
|
||||
|
||||
ib_dereg_mr(port_priv->mr);
|
||||
|
||||
ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
|
||||
ib_unregister_mad_agent(port_priv->smp_agent);
|
||||
kfree(port_priv);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* $Id: agent_priv.h 1389 2004-12-27 22:56:47Z roland $
|
||||
* $Id: agent_priv.h 1640 2005-01-24 22:39:02Z halr $
|
||||
*/
|
||||
|
||||
#ifndef __IB_AGENT_PRIV_H__
|
||||
|
|
@ -57,7 +57,6 @@ struct ib_agent_port_private {
|
|||
int port_num;
|
||||
struct ib_mad_agent *smp_agent; /* SM class */
|
||||
struct ib_mad_agent *perf_mgmt_agent; /* PerfMgmt class */
|
||||
struct ib_mr *mr;
|
||||
};
|
||||
|
||||
#endif /* __IB_AGENT_PRIV_H__ */
|
||||
|
|
|
|||
3324
drivers/infiniband/core/cm.c
Normal file
3324
drivers/infiniband/core/cm.c
Normal file
File diff suppressed because it is too large
Load diff
819
drivers/infiniband/core/cm_msgs.h
Normal file
819
drivers/infiniband/core/cm_msgs.h
Normal file
|
|
@ -0,0 +1,819 @@
|
|||
/*
|
||||
* Copyright (c) 2004 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Voltaire Corporation. 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 the madirectory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use source and binary forms, with or
|
||||
* withmodification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retathe above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHWARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#if !defined(CM_MSGS_H)
|
||||
#define CM_MSGS_H
|
||||
|
||||
#include <ib_mad.h>
|
||||
|
||||
/*
|
||||
* Parameters to routines below should be in network-byte order, and values
|
||||
* are returned in network-byte order.
|
||||
*/
|
||||
|
||||
#define IB_CM_CLASS_VERSION 2 /* IB specification 1.2 */
|
||||
|
||||
enum cm_msg_attr_id {
|
||||
CM_REQ_ATTR_ID = __constant_htons(0x0010),
|
||||
CM_MRA_ATTR_ID = __constant_htons(0x0011),
|
||||
CM_REJ_ATTR_ID = __constant_htons(0x0012),
|
||||
CM_REP_ATTR_ID = __constant_htons(0x0013),
|
||||
CM_RTU_ATTR_ID = __constant_htons(0x0014),
|
||||
CM_DREQ_ATTR_ID = __constant_htons(0x0015),
|
||||
CM_DREP_ATTR_ID = __constant_htons(0x0016),
|
||||
CM_SIDR_REQ_ATTR_ID = __constant_htons(0x0017),
|
||||
CM_SIDR_REP_ATTR_ID = __constant_htons(0x0018),
|
||||
CM_LAP_ATTR_ID = __constant_htons(0x0019),
|
||||
CM_APR_ATTR_ID = __constant_htons(0x001A)
|
||||
};
|
||||
|
||||
enum cm_msg_sequence {
|
||||
CM_MSG_SEQUENCE_REQ,
|
||||
CM_MSG_SEQUENCE_LAP,
|
||||
CM_MSG_SEQUENCE_DREQ,
|
||||
CM_MSG_SEQUENCE_SIDR
|
||||
};
|
||||
|
||||
struct cm_req_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 rsvd4;
|
||||
u64 service_id;
|
||||
u64 local_ca_guid;
|
||||
u32 rsvd24;
|
||||
u32 local_qkey;
|
||||
/* local QPN:24, responder resources:8 */
|
||||
u32 offset32;
|
||||
/* local EECN:24, initiator depth:8 */
|
||||
u32 offset36;
|
||||
/*
|
||||
* remote EECN:24, remote CM response timeout:5,
|
||||
* transport service type:2, end-to-end flow control:1
|
||||
*/
|
||||
u32 offset40;
|
||||
/* starting PSN:24, local CM response timeout:5, retry count:3 */
|
||||
u32 offset44;
|
||||
u16 pkey;
|
||||
/* path MTU:4, RDC exists:1, RNR retry count:3. */
|
||||
u8 offset50;
|
||||
/* max CM Retries:4, SRQ:1, rsvd:3 */
|
||||
u8 offset51;
|
||||
|
||||
u16 primary_local_lid;
|
||||
u16 primary_remote_lid;
|
||||
union ib_gid primary_local_gid;
|
||||
union ib_gid primary_remote_gid;
|
||||
/* flow label:20, rsvd:6, packet rate:6 */
|
||||
u32 primary_offset88;
|
||||
u8 primary_traffic_class;
|
||||
u8 primary_hop_limit;
|
||||
/* SL:4, subnet local:1, rsvd:3 */
|
||||
u8 primary_offset94;
|
||||
/* local ACK timeout:5, rsvd:3 */
|
||||
u8 primary_offset95;
|
||||
|
||||
u16 alt_local_lid;
|
||||
u16 alt_remote_lid;
|
||||
union ib_gid alt_local_gid;
|
||||
union ib_gid alt_remote_gid;
|
||||
/* flow label:20, rsvd:6, packet rate:6 */
|
||||
u32 alt_offset132;
|
||||
u8 alt_traffic_class;
|
||||
u8 alt_hop_limit;
|
||||
/* SL:4, subnet local:1, rsvd:3 */
|
||||
u8 alt_offset138;
|
||||
/* local ACK timeout:5, rsvd:3 */
|
||||
u8 alt_offset139;
|
||||
|
||||
u8 private_data[IB_CM_REQ_PRIVATE_DATA_SIZE];
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u32 cm_req_get_local_qpn(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(req_msg->offset32) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_local_qpn(struct cm_req_msg *req_msg, u32 qpn)
|
||||
{
|
||||
req_msg->offset32 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
|
||||
(be32_to_cpu(req_msg->offset32) &
|
||||
0x000000FF));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_resp_res(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) be32_to_cpu(req_msg->offset32);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_resp_res(struct cm_req_msg *req_msg, u8 resp_res)
|
||||
{
|
||||
req_msg->offset32 = cpu_to_be32(resp_res |
|
||||
(be32_to_cpu(req_msg->offset32) &
|
||||
0xFFFFFF00));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_init_depth(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) be32_to_cpu(req_msg->offset36);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_init_depth(struct cm_req_msg *req_msg,
|
||||
u8 init_depth)
|
||||
{
|
||||
req_msg->offset36 = cpu_to_be32(init_depth |
|
||||
(be32_to_cpu(req_msg->offset36) &
|
||||
0xFFFFFF00));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_remote_resp_timeout(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) ((be32_to_cpu(req_msg->offset40) & 0xF8) >> 3);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_remote_resp_timeout(struct cm_req_msg *req_msg,
|
||||
u8 resp_timeout)
|
||||
{
|
||||
req_msg->offset40 = cpu_to_be32((resp_timeout << 3) |
|
||||
(be32_to_cpu(req_msg->offset40) &
|
||||
0xFFFFFF07));
|
||||
}
|
||||
|
||||
static inline enum ib_qp_type cm_req_get_qp_type(struct cm_req_msg *req_msg)
|
||||
{
|
||||
u8 transport_type = (u8) (be32_to_cpu(req_msg->offset40) & 0x06) >> 1;
|
||||
switch(transport_type) {
|
||||
case 0: return IB_QPT_RC;
|
||||
case 1: return IB_QPT_UC;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cm_req_set_qp_type(struct cm_req_msg *req_msg,
|
||||
enum ib_qp_type qp_type)
|
||||
{
|
||||
switch(qp_type) {
|
||||
case IB_QPT_UC:
|
||||
req_msg->offset40 = cpu_to_be32((be32_to_cpu(
|
||||
req_msg->offset40) &
|
||||
0xFFFFFFF9) | 0x2);
|
||||
default:
|
||||
req_msg->offset40 = cpu_to_be32(be32_to_cpu(
|
||||
req_msg->offset40) &
|
||||
0xFFFFFFF9);
|
||||
}
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_flow_ctrl(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return be32_to_cpu(req_msg->offset40) & 0x1;
|
||||
}
|
||||
|
||||
static inline void cm_req_set_flow_ctrl(struct cm_req_msg *req_msg,
|
||||
u8 flow_ctrl)
|
||||
{
|
||||
req_msg->offset40 = cpu_to_be32((flow_ctrl & 0x1) |
|
||||
(be32_to_cpu(req_msg->offset40) &
|
||||
0xFFFFFFFE));
|
||||
}
|
||||
|
||||
static inline u32 cm_req_get_starting_psn(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(req_msg->offset44) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_starting_psn(struct cm_req_msg *req_msg,
|
||||
u32 starting_psn)
|
||||
{
|
||||
req_msg->offset44 = cpu_to_be32((be32_to_cpu(starting_psn) << 8) |
|
||||
(be32_to_cpu(req_msg->offset44) & 0x000000FF));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_local_resp_timeout(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) ((be32_to_cpu(req_msg->offset44) & 0xF8) >> 3);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_local_resp_timeout(struct cm_req_msg *req_msg,
|
||||
u8 resp_timeout)
|
||||
{
|
||||
req_msg->offset44 = cpu_to_be32((resp_timeout << 3) |
|
||||
(be32_to_cpu(req_msg->offset44) & 0xFFFFFF07));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_retry_count(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) (be32_to_cpu(req_msg->offset44) & 0x7);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_retry_count(struct cm_req_msg *req_msg,
|
||||
u8 retry_count)
|
||||
{
|
||||
req_msg->offset44 = cpu_to_be32((retry_count & 0x7) |
|
||||
(be32_to_cpu(req_msg->offset44) & 0xFFFFFFF8));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_path_mtu(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return req_msg->offset50 >> 4;
|
||||
}
|
||||
|
||||
static inline void cm_req_set_path_mtu(struct cm_req_msg *req_msg, u8 path_mtu)
|
||||
{
|
||||
req_msg->offset50 = (u8) ((req_msg->offset50 & 0xF) | (path_mtu << 4));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_rnr_retry_count(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return req_msg->offset50 & 0x7;
|
||||
}
|
||||
|
||||
static inline void cm_req_set_rnr_retry_count(struct cm_req_msg *req_msg,
|
||||
u8 rnr_retry_count)
|
||||
{
|
||||
req_msg->offset50 = (u8) ((req_msg->offset50 & 0xF8) |
|
||||
(rnr_retry_count & 0x7));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_max_cm_retries(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return req_msg->offset51 >> 4;
|
||||
}
|
||||
|
||||
static inline void cm_req_set_max_cm_retries(struct cm_req_msg *req_msg,
|
||||
u8 retries)
|
||||
{
|
||||
req_msg->offset51 = (u8) ((req_msg->offset51 & 0xF) | (retries << 4));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_srq(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (req_msg->offset51 & 0x8) >> 3;
|
||||
}
|
||||
|
||||
static inline void cm_req_set_srq(struct cm_req_msg *req_msg, u8 srq)
|
||||
{
|
||||
req_msg->offset51 = (u8) ((req_msg->offset51 & 0xF7) |
|
||||
((srq & 0x1) << 3));
|
||||
}
|
||||
|
||||
static inline u32 cm_req_get_primary_flow_label(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return cpu_to_be32((be32_to_cpu(req_msg->primary_offset88) >> 12));
|
||||
}
|
||||
|
||||
static inline void cm_req_set_primary_flow_label(struct cm_req_msg *req_msg,
|
||||
u32 flow_label)
|
||||
{
|
||||
req_msg->primary_offset88 = cpu_to_be32(
|
||||
(be32_to_cpu(req_msg->primary_offset88) &
|
||||
0x00000FFF) |
|
||||
(be32_to_cpu(flow_label) << 12));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_primary_packet_rate(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) (be32_to_cpu(req_msg->primary_offset88) & 0x3F);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_primary_packet_rate(struct cm_req_msg *req_msg,
|
||||
u8 rate)
|
||||
{
|
||||
req_msg->primary_offset88 = cpu_to_be32(
|
||||
(be32_to_cpu(req_msg->primary_offset88) &
|
||||
0xFFFFFFC0) | (rate & 0x3F));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_primary_sl(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) (req_msg->primary_offset94 >> 4);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_primary_sl(struct cm_req_msg *req_msg, u8 sl)
|
||||
{
|
||||
req_msg->primary_offset94 = (u8) ((req_msg->primary_offset94 & 0x0F) |
|
||||
(sl << 4));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_primary_subnet_local(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) ((req_msg->primary_offset94 & 0x08) >> 3);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_primary_subnet_local(struct cm_req_msg *req_msg,
|
||||
u8 subnet_local)
|
||||
{
|
||||
req_msg->primary_offset94 = (u8) ((req_msg->primary_offset94 & 0xF7) |
|
||||
((subnet_local & 0x1) << 3));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_primary_local_ack_timeout(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) (req_msg->primary_offset95 >> 3);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_primary_local_ack_timeout(struct cm_req_msg *req_msg,
|
||||
u8 local_ack_timeout)
|
||||
{
|
||||
req_msg->primary_offset95 = (u8) ((req_msg->primary_offset95 & 0x07) |
|
||||
(local_ack_timeout << 3));
|
||||
}
|
||||
|
||||
static inline u32 cm_req_get_alt_flow_label(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return cpu_to_be32((be32_to_cpu(req_msg->alt_offset132) >> 12));
|
||||
}
|
||||
|
||||
static inline void cm_req_set_alt_flow_label(struct cm_req_msg *req_msg,
|
||||
u32 flow_label)
|
||||
{
|
||||
req_msg->alt_offset132 = cpu_to_be32(
|
||||
(be32_to_cpu(req_msg->alt_offset132) &
|
||||
0x00000FFF) |
|
||||
(be32_to_cpu(flow_label) << 12));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_alt_packet_rate(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) (be32_to_cpu(req_msg->alt_offset132) & 0x3F);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_alt_packet_rate(struct cm_req_msg *req_msg,
|
||||
u8 rate)
|
||||
{
|
||||
req_msg->alt_offset132 = cpu_to_be32(
|
||||
(be32_to_cpu(req_msg->alt_offset132) &
|
||||
0xFFFFFFC0) | (rate & 0x3F));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_alt_sl(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) (req_msg->alt_offset138 >> 4);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_alt_sl(struct cm_req_msg *req_msg, u8 sl)
|
||||
{
|
||||
req_msg->alt_offset138 = (u8) ((req_msg->alt_offset138 & 0x0F) |
|
||||
(sl << 4));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_alt_subnet_local(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) ((req_msg->alt_offset138 & 0x08) >> 3);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_alt_subnet_local(struct cm_req_msg *req_msg,
|
||||
u8 subnet_local)
|
||||
{
|
||||
req_msg->alt_offset138 = (u8) ((req_msg->alt_offset138 & 0xF7) |
|
||||
((subnet_local & 0x1) << 3));
|
||||
}
|
||||
|
||||
static inline u8 cm_req_get_alt_local_ack_timeout(struct cm_req_msg *req_msg)
|
||||
{
|
||||
return (u8) (req_msg->alt_offset139 >> 3);
|
||||
}
|
||||
|
||||
static inline void cm_req_set_alt_local_ack_timeout(struct cm_req_msg *req_msg,
|
||||
u8 local_ack_timeout)
|
||||
{
|
||||
req_msg->alt_offset139 = (u8) ((req_msg->alt_offset139 & 0x07) |
|
||||
(local_ack_timeout << 3));
|
||||
}
|
||||
|
||||
/* Message REJected or MRAed */
|
||||
enum cm_msg_response {
|
||||
CM_MSG_RESPONSE_REQ = 0x0,
|
||||
CM_MSG_RESPONSE_REP = 0x1,
|
||||
CM_MSG_RESPONSE_OTHER = 0x2
|
||||
};
|
||||
|
||||
struct cm_mra_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
/* message MRAed:2, rsvd:6 */
|
||||
u8 offset8;
|
||||
/* service timeout:5, rsvd:3 */
|
||||
u8 offset9;
|
||||
|
||||
u8 private_data[IB_CM_MRA_PRIVATE_DATA_SIZE];
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u8 cm_mra_get_msg_mraed(struct cm_mra_msg *mra_msg)
|
||||
{
|
||||
return (u8) (mra_msg->offset8 >> 6);
|
||||
}
|
||||
|
||||
static inline void cm_mra_set_msg_mraed(struct cm_mra_msg *mra_msg, u8 msg)
|
||||
{
|
||||
mra_msg->offset8 = (u8) ((mra_msg->offset8 & 0x3F) | (msg << 6));
|
||||
}
|
||||
|
||||
static inline u8 cm_mra_get_service_timeout(struct cm_mra_msg *mra_msg)
|
||||
{
|
||||
return (u8) (mra_msg->offset9 >> 3);
|
||||
}
|
||||
|
||||
static inline void cm_mra_set_service_timeout(struct cm_mra_msg *mra_msg,
|
||||
u8 service_timeout)
|
||||
{
|
||||
mra_msg->offset9 = (u8) ((mra_msg->offset9 & 0x07) |
|
||||
(service_timeout << 3));
|
||||
}
|
||||
|
||||
struct cm_rej_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
/* message REJected:2, rsvd:6 */
|
||||
u8 offset8;
|
||||
/* reject info length:7, rsvd:1. */
|
||||
u8 offset9;
|
||||
u16 reason;
|
||||
u8 ari[IB_CM_REJ_ARI_LENGTH];
|
||||
|
||||
u8 private_data[IB_CM_REJ_PRIVATE_DATA_SIZE];
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u8 cm_rej_get_msg_rejected(struct cm_rej_msg *rej_msg)
|
||||
{
|
||||
return (u8) (rej_msg->offset8 >> 6);
|
||||
}
|
||||
|
||||
static inline void cm_rej_set_msg_rejected(struct cm_rej_msg *rej_msg, u8 msg)
|
||||
{
|
||||
rej_msg->offset8 = (u8) ((rej_msg->offset8 & 0x3F) | (msg << 6));
|
||||
}
|
||||
|
||||
static inline u8 cm_rej_get_reject_info_len(struct cm_rej_msg *rej_msg)
|
||||
{
|
||||
return (u8) (rej_msg->offset9 >> 1);
|
||||
}
|
||||
|
||||
static inline void cm_rej_set_reject_info_len(struct cm_rej_msg *rej_msg,
|
||||
u8 len)
|
||||
{
|
||||
rej_msg->offset9 = (u8) ((rej_msg->offset9 & 0x1) | (len << 1));
|
||||
}
|
||||
|
||||
struct cm_rep_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
u32 local_qkey;
|
||||
/* local QPN:24, rsvd:8 */
|
||||
u32 offset12;
|
||||
/* local EECN:24, rsvd:8 */
|
||||
u32 offset16;
|
||||
/* starting PSN:24 rsvd:8 */
|
||||
u32 offset20;
|
||||
u8 resp_resources;
|
||||
u8 initiator_depth;
|
||||
/* target ACK delay:5, failover accepted:2, end-to-end flow control:1 */
|
||||
u8 offset26;
|
||||
/* RNR retry count:3, SRQ:1, rsvd:5 */
|
||||
u8 offset27;
|
||||
u64 local_ca_guid;
|
||||
|
||||
u8 private_data[IB_CM_REP_PRIVATE_DATA_SIZE];
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u32 cm_rep_get_local_qpn(struct cm_rep_msg *rep_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(rep_msg->offset12) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, u32 qpn)
|
||||
{
|
||||
rep_msg->offset12 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
|
||||
(be32_to_cpu(rep_msg->offset12) & 0x000000FF));
|
||||
}
|
||||
|
||||
static inline u32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_rep_set_starting_psn(struct cm_rep_msg *rep_msg,
|
||||
u32 starting_psn)
|
||||
{
|
||||
rep_msg->offset20 = cpu_to_be32((be32_to_cpu(starting_psn) << 8) |
|
||||
(be32_to_cpu(rep_msg->offset20) & 0x000000FF));
|
||||
}
|
||||
|
||||
static inline u8 cm_rep_get_target_ack_delay(struct cm_rep_msg *rep_msg)
|
||||
{
|
||||
return (u8) (rep_msg->offset26 >> 3);
|
||||
}
|
||||
|
||||
static inline void cm_rep_set_target_ack_delay(struct cm_rep_msg *rep_msg,
|
||||
u8 target_ack_delay)
|
||||
{
|
||||
rep_msg->offset26 = (u8) ((rep_msg->offset26 & 0x07) |
|
||||
(target_ack_delay << 3));
|
||||
}
|
||||
|
||||
static inline u8 cm_rep_get_failover(struct cm_rep_msg *rep_msg)
|
||||
{
|
||||
return (u8) ((rep_msg->offset26 & 0x06) >> 1);
|
||||
}
|
||||
|
||||
static inline void cm_rep_set_failover(struct cm_rep_msg *rep_msg, u8 failover)
|
||||
{
|
||||
rep_msg->offset26 = (u8) ((rep_msg->offset26 & 0xF9) |
|
||||
((failover & 0x3) << 1));
|
||||
}
|
||||
|
||||
static inline u8 cm_rep_get_flow_ctrl(struct cm_rep_msg *rep_msg)
|
||||
{
|
||||
return (u8) (rep_msg->offset26 & 0x01);
|
||||
}
|
||||
|
||||
static inline void cm_rep_set_flow_ctrl(struct cm_rep_msg *rep_msg,
|
||||
u8 flow_ctrl)
|
||||
{
|
||||
rep_msg->offset26 = (u8) ((rep_msg->offset26 & 0xFE) |
|
||||
(flow_ctrl & 0x1));
|
||||
}
|
||||
|
||||
static inline u8 cm_rep_get_rnr_retry_count(struct cm_rep_msg *rep_msg)
|
||||
{
|
||||
return (u8) (rep_msg->offset27 >> 5);
|
||||
}
|
||||
|
||||
static inline void cm_rep_set_rnr_retry_count(struct cm_rep_msg *rep_msg,
|
||||
u8 rnr_retry_count)
|
||||
{
|
||||
rep_msg->offset27 = (u8) ((rep_msg->offset27 & 0x1F) |
|
||||
(rnr_retry_count << 5));
|
||||
}
|
||||
|
||||
static inline u8 cm_rep_get_srq(struct cm_rep_msg *rep_msg)
|
||||
{
|
||||
return (u8) ((rep_msg->offset27 >> 4) & 0x1);
|
||||
}
|
||||
|
||||
static inline void cm_rep_set_srq(struct cm_rep_msg *rep_msg, u8 srq)
|
||||
{
|
||||
rep_msg->offset27 = (u8) ((rep_msg->offset27 & 0xEF) |
|
||||
((srq & 0x1) << 4));
|
||||
}
|
||||
|
||||
struct cm_rtu_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
|
||||
u8 private_data[IB_CM_RTU_PRIVATE_DATA_SIZE];
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cm_dreq_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
/* remote QPN/EECN:24, rsvd:8 */
|
||||
u32 offset8;
|
||||
|
||||
u8 private_data[IB_CM_DREQ_PRIVATE_DATA_SIZE];
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u32 cm_dreq_get_remote_qpn(struct cm_dreq_msg *dreq_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(dreq_msg->offset8) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_dreq_set_remote_qpn(struct cm_dreq_msg *dreq_msg, u32 qpn)
|
||||
{
|
||||
dreq_msg->offset8 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
|
||||
(be32_to_cpu(dreq_msg->offset8) & 0x000000FF));
|
||||
}
|
||||
|
||||
struct cm_drep_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
|
||||
u8 private_data[IB_CM_DREP_PRIVATE_DATA_SIZE];
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cm_lap_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
|
||||
u32 rsvd8;
|
||||
/* remote QPN/EECN:24, remote CM response timeout:5, rsvd:3 */
|
||||
u32 offset12;
|
||||
u32 rsvd16;
|
||||
|
||||
u16 alt_local_lid;
|
||||
u16 alt_remote_lid;
|
||||
union ib_gid alt_local_gid;
|
||||
union ib_gid alt_remote_gid;
|
||||
/* flow label:20, rsvd:4, traffic class:8 */
|
||||
u32 offset56;
|
||||
u8 alt_hop_limit;
|
||||
/* rsvd:2, packet rate:6 */
|
||||
uint8_t offset61;
|
||||
/* SL:4, subnet local:1, rsvd:3 */
|
||||
uint8_t offset62;
|
||||
/* local ACK timeout:5, rsvd:3 */
|
||||
uint8_t offset63;
|
||||
|
||||
u8 private_data[IB_CM_LAP_PRIVATE_DATA_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u32 cm_lap_get_remote_qpn(struct cm_lap_msg *lap_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(lap_msg->offset12) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_lap_set_remote_qpn(struct cm_lap_msg *lap_msg, u32 qpn)
|
||||
{
|
||||
lap_msg->offset12 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
|
||||
(be32_to_cpu(lap_msg->offset12) &
|
||||
0x000000FF));
|
||||
}
|
||||
|
||||
static inline u8 cm_lap_get_remote_resp_timeout(struct cm_lap_msg *lap_msg)
|
||||
{
|
||||
return (u8) ((be32_to_cpu(lap_msg->offset12) & 0xF8) >> 3);
|
||||
}
|
||||
|
||||
static inline void cm_lap_set_remote_resp_timeout(struct cm_lap_msg *lap_msg,
|
||||
u8 resp_timeout)
|
||||
{
|
||||
lap_msg->offset12 = cpu_to_be32((resp_timeout << 3) |
|
||||
(be32_to_cpu(lap_msg->offset12) &
|
||||
0xFFFFFF07));
|
||||
}
|
||||
|
||||
static inline u32 cm_lap_get_flow_label(struct cm_lap_msg *lap_msg)
|
||||
{
|
||||
return be32_to_cpu(lap_msg->offset56) >> 12;
|
||||
}
|
||||
|
||||
static inline void cm_lap_set_flow_label(struct cm_lap_msg *lap_msg,
|
||||
u32 flow_label)
|
||||
{
|
||||
lap_msg->offset56 = cpu_to_be32((flow_label << 12) |
|
||||
(be32_to_cpu(lap_msg->offset56) &
|
||||
0x00000FFF));
|
||||
}
|
||||
|
||||
static inline u8 cm_lap_get_traffic_class(struct cm_lap_msg *lap_msg)
|
||||
{
|
||||
return (u8) be32_to_cpu(lap_msg->offset56);
|
||||
}
|
||||
|
||||
static inline void cm_lap_set_traffic_class(struct cm_lap_msg *lap_msg,
|
||||
u8 traffic_class)
|
||||
{
|
||||
lap_msg->offset56 = cpu_to_be32(traffic_class |
|
||||
(be32_to_cpu(lap_msg->offset56) &
|
||||
0xFFFFFF00));
|
||||
}
|
||||
|
||||
static inline u8 cm_lap_get_packet_rate(struct cm_lap_msg *lap_msg)
|
||||
{
|
||||
return lap_msg->offset61 & 0x3F;
|
||||
}
|
||||
|
||||
static inline void cm_lap_set_packet_rate(struct cm_lap_msg *lap_msg,
|
||||
u8 packet_rate)
|
||||
{
|
||||
lap_msg->offset61 = (packet_rate & 0x3F) | (lap_msg->offset61 & 0xC0);
|
||||
}
|
||||
|
||||
static inline u8 cm_lap_get_sl(struct cm_lap_msg *lap_msg)
|
||||
{
|
||||
return lap_msg->offset62 >> 4;
|
||||
}
|
||||
|
||||
static inline void cm_lap_set_sl(struct cm_lap_msg *lap_msg, u8 sl)
|
||||
{
|
||||
lap_msg->offset62 = (sl << 4) | (lap_msg->offset62 & 0x0F);
|
||||
}
|
||||
|
||||
static inline u8 cm_lap_get_subnet_local(struct cm_lap_msg *lap_msg)
|
||||
{
|
||||
return (lap_msg->offset62 >> 3) & 0x1;
|
||||
}
|
||||
|
||||
static inline void cm_lap_set_subnet_local(struct cm_lap_msg *lap_msg,
|
||||
u8 subnet_local)
|
||||
{
|
||||
lap_msg->offset62 = ((subnet_local & 0x1) << 3) |
|
||||
(lap_msg->offset61 & 0xF7);
|
||||
}
|
||||
static inline u8 cm_lap_get_local_ack_timeout(struct cm_lap_msg *lap_msg)
|
||||
{
|
||||
return lap_msg->offset63 >> 3;
|
||||
}
|
||||
|
||||
static inline void cm_lap_set_local_ack_timeout(struct cm_lap_msg *lap_msg,
|
||||
u8 local_ack_timeout)
|
||||
{
|
||||
lap_msg->offset63 = (local_ack_timeout << 3) |
|
||||
(lap_msg->offset63 & 0x07);
|
||||
}
|
||||
|
||||
struct cm_apr_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 local_comm_id;
|
||||
u32 remote_comm_id;
|
||||
|
||||
u8 info_length;
|
||||
u8 ap_status;
|
||||
u8 info[IB_CM_APR_INFO_LENGTH];
|
||||
|
||||
u8 private_data[IB_CM_APR_PRIVATE_DATA_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cm_sidr_req_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 request_id;
|
||||
u16 pkey;
|
||||
u16 rsvd;
|
||||
u64 service_id;
|
||||
|
||||
u8 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cm_sidr_rep_msg {
|
||||
struct ib_mad_hdr hdr;
|
||||
|
||||
u32 request_id;
|
||||
u8 status;
|
||||
u8 info_length;
|
||||
u16 rsvd;
|
||||
/* QPN:24, rsvd:8 */
|
||||
u32 offset8;
|
||||
u64 service_id;
|
||||
u32 qkey;
|
||||
u8 info[IB_CM_SIDR_REP_INFO_LENGTH];
|
||||
|
||||
u8 private_data[IB_CM_SIDR_REP_PRIVATE_DATA_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline u32 cm_sidr_rep_get_qpn(struct cm_sidr_rep_msg *sidr_rep_msg)
|
||||
{
|
||||
return cpu_to_be32(be32_to_cpu(sidr_rep_msg->offset8) >> 8);
|
||||
}
|
||||
|
||||
static inline void cm_sidr_rep_set_qpn(struct cm_sidr_rep_msg *sidr_rep_msg,
|
||||
u32 qpn)
|
||||
{
|
||||
sidr_rep_msg->offset8 = cpu_to_be32((be32_to_cpu(qpn) << 8) |
|
||||
(be32_to_cpu(sidr_rep_msg->offset8) &
|
||||
0x000000FF));
|
||||
}
|
||||
|
||||
#endif /* CM_MSGS_H */
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. 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
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* $Id: fmr_pool.c 1349 2004-12-16 21:09:43Z roland $
|
||||
* $Id: fmr_pool.c 2730 2005-06-28 16:43:03Z sean.hefty $
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
|
|
@ -329,7 +330,7 @@ EXPORT_SYMBOL(ib_create_fmr_pool);
|
|||
*
|
||||
* Destroy an FMR pool and free all associated resources.
|
||||
*/
|
||||
int ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
|
||||
void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
|
||||
{
|
||||
struct ib_pool_fmr *fmr;
|
||||
struct ib_pool_fmr *tmp;
|
||||
|
|
@ -352,8 +353,6 @@ int ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
|
|||
|
||||
kfree(pool->cache_bucket);
|
||||
kfree(pool);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_destroy_fmr_pool);
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2004, 2005, Voltaire, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. 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
|
||||
|
|
@ -29,7 +31,7 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* $Id: mad_priv.h 1389 2004-12-27 22:56:47Z roland $
|
||||
* $Id: mad_priv.h 2730 2005-06-28 16:43:03Z sean.hefty $
|
||||
*/
|
||||
|
||||
#ifndef __IB_MAD_PRIV_H__
|
||||
|
|
@ -92,16 +94,15 @@ struct ib_mad_agent_private {
|
|||
spinlock_t lock;
|
||||
struct list_head send_list;
|
||||
struct list_head wait_list;
|
||||
struct list_head done_list;
|
||||
struct work_struct timed_work;
|
||||
unsigned long timeout;
|
||||
struct list_head local_list;
|
||||
struct work_struct local_work;
|
||||
struct list_head canceled_list;
|
||||
struct work_struct canceled_work;
|
||||
struct list_head rmpp_list;
|
||||
|
||||
atomic_t refcount;
|
||||
wait_queue_head_t wait;
|
||||
u8 rmpp_version;
|
||||
};
|
||||
|
||||
struct ib_mad_snoop_private {
|
||||
|
|
@ -116,15 +117,24 @@ struct ib_mad_snoop_private {
|
|||
struct ib_mad_send_wr_private {
|
||||
struct ib_mad_list_head mad_list;
|
||||
struct list_head agent_list;
|
||||
struct ib_mad_agent *agent;
|
||||
struct ib_mad_agent_private *mad_agent_priv;
|
||||
struct ib_send_wr send_wr;
|
||||
struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
|
||||
u64 wr_id; /* client WR ID */
|
||||
u64 tid;
|
||||
unsigned long timeout;
|
||||
int retries;
|
||||
int retry;
|
||||
int refcount;
|
||||
enum ib_wc_status status;
|
||||
|
||||
/* RMPP control */
|
||||
int last_ack;
|
||||
int seg_num;
|
||||
int newwin;
|
||||
int total_seg;
|
||||
int data_offset;
|
||||
int pad;
|
||||
};
|
||||
|
||||
struct ib_mad_local_private {
|
||||
|
|
@ -197,4 +207,17 @@ struct ib_mad_port_private {
|
|||
|
||||
extern kmem_cache_t *ib_mad_cache;
|
||||
|
||||
int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr);
|
||||
|
||||
struct ib_mad_send_wr_private *
|
||||
ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, u64 tid);
|
||||
|
||||
void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
|
||||
struct ib_mad_send_wc *mad_send_wc);
|
||||
|
||||
void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr);
|
||||
|
||||
void ib_reset_mad_timeout(struct ib_mad_send_wr_private *mad_send_wr,
|
||||
int timeout_ms);
|
||||
|
||||
#endif /* __IB_MAD_PRIV_H__ */
|
||||
|
|
|
|||
765
drivers/infiniband/core/mad_rmpp.c
Normal file
765
drivers/infiniband/core/mad_rmpp.c
Normal file
|
|
@ -0,0 +1,765 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Intel Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. 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_rmpp.c 1921 2005-03-02 22:58:44Z sean.hefty $
|
||||
*/
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include "mad_priv.h"
|
||||
#include "mad_rmpp.h"
|
||||
|
||||
enum rmpp_state {
|
||||
RMPP_STATE_ACTIVE,
|
||||
RMPP_STATE_TIMEOUT,
|
||||
RMPP_STATE_COMPLETE
|
||||
};
|
||||
|
||||
struct mad_rmpp_recv {
|
||||
struct ib_mad_agent_private *agent;
|
||||
struct list_head list;
|
||||
struct work_struct timeout_work;
|
||||
struct work_struct cleanup_work;
|
||||
wait_queue_head_t wait;
|
||||
enum rmpp_state state;
|
||||
spinlock_t lock;
|
||||
atomic_t refcount;
|
||||
|
||||
struct ib_ah *ah;
|
||||
struct ib_mad_recv_wc *rmpp_wc;
|
||||
struct ib_mad_recv_buf *cur_seg_buf;
|
||||
int last_ack;
|
||||
int seg_num;
|
||||
int newwin;
|
||||
|
||||
u64 tid;
|
||||
u32 src_qp;
|
||||
u16 slid;
|
||||
u8 mgmt_class;
|
||||
u8 class_version;
|
||||
u8 method;
|
||||
};
|
||||
|
||||
static void destroy_rmpp_recv(struct mad_rmpp_recv *rmpp_recv)
|
||||
{
|
||||
atomic_dec(&rmpp_recv->refcount);
|
||||
wait_event(rmpp_recv->wait, !atomic_read(&rmpp_recv->refcount));
|
||||
ib_destroy_ah(rmpp_recv->ah);
|
||||
kfree(rmpp_recv);
|
||||
}
|
||||
|
||||
void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent)
|
||||
{
|
||||
struct mad_rmpp_recv *rmpp_recv, *temp_rmpp_recv;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&agent->lock, flags);
|
||||
list_for_each_entry(rmpp_recv, &agent->rmpp_list, list) {
|
||||
cancel_delayed_work(&rmpp_recv->timeout_work);
|
||||
cancel_delayed_work(&rmpp_recv->cleanup_work);
|
||||
}
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
|
||||
flush_workqueue(agent->qp_info->port_priv->wq);
|
||||
|
||||
list_for_each_entry_safe(rmpp_recv, temp_rmpp_recv,
|
||||
&agent->rmpp_list, list) {
|
||||
list_del(&rmpp_recv->list);
|
||||
if (rmpp_recv->state != RMPP_STATE_COMPLETE)
|
||||
ib_free_recv_mad(rmpp_recv->rmpp_wc);
|
||||
destroy_rmpp_recv(rmpp_recv);
|
||||
}
|
||||
}
|
||||
|
||||
static void recv_timeout_handler(void *data)
|
||||
{
|
||||
struct mad_rmpp_recv *rmpp_recv = data;
|
||||
struct ib_mad_recv_wc *rmpp_wc;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rmpp_recv->agent->lock, flags);
|
||||
if (rmpp_recv->state != RMPP_STATE_ACTIVE) {
|
||||
spin_unlock_irqrestore(&rmpp_recv->agent->lock, flags);
|
||||
return;
|
||||
}
|
||||
rmpp_recv->state = RMPP_STATE_TIMEOUT;
|
||||
list_del(&rmpp_recv->list);
|
||||
spin_unlock_irqrestore(&rmpp_recv->agent->lock, flags);
|
||||
|
||||
/* TODO: send abort. */
|
||||
rmpp_wc = rmpp_recv->rmpp_wc;
|
||||
destroy_rmpp_recv(rmpp_recv);
|
||||
ib_free_recv_mad(rmpp_wc);
|
||||
}
|
||||
|
||||
static void recv_cleanup_handler(void *data)
|
||||
{
|
||||
struct mad_rmpp_recv *rmpp_recv = data;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rmpp_recv->agent->lock, flags);
|
||||
list_del(&rmpp_recv->list);
|
||||
spin_unlock_irqrestore(&rmpp_recv->agent->lock, flags);
|
||||
destroy_rmpp_recv(rmpp_recv);
|
||||
}
|
||||
|
||||
static struct mad_rmpp_recv *
|
||||
create_rmpp_recv(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
{
|
||||
struct mad_rmpp_recv *rmpp_recv;
|
||||
struct ib_mad_hdr *mad_hdr;
|
||||
|
||||
rmpp_recv = kmalloc(sizeof *rmpp_recv, GFP_KERNEL);
|
||||
if (!rmpp_recv)
|
||||
return NULL;
|
||||
|
||||
rmpp_recv->ah = ib_create_ah_from_wc(agent->agent.qp->pd,
|
||||
mad_recv_wc->wc,
|
||||
mad_recv_wc->recv_buf.grh,
|
||||
agent->agent.port_num);
|
||||
if (IS_ERR(rmpp_recv->ah))
|
||||
goto error;
|
||||
|
||||
rmpp_recv->agent = agent;
|
||||
init_waitqueue_head(&rmpp_recv->wait);
|
||||
INIT_WORK(&rmpp_recv->timeout_work, recv_timeout_handler, rmpp_recv);
|
||||
INIT_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler, rmpp_recv);
|
||||
spin_lock_init(&rmpp_recv->lock);
|
||||
rmpp_recv->state = RMPP_STATE_ACTIVE;
|
||||
atomic_set(&rmpp_recv->refcount, 1);
|
||||
|
||||
rmpp_recv->rmpp_wc = mad_recv_wc;
|
||||
rmpp_recv->cur_seg_buf = &mad_recv_wc->recv_buf;
|
||||
rmpp_recv->newwin = 1;
|
||||
rmpp_recv->seg_num = 1;
|
||||
rmpp_recv->last_ack = 0;
|
||||
|
||||
mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr;
|
||||
rmpp_recv->tid = mad_hdr->tid;
|
||||
rmpp_recv->src_qp = mad_recv_wc->wc->src_qp;
|
||||
rmpp_recv->slid = mad_recv_wc->wc->slid;
|
||||
rmpp_recv->mgmt_class = mad_hdr->mgmt_class;
|
||||
rmpp_recv->class_version = mad_hdr->class_version;
|
||||
rmpp_recv->method = mad_hdr->method;
|
||||
return rmpp_recv;
|
||||
|
||||
error: kfree(rmpp_recv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void deref_rmpp_recv(struct mad_rmpp_recv *rmpp_recv)
|
||||
{
|
||||
if (atomic_dec_and_test(&rmpp_recv->refcount))
|
||||
wake_up(&rmpp_recv->wait);
|
||||
}
|
||||
|
||||
static struct mad_rmpp_recv *
|
||||
find_rmpp_recv(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
{
|
||||
struct mad_rmpp_recv *rmpp_recv;
|
||||
struct ib_mad_hdr *mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr;
|
||||
|
||||
list_for_each_entry(rmpp_recv, &agent->rmpp_list, list) {
|
||||
if (rmpp_recv->tid == mad_hdr->tid &&
|
||||
rmpp_recv->src_qp == mad_recv_wc->wc->src_qp &&
|
||||
rmpp_recv->slid == mad_recv_wc->wc->slid &&
|
||||
rmpp_recv->mgmt_class == mad_hdr->mgmt_class &&
|
||||
rmpp_recv->class_version == mad_hdr->class_version &&
|
||||
rmpp_recv->method == mad_hdr->method)
|
||||
return rmpp_recv;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct mad_rmpp_recv *
|
||||
acquire_rmpp_recv(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
{
|
||||
struct mad_rmpp_recv *rmpp_recv;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&agent->lock, flags);
|
||||
rmpp_recv = find_rmpp_recv(agent, mad_recv_wc);
|
||||
if (rmpp_recv)
|
||||
atomic_inc(&rmpp_recv->refcount);
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
return rmpp_recv;
|
||||
}
|
||||
|
||||
static struct mad_rmpp_recv *
|
||||
insert_rmpp_recv(struct ib_mad_agent_private *agent,
|
||||
struct mad_rmpp_recv *rmpp_recv)
|
||||
{
|
||||
struct mad_rmpp_recv *cur_rmpp_recv;
|
||||
|
||||
cur_rmpp_recv = find_rmpp_recv(agent, rmpp_recv->rmpp_wc);
|
||||
if (!cur_rmpp_recv)
|
||||
list_add_tail(&rmpp_recv->list, &agent->rmpp_list);
|
||||
|
||||
return cur_rmpp_recv;
|
||||
}
|
||||
|
||||
static int data_offset(u8 mgmt_class)
|
||||
{
|
||||
if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
|
||||
return offsetof(struct ib_sa_mad, data);
|
||||
else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
|
||||
(mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
|
||||
return offsetof(struct ib_vendor_mad, data);
|
||||
else
|
||||
return offsetof(struct ib_rmpp_mad, data);
|
||||
}
|
||||
|
||||
static void format_ack(struct ib_rmpp_mad *ack,
|
||||
struct ib_rmpp_mad *data,
|
||||
struct mad_rmpp_recv *rmpp_recv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
memcpy(&ack->mad_hdr, &data->mad_hdr,
|
||||
data_offset(data->mad_hdr.mgmt_class));
|
||||
|
||||
ack->mad_hdr.method ^= IB_MGMT_METHOD_RESP;
|
||||
ack->rmpp_hdr.rmpp_type = IB_MGMT_RMPP_TYPE_ACK;
|
||||
ib_set_rmpp_flags(&ack->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
|
||||
|
||||
spin_lock_irqsave(&rmpp_recv->lock, flags);
|
||||
rmpp_recv->last_ack = rmpp_recv->seg_num;
|
||||
ack->rmpp_hdr.seg_num = cpu_to_be32(rmpp_recv->seg_num);
|
||||
ack->rmpp_hdr.paylen_newwin = cpu_to_be32(rmpp_recv->newwin);
|
||||
spin_unlock_irqrestore(&rmpp_recv->lock, flags);
|
||||
}
|
||||
|
||||
static void ack_recv(struct mad_rmpp_recv *rmpp_recv,
|
||||
struct ib_mad_recv_wc *recv_wc)
|
||||
{
|
||||
struct ib_mad_send_buf *msg;
|
||||
struct ib_send_wr *bad_send_wr;
|
||||
int hdr_len, ret;
|
||||
|
||||
hdr_len = sizeof(struct ib_mad_hdr) + sizeof(struct ib_rmpp_hdr);
|
||||
msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp,
|
||||
recv_wc->wc->pkey_index, rmpp_recv->ah, 1,
|
||||
hdr_len, sizeof(struct ib_rmpp_mad) - hdr_len,
|
||||
GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
format_ack((struct ib_rmpp_mad *) msg->mad,
|
||||
(struct ib_rmpp_mad *) recv_wc->recv_buf.mad, rmpp_recv);
|
||||
ret = ib_post_send_mad(&rmpp_recv->agent->agent, &msg->send_wr,
|
||||
&bad_send_wr);
|
||||
if (ret)
|
||||
ib_free_send_mad(msg);
|
||||
}
|
||||
|
||||
static inline int get_last_flag(struct ib_mad_recv_buf *seg)
|
||||
{
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *) seg->mad;
|
||||
return ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_LAST;
|
||||
}
|
||||
|
||||
static inline int get_seg_num(struct ib_mad_recv_buf *seg)
|
||||
{
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *) seg->mad;
|
||||
return be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num);
|
||||
}
|
||||
|
||||
static inline struct ib_mad_recv_buf * get_next_seg(struct list_head *rmpp_list,
|
||||
struct ib_mad_recv_buf *seg)
|
||||
{
|
||||
if (seg->list.next == rmpp_list)
|
||||
return NULL;
|
||||
|
||||
return container_of(seg->list.next, struct ib_mad_recv_buf, list);
|
||||
}
|
||||
|
||||
static inline int window_size(struct ib_mad_agent_private *agent)
|
||||
{
|
||||
return max(agent->qp_info->recv_queue.max_active >> 3, 1);
|
||||
}
|
||||
|
||||
static struct ib_mad_recv_buf * find_seg_location(struct list_head *rmpp_list,
|
||||
int seg_num)
|
||||
{
|
||||
struct ib_mad_recv_buf *seg_buf;
|
||||
int cur_seg_num;
|
||||
|
||||
list_for_each_entry_reverse(seg_buf, rmpp_list, list) {
|
||||
cur_seg_num = get_seg_num(seg_buf);
|
||||
if (seg_num > cur_seg_num)
|
||||
return seg_buf;
|
||||
if (seg_num == cur_seg_num)
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void update_seg_num(struct mad_rmpp_recv *rmpp_recv,
|
||||
struct ib_mad_recv_buf *new_buf)
|
||||
{
|
||||
struct list_head *rmpp_list = &rmpp_recv->rmpp_wc->rmpp_list;
|
||||
|
||||
while (new_buf && (get_seg_num(new_buf) == rmpp_recv->seg_num + 1)) {
|
||||
rmpp_recv->cur_seg_buf = new_buf;
|
||||
rmpp_recv->seg_num++;
|
||||
new_buf = get_next_seg(rmpp_list, new_buf);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv)
|
||||
{
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
int hdr_size, data_size, pad;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *)rmpp_recv->cur_seg_buf->mad;
|
||||
|
||||
hdr_size = data_offset(rmpp_mad->mad_hdr.mgmt_class);
|
||||
data_size = sizeof(struct ib_rmpp_mad) - hdr_size;
|
||||
pad = data_size - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
|
||||
if (pad > data_size || pad < 0)
|
||||
pad = 0;
|
||||
|
||||
return hdr_size + rmpp_recv->seg_num * data_size - pad;
|
||||
}
|
||||
|
||||
static struct ib_mad_recv_wc * complete_rmpp(struct mad_rmpp_recv *rmpp_recv)
|
||||
{
|
||||
struct ib_mad_recv_wc *rmpp_wc;
|
||||
|
||||
ack_recv(rmpp_recv, rmpp_recv->rmpp_wc);
|
||||
if (rmpp_recv->seg_num > 1)
|
||||
cancel_delayed_work(&rmpp_recv->timeout_work);
|
||||
|
||||
rmpp_wc = rmpp_recv->rmpp_wc;
|
||||
rmpp_wc->mad_len = get_mad_len(rmpp_recv);
|
||||
/* 10 seconds until we can find the packet lifetime */
|
||||
queue_delayed_work(rmpp_recv->agent->qp_info->port_priv->wq,
|
||||
&rmpp_recv->cleanup_work, msecs_to_jiffies(10000));
|
||||
return rmpp_wc;
|
||||
}
|
||||
|
||||
void ib_coalesce_recv_mad(struct ib_mad_recv_wc *mad_recv_wc, void *buf)
|
||||
{
|
||||
struct ib_mad_recv_buf *seg_buf;
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
void *data;
|
||||
int size, len, offset;
|
||||
u8 flags;
|
||||
|
||||
len = mad_recv_wc->mad_len;
|
||||
if (len <= sizeof(struct ib_mad)) {
|
||||
memcpy(buf, mad_recv_wc->recv_buf.mad, len);
|
||||
return;
|
||||
}
|
||||
|
||||
offset = data_offset(mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class);
|
||||
|
||||
list_for_each_entry(seg_buf, &mad_recv_wc->rmpp_list, list) {
|
||||
rmpp_mad = (struct ib_rmpp_mad *)seg_buf->mad;
|
||||
flags = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr);
|
||||
|
||||
if (flags & IB_MGMT_RMPP_FLAG_FIRST) {
|
||||
data = rmpp_mad;
|
||||
size = sizeof(*rmpp_mad);
|
||||
} else {
|
||||
data = (void *) rmpp_mad + offset;
|
||||
if (flags & IB_MGMT_RMPP_FLAG_LAST)
|
||||
size = len;
|
||||
else
|
||||
size = sizeof(*rmpp_mad) - offset;
|
||||
}
|
||||
|
||||
memcpy(buf, data, size);
|
||||
len -= size;
|
||||
buf += size;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ib_coalesce_recv_mad);
|
||||
|
||||
static struct ib_mad_recv_wc *
|
||||
continue_rmpp(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
{
|
||||
struct mad_rmpp_recv *rmpp_recv;
|
||||
struct ib_mad_recv_buf *prev_buf;
|
||||
struct ib_mad_recv_wc *done_wc;
|
||||
int seg_num;
|
||||
unsigned long flags;
|
||||
|
||||
rmpp_recv = acquire_rmpp_recv(agent, mad_recv_wc);
|
||||
if (!rmpp_recv)
|
||||
goto drop1;
|
||||
|
||||
seg_num = get_seg_num(&mad_recv_wc->recv_buf);
|
||||
|
||||
spin_lock_irqsave(&rmpp_recv->lock, flags);
|
||||
if ((rmpp_recv->state == RMPP_STATE_TIMEOUT) ||
|
||||
(seg_num > rmpp_recv->newwin))
|
||||
goto drop3;
|
||||
|
||||
if ((seg_num <= rmpp_recv->last_ack) ||
|
||||
(rmpp_recv->state == RMPP_STATE_COMPLETE)) {
|
||||
spin_unlock_irqrestore(&rmpp_recv->lock, flags);
|
||||
ack_recv(rmpp_recv, mad_recv_wc);
|
||||
goto drop2;
|
||||
}
|
||||
|
||||
prev_buf = find_seg_location(&rmpp_recv->rmpp_wc->rmpp_list, seg_num);
|
||||
if (!prev_buf)
|
||||
goto drop3;
|
||||
|
||||
done_wc = NULL;
|
||||
list_add(&mad_recv_wc->recv_buf.list, &prev_buf->list);
|
||||
if (rmpp_recv->cur_seg_buf == prev_buf) {
|
||||
update_seg_num(rmpp_recv, &mad_recv_wc->recv_buf);
|
||||
if (get_last_flag(rmpp_recv->cur_seg_buf)) {
|
||||
rmpp_recv->state = RMPP_STATE_COMPLETE;
|
||||
spin_unlock_irqrestore(&rmpp_recv->lock, flags);
|
||||
done_wc = complete_rmpp(rmpp_recv);
|
||||
goto out;
|
||||
} else if (rmpp_recv->seg_num == rmpp_recv->newwin) {
|
||||
rmpp_recv->newwin += window_size(agent);
|
||||
spin_unlock_irqrestore(&rmpp_recv->lock, flags);
|
||||
ack_recv(rmpp_recv, mad_recv_wc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&rmpp_recv->lock, flags);
|
||||
out:
|
||||
deref_rmpp_recv(rmpp_recv);
|
||||
return done_wc;
|
||||
|
||||
drop3: spin_unlock_irqrestore(&rmpp_recv->lock, flags);
|
||||
drop2: deref_rmpp_recv(rmpp_recv);
|
||||
drop1: ib_free_recv_mad(mad_recv_wc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ib_mad_recv_wc *
|
||||
start_rmpp(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
{
|
||||
struct mad_rmpp_recv *rmpp_recv;
|
||||
unsigned long flags;
|
||||
|
||||
rmpp_recv = create_rmpp_recv(agent, mad_recv_wc);
|
||||
if (!rmpp_recv) {
|
||||
ib_free_recv_mad(mad_recv_wc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&agent->lock, flags);
|
||||
if (insert_rmpp_recv(agent, rmpp_recv)) {
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
/* duplicate first MAD */
|
||||
destroy_rmpp_recv(rmpp_recv);
|
||||
return continue_rmpp(agent, mad_recv_wc);
|
||||
}
|
||||
atomic_inc(&rmpp_recv->refcount);
|
||||
|
||||
if (get_last_flag(&mad_recv_wc->recv_buf)) {
|
||||
rmpp_recv->state = RMPP_STATE_COMPLETE;
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
complete_rmpp(rmpp_recv);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
/* 40 seconds until we can find the packet lifetimes */
|
||||
queue_delayed_work(agent->qp_info->port_priv->wq,
|
||||
&rmpp_recv->timeout_work,
|
||||
msecs_to_jiffies(40000));
|
||||
rmpp_recv->newwin += window_size(agent);
|
||||
ack_recv(rmpp_recv, mad_recv_wc);
|
||||
mad_recv_wc = NULL;
|
||||
}
|
||||
deref_rmpp_recv(rmpp_recv);
|
||||
return mad_recv_wc;
|
||||
}
|
||||
|
||||
static inline u64 get_seg_addr(struct ib_mad_send_wr_private *mad_send_wr)
|
||||
{
|
||||
return mad_send_wr->sg_list[0].addr + mad_send_wr->data_offset +
|
||||
(sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset) *
|
||||
(mad_send_wr->seg_num - 1);
|
||||
}
|
||||
|
||||
static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr)
|
||||
{
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
int timeout;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
|
||||
ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE);
|
||||
rmpp_mad->rmpp_hdr.seg_num = cpu_to_be32(mad_send_wr->seg_num);
|
||||
|
||||
if (mad_send_wr->seg_num == 1) {
|
||||
rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST;
|
||||
rmpp_mad->rmpp_hdr.paylen_newwin =
|
||||
cpu_to_be32(mad_send_wr->total_seg *
|
||||
(sizeof(struct ib_rmpp_mad) -
|
||||
offsetof(struct ib_rmpp_mad, data)));
|
||||
mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad);
|
||||
} else {
|
||||
mad_send_wr->send_wr.num_sge = 2;
|
||||
mad_send_wr->sg_list[0].length = mad_send_wr->data_offset;
|
||||
mad_send_wr->sg_list[1].addr = get_seg_addr(mad_send_wr);
|
||||
mad_send_wr->sg_list[1].length = sizeof(struct ib_rmpp_mad) -
|
||||
mad_send_wr->data_offset;
|
||||
mad_send_wr->sg_list[1].lkey = mad_send_wr->sg_list[0].lkey;
|
||||
}
|
||||
|
||||
if (mad_send_wr->seg_num == mad_send_wr->total_seg) {
|
||||
rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST;
|
||||
rmpp_mad->rmpp_hdr.paylen_newwin =
|
||||
cpu_to_be32(sizeof(struct ib_rmpp_mad) -
|
||||
offsetof(struct ib_rmpp_mad, data) -
|
||||
mad_send_wr->pad);
|
||||
}
|
||||
|
||||
/* 2 seconds for an ACK until we can find the packet lifetime */
|
||||
timeout = mad_send_wr->send_wr.wr.ud.timeout_ms;
|
||||
if (!timeout || timeout > 2000)
|
||||
mad_send_wr->timeout = msecs_to_jiffies(2000);
|
||||
mad_send_wr->seg_num++;
|
||||
return ib_send_mad(mad_send_wr);
|
||||
}
|
||||
|
||||
static void process_rmpp_ack(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
{
|
||||
struct ib_mad_send_wr_private *mad_send_wr;
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
unsigned long flags;
|
||||
int seg_num, newwin, ret;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_status)
|
||||
return;
|
||||
|
||||
seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num);
|
||||
newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
|
||||
|
||||
spin_lock_irqsave(&agent->lock, flags);
|
||||
mad_send_wr = ib_find_send_mad(agent, rmpp_mad->mad_hdr.tid);
|
||||
if (!mad_send_wr)
|
||||
goto out; /* Unmatched ACK */
|
||||
|
||||
if ((mad_send_wr->last_ack == mad_send_wr->total_seg) ||
|
||||
(!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS))
|
||||
goto out; /* Send is already done */
|
||||
|
||||
if (seg_num > mad_send_wr->total_seg)
|
||||
goto out; /* Bad ACK */
|
||||
|
||||
if (newwin < mad_send_wr->newwin || seg_num < mad_send_wr->last_ack)
|
||||
goto out; /* Old ACK */
|
||||
|
||||
if (seg_num > mad_send_wr->last_ack) {
|
||||
mad_send_wr->last_ack = seg_num;
|
||||
mad_send_wr->retries = mad_send_wr->send_wr.wr.ud.retries;
|
||||
}
|
||||
mad_send_wr->newwin = newwin;
|
||||
if (mad_send_wr->last_ack == mad_send_wr->total_seg) {
|
||||
/* If no response is expected, the ACK completes the send */
|
||||
if (!mad_send_wr->send_wr.wr.ud.timeout_ms) {
|
||||
struct ib_mad_send_wc wc;
|
||||
|
||||
ib_mark_mad_done(mad_send_wr);
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
|
||||
wc.status = IB_WC_SUCCESS;
|
||||
wc.vendor_err = 0;
|
||||
wc.wr_id = mad_send_wr->wr_id;
|
||||
ib_mad_complete_send_wr(mad_send_wr, &wc);
|
||||
return;
|
||||
}
|
||||
if (mad_send_wr->refcount == 1)
|
||||
ib_reset_mad_timeout(mad_send_wr, mad_send_wr->
|
||||
send_wr.wr.ud.timeout_ms);
|
||||
} else if (mad_send_wr->refcount == 1 &&
|
||||
mad_send_wr->seg_num < mad_send_wr->newwin &&
|
||||
mad_send_wr->seg_num <= mad_send_wr->total_seg) {
|
||||
/* Send failure will just result in a timeout/retry */
|
||||
ret = send_next_seg(mad_send_wr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mad_send_wr->refcount++;
|
||||
list_del(&mad_send_wr->agent_list);
|
||||
list_add_tail(&mad_send_wr->agent_list,
|
||||
&mad_send_wr->mad_agent_priv->send_list);
|
||||
}
|
||||
out:
|
||||
spin_unlock_irqrestore(&agent->lock, flags);
|
||||
}
|
||||
|
||||
struct ib_mad_recv_wc *
|
||||
ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc)
|
||||
{
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
|
||||
if (!(rmpp_mad->rmpp_hdr.rmpp_rtime_flags & IB_MGMT_RMPP_FLAG_ACTIVE))
|
||||
return mad_recv_wc;
|
||||
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION)
|
||||
goto out;
|
||||
|
||||
switch (rmpp_mad->rmpp_hdr.rmpp_type) {
|
||||
case IB_MGMT_RMPP_TYPE_DATA:
|
||||
if (rmpp_mad->rmpp_hdr.seg_num == __constant_htonl(1))
|
||||
return start_rmpp(agent, mad_recv_wc);
|
||||
else
|
||||
return continue_rmpp(agent, mad_recv_wc);
|
||||
case IB_MGMT_RMPP_TYPE_ACK:
|
||||
process_rmpp_ack(agent, mad_recv_wc);
|
||||
break;
|
||||
case IB_MGMT_RMPP_TYPE_STOP:
|
||||
case IB_MGMT_RMPP_TYPE_ABORT:
|
||||
/* TODO: process_rmpp_nack(agent, mad_recv_wc); */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
out:
|
||||
ib_free_recv_mad(mad_recv_wc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr)
|
||||
{
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
int i, total_len, ret;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
|
||||
if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
|
||||
IB_MGMT_RMPP_FLAG_ACTIVE))
|
||||
return IB_RMPP_RESULT_UNHANDLED;
|
||||
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA)
|
||||
return IB_RMPP_RESULT_INTERNAL;
|
||||
|
||||
if (mad_send_wr->send_wr.num_sge > 1)
|
||||
return -EINVAL; /* TODO: support num_sge > 1 */
|
||||
|
||||
mad_send_wr->seg_num = 1;
|
||||
mad_send_wr->newwin = 1;
|
||||
mad_send_wr->data_offset = data_offset(rmpp_mad->mad_hdr.mgmt_class);
|
||||
|
||||
total_len = 0;
|
||||
for (i = 0; i < mad_send_wr->send_wr.num_sge; i++)
|
||||
total_len += mad_send_wr->send_wr.sg_list[i].length;
|
||||
|
||||
mad_send_wr->total_seg = (total_len - mad_send_wr->data_offset) /
|
||||
(sizeof(struct ib_rmpp_mad) - mad_send_wr->data_offset);
|
||||
mad_send_wr->pad = total_len - offsetof(struct ib_rmpp_mad, data) -
|
||||
be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin);
|
||||
|
||||
/* We need to wait for the final ACK even if there isn't a response */
|
||||
mad_send_wr->refcount += (mad_send_wr->timeout == 0);
|
||||
ret = send_next_seg(mad_send_wr);
|
||||
if (!ret)
|
||||
return IB_RMPP_RESULT_CONSUMED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
|
||||
struct ib_mad_send_wc *mad_send_wc)
|
||||
{
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
struct ib_mad_send_buf *msg;
|
||||
int ret;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
|
||||
if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
|
||||
IB_MGMT_RMPP_FLAG_ACTIVE))
|
||||
return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */
|
||||
|
||||
if (rmpp_mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA) {
|
||||
msg = (struct ib_mad_send_buf *) (unsigned long)
|
||||
mad_send_wc->wr_id;
|
||||
ib_free_send_mad(msg);
|
||||
return IB_RMPP_RESULT_INTERNAL; /* ACK, STOP, or ABORT */
|
||||
}
|
||||
|
||||
if (mad_send_wc->status != IB_WC_SUCCESS ||
|
||||
mad_send_wr->status != IB_WC_SUCCESS)
|
||||
return IB_RMPP_RESULT_PROCESSED; /* Canceled or send error */
|
||||
|
||||
if (!mad_send_wr->timeout)
|
||||
return IB_RMPP_RESULT_PROCESSED; /* Response received */
|
||||
|
||||
if (mad_send_wr->last_ack == mad_send_wr->total_seg) {
|
||||
mad_send_wr->timeout =
|
||||
msecs_to_jiffies(mad_send_wr->send_wr.wr.ud.timeout_ms);
|
||||
return IB_RMPP_RESULT_PROCESSED; /* Send done */
|
||||
}
|
||||
|
||||
if (mad_send_wr->seg_num > mad_send_wr->newwin ||
|
||||
mad_send_wr->seg_num > mad_send_wr->total_seg)
|
||||
return IB_RMPP_RESULT_PROCESSED; /* Wait for ACK */
|
||||
|
||||
ret = send_next_seg(mad_send_wr);
|
||||
if (ret) {
|
||||
mad_send_wc->status = IB_WC_GENERAL_ERR;
|
||||
return IB_RMPP_RESULT_PROCESSED;
|
||||
}
|
||||
return IB_RMPP_RESULT_CONSUMED;
|
||||
}
|
||||
|
||||
int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr)
|
||||
{
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
int ret;
|
||||
|
||||
rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr;
|
||||
if (!(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
|
||||
IB_MGMT_RMPP_FLAG_ACTIVE))
|
||||
return IB_RMPP_RESULT_UNHANDLED; /* RMPP not active */
|
||||
|
||||
if (mad_send_wr->last_ack == mad_send_wr->total_seg)
|
||||
return IB_RMPP_RESULT_PROCESSED;
|
||||
|
||||
mad_send_wr->seg_num = mad_send_wr->last_ack + 1;
|
||||
ret = send_next_seg(mad_send_wr);
|
||||
if (ret)
|
||||
return IB_RMPP_RESULT_PROCESSED;
|
||||
|
||||
return IB_RMPP_RESULT_CONSUMED;
|
||||
}
|
||||
58
drivers/infiniband/core/mad_rmpp.h
Normal file
58
drivers/infiniband/core/mad_rmpp.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Intel Inc. 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_rmpp.h 1921 2005-02-25 22:58:44Z sean.hefty $
|
||||
*/
|
||||
|
||||
#ifndef __MAD_RMPP_H__
|
||||
#define __MAD_RMPP_H__
|
||||
|
||||
enum {
|
||||
IB_RMPP_RESULT_PROCESSED,
|
||||
IB_RMPP_RESULT_CONSUMED,
|
||||
IB_RMPP_RESULT_INTERNAL,
|
||||
IB_RMPP_RESULT_UNHANDLED
|
||||
};
|
||||
|
||||
int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr);
|
||||
|
||||
struct ib_mad_recv_wc *
|
||||
ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent,
|
||||
struct ib_mad_recv_wc *mad_recv_wc);
|
||||
|
||||
int ib_process_rmpp_send_wc(struct ib_mad_send_wr_private *mad_send_wr,
|
||||
struct ib_mad_send_wc *mad_send_wc);
|
||||
|
||||
void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent);
|
||||
|
||||
int ib_retry_rmpp(struct ib_mad_send_wr_private *mad_send_wr);
|
||||
|
||||
#endif /* __MAD_RMPP_H__ */
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. 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
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
* 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 $
|
||||
* $Id: sa_query.c 2811 2005-07-06 18:11:43Z halr $
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -50,26 +51,6 @@ 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;
|
||||
|
|
@ -77,7 +58,6 @@ struct ib_sa_sm_ah {
|
|||
|
||||
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;
|
||||
|
|
@ -100,6 +80,12 @@ struct ib_sa_query {
|
|||
int id;
|
||||
};
|
||||
|
||||
struct ib_sa_service_query {
|
||||
void (*callback)(int, struct ib_sa_service_rec *, void *);
|
||||
void *context;
|
||||
struct ib_sa_query sa_query;
|
||||
};
|
||||
|
||||
struct ib_sa_path_query {
|
||||
void (*callback)(int, struct ib_sa_path_rec *, void *);
|
||||
void *context;
|
||||
|
|
@ -341,6 +327,54 @@ static const struct ib_field mcmember_rec_table[] = {
|
|||
.size_bits = 23 },
|
||||
};
|
||||
|
||||
#define SERVICE_REC_FIELD(field) \
|
||||
.struct_offset_bytes = offsetof(struct ib_sa_service_rec, field), \
|
||||
.struct_size_bytes = sizeof ((struct ib_sa_service_rec *) 0)->field, \
|
||||
.field_name = "sa_service_rec:" #field
|
||||
|
||||
static const struct ib_field service_rec_table[] = {
|
||||
{ SERVICE_REC_FIELD(id),
|
||||
.offset_words = 0,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 64 },
|
||||
{ SERVICE_REC_FIELD(gid),
|
||||
.offset_words = 2,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 128 },
|
||||
{ SERVICE_REC_FIELD(pkey),
|
||||
.offset_words = 6,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 16 },
|
||||
{ SERVICE_REC_FIELD(lease),
|
||||
.offset_words = 7,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 32 },
|
||||
{ SERVICE_REC_FIELD(key),
|
||||
.offset_words = 8,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 128 },
|
||||
{ SERVICE_REC_FIELD(name),
|
||||
.offset_words = 12,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 64*8 },
|
||||
{ SERVICE_REC_FIELD(data8),
|
||||
.offset_words = 28,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 16*8 },
|
||||
{ SERVICE_REC_FIELD(data16),
|
||||
.offset_words = 32,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 8*16 },
|
||||
{ SERVICE_REC_FIELD(data32),
|
||||
.offset_words = 36,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 4*32 },
|
||||
{ SERVICE_REC_FIELD(data64),
|
||||
.offset_words = 40,
|
||||
.offset_bits = 0,
|
||||
.size_bits = 2*64 },
|
||||
};
|
||||
|
||||
static void free_sm_ah(struct kref *kref)
|
||||
{
|
||||
struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref);
|
||||
|
|
@ -463,7 +497,7 @@ static int send_mad(struct ib_sa_query *query, int timeout_ms)
|
|||
.mad_hdr = &query->mad->mad_hdr,
|
||||
.remote_qpn = 1,
|
||||
.remote_qkey = IB_QP1_QKEY,
|
||||
.timeout_ms = timeout_ms
|
||||
.timeout_ms = timeout_ms,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -492,7 +526,7 @@ retry:
|
|||
sizeof (struct ib_sa_mad),
|
||||
DMA_TO_DEVICE);
|
||||
gather_list.length = sizeof (struct ib_sa_mad);
|
||||
gather_list.lkey = port->mr->lkey;
|
||||
gather_list.lkey = port->agent->mr->lkey;
|
||||
pci_unmap_addr_set(query, mapping, gather_list.addr);
|
||||
|
||||
ret = ib_post_send_mad(port->agent, &wr, &bad_wr);
|
||||
|
|
@ -566,7 +600,7 @@ static void ib_sa_path_rec_release(struct ib_sa_query *sa_query)
|
|||
int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
|
||||
struct ib_sa_path_rec *rec,
|
||||
ib_sa_comp_mask comp_mask,
|
||||
int timeout_ms, int gfp_mask,
|
||||
int timeout_ms, unsigned int __nocast gfp_mask,
|
||||
void (*callback)(int status,
|
||||
struct ib_sa_path_rec *resp,
|
||||
void *context),
|
||||
|
|
@ -616,6 +650,114 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
|
|||
}
|
||||
EXPORT_SYMBOL(ib_sa_path_rec_get);
|
||||
|
||||
static void ib_sa_service_rec_callback(struct ib_sa_query *sa_query,
|
||||
int status,
|
||||
struct ib_sa_mad *mad)
|
||||
{
|
||||
struct ib_sa_service_query *query =
|
||||
container_of(sa_query, struct ib_sa_service_query, sa_query);
|
||||
|
||||
if (mad) {
|
||||
struct ib_sa_service_rec rec;
|
||||
|
||||
ib_unpack(service_rec_table, ARRAY_SIZE(service_rec_table),
|
||||
mad->data, &rec);
|
||||
query->callback(status, &rec, query->context);
|
||||
} else
|
||||
query->callback(status, NULL, query->context);
|
||||
}
|
||||
|
||||
static void ib_sa_service_rec_release(struct ib_sa_query *sa_query)
|
||||
{
|
||||
kfree(sa_query->mad);
|
||||
kfree(container_of(sa_query, struct ib_sa_service_query, sa_query));
|
||||
}
|
||||
|
||||
/**
|
||||
* ib_sa_service_rec_query - Start Service Record operation
|
||||
* @device:device to send request on
|
||||
* @port_num: port number to send request on
|
||||
* @method:SA method - should be get, set, or delete
|
||||
* @rec:Service Record to send in request
|
||||
* @comp_mask:component mask to send in request
|
||||
* @timeout_ms:time to wait for response
|
||||
* @gfp_mask:GFP mask to use for internal allocations
|
||||
* @callback:function called when request completes, times out or is
|
||||
* canceled
|
||||
* @context:opaque user context passed to callback
|
||||
* @sa_query:request context, used to cancel request
|
||||
*
|
||||
* Send a Service Record set/get/delete to the SA to register,
|
||||
* unregister or query a service record.
|
||||
* The callback function will be called when the request completes (or
|
||||
* fails); status is 0 for a successful response, -EINTR if the query
|
||||
* is canceled, -ETIMEDOUT is the query timed out, or -EIO if an error
|
||||
* occurred sending the query. The resp parameter of the callback is
|
||||
* only valid if status is 0.
|
||||
*
|
||||
* If the return value of ib_sa_service_rec_query() is negative, it is an
|
||||
* error code. Otherwise it is a request ID that can be used to cancel
|
||||
* the query.
|
||||
*/
|
||||
int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method,
|
||||
struct ib_sa_service_rec *rec,
|
||||
ib_sa_comp_mask comp_mask,
|
||||
int timeout_ms, unsigned int __nocast gfp_mask,
|
||||
void (*callback)(int status,
|
||||
struct ib_sa_service_rec *resp,
|
||||
void *context),
|
||||
void *context,
|
||||
struct ib_sa_query **sa_query)
|
||||
{
|
||||
struct ib_sa_service_query *query;
|
||||
struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
|
||||
struct ib_sa_port *port = &sa_dev->port[port_num - sa_dev->start_port];
|
||||
struct ib_mad_agent *agent = port->agent;
|
||||
int ret;
|
||||
|
||||
if (method != IB_MGMT_METHOD_GET &&
|
||||
method != IB_MGMT_METHOD_SET &&
|
||||
method != IB_SA_METHOD_DELETE)
|
||||
return -EINVAL;
|
||||
|
||||
query = kmalloc(sizeof *query, gfp_mask);
|
||||
if (!query)
|
||||
return -ENOMEM;
|
||||
query->sa_query.mad = kmalloc(sizeof *query->sa_query.mad, gfp_mask);
|
||||
if (!query->sa_query.mad) {
|
||||
kfree(query);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
query->callback = callback;
|
||||
query->context = context;
|
||||
|
||||
init_mad(query->sa_query.mad, agent);
|
||||
|
||||
query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
|
||||
query->sa_query.release = ib_sa_service_rec_release;
|
||||
query->sa_query.port = port;
|
||||
query->sa_query.mad->mad_hdr.method = method;
|
||||
query->sa_query.mad->mad_hdr.attr_id =
|
||||
cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
|
||||
query->sa_query.mad->sa_hdr.comp_mask = comp_mask;
|
||||
|
||||
ib_pack(service_rec_table, ARRAY_SIZE(service_rec_table),
|
||||
rec, query->sa_query.mad->data);
|
||||
|
||||
*sa_query = &query->sa_query;
|
||||
|
||||
ret = send_mad(&query->sa_query, timeout_ms);
|
||||
if (ret < 0) {
|
||||
*sa_query = NULL;
|
||||
kfree(query->sa_query.mad);
|
||||
kfree(query);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ib_sa_service_rec_query);
|
||||
|
||||
static void ib_sa_mcmember_rec_callback(struct ib_sa_query *sa_query,
|
||||
int status,
|
||||
struct ib_sa_mad *mad)
|
||||
|
|
@ -643,7 +785,7 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
|
|||
u8 method,
|
||||
struct ib_sa_mcmember_rec *rec,
|
||||
ib_sa_comp_mask comp_mask,
|
||||
int timeout_ms, int gfp_mask,
|
||||
int timeout_ms, unsigned int __nocast gfp_mask,
|
||||
void (*callback)(int status,
|
||||
struct ib_sa_mcmember_rec *resp,
|
||||
void *context),
|
||||
|
|
@ -780,7 +922,6 @@ static void ib_sa_add_one(struct ib_device *device)
|
|||
sa_dev->end_port = e;
|
||||
|
||||
for (i = 0; i <= e - s; ++i) {
|
||||
sa_dev->port[i].mr = NULL;
|
||||
sa_dev->port[i].sm_ah = NULL;
|
||||
sa_dev->port[i].port_num = i + s;
|
||||
spin_lock_init(&sa_dev->port[i].ah_lock);
|
||||
|
|
@ -792,13 +933,6 @@ static void ib_sa_add_one(struct ib_device *device)
|
|||
if (IS_ERR(sa_dev->port[i].agent))
|
||||
goto err;
|
||||
|
||||
sa_dev->port[i].mr = ib_get_dma_mr(sa_dev->port[i].agent->qp->pd,
|
||||
IB_ACCESS_LOCAL_WRITE);
|
||||
if (IS_ERR(sa_dev->port[i].mr)) {
|
||||
ib_unregister_mad_agent(sa_dev->port[i].agent);
|
||||
goto err;
|
||||
}
|
||||
|
||||
INIT_WORK(&sa_dev->port[i].update_task,
|
||||
update_sm_ah, &sa_dev->port[i]);
|
||||
}
|
||||
|
|
@ -822,10 +956,8 @@ static void ib_sa_add_one(struct ib_device *device)
|
|||
return;
|
||||
|
||||
err:
|
||||
while (--i >= 0) {
|
||||
ib_dereg_mr(sa_dev->port[i].mr);
|
||||
while (--i >= 0)
|
||||
ib_unregister_mad_agent(sa_dev->port[i].agent);
|
||||
}
|
||||
|
||||
kfree(sa_dev);
|
||||
|
||||
|
|
|
|||
1393
drivers/infiniband/core/ucm.c
Normal file
1393
drivers/infiniband/core/ucm.c
Normal file
File diff suppressed because it is too large
Load diff
89
drivers/infiniband/core/ucm.h
Normal file
89
drivers/infiniband/core/ucm.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2005 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: ucm.h 2208 2005-04-22 23:24:31Z libor $
|
||||
*/
|
||||
|
||||
#ifndef UCM_H
|
||||
#define UCM_H
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/idr.h>
|
||||
|
||||
#include <ib_cm.h>
|
||||
#include <ib_user_cm.h>
|
||||
|
||||
#define IB_UCM_CM_ID_INVALID 0xffffffff
|
||||
|
||||
struct ib_ucm_file {
|
||||
struct semaphore mutex;
|
||||
struct file *filp;
|
||||
/*
|
||||
* list of pending events
|
||||
*/
|
||||
struct list_head ctxs; /* list of active connections */
|
||||
struct list_head events; /* list of pending events */
|
||||
wait_queue_head_t poll_wait;
|
||||
};
|
||||
|
||||
struct ib_ucm_context {
|
||||
int id;
|
||||
int ref;
|
||||
int error;
|
||||
|
||||
struct ib_ucm_file *file;
|
||||
struct ib_cm_id *cm_id;
|
||||
struct semaphore mutex;
|
||||
|
||||
struct list_head events; /* list of pending events. */
|
||||
struct list_head file_list; /* member in file ctx list */
|
||||
};
|
||||
|
||||
struct ib_ucm_event {
|
||||
struct ib_ucm_context *ctx;
|
||||
struct list_head file_list; /* member in file event list */
|
||||
struct list_head ctx_list; /* member in ctx event list */
|
||||
|
||||
struct ib_ucm_event_resp resp;
|
||||
void *data;
|
||||
void *info;
|
||||
int data_len;
|
||||
int info_len;
|
||||
/*
|
||||
* new connection identifiers needs to be saved until
|
||||
* userspace can get a handle on them.
|
||||
*/
|
||||
struct ib_cm_id *cm_id;
|
||||
};
|
||||
|
||||
#endif /* UCM_H */
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. 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
|
||||
|
|
@ -29,7 +31,7 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* $Id: user_mad.c 1389 2004-12-27 22:56:47Z roland $
|
||||
* $Id: user_mad.c 2814 2005-07-06 19:14:09Z halr $
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -94,10 +96,12 @@ struct ib_umad_file {
|
|||
};
|
||||
|
||||
struct ib_umad_packet {
|
||||
struct ib_user_mad mad;
|
||||
struct ib_ah *ah;
|
||||
struct ib_mad_send_buf *msg;
|
||||
struct list_head list;
|
||||
int length;
|
||||
DECLARE_PCI_UNMAP_ADDR(mapping)
|
||||
struct ib_user_mad mad;
|
||||
};
|
||||
|
||||
static const dev_t base_dev = MKDEV(IB_UMAD_MAJOR, IB_UMAD_MINOR_BASE);
|
||||
|
|
@ -114,10 +118,10 @@ static int queue_packet(struct ib_umad_file *file,
|
|||
int ret = 1;
|
||||
|
||||
down_read(&file->agent_mutex);
|
||||
for (packet->mad.id = 0;
|
||||
packet->mad.id < IB_UMAD_MAX_AGENTS;
|
||||
packet->mad.id++)
|
||||
if (agent == file->agent[packet->mad.id]) {
|
||||
for (packet->mad.hdr.id = 0;
|
||||
packet->mad.hdr.id < IB_UMAD_MAX_AGENTS;
|
||||
packet->mad.hdr.id++)
|
||||
if (agent == file->agent[packet->mad.hdr.id]) {
|
||||
spin_lock_irq(&file->recv_lock);
|
||||
list_add_tail(&packet->list, &file->recv_list);
|
||||
spin_unlock_irq(&file->recv_lock);
|
||||
|
|
@ -135,22 +139,30 @@ static void send_handler(struct ib_mad_agent *agent,
|
|||
struct ib_mad_send_wc *send_wc)
|
||||
{
|
||||
struct ib_umad_file *file = agent->context;
|
||||
struct ib_umad_packet *packet =
|
||||
struct ib_umad_packet *timeout, *packet =
|
||||
(void *) (unsigned long) send_wc->wr_id;
|
||||
|
||||
dma_unmap_single(agent->device->dma_device,
|
||||
pci_unmap_addr(packet, mapping),
|
||||
sizeof packet->mad.data,
|
||||
DMA_TO_DEVICE);
|
||||
ib_destroy_ah(packet->ah);
|
||||
ib_destroy_ah(packet->msg->send_wr.wr.ud.ah);
|
||||
ib_free_send_mad(packet->msg);
|
||||
|
||||
if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) {
|
||||
packet->mad.status = ETIMEDOUT;
|
||||
timeout = kmalloc(sizeof *timeout + sizeof (struct ib_mad_hdr),
|
||||
GFP_KERNEL);
|
||||
if (!timeout)
|
||||
goto out;
|
||||
|
||||
if (!queue_packet(file, agent, packet))
|
||||
return;
|
||||
memset(timeout, 0, sizeof *timeout + sizeof (struct ib_mad_hdr));
|
||||
|
||||
timeout->length = sizeof (struct ib_mad_hdr);
|
||||
timeout->mad.hdr.id = packet->mad.hdr.id;
|
||||
timeout->mad.hdr.status = ETIMEDOUT;
|
||||
memcpy(timeout->mad.data, packet->mad.data,
|
||||
sizeof (struct ib_mad_hdr));
|
||||
|
||||
if (!queue_packet(file, agent, timeout))
|
||||
return;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(packet);
|
||||
}
|
||||
|
||||
|
|
@ -159,30 +171,35 @@ static void recv_handler(struct ib_mad_agent *agent,
|
|||
{
|
||||
struct ib_umad_file *file = agent->context;
|
||||
struct ib_umad_packet *packet;
|
||||
int length;
|
||||
|
||||
if (mad_recv_wc->wc->status != IB_WC_SUCCESS)
|
||||
goto out;
|
||||
|
||||
packet = kmalloc(sizeof *packet, GFP_KERNEL);
|
||||
length = mad_recv_wc->mad_len;
|
||||
packet = kmalloc(sizeof *packet + length, GFP_KERNEL);
|
||||
if (!packet)
|
||||
goto out;
|
||||
|
||||
memset(packet, 0, sizeof *packet);
|
||||
memset(packet, 0, sizeof *packet + length);
|
||||
packet->length = length;
|
||||
|
||||
memcpy(packet->mad.data, mad_recv_wc->recv_buf.mad, sizeof packet->mad.data);
|
||||
packet->mad.status = 0;
|
||||
packet->mad.qpn = cpu_to_be32(mad_recv_wc->wc->src_qp);
|
||||
packet->mad.lid = cpu_to_be16(mad_recv_wc->wc->slid);
|
||||
packet->mad.sl = mad_recv_wc->wc->sl;
|
||||
packet->mad.path_bits = mad_recv_wc->wc->dlid_path_bits;
|
||||
packet->mad.grh_present = !!(mad_recv_wc->wc->wc_flags & IB_WC_GRH);
|
||||
if (packet->mad.grh_present) {
|
||||
ib_coalesce_recv_mad(mad_recv_wc, packet->mad.data);
|
||||
|
||||
packet->mad.hdr.status = 0;
|
||||
packet->mad.hdr.length = length + sizeof (struct ib_user_mad);
|
||||
packet->mad.hdr.qpn = cpu_to_be32(mad_recv_wc->wc->src_qp);
|
||||
packet->mad.hdr.lid = cpu_to_be16(mad_recv_wc->wc->slid);
|
||||
packet->mad.hdr.sl = mad_recv_wc->wc->sl;
|
||||
packet->mad.hdr.path_bits = mad_recv_wc->wc->dlid_path_bits;
|
||||
packet->mad.hdr.grh_present = !!(mad_recv_wc->wc->wc_flags & IB_WC_GRH);
|
||||
if (packet->mad.hdr.grh_present) {
|
||||
/* XXX parse GRH */
|
||||
packet->mad.gid_index = 0;
|
||||
packet->mad.hop_limit = 0;
|
||||
packet->mad.traffic_class = 0;
|
||||
memset(packet->mad.gid, 0, 16);
|
||||
packet->mad.flow_label = 0;
|
||||
packet->mad.hdr.gid_index = 0;
|
||||
packet->mad.hdr.hop_limit = 0;
|
||||
packet->mad.hdr.traffic_class = 0;
|
||||
memset(packet->mad.hdr.gid, 0, 16);
|
||||
packet->mad.hdr.flow_label = 0;
|
||||
}
|
||||
|
||||
if (queue_packet(file, agent, packet))
|
||||
|
|
@ -199,7 +216,7 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
|
|||
struct ib_umad_packet *packet;
|
||||
ssize_t ret;
|
||||
|
||||
if (count < sizeof (struct ib_user_mad))
|
||||
if (count < sizeof (struct ib_user_mad) + sizeof (struct ib_mad))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irq(&file->recv_lock);
|
||||
|
|
@ -222,12 +239,25 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
|
|||
|
||||
spin_unlock_irq(&file->recv_lock);
|
||||
|
||||
if (copy_to_user(buf, &packet->mad, sizeof packet->mad))
|
||||
if (count < packet->length + sizeof (struct ib_user_mad)) {
|
||||
/* Return length needed (and first RMPP segment) if too small */
|
||||
if (copy_to_user(buf, &packet->mad,
|
||||
sizeof (struct ib_user_mad) + sizeof (struct ib_mad)))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = -ENOSPC;
|
||||
} else if (copy_to_user(buf, &packet->mad,
|
||||
packet->length + sizeof (struct ib_user_mad)))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = sizeof packet->mad;
|
||||
|
||||
kfree(packet);
|
||||
ret = packet->length + sizeof (struct ib_user_mad);
|
||||
if (ret < 0) {
|
||||
/* Requeue packet */
|
||||
spin_lock_irq(&file->recv_lock);
|
||||
list_add(&packet->list, &file->recv_list);
|
||||
spin_unlock_irq(&file->recv_lock);
|
||||
} else
|
||||
kfree(packet);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -238,69 +268,57 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
|
|||
struct ib_umad_packet *packet;
|
||||
struct ib_mad_agent *agent;
|
||||
struct ib_ah_attr ah_attr;
|
||||
struct ib_sge gather_list;
|
||||
struct ib_send_wr *bad_wr, wr = {
|
||||
.opcode = IB_WR_SEND,
|
||||
.sg_list = &gather_list,
|
||||
.num_sge = 1,
|
||||
.send_flags = IB_SEND_SIGNALED,
|
||||
};
|
||||
struct ib_send_wr *bad_wr;
|
||||
struct ib_rmpp_mad *rmpp_mad;
|
||||
u8 method;
|
||||
u64 *tid;
|
||||
int ret;
|
||||
int ret, length, hdr_len, data_len, rmpp_hdr_size;
|
||||
int rmpp_active = 0;
|
||||
|
||||
if (count < sizeof (struct ib_user_mad))
|
||||
return -EINVAL;
|
||||
|
||||
packet = kmalloc(sizeof *packet, GFP_KERNEL);
|
||||
length = count - sizeof (struct ib_user_mad);
|
||||
packet = kmalloc(sizeof *packet + sizeof(struct ib_mad_hdr) +
|
||||
sizeof(struct ib_rmpp_hdr), GFP_KERNEL);
|
||||
if (!packet)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(&packet->mad, buf, sizeof packet->mad)) {
|
||||
kfree(packet);
|
||||
return -EFAULT;
|
||||
if (copy_from_user(&packet->mad, buf,
|
||||
sizeof (struct ib_user_mad) +
|
||||
sizeof(struct ib_mad_hdr) +
|
||||
sizeof(struct ib_rmpp_hdr))) {
|
||||
ret = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (packet->mad.id < 0 || packet->mad.id >= IB_UMAD_MAX_AGENTS) {
|
||||
if (packet->mad.hdr.id < 0 ||
|
||||
packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
packet->length = length;
|
||||
|
||||
down_read(&file->agent_mutex);
|
||||
|
||||
agent = file->agent[packet->mad.id];
|
||||
agent = file->agent[packet->mad.hdr.id];
|
||||
if (!agent) {
|
||||
ret = -EINVAL;
|
||||
goto err_up;
|
||||
}
|
||||
|
||||
/*
|
||||
* If userspace is generating a request that will generate a
|
||||
* response, we need to make sure the high-order part of the
|
||||
* transaction ID matches the agent being used to send the
|
||||
* MAD.
|
||||
*/
|
||||
method = ((struct ib_mad_hdr *) packet->mad.data)->method;
|
||||
|
||||
if (!(method & IB_MGMT_METHOD_RESP) &&
|
||||
method != IB_MGMT_METHOD_TRAP_REPRESS &&
|
||||
method != IB_MGMT_METHOD_SEND) {
|
||||
tid = &((struct ib_mad_hdr *) packet->mad.data)->tid;
|
||||
*tid = cpu_to_be64(((u64) agent->hi_tid) << 32 |
|
||||
(be64_to_cpup(tid) & 0xffffffff));
|
||||
}
|
||||
|
||||
memset(&ah_attr, 0, sizeof ah_attr);
|
||||
ah_attr.dlid = be16_to_cpu(packet->mad.lid);
|
||||
ah_attr.sl = packet->mad.sl;
|
||||
ah_attr.src_path_bits = packet->mad.path_bits;
|
||||
ah_attr.dlid = be16_to_cpu(packet->mad.hdr.lid);
|
||||
ah_attr.sl = packet->mad.hdr.sl;
|
||||
ah_attr.src_path_bits = packet->mad.hdr.path_bits;
|
||||
ah_attr.port_num = file->port->port_num;
|
||||
if (packet->mad.grh_present) {
|
||||
if (packet->mad.hdr.grh_present) {
|
||||
ah_attr.ah_flags = IB_AH_GRH;
|
||||
memcpy(ah_attr.grh.dgid.raw, packet->mad.gid, 16);
|
||||
ah_attr.grh.flow_label = packet->mad.flow_label;
|
||||
ah_attr.grh.hop_limit = packet->mad.hop_limit;
|
||||
ah_attr.grh.traffic_class = packet->mad.traffic_class;
|
||||
memcpy(ah_attr.grh.dgid.raw, packet->mad.hdr.gid, 16);
|
||||
ah_attr.grh.flow_label = packet->mad.hdr.flow_label;
|
||||
ah_attr.grh.hop_limit = packet->mad.hdr.hop_limit;
|
||||
ah_attr.grh.traffic_class = packet->mad.hdr.traffic_class;
|
||||
}
|
||||
|
||||
packet->ah = ib_create_ah(agent->qp->pd, &ah_attr);
|
||||
|
|
@ -309,34 +327,104 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
|
|||
goto err_up;
|
||||
}
|
||||
|
||||
gather_list.addr = dma_map_single(agent->device->dma_device,
|
||||
packet->mad.data,
|
||||
sizeof packet->mad.data,
|
||||
DMA_TO_DEVICE);
|
||||
gather_list.length = sizeof packet->mad.data;
|
||||
gather_list.lkey = file->mr[packet->mad.id]->lkey;
|
||||
pci_unmap_addr_set(packet, mapping, gather_list.addr);
|
||||
|
||||
wr.wr.ud.mad_hdr = (struct ib_mad_hdr *) packet->mad.data;
|
||||
wr.wr.ud.ah = packet->ah;
|
||||
wr.wr.ud.remote_qpn = be32_to_cpu(packet->mad.qpn);
|
||||
wr.wr.ud.remote_qkey = be32_to_cpu(packet->mad.qkey);
|
||||
wr.wr.ud.timeout_ms = packet->mad.timeout_ms;
|
||||
|
||||
wr.wr_id = (unsigned long) packet;
|
||||
|
||||
ret = ib_post_send_mad(agent, &wr, &bad_wr);
|
||||
if (ret) {
|
||||
dma_unmap_single(agent->device->dma_device,
|
||||
pci_unmap_addr(packet, mapping),
|
||||
sizeof packet->mad.data,
|
||||
DMA_TO_DEVICE);
|
||||
goto err_up;
|
||||
rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data;
|
||||
if (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE) {
|
||||
/* RMPP active */
|
||||
if (!agent->rmpp_version) {
|
||||
ret = -EINVAL;
|
||||
goto err_ah;
|
||||
}
|
||||
/* Validate that management class can support RMPP */
|
||||
if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
|
||||
hdr_len = offsetof(struct ib_sa_mad, data);
|
||||
data_len = length;
|
||||
} else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
|
||||
(rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) {
|
||||
hdr_len = offsetof(struct ib_vendor_mad, data);
|
||||
data_len = length - hdr_len;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
goto err_ah;
|
||||
}
|
||||
rmpp_active = 1;
|
||||
} else {
|
||||
if (length > sizeof(struct ib_mad)) {
|
||||
ret = -EINVAL;
|
||||
goto err_ah;
|
||||
}
|
||||
hdr_len = offsetof(struct ib_mad, data);
|
||||
data_len = length - hdr_len;
|
||||
}
|
||||
|
||||
packet->msg = ib_create_send_mad(agent,
|
||||
be32_to_cpu(packet->mad.hdr.qpn),
|
||||
0, packet->ah, rmpp_active,
|
||||
hdr_len, data_len,
|
||||
GFP_KERNEL);
|
||||
if (IS_ERR(packet->msg)) {
|
||||
ret = PTR_ERR(packet->msg);
|
||||
goto err_ah;
|
||||
}
|
||||
|
||||
packet->msg->send_wr.wr.ud.timeout_ms = packet->mad.hdr.timeout_ms;
|
||||
packet->msg->send_wr.wr.ud.retries = packet->mad.hdr.retries;
|
||||
|
||||
/* Override send WR WRID initialized in ib_create_send_mad */
|
||||
packet->msg->send_wr.wr_id = (unsigned long) packet;
|
||||
|
||||
if (!rmpp_active) {
|
||||
/* Copy message from user into send buffer */
|
||||
if (copy_from_user(packet->msg->mad,
|
||||
buf + sizeof(struct ib_user_mad), length)) {
|
||||
ret = -EFAULT;
|
||||
goto err_msg;
|
||||
}
|
||||
} else {
|
||||
rmpp_hdr_size = sizeof(struct ib_mad_hdr) +
|
||||
sizeof(struct ib_rmpp_hdr);
|
||||
|
||||
/* Only copy MAD headers (RMPP header in place) */
|
||||
memcpy(packet->msg->mad, packet->mad.data,
|
||||
sizeof(struct ib_mad_hdr));
|
||||
|
||||
/* Now, copy rest of message from user into send buffer */
|
||||
if (copy_from_user(((struct ib_rmpp_mad *) packet->msg->mad)->data,
|
||||
buf + sizeof (struct ib_user_mad) + rmpp_hdr_size,
|
||||
length - rmpp_hdr_size)) {
|
||||
ret = -EFAULT;
|
||||
goto err_msg;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If userspace is generating a request that will generate a
|
||||
* response, we need to make sure the high-order part of the
|
||||
* transaction ID matches the agent being used to send the
|
||||
* MAD.
|
||||
*/
|
||||
method = packet->msg->mad->mad_hdr.method;
|
||||
|
||||
if (!(method & IB_MGMT_METHOD_RESP) &&
|
||||
method != IB_MGMT_METHOD_TRAP_REPRESS &&
|
||||
method != IB_MGMT_METHOD_SEND) {
|
||||
tid = &packet->msg->mad->mad_hdr.tid;
|
||||
*tid = cpu_to_be64(((u64) agent->hi_tid) << 32 |
|
||||
(be64_to_cpup(tid) & 0xffffffff));
|
||||
}
|
||||
|
||||
ret = ib_post_send_mad(agent, &packet->msg->send_wr, &bad_wr);
|
||||
if (ret)
|
||||
goto err_msg;
|
||||
|
||||
up_read(&file->agent_mutex);
|
||||
|
||||
return sizeof packet->mad;
|
||||
return sizeof (struct ib_user_mad_hdr) + packet->length;
|
||||
|
||||
err_msg:
|
||||
ib_free_send_mad(packet->msg);
|
||||
|
||||
err_ah:
|
||||
ib_destroy_ah(packet->ah);
|
||||
|
||||
err_up:
|
||||
up_read(&file->agent_mutex);
|
||||
|
|
@ -399,7 +487,8 @@ found:
|
|||
agent = ib_register_mad_agent(file->port->ib_dev, file->port->port_num,
|
||||
ureq.qpn ? IB_QPT_GSI : IB_QPT_SMI,
|
||||
ureq.mgmt_class ? &req : NULL,
|
||||
0, send_handler, recv_handler, file);
|
||||
ureq.rmpp_version,
|
||||
send_handler, recv_handler, file);
|
||||
if (IS_ERR(agent)) {
|
||||
ret = PTR_ERR(agent);
|
||||
goto out;
|
||||
|
|
@ -460,8 +549,8 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static long ib_umad_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
static long ib_umad_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
case IB_USER_MAD_REGISTER_AGENT:
|
||||
|
|
@ -517,14 +606,14 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
|
|||
}
|
||||
|
||||
static struct file_operations umad_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = ib_umad_read,
|
||||
.write = ib_umad_write,
|
||||
.poll = ib_umad_poll,
|
||||
.owner = THIS_MODULE,
|
||||
.read = ib_umad_read,
|
||||
.write = ib_umad_write,
|
||||
.poll = ib_umad_poll,
|
||||
.unlocked_ioctl = ib_umad_ioctl,
|
||||
.compat_ioctl = ib_umad_ioctl,
|
||||
.open = ib_umad_open,
|
||||
.release = ib_umad_close
|
||||
.compat_ioctl = ib_umad_ioctl,
|
||||
.open = ib_umad_open,
|
||||
.release = ib_umad_close
|
||||
};
|
||||
|
||||
static int ib_umad_sm_open(struct inode *inode, struct file *filp)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include <linux/err.h>
|
||||
|
||||
#include <ib_verbs.h>
|
||||
#include <ib_cache.h>
|
||||
|
||||
/* Protection domains */
|
||||
|
||||
|
|
@ -88,6 +89,40 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
|
|||
}
|
||||
EXPORT_SYMBOL(ib_create_ah);
|
||||
|
||||
struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc,
|
||||
struct ib_grh *grh, u8 port_num)
|
||||
{
|
||||
struct ib_ah_attr ah_attr;
|
||||
u32 flow_class;
|
||||
u16 gid_index;
|
||||
int ret;
|
||||
|
||||
memset(&ah_attr, 0, sizeof ah_attr);
|
||||
ah_attr.dlid = wc->slid;
|
||||
ah_attr.sl = wc->sl;
|
||||
ah_attr.src_path_bits = wc->dlid_path_bits;
|
||||
ah_attr.port_num = port_num;
|
||||
|
||||
if (wc->wc_flags & IB_WC_GRH) {
|
||||
ah_attr.ah_flags = IB_AH_GRH;
|
||||
ah_attr.grh.dgid = grh->dgid;
|
||||
|
||||
ret = ib_find_cached_gid(pd->device, &grh->sgid, &port_num,
|
||||
&gid_index);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
ah_attr.grh.sgid_index = (u8) gid_index;
|
||||
flow_class = be32_to_cpu(grh->version_tclass_flow);
|
||||
ah_attr.grh.flow_label = flow_class & 0xFFFFF;
|
||||
ah_attr.grh.traffic_class = (flow_class >> 20) & 0xFF;
|
||||
ah_attr.grh.hop_limit = grh->hop_limit;
|
||||
}
|
||||
|
||||
return ib_create_ah(pd, &ah_attr);
|
||||
}
|
||||
EXPORT_SYMBOL(ib_create_ah_from_wc);
|
||||
|
||||
int ib_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
|
||||
{
|
||||
return ah->device->modify_ah ?
|
||||
|
|
|
|||
568
drivers/infiniband/include/ib_cm.h
Normal file
568
drivers/infiniband/include/ib_cm.h
Normal file
|
|
@ -0,0 +1,568 @@
|
|||
/*
|
||||
* Copyright (c) 2004 Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2004 Voltaire Corporation. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. 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: ib_cm.h 2730 2005-06-28 16:43:03Z sean.hefty $
|
||||
*/
|
||||
#if !defined(IB_CM_H)
|
||||
#define IB_CM_H
|
||||
|
||||
#include <ib_mad.h>
|
||||
#include <ib_sa.h>
|
||||
|
||||
enum ib_cm_state {
|
||||
IB_CM_IDLE,
|
||||
IB_CM_LISTEN,
|
||||
IB_CM_REQ_SENT,
|
||||
IB_CM_REQ_RCVD,
|
||||
IB_CM_MRA_REQ_SENT,
|
||||
IB_CM_MRA_REQ_RCVD,
|
||||
IB_CM_REP_SENT,
|
||||
IB_CM_REP_RCVD,
|
||||
IB_CM_MRA_REP_SENT,
|
||||
IB_CM_MRA_REP_RCVD,
|
||||
IB_CM_ESTABLISHED,
|
||||
IB_CM_DREQ_SENT,
|
||||
IB_CM_DREQ_RCVD,
|
||||
IB_CM_TIMEWAIT,
|
||||
IB_CM_SIDR_REQ_SENT,
|
||||
IB_CM_SIDR_REQ_RCVD
|
||||
};
|
||||
|
||||
enum ib_cm_lap_state {
|
||||
IB_CM_LAP_IDLE,
|
||||
IB_CM_LAP_SENT,
|
||||
IB_CM_LAP_RCVD,
|
||||
IB_CM_MRA_LAP_SENT,
|
||||
IB_CM_MRA_LAP_RCVD,
|
||||
};
|
||||
|
||||
enum ib_cm_event_type {
|
||||
IB_CM_REQ_ERROR,
|
||||
IB_CM_REQ_RECEIVED,
|
||||
IB_CM_REP_ERROR,
|
||||
IB_CM_REP_RECEIVED,
|
||||
IB_CM_RTU_RECEIVED,
|
||||
IB_CM_USER_ESTABLISHED,
|
||||
IB_CM_DREQ_ERROR,
|
||||
IB_CM_DREQ_RECEIVED,
|
||||
IB_CM_DREP_RECEIVED,
|
||||
IB_CM_TIMEWAIT_EXIT,
|
||||
IB_CM_MRA_RECEIVED,
|
||||
IB_CM_REJ_RECEIVED,
|
||||
IB_CM_LAP_ERROR,
|
||||
IB_CM_LAP_RECEIVED,
|
||||
IB_CM_APR_RECEIVED,
|
||||
IB_CM_SIDR_REQ_ERROR,
|
||||
IB_CM_SIDR_REQ_RECEIVED,
|
||||
IB_CM_SIDR_REP_RECEIVED
|
||||
};
|
||||
|
||||
enum ib_cm_data_size {
|
||||
IB_CM_REQ_PRIVATE_DATA_SIZE = 92,
|
||||
IB_CM_MRA_PRIVATE_DATA_SIZE = 222,
|
||||
IB_CM_REJ_PRIVATE_DATA_SIZE = 148,
|
||||
IB_CM_REP_PRIVATE_DATA_SIZE = 196,
|
||||
IB_CM_RTU_PRIVATE_DATA_SIZE = 224,
|
||||
IB_CM_DREQ_PRIVATE_DATA_SIZE = 220,
|
||||
IB_CM_DREP_PRIVATE_DATA_SIZE = 224,
|
||||
IB_CM_REJ_ARI_LENGTH = 72,
|
||||
IB_CM_LAP_PRIVATE_DATA_SIZE = 168,
|
||||
IB_CM_APR_PRIVATE_DATA_SIZE = 148,
|
||||
IB_CM_APR_INFO_LENGTH = 72,
|
||||
IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE = 216,
|
||||
IB_CM_SIDR_REP_PRIVATE_DATA_SIZE = 136,
|
||||
IB_CM_SIDR_REP_INFO_LENGTH = 72
|
||||
};
|
||||
|
||||
struct ib_cm_id;
|
||||
|
||||
struct ib_cm_req_event_param {
|
||||
struct ib_cm_id *listen_id;
|
||||
struct ib_device *device;
|
||||
u8 port;
|
||||
|
||||
struct ib_sa_path_rec *primary_path;
|
||||
struct ib_sa_path_rec *alternate_path;
|
||||
|
||||
u64 remote_ca_guid;
|
||||
u32 remote_qkey;
|
||||
u32 remote_qpn;
|
||||
enum ib_qp_type qp_type;
|
||||
|
||||
u32 starting_psn;
|
||||
u8 responder_resources;
|
||||
u8 initiator_depth;
|
||||
unsigned int local_cm_response_timeout:5;
|
||||
unsigned int flow_control:1;
|
||||
unsigned int remote_cm_response_timeout:5;
|
||||
unsigned int retry_count:3;
|
||||
unsigned int rnr_retry_count:3;
|
||||
unsigned int srq:1;
|
||||
};
|
||||
|
||||
struct ib_cm_rep_event_param {
|
||||
u64 remote_ca_guid;
|
||||
u32 remote_qkey;
|
||||
u32 remote_qpn;
|
||||
u32 starting_psn;
|
||||
u8 responder_resources;
|
||||
u8 initiator_depth;
|
||||
unsigned int target_ack_delay:5;
|
||||
unsigned int failover_accepted:2;
|
||||
unsigned int flow_control:1;
|
||||
unsigned int rnr_retry_count:3;
|
||||
unsigned int srq:1;
|
||||
};
|
||||
|
||||
enum ib_cm_rej_reason {
|
||||
IB_CM_REJ_NO_QP = __constant_htons(1),
|
||||
IB_CM_REJ_NO_EEC = __constant_htons(2),
|
||||
IB_CM_REJ_NO_RESOURCES = __constant_htons(3),
|
||||
IB_CM_REJ_TIMEOUT = __constant_htons(4),
|
||||
IB_CM_REJ_UNSUPPORTED = __constant_htons(5),
|
||||
IB_CM_REJ_INVALID_COMM_ID = __constant_htons(6),
|
||||
IB_CM_REJ_INVALID_COMM_INSTANCE = __constant_htons(7),
|
||||
IB_CM_REJ_INVALID_SERVICE_ID = __constant_htons(8),
|
||||
IB_CM_REJ_INVALID_TRANSPORT_TYPE = __constant_htons(9),
|
||||
IB_CM_REJ_STALE_CONN = __constant_htons(10),
|
||||
IB_CM_REJ_RDC_NOT_EXIST = __constant_htons(11),
|
||||
IB_CM_REJ_INVALID_GID = __constant_htons(12),
|
||||
IB_CM_REJ_INVALID_LID = __constant_htons(13),
|
||||
IB_CM_REJ_INVALID_SL = __constant_htons(14),
|
||||
IB_CM_REJ_INVALID_TRAFFIC_CLASS = __constant_htons(15),
|
||||
IB_CM_REJ_INVALID_HOP_LIMIT = __constant_htons(16),
|
||||
IB_CM_REJ_INVALID_PACKET_RATE = __constant_htons(17),
|
||||
IB_CM_REJ_INVALID_ALT_GID = __constant_htons(18),
|
||||
IB_CM_REJ_INVALID_ALT_LID = __constant_htons(19),
|
||||
IB_CM_REJ_INVALID_ALT_SL = __constant_htons(20),
|
||||
IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS = __constant_htons(21),
|
||||
IB_CM_REJ_INVALID_ALT_HOP_LIMIT = __constant_htons(22),
|
||||
IB_CM_REJ_INVALID_ALT_PACKET_RATE = __constant_htons(23),
|
||||
IB_CM_REJ_PORT_REDIRECT = __constant_htons(24),
|
||||
IB_CM_REJ_INVALID_MTU = __constant_htons(26),
|
||||
IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES = __constant_htons(27),
|
||||
IB_CM_REJ_CONSUMER_DEFINED = __constant_htons(28),
|
||||
IB_CM_REJ_INVALID_RNR_RETRY = __constant_htons(29),
|
||||
IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID = __constant_htons(30),
|
||||
IB_CM_REJ_INVALID_CLASS_VERSION = __constant_htons(31),
|
||||
IB_CM_REJ_INVALID_FLOW_LABEL = __constant_htons(32),
|
||||
IB_CM_REJ_INVALID_ALT_FLOW_LABEL = __constant_htons(33)
|
||||
};
|
||||
|
||||
struct ib_cm_rej_event_param {
|
||||
enum ib_cm_rej_reason reason;
|
||||
void *ari;
|
||||
u8 ari_length;
|
||||
};
|
||||
|
||||
struct ib_cm_mra_event_param {
|
||||
u8 service_timeout;
|
||||
};
|
||||
|
||||
struct ib_cm_lap_event_param {
|
||||
struct ib_sa_path_rec *alternate_path;
|
||||
};
|
||||
|
||||
enum ib_cm_apr_status {
|
||||
IB_CM_APR_SUCCESS,
|
||||
IB_CM_APR_INVALID_COMM_ID,
|
||||
IB_CM_APR_UNSUPPORTED,
|
||||
IB_CM_APR_REJECT,
|
||||
IB_CM_APR_REDIRECT,
|
||||
IB_CM_APR_IS_CURRENT,
|
||||
IB_CM_APR_INVALID_QPN_EECN,
|
||||
IB_CM_APR_INVALID_LID,
|
||||
IB_CM_APR_INVALID_GID,
|
||||
IB_CM_APR_INVALID_FLOW_LABEL,
|
||||
IB_CM_APR_INVALID_TCLASS,
|
||||
IB_CM_APR_INVALID_HOP_LIMIT,
|
||||
IB_CM_APR_INVALID_PACKET_RATE,
|
||||
IB_CM_APR_INVALID_SL
|
||||
};
|
||||
|
||||
struct ib_cm_apr_event_param {
|
||||
enum ib_cm_apr_status ap_status;
|
||||
void *apr_info;
|
||||
u8 info_len;
|
||||
};
|
||||
|
||||
struct ib_cm_sidr_req_event_param {
|
||||
struct ib_cm_id *listen_id;
|
||||
struct ib_device *device;
|
||||
u8 port;
|
||||
|
||||
u16 pkey;
|
||||
};
|
||||
|
||||
enum ib_cm_sidr_status {
|
||||
IB_SIDR_SUCCESS,
|
||||
IB_SIDR_UNSUPPORTED,
|
||||
IB_SIDR_REJECT,
|
||||
IB_SIDR_NO_QP,
|
||||
IB_SIDR_REDIRECT,
|
||||
IB_SIDR_UNSUPPORTED_VERSION
|
||||
};
|
||||
|
||||
struct ib_cm_sidr_rep_event_param {
|
||||
enum ib_cm_sidr_status status;
|
||||
u32 qkey;
|
||||
u32 qpn;
|
||||
void *info;
|
||||
u8 info_len;
|
||||
|
||||
};
|
||||
|
||||
struct ib_cm_event {
|
||||
enum ib_cm_event_type event;
|
||||
union {
|
||||
struct ib_cm_req_event_param req_rcvd;
|
||||
struct ib_cm_rep_event_param rep_rcvd;
|
||||
/* No data for RTU received events. */
|
||||
struct ib_cm_rej_event_param rej_rcvd;
|
||||
struct ib_cm_mra_event_param mra_rcvd;
|
||||
struct ib_cm_lap_event_param lap_rcvd;
|
||||
struct ib_cm_apr_event_param apr_rcvd;
|
||||
/* No data for DREQ/DREP received events. */
|
||||
struct ib_cm_sidr_req_event_param sidr_req_rcvd;
|
||||
struct ib_cm_sidr_rep_event_param sidr_rep_rcvd;
|
||||
enum ib_wc_status send_status;
|
||||
} param;
|
||||
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* ib_cm_handler - User-defined callback to process communication events.
|
||||
* @cm_id: Communication identifier associated with the reported event.
|
||||
* @event: Information about the communication event.
|
||||
*
|
||||
* IB_CM_REQ_RECEIVED and IB_CM_SIDR_REQ_RECEIVED communication events
|
||||
* generated as a result of listen requests result in the allocation of a
|
||||
* new @cm_id. The new @cm_id is returned to the user through this callback.
|
||||
* Clients are responsible for destroying the new @cm_id. For peer-to-peer
|
||||
* IB_CM_REQ_RECEIVED and all other events, the returned @cm_id corresponds
|
||||
* to a user's existing communication identifier.
|
||||
*
|
||||
* Users may not call ib_destroy_cm_id while in the context of this callback;
|
||||
* however, returning a non-zero value instructs the communication manager to
|
||||
* destroy the @cm_id after the callback completes.
|
||||
*/
|
||||
typedef int (*ib_cm_handler)(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_event *event);
|
||||
|
||||
struct ib_cm_id {
|
||||
ib_cm_handler cm_handler;
|
||||
void *context;
|
||||
u64 service_id;
|
||||
u64 service_mask;
|
||||
enum ib_cm_state state; /* internal CM/debug use */
|
||||
enum ib_cm_lap_state lap_state; /* internal CM/debug use */
|
||||
u32 local_id;
|
||||
u32 remote_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* ib_create_cm_id - Allocate a communication identifier.
|
||||
* @cm_handler: Callback invoked to notify the user of CM events.
|
||||
* @context: User specified context associated with the communication
|
||||
* identifier.
|
||||
*
|
||||
* Communication identifiers are used to track connection states, service
|
||||
* ID resolution requests, and listen requests.
|
||||
*/
|
||||
struct ib_cm_id *ib_create_cm_id(ib_cm_handler cm_handler,
|
||||
void *context);
|
||||
|
||||
/**
|
||||
* ib_destroy_cm_id - Destroy a connection identifier.
|
||||
* @cm_id: Connection identifier to destroy.
|
||||
*
|
||||
* This call blocks until the connection identifier is destroyed.
|
||||
*/
|
||||
void ib_destroy_cm_id(struct ib_cm_id *cm_id);
|
||||
|
||||
#define IB_SERVICE_ID_AGN_MASK __constant_cpu_to_be64(0xFF00000000000000ULL)
|
||||
#define IB_CM_ASSIGN_SERVICE_ID __constant_cpu_to_be64(0x0200000000000000ULL)
|
||||
|
||||
/**
|
||||
* ib_cm_listen - Initiates listening on the specified service ID for
|
||||
* connection and service ID resolution requests.
|
||||
* @cm_id: Connection identifier associated with the listen request.
|
||||
* @service_id: Service identifier matched against incoming connection
|
||||
* and service ID resolution requests. The service ID should be specified
|
||||
* network-byte order. If set to IB_CM_ASSIGN_SERVICE_ID, the CM will
|
||||
* assign a service ID to the caller.
|
||||
* @service_mask: Mask applied to service ID used to listen across a
|
||||
* range of service IDs. If set to 0, the service ID is matched
|
||||
* exactly. This parameter is ignored if %service_id is set to
|
||||
* IB_CM_ASSIGN_SERVICE_ID.
|
||||
*/
|
||||
int ib_cm_listen(struct ib_cm_id *cm_id,
|
||||
u64 service_id,
|
||||
u64 service_mask);
|
||||
|
||||
struct ib_cm_req_param {
|
||||
struct ib_sa_path_rec *primary_path;
|
||||
struct ib_sa_path_rec *alternate_path;
|
||||
u64 service_id;
|
||||
u32 qp_num;
|
||||
enum ib_qp_type qp_type;
|
||||
u32 starting_psn;
|
||||
const void *private_data;
|
||||
u8 private_data_len;
|
||||
u8 peer_to_peer;
|
||||
u8 responder_resources;
|
||||
u8 initiator_depth;
|
||||
u8 remote_cm_response_timeout;
|
||||
u8 flow_control;
|
||||
u8 local_cm_response_timeout;
|
||||
u8 retry_count;
|
||||
u8 rnr_retry_count;
|
||||
u8 max_cm_retries;
|
||||
u8 srq;
|
||||
};
|
||||
|
||||
/**
|
||||
* ib_send_cm_req - Sends a connection request to the remote node.
|
||||
* @cm_id: Connection identifier that will be associated with the
|
||||
* connection request.
|
||||
* @param: Connection request information needed to establish the
|
||||
* connection.
|
||||
*/
|
||||
int ib_send_cm_req(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_req_param *param);
|
||||
|
||||
struct ib_cm_rep_param {
|
||||
u32 qp_num;
|
||||
u32 starting_psn;
|
||||
const void *private_data;
|
||||
u8 private_data_len;
|
||||
u8 responder_resources;
|
||||
u8 initiator_depth;
|
||||
u8 target_ack_delay;
|
||||
u8 failover_accepted;
|
||||
u8 flow_control;
|
||||
u8 rnr_retry_count;
|
||||
u8 srq;
|
||||
};
|
||||
|
||||
/**
|
||||
* ib_send_cm_rep - Sends a connection reply in response to a connection
|
||||
* request.
|
||||
* @cm_id: Connection identifier that will be associated with the
|
||||
* connection request.
|
||||
* @param: Connection reply information needed to establish the
|
||||
* connection.
|
||||
*/
|
||||
int ib_send_cm_rep(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_rep_param *param);
|
||||
|
||||
/**
|
||||
* ib_send_cm_rtu - Sends a connection ready to use message in response
|
||||
* to a connection reply message.
|
||||
* @cm_id: Connection identifier associated with the connection request.
|
||||
* @private_data: Optional user-defined private data sent with the
|
||||
* ready to use message.
|
||||
* @private_data_len: Size of the private data buffer, in bytes.
|
||||
*/
|
||||
int ib_send_cm_rtu(struct ib_cm_id *cm_id,
|
||||
const void *private_data,
|
||||
u8 private_data_len);
|
||||
|
||||
/**
|
||||
* ib_send_cm_dreq - Sends a disconnection request for an existing
|
||||
* connection.
|
||||
* @cm_id: Connection identifier associated with the connection being
|
||||
* released.
|
||||
* @private_data: Optional user-defined private data sent with the
|
||||
* disconnection request message.
|
||||
* @private_data_len: Size of the private data buffer, in bytes.
|
||||
*/
|
||||
int ib_send_cm_dreq(struct ib_cm_id *cm_id,
|
||||
const void *private_data,
|
||||
u8 private_data_len);
|
||||
|
||||
/**
|
||||
* ib_send_cm_drep - Sends a disconnection reply to a disconnection request.
|
||||
* @cm_id: Connection identifier associated with the connection being
|
||||
* released.
|
||||
* @private_data: Optional user-defined private data sent with the
|
||||
* disconnection reply message.
|
||||
* @private_data_len: Size of the private data buffer, in bytes.
|
||||
*
|
||||
* If the cm_id is in the correct state, the CM will transition the connection
|
||||
* to the timewait state, even if an error occurs sending the DREP message.
|
||||
*/
|
||||
int ib_send_cm_drep(struct ib_cm_id *cm_id,
|
||||
const void *private_data,
|
||||
u8 private_data_len);
|
||||
|
||||
/**
|
||||
* ib_cm_establish - Forces a connection state to established.
|
||||
* @cm_id: Connection identifier to transition to established.
|
||||
*
|
||||
* This routine should be invoked by users who receive messages on a
|
||||
* connected QP before an RTU has been received.
|
||||
*/
|
||||
int ib_cm_establish(struct ib_cm_id *cm_id);
|
||||
|
||||
/**
|
||||
* ib_send_cm_rej - Sends a connection rejection message to the
|
||||
* remote node.
|
||||
* @cm_id: Connection identifier associated with the connection being
|
||||
* rejected.
|
||||
* @reason: Reason for the connection request rejection.
|
||||
* @ari: Optional additional rejection information.
|
||||
* @ari_length: Size of the additional rejection information, in bytes.
|
||||
* @private_data: Optional user-defined private data sent with the
|
||||
* rejection message.
|
||||
* @private_data_len: Size of the private data buffer, in bytes.
|
||||
*/
|
||||
int ib_send_cm_rej(struct ib_cm_id *cm_id,
|
||||
enum ib_cm_rej_reason reason,
|
||||
void *ari,
|
||||
u8 ari_length,
|
||||
const void *private_data,
|
||||
u8 private_data_len);
|
||||
|
||||
/**
|
||||
* ib_send_cm_mra - Sends a message receipt acknowledgement to a connection
|
||||
* message.
|
||||
* @cm_id: Connection identifier associated with the connection message.
|
||||
* @service_timeout: The maximum time required for the sender to reply to
|
||||
* to the connection message.
|
||||
* @private_data: Optional user-defined private data sent with the
|
||||
* message receipt acknowledgement.
|
||||
* @private_data_len: Size of the private data buffer, in bytes.
|
||||
*/
|
||||
int ib_send_cm_mra(struct ib_cm_id *cm_id,
|
||||
u8 service_timeout,
|
||||
const void *private_data,
|
||||
u8 private_data_len);
|
||||
|
||||
/**
|
||||
* ib_send_cm_lap - Sends a load alternate path request.
|
||||
* @cm_id: Connection identifier associated with the load alternate path
|
||||
* message.
|
||||
* @alternate_path: A path record that identifies the alternate path to
|
||||
* load.
|
||||
* @private_data: Optional user-defined private data sent with the
|
||||
* load alternate path message.
|
||||
* @private_data_len: Size of the private data buffer, in bytes.
|
||||
*/
|
||||
int ib_send_cm_lap(struct ib_cm_id *cm_id,
|
||||
struct ib_sa_path_rec *alternate_path,
|
||||
const void *private_data,
|
||||
u8 private_data_len);
|
||||
|
||||
/**
|
||||
* ib_cm_init_qp_attr - Initializes the QP attributes for use in transitioning
|
||||
* to a specified QP state.
|
||||
* @cm_id: Communication identifier associated with the QP attributes to
|
||||
* initialize.
|
||||
* @qp_attr: On input, specifies the desired QP state. On output, the
|
||||
* mandatory and desired optional attributes will be set in order to
|
||||
* modify the QP to the specified state.
|
||||
* @qp_attr_mask: The QP attribute mask that may be used to transition the
|
||||
* QP to the specified state.
|
||||
*
|
||||
* Users must set the @qp_attr->qp_state to the desired QP state. This call
|
||||
* will set all required attributes for the given transition, along with
|
||||
* known optional attributes. Users may override the attributes returned from
|
||||
* this call before calling ib_modify_qp.
|
||||
*/
|
||||
int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
|
||||
struct ib_qp_attr *qp_attr,
|
||||
int *qp_attr_mask);
|
||||
|
||||
/**
|
||||
* ib_send_cm_apr - Sends an alternate path response message in response to
|
||||
* a load alternate path request.
|
||||
* @cm_id: Connection identifier associated with the alternate path response.
|
||||
* @status: Reply status sent with the alternate path response.
|
||||
* @info: Optional additional information sent with the alternate path
|
||||
* response.
|
||||
* @info_length: Size of the additional information, in bytes.
|
||||
* @private_data: Optional user-defined private data sent with the
|
||||
* alternate path response message.
|
||||
* @private_data_len: Size of the private data buffer, in bytes.
|
||||
*/
|
||||
int ib_send_cm_apr(struct ib_cm_id *cm_id,
|
||||
enum ib_cm_apr_status status,
|
||||
void *info,
|
||||
u8 info_length,
|
||||
const void *private_data,
|
||||
u8 private_data_len);
|
||||
|
||||
struct ib_cm_sidr_req_param {
|
||||
struct ib_sa_path_rec *path;
|
||||
u64 service_id;
|
||||
int timeout_ms;
|
||||
const void *private_data;
|
||||
u8 private_data_len;
|
||||
u8 max_cm_retries;
|
||||
u16 pkey;
|
||||
};
|
||||
|
||||
/**
|
||||
* ib_send_cm_sidr_req - Sends a service ID resolution request to the
|
||||
* remote node.
|
||||
* @cm_id: Communication identifier that will be associated with the
|
||||
* service ID resolution request.
|
||||
* @param: Service ID resolution request information.
|
||||
*/
|
||||
int ib_send_cm_sidr_req(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_sidr_req_param *param);
|
||||
|
||||
struct ib_cm_sidr_rep_param {
|
||||
u32 qp_num;
|
||||
u32 qkey;
|
||||
enum ib_cm_sidr_status status;
|
||||
const void *info;
|
||||
u8 info_length;
|
||||
const void *private_data;
|
||||
u8 private_data_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* ib_send_cm_sidr_rep - Sends a service ID resolution request to the
|
||||
* remote node.
|
||||
* @cm_id: Communication identifier associated with the received service ID
|
||||
* resolution request.
|
||||
* @param: Service ID resolution reply information.
|
||||
*/
|
||||
int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
|
||||
struct ib_cm_sidr_rep_param *param);
|
||||
|
||||
#endif /* IB_CM_H */
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2004 Topspin Corporation. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. 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
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* $Id: ib_fmr_pool.h 1349 2004-12-16 21:09:43Z roland $
|
||||
* $Id: ib_fmr_pool.h 2730 2005-06-28 16:43:03Z sean.hefty $
|
||||
*/
|
||||
|
||||
#if !defined(IB_FMR_POOL_H)
|
||||
|
|
@ -78,7 +79,7 @@ struct ib_pool_fmr {
|
|||
struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd *pd,
|
||||
struct ib_fmr_pool_param *params);
|
||||
|
||||
int ib_destroy_fmr_pool(struct ib_fmr_pool *pool);
|
||||
void ib_destroy_fmr_pool(struct ib_fmr_pool *pool);
|
||||
|
||||
int ib_flush_fmr_pool(struct ib_fmr_pool *pool);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,12 +33,14 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* $Id: ib_mad.h 1389 2004-12-27 22:56:47Z roland $
|
||||
* $Id: ib_mad.h 2775 2005-07-02 13:42:12Z halr $
|
||||
*/
|
||||
|
||||
#if !defined( IB_MAD_H )
|
||||
#define IB_MAD_H
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <ib_verbs.h>
|
||||
|
||||
/* Management base version */
|
||||
|
|
@ -56,6 +58,8 @@
|
|||
#define IB_MGMT_CLASS_VENDOR_RANGE2_START 0x30
|
||||
#define IB_MGMT_CLASS_VENDOR_RANGE2_END 0x4F
|
||||
|
||||
#define IB_OPENIB_OUI (0x001405)
|
||||
|
||||
/* Management methods */
|
||||
#define IB_MGMT_METHOD_GET 0x01
|
||||
#define IB_MGMT_METHOD_SET 0x02
|
||||
|
|
@ -70,18 +74,37 @@
|
|||
|
||||
#define IB_MGMT_MAX_METHODS 128
|
||||
|
||||
/* RMPP information */
|
||||
#define IB_MGMT_RMPP_VERSION 1
|
||||
|
||||
#define IB_MGMT_RMPP_TYPE_DATA 1
|
||||
#define IB_MGMT_RMPP_TYPE_ACK 2
|
||||
#define IB_MGMT_RMPP_TYPE_STOP 3
|
||||
#define IB_MGMT_RMPP_TYPE_ABORT 4
|
||||
|
||||
#define IB_MGMT_RMPP_FLAG_ACTIVE 1
|
||||
#define IB_MGMT_RMPP_FLAG_FIRST (1<<1)
|
||||
#define IB_MGMT_RMPP_FLAG_LAST (1<<2)
|
||||
|
||||
#define IB_MGMT_RMPP_NO_RESPTIME 0x1F
|
||||
|
||||
#define IB_MGMT_RMPP_STATUS_SUCCESS 0
|
||||
#define IB_MGMT_RMPP_STATUS_RESX 1
|
||||
#define IB_MGMT_RMPP_STATUS_T2L 118
|
||||
#define IB_MGMT_RMPP_STATUS_BAD_LEN 119
|
||||
#define IB_MGMT_RMPP_STATUS_BAD_SEG 120
|
||||
#define IB_MGMT_RMPP_STATUS_BADT 121
|
||||
#define IB_MGMT_RMPP_STATUS_W2S 122
|
||||
#define IB_MGMT_RMPP_STATUS_S2B 123
|
||||
#define IB_MGMT_RMPP_STATUS_BAD_STATUS 124
|
||||
#define IB_MGMT_RMPP_STATUS_UNV 125
|
||||
#define IB_MGMT_RMPP_STATUS_TMR 126
|
||||
#define IB_MGMT_RMPP_STATUS_UNSPEC 127
|
||||
|
||||
#define IB_QP0 0
|
||||
#define IB_QP1 __constant_htonl(1)
|
||||
#define IB_QP1_QKEY 0x80010000
|
||||
|
||||
struct ib_grh {
|
||||
u32 version_tclass_flow;
|
||||
u16 paylen;
|
||||
u8 next_hdr;
|
||||
u8 hop_limit;
|
||||
union ib_gid sgid;
|
||||
union ib_gid dgid;
|
||||
} __attribute__ ((packed));
|
||||
#define IB_QP_SET_QKEY 0x80000000
|
||||
|
||||
struct ib_mad_hdr {
|
||||
u8 base_version;
|
||||
|
|
@ -94,7 +117,7 @@ struct ib_mad_hdr {
|
|||
u16 attr_id;
|
||||
u16 resv;
|
||||
u32 attr_mod;
|
||||
} __attribute__ ((packed));
|
||||
};
|
||||
|
||||
struct ib_rmpp_hdr {
|
||||
u8 rmpp_version;
|
||||
|
|
@ -103,17 +126,41 @@ struct ib_rmpp_hdr {
|
|||
u8 rmpp_status;
|
||||
u32 seg_num;
|
||||
u32 paylen_newwin;
|
||||
};
|
||||
|
||||
typedef u64 __bitwise ib_sa_comp_mask;
|
||||
|
||||
#define IB_SA_COMP_MASK(n) ((__force ib_sa_comp_mask) cpu_to_be64(1ull << n))
|
||||
|
||||
/*
|
||||
* ib_sa_hdr and ib_sa_mad 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_mad {
|
||||
struct ib_mad_hdr mad_hdr;
|
||||
u8 data[232];
|
||||
} __attribute__ ((packed));
|
||||
};
|
||||
|
||||
struct ib_rmpp_mad {
|
||||
struct ib_mad_hdr mad_hdr;
|
||||
struct ib_rmpp_hdr rmpp_hdr;
|
||||
u8 data[220];
|
||||
};
|
||||
|
||||
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_vendor_mad {
|
||||
|
|
@ -122,7 +169,70 @@ struct ib_vendor_mad {
|
|||
u8 reserved;
|
||||
u8 oui[3];
|
||||
u8 data[216];
|
||||
} __attribute__ ((packed));
|
||||
};
|
||||
|
||||
/**
|
||||
* ib_mad_send_buf - MAD data buffer and work request for sends.
|
||||
* @mad: References an allocated MAD data buffer. The size of the data
|
||||
* buffer is specified in the @send_wr.length field.
|
||||
* @mapping: DMA mapping information.
|
||||
* @mad_agent: MAD agent that allocated the buffer.
|
||||
* @context: User-controlled context fields.
|
||||
* @send_wr: An initialized work request structure used when sending the MAD.
|
||||
* The wr_id field of the work request is initialized to reference this
|
||||
* data structure.
|
||||
* @sge: A scatter-gather list referenced by the work request.
|
||||
*
|
||||
* Users are responsible for initializing the MAD buffer itself, with the
|
||||
* exception of specifying the payload length field in any RMPP MAD.
|
||||
*/
|
||||
struct ib_mad_send_buf {
|
||||
struct ib_mad *mad;
|
||||
DECLARE_PCI_UNMAP_ADDR(mapping)
|
||||
struct ib_mad_agent *mad_agent;
|
||||
void *context[2];
|
||||
struct ib_send_wr send_wr;
|
||||
struct ib_sge sge;
|
||||
};
|
||||
|
||||
/**
|
||||
* ib_get_rmpp_resptime - Returns the RMPP response time.
|
||||
* @rmpp_hdr: An RMPP header.
|
||||
*/
|
||||
static inline u8 ib_get_rmpp_resptime(struct ib_rmpp_hdr *rmpp_hdr)
|
||||
{
|
||||
return rmpp_hdr->rmpp_rtime_flags >> 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* ib_get_rmpp_flags - Returns the RMPP flags.
|
||||
* @rmpp_hdr: An RMPP header.
|
||||
*/
|
||||
static inline u8 ib_get_rmpp_flags(struct ib_rmpp_hdr *rmpp_hdr)
|
||||
{
|
||||
return rmpp_hdr->rmpp_rtime_flags & 0x7;
|
||||
}
|
||||
|
||||
/**
|
||||
* ib_set_rmpp_resptime - Sets the response time in an RMPP header.
|
||||
* @rmpp_hdr: An RMPP header.
|
||||
* @rtime: The response time to set.
|
||||
*/
|
||||
static inline void ib_set_rmpp_resptime(struct ib_rmpp_hdr *rmpp_hdr, u8 rtime)
|
||||
{
|
||||
rmpp_hdr->rmpp_rtime_flags = ib_get_rmpp_flags(rmpp_hdr) | (rtime << 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* ib_set_rmpp_flags - Sets the flags in an RMPP header.
|
||||
* @rmpp_hdr: An RMPP header.
|
||||
* @flags: The flags to set.
|
||||
*/
|
||||
static inline void ib_set_rmpp_flags(struct ib_rmpp_hdr *rmpp_hdr, u8 flags)
|
||||
{
|
||||
rmpp_hdr->rmpp_rtime_flags = (rmpp_hdr->rmpp_rtime_flags & 0xF1) |
|
||||
(flags & 0x7);
|
||||
}
|
||||
|
||||
struct ib_mad_agent;
|
||||
struct ib_mad_send_wc;
|
||||
|
|
@ -168,6 +278,7 @@ typedef void (*ib_mad_recv_handler)(struct ib_mad_agent *mad_agent,
|
|||
* ib_mad_agent - Used to track MAD registration with the access layer.
|
||||
* @device: Reference to device registration is on.
|
||||
* @qp: Reference to QP used for sending and receiving MADs.
|
||||
* @mr: Memory region for system memory usable for DMA.
|
||||
* @recv_handler: Callback handler for a received MAD.
|
||||
* @send_handler: Callback handler for a sent MAD.
|
||||
* @snoop_handler: Callback handler for snooped sent MADs.
|
||||
|
|
@ -176,16 +287,19 @@ typedef void (*ib_mad_recv_handler)(struct ib_mad_agent *mad_agent,
|
|||
* Unsolicited MADs sent by this client will have the upper 32-bits
|
||||
* of their TID set to this value.
|
||||
* @port_num: Port number on which QP is registered
|
||||
* @rmpp_version: If set, indicates the RMPP version used by this agent.
|
||||
*/
|
||||
struct ib_mad_agent {
|
||||
struct ib_device *device;
|
||||
struct ib_qp *qp;
|
||||
struct ib_mr *mr;
|
||||
ib_mad_recv_handler recv_handler;
|
||||
ib_mad_send_handler send_handler;
|
||||
ib_mad_snoop_handler snoop_handler;
|
||||
void *context;
|
||||
u32 hi_tid;
|
||||
u8 port_num;
|
||||
u8 rmpp_version;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -219,6 +333,7 @@ struct ib_mad_recv_buf {
|
|||
* ib_mad_recv_wc - received MAD information.
|
||||
* @wc: Completion information for the received data.
|
||||
* @recv_buf: Specifies the location of the received data buffer(s).
|
||||
* @rmpp_list: Specifies a list of RMPP reassembled received MAD buffers.
|
||||
* @mad_len: The length of the received MAD, without duplicated headers.
|
||||
*
|
||||
* For received response, the wr_id field of the wc is set to the wr_id
|
||||
|
|
@ -227,6 +342,7 @@ struct ib_mad_recv_buf {
|
|||
struct ib_mad_recv_wc {
|
||||
struct ib_wc *wc;
|
||||
struct ib_mad_recv_buf recv_buf;
|
||||
struct list_head rmpp_list;
|
||||
int mad_len;
|
||||
};
|
||||
|
||||
|
|
@ -322,6 +438,16 @@ int ib_unregister_mad_agent(struct ib_mad_agent *mad_agent);
|
|||
* @bad_send_wr: Specifies the MAD on which an error was encountered.
|
||||
*
|
||||
* Sent MADs are not guaranteed to complete in the order that they were posted.
|
||||
*
|
||||
* If the MAD requires RMPP, the data buffer should contain a single copy
|
||||
* of the common MAD, RMPP, and class specific headers, followed by the class
|
||||
* defined data. If the class defined data would not divide evenly into
|
||||
* RMPP segments, then space must be allocated at the end of the referenced
|
||||
* buffer for any required padding. To indicate the amount of class defined
|
||||
* data being transferred, the paylen_newwin field in the RMPP header should
|
||||
* be set to the size of the class specific header plus the amount of class
|
||||
* defined data being transferred. The paylen_newwin field should be
|
||||
* specified in network-byte order.
|
||||
*/
|
||||
int ib_post_send_mad(struct ib_mad_agent *mad_agent,
|
||||
struct ib_send_wr *send_wr,
|
||||
|
|
@ -334,15 +460,13 @@ int ib_post_send_mad(struct ib_mad_agent *mad_agent,
|
|||
* referenced buffer should be at least the size of the mad_len specified
|
||||
* by @mad_recv_wc.
|
||||
*
|
||||
* This call copies a chain of received RMPP MADs into a single data buffer,
|
||||
* This call copies a chain of received MAD segments into a single data buffer,
|
||||
* removing duplicated headers.
|
||||
*/
|
||||
void ib_coalesce_recv_mad(struct ib_mad_recv_wc *mad_recv_wc,
|
||||
void *buf);
|
||||
void ib_coalesce_recv_mad(struct ib_mad_recv_wc *mad_recv_wc, void *buf);
|
||||
|
||||
/**
|
||||
* ib_free_recv_mad - Returns data buffers used to receive a MAD to the
|
||||
* access layer.
|
||||
* ib_free_recv_mad - Returns data buffers used to receive a MAD.
|
||||
* @mad_recv_wc: Work completion information for a received MAD.
|
||||
*
|
||||
* Clients receiving MADs through their ib_mad_recv_handler must call this
|
||||
|
|
@ -358,8 +482,18 @@ void ib_free_recv_mad(struct ib_mad_recv_wc *mad_recv_wc);
|
|||
* MADs will be returned to the user through the corresponding
|
||||
* ib_mad_send_handler.
|
||||
*/
|
||||
void ib_cancel_mad(struct ib_mad_agent *mad_agent,
|
||||
u64 wr_id);
|
||||
void ib_cancel_mad(struct ib_mad_agent *mad_agent, u64 wr_id);
|
||||
|
||||
/**
|
||||
* ib_modify_mad - Modifies an outstanding send MAD operation.
|
||||
* @mad_agent: Specifies the registration associated with sent MAD.
|
||||
* @wr_id: Indicates the work request identifier of the MAD to modify.
|
||||
* @timeout_ms: New timeout value for sent MAD.
|
||||
*
|
||||
* This call will reset the timeout value for a sent MAD to the specified
|
||||
* value.
|
||||
*/
|
||||
int ib_modify_mad(struct ib_mad_agent *mad_agent, u64 wr_id, u32 timeout_ms);
|
||||
|
||||
/**
|
||||
* ib_redirect_mad_qp - Registers a QP for MAD services.
|
||||
|
|
@ -401,4 +535,43 @@ struct ib_mad_agent *ib_redirect_mad_qp(struct ib_qp *qp,
|
|||
int ib_process_mad_wc(struct ib_mad_agent *mad_agent,
|
||||
struct ib_wc *wc);
|
||||
|
||||
/**
|
||||
* ib_create_send_mad - Allocate and initialize a data buffer and work request
|
||||
* for sending a MAD.
|
||||
* @mad_agent: Specifies the registered MAD service to associate with the MAD.
|
||||
* @remote_qpn: Specifies the QPN of the receiving node.
|
||||
* @pkey_index: Specifies which PKey the MAD will be sent using. This field
|
||||
* is valid only if the remote_qpn is QP 1.
|
||||
* @ah: References the address handle used to transfer to the remote node.
|
||||
* @rmpp_active: Indicates if the send will enable RMPP.
|
||||
* @hdr_len: Indicates the size of the data header of the MAD. This length
|
||||
* should include the common MAD header, RMPP header, plus any class
|
||||
* specific header.
|
||||
* @data_len: Indicates the size of any user-transferred data. The call will
|
||||
* automatically adjust the allocated buffer size to account for any
|
||||
* additional padding that may be necessary.
|
||||
* @gfp_mask: GFP mask used for the memory allocation.
|
||||
*
|
||||
* This is a helper routine that may be used to allocate a MAD. Users are
|
||||
* not required to allocate outbound MADs using this call. The returned
|
||||
* MAD send buffer will reference a data buffer usable for sending a MAD, along
|
||||
* with an initialized work request structure. Users may modify the returned
|
||||
* MAD data buffer or work request before posting the send.
|
||||
*
|
||||
* The returned data buffer will be cleared. Users are responsible for
|
||||
* initializing the common MAD and any class specific headers. If @rmpp_active
|
||||
* is set, the RMPP header will be initialized for sending.
|
||||
*/
|
||||
struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent,
|
||||
u32 remote_qpn, u16 pkey_index,
|
||||
struct ib_ah *ah, int rmpp_active,
|
||||
int hdr_len, int data_len,
|
||||
unsigned int __nocast gfp_mask);
|
||||
|
||||
/**
|
||||
* ib_free_send_mad - Returns data buffers used to send a MAD.
|
||||
* @send_buf: Previously allocated send data buffer.
|
||||
*/
|
||||
void ib_free_send_mad(struct ib_mad_send_buf *send_buf);
|
||||
|
||||
#endif /* IB_MAD_H */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. 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
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* $Id: ib_sa.h 1389 2004-12-27 22:56:47Z roland $
|
||||
* $Id: ib_sa.h 2811 2005-07-06 18:11:43Z halr $
|
||||
*/
|
||||
|
||||
#ifndef IB_SA_H
|
||||
|
|
@ -41,9 +42,11 @@
|
|||
#include <ib_mad.h>
|
||||
|
||||
enum {
|
||||
IB_SA_CLASS_VERSION = 2, /* IB spec version 1.1/1.2 */
|
||||
IB_SA_CLASS_VERSION = 2, /* IB spec version 1.1/1.2 */
|
||||
|
||||
IB_SA_METHOD_DELETE = 0x15
|
||||
IB_SA_METHOD_GET_TABLE = 0x12,
|
||||
IB_SA_METHOD_GET_TABLE_RESP = 0x92,
|
||||
IB_SA_METHOD_DELETE = 0x15
|
||||
};
|
||||
|
||||
enum ib_sa_selector {
|
||||
|
|
@ -87,10 +90,6 @@ static inline int ib_sa_rate_enum_to_int(enum ib_sa_rate rate)
|
|||
}
|
||||
}
|
||||
|
||||
typedef u64 __bitwise ib_sa_comp_mask;
|
||||
|
||||
#define IB_SA_COMP_MASK(n) ((__force ib_sa_comp_mask) cpu_to_be64(1ull << n))
|
||||
|
||||
/*
|
||||
* Structures for SA records are named "struct ib_sa_xxx_rec." No
|
||||
* attempt is made to pack structures to match the physical layout of
|
||||
|
|
@ -195,6 +194,61 @@ struct ib_sa_mcmember_rec {
|
|||
int proxy_join;
|
||||
};
|
||||
|
||||
/* Service Record Component Mask Sec 15.2.5.14 Ver 1.1 */
|
||||
#define IB_SA_SERVICE_REC_SERVICE_ID IB_SA_COMP_MASK( 0)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_GID IB_SA_COMP_MASK( 1)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_PKEY IB_SA_COMP_MASK( 2)
|
||||
/* reserved: 3 */
|
||||
#define IB_SA_SERVICE_REC_SERVICE_LEASE IB_SA_COMP_MASK( 4)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_KEY IB_SA_COMP_MASK( 5)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_NAME IB_SA_COMP_MASK( 6)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_0 IB_SA_COMP_MASK( 7)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_1 IB_SA_COMP_MASK( 8)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_2 IB_SA_COMP_MASK( 9)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_3 IB_SA_COMP_MASK(10)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_4 IB_SA_COMP_MASK(11)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_5 IB_SA_COMP_MASK(12)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_6 IB_SA_COMP_MASK(13)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_7 IB_SA_COMP_MASK(14)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_8 IB_SA_COMP_MASK(15)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_9 IB_SA_COMP_MASK(16)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_10 IB_SA_COMP_MASK(17)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_11 IB_SA_COMP_MASK(18)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_12 IB_SA_COMP_MASK(19)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_13 IB_SA_COMP_MASK(20)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_14 IB_SA_COMP_MASK(21)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA8_15 IB_SA_COMP_MASK(22)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA16_0 IB_SA_COMP_MASK(23)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA16_1 IB_SA_COMP_MASK(24)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA16_2 IB_SA_COMP_MASK(25)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA16_3 IB_SA_COMP_MASK(26)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA16_4 IB_SA_COMP_MASK(27)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA16_5 IB_SA_COMP_MASK(28)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA16_6 IB_SA_COMP_MASK(29)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA16_7 IB_SA_COMP_MASK(30)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA32_0 IB_SA_COMP_MASK(31)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA32_1 IB_SA_COMP_MASK(32)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA32_2 IB_SA_COMP_MASK(33)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA32_3 IB_SA_COMP_MASK(34)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA64_0 IB_SA_COMP_MASK(35)
|
||||
#define IB_SA_SERVICE_REC_SERVICE_DATA64_1 IB_SA_COMP_MASK(36)
|
||||
|
||||
#define IB_DEFAULT_SERVICE_LEASE 0xFFFFFFFF
|
||||
|
||||
struct ib_sa_service_rec {
|
||||
u64 id;
|
||||
union ib_gid gid;
|
||||
u16 pkey;
|
||||
/* reserved */
|
||||
u32 lease;
|
||||
u8 key[16];
|
||||
u8 name[64];
|
||||
u8 data8[16];
|
||||
u16 data16[8];
|
||||
u32 data32[4];
|
||||
u64 data64[2];
|
||||
};
|
||||
|
||||
struct ib_sa_query;
|
||||
|
||||
void ib_sa_cancel_query(int id, struct ib_sa_query *query);
|
||||
|
|
@ -202,7 +256,7 @@ void ib_sa_cancel_query(int id, struct ib_sa_query *query);
|
|||
int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
|
||||
struct ib_sa_path_rec *rec,
|
||||
ib_sa_comp_mask comp_mask,
|
||||
int timeout_ms, int gfp_mask,
|
||||
int timeout_ms, unsigned int __nocast gfp_mask,
|
||||
void (*callback)(int status,
|
||||
struct ib_sa_path_rec *resp,
|
||||
void *context),
|
||||
|
|
@ -213,13 +267,24 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
|
|||
u8 method,
|
||||
struct ib_sa_mcmember_rec *rec,
|
||||
ib_sa_comp_mask comp_mask,
|
||||
int timeout_ms, int gfp_mask,
|
||||
int timeout_ms, unsigned int __nocast gfp_mask,
|
||||
void (*callback)(int status,
|
||||
struct ib_sa_mcmember_rec *resp,
|
||||
void *context),
|
||||
void *context,
|
||||
struct ib_sa_query **query);
|
||||
|
||||
int ib_sa_service_rec_query(struct ib_device *device, u8 port_num,
|
||||
u8 method,
|
||||
struct ib_sa_service_rec *rec,
|
||||
ib_sa_comp_mask comp_mask,
|
||||
int timeout_ms, unsigned int __nocast gfp_mask,
|
||||
void (*callback)(int status,
|
||||
struct ib_sa_service_rec *resp,
|
||||
void *context),
|
||||
void *context,
|
||||
struct ib_sa_query **sa_query);
|
||||
|
||||
/**
|
||||
* ib_sa_mcmember_rec_set - Start an MCMember set query
|
||||
* @device:device to send query on
|
||||
|
|
@ -248,7 +313,7 @@ static inline int
|
|||
ib_sa_mcmember_rec_set(struct ib_device *device, u8 port_num,
|
||||
struct ib_sa_mcmember_rec *rec,
|
||||
ib_sa_comp_mask comp_mask,
|
||||
int timeout_ms, int gfp_mask,
|
||||
int timeout_ms, unsigned int __nocast gfp_mask,
|
||||
void (*callback)(int status,
|
||||
struct ib_sa_mcmember_rec *resp,
|
||||
void *context),
|
||||
|
|
@ -290,7 +355,7 @@ static inline int
|
|||
ib_sa_mcmember_rec_delete(struct ib_device *device, u8 port_num,
|
||||
struct ib_sa_mcmember_rec *rec,
|
||||
ib_sa_comp_mask comp_mask,
|
||||
int timeout_ms, int gfp_mask,
|
||||
int timeout_ms, unsigned int __nocast gfp_mask,
|
||||
void (*callback)(int status,
|
||||
struct ib_sa_mcmember_rec *resp,
|
||||
void *context),
|
||||
|
|
|
|||
328
drivers/infiniband/include/ib_user_cm.h
Normal file
328
drivers/infiniband/include/ib_user_cm.h
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
/*
|
||||
* Copyright (c) 2005 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: ib_user_cm.h 2576 2005-06-09 17:00:30Z libor $
|
||||
*/
|
||||
|
||||
#ifndef IB_USER_CM_H
|
||||
#define IB_USER_CM_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define IB_USER_CM_ABI_VERSION 1
|
||||
|
||||
enum {
|
||||
IB_USER_CM_CMD_CREATE_ID,
|
||||
IB_USER_CM_CMD_DESTROY_ID,
|
||||
IB_USER_CM_CMD_ATTR_ID,
|
||||
|
||||
IB_USER_CM_CMD_LISTEN,
|
||||
IB_USER_CM_CMD_ESTABLISH,
|
||||
|
||||
IB_USER_CM_CMD_SEND_REQ,
|
||||
IB_USER_CM_CMD_SEND_REP,
|
||||
IB_USER_CM_CMD_SEND_RTU,
|
||||
IB_USER_CM_CMD_SEND_DREQ,
|
||||
IB_USER_CM_CMD_SEND_DREP,
|
||||
IB_USER_CM_CMD_SEND_REJ,
|
||||
IB_USER_CM_CMD_SEND_MRA,
|
||||
IB_USER_CM_CMD_SEND_LAP,
|
||||
IB_USER_CM_CMD_SEND_APR,
|
||||
IB_USER_CM_CMD_SEND_SIDR_REQ,
|
||||
IB_USER_CM_CMD_SEND_SIDR_REP,
|
||||
|
||||
IB_USER_CM_CMD_EVENT,
|
||||
};
|
||||
/*
|
||||
* command ABI structures.
|
||||
*/
|
||||
struct ib_ucm_cmd_hdr {
|
||||
__u32 cmd;
|
||||
__u16 in;
|
||||
__u16 out;
|
||||
};
|
||||
|
||||
struct ib_ucm_create_id {
|
||||
__u64 response;
|
||||
};
|
||||
|
||||
struct ib_ucm_create_id_resp {
|
||||
__u32 id;
|
||||
};
|
||||
|
||||
struct ib_ucm_destroy_id {
|
||||
__u32 id;
|
||||
};
|
||||
|
||||
struct ib_ucm_attr_id {
|
||||
__u64 response;
|
||||
__u32 id;
|
||||
};
|
||||
|
||||
struct ib_ucm_attr_id_resp {
|
||||
__u64 service_id;
|
||||
__u64 service_mask;
|
||||
__u32 local_id;
|
||||
__u32 remote_id;
|
||||
};
|
||||
|
||||
struct ib_ucm_listen {
|
||||
__u64 service_id;
|
||||
__u64 service_mask;
|
||||
__u32 id;
|
||||
};
|
||||
|
||||
struct ib_ucm_establish {
|
||||
__u32 id;
|
||||
};
|
||||
|
||||
struct ib_ucm_private_data {
|
||||
__u64 data;
|
||||
__u32 id;
|
||||
__u8 len;
|
||||
__u8 reserved[3];
|
||||
};
|
||||
|
||||
struct ib_ucm_path_rec {
|
||||
__u8 dgid[16];
|
||||
__u8 sgid[16];
|
||||
__u16 dlid;
|
||||
__u16 slid;
|
||||
__u32 raw_traffic;
|
||||
__u32 flow_label;
|
||||
__u32 reversible;
|
||||
__u32 mtu;
|
||||
__u16 pkey;
|
||||
__u8 hop_limit;
|
||||
__u8 traffic_class;
|
||||
__u8 numb_path;
|
||||
__u8 sl;
|
||||
__u8 mtu_selector;
|
||||
__u8 rate_selector;
|
||||
__u8 rate;
|
||||
__u8 packet_life_time_selector;
|
||||
__u8 packet_life_time;
|
||||
__u8 preference;
|
||||
};
|
||||
|
||||
struct ib_ucm_req {
|
||||
__u32 id;
|
||||
__u32 qpn;
|
||||
__u32 qp_type;
|
||||
__u32 psn;
|
||||
__u64 sid;
|
||||
__u64 data;
|
||||
__u64 primary_path;
|
||||
__u64 alternate_path;
|
||||
__u8 len;
|
||||
__u8 peer_to_peer;
|
||||
__u8 responder_resources;
|
||||
__u8 initiator_depth;
|
||||
__u8 remote_cm_response_timeout;
|
||||
__u8 flow_control;
|
||||
__u8 local_cm_response_timeout;
|
||||
__u8 retry_count;
|
||||
__u8 rnr_retry_count;
|
||||
__u8 max_cm_retries;
|
||||
__u8 srq;
|
||||
__u8 reserved[1];
|
||||
};
|
||||
|
||||
struct ib_ucm_rep {
|
||||
__u64 data;
|
||||
__u32 id;
|
||||
__u32 qpn;
|
||||
__u32 psn;
|
||||
__u8 len;
|
||||
__u8 responder_resources;
|
||||
__u8 initiator_depth;
|
||||
__u8 target_ack_delay;
|
||||
__u8 failover_accepted;
|
||||
__u8 flow_control;
|
||||
__u8 rnr_retry_count;
|
||||
__u8 srq;
|
||||
};
|
||||
|
||||
struct ib_ucm_info {
|
||||
__u32 id;
|
||||
__u32 status;
|
||||
__u64 info;
|
||||
__u64 data;
|
||||
__u8 info_len;
|
||||
__u8 data_len;
|
||||
__u8 reserved[2];
|
||||
};
|
||||
|
||||
struct ib_ucm_mra {
|
||||
__u64 data;
|
||||
__u32 id;
|
||||
__u8 len;
|
||||
__u8 timeout;
|
||||
__u8 reserved[2];
|
||||
};
|
||||
|
||||
struct ib_ucm_lap {
|
||||
__u64 path;
|
||||
__u64 data;
|
||||
__u32 id;
|
||||
__u8 len;
|
||||
__u8 reserved[3];
|
||||
};
|
||||
|
||||
struct ib_ucm_sidr_req {
|
||||
__u32 id;
|
||||
__u32 timeout;
|
||||
__u64 sid;
|
||||
__u64 data;
|
||||
__u64 path;
|
||||
__u16 pkey;
|
||||
__u8 len;
|
||||
__u8 max_cm_retries;
|
||||
};
|
||||
|
||||
struct ib_ucm_sidr_rep {
|
||||
__u32 id;
|
||||
__u32 qpn;
|
||||
__u32 qkey;
|
||||
__u32 status;
|
||||
__u64 info;
|
||||
__u64 data;
|
||||
__u8 info_len;
|
||||
__u8 data_len;
|
||||
__u8 reserved[2];
|
||||
};
|
||||
/*
|
||||
* event notification ABI structures.
|
||||
*/
|
||||
struct ib_ucm_event_get {
|
||||
__u64 response;
|
||||
__u64 data;
|
||||
__u64 info;
|
||||
__u8 data_len;
|
||||
__u8 info_len;
|
||||
__u8 reserved[2];
|
||||
};
|
||||
|
||||
struct ib_ucm_req_event_resp {
|
||||
__u32 listen_id;
|
||||
/* device */
|
||||
/* port */
|
||||
struct ib_ucm_path_rec primary_path;
|
||||
struct ib_ucm_path_rec alternate_path;
|
||||
__u64 remote_ca_guid;
|
||||
__u32 remote_qkey;
|
||||
__u32 remote_qpn;
|
||||
__u32 qp_type;
|
||||
__u32 starting_psn;
|
||||
__u8 responder_resources;
|
||||
__u8 initiator_depth;
|
||||
__u8 local_cm_response_timeout;
|
||||
__u8 flow_control;
|
||||
__u8 remote_cm_response_timeout;
|
||||
__u8 retry_count;
|
||||
__u8 rnr_retry_count;
|
||||
__u8 srq;
|
||||
};
|
||||
|
||||
struct ib_ucm_rep_event_resp {
|
||||
__u64 remote_ca_guid;
|
||||
__u32 remote_qkey;
|
||||
__u32 remote_qpn;
|
||||
__u32 starting_psn;
|
||||
__u8 responder_resources;
|
||||
__u8 initiator_depth;
|
||||
__u8 target_ack_delay;
|
||||
__u8 failover_accepted;
|
||||
__u8 flow_control;
|
||||
__u8 rnr_retry_count;
|
||||
__u8 srq;
|
||||
__u8 reserved[1];
|
||||
};
|
||||
|
||||
struct ib_ucm_rej_event_resp {
|
||||
__u32 reason;
|
||||
/* ari in ib_ucm_event_get info field. */
|
||||
};
|
||||
|
||||
struct ib_ucm_mra_event_resp {
|
||||
__u8 timeout;
|
||||
__u8 reserved[3];
|
||||
};
|
||||
|
||||
struct ib_ucm_lap_event_resp {
|
||||
struct ib_ucm_path_rec path;
|
||||
};
|
||||
|
||||
struct ib_ucm_apr_event_resp {
|
||||
__u32 status;
|
||||
/* apr info in ib_ucm_event_get info field. */
|
||||
};
|
||||
|
||||
struct ib_ucm_sidr_req_event_resp {
|
||||
__u32 listen_id;
|
||||
/* device */
|
||||
/* port */
|
||||
__u16 pkey;
|
||||
__u8 reserved[2];
|
||||
};
|
||||
|
||||
struct ib_ucm_sidr_rep_event_resp {
|
||||
__u32 status;
|
||||
__u32 qkey;
|
||||
__u32 qpn;
|
||||
/* info in ib_ucm_event_get info field. */
|
||||
};
|
||||
|
||||
#define IB_UCM_PRES_DATA 0x01
|
||||
#define IB_UCM_PRES_INFO 0x02
|
||||
#define IB_UCM_PRES_PRIMARY 0x04
|
||||
#define IB_UCM_PRES_ALTERNATE 0x08
|
||||
|
||||
struct ib_ucm_event_resp {
|
||||
__u32 id;
|
||||
__u32 event;
|
||||
__u32 present;
|
||||
union {
|
||||
struct ib_ucm_req_event_resp req_resp;
|
||||
struct ib_ucm_rep_event_resp rep_resp;
|
||||
struct ib_ucm_rej_event_resp rej_resp;
|
||||
struct ib_ucm_mra_event_resp mra_resp;
|
||||
struct ib_ucm_lap_event_resp lap_resp;
|
||||
struct ib_ucm_apr_event_resp apr_resp;
|
||||
|
||||
struct ib_ucm_sidr_req_event_resp sidr_req_resp;
|
||||
struct ib_ucm_sidr_rep_event_resp sidr_rep_resp;
|
||||
|
||||
__u32 send_status;
|
||||
} u;
|
||||
};
|
||||
|
||||
#endif /* IB_USER_CM_H */
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2004 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Voltaire, Inc. 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
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* $Id: ib_user_mad.h 1389 2004-12-27 22:56:47Z roland $
|
||||
* $Id: ib_user_mad.h 2814 2005-07-06 19:14:09Z halr $
|
||||
*/
|
||||
|
||||
#ifndef IB_USER_MAD_H
|
||||
|
|
@ -42,7 +43,7 @@
|
|||
* Increment this value if any changes that break userspace ABI
|
||||
* compatibility are made.
|
||||
*/
|
||||
#define IB_USER_MAD_ABI_VERSION 2
|
||||
#define IB_USER_MAD_ABI_VERSION 5
|
||||
|
||||
/*
|
||||
* Make sure that all structs defined in this file remain laid out so
|
||||
|
|
@ -51,13 +52,13 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* ib_user_mad - MAD packet
|
||||
* @data - Contents of MAD
|
||||
* ib_user_mad_hdr - MAD packet header
|
||||
* @id - ID of agent MAD received with/to be sent with
|
||||
* @status - 0 on successful receive, ETIMEDOUT if no response
|
||||
* received (transaction ID in data[] will be set to TID of original
|
||||
* request) (ignored on send)
|
||||
* @timeout_ms - Milliseconds to wait for response (unset on receive)
|
||||
* @retries - Number of automatic retries to attempt
|
||||
* @qpn - Remote QP number received from/to be sent to
|
||||
* @qkey - Remote Q_Key to be sent with (unset on receive)
|
||||
* @lid - Remote lid received from/to be sent to
|
||||
|
|
@ -72,11 +73,12 @@
|
|||
*
|
||||
* All multi-byte quantities are stored in network (big endian) byte order.
|
||||
*/
|
||||
struct ib_user_mad {
|
||||
__u8 data[256];
|
||||
struct ib_user_mad_hdr {
|
||||
__u32 id;
|
||||
__u32 status;
|
||||
__u32 timeout_ms;
|
||||
__u32 retries;
|
||||
__u32 length;
|
||||
__u32 qpn;
|
||||
__u32 qkey;
|
||||
__u16 lid;
|
||||
|
|
@ -90,6 +92,17 @@ struct ib_user_mad {
|
|||
__u32 flow_label;
|
||||
};
|
||||
|
||||
/**
|
||||
* ib_user_mad - MAD packet
|
||||
* @hdr - MAD packet header
|
||||
* @data - Contents of MAD
|
||||
*
|
||||
*/
|
||||
struct ib_user_mad {
|
||||
struct ib_user_mad_hdr hdr;
|
||||
__u8 data[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* ib_user_mad_reg_req - MAD registration request
|
||||
* @id - Set by the kernel; used to identify agent in future requests.
|
||||
|
|
@ -103,6 +116,8 @@ struct ib_user_mad {
|
|||
* management class to receive.
|
||||
* @oui: Indicates IEEE OUI when mgmt_class is a vendor class
|
||||
* in the range from 0x30 to 0x4f. Otherwise not used.
|
||||
* @rmpp_version: If set, indicates the RMPP version used.
|
||||
*
|
||||
*/
|
||||
struct ib_user_mad_reg_req {
|
||||
__u32 id;
|
||||
|
|
@ -111,6 +126,7 @@ struct ib_user_mad_reg_req {
|
|||
__u8 mgmt_class;
|
||||
__u8 mgmt_class_version;
|
||||
__u8 oui[3];
|
||||
__u8 rmpp_version;
|
||||
};
|
||||
|
||||
#define IB_IOCTL_MAGIC 0x1b
|
||||
|
|
|
|||
|
|
@ -289,6 +289,15 @@ struct ib_global_route {
|
|||
u8 traffic_class;
|
||||
};
|
||||
|
||||
struct ib_grh {
|
||||
u32 version_tclass_flow;
|
||||
u16 paylen;
|
||||
u8 next_hdr;
|
||||
u8 hop_limit;
|
||||
union ib_gid sgid;
|
||||
union ib_gid dgid;
|
||||
};
|
||||
|
||||
enum {
|
||||
IB_MULTICAST_QPN = 0xffffff
|
||||
};
|
||||
|
|
@ -566,6 +575,7 @@ struct ib_send_wr {
|
|||
u32 remote_qpn;
|
||||
u32 remote_qkey;
|
||||
int timeout_ms; /* valid for MADs only */
|
||||
int retries; /* valid for MADs only */
|
||||
u16 pkey_index; /* valid for GSI only */
|
||||
u8 port_num; /* valid for DR SMPs on switch only */
|
||||
} ud;
|
||||
|
|
@ -989,6 +999,21 @@ int ib_dealloc_pd(struct ib_pd *pd);
|
|||
*/
|
||||
struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
|
||||
|
||||
/**
|
||||
* ib_create_ah_from_wc - Creates an address handle associated with the
|
||||
* sender of the specified work completion.
|
||||
* @pd: The protection domain associated with the address handle.
|
||||
* @wc: Work completion information associated with a received message.
|
||||
* @grh: References the received global route header. This parameter is
|
||||
* ignored unless the work completion indicates that the GRH is valid.
|
||||
* @port_num: The outbound port number to associate with the address.
|
||||
*
|
||||
* The address handle is used to reference a local or global destination
|
||||
* in all UD QP post sends.
|
||||
*/
|
||||
struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc,
|
||||
struct ib_grh *grh, u8 port_num);
|
||||
|
||||
/**
|
||||
* ib_modify_ah - Modifies the address vector associated with an address
|
||||
* handle.
|
||||
|
|
|
|||
Loading…
Reference in a new issue