@@ -1624,7 +1624,7 @@ r535_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
16241624 meta -> magic = GSP_FW_WPR_META_MAGIC ;
16251625 meta -> revision = GSP_FW_WPR_META_REVISION ;
16261626
1627- meta -> sysmemAddrOfRadix3Elf = gsp -> radix3 .mem [ 0 ] .addr ;
1627+ meta -> sysmemAddrOfRadix3Elf = gsp -> radix3 .lvl0 .addr ;
16281628 meta -> sizeOfRadix3Elf = gsp -> fb .wpr2 .elf .size ;
16291629
16301630 meta -> sysmemAddrOfBootloader = gsp -> boot .fw .addr ;
@@ -1919,8 +1919,9 @@ nvkm_gsp_sg(struct nvkm_device *device, u64 size, struct sg_table *sgt)
19191919static void
19201920nvkm_gsp_radix3_dtor (struct nvkm_gsp * gsp , struct nvkm_gsp_radix3 * rx3 )
19211921{
1922- for (int i = ARRAY_SIZE (rx3 -> mem ) - 1 ; i >= 0 ; i -- )
1923- nvkm_gsp_mem_dtor (gsp , & rx3 -> mem [i ]);
1922+ nvkm_gsp_sg_free (gsp -> subdev .device , & rx3 -> lvl2 );
1923+ nvkm_gsp_mem_dtor (gsp , & rx3 -> lvl1 );
1924+ nvkm_gsp_mem_dtor (gsp , & rx3 -> lvl0 );
19241925}
19251926
19261927/**
@@ -1960,36 +1961,60 @@ static int
19601961nvkm_gsp_radix3_sg (struct nvkm_gsp * gsp , struct sg_table * sgt , u64 size ,
19611962 struct nvkm_gsp_radix3 * rx3 )
19621963{
1963- u64 addr ;
1964+ struct sg_dma_page_iter sg_dma_iter ;
1965+ struct scatterlist * sg ;
1966+ size_t bufsize ;
1967+ u64 * pte ;
1968+ int ret , i , page_idx = 0 ;
19641969
1965- for (int i = ARRAY_SIZE (rx3 -> mem ) - 1 ; i >= 0 ; i -- ) {
1966- u64 * ptes ;
1967- size_t bufsize ;
1968- int ret , idx ;
1970+ ret = nvkm_gsp_mem_ctor (gsp , GSP_PAGE_SIZE , & rx3 -> lvl0 );
1971+ if (ret )
1972+ return ret ;
19691973
1970- bufsize = ALIGN ((size / GSP_PAGE_SIZE ) * sizeof (u64 ), GSP_PAGE_SIZE );
1971- ret = nvkm_gsp_mem_ctor (gsp , bufsize , & rx3 -> mem [i ]);
1972- if (ret )
1973- return ret ;
1974+ ret = nvkm_gsp_mem_ctor (gsp , GSP_PAGE_SIZE , & rx3 -> lvl1 );
1975+ if (ret )
1976+ goto lvl1_fail ;
19741977
1975- ptes = rx3 -> mem [i ].data ;
1976- if (i == 2 ) {
1977- struct scatterlist * sgl ;
1978+ // Allocate level 2
1979+ bufsize = ALIGN ((size / GSP_PAGE_SIZE ) * sizeof (u64 ), GSP_PAGE_SIZE );
1980+ ret = nvkm_gsp_sg (gsp -> subdev .device , bufsize , & rx3 -> lvl2 );
1981+ if (ret )
1982+ goto lvl2_fail ;
19781983
1979- for_each_sgtable_dma_sg (sgt , sgl , idx ) {
1980- for (int j = 0 ; j < sg_dma_len (sgl ) / GSP_PAGE_SIZE ; j ++ )
1981- * ptes ++ = sg_dma_address (sgl ) + (GSP_PAGE_SIZE * j );
1982- }
1983- } else {
1984- for (int j = 0 ; j < size / GSP_PAGE_SIZE ; j ++ )
1985- * ptes ++ = addr + GSP_PAGE_SIZE * j ;
1984+ // Write the bus address of level 1 to level 0
1985+ pte = rx3 -> lvl0 .data ;
1986+ * pte = rx3 -> lvl1 .addr ;
1987+
1988+ // Write the bus address of each page in level 2 to level 1
1989+ pte = rx3 -> lvl1 .data ;
1990+ for_each_sgtable_dma_page (& rx3 -> lvl2 , & sg_dma_iter , 0 )
1991+ * pte ++ = sg_page_iter_dma_address (& sg_dma_iter );
1992+
1993+ // Finally, write the bus address of each page in sgt to level 2
1994+ for_each_sgtable_sg (& rx3 -> lvl2 , sg , i ) {
1995+ void * sgl_end ;
1996+
1997+ pte = sg_virt (sg );
1998+ sgl_end = (void * )pte + sg -> length ;
1999+
2000+ for_each_sgtable_dma_page (sgt , & sg_dma_iter , page_idx ) {
2001+ * pte ++ = sg_page_iter_dma_address (& sg_dma_iter );
2002+ page_idx ++ ;
2003+
2004+ // Go to the next scatterlist for level 2 if we've reached the end
2005+ if ((void * )pte >= sgl_end )
2006+ break ;
19862007 }
2008+ }
19872009
1988- size = rx3 -> mem [i ].size ;
1989- addr = rx3 -> mem [i ].addr ;
2010+ if (ret ) {
2011+ lvl2_fail :
2012+ nvkm_gsp_mem_dtor (gsp , & rx3 -> lvl1 );
2013+ lvl1_fail :
2014+ nvkm_gsp_mem_dtor (gsp , & rx3 -> lvl0 );
19902015 }
19912016
1992- return 0 ;
2017+ return ret ;
19932018}
19942019
19952020int
@@ -2021,7 +2046,7 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
20212046 sr = gsp -> sr .meta .data ;
20222047 sr -> magic = GSP_FW_SR_META_MAGIC ;
20232048 sr -> revision = GSP_FW_SR_META_REVISION ;
2024- sr -> sysmemAddrOfSuspendResumeData = gsp -> sr .radix3 .mem [ 0 ] .addr ;
2049+ sr -> sysmemAddrOfSuspendResumeData = gsp -> sr .radix3 .lvl0 .addr ;
20252050 sr -> sizeOfSuspendResumeData = len ;
20262051
20272052 mbox0 = lower_32_bits (gsp -> sr .meta .addr );
0 commit comments