Re: [PATCH 13/17] staging: wfx: fix endianness of the field 'len'

2020-05-12 Thread Jérôme Pouiller
On Tuesday 12 May 2020 09:43:34 CEST Geert Uytterhoeven wrote:
> Hi Jerome,
> 
> On Mon, May 11, 2020 at 5:53 PM Jerome Pouiller
>  wrote:
> > From: Jérôme Pouiller 
> >
> > The struct hif_msg is received from the hardware. So, it declared as
> > little endian. However, it is also accessed from many places in the
> > driver. Sparse complains about that:
> >
> > drivers/staging/wfx/bh.c:88:32: warning: restricted __le16 degrades to 
> > integer
> > drivers/staging/wfx/bh.c:88:32: warning: restricted __le16 degrades to 
> > integer
> > drivers/staging/wfx/bh.c:93:32: warning: restricted __le16 degrades to 
> > integer
> > drivers/staging/wfx/bh.c:93:32: warning: cast to restricted __le16
> > drivers/staging/wfx/bh.c:93:32: warning: restricted __le16 degrades to 
> > integer
> > drivers/staging/wfx/bh.c:121:25: warning: incorrect type in argument 2 
> > (different base types)
> > drivers/staging/wfx/bh.c:121:25:expected unsigned int len
> > drivers/staging/wfx/bh.c:121:25:got restricted __le16 [usertype] len
> > drivers/staging/wfx/hif_rx.c:27:22: warning: restricted __le16 degrades 
> > to integer
> > drivers/staging/wfx/hif_rx.c:347:39: warning: incorrect type in 
> > argument 7 (different base types)
> > drivers/staging/wfx/hif_rx.c:347:39:expected unsigned int 
> > [usertype] len
> > drivers/staging/wfx/hif_rx.c:347:39:got restricted __le16 const 
> > [usertype] len
> > drivers/staging/wfx/hif_rx.c:365:39: warning: incorrect type in 
> > argument 7 (different base types)
> > drivers/staging/wfx/hif_rx.c:365:39:expected unsigned int 
> > [usertype] len
> > drivers/staging/wfx/hif_rx.c:365:39:got restricted __le16 const 
> > [usertype] len
> > drivers/staging/wfx/./traces.h:195:1: warning: incorrect type in 
> > assignment (different base types)
> > drivers/staging/wfx/./traces.h:195:1:expected int msg_len
> > drivers/staging/wfx/./traces.h:195:1:got restricted __le16 const 
> > [usertype] len
> > drivers/staging/wfx/./traces.h:195:1: warning: incorrect type in 
> > assignment (different base types)
> > drivers/staging/wfx/./traces.h:195:1:expected int msg_len
> > drivers/staging/wfx/./traces.h:195:1:got restricted __le16 const 
> > [usertype] len
> > drivers/staging/wfx/debug.c:319:20: warning: restricted __le16 degrades 
> > to integer
> > drivers/staging/wfx/secure_link.c:85:27: warning: restricted __le16 
> > degrades to integer
> > drivers/staging/wfx/secure_link.c:85:27: warning: restricted __le16 
> > degrades to integer
> 
> Thanks for your patch!
> 
> > In order to make Sparse happy and to keep access from the driver easy,
> > this patch declare 'len' with native endianness.
> >
> > On reception of hardware data, this patch takes care to do byte-swap and
> > keep Sparse happy.
> 
> Which means sparse can no longer do any checking on the field,
> and new bugs may/will creep in in the future, unnoticed.
> 
> > --- a/drivers/staging/wfx/hif_api_general.h
> > +++ b/drivers/staging/wfx/hif_api_general.h
> > @@ -23,7 +23,10 @@
> >  #define HIF_COUNTER_MAX   7
> >
> >  struct hif_msg {
> > -   __le16 len;
> > +   // len is in fact little endian. However, it is widely used in the
> > +   // driver, so we declare it in native byte order and we reorder just
> > +   // before/after send/receive it (see bh.c).
> > +   u16len;
> 
> While there's a small penalty associated with always doing the conversion
> on big-endian platforms, it will probably be lost in the noise anyway.

I have made the changes to show you that the code is far more complicated
with a le16... and the result was not as complicated as I expected...

I am going to post a v2.


-- 
Jérôme Pouiller




Re: [PATCH 13/17] staging: wfx: fix endianness of the field 'len'

2020-05-12 Thread Geert Uytterhoeven
Hi Jerome,

On Mon, May 11, 2020 at 5:53 PM Jerome Pouiller
 wrote:
> From: Jérôme Pouiller 
>
> The struct hif_msg is received from the hardware. So, it declared as
> little endian. However, it is also accessed from many places in the
> driver. Sparse complains about that:
>
> drivers/staging/wfx/bh.c:88:32: warning: restricted __le16 degrades to 
> integer
> drivers/staging/wfx/bh.c:88:32: warning: restricted __le16 degrades to 
> integer
> drivers/staging/wfx/bh.c:93:32: warning: restricted __le16 degrades to 
> integer
> drivers/staging/wfx/bh.c:93:32: warning: cast to restricted __le16
> drivers/staging/wfx/bh.c:93:32: warning: restricted __le16 degrades to 
> integer
> drivers/staging/wfx/bh.c:121:25: warning: incorrect type in argument 2 
> (different base types)
> drivers/staging/wfx/bh.c:121:25:expected unsigned int len
> drivers/staging/wfx/bh.c:121:25:got restricted __le16 [usertype] len
> drivers/staging/wfx/hif_rx.c:27:22: warning: restricted __le16 degrades 
> to integer
> drivers/staging/wfx/hif_rx.c:347:39: warning: incorrect type in argument 
> 7 (different base types)
> drivers/staging/wfx/hif_rx.c:347:39:expected unsigned int [usertype] 
> len
> drivers/staging/wfx/hif_rx.c:347:39:got restricted __le16 const 
> [usertype] len
> drivers/staging/wfx/hif_rx.c:365:39: warning: incorrect type in argument 
> 7 (different base types)
> drivers/staging/wfx/hif_rx.c:365:39:expected unsigned int [usertype] 
> len
> drivers/staging/wfx/hif_rx.c:365:39:got restricted __le16 const 
> [usertype] len
> drivers/staging/wfx/./traces.h:195:1: warning: incorrect type in 
> assignment (different base types)
> drivers/staging/wfx/./traces.h:195:1:expected int msg_len
> drivers/staging/wfx/./traces.h:195:1:got restricted __le16 const 
> [usertype] len
> drivers/staging/wfx/./traces.h:195:1: warning: incorrect type in 
> assignment (different base types)
> drivers/staging/wfx/./traces.h:195:1:expected int msg_len
> drivers/staging/wfx/./traces.h:195:1:got restricted __le16 const 
> [usertype] len
> drivers/staging/wfx/debug.c:319:20: warning: restricted __le16 degrades 
> to integer
> drivers/staging/wfx/secure_link.c:85:27: warning: restricted __le16 
> degrades to integer
> drivers/staging/wfx/secure_link.c:85:27: warning: restricted __le16 
> degrades to integer

Thanks for your patch!

> In order to make Sparse happy and to keep access from the driver easy,
> this patch declare 'len' with native endianness.
>
> On reception of hardware data, this patch takes care to do byte-swap and
> keep Sparse happy.

Which means sparse can no longer do any checking on the field,
and new bugs may/will creep in in the future, unnoticed.

> --- a/drivers/staging/wfx/hif_api_general.h
> +++ b/drivers/staging/wfx/hif_api_general.h
> @@ -23,7 +23,10 @@
>  #define HIF_COUNTER_MAX   7
>
>  struct hif_msg {
> -   __le16 len;
> +   // len is in fact little endian. However, it is widely used in the
> +   // driver, so we declare it in native byte order and we reorder just
> +   // before/after send/receive it (see bh.c).
> +   u16len;

While there's a small penalty associated with always doing the conversion
on big-endian platforms, it will probably be lost in the noise anyway.

Gr{oetje,eeting}s,

Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


Re: [PATCH 13/17] staging: wfx: fix endianness of the field 'len'

2020-05-11 Thread kbuild test robot
Hi Jerome,

I love your patch! Perhaps something to improve:

[auto build test WARNING on staging/staging-testing]
[also build test WARNING on next-20200511]
[cannot apply to v5.7-rc5]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:
https://github.com/0day-ci/linux/commits/Jerome-Pouiller/staging-wfx-fix-support-for-big-endian-hosts/20200512-031750
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git 
ae73e7784871ebe2c43da619b4a1e2c9ff81508d
config: m68k-allmodconfig (attached as .config)
compiler: m68k-linux-gcc (GCC) 9.3.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day GCC_VERSION=9.3.0 make.cross ARCH=m68k 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot 

All warnings (new ones prefixed by >>):

   In file included from include/linux/byteorder/big_endian.h:5,
from arch/m68k/include/uapi/asm/byteorder.h:5,
from include/asm-generic/bitops/le.h:6,
from arch/m68k/include/asm/bitops.h:528,
from include/linux/bitops.h:29,
from include/linux/kernel.h:12,
from include/asm-generic/bug.h:19,
from arch/m68k/include/asm/bug.h:32,
from include/linux/bug.h:5,
from include/linux/gpio/consumer.h:6,
from drivers/staging/wfx/bh.c:8:
   drivers/staging/wfx/bh.c: In function 'tx_helper':
>> drivers/staging/wfx/bh.c:202:39: warning: passing argument 1 of '__swab16s' 
>> makes pointer from integer without a cast [-Wint-conversion]
 202 |  cpu_to_le16s(((struct hif_msg *)data)->len);
   include/uapi/linux/byteorder/big_endian.h:96:38: note: in definition of 
macro '__cpu_to_le16s'
  96 | #define __cpu_to_le16s(x) __swab16s((x))
 |  ^
>> drivers/staging/wfx/bh.c:202:2: note: in expansion of macro 'cpu_to_le16s'
 202 |  cpu_to_le16s(((struct hif_msg *)data)->len);
 |  ^~~~
   In file included from include/linux/swab.h:5,
from include/uapi/linux/byteorder/big_endian.h:13,
from include/linux/byteorder/big_endian.h:5,
from arch/m68k/include/uapi/asm/byteorder.h:5,
from include/asm-generic/bitops/le.h:6,
from arch/m68k/include/asm/bitops.h:528,
from include/linux/bitops.h:29,
from include/linux/kernel.h:12,
from include/asm-generic/bug.h:19,
from arch/m68k/include/asm/bug.h:32,
from include/linux/bug.h:5,
from include/linux/gpio/consumer.h:6,
from drivers/staging/wfx/bh.c:8:
   include/uapi/linux/swab.h:240:37: note: expected '__u16 *' {aka 'short 
unsigned int *'} but argument is of type 'u16' {aka 'short unsigned int'}
 240 | static inline void __swab16s(__u16 *p)
 |  ~~~^

vim +/__swab16s +202 drivers/staging/wfx/bh.c

   169  
   170  static void tx_helper(struct wfx_dev *wdev, struct hif_msg *hif)
   171  {
   172  int ret;
   173  void *data;
   174  bool is_encrypted = false;
   175  size_t len = hif->len;
   176  
   177  WARN(len < sizeof(*hif), "try to send corrupted data");
   178  
   179  hif->seqnum = wdev->hif.tx_seqnum;
   180  wdev->hif.tx_seqnum = (wdev->hif.tx_seqnum + 1) % 
(HIF_COUNTER_MAX + 1);
   181  
   182  if (wfx_is_secure_command(wdev, hif->id)) {
   183  len = round_up(len - sizeof(hif->len), 16) + 
sizeof(hif->len) +
   184  sizeof(struct hif_sl_msg_hdr) +
   185  sizeof(struct hif_sl_tag);
   186  // AES support encryption in-place. However, mac80211 
access to
   187  // 802.11 header after frame was sent (to get MAC 
addresses).
   188  // So, keep origin buffer clear.
   189  data = kmalloc(len, GFP_KERNEL);
   190  if (!data)
   191  goto end;
   192  is_encrypted = true;
   193  ret = wfx_sl_encode(wdev, hif, data);
   194  if (ret)
   195  goto end;
   196  } else {
   197  data = hif;
   198  }
   199  WARN(len > wdev->hw_caps.size_inp_ch_buf,
   200   "%s: request exceed WFx capability: %zu > %d\n", __func__,
   201   len, 

[PATCH 13/17] staging: wfx: fix endianness of the field 'len'

2020-05-11 Thread Jerome Pouiller
From: Jérôme Pouiller 

The struct hif_msg is received from the hardware. So, it declared as
little endian. However, it is also accessed from many places in the
driver. Sparse complains about that:

drivers/staging/wfx/bh.c:88:32: warning: restricted __le16 degrades to 
integer
drivers/staging/wfx/bh.c:88:32: warning: restricted __le16 degrades to 
integer
drivers/staging/wfx/bh.c:93:32: warning: restricted __le16 degrades to 
integer
drivers/staging/wfx/bh.c:93:32: warning: cast to restricted __le16
drivers/staging/wfx/bh.c:93:32: warning: restricted __le16 degrades to 
integer
drivers/staging/wfx/bh.c:121:25: warning: incorrect type in argument 2 
(different base types)
drivers/staging/wfx/bh.c:121:25:expected unsigned int len
drivers/staging/wfx/bh.c:121:25:got restricted __le16 [usertype] len
drivers/staging/wfx/hif_rx.c:27:22: warning: restricted __le16 degrades to 
integer
drivers/staging/wfx/hif_rx.c:347:39: warning: incorrect type in argument 7 
(different base types)
drivers/staging/wfx/hif_rx.c:347:39:expected unsigned int [usertype] len
drivers/staging/wfx/hif_rx.c:347:39:got restricted __le16 const 
[usertype] len
drivers/staging/wfx/hif_rx.c:365:39: warning: incorrect type in argument 7 
(different base types)
drivers/staging/wfx/hif_rx.c:365:39:expected unsigned int [usertype] len
drivers/staging/wfx/hif_rx.c:365:39:got restricted __le16 const 
[usertype] len
drivers/staging/wfx/./traces.h:195:1: warning: incorrect type in assignment 
(different base types)
drivers/staging/wfx/./traces.h:195:1:expected int msg_len
drivers/staging/wfx/./traces.h:195:1:got restricted __le16 const 
[usertype] len
drivers/staging/wfx/./traces.h:195:1: warning: incorrect type in assignment 
(different base types)
drivers/staging/wfx/./traces.h:195:1:expected int msg_len
drivers/staging/wfx/./traces.h:195:1:got restricted __le16 const 
[usertype] len
drivers/staging/wfx/debug.c:319:20: warning: restricted __le16 degrades to 
integer
drivers/staging/wfx/secure_link.c:85:27: warning: restricted __le16 
degrades to integer
drivers/staging/wfx/secure_link.c:85:27: warning: restricted __le16 
degrades to integer

In order to make Sparse happy and to keep access from the driver easy,
this patch declare 'len' with native endianness.

On reception of hardware data, this patch takes care to do byte-swap and
keep Sparse happy.

Signed-off-by: Jérôme Pouiller 
---
 drivers/staging/wfx/bh.c  | 7 ---
 drivers/staging/wfx/data_tx.c | 2 +-
 drivers/staging/wfx/hif_api_general.h | 8 ++--
 drivers/staging/wfx/hif_tx.c  | 2 +-
 4 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/wfx/bh.c b/drivers/staging/wfx/bh.c
index 55724e4295c4..0355b1a1c4bb 100644
--- a/drivers/staging/wfx/bh.c
+++ b/drivers/staging/wfx/bh.c
@@ -74,6 +74,7 @@ static int rx_helper(struct wfx_dev *wdev, size_t read_len, 
int *is_cnf)
_trace_piggyback(piggyback, false);
 
hif = (struct hif_msg *)skb->data;
+   le16_to_cpus((__le16 *)>len);
WARN(hif->encrypted & 0x1, "unsupported encryption type");
if (hif->encrypted == 0x2) {
if (wfx_sl_decode(wdev, (void *)hif)) {
@@ -84,12 +85,11 @@ static int rx_helper(struct wfx_dev *wdev, size_t read_len, 
int *is_cnf)
// piggyback is probably correct.
return piggyback;
}
-   le16_to_cpus(>len);
+   le16_to_cpus((__le16 *)>len);
computed_len = round_up(hif->len - sizeof(hif->len), 16)
   + sizeof(struct hif_sl_msg)
   + sizeof(struct hif_sl_tag);
} else {
-   le16_to_cpus(>len);
computed_len = round_up(hif->len, 2);
}
if (computed_len != read_len) {
@@ -172,7 +172,7 @@ static void tx_helper(struct wfx_dev *wdev, struct hif_msg 
*hif)
int ret;
void *data;
bool is_encrypted = false;
-   size_t len = le16_to_cpu(hif->len);
+   size_t len = hif->len;
 
WARN(len < sizeof(*hif), "try to send corrupted data");
 
@@ -199,6 +199,7 @@ static void tx_helper(struct wfx_dev *wdev, struct hif_msg 
*hif)
WARN(len > wdev->hw_caps.size_inp_ch_buf,
 "%s: request exceed WFx capability: %zu > %d\n", __func__,
 len, wdev->hw_caps.size_inp_ch_buf);
+   cpu_to_le16s(((struct hif_msg *)data)->len);
len = wdev->hwbus_ops->align_size(wdev->hwbus_priv, len);
ret = wfx_data_write(wdev, data, len);
if (ret)
diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c
index 014fa36c8f78..84656d1a6278 100644
--- a/drivers/staging/wfx/data_tx.c
+++ b/drivers/staging/wfx/data_tx.c
@@ -384,7 +384,7 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct 
ieee80211_sta *sta,