[image] Allow for zero embedded images
[people/asdlkf/gpxe.git] / src / drivers / net / mlx_ipoib / cmdif_comm.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 "cmdif.h"
23 #include "cmdif_comm.h"
24 #include "cmdif_priv.h"
25
26 static int cmdif_is_free(int *is_free)
27 {
28         int rc;
29         __u32 result;
30
31         rc = gw_read_cr(HCR_OFFSET_GO, &result);
32         if (rc) {
33                 eprintf("");
34                 return rc;
35         }
36         *is_free = (result & 0x800000) == 0;
37
38         return 0;
39 }
40
41 static void edit_hcr(command_fields_t * cmd_prms, __u32 * buf)
42 {
43         unsigned int i;
44
45         switch (cmd_prms->in_trans) {
46         case TRANS_NA:
47                 /* note! since these are zeroes I do not bother to deal with endianess */
48                 buf[0] = 0;
49                 buf[1] = 0;
50                 break;
51
52         case TRANS_IMMEDIATE:
53                 buf[0] = cmd_prms->in_param[0];
54                 buf[1] = cmd_prms->in_param[1];
55                 break;
56
57         case TRANS_MAILBOX:
58                 buf[0] = 0;
59                 buf[1] = virt_to_bus(cmd_prms->in_param);
60
61                 for (i = 0; i < cmd_prms->in_param_size; i += 4)
62                         cmd_prms->in_param[i >> 2] =
63                             cpu_to_be32(cmd_prms->in_param[i >> 2]);
64                 break;
65         }
66
67         buf[2] = cmd_prms->input_modifier;
68
69         switch (cmd_prms->out_trans) {
70         case TRANS_NA:
71                 /* note! since these are zeroes I do not bother to deal with endianess */
72                 buf[3] = 0;
73                 buf[4] = 0;
74                 break;
75
76         case TRANS_IMMEDIATE:
77                 break;
78         case TRANS_MAILBOX:
79                 buf[3] = 0;
80                 buf[4] = virt_to_bus(cmd_prms->out_param);
81                 break;
82         }
83
84         buf[5] = 0;             /* token is always 0 */
85         buf[6] = cmd_prms->opcode |     /* opcode */
86             0x800000 |          /* go bit */
87             ((cmd_prms->opcode_modifier & 0xf) << 12);  /* opcode modifier 
88 */ }
89
90 static int wait_cmdif_free(void)
91 {
92         int ret, is_free;
93         unsigned int i, relax_time = 1, max_time = 5000;
94
95         /* wait until go bit is free */
96         for (i = 0; i < max_time; i += relax_time) {
97                 ret = cmdif_is_free(&is_free);
98                 if (ret)
99                         return ret;
100                 if (is_free)
101                         break;
102                 mdelay(relax_time);
103         }
104         if (i >= max_time)
105                 return -1;
106         return 0;
107 }
108
109 static XHH_cmd_status_t cmd_invoke(command_fields_t * cmd_prms)
110 {
111         int ret, is_free, i;
112         __u32 hcr[7], data;
113         __u8 status;
114
115         /* check if go bit is free */
116         ret = cmdif_is_free(&is_free);
117         if (ret) {
118                 eprintf("");
119                 return -1;
120         }
121
122         __asm__ __volatile__("":::"memory");
123         /* it must be free */
124         if (!is_free) {
125                 eprintf("");
126                 return -1;
127         }
128         __asm__ __volatile__("":::"memory");
129         edit_hcr(cmd_prms, hcr);
130         __asm__ __volatile__("":::"memory");
131
132         for (i = 0; i < 7; ++i) {
133                 ret = gw_write_cr(HCR_BASE + i * 4, hcr[i]);
134                 if (ret) {
135                         eprintf("");
136                         return -1;
137                 }
138         }
139
140         __asm__ __volatile__("":::"memory");
141         /* wait for completion */
142         ret = wait_cmdif_free();
143         if (ret) {
144                 eprintf("");
145                 return -1;
146         }
147
148         __asm__ __volatile__("":::"memory");
149         ret = gw_read_cr(HCR_OFFSET_STATUS, &data);
150         if (ret) {
151                 eprintf("");
152                 return -1;
153         }
154
155         status = data >> 24;
156
157         if (status) {
158                 tprintf("status=0x%x", status);
159                 return status;
160         }
161
162         if (cmd_prms->out_trans == TRANS_MAILBOX)
163                 be_to_cpu_buf(cmd_prms->out_param, cmd_prms->out_param_size);
164         else if (cmd_prms->out_trans == TRANS_IMMEDIATE) {
165                 if (gw_read_cr(HCR_OFFSET_OUTPRM_H, &cmd_prms->out_param[0]))
166                         return -1;
167                 if (gw_read_cr(HCR_OFFSET_OUTPRM_L, &cmd_prms->out_param[1]))
168                         return -1;
169         }
170
171         return 0;
172 }
173
174 /*************************************************
175                                         commands
176 *************************************************/
177
178 /*
179  *  cmd_close_hca
180  */
181 static int cmd_close_hca(int panic)
182 {
183         int rc;
184         command_fields_t cmd_desc;
185
186         memset(&cmd_desc, 0, sizeof cmd_desc);
187         cmd_desc.opcode = XDEV_CMD_CLOSE_HCA;
188         cmd_desc.opcode_modifier= panic;
189         rc = cmd_invoke(&cmd_desc);
190
191         return rc;
192 }
193
194 /*
195  *  cmd_init_hca
196  */
197 static int cmd_init_hca(__u32 * inprm, __u32 in_prm_size)
198 {
199         int rc;
200
201         command_fields_t cmd_desc;
202
203         memset(&cmd_desc, 0, sizeof cmd_desc);
204         cmd_desc.in_trans = TRANS_MAILBOX;
205         cmd_desc.opcode = XDEV_CMD_INIT_HCA;
206         cmd_desc.in_param = inprm;
207         cmd_desc.in_param_size = in_prm_size;
208
209         rc = cmd_invoke(&cmd_desc);
210
211         return rc;
212 }
213
214 /*
215  *  cmd_sw2hw_eq
216  */
217 static int cmd_sw2hw_eq(__u32 inprm_sz)
218 {
219         int rc;
220         command_fields_t cmd_desc;
221         void *inprm;
222
223         memset(&cmd_desc, 0, sizeof cmd_desc);
224
225         inprm = get_inprm_buf();
226         cmd_desc.in_trans = TRANS_MAILBOX;
227         cmd_desc.opcode = XDEV_CMD_SW2HW_EQ;
228         cmd_desc.in_param = inprm;
229         cmd_desc.in_param_size = inprm_sz;
230
231         rc = cmd_invoke(&cmd_desc);
232
233         return rc;
234 }
235
236 /*
237  *  cmd_hw2sw_eq
238  */
239 static int cmd_hw2sw_eq(__u8 eqn)
240 {
241         int rc;
242         command_fields_t cmd_desc;
243         void *outprm;
244
245         memset(&cmd_desc, 0, sizeof cmd_desc);
246
247         outprm = get_outprm_buf();
248         cmd_desc.opcode = XDEV_CMD_HW2SW_EQ;
249         cmd_desc.input_modifier = eqn;
250         cmd_desc.out_trans = TRANS_MAILBOX;
251         cmd_desc.out_param = outprm;
252         cmd_desc.out_param_size = 0x40;
253         rc = cmd_invoke(&cmd_desc);
254
255         return rc;
256 }
257
258 /*
259  *  cmd_map_eq
260  */
261 static int cmd_map_eq(__u8 eqn, __u32 mask, int map)
262 {
263         int rc;
264         command_fields_t cmd_desc;
265         __u32 *inprm;
266
267         memset(&cmd_desc, 0, sizeof cmd_desc);
268
269         inprm = get_inprm_buf();
270
271         inprm[1] = mask;
272         inprm[0] = 0;
273
274         cmd_desc.opcode = XDEV_CMD_MAP_EQ;
275         cmd_desc.in_trans = TRANS_IMMEDIATE;
276         cmd_desc.in_param = inprm;
277         cmd_desc.input_modifier = ((map ? 0 : 1) << 31) | eqn;
278
279         rc = cmd_invoke(&cmd_desc);
280
281         return rc;
282 }
283
284 /*
285  *  cmd_sw2hw_mpt
286  */
287 static int cmd_sw2hw_mpt(__u32 * lkey, __u32 in_key, __u32 * inprm,
288                          __u32 inprm_sz)
289 {
290         int rc;
291         command_fields_t cmd_desc;
292
293         memset(&cmd_desc, 0, sizeof cmd_desc);
294         cmd_desc.in_trans = TRANS_MAILBOX;
295         cmd_desc.opcode = XDEV_CMD_SW2HW_MPT;
296         cmd_desc.input_modifier = in_key & MKEY_IDX_MASK;       /* only one MR for the whole driver */
297         cmd_desc.in_param = inprm;
298         cmd_desc.in_param_size = inprm_sz;
299
300         rc = cmd_invoke(&cmd_desc);
301         if (!rc)
302                 *lkey = in_key;
303
304         return rc;
305 }
306
307 /*
308  *  cmd_hw2sw_mpt
309  */
310 static int cmd_hw2sw_mpt(__u32 key)
311 {
312         int rc;
313         command_fields_t cmd_desc;
314
315         memset(&cmd_desc, 0, sizeof cmd_desc);
316         cmd_desc.opcode = XDEV_CMD_HW2SW_MPT;
317         cmd_desc.input_modifier = key & MKEY_IDX_MASK;
318         cmd_desc.opcode_modifier = 1;
319
320         rc = cmd_invoke(&cmd_desc);
321
322         return rc;
323 }
324
325 /*
326  *  cmd_init_ib
327  */
328 static int cmd_init_ib(__u32 port, __u32 * inprm, __u32 inprm_sz)
329 {
330         int rc;
331         command_fields_t cmd_desc;
332
333         memset(&cmd_desc, 0, sizeof cmd_desc);
334         cmd_desc.opcode = XDEV_CMD_INIT_IB;
335         cmd_desc.input_modifier = port;
336         cmd_desc.in_trans = TRANS_MAILBOX;
337         cmd_desc.in_param = inprm;
338         cmd_desc.in_param_size = inprm_sz;
339
340         rc = cmd_invoke(&cmd_desc);
341
342         return rc;
343 }
344
345 /*
346  *  cmd_close_ib
347  */
348 static int cmd_close_ib(__u32 port)
349 {
350         int rc;
351         command_fields_t cmd_desc;
352
353         memset(&cmd_desc, 0, sizeof cmd_desc);
354         cmd_desc.opcode = XDEV_CMD_CLOSE_IB;
355         cmd_desc.input_modifier = port;
356
357         rc = cmd_invoke(&cmd_desc);
358
359         return rc;
360 }
361
362 /*
363  *  cmd_sw2hw_cq
364  */
365 static int cmd_sw2hw_cq(__u32 cqn, __u32 * inprm, __u32 inprm_sz)
366 {
367         int rc;
368         command_fields_t cmd_desc;
369
370         memset(&cmd_desc, 0, sizeof cmd_desc);
371         cmd_desc.opcode = XDEV_CMD_SW2HW_CQ;
372         cmd_desc.in_trans = TRANS_MAILBOX;
373         cmd_desc.in_param = inprm;
374         cmd_desc.in_param_size = inprm_sz;
375         cmd_desc.input_modifier = cqn;
376
377         rc = cmd_invoke(&cmd_desc);
378
379         return rc;
380 }
381
382 /*
383  *  cmd_hw2sw_cq
384  */
385 static int cmd_hw2sw_cq(__u32 cqn)
386 {
387         int rc;
388         command_fields_t cmd_desc;
389
390         memset(&cmd_desc, 0, sizeof cmd_desc);
391         cmd_desc.opcode = XDEV_CMD_HW2SW_CQ;
392         cmd_desc.input_modifier = cqn;
393         cmd_desc.out_trans = TRANS_MAILBOX;
394         cmd_desc.out_param = get_outprm_buf();
395
396         rc = cmd_invoke(&cmd_desc);
397
398         return rc;
399 }
400
401 /*
402  *  cmd_rst2init_qpee
403  */
404 static int cmd_rst2init_qpee(__u32 qpn, __u32 * inprm, __u32 inprm_sz)
405 {
406         int rc;
407         command_fields_t cmd_desc;
408
409         memset(&cmd_desc, 0, sizeof cmd_desc);
410         cmd_desc.opcode = XDEV_CMD_RST2INIT_QPEE;
411         cmd_desc.in_trans = TRANS_MAILBOX;
412         cmd_desc.in_param = inprm;
413         cmd_desc.in_param_size = inprm_sz;
414         cmd_desc.input_modifier = qpn;
415
416         rc = cmd_invoke(&cmd_desc);
417
418         return rc;
419 }
420
421 /*
422  *  cmd_init2rtr_qpee
423  */
424 static int cmd_init2rtr_qpee(__u32 qpn, __u32 * inprm, __u32 inprm_sz)
425 {
426         int rc;
427         command_fields_t cmd_desc;
428
429         memset(&cmd_desc, 0, sizeof cmd_desc);
430         cmd_desc.opcode = XDEV_CMD_INIT2RTR_QPEE;
431         cmd_desc.in_trans = TRANS_MAILBOX;
432         cmd_desc.in_param = inprm;
433         cmd_desc.in_param_size = inprm_sz;
434         cmd_desc.input_modifier = qpn;;
435
436         rc = cmd_invoke(&cmd_desc);
437
438         return rc;
439 }
440
441 /*
442  *  cmd_rtr2rts_qpee
443  */
444 static int cmd_rtr2rts_qpee(__u32 qpn, __u32 * inprm, __u32 inprm_sz)
445 {
446         int rc;
447         command_fields_t cmd_desc;
448
449         memset(&cmd_desc, 0, sizeof cmd_desc);
450         cmd_desc.opcode = XDEV_CMD_RTR2RTS_QPEE;
451         cmd_desc.in_trans = TRANS_MAILBOX;
452         cmd_desc.in_param = inprm;
453         cmd_desc.in_param_size = inprm_sz;
454         cmd_desc.input_modifier = qpn;
455
456         rc = cmd_invoke(&cmd_desc);
457
458         return rc;
459 }
460
461 /*
462  *  cmd_2rst_qpee
463  */
464 static int cmd_2rst_qpee(__u32 qpn)
465 {
466         int rc;
467         command_fields_t cmd_desc;
468
469         memset(&cmd_desc, 0, sizeof cmd_desc);
470         cmd_desc.opcode = XDEV_CMD_ERR2RST_QPEE;
471         cmd_desc.opcode_modifier = 0;
472         cmd_desc.input_modifier = qpn;
473         cmd_desc.out_trans = TRANS_MAILBOX;
474         cmd_desc.out_param = get_outprm_buf();
475
476         rc = cmd_invoke(&cmd_desc);
477
478         return rc;
479 }
480
481 /*
482  *  cmd_2err_qpee
483  */
484 static int cmd_2err_qpee(__u32 qpn)
485 {
486         int rc;
487         command_fields_t cmd_desc;
488
489         memset(&cmd_desc, 0, sizeof cmd_desc);
490         cmd_desc.opcode = XDEV_CMD_2ERR_QPEE;
491         cmd_desc.input_modifier = qpn;
492
493         rc = cmd_invoke(&cmd_desc);
494
495         return rc;
496 }
497
498 /*
499  *  cmd_post_doorbell
500  */
501 static int cmd_post_doorbell(void *inprm, __u32 offset)
502 {
503         int rc;
504         command_fields_t cmd_desc;
505
506         memset(&cmd_desc, 0, sizeof cmd_desc);
507         cmd_desc.opcode = XDEV_CMD_POST_DOORBELL;
508         cmd_desc.in_trans = TRANS_IMMEDIATE;
509         cmd_desc.in_param = inprm;
510         cmd_desc.input_modifier = offset;
511         if (0) {
512                 rc = cmd_invoke(&cmd_desc);
513         } else {
514                 dev_post_dbell(inprm, offset);
515                 rc = 0;
516         }
517
518         return rc;
519 }
520
521 static int cmd_mad_ifc(void *inprm, struct ib_mad_st *mad, __u8 port)
522 {
523         int rc;
524         command_fields_t cmd_desc;
525
526         memset(&cmd_desc, 0, sizeof cmd_desc);
527         cmd_desc.opcode = XDEV_CMD_MAD_IFC;
528         cmd_desc.opcode_modifier = 1;   /* no mkey/bkey validation */
529         cmd_desc.input_modifier = port;
530         cmd_desc.in_trans = TRANS_MAILBOX;
531         cmd_desc.in_param_size = 256;
532         cmd_desc.in_param = (__u32 *) inprm;
533         cmd_desc.out_trans = TRANS_MAILBOX;
534         cmd_desc.out_param = (__u32 *) mad;
535         cmd_desc.out_param_size = 256;
536         rc = cmd_invoke(&cmd_desc);
537
538         return rc;
539 }
540
541 static int cmd_mgid_hash(__u8 * gid, __u16 * mgid_hash_p)
542 {
543         int rc;
544         command_fields_t cmd_desc;
545         __u16 result[2];
546
547         memset(&cmd_desc, 0, sizeof cmd_desc);
548
549         cmd_desc.opcode = XDEV_CMD_MGID_HASH;
550         cmd_desc.in_trans = TRANS_MAILBOX;
551         cmd_desc.in_param = (__u32 *) gid;
552         cmd_desc.in_param_size = 16;
553         cmd_desc.out_trans = TRANS_IMMEDIATE;
554
555         rc = cmd_invoke(&cmd_desc);
556         if (!rc) {
557                 rc = gw_read_cr(HCR_BASE + 16, (__u32 *) result);
558                 if (!rc) {
559                         *mgid_hash_p = result[0];
560                 }
561         }
562
563         return rc;
564 }