From e94e15f70559962f60915a09d44658b73a453fe2 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 27 Jun 2005 16:28:15 -0700 Subject: [PATCH] pcmcia: cleanups From: Adrian Bunk This patch contains the following cleanups: - make needlessly global code static - remove the following unneeded EXPORT_SYMBOL's: - ds.c: pcmcia_report_error - ds.c: pcmcia_bus_type Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/rsrc_nonstatic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/pcmcia/rsrc_nonstatic.c') diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 5876bab7c14..9a0b835d612 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -601,7 +601,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star ======================================================================*/ -struct resource *nonstatic_find_io_region(unsigned long base, int num, +static struct resource *nonstatic_find_io_region(unsigned long base, int num, unsigned long align, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id); @@ -635,8 +635,8 @@ struct resource *nonstatic_find_io_region(unsigned long base, int num, return res; } -struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long align, - int low, struct pcmcia_socket *s) +static struct resource * nonstatic_find_mem_region(u_long base, u_long num, + u_long align, int low, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id); struct socket_data *s_data = s->resource_data; -- cgit v1.2.3-70-g09d2 From 22916638b124e859b595099bd0c86a1e09e767fb Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 27 Jun 2005 16:28:46 -0700 Subject: [PATCH] pcmcia: update resource database adjust routines to use unsigned long values Make adjust_io and adjust_memory independent of adjust_t to allow for IO resources > x86's IO_SPACE_LIMIT. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/rsrc_nonstatic.c | 89 ++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 51 deletions(-) (limited to 'drivers/pcmcia/rsrc_nonstatic.c') diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 9a0b835d612..6b463609a3a 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -683,27 +683,23 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num, } -static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj) +static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end) { - u_long base, num; struct socket_data *data = s->resource_data; - int ret; - - base = adj->resource.memory.Base; - num = adj->resource.memory.Size; - if ((num == 0) || (base+num-1 < base)) - return CS_BAD_SIZE; + unsigned long size = end - start + 1; + int ret = 0; - ret = CS_SUCCESS; + if (end <= start) + return -EINVAL; down(&rsrc_sem); - switch (adj->Action) { + switch (action) { case ADD_MANAGED_RESOURCE: - ret = add_interval(&data->mem_db, base, num); + ret = add_interval(&data->mem_db, start, size); break; case REMOVE_MANAGED_RESOURCE: - ret = sub_interval(&data->mem_db, base, num); - if (ret == CS_SUCCESS) { + ret = sub_interval(&data->mem_db, start, size); + if (!ret) { struct pcmcia_socket *socket; down_read(&pcmcia_socket_list_rwsem); list_for_each_entry(socket, &pcmcia_socket_list, socket_list) @@ -712,7 +708,7 @@ static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj) } break; default: - ret = CS_UNSUPPORTED_FUNCTION; + ret = -EINVAL; } up(&rsrc_sem); @@ -720,36 +716,35 @@ static int adjust_memory(struct pcmcia_socket *s, adjust_t *adj) } -static int adjust_io(struct pcmcia_socket *s, adjust_t *adj) +static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end) { struct socket_data *data = s->resource_data; - kio_addr_t base, num; - int ret = CS_SUCCESS; + unsigned long size = end - start + 1; + int ret = 0; - base = adj->resource.io.BasePort; - num = adj->resource.io.NumPorts; - if ((base < 0) || (base > 0xffff)) - return CS_BAD_BASE; - if ((num <= 0) || (base+num > 0x10000) || (base+num <= base)) - return CS_BAD_SIZE; + if (end <= start) + return -EINVAL; + + if (end > IO_SPACE_LIMIT) + return -EINVAL; down(&rsrc_sem); - switch (adj->Action) { + switch (action) { case ADD_MANAGED_RESOURCE: - if (add_interval(&data->io_db, base, num) != 0) { - ret = CS_IN_USE; + if (add_interval(&data->io_db, start, size) != 0) { + ret = -EBUSY; break; } #ifdef CONFIG_PCMCIA_PROBE if (probe_io) - do_io_probe(s, base, num); + do_io_probe(s, start, size); #endif break; case REMOVE_MANAGED_RESOURCE: - sub_interval(&data->io_db, base, num); + sub_interval(&data->io_db, start, size); break; default: - ret = CS_UNSUPPORTED_FUNCTION; + ret = -EINVAL; break; } up(&rsrc_sem); @@ -760,11 +755,15 @@ static int adjust_io(struct pcmcia_socket *s, adjust_t *adj) static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj) { + unsigned long end; + switch (adj->Resource) { case RES_MEMORY_RANGE: - return adjust_memory(s, adj); + end = adj->resource.memory.Base + adj->resource.memory.Size - 1; + return adjust_memory(s, adj->Action, adj->resource.memory.Base, end); case RES_IO_RANGE: - return adjust_io(s, adj); + end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1; + return adjust_io(s, adj->Action, adj->resource.io.BasePort, end); } return CS_UNSUPPORTED_FUNCTION; } @@ -845,17 +844,16 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size { struct pcmcia_socket *s = class_get_devdata(class_dev); unsigned long start_addr, end_addr; - unsigned int add = 1; - adjust_t adj; + unsigned int add = ADD_MANAGED_RESOURCE; ssize_t ret = 0; ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); if (ret != 2) { ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); - add = 0; + add = REMOVE_MANAGED_RESOURCE; if (ret != 2) { ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); - add = 1; + add = ADD_MANAGED_RESOURCE; if (ret != 2) return -EINVAL; } @@ -863,12 +861,7 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size if (end_addr <= start_addr) return -EINVAL; - adj.Action = add ? ADD_MANAGED_RESOURCE : REMOVE_MANAGED_RESOURCE; - adj.Resource = RES_IO_RANGE; - adj.resource.io.BasePort = start_addr; - adj.resource.io.NumPorts = end_addr - start_addr + 1; - - ret = adjust_io(s, &adj); + ret = adjust_io(s, add, start_addr, end_addr); return ret ? ret : count; } @@ -901,17 +894,16 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz { struct pcmcia_socket *s = class_get_devdata(class_dev); unsigned long start_addr, end_addr; - unsigned int add = 1; - adjust_t adj; + unsigned int add = ADD_MANAGED_RESOURCE; ssize_t ret = 0; ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); if (ret != 2) { ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); - add = 0; + add = REMOVE_MANAGED_RESOURCE; if (ret != 2) { ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); - add = 1; + add = ADD_MANAGED_RESOURCE; if (ret != 2) return -EINVAL; } @@ -919,12 +911,7 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz if (end_addr <= start_addr) return -EINVAL; - adj.Action = add ? ADD_MANAGED_RESOURCE : REMOVE_MANAGED_RESOURCE; - adj.Resource = RES_MEMORY_RANGE; - adj.resource.memory.Base = start_addr; - adj.resource.memory.Size = end_addr - start_addr + 1; - - ret = adjust_memory(s, &adj); + ret = adjust_memory(s, add, start_addr, end_addr); return ret ? ret : count; } -- cgit v1.2.3-70-g09d2 From 3c29976a6469b81a7858812dc2d4b8430d74004a Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 27 Jun 2005 16:28:46 -0700 Subject: [PATCH] pcmcia: mark parent bridge windows as resources available for PCMCIA devices Automatically mark the parent PCI-PCI bridge windows as resources available for PCMCIA usage. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/rsrc_mgr.c | 2 +- drivers/pcmcia/rsrc_nonstatic.c | 58 +++++++++++++++++++++++++++++++++++++++++ include/pcmcia/ss.h | 3 ++- 3 files changed, 61 insertions(+), 2 deletions(-) (limited to 'drivers/pcmcia/rsrc_nonstatic.c') diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index b6843f8d300..b9269e66281 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -72,7 +72,7 @@ int pcmcia_adjust_resource_info(adjust_t *adj) /* you can't use the old interface if the new * one was used before */ spin_lock_irqsave(&s->lock, flags); - if ((s->resource_setup_done) && + if ((s->resource_setup_new) && !(s->resource_setup_old)) { spin_unlock_irqrestore(&s->lock, flags); continue; diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 6b463609a3a..c8f21796c59 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -768,6 +768,58 @@ static int nonstatic_adjust_resource_info(struct pcmcia_socket *s, adjust_t *adj return CS_UNSUPPORTED_FUNCTION; } +#ifdef CONFIG_PCI +static int nonstatic_autoadd_resources(struct pcmcia_socket *s) +{ + struct resource *res; + int i, done = 0; + + if (!s->cb_dev || !s->cb_dev->bus) + return -ENODEV; + + for (i=0; i < PCI_BUS_NUM_RESOURCES; i++) { + res = s->cb_dev->bus->resource[i]; + if (!res) + continue; + + if (res->flags & IORESOURCE_IO) { + if (res == &ioport_resource) + continue; + printk(KERN_INFO "pcmcia: parent PCI bridge I/O window: 0x%lx - 0x%lx\n", + res->start, res->end); + if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end)) + done |= IORESOURCE_IO; + + } + + if (res->flags & IORESOURCE_MEM) { + if (res == &iomem_resource) + continue; + printk(KERN_INFO "pcmcia: parent PCI bridge Memory window: 0x%lx - 0x%lx\n", + res->start, res->end); + if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end)) + done |= IORESOURCE_MEM; + } + } + + /* if we got at least one of IO, and one of MEM, we can be glad and + * activate the PCMCIA subsystem */ + if (done & (IORESOURCE_MEM | IORESOURCE_IO)) + s->resource_setup_done = 1; + + return 0; +} + +#else + +static inline int nonstatic_autoadd_resources(struct pcmcia_socket *s) +{ + return -ENODEV; +} + +#endif + + static int nonstatic_init(struct pcmcia_socket *s) { struct socket_data *data; @@ -782,6 +834,8 @@ static int nonstatic_init(struct pcmcia_socket *s) s->resource_data = (void *) data; + nonstatic_autoadd_resources(s); + return 0; } @@ -862,6 +916,8 @@ static ssize_t store_io_db(struct class_device *class_dev, const char *buf, size return -EINVAL; ret = adjust_io(s, add, start_addr, end_addr); + if (!ret) + s->resource_setup_new = 1; return ret ? ret : count; } @@ -912,6 +968,8 @@ static ssize_t store_mem_db(struct class_device *class_dev, const char *buf, siz return -EINVAL; ret = adjust_memory(s, add, start_addr, end_addr); + if (!ret) + s->resource_setup_new = 1; return ret ? ret : count; } diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 67b867f31fe..f8797767051 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -216,8 +216,9 @@ struct pcmcia_socket { /* is set to one if resource setup is done using adjust_resource_info() */ u8 resource_setup_old:1; + u8 resource_setup_new:1; - u8 reserved:6; + u8 reserved:5; /* socket operations */ struct pccard_operations * ops; -- cgit v1.2.3-70-g09d2 From 2ad0a0a793cbd87a87488d59abc744374669498f Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 27 Jun 2005 16:28:58 -0700 Subject: [PATCH] pcmcia: resource handling fixes - properly bail out in set_cis_map if call to socket driver's set_mem_map failed - don't abort do_mem_probe cycle if one entry failed (!CONFIG_PCMCIA_PROBE) - don't do iomem probing in chunks larger than 0x800000 (1 << 23) as yenta_socket and vrc4173_cardu.c fail to set_mem_map for windows equal to or larger than (1 << 24). Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/cistpl.c | 9 ++++++++- drivers/pcmcia/rsrc_nonstatic.c | 6 ++++-- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/pcmcia/rsrc_nonstatic.c') diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 8567f4fad50..dd7651ff5b4 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -89,6 +89,8 @@ static void __iomem * set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags) { pccard_mem_map *mem = &s->cis_mem; + int ret; + if (!(s->features & SS_CAP_STATIC_MAP) && mem->res == NULL) { mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s); if (mem->res == NULL) { @@ -99,7 +101,12 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag } mem->card_start = card_offset; mem->flags = flags; - s->ops->set_mem_map(s, mem); + ret = s->ops->set_mem_map(s, mem); + if (ret) { + iounmap(s->cis_virt); + return NULL; + } + if (s->features & SS_CAP_STATIC_MAP) { if (s->cis_virt) iounmap(s->cis_virt); diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index c8f21796c59..51aa04b7ecc 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -372,6 +372,9 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) base, base+num-1); bad = fail = 0; step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff); + /* don't allow too large steps */ + if (step > 0x800000) + step = 0x800000; /* cis_readable wants to map 2x map_size */ if (step < 2 * s->map_size) step = 2 * s->map_size; @@ -465,8 +468,7 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { mm = *m; - if (do_mem_probe(mm.base, mm.num, s)) - break; + do_mem_probe(mm.base, mm.num, s); } } -- cgit v1.2.3-70-g09d2 From b6d00f0de9e932e2884b3b7af8e43c0a61a271ee Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 27 Jun 2005 16:29:02 -0700 Subject: [PATCH] ACPI-based PCI resources: PCMCIA bugfix, but resources missing in trees Don't auto-configure yenta sockets for PCMCIA devices if it is connected to the root PCI bus on the x86 or x86_64 architectures. Previously, this was handled by the "ioport_resource"/"iomem_resource" check a few lines below, but with the new ACPI-based resource handling this doesn't catch all cases any longer. pci-yenta-cardbus-fix.patch and this patch should solve the initialization time trouble. However, the ACPI-based PCI resource handling is badly broken, IMHO: - many resources of devices don't show up in the resource trees ( /proc/iomem and /proc/ioports) any longer. This means that PCMCIA, but also possibly other subsystems (ISA, PnP, ...) do not know which resources it cannot use. - verify_root_windows() should fail if there are no iomem _or_ ioport resources, not only if there are no iomem _and_ ioport resources. Signed-off-by: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/rsrc_nonstatic.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/pcmcia/rsrc_nonstatic.c') diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 51aa04b7ecc..c42455d20eb 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -779,6 +779,17 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s) if (!s->cb_dev || !s->cb_dev->bus) return -ENODEV; +#if defined(CONFIG_X86) || defined(CONFIG_X86_64) + /* If this is the root bus, the risk of hitting + * some strange system devices which aren't protected + * by either ACPI resource tables or properly requested + * resources is too big. Therefore, don't do auto-adding + * of resources at the moment. + */ + if (s->cb_dev->bus->number == 0) + return -EINVAL; +#endif + for (i=0; i < PCI_BUS_NUM_RESOURCES; i++) { res = s->cb_dev->bus->resource[i]; if (!res) -- cgit v1.2.3-70-g09d2