cxgb4/cxgb4vf: add support for ndo_set_vf_vlan
implement ndo_set_vf_vlan for mgmt netdevice to configure the PCIe VF. Original work by: Casey Leedom <leedom@chelsio.com> Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
43df215d99
commit
9d5fd927d2
9 changed files with 116 additions and 8 deletions
|
@ -820,6 +820,7 @@ struct vf_info {
|
||||||
unsigned char vf_mac_addr[ETH_ALEN];
|
unsigned char vf_mac_addr[ETH_ALEN];
|
||||||
unsigned int tx_rate;
|
unsigned int tx_rate;
|
||||||
bool pf_set_mac;
|
bool pf_set_mac;
|
||||||
|
u16 vlan;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mbox_list {
|
struct mbox_list {
|
||||||
|
@ -1738,4 +1739,6 @@ void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, struct sge_fl *fl);
|
||||||
void free_tx_desc(struct adapter *adap, struct sge_txq *q,
|
void free_tx_desc(struct adapter *adap, struct sge_txq *q,
|
||||||
unsigned int n, bool unmap);
|
unsigned int n, bool unmap);
|
||||||
void free_txq(struct adapter *adap, struct sge_txq *q);
|
void free_txq(struct adapter *adap, struct sge_txq *q);
|
||||||
|
int t4_set_vlan_acl(struct adapter *adap, unsigned int mbox, unsigned int vf,
|
||||||
|
u16 vlan);
|
||||||
#endif /* __CXGB4_H__ */
|
#endif /* __CXGB4_H__ */
|
||||||
|
|
|
@ -2783,7 +2783,30 @@ static int cxgb4_mgmt_set_vf_rate(struct net_device *dev, int vf,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
static int cxgb4_mgmt_set_vf_vlan(struct net_device *dev, int vf,
|
||||||
|
u16 vlan, u8 qos, __be16 vlan_proto)
|
||||||
|
{
|
||||||
|
struct port_info *pi = netdev_priv(dev);
|
||||||
|
struct adapter *adap = pi->adapter;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (vf >= adap->num_vfs || vlan > 4095 || qos > 7)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (vlan_proto != htons(ETH_P_8021Q) || qos != 0)
|
||||||
|
return -EPROTONOSUPPORT;
|
||||||
|
|
||||||
|
ret = t4_set_vlan_acl(adap, adap->mbox, vf + 1, vlan);
|
||||||
|
if (!ret) {
|
||||||
|
adap->vfinfo[vf].vlan = vlan;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_err(adap->pdev_dev, "Err %d %s VLAN ACL for PF/VF %d/%d\n",
|
||||||
|
ret, (vlan ? "setting" : "clearing"), adap->pf, vf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_PCI_IOV */
|
||||||
|
|
||||||
static int cxgb_set_mac_addr(struct net_device *dev, void *p)
|
static int cxgb_set_mac_addr(struct net_device *dev, void *p)
|
||||||
{
|
{
|
||||||
|
@ -3207,6 +3230,7 @@ static const struct net_device_ops cxgb4_mgmt_netdev_ops = {
|
||||||
.ndo_get_vf_config = cxgb4_mgmt_get_vf_config,
|
.ndo_get_vf_config = cxgb4_mgmt_get_vf_config,
|
||||||
.ndo_set_vf_rate = cxgb4_mgmt_set_vf_rate,
|
.ndo_set_vf_rate = cxgb4_mgmt_set_vf_rate,
|
||||||
.ndo_get_phys_port_id = cxgb4_mgmt_get_phys_port_id,
|
.ndo_get_phys_port_id = cxgb4_mgmt_get_phys_port_id,
|
||||||
|
.ndo_set_vf_vlan = cxgb4_mgmt_set_vf_vlan,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -9899,3 +9899,35 @@ int t4_i2c_rd(struct adapter *adap, unsigned int mbox, int port,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* t4_set_vlan_acl - Set a VLAN id for the specified VF
|
||||||
|
* @adapter: the adapter
|
||||||
|
* @mbox: mailbox to use for the FW command
|
||||||
|
* @vf: one of the VFs instantiated by the specified PF
|
||||||
|
* @vlan: The vlanid to be set
|
||||||
|
*/
|
||||||
|
int t4_set_vlan_acl(struct adapter *adap, unsigned int mbox, unsigned int vf,
|
||||||
|
u16 vlan)
|
||||||
|
{
|
||||||
|
struct fw_acl_vlan_cmd vlan_cmd;
|
||||||
|
unsigned int enable;
|
||||||
|
|
||||||
|
enable = (vlan ? FW_ACL_VLAN_CMD_EN_F : 0);
|
||||||
|
memset(&vlan_cmd, 0, sizeof(vlan_cmd));
|
||||||
|
vlan_cmd.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_ACL_VLAN_CMD) |
|
||||||
|
FW_CMD_REQUEST_F |
|
||||||
|
FW_CMD_WRITE_F |
|
||||||
|
FW_CMD_EXEC_F |
|
||||||
|
FW_ACL_VLAN_CMD_PFN_V(adap->pf) |
|
||||||
|
FW_ACL_VLAN_CMD_VFN_V(vf));
|
||||||
|
vlan_cmd.en_to_len16 = cpu_to_be32(enable | FW_LEN16(vlan_cmd));
|
||||||
|
/* Drop all packets that donot match vlan id */
|
||||||
|
vlan_cmd.dropnovlan_fm = FW_ACL_VLAN_CMD_FM_F;
|
||||||
|
if (enable != 0) {
|
||||||
|
vlan_cmd.nvlan = 1;
|
||||||
|
vlan_cmd.vlanid[0] = cpu_to_be16(vlan);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t4_wr_mbox(adap, adap->mbox, &vlan_cmd, sizeof(vlan_cmd), NULL);
|
||||||
|
}
|
||||||
|
|
|
@ -2353,14 +2353,22 @@ struct fw_acl_vlan_cmd {
|
||||||
#define FW_ACL_VLAN_CMD_VFN_S 0
|
#define FW_ACL_VLAN_CMD_VFN_S 0
|
||||||
#define FW_ACL_VLAN_CMD_VFN_V(x) ((x) << FW_ACL_VLAN_CMD_VFN_S)
|
#define FW_ACL_VLAN_CMD_VFN_V(x) ((x) << FW_ACL_VLAN_CMD_VFN_S)
|
||||||
|
|
||||||
#define FW_ACL_VLAN_CMD_EN_S 31
|
#define FW_ACL_VLAN_CMD_EN_S 31
|
||||||
#define FW_ACL_VLAN_CMD_EN_V(x) ((x) << FW_ACL_VLAN_CMD_EN_S)
|
#define FW_ACL_VLAN_CMD_EN_M 0x1
|
||||||
|
#define FW_ACL_VLAN_CMD_EN_V(x) ((x) << FW_ACL_VLAN_CMD_EN_S)
|
||||||
|
#define FW_ACL_VLAN_CMD_EN_G(x) \
|
||||||
|
(((x) >> S_FW_ACL_VLAN_CMD_EN_S) & FW_ACL_VLAN_CMD_EN_M)
|
||||||
|
#define FW_ACL_VLAN_CMD_EN_F FW_ACL_VLAN_CMD_EN_V(1U)
|
||||||
|
|
||||||
#define FW_ACL_VLAN_CMD_DROPNOVLAN_S 7
|
#define FW_ACL_VLAN_CMD_DROPNOVLAN_S 7
|
||||||
#define FW_ACL_VLAN_CMD_DROPNOVLAN_V(x) ((x) << FW_ACL_VLAN_CMD_DROPNOVLAN_S)
|
#define FW_ACL_VLAN_CMD_DROPNOVLAN_V(x) ((x) << FW_ACL_VLAN_CMD_DROPNOVLAN_S)
|
||||||
|
|
||||||
#define FW_ACL_VLAN_CMD_FM_S 6
|
#define FW_ACL_VLAN_CMD_FM_S 6
|
||||||
#define FW_ACL_VLAN_CMD_FM_V(x) ((x) << FW_ACL_VLAN_CMD_FM_S)
|
#define FW_ACL_VLAN_CMD_FM_M 0x1
|
||||||
|
#define FW_ACL_VLAN_CMD_FM_V(x) ((x) << FW_ACL_VLAN_CMD_FM_S)
|
||||||
|
#define FW_ACL_VLAN_CMD_FM_G(x) \
|
||||||
|
(((x) >> FW_ACL_VLAN_CMD_FM_S) & FW_ACL_VLAN_CMD_FM_M)
|
||||||
|
#define FW_ACL_VLAN_CMD_FM_F FW_ACL_VLAN_CMD_FM_V(1U)
|
||||||
|
|
||||||
/* old 16-bit port capabilities bitmap (fw_port_cap16_t) */
|
/* old 16-bit port capabilities bitmap (fw_port_cap16_t) */
|
||||||
enum fw_port_cap {
|
enum fw_port_cap {
|
||||||
|
|
|
@ -92,6 +92,7 @@ struct sge_rspq;
|
||||||
*/
|
*/
|
||||||
struct port_info {
|
struct port_info {
|
||||||
struct adapter *adapter; /* our adapter */
|
struct adapter *adapter; /* our adapter */
|
||||||
|
u32 vlan_id; /* vlan id for VST */
|
||||||
u16 viid; /* virtual interface ID */
|
u16 viid; /* virtual interface ID */
|
||||||
s16 xact_addr_filt; /* index of our MAC address filter */
|
s16 xact_addr_filt; /* index of our MAC address filter */
|
||||||
u16 rss_size; /* size of VI's RSS table slice */
|
u16 rss_size; /* size of VI's RSS table slice */
|
||||||
|
|
|
@ -791,6 +791,8 @@ static int cxgb4vf_open(struct net_device *dev)
|
||||||
if (err)
|
if (err)
|
||||||
goto err_unwind;
|
goto err_unwind;
|
||||||
|
|
||||||
|
pi->vlan_id = t4vf_get_vf_vlan_acl(adapter);
|
||||||
|
|
||||||
netif_tx_start_all_queues(dev);
|
netif_tx_start_all_queues(dev);
|
||||||
set_bit(pi->port_id, &adapter->open_device_map);
|
set_bit(pi->port_id, &adapter->open_device_map);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1202,6 +1202,10 @@ int t4vf_eth_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
BUG_ON(qidx >= pi->nqsets);
|
BUG_ON(qidx >= pi->nqsets);
|
||||||
txq = &adapter->sge.ethtxq[pi->first_qset + qidx];
|
txq = &adapter->sge.ethtxq[pi->first_qset + qidx];
|
||||||
|
|
||||||
|
if (pi->vlan_id && !skb_vlan_tag_present(skb))
|
||||||
|
__vlan_hwaccel_put_tag(skb, cpu_to_be16(ETH_P_8021Q),
|
||||||
|
pi->vlan_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Take this opportunity to reclaim any TX Descriptors whose DMA
|
* Take this opportunity to reclaim any TX Descriptors whose DMA
|
||||||
* transfers have completed.
|
* transfers have completed.
|
||||||
|
@ -1570,6 +1574,7 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
|
||||||
{
|
{
|
||||||
struct adapter *adapter = rxq->rspq.adapter;
|
struct adapter *adapter = rxq->rspq.adapter;
|
||||||
struct sge *s = &adapter->sge;
|
struct sge *s = &adapter->sge;
|
||||||
|
struct port_info *pi;
|
||||||
int ret;
|
int ret;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
|
@ -1586,8 +1591,9 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl,
|
||||||
skb->truesize += skb->data_len;
|
skb->truesize += skb->data_len;
|
||||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||||
skb_record_rx_queue(skb, rxq->rspq.idx);
|
skb_record_rx_queue(skb, rxq->rspq.idx);
|
||||||
|
pi = netdev_priv(skb->dev);
|
||||||
|
|
||||||
if (pkt->vlan_ex) {
|
if (pkt->vlan_ex && !pi->vlan_id) {
|
||||||
__vlan_hwaccel_put_tag(skb, cpu_to_be16(ETH_P_8021Q),
|
__vlan_hwaccel_put_tag(skb, cpu_to_be16(ETH_P_8021Q),
|
||||||
be16_to_cpu(pkt->vlan));
|
be16_to_cpu(pkt->vlan));
|
||||||
rxq->stats.vlan_ex++;
|
rxq->stats.vlan_ex++;
|
||||||
|
@ -1620,6 +1626,7 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
|
||||||
struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
|
struct sge_eth_rxq *rxq = container_of(rspq, struct sge_eth_rxq, rspq);
|
||||||
struct adapter *adapter = rspq->adapter;
|
struct adapter *adapter = rspq->adapter;
|
||||||
struct sge *s = &adapter->sge;
|
struct sge *s = &adapter->sge;
|
||||||
|
struct port_info *pi;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is a good TCP packet and we have Generic Receive Offload
|
* If this is a good TCP packet and we have Generic Receive Offload
|
||||||
|
@ -1644,6 +1651,7 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
|
||||||
__skb_pull(skb, s->pktshift);
|
__skb_pull(skb, s->pktshift);
|
||||||
skb->protocol = eth_type_trans(skb, rspq->netdev);
|
skb->protocol = eth_type_trans(skb, rspq->netdev);
|
||||||
skb_record_rx_queue(skb, rspq->idx);
|
skb_record_rx_queue(skb, rspq->idx);
|
||||||
|
pi = netdev_priv(skb->dev);
|
||||||
rxq->stats.pkts++;
|
rxq->stats.pkts++;
|
||||||
|
|
||||||
if (csum_ok && !pkt->err_vec &&
|
if (csum_ok && !pkt->err_vec &&
|
||||||
|
@ -1660,9 +1668,10 @@ int t4vf_ethrx_handler(struct sge_rspq *rspq, const __be64 *rsp,
|
||||||
} else
|
} else
|
||||||
skb_checksum_none_assert(skb);
|
skb_checksum_none_assert(skb);
|
||||||
|
|
||||||
if (pkt->vlan_ex) {
|
if (pkt->vlan_ex && !pi->vlan_id) {
|
||||||
rxq->stats.vlan_ex++;
|
rxq->stats.vlan_ex++;
|
||||||
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), be16_to_cpu(pkt->vlan));
|
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
|
||||||
|
be16_to_cpu(pkt->vlan));
|
||||||
}
|
}
|
||||||
|
|
||||||
netif_receive_skb(skb);
|
netif_receive_skb(skb);
|
||||||
|
|
|
@ -413,5 +413,6 @@ int t4vf_handle_fw_rpl(struct adapter *, const __be64 *);
|
||||||
int t4vf_prep_adapter(struct adapter *);
|
int t4vf_prep_adapter(struct adapter *);
|
||||||
int t4vf_get_vf_mac_acl(struct adapter *adapter, unsigned int pf,
|
int t4vf_get_vf_mac_acl(struct adapter *adapter, unsigned int pf,
|
||||||
unsigned int *naddr, u8 *addr);
|
unsigned int *naddr, u8 *addr);
|
||||||
|
int t4vf_get_vf_vlan_acl(struct adapter *adapter);
|
||||||
|
|
||||||
#endif /* __T4VF_COMMON_H__ */
|
#endif /* __T4VF_COMMON_H__ */
|
||||||
|
|
|
@ -2147,3 +2147,31 @@ int t4vf_get_vf_mac_acl(struct adapter *adapter, unsigned int pf,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* t4vf_get_vf_vlan_acl - Get the VLAN ID to be set to
|
||||||
|
* the VI of this VF.
|
||||||
|
* @adapter: The adapter
|
||||||
|
*
|
||||||
|
* Find the VLAN ID to be set to the VF's VI. The requested VLAN ID
|
||||||
|
* is from the host OS via callback in the PF driver.
|
||||||
|
*/
|
||||||
|
int t4vf_get_vf_vlan_acl(struct adapter *adapter)
|
||||||
|
{
|
||||||
|
struct fw_acl_vlan_cmd cmd;
|
||||||
|
int vlan = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
cmd.op_to_vfn = htonl(FW_CMD_OP_V(FW_ACL_VLAN_CMD) |
|
||||||
|
FW_CMD_REQUEST_F | FW_CMD_READ_F);
|
||||||
|
|
||||||
|
/* Note: Do not enable the ACL */
|
||||||
|
cmd.en_to_len16 = cpu_to_be32((unsigned int)FW_LEN16(cmd));
|
||||||
|
|
||||||
|
ret = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &cmd);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
vlan = be16_to_cpu(cmd.vlanid[0]);
|
||||||
|
|
||||||
|
return vlan;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue