aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c149
1 files changed, 133 insertions, 16 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 32a205e0b063..3f8e69c29146 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -22,9 +22,11 @@
22#include <linux/pci_ids.h> 22#include <linux/pci_ids.h>
23#include <linux/sched.h> 23#include <linux/sched.h>
24#include <linux/completion.h> 24#include <linux/completion.h>
25#include <linux/scatterlist.h>
25#include <linux/mmc/sdio.h> 26#include <linux/mmc/sdio.h>
26#include <linux/mmc/sdio_func.h> 27#include <linux/mmc/sdio_func.h>
27#include <linux/mmc/card.h> 28#include <linux/mmc/card.h>
29#include <linux/mmc/host.h>
28#include <linux/platform_data/brcmfmac-sdio.h> 30#include <linux/platform_data/brcmfmac-sdio.h>
29 31
30#include <defs.h> 32#include <defs.h>
@@ -316,34 +318,138 @@ void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
316 * caller has already been padded and aligned. 318 * caller has already been padded and aligned.
317 */ 319 */
318static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn, 320static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
319 bool write, u32 addr, struct sk_buff *pkt) 321 bool write, u32 addr, struct sk_buff_head *pktlist)
320{ 322{
321 uint len; 323 unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
324 unsigned int max_blks, max_req_sz;
325 unsigned short max_seg_sz, seg_sz;
326 unsigned char *pkt_data;
327 struct sk_buff *pkt_next = NULL;
328 struct mmc_request mmc_req;
329 struct mmc_command mmc_cmd;
330 struct mmc_data mmc_dat;
331 struct sg_table st;
332 struct scatterlist *sgl;
333 struct mmc_host *host;
334 int ret = 0;
335
336 if (!pktlist->qlen)
337 return -EINVAL;
322 338
323 brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); 339 brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
324 if (brcmf_pm_resume_error(sdiodev)) 340 if (brcmf_pm_resume_error(sdiodev))
325 return -EIO; 341 return -EIO;
326 342
327 /* Single skb use the standard mmc interface */ 343 /* Single skb use the standard mmc interface */
328 if (!pkt->next) { 344 if (pktlist->qlen == 1) {
329 len = pkt->len + 3; 345 pkt_next = pktlist->next;
330 len &= (uint)~3; 346 req_sz = pkt_next->len + 3;
347 req_sz &= (uint)~3;
331 348
332 if (write) 349 if (write)
333 return sdio_memcpy_toio(sdiodev->func[fn], addr, 350 return sdio_memcpy_toio(sdiodev->func[fn], addr,
334 ((u8 *)(pkt->data)), len); 351 ((u8 *)(pkt_next->data)),
352 req_sz);
335 else if (fn == 1) 353 else if (fn == 1)
336 return sdio_memcpy_fromio(sdiodev->func[fn], 354 return sdio_memcpy_fromio(sdiodev->func[fn],
337 ((u8 *)(pkt->data)), addr, 355 ((u8 *)(pkt_next->data)),
338 len); 356 addr, req_sz);
339 else 357 else
340 /* function 2 read is FIFO operation */ 358 /* function 2 read is FIFO operation */
341 return sdio_readsb(sdiodev->func[fn], 359 return sdio_readsb(sdiodev->func[fn],
342 ((u8 *)(pkt->data)), addr, len); 360 ((u8 *)(pkt_next->data)), addr,
361 req_sz);
343 } 362 }
344 363
345 brcmf_err("skb chain is not supported yet.\n"); 364 host = sdiodev->func[fn]->card->host;
346 return -EOPNOTSUPP; 365 func_blk_sz = sdiodev->func[fn]->cur_blksize;
366 /* Blocks per command is limited by host count, host transfer
367 * size and the maximum for IO_RW_EXTENDED of 511 blocks.
368 */
369 max_blks = min_t(unsigned int, host->max_blk_count, 511u);
370 max_req_sz = min_t(unsigned int, host->max_req_size,
371 max_blks * func_blk_sz);
372 max_seg_sz = min_t(unsigned short, host->max_segs, SG_MAX_SINGLE_ALLOC);
373 max_seg_sz = min_t(unsigned short, max_seg_sz, pktlist->qlen);
374 seg_sz = pktlist->qlen;
375 pkt_offset = 0;
376 pkt_next = pktlist->next;
377
378 if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL))
379 return -ENOMEM;
380
381 while (seg_sz) {
382 req_sz = 0;
383 sg_cnt = 0;
384 memset(&mmc_req, 0, sizeof(struct mmc_request));
385 memset(&mmc_cmd, 0, sizeof(struct mmc_command));
386 memset(&mmc_dat, 0, sizeof(struct mmc_data));
387 sgl = st.sgl;
388 /* prep sg table */
389 while (pkt_next != (struct sk_buff *)pktlist) {
390 pkt_data = pkt_next->data + pkt_offset;
391 sg_data_sz = pkt_next->len - pkt_offset;
392 if (sg_data_sz > host->max_seg_size)
393 sg_data_sz = host->max_seg_size;
394 if (sg_data_sz > max_req_sz - req_sz)
395 sg_data_sz = max_req_sz - req_sz;
396
397 sg_set_buf(sgl, pkt_data, sg_data_sz);
398
399 sg_cnt++;
400 sgl = sg_next(sgl);
401 req_sz += sg_data_sz;
402 pkt_offset += sg_data_sz;
403 if (pkt_offset == pkt_next->len) {
404 pkt_offset = 0;
405 pkt_next = pkt_next->next;
406 }
407
408 if (req_sz >= max_req_sz || sg_cnt >= max_seg_sz)
409 break;
410 }
411 seg_sz -= sg_cnt;
412
413 if (req_sz % func_blk_sz != 0) {
414 brcmf_err("sg request length %u is not %u aligned\n",
415 req_sz, func_blk_sz);
416 sg_free_table(&st);
417 return -ENOTBLK;
418 }
419 mmc_dat.sg = st.sgl;
420 mmc_dat.sg_len = sg_cnt;
421 mmc_dat.blksz = func_blk_sz;
422 mmc_dat.blocks = req_sz / func_blk_sz;
423 mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
424 mmc_cmd.opcode = SD_IO_RW_EXTENDED;
425 mmc_cmd.arg = write ? 1<<31 : 0; /* write flag */
426 mmc_cmd.arg |= (fn & 0x7) << 28; /* SDIO func num */
427 mmc_cmd.arg |= 1<<27; /* block mode */
428 /* incrementing addr for function 1 */
429 mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0;
430 mmc_cmd.arg |= (addr & 0x1FFFF) << 9; /* address */
431 mmc_cmd.arg |= mmc_dat.blocks & 0x1FF; /* block count */
432 mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
433 mmc_req.cmd = &mmc_cmd;
434 mmc_req.data = &mmc_dat;
435 if (fn == 1)
436 addr += req_sz;
437
438 mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card);
439 mmc_wait_for_req(host, &mmc_req);
440
441 ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
442 if (ret != 0) {
443 brcmf_err("CMD53 sg block %s failed %d\n",
444 write ? "write" : "read", ret);
445 ret = -EIO;
446 break;
447 }
448 }
449
450 sg_free_table(&st);
451
452 return ret;
347} 453}
348 454
349static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, 455static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn,
@@ -400,6 +506,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
400{ 506{
401 uint width; 507 uint width;
402 int err = 0; 508 int err = 0;
509 struct sk_buff_head pkt_list;
403 510
404 brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", 511 brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
405 fn, addr, pkt->len); 512 fn, addr, pkt->len);
@@ -409,7 +516,10 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
409 if (err) 516 if (err)
410 goto done; 517 goto done;
411 518
412 err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pkt); 519 skb_queue_head_init(&pkt_list);
520 skb_queue_tail(&pkt_list, pkt);
521 err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, &pkt_list);
522 skb_dequeue_tail(&pkt_list);
413 523
414done: 524done:
415 return err; 525 return err;
@@ -431,8 +541,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
431 goto done; 541 goto done;
432 542
433 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; 543 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
434 err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr, 544 err = brcmf_sdio_buffrw(sdiodev, fn, false, addr, pktq);
435 pktq);
436 545
437done: 546done:
438 return err; 547 return err;
@@ -467,6 +576,7 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
467 uint width; 576 uint width;
468 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; 577 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
469 int err = 0; 578 int err = 0;
579 struct sk_buff_head pkt_list;
470 580
471 brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n", 581 brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
472 fn, addr, pkt->len); 582 fn, addr, pkt->len);
@@ -489,7 +599,10 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
489 if (width == 4) 599 if (width == 4)
490 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; 600 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
491 601
492 err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, pkt); 602 skb_queue_head_init(&pkt_list);
603 skb_queue_tail(&pkt_list, pkt);
604 err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, &pkt_list);
605 skb_dequeue_tail(&pkt_list);
493 606
494done: 607done:
495 return err; 608 return err;
@@ -503,6 +616,7 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
503 struct sk_buff *pkt; 616 struct sk_buff *pkt;
504 u32 sdaddr; 617 u32 sdaddr;
505 uint dsize; 618 uint dsize;
619 struct sk_buff_head pkt_list;
506 620
507 dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); 621 dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size);
508 pkt = dev_alloc_skb(dsize); 622 pkt = dev_alloc_skb(dsize);
@@ -511,6 +625,7 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
511 return -EIO; 625 return -EIO;
512 } 626 }
513 pkt->priority = 0; 627 pkt->priority = 0;
628 skb_queue_head_init(&pkt_list);
514 629
515 /* Determine initial transfer parameters */ 630 /* Determine initial transfer parameters */
516 sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; 631 sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
@@ -538,8 +653,10 @@ brcmf_sdio_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
538 skb_put(pkt, dsize); 653 skb_put(pkt, dsize);
539 if (write) 654 if (write)
540 memcpy(pkt->data, data, dsize); 655 memcpy(pkt->data, data, dsize);
656 skb_queue_tail(&pkt_list, pkt);
541 bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write, 657 bcmerror = brcmf_sdio_buffrw(sdiodev, SDIO_FUNC_1, write,
542 sdaddr, pkt); 658 sdaddr, &pkt_list);
659 skb_dequeue_tail(&pkt_list);
543 if (bcmerror) { 660 if (bcmerror) {
544 brcmf_err("membytes transfer failed\n"); 661 brcmf_err("membytes transfer failed\n");
545 break; 662 break;