summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c52
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);