RDMA/cxgb4: Connect_request_upcall fixes.
[opensuse:kernel-source.git] / patches.drivers / 0021-RDMA-cxgb4-Connect_request_upcall-fixes.patch
1 From: Steve Wise <swise@opengridcomputing.com>
2 Date: Fri, 21 Mar 2014 20:40:33 +0530
3 Subject: RDMA/cxgb4: Connect_request_upcall fixes
4 Patch-mainline: v3.15-rc1
5 Git-commit: be13b2dff8c4e41846477b22cc5c164ea5a6ac2e
6
7 When processing an MPA Start Request, if the listening endpoint is
8 DEAD, then abort the connection.
9
10 If the IWCM returns an error, then we must abort the connection and
11 release resources.  Also abort_connection() should not post a CLOSE
12 event, so clean that up too.
13
14 Signed-off-by: Steve Wise <swise@opengridcomputing.com>
15 Signed-off-by: Roland Dreier <roland@purestorage.com>
16 Acked-by: John Jolly <jjolly@suse.de>
17 ---
18  drivers/infiniband/hw/cxgb4/cm.c | 40 ++++++++++++++++++++++++----------------
19  1 file changed, 24 insertions(+), 16 deletions(-)
20
21 diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
22 index 773d010..6bfef31 100644
23 --- a/drivers/infiniband/hw/cxgb4/cm.c
24 +++ b/drivers/infiniband/hw/cxgb4/cm.c
25 @@ -968,13 +968,14 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
26         return 0;
27  }
28  
29 -static void close_complete_upcall(struct c4iw_ep *ep)
30 +static void close_complete_upcall(struct c4iw_ep *ep, int status)
31  {
32         struct iw_cm_event event;
33  
34         PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
35         memset(&event, 0, sizeof(event));
36         event.event = IW_CM_EVENT_CLOSE;
37 +       event.status = status;
38         if (ep->com.cm_id) {
39                 PDBG("close complete delivered ep %p cm_id %p tid %u\n",
40                      ep, ep->com.cm_id, ep->hwtid);
41 @@ -988,7 +989,6 @@ static void close_complete_upcall(struct c4iw_ep *ep)
42  static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
43  {
44         PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
45 -       close_complete_upcall(ep);
46         state_set(&ep->com, ABORTING);
47         set_bit(ABORT_CONN, &ep->com.history);
48         return send_abort(ep, skb, gfp);
49 @@ -1067,9 +1067,10 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
50         }
51  }
52  
53 -static void connect_request_upcall(struct c4iw_ep *ep)
54 +static int connect_request_upcall(struct c4iw_ep *ep)
55  {
56         struct iw_cm_event event;
57 +       int ret;
58  
59         PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
60         memset(&event, 0, sizeof(event));
61 @@ -1094,15 +1095,14 @@ static void connect_request_upcall(struct c4iw_ep *ep)
62                 event.private_data_len = ep->plen;
63                 event.private_data = ep->mpa_pkt + sizeof(struct mpa_message);
64         }
65 -       if (state_read(&ep->parent_ep->com) != DEAD) {
66 -               c4iw_get_ep(&ep->com);
67 -               ep->parent_ep->com.cm_id->event_handler(
68 -                                               ep->parent_ep->com.cm_id,
69 -                                               &event);
70 -       }
71 +       c4iw_get_ep(&ep->com);
72 +       ret = ep->parent_ep->com.cm_id->event_handler(ep->parent_ep->com.cm_id,
73 +                                                     &event);
74 +       if (ret)
75 +               c4iw_put_ep(&ep->com);
76         set_bit(CONNREQ_UPCALL, &ep->com.history);
77         c4iw_put_ep(&ep->parent_ep->com);
78 -       ep->parent_ep = NULL;
79 +       return ret;
80  }
81  
82  static void established_upcall(struct c4iw_ep *ep)
83 @@ -1401,7 +1401,6 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
84                 return;
85  
86         PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
87 -       stop_ep_timer(ep);
88         mpa = (struct mpa_message *) ep->mpa_pkt;
89  
90         /*
91 @@ -1494,9 +1493,17 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
92              ep->mpa_attr.p2p_type);
93  
94         state_set(&ep->com, MPA_REQ_RCVD);
95 +       stop_ep_timer(ep);
96  
97         /* drive upcall */
98 -       connect_request_upcall(ep);
99 +       mutex_lock(&ep->parent_ep->com.mutex);
100 +       if (ep->parent_ep->com.state != DEAD) {
101 +               if (connect_request_upcall(ep))
102 +                       abort_connection(ep, skb, GFP_KERNEL);
103 +       } else {
104 +               abort_connection(ep, skb, GFP_KERNEL);
105 +       }
106 +       mutex_unlock(&ep->parent_ep->com.mutex);
107         return;
108  }
109  
110 @@ -2247,7 +2254,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
111                         c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
112                                        C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
113                 }
114 -               close_complete_upcall(ep);
115 +               close_complete_upcall(ep, 0);
116                 __state_set(&ep->com, DEAD);
117                 release = 1;
118                 disconnect = 0;
119 @@ -2426,7 +2433,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
120                                              C4IW_QP_ATTR_NEXT_STATE,
121                                              &attrs, 1);
122                 }
123 -               close_complete_upcall(ep);
124 +               close_complete_upcall(ep, 0);
125                 __state_set(&ep->com, DEAD);
126                 release = 1;
127                 break;
128 @@ -2981,7 +2988,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
129         rdev = &ep->com.dev->rdev;
130         if (c4iw_fatal_error(rdev)) {
131                 fatal = 1;
132 -               close_complete_upcall(ep);
133 +               close_complete_upcall(ep, -EIO);
134                 ep->com.state = DEAD;
135         }
136         switch (ep->com.state) {
137 @@ -3023,7 +3030,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
138         if (close) {
139                 if (abrupt) {
140                         set_bit(EP_DISC_ABORT, &ep->com.history);
141 -                       close_complete_upcall(ep);
142 +                       close_complete_upcall(ep, -ECONNRESET);
143                         ret = send_abort(ep, NULL, gfp);
144                 } else {
145                         set_bit(EP_DISC_CLOSE, &ep->com.history);
146 @@ -3435,6 +3442,7 @@ static void process_timeout(struct c4iw_ep *ep)
147                                      &attrs, 1);
148                 }
149                 __state_set(&ep->com, ABORTING);
150 +               close_complete_upcall(ep, -ETIMEDOUT);
151                 break;
152         default:
153                 WARN(1, "%s unexpected state ep %p tid %u state %u\n",
154 -- 
155 1.8.5.2
156