diff options
Diffstat (limited to 'drivers/ieee1394/raw1394.c')
-rw-r--r-- | drivers/ieee1394/raw1394.c | 138 |
1 files changed, 80 insertions, 58 deletions
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 571ea68c0cf2..5ec4f5eb6b19 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c | |||
@@ -44,14 +44,15 @@ | |||
44 | #include <linux/compat.h> | 44 | #include <linux/compat.h> |
45 | 45 | ||
46 | #include "csr1212.h" | 46 | #include "csr1212.h" |
47 | #include "highlevel.h" | ||
48 | #include "hosts.h" | ||
47 | #include "ieee1394.h" | 49 | #include "ieee1394.h" |
48 | #include "ieee1394_types.h" | ||
49 | #include "ieee1394_core.h" | 50 | #include "ieee1394_core.h" |
50 | #include "nodemgr.h" | 51 | #include "ieee1394_hotplug.h" |
51 | #include "hosts.h" | ||
52 | #include "highlevel.h" | ||
53 | #include "iso.h" | ||
54 | #include "ieee1394_transactions.h" | 52 | #include "ieee1394_transactions.h" |
53 | #include "ieee1394_types.h" | ||
54 | #include "iso.h" | ||
55 | #include "nodemgr.h" | ||
55 | #include "raw1394.h" | 56 | #include "raw1394.h" |
56 | #include "raw1394-private.h" | 57 | #include "raw1394-private.h" |
57 | 58 | ||
@@ -66,7 +67,7 @@ | |||
66 | #define DBGMSG(fmt, args...) \ | 67 | #define DBGMSG(fmt, args...) \ |
67 | printk(KERN_INFO "raw1394:" fmt "\n" , ## args) | 68 | printk(KERN_INFO "raw1394:" fmt "\n" , ## args) |
68 | #else | 69 | #else |
69 | #define DBGMSG(fmt, args...) | 70 | #define DBGMSG(fmt, args...) do {} while (0) |
70 | #endif | 71 | #endif |
71 | 72 | ||
72 | static LIST_HEAD(host_info_list); | 73 | static LIST_HEAD(host_info_list); |
@@ -132,10 +133,9 @@ static void free_pending_request(struct pending_request *req) | |||
132 | static void __queue_complete_req(struct pending_request *req) | 133 | static void __queue_complete_req(struct pending_request *req) |
133 | { | 134 | { |
134 | struct file_info *fi = req->file_info; | 135 | struct file_info *fi = req->file_info; |
135 | list_move_tail(&req->list, &fi->req_complete); | ||
136 | 136 | ||
137 | up(&fi->complete_sem); | 137 | list_move_tail(&req->list, &fi->req_complete); |
138 | wake_up_interruptible(&fi->poll_wait_complete); | 138 | wake_up(&fi->wait_complete); |
139 | } | 139 | } |
140 | 140 | ||
141 | static void queue_complete_req(struct pending_request *req) | 141 | static void queue_complete_req(struct pending_request *req) |
@@ -463,13 +463,36 @@ raw1394_compat_read(const char __user *buf, struct raw1394_request *r) | |||
463 | 463 | ||
464 | #endif | 464 | #endif |
465 | 465 | ||
466 | /* get next completed request (caller must hold fi->reqlists_lock) */ | ||
467 | static inline struct pending_request *__next_complete_req(struct file_info *fi) | ||
468 | { | ||
469 | struct list_head *lh; | ||
470 | struct pending_request *req = NULL; | ||
471 | |||
472 | if (!list_empty(&fi->req_complete)) { | ||
473 | lh = fi->req_complete.next; | ||
474 | list_del(lh); | ||
475 | req = list_entry(lh, struct pending_request, list); | ||
476 | } | ||
477 | return req; | ||
478 | } | ||
479 | |||
480 | /* atomically get next completed request */ | ||
481 | static struct pending_request *next_complete_req(struct file_info *fi) | ||
482 | { | ||
483 | unsigned long flags; | ||
484 | struct pending_request *req; | ||
485 | |||
486 | spin_lock_irqsave(&fi->reqlists_lock, flags); | ||
487 | req = __next_complete_req(fi); | ||
488 | spin_unlock_irqrestore(&fi->reqlists_lock, flags); | ||
489 | return req; | ||
490 | } | ||
466 | 491 | ||
467 | static ssize_t raw1394_read(struct file *file, char __user * buffer, | 492 | static ssize_t raw1394_read(struct file *file, char __user * buffer, |
468 | size_t count, loff_t * offset_is_ignored) | 493 | size_t count, loff_t * offset_is_ignored) |
469 | { | 494 | { |
470 | unsigned long flags; | ||
471 | struct file_info *fi = (struct file_info *)file->private_data; | 495 | struct file_info *fi = (struct file_info *)file->private_data; |
472 | struct list_head *lh; | ||
473 | struct pending_request *req; | 496 | struct pending_request *req; |
474 | ssize_t ret; | 497 | ssize_t ret; |
475 | 498 | ||
@@ -487,22 +510,21 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer, | |||
487 | } | 510 | } |
488 | 511 | ||
489 | if (file->f_flags & O_NONBLOCK) { | 512 | if (file->f_flags & O_NONBLOCK) { |
490 | if (down_trylock(&fi->complete_sem)) { | 513 | if (!(req = next_complete_req(fi))) |
491 | return -EAGAIN; | 514 | return -EAGAIN; |
492 | } | ||
493 | } else { | 515 | } else { |
494 | if (down_interruptible(&fi->complete_sem)) { | 516 | /* |
517 | * NB: We call the macro wait_event_interruptible() with a | ||
518 | * condition argument with side effect. This is only possible | ||
519 | * because the side effect does not occur until the condition | ||
520 | * became true, and wait_event_interruptible() won't evaluate | ||
521 | * the condition again after that. | ||
522 | */ | ||
523 | if (wait_event_interruptible(fi->wait_complete, | ||
524 | (req = next_complete_req(fi)))) | ||
495 | return -ERESTARTSYS; | 525 | return -ERESTARTSYS; |
496 | } | ||
497 | } | 526 | } |
498 | 527 | ||
499 | spin_lock_irqsave(&fi->reqlists_lock, flags); | ||
500 | lh = fi->req_complete.next; | ||
501 | list_del(lh); | ||
502 | spin_unlock_irqrestore(&fi->reqlists_lock, flags); | ||
503 | |||
504 | req = list_entry(lh, struct pending_request, list); | ||
505 | |||
506 | if (req->req.length) { | 528 | if (req->req.length) { |
507 | if (copy_to_user(int2ptr(req->req.recvb), req->data, | 529 | if (copy_to_user(int2ptr(req->req.recvb), req->data, |
508 | req->req.length)) { | 530 | req->req.length)) { |
@@ -1752,6 +1774,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req) | |||
1752 | addr->notification_options |= addr->client_transactions; | 1774 | addr->notification_options |= addr->client_transactions; |
1753 | addr->recvb = req->req.recvb; | 1775 | addr->recvb = req->req.recvb; |
1754 | addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF); | 1776 | addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF); |
1777 | |||
1755 | spin_lock_irqsave(&host_info_lock, flags); | 1778 | spin_lock_irqsave(&host_info_lock, flags); |
1756 | hi = find_host_info(fi->host); | 1779 | hi = find_host_info(fi->host); |
1757 | same_host = 0; | 1780 | same_host = 0; |
@@ -1777,9 +1800,9 @@ static int arm_register(struct file_info *fi, struct pending_request *req) | |||
1777 | } | 1800 | } |
1778 | if (same_host) { | 1801 | if (same_host) { |
1779 | /* addressrange occupied by same host */ | 1802 | /* addressrange occupied by same host */ |
1803 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1780 | vfree(addr->addr_space_buffer); | 1804 | vfree(addr->addr_space_buffer); |
1781 | kfree(addr); | 1805 | kfree(addr); |
1782 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1783 | return (-EALREADY); | 1806 | return (-EALREADY); |
1784 | } | 1807 | } |
1785 | /* another host with valid address-entry containing same addressrange */ | 1808 | /* another host with valid address-entry containing same addressrange */ |
@@ -1807,6 +1830,8 @@ static int arm_register(struct file_info *fi, struct pending_request *req) | |||
1807 | } | 1830 | } |
1808 | } | 1831 | } |
1809 | } | 1832 | } |
1833 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1834 | |||
1810 | if (another_host) { | 1835 | if (another_host) { |
1811 | DBGMSG("another hosts entry is valid -> SUCCESS"); | 1836 | DBGMSG("another hosts entry is valid -> SUCCESS"); |
1812 | if (copy_to_user(int2ptr(req->req.recvb), | 1837 | if (copy_to_user(int2ptr(req->req.recvb), |
@@ -1815,11 +1840,11 @@ static int arm_register(struct file_info *fi, struct pending_request *req) | |||
1815 | " address-range-entry is invalid -> EFAULT !!!\n"); | 1840 | " address-range-entry is invalid -> EFAULT !!!\n"); |
1816 | vfree(addr->addr_space_buffer); | 1841 | vfree(addr->addr_space_buffer); |
1817 | kfree(addr); | 1842 | kfree(addr); |
1818 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1819 | return (-EFAULT); | 1843 | return (-EFAULT); |
1820 | } | 1844 | } |
1821 | free_pending_request(req); /* immediate success or fail */ | 1845 | free_pending_request(req); /* immediate success or fail */ |
1822 | /* INSERT ENTRY */ | 1846 | /* INSERT ENTRY */ |
1847 | spin_lock_irqsave(&host_info_lock, flags); | ||
1823 | list_add_tail(&addr->addr_list, &fi->addr_list); | 1848 | list_add_tail(&addr->addr_list, &fi->addr_list); |
1824 | spin_unlock_irqrestore(&host_info_lock, flags); | 1849 | spin_unlock_irqrestore(&host_info_lock, flags); |
1825 | return sizeof(struct raw1394_request); | 1850 | return sizeof(struct raw1394_request); |
@@ -1830,15 +1855,15 @@ static int arm_register(struct file_info *fi, struct pending_request *req) | |||
1830 | req->req.address + req->req.length); | 1855 | req->req.address + req->req.length); |
1831 | if (retval) { | 1856 | if (retval) { |
1832 | /* INSERT ENTRY */ | 1857 | /* INSERT ENTRY */ |
1858 | spin_lock_irqsave(&host_info_lock, flags); | ||
1833 | list_add_tail(&addr->addr_list, &fi->addr_list); | 1859 | list_add_tail(&addr->addr_list, &fi->addr_list); |
1860 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1834 | } else { | 1861 | } else { |
1835 | DBGMSG("arm_register failed errno: %d \n", retval); | 1862 | DBGMSG("arm_register failed errno: %d \n", retval); |
1836 | vfree(addr->addr_space_buffer); | 1863 | vfree(addr->addr_space_buffer); |
1837 | kfree(addr); | 1864 | kfree(addr); |
1838 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1839 | return (-EALREADY); | 1865 | return (-EALREADY); |
1840 | } | 1866 | } |
1841 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1842 | free_pending_request(req); /* immediate success or fail */ | 1867 | free_pending_request(req); /* immediate success or fail */ |
1843 | return sizeof(struct raw1394_request); | 1868 | return sizeof(struct raw1394_request); |
1844 | } | 1869 | } |
@@ -1904,10 +1929,10 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req) | |||
1904 | if (another_host) { | 1929 | if (another_host) { |
1905 | DBGMSG("delete entry from list -> success"); | 1930 | DBGMSG("delete entry from list -> success"); |
1906 | list_del(&addr->addr_list); | 1931 | list_del(&addr->addr_list); |
1932 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1907 | vfree(addr->addr_space_buffer); | 1933 | vfree(addr->addr_space_buffer); |
1908 | kfree(addr); | 1934 | kfree(addr); |
1909 | free_pending_request(req); /* immediate success or fail */ | 1935 | free_pending_request(req); /* immediate success or fail */ |
1910 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1911 | return sizeof(struct raw1394_request); | 1936 | return sizeof(struct raw1394_request); |
1912 | } | 1937 | } |
1913 | retval = | 1938 | retval = |
@@ -1949,23 +1974,19 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req) | |||
1949 | (arm_addr->end > req->req.address)) { | 1974 | (arm_addr->end > req->req.address)) { |
1950 | if (req->req.address + req->req.length <= arm_addr->end) { | 1975 | if (req->req.address + req->req.length <= arm_addr->end) { |
1951 | offset = req->req.address - arm_addr->start; | 1976 | offset = req->req.address - arm_addr->start; |
1977 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1952 | 1978 | ||
1953 | DBGMSG | 1979 | DBGMSG |
1954 | ("arm_get_buf copy_to_user( %08X, %p, %u )", | 1980 | ("arm_get_buf copy_to_user( %08X, %p, %u )", |
1955 | (u32) req->req.recvb, | 1981 | (u32) req->req.recvb, |
1956 | arm_addr->addr_space_buffer + offset, | 1982 | arm_addr->addr_space_buffer + offset, |
1957 | (u32) req->req.length); | 1983 | (u32) req->req.length); |
1958 | |||
1959 | if (copy_to_user | 1984 | if (copy_to_user |
1960 | (int2ptr(req->req.recvb), | 1985 | (int2ptr(req->req.recvb), |
1961 | arm_addr->addr_space_buffer + offset, | 1986 | arm_addr->addr_space_buffer + offset, |
1962 | req->req.length)) { | 1987 | req->req.length)) |
1963 | spin_unlock_irqrestore(&host_info_lock, | ||
1964 | flags); | ||
1965 | return (-EFAULT); | 1988 | return (-EFAULT); |
1966 | } | ||
1967 | 1989 | ||
1968 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1969 | /* We have to free the request, because we | 1990 | /* We have to free the request, because we |
1970 | * queue no response, and therefore nobody | 1991 | * queue no response, and therefore nobody |
1971 | * will free it. */ | 1992 | * will free it. */ |
@@ -2005,24 +2026,23 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req) | |||
2005 | (arm_addr->end > req->req.address)) { | 2026 | (arm_addr->end > req->req.address)) { |
2006 | if (req->req.address + req->req.length <= arm_addr->end) { | 2027 | if (req->req.address + req->req.length <= arm_addr->end) { |
2007 | offset = req->req.address - arm_addr->start; | 2028 | offset = req->req.address - arm_addr->start; |
2029 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
2008 | 2030 | ||
2009 | DBGMSG | 2031 | DBGMSG |
2010 | ("arm_set_buf copy_from_user( %p, %08X, %u )", | 2032 | ("arm_set_buf copy_from_user( %p, %08X, %u )", |
2011 | arm_addr->addr_space_buffer + offset, | 2033 | arm_addr->addr_space_buffer + offset, |
2012 | (u32) req->req.sendb, | 2034 | (u32) req->req.sendb, |
2013 | (u32) req->req.length); | 2035 | (u32) req->req.length); |
2014 | |||
2015 | if (copy_from_user | 2036 | if (copy_from_user |
2016 | (arm_addr->addr_space_buffer + offset, | 2037 | (arm_addr->addr_space_buffer + offset, |
2017 | int2ptr(req->req.sendb), | 2038 | int2ptr(req->req.sendb), |
2018 | req->req.length)) { | 2039 | req->req.length)) |
2019 | spin_unlock_irqrestore(&host_info_lock, | ||
2020 | flags); | ||
2021 | return (-EFAULT); | 2040 | return (-EFAULT); |
2022 | } | ||
2023 | 2041 | ||
2024 | spin_unlock_irqrestore(&host_info_lock, flags); | 2042 | /* We have to free the request, because we |
2025 | free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ | 2043 | * queue no response, and therefore nobody |
2044 | * will free it. */ | ||
2045 | free_pending_request(req); | ||
2026 | return sizeof(struct raw1394_request); | 2046 | return sizeof(struct raw1394_request); |
2027 | } else { | 2047 | } else { |
2028 | DBGMSG("arm_set_buf request exceeded mapping"); | 2048 | DBGMSG("arm_set_buf request exceeded mapping"); |
@@ -2744,7 +2764,7 @@ static unsigned int raw1394_poll(struct file *file, poll_table * pt) | |||
2744 | unsigned int mask = POLLOUT | POLLWRNORM; | 2764 | unsigned int mask = POLLOUT | POLLWRNORM; |
2745 | unsigned long flags; | 2765 | unsigned long flags; |
2746 | 2766 | ||
2747 | poll_wait(file, &fi->poll_wait_complete, pt); | 2767 | poll_wait(file, &fi->wait_complete, pt); |
2748 | 2768 | ||
2749 | spin_lock_irqsave(&fi->reqlists_lock, flags); | 2769 | spin_lock_irqsave(&fi->reqlists_lock, flags); |
2750 | if (!list_empty(&fi->req_complete)) { | 2770 | if (!list_empty(&fi->req_complete)) { |
@@ -2769,9 +2789,8 @@ static int raw1394_open(struct inode *inode, struct file *file) | |||
2769 | fi->state = opened; | 2789 | fi->state = opened; |
2770 | INIT_LIST_HEAD(&fi->req_pending); | 2790 | INIT_LIST_HEAD(&fi->req_pending); |
2771 | INIT_LIST_HEAD(&fi->req_complete); | 2791 | INIT_LIST_HEAD(&fi->req_complete); |
2772 | sema_init(&fi->complete_sem, 0); | ||
2773 | spin_lock_init(&fi->reqlists_lock); | 2792 | spin_lock_init(&fi->reqlists_lock); |
2774 | init_waitqueue_head(&fi->poll_wait_complete); | 2793 | init_waitqueue_head(&fi->wait_complete); |
2775 | INIT_LIST_HEAD(&fi->addr_list); | 2794 | INIT_LIST_HEAD(&fi->addr_list); |
2776 | 2795 | ||
2777 | file->private_data = fi; | 2796 | file->private_data = fi; |
@@ -2784,7 +2803,7 @@ static int raw1394_release(struct inode *inode, struct file *file) | |||
2784 | struct file_info *fi = file->private_data; | 2803 | struct file_info *fi = file->private_data; |
2785 | struct list_head *lh; | 2804 | struct list_head *lh; |
2786 | struct pending_request *req; | 2805 | struct pending_request *req; |
2787 | int done = 0, i, fail = 0; | 2806 | int i, fail; |
2788 | int retval = 0; | 2807 | int retval = 0; |
2789 | struct list_head *entry; | 2808 | struct list_head *entry; |
2790 | struct arm_addr *addr = NULL; | 2809 | struct arm_addr *addr = NULL; |
@@ -2864,25 +2883,28 @@ static int raw1394_release(struct inode *inode, struct file *file) | |||
2864 | "error(s) occurred \n"); | 2883 | "error(s) occurred \n"); |
2865 | } | 2884 | } |
2866 | 2885 | ||
2867 | while (!done) { | 2886 | for (;;) { |
2887 | /* This locked section guarantees that neither | ||
2888 | * complete nor pending requests exist once i!=0 */ | ||
2868 | spin_lock_irqsave(&fi->reqlists_lock, flags); | 2889 | spin_lock_irqsave(&fi->reqlists_lock, flags); |
2869 | 2890 | while ((req = __next_complete_req(fi))) | |
2870 | while (!list_empty(&fi->req_complete)) { | ||
2871 | lh = fi->req_complete.next; | ||
2872 | list_del(lh); | ||
2873 | |||
2874 | req = list_entry(lh, struct pending_request, list); | ||
2875 | |||
2876 | free_pending_request(req); | 2891 | free_pending_request(req); |
2877 | } | ||
2878 | |||
2879 | if (list_empty(&fi->req_pending)) | ||
2880 | done = 1; | ||
2881 | 2892 | ||
2893 | i = list_empty(&fi->req_pending); | ||
2882 | spin_unlock_irqrestore(&fi->reqlists_lock, flags); | 2894 | spin_unlock_irqrestore(&fi->reqlists_lock, flags); |
2883 | 2895 | ||
2884 | if (!done) | 2896 | if (i) |
2885 | down_interruptible(&fi->complete_sem); | 2897 | break; |
2898 | /* | ||
2899 | * Sleep until more requests can be freed. | ||
2900 | * | ||
2901 | * NB: We call the macro wait_event() with a condition argument | ||
2902 | * with side effect. This is only possible because the side | ||
2903 | * effect does not occur until the condition became true, and | ||
2904 | * wait_event() won't evaluate the condition again after that. | ||
2905 | */ | ||
2906 | wait_event(fi->wait_complete, (req = next_complete_req(fi))); | ||
2907 | free_pending_request(req); | ||
2886 | } | 2908 | } |
2887 | 2909 | ||
2888 | /* Remove any sub-trees left by user space programs */ | 2910 | /* Remove any sub-trees left by user space programs */ |