28e3c1a65f88d106f3a69171b4e440ef559ff529
[librecmc/librecmc.git] /
1 From b69c1df47281ad47bd2037a42b98f5c7115b7fd5 Mon Sep 17 00:00:00 2001
2 From: Arend Van Spriel <arend.vanspriel@broadcom.com>
3 Date: Mon, 22 Jan 2018 21:46:40 +0100
4 Subject: [PATCH] brcmfmac: separate firmware errors from i/o errors
5
6 When using the firmware api it can fail simply because firmware does
7 not like the request or it fails due to issues in the host interface.
8 Currently, there is only a single error code which is confusing. So
9 adding a parameter to pass the firmware error separately and in case
10 of a firmware error always return -EBADE to user-space.
11
12 Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
13 Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
14 Reviewed-by: Franky Lin <franky.lin@broadcom.com>
15 Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
16 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
17 ---
18  drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c  | 11 ++++++-----
19  drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c  | 16 +++++++++++-----
20  .../net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c    | 10 ++++++----
21  drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h | 14 ++++++++------
22  4 files changed, 31 insertions(+), 20 deletions(-)
23
24 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
25 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
26 @@ -165,7 +165,7 @@ static int brcmf_proto_bcdc_cmplt(struct
27  
28  static int
29  brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
30 -                           void *buf, uint len)
31 +                           void *buf, uint len, int *fwerr)
32  {
33         struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
34         struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
35 @@ -175,6 +175,7 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf
36  
37         brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
38  
39 +       *fwerr = 0;
40         ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false);
41         if (ret < 0) {
42                 brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n",
43 @@ -215,15 +216,14 @@ retry:
44  
45         /* Check the ERROR flag */
46         if (flags & BCDC_DCMD_ERROR)
47 -               ret = le32_to_cpu(msg->status);
48 -
49 +               *fwerr = le32_to_cpu(msg->status);
50  done:
51         return ret;
52  }
53  
54  static int
55  brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
56 -                         void *buf, uint len)
57 +                         void *buf, uint len, int *fwerr)
58  {
59         struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
60         struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
61 @@ -232,6 +232,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p
62  
63         brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
64  
65 +       *fwerr = 0;
66         ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true);
67         if (ret < 0)
68                 goto done;
69 @@ -255,7 +256,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p
70  
71         /* Check the ERROR flag */
72         if (flags & BCDC_DCMD_ERROR)
73 -               ret = le32_to_cpu(msg->status);
74 +               *fwerr = le32_to_cpu(msg->status);
75  
76  done:
77         return ret;
78 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
79 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
80 @@ -107,7 +107,7 @@ static s32
81  brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
82  {
83         struct brcmf_pub *drvr = ifp->drvr;
84 -       s32 err;
85 +       s32 err, fwerr;
86  
87         if (drvr->bus_if->state != BRCMF_BUS_UP) {
88                 brcmf_err("bus is down. we have nothing to do.\n");
89 @@ -117,14 +117,20 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp,
90         if (data != NULL)
91                 len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
92         if (set)
93 -               err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len);
94 +               err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd,
95 +                                          data, len, &fwerr);
96         else
97 -               err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len);
98 +               err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd,
99 +                                            data, len, &fwerr);
100  
101 -       if (err)
102 +       if (err) {
103                 brcmf_dbg(FIL, "Failed: %s (%d)\n",
104                           brcmf_fil_get_errstr((u32)(-err)), err);
105 -
106 +       } else if (fwerr < 0) {
107 +               brcmf_dbg(FIL, "Firmware error: %s (%d)\n",
108 +                         brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
109 +               err = -EBADE;
110 +       }
111         return err;
112  }
113  
114 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
115 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
116 @@ -477,7 +477,7 @@ static void brcmf_msgbuf_ioctl_resp_wake
117  
118  
119  static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
120 -                                  uint cmd, void *buf, uint len)
121 +                                  uint cmd, void *buf, uint len, int *fwerr)
122  {
123         struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
124         struct sk_buff *skb = NULL;
125 @@ -485,6 +485,7 @@ static int brcmf_msgbuf_query_dcmd(struc
126         int err;
127  
128         brcmf_dbg(MSGBUF, "ifidx=%d, cmd=%d, len=%d\n", ifidx, cmd, len);
129 +       *fwerr = 0;
130         msgbuf->ctl_completed = false;
131         err = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len);
132         if (err)
133 @@ -508,14 +509,15 @@ static int brcmf_msgbuf_query_dcmd(struc
134         }
135         brcmu_pkt_buf_free_skb(skb);
136  
137 -       return msgbuf->ioctl_resp_status;
138 +       *fwerr = msgbuf->ioctl_resp_status;
139 +       return 0;
140  }
141  
142  
143  static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx,
144 -                                uint cmd, void *buf, uint len)
145 +                                uint cmd, void *buf, uint len, int *fwerr)
146  {
147 -       return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len);
148 +       return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len, fwerr);
149  }
150  
151  
152 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
153 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
154 @@ -30,9 +30,9 @@ struct brcmf_proto {
155         int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws,
156                        struct sk_buff *skb, struct brcmf_if **ifp);
157         int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd,
158 -                         void *buf, uint len);
159 +                         void *buf, uint len, int *fwerr);
160         int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
161 -                       uint len);
162 +                       uint len, int *fwerr);
163         int (*tx_queue_data)(struct brcmf_pub *drvr, int ifidx,
164                              struct sk_buff *skb);
165         int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
166 @@ -71,14 +71,16 @@ static inline int brcmf_proto_hdrpull(st
167         return drvr->proto->hdrpull(drvr, do_fws, skb, ifp);
168  }
169  static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx,
170 -                                        uint cmd, void *buf, uint len)
171 +                                        uint cmd, void *buf, uint len,
172 +                                        int *fwerr)
173  {
174 -       return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len);
175 +       return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len,fwerr);
176  }
177  static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx,
178 -                                      uint cmd, void *buf, uint len)
179 +                                      uint cmd, void *buf, uint len,
180 +                                      int *fwerr)
181  {
182 -       return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
183 +       return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len, fwerr);
184  }
185  
186  static inline int brcmf_proto_tx_queue_data(struct brcmf_pub *drvr, int ifidx,