diff options
author | Andy Wingo <wingo@pobox.com> | 2005-10-20 00:23:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-20 02:04:30 -0400 |
commit | 4a9949d7ac9e2bc51939f27b184be6e1bd99004e (patch) | |
tree | 85f67b527d3ff5a550ada8e08600f1400ddc5960 /drivers/ieee1394 | |
parent | c367c21c93ccdaf7e1e124891633d89f9ae77f54 (diff) |
[PATCH] raw1394: fix locking in the presence of SMP and interrupts
Changes all spinlocks that can be held during an irq handler to disable
interrupts while the lock is held. Changes spin_[un]lock_irq to use the
irqsave/irqrestore variants for robustness and readability.
In raw1394.c:handle_iso_listen(), don't grab host_info_lock at all -- we're
not accessing host_info_list or host_count, and holding this lock while
trying to tasklet_kill the iso tasklet this can cause an ABBA deadlock if
ohci:dma_rcv_tasklet is running and tries to grab host_info_lock in
raw1394.c:receive_iso. Test program attached reliably deadlocks all SMP
machines I have been able to test without this patch.
Signed-off-by: Andy Wingo <wingo@pobox.com>
Acked-by: Ben Collins <bcollins@ubuntu.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/ieee1394')
-rw-r--r-- | drivers/ieee1394/ohci1394.c | 6 | ||||
-rw-r--r-- | drivers/ieee1394/raw1394.c | 100 |
2 files changed, 57 insertions, 49 deletions
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 6a6acbd80af4..4cf9b8f3e336 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c | |||
@@ -2283,8 +2283,9 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci, | |||
2283 | { | 2283 | { |
2284 | struct ohci1394_iso_tasklet *t; | 2284 | struct ohci1394_iso_tasklet *t; |
2285 | unsigned long mask; | 2285 | unsigned long mask; |
2286 | unsigned long flags; | ||
2286 | 2287 | ||
2287 | spin_lock(&ohci->iso_tasklet_list_lock); | 2288 | spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags); |
2288 | 2289 | ||
2289 | list_for_each_entry(t, &ohci->iso_tasklet_list, link) { | 2290 | list_for_each_entry(t, &ohci->iso_tasklet_list, link) { |
2290 | mask = 1 << t->context; | 2291 | mask = 1 << t->context; |
@@ -2295,8 +2296,7 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci, | |||
2295 | tasklet_schedule(&t->tasklet); | 2296 | tasklet_schedule(&t->tasklet); |
2296 | } | 2297 | } |
2297 | 2298 | ||
2298 | spin_unlock(&ohci->iso_tasklet_list_lock); | 2299 | spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags); |
2299 | |||
2300 | } | 2300 | } |
2301 | 2301 | ||
2302 | static irqreturn_t ohci_irq_handler(int irq, void *dev_id, | 2302 | static irqreturn_t ohci_irq_handler(int irq, void *dev_id, |
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 315f5ca8bedb..0470f77a9cd1 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c | |||
@@ -412,6 +412,7 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction, | |||
412 | static ssize_t raw1394_read(struct file *file, char __user * buffer, | 412 | static ssize_t raw1394_read(struct file *file, char __user * buffer, |
413 | size_t count, loff_t * offset_is_ignored) | 413 | size_t count, loff_t * offset_is_ignored) |
414 | { | 414 | { |
415 | unsigned long flags; | ||
415 | struct file_info *fi = (struct file_info *)file->private_data; | 416 | struct file_info *fi = (struct file_info *)file->private_data; |
416 | struct list_head *lh; | 417 | struct list_head *lh; |
417 | struct pending_request *req; | 418 | struct pending_request *req; |
@@ -435,10 +436,10 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer, | |||
435 | } | 436 | } |
436 | } | 437 | } |
437 | 438 | ||
438 | spin_lock_irq(&fi->reqlists_lock); | 439 | spin_lock_irqsave(&fi->reqlists_lock, flags); |
439 | lh = fi->req_complete.next; | 440 | lh = fi->req_complete.next; |
440 | list_del(lh); | 441 | list_del(lh); |
441 | spin_unlock_irq(&fi->reqlists_lock); | 442 | spin_unlock_irqrestore(&fi->reqlists_lock, flags); |
442 | 443 | ||
443 | req = list_entry(lh, struct pending_request, list); | 444 | req = list_entry(lh, struct pending_request, list); |
444 | 445 | ||
@@ -486,6 +487,7 @@ static int state_opened(struct file_info *fi, struct pending_request *req) | |||
486 | 487 | ||
487 | static int state_initialized(struct file_info *fi, struct pending_request *req) | 488 | static int state_initialized(struct file_info *fi, struct pending_request *req) |
488 | { | 489 | { |
490 | unsigned long flags; | ||
489 | struct host_info *hi; | 491 | struct host_info *hi; |
490 | struct raw1394_khost_list *khl; | 492 | struct raw1394_khost_list *khl; |
491 | 493 | ||
@@ -499,7 +501,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) | |||
499 | 501 | ||
500 | switch (req->req.type) { | 502 | switch (req->req.type) { |
501 | case RAW1394_REQ_LIST_CARDS: | 503 | case RAW1394_REQ_LIST_CARDS: |
502 | spin_lock_irq(&host_info_lock); | 504 | spin_lock_irqsave(&host_info_lock, flags); |
503 | khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count, | 505 | khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count, |
504 | SLAB_ATOMIC); | 506 | SLAB_ATOMIC); |
505 | 507 | ||
@@ -513,7 +515,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) | |||
513 | khl++; | 515 | khl++; |
514 | } | 516 | } |
515 | } | 517 | } |
516 | spin_unlock_irq(&host_info_lock); | 518 | spin_unlock_irqrestore(&host_info_lock, flags); |
517 | 519 | ||
518 | if (khl != NULL) { | 520 | if (khl != NULL) { |
519 | req->req.error = RAW1394_ERROR_NONE; | 521 | req->req.error = RAW1394_ERROR_NONE; |
@@ -528,7 +530,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) | |||
528 | break; | 530 | break; |
529 | 531 | ||
530 | case RAW1394_REQ_SET_CARD: | 532 | case RAW1394_REQ_SET_CARD: |
531 | spin_lock_irq(&host_info_lock); | 533 | spin_lock_irqsave(&host_info_lock, flags); |
532 | if (req->req.misc < host_count) { | 534 | if (req->req.misc < host_count) { |
533 | list_for_each_entry(hi, &host_info_list, list) { | 535 | list_for_each_entry(hi, &host_info_list, list) { |
534 | if (!req->req.misc--) | 536 | if (!req->req.misc--) |
@@ -550,7 +552,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) | |||
550 | } else { | 552 | } else { |
551 | req->req.error = RAW1394_ERROR_INVALID_ARG; | 553 | req->req.error = RAW1394_ERROR_INVALID_ARG; |
552 | } | 554 | } |
553 | spin_unlock_irq(&host_info_lock); | 555 | spin_unlock_irqrestore(&host_info_lock, flags); |
554 | 556 | ||
555 | req->req.length = 0; | 557 | req->req.length = 0; |
556 | break; | 558 | break; |
@@ -569,7 +571,6 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req) | |||
569 | { | 571 | { |
570 | int channel = req->req.misc; | 572 | int channel = req->req.misc; |
571 | 573 | ||
572 | spin_lock_irq(&host_info_lock); | ||
573 | if ((channel > 63) || (channel < -64)) { | 574 | if ((channel > 63) || (channel < -64)) { |
574 | req->req.error = RAW1394_ERROR_INVALID_ARG; | 575 | req->req.error = RAW1394_ERROR_INVALID_ARG; |
575 | } else if (channel >= 0) { | 576 | } else if (channel >= 0) { |
@@ -601,7 +602,6 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req) | |||
601 | 602 | ||
602 | req->req.length = 0; | 603 | req->req.length = 0; |
603 | queue_complete_req(req); | 604 | queue_complete_req(req); |
604 | spin_unlock_irq(&host_info_lock); | ||
605 | } | 605 | } |
606 | 606 | ||
607 | static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) | 607 | static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) |
@@ -627,6 +627,7 @@ static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) | |||
627 | static int handle_async_request(struct file_info *fi, | 627 | static int handle_async_request(struct file_info *fi, |
628 | struct pending_request *req, int node) | 628 | struct pending_request *req, int node) |
629 | { | 629 | { |
630 | unsigned long flags; | ||
630 | struct hpsb_packet *packet = NULL; | 631 | struct hpsb_packet *packet = NULL; |
631 | u64 addr = req->req.address & 0xffffffffffffULL; | 632 | u64 addr = req->req.address & 0xffffffffffffULL; |
632 | 633 | ||
@@ -761,9 +762,9 @@ static int handle_async_request(struct file_info *fi, | |||
761 | hpsb_set_packet_complete_task(packet, | 762 | hpsb_set_packet_complete_task(packet, |
762 | (void (*)(void *))queue_complete_cb, req); | 763 | (void (*)(void *))queue_complete_cb, req); |
763 | 764 | ||
764 | spin_lock_irq(&fi->reqlists_lock); | 765 | spin_lock_irqsave(&fi->reqlists_lock, flags); |
765 | list_add_tail(&req->list, &fi->req_pending); | 766 | list_add_tail(&req->list, &fi->req_pending); |
766 | spin_unlock_irq(&fi->reqlists_lock); | 767 | spin_unlock_irqrestore(&fi->reqlists_lock, flags); |
767 | 768 | ||
768 | packet->generation = req->req.generation; | 769 | packet->generation = req->req.generation; |
769 | 770 | ||
@@ -779,6 +780,7 @@ static int handle_async_request(struct file_info *fi, | |||
779 | static int handle_iso_send(struct file_info *fi, struct pending_request *req, | 780 | static int handle_iso_send(struct file_info *fi, struct pending_request *req, |
780 | int channel) | 781 | int channel) |
781 | { | 782 | { |
783 | unsigned long flags; | ||
782 | struct hpsb_packet *packet; | 784 | struct hpsb_packet *packet; |
783 | 785 | ||
784 | packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f, | 786 | packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f, |
@@ -804,9 +806,9 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req, | |||
804 | (void (*)(void *))queue_complete_req, | 806 | (void (*)(void *))queue_complete_req, |
805 | req); | 807 | req); |
806 | 808 | ||
807 | spin_lock_irq(&fi->reqlists_lock); | 809 | spin_lock_irqsave(&fi->reqlists_lock, flags); |
808 | list_add_tail(&req->list, &fi->req_pending); | 810 | list_add_tail(&req->list, &fi->req_pending); |
809 | spin_unlock_irq(&fi->reqlists_lock); | 811 | spin_unlock_irqrestore(&fi->reqlists_lock, flags); |
810 | 812 | ||
811 | /* Update the generation of the packet just before sending. */ | 813 | /* Update the generation of the packet just before sending. */ |
812 | packet->generation = req->req.generation; | 814 | packet->generation = req->req.generation; |
@@ -821,6 +823,7 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req, | |||
821 | 823 | ||
822 | static int handle_async_send(struct file_info *fi, struct pending_request *req) | 824 | static int handle_async_send(struct file_info *fi, struct pending_request *req) |
823 | { | 825 | { |
826 | unsigned long flags; | ||
824 | struct hpsb_packet *packet; | 827 | struct hpsb_packet *packet; |
825 | int header_length = req->req.misc & 0xffff; | 828 | int header_length = req->req.misc & 0xffff; |
826 | int expect_response = req->req.misc >> 16; | 829 | int expect_response = req->req.misc >> 16; |
@@ -867,9 +870,9 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req) | |||
867 | hpsb_set_packet_complete_task(packet, | 870 | hpsb_set_packet_complete_task(packet, |
868 | (void (*)(void *))queue_complete_cb, req); | 871 | (void (*)(void *))queue_complete_cb, req); |
869 | 872 | ||
870 | spin_lock_irq(&fi->reqlists_lock); | 873 | spin_lock_irqsave(&fi->reqlists_lock, flags); |
871 | list_add_tail(&req->list, &fi->req_pending); | 874 | list_add_tail(&req->list, &fi->req_pending); |
872 | spin_unlock_irq(&fi->reqlists_lock); | 875 | spin_unlock_irqrestore(&fi->reqlists_lock, flags); |
873 | 876 | ||
874 | /* Update the generation of the packet just before sending. */ | 877 | /* Update the generation of the packet just before sending. */ |
875 | packet->generation = req->req.generation; | 878 | packet->generation = req->req.generation; |
@@ -885,6 +888,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req) | |||
885 | static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, | 888 | static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, |
886 | u64 addr, size_t length, u16 flags) | 889 | u64 addr, size_t length, u16 flags) |
887 | { | 890 | { |
891 | unsigned long irqflags; | ||
888 | struct pending_request *req; | 892 | struct pending_request *req; |
889 | struct host_info *hi; | 893 | struct host_info *hi; |
890 | struct file_info *fi = NULL; | 894 | struct file_info *fi = NULL; |
@@ -899,7 +903,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, | |||
899 | "addr: %4.4x %8.8x length: %Zu", nodeid, | 903 | "addr: %4.4x %8.8x length: %Zu", nodeid, |
900 | (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), | 904 | (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), |
901 | length); | 905 | length); |
902 | spin_lock(&host_info_lock); | 906 | spin_lock_irqsave(&host_info_lock, irqflags); |
903 | hi = find_host_info(host); /* search address-entry */ | 907 | hi = find_host_info(host); /* search address-entry */ |
904 | if (hi != NULL) { | 908 | if (hi != NULL) { |
905 | list_for_each_entry(fi, &hi->file_info_list, list) { | 909 | list_for_each_entry(fi, &hi->file_info_list, list) { |
@@ -924,7 +928,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, | |||
924 | if (!found) { | 928 | if (!found) { |
925 | printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found" | 929 | printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found" |
926 | " -> rcode_address_error\n"); | 930 | " -> rcode_address_error\n"); |
927 | spin_unlock(&host_info_lock); | 931 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
928 | return (RCODE_ADDRESS_ERROR); | 932 | return (RCODE_ADDRESS_ERROR); |
929 | } else { | 933 | } else { |
930 | DBGMSG("arm_read addr_entry FOUND"); | 934 | DBGMSG("arm_read addr_entry FOUND"); |
@@ -954,7 +958,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, | |||
954 | req = __alloc_pending_request(SLAB_ATOMIC); | 958 | req = __alloc_pending_request(SLAB_ATOMIC); |
955 | if (!req) { | 959 | if (!req) { |
956 | DBGMSG("arm_read -> rcode_conflict_error"); | 960 | DBGMSG("arm_read -> rcode_conflict_error"); |
957 | spin_unlock(&host_info_lock); | 961 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
958 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. | 962 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. |
959 | The request may be retried */ | 963 | The request may be retried */ |
960 | } | 964 | } |
@@ -974,7 +978,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, | |||
974 | if (!(req->data)) { | 978 | if (!(req->data)) { |
975 | free_pending_request(req); | 979 | free_pending_request(req); |
976 | DBGMSG("arm_read -> rcode_conflict_error"); | 980 | DBGMSG("arm_read -> rcode_conflict_error"); |
977 | spin_unlock(&host_info_lock); | 981 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
978 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. | 982 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. |
979 | The request may be retried */ | 983 | The request may be retried */ |
980 | } | 984 | } |
@@ -1031,13 +1035,14 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, | |||
1031 | sizeof(struct arm_request)); | 1035 | sizeof(struct arm_request)); |
1032 | queue_complete_req(req); | 1036 | queue_complete_req(req); |
1033 | } | 1037 | } |
1034 | spin_unlock(&host_info_lock); | 1038 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1035 | return (rcode); | 1039 | return (rcode); |
1036 | } | 1040 | } |
1037 | 1041 | ||
1038 | static int arm_write(struct hpsb_host *host, int nodeid, int destid, | 1042 | static int arm_write(struct hpsb_host *host, int nodeid, int destid, |
1039 | quadlet_t * data, u64 addr, size_t length, u16 flags) | 1043 | quadlet_t * data, u64 addr, size_t length, u16 flags) |
1040 | { | 1044 | { |
1045 | unsigned long irqflags; | ||
1041 | struct pending_request *req; | 1046 | struct pending_request *req; |
1042 | struct host_info *hi; | 1047 | struct host_info *hi; |
1043 | struct file_info *fi = NULL; | 1048 | struct file_info *fi = NULL; |
@@ -1052,7 +1057,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, | |||
1052 | "addr: %4.4x %8.8x length: %Zu", nodeid, | 1057 | "addr: %4.4x %8.8x length: %Zu", nodeid, |
1053 | (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), | 1058 | (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), |
1054 | length); | 1059 | length); |
1055 | spin_lock(&host_info_lock); | 1060 | spin_lock_irqsave(&host_info_lock, irqflags); |
1056 | hi = find_host_info(host); /* search address-entry */ | 1061 | hi = find_host_info(host); /* search address-entry */ |
1057 | if (hi != NULL) { | 1062 | if (hi != NULL) { |
1058 | list_for_each_entry(fi, &hi->file_info_list, list) { | 1063 | list_for_each_entry(fi, &hi->file_info_list, list) { |
@@ -1077,7 +1082,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, | |||
1077 | if (!found) { | 1082 | if (!found) { |
1078 | printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found" | 1083 | printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found" |
1079 | " -> rcode_address_error\n"); | 1084 | " -> rcode_address_error\n"); |
1080 | spin_unlock(&host_info_lock); | 1085 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1081 | return (RCODE_ADDRESS_ERROR); | 1086 | return (RCODE_ADDRESS_ERROR); |
1082 | } else { | 1087 | } else { |
1083 | DBGMSG("arm_write addr_entry FOUND"); | 1088 | DBGMSG("arm_write addr_entry FOUND"); |
@@ -1106,7 +1111,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, | |||
1106 | req = __alloc_pending_request(SLAB_ATOMIC); | 1111 | req = __alloc_pending_request(SLAB_ATOMIC); |
1107 | if (!req) { | 1112 | if (!req) { |
1108 | DBGMSG("arm_write -> rcode_conflict_error"); | 1113 | DBGMSG("arm_write -> rcode_conflict_error"); |
1109 | spin_unlock(&host_info_lock); | 1114 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1110 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. | 1115 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. |
1111 | The request my be retried */ | 1116 | The request my be retried */ |
1112 | } | 1117 | } |
@@ -1118,7 +1123,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, | |||
1118 | if (!(req->data)) { | 1123 | if (!(req->data)) { |
1119 | free_pending_request(req); | 1124 | free_pending_request(req); |
1120 | DBGMSG("arm_write -> rcode_conflict_error"); | 1125 | DBGMSG("arm_write -> rcode_conflict_error"); |
1121 | spin_unlock(&host_info_lock); | 1126 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1122 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. | 1127 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. |
1123 | The request may be retried */ | 1128 | The request may be retried */ |
1124 | } | 1129 | } |
@@ -1165,7 +1170,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, | |||
1165 | sizeof(struct arm_request)); | 1170 | sizeof(struct arm_request)); |
1166 | queue_complete_req(req); | 1171 | queue_complete_req(req); |
1167 | } | 1172 | } |
1168 | spin_unlock(&host_info_lock); | 1173 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1169 | return (rcode); | 1174 | return (rcode); |
1170 | } | 1175 | } |
1171 | 1176 | ||
@@ -1173,6 +1178,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, | |||
1173 | u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, | 1178 | u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, |
1174 | u16 flags) | 1179 | u16 flags) |
1175 | { | 1180 | { |
1181 | unsigned long irqflags; | ||
1176 | struct pending_request *req; | 1182 | struct pending_request *req; |
1177 | struct host_info *hi; | 1183 | struct host_info *hi; |
1178 | struct file_info *fi = NULL; | 1184 | struct file_info *fi = NULL; |
@@ -1198,7 +1204,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, | |||
1198 | (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF, | 1204 | (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF, |
1199 | be32_to_cpu(data), be32_to_cpu(arg)); | 1205 | be32_to_cpu(data), be32_to_cpu(arg)); |
1200 | } | 1206 | } |
1201 | spin_lock(&host_info_lock); | 1207 | spin_lock_irqsave(&host_info_lock, irqflags); |
1202 | hi = find_host_info(host); /* search address-entry */ | 1208 | hi = find_host_info(host); /* search address-entry */ |
1203 | if (hi != NULL) { | 1209 | if (hi != NULL) { |
1204 | list_for_each_entry(fi, &hi->file_info_list, list) { | 1210 | list_for_each_entry(fi, &hi->file_info_list, list) { |
@@ -1224,7 +1230,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, | |||
1224 | if (!found) { | 1230 | if (!found) { |
1225 | printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found" | 1231 | printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found" |
1226 | " -> rcode_address_error\n"); | 1232 | " -> rcode_address_error\n"); |
1227 | spin_unlock(&host_info_lock); | 1233 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1228 | return (RCODE_ADDRESS_ERROR); | 1234 | return (RCODE_ADDRESS_ERROR); |
1229 | } else { | 1235 | } else { |
1230 | DBGMSG("arm_lock addr_entry FOUND"); | 1236 | DBGMSG("arm_lock addr_entry FOUND"); |
@@ -1307,7 +1313,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, | |||
1307 | req = __alloc_pending_request(SLAB_ATOMIC); | 1313 | req = __alloc_pending_request(SLAB_ATOMIC); |
1308 | if (!req) { | 1314 | if (!req) { |
1309 | DBGMSG("arm_lock -> rcode_conflict_error"); | 1315 | DBGMSG("arm_lock -> rcode_conflict_error"); |
1310 | spin_unlock(&host_info_lock); | 1316 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1311 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. | 1317 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. |
1312 | The request may be retried */ | 1318 | The request may be retried */ |
1313 | } | 1319 | } |
@@ -1316,7 +1322,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, | |||
1316 | if (!(req->data)) { | 1322 | if (!(req->data)) { |
1317 | free_pending_request(req); | 1323 | free_pending_request(req); |
1318 | DBGMSG("arm_lock -> rcode_conflict_error"); | 1324 | DBGMSG("arm_lock -> rcode_conflict_error"); |
1319 | spin_unlock(&host_info_lock); | 1325 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1320 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. | 1326 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. |
1321 | The request may be retried */ | 1327 | The request may be retried */ |
1322 | } | 1328 | } |
@@ -1382,7 +1388,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, | |||
1382 | sizeof(struct arm_response) + 2 * sizeof(*store)); | 1388 | sizeof(struct arm_response) + 2 * sizeof(*store)); |
1383 | queue_complete_req(req); | 1389 | queue_complete_req(req); |
1384 | } | 1390 | } |
1385 | spin_unlock(&host_info_lock); | 1391 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1386 | return (rcode); | 1392 | return (rcode); |
1387 | } | 1393 | } |
1388 | 1394 | ||
@@ -1390,6 +1396,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, | |||
1390 | u64 addr, octlet_t data, octlet_t arg, int ext_tcode, | 1396 | u64 addr, octlet_t data, octlet_t arg, int ext_tcode, |
1391 | u16 flags) | 1397 | u16 flags) |
1392 | { | 1398 | { |
1399 | unsigned long irqflags; | ||
1393 | struct pending_request *req; | 1400 | struct pending_request *req; |
1394 | struct host_info *hi; | 1401 | struct host_info *hi; |
1395 | struct file_info *fi = NULL; | 1402 | struct file_info *fi = NULL; |
@@ -1422,7 +1429,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, | |||
1422 | (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF), | 1429 | (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF), |
1423 | (u32) (be64_to_cpu(arg) & 0xFFFFFFFF)); | 1430 | (u32) (be64_to_cpu(arg) & 0xFFFFFFFF)); |
1424 | } | 1431 | } |
1425 | spin_lock(&host_info_lock); | 1432 | spin_lock_irqsave(&host_info_lock, irqflags); |
1426 | hi = find_host_info(host); /* search addressentry in file_info's for host */ | 1433 | hi = find_host_info(host); /* search addressentry in file_info's for host */ |
1427 | if (hi != NULL) { | 1434 | if (hi != NULL) { |
1428 | list_for_each_entry(fi, &hi->file_info_list, list) { | 1435 | list_for_each_entry(fi, &hi->file_info_list, list) { |
@@ -1449,7 +1456,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, | |||
1449 | printk(KERN_ERR | 1456 | printk(KERN_ERR |
1450 | "raw1394: arm_lock64 FAILED addr_entry not found" | 1457 | "raw1394: arm_lock64 FAILED addr_entry not found" |
1451 | " -> rcode_address_error\n"); | 1458 | " -> rcode_address_error\n"); |
1452 | spin_unlock(&host_info_lock); | 1459 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1453 | return (RCODE_ADDRESS_ERROR); | 1460 | return (RCODE_ADDRESS_ERROR); |
1454 | } else { | 1461 | } else { |
1455 | DBGMSG("arm_lock64 addr_entry FOUND"); | 1462 | DBGMSG("arm_lock64 addr_entry FOUND"); |
@@ -1533,7 +1540,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, | |||
1533 | DBGMSG("arm_lock64 -> entering notification-section"); | 1540 | DBGMSG("arm_lock64 -> entering notification-section"); |
1534 | req = __alloc_pending_request(SLAB_ATOMIC); | 1541 | req = __alloc_pending_request(SLAB_ATOMIC); |
1535 | if (!req) { | 1542 | if (!req) { |
1536 | spin_unlock(&host_info_lock); | 1543 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1537 | DBGMSG("arm_lock64 -> rcode_conflict_error"); | 1544 | DBGMSG("arm_lock64 -> rcode_conflict_error"); |
1538 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. | 1545 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. |
1539 | The request may be retried */ | 1546 | The request may be retried */ |
@@ -1542,7 +1549,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, | |||
1542 | req->data = kmalloc(size, SLAB_ATOMIC); | 1549 | req->data = kmalloc(size, SLAB_ATOMIC); |
1543 | if (!(req->data)) { | 1550 | if (!(req->data)) { |
1544 | free_pending_request(req); | 1551 | free_pending_request(req); |
1545 | spin_unlock(&host_info_lock); | 1552 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1546 | DBGMSG("arm_lock64 -> rcode_conflict_error"); | 1553 | DBGMSG("arm_lock64 -> rcode_conflict_error"); |
1547 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. | 1554 | return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. |
1548 | The request may be retried */ | 1555 | The request may be retried */ |
@@ -1609,7 +1616,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, | |||
1609 | sizeof(struct arm_response) + 2 * sizeof(*store)); | 1616 | sizeof(struct arm_response) + 2 * sizeof(*store)); |
1610 | queue_complete_req(req); | 1617 | queue_complete_req(req); |
1611 | } | 1618 | } |
1612 | spin_unlock(&host_info_lock); | 1619 | spin_unlock_irqrestore(&host_info_lock, irqflags); |
1613 | return (rcode); | 1620 | return (rcode); |
1614 | } | 1621 | } |
1615 | 1622 | ||
@@ -1980,6 +1987,7 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req) | |||
1980 | struct hpsb_packet *packet = NULL; | 1987 | struct hpsb_packet *packet = NULL; |
1981 | int retval = 0; | 1988 | int retval = 0; |
1982 | quadlet_t data; | 1989 | quadlet_t data; |
1990 | unsigned long flags; | ||
1983 | 1991 | ||
1984 | data = be32_to_cpu((u32) req->req.sendb); | 1992 | data = be32_to_cpu((u32) req->req.sendb); |
1985 | DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data); | 1993 | DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data); |
@@ -1990,9 +1998,9 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req) | |||
1990 | req->packet = packet; | 1998 | req->packet = packet; |
1991 | hpsb_set_packet_complete_task(packet, | 1999 | hpsb_set_packet_complete_task(packet, |
1992 | (void (*)(void *))queue_complete_cb, req); | 2000 | (void (*)(void *))queue_complete_cb, req); |
1993 | spin_lock_irq(&fi->reqlists_lock); | 2001 | spin_lock_irqsave(&fi->reqlists_lock, flags); |
1994 | list_add_tail(&req->list, &fi->req_pending); | 2002 | list_add_tail(&req->list, &fi->req_pending); |
1995 | spin_unlock_irq(&fi->reqlists_lock); | 2003 | spin_unlock_irqrestore(&fi->reqlists_lock, flags); |
1996 | packet->generation = req->req.generation; | 2004 | packet->generation = req->req.generation; |
1997 | retval = hpsb_send_packet(packet); | 2005 | retval = hpsb_send_packet(packet); |
1998 | DBGMSG("write_phypacket send_packet called => retval: %d ", retval); | 2006 | DBGMSG("write_phypacket send_packet called => retval: %d ", retval); |
@@ -2659,14 +2667,15 @@ static unsigned int raw1394_poll(struct file *file, poll_table * pt) | |||
2659 | { | 2667 | { |
2660 | struct file_info *fi = file->private_data; | 2668 | struct file_info *fi = file->private_data; |
2661 | unsigned int mask = POLLOUT | POLLWRNORM; | 2669 | unsigned int mask = POLLOUT | POLLWRNORM; |
2670 | unsigned long flags; | ||
2662 | 2671 | ||
2663 | poll_wait(file, &fi->poll_wait_complete, pt); | 2672 | poll_wait(file, &fi->poll_wait_complete, pt); |
2664 | 2673 | ||
2665 | spin_lock_irq(&fi->reqlists_lock); | 2674 | spin_lock_irqsave(&fi->reqlists_lock, flags); |
2666 | if (!list_empty(&fi->req_complete)) { | 2675 | if (!list_empty(&fi->req_complete)) { |
2667 | mask |= POLLIN | POLLRDNORM; | 2676 | mask |= POLLIN | POLLRDNORM; |
2668 | } | 2677 | } |
2669 | spin_unlock_irq(&fi->reqlists_lock); | 2678 | spin_unlock_irqrestore(&fi->reqlists_lock, flags); |
2670 | 2679 | ||
2671 | return mask; | 2680 | return mask; |
2672 | } | 2681 | } |
@@ -2710,6 +2719,7 @@ static int raw1394_release(struct inode *inode, struct file *file) | |||
2710 | struct arm_addr *arm_addr = NULL; | 2719 | struct arm_addr *arm_addr = NULL; |
2711 | int another_host; | 2720 | int another_host; |
2712 | int csr_mod = 0; | 2721 | int csr_mod = 0; |
2722 | unsigned long flags; | ||
2713 | 2723 | ||
2714 | if (fi->iso_state != RAW1394_ISO_INACTIVE) | 2724 | if (fi->iso_state != RAW1394_ISO_INACTIVE) |
2715 | raw1394_iso_shutdown(fi); | 2725 | raw1394_iso_shutdown(fi); |
@@ -2720,13 +2730,11 @@ static int raw1394_release(struct inode *inode, struct file *file) | |||
2720 | } | 2730 | } |
2721 | } | 2731 | } |
2722 | 2732 | ||
2723 | spin_lock_irq(&host_info_lock); | 2733 | spin_lock_irqsave(&host_info_lock, flags); |
2724 | fi->listen_channels = 0; | 2734 | fi->listen_channels = 0; |
2725 | spin_unlock_irq(&host_info_lock); | ||
2726 | 2735 | ||
2727 | fail = 0; | 2736 | fail = 0; |
2728 | /* set address-entries invalid */ | 2737 | /* set address-entries invalid */ |
2729 | spin_lock_irq(&host_info_lock); | ||
2730 | 2738 | ||
2731 | while (!list_empty(&fi->addr_list)) { | 2739 | while (!list_empty(&fi->addr_list)) { |
2732 | another_host = 0; | 2740 | another_host = 0; |
@@ -2777,14 +2785,14 @@ static int raw1394_release(struct inode *inode, struct file *file) | |||
2777 | vfree(addr->addr_space_buffer); | 2785 | vfree(addr->addr_space_buffer); |
2778 | kfree(addr); | 2786 | kfree(addr); |
2779 | } /* while */ | 2787 | } /* while */ |
2780 | spin_unlock_irq(&host_info_lock); | 2788 | spin_unlock_irqrestore(&host_info_lock, flags); |
2781 | if (fail > 0) { | 2789 | if (fail > 0) { |
2782 | printk(KERN_ERR "raw1394: during addr_list-release " | 2790 | printk(KERN_ERR "raw1394: during addr_list-release " |
2783 | "error(s) occurred \n"); | 2791 | "error(s) occurred \n"); |
2784 | } | 2792 | } |
2785 | 2793 | ||
2786 | while (!done) { | 2794 | while (!done) { |
2787 | spin_lock_irq(&fi->reqlists_lock); | 2795 | spin_lock_irqsave(&fi->reqlists_lock, flags); |
2788 | 2796 | ||
2789 | while (!list_empty(&fi->req_complete)) { | 2797 | while (!list_empty(&fi->req_complete)) { |
2790 | lh = fi->req_complete.next; | 2798 | lh = fi->req_complete.next; |
@@ -2798,7 +2806,7 @@ static int raw1394_release(struct inode *inode, struct file *file) | |||
2798 | if (list_empty(&fi->req_pending)) | 2806 | if (list_empty(&fi->req_pending)) |
2799 | done = 1; | 2807 | done = 1; |
2800 | 2808 | ||
2801 | spin_unlock_irq(&fi->reqlists_lock); | 2809 | spin_unlock_irqrestore(&fi->reqlists_lock, flags); |
2802 | 2810 | ||
2803 | if (!done) | 2811 | if (!done) |
2804 | down_interruptible(&fi->complete_sem); | 2812 | down_interruptible(&fi->complete_sem); |
@@ -2828,9 +2836,9 @@ static int raw1394_release(struct inode *inode, struct file *file) | |||
2828 | fi->host->id); | 2836 | fi->host->id); |
2829 | 2837 | ||
2830 | if (fi->state == connected) { | 2838 | if (fi->state == connected) { |
2831 | spin_lock_irq(&host_info_lock); | 2839 | spin_lock_irqsave(&host_info_lock, flags); |
2832 | list_del(&fi->list); | 2840 | list_del(&fi->list); |
2833 | spin_unlock_irq(&host_info_lock); | 2841 | spin_unlock_irqrestore(&host_info_lock, flags); |
2834 | 2842 | ||
2835 | put_device(&fi->host->device); | 2843 | put_device(&fi->host->device); |
2836 | } | 2844 | } |