[parisc-linux-cvs] [PATCH] iotree/ccio tree cleanup + the bug Grant found.

Ryan Bradetich rbradetich@uswest.net
Fri, 16 Nov 2001 19:04:14 -0700


--LZvS9be/3tNcYl/X
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hello parisc-linux kernel hackers,

The following diff contains enhancements:
	* ccio cleanups from willy's all.diff file.
	* The bugfix from Grant where we exceeded DMA_CHUNK_SIZE
	* Moved the buswalk code under ccio to a generic iotree
	  buswalk function.  (This generic buswalk code also will
	  walk the GeckoBOA buses below CCIO on K-Class as well).

I still do not think the buswalk code is perfect yet, but this is
a small incrimental step in the right direction.

Thanks,

- Ryan

--LZvS9be/3tNcYl/X
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="iotree.diff"

Index: arch/parisc/kernel/ccio-dma.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/ccio-dma.c,v
retrieving revision 1.46
diff -u -p -r1.46 ccio-dma.c
--- arch/parisc/kernel/ccio-dma.c	2001/11/09 23:35:15	1.46
+++ arch/parisc/kernel/ccio-dma.c	2001/11/17 01:58:29
@@ -99,17 +99,6 @@
 #define UTURN_IOA_RUNWAY 0x581
 #define UTURN_BC_GSC     0x502
 
-#define IS_U2(id) ( \
-    (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \
-    (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC))  \
-)
-
-#define IS_UTURN(id) ( \
-    (((id)->hw_type == HPHW_IOA) && ((id)->hversion == UTURN_IOA_RUNWAY)) || \
-    (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC))  \
-)
-
-
 #define IOA_NORMAL_MODE      0x00020080 /* IO_CONTROL to turn on CCIO        */
 #define CMD_TLB_DIRECT_WRITE 35         /* IO_COMMAND for I/O TLB Writes     */
 #define CMD_TLB_PURGE        33         /* IO_COMMAND to Purge I/O TLB entry */
@@ -276,7 +265,7 @@ ccio_alloc_range(struct ioc *ioc, unsign
 
 	/*
 	** "seek and ye shall find"...praying never hurts either...
-	** ggg sacrafices another 710 to the computer gods.
+	** ggg sacrifices another 710 to the computer gods.
 	*/
 
 	if(pages_needed <= 8) {
@@ -915,6 +904,14 @@ ccio_coalesce_chunks(struct ioc *ioc, st
 			sg_dma_len(startsg) = 0;
 
 			/*
+			** First make sure current dma stream won't
+			** exceed DMA_CHUNK_SIZE if we coalesce the
+			** next entry.
+			*/   
+			if (dma_len + startsg->length > DMA_CHUNK_SIZE)
+				break;
+
+			/*
 			** Append the next transaction?
 			*/
 			if(vcontig_end == (unsigned long) startsg->address) {
@@ -981,7 +978,7 @@ ccio_map_sg(struct pci_dev *dev, struct 
 	ASSERT(dev->sysdata);
 	ASSERT(HBA_DATA(dev->sysdata)->iommu);
 	ioc = GET_IOC(dev);
-
+	
 	DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents);
 
 	/* Fast path single entry scatterlists. */
@@ -1080,32 +1077,63 @@ static struct pci_dma_ops ccio_ops = {
 };
 
 #ifdef CONFIG_PROC_FS
-static int 
-ccio_proc_info(char *buf, char **start, off_t offset, int len)
+static int proc_append(char *src, int len, char **dst, off_t *offset, int *max)
+{
+	if (len < *offset) {
+		*offset -= len;
+		return 0;
+	}
+	if (*offset > 0) {
+		src += *offset;
+		len -= *offset;
+		*offset = 0;
+	}
+	if (len > *max) {
+		len = *max;
+	}
+	memcpy(*dst, src, len);
+	*dst += len;
+	*max -= len;
+	return (*max == 0);
+}
+
+static int ccio_proc_info(char *buf, char **start, off_t offset, int count,
+			  int *eof, void *data)
 {
+	int max = count;
+	char tmp[80]; /* width of an ANSI-standard terminal */
 	struct ioc *ioc = ioc_list;
 
-	buf[0] = '\0';
 	while (ioc != NULL) {
 		unsigned int total_pages = ioc->res_size << 3;
 		unsigned long avg = 0, min, max;
-		int j;
-
-		sprintf(buf, "%s%s\n", buf, ioc->name);
-
-		sprintf(buf, "%sCujo 2.0 bug    : %s\n",
-			buf, (ioc->cujo20_bug ? "yes" : "no"));
-
-		sprintf(buf, "%sIO PDIR size    : %d bytes (%d entries)\n",
-			buf, ((ioc->res_size << 3) * sizeof(u64)), total_pages);
+		int j, len;
 
-		sprintf(buf, "%sIO PDIR entries : %ld free  %ld used (%d%%)\n", buf,
-			total_pages - ioc->used_pages, ioc->used_pages,
-			(int)(ioc->used_pages * 100 / total_pages));
-
-		sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", 
-			buf, ioc->res_size, ioc->res_size << 3);
-
+		len = sprintf(tmp, "%s\n", ioc->name);
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
+		len = sprintf(tmp, "Cujo 2.0 bug    : %s\n",
+			      (ioc->cujo20_bug ? "yes" : "no"));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
+		len = sprintf(tmp, "IO PDIR size    : %d bytes (%d entries)\n",
+			      ((ioc->res_size << 3) * sizeof(u64)), total_pages);
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
+		len = sprintf(tmp, "IO PDIR entries : %ld free  %ld used (%d%%)\n",
+			      total_pages - ioc->used_pages, ioc->used_pages,
+			      (int)(ioc->used_pages * 100 / total_pages));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
+		len = sprintf(tmp, "Resource bitmap : %d bytes (%d pages)\n", 
+			ioc->res_size, ioc->res_size << 3);
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
 		min = max = ioc->avg_search[0];
 		for(j = 0; j < CCIO_SEARCH_SAMPLE; ++j) {
 			avg += ioc->avg_search[j];
@@ -1115,34 +1143,48 @@ ccio_proc_info(char *buf, char **start, 
 				min = ioc->avg_search[j];
 		}
 		avg /= CCIO_SEARCH_SAMPLE;
-		sprintf(buf, "%s  Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
-			buf, min, avg, max);
+		len = sprintf(tmp, "  Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
+			      min, avg, max);
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
 
-		sprintf(buf, "%spci_map_single(): %8ld calls  %8ld pages (avg %d/1000)\n",
-			buf, ioc->msingle_calls, ioc->msingle_pages,
-			(int)((ioc->msingle_pages * 1000)/ioc->msingle_calls));
+		len = sprintf(tmp, "pci_map_single(): %8ld calls  %8ld pages (avg %d/1000)\n",
+			      ioc->msingle_calls, ioc->msingle_pages,
+			      (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
 
 		/* KLUGE - unmap_sg calls unmap_single for each mapped page */
 		min = ioc->usingle_calls - ioc->usg_calls;
 		max = ioc->usingle_pages - ioc->usg_pages;
-		sprintf(buf, "%spci_unmap_single: %8ld calls  %8ld pages (avg %d/1000)\n",
-			buf, min, max, (int)((max * 1000)/min));
+		len = sprintf(tmp, "pci_unmap_single: %8ld calls  %8ld pages (avg %d/1000)\n",
+			      min, max, (int)((max * 1000)/min));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+ 
+		len = sprintf(tmp, "pci_map_sg()    : %8ld calls  %8ld pages (avg %d/1000)\n",
+			      ioc->msg_calls, ioc->msg_pages,
+			      (int)((ioc->msg_pages * 1000)/ioc->msg_calls));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		len = sprintf(tmp, "pci_unmap_sg()  : %8ld calls  %8ld pages (avg %d/1000)\n\n\n",
+			      ioc->usg_calls, ioc->usg_pages,
+			      (int)((ioc->usg_pages * 1000)/ioc->usg_calls));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
 
-		sprintf(buf, "%spci_map_sg()    : %8ld calls  %8ld pages (avg %d/1000)\n",
-			buf, ioc->msg_calls, ioc->msg_pages,
-			(int)((ioc->msg_pages * 1000)/ioc->msg_calls));
-
-		sprintf(buf, "%spci_unmap_sg()  : %8ld calls  %8ld pages (avg %d/1000)\n\n\n",
-			buf, ioc->usg_calls, ioc->usg_pages,
-			(int)((ioc->usg_pages * 1000)/ioc->usg_calls));
 		ioc = ioc->next;
 	}
 
-	return strlen(buf);
+	if (count == 0) {
+		*eof = 1;
+	}
+	return (max - count);
 }
 
-static int
-ccio_resource_map(char *buf, char **start, off_t offset, int len)
+static int ccio_resource_map(char *buf, char **start, off_t offset, int len,
+			     int *eof, void *data)
 {
 	struct ioc *ioc = ioc_list;
 
@@ -1159,6 +1201,7 @@ ccio_resource_map(char *buf, char **star
 		}
 		strcat(buf, "\n\n");
 		ioc = ioc->next;
+		break; /* XXX - remove me */
 	}
 
 	return strlen(buf);
@@ -1346,8 +1389,6 @@ ccio_ioc_init(struct ioc *ioc)
 	}
 }
 
-int do_native_bus_walk(unsigned long io_io_low);
-
 /**
  * ccio_probe - Determine if ccio should claim this device.
  * @dev: The device which has been found
@@ -1359,9 +1400,10 @@ int do_native_bus_walk(unsigned long io_
 static int ccio_probe(struct parisc_device *dev)
 {
 	int i;
-	unsigned long io_io_low;
 	struct ioc *ioc, **ioc_p = &ioc_list;
-
+	unsigned long io_io_low, io_io_low_hv;
+	unsigned long io_io_high, io_io_high_hv;
+	
 	ioc = kmalloc(sizeof(struct ioc), GFP_KERNEL);
 	if (ioc == NULL) {
 		printk(KERN_ERR MODULE_NAME ": memory allocation failure\n");
@@ -1369,9 +1411,8 @@ static int ccio_probe(struct parisc_devi
 	}
 	memset(ioc, 0, sizeof(struct ioc));
 
-	printk(KERN_INFO "%s found %s at 0x%lx\n", MODULE_NAME,
-			dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn",
-			dev->hpa);
+	printk(KERN_INFO MODULE_NAME " found %s at 0x%lx\n", 
+	       dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn", dev->hpa);
 
 	for (i = 0; i < ioc_count; i++) {
 		ioc_p = &(*ioc_p)->next;
@@ -1384,25 +1425,26 @@ static int ccio_probe(struct parisc_devi
 	ioc->ioc_hpa = (struct ioa_registers *)dev->hpa;
 	ccio_ioc_init(ioc);
 
+	io_io_low = READ_U32(&ioc->ioc_hpa->io_io_low) << 16;
+	io_io_low_hv = READ_U32(&ioc->ioc_hpa->io_io_low_hv) << 16;
+	io_io_high = READ_U32(&ioc->ioc_hpa->io_io_high) << 16;
+	io_io_high_hv = READ_U32(&ioc->ioc_hpa->io_io_high_hv) << 16;
+
+	printk("io_io_low: %lx io_io_high: %lx\nio_io_low_hv: %lx io_io_high_hv: %lx\n",
+	       io_io_low, io_io_high, io_io_low_hv, io_io_high_hv);
+
+
 	hppa_dma_ops = &ccio_ops;
 
 	if (ioc_count == 0) {
 		/* XXX: Create separate entries for each ioc */
-		create_proc_info_entry(MODULE_NAME, 0, proc_runway_root, ccio_proc_info);
-		create_proc_info_entry(MODULE_NAME"-bitmap", 0, proc_runway_root,
-					       ccio_resource_map);
+		create_proc_read_entry(MODULE_NAME, S_IRWXU, proc_runway_root,
+				       ccio_proc_info, NULL);
+		create_proc_read_entry(MODULE_NAME"-bitmap", S_IRWXU,
+				       proc_runway_root, ccio_resource_map, NULL);
 	}
 
 	ioc_count++;
-
-	io_io_low = READ_U32(&ioc->ioc_hpa->io_io_low) << 16;
-#ifdef __LP64__
-	/* Need to sign extend these io addresses */
-	io_io_low |= 0xffffffff00000000UL;
-#endif
-	printk(KERN_INFO "io_io_low: 0x%lx\n", io_io_low);
-	walk_native_bus(io_io_low, dev);
-	print_subdevices(dev);
 	return 0;
 }
 
Index: arch/parisc/kernel/drivers.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/drivers.c,v
retrieving revision 1.33
diff -u -p -r1.33 drivers.c
--- arch/parisc/kernel/drivers.c	2001/10/29 18:38:21	1.33
+++ arch/parisc/kernel/drivers.c	2001/11/17 01:58:29
@@ -22,6 +22,7 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/pdc.h>
+#include <asm/gsc.h>
 
 static struct parisc_driver *pa_drivers;
 static struct parisc_device root;
@@ -339,6 +340,44 @@ int register_parisc_device(struct parisc
 	return driver != NULL;
 }
 
+#define BC_PORT_MASK 0x8
+#define BC_LOWER_PORT 0x8
+
+#define BUS_CONVERTER(dev) \
+        ((dev->id.hw_type == HPHW_IOA) || (dev->id.hw_type == HPHW_BCPORT))
+#define IS_LOWER_PORT(dev) \
+        ((gsc_readl(&((struct bc_module *)dev->hpa)->io_status) \
+                & BC_PORT_MASK) == BC_LOWER_PORT)
+
+#define READ_IO_IO_LOW(dev) \
+	(dev->id.hw_type == HPHW_IOA ? \
+	        gsc_readl(&((struct bc_module *)dev->hpa)->io_io_low) << 16 : \
+	        gsc_readl(&((struct bc_module *)dev->hpa)->io_io_low))
+#define READ_IO_IO_HIGH(dev) \
+	(dev->id.hw_type == HPHW_IOA ? \
+	        gsc_readl(&((struct bc_module *)dev->hpa)->io_io_high) << 16 : \
+	        gsc_readl(&((struct bc_module *)dev->hpa)->io_io_high))
+
+static void walk_native_bus(unsigned long addr, struct parisc_device *parent);
+void walk_lower_bus(struct parisc_device *dev)
+{
+	unsigned long io_io_low, io_io_high;
+
+	if(!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev))
+		return;
+
+	io_io_low = READ_IO_IO_LOW(dev);
+	io_io_high = READ_IO_IO_HIGH(dev);
+
+#ifdef __LP64__
+	/* Need to f-extend these io addresses */
+	io_io_low |= 0xffffffff00000000UL;
+	io_io_high |= 0xffffffff00000000UL;
+#endif
+
+	walk_native_bus(io_io_low, dev);
+}
+
 #define MAX_NATIVE_DEVICES 64
 #define NATIVE_DEVICE_OFFSET 0x1000
 
@@ -352,18 +391,30 @@ int register_parisc_device(struct parisc
  * devices which are not physically connected (such as extra serial &
  * keyboard ports).  This problem is not yet solved.
  */
-void walk_native_bus(unsigned long addr, struct parisc_device *parent)
+static void walk_native_bus(unsigned long addr, struct parisc_device *parent)
 {
 	int i;
 	struct hardware_path path;
+
 	get_node_path(parent, &path);
 	for (i = 0; i < MAX_NATIVE_DEVICES; i++) {
+		unsigned long hpa = (addr + i * NATIVE_DEVICE_OFFSET);
 		struct parisc_device *dev;
+
+		/* Was the device added by Firmware? */
+		dev = find_device_by_addr(hpa);
+		if(dev) {
+			walk_lower_bus(dev);
+			continue;
+		}
+
 		path.mod = i;
-		dev = alloc_pa_dev(addr + i * NATIVE_DEVICE_OFFSET, &path);
+		dev = alloc_pa_dev(hpa, &path);
 		if (!dev)
 			continue;
+
 		register_parisc_device(dev);
+		walk_lower_bus(dev);
 	}
 }
 
Index: include/asm-parisc/hardware.h
===================================================================
RCS file: /var/cvs/linux/include/asm-parisc/hardware.h,v
retrieving revision 1.30
diff -u -p -r1.30 hardware.h
--- include/asm-parisc/hardware.h	2001/10/29 18:38:21	1.30
+++ include/asm-parisc/hardware.h	2001/11/17 01:58:29
@@ -72,7 +72,44 @@ struct parisc_driver {
 	int (*probe) (struct parisc_device *dev); /* New device discovered */
 };
 
+struct io_module {
+        volatile uint32_t nothing;		/* reg 0 */
+        volatile uint32_t io_eim;
+        volatile uint32_t io_dc_adata;
+        volatile uint32_t io_ii_cdata;
+        volatile uint32_t io_dma_link;		/* reg 4 */
+        volatile uint32_t io_dma_command;
+        volatile uint32_t io_dma_address;
+        volatile uint32_t io_dma_count;
+        volatile uint32_t io_flex;		/* reg 8 */
+        volatile uint32_t io_spa_address;
+        volatile uint32_t reserved1[2];
+        volatile uint32_t io_command;		/* reg 12 */
+        volatile uint32_t io_status;
+        volatile uint32_t io_control;
+        volatile uint32_t io_data;
+        volatile uint32_t reserved2;		/* reg 16 */
+        volatile uint32_t chain_addr;
+        volatile uint32_t sub_mask_clr;
+        volatile uint32_t reserved3[13];
+        volatile uint32_t undefined[480];
+        volatile uint32_t unpriv[512];
+};
 
+struct bc_module {
+        volatile uint32_t unused1[12];
+        volatile uint32_t io_command;
+        volatile uint32_t io_status;
+        volatile uint32_t io_control;
+        volatile uint32_t unused2[1];
+        volatile uint32_t io_err_resp;
+        volatile uint32_t io_err_info;
+        volatile uint32_t io_err_req;
+        volatile uint32_t unused3[11];
+        volatile uint32_t io_io_low;
+        volatile uint32_t io_io_high;
+};
+
 #define HPHW_NPROC     0 
 #define HPHW_MEMORY    1       
 #define HPHW_B_DMA     2
@@ -102,7 +139,6 @@ extern struct parisc_device *alloc_pa_de
 extern int register_parisc_device(struct parisc_device *dev);
 extern int register_parisc_driver(struct parisc_driver *driver);
 extern int unregister_parisc_driver(struct parisc_driver *driver);
-extern void walk_native_bus(unsigned long addr, struct parisc_device *parent);
 extern void walk_central_bus(void);
 extern void fixup_child_irqs(struct parisc_device *parent, int irqbase,
 		int (*choose)(struct parisc_device *parent));

--LZvS9be/3tNcYl/X--