Commit 4c5fc5ae authored by Jeffrey Lee's avatar Jeffrey Lee Committed by ROOL
Browse files

Fix bulk transfers on Pi 4

VCHIQ bulk transfers on Pi 4 use a different page list format, in order
to allow full use of the larger 36bit physical address space. Update our
vchiq_prepare_bulk_data implementation to use this new format when
necessary.

Version 0.14. Tagged as 'VCHIQ-0_14'
parent 7196f487
/* (0.13)
/* (0.14)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.13
#define Module_MajorVersion_CMHG 0.14
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 14 Feb 2019
#define Module_Date_CMHG 19 Feb 2020
#define Module_MajorVersion "0.13"
#define Module_Version 13
#define Module_MajorVersion "0.14"
#define Module_Version 14
#define Module_MinorVersion ""
#define Module_Date "14 Feb 2019"
#define Module_Date "19 Feb 2020"
#define Module_ApplicationDate "14-Feb-19"
#define Module_ApplicationDate "19-Feb-20"
#define Module_ComponentName "VCHIQ"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/VCHIQ"
#define Module_FullVersion "0.13"
#define Module_HelpVersion "0.13 (14 Feb 2019)"
#define Module_LibraryVersionInfo "0:13"
#define Module_FullVersion "0.14"
#define Module_HelpVersion "0.14 (19 Feb 2020)"
#define Module_LibraryVersionInfo "0:14"
......@@ -255,29 +255,71 @@ int32_t atomic_cmpxchg(atomic_t *a, int32_t old, int32_t new)
/* Page list handling */
static uint32_t calc_bulk_addr(uint64_t phys)
{
if (GET_DEV_FLAGS(vchiq_dev) & DEV_FLAG_USE36BIT)
{
return phys >> 4;
}
else
{
return phys + vchiq_dev->arm_to_vc_offset;
}
}
VCHIQ_STATUS_T vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, void *offset, int size, int dir)
{
/* For the moment, assume that all bulk data is located in an area of physically contiguous uncached memory */
uint64_t phys;
uint32_t pageblock[3];
pageblock[0] = ~0;
pageblock[1] = (uint32_t) offset;
pageblock[1] = ((uint32_t) offset) & ~0xfff;
pageblock[2] = ~0;
if(_swix(OS_Memory,_INR(0,2),0+(1<<9)+(1<<13),pageblock,1))
return VCHIQ_ERROR;
phys = pageblock[2];
/* Each "addrs" entry is a page-aligned start address in the upper bits,
and a count of consecutive pages in the low bits.
With 32bit physical addresses, the top 20 bits are the upper 20 bits
of the address, and the low 12 are the consecutive page count.
With 36bit physical addresses, the top 24 bits are the upper 24 bits
of the address, and the low 8 bits are the consecutive page count.
For transfers which aren't page-aligned, the pagelist 'offset' entry
is the sub-page offset to start at. */
uint32_t first_page = ((uint32_t)offset)>>12;
uint32_t last_page = (((uint32_t)offset)+size-1)>>12;
/* Number of pages the transfer touches */
uint32_t num_pages = last_page-first_page+1;
/* Max consecutive pages in each "addrs" entry */
uint32_t max_pages = (GET_DEV_FLAGS(vchiq_dev) & DEV_FLAG_USE36BIT) ? 256 : 4096;
/* Number of "addrs" entries required */
uint32_t num_addrs = (num_pages+max_pages-1)/max_pages;
PAGELIST_T *pagelist;
uint32_t phy_pagelist;
if(_swix(PCI_RAMAlloc,_INR(0,2)|_OUTR(0,1),sizeof(PAGELIST_T),0,0,&pagelist,&phy_pagelist))
if(_swix(PCI_RAMAlloc,_INR(0,2)|_OUTR(0,1),sizeof(PAGELIST_T)+(num_addrs-1)*4,0,0,&pagelist,&phy_pagelist))
return VCHIQ_ERROR;
pagelist->length = size;
pagelist->type = (dir == VCHIQ_BULK_RECEIVE?PAGELIST_READ:PAGELIST_WRITE);
pagelist->offset = ((uint32_t) offset) & 0xfff;
pagelist->addrs[0] = pageblock[2] + vchiq_dev->arm_to_vc_offset;
/* Low 12 bits of page address indicates how many pages are at consecutive addresses */
uint32_t firstpage = ((uint32_t)offset)>>12;
uint32_t lastpage = (((uint32_t)offset)+size-1)>>12;
pagelist->addrs[0] += lastpage-firstpage;
uint32_t *addrs = pagelist->addrs;
while (num_pages > max_pages)
{
*addrs++ = calc_bulk_addr(phys) | (max_pages-1);
phys += max_pages<<12;
num_pages -= max_pages;
}
*addrs = calc_bulk_addr(phys) | (num_pages-1);
bulk->handle = memhandle;
bulk->data = (void *) (phy_pagelist + vchiq_dev->arm_to_vc_offset);
......
......@@ -46,8 +46,16 @@ typedef struct vchiq_device {
uint32_t (*arm_doorbell)(struct vchiq_device *dev); /* Read state of our doorbell */
void (*init_vc)(struct vchiq_device *dev, uint32_t addr); /* Perform mailbox write to initialise VC side */
/* API 0.1 additions */
int flags; /* Extra flags */
#define DEV_FLAG_USE36BIT 1 /* Use 36bit physical addresses in bulk transfers */
} vchiq_device_t;
#define GET_DEV_FLAGS(DEV) ((DEV->dev.version & 0xffff) ? DEV->flags : 0)
extern vchiq_device_t *vchiq_dev;
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment