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

Commit 996abf0a authored by Ismail, Mustafa's avatar Ismail, Mustafa Committed by Doug Ledford
Browse files

RDMA/i40iw: Add qp table lock around AE processing



QP may be freed during Async Event processing.
Add a lock around QP table to prevent it.

Signed-off-by: default avatarMustafa Ismail <mustafa.ismail@intel.com>
Signed-off-by: default avatarFaisal Latif <faisal.latif@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 36a47933
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -254,6 +254,7 @@ struct i40iw_device {
	u32 arp_table_size;
	u32 arp_table_size;
	u32 next_arp_index;
	u32 next_arp_index;
	spinlock_t resource_lock; /* hw resource access */
	spinlock_t resource_lock; /* hw resource access */
	spinlock_t qptable_lock;
	u32 vendor_id;
	u32 vendor_id;
	u32 vendor_part_id;
	u32 vendor_part_id;
	u32 of_device_registered;
	u32 of_device_registered;
+7 −0
Original line number Original line Diff line number Diff line
@@ -106,6 +106,7 @@ u32 i40iw_initialize_hw_resources(struct i40iw_device *iwdev)
	set_bit(2, iwdev->allocated_pds);
	set_bit(2, iwdev->allocated_pds);


	spin_lock_init(&iwdev->resource_lock);
	spin_lock_init(&iwdev->resource_lock);
	spin_lock_init(&iwdev->qptable_lock);
	mrdrvbits = 24 - get_count_order(iwdev->max_mr);
	mrdrvbits = 24 - get_count_order(iwdev->max_mr);
	iwdev->mr_stagmask = ~(((1 << mrdrvbits) - 1) << (32 - mrdrvbits));
	iwdev->mr_stagmask = ~(((1 << mrdrvbits) - 1) << (32 - mrdrvbits));
	return 0;
	return 0;
@@ -301,11 +302,15 @@ void i40iw_process_aeq(struct i40iw_device *iwdev)
			    "%s ae_id = 0x%x bool qp=%d qp_id = %d\n",
			    "%s ae_id = 0x%x bool qp=%d qp_id = %d\n",
			    __func__, info->ae_id, info->qp, info->qp_cq_id);
			    __func__, info->ae_id, info->qp, info->qp_cq_id);
		if (info->qp) {
		if (info->qp) {
			spin_lock_irqsave(&iwdev->qptable_lock, flags);
			iwqp = iwdev->qp_table[info->qp_cq_id];
			iwqp = iwdev->qp_table[info->qp_cq_id];
			if (!iwqp) {
			if (!iwqp) {
				spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
				i40iw_pr_err("qp_id %d is already freed\n", info->qp_cq_id);
				i40iw_pr_err("qp_id %d is already freed\n", info->qp_cq_id);
				continue;
				continue;
			}
			}
			i40iw_add_ref(&iwqp->ibqp);
			spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
			qp = &iwqp->sc_qp;
			qp = &iwqp->sc_qp;
			spin_lock_irqsave(&iwqp->lock, flags);
			spin_lock_irqsave(&iwqp->lock, flags);
			iwqp->hw_tcp_state = info->tcp_state;
			iwqp->hw_tcp_state = info->tcp_state;
@@ -411,6 +416,8 @@ void i40iw_process_aeq(struct i40iw_device *iwdev)
				i40iw_terminate_connection(qp, info);
				i40iw_terminate_connection(qp, info);
				break;
				break;
		}
		}
		if (info->qp)
			i40iw_rem_ref(&iwqp->ibqp);
	} while (1);
	} while (1);


	if (aeqcnt)
	if (aeqcnt)
+7 −2
Original line number Original line Diff line number Diff line
@@ -506,14 +506,19 @@ void i40iw_rem_ref(struct ib_qp *ibqp)
	struct cqp_commands_info *cqp_info;
	struct cqp_commands_info *cqp_info;
	struct i40iw_device *iwdev;
	struct i40iw_device *iwdev;
	u32 qp_num;
	u32 qp_num;
	unsigned long flags;


	iwqp = to_iwqp(ibqp);
	iwqp = to_iwqp(ibqp);
	if (!atomic_dec_and_test(&iwqp->refcount))
	iwdev = iwqp->iwdev;
	spin_lock_irqsave(&iwdev->qptable_lock, flags);
	if (!atomic_dec_and_test(&iwqp->refcount)) {
		spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
		return;
		return;
	}


	iwdev = iwqp->iwdev;
	qp_num = iwqp->ibqp.qp_num;
	qp_num = iwqp->ibqp.qp_num;
	iwdev->qp_table[qp_num] = NULL;
	iwdev->qp_table[qp_num] = NULL;
	spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
	cqp_request = i40iw_get_cqp_request(&iwdev->cqp, false);
	cqp_request = i40iw_get_cqp_request(&iwdev->cqp, false);
	if (!cqp_request)
	if (!cqp_request)
		return;
		return;