aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@web.de>2010-02-08 05:12:14 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-16 19:01:22 -0500
commit0ca3a017a7373a4545dd7b345a8a0cecc16bc7e2 (patch)
treea739bfb8ddd0c7fcfdcd40ab6fcd990570c716bf
parentef69bb2ec6036945da1d3d3f07b75253f484f693 (diff)
CAPI: Rework locking of controller data structures
This patch applies the mutex so far only protecting the controller list to (almost) all accesses of controller data structures. It also reworks waiting on state changes in old_capi_manufacturer so that it no longer poll and holds a module reference to the controller owner while waiting (the latter was partly done already). Modification and checking of the blocked state remains racy by design, the caller is responsible for dealing with this. Signed-off-by: Jan Kiszka <jan.kiszka@web.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/isdn/capi/kcapi.c291
-rw-r--r--drivers/isdn/capi/kcapi.h5
-rw-r--r--drivers/isdn/capi/kcapi_proc.c5
-rw-r--r--include/linux/isdn/capilli.h5
4 files changed, 217 insertions, 89 deletions
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index e08914d33be1..a99f7e3f8f51 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -61,11 +61,12 @@ static char capi_manufakturer[64] = "AVM Berlin";
61LIST_HEAD(capi_drivers); 61LIST_HEAD(capi_drivers);
62DEFINE_MUTEX(capi_drivers_lock); 62DEFINE_MUTEX(capi_drivers_lock);
63 63
64struct capi_ctr *capi_controller[CAPI_MAXCONTR];
65DEFINE_MUTEX(capi_controller_lock);
66
64static DEFINE_RWLOCK(application_lock); 67static DEFINE_RWLOCK(application_lock);
65static DEFINE_MUTEX(controller_mutex);
66 68
67struct capi20_appl *capi_applications[CAPI_MAXAPPL]; 69struct capi20_appl *capi_applications[CAPI_MAXAPPL];
68struct capi_ctr *capi_controller[CAPI_MAXCONTR];
69 70
70static int ncontrollers; 71static int ncontrollers;
71 72
@@ -171,13 +172,15 @@ static void notify_up(u32 contr)
171 struct capi_ctr *ctr; 172 struct capi_ctr *ctr;
172 u16 applid; 173 u16 applid;
173 174
175 mutex_lock(&capi_controller_lock);
176
174 if (showcapimsgs & 1) 177 if (showcapimsgs & 1)
175 printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); 178 printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
176 179
177 ctr = get_capi_ctr_by_nr(contr); 180 ctr = get_capi_ctr_by_nr(contr);
178 if (ctr) { 181 if (ctr) {
179 if (ctr->state == CAPI_CTR_RUNNING) 182 if (ctr->state == CAPI_CTR_RUNNING)
180 return; 183 goto unlock_out;
181 184
182 ctr->state = CAPI_CTR_RUNNING; 185 ctr->state = CAPI_CTR_RUNNING;
183 186
@@ -187,19 +190,24 @@ static void notify_up(u32 contr)
187 continue; 190 continue;
188 register_appl(ctr, applid, &ap->rparam); 191 register_appl(ctr, applid, &ap->rparam);
189 } 192 }
193
194 wake_up_interruptible_all(&ctr->state_wait_queue);
190 } else 195 } else
191 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); 196 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
197
198unlock_out:
199 mutex_unlock(&capi_controller_lock);
192} 200}
193 201
194static void ctr_down(struct capi_ctr *ctr) 202static void ctr_down(struct capi_ctr *ctr, int new_state)
195{ 203{
196 struct capi20_appl *ap; 204 struct capi20_appl *ap;
197 u16 applid; 205 u16 applid;
198 206
199 if (ctr->state == CAPI_CTR_DETECTED) 207 if (ctr->state == CAPI_CTR_DETECTED || ctr->state == CAPI_CTR_DETACHED)
200 return; 208 return;
201 209
202 ctr->state = CAPI_CTR_DETECTED; 210 ctr->state = new_state;
203 211
204 memset(ctr->manu, 0, sizeof(ctr->manu)); 212 memset(ctr->manu, 0, sizeof(ctr->manu));
205 memset(&ctr->version, 0, sizeof(ctr->version)); 213 memset(&ctr->version, 0, sizeof(ctr->version));
@@ -211,20 +219,26 @@ static void ctr_down(struct capi_ctr *ctr)
211 if (ap && !ap->release_in_progress) 219 if (ap && !ap->release_in_progress)
212 capi_ctr_put(ctr); 220 capi_ctr_put(ctr);
213 } 221 }
222
223 wake_up_interruptible_all(&ctr->state_wait_queue);
214} 224}
215 225
216static void notify_down(u32 contr) 226static void notify_down(u32 contr)
217{ 227{
218 struct capi_ctr *ctr; 228 struct capi_ctr *ctr;
219 229
230 mutex_lock(&capi_controller_lock);
231
220 if (showcapimsgs & 1) 232 if (showcapimsgs & 1)
221 printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr); 233 printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr);
222 234
223 ctr = get_capi_ctr_by_nr(contr); 235 ctr = get_capi_ctr_by_nr(contr);
224 if (ctr) 236 if (ctr)
225 ctr_down(ctr); 237 ctr_down(ctr, CAPI_CTR_DETECTED);
226 else 238 else
227 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); 239 printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
240
241 mutex_unlock(&capi_controller_lock);
228} 242}
229 243
230static int 244static int
@@ -436,6 +450,9 @@ EXPORT_SYMBOL(capi_ctr_down);
436 * @ctr: controller descriptor structure. 450 * @ctr: controller descriptor structure.
437 * 451 *
438 * Called by hardware driver to stop data flow. 452 * Called by hardware driver to stop data flow.
453 *
454 * Note: The caller is responsible for synchronizing concurrent state changes
455 * as well as invocations of capi_ctr_handle_message.
439 */ 456 */
440 457
441void capi_ctr_suspend_output(struct capi_ctr *ctr) 458void capi_ctr_suspend_output(struct capi_ctr *ctr)
@@ -454,6 +471,9 @@ EXPORT_SYMBOL(capi_ctr_suspend_output);
454 * @ctr: controller descriptor structure. 471 * @ctr: controller descriptor structure.
455 * 472 *
456 * Called by hardware driver to resume data flow. 473 * Called by hardware driver to resume data flow.
474 *
475 * Note: The caller is responsible for synchronizing concurrent state changes
476 * as well as invocations of capi_ctr_handle_message.
457 */ 477 */
458 478
459void capi_ctr_resume_output(struct capi_ctr *ctr) 479void capi_ctr_resume_output(struct capi_ctr *ctr)
@@ -481,21 +501,19 @@ int attach_capi_ctr(struct capi_ctr *ctr)
481{ 501{
482 int i; 502 int i;
483 503
484 mutex_lock(&controller_mutex); 504 mutex_lock(&capi_controller_lock);
485 505
486 for (i = 0; i < CAPI_MAXCONTR; i++) { 506 for (i = 0; i < CAPI_MAXCONTR; i++) {
487 if (!capi_controller[i]) 507 if (!capi_controller[i])
488 break; 508 break;
489 } 509 }
490 if (i == CAPI_MAXCONTR) { 510 if (i == CAPI_MAXCONTR) {
491 mutex_unlock(&controller_mutex); 511 mutex_unlock(&capi_controller_lock);
492 printk(KERN_ERR "kcapi: out of controller slots\n"); 512 printk(KERN_ERR "kcapi: out of controller slots\n");
493 return -EBUSY; 513 return -EBUSY;
494 } 514 }
495 capi_controller[i] = ctr; 515 capi_controller[i] = ctr;
496 516
497 mutex_unlock(&controller_mutex);
498
499 ctr->nrecvctlpkt = 0; 517 ctr->nrecvctlpkt = 0;
500 ctr->nrecvdatapkt = 0; 518 ctr->nrecvdatapkt = 0;
501 ctr->nsentctlpkt = 0; 519 ctr->nsentctlpkt = 0;
@@ -504,11 +522,15 @@ int attach_capi_ctr(struct capi_ctr *ctr)
504 ctr->state = CAPI_CTR_DETECTED; 522 ctr->state = CAPI_CTR_DETECTED;
505 ctr->blocked = 0; 523 ctr->blocked = 0;
506 ctr->traceflag = showcapimsgs; 524 ctr->traceflag = showcapimsgs;
525 init_waitqueue_head(&ctr->state_wait_queue);
507 526
508 sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr); 527 sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr);
509 ctr->procent = proc_create_data(ctr->procfn, 0, NULL, ctr->proc_fops, ctr); 528 ctr->procent = proc_create_data(ctr->procfn, 0, NULL, ctr->proc_fops, ctr);
510 529
511 ncontrollers++; 530 ncontrollers++;
531
532 mutex_unlock(&capi_controller_lock);
533
512 printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n", 534 printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n",
513 ctr->cnr, ctr->name); 535 ctr->cnr, ctr->name);
514 return 0; 536 return 0;
@@ -527,19 +549,29 @@ EXPORT_SYMBOL(attach_capi_ctr);
527 549
528int detach_capi_ctr(struct capi_ctr *ctr) 550int detach_capi_ctr(struct capi_ctr *ctr)
529{ 551{
530 ctr_down(ctr); 552 int err = 0;
531 553
532 ncontrollers--; 554 mutex_lock(&capi_controller_lock);
533 555
534 if (ctr->procent) { 556 ctr_down(ctr, CAPI_CTR_DETACHED);
535 remove_proc_entry(ctr->procfn, NULL); 557
536 ctr->procent = NULL; 558 if (capi_controller[ctr->cnr - 1] != ctr) {
559 err = -EINVAL;
560 goto unlock_out;
537 } 561 }
538 capi_controller[ctr->cnr - 1] = NULL; 562 capi_controller[ctr->cnr - 1] = NULL;
563 ncontrollers--;
564
565 if (ctr->procent)
566 remove_proc_entry(ctr->procfn, NULL);
567
539 printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n", 568 printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n",
540 ctr->cnr, ctr->name); 569 ctr->cnr, ctr->name);
541 570
542 return 0; 571unlock_out:
572 mutex_unlock(&capi_controller_lock);
573
574 return err;
543} 575}
544 576
545EXPORT_SYMBOL(detach_capi_ctr); 577EXPORT_SYMBOL(detach_capi_ctr);
@@ -589,13 +621,21 @@ EXPORT_SYMBOL(unregister_capi_driver);
589 621
590u16 capi20_isinstalled(void) 622u16 capi20_isinstalled(void)
591{ 623{
624 u16 ret = CAPI_REGNOTINSTALLED;
592 int i; 625 int i;
593 for (i = 0; i < CAPI_MAXCONTR; i++) { 626
627 mutex_lock(&capi_controller_lock);
628
629 for (i = 0; i < CAPI_MAXCONTR; i++)
594 if (capi_controller[i] && 630 if (capi_controller[i] &&
595 capi_controller[i]->state == CAPI_CTR_RUNNING) 631 capi_controller[i]->state == CAPI_CTR_RUNNING) {
596 return CAPI_NOERROR; 632 ret = CAPI_NOERROR;
597 } 633 break;
598 return CAPI_REGNOTINSTALLED; 634 }
635
636 mutex_unlock(&capi_controller_lock);
637
638 return ret;
599} 639}
600 640
601EXPORT_SYMBOL(capi20_isinstalled); 641EXPORT_SYMBOL(capi20_isinstalled);
@@ -648,14 +688,16 @@ u16 capi20_register(struct capi20_appl *ap)
648 688
649 write_unlock_irqrestore(&application_lock, flags); 689 write_unlock_irqrestore(&application_lock, flags);
650 690
651 mutex_lock(&controller_mutex); 691 mutex_lock(&capi_controller_lock);
692
652 for (i = 0; i < CAPI_MAXCONTR; i++) { 693 for (i = 0; i < CAPI_MAXCONTR; i++) {
653 if (!capi_controller[i] || 694 if (!capi_controller[i] ||
654 capi_controller[i]->state != CAPI_CTR_RUNNING) 695 capi_controller[i]->state != CAPI_CTR_RUNNING)
655 continue; 696 continue;
656 register_appl(capi_controller[i], applid, &ap->rparam); 697 register_appl(capi_controller[i], applid, &ap->rparam);
657 } 698 }
658 mutex_unlock(&controller_mutex); 699
700 mutex_unlock(&capi_controller_lock);
659 701
660 if (showcapimsgs & 1) { 702 if (showcapimsgs & 1) {
661 printk(KERN_DEBUG "kcapi: appl %d up\n", applid); 703 printk(KERN_DEBUG "kcapi: appl %d up\n", applid);
@@ -688,14 +730,16 @@ u16 capi20_release(struct capi20_appl *ap)
688 capi_applications[ap->applid - 1] = NULL; 730 capi_applications[ap->applid - 1] = NULL;
689 write_unlock_irqrestore(&application_lock, flags); 731 write_unlock_irqrestore(&application_lock, flags);
690 732
691 mutex_lock(&controller_mutex); 733 mutex_lock(&capi_controller_lock);
734
692 for (i = 0; i < CAPI_MAXCONTR; i++) { 735 for (i = 0; i < CAPI_MAXCONTR; i++) {
693 if (!capi_controller[i] || 736 if (!capi_controller[i] ||
694 capi_controller[i]->state != CAPI_CTR_RUNNING) 737 capi_controller[i]->state != CAPI_CTR_RUNNING)
695 continue; 738 continue;
696 release_appl(capi_controller[i], ap->applid); 739 release_appl(capi_controller[i], ap->applid);
697 } 740 }
698 mutex_unlock(&controller_mutex); 741
742 mutex_unlock(&capi_controller_lock);
699 743
700 flush_scheduled_work(); 744 flush_scheduled_work();
701 skb_queue_purge(&ap->recv_queue); 745 skb_queue_purge(&ap->recv_queue);
@@ -734,6 +778,12 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb)
734 || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) 778 || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
735 || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) 779 || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
736 return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; 780 return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
781
782 /*
783 * The controller reference is protected by the existence of the
784 * application passed to us. We assume that the caller properly
785 * synchronizes this service with capi20_release.
786 */
737 ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); 787 ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data));
738 if (!ctr || ctr->state != CAPI_CTR_RUNNING) { 788 if (!ctr || ctr->state != CAPI_CTR_RUNNING) {
739 ctr = get_capi_ctr_by_nr(1); /* XXX why? */ 789 ctr = get_capi_ctr_by_nr(1); /* XXX why? */
@@ -798,16 +848,24 @@ EXPORT_SYMBOL(capi20_put_message);
798u16 capi20_get_manufacturer(u32 contr, u8 *buf) 848u16 capi20_get_manufacturer(u32 contr, u8 *buf)
799{ 849{
800 struct capi_ctr *ctr; 850 struct capi_ctr *ctr;
851 u16 ret;
801 852
802 if (contr == 0) { 853 if (contr == 0) {
803 strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); 854 strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
804 return CAPI_NOERROR; 855 return CAPI_NOERROR;
805 } 856 }
857
858 mutex_lock(&capi_controller_lock);
859
806 ctr = get_capi_ctr_by_nr(contr); 860 ctr = get_capi_ctr_by_nr(contr);
807 if (!ctr || ctr->state != CAPI_CTR_RUNNING) 861 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
808 return CAPI_REGNOTINSTALLED; 862 strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN);
809 strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN); 863 ret = CAPI_NOERROR;
810 return CAPI_NOERROR; 864 } else
865 ret = CAPI_REGNOTINSTALLED;
866
867 mutex_unlock(&capi_controller_lock);
868 return ret;
811} 869}
812 870
813EXPORT_SYMBOL(capi20_get_manufacturer); 871EXPORT_SYMBOL(capi20_get_manufacturer);
@@ -825,17 +883,24 @@ EXPORT_SYMBOL(capi20_get_manufacturer);
825u16 capi20_get_version(u32 contr, struct capi_version *verp) 883u16 capi20_get_version(u32 contr, struct capi_version *verp)
826{ 884{
827 struct capi_ctr *ctr; 885 struct capi_ctr *ctr;
886 u16 ret;
828 887
829 if (contr == 0) { 888 if (contr == 0) {
830 *verp = driver_version; 889 *verp = driver_version;
831 return CAPI_NOERROR; 890 return CAPI_NOERROR;
832 } 891 }
892
893 mutex_lock(&capi_controller_lock);
894
833 ctr = get_capi_ctr_by_nr(contr); 895 ctr = get_capi_ctr_by_nr(contr);
834 if (!ctr || ctr->state != CAPI_CTR_RUNNING) 896 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
835 return CAPI_REGNOTINSTALLED; 897 memcpy(verp, &ctr->version, sizeof(capi_version));
898 ret = CAPI_NOERROR;
899 } else
900 ret = CAPI_REGNOTINSTALLED;
836 901
837 memcpy(verp, &ctr->version, sizeof(capi_version)); 902 mutex_unlock(&capi_controller_lock);
838 return CAPI_NOERROR; 903 return ret;
839} 904}
840 905
841EXPORT_SYMBOL(capi20_get_version); 906EXPORT_SYMBOL(capi20_get_version);
@@ -853,17 +918,24 @@ EXPORT_SYMBOL(capi20_get_version);
853u16 capi20_get_serial(u32 contr, u8 *serial) 918u16 capi20_get_serial(u32 contr, u8 *serial)
854{ 919{
855 struct capi_ctr *ctr; 920 struct capi_ctr *ctr;
921 u16 ret;
856 922
857 if (contr == 0) { 923 if (contr == 0) {
858 strlcpy(serial, driver_serial, CAPI_SERIAL_LEN); 924 strlcpy(serial, driver_serial, CAPI_SERIAL_LEN);
859 return CAPI_NOERROR; 925 return CAPI_NOERROR;
860 } 926 }
927
928 mutex_lock(&capi_controller_lock);
929
861 ctr = get_capi_ctr_by_nr(contr); 930 ctr = get_capi_ctr_by_nr(contr);
862 if (!ctr || ctr->state != CAPI_CTR_RUNNING) 931 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
863 return CAPI_REGNOTINSTALLED; 932 strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN);
933 ret = CAPI_NOERROR;
934 } else
935 ret = CAPI_REGNOTINSTALLED;
864 936
865 strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN); 937 mutex_unlock(&capi_controller_lock);
866 return CAPI_NOERROR; 938 return ret;
867} 939}
868 940
869EXPORT_SYMBOL(capi20_get_serial); 941EXPORT_SYMBOL(capi20_get_serial);
@@ -881,21 +953,64 @@ EXPORT_SYMBOL(capi20_get_serial);
881u16 capi20_get_profile(u32 contr, struct capi_profile *profp) 953u16 capi20_get_profile(u32 contr, struct capi_profile *profp)
882{ 954{
883 struct capi_ctr *ctr; 955 struct capi_ctr *ctr;
956 u16 ret;
884 957
885 if (contr == 0) { 958 if (contr == 0) {
886 profp->ncontroller = ncontrollers; 959 profp->ncontroller = ncontrollers;
887 return CAPI_NOERROR; 960 return CAPI_NOERROR;
888 } 961 }
962
963 mutex_lock(&capi_controller_lock);
964
889 ctr = get_capi_ctr_by_nr(contr); 965 ctr = get_capi_ctr_by_nr(contr);
890 if (!ctr || ctr->state != CAPI_CTR_RUNNING) 966 if (ctr && ctr->state == CAPI_CTR_RUNNING) {
891 return CAPI_REGNOTINSTALLED; 967 memcpy(profp, &ctr->profile, sizeof(struct capi_profile));
968 ret = CAPI_NOERROR;
969 } else
970 ret = CAPI_REGNOTINSTALLED;
892 971
893 memcpy(profp, &ctr->profile, sizeof(struct capi_profile)); 972 mutex_unlock(&capi_controller_lock);
894 return CAPI_NOERROR; 973 return ret;
895} 974}
896 975
897EXPORT_SYMBOL(capi20_get_profile); 976EXPORT_SYMBOL(capi20_get_profile);
898 977
978/* Must be called with capi_controller_lock held. */
979static int wait_on_ctr_state(struct capi_ctr *ctr, unsigned int state)
980{
981 DEFINE_WAIT(wait);
982 int retval = 0;
983
984 ctr = capi_ctr_get(ctr);
985 if (!ctr)
986 return -ESRCH;
987
988 for (;;) {
989 prepare_to_wait(&ctr->state_wait_queue, &wait,
990 TASK_INTERRUPTIBLE);
991
992 if (ctr->state == state)
993 break;
994 if (ctr->state == CAPI_CTR_DETACHED) {
995 retval = -ESRCH;
996 break;
997 }
998 if (signal_pending(current)) {
999 retval = -EINTR;
1000 break;
1001 }
1002
1003 mutex_unlock(&capi_controller_lock);
1004 schedule();
1005 mutex_lock(&capi_controller_lock);
1006 }
1007 finish_wait(&ctr->state_wait_queue, &wait);
1008
1009 capi_ctr_put(ctr);
1010
1011 return retval;
1012}
1013
899#ifdef AVMB1_COMPAT 1014#ifdef AVMB1_COMPAT
900static int old_capi_manufacturer(unsigned int cmd, void __user *data) 1015static int old_capi_manufacturer(unsigned int cmd, void __user *data)
901{ 1016{
@@ -973,27 +1088,30 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
973 sizeof(avmb1_loadandconfigdef))) 1088 sizeof(avmb1_loadandconfigdef)))
974 return -EFAULT; 1089 return -EFAULT;
975 } 1090 }
1091
1092 mutex_lock(&capi_controller_lock);
1093
976 ctr = get_capi_ctr_by_nr(ldef.contr); 1094 ctr = get_capi_ctr_by_nr(ldef.contr);
977 if (!ctr) 1095 if (!ctr) {
978 return -EINVAL; 1096 retval = -EINVAL;
979 ctr = capi_ctr_get(ctr); 1097 goto load_unlock_out;
980 if (!ctr) 1098 }
981 return -ESRCH; 1099
982 if (ctr->load_firmware == NULL) { 1100 if (ctr->load_firmware == NULL) {
983 printk(KERN_DEBUG "kcapi: load: no load function\n"); 1101 printk(KERN_DEBUG "kcapi: load: no load function\n");
984 capi_ctr_put(ctr); 1102 retval = -ESRCH;
985 return -ESRCH; 1103 goto load_unlock_out;
986 } 1104 }
987 1105
988 if (ldef.t4file.len <= 0) { 1106 if (ldef.t4file.len <= 0) {
989 printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); 1107 printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
990 capi_ctr_put(ctr); 1108 retval = -EINVAL;
991 return -EINVAL; 1109 goto load_unlock_out;
992 } 1110 }
993 if (ldef.t4file.data == NULL) { 1111 if (ldef.t4file.data == NULL) {
994 printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); 1112 printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n");
995 capi_ctr_put(ctr); 1113 retval = -EINVAL;
996 return -EINVAL; 1114 goto load_unlock_out;
997 } 1115 }
998 1116
999 ldata.firmware.user = 1; 1117 ldata.firmware.user = 1;
@@ -1005,52 +1123,47 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
1005 1123
1006 if (ctr->state != CAPI_CTR_DETECTED) { 1124 if (ctr->state != CAPI_CTR_DETECTED) {
1007 printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); 1125 printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr);
1008 capi_ctr_put(ctr); 1126 retval = -EBUSY;
1009 return -EBUSY; 1127 goto load_unlock_out;
1010 } 1128 }
1011 ctr->state = CAPI_CTR_LOADING; 1129 ctr->state = CAPI_CTR_LOADING;
1012 1130
1013 retval = ctr->load_firmware(ctr, &ldata); 1131 retval = ctr->load_firmware(ctr, &ldata);
1014
1015 if (retval) { 1132 if (retval) {
1016 ctr->state = CAPI_CTR_DETECTED; 1133 ctr->state = CAPI_CTR_DETECTED;
1017 capi_ctr_put(ctr); 1134 goto load_unlock_out;
1018 return retval;
1019 } 1135 }
1020 1136
1021 while (ctr->state != CAPI_CTR_RUNNING) { 1137 retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING);
1022
1023 msleep_interruptible(100); /* 0.1 sec */
1024 1138
1025 if (signal_pending(current)) { 1139load_unlock_out:
1026 capi_ctr_put(ctr); 1140 mutex_unlock(&capi_controller_lock);
1027 return -EINTR; 1141 return retval;
1028 }
1029 }
1030 capi_ctr_put(ctr);
1031 return 0;
1032 1142
1033 case AVMB1_RESETCARD: 1143 case AVMB1_RESETCARD:
1034 if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) 1144 if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef)))
1035 return -EFAULT; 1145 return -EFAULT;
1146
1147 retval = 0;
1148
1149 mutex_lock(&capi_controller_lock);
1150
1036 ctr = get_capi_ctr_by_nr(rdef.contr); 1151 ctr = get_capi_ctr_by_nr(rdef.contr);
1037 if (!ctr) 1152 if (!ctr) {
1038 return -ESRCH; 1153 retval = -ESRCH;
1154 goto reset_unlock_out;
1155 }
1039 1156
1040 if (ctr->state == CAPI_CTR_DETECTED) 1157 if (ctr->state == CAPI_CTR_DETECTED)
1041 return 0; 1158 goto reset_unlock_out;
1042 1159
1043 ctr->reset_ctr(ctr); 1160 ctr->reset_ctr(ctr);
1044 1161
1045 while (ctr->state > CAPI_CTR_DETECTED) { 1162 retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED);
1046
1047 msleep_interruptible(100); /* 0.1 sec */
1048
1049 if (signal_pending(current))
1050 return -EINTR;
1051 }
1052 return 0;
1053 1163
1164reset_unlock_out:
1165 mutex_unlock(&capi_controller_lock);
1166 return retval;
1054 } 1167 }
1055 return -EINVAL; 1168 return -EINVAL;
1056} 1169}
@@ -1068,6 +1181,7 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data)
1068int capi20_manufacturer(unsigned int cmd, void __user *data) 1181int capi20_manufacturer(unsigned int cmd, void __user *data)
1069{ 1182{
1070 struct capi_ctr *ctr; 1183 struct capi_ctr *ctr;
1184 int retval;
1071 1185
1072 switch (cmd) { 1186 switch (cmd) {
1073#ifdef AVMB1_COMPAT 1187#ifdef AVMB1_COMPAT
@@ -1085,14 +1199,20 @@ int capi20_manufacturer(unsigned int cmd, void __user *data)
1085 if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef))) 1199 if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef)))
1086 return -EFAULT; 1200 return -EFAULT;
1087 1201
1202 mutex_lock(&capi_controller_lock);
1203
1088 ctr = get_capi_ctr_by_nr(fdef.contr); 1204 ctr = get_capi_ctr_by_nr(fdef.contr);
1089 if (!ctr) 1205 if (ctr) {
1090 return -ESRCH; 1206 ctr->traceflag = fdef.flag;
1207 printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n",
1208 ctr->cnr, ctr->traceflag);
1209 retval = 0;
1210 } else
1211 retval = -ESRCH;
1212
1213 mutex_unlock(&capi_controller_lock);
1091 1214
1092 ctr->traceflag = fdef.flag; 1215 return retval;
1093 printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n",
1094 ctr->cnr, ctr->traceflag);
1095 return 0;
1096 } 1216 }
1097 case KCAPI_CMD_ADDCARD: 1217 case KCAPI_CMD_ADDCARD:
1098 { 1218 {
@@ -1100,7 +1220,6 @@ int capi20_manufacturer(unsigned int cmd, void __user *data)
1100 struct capi_driver *driver = NULL; 1220 struct capi_driver *driver = NULL;
1101 capicardparams cparams; 1221 capicardparams cparams;
1102 kcapi_carddef cdef; 1222 kcapi_carddef cdef;
1103 int retval;
1104 1223
1105 if ((retval = copy_from_user(&cdef, data, sizeof(cdef)))) 1224 if ((retval = copy_from_user(&cdef, data, sizeof(cdef))))
1106 return retval; 1225 return retval;
diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h
index 07c58500fe48..f4620b38ec51 100644
--- a/drivers/isdn/capi/kcapi.h
+++ b/drivers/isdn/capi/kcapi.h
@@ -24,6 +24,7 @@ printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \
24#endif 24#endif
25 25
26enum { 26enum {
27 CAPI_CTR_DETACHED = 0,
27 CAPI_CTR_DETECTED = 1, 28 CAPI_CTR_DETECTED = 1,
28 CAPI_CTR_LOADING = 2, 29 CAPI_CTR_LOADING = 2,
29 CAPI_CTR_RUNNING = 3, 30 CAPI_CTR_RUNNING = 3,
@@ -32,8 +33,10 @@ enum {
32extern struct list_head capi_drivers; 33extern struct list_head capi_drivers;
33extern struct mutex capi_drivers_lock; 34extern struct mutex capi_drivers_lock;
34 35
35extern struct capi20_appl *capi_applications[CAPI_MAXAPPL];
36extern struct capi_ctr *capi_controller[CAPI_MAXCONTR]; 36extern struct capi_ctr *capi_controller[CAPI_MAXCONTR];
37extern struct mutex capi_controller_lock;
38
39extern struct capi20_appl *capi_applications[CAPI_MAXAPPL];
37 40
38#ifdef CONFIG_PROC_FS 41#ifdef CONFIG_PROC_FS
39 42
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index 71b07610ff31..3e6e17a24389 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -35,7 +35,10 @@ static char *state2str(unsigned short state)
35// --------------------------------------------------------------------------- 35// ---------------------------------------------------------------------------
36 36
37static void *controller_start(struct seq_file *seq, loff_t *pos) 37static void *controller_start(struct seq_file *seq, loff_t *pos)
38 __acquires(capi_controller_lock)
38{ 39{
40 mutex_lock(&capi_controller_lock);
41
39 if (*pos < CAPI_MAXCONTR) 42 if (*pos < CAPI_MAXCONTR)
40 return &capi_controller[*pos]; 43 return &capi_controller[*pos];
41 44
@@ -52,7 +55,9 @@ static void *controller_next(struct seq_file *seq, void *v, loff_t *pos)
52} 55}
53 56
54static void controller_stop(struct seq_file *seq, void *v) 57static void controller_stop(struct seq_file *seq, void *v)
58 __releases(capi_controller_lock)
55{ 59{
60 mutex_unlock(&capi_controller_lock);
56} 61}
57 62
58static int controller_show(struct seq_file *seq, void *v) 63static int controller_show(struct seq_file *seq, void *v)
diff --git a/include/linux/isdn/capilli.h b/include/linux/isdn/capilli.h
index 856f38eddd78..11b57c485854 100644
--- a/include/linux/isdn/capilli.h
+++ b/include/linux/isdn/capilli.h
@@ -66,9 +66,10 @@ struct capi_ctr {
66 unsigned long nsentdatapkt; 66 unsigned long nsentdatapkt;
67 67
68 int cnr; /* controller number */ 68 int cnr; /* controller number */
69 volatile unsigned short state; /* controller state */ 69 unsigned short state; /* controller state */
70 volatile int blocked; /* output blocked */ 70 int blocked; /* output blocked */
71 int traceflag; /* capi trace */ 71 int traceflag; /* capi trace */
72 wait_queue_head_t state_wait_queue;
72 73
73 struct proc_dir_entry *procent; 74 struct proc_dir_entry *procent;
74 char procfn[128]; 75 char procfn[128];