diff options
author | Arend van Spriel <arend@broadcom.com> | 2014-02-27 13:25:00 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-02-28 14:33:45 -0500 |
commit | af1fa210f4fc6e304b859b386a3c8a266b1110ab (patch) | |
tree | 0ff7c96ae5f50229100a3483ccc5275f9d4711f9 | |
parent | 4aca7a185aeba4472e7a798e5d834d7702ebbeca (diff) |
brcmfmac: use pre-allocated scatter-gather table for txglomming
Instead of allocating a scatter-gather table for every transmit
reuse a pre-allocated table. The transmit path will be faster by
taking out this allocation.
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 47 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | 2 |
3 files changed, 41 insertions, 16 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 07e7d2520257..9eea7d4dd501 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -53,6 +53,12 @@ | |||
53 | /* Maximum milliseconds to wait for F2 to come up */ | 53 | /* Maximum milliseconds to wait for F2 to come up */ |
54 | #define SDIO_WAIT_F2RDY 3000 | 54 | #define SDIO_WAIT_F2RDY 3000 |
55 | 55 | ||
56 | #define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */ | ||
57 | #define BRCMF_DEFAULT_RXGLOM_SIZE 32 /* max rx frames in glom chain */ | ||
58 | |||
59 | static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE; | ||
60 | module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0); | ||
61 | MODULE_PARM_DESC(txglomsz, "maximum tx packet chain size [SDIO]"); | ||
56 | 62 | ||
57 | static irqreturn_t brcmf_sdiod_oob_irqhandler(int irq, void *dev_id) | 63 | static irqreturn_t brcmf_sdiod_oob_irqhandler(int irq, void *dev_id) |
58 | { | 64 | { |
@@ -487,7 +493,6 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
487 | struct mmc_request mmc_req; | 493 | struct mmc_request mmc_req; |
488 | struct mmc_command mmc_cmd; | 494 | struct mmc_command mmc_cmd; |
489 | struct mmc_data mmc_dat; | 495 | struct mmc_data mmc_dat; |
490 | struct sg_table st; | ||
491 | struct scatterlist *sgl; | 496 | struct scatterlist *sgl; |
492 | int ret = 0; | 497 | int ret = 0; |
493 | 498 | ||
@@ -532,16 +537,11 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
532 | pkt_offset = 0; | 537 | pkt_offset = 0; |
533 | pkt_next = target_list->next; | 538 | pkt_next = target_list->next; |
534 | 539 | ||
535 | if (sg_alloc_table(&st, max_seg_cnt, GFP_KERNEL)) { | ||
536 | ret = -ENOMEM; | ||
537 | goto exit; | ||
538 | } | ||
539 | |||
540 | memset(&mmc_req, 0, sizeof(struct mmc_request)); | 540 | memset(&mmc_req, 0, sizeof(struct mmc_request)); |
541 | memset(&mmc_cmd, 0, sizeof(struct mmc_command)); | 541 | memset(&mmc_cmd, 0, sizeof(struct mmc_command)); |
542 | memset(&mmc_dat, 0, sizeof(struct mmc_data)); | 542 | memset(&mmc_dat, 0, sizeof(struct mmc_data)); |
543 | 543 | ||
544 | mmc_dat.sg = st.sgl; | 544 | mmc_dat.sg = sdiodev->sgtable.sgl; |
545 | mmc_dat.blksz = func_blk_sz; | 545 | mmc_dat.blksz = func_blk_sz; |
546 | mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; | 546 | mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; |
547 | mmc_cmd.opcode = SD_IO_RW_EXTENDED; | 547 | mmc_cmd.opcode = SD_IO_RW_EXTENDED; |
@@ -557,7 +557,7 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
557 | while (seg_sz) { | 557 | while (seg_sz) { |
558 | req_sz = 0; | 558 | req_sz = 0; |
559 | sg_cnt = 0; | 559 | sg_cnt = 0; |
560 | sgl = st.sgl; | 560 | sgl = sdiodev->sgtable.sgl; |
561 | /* prep sg table */ | 561 | /* prep sg table */ |
562 | while (pkt_next != (struct sk_buff *)target_list) { | 562 | while (pkt_next != (struct sk_buff *)target_list) { |
563 | pkt_data = pkt_next->data + pkt_offset; | 563 | pkt_data = pkt_next->data + pkt_offset; |
@@ -639,7 +639,7 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn, | |||
639 | } | 639 | } |
640 | 640 | ||
641 | exit: | 641 | exit: |
642 | sg_free_table(&st); | 642 | sg_init_table(sdiodev->sgtable.sgl, sdiodev->sgtable.orig_nents); |
643 | while ((pkt_next = __skb_dequeue(&local_list)) != NULL) | 643 | while ((pkt_next = __skb_dequeue(&local_list)) != NULL) |
644 | brcmu_pkt_buf_free_skb(pkt_next); | 644 | brcmu_pkt_buf_free_skb(pkt_next); |
645 | 645 | ||
@@ -863,6 +863,29 @@ int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn) | |||
863 | return 0; | 863 | return 0; |
864 | } | 864 | } |
865 | 865 | ||
866 | static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev) | ||
867 | { | ||
868 | uint nents; | ||
869 | int err; | ||
870 | |||
871 | if (!sdiodev->sg_support) | ||
872 | return; | ||
873 | |||
874 | nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE, brcmf_sdiod_txglomsz); | ||
875 | nents += (nents >> 4) + 1; | ||
876 | |||
877 | WARN_ON(nents > sdiodev->max_segment_count); | ||
878 | |||
879 | brcmf_dbg(TRACE, "nents=%d\n", nents); | ||
880 | err = sg_alloc_table(&sdiodev->sgtable, nents, GFP_KERNEL); | ||
881 | if (err < 0) { | ||
882 | brcmf_err("allocation failed: disable scatter-gather"); | ||
883 | sdiodev->sg_support = false; | ||
884 | } | ||
885 | |||
886 | sdiodev->txglomsz = brcmf_sdiod_txglomsz; | ||
887 | } | ||
888 | |||
866 | static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) | 889 | static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) |
867 | { | 890 | { |
868 | if (sdiodev->bus) { | 891 | if (sdiodev->bus) { |
@@ -880,6 +903,7 @@ static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) | |||
880 | sdio_disable_func(sdiodev->func[1]); | 903 | sdio_disable_func(sdiodev->func[1]); |
881 | sdio_release_host(sdiodev->func[1]); | 904 | sdio_release_host(sdiodev->func[1]); |
882 | 905 | ||
906 | sg_free_table(&sdiodev->sgtable); | ||
883 | sdiodev->sbwad = 0; | 907 | sdiodev->sbwad = 0; |
884 | 908 | ||
885 | return 0; | 909 | return 0; |
@@ -935,6 +959,11 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) | |||
935 | SG_MAX_SINGLE_ALLOC); | 959 | SG_MAX_SINGLE_ALLOC); |
936 | sdiodev->max_segment_size = host->max_seg_size; | 960 | sdiodev->max_segment_size = host->max_seg_size; |
937 | 961 | ||
962 | /* allocate scatter-gather table. sg support | ||
963 | * will be disabled upon allocation failure. | ||
964 | */ | ||
965 | brcmf_sdiod_sgtable_alloc(sdiodev); | ||
966 | |||
938 | /* try to attach to the target device */ | 967 | /* try to attach to the target device */ |
939 | sdiodev->bus = brcmf_sdio_probe(sdiodev); | 968 | sdiodev->bus = brcmf_sdio_probe(sdiodev); |
940 | if (!sdiodev->bus) { | 969 | if (!sdiodev->bus) { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index c894ee358153..b5ded8a57cb0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -113,8 +113,6 @@ struct rte_console { | |||
113 | #define BRCMF_TXBOUND 20 /* Default for max tx frames in | 113 | #define BRCMF_TXBOUND 20 /* Default for max tx frames in |
114 | one scheduling */ | 114 | one scheduling */ |
115 | 115 | ||
116 | #define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */ | ||
117 | |||
118 | #define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */ | 116 | #define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */ |
119 | 117 | ||
120 | #define MEMBLOCK 2048 /* Block size used for downloading | 118 | #define MEMBLOCK 2048 /* Block size used for downloading |
@@ -511,10 +509,6 @@ static const uint max_roundup = 512; | |||
511 | 509 | ||
512 | #define ALIGNMENT 4 | 510 | #define ALIGNMENT 4 |
513 | 511 | ||
514 | static int brcmf_sdio_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE; | ||
515 | module_param_named(txglomsz, brcmf_sdio_txglomsz, int, 0); | ||
516 | MODULE_PARM_DESC(txglomsz, "maximum tx packet chain size [SDIO]"); | ||
517 | |||
518 | enum brcmf_sdio_frmtype { | 512 | enum brcmf_sdio_frmtype { |
519 | BRCMF_SDIO_FT_NORMAL, | 513 | BRCMF_SDIO_FT_NORMAL, |
520 | BRCMF_SDIO_FT_SUPER, | 514 | BRCMF_SDIO_FT_SUPER, |
@@ -2321,7 +2315,7 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2321 | __skb_queue_head_init(&pktq); | 2315 | __skb_queue_head_init(&pktq); |
2322 | if (bus->txglom) | 2316 | if (bus->txglom) |
2323 | pkt_num = min_t(u8, bus->tx_max - bus->tx_seq, | 2317 | pkt_num = min_t(u8, bus->tx_max - bus->tx_seq, |
2324 | brcmf_sdio_txglomsz); | 2318 | bus->sdiodev->txglomsz); |
2325 | pkt_num = min_t(u32, pkt_num, | 2319 | pkt_num = min_t(u32, pkt_num, |
2326 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)); | 2320 | brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol)); |
2327 | spin_lock_bh(&bus->txqlock); | 2321 | spin_lock_bh(&bus->txqlock); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 5e53eb1b2ffa..3deab7959a0d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
@@ -180,6 +180,8 @@ struct brcmf_sdio_dev { | |||
180 | uint max_request_size; | 180 | uint max_request_size; |
181 | ushort max_segment_count; | 181 | ushort max_segment_count; |
182 | uint max_segment_size; | 182 | uint max_segment_size; |
183 | uint txglomsz; | ||
184 | struct sg_table sgtable; | ||
183 | }; | 185 | }; |
184 | 186 | ||
185 | /* sdio core registers */ | 187 | /* sdio core registers */ |