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