fix cleanup flow for memfree devices
[etherboot.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 static int ib_driver_init(struct pci_device *pci, udqp_t * ipoib_qph_p)
66 {
67         int rc;
68         __u8 port;
69         __u16 status;
70         __u32 qkey;
71         __u16 mlid;
72         ud_av_t av;
73         struct ib_eqe_st ib_eqe;
74         __u8 num_eqe;
75
76         tprintf("");
77         rc = ib_device_init(pci);
78         if (rc)
79                 return rc;
80
81         tprintf("");
82
83         memcpy(ib_data.bcast_gid.raw, ipv4_bcast_gid, sizeof(ipv4_bcast_gid));
84
85         port = PXE_IB_PORT;
86         rc = setup_hca(port, &ib_data.eq);
87         if (rc)
88                 return rc;
89         tprintf("setup_hca() success");
90
91         ib_data.port = port;
92
93         if(print_info)
94                 printf("boot port = %d\n", ib_data.port);
95
96         rc = wait_logic_link_up(port);
97         if (rc)
98                 return rc;
99
100         tprintf("wait_logic_link_up() success");
101
102         rc = get_guid_info(&status);
103         if (rc) {
104                 eprintf("");
105                 return rc;
106         } else if (status) {
107                 eprintf("");
108                 return rc;
109         }
110
111         tprintf("get_guid_info() success");
112
113         /* this to flush stdout that contains previous chars */
114         printf("    \n");
115         if(print_info) {
116                 __u8 *gid=ib_data.port_gid.raw;
117
118                 printf("\n");
119                 printf("port GID=%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:"
120                        "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\n",
121                        gid[0],gid[1],gid[2],gid[3],gid[4],gid[5],gid[6],gid[7],
122                        gid[8],gid[9],gid[10],gid[11],gid[12],gid[13],gid[14],gid[15]);
123         }
124
125         rc = get_pkey_tbl(NULL, &status);
126         if (rc) {
127                 eprintf("");
128                 return rc;
129         } else if (status) {
130                 eprintf("");
131                 return rc;
132         }
133         rc = create_mads_qp(&ib_data.mads_qp,
134                             &ib_data.mads_snd_cq, &ib_data.mads_rcv_cq);
135         if (rc) {
136                 eprintf("");
137                 return rc;
138         }
139
140         tprintf("attempt to join mcast group ...");
141         rc = join_mc_group(&qkey, &mlid, 1);
142         if (rc) {
143                 eprintf("");
144                 return rc;
145         } else {
146                 tprintf("join_mc_group() successfull qkey=0x%lx, mlid=0x%x",
147                         qkey, mlid);
148         }
149
150         rc = create_ipoib_qp(&ib_data.ipoib_qp,
151                              &ib_data.ipoib_snd_cq,
152                              &ib_data.ipoib_rcv_cq, qkey);
153         if (rc) {
154                 eprintf("");
155                 return rc;
156         }
157
158         tprintf("create_ipoib_qp() success");
159         *ipoib_qph_p = ib_data.ipoib_qp;
160
161         tprintf("register qp to receive mcast...");
162         rc = add_qp_to_mcast_group(ib_data.bcast_gid, 1);
163         if (rc) {
164                 eprintf("");
165                 return rc;
166         } else {
167                 tprintf("add_qp_to_mcast_group() success");
168         }
169
170         /* create a broadcast group ud AV */
171         av = alloc_ud_av();
172         if (!av) {
173                 eprintf("");
174                 return -1;
175         }
176         tprintf("alloc_ud_av() success");
177         modify_av_params(av, mlid, 1, 0, 0, &ib_data.bcast_gid, BCAST_QPN);
178         tprintf("modify_av_params() success");
179         ib_data.bcast_av = av;
180
181         do {
182                 rc = poll_eq(&ib_eqe, &num_eqe);
183                 if (rc) {
184                         eprintf("");
185                         return -1;
186                 }
187                 if (num_eqe) {
188                         tprintf("num_eqe=%d", num_eqe);
189                 }
190                 tprintf("num_eqe=%d", num_eqe);
191         } while (num_eqe);
192         tprintf("eq is drained");
193
194         clear_interrupt();
195
196         return rc;
197 }
198
199 static int ib_driver_close(int fw_fatal)
200 {
201         int rc, ret = 0;
202         __u32 qkey;
203         __u16 mlid;
204
205         rc = ib_device_close();
206         if (rc) {
207                 eprintf("ib_device_close() failed");
208                 ret = 1;
209         }
210
211         tprintf("");
212         if (!fw_fatal) {
213                 rc = join_mc_group(&qkey, &mlid, 0);
214                 if (rc) {
215                         eprintf("");
216                         ret = 1;
217                 }
218                 tprintf("join_mc_group(leave) success");
219
220                 rc = add_qp_to_mcast_group(ib_data.bcast_gid, 0);
221                 if (rc) {
222                         eprintf("");
223                         ret = 1;
224                 }
225                 tprintf("add_qp_to_mcast_group(remove) success");
226
227                 rc = cmd_close_ib(ib_data.port);
228                 if (rc) {
229                         eprintf("");
230                         ret = 1;
231                 }
232                 tprintf("cmd_close_ib(%d) success", ib_data.port);
233
234                 if (destroy_udqp(ib_data.mads_qp)) {
235                         eprintf("");
236                         ret = 1;
237                 }
238
239                 if (destroy_udqp(ib_data.ipoib_qp)) {
240                         eprintf("");
241                         ret = 1;
242                 }
243         }
244
245         rc = cmd_close_hca(fw_fatal);
246         if (rc) {
247                 eprintf("");
248                 ret = 1;
249         }
250
251         rc = unset_hca();
252         if (rc) {
253                 eprintf("");
254                 ret = 1;
255         }
256
257         return ret;
258 }
259
260 static int poll_cqe_tout(cq_t cqh, __u16 tout, void **wqe, int *good_p)
261 {
262         int rc;
263         struct ib_cqe_st ib_cqe;
264         __u8 num_cqes;
265         unsigned long end;
266
267         end = currticks() + tout;
268         do {
269                 rc = ib_poll_cq(cqh, &ib_cqe, &num_cqes);
270                 if (rc)
271                         return rc;
272
273                 if (num_cqes == 1) {
274                         if (good_p) {
275                                 *good_p = ib_cqe.is_error ? 0 : 1;
276                         }
277                         if (wqe)
278                                 *wqe = ib_cqe.wqe;
279                         return 0;
280                 }
281         }
282         while (currticks() < end);
283
284         return -1;
285 }
286
287 static u8 *get_port_gid(void)
288 {
289         return ib_data.port_gid.raw;
290 }
291
292 static __u32 ib_get_qpn(udqp_t qph)
293 {
294         __u32 qpn;
295
296         qpn = dev_get_qpn(qph);
297
298         return qpn;
299 }
300
301 static int drain_eq(void)
302 {
303         __u8 num_eqe = 0, tot_eqe = 0;
304         int rc;
305
306         do {
307                 tot_eqe += num_eqe;
308                 rc = poll_eq(ib_data.eq, &num_eqe);
309                 if (rc) {
310                         eprintf("");
311                         return -1;
312                 }
313
314                 tprintf("num_eqe=%d", num_eqe);
315         } while (num_eqe);
316         tprintf("eq is drained");
317         if (tot_eqe) {
318                 tprintf("got %d eqes", tot_eqe);
319                 return -1;
320         }
321
322         return 0;
323 }
324
325
326 static int poll_error_buf(void)
327 {
328         __u32 *ptr= dev_ib_data.error_buf_addr;
329         __u32 i;
330
331         for (i=0; i<dev_ib_data.error_buf_size; ++i, ptr++) {
332                 if ( readl(ptr) ) {
333                         return -1;
334                 }
335         }
336
337         return 0;
338 }
339
340