rt2x00: byte ordering correctness
Subsystems (3)
PATCH 20/32 rt2x00: byte ordering correctness
From: Ivo van Doorn <[email protected]>
Fix various little/big endian conversions. rt2500pci should use cpu_to_le32 and rt2500usb should not.
drivers/net/wireless/d80211/rt2x00/rt2500pci.c +1 -1
@@ -441,7 +441,7 @@ rt2500pci_config_channel(struct rt2x00_p txpower = (txpower >31 ) ?31 : txpower;if (rt2x00_rf (&rt2x00pci->chip,RF2525E ) && channel ==14 ) - rf4 |=0x00000010 ; + rf4 |=cpu_to_le32 (0x00000010 );if (rt2x00_rf (&rt2x00pci->chip,RF5222 )) {if (channel <14 ) {
drivers/net/wireless/d80211/rt2x00/rt2500usb.c +17 -18
@@ -324,20 +324,20 @@ rt2500usb_config_channel(struct rt2x00_uif (rt2x00_rf (&rt2x00usb->chip,RF5222 )) {if (channel <14 ) { - rf1 =cpu_to_le32 (0x00022020 ); - rf4 =cpu_to_le32 (0x00000a0b ); + rf1 =0x00022020 ; + rf4 =0x00000a0b ; }else if (channel ==14 ) { - rf1 =cpu_to_le32 (0x00022010 ); - rf4 =cpu_to_le32 (0x00000a1b ); + rf1 =0x00022010 ; + rf4 =0x00000a1b ; }else if (channel <64 ) { - rf1 =cpu_to_le32 (0x00022010 ); - rf4 =cpu_to_le32 (0x00000a1f ); + rf1 =0x00022010 ; + rf4 =0x00000a1f ; }else if (channel <140 ) { - rf1 =cpu_to_le32 (0x00022010 ); - rf4 =cpu_to_le32 (0x00000a0f ); + rf1 =0x00022010 ; + rf4 =0x00000a0f ; }else if (channel <161 ) { - rf1 =cpu_to_le32 (0x00022020 ); - rf4 =cpu_to_le32 (0x00000a07 ); + rf1 =0x00022020 ; + rf4 =0x00000a07 ; } }
@@ -1829,7 +1829,7 @@ rt2500usb_init_hw_channels(struct rt2x00 };for (counter =0 ; counter <ARRAY_SIZE (vals); counter++) - channels[counter].val =cpu_to_le32 (vals[counter]); + channels[counter].val = vals[counter]; }else if (rt2x00_rf (&rt2x00usb->chip,RF2523 ) ||rt2x00_rf (&rt2x00usb->chip,RF2524 ) ||rt2x00_rf (&rt2x00usb->chip,RF2525 )) {
@@ -1841,8 +1841,7 @@ rt2500usb_init_hw_channels(struct rt2x00 };for (counter =0 ; counter <ARRAY_SIZE (vals); counter++) - channels[counter].val = -cpu_to_le32 (vals[counter] | rf2_base); + channels[counter].val = vals[counter] | rf2_base; }else if (rt2x00_rf (&rt2x00usb->chip,RF2525E )) {u32 vals[] = { 0x0000089a, 0x0000089e, 0x0000089e, 0x000008a2,
@@ -1852,7 +1851,7 @@ rt2500usb_init_hw_channels(struct rt2x00 };for (counter =0 ; counter <ARRAY_SIZE (vals); counter++) - channels[counter].val =cpu_to_le32 (vals[counter]); + channels[counter].val = vals[counter]; }else if (rt2x00_rf (&rt2x00usb->chip,RF5222 )) {static u32 vals[] = { 0x00001136, 0x0000113a, 0x0000113e, 0x00001182,
@@ -1868,7 +1867,7 @@ rt2500usb_init_hw_channels(struct rt2x00 };for (counter =0 ; counter <ARRAY_SIZE (vals); counter++) - channels[counter].val =cpu_to_le32 (vals[counter]); + channels[counter].val = vals[counter]; }/*
@@ -1895,9 +1894,9 @@ rt2500usb_init_hw_channels(struct rt2x00*/ for (counter =0 ; counter <ARRAY_SIZE (rf); counter++) {if (rt2x00_rf (&rt2x00usb->chip, rf[counter].chip)) { - rt2x00usb->rf1 =cpu_to_le32 (rf[counter].val[0 ]); - rt2x00usb->rf3 =cpu_to_le32 (rf[counter].val[1 ]); - rt2x00usb->rf4 =cpu_to_le32 (rf[counter].val[2 ]); + rt2x00usb->rf1 = rf[counter].val[0 ]; + rt2x00usb->rf3 = rf[counter].val[1 ]; + rt2x00usb->rf4 = rf[counter].val[2 ]; } } }
Quoted 4 lines · Ivo van Doorn
From: Ivo van Doorn <[email protected]>
Fix various little/big endian conversions. rt2500pci should use
cpu_to_le32and rt2500usb should not.
While you're at it can you add __be* annotations to the hardware datastructures so the endianess handling can be verified using sparse?
Quoted 8 lines · Christoph Hellwig
Quoted 4 lines · Ivo van Doorn
From: Ivo van Doorn <[email protected]>
Fix various little/big endian conversions. rt2500pci should use
cpu_to_le32and rt2500usb should not.While you're at it can you add __be* annotations to the hardware datastructures so the endianess handling can be verified using sparse?
I am not sure if that would be a wise idea,
there is no byte ordering done in rt2500usb except for the EEPROM contents which is little endian.
So when the module is used on a normal x86 platform, there won't be any big endian structures or fields.
Quoted 5 lines · Ivo van Doorn
I am not sure if that would be a wise idea,
there is no byte ordering done in rt2500usb except for the EEPROM contents which is little endian.
So when the module is used on a normal x86 platform, there won't be any big endian structures or fields.
Well, then you'll need __le* annotation and the le*_to_cpu/cpu_to_le* instead. Any new driver should be endian clean.
Quoted 9 lines · Christoph Hellwig
Quoted 5 lines · Ivo van Doorn
I am not sure if that would be a wise idea,
there is no byte ordering done in rt2500usb except for the EEPROM contents which is little endian.
So when the module is used on a normal x86 platform, there won't be any big endian structures or fields.Well, then you'll need __le* annotation and the le*_to_cpu/cpu_to_le* instead. Any new driver should be endian clean.
Not exactly true for rt2570, to correctly operate with the device, no endian conversions should be made at all. Not to big endian and not
to little endian. The register should be send as a regular value with the byteordering equal to the byteordering of the currently used CPU.
It has been tested to send only little endian or big endian values to
the device on all CPU's, and in all cases it meant that the device would not function on CPU's with the other byte ordering.
Quoted 11 lines · you
Quoted 9 lines · Christoph Hellwig
Quoted 5 lines · Ivo van Doorn
I am not sure if that would be a wise idea,
there is no byte ordering done in rt2500usb except for the EEPROM contents which is little endian.
So when the module is used on a normal x86 platform, there won't be any big endian structures or fields.Well, then you'll need __le* annotation and the le*_to_cpu/cpu_to_le* instead. Any new driver should be endian clean.
Quoted 7 lines
Not exactly true for rt2570, to correctly operate with the device, no endian conversions should be made at all. Not to big endian and not
to little endian. The register should be send as a regular value with the byteordering equal to the byteordering of the currently used CPU.
It has been tested to send only little endian or big endian values to
the device on all CPU's, and in all cases it meant that the device would not function on CPU's with the other byte ordering.
I guess you are confusing something here:
MMIO access versus values in structs (for example) that are accessed through DMA (for example).
Signature · 1 line
Greetings Michael.
Quoted 20 lines · Michael Buesch
Quoted 11 lines · you
Quoted 9 lines · Christoph Hellwig
Quoted 5 lines · Ivo van Doorn
I am not sure if that would be a wise idea,
there is no byte ordering done in rt2500usb except for the EEPROM contents which is little endian.
So when the module is used on a normal x86 platform, there won't be any big endian structures or fields.Well, then you'll need __le* annotation and the le*_to_cpu/cpu_to_le* instead. Any new driver should be endian clean.
Quoted 7 lines
Not exactly true for rt2570, to correctly operate with the device, no endian conversions should be made at all. Not to big endian and not
to little endian. The register should be send as a regular value with the byteordering equal to the byteordering of the currently used CPU.
It has been tested to send only little endian or big endian values to
the device on all CPU's, and in all cases it meant that the device would not function on CPU's with the other byte ordering.
Quoted 3 lines
I guess you are confusing something here:
MMIO access versus values in structs (for example) that are accessed through DMA (for example).
Ah ok. I was indeed missing that point.
In that case you are right, there could be some places where the __le* annotation could be used.
I'll create a quick patch to do that.
Quoted 3 lines · Michael Buesch
I guess you are confusing something here:
MMIO access versus values in structs (for example) that are accessed through DMA (for example).
so there's two general problems:
mmio/pio - linux expects the device to be le there by defalt and
{read,write}{b,s,l} do the switch automatically
dmaed data - you always need to switch data yourself, data is commonly
either be or le
now there's devices that are always be for mmio or can be switched to it during initialization. For Linux you'd traditionally have to switch before calling {read,write}{b,s,l} or use the __raw_ version that have other issues. The ioread*/iowrite* APIs now have a BE version, too.
I've not heard about devices having this switch for dma payload, and it would be rather usual as large parts of it are determined by some on the wire protocol anyway.
Quoted 3 lines
Signature · 2 lines
-- Greetings Michael.
---end quoted text---
Quoted 12 lines · you
Quoted 3 lines · Michael Buesch
I guess you are confusing something here:
MMIO access versus values in structs (for example) that are accessed through DMA (for example).so there's two general problems:
mmio/pio - linux expects the device to be le there by defalt and
{read,write}{b,s,l} do the switch automatically
dmaed data - you always need to switch data yourself, data is commonly
either be or le
Quoted 8 lines
now there's devices that are always be for mmio or can be switched to it during initialization. For Linux you'd traditionally have to switch before calling {read,write}{b,s,l} or use the
__raw_version that have other issues. The ioread*/iowrite* APIs now have a BE version, too.I've not heard about devices having this switch for dma payload, and it would be rather usual as large parts of it are determined by some on the wire protocol anyway.
bcm43xx has a switch for this in PIO mode.
But we are currently not using it, because it is a little bit tricky to get right and I did not want to do such experiments before 2.6.17.
Signature · 1 line
Greetings Michael.
Quoted 12 lines · Christoph Hellwig
Quoted 3 lines · Michael Buesch
I guess you are confusing something here:
MMIO access versus values in structs (for example) that are accessed through DMA (for example).so there's two general problems:
mmio/pio - linux expects the device to be le there by defalt and
{read,write}{b,s,l} do the switch automatically
dmaed data - you always need to switch data yourself, data is commonly
either be or le
Quoted 4 lines
now there's devices that are always be for mmio or can be switched to it during initialization. For Linux you'd traditionally have to switch before calling {read,write}{b,s,l} or use the
__raw_version that have other issues. The ioread*/iowrite* APIs now have a BE version, too.
Unless I am mistaken, or the ralink design sheets are outdated on that issue, I do recall that there was a big endian switch in one of the registers. I think I need to definately investigate that to see if it would be usefull. :)
Thanks,
Ivo