LCOV - code coverage report
Current view: top level - drivers/pcmcia - rsrc_nonstatic.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 2 410 0.5 %
Date: 2022-04-01 14:17:54 Functions: 1 24 4.2 %
Branches: 0 269 0.0 %

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

Generated by: LCOV version 1.14