aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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];