diff options
author | Rob Rice <rob.rice@broadcom.com> | 2016-11-14 13:26:01 -0500 |
---|---|---|
committer | Jassi Brar <jaswinder.singh@linaro.org> | 2016-12-19 09:40:21 -0500 |
commit | 8aef00f090bcbe5237c5a6628e7c000890267efe (patch) | |
tree | a388b78ba634615cbabcb38956c7c39040bcec83 /drivers/mailbox | |
parent | 7493cde34efc28641c295ee0d52ab9d790853c62 (diff) |
mailbox: bcm-pdc: Convert from threaded IRQ to tasklet
Previously used threaded IRQs in the PDC driver to defer
processing the rx DMA ring after getting an rx done interrupt.
Instead, use a tasklet at normal priority for deferred processing.
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>
Diffstat (limited to 'drivers/mailbox')
-rw-r--r-- | drivers/mailbox/bcm-pdc-mailbox.c | 57 |
1 files changed, 25 insertions, 32 deletions
diff --git a/drivers/mailbox/bcm-pdc-mailbox.c b/drivers/mailbox/bcm-pdc-mailbox.c index 7ed3f0247cb8..16e544018a68 100644 --- a/drivers/mailbox/bcm-pdc-mailbox.c +++ b/drivers/mailbox/bcm-pdc-mailbox.c | |||
@@ -285,6 +285,9 @@ struct pdc_state { | |||
285 | */ | 285 | */ |
286 | unsigned long intstatus; | 286 | unsigned long intstatus; |
287 | 287 | ||
288 | /* tasklet for deferred processing after DMA rx interrupt */ | ||
289 | struct tasklet_struct rx_tasklet; | ||
290 | |||
288 | /* Number of bytes of receive status prior to each rx frame */ | 291 | /* Number of bytes of receive status prior to each rx frame */ |
289 | u32 rx_status_len; | 292 | u32 rx_status_len; |
290 | /* Whether a BCM header is prepended to each frame */ | 293 | /* Whether a BCM header is prepended to each frame */ |
@@ -931,7 +934,7 @@ static int pdc_rx_list_sg_add(struct pdc_state *pdcs, struct scatterlist *sg) | |||
931 | /** | 934 | /** |
932 | * pdc_irq_handler() - Interrupt handler called in interrupt context. | 935 | * pdc_irq_handler() - Interrupt handler called in interrupt context. |
933 | * @irq: Interrupt number that has fired | 936 | * @irq: Interrupt number that has fired |
934 | * @cookie: PDC state for DMA engine that generated the interrupt | 937 | * @data: device struct for DMA engine that generated the interrupt |
935 | * | 938 | * |
936 | * We have to clear the device interrupt status flags here. So cache the | 939 | * We have to clear the device interrupt status flags here. So cache the |
937 | * status for later use in the thread function. Other than that, just return | 940 | * status for later use in the thread function. Other than that, just return |
@@ -940,9 +943,10 @@ static int pdc_rx_list_sg_add(struct pdc_state *pdcs, struct scatterlist *sg) | |||
940 | * Return: IRQ_WAKE_THREAD if interrupt is ours | 943 | * Return: IRQ_WAKE_THREAD if interrupt is ours |
941 | * IRQ_NONE otherwise | 944 | * IRQ_NONE otherwise |
942 | */ | 945 | */ |
943 | static irqreturn_t pdc_irq_handler(int irq, void *cookie) | 946 | static irqreturn_t pdc_irq_handler(int irq, void *data) |
944 | { | 947 | { |
945 | struct pdc_state *pdcs = cookie; | 948 | struct device *dev = (struct device *)data; |
949 | struct pdc_state *pdcs = dev_get_drvdata(dev); | ||
946 | u32 intstatus = ioread32(pdcs->pdc_reg_vbase + PDC_INTSTATUS_OFFSET); | 950 | u32 intstatus = ioread32(pdcs->pdc_reg_vbase + PDC_INTSTATUS_OFFSET); |
947 | 951 | ||
948 | if (likely(intstatus & PDC_RCVINTEN_0)) | 952 | if (likely(intstatus & PDC_RCVINTEN_0)) |
@@ -952,39 +956,22 @@ static irqreturn_t pdc_irq_handler(int irq, void *cookie) | |||
952 | iowrite32(intstatus, pdcs->pdc_reg_vbase + PDC_INTSTATUS_OFFSET); | 956 | iowrite32(intstatus, pdcs->pdc_reg_vbase + PDC_INTSTATUS_OFFSET); |
953 | 957 | ||
954 | /* Wakeup IRQ thread */ | 958 | /* Wakeup IRQ thread */ |
955 | if (likely(pdcs && (irq == pdcs->pdc_irq) && (intstatus & PDC_INTMASK))) | 959 | if (likely(pdcs && (irq == pdcs->pdc_irq) && |
956 | return IRQ_WAKE_THREAD; | 960 | (intstatus & PDC_INTMASK))) { |
957 | 961 | tasklet_schedule(&pdcs->rx_tasklet); | |
962 | return IRQ_HANDLED; | ||
963 | } | ||
958 | return IRQ_NONE; | 964 | return IRQ_NONE; |
959 | } | 965 | } |
960 | 966 | ||
961 | /** | 967 | static void pdc_tasklet_cb(unsigned long data) |
962 | * pdc_irq_thread() - Function invoked on deferred thread when data is available | ||
963 | * to receive. | ||
964 | * @irq: Interrupt number | ||
965 | * @cookie: PDC state for PDC that generated the interrupt | ||
966 | * | ||
967 | * On DMA rx complete, process as many SPU response messages as are available | ||
968 | * and send each to the mailbox client. | ||
969 | * | ||
970 | * Return: IRQ_HANDLED if we recognized and handled the interrupt | ||
971 | * IRQ_NONE otherwise | ||
972 | */ | ||
973 | static irqreturn_t pdc_irq_thread(int irq, void *cookie) | ||
974 | { | 968 | { |
975 | struct pdc_state *pdcs = cookie; | 969 | struct pdc_state *pdcs = (struct pdc_state *)data; |
976 | bool rx_int; | 970 | bool rx_int; |
977 | 971 | ||
978 | rx_int = test_and_clear_bit(PDC_RCVINT_0, &pdcs->intstatus); | 972 | rx_int = test_and_clear_bit(PDC_RCVINT_0, &pdcs->intstatus); |
979 | if (likely(pdcs && rx_int)) { | 973 | if (likely(pdcs && rx_int)) |
980 | dev_dbg(&pdcs->pdev->dev, | ||
981 | "%s() got irq %d with rx_int %s", | ||
982 | __func__, irq, rx_int ? "set" : "clear"); | ||
983 | |||
984 | pdc_receive(pdcs); | 974 | pdc_receive(pdcs); |
985 | return IRQ_HANDLED; | ||
986 | } | ||
987 | return IRQ_NONE; | ||
988 | } | 975 | } |
989 | 976 | ||
990 | /** | 977 | /** |
@@ -1416,11 +1403,11 @@ static int pdc_interrupts_init(struct pdc_state *pdcs) | |||
1416 | pdcs->pdc_irq = irq_of_parse_and_map(dn, 0); | 1403 | pdcs->pdc_irq = irq_of_parse_and_map(dn, 0); |
1417 | dev_dbg(dev, "pdc device %s irq %u for pdcs %p", | 1404 | dev_dbg(dev, "pdc device %s irq %u for pdcs %p", |
1418 | dev_name(dev), pdcs->pdc_irq, pdcs); | 1405 | dev_name(dev), pdcs->pdc_irq, pdcs); |
1419 | err = devm_request_threaded_irq(dev, pdcs->pdc_irq, | 1406 | |
1420 | pdc_irq_handler, | 1407 | err = devm_request_irq(dev, pdcs->pdc_irq, pdc_irq_handler, 0, |
1421 | pdc_irq_thread, 0, dev_name(dev), pdcs); | 1408 | dev_name(dev), dev); |
1422 | if (err) { | 1409 | if (err) { |
1423 | dev_err(dev, "threaded tx IRQ %u request failed with err %d\n", | 1410 | dev_err(dev, "IRQ %u request failed with err %d\n", |
1424 | pdcs->pdc_irq, err); | 1411 | pdcs->pdc_irq, err); |
1425 | return err; | 1412 | return err; |
1426 | } | 1413 | } |
@@ -1579,6 +1566,9 @@ static int pdc_probe(struct platform_device *pdev) | |||
1579 | 1566 | ||
1580 | pdc_hw_init(pdcs); | 1567 | pdc_hw_init(pdcs); |
1581 | 1568 | ||
1569 | /* Init tasklet for deferred DMA rx processing */ | ||
1570 | tasklet_init(&pdcs->rx_tasklet, pdc_tasklet_cb, (unsigned long) pdcs); | ||
1571 | |||
1582 | err = pdc_interrupts_init(pdcs); | 1572 | err = pdc_interrupts_init(pdcs); |
1583 | if (err) | 1573 | if (err) |
1584 | goto cleanup_buf_pool; | 1574 | goto cleanup_buf_pool; |
@@ -1595,6 +1585,7 @@ static int pdc_probe(struct platform_device *pdev) | |||
1595 | return PDC_SUCCESS; | 1585 | return PDC_SUCCESS; |
1596 | 1586 | ||
1597 | cleanup_buf_pool: | 1587 | cleanup_buf_pool: |
1588 | tasklet_kill(&pdcs->rx_tasklet); | ||
1598 | dma_pool_destroy(pdcs->rx_buf_pool); | 1589 | dma_pool_destroy(pdcs->rx_buf_pool); |
1599 | 1590 | ||
1600 | cleanup_ring_pool: | 1591 | cleanup_ring_pool: |
@@ -1610,6 +1601,8 @@ static int pdc_remove(struct platform_device *pdev) | |||
1610 | 1601 | ||
1611 | pdc_free_debugfs(); | 1602 | pdc_free_debugfs(); |
1612 | 1603 | ||
1604 | tasklet_kill(&pdcs->rx_tasklet); | ||
1605 | |||
1613 | pdc_hw_disable(pdcs); | 1606 | pdc_hw_disable(pdcs); |
1614 | 1607 | ||
1615 | mbox_controller_unregister(&pdcs->mbc); | 1608 | mbox_controller_unregister(&pdcs->mbc); |