[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--