1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include "c2.h"
34#include <rdma/iw_cm.h>
35#include "c2_vq.h"
36
37static void handle_mq(struct c2_dev *c2dev, u32 index);
38static void handle_vq(struct c2_dev *c2dev, u32 mq_index);
39
40
41
42
43void c2_rnic_interrupt(struct c2_dev *c2dev)
44{
45 unsigned int mq_index;
46
47 while (c2dev->hints_read != be16_to_cpu(*c2dev->hint_count)) {
48 mq_index = readl(c2dev->regs + PCI_BAR0_HOST_HINT);
49 if (mq_index & 0x80000000) {
50 break;
51 }
52
53 c2dev->hints_read++;
54 handle_mq(c2dev, mq_index);
55 }
56
57}
58
59
60
61
62static void handle_mq(struct c2_dev *c2dev, u32 mq_index)
63{
64 if (c2dev->qptr_array[mq_index] == NULL) {
65 pr_debug("handle_mq: stray activity for mq_index=%d\n",
66 mq_index);
67 return;
68 }
69
70 switch (mq_index) {
71 case (0):
72
73
74
75
76
77
78
79
80 wake_up(&c2dev->req_vq_wo);
81 break;
82 case (1):
83 handle_vq(c2dev, mq_index);
84 break;
85 case (2):
86
87
88
89
90
91
92 handle_vq(c2dev, 1);
93
94 c2_ae_event(c2dev, mq_index);
95 break;
96 default:
97
98
99
100
101
102
103
104
105 c2_cq_event(c2dev, mq_index);
106 break;
107 }
108
109 return;
110}
111
112
113
114
115static void handle_vq(struct c2_dev *c2dev, u32 mq_index)
116{
117 void *adapter_msg, *reply_msg;
118 struct c2wr_hdr *host_msg;
119 struct c2wr_hdr tmp;
120 struct c2_mq *reply_vq;
121 struct c2_vq_req *req;
122 struct iw_cm_event cm_event;
123 int err;
124
125 reply_vq = (struct c2_mq *) c2dev->qptr_array[mq_index];
126
127
128
129
130
131 adapter_msg = c2_mq_consume(reply_vq);
132 if (adapter_msg == NULL) {
133 return;
134 }
135
136 host_msg = vq_repbuf_alloc(c2dev);
137
138
139
140
141
142
143 if (!host_msg) {
144 pr_debug("handle_vq: no repbufs!\n");
145
146
147
148
149
150 host_msg = &tmp;
151 memcpy(host_msg, adapter_msg, sizeof(tmp));
152 reply_msg = NULL;
153 } else {
154 memcpy(host_msg, adapter_msg, reply_vq->msg_size);
155 reply_msg = host_msg;
156 }
157
158
159
160
161 c2_mq_free(reply_vq);
162
163
164
165
166 req = (struct c2_vq_req *) (unsigned long) host_msg->context;
167 if (req == NULL) {
168
169
170
171
172 vq_repbuf_free(c2dev, host_msg);
173 pr_debug("handle_vq: UNEXPECTEDLY got NULL req\n");
174 return;
175 }
176
177 if (reply_msg)
178 err = c2_errno(reply_msg);
179 else
180 err = -ENOMEM;
181
182 if (!err) switch (req->event) {
183 case IW_CM_EVENT_ESTABLISHED:
184 c2_set_qp_state(req->qp,
185 C2_QP_STATE_RTS);
186
187
188
189
190 cm_event.ird = cm_event.ord = 128;
191 case IW_CM_EVENT_CLOSE:
192
193
194
195
196
197 cm_event.event = req->event;
198 cm_event.status = 0;
199 cm_event.local_addr = req->cm_id->local_addr;
200 cm_event.remote_addr = req->cm_id->remote_addr;
201 cm_event.private_data = NULL;
202 cm_event.private_data_len = 0;
203 req->cm_id->event_handler(req->cm_id, &cm_event);
204 break;
205 default:
206 break;
207 }
208
209 req->reply_msg = (u64) (unsigned long) (reply_msg);
210 atomic_set(&req->reply_ready, 1);
211 wake_up(&req->wait_object);
212
213
214
215
216
217 vq_req_put(c2dev, req);
218}
219