aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2006-09-14 16:05:16 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2006-09-23 09:13:55 -0400
commit3253b669eed7194ae490acb4aadab7262bbfeb8d (patch)
tree376e683b87841ac2fa30d43f705d6982c2edc990 /drivers/ieee1394
parent919251758195919ae3568021bc221e4f8c4b20eb (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.c34
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");