Commit 08feecd7 authored by Yuval Mintz's avatar Yuval Mintz Committed by David S. Miller

qed*: Support PVID configuration

This adds support for PF control over the VF vlan configuration.
I.e., `ip link ... vf <x> vlan <vid>' should now be supported.

 1. <vid> != 0 => VF receives [unknowingly] only traffic tagged by
    <vid> and tags all outgoing traffic sent by VF with <vid>.
 2. <vid> == 0 ==> Remove the pvid configuration, reverting to previous.
Signed-off-by: default avatarYuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fefb0202
...@@ -1104,9 +1104,16 @@ static void qed_hw_get_resc(struct qed_hwfn *p_hwfn) ...@@ -1104,9 +1104,16 @@ static void qed_hw_get_resc(struct qed_hwfn *p_hwfn)
u8 num_funcs = p_hwfn->num_funcs_on_engine; u8 num_funcs = p_hwfn->num_funcs_on_engine;
u32 *resc_num = p_hwfn->hw_info.resc_num; u32 *resc_num = p_hwfn->hw_info.resc_num;
struct qed_sb_cnt_info sb_cnt_info; struct qed_sb_cnt_info sb_cnt_info;
int i; int i, max_vf_vlan_filters;
memset(&sb_cnt_info, 0, sizeof(sb_cnt_info)); memset(&sb_cnt_info, 0, sizeof(sb_cnt_info));
#ifdef CONFIG_QED_SRIOV
max_vf_vlan_filters = QED_ETH_MAX_VF_NUM_VLAN_FILTERS;
#else
max_vf_vlan_filters = 0;
#endif
qed_int_get_num_sbs(p_hwfn, &sb_cnt_info); qed_int_get_num_sbs(p_hwfn, &sb_cnt_info);
resc_num[QED_SB] = min_t(u32, resc_num[QED_SB] = min_t(u32,
......
...@@ -114,7 +114,8 @@ int qed_sp_vport_start(struct qed_hwfn *p_hwfn, ...@@ -114,7 +114,8 @@ int qed_sp_vport_start(struct qed_hwfn *p_hwfn,
p_params->mtu, p_params->mtu,
p_params->remove_inner_vlan, p_params->remove_inner_vlan,
p_params->tpa_mode, p_params->tpa_mode,
p_params->max_buffers_per_cqe); p_params->max_buffers_per_cqe,
p_params->only_untagged);
} }
return qed_sp_eth_vport_start(p_hwfn, p_params); return qed_sp_eth_vport_start(p_hwfn, p_params);
...@@ -367,6 +368,16 @@ int qed_sp_vport_update(struct qed_hwfn *p_hwfn, ...@@ -367,6 +368,16 @@ int qed_sp_vport_update(struct qed_hwfn *p_hwfn,
p_cmn->inner_vlan_removal_en = p_params->inner_vlan_removal_flg; p_cmn->inner_vlan_removal_en = p_params->inner_vlan_removal_flg;
val = p_params->update_inner_vlan_removal_flg; val = p_params->update_inner_vlan_removal_flg;
p_cmn->update_inner_vlan_removal_en_flg = val; p_cmn->update_inner_vlan_removal_en_flg = val;
p_cmn->default_vlan_en = p_params->default_vlan_enable_flg;
val = p_params->update_default_vlan_enable_flg;
p_cmn->update_default_vlan_en_flg = val;
p_cmn->default_vlan = cpu_to_le16(p_params->default_vlan);
p_cmn->update_default_vlan_flg = p_params->update_default_vlan_flg;
p_cmn->silent_vlan_removal_en = p_params->silent_vlan_removal_flg;
p_ramrod->common.tx_switching_en = p_params->tx_switching_flg; p_ramrod->common.tx_switching_en = p_params->tx_switching_flg;
p_cmn->update_tx_switching_en_flg = p_params->update_tx_switching_flg; p_cmn->update_tx_switching_en_flg = p_params->update_tx_switching_flg;
...@@ -1702,6 +1713,7 @@ static int qed_start_vport(struct qed_dev *cdev, ...@@ -1702,6 +1713,7 @@ static int qed_start_vport(struct qed_dev *cdev,
start.tpa_mode = params->gro_enable ? QED_TPA_MODE_GRO : start.tpa_mode = params->gro_enable ? QED_TPA_MODE_GRO :
QED_TPA_MODE_NONE; QED_TPA_MODE_NONE;
start.remove_inner_vlan = params->remove_inner_vlan; start.remove_inner_vlan = params->remove_inner_vlan;
start.only_untagged = true; /* untagged only */
start.drop_ttl0 = params->drop_ttl0; start.drop_ttl0 = params->drop_ttl0;
start.opaque_fid = p_hwfn->hw_info.opaque_fid; start.opaque_fid = p_hwfn->hw_info.opaque_fid;
start.concrete_fid = p_hwfn->hw_info.concrete_fid; start.concrete_fid = p_hwfn->hw_info.concrete_fid;
......
...@@ -94,6 +94,7 @@ enum qed_tpa_mode { ...@@ -94,6 +94,7 @@ enum qed_tpa_mode {
struct qed_sp_vport_start_params { struct qed_sp_vport_start_params {
enum qed_tpa_mode tpa_mode; enum qed_tpa_mode tpa_mode;
bool remove_inner_vlan; bool remove_inner_vlan;
bool only_untagged;
bool drop_ttl0; bool drop_ttl0;
u8 max_buffers_per_cqe; u8 max_buffers_per_cqe;
u32 concrete_fid; u32 concrete_fid;
...@@ -140,6 +141,11 @@ struct qed_sp_vport_update_params { ...@@ -140,6 +141,11 @@ struct qed_sp_vport_update_params {
u8 vport_active_tx_flg; u8 vport_active_tx_flg;
u8 update_inner_vlan_removal_flg; u8 update_inner_vlan_removal_flg;
u8 inner_vlan_removal_flg; u8 inner_vlan_removal_flg;
u8 silent_vlan_removal_flg;
u8 update_default_vlan_enable_flg;
u8 default_vlan_enable_flg;
u8 update_default_vlan_flg;
u16 default_vlan;
u8 update_tx_switching_flg; u8 update_tx_switching_flg;
u8 tx_switching_flg; u8 tx_switching_flg;
u8 update_approx_mcast_flg; u8 update_approx_mcast_flg;
......
This diff is collapsed.
...@@ -24,6 +24,9 @@ ...@@ -24,6 +24,9 @@
#define QED_MAX_VF_CHAINS_PER_PF 16 #define QED_MAX_VF_CHAINS_PER_PF 16
#define QED_ETH_VF_NUM_VLAN_FILTERS 2 #define QED_ETH_VF_NUM_VLAN_FILTERS 2
#define QED_ETH_MAX_VF_NUM_VLAN_FILTERS \
(MAX_NUM_VFS * QED_ETH_VF_NUM_VLAN_FILTERS)
enum qed_iov_vport_update_flag { enum qed_iov_vport_update_flag {
QED_IOV_VP_UPDATE_ACTIVATE, QED_IOV_VP_UPDATE_ACTIVATE,
QED_IOV_VP_UPDATE_VLAN_STRIP, QED_IOV_VP_UPDATE_VLAN_STRIP,
...@@ -40,6 +43,7 @@ struct qed_public_vf_info { ...@@ -40,6 +43,7 @@ struct qed_public_vf_info {
/* These copies will later be reflected in the bulletin board, /* These copies will later be reflected in the bulletin board,
* but this copy should be newer. * but this copy should be newer.
*/ */
u16 forced_vlan;
u8 mac[ETH_ALEN]; u8 mac[ETH_ALEN];
}; };
...@@ -98,6 +102,18 @@ enum vf_state { ...@@ -98,6 +102,18 @@ enum vf_state {
VF_STOPPED /* VF, Stopped */ VF_STOPPED /* VF, Stopped */
}; };
struct qed_vf_vlan_shadow {
bool used;
u16 vid;
};
struct qed_vf_shadow_config {
/* Shadow copy of all guest vlans */
struct qed_vf_vlan_shadow vlans[QED_ETH_VF_NUM_VLAN_FILTERS + 1];
u8 inner_vlan_removal;
};
/* PFs maintain an array of this structure, per VF */ /* PFs maintain an array of this structure, per VF */
struct qed_vf_info { struct qed_vf_info {
struct qed_iov_vf_mbx vf_mbx; struct qed_iov_vf_mbx vf_mbx;
...@@ -131,6 +147,16 @@ struct qed_vf_info { ...@@ -131,6 +147,16 @@ struct qed_vf_info {
u16 igu_sbs[QED_MAX_VF_CHAINS_PER_PF]; u16 igu_sbs[QED_MAX_VF_CHAINS_PER_PF];
u8 num_active_rxqs; u8 num_active_rxqs;
struct qed_public_vf_info p_vf_info; struct qed_public_vf_info p_vf_info;
/* Stores the configuration requested by VF */
struct qed_vf_shadow_config shadow_config;
/* A bitfield using bulletin's valid-map bits, used to indicate
* which of the bulletin board features have been configured.
*/
u64 configured_features;
#define QED_IOV_CONFIGURED_FEATURES_MASK ((1 << MAC_ADDR_FORCED) | \
(1 << VLAN_ADDR_FORCED))
}; };
/* This structure is part of qed_hwfn and used only for PFs that have sriov /* This structure is part of qed_hwfn and used only for PFs that have sriov
......
...@@ -474,7 +474,7 @@ int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn, ...@@ -474,7 +474,7 @@ int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn,
u16 mtu, u16 mtu,
u8 inner_vlan_removal, u8 inner_vlan_removal,
enum qed_tpa_mode tpa_mode, enum qed_tpa_mode tpa_mode,
u8 max_buffers_per_cqe) u8 max_buffers_per_cqe, u8 only_untagged)
{ {
struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info;
struct vfpf_vport_start_tlv *req; struct vfpf_vport_start_tlv *req;
...@@ -489,6 +489,7 @@ int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn, ...@@ -489,6 +489,7 @@ int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn,
req->inner_vlan_removal = inner_vlan_removal; req->inner_vlan_removal = inner_vlan_removal;
req->tpa_mode = tpa_mode; req->tpa_mode = tpa_mode;
req->max_buffers_per_cqe = max_buffers_per_cqe; req->max_buffers_per_cqe = max_buffers_per_cqe;
req->only_untagged = only_untagged;
/* status blocks */ /* status blocks */
for (i = 0; i < p_hwfn->vf_iov_info->acquire_resp.resc.num_sbs; i++) for (i = 0; i < p_hwfn->vf_iov_info->acquire_resp.resc.num_sbs; i++)
...@@ -547,6 +548,8 @@ qed_vf_handle_vp_update_is_needed(struct qed_hwfn *p_hwfn, ...@@ -547,6 +548,8 @@ qed_vf_handle_vp_update_is_needed(struct qed_hwfn *p_hwfn,
return !!p_data->update_tx_switching_flg; return !!p_data->update_tx_switching_flg;
case CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP: case CHANNEL_TLV_VPORT_UPDATE_VLAN_STRIP:
return !!p_data->update_inner_vlan_removal_flg; return !!p_data->update_inner_vlan_removal_flg;
case CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN:
return !!p_data->update_accept_any_vlan_flg;
case CHANNEL_TLV_VPORT_UPDATE_MCAST: case CHANNEL_TLV_VPORT_UPDATE_MCAST:
return !!p_data->update_approx_mcast_flg; return !!p_data->update_approx_mcast_flg;
case CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM: case CHANNEL_TLV_VPORT_UPDATE_ACCEPT_PARAM:
...@@ -696,6 +699,19 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn, ...@@ -696,6 +699,19 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn,
sizeof(rss_params->rss_key)); sizeof(rss_params->rss_key));
} }
if (p_params->update_accept_any_vlan_flg) {
struct vfpf_vport_update_accept_any_vlan_tlv *p_any_vlan_tlv;
size = sizeof(struct vfpf_vport_update_accept_any_vlan_tlv);
tlv = CHANNEL_TLV_VPORT_UPDATE_ACCEPT_ANY_VLAN;
p_any_vlan_tlv = qed_add_tlv(p_hwfn, &p_iov->offset, tlv, size);
resp_size += sizeof(struct pfvf_def_resp_tlv);
p_any_vlan_tlv->accept_any_vlan = p_params->accept_any_vlan;
p_any_vlan_tlv->update_accept_any_vlan_flg =
p_params->update_accept_any_vlan_flg;
}
/* add list termination tlv */ /* add list termination tlv */
qed_add_tlv(p_hwfn, &p_iov->offset, qed_add_tlv(p_hwfn, &p_iov->offset,
CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
......
...@@ -417,6 +417,16 @@ union pfvf_tlvs { ...@@ -417,6 +417,16 @@ union pfvf_tlvs {
struct pfvf_start_queue_resp_tlv queue_start; struct pfvf_start_queue_resp_tlv queue_start;
}; };
enum qed_bulletin_bit {
/* Alert the VF that a forced VLAN was set by the PF */
VLAN_ADDR_FORCED = 2,
/* Indicate that `default_only_untagged' contains actual data */
VFPF_BULLETIN_UNTAGGED_DEFAULT = 3,
VFPF_BULLETIN_UNTAGGED_DEFAULT_FORCED = 4,
};
struct qed_bulletin_content { struct qed_bulletin_content {
/* crc of structure to ensure is not in mid-update */ /* crc of structure to ensure is not in mid-update */
u32 crc; u32 crc;
...@@ -465,6 +475,10 @@ struct qed_bulletin_content { ...@@ -465,6 +475,10 @@ struct qed_bulletin_content {
u32 partner_adv_speed; u32 partner_adv_speed;
u32 capability_speed; u32 capability_speed;
/* Forced vlan */
u16 pvid;
u16 padding5;
}; };
struct qed_bulletin { struct qed_bulletin {
...@@ -737,7 +751,7 @@ int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn, ...@@ -737,7 +751,7 @@ int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn,
u16 mtu, u16 mtu,
u8 inner_vlan_removal, u8 inner_vlan_removal,
enum qed_tpa_mode tpa_mode, enum qed_tpa_mode tpa_mode,
u8 max_buffers_per_cqe); u8 max_buffers_per_cqe, u8 only_untagged);
/** /**
* @brief qed_vf_pf_vport_stop - stop the VF's vport * @brief qed_vf_pf_vport_stop - stop the VF's vport
...@@ -898,7 +912,8 @@ static inline int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn, ...@@ -898,7 +912,8 @@ static inline int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn,
u16 mtu, u16 mtu,
u8 inner_vlan_removal, u8 inner_vlan_removal,
enum qed_tpa_mode tpa_mode, enum qed_tpa_mode tpa_mode,
u8 max_buffers_per_cqe) u8 max_buffers_per_cqe,
u8 only_untagged)
{ {
return -EINVAL; return -EINVAL;
} }
......
...@@ -103,6 +103,21 @@ static int qede_alloc_rx_buffer(struct qede_dev *edev, ...@@ -103,6 +103,21 @@ static int qede_alloc_rx_buffer(struct qede_dev *edev,
static void qede_link_update(void *dev, struct qed_link_output *link); static void qede_link_update(void *dev, struct qed_link_output *link);
#ifdef CONFIG_QED_SRIOV #ifdef CONFIG_QED_SRIOV
static int qede_set_vf_vlan(struct net_device *ndev, int vf, u16 vlan, u8 qos)
{
struct qede_dev *edev = netdev_priv(ndev);
if (vlan > 4095) {
DP_NOTICE(edev, "Illegal vlan value %d\n", vlan);
return -EINVAL;
}
DP_VERBOSE(edev, QED_MSG_IOV, "Setting Vlan 0x%04x to VF [%d]\n",
vlan, vf);
return edev->ops->iov->set_vlan(edev->cdev, vlan, vf);
}
static int qede_sriov_configure(struct pci_dev *pdev, int num_vfs_param) static int qede_sriov_configure(struct pci_dev *pdev, int num_vfs_param)
{ {
struct qede_dev *edev = netdev_priv(pci_get_drvdata(pdev)); struct qede_dev *edev = netdev_priv(pci_get_drvdata(pdev));
...@@ -2071,6 +2086,9 @@ static const struct net_device_ops qede_netdev_ops = { ...@@ -2071,6 +2086,9 @@ static const struct net_device_ops qede_netdev_ops = {
.ndo_set_mac_address = qede_set_mac_addr, .ndo_set_mac_address = qede_set_mac_addr,
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = qede_change_mtu, .ndo_change_mtu = qede_change_mtu,
#ifdef CONFIG_QED_SRIOV
.ndo_set_vf_vlan = qede_set_vf_vlan,
#endif
.ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid, .ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid, .ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid,
.ndo_get_stats64 = qede_get_stats64, .ndo_get_stats64 = qede_get_stats64,
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
struct qed_iov_hv_ops { struct qed_iov_hv_ops {
int (*configure)(struct qed_dev *cdev, int num_vfs_param); int (*configure)(struct qed_dev *cdev, int num_vfs_param);
int (*set_vlan) (struct qed_dev *cdev, u16 vid, int vfid);
}; };
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment