From b78752cc71d86998d3b77d873c61d6ffdb7a2142 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 8 Aug 2010 23:06:53 -0400 Subject: [PATCH] Bluetooth: Process recv path in a workqueue instead of a tasklet Run recv process in workqueue helps a lot with our processing as the recv path will also be in the process context, i.e., now all our tx and rx are in process context. Signed-off-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 3 ++- net/bluetooth/hci_core.c | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 6a1ac2c2489c..1e28be45c4f2 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -194,8 +194,9 @@ struct hci_dev { struct delayed_work discov_off; struct timer_list cmd_timer; + + struct work_struct rx_work; struct tasklet_struct cmd_task; - struct tasklet_struct rx_task; struct tasklet_struct tx_task; struct sk_buff_head rx_q; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 700d0abdf2b1..4f15722c56dc 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -56,8 +56,8 @@ int enable_hs; +static void hci_rx_work(struct work_struct *work); static void hci_cmd_task(unsigned long arg); -static void hci_rx_task(unsigned long arg); static void hci_tx_task(unsigned long arg); static DEFINE_RWLOCK(hci_task_lock); @@ -547,9 +547,9 @@ int hci_dev_open(__u16 dev) } } else { /* Init failed, cleanup */ - tasklet_kill(&hdev->rx_task); tasklet_kill(&hdev->tx_task); tasklet_kill(&hdev->cmd_task); + flush_work(&hdev->rx_work); skb_queue_purge(&hdev->cmd_q); skb_queue_purge(&hdev->rx_q); @@ -586,8 +586,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) } /* Kill RX and TX tasks */ - tasklet_kill(&hdev->rx_task); tasklet_kill(&hdev->tx_task); + flush_work(&hdev->rx_work); if (hdev->discov_timeout > 0) { cancel_delayed_work(&hdev->discov_off); @@ -1456,8 +1456,9 @@ int hci_register_dev(struct hci_dev *hdev) hdev->sniff_max_interval = 800; hdev->sniff_min_interval = 80; - tasklet_init(&hdev->cmd_task, hci_cmd_task, (unsigned long) hdev); - tasklet_init(&hdev->rx_task, hci_rx_task, (unsigned long) hdev); + INIT_WORK(&hdev->rx_work, hci_rx_work); + + tasklet_init(&hdev->cmd_task, hci_cmd_task,(unsigned long) hdev); tasklet_init(&hdev->tx_task, hci_tx_task, (unsigned long) hdev); skb_queue_head_init(&hdev->rx_q); @@ -1623,9 +1624,8 @@ int hci_recv_frame(struct sk_buff *skb) /* Time stamp */ __net_timestamp(skb); - /* Queue frame for rx task */ skb_queue_tail(&hdev->rx_q, skb); - tasklet_schedule(&hdev->rx_task); + queue_work(hdev->workqueue, &hdev->rx_work); return 0; } @@ -2486,9 +2486,9 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) kfree_skb(skb); } -static void hci_rx_task(unsigned long arg) +static void hci_rx_work(struct work_struct *work) { - struct hci_dev *hdev = (struct hci_dev *) arg; + struct hci_dev *hdev = container_of(work, struct hci_dev, rx_work); struct sk_buff *skb; BT_DBG("%s", hdev->name); @@ -2519,6 +2519,7 @@ static void hci_rx_task(unsigned long arg) /* Process frame */ switch (bt_cb(skb)->pkt_type) { case HCI_EVENT_PKT: + BT_DBG("%s Event packet", hdev->name); hci_event_packet(hdev, skb); break;