ASoC: fsl_ssi: remove explicit register defaults
[cascardo/linux.git] / drivers / infiniband / core / ud_header.c
1 /*
2  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
3  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  */
33
34 #include <linux/errno.h>
35 #include <linux/string.h>
36 #include <linux/export.h>
37 #include <linux/if_ether.h>
38 #include <linux/ip.h>
39
40 #include <rdma/ib_pack.h>
41
42 #define STRUCT_FIELD(header, field) \
43         .struct_offset_bytes = offsetof(struct ib_unpacked_ ## header, field),      \
44         .struct_size_bytes   = sizeof ((struct ib_unpacked_ ## header *) 0)->field, \
45         .field_name          = #header ":" #field
46
47 static const struct ib_field lrh_table[]  = {
48         { STRUCT_FIELD(lrh, virtual_lane),
49           .offset_words = 0,
50           .offset_bits  = 0,
51           .size_bits    = 4 },
52         { STRUCT_FIELD(lrh, link_version),
53           .offset_words = 0,
54           .offset_bits  = 4,
55           .size_bits    = 4 },
56         { STRUCT_FIELD(lrh, service_level),
57           .offset_words = 0,
58           .offset_bits  = 8,
59           .size_bits    = 4 },
60         { RESERVED,
61           .offset_words = 0,
62           .offset_bits  = 12,
63           .size_bits    = 2 },
64         { STRUCT_FIELD(lrh, link_next_header),
65           .offset_words = 0,
66           .offset_bits  = 14,
67           .size_bits    = 2 },
68         { STRUCT_FIELD(lrh, destination_lid),
69           .offset_words = 0,
70           .offset_bits  = 16,
71           .size_bits    = 16 },
72         { RESERVED,
73           .offset_words = 1,
74           .offset_bits  = 0,
75           .size_bits    = 5 },
76         { STRUCT_FIELD(lrh, packet_length),
77           .offset_words = 1,
78           .offset_bits  = 5,
79           .size_bits    = 11 },
80         { STRUCT_FIELD(lrh, source_lid),
81           .offset_words = 1,
82           .offset_bits  = 16,
83           .size_bits    = 16 }
84 };
85
86 static const struct ib_field eth_table[]  = {
87         { STRUCT_FIELD(eth, dmac_h),
88           .offset_words = 0,
89           .offset_bits  = 0,
90           .size_bits    = 32 },
91         { STRUCT_FIELD(eth, dmac_l),
92           .offset_words = 1,
93           .offset_bits  = 0,
94           .size_bits    = 16 },
95         { STRUCT_FIELD(eth, smac_h),
96           .offset_words = 1,
97           .offset_bits  = 16,
98           .size_bits    = 16 },
99         { STRUCT_FIELD(eth, smac_l),
100           .offset_words = 2,
101           .offset_bits  = 0,
102           .size_bits    = 32 },
103         { STRUCT_FIELD(eth, type),
104           .offset_words = 3,
105           .offset_bits  = 0,
106           .size_bits    = 16 }
107 };
108
109 static const struct ib_field vlan_table[]  = {
110         { STRUCT_FIELD(vlan, tag),
111           .offset_words = 0,
112           .offset_bits  = 0,
113           .size_bits    = 16 },
114         { STRUCT_FIELD(vlan, type),
115           .offset_words = 0,
116           .offset_bits  = 16,
117           .size_bits    = 16 }
118 };
119
120 static const struct ib_field ip4_table[]  = {
121         { STRUCT_FIELD(ip4, ver),
122           .offset_words = 0,
123           .offset_bits  = 0,
124           .size_bits    = 4 },
125         { STRUCT_FIELD(ip4, hdr_len),
126           .offset_words = 0,
127           .offset_bits  = 4,
128           .size_bits    = 4 },
129         { STRUCT_FIELD(ip4, tos),
130           .offset_words = 0,
131           .offset_bits  = 8,
132           .size_bits    = 8 },
133         { STRUCT_FIELD(ip4, tot_len),
134           .offset_words = 0,
135           .offset_bits  = 16,
136           .size_bits    = 16 },
137         { STRUCT_FIELD(ip4, id),
138           .offset_words = 1,
139           .offset_bits  = 0,
140           .size_bits    = 16 },
141         { STRUCT_FIELD(ip4, frag_off),
142           .offset_words = 1,
143           .offset_bits  = 16,
144           .size_bits    = 16 },
145         { STRUCT_FIELD(ip4, ttl),
146           .offset_words = 2,
147           .offset_bits  = 0,
148           .size_bits    = 8 },
149         { STRUCT_FIELD(ip4, protocol),
150           .offset_words = 2,
151           .offset_bits  = 8,
152           .size_bits    = 8 },
153         { STRUCT_FIELD(ip4, check),
154           .offset_words = 2,
155           .offset_bits  = 16,
156           .size_bits    = 16 },
157         { STRUCT_FIELD(ip4, saddr),
158           .offset_words = 3,
159           .offset_bits  = 0,
160           .size_bits    = 32 },
161         { STRUCT_FIELD(ip4, daddr),
162           .offset_words = 4,
163           .offset_bits  = 0,
164           .size_bits    = 32 }
165 };
166
167 static const struct ib_field udp_table[]  = {
168         { STRUCT_FIELD(udp, sport),
169           .offset_words = 0,
170           .offset_bits  = 0,
171           .size_bits    = 16 },
172         { STRUCT_FIELD(udp, dport),
173           .offset_words = 0,
174           .offset_bits  = 16,
175           .size_bits    = 16 },
176         { STRUCT_FIELD(udp, length),
177           .offset_words = 1,
178           .offset_bits  = 0,
179           .size_bits    = 16 },
180         { STRUCT_FIELD(udp, csum),
181           .offset_words = 1,
182           .offset_bits  = 16,
183           .size_bits    = 16 }
184 };
185
186 static const struct ib_field grh_table[]  = {
187         { STRUCT_FIELD(grh, ip_version),
188           .offset_words = 0,
189           .offset_bits  = 0,
190           .size_bits    = 4 },
191         { STRUCT_FIELD(grh, traffic_class),
192           .offset_words = 0,
193           .offset_bits  = 4,
194           .size_bits    = 8 },
195         { STRUCT_FIELD(grh, flow_label),
196           .offset_words = 0,
197           .offset_bits  = 12,
198           .size_bits    = 20 },
199         { STRUCT_FIELD(grh, payload_length),
200           .offset_words = 1,
201           .offset_bits  = 0,
202           .size_bits    = 16 },
203         { STRUCT_FIELD(grh, next_header),
204           .offset_words = 1,
205           .offset_bits  = 16,
206           .size_bits    = 8 },
207         { STRUCT_FIELD(grh, hop_limit),
208           .offset_words = 1,
209           .offset_bits  = 24,
210           .size_bits    = 8 },
211         { STRUCT_FIELD(grh, source_gid),
212           .offset_words = 2,
213           .offset_bits  = 0,
214           .size_bits    = 128 },
215         { STRUCT_FIELD(grh, destination_gid),
216           .offset_words = 6,
217           .offset_bits  = 0,
218           .size_bits    = 128 }
219 };
220
221 static const struct ib_field bth_table[]  = {
222         { STRUCT_FIELD(bth, opcode),
223           .offset_words = 0,
224           .offset_bits  = 0,
225           .size_bits    = 8 },
226         { STRUCT_FIELD(bth, solicited_event),
227           .offset_words = 0,
228           .offset_bits  = 8,
229           .size_bits    = 1 },
230         { STRUCT_FIELD(bth, mig_req),
231           .offset_words = 0,
232           .offset_bits  = 9,
233           .size_bits    = 1 },
234         { STRUCT_FIELD(bth, pad_count),
235           .offset_words = 0,
236           .offset_bits  = 10,
237           .size_bits    = 2 },
238         { STRUCT_FIELD(bth, transport_header_version),
239           .offset_words = 0,
240           .offset_bits  = 12,
241           .size_bits    = 4 },
242         { STRUCT_FIELD(bth, pkey),
243           .offset_words = 0,
244           .offset_bits  = 16,
245           .size_bits    = 16 },
246         { RESERVED,
247           .offset_words = 1,
248           .offset_bits  = 0,
249           .size_bits    = 8 },
250         { STRUCT_FIELD(bth, destination_qpn),
251           .offset_words = 1,
252           .offset_bits  = 8,
253           .size_bits    = 24 },
254         { STRUCT_FIELD(bth, ack_req),
255           .offset_words = 2,
256           .offset_bits  = 0,
257           .size_bits    = 1 },
258         { RESERVED,
259           .offset_words = 2,
260           .offset_bits  = 1,
261           .size_bits    = 7 },
262         { STRUCT_FIELD(bth, psn),
263           .offset_words = 2,
264           .offset_bits  = 8,
265           .size_bits    = 24 }
266 };
267
268 static const struct ib_field deth_table[] = {
269         { STRUCT_FIELD(deth, qkey),
270           .offset_words = 0,
271           .offset_bits  = 0,
272           .size_bits    = 32 },
273         { RESERVED,
274           .offset_words = 1,
275           .offset_bits  = 0,
276           .size_bits    = 8 },
277         { STRUCT_FIELD(deth, source_qpn),
278           .offset_words = 1,
279           .offset_bits  = 8,
280           .size_bits    = 24 }
281 };
282
283 __sum16 ib_ud_ip4_csum(struct ib_ud_header *header)
284 {
285         struct iphdr iph;
286
287         iph.ihl         = 5;
288         iph.version     = 4;
289         iph.tos         = header->ip4.tos;
290         iph.tot_len     = header->ip4.tot_len;
291         iph.id          = header->ip4.id;
292         iph.frag_off    = header->ip4.frag_off;
293         iph.ttl         = header->ip4.ttl;
294         iph.protocol    = header->ip4.protocol;
295         iph.check       = 0;
296         iph.saddr       = header->ip4.saddr;
297         iph.daddr       = header->ip4.daddr;
298
299         return ip_fast_csum((u8 *)&iph, iph.ihl);
300 }
301 EXPORT_SYMBOL(ib_ud_ip4_csum);
302
303 /**
304  * ib_ud_header_init - Initialize UD header structure
305  * @payload_bytes:Length of packet payload
306  * @lrh_present: specify if LRH is present
307  * @eth_present: specify if Eth header is present
308  * @vlan_present: packet is tagged vlan
309  * @grh_present: GRH flag (if non-zero, GRH will be included)
310  * @ip_version: if non-zero, IP header, V4 or V6, will be included
311  * @udp_present :if non-zero, UDP header will be included
312  * @immediate_present: specify if immediate data is present
313  * @header:Structure to initialize
314  */
315 int ib_ud_header_init(int     payload_bytes,
316                       int    lrh_present,
317                       int    eth_present,
318                       int    vlan_present,
319                       int    grh_present,
320                       int    ip_version,
321                       int    udp_present,
322                       int    immediate_present,
323                       struct ib_ud_header *header)
324 {
325         grh_present = grh_present && !ip_version;
326         memset(header, 0, sizeof *header);
327
328         /*
329          * UDP header without IP header doesn't make sense
330          */
331         if (udp_present && ip_version != 4 && ip_version != 6)
332                 return -EINVAL;
333
334         if (lrh_present) {
335                 u16 packet_length;
336
337                 header->lrh.link_version     = 0;
338                 header->lrh.link_next_header =
339                         grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
340                 packet_length = (IB_LRH_BYTES   +
341                                  IB_BTH_BYTES   +
342                                  IB_DETH_BYTES  +
343                                  (grh_present ? IB_GRH_BYTES : 0) +
344                                  payload_bytes  +
345                                  4              + /* ICRC     */
346                                  3) / 4;          /* round up */
347                 header->lrh.packet_length = cpu_to_be16(packet_length);
348         }
349
350         if (vlan_present)
351                 header->eth.type = cpu_to_be16(ETH_P_8021Q);
352
353         if (ip_version == 6 || grh_present) {
354                 header->grh.ip_version      = 6;
355                 header->grh.payload_length  =
356                         cpu_to_be16((IB_BTH_BYTES     +
357                                      IB_DETH_BYTES    +
358                                      payload_bytes    +
359                                      4                + /* ICRC     */
360                                      3) & ~3);          /* round up */
361                 header->grh.next_header     = udp_present ? IPPROTO_UDP : 0x1b;
362         }
363
364         if (ip_version == 4) {
365                 int udp_bytes = udp_present ? IB_UDP_BYTES : 0;
366
367                 header->ip4.ver = 4; /* version 4 */
368                 header->ip4.hdr_len = 5; /* 5 words */
369                 header->ip4.tot_len =
370                         cpu_to_be16(IB_IP4_BYTES   +
371                                      udp_bytes     +
372                                      IB_BTH_BYTES  +
373                                      IB_DETH_BYTES +
374                                      payload_bytes +
375                                      4);     /* ICRC     */
376                 header->ip4.protocol = IPPROTO_UDP;
377         }
378         if (udp_present && ip_version)
379                 header->udp.length =
380                         cpu_to_be16(IB_UDP_BYTES   +
381                                      IB_BTH_BYTES  +
382                                      IB_DETH_BYTES +
383                                      payload_bytes +
384                                      4);     /* ICRC     */
385
386         if (immediate_present)
387                 header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
388         else
389                 header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY;
390         header->bth.pad_count                = (4 - payload_bytes) & 3;
391         header->bth.transport_header_version = 0;
392
393         header->lrh_present = lrh_present;
394         header->eth_present = eth_present;
395         header->vlan_present = vlan_present;
396         header->grh_present = grh_present || (ip_version == 6);
397         header->ipv4_present = ip_version == 4;
398         header->udp_present = udp_present;
399         header->immediate_present = immediate_present;
400         return 0;
401 }
402 EXPORT_SYMBOL(ib_ud_header_init);
403
404 /**
405  * ib_ud_header_pack - Pack UD header struct into wire format
406  * @header:UD header struct
407  * @buf:Buffer to pack into
408  *
409  * ib_ud_header_pack() packs the UD header structure @header into wire
410  * format in the buffer @buf.
411  */
412 int ib_ud_header_pack(struct ib_ud_header *header,
413                       void                *buf)
414 {
415         int len = 0;
416
417         if (header->lrh_present) {
418                 ib_pack(lrh_table, ARRAY_SIZE(lrh_table),
419                         &header->lrh, buf + len);
420                 len += IB_LRH_BYTES;
421         }
422         if (header->eth_present) {
423                 ib_pack(eth_table, ARRAY_SIZE(eth_table),
424                         &header->eth, buf + len);
425                 len += IB_ETH_BYTES;
426         }
427         if (header->vlan_present) {
428                 ib_pack(vlan_table, ARRAY_SIZE(vlan_table),
429                         &header->vlan, buf + len);
430                 len += IB_VLAN_BYTES;
431         }
432         if (header->grh_present) {
433                 ib_pack(grh_table, ARRAY_SIZE(grh_table),
434                         &header->grh, buf + len);
435                 len += IB_GRH_BYTES;
436         }
437         if (header->ipv4_present) {
438                 ib_pack(ip4_table, ARRAY_SIZE(ip4_table),
439                         &header->ip4, buf + len);
440                 len += IB_IP4_BYTES;
441         }
442         if (header->udp_present) {
443                 ib_pack(udp_table, ARRAY_SIZE(udp_table),
444                         &header->udp, buf + len);
445                 len += IB_UDP_BYTES;
446         }
447
448         ib_pack(bth_table, ARRAY_SIZE(bth_table),
449                 &header->bth, buf + len);
450         len += IB_BTH_BYTES;
451
452         ib_pack(deth_table, ARRAY_SIZE(deth_table),
453                 &header->deth, buf + len);
454         len += IB_DETH_BYTES;
455
456         if (header->immediate_present) {
457                 memcpy(buf + len, &header->immediate_data, sizeof header->immediate_data);
458                 len += sizeof header->immediate_data;
459         }
460
461         return len;
462 }
463 EXPORT_SYMBOL(ib_ud_header_pack);
464
465 /**
466  * ib_ud_header_unpack - Unpack UD header struct from wire format
467  * @header:UD header struct
468  * @buf:Buffer to pack into
469  *
470  * ib_ud_header_pack() unpacks the UD header structure @header from wire
471  * format in the buffer @buf.
472  */
473 int ib_ud_header_unpack(void                *buf,
474                         struct ib_ud_header *header)
475 {
476         ib_unpack(lrh_table, ARRAY_SIZE(lrh_table),
477                   buf, &header->lrh);
478         buf += IB_LRH_BYTES;
479
480         if (header->lrh.link_version != 0) {
481                 printk(KERN_WARNING "Invalid LRH.link_version %d\n",
482                        header->lrh.link_version);
483                 return -EINVAL;
484         }
485
486         switch (header->lrh.link_next_header) {
487         case IB_LNH_IBA_LOCAL:
488                 header->grh_present = 0;
489                 break;
490
491         case IB_LNH_IBA_GLOBAL:
492                 header->grh_present = 1;
493                 ib_unpack(grh_table, ARRAY_SIZE(grh_table),
494                           buf, &header->grh);
495                 buf += IB_GRH_BYTES;
496
497                 if (header->grh.ip_version != 6) {
498                         printk(KERN_WARNING "Invalid GRH.ip_version %d\n",
499                                header->grh.ip_version);
500                         return -EINVAL;
501                 }
502                 if (header->grh.next_header != 0x1b) {
503                         printk(KERN_WARNING "Invalid GRH.next_header 0x%02x\n",
504                                header->grh.next_header);
505                         return -EINVAL;
506                 }
507                 break;
508
509         default:
510                 printk(KERN_WARNING "Invalid LRH.link_next_header %d\n",
511                        header->lrh.link_next_header);
512                 return -EINVAL;
513         }
514
515         ib_unpack(bth_table, ARRAY_SIZE(bth_table),
516                   buf, &header->bth);
517         buf += IB_BTH_BYTES;
518
519         switch (header->bth.opcode) {
520         case IB_OPCODE_UD_SEND_ONLY:
521                 header->immediate_present = 0;
522                 break;
523         case IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE:
524                 header->immediate_present = 1;
525                 break;
526         default:
527                 printk(KERN_WARNING "Invalid BTH.opcode 0x%02x\n",
528                        header->bth.opcode);
529                 return -EINVAL;
530         }
531
532         if (header->bth.transport_header_version != 0) {
533                 printk(KERN_WARNING "Invalid BTH.transport_header_version %d\n",
534                        header->bth.transport_header_version);
535                 return -EINVAL;
536         }
537
538         ib_unpack(deth_table, ARRAY_SIZE(deth_table),
539                   buf, &header->deth);
540         buf += IB_DETH_BYTES;
541
542         if (header->immediate_present)
543                 memcpy(&header->immediate_data, buf, sizeof header->immediate_data);
544
545         return 0;
546 }
547 EXPORT_SYMBOL(ib_ud_header_unpack);