diff options
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 8ad1dcca..2ba160dd 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -1790,23 +1790,51 @@ int gk20a_submit_channel_gpfifo(struct channel_gk20a *c, | |||
1790 | start = c->gpfifo.put; | 1790 | start = c->gpfifo.put; |
1791 | end = start + num_entries; | 1791 | end = start + num_entries; |
1792 | 1792 | ||
1793 | if (end > c->gpfifo.entry_num) { | 1793 | /* |
1794 | int length0 = c->gpfifo.entry_num - start; | 1794 | * This WAR is in place for handling invalid simulation GPFIFO entries |
1795 | int length1 = num_entries - length0; | 1795 | * passed to us from userspace. This will be removed once these invalid |
1796 | * GPFIFO entries are handled in userspace. | ||
1797 | */ | ||
1798 | if (tegra_platform_is_linsim()) { | ||
1799 | int i; | ||
1800 | struct gpfifo *gpfifo_entries = c->gpfifo.mem.cpu_va; | ||
1796 | 1801 | ||
1797 | memcpy((struct gpfifo *)c->gpfifo.mem.cpu_va + start, gpfifo, | 1802 | for (i = 0; i < num_entries; i++) { |
1798 | length0 * sizeof(*gpfifo)); | 1803 | int index = (start + i) & (c->gpfifo.entry_num - 1); |
1799 | 1804 | ||
1800 | memcpy((struct gpfifo *)c->gpfifo.mem.cpu_va, gpfifo + length0, | 1805 | /* Copy the entry... */ |
1801 | length1 * sizeof(*gpfifo)); | 1806 | gpfifo_entries[index].entry0 = gpfifo[i].entry0; |
1807 | gpfifo_entries[index].entry1 = gpfifo[i].entry1; | ||
1802 | 1808 | ||
1803 | trace_write_pushbuffer_range(c, gpfifo, length0); | 1809 | /* |
1804 | trace_write_pushbuffer_range(c, gpfifo + length0, length1); | 1810 | * And here's the WAR: if the length is 0 clear the |
1811 | * opcode field (bottom 8 bits). | ||
1812 | */ | ||
1813 | if (!pbdma_gp_entry1_length_v(gpfifo[i].entry1)) | ||
1814 | gpfifo_entries[index].entry1 &= ~0xff; | ||
1815 | |||
1816 | trace_write_pushbuffer_range(c, gpfifo, num_entries); | ||
1817 | } | ||
1805 | } else { | 1818 | } else { |
1806 | memcpy((struct gpfifo *)c->gpfifo.mem.cpu_va + start, gpfifo, | 1819 | if (end > c->gpfifo.entry_num) { |
1807 | num_entries * sizeof(*gpfifo)); | 1820 | int length0 = c->gpfifo.entry_num - start; |
1821 | int length1 = num_entries - length0; | ||
1808 | 1822 | ||
1809 | trace_write_pushbuffer_range(c, gpfifo, num_entries); | 1823 | memcpy((struct gpfifo *)c->gpfifo.mem.cpu_va + start, |
1824 | gpfifo, length0 * sizeof(*gpfifo)); | ||
1825 | |||
1826 | memcpy((struct gpfifo *)c->gpfifo.mem.cpu_va, | ||
1827 | gpfifo + length0, length1 * sizeof(*gpfifo)); | ||
1828 | |||
1829 | trace_write_pushbuffer_range(c, gpfifo, length0); | ||
1830 | trace_write_pushbuffer_range(c, gpfifo + length0, | ||
1831 | length1); | ||
1832 | } else { | ||
1833 | memcpy((struct gpfifo *)c->gpfifo.mem.cpu_va + start, | ||
1834 | gpfifo, num_entries * sizeof(*gpfifo)); | ||
1835 | |||
1836 | trace_write_pushbuffer_range(c, gpfifo, num_entries); | ||
1837 | } | ||
1810 | } | 1838 | } |
1811 | c->gpfifo.put = (c->gpfifo.put + num_entries) & | 1839 | c->gpfifo.put = (c->gpfifo.put + num_entries) & |
1812 | (c->gpfifo.entry_num - 1); | 1840 | (c->gpfifo.entry_num - 1); |