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

Commit 7c7973b2 authored by Mintz, Yuval's avatar Mintz, Yuval Committed by David S. Miller
Browse files

qed: LL2 to use packed information for tx



First step in revising the LL2 interface, this declares
qed_ll2_tx_pkt_info as part of the ll2 interface, and uses it for
transmission instead of receiving lots of parameters.

Signed-off-by: default avatarYuval Mintz <Yuval.Mintz@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5189c555
Loading
Loading
Loading
Loading
+57 −70
Original line number Diff line number Diff line
@@ -740,12 +740,13 @@ static void
qed_ooo_submit_tx_buffers(struct qed_hwfn *p_hwfn,
			  struct qed_ll2_info *p_ll2_conn)
{
	struct qed_ll2_tx_pkt_info tx_pkt;
	struct qed_ooo_buffer *p_buffer;
	int rc;
	u16 l4_hdr_offset_w;
	dma_addr_t first_frag;
	u16 parse_flags;
	u8 bd_flags;
	int rc;

	/* Submit Tx buffers here */
	while ((p_buffer = qed_ooo_get_ready_buffer(p_hwfn,
@@ -760,13 +761,18 @@ qed_ooo_submit_tx_buffers(struct qed_hwfn *p_hwfn,
		SET_FIELD(bd_flags, CORE_TX_BD_DATA_FORCE_VLAN_MODE, 1);
		SET_FIELD(bd_flags, CORE_TX_BD_DATA_L4_PROTOCOL, 1);

		rc = qed_ll2_prepare_tx_packet(p_hwfn, p_ll2_conn->my_id, 1,
					       p_buffer->vlan, bd_flags,
					       l4_hdr_offset_w,
					       p_ll2_conn->conn.tx_dest, 0,
					       first_frag,
					       p_buffer->packet_length,
					       p_buffer, true);
		memset(&tx_pkt, 0, sizeof(tx_pkt));
		tx_pkt.num_of_bds = 1;
		tx_pkt.vlan = p_buffer->vlan;
		tx_pkt.bd_flags = bd_flags;
		tx_pkt.l4_hdr_offset_w = l4_hdr_offset_w;
		tx_pkt.tx_dest = p_ll2_conn->conn.tx_dest;
		tx_pkt.first_frag = first_frag;
		tx_pkt.first_frag_len = p_buffer->packet_length;
		tx_pkt.cookie = p_buffer;

		rc = qed_ll2_prepare_tx_packet(p_hwfn, p_ll2_conn->my_id,
					       &tx_pkt, true);
		if (rc) {
			qed_ooo_put_ready_buffer(p_hwfn, p_hwfn->p_ooo_info,
						 p_buffer, false);
@@ -1593,20 +1599,18 @@ int qed_ll2_post_rx_buffer(struct qed_hwfn *p_hwfn,
static void qed_ll2_prepare_tx_packet_set(struct qed_hwfn *p_hwfn,
					  struct qed_ll2_tx_queue *p_tx,
					  struct qed_ll2_tx_packet *p_curp,
					  u8 num_of_bds,
					  dma_addr_t first_frag,
					  u16 first_frag_len, void *p_cookie,
					  struct qed_ll2_tx_pkt_info *pkt,
					  u8 notify_fw)
{
	list_del(&p_curp->list_entry);
	p_curp->cookie = p_cookie;
	p_curp->bd_used = num_of_bds;
	p_curp->cookie = pkt->cookie;
	p_curp->bd_used = pkt->num_of_bds;
	p_curp->notify_fw = notify_fw;
	p_tx->cur_send_packet = p_curp;
	p_tx->cur_send_frag_num = 0;

	p_curp->bds_set[p_tx->cur_send_frag_num].tx_frag = first_frag;
	p_curp->bds_set[p_tx->cur_send_frag_num].frag_len = first_frag_len;
	p_curp->bds_set[p_tx->cur_send_frag_num].tx_frag = pkt->first_frag;
	p_curp->bds_set[p_tx->cur_send_frag_num].frag_len = pkt->first_frag_len;
	p_tx->cur_send_frag_num++;
}

@@ -1614,32 +1618,33 @@ static void
qed_ll2_prepare_tx_packet_set_bd(struct qed_hwfn *p_hwfn,
				 struct qed_ll2_info *p_ll2,
				 struct qed_ll2_tx_packet *p_curp,
				 u8 num_of_bds,
				 enum core_tx_dest tx_dest,
				 u16 vlan,
				 u8 bd_flags,
				 u16 l4_hdr_offset_w,
				 enum core_roce_flavor_type roce_flavor,
				 dma_addr_t first_frag,
				 u16 first_frag_len)
				 struct qed_ll2_tx_pkt_info *pkt)
{
	struct qed_chain *p_tx_chain = &p_ll2->tx_queue.txq_chain;
	u16 prod_idx = qed_chain_get_prod_idx(p_tx_chain);
	struct core_tx_bd *start_bd = NULL;
	enum core_roce_flavor_type roce_flavor;
	enum core_tx_dest tx_dest;
	u16 bd_data = 0, frag_idx;

	roce_flavor = (pkt->qed_roce_flavor == QED_LL2_ROCE) ? CORE_ROCE
							     : CORE_RROCE;

	tx_dest = (pkt->tx_dest == QED_LL2_TX_DEST_NW) ? CORE_TX_DEST_NW
						       : CORE_TX_DEST_LB;

	start_bd = (struct core_tx_bd *)qed_chain_produce(p_tx_chain);
	start_bd->nw_vlan_or_lb_echo = cpu_to_le16(vlan);
	start_bd->nw_vlan_or_lb_echo = cpu_to_le16(pkt->vlan);
	SET_FIELD(start_bd->bitfield1, CORE_TX_BD_L4_HDR_OFFSET_W,
		  cpu_to_le16(l4_hdr_offset_w));
		  cpu_to_le16(pkt->l4_hdr_offset_w));
	SET_FIELD(start_bd->bitfield1, CORE_TX_BD_TX_DST, tx_dest);
	bd_data |= bd_flags;
	bd_data |= pkt->bd_flags;
	SET_FIELD(bd_data, CORE_TX_BD_DATA_START_BD, 0x1);
	SET_FIELD(bd_data, CORE_TX_BD_DATA_NBDS, num_of_bds);
	SET_FIELD(bd_data, CORE_TX_BD_DATA_NBDS, pkt->num_of_bds);
	SET_FIELD(bd_data, CORE_TX_BD_DATA_ROCE_FLAV, roce_flavor);
	start_bd->bd_data.as_bitfield = cpu_to_le16(bd_data);
	DMA_REGPAIR_LE(start_bd->addr, first_frag);
	start_bd->nbytes = cpu_to_le16(first_frag_len);
	DMA_REGPAIR_LE(start_bd->addr, pkt->first_frag);
	start_bd->nbytes = cpu_to_le16(pkt->first_frag_len);

	DP_VERBOSE(p_hwfn,
		   (NETIF_MSG_TX_QUEUED | QED_MSG_LL2),
@@ -1648,17 +1653,17 @@ qed_ll2_prepare_tx_packet_set_bd(struct qed_hwfn *p_hwfn,
		   p_ll2->cid,
		   p_ll2->conn.conn_type,
		   prod_idx,
		   first_frag_len,
		   num_of_bds,
		   pkt->first_frag_len,
		   pkt->num_of_bds,
		   le32_to_cpu(start_bd->addr.hi),
		   le32_to_cpu(start_bd->addr.lo));

	if (p_ll2->tx_queue.cur_send_frag_num == num_of_bds)
	if (p_ll2->tx_queue.cur_send_frag_num == pkt->num_of_bds)
		return;

	/* Need to provide the packet with additional BDs for frags */
	for (frag_idx = p_ll2->tx_queue.cur_send_frag_num;
	     frag_idx < num_of_bds; frag_idx++) {
	     frag_idx < pkt->num_of_bds; frag_idx++) {
		struct core_tx_bd **p_bd = &p_curp->bds_set[frag_idx].txq_bd;

		*p_bd = (struct core_tx_bd *)qed_chain_produce(p_tx_chain);
@@ -1726,21 +1731,13 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn *p_hwfn,

int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
			      u8 connection_handle,
			      u8 num_of_bds,
			      u16 vlan,
			      u8 bd_flags,
			      u16 l4_hdr_offset_w,
			      enum qed_ll2_tx_dest e_tx_dest,
			      enum qed_ll2_roce_flavor_type qed_roce_flavor,
			      dma_addr_t first_frag,
			      u16 first_frag_len, void *cookie, u8 notify_fw)
			      struct qed_ll2_tx_pkt_info *pkt,
			      bool notify_fw)
{
	struct qed_ll2_tx_packet *p_curp = NULL;
	struct qed_ll2_info *p_ll2_conn = NULL;
	enum core_roce_flavor_type roce_flavor;
	struct qed_ll2_tx_queue *p_tx;
	struct qed_chain *p_tx_chain;
	enum core_tx_dest tx_dest;
	unsigned long flags;
	int rc = 0;

@@ -1750,7 +1747,7 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
	p_tx = &p_ll2_conn->tx_queue;
	p_tx_chain = &p_tx->txq_chain;

	if (num_of_bds > CORE_LL2_TX_MAX_BDS_PER_PACKET)
	if (pkt->num_of_bds > CORE_LL2_TX_MAX_BDS_PER_PACKET)
		return -EIO;

	spin_lock_irqsave(&p_tx->lock, flags);
@@ -1763,7 +1760,7 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
	if (!list_empty(&p_tx->free_descq))
		p_curp = list_first_entry(&p_tx->free_descq,
					  struct qed_ll2_tx_packet, list_entry);
	if (p_curp && qed_chain_get_elem_left(p_tx_chain) < num_of_bds)
	if (p_curp && qed_chain_get_elem_left(p_tx_chain) < pkt->num_of_bds)
		p_curp = NULL;

	if (!p_curp) {
@@ -1771,26 +1768,10 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
		goto out;
	}

	tx_dest = e_tx_dest == QED_LL2_TX_DEST_NW ? CORE_TX_DEST_NW :
						    CORE_TX_DEST_LB;
	if (qed_roce_flavor == QED_LL2_ROCE) {
		roce_flavor = CORE_ROCE;
	} else if (qed_roce_flavor == QED_LL2_RROCE) {
		roce_flavor = CORE_RROCE;
	} else {
		rc = -EINVAL;
		goto out;
	}

	/* Prepare packet and BD, and perhaps send a doorbell to FW */
	qed_ll2_prepare_tx_packet_set(p_hwfn, p_tx, p_curp,
				      num_of_bds, first_frag,
				      first_frag_len, cookie, notify_fw);
	qed_ll2_prepare_tx_packet_set_bd(p_hwfn, p_ll2_conn, p_curp,
					 num_of_bds, tx_dest,
					 vlan, bd_flags, l4_hdr_offset_w,
					 roce_flavor,
					 first_frag, first_frag_len);
	qed_ll2_prepare_tx_packet_set(p_hwfn, p_tx, p_curp, pkt, notify_fw);

	qed_ll2_prepare_tx_packet_set_bd(p_hwfn, p_ll2_conn, p_curp, pkt);

	qed_ll2_tx_packet_notify(p_hwfn, p_ll2_conn);

@@ -2245,6 +2226,7 @@ static int qed_ll2_stop(struct qed_dev *cdev)

static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb)
{
	struct qed_ll2_tx_pkt_info pkt;
	const skb_frag_t *frag;
	int rc = -EINVAL, i;
	dma_addr_t mapping;
@@ -2279,12 +2261,17 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb)
		flags |= BIT(CORE_TX_BD_DATA_VLAN_INSERTION_SHIFT);
	}

	rc = qed_ll2_prepare_tx_packet(QED_LEADING_HWFN(cdev),
				       cdev->ll2->handle,
				       1 + skb_shinfo(skb)->nr_frags,
				       vlan, flags, 0, QED_LL2_TX_DEST_NW,
				       0 /* RoCE FLAVOR */,
				       mapping, skb->len, skb, 1);
	memset(&pkt, 0, sizeof(pkt));
	pkt.num_of_bds = 1 + skb_shinfo(skb)->nr_frags;
	pkt.vlan = vlan;
	pkt.bd_flags = flags;
	pkt.tx_dest = QED_LL2_TX_DEST_NW;
	pkt.first_frag = mapping;
	pkt.first_frag_len = skb->len;
	pkt.cookie = skb;

	rc = qed_ll2_prepare_tx_packet(&cdev->hwfns[0], cdev->ll2->handle,
				       &pkt, 1);
	if (rc)
		goto err;

+5 −36
Original line number Diff line number Diff line
@@ -47,12 +47,6 @@

#define QED_MAX_NUM_OF_LL2_CONNECTIONS                    (4)

enum qed_ll2_roce_flavor_type {
	QED_LL2_ROCE,
	QED_LL2_RROCE,
	MAX_QED_LL2_ROCE_FLAVOR_TYPE
};

enum qed_ll2_conn_type {
	QED_LL2_TYPE_FCOE,
	QED_LL2_TYPE_ISCSI,
@@ -64,12 +58,6 @@ enum qed_ll2_conn_type {
	MAX_QED_LL2_RX_CONN_TYPE
};

enum qed_ll2_tx_dest {
	QED_LL2_TX_DEST_NW, /* Light L2 TX Destination to the Network */
	QED_LL2_TX_DEST_LB, /* Light L2 TX Destination to the Loopback */
	QED_LL2_TX_DEST_MAX
};

struct qed_ll2_rx_packet {
	struct list_head list_entry;
	struct core_rx_bd_with_buff_len *rxq_bd;
@@ -216,35 +204,16 @@ int qed_ll2_post_rx_buffer(struct qed_hwfn *p_hwfn,
 *				      to prepare Tx packet submission to FW.
 *
 * @param p_hwfn
 * @param connection_handle	LL2 connection's handle obtained from
 *				qed_ll2_require_connection
 * @param num_of_bds		a number of requested BD equals a number of
 *				fragments in Tx packet
 * @param vlan			VLAN to insert to packet (if insertion set)
 * @param bd_flags
 * @param l4_hdr_offset_w	L4 Header Offset from start of packet
 *				(in words). This is needed if both l4_csum
 *				and ipv6_ext are set
 * @param e_tx_dest             indicates if the packet is to be transmitted via
 *                              loopback or to the network
 * @param first_frag
 * @param first_frag_len
 * @param cookie
 *
 * @param notify_fw
 * @param connection_handle
 * @param pkt - info regarding the tx packet
 * @param notify_fw - issue doorbell to fw for this packet
 *
 * @return 0 on success, failure otherwise
 */
int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
			      u8 connection_handle,
			      u8 num_of_bds,
			      u16 vlan,
			      u8 bd_flags,
			      u16 l4_hdr_offset_w,
			      enum qed_ll2_tx_dest e_tx_dest,
			      enum qed_ll2_roce_flavor_type qed_roce_flavor,
			      dma_addr_t first_frag,
			      u16 first_frag_len, void *cookie, u8 notify_fw);
			      struct qed_ll2_tx_pkt_info *pkt,
			      bool notify_fw);

/**
 * @brief qed_ll2_release_connection -	releases resources
+13 −5
Original line number Diff line number Diff line
@@ -2937,6 +2937,7 @@ static int qed_roce_ll2_tx(struct qed_dev *cdev,
	struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
	struct qed_roce_ll2_info *roce_ll2 = hwfn->ll2;
	enum qed_ll2_roce_flavor_type qed_roce_flavor;
	struct qed_ll2_tx_pkt_info ll2_pkt;
	u8 flags = 0;
	int rc;
	int i;
@@ -2955,11 +2956,18 @@ static int qed_roce_ll2_tx(struct qed_dev *cdev,
		flags |= BIT(CORE_TX_BD_DATA_IP_CSUM_SHIFT);

	/* Tx header */
	rc = qed_ll2_prepare_tx_packet(QED_LEADING_HWFN(cdev), roce_ll2->handle,
				       1 + pkt->n_seg, 0, flags, 0,
				       QED_LL2_TX_DEST_NW,
				       qed_roce_flavor, pkt->header.baddr,
				       pkt->header.len, pkt, 1);
	memset(&ll2_pkt, 0, sizeof(ll2_pkt));
	ll2_pkt.num_of_bds = 1 + pkt->n_seg;
	ll2_pkt.bd_flags = flags;
	ll2_pkt.tx_dest = QED_LL2_TX_DEST_NW;
	ll2_pkt.qed_roce_flavor = qed_roce_flavor;
	ll2_pkt.first_frag = pkt->header.baddr;
	ll2_pkt.first_frag_len = pkt->header.len;
	ll2_pkt.cookie = pkt;

	rc = qed_ll2_prepare_tx_packet(QED_LEADING_HWFN(cdev),
				       roce_ll2->handle,
				       &ll2_pkt, 1);
	if (rc) {
		DP_ERR(cdev, "roce ll2 tx: header failed (rc=%d)\n", rc);
		return QED_ROCE_TX_HEAD_FAILURE;
+27 −0
Original line number Diff line number Diff line
@@ -43,6 +43,18 @@
#include <linux/slab.h>
#include <linux/qed/qed_if.h>

enum qed_ll2_roce_flavor_type {
	QED_LL2_ROCE,
	QED_LL2_RROCE,
	MAX_QED_LL2_ROCE_FLAVOR_TYPE
};

enum qed_ll2_tx_dest {
	QED_LL2_TX_DEST_NW, /* Light L2 TX Destination to the Network */
	QED_LL2_TX_DEST_LB, /* Light L2 TX Destination to the Loopback */
	QED_LL2_TX_DEST_MAX
};

struct qed_ll2_stats {
	u64 gsi_invalid_hdr;
	u64 gsi_invalid_pkt_length;
@@ -67,6 +79,21 @@ struct qed_ll2_stats {
	u64 sent_bcast_pkts;
};

struct qed_ll2_tx_pkt_info {
	void *cookie;
	dma_addr_t first_frag;
	enum qed_ll2_tx_dest tx_dest;
	enum qed_ll2_roce_flavor_type qed_roce_flavor;
	u16 vlan;
	u16 l4_hdr_offset_w;	/* from start of packet */
	u16 first_frag_len;
	u8 num_of_bds;
	u8 bd_flags;
	bool enable_ip_cksum;
	bool enable_l4_cksum;
	bool calc_ip_len;
};

#define QED_LL2_UNUSED_HANDLE   (0xff)

struct qed_ll2_cb_ops {