From: Rafał Miłecki Date: Wed, 21 Mar 2018 07:35:58 +0000 (+0100) Subject: mac80211: backport brcmfmac fixes from 4.16 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=0f1a1489a6c584d7de6680a65b457acf328818bd;p=openwrt%2Fstaging%2Fmans0n.git mac80211: backport brcmfmac fixes from 4.16 Signed-off-by: Rafał Miłecki --- diff --git a/package/kernel/mac80211/patches/312-v4.16-0006-brcmfmac-Remove-brcmf_sdiod_addrprep.patch b/package/kernel/mac80211/patches/312-v4.16-0006-brcmfmac-Remove-brcmf_sdiod_addrprep.patch index 3c78af89d8..44303fa410 100644 --- a/package/kernel/mac80211/patches/312-v4.16-0006-brcmfmac-Remove-brcmf_sdiod_addrprep.patch +++ b/package/kernel/mac80211/patches/312-v4.16-0006-brcmfmac-Remove-brcmf_sdiod_addrprep.patch @@ -71,7 +71,7 @@ Signed-off-by: Kalle Valo } u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) -@@ -272,11 +256,16 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) +@@ -272,11 +256,16 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_ u32 data = 0; int retval; @@ -111,7 +111,7 @@ Signed-off-by: Kalle Valo if (ret) *ret = retval; } -@@ -540,10 +534,13 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt) +@@ -540,10 +534,13 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len); diff --git a/package/kernel/mac80211/patches/321-v4.16-0001-brcmfmac-assure-bcdc-dcmd-api-does-not-return-value-.patch b/package/kernel/mac80211/patches/321-v4.16-0001-brcmfmac-assure-bcdc-dcmd-api-does-not-return-value-.patch new file mode 100644 index 0000000000..394fbfc5b2 --- /dev/null +++ b/package/kernel/mac80211/patches/321-v4.16-0001-brcmfmac-assure-bcdc-dcmd-api-does-not-return-value-.patch @@ -0,0 +1,68 @@ +From 5242a5444e0b6464d7455beb55d936dd192b5e9d Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Mon, 22 Jan 2018 21:46:39 +0100 +Subject: [PATCH] brcmfmac: assure bcdc dcmd api does not return value > 0 + +The protocol layer api defines callbacks for dongle commands. +Although not really well documented these should only return an +error code in case of an error, or 0 upon success. In the bcdc +protocol it can return value above 0 and we carry a fix in the +caller of the protocol layer api. This patch makes it adhere to +the intent of the api as described above. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 6 +++++- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 8 +++----- + 2 files changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +@@ -211,6 +211,8 @@ retry: + memcpy(buf, info, len); + } + ++ ret = 0; ++ + /* Check the ERROR flag */ + if (flags & BCDC_DCMD_ERROR) + ret = le32_to_cpu(msg->status); +@@ -225,7 +227,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p + { + struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; + struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; +- int ret = 0; ++ int ret; + u32 flags, id; + + brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); +@@ -249,6 +251,8 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p + goto done; + } + ++ ret = 0; ++ + /* Check the ERROR flag */ + if (flags & BCDC_DCMD_ERROR) + ret = le32_to_cpu(msg->status); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +@@ -121,11 +121,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, + else + err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); + +- if (err >= 0) +- return 0; +- +- brcmf_dbg(FIL, "Failed: %s (%d)\n", +- brcmf_fil_get_errstr((u32)(-err)), err); ++ if (err) ++ brcmf_dbg(FIL, "Failed: %s (%d)\n", ++ brcmf_fil_get_errstr((u32)(-err)), err); + + return err; + } diff --git a/package/kernel/mac80211/patches/321-v4.16-0002-brcmfmac-separate-firmware-errors-from-i-o-errors.patch b/package/kernel/mac80211/patches/321-v4.16-0002-brcmfmac-separate-firmware-errors-from-i-o-errors.patch new file mode 100644 index 0000000000..28e3c1a65f --- /dev/null +++ b/package/kernel/mac80211/patches/321-v4.16-0002-brcmfmac-separate-firmware-errors-from-i-o-errors.patch @@ -0,0 +1,186 @@ +From b69c1df47281ad47bd2037a42b98f5c7115b7fd5 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Mon, 22 Jan 2018 21:46:40 +0100 +Subject: [PATCH] brcmfmac: separate firmware errors from i/o errors + +When using the firmware api it can fail simply because firmware does +not like the request or it fails due to issues in the host interface. +Currently, there is only a single error code which is confusing. So +adding a parameter to pass the firmware error separately and in case +of a firmware error always return -EBADE to user-space. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 11 ++++++----- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 16 +++++++++++----- + .../net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 10 ++++++---- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h | 14 ++++++++------ + 4 files changed, 31 insertions(+), 20 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +@@ -165,7 +165,7 @@ static int brcmf_proto_bcdc_cmplt(struct + + static int + brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, +- void *buf, uint len) ++ void *buf, uint len, int *fwerr) + { + struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; + struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; +@@ -175,6 +175,7 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf + + brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); + ++ *fwerr = 0; + ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false); + if (ret < 0) { + brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n", +@@ -215,15 +216,14 @@ retry: + + /* Check the ERROR flag */ + if (flags & BCDC_DCMD_ERROR) +- ret = le32_to_cpu(msg->status); +- ++ *fwerr = le32_to_cpu(msg->status); + done: + return ret; + } + + static int + brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, +- void *buf, uint len) ++ void *buf, uint len, int *fwerr) + { + struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; + struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; +@@ -232,6 +232,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p + + brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); + ++ *fwerr = 0; + ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true); + if (ret < 0) + goto done; +@@ -255,7 +256,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p + + /* Check the ERROR flag */ + if (flags & BCDC_DCMD_ERROR) +- ret = le32_to_cpu(msg->status); ++ *fwerr = le32_to_cpu(msg->status); + + done: + return ret; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +@@ -107,7 +107,7 @@ static s32 + brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) + { + struct brcmf_pub *drvr = ifp->drvr; +- s32 err; ++ s32 err, fwerr; + + if (drvr->bus_if->state != BRCMF_BUS_UP) { + brcmf_err("bus is down. we have nothing to do.\n"); +@@ -117,14 +117,20 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, + if (data != NULL) + len = min_t(uint, len, BRCMF_DCMD_MAXLEN); + if (set) +- err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len); ++ err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, ++ data, len, &fwerr); + else +- err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); ++ err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, ++ data, len, &fwerr); + +- if (err) ++ if (err) { + brcmf_dbg(FIL, "Failed: %s (%d)\n", + brcmf_fil_get_errstr((u32)(-err)), err); +- ++ } else if (fwerr < 0) { ++ brcmf_dbg(FIL, "Firmware error: %s (%d)\n", ++ brcmf_fil_get_errstr((u32)(-fwerr)), fwerr); ++ err = -EBADE; ++ } + return err; + } + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +@@ -477,7 +477,7 @@ static void brcmf_msgbuf_ioctl_resp_wake + + + static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx, +- uint cmd, void *buf, uint len) ++ uint cmd, void *buf, uint len, int *fwerr) + { + struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; + struct sk_buff *skb = NULL; +@@ -485,6 +485,7 @@ static int brcmf_msgbuf_query_dcmd(struc + int err; + + brcmf_dbg(MSGBUF, "ifidx=%d, cmd=%d, len=%d\n", ifidx, cmd, len); ++ *fwerr = 0; + msgbuf->ctl_completed = false; + err = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len); + if (err) +@@ -508,14 +509,15 @@ static int brcmf_msgbuf_query_dcmd(struc + } + brcmu_pkt_buf_free_skb(skb); + +- return msgbuf->ioctl_resp_status; ++ *fwerr = msgbuf->ioctl_resp_status; ++ return 0; + } + + + static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx, +- uint cmd, void *buf, uint len) ++ uint cmd, void *buf, uint len, int *fwerr) + { +- return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len); ++ return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len, fwerr); + } + + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h +@@ -30,9 +30,9 @@ struct brcmf_proto { + int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, + struct sk_buff *skb, struct brcmf_if **ifp); + int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, +- void *buf, uint len); ++ void *buf, uint len, int *fwerr); + int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, +- uint len); ++ uint len, int *fwerr); + int (*tx_queue_data)(struct brcmf_pub *drvr, int ifidx, + struct sk_buff *skb); + int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset, +@@ -71,14 +71,16 @@ static inline int brcmf_proto_hdrpull(st + return drvr->proto->hdrpull(drvr, do_fws, skb, ifp); + } + static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx, +- uint cmd, void *buf, uint len) ++ uint cmd, void *buf, uint len, ++ int *fwerr) + { +- return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len); ++ return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len,fwerr); + } + static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx, +- uint cmd, void *buf, uint len) ++ uint cmd, void *buf, uint len, ++ int *fwerr) + { +- return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len); ++ return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len, fwerr); + } + + static inline int brcmf_proto_tx_queue_data(struct brcmf_pub *drvr, int ifidx, diff --git a/package/kernel/mac80211/patches/321-v4.17-0001-brcmfmac-assure-bcdc-dcmd-api-does-not-return-value-.patch b/package/kernel/mac80211/patches/321-v4.17-0001-brcmfmac-assure-bcdc-dcmd-api-does-not-return-value-.patch deleted file mode 100644 index 394fbfc5b2..0000000000 --- a/package/kernel/mac80211/patches/321-v4.17-0001-brcmfmac-assure-bcdc-dcmd-api-does-not-return-value-.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 5242a5444e0b6464d7455beb55d936dd192b5e9d Mon Sep 17 00:00:00 2001 -From: Arend Van Spriel -Date: Mon, 22 Jan 2018 21:46:39 +0100 -Subject: [PATCH] brcmfmac: assure bcdc dcmd api does not return value > 0 - -The protocol layer api defines callbacks for dongle commands. -Although not really well documented these should only return an -error code in case of an error, or 0 upon success. In the bcdc -protocol it can return value above 0 and we carry a fix in the -caller of the protocol layer api. This patch makes it adhere to -the intent of the api as described above. - -Reviewed-by: Hante Meuleman -Reviewed-by: Pieter-Paul Giesberts -Reviewed-by: Franky Lin -Signed-off-by: Arend van Spriel -Signed-off-by: Kalle Valo ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 6 +++++- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 8 +++----- - 2 files changed, 8 insertions(+), 6 deletions(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c -@@ -211,6 +211,8 @@ retry: - memcpy(buf, info, len); - } - -+ ret = 0; -+ - /* Check the ERROR flag */ - if (flags & BCDC_DCMD_ERROR) - ret = le32_to_cpu(msg->status); -@@ -225,7 +227,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p - { - struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; - struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; -- int ret = 0; -+ int ret; - u32 flags, id; - - brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); -@@ -249,6 +251,8 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p - goto done; - } - -+ ret = 0; -+ - /* Check the ERROR flag */ - if (flags & BCDC_DCMD_ERROR) - ret = le32_to_cpu(msg->status); ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c -@@ -121,11 +121,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, - else - err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); - -- if (err >= 0) -- return 0; -- -- brcmf_dbg(FIL, "Failed: %s (%d)\n", -- brcmf_fil_get_errstr((u32)(-err)), err); -+ if (err) -+ brcmf_dbg(FIL, "Failed: %s (%d)\n", -+ brcmf_fil_get_errstr((u32)(-err)), err); - - return err; - } diff --git a/package/kernel/mac80211/patches/321-v4.17-0002-brcmfmac-separate-firmware-errors-from-i-o-errors.patch b/package/kernel/mac80211/patches/321-v4.17-0002-brcmfmac-separate-firmware-errors-from-i-o-errors.patch deleted file mode 100644 index 28e3c1a65f..0000000000 --- a/package/kernel/mac80211/patches/321-v4.17-0002-brcmfmac-separate-firmware-errors-from-i-o-errors.patch +++ /dev/null @@ -1,186 +0,0 @@ -From b69c1df47281ad47bd2037a42b98f5c7115b7fd5 Mon Sep 17 00:00:00 2001 -From: Arend Van Spriel -Date: Mon, 22 Jan 2018 21:46:40 +0100 -Subject: [PATCH] brcmfmac: separate firmware errors from i/o errors - -When using the firmware api it can fail simply because firmware does -not like the request or it fails due to issues in the host interface. -Currently, there is only a single error code which is confusing. So -adding a parameter to pass the firmware error separately and in case -of a firmware error always return -EBADE to user-space. - -Reviewed-by: Hante Meuleman -Reviewed-by: Pieter-Paul Giesberts -Reviewed-by: Franky Lin -Signed-off-by: Arend van Spriel -Signed-off-by: Kalle Valo ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 11 ++++++----- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 16 +++++++++++----- - .../net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 10 ++++++---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h | 14 ++++++++------ - 4 files changed, 31 insertions(+), 20 deletions(-) - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c -@@ -165,7 +165,7 @@ static int brcmf_proto_bcdc_cmplt(struct - - static int - brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, -- void *buf, uint len) -+ void *buf, uint len, int *fwerr) - { - struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; - struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; -@@ -175,6 +175,7 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf - - brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); - -+ *fwerr = 0; - ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false); - if (ret < 0) { - brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n", -@@ -215,15 +216,14 @@ retry: - - /* Check the ERROR flag */ - if (flags & BCDC_DCMD_ERROR) -- ret = le32_to_cpu(msg->status); -- -+ *fwerr = le32_to_cpu(msg->status); - done: - return ret; - } - - static int - brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, -- void *buf, uint len) -+ void *buf, uint len, int *fwerr) - { - struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd; - struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg; -@@ -232,6 +232,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p - - brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len); - -+ *fwerr = 0; - ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true); - if (ret < 0) - goto done; -@@ -255,7 +256,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p - - /* Check the ERROR flag */ - if (flags & BCDC_DCMD_ERROR) -- ret = le32_to_cpu(msg->status); -+ *fwerr = le32_to_cpu(msg->status); - - done: - return ret; ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c -@@ -107,7 +107,7 @@ static s32 - brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) - { - struct brcmf_pub *drvr = ifp->drvr; -- s32 err; -+ s32 err, fwerr; - - if (drvr->bus_if->state != BRCMF_BUS_UP) { - brcmf_err("bus is down. we have nothing to do.\n"); -@@ -117,14 +117,20 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, - if (data != NULL) - len = min_t(uint, len, BRCMF_DCMD_MAXLEN); - if (set) -- err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len); -+ err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, -+ data, len, &fwerr); - else -- err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); -+ err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, -+ data, len, &fwerr); - -- if (err) -+ if (err) { - brcmf_dbg(FIL, "Failed: %s (%d)\n", - brcmf_fil_get_errstr((u32)(-err)), err); -- -+ } else if (fwerr < 0) { -+ brcmf_dbg(FIL, "Firmware error: %s (%d)\n", -+ brcmf_fil_get_errstr((u32)(-fwerr)), fwerr); -+ err = -EBADE; -+ } - return err; - } - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c -@@ -477,7 +477,7 @@ static void brcmf_msgbuf_ioctl_resp_wake - - - static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx, -- uint cmd, void *buf, uint len) -+ uint cmd, void *buf, uint len, int *fwerr) - { - struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; - struct sk_buff *skb = NULL; -@@ -485,6 +485,7 @@ static int brcmf_msgbuf_query_dcmd(struc - int err; - - brcmf_dbg(MSGBUF, "ifidx=%d, cmd=%d, len=%d\n", ifidx, cmd, len); -+ *fwerr = 0; - msgbuf->ctl_completed = false; - err = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len); - if (err) -@@ -508,14 +509,15 @@ static int brcmf_msgbuf_query_dcmd(struc - } - brcmu_pkt_buf_free_skb(skb); - -- return msgbuf->ioctl_resp_status; -+ *fwerr = msgbuf->ioctl_resp_status; -+ return 0; - } - - - static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx, -- uint cmd, void *buf, uint len) -+ uint cmd, void *buf, uint len, int *fwerr) - { -- return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len); -+ return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len, fwerr); - } - - ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h -@@ -30,9 +30,9 @@ struct brcmf_proto { - int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, - struct sk_buff *skb, struct brcmf_if **ifp); - int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, -- void *buf, uint len); -+ void *buf, uint len, int *fwerr); - int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, -- uint len); -+ uint len, int *fwerr); - int (*tx_queue_data)(struct brcmf_pub *drvr, int ifidx, - struct sk_buff *skb); - int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset, -@@ -71,14 +71,16 @@ static inline int brcmf_proto_hdrpull(st - return drvr->proto->hdrpull(drvr, do_fws, skb, ifp); - } - static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx, -- uint cmd, void *buf, uint len) -+ uint cmd, void *buf, uint len, -+ int *fwerr) - { -- return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len); -+ return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len,fwerr); - } - static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx, -- uint cmd, void *buf, uint len) -+ uint cmd, void *buf, uint len, -+ int *fwerr) - { -- return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len); -+ return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len, fwerr); - } - - static inline int brcmf_proto_tx_queue_data(struct brcmf_pub *drvr, int ifidx, diff --git a/package/kernel/mac80211/patches/322-v4.16-0001-brcmfmac-add-possibility-to-obtain-firmware-error.patch b/package/kernel/mac80211/patches/322-v4.16-0001-brcmfmac-add-possibility-to-obtain-firmware-error.patch new file mode 100644 index 0000000000..e6486160fc --- /dev/null +++ b/package/kernel/mac80211/patches/322-v4.16-0001-brcmfmac-add-possibility-to-obtain-firmware-error.patch @@ -0,0 +1,92 @@ +From 933897342d0714ae1c10729cbaeecea0c6178db5 Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 28 Feb 2018 21:15:19 +0100 +Subject: [PATCH] brcmfmac: add possibility to obtain firmware error + +The feature module needs to evaluate the actual firmware error return +upon a control command. This adds a flag to struct brcmf_if that the +caller can set. This flag is checked to determine the error code that +needs to be returned. + +Fixes: b69c1df47281 ("brcmfmac: separate firmware errors from i/o errors") +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h | 2 ++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 10 ++++++++++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 3 +++ + 3 files changed, 15 insertions(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +@@ -181,6 +181,7 @@ enum brcmf_netif_stop_reason { + * @netif_stop_lock: spinlock for update netif_stop from multiple sources. + * @pend_8021x_cnt: tracks outstanding number of 802.1x frames. + * @pend_8021x_wait: used for signalling change in count. ++ * @fwil_fwerr: flag indicating fwil layer should return firmware error codes. + */ + struct brcmf_if { + struct brcmf_pub *drvr; +@@ -198,6 +199,7 @@ struct brcmf_if { + wait_queue_head_t pend_8021x_wait; + struct in6_addr ipv6_addr_tbl[NDOL_MAX_ENTRIES]; + u8 ipv6addr_idx; ++ bool fwil_fwerr; + }; + + int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +@@ -104,6 +104,9 @@ static void brcmf_feat_iovar_int_get(str + u32 data; + int err; + ++ /* we need to know firmware error */ ++ ifp->fwil_fwerr = true; ++ + err = brcmf_fil_iovar_int_get(ifp, name, &data); + if (err == 0) { + brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]); +@@ -112,6 +115,8 @@ static void brcmf_feat_iovar_int_get(str + brcmf_dbg(TRACE, "%s feature check failed: %d\n", + brcmf_feat_names[id], err); + } ++ ++ ifp->fwil_fwerr = false; + } + + static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp, +@@ -120,6 +125,9 @@ static void brcmf_feat_iovar_data_set(st + { + int err; + ++ /* we need to know firmware error */ ++ ifp->fwil_fwerr = true; ++ + err = brcmf_fil_iovar_data_set(ifp, name, data, len); + if (err != -BRCMF_FW_UNSUPPORTED) { + brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]); +@@ -128,6 +136,8 @@ static void brcmf_feat_iovar_data_set(st + brcmf_dbg(TRACE, "%s feature check failed: %d\n", + brcmf_feat_names[id], err); + } ++ ++ ifp->fwil_fwerr = false; + } + + #define MAX_CAPS_BUFFER_SIZE 512 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +@@ -131,6 +131,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, + brcmf_fil_get_errstr((u32)(-fwerr)), fwerr); + err = -EBADE; + } ++ if (ifp->fwil_fwerr) ++ return fwerr; ++ + return err; + } + diff --git a/package/kernel/mac80211/patches/322-v4.16-0002-brcmfmac-fix-P2P_DEVICE-ethernet-address-generation.patch b/package/kernel/mac80211/patches/322-v4.16-0002-brcmfmac-fix-P2P_DEVICE-ethernet-address-generation.patch new file mode 100644 index 0000000000..20e16ad23f --- /dev/null +++ b/package/kernel/mac80211/patches/322-v4.16-0002-brcmfmac-fix-P2P_DEVICE-ethernet-address-generation.patch @@ -0,0 +1,64 @@ +From 455f3e76cfc0d893585a5f358b9ddbe9c1e1e53b Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Wed, 28 Feb 2018 21:15:20 +0100 +Subject: [PATCH] brcmfmac: fix P2P_DEVICE ethernet address generation + +The firmware has a requirement that the P2P_DEVICE address should +be different from the address of the primary interface. When not +specified by user-space, the driver generates the MAC address for +the P2P_DEVICE interface using the MAC address of the primary +interface and setting the locally administered bit. However, the MAC +address of the primary interface may already have that bit set causing +the creation of the P2P_DEVICE interface to fail with -EBUSY. Fix this +by using a random address instead to determine the P2P_DEVICE address. + +Cc: stable@vger.kernel.org # 3.10.y +Reported-by: Hans de Goede +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 24 ++++++++++------------ + 1 file changed, 11 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +@@ -462,25 +462,23 @@ static int brcmf_p2p_set_firmware(struct + * @dev_addr: optional device address. + * + * P2P needs mac addresses for P2P device and interface. If no device +- * address it specified, these are derived from the primary net device, ie. +- * the permanent ethernet address of the device. ++ * address it specified, these are derived from a random ethernet ++ * address. + */ + static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr) + { +- struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; +- bool local_admin = false; ++ bool random_addr = false; + +- if (!dev_addr || is_zero_ether_addr(dev_addr)) { +- dev_addr = pri_ifp->mac_addr; +- local_admin = true; +- } ++ if (!dev_addr || is_zero_ether_addr(dev_addr)) ++ random_addr = true; + +- /* Generate the P2P Device Address. This consists of the device's +- * primary MAC address with the locally administered bit set. ++ /* Generate the P2P Device Address obtaining a random ethernet ++ * address with the locally administered bit set. + */ +- memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); +- if (local_admin) +- p2p->dev_addr[0] |= 0x02; ++ if (random_addr) ++ eth_random_addr(p2p->dev_addr); ++ else ++ memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); + + /* Generate the P2P Interface Address. If the discovery and connection + * BSSCFGs need to simultaneously co-exist, then this address must be diff --git a/package/kernel/mac80211/patches/323-v4.16-0001-brcmfmac-drop-Inter-Access-Point-Protocol-packets-by.patch b/package/kernel/mac80211/patches/323-v4.16-0001-brcmfmac-drop-Inter-Access-Point-Protocol-packets-by.patch new file mode 100644 index 0000000000..f25dea01d2 --- /dev/null +++ b/package/kernel/mac80211/patches/323-v4.16-0001-brcmfmac-drop-Inter-Access-Point-Protocol-packets-by.patch @@ -0,0 +1,157 @@ +From 1259055170287a350cad453e9eac139c81609860 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 15 Mar 2018 08:29:09 +0100 +Subject: [PATCH] brcmfmac: drop Inter-Access Point Protocol packets by default +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Testing brcmfmac with more recent firmwares resulted in AP interfaces +not working in some specific setups. Debugging resulted in discovering +support for IAPP in Broadcom's firmwares. + +Older firmwares were only generating 802.11f frames. Newer ones like: +1) 10.10 (TOB) (r663589) +2) 10.10.122.20 (r683106) +for 4366b1 and 4366c0 respectively seem to also /respect/ 802.11f frames +in the Tx path by performing a STA disassociation. + +This obsoleted standard and its implementation is something that: +1) Most people don't need / want to use +2) Can allow local DoS attacks +3) Breaks AP interfaces in some specific bridge setups + +To solve issues it can cause this commit modifies brcmfmac to drop IAPP +packets. If affects: +1) Rx path: driver won't be sending these unwanted packets up. +2) Tx path: driver will reject packets that would trigger STA + disassociation perfromed by a firmware (possible local DoS attack). + +It appears there are some Broadcom's clients/users who care about this +feature despite the drawbacks. They can switch it on using a new module +param. + +This change results in only two more comparisons (check for module param +and check for Ethernet packet length) for 99.9% of packets. Its overhead +should be very minimal. + +Signed-off-by: Rafał Miłecki +Acked-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../wireless/broadcom/brcm80211/brcmfmac/common.c | 5 ++ + .../wireless/broadcom/brcm80211/brcmfmac/common.h | 1 + + .../wireless/broadcom/brcm80211/brcmfmac/core.c | 57 ++++++++++++++++++++++ + 3 files changed, 63 insertions(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -75,6 +75,10 @@ static int brcmf_roamoff; + module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); + MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); + ++static int brcmf_iapp_enable; ++module_param_named(iapp, brcmf_iapp_enable, int, 0); ++MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol"); ++ + #ifdef DEBUG + /* always succeed brcmf_bus_started() */ + static int brcmf_ignore_probe_fail; +@@ -441,6 +445,7 @@ struct brcmf_mp_device *brcmf_get_module + settings->feature_disable = brcmf_feature_disable; + settings->fcmode = brcmf_fcmode; + settings->roamoff = !!brcmf_roamoff; ++ settings->iapp = !!brcmf_iapp_enable; + #ifdef DEBUG + settings->ignore_probe_fail = !!brcmf_ignore_probe_fail; + #endif +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +@@ -58,6 +58,7 @@ struct brcmf_mp_device { + unsigned int feature_disable; + int fcmode; + bool roamoff; ++ bool iapp; + bool ignore_probe_fail; + struct brcmfmac_pd_cc *country_codes; + union { +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -230,6 +230,37 @@ static void brcmf_netdev_set_multicast_l + schedule_work(&ifp->multicast_work); + } + ++/** ++ * brcmf_skb_is_iapp - checks if skb is an IAPP packet ++ * ++ * @skb: skb to check ++ */ ++static bool brcmf_skb_is_iapp(struct sk_buff *skb) ++{ ++ static const u8 iapp_l2_update_packet[6] __aligned(2) = { ++ 0x00, 0x01, 0xaf, 0x81, 0x01, 0x00, ++ }; ++ unsigned char *eth_data; ++#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ++ const u16 *a, *b; ++#endif ++ ++ if (skb->len - skb->mac_len != 6 || ++ !is_multicast_ether_addr(eth_hdr(skb)->h_dest)) ++ return false; ++ ++ eth_data = skb_mac_header(skb) + ETH_HLEN; ++#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ++ return !(((*(const u32 *)eth_data) ^ (*(const u32 *)iapp_l2_update_packet)) | ++ ((*(const u16 *)(eth_data + 4)) ^ (*(const u16 *)(iapp_l2_update_packet + 4)))); ++#else ++ a = (const u16 *)eth_data; ++ b = (const u16 *)iapp_l2_update_packet; ++ ++ return !((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])); ++#endif ++} ++ + static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, + struct net_device *ndev) + { +@@ -250,6 +281,23 @@ static netdev_tx_t brcmf_netdev_start_xm + goto done; + } + ++ /* Some recent Broadcom's firmwares disassociate STA when they receive ++ * an 802.11f ADD frame. This behavior can lead to a local DoS security ++ * issue. Attacker may trigger disassociation of any STA by sending a ++ * proper Ethernet frame to the wireless interface. ++ * ++ * Moreover this feature may break AP interfaces in some specific ++ * setups. This applies e.g. to the bridge with hairpin mode enabled and ++ * IFLA_BRPORT_MCAST_TO_UCAST set. IAPP packet generated by a firmware ++ * will get passed back to the wireless interface and cause immediate ++ * disassociation of a just-connected STA. ++ */ ++ if (!drvr->settings->iapp && brcmf_skb_is_iapp(skb)) { ++ dev_kfree_skb(skb); ++ ret = -EINVAL; ++ goto done; ++ } ++ + /* Make sure there's enough writeable headroom */ + if (skb_headroom(skb) < drvr->hdrlen || skb_header_cloned(skb)) { + head_delta = max_t(int, drvr->hdrlen - skb_headroom(skb), 0); +@@ -325,6 +373,15 @@ void brcmf_txflowblock_if(struct brcmf_i + + void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) + { ++ /* Most of Broadcom's firmwares send 802.11f ADD frame every time a new ++ * STA connects to the AP interface. This is an obsoleted standard most ++ * users don't use, so don't pass these frames up unless requested. ++ */ ++ if (!ifp->drvr->settings->iapp && brcmf_skb_is_iapp(skb)) { ++ brcmu_pkt_buf_free_skb(skb); ++ return; ++ } ++ + if (skb->pkt_type == PACKET_MULTICAST) + ifp->ndev->stats.multicast++; + diff --git a/package/kernel/mac80211/patches/324-v4.16-0001-brcmfmac-Fix-check-for-ISO3166-code.patch b/package/kernel/mac80211/patches/324-v4.16-0001-brcmfmac-Fix-check-for-ISO3166-code.patch new file mode 100644 index 0000000000..d45f64ff23 --- /dev/null +++ b/package/kernel/mac80211/patches/324-v4.16-0001-brcmfmac-Fix-check-for-ISO3166-code.patch @@ -0,0 +1,29 @@ +From 9b9322db5c5a1917a66c71fe47c3848a9a31227e Mon Sep 17 00:00:00 2001 +From: Stefan Wahren +Date: Wed, 14 Mar 2018 20:02:59 +0100 +Subject: [PATCH] brcmfmac: Fix check for ISO3166 code + +The commit "regulatory: add NUL to request alpha2" increases the length of +alpha2 to 3. This causes a regression on brcmfmac, because +brcmf_cfg80211_reg_notifier() expect valid ISO3166 codes in the complete +array. So fix this accordingly. + +Fixes: 657308f73e67 ("regulatory: add NUL to request alpha2") +Signed-off-by: Stefan Wahren +Acked-by: Franky Lin +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -6803,7 +6803,7 @@ static void brcmf_cfg80211_reg_notifier( + return; + + /* ignore non-ISO3166 country codes */ +- for (i = 0; i < sizeof(req->alpha2); i++) ++ for (i = 0; i < 2; i++) + if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { + brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n", + req->alpha2[0], req->alpha2[1]); diff --git a/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch index 0e98cb50c8..b7bce637fa 100644 --- a/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch +++ b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch @@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -1238,6 +1238,7 @@ int __init brcmf_core_init(void) +@@ -1295,6 +1295,7 @@ int __init brcmf_core_init(void) { if (!schedule_work(&brcmf_driver_work)) return -EBUSY;