diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2006-09-14 16:05:16 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2006-09-23 09:13:55 -0400 |
commit | 3253b669eed7194ae490acb4aadab7262bbfeb8d (patch) | |
tree | 376e683b87841ac2fa30d43f705d6982c2edc990 /drivers/ieee1394 | |
parent | 919251758195919ae3568021bc221e4f8c4b20eb (diff) |
ieee1394: raw1394: arm functions slept in atomic context
Sleeping functions like copy_to_user were accessed inside spinlocks in
raw1394's arm_register, arm_unregister, arm_get_buf, arm_set_buf.
http://bugzilla.kernel.org/show_bug.cgi?id=7120
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Tested-by: David Trent <DTrent@piacton.com>
(cherry picked from e575953ec17c3f5c1e738847d2d16c241bb99783 commit)
Diffstat (limited to 'drivers/ieee1394')
-rw-r--r-- | drivers/ieee1394/raw1394.c | 34 |
1 files changed, 16 insertions, 18 deletions
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 47e667593244..5ec4f5eb6b19 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c | |||
@@ -1774,6 +1774,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req) | |||
1774 | addr->notification_options |= addr->client_transactions; | 1774 | addr->notification_options |= addr->client_transactions; |
1775 | addr->recvb = req->req.recvb; | 1775 | addr->recvb = req->req.recvb; |
1776 | addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF); | 1776 | addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF); |
1777 | |||
1777 | spin_lock_irqsave(&host_info_lock, flags); | 1778 | spin_lock_irqsave(&host_info_lock, flags); |
1778 | hi = find_host_info(fi->host); | 1779 | hi = find_host_info(fi->host); |
1779 | same_host = 0; | 1780 | same_host = 0; |
@@ -1799,9 +1800,9 @@ static int arm_register(struct file_info *fi, struct pending_request *req) | |||
1799 | } | 1800 | } |
1800 | if (same_host) { | 1801 | if (same_host) { |
1801 | /* addressrange occupied by same host */ | 1802 | /* addressrange occupied by same host */ |
1803 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1802 | vfree(addr->addr_space_buffer); | 1804 | vfree(addr->addr_space_buffer); |
1803 | kfree(addr); | 1805 | kfree(addr); |
1804 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1805 | return (-EALREADY); | 1806 | return (-EALREADY); |
1806 | } | 1807 | } |
1807 | /* another host with valid address-entry containing same addressrange */ | 1808 | /* another host with valid address-entry containing same addressrange */ |
@@ -1829,6 +1830,8 @@ static int arm_register(struct file_info *fi, struct pending_request *req) | |||
1829 | } | 1830 | } |
1830 | } | 1831 | } |
1831 | } | 1832 | } |
1833 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1834 | |||
1832 | if (another_host) { | 1835 | if (another_host) { |
1833 | DBGMSG("another hosts entry is valid -> SUCCESS"); | 1836 | DBGMSG("another hosts entry is valid -> SUCCESS"); |
1834 | if (copy_to_user(int2ptr(req->req.recvb), | 1837 | if (copy_to_user(int2ptr(req->req.recvb), |
@@ -1837,11 +1840,11 @@ static int arm_register(struct file_info *fi, struct pending_request *req) | |||
1837 | " address-range-entry is invalid -> EFAULT !!!\n"); | 1840 | " address-range-entry is invalid -> EFAULT !!!\n"); |
1838 | vfree(addr->addr_space_buffer); | 1841 | vfree(addr->addr_space_buffer); |
1839 | kfree(addr); | 1842 | kfree(addr); |
1840 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1841 | return (-EFAULT); | 1843 | return (-EFAULT); |
1842 | } | 1844 | } |
1843 | free_pending_request(req); /* immediate success or fail */ | 1845 | free_pending_request(req); /* immediate success or fail */ |
1844 | /* INSERT ENTRY */ | 1846 | /* INSERT ENTRY */ |
1847 | spin_lock_irqsave(&host_info_lock, flags); | ||
1845 | list_add_tail(&addr->addr_list, &fi->addr_list); | 1848 | list_add_tail(&addr->addr_list, &fi->addr_list); |
1846 | spin_unlock_irqrestore(&host_info_lock, flags); | 1849 | spin_unlock_irqrestore(&host_info_lock, flags); |
1847 | return sizeof(struct raw1394_request); | 1850 | return sizeof(struct raw1394_request); |
@@ -1852,15 +1855,15 @@ static int arm_register(struct file_info *fi, struct pending_request *req) | |||
1852 | req->req.address + req->req.length); | 1855 | req->req.address + req->req.length); |
1853 | if (retval) { | 1856 | if (retval) { |
1854 | /* INSERT ENTRY */ | 1857 | /* INSERT ENTRY */ |
1858 | spin_lock_irqsave(&host_info_lock, flags); | ||
1855 | 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); | ||
1856 | } else { | 1861 | } else { |
1857 | DBGMSG("arm_register failed errno: %d \n", retval); | 1862 | DBGMSG("arm_register failed errno: %d \n", retval); |
1858 | vfree(addr->addr_space_buffer); | 1863 | vfree(addr->addr_space_buffer); |
1859 | kfree(addr); | 1864 | kfree(addr); |
1860 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1861 | return (-EALREADY); | 1865 | return (-EALREADY); |
1862 | } | 1866 | } |
1863 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1864 | free_pending_request(req); /* immediate success or fail */ | 1867 | free_pending_request(req); /* immediate success or fail */ |
1865 | return sizeof(struct raw1394_request); | 1868 | return sizeof(struct raw1394_request); |
1866 | } | 1869 | } |
@@ -1926,10 +1929,10 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req) | |||
1926 | if (another_host) { | 1929 | if (another_host) { |
1927 | DBGMSG("delete entry from list -> success"); | 1930 | DBGMSG("delete entry from list -> success"); |
1928 | list_del(&addr->addr_list); | 1931 | list_del(&addr->addr_list); |
1932 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1929 | vfree(addr->addr_space_buffer); | 1933 | vfree(addr->addr_space_buffer); |
1930 | kfree(addr); | 1934 | kfree(addr); |
1931 | free_pending_request(req); /* immediate success or fail */ | 1935 | free_pending_request(req); /* immediate success or fail */ |
1932 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1933 | return sizeof(struct raw1394_request); | 1936 | return sizeof(struct raw1394_request); |
1934 | } | 1937 | } |
1935 | retval = | 1938 | retval = |
@@ -1971,23 +1974,19 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req) | |||
1971 | (arm_addr->end > req->req.address)) { | 1974 | (arm_addr->end > req->req.address)) { |
1972 | if (req->req.address + req->req.length <= arm_addr->end) { | 1975 | if (req->req.address + req->req.length <= arm_addr->end) { |
1973 | offset = req->req.address - arm_addr->start; | 1976 | offset = req->req.address - arm_addr->start; |
1977 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1974 | 1978 | ||
1975 | DBGMSG | 1979 | DBGMSG |
1976 | ("arm_get_buf copy_to_user( %08X, %p, %u )", | 1980 | ("arm_get_buf copy_to_user( %08X, %p, %u )", |
1977 | (u32) req->req.recvb, | 1981 | (u32) req->req.recvb, |
1978 | arm_addr->addr_space_buffer + offset, | 1982 | arm_addr->addr_space_buffer + offset, |
1979 | (u32) req->req.length); | 1983 | (u32) req->req.length); |
1980 | |||
1981 | if (copy_to_user | 1984 | if (copy_to_user |
1982 | (int2ptr(req->req.recvb), | 1985 | (int2ptr(req->req.recvb), |
1983 | arm_addr->addr_space_buffer + offset, | 1986 | arm_addr->addr_space_buffer + offset, |
1984 | req->req.length)) { | 1987 | req->req.length)) |
1985 | spin_unlock_irqrestore(&host_info_lock, | ||
1986 | flags); | ||
1987 | return (-EFAULT); | 1988 | return (-EFAULT); |
1988 | } | ||
1989 | 1989 | ||
1990 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
1991 | /* We have to free the request, because we | 1990 | /* We have to free the request, because we |
1992 | * queue no response, and therefore nobody | 1991 | * queue no response, and therefore nobody |
1993 | * will free it. */ | 1992 | * will free it. */ |
@@ -2027,24 +2026,23 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req) | |||
2027 | (arm_addr->end > req->req.address)) { | 2026 | (arm_addr->end > req->req.address)) { |
2028 | if (req->req.address + req->req.length <= arm_addr->end) { | 2027 | if (req->req.address + req->req.length <= arm_addr->end) { |
2029 | offset = req->req.address - arm_addr->start; | 2028 | offset = req->req.address - arm_addr->start; |
2029 | spin_unlock_irqrestore(&host_info_lock, flags); | ||
2030 | 2030 | ||
2031 | DBGMSG | 2031 | DBGMSG |
2032 | ("arm_set_buf copy_from_user( %p, %08X, %u )", | 2032 | ("arm_set_buf copy_from_user( %p, %08X, %u )", |
2033 | arm_addr->addr_space_buffer + offset, | 2033 | arm_addr->addr_space_buffer + offset, |
2034 | (u32) req->req.sendb, | 2034 | (u32) req->req.sendb, |
2035 | (u32) req->req.length); | 2035 | (u32) req->req.length); |
2036 | |||
2037 | if (copy_from_user | 2036 | if (copy_from_user |
2038 | (arm_addr->addr_space_buffer + offset, | 2037 | (arm_addr->addr_space_buffer + offset, |
2039 | int2ptr(req->req.sendb), | 2038 | int2ptr(req->req.sendb), |
2040 | req->req.length)) { | 2039 | req->req.length)) |
2041 | spin_unlock_irqrestore(&host_info_lock, | ||
2042 | flags); | ||
2043 | return (-EFAULT); | 2040 | return (-EFAULT); |
2044 | } | ||
2045 | 2041 | ||
2046 | spin_unlock_irqrestore(&host_info_lock, flags); | 2042 | /* We have to free the request, because we |
2047 | 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); | ||
2048 | return sizeof(struct raw1394_request); | 2046 | return sizeof(struct raw1394_request); |
2049 | } else { | 2047 | } else { |
2050 | DBGMSG("arm_set_buf request exceeded mapping"); | 2048 | DBGMSG("arm_set_buf request exceeded mapping"); |