diff options
author | Arnd Bergmann <arnd@arndb.de> | 2018-03-27 09:50:57 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2018-03-27 09:50:57 -0400 |
commit | d0994465d0eaeab1627697d88eccfa32bbd39714 (patch) | |
tree | 82e29a2b9c514932b003dd950b93fa1c02fbafc7 | |
parent | 3bea9c5885d923ab6b231c55f2bf6acaf648e316 (diff) | |
parent | 1320f76897c5e4893aff68d0bfc1797a5ba543ff (diff) |
Merge tag 'tegra-for-4.17-firmware' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/drivers
Pull "firmware: Changes for v4.17-rc1" from Thierry Reding:
These changes are rather small, with just a fix for a return value check
and some preparatory work for Tegra194 BPMP support.
* tag 'tegra-for-4.17-firmware' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
firmware: tegra: adjust tested variable
firmware: tegra: Simplify channel management
-rw-r--r-- | drivers/firmware/tegra/bpmp.c | 144 | ||||
-rw-r--r-- | include/soc/tegra/bpmp.h | 4 |
2 files changed, 67 insertions, 81 deletions
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c index a7f461f2e650..14a456afa379 100644 --- a/drivers/firmware/tegra/bpmp.c +++ b/drivers/firmware/tegra/bpmp.c | |||
@@ -70,57 +70,20 @@ void tegra_bpmp_put(struct tegra_bpmp *bpmp) | |||
70 | } | 70 | } |
71 | EXPORT_SYMBOL_GPL(tegra_bpmp_put); | 71 | EXPORT_SYMBOL_GPL(tegra_bpmp_put); |
72 | 72 | ||
73 | static int tegra_bpmp_channel_get_index(struct tegra_bpmp_channel *channel) | ||
74 | { | ||
75 | return channel - channel->bpmp->channels; | ||
76 | } | ||
77 | |||
78 | static int | 73 | static int |
79 | tegra_bpmp_channel_get_thread_index(struct tegra_bpmp_channel *channel) | 74 | tegra_bpmp_channel_get_thread_index(struct tegra_bpmp_channel *channel) |
80 | { | 75 | { |
81 | struct tegra_bpmp *bpmp = channel->bpmp; | 76 | struct tegra_bpmp *bpmp = channel->bpmp; |
82 | unsigned int offset, count; | 77 | unsigned int count; |
83 | int index; | 78 | int index; |
84 | 79 | ||
85 | offset = bpmp->soc->channels.thread.offset; | ||
86 | count = bpmp->soc->channels.thread.count; | 80 | count = bpmp->soc->channels.thread.count; |
87 | 81 | ||
88 | index = tegra_bpmp_channel_get_index(channel); | 82 | index = channel - channel->bpmp->threaded_channels; |
89 | if (index < 0) | 83 | if (index < 0 || index >= count) |
90 | return index; | ||
91 | |||
92 | if (index < offset || index >= offset + count) | ||
93 | return -EINVAL; | 84 | return -EINVAL; |
94 | 85 | ||
95 | return index - offset; | 86 | return index; |
96 | } | ||
97 | |||
98 | static struct tegra_bpmp_channel * | ||
99 | tegra_bpmp_channel_get_thread(struct tegra_bpmp *bpmp, unsigned int index) | ||
100 | { | ||
101 | unsigned int offset = bpmp->soc->channels.thread.offset; | ||
102 | unsigned int count = bpmp->soc->channels.thread.count; | ||
103 | |||
104 | if (index >= count) | ||
105 | return NULL; | ||
106 | |||
107 | return &bpmp->channels[offset + index]; | ||
108 | } | ||
109 | |||
110 | static struct tegra_bpmp_channel * | ||
111 | tegra_bpmp_channel_get_tx(struct tegra_bpmp *bpmp) | ||
112 | { | ||
113 | unsigned int offset = bpmp->soc->channels.cpu_tx.offset; | ||
114 | |||
115 | return &bpmp->channels[offset + smp_processor_id()]; | ||
116 | } | ||
117 | |||
118 | static struct tegra_bpmp_channel * | ||
119 | tegra_bpmp_channel_get_rx(struct tegra_bpmp *bpmp) | ||
120 | { | ||
121 | unsigned int offset = bpmp->soc->channels.cpu_rx.offset; | ||
122 | |||
123 | return &bpmp->channels[offset]; | ||
124 | } | 87 | } |
125 | 88 | ||
126 | static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg) | 89 | static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg) |
@@ -271,11 +234,7 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq, | |||
271 | goto unlock; | 234 | goto unlock; |
272 | } | 235 | } |
273 | 236 | ||
274 | channel = tegra_bpmp_channel_get_thread(bpmp, index); | 237 | channel = &bpmp->threaded_channels[index]; |
275 | if (!channel) { | ||
276 | err = -EINVAL; | ||
277 | goto unlock; | ||
278 | } | ||
279 | 238 | ||
280 | if (!tegra_bpmp_master_free(channel)) { | 239 | if (!tegra_bpmp_master_free(channel)) { |
281 | err = -EBUSY; | 240 | err = -EBUSY; |
@@ -328,12 +287,18 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp, | |||
328 | if (!tegra_bpmp_message_valid(msg)) | 287 | if (!tegra_bpmp_message_valid(msg)) |
329 | return -EINVAL; | 288 | return -EINVAL; |
330 | 289 | ||
331 | channel = tegra_bpmp_channel_get_tx(bpmp); | 290 | channel = bpmp->tx_channel; |
291 | |||
292 | spin_lock(&bpmp->atomic_tx_lock); | ||
332 | 293 | ||
333 | err = tegra_bpmp_channel_write(channel, msg->mrq, MSG_ACK, | 294 | err = tegra_bpmp_channel_write(channel, msg->mrq, MSG_ACK, |
334 | msg->tx.data, msg->tx.size); | 295 | msg->tx.data, msg->tx.size); |
335 | if (err < 0) | 296 | if (err < 0) { |
297 | spin_unlock(&bpmp->atomic_tx_lock); | ||
336 | return err; | 298 | return err; |
299 | } | ||
300 | |||
301 | spin_unlock(&bpmp->atomic_tx_lock); | ||
337 | 302 | ||
338 | err = mbox_send_message(bpmp->mbox.channel, NULL); | 303 | err = mbox_send_message(bpmp->mbox.channel, NULL); |
339 | if (err < 0) | 304 | if (err < 0) |
@@ -607,7 +572,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data) | |||
607 | unsigned int i, count; | 572 | unsigned int i, count; |
608 | unsigned long *busy; | 573 | unsigned long *busy; |
609 | 574 | ||
610 | channel = tegra_bpmp_channel_get_rx(bpmp); | 575 | channel = bpmp->rx_channel; |
611 | count = bpmp->soc->channels.thread.count; | 576 | count = bpmp->soc->channels.thread.count; |
612 | busy = bpmp->threaded.busy; | 577 | busy = bpmp->threaded.busy; |
613 | 578 | ||
@@ -619,9 +584,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data) | |||
619 | for_each_set_bit(i, busy, count) { | 584 | for_each_set_bit(i, busy, count) { |
620 | struct tegra_bpmp_channel *channel; | 585 | struct tegra_bpmp_channel *channel; |
621 | 586 | ||
622 | channel = tegra_bpmp_channel_get_thread(bpmp, i); | 587 | channel = &bpmp->threaded_channels[i]; |
623 | if (!channel) | ||
624 | continue; | ||
625 | 588 | ||
626 | if (tegra_bpmp_master_acked(channel)) { | 589 | if (tegra_bpmp_master_acked(channel)) { |
627 | tegra_bpmp_channel_signal(channel); | 590 | tegra_bpmp_channel_signal(channel); |
@@ -698,7 +661,6 @@ static void tegra_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel) | |||
698 | 661 | ||
699 | static int tegra_bpmp_probe(struct platform_device *pdev) | 662 | static int tegra_bpmp_probe(struct platform_device *pdev) |
700 | { | 663 | { |
701 | struct tegra_bpmp_channel *channel; | ||
702 | struct tegra_bpmp *bpmp; | 664 | struct tegra_bpmp *bpmp; |
703 | unsigned int i; | 665 | unsigned int i; |
704 | char tag[32]; | 666 | char tag[32]; |
@@ -732,7 +694,7 @@ static int tegra_bpmp_probe(struct platform_device *pdev) | |||
732 | } | 694 | } |
733 | 695 | ||
734 | bpmp->rx.virt = gen_pool_dma_alloc(bpmp->rx.pool, 4096, &bpmp->rx.phys); | 696 | bpmp->rx.virt = gen_pool_dma_alloc(bpmp->rx.pool, 4096, &bpmp->rx.phys); |
735 | if (!bpmp->rx.pool) { | 697 | if (!bpmp->rx.virt) { |
736 | dev_err(&pdev->dev, "failed to allocate from RX pool\n"); | 698 | dev_err(&pdev->dev, "failed to allocate from RX pool\n"); |
737 | err = -ENOMEM; | 699 | err = -ENOMEM; |
738 | goto free_tx; | 700 | goto free_tx; |
@@ -758,24 +720,45 @@ static int tegra_bpmp_probe(struct platform_device *pdev) | |||
758 | goto free_rx; | 720 | goto free_rx; |
759 | } | 721 | } |
760 | 722 | ||
761 | bpmp->num_channels = bpmp->soc->channels.cpu_tx.count + | 723 | spin_lock_init(&bpmp->atomic_tx_lock); |
762 | bpmp->soc->channels.thread.count + | 724 | bpmp->tx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->tx_channel), |
763 | bpmp->soc->channels.cpu_rx.count; | 725 | GFP_KERNEL); |
726 | if (!bpmp->tx_channel) { | ||
727 | err = -ENOMEM; | ||
728 | goto free_rx; | ||
729 | } | ||
764 | 730 | ||
765 | bpmp->channels = devm_kcalloc(&pdev->dev, bpmp->num_channels, | 731 | bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel), |
766 | sizeof(*channel), GFP_KERNEL); | 732 | GFP_KERNEL); |
767 | if (!bpmp->channels) { | 733 | if (!bpmp->rx_channel) { |
768 | err = -ENOMEM; | 734 | err = -ENOMEM; |
769 | goto free_rx; | 735 | goto free_rx; |
770 | } | 736 | } |
771 | 737 | ||
772 | /* message channel initialization */ | 738 | bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count, |
773 | for (i = 0; i < bpmp->num_channels; i++) { | 739 | sizeof(*bpmp->threaded_channels), |
774 | struct tegra_bpmp_channel *channel = &bpmp->channels[i]; | 740 | GFP_KERNEL); |
741 | if (!bpmp->threaded_channels) { | ||
742 | err = -ENOMEM; | ||
743 | goto free_rx; | ||
744 | } | ||
775 | 745 | ||
776 | err = tegra_bpmp_channel_init(channel, bpmp, i); | 746 | err = tegra_bpmp_channel_init(bpmp->tx_channel, bpmp, |
747 | bpmp->soc->channels.cpu_tx.offset); | ||
748 | if (err < 0) | ||
749 | goto free_rx; | ||
750 | |||
751 | err = tegra_bpmp_channel_init(bpmp->rx_channel, bpmp, | ||
752 | bpmp->soc->channels.cpu_rx.offset); | ||
753 | if (err < 0) | ||
754 | goto cleanup_tx_channel; | ||
755 | |||
756 | for (i = 0; i < bpmp->threaded.count; i++) { | ||
757 | err = tegra_bpmp_channel_init( | ||
758 | &bpmp->threaded_channels[i], bpmp, | ||
759 | bpmp->soc->channels.thread.offset + i); | ||
777 | if (err < 0) | 760 | if (err < 0) |
778 | goto cleanup_channels; | 761 | goto cleanup_threaded_channels; |
779 | } | 762 | } |
780 | 763 | ||
781 | /* mbox registration */ | 764 | /* mbox registration */ |
@@ -788,15 +771,14 @@ static int tegra_bpmp_probe(struct platform_device *pdev) | |||
788 | if (IS_ERR(bpmp->mbox.channel)) { | 771 | if (IS_ERR(bpmp->mbox.channel)) { |
789 | err = PTR_ERR(bpmp->mbox.channel); | 772 | err = PTR_ERR(bpmp->mbox.channel); |
790 | dev_err(&pdev->dev, "failed to get HSP mailbox: %d\n", err); | 773 | dev_err(&pdev->dev, "failed to get HSP mailbox: %d\n", err); |
791 | goto cleanup_channels; | 774 | goto cleanup_threaded_channels; |
792 | } | 775 | } |
793 | 776 | ||
794 | /* reset message channels */ | 777 | /* reset message channels */ |
795 | for (i = 0; i < bpmp->num_channels; i++) { | 778 | tegra_bpmp_channel_reset(bpmp->tx_channel); |
796 | struct tegra_bpmp_channel *channel = &bpmp->channels[i]; | 779 | tegra_bpmp_channel_reset(bpmp->rx_channel); |
797 | 780 | for (i = 0; i < bpmp->threaded.count; i++) | |
798 | tegra_bpmp_channel_reset(channel); | 781 | tegra_bpmp_channel_reset(&bpmp->threaded_channels[i]); |
799 | } | ||
800 | 782 | ||
801 | err = tegra_bpmp_request_mrq(bpmp, MRQ_PING, | 783 | err = tegra_bpmp_request_mrq(bpmp, MRQ_PING, |
802 | tegra_bpmp_mrq_handle_ping, bpmp); | 784 | tegra_bpmp_mrq_handle_ping, bpmp); |
@@ -845,9 +827,15 @@ free_mrq: | |||
845 | tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp); | 827 | tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp); |
846 | free_mbox: | 828 | free_mbox: |
847 | mbox_free_channel(bpmp->mbox.channel); | 829 | mbox_free_channel(bpmp->mbox.channel); |
848 | cleanup_channels: | 830 | cleanup_threaded_channels: |
849 | while (i--) | 831 | for (i = 0; i < bpmp->threaded.count; i++) { |
850 | tegra_bpmp_channel_cleanup(&bpmp->channels[i]); | 832 | if (bpmp->threaded_channels[i].bpmp) |
833 | tegra_bpmp_channel_cleanup(&bpmp->threaded_channels[i]); | ||
834 | } | ||
835 | |||
836 | tegra_bpmp_channel_cleanup(bpmp->rx_channel); | ||
837 | cleanup_tx_channel: | ||
838 | tegra_bpmp_channel_cleanup(bpmp->tx_channel); | ||
851 | free_rx: | 839 | free_rx: |
852 | gen_pool_free(bpmp->rx.pool, (unsigned long)bpmp->rx.virt, 4096); | 840 | gen_pool_free(bpmp->rx.pool, (unsigned long)bpmp->rx.virt, 4096); |
853 | free_tx: | 841 | free_tx: |
@@ -858,18 +846,16 @@ free_tx: | |||
858 | static const struct tegra_bpmp_soc tegra186_soc = { | 846 | static const struct tegra_bpmp_soc tegra186_soc = { |
859 | .channels = { | 847 | .channels = { |
860 | .cpu_tx = { | 848 | .cpu_tx = { |
861 | .offset = 0, | 849 | .offset = 3, |
862 | .count = 6, | ||
863 | .timeout = 60 * USEC_PER_SEC, | 850 | .timeout = 60 * USEC_PER_SEC, |
864 | }, | 851 | }, |
865 | .thread = { | 852 | .thread = { |
866 | .offset = 6, | 853 | .offset = 0, |
867 | .count = 7, | 854 | .count = 3, |
868 | .timeout = 600 * USEC_PER_SEC, | 855 | .timeout = 600 * USEC_PER_SEC, |
869 | }, | 856 | }, |
870 | .cpu_rx = { | 857 | .cpu_rx = { |
871 | .offset = 13, | 858 | .offset = 13, |
872 | .count = 1, | ||
873 | .timeout = 0, | 859 | .timeout = 0, |
874 | }, | 860 | }, |
875 | }, | 861 | }, |
diff --git a/include/soc/tegra/bpmp.h b/include/soc/tegra/bpmp.h index aeae4466dd25..e69e4c4d80ae 100644 --- a/include/soc/tegra/bpmp.h +++ b/include/soc/tegra/bpmp.h | |||
@@ -75,8 +75,8 @@ struct tegra_bpmp { | |||
75 | struct mbox_chan *channel; | 75 | struct mbox_chan *channel; |
76 | } mbox; | 76 | } mbox; |
77 | 77 | ||
78 | struct tegra_bpmp_channel *channels; | 78 | spinlock_t atomic_tx_lock; |
79 | unsigned int num_channels; | 79 | struct tegra_bpmp_channel *tx_channel, *rx_channel, *threaded_channels; |
80 | 80 | ||
81 | struct { | 81 | struct { |
82 | unsigned long *allocated; | 82 | unsigned long *allocated; |