aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/serial_cs.c
diff options
context:
space:
mode:
authorYum Rayan <yum.rayan@gmail.com>2005-05-01 11:59:14 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-01 11:59:14 -0400
commit16f31113a614a35acc2da64f4ae39ab0ed7e194f (patch)
tree65dd7e25ed720d8001e7571645a41817cb88c300 /drivers/serial/serial_cs.c
parentdbcf31ba68c92b23ac3f874c4d516bacd5d7518a (diff)
[PATCH] serial_cs: Reduce stack usage in serial_event()
This patch reduces the stack usage of the function serial_event() in serial_cs from 2212 to 228. I used a patched version of gcc 3.4.3 on i386 with -fno-unit-at-a-time disabled. This patch is only compile tested. Acked-by: Randy Dunlap <rddunlap@osdl.org> Signed-off-by: Yum Rayan <yum.rayan@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/serial/serial_cs.c')
-rw-r--r--drivers/serial/serial_cs.c173
1 files changed, 112 insertions, 61 deletions
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 9034f9ad37c7..6eeb48f6a482 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -107,6 +107,13 @@ struct serial_info {
107 int line[4]; 107 int line[4];
108}; 108};
109 109
110struct serial_cfg_mem {
111 tuple_t tuple;
112 cisparse_t parse;
113 u_char buf[256];
114};
115
116
110static void serial_config(dev_link_t * link); 117static void serial_config(dev_link_t * link);
111static int serial_event(event_t event, int priority, 118static int serial_event(event_t event, int priority,
112 event_callback_args_t * args); 119 event_callback_args_t * args);
@@ -357,14 +364,24 @@ static int simple_config(dev_link_t *link)
357 static int size_table[2] = { 8, 16 }; 364 static int size_table[2] = { 8, 16 };
358 client_handle_t handle = link->handle; 365 client_handle_t handle = link->handle;
359 struct serial_info *info = link->priv; 366 struct serial_info *info = link->priv;
360 tuple_t tuple; 367 struct serial_cfg_mem *cfg_mem;
361 u_char buf[256]; 368 tuple_t *tuple;
362 cisparse_t parse; 369 u_char *buf;
363 cistpl_cftable_entry_t *cf = &parse.cftable_entry; 370 cisparse_t *parse;
371 cistpl_cftable_entry_t *cf;
364 config_info_t config; 372 config_info_t config;
365 int i, j, try; 373 int i, j, try;
366 int s; 374 int s;
367 375
376 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
377 if (!cfg_mem)
378 return -1;
379
380 tuple = &cfg_mem->tuple;
381 parse = &cfg_mem->parse;
382 cf = &parse->cftable_entry;
383 buf = cfg_mem->buf;
384
368 /* If the card is already configured, look up the port and irq */ 385 /* If the card is already configured, look up the port and irq */
369 i = pcmcia_get_configuration_info(handle, &config); 386 i = pcmcia_get_configuration_info(handle, &config);
370 if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) { 387 if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
@@ -377,21 +394,23 @@ static int simple_config(dev_link_t *link)
377 port = config.BasePort1 + 0x28; 394 port = config.BasePort1 + 0x28;
378 info->slave = 1; 395 info->slave = 1;
379 } 396 }
380 if (info->slave) 397 if (info->slave) {
398 kfree(cfg_mem);
381 return setup_serial(handle, info, port, config.AssignedIRQ); 399 return setup_serial(handle, info, port, config.AssignedIRQ);
400 }
382 } 401 }
383 link->conf.Vcc = config.Vcc; 402 link->conf.Vcc = config.Vcc;
384 403
385 /* First pass: look for a config entry that looks normal. */ 404 /* First pass: look for a config entry that looks normal. */
386 tuple.TupleData = (cisdata_t *) buf; 405 tuple->TupleData = (cisdata_t *) buf;
387 tuple.TupleOffset = 0; 406 tuple->TupleOffset = 0;
388 tuple.TupleDataMax = 255; 407 tuple->TupleDataMax = 255;
389 tuple.Attributes = 0; 408 tuple->Attributes = 0;
390 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 409 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
391 /* Two tries: without IO aliases, then with aliases */ 410 /* Two tries: without IO aliases, then with aliases */
392 for (s = 0; s < 2; s++) { 411 for (s = 0; s < 2; s++) {
393 for (try = 0; try < 2; try++) { 412 for (try = 0; try < 2; try++) {
394 i = first_tuple(handle, &tuple, &parse); 413 i = first_tuple(handle, tuple, parse);
395 while (i != CS_NO_MORE_ITEMS) { 414 while (i != CS_NO_MORE_ITEMS) {
396 if (i != CS_SUCCESS) 415 if (i != CS_SUCCESS)
397 goto next_entry; 416 goto next_entry;
@@ -409,14 +428,14 @@ static int simple_config(dev_link_t *link)
409 goto found_port; 428 goto found_port;
410 } 429 }
411next_entry: 430next_entry:
412 i = next_tuple(handle, &tuple, &parse); 431 i = next_tuple(handle, tuple, parse);
413 } 432 }
414 } 433 }
415 } 434 }
416 /* Second pass: try to find an entry that isn't picky about 435 /* Second pass: try to find an entry that isn't picky about
417 its base address, then try to grab any standard serial port 436 its base address, then try to grab any standard serial port
418 address, and finally try to get any free port. */ 437 address, and finally try to get any free port. */
419 i = first_tuple(handle, &tuple, &parse); 438 i = first_tuple(handle, tuple, parse);
420 while (i != CS_NO_MORE_ITEMS) { 439 while (i != CS_NO_MORE_ITEMS) {
421 if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && 440 if ((i == CS_SUCCESS) && (cf->io.nwin > 0) &&
422 ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { 441 ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
@@ -429,7 +448,7 @@ next_entry:
429 goto found_port; 448 goto found_port;
430 } 449 }
431 } 450 }
432 i = next_tuple(handle, &tuple, &parse); 451 i = next_tuple(handle, tuple, parse);
433 } 452 }
434 453
435 found_port: 454 found_port:
@@ -437,6 +456,7 @@ next_entry:
437 printk(KERN_NOTICE 456 printk(KERN_NOTICE
438 "serial_cs: no usable port range found, giving up\n"); 457 "serial_cs: no usable port range found, giving up\n");
439 cs_error(link->handle, RequestIO, i); 458 cs_error(link->handle, RequestIO, i);
459 kfree(cfg_mem);
440 return -1; 460 return -1;
441 } 461 }
442 462
@@ -450,9 +470,10 @@ next_entry:
450 i = pcmcia_request_configuration(link->handle, &link->conf); 470 i = pcmcia_request_configuration(link->handle, &link->conf);
451 if (i != CS_SUCCESS) { 471 if (i != CS_SUCCESS) {
452 cs_error(link->handle, RequestConfiguration, i); 472 cs_error(link->handle, RequestConfiguration, i);
473 kfree(cfg_mem);
453 return -1; 474 return -1;
454 } 475 }
455 476 kfree(cfg_mem);
456 return setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ); 477 return setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
457} 478}
458 479
@@ -460,29 +481,39 @@ static int multi_config(dev_link_t * link)
460{ 481{
461 client_handle_t handle = link->handle; 482 client_handle_t handle = link->handle;
462 struct serial_info *info = link->priv; 483 struct serial_info *info = link->priv;
463 tuple_t tuple; 484 struct serial_cfg_mem *cfg_mem;
464 u_char buf[256]; 485 tuple_t *tuple;
465 cisparse_t parse; 486 u_char *buf;
466 cistpl_cftable_entry_t *cf = &parse.cftable_entry; 487 cisparse_t *parse;
488 cistpl_cftable_entry_t *cf;
467 config_info_t config; 489 config_info_t config;
468 int i, base2 = 0; 490 int i, rc, base2 = 0;
491
492 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
493 if (!cfg_mem)
494 return -1;
495 tuple = &cfg_mem->tuple;
496 parse = &cfg_mem->parse;
497 cf = &parse->cftable_entry;
498 buf = cfg_mem->buf;
469 499
470 i = pcmcia_get_configuration_info(handle, &config); 500 i = pcmcia_get_configuration_info(handle, &config);
471 if (i != CS_SUCCESS) { 501 if (i != CS_SUCCESS) {
472 cs_error(handle, GetConfigurationInfo, i); 502 cs_error(handle, GetConfigurationInfo, i);
473 return -1; 503 rc = -1;
504 goto free_cfg_mem;
474 } 505 }
475 link->conf.Vcc = config.Vcc; 506 link->conf.Vcc = config.Vcc;
476 507
477 tuple.TupleData = (cisdata_t *) buf; 508 tuple->TupleData = (cisdata_t *) buf;
478 tuple.TupleOffset = 0; 509 tuple->TupleOffset = 0;
479 tuple.TupleDataMax = 255; 510 tuple->TupleDataMax = 255;
480 tuple.Attributes = 0; 511 tuple->Attributes = 0;
481 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 512 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
482 513
483 /* First, look for a generic full-sized window */ 514 /* First, look for a generic full-sized window */
484 link->io.NumPorts1 = info->multi * 8; 515 link->io.NumPorts1 = info->multi * 8;
485 i = first_tuple(handle, &tuple, &parse); 516 i = first_tuple(handle, tuple, parse);
486 while (i != CS_NO_MORE_ITEMS) { 517 while (i != CS_NO_MORE_ITEMS) {
487 /* The quad port cards have bad CIS's, so just look for a 518 /* The quad port cards have bad CIS's, so just look for a
488 window larger than 8 ports and assume it will be right */ 519 window larger than 8 ports and assume it will be right */
@@ -497,14 +528,14 @@ static int multi_config(dev_link_t * link)
497 if (i == CS_SUCCESS) 528 if (i == CS_SUCCESS)
498 break; 529 break;
499 } 530 }
500 i = next_tuple(handle, &tuple, &parse); 531 i = next_tuple(handle, tuple, parse);
501 } 532 }
502 533
503 /* If that didn't work, look for two windows */ 534 /* If that didn't work, look for two windows */
504 if (i != CS_SUCCESS) { 535 if (i != CS_SUCCESS) {
505 link->io.NumPorts1 = link->io.NumPorts2 = 8; 536 link->io.NumPorts1 = link->io.NumPorts2 = 8;
506 info->multi = 2; 537 info->multi = 2;
507 i = first_tuple(handle, &tuple, &parse); 538 i = first_tuple(handle, tuple, parse);
508 while (i != CS_NO_MORE_ITEMS) { 539 while (i != CS_NO_MORE_ITEMS) {
509 if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { 540 if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) {
510 link->conf.ConfigIndex = cf->index; 541 link->conf.ConfigIndex = cf->index;
@@ -517,13 +548,14 @@ static int multi_config(dev_link_t * link)
517 if (i == CS_SUCCESS) 548 if (i == CS_SUCCESS)
518 break; 549 break;
519 } 550 }
520 i = next_tuple(handle, &tuple, &parse); 551 i = next_tuple(handle, tuple, parse);
521 } 552 }
522 } 553 }
523 554
524 if (i != CS_SUCCESS) { 555 if (i != CS_SUCCESS) {
525 cs_error(link->handle, RequestIO, i); 556 cs_error(link->handle, RequestIO, i);
526 return -1; 557 rc = -1;
558 goto free_cfg_mem;
527 } 559 }
528 560
529 i = pcmcia_request_irq(link->handle, &link->irq); 561 i = pcmcia_request_irq(link->handle, &link->irq);
@@ -541,7 +573,8 @@ static int multi_config(dev_link_t * link)
541 i = pcmcia_request_configuration(link->handle, &link->conf); 573 i = pcmcia_request_configuration(link->handle, &link->conf);
542 if (i != CS_SUCCESS) { 574 if (i != CS_SUCCESS) {
543 cs_error(link->handle, RequestConfiguration, i); 575 cs_error(link->handle, RequestConfiguration, i);
544 return -1; 576 rc = -1;
577 goto free_cfg_mem;
545 } 578 }
546 579
547 /* The Oxford Semiconductor OXCF950 cards are in fact single-port: 580 /* The Oxford Semiconductor OXCF950 cards are in fact single-port:
@@ -554,17 +587,23 @@ static int multi_config(dev_link_t * link)
554 setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ); 587 setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
555 outb(12, base2 + 1); 588 outb(12, base2 + 1);
556 } 589 }
557 return 0; 590 rc = 0;
591 goto free_cfg_mem;
558 } 592 }
559 593
560 setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ); 594 setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ);
561 /* The Nokia cards are not really multiport cards */ 595 /* The Nokia cards are not really multiport cards */
562 if (info->manfid == MANFID_NOKIA) 596 if (info->manfid == MANFID_NOKIA) {
563 return 0; 597 rc = 0;
598 goto free_cfg_mem;
599 }
564 for (i = 0; i < info->multi - 1; i++) 600 for (i = 0; i < info->multi - 1; i++)
565 setup_serial(handle, info, base2 + (8 * i), link->irq.AssignedIRQ); 601 setup_serial(handle, info, base2 + (8 * i),
566 602 link->irq.AssignedIRQ);
567 return 0; 603 rc = 0;
604free_cfg_mem:
605 kfree(cfg_mem);
606 return rc;
568} 607}
569 608
570/*====================================================================== 609/*======================================================================
@@ -579,39 +618,49 @@ void serial_config(dev_link_t * link)
579{ 618{
580 client_handle_t handle = link->handle; 619 client_handle_t handle = link->handle;
581 struct serial_info *info = link->priv; 620 struct serial_info *info = link->priv;
582 tuple_t tuple; 621 struct serial_cfg_mem *cfg_mem;
583 u_short buf[128]; 622 tuple_t *tuple;
584 cisparse_t parse; 623 u_char *buf;
585 cistpl_cftable_entry_t *cf = &parse.cftable_entry; 624 cisparse_t *parse;
625 cistpl_cftable_entry_t *cf;
586 int i, last_ret, last_fn; 626 int i, last_ret, last_fn;
587 627
588 DEBUG(0, "serial_config(0x%p)\n", link); 628 DEBUG(0, "serial_config(0x%p)\n", link);
589 629
590 tuple.TupleData = (cisdata_t *) buf; 630 cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL);
591 tuple.TupleOffset = 0; 631 if (!cfg_mem)
592 tuple.TupleDataMax = 255; 632 goto failed;
593 tuple.Attributes = 0; 633
634 tuple = &cfg_mem->tuple;
635 parse = &cfg_mem->parse;
636 cf = &parse->cftable_entry;
637 buf = cfg_mem->buf;
638
639 tuple->TupleData = (cisdata_t *) buf;
640 tuple->TupleOffset = 0;
641 tuple->TupleDataMax = 255;
642 tuple->Attributes = 0;
594 /* Get configuration register information */ 643 /* Get configuration register information */
595 tuple.DesiredTuple = CISTPL_CONFIG; 644 tuple->DesiredTuple = CISTPL_CONFIG;
596 last_ret = first_tuple(handle, &tuple, &parse); 645 last_ret = first_tuple(handle, tuple, parse);
597 if (last_ret != CS_SUCCESS) { 646 if (last_ret != CS_SUCCESS) {
598 last_fn = ParseTuple; 647 last_fn = ParseTuple;
599 goto cs_failed; 648 goto cs_failed;
600 } 649 }
601 link->conf.ConfigBase = parse.config.base; 650 link->conf.ConfigBase = parse->config.base;
602 link->conf.Present = parse.config.rmask[0]; 651 link->conf.Present = parse->config.rmask[0];
603 652
604 /* Configure card */ 653 /* Configure card */
605 link->state |= DEV_CONFIG; 654 link->state |= DEV_CONFIG;
606 655
607 /* Is this a compliant multifunction card? */ 656 /* Is this a compliant multifunction card? */
608 tuple.DesiredTuple = CISTPL_LONGLINK_MFC; 657 tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
609 tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; 658 tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK;
610 info->multi = (first_tuple(handle, &tuple, &parse) == CS_SUCCESS); 659 info->multi = (first_tuple(handle, tuple, parse) == CS_SUCCESS);
611 660
612 /* Is this a multiport card? */ 661 /* Is this a multiport card? */
613 tuple.DesiredTuple = CISTPL_MANFID; 662 tuple->DesiredTuple = CISTPL_MANFID;
614 if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { 663 if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
615 info->manfid = le16_to_cpu(buf[0]); 664 info->manfid = le16_to_cpu(buf[0]);
616 for (i = 0; i < MULTI_COUNT; i++) 665 for (i = 0; i < MULTI_COUNT; i++)
617 if ((info->manfid == multi_id[i].manfid) && 666 if ((info->manfid == multi_id[i].manfid) &&
@@ -623,13 +672,13 @@ void serial_config(dev_link_t * link)
623 672
624 /* Another check for dual-serial cards: look for either serial or 673 /* Another check for dual-serial cards: look for either serial or
625 multifunction cards that ask for appropriate IO port ranges */ 674 multifunction cards that ask for appropriate IO port ranges */
626 tuple.DesiredTuple = CISTPL_FUNCID; 675 tuple->DesiredTuple = CISTPL_FUNCID;
627 if ((info->multi == 0) && 676 if ((info->multi == 0) &&
628 ((first_tuple(handle, &tuple, &parse) != CS_SUCCESS) || 677 ((first_tuple(handle, tuple, parse) != CS_SUCCESS) ||
629 (parse.funcid.func == CISTPL_FUNCID_MULTI) || 678 (parse->funcid.func == CISTPL_FUNCID_MULTI) ||
630 (parse.funcid.func == CISTPL_FUNCID_SERIAL))) { 679 (parse->funcid.func == CISTPL_FUNCID_SERIAL))) {
631 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 680 tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
632 if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { 681 if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
633 if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) 682 if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
634 info->multi = cf->io.win[0].len >> 3; 683 info->multi = cf->io.win[0].len >> 3;
635 if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && 684 if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
@@ -664,6 +713,7 @@ void serial_config(dev_link_t * link)
664 713
665 link->dev = &info->node[0]; 714 link->dev = &info->node[0];
666 link->state &= ~DEV_CONFIG_PENDING; 715 link->state &= ~DEV_CONFIG_PENDING;
716 kfree(cfg_mem);
667 return; 717 return;
668 718
669 cs_failed: 719 cs_failed:
@@ -671,6 +721,7 @@ void serial_config(dev_link_t * link)
671 failed: 721 failed:
672 serial_remove(link); 722 serial_remove(link);
673 link->state &= ~DEV_CONFIG_PENDING; 723 link->state &= ~DEV_CONFIG_PENDING;
724 kfree(cfg_mem);
674} 725}
675 726
676/*====================================================================== 727/*======================================================================