[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-ti33x-psp-3.2 / 3.2.14 / 0049-IB-iser-Post-initial-receive-buffers-before-sending-.patch
1 From de960f13b12a65cff5f74f1f7bb6871fbd9ac432 Mon Sep 17 00:00:00 2001
2 From: Or Gerlitz <ogerlitz@mellanox.com>
3 Date: Mon, 5 Mar 2012 18:21:44 +0200
4 Subject: [PATCH 049/147] IB/iser: Post initial receive buffers before sending
5 the final login request
7 commit 89e984e2c2cd14f77ccb26c47726ac7f13b70ae8 upstream.
9 An iser target may send iscsi NO-OP PDUs as soon as it marks the iSER
10 iSCSI session as fully operative. This means that there is window
11 where there are no posted receive buffers on the initiator side, so
12 it's possible for the iSER RC connection to break because of RNR NAK /
13 retry errors. To fix this, rely on the flags bits in the login
14 request to have FFP (0x3) in the lower nibble as a marker for the
15 final login request, and post an initial chunk of receive buffers
16 before sending that login request instead of after getting the login
17 response.
19 Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
20 Signed-off-by: Roland Dreier <roland@purestorage.com>
21 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22 ---
23 drivers/infiniband/ulp/iser/iscsi_iser.c | 18 ++++------------
24 drivers/infiniband/ulp/iser/iscsi_iser.h | 1 +
25 drivers/infiniband/ulp/iser/iser_initiator.c | 30 +++++++++++++++-----------
26 3 files changed, 22 insertions(+), 27 deletions(-)
28 diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
29 index 7e7373a..d5f3b69 100644
30 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c
31 +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
32 @@ -364,6 +364,9 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
33 }
34 ib_conn = ep->dd_data;
36 + if (iser_alloc_rx_descriptors(ib_conn))
37 + return -ENOMEM;
38 +
39 /* binds the iSER connection retrieved from the previously
40 * connected ep_handle to the iSCSI layer connection. exchanges
41 * connection pointers */
42 @@ -398,19 +401,6 @@ iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
43 iser_conn->ib_conn = NULL;
44 }
46 -static int
47 -iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
48 -{
49 - struct iscsi_conn *conn = cls_conn->dd_data;
50 - int err;
51 -
52 - err = iser_conn_set_full_featured_mode(conn);
53 - if (err)
54 - return err;
55 -
56 - return iscsi_conn_start(cls_conn);
57 -}
58 -
59 static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
60 {
61 struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
62 @@ -724,7 +714,7 @@ static struct iscsi_transport iscsi_iser_transport = {
63 .get_conn_param = iscsi_conn_get_param,
64 .get_ep_param = iscsi_iser_get_ep_param,
65 .get_session_param = iscsi_session_get_param,
66 - .start_conn = iscsi_iser_conn_start,
67 + .start_conn = iscsi_conn_start,
68 .stop_conn = iscsi_iser_conn_stop,
69 /* iscsi host params */
70 .get_host_param = iscsi_host_get_param,
71 diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
72 index db7ea37..296be43 100644
73 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h
74 +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
75 @@ -366,4 +366,5 @@ int iser_dma_map_task_data(struct iscsi_iser_task *iser_task,
76 void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task);
77 int iser_initialize_task_headers(struct iscsi_task *task,
78 struct iser_tx_desc *tx_desc);
79 +int iser_alloc_rx_descriptors(struct iser_conn *ib_conn);
80 #endif
81 diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
82 index a607542..738a149 100644
83 --- a/drivers/infiniband/ulp/iser/iser_initiator.c
84 +++ b/drivers/infiniband/ulp/iser/iser_initiator.c
85 @@ -170,7 +170,7 @@ static void iser_create_send_desc(struct iser_conn *ib_conn,
86 }
89 -static int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
90 +int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
91 {
92 int i, j;
93 u64 dma_addr;
94 @@ -242,23 +242,24 @@ void iser_free_rx_descriptors(struct iser_conn *ib_conn)
95 kfree(ib_conn->rx_descs);
96 }
98 -/**
99 - * iser_conn_set_full_featured_mode - (iSER API)
100 - */
101 -int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
102 +static int iser_post_rx_bufs(struct iscsi_conn *conn, struct iscsi_hdr *req)
103 {
104 struct iscsi_iser_conn *iser_conn = conn->dd_data;
106 - iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
107 -
108 - /* Check that there is no posted recv or send buffers left - */
109 - /* they must be consumed during the login phase */
110 - BUG_ON(iser_conn->ib_conn->post_recv_buf_count != 0);
111 - BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
112 + iser_dbg("req op %x flags %x\n", req->opcode, req->flags);
113 + /* check if this is the last login - going to full feature phase */
114 + if ((req->flags & ISCSI_FULL_FEATURE_PHASE) != ISCSI_FULL_FEATURE_PHASE)
115 + return 0;
117 - if (iser_alloc_rx_descriptors(iser_conn->ib_conn))
118 - return -ENOMEM;
119 + /*
120 + * Check that there is one posted recv buffer (for the last login
121 + * response) and no posted send buffers left - they must have been
122 + * consumed during previous login phases.
123 + */
124 + WARN_ON(iser_conn->ib_conn->post_recv_buf_count != 1);
125 + WARN_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
127 + iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
128 /* Initial post receive buffers */
129 if (iser_post_recvm(iser_conn->ib_conn, ISER_MIN_POSTED_RX))
130 return -ENOMEM;
131 @@ -438,6 +439,9 @@ int iser_send_control(struct iscsi_conn *conn,
132 err = iser_post_recvl(iser_conn->ib_conn);
133 if (err)
134 goto send_control_error;
135 + err = iser_post_rx_bufs(conn, task->hdr);
136 + if (err)
137 + goto send_control_error;
138 }
140 err = iser_post_send(iser_conn->ib_conn, mdesc);
141 --
142 1.7.9.4