net/ncsi: NCSI response packet handler
[deliverable/linux.git] / net / ncsi / ncsi-rsp.c
1 /*
2 * Copyright Gavin Shan, IBM Corporation 2016.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/netdevice.h>
14 #include <linux/skbuff.h>
15
16 #include <net/ncsi.h>
17 #include <net/net_namespace.h>
18 #include <net/sock.h>
19
20 #include "internal.h"
21 #include "ncsi-pkt.h"
22
23 static int ncsi_validate_rsp_pkt(struct ncsi_request *nr,
24 unsigned short payload)
25 {
26 struct ncsi_rsp_pkt_hdr *h;
27 u32 checksum;
28 __be32 *pchecksum;
29
30 /* Check NCSI packet header. We don't need validate
31 * the packet type, which should have been checked
32 * before calling this function.
33 */
34 h = (struct ncsi_rsp_pkt_hdr *)skb_network_header(nr->rsp);
35 if (h->common.revision != NCSI_PKT_REVISION)
36 return -EINVAL;
37 if (ntohs(h->common.length) != payload)
38 return -EINVAL;
39
40 /* Check on code and reason */
41 if (ntohs(h->code) != NCSI_PKT_RSP_C_COMPLETED ||
42 ntohs(h->reason) != NCSI_PKT_RSP_R_NO_ERROR)
43 return -EINVAL;
44
45 /* Validate checksum, which might be zeroes if the
46 * sender doesn't support checksum according to NCSI
47 * specification.
48 */
49 pchecksum = (__be32 *)((void *)(h + 1) + payload - 4);
50 if (ntohl(*pchecksum) == 0)
51 return 0;
52
53 checksum = ncsi_calculate_checksum((unsigned char *)h,
54 sizeof(*h) + payload - 4);
55 if (*pchecksum != htonl(checksum))
56 return -EINVAL;
57
58 return 0;
59 }
60
61 static int ncsi_rsp_handler_cis(struct ncsi_request *nr)
62 {
63 struct ncsi_rsp_pkt *rsp;
64 struct ncsi_dev_priv *ndp = nr->ndp;
65 struct ncsi_package *np;
66 struct ncsi_channel *nc;
67 unsigned char id;
68
69 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
70 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel, &np, &nc);
71 if (!nc) {
72 id = NCSI_CHANNEL_INDEX(rsp->rsp.common.channel);
73 nc = ncsi_add_channel(np, id);
74 }
75
76 return nc ? 0 : -ENODEV;
77 }
78
79 static int ncsi_rsp_handler_sp(struct ncsi_request *nr)
80 {
81 struct ncsi_rsp_pkt *rsp;
82 struct ncsi_dev_priv *ndp = nr->ndp;
83 struct ncsi_package *np;
84 unsigned char id;
85
86 /* Add the package if it's not existing. Otherwise,
87 * to change the state of its child channels.
88 */
89 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
90 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
91 &np, NULL);
92 if (!np) {
93 id = NCSI_PACKAGE_INDEX(rsp->rsp.common.channel);
94 np = ncsi_add_package(ndp, id);
95 if (!np)
96 return -ENODEV;
97 }
98
99 return 0;
100 }
101
102 static int ncsi_rsp_handler_dp(struct ncsi_request *nr)
103 {
104 struct ncsi_rsp_pkt *rsp;
105 struct ncsi_dev_priv *ndp = nr->ndp;
106 struct ncsi_package *np;
107 struct ncsi_channel *nc;
108 unsigned long flags;
109
110 /* Find the package */
111 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
112 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
113 &np, NULL);
114 if (!np)
115 return -ENODEV;
116
117 /* Change state of all channels attached to the package */
118 NCSI_FOR_EACH_CHANNEL(np, nc) {
119 spin_lock_irqsave(&nc->lock, flags);
120 nc->state = NCSI_CHANNEL_INACTIVE;
121 spin_unlock_irqrestore(&nc->lock, flags);
122 }
123
124 return 0;
125 }
126
127 static int ncsi_rsp_handler_ec(struct ncsi_request *nr)
128 {
129 struct ncsi_rsp_pkt *rsp;
130 struct ncsi_dev_priv *ndp = nr->ndp;
131 struct ncsi_channel *nc;
132 struct ncsi_channel_mode *ncm;
133
134 /* Find the package and channel */
135 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
136 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
137 NULL, &nc);
138 if (!nc)
139 return -ENODEV;
140
141 ncm = &nc->modes[NCSI_MODE_ENABLE];
142 if (ncm->enable)
143 return -EBUSY;
144
145 ncm->enable = 1;
146 return 0;
147 }
148
149 static int ncsi_rsp_handler_dc(struct ncsi_request *nr)
150 {
151 struct ncsi_rsp_pkt *rsp;
152 struct ncsi_dev_priv *ndp = nr->ndp;
153 struct ncsi_channel *nc;
154 struct ncsi_channel_mode *ncm;
155 int ret;
156
157 ret = ncsi_validate_rsp_pkt(nr, 4);
158 if (ret)
159 return ret;
160
161 /* Find the package and channel */
162 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
163 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
164 NULL, &nc);
165 if (!nc)
166 return -ENODEV;
167
168 ncm = &nc->modes[NCSI_MODE_ENABLE];
169 if (!ncm->enable)
170 return -EBUSY;
171
172 ncm->enable = 0;
173 return 0;
174 }
175
176 static int ncsi_rsp_handler_rc(struct ncsi_request *nr)
177 {
178 struct ncsi_rsp_pkt *rsp;
179 struct ncsi_dev_priv *ndp = nr->ndp;
180 struct ncsi_channel *nc;
181 unsigned long flags;
182
183 /* Find the package and channel */
184 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
185 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
186 NULL, &nc);
187 if (!nc)
188 return -ENODEV;
189
190 /* Update state for the specified channel */
191 spin_lock_irqsave(&nc->lock, flags);
192 nc->state = NCSI_CHANNEL_INACTIVE;
193 spin_unlock_irqrestore(&nc->lock, flags);
194
195 return 0;
196 }
197
198 static int ncsi_rsp_handler_ecnt(struct ncsi_request *nr)
199 {
200 struct ncsi_rsp_pkt *rsp;
201 struct ncsi_dev_priv *ndp = nr->ndp;
202 struct ncsi_channel *nc;
203 struct ncsi_channel_mode *ncm;
204
205 /* Find the package and channel */
206 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
207 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
208 NULL, &nc);
209 if (!nc)
210 return -ENODEV;
211
212 ncm = &nc->modes[NCSI_MODE_TX_ENABLE];
213 if (ncm->enable)
214 return -EBUSY;
215
216 ncm->enable = 1;
217 return 0;
218 }
219
220 static int ncsi_rsp_handler_dcnt(struct ncsi_request *nr)
221 {
222 struct ncsi_rsp_pkt *rsp;
223 struct ncsi_dev_priv *ndp = nr->ndp;
224 struct ncsi_channel *nc;
225 struct ncsi_channel_mode *ncm;
226
227 /* Find the package and channel */
228 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
229 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
230 NULL, &nc);
231 if (!nc)
232 return -ENODEV;
233
234 ncm = &nc->modes[NCSI_MODE_TX_ENABLE];
235 if (!ncm->enable)
236 return -EBUSY;
237
238 ncm->enable = 1;
239 return 0;
240 }
241
242 static int ncsi_rsp_handler_ae(struct ncsi_request *nr)
243 {
244 struct ncsi_cmd_ae_pkt *cmd;
245 struct ncsi_rsp_pkt *rsp;
246 struct ncsi_dev_priv *ndp = nr->ndp;
247 struct ncsi_channel *nc;
248 struct ncsi_channel_mode *ncm;
249
250 /* Find the package and channel */
251 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
252 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
253 NULL, &nc);
254 if (!nc)
255 return -ENODEV;
256
257 /* Check if the AEN has been enabled */
258 ncm = &nc->modes[NCSI_MODE_AEN];
259 if (ncm->enable)
260 return -EBUSY;
261
262 /* Update to AEN configuration */
263 cmd = (struct ncsi_cmd_ae_pkt *)skb_network_header(nr->cmd);
264 ncm->enable = 1;
265 ncm->data[0] = cmd->mc_id;
266 ncm->data[1] = ntohl(cmd->mode);
267
268 return 0;
269 }
270
271 static int ncsi_rsp_handler_sl(struct ncsi_request *nr)
272 {
273 struct ncsi_cmd_sl_pkt *cmd;
274 struct ncsi_rsp_pkt *rsp;
275 struct ncsi_dev_priv *ndp = nr->ndp;
276 struct ncsi_channel *nc;
277 struct ncsi_channel_mode *ncm;
278
279 /* Find the package and channel */
280 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
281 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
282 NULL, &nc);
283 if (!nc)
284 return -ENODEV;
285
286 cmd = (struct ncsi_cmd_sl_pkt *)skb_network_header(nr->cmd);
287 ncm = &nc->modes[NCSI_MODE_LINK];
288 ncm->data[0] = ntohl(cmd->mode);
289 ncm->data[1] = ntohl(cmd->oem_mode);
290
291 return 0;
292 }
293
294 static int ncsi_rsp_handler_gls(struct ncsi_request *nr)
295 {
296 struct ncsi_rsp_gls_pkt *rsp;
297 struct ncsi_dev_priv *ndp = nr->ndp;
298 struct ncsi_channel *nc;
299 struct ncsi_channel_mode *ncm;
300
301 /* Find the package and channel */
302 rsp = (struct ncsi_rsp_gls_pkt *)skb_network_header(nr->rsp);
303 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
304 NULL, &nc);
305 if (!nc)
306 return -ENODEV;
307
308 ncm = &nc->modes[NCSI_MODE_LINK];
309 ncm->data[2] = ntohl(rsp->status);
310 ncm->data[3] = ntohl(rsp->other);
311 ncm->data[4] = ntohl(rsp->oem_status);
312
313 return 0;
314 }
315
316 static int ncsi_rsp_handler_svf(struct ncsi_request *nr)
317 {
318 struct ncsi_cmd_svf_pkt *cmd;
319 struct ncsi_rsp_pkt *rsp;
320 struct ncsi_dev_priv *ndp = nr->ndp;
321 struct ncsi_channel *nc;
322 struct ncsi_channel_filter *ncf;
323 unsigned short vlan;
324 int ret;
325
326 /* Find the package and channel */
327 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
328 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
329 NULL, &nc);
330 if (!nc)
331 return -ENODEV;
332
333 cmd = (struct ncsi_cmd_svf_pkt *)skb_network_header(nr->cmd);
334 ncf = nc->filters[NCSI_FILTER_VLAN];
335 if (!ncf)
336 return -ENOENT;
337 if (cmd->index >= ncf->total)
338 return -ERANGE;
339
340 /* Add or remove the VLAN filter */
341 if (!(cmd->enable & 0x1)) {
342 ret = ncsi_remove_filter(nc, NCSI_FILTER_VLAN, cmd->index);
343 } else {
344 vlan = ntohs(cmd->vlan);
345 ret = ncsi_add_filter(nc, NCSI_FILTER_VLAN, &vlan);
346 }
347
348 return ret;
349 }
350
351 static int ncsi_rsp_handler_ev(struct ncsi_request *nr)
352 {
353 struct ncsi_cmd_ev_pkt *cmd;
354 struct ncsi_rsp_pkt *rsp;
355 struct ncsi_dev_priv *ndp = nr->ndp;
356 struct ncsi_channel *nc;
357 struct ncsi_channel_mode *ncm;
358
359 /* Find the package and channel */
360 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
361 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
362 NULL, &nc);
363 if (!nc)
364 return -ENODEV;
365
366 /* Check if VLAN mode has been enabled */
367 ncm = &nc->modes[NCSI_MODE_VLAN];
368 if (ncm->enable)
369 return -EBUSY;
370
371 /* Update to VLAN mode */
372 cmd = (struct ncsi_cmd_ev_pkt *)skb_network_header(nr->cmd);
373 ncm->enable = 1;
374 ncm->data[0] = ntohl(cmd->mode);
375
376 return 0;
377 }
378
379 static int ncsi_rsp_handler_dv(struct ncsi_request *nr)
380 {
381 struct ncsi_rsp_pkt *rsp;
382 struct ncsi_dev_priv *ndp = nr->ndp;
383 struct ncsi_channel *nc;
384 struct ncsi_channel_mode *ncm;
385
386 /* Find the package and channel */
387 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
388 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
389 NULL, &nc);
390 if (!nc)
391 return -ENODEV;
392
393 /* Check if VLAN mode has been enabled */
394 ncm = &nc->modes[NCSI_MODE_VLAN];
395 if (!ncm->enable)
396 return -EBUSY;
397
398 /* Update to VLAN mode */
399 ncm->enable = 0;
400 return 0;
401 }
402
403 static int ncsi_rsp_handler_sma(struct ncsi_request *nr)
404 {
405 struct ncsi_cmd_sma_pkt *cmd;
406 struct ncsi_rsp_pkt *rsp;
407 struct ncsi_dev_priv *ndp = nr->ndp;
408 struct ncsi_channel *nc;
409 struct ncsi_channel_filter *ncf;
410 void *bitmap;
411
412 /* Find the package and channel */
413 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
414 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
415 NULL, &nc);
416 if (!nc)
417 return -ENODEV;
418
419 /* According to NCSI spec 1.01, the mixed filter table
420 * isn't supported yet.
421 */
422 cmd = (struct ncsi_cmd_sma_pkt *)skb_network_header(nr->cmd);
423 switch (cmd->at_e >> 5) {
424 case 0x0: /* UC address */
425 ncf = nc->filters[NCSI_FILTER_UC];
426 break;
427 case 0x1: /* MC address */
428 ncf = nc->filters[NCSI_FILTER_MC];
429 break;
430 default:
431 return -EINVAL;
432 }
433
434 /* Sanity check on the filter */
435 if (!ncf)
436 return -ENOENT;
437 else if (cmd->index >= ncf->total)
438 return -ERANGE;
439
440 bitmap = &ncf->bitmap;
441 if (cmd->at_e & 0x1) {
442 if (test_and_set_bit(cmd->index, bitmap))
443 return -EBUSY;
444 memcpy(ncf->data + 6 * cmd->index, cmd->mac, 6);
445 } else {
446 if (!test_and_clear_bit(cmd->index, bitmap))
447 return -EBUSY;
448
449 memset(ncf->data + 6 * cmd->index, 0, 6);
450 }
451
452 return 0;
453 }
454
455 static int ncsi_rsp_handler_ebf(struct ncsi_request *nr)
456 {
457 struct ncsi_cmd_ebf_pkt *cmd;
458 struct ncsi_rsp_pkt *rsp;
459 struct ncsi_dev_priv *ndp = nr->ndp;
460 struct ncsi_channel *nc;
461 struct ncsi_channel_mode *ncm;
462
463 /* Find the package and channel */
464 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
465 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel, NULL, &nc);
466 if (!nc)
467 return -ENODEV;
468
469 /* Check if broadcast filter has been enabled */
470 ncm = &nc->modes[NCSI_MODE_BC];
471 if (ncm->enable)
472 return -EBUSY;
473
474 /* Update to broadcast filter mode */
475 cmd = (struct ncsi_cmd_ebf_pkt *)skb_network_header(nr->cmd);
476 ncm->enable = 1;
477 ncm->data[0] = ntohl(cmd->mode);
478
479 return 0;
480 }
481
482 static int ncsi_rsp_handler_dbf(struct ncsi_request *nr)
483 {
484 struct ncsi_rsp_pkt *rsp;
485 struct ncsi_dev_priv *ndp = nr->ndp;
486 struct ncsi_channel *nc;
487 struct ncsi_channel_mode *ncm;
488
489 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
490 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
491 NULL, &nc);
492 if (!nc)
493 return -ENODEV;
494
495 /* Check if broadcast filter isn't enabled */
496 ncm = &nc->modes[NCSI_MODE_BC];
497 if (!ncm->enable)
498 return -EBUSY;
499
500 /* Update to broadcast filter mode */
501 ncm->enable = 0;
502 ncm->data[0] = 0;
503
504 return 0;
505 }
506
507 static int ncsi_rsp_handler_egmf(struct ncsi_request *nr)
508 {
509 struct ncsi_cmd_egmf_pkt *cmd;
510 struct ncsi_rsp_pkt *rsp;
511 struct ncsi_dev_priv *ndp = nr->ndp;
512 struct ncsi_channel *nc;
513 struct ncsi_channel_mode *ncm;
514
515 /* Find the channel */
516 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
517 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
518 NULL, &nc);
519 if (!nc)
520 return -ENODEV;
521
522 /* Check if multicast filter has been enabled */
523 ncm = &nc->modes[NCSI_MODE_MC];
524 if (ncm->enable)
525 return -EBUSY;
526
527 /* Update to multicast filter mode */
528 cmd = (struct ncsi_cmd_egmf_pkt *)skb_network_header(nr->cmd);
529 ncm->enable = 1;
530 ncm->data[0] = ntohl(cmd->mode);
531
532 return 0;
533 }
534
535 static int ncsi_rsp_handler_dgmf(struct ncsi_request *nr)
536 {
537 struct ncsi_rsp_pkt *rsp;
538 struct ncsi_dev_priv *ndp = nr->ndp;
539 struct ncsi_channel *nc;
540 struct ncsi_channel_mode *ncm;
541
542 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
543 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
544 NULL, &nc);
545 if (!nc)
546 return -ENODEV;
547
548 /* Check if multicast filter has been enabled */
549 ncm = &nc->modes[NCSI_MODE_MC];
550 if (!ncm->enable)
551 return -EBUSY;
552
553 /* Update to multicast filter mode */
554 ncm->enable = 0;
555 ncm->data[0] = 0;
556
557 return 0;
558 }
559
560 static int ncsi_rsp_handler_snfc(struct ncsi_request *nr)
561 {
562 struct ncsi_cmd_snfc_pkt *cmd;
563 struct ncsi_rsp_pkt *rsp;
564 struct ncsi_dev_priv *ndp = nr->ndp;
565 struct ncsi_channel *nc;
566 struct ncsi_channel_mode *ncm;
567
568 /* Find the channel */
569 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
570 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
571 NULL, &nc);
572 if (!nc)
573 return -ENODEV;
574
575 /* Check if flow control has been enabled */
576 ncm = &nc->modes[NCSI_MODE_FC];
577 if (ncm->enable)
578 return -EBUSY;
579
580 /* Update to flow control mode */
581 cmd = (struct ncsi_cmd_snfc_pkt *)skb_network_header(nr->cmd);
582 ncm->enable = 1;
583 ncm->data[0] = cmd->mode;
584
585 return 0;
586 }
587
588 static int ncsi_rsp_handler_gvi(struct ncsi_request *nr)
589 {
590 struct ncsi_rsp_gvi_pkt *rsp;
591 struct ncsi_dev_priv *ndp = nr->ndp;
592 struct ncsi_channel *nc;
593 struct ncsi_channel_version *ncv;
594 int i;
595
596 /* Find the channel */
597 rsp = (struct ncsi_rsp_gvi_pkt *)skb_network_header(nr->rsp);
598 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
599 NULL, &nc);
600 if (!nc)
601 return -ENODEV;
602
603 /* Update to channel's version info */
604 ncv = &nc->version;
605 ncv->version = ntohl(rsp->ncsi_version);
606 ncv->alpha2 = rsp->alpha2;
607 memcpy(ncv->fw_name, rsp->fw_name, 12);
608 ncv->fw_version = ntohl(rsp->fw_version);
609 for (i = 0; i < ARRAY_SIZE(ncv->pci_ids); i++)
610 ncv->pci_ids[i] = ntohs(rsp->pci_ids[i]);
611 ncv->mf_id = ntohl(rsp->mf_id);
612
613 return 0;
614 }
615
616 static int ncsi_rsp_handler_gc(struct ncsi_request *nr)
617 {
618 struct ncsi_rsp_gc_pkt *rsp;
619 struct ncsi_dev_priv *ndp = nr->ndp;
620 struct ncsi_channel *nc;
621 struct ncsi_channel_filter *ncf;
622 size_t size, entry_size;
623 int cnt, i;
624
625 /* Find the channel */
626 rsp = (struct ncsi_rsp_gc_pkt *)skb_network_header(nr->rsp);
627 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
628 NULL, &nc);
629 if (!nc)
630 return -ENODEV;
631
632 /* Update channel's capabilities */
633 nc->caps[NCSI_CAP_GENERIC].cap = ntohl(rsp->cap) &
634 NCSI_CAP_GENERIC_MASK;
635 nc->caps[NCSI_CAP_BC].cap = ntohl(rsp->bc_cap) &
636 NCSI_CAP_BC_MASK;
637 nc->caps[NCSI_CAP_MC].cap = ntohl(rsp->mc_cap) &
638 NCSI_CAP_MC_MASK;
639 nc->caps[NCSI_CAP_BUFFER].cap = ntohl(rsp->buf_cap);
640 nc->caps[NCSI_CAP_AEN].cap = ntohl(rsp->aen_cap) &
641 NCSI_CAP_AEN_MASK;
642 nc->caps[NCSI_CAP_VLAN].cap = rsp->vlan_mode &
643 NCSI_CAP_VLAN_MASK;
644
645 /* Build filters */
646 for (i = 0; i < NCSI_FILTER_MAX; i++) {
647 switch (i) {
648 case NCSI_FILTER_VLAN:
649 cnt = rsp->vlan_cnt;
650 entry_size = 2;
651 break;
652 case NCSI_FILTER_MIXED:
653 cnt = rsp->mixed_cnt;
654 entry_size = 6;
655 break;
656 case NCSI_FILTER_MC:
657 cnt = rsp->mc_cnt;
658 entry_size = 6;
659 break;
660 case NCSI_FILTER_UC:
661 cnt = rsp->uc_cnt;
662 entry_size = 6;
663 break;
664 default:
665 continue;
666 }
667
668 if (!cnt || nc->filters[i])
669 continue;
670
671 size = sizeof(*ncf) + cnt * entry_size;
672 ncf = kzalloc(size, GFP_ATOMIC);
673 if (!ncf) {
674 pr_warn("%s: Cannot alloc filter table (%d)\n",
675 __func__, i);
676 return -ENOMEM;
677 }
678
679 ncf->index = i;
680 ncf->total = cnt;
681 ncf->bitmap = 0x0ul;
682 nc->filters[i] = ncf;
683 }
684
685 return 0;
686 }
687
688 static int ncsi_rsp_handler_gp(struct ncsi_request *nr)
689 {
690 struct ncsi_rsp_gp_pkt *rsp;
691 struct ncsi_dev_priv *ndp = nr->ndp;
692 struct ncsi_channel *nc;
693 unsigned short enable, vlan;
694 unsigned char *pdata;
695 int table, i;
696
697 /* Find the channel */
698 rsp = (struct ncsi_rsp_gp_pkt *)skb_network_header(nr->rsp);
699 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
700 NULL, &nc);
701 if (!nc)
702 return -ENODEV;
703
704 /* Modes with explicit enabled indications */
705 if (ntohl(rsp->valid_modes) & 0x1) { /* BC filter mode */
706 nc->modes[NCSI_MODE_BC].enable = 1;
707 nc->modes[NCSI_MODE_BC].data[0] = ntohl(rsp->bc_mode);
708 }
709 if (ntohl(rsp->valid_modes) & 0x2) /* Channel enabled */
710 nc->modes[NCSI_MODE_ENABLE].enable = 1;
711 if (ntohl(rsp->valid_modes) & 0x4) /* Channel Tx enabled */
712 nc->modes[NCSI_MODE_TX_ENABLE].enable = 1;
713 if (ntohl(rsp->valid_modes) & 0x8) /* MC filter mode */
714 nc->modes[NCSI_MODE_MC].enable = 1;
715
716 /* Modes without explicit enabled indications */
717 nc->modes[NCSI_MODE_LINK].enable = 1;
718 nc->modes[NCSI_MODE_LINK].data[0] = ntohl(rsp->link_mode);
719 nc->modes[NCSI_MODE_VLAN].enable = 1;
720 nc->modes[NCSI_MODE_VLAN].data[0] = rsp->vlan_mode;
721 nc->modes[NCSI_MODE_FC].enable = 1;
722 nc->modes[NCSI_MODE_FC].data[0] = rsp->fc_mode;
723 nc->modes[NCSI_MODE_AEN].enable = 1;
724 nc->modes[NCSI_MODE_AEN].data[0] = ntohl(rsp->aen_mode);
725
726 /* MAC addresses filter table */
727 pdata = (unsigned char *)rsp + 48;
728 enable = rsp->mac_enable;
729 for (i = 0; i < rsp->mac_cnt; i++, pdata += 6) {
730 if (i >= (nc->filters[NCSI_FILTER_UC]->total +
731 nc->filters[NCSI_FILTER_MC]->total))
732 table = NCSI_FILTER_MIXED;
733 else if (i >= nc->filters[NCSI_FILTER_UC]->total)
734 table = NCSI_FILTER_MC;
735 else
736 table = NCSI_FILTER_UC;
737
738 if (!(enable & (0x1 << i)))
739 continue;
740
741 if (ncsi_find_filter(nc, table, pdata) >= 0)
742 continue;
743
744 ncsi_add_filter(nc, table, pdata);
745 }
746
747 /* VLAN filter table */
748 enable = ntohs(rsp->vlan_enable);
749 for (i = 0; i < rsp->vlan_cnt; i++, pdata += 2) {
750 if (!(enable & (0x1 << i)))
751 continue;
752
753 vlan = ntohs(*(__be16 *)pdata);
754 if (ncsi_find_filter(nc, NCSI_FILTER_VLAN, &vlan) >= 0)
755 continue;
756
757 ncsi_add_filter(nc, NCSI_FILTER_VLAN, &vlan);
758 }
759
760 return 0;
761 }
762
763 static int ncsi_rsp_handler_gcps(struct ncsi_request *nr)
764 {
765 struct ncsi_rsp_gcps_pkt *rsp;
766 struct ncsi_dev_priv *ndp = nr->ndp;
767 struct ncsi_channel *nc;
768 struct ncsi_channel_stats *ncs;
769
770 /* Find the channel */
771 rsp = (struct ncsi_rsp_gcps_pkt *)skb_network_header(nr->rsp);
772 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
773 NULL, &nc);
774 if (!nc)
775 return -ENODEV;
776
777 /* Update HNC's statistics */
778 ncs = &nc->stats;
779 ncs->hnc_cnt_hi = ntohl(rsp->cnt_hi);
780 ncs->hnc_cnt_lo = ntohl(rsp->cnt_lo);
781 ncs->hnc_rx_bytes = ntohl(rsp->rx_bytes);
782 ncs->hnc_tx_bytes = ntohl(rsp->tx_bytes);
783 ncs->hnc_rx_uc_pkts = ntohl(rsp->rx_uc_pkts);
784 ncs->hnc_rx_mc_pkts = ntohl(rsp->rx_mc_pkts);
785 ncs->hnc_rx_bc_pkts = ntohl(rsp->rx_bc_pkts);
786 ncs->hnc_tx_uc_pkts = ntohl(rsp->tx_uc_pkts);
787 ncs->hnc_tx_mc_pkts = ntohl(rsp->tx_mc_pkts);
788 ncs->hnc_tx_bc_pkts = ntohl(rsp->tx_bc_pkts);
789 ncs->hnc_fcs_err = ntohl(rsp->fcs_err);
790 ncs->hnc_align_err = ntohl(rsp->align_err);
791 ncs->hnc_false_carrier = ntohl(rsp->false_carrier);
792 ncs->hnc_runt_pkts = ntohl(rsp->runt_pkts);
793 ncs->hnc_jabber_pkts = ntohl(rsp->jabber_pkts);
794 ncs->hnc_rx_pause_xon = ntohl(rsp->rx_pause_xon);
795 ncs->hnc_rx_pause_xoff = ntohl(rsp->rx_pause_xoff);
796 ncs->hnc_tx_pause_xon = ntohl(rsp->tx_pause_xon);
797 ncs->hnc_tx_pause_xoff = ntohl(rsp->tx_pause_xoff);
798 ncs->hnc_tx_s_collision = ntohl(rsp->tx_s_collision);
799 ncs->hnc_tx_m_collision = ntohl(rsp->tx_m_collision);
800 ncs->hnc_l_collision = ntohl(rsp->l_collision);
801 ncs->hnc_e_collision = ntohl(rsp->e_collision);
802 ncs->hnc_rx_ctl_frames = ntohl(rsp->rx_ctl_frames);
803 ncs->hnc_rx_64_frames = ntohl(rsp->rx_64_frames);
804 ncs->hnc_rx_127_frames = ntohl(rsp->rx_127_frames);
805 ncs->hnc_rx_255_frames = ntohl(rsp->rx_255_frames);
806 ncs->hnc_rx_511_frames = ntohl(rsp->rx_511_frames);
807 ncs->hnc_rx_1023_frames = ntohl(rsp->rx_1023_frames);
808 ncs->hnc_rx_1522_frames = ntohl(rsp->rx_1522_frames);
809 ncs->hnc_rx_9022_frames = ntohl(rsp->rx_9022_frames);
810 ncs->hnc_tx_64_frames = ntohl(rsp->tx_64_frames);
811 ncs->hnc_tx_127_frames = ntohl(rsp->tx_127_frames);
812 ncs->hnc_tx_255_frames = ntohl(rsp->tx_255_frames);
813 ncs->hnc_tx_511_frames = ntohl(rsp->tx_511_frames);
814 ncs->hnc_tx_1023_frames = ntohl(rsp->tx_1023_frames);
815 ncs->hnc_tx_1522_frames = ntohl(rsp->tx_1522_frames);
816 ncs->hnc_tx_9022_frames = ntohl(rsp->tx_9022_frames);
817 ncs->hnc_rx_valid_bytes = ntohl(rsp->rx_valid_bytes);
818 ncs->hnc_rx_runt_pkts = ntohl(rsp->rx_runt_pkts);
819 ncs->hnc_rx_jabber_pkts = ntohl(rsp->rx_jabber_pkts);
820
821 return 0;
822 }
823
824 static int ncsi_rsp_handler_gns(struct ncsi_request *nr)
825 {
826 struct ncsi_rsp_gns_pkt *rsp;
827 struct ncsi_dev_priv *ndp = nr->ndp;
828 struct ncsi_channel *nc;
829 struct ncsi_channel_stats *ncs;
830
831 /* Find the channel */
832 rsp = (struct ncsi_rsp_gns_pkt *)skb_network_header(nr->rsp);
833 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
834 NULL, &nc);
835 if (!nc)
836 return -ENODEV;
837
838 /* Update HNC's statistics */
839 ncs = &nc->stats;
840 ncs->ncsi_rx_cmds = ntohl(rsp->rx_cmds);
841 ncs->ncsi_dropped_cmds = ntohl(rsp->dropped_cmds);
842 ncs->ncsi_cmd_type_errs = ntohl(rsp->cmd_type_errs);
843 ncs->ncsi_cmd_csum_errs = ntohl(rsp->cmd_csum_errs);
844 ncs->ncsi_rx_pkts = ntohl(rsp->rx_pkts);
845 ncs->ncsi_tx_pkts = ntohl(rsp->tx_pkts);
846 ncs->ncsi_tx_aen_pkts = ntohl(rsp->tx_aen_pkts);
847
848 return 0;
849 }
850
851 static int ncsi_rsp_handler_gnpts(struct ncsi_request *nr)
852 {
853 struct ncsi_rsp_gnpts_pkt *rsp;
854 struct ncsi_dev_priv *ndp = nr->ndp;
855 struct ncsi_channel *nc;
856 struct ncsi_channel_stats *ncs;
857
858 /* Find the channel */
859 rsp = (struct ncsi_rsp_gnpts_pkt *)skb_network_header(nr->rsp);
860 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
861 NULL, &nc);
862 if (!nc)
863 return -ENODEV;
864
865 /* Update HNC's statistics */
866 ncs = &nc->stats;
867 ncs->pt_tx_pkts = ntohl(rsp->tx_pkts);
868 ncs->pt_tx_dropped = ntohl(rsp->tx_dropped);
869 ncs->pt_tx_channel_err = ntohl(rsp->tx_channel_err);
870 ncs->pt_tx_us_err = ntohl(rsp->tx_us_err);
871 ncs->pt_rx_pkts = ntohl(rsp->rx_pkts);
872 ncs->pt_rx_dropped = ntohl(rsp->rx_dropped);
873 ncs->pt_rx_channel_err = ntohl(rsp->rx_channel_err);
874 ncs->pt_rx_us_err = ntohl(rsp->rx_us_err);
875 ncs->pt_rx_os_err = ntohl(rsp->rx_os_err);
876
877 return 0;
878 }
879
880 static int ncsi_rsp_handler_gps(struct ncsi_request *nr)
881 {
882 struct ncsi_rsp_gps_pkt *rsp;
883 struct ncsi_dev_priv *ndp = nr->ndp;
884 struct ncsi_package *np;
885
886 /* Find the package */
887 rsp = (struct ncsi_rsp_gps_pkt *)skb_network_header(nr->rsp);
888 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
889 &np, NULL);
890 if (!np)
891 return -ENODEV;
892
893 return 0;
894 }
895
896 static int ncsi_rsp_handler_gpuuid(struct ncsi_request *nr)
897 {
898 struct ncsi_rsp_gpuuid_pkt *rsp;
899 struct ncsi_dev_priv *ndp = nr->ndp;
900 struct ncsi_package *np;
901
902 /* Find the package */
903 rsp = (struct ncsi_rsp_gpuuid_pkt *)skb_network_header(nr->rsp);
904 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
905 &np, NULL);
906 if (!np)
907 return -ENODEV;
908
909 memcpy(np->uuid, rsp->uuid, sizeof(rsp->uuid));
910
911 return 0;
912 }
913
914 static struct ncsi_rsp_handler {
915 unsigned char type;
916 int payload;
917 int (*handler)(struct ncsi_request *nr);
918 } ncsi_rsp_handlers[] = {
919 { NCSI_PKT_RSP_CIS, 4, ncsi_rsp_handler_cis },
920 { NCSI_PKT_RSP_SP, 4, ncsi_rsp_handler_sp },
921 { NCSI_PKT_RSP_DP, 4, ncsi_rsp_handler_dp },
922 { NCSI_PKT_RSP_EC, 4, ncsi_rsp_handler_ec },
923 { NCSI_PKT_RSP_DC, 4, ncsi_rsp_handler_dc },
924 { NCSI_PKT_RSP_RC, 4, ncsi_rsp_handler_rc },
925 { NCSI_PKT_RSP_ECNT, 4, ncsi_rsp_handler_ecnt },
926 { NCSI_PKT_RSP_DCNT, 4, ncsi_rsp_handler_dcnt },
927 { NCSI_PKT_RSP_AE, 4, ncsi_rsp_handler_ae },
928 { NCSI_PKT_RSP_SL, 4, ncsi_rsp_handler_sl },
929 { NCSI_PKT_RSP_GLS, 16, ncsi_rsp_handler_gls },
930 { NCSI_PKT_RSP_SVF, 4, ncsi_rsp_handler_svf },
931 { NCSI_PKT_RSP_EV, 4, ncsi_rsp_handler_ev },
932 { NCSI_PKT_RSP_DV, 4, ncsi_rsp_handler_dv },
933 { NCSI_PKT_RSP_SMA, 4, ncsi_rsp_handler_sma },
934 { NCSI_PKT_RSP_EBF, 4, ncsi_rsp_handler_ebf },
935 { NCSI_PKT_RSP_DBF, 4, ncsi_rsp_handler_dbf },
936 { NCSI_PKT_RSP_EGMF, 4, ncsi_rsp_handler_egmf },
937 { NCSI_PKT_RSP_DGMF, 4, ncsi_rsp_handler_dgmf },
938 { NCSI_PKT_RSP_SNFC, 4, ncsi_rsp_handler_snfc },
939 { NCSI_PKT_RSP_GVI, 36, ncsi_rsp_handler_gvi },
940 { NCSI_PKT_RSP_GC, 32, ncsi_rsp_handler_gc },
941 { NCSI_PKT_RSP_GP, -1, ncsi_rsp_handler_gp },
942 { NCSI_PKT_RSP_GCPS, 172, ncsi_rsp_handler_gcps },
943 { NCSI_PKT_RSP_GNS, 172, ncsi_rsp_handler_gns },
944 { NCSI_PKT_RSP_GNPTS, 172, ncsi_rsp_handler_gnpts },
945 { NCSI_PKT_RSP_GPS, 8, ncsi_rsp_handler_gps },
946 { NCSI_PKT_RSP_OEM, 0, NULL },
947 { NCSI_PKT_RSP_PLDM, 0, NULL },
948 { NCSI_PKT_RSP_GPUUID, 20, ncsi_rsp_handler_gpuuid }
949 };
950
951 int ncsi_rcv_rsp(struct sk_buff *skb, struct net_device *dev,
952 struct packet_type *pt, struct net_device *orig_dev)
953 {
954 struct ncsi_rsp_handler *nrh = NULL;
955 struct ncsi_dev *nd;
956 struct ncsi_dev_priv *ndp;
957 struct ncsi_request *nr;
958 struct ncsi_pkt_hdr *hdr;
959 unsigned long flags;
960 int payload, i, ret;
961
962 /* Find the NCSI device */
963 nd = ncsi_find_dev(dev);
964 ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL;
965 if (!ndp)
966 return -ENODEV;
967
968 /* Find the handler */
969 hdr = (struct ncsi_pkt_hdr *)skb_network_header(skb);
970 for (i = 0; i < ARRAY_SIZE(ncsi_rsp_handlers); i++) {
971 if (ncsi_rsp_handlers[i].type == hdr->type) {
972 if (ncsi_rsp_handlers[i].handler)
973 nrh = &ncsi_rsp_handlers[i];
974 else
975 nrh = NULL;
976
977 break;
978 }
979 }
980
981 if (!nrh) {
982 netdev_err(nd->dev, "Received unrecognized packet (0x%x)\n",
983 hdr->type);
984 return -ENOENT;
985 }
986
987 /* Associate with the request */
988 spin_lock_irqsave(&ndp->lock, flags);
989 nr = &ndp->requests[hdr->id];
990 if (!nr->used) {
991 spin_unlock_irqrestore(&ndp->lock, flags);
992 return -ENODEV;
993 }
994
995 nr->rsp = skb;
996 if (!nr->enabled) {
997 spin_unlock_irqrestore(&ndp->lock, flags);
998 ret = -ENOENT;
999 goto out;
1000 }
1001
1002 /* Validate the packet */
1003 spin_unlock_irqrestore(&ndp->lock, flags);
1004 payload = nrh->payload;
1005 if (payload < 0)
1006 payload = ntohs(hdr->length);
1007 ret = ncsi_validate_rsp_pkt(nr, payload);
1008 if (ret)
1009 goto out;
1010
1011 /* Process the packet */
1012 ret = nrh->handler(nr);
1013 out:
1014 ncsi_free_request(nr);
1015 return ret;
1016 }
This page took 0.079387 seconds and 6 git commands to generate.