Skip to contentSkip to conversation

net: nixge: Add __packed attribute to DMA descriptor struct

PATCH In review Moritz Fischer 4 participants 7 messages Jun 19, 2018 – Jun 21, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 net: nixge: Add __packed attribute to DMA descriptor struct

Add __packed attribute to DMA descriptor structure in order to make sure that the DMA engine's alignemnt requirements are met.

Fixes commit 492caffa8a1a ("net: ethernet: nixge: Add support for National Instruments XGE netdev")

---

Hi David,

this addresses an issue where padding occured breaking the alignment in the array the descriptors are allocated in coherent memory. This was discovered when we tried to bring up the driver via a PCIe bridge on x86.

Thanks,

Moritz

---
 drivers/net/ethernet/ni/nixge.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/ni/nixge.c +1 -1
index 09f674ec0f9e..fea0e994324b 100644
@@ -122,7 +122,7 @@ struct nixge_hw_dma_bd {
 	u32 sw_id_offset;
 	u32 reserved5;
 	u32 reserved6;
-};
+} __packed;
 
 struct nixge_tx_skb {
 	struct sk_buff *skb;
Signature · 1 line
2.17.1
#1 lore raw
Quoted 6 lines · Moritz Fischer

Add __packed attribute to DMA descriptor structure in order to make sure that the DMA engine's alignemnt requirements are met.

Fixes commit 492caffa8a1a ("net: ethernet: nixge: Add support for National Instruments XGE netdev")

Quoted 8 lines

---

Hi David,

this addresses an issue where padding occured breaking the alignment in the array the descriptors are allocated in coherent memory. This was discovered when we tried to bring up the driver via a PCIe bridge on x86.

How could padding be inserted given than all of the structure members are naturally aligned (all u32 type). Compiler bug?

Also

Quoted 23 lines

Thanks,

Moritz

---
 drivers/net/ethernet/ni/nixge.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/ni/nixge.c +1 -1
index 09f674ec0f9e..fea0e994324b 100644
@@ -122,7 +122,7 @@ struct nixge_hw_dma_bd {
 	u32 sw_id_offset;
 	u32 reserved5;
 	u32 reserved6;
-};
+} __packed;
 
 struct nixge_tx_skb {
 	struct sk_buff *skb;
Signature · 1 line
Florian
#2 lore raw

Hi Florian,

Quoted 11 lines · Florian Fainelli
Quoted 10 lines · Moritz Fischer

Add __packed attribute to DMA descriptor structure in order to make sure that the DMA engine's alignemnt requirements are met.

Fixes commit 492caffa8a1a ("net: ethernet: nixge: Add support for National Instruments XGE netdev")

---

Hi David,

Quoted 7 lines
Quoted 4 lines

this addresses an issue where padding occured breaking the alignment in the array the descriptors are allocated in coherent memory. This was discovered when we tried to bring up the driver via a PCIe bridge on x86.

How could padding be inserted given than all of the structure members are naturally aligned (all u32 type). Compiler bug?

I have no good answer to this, all I can tell you is that it wouldn't work otherwise. This was part of a bunch of changes that I made in order to make this work with 64bit DMA. I made sure to remove the padding/ reserved fields accordingly such that the net difference would be zero.

I might've messed that up? The descriptors looked something like this:

struct nixge_hw_dma_bd {

#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
        u64 next;
        u64 phys;
#else
        u32 next;
        u32 reserved1;
        u32 phys;
        u32 reserved2;
#endif
        u32 reserved3;
        u32 reserved4;
        u32 cntrl;
        u32 status;
        u32 app0;
        u32 app1;
        u32 app2;
        u32 app3;
        u32 app4;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
        u64 sw_id_offset;
#else
        u32 sw_id_offset;
        u32 reserved5;
#endif
        u32 reserved6;
} __packed;

I'll have some follow up patches to add 64bit support together with a wrapper driver for the PCIe bridge once the architecture solidifies here.

Thanks for the feedback,

Moritz

#3 lore raw
Quoted 22 lines · Moritz Fischer

Hi Florian,

Quoted 11 lines · Florian Fainelli
Quoted 10 lines · Moritz Fischer

Add __packed attribute to DMA descriptor structure in order to make sure that the DMA engine's alignemnt requirements are met.

Fixes commit 492caffa8a1a ("net: ethernet: nixge: Add support for National Instruments XGE netdev")

---

Hi David,

Quoted 7 lines
Quoted 4 lines

this addresses an issue where padding occured breaking the alignment in the array the descriptors are allocated in coherent memory. This was discovered when we tried to bring up the driver via a PCIe bridge on x86.

How could padding be inserted given than all of the structure members are naturally aligned (all u32 type). Compiler bug?

Quoted 6 lines

I have no good answer to this, all I can tell you is that it wouldn't work otherwise. This was part of a bunch of changes that I made in order to make this work with 64bit DMA. I made sure to remove the padding/ reserved fields accordingly such that the net difference would be zero.

I might've messed that up? The descriptors looked something like this:

Ah ah! This is not the layout in the upstream tree I am looking at, but your layout below will definitive introduce padding, yes.

Quoted 30 lines

struct nixge_hw_dma_bd {

#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
        u64 next;
        u64 phys;
#else
        u32 next;
        u32 reserved1;
        u32 phys;
        u32 reserved2;
#endif
        u32 reserved3;
        u32 reserved4;
        u32 cntrl;
        u32 status;
        u32 app0;
        u32 app1;
        u32 app2;
        u32 app3;
        u32 app4;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
        u64 sw_id_offset;
#else
        u32 sw_id_offset;
        u32 reserved5;
#endif
        u32 reserved6;
} __packed;
Quoted 2 lines

I'll have some follow up patches to add 64bit support together with a wrapper driver for the PCIe bridge once the architecture solidifies here.

Why not have the structure updated like this:

struct nixge_hw_dma_bd {
	u32 next_lo;	/* lower 32-bit address part */
	u32 next_hi;	/* upper 32-bit address part */
	u32 phys_lo;
	u32 phys_hi;
        u32 reserved3;
        u32 reserved4;
        u32 cntrl;
        u32 status;
        u32 app0;
        u32 app1;
        u32 app2;
        u32 app3;
        u32 app4;
        u32 sw_id_offset_low;
        u32 sw_id_offset_hi;
        u32 reserved6;
};

That assumes I got the upper/lower address part correct, if not, swapthe members. Then in your code, if you want to be efficient, you can populate the fields only if CONFIG_ARCH_DMA_ADDR_T_64BIT is defined. I did that in bcmgenet.c for instance because the register accesses are slow, so if we can save 200ns per packet transmit/receive, that's a win.

This should not change anything because the structure size is the same in both cases, but how you are managing is different, and that would in turn influence what the HW sees.

Does that make sense?

Quoted 5 lines

Thanks for the feedback,

Moritz

Signature · 1 line
Florian
maintainer
#4 lore raw
In reply to Florian Fainelli

From: Florian Fainelli <[email protected]>
Date: Tue, 19 Jun 2018 10:13:55 -0700

Quoted 2 lines

How could padding be inserted given than all of the structure members are naturally aligned (all u32 type). Compiler bug?

Agreed, this looks completely unnecessary.

__packed should only be used when absolutely necessary because using it generates less efficient code on some architectures.

#5 lore raw

Hi David,

Quoted 10 lines · David Miller

From: Florian Fainelli <[email protected]>
Date: Tue, 19 Jun 2018 10:13:55 -0700

Quoted 2 lines

How could padding be inserted given than all of the structure members are naturally aligned (all u32 type). Compiler bug?

Agreed, this looks completely unnecessary.

__packed should only be used when absolutely necessary because using it generates less efficient code on some architectures.

Thanks for your input, will fix with the whole series when I submit it.

- Moritz

maintainer
#6 lore raw
In reply to Moritz Fischer

From: Moritz Fischer <[email protected]>
Date: Tue, 19 Jun 2018 09:54:53 -0700

drivers/net/ethernet/ni/nixge.c struct nixge_hw_dma_bd { · line 125

Quoted 6 lines
drivers/net/ethernet/ni/nixge.c +1 -1
@@ -122,7 +122,7 @@ struct nixge_hw_dma_bd {
 	u32 sw_id_offset;
 	u32 reserved5;
 	u32 reserved6;
-};
+} __packed;

As I understand it, based upon your replies to Florian, this bug doesn't even show up with the current code. The problem only happens with some 64-bit changes you are working on.

So, the change is not valid right now.

And for the 64-bit changes, I agree with Florian that you should adjust your implementation so that this __packed dance isn't necessary and that you can avoid some MMIOs as well.

Thanks.