/* When a new command is implemented, the below table should be updated * with new command and it's version info.
*/ static u32 pfvf_cmd_versions[OCTEP_PFVF_MBOX_CMD_MAX] = {
[0 ... OCTEP_PFVF_MBOX_CMD_DEV_REMOVE] = OCTEP_PFVF_MBOX_VERSION_V1,
[OCTEP_PFVF_MBOX_CMD_GET_FW_INFO ... OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS] =
OCTEP_PFVF_MBOX_VERSION_V2
};
staticvoid octep_pfvf_validate_version(struct octep_device *oct, u32 vf_id, union octep_pfvf_mbox_word cmd, union octep_pfvf_mbox_word *rsp)
{
u32 vf_version = (u32)cmd.s_version.version;
staticvoid octep_pfvf_get_link_status(struct octep_device *oct, u32 vf_id, union octep_pfvf_mbox_word cmd, union octep_pfvf_mbox_word *rsp)
{ int status;
status = octep_ctrl_net_get_link_status(oct, vf_id); if (status < 0) {
rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
dev_err(&oct->pdev->dev, "Get VF link status failed via host control Mbox\n"); return;
}
rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
rsp->s_link_status.status = status;
}
staticvoid octep_pfvf_set_link_status(struct octep_device *oct, u32 vf_id, union octep_pfvf_mbox_word cmd, union octep_pfvf_mbox_word *rsp)
{ int err;
err = octep_ctrl_net_set_link_status(oct, vf_id, cmd.s_link_status.status, true); if (err) {
rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
dev_err(&oct->pdev->dev, "Set VF link status failed via host control Mbox\n"); return;
}
rsp->s_link_status.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
}
staticvoid octep_pfvf_set_rx_state(struct octep_device *oct, u32 vf_id, union octep_pfvf_mbox_word cmd, union octep_pfvf_mbox_word *rsp)
{ int err;
err = octep_ctrl_net_set_rx_state(oct, vf_id, cmd.s_link_state.state, true); if (err) {
rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
dev_err(&oct->pdev->dev, "Set VF Rx link state failed via host control Mbox\n"); return;
}
rsp->s_link_state.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
}
/* check if VF PF Mailbox is compatible for this notification */ if (pfvf_cmd_versions[cmd.s.opcode] > oct->vf_info[vf_id].mbox_version) {
dev_dbg(&oct->pdev->dev, "VF Mbox doesn't support Notification:%d on VF ver:%d\n",
cmd.s.opcode, oct->vf_info[vf_id].mbox_version); return -EOPNOTSUPP;
}
max_rings_per_vf = CFG_GET_MAX_RPVF(oct->conf);
vf_mbox_queue = vf_id * max_rings_per_vf; if (!oct->mbox[vf_mbox_queue]) {
dev_err(&oct->pdev->dev, "Notif obtained for bad mbox vf %d\n", vf_id); return -EINVAL;
}
mbox = oct->mbox[vf_mbox_queue];
staticvoid octep_pfvf_set_mac_addr(struct octep_device *oct, u32 vf_id, union octep_pfvf_mbox_word cmd, union octep_pfvf_mbox_word *rsp)
{ int err;
if (oct->vf_info[vf_id].flags & OCTEON_PFVF_FLAG_MAC_SET_BY_PF) {
dev_err(&oct->pdev->dev, "VF%d attempted to override administrative set MAC address\n",
vf_id);
rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; return;
}
err = octep_ctrl_net_set_mac_addr(oct, vf_id, cmd.s_set_mac.mac_addr, true); if (err) {
rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
dev_err(&oct->pdev->dev, "Set VF%d MAC address failed via host control Mbox\n",
vf_id); return;
}
free_mbox: while (i) {
i--;
ring = rings_per_vf * i;
cancel_work_sync(&oct->mbox[ring]->wk.work);
mutex_destroy(&oct->mbox[ring]->lock);
vfree(oct->mbox[ring]);
oct->mbox[ring] = NULL;
} return -ENOMEM;
}
void octep_delete_pfvf_mbox(struct octep_device *oct)
{ int rings_per_vf = oct->conf->sriov_cfg.max_rings_per_vf; int num_vfs = oct->conf->sriov_cfg.active_vfs; int i = 0, ring = 0, vf_srn = 0;
for (i = 0; i < num_vfs; i++) {
ring = vf_srn + rings_per_vf * i; if (!oct->mbox[ring]) continue;
if (work_pending(&oct->mbox[ring]->wk.work))
cancel_work_sync(&oct->mbox[ring]->wk.work);
staticvoid octep_pfvf_pf_get_data(struct octep_device *oct, struct octep_mbox *mbox, int vf_id, union octep_pfvf_mbox_word cmd, union octep_pfvf_mbox_word *rsp)
{ int length = 0; int i = 0; int err; struct octep_iface_link_info link_info; struct octep_iface_rx_stats rx_stats; struct octep_iface_tx_stats tx_stats;
rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
if (cmd.s_data.frag != OCTEP_PFVF_MBOX_MORE_FRAG_FLAG) {
mbox->config_data_index = 0;
memset(mbox->config_data, 0, MAX_VF_PF_MBOX_DATA_SIZE); /* Based on the OPCODE CMD the PF driver * specific API should be called to fetch * the requested data
*/ switch (cmd.s.opcode) { case OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO:
memset(&link_info, 0, sizeof(link_info));
err = octep_ctrl_net_get_link_info(oct, vf_id, &link_info); if (!err) {
mbox->message_len = sizeof(link_info);
*((int32_t *)rsp->s_data.data) = mbox->message_len;
memcpy(mbox->config_data, (u8 *)&link_info, sizeof(link_info));
} else {
rsp->s_data.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; return;
} break; case OCTEP_PFVF_MBOX_CMD_GET_STATS:
memset(&rx_stats, 0, sizeof(rx_stats));
memset(&tx_stats, 0, sizeof(tx_stats));
err = octep_ctrl_net_get_if_stats(oct, vf_id, &rx_stats, &tx_stats); if (!err) {
mbox->message_len = sizeof(rx_stats) + sizeof(tx_stats);
*((int32_t *)rsp->s_data.data) = mbox->message_len;
memcpy(mbox->config_data, (u8 *)&rx_stats, sizeof(rx_stats));
memcpy(mbox->config_data + sizeof(rx_stats), (u8 *)&tx_stats, sizeof(tx_stats));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.