提交 f470f8d4 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband: (62 commits)
  mlx4_core: Deprecate log_num_vlan module param
  IB/mlx4: Don't set VLAN in IBoE WQEs' control segment
  IB/mlx4: Enable 4K mtu for IBoE
  RDMA/cxgb4: Mark QP in error before disabling the queue in firmware
  RDMA/cxgb4: Serialize calls to CQ's comp_handler
  RDMA/cxgb3: Serialize calls to CQ's comp_handler
  IB/qib: Fix issue with link states and QSFP cables
  IB/mlx4: Configure extended active speeds
  mlx4_core: Add extended port capabilities support
  IB/qib: Hold links until tuning data is available
  IB/qib: Clean up checkpatch issue
  IB/qib: Remove s_lock around header validation
  IB/qib: Precompute timeout jiffies to optimize latency
  IB/qib: Use RCU for qpn lookup
  IB/qib: Eliminate divide/mod in converting idx to egr buf pointer
  IB/qib: Decode path MTU optimization
  IB/qib: Optimize RC/UC code by IB operation
  IPoIB: Use the right function to do DMA unmap pages
  RDMA/cxgb4: Use correct QID in insert_recv_cqe()
  RDMA/cxgb4: Make sure flush CQ entries are collected on connection close
  ...
无相关合并请求
...@@ -889,6 +889,8 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err) ...@@ -889,6 +889,8 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
break; break;
case IB_CM_ESTABLISHED: case IB_CM_ESTABLISHED:
spin_unlock_irq(&cm_id_priv->lock); spin_unlock_irq(&cm_id_priv->lock);
if (cm_id_priv->qp_type == IB_QPT_XRC_TGT)
break;
ib_send_cm_dreq(cm_id, NULL, 0); ib_send_cm_dreq(cm_id, NULL, 0);
goto retest; goto retest;
case IB_CM_DREQ_SENT: case IB_CM_DREQ_SENT:
...@@ -1008,7 +1010,6 @@ static void cm_format_req(struct cm_req_msg *req_msg, ...@@ -1008,7 +1010,6 @@ static void cm_format_req(struct cm_req_msg *req_msg,
req_msg->service_id = param->service_id; req_msg->service_id = param->service_id;
req_msg->local_ca_guid = cm_id_priv->id.device->node_guid; req_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
cm_req_set_local_qpn(req_msg, cpu_to_be32(param->qp_num)); cm_req_set_local_qpn(req_msg, cpu_to_be32(param->qp_num));
cm_req_set_resp_res(req_msg, param->responder_resources);
cm_req_set_init_depth(req_msg, param->initiator_depth); cm_req_set_init_depth(req_msg, param->initiator_depth);
cm_req_set_remote_resp_timeout(req_msg, cm_req_set_remote_resp_timeout(req_msg,
param->remote_cm_response_timeout); param->remote_cm_response_timeout);
...@@ -1017,12 +1018,16 @@ static void cm_format_req(struct cm_req_msg *req_msg, ...@@ -1017,12 +1018,16 @@ static void cm_format_req(struct cm_req_msg *req_msg,
cm_req_set_starting_psn(req_msg, cpu_to_be32(param->starting_psn)); cm_req_set_starting_psn(req_msg, cpu_to_be32(param->starting_psn));
cm_req_set_local_resp_timeout(req_msg, cm_req_set_local_resp_timeout(req_msg,
param->local_cm_response_timeout); param->local_cm_response_timeout);
cm_req_set_retry_count(req_msg, param->retry_count);
req_msg->pkey = param->primary_path->pkey; req_msg->pkey = param->primary_path->pkey;
cm_req_set_path_mtu(req_msg, param->primary_path->mtu); cm_req_set_path_mtu(req_msg, param->primary_path->mtu);
cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
cm_req_set_max_cm_retries(req_msg, param->max_cm_retries); cm_req_set_max_cm_retries(req_msg, param->max_cm_retries);
cm_req_set_srq(req_msg, param->srq);
if (param->qp_type != IB_QPT_XRC_INI) {
cm_req_set_resp_res(req_msg, param->responder_resources);
cm_req_set_retry_count(req_msg, param->retry_count);
cm_req_set_rnr_retry_count(req_msg, param->rnr_retry_count);
cm_req_set_srq(req_msg, param->srq);
}
if (pri_path->hop_limit <= 1) { if (pri_path->hop_limit <= 1) {
req_msg->primary_local_lid = pri_path->slid; req_msg->primary_local_lid = pri_path->slid;
...@@ -1080,7 +1085,8 @@ static int cm_validate_req_param(struct ib_cm_req_param *param) ...@@ -1080,7 +1085,8 @@ static int cm_validate_req_param(struct ib_cm_req_param *param)
if (!param->primary_path) if (!param->primary_path)
return -EINVAL; return -EINVAL;
if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC) if (param->qp_type != IB_QPT_RC && param->qp_type != IB_QPT_UC &&
param->qp_type != IB_QPT_XRC_INI)
return -EINVAL; return -EINVAL;
if (param->private_data && if (param->private_data &&
...@@ -1601,18 +1607,24 @@ static void cm_format_rep(struct cm_rep_msg *rep_msg, ...@@ -1601,18 +1607,24 @@ static void cm_format_rep(struct cm_rep_msg *rep_msg,
cm_format_mad_hdr(&rep_msg->hdr, CM_REP_ATTR_ID, cm_id_priv->tid); cm_format_mad_hdr(&rep_msg->hdr, CM_REP_ATTR_ID, cm_id_priv->tid);
rep_msg->local_comm_id = cm_id_priv->id.local_id; rep_msg->local_comm_id = cm_id_priv->id.local_id;
rep_msg->remote_comm_id = cm_id_priv->id.remote_id; rep_msg->remote_comm_id = cm_id_priv->id.remote_id;
cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn)); cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn));
rep_msg->resp_resources = param->responder_resources; rep_msg->resp_resources = param->responder_resources;
rep_msg->initiator_depth = param->initiator_depth;
cm_rep_set_target_ack_delay(rep_msg, cm_rep_set_target_ack_delay(rep_msg,
cm_id_priv->av.port->cm_dev->ack_delay); cm_id_priv->av.port->cm_dev->ack_delay);
cm_rep_set_failover(rep_msg, param->failover_accepted); cm_rep_set_failover(rep_msg, param->failover_accepted);
cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count); cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
cm_rep_set_srq(rep_msg, param->srq);
rep_msg->local_ca_guid = cm_id_priv->id.device->node_guid; rep_msg->local_ca_guid = cm_id_priv->id.device->node_guid;
if (cm_id_priv->qp_type != IB_QPT_XRC_TGT) {
rep_msg->initiator_depth = param->initiator_depth;
cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
cm_rep_set_srq(rep_msg, param->srq);
cm_rep_set_local_qpn(rep_msg, cpu_to_be32(param->qp_num));
} else {
cm_rep_set_srq(rep_msg, 1);
cm_rep_set_local_eecn(rep_msg, cpu_to_be32(param->qp_num));
}
if (param->private_data && param->private_data_len) if (param->private_data && param->private_data_len)
memcpy(rep_msg->private_data, param->private_data, memcpy(rep_msg->private_data, param->private_data,
param->private_data_len); param->private_data_len);
...@@ -1660,7 +1672,7 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id, ...@@ -1660,7 +1672,7 @@ int ib_send_cm_rep(struct ib_cm_id *cm_id,
cm_id_priv->initiator_depth = param->initiator_depth; cm_id_priv->initiator_depth = param->initiator_depth;
cm_id_priv->responder_resources = param->responder_resources; cm_id_priv->responder_resources = param->responder_resources;
cm_id_priv->rq_psn = cm_rep_get_starting_psn(rep_msg); cm_id_priv->rq_psn = cm_rep_get_starting_psn(rep_msg);
cm_id_priv->local_qpn = cm_rep_get_local_qpn(rep_msg); cm_id_priv->local_qpn = cpu_to_be32(param->qp_num & 0xFFFFFF);
out: spin_unlock_irqrestore(&cm_id_priv->lock, flags); out: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
return ret; return ret;
...@@ -1731,7 +1743,7 @@ error: spin_unlock_irqrestore(&cm_id_priv->lock, flags); ...@@ -1731,7 +1743,7 @@ error: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
} }
EXPORT_SYMBOL(ib_send_cm_rtu); EXPORT_SYMBOL(ib_send_cm_rtu);
static void cm_format_rep_event(struct cm_work *work) static void cm_format_rep_event(struct cm_work *work, enum ib_qp_type qp_type)
{ {
struct cm_rep_msg *rep_msg; struct cm_rep_msg *rep_msg;
struct ib_cm_rep_event_param *param; struct ib_cm_rep_event_param *param;
...@@ -1740,7 +1752,7 @@ static void cm_format_rep_event(struct cm_work *work) ...@@ -1740,7 +1752,7 @@ static void cm_format_rep_event(struct cm_work *work)
param = &work->cm_event.param.rep_rcvd; param = &work->cm_event.param.rep_rcvd;
param->remote_ca_guid = rep_msg->local_ca_guid; param->remote_ca_guid = rep_msg->local_ca_guid;
param->remote_qkey = be32_to_cpu(rep_msg->local_qkey); param->remote_qkey = be32_to_cpu(rep_msg->local_qkey);
param->remote_qpn = be32_to_cpu(cm_rep_get_local_qpn(rep_msg)); param->remote_qpn = be32_to_cpu(cm_rep_get_qpn(rep_msg, qp_type));
param->starting_psn = be32_to_cpu(cm_rep_get_starting_psn(rep_msg)); param->starting_psn = be32_to_cpu(cm_rep_get_starting_psn(rep_msg));
param->responder_resources = rep_msg->initiator_depth; param->responder_resources = rep_msg->initiator_depth;
param->initiator_depth = rep_msg->resp_resources; param->initiator_depth = rep_msg->resp_resources;
...@@ -1808,7 +1820,7 @@ static int cm_rep_handler(struct cm_work *work) ...@@ -1808,7 +1820,7 @@ static int cm_rep_handler(struct cm_work *work)
return -EINVAL; return -EINVAL;
} }
cm_format_rep_event(work); cm_format_rep_event(work, cm_id_priv->qp_type);
spin_lock_irq(&cm_id_priv->lock); spin_lock_irq(&cm_id_priv->lock);
switch (cm_id_priv->id.state) { switch (cm_id_priv->id.state) {
...@@ -1823,7 +1835,7 @@ static int cm_rep_handler(struct cm_work *work) ...@@ -1823,7 +1835,7 @@ static int cm_rep_handler(struct cm_work *work)
cm_id_priv->timewait_info->work.remote_id = rep_msg->local_comm_id; cm_id_priv->timewait_info->work.remote_id = rep_msg->local_comm_id;
cm_id_priv->timewait_info->remote_ca_guid = rep_msg->local_ca_guid; cm_id_priv->timewait_info->remote_ca_guid = rep_msg->local_ca_guid;
cm_id_priv->timewait_info->remote_qpn = cm_rep_get_local_qpn(rep_msg); cm_id_priv->timewait_info->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
spin_lock(&cm.lock); spin_lock(&cm.lock);
/* Check for duplicate REP. */ /* Check for duplicate REP. */
...@@ -1850,7 +1862,7 @@ static int cm_rep_handler(struct cm_work *work) ...@@ -1850,7 +1862,7 @@ static int cm_rep_handler(struct cm_work *work)
cm_id_priv->id.state = IB_CM_REP_RCVD; cm_id_priv->id.state = IB_CM_REP_RCVD;
cm_id_priv->id.remote_id = rep_msg->local_comm_id; cm_id_priv->id.remote_id = rep_msg->local_comm_id;
cm_id_priv->remote_qpn = cm_rep_get_local_qpn(rep_msg); cm_id_priv->remote_qpn = cm_rep_get_qpn(rep_msg, cm_id_priv->qp_type);
cm_id_priv->initiator_depth = rep_msg->resp_resources; cm_id_priv->initiator_depth = rep_msg->resp_resources;
cm_id_priv->responder_resources = rep_msg->initiator_depth; cm_id_priv->responder_resources = rep_msg->initiator_depth;
cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg); cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg);
...@@ -3492,7 +3504,8 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv, ...@@ -3492,7 +3504,8 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
qp_attr->path_mtu = cm_id_priv->path_mtu; qp_attr->path_mtu = cm_id_priv->path_mtu;
qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn); qp_attr->dest_qp_num = be32_to_cpu(cm_id_priv->remote_qpn);
qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn); qp_attr->rq_psn = be32_to_cpu(cm_id_priv->rq_psn);
if (cm_id_priv->qp_type == IB_QPT_RC) { if (cm_id_priv->qp_type == IB_QPT_RC ||
cm_id_priv->qp_type == IB_QPT_XRC_TGT) {
*qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC | *qp_attr_mask |= IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_MIN_RNR_TIMER; IB_QP_MIN_RNR_TIMER;
qp_attr->max_dest_rd_atomic = qp_attr->max_dest_rd_atomic =
...@@ -3537,15 +3550,21 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv, ...@@ -3537,15 +3550,21 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) { if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) {
*qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN; *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN;
qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn); qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn);
if (cm_id_priv->qp_type == IB_QPT_RC) { switch (cm_id_priv->qp_type) {
*qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT | case IB_QPT_RC:
IB_QP_RNR_RETRY | case IB_QPT_XRC_INI:
*qp_attr_mask |= IB_QP_RETRY_CNT | IB_QP_RNR_RETRY |
IB_QP_MAX_QP_RD_ATOMIC; IB_QP_MAX_QP_RD_ATOMIC;
qp_attr->timeout = cm_id_priv->av.timeout;
qp_attr->retry_cnt = cm_id_priv->retry_count; qp_attr->retry_cnt = cm_id_priv->retry_count;
qp_attr->rnr_retry = cm_id_priv->rnr_retry_count; qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
qp_attr->max_rd_atomic = qp_attr->max_rd_atomic = cm_id_priv->initiator_depth;
cm_id_priv->initiator_depth; /* fall through */
case IB_QPT_XRC_TGT:
*qp_attr_mask |= IB_QP_TIMEOUT;
qp_attr->timeout = cm_id_priv->av.timeout;
break;
default:
break;
} }
if (cm_id_priv->alt_av.ah_attr.dlid) { if (cm_id_priv->alt_av.ah_attr.dlid) {
*qp_attr_mask |= IB_QP_PATH_MIG_STATE; *qp_attr_mask |= IB_QP_PATH_MIG_STATE;
......
/* /*
* Copyright (c) 2004 Intel Corporation. All rights reserved. * Copyright (c) 2004, 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2004 Topspin Corporation. All rights reserved. * Copyright (c) 2004 Topspin Corporation. All rights reserved.
* Copyright (c) 2004 Voltaire Corporation. All rights reserved. * Copyright (c) 2004 Voltaire Corporation. All rights reserved.
* *
...@@ -86,7 +86,7 @@ struct cm_req_msg { ...@@ -86,7 +86,7 @@ struct cm_req_msg {
__be16 pkey; __be16 pkey;
/* path MTU:4, RDC exists:1, RNR retry count:3. */ /* path MTU:4, RDC exists:1, RNR retry count:3. */
u8 offset50; u8 offset50;
/* max CM Retries:4, SRQ:1, rsvd:3 */ /* max CM Retries:4, SRQ:1, extended transport type:3 */
u8 offset51; u8 offset51;
__be16 primary_local_lid; __be16 primary_local_lid;
...@@ -175,6 +175,11 @@ static inline enum ib_qp_type cm_req_get_qp_type(struct cm_req_msg *req_msg) ...@@ -175,6 +175,11 @@ static inline enum ib_qp_type cm_req_get_qp_type(struct cm_req_msg *req_msg)
switch(transport_type) { switch(transport_type) {
case 0: return IB_QPT_RC; case 0: return IB_QPT_RC;
case 1: return IB_QPT_UC; case 1: return IB_QPT_UC;
case 3:
switch (req_msg->offset51 & 0x7) {
case 1: return IB_QPT_XRC_TGT;
default: return 0;
}
default: return 0; default: return 0;
} }
} }
...@@ -188,6 +193,12 @@ static inline void cm_req_set_qp_type(struct cm_req_msg *req_msg, ...@@ -188,6 +193,12 @@ static inline void cm_req_set_qp_type(struct cm_req_msg *req_msg,
req_msg->offset40) & req_msg->offset40) &
0xFFFFFFF9) | 0x2); 0xFFFFFFF9) | 0x2);
break; break;
case IB_QPT_XRC_INI:
req_msg->offset40 = cpu_to_be32((be32_to_cpu(
req_msg->offset40) &
0xFFFFFFF9) | 0x6);
req_msg->offset51 = (req_msg->offset51 & 0xF8) | 1;
break;
default: default:
req_msg->offset40 = cpu_to_be32(be32_to_cpu( req_msg->offset40 = cpu_to_be32(be32_to_cpu(
req_msg->offset40) & req_msg->offset40) &
...@@ -527,6 +538,23 @@ static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, __be32 qpn) ...@@ -527,6 +538,23 @@ static inline void cm_rep_set_local_qpn(struct cm_rep_msg *rep_msg, __be32 qpn)
(be32_to_cpu(rep_msg->offset12) & 0x000000FF)); (be32_to_cpu(rep_msg->offset12) & 0x000000FF));
} }
static inline __be32 cm_rep_get_local_eecn(struct cm_rep_msg *rep_msg)
{
return cpu_to_be32(be32_to_cpu(rep_msg->offset16) >> 8);
}
static inline void cm_rep_set_local_eecn(struct cm_rep_msg *rep_msg, __be32 eecn)
{
rep_msg->offset16 = cpu_to_be32((be32_to_cpu(eecn) << 8) |
(be32_to_cpu(rep_msg->offset16) & 0x000000FF));
}
static inline __be32 cm_rep_get_qpn(struct cm_rep_msg *rep_msg, enum ib_qp_type qp_type)
{
return (qp_type == IB_QPT_XRC_INI) ?
cm_rep_get_local_eecn(rep_msg) : cm_rep_get_local_qpn(rep_msg);
}
static inline __be32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg) static inline __be32 cm_rep_get_starting_psn(struct cm_rep_msg *rep_msg)
{ {
return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8); return cpu_to_be32(be32_to_cpu(rep_msg->offset20) >> 8);
......
...@@ -81,6 +81,7 @@ static DEFINE_IDR(sdp_ps); ...@@ -81,6 +81,7 @@ static DEFINE_IDR(sdp_ps);
static DEFINE_IDR(tcp_ps); static DEFINE_IDR(tcp_ps);
static DEFINE_IDR(udp_ps); static DEFINE_IDR(udp_ps);
static DEFINE_IDR(ipoib_ps); static DEFINE_IDR(ipoib_ps);
static DEFINE_IDR(ib_ps);
struct cma_device { struct cma_device {
struct list_head list; struct list_head list;
...@@ -1179,6 +1180,15 @@ static void cma_set_req_event_data(struct rdma_cm_event *event, ...@@ -1179,6 +1180,15 @@ static void cma_set_req_event_data(struct rdma_cm_event *event,
event->param.conn.qp_num = req_data->remote_qpn; event->param.conn.qp_num = req_data->remote_qpn;
} }
static int cma_check_req_qp_type(struct rdma_cm_id *id, struct ib_cm_event *ib_event)
{
return (((ib_event->event == IB_CM_REQ_RECEIVED) ||
(ib_event->param.req_rcvd.qp_type == id->qp_type)) ||
((ib_event->event == IB_CM_SIDR_REQ_RECEIVED) &&
(id->qp_type == IB_QPT_UD)) ||
(!id->qp_type));
}
static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
{ {
struct rdma_id_private *listen_id, *conn_id; struct rdma_id_private *listen_id, *conn_id;
...@@ -1186,13 +1196,16 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) ...@@ -1186,13 +1196,16 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
int offset, ret; int offset, ret;
listen_id = cm_id->context; listen_id = cm_id->context;
if (!cma_check_req_qp_type(&listen_id->id, ib_event))
return -EINVAL;
if (cma_disable_callback(listen_id, RDMA_CM_LISTEN)) if (cma_disable_callback(listen_id, RDMA_CM_LISTEN))
return -ECONNABORTED; return -ECONNABORTED;
memset(&event, 0, sizeof event); memset(&event, 0, sizeof event);
offset = cma_user_data_offset(listen_id->id.ps); offset = cma_user_data_offset(listen_id->id.ps);
event.event = RDMA_CM_EVENT_CONNECT_REQUEST; event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
if (listen_id->id.qp_type == IB_QPT_UD) { if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) {
conn_id = cma_new_udp_id(&listen_id->id, ib_event); conn_id = cma_new_udp_id(&listen_id->id, ib_event);
event.param.ud.private_data = ib_event->private_data + offset; event.param.ud.private_data = ib_event->private_data + offset;
event.param.ud.private_data_len = event.param.ud.private_data_len =
...@@ -1328,6 +1341,8 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) ...@@ -1328,6 +1341,8 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
switch (iw_event->status) { switch (iw_event->status) {
case 0: case 0:
event.event = RDMA_CM_EVENT_ESTABLISHED; event.event = RDMA_CM_EVENT_ESTABLISHED;
event.param.conn.initiator_depth = iw_event->ird;
event.param.conn.responder_resources = iw_event->ord;
break; break;
case -ECONNRESET: case -ECONNRESET:
case -ECONNREFUSED: case -ECONNREFUSED:
...@@ -1343,6 +1358,8 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) ...@@ -1343,6 +1358,8 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
break; break;
case IW_CM_EVENT_ESTABLISHED: case IW_CM_EVENT_ESTABLISHED:
event.event = RDMA_CM_EVENT_ESTABLISHED; event.event = RDMA_CM_EVENT_ESTABLISHED;
event.param.conn.initiator_depth = iw_event->ird;
event.param.conn.responder_resources = iw_event->ord;
break; break;
default: default:
BUG_ON(1); BUG_ON(1);
...@@ -1433,8 +1450,8 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id, ...@@ -1433,8 +1450,8 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
event.event = RDMA_CM_EVENT_CONNECT_REQUEST; event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
event.param.conn.private_data = iw_event->private_data; event.param.conn.private_data = iw_event->private_data;
event.param.conn.private_data_len = iw_event->private_data_len; event.param.conn.private_data_len = iw_event->private_data_len;
event.param.conn.initiator_depth = attr.max_qp_init_rd_atom; event.param.conn.initiator_depth = iw_event->ird;
event.param.conn.responder_resources = attr.max_qp_rd_atom; event.param.conn.responder_resources = iw_event->ord;
/* /*
* Protect against the user destroying conn_id from another thread * Protect against the user destroying conn_id from another thread
...@@ -2234,6 +2251,9 @@ static int cma_get_port(struct rdma_id_private *id_priv) ...@@ -2234,6 +2251,9 @@ static int cma_get_port(struct rdma_id_private *id_priv)
case RDMA_PS_IPOIB: case RDMA_PS_IPOIB:
ps = &ipoib_ps; ps = &ipoib_ps;
break; break;
case RDMA_PS_IB:
ps = &ib_ps;
break;
default: default:
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
} }
...@@ -2569,7 +2589,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv, ...@@ -2569,7 +2589,7 @@ static int cma_connect_ib(struct rdma_id_private *id_priv,
req.service_id = cma_get_service_id(id_priv->id.ps, req.service_id = cma_get_service_id(id_priv->id.ps,
(struct sockaddr *) &route->addr.dst_addr); (struct sockaddr *) &route->addr.dst_addr);
req.qp_num = id_priv->qp_num; req.qp_num = id_priv->qp_num;
req.qp_type = IB_QPT_RC; req.qp_type = id_priv->id.qp_type;
req.starting_psn = id_priv->seq_num; req.starting_psn = id_priv->seq_num;
req.responder_resources = conn_param->responder_resources; req.responder_resources = conn_param->responder_resources;
req.initiator_depth = conn_param->initiator_depth; req.initiator_depth = conn_param->initiator_depth;
...@@ -2616,14 +2636,16 @@ static int cma_connect_iw(struct rdma_id_private *id_priv, ...@@ -2616,14 +2636,16 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
if (ret) if (ret)
goto out; goto out;
iw_param.ord = conn_param->initiator_depth; if (conn_param) {
iw_param.ird = conn_param->responder_resources; iw_param.ord = conn_param->initiator_depth;
iw_param.private_data = conn_param->private_data; iw_param.ird = conn_param->responder_resources;
iw_param.private_data_len = conn_param->private_data_len; iw_param.private_data = conn_param->private_data;
if (id_priv->id.qp) iw_param.private_data_len = conn_param->private_data_len;
iw_param.qpn = id_priv->id.qp ? id_priv->qp_num : conn_param->qp_num;
} else {
memset(&iw_param, 0, sizeof iw_param);
iw_param.qpn = id_priv->qp_num; iw_param.qpn = id_priv->qp_num;
else }
iw_param.qpn = conn_param->qp_num;
ret = iw_cm_connect(cm_id, &iw_param); ret = iw_cm_connect(cm_id, &iw_param);
out: out:
if (ret) { if (ret) {
...@@ -2765,14 +2787,20 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) ...@@ -2765,14 +2787,20 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
switch (rdma_node_get_transport(id->device->node_type)) { switch (rdma_node_get_transport(id->device->node_type)) {
case RDMA_TRANSPORT_IB: case RDMA_TRANSPORT_IB:
if (id->qp_type == IB_QPT_UD) if (id->qp_type == IB_QPT_UD) {
ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS, if (conn_param)
conn_param->private_data, ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
conn_param->private_data_len); conn_param->private_data,
else if (conn_param) conn_param->private_data_len);
ret = cma_accept_ib(id_priv, conn_param); else
else ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
ret = cma_rep_recv(id_priv); NULL, 0);
} else {
if (conn_param)
ret = cma_accept_ib(id_priv, conn_param);
else
ret = cma_rep_recv(id_priv);
}
break; break;
case RDMA_TRANSPORT_IWARP: case RDMA_TRANSPORT_IWARP:
ret = cma_accept_iw(id_priv, conn_param); ret = cma_accept_iw(id_priv, conn_param);
...@@ -3460,6 +3488,7 @@ static void __exit cma_cleanup(void) ...@@ -3460,6 +3488,7 @@ static void __exit cma_cleanup(void)
idr_destroy(&tcp_ps); idr_destroy(&tcp_ps);
idr_destroy(&udp_ps); idr_destroy(&udp_ps);
idr_destroy(&ipoib_ps); idr_destroy(&ipoib_ps);
idr_destroy(&ib_ps);
} }
module_init(cma_init); module_init(cma_init);
......
...@@ -1596,6 +1596,9 @@ find_mad_agent(struct ib_mad_port_private *port_priv, ...@@ -1596,6 +1596,9 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
mad->mad_hdr.class_version].class; mad->mad_hdr.class_version].class;
if (!class) if (!class)
goto out; goto out;
if (convert_mgmt_class(mad->mad_hdr.mgmt_class) >=
IB_MGMT_MAX_METHODS)
goto out;
method = class->method_table[convert_mgmt_class( method = class->method_table[convert_mgmt_class(
mad->mad_hdr.mgmt_class)]; mad->mad_hdr.mgmt_class)];
if (method) if (method)
......
...@@ -185,17 +185,35 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused, ...@@ -185,17 +185,35 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,
if (ret) if (ret)
return ret; return ret;
rate = (25 * attr.active_speed) / 10;
switch (attr.active_speed) { switch (attr.active_speed) {
case 2: speed = " DDR"; break; case 2:
case 4: speed = " QDR"; break; speed = " DDR";
break;
case 4:
speed = " QDR";
break;
case 8:
speed = " FDR10";
rate = 10;
break;
case 16:
speed = " FDR";
rate = 14;
break;
case 32:
speed = " EDR";
rate = 25;
break;
} }
rate = 25 * ib_width_enum_to_int(attr.active_width) * attr.active_speed; rate *= ib_width_enum_to_int(attr.active_width);
if (rate < 0) if (rate < 0)
return -EINVAL; return -EINVAL;
return sprintf(buf, "%d%s Gb/sec (%dX%s)\n", return sprintf(buf, "%d%s Gb/sec (%dX%s)\n",
rate / 10, rate % 10 ? ".5" : "", rate, (attr.active_speed == 1) ? ".5" : "",
ib_width_enum_to_int(attr.active_width), speed); ib_width_enum_to_int(attr.active_width), speed);
} }
......
...@@ -1122,7 +1122,7 @@ static ssize_t ib_ucm_write(struct file *filp, const char __user *buf, ...@@ -1122,7 +1122,7 @@ static ssize_t ib_ucm_write(struct file *filp, const char __user *buf,
if (copy_from_user(&hdr, buf, sizeof(hdr))) if (copy_from_user(&hdr, buf, sizeof(hdr)))
return -EFAULT; return -EFAULT;
if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucm_cmd_table)) if (hdr.cmd >= ARRAY_SIZE(ucm_cmd_table))
return -EINVAL; return -EINVAL;
if (hdr.in + sizeof(hdr) > len) if (hdr.in + sizeof(hdr) > len)
......
...@@ -276,7 +276,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id, ...@@ -276,7 +276,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,
ucma_set_event_context(ctx, event, uevent); ucma_set_event_context(ctx, event, uevent);
uevent->resp.event = event->event; uevent->resp.event = event->event;
uevent->resp.status = event->status; uevent->resp.status = event->status;
if (cm_id->ps == RDMA_PS_UDP || cm_id->ps == RDMA_PS_IPOIB) if (cm_id->qp_type == IB_QPT_UD)
ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud); ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
else else
ucma_copy_conn_event(&uevent->resp.param.conn, ucma_copy_conn_event(&uevent->resp.param.conn,
...@@ -377,6 +377,9 @@ static int ucma_get_qp_type(struct rdma_ucm_create_id *cmd, enum ib_qp_type *qp_ ...@@ -377,6 +377,9 @@ static int ucma_get_qp_type(struct rdma_ucm_create_id *cmd, enum ib_qp_type *qp_
case RDMA_PS_IPOIB: case RDMA_PS_IPOIB:
*qp_type = IB_QPT_UD; *qp_type = IB_QPT_UD;
return 0; return 0;
case RDMA_PS_IB:
*qp_type = cmd->qp_type;
return 0;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -1270,7 +1273,7 @@ static ssize_t ucma_write(struct file *filp, const char __user *buf, ...@@ -1270,7 +1273,7 @@ static ssize_t ucma_write(struct file *filp, const char __user *buf,
if (copy_from_user(&hdr, buf, sizeof(hdr))) if (copy_from_user(&hdr, buf, sizeof(hdr)))
return -EFAULT; return -EFAULT;
if (hdr.cmd < 0 || hdr.cmd >= ARRAY_SIZE(ucma_cmd_table)) if (hdr.cmd >= ARRAY_SIZE(ucma_cmd_table))
return -EINVAL; return -EINVAL;
if (hdr.in + sizeof(hdr) > len) if (hdr.in + sizeof(hdr) > len)
......
...@@ -458,8 +458,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, ...@@ -458,8 +458,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
goto err; goto err;
} }
if (packet->mad.hdr.id < 0 || if (packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
packet->mad.hdr.id >= IB_UMAD_MAX_AGENTS) {
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
...@@ -703,7 +702,7 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg) ...@@ -703,7 +702,7 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
mutex_lock(&file->port->file_mutex); mutex_lock(&file->port->file_mutex);
mutex_lock(&file->mutex); mutex_lock(&file->mutex);
if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) { if (id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
......
...@@ -76,6 +76,8 @@ struct ib_uverbs_device { ...@@ -76,6 +76,8 @@ struct ib_uverbs_device {
struct ib_device *ib_dev; struct ib_device *ib_dev;
int devnum; int devnum;
struct cdev cdev; struct cdev cdev;
struct rb_root xrcd_tree;
struct mutex xrcd_tree_mutex;
}; };
struct ib_uverbs_event_file { struct ib_uverbs_event_file {
...@@ -120,6 +122,16 @@ struct ib_uevent_object { ...@@ -120,6 +122,16 @@ struct ib_uevent_object {
u32 events_reported; u32 events_reported;
}; };
struct ib_uxrcd_object {
struct ib_uobject uobject;
atomic_t refcnt;
};
struct ib_usrq_object {
struct ib_uevent_object uevent;
struct ib_uxrcd_object *uxrcd;
};
struct ib_uqp_object { struct ib_uqp_object {
struct ib_uevent_object uevent; struct ib_uevent_object uevent;
struct list_head mcast_list; struct list_head mcast_list;
...@@ -142,6 +154,7 @@ extern struct idr ib_uverbs_ah_idr; ...@@ -142,6 +154,7 @@ extern struct idr ib_uverbs_ah_idr;
extern struct idr ib_uverbs_cq_idr; extern struct idr ib_uverbs_cq_idr;
extern struct idr ib_uverbs_qp_idr; extern struct idr ib_uverbs_qp_idr;
extern struct idr ib_uverbs_srq_idr; extern struct idr ib_uverbs_srq_idr;
extern struct idr ib_uverbs_xrcd_idr;
void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj); void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
...@@ -161,6 +174,7 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr); ...@@ -161,6 +174,7 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr); void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_event_handler(struct ib_event_handler *handler, void ib_uverbs_event_handler(struct ib_event_handler *handler,
struct ib_event *event); struct ib_event *event);
void ib_uverbs_dealloc_xrcd(struct ib_uverbs_device *dev, struct ib_xrcd *xrcd);
#define IB_UVERBS_DECLARE_CMD(name) \ #define IB_UVERBS_DECLARE_CMD(name) \
ssize_t ib_uverbs_##name(struct ib_uverbs_file *file, \ ssize_t ib_uverbs_##name(struct ib_uverbs_file *file, \
...@@ -181,6 +195,7 @@ IB_UVERBS_DECLARE_CMD(poll_cq); ...@@ -181,6 +195,7 @@ IB_UVERBS_DECLARE_CMD(poll_cq);
IB_UVERBS_DECLARE_CMD(req_notify_cq); IB_UVERBS_DECLARE_CMD(req_notify_cq);
IB_UVERBS_DECLARE_CMD(destroy_cq); IB_UVERBS_DECLARE_CMD(destroy_cq);
IB_UVERBS_DECLARE_CMD(create_qp); IB_UVERBS_DECLARE_CMD(create_qp);
IB_UVERBS_DECLARE_CMD(open_qp);
IB_UVERBS_DECLARE_CMD(query_qp); IB_UVERBS_DECLARE_CMD(query_qp);
IB_UVERBS_DECLARE_CMD(modify_qp); IB_UVERBS_DECLARE_CMD(modify_qp);
IB_UVERBS_DECLARE_CMD(destroy_qp); IB_UVERBS_DECLARE_CMD(destroy_qp);
...@@ -195,5 +210,8 @@ IB_UVERBS_DECLARE_CMD(create_srq); ...@@ -195,5 +210,8 @@ IB_UVERBS_DECLARE_CMD(create_srq);
IB_UVERBS_DECLARE_CMD(modify_srq); IB_UVERBS_DECLARE_CMD(modify_srq);
IB_UVERBS_DECLARE_CMD(query_srq); IB_UVERBS_DECLARE_CMD(query_srq);
IB_UVERBS_DECLARE_CMD(destroy_srq); IB_UVERBS_DECLARE_CMD(destroy_srq);
IB_UVERBS_DECLARE_CMD(create_xsrq);
IB_UVERBS_DECLARE_CMD(open_xrcd);
IB_UVERBS_DECLARE_CMD(close_xrcd);
#endif /* UVERBS_H */ #endif /* UVERBS_H */
...@@ -72,6 +72,7 @@ DEFINE_IDR(ib_uverbs_ah_idr); ...@@ -72,6 +72,7 @@ DEFINE_IDR(ib_uverbs_ah_idr);
DEFINE_IDR(ib_uverbs_cq_idr); DEFINE_IDR(ib_uverbs_cq_idr);
DEFINE_IDR(ib_uverbs_qp_idr); DEFINE_IDR(ib_uverbs_qp_idr);
DEFINE_IDR(ib_uverbs_srq_idr); DEFINE_IDR(ib_uverbs_srq_idr);
DEFINE_IDR(ib_uverbs_xrcd_idr);
static DEFINE_SPINLOCK(map_lock); static DEFINE_SPINLOCK(map_lock);
static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES); static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
...@@ -107,6 +108,10 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file, ...@@ -107,6 +108,10 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
[IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq, [IB_USER_VERBS_CMD_MODIFY_SRQ] = ib_uverbs_modify_srq,
[IB_USER_VERBS_CMD_QUERY_SRQ] = ib_uverbs_query_srq, [IB_USER_VERBS_CMD_QUERY_SRQ] = ib_uverbs_query_srq,
[IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq, [IB_USER_VERBS_CMD_DESTROY_SRQ] = ib_uverbs_destroy_srq,
[IB_USER_VERBS_CMD_OPEN_XRCD] = ib_uverbs_open_xrcd,
[IB_USER_VERBS_CMD_CLOSE_XRCD] = ib_uverbs_close_xrcd,
[IB_USER_VERBS_CMD_CREATE_XSRQ] = ib_uverbs_create_xsrq,
[IB_USER_VERBS_CMD_OPEN_QP] = ib_uverbs_open_qp
}; };
static void ib_uverbs_add_one(struct ib_device *device); static void ib_uverbs_add_one(struct ib_device *device);
...@@ -202,8 +207,12 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, ...@@ -202,8 +207,12 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
container_of(uobj, struct ib_uqp_object, uevent.uobject); container_of(uobj, struct ib_uqp_object, uevent.uobject);
idr_remove_uobj(&ib_uverbs_qp_idr, uobj); idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
ib_uverbs_detach_umcast(qp, uqp); if (qp != qp->real_qp) {
ib_destroy_qp(qp); ib_close_qp(qp);
} else {
ib_uverbs_detach_umcast(qp, uqp);
ib_destroy_qp(qp);
}
ib_uverbs_release_uevent(file, &uqp->uevent); ib_uverbs_release_uevent(file, &uqp->uevent);
kfree(uqp); kfree(uqp);
} }
...@@ -241,6 +250,18 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, ...@@ -241,6 +250,18 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
kfree(uobj); kfree(uobj);
} }
mutex_lock(&file->device->xrcd_tree_mutex);
list_for_each_entry_safe(uobj, tmp, &context->xrcd_list, list) {
struct ib_xrcd *xrcd = uobj->object;
struct ib_uxrcd_object *uxrcd =
container_of(uobj, struct ib_uxrcd_object, uobject);
idr_remove_uobj(&ib_uverbs_xrcd_idr, uobj);
ib_uverbs_dealloc_xrcd(file->device, xrcd);
kfree(uxrcd);
}
mutex_unlock(&file->device->xrcd_tree_mutex);
list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) { list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
struct ib_pd *pd = uobj->object; struct ib_pd *pd = uobj->object;
...@@ -557,8 +578,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, ...@@ -557,8 +578,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
if (hdr.in_words * 4 != count) if (hdr.in_words * 4 != count)
return -EINVAL; return -EINVAL;
if (hdr.command < 0 || if (hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
hdr.command >= ARRAY_SIZE(uverbs_cmd_table) ||
!uverbs_cmd_table[hdr.command]) !uverbs_cmd_table[hdr.command])
return -EINVAL; return -EINVAL;
...@@ -741,6 +761,8 @@ static void ib_uverbs_add_one(struct ib_device *device) ...@@ -741,6 +761,8 @@ static void ib_uverbs_add_one(struct ib_device *device)
kref_init(&uverbs_dev->ref); kref_init(&uverbs_dev->ref);
init_completion(&uverbs_dev->comp); init_completion(&uverbs_dev->comp);
uverbs_dev->xrcd_tree = RB_ROOT;
mutex_init(&uverbs_dev->xrcd_tree_mutex);
spin_lock(&map_lock); spin_lock(&map_lock);
devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/slab.h>
#include <rdma/ib_verbs.h> #include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h> #include <rdma/ib_cache.h>
...@@ -77,6 +78,31 @@ enum ib_rate mult_to_ib_rate(int mult) ...@@ -77,6 +78,31 @@ enum ib_rate mult_to_ib_rate(int mult)
} }
EXPORT_SYMBOL(mult_to_ib_rate); EXPORT_SYMBOL(mult_to_ib_rate);
int ib_rate_to_mbps(enum ib_rate rate)
{
switch (rate) {
case IB_RATE_2_5_GBPS: return 2500;
case IB_RATE_5_GBPS: return 5000;
case IB_RATE_10_GBPS: return 10000;
case IB_RATE_20_GBPS: return 20000;
case IB_RATE_30_GBPS: return 30000;
case IB_RATE_40_GBPS: return 40000;
case IB_RATE_60_GBPS: return 60000;
case IB_RATE_80_GBPS: return 80000;
case IB_RATE_120_GBPS: return 120000;
case IB_RATE_14_GBPS: return 14062;
case IB_RATE_56_GBPS: return 56250;
case IB_RATE_112_GBPS: return 112500;
case IB_RATE_168_GBPS: return 168750;
case IB_RATE_25_GBPS: return 25781;
case IB_RATE_100_GBPS: return 103125;
case IB_RATE_200_GBPS: return 206250;
case IB_RATE_300_GBPS: return 309375;
default: return -1;
}
}
EXPORT_SYMBOL(ib_rate_to_mbps);
enum rdma_transport_type enum rdma_transport_type
rdma_node_get_transport(enum rdma_node_type node_type) rdma_node_get_transport(enum rdma_node_type node_type)
{ {
...@@ -250,6 +276,13 @@ struct ib_srq *ib_create_srq(struct ib_pd *pd, ...@@ -250,6 +276,13 @@ struct ib_srq *ib_create_srq(struct ib_pd *pd,
srq->uobject = NULL; srq->uobject = NULL;
srq->event_handler = srq_init_attr->event_handler; srq->event_handler = srq_init_attr->event_handler;
srq->srq_context = srq_init_attr->srq_context; srq->srq_context = srq_init_attr->srq_context;
srq->srq_type = srq_init_attr->srq_type;
if (srq->srq_type == IB_SRQT_XRC) {
srq->ext.xrc.xrcd = srq_init_attr->ext.xrc.xrcd;
srq->ext.xrc.cq = srq_init_attr->ext.xrc.cq;
atomic_inc(&srq->ext.xrc.xrcd->usecnt);
atomic_inc(&srq->ext.xrc.cq->usecnt);
}
atomic_inc(&pd->usecnt); atomic_inc(&pd->usecnt);
atomic_set(&srq->usecnt, 0); atomic_set(&srq->usecnt, 0);
} }
...@@ -279,16 +312,29 @@ EXPORT_SYMBOL(ib_query_srq); ...@@ -279,16 +312,29 @@ EXPORT_SYMBOL(ib_query_srq);
int ib_destroy_srq(struct ib_srq *srq) int ib_destroy_srq(struct ib_srq *srq)
{ {
struct ib_pd *pd; struct ib_pd *pd;
enum ib_srq_type srq_type;
struct ib_xrcd *uninitialized_var(xrcd);
struct ib_cq *uninitialized_var(cq);
int ret; int ret;
if (atomic_read(&srq->usecnt)) if (atomic_read(&srq->usecnt))
return -EBUSY; return -EBUSY;
pd = srq->pd; pd = srq->pd;
srq_type = srq->srq_type;
if (srq_type == IB_SRQT_XRC) {
xrcd = srq->ext.xrc.xrcd;
cq = srq->ext.xrc.cq;
}
ret = srq->device->destroy_srq(srq); ret = srq->device->destroy_srq(srq);
if (!ret) if (!ret) {
atomic_dec(&pd->usecnt); atomic_dec(&pd->usecnt);
if (srq_type == IB_SRQT_XRC) {
atomic_dec(&xrcd->usecnt);
atomic_dec(&cq->usecnt);
}
}
return ret; return ret;
} }
...@@ -296,28 +342,123 @@ EXPORT_SYMBOL(ib_destroy_srq); ...@@ -296,28 +342,123 @@ EXPORT_SYMBOL(ib_destroy_srq);
/* Queue pairs */ /* Queue pairs */
static void __ib_shared_qp_event_handler(struct ib_event *event, void *context)
{
struct ib_qp *qp = context;
list_for_each_entry(event->element.qp, &qp->open_list, open_list)
event->element.qp->event_handler(event, event->element.qp->qp_context);
}
static void __ib_insert_xrcd_qp(struct ib_xrcd *xrcd, struct ib_qp *qp)
{
mutex_lock(&xrcd->tgt_qp_mutex);
list_add(&qp->xrcd_list, &xrcd->tgt_qp_list);
mutex_unlock(&xrcd->tgt_qp_mutex);
}
static struct ib_qp *__ib_open_qp(struct ib_qp *real_qp,
void (*event_handler)(struct ib_event *, void *),
void *qp_context)
{
struct ib_qp *qp;
unsigned long flags;
qp = kzalloc(sizeof *qp, GFP_KERNEL);
if (!qp)
return ERR_PTR(-ENOMEM);
qp->real_qp = real_qp;
atomic_inc(&real_qp->usecnt);
qp->device = real_qp->device;
qp->event_handler = event_handler;
qp->qp_context = qp_context;
qp->qp_num = real_qp->qp_num;
qp->qp_type = real_qp->qp_type;
spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
list_add(&qp->open_list, &real_qp->open_list);
spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
return qp;
}
struct ib_qp *ib_open_qp(struct ib_xrcd *xrcd,
struct ib_qp_open_attr *qp_open_attr)
{
struct ib_qp *qp, *real_qp;
if (qp_open_attr->qp_type != IB_QPT_XRC_TGT)
return ERR_PTR(-EINVAL);
qp = ERR_PTR(-EINVAL);
mutex_lock(&xrcd->tgt_qp_mutex);
list_for_each_entry(real_qp, &xrcd->tgt_qp_list, xrcd_list) {
if (real_qp->qp_num == qp_open_attr->qp_num) {
qp = __ib_open_qp(real_qp, qp_open_attr->event_handler,
qp_open_attr->qp_context);
break;
}
}
mutex_unlock(&xrcd->tgt_qp_mutex);
return qp;
}
EXPORT_SYMBOL(ib_open_qp);
struct ib_qp *ib_create_qp(struct ib_pd *pd, struct ib_qp *ib_create_qp(struct ib_pd *pd,
struct ib_qp_init_attr *qp_init_attr) struct ib_qp_init_attr *qp_init_attr)
{ {
struct ib_qp *qp; struct ib_qp *qp, *real_qp;
struct ib_device *device;
qp = pd->device->create_qp(pd, qp_init_attr, NULL); device = pd ? pd->device : qp_init_attr->xrcd->device;
qp = device->create_qp(pd, qp_init_attr, NULL);
if (!IS_ERR(qp)) { if (!IS_ERR(qp)) {
qp->device = pd->device; qp->device = device;
qp->pd = pd; qp->real_qp = qp;
qp->send_cq = qp_init_attr->send_cq; qp->uobject = NULL;
qp->recv_cq = qp_init_attr->recv_cq; qp->qp_type = qp_init_attr->qp_type;
qp->srq = qp_init_attr->srq;
qp->uobject = NULL; if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
qp->event_handler = qp_init_attr->event_handler; qp->event_handler = __ib_shared_qp_event_handler;
qp->qp_context = qp_init_attr->qp_context; qp->qp_context = qp;
qp->qp_type = qp_init_attr->qp_type; qp->pd = NULL;
atomic_inc(&pd->usecnt); qp->send_cq = qp->recv_cq = NULL;
atomic_inc(&qp_init_attr->send_cq->usecnt); qp->srq = NULL;
atomic_inc(&qp_init_attr->recv_cq->usecnt); qp->xrcd = qp_init_attr->xrcd;
if (qp_init_attr->srq) atomic_inc(&qp_init_attr->xrcd->usecnt);
atomic_inc(&qp_init_attr->srq->usecnt); INIT_LIST_HEAD(&qp->open_list);
atomic_set(&qp->usecnt, 0);
real_qp = qp;
qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
qp_init_attr->qp_context);
if (!IS_ERR(qp))
__ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp);
else
real_qp->device->destroy_qp(real_qp);
} else {
qp->event_handler = qp_init_attr->event_handler;
qp->qp_context = qp_init_attr->qp_context;
if (qp_init_attr->qp_type == IB_QPT_XRC_INI) {
qp->recv_cq = NULL;
qp->srq = NULL;
} else {
qp->recv_cq = qp_init_attr->recv_cq;
atomic_inc(&qp_init_attr->recv_cq->usecnt);
qp->srq = qp_init_attr->srq;
if (qp->srq)
atomic_inc(&qp_init_attr->srq->usecnt);
}
qp->pd = pd;
qp->send_cq = qp_init_attr->send_cq;
qp->xrcd = NULL;
atomic_inc(&pd->usecnt);
atomic_inc(&qp_init_attr->send_cq->usecnt);
}
} }
return qp; return qp;
...@@ -326,8 +467,8 @@ EXPORT_SYMBOL(ib_create_qp); ...@@ -326,8 +467,8 @@ EXPORT_SYMBOL(ib_create_qp);
static const struct { static const struct {
int valid; int valid;
enum ib_qp_attr_mask req_param[IB_QPT_RAW_ETHERTYPE + 1]; enum ib_qp_attr_mask req_param[IB_QPT_MAX];
enum ib_qp_attr_mask opt_param[IB_QPT_RAW_ETHERTYPE + 1]; enum ib_qp_attr_mask opt_param[IB_QPT_MAX];
} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = { } qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
[IB_QPS_RESET] = { [IB_QPS_RESET] = {
[IB_QPS_RESET] = { .valid = 1 }, [IB_QPS_RESET] = { .valid = 1 },
...@@ -343,6 +484,12 @@ static const struct { ...@@ -343,6 +484,12 @@ static const struct {
[IB_QPT_RC] = (IB_QP_PKEY_INDEX | [IB_QPT_RC] = (IB_QP_PKEY_INDEX |
IB_QP_PORT | IB_QP_PORT |
IB_QP_ACCESS_FLAGS), IB_QP_ACCESS_FLAGS),
[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX | [IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY), IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX | [IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
...@@ -365,6 +512,12 @@ static const struct { ...@@ -365,6 +512,12 @@ static const struct {
[IB_QPT_RC] = (IB_QP_PKEY_INDEX | [IB_QPT_RC] = (IB_QP_PKEY_INDEX |
IB_QP_PORT | IB_QP_PORT |
IB_QP_ACCESS_FLAGS), IB_QP_ACCESS_FLAGS),
[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
[IB_QPT_XRC_TGT] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX | [IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY), IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX | [IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
...@@ -384,6 +537,16 @@ static const struct { ...@@ -384,6 +537,16 @@ static const struct {
IB_QP_RQ_PSN | IB_QP_RQ_PSN |
IB_QP_MAX_DEST_RD_ATOMIC | IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_MIN_RNR_TIMER), IB_QP_MIN_RNR_TIMER),
[IB_QPT_XRC_INI] = (IB_QP_AV |
IB_QP_PATH_MTU |
IB_QP_DEST_QPN |
IB_QP_RQ_PSN),
[IB_QPT_XRC_TGT] = (IB_QP_AV |
IB_QP_PATH_MTU |
IB_QP_DEST_QPN |
IB_QP_RQ_PSN |
IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_MIN_RNR_TIMER),
}, },
.opt_param = { .opt_param = {
[IB_QPT_UD] = (IB_QP_PKEY_INDEX | [IB_QPT_UD] = (IB_QP_PKEY_INDEX |
...@@ -394,6 +557,12 @@ static const struct { ...@@ -394,6 +557,12 @@ static const struct {
[IB_QPT_RC] = (IB_QP_ALT_PATH | [IB_QPT_RC] = (IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS | IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX), IB_QP_PKEY_INDEX),
[IB_QPT_XRC_INI] = (IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX),
[IB_QPT_XRC_TGT] = (IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX | [IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY), IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX | [IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
...@@ -414,6 +583,13 @@ static const struct { ...@@ -414,6 +583,13 @@ static const struct {
IB_QP_RNR_RETRY | IB_QP_RNR_RETRY |
IB_QP_SQ_PSN | IB_QP_SQ_PSN |
IB_QP_MAX_QP_RD_ATOMIC), IB_QP_MAX_QP_RD_ATOMIC),
[IB_QPT_XRC_INI] = (IB_QP_TIMEOUT |
IB_QP_RETRY_CNT |
IB_QP_RNR_RETRY |
IB_QP_SQ_PSN |
IB_QP_MAX_QP_RD_ATOMIC),
[IB_QPT_XRC_TGT] = (IB_QP_TIMEOUT |
IB_QP_SQ_PSN),
[IB_QPT_SMI] = IB_QP_SQ_PSN, [IB_QPT_SMI] = IB_QP_SQ_PSN,
[IB_QPT_GSI] = IB_QP_SQ_PSN, [IB_QPT_GSI] = IB_QP_SQ_PSN,
}, },
...@@ -429,6 +605,15 @@ static const struct { ...@@ -429,6 +605,15 @@ static const struct {
IB_QP_ACCESS_FLAGS | IB_QP_ACCESS_FLAGS |
IB_QP_MIN_RNR_TIMER | IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE), IB_QP_PATH_MIG_STATE),
[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_PATH_MIG_STATE),
[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
[IB_QPT_SMI] = (IB_QP_CUR_STATE | [IB_QPT_SMI] = (IB_QP_CUR_STATE |
IB_QP_QKEY), IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_CUR_STATE | [IB_QPT_GSI] = (IB_QP_CUR_STATE |
...@@ -453,6 +638,15 @@ static const struct { ...@@ -453,6 +638,15 @@ static const struct {
IB_QP_ALT_PATH | IB_QP_ALT_PATH |
IB_QP_PATH_MIG_STATE | IB_QP_PATH_MIG_STATE |
IB_QP_MIN_RNR_TIMER), IB_QP_MIN_RNR_TIMER),
[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE |
IB_QP_ACCESS_FLAGS |
IB_QP_ALT_PATH |
IB_QP_PATH_MIG_STATE),
[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE |
IB_QP_ACCESS_FLAGS |
IB_QP_ALT_PATH |
IB_QP_PATH_MIG_STATE |
IB_QP_MIN_RNR_TIMER),
[IB_QPT_SMI] = (IB_QP_CUR_STATE | [IB_QPT_SMI] = (IB_QP_CUR_STATE |
IB_QP_QKEY), IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_CUR_STATE | [IB_QPT_GSI] = (IB_QP_CUR_STATE |
...@@ -465,6 +659,8 @@ static const struct { ...@@ -465,6 +659,8 @@ static const struct {
[IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY, [IB_QPT_UD] = IB_QP_EN_SQD_ASYNC_NOTIFY,
[IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY, [IB_QPT_UC] = IB_QP_EN_SQD_ASYNC_NOTIFY,
[IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY, [IB_QPT_RC] = IB_QP_EN_SQD_ASYNC_NOTIFY,
[IB_QPT_XRC_INI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
[IB_QPT_XRC_TGT] = IB_QP_EN_SQD_ASYNC_NOTIFY, /* ??? */
[IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY, [IB_QPT_SMI] = IB_QP_EN_SQD_ASYNC_NOTIFY,
[IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY [IB_QPT_GSI] = IB_QP_EN_SQD_ASYNC_NOTIFY
} }
...@@ -487,6 +683,15 @@ static const struct { ...@@ -487,6 +683,15 @@ static const struct {
IB_QP_ACCESS_FLAGS | IB_QP_ACCESS_FLAGS |
IB_QP_MIN_RNR_TIMER | IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE), IB_QP_PATH_MIG_STATE),
[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_PATH_MIG_STATE),
[IB_QPT_XRC_TGT] = (IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
[IB_QPT_SMI] = (IB_QP_CUR_STATE | [IB_QPT_SMI] = (IB_QP_CUR_STATE |
IB_QP_QKEY), IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_CUR_STATE | [IB_QPT_GSI] = (IB_QP_CUR_STATE |
...@@ -515,6 +720,25 @@ static const struct { ...@@ -515,6 +720,25 @@ static const struct {
IB_QP_PKEY_INDEX | IB_QP_PKEY_INDEX |
IB_QP_MIN_RNR_TIMER | IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE), IB_QP_PATH_MIG_STATE),
[IB_QPT_XRC_INI] = (IB_QP_PORT |
IB_QP_AV |
IB_QP_TIMEOUT |
IB_QP_RETRY_CNT |
IB_QP_RNR_RETRY |
IB_QP_MAX_QP_RD_ATOMIC |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX |
IB_QP_PATH_MIG_STATE),
[IB_QPT_XRC_TGT] = (IB_QP_PORT |
IB_QP_AV |
IB_QP_TIMEOUT |
IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
[IB_QPT_SMI] = (IB_QP_PKEY_INDEX | [IB_QPT_SMI] = (IB_QP_PKEY_INDEX |
IB_QP_QKEY), IB_QP_QKEY),
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX | [IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
...@@ -579,7 +803,7 @@ int ib_modify_qp(struct ib_qp *qp, ...@@ -579,7 +803,7 @@ int ib_modify_qp(struct ib_qp *qp,
struct ib_qp_attr *qp_attr, struct ib_qp_attr *qp_attr,
int qp_attr_mask) int qp_attr_mask)
{ {
return qp->device->modify_qp(qp, qp_attr, qp_attr_mask, NULL); return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
} }
EXPORT_SYMBOL(ib_modify_qp); EXPORT_SYMBOL(ib_modify_qp);
...@@ -589,11 +813,59 @@ int ib_query_qp(struct ib_qp *qp, ...@@ -589,11 +813,59 @@ int ib_query_qp(struct ib_qp *qp,
struct ib_qp_init_attr *qp_init_attr) struct ib_qp_init_attr *qp_init_attr)
{ {
return qp->device->query_qp ? return qp->device->query_qp ?
qp->device->query_qp(qp, qp_attr, qp_attr_mask, qp_init_attr) : qp->device->query_qp(qp->real_qp, qp_attr, qp_attr_mask, qp_init_attr) :
-ENOSYS; -ENOSYS;
} }
EXPORT_SYMBOL(ib_query_qp); EXPORT_SYMBOL(ib_query_qp);
int ib_close_qp(struct ib_qp *qp)
{
struct ib_qp *real_qp;
unsigned long flags;
real_qp = qp->real_qp;
if (real_qp == qp)
return -EINVAL;
spin_lock_irqsave(&real_qp->device->event_handler_lock, flags);
list_del(&qp->open_list);
spin_unlock_irqrestore(&real_qp->device->event_handler_lock, flags);
atomic_dec(&real_qp->usecnt);
kfree(qp);
return 0;
}
EXPORT_SYMBOL(ib_close_qp);
static int __ib_destroy_shared_qp(struct ib_qp *qp)
{
struct ib_xrcd *xrcd;
struct ib_qp *real_qp;
int ret;
real_qp = qp->real_qp;
xrcd = real_qp->xrcd;
mutex_lock(&xrcd->tgt_qp_mutex);
ib_close_qp(qp);
if (atomic_read(&real_qp->usecnt) == 0)
list_del(&real_qp->xrcd_list);
else
real_qp = NULL;
mutex_unlock(&xrcd->tgt_qp_mutex);
if (real_qp) {
ret = ib_destroy_qp(real_qp);
if (!ret)
atomic_dec(&xrcd->usecnt);
else
__ib_insert_xrcd_qp(xrcd, real_qp);
}
return 0;
}
int ib_destroy_qp(struct ib_qp *qp) int ib_destroy_qp(struct ib_qp *qp)
{ {
struct ib_pd *pd; struct ib_pd *pd;
...@@ -601,16 +873,25 @@ int ib_destroy_qp(struct ib_qp *qp) ...@@ -601,16 +873,25 @@ int ib_destroy_qp(struct ib_qp *qp)
struct ib_srq *srq; struct ib_srq *srq;
int ret; int ret;
pd = qp->pd; if (atomic_read(&qp->usecnt))
scq = qp->send_cq; return -EBUSY;
rcq = qp->recv_cq;
srq = qp->srq; if (qp->real_qp != qp)
return __ib_destroy_shared_qp(qp);
pd = qp->pd;
scq = qp->send_cq;
rcq = qp->recv_cq;
srq = qp->srq;
ret = qp->device->destroy_qp(qp); ret = qp->device->destroy_qp(qp);
if (!ret) { if (!ret) {
atomic_dec(&pd->usecnt); if (pd)
atomic_dec(&scq->usecnt); atomic_dec(&pd->usecnt);
atomic_dec(&rcq->usecnt); if (scq)
atomic_dec(&scq->usecnt);
if (rcq)
atomic_dec(&rcq->usecnt);
if (srq) if (srq)
atomic_dec(&srq->usecnt); atomic_dec(&srq->usecnt);
} }
...@@ -920,3 +1201,42 @@ int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid) ...@@ -920,3 +1201,42 @@ int ib_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid)
return qp->device->detach_mcast(qp, gid, lid); return qp->device->detach_mcast(qp, gid, lid);
} }
EXPORT_SYMBOL(ib_detach_mcast); EXPORT_SYMBOL(ib_detach_mcast);
struct ib_xrcd *ib_alloc_xrcd(struct ib_device *device)
{
struct ib_xrcd *xrcd;
if (!device->alloc_xrcd)
return ERR_PTR(-ENOSYS);
xrcd = device->alloc_xrcd(device, NULL, NULL);
if (!IS_ERR(xrcd)) {
xrcd->device = device;
xrcd->inode = NULL;
atomic_set(&xrcd->usecnt, 0);
mutex_init(&xrcd->tgt_qp_mutex);
INIT_LIST_HEAD(&xrcd->tgt_qp_list);
}
return xrcd;
}
EXPORT_SYMBOL(ib_alloc_xrcd);
int ib_dealloc_xrcd(struct ib_xrcd *xrcd)
{
struct ib_qp *qp;
int ret;
if (atomic_read(&xrcd->usecnt))
return -EBUSY;
while (!list_empty(&xrcd->tgt_qp_list)) {
qp = list_entry(xrcd->tgt_qp_list.next, struct ib_qp, xrcd_list);
ret = ib_destroy_qp(qp);
if (ret)
return ret;
}
return xrcd->device->dealloc_xrcd(xrcd);
}
EXPORT_SYMBOL(ib_dealloc_xrcd);
...@@ -288,6 +288,11 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index) ...@@ -288,6 +288,11 @@ void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)
cm_event.private_data_len = cm_event.private_data_len =
be32_to_cpu(req->private_data_length); be32_to_cpu(req->private_data_length);
cm_event.private_data = req->private_data; cm_event.private_data = req->private_data;
/*
* Until ird/ord negotiation via MPAv2 support is added, send
* max supported values
*/
cm_event.ird = cm_event.ord = 128;
if (cm_id->event_handler) if (cm_id->event_handler)
cm_id->event_handler(cm_id, &cm_event); cm_id->event_handler(cm_id, &cm_event);
......
...@@ -183,6 +183,11 @@ static void handle_vq(struct c2_dev *c2dev, u32 mq_index) ...@@ -183,6 +183,11 @@ static void handle_vq(struct c2_dev *c2dev, u32 mq_index)
case IW_CM_EVENT_ESTABLISHED: case IW_CM_EVENT_ESTABLISHED:
c2_set_qp_state(req->qp, c2_set_qp_state(req->qp,
C2_QP_STATE_RTS); C2_QP_STATE_RTS);
/*
* Until ird/ord negotiation via MPAv2 support is added, send
* max supported values
*/
cm_event.ird = cm_event.ord = 128;
case IW_CM_EVENT_CLOSE: case IW_CM_EVENT_CLOSE:
/* /*
......
...@@ -753,10 +753,7 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev) ...@@ -753,10 +753,7 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev)
memcpy_fromio(netdev->dev_addr, c2dev->kva + C2_REGS_RDMA_ENADDR, 6); memcpy_fromio(netdev->dev_addr, c2dev->kva + C2_REGS_RDMA_ENADDR, 6);
/* Print out the MAC address */ /* Print out the MAC address */
pr_debug("%s: MAC %02X:%02X:%02X:%02X:%02X:%02X\n", pr_debug("%s: MAC %pM\n", netdev->name, netdev->dev_addr);
netdev->name,
netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
#if 0 #if 0
/* Disable network packets */ /* Disable network packets */
......
...@@ -753,6 +753,11 @@ static void connect_request_upcall(struct iwch_ep *ep) ...@@ -753,6 +753,11 @@ static void connect_request_upcall(struct iwch_ep *ep)
event.private_data_len = ep->plen; event.private_data_len = ep->plen;
event.private_data = ep->mpa_pkt + sizeof(struct mpa_message); event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
event.provider_data = ep; event.provider_data = ep;
/*
* Until ird/ord negotiation via MPAv2 support is added, send max
* supported values
*/
event.ird = event.ord = 8;
if (state_read(&ep->parent_ep->com) != DEAD) { if (state_read(&ep->parent_ep->com) != DEAD) {
get_ep(&ep->com); get_ep(&ep->com);
ep->parent_ep->com.cm_id->event_handler( ep->parent_ep->com.cm_id->event_handler(
...@@ -770,6 +775,11 @@ static void established_upcall(struct iwch_ep *ep) ...@@ -770,6 +775,11 @@ static void established_upcall(struct iwch_ep *ep)
PDBG("%s ep %p\n", __func__, ep); PDBG("%s ep %p\n", __func__, ep);
memset(&event, 0, sizeof(event)); memset(&event, 0, sizeof(event));
event.event = IW_CM_EVENT_ESTABLISHED; event.event = IW_CM_EVENT_ESTABLISHED;
/*
* Until ird/ord negotiation via MPAv2 support is added, send max
* supported values
*/
event.ird = event.ord = 8;
if (ep->com.cm_id) { if (ep->com.cm_id) {
PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid); PDBG("%s ep %p tid %d\n", __func__, ep, ep->hwtid);
ep->com.cm_id->event_handler(ep->com.cm_id, &event); ep->com.cm_id->event_handler(ep->com.cm_id, &event);
......
...@@ -46,6 +46,7 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp, ...@@ -46,6 +46,7 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
struct ib_event event; struct ib_event event;
struct iwch_qp_attributes attrs; struct iwch_qp_attributes attrs;
struct iwch_qp *qhp; struct iwch_qp *qhp;
unsigned long flag;
spin_lock(&rnicp->lock); spin_lock(&rnicp->lock);
qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe)); qhp = get_qhp(rnicp, CQE_QPID(rsp_msg->cqe));
...@@ -94,7 +95,9 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp, ...@@ -94,7 +95,9 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
if (qhp->ibqp.event_handler) if (qhp->ibqp.event_handler)
(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context); (*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
if (atomic_dec_and_test(&qhp->refcnt)) if (atomic_dec_and_test(&qhp->refcnt))
wake_up(&qhp->wait); wake_up(&qhp->wait);
...@@ -107,6 +110,7 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb) ...@@ -107,6 +110,7 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
struct iwch_cq *chp; struct iwch_cq *chp;
struct iwch_qp *qhp; struct iwch_qp *qhp;
u32 cqid = RSPQ_CQID(rsp_msg); u32 cqid = RSPQ_CQID(rsp_msg);
unsigned long flag;
rnicp = (struct iwch_dev *) rdev_p->ulp; rnicp = (struct iwch_dev *) rdev_p->ulp;
spin_lock(&rnicp->lock); spin_lock(&rnicp->lock);
...@@ -170,7 +174,9 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb) ...@@ -170,7 +174,9 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
*/ */
if (qhp->ep && SQ_TYPE(rsp_msg->cqe)) if (qhp->ep && SQ_TYPE(rsp_msg->cqe))
dst_confirm(qhp->ep->dst); dst_confirm(qhp->ep->dst);
spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
break; break;
case TPT_ERR_STAG: case TPT_ERR_STAG:
......
...@@ -190,6 +190,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve ...@@ -190,6 +190,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
chp->rhp = rhp; chp->rhp = rhp;
chp->ibcq.cqe = 1 << chp->cq.size_log2; chp->ibcq.cqe = 1 << chp->cq.size_log2;
spin_lock_init(&chp->lock); spin_lock_init(&chp->lock);
spin_lock_init(&chp->comp_handler_lock);
atomic_set(&chp->refcnt, 1); atomic_set(&chp->refcnt, 1);
init_waitqueue_head(&chp->wait); init_waitqueue_head(&chp->wait);
if (insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid)) { if (insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid)) {
......
...@@ -103,6 +103,7 @@ struct iwch_cq { ...@@ -103,6 +103,7 @@ struct iwch_cq {
struct iwch_dev *rhp; struct iwch_dev *rhp;
struct t3_cq cq; struct t3_cq cq;
spinlock_t lock; spinlock_t lock;
spinlock_t comp_handler_lock;
atomic_t refcnt; atomic_t refcnt;
wait_queue_head_t wait; wait_queue_head_t wait;
u32 __user *user_rptr_addr; u32 __user *user_rptr_addr;
......
...@@ -822,8 +822,11 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp, ...@@ -822,8 +822,11 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
flushed = cxio_flush_rq(&qhp->wq, &rchp->cq, count); flushed = cxio_flush_rq(&qhp->wq, &rchp->cq, count);
spin_unlock(&qhp->lock); spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&rchp->lock, *flag); spin_unlock_irqrestore(&rchp->lock, *flag);
if (flushed) if (flushed) {
spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context); (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
}
/* locking hierarchy: cq lock first, then qp lock. */ /* locking hierarchy: cq lock first, then qp lock. */
spin_lock_irqsave(&schp->lock, *flag); spin_lock_irqsave(&schp->lock, *flag);
...@@ -833,8 +836,11 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp, ...@@ -833,8 +836,11 @@ static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
flushed = cxio_flush_sq(&qhp->wq, &schp->cq, count); flushed = cxio_flush_sq(&qhp->wq, &schp->cq, count);
spin_unlock(&qhp->lock); spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&schp->lock, *flag); spin_unlock_irqrestore(&schp->lock, *flag);
if (flushed) if (flushed) {
spin_lock_irqsave(&schp->comp_handler_lock, *flag);
(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context); (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
}
/* deref */ /* deref */
if (atomic_dec_and_test(&qhp->refcnt)) if (atomic_dec_and_test(&qhp->refcnt))
...@@ -853,11 +859,15 @@ static void flush_qp(struct iwch_qp *qhp, unsigned long *flag) ...@@ -853,11 +859,15 @@ static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
if (qhp->ibqp.uobject) { if (qhp->ibqp.uobject) {
cxio_set_wq_in_error(&qhp->wq); cxio_set_wq_in_error(&qhp->wq);
cxio_set_cq_in_error(&rchp->cq); cxio_set_cq_in_error(&rchp->cq);
spin_lock_irqsave(&rchp->comp_handler_lock, *flag);
(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context); (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
spin_unlock_irqrestore(&rchp->comp_handler_lock, *flag);
if (schp != rchp) { if (schp != rchp) {
cxio_set_cq_in_error(&schp->cq); cxio_set_cq_in_error(&schp->cq);
spin_lock_irqsave(&schp->comp_handler_lock, *flag);
(*schp->ibcq.comp_handler)(&schp->ibcq, (*schp->ibcq.comp_handler)(&schp->ibcq,
schp->ibcq.cq_context); schp->ibcq.cq_context);
spin_unlock_irqrestore(&schp->comp_handler_lock, *flag);
} }
return; return;
} }
......
此差异已折叠。
...@@ -185,7 +185,7 @@ static void insert_recv_cqe(struct t4_wq *wq, struct t4_cq *cq) ...@@ -185,7 +185,7 @@ static void insert_recv_cqe(struct t4_wq *wq, struct t4_cq *cq)
V_CQE_OPCODE(FW_RI_SEND) | V_CQE_OPCODE(FW_RI_SEND) |
V_CQE_TYPE(0) | V_CQE_TYPE(0) |
V_CQE_SWCQE(1) | V_CQE_SWCQE(1) |
V_CQE_QPID(wq->rq.qid)); V_CQE_QPID(wq->sq.qid));
cqe.bits_type_ts = cpu_to_be64(V_CQE_GENBIT((u64)cq->gen)); cqe.bits_type_ts = cpu_to_be64(V_CQE_GENBIT((u64)cq->gen));
cq->sw_queue[cq->sw_pidx] = cqe; cq->sw_queue[cq->sw_pidx] = cqe;
t4_swcq_produce(cq); t4_swcq_produce(cq);
...@@ -818,6 +818,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries, ...@@ -818,6 +818,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
chp->cq.size--; /* status page */ chp->cq.size--; /* status page */
chp->ibcq.cqe = entries - 2; chp->ibcq.cqe = entries - 2;
spin_lock_init(&chp->lock); spin_lock_init(&chp->lock);
spin_lock_init(&chp->comp_handler_lock);
atomic_set(&chp->refcnt, 1); atomic_set(&chp->refcnt, 1);
init_waitqueue_head(&chp->wait); init_waitqueue_head(&chp->wait);
ret = insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid); ret = insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid);
......
...@@ -376,10 +376,8 @@ struct uld_ctx { ...@@ -376,10 +376,8 @@ struct uld_ctx {
struct c4iw_dev *dev; struct c4iw_dev *dev;
}; };
static void c4iw_remove(struct uld_ctx *ctx) static void c4iw_dealloc(struct uld_ctx *ctx)
{ {
PDBG("%s c4iw_dev %p\n", __func__, ctx->dev);
c4iw_unregister_device(ctx->dev);
c4iw_rdev_close(&ctx->dev->rdev); c4iw_rdev_close(&ctx->dev->rdev);
idr_destroy(&ctx->dev->cqidr); idr_destroy(&ctx->dev->cqidr);
idr_destroy(&ctx->dev->qpidr); idr_destroy(&ctx->dev->qpidr);
...@@ -389,11 +387,30 @@ static void c4iw_remove(struct uld_ctx *ctx) ...@@ -389,11 +387,30 @@ static void c4iw_remove(struct uld_ctx *ctx)
ctx->dev = NULL; ctx->dev = NULL;
} }
static void c4iw_remove(struct uld_ctx *ctx)
{
PDBG("%s c4iw_dev %p\n", __func__, ctx->dev);
c4iw_unregister_device(ctx->dev);
c4iw_dealloc(ctx);
}
static int rdma_supported(const struct cxgb4_lld_info *infop)
{
return infop->vr->stag.size > 0 && infop->vr->pbl.size > 0 &&
infop->vr->rq.size > 0 && infop->vr->qp.size > 0 &&
infop->vr->cq.size > 0 && infop->vr->ocq.size > 0;
}
static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop) static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
{ {
struct c4iw_dev *devp; struct c4iw_dev *devp;
int ret; int ret;
if (!rdma_supported(infop)) {
printk(KERN_INFO MOD "%s: RDMA not supported on this device.\n",
pci_name(infop->pdev));
return ERR_PTR(-ENOSYS);
}
devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp)); devp = (struct c4iw_dev *)ib_alloc_device(sizeof(*devp));
if (!devp) { if (!devp) {
printk(KERN_ERR MOD "Cannot allocate ib device\n"); printk(KERN_ERR MOD "Cannot allocate ib device\n");
...@@ -414,7 +431,6 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop) ...@@ -414,7 +431,6 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
ret = c4iw_rdev_open(&devp->rdev); ret = c4iw_rdev_open(&devp->rdev);
if (ret) { if (ret) {
mutex_unlock(&dev_mutex);
printk(KERN_ERR MOD "Unable to open CXIO rdev err %d\n", ret); printk(KERN_ERR MOD "Unable to open CXIO rdev err %d\n", ret);
ib_dealloc_device(&devp->ibdev); ib_dealloc_device(&devp->ibdev);
return ERR_PTR(ret); return ERR_PTR(ret);
...@@ -519,15 +535,24 @@ static int c4iw_uld_state_change(void *handle, enum cxgb4_state new_state) ...@@ -519,15 +535,24 @@ static int c4iw_uld_state_change(void *handle, enum cxgb4_state new_state)
case CXGB4_STATE_UP: case CXGB4_STATE_UP:
printk(KERN_INFO MOD "%s: Up\n", pci_name(ctx->lldi.pdev)); printk(KERN_INFO MOD "%s: Up\n", pci_name(ctx->lldi.pdev));
if (!ctx->dev) { if (!ctx->dev) {
int ret = 0; int ret;
ctx->dev = c4iw_alloc(&ctx->lldi); ctx->dev = c4iw_alloc(&ctx->lldi);
if (!IS_ERR(ctx->dev)) if (IS_ERR(ctx->dev)) {
ret = c4iw_register_device(ctx->dev); printk(KERN_ERR MOD
if (IS_ERR(ctx->dev) || ret) "%s: initialization failed: %ld\n",
pci_name(ctx->lldi.pdev),
PTR_ERR(ctx->dev));
ctx->dev = NULL;
break;
}
ret = c4iw_register_device(ctx->dev);
if (ret) {
printk(KERN_ERR MOD printk(KERN_ERR MOD
"%s: RDMA registration failed: %d\n", "%s: RDMA registration failed: %d\n",
pci_name(ctx->lldi.pdev), ret); pci_name(ctx->lldi.pdev), ret);
c4iw_dealloc(ctx);
}
} }
break; break;
case CXGB4_STATE_DOWN: case CXGB4_STATE_DOWN:
......
...@@ -42,6 +42,7 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp, ...@@ -42,6 +42,7 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
{ {
struct ib_event event; struct ib_event event;
struct c4iw_qp_attributes attrs; struct c4iw_qp_attributes attrs;
unsigned long flag;
if ((qhp->attr.state == C4IW_QP_STATE_ERROR) || if ((qhp->attr.state == C4IW_QP_STATE_ERROR) ||
(qhp->attr.state == C4IW_QP_STATE_TERMINATE)) { (qhp->attr.state == C4IW_QP_STATE_TERMINATE)) {
...@@ -72,7 +73,9 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp, ...@@ -72,7 +73,9 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
if (qhp->ibqp.event_handler) if (qhp->ibqp.event_handler)
(*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context); (*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
} }
void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe) void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
...@@ -183,11 +186,14 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe) ...@@ -183,11 +186,14 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid) int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
{ {
struct c4iw_cq *chp; struct c4iw_cq *chp;
unsigned long flag;
chp = get_chp(dev, qid); chp = get_chp(dev, qid);
if (chp) if (chp) {
spin_lock_irqsave(&chp->comp_handler_lock, flag);
(*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
else spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
} else
PDBG("%s unknown cqid 0x%x\n", __func__, qid); PDBG("%s unknown cqid 0x%x\n", __func__, qid);
return 0; return 0;
} }
...@@ -309,6 +309,7 @@ struct c4iw_cq { ...@@ -309,6 +309,7 @@ struct c4iw_cq {
struct c4iw_dev *rhp; struct c4iw_dev *rhp;
struct t4_cq cq; struct t4_cq cq;
spinlock_t lock; spinlock_t lock;
spinlock_t comp_handler_lock;
atomic_t refcnt; atomic_t refcnt;
wait_queue_head_t wait; wait_queue_head_t wait;
}; };
...@@ -323,6 +324,7 @@ struct c4iw_mpa_attributes { ...@@ -323,6 +324,7 @@ struct c4iw_mpa_attributes {
u8 recv_marker_enabled; u8 recv_marker_enabled;
u8 xmit_marker_enabled; u8 xmit_marker_enabled;
u8 crc_enabled; u8 crc_enabled;
u8 enhanced_rdma_conn;
u8 version; u8 version;
u8 p2p_type; u8 p2p_type;
}; };
...@@ -349,6 +351,8 @@ struct c4iw_qp_attributes { ...@@ -349,6 +351,8 @@ struct c4iw_qp_attributes {
u8 is_terminate_local; u8 is_terminate_local;
struct c4iw_mpa_attributes mpa_attr; struct c4iw_mpa_attributes mpa_attr;
struct c4iw_ep *llp_stream_handle; struct c4iw_ep *llp_stream_handle;
u8 layer_etype;
u8 ecode;
}; };
struct c4iw_qp { struct c4iw_qp {
...@@ -501,11 +505,18 @@ enum c4iw_mmid_state { ...@@ -501,11 +505,18 @@ enum c4iw_mmid_state {
#define MPA_KEY_REP "MPA ID Rep Frame" #define MPA_KEY_REP "MPA ID Rep Frame"
#define MPA_MAX_PRIVATE_DATA 256 #define MPA_MAX_PRIVATE_DATA 256
#define MPA_ENHANCED_RDMA_CONN 0x10
#define MPA_REJECT 0x20 #define MPA_REJECT 0x20
#define MPA_CRC 0x40 #define MPA_CRC 0x40
#define MPA_MARKERS 0x80 #define MPA_MARKERS 0x80
#define MPA_FLAGS_MASK 0xE0 #define MPA_FLAGS_MASK 0xE0
#define MPA_V2_PEER2PEER_MODEL 0x8000
#define MPA_V2_ZERO_LEN_FPDU_RTR 0x4000
#define MPA_V2_RDMA_WRITE_RTR 0x8000
#define MPA_V2_RDMA_READ_RTR 0x4000
#define MPA_V2_IRD_ORD_MASK 0x3FFF
#define c4iw_put_ep(ep) { \ #define c4iw_put_ep(ep) { \
PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__, \ PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__, \
ep, atomic_read(&((ep)->kref.refcount))); \ ep, atomic_read(&((ep)->kref.refcount))); \
...@@ -528,6 +539,11 @@ struct mpa_message { ...@@ -528,6 +539,11 @@ struct mpa_message {
u8 private_data[0]; u8 private_data[0];
}; };
struct mpa_v2_conn_params {
__be16 ird;
__be16 ord;
};
struct terminate_message { struct terminate_message {
u8 layer_etype; u8 layer_etype;
u8 ecode; u8 ecode;
...@@ -580,7 +596,10 @@ enum c4iw_ddp_ecodes { ...@@ -580,7 +596,10 @@ enum c4iw_ddp_ecodes {
enum c4iw_mpa_ecodes { enum c4iw_mpa_ecodes {
MPA_CRC_ERR = 0x02, MPA_CRC_ERR = 0x02,
MPA_MARKER_ERR = 0x03 MPA_MARKER_ERR = 0x03,
MPA_LOCAL_CATA = 0x05,
MPA_INSUFF_IRD = 0x06,
MPA_NOMATCH_RTR = 0x07,
}; };
enum c4iw_ep_state { enum c4iw_ep_state {
...@@ -651,6 +670,8 @@ struct c4iw_ep { ...@@ -651,6 +670,8 @@ struct c4iw_ep {
u16 txq_idx; u16 txq_idx;
u16 ctrlq_idx; u16 ctrlq_idx;
u8 tos; u8 tos;
u8 retry_with_mpa_v1;
u8 tried_with_mpa_v1;
}; };
static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id) static inline struct c4iw_ep *to_ep(struct iw_cm_id *cm_id)
......
...@@ -917,7 +917,11 @@ static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe, ...@@ -917,7 +917,11 @@ static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe,
wqe->u.terminate.type = FW_RI_TYPE_TERMINATE; wqe->u.terminate.type = FW_RI_TYPE_TERMINATE;
wqe->u.terminate.immdlen = cpu_to_be32(sizeof *term); wqe->u.terminate.immdlen = cpu_to_be32(sizeof *term);
term = (struct terminate_message *)wqe->u.terminate.termmsg; term = (struct terminate_message *)wqe->u.terminate.termmsg;
build_term_codes(err_cqe, &term->layer_etype, &term->ecode); if (qhp->attr.layer_etype == (LAYER_MPA|DDP_LLP)) {
term->layer_etype = qhp->attr.layer_etype;
term->ecode = qhp->attr.ecode;
} else
build_term_codes(err_cqe, &term->layer_etype, &term->ecode);
c4iw_ofld_send(&qhp->rhp->rdev, skb); c4iw_ofld_send(&qhp->rhp->rdev, skb);
} }
...@@ -941,8 +945,11 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp, ...@@ -941,8 +945,11 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count); flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
spin_unlock(&qhp->lock); spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&rchp->lock, flag); spin_unlock_irqrestore(&rchp->lock, flag);
if (flushed) if (flushed) {
spin_lock_irqsave(&rchp->comp_handler_lock, flag);
(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context); (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
}
/* locking hierarchy: cq lock first, then qp lock. */ /* locking hierarchy: cq lock first, then qp lock. */
spin_lock_irqsave(&schp->lock, flag); spin_lock_irqsave(&schp->lock, flag);
...@@ -952,13 +959,17 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp, ...@@ -952,13 +959,17 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count); flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count);
spin_unlock(&qhp->lock); spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&schp->lock, flag); spin_unlock_irqrestore(&schp->lock, flag);
if (flushed) if (flushed) {
spin_lock_irqsave(&schp->comp_handler_lock, flag);
(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context); (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
}
} }
static void flush_qp(struct c4iw_qp *qhp) static void flush_qp(struct c4iw_qp *qhp)
{ {
struct c4iw_cq *rchp, *schp; struct c4iw_cq *rchp, *schp;
unsigned long flag;
rchp = get_chp(qhp->rhp, qhp->attr.rcq); rchp = get_chp(qhp->rhp, qhp->attr.rcq);
schp = get_chp(qhp->rhp, qhp->attr.scq); schp = get_chp(qhp->rhp, qhp->attr.scq);
...@@ -966,8 +977,16 @@ static void flush_qp(struct c4iw_qp *qhp) ...@@ -966,8 +977,16 @@ static void flush_qp(struct c4iw_qp *qhp)
if (qhp->ibqp.uobject) { if (qhp->ibqp.uobject) {
t4_set_wq_in_error(&qhp->wq); t4_set_wq_in_error(&qhp->wq);
t4_set_cq_in_error(&rchp->cq); t4_set_cq_in_error(&rchp->cq);
if (schp != rchp) spin_lock_irqsave(&rchp->comp_handler_lock, flag);
(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
if (schp != rchp) {
t4_set_cq_in_error(&schp->cq); t4_set_cq_in_error(&schp->cq);
spin_lock_irqsave(&schp->comp_handler_lock, flag);
(*schp->ibcq.comp_handler)(&schp->ibcq,
schp->ibcq.cq_context);
spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
}
return; return;
} }
__flush_qp(qhp, rchp, schp); __flush_qp(qhp, rchp, schp);
...@@ -1012,6 +1031,7 @@ static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp, ...@@ -1012,6 +1031,7 @@ static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
static void build_rtr_msg(u8 p2p_type, struct fw_ri_init *init) static void build_rtr_msg(u8 p2p_type, struct fw_ri_init *init)
{ {
PDBG("%s p2p_type = %d\n", __func__, p2p_type);
memset(&init->u, 0, sizeof init->u); memset(&init->u, 0, sizeof init->u);
switch (p2p_type) { switch (p2p_type) {
case FW_RI_INIT_P2PTYPE_RDMA_WRITE: case FW_RI_INIT_P2PTYPE_RDMA_WRITE:
...@@ -1206,12 +1226,16 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, ...@@ -1206,12 +1226,16 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
disconnect = 1; disconnect = 1;
c4iw_get_ep(&qhp->ep->com); c4iw_get_ep(&qhp->ep->com);
} }
if (qhp->ibqp.uobject)
t4_set_wq_in_error(&qhp->wq);
ret = rdma_fini(rhp, qhp, ep); ret = rdma_fini(rhp, qhp, ep);
if (ret) if (ret)
goto err; goto err;
break; break;
case C4IW_QP_STATE_TERMINATE: case C4IW_QP_STATE_TERMINATE:
set_state(qhp, C4IW_QP_STATE_TERMINATE); set_state(qhp, C4IW_QP_STATE_TERMINATE);
qhp->attr.layer_etype = attrs->layer_etype;
qhp->attr.ecode = attrs->ecode;
if (qhp->ibqp.uobject) if (qhp->ibqp.uobject)
t4_set_wq_in_error(&qhp->wq); t4_set_wq_in_error(&qhp->wq);
ep = qhp->ep; ep = qhp->ep;
...@@ -1222,6 +1246,8 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, ...@@ -1222,6 +1246,8 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
break; break;
case C4IW_QP_STATE_ERROR: case C4IW_QP_STATE_ERROR:
set_state(qhp, C4IW_QP_STATE_ERROR); set_state(qhp, C4IW_QP_STATE_ERROR);
if (qhp->ibqp.uobject)
t4_set_wq_in_error(&qhp->wq);
if (!internal) { if (!internal) {
abort = 1; abort = 1;
disconnect = 1; disconnect = 1;
...@@ -1334,7 +1360,10 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp) ...@@ -1334,7 +1360,10 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
rhp = qhp->rhp; rhp = qhp->rhp;
attrs.next_state = C4IW_QP_STATE_ERROR; attrs.next_state = C4IW_QP_STATE_ERROR;
c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0); if (qhp->attr.state == C4IW_QP_STATE_TERMINATE)
c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
else
c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
wait_event(qhp->wait, !qhp->ep); wait_event(qhp->wait, !qhp->ep);
remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid); remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid);
......
...@@ -125,7 +125,7 @@ int ehca_create_eq(struct ehca_shca *shca, ...@@ -125,7 +125,7 @@ int ehca_create_eq(struct ehca_shca *shca,
tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca); tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq, ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,
IRQF_DISABLED, "ehca_eq", 0, "ehca_eq",
(void *)shca); (void *)shca);
if (ret < 0) if (ret < 0)
ehca_err(ib_dev, "Can't map interrupt handler."); ehca_err(ib_dev, "Can't map interrupt handler.");
...@@ -133,7 +133,7 @@ int ehca_create_eq(struct ehca_shca *shca, ...@@ -133,7 +133,7 @@ int ehca_create_eq(struct ehca_shca *shca,
tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca); tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca);
ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq, ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,
IRQF_DISABLED, "ehca_neq", 0, "ehca_neq",
(void *)shca); (void *)shca);
if (ret < 0) if (ret < 0)
ehca_err(ib_dev, "Can't map interrupt handler."); ehca_err(ib_dev, "Can't map interrupt handler.");
......
...@@ -977,6 +977,9 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd, ...@@ -977,6 +977,9 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
struct hcp_modify_qp_control_block *mqpcb; struct hcp_modify_qp_control_block *mqpcb;
u64 hret, update_mask; u64 hret, update_mask;
if (srq_init_attr->srq_type != IB_SRQT_BASIC)
return ERR_PTR(-ENOSYS);
/* For common attributes, internal_create_qp() takes its info /* For common attributes, internal_create_qp() takes its info
* out of qp_init_attr, so copy all common attrs there. * out of qp_init_attr, so copy all common attrs there.
*/ */
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/stat.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include "ipath_kernel.h" #include "ipath_kernel.h"
......
...@@ -107,6 +107,11 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd, ...@@ -107,6 +107,11 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
u32 sz; u32 sz;
struct ib_srq *ret; struct ib_srq *ret;
if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
ret = ERR_PTR(-ENOSYS);
goto done;
}
if (srq_init_attr->attr.max_wr == 0) { if (srq_init_attr->attr.max_wr == 0) {
ret = ERR_PTR(-EINVAL); ret = ERR_PTR(-EINVAL);
goto done; goto done;
......
...@@ -128,6 +128,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, ...@@ -128,6 +128,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
(dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) && (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) &&
(dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR)) (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR))
props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS; props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)
props->device_cap_flags |= IB_DEVICE_XRC;
props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) & props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
0xffffff; 0xffffff;
...@@ -181,8 +183,12 @@ mlx4_ib_port_link_layer(struct ib_device *device, u8 port_num) ...@@ -181,8 +183,12 @@ mlx4_ib_port_link_layer(struct ib_device *device, u8 port_num)
static int ib_link_query_port(struct ib_device *ibdev, u8 port, static int ib_link_query_port(struct ib_device *ibdev, u8 port,
struct ib_port_attr *props, struct ib_port_attr *props,
struct ib_smp *in_mad,
struct ib_smp *out_mad) struct ib_smp *out_mad)
{ {
int ext_active_speed;
int err;
props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16)); props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16));
props->lmc = out_mad->data[34] & 0x7; props->lmc = out_mad->data[34] & 0x7;
props->sm_lid = be16_to_cpup((__be16 *) (out_mad->data + 18)); props->sm_lid = be16_to_cpup((__be16 *) (out_mad->data + 18));
...@@ -203,6 +209,39 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port, ...@@ -203,6 +209,39 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port,
props->max_vl_num = out_mad->data[37] >> 4; props->max_vl_num = out_mad->data[37] >> 4;
props->init_type_reply = out_mad->data[41] >> 4; props->init_type_reply = out_mad->data[41] >> 4;
/* Check if extended speeds (EDR/FDR/...) are supported */
if (props->port_cap_flags & IB_PORT_EXTENDED_SPEEDS_SUP) {
ext_active_speed = out_mad->data[62] >> 4;
switch (ext_active_speed) {
case 1:
props->active_speed = 16; /* FDR */
break;
case 2:
props->active_speed = 32; /* EDR */
break;
}
}
/* If reported active speed is QDR, check if is FDR-10 */
if (props->active_speed == 4) {
if (to_mdev(ibdev)->dev->caps.ext_port_cap[port] &
MLX_EXT_PORT_CAP_FLAG_EXTENDED_PORT_INFO) {
init_query_mad(in_mad);
in_mad->attr_id = MLX4_ATTR_EXTENDED_PORT_INFO;
in_mad->attr_mod = cpu_to_be32(port);
err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port,
NULL, NULL, in_mad, out_mad);
if (err)
return err;
/* Checking LinkSpeedActive for FDR-10 */
if (out_mad->data[15] & 0x1)
props->active_speed = 8;
}
}
return 0; return 0;
} }
...@@ -227,7 +266,7 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port, ...@@ -227,7 +266,7 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port,
props->pkey_tbl_len = 1; props->pkey_tbl_len = 1;
props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46)); props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46));
props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48)); props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48));
props->max_mtu = IB_MTU_2048; props->max_mtu = IB_MTU_4096;
props->subnet_timeout = 0; props->subnet_timeout = 0;
props->max_vl_num = out_mad->data[37] >> 4; props->max_vl_num = out_mad->data[37] >> 4;
props->init_type_reply = 0; props->init_type_reply = 0;
...@@ -274,7 +313,7 @@ static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port, ...@@ -274,7 +313,7 @@ static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
goto out; goto out;
err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ? err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ?
ib_link_query_port(ibdev, port, props, out_mad) : ib_link_query_port(ibdev, port, props, in_mad, out_mad) :
eth_link_query_port(ibdev, port, props, out_mad); eth_link_query_port(ibdev, port, props, out_mad);
out: out:
...@@ -566,6 +605,57 @@ static int mlx4_ib_dealloc_pd(struct ib_pd *pd) ...@@ -566,6 +605,57 @@ static int mlx4_ib_dealloc_pd(struct ib_pd *pd)
return 0; return 0;
} }
static struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev,
struct ib_ucontext *context,
struct ib_udata *udata)
{
struct mlx4_ib_xrcd *xrcd;
int err;
if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
return ERR_PTR(-ENOSYS);
xrcd = kmalloc(sizeof *xrcd, GFP_KERNEL);
if (!xrcd)
return ERR_PTR(-ENOMEM);
err = mlx4_xrcd_alloc(to_mdev(ibdev)->dev, &xrcd->xrcdn);
if (err)
goto err1;
xrcd->pd = ib_alloc_pd(ibdev);
if (IS_ERR(xrcd->pd)) {
err = PTR_ERR(xrcd->pd);
goto err2;
}
xrcd->cq = ib_create_cq(ibdev, NULL, NULL, xrcd, 1, 0);
if (IS_ERR(xrcd->cq)) {
err = PTR_ERR(xrcd->cq);
goto err3;
}
return &xrcd->ibxrcd;
err3:
ib_dealloc_pd(xrcd->pd);
err2:
mlx4_xrcd_free(to_mdev(ibdev)->dev, xrcd->xrcdn);
err1:
kfree(xrcd);
return ERR_PTR(err);
}
static int mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
{
ib_destroy_cq(to_mxrcd(xrcd)->cq);
ib_dealloc_pd(to_mxrcd(xrcd)->pd);
mlx4_xrcd_free(to_mdev(xrcd->device)->dev, to_mxrcd(xrcd)->xrcdn);
kfree(xrcd);
return 0;
}
static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid) static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid)
{ {
struct mlx4_ib_qp *mqp = to_mqp(ibqp); struct mlx4_ib_qp *mqp = to_mqp(ibqp);
...@@ -1044,7 +1134,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) ...@@ -1044,7 +1134,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
(1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
(1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ); (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) |
(1ull << IB_USER_VERBS_CMD_CREATE_XSRQ) |
(1ull << IB_USER_VERBS_CMD_OPEN_QP);
ibdev->ib_dev.query_device = mlx4_ib_query_device; ibdev->ib_dev.query_device = mlx4_ib_query_device;
ibdev->ib_dev.query_port = mlx4_ib_query_port; ibdev->ib_dev.query_port = mlx4_ib_query_port;
...@@ -1093,6 +1185,14 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) ...@@ -1093,6 +1185,14 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr; ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr;
ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc; ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc;
if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) {
ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd;
ibdev->ib_dev.dealloc_xrcd = mlx4_ib_dealloc_xrcd;
ibdev->ib_dev.uverbs_cmd_mask |=
(1ull << IB_USER_VERBS_CMD_OPEN_XRCD) |
(1ull << IB_USER_VERBS_CMD_CLOSE_XRCD);
}
spin_lock_init(&iboe->lock); spin_lock_init(&iboe->lock);
if (init_node_data(ibdev)) if (init_node_data(ibdev))
......
...@@ -56,6 +56,13 @@ struct mlx4_ib_pd { ...@@ -56,6 +56,13 @@ struct mlx4_ib_pd {
u32 pdn; u32 pdn;
}; };
struct mlx4_ib_xrcd {
struct ib_xrcd ibxrcd;
u32 xrcdn;
struct ib_pd *pd;
struct ib_cq *cq;
};
struct mlx4_ib_cq_buf { struct mlx4_ib_cq_buf {
struct mlx4_buf buf; struct mlx4_buf buf;
struct mlx4_mtt mtt; struct mlx4_mtt mtt;
...@@ -138,6 +145,7 @@ struct mlx4_ib_qp { ...@@ -138,6 +145,7 @@ struct mlx4_ib_qp {
struct mlx4_mtt mtt; struct mlx4_mtt mtt;
int buf_size; int buf_size;
struct mutex mutex; struct mutex mutex;
u16 xrcdn;
u32 flags; u32 flags;
u8 port; u8 port;
u8 alt_port; u8 alt_port;
...@@ -211,6 +219,11 @@ static inline struct mlx4_ib_pd *to_mpd(struct ib_pd *ibpd) ...@@ -211,6 +219,11 @@ static inline struct mlx4_ib_pd *to_mpd(struct ib_pd *ibpd)
return container_of(ibpd, struct mlx4_ib_pd, ibpd); return container_of(ibpd, struct mlx4_ib_pd, ibpd);
} }
static inline struct mlx4_ib_xrcd *to_mxrcd(struct ib_xrcd *ibxrcd)
{
return container_of(ibxrcd, struct mlx4_ib_xrcd, ibxrcd);
}
static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq) static inline struct mlx4_ib_cq *to_mcq(struct ib_cq *ibcq)
{ {
return container_of(ibcq, struct mlx4_ib_cq, ibcq); return container_of(ibcq, struct mlx4_ib_cq, ibcq);
......
...@@ -302,15 +302,14 @@ static int send_wqe_overhead(enum ib_qp_type type, u32 flags) ...@@ -302,15 +302,14 @@ static int send_wqe_overhead(enum ib_qp_type type, u32 flags)
} }
static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
int is_user, int has_srq, struct mlx4_ib_qp *qp) int is_user, int has_rq, struct mlx4_ib_qp *qp)
{ {
/* Sanity check RQ size before proceeding */ /* Sanity check RQ size before proceeding */
if (cap->max_recv_wr > dev->dev->caps.max_wqes || if (cap->max_recv_wr > dev->dev->caps.max_wqes ||
cap->max_recv_sge > dev->dev->caps.max_rq_sg) cap->max_recv_sge > dev->dev->caps.max_rq_sg)
return -EINVAL; return -EINVAL;
if (has_srq) { if (!has_rq) {
/* QPs attached to an SRQ should have no RQ */
if (cap->max_recv_wr) if (cap->max_recv_wr)
return -EINVAL; return -EINVAL;
...@@ -463,6 +462,14 @@ static int set_user_sq_size(struct mlx4_ib_dev *dev, ...@@ -463,6 +462,14 @@ static int set_user_sq_size(struct mlx4_ib_dev *dev,
return 0; return 0;
} }
static int qp_has_rq(struct ib_qp_init_attr *attr)
{
if (attr->qp_type == IB_QPT_XRC_INI || attr->qp_type == IB_QPT_XRC_TGT)
return 0;
return !attr->srq;
}
static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
struct ib_qp_init_attr *init_attr, struct ib_qp_init_attr *init_attr,
struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp) struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
...@@ -479,7 +486,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, ...@@ -479,7 +486,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
qp->sq_signal_bits = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE); qp->sq_signal_bits = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE);
err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, !!init_attr->srq, qp); err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, qp_has_rq(init_attr), qp);
if (err) if (err)
goto err; goto err;
...@@ -513,7 +520,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, ...@@ -513,7 +520,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err) if (err)
goto err_mtt; goto err_mtt;
if (!init_attr->srq) { if (qp_has_rq(init_attr)) {
err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context), err = mlx4_ib_db_map_user(to_mucontext(pd->uobject->context),
ucmd.db_addr, &qp->db); ucmd.db_addr, &qp->db);
if (err) if (err)
...@@ -532,7 +539,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, ...@@ -532,7 +539,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err) if (err)
goto err; goto err;
if (!init_attr->srq) { if (qp_has_rq(init_attr)) {
err = mlx4_db_alloc(dev->dev, &qp->db, 0); err = mlx4_db_alloc(dev->dev, &qp->db, 0);
if (err) if (err)
goto err; goto err;
...@@ -575,6 +582,9 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, ...@@ -575,6 +582,9 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err) if (err)
goto err_qpn; goto err_qpn;
if (init_attr->qp_type == IB_QPT_XRC_TGT)
qp->mqp.qpn |= (1 << 23);
/* /*
* Hardware wants QPN written in big-endian order (after * Hardware wants QPN written in big-endian order (after
* shifting) for send doorbell. Precompute this value to save * shifting) for send doorbell. Precompute this value to save
...@@ -592,9 +602,8 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, ...@@ -592,9 +602,8 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
err_wrid: err_wrid:
if (pd->uobject) { if (pd->uobject) {
if (!init_attr->srq) if (qp_has_rq(init_attr))
mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db);
&qp->db);
} else { } else {
kfree(qp->sq.wrid); kfree(qp->sq.wrid);
kfree(qp->rq.wrid); kfree(qp->rq.wrid);
...@@ -610,7 +619,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, ...@@ -610,7 +619,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf); mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
err_db: err_db:
if (!pd->uobject && !init_attr->srq) if (!pd->uobject && qp_has_rq(init_attr))
mlx4_db_free(dev->dev, &qp->db); mlx4_db_free(dev->dev, &qp->db);
err: err:
...@@ -671,6 +680,33 @@ static void del_gid_entries(struct mlx4_ib_qp *qp) ...@@ -671,6 +680,33 @@ static void del_gid_entries(struct mlx4_ib_qp *qp)
} }
} }
static struct mlx4_ib_pd *get_pd(struct mlx4_ib_qp *qp)
{
if (qp->ibqp.qp_type == IB_QPT_XRC_TGT)
return to_mpd(to_mxrcd(qp->ibqp.xrcd)->pd);
else
return to_mpd(qp->ibqp.pd);
}
static void get_cqs(struct mlx4_ib_qp *qp,
struct mlx4_ib_cq **send_cq, struct mlx4_ib_cq **recv_cq)
{
switch (qp->ibqp.qp_type) {
case IB_QPT_XRC_TGT:
*send_cq = to_mcq(to_mxrcd(qp->ibqp.xrcd)->cq);
*recv_cq = *send_cq;
break;
case IB_QPT_XRC_INI:
*send_cq = to_mcq(qp->ibqp.send_cq);
*recv_cq = *send_cq;
break;
default:
*send_cq = to_mcq(qp->ibqp.send_cq);
*recv_cq = to_mcq(qp->ibqp.recv_cq);
break;
}
}
static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
int is_user) int is_user)
{ {
...@@ -682,8 +718,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, ...@@ -682,8 +718,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
printk(KERN_WARNING "mlx4_ib: modify QP %06x to RESET failed.\n", printk(KERN_WARNING "mlx4_ib: modify QP %06x to RESET failed.\n",
qp->mqp.qpn); qp->mqp.qpn);
send_cq = to_mcq(qp->ibqp.send_cq); get_cqs(qp, &send_cq, &recv_cq);
recv_cq = to_mcq(qp->ibqp.recv_cq);
mlx4_ib_lock_cqs(send_cq, recv_cq); mlx4_ib_lock_cqs(send_cq, recv_cq);
...@@ -706,7 +741,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, ...@@ -706,7 +741,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
mlx4_mtt_cleanup(dev->dev, &qp->mtt); mlx4_mtt_cleanup(dev->dev, &qp->mtt);
if (is_user) { if (is_user) {
if (!qp->ibqp.srq) if (qp->rq.wqe_cnt)
mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context), mlx4_ib_db_unmap_user(to_mucontext(qp->ibqp.uobject->context),
&qp->db); &qp->db);
ib_umem_release(qp->umem); ib_umem_release(qp->umem);
...@@ -714,7 +749,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, ...@@ -714,7 +749,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
kfree(qp->sq.wrid); kfree(qp->sq.wrid);
kfree(qp->rq.wrid); kfree(qp->rq.wrid);
mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf); mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
if (!qp->ibqp.srq) if (qp->rq.wqe_cnt)
mlx4_db_free(dev->dev, &qp->db); mlx4_db_free(dev->dev, &qp->db);
} }
...@@ -725,10 +760,10 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd, ...@@ -725,10 +760,10 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
struct ib_qp_init_attr *init_attr, struct ib_qp_init_attr *init_attr,
struct ib_udata *udata) struct ib_udata *udata)
{ {
struct mlx4_ib_dev *dev = to_mdev(pd->device);
struct mlx4_ib_sqp *sqp; struct mlx4_ib_sqp *sqp;
struct mlx4_ib_qp *qp; struct mlx4_ib_qp *qp;
int err; int err;
u16 xrcdn = 0;
/* /*
* We only support LSO and multicast loopback blocking, and * We only support LSO and multicast loopback blocking, and
...@@ -739,10 +774,20 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd, ...@@ -739,10 +774,20 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (init_attr->create_flags && if (init_attr->create_flags &&
(pd->uobject || init_attr->qp_type != IB_QPT_UD)) (udata || init_attr->qp_type != IB_QPT_UD))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
switch (init_attr->qp_type) { switch (init_attr->qp_type) {
case IB_QPT_XRC_TGT:
pd = to_mxrcd(init_attr->xrcd)->pd;
xrcdn = to_mxrcd(init_attr->xrcd)->xrcdn;
init_attr->send_cq = to_mxrcd(init_attr->xrcd)->cq;
/* fall through */
case IB_QPT_XRC_INI:
if (!(to_mdev(pd->device)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC))
return ERR_PTR(-ENOSYS);
init_attr->recv_cq = init_attr->send_cq;
/* fall through */
case IB_QPT_RC: case IB_QPT_RC:
case IB_QPT_UC: case IB_QPT_UC:
case IB_QPT_UD: case IB_QPT_UD:
...@@ -751,13 +796,14 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd, ...@@ -751,13 +796,14 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
if (!qp) if (!qp)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
err = create_qp_common(dev, pd, init_attr, udata, 0, qp); err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata, 0, qp);
if (err) { if (err) {
kfree(qp); kfree(qp);
return ERR_PTR(err); return ERR_PTR(err);
} }
qp->ibqp.qp_num = qp->mqp.qpn; qp->ibqp.qp_num = qp->mqp.qpn;
qp->xrcdn = xrcdn;
break; break;
} }
...@@ -765,7 +811,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd, ...@@ -765,7 +811,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
case IB_QPT_GSI: case IB_QPT_GSI:
{ {
/* Userspace is not allowed to create special QPs: */ /* Userspace is not allowed to create special QPs: */
if (pd->uobject) if (udata)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
sqp = kzalloc(sizeof *sqp, GFP_KERNEL); sqp = kzalloc(sizeof *sqp, GFP_KERNEL);
...@@ -774,8 +820,8 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd, ...@@ -774,8 +820,8 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
qp = &sqp->qp; qp = &sqp->qp;
err = create_qp_common(dev, pd, init_attr, udata, err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata,
dev->dev->caps.sqp_start + to_mdev(pd->device)->dev->caps.sqp_start +
(init_attr->qp_type == IB_QPT_SMI ? 0 : 2) + (init_attr->qp_type == IB_QPT_SMI ? 0 : 2) +
init_attr->port_num - 1, init_attr->port_num - 1,
qp); qp);
...@@ -801,11 +847,13 @@ int mlx4_ib_destroy_qp(struct ib_qp *qp) ...@@ -801,11 +847,13 @@ int mlx4_ib_destroy_qp(struct ib_qp *qp)
{ {
struct mlx4_ib_dev *dev = to_mdev(qp->device); struct mlx4_ib_dev *dev = to_mdev(qp->device);
struct mlx4_ib_qp *mqp = to_mqp(qp); struct mlx4_ib_qp *mqp = to_mqp(qp);
struct mlx4_ib_pd *pd;
if (is_qp0(dev, mqp)) if (is_qp0(dev, mqp))
mlx4_CLOSE_PORT(dev->dev, mqp->port); mlx4_CLOSE_PORT(dev->dev, mqp->port);
destroy_qp_common(dev, mqp, !!qp->pd->uobject); pd = get_pd(mqp);
destroy_qp_common(dev, mqp, !!pd->ibpd.uobject);
if (is_sqp(dev, mqp)) if (is_sqp(dev, mqp))
kfree(to_msqp(mqp)); kfree(to_msqp(mqp));
...@@ -821,6 +869,8 @@ static int to_mlx4_st(enum ib_qp_type type) ...@@ -821,6 +869,8 @@ static int to_mlx4_st(enum ib_qp_type type)
case IB_QPT_RC: return MLX4_QP_ST_RC; case IB_QPT_RC: return MLX4_QP_ST_RC;
case IB_QPT_UC: return MLX4_QP_ST_UC; case IB_QPT_UC: return MLX4_QP_ST_UC;
case IB_QPT_UD: return MLX4_QP_ST_UD; case IB_QPT_UD: return MLX4_QP_ST_UD;
case IB_QPT_XRC_INI:
case IB_QPT_XRC_TGT: return MLX4_QP_ST_XRC;
case IB_QPT_SMI: case IB_QPT_SMI:
case IB_QPT_GSI: return MLX4_QP_ST_MLX; case IB_QPT_GSI: return MLX4_QP_ST_MLX;
default: return -1; default: return -1;
...@@ -959,6 +1009,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, ...@@ -959,6 +1009,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
{ {
struct mlx4_ib_dev *dev = to_mdev(ibqp->device); struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
struct mlx4_ib_qp *qp = to_mqp(ibqp); struct mlx4_ib_qp *qp = to_mqp(ibqp);
struct mlx4_ib_pd *pd;
struct mlx4_ib_cq *send_cq, *recv_cq;
struct mlx4_qp_context *context; struct mlx4_qp_context *context;
enum mlx4_qp_optpar optpar = 0; enum mlx4_qp_optpar optpar = 0;
int sqd_event; int sqd_event;
...@@ -1014,8 +1066,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, ...@@ -1014,8 +1066,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3; context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
context->sq_size_stride |= qp->sq.wqe_shift - 4; context->sq_size_stride |= qp->sq.wqe_shift - 4;
if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
context->sq_size_stride |= !!qp->sq_no_prefetch << 7; context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
context->xrcd = cpu_to_be32((u32) qp->xrcdn);
}
if (qp->ibqp.uobject) if (qp->ibqp.uobject)
context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index); context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index);
...@@ -1079,8 +1133,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, ...@@ -1079,8 +1133,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH; optpar |= MLX4_QP_OPTPAR_ALT_ADDR_PATH;
} }
context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn); pd = get_pd(qp);
context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28); get_cqs(qp, &send_cq, &recv_cq);
context->pd = cpu_to_be32(pd->pdn);
context->cqn_send = cpu_to_be32(send_cq->mcq.cqn);
context->cqn_recv = cpu_to_be32(recv_cq->mcq.cqn);
context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
/* Set "fast registration enabled" for all kernel QPs */ /* Set "fast registration enabled" for all kernel QPs */
if (!qp->ibqp.uobject) if (!qp->ibqp.uobject)
...@@ -1106,8 +1164,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, ...@@ -1106,8 +1164,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (attr_mask & IB_QP_SQ_PSN) if (attr_mask & IB_QP_SQ_PSN)
context->next_send_psn = cpu_to_be32(attr->sq_psn); context->next_send_psn = cpu_to_be32(attr->sq_psn);
context->cqn_send = cpu_to_be32(to_mcq(ibqp->send_cq)->mcq.cqn);
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
if (attr->max_dest_rd_atomic) if (attr->max_dest_rd_atomic)
context->params2 |= context->params2 |=
...@@ -1130,8 +1186,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, ...@@ -1130,8 +1186,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (attr_mask & IB_QP_RQ_PSN) if (attr_mask & IB_QP_RQ_PSN)
context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn); context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
context->cqn_recv = cpu_to_be32(to_mcq(ibqp->recv_cq)->mcq.cqn);
if (attr_mask & IB_QP_QKEY) { if (attr_mask & IB_QP_QKEY) {
context->qkey = cpu_to_be32(attr->qkey); context->qkey = cpu_to_be32(attr->qkey);
optpar |= MLX4_QP_OPTPAR_Q_KEY; optpar |= MLX4_QP_OPTPAR_Q_KEY;
...@@ -1140,7 +1194,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, ...@@ -1140,7 +1194,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
if (ibqp->srq) if (ibqp->srq)
context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn); context->srqn = cpu_to_be32(1 << 24 | to_msrq(ibqp->srq)->msrq.srqn);
if (!ibqp->srq && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) if (qp->rq.wqe_cnt && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
context->db_rec_addr = cpu_to_be64(qp->db.dma); context->db_rec_addr = cpu_to_be64(qp->db.dma);
if (cur_state == IB_QPS_INIT && if (cur_state == IB_QPS_INIT &&
...@@ -1225,17 +1279,17 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, ...@@ -1225,17 +1279,17 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
* entries and reinitialize the QP. * entries and reinitialize the QP.
*/ */
if (new_state == IB_QPS_RESET && !ibqp->uobject) { if (new_state == IB_QPS_RESET && !ibqp->uobject) {
mlx4_ib_cq_clean(to_mcq(ibqp->recv_cq), qp->mqp.qpn, mlx4_ib_cq_clean(recv_cq, qp->mqp.qpn,
ibqp->srq ? to_msrq(ibqp->srq): NULL); ibqp->srq ? to_msrq(ibqp->srq): NULL);
if (ibqp->send_cq != ibqp->recv_cq) if (send_cq != recv_cq)
mlx4_ib_cq_clean(to_mcq(ibqp->send_cq), qp->mqp.qpn, NULL); mlx4_ib_cq_clean(send_cq, qp->mqp.qpn, NULL);
qp->rq.head = 0; qp->rq.head = 0;
qp->rq.tail = 0; qp->rq.tail = 0;
qp->sq.head = 0; qp->sq.head = 0;
qp->sq.tail = 0; qp->sq.tail = 0;
qp->sq_next_wqe = 0; qp->sq_next_wqe = 0;
if (!ibqp->srq) if (qp->rq.wqe_cnt)
*qp->db.db = 0; *qp->db.db = 0;
} }
...@@ -1547,14 +1601,13 @@ static void set_masked_atomic_seg(struct mlx4_wqe_masked_atomic_seg *aseg, ...@@ -1547,14 +1601,13 @@ static void set_masked_atomic_seg(struct mlx4_wqe_masked_atomic_seg *aseg,
} }
static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg, static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
struct ib_send_wr *wr, __be16 *vlan) struct ib_send_wr *wr)
{ {
memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av)); memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av));
dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn); dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn);
dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey); dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan; dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan;
memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6); memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6);
*vlan = dseg->vlan;
} }
static void set_mlx_icrc_seg(void *dseg) static void set_mlx_icrc_seg(void *dseg)
...@@ -1657,7 +1710,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, ...@@ -1657,7 +1710,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
__be32 uninitialized_var(lso_hdr_sz); __be32 uninitialized_var(lso_hdr_sz);
__be32 blh; __be32 blh;
int i; int i;
__be16 vlan = cpu_to_be16(0xffff);
spin_lock_irqsave(&qp->sq.lock, flags); spin_lock_irqsave(&qp->sq.lock, flags);
...@@ -1761,7 +1813,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, ...@@ -1761,7 +1813,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
break; break;
case IB_QPT_UD: case IB_QPT_UD:
set_datagram_seg(wqe, wr, &vlan); set_datagram_seg(wqe, wr);
wqe += sizeof (struct mlx4_wqe_datagram_seg); wqe += sizeof (struct mlx4_wqe_datagram_seg);
size += sizeof (struct mlx4_wqe_datagram_seg) / 16; size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
...@@ -1824,11 +1876,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, ...@@ -1824,11 +1876,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ? ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ?
MLX4_WQE_CTRL_FENCE : 0) | size; MLX4_WQE_CTRL_FENCE : 0) | size;
if (be16_to_cpu(vlan) < 0x1000) {
ctrl->ins_vlan = 1 << 6;
ctrl->vlan_tag = vlan;
}
/* /*
* Make sure descriptor is fully written before * Make sure descriptor is fully written before
* setting ownership bit (because HW can start * setting ownership bit (because HW can start
......
...@@ -76,6 +76,8 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd, ...@@ -76,6 +76,8 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
struct mlx4_ib_srq *srq; struct mlx4_ib_srq *srq;
struct mlx4_wqe_srq_next_seg *next; struct mlx4_wqe_srq_next_seg *next;
struct mlx4_wqe_data_seg *scatter; struct mlx4_wqe_data_seg *scatter;
u32 cqn;
u16 xrcdn;
int desc_size; int desc_size;
int buf_size; int buf_size;
int err; int err;
...@@ -174,12 +176,18 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd, ...@@ -174,12 +176,18 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
} }
} }
err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, &srq->mtt, cqn = (init_attr->srq_type == IB_SRQT_XRC) ?
to_mcq(init_attr->ext.xrc.cq)->mcq.cqn : 0;
xrcdn = (init_attr->srq_type == IB_SRQT_XRC) ?
to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn :
(u16) dev->dev->caps.reserved_xrcds;
err = mlx4_srq_alloc(dev->dev, to_mpd(pd)->pdn, cqn, xrcdn, &srq->mtt,
srq->db.dma, &srq->msrq); srq->db.dma, &srq->msrq);
if (err) if (err)
goto err_wrid; goto err_wrid;
srq->msrq.event = mlx4_ib_srq_event; srq->msrq.event = mlx4_ib_srq_event;
srq->ibsrq.ext.xrc.srq_num = srq->msrq.srqn;
if (pd->uobject) if (pd->uobject)
if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) { if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof (__u32))) {
......
...@@ -438,6 +438,9 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd, ...@@ -438,6 +438,9 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd,
struct mthca_srq *srq; struct mthca_srq *srq;
int err; int err;
if (init_attr->srq_type != IB_SRQT_BASIC)
return ERR_PTR(-ENOSYS);
srq = kmalloc(sizeof *srq, GFP_KERNEL); srq = kmalloc(sizeof *srq, GFP_KERNEL);
if (!srq) if (!srq)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
......
obj-$(CONFIG_INFINIBAND_NES) += iw_nes.o obj-$(CONFIG_INFINIBAND_NES) += iw_nes.o
iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o nes_mgt.o
...@@ -84,7 +84,7 @@ module_param(send_first, int, 0644); ...@@ -84,7 +84,7 @@ module_param(send_first, int, 0644);
MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection"); MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection");
unsigned int nes_drv_opt = 0; unsigned int nes_drv_opt = NES_DRV_OPT_DISABLE_INT_MOD | NES_DRV_OPT_ENABLE_PAU;
module_param(nes_drv_opt, int, 0644); module_param(nes_drv_opt, int, 0644);
MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters"); MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters");
...@@ -130,9 +130,6 @@ static struct notifier_block nes_net_notifier = { ...@@ -130,9 +130,6 @@ static struct notifier_block nes_net_notifier = {
.notifier_call = nes_net_event .notifier_call = nes_net_event
}; };
/** /**
* nes_inetaddr_event * nes_inetaddr_event
*/ */
...@@ -321,6 +318,9 @@ void nes_rem_ref(struct ib_qp *ibqp) ...@@ -321,6 +318,9 @@ void nes_rem_ref(struct ib_qp *ibqp)
} }
if (atomic_dec_and_test(&nesqp->refcount)) { if (atomic_dec_and_test(&nesqp->refcount)) {
if (nesqp->pau_mode)
nes_destroy_pau_qp(nesdev, nesqp);
/* Destroy the QP */ /* Destroy the QP */
cqp_request = nes_get_cqp_request(nesdev); cqp_request = nes_get_cqp_request(nesdev);
if (cqp_request == NULL) { if (cqp_request == NULL) {
......
...@@ -102,6 +102,7 @@ ...@@ -102,6 +102,7 @@
#define NES_DRV_OPT_NO_INLINE_DATA 0x00000080 #define NES_DRV_OPT_NO_INLINE_DATA 0x00000080
#define NES_DRV_OPT_DISABLE_INT_MOD 0x00000100 #define NES_DRV_OPT_DISABLE_INT_MOD 0x00000100
#define NES_DRV_OPT_DISABLE_VIRT_WQ 0x00000200 #define NES_DRV_OPT_DISABLE_VIRT_WQ 0x00000200
#define NES_DRV_OPT_ENABLE_PAU 0x00000400
#define NES_AEQ_EVENT_TIMEOUT 2500 #define NES_AEQ_EVENT_TIMEOUT 2500
#define NES_DISCONNECT_EVENT_TIMEOUT 2000 #define NES_DISCONNECT_EVENT_TIMEOUT 2000
...@@ -128,6 +129,7 @@ ...@@ -128,6 +129,7 @@
#define NES_DBG_IW_RX 0x00020000 #define NES_DBG_IW_RX 0x00020000
#define NES_DBG_IW_TX 0x00040000 #define NES_DBG_IW_TX 0x00040000
#define NES_DBG_SHUTDOWN 0x00080000 #define NES_DBG_SHUTDOWN 0x00080000
#define NES_DBG_PAU 0x00100000
#define NES_DBG_RSVD1 0x10000000 #define NES_DBG_RSVD1 0x10000000
#define NES_DBG_RSVD2 0x20000000 #define NES_DBG_RSVD2 0x20000000
#define NES_DBG_RSVD3 0x40000000 #define NES_DBG_RSVD3 0x40000000
...@@ -162,6 +164,7 @@ do { \ ...@@ -162,6 +164,7 @@ do { \
#include "nes_context.h" #include "nes_context.h"
#include "nes_user.h" #include "nes_user.h"
#include "nes_cm.h" #include "nes_cm.h"
#include "nes_mgt.h"
extern int max_mtu; extern int max_mtu;
#define max_frame_len (max_mtu+ETH_HLEN) #define max_frame_len (max_mtu+ETH_HLEN)
...@@ -202,6 +205,8 @@ extern atomic_t cm_nodes_created; ...@@ -202,6 +205,8 @@ extern atomic_t cm_nodes_created;
extern atomic_t cm_nodes_destroyed; extern atomic_t cm_nodes_destroyed;
extern atomic_t cm_accel_dropped_pkts; extern atomic_t cm_accel_dropped_pkts;
extern atomic_t cm_resets_recvd; extern atomic_t cm_resets_recvd;
extern atomic_t pau_qps_created;
extern atomic_t pau_qps_destroyed;
extern u32 int_mod_timer_init; extern u32 int_mod_timer_init;
extern u32 int_mod_cq_depth_256; extern u32 int_mod_cq_depth_256;
...@@ -273,6 +278,14 @@ struct nes_device { ...@@ -273,6 +278,14 @@ struct nes_device {
u8 link_recheck; u8 link_recheck;
}; };
/* Receive skb private area - must fit in skb->cb area */
struct nes_rskb_cb {
u64 busaddr;
u32 maplen;
u32 seqnum;
u8 *data_start;
struct nes_qp *nesqp;
};
static inline __le32 get_crc_value(struct nes_v4_quad *nes_quad) static inline __le32 get_crc_value(struct nes_v4_quad *nes_quad)
{ {
...@@ -305,8 +318,8 @@ set_wqe_32bit_value(__le32 *wqe_words, u32 index, u32 value) ...@@ -305,8 +318,8 @@ set_wqe_32bit_value(__le32 *wqe_words, u32 index, u32 value)
static inline void static inline void
nes_fill_init_cqp_wqe(struct nes_hw_cqp_wqe *cqp_wqe, struct nes_device *nesdev) nes_fill_init_cqp_wqe(struct nes_hw_cqp_wqe *cqp_wqe, struct nes_device *nesdev)
{ {
set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_CTX_LOW_IDX, cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_LOW_IDX] = 0;
(u64)((unsigned long) &nesdev->cqp)); cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0;
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0; cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] = 0;
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0; cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = 0;
cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0; cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0;
......
此差异已折叠。
...@@ -48,7 +48,16 @@ ...@@ -48,7 +48,16 @@
#define IETF_MPA_KEY_SIZE 16 #define IETF_MPA_KEY_SIZE 16
#define IETF_MPA_VERSION 1 #define IETF_MPA_VERSION 1
#define IETF_MAX_PRIV_DATA_LEN 512 #define IETF_MAX_PRIV_DATA_LEN 512
#define IETF_MPA_FRAME_SIZE 20 #define IETF_MPA_FRAME_SIZE 20
#define IETF_RTR_MSG_SIZE 4
#define IETF_MPA_V2_FLAG 0x10
/* IETF RTR MSG Fields */
#define IETF_PEER_TO_PEER 0x8000
#define IETF_FLPDU_ZERO_LEN 0x4000
#define IETF_RDMA0_WRITE 0x8000
#define IETF_RDMA0_READ 0x4000
#define IETF_NO_IRD_ORD 0x3FFF
enum ietf_mpa_flags { enum ietf_mpa_flags {
IETF_MPA_FLAGS_MARKERS = 0x80, /* receive Markers */ IETF_MPA_FLAGS_MARKERS = 0x80, /* receive Markers */
...@@ -56,7 +65,7 @@ enum ietf_mpa_flags { ...@@ -56,7 +65,7 @@ enum ietf_mpa_flags {
IETF_MPA_FLAGS_REJECT = 0x20, /* Reject */ IETF_MPA_FLAGS_REJECT = 0x20, /* Reject */
}; };
struct ietf_mpa_frame { struct ietf_mpa_v1 {
u8 key[IETF_MPA_KEY_SIZE]; u8 key[IETF_MPA_KEY_SIZE];
u8 flags; u8 flags;
u8 rev; u8 rev;
...@@ -66,6 +75,20 @@ struct ietf_mpa_frame { ...@@ -66,6 +75,20 @@ struct ietf_mpa_frame {
#define ietf_mpa_req_resp_frame ietf_mpa_frame #define ietf_mpa_req_resp_frame ietf_mpa_frame
struct ietf_rtr_msg {
__be16 ctrl_ird;
__be16 ctrl_ord;
};
struct ietf_mpa_v2 {
u8 key[IETF_MPA_KEY_SIZE];
u8 flags;
u8 rev;
__be16 priv_data_len;
struct ietf_rtr_msg rtr_msg;
u8 priv_data[0];
};
struct nes_v4_quad { struct nes_v4_quad {
u32 rsvd0; u32 rsvd0;
__le32 DstIpAdrIndex; /* Only most significant 5 bits are valid */ __le32 DstIpAdrIndex; /* Only most significant 5 bits are valid */
...@@ -171,8 +194,7 @@ struct nes_timer_entry { ...@@ -171,8 +194,7 @@ struct nes_timer_entry {
#define NES_CM_DEF_SEQ2 0x18ed5740 #define NES_CM_DEF_SEQ2 0x18ed5740
#define NES_CM_DEF_LOCAL_ID2 0xb807 #define NES_CM_DEF_LOCAL_ID2 0xb807
#define MAX_CM_BUFFER (IETF_MPA_FRAME_SIZE + IETF_MAX_PRIV_DATA_LEN) #define MAX_CM_BUFFER (IETF_MPA_FRAME_SIZE + IETF_RTR_MSG_SIZE + IETF_MAX_PRIV_DATA_LEN)
typedef u32 nes_addr_t; typedef u32 nes_addr_t;
...@@ -204,6 +226,21 @@ enum nes_cm_node_state { ...@@ -204,6 +226,21 @@ enum nes_cm_node_state {
NES_CM_STATE_CLOSED NES_CM_STATE_CLOSED
}; };
enum mpa_frame_version {
IETF_MPA_V1 = 1,
IETF_MPA_V2 = 2
};
enum mpa_frame_key {
MPA_KEY_REQUEST,
MPA_KEY_REPLY
};
enum send_rdma0 {
SEND_RDMA_READ_ZERO = 1,
SEND_RDMA_WRITE_ZERO = 2
};
enum nes_tcpip_pkt_type { enum nes_tcpip_pkt_type {
NES_PKT_TYPE_UNKNOWN, NES_PKT_TYPE_UNKNOWN,
NES_PKT_TYPE_SYN, NES_PKT_TYPE_SYN,
...@@ -245,9 +282,9 @@ struct nes_cm_tcp_context { ...@@ -245,9 +282,9 @@ struct nes_cm_tcp_context {
enum nes_cm_listener_state { enum nes_cm_listener_state {
NES_CM_LISTENER_PASSIVE_STATE=1, NES_CM_LISTENER_PASSIVE_STATE = 1,
NES_CM_LISTENER_ACTIVE_STATE=2, NES_CM_LISTENER_ACTIVE_STATE = 2,
NES_CM_LISTENER_EITHER_STATE=3 NES_CM_LISTENER_EITHER_STATE = 3
}; };
struct nes_cm_listener { struct nes_cm_listener {
...@@ -283,16 +320,20 @@ struct nes_cm_node { ...@@ -283,16 +320,20 @@ struct nes_cm_node {
struct nes_cm_node *loopbackpartner; struct nes_cm_node *loopbackpartner;
struct nes_timer_entry *send_entry; struct nes_timer_entry *send_entry;
struct nes_timer_entry *recv_entry;
spinlock_t retrans_list_lock; spinlock_t retrans_list_lock;
struct nes_timer_entry *recv_entry; enum send_rdma0 send_rdma0_op;
int send_write0;
union { union {
struct ietf_mpa_frame mpa_frame; struct ietf_mpa_v1 mpa_frame;
u8 mpa_frame_buf[MAX_CM_BUFFER]; struct ietf_mpa_v2 mpa_v2_frame;
u8 mpa_frame_buf[MAX_CM_BUFFER];
}; };
enum mpa_frame_version mpa_frame_rev;
u16 ird_size;
u16 ord_size;
u16 mpa_frame_size; u16 mpa_frame_size;
struct iw_cm_id *cm_id; struct iw_cm_id *cm_id;
struct list_head list; struct list_head list;
...@@ -399,10 +440,8 @@ struct nes_cm_ops { ...@@ -399,10 +440,8 @@ struct nes_cm_ops {
struct nes_vnic *, u16, void *, struct nes_vnic *, u16, void *,
struct nes_cm_info *); struct nes_cm_info *);
int (*close)(struct nes_cm_core *, struct nes_cm_node *); int (*close)(struct nes_cm_core *, struct nes_cm_node *);
int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *, int (*accept)(struct nes_cm_core *, struct nes_cm_node *);
struct nes_cm_node *); int (*reject)(struct nes_cm_core *, struct nes_cm_node *);
int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *,
struct nes_cm_node *);
int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *, int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *,
struct sk_buff *); struct sk_buff *);
int (*destroy_cm_core)(struct nes_cm_core *); int (*destroy_cm_core)(struct nes_cm_core *);
...@@ -422,5 +461,7 @@ int nes_destroy_listen(struct iw_cm_id *); ...@@ -422,5 +461,7 @@ int nes_destroy_listen(struct iw_cm_id *);
int nes_cm_recv(struct sk_buff *, struct net_device *); int nes_cm_recv(struct sk_buff *, struct net_device *);
int nes_cm_start(void); int nes_cm_start(void);
int nes_cm_stop(void); int nes_cm_stop(void);
int nes_add_ref_cm_node(struct nes_cm_node *cm_node);
int nes_rem_ref_cm_node(struct nes_cm_node *cm_node);
#endif /* NES_CM_H */ #endif /* NES_CM_H */
...@@ -110,6 +110,14 @@ static unsigned char *nes_tcp_state_str[] = { ...@@ -110,6 +110,14 @@ static unsigned char *nes_tcp_state_str[] = {
}; };
#endif #endif
static inline void print_ip(struct nes_cm_node *cm_node)
{
unsigned char *rem_addr;
if (cm_node) {
rem_addr = (unsigned char *)&cm_node->rem_addr;
printk(KERN_ERR PFX "Remote IP addr: %pI4\n", rem_addr);
}
}
/** /**
* nes_nic_init_timer_defaults * nes_nic_init_timer_defaults
...@@ -1555,6 +1563,7 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic) ...@@ -1555,6 +1563,7 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
struct nes_hw_nic_rq_wqe *nic_rqe; struct nes_hw_nic_rq_wqe *nic_rqe;
struct nes_hw_nic *nesnic; struct nes_hw_nic *nesnic;
struct nes_device *nesdev; struct nes_device *nesdev;
struct nes_rskb_cb *cb;
u32 rx_wqes_posted = 0; u32 rx_wqes_posted = 0;
nesnic = &nesvnic->nic; nesnic = &nesvnic->nic;
...@@ -1580,6 +1589,9 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic) ...@@ -1580,6 +1589,9 @@ static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
bus_address = pci_map_single(nesdev->pcidev, bus_address = pci_map_single(nesdev->pcidev,
skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE); skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
cb = (struct nes_rskb_cb *)&skb->cb[0];
cb->busaddr = bus_address;
cb->maplen = nesvnic->max_frame_size;
nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head]; nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];
nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
...@@ -1669,6 +1681,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) ...@@ -1669,6 +1681,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
u32 cqp_head; u32 cqp_head;
u32 counter; u32 counter;
u32 wqe_count; u32 wqe_count;
struct nes_rskb_cb *cb;
u8 jumbomode=0; u8 jumbomode=0;
/* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */ /* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */
...@@ -1845,6 +1858,9 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) ...@@ -1845,6 +1858,9 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
pmem = pci_map_single(nesdev->pcidev, skb->data, pmem = pci_map_single(nesdev->pcidev, skb->data,
nesvnic->max_frame_size, PCI_DMA_FROMDEVICE); nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
cb = (struct nes_rskb_cb *)&skb->cb[0];
cb->busaddr = pmem;
cb->maplen = nesvnic->max_frame_size;
nic_rqe = &nesvnic->nic.rq_vbase[counter]; nic_rqe = &nesvnic->nic.rq_vbase[counter];
nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size); nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
...@@ -1873,6 +1889,13 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) ...@@ -1873,6 +1889,13 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
jumbomode = 1; jumbomode = 1;
nes_nic_init_timer_defaults(nesdev, jumbomode); nes_nic_init_timer_defaults(nesdev, jumbomode);
} }
if ((nesdev->nesadapter->allow_unaligned_fpdus) &&
(nes_init_mgt_qp(nesdev, netdev, nesvnic))) {
nes_debug(NES_DBG_INIT, "%s: Out of memory for pau nic\n", netdev->name);
nes_destroy_nic_qp(nesvnic);
return -ENOMEM;
}
nesvnic->lro_mgr.max_aggr = nes_lro_max_aggr; nesvnic->lro_mgr.max_aggr = nes_lro_max_aggr;
nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS; nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS;
nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc; nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc;
...@@ -1895,28 +1918,29 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic) ...@@ -1895,28 +1918,29 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
struct nes_device *nesdev = nesvnic->nesdev; struct nes_device *nesdev = nesvnic->nesdev;
struct nes_hw_cqp_wqe *cqp_wqe; struct nes_hw_cqp_wqe *cqp_wqe;
struct nes_hw_nic_sq_wqe *nic_sqe; struct nes_hw_nic_sq_wqe *nic_sqe;
struct nes_hw_nic_rq_wqe *nic_rqe;
__le16 *wqe_fragment_length; __le16 *wqe_fragment_length;
u16 wqe_fragment_index; u16 wqe_fragment_index;
u64 wqe_frag;
u32 cqp_head; u32 cqp_head;
u32 wqm_cfg0; u32 wqm_cfg0;
unsigned long flags; unsigned long flags;
struct sk_buff *rx_skb;
struct nes_rskb_cb *cb;
int ret; int ret;
if (nesdev->nesadapter->allow_unaligned_fpdus)
nes_destroy_mgt(nesvnic);
/* clear wqe stall before destroying NIC QP */ /* clear wqe stall before destroying NIC QP */
wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0); wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0);
nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF); nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF);
/* Free remaining NIC receive buffers */ /* Free remaining NIC receive buffers */
while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) { while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail]; rx_skb = nesvnic->nic.rx_skb[nesvnic->nic.rq_tail];
wqe_frag = (u64)le32_to_cpu( cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]); pci_unmap_single(nesdev->pcidev, cb->busaddr, cb->maplen,
wqe_frag |= ((u64)le32_to_cpu( PCI_DMA_FROMDEVICE);
nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX]))<<32;
pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]); dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1); nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
} }
...@@ -2775,6 +2799,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) ...@@ -2775,6 +2799,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
struct nes_hw_nic_sq_wqe *nic_sqe; struct nes_hw_nic_sq_wqe *nic_sqe;
struct sk_buff *skb; struct sk_buff *skb;
struct sk_buff *rx_skb; struct sk_buff *rx_skb;
struct nes_rskb_cb *cb;
__le16 *wqe_fragment_length; __le16 *wqe_fragment_length;
u32 head; u32 head;
u32 cq_size; u32 cq_size;
...@@ -2859,6 +2884,8 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) ...@@ -2859,6 +2884,8 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32; bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
pci_unmap_single(nesdev->pcidev, bus_address, pci_unmap_single(nesdev->pcidev, bus_address,
nesvnic->max_frame_size, PCI_DMA_FROMDEVICE); nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
cb = (struct nes_rskb_cb *)&rx_skb->cb[0];
cb->busaddr = 0;
/* rx_skb->tail = rx_skb->data + rx_pkt_size; */ /* rx_skb->tail = rx_skb->data + rx_pkt_size; */
/* rx_skb->len = rx_pkt_size; */ /* rx_skb->len = rx_pkt_size; */
rx_skb->len = 0; /* TODO: see if this is necessary */ rx_skb->len = 0; /* TODO: see if this is necessary */
...@@ -2983,6 +3010,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) ...@@ -2983,6 +3010,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
} }
/** /**
* nes_cqp_ce_handler * nes_cqp_ce_handler
*/ */
...@@ -2997,6 +3025,8 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq) ...@@ -2997,6 +3025,8 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
u32 cq_size; u32 cq_size;
u32 cqe_count=0; u32 cqe_count=0;
u32 error_code; u32 error_code;
u32 opcode;
u32 ctx_index;
/* u32 counter; */ /* u32 counter; */
head = cq->cq_head; head = cq->cq_head;
...@@ -3007,12 +3037,9 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq) ...@@ -3007,12 +3037,9 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
/* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head, /* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,
le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */ le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */
if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) { opcode = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]);
u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head]. if (opcode & NES_CQE_VALID) {
cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) | cqp = &nesdev->cqp;
((u64)(le32_to_cpu(cq->cq_vbase[head].
cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
cqp = *((struct nes_hw_cqp **)&u64temp);
error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]); error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);
if (error_code) { if (error_code) {
...@@ -3021,15 +3048,14 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq) ...@@ -3021,15 +3048,14 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f, le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,
(u16)(error_code >> 16), (u16)(error_code >> 16),
(u16)error_code); (u16)error_code);
nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",
cqp->qp_id, cqp->sq_head, cqp->sq_tail);
} }
u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail]. u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) | cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail]. ((u64)(le32_to_cpu(cq->cq_vbase[head].
wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX]))); cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
cqp_request = *((struct nes_cqp_request **)&u64temp);
cqp_request = (struct nes_cqp_request *)(unsigned long)u64temp;
if (cqp_request) { if (cqp_request) {
if (cqp_request->waiting) { if (cqp_request->waiting) {
/* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */ /* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */
...@@ -3075,9 +3101,15 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq) ...@@ -3075,9 +3101,15 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
cqp_wqe = &nesdev->cqp.sq_vbase[head]; cqp_wqe = &nesdev->cqp.sq_vbase[head];
memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe)); memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
barrier(); barrier();
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =
opcode = cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX];
if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
else
ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
cqp_wqe->wqe_words[ctx_index] =
cpu_to_le32((u32)((unsigned long)cqp_request)); cpu_to_le32((u32)((unsigned long)cqp_request));
cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] = cqp_wqe->wqe_words[ctx_index + 1] =
cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request))); cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));
nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n", nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",
cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head); cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);
...@@ -3093,7 +3125,6 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq) ...@@ -3093,7 +3125,6 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
nes_read32(nesdev->regs+NES_CQE_ALLOC); nes_read32(nesdev->regs+NES_CQE_ALLOC);
} }
static u8 *locate_mpa(u8 *pkt, u32 aeq_info) static u8 *locate_mpa(u8 *pkt, u32 aeq_info)
{ {
if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) { if (aeq_info & NES_AEQE_Q2_DATA_ETHERNET) {
...@@ -3553,9 +3584,9 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, ...@@ -3553,9 +3584,9 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]); aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
if (aeq_info & NES_AEQE_QP) { if (aeq_info & NES_AEQE_QP) {
if ((!nes_is_resource_allocated(nesadapter, nesadapter->allocated_qps, if (!nes_is_resource_allocated(nesadapter,
aeqe_cq_id)) || nesadapter->allocated_qps,
(atomic_read(&nesqp->close_timer_started))) aeqe_cq_id))
return; return;
} }
...@@ -3566,8 +3597,7 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, ...@@ -3566,8 +3597,7 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
if (atomic_inc_return(&nesqp->close_timer_started) == 1) { if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) && if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) &&
(nesqp->ibqp_state == IB_QPS_RTS) && (nesqp->ibqp_state == IB_QPS_RTS)) {
((nesadapter->eeprom_version >> 16) != NES_A0)) {
spin_lock_irqsave(&nesqp->lock, flags); spin_lock_irqsave(&nesqp->lock, flags);
nesqp->hw_iwarp_state = iwarp_state; nesqp->hw_iwarp_state = iwarp_state;
nesqp->hw_tcp_state = tcp_state; nesqp->hw_tcp_state = tcp_state;
...@@ -3594,9 +3624,10 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, ...@@ -3594,9 +3624,10 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
return; return;
} }
spin_lock_irqsave(&nesqp->lock, flags); spin_lock_irqsave(&nesqp->lock, flags);
nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING; nesqp->hw_iwarp_state = iwarp_state;
nesqp->hw_tcp_state = tcp_state;
nesqp->last_aeq = async_event_id;
spin_unlock_irqrestore(&nesqp->lock, flags); spin_unlock_irqrestore(&nesqp->lock, flags);
nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_CLOSING, 0, 0);
nes_cm_disconn(nesqp); nes_cm_disconn(nesqp);
break; break;
...@@ -3694,7 +3725,9 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, ...@@ -3694,7 +3725,9 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP: case NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP:
printk(KERN_ERR PFX "QP[%u] async_event_id=0x%04X IB_EVENT_QP_FATAL\n", printk(KERN_ERR PFX "QP[%u] async_event_id=0x%04X IB_EVENT_QP_FATAL\n",
nesqp->hwqp.qp_id, async_event_id); nesqp->hwqp.qp_id, async_event_id);
nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL); print_ip(nesqp->cm_node);
if (!atomic_read(&nesqp->close_timer_started))
nes_terminate_connection(nesdev, nesqp, aeqe, IB_EVENT_QP_FATAL);
break; break;
case NES_AEQE_AEID_CQ_OPERATION_ERROR: case NES_AEQE_AEID_CQ_OPERATION_ERROR:
......
...@@ -47,6 +47,11 @@ ...@@ -47,6 +47,11 @@
#define NES_MULTICAST_PF_MAX 8 #define NES_MULTICAST_PF_MAX 8
#define NES_A0 3 #define NES_A0 3
#define NES_ENABLE_PAU 0x07000001
#define NES_DISABLE_PAU 0x07000000
#define NES_PAU_COUNTER 10
#define NES_CQP_OPCODE_MASK 0x3f
enum pci_regs { enum pci_regs {
NES_INT_STAT = 0x0000, NES_INT_STAT = 0x0000,
NES_INT_MASK = 0x0004, NES_INT_MASK = 0x0004,
...@@ -73,8 +78,10 @@ enum indexed_regs { ...@@ -73,8 +78,10 @@ enum indexed_regs {
NES_IDX_QP_CONTROL = 0x0040, NES_IDX_QP_CONTROL = 0x0040,
NES_IDX_FLM_CONTROL = 0x0080, NES_IDX_FLM_CONTROL = 0x0080,
NES_IDX_INT_CPU_STATUS = 0x00a0, NES_IDX_INT_CPU_STATUS = 0x00a0,
NES_IDX_GPR_TRIGGER = 0x00bc,
NES_IDX_GPIO_CONTROL = 0x00f0, NES_IDX_GPIO_CONTROL = 0x00f0,
NES_IDX_GPIO_DATA = 0x00f4, NES_IDX_GPIO_DATA = 0x00f4,
NES_IDX_GPR2 = 0x010c,
NES_IDX_TCP_CONFIG0 = 0x01e4, NES_IDX_TCP_CONFIG0 = 0x01e4,
NES_IDX_TCP_TIMER_CONFIG = 0x01ec, NES_IDX_TCP_TIMER_CONFIG = 0x01ec,
NES_IDX_TCP_NOW = 0x01f0, NES_IDX_TCP_NOW = 0x01f0,
...@@ -202,6 +209,7 @@ enum nes_cqp_opcodes { ...@@ -202,6 +209,7 @@ enum nes_cqp_opcodes {
NES_CQP_REGISTER_SHARED_STAG = 0x0c, NES_CQP_REGISTER_SHARED_STAG = 0x0c,
NES_CQP_DEALLOCATE_STAG = 0x0d, NES_CQP_DEALLOCATE_STAG = 0x0d,
NES_CQP_MANAGE_ARP_CACHE = 0x0f, NES_CQP_MANAGE_ARP_CACHE = 0x0f,
NES_CQP_DOWNLOAD_SEGMENT = 0x10,
NES_CQP_SUSPEND_QPS = 0x11, NES_CQP_SUSPEND_QPS = 0x11,
NES_CQP_UPLOAD_CONTEXT = 0x13, NES_CQP_UPLOAD_CONTEXT = 0x13,
NES_CQP_CREATE_CEQ = 0x16, NES_CQP_CREATE_CEQ = 0x16,
...@@ -210,7 +218,8 @@ enum nes_cqp_opcodes { ...@@ -210,7 +218,8 @@ enum nes_cqp_opcodes {
NES_CQP_DESTROY_AEQ = 0x1b, NES_CQP_DESTROY_AEQ = 0x1b,
NES_CQP_LMI_ACCESS = 0x20, NES_CQP_LMI_ACCESS = 0x20,
NES_CQP_FLUSH_WQES = 0x22, NES_CQP_FLUSH_WQES = 0x22,
NES_CQP_MANAGE_APBVT = 0x23 NES_CQP_MANAGE_APBVT = 0x23,
NES_CQP_MANAGE_QUAD_HASH = 0x25
}; };
enum nes_cqp_wqe_word_idx { enum nes_cqp_wqe_word_idx {
...@@ -222,6 +231,14 @@ enum nes_cqp_wqe_word_idx { ...@@ -222,6 +231,14 @@ enum nes_cqp_wqe_word_idx {
NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX = 5, NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX = 5,
}; };
enum nes_cqp_wqe_word_download_idx { /* format differs from other cqp ops */
NES_CQP_WQE_DL_OPCODE_IDX = 0,
NES_CQP_WQE_DL_COMP_CTX_LOW_IDX = 1,
NES_CQP_WQE_DL_COMP_CTX_HIGH_IDX = 2,
NES_CQP_WQE_DL_LENGTH_0_TOTAL_IDX = 3
/* For index values 4-15 use NES_NIC_SQ_WQE_ values */
};
enum nes_cqp_cq_wqeword_idx { enum nes_cqp_cq_wqeword_idx {
NES_CQP_CQ_WQE_PBL_LOW_IDX = 6, NES_CQP_CQ_WQE_PBL_LOW_IDX = 6,
NES_CQP_CQ_WQE_PBL_HIGH_IDX = 7, NES_CQP_CQ_WQE_PBL_HIGH_IDX = 7,
...@@ -242,6 +259,7 @@ enum nes_cqp_stag_wqeword_idx { ...@@ -242,6 +259,7 @@ enum nes_cqp_stag_wqeword_idx {
NES_CQP_STAG_WQE_PBL_LEN_IDX = 14 NES_CQP_STAG_WQE_PBL_LEN_IDX = 14
}; };
#define NES_CQP_OP_LOGICAL_PORT_SHIFT 26
#define NES_CQP_OP_IWARP_STATE_SHIFT 28 #define NES_CQP_OP_IWARP_STATE_SHIFT 28
#define NES_CQP_OP_TERMLEN_SHIFT 28 #define NES_CQP_OP_TERMLEN_SHIFT 28
...@@ -599,6 +617,7 @@ enum nes_nic_sq_wqe_bits { ...@@ -599,6 +617,7 @@ enum nes_nic_sq_wqe_bits {
enum nes_nic_cqe_word_idx { enum nes_nic_cqe_word_idx {
NES_NIC_CQE_ACCQP_ID_IDX = 0, NES_NIC_CQE_ACCQP_ID_IDX = 0,
NES_NIC_CQE_HASH_RCVNXT = 1,
NES_NIC_CQE_TAG_PKT_TYPE_IDX = 2, NES_NIC_CQE_TAG_PKT_TYPE_IDX = 2,
NES_NIC_CQE_MISC_IDX = 3, NES_NIC_CQE_MISC_IDX = 3,
}; };
...@@ -1005,6 +1024,11 @@ struct nes_arp_entry { ...@@ -1005,6 +1024,11 @@ struct nes_arp_entry {
#define NES_NIC_CQ_DOWNWARD_TREND 16 #define NES_NIC_CQ_DOWNWARD_TREND 16
#define NES_PFT_SIZE 48 #define NES_PFT_SIZE 48
#define NES_MGT_WQ_COUNT 32
#define NES_MGT_CTX_SIZE ((NES_NIC_CTX_RQ_SIZE_32) | (NES_NIC_CTX_SQ_SIZE_32))
#define NES_MGT_QP_OFFSET 36
#define NES_MGT_QP_COUNT 4
struct nes_hw_tune_timer { struct nes_hw_tune_timer {
/* u16 cq_count; */ /* u16 cq_count; */
u16 threshold_low; u16 threshold_low;
...@@ -1118,6 +1142,7 @@ struct nes_adapter { ...@@ -1118,6 +1142,7 @@ struct nes_adapter {
u32 et_rate_sample_interval; u32 et_rate_sample_interval;
u32 timer_int_limit; u32 timer_int_limit;
u32 wqm_quanta; u32 wqm_quanta;
u8 allow_unaligned_fpdus;
/* Adapter base MAC address */ /* Adapter base MAC address */
u32 mac_addr_low; u32 mac_addr_low;
...@@ -1251,6 +1276,14 @@ struct nes_vnic { ...@@ -1251,6 +1276,14 @@ struct nes_vnic {
enum ib_event_type delayed_event; enum ib_event_type delayed_event;
enum ib_event_type last_dispatched_event; enum ib_event_type last_dispatched_event;
spinlock_t port_ibevent_lock; spinlock_t port_ibevent_lock;
u32 mgt_mem_size;
void *mgt_vbase;
dma_addr_t mgt_pbase;
struct nes_vnic_mgt *mgtvnic[NES_MGT_QP_COUNT];
struct task_struct *mgt_thread;
wait_queue_head_t mgt_wait_queue;
struct sk_buff_head mgt_skb_list;
}; };
struct nes_ib_device { struct nes_ib_device {
......
此差异已折叠。
/*
* Copyright (c) 2010 Intel-NE, 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.
*/
#ifndef __NES_MGT_H
#define __NES_MGT_H
#define MPA_FRAMING 6 /* length is 2 bytes, crc is 4 bytes */
int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct nes_vnic *nesvnic);
void nes_queue_mgt_skbs(struct sk_buff *skb, struct nes_vnic *nesvnic, struct nes_qp *nesqp);
void nes_destroy_mgt(struct nes_vnic *nesvnic);
void nes_destroy_pau_qp(struct nes_device *nesdev, struct nes_qp *nesqp);
struct nes_hw_mgt {
struct nes_hw_nic_rq_wqe *rq_vbase; /* virtual address of rq */
dma_addr_t rq_pbase; /* PCI memory for host rings */
struct sk_buff *rx_skb[NES_NIC_WQ_SIZE];
u16 qp_id;
u16 sq_head;
u16 rq_head;
u16 rq_tail;
u16 rq_size;
u8 replenishing_rq;
u8 reserved;
spinlock_t rq_lock;
};
struct nes_vnic_mgt {
struct nes_vnic *nesvnic;
struct nes_hw_mgt mgt;
struct nes_hw_nic_cq mgt_cq;
atomic_t rx_skbs_needed;
struct timer_list rq_wqes_timer;
atomic_t rx_skb_timer_running;
};
#define MAX_FPDU_FRAGS 4
struct pau_fpdu_frag {
struct sk_buff *skb;
u64 physaddr;
u32 frag_len;
bool cmplt;
};
struct pau_fpdu_info {
struct nes_qp *nesqp;
struct nes_cqp_request *cqp_request;
void *hdr_vbase;
dma_addr_t hdr_pbase;
int hdr_len;
u16 data_len;
u16 frag_cnt;
struct pau_fpdu_frag frags[MAX_FPDU_FRAGS];
};
enum pau_qh_state {
PAU_DEL_QH,
PAU_ADD_LB_QH,
PAU_READY
};
struct pau_qh_chg {
struct nes_device *nesdev;
struct nes_vnic *nesvnic;
struct nes_qp *nesqp;
};
#endif /* __NES_MGT_H */
...@@ -1091,6 +1091,8 @@ static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = { ...@@ -1091,6 +1091,8 @@ static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
"LRO aggregated", "LRO aggregated",
"LRO flushed", "LRO flushed",
"LRO no_desc", "LRO no_desc",
"PAU CreateQPs",
"PAU DestroyQPs",
}; };
#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset) #define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset)
...@@ -1306,6 +1308,8 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev, ...@@ -1306,6 +1308,8 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
target_stat_values[++index] = nesvnic->lro_mgr.stats.aggregated; target_stat_values[++index] = nesvnic->lro_mgr.stats.aggregated;
target_stat_values[++index] = nesvnic->lro_mgr.stats.flushed; target_stat_values[++index] = nesvnic->lro_mgr.stats.flushed;
target_stat_values[++index] = nesvnic->lro_mgr.stats.no_desc; target_stat_values[++index] = nesvnic->lro_mgr.stats.no_desc;
target_stat_values[++index] = atomic_read(&pau_qps_created);
target_stat_values[++index] = atomic_read(&pau_qps_destroyed);
} }
/** /**
......
...@@ -51,13 +51,34 @@ ...@@ -51,13 +51,34 @@
#include "nes.h" #include "nes.h"
static u16 nes_read16_eeprom(void __iomem *addr, u16 offset); static u16 nes_read16_eeprom(void __iomem *addr, u16 offset);
u32 mh_detected; u32 mh_detected;
u32 mh_pauses_sent; u32 mh_pauses_sent;
u32 nes_set_pau(struct nes_device *nesdev)
{
u32 ret = 0;
u32 counter;
nes_write_indexed(nesdev, NES_IDX_GPR2, NES_ENABLE_PAU);
nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
for (counter = 0; counter < NES_PAU_COUNTER; counter++) {
udelay(30);
if (!nes_read_indexed(nesdev, NES_IDX_GPR2)) {
printk(KERN_INFO PFX "PAU is supported.\n");
break;
}
nes_write_indexed(nesdev, NES_IDX_GPR_TRIGGER, 1);
}
if (counter == NES_PAU_COUNTER) {
printk(KERN_INFO PFX "PAU is not supported.\n");
return -EPERM;
}
return ret;
}
/** /**
* nes_read_eeprom_values - * nes_read_eeprom_values -
*/ */
...@@ -187,6 +208,11 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada ...@@ -187,6 +208,11 @@ int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesada
if (((major_ver == 3) && (minor_ver >= 16)) || (major_ver > 3)) if (((major_ver == 3) && (minor_ver >= 16)) || (major_ver > 3))
nesadapter->send_term_ok = 1; nesadapter->send_term_ok = 1;
if (nes_drv_opt & NES_DRV_OPT_ENABLE_PAU) {
if (!nes_set_pau(nesdev))
nesadapter->allow_unaligned_fpdus = 1;
}
nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8)) << 16) + nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8)) << 16) +
(u32)((u8)eeprom_data); (u32)((u8)eeprom_data);
...@@ -594,6 +620,7 @@ void nes_put_cqp_request(struct nes_device *nesdev, ...@@ -594,6 +620,7 @@ void nes_put_cqp_request(struct nes_device *nesdev,
nes_free_cqp_request(nesdev, cqp_request); nes_free_cqp_request(nesdev, cqp_request);
} }
/** /**
* nes_post_cqp_request * nes_post_cqp_request
*/ */
...@@ -604,6 +631,8 @@ void nes_post_cqp_request(struct nes_device *nesdev, ...@@ -604,6 +631,8 @@ void nes_post_cqp_request(struct nes_device *nesdev,
unsigned long flags; unsigned long flags;
u32 cqp_head; u32 cqp_head;
u64 u64temp; u64 u64temp;
u32 opcode;
int ctx_index = NES_CQP_WQE_COMP_CTX_LOW_IDX;
spin_lock_irqsave(&nesdev->cqp.lock, flags); spin_lock_irqsave(&nesdev->cqp.lock, flags);
...@@ -614,17 +643,20 @@ void nes_post_cqp_request(struct nes_device *nesdev, ...@@ -614,17 +643,20 @@ void nes_post_cqp_request(struct nes_device *nesdev,
nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1; nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head]; cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe)); memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
opcode = le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]);
if ((opcode & NES_CQP_OPCODE_MASK) == NES_CQP_DOWNLOAD_SEGMENT)
ctx_index = NES_CQP_WQE_DL_COMP_CTX_LOW_IDX;
barrier(); barrier();
u64temp = (unsigned long)cqp_request; u64temp = (unsigned long)cqp_request;
set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_SCRATCH_LOW_IDX, set_wqe_64bit_value(cqp_wqe->wqe_words, ctx_index, u64temp);
u64temp);
nes_debug(NES_DBG_CQP, "CQP request (opcode 0x%02X), line 1 = 0x%08X put on CQPs SQ," nes_debug(NES_DBG_CQP, "CQP request (opcode 0x%02X), line 1 = 0x%08X put on CQPs SQ,"
" request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u," " request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
" waiting = %d, refcount = %d.\n", " waiting = %d, refcount = %d.\n",
le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, opcode & NES_CQP_OPCODE_MASK,
le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size, nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
cqp_request->waiting, atomic_read(&cqp_request->refcount)); cqp_request->waiting, atomic_read(&cqp_request->refcount));
barrier(); barrier();
/* Ring doorbell (1 WQEs) */ /* Ring doorbell (1 WQEs) */
...@@ -645,7 +677,6 @@ void nes_post_cqp_request(struct nes_device *nesdev, ...@@ -645,7 +677,6 @@ void nes_post_cqp_request(struct nes_device *nesdev,
return; return;
} }
/** /**
* nes_arp_table * nes_arp_table
*/ */
......
...@@ -1458,7 +1458,7 @@ static int nes_destroy_qp(struct ib_qp *ibqp) ...@@ -1458,7 +1458,7 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
struct ib_qp_attr attr; struct ib_qp_attr attr;
struct iw_cm_id *cm_id; struct iw_cm_id *cm_id;
struct iw_cm_event cm_event; struct iw_cm_event cm_event;
int ret; int ret = 0;
atomic_inc(&sw_qps_destroyed); atomic_inc(&sw_qps_destroyed);
nesqp->destroyed = 1; nesqp->destroyed = 1;
...@@ -1511,7 +1511,6 @@ static int nes_destroy_qp(struct ib_qp *ibqp) ...@@ -1511,7 +1511,6 @@ static int nes_destroy_qp(struct ib_qp *ibqp)
if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq)) if ((nesqp->nesrcq) && (nesqp->nesrcq != nesqp->nesscq))
nes_clean_cq(nesqp, nesqp->nesrcq); nes_clean_cq(nesqp, nesqp->nesrcq);
} }
nes_rem_ref(&nesqp->ibqp); nes_rem_ref(&nesqp->ibqp);
return 0; return 0;
} }
...@@ -2338,8 +2337,10 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -2338,8 +2337,10 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
skip_pages = ((u32)region->offset) >> 12; skip_pages = ((u32)region->offset) >> 12;
if (ib_copy_from_udata(&req, udata, sizeof(req))) if (ib_copy_from_udata(&req, udata, sizeof(req))) {
ib_umem_release(region);
return ERR_PTR(-EFAULT); return ERR_PTR(-EFAULT);
}
nes_debug(NES_DBG_MR, "Memory Registration type = %08X.\n", req.reg_type); nes_debug(NES_DBG_MR, "Memory Registration type = %08X.\n", req.reg_type);
switch (req.reg_type) { switch (req.reg_type) {
...@@ -2631,6 +2632,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, ...@@ -2631,6 +2632,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
return &nesmr->ibmr; return &nesmr->ibmr;
} }
ib_umem_release(region);
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
} }
......
...@@ -139,7 +139,8 @@ struct nes_qp { ...@@ -139,7 +139,8 @@ struct nes_qp {
struct nes_cq *nesrcq; struct nes_cq *nesrcq;
struct nes_pd *nespd; struct nes_pd *nespd;
void *cm_node; /* handle of the node this QP is associated with */ void *cm_node; /* handle of the node this QP is associated with */
struct ietf_mpa_frame *ietf_frame; void *ietf_frame;
u8 ietf_frame_size;
dma_addr_t ietf_frame_pbase; dma_addr_t ietf_frame_pbase;
struct ib_mr *lsmm_mr; struct ib_mr *lsmm_mr;
struct nes_hw_qp hwqp; struct nes_hw_qp hwqp;
...@@ -154,6 +155,7 @@ struct nes_qp { ...@@ -154,6 +155,7 @@ struct nes_qp {
u32 mmap_sq_db_index; u32 mmap_sq_db_index;
u32 mmap_rq_db_index; u32 mmap_rq_db_index;
spinlock_t lock; spinlock_t lock;
spinlock_t pau_lock;
struct nes_qp_context *nesqp_context; struct nes_qp_context *nesqp_context;
dma_addr_t nesqp_context_pbase; dma_addr_t nesqp_context_pbase;
void *pbl_vbase; void *pbl_vbase;
...@@ -161,6 +163,8 @@ struct nes_qp { ...@@ -161,6 +163,8 @@ struct nes_qp {
struct page *page; struct page *page;
struct timer_list terminate_timer; struct timer_list terminate_timer;
enum ib_event_type terminate_eventtype; enum ib_event_type terminate_eventtype;
struct sk_buff_head pau_list;
u32 pau_rcv_nxt;
u16 active_conn:1; u16 active_conn:1;
u16 skip_lsmm:1; u16 skip_lsmm:1;
u16 user_mode:1; u16 user_mode:1;
...@@ -168,7 +172,8 @@ struct nes_qp { ...@@ -168,7 +172,8 @@ struct nes_qp {
u16 flush_issued:1; u16 flush_issued:1;
u16 destroyed:1; u16 destroyed:1;
u16 sig_all:1; u16 sig_all:1;
u16 rsvd:9; u16 pau_mode:1;
u16 rsvd:8;
u16 private_data_len; u16 private_data_len;
u16 term_sq_flush_code; u16 term_sq_flush_code;
u16 term_rq_flush_code; u16 term_rq_flush_code;
...@@ -176,5 +181,8 @@ struct nes_qp { ...@@ -176,5 +181,8 @@ struct nes_qp {
u8 hw_tcp_state; u8 hw_tcp_state;
u8 term_flags; u8 term_flags;
u8 sq_kmapped; u8 sq_kmapped;
u8 pau_busy;
u8 pau_pending;
u8 pau_state;
}; };
#endif /* NES_VERBS_H */ #endif /* NES_VERBS_H */
...@@ -171,7 +171,9 @@ struct qib_ctxtdata { ...@@ -171,7 +171,9 @@ struct qib_ctxtdata {
/* how many alloc_pages() chunks in rcvegrbuf_pages */ /* how many alloc_pages() chunks in rcvegrbuf_pages */
u32 rcvegrbuf_chunks; u32 rcvegrbuf_chunks;
/* how many egrbufs per chunk */ /* how many egrbufs per chunk */
u32 rcvegrbufs_perchunk; u16 rcvegrbufs_perchunk;
/* ilog2 of above */
u16 rcvegrbufs_perchunk_shift;
/* order for rcvegrbuf_pages */ /* order for rcvegrbuf_pages */
size_t rcvegrbuf_size; size_t rcvegrbuf_size;
/* rcvhdrq size (for freeing) */ /* rcvhdrq size (for freeing) */
...@@ -221,6 +223,9 @@ struct qib_ctxtdata { ...@@ -221,6 +223,9 @@ struct qib_ctxtdata {
/* ctxt rcvhdrq head offset */ /* ctxt rcvhdrq head offset */
u32 head; u32 head;
u32 pkt_count; u32 pkt_count;
/* lookaside fields */
struct qib_qp *lookaside_qp;
u32 lookaside_qpn;
/* QPs waiting for context processing */ /* QPs waiting for context processing */
struct list_head qp_wait_list; struct list_head qp_wait_list;
}; };
...@@ -807,6 +812,10 @@ struct qib_devdata { ...@@ -807,6 +812,10 @@ struct qib_devdata {
* supports, less gives more pio bufs/ctxt, etc. * supports, less gives more pio bufs/ctxt, etc.
*/ */
u32 cfgctxts; u32 cfgctxts;
/*
* number of ctxts available for PSM open
*/
u32 freectxts;
/* /*
* hint that we should update pioavailshadow before * hint that we should update pioavailshadow before
...@@ -936,7 +945,9 @@ struct qib_devdata { ...@@ -936,7 +945,9 @@ struct qib_devdata {
/* chip address space used by 4k pio buffers */ /* chip address space used by 4k pio buffers */
u32 align4k; u32 align4k;
/* size of each rcvegrbuffer */ /* size of each rcvegrbuffer */
u32 rcvegrbufsize; u16 rcvegrbufsize;
/* log2 of above */
u16 rcvegrbufsize_shift;
/* localbus width (1, 2,4,8,16,32) from config space */ /* localbus width (1, 2,4,8,16,32) from config space */
u32 lbus_width; u32 lbus_width;
/* localbus speed in MHz */ /* localbus speed in MHz */
......
...@@ -279,10 +279,10 @@ int qib_set_linkstate(struct qib_pportdata *ppd, u8 newstate) ...@@ -279,10 +279,10 @@ int qib_set_linkstate(struct qib_pportdata *ppd, u8 newstate)
*/ */
static inline void *qib_get_egrbuf(const struct qib_ctxtdata *rcd, u32 etail) static inline void *qib_get_egrbuf(const struct qib_ctxtdata *rcd, u32 etail)
{ {
const u32 chunk = etail / rcd->rcvegrbufs_perchunk; const u32 chunk = etail >> rcd->rcvegrbufs_perchunk_shift;
const u32 idx = etail % rcd->rcvegrbufs_perchunk; const u32 idx = etail & ((u32)rcd->rcvegrbufs_perchunk - 1);
return rcd->rcvegrbuf[chunk] + idx * rcd->dd->rcvegrbufsize; return rcd->rcvegrbuf[chunk] + (idx << rcd->dd->rcvegrbufsize_shift);
} }
/* /*
...@@ -310,7 +310,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd, ...@@ -310,7 +310,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
u32 opcode; u32 opcode;
u32 psn; u32 psn;
int diff; int diff;
unsigned long flags;
/* Sanity check packet */ /* Sanity check packet */
if (tlen < 24) if (tlen < 24)
...@@ -365,7 +364,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd, ...@@ -365,7 +364,6 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
switch (qp->ibqp.qp_type) { switch (qp->ibqp.qp_type) {
case IB_QPT_RC: case IB_QPT_RC:
spin_lock_irqsave(&qp->s_lock, flags);
ruc_res = ruc_res =
qib_ruc_check_hdr( qib_ruc_check_hdr(
ibp, hdr, ibp, hdr,
...@@ -373,11 +371,8 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd, ...@@ -373,11 +371,8 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd,
qp, qp,
be32_to_cpu(ohdr->bth[0])); be32_to_cpu(ohdr->bth[0]));
if (ruc_res) { if (ruc_res) {
spin_unlock_irqrestore(&qp->s_lock,
flags);
goto unlock; goto unlock;
} }
spin_unlock_irqrestore(&qp->s_lock, flags);
/* Only deal with RDMA Writes for now */ /* Only deal with RDMA Writes for now */
if (opcode < if (opcode <
...@@ -547,6 +542,15 @@ u32 qib_kreceive(struct qib_ctxtdata *rcd, u32 *llic, u32 *npkts) ...@@ -547,6 +542,15 @@ u32 qib_kreceive(struct qib_ctxtdata *rcd, u32 *llic, u32 *npkts)
updegr = 0; updegr = 0;
} }
} }
/*
* Notify qib_destroy_qp() if it is waiting
* for lookaside_qp to finish.
*/
if (rcd->lookaside_qp) {
if (atomic_dec_and_test(&rcd->lookaside_qp->refcount))
wake_up(&rcd->lookaside_qp->wait);
rcd->lookaside_qp = NULL;
}
rcd->head = l; rcd->head = l;
rcd->pkt_count += i; rcd->pkt_count += i;
......
...@@ -1284,6 +1284,7 @@ static int setup_ctxt(struct qib_pportdata *ppd, int ctxt, ...@@ -1284,6 +1284,7 @@ static int setup_ctxt(struct qib_pportdata *ppd, int ctxt,
strlcpy(rcd->comm, current->comm, sizeof(rcd->comm)); strlcpy(rcd->comm, current->comm, sizeof(rcd->comm));
ctxt_fp(fp) = rcd; ctxt_fp(fp) = rcd;
qib_stats.sps_ctxts++; qib_stats.sps_ctxts++;
dd->freectxts++;
ret = 0; ret = 0;
goto bail; goto bail;
...@@ -1792,6 +1793,7 @@ static int qib_close(struct inode *in, struct file *fp) ...@@ -1792,6 +1793,7 @@ static int qib_close(struct inode *in, struct file *fp)
if (dd->pageshadow) if (dd->pageshadow)
unlock_expected_tids(rcd); unlock_expected_tids(rcd);
qib_stats.sps_ctxts--; qib_stats.sps_ctxts--;
dd->freectxts--;
} }
mutex_unlock(&qib_mutex); mutex_unlock(&qib_mutex);
......
...@@ -3273,6 +3273,8 @@ static int init_6120_variables(struct qib_devdata *dd) ...@@ -3273,6 +3273,8 @@ static int init_6120_variables(struct qib_devdata *dd)
/* we always allocate at least 2048 bytes for eager buffers */ /* we always allocate at least 2048 bytes for eager buffers */
ret = ib_mtu_enum_to_int(qib_ibmtu); ret = ib_mtu_enum_to_int(qib_ibmtu);
dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU; dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
qib_6120_tidtemplate(dd); qib_6120_tidtemplate(dd);
......
...@@ -4085,6 +4085,8 @@ static int qib_init_7220_variables(struct qib_devdata *dd) ...@@ -4085,6 +4085,8 @@ static int qib_init_7220_variables(struct qib_devdata *dd)
/* we always allocate at least 2048 bytes for eager buffers */ /* we always allocate at least 2048 bytes for eager buffers */
ret = ib_mtu_enum_to_int(qib_ibmtu); ret = ib_mtu_enum_to_int(qib_ibmtu);
dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU; dd->rcvegrbufsize = ret != -1 ? max(ret, 2048) : QIB_DEFAULT_MTU;
BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
qib_7220_tidtemplate(dd); qib_7220_tidtemplate(dd);
......
...@@ -2310,12 +2310,15 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd) ...@@ -2310,12 +2310,15 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE << val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
QLOGIC_IB_IBCC_LINKINITCMD_SHIFT); QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
ppd->cpspec->ibcctrl_a = val;
/* /*
* Reset the PCS interface to the serdes (and also ibc, which is still * Reset the PCS interface to the serdes (and also ibc, which is still
* in reset from above). Writes new value of ibcctrl_a as last step. * in reset from above). Writes new value of ibcctrl_a as last step.
*/ */
qib_7322_mini_pcs_reset(ppd); qib_7322_mini_pcs_reset(ppd);
qib_write_kreg(dd, kr_scratch, 0ULL); qib_write_kreg(dd, kr_scratch, 0ULL);
/* clear the linkinit cmds */
ppd->cpspec->ibcctrl_a &= ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
if (!ppd->cpspec->ibcctrl_b) { if (!ppd->cpspec->ibcctrl_b) {
unsigned lse = ppd->link_speed_enabled; unsigned lse = ppd->link_speed_enabled;
...@@ -2387,11 +2390,6 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd) ...@@ -2387,11 +2390,6 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
qib_write_kreg_port(ppd, krp_rcvctrl, ppd->p_rcvctrl); qib_write_kreg_port(ppd, krp_rcvctrl, ppd->p_rcvctrl);
spin_unlock_irqrestore(&dd->cspec->rcvmod_lock, flags); spin_unlock_irqrestore(&dd->cspec->rcvmod_lock, flags);
/* Hold the link state machine for mezz boards */
if (IS_QMH(dd) || IS_QME(dd))
qib_set_ib_7322_lstate(ppd, 0,
QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
/* Also enable IBSTATUSCHG interrupt. */ /* Also enable IBSTATUSCHG interrupt. */
val = qib_read_kreg_port(ppd, krp_errmask); val = qib_read_kreg_port(ppd, krp_errmask);
qib_write_kreg_port(ppd, krp_errmask, qib_write_kreg_port(ppd, krp_errmask,
...@@ -2853,9 +2851,8 @@ static irqreturn_t qib_7322intr(int irq, void *data) ...@@ -2853,9 +2851,8 @@ static irqreturn_t qib_7322intr(int irq, void *data)
for (i = 0; i < dd->first_user_ctxt; i++) { for (i = 0; i < dd->first_user_ctxt; i++) {
if (ctxtrbits & rmask) { if (ctxtrbits & rmask) {
ctxtrbits &= ~rmask; ctxtrbits &= ~rmask;
if (dd->rcd[i]) { if (dd->rcd[i])
qib_kreceive(dd->rcd[i], NULL, &npkts); qib_kreceive(dd->rcd[i], NULL, &npkts);
}
} }
rmask <<= 1; rmask <<= 1;
} }
...@@ -5230,6 +5227,8 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs) ...@@ -5230,6 +5227,8 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
QIBL_IB_AUTONEG_INPROG))) QIBL_IB_AUTONEG_INPROG)))
set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled); set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled);
if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) { if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) {
struct qib_qsfp_data *qd =
&ppd->cpspec->qsfp_data;
/* unlock the Tx settings, speed may change */ /* unlock the Tx settings, speed may change */
qib_write_kreg_port(ppd, krp_tx_deemph_override, qib_write_kreg_port(ppd, krp_tx_deemph_override,
SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0,
...@@ -5237,6 +5236,12 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs) ...@@ -5237,6 +5236,12 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
qib_cancel_sends(ppd); qib_cancel_sends(ppd);
/* on link down, ensure sane pcs state */ /* on link down, ensure sane pcs state */
qib_7322_mini_pcs_reset(ppd); qib_7322_mini_pcs_reset(ppd);
/* schedule the qsfp refresh which should turn the link
off */
if (ppd->dd->flags & QIB_HAS_QSFP) {
qd->t_insert = get_jiffies_64();
schedule_work(&qd->work);
}
spin_lock_irqsave(&ppd->sdma_lock, flags); spin_lock_irqsave(&ppd->sdma_lock, flags);
if (__qib_sdma_running(ppd)) if (__qib_sdma_running(ppd))
__qib_sdma_process_event(ppd, __qib_sdma_process_event(ppd,
...@@ -5587,43 +5592,79 @@ static void qsfp_7322_event(struct work_struct *work) ...@@ -5587,43 +5592,79 @@ static void qsfp_7322_event(struct work_struct *work)
struct qib_qsfp_data *qd; struct qib_qsfp_data *qd;
struct qib_pportdata *ppd; struct qib_pportdata *ppd;
u64 pwrup; u64 pwrup;
unsigned long flags;
int ret; int ret;
u32 le2; u32 le2;
qd = container_of(work, struct qib_qsfp_data, work); qd = container_of(work, struct qib_qsfp_data, work);
ppd = qd->ppd; ppd = qd->ppd;
pwrup = qd->t_insert + msecs_to_jiffies(QSFP_PWR_LAG_MSEC); pwrup = qd->t_insert +
msecs_to_jiffies(QSFP_PWR_LAG_MSEC - QSFP_MODPRS_LAG_MSEC);
/* /* Delay for 20 msecs to allow ModPrs resistor to setup */
* Some QSFP's not only do not respond until the full power-up mdelay(QSFP_MODPRS_LAG_MSEC);
* time, but may behave badly if we try. So hold off responding
* to insertion. if (!qib_qsfp_mod_present(ppd)) {
*/ ppd->cpspec->qsfp_data.modpresent = 0;
while (1) { /* Set the physical link to disabled */
u64 now = get_jiffies_64(); qib_set_ib_7322_lstate(ppd, 0,
if (time_after64(now, pwrup)) QLOGIC_IB_IBCC_LINKINITCMD_DISABLE);
break; spin_lock_irqsave(&ppd->lflags_lock, flags);
msleep(20); ppd->lflags &= ~QIBL_LINKV;
} spin_unlock_irqrestore(&ppd->lflags_lock, flags);
ret = qib_refresh_qsfp_cache(ppd, &qd->cache); } else {
/* /*
* Need to change LE2 back to defaults if we couldn't * Some QSFP's not only do not respond until the full power-up
* read the cable type (to handle cable swaps), so do this * time, but may behave badly if we try. So hold off responding
* even on failure to read cable information. We don't * to insertion.
* get here for QME, so IS_QME check not needed here. */
*/ while (1) {
if (!ret && !ppd->dd->cspec->r1) { u64 now = get_jiffies_64();
if (QSFP_IS_ACTIVE_FAR(qd->cache.tech)) if (time_after64(now, pwrup))
le2 = LE2_QME; break;
else if (qd->cache.atten[1] >= qib_long_atten && msleep(20);
QSFP_IS_CU(qd->cache.tech)) }
le2 = LE2_5m;
else ret = qib_refresh_qsfp_cache(ppd, &qd->cache);
/*
* Need to change LE2 back to defaults if we couldn't
* read the cable type (to handle cable swaps), so do this
* even on failure to read cable information. We don't
* get here for QME, so IS_QME check not needed here.
*/
if (!ret && !ppd->dd->cspec->r1) {
if (QSFP_IS_ACTIVE_FAR(qd->cache.tech))
le2 = LE2_QME;
else if (qd->cache.atten[1] >= qib_long_atten &&
QSFP_IS_CU(qd->cache.tech))
le2 = LE2_5m;
else
le2 = LE2_DEFAULT;
} else
le2 = LE2_DEFAULT; le2 = LE2_DEFAULT;
} else ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
le2 = LE2_DEFAULT; /*
ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7)); * We always change parameteters, since we can choose
init_txdds_table(ppd, 0); * values for cables without eeproms, and the cable may have
* changed from a cable with full or partial eeprom content
* to one with partial or no content.
*/
init_txdds_table(ppd, 0);
/* The physical link is being re-enabled only when the
* previous state was DISABLED and the VALID bit is not
* set. This should only happen when the cable has been
* physically pulled. */
if (!ppd->cpspec->qsfp_data.modpresent &&
(ppd->lflags & (QIBL_LINKV | QIBL_IB_LINK_DISABLED))) {
ppd->cpspec->qsfp_data.modpresent = 1;
qib_set_ib_7322_lstate(ppd, 0,
QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
spin_lock_irqsave(&ppd->lflags_lock, flags);
ppd->lflags |= QIBL_LINKV;
spin_unlock_irqrestore(&ppd->lflags_lock, flags);
}
}
} }
/* /*
...@@ -5727,7 +5768,8 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change) ...@@ -5727,7 +5768,8 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change)
/* now change the IBC and serdes, overriding generic */ /* now change the IBC and serdes, overriding generic */
init_txdds_table(ppd, 1); init_txdds_table(ppd, 1);
/* Re-enable the physical state machine on mezz boards /* Re-enable the physical state machine on mezz boards
* now that the correct settings have been set. */ * now that the correct settings have been set.
* QSFP boards are handles by the QSFP event handler */
if (IS_QMH(dd) || IS_QME(dd)) if (IS_QMH(dd) || IS_QME(dd))
qib_set_ib_7322_lstate(ppd, 0, qib_set_ib_7322_lstate(ppd, 0,
QLOGIC_IB_IBCC_LINKINITCMD_SLEEP); QLOGIC_IB_IBCC_LINKINITCMD_SLEEP);
...@@ -6205,6 +6247,8 @@ static int qib_init_7322_variables(struct qib_devdata *dd) ...@@ -6205,6 +6247,8 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
/* we always allocate at least 2048 bytes for eager buffers */ /* we always allocate at least 2048 bytes for eager buffers */
dd->rcvegrbufsize = max(mtu, 2048); dd->rcvegrbufsize = max(mtu, 2048);
BUG_ON(!is_power_of_2(dd->rcvegrbufsize));
dd->rcvegrbufsize_shift = ilog2(dd->rcvegrbufsize);
qib_7322_tidtemplate(dd); qib_7322_tidtemplate(dd);
...@@ -7147,7 +7191,8 @@ static void find_best_ent(struct qib_pportdata *ppd, ...@@ -7147,7 +7191,8 @@ static void find_best_ent(struct qib_pportdata *ppd,
} }
} }
/* Lookup serdes setting by cable type and attenuation */ /* Active cables don't have attenuation so we only set SERDES
* settings to account for the attenuation of the board traces. */
if (!override && QSFP_IS_ACTIVE(qd->tech)) { if (!override && QSFP_IS_ACTIVE(qd->tech)) {
*sdr_dds = txdds_sdr + ppd->dd->board_atten; *sdr_dds = txdds_sdr + ppd->dd->board_atten;
*ddr_dds = txdds_ddr + ppd->dd->board_atten; *ddr_dds = txdds_ddr + ppd->dd->board_atten;
...@@ -7464,12 +7509,6 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd) ...@@ -7464,12 +7509,6 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd)
u32 le_val, rxcaldone; u32 le_val, rxcaldone;
int chan, chan_done = (1 << SERDES_CHANS) - 1; int chan, chan_done = (1 << SERDES_CHANS) - 1;
/*
* Initialize the Tx DDS tables. Also done every QSFP event,
* for adapters with QSFP
*/
init_txdds_table(ppd, 0);
/* Clear cmode-override, may be set from older driver */ /* Clear cmode-override, may be set from older driver */
ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 0 << 14, 1 << 14); ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 0 << 14, 1 << 14);
...@@ -7655,6 +7694,12 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd) ...@@ -7655,6 +7694,12 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd)
/* VGA output common mode */ /* VGA output common mode */
ibsd_wr_allchans(ppd, 12, (3 << 2), BMASK(3, 2)); ibsd_wr_allchans(ppd, 12, (3 << 2), BMASK(3, 2));
/*
* Initialize the Tx DDS tables. Also done every QSFP event,
* for adapters with QSFP
*/
init_txdds_table(ppd, 0);
return 0; return 0;
} }
......
...@@ -183,6 +183,9 @@ struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt) ...@@ -183,6 +183,9 @@ struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt)
rcd->rcvegrbuf_chunks = (rcd->rcvegrcnt + rcd->rcvegrbuf_chunks = (rcd->rcvegrcnt +
rcd->rcvegrbufs_perchunk - 1) / rcd->rcvegrbufs_perchunk - 1) /
rcd->rcvegrbufs_perchunk; rcd->rcvegrbufs_perchunk;
BUG_ON(!is_power_of_2(rcd->rcvegrbufs_perchunk));
rcd->rcvegrbufs_perchunk_shift =
ilog2(rcd->rcvegrbufs_perchunk);
} }
return rcd; return rcd;
} }
...@@ -398,6 +401,7 @@ static void enable_chip(struct qib_devdata *dd) ...@@ -398,6 +401,7 @@ static void enable_chip(struct qib_devdata *dd)
if (rcd) if (rcd)
dd->f_rcvctrl(rcd->ppd, rcvmask, i); dd->f_rcvctrl(rcd->ppd, rcvmask, i);
} }
dd->freectxts = dd->cfgctxts - dd->first_user_ctxt;
} }
static void verify_interrupt(unsigned long opaque) static void verify_interrupt(unsigned long opaque)
...@@ -581,10 +585,6 @@ int qib_init(struct qib_devdata *dd, int reinit) ...@@ -581,10 +585,6 @@ int qib_init(struct qib_devdata *dd, int reinit)
continue; continue;
} }
/* let link come up, and enable IBC */
spin_lock_irqsave(&ppd->lflags_lock, flags);
ppd->lflags &= ~QIBL_IB_LINK_DISABLED;
spin_unlock_irqrestore(&ppd->lflags_lock, flags);
portok++; portok++;
} }
......
此差异已折叠。
...@@ -273,18 +273,12 @@ int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, struct qib_qsfp_cache *cp) ...@@ -273,18 +273,12 @@ int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, struct qib_qsfp_cache *cp)
int ret; int ret;
int idx; int idx;
u16 cks; u16 cks;
u32 mask;
u8 peek[4]; u8 peek[4];
/* ensure sane contents on invalid reads, for cable swaps */ /* ensure sane contents on invalid reads, for cable swaps */
memset(cp, 0, sizeof(*cp)); memset(cp, 0, sizeof(*cp));
mask = QSFP_GPIO_MOD_PRS_N; if (!qib_qsfp_mod_present(ppd)) {
if (ppd->hw_pidx)
mask <<= QSFP_GPIO_PORT2_SHIFT;
ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
if (ret & mask) {
ret = -ENODEV; ret = -ENODEV;
goto bail; goto bail;
} }
...@@ -444,6 +438,19 @@ const char * const qib_qsfp_devtech[16] = { ...@@ -444,6 +438,19 @@ const char * const qib_qsfp_devtech[16] = {
static const char *pwr_codes = "1.5W2.0W2.5W3.5W"; static const char *pwr_codes = "1.5W2.0W2.5W3.5W";
int qib_qsfp_mod_present(struct qib_pportdata *ppd)
{
u32 mask;
int ret;
mask = QSFP_GPIO_MOD_PRS_N <<
(ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT);
ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
return !((ret & mask) >>
((ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT) + 3));
}
/* /*
* Initialize structures that control access to QSFP. Called once per port * Initialize structures that control access to QSFP. Called once per port
* on cards that support QSFP. * on cards that support QSFP.
...@@ -452,7 +459,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd, ...@@ -452,7 +459,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
void (*fevent)(struct work_struct *)) void (*fevent)(struct work_struct *))
{ {
u32 mask, highs; u32 mask, highs;
int pins;
struct qib_devdata *dd = qd->ppd->dd; struct qib_devdata *dd = qd->ppd->dd;
...@@ -480,8 +486,7 @@ void qib_qsfp_init(struct qib_qsfp_data *qd, ...@@ -480,8 +486,7 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
mask <<= QSFP_GPIO_PORT2_SHIFT; mask <<= QSFP_GPIO_PORT2_SHIFT;
/* Do not try to wait here. Better to let event handle it */ /* Do not try to wait here. Better to let event handle it */
pins = dd->f_gpio_mod(dd, 0, 0, 0); if (!qib_qsfp_mod_present(qd->ppd))
if (pins & mask)
goto bail; goto bail;
/* We see a module, but it may be unwise to look yet. Just schedule */ /* We see a module, but it may be unwise to look yet. Just schedule */
qd->t_insert = get_jiffies_64(); qd->t_insert = get_jiffies_64();
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#define QSFP_DEV 0xA0 #define QSFP_DEV 0xA0
#define QSFP_PWR_LAG_MSEC 2000 #define QSFP_PWR_LAG_MSEC 2000
#define QSFP_MODPRS_LAG_MSEC 20
/* /*
* Below are masks for various QSFP signals, for Port 1. * Below are masks for various QSFP signals, for Port 1.
...@@ -177,10 +178,12 @@ struct qib_qsfp_data { ...@@ -177,10 +178,12 @@ struct qib_qsfp_data {
struct work_struct work; struct work_struct work;
struct qib_qsfp_cache cache; struct qib_qsfp_cache cache;
u64 t_insert; u64 t_insert;
u8 modpresent;
}; };
extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, extern int qib_refresh_qsfp_cache(struct qib_pportdata *ppd,
struct qib_qsfp_cache *cp); struct qib_qsfp_cache *cp);
extern int qib_qsfp_mod_present(struct qib_pportdata *ppd);
extern void qib_qsfp_init(struct qib_qsfp_data *qd, extern void qib_qsfp_init(struct qib_qsfp_data *qd,
void (*fevent)(struct work_struct *)); void (*fevent)(struct work_struct *));
extern void qib_qsfp_deinit(struct qib_qsfp_data *qd); extern void qib_qsfp_deinit(struct qib_qsfp_data *qd);
此差异已折叠。
...@@ -260,12 +260,15 @@ static int gid_ok(union ib_gid *gid, __be64 gid_prefix, __be64 id) ...@@ -260,12 +260,15 @@ static int gid_ok(union ib_gid *gid, __be64 gid_prefix, __be64 id)
/* /*
* *
* This should be called with the QP s_lock held. * This should be called with the QP r_lock held.
*
* The s_lock will be acquired around the qib_migrate_qp() call.
*/ */
int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr, int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr,
int has_grh, struct qib_qp *qp, u32 bth0) int has_grh, struct qib_qp *qp, u32 bth0)
{ {
__be64 guid; __be64 guid;
unsigned long flags;
if (qp->s_mig_state == IB_MIG_ARMED && (bth0 & IB_BTH_MIG_REQ)) { if (qp->s_mig_state == IB_MIG_ARMED && (bth0 & IB_BTH_MIG_REQ)) {
if (!has_grh) { if (!has_grh) {
...@@ -295,7 +298,9 @@ int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr, ...@@ -295,7 +298,9 @@ int qib_ruc_check_hdr(struct qib_ibport *ibp, struct qib_ib_header *hdr,
if (be16_to_cpu(hdr->lrh[3]) != qp->alt_ah_attr.dlid || if (be16_to_cpu(hdr->lrh[3]) != qp->alt_ah_attr.dlid ||
ppd_from_ibp(ibp)->port != qp->alt_ah_attr.port_num) ppd_from_ibp(ibp)->port != qp->alt_ah_attr.port_num)
goto err; goto err;
spin_lock_irqsave(&qp->s_lock, flags);
qib_migrate_qp(qp); qib_migrate_qp(qp);
spin_unlock_irqrestore(&qp->s_lock, flags);
} else { } else {
if (!has_grh) { if (!has_grh) {
if (qp->remote_ah_attr.ah_flags & IB_AH_GRH) if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)
......
...@@ -107,6 +107,11 @@ struct ib_srq *qib_create_srq(struct ib_pd *ibpd, ...@@ -107,6 +107,11 @@ struct ib_srq *qib_create_srq(struct ib_pd *ibpd,
u32 sz; u32 sz;
struct ib_srq *ret; struct ib_srq *ret;
if (srq_init_attr->srq_type != IB_SRQT_BASIC) {
ret = ERR_PTR(-ENOSYS);
goto done;
}
if (srq_init_attr->attr.max_sge == 0 || if (srq_init_attr->attr.max_sge == 0 ||
srq_init_attr->attr.max_sge > ib_qib_max_srq_sges || srq_init_attr->attr.max_sge > ib_qib_max_srq_sges ||
srq_init_attr->attr.max_wr == 0 || srq_init_attr->attr.max_wr == 0 ||
......
...@@ -515,8 +515,7 @@ static ssize_t show_nfreectxts(struct device *device, ...@@ -515,8 +515,7 @@ static ssize_t show_nfreectxts(struct device *device,
struct qib_devdata *dd = dd_from_dev(dev); struct qib_devdata *dd = dd_from_dev(dev);
/* Return the number of free user ports (contexts) available. */ /* Return the number of free user ports (contexts) available. */
return scnprintf(buf, PAGE_SIZE, "%u\n", dd->cfgctxts - return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts);
dd->first_user_ctxt - (u32)qib_stats.sps_ctxts);
} }
static ssize_t show_serial(struct device *device, static ssize_t show_serial(struct device *device,
......
此差异已折叠。
...@@ -485,6 +485,7 @@ struct qib_qp { ...@@ -485,6 +485,7 @@ struct qib_qp {
u8 alt_timeout; /* Alternate path timeout for this QP */ u8 alt_timeout; /* Alternate path timeout for this QP */
u8 port_num; u8 port_num;
enum ib_mtu path_mtu; enum ib_mtu path_mtu;
u32 pmtu; /* decoded from path_mtu */
u32 remote_qpn; u32 remote_qpn;
u32 qkey; /* QKEY for this QP (for UD or RD) */ u32 qkey; /* QKEY for this QP (for UD or RD) */
u32 s_size; /* send work queue size */ u32 s_size; /* send work queue size */
...@@ -495,6 +496,7 @@ struct qib_qp { ...@@ -495,6 +496,7 @@ struct qib_qp {
u32 s_last; /* last completed entry */ u32 s_last; /* last completed entry */
u32 s_ssn; /* SSN of tail entry */ u32 s_ssn; /* SSN of tail entry */
u32 s_lsn; /* limit sequence number (credit) */ u32 s_lsn; /* limit sequence number (credit) */
unsigned long timeout_jiffies; /* computed from timeout */
struct qib_swqe *s_wq; /* send work queue */ struct qib_swqe *s_wq; /* send work queue */
struct qib_swqe *s_wqe; struct qib_swqe *s_wqe;
struct qib_rq r_rq; /* receive work queue */ struct qib_rq r_rq; /* receive work queue */
...@@ -723,7 +725,8 @@ struct qib_ibdev { ...@@ -723,7 +725,8 @@ struct qib_ibdev {
dma_addr_t pio_hdrs_phys; dma_addr_t pio_hdrs_phys;
/* list of QPs waiting for RNR timer */ /* list of QPs waiting for RNR timer */
spinlock_t pending_lock; /* protect wait lists, PMA counters, etc. */ spinlock_t pending_lock; /* protect wait lists, PMA counters, etc. */
unsigned qp_table_size; /* size of the hash table */ u32 qp_table_size; /* size of the hash table */
u32 qp_rnd; /* random bytes for hash */
spinlock_t qpt_lock; spinlock_t qpt_lock;
u32 n_piowait; u32 n_piowait;
......
...@@ -484,7 +484,7 @@ static void mlx4_free_eq(struct mlx4_dev *dev, ...@@ -484,7 +484,7 @@ static void mlx4_free_eq(struct mlx4_dev *dev,
mlx4_mtt_cleanup(dev, &eq->mtt); mlx4_mtt_cleanup(dev, &eq->mtt);
for (i = 0; i < npages; ++i) for (i = 0; i < npages; ++i)
pci_free_consistent(dev->pdev, PAGE_SIZE, dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
eq->page_list[i].buf, eq->page_list[i].buf,
eq->page_list[i].map); eq->page_list[i].map);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部