IPoIB code separated out to ipoib.c.
[people/pcmattman/gpxe.git] / src / drivers / net / mlx_ipoib / ib_driver.c
1 /*
2   This software is available to you under a choice of one of two
3   licenses.  You may choose to be licensed under the terms of the GNU
4   General Public License (GPL) Version 2, available at
5   <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD
6   license, available in the LICENSE.TXT file accompanying this
7   software.  These details are also available at
8   <http://openib.org/license.html>.
9
10   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
11   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
14   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
15   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   SOFTWARE.
18
19   Copyright (c) 2004 Mellanox Technologies Ltd.  All rights reserved.
20 */
21
22 #include "ib_driver.h"
23
24 static const __u8 ipv4_bcast_gid[] = {
25         0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00,
26         0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
27 };
28
29 static int wait_logic_link_up(__u8 port)
30 {
31         unsigned int relax_time, max_time;
32         relax_time = 500;
33         max_time = 30000;       /* 30 seconds */
34         int rc;
35         unsigned int i, error = 1;
36         __u16 status;
37         struct port_info_st pi_var;
38         __u8 port_state;
39
40         for (i = 0; i < max_time; i += relax_time) {
41                 rc = get_port_info(port, &pi_var, &status);
42                 if (rc) {
43                         eprintf("");
44                         return rc;
45                 } else {
46                         if (status == 0) {
47                                 port_state = (pi_var.combined4 >> 24) & 0xf;
48                                 //port_state= pi_var.port_state;
49                                 if (port_state == 4) {
50                                         error = 0;
51                                         break;
52                                 }
53                         }
54                 }
55                 printf("+");
56                 mdelay(relax_time);
57         }
58
59         if (i >= max_time)
60                 return -1;
61
62         return 0;
63 }
64
65 unsigned long ipoib_qkey;
66 unsigned long hack_ipoib_qkey;
67
68 static int ib_driver_init(struct pci_device *pci, udqp_t * ipoib_qph_p)
69 {
70         int rc;
71         __u8 port;
72         __u16 status;
73         __u32 qkey;
74         __u16 mlid;
75         ud_av_t av;
76         struct ib_eqe_st ib_eqe;
77         __u8 num_eqe;
78
79         tprintf("");
80         rc = ib_device_init(pci);
81         if (rc)
82                 return rc;
83
84         tprintf("");
85
86         memcpy(ib_data.bcast_gid.raw, ipv4_bcast_gid, sizeof(ipv4_bcast_gid));
87
88         port = PXE_IB_PORT;
89         rc = setup_hca(port, &ib_data.eq);
90         if (rc)
91                 return rc;
92         tprintf("setup_hca() success");
93
94         ib_data.port = port;
95
96         if(print_info)
97                 printf("boot port = %d\n", ib_data.port);
98
99         rc = wait_logic_link_up(port);
100         if (rc)
101                 return rc;
102
103         tprintf("wait_logic_link_up() success");
104
105         rc = get_guid_info(&status);
106         if (rc) {
107                 eprintf("");
108                 return rc;
109         } else if (status) {
110                 eprintf("");
111                 return rc;
112         }
113
114         tprintf("get_guid_info() success");
115
116         /* this to flush stdout that contains previous chars */
117         printf("    \n");
118         if(print_info) {
119                 __u8 *gid=ib_data.port_gid.raw;
120
121                 printf("\n");
122                 printf("port GID=%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:"
123                        "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\n",
124                        gid[0],gid[1],gid[2],gid[3],gid[4],gid[5],gid[6],gid[7],
125                        gid[8],gid[9],gid[10],gid[11],gid[12],gid[13],gid[14],gid[15]);
126         }
127
128         rc = get_pkey_tbl(NULL, &status);
129         if (rc) {
130                 eprintf("");
131                 return rc;
132         } else if (status) {
133                 eprintf("");
134                 return rc;
135         }
136         rc = create_mads_qp(&ib_data.mads_qp,
137                             &ib_data.mads_snd_cq, &ib_data.mads_rcv_cq);
138         if (rc) {
139                 eprintf("");
140                 return rc;
141         }
142
143         tprintf("attempt to join mcast group ...");
144         rc = join_mc_group(&qkey, &mlid, 1);
145         if (rc) {
146                 eprintf("");
147                 return rc;
148         } else {
149                 tprintf("join_mc_group() successfull qkey=0x%lx, mlid=0x%x",
150                         qkey, mlid);
151         }
152
153         hack_ipoib_qkey = ipoib_qkey = qkey;
154
155 #if 0
156         rc = create_ipoib_qp(&ib_data.ipoib_qp,
157                              &ib_data.ipoib_snd_cq,
158                              &ib_data.ipoib_rcv_cq, qkey);
159         if (rc) {
160                 eprintf("");
161                 return rc;
162         }
163
164         tprintf("create_ipoib_qp() success");
165         *ipoib_qph_p = ib_data.ipoib_qp;
166
167         tprintf("register qp to receive mcast...");
168         rc = add_qp_to_mcast_group(ib_data.bcast_gid, 1);
169         if (rc) {
170                 eprintf("");
171                 return rc;
172         } else {
173                 tprintf("add_qp_to_mcast_group() success");
174         }
175 #endif
176
177         /* create a broadcast group ud AV */
178         av = alloc_ud_av();
179         if (!av) {
180                 eprintf("");
181                 return -1;
182         }
183         tprintf("alloc_ud_av() success");
184         modify_av_params(av, mlid, 1, 0, 0, &ib_data.bcast_gid, BCAST_QPN);
185         tprintf("modify_av_params() success");
186         ib_data.bcast_av = av;
187
188 #if ! CREATE_OWN
189         rc = create_ipoib_qp(&ib_data.ipoib_qp,
190                              &ib_data.ipoib_snd_cq,
191                              &ib_data.ipoib_rcv_cq, qkey);
192         if (rc) {
193                 eprintf("");
194                 return rc;
195         }
196
197         tprintf("create_ipoib_qp() success");
198         *ipoib_qph_p = ib_data.ipoib_qp;
199 #endif
200
201         do {
202                 rc = poll_eq(&ib_eqe, &num_eqe);
203                 if (rc) {
204                         eprintf("");
205                         return -1;
206                 }
207                 if (num_eqe) {
208                         tprintf("num_eqe=%d", num_eqe);
209                 }
210                 tprintf("num_eqe=%d", num_eqe);
211         } while (num_eqe);
212         tprintf("eq is drained");
213
214         clear_interrupt();
215
216         return rc;
217 }
218
219 static int ib_driver_close(int fw_fatal)
220 {
221         int rc, ret = 0;
222         __u32 qkey;
223         __u16 mlid;
224
225         rc = ib_device_close();
226         if (rc) {
227                 eprintf("ib_device_close() failed");
228                 ret = 1;
229         }
230
231         tprintf("");
232         if (!fw_fatal) {
233                 rc = join_mc_group(&qkey, &mlid, 0);
234                 if (rc) {
235                         eprintf("");
236                         ret = 1;
237                 }
238                 tprintf("join_mc_group(leave) success");
239
240                 rc = add_qp_to_mcast_group(ib_data.bcast_gid, 0);
241                 if (rc) {
242                         eprintf("");
243                         ret = 1;
244                 }
245                 tprintf("add_qp_to_mcast_group(remove) success");
246
247                 rc = cmd_close_ib(ib_data.port);
248                 if (rc) {
249                         eprintf("");
250                         ret = 1;
251                 }
252                 tprintf("cmd_close_ib(%d) success", ib_data.port);
253
254                 if (destroy_udqp(ib_data.mads_qp)) {
255                         eprintf("");
256                         ret = 1;
257                 }
258
259                 if (destroy_udqp(ib_data.ipoib_qp)) {
260                         eprintf("");
261                         ret = 1;
262                 }
263         }
264
265         rc = cmd_close_hca(fw_fatal);
266         if (rc) {
267                 eprintf("");
268                 ret = 1;
269         }
270
271         rc = unset_hca();
272         if (rc) {
273                 eprintf("");
274                 ret = 1;
275         }
276
277         return ret;
278 }
279
280 static int poll_cqe_tout(cq_t cqh, __u16 tout, void **wqe, int *good_p)
281 {
282         int rc;
283         struct ib_cqe_st ib_cqe;
284         __u8 num_cqes;
285         unsigned long end;
286
287         end = currticks() + tout;
288         do {
289                 rc = ib_poll_cqx(cqh, &ib_cqe, &num_cqes);
290                 if (rc)
291                         return rc;
292
293                 if (num_cqes == 1) {
294                         if (good_p) {
295                                 *good_p = ib_cqe.is_error ? 0 : 1;
296                         }
297                         if (wqe)
298                                 *wqe = ib_cqe.wqe;
299                         return 0;
300                 }
301         }
302         while (currticks() < end);
303
304         return -1;
305 }
306
307 static u8 *get_port_gid(void)
308 {
309         return ib_data.port_gid.raw;
310 }
311
312 static __u32 ib_get_qpn(udqp_t qph)
313 {
314         __u32 qpn;
315
316         qpn = dev_get_qpn(qph);
317
318         return qpn;
319 }
320
321 static int drain_eq(void)
322 {
323         __u8 num_eqe = 0, tot_eqe = 0;
324         int rc;
325
326         do {
327                 tot_eqe += num_eqe;
328                 rc = poll_eq(ib_data.eq, &num_eqe);
329                 if (rc) {
330                         eprintf("");
331                         return -1;
332                 }
333
334                 tprintf("num_eqe=%d", num_eqe);
335         } while (num_eqe);
336         tprintf("eq is drained");
337         if (tot_eqe) {
338                 tprintf("got %d eqes", tot_eqe);
339                 return -1;
340         }
341
342         return 0;
343 }
344
345
346 static int poll_error_buf(void)
347 {
348         __u32 *ptr= dev_ib_data.error_buf_addr;
349         __u32 i;
350
351         for (i=0; i<dev_ib_data.error_buf_size; ++i, ptr++) {
352                 if ( readl(ptr) ) {
353                         return -1;
354                 }
355         }
356
357         return 0;
358 }
359
360