mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-25 16:11:45 +00:00
i40evf: handle many MAC filters correctly
When a lot (many hundreds) of MAC or VLAN filters are added at one time, we can overflow the Admin Queue buffer size with all the requests. Unfortunately, the driver would then calculate the message size incorrectly, causing it to be rejected by the PF. Furthermore, there was no mechanism to trigger another request to allow for configuring the rest of the filters that didn't fit into the first request. To fix this, recalculate the correct buffer size when we detect the overflow condition instead of just assuming the max buffer size. Also, don't clear the request bit in adapter->aq_required when we have an overflow, so that the rest of the filters can be processed later. Change-ID: Idd7cbbc5af31315e0dcb1b10e6a02ad9817ce65c Signed-off-by: Mitch Williams <mitch.a.williams@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
8d8f2295d0
commit
1418c34581
1 changed files with 24 additions and 8 deletions
|
@ -391,6 +391,7 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter)
|
|||
struct i40e_virtchnl_ether_addr_list *veal;
|
||||
int len, i = 0, count = 0;
|
||||
struct i40evf_mac_filter *f;
|
||||
bool more = false;
|
||||
|
||||
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
|
||||
/* bail because we already have a command pending */
|
||||
|
@ -415,7 +416,9 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter)
|
|||
count = (I40EVF_MAX_AQ_BUF_SIZE -
|
||||
sizeof(struct i40e_virtchnl_ether_addr_list)) /
|
||||
sizeof(struct i40e_virtchnl_ether_addr);
|
||||
len = I40EVF_MAX_AQ_BUF_SIZE;
|
||||
len = sizeof(struct i40e_virtchnl_ether_addr_list) +
|
||||
(count * sizeof(struct i40e_virtchnl_ether_addr));
|
||||
more = true;
|
||||
}
|
||||
|
||||
veal = kzalloc(len, GFP_ATOMIC);
|
||||
|
@ -431,7 +434,8 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter)
|
|||
f->add = false;
|
||||
}
|
||||
}
|
||||
adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
|
||||
if (!more)
|
||||
adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_MAC_FILTER;
|
||||
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
|
||||
(u8 *)veal, len);
|
||||
kfree(veal);
|
||||
|
@ -450,6 +454,7 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter)
|
|||
struct i40e_virtchnl_ether_addr_list *veal;
|
||||
struct i40evf_mac_filter *f, *ftmp;
|
||||
int len, i = 0, count = 0;
|
||||
bool more = false;
|
||||
|
||||
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
|
||||
/* bail because we already have a command pending */
|
||||
|
@ -474,7 +479,9 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter)
|
|||
count = (I40EVF_MAX_AQ_BUF_SIZE -
|
||||
sizeof(struct i40e_virtchnl_ether_addr_list)) /
|
||||
sizeof(struct i40e_virtchnl_ether_addr);
|
||||
len = I40EVF_MAX_AQ_BUF_SIZE;
|
||||
len = sizeof(struct i40e_virtchnl_ether_addr_list) +
|
||||
(count * sizeof(struct i40e_virtchnl_ether_addr));
|
||||
more = true;
|
||||
}
|
||||
veal = kzalloc(len, GFP_ATOMIC);
|
||||
if (!veal)
|
||||
|
@ -490,7 +497,8 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter)
|
|||
kfree(f);
|
||||
}
|
||||
}
|
||||
adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
|
||||
if (!more)
|
||||
adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_MAC_FILTER;
|
||||
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
|
||||
(u8 *)veal, len);
|
||||
kfree(veal);
|
||||
|
@ -509,6 +517,7 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter)
|
|||
struct i40e_virtchnl_vlan_filter_list *vvfl;
|
||||
int len, i = 0, count = 0;
|
||||
struct i40evf_vlan_filter *f;
|
||||
bool more = false;
|
||||
|
||||
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
|
||||
/* bail because we already have a command pending */
|
||||
|
@ -534,7 +543,9 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter)
|
|||
count = (I40EVF_MAX_AQ_BUF_SIZE -
|
||||
sizeof(struct i40e_virtchnl_vlan_filter_list)) /
|
||||
sizeof(u16);
|
||||
len = I40EVF_MAX_AQ_BUF_SIZE;
|
||||
len = sizeof(struct i40e_virtchnl_vlan_filter_list) +
|
||||
(count * sizeof(u16));
|
||||
more = true;
|
||||
}
|
||||
vvfl = kzalloc(len, GFP_ATOMIC);
|
||||
if (!vvfl)
|
||||
|
@ -549,7 +560,8 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter)
|
|||
f->add = false;
|
||||
}
|
||||
}
|
||||
adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
|
||||
if (!more)
|
||||
adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_VLAN_FILTER;
|
||||
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_ADD_VLAN, (u8 *)vvfl, len);
|
||||
kfree(vvfl);
|
||||
}
|
||||
|
@ -567,6 +579,7 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter)
|
|||
struct i40e_virtchnl_vlan_filter_list *vvfl;
|
||||
struct i40evf_vlan_filter *f, *ftmp;
|
||||
int len, i = 0, count = 0;
|
||||
bool more = false;
|
||||
|
||||
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
|
||||
/* bail because we already have a command pending */
|
||||
|
@ -592,7 +605,9 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter)
|
|||
count = (I40EVF_MAX_AQ_BUF_SIZE -
|
||||
sizeof(struct i40e_virtchnl_vlan_filter_list)) /
|
||||
sizeof(u16);
|
||||
len = I40EVF_MAX_AQ_BUF_SIZE;
|
||||
len = sizeof(struct i40e_virtchnl_vlan_filter_list) +
|
||||
(count * sizeof(u16));
|
||||
more = true;
|
||||
}
|
||||
vvfl = kzalloc(len, GFP_ATOMIC);
|
||||
if (!vvfl)
|
||||
|
@ -608,7 +623,8 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter)
|
|||
kfree(f);
|
||||
}
|
||||
}
|
||||
adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
|
||||
if (!more)
|
||||
adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_VLAN_FILTER;
|
||||
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_DEL_VLAN, (u8 *)vvfl, len);
|
||||
kfree(vvfl);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue