Skip to content

Commit

Permalink
octeontx2-pf: Add support to sync link state between representor and VFs
Browse files Browse the repository at this point in the history
Implements the below requirement mentioned
in the representors documentation.

"
The representee's link state is controlled through the
representor. Setting the representor administratively UP
or DOWN should cause carrier ON or OFF at the representee.
"

This patch enables
- Reflecting the link state of representor based on the VF state and
 link state of VF based on representor.
- On VF interface up/down a notification is sent via mbox to representor
  to update the link state.
  eg: ip link set eth0 up/down  will disable carrier on/off
       of the corresponding representor(r0p1) interface.
- On representor interface up/down will cause the link state update of VF.
  eg: ip link set r0p1 up/down  will disable carrier on/off
       of the corresponding representee(eth0) interface.

Signed-off-by: Harman Kalra <hkalra@marvell.com>
Signed-off-by: Geetha sowjanya <gakula@marvell.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Geetha sowjanya authored and David S. Miller committed Nov 13, 2024
1 parent 940754a commit b8fea84
Show file tree
Hide file tree
Showing 8 changed files with 287 additions and 3 deletions.
25 changes: 25 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/mbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ M(SET_VF_PERM, 0x00b, set_vf_perm, set_vf_perm, msg_rsp) \
M(PTP_GET_CAP, 0x00c, ptp_get_cap, msg_req, ptp_get_cap_rsp) \
M(GET_REP_CNT, 0x00d, get_rep_cnt, msg_req, get_rep_cnt_rsp) \
M(ESW_CFG, 0x00e, esw_cfg, esw_cfg_req, msg_rsp) \
M(REP_EVENT_NOTIFY, 0x00f, rep_event_notify, rep_event, msg_rsp) \
/* CGX mbox IDs (range 0x200 - 0x3FF) */ \
M(CGX_START_RXTX, 0x200, cgx_start_rxtx, msg_req, msg_rsp) \
M(CGX_STOP_RXTX, 0x201, cgx_stop_rxtx, msg_req, msg_rsp) \
Expand Down Expand Up @@ -383,12 +384,16 @@ M(CPT_INST_LMTST, 0xD00, cpt_inst_lmtst, cpt_inst_lmtst_req, msg_rsp)
#define MBOX_UP_MCS_MESSAGES \
M(MCS_INTR_NOTIFY, 0xE00, mcs_intr_notify, mcs_intr_info, msg_rsp)

#define MBOX_UP_REP_MESSAGES \
M(REP_EVENT_UP_NOTIFY, 0xEF0, rep_event_up_notify, rep_event, msg_rsp) \

enum {
#define M(_name, _id, _1, _2, _3) MBOX_MSG_ ## _name = _id,
MBOX_MESSAGES
MBOX_UP_CGX_MESSAGES
MBOX_UP_CPT_MESSAGES
MBOX_UP_MCS_MESSAGES
MBOX_UP_REP_MESSAGES
#undef M
};

Expand Down Expand Up @@ -1572,6 +1577,26 @@ struct esw_cfg_req {
u64 rsvd;
};

struct rep_evt_data {
u8 port_state;
u8 vf_state;
u16 rx_mode;
u16 rx_flags;
u16 mtu;
u64 rsvd[5];
};

struct rep_event {
struct mbox_msghdr hdr;
u16 pcifunc;
#define RVU_EVENT_PORT_STATE BIT_ULL(0)
#define RVU_EVENT_PFVF_STATE BIT_ULL(1)
#define RVU_EVENT_MTU_CHANGE BIT_ULL(2)
#define RVU_EVENT_RX_MODE_CHANGE BIT_ULL(3)
u16 event;
struct rep_evt_data evt_data;
};

struct flow_msg {
unsigned char dmac[6];
unsigned char smac[6];
Expand Down
11 changes: 11 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,11 @@ struct rvu_switch {
u16 start_entry;
};

struct rep_evtq_ent {
struct list_head node;
struct rep_event event;
};

struct rvu {
void __iomem *afreg_base;
void __iomem *pfreg_base;
Expand Down Expand Up @@ -599,6 +604,11 @@ struct rvu {
int rep_cnt;
u16 *rep2pfvf_map;
u8 rep_mode;
struct work_struct rep_evt_work;
struct workqueue_struct *rep_evt_wq;
struct list_head rep_evtq_head;
/* Representor event lock */
spinlock_t rep_evtq_lock;
};

static inline void rvu_write64(struct rvu *rvu, u64 block, u64 offset, u64 val)
Expand Down Expand Up @@ -1081,4 +1091,5 @@ void rvu_mcs_exit(struct rvu *rvu);
int rvu_rep_pf_init(struct rvu *rvu);
int rvu_rep_install_mcam_rules(struct rvu *rvu);
void rvu_rep_update_rules(struct rvu *rvu, u16 pcifunc, bool ena);
int rvu_rep_notify_pfvf_state(struct rvu *rvu, u16 pcifunc, bool enable);
#endif /* RVU_H */
15 changes: 12 additions & 3 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,6 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf,

cgx_set_pkind(rvu_cgx_pdata(cgx_id, rvu), lmac_id, pkind);
rvu_npc_set_pkind(rvu, pkind, pfvf);

break;
case NIX_INTF_TYPE_LBK:
vf = (pcifunc & RVU_PFVF_FUNC_MASK) - 1;
Expand Down Expand Up @@ -5180,7 +5179,7 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req,
{
u16 pcifunc = req->hdr.pcifunc;
struct rvu_pfvf *pfvf;
int nixlf, err;
int nixlf, err, pf;

err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL);
if (err)
Expand All @@ -5198,6 +5197,10 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req,

rvu_switch_update_rules(rvu, pcifunc, true);

pf = rvu_get_pf(pcifunc);
if (is_pf_cgxmapped(rvu, pf) && rvu->rep_mode)
rvu_rep_notify_pfvf_state(rvu, pcifunc, true);

return rvu_cgx_start_stop_io(rvu, pcifunc, true);
}

Expand All @@ -5206,7 +5209,7 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
{
u16 pcifunc = req->hdr.pcifunc;
struct rvu_pfvf *pfvf;
int nixlf, err;
int nixlf, err, pf;

err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL);
if (err)
Expand All @@ -5227,6 +5230,9 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
rvu_switch_update_rules(rvu, pcifunc, false);
rvu_cgx_tx_enable(rvu, pcifunc, true);

pf = rvu_get_pf(pcifunc);
if (is_pf_cgxmapped(rvu, pf) && rvu->rep_mode)
rvu_rep_notify_pfvf_state(rvu, pcifunc, false);
return 0;
}

Expand Down Expand Up @@ -5254,6 +5260,9 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)

clear_bit(NIXLF_INITIALIZED, &pfvf->flags);

if (is_pf_cgxmapped(rvu, pf) && rvu->rep_mode)
rvu_rep_notify_pfvf_state(rvu, pcifunc, false);

rvu_cgx_start_stop_io(rvu, pcifunc, false);

if (pfvf->sq_ctx) {
Expand Down
128 changes: 128 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,124 @@
#include "rvu.h"
#include "rvu_reg.h"

#define M(_name, _id, _fn_name, _req_type, _rsp_type) \
static struct _req_type __maybe_unused \
*otx2_mbox_alloc_msg_ ## _fn_name(struct rvu *rvu, int devid) \
{ \
struct _req_type *req; \
\
req = (struct _req_type *)otx2_mbox_alloc_msg_rsp( \
&rvu->afpf_wq_info.mbox_up, devid, sizeof(struct _req_type), \
sizeof(struct _rsp_type)); \
if (!req) \
return NULL; \
req->hdr.sig = OTX2_MBOX_REQ_SIG; \
req->hdr.id = _id; \
return req; \
}

MBOX_UP_REP_MESSAGES
#undef M

static int rvu_rep_up_notify(struct rvu *rvu, struct rep_event *event)
{
struct rep_event *msg;
int pf;

pf = rvu_get_pf(event->pcifunc);

mutex_lock(&rvu->mbox_lock);
msg = otx2_mbox_alloc_msg_rep_event_up_notify(rvu, pf);
if (!msg) {
mutex_unlock(&rvu->mbox_lock);
return -ENOMEM;
}

msg->hdr.pcifunc = event->pcifunc;
msg->event = event->event;

memcpy(&msg->evt_data, &event->evt_data, sizeof(struct rep_evt_data));

otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf);

otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf);

mutex_unlock(&rvu->mbox_lock);
return 0;
}

static void rvu_rep_wq_handler(struct work_struct *work)
{
struct rvu *rvu = container_of(work, struct rvu, rep_evt_work);
struct rep_evtq_ent *qentry;
struct rep_event *event;
unsigned long flags;

do {
spin_lock_irqsave(&rvu->rep_evtq_lock, flags);
qentry = list_first_entry_or_null(&rvu->rep_evtq_head,
struct rep_evtq_ent,
node);
if (qentry)
list_del(&qentry->node);

spin_unlock_irqrestore(&rvu->rep_evtq_lock, flags);
if (!qentry)
break; /* nothing more to process */

event = &qentry->event;

rvu_rep_up_notify(rvu, event);
kfree(qentry);
} while (1);
}

int rvu_mbox_handler_rep_event_notify(struct rvu *rvu, struct rep_event *req,
struct msg_rsp *rsp)
{
struct rep_evtq_ent *qentry;

qentry = kmalloc(sizeof(*qentry), GFP_ATOMIC);
if (!qentry)
return -ENOMEM;

qentry->event = *req;
spin_lock(&rvu->rep_evtq_lock);
list_add_tail(&qentry->node, &rvu->rep_evtq_head);
spin_unlock(&rvu->rep_evtq_lock);
queue_work(rvu->rep_evt_wq, &rvu->rep_evt_work);
return 0;
}

int rvu_rep_notify_pfvf_state(struct rvu *rvu, u16 pcifunc, bool enable)
{
struct rep_event *req;
int pf;

if (!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc)))
return 0;

pf = rvu_get_pf(rvu->rep_pcifunc);

mutex_lock(&rvu->mbox_lock);
req = otx2_mbox_alloc_msg_rep_event_up_notify(rvu, pf);
if (!req) {
mutex_unlock(&rvu->mbox_lock);
return -ENOMEM;
}

req->hdr.pcifunc = rvu->rep_pcifunc;
req->event |= RVU_EVENT_PFVF_STATE;
req->pcifunc = pcifunc;
req->evt_data.vf_state = enable;

otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf);
otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf);

mutex_unlock(&rvu->mbox_lock);
return 0;
}

#define RVU_LF_RX_STATS(reg) \
rvu_read64(rvu, blkaddr, NIX_AF_LFX_RX_STATX(nixlf, reg))

Expand Down Expand Up @@ -248,6 +366,16 @@ int rvu_rep_install_mcam_rules(struct rvu *rvu)
}
}
}

/* Initialize the wq for handling REP events */
spin_lock_init(&rvu->rep_evtq_lock);
INIT_LIST_HEAD(&rvu->rep_evtq_head);
INIT_WORK(&rvu->rep_evt_work, rvu_rep_wq_handler);
rvu->rep_evt_wq = alloc_workqueue("rep_evt_wq", 0, 0);
if (!rvu->rep_evt_wq) {
dev_err(rvu->dev, "REP workqueue allocation failed\n");
return -ENOMEM;
}
return 0;
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@ struct otx2_nic {
#define OTX2_FLAG_ADPTV_INT_COAL_ENABLED BIT_ULL(16)
#define OTX2_FLAG_TC_MARK_ENABLED BIT_ULL(17)
#define OTX2_FLAG_REP_MODE_ENABLED BIT_ULL(18)
#define OTX2_FLAG_PORT_UP BIT_ULL(19)
u64 flags;
u64 *cq_op_addr;

Expand Down Expand Up @@ -1125,4 +1126,5 @@ u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
int otx2_get_txq_by_classid(struct otx2_nic *pfvf, u16 classid);
void otx2_qos_config_txschq(struct otx2_nic *pfvf);
void otx2_clean_qos_queues(struct otx2_nic *pfvf);
int rvu_event_up_notify(struct otx2_nic *pf, struct rep_event *info);
#endif /* OTX2_COMMON_H */
30 changes: 30 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ static void otx2_pfvf_mbox_up_handler(struct work_struct *work)

switch (msg->id) {
case MBOX_MSG_CGX_LINK_EVENT:
case MBOX_MSG_REP_EVENT_UP_NOTIFY:
break;
default:
if (msg->rc)
Expand Down Expand Up @@ -832,6 +833,9 @@ static void otx2_handle_link_event(struct otx2_nic *pf)
struct cgx_link_user_info *linfo = &pf->linfo;
struct net_device *netdev = pf->netdev;

if (pf->flags & OTX2_FLAG_PORT_UP)
return;

pr_info("%s NIC Link is %s %d Mbps %s duplex\n", netdev->name,
linfo->link_up ? "UP" : "DOWN", linfo->speed,
linfo->full_duplex ? "Full" : "Half");
Expand All @@ -844,6 +848,30 @@ static void otx2_handle_link_event(struct otx2_nic *pf)
}
}

static int otx2_mbox_up_handler_rep_event_up_notify(struct otx2_nic *pf,
struct rep_event *info,
struct msg_rsp *rsp)
{
struct net_device *netdev = pf->netdev;

if (info->event == RVU_EVENT_PORT_STATE) {
if (info->evt_data.port_state) {
pf->flags |= OTX2_FLAG_PORT_UP;
netif_carrier_on(netdev);
netif_tx_start_all_queues(netdev);
} else {
pf->flags &= ~OTX2_FLAG_PORT_UP;
netif_tx_stop_all_queues(netdev);
netif_carrier_off(netdev);
}
return 0;
}
#ifdef CONFIG_RVU_ESWITCH
rvu_event_up_notify(pf, info);
#endif
return 0;
}

int otx2_mbox_up_handler_mcs_intr_notify(struct otx2_nic *pf,
struct mcs_intr_info *event,
struct msg_rsp *rsp)
Expand Down Expand Up @@ -913,6 +941,7 @@ static int otx2_process_mbox_msg_up(struct otx2_nic *pf,
}
MBOX_UP_CGX_MESSAGES
MBOX_UP_MCS_MESSAGES
MBOX_UP_REP_MESSAGES
#undef M
break;
default:
Expand Down Expand Up @@ -1974,6 +2003,7 @@ int otx2_open(struct net_device *netdev)
}

pf->flags &= ~OTX2_FLAG_INTF_DOWN;
pf->flags &= ~OTX2_FLAG_PORT_UP;
/* 'intf_down' may be checked on any cpu */
smp_wmb();

Expand Down
Loading

0 comments on commit b8fea84

Please sign in to comment.