Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Nov 2015 05:25:06 +0000 (UTC)
From:      Oleksandr Tymoshenko <gonzo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r290322 - head/sys/contrib/vchiq/interface/vchiq_arm
Message-ID:  <201511030525.tA35P6k2006721@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gonzo
Date: Tue Nov  3 05:25:06 2015
New Revision: 290322
URL: https://svnweb.freebsd.org/changeset/base/290322

Log:
  Fix cache issues with bulk transfers
  
  - Use pmap_quick_enter_page/pmap_quick_remove_page to bounce non-cacheline
      aligned head and tail fragments
  - Switch from static fragment size to configurable one, newer firmware
      passes cache line size as cache_line_size DTB parameter.
  
  With these changes both RPi and RPi2 pass functinal part of vchiq_test

Modified:
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
  head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h

Modified: head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c
==============================================================================
--- head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c	Tue Nov  3 04:50:58 2015	(r290321)
+++ head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_2835_arm.c	Tue Nov  3 05:25:06 2015	(r290322)
@@ -65,6 +65,9 @@ MALLOC_DEFINE(M_VCPAGELIST, "vcpagelist"
 
 #define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2)
 
+int g_cache_line_size = 32;
+static int g_fragment_size;
+
 typedef struct vchiq_2835_state_struct {
    int inited;
    VCHIQ_ARM_STATE_T arm_state;
@@ -77,8 +80,8 @@ vm_paddr_t g_slot_phys;
 bus_dma_tag_t bcm_slots_dma_tag;
 bus_dmamap_t bcm_slots_dma_map;
 
-static FRAGMENTS_T *g_fragments_base;
-static FRAGMENTS_T *g_free_fragments;
+static char *g_fragments_base;
+static char *g_free_fragments;
 struct semaphore g_free_fragments_sema;
 
 static DEFINE_SEMAPHORE(g_free_fragments_mutex);
@@ -115,13 +118,13 @@ copyout_page(vm_page_t p, size_t offset,
 {
         uint8_t *dst;
 
-        dst = pmap_mapdev(VM_PAGE_TO_PHYS(p), PAGE_SIZE);
+        dst = (uint8_t*)pmap_quick_enter_page(p);
         if (!dst)
                 return ENOMEM;
 
         memcpy(dst + offset, kaddr, size);
 
-        pmap_unmapdev((vm_offset_t)dst, PAGE_SIZE);
+        pmap_quick_remove_page((vm_offset_t)dst);
 
         return 0;
 }
@@ -136,7 +139,8 @@ vchiq_platform_init(VCHIQ_STATE_T *state
 
 	/* Allocate space for the channels in coherent memory */
 	g_slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
-	frag_mem_size = PAGE_ALIGN(sizeof(FRAGMENTS_T) * MAX_FRAGMENTS);
+	g_fragment_size = 2*g_cache_line_size;
+	frag_mem_size = PAGE_ALIGN(g_fragment_size * MAX_FRAGMENTS);
 
 	err = bus_dma_tag_create(
 	    NULL,
@@ -180,15 +184,15 @@ vchiq_platform_init(VCHIQ_STATE_T *state
 	vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] =
 		MAX_FRAGMENTS;
 
-	g_fragments_base = (FRAGMENTS_T *)(g_slot_mem + g_slot_mem_size);
+	g_fragments_base = (char *)(g_slot_mem + g_slot_mem_size);
 	g_slot_mem_size += frag_mem_size;
 
 	g_free_fragments = g_fragments_base;
 	for (i = 0; i < (MAX_FRAGMENTS - 1); i++) {
-		*(FRAGMENTS_T **)&g_fragments_base[i] =
-			&g_fragments_base[i + 1];
+		*(char **)&g_fragments_base[i*g_fragment_size] =
+			&g_fragments_base[(i + 1)*g_fragment_size];
 	}
-	*(FRAGMENTS_T **)&g_fragments_base[i] = NULL;
+	*(char **)&g_fragments_base[i*g_fragment_size] = NULL;
 	_sema_init(&g_free_fragments_sema, MAX_FRAGMENTS);
 
 	if (vchiq_init_state(state, vchiq_slot_zero, 0/*slave*/) !=
@@ -452,7 +456,8 @@ create_pagelist(char __user *buf, size_t
 	}
 
 	vchiq_log_trace(vchiq_arm_log_level,
-		"create_pagelist - %x", (unsigned int)pagelist);
+		"create_pagelist - %x (%d bytes @%p)", (unsigned int)pagelist, count, buf);
+
 	if (!pagelist)
 		return -ENOMEM;
 
@@ -506,10 +511,10 @@ create_pagelist(char __user *buf, size_t
 
 	/* Partial cache lines (fragments) require special measures */
 	if ((type == PAGELIST_READ) &&
-		((pagelist->offset & (CACHE_LINE_SIZE - 1)) ||
+		((pagelist->offset & (g_cache_line_size - 1)) ||
 		((pagelist->offset + pagelist->length) &
-		(CACHE_LINE_SIZE - 1)))) {
-		FRAGMENTS_T *fragments;
+		(g_cache_line_size - 1)))) {
+		char *fragments;
 
 		if (down_interruptible(&g_free_fragments_sema) != 0) {
       			free(pagelist, M_VCPAGELIST);
@@ -519,13 +524,13 @@ create_pagelist(char __user *buf, size_t
 		WARN_ON(g_free_fragments == NULL);
 
 		down(&g_free_fragments_mutex);
-		fragments = (FRAGMENTS_T *) g_free_fragments;
+		fragments = g_free_fragments;
 		WARN_ON(fragments == NULL);
-		g_free_fragments = *(FRAGMENTS_T **) g_free_fragments;
+		g_free_fragments = *(char **) g_free_fragments;
 		up(&g_free_fragments_mutex);
 		pagelist->type =
-			 PAGELIST_READ_WITH_FRAGMENTS + (fragments -
-							 g_fragments_base);
+			 PAGELIST_READ_WITH_FRAGMENTS + 
+			 (fragments - g_fragments_base)/g_fragment_size;
 	}
 
 	cpu_dcache_wbinv_range((vm_offset_t)buf, count);
@@ -555,7 +560,7 @@ free_pagelist(BULKINFO_T *bi, int actual
 	pagelist = bi->pagelist;
 
 	vchiq_log_trace(vchiq_arm_log_level,
-		"free_pagelist - %x, %d", (unsigned int)pagelist, actual);
+		"free_pagelist - %x, %d (%lu bytes @%p)", (unsigned int)pagelist, actual, pagelist->length, bi->buf);
 
 	num_pages =
 		(pagelist->length + pagelist->offset + PAGE_SIZE - 1) /
@@ -565,13 +570,13 @@ free_pagelist(BULKINFO_T *bi, int actual
 
 	/* Deal with any partial cache lines (fragments) */
 	if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) {
-		FRAGMENTS_T *fragments = g_fragments_base +
-			(pagelist->type - PAGELIST_READ_WITH_FRAGMENTS);
+		char *fragments = g_fragments_base +
+			(pagelist->type - PAGELIST_READ_WITH_FRAGMENTS)*g_fragment_size;
 		int head_bytes, tail_bytes;
-		head_bytes = (CACHE_LINE_SIZE - pagelist->offset) &
-			(CACHE_LINE_SIZE - 1);
+		head_bytes = (g_cache_line_size - pagelist->offset) &
+			(g_cache_line_size - 1);
 		tail_bytes = (pagelist->offset + actual) &
-			(CACHE_LINE_SIZE - 1);
+			(g_cache_line_size - 1);
 
 		if ((actual >= 0) && (head_bytes != 0)) {
 			if (head_bytes > actual)
@@ -579,7 +584,7 @@ free_pagelist(BULKINFO_T *bi, int actual
 
 			copyout_page(pages[0],
 				pagelist->offset,
-				fragments->headbuf,
+				fragments,
 				head_bytes);
 		}
 
@@ -588,12 +593,12 @@ free_pagelist(BULKINFO_T *bi, int actual
 
 			copyout_page(pages[num_pages-1],
 				(((vm_offset_t)bi->buf + actual) % PAGE_SIZE) - tail_bytes,
-				fragments->tailbuf,
+				fragments + g_cache_line_size,
 				tail_bytes);
 		}
 
 		down(&g_free_fragments_mutex);
-		*(FRAGMENTS_T **) fragments = g_free_fragments;
+		*(char **) fragments = g_free_fragments;
 		g_free_fragments = fragments;
 		up(&g_free_fragments_mutex);
 		up(&g_free_fragments_sema);

Modified: head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
==============================================================================
--- head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c	Tue Nov  3 04:50:58 2015	(r290321)
+++ head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c	Tue Nov  3 05:25:06 2015	(r290322)
@@ -88,6 +88,7 @@ void vchiq_exit(void);
 int vchiq_init(void);
 
 extern VCHIQ_STATE_T g_state;
+extern int g_cache_line_size;
 
 static void
 bcm_vchiq_intr(void *arg)
@@ -133,6 +134,8 @@ static int
 bcm_vchiq_attach(device_t dev)
 {
 	struct bcm_vchiq_softc *sc = device_get_softc(dev);
+	phandle_t node;
+	pcell_t cell;
 	int rid = 0;
 
 	if (bcm_vchiq_sc != NULL)
@@ -154,6 +157,10 @@ bcm_vchiq_attach(device_t dev)
 		return (ENXIO);
 	}
 
+	node = ofw_bus_get_node(dev);
+	if ((OF_getencprop(node, "cache-line-size", &cell, sizeof(cell))) > 0)
+		g_cache_line_size = cell;
+
 	vchiq_core_initialize();
 
 	/* Setup and enable the timer */

Modified: head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h
==============================================================================
--- head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h	Tue Nov  3 04:50:58 2015	(r290321)
+++ head/sys/contrib/vchiq/interface/vchiq_arm/vchiq_pagelist.h	Tue Nov  3 05:25:06 2015	(r290322)
@@ -37,8 +37,6 @@
 #ifndef PAGE_SIZE
 #define PAGE_SIZE 4096
 #endif
-#undef CACHE_LINE_SIZE
-#define CACHE_LINE_SIZE 32
 #define PAGELIST_WRITE 0
 #define PAGELIST_READ 1
 #define PAGELIST_READ_WITH_FRAGMENTS 2
@@ -51,9 +49,4 @@ typedef struct pagelist_struct {
 				   pages at consecutive addresses. */
 } PAGELIST_T;
 
-typedef struct fragments_struct {
-	char headbuf[CACHE_LINE_SIZE];
-	char tailbuf[CACHE_LINE_SIZE];
-} FRAGMENTS_T;
-
 #endif /* VCHIQ_PAGELIST_H */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201511030525.tA35P6k2006721>