2012-04-30 13:55:29 +10:00
/*
* Copyright 2012 Red Hat Inc .
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE COPYRIGHT HOLDER ( S ) OR AUTHOR ( S ) BE LIABLE FOR ANY CLAIM , DAMAGES OR
* OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE ,
* ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE .
*
* Authors : Ben Skeggs
*/
2016-05-20 09:22:55 +10:00
# include "nouveau_drv.h"
2012-07-20 08:17:34 +10:00
# include "nouveau_dma.h"
2012-04-30 13:55:29 +10:00
# include "nouveau_fence.h"
2017-11-01 03:56:19 +10:00
# include "nouveau_vmm.h"
2012-04-30 13:55:29 +10:00
2012-07-31 16:16:21 +10:00
# include "nv50_display.h"
2020-06-22 20:18:06 +10:00
# include <nvif/push206e.h>
2020-07-20 11:19:14 +10:00
# include <nvhw/class/cl826f.h>
2012-04-30 13:55:29 +10:00
static int
2013-02-14 09:37:35 +10:00
nv84_fence_emit32 ( struct nouveau_channel * chan , u64 virtual , u32 sequence )
2012-04-30 13:55:29 +10:00
{
2020-06-22 20:18:06 +10:00
struct nvif_push * push = chan - > chan . push ;
int ret = PUSH_WAIT ( push , 8 ) ;
2012-04-30 13:55:29 +10:00
if ( ret = = 0 ) {
2020-07-20 11:19:14 +10:00
PUSH_MTHD ( push , NV826F , SET_CONTEXT_DMA_SEMAPHORE , chan - > vram . handle ) ;
PUSH_MTHD ( push , NV826F , SEMAPHOREA ,
NVVAL ( NV826F , SEMAPHOREA , OFFSET_UPPER , upper_32_bits ( virtual ) ) ,
SEMAPHOREB , lower_32_bits ( virtual ) ,
SEMAPHOREC , sequence ,
SEMAPHORED ,
NVDEF ( NV826F , SEMAPHORED , OPERATION , RELEASE ) ,
NON_STALLED_INTERRUPT , 0 ) ;
2020-06-22 20:18:06 +10:00
PUSH_KICK ( push ) ;
2012-04-30 13:55:29 +10:00
}
return ret ;
}
static int
2013-02-14 09:37:35 +10:00
nv84_fence_sync32 ( struct nouveau_channel * chan , u64 virtual , u32 sequence )
2012-04-30 13:55:29 +10:00
{
2020-06-22 20:26:07 +10:00
struct nvif_push * push = chan - > chan . push ;
int ret = PUSH_WAIT ( push , 7 ) ;
2012-04-30 13:55:29 +10:00
if ( ret = = 0 ) {
2020-07-20 11:19:26 +10:00
PUSH_MTHD ( push , NV826F , SET_CONTEXT_DMA_SEMAPHORE , chan - > vram . handle ) ;
PUSH_MTHD ( push , NV826F , SEMAPHOREA ,
NVVAL ( NV826F , SEMAPHOREA , OFFSET_UPPER , upper_32_bits ( virtual ) ) ,
SEMAPHOREB , lower_32_bits ( virtual ) ,
SEMAPHOREC , sequence ,
SEMAPHORED ,
NVDEF ( NV826F , SEMAPHORED , OPERATION , ACQ_GEQ ) ) ;
2020-06-22 20:26:07 +10:00
PUSH_KICK ( push ) ;
2012-04-30 13:55:29 +10:00
}
return ret ;
}
2013-02-14 13:43:21 +10:00
static int
2013-02-14 09:37:35 +10:00
nv84_fence_emit ( struct nouveau_fence * fence )
{
struct nouveau_channel * chan = fence - > channel ;
struct nv84_fence_chan * fctx = chan - > fence ;
2017-11-01 03:56:19 +10:00
u64 addr = fctx - > vma - > addr + chan - > chid * 16 ;
2013-02-14 13:43:21 +10:00
2014-01-09 11:03:11 +01:00
return fctx - > base . emit32 ( chan , addr , fence - > base . seqno ) ;
2013-02-14 09:37:35 +10:00
}
2013-02-14 13:43:21 +10:00
static int
2013-02-14 09:37:35 +10:00
nv84_fence_sync ( struct nouveau_fence * fence ,
struct nouveau_channel * prev , struct nouveau_channel * chan )
{
struct nv84_fence_chan * fctx = chan - > fence ;
2017-11-01 03:56:19 +10:00
u64 addr = fctx - > vma - > addr + prev - > chid * 16 ;
2013-02-14 13:43:21 +10:00
2014-01-09 11:03:11 +01:00
return fctx - > base . sync32 ( chan , addr , fence - > base . seqno ) ;
2013-02-14 09:37:35 +10:00
}
2013-02-14 13:43:21 +10:00
static u32
2012-04-30 13:55:29 +10:00
nv84_fence_read ( struct nouveau_channel * chan )
{
2012-07-20 08:17:34 +10:00
struct nv84_fence_priv * priv = chan - > drm - > fence ;
2014-08-10 04:10:25 +10:00
return nouveau_bo_rd32 ( priv - > bo , chan - > chid * 16 / 4 ) ;
2012-04-30 13:55:29 +10:00
}
2013-02-14 13:43:21 +10:00
static void
2012-07-19 10:51:42 +10:00
nv84_fence_context_del ( struct nouveau_channel * chan )
2012-04-30 13:55:29 +10:00
{
2013-02-14 09:28:37 +10:00
struct nv84_fence_priv * priv = chan - > drm - > fence ;
2012-07-19 10:51:42 +10:00
struct nv84_fence_chan * fctx = chan - > fence ;
2013-02-14 09:28:37 +10:00
2014-09-22 11:08:48 +02:00
nouveau_bo_wr32 ( priv - > bo , chan - > chid * 16 / 4 , fctx - > base . sequence ) ;
2016-12-14 09:52:39 +10:00
mutex_lock ( & priv - > mutex ) ;
2017-11-01 03:56:19 +10:00
nouveau_vma_del ( & fctx - > vma ) ;
2016-12-14 09:52:39 +10:00
mutex_unlock ( & priv - > mutex ) ;
2012-04-30 13:55:29 +10:00
nouveau_fence_context_del ( & fctx - > base ) ;
2012-07-19 10:51:42 +10:00
chan - > fence = NULL ;
2014-09-29 10:06:18 +02:00
nouveau_fence_context_free ( & fctx - > base ) ;
2012-04-30 13:55:29 +10:00
}
2013-02-14 09:28:37 +10:00
int
2012-07-19 10:51:42 +10:00
nv84_fence_context_new ( struct nouveau_channel * chan )
2012-04-30 13:55:29 +10:00
{
2012-07-20 08:17:34 +10:00
struct nv84_fence_priv * priv = chan - > drm - > fence ;
2012-04-30 13:55:29 +10:00
struct nv84_fence_chan * fctx ;
2016-11-04 17:20:36 +10:00
int ret ;
2012-04-30 13:55:29 +10:00
2012-07-19 10:51:42 +10:00
fctx = chan - > fence = kzalloc ( sizeof ( * fctx ) , GFP_KERNEL ) ;
2012-04-30 13:55:29 +10:00
if ( ! fctx )
return - ENOMEM ;
2014-01-09 11:03:11 +01:00
nouveau_fence_context_new ( chan , & fctx - > base ) ;
2013-02-14 13:20:17 +10:00
fctx - > base . emit = nv84_fence_emit ;
fctx - > base . sync = nv84_fence_sync ;
fctx - > base . read = nv84_fence_read ;
fctx - > base . emit32 = nv84_fence_emit32 ;
fctx - > base . sync32 = nv84_fence_sync32 ;
2014-01-09 11:03:11 +01:00
fctx - > base . sequence = nv84_fence_read ( chan ) ;
2012-04-30 13:55:29 +10:00
2016-12-14 09:52:39 +10:00
mutex_lock ( & priv - > mutex ) ;
2019-02-19 17:21:48 +10:00
ret = nouveau_vma_new ( priv - > bo , chan - > vmm , & fctx - > vma ) ;
2016-12-14 09:52:39 +10:00
mutex_unlock ( & priv - > mutex ) ;
2012-07-20 08:17:34 +10:00
2013-02-14 13:43:21 +10:00
if ( ret )
nv84_fence_context_del ( chan ) ;
2012-04-30 13:55:29 +10:00
return ret ;
}
2013-02-14 13:43:21 +10:00
static bool
2013-02-14 09:28:37 +10:00
nv84_fence_suspend ( struct nouveau_drm * drm )
{
struct nv84_fence_priv * priv = drm - > fence ;
int i ;
treewide: Use array_size() in vmalloc()
The vmalloc() function has no 2-factor argument form, so multiplication
factors need to be wrapped in array_size(). This patch replaces cases of:
vmalloc(a * b)
with:
vmalloc(array_size(a, b))
as well as handling cases of:
vmalloc(a * b * c)
with:
vmalloc(array3_size(a, b, c))
This does, however, attempt to ignore constant size factors like:
vmalloc(4 * 1024)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
vmalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
vmalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
vmalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
vmalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
vmalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
vmalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
vmalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
vmalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
vmalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
vmalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
vmalloc(
- sizeof(TYPE) * (COUNT_ID)
+ array_size(COUNT_ID, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * COUNT_ID
+ array_size(COUNT_ID, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * (COUNT_CONST)
+ array_size(COUNT_CONST, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * COUNT_CONST
+ array_size(COUNT_CONST, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(THING) * (COUNT_ID)
+ array_size(COUNT_ID, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * COUNT_ID
+ array_size(COUNT_ID, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * (COUNT_CONST)
+ array_size(COUNT_CONST, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * COUNT_CONST
+ array_size(COUNT_CONST, sizeof(THING))
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
vmalloc(
- SIZE * COUNT
+ array_size(COUNT, SIZE)
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
vmalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vmalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vmalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
vmalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
vmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
vmalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
vmalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
vmalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
vmalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
vmalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vmalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
vmalloc(C1 * C2 * C3, ...)
|
vmalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants.
@@
expression E1, E2;
constant C1, C2;
@@
(
vmalloc(C1 * C2, ...)
|
vmalloc(
- E1 * E2
+ array_size(E1, E2)
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 14:27:11 -07:00
priv - > suspend = vmalloc ( array_size ( sizeof ( u32 ) , drm - > chan . nr ) ) ;
2013-02-14 09:28:37 +10:00
if ( priv - > suspend ) {
2018-05-08 20:39:46 +10:00
for ( i = 0 ; i < drm - > chan . nr ; i + + )
2013-02-14 09:28:37 +10:00
priv - > suspend [ i ] = nouveau_bo_rd32 ( priv - > bo , i * 4 ) ;
}
return priv - > suspend ! = NULL ;
}
2013-02-14 13:43:21 +10:00
static void
2013-02-14 09:28:37 +10:00
nv84_fence_resume ( struct nouveau_drm * drm )
{
struct nv84_fence_priv * priv = drm - > fence ;
int i ;
if ( priv - > suspend ) {
2018-05-08 20:39:46 +10:00
for ( i = 0 ; i < drm - > chan . nr ; i + + )
2013-02-14 09:28:37 +10:00
nouveau_bo_wr32 ( priv - > bo , i * 4 , priv - > suspend [ i ] ) ;
vfree ( priv - > suspend ) ;
priv - > suspend = NULL ;
}
}
2013-02-14 13:43:21 +10:00
static void
2012-07-20 08:17:34 +10:00
nv84_fence_destroy ( struct nouveau_drm * drm )
2012-04-30 13:55:29 +10:00
{
2012-07-20 08:17:34 +10:00
struct nv84_fence_priv * priv = drm - > fence ;
2013-02-14 09:28:37 +10:00
nouveau_bo_unmap ( priv - > bo ) ;
if ( priv - > bo )
nouveau_bo_unpin ( priv - > bo ) ;
nouveau_bo_ref ( NULL , & priv - > bo ) ;
2012-07-20 08:17:34 +10:00
drm - > fence = NULL ;
2012-04-30 13:55:29 +10:00
kfree ( priv ) ;
}
int
2012-07-20 08:17:34 +10:00
nv84_fence_create ( struct nouveau_drm * drm )
2012-04-30 13:55:29 +10:00
{
struct nv84_fence_priv * priv ;
2015-02-20 18:22:59 +09:00
u32 domain ;
2012-04-30 13:55:29 +10:00
int ret ;
2012-07-20 08:17:34 +10:00
priv = drm - > fence = kzalloc ( sizeof ( * priv ) , GFP_KERNEL ) ;
2012-04-30 13:55:29 +10:00
if ( ! priv )
return - ENOMEM ;
2012-07-19 10:51:42 +10:00
priv - > base . dtor = nv84_fence_destroy ;
2013-02-14 09:28:37 +10:00
priv - > base . suspend = nv84_fence_suspend ;
priv - > base . resume = nv84_fence_resume ;
2012-07-19 10:51:42 +10:00
priv - > base . context_new = nv84_fence_context_new ;
priv - > base . context_del = nv84_fence_context_del ;
2012-04-30 13:55:29 +10:00
2021-09-17 08:04:06 +10:00
priv - > base . uevent = drm - > client . device . info . family < NV_DEVICE_INFO_V0_AMPERE ;
2013-01-31 14:57:33 +10:00
2016-12-14 09:52:39 +10:00
mutex_init ( & priv - > mutex ) ;
2015-02-20 18:22:59 +09:00
/* Use VRAM if there is any ; otherwise fallback to system memory */
2020-09-08 14:39:36 +02:00
domain = drm - > client . device . info . ram_size ! = 0 ?
NOUVEAU_GEM_DOMAIN_VRAM :
/*
* fences created in sysmem must be non - cached or we
* will lose CPU / GPU coherency !
*/
NOUVEAU_GEM_DOMAIN_GART | NOUVEAU_GEM_DOMAIN_COHERENT ;
2018-05-08 20:39:46 +10:00
ret = nouveau_bo_new ( & drm - > client , 16 * drm - > chan . nr , 0 ,
2016-05-24 17:26:48 +10:00
domain , 0 , 0 , NULL , NULL , & priv - > bo ) ;
2013-02-14 09:28:37 +10:00
if ( ret = = 0 ) {
2015-02-20 18:22:59 +09:00
ret = nouveau_bo_pin ( priv - > bo , domain , false ) ;
2013-02-14 09:28:37 +10:00
if ( ret = = 0 ) {
ret = nouveau_bo_map ( priv - > bo ) ;
if ( ret )
nouveau_bo_unpin ( priv - > bo ) ;
}
if ( ret )
nouveau_bo_ref ( NULL , & priv - > bo ) ;
}
2012-04-30 13:55:29 +10:00
if ( ret )
2012-07-20 08:17:34 +10:00
nv84_fence_destroy ( drm ) ;
2012-04-30 13:55:29 +10:00
return ret ;
}