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

Commit 0518c12f authored by Michal Kalderon's avatar Michal Kalderon Committed by David S. Miller
Browse files

qed*: LL2 callback operations



LL2 today is interrupt driven - when tx/rx completion arrives [or any
other indication], qed needs to operate on the connection and pass
the information to the protocol-driver [or internal qed consumer].
Since we have several flavors of ll2 employeed by the driver,
each handler needs to do an if-else to determine the right functionality
to use based on the connection type.

In order to make things more scalable [given that we're going to add
additional types of ll2 flavors] move the infrastrucutre into using
a callback-based approach - the callbacks would be provided as part
of the connection's initialization parameters.

Signed-off-by: default avatarMichal Kalderon <Michal.Kalderon@cavium.com>
Signed-off-by: default avatarYuval Mintz <Yuval.Mintz@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 58de2898
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -886,7 +886,7 @@ static void qedr_mac_address_change(struct qedr_dev *dev)
	memcpy(&sgid->raw[8], guid, sizeof(guid));

	/* Update LL2 */
	rc = dev->ops->roce_ll2_set_mac_filter(dev->cdev,
	rc = dev->ops->ll2_set_mac_filter(dev->cdev,
					  dev->gsi_ll2_mac_address,
					  dev->ndev->dev_addr);

+2 −0
Original line number Diff line number Diff line
@@ -150,6 +150,8 @@ struct qedr_dev {
	u32			dp_module;
	u8			dp_level;
	u8			num_hwfns;
	u8			gsi_ll2_handle;

	uint			wq_multiplier;
	u8			gsi_ll2_mac_address[ETH_ALEN];
	int			gsi_qp_created;
+183 −55
Original line number Diff line number Diff line
@@ -64,9 +64,14 @@ void qedr_store_gsi_qp_cq(struct qedr_dev *dev, struct qedr_qp *qp,
	dev->gsi_qp = qp;
}

void qedr_ll2_tx_cb(void *_qdev, struct qed_roce_ll2_packet *pkt)
void qedr_ll2_complete_tx_packet(void *cxt,
				 u8 connection_handle,
				 void *cookie,
				 dma_addr_t first_frag_addr,
				 bool b_last_fragment, bool b_last_packet)
{
	struct qedr_dev *dev = (struct qedr_dev *)_qdev;
	struct qedr_dev *dev = (struct qedr_dev *)cxt;
	struct qed_roce_ll2_packet *pkt = cookie;
	struct qedr_cq *cq = dev->gsi_sqcq;
	struct qedr_qp *qp = dev->gsi_qp;
	unsigned long flags;
@@ -88,20 +93,26 @@ void qedr_ll2_tx_cb(void *_qdev, struct qed_roce_ll2_packet *pkt)
		(*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
}

void qedr_ll2_rx_cb(void *_dev, struct qed_roce_ll2_packet *pkt,
		    struct qed_roce_ll2_rx_params *params)
void qedr_ll2_complete_rx_packet(void *cxt,
				 struct qed_ll2_comp_rx_data *data)
{
	struct qedr_dev *dev = (struct qedr_dev *)_dev;
	struct qedr_dev *dev = (struct qedr_dev *)cxt;
	struct qedr_cq *cq = dev->gsi_rqcq;
	struct qedr_qp *qp = dev->gsi_qp;
	unsigned long flags;

	spin_lock_irqsave(&qp->q_lock, flags);

	qp->rqe_wr_id[qp->rq.gsi_cons].rc = params->rc;
	qp->rqe_wr_id[qp->rq.gsi_cons].vlan_id = params->vlan_id;
	qp->rqe_wr_id[qp->rq.gsi_cons].sg_list[0].length = pkt->payload[0].len;
	ether_addr_copy(qp->rqe_wr_id[qp->rq.gsi_cons].smac, params->smac);
	qp->rqe_wr_id[qp->rq.gsi_cons].rc = data->u.data_length_error ?
		-EINVAL : 0;
	qp->rqe_wr_id[qp->rq.gsi_cons].vlan_id = data->vlan;
	/* note: length stands for data length i.e. GRH is excluded */
	qp->rqe_wr_id[qp->rq.gsi_cons].sg_list[0].length =
		data->length.data_length;
	*((u32 *)&qp->rqe_wr_id[qp->rq.gsi_cons].smac[0]) =
		ntohl(data->opaque_data_0);
	*((u16 *)&qp->rqe_wr_id[qp->rq.gsi_cons].smac[4]) =
		ntohs((u16)data->opaque_data_1);

	qedr_inc_sw_gsi_cons(&qp->rq);

@@ -111,6 +122,14 @@ void qedr_ll2_rx_cb(void *_dev, struct qed_roce_ll2_packet *pkt,
		(*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
}

void qedr_ll2_release_rx_packet(void *cxt,
				u8 connection_handle,
				void *cookie,
				dma_addr_t rx_buf_addr, bool b_last_packet)
{
	/* Do nothing... */
}

static void qedr_destroy_gsi_cq(struct qedr_dev *dev,
				struct ib_qp_init_attr *attrs)
{
@@ -159,27 +178,159 @@ static inline int qedr_check_gsi_qp_attrs(struct qedr_dev *dev,
	return 0;
}

static int qedr_ll2_post_tx(struct qedr_dev *dev,
			    struct qed_roce_ll2_packet *pkt)
{
	enum qed_ll2_roce_flavor_type roce_flavor;
	struct qed_ll2_tx_pkt_info ll2_tx_pkt;
	int rc;
	int i;

	memset(&ll2_tx_pkt, 0, sizeof(ll2_tx_pkt));

	roce_flavor = (pkt->roce_mode == ROCE_V1) ?
	    QED_LL2_ROCE : QED_LL2_RROCE;

	if (pkt->roce_mode == ROCE_V2_IPV4)
		ll2_tx_pkt.enable_ip_cksum = 1;

	ll2_tx_pkt.num_of_bds = 1 /* hdr */  + pkt->n_seg;
	ll2_tx_pkt.vlan = 0;
	ll2_tx_pkt.tx_dest = pkt->tx_dest;
	ll2_tx_pkt.qed_roce_flavor = roce_flavor;
	ll2_tx_pkt.first_frag = pkt->header.baddr;
	ll2_tx_pkt.first_frag_len = pkt->header.len;
	ll2_tx_pkt.cookie = pkt;

	/* tx header */
	rc = dev->ops->ll2_prepare_tx_packet(dev->rdma_ctx,
					     dev->gsi_ll2_handle,
					     &ll2_tx_pkt, 1);
	if (rc) {
		/* TX failed while posting header - release resources */
		dma_free_coherent(&dev->pdev->dev, pkt->header.len,
				  pkt->header.vaddr, pkt->header.baddr);
		kfree(pkt);

		DP_ERR(dev, "roce ll2 tx: header failed (rc=%d)\n", rc);
		return rc;
	}

	/* tx payload */
	for (i = 0; i < pkt->n_seg; i++) {
		rc = dev->ops->ll2_set_fragment_of_tx_packet(
			dev->rdma_ctx,
			dev->gsi_ll2_handle,
			pkt->payload[i].baddr,
			pkt->payload[i].len);

		if (rc) {
			/* if failed not much to do here, partial packet has
			 * been posted we can't free memory, will need to wait
			 * for completion
			 */
			DP_ERR(dev, "ll2 tx: payload failed (rc=%d)\n", rc);
			return rc;
		}
	}

	return 0;
}

int qedr_ll2_stop(struct qedr_dev *dev)
{
	int rc;

	if (dev->gsi_ll2_handle == QED_LL2_UNUSED_HANDLE)
		return 0;

	/* remove LL2 MAC address filter */
	rc = dev->ops->ll2_set_mac_filter(dev->cdev,
					  dev->gsi_ll2_mac_address, NULL);

	rc = dev->ops->ll2_terminate_connection(dev->rdma_ctx,
						dev->gsi_ll2_handle);
	if (rc)
		DP_ERR(dev, "Failed to terminate LL2 connection (rc=%d)\n", rc);

	dev->ops->ll2_release_connection(dev->rdma_ctx, dev->gsi_ll2_handle);

	dev->gsi_ll2_handle = QED_LL2_UNUSED_HANDLE;

	return rc;
}

int qedr_ll2_start(struct qedr_dev *dev,
		   struct ib_qp_init_attr *attrs, struct qedr_qp *qp)
{
	struct qed_ll2_acquire_data data;
	struct qed_ll2_cbs cbs;
	int rc;

	/* configure and start LL2 */
	cbs.rx_comp_cb = qedr_ll2_complete_rx_packet;
	cbs.tx_comp_cb = qedr_ll2_complete_tx_packet;
	cbs.rx_release_cb = qedr_ll2_release_rx_packet;
	cbs.tx_release_cb = qedr_ll2_complete_tx_packet;
	cbs.cookie = dev;

	memset(&data, 0, sizeof(data));
	data.input.conn_type = QED_LL2_TYPE_ROCE;
	data.input.mtu = dev->ndev->mtu;
	data.input.rx_num_desc = attrs->cap.max_recv_wr;
	data.input.rx_drop_ttl0_flg = true;
	data.input.rx_vlan_removal_en = false;
	data.input.tx_num_desc = attrs->cap.max_send_wr;
	data.input.tx_tc = 0;
	data.input.tx_dest = QED_LL2_TX_DEST_NW;
	data.input.ai_err_packet_too_big = QED_LL2_DROP_PACKET;
	data.input.ai_err_no_buf = QED_LL2_DROP_PACKET;
	data.input.gsi_enable = 1;
	data.p_connection_handle = &dev->gsi_ll2_handle;
	data.cbs = &cbs;

	rc = dev->ops->ll2_acquire_connection(dev->rdma_ctx, &data);
	if (rc) {
		DP_ERR(dev,
		       "ll2 start: failed to acquire LL2 connection (rc=%d)\n",
		       rc);
		return rc;
	}

	rc = dev->ops->ll2_establish_connection(dev->rdma_ctx,
						dev->gsi_ll2_handle);
	if (rc) {
		DP_ERR(dev,
		       "ll2 start: failed to establish LL2 connection (rc=%d)\n",
		       rc);
		goto err1;
	}

	rc = dev->ops->ll2_set_mac_filter(dev->cdev, NULL, dev->ndev->dev_addr);
	if (rc)
		goto err2;

	return 0;

err2:
	dev->ops->ll2_terminate_connection(dev->rdma_ctx, dev->gsi_ll2_handle);
err1:
	dev->ops->ll2_release_connection(dev->rdma_ctx, dev->gsi_ll2_handle);

	return rc;
}

struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
				 struct ib_qp_init_attr *attrs,
				 struct qedr_qp *qp)
{
	struct qed_roce_ll2_params ll2_params;
	int rc;

	rc = qedr_check_gsi_qp_attrs(dev, attrs);
	if (rc)
		return ERR_PTR(rc);

	/* configure and start LL2 */
	memset(&ll2_params, 0, sizeof(ll2_params));
	ll2_params.max_tx_buffers = attrs->cap.max_send_wr;
	ll2_params.max_rx_buffers = attrs->cap.max_recv_wr;
	ll2_params.cbs.tx_cb = qedr_ll2_tx_cb;
	ll2_params.cbs.rx_cb = qedr_ll2_rx_cb;
	ll2_params.cb_cookie = (void *)dev;
	ll2_params.mtu = dev->ndev->mtu;
	ether_addr_copy(ll2_params.mac_address, dev->ndev->dev_addr);
	rc = dev->ops->roce_ll2_start(dev->cdev, &ll2_params);
	rc = qedr_ll2_start(dev, attrs, qp);
	if (rc) {
		DP_ERR(dev, "create gsi qp: failed on ll2 start. rc=%d\n", rc);
		return ERR_PTR(rc);
@@ -214,7 +365,7 @@ struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,
err:
	kfree(qp->rqe_wr_id);

	rc = dev->ops->roce_ll2_stop(dev->cdev);
	rc = qedr_ll2_stop(dev);
	if (rc)
		DP_ERR(dev, "create gsi qp: failed destroy on create\n");

@@ -223,15 +374,7 @@ struct ib_qp *qedr_create_gsi_qp(struct qedr_dev *dev,

int qedr_destroy_gsi_qp(struct qedr_dev *dev)
{
	int rc;

	rc = dev->ops->roce_ll2_stop(dev->cdev);
	if (rc)
		DP_ERR(dev, "destroy gsi qp: failed (rc=%d)\n", rc);
	else
		DP_DEBUG(dev, QEDR_MSG_GSI, "destroy gsi qp: success\n");

	return rc;
	return qedr_ll2_stop(dev);
}

#define QEDR_MAX_UD_HEADER_SIZE	(100)
@@ -421,7 +564,6 @@ int qedr_gsi_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
{
	struct qed_roce_ll2_packet *pkt = NULL;
	struct qedr_qp *qp = get_qedr_qp(ibqp);
	struct qed_roce_ll2_tx_params params;
	struct qedr_dev *dev = qp->dev;
	unsigned long flags;
	int rc;
@@ -449,8 +591,6 @@ int qedr_gsi_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
		goto err;
	}

	memset(&params, 0, sizeof(params));

	spin_lock_irqsave(&qp->q_lock, flags);

	rc = qedr_gsi_build_packet(dev, qp, wr, &pkt);
@@ -459,7 +599,8 @@ int qedr_gsi_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
		goto err;
	}

	rc = dev->ops->roce_ll2_tx(dev->cdev, pkt, &params);
	rc = qedr_ll2_post_tx(dev, pkt);

	if (!rc) {
		qp->wqe_wr_id[qp->sq.prod].wr_id = wr->wr_id;
		qedr_inc_sw_prod(&qp->sq);
@@ -467,17 +608,6 @@ int qedr_gsi_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
			 "gsi post send: opcode=%d, in_irq=%ld, irqs_disabled=%d, wr_id=%llx\n",
			 wr->opcode, in_irq(), irqs_disabled(), wr->wr_id);
	} else {
		if (rc == QED_ROCE_TX_HEAD_FAILURE) {
			/* TX failed while posting header - release resources */
			dma_free_coherent(&dev->pdev->dev, pkt->header.len,
					  pkt->header.vaddr, pkt->header.baddr);
			kfree(pkt);
		} else if (rc == QED_ROCE_TX_FRAG_FAILURE) {
			/* NTD since TX failed while posting a fragment. We will
			 * release the resources on TX callback
			 */
		}

		DP_ERR(dev, "gsi post send: failed to transmit (rc=%d)\n", rc);
		rc = -EAGAIN;
		*bad_wr = wr;
@@ -504,10 +634,8 @@ int qedr_gsi_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
{
	struct qedr_dev *dev = get_qedr_dev(ibqp->device);
	struct qedr_qp *qp = get_qedr_qp(ibqp);
	struct qed_roce_ll2_buffer buf;
	unsigned long flags;
	int status = 0;
	int rc;
	int rc = 0;

	if ((qp->state != QED_ROCE_QP_STATE_RTR) &&
	    (qp->state != QED_ROCE_QP_STATE_RTS)) {
@@ -518,8 +646,6 @@ int qedr_gsi_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
		return -EINVAL;
	}

	memset(&buf, 0, sizeof(buf));

	spin_lock_irqsave(&qp->q_lock, flags);

	while (wr) {
@@ -530,10 +656,12 @@ int qedr_gsi_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
			goto err;
		}

		buf.baddr = wr->sg_list[0].addr;
		buf.len = wr->sg_list[0].length;

		rc = dev->ops->roce_ll2_post_rx_buffer(dev->cdev, &buf, 0, 1);
		rc = dev->ops->ll2_post_rx_buffer(dev->rdma_ctx,
						  dev->gsi_ll2_handle,
						  wr->sg_list[0].addr,
						  wr->sg_list[0].length,
						  0 /* cookie */,
						  1 /* notify_fw */);
		if (rc) {
			DP_ERR(dev,
			       "gsi post recv: failed to post rx buffer (rc=%d)\n",
@@ -553,7 +681,7 @@ int qedr_gsi_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,

	spin_unlock_irqrestore(&qp->q_lock, flags);

	return status;
	return rc;
err:
	spin_unlock_irqrestore(&qp->q_lock, flags);
	*bad_wr = wr;
+0 −1
Original line number Diff line number Diff line
@@ -552,7 +552,6 @@ struct qed_hwfn {
#endif

	struct z_stream_s		*stream;
	struct qed_roce_ll2_info	*ll2;
};

struct pci_params {
+99 −98
Original line number Diff line number Diff line
@@ -89,13 +89,14 @@ struct qed_ll2_buffer {
	dma_addr_t phys_addr;
};

static void qed_ll2b_complete_tx_packet(struct qed_hwfn *p_hwfn,
static void qed_ll2b_complete_tx_packet(void *cxt,
					u8 connection_handle,
					void *cookie,
					dma_addr_t first_frag_addr,
					bool b_last_fragment,
					bool b_last_packet)
{
	struct qed_hwfn *p_hwfn = cxt;
	struct qed_dev *cdev = p_hwfn->cdev;
	struct sk_buff *skb = cookie;

@@ -164,9 +165,9 @@ static void qed_ll2_kill_buffers(struct qed_dev *cdev)
		qed_ll2_dealloc_buffer(cdev, buffer);
}

static void qed_ll2b_complete_rx_packet(struct qed_hwfn *p_hwfn,
				 struct qed_ll2_comp_rx_data *data)
void qed_ll2b_complete_rx_packet(void *cxt, struct qed_ll2_comp_rx_data *data)
{
	struct qed_hwfn *p_hwfn = cxt;
	struct qed_ll2_buffer *buffer = data->cookie;
	struct qed_dev *cdev = p_hwfn->cdev;
	dma_addr_t new_phys_addr;
@@ -327,16 +328,7 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
			b_last_frag =
				p_tx->cur_completing_bd_idx == p_pkt->bd_used;
			tx_frag = p_pkt->bds_set[0].tx_frag;
			if (p_ll2_conn->input.gsi_enable)
				qed_ll2b_release_tx_gsi_packet(p_hwfn,
							       p_ll2_conn->
							       my_id,
							       p_pkt->cookie,
							       tx_frag,
							       b_last_frag,
							       b_last_packet);
			else
				qed_ll2b_complete_tx_packet(p_hwfn,
			p_ll2_conn->cbs.tx_release_cb(p_ll2_conn->cbs.cookie,
						      p_ll2_conn->my_id,
						      p_pkt->cookie,
						      tx_frag,
@@ -354,7 +346,6 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
	struct qed_ll2_tx_packet *p_pkt;
	bool b_last_frag = false;
	unsigned long flags;
	dma_addr_t tx_frag;
	int rc = -EINVAL;

	spin_lock_irqsave(&p_tx->lock, flags);
@@ -395,19 +386,13 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
		list_add_tail(&p_pkt->list_entry, &p_tx->free_descq);

		spin_unlock_irqrestore(&p_tx->lock, flags);
		tx_frag = p_pkt->bds_set[0].tx_frag;
		if (p_ll2_conn->input.gsi_enable)
			qed_ll2b_complete_tx_gsi_packet(p_hwfn,
							p_ll2_conn->my_id,
							p_pkt->cookie,
							tx_frag,
							b_last_frag, !num_bds);
		else
			qed_ll2b_complete_tx_packet(p_hwfn,

		p_ll2_conn->cbs.tx_comp_cb(p_ll2_conn->cbs.cookie,
					   p_ll2_conn->my_id,
					   p_pkt->cookie,
						    tx_frag,
					   p_pkt->bds_set[0].tx_frag,
					   b_last_frag, !num_bds);

		spin_lock_irqsave(&p_tx->lock, flags);
	}

@@ -418,52 +403,16 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
	return rc;
}

static int
qed_ll2_rxq_completion_gsi(struct qed_hwfn *p_hwfn,
			   struct qed_ll2_info *p_ll2_info,
static void qed_ll2_rxq_parse_gsi(struct qed_hwfn *p_hwfn,
				  union core_rx_cqe_union *p_cqe,
			   unsigned long lock_flags, bool b_last_cqe)
				  struct qed_ll2_comp_rx_data *data)
{
	struct qed_ll2_rx_queue *p_rx = &p_ll2_info->rx_queue;
	struct qed_ll2_rx_packet *p_pkt = NULL;
	u16 packet_length, parse_flags, vlan;
	u32 src_mac_addrhi;
	u16 src_mac_addrlo;

	if (!list_empty(&p_rx->active_descq))
		p_pkt = list_first_entry(&p_rx->active_descq,
					 struct qed_ll2_rx_packet, list_entry);
	if (!p_pkt) {
		DP_NOTICE(p_hwfn,
			  "GSI Rx completion but active_descq is empty\n");
		return -EIO;
	}

	list_del(&p_pkt->list_entry);
	parse_flags = le16_to_cpu(p_cqe->rx_cqe_gsi.parse_flags.flags);
	packet_length = le16_to_cpu(p_cqe->rx_cqe_gsi.data_length);
	vlan = le16_to_cpu(p_cqe->rx_cqe_gsi.vlan);
	src_mac_addrhi = le32_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrhi);
	src_mac_addrlo = le16_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrlo);
	if (qed_chain_consume(&p_rx->rxq_chain) != p_pkt->rxq_bd)
		DP_NOTICE(p_hwfn,
			  "Mismatch between active_descq and the LL2 Rx chain\n");
	list_add_tail(&p_pkt->list_entry, &p_rx->free_descq);

	spin_unlock_irqrestore(&p_rx->lock, lock_flags);
	qed_ll2b_complete_rx_gsi_packet(p_hwfn,
					p_ll2_info->my_id,
					p_pkt->cookie,
					p_pkt->rx_buf_addr,
					packet_length,
					p_cqe->rx_cqe_gsi.data_length_error,
					parse_flags,
					vlan,
					src_mac_addrhi,
					src_mac_addrlo, b_last_cqe);
	spin_lock_irqsave(&p_rx->lock, lock_flags);

	return 0;
	data->parse_flags = le16_to_cpu(p_cqe->rx_cqe_gsi.parse_flags.flags);
	data->length.data_length = le16_to_cpu(p_cqe->rx_cqe_gsi.data_length);
	data->vlan = le16_to_cpu(p_cqe->rx_cqe_gsi.vlan);
	data->opaque_data_0 = le32_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrhi);
	data->opaque_data_1 = le16_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrlo);
	data->u.data_length_error = p_cqe->rx_cqe_gsi.data_length_error;
}

static void qed_ll2_rxq_parse_reg(struct qed_hwfn *p_hwfn,
@@ -501,7 +450,10 @@ qed_ll2_rxq_handle_completion(struct qed_hwfn *p_hwfn,
	}
	list_del(&p_pkt->list_entry);

	if (p_cqe->rx_cqe_sp.type == CORE_RX_CQE_TYPE_REGULAR)
		qed_ll2_rxq_parse_reg(p_hwfn, p_cqe, &data);
	else
		qed_ll2_rxq_parse_gsi(p_hwfn, p_cqe, &data);
	if (qed_chain_consume(&p_rx->rxq_chain) != p_pkt->rxq_bd)
		DP_NOTICE(p_hwfn,
			  "Mismatch between active_descq and the LL2 Rx chain\n");
@@ -514,7 +466,8 @@ qed_ll2_rxq_handle_completion(struct qed_hwfn *p_hwfn,
	data.b_last_packet = b_last_cqe;

	spin_unlock_irqrestore(&p_rx->lock, *p_lock_flags);
	qed_ll2b_complete_rx_packet(p_hwfn, &data);
	p_ll2_conn->cbs.rx_comp_cb(p_ll2_conn->cbs.cookie, &data);

	spin_lock_irqsave(&p_rx->lock, *p_lock_flags);

	return 0;
@@ -552,9 +505,6 @@ static int qed_ll2_rxq_completion(struct qed_hwfn *p_hwfn, void *cookie)
			rc = -EINVAL;
			break;
		case CORE_RX_CQE_TYPE_GSI_OFFLOAD:
			rc = qed_ll2_rxq_completion_gsi(p_hwfn, p_ll2_conn,
							cqe, flags, b_last_cqe);
			break;
		case CORE_RX_CQE_TYPE_REGULAR:
			rc = qed_ll2_rxq_handle_completion(p_hwfn, p_ll2_conn,
							   cqe, &flags,
@@ -1244,6 +1194,23 @@ qed_ll2_acquire_connection_ooo(struct qed_hwfn *p_hwfn,
	return rc;
}

static int
qed_ll2_set_cbs(struct qed_ll2_info *p_ll2_info, const struct qed_ll2_cbs *cbs)
{
	if (!cbs || (!cbs->rx_comp_cb ||
		     !cbs->rx_release_cb ||
		     !cbs->tx_comp_cb || !cbs->tx_release_cb || !cbs->cookie))
		return -EINVAL;

	p_ll2_info->cbs.rx_comp_cb = cbs->rx_comp_cb;
	p_ll2_info->cbs.rx_release_cb = cbs->rx_release_cb;
	p_ll2_info->cbs.tx_comp_cb = cbs->tx_comp_cb;
	p_ll2_info->cbs.tx_release_cb = cbs->tx_release_cb;
	p_ll2_info->cbs.cookie = cbs->cookie;

	return 0;
}

static enum core_error_handle
qed_ll2_get_error_choice(enum qed_ll2_error_handle err)
{
@@ -1259,9 +1226,9 @@ qed_ll2_get_error_choice(enum qed_ll2_error_handle err)
	}
}

int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
			       struct qed_ll2_acquire_data *data)
int qed_ll2_acquire_connection(void *cxt, struct qed_ll2_acquire_data *data)
{
	struct qed_hwfn *p_hwfn = cxt;
	qed_int_comp_cb_t comp_rx_cb, comp_tx_cb;
	struct qed_ll2_info *p_ll2_info = NULL;
	u8 i, *p_tx_max;
@@ -1298,6 +1265,13 @@ int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn,
	else
		*p_tx_max = min_t(u8, *p_tx_max,
				  CORE_LL2_TX_MAX_BDS_PER_PACKET);

	rc = qed_ll2_set_cbs(p_ll2_info, data->cbs);
	if (rc) {
		DP_NOTICE(p_hwfn, "Invalid callback functions\n");
		goto q_allocate_fail;
	}

	rc = qed_ll2_acquire_connection_rx(p_hwfn, p_ll2_info);
	if (rc)
		goto q_allocate_fail;
@@ -1377,8 +1351,10 @@ qed_ll2_establish_connection_ooo(struct qed_hwfn *p_hwfn,
	qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);
	qed_ooo_submit_rx_buffers(p_hwfn, p_ll2_conn);
}
int qed_ll2_establish_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)

int qed_ll2_establish_connection(void *cxt, u8 connection_handle)
{
	struct qed_hwfn *p_hwfn = cxt;
	struct qed_ll2_info *p_ll2_conn;
	struct qed_ll2_rx_queue *p_rx;
	struct qed_ll2_tx_queue *p_tx;
@@ -1505,11 +1481,12 @@ static void qed_ll2_post_rx_buffer_notify_fw(struct qed_hwfn *p_hwfn,
	DIRECT_REG_WR(p_rx->set_prod_addr, *((u32 *)&rx_prod));
}

int qed_ll2_post_rx_buffer(struct qed_hwfn *p_hwfn,
int qed_ll2_post_rx_buffer(void *cxt,
			   u8 connection_handle,
			   dma_addr_t addr,
			   u16 buf_len, void *cookie, u8 notify_fw)
{
	struct qed_hwfn *p_hwfn = cxt;
	struct core_rx_bd_with_buff_len *p_curb = NULL;
	struct qed_ll2_rx_packet *p_curp = NULL;
	struct qed_ll2_info *p_ll2_conn;
@@ -1699,11 +1676,12 @@ static void qed_ll2_tx_packet_notify(struct qed_hwfn *p_hwfn,
		   p_ll2_conn->input.conn_type, db_msg.spq_prod);
}

int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
int qed_ll2_prepare_tx_packet(void *cxt,
			      u8 connection_handle,
			      struct qed_ll2_tx_pkt_info *pkt,
			      bool notify_fw)
{
	struct qed_hwfn *p_hwfn = cxt;
	struct qed_ll2_tx_packet *p_curp = NULL;
	struct qed_ll2_info *p_ll2_conn = NULL;
	struct qed_ll2_tx_queue *p_tx;
@@ -1750,11 +1728,12 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn,
	return rc;
}

int qed_ll2_set_fragment_of_tx_packet(struct qed_hwfn *p_hwfn,
int qed_ll2_set_fragment_of_tx_packet(void *cxt,
				      u8 connection_handle,
				      dma_addr_t addr, u16 nbytes)
{
	struct qed_ll2_tx_packet *p_cur_send_packet = NULL;
	struct qed_hwfn *p_hwfn = cxt;
	struct qed_ll2_info *p_ll2_conn = NULL;
	u16 cur_send_frag_num = 0;
	struct core_tx_bd *p_bd;
@@ -1789,8 +1768,9 @@ int qed_ll2_set_fragment_of_tx_packet(struct qed_hwfn *p_hwfn,
	return 0;
}

int qed_ll2_terminate_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)
int qed_ll2_terminate_connection(void *cxt, u8 connection_handle)
{
	struct qed_hwfn *p_hwfn = cxt;
	struct qed_ll2_info *p_ll2_conn = NULL;
	int rc = -EINVAL;
	struct qed_ptt *p_ptt;
@@ -1855,8 +1835,10 @@ static void qed_ll2_release_connection_ooo(struct qed_hwfn *p_hwfn,
		kfree(p_buffer);
	}
}
void qed_ll2_release_connection(struct qed_hwfn *p_hwfn, u8 connection_handle)

void qed_ll2_release_connection(void *cxt, u8 connection_handle)
{
	struct qed_hwfn *p_hwfn = cxt;
	struct qed_ll2_info *p_ll2_conn = NULL;

	p_ll2_conn = qed_ll2_handle_sanity(p_hwfn, connection_handle);
@@ -1989,9 +1971,10 @@ static void _qed_ll2_get_pstats(struct qed_hwfn *p_hwfn,
	p_stats->sent_bcast_pkts = HILO_64_REGPAIR(pstats.sent_bcast_pkts);
}

int qed_ll2_get_stats(struct qed_hwfn *p_hwfn,
int qed_ll2_get_stats(void *cxt,
		      u8 connection_handle, struct qed_ll2_stats *p_stats)
{
	struct qed_hwfn *p_hwfn = cxt;
	struct qed_ll2_info *p_ll2_conn = NULL;
	struct qed_ptt *p_ptt;

@@ -2018,6 +2001,17 @@ int qed_ll2_get_stats(struct qed_hwfn *p_hwfn,
	return 0;
}

static void qed_ll2b_release_rx_packet(void *cxt,
				       u8 connection_handle,
				       void *cookie,
				       dma_addr_t rx_buf_addr,
				       bool b_last_packet)
{
	struct qed_hwfn *p_hwfn = cxt;

	qed_ll2_dealloc_buffer(p_hwfn->cdev, cookie);
}

static void qed_ll2_register_cb_ops(struct qed_dev *cdev,
				    const struct qed_ll2_cb_ops *ops,
				    void *cookie)
@@ -2026,11 +2020,18 @@ static void qed_ll2_register_cb_ops(struct qed_dev *cdev,
	cdev->ll2->cb_cookie = cookie;
}

struct qed_ll2_cbs ll2_cbs = {
	.rx_comp_cb = &qed_ll2b_complete_rx_packet,
	.rx_release_cb = &qed_ll2b_release_rx_packet,
	.tx_comp_cb = &qed_ll2b_complete_tx_packet,
	.tx_release_cb = &qed_ll2b_complete_tx_packet,
};

static void qed_ll2_set_conn_data(struct qed_dev *cdev,
				  struct qed_ll2_acquire_data *data,
				  struct qed_ll2_params *params,
				  enum qed_ll2_conn_type conn_type,
				  u8 *handle, bool lb, u8 gsi_enable)
				  u8 *handle, bool lb)
{
	memset(data, 0, sizeof(*data));

@@ -2040,8 +2041,10 @@ static void qed_ll2_set_conn_data(struct qed_dev *cdev,
	data->input.rx_drop_ttl0_flg = params->drop_ttl0_packets;
	data->input.rx_vlan_removal_en = params->rx_vlan_stripping;
	data->input.tx_num_desc = QED_LL2_TX_SIZE;
	data->input.gsi_enable = gsi_enable;
	data->p_connection_handle = handle;
	data->cbs = &ll2_cbs;
	ll2_cbs.cookie = QED_LEADING_HWFN(cdev);

	if (lb) {
		data->input.tx_tc = OOO_LB_TC;
		data->input.tx_dest = QED_LL2_TX_DEST_LB;
@@ -2060,7 +2063,7 @@ static int qed_ll2_start_ooo(struct qed_dev *cdev,
	int rc;

	qed_ll2_set_conn_data(cdev, &data, params,
			      QED_LL2_TYPE_ISCSI_OOO, handle, true, 0);
			      QED_LL2_TYPE_ISCSI_OOO, handle, true);

	rc = qed_ll2_acquire_connection(hwfn, &data);
	if (rc) {
@@ -2090,7 +2093,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
	struct qed_ll2_acquire_data data;
	struct qed_ptt *p_ptt;
	int rc, i;
	u8 gsi_enable = 1;


	/* Initialize LL2 locks & lists */
	INIT_LIST_HEAD(&cdev->ll2->list);
@@ -2122,11 +2125,9 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
	switch (QED_LEADING_HWFN(cdev)->hw_info.personality) {
	case QED_PCI_FCOE:
		conn_type = QED_LL2_TYPE_FCOE;
		gsi_enable = 0;
		break;
	case QED_PCI_ISCSI:
		conn_type = QED_LL2_TYPE_ISCSI;
		gsi_enable = 0;
		break;
	case QED_PCI_ETH_ROCE:
		conn_type = QED_LL2_TYPE_ROCE;
@@ -2136,7 +2137,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
	}

	qed_ll2_set_conn_data(cdev, &data, params, conn_type,
			      &cdev->ll2->handle, false, gsi_enable);
			      &cdev->ll2->handle, false);

	rc = qed_ll2_acquire_connection(QED_LEADING_HWFN(cdev), &data);
	if (rc) {
Loading