| @@ -626,6 +626,33 @@ static void iavf_mac_add_reject(struct iavf_adapter *adapter) · 625 unmodified lines |
| 626 | 626 | spin_unlock_bh(&adapter->mac_vlan_list_lock); |
| 627 | 627 | } |
| 628 | 628 | |
| 629 | +/** |
| 630 | + * iavf_vlan_add_reject |
| 631 | + * @adapter: adapter structure |
| 632 | + * |
| 633 | + * Remove VLAN filters from list based on PF response. |
| 634 | + **/ |
| 635 | +static void iavf_vlan_add_reject(struct iavf_adapter *adapter) |
| 636 | +{ |
| 637 | + struct iavf_vlan_filter *f, *ftmp; |
| 638 | + |
| 639 | + spin_lock_bh(&adapter->mac_vlan_list_lock); |
| 640 | + list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) { |
| 641 | + if (f->is_new_vlan) { |
| 642 | + if (f->vlan.tpid == ETH_P_8021Q) |
| 643 | + clear_bit(f->vlan.vid, |
| 644 | + adapter->vsi.active_cvlans); |
| 645 | + else |
| 646 | + clear_bit(f->vlan.vid, |
| 647 | + adapter->vsi.active_svlans); |
| 648 | + |
| 649 | + list_del(&f->list); |
| 650 | + kfree(f); |
| 651 | + } |
| 652 | + } |
| 653 | + spin_unlock_bh(&adapter->mac_vlan_list_lock); |
| 654 | +} |
| 655 | + |
| 629 | 656 | /** |
| 630 | 657 | * iavf_add_vlans |
| 631 | 658 | * @adapter: adapter structure |
| @@ -683,6 +710,7 @@ void iavf_add_vlans(struct iavf_adapter *adapter) · 51 unmodified lines |
| 683 | 710 | vvfl->vlan_id[i] = f->vlan.vid; |
| 684 | 711 | i++; |
| 685 | 712 | f->add = false; |
| 713 | + f->is_new_vlan = true; |
| 686 | 714 | if (i == count) |
| 687 | 715 | break; |
| 688 | 716 | } |
| @@ -695,10 +723,18 @@ void iavf_add_vlans(struct iavf_adapter *adapter) · 6 unmodified lines |
| 695 | 723 | iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len); |
| 696 | 724 | kfree(vvfl); |
| 697 | 725 | } else { |
| 726 | + u16 max_vlans = adapter->vlan_v2_caps.filtering.max_filters; |
| 727 | + u16 current_vlans = iavf_get_num_vlans_added(adapter); |
| 698 | 728 | struct virtchnl_vlan_filter_list_v2 *vvfl_v2; |
| 699 | 729 | |
| 700 | 730 | adapter->current_op = VIRTCHNL_OP_ADD_VLAN_V2; |
| 701 | 731 | |
| 732 | + if ((count + current_vlans) > max_vlans && |
| 733 | + current_vlans < max_vlans) { |
| 734 | + count = max_vlans - iavf_get_num_vlans_added(adapter); |
| 735 | + more = true; |
| 736 | + } |
| 737 | + |
| 702 | 738 | len = sizeof(*vvfl_v2) + ((count - 1) * |
| 703 | 739 | sizeof(struct virtchnl_vlan_filter)); |
| 704 | 740 | if (len > IAVF_MAX_AQ_BUF_SIZE) { |
| @@ -725,6 +761,9 @@ void iavf_add_vlans(struct iavf_adapter *adapter) · 20 unmodified lines |
| 725 | 761 | &adapter->vlan_v2_caps.filtering.filtering_support; |
| 726 | 762 | struct virtchnl_vlan *vlan; |
| 727 | 763 | |
| 764 | + if (i == count) |
| 765 | + break; |
| 766 | + |
| 728 | 767 | /* give priority over outer if it's enabled */ |
| 729 | 768 | if (filtering_support->outer) |
| 730 | 769 | vlan = &vvfl_v2->filters[i].outer; |
| @@ -736,8 +775,7 @@ void iavf_add_vlans(struct iavf_adapter *adapter) · 5 unmodified lines |
| 736 | 775 | |
| 737 | 776 | i++; |
| 738 | 777 | f->add = false; |
| 739 | | − if (i == count) |
| 740 | | − break; |
| 778 | + f->is_new_vlan = true; |
| 741 | 779 | } |
| 742 | 780 | } |
| 743 | 781 | |
| @@ -2080,6 +2118,11 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, · 1336 unmodified lines |
| 2080 | 2118 | */ |
| 2081 | 2119 | iavf_netdev_features_vlan_strip_set(netdev, true); |
| 2082 | 2120 | break; |
| 2121 | + case VIRTCHNL_OP_ADD_VLAN_V2: |
| 2122 | + iavf_vlan_add_reject(adapter); |
| 2123 | + dev_warn(&adapter->pdev->dev, "Failed to add VLAN filter, error %s\n", |
| 2124 | + iavf_stat_str(&adapter->hw, v_retval)); |
| 2125 | + break; |
| 2083 | 2126 | default: |
| 2084 | 2127 | dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n", |
| 2085 | 2128 | v_retval, iavf_stat_str(&adapter->hw, v_retval), |
| @@ -2332,6 +2375,24 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter, · 246 unmodified lines |
| 2332 | 2375 | spin_unlock_bh(&adapter->adv_rss_lock); |
| 2333 | 2376 | } |
| 2334 | 2377 | break; |
| 2378 | + case VIRTCHNL_OP_ADD_VLAN_V2: { |
| 2379 | + struct iavf_vlan_filter *f; |
| 2380 | + |
| 2381 | + spin_lock_bh(&adapter->mac_vlan_list_lock); |
| 2382 | + list_for_each_entry(f, &adapter->vlan_filter_list, list) { |
| 2383 | + if (f->is_new_vlan) { |
| 2384 | + f->is_new_vlan = false; |
| 2385 | + if (f->vlan.tpid == ETH_P_8021Q) |
| 2386 | + set_bit(f->vlan.vid, |
| 2387 | + adapter->vsi.active_cvlans); |
| 2388 | + else |
| 2389 | + set_bit(f->vlan.vid, |
| 2390 | + adapter->vsi.active_svlans); |
| 2391 | + } |
| 2392 | + } |
| 2393 | + spin_unlock_bh(&adapter->mac_vlan_list_lock); |
| 2394 | + } |
| 2395 | + break; |
| 2335 | 2396 | case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING: |
| 2336 | 2397 | /* PF enabled vlan strip on this VF. |
| 2337 | 2398 | * Update netdev->features if needed to be in sync with ethtool. |