1 /* 2 * Copyright 2019 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 #ifndef __NVIF_PUSH_H__ 23 #define __NVIF_PUSH_H__ 24 #include <nvif/mem.h> 25 #include <nvif/printf.h> 26 27 #include <nvhw/drf.h> 28 29 struct nvif_push { 30 int (*wait)(struct nvif_push *push, u32 size); 31 void (*kick)(struct nvif_push *push); 32 33 struct nvif_mem mem; 34 u64 addr; 35 36 struct { 37 u32 get; 38 u32 max; 39 } hw; 40 41 u32 *bgn; 42 u32 *cur; 43 u32 *seg; 44 u32 *end; 45 }; 46 47 static inline __must_check int 48 PUSH_WAIT(struct nvif_push *push, u32 size) 49 { 50 if (push->cur + size > push->end) { 51 int ret = push->wait(push, size); 52 if (ret) 53 return ret; 54 } 55 #ifdef CONFIG_NOUVEAU_DEBUG_PUSH 56 push->seg = push->cur + size; 57 #endif 58 return 0; 59 } 60 61 static inline int 62 PUSH_KICK(struct nvif_push *push) 63 { 64 if (push->cur != push->bgn) { 65 push->kick(push); 66 push->bgn = push->cur; 67 } 68 69 return 0; 70 } 71 72 #ifdef CONFIG_NOUVEAU_DEBUG_PUSH 73 #define PUSH_PRINTF(p,f,a...) do { \ 74 struct nvif_push *_ppp = (p); \ 75 u32 __o = _ppp->cur - (u32 *)_ppp->mem.object.map.ptr; \ 76 NVIF_DEBUG(&_ppp->mem.object, "%08x: "f, __o * 4, ##a); \ 77 (void)__o; \ 78 } while(0) 79 #define PUSH_ASSERT_ON(a,b) WARN((a), b) 80 #else 81 #define PUSH_PRINTF(p,f,a...) 82 #define PUSH_ASSERT_ON(a, b) 83 #endif 84 85 #define PUSH_ASSERT(a,b) do { \ 86 static_assert( \ 87 __builtin_choose_expr(__builtin_constant_p(a), (a), 1), b \ 88 ); \ 89 PUSH_ASSERT_ON(!(a), b); \ 90 } while(0) 91 92 #define PUSH_DATA__(p,d,f,a...) do { \ 93 struct nvif_push *_p = (p); \ 94 u32 _d = (d); \ 95 PUSH_ASSERT(_p->cur < _p->seg, "segment overrun"); \ 96 PUSH_ASSERT(_p->cur < _p->end, "pushbuf overrun"); \ 97 PUSH_PRINTF(_p, "%08x"f, _d, ##a); \ 98 *_p->cur++ = _d; \ 99 } while(0) 100 101 #define PUSH_DATA_(X,p,m,i0,i1,d,s,f,a...) PUSH_DATA__((p), (d), "-> "#m f, ##a) 102 #define PUSH_DATA(p,d) PUSH_DATA__((p), (d), " data - %s", __func__) 103 104 //XXX: error-check this against *real* pushbuffer end? 105 #define PUSH_RSVD(p,d) do { \ 106 struct nvif_push *__p = (p); \ 107 __p->seg++; \ 108 __p->end++; \ 109 d; \ 110 } while(0) 111 112 #ifdef CONFIG_NOUVEAU_DEBUG_PUSH 113 #define PUSH_DATAp(X,p,m,i,o,d,s,f,a...) do { \ 114 struct nvif_push *_pp = (p); \ 115 const u32 *_dd = (d); \ 116 u32 _s = (s), _i = (i?PUSH_##o##_INC); \ 117 if (_s--) { \ 118 PUSH_DATA_(X, _pp, X##m, i0, i1, *_dd++, 1, "+0x%x", 0); \ 119 while (_s--) { \ 120 PUSH_DATA_(X, _pp, X##m, i0, i1, *_dd++, 1, "+0x%x", _i); \ 121 _i += (0?PUSH_##o##_INC); \ 122 } \ 123 } \ 124 } while(0) 125 #else 126 #define PUSH_DATAp(X,p,m,i,o,d,s,f,a...) do { \ 127 struct nvif_push *_p = (p); \ 128 u32 _s = (s); \ 129 PUSH_ASSERT(_p->cur + _s <= _p->seg, "segment overrun"); \ 130 PUSH_ASSERT(_p->cur + _s <= _p->end, "pushbuf overrun"); \ 131 memcpy(_p->cur, (d), _s << 2); \ 132 _p->cur += _s; \ 133 } while(0) 134 #endif 135 136 #define PUSH_1(X,f,ds,n,o,p,s,mA,dA) do { \ 137 PUSH_##o##_HDR((p), s, mA, (ds)+(n)); \ 138 PUSH_##f(X, (p), X##mA, 1, o, (dA), ds, ""); \ 139 } while(0) 140 #define PUSH_2(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 141 PUSH_ASSERT((mB) - (mA) == (1?PUSH_##o##_INC), "mthd1"); \ 142 PUSH_1(X, DATA_, 1, (ds) + (n), o, (p), s, X##mA, (dA), ##a); \ 143 PUSH_##f(X, (p), X##mB, 0, o, (dB), ds, ""); \ 144 } while(0) 145 #define PUSH_3(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 146 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd2"); \ 147 PUSH_2(X, DATA_, 1, (ds) + (n), o, (p), s, X##mA, (dA), ##a); \ 148 PUSH_##f(X, (p), X##mB, 0, o, (dB), ds, ""); \ 149 } while(0) 150 #define PUSH_4(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 151 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd3"); \ 152 PUSH_3(X, DATA_, 1, (ds) + (n), o, (p), s, X##mA, (dA), ##a); \ 153 PUSH_##f(X, (p), X##mB, 0, o, (dB), ds, ""); \ 154 } while(0) 155 #define PUSH_5(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 156 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd4"); \ 157 PUSH_4(X, DATA_, 1, (ds) + (n), o, (p), s, X##mA, (dA), ##a); \ 158 PUSH_##f(X, (p), X##mB, 0, o, (dB), ds, ""); \ 159 } while(0) 160 #define PUSH_6(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 161 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd5"); \ 162 PUSH_5(X, DATA_, 1, (ds) + (n), o, (p), s, X##mA, (dA), ##a); \ 163 PUSH_##f(X, (p), X##mB, 0, o, (dB), ds, ""); \ 164 } while(0) 165 #define PUSH_7(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 166 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd6"); \ 167 PUSH_6(X, DATA_, 1, (ds) + (n), o, (p), s, X##mA, (dA), ##a); \ 168 PUSH_##f(X, (p), X##mB, 0, o, (dB), ds, ""); \ 169 } while(0) 170 #define PUSH_8(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 171 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd7"); \ 172 PUSH_7(X, DATA_, 1, (ds) + (n), o, (p), s, X##mA, (dA), ##a); \ 173 PUSH_##f(X, (p), X##mB, 0, o, (dB), ds, ""); \ 174 } while(0) 175 #define PUSH_9(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 176 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd8"); \ 177 PUSH_8(X, DATA_, 1, (ds) + (n), o, (p), s, X##mA, (dA), ##a); \ 178 PUSH_##f(X, (p), X##mB, 0, o, (dB), ds, ""); \ 179 } while(0) 180 #define PUSH_10(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 181 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd9"); \ 182 PUSH_9(X, DATA_, 1, (ds) + (n), o, (p), s, X##mA, (dA), ##a); \ 183 PUSH_##f(X, (p), X##mB, 0, o, (dB), ds, ""); \ 184 } while(0) 185 186 #define PUSH_1D(X,o,p,s,mA,dA) \ 187 PUSH_1(X, DATA_, 1, 0, o, (p), s, X##mA, (dA)) 188 #define PUSH_2D(X,o,p,s,mA,dA,mB,dB) \ 189 PUSH_2(X, DATA_, 1, 0, o, (p), s, X##mB, (dB), \ 190 X##mA, (dA)) 191 #define PUSH_3D(X,o,p,s,mA,dA,mB,dB,mC,dC) \ 192 PUSH_3(X, DATA_, 1, 0, o, (p), s, X##mC, (dC), \ 193 X##mB, (dB), \ 194 X##mA, (dA)) 195 #define PUSH_4D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD) \ 196 PUSH_4(X, DATA_, 1, 0, o, (p), s, X##mD, (dD), \ 197 X##mC, (dC), \ 198 X##mB, (dB), \ 199 X##mA, (dA)) 200 #define PUSH_5D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE) \ 201 PUSH_5(X, DATA_, 1, 0, o, (p), s, X##mE, (dE), \ 202 X##mD, (dD), \ 203 X##mC, (dC), \ 204 X##mB, (dB), \ 205 X##mA, (dA)) 206 #define PUSH_6D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF) \ 207 PUSH_6(X, DATA_, 1, 0, o, (p), s, X##mF, (dF), \ 208 X##mE, (dE), \ 209 X##mD, (dD), \ 210 X##mC, (dC), \ 211 X##mB, (dB), \ 212 X##mA, (dA)) 213 #define PUSH_7D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,dG) \ 214 PUSH_7(X, DATA_, 1, 0, o, (p), s, X##mG, (dG), \ 215 X##mF, (dF), \ 216 X##mE, (dE), \ 217 X##mD, (dD), \ 218 X##mC, (dC), \ 219 X##mB, (dB), \ 220 X##mA, (dA)) 221 #define PUSH_8D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,dG,mH,dH) \ 222 PUSH_8(X, DATA_, 1, 0, o, (p), s, X##mH, (dH), \ 223 X##mG, (dG), \ 224 X##mF, (dF), \ 225 X##mE, (dE), \ 226 X##mD, (dD), \ 227 X##mC, (dC), \ 228 X##mB, (dB), \ 229 X##mA, (dA)) 230 #define PUSH_9D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,dG,mH,dH,mI,dI) \ 231 PUSH_9(X, DATA_, 1, 0, o, (p), s, X##mI, (dI), \ 232 X##mH, (dH), \ 233 X##mG, (dG), \ 234 X##mF, (dF), \ 235 X##mE, (dE), \ 236 X##mD, (dD), \ 237 X##mC, (dC), \ 238 X##mB, (dB), \ 239 X##mA, (dA)) 240 #define PUSH_10D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,dG,mH,dH,mI,dI,mJ,dJ) \ 241 PUSH_10(X, DATA_, 1, 0, o, (p), s, X##mJ, (dJ), \ 242 X##mI, (dI), \ 243 X##mH, (dH), \ 244 X##mG, (dG), \ 245 X##mF, (dF), \ 246 X##mE, (dE), \ 247 X##mD, (dD), \ 248 X##mC, (dC), \ 249 X##mB, (dB), \ 250 X##mA, (dA)) 251 252 #define PUSH_1P(X,o,p,s,mA,dp,ds) \ 253 PUSH_1(X, DATAp, ds, 0, o, (p), s, X##mA, (dp)) 254 #define PUSH_2P(X,o,p,s,mA,dA,mB,dp,ds) \ 255 PUSH_2(X, DATAp, ds, 0, o, (p), s, X##mB, (dp), \ 256 X##mA, (dA)) 257 #define PUSH_3P(X,o,p,s,mA,dA,mB,dB,mC,dp,ds) \ 258 PUSH_3(X, DATAp, ds, 0, o, (p), s, X##mC, (dp), \ 259 X##mB, (dB), \ 260 X##mA, (dA)) 261 262 #define PUSH_(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,IMPL,...) IMPL 263 #define PUSH(A...) PUSH_(A, PUSH_10P, PUSH_10D, \ 264 PUSH_9P , PUSH_9D, \ 265 PUSH_8P , PUSH_8D, \ 266 PUSH_7P , PUSH_7D, \ 267 PUSH_6P , PUSH_6D, \ 268 PUSH_5P , PUSH_5D, \ 269 PUSH_4P , PUSH_4D, \ 270 PUSH_3P , PUSH_3D, \ 271 PUSH_2P , PUSH_2D, \ 272 PUSH_1P , PUSH_1D)(, ##A) 273 274 #define PUSH_NVIM(p,c,m,d) do { \ 275 struct nvif_push *__p = (p); \ 276 u32 __d = (d); \ 277 PUSH_IMMD_HDR(__p, c, m, __d); \ 278 __p->cur--; \ 279 PUSH_PRINTF(__p, "%08x-> "#m, __d); \ 280 __p->cur++; \ 281 } while(0) 282 #define PUSH_NVSQ(A...) PUSH(MTHD, ##A) 283 #define PUSH_NV1I(A...) PUSH(1INC, ##A) 284 #define PUSH_NVNI(A...) PUSH(NINC, ##A) 285 286 287 #define PUSH_NV_1(X,o,p,c,mA,d...) \ 288 PUSH_##o(p,c,c##_##mA,d) 289 #define PUSH_NV_2(X,o,p,c,mA,dA,mB,d...) \ 290 PUSH_##o(p,c,c##_##mA,dA, \ 291 c##_##mB,d) 292 #define PUSH_NV_3(X,o,p,c,mA,dA,mB,dB,mC,d...) \ 293 PUSH_##o(p,c,c##_##mA,dA, \ 294 c##_##mB,dB, \ 295 c##_##mC,d) 296 #define PUSH_NV_4(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,d...) \ 297 PUSH_##o(p,c,c##_##mA,dA, \ 298 c##_##mB,dB, \ 299 c##_##mC,dC, \ 300 c##_##mD,d) 301 #define PUSH_NV_5(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,dD,mE,d...) \ 302 PUSH_##o(p,c,c##_##mA,dA, \ 303 c##_##mB,dB, \ 304 c##_##mC,dC, \ 305 c##_##mD,dD, \ 306 c##_##mE,d) 307 #define PUSH_NV_6(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,d...) \ 308 PUSH_##o(p,c,c##_##mA,dA, \ 309 c##_##mB,dB, \ 310 c##_##mC,dC, \ 311 c##_##mD,dD, \ 312 c##_##mE,dE, \ 313 c##_##mF,d) 314 #define PUSH_NV_7(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,d...) \ 315 PUSH_##o(p,c,c##_##mA,dA, \ 316 c##_##mB,dB, \ 317 c##_##mC,dC, \ 318 c##_##mD,dD, \ 319 c##_##mE,dE, \ 320 c##_##mF,dF, \ 321 c##_##mG,d) 322 #define PUSH_NV_8(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,dG,mH,d...) \ 323 PUSH_##o(p,c,c##_##mA,dA, \ 324 c##_##mB,dB, \ 325 c##_##mC,dC, \ 326 c##_##mD,dD, \ 327 c##_##mE,dE, \ 328 c##_##mF,dF, \ 329 c##_##mG,dG, \ 330 c##_##mH,d) 331 #define PUSH_NV_9(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,dG,mH,dH,mI,d...) \ 332 PUSH_##o(p,c,c##_##mA,dA, \ 333 c##_##mB,dB, \ 334 c##_##mC,dC, \ 335 c##_##mD,dD, \ 336 c##_##mE,dE, \ 337 c##_##mF,dF, \ 338 c##_##mG,dG, \ 339 c##_##mH,dH, \ 340 c##_##mI,d) 341 #define PUSH_NV_10(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,dG,mH,dH,mI,dI,mJ,d...) \ 342 PUSH_##o(p,c,c##_##mA,dA, \ 343 c##_##mB,dB, \ 344 c##_##mC,dC, \ 345 c##_##mD,dD, \ 346 c##_##mE,dE, \ 347 c##_##mF,dF, \ 348 c##_##mG,dG, \ 349 c##_##mH,dH, \ 350 c##_##mI,dI, \ 351 c##_##mJ,d) 352 353 #define PUSH_NV_(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,IMPL,...) IMPL 354 #define PUSH_NV(A...) PUSH_NV_(A, PUSH_NV_10, PUSH_NV_10, \ 355 PUSH_NV_9 , PUSH_NV_9, \ 356 PUSH_NV_8 , PUSH_NV_8, \ 357 PUSH_NV_7 , PUSH_NV_7, \ 358 PUSH_NV_6 , PUSH_NV_6, \ 359 PUSH_NV_5 , PUSH_NV_5, \ 360 PUSH_NV_4 , PUSH_NV_4, \ 361 PUSH_NV_3 , PUSH_NV_3, \ 362 PUSH_NV_2 , PUSH_NV_2, \ 363 PUSH_NV_1 , PUSH_NV_1)(, ##A) 364 365 #define PUSH_IMMD(A...) PUSH_NV(NVIM, ##A) 366 #define PUSH_MTHD(A...) PUSH_NV(NVSQ, ##A) 367 #define PUSH_1INC(A...) PUSH_NV(NV1I, ##A) 368 #define PUSH_NINC(A...) PUSH_NV(NVNI, ##A) 369 #endif 370