]> git.neil.brown.name Git - history.git/commitdiff
[Bluetooth] Fix deadlock in the 3Com driver
authorMarcel Holtmann <marcel@holtmann.org>
Sun, 4 Jul 2004 16:46:07 +0000 (18:46 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Sun, 4 Jul 2004 16:46:07 +0000 (18:46 +0200)
This patch fixes the deadlock problem when bt3c_interrupt() is calling
bt3c_write_wakeup() with info->lock held.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
drivers/bluetooth/bt3c_cs.c

index 5aa5cd3a2e25a5fb2268806942399e270b10cd49..e298846835ef03873bd7519b44462509f71c00b9 100644 (file)
@@ -194,10 +194,8 @@ static int bt3c_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
 }
 
 
-static void bt3c_write_wakeup(bt3c_info_t *info, int from)
+static void bt3c_write_wakeup(bt3c_info_t *info)
 {
-       unsigned long flags;
-
        if (!info) {
                BT_ERR("Unknown device");
                return;
@@ -206,8 +204,6 @@ static void bt3c_write_wakeup(bt3c_info_t *info, int from)
        if (test_and_set_bit(XMIT_SENDING, &(info->tx_state)))
                return;
 
-       spin_lock_irqsave(&(info->lock), flags);
-
        do {
                register unsigned int iobase = info->link.io.BasePort1;
                register struct sk_buff *skb;
@@ -234,8 +230,6 @@ static void bt3c_write_wakeup(bt3c_info_t *info, int from)
                info->hdev->stat.byte_tx += len;
 
        } while (0);
-
-       spin_unlock_irqrestore(&(info->lock), flags);
 }
 
 
@@ -391,7 +385,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
                        if (stat & 0x0002) {
                                //BT_ERR("Ack (stat=0x%04x)", stat);
                                clear_bit(XMIT_SENDING, &(info->tx_state));
-                               bt3c_write_wakeup(info, 1);
+                               bt3c_write_wakeup(info);
                        }
 
                        bt3c_io_write(iobase, 0x7001, 0x0000);
@@ -444,6 +438,7 @@ static int bt3c_hci_send_frame(struct sk_buff *skb)
 {
        bt3c_info_t *info;
        struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
+       unsigned long flags;
 
        if (!hdev) {
                BT_ERR("Frame for unknown HCI device (hdev=NULL)");
@@ -468,7 +463,11 @@ static int bt3c_hci_send_frame(struct sk_buff *skb)
        memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
        skb_queue_tail(&(info->txq), skb);
 
-       bt3c_write_wakeup(info, 0);
+       spin_lock_irqsave(&(info->lock), flags);
+
+       bt3c_write_wakeup(info);
+
+       spin_unlock_irqrestore(&(info->lock), flags);
 
        return 0;
 }