Skip to content

Commit

Permalink
octeon_ep: control net API framework to support offloads
Browse files Browse the repository at this point in the history
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: Shinas Rasheed <srasheed@marvell.com>
Link: https://lore.kernel.org/r/20231204154940.2583140-1-srasheed@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Shinas Rasheed authored and Jakub Kicinski committed Dec 6, 2023
1 parent 93df7cc commit 5aa00e9
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 51 deletions.
1 change: 0 additions & 1 deletion drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
33 changes: 27 additions & 6 deletions drivers/net/ethernet/marvell/octeon_ep/octep_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)

Expand All @@ -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.
*/
Expand Down Expand Up @@ -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 */
Expand Down
22 changes: 21 additions & 1 deletion drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down
37 changes: 37 additions & 0 deletions drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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.
*
Expand Down
68 changes: 64 additions & 4 deletions drivers/net/ethernet/marvell/octeon_ep/octep_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand All @@ -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,
};

/**
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down
3 changes: 1 addition & 2 deletions drivers/net/ethernet/marvell/octeon_ep/octep_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,7 @@ struct octep_device {

/* Tx queues (IQ: Instruction Queue) */
u16 num_iqs;
/* pkind value to be used in every Tx hardware descriptor */
u8 pkind;

/* Pointers to Octeon Tx queues */
struct octep_iq *iq[OCTEP_MAX_IQ];

Expand Down
12 changes: 8 additions & 4 deletions drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ static int octep_setup_oq(struct octep_device *oct, int q_no)
* additional header is filled-in by Octeon after length field in
* Rx packets. this header contains additional packet information.
*/
if (oct->caps_enabled)
if (oct->conf->fw_info.rx_ol_flags)
oq->max_single_buffer_size -= OCTEP_OQ_RESP_HW_EXT_SIZE;

oq->refill_threshold = CFG_GET_OQ_REFILL_THRESHOLD(oct->conf);
Expand Down Expand Up @@ -353,11 +353,13 @@ static int __octep_oq_process_rx(struct octep_device *oct,
struct octep_oq *oq, u16 pkts_to_process)
{
struct octep_oq_resp_hw_ext *resp_hw_ext = NULL;
netdev_features_t feat = oq->netdev->features;
struct octep_rx_buffer *buff_info;
struct octep_oq_resp_hw *resp_hw;
u32 pkt, rx_bytes, desc_used;
struct sk_buff *skb;
u16 data_offset;
u16 rx_ol_flags;
u32 read_idx;

read_idx = oq->host_read_idx;
Expand All @@ -372,7 +374,7 @@ static int __octep_oq_process_rx(struct octep_device *oct,

/* Swap the length field that is in Big-Endian to CPU */
buff_info->len = be64_to_cpu(resp_hw->length);
if (oct->caps_enabled & OCTEP_CAP_RX_CHECKSUM) {
if (oct->conf->fw_info.rx_ol_flags) {
/* Extended response header is immediately after
* response header (resp_hw)
*/
Expand All @@ -384,11 +386,13 @@ static int __octep_oq_process_rx(struct octep_device *oct,
*/
data_offset = OCTEP_OQ_RESP_HW_SIZE +
OCTEP_OQ_RESP_HW_EXT_SIZE;
rx_ol_flags = resp_hw_ext->rx_ol_flags;
} else {
/* Data is immediately after
* Hardware Rx response header.
*/
data_offset = OCTEP_OQ_RESP_HW_SIZE;
rx_ol_flags = 0;
}
rx_bytes += buff_info->len;

Expand Down Expand Up @@ -444,8 +448,8 @@ static int __octep_oq_process_rx(struct octep_device *oct,

skb->dev = oq->netdev;
skb->protocol = eth_type_trans(skb, skb->dev);
if (resp_hw_ext &&
resp_hw_ext->csum_verified == OCTEP_CSUM_VERIFIED)
if (feat & NETIF_F_RXCSUM &&
OCTEP_RX_CSUM_VERIFIED(rx_ol_flags))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
Expand Down
Loading

0 comments on commit 5aa00e9

Please sign in to comment.