hc
2024-01-31 f9004dbfff8a3fbbd7e2a88c8a4327c7f2f8e5b2
kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
....@@ -1,17 +1,6 @@
1
+// SPDX-License-Identifier: ISC
12 /*
23 * Copyright (c) 2010 Broadcom Corporation
3
- *
4
- * Permission to use, copy, modify, and/or distribute this software for any
5
- * purpose with or without fee is hereby granted, provided that the above
6
- * copyright notice and this permission notice appear in all copies.
7
- *
8
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
154 */
165 /* ****************** SDIO CARD Interface Functions **************************/
176
....@@ -54,6 +43,9 @@
5443
5544 #define SDIO_FUNC1_BLOCKSIZE 64
5645 #define SDIO_FUNC2_BLOCKSIZE 512
46
+#define SDIO_4373_FUNC2_BLOCKSIZE 256
47
+#define SDIO_435X_FUNC2_BLOCKSIZE 256
48
+#define SDIO_4329_FUNC2_BLOCKSIZE 128
5749 /* Maximum milliseconds to wait for F2 to come up */
5850 #define SDIO_WAIT_F2RDY 3000
5951
....@@ -82,7 +74,7 @@
8274 sdiodev->irq_en = false;
8375 }
8476
85
- brcmf_sdio_isr(sdiodev->bus);
77
+ brcmf_sdio_isr(sdiodev->bus, true);
8678
8779 return IRQ_HANDLED;
8880 }
....@@ -94,7 +86,7 @@
9486
9587 brcmf_dbg(INTR, "IB intr triggered\n");
9688
97
- brcmf_sdio_isr(sdiodev->bus);
89
+ brcmf_sdio_isr(sdiodev->bus, false);
9890 }
9991
10092 /* dummy handler for SDIO function 2 interrupt */
....@@ -130,7 +122,7 @@
130122 brcmf_err("enable_irq_wake failed %d\n", ret);
131123 return ret;
132124 }
133
- sdiodev->irq_wake = true;
125
+ disable_irq_wake(pdata->oob_irq_nr);
134126
135127 sdio_claim_host(sdiodev->func1);
136128
....@@ -189,10 +181,6 @@
189181 sdio_release_host(sdiodev->func1);
190182
191183 sdiodev->oob_irq_requested = false;
192
- if (sdiodev->irq_wake) {
193
- disable_irq_wake(pdata->oob_irq_nr);
194
- sdiodev->irq_wake = false;
195
- }
196184 free_irq(pdata->oob_irq_nr, &sdiodev->func1->dev);
197185 sdiodev->irq_en = false;
198186 sdiodev->oob_irq_requested = false;
....@@ -315,7 +303,7 @@
315303 /* bail out as things are really fishy here */
316304 WARN(1, "invalid sdio function number: %d\n", func->num);
317305 err = -ENOMEDIUM;
318
- };
306
+ }
319307
320308 if (err == -ENOMEDIUM)
321309 brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
....@@ -342,6 +330,37 @@
342330 return err;
343331 }
344332
333
+static int mmc_submit_one(struct mmc_data *md, struct mmc_request *mr,
334
+ struct mmc_command *mc, int sg_cnt, int req_sz,
335
+ int func_blk_sz, u32 *addr,
336
+ struct brcmf_sdio_dev *sdiodev,
337
+ struct sdio_func *func, int write)
338
+{
339
+ int ret;
340
+
341
+ md->sg_len = sg_cnt;
342
+ md->blocks = req_sz / func_blk_sz;
343
+ mc->arg |= (*addr & 0x1FFFF) << 9; /* address */
344
+ mc->arg |= md->blocks & 0x1FF; /* block count */
345
+ /* incrementing addr for function 1 */
346
+ if (func->num == 1)
347
+ *addr += req_sz;
348
+
349
+ mmc_set_data_timeout(md, func->card);
350
+ mmc_wait_for_req(func->card->host, mr);
351
+
352
+ ret = mc->error ? mc->error : md->error;
353
+ if (ret == -ENOMEDIUM) {
354
+ brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
355
+ } else if (ret != 0) {
356
+ brcmf_err("CMD53 sg block %s failed %d\n",
357
+ write ? "write" : "read", ret);
358
+ ret = -EIO;
359
+ }
360
+
361
+ return ret;
362
+}
363
+
345364 /**
346365 * brcmf_sdiod_sglist_rw - SDIO interface function for block data access
347366 * @sdiodev: brcmfmac sdio device
....@@ -360,11 +379,11 @@
360379 struct sk_buff_head *pktlist)
361380 {
362381 unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
363
- unsigned int max_req_sz, orig_offset, dst_offset;
364
- unsigned short max_seg_cnt, seg_sz;
382
+ unsigned int max_req_sz, src_offset, dst_offset;
365383 unsigned char *pkt_data, *orig_data, *dst_data;
366
- struct sk_buff *pkt_next = NULL, *local_pkt_next;
367384 struct sk_buff_head local_list, *target_list;
385
+ struct sk_buff *pkt_next = NULL, *src;
386
+ unsigned short max_seg_cnt;
368387 struct mmc_request mmc_req;
369388 struct mmc_command mmc_cmd;
370389 struct mmc_data mmc_dat;
....@@ -404,9 +423,6 @@
404423 max_req_sz = sdiodev->max_request_size;
405424 max_seg_cnt = min_t(unsigned short, sdiodev->max_segment_count,
406425 target_list->qlen);
407
- seg_sz = target_list->qlen;
408
- pkt_offset = 0;
409
- pkt_next = target_list->next;
410426
411427 memset(&mmc_req, 0, sizeof(struct mmc_request));
412428 memset(&mmc_cmd, 0, sizeof(struct mmc_command));
....@@ -425,12 +441,12 @@
425441 mmc_req.cmd = &mmc_cmd;
426442 mmc_req.data = &mmc_dat;
427443
428
- while (seg_sz) {
429
- req_sz = 0;
430
- sg_cnt = 0;
431
- sgl = sdiodev->sgtable.sgl;
432
- /* prep sg table */
433
- while (pkt_next != (struct sk_buff *)target_list) {
444
+ req_sz = 0;
445
+ sg_cnt = 0;
446
+ sgl = sdiodev->sgtable.sgl;
447
+ skb_queue_walk(target_list, pkt_next) {
448
+ pkt_offset = 0;
449
+ while (pkt_offset < pkt_next->len) {
434450 pkt_data = pkt_next->data + pkt_offset;
435451 sg_data_sz = pkt_next->len - pkt_offset;
436452 if (sg_data_sz > sdiodev->max_segment_size)
....@@ -439,72 +455,55 @@
439455 sg_data_sz = max_req_sz - req_sz;
440456
441457 sg_set_buf(sgl, pkt_data, sg_data_sz);
442
-
443458 sg_cnt++;
459
+
444460 sgl = sg_next(sgl);
445461 req_sz += sg_data_sz;
446462 pkt_offset += sg_data_sz;
447
- if (pkt_offset == pkt_next->len) {
448
- pkt_offset = 0;
449
- pkt_next = pkt_next->next;
463
+ if (req_sz >= max_req_sz || sg_cnt >= max_seg_cnt) {
464
+ ret = mmc_submit_one(&mmc_dat, &mmc_req, &mmc_cmd,
465
+ sg_cnt, req_sz, func_blk_sz,
466
+ &addr, sdiodev, func, write);
467
+ if (ret)
468
+ goto exit_queue_walk;
469
+ req_sz = 0;
470
+ sg_cnt = 0;
471
+ sgl = sdiodev->sgtable.sgl;
450472 }
451
-
452
- if (req_sz >= max_req_sz || sg_cnt >= max_seg_cnt)
453
- break;
454
- }
455
- seg_sz -= sg_cnt;
456
-
457
- if (req_sz % func_blk_sz != 0) {
458
- brcmf_err("sg request length %u is not %u aligned\n",
459
- req_sz, func_blk_sz);
460
- ret = -ENOTBLK;
461
- goto exit;
462
- }
463
-
464
- mmc_dat.sg_len = sg_cnt;
465
- mmc_dat.blocks = req_sz / func_blk_sz;
466
- mmc_cmd.arg |= (addr & 0x1FFFF) << 9; /* address */
467
- mmc_cmd.arg |= mmc_dat.blocks & 0x1FF; /* block count */
468
- /* incrementing addr for function 1 */
469
- if (func->num == 1)
470
- addr += req_sz;
471
-
472
- mmc_set_data_timeout(&mmc_dat, func->card);
473
- mmc_wait_for_req(func->card->host, &mmc_req);
474
-
475
- ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
476
- if (ret == -ENOMEDIUM) {
477
- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
478
- break;
479
- } else if (ret != 0) {
480
- brcmf_err("CMD53 sg block %s failed %d\n",
481
- write ? "write" : "read", ret);
482
- ret = -EIO;
483
- break;
484473 }
485474 }
486
-
475
+ if (sg_cnt)
476
+ ret = mmc_submit_one(&mmc_dat, &mmc_req, &mmc_cmd,
477
+ sg_cnt, req_sz, func_blk_sz,
478
+ &addr, sdiodev, func, write);
479
+exit_queue_walk:
487480 if (!write && sdiodev->settings->bus.sdio.broken_sg_support) {
488
- local_pkt_next = local_list.next;
489
- orig_offset = 0;
481
+ src = __skb_peek(&local_list);
482
+ src_offset = 0;
490483 skb_queue_walk(pktlist, pkt_next) {
491484 dst_offset = 0;
492
- do {
493
- req_sz = local_pkt_next->len - orig_offset;
494
- req_sz = min_t(uint, pkt_next->len - dst_offset,
495
- req_sz);
496
- orig_data = local_pkt_next->data + orig_offset;
485
+
486
+ /* This is safe because we must have enough SKB data
487
+ * in the local list to cover everything in pktlist.
488
+ */
489
+ while (1) {
490
+ req_sz = pkt_next->len - dst_offset;
491
+ if (req_sz > src->len - src_offset)
492
+ req_sz = src->len - src_offset;
493
+
494
+ orig_data = src->data + src_offset;
497495 dst_data = pkt_next->data + dst_offset;
498496 memcpy(dst_data, orig_data, req_sz);
499
- orig_offset += req_sz;
500
- dst_offset += req_sz;
501
- if (orig_offset == local_pkt_next->len) {
502
- orig_offset = 0;
503
- local_pkt_next = local_pkt_next->next;
497
+
498
+ src_offset += req_sz;
499
+ if (src_offset == src->len) {
500
+ src_offset = 0;
501
+ src = skb_peek_next(src, &local_list);
504502 }
503
+ dst_offset += req_sz;
505504 if (dst_offset == pkt_next->len)
506505 break;
507
- } while (!skb_queue_empty(&local_list));
506
+ }
508507 }
509508 }
510509
....@@ -576,7 +575,7 @@
576575
577576 if (pktq->qlen == 1)
578577 err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr,
579
- pktq->next);
578
+ __skb_peek(pktq));
580579 else if (!sdiodev->sg_support) {
581580 glom_skb = brcmu_pkt_buf_get_skb(totlen);
582581 if (!glom_skb)
....@@ -865,7 +864,7 @@
865864 }
866865 #endif /* CONFIG_PM_SLEEP */
867866
868
-static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
867
+int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
869868 {
870869 sdiodev->state = BRCMF_SDIOD_DOWN;
871870 if (sdiodev->bus) {
....@@ -900,9 +899,10 @@
900899 host->caps |= MMC_CAP_NONREMOVABLE;
901900 }
902901
903
-static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
902
+int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
904903 {
905904 int ret = 0;
905
+ unsigned int f2_blksz = SDIO_FUNC2_BLOCKSIZE;
906906
907907 sdio_claim_host(sdiodev->func1);
908908
....@@ -912,11 +912,29 @@
912912 sdio_release_host(sdiodev->func1);
913913 goto out;
914914 }
915
- ret = sdio_set_block_size(sdiodev->func2, SDIO_FUNC2_BLOCKSIZE);
915
+ switch (sdiodev->func2->device) {
916
+ case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373:
917
+ f2_blksz = SDIO_4373_FUNC2_BLOCKSIZE;
918
+ break;
919
+ case SDIO_DEVICE_ID_BROADCOM_4359:
920
+ case SDIO_DEVICE_ID_BROADCOM_4354:
921
+ case SDIO_DEVICE_ID_BROADCOM_4356:
922
+ f2_blksz = SDIO_435X_FUNC2_BLOCKSIZE;
923
+ break;
924
+ case SDIO_DEVICE_ID_BROADCOM_4329:
925
+ f2_blksz = SDIO_4329_FUNC2_BLOCKSIZE;
926
+ break;
927
+ default:
928
+ break;
929
+ }
930
+
931
+ ret = sdio_set_block_size(sdiodev->func2, f2_blksz);
916932 if (ret) {
917933 brcmf_err("Failed to set F2 blocksize\n");
918934 sdio_release_host(sdiodev->func1);
919935 goto out;
936
+ } else {
937
+ brcmf_dbg(SDIO, "set F2 blocksize to %d\n", f2_blksz);
920938 }
921939
922940 /* increase F2 timeout */
....@@ -961,7 +979,7 @@
961979 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43340),
962980 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341),
963981 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362),
964
- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43364),
982
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43364),
965983 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339),
966984 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4339),
967985 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430),
....@@ -969,7 +987,10 @@
969987 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455),
970988 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
971989 BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356),
972
- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_CYPRESS_4373),
990
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4359),
991
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373),
992
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012),
993
+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359),
973994 { /* end: all zeroes */ }
974995 };
975996 MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
....@@ -1107,7 +1128,8 @@
11071128 struct sdio_func *func;
11081129 struct brcmf_bus *bus_if;
11091130 struct brcmf_sdio_dev *sdiodev;
1110
- mmc_pm_flag_t sdio_flags;
1131
+ mmc_pm_flag_t pm_caps, sdio_flags;
1132
+ int ret = 0;
11111133
11121134 func = container_of(dev, struct sdio_func, dev);
11131135 brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
....@@ -1118,19 +1140,33 @@
11181140 bus_if = dev_get_drvdata(dev);
11191141 sdiodev = bus_if->bus_priv.sdio;
11201142
1121
- brcmf_sdiod_freezer_on(sdiodev);
1122
- brcmf_sdio_wd_timer(sdiodev->bus, 0);
1143
+ pm_caps = sdio_get_host_pm_caps(func);
11231144
1124
- sdio_flags = MMC_PM_KEEP_POWER;
1125
- if (sdiodev->wowl_enabled) {
1126
- if (sdiodev->settings->bus.sdio.oob_irq_supported)
1127
- enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
1128
- else
1129
- sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
1145
+ if (pm_caps & MMC_PM_KEEP_POWER) {
1146
+ /* preserve card power during suspend */
1147
+ brcmf_sdiod_freezer_on(sdiodev);
1148
+ brcmf_sdio_wd_timer(sdiodev->bus, 0);
1149
+
1150
+ sdio_flags = MMC_PM_KEEP_POWER;
1151
+ if (sdiodev->wowl_enabled) {
1152
+ if (sdiodev->settings->bus.sdio.oob_irq_supported)
1153
+ enable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
1154
+ else
1155
+ sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
1156
+ }
1157
+
1158
+ if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
1159
+ brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
1160
+
1161
+ } else {
1162
+ /* power will be cut so remove device, probe again in resume */
1163
+ brcmf_sdiod_intr_unregister(sdiodev);
1164
+ ret = brcmf_sdiod_remove(sdiodev);
1165
+ if (ret)
1166
+ brcmf_err("Failed to remove device on suspend\n");
11301167 }
1131
- if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
1132
- brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
1133
- return 0;
1168
+
1169
+ return ret;
11341170 }
11351171
11361172 static int brcmf_ops_sdio_resume(struct device *dev)
....@@ -1138,13 +1174,27 @@
11381174 struct brcmf_bus *bus_if = dev_get_drvdata(dev);
11391175 struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
11401176 struct sdio_func *func = container_of(dev, struct sdio_func, dev);
1177
+ mmc_pm_flag_t pm_caps = sdio_get_host_pm_caps(func);
1178
+ int ret = 0;
11411179
11421180 brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
11431181 if (func->num != 2)
11441182 return 0;
11451183
1146
- brcmf_sdiod_freezer_off(sdiodev);
1147
- return 0;
1184
+ if (!(pm_caps & MMC_PM_KEEP_POWER)) {
1185
+ /* bus was powered off and device removed, probe again */
1186
+ ret = brcmf_sdiod_probe(sdiodev);
1187
+ if (ret)
1188
+ brcmf_err("Failed to probe device on resume\n");
1189
+ } else {
1190
+ if (sdiodev->wowl_enabled &&
1191
+ sdiodev->settings->bus.sdio.oob_irq_supported)
1192
+ disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr);
1193
+
1194
+ brcmf_sdiod_freezer_off(sdiodev);
1195
+ }
1196
+
1197
+ return ret;
11481198 }
11491199
11501200 static const struct dev_pm_ops brcmf_sdio_pm_ops = {
....@@ -1167,13 +1217,9 @@
11671217 },
11681218 };
11691219
1170
-void brcmf_sdio_register(void)
1220
+int brcmf_sdio_register(void)
11711221 {
1172
- int ret;
1173
-
1174
- ret = sdio_register_driver(&brcmf_sdmmc_driver);
1175
- if (ret)
1176
- brcmf_err("sdio_register_driver failed: %d\n", ret);
1222
+ return sdio_register_driver(&brcmf_sdmmc_driver);
11771223 }
11781224
11791225 void brcmf_sdio_exit(void)