提交 4a9949d7 编写于 作者: A Andy Wingo 提交者: Linus Torvalds

[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: NAndy Wingo <wingo@pobox.com>
Acked-by: NBen Collins <bcollins@ubuntu.com>
Signed-off-by: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 c367c21c
...@@ -2283,8 +2283,9 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci, ...@@ -2283,8 +2283,9 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
{ {
struct ohci1394_iso_tasklet *t; struct ohci1394_iso_tasklet *t;
unsigned long mask; unsigned long mask;
unsigned long flags;
spin_lock(&ohci->iso_tasklet_list_lock); spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags);
list_for_each_entry(t, &ohci->iso_tasklet_list, link) { list_for_each_entry(t, &ohci->iso_tasklet_list, link) {
mask = 1 << t->context; mask = 1 << t->context;
...@@ -2295,8 +2296,7 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci, ...@@ -2295,8 +2296,7 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
tasklet_schedule(&t->tasklet); tasklet_schedule(&t->tasklet);
} }
spin_unlock(&ohci->iso_tasklet_list_lock); spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
} }
static irqreturn_t ohci_irq_handler(int irq, void *dev_id, static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
......
...@@ -412,6 +412,7 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction, ...@@ -412,6 +412,7 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
static ssize_t raw1394_read(struct file *file, char __user * buffer, static ssize_t raw1394_read(struct file *file, char __user * buffer,
size_t count, loff_t * offset_is_ignored) size_t count, loff_t * offset_is_ignored)
{ {
unsigned long flags;
struct file_info *fi = (struct file_info *)file->private_data; struct file_info *fi = (struct file_info *)file->private_data;
struct list_head *lh; struct list_head *lh;
struct pending_request *req; struct pending_request *req;
...@@ -435,10 +436,10 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer, ...@@ -435,10 +436,10 @@ static ssize_t raw1394_read(struct file *file, char __user * buffer,
} }
} }
spin_lock_irq(&fi->reqlists_lock); spin_lock_irqsave(&fi->reqlists_lock, flags);
lh = fi->req_complete.next; lh = fi->req_complete.next;
list_del(lh); list_del(lh);
spin_unlock_irq(&fi->reqlists_lock); spin_unlock_irqrestore(&fi->reqlists_lock, flags);
req = list_entry(lh, struct pending_request, list); req = list_entry(lh, struct pending_request, list);
...@@ -486,6 +487,7 @@ static int state_opened(struct file_info *fi, struct pending_request *req) ...@@ -486,6 +487,7 @@ static int state_opened(struct file_info *fi, struct pending_request *req)
static int state_initialized(struct file_info *fi, struct pending_request *req) static int state_initialized(struct file_info *fi, struct pending_request *req)
{ {
unsigned long flags;
struct host_info *hi; struct host_info *hi;
struct raw1394_khost_list *khl; struct raw1394_khost_list *khl;
...@@ -499,7 +501,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) ...@@ -499,7 +501,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
switch (req->req.type) { switch (req->req.type) {
case RAW1394_REQ_LIST_CARDS: case RAW1394_REQ_LIST_CARDS:
spin_lock_irq(&host_info_lock); spin_lock_irqsave(&host_info_lock, flags);
khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count, khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count,
SLAB_ATOMIC); SLAB_ATOMIC);
...@@ -513,7 +515,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) ...@@ -513,7 +515,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
khl++; khl++;
} }
} }
spin_unlock_irq(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, flags);
if (khl != NULL) { if (khl != NULL) {
req->req.error = RAW1394_ERROR_NONE; req->req.error = RAW1394_ERROR_NONE;
...@@ -528,7 +530,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) ...@@ -528,7 +530,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
break; break;
case RAW1394_REQ_SET_CARD: case RAW1394_REQ_SET_CARD:
spin_lock_irq(&host_info_lock); spin_lock_irqsave(&host_info_lock, flags);
if (req->req.misc < host_count) { if (req->req.misc < host_count) {
list_for_each_entry(hi, &host_info_list, list) { list_for_each_entry(hi, &host_info_list, list) {
if (!req->req.misc--) if (!req->req.misc--)
...@@ -550,7 +552,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) ...@@ -550,7 +552,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
} else { } else {
req->req.error = RAW1394_ERROR_INVALID_ARG; req->req.error = RAW1394_ERROR_INVALID_ARG;
} }
spin_unlock_irq(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, flags);
req->req.length = 0; req->req.length = 0;
break; break;
...@@ -569,7 +571,6 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req) ...@@ -569,7 +571,6 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
{ {
int channel = req->req.misc; int channel = req->req.misc;
spin_lock_irq(&host_info_lock);
if ((channel > 63) || (channel < -64)) { if ((channel > 63) || (channel < -64)) {
req->req.error = RAW1394_ERROR_INVALID_ARG; req->req.error = RAW1394_ERROR_INVALID_ARG;
} else if (channel >= 0) { } else if (channel >= 0) {
...@@ -601,7 +602,6 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req) ...@@ -601,7 +602,6 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
req->req.length = 0; req->req.length = 0;
queue_complete_req(req); queue_complete_req(req);
spin_unlock_irq(&host_info_lock);
} }
static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) 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,6 +627,7 @@ static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
static int handle_async_request(struct file_info *fi, static int handle_async_request(struct file_info *fi,
struct pending_request *req, int node) struct pending_request *req, int node)
{ {
unsigned long flags;
struct hpsb_packet *packet = NULL; struct hpsb_packet *packet = NULL;
u64 addr = req->req.address & 0xffffffffffffULL; u64 addr = req->req.address & 0xffffffffffffULL;
...@@ -761,9 +762,9 @@ static int handle_async_request(struct file_info *fi, ...@@ -761,9 +762,9 @@ static int handle_async_request(struct file_info *fi,
hpsb_set_packet_complete_task(packet, hpsb_set_packet_complete_task(packet,
(void (*)(void *))queue_complete_cb, req); (void (*)(void *))queue_complete_cb, req);
spin_lock_irq(&fi->reqlists_lock); spin_lock_irqsave(&fi->reqlists_lock, flags);
list_add_tail(&req->list, &fi->req_pending); list_add_tail(&req->list, &fi->req_pending);
spin_unlock_irq(&fi->reqlists_lock); spin_unlock_irqrestore(&fi->reqlists_lock, flags);
packet->generation = req->req.generation; packet->generation = req->req.generation;
...@@ -779,6 +780,7 @@ static int handle_async_request(struct file_info *fi, ...@@ -779,6 +780,7 @@ static int handle_async_request(struct file_info *fi,
static int handle_iso_send(struct file_info *fi, struct pending_request *req, static int handle_iso_send(struct file_info *fi, struct pending_request *req,
int channel) int channel)
{ {
unsigned long flags;
struct hpsb_packet *packet; struct hpsb_packet *packet;
packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f, 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,9 +806,9 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
(void (*)(void *))queue_complete_req, (void (*)(void *))queue_complete_req,
req); req);
spin_lock_irq(&fi->reqlists_lock); spin_lock_irqsave(&fi->reqlists_lock, flags);
list_add_tail(&req->list, &fi->req_pending); list_add_tail(&req->list, &fi->req_pending);
spin_unlock_irq(&fi->reqlists_lock); spin_unlock_irqrestore(&fi->reqlists_lock, flags);
/* Update the generation of the packet just before sending. */ /* Update the generation of the packet just before sending. */
packet->generation = req->req.generation; packet->generation = req->req.generation;
...@@ -821,6 +823,7 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req, ...@@ -821,6 +823,7 @@ static int handle_iso_send(struct file_info *fi, struct pending_request *req,
static int handle_async_send(struct file_info *fi, struct pending_request *req) static int handle_async_send(struct file_info *fi, struct pending_request *req)
{ {
unsigned long flags;
struct hpsb_packet *packet; struct hpsb_packet *packet;
int header_length = req->req.misc & 0xffff; int header_length = req->req.misc & 0xffff;
int expect_response = req->req.misc >> 16; 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,9 +870,9 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
hpsb_set_packet_complete_task(packet, hpsb_set_packet_complete_task(packet,
(void (*)(void *))queue_complete_cb, req); (void (*)(void *))queue_complete_cb, req);
spin_lock_irq(&fi->reqlists_lock); spin_lock_irqsave(&fi->reqlists_lock, flags);
list_add_tail(&req->list, &fi->req_pending); list_add_tail(&req->list, &fi->req_pending);
spin_unlock_irq(&fi->reqlists_lock); spin_unlock_irqrestore(&fi->reqlists_lock, flags);
/* Update the generation of the packet just before sending. */ /* Update the generation of the packet just before sending. */
packet->generation = req->req.generation; packet->generation = req->req.generation;
...@@ -885,6 +888,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req) ...@@ -885,6 +888,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
u64 addr, size_t length, u16 flags) u64 addr, size_t length, u16 flags)
{ {
unsigned long irqflags;
struct pending_request *req; struct pending_request *req;
struct host_info *hi; struct host_info *hi;
struct file_info *fi = NULL; struct file_info *fi = NULL;
...@@ -899,7 +903,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, ...@@ -899,7 +903,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
"addr: %4.4x %8.8x length: %Zu", nodeid, "addr: %4.4x %8.8x length: %Zu", nodeid,
(u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
length); length);
spin_lock(&host_info_lock); spin_lock_irqsave(&host_info_lock, irqflags);
hi = find_host_info(host); /* search address-entry */ hi = find_host_info(host); /* search address-entry */
if (hi != NULL) { if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) { 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,7 +928,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
if (!found) { if (!found) {
printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found" printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
" -> rcode_address_error\n"); " -> rcode_address_error\n");
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_ADDRESS_ERROR); return (RCODE_ADDRESS_ERROR);
} else { } else {
DBGMSG("arm_read addr_entry FOUND"); DBGMSG("arm_read addr_entry FOUND");
...@@ -954,7 +958,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, ...@@ -954,7 +958,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
req = __alloc_pending_request(SLAB_ATOMIC); req = __alloc_pending_request(SLAB_ATOMIC);
if (!req) { if (!req) {
DBGMSG("arm_read -> rcode_conflict_error"); DBGMSG("arm_read -> rcode_conflict_error");
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */ The request may be retried */
} }
...@@ -974,7 +978,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, ...@@ -974,7 +978,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
if (!(req->data)) { if (!(req->data)) {
free_pending_request(req); free_pending_request(req);
DBGMSG("arm_read -> rcode_conflict_error"); DBGMSG("arm_read -> rcode_conflict_error");
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */ The request may be retried */
} }
...@@ -1031,13 +1035,14 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, ...@@ -1031,13 +1035,14 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
sizeof(struct arm_request)); sizeof(struct arm_request));
queue_complete_req(req); queue_complete_req(req);
} }
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (rcode); return (rcode);
} }
static int arm_write(struct hpsb_host *host, int nodeid, int destid, static int arm_write(struct hpsb_host *host, int nodeid, int destid,
quadlet_t * data, u64 addr, size_t length, u16 flags) quadlet_t * data, u64 addr, size_t length, u16 flags)
{ {
unsigned long irqflags;
struct pending_request *req; struct pending_request *req;
struct host_info *hi; struct host_info *hi;
struct file_info *fi = NULL; struct file_info *fi = NULL;
...@@ -1052,7 +1057,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, ...@@ -1052,7 +1057,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
"addr: %4.4x %8.8x length: %Zu", nodeid, "addr: %4.4x %8.8x length: %Zu", nodeid,
(u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
length); length);
spin_lock(&host_info_lock); spin_lock_irqsave(&host_info_lock, irqflags);
hi = find_host_info(host); /* search address-entry */ hi = find_host_info(host); /* search address-entry */
if (hi != NULL) { if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) { 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,7 +1082,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
if (!found) { if (!found) {
printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found" printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found"
" -> rcode_address_error\n"); " -> rcode_address_error\n");
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_ADDRESS_ERROR); return (RCODE_ADDRESS_ERROR);
} else { } else {
DBGMSG("arm_write addr_entry FOUND"); DBGMSG("arm_write addr_entry FOUND");
...@@ -1106,7 +1111,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, ...@@ -1106,7 +1111,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
req = __alloc_pending_request(SLAB_ATOMIC); req = __alloc_pending_request(SLAB_ATOMIC);
if (!req) { if (!req) {
DBGMSG("arm_write -> rcode_conflict_error"); DBGMSG("arm_write -> rcode_conflict_error");
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request my be retried */ The request my be retried */
} }
...@@ -1118,7 +1123,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, ...@@ -1118,7 +1123,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
if (!(req->data)) { if (!(req->data)) {
free_pending_request(req); free_pending_request(req);
DBGMSG("arm_write -> rcode_conflict_error"); DBGMSG("arm_write -> rcode_conflict_error");
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */ The request may be retried */
} }
...@@ -1165,7 +1170,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, ...@@ -1165,7 +1170,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
sizeof(struct arm_request)); sizeof(struct arm_request));
queue_complete_req(req); queue_complete_req(req);
} }
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (rcode); return (rcode);
} }
...@@ -1173,6 +1178,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, ...@@ -1173,6 +1178,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
u16 flags) u16 flags)
{ {
unsigned long irqflags;
struct pending_request *req; struct pending_request *req;
struct host_info *hi; struct host_info *hi;
struct file_info *fi = NULL; struct file_info *fi = NULL;
...@@ -1198,7 +1204,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, ...@@ -1198,7 +1204,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
(u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF, (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
be32_to_cpu(data), be32_to_cpu(arg)); be32_to_cpu(data), be32_to_cpu(arg));
} }
spin_lock(&host_info_lock); spin_lock_irqsave(&host_info_lock, irqflags);
hi = find_host_info(host); /* search address-entry */ hi = find_host_info(host); /* search address-entry */
if (hi != NULL) { if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) { 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,7 +1230,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
if (!found) { if (!found) {
printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found" printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found"
" -> rcode_address_error\n"); " -> rcode_address_error\n");
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_ADDRESS_ERROR); return (RCODE_ADDRESS_ERROR);
} else { } else {
DBGMSG("arm_lock addr_entry FOUND"); DBGMSG("arm_lock addr_entry FOUND");
...@@ -1307,7 +1313,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, ...@@ -1307,7 +1313,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
req = __alloc_pending_request(SLAB_ATOMIC); req = __alloc_pending_request(SLAB_ATOMIC);
if (!req) { if (!req) {
DBGMSG("arm_lock -> rcode_conflict_error"); DBGMSG("arm_lock -> rcode_conflict_error");
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */ The request may be retried */
} }
...@@ -1316,7 +1322,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, ...@@ -1316,7 +1322,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
if (!(req->data)) { if (!(req->data)) {
free_pending_request(req); free_pending_request(req);
DBGMSG("arm_lock -> rcode_conflict_error"); DBGMSG("arm_lock -> rcode_conflict_error");
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */ The request may be retried */
} }
...@@ -1382,7 +1388,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, ...@@ -1382,7 +1388,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
sizeof(struct arm_response) + 2 * sizeof(*store)); sizeof(struct arm_response) + 2 * sizeof(*store));
queue_complete_req(req); queue_complete_req(req);
} }
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (rcode); return (rcode);
} }
...@@ -1390,6 +1396,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, ...@@ -1390,6 +1396,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags) u16 flags)
{ {
unsigned long irqflags;
struct pending_request *req; struct pending_request *req;
struct host_info *hi; struct host_info *hi;
struct file_info *fi = NULL; struct file_info *fi = NULL;
...@@ -1422,7 +1429,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, ...@@ -1422,7 +1429,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
(u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF), (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF),
(u32) (be64_to_cpu(arg) & 0xFFFFFFFF)); (u32) (be64_to_cpu(arg) & 0xFFFFFFFF));
} }
spin_lock(&host_info_lock); spin_lock_irqsave(&host_info_lock, irqflags);
hi = find_host_info(host); /* search addressentry in file_info's for host */ hi = find_host_info(host); /* search addressentry in file_info's for host */
if (hi != NULL) { if (hi != NULL) {
list_for_each_entry(fi, &hi->file_info_list, list) { 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,7 +1456,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
printk(KERN_ERR printk(KERN_ERR
"raw1394: arm_lock64 FAILED addr_entry not found" "raw1394: arm_lock64 FAILED addr_entry not found"
" -> rcode_address_error\n"); " -> rcode_address_error\n");
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (RCODE_ADDRESS_ERROR); return (RCODE_ADDRESS_ERROR);
} else { } else {
DBGMSG("arm_lock64 addr_entry FOUND"); DBGMSG("arm_lock64 addr_entry FOUND");
...@@ -1533,7 +1540,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, ...@@ -1533,7 +1540,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
DBGMSG("arm_lock64 -> entering notification-section"); DBGMSG("arm_lock64 -> entering notification-section");
req = __alloc_pending_request(SLAB_ATOMIC); req = __alloc_pending_request(SLAB_ATOMIC);
if (!req) { if (!req) {
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
DBGMSG("arm_lock64 -> rcode_conflict_error"); DBGMSG("arm_lock64 -> rcode_conflict_error");
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */ The request may be retried */
...@@ -1542,7 +1549,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, ...@@ -1542,7 +1549,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
req->data = kmalloc(size, SLAB_ATOMIC); req->data = kmalloc(size, SLAB_ATOMIC);
if (!(req->data)) { if (!(req->data)) {
free_pending_request(req); free_pending_request(req);
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
DBGMSG("arm_lock64 -> rcode_conflict_error"); DBGMSG("arm_lock64 -> rcode_conflict_error");
return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
The request may be retried */ The request may be retried */
...@@ -1609,7 +1616,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, ...@@ -1609,7 +1616,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
sizeof(struct arm_response) + 2 * sizeof(*store)); sizeof(struct arm_response) + 2 * sizeof(*store));
queue_complete_req(req); queue_complete_req(req);
} }
spin_unlock(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, irqflags);
return (rcode); return (rcode);
} }
...@@ -1980,6 +1987,7 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req) ...@@ -1980,6 +1987,7 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req)
struct hpsb_packet *packet = NULL; struct hpsb_packet *packet = NULL;
int retval = 0; int retval = 0;
quadlet_t data; quadlet_t data;
unsigned long flags;
data = be32_to_cpu((u32) req->req.sendb); data = be32_to_cpu((u32) req->req.sendb);
DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data); 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,9 +1998,9 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req)
req->packet = packet; req->packet = packet;
hpsb_set_packet_complete_task(packet, hpsb_set_packet_complete_task(packet,
(void (*)(void *))queue_complete_cb, req); (void (*)(void *))queue_complete_cb, req);
spin_lock_irq(&fi->reqlists_lock); spin_lock_irqsave(&fi->reqlists_lock, flags);
list_add_tail(&req->list, &fi->req_pending); list_add_tail(&req->list, &fi->req_pending);
spin_unlock_irq(&fi->reqlists_lock); spin_unlock_irqrestore(&fi->reqlists_lock, flags);
packet->generation = req->req.generation; packet->generation = req->req.generation;
retval = hpsb_send_packet(packet); retval = hpsb_send_packet(packet);
DBGMSG("write_phypacket send_packet called => retval: %d ", retval); 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,14 +2667,15 @@ static unsigned int raw1394_poll(struct file *file, poll_table * pt)
{ {
struct file_info *fi = file->private_data; struct file_info *fi = file->private_data;
unsigned int mask = POLLOUT | POLLWRNORM; unsigned int mask = POLLOUT | POLLWRNORM;
unsigned long flags;
poll_wait(file, &fi->poll_wait_complete, pt); poll_wait(file, &fi->poll_wait_complete, pt);
spin_lock_irq(&fi->reqlists_lock); spin_lock_irqsave(&fi->reqlists_lock, flags);
if (!list_empty(&fi->req_complete)) { if (!list_empty(&fi->req_complete)) {
mask |= POLLIN | POLLRDNORM; mask |= POLLIN | POLLRDNORM;
} }
spin_unlock_irq(&fi->reqlists_lock); spin_unlock_irqrestore(&fi->reqlists_lock, flags);
return mask; return mask;
} }
...@@ -2710,6 +2719,7 @@ static int raw1394_release(struct inode *inode, struct file *file) ...@@ -2710,6 +2719,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
struct arm_addr *arm_addr = NULL; struct arm_addr *arm_addr = NULL;
int another_host; int another_host;
int csr_mod = 0; int csr_mod = 0;
unsigned long flags;
if (fi->iso_state != RAW1394_ISO_INACTIVE) if (fi->iso_state != RAW1394_ISO_INACTIVE)
raw1394_iso_shutdown(fi); raw1394_iso_shutdown(fi);
...@@ -2720,13 +2730,11 @@ static int raw1394_release(struct inode *inode, struct file *file) ...@@ -2720,13 +2730,11 @@ static int raw1394_release(struct inode *inode, struct file *file)
} }
} }
spin_lock_irq(&host_info_lock); spin_lock_irqsave(&host_info_lock, flags);
fi->listen_channels = 0; fi->listen_channels = 0;
spin_unlock_irq(&host_info_lock);
fail = 0; fail = 0;
/* set address-entries invalid */ /* set address-entries invalid */
spin_lock_irq(&host_info_lock);
while (!list_empty(&fi->addr_list)) { while (!list_empty(&fi->addr_list)) {
another_host = 0; another_host = 0;
...@@ -2777,14 +2785,14 @@ static int raw1394_release(struct inode *inode, struct file *file) ...@@ -2777,14 +2785,14 @@ static int raw1394_release(struct inode *inode, struct file *file)
vfree(addr->addr_space_buffer); vfree(addr->addr_space_buffer);
kfree(addr); kfree(addr);
} /* while */ } /* while */
spin_unlock_irq(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, flags);
if (fail > 0) { if (fail > 0) {
printk(KERN_ERR "raw1394: during addr_list-release " printk(KERN_ERR "raw1394: during addr_list-release "
"error(s) occurred \n"); "error(s) occurred \n");
} }
while (!done) { while (!done) {
spin_lock_irq(&fi->reqlists_lock); spin_lock_irqsave(&fi->reqlists_lock, flags);
while (!list_empty(&fi->req_complete)) { while (!list_empty(&fi->req_complete)) {
lh = fi->req_complete.next; lh = fi->req_complete.next;
...@@ -2798,7 +2806,7 @@ static int raw1394_release(struct inode *inode, struct file *file) ...@@ -2798,7 +2806,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
if (list_empty(&fi->req_pending)) if (list_empty(&fi->req_pending))
done = 1; done = 1;
spin_unlock_irq(&fi->reqlists_lock); spin_unlock_irqrestore(&fi->reqlists_lock, flags);
if (!done) if (!done)
down_interruptible(&fi->complete_sem); down_interruptible(&fi->complete_sem);
...@@ -2828,9 +2836,9 @@ static int raw1394_release(struct inode *inode, struct file *file) ...@@ -2828,9 +2836,9 @@ static int raw1394_release(struct inode *inode, struct file *file)
fi->host->id); fi->host->id);
if (fi->state == connected) { if (fi->state == connected) {
spin_lock_irq(&host_info_lock); spin_lock_irqsave(&host_info_lock, flags);
list_del(&fi->list); list_del(&fi->list);
spin_unlock_irq(&host_info_lock); spin_unlock_irqrestore(&host_info_lock, flags);
put_device(&fi->host->device); put_device(&fi->host->device);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册