Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * rsrc_nonstatic.c -- Resource management routines for !SS_CAP_STATIC_MAP sockets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * The initial developer of the original code is David A. Hinds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  * (C) 1999		David A. Hinds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <pcmcia/ss.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <pcmcia/cistpl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include "cs_internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) /* moved to rsrc_mgr.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) MODULE_AUTHOR("David A. Hinds, Dominik Brodowski");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) /* Parameters that can be set with 'insmod' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) INT_MODULE_PARM(probe_mem,	1);		/* memory probe? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #ifdef CONFIG_PCMCIA_PROBE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) INT_MODULE_PARM(probe_io,	1);		/* IO port probe? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) INT_MODULE_PARM(mem_limit,	0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) /* for io_db and mem_db */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) struct resource_map {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 	u_long			base, num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	struct resource_map	*next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) struct socket_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 	struct resource_map		mem_db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 	struct resource_map		mem_db_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	struct resource_map		io_db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #define MEM_PROBE_LOW	(1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define MEM_PROBE_HIGH	(1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) /* Action field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #define REMOVE_MANAGED_RESOURCE		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #define ADD_MANAGED_RESOURCE		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) /*======================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68)     Linux resource management extensions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) ======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) static struct resource *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) claim_region(struct pcmcia_socket *s, resource_size_t base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 		resource_size_t size, int type, char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	struct resource *res, *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 	parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 	res = pcmcia_make_resource(base, size, type | IORESOURCE_BUSY, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 	if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 		if (s && s->cb_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 			parent = pci_find_parent_resource(s->cb_dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 		if (!parent || request_resource(parent, res)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 			kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 			res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) static void free_region(struct resource *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 	if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 		release_resource(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 		kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) /*======================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104)     These manage the internal databases of available resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) ======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) static int add_interval(struct resource_map *map, u_long base, u_long num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	struct resource_map *p, *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	for (p = map; ; p = p->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 		if ((p != map) && (p->base+p->num >= base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 			p->num = max(num + base - p->base, p->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 		if ((p->next == map) || (p->next->base > base+num-1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	if (!q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 		printk(KERN_WARNING "out of memory to update resources\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	q->base = base; q->num = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 	q->next = p->next; p->next = q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) static int sub_interval(struct resource_map *map, u_long base, u_long num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	struct resource_map *p, *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	for (p = map; ; p = q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 		q = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 		if (q == map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 		if ((q->base+q->num > base) && (base+num > q->base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 			if (q->base >= base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 				if (q->base+q->num <= base+num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 					/* Delete whole block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 					p->next = q->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 					kfree(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 					/* don't advance the pointer yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 					q = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 				} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 					/* Cut off bit from the front */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 					q->num = q->base + q->num - base - num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 					q->base = base + num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 			} else if (q->base+q->num <= base+num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 				/* Cut off bit from the end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 				q->num = base - q->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 				/* Split the block into two pieces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 				p = kmalloc(sizeof(struct resource_map),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 					GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 				if (!p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 					printk(KERN_WARNING "out of memory to update resources\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 					return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 				p->base = base+num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 				p->num = q->base+q->num - p->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 				q->num = base - q->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 				p->next = q->next ; q->next = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) /*======================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176)     These routines examine a region of IO or memory addresses to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177)     determine what ranges might be genuinely available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) ======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) #ifdef CONFIG_PCMCIA_PROBE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 			unsigned int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	struct socket_data *s_data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	unsigned int i, j, bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	int any;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	u_char *b, hole, most;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	dev_info(&s->dev, "cs: IO port probe %#x-%#x:", base, base+num-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	/* First, what does a floating port look like? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	b = kzalloc(256, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	if (!b) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 		pr_cont("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 		dev_err(&s->dev, "do_io_probe: unable to kmalloc 256 bytes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	for (i = base, most = 0; i < base+num; i += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 		res = claim_region(s, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 		if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 		hole = inb(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 		for (j = 1; j < 8; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 			if (inb(i+j) != hole)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		free_region(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 		if ((j == 8) && (++b[hole] > b[most]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 			most = hole;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 		if (b[most] == 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	kfree(b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	bad = any = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	for (i = base; i < base+num; i += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 		res = claim_region(s, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 		if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 			if (!any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 				pr_cont(" excluding");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 			if (!bad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 				bad = any = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 		for (j = 0; j < 8; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 			if (inb(i+j) != most)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 		free_region(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 		if (j < 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 			if (!any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 				pr_cont(" excluding");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 			if (!bad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 				bad = any = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 			if (bad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 				sub_interval(&s_data->io_db, bad, i-bad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 				pr_cont(" %#x-%#x", bad, i-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 				bad = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	if (bad) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 		if ((num > 16) && (bad == base) && (i == base+num)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 			sub_interval(&s_data->io_db, bad, i-bad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 			pr_cont(" nothing: probe failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 			sub_interval(&s_data->io_db, bad, i-bad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 			pr_cont(" %#x-%#x", bad, i-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	pr_cont("%s\n", !any ? " clean" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) /*======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261)  * readable() - iomem validation function for cards with a valid CIS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) static int readable(struct pcmcia_socket *s, struct resource *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 		    unsigned int *count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	if (s->fake_cis) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 		dev_dbg(&s->dev, "fake CIS is being used: can't validate mem\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	s->cis_mem.res = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	s->cis_virt = ioremap(res->start, s->map_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	if (s->cis_virt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 		mutex_unlock(&s->ops_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 		/* as we're only called from pcmcia.c, we're safe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 		if (s->callback->validate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 			ret = s->callback->validate(s, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 		/* invalidate mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 		mutex_lock(&s->ops_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 		iounmap(s->cis_virt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 		s->cis_virt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	s->cis_mem.res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	if ((ret) || (*count == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292)  * checksum() - iomem validation function for simple memory cards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) static int checksum(struct pcmcia_socket *s, struct resource *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 		    unsigned int *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	pccard_mem_map map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	int i, a = 0, b = -1, d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	void __iomem *virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	virt = ioremap(res->start, s->map_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	if (virt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 		map.map = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 		map.flags = MAP_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 		map.speed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 		map.res = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 		map.card_start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 		s->ops->set_mem_map(s, &map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 		/* Don't bother checking every word... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 		for (i = 0; i < s->map_size; i += 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 			d = readl(virt+i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 			a += d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 			b &= d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 		map.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 		s->ops->set_mem_map(s, &map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 		iounmap(virt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	if (b == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	*value = a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332)  * do_validate_mem() - low level validate a memory region for PCMCIA use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333)  * @s:		PCMCIA socket to validate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334)  * @base:	start address of resource to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335)  * @size:	size of resource to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336)  * @validate:	validation function to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338)  * do_validate_mem() splits up the memory region which is to be checked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339)  * into two parts. Both are passed to the @validate() function. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340)  * @validate() returns non-zero, or the value parameter to @validate()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341)  * is zero, or the value parameter is different between both calls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342)  * the check fails, and -EINVAL is returned. Else, 0 is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) static int do_validate_mem(struct pcmcia_socket *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 			   unsigned long base, unsigned long size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 			   int validate (struct pcmcia_socket *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 					 struct resource *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 					 unsigned int *value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	struct socket_data *s_data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	struct resource *res1, *res2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	unsigned int info1 = 1, info2 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	int ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 			"PCMCIA memprobe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 	if (res1 && res2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 		if (validate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 			ret = validate(s, res1, &info1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 			ret += validate(s, res2, &info2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	dev_dbg(&s->dev, "cs: memory probe 0x%06lx-0x%06lx: %pr %pr %u %u %u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 		base, base+size-1, res1, res2, ret, info1, info2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 	free_region(res2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 	free_region(res1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	if ((ret) || (info1 != info2) || (info1 == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 	if (validate && !s->fake_cis) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 		/* move it to the validated data set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 		add_interval(&s_data->mem_db_valid, base, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		sub_interval(&s_data->mem_db, base, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387)  * do_mem_probe() - validate a memory region for PCMCIA use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388)  * @s:		PCMCIA socket to validate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389)  * @base:	start address of resource to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390)  * @num:	size of resource to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391)  * @validate:	validation function to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392)  * @fallback:	validation function to use if validate fails
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394)  * do_mem_probe() checks a memory region for use by the PCMCIA subsystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395)  * To do so, the area is split up into sensible parts, and then passed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396)  * into the @validate() function. Only if @validate() and @fallback() fail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397)  * the area is marked as unavaibale for use by the PCMCIA subsystem. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398)  * function returns the size of the usable memory area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) static int do_mem_probe(struct pcmcia_socket *s, u_long base, u_long num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 			int validate (struct pcmcia_socket *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 				      struct resource *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 				      unsigned int *value),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 			int fallback (struct pcmcia_socket *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 				      struct resource *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 				      unsigned int *value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	struct socket_data *s_data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	u_long i, j, bad, fail, step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	dev_info(&s->dev, "cs: memory probe 0x%06lx-0x%06lx:",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 		 base, base+num-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	bad = fail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	/* don't allow too large steps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	if (step > 0x800000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 		step = 0x800000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	/* cis_readable wants to map 2x map_size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 	if (step < 2 * s->map_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 		step = 2 * s->map_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	for (i = j = base; i < base+num; i = j + step) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 		if (!fail) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 			for (j = i; j < base+num; j += step) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 				if (!do_validate_mem(s, j, step, validate))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 			fail = ((i == base) && (j == base+num));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 		if ((fail) && (fallback)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 			for (j = i; j < base+num; j += step)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 				if (!do_validate_mem(s, j, step, fallback))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 		if (i != j) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 			if (!bad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 				pr_cont(" excluding");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 			pr_cont(" %#05lx-%#05lx", i, j-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 			sub_interval(&s_data->mem_db, i, j-i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 			bad += j-i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	pr_cont("%s\n", !bad ? " clean" : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	return num - bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) #ifdef CONFIG_PCMCIA_PROBE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450)  * inv_probe() - top-to-bottom search for one usuable high memory area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451)  * @s:		PCMCIA socket to validate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452)  * @m:		resource_map to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	struct socket_data *s_data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	u_long ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 	if (m == &s_data->mem_db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	ok = inv_probe(m->next, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	if (ok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		if (m->base >= 0x100000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 			sub_interval(&s_data->mem_db, m->base, m->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		return ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	if (m->base < 0x100000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 	return do_mem_probe(s, m->base, m->num, readable, checksum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472)  * validate_mem() - memory probe function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473)  * @s:		PCMCIA socket to validate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474)  * @probe_mask: MEM_PROBE_LOW | MEM_PROBE_HIGH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476)  * The memory probe.  If the memory list includes a 64K-aligned block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477)  * below 1MB, we probe in 64K chunks, and as soon as we accumulate at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478)  * least mem_limit free space, we quit. Returns 0 on usuable ports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	struct resource_map *m, mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	unsigned long b, i, ok = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	struct socket_data *s_data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	/* We do up to four passes through the list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	if (probe_mask & MEM_PROBE_HIGH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 		if (inv_probe(s_data->mem_db.next, s) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 		if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 		dev_notice(&s->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 			   "cs: warning: no high memory space available!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 		mm = *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 		/* Only probe < 1 MB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 		if (mm.base >= 0x100000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 		if ((mm.base | mm.num) & 0xffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 			ok += do_mem_probe(s, mm.base, mm.num, readable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 					   checksum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 		/* Special probe for 64K-aligned block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 		for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 			b = order[i] << 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 			if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 				if (ok >= mem_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 					sub_interval(&s_data->mem_db, b, 0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 				else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 					ok += do_mem_probe(s, b, 0x10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 							   readable, checksum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 	if (ok > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) #else /* CONFIG_PCMCIA_PROBE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530)  * validate_mem() - memory probe function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531)  * @s:		PCMCIA socket to validate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532)  * @probe_mask: ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534)  * Returns 0 on usuable ports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	struct resource_map *m, mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	struct socket_data *s_data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	unsigned long ok = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 		mm = *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 		ok += do_mem_probe(s, mm.base, mm.num, readable, checksum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	if (ok > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) #endif /* CONFIG_PCMCIA_PROBE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555)  * pcmcia_nonstatic_validate_mem() - try to validate iomem for PCMCIA use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556)  * @s:		PCMCIA socket to validate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558)  * This is tricky... when we set up CIS memory, we try to validate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559)  * the memory window space allocations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561)  * Locking note: Must be called with skt_mutex held!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	struct socket_data *s_data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	unsigned int probe_mask = MEM_PROBE_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 	if (!probe_mem || !(s->state & SOCKET_PRESENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	if (s->features & SS_CAP_PAGE_REGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 		probe_mask = MEM_PROBE_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	ret = validate_mem(s, probe_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) struct pcmcia_align_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	unsigned long	mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	unsigned long	offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 	struct resource_map	*map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) static resource_size_t pcmcia_common_align(struct pcmcia_align_data *align_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 					resource_size_t start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	resource_size_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	 * Ensure that we have the correct start address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 	ret = (start & ~align_data->mask) + align_data->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 	if (ret < start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		ret += align_data->mask + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) static resource_size_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) pcmcia_align(void *align_data, const struct resource *res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	resource_size_t size, resource_size_t align)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	struct pcmcia_align_data *data = align_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	struct resource_map *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	resource_size_t start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	start = pcmcia_common_align(data, res->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 	for (m = data->map->next; m != data->map; m = m->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 		unsigned long map_start = m->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 		unsigned long map_end = m->base + m->num - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 		 * If the lower resources are not available, try aligning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 		 * to this entry of the resource database to see if it'll
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 		 * fit here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 		if (start < map_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 			start = pcmcia_common_align(data, map_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 		 * If we're above the area which was passed in, there's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 		 * no point proceeding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 		if (start >= res->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 		if ((start + size - 1) <= map_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	 * If we failed to find something suitable, ensure we fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	if (m == data->map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 		start = res->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	return start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645)  * Adjust an existing IO region allocation, but making sure that we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646)  * encroach outside the resources which the user supplied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) static int __nonstatic_adjust_io_region(struct pcmcia_socket *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 					unsigned long r_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 					unsigned long r_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	struct resource_map *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	struct socket_data *s_data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	int ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 		unsigned long start = m->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 		unsigned long end = m->base + m->num - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		if (start > r_start || r_end > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) /*======================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671)     These find ranges of I/O ports or memory addresses that are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672)     currently allocated by other devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674)     The 'align' field should reflect the number of bits of address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675)     that need to be preserved from the initial value of *base.  It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676)     should be a power of two, greater than or equal to 'num'.  A value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677)     of 0 means that all bits of *base are significant.  *base should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678)     also be strictly less than 'align'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) ======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) static struct resource *__nonstatic_find_io_region(struct pcmcia_socket *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 						unsigned long base, int num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 						unsigned long align)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 						dev_name(&s->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	struct socket_data *s_data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	struct pcmcia_align_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	unsigned long min = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	data.mask = align - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	data.offset = base & data.mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	data.map = &s_data->io_db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	if (s->cb_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 		ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 					     min, 0, pcmcia_align, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 					1, pcmcia_align, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 		res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 			unsigned int *base, unsigned int num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 			unsigned int align, struct resource **parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	/* Check for an already-allocated window that must conflict with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	 * what was asked for.  It is a hack because it does not catch all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	 * potential conflicts, just the most obvious ones.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	for (i = 0; i < MAX_IO_WIN; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 		if (!s->io[i].res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 		if (!*base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 		if ((s->io[i].res->start & (align-1)) == *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 			return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 	for (i = 0; i < MAX_IO_WIN; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 		struct resource *res = s->io[i].res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 		unsigned int try;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		if (res && (res->flags & IORESOURCE_BITS) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 			(attr & IORESOURCE_BITS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 		if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 			if (align == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 				align = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 			res = s->io[i].res = __nonstatic_find_io_region(s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 								*base, num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 								align);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 			if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 			*base = res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 			s->io[i].res->flags =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 				((res->flags & ~IORESOURCE_BITS) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 					(attr & IORESOURCE_BITS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 			s->io[i].InUse = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 			*parent = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 		/* Try to extend top of window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 		try = res->end + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 		if ((*base == 0) || (*base == try)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 			ret =  __nonstatic_adjust_io_region(s, res->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 							res->end + num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 			if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 				ret = adjust_resource(s->io[i].res, res->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 						      resource_size(res) + num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 				if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 				*base = try;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 				s->io[i].InUse += num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 				*parent = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 		/* Try to extend bottom of window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		try = res->start - num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 		if ((*base == 0) || (*base == try)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 			ret =  __nonstatic_adjust_io_region(s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 							res->start - num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 							res->end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 			if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 				ret = adjust_resource(s->io[i].res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 						      res->start - num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 						      resource_size(res) + num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 				if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 				*base = try;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 				s->io[i].InUse += num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 				*parent = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) static struct resource *nonstatic_find_mem_region(u_long base, u_long num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 		u_long align, int low, struct pcmcia_socket *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 						dev_name(&s->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 	struct socket_data *s_data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	struct pcmcia_align_data data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 	unsigned long min, max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	int ret, i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 	low = low || !(s->features & SS_CAP_PAGE_REGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	data.mask = align - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	data.offset = base & data.mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 		data.map = &s_data->mem_db_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 		if (low) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 			max = 0x100000UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 			min = base < max ? base : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 			max = ~0UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 			min = 0x100000UL + base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 		for (j = 0; j < 2; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 			if (s->cb_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 				ret = pci_bus_alloc_resource(s->cb_dev->bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 							res, num, 1, min, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 							pcmcia_align, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 			} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 			{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 				ret = allocate_resource(&iomem_resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 							res, num, min, max, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 							pcmcia_align, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 			if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 			data.map = &s_data->mem_db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		if (ret == 0 || low)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 		low = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 	if (ret != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 		kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 	struct socket_data *data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	unsigned long size = end - start + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	if (end < start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	switch (action) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 	case ADD_MANAGED_RESOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 		ret = add_interval(&data->mem_db, start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 		if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 			do_mem_probe(s, start, size, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	case REMOVE_MANAGED_RESOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 		ret = sub_interval(&data->mem_db, start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	struct socket_data *data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) #if defined(CONFIG_X86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	/* on x86, avoid anything < 0x100 for it is often used for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	 * legacy platform devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	if (start < 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 		start = 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	size = end - start + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	if (end < start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	if (end > IO_SPACE_LIMIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	switch (action) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	case ADD_MANAGED_RESOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 		if (add_interval(&data->io_db, start, size) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 			ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) #ifdef CONFIG_PCMCIA_PROBE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 		if (probe_io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 			do_io_probe(s, start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 	case REMOVE_MANAGED_RESOURCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		sub_interval(&data->io_db, start, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	int i, done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	if (!s->cb_dev || !s->cb_dev->bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) #if defined(CONFIG_X86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	/* If this is the root bus, the risk of hitting some strange
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	 * system devices is too high: If a driver isn't loaded, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	 * resources are not claimed; even if a driver is loaded, it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	 * may not request all resources or even the wrong one. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	 * can neither trust the rest of the kernel nor ACPI/PNP and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	 * CRS parsing to get it right. Therefore, use several
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 	 * safeguards:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	 * - Do not auto-add resources if the CardBus bridge is on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	 *   the PCI root bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	 * - Avoid any I/O ports < 0x100.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	 * - On PCI-PCI bridges, only use resources which are set up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	 *   exclusively for the secondary PCI bus: the risk of hitting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	 *   system devices is quite low, as they usually aren't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	 *   connected to the secondary PCI bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	if (s->cb_dev->bus->number == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 		res = s->cb_dev->bus->resource[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	pci_bus_for_each_resource(s->cb_dev->bus, res, i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 		if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		if (res->flags & IORESOURCE_IO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 			/* safeguard against the root resource, where the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 			 * risk of hitting any other device would be too
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 			 * high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 			if (res == &ioport_resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 			dev_info(&s->cb_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 				 "pcmcia: parent PCI bridge window: %pR\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 				 res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 			if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 				done |= IORESOURCE_IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		if (res->flags & IORESOURCE_MEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 			/* safeguard against the root resource, where the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 			 * risk of hitting any other device would be too
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 			 * high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 			if (res == &iomem_resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 			dev_info(&s->cb_dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 				 "pcmcia: parent PCI bridge window: %pR\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 				 res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 			if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 				done |= IORESOURCE_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	/* if we got at least one of IO, and one of MEM, we can be glad and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	 * activate the PCMCIA subsystem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 	if (done == (IORESOURCE_MEM | IORESOURCE_IO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 		s->resource_setup_done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) static inline int nonstatic_autoadd_resources(struct pcmcia_socket *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) static int nonstatic_init(struct pcmcia_socket *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	struct socket_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	data = kzalloc(sizeof(struct socket_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 	if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 	data->mem_db.next = &data->mem_db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	data->mem_db_valid.next = &data->mem_db_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 	data->io_db.next = &data->io_db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	s->resource_data = (void *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	nonstatic_autoadd_resources(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static void nonstatic_release_resource_db(struct pcmcia_socket *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	struct socket_data *data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	struct resource_map *p, *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 	for (p = data->mem_db_valid.next; p != &data->mem_db_valid; p = q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 		q = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	for (p = data->mem_db.next; p != &data->mem_db; p = q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 		q = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	for (p = data->io_db.next; p != &data->io_db; p = q) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 		q = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) 		kfree(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) struct pccard_resource_ops pccard_nonstatic_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 	.validate_mem = pcmcia_nonstatic_validate_mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) 	.find_io = nonstatic_find_io,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) 	.find_mem = nonstatic_find_mem_region,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 	.init = nonstatic_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) 	.exit = nonstatic_release_resource_db,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) EXPORT_SYMBOL(pccard_nonstatic_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) /* sysfs interface to the resource database */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) static ssize_t show_io_db(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) 			  struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 	struct pcmcia_socket *s = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	struct socket_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	struct resource_map *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 	ssize_t ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 	mutex_lock(&s->ops_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 	for (p = data->io_db.next; p != &data->io_db; p = p->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 		if (ret > (PAGE_SIZE - 10))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 		ret += scnprintf(&buf[ret], (PAGE_SIZE - ret - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 				"0x%08lx - 0x%08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 				((unsigned long) p->base),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 				((unsigned long) p->base + p->num - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 	mutex_unlock(&s->ops_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) static ssize_t store_io_db(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 			   struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 			   const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 	struct pcmcia_socket *s = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 	unsigned long start_addr, end_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 	unsigned int add = ADD_MANAGED_RESOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 	ssize_t ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 	if (ret != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 		ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 		add = REMOVE_MANAGED_RESOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 		if (ret != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 			ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 				&end_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 			add = ADD_MANAGED_RESOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 			if (ret != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 	if (end_addr < start_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	mutex_lock(&s->ops_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	ret = adjust_io(s, add, start_addr, end_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 	mutex_unlock(&s->ops_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 	return ret ? ret : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) static DEVICE_ATTR(available_resources_io, 0600, show_io_db, store_io_db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) static ssize_t show_mem_db(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 			   struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 	struct pcmcia_socket *s = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 	struct socket_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	struct resource_map *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 	ssize_t ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 	mutex_lock(&s->ops_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 	data = s->resource_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	for (p = data->mem_db_valid.next; p != &data->mem_db_valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 	     p = p->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 		if (ret > (PAGE_SIZE - 10))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 		ret += scnprintf(&buf[ret], (PAGE_SIZE - ret - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 				"0x%08lx - 0x%08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 				((unsigned long) p->base),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 				((unsigned long) p->base + p->num - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 		if (ret > (PAGE_SIZE - 10))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 		ret += scnprintf(&buf[ret], (PAGE_SIZE - ret - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) 				"0x%08lx - 0x%08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) 				((unsigned long) p->base),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) 				((unsigned long) p->base + p->num - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	mutex_unlock(&s->ops_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) static ssize_t store_mem_db(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 			    struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 			    const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	struct pcmcia_socket *s = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	unsigned long start_addr, end_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	unsigned int add = ADD_MANAGED_RESOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	ssize_t ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	if (ret != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 		add = REMOVE_MANAGED_RESOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 		if (ret != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 			ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 				&end_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 			add = ADD_MANAGED_RESOURCE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 			if (ret != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 	if (end_addr < start_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	mutex_lock(&s->ops_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 	ret = adjust_memory(s, add, start_addr, end_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 	mutex_unlock(&s->ops_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	return ret ? ret : count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) static DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) static struct attribute *pccard_rsrc_attributes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 	&dev_attr_available_resources_io.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	&dev_attr_available_resources_mem.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) static const struct attribute_group rsrc_attributes = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	.attrs = pccard_rsrc_attributes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) static int pccard_sysfs_add_rsrc(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 					   struct class_interface *class_intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 	struct pcmcia_socket *s = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	if (s->resource_ops != &pccard_nonstatic_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 	return sysfs_create_group(&dev->kobj, &rsrc_attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) static void pccard_sysfs_remove_rsrc(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 					       struct class_interface *class_intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	struct pcmcia_socket *s = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	if (s->resource_ops != &pccard_nonstatic_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	sysfs_remove_group(&dev->kobj, &rsrc_attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) static struct class_interface pccard_rsrc_interface __refdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	.class = &pcmcia_socket_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	.add_dev = &pccard_sysfs_add_rsrc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	.remove_dev = &pccard_sysfs_remove_rsrc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) static int __init nonstatic_sysfs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	return class_interface_register(&pccard_rsrc_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) static void __exit nonstatic_sysfs_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	class_interface_unregister(&pccard_rsrc_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) module_init(nonstatic_sysfs_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) module_exit(nonstatic_sysfs_exit);