diff options
| -rw-r--r-- | drivers/firewire/core-transaction.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 87d6f2d2f02d..d39cfa45817a 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
| 32 | #include <linux/list.h> | 32 | #include <linux/list.h> |
| 33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
| 34 | #include <linux/rculist.h> | ||
| 34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 35 | #include <linux/spinlock.h> | 36 | #include <linux/spinlock.h> |
| 36 | #include <linux/string.h> | 37 | #include <linux/string.h> |
| @@ -489,7 +490,7 @@ static struct fw_address_handler *lookup_overlapping_address_handler( | |||
| 489 | { | 490 | { |
| 490 | struct fw_address_handler *handler; | 491 | struct fw_address_handler *handler; |
| 491 | 492 | ||
| 492 | list_for_each_entry(handler, list, link) { | 493 | list_for_each_entry_rcu(handler, list, link) { |
| 493 | if (handler->offset < offset + length && | 494 | if (handler->offset < offset + length && |
| 494 | offset < handler->offset + handler->length) | 495 | offset < handler->offset + handler->length) |
| 495 | return handler; | 496 | return handler; |
| @@ -510,7 +511,7 @@ static struct fw_address_handler *lookup_enclosing_address_handler( | |||
| 510 | { | 511 | { |
| 511 | struct fw_address_handler *handler; | 512 | struct fw_address_handler *handler; |
| 512 | 513 | ||
| 513 | list_for_each_entry(handler, list, link) { | 514 | list_for_each_entry_rcu(handler, list, link) { |
| 514 | if (is_enclosing_handler(handler, offset, length)) | 515 | if (is_enclosing_handler(handler, offset, length)) |
| 515 | return handler; | 516 | return handler; |
| 516 | } | 517 | } |
| @@ -588,7 +589,7 @@ int fw_core_add_address_handler(struct fw_address_handler *handler, | |||
| 588 | if (other != NULL) { | 589 | if (other != NULL) { |
| 589 | handler->offset += other->length; | 590 | handler->offset += other->length; |
| 590 | } else { | 591 | } else { |
| 591 | list_add_tail(&handler->link, &address_handler_list); | 592 | list_add_tail_rcu(&handler->link, &address_handler_list); |
| 592 | ret = 0; | 593 | ret = 0; |
| 593 | break; | 594 | break; |
| 594 | } | 595 | } |
| @@ -609,8 +610,9 @@ EXPORT_SYMBOL(fw_core_add_address_handler); | |||
| 609 | void fw_core_remove_address_handler(struct fw_address_handler *handler) | 610 | void fw_core_remove_address_handler(struct fw_address_handler *handler) |
| 610 | { | 611 | { |
| 611 | spin_lock_bh(&address_handler_lock); | 612 | spin_lock_bh(&address_handler_lock); |
| 612 | list_del(&handler->link); | 613 | list_del_rcu(&handler->link); |
| 613 | spin_unlock_bh(&address_handler_lock); | 614 | spin_unlock_bh(&address_handler_lock); |
| 615 | synchronize_rcu(); | ||
| 614 | } | 616 | } |
| 615 | EXPORT_SYMBOL(fw_core_remove_address_handler); | 617 | EXPORT_SYMBOL(fw_core_remove_address_handler); |
| 616 | 618 | ||
| @@ -844,7 +846,7 @@ static void handle_exclusive_region_request(struct fw_card *card, | |||
| 844 | if (tcode == TCODE_LOCK_REQUEST) | 846 | if (tcode == TCODE_LOCK_REQUEST) |
| 845 | tcode = 0x10 + HEADER_GET_EXTENDED_TCODE(p->header[3]); | 847 | tcode = 0x10 + HEADER_GET_EXTENDED_TCODE(p->header[3]); |
| 846 | 848 | ||
| 847 | spin_lock_bh(&address_handler_lock); | 849 | rcu_read_lock(); |
| 848 | handler = lookup_enclosing_address_handler(&address_handler_list, | 850 | handler = lookup_enclosing_address_handler(&address_handler_list, |
| 849 | offset, request->length); | 851 | offset, request->length); |
| 850 | if (handler) | 852 | if (handler) |
| @@ -853,7 +855,7 @@ static void handle_exclusive_region_request(struct fw_card *card, | |||
| 853 | p->generation, offset, | 855 | p->generation, offset, |
| 854 | request->data, request->length, | 856 | request->data, request->length, |
| 855 | handler->callback_data); | 857 | handler->callback_data); |
| 856 | spin_unlock_bh(&address_handler_lock); | 858 | rcu_read_unlock(); |
| 857 | 859 | ||
| 858 | if (!handler) | 860 | if (!handler) |
| 859 | fw_send_response(card, request, RCODE_ADDRESS_ERROR); | 861 | fw_send_response(card, request, RCODE_ADDRESS_ERROR); |
| @@ -886,8 +888,8 @@ static void handle_fcp_region_request(struct fw_card *card, | |||
| 886 | return; | 888 | return; |
| 887 | } | 889 | } |
| 888 | 890 | ||
| 889 | spin_lock_bh(&address_handler_lock); | 891 | rcu_read_lock(); |
| 890 | list_for_each_entry(handler, &address_handler_list, link) { | 892 | list_for_each_entry_rcu(handler, &address_handler_list, link) { |
| 891 | if (is_enclosing_handler(handler, offset, request->length)) | 893 | if (is_enclosing_handler(handler, offset, request->length)) |
| 892 | handler->address_callback(card, NULL, tcode, | 894 | handler->address_callback(card, NULL, tcode, |
| 893 | destination, source, | 895 | destination, source, |
| @@ -896,7 +898,7 @@ static void handle_fcp_region_request(struct fw_card *card, | |||
| 896 | request->length, | 898 | request->length, |
| 897 | handler->callback_data); | 899 | handler->callback_data); |
| 898 | } | 900 | } |
| 899 | spin_unlock_bh(&address_handler_lock); | 901 | rcu_read_unlock(); |
| 900 | 902 | ||
| 901 | fw_send_response(card, request, RCODE_COMPLETE); | 903 | fw_send_response(card, request, RCODE_COMPLETE); |
| 902 | } | 904 | } |
