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 35 u32 *bgn; 36 u32 *cur; 37 u32 *seg; 38 u32 *end; 39 }; 40 41 static inline __must_check int 42 PUSH_WAIT(struct nvif_push *push, u32 size) 43 { 44 if (push->cur + size >= push->end) { 45 int ret = push->wait(push, size); 46 if (ret) 47 return ret; 48 } 49 #ifdef CONFIG_NOUVEAU_DEBUG_PUSH 50 push->seg = push->cur + size; 51 #endif 52 return 0; 53 } 54 55 static inline int 56 PUSH_KICK(struct nvif_push *push) 57 { 58 push->kick(push); 59 return 0; 60 } 61 62 #ifdef CONFIG_NOUVEAU_DEBUG_PUSH 63 #define PUSH_PRINTF(p,f,a...) do { \ 64 struct nvif_push *_ppp = (p); \ 65 u32 __o = _ppp->cur - (u32 *)_ppp->mem.object.map.ptr; \ 66 NVIF_DEBUG(&_ppp->mem.object, "%08x: "f, __o * 4, ##a); \ 67 (void)__o; \ 68 } while(0) 69 #define PUSH_ASSERT_ON(a,b) WARN((a), b) 70 #else 71 #define PUSH_PRINTF(p,f,a...) 72 #define PUSH_ASSERT_ON(a, b) 73 #endif 74 75 #define PUSH_ASSERT(a,b) do { \ 76 static_assert( \ 77 __builtin_choose_expr(__builtin_constant_p(a), (a), 1), b \ 78 ); \ 79 PUSH_ASSERT_ON(!(a), b); \ 80 } while(0) 81 82 #define PUSH_DATA__(p,d,f,a...) do { \ 83 struct nvif_push *_p = (p); \ 84 u32 _d = (d); \ 85 PUSH_ASSERT(_p->cur < _p->seg, "segment overrun"); \ 86 PUSH_ASSERT(_p->cur < _p->end, "pushbuf overrun"); \ 87 PUSH_PRINTF(_p, "%08x"f, _d, ##a); \ 88 *_p->cur++ = _d; \ 89 } while(0) 90 91 #define PUSH_DATA_(X,p,m,i0,i1,d,s,f,a...) PUSH_DATA__((p), (d), "-> "#m f, ##a) 92 #define PUSH_DATA(p,d) PUSH_DATA__((p), (d), " data - %s", __func__) 93 94 //XXX: error-check this against *real* pushbuffer end? 95 #define PUSH_RSVD(p,d) do { \ 96 struct nvif_push *__p = (p); \ 97 __p->seg++; \ 98 __p->end++; \ 99 d; \ 100 } while(0) 101 102 #ifdef CONFIG_NOUVEAU_DEBUG_PUSH 103 #define PUSH_DATAp(X,p,m,i,o,d,s,f,a...) do { \ 104 struct nvif_push *_pp = (p); \ 105 const u32 *_dd = (d); \ 106 u32 _s = (s), _i = (i?PUSH_##o##_INC); \ 107 if (_s--) { \ 108 PUSH_DATA_(X, _pp, X##m, i0, i1, *_dd++, 1, "+0x%x", 0); \ 109 while (_s--) { \ 110 PUSH_DATA_(X, _pp, X##m, i0, i1, *_dd++, 1, "+0x%x", _i); \ 111 _i += (0?PUSH_##o##_INC); \ 112 } \ 113 } \ 114 } while(0) 115 #else 116 #define PUSH_DATAp(X,p,m,i,o,d,s,f,a...) do { \ 117 struct nvif_push *_p = (p); \ 118 u32 _s = (s); \ 119 PUSH_ASSERT(_p->cur + _s <= _p->seg, "segment overrun"); \ 120 PUSH_ASSERT(_p->cur + _s <= _p->end, "pushbuf overrun"); \ 121 memcpy(_p->cur, (d), _s << 2); \ 122 _p->cur += _s; \ 123 } while(0) 124 #endif 125 126 #define PUSH_1(X,f,ds,n,o,p,s,mA,dA) do { \ 127 PUSH_##o##_HDR((p), s, mA, (ds)+(n)); \ 128 PUSH_##f(X, (p), X##mA, 1, o, (dA), ds, ""); \ 129 } while(0) 130 #define PUSH_2(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 131 PUSH_ASSERT((mB) - (mA) == (1?PUSH_##o##_INC), "mthd1"); \ 132 PUSH_1(X, DATA_, 1, (ds) + (n), o, (p), s, X##mA, (dA), ##a); \ 133 PUSH_##f(X, (p), X##mB, 0, o, (dB), ds, ""); \ 134 } while(0) 135 #define PUSH_3(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 136 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd2"); \ 137 PUSH_2(X, DATA_, 1, (ds) + (n), o, (p), s, X##mA, (dA), ##a); \ 138 PUSH_##f(X, (p), X##mB, 0, o, (dB), ds, ""); \ 139 } while(0) 140 #define PUSH_4(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 141 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd3"); \ 142 PUSH_3(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_5(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 146 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd4"); \ 147 PUSH_4(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_6(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 151 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd5"); \ 152 PUSH_5(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_7(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 156 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd6"); \ 157 PUSH_6(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_8(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 161 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd7"); \ 162 PUSH_7(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_9(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 166 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd8"); \ 167 PUSH_8(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_10(X,f,ds,n,o,p,s,mB,dB,mA,dA,a...) do { \ 171 PUSH_ASSERT((mB) - (mA) == (0?PUSH_##o##_INC), "mthd9"); \ 172 PUSH_9(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 176 #define PUSH_1D(X,o,p,s,mA,dA) \ 177 PUSH_1(X, DATA_, 1, 0, o, (p), s, X##mA, (dA)) 178 #define PUSH_2D(X,o,p,s,mA,dA,mB,dB) \ 179 PUSH_2(X, DATA_, 1, 0, o, (p), s, X##mB, (dB), \ 180 X##mA, (dA)) 181 #define PUSH_3D(X,o,p,s,mA,dA,mB,dB,mC,dC) \ 182 PUSH_3(X, DATA_, 1, 0, o, (p), s, X##mC, (dC), \ 183 X##mB, (dB), \ 184 X##mA, (dA)) 185 #define PUSH_4D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD) \ 186 PUSH_4(X, DATA_, 1, 0, o, (p), s, X##mD, (dD), \ 187 X##mC, (dC), \ 188 X##mB, (dB), \ 189 X##mA, (dA)) 190 #define PUSH_5D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE) \ 191 PUSH_5(X, DATA_, 1, 0, o, (p), s, X##mE, (dE), \ 192 X##mD, (dD), \ 193 X##mC, (dC), \ 194 X##mB, (dB), \ 195 X##mA, (dA)) 196 #define PUSH_6D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF) \ 197 PUSH_6(X, DATA_, 1, 0, o, (p), s, X##mF, (dF), \ 198 X##mE, (dE), \ 199 X##mD, (dD), \ 200 X##mC, (dC), \ 201 X##mB, (dB), \ 202 X##mA, (dA)) 203 #define PUSH_7D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,dG) \ 204 PUSH_7(X, DATA_, 1, 0, o, (p), s, X##mG, (dG), \ 205 X##mF, (dF), \ 206 X##mE, (dE), \ 207 X##mD, (dD), \ 208 X##mC, (dC), \ 209 X##mB, (dB), \ 210 X##mA, (dA)) 211 #define PUSH_8D(X,o,p,s,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,dG,mH,dH) \ 212 PUSH_8(X, DATA_, 1, 0, o, (p), s, X##mH, (dH), \ 213 X##mG, (dG), \ 214 X##mF, (dF), \ 215 X##mE, (dE), \ 216 X##mD, (dD), \ 217 X##mC, (dC), \ 218 X##mB, (dB), \ 219 X##mA, (dA)) 220 #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) \ 221 PUSH_9(X, DATA_, 1, 0, o, (p), s, X##mI, (dI), \ 222 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_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) \ 231 PUSH_10(X, DATA_, 1, 0, o, (p), s, X##mJ, (dJ), \ 232 X##mI, (dI), \ 233 X##mH, (dH), \ 234 X##mG, (dG), \ 235 X##mF, (dF), \ 236 X##mE, (dE), \ 237 X##mD, (dD), \ 238 X##mC, (dC), \ 239 X##mB, (dB), \ 240 X##mA, (dA)) 241 242 #define PUSH_1P(X,o,p,s,mA,dp,ds) \ 243 PUSH_1(X, DATAp, ds, 0, o, (p), s, X##mA, (dp)) 244 #define PUSH_2P(X,o,p,s,mA,dA,mB,dp,ds) \ 245 PUSH_2(X, DATAp, ds, 0, o, (p), s, X##mB, (dp), \ 246 X##mA, (dA)) 247 #define PUSH_3P(X,o,p,s,mA,dA,mB,dB,mC,dp,ds) \ 248 PUSH_3(X, DATAp, ds, 0, o, (p), s, X##mC, (dp), \ 249 X##mB, (dB), \ 250 X##mA, (dA)) 251 252 #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 253 #define PUSH(A...) PUSH_(A, PUSH_10P, PUSH_10D, \ 254 PUSH_9P , PUSH_9D, \ 255 PUSH_8P , PUSH_8D, \ 256 PUSH_7P , PUSH_7D, \ 257 PUSH_6P , PUSH_6D, \ 258 PUSH_5P , PUSH_5D, \ 259 PUSH_4P , PUSH_4D, \ 260 PUSH_3P , PUSH_3D, \ 261 PUSH_2P , PUSH_2D, \ 262 PUSH_1P , PUSH_1D)(, ##A) 263 264 #define PUSH_NVIM(p,c,m,d) do { \ 265 struct nvif_push *__p = (p); \ 266 u32 __d = (d); \ 267 PUSH_IMMD_HDR(__p, c, m, __d); \ 268 __p->cur--; \ 269 PUSH_PRINTF(__p, "%08x-> "#m, __d); \ 270 __p->cur++; \ 271 } while(0) 272 #define PUSH_NVSQ(A...) PUSH(MTHD, ##A) 273 #define PUSH_NV1I(A...) PUSH(1INC, ##A) 274 #define PUSH_NVNI(A...) PUSH(NINC, ##A) 275 276 277 #define PUSH_NV_1(X,o,p,c,mA,d...) \ 278 PUSH_##o(p,c,c##_##mA,d) 279 #define PUSH_NV_2(X,o,p,c,mA,dA,mB,d...) \ 280 PUSH_##o(p,c,c##_##mA,dA, \ 281 c##_##mB,d) 282 #define PUSH_NV_3(X,o,p,c,mA,dA,mB,dB,mC,d...) \ 283 PUSH_##o(p,c,c##_##mA,dA, \ 284 c##_##mB,dB, \ 285 c##_##mC,d) 286 #define PUSH_NV_4(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,d...) \ 287 PUSH_##o(p,c,c##_##mA,dA, \ 288 c##_##mB,dB, \ 289 c##_##mC,dC, \ 290 c##_##mD,d) 291 #define PUSH_NV_5(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,dD,mE,d...) \ 292 PUSH_##o(p,c,c##_##mA,dA, \ 293 c##_##mB,dB, \ 294 c##_##mC,dC, \ 295 c##_##mD,dD, \ 296 c##_##mE,d) 297 #define PUSH_NV_6(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,d...) \ 298 PUSH_##o(p,c,c##_##mA,dA, \ 299 c##_##mB,dB, \ 300 c##_##mC,dC, \ 301 c##_##mD,dD, \ 302 c##_##mE,dE, \ 303 c##_##mF,d) 304 #define PUSH_NV_7(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,d...) \ 305 PUSH_##o(p,c,c##_##mA,dA, \ 306 c##_##mB,dB, \ 307 c##_##mC,dC, \ 308 c##_##mD,dD, \ 309 c##_##mE,dE, \ 310 c##_##mF,dF, \ 311 c##_##mG,d) 312 #define PUSH_NV_8(X,o,p,c,mA,dA,mB,dB,mC,dC,mD,dD,mE,dE,mF,dF,mG,dG,mH,d...) \ 313 PUSH_##o(p,c,c##_##mA,dA, \ 314 c##_##mB,dB, \ 315 c##_##mC,dC, \ 316 c##_##mD,dD, \ 317 c##_##mE,dE, \ 318 c##_##mF,dF, \ 319 c##_##mG,dG, \ 320 c##_##mH,d) 321 #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...) \ 322 PUSH_##o(p,c,c##_##mA,dA, \ 323 c##_##mB,dB, \ 324 c##_##mC,dC, \ 325 c##_##mD,dD, \ 326 c##_##mE,dE, \ 327 c##_##mF,dF, \ 328 c##_##mG,dG, \ 329 c##_##mH,dH, \ 330 c##_##mI,d) 331 #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...) \ 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,dI, \ 341 c##_##mJ,d) 342 343 #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 344 #define PUSH_NV(A...) PUSH_NV_(A, PUSH_NV_10, PUSH_NV_10, \ 345 PUSH_NV_9 , PUSH_NV_9, \ 346 PUSH_NV_8 , PUSH_NV_8, \ 347 PUSH_NV_7 , PUSH_NV_7, \ 348 PUSH_NV_6 , PUSH_NV_6, \ 349 PUSH_NV_5 , PUSH_NV_5, \ 350 PUSH_NV_4 , PUSH_NV_4, \ 351 PUSH_NV_3 , PUSH_NV_3, \ 352 PUSH_NV_2 , PUSH_NV_2, \ 353 PUSH_NV_1 , PUSH_NV_1)(, ##A) 354 355 #define PUSH_IMMD(A...) PUSH_NV(NVIM, ##A) 356 #define PUSH_MTHD(A...) PUSH_NV(NVSQ, ##A) 357 #define PUSH_1INC(A...) PUSH_NV(NV1I, ##A) 358 #define PUSH_NINC(A...) PUSH_NV(NVNI, ##A) 359 #endif 360