Commit 57806b28 authored by David S. Miller's avatar David S. Miller

Merge branch 'octeontx2-trusted-vf'

Naveen Mamindlapalli says:

====================
octeontx2: Add trusted VF support

This series adds support for trusted VF. The trusted VF support
allows VFs to perform priviliged operations such as setting VF
interface in promiscuous mode, all-multicast mode and also
changing the VF MAC address even if it was asssigned by PF.

Patches #1 and #2 provides the necessary functionality for supporting
promiscuous and multicast packets on both the PF and VF.

Patches #3 and #4 enable trusted VF configuration support.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 52e597d3 b1dc2040
...@@ -197,6 +197,11 @@ enum nix_scheduler { ...@@ -197,6 +197,11 @@ enum nix_scheduler {
#define SDP_CHANNELS 256 #define SDP_CHANNELS 256
/* The mask is to extract lower 10-bits of channel number
* which CPT will pass to X2P.
*/
#define NIX_CHAN_CPT_X2P_MASK (0x3ffull)
/* NIX LSO format indices. /* NIX LSO format indices.
* As of now TSO is the only one using, so statically assigning indices. * As of now TSO is the only one using, so statically assigning indices.
*/ */
......
...@@ -134,6 +134,7 @@ M(MSIX_OFFSET, 0x005, msix_offset, msg_req, msix_offset_rsp) \ ...@@ -134,6 +134,7 @@ M(MSIX_OFFSET, 0x005, msix_offset, msg_req, msix_offset_rsp) \
M(VF_FLR, 0x006, vf_flr, msg_req, msg_rsp) \ M(VF_FLR, 0x006, vf_flr, msg_req, msg_rsp) \
M(PTP_OP, 0x007, ptp_op, ptp_req, ptp_rsp) \ M(PTP_OP, 0x007, ptp_op, ptp_req, ptp_rsp) \
M(GET_HW_CAP, 0x008, get_hw_cap, msg_req, get_hw_cap_rsp) \ M(GET_HW_CAP, 0x008, get_hw_cap, msg_req, get_hw_cap_rsp) \
M(SET_VF_PERM, 0x00b, set_vf_perm, set_vf_perm, msg_rsp) \
/* CGX mbox IDs (range 0x200 - 0x3FF) */ \ /* CGX mbox IDs (range 0x200 - 0x3FF) */ \
M(CGX_START_RXTX, 0x200, cgx_start_rxtx, msg_req, msg_rsp) \ M(CGX_START_RXTX, 0x200, cgx_start_rxtx, msg_req, msg_rsp) \
M(CGX_STOP_RXTX, 0x201, cgx_stop_rxtx, msg_req, msg_rsp) \ M(CGX_STOP_RXTX, 0x201, cgx_stop_rxtx, msg_req, msg_rsp) \
...@@ -611,7 +612,9 @@ enum nix_af_status { ...@@ -611,7 +612,9 @@ enum nix_af_status {
NIX_AF_INVAL_SSO_PF_FUNC = -420, NIX_AF_INVAL_SSO_PF_FUNC = -420,
NIX_AF_ERR_TX_VTAG_NOSPC = -421, NIX_AF_ERR_TX_VTAG_NOSPC = -421,
NIX_AF_ERR_RX_VTAG_INUSE = -422, NIX_AF_ERR_RX_VTAG_INUSE = -422,
NIX_AF_ERR_NPC_KEY_NOT_SUPP = -423, NIX_AF_ERR_PTP_CONFIG_FAIL = -423,
NIX_AF_ERR_NPC_KEY_NOT_SUPP = -424,
NIX_AF_ERR_INVALID_NIXBLK = -425,
}; };
/* For NIX RX vtag action */ /* For NIX RX vtag action */
...@@ -913,6 +916,7 @@ struct nix_rx_mode { ...@@ -913,6 +916,7 @@ struct nix_rx_mode {
#define NIX_RX_MODE_UCAST BIT(0) #define NIX_RX_MODE_UCAST BIT(0)
#define NIX_RX_MODE_PROMISC BIT(1) #define NIX_RX_MODE_PROMISC BIT(1)
#define NIX_RX_MODE_ALLMULTI BIT(2) #define NIX_RX_MODE_ALLMULTI BIT(2)
#define NIX_RX_MODE_USE_MCE BIT(3)
u16 mode; u16 mode;
}; };
...@@ -1228,6 +1232,14 @@ struct ptp_rsp { ...@@ -1228,6 +1232,14 @@ struct ptp_rsp {
u64 clk; u64 clk;
}; };
struct set_vf_perm {
struct mbox_msghdr hdr;
u16 vf;
#define RESET_VF_PERM BIT_ULL(0)
#define VF_TRUSTED BIT_ULL(1)
u64 flags;
};
/* CPT mailbox error codes /* CPT mailbox error codes
* Range 901 - 1000. * Range 901 - 1000.
*/ */
......
...@@ -438,7 +438,8 @@ struct nix_tx_action { ...@@ -438,7 +438,8 @@ struct nix_tx_action {
/* NPC MCAM reserved entry index per nixlf */ /* NPC MCAM reserved entry index per nixlf */
#define NIXLF_UCAST_ENTRY 0 #define NIXLF_UCAST_ENTRY 0
#define NIXLF_BCAST_ENTRY 1 #define NIXLF_BCAST_ENTRY 1
#define NIXLF_PROMISC_ENTRY 2 #define NIXLF_ALLMULTI_ENTRY 2
#define NIXLF_PROMISC_ENTRY 3
struct npc_coalesced_kpu_prfl { struct npc_coalesced_kpu_prfl {
#define NPC_SIGN 0x00666f727063706e #define NPC_SIGN 0x00666f727063706e
......
...@@ -1758,6 +1758,48 @@ int rvu_mbox_handler_get_hw_cap(struct rvu *rvu, struct msg_req *req, ...@@ -1758,6 +1758,48 @@ int rvu_mbox_handler_get_hw_cap(struct rvu *rvu, struct msg_req *req,
return 0; return 0;
} }
int rvu_mbox_handler_set_vf_perm(struct rvu *rvu, struct set_vf_perm *req,
struct msg_rsp *rsp)
{
struct rvu_hwinfo *hw = rvu->hw;
u16 pcifunc = req->hdr.pcifunc;
struct rvu_pfvf *pfvf;
int blkaddr, nixlf;
u16 target;
/* Only PF can add VF permissions */
if ((pcifunc & RVU_PFVF_FUNC_MASK) || is_afvf(pcifunc))
return -EOPNOTSUPP;
target = (pcifunc & ~RVU_PFVF_FUNC_MASK) | (req->vf + 1);
pfvf = rvu_get_pfvf(rvu, target);
if (req->flags & RESET_VF_PERM) {
pfvf->flags &= RVU_CLEAR_VF_PERM;
} else if (test_bit(PF_SET_VF_TRUSTED, &pfvf->flags) ^
(req->flags & VF_TRUSTED)) {
change_bit(PF_SET_VF_TRUSTED, &pfvf->flags);
/* disable multicast and promisc entries */
if (!test_bit(PF_SET_VF_TRUSTED, &pfvf->flags)) {
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, target);
if (blkaddr < 0)
return 0;
nixlf = rvu_get_lf(rvu, &hw->block[blkaddr],
target, 0);
if (nixlf < 0)
return 0;
npc_enadis_default_mce_entry(rvu, target, nixlf,
NIXLF_ALLMULTI_ENTRY,
false);
npc_enadis_default_mce_entry(rvu, target, nixlf,
NIXLF_PROMISC_ENTRY,
false);
}
}
return 0;
}
static int rvu_process_mbox_msg(struct otx2_mbox *mbox, int devid, static int rvu_process_mbox_msg(struct otx2_mbox *mbox, int devid,
struct mbox_msghdr *req) struct mbox_msghdr *req)
{ {
......
...@@ -223,13 +223,17 @@ struct rvu_pfvf { ...@@ -223,13 +223,17 @@ struct rvu_pfvf {
u16 maxlen; u16 maxlen;
u16 minlen; u16 minlen;
u8 pf_set_vf_cfg;
u8 mac_addr[ETH_ALEN]; /* MAC address of this PF/VF */ u8 mac_addr[ETH_ALEN]; /* MAC address of this PF/VF */
u8 default_mac[ETH_ALEN]; /* MAC address from FWdata */ u8 default_mac[ETH_ALEN]; /* MAC address from FWdata */
/* Broadcast pkt replication info */ /* Broadcast/Multicast/Promisc pkt replication info */
u16 bcast_mce_idx; u16 bcast_mce_idx;
u16 mcast_mce_idx;
u16 promisc_mce_idx;
struct nix_mce_list bcast_mce_list; struct nix_mce_list bcast_mce_list;
struct nix_mce_list mcast_mce_list;
struct nix_mce_list promisc_mce_list;
bool use_mce_list;
struct rvu_npc_mcam_rule *def_ucast_rule; struct rvu_npc_mcam_rule *def_ucast_rule;
...@@ -239,8 +243,18 @@ struct rvu_pfvf { ...@@ -239,8 +243,18 @@ struct rvu_pfvf {
u8 nix_blkaddr; /* BLKADDR_NIX0/1 assigned to this PF */ u8 nix_blkaddr; /* BLKADDR_NIX0/1 assigned to this PF */
u8 nix_rx_intf; /* NIX0_RX/NIX1_RX interface to NPC */ u8 nix_rx_intf; /* NIX0_RX/NIX1_RX interface to NPC */
u8 nix_tx_intf; /* NIX0_TX/NIX1_TX interface to NPC */ u8 nix_tx_intf; /* NIX0_TX/NIX1_TX interface to NPC */
unsigned long flags;
}; };
enum rvu_pfvf_flags {
NIXLF_INITIALIZED = 0,
PF_SET_VF_MAC,
PF_SET_VF_CFG,
PF_SET_VF_TRUSTED,
};
#define RVU_CLEAR_VF_PERM ~GENMASK(PF_SET_VF_TRUSTED, PF_SET_VF_MAC)
struct nix_txsch { struct nix_txsch {
struct rsrc_bmap schq; struct rsrc_bmap schq;
u8 lvl; u8 lvl;
...@@ -548,11 +562,16 @@ static inline u16 rvu_nix_chan_cpt(struct rvu *rvu, u8 chan) ...@@ -548,11 +562,16 @@ static inline u16 rvu_nix_chan_cpt(struct rvu *rvu, u8 chan)
/* Function Prototypes /* Function Prototypes
* RVU * RVU
*/ */
static inline int is_afvf(u16 pcifunc) static inline bool is_afvf(u16 pcifunc)
{ {
return !(pcifunc & ~RVU_PFVF_FUNC_MASK); return !(pcifunc & ~RVU_PFVF_FUNC_MASK);
} }
static inline bool is_vf(u16 pcifunc)
{
return !!(pcifunc & RVU_PFVF_FUNC_MASK);
}
/* check if PF_FUNC is AF */ /* check if PF_FUNC is AF */
static inline bool is_pffunc_af(u16 pcifunc) static inline bool is_pffunc_af(u16 pcifunc)
{ {
...@@ -608,6 +627,12 @@ static inline void rvu_get_cgx_lmac_id(u8 map, u8 *cgx_id, u8 *lmac_id) ...@@ -608,6 +627,12 @@ static inline void rvu_get_cgx_lmac_id(u8 map, u8 *cgx_id, u8 *lmac_id)
*lmac_id = (map & 0xF); *lmac_id = (map & 0xF);
} }
static inline bool is_cgx_vf(struct rvu *rvu, u16 pcifunc)
{
return ((pcifunc & RVU_PFVF_FUNC_MASK) &&
is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc)));
}
#define M(_name, _id, fn_name, req, rsp) \ #define M(_name, _id, fn_name, req, rsp) \
int rvu_mbox_handler_ ## fn_name(struct rvu *, struct req *, struct rsp *); int rvu_mbox_handler_ ## fn_name(struct rvu *, struct req *, struct rsp *);
MBOX_MESSAGES MBOX_MESSAGES
...@@ -637,10 +662,16 @@ void rvu_nix_freemem(struct rvu *rvu); ...@@ -637,10 +662,16 @@ void rvu_nix_freemem(struct rvu *rvu);
int rvu_get_nixlf_count(struct rvu *rvu); int rvu_get_nixlf_count(struct rvu *rvu);
void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int npalf); void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int npalf);
int nix_get_nixlf(struct rvu *rvu, u16 pcifunc, int *nixlf, int *nix_blkaddr); int nix_get_nixlf(struct rvu *rvu, u16 pcifunc, int *nixlf, int *nix_blkaddr);
int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add); int nix_update_mce_list(struct rvu *rvu, u16 pcifunc,
struct nix_mce_list *mce_list,
int mce_idx, int mcam_index, bool add);
void nix_get_mce_list(struct rvu *rvu, u16 pcifunc, int type,
struct nix_mce_list **mce_list, int *mce_idx);
struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr); struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr);
int rvu_get_next_nix_blkaddr(struct rvu *rvu, int blkaddr); int rvu_get_next_nix_blkaddr(struct rvu *rvu, int blkaddr);
void rvu_nix_reset_mac(struct rvu_pfvf *pfvf, int pcifunc); void rvu_nix_reset_mac(struct rvu_pfvf *pfvf, int pcifunc);
int nix_get_struct_ptrs(struct rvu *rvu, u16 pcifunc,
struct nix_hw **nix_hw, int *blkaddr);
/* NPC APIs */ /* NPC APIs */
int rvu_npc_init(struct rvu *rvu); int rvu_npc_init(struct rvu *rvu);
...@@ -651,13 +682,19 @@ int npc_config_ts_kpuaction(struct rvu *rvu, int pf, u16 pcifunc, bool en); ...@@ -651,13 +682,19 @@ int npc_config_ts_kpuaction(struct rvu *rvu, int pf, u16 pcifunc, bool en);
void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc, void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, u64 chan, u8 *mac_addr); int nixlf, u64 chan, u8 *mac_addr);
void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc, void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, u64 chan, u8 chan_cnt, int nixlf, u64 chan, u8 chan_cnt);
bool allmulti); void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
void rvu_npc_disable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf); bool enable);
void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc, void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, u64 chan); int nixlf, u64 chan);
void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, bool enable); void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
bool enable);
void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
u64 chan);
void rvu_npc_enable_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
bool enable);
void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, int type, bool enable);
void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf); void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_free_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf); void rvu_npc_free_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf); void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
......
...@@ -2132,6 +2132,7 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_file *s, void *unused) ...@@ -2132,6 +2132,7 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_file *s, void *unused)
struct rvu *rvu = s->private; struct rvu *rvu = s->private;
struct npc_mcam *mcam; struct npc_mcam *mcam;
int pf, vf = -1; int pf, vf = -1;
bool enabled;
int blkaddr; int blkaddr;
u16 target; u16 target;
u64 hits; u64 hits;
...@@ -2173,7 +2174,9 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_file *s, void *unused) ...@@ -2173,7 +2174,9 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_file *s, void *unused)
} }
rvu_dbg_npc_mcam_show_action(s, iter); rvu_dbg_npc_mcam_show_action(s, iter);
seq_printf(s, "\tenabled: %s\n", iter->enable ? "yes" : "no");
enabled = is_mcam_entry_enabled(rvu, mcam, blkaddr, iter->entry);
seq_printf(s, "\tenabled: %s\n", enabled ? "yes" : "no");
if (!iter->has_cntr) if (!iter->has_cntr)
continue; continue;
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
static void nix_free_tx_vtag_entries(struct rvu *rvu, u16 pcifunc); static void nix_free_tx_vtag_entries(struct rvu *rvu, u16 pcifunc);
static int rvu_nix_get_bpid(struct rvu *rvu, struct nix_bp_cfg_req *req, static int rvu_nix_get_bpid(struct rvu *rvu, struct nix_bp_cfg_req *req,
int type, int chan_id); int type, int chan_id);
static int nix_update_mce_rule(struct rvu *rvu, u16 pcifunc,
int type, bool add);
enum mc_tbl_sz { enum mc_tbl_sz {
MC_TBL_SZ_256, MC_TBL_SZ_256,
...@@ -132,6 +134,22 @@ int nix_get_nixlf(struct rvu *rvu, u16 pcifunc, int *nixlf, int *nix_blkaddr) ...@@ -132,6 +134,22 @@ int nix_get_nixlf(struct rvu *rvu, u16 pcifunc, int *nixlf, int *nix_blkaddr)
return 0; return 0;
} }
int nix_get_struct_ptrs(struct rvu *rvu, u16 pcifunc,
struct nix_hw **nix_hw, int *blkaddr)
{
struct rvu_pfvf *pfvf;
pfvf = rvu_get_pfvf(rvu, pcifunc);
*blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
if (!pfvf->nixlf || *blkaddr < 0)
return NIX_AF_ERR_AF_LF_INVALID;
*nix_hw = get_nix_hw(rvu->hw, *blkaddr);
if (!*nix_hw)
return NIX_AF_ERR_INVALID_NIXBLK;
return 0;
}
static void nix_mce_list_init(struct nix_mce_list *list, int max) static void nix_mce_list_init(struct nix_mce_list *list, int max)
{ {
INIT_HLIST_HEAD(&list->head); INIT_HLIST_HEAD(&list->head);
...@@ -274,7 +292,7 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf) ...@@ -274,7 +292,7 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf)
pfvf->tx_chan_cnt = 1; pfvf->tx_chan_cnt = 1;
rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf, rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf,
pfvf->rx_chan_base, pfvf->rx_chan_base,
pfvf->rx_chan_cnt, false); pfvf->rx_chan_cnt);
break; break;
} }
...@@ -285,16 +303,17 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf) ...@@ -285,16 +303,17 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf)
pfvf->rx_chan_base, pfvf->mac_addr); pfvf->rx_chan_base, pfvf->mac_addr);
/* Add this PF_FUNC to bcast pkt replication list */ /* Add this PF_FUNC to bcast pkt replication list */
err = nix_update_bcast_mce_list(rvu, pcifunc, true); err = nix_update_mce_rule(rvu, pcifunc, NIXLF_BCAST_ENTRY, true);
if (err) { if (err) {
dev_err(rvu->dev, dev_err(rvu->dev,
"Bcast list, failed to enable PF_FUNC 0x%x\n", "Bcast list, failed to enable PF_FUNC 0x%x\n",
pcifunc); pcifunc);
return err; return err;
} }
/* Install MCAM rule matching Ethernet broadcast mac address */
rvu_npc_install_bcast_match_entry(rvu, pcifunc, rvu_npc_install_bcast_match_entry(rvu, pcifunc,
nixlf, pfvf->rx_chan_base); nixlf, pfvf->rx_chan_base);
pfvf->maxlen = NIC_HW_MIN_FRS; pfvf->maxlen = NIC_HW_MIN_FRS;
pfvf->minlen = NIC_HW_MIN_FRS; pfvf->minlen = NIC_HW_MIN_FRS;
...@@ -310,7 +329,7 @@ static void nix_interface_deinit(struct rvu *rvu, u16 pcifunc, u8 nixlf) ...@@ -310,7 +329,7 @@ static void nix_interface_deinit(struct rvu *rvu, u16 pcifunc, u8 nixlf)
pfvf->minlen = 0; pfvf->minlen = 0;
/* Remove this PF_FUNC from bcast pkt replication list */ /* Remove this PF_FUNC from bcast pkt replication list */
err = nix_update_bcast_mce_list(rvu, pcifunc, false); err = nix_update_mce_rule(rvu, pcifunc, NIXLF_BCAST_ENTRY, false);
if (err) { if (err) {
dev_err(rvu->dev, dev_err(rvu->dev,
"Bcast list, failed to disable PF_FUNC 0x%x\n", "Bcast list, failed to disable PF_FUNC 0x%x\n",
...@@ -2203,8 +2222,8 @@ static int nix_blk_setup_mce(struct rvu *rvu, struct nix_hw *nix_hw, ...@@ -2203,8 +2222,8 @@ static int nix_blk_setup_mce(struct rvu *rvu, struct nix_hw *nix_hw,
aq_req.op = op; aq_req.op = op;
aq_req.qidx = mce; aq_req.qidx = mce;
/* Forward bcast pkts to RQ0, RSS not needed */ /* Use RSS with RSS index 0 */
aq_req.mce.op = 0; aq_req.mce.op = 1;
aq_req.mce.index = 0; aq_req.mce.index = 0;
aq_req.mce.eol = eol; aq_req.mce.eol = eol;
aq_req.mce.pf_func = pcifunc; aq_req.mce.pf_func = pcifunc;
...@@ -2222,8 +2241,8 @@ static int nix_blk_setup_mce(struct rvu *rvu, struct nix_hw *nix_hw, ...@@ -2222,8 +2241,8 @@ static int nix_blk_setup_mce(struct rvu *rvu, struct nix_hw *nix_hw,
return 0; return 0;
} }
static int nix_update_mce_list(struct nix_mce_list *mce_list, static int nix_update_mce_list_entry(struct nix_mce_list *mce_list,
u16 pcifunc, bool add) u16 pcifunc, bool add)
{ {
struct mce *mce, *tail = NULL; struct mce *mce, *tail = NULL;
bool delete = false; bool delete = false;
...@@ -2234,6 +2253,9 @@ static int nix_update_mce_list(struct nix_mce_list *mce_list, ...@@ -2234,6 +2253,9 @@ static int nix_update_mce_list(struct nix_mce_list *mce_list,
if (mce->pcifunc == pcifunc && !add) { if (mce->pcifunc == pcifunc && !add) {
delete = true; delete = true;
break; break;
} else if (mce->pcifunc == pcifunc && add) {
/* entry already exists */
return 0;
} }
tail = mce; tail = mce;
} }
...@@ -2261,36 +2283,23 @@ static int nix_update_mce_list(struct nix_mce_list *mce_list, ...@@ -2261,36 +2283,23 @@ static int nix_update_mce_list(struct nix_mce_list *mce_list,
return 0; return 0;
} }
int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add) int nix_update_mce_list(struct rvu *rvu, u16 pcifunc,
struct nix_mce_list *mce_list,
int mce_idx, int mcam_index, bool add)
{ {
int err = 0, idx, next_idx, last_idx; int err = 0, idx, next_idx, last_idx, blkaddr, npc_blkaddr;
struct nix_mce_list *mce_list; struct npc_mcam *mcam = &rvu->hw->mcam;
struct nix_mcast *mcast; struct nix_mcast *mcast;
struct nix_hw *nix_hw; struct nix_hw *nix_hw;
struct rvu_pfvf *pfvf;
struct mce *mce; struct mce *mce;
int blkaddr;
/* Broadcast pkt replication is not needed for AF's VFs, hence skip */
if (is_afvf(pcifunc))
return 0;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
if (blkaddr < 0)
return 0;
nix_hw = get_nix_hw(rvu->hw, blkaddr); if (!mce_list)
if (!nix_hw) return -EINVAL;
return 0;
mcast = &nix_hw->mcast;
/* Get this PF/VF func's MCE index */ /* Get this PF/VF func's MCE index */
pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK); idx = mce_idx + (pcifunc & RVU_PFVF_FUNC_MASK);
idx = pfvf->bcast_mce_idx + (pcifunc & RVU_PFVF_FUNC_MASK);
mce_list = &pfvf->bcast_mce_list; if (idx > (mce_idx + mce_list->max)) {
if (idx > (pfvf->bcast_mce_idx + mce_list->max)) {
dev_err(rvu->dev, dev_err(rvu->dev,
"%s: Idx %d > max MCE idx %d, for PF%d bcast list\n", "%s: Idx %d > max MCE idx %d, for PF%d bcast list\n",
__func__, idx, mce_list->max, __func__, idx, mce_list->max,
...@@ -2298,20 +2307,26 @@ int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add) ...@@ -2298,20 +2307,26 @@ int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
return -EINVAL; return -EINVAL;
} }
err = nix_get_struct_ptrs(rvu, pcifunc, &nix_hw, &blkaddr);
if (err)
return err;
mcast = &nix_hw->mcast;
mutex_lock(&mcast->mce_lock); mutex_lock(&mcast->mce_lock);
err = nix_update_mce_list(mce_list, pcifunc, add); err = nix_update_mce_list_entry(mce_list, pcifunc, add);
if (err) if (err)
goto end; goto end;
/* Disable MCAM entry in NPC */ /* Disable MCAM entry in NPC */
if (!mce_list->count) { if (!mce_list->count) {
rvu_npc_enable_bcast_entry(rvu, pcifunc, false); npc_blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
npc_enable_mcam_entry(rvu, mcam, npc_blkaddr, mcam_index, false);
goto end; goto end;
} }
/* Dump the updated list to HW */ /* Dump the updated list to HW */
idx = pfvf->bcast_mce_idx; idx = mce_idx;
last_idx = idx + mce_list->count - 1; last_idx = idx + mce_list->count - 1;
hlist_for_each_entry(mce, &mce_list->head, node) { hlist_for_each_entry(mce, &mce_list->head, node) {
if (idx > last_idx) if (idx > last_idx)
...@@ -2332,7 +2347,71 @@ int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add) ...@@ -2332,7 +2347,71 @@ int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
return err; return err;
} }
static int nix_setup_bcast_tables(struct rvu *rvu, struct nix_hw *nix_hw) void nix_get_mce_list(struct rvu *rvu, u16 pcifunc, int type,
struct nix_mce_list **mce_list, int *mce_idx)
{
struct rvu_hwinfo *hw = rvu->hw;
struct rvu_pfvf *pfvf;
if (!hw->cap.nix_rx_multicast ||
!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc & ~RVU_PFVF_FUNC_MASK))) {
*mce_list = NULL;
*mce_idx = 0;
return;
}
/* Get this PF/VF func's MCE index */
pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK);
if (type == NIXLF_BCAST_ENTRY) {
*mce_list = &pfvf->bcast_mce_list;
*mce_idx = pfvf->bcast_mce_idx;
} else if (type == NIXLF_ALLMULTI_ENTRY) {
*mce_list = &pfvf->mcast_mce_list;
*mce_idx = pfvf->mcast_mce_idx;
} else if (type == NIXLF_PROMISC_ENTRY) {
*mce_list = &pfvf->promisc_mce_list;
*mce_idx = pfvf->promisc_mce_idx;
} else {
*mce_list = NULL;
*mce_idx = 0;
}
}
static int nix_update_mce_rule(struct rvu *rvu, u16 pcifunc,
int type, bool add)
{
int err = 0, nixlf, blkaddr, mcam_index, mce_idx;
struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_hwinfo *hw = rvu->hw;
struct nix_mce_list *mce_list;
/* skip multicast pkt replication for AF's VFs */
if (is_afvf(pcifunc))
return 0;
if (!hw->cap.nix_rx_multicast)
return 0;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
if (blkaddr < 0)
return -EINVAL;
nixlf = rvu_get_lf(rvu, &hw->block[blkaddr], pcifunc, 0);
if (nixlf < 0)
return -EINVAL;
nix_get_mce_list(rvu, pcifunc, type, &mce_list, &mce_idx);
mcam_index = npc_get_nixlf_mcam_index(mcam,
pcifunc & ~RVU_PFVF_FUNC_MASK,
nixlf, type);
err = nix_update_mce_list(rvu, pcifunc, mce_list,
mce_idx, mcam_index, add);
return err;
}
static int nix_setup_mce_tables(struct rvu *rvu, struct nix_hw *nix_hw)
{ {
struct nix_mcast *mcast = &nix_hw->mcast; struct nix_mcast *mcast = &nix_hw->mcast;
int err, pf, numvfs, idx; int err, pf, numvfs, idx;
...@@ -2355,11 +2434,18 @@ static int nix_setup_bcast_tables(struct rvu *rvu, struct nix_hw *nix_hw) ...@@ -2355,11 +2434,18 @@ static int nix_setup_bcast_tables(struct rvu *rvu, struct nix_hw *nix_hw)
if (pfvf->nix_blkaddr != nix_hw->blkaddr) if (pfvf->nix_blkaddr != nix_hw->blkaddr)
continue; continue;
/* Save the start MCE */ /* save start idx of broadcast mce list */
pfvf->bcast_mce_idx = nix_alloc_mce_list(mcast, numvfs + 1); pfvf->bcast_mce_idx = nix_alloc_mce_list(mcast, numvfs + 1);
nix_mce_list_init(&pfvf->bcast_mce_list, numvfs + 1); nix_mce_list_init(&pfvf->bcast_mce_list, numvfs + 1);
/* save start idx of multicast mce list */
pfvf->mcast_mce_idx = nix_alloc_mce_list(mcast, numvfs + 1);
nix_mce_list_init(&pfvf->mcast_mce_list, numvfs + 1);
/* save the start idx of promisc mce list */
pfvf->promisc_mce_idx = nix_alloc_mce_list(mcast, numvfs + 1);
nix_mce_list_init(&pfvf->promisc_mce_list, numvfs + 1);
for (idx = 0; idx < (numvfs + 1); idx++) { for (idx = 0; idx < (numvfs + 1); idx++) {
/* idx-0 is for PF, followed by VFs */ /* idx-0 is for PF, followed by VFs */
pcifunc = (pf << RVU_PFVF_PF_SHIFT); pcifunc = (pf << RVU_PFVF_PF_SHIFT);
...@@ -2375,6 +2461,22 @@ static int nix_setup_bcast_tables(struct rvu *rvu, struct nix_hw *nix_hw) ...@@ -2375,6 +2461,22 @@ static int nix_setup_bcast_tables(struct rvu *rvu, struct nix_hw *nix_hw)
pcifunc, 0, true); pcifunc, 0, true);
if (err) if (err)
return err; return err;
/* add dummy entries to multicast mce list */
err = nix_blk_setup_mce(rvu, nix_hw,
pfvf->mcast_mce_idx + idx,
NIX_AQ_INSTOP_INIT,
pcifunc, 0, true);
if (err)
return err;
/* add dummy entries to promisc mce list */
err = nix_blk_setup_mce(rvu, nix_hw,
pfvf->promisc_mce_idx + idx,
NIX_AQ_INSTOP_INIT,
pcifunc, 0, true);
if (err)
return err;
} }
} }
return 0; return 0;
...@@ -2421,7 +2523,7 @@ static int nix_setup_mcast(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr) ...@@ -2421,7 +2523,7 @@ static int nix_setup_mcast(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr)
mutex_init(&mcast->mce_lock); mutex_init(&mcast->mce_lock);
return nix_setup_bcast_tables(rvu, nix_hw); return nix_setup_mce_tables(rvu, nix_hw);
} }
static int nix_setup_txvlan(struct rvu *rvu, struct nix_hw *nix_hw) static int nix_setup_txvlan(struct rvu *rvu, struct nix_hw *nix_hw)
...@@ -3035,15 +3137,22 @@ int rvu_mbox_handler_nix_set_mac_addr(struct rvu *rvu, ...@@ -3035,15 +3137,22 @@ int rvu_mbox_handler_nix_set_mac_addr(struct rvu *rvu,
pfvf = rvu_get_pfvf(rvu, pcifunc); pfvf = rvu_get_pfvf(rvu, pcifunc);
/* VF can't overwrite admin(PF) changes */ /* untrusted VF can't overwrite admin(PF) changes */
if (from_vf && pfvf->pf_set_vf_cfg) if (!test_bit(PF_SET_VF_TRUSTED, &pfvf->flags) &&
(from_vf && test_bit(PF_SET_VF_MAC, &pfvf->flags))) {
dev_warn(rvu->dev,
"MAC address set by admin(PF) cannot be overwritten by untrusted VF");
return -EPERM; return -EPERM;
}
ether_addr_copy(pfvf->mac_addr, req->mac_addr); ether_addr_copy(pfvf->mac_addr, req->mac_addr);
rvu_npc_install_ucast_entry(rvu, pcifunc, nixlf, rvu_npc_install_ucast_entry(rvu, pcifunc, nixlf,
pfvf->rx_chan_base, req->mac_addr); pfvf->rx_chan_base, req->mac_addr);
if (test_bit(PF_SET_VF_TRUSTED, &pfvf->flags) && from_vf)
ether_addr_copy(pfvf->default_mac, req->mac_addr);
return 0; return 0;
} }
...@@ -3067,30 +3176,75 @@ int rvu_mbox_handler_nix_get_mac_addr(struct rvu *rvu, ...@@ -3067,30 +3176,75 @@ int rvu_mbox_handler_nix_get_mac_addr(struct rvu *rvu,
int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req, int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req,
struct msg_rsp *rsp) struct msg_rsp *rsp)
{ {
bool allmulti = false, disable_promisc = false; bool allmulti, promisc, nix_rx_multicast;
u16 pcifunc = req->hdr.pcifunc; u16 pcifunc = req->hdr.pcifunc;
int blkaddr, nixlf, err;
struct rvu_pfvf *pfvf; struct rvu_pfvf *pfvf;
int nixlf, err;
err = nix_get_nixlf(rvu, pcifunc, &nixlf, &blkaddr); pfvf = rvu_get_pfvf(rvu, pcifunc);
promisc = req->mode & NIX_RX_MODE_PROMISC ? true : false;
allmulti = req->mode & NIX_RX_MODE_ALLMULTI ? true : false;
pfvf->use_mce_list = req->mode & NIX_RX_MODE_USE_MCE ? true : false;
nix_rx_multicast = rvu->hw->cap.nix_rx_multicast & pfvf->use_mce_list;
if (is_vf(pcifunc) && !nix_rx_multicast &&
(promisc || allmulti)) {
dev_warn_ratelimited(rvu->dev,
"VF promisc/multicast not supported\n");
return 0;
}
/* untrusted VF can't configure promisc/allmulti */
if (is_vf(pcifunc) && !test_bit(PF_SET_VF_TRUSTED, &pfvf->flags) &&
(promisc || allmulti))
return 0;
err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL);
if (err) if (err)
return err; return err;
pfvf = rvu_get_pfvf(rvu, pcifunc); if (nix_rx_multicast) {
/* add/del this PF_FUNC to/from mcast pkt replication list */
err = nix_update_mce_rule(rvu, pcifunc, NIXLF_ALLMULTI_ENTRY,
allmulti);
if (err) {
dev_err(rvu->dev,
"Failed to update pcifunc 0x%x to multicast list\n",
pcifunc);
return err;
}
if (req->mode & NIX_RX_MODE_PROMISC) /* add/del this PF_FUNC to/from promisc pkt replication list */
allmulti = false; err = nix_update_mce_rule(rvu, pcifunc, NIXLF_PROMISC_ENTRY,
else if (req->mode & NIX_RX_MODE_ALLMULTI) promisc);
allmulti = true; if (err) {
else dev_err(rvu->dev,
disable_promisc = true; "Failed to update pcifunc 0x%x to promisc list\n",
pcifunc);
return err;
}
}
if (disable_promisc) /* install/uninstall allmulti entry */
rvu_npc_disable_promisc_entry(rvu, pcifunc, nixlf); if (allmulti) {
else rvu_npc_install_allmulti_entry(rvu, pcifunc, nixlf,
pfvf->rx_chan_base);
} else {
if (!nix_rx_multicast)
rvu_npc_enable_allmulti_entry(rvu, pcifunc, nixlf, false);
}
/* install/uninstall promisc entry */
if (promisc) {
rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf, rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf,
pfvf->rx_chan_base, pfvf->rx_chan_base,
pfvf->rx_chan_cnt, allmulti); pfvf->rx_chan_cnt);
} else {
if (!nix_rx_multicast)
rvu_npc_enable_promisc_entry(rvu, pcifunc, nixlf, false);
}
return 0; return 0;
} }
...@@ -3648,6 +3802,7 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req, ...@@ -3648,6 +3802,7 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req,
struct msg_rsp *rsp) struct msg_rsp *rsp)
{ {
u16 pcifunc = req->hdr.pcifunc; u16 pcifunc = req->hdr.pcifunc;
struct rvu_pfvf *pfvf;
int nixlf, err; int nixlf, err;
err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL); err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL);
...@@ -3658,6 +3813,9 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req, ...@@ -3658,6 +3813,9 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req,
npc_mcam_enable_flows(rvu, pcifunc); npc_mcam_enable_flows(rvu, pcifunc);
pfvf = rvu_get_pfvf(rvu, pcifunc);
set_bit(NIXLF_INITIALIZED, &pfvf->flags);
return rvu_cgx_start_stop_io(rvu, pcifunc, true); return rvu_cgx_start_stop_io(rvu, pcifunc, true);
} }
...@@ -3665,6 +3823,7 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req, ...@@ -3665,6 +3823,7 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
struct msg_rsp *rsp) struct msg_rsp *rsp)
{ {
u16 pcifunc = req->hdr.pcifunc; u16 pcifunc = req->hdr.pcifunc;
struct rvu_pfvf *pfvf;
int nixlf, err; int nixlf, err;
err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL); err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL);
...@@ -3673,6 +3832,9 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req, ...@@ -3673,6 +3832,9 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
rvu_npc_disable_mcam_entries(rvu, pcifunc, nixlf); rvu_npc_disable_mcam_entries(rvu, pcifunc, nixlf);
pfvf = rvu_get_pfvf(rvu, pcifunc);
clear_bit(NIXLF_INITIALIZED, &pfvf->flags);
return rvu_cgx_start_stop_io(rvu, pcifunc, false); return rvu_cgx_start_stop_io(rvu, pcifunc, false);
} }
...@@ -3691,6 +3853,8 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf) ...@@ -3691,6 +3853,8 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
nix_rx_sync(rvu, blkaddr); nix_rx_sync(rvu, blkaddr);
nix_txschq_free(rvu, pcifunc); nix_txschq_free(rvu, pcifunc);
clear_bit(NIXLF_INITIALIZED, &pfvf->flags);
rvu_cgx_start_stop_io(rvu, pcifunc, false); rvu_cgx_start_stop_io(rvu, pcifunc, false);
if (pfvf->sq_ctx) { if (pfvf->sq_ctx) {
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include "cgx.h" #include "cgx.h"
#include "npc_profile.h" #include "npc_profile.h"
#define RSVD_MCAM_ENTRIES_PER_PF 2 /* Bcast & Promisc */ #define RSVD_MCAM_ENTRIES_PER_PF 3 /* Broadcast, Promisc and AllMulticast */
#define RSVD_MCAM_ENTRIES_PER_NIXLF 1 /* Ucast for LFs */ #define RSVD_MCAM_ENTRIES_PER_NIXLF 1 /* Ucast for LFs */
#define NPC_PARSE_RESULT_DMAC_OFFSET 8 #define NPC_PARSE_RESULT_DMAC_OFFSET 8
...@@ -214,8 +214,10 @@ int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, ...@@ -214,8 +214,10 @@ int npc_get_nixlf_mcam_index(struct npc_mcam *mcam,
*/ */
if (type == NIXLF_BCAST_ENTRY) if (type == NIXLF_BCAST_ENTRY)
return index; return index;
else if (type == NIXLF_PROMISC_ENTRY) else if (type == NIXLF_ALLMULTI_ENTRY)
return index + 1; return index + 1;
else if (type == NIXLF_PROMISC_ENTRY)
return index + 2;
} }
return npc_get_ucast_mcam_index(mcam, pcifunc, nixlf); return npc_get_ucast_mcam_index(mcam, pcifunc, nixlf);
...@@ -413,37 +415,49 @@ static void npc_fill_entryword(struct mcam_entry *entry, int idx, ...@@ -413,37 +415,49 @@ static void npc_fill_entryword(struct mcam_entry *entry, int idx,
} }
} }
static void npc_get_default_entry_action(struct rvu *rvu, struct npc_mcam *mcam, static u64 npc_get_default_entry_action(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, int index, int blkaddr, u16 pf_func)
struct mcam_entry *entry) {
int bank, nixlf, index;
/* get ucast entry rule entry index */
nix_get_nixlf(rvu, pf_func, &nixlf, NULL);
index = npc_get_nixlf_mcam_index(mcam, pf_func, nixlf,
NIXLF_UCAST_ENTRY);
bank = npc_get_bank(mcam, index);
index &= (mcam->banksize - 1);
return rvu_read64(rvu, blkaddr,
NPC_AF_MCAMEX_BANKX_ACTION(index, bank));
}
static void npc_fixup_vf_rule(struct rvu *rvu, struct npc_mcam *mcam,
int blkaddr, int index, struct mcam_entry *entry,
bool *enable)
{ {
u16 owner, target_func; u16 owner, target_func;
struct rvu_pfvf *pfvf; struct rvu_pfvf *pfvf;
int bank, nixlf;
u64 rx_action; u64 rx_action;
owner = mcam->entry2pfvf_map[index]; owner = mcam->entry2pfvf_map[index];
target_func = (entry->action >> 4) & 0xffff; target_func = (entry->action >> 4) & 0xffff;
/* return incase target is PF or LBK or rule owner is not PF */ /* do nothing when target is LBK/PF or owner is not PF */
if (is_afvf(target_func) || (owner & RVU_PFVF_FUNC_MASK) || if (is_afvf(target_func) || (owner & RVU_PFVF_FUNC_MASK) ||
!(target_func & RVU_PFVF_FUNC_MASK)) !(target_func & RVU_PFVF_FUNC_MASK))
return; return;
/* save entry2target_pffunc */
pfvf = rvu_get_pfvf(rvu, target_func); pfvf = rvu_get_pfvf(rvu, target_func);
mcam->entry2target_pffunc[index] = target_func; mcam->entry2target_pffunc[index] = target_func;
/* return if nixlf is not attached or initialized */
if (!is_nixlf_attached(rvu, target_func) || !pfvf->def_ucast_rule)
return;
/* get VF ucast entry rule */ /* don't enable rule when nixlf not attached or initialized */
nix_get_nixlf(rvu, target_func, &nixlf, NULL); if (!(is_nixlf_attached(rvu, target_func) &&
index = npc_get_nixlf_mcam_index(mcam, target_func, test_bit(NIXLF_INITIALIZED, &pfvf->flags)))
nixlf, NIXLF_UCAST_ENTRY); *enable = false;
bank = npc_get_bank(mcam, index);
index &= (mcam->banksize - 1);
rx_action = rvu_read64(rvu, blkaddr, /* copy VF default entry action to the VF mcam entry */
NPC_AF_MCAMEX_BANKX_ACTION(index, bank)); rx_action = npc_get_default_entry_action(rvu, mcam, blkaddr,
target_func);
if (rx_action) if (rx_action)
entry->action = rx_action; entry->action = rx_action;
} }
...@@ -495,10 +509,9 @@ static void npc_config_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam, ...@@ -495,10 +509,9 @@ static void npc_config_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
NPC_AF_MCAMEX_BANKX_CAMX_W1(index, bank, 0), cam0); NPC_AF_MCAMEX_BANKX_CAMX_W1(index, bank, 0), cam0);
} }
/* copy VF default entry action to the VF mcam entry */ /* PF installing VF rule */
if (intf == NIX_INTF_RX && actindex < mcam->bmap_entries) if (intf == NIX_INTF_RX && actindex < mcam->bmap_entries)
npc_get_default_entry_action(rvu, mcam, blkaddr, actindex, npc_fixup_vf_rule(rvu, mcam, blkaddr, index, entry, &enable);
entry);
/* Set 'action' */ /* Set 'action' */
rvu_write64(rvu, blkaddr, rvu_write64(rvu, blkaddr,
...@@ -649,30 +662,32 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc, ...@@ -649,30 +662,32 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
} }
void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc, void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, u64 chan, u8 chan_cnt, int nixlf, u64 chan, u8 chan_cnt)
bool allmulti)
{ {
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
struct npc_install_flow_req req = { 0 }; struct npc_install_flow_req req = { 0 };
struct npc_install_flow_rsp rsp = { 0 }; struct npc_install_flow_rsp rsp = { 0 };
struct npc_mcam *mcam = &rvu->hw->mcam; struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_hwinfo *hw = rvu->hw;
int blkaddr, ucast_idx, index; int blkaddr, ucast_idx, index;
u8 mac_addr[ETH_ALEN] = { 0 };
struct nix_rx_action action; struct nix_rx_action action;
u64 relaxed_mask; u64 relaxed_mask;
/* Only PF or AF VF can add a promiscuous entry */ if (!hw->cap.nix_rx_multicast && is_cgx_vf(rvu, pcifunc))
if ((pcifunc & RVU_PFVF_FUNC_MASK) && !is_afvf(pcifunc))
return; return;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0) if (blkaddr < 0)
return; return;
*(u64 *)&action = 0x00;
index = npc_get_nixlf_mcam_index(mcam, pcifunc, index = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_PROMISC_ENTRY); nixlf, NIXLF_PROMISC_ENTRY);
if (is_cgx_vf(rvu, pcifunc))
index = npc_get_nixlf_mcam_index(mcam,
pcifunc & ~RVU_PFVF_FUNC_MASK,
nixlf, NIXLF_PROMISC_ENTRY);
/* If the corresponding PF's ucast action is RSS, /* If the corresponding PF's ucast action is RSS,
* use the same action for promisc also * use the same action for promisc also
*/ */
...@@ -680,19 +695,20 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc, ...@@ -680,19 +695,20 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
nixlf, NIXLF_UCAST_ENTRY); nixlf, NIXLF_UCAST_ENTRY);
if (is_mcam_entry_enabled(rvu, mcam, blkaddr, ucast_idx)) if (is_mcam_entry_enabled(rvu, mcam, blkaddr, ucast_idx))
*(u64 *)&action = npc_get_mcam_action(rvu, mcam, *(u64 *)&action = npc_get_mcam_action(rvu, mcam,
blkaddr, ucast_idx); blkaddr, ucast_idx);
if (action.op != NIX_RX_ACTIONOP_RSS) { if (action.op != NIX_RX_ACTIONOP_RSS) {
*(u64 *)&action = 0x00; *(u64 *)&action = 0x00;
action.op = NIX_RX_ACTIONOP_UCAST; action.op = NIX_RX_ACTIONOP_UCAST;
action.pf_func = pcifunc;
} }
if (allmulti) { /* RX_ACTION set to MCAST for CGX PF's */
mac_addr[0] = 0x01; /* LSB bit of 1st byte in DMAC */ if (hw->cap.nix_rx_multicast && pfvf->use_mce_list &&
ether_addr_copy(req.packet.dmac, mac_addr); is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) {
ether_addr_copy(req.mask.dmac, mac_addr); *(u64 *)&action = 0x00;
req.features = BIT_ULL(NPC_DMAC); action.op = NIX_RX_ACTIONOP_MCAST;
pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK);
action.index = pfvf->promisc_mce_idx;
} }
req.chan_mask = 0xFFFU; req.chan_mask = 0xFFFU;
...@@ -720,8 +736,8 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc, ...@@ -720,8 +736,8 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
} }
static void npc_enadis_promisc_entry(struct rvu *rvu, u16 pcifunc, void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, bool enable) int nixlf, bool enable)
{ {
struct npc_mcam *mcam = &rvu->hw->mcam; struct npc_mcam *mcam = &rvu->hw->mcam;
int blkaddr, index; int blkaddr, index;
...@@ -730,25 +746,14 @@ static void npc_enadis_promisc_entry(struct rvu *rvu, u16 pcifunc, ...@@ -730,25 +746,14 @@ static void npc_enadis_promisc_entry(struct rvu *rvu, u16 pcifunc,
if (blkaddr < 0) if (blkaddr < 0)
return; return;
/* Only PF's have a promiscuous entry */ /* Get 'pcifunc' of PF device */
if (pcifunc & RVU_PFVF_FUNC_MASK) pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
return;
index = npc_get_nixlf_mcam_index(mcam, pcifunc, index = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_PROMISC_ENTRY); nixlf, NIXLF_PROMISC_ENTRY);
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable); npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
} }
void rvu_npc_disable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf)
{
npc_enadis_promisc_entry(rvu, pcifunc, nixlf, false);
}
void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf)
{
npc_enadis_promisc_entry(rvu, pcifunc, nixlf, true);
}
void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc, void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, u64 chan) int nixlf, u64 chan)
{ {
...@@ -758,8 +763,6 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc, ...@@ -758,8 +763,6 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
struct npc_mcam *mcam = &rvu->hw->mcam; struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_hwinfo *hw = rvu->hw; struct rvu_hwinfo *hw = rvu->hw;
int blkaddr, index; int blkaddr, index;
u32 req_index = 0;
u8 op;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0) if (blkaddr < 0)
...@@ -772,7 +775,7 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc, ...@@ -772,7 +775,7 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
/* If pkt replication is not supported, /* If pkt replication is not supported,
* then only PF is allowed to add a bcast match entry. * then only PF is allowed to add a bcast match entry.
*/ */
if (!hw->cap.nix_rx_multicast && pcifunc & RVU_PFVF_FUNC_MASK) if (!hw->cap.nix_rx_multicast && is_vf(pcifunc))
return; return;
/* Get 'pcifunc' of PF device */ /* Get 'pcifunc' of PF device */
...@@ -786,10 +789,10 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc, ...@@ -786,10 +789,10 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
* so install entry with UCAST action, so that PF * so install entry with UCAST action, so that PF
* receives all broadcast packets. * receives all broadcast packets.
*/ */
op = NIX_RX_ACTIONOP_UCAST; req.op = NIX_RX_ACTIONOP_UCAST;
} else { } else {
op = NIX_RX_ACTIONOP_MCAST; req.op = NIX_RX_ACTIONOP_MCAST;
req_index = pfvf->bcast_mce_idx; req.index = pfvf->bcast_mce_idx;
} }
eth_broadcast_addr((u8 *)&req.packet.dmac); eth_broadcast_addr((u8 *)&req.packet.dmac);
...@@ -798,15 +801,110 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc, ...@@ -798,15 +801,110 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
req.channel = chan; req.channel = chan;
req.intf = pfvf->nix_rx_intf; req.intf = pfvf->nix_rx_intf;
req.entry = index; req.entry = index;
req.op = op;
req.hdr.pcifunc = 0; /* AF is requester */ req.hdr.pcifunc = 0; /* AF is requester */
req.vf = pcifunc; req.vf = pcifunc;
req.index = req_index;
rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
} }
void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, bool enable) void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
bool enable)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
int blkaddr, index;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
return;
/* Get 'pcifunc' of PF device */
pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf,
NIXLF_BCAST_ENTRY);
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
}
void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
u64 chan)
{
struct npc_install_flow_req req = { 0 };
struct npc_install_flow_rsp rsp = { 0 };
struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_hwinfo *hw = rvu->hw;
int blkaddr, ucast_idx, index;
u8 mac_addr[ETH_ALEN] = { 0 };
struct nix_rx_action action;
struct rvu_pfvf *pfvf;
u16 vf_func;
/* Only CGX PF/VF can add allmulticast entry */
if (is_afvf(pcifunc))
return;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
return;
/* Get 'pcifunc' of PF device */
vf_func = pcifunc & RVU_PFVF_FUNC_MASK;
pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
pfvf = rvu_get_pfvf(rvu, pcifunc);
index = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_ALLMULTI_ENTRY);
/* If the corresponding PF's ucast action is RSS,
* use the same action for multicast entry also
*/
ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_UCAST_ENTRY);
if (is_mcam_entry_enabled(rvu, mcam, blkaddr, ucast_idx))
*(u64 *)&action = npc_get_mcam_action(rvu, mcam,
blkaddr, ucast_idx);
if (action.op != NIX_RX_ACTIONOP_RSS) {
*(u64 *)&action = 0x00;
action.op = NIX_RX_ACTIONOP_UCAST;
action.pf_func = pcifunc;
}
/* RX_ACTION set to MCAST for CGX PF's */
if (hw->cap.nix_rx_multicast && pfvf->use_mce_list) {
*(u64 *)&action = 0x00;
action.op = NIX_RX_ACTIONOP_MCAST;
action.index = pfvf->mcast_mce_idx;
}
mac_addr[0] = 0x01; /* LSB bit of 1st byte in DMAC */
ether_addr_copy(req.packet.dmac, mac_addr);
ether_addr_copy(req.mask.dmac, mac_addr);
req.features = BIT_ULL(NPC_DMAC);
/* For cn10k the upper two bits of the channel number are
* cpt channel number. with masking out these bits in the
* mcam entry, same entry used for NIX will allow packets
* received from cpt for parsing.
*/
if (!is_rvu_otx2(rvu))
req.chan_mask = NIX_CHAN_CPT_X2P_MASK;
else
req.chan_mask = 0xFFFU;
req.channel = chan;
req.intf = pfvf->nix_rx_intf;
req.entry = index;
req.op = action.op;
req.hdr.pcifunc = 0; /* AF is requester */
req.vf = pcifunc | vf_func;
req.index = action.index;
req.match_id = action.match_id;
req.flow_key_alg = action.flow_key_alg;
rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
}
void rvu_npc_enable_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
bool enable)
{ {
struct npc_mcam *mcam = &rvu->hw->mcam; struct npc_mcam *mcam = &rvu->hw->mcam;
int blkaddr, index; int blkaddr, index;
...@@ -818,7 +916,8 @@ void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, bool enable) ...@@ -818,7 +916,8 @@ void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, bool enable)
/* Get 'pcifunc' of PF device */ /* Get 'pcifunc' of PF device */
pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK; pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
index = npc_get_nixlf_mcam_index(mcam, pcifunc, 0, NIXLF_BCAST_ENTRY); index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf,
NIXLF_ALLMULTI_ENTRY);
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable); npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
} }
...@@ -860,6 +959,7 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf, ...@@ -860,6 +959,7 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
int group, int alg_idx, int mcam_index) int group, int alg_idx, int mcam_index)
{ {
struct npc_mcam *mcam = &rvu->hw->mcam; struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_hwinfo *hw = rvu->hw;
struct nix_rx_action action; struct nix_rx_action action;
int blkaddr, index, bank; int blkaddr, index, bank;
struct rvu_pfvf *pfvf; struct rvu_pfvf *pfvf;
...@@ -915,7 +1015,8 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf, ...@@ -915,7 +1015,8 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
/* If PF's promiscuous entry is enabled, /* If PF's promiscuous entry is enabled,
* Set RSS action for that entry as well * Set RSS action for that entry as well
*/ */
if (is_mcam_entry_enabled(rvu, mcam, blkaddr, index)) { if ((!hw->cap.nix_rx_multicast || !pfvf->use_mce_list) &&
is_mcam_entry_enabled(rvu, mcam, blkaddr, index)) {
bank = npc_get_bank(mcam, index); bank = npc_get_bank(mcam, index);
index &= (mcam->banksize - 1); index &= (mcam->banksize - 1);
...@@ -925,12 +1026,47 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf, ...@@ -925,12 +1026,47 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
} }
} }
void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, int type, bool enable)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_hwinfo *hw = rvu->hw;
struct nix_mce_list *mce_list;
int index, blkaddr, mce_idx;
struct rvu_pfvf *pfvf;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
return;
index = npc_get_nixlf_mcam_index(mcam, pcifunc & ~RVU_PFVF_FUNC_MASK,
nixlf, type);
/* disable MCAM entry when packet replication is not supported by hw */
if (!hw->cap.nix_rx_multicast && !is_vf(pcifunc)) {
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
return;
}
/* return incase mce list is not enabled */
pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK);
if (hw->cap.nix_rx_multicast && is_vf(pcifunc) &&
type != NIXLF_BCAST_ENTRY && !pfvf->use_mce_list)
return;
nix_get_mce_list(rvu, pcifunc, type, &mce_list, &mce_idx);
nix_update_mce_list(rvu, pcifunc, mce_list,
mce_idx, index, enable);
if (enable)
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
}
static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc, static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
int nixlf, bool enable) int nixlf, bool enable)
{ {
struct npc_mcam *mcam = &rvu->hw->mcam; struct npc_mcam *mcam = &rvu->hw->mcam;
struct nix_rx_action action; int index, blkaddr;
int index, bank, blkaddr;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0) if (blkaddr < 0)
...@@ -941,48 +1077,33 @@ static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc, ...@@ -941,48 +1077,33 @@ static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
nixlf, NIXLF_UCAST_ENTRY); nixlf, NIXLF_UCAST_ENTRY);
npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable); npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
/* For PF, ena/dis promisc and bcast MCAM match entries. /* Nothing to do for VFs, on platforms where pkt replication
* For VFs add/delete from bcast list when RX multicast * is not supported
* feature is present.
*/ */
if (pcifunc & RVU_PFVF_FUNC_MASK && !rvu->hw->cap.nix_rx_multicast) if ((pcifunc & RVU_PFVF_FUNC_MASK) && !rvu->hw->cap.nix_rx_multicast)
return; return;
/* For bcast, enable/disable only if it's action is not /* add/delete pf_func to broadcast MCE list */
* packet replication, incase if action is replication npc_enadis_default_mce_entry(rvu, pcifunc, nixlf,
* then this PF/VF's nixlf is removed from bcast replication NIXLF_BCAST_ENTRY, enable);
* list.
*/
index = npc_get_nixlf_mcam_index(mcam, pcifunc & ~RVU_PFVF_FUNC_MASK,
nixlf, NIXLF_BCAST_ENTRY);
bank = npc_get_bank(mcam, index);
*(u64 *)&action = rvu_read64(rvu, blkaddr,
NPC_AF_MCAMEX_BANKX_ACTION(index & (mcam->banksize - 1), bank));
/* VFs will not have BCAST entry */
if (action.op != NIX_RX_ACTIONOP_MCAST &&
!(pcifunc & RVU_PFVF_FUNC_MASK)) {
npc_enable_mcam_entry(rvu, mcam,
blkaddr, index, enable);
} else {
nix_update_bcast_mce_list(rvu, pcifunc, enable);
/* Enable PF's BCAST entry for packet replication */
rvu_npc_enable_bcast_entry(rvu, pcifunc, enable);
}
if (enable)
rvu_npc_enable_promisc_entry(rvu, pcifunc, nixlf);
else
rvu_npc_disable_promisc_entry(rvu, pcifunc, nixlf);
} }
void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf) void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
{ {
npc_enadis_default_entries(rvu, pcifunc, nixlf, false); npc_enadis_default_entries(rvu, pcifunc, nixlf, false);
/* Delete multicast and promisc MCAM entries */
npc_enadis_default_mce_entry(rvu, pcifunc, nixlf,
NIXLF_ALLMULTI_ENTRY, false);
npc_enadis_default_mce_entry(rvu, pcifunc, nixlf,
NIXLF_PROMISC_ENTRY, false);
} }
void rvu_npc_enable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf) void rvu_npc_enable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
{ {
/* Enables only broadcast match entry. Promisc/Allmulti are enabled
* in set_rx_mode mbox handler.
*/
npc_enadis_default_entries(rvu, pcifunc, nixlf, true); npc_enadis_default_entries(rvu, pcifunc, nixlf, true);
} }
...@@ -1002,7 +1123,8 @@ void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf) ...@@ -1002,7 +1123,8 @@ void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
/* Disable MCAM entries directing traffic to this 'pcifunc' */ /* Disable MCAM entries directing traffic to this 'pcifunc' */
list_for_each_entry_safe(rule, tmp, &mcam->mcam_rules, list) { list_for_each_entry_safe(rule, tmp, &mcam->mcam_rules, list) {
if (is_npc_intf_rx(rule->intf) && if (is_npc_intf_rx(rule->intf) &&
rule->rx_action.pf_func == pcifunc) { rule->rx_action.pf_func == pcifunc &&
rule->rx_action.op != NIX_RX_ACTIONOP_MCAST) {
npc_enable_mcam_entry(rvu, mcam, blkaddr, npc_enable_mcam_entry(rvu, mcam, blkaddr,
rule->entry, false); rule->entry, false);
rule->enable = false; rule->enable = false;
......
...@@ -1103,9 +1103,11 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target, ...@@ -1103,9 +1103,11 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
if (pf_set_vfs_mac) { if (pf_set_vfs_mac) {
ether_addr_copy(pfvf->default_mac, req->packet.dmac); ether_addr_copy(pfvf->default_mac, req->packet.dmac);
ether_addr_copy(pfvf->mac_addr, req->packet.dmac); ether_addr_copy(pfvf->mac_addr, req->packet.dmac);
set_bit(PF_SET_VF_MAC, &pfvf->flags);
} }
if (pfvf->pf_set_vf_cfg && req->vtag0_type == NIX_AF_LFX_RX_VTAG_TYPE7) if (test_bit(PF_SET_VF_CFG, &pfvf->flags) &&
req->vtag0_type == NIX_AF_LFX_RX_VTAG_TYPE7)
rule->vfvlan_cfg = true; rule->vfvlan_cfg = true;
return 0; return 0;
...@@ -1167,7 +1169,7 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu, ...@@ -1167,7 +1169,7 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
/* PF installing for its VF */ /* PF installing for its VF */
if (req->hdr.pcifunc && !from_vf && req->vf) if (req->hdr.pcifunc && !from_vf && req->vf)
pfvf->pf_set_vf_cfg = 1; set_bit(PF_SET_VF_CFG, &pfvf->flags);
/* update req destination mac addr */ /* update req destination mac addr */
if ((req->features & BIT_ULL(NPC_DMAC)) && is_npc_intf_rx(req->intf) && if ((req->features & BIT_ULL(NPC_DMAC)) && is_npc_intf_rx(req->intf) &&
...@@ -1177,9 +1179,12 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu, ...@@ -1177,9 +1179,12 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
} }
err = nix_get_nixlf(rvu, target, &nixlf, NULL); err = nix_get_nixlf(rvu, target, &nixlf, NULL);
if (err && is_npc_intf_rx(req->intf) && !pf_set_vfs_mac)
return -EINVAL;
/* If interface is uninitialized then do not enable entry */ /* don't enable rule when nixlf not attached or initialized */
if (err || (!req->default_rule && !pfvf->def_ucast_rule)) if (!(is_nixlf_attached(rvu, target) &&
test_bit(NIXLF_INITIALIZED, &pfvf->flags)))
enable = false; enable = false;
/* Packets reaching NPC in Tx path implies that a /* Packets reaching NPC in Tx path implies that a
...@@ -1193,6 +1198,14 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu, ...@@ -1193,6 +1198,14 @@ int rvu_mbox_handler_npc_install_flow(struct rvu *rvu,
if (from_vf && !enable) if (from_vf && !enable)
return -EINVAL; return -EINVAL;
/* PF sets VF mac & VF NIXLF is not attached, update the mac addr */
if (pf_set_vfs_mac && !enable) {
ether_addr_copy(pfvf->default_mac, req->packet.dmac);
ether_addr_copy(pfvf->mac_addr, req->packet.dmac);
set_bit(PF_SET_VF_MAC, &pfvf->flags);
return 0;
}
/* If message is from VF then its flow should not overlap with /* If message is from VF then its flow should not overlap with
* reserved unicast flow. * reserved unicast flow.
*/ */
......
...@@ -223,6 +223,11 @@ struct otx2_hw { ...@@ -223,6 +223,11 @@ struct otx2_hw {
u64 *nix_lmt_base; u64 *nix_lmt_base;
}; };
enum vfperm {
OTX2_RESET_VF_PERM,
OTX2_TRUSTED_VF,
};
struct otx2_vf_config { struct otx2_vf_config {
struct otx2_nic *pf; struct otx2_nic *pf;
struct delayed_work link_event_work; struct delayed_work link_event_work;
...@@ -230,6 +235,7 @@ struct otx2_vf_config { ...@@ -230,6 +235,7 @@ struct otx2_vf_config {
u8 mac[ETH_ALEN]; u8 mac[ETH_ALEN];
u16 vlan; u16 vlan;
int tx_vtag_idx; int tx_vtag_idx;
bool trusted;
}; };
struct flr_work { struct flr_work {
......
...@@ -39,6 +39,8 @@ MODULE_DESCRIPTION(DRV_STRING); ...@@ -39,6 +39,8 @@ MODULE_DESCRIPTION(DRV_STRING);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_DEVICE_TABLE(pci, otx2_pf_id_table); MODULE_DEVICE_TABLE(pci, otx2_pf_id_table);
static void otx2_vf_link_event_task(struct work_struct *work);
enum { enum {
TYPE_PFAF, TYPE_PFAF,
TYPE_PFVF, TYPE_PFVF,
...@@ -1820,9 +1822,11 @@ static void otx2_do_set_rx_mode(struct work_struct *work) ...@@ -1820,9 +1822,11 @@ static void otx2_do_set_rx_mode(struct work_struct *work)
if (promisc) if (promisc)
req->mode |= NIX_RX_MODE_PROMISC; req->mode |= NIX_RX_MODE_PROMISC;
else if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST)) if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST))
req->mode |= NIX_RX_MODE_ALLMULTI; req->mode |= NIX_RX_MODE_ALLMULTI;
req->mode |= NIX_RX_MODE_USE_MCE;
otx2_sync_mbox_msg(&pf->mbox); otx2_sync_mbox_msg(&pf->mbox);
mutex_unlock(&pf->mbox.lock); mutex_unlock(&pf->mbox.lock);
} }
...@@ -2044,7 +2048,7 @@ static int otx2_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) ...@@ -2044,7 +2048,7 @@ static int otx2_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
if (!netif_running(netdev)) if (!netif_running(netdev))
return -EAGAIN; return -EAGAIN;
if (vf >= pci_num_vf(pdev)) if (vf >= pf->total_vfs)
return -EINVAL; return -EINVAL;
if (!is_valid_ether_addr(mac)) if (!is_valid_ether_addr(mac))
...@@ -2055,7 +2059,8 @@ static int otx2_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) ...@@ -2055,7 +2059,8 @@ static int otx2_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
ret = otx2_do_set_vf_mac(pf, vf, mac); ret = otx2_do_set_vf_mac(pf, vf, mac);
if (ret == 0) if (ret == 0)
dev_info(&pdev->dev, "Reload VF driver to apply the changes\n"); dev_info(&pdev->dev,
"Load/Reload VF driver\n");
return ret; return ret;
} }
...@@ -2241,10 +2246,63 @@ static int otx2_get_vf_config(struct net_device *netdev, int vf, ...@@ -2241,10 +2246,63 @@ static int otx2_get_vf_config(struct net_device *netdev, int vf,
ivi->vf = vf; ivi->vf = vf;
ether_addr_copy(ivi->mac, config->mac); ether_addr_copy(ivi->mac, config->mac);
ivi->vlan = config->vlan; ivi->vlan = config->vlan;
ivi->trusted = config->trusted;
return 0; return 0;
} }
static int otx2_set_vf_permissions(struct otx2_nic *pf, int vf,
int req_perm)
{
struct set_vf_perm *req;
int rc;
mutex_lock(&pf->mbox.lock);
req = otx2_mbox_alloc_msg_set_vf_perm(&pf->mbox);
if (!req) {
rc = -ENOMEM;
goto out;
}
/* Let AF reset VF permissions as sriov is disabled */
if (req_perm == OTX2_RESET_VF_PERM) {
req->flags |= RESET_VF_PERM;
} else if (req_perm == OTX2_TRUSTED_VF) {
if (pf->vf_configs[vf].trusted)
req->flags |= VF_TRUSTED;
}
req->vf = vf;
rc = otx2_sync_mbox_msg(&pf->mbox);
out:
mutex_unlock(&pf->mbox.lock);
return rc;
}
static int otx2_ndo_set_vf_trust(struct net_device *netdev, int vf,
bool enable)
{
struct otx2_nic *pf = netdev_priv(netdev);
struct pci_dev *pdev = pf->pdev;
int rc;
if (vf >= pci_num_vf(pdev))
return -EINVAL;
if (pf->vf_configs[vf].trusted == enable)
return 0;
pf->vf_configs[vf].trusted = enable;
rc = otx2_set_vf_permissions(pf, vf, OTX2_TRUSTED_VF);
if (rc)
pf->vf_configs[vf].trusted = !enable;
else
netdev_info(pf->netdev, "VF %d is %strusted\n",
vf, enable ? "" : "not ");
return rc;
}
static const struct net_device_ops otx2_netdev_ops = { static const struct net_device_ops otx2_netdev_ops = {
.ndo_open = otx2_open, .ndo_open = otx2_open,
.ndo_stop = otx2_stop, .ndo_stop = otx2_stop,
...@@ -2261,6 +2319,7 @@ static const struct net_device_ops otx2_netdev_ops = { ...@@ -2261,6 +2319,7 @@ static const struct net_device_ops otx2_netdev_ops = {
.ndo_set_vf_vlan = otx2_set_vf_vlan, .ndo_set_vf_vlan = otx2_set_vf_vlan,
.ndo_get_vf_config = otx2_get_vf_config, .ndo_get_vf_config = otx2_get_vf_config,
.ndo_setup_tc = otx2_setup_tc, .ndo_setup_tc = otx2_setup_tc,
.ndo_set_vf_trust = otx2_ndo_set_vf_trust,
}; };
static int otx2_wq_init(struct otx2_nic *pf) static int otx2_wq_init(struct otx2_nic *pf)
...@@ -2315,6 +2374,40 @@ static int otx2_realloc_msix_vectors(struct otx2_nic *pf) ...@@ -2315,6 +2374,40 @@ static int otx2_realloc_msix_vectors(struct otx2_nic *pf)
return otx2_register_mbox_intr(pf, false); return otx2_register_mbox_intr(pf, false);
} }
static int otx2_sriov_vfcfg_init(struct otx2_nic *pf)
{
int i;
pf->vf_configs = devm_kcalloc(pf->dev, pf->total_vfs,
sizeof(struct otx2_vf_config),
GFP_KERNEL);
if (!pf->vf_configs)
return -ENOMEM;
for (i = 0; i < pf->total_vfs; i++) {
pf->vf_configs[i].pf = pf;
pf->vf_configs[i].intf_down = true;
pf->vf_configs[i].trusted = false;
INIT_DELAYED_WORK(&pf->vf_configs[i].link_event_work,
otx2_vf_link_event_task);
}
return 0;
}
static void otx2_sriov_vfcfg_cleanup(struct otx2_nic *pf)
{
int i;
if (!pf->vf_configs)
return;
for (i = 0; i < pf->total_vfs; i++) {
cancel_delayed_work_sync(&pf->vf_configs[i].link_event_work);
otx2_set_vf_permissions(pf, i, OTX2_RESET_VF_PERM);
}
}
static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -2509,6 +2602,11 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2509,6 +2602,11 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (err) if (err)
goto err_mcam_flow_del; goto err_mcam_flow_del;
/* Initialize SR-IOV resources */
err = otx2_sriov_vfcfg_init(pf);
if (err)
goto err_pf_sriov_init;
/* Enable link notifications */ /* Enable link notifications */
otx2_cgx_config_linkevents(pf, true); otx2_cgx_config_linkevents(pf, true);
...@@ -2518,6 +2616,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2518,6 +2616,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0; return 0;
err_pf_sriov_init:
otx2_shutdown_tc(pf);
err_mcam_flow_del: err_mcam_flow_del:
otx2_mcam_flow_del(pf); otx2_mcam_flow_del(pf);
err_unreg_netdev: err_unreg_netdev:
...@@ -2576,7 +2676,7 @@ static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs) ...@@ -2576,7 +2676,7 @@ static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs)
{ {
struct net_device *netdev = pci_get_drvdata(pdev); struct net_device *netdev = pci_get_drvdata(pdev);
struct otx2_nic *pf = netdev_priv(netdev); struct otx2_nic *pf = netdev_priv(netdev);
int ret, i; int ret;
/* Init PF <=> VF mailbox stuff */ /* Init PF <=> VF mailbox stuff */
ret = otx2_pfvf_mbox_init(pf, numvfs); ret = otx2_pfvf_mbox_init(pf, numvfs);
...@@ -2587,23 +2687,9 @@ static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs) ...@@ -2587,23 +2687,9 @@ static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs)
if (ret) if (ret)
goto free_mbox; goto free_mbox;
pf->vf_configs = kcalloc(numvfs, sizeof(struct otx2_vf_config),
GFP_KERNEL);
if (!pf->vf_configs) {
ret = -ENOMEM;
goto free_intr;
}
for (i = 0; i < numvfs; i++) {
pf->vf_configs[i].pf = pf;
pf->vf_configs[i].intf_down = true;
INIT_DELAYED_WORK(&pf->vf_configs[i].link_event_work,
otx2_vf_link_event_task);
}
ret = otx2_pf_flr_init(pf, numvfs); ret = otx2_pf_flr_init(pf, numvfs);
if (ret) if (ret)
goto free_configs; goto free_intr;
ret = otx2_register_flr_me_intr(pf, numvfs); ret = otx2_register_flr_me_intr(pf, numvfs);
if (ret) if (ret)
...@@ -2618,8 +2704,6 @@ static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs) ...@@ -2618,8 +2704,6 @@ static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs)
otx2_disable_flr_me_intr(pf); otx2_disable_flr_me_intr(pf);
free_flr: free_flr:
otx2_flr_wq_destroy(pf); otx2_flr_wq_destroy(pf);
free_configs:
kfree(pf->vf_configs);
free_intr: free_intr:
otx2_disable_pfvf_mbox_intr(pf, numvfs); otx2_disable_pfvf_mbox_intr(pf, numvfs);
free_mbox: free_mbox:
...@@ -2632,17 +2716,12 @@ static int otx2_sriov_disable(struct pci_dev *pdev) ...@@ -2632,17 +2716,12 @@ static int otx2_sriov_disable(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev); struct net_device *netdev = pci_get_drvdata(pdev);
struct otx2_nic *pf = netdev_priv(netdev); struct otx2_nic *pf = netdev_priv(netdev);
int numvfs = pci_num_vf(pdev); int numvfs = pci_num_vf(pdev);
int i;
if (!numvfs) if (!numvfs)
return 0; return 0;
pci_disable_sriov(pdev); pci_disable_sriov(pdev);
for (i = 0; i < pci_num_vf(pdev); i++)
cancel_delayed_work_sync(&pf->vf_configs[i].link_event_work);
kfree(pf->vf_configs);
otx2_disable_flr_me_intr(pf); otx2_disable_flr_me_intr(pf);
otx2_flr_wq_destroy(pf); otx2_flr_wq_destroy(pf);
otx2_disable_pfvf_mbox_intr(pf, numvfs); otx2_disable_pfvf_mbox_intr(pf, numvfs);
...@@ -2682,6 +2761,7 @@ static void otx2_remove(struct pci_dev *pdev) ...@@ -2682,6 +2761,7 @@ static void otx2_remove(struct pci_dev *pdev)
unregister_netdev(netdev); unregister_netdev(netdev);
otx2_sriov_disable(pf->pdev); otx2_sriov_disable(pf->pdev);
otx2_sriov_vfcfg_cleanup(pf);
if (pf->otx2_wq) if (pf->otx2_wq)
destroy_workqueue(pf->otx2_wq); destroy_workqueue(pf->otx2_wq);
......
...@@ -395,6 +395,42 @@ static netdev_tx_t otx2vf_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -395,6 +395,42 @@ static netdev_tx_t otx2vf_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
static void otx2vf_set_rx_mode(struct net_device *netdev)
{
struct otx2_nic *vf = netdev_priv(netdev);
queue_work(vf->otx2_wq, &vf->rx_mode_work);
}
static void otx2vf_do_set_rx_mode(struct work_struct *work)
{
struct otx2_nic *vf = container_of(work, struct otx2_nic, rx_mode_work);
struct net_device *netdev = vf->netdev;
unsigned int flags = netdev->flags;
struct nix_rx_mode *req;
mutex_lock(&vf->mbox.lock);
req = otx2_mbox_alloc_msg_nix_set_rx_mode(&vf->mbox);
if (!req) {
mutex_unlock(&vf->mbox.lock);
return;
}
req->mode = NIX_RX_MODE_UCAST;
if (flags & IFF_PROMISC)
req->mode |= NIX_RX_MODE_PROMISC;
if (flags & (IFF_ALLMULTI | IFF_MULTICAST))
req->mode |= NIX_RX_MODE_ALLMULTI;
req->mode |= NIX_RX_MODE_USE_MCE;
otx2_sync_mbox_msg(&vf->mbox);
mutex_unlock(&vf->mbox.lock);
}
static int otx2vf_change_mtu(struct net_device *netdev, int new_mtu) static int otx2vf_change_mtu(struct net_device *netdev, int new_mtu)
{ {
bool if_up = netif_running(netdev); bool if_up = netif_running(netdev);
...@@ -432,12 +468,24 @@ static const struct net_device_ops otx2vf_netdev_ops = { ...@@ -432,12 +468,24 @@ static const struct net_device_ops otx2vf_netdev_ops = {
.ndo_open = otx2vf_open, .ndo_open = otx2vf_open,
.ndo_stop = otx2vf_stop, .ndo_stop = otx2vf_stop,
.ndo_start_xmit = otx2vf_xmit, .ndo_start_xmit = otx2vf_xmit,
.ndo_set_rx_mode = otx2vf_set_rx_mode,
.ndo_set_mac_address = otx2_set_mac_address, .ndo_set_mac_address = otx2_set_mac_address,
.ndo_change_mtu = otx2vf_change_mtu, .ndo_change_mtu = otx2vf_change_mtu,
.ndo_get_stats64 = otx2_get_stats64, .ndo_get_stats64 = otx2_get_stats64,
.ndo_tx_timeout = otx2_tx_timeout, .ndo_tx_timeout = otx2_tx_timeout,
}; };
static int otx2_wq_init(struct otx2_nic *vf)
{
vf->otx2_wq = create_singlethread_workqueue("otx2vf_wq");
if (!vf->otx2_wq)
return -ENOMEM;
INIT_WORK(&vf->rx_mode_work, otx2vf_do_set_rx_mode);
INIT_WORK(&vf->reset_task, otx2vf_reset_task);
return 0;
}
static int otx2vf_realloc_msix_vectors(struct otx2_nic *vf) static int otx2vf_realloc_msix_vectors(struct otx2_nic *vf)
{ {
struct otx2_hw *hw = &vf->hw; struct otx2_hw *hw = &vf->hw;
...@@ -588,8 +636,6 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -588,8 +636,6 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
netdev->min_mtu = OTX2_MIN_MTU; netdev->min_mtu = OTX2_MIN_MTU;
netdev->max_mtu = otx2_get_max_mtu(vf); netdev->max_mtu = otx2_get_max_mtu(vf);
INIT_WORK(&vf->reset_task, otx2vf_reset_task);
/* To distinguish, for LBK VFs set netdev name explicitly */ /* To distinguish, for LBK VFs set netdev name explicitly */
if (is_otx2_lbkvf(vf->pdev)) { if (is_otx2_lbkvf(vf->pdev)) {
int n; int n;
...@@ -606,6 +652,10 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -606,6 +652,10 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_detach_rsrc; goto err_detach_rsrc;
} }
err = otx2_wq_init(vf);
if (err)
goto err_unreg_netdev;
otx2vf_set_ethtool_ops(netdev); otx2vf_set_ethtool_ops(netdev);
/* Enable pause frames by default */ /* Enable pause frames by default */
...@@ -614,6 +664,8 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -614,6 +664,8 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0; return 0;
err_unreg_netdev:
unregister_netdev(netdev);
err_detach_rsrc: err_detach_rsrc:
if (hw->lmt_base) if (hw->lmt_base)
iounmap(hw->lmt_base); iounmap(hw->lmt_base);
...@@ -644,6 +696,8 @@ static void otx2vf_remove(struct pci_dev *pdev) ...@@ -644,6 +696,8 @@ static void otx2vf_remove(struct pci_dev *pdev)
cancel_work_sync(&vf->reset_task); cancel_work_sync(&vf->reset_task);
unregister_netdev(netdev); unregister_netdev(netdev);
if (vf->otx2_wq)
destroy_workqueue(vf->otx2_wq);
otx2vf_disable_mbox_intr(vf); otx2vf_disable_mbox_intr(vf);
otx2_detach_resources(&vf->mbox); otx2_detach_resources(&vf->mbox);
......
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