Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/if_ixl.c
Show First 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | |||||
static void ixl_set_promisc(struct ixl_ifx *); | static void ixl_set_promisc(struct ixl_ifx *); | ||||
static void ixl_add_multi(struct ixl_ifx *); | static void ixl_add_multi(struct ixl_ifx *); | ||||
static void ixl_del_multi(struct ixl_ifx *); | static void ixl_del_multi(struct ixl_ifx *); | ||||
static void ixl_register_vlan(void *, struct ifnet *, u16); | static void ixl_register_vlan(void *, struct ifnet *, u16); | ||||
static void ixl_unregister_vlan(void *, struct ifnet *, u16); | static void ixl_unregister_vlan(void *, struct ifnet *, u16); | ||||
static void ixl_setup_vlan_filters(struct ixl_vsi *); | static void ixl_setup_vlan_filters(struct ixl_vsi *); | ||||
static void ixl_init_filters(struct ixl_ifx *); | static void ixl_init_filters(struct ixl_ifx *); | ||||
static void ixl_reconfigure_filters(struct ixl_vsi *vsi); | |||||
static void ixl_add_filter(struct ixl_vsi *, u8 *, s16 vlan); | static void ixl_add_filter(struct ixl_vsi *, u8 *, s16 vlan); | ||||
static void ixl_del_filter(struct ixl_vsi *, u8 *, s16 vlan); | static void ixl_del_filter(struct ixl_vsi *, u8 *, s16 vlan); | ||||
static void ixl_add_hw_filters(struct ixl_vsi *, int, int); | static void ixl_add_hw_filters(struct ixl_vsi *, int, int); | ||||
static void ixl_del_hw_filters(struct ixl_vsi *, int); | static void ixl_del_hw_filters(struct ixl_vsi *, int); | ||||
static struct ixl_mac_filter * | static struct ixl_mac_filter * | ||||
ixl_find_filter(struct ixl_vsi *, u8 *, s16); | ixl_find_filter(struct ixl_vsi *, u8 *, s16); | ||||
static void ixl_add_mc_filter(struct ixl_ifx *, u8 *); | static void ixl_add_mc_filter(struct ixl_ifx *, u8 *); | ||||
static void ixl_free_mac_filters(struct ixl_vsi *vsi); | static void ixl_free_mac_filters(struct ixl_vsi *vsi); | ||||
▲ Show 20 Lines • Show All 1,043 Lines • ▼ Show 20 Lines | if (ixl_enable_msix) { | ||||
ixl_configure_itr(pf); | ixl_configure_itr(pf); | ||||
} else | } else | ||||
ixl_configure_legacy(pf); | ixl_configure_legacy(pf); | ||||
ixl_enable_rings(&ifx->vsi); | ixl_enable_rings(&ifx->vsi); | ||||
i40e_aq_set_default_vsi(hw, ifx->vsi.seid, NULL); | i40e_aq_set_default_vsi(hw, ifx->vsi.seid, NULL); | ||||
ixl_reconfigure_filters(vsi); | |||||
/* Set MTU in hardware*/ | /* Set MTU in hardware*/ | ||||
int aq_error = i40e_aq_set_mac_config(hw, ifx->max_frame_size, | int aq_error = i40e_aq_set_mac_config(hw, ifx->max_frame_size, | ||||
TRUE, 0, NULL); | TRUE, 0, NULL); | ||||
if (aq_error) | if (aq_error) | ||||
device_printf(ifx->dev, | device_printf(ifx->dev, | ||||
"aq_set_mac_config in init error, code %d\n", | "aq_set_mac_config in init error, code %d\n", | ||||
aq_error); | aq_error); | ||||
▲ Show 20 Lines • Show All 2,282 Lines • ▼ Show 20 Lines | ixl_add_mc_filter(struct ixl_ifx *ifx, u8 *macaddr) | ||||
bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN); | bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN); | ||||
f->vlan = IXL_VLAN_ANY; | f->vlan = IXL_VLAN_ANY; | ||||
f->flags |= (IXL_FILTER_ADD | IXL_FILTER_USED | f->flags |= (IXL_FILTER_ADD | IXL_FILTER_USED | ||||
| IXL_FILTER_MC); | | IXL_FILTER_MC); | ||||
return; | return; | ||||
} | } | ||||
static void | |||||
ixl_reconfigure_filters(struct ixl_vsi *vsi) | |||||
{ | |||||
ixl_add_hw_filters(vsi, IXL_FILTER_USED, vsi->num_macs); | |||||
} | |||||
/* | /* | ||||
** This routine adds macvlan filters | ** This routine adds macvlan filters | ||||
*/ | */ | ||||
static void | static void | ||||
ixl_add_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan) | ixl_add_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan) | ||||
{ | { | ||||
struct ixl_mac_filter *f, *tmp; | struct ixl_mac_filter *f, *tmp; | ||||
struct ixl_pf *pf; | struct ixl_pf *pf; | ||||
Show All 26 Lines | if (f == NULL) { | ||||
device_printf(dev, "WARNING: no filter available!!\n"); | device_printf(dev, "WARNING: no filter available!!\n"); | ||||
return; | return; | ||||
} | } | ||||
bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN); | bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN); | ||||
f->vlan = vlan; | f->vlan = vlan; | ||||
f->flags |= (IXL_FILTER_ADD | IXL_FILTER_USED); | f->flags |= (IXL_FILTER_ADD | IXL_FILTER_USED); | ||||
if (f->vlan != IXL_VLAN_ANY) | if (f->vlan != IXL_VLAN_ANY) | ||||
f->flags |= IXL_FILTER_VLAN; | f->flags |= IXL_FILTER_VLAN; | ||||
else | |||||
vsi->num_macs++; | |||||
ixl_add_hw_filters(vsi, f->flags, 1); | ixl_add_hw_filters(vsi, f->flags, 1); | ||||
return; | return; | ||||
} | } | ||||
static void | static void | ||||
ixl_del_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan) | ixl_del_filter(struct ixl_vsi *vsi, u8 *macaddr, s16 vlan) | ||||
{ | { | ||||
struct ixl_mac_filter *f; | struct ixl_mac_filter *f; | ||||
f = ixl_find_filter(vsi, macaddr, vlan); | f = ixl_find_filter(vsi, macaddr, vlan); | ||||
if (f == NULL) | if (f == NULL) | ||||
return; | return; | ||||
f->flags |= IXL_FILTER_DEL; | f->flags |= IXL_FILTER_DEL; | ||||
ixl_del_hw_filters(vsi, 1); | ixl_del_hw_filters(vsi, 1); | ||||
vsi->num_macs--; | |||||
/* Check if this is the last vlan removal */ | /* Check if this is the last vlan removal */ | ||||
if (vlan != IXL_VLAN_ANY && vsi->num_vlans == 0) { | if (vlan != IXL_VLAN_ANY && vsi->num_vlans == 0) { | ||||
/* Switch back to a non-vlan filter */ | /* Switch back to a non-vlan filter */ | ||||
ixl_del_filter(vsi, macaddr, 0); | ixl_del_filter(vsi, macaddr, 0); | ||||
ixl_add_filter(vsi, macaddr, IXL_VLAN_ANY); | ixl_add_filter(vsi, macaddr, IXL_VLAN_ANY); | ||||
} | } | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | ixl_add_hw_filters(struct ixl_vsi *vsi, int flags, int cnt) | ||||
** Scan the filter list, each time we find one | ** Scan the filter list, each time we find one | ||||
** we add it to the admin queue array and turn off | ** we add it to the admin queue array and turn off | ||||
** the add bit. | ** the add bit. | ||||
*/ | */ | ||||
SLIST_FOREACH(f, &vsi->ftl, next) { | SLIST_FOREACH(f, &vsi->ftl, next) { | ||||
if (f->flags == flags) { | if (f->flags == flags) { | ||||
b = &a[j]; // a pox on fvl long names :) | b = &a[j]; // a pox on fvl long names :) | ||||
bcopy(f->macaddr, b->mac_addr, ETHER_ADDR_LEN); | bcopy(f->macaddr, b->mac_addr, ETHER_ADDR_LEN); | ||||
b->vlan_tag = | if (f->vlan == IXL_VLAN_ANY) { | ||||
(f->vlan == IXL_VLAN_ANY ? 0 : f->vlan); | b->vlan_tag = 0; | ||||
b->flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH; | b->flags = I40E_AQC_MACVLAN_ADD_IGNORE_VLAN; | ||||
} else { | |||||
b->vlan_tag = f->vlan; | |||||
b->flags = 0; | |||||
} | |||||
b->flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH; | |||||
f->flags &= ~IXL_FILTER_ADD; | f->flags &= ~IXL_FILTER_ADD; | ||||
j++; | j++; | ||||
} | } | ||||
if (j == cnt) | if (j == cnt) | ||||
break; | break; | ||||
} | } | ||||
if (j > 0) { | if (j > 0) { | ||||
err = i40e_aq_add_macvlan(hw, vsi->seid, a, j, NULL); | err = i40e_aq_add_macvlan(hw, vsi->seid, a, j, NULL); | ||||
▲ Show 20 Lines • Show All 1,568 Lines • ▼ Show 20 Lines | ixl_vf_setup_vsi(struct ixl_pf *pf, struct ixl_vf *vf) | ||||
int error; | int error; | ||||
hw = &pf->hw; | hw = &pf->hw; | ||||
error = ixl_vf_alloc_vsi(pf, vf); | error = ixl_vf_alloc_vsi(pf, vf); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
vf->vsi.hw_filters_add = 0; | |||||
vf->vsi.hw_filters_del = 0; | |||||
ixl_add_filter(&vf->vsi, ixl_bcast_addr, IXL_VLAN_ANY); | |||||
ixl_reconfigure_filters(&vf->vsi); | |||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
ixl_vf_map_vsi_queue(struct i40e_hw *hw, struct ixl_vf *vf, int qnum, | ixl_vf_map_vsi_queue(struct i40e_hw *hw, struct ixl_vf *vf, int qnum, | ||||
uint32_t val) | uint32_t val) | ||||
{ | { | ||||
uint32_t qtable; | uint32_t qtable; | ||||
▲ Show 20 Lines • Show All 756 Lines • ▼ Show 20 Lines | if (error) { | ||||
i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_DISABLE_QUEUES, | i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_DISABLE_QUEUES, | ||||
I40E_ERR_TIMEOUT); | I40E_ERR_TIMEOUT); | ||||
return; | return; | ||||
} | } | ||||
ixl_send_vf_ack(pf, vf, I40E_VIRTCHNL_OP_DISABLE_QUEUES); | ixl_send_vf_ack(pf, vf, I40E_VIRTCHNL_OP_DISABLE_QUEUES); | ||||
} | } | ||||
static boolean_t | |||||
ixl_zero_mac(const uint8_t *addr) | |||||
{ | |||||
uint8_t zero[ETHER_ADDR_LEN] = {0, 0, 0, 0, 0, 0}; | |||||
return (cmp_etheraddr(addr, zero)); | |||||
} | |||||
static boolean_t | |||||
ixl_bcast_mac(const uint8_t *addr) | |||||
{ | |||||
return (cmp_etheraddr(addr, ixl_bcast_addr)); | |||||
} | |||||
static int | |||||
ixl_vf_mac_valid(struct ixl_vf *vf, const uint8_t *addr) | |||||
{ | |||||
if (ixl_zero_mac(addr) || ixl_bcast_mac(addr)) | |||||
return (EINVAL); | |||||
/* | |||||
* If the VF is not allowed to change its MAC address, don't let it | |||||
* set a MAC filter for an address that is not a multicast address and | |||||
* is not its assigned MAC. | |||||
*/ | |||||
if (!(vf->vf_flags & VF_FLAG_SET_MAC_CAP) && | |||||
!(ETHER_IS_MULTICAST(addr) || cmp_etheraddr(addr, vf->mac))) | |||||
return (EPERM); | |||||
return (0); | |||||
} | |||||
static void | static void | ||||
ixl_vf_add_mac_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | |||||
uint16_t msg_size) | |||||
{ | |||||
struct i40e_virtchnl_ether_addr_list *addr_list; | |||||
struct i40e_virtchnl_ether_addr *addr; | |||||
struct ixl_vsi *vsi; | |||||
int i; | |||||
size_t expected_size; | |||||
vsi = &vf->vsi; | |||||
if (msg_size < sizeof(*addr_list)) { | |||||
i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
addr_list = msg; | |||||
expected_size = sizeof(*addr_list) + | |||||
addr_list->num_elements * sizeof(*addr); | |||||
if (addr_list->num_elements == 0 || | |||||
addr_list->vsi_id != vsi->vsi_num || | |||||
msg_size != expected_size) { | |||||
i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
for (i = 0; i < addr_list->num_elements; i++) { | |||||
if (ixl_vf_mac_valid(vf, addr_list->list[i].addr) != 0) { | |||||
i40e_send_vf_nack(pf, vf, | |||||
I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS, I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
} | |||||
for (i = 0; i < addr_list->num_elements; i++) { | |||||
addr = &addr_list->list[i]; | |||||
ixl_add_filter(vsi, addr->addr, IXL_VLAN_ANY); | |||||
} | |||||
ixl_send_vf_ack(pf, vf, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS); | |||||
} | |||||
static void | |||||
ixl_vf_del_mac_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, | |||||
uint16_t msg_size) | |||||
{ | |||||
struct i40e_virtchnl_ether_addr_list *addr_list; | |||||
struct i40e_virtchnl_ether_addr *addr; | |||||
size_t expected_size; | |||||
int i; | |||||
if (msg_size < sizeof(*addr_list)) { | |||||
i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
addr_list = msg; | |||||
expected_size = sizeof(*addr_list) + | |||||
addr_list->num_elements * sizeof(*addr); | |||||
if (addr_list->num_elements == 0 || | |||||
addr_list->vsi_id != vf->vsi.vsi_num || | |||||
msg_size != expected_size) { | |||||
i40e_send_vf_nack(pf, vf, I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS, | |||||
I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
for (i = 0; i < addr_list->num_elements; i++) { | |||||
addr = &addr_list->list[i]; | |||||
if (ixl_zero_mac(addr->addr) || ixl_bcast_mac(addr->addr)) { | |||||
i40e_send_vf_nack(pf, vf, | |||||
I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS, I40E_ERR_PARAM); | |||||
return; | |||||
} | |||||
} | |||||
for (i = 0; i < addr_list->num_elements; i++) { | |||||
addr = &addr_list->list[i]; | |||||
ixl_del_filter(&vf->vsi, addr->addr, IXL_VLAN_ANY); | |||||
} | |||||
ixl_send_vf_ack(pf, vf, I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS); | |||||
} | |||||
static void | |||||
ixl_handle_vf_msg(struct ixl_pf *pf, struct i40e_arq_event_info *event) | ixl_handle_vf_msg(struct ixl_pf *pf, struct i40e_arq_event_info *event) | ||||
{ | { | ||||
struct ixl_vf *vf; | struct ixl_vf *vf; | ||||
void *msg; | void *msg; | ||||
uint16_t vf_num, msg_size; | uint16_t vf_num, msg_size; | ||||
uint32_t opcode; | uint32_t opcode; | ||||
vf_num = le16toh(event->desc.retval); | vf_num = le16toh(event->desc.retval); | ||||
Show All 34 Lines | ixl_handle_vf_msg(struct ixl_pf *pf, struct i40e_arq_event_info *event) | ||||
case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP: | case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP: | ||||
ixl_vf_config_irq_msg(pf, vf, msg, msg_size); | ixl_vf_config_irq_msg(pf, vf, msg, msg_size); | ||||
break; | break; | ||||
case I40E_VIRTCHNL_OP_ENABLE_QUEUES: | case I40E_VIRTCHNL_OP_ENABLE_QUEUES: | ||||
ixl_vf_enable_queues_msg(pf, vf, msg, msg_size); | ixl_vf_enable_queues_msg(pf, vf, msg, msg_size); | ||||
break; | break; | ||||
case I40E_VIRTCHNL_OP_DISABLE_QUEUES: | case I40E_VIRTCHNL_OP_DISABLE_QUEUES: | ||||
ixl_vf_disable_queues_msg(pf, vf, msg, msg_size); | ixl_vf_disable_queues_msg(pf, vf, msg, msg_size); | ||||
break; | |||||
case I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS: | |||||
ixl_vf_add_mac_msg(pf, vf, msg, msg_size); | |||||
break; | |||||
case I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS: | |||||
ixl_vf_del_mac_msg(pf, vf, msg, msg_size); | |||||
break; | break; | ||||
default: | default: | ||||
i40e_send_vf_nack(pf, vf, opcode, I40E_ERR_NOT_IMPLEMENTED); | i40e_send_vf_nack(pf, vf, opcode, I40E_ERR_NOT_IMPLEMENTED); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 149 Lines • Show Last 20 Lines |