diff mbox

[for-4.6] iw_cxgb4: Fix bar2 virtual address calculation for T4 adapters

Message ID 1459747840-9583-1-git-send-email-hariprasad@chelsio.com (mailing list archive)
State Superseded
Headers show

Commit Message

Hariprasad S April 4, 2016, 5:30 a.m. UTC
For T4, kernel mode qps don't use the user doorbell. User mode qps during
flow control db ringing are forced into kernel, where user doorbell is
treated as kernel doorbell and proper bar2 offset in bar2 virtual space is
calculated, which incase of T4 is a bogus address, causing a kernel panic
due to illegal write during doorbell ringing.
In case of T4, kernel mode qp bar2 virtual address should be 0. Added T4
check during bar2 virtual address calculation to return 0. Fixed Bar2
range checks based on bar2 physical address.

Based on original work by Bharat Potnuri <bharat@chelsio.com>

Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
 drivers/infiniband/hw/cxgb4/cq.c | 2 +-
 drivers/infiniband/hw/cxgb4/qp.c | 6 +++++-
 2 files changed, 6 insertions(+), 2 deletions(-)

Comments

Leon Romanovsky April 4, 2016, 5:32 p.m. UTC | #1
On Mon, Apr 04, 2016 at 11:00:40AM +0530, Hariprasad Shenai wrote:
> For T4, kernel mode qps don't use the user doorbell. User mode qps during
> flow control db ringing are forced into kernel, where user doorbell is
> treated as kernel doorbell and proper bar2 offset in bar2 virtual space is
> calculated, which incase of T4 is a bogus address, causing a kernel panic
> due to illegal write during doorbell ringing.
> In case of T4, kernel mode qp bar2 virtual address should be 0. Added T4
> check during bar2 virtual address calculation to return 0. Fixed Bar2
> range checks based on bar2 physical address.
> 
> Based on original work by Bharat Potnuri <bharat@chelsio.com>
> 
> Signed-off-by: Steve Wise <swise@opengridcomputing.com>
> Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>

A very minor nitpicks:
1. Please add IB or RDMA into the subject, so we will be able to see it
clearly in git log (iw_cxgb4 -> IB/iw_cxgb4).
2. Please add kernel panic observed, so it will be documented for other
users who can potentially experience this failure without your fix.
3. Please add Fixes annotation there the issue was introduced.

> ---
>  drivers/infiniband/hw/cxgb4/cq.c | 2 +-
>  drivers/infiniband/hw/cxgb4/qp.c | 6 +++++-
>  2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
> index b4eeb783573c..b0b955724458 100644
> --- a/drivers/infiniband/hw/cxgb4/cq.c
> +++ b/drivers/infiniband/hw/cxgb4/cq.c
> @@ -162,7 +162,7 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
>  	cq->bar2_va = c4iw_bar2_addrs(rdev, cq->cqid, T4_BAR2_QTYPE_INGRESS,
>  				      &cq->bar2_qid,
>  				      user ? &cq->bar2_pa : NULL);
> -	if (user && !cq->bar2_va) {
> +	if (user && !cq->bar2_pa) {
>  		pr_warn(MOD "%s: cqid %u not in BAR2 range.\n",
>  			pci_name(rdev->lldi.pdev), cq->cqid);
>  		ret = -EINVAL;
> diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
> index e17fb5d5e033..48ca455d057b 100644
> --- a/drivers/infiniband/hw/cxgb4/qp.c
> +++ b/drivers/infiniband/hw/cxgb4/qp.c
> @@ -185,6 +185,10 @@ void __iomem *c4iw_bar2_addrs(struct c4iw_rdev *rdev, unsigned int qid,
>  
>  	if (pbar2_pa)
>  		*pbar2_pa = (rdev->bar2_pa + bar2_qoffset) & PAGE_MASK;
> +
> +	if (is_t4(rdev->lldi.adapter_type))
> +		return NULL;
> +
>  	return rdev->bar2_kva + bar2_qoffset;
>  }
>  
> @@ -270,7 +274,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
>  	/*
>  	 * User mode must have bar2 access.
>  	 */
> -	if (user && (!wq->sq.bar2_va || !wq->rq.bar2_va)) {
> +	if (user && (!wq->sq.bar2_pa || !wq->rq.bar2_pa)) {
>  		pr_warn(MOD "%s: sqid %u or rqid %u not in BAR2 range.\n",
>  			pci_name(rdev->lldi.pdev), wq->sq.qid, wq->rq.qid);
>  		goto free_dma;
> -- 
> 2.3.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index b4eeb783573c..b0b955724458 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -162,7 +162,7 @@  static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
 	cq->bar2_va = c4iw_bar2_addrs(rdev, cq->cqid, T4_BAR2_QTYPE_INGRESS,
 				      &cq->bar2_qid,
 				      user ? &cq->bar2_pa : NULL);
-	if (user && !cq->bar2_va) {
+	if (user && !cq->bar2_pa) {
 		pr_warn(MOD "%s: cqid %u not in BAR2 range.\n",
 			pci_name(rdev->lldi.pdev), cq->cqid);
 		ret = -EINVAL;
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index e17fb5d5e033..48ca455d057b 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -185,6 +185,10 @@  void __iomem *c4iw_bar2_addrs(struct c4iw_rdev *rdev, unsigned int qid,
 
 	if (pbar2_pa)
 		*pbar2_pa = (rdev->bar2_pa + bar2_qoffset) & PAGE_MASK;
+
+	if (is_t4(rdev->lldi.adapter_type))
+		return NULL;
+
 	return rdev->bar2_kva + bar2_qoffset;
 }
 
@@ -270,7 +274,7 @@  static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 	/*
 	 * User mode must have bar2 access.
 	 */
-	if (user && (!wq->sq.bar2_va || !wq->rq.bar2_va)) {
+	if (user && (!wq->sq.bar2_pa || !wq->rq.bar2_pa)) {
 		pr_warn(MOD "%s: sqid %u or rqid %u not in BAR2 range.\n",
 			pci_name(rdev->lldi.pdev), wq->sq.qid, wq->rq.qid);
 		goto free_dma;