summaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/cxgb4/cm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/cxgb4/cm.c')
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c112
1 files changed, 82 insertions, 30 deletions
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 768a0fb67dd..c2fb71c182a 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -79,9 +79,10 @@ static int dack_mode = 1;
module_param(dack_mode, int, 0644);
MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)");
-int c4iw_max_read_depth = 8;
+uint c4iw_max_read_depth = 32;
module_param(c4iw_max_read_depth, int, 0644);
-MODULE_PARM_DESC(c4iw_max_read_depth, "Per-connection max ORD/IRD (default=8)");
+MODULE_PARM_DESC(c4iw_max_read_depth,
+ "Per-connection max ORD/IRD (default=32)");
static int enable_tcp_timestamps;
module_param(enable_tcp_timestamps, int, 0644);
@@ -474,7 +475,8 @@ static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb)
16)) | FW_WR_FLOWID(ep->hwtid));
flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
- flowc->mnemval[0].val = cpu_to_be32(PCI_FUNC(ep->com.dev->rdev.lldi.pdev->devfn) << 8);
+ flowc->mnemval[0].val = cpu_to_be32(FW_PFVF_CMD_PFN
+ (ep->com.dev->rdev.lldi.pf));
flowc->mnemval[1].mnemonic = FW_FLOWC_MNEM_CH;
flowc->mnemval[1].val = cpu_to_be32(ep->tx_chan);
flowc->mnemval[2].mnemonic = FW_FLOWC_MNEM_PORT;
@@ -821,6 +823,8 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
if (mpa_rev_to_use == 2) {
mpa->private_data_size = htons(ntohs(mpa->private_data_size) +
sizeof (struct mpa_v2_conn_params));
+ PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird,
+ ep->ord);
mpa_v2_params.ird = htons((u16)ep->ird);
mpa_v2_params.ord = htons((u16)ep->ord);
@@ -1190,8 +1194,8 @@ static int connect_request_upcall(struct c4iw_ep *ep)
sizeof(struct mpa_v2_conn_params);
} else {
/* this means MPA_v1 is used. Send max supported */
- event.ord = c4iw_max_read_depth;
- event.ird = c4iw_max_read_depth;
+ event.ord = cur_max_read_depth(ep->com.dev);
+ event.ird = cur_max_read_depth(ep->com.dev);
event.private_data_len = ep->plen;
event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
}
@@ -1255,6 +1259,8 @@ static int update_rx_credits(struct c4iw_ep *ep, u32 credits)
return credits;
}
+#define RELAXED_IRD_NEGOTIATION 1
+
static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
{
struct mpa_message *mpa;
@@ -1366,17 +1372,33 @@ static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
MPA_V2_IRD_ORD_MASK;
resp_ord = ntohs(mpa_v2_params->ord) &
MPA_V2_IRD_ORD_MASK;
+ PDBG("%s responder ird %u ord %u ep ird %u ord %u\n",
+ __func__, resp_ird, resp_ord, ep->ird, ep->ord);
/*
* This is a double-check. Ideally, below checks are
* not required since ird/ord stuff has been taken
* care of in c4iw_accept_cr
*/
- if ((ep->ird < resp_ord) || (ep->ord > resp_ird)) {
+ if (ep->ird < resp_ord) {
+ if (RELAXED_IRD_NEGOTIATION && resp_ord <=
+ ep->com.dev->rdev.lldi.max_ordird_qp)
+ ep->ird = resp_ord;
+ else
+ insuff_ird = 1;
+ } else if (ep->ird > resp_ord) {
+ ep->ird = resp_ord;
+ }
+ if (ep->ord > resp_ird) {
+ if (RELAXED_IRD_NEGOTIATION)
+ ep->ord = resp_ird;
+ else
+ insuff_ird = 1;
+ }
+ if (insuff_ird) {
err = -ENOMEM;
ep->ird = resp_ord;
ep->ord = resp_ird;
- insuff_ird = 1;
}
if (ntohs(mpa_v2_params->ird) &
@@ -1579,6 +1601,8 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
MPA_V2_IRD_ORD_MASK;
ep->ord = ntohs(mpa_v2_params->ord) &
MPA_V2_IRD_ORD_MASK;
+ PDBG("%s initiator ird %u ord %u\n", __func__, ep->ird,
+ ep->ord);
if (ntohs(mpa_v2_params->ird) & MPA_V2_PEER2PEER_MODEL)
if (peer2peer) {
if (ntohs(mpa_v2_params->ord) &
@@ -1798,6 +1822,20 @@ static int is_neg_adv(unsigned int status)
status == CPL_ERR_KEEPALV_NEG_ADVICE;
}
+static char *neg_adv_str(unsigned int status)
+{
+ switch (status) {
+ case CPL_ERR_RTX_NEG_ADVICE:
+ return "Retransmit timeout";
+ case CPL_ERR_PERSIST_NEG_ADVICE:
+ return "Persist timeout";
+ case CPL_ERR_KEEPALV_NEG_ADVICE:
+ return "Keepalive timeout";
+ default:
+ return "Unknown";
+ }
+}
+
static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi)
{
ep->snd_win = snd_win;
@@ -1996,8 +2034,9 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
status, status2errno(status));
if (is_neg_adv(status)) {
- printk(KERN_WARNING MOD "Connection problems for atid %u\n",
- atid);
+ dev_warn(&dev->rdev.lldi.pdev->dev,
+ "Connection problems for atid %u status %u (%s)\n",
+ atid, status, neg_adv_str(status));
return 0;
}
@@ -2472,8 +2511,9 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
ep = lookup_tid(t, tid);
if (is_neg_adv(req->status)) {
- PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
- ep->hwtid);
+ dev_warn(&dev->rdev.lldi.pdev->dev,
+ "Negative advice on abort - tid %u status %d (%s)\n",
+ ep->hwtid, req->status, neg_adv_str(req->status));
return 0;
}
PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
@@ -2731,8 +2771,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
BUG_ON(!qp);
set_bit(ULP_ACCEPT, &ep->com.history);
- if ((conn_param->ord > c4iw_max_read_depth) ||
- (conn_param->ird > c4iw_max_read_depth)) {
+ if ((conn_param->ord > cur_max_read_depth(ep->com.dev)) ||
+ (conn_param->ird > cur_max_read_depth(ep->com.dev))) {
abort_connection(ep, NULL, GFP_KERNEL);
err = -EINVAL;
goto err;
@@ -2740,31 +2780,41 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
if (conn_param->ord > ep->ird) {
- ep->ird = conn_param->ird;
- ep->ord = conn_param->ord;
- send_mpa_reject(ep, conn_param->private_data,
- conn_param->private_data_len);
- abort_connection(ep, NULL, GFP_KERNEL);
- err = -ENOMEM;
- goto err;
+ if (RELAXED_IRD_NEGOTIATION) {
+ ep->ord = ep->ird;
+ } else {
+ ep->ird = conn_param->ird;
+ ep->ord = conn_param->ord;
+ send_mpa_reject(ep, conn_param->private_data,
+ conn_param->private_data_len);
+ abort_connection(ep, NULL, GFP_KERNEL);
+ err = -ENOMEM;
+ goto err;
+ }
}
- if (conn_param->ird > ep->ord) {
- if (!ep->ord)
- conn_param->ird = 1;
- else {
+ if (conn_param->ird < ep->ord) {
+ if (RELAXED_IRD_NEGOTIATION &&
+ ep->ord <= h->rdev.lldi.max_ordird_qp) {
+ conn_param->ird = ep->ord;
+ } else {
abort_connection(ep, NULL, GFP_KERNEL);
err = -ENOMEM;
goto err;
}
}
-
}
ep->ird = conn_param->ird;
ep->ord = conn_param->ord;
- if (ep->mpa_attr.version != 2)
+ if (ep->mpa_attr.version == 1) {
if (peer2peer && ep->ird == 0)
ep->ird = 1;
+ } else {
+ if (peer2peer &&
+ (ep->mpa_attr.p2p_type != FW_RI_INIT_P2PTYPE_DISABLED) &&
+ (p2p_type == FW_RI_INIT_P2PTYPE_READ_REQ) && ep->ord == 0)
+ ep->ird = 1;
+ }
PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
@@ -2803,6 +2853,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
return 0;
err1:
ep->com.cm_id = NULL;
+ abort_connection(ep, NULL, GFP_KERNEL);
cm_id->rem_ref(cm_id);
err:
mutex_unlock(&ep->com.mutex);
@@ -2886,8 +2937,8 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
int iptype;
int iwpm_err = 0;
- if ((conn_param->ord > c4iw_max_read_depth) ||
- (conn_param->ird > c4iw_max_read_depth)) {
+ if ((conn_param->ord > cur_max_read_depth(dev)) ||
+ (conn_param->ird > cur_max_read_depth(dev))) {
err = -EINVAL;
goto out;
}
@@ -3867,8 +3918,9 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
return 0;
}
if (is_neg_adv(req->status)) {
- PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
- ep->hwtid);
+ dev_warn(&dev->rdev.lldi.pdev->dev,
+ "Negative advice on abort - tid %u status %d (%s)\n",
+ ep->hwtid, req->status, neg_adv_str(req->status));
kfree_skb(skb);
return 0;
}