diff mbox

qlcnic: dma address align check

Message ID 1288085882-11988-5-git-send-email-amit.salecha@qlogic.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

amit salecha Oct. 26, 2010, 9:38 a.m. UTC
Device requires tx_hw_cosnumer to be 64 byte aligned.
Tx desc size is 64 byte, alloc tx_hw_consumer with tx desc.

Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
 drivers/net/qlcnic/qlcnic_ctx.c |   35 +++++++++++++++--------------------
 1 files changed, 15 insertions(+), 20 deletions(-)

Comments

Eric Dumazet Oct. 26, 2010, 9:54 a.m. UTC | #1
Le mardi 26 octobre 2010 à 02:38 -0700, Amit Kumar Salecha a écrit :
> Device requires tx_hw_cosnumer to be 64 byte aligned.
> Tx desc size is 64 byte, alloc tx_hw_consumer with tx desc.
> 
> Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
> ---
>  drivers/net/qlcnic/qlcnic_ctx.c |   35 +++++++++++++++--------------------
>  1 files changed, 15 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
> index 1cdc05d..21c9c28 100644
> --- a/drivers/net/qlcnic/qlcnic_ctx.c
> +++ b/drivers/net/qlcnic/qlcnic_ctx.c
> @@ -418,18 +418,9 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
>  	recv_ctx = &adapter->recv_ctx;
>  	tx_ring = adapter->tx_ring;
>  
> -	tx_ring->hw_consumer = (__le32 *)pci_alloc_consistent(pdev, sizeof(u32),
> -						&tx_ring->hw_cons_phys_addr);
> -	if (tx_ring->hw_consumer == NULL) {
> -		dev_err(&pdev->dev, "failed to allocate tx consumer\n");
> -		return -ENOMEM;
> -	}
> -	*(tx_ring->hw_consumer) = 0;
> -
>  	/* cmd desc ring */
> -	addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring),
> -			&tx_ring->phys_addr);
> -
> +	addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring) +
> +			sizeof(u32), &tx_ring->phys_addr);

Wont this use twice memory than before, due to power-of-two
allocations ?

Allocating 65536 + 4 bytes gives you 131072 bytes.


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
amit salecha Oct. 26, 2010, 10:04 a.m. UTC | #2
> -----Original Message-----

> From: Eric Dumazet [mailto:eric.dumazet@gmail.com]

> Sent: Tuesday, October 26, 2010 3:25 PM

> To: Amit Salecha

> Cc: davem@davemloft.net; netdev@vger.kernel.org; Ameen Rahman; Anirban

> Chakraborty

> Subject: Re: [PATCH] qlcnic: dma address align check

> 

> Le mardi 26 octobre 2010 à 02:38 -0700, Amit Kumar Salecha a écrit :

> > Device requires tx_hw_cosnumer to be 64 byte aligned.

> > Tx desc size is 64 byte, alloc tx_hw_consumer with tx desc.

> >

> > Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>

> > ---

> >  drivers/net/qlcnic/qlcnic_ctx.c |   35 +++++++++++++++--------------

> ------

> >  1 files changed, 15 insertions(+), 20 deletions(-)

> >

> > diff --git a/drivers/net/qlcnic/qlcnic_ctx.c

> b/drivers/net/qlcnic/qlcnic_ctx.c

> > index 1cdc05d..21c9c28 100644

> > --- a/drivers/net/qlcnic/qlcnic_ctx.c

> > +++ b/drivers/net/qlcnic/qlcnic_ctx.c

> > @@ -418,18 +418,9 @@ int qlcnic_alloc_hw_resources(struct

> qlcnic_adapter *adapter)

> >  	recv_ctx = &adapter->recv_ctx;

> >  	tx_ring = adapter->tx_ring;

> >

> > -	tx_ring->hw_consumer = (__le32 *)pci_alloc_consistent(pdev,

> sizeof(u32),

> > -						&tx_ring->hw_cons_phys_addr);

> > -	if (tx_ring->hw_consumer == NULL) {

> > -		dev_err(&pdev->dev, "failed to allocate tx consumer\n");

> > -		return -ENOMEM;

> > -	}

> > -	*(tx_ring->hw_consumer) = 0;

> > -

> >  	/* cmd desc ring */

> > -	addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring),

> > -			&tx_ring->phys_addr);

> > -

> > +	addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring) +

> > +			sizeof(u32), &tx_ring->phys_addr);

> 

> Wont this use twice memory than before, due to power-of-two

> allocations ?

> 

> Allocating 65536 + 4 bytes gives you 131072 bytes.

>

Is it ? I am not aware about such calculation.
Is pci_alloc_consistent guarantee to give PAGE align dma address ?

-Amit
Eric Dumazet Oct. 26, 2010, 10:30 a.m. UTC | #3
Le mardi 26 octobre 2010 à 05:04 -0500, Amit Salecha a écrit :

> Is it ? I am not aware about such calculation.

Yes it is

> Is pci_alloc_consistent guarantee to give PAGE align dma address ?

I believe so

By the way, you should use dma_alloc_coherent() instead of
pci_alloc_consistent() so that you can use GFP_KERNEL allocations
instead of GFP_ATOMIC, it might help in low memory conditions (if you
dont hold a spinlock at this point)


If TX_DESC_RINGSIZE(tx_ring) is not a power of two, then yes you could
probably add 64 bytes and avoid allocating a full page only for the u32
field ;)



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
amit salecha Oct. 26, 2010, 10:52 a.m. UTC | #4
> > Is pci_alloc_consistent guarantee to give PAGE align dma address ?

> 

> I believe so

> 

> By the way, you should use dma_alloc_coherent() instead of

> pci_alloc_consistent() so that you can use GFP_KERNEL allocations

> instead of GFP_ATOMIC, it might help in low memory conditions (if you

> dont hold a spinlock at this point)

> 

> 

> If TX_DESC_RINGSIZE(tx_ring) is not a power of two, then yes you could

> probably add 64 bytes and avoid allocating a full page only for the u32

> field ;)

> 

> 


TX_DESC_RINGSIZE is power of two.

If pci_alloc_consistent guarantee to give PAGE align dma address, then this patch is not required.
>
diff mbox

Patch

diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index 1cdc05d..21c9c28 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -418,18 +418,9 @@  int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
 	recv_ctx = &adapter->recv_ctx;
 	tx_ring = adapter->tx_ring;
 
-	tx_ring->hw_consumer = (__le32 *)pci_alloc_consistent(pdev, sizeof(u32),
-						&tx_ring->hw_cons_phys_addr);
-	if (tx_ring->hw_consumer == NULL) {
-		dev_err(&pdev->dev, "failed to allocate tx consumer\n");
-		return -ENOMEM;
-	}
-	*(tx_ring->hw_consumer) = 0;
-
 	/* cmd desc ring */
-	addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring),
-			&tx_ring->phys_addr);
-
+	addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring) +
+			sizeof(u32), &tx_ring->phys_addr);
 	if (addr == NULL) {
 		dev_err(&pdev->dev, "failed to allocate tx desc ring\n");
 		err = -ENOMEM;
@@ -437,6 +428,17 @@  int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
 	}
 
 	tx_ring->desc_head = (struct cmd_desc_type0 *)addr;
+	tx_ring->hw_consumer = (__le32 *)(((char *)addr) +
+					TX_DESC_RINGSIZE(tx_ring));
+	tx_ring->hw_cons_phys_addr = (dma_addr_t)(((char *)tx_ring->phys_addr) +
+					TX_DESC_RINGSIZE(tx_ring));
+	if (tx_ring->hw_cons_phys_addr & 0x3F) {
+		dev_err(&pdev->dev, "Device requires 64 byte aligned dma addr"
+			". dma_addr=%p\n", (void *)tx_ring->hw_cons_phys_addr);
+		err = -ENOMEM;
+		goto err_out_free;
+	}
+	*(tx_ring->hw_consumer) = 0;
 
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
 		rds_ring = &recv_ctx->rds_rings[ring];
@@ -516,19 +518,12 @@  void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
 	recv_ctx = &adapter->recv_ctx;
 
 	tx_ring = adapter->tx_ring;
-	if (tx_ring->hw_consumer != NULL) {
-		pci_free_consistent(adapter->pdev,
-				sizeof(u32),
-				tx_ring->hw_consumer,
-				tx_ring->hw_cons_phys_addr);
-		tx_ring->hw_consumer = NULL;
-	}
-
 	if (tx_ring->desc_head != NULL) {
 		pci_free_consistent(adapter->pdev,
-				TX_DESC_RINGSIZE(tx_ring),
+				TX_DESC_RINGSIZE(tx_ring) + sizeof(u32),
 				tx_ring->desc_head, tx_ring->phys_addr);
 		tx_ring->desc_head = NULL;
+		tx_ring->hw_consumer = NULL;
 	}
 
 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {