Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2d254fa authored by Intiyaz Basha's avatar Intiyaz Basha Committed by David S. Miller
Browse files

liquidio: Added support for trusted VF



When a VF is trusted, all promiscuous traffic will only be sent to that VF.
In normal operation promiscuous traffic is sent to the PF. There can be
only one trusted VF per PF

Signed-off-by: default avatarIntiyaz Basha <intiyaz.basha@cavium.com>
Signed-off-by: default avatarFelix Manlunas <felix.manlunas@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cf57d49c
Loading
Loading
Loading
Loading
+116 −0
Original line number Diff line number Diff line
@@ -91,6 +91,11 @@ static int octeon_console_debug_enabled(u32 console)
 */
#define LIO_SYNC_OCTEON_TIME_INTERVAL_MS 60000

struct lio_trusted_vf_ctx {
	struct completion complete;
	int status;
};

struct liquidio_rx_ctl_context {
	int octeon_id;

@@ -3265,10 +3270,120 @@ static int liquidio_get_vf_config(struct net_device *netdev, int vfidx,
	ether_addr_copy(&ivi->mac[0], macaddr);
	ivi->vlan = oct->sriov_info.vf_vlantci[vfidx] & VLAN_VID_MASK;
	ivi->qos = oct->sriov_info.vf_vlantci[vfidx] >> VLAN_PRIO_SHIFT;
	if (oct->sriov_info.trusted_vf.active &&
	    oct->sriov_info.trusted_vf.id == vfidx)
		ivi->trusted = true;
	else
		ivi->trusted = false;
	ivi->linkstate = oct->sriov_info.vf_linkstate[vfidx];
	return 0;
}

static void trusted_vf_callback(struct octeon_device *oct_dev,
				u32 status, void *ptr)
{
	struct octeon_soft_command *sc = (struct octeon_soft_command *)ptr;
	struct lio_trusted_vf_ctx *ctx;

	ctx = (struct lio_trusted_vf_ctx *)sc->ctxptr;
	ctx->status = status;

	complete(&ctx->complete);
}

static int liquidio_send_vf_trust_cmd(struct lio *lio, int vfidx, bool trusted)
{
	struct octeon_device *oct = lio->oct_dev;
	struct lio_trusted_vf_ctx *ctx;
	struct octeon_soft_command *sc;
	int ctx_size, retval;

	ctx_size = sizeof(struct lio_trusted_vf_ctx);
	sc = octeon_alloc_soft_command(oct, 0, 0, ctx_size);

	ctx  = (struct lio_trusted_vf_ctx *)sc->ctxptr;
	init_completion(&ctx->complete);

	sc->iq_no = lio->linfo.txpciq[0].s.q_no;

	/* vfidx is 0 based, but vf_num (param1) is 1 based */
	octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
				    OPCODE_NIC_SET_TRUSTED_VF, 0, vfidx + 1,
				    trusted);

	sc->callback = trusted_vf_callback;
	sc->callback_arg = sc;
	sc->wait_time = 1000;

	retval = octeon_send_soft_command(oct, sc);
	if (retval == IQ_SEND_FAILED) {
		retval = -1;
	} else {
		/* Wait for response or timeout */
		if (wait_for_completion_timeout(&ctx->complete,
						msecs_to_jiffies(2000)))
			retval = ctx->status;
		else
			retval = -1;
	}

	octeon_free_soft_command(oct, sc);

	return retval;
}

static int liquidio_set_vf_trust(struct net_device *netdev, int vfidx,
				 bool setting)
{
	struct lio *lio = GET_LIO(netdev);
	struct octeon_device *oct = lio->oct_dev;

	if (strcmp(oct->fw_info.liquidio_firmware_version, "1.7.1") < 0) {
		/* trusted vf is not supported by firmware older than 1.7.1 */
		return -EOPNOTSUPP;
	}

	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced) {
		netif_info(lio, drv, lio->netdev, "Invalid vfidx %d\n", vfidx);
		return -EINVAL;
	}

	if (setting) {
		/* Set */

		if (oct->sriov_info.trusted_vf.active &&
		    oct->sriov_info.trusted_vf.id == vfidx)
			return 0;

		if (oct->sriov_info.trusted_vf.active) {
			netif_info(lio, drv, lio->netdev, "More than one trusted VF is not allowed\n");
			return -EPERM;
		}
	} else {
		/* Clear */

		if (!oct->sriov_info.trusted_vf.active)
			return 0;
	}

	if (!liquidio_send_vf_trust_cmd(lio, vfidx, setting)) {
		if (setting) {
			oct->sriov_info.trusted_vf.id = vfidx;
			oct->sriov_info.trusted_vf.active = true;
		} else {
			oct->sriov_info.trusted_vf.active = false;
		}

		netif_info(lio, drv, lio->netdev, "VF %u is %strusted\n", vfidx,
			   setting ? "" : "not ");
	} else {
		netif_info(lio, drv, lio->netdev, "Failed to set VF trusted\n");
		return -1;
	}

	return 0;
}

static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx,
				      int linkstate)
{
@@ -3399,6 +3514,7 @@ static const struct net_device_ops lionetdevops = {
	.ndo_set_vf_mac		= liquidio_set_vf_mac,
	.ndo_set_vf_vlan	= liquidio_set_vf_vlan,
	.ndo_get_vf_config	= liquidio_get_vf_config,
	.ndo_set_vf_trust	= liquidio_set_vf_trust,
	.ndo_set_vf_link_state  = liquidio_set_vf_link_state,
};

+7 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ enum octeon_tag_type {
#define OPCODE_NIC_IF_CFG              0x09
#define OPCODE_NIC_VF_DRV_NOTICE       0x0A
#define OPCODE_NIC_INTRMOD_PARAMS      0x0B
#define OPCODE_NIC_SET_TRUSTED_VF	0x13
#define OPCODE_NIC_SYNC_OCTEON_TIME	0x14
#define VF_DRV_LOADED                  1
#define VF_DRV_REMOVED                -1
@@ -918,6 +919,12 @@ union oct_nic_if_cfg {
	} s;
};

struct lio_trusted_vf {
	uint64_t active: 1;
	uint64_t id : 8;
	uint64_t reserved: 55;
};

struct lio_time {
	s64 sec;   /* seconds */
	s64 nsec;  /* nanoseconds */
+2 −0
Original line number Diff line number Diff line
@@ -370,6 +370,8 @@ struct octeon_sriov_info {

	u32	sriov_enabled;

	struct lio_trusted_vf	trusted_vf;

	/*lookup table that maps DPI ring number to VF pci_dev struct pointer*/
	struct pci_dev *dpiring_to_vfpcidev_lut[MAX_POSSIBLE_VFS];