ncsi-rsp.c (664b0bae0b87f69bc9deb098f5e0158b9cf18e04) ncsi-rsp.c (062b3e1b6d4f2a33c1d0fd7ae9b4550da5cf7e4b)
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 */

--- 320 unchanged lines hidden (view full) ---

329}
330
331static int ncsi_rsp_handler_svf(struct ncsi_request *nr)
332{
333 struct ncsi_cmd_svf_pkt *cmd;
334 struct ncsi_rsp_pkt *rsp;
335 struct ncsi_dev_priv *ndp = nr->ndp;
336 struct ncsi_channel *nc;
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 */

--- 320 unchanged lines hidden (view full) ---

329}
330
331static int ncsi_rsp_handler_svf(struct ncsi_request *nr)
332{
333 struct ncsi_cmd_svf_pkt *cmd;
334 struct ncsi_rsp_pkt *rsp;
335 struct ncsi_dev_priv *ndp = nr->ndp;
336 struct ncsi_channel *nc;
337 struct ncsi_channel_filter *ncf;
338 unsigned short vlan;
339 int ret;
337 struct ncsi_channel_vlan_filter *ncf;
338 unsigned long flags;
339 void *bitmap;
340
341 /* Find the package and channel */
342 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
343 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
344 NULL, &nc);
345 if (!nc)
346 return -ENODEV;
347
348 cmd = (struct ncsi_cmd_svf_pkt *)skb_network_header(nr->cmd);
340
341 /* Find the package and channel */
342 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
343 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
344 NULL, &nc);
345 if (!nc)
346 return -ENODEV;
347
348 cmd = (struct ncsi_cmd_svf_pkt *)skb_network_header(nr->cmd);
349 ncf = nc->filters[NCSI_FILTER_VLAN];
350 if (!ncf)
351 return -ENOENT;
352 if (cmd->index >= ncf->total)
349 ncf = &nc->vlan_filter;
350 if (cmd->index > ncf->n_vids)
353 return -ERANGE;
354
351 return -ERANGE;
352
355 /* Add or remove the VLAN filter */
353 /* Add or remove the VLAN filter. Remember HW indexes from 1 */
354 spin_lock_irqsave(&nc->lock, flags);
355 bitmap = &ncf->bitmap;
356 if (!(cmd->enable & 0x1)) {
356 if (!(cmd->enable & 0x1)) {
357 /* HW indexes from 1 */
358 ret = ncsi_remove_filter(nc, NCSI_FILTER_VLAN, cmd->index - 1);
357 if (test_and_clear_bit(cmd->index - 1, bitmap))
358 ncf->vids[cmd->index - 1] = 0;
359 } else {
359 } else {
360 vlan = ntohs(cmd->vlan);
361 ret = ncsi_add_filter(nc, NCSI_FILTER_VLAN, &vlan);
360 set_bit(cmd->index - 1, bitmap);
361 ncf->vids[cmd->index - 1] = ntohs(cmd->vlan);
362 }
362 }
363 spin_unlock_irqrestore(&nc->lock, flags);
363
364
364 return ret;
365 return 0;
365}
366
367static int ncsi_rsp_handler_ev(struct ncsi_request *nr)
368{
369 struct ncsi_cmd_ev_pkt *cmd;
370 struct ncsi_rsp_pkt *rsp;
371 struct ncsi_dev_priv *ndp = nr->ndp;
372 struct ncsi_channel *nc;

--- 44 unchanged lines hidden (view full) ---

417}
418
419static int ncsi_rsp_handler_sma(struct ncsi_request *nr)
420{
421 struct ncsi_cmd_sma_pkt *cmd;
422 struct ncsi_rsp_pkt *rsp;
423 struct ncsi_dev_priv *ndp = nr->ndp;
424 struct ncsi_channel *nc;
366}
367
368static int ncsi_rsp_handler_ev(struct ncsi_request *nr)
369{
370 struct ncsi_cmd_ev_pkt *cmd;
371 struct ncsi_rsp_pkt *rsp;
372 struct ncsi_dev_priv *ndp = nr->ndp;
373 struct ncsi_channel *nc;

--- 44 unchanged lines hidden (view full) ---

418}
419
420static int ncsi_rsp_handler_sma(struct ncsi_request *nr)
421{
422 struct ncsi_cmd_sma_pkt *cmd;
423 struct ncsi_rsp_pkt *rsp;
424 struct ncsi_dev_priv *ndp = nr->ndp;
425 struct ncsi_channel *nc;
425 struct ncsi_channel_filter *ncf;
426 struct ncsi_channel_mac_filter *ncf;
427 unsigned long flags;
426 void *bitmap;
428 void *bitmap;
429 bool enabled;
430 int index;
427
431
432
428 /* Find the package and channel */
429 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
430 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
431 NULL, &nc);
432 if (!nc)
433 return -ENODEV;
434
435 /* According to NCSI spec 1.01, the mixed filter table
436 * isn't supported yet.
437 */
438 cmd = (struct ncsi_cmd_sma_pkt *)skb_network_header(nr->cmd);
433 /* Find the package and channel */
434 rsp = (struct ncsi_rsp_pkt *)skb_network_header(nr->rsp);
435 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
436 NULL, &nc);
437 if (!nc)
438 return -ENODEV;
439
440 /* According to NCSI spec 1.01, the mixed filter table
441 * isn't supported yet.
442 */
443 cmd = (struct ncsi_cmd_sma_pkt *)skb_network_header(nr->cmd);
439 switch (cmd->at_e >> 5) {
440 case 0x0: /* UC address */
441 ncf = nc->filters[NCSI_FILTER_UC];
442 break;
443 case 0x1: /* MC address */
444 ncf = nc->filters[NCSI_FILTER_MC];
445 break;
446 default:
447 return -EINVAL;
448 }
444 enabled = cmd->at_e & 0x1;
445 ncf = &nc->mac_filter;
446 bitmap = &ncf->bitmap;
449
447
450 /* Sanity check on the filter */
451 if (!ncf)
452 return -ENOENT;
453 else if (cmd->index >= ncf->total)
448 if (cmd->index > ncf->n_uc + ncf->n_mc + ncf->n_mixed)
454 return -ERANGE;
455
449 return -ERANGE;
450
456 bitmap = &ncf->bitmap;
457 if (cmd->at_e & 0x1) {
458 set_bit(cmd->index, bitmap);
459 memcpy(ncf->data + 6 * cmd->index, cmd->mac, 6);
451 index = (cmd->index - 1) * ETH_ALEN;
452 spin_lock_irqsave(&nc->lock, flags);
453 if (enabled) {
454 set_bit(cmd->index - 1, bitmap);
455 memcpy(&ncf->addrs[index], cmd->mac, ETH_ALEN);
460 } else {
456 } else {
461 clear_bit(cmd->index, bitmap);
462 memset(ncf->data + 6 * cmd->index, 0, 6);
457 clear_bit(cmd->index - 1, bitmap);
458 memset(&ncf->addrs[index], 0, ETH_ALEN);
463 }
459 }
460 spin_unlock_irqrestore(&nc->lock, flags);
464
465 return 0;
466}
467
468static int ncsi_rsp_handler_ebf(struct ncsi_request *nr)
469{
470 struct ncsi_cmd_ebf_pkt *cmd;
471 struct ncsi_rsp_pkt *rsp;

--- 154 unchanged lines hidden (view full) ---

626 return 0;
627}
628
629static int ncsi_rsp_handler_gc(struct ncsi_request *nr)
630{
631 struct ncsi_rsp_gc_pkt *rsp;
632 struct ncsi_dev_priv *ndp = nr->ndp;
633 struct ncsi_channel *nc;
461
462 return 0;
463}
464
465static int ncsi_rsp_handler_ebf(struct ncsi_request *nr)
466{
467 struct ncsi_cmd_ebf_pkt *cmd;
468 struct ncsi_rsp_pkt *rsp;

--- 154 unchanged lines hidden (view full) ---

623 return 0;
624}
625
626static int ncsi_rsp_handler_gc(struct ncsi_request *nr)
627{
628 struct ncsi_rsp_gc_pkt *rsp;
629 struct ncsi_dev_priv *ndp = nr->ndp;
630 struct ncsi_channel *nc;
634 struct ncsi_channel_filter *ncf;
635 size_t size, entry_size;
636 int cnt, i;
631 size_t size;
637
638 /* Find the channel */
639 rsp = (struct ncsi_rsp_gc_pkt *)skb_network_header(nr->rsp);
640 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
641 NULL, &nc);
642 if (!nc)
643 return -ENODEV;
644

--- 5 unchanged lines hidden (view full) ---

650 nc->caps[NCSI_CAP_MC].cap = ntohl(rsp->mc_cap) &
651 NCSI_CAP_MC_MASK;
652 nc->caps[NCSI_CAP_BUFFER].cap = ntohl(rsp->buf_cap);
653 nc->caps[NCSI_CAP_AEN].cap = ntohl(rsp->aen_cap) &
654 NCSI_CAP_AEN_MASK;
655 nc->caps[NCSI_CAP_VLAN].cap = rsp->vlan_mode &
656 NCSI_CAP_VLAN_MASK;
657
632
633 /* Find the channel */
634 rsp = (struct ncsi_rsp_gc_pkt *)skb_network_header(nr->rsp);
635 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
636 NULL, &nc);
637 if (!nc)
638 return -ENODEV;
639

--- 5 unchanged lines hidden (view full) ---

645 nc->caps[NCSI_CAP_MC].cap = ntohl(rsp->mc_cap) &
646 NCSI_CAP_MC_MASK;
647 nc->caps[NCSI_CAP_BUFFER].cap = ntohl(rsp->buf_cap);
648 nc->caps[NCSI_CAP_AEN].cap = ntohl(rsp->aen_cap) &
649 NCSI_CAP_AEN_MASK;
650 nc->caps[NCSI_CAP_VLAN].cap = rsp->vlan_mode &
651 NCSI_CAP_VLAN_MASK;
652
658 /* Build filters */
659 for (i = 0; i < NCSI_FILTER_MAX; i++) {
660 switch (i) {
661 case NCSI_FILTER_VLAN:
662 cnt = rsp->vlan_cnt;
663 entry_size = 2;
664 break;
665 case NCSI_FILTER_MIXED:
666 cnt = rsp->mixed_cnt;
667 entry_size = 6;
668 break;
669 case NCSI_FILTER_MC:
670 cnt = rsp->mc_cnt;
671 entry_size = 6;
672 break;
673 case NCSI_FILTER_UC:
674 cnt = rsp->uc_cnt;
675 entry_size = 6;
676 break;
677 default:
678 continue;
679 }
653 size = (rsp->uc_cnt + rsp->mc_cnt + rsp->mixed_cnt) * ETH_ALEN;
654 nc->mac_filter.addrs = kzalloc(size, GFP_KERNEL);
655 if (!nc->mac_filter.addrs)
656 return -ENOMEM;
657 nc->mac_filter.n_uc = rsp->uc_cnt;
658 nc->mac_filter.n_mc = rsp->mc_cnt;
659 nc->mac_filter.n_mixed = rsp->mixed_cnt;
680
660
681 if (!cnt || nc->filters[i])
682 continue;
661 nc->vlan_filter.vids = kcalloc(rsp->vlan_cnt,
662 sizeof(*nc->vlan_filter.vids),
663 GFP_KERNEL);
664 if (!nc->vlan_filter.vids)
665 return -ENOMEM;
666 /* Set VLAN filters active so they are cleared in the first
667 * configuration state
668 */
669 nc->vlan_filter.bitmap = U64_MAX;
670 nc->vlan_filter.n_vids = rsp->vlan_cnt;
683
671
684 size = sizeof(*ncf) + cnt * entry_size;
685 ncf = kzalloc(size, GFP_ATOMIC);
686 if (!ncf) {
687 pr_warn("%s: Cannot alloc filter table (%d)\n",
688 __func__, i);
689 return -ENOMEM;
690 }
691
692 ncf->index = i;
693 ncf->total = cnt;
694 if (i == NCSI_FILTER_VLAN) {
695 /* Set VLAN filters active so they are cleared in
696 * first configuration state
697 */
698 ncf->bitmap = U64_MAX;
699 } else {
700 ncf->bitmap = 0x0ul;
701 }
702 nc->filters[i] = ncf;
703 }
704
705 return 0;
706}
707
708static int ncsi_rsp_handler_gp(struct ncsi_request *nr)
709{
672 return 0;
673}
674
675static int ncsi_rsp_handler_gp(struct ncsi_request *nr)
676{
710 struct ncsi_rsp_gp_pkt *rsp;
677 struct ncsi_channel_vlan_filter *ncvf;
678 struct ncsi_channel_mac_filter *ncmf;
711 struct ncsi_dev_priv *ndp = nr->ndp;
679 struct ncsi_dev_priv *ndp = nr->ndp;
680 struct ncsi_rsp_gp_pkt *rsp;
712 struct ncsi_channel *nc;
681 struct ncsi_channel *nc;
713 unsigned short enable, vlan;
682 unsigned short enable;
714 unsigned char *pdata;
683 unsigned char *pdata;
715 int table, i;
684 unsigned long flags;
685 void *bitmap;
686 int i;
716
717 /* Find the channel */
718 rsp = (struct ncsi_rsp_gp_pkt *)skb_network_header(nr->rsp);
719 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
720 NULL, &nc);
721 if (!nc)
722 return -ENODEV;
723

--- 17 unchanged lines hidden (view full) ---

741 nc->modes[NCSI_MODE_FC].enable = 1;
742 nc->modes[NCSI_MODE_FC].data[0] = rsp->fc_mode;
743 nc->modes[NCSI_MODE_AEN].enable = 1;
744 nc->modes[NCSI_MODE_AEN].data[0] = ntohl(rsp->aen_mode);
745
746 /* MAC addresses filter table */
747 pdata = (unsigned char *)rsp + 48;
748 enable = rsp->mac_enable;
687
688 /* Find the channel */
689 rsp = (struct ncsi_rsp_gp_pkt *)skb_network_header(nr->rsp);
690 ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
691 NULL, &nc);
692 if (!nc)
693 return -ENODEV;
694

--- 17 unchanged lines hidden (view full) ---

712 nc->modes[NCSI_MODE_FC].enable = 1;
713 nc->modes[NCSI_MODE_FC].data[0] = rsp->fc_mode;
714 nc->modes[NCSI_MODE_AEN].enable = 1;
715 nc->modes[NCSI_MODE_AEN].data[0] = ntohl(rsp->aen_mode);
716
717 /* MAC addresses filter table */
718 pdata = (unsigned char *)rsp + 48;
719 enable = rsp->mac_enable;
720 ncmf = &nc->mac_filter;
721 spin_lock_irqsave(&nc->lock, flags);
722 bitmap = &ncmf->bitmap;
749 for (i = 0; i < rsp->mac_cnt; i++, pdata += 6) {
723 for (i = 0; i < rsp->mac_cnt; i++, pdata += 6) {
750 if (i >= (nc->filters[NCSI_FILTER_UC]->total +
751 nc->filters[NCSI_FILTER_MC]->total))
752 table = NCSI_FILTER_MIXED;
753 else if (i >= nc->filters[NCSI_FILTER_UC]->total)
754 table = NCSI_FILTER_MC;
724 if (!(enable & (0x1 << i)))
725 clear_bit(i, bitmap);
755 else
726 else
756 table = NCSI_FILTER_UC;
727 set_bit(i, bitmap);
757
728
758 if (!(enable & (0x1 << i)))
759 continue;
760
761 if (ncsi_find_filter(nc, table, pdata) >= 0)
762 continue;
763
764 ncsi_add_filter(nc, table, pdata);
729 memcpy(&ncmf->addrs[i * ETH_ALEN], pdata, ETH_ALEN);
765 }
730 }
731 spin_unlock_irqrestore(&nc->lock, flags);
766
767 /* VLAN filter table */
768 enable = ntohs(rsp->vlan_enable);
732
733 /* VLAN filter table */
734 enable = ntohs(rsp->vlan_enable);
735 ncvf = &nc->vlan_filter;
736 bitmap = &ncvf->bitmap;
737 spin_lock_irqsave(&nc->lock, flags);
769 for (i = 0; i < rsp->vlan_cnt; i++, pdata += 2) {
770 if (!(enable & (0x1 << i)))
738 for (i = 0; i < rsp->vlan_cnt; i++, pdata += 2) {
739 if (!(enable & (0x1 << i)))
771 continue;
740 clear_bit(i, bitmap);
741 else
742 set_bit(i, bitmap);
772
743
773 vlan = ntohs(*(__be16 *)pdata);
774 if (ncsi_find_filter(nc, NCSI_FILTER_VLAN, &vlan) >= 0)
775 continue;
776
777 ncsi_add_filter(nc, NCSI_FILTER_VLAN, &vlan);
744 ncvf->vids[i] = ntohs(*(__be16 *)pdata);
778 }
745 }
746 spin_unlock_irqrestore(&nc->lock, flags);
779
780 return 0;
781}
782
783static int ncsi_rsp_handler_gcps(struct ncsi_request *nr)
784{
785 struct ncsi_rsp_gcps_pkt *rsp;
786 struct ncsi_dev_priv *ndp = nr->ndp;

--- 262 unchanged lines hidden ---
747
748 return 0;
749}
750
751static int ncsi_rsp_handler_gcps(struct ncsi_request *nr)
752{
753 struct ncsi_rsp_gcps_pkt *rsp;
754 struct ncsi_dev_priv *ndp = nr->ndp;

--- 262 unchanged lines hidden ---