Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/nvc0-/gr: generate grctx template at init time, not first context ctor

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>

+463 -607
+229 -40
drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
··· 35 35 while (nv_rd32(priv, 0x400700) & 2) {} 36 36 } 37 37 38 + int 39 + nvc0_grctx_init(struct drm_device *priv, struct nvc0_graph_priv *oprv, 40 + struct nvc0_grctx *info) 41 + { 42 + struct nouveau_gpuobj *chan; 43 + u32 size = (0x80000 + oprv->size + 4095) & ~4095; 44 + int ret, i; 45 + 46 + /* allocate memory to for a "channel", which we'll use to generate 47 + * the default context values 48 + */ 49 + ret = nouveau_gpuobj_new(priv, NULL, size, 0x1000, 50 + NVOBJ_FLAG_ZERO_ALLOC, &info->chan); 51 + chan = info->chan; 52 + if (ret) { 53 + NV_ERROR(priv, "failed to allocate channel memory, %d\n", ret); 54 + return ret; 55 + } 56 + 57 + /* PGD pointer */ 58 + nv_wo32(chan, 0x0200, lower_32_bits(chan->addr + 0x1000)); 59 + nv_wo32(chan, 0x0204, upper_32_bits(chan->addr + 0x1000)); 60 + nv_wo32(chan, 0x0208, 0xffffffff); 61 + nv_wo32(chan, 0x020c, 0x000000ff); 62 + 63 + /* PGT[0] pointer */ 64 + nv_wo32(chan, 0x1000, 0x00000000); 65 + nv_wo32(chan, 0x1004, 0x00000001 | (chan->addr + 0x2000) >> 8); 66 + 67 + /* identity-map the whole "channel" into its own vm */ 68 + for (i = 0; i < size / 4096; i++) { 69 + u64 addr = ((chan->addr + (i * 4096)) >> 8) | 1; 70 + nv_wo32(chan, 0x2000 + (i * 8), lower_32_bits(addr)); 71 + nv_wo32(chan, 0x2004 + (i * 8), upper_32_bits(addr)); 72 + } 73 + 74 + /* context pointer (virt) */ 75 + nv_wo32(chan, 0x0210, 0x00080004); 76 + nv_wo32(chan, 0x0214, 0x00000000); 77 + 78 + nvimem_flush(priv); 79 + 80 + nv_wr32(priv, 0x100cb8, (chan->addr + 0x1000) >> 8); 81 + nv_wr32(priv, 0x100cbc, 0x80000001); 82 + nv_wait(priv, 0x100c80, 0x00008000, 0x00008000); 83 + 84 + /* setup default state for mmio list construction */ 85 + info->dev = priv; 86 + info->data = oprv->mmio_data; 87 + info->mmio = oprv->mmio_list; 88 + info->addr = 0x2000 + (i * 8); 89 + info->priv = oprv; 90 + info->buffer_nr = 0; 91 + 92 + if (oprv->firmware) { 93 + nv_wr32(priv, 0x409840, 0x00000030); 94 + nv_wr32(priv, 0x409500, 0x80000000 | chan->addr >> 12); 95 + nv_wr32(priv, 0x409504, 0x00000003); 96 + if (!nv_wait(priv, 0x409800, 0x00000010, 0x00000010)) 97 + NV_ERROR(priv, "load_ctx timeout\n"); 98 + 99 + nv_wo32(chan, 0x8001c, 1); 100 + nv_wo32(chan, 0x80020, 0); 101 + nv_wo32(chan, 0x80028, 0); 102 + nv_wo32(chan, 0x8002c, 0); 103 + nvimem_flush(priv); 104 + return 0; 105 + } 106 + 107 + /* HUB_FUC(SET_CHAN) */ 108 + nv_wr32(priv, 0x409840, 0x80000000); 109 + nv_wr32(priv, 0x409500, 0x80000000 | chan->addr >> 12); 110 + nv_wr32(priv, 0x409504, 0x00000001); 111 + if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) { 112 + NV_ERROR(priv, "HUB_SET_CHAN timeout\n"); 113 + nvc0_graph_ctxctl_debug(priv); 114 + nouveau_gpuobj_ref(NULL, &info->chan); 115 + return -EBUSY; 116 + } 117 + 118 + return 0; 119 + } 120 + 121 + void 122 + nvc0_grctx_data(struct nvc0_grctx *info, u32 size, u32 align, u32 access) 123 + { 124 + info->buffer[info->buffer_nr] = info->addr; 125 + info->buffer[info->buffer_nr] += (align - 1); 126 + info->buffer[info->buffer_nr] &= ~(align - 1); 127 + info->addr = info->buffer[info->buffer_nr++] + size; 128 + 129 + info->data->size = size; 130 + info->data->align = align; 131 + info->data->access = access; 132 + info->data++; 133 + } 134 + 135 + void 136 + nvc0_grctx_mmio(struct nvc0_grctx *info, u32 addr, u32 data, u32 shift, u32 buf) 137 + { 138 + info->mmio->addr = addr; 139 + info->mmio->data = data; 140 + info->mmio->shift = shift; 141 + info->mmio->buffer = buf; 142 + info->mmio++; 143 + 144 + if (shift) 145 + data |= info->buffer[buf] >> shift; 146 + nv_wr32(info->dev, addr, data); 147 + } 148 + 149 + int 150 + nvc0_grctx_fini(struct nvc0_grctx *info) 151 + { 152 + struct nvc0_graph_priv *priv = info->priv; 153 + int i; 154 + 155 + if (priv->firmware) { 156 + nv_wr32(info->dev, 0x409840, 0x00000003); 157 + nv_wr32(info->dev, 0x409500, 0x80000000 | info->chan->addr >> 12); 158 + nv_wr32(info->dev, 0x409504, 0x00000009); 159 + if (!nv_wait(info->dev, 0x409800, 0x00000001, 0x00000000)) { 160 + NV_ERROR(info->dev, "unload_ctx timeout\n"); 161 + return -EBUSY; 162 + } 163 + 164 + goto save; 165 + } 166 + 167 + /* HUB_FUC(CTX_SAVE) */ 168 + nv_wr32(info->dev, 0x409840, 0x80000000); 169 + nv_wr32(info->dev, 0x409500, 0x80000000 | info->chan->addr >> 12); 170 + nv_wr32(info->dev, 0x409504, 0x00000002); 171 + if (!nv_wait(info->dev, 0x409800, 0x80000000, 0x80000000)) { 172 + NV_ERROR(info->dev, "HUB_CTX_SAVE timeout\n"); 173 + nvc0_graph_ctxctl_debug(info->dev); 174 + return -EBUSY; 175 + } 176 + 177 + save: 178 + priv->data = kmalloc(priv->size, GFP_KERNEL); 179 + if (priv->data) { 180 + for (i = 0; i < priv->size; i += 4) 181 + priv->data[i / 4] = nv_ro32(info->chan, 0x80000 + i); 182 + } 183 + 184 + nouveau_gpuobj_ref(NULL, &info->chan); 185 + return priv->data ? 0 : -ENOMEM; 186 + } 187 + 38 188 static void 39 189 nvc0_grctx_generate_9097(struct drm_device *priv) 40 190 { ··· 1929 1779 } 1930 1780 1931 1781 int 1932 - nvc0_grctx_generate(struct nouveau_channel *chan) 1782 + nvc0_grctx_generate(struct drm_device *priv) 1933 1783 { 1934 - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; 1935 - struct nvc0_graph_priv *oprv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); 1936 - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; 1937 - struct drm_device *priv = chan->dev; 1938 - int i, gpc, tp, id; 1784 + struct drm_nouveau_private *dev_priv = priv->dev_private; 1785 + struct nvc0_graph_priv *oprv = nv_engine(priv, NVOBJ_ENGINE_GR); 1786 + struct nvc0_grctx info; 1787 + int ret, i, gpc, tpc, id; 1939 1788 u32 fermi = nvc0_graph_class(priv); 1940 1789 u32 r000260, tmp; 1790 + 1791 + ret = nvc0_grctx_init(priv, oprv, &info); 1792 + if (ret) 1793 + return ret; 1941 1794 1942 1795 r000260 = nv_rd32(priv, 0x000260); 1943 1796 nv_wr32(priv, 0x000260, r000260 & ~1); ··· 1961 1808 1962 1809 nv_wr32(priv, 0x404154, 0x00000000); 1963 1810 1964 - /* fuc "mmio list" writes */ 1965 - for (i = 0; i < grch->mmio_nr * 8; i += 8) { 1966 - u32 reg = nv_ro32(grch->mmio, i + 0); 1967 - nv_wr32(priv, reg, nv_ro32(grch->mmio, i + 4)); 1811 + /* generate per-context mmio list data */ 1812 + mmio_data(0x002000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); 1813 + mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); 1814 + mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW); 1815 + mmio_list(0x408004, 0x00000000, 8, 0); 1816 + mmio_list(0x408008, 0x80000018, 0, 0); 1817 + mmio_list(0x40800c, 0x00000000, 8, 1); 1818 + mmio_list(0x408010, 0x80000000, 0, 0); 1819 + mmio_list(0x418810, 0x80000000, 12, 2); 1820 + mmio_list(0x419848, 0x10000000, 12, 2); 1821 + mmio_list(0x419004, 0x00000000, 8, 1); 1822 + mmio_list(0x419008, 0x00000000, 0, 0); 1823 + mmio_list(0x418808, 0x00000000, 8, 0); 1824 + mmio_list(0x41880c, 0x80000018, 0, 0); 1825 + if (dev_priv->chipset != 0xc1) { 1826 + tmp = 0x02180000; 1827 + mmio_list(0x405830, tmp, 0, 0); 1828 + for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { 1829 + for (tpc = 0; tpc < oprv->tpc_nr[gpc]; tpc++) { 1830 + u32 reg = TPC_UNIT(gpc, tpc, 0x0520); 1831 + mmio_list(reg, tmp, 0, 0); 1832 + tmp += 0x0324; 1833 + } 1834 + } 1835 + } else { 1836 + tmp = 0x02180000; 1837 + mmio_list(0x405830, 0x00000218 | tmp, 0, 0); 1838 + mmio_list(0x4064c4, 0x0086ffff, 0, 0); 1839 + for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { 1840 + for (tpc = 0; tpc < oprv->tpc_nr[gpc]; tpc++) { 1841 + u32 reg = TPC_UNIT(gpc, tpc, 0x0520); 1842 + mmio_list(reg, 0x10000000 | tmp, 0, 0); 1843 + tmp += 0x0324; 1844 + } 1845 + for (tpc = 0; tpc < oprv->tpc_nr[gpc]; tpc++) { 1846 + u32 reg = TPC_UNIT(gpc, tpc, 0x0544); 1847 + mmio_list(reg, tmp, 0, 0); 1848 + tmp += 0x0324; 1849 + } 1850 + } 1968 1851 } 1969 1852 1970 - for (tp = 0, id = 0; tp < 4; tp++) { 1853 + for (tpc = 0, id = 0; tpc < 4; tpc++) { 1971 1854 for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { 1972 - if (tp < oprv->tpc_nr[gpc]) { 1973 - nv_wr32(priv, TPC_UNIT(gpc, tp, 0x698), id); 1974 - nv_wr32(priv, TPC_UNIT(gpc, tp, 0x4e8), id); 1975 - nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tp * 4), id); 1976 - nv_wr32(priv, TPC_UNIT(gpc, tp, 0x088), id); 1855 + if (tpc < oprv->tpc_nr[gpc]) { 1856 + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x698), id); 1857 + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x4e8), id); 1858 + nv_wr32(priv, GPC_UNIT(gpc, 0x0c10 + tpc * 4), id); 1859 + nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x088), id); 1977 1860 id++; 1978 1861 } 1979 1862 ··· 2032 1843 nv_wr32(priv, 0x40587c, 0x00000000); 2033 1844 2034 1845 if (1) { 2035 - u8 tpnr[GPC_MAX], data[TPC_MAX]; 1846 + u8 tpcnr[GPC_MAX], data[TPC_MAX]; 2036 1847 2037 - memcpy(tpnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); 1848 + memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); 2038 1849 memset(data, 0x1f, sizeof(data)); 2039 1850 2040 1851 gpc = -1; 2041 - for (tp = 0; tp < oprv->tpc_total; tp++) { 1852 + for (tpc = 0; tpc < oprv->tpc_total; tpc++) { 2042 1853 do { 2043 1854 gpc = (gpc + 1) % oprv->gpc_nr; 2044 - } while (!tpnr[gpc]); 2045 - tpnr[gpc]--; 2046 - data[tp] = gpc; 1855 + } while (!tpcnr[gpc]); 1856 + tpcnr[gpc]--; 1857 + data[tpc] = gpc; 2047 1858 } 2048 1859 2049 1860 for (i = 0; i < 4; i++) ··· 2052 1863 2053 1864 if (1) { 2054 1865 u32 data[6] = {}, data2[2] = {}; 2055 - u8 tpnr[GPC_MAX]; 1866 + u8 tpcnr[GPC_MAX]; 2056 1867 u8 shift, ntpcv; 2057 1868 2058 1869 /* calculate first set of magics */ 2059 - memcpy(tpnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); 1870 + memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); 2060 1871 2061 1872 gpc = -1; 2062 - for (tp = 0; tp < oprv->tpc_total; tp++) { 1873 + for (tpc = 0; tpc < oprv->tpc_total; tpc++) { 2063 1874 do { 2064 1875 gpc = (gpc + 1) % oprv->gpc_nr; 2065 - } while (!tpnr[gpc]); 2066 - tpnr[gpc]--; 1876 + } while (!tpcnr[gpc]); 1877 + tpcnr[gpc]--; 2067 1878 2068 - data[tp / 6] |= gpc << ((tp % 6) * 5); 1879 + data[tpc / 6] |= gpc << ((tpc % 6) * 5); 2069 1880 } 2070 1881 2071 - for (; tp < 32; tp++) 2072 - data[tp / 6] |= 7 << ((tp % 6) * 5); 1882 + for (; tpc < 32; tpc++) 1883 + data[tpc / 6] |= 7 << ((tpc % 6) * 5); 2073 1884 2074 1885 /* and the second... */ 2075 1886 shift = 0; ··· 2107 1918 } 2108 1919 2109 1920 if (1) { 2110 - u32 tp_mask = 0, tp_set = 0; 2111 - u8 tpnr[GPC_MAX], a, b; 1921 + u32 tpc_mask = 0, tpc_set = 0; 1922 + u8 tpcnr[GPC_MAX], a, b; 2112 1923 2113 - memcpy(tpnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); 1924 + memcpy(tpcnr, oprv->tpc_nr, sizeof(oprv->tpc_nr)); 2114 1925 for (gpc = 0; gpc < oprv->gpc_nr; gpc++) 2115 - tp_mask |= ((1 << oprv->tpc_nr[gpc]) - 1) << (gpc * 8); 1926 + tpc_mask |= ((1 << oprv->tpc_nr[gpc]) - 1) << (gpc * 8); 2116 1927 2117 1928 for (i = 0, gpc = -1, b = -1; i < 32; i++) { 2118 1929 a = (i * (oprv->tpc_total - 1)) / 32; ··· 2120 1931 b = a; 2121 1932 do { 2122 1933 gpc = (gpc + 1) % oprv->gpc_nr; 2123 - } while (!tpnr[gpc]); 2124 - tp = oprv->tpc_nr[gpc] - tpnr[gpc]--; 1934 + } while (!tpcnr[gpc]); 1935 + tpc = oprv->tpc_nr[gpc] - tpcnr[gpc]--; 2125 1936 2126 - tp_set |= 1 << ((gpc * 8) + tp); 1937 + tpc_set |= 1 << ((gpc * 8) + tpc); 2127 1938 } 2128 1939 2129 - nv_wr32(priv, 0x406800 + (i * 0x20), tp_set); 2130 - nv_wr32(priv, 0x406c00 + (i * 0x20), tp_set ^ tp_mask); 1940 + nv_wr32(priv, 0x406800 + (i * 0x20), tpc_set); 1941 + nv_wr32(priv, 0x406c00 + (i * 0x20), tpc_set ^ tpc_mask); 2131 1942 } 2132 1943 } 2133 1944 ··· 3056 2867 nvc0_grctx_generate_90c0(priv); 3057 2868 3058 2869 nv_wr32(priv, 0x000260, r000260); 3059 - return 0; 2870 + return nvc0_grctx_fini(&info); 3060 2871 }
+40 -10
drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c
··· 2604 2604 } 2605 2605 2606 2606 int 2607 - nve0_grctx_generate(struct nouveau_channel *chan) 2607 + nve0_grctx_generate(struct drm_device *priv) 2608 2608 { 2609 - struct nvc0_graph_priv *oprv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); 2610 - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; 2611 - struct drm_device *priv = chan->dev; 2609 + struct nvc0_graph_priv *oprv = nv_engine(priv, NVOBJ_ENGINE_GR); 2610 + struct nvc0_grctx info; 2611 + int ret, i, gpc, tpc, id; 2612 2612 u32 data[6] = {}, data2[2] = {}, tmp; 2613 2613 u32 tpc_set = 0, tpc_mask = 0; 2614 + u32 magic[GPC_MAX][2], offset; 2614 2615 u8 tpcnr[GPC_MAX], a, b; 2615 2616 u8 shift, ntpcv; 2616 - int i, gpc, tpc, id; 2617 + 2618 + ret = nvc0_grctx_init(priv, oprv, &info); 2619 + if (ret) 2620 + return ret; 2617 2621 2618 2622 nv_mask(priv, 0x000260, 0x00000001, 0x00000000); 2619 2623 nv_wr32(priv, 0x400204, 0x00000000); ··· 2640 2636 2641 2637 nv_wr32(priv, 0x404154, 0x0); 2642 2638 2643 - for (i = 0; i < grch->mmio_nr * 8; i += 8) { 2644 - u32 reg = nv_ro32(grch->mmio, i + 0); 2645 - u32 val = nv_ro32(grch->mmio, i + 4); 2646 - nv_wr32(priv, reg, val); 2639 + mmio_data(0x003000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); 2640 + mmio_data(0x008000, 0x0100, NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS); 2641 + mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW); 2642 + mmio_list(0x40800c, 0x00000000, 8, 1); 2643 + mmio_list(0x408010, 0x80000000, 0, 0); 2644 + mmio_list(0x419004, 0x00000000, 8, 1); 2645 + mmio_list(0x419008, 0x00000000, 0, 0); 2646 + mmio_list(0x4064cc, 0x80000000, 0, 0); 2647 + mmio_list(0x408004, 0x00000000, 8, 0); 2648 + mmio_list(0x408008, 0x80000030, 0, 0); 2649 + mmio_list(0x418808, 0x00000000, 8, 0); 2650 + mmio_list(0x41880c, 0x80000030, 0, 0); 2651 + mmio_list(0x4064c8, 0x01800600, 0, 0); 2652 + mmio_list(0x418810, 0x80000000, 12, 2); 2653 + mmio_list(0x419848, 0x10000000, 12, 2); 2654 + mmio_list(0x405830, 0x02180648, 0, 0); 2655 + mmio_list(0x4064c4, 0x0192ffff, 0, 0); 2656 + for (gpc = 0, offset = 0; gpc < oprv->gpc_nr; gpc++) { 2657 + u16 magic0 = 0x0218 * oprv->tpc_nr[gpc]; 2658 + u16 magic1 = 0x0648 * oprv->tpc_nr[gpc]; 2659 + magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset; 2660 + magic[gpc][1] = 0x00000000 | (magic1 << 16); 2661 + offset += 0x0324 * oprv->tpc_nr[gpc]; 2647 2662 } 2663 + for (gpc = 0; gpc < oprv->gpc_nr; gpc++) { 2664 + mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0); 2665 + mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0); 2666 + offset += 0x07ff * oprv->tpc_nr[gpc]; 2667 + } 2668 + mmio_list(0x17e91c, 0x06060609, 0, 0); 2669 + mmio_list(0x17e920, 0x00090a05, 0, 0); 2648 2670 2649 2671 nv_wr32(priv, 0x418c6c, 0x1); 2650 2672 nv_wr32(priv, 0x41980c, 0x10); ··· 2788 2758 nv_mask(priv, 0x000260, 0x00000001, 0x00000001); 2789 2759 nv_wr32(priv, 0x418800, 0x7026860a); //XXX 2790 2760 nv_wr32(priv, 0x41be10, 0x00bb8bc7); //XXX 2791 - return 0; 2761 + return nvc0_grctx_fini(&info); 2792 2762 }
+153 -303
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
··· 48 48 nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c)); 49 49 } 50 50 51 - static void 51 + void 52 52 nvc0_graph_ctxctl_debug(struct drm_device *dev) 53 53 { 54 54 u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff; ··· 59 59 nvc0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000)); 60 60 } 61 61 62 - static int 63 - nvc0_graph_load_context(struct nouveau_channel *chan) 64 - { 65 - struct drm_device *dev = chan->dev; 66 - 67 - nv_wr32(dev, 0x409840, 0x00000030); 68 - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); 69 - nv_wr32(dev, 0x409504, 0x00000003); 70 - if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) 71 - NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); 72 - 73 - return 0; 74 - } 75 - 76 - static int 77 - nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) 78 - { 79 - nv_wr32(dev, 0x409840, 0x00000003); 80 - nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); 81 - nv_wr32(dev, 0x409504, 0x00000009); 82 - if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { 83 - NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); 84 - return -EBUSY; 85 - } 86 - 87 - return 0; 88 - } 89 - 90 - static int 91 - nvc0_graph_construct_context(struct nouveau_channel *chan) 92 - { 93 - struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); 94 - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; 95 - struct drm_device *dev = chan->dev; 96 - int ret, i; 97 - u32 *ctx; 98 - 99 - ctx = kmalloc(priv->grctx_size, GFP_KERNEL); 100 - if (!ctx) 101 - return -ENOMEM; 102 - 103 - if (!nouveau_ctxfw) { 104 - nv_wr32(dev, 0x409840, 0x80000000); 105 - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); 106 - nv_wr32(dev, 0x409504, 0x00000001); 107 - if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { 108 - NV_ERROR(dev, "PGRAPH: HUB_SET_CHAN timeout\n"); 109 - nvc0_graph_ctxctl_debug(dev); 110 - ret = -EBUSY; 111 - goto err; 112 - } 113 - } else { 114 - nvc0_graph_load_context(chan); 115 - 116 - nv_wo32(grch->grctx, 0x1c, 1); 117 - nv_wo32(grch->grctx, 0x20, 0); 118 - nv_wo32(grch->grctx, 0x28, 0); 119 - nv_wo32(grch->grctx, 0x2c, 0); 120 - nvimem_flush(dev); 121 - } 122 - 123 - ret = nvc0_grctx_generate(chan); 124 - if (ret) 125 - goto err; 126 - 127 - if (!nouveau_ctxfw) { 128 - nv_wr32(dev, 0x409840, 0x80000000); 129 - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); 130 - nv_wr32(dev, 0x409504, 0x00000002); 131 - if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { 132 - NV_ERROR(dev, "PGRAPH: HUB_CTX_SAVE timeout\n"); 133 - nvc0_graph_ctxctl_debug(dev); 134 - ret = -EBUSY; 135 - goto err; 136 - } 137 - } else { 138 - ret = nvc0_graph_unload_context_to(dev, chan->ramin->addr); 139 - if (ret) 140 - goto err; 141 - } 142 - 143 - for (i = 0; i < priv->grctx_size; i += 4) 144 - ctx[i / 4] = nv_ro32(grch->grctx, i); 145 - 146 - priv->grctx_vals = ctx; 147 - return 0; 148 - 149 - err: 150 - kfree(ctx); 151 - return ret; 152 - } 153 - 154 - static int 155 - nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) 156 - { 157 - struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); 158 - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; 159 - struct drm_device *dev = chan->dev; 160 - struct drm_nouveau_private *dev_priv = dev->dev_private; 161 - int i = 0, gpc, tp, ret; 162 - 163 - ret = nouveau_gpuobj_new(dev, NULL, 0x2000, 256, 0, &grch->unk408004); 164 - if (ret) 165 - return ret; 166 - 167 - ret = nouveau_gpuobj_map_vm(grch->unk408004, chan->vm, 168 - NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, 169 - &grch->unk408004_vma); 170 - if (ret) 171 - return ret; 172 - 173 - ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, 0, &grch->unk40800c); 174 - if (ret) 175 - return ret; 176 - 177 - ret = nouveau_gpuobj_map_vm(grch->unk40800c, chan->vm, 178 - NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, 179 - &grch->unk40800c_vma); 180 - if (ret) 181 - return ret; 182 - 183 - ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096, 0, 184 - &grch->unk418810); 185 - if (ret) 186 - return ret; 187 - 188 - ret = nouveau_gpuobj_map_vm(grch->unk418810, chan->vm, 189 - NV_MEM_ACCESS_RW, &grch->unk418810_vma); 190 - if (ret) 191 - return ret; 192 - 193 - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, 0, &grch->mmio); 194 - if (ret) 195 - return ret; 196 - 197 - ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, NV_MEM_ACCESS_RW | 198 - NV_MEM_ACCESS_SYS, &grch->mmio_vma); 199 - if (ret) 200 - return ret; 201 - 202 - nv_wo32(grch->mmio, i++ * 4, 0x00408004); 203 - nv_wo32(grch->mmio, i++ * 4, grch->unk408004_vma.offset >> 8); 204 - nv_wo32(grch->mmio, i++ * 4, 0x00408008); 205 - nv_wo32(grch->mmio, i++ * 4, 0x80000018); 206 - 207 - nv_wo32(grch->mmio, i++ * 4, 0x0040800c); 208 - nv_wo32(grch->mmio, i++ * 4, grch->unk40800c_vma.offset >> 8); 209 - nv_wo32(grch->mmio, i++ * 4, 0x00408010); 210 - nv_wo32(grch->mmio, i++ * 4, 0x80000000); 211 - 212 - nv_wo32(grch->mmio, i++ * 4, 0x00418810); 213 - nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810_vma.offset >> 12); 214 - nv_wo32(grch->mmio, i++ * 4, 0x00419848); 215 - nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810_vma.offset >> 12); 216 - 217 - nv_wo32(grch->mmio, i++ * 4, 0x00419004); 218 - nv_wo32(grch->mmio, i++ * 4, grch->unk40800c_vma.offset >> 8); 219 - nv_wo32(grch->mmio, i++ * 4, 0x00419008); 220 - nv_wo32(grch->mmio, i++ * 4, 0x00000000); 221 - 222 - nv_wo32(grch->mmio, i++ * 4, 0x00418808); 223 - nv_wo32(grch->mmio, i++ * 4, grch->unk408004_vma.offset >> 8); 224 - nv_wo32(grch->mmio, i++ * 4, 0x0041880c); 225 - nv_wo32(grch->mmio, i++ * 4, 0x80000018); 226 - 227 - if (dev_priv->chipset != 0xc1) { 228 - u32 magic = 0x02180000; 229 - nv_wo32(grch->mmio, i++ * 4, 0x00405830); 230 - nv_wo32(grch->mmio, i++ * 4, magic); 231 - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { 232 - for (tp = 0; tp < priv->tpc_nr[gpc]; tp++) { 233 - u32 reg = TPC_UNIT(gpc, tp, 0x520); 234 - nv_wo32(grch->mmio, i++ * 4, reg); 235 - nv_wo32(grch->mmio, i++ * 4, magic); 236 - magic += 0x0324; 237 - } 238 - } 239 - } else { 240 - u32 magic = 0x02180000; 241 - nv_wo32(grch->mmio, i++ * 4, 0x00405830); 242 - nv_wo32(grch->mmio, i++ * 4, magic | 0x0000218); 243 - nv_wo32(grch->mmio, i++ * 4, 0x004064c4); 244 - nv_wo32(grch->mmio, i++ * 4, 0x0086ffff); 245 - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { 246 - for (tp = 0; tp < priv->tpc_nr[gpc]; tp++) { 247 - u32 reg = TPC_UNIT(gpc, tp, 0x520); 248 - nv_wo32(grch->mmio, i++ * 4, reg); 249 - nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic); 250 - magic += 0x0324; 251 - } 252 - for (tp = 0; tp < priv->tpc_nr[gpc]; tp++) { 253 - u32 reg = TPC_UNIT(gpc, tp, 0x544); 254 - nv_wo32(grch->mmio, i++ * 4, reg); 255 - nv_wo32(grch->mmio, i++ * 4, magic); 256 - magic += 0x0324; 257 - } 258 - } 259 - } 260 - 261 - grch->mmio_nr = i / 2; 262 - return 0; 263 - } 264 - 265 - static int 62 + int 266 63 nvc0_graph_context_new(struct nouveau_channel *chan, int engine) 267 64 { 268 65 struct drm_device *dev = chan->dev; 269 66 struct nvc0_graph_priv *priv = nv_engine(dev, engine); 67 + struct nvc0_graph_data *data = priv->mmio_data; 68 + struct nvc0_graph_mmio *mmio = priv->mmio_list; 270 69 struct nvc0_graph_chan *grch; 271 70 struct nouveau_gpuobj *grctx; 272 71 int ret, i; ··· 75 276 return -ENOMEM; 76 277 chan->engctx[NVOBJ_ENGINE_GR] = grch; 77 278 78 - ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, 0, 79 - &grch->grctx); 279 + ret = nouveau_gpuobj_new(dev, NULL, priv->size, 256, 0, &grch->grctx); 80 280 if (ret) 81 281 goto error; 82 282 ··· 86 288 87 289 grctx = grch->grctx; 88 290 89 - ret = nvc0_graph_create_context_mmio_list(chan); 291 + /* allocate memory for a "mmio list" buffer that's used by the HUB 292 + * fuc to modify some per-context register settings on first load 293 + * of the context. 294 + */ 295 + ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x100, 0, &grch->mmio); 90 296 if (ret) 91 - goto error; 297 + return ret; 298 + 299 + ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, 300 + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, 301 + &grch->mmio_vma); 302 + if (ret) 303 + return ret; 304 + 305 + /* allocate buffers referenced by mmio list */ 306 + for (i = 0; data->size && i < ARRAY_SIZE(priv->mmio_data); i++) { 307 + ret = nouveau_gpuobj_new(dev, NULL, data->size, data->align, 308 + 0, &grch->data[i].mem); 309 + if (ret) 310 + return ret; 311 + 312 + ret = nouveau_gpuobj_map_vm(grch->data[i].mem, chan->vm, 313 + data->access, 314 + &grch->data[i].vma); 315 + if (ret) 316 + return ret; 317 + 318 + data++; 319 + } 320 + 321 + /* finally, fill in the mmio list and point the context at it */ 322 + for (i = 0; mmio->addr && i < ARRAY_SIZE(priv->mmio_list); i++) { 323 + u32 addr = mmio->addr; 324 + u32 data = mmio->data; 325 + 326 + if (mmio->shift) { 327 + u64 info = grch->data[mmio->buffer].vma.offset; 328 + data |= info >> mmio->shift; 329 + } 330 + 331 + nv_wo32(grch->mmio, grch->mmio_nr++ * 4, addr); 332 + nv_wo32(grch->mmio, grch->mmio_nr++ * 4, data); 333 + mmio++; 334 + } 335 + 336 + for (i = 0; i < priv->size; i += 4) 337 + nv_wo32(grch->grctx, i, priv->data[i / 4]); 92 338 93 339 nv_wo32(chan->ramin, 0x0210, lower_32_bits(grch->grctx_vma.offset) | 4); 94 340 nv_wo32(chan->ramin, 0x0214, upper_32_bits(grch->grctx_vma.offset)); 95 341 nvimem_flush(dev); 96 342 97 - if (!priv->grctx_vals) { 98 - ret = nvc0_graph_construct_context(chan); 99 - if (ret) 100 - goto error; 101 - } 102 - 103 - for (i = 0; i < priv->grctx_size; i += 4) 104 - nv_wo32(grctx, i, priv->grctx_vals[i / 4]); 105 - 106 - if (!nouveau_ctxfw) { 107 - nv_wo32(grctx, 0x00, grch->mmio_nr); 343 + if (!priv->firmware) { 344 + nv_wo32(grctx, 0x00, grch->mmio_nr / 2); 108 345 nv_wo32(grctx, 0x04, grch->mmio_vma.offset >> 8); 109 346 } else { 110 347 nv_wo32(grctx, 0xf4, 0); 111 348 nv_wo32(grctx, 0xf8, 0); 112 - nv_wo32(grctx, 0x10, grch->mmio_nr); 349 + nv_wo32(grctx, 0x10, grch->mmio_nr / 2); 113 350 nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio_vma.offset)); 114 351 nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio_vma.offset)); 115 352 nv_wo32(grctx, 0x1c, 1); ··· 160 327 return ret; 161 328 } 162 329 163 - static void 330 + void 164 331 nvc0_graph_context_del(struct nouveau_channel *chan, int engine) 165 332 { 166 333 struct nvc0_graph_chan *grch = chan->engctx[engine]; 334 + int i; 335 + 336 + for (i = 0; i < ARRAY_SIZE(grch->data); i++) { 337 + nouveau_gpuobj_unmap(&grch->data[i].vma); 338 + nouveau_gpuobj_ref(NULL, &grch->data[i].mem); 339 + } 167 340 168 341 nouveau_gpuobj_unmap(&grch->mmio_vma); 169 - nouveau_gpuobj_unmap(&grch->unk418810_vma); 170 - nouveau_gpuobj_unmap(&grch->unk40800c_vma); 171 - nouveau_gpuobj_unmap(&grch->unk408004_vma); 172 - nouveau_gpuobj_unmap(&grch->grctx_vma); 173 342 nouveau_gpuobj_ref(NULL, &grch->mmio); 174 - nouveau_gpuobj_ref(NULL, &grch->unk418810); 175 - nouveau_gpuobj_ref(NULL, &grch->unk40800c); 176 - nouveau_gpuobj_ref(NULL, &grch->unk408004); 343 + 344 + nouveau_gpuobj_unmap(&grch->grctx_vma); 177 345 nouveau_gpuobj_ref(NULL, &grch->grctx); 178 346 chan->engctx[engine] = NULL; 179 347 } ··· 351 517 u32 r000260; 352 518 int i; 353 519 354 - if (!nouveau_ctxfw) { 355 - /* load HUB microcode */ 520 + if (priv->firmware) { 521 + /* load fuc microcode */ 356 522 r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); 357 - nv_wr32(dev, 0x4091c0, 0x01000000); 358 - for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++) 359 - nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]); 360 - 361 - nv_wr32(dev, 0x409180, 0x01000000); 362 - for (i = 0; i < sizeof(nvc0_grhub_code) / 4; i++) { 363 - if ((i & 0x3f) == 0) 364 - nv_wr32(dev, 0x409188, i >> 6); 365 - nv_wr32(dev, 0x409184, nvc0_grhub_code[i]); 366 - } 367 - 368 - /* load GPC microcode */ 369 - nv_wr32(dev, 0x41a1c0, 0x01000000); 370 - for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++) 371 - nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]); 372 - 373 - nv_wr32(dev, 0x41a180, 0x01000000); 374 - for (i = 0; i < sizeof(nvc0_grgpc_code) / 4; i++) { 375 - if ((i & 0x3f) == 0) 376 - nv_wr32(dev, 0x41a188, i >> 6); 377 - nv_wr32(dev, 0x41a184, nvc0_grgpc_code[i]); 378 - } 523 + nvc0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, 524 + &priv->fuc409d); 525 + nvc0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, 526 + &priv->fuc41ad); 379 527 nv_wr32(dev, 0x000260, r000260); 380 528 381 - /* start HUB ucode running, it'll init the GPCs */ 382 - nv_wr32(dev, 0x409800, dev_priv->chipset); 529 + /* start both of them running */ 530 + nv_wr32(dev, 0x409840, 0xffffffff); 531 + nv_wr32(dev, 0x41a10c, 0x00000000); 383 532 nv_wr32(dev, 0x40910c, 0x00000000); 533 + nv_wr32(dev, 0x41a100, 0x00000002); 384 534 nv_wr32(dev, 0x409100, 0x00000002); 385 - if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { 386 - NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n"); 387 - nvc0_graph_ctxctl_debug(dev); 535 + if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000001)) 536 + NV_INFO(dev, "0x409800 wait failed\n"); 537 + 538 + nv_wr32(dev, 0x409840, 0xffffffff); 539 + nv_wr32(dev, 0x409500, 0x7fffffff); 540 + nv_wr32(dev, 0x409504, 0x00000021); 541 + 542 + nv_wr32(dev, 0x409840, 0xffffffff); 543 + nv_wr32(dev, 0x409500, 0x00000000); 544 + nv_wr32(dev, 0x409504, 0x00000010); 545 + if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { 546 + NV_ERROR(dev, "fuc09 req 0x10 timeout\n"); 547 + return -EBUSY; 548 + } 549 + priv->size = nv_rd32(dev, 0x409800); 550 + 551 + nv_wr32(dev, 0x409840, 0xffffffff); 552 + nv_wr32(dev, 0x409500, 0x00000000); 553 + nv_wr32(dev, 0x409504, 0x00000016); 554 + if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { 555 + NV_ERROR(dev, "fuc09 req 0x16 timeout\n"); 388 556 return -EBUSY; 389 557 } 390 558 391 - priv->grctx_size = nv_rd32(dev, 0x409804); 392 - return 0; 559 + nv_wr32(dev, 0x409840, 0xffffffff); 560 + nv_wr32(dev, 0x409500, 0x00000000); 561 + nv_wr32(dev, 0x409504, 0x00000025); 562 + if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { 563 + NV_ERROR(dev, "fuc09 req 0x25 timeout\n"); 564 + return -EBUSY; 565 + } 566 + 567 + goto done; 393 568 } 394 569 395 - /* load fuc microcode */ 570 + /* load HUB microcode */ 396 571 r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); 397 - nvc0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, &priv->fuc409d); 398 - nvc0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, &priv->fuc41ad); 572 + nv_wr32(dev, 0x4091c0, 0x01000000); 573 + for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++) 574 + nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]); 575 + 576 + nv_wr32(dev, 0x409180, 0x01000000); 577 + for (i = 0; i < sizeof(nvc0_grhub_code) / 4; i++) { 578 + if ((i & 0x3f) == 0) 579 + nv_wr32(dev, 0x409188, i >> 6); 580 + nv_wr32(dev, 0x409184, nvc0_grhub_code[i]); 581 + } 582 + 583 + /* load GPC microcode */ 584 + nv_wr32(dev, 0x41a1c0, 0x01000000); 585 + for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++) 586 + nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]); 587 + 588 + nv_wr32(dev, 0x41a180, 0x01000000); 589 + for (i = 0; i < sizeof(nvc0_grgpc_code) / 4; i++) { 590 + if ((i & 0x3f) == 0) 591 + nv_wr32(dev, 0x41a188, i >> 6); 592 + nv_wr32(dev, 0x41a184, nvc0_grgpc_code[i]); 593 + } 399 594 nv_wr32(dev, 0x000260, r000260); 400 595 401 - /* start both of them running */ 402 - nv_wr32(dev, 0x409840, 0xffffffff); 403 - nv_wr32(dev, 0x41a10c, 0x00000000); 596 + /* start HUB ucode running, it'll init the GPCs */ 597 + nv_wr32(dev, 0x409800, dev_priv->chipset); 404 598 nv_wr32(dev, 0x40910c, 0x00000000); 405 - nv_wr32(dev, 0x41a100, 0x00000002); 406 599 nv_wr32(dev, 0x409100, 0x00000002); 407 - if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000001)) 408 - NV_INFO(dev, "0x409800 wait failed\n"); 409 - 410 - nv_wr32(dev, 0x409840, 0xffffffff); 411 - nv_wr32(dev, 0x409500, 0x7fffffff); 412 - nv_wr32(dev, 0x409504, 0x00000021); 413 - 414 - nv_wr32(dev, 0x409840, 0xffffffff); 415 - nv_wr32(dev, 0x409500, 0x00000000); 416 - nv_wr32(dev, 0x409504, 0x00000010); 417 - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { 418 - NV_ERROR(dev, "fuc09 req 0x10 timeout\n"); 419 - return -EBUSY; 420 - } 421 - priv->grctx_size = nv_rd32(dev, 0x409800); 422 - 423 - nv_wr32(dev, 0x409840, 0xffffffff); 424 - nv_wr32(dev, 0x409500, 0x00000000); 425 - nv_wr32(dev, 0x409504, 0x00000016); 426 - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { 427 - NV_ERROR(dev, "fuc09 req 0x16 timeout\n"); 600 + if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { 601 + NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n"); 602 + nvc0_graph_ctxctl_debug(dev); 428 603 return -EBUSY; 429 604 } 430 605 431 - nv_wr32(dev, 0x409840, 0xffffffff); 432 - nv_wr32(dev, 0x409500, 0x00000000); 433 - nv_wr32(dev, 0x409504, 0x00000025); 434 - if (!nv_wait_ne(dev, 0x409800, 0xffffffff, 0x00000000)) { 435 - NV_ERROR(dev, "fuc09 req 0x25 timeout\n"); 436 - return -EBUSY; 606 + priv->size = nv_rd32(dev, 0x409804); 607 + done: 608 + if (priv->data == NULL) { 609 + int ret = nvc0_grctx_generate(dev); 610 + if (ret) { 611 + NV_ERROR(dev, "PGRAPH: failed to construct context\n"); 612 + return ret; 613 + } 614 + 615 + return 1; 437 616 } 438 617 439 618 return 0; ··· 457 610 { 458 611 int ret; 459 612 613 + reset: 460 614 nv_mask(dev, 0x000200, 0x18001000, 0x00000000); 461 615 nv_mask(dev, 0x000200, 0x18001000, 0x18001000); 462 616 ··· 484 636 nv_wr32(dev, 0x400054, 0x34ce3464); 485 637 486 638 ret = nvc0_graph_init_ctxctl(dev); 487 - if (ret) 639 + if (ret) { 640 + if (ret == 1) 641 + goto reset; 488 642 return ret; 643 + } 489 644 490 645 return 0; 491 646 } ··· 635 784 { 636 785 struct nvc0_graph_priv *priv = nv_engine(dev, engine); 637 786 638 - if (nouveau_ctxfw) { 639 - nvc0_graph_destroy_fw(&priv->fuc409c); 640 - nvc0_graph_destroy_fw(&priv->fuc409d); 641 - nvc0_graph_destroy_fw(&priv->fuc41ac); 642 - nvc0_graph_destroy_fw(&priv->fuc41ad); 643 - } 787 + nvc0_graph_destroy_fw(&priv->fuc409c); 788 + nvc0_graph_destroy_fw(&priv->fuc409d); 789 + nvc0_graph_destroy_fw(&priv->fuc41ac); 790 + nvc0_graph_destroy_fw(&priv->fuc41ad); 644 791 645 792 nouveau_irq_unregister(dev, 12); 646 793 647 794 nouveau_gpuobj_ref(NULL, &priv->unk4188b8); 648 795 nouveau_gpuobj_ref(NULL, &priv->unk4188b4); 649 796 650 - if (priv->grctx_vals) 651 - kfree(priv->grctx_vals); 797 + if (priv->data) 798 + kfree(priv->data); 652 799 653 800 NVOBJ_ENGINE_DEL(dev, GR); 654 801 kfree(priv); ··· 689 840 ret = 0; 690 841 goto error; 691 842 } 843 + priv->firmware = true; 692 844 } 693 845 694 846 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4);
+19 -11
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h
··· 66 66 u8 tpc_nr[GPC_MAX]; 67 67 u8 tpc_total; 68 68 69 - u32 grctx_size; 70 - u32 *grctx_vals; 71 69 struct nouveau_gpuobj *unk4188b4; 72 70 struct nouveau_gpuobj *unk4188b8; 71 + 72 + struct nvc0_graph_data mmio_data[4]; 73 + struct nvc0_graph_mmio mmio_list[4096/8]; 74 + u32 size; 75 + u32 *data; 73 76 74 77 u8 magic_not_rop_nr; 75 78 }; ··· 80 77 struct nvc0_graph_chan { 81 78 struct nouveau_gpuobj *grctx; 82 79 struct nouveau_vma grctx_vma; 83 - struct nouveau_gpuobj *unk408004; /* 0x418808 too */ 84 - struct nouveau_vma unk408004_vma; 85 - struct nouveau_gpuobj *unk40800c; /* 0x419004 too */ 86 - struct nouveau_vma unk40800c_vma; 87 - struct nouveau_gpuobj *unk418810; /* 0x419848 too */ 88 - struct nouveau_vma unk418810_vma; 89 80 90 81 struct nouveau_gpuobj *mmio; 91 82 struct nouveau_vma mmio_vma; 92 83 int mmio_nr; 84 + struct { 85 + struct nouveau_gpuobj *mem; 86 + struct nouveau_vma vma; 87 + } data[4]; 93 88 }; 94 89 95 90 static inline u32 ··· 125 124 } 126 125 127 126 struct nvc0_grctx { 127 + struct drm_device *dev; 128 128 struct nvc0_graph_priv *priv; 129 129 struct nvc0_graph_data *data; 130 130 struct nvc0_graph_mmio *mmio; ··· 135 133 u64 addr; 136 134 }; 137 135 138 - int nvc0_grctx_generate(struct nouveau_channel *); 139 - int nvc0_grctx_init(struct nvc0_graph_priv *, struct nvc0_grctx *); 136 + int nvc0_grctx_generate(struct drm_device *); 137 + int nvc0_grctx_init(struct drm_device *, struct nvc0_graph_priv *, 138 + struct nvc0_grctx *); 140 139 void nvc0_grctx_data(struct nvc0_grctx *, u32, u32, u32); 141 140 void nvc0_grctx_mmio(struct nvc0_grctx *, u32, u32, u32, u32); 142 141 int nvc0_grctx_fini(struct nvc0_grctx *); 143 142 144 - int nve0_grctx_generate(struct nouveau_channel *); 143 + int nve0_grctx_generate(struct drm_device *); 145 144 146 145 #define mmio_data(s,a,p) nvc0_grctx_data(&info, (s), (a), (p)) 147 146 #define mmio_list(r,d,s,b) nvc0_grctx_mmio(&info, (r), (d), (s), (b)) ··· 156 153 struct nouveau_oclass *, void *, u32, 157 154 struct nouveau_object **); 158 155 void nvc0_graph_context_dtor(struct nouveau_object *); 156 + 157 + void nvc0_graph_ctxctl_debug(struct drm_device *); 158 + 159 + int nvc0_graph_context_new(struct nouveau_channel *, int); 160 + void nvc0_graph_context_del(struct nouveau_channel *, int); 159 161 160 162 #endif
+22 -243
drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
··· 58 58 } 59 59 60 60 static int 61 - nve0_graph_load_context(struct nouveau_channel *chan) 62 - { 63 - struct drm_device *dev = chan->dev; 64 - 65 - nv_wr32(dev, 0x409840, 0x00000030); 66 - nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->addr >> 12); 67 - nv_wr32(dev, 0x409504, 0x00000003); 68 - if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) 69 - NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); 70 - 71 - return 0; 72 - } 73 - 74 - static int 75 - nve0_graph_unload_context_to(struct drm_device *dev, u64 chan) 76 - { 77 - nv_wr32(dev, 0x409840, 0x00000003); 78 - nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); 79 - nv_wr32(dev, 0x409504, 0x00000009); 80 - if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { 81 - NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); 82 - return -EBUSY; 83 - } 84 - 85 - return 0; 86 - } 87 - 88 - static int 89 - nve0_graph_construct_context(struct nouveau_channel *chan) 90 - { 91 - struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); 92 - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; 93 - struct drm_device *dev = chan->dev; 94 - int ret, i; 95 - u32 *ctx; 96 - 97 - ctx = kmalloc(priv->grctx_size, GFP_KERNEL); 98 - if (!ctx) 99 - return -ENOMEM; 100 - 101 - nve0_graph_load_context(chan); 102 - 103 - nv_wo32(grch->grctx, 0x1c, 1); 104 - nv_wo32(grch->grctx, 0x20, 0); 105 - nv_wo32(grch->grctx, 0x28, 0); 106 - nv_wo32(grch->grctx, 0x2c, 0); 107 - nvimem_flush(dev); 108 - 109 - ret = nve0_grctx_generate(chan); 110 - if (ret) 111 - goto err; 112 - 113 - ret = nve0_graph_unload_context_to(dev, chan->ramin->addr); 114 - if (ret) 115 - goto err; 116 - 117 - for (i = 0; i < priv->grctx_size; i += 4) 118 - ctx[i / 4] = nv_ro32(grch->grctx, i); 119 - 120 - priv->grctx_vals = ctx; 121 - return 0; 122 - 123 - err: 124 - kfree(ctx); 125 - return ret; 126 - } 127 - 128 - static int 129 - nve0_graph_create_context_mmio_list(struct nouveau_channel *chan) 130 - { 131 - struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); 132 - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; 133 - struct drm_device *dev = chan->dev; 134 - u32 magic[GPC_MAX][2]; 135 - u16 offset = 0x0000; 136 - int gpc; 137 - int ret; 138 - 139 - ret = nouveau_gpuobj_new(dev, NULL, 0x3000, 256, 0, &grch->unk408004); 140 - if (ret) 141 - return ret; 142 - 143 - ret = nouveau_gpuobj_map_vm(grch->unk408004, chan->vm, 144 - NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, 145 - &grch->unk408004_vma); 146 - if (ret) 147 - return ret; 148 - 149 - ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, 0, &grch->unk40800c); 150 - if (ret) 151 - return ret; 152 - 153 - ret = nouveau_gpuobj_map_vm(grch->unk40800c, chan->vm, 154 - NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, 155 - &grch->unk40800c_vma); 156 - if (ret) 157 - return ret; 158 - 159 - ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096, 0, 160 - &grch->unk418810); 161 - if (ret) 162 - return ret; 163 - 164 - ret = nouveau_gpuobj_map_vm(grch->unk418810, chan->vm, 165 - NV_MEM_ACCESS_RW, &grch->unk418810_vma); 166 - if (ret) 167 - return ret; 168 - 169 - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, 0, &grch->mmio); 170 - if (ret) 171 - return ret; 172 - 173 - ret = nouveau_gpuobj_map_vm(grch->mmio, chan->vm, 174 - NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, 175 - &grch->mmio_vma); 176 - if (ret) 177 - return ret; 178 - 179 - #define mmio(r,v) do { \ 180 - nv_wo32(grch->mmio, (grch->mmio_nr * 8) + 0, (r)); \ 181 - nv_wo32(grch->mmio, (grch->mmio_nr * 8) + 4, (v)); \ 182 - grch->mmio_nr++; \ 183 - } while (0) 184 - mmio(0x40800c, grch->unk40800c_vma.offset >> 8); 185 - mmio(0x408010, 0x80000000); 186 - mmio(0x419004, grch->unk40800c_vma.offset >> 8); 187 - mmio(0x419008, 0x00000000); 188 - mmio(0x4064cc, 0x80000000); 189 - mmio(0x408004, grch->unk408004_vma.offset >> 8); 190 - mmio(0x408008, 0x80000030); 191 - mmio(0x418808, grch->unk408004_vma.offset >> 8); 192 - mmio(0x41880c, 0x80000030); 193 - mmio(0x4064c8, 0x01800600); 194 - mmio(0x418810, 0x80000000 | grch->unk418810_vma.offset >> 12); 195 - mmio(0x419848, 0x10000000 | grch->unk418810_vma.offset >> 12); 196 - mmio(0x405830, 0x02180648); 197 - mmio(0x4064c4, 0x0192ffff); 198 - 199 - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { 200 - u16 magic0 = 0x0218 * priv->tpc_nr[gpc]; 201 - u16 magic1 = 0x0648 * priv->tpc_nr[gpc]; 202 - magic[gpc][0] = 0x10000000 | (magic0 << 16) | offset; 203 - magic[gpc][1] = 0x00000000 | (magic1 << 16); 204 - offset += 0x0324 * priv->tpc_nr[gpc]; 205 - } 206 - 207 - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { 208 - mmio(GPC_UNIT(gpc, 0x30c0), magic[gpc][0]); 209 - mmio(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset); 210 - offset += 0x07ff * priv->tpc_nr[gpc]; 211 - } 212 - 213 - mmio(0x17e91c, 0x06060609); 214 - mmio(0x17e920, 0x00090a05); 215 - #undef mmio 216 - return 0; 217 - } 218 - 219 - static int 220 - nve0_graph_context_new(struct nouveau_channel *chan, int engine) 221 - { 222 - struct drm_device *dev = chan->dev; 223 - struct nvc0_graph_priv *priv = nv_engine(dev, engine); 224 - struct nvc0_graph_chan *grch; 225 - struct nouveau_gpuobj *grctx; 226 - int ret, i; 227 - 228 - grch = kzalloc(sizeof(*grch), GFP_KERNEL); 229 - if (!grch) 230 - return -ENOMEM; 231 - chan->engctx[NVOBJ_ENGINE_GR] = grch; 232 - 233 - ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, 0, 234 - &grch->grctx); 235 - if (ret) 236 - goto error; 237 - 238 - ret = nouveau_gpuobj_map_vm(grch->grctx, chan->vm, NV_MEM_ACCESS_RW | 239 - NV_MEM_ACCESS_SYS, &grch->grctx_vma); 240 - if (ret) 241 - return ret; 242 - 243 - grctx = grch->grctx; 244 - 245 - ret = nve0_graph_create_context_mmio_list(chan); 246 - if (ret) 247 - goto error; 248 - 249 - nv_wo32(chan->ramin, 0x0210, lower_32_bits(grch->grctx_vma.offset) | 4); 250 - nv_wo32(chan->ramin, 0x0214, upper_32_bits(grch->grctx_vma.offset)); 251 - nvimem_flush(dev); 252 - 253 - if (!priv->grctx_vals) { 254 - ret = nve0_graph_construct_context(chan); 255 - if (ret) 256 - goto error; 257 - } 258 - 259 - for (i = 0; i < priv->grctx_size; i += 4) 260 - nv_wo32(grctx, i, priv->grctx_vals[i / 4]); 261 - nv_wo32(grctx, 0xf4, 0); 262 - nv_wo32(grctx, 0xf8, 0); 263 - nv_wo32(grctx, 0x10, grch->mmio_nr); 264 - nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio_vma.offset)); 265 - nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio_vma.offset)); 266 - nv_wo32(grctx, 0x1c, 1); 267 - nv_wo32(grctx, 0x20, 0); 268 - nv_wo32(grctx, 0x28, 0); 269 - nv_wo32(grctx, 0x2c, 0); 270 - 271 - nvimem_flush(dev); 272 - return 0; 273 - 274 - error: 275 - priv->base.context_del(chan, engine); 276 - return ret; 277 - } 278 - 279 - static void 280 - nve0_graph_context_del(struct nouveau_channel *chan, int engine) 281 - { 282 - struct nvc0_graph_chan *grch = chan->engctx[engine]; 283 - 284 - nouveau_gpuobj_unmap(&grch->mmio_vma); 285 - nouveau_gpuobj_unmap(&grch->unk418810_vma); 286 - nouveau_gpuobj_unmap(&grch->unk40800c_vma); 287 - nouveau_gpuobj_unmap(&grch->unk408004_vma); 288 - nouveau_gpuobj_unmap(&grch->grctx_vma); 289 - nouveau_gpuobj_ref(NULL, &grch->mmio); 290 - nouveau_gpuobj_ref(NULL, &grch->unk418810); 291 - nouveau_gpuobj_ref(NULL, &grch->unk40800c); 292 - nouveau_gpuobj_ref(NULL, &grch->unk408004); 293 - nouveau_gpuobj_ref(NULL, &grch->grctx); 294 - chan->engctx[engine] = NULL; 295 - } 296 - 297 - static int 298 61 nve0_graph_object_new(struct nouveau_channel *chan, int engine, 299 62 u32 handle, u16 class) 300 63 { ··· 250 487 NV_ERROR(dev, "fuc09 req 0x10 timeout\n"); 251 488 return -EBUSY; 252 489 } 253 - priv->grctx_size = nv_rd32(dev, 0x409800); 490 + priv->size = nv_rd32(dev, 0x409800); 254 491 255 492 nv_wr32(dev, 0x409840, 0xffffffff); 256 493 nv_wr32(dev, 0x409500, 0x00000000); ··· 297 534 nv_wr32(dev, 0x409614, 0x00000070); 298 535 nv_wr32(dev, 0x409614, 0x00000770); 299 536 nv_wr32(dev, 0x40802c, 0x00000001); 537 + 538 + if (priv->data == NULL) { 539 + int ret = nve0_grctx_generate(dev); 540 + if (ret) { 541 + NV_ERROR(dev, "PGRAPH: failed to construct context\n"); 542 + return ret; 543 + } 544 + 545 + return 1; 546 + } 547 + 300 548 return 0; 301 549 } 302 550 ··· 316 542 { 317 543 int ret; 318 544 545 + reset: 319 546 nv_mask(dev, 0x000200, 0x18001000, 0x00000000); 320 547 nv_mask(dev, 0x000200, 0x18001000, 0x18001000); 321 548 ··· 341 566 nv_wr32(dev, 0x400054, 0x34ce3464); 342 567 343 568 ret = nve0_graph_init_ctxctl(dev); 344 - if (ret) 569 + if (ret) { 570 + if (ret == 1) 571 + goto reset; 345 572 return ret; 573 + } 346 574 347 575 return 0; 348 576 } ··· 536 758 nouveau_gpuobj_ref(NULL, &priv->unk4188b8); 537 759 nouveau_gpuobj_ref(NULL, &priv->unk4188b4); 538 760 539 - if (priv->grctx_vals) 540 - kfree(priv->grctx_vals); 761 + if (priv->data) 762 + kfree(priv->data); 541 763 542 764 NVOBJ_ENGINE_DEL(dev, GR); 543 765 kfree(priv); ··· 564 786 priv->base.destroy = nve0_graph_destroy; 565 787 priv->base.init = nve0_graph_init; 566 788 priv->base.fini = nve0_graph_fini; 567 - priv->base.context_new = nve0_graph_context_new; 568 - priv->base.context_del = nve0_graph_context_del; 789 + priv->base.context_new = nvc0_graph_context_new; 790 + priv->base.context_del = nvc0_graph_context_del; 569 791 priv->base.object_new = nve0_graph_object_new; 570 792 571 793 NVOBJ_ENGINE_ADD(dev, GR, &priv->base); ··· 579 801 ret = 0; 580 802 goto error; 581 803 } 804 + priv->firmware = true; 582 805 583 806 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); 584 807 if (ret)