aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2010-01-02 16:22:50 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2010-01-17 12:30:59 -0500
commit3f32b3c093eddc03ed477ae0d7a6938db6b94a05 (patch)
tree3e949845afa85bb76cb50e5532d7b1825ad39c72 /drivers/pcmcia
parent180c33ee409eb3ed605d4ad9884e4a526a7655ff (diff)
pcmcia: rsrc_nonstatic io memory probe improvements
Add a lot of documentation to the rsrc_nonstatic io memory probe functions. Also, add a first memory probe call -- just checking whether request_resource() succeeds -- upon adding of resources. Tested-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c174
1 files changed, 114 insertions, 60 deletions
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index b886385f12e2..120d5ad99296 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -264,18 +264,15 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
264} 264}
265#endif 265#endif
266 266
267/*====================================================================== 267/*======================================================================*/
268
269 This is tricky... when we set up CIS memory, we try to validate
270 the memory window space allocations.
271
272======================================================================*/
273 268
274/* Validation function for cards with a valid CIS */ 269/**
270 * readable() - iomem validation function for cards with a valid CIS
271 */
275static int readable(struct pcmcia_socket *s, struct resource *res, 272static int readable(struct pcmcia_socket *s, struct resource *res,
276 unsigned int *count) 273 unsigned int *count)
277{ 274{
278 int ret = -1; 275 int ret = -EINVAL;
279 276
280 s->cis_mem.res = res; 277 s->cis_mem.res = res;
281 s->cis_virt = ioremap(res->start, s->map_size); 278 s->cis_virt = ioremap(res->start, s->map_size);
@@ -286,13 +283,16 @@ static int readable(struct pcmcia_socket *s, struct resource *res,
286 s->cis_virt = NULL; 283 s->cis_virt = NULL;
287 } 284 }
288 s->cis_mem.res = NULL; 285 s->cis_mem.res = NULL;
289 if ((ret != 0) || (*count == 0)) 286 if ((ret) || (*count == 0))
290 return 0; 287 return -EINVAL;
291 return 1; 288 return 0;
292} 289}
293 290
294/* Validation function for simple memory cards */ 291/**
295static int checksum(struct pcmcia_socket *s, struct resource *res) 292 * checksum() - iomem validation function for simple memory cards
293 */
294static int checksum(struct pcmcia_socket *s, struct resource *res,
295 unsigned int *value)
296{ 296{
297 pccard_mem_map map; 297 pccard_mem_map map;
298 int i, a = 0, b = -1, d; 298 int i, a = 0, b = -1, d;
@@ -320,61 +320,83 @@ static int checksum(struct pcmcia_socket *s, struct resource *res)
320 iounmap(virt); 320 iounmap(virt);
321 } 321 }
322 322
323 return (b == -1) ? -1 : (a>>1); 323 if (b == -1)
324} 324 return -EINVAL;
325
326static int
327cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
328{
329 struct resource *res1, *res2;
330 unsigned int info1, info2;
331 int ret = 0;
332
333 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe");
334 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM,
335 "PCMCIA memprobe");
336
337 if (res1 && res2) {
338 ret = readable(s, res1, &info1);
339 ret += readable(s, res2, &info2);
340 }
341 325
342 free_region(res2); 326 *value = a;
343 free_region(res1);
344 327
345 return (ret == 2) && (info1 == info2); 328 return 0;
346} 329}
347 330
348static int 331/**
349checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size) 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 */
344static 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))
350{ 349{
351 struct resource *res1, *res2; 350 struct resource *res1, *res2;
352 int a = -1, b = -1; 351 unsigned int info1 = 1, info2 = 1;
352 int ret = -EINVAL;
353 353
354 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe"); 354 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe");
355 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, 355 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM,
356 "PCMCIA memprobe"); 356 "PCMCIA memprobe");
357 357
358 if (res1 && res2) { 358 if (res1 && res2) {
359 a = checksum(s, res1); 359 ret = 0;
360 b = checksum(s, res2); 360 if (validate) {
361 ret = validate(s, res1, &info1);
362 ret += validate(s, res2, &info2);
363 }
361 } 364 }
362 365
363 free_region(res2); 366 free_region(res2);
364 free_region(res1); 367 free_region(res1);
365 368
366 return (a == b) && (a >= 0); 369 dev_dbg(&s->dev, "cs: memory probe 0x%06lx-0x%06lx: %p %p %u %u %u",
367} 370 base, base+size-1, res1, res2, ret, info1, info2);
368 371
369/*====================================================================== 372 if ((ret) || (info1 != info2) || (info1 == 0))
373 return -EINVAL;
370 374
371 The memory probe. If the memory list includes a 64K-aligned block 375 return 0;
372 below 1MB, we probe in 64K chunks, and as soon as we accumulate at 376}
373 least mem_limit free space, we quit.
374 377
375======================================================================*/
376 378
377static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) 379/**
380 * do_mem_probe() - validate a memory region for PCMCIA use
381 * @s: PCMCIA socket to validate
382 * @base: start address of resource to check
383 * @num: size of resource to check
384 * @validate: validation function to use
385 * @fallback: validation function to use if validate fails
386 *
387 * do_mem_probe() checks a memory region for use by the PCMCIA subsystem.
388 * To do so, the area is split up into sensible parts, and then passed
389 * into the @validate() function. Only if @validate() and @fallback() fail,
390 * the area is marked as unavaibale for use by the PCMCIA subsystem. The
391 * function returns the size of the usable memory area.
392 */
393static int do_mem_probe(struct pcmcia_socket *s, u_long base, u_long num,
394 int validate (struct pcmcia_socket *s,
395 struct resource *res,
396 unsigned int *value),
397 int fallback (struct pcmcia_socket *s,
398 struct resource *res,
399 unsigned int *value))
378{ 400{
379 struct socket_data *s_data = s->resource_data; 401 struct socket_data *s_data = s->resource_data;
380 u_long i, j, bad, fail, step; 402 u_long i, j, bad, fail, step;
@@ -392,15 +414,14 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
392 for (i = j = base; i < base+num; i = j + step) { 414 for (i = j = base; i < base+num; i = j + step) {
393 if (!fail) { 415 if (!fail) {
394 for (j = i; j < base+num; j += step) { 416 for (j = i; j < base+num; j += step) {
395 if (cis_readable(s, j, step)) 417 if (!do_validate_mem(s, j, step, validate))
396 break; 418 break;
397 } 419 }
398 fail = ((i == base) && (j == base+num)); 420 fail = ((i == base) && (j == base+num));
399 } 421 }
400 if (fail) { 422 if ((fail) && (fallback)) {
401 for (j = i; j < base+num; j += 2*step) 423 for (j = i; j < base+num; j += step)
402 if (checksum_match(s, j, step) && 424 if (!do_validate_mem(s, j, step, fallback))
403 checksum_match(s, j + step, step))
404 break; 425 break;
405 } 426 }
406 if (i != j) { 427 if (i != j) {
@@ -415,8 +436,14 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
415 return num - bad; 436 return num - bad;
416} 437}
417 438
439
418#ifdef CONFIG_PCMCIA_PROBE 440#ifdef CONFIG_PCMCIA_PROBE
419 441
442/**
443 * inv_probe() - top-to-bottom search for one usuable high memory area
444 * @s: PCMCIA socket to validate
445 * @m: resource_map to check
446 */
420static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s) 447static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
421{ 448{
422 struct socket_data *s_data = s->resource_data; 449 struct socket_data *s_data = s->resource_data;
@@ -431,9 +458,18 @@ static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
431 } 458 }
432 if (m->base < 0x100000) 459 if (m->base < 0x100000)
433 return 0; 460 return 0;
434 return do_mem_probe(m->base, m->num, s); 461 return do_mem_probe(s, m->base, m->num, readable, checksum);
435} 462}
436 463
464/**
465 * validate_mem() - memory probe function
466 * @s: PCMCIA socket to validate
467 * @probe_mask: MEM_PROBE_LOW | MEM_PROBE_HIGH
468 *
469 * The memory probe. If the memory list includes a 64K-aligned block
470 * below 1MB, we probe in 64K chunks, and as soon as we accumulate at
471 * least mem_limit free space, we quit. Returns 0 on usuable ports.
472 */
437static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) 473static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
438{ 474{
439 struct resource_map *m, mm; 475 struct resource_map *m, mm;
@@ -456,7 +492,8 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
456 if (mm.base >= 0x100000) 492 if (mm.base >= 0x100000)
457 continue; 493 continue;
458 if ((mm.base | mm.num) & 0xffff) { 494 if ((mm.base | mm.num) & 0xffff) {
459 ok += do_mem_probe(mm.base, mm.num, s); 495 ok += do_mem_probe(s, mm.base, mm.num, readable,
496 checksum);
460 continue; 497 continue;
461 } 498 }
462 /* Special probe for 64K-aligned block */ 499 /* Special probe for 64K-aligned block */
@@ -466,7 +503,8 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
466 if (ok >= mem_limit) 503 if (ok >= mem_limit)
467 sub_interval(&s_data->mem_db, b, 0x10000); 504 sub_interval(&s_data->mem_db, b, 0x10000);
468 else 505 else
469 ok += do_mem_probe(b, 0x10000, s); 506 ok += do_mem_probe(s, b, 0x10000,
507 readable, checksum);
470 } 508 }
471 } 509 }
472 } 510 }
@@ -479,6 +517,13 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
479 517
480#else /* CONFIG_PCMCIA_PROBE */ 518#else /* CONFIG_PCMCIA_PROBE */
481 519
520/**
521 * validate_mem() - memory probe function
522 * @s: PCMCIA socket to validate
523 * @probe_mask: ignored
524 *
525 * Returns 0 on usuable ports.
526 */
482static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) 527static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
483{ 528{
484 struct resource_map *m, mm; 529 struct resource_map *m, mm;
@@ -487,7 +532,7 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
487 532
488 for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { 533 for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
489 mm = *m; 534 mm = *m;
490 ok += do_mem_probe(mm.base, mm.num, s); 535 ok += do_mem_probe(s, mm.base, mm.num, readable, checksum);
491 } 536 }
492 if (ok > 0) 537 if (ok > 0)
493 return 0; 538 return 0;
@@ -497,7 +542,13 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
497#endif /* CONFIG_PCMCIA_PROBE */ 542#endif /* CONFIG_PCMCIA_PROBE */
498 543
499 544
500/* 545/**
546 * pcmcia_nonstatic_validate_mem() - try to validate iomem for PCMCIA use
547 * @s: PCMCIA socket to validate
548 *
549 * This is tricky... when we set up CIS memory, we try to validate
550 * the memory window space allocations.
551 *
501 * Locking note: Must be called with skt_mutex held! 552 * Locking note: Must be called with skt_mutex held!
502 */ 553 */
503static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) 554static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
@@ -515,10 +566,11 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
515 probe_mask = MEM_PROBE_HIGH; 566 probe_mask = MEM_PROBE_HIGH;
516 567
517 if (probe_mask & ~s_data->rsrc_mem_probe) { 568 if (probe_mask & ~s_data->rsrc_mem_probe) {
518 if (s->state & SOCKET_PRESENT) 569 if (s->state & SOCKET_PRESENT) {
519 ret = validate_mem(s, probe_mask); 570 ret = validate_mem(s, probe_mask);
520 if (!ret) 571 if (!ret)
521 s_data->rsrc_mem_probe |= probe_mask; 572 s_data->rsrc_mem_probe |= probe_mask;
573 }
522 } 574 }
523 575
524 mutex_unlock(&rsrc_mutex); 576 mutex_unlock(&rsrc_mutex);
@@ -723,6 +775,8 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned
723 switch (action) { 775 switch (action) {
724 case ADD_MANAGED_RESOURCE: 776 case ADD_MANAGED_RESOURCE:
725 ret = add_interval(&data->mem_db, start, size); 777 ret = add_interval(&data->mem_db, start, size);
778 if (!ret)
779 do_mem_probe(s, start, size, NULL, NULL);
726 break; 780 break;
727 case REMOVE_MANAGED_RESOURCE: 781 case REMOVE_MANAGED_RESOURCE:
728 ret = sub_interval(&data->mem_db, start, size); 782 ret = sub_interval(&data->mem_db, start, size);