summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Rice <rob.rice@broadcom.com>2016-11-14 13:26:03 -0500
committerJassi Brar <jaswinder.singh@linaro.org>2016-12-19 09:40:22 -0500
commit63bb50bdb997f4bede1b5f2d56645f393f7f39fb (patch)
treea9dc04c94d42199070b742e050db30d624c8e170
parent38ed49ed4a99942f1a340f4a82a5a8b492e3463b (diff)
mailbox: bcm-pdc: Performance improvements
Three changes to improve performance in the PDC driver: - disable and reenable interrupts while the interrupt handler is running - update rxin and txin descriptor indexes more efficiently - group receive descriptor context into a structure and keep context in a single array rather than five to improve locality of reference Signed-off-by: Rob Rice <rob.rice@broadcom.com> Reviewed-by: Andy Gospodarek <gospo@broadcom.com> Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
-rw-r--r--drivers/mailbox/bcm-pdc-mailbox.c85
1 files changed, 49 insertions, 36 deletions
diff --git a/drivers/mailbox/bcm-pdc-mailbox.c b/drivers/mailbox/bcm-pdc-mailbox.c
index e7dc1a227713..8c2aa7c9c27f 100644
--- a/drivers/mailbox/bcm-pdc-mailbox.c
+++ b/drivers/mailbox/bcm-pdc-mailbox.c
@@ -260,6 +260,27 @@ struct pdc_ring_alloc {
260 u32 size; /* ring allocation size in bytes */ 260 u32 size; /* ring allocation size in bytes */
261}; 261};
262 262
263/*
264 * context associated with a receive descriptor.
265 * @rxp_ctx: opaque context associated with frame that starts at each
266 * rx ring index.
267 * @dst_sg: Scatterlist used to form reply frames beginning at a given ring
268 * index. Retained in order to unmap each sg after reply is processed.
269 * @rxin_numd: Number of rx descriptors associated with the message that starts
270 * at a descriptor index. Not set for every index. For example,
271 * if descriptor index i points to a scatterlist with 4 entries,
272 * then the next three descriptor indexes don't have a value set.
273 * @resp_hdr: Virtual address of buffer used to catch DMA rx status
274 * @resp_hdr_daddr: physical address of DMA rx status buffer
275 */
276struct pdc_rx_ctx {
277 void *rxp_ctx;
278 struct scatterlist *dst_sg;
279 u32 rxin_numd;
280 void *resp_hdr;
281 dma_addr_t resp_hdr_daddr;
282};
283
263/* PDC state structure */ 284/* PDC state structure */
264struct pdc_state { 285struct pdc_state {
265 /* Index of the PDC whose state is in this structure instance */ 286 /* Index of the PDC whose state is in this structure instance */
@@ -377,11 +398,7 @@ struct pdc_state {
377 /* Index of next rx descriptor to post. */ 398 /* Index of next rx descriptor to post. */
378 u32 rxout; 399 u32 rxout;
379 400
380 /* 401 struct pdc_rx_ctx rx_ctx[PDC_RING_ENTRIES];
381 * opaque context associated with frame that starts at each
382 * rx ring index.
383 */
384 void *rxp_ctx[PDC_RING_ENTRIES];
385 402
386 /* 403 /*
387 * Scatterlists used to form request and reply frames beginning at a 404 * Scatterlists used to form request and reply frames beginning at a
@@ -389,18 +406,6 @@ struct pdc_state {
389 * is processed 406 * is processed
390 */ 407 */
391 struct scatterlist *src_sg[PDC_RING_ENTRIES]; 408 struct scatterlist *src_sg[PDC_RING_ENTRIES];
392 struct scatterlist *dst_sg[PDC_RING_ENTRIES];
393
394 /*
395 * Number of rx descriptors associated with the message that starts
396 * at this descriptor index. Not set for every index. For example,
397 * if descriptor index i points to a scatterlist with 4 entries, then
398 * the next three descriptor indexes don't have a value set.
399 */
400 u32 rxin_numd[PDC_RING_ENTRIES];
401
402 void *resp_hdr[PDC_RING_ENTRIES];
403 dma_addr_t resp_hdr_daddr[PDC_RING_ENTRIES];
404 409
405 struct dentry *debugfs_stats; /* debug FS stats file for this PDC */ 410 struct dentry *debugfs_stats; /* debug FS stats file for this PDC */
406 411
@@ -591,11 +596,11 @@ pdc_receive_one(struct pdc_state *pdcs)
591 struct brcm_message mssg; 596 struct brcm_message mssg;
592 u32 len, rx_status; 597 u32 len, rx_status;
593 u32 num_frags; 598 u32 num_frags;
594 int i;
595 u8 *resp_hdr; /* virtual addr of start of resp message DMA header */ 599 u8 *resp_hdr; /* virtual addr of start of resp message DMA header */
596 u32 frags_rdy; /* number of fragments ready to read */ 600 u32 frags_rdy; /* number of fragments ready to read */
597 u32 rx_idx; /* ring index of start of receive frame */ 601 u32 rx_idx; /* ring index of start of receive frame */
598 dma_addr_t resp_hdr_daddr; 602 dma_addr_t resp_hdr_daddr;
603 struct pdc_rx_ctx *rx_ctx;
599 604
600 mbc = &pdcs->mbc; 605 mbc = &pdcs->mbc;
601 chan = &mbc->chans[0]; 606 chan = &mbc->chans[0];
@@ -607,7 +612,8 @@ pdc_receive_one(struct pdc_state *pdcs)
607 * to read. 612 * to read.
608 */ 613 */
609 frags_rdy = NRXDACTIVE(pdcs->rxin, pdcs->last_rx_curr, pdcs->nrxpost); 614 frags_rdy = NRXDACTIVE(pdcs->rxin, pdcs->last_rx_curr, pdcs->nrxpost);
610 if ((frags_rdy == 0) || (frags_rdy < pdcs->rxin_numd[pdcs->rxin])) 615 if ((frags_rdy == 0) ||
616 (frags_rdy < pdcs->rx_ctx[pdcs->rxin].rxin_numd))
611 /* No response ready */ 617 /* No response ready */
612 return -EAGAIN; 618 return -EAGAIN;
613 619
@@ -617,24 +623,23 @@ pdc_receive_one(struct pdc_state *pdcs)
617 dma_unmap_sg(dev, pdcs->src_sg[pdcs->txin], 623 dma_unmap_sg(dev, pdcs->src_sg[pdcs->txin],
618 sg_nents(pdcs->src_sg[pdcs->txin]), DMA_TO_DEVICE); 624 sg_nents(pdcs->src_sg[pdcs->txin]), DMA_TO_DEVICE);
619 625
620 for (i = 0; i < num_frags; i++) 626 pdcs->txin = (pdcs->txin + num_frags) & pdcs->ntxpost;
621 pdcs->txin = NEXTTXD(pdcs->txin, pdcs->ntxpost);
622 627
623 dev_dbg(dev, "PDC %u reclaimed %d tx descriptors", 628 dev_dbg(dev, "PDC %u reclaimed %d tx descriptors",
624 pdcs->pdc_idx, num_frags); 629 pdcs->pdc_idx, num_frags);
625 630
626 rx_idx = pdcs->rxin; 631 rx_idx = pdcs->rxin;
627 num_frags = pdcs->rxin_numd[rx_idx]; 632 rx_ctx = &pdcs->rx_ctx[rx_idx];
633 num_frags = rx_ctx->rxin_numd;
628 /* Return opaque context with result */ 634 /* Return opaque context with result */
629 mssg.ctx = pdcs->rxp_ctx[rx_idx]; 635 mssg.ctx = rx_ctx->rxp_ctx;
630 pdcs->rxp_ctx[rx_idx] = NULL; 636 rx_ctx->rxp_ctx = NULL;
631 resp_hdr = pdcs->resp_hdr[rx_idx]; 637 resp_hdr = rx_ctx->resp_hdr;
632 resp_hdr_daddr = pdcs->resp_hdr_daddr[rx_idx]; 638 resp_hdr_daddr = rx_ctx->resp_hdr_daddr;
633 dma_unmap_sg(dev, pdcs->dst_sg[rx_idx], 639 dma_unmap_sg(dev, rx_ctx->dst_sg, sg_nents(rx_ctx->dst_sg),
634 sg_nents(pdcs->dst_sg[rx_idx]), DMA_FROM_DEVICE); 640 DMA_FROM_DEVICE);
635 641
636 for (i = 0; i < num_frags; i++) 642 pdcs->rxin = (pdcs->rxin + num_frags) & pdcs->nrxpost;
637 pdcs->rxin = NEXTRXD(pdcs->rxin, pdcs->nrxpost);
638 643
639 dev_dbg(dev, "PDC %u reclaimed %d rx descriptors", 644 dev_dbg(dev, "PDC %u reclaimed %d rx descriptors",
640 pdcs->pdc_idx, num_frags); 645 pdcs->pdc_idx, num_frags);
@@ -826,6 +831,7 @@ static int pdc_rx_list_init(struct pdc_state *pdcs, struct scatterlist *dst_sg,
826 u32 rx_pkt_cnt = 1; /* Adding a single rx buffer */ 831 u32 rx_pkt_cnt = 1; /* Adding a single rx buffer */
827 dma_addr_t daddr; 832 dma_addr_t daddr;
828 void *vaddr; 833 void *vaddr;
834 struct pdc_rx_ctx *rx_ctx;
829 835
830 rx_avail = pdcs->nrxpost - NRXDACTIVE(pdcs->rxin, pdcs->rxout, 836 rx_avail = pdcs->nrxpost - NRXDACTIVE(pdcs->rxin, pdcs->rxout,
831 pdcs->nrxpost); 837 pdcs->nrxpost);
@@ -849,15 +855,16 @@ static int pdc_rx_list_init(struct pdc_state *pdcs, struct scatterlist *dst_sg,
849 855
850 /* This is always the first descriptor in the receive sequence */ 856 /* This is always the first descriptor in the receive sequence */
851 flags = D64_CTRL1_SOF; 857 flags = D64_CTRL1_SOF;
852 pdcs->rxin_numd[pdcs->rx_msg_start] = 1; 858 pdcs->rx_ctx[pdcs->rx_msg_start].rxin_numd = 1;
853 859
854 if (unlikely(pdcs->rxout == (pdcs->nrxd - 1))) 860 if (unlikely(pdcs->rxout == (pdcs->nrxd - 1)))
855 flags |= D64_CTRL1_EOT; 861 flags |= D64_CTRL1_EOT;
856 862
857 pdcs->rxp_ctx[pdcs->rxout] = ctx; 863 rx_ctx = &pdcs->rx_ctx[pdcs->rxout];
858 pdcs->dst_sg[pdcs->rxout] = dst_sg; 864 rx_ctx->rxp_ctx = ctx;
859 pdcs->resp_hdr[pdcs->rxout] = vaddr; 865 rx_ctx->dst_sg = dst_sg;
860 pdcs->resp_hdr_daddr[pdcs->rxout] = daddr; 866 rx_ctx->resp_hdr = vaddr;
867 rx_ctx->resp_hdr_daddr = daddr;
861 pdc_build_rxd(pdcs, daddr, pdcs->pdc_resp_hdr_len, flags); 868 pdc_build_rxd(pdcs, daddr, pdcs->pdc_resp_hdr_len, flags);
862 return PDC_SUCCESS; 869 return PDC_SUCCESS;
863} 870}
@@ -925,7 +932,7 @@ static int pdc_rx_list_sg_add(struct pdc_state *pdcs, struct scatterlist *sg)
925 desc_w++; 932 desc_w++;
926 sg = sg_next(sg); 933 sg = sg_next(sg);
927 } 934 }
928 pdcs->rxin_numd[pdcs->rx_msg_start] += desc_w; 935 pdcs->rx_ctx[pdcs->rx_msg_start].rxin_numd += desc_w;
929 936
930 return PDC_SUCCESS; 937 return PDC_SUCCESS;
931} 938}
@@ -954,6 +961,9 @@ static irqreturn_t pdc_irq_handler(int irq, void *data)
954 /* Clear interrupt flags in device */ 961 /* Clear interrupt flags in device */
955 iowrite32(intstatus, pdcs->pdc_reg_vbase + PDC_INTSTATUS_OFFSET); 962 iowrite32(intstatus, pdcs->pdc_reg_vbase + PDC_INTSTATUS_OFFSET);
956 963
964 /* Disable interrupts until soft handler runs */
965 iowrite32(0, pdcs->pdc_reg_vbase + PDC_INTMASK_OFFSET);
966
957 /* Wakeup IRQ thread */ 967 /* Wakeup IRQ thread */
958 if (likely(pdcs && (irq == pdcs->pdc_irq) && 968 if (likely(pdcs && (irq == pdcs->pdc_irq) &&
959 (intstatus & PDC_INTMASK))) { 969 (intstatus & PDC_INTMASK))) {
@@ -971,6 +981,9 @@ static void pdc_tasklet_cb(unsigned long data)
971 rx_int = test_and_clear_bit(PDC_RCVINT_0, &pdcs->intstatus); 981 rx_int = test_and_clear_bit(PDC_RCVINT_0, &pdcs->intstatus);
972 if (likely(pdcs && rx_int)) 982 if (likely(pdcs && rx_int))
973 pdc_receive(pdcs); 983 pdc_receive(pdcs);
984
985 /* reenable interrupts */
986 iowrite32(PDC_INTMASK, pdcs->pdc_reg_vbase + PDC_INTMASK_OFFSET);
974} 987}
975 988
976/** 989/**