aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c36
1 files changed, 16 insertions, 20 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 7550f9f1211f..2b5cde67e728 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -197,32 +197,21 @@ int brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev)
197 return 0; 197 return 0;
198} 198}
199 199
200static inline int brcmf_sdiod_f0_write_byte(struct brcmf_sdio_dev *sdiodev, 200static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func,
201 uint regaddr, u8 *byte) 201 uint regaddr, u8 byte)
202{ 202{
203 struct sdio_func *sdfunc = sdiodev->func[0];
204 int err_ret; 203 int err_ret;
205 204
206 /* 205 /*
207 * Can only directly write to some F0 registers. 206 * Can only directly write to some F0 registers.
208 * Handle F2 enable/disable and Abort command 207 * Handle CCCR_IENx and CCCR_ABORT command
209 * as a special case. 208 * as a special case.
210 */ 209 */
211 if ((regaddr == SDIO_CCCR_ABORT) || 210 if ((regaddr == SDIO_CCCR_ABORT) ||
212 (regaddr == SDIO_CCCR_IENx)) { 211 (regaddr == SDIO_CCCR_IENx))
213 sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func), 212 sdio_writeb(func, byte, regaddr, &err_ret);
214 GFP_KERNEL); 213 else
215 if (!sdfunc) 214 sdio_f0_writeb(func, byte, regaddr, &err_ret);
216 return -ENOMEM;
217 sdfunc->num = 0;
218 sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
219 kfree(sdfunc);
220 } else if (regaddr < 0xF0) {
221 brcmf_err("F0 Wr:0x%02x: write disallowed\n", regaddr);
222 err_ret = -EPERM;
223 } else {
224 sdio_f0_writeb(sdfunc, *byte, regaddr, &err_ret);
225 }
226 215
227 return err_ret; 216 return err_ret;
228} 217}
@@ -240,7 +229,8 @@ static int brcmf_sdiod_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw,
240 229
241 if (rw && func == 0) { 230 if (rw && func == 0) {
242 /* handle F0 separately */ 231 /* handle F0 separately */
243 err_ret = brcmf_sdiod_f0_write_byte(sdiodev, regaddr, byte); 232 err_ret = brcmf_sdiod_f0_writeb(sdiodev->func[func],
233 regaddr, *byte);
244 } else { 234 } else {
245 if (rw) /* CMD52 Write */ 235 if (rw) /* CMD52 Write */
246 sdio_writeb(sdiodev->func[func], *byte, regaddr, 236 sdio_writeb(sdiodev->func[func], *byte, regaddr,
@@ -1030,7 +1020,11 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
1030 return -ENOMEM; 1020 return -ENOMEM;
1031 } 1021 }
1032 1022
1033 sdiodev->func[0] = func->card->sdio_func[0]; 1023 /* store refs to functions used. mmc_card does
1024 * not hold the F0 function pointer.
1025 */
1026 sdiodev->func[0] = kmemdup(func, sizeof(*func), GFP_KERNEL);
1027 sdiodev->func[0]->num = 0;
1034 sdiodev->func[1] = func->card->sdio_func[0]; 1028 sdiodev->func[1] = func->card->sdio_func[0];
1035 sdiodev->func[2] = func; 1029 sdiodev->func[2] = func;
1036 1030
@@ -1060,6 +1054,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
1060fail: 1054fail:
1061 dev_set_drvdata(&func->dev, NULL); 1055 dev_set_drvdata(&func->dev, NULL);
1062 dev_set_drvdata(&sdiodev->func[1]->dev, NULL); 1056 dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
1057 kfree(sdiodev->func[0]);
1063 kfree(sdiodev); 1058 kfree(sdiodev);
1064 kfree(bus_if); 1059 kfree(bus_if);
1065 return err; 1060 return err;
@@ -1087,6 +1082,7 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
1087 dev_set_drvdata(&sdiodev->func[2]->dev, NULL); 1082 dev_set_drvdata(&sdiodev->func[2]->dev, NULL);
1088 1083
1089 kfree(bus_if); 1084 kfree(bus_if);
1085 kfree(sdiodev->func[0]);
1090 kfree(sdiodev); 1086 kfree(sdiodev);
1091 } 1087 }
1092 1088