aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2018-03-27 09:50:57 -0400
committerArnd Bergmann <arnd@arndb.de>2018-03-27 09:50:57 -0400
commitd0994465d0eaeab1627697d88eccfa32bbd39714 (patch)
tree82e29a2b9c514932b003dd950b93fa1c02fbafc7
parent3bea9c5885d923ab6b231c55f2bf6acaf648e316 (diff)
parent1320f76897c5e4893aff68d0bfc1797a5ba543ff (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.c144
-rw-r--r--include/soc/tegra/bpmp.h4
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}
71EXPORT_SYMBOL_GPL(tegra_bpmp_put); 71EXPORT_SYMBOL_GPL(tegra_bpmp_put);
72 72
73static int tegra_bpmp_channel_get_index(struct tegra_bpmp_channel *channel)
74{
75 return channel - channel->bpmp->channels;
76}
77
78static int 73static int
79tegra_bpmp_channel_get_thread_index(struct tegra_bpmp_channel *channel) 74tegra_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
98static struct tegra_bpmp_channel *
99tegra_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
110static struct tegra_bpmp_channel *
111tegra_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
118static struct tegra_bpmp_channel *
119tegra_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
126static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg) 89static 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
699static int tegra_bpmp_probe(struct platform_device *pdev) 662static 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);
846free_mbox: 828free_mbox:
847 mbox_free_channel(bpmp->mbox.channel); 829 mbox_free_channel(bpmp->mbox.channel);
848cleanup_channels: 830cleanup_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);
837cleanup_tx_channel:
838 tegra_bpmp_channel_cleanup(bpmp->tx_channel);
851free_rx: 839free_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);
853free_tx: 841free_tx:
@@ -858,18 +846,16 @@ free_tx:
858static const struct tegra_bpmp_soc tegra186_soc = { 846static 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;