Commit 5aa00e9e authored by Shinas Rasheed's avatar Shinas Rasheed Committed by Jakub Kicinski
Browse files

octeon_ep: control net API framework to support offloads



Inquire firmware on supported offloads, as well as convey offloads
enabled dynamically to firmware. New control net API functionality is
required for the above. Implement control net API framework for
offloads.

Additionally, fetch/insert offload metadata from hardware RX/TX
buffer respectively during receive/transmit.

Currently supported offloads include checksum and TSO.

Signed-off-by: default avatarShinas Rasheed <srasheed@marvell.com>
Link: https://lore.kernel.org/r/20231204154940.2583140-1-srasheed@marvell.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 93df7cc6
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -231,7 +231,6 @@ static void octep_init_config_cn93_pf(struct octep_device *oct)

	conf->iq.num_descs = OCTEP_IQ_MAX_DESCRIPTORS;
	conf->iq.instr_type = OCTEP_64BYTE_INSTR;
	conf->iq.pkind = 0;
	conf->iq.db_min = OCTEP_DB_MIN;
	conf->iq.intr_threshold = OCTEP_IQ_INTR_THRESHOLD;

+27 −6
Original line number Diff line number Diff line
@@ -60,7 +60,6 @@
#define CFG_GET_IQ_CFG(cfg)             ((cfg)->iq)
#define CFG_GET_IQ_NUM_DESC(cfg)        ((cfg)->iq.num_descs)
#define CFG_GET_IQ_INSTR_TYPE(cfg)      ((cfg)->iq.instr_type)
#define CFG_GET_IQ_PKIND(cfg)           ((cfg)->iq.pkind)
#define CFG_GET_IQ_INSTR_SIZE(cfg)      (64)
#define CFG_GET_IQ_DB_MIN(cfg)          ((cfg)->iq.db_min)
#define CFG_GET_IQ_INTR_THRESHOLD(cfg)  ((cfg)->iq.intr_threshold)
@@ -76,7 +75,6 @@
#define CFG_GET_PORTS_ACTIVE_IO_RINGS(cfg) ((cfg)->pf_ring_cfg.active_io_rings)
#define CFG_GET_PORTS_PF_SRN(cfg)          ((cfg)->pf_ring_cfg.srn)

#define CFG_GET_DPI_PKIND(cfg)            ((cfg)->core_cfg.dpi_pkind)
#define CFG_GET_CORE_TICS_PER_US(cfg)     ((cfg)->core_cfg.core_tics_per_us)
#define CFG_GET_COPROC_TICS_PER_US(cfg)   ((cfg)->core_cfg.coproc_tics_per_us)

@@ -100,9 +98,6 @@ struct octep_iq_config {
	/* Command size - 32 or 64 bytes */
	u16 instr_type;

	/* pkind for packets sent to Octeon */
	u16 pkind;

	/* Minimum number of commands pending to be posted to Octeon before driver
	 * hits the Input queue doorbell.
	 */
@@ -198,11 +193,37 @@ struct octep_ctrl_mbox_config {
/* Info from firmware */
struct octep_fw_info {
	/* interface pkind */
	u16 pkind;
	u8 pkind;

	/* front size data */
	u8 fsz;

	/* heartbeat interval in milliseconds */
	u16 hb_interval;

	/* heartbeat miss count */
	u16 hb_miss_count;

	/* reserved */
	u16 reserved1;

	/* supported rx offloads OCTEP_ETH_RX_OFFLOAD_* */
	u16 rx_ol_flags;

	/* supported tx offloads OCTEP_ETH_TX_OFFLOAD_* */
	u16 tx_ol_flags;

	/* reserved */
	u32 reserved_offloads;

	/* extra offload flags */
	u64 ext_ol_flags;

	/* supported features */
	u64 features[2];

	/* reserved */
	u64 reserved2[3];
};

/* Data Structure to hold configuration limits and active config */
+21 −1
Original line number Diff line number Diff line
@@ -22,12 +22,15 @@ static const u32 mtu_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mtu);
static const u32 mac_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_mac);
static const u32 state_sz = sizeof(struct octep_ctrl_net_h2f_req_cmd_state);
static const u32 link_info_sz = sizeof(struct octep_ctrl_net_link_info);
static const u32 offloads_sz = sizeof(struct octep_ctrl_net_offloads);
static atomic_t ctrl_net_msg_id;

/* Control plane version in which OCTEP_CTRL_NET_H2F_CMD was added */
static const u32 octep_ctrl_net_h2f_cmd_versions[OCTEP_CTRL_NET_H2F_CMD_MAX] = {
	[OCTEP_CTRL_NET_H2F_CMD_INVALID ... OCTEP_CTRL_NET_H2F_CMD_DEV_REMOVE] =
	 OCTEP_CP_VERSION(1, 0, 0)
	 OCTEP_CP_VERSION(1, 0, 0),
	[OCTEP_CTRL_NET_H2F_CMD_OFFLOADS] = OCTEP_CP_VERSION(1, 0, 1)

};

/* Control plane version in which OCTEP_CTRL_NET_F2H_CMD was added */
@@ -405,6 +408,23 @@ int octep_ctrl_net_dev_remove(struct octep_device *oct, int vfid)

	return octep_send_mbox_req(oct, &d, false);
}

int octep_ctrl_net_set_offloads(struct octep_device *oct, int vfid,
				struct octep_ctrl_net_offloads *offloads,
				bool wait_for_response)
{
	struct octep_ctrl_net_wait_data d = {};
	struct octep_ctrl_net_h2f_req *req;

	req = &d.data.req;
	init_send_req(&d.msg, req, offloads_sz, vfid);
	req->hdr.s.cmd = OCTEP_CTRL_NET_H2F_CMD_OFFLOADS;
	req->offloads.cmd = OCTEP_CTRL_NET_CMD_SET;
	req->offloads.offloads = *offloads;

	return octep_send_mbox_req(oct, &d, wait_for_response);
}

int octep_ctrl_net_uninit(struct octep_device *oct)
{
	struct octep_ctrl_net_wait_data *pos, *n;
+37 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ enum octep_ctrl_net_h2f_cmd {
	OCTEP_CTRL_NET_H2F_CMD_LINK_INFO,
	OCTEP_CTRL_NET_H2F_CMD_GET_INFO,
	OCTEP_CTRL_NET_H2F_CMD_DEV_REMOVE,
	OCTEP_CTRL_NET_H2F_CMD_OFFLOADS,
	OCTEP_CTRL_NET_H2F_CMD_MAX
};

@@ -113,6 +114,26 @@ struct octep_ctrl_net_h2f_req_cmd_link_info {
	struct octep_ctrl_net_link_info info;
};

/* offloads */
struct octep_ctrl_net_offloads {
	/* supported rx offloads OCTEP_RX_OFFLOAD_* */
	u16 rx_offloads;
	/* supported tx offloads OCTEP_TX_OFFLOAD_* */
	u16 tx_offloads;
	/* reserved */
	u32 reserved_offloads;
	/* extra offloads */
	u64 ext_offloads;
};

/* get/set offloads */
struct octep_ctrl_net_h2f_req_cmd_offloads {
	/* enum octep_ctrl_net_cmd */
	u16 cmd;
	/* struct octep_ctrl_net_offloads */
	struct octep_ctrl_net_offloads offloads;
};

/* Host to fw request data */
struct octep_ctrl_net_h2f_req {
	union octep_ctrl_net_req_hdr hdr;
@@ -122,6 +143,7 @@ struct octep_ctrl_net_h2f_req {
		struct octep_ctrl_net_h2f_req_cmd_state link;
		struct octep_ctrl_net_h2f_req_cmd_state rx;
		struct octep_ctrl_net_h2f_req_cmd_link_info link_info;
		struct octep_ctrl_net_h2f_req_cmd_offloads offloads;
	};
} __packed;

@@ -179,6 +201,7 @@ struct octep_ctrl_net_h2f_resp {
		struct octep_ctrl_net_h2f_resp_cmd_state rx;
		struct octep_ctrl_net_link_info link_info;
		struct octep_ctrl_net_h2f_resp_cmd_get_info info;
		struct octep_ctrl_net_offloads offloads;
	};
} __packed;

@@ -381,6 +404,20 @@ int octep_ctrl_net_get_info(struct octep_device *oct, int vfid,
 */
int octep_ctrl_net_dev_remove(struct octep_device *oct, int vfid);

/**
 * octep_ctrl_net_set_offloads() - Set offloads in firmware.
 *
 * @oct: non-null pointer to struct octep_device.
 * @vfid: Index of virtual function.
 * @offloads: non-null pointer to struct octep_ctrl_net_offloads.
 * @wait_for_response: poll for response.
 *
 * return value: 0 on success, -errno on failure.
 */
int octep_ctrl_net_set_offloads(struct octep_device *oct, int vfid,
				struct octep_ctrl_net_offloads *offloads,
				bool wait_for_response);

/**
 * octep_ctrl_net_uninit() - Uninitialize data for ctrl net.
 *
+64 −4
Original line number Diff line number Diff line
@@ -822,6 +822,7 @@ static netdev_tx_t octep_start_xmit(struct sk_buff *skb,
				    struct net_device *netdev)
{
	struct octep_device *oct = netdev_priv(netdev);
	netdev_features_t feat  = netdev->features;
	struct octep_tx_sglist_desc *sglist;
	struct octep_tx_buffer *tx_buffer;
	struct octep_tx_desc_hw *hw_desc;
@@ -855,8 +856,9 @@ static netdev_tx_t octep_start_xmit(struct sk_buff *skb,
	tx_buffer->skb = skb;

	ih = &hw_desc->ih;
	ih->tlen = skb->len;
	ih->pkind = oct->pkind;
	ih->pkind = oct->conf->fw_info.pkind;
	ih->fsz = oct->conf->fw_info.fsz;
	ih->tlen = skb->len + ih->fsz;

	if (!nr_frags) {
		tx_buffer->gather = 0;
@@ -903,6 +905,19 @@ static netdev_tx_t octep_start_xmit(struct sk_buff *skb,
		hw_desc->dptr = tx_buffer->sglist_dma;
	}

	if (oct->conf->fw_info.tx_ol_flags) {
		if ((feat & (NETIF_F_TSO)) && (skb_is_gso(skb))) {
			hw_desc->txm.ol_flags = OCTEP_TX_OFFLOAD_CKSUM;
			hw_desc->txm.ol_flags |= OCTEP_TX_OFFLOAD_TSO;
			hw_desc->txm.gso_size =  skb_shinfo(skb)->gso_size;
			hw_desc->txm.gso_segs =  skb_shinfo(skb)->gso_segs;
		} else if (feat & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) {
			hw_desc->txm.ol_flags = OCTEP_TX_OFFLOAD_CKSUM;
		}
		/* due to ESR txm will be swapped by hw */
		hw_desc->txm64[0] = (__force u64)cpu_to_be64(hw_desc->txm64[0]);
	}

	xmit_more = netdev_xmit_more();

	__netdev_tx_sent_queue(iq->netdev_q, skb->len, xmit_more);
@@ -1067,6 +1082,41 @@ static int octep_change_mtu(struct net_device *netdev, int new_mtu)
	return err;
}

static int octep_set_features(struct net_device *dev, netdev_features_t features)
{
	struct octep_ctrl_net_offloads offloads = { 0 };
	struct octep_device *oct = netdev_priv(dev);
	int err;

	/* We only support features received from firmware */
	if ((features & dev->hw_features) != features)
		return -EINVAL;

	if (features & NETIF_F_TSO)
		offloads.tx_offloads |= OCTEP_TX_OFFLOAD_TSO;

	if (features & NETIF_F_TSO6)
		offloads.tx_offloads |= OCTEP_TX_OFFLOAD_TSO;

	if (features & NETIF_F_IP_CSUM)
		offloads.tx_offloads |= OCTEP_TX_OFFLOAD_CKSUM;

	if (features & NETIF_F_IPV6_CSUM)
		offloads.tx_offloads |= OCTEP_TX_OFFLOAD_CKSUM;

	if (features & NETIF_F_RXCSUM)
		offloads.rx_offloads |= OCTEP_RX_OFFLOAD_CKSUM;

	err = octep_ctrl_net_set_offloads(oct,
					  OCTEP_CTRL_NET_INVALID_VFID,
					  &offloads,
					  true);
	if (!err)
		dev->features = features;

	return err;
}

static const struct net_device_ops octep_netdev_ops = {
	.ndo_open                = octep_open,
	.ndo_stop                = octep_stop,
@@ -1075,6 +1125,7 @@ static const struct net_device_ops octep_netdev_ops = {
	.ndo_tx_timeout          = octep_tx_timeout,
	.ndo_set_mac_address     = octep_set_mac,
	.ndo_change_mtu          = octep_change_mtu,
	.ndo_set_features        = octep_set_features,
};

/**
@@ -1222,7 +1273,6 @@ int octep_device_setup(struct octep_device *oct)
		goto unsupported_dev;
	}

	oct->pkind = CFG_GET_IQ_PKIND(oct->conf);

	ret = octep_ctrl_net_init(oct);
	if (ret)
@@ -1381,7 +1431,11 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	netif_carrier_off(netdev);

	netdev->hw_features = NETIF_F_SG;
	netdev->features |= netdev->hw_features;
	if (OCTEP_TX_IP_CSUM(octep_dev->conf->fw_info.tx_ol_flags))
		netdev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);

	if (OCTEP_RX_IP_CSUM(octep_dev->conf->fw_info.rx_ol_flags))
		netdev->hw_features |= NETIF_F_RXCSUM;

	max_rx_pktlen = octep_ctrl_net_get_mtu(octep_dev, OCTEP_CTRL_NET_INVALID_VFID);
	if (max_rx_pktlen < 0) {
@@ -1394,6 +1448,12 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	netdev->max_mtu = max_rx_pktlen - (ETH_HLEN + ETH_FCS_LEN);
	netdev->mtu = OCTEP_DEFAULT_MTU;

	if (OCTEP_TX_TSO(octep_dev->conf->fw_info.tx_ol_flags)) {
		netdev->hw_features |= NETIF_F_TSO;
		netif_set_tso_max_size(netdev, netdev->max_mtu);
	}

	netdev->features |= netdev->hw_features;
	err = octep_ctrl_net_get_mac_addr(octep_dev, OCTEP_CTRL_NET_INVALID_VFID,
					  octep_dev->mac_addr);
	if (err) {
Loading