--- x/drivers/bluetooth/hci_ldisc.c +++ y/drivers/bluetooth/hci_ldisc.c @@ -100,13 +100,9 @@ static inline struct sk_buff *hci_uart_d struct sk_buff *skb = hu->tx_skb; if (!skb) { - percpu_down_read(&hu->proto_lock); - if (test_bit(HCI_UART_PROTO_READY, &hu->flags) || test_bit(HCI_UART_PROTO_INIT, &hu->flags)) skb = hu->proto->dequeue(hu); - - percpu_up_read(&hu->proto_lock); } else { hu->tx_skb = NULL; } @@ -154,6 +150,11 @@ static void hci_uart_write_work(struct w /* REVISIT: should we cope with bad skbs or ->write() returning * and error value ? */ + percpu_down_read(&hu->proto_lock); + if (!test_bit(HCI_UART_PROTO_READY, &hu->flags)) { + percpu_up_read(&hu->proto_lock); + return; + } restart: clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); @@ -179,6 +180,7 @@ restart: if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)) goto restart; + percpu_up_read(&hu->proto_lock); wake_up_bit(&hu->tx_state, HCI_UART_SENDING); } @@ -231,9 +233,12 @@ static int hci_uart_flush(struct hci_dev BT_DBG("hdev %p tty %p", hdev, tty); + percpu_down_write(&hu->proto_lock); if (hu->tx_skb) { - kfree_skb(hu->tx_skb); hu->tx_skb = NULL; + kfree_skb(hu->tx_skb); + hu->tx_skb = NULL; } + percpu_up_write(&hu->proto_lock); /* Flush any pending characters in the driver and discipline. */ tty_ldisc_flush(tty);