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 --- |