Committed patch from Eli Cohen for Mellanox Technologies Infiniband cards
[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         rc = wait_logic_link_up(port);
94         if (rc)
95                 return rc;
96
97         tprintf("wait_logic_link_up() success");
98
99         rc = get_guid_info(&status);
100         if (rc) {
101                 eprintf("");
102                 return rc;
103         } else if (status) {
104                 eprintf("");
105                 return rc;
106         }
107
108         tprintf("get_guid_info() success");
109
110         rc = get_pkey_tbl(NULL, &status);
111         if (rc) {
112                 eprintf("");
113                 return rc;
114         } else if (status) {
115                 eprintf("");
116                 return rc;
117         }
118         rc = create_mads_qp(&ib_data.mads_qp,
119                             &ib_data.mads_snd_cq, &ib_data.mads_rcv_cq);
120         if (rc) {
121                 eprintf("");
122                 return rc;
123         }
124
125         tprintf("attempt to join mcast group ...");
126         rc = join_mc_group(&qkey, &mlid, 1);
127         if (rc) {
128                 eprintf("");
129                 return rc;
130         } else {
131                 tprintf("join_mc_group() successfull qkey=0x%lx, mlid=0x%x",
132                         qkey, mlid);
133         }
134
135         rc = create_ipoib_qp(&ib_data.ipoib_qp,
136                              &ib_data.ipoib_snd_cq,
137                              &ib_data.ipoib_rcv_cq, qkey);
138         if (rc) {
139                 eprintf("");
140                 return rc;
141         }
142
143         tprintf("create_ipoib_qp() success");
144         *ipoib_qph_p = ib_data.ipoib_qp;
145
146         tprintf("register qp to receive mcast...");
147         rc = add_qp_to_mcast_group(ib_data.bcast_gid, 1);
148         if (rc) {
149                 eprintf("");
150                 return rc;
151         } else {
152                 tprintf("add_qp_to_mcast_group() success");
153         }
154
155         /* create a broadcast group ud AV */
156         av = alloc_ud_av();
157         if (!av) {
158                 eprintf("");
159                 return -1;
160         }
161         tprintf("alloc_ud_av() success");
162         modify_av_params(av, mlid, 1, 0, 0, &ib_data.bcast_gid, BCAST_QPN);
163         tprintf("modify_av_params() success");
164         ib_data.bcast_av = av;
165
166         do {
167                 rc = poll_eq(&ib_eqe, &num_eqe);
168                 if (rc) {
169                         eprintf("");
170                         return -1;
171                 }
172                 if (num_eqe) {
173                         tprintf("num_eqe=%d", num_eqe);
174                 }
175                 tprintf("num_eqe=%d", num_eqe);
176         } while (num_eqe);
177         tprintf("eq is drained");
178
179         clear_interrupt();
180
181         return rc;
182 }
183
184 static int ib_driver_close(int fw_fatal)
185 {
186         int rc, ret = 0;
187         __u32 qkey;
188         __u16 mlid;
189
190         rc = ib_device_close();
191         if (rc) {
192                 eprintf("ib_device_close() failed");
193                 ret = 1;
194         }
195
196         tprintf("");
197         if (!fw_fatal) {
198                 rc = join_mc_group(&qkey, &mlid, 0);
199                 if (rc) {
200                         eprintf("");
201                         ret = 1;
202                 }
203                 tprintf("join_mc_group(leave) success");
204
205                 rc = add_qp_to_mcast_group(ib_data.bcast_gid, 0);
206                 if (rc) {
207                         eprintf("");
208                         ret = 1;
209                 }
210                 tprintf("add_qp_to_mcast_group(remove) success");
211
212                 rc = cmd_close_ib(ib_data.port);
213                 if (rc) {
214                         eprintf("");
215                         ret = 1;
216                 }
217                 tprintf("cmd_close_ib(%d) success", ib_data.port);
218
219                 if (destroy_udqp(ib_data.mads_qp)) {
220                         eprintf("");
221                         ret = 1;
222                 }
223
224                 if (destroy_udqp(ib_data.ipoib_qp)) {
225                         eprintf("");
226                         ret = 1;
227                 }
228         }
229
230         rc = cmd_close_hca(fw_fatal);
231         if (rc) {
232                 eprintf("");
233                 ret = 1;
234         }
235
236         if (!fw_fatal) {
237                 rc = cmd_sys_dis();
238                 if (rc) {
239                         eprintf("");
240                         ret = 1;
241                 }
242         }
243
244         return ret;
245 }
246
247 static int poll_cqe_tout(cq_t cqh, __u16 tout, void **wqe, int *good_p)
248 {
249         int rc;
250         struct ib_cqe_st ib_cqe;
251         __u8 num_cqes;
252         unsigned long end;
253
254         end = currticks() + tout;
255         do {
256                 rc = ib_poll_cq(cqh, &ib_cqe, &num_cqes);
257                 if (rc)
258                         return rc;
259
260                 if (num_cqes == 1) {
261                         if (good_p) {
262                                 *good_p = ib_cqe.is_error ? 0 : 1;
263                         }
264                         if (wqe)
265                                 *wqe = ib_cqe.wqe;
266                         return 0;
267                 }
268         }
269         while (currticks() < end);
270
271         return -1;
272 }
273
274 static u8 *get_port_gid(void)
275 {
276         return ib_data.port_gid.raw;
277 }
278
279 static __u32 ib_get_qpn(udqp_t qph)
280 {
281         __u32 qpn;
282
283         qpn = dev_get_qpn(qph);
284
285         return qpn;
286 }
287
288 static int drain_eq(void)
289 {
290         __u8 num_eqe = 0, tot_eqe = 0;
291         int rc;
292
293         do {
294                 tot_eqe += num_eqe;
295                 rc = poll_eq(ib_data.eq, &num_eqe);
296                 if (rc) {
297                         eprintf("");
298                         return -1;
299                 }
300
301                 tprintf("num_eqe=%d", num_eqe);
302         } while (num_eqe);
303         tprintf("eq is drained");
304         if (tot_eqe) {
305                 tprintf("got %d eqes", tot_eqe);
306                 return -1;
307         }
308
309         return 0;
310 }
311
312
313 static int poll_error_buf(void)
314 {
315         __u32 *ptr= dev_ib_data.error_buf_addr;
316         __u32 i;
317
318         for (i=0; i<dev_ib_data.error_buf_size; ++i, ptr++) {
319                 if ( readl(ptr) ) {
320                         return -1;
321                 }
322         }
323
324         return 0;
325 }
326
327