goto done;
        }
 
+       if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+               err = -EOPNOTSUPP;
+               goto done;
+       }
+
        if (hdev->dev_type != HCI_BREDR) {
                err = -EOPNOTSUPP;
                goto done;
                ret = hdev->setup(hdev);
 
        if (!ret) {
-               if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
-                       set_bit(HCI_RAW, &hdev->flags);
-
-               if (!test_bit(HCI_RAW, &hdev->flags) &&
+               if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks) &&
                    !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
                        ret = __hci_init(hdev);
        }
                }
 
                hdev->close(hdev);
-               hdev->flags = 0;
+               hdev->flags &= BIT(HCI_RAW);
        }
 
 done:
        if (!hdev)
                return -ENODEV;
 
+       /* Devices that are marked for raw-only usage can only be powered
+        * up as user channel. Trying to bring them up as normal devices
+        * will result into a failure. Only user channel operation is
+        * possible.
+        *
+        * When this function is called for a user channel, the flag
+        * HCI_USER_CHANNEL will be set first before attempting to
+        * open the device.
+        */
+       if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks) &&
+           !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+               err = -EOPNOTSUPP;
+               goto done;
+       }
+
        /* We need to ensure that no other power on/off work is pending
         * before proceeding to call hci_dev_do_open. This is
         * particularly important if the setup procedure has not yet
 
        err = hci_dev_do_open(hdev);
 
+done:
        hci_dev_put(hdev);
-
        return err;
 }
 
        /* Reset device */
        skb_queue_purge(&hdev->cmd_q);
        atomic_set(&hdev->cmd_cnt, 1);
-       if (!test_bit(HCI_RAW, &hdev->flags) &&
+       if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks) &&
            !test_bit(HCI_AUTO_OFF, &hdev->dev_flags) &&
            test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) {
                set_bit(HCI_INIT, &hdev->flags);
        hdev->close(hdev);
 
        /* Clear flags */
-       hdev->flags = 0;
+       hdev->flags &= BIT(HCI_RAW);
        hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
 
        if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
                goto done;
        }
 
+       if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+               ret = -EOPNOTSUPP;
+               goto done;
+       }
+
        /* Drop queues */
        skb_queue_purge(&hdev->rx_q);
        skb_queue_purge(&hdev->cmd_q);
        atomic_set(&hdev->cmd_cnt, 1);
        hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0;
 
-       if (!test_bit(HCI_RAW, &hdev->flags))
-               ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT);
+       ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT);
 
 done:
        hci_req_unlock(hdev);
                goto done;
        }
 
+       if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+               ret = -EOPNOTSUPP;
+               goto done;
+       }
+
        memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
 
 done:
                goto done;
        }
 
+       if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+               err = -EOPNOTSUPP;
+               goto done;
+       }
+
        if (hdev->dev_type != HCI_BREDR) {
                err = -EOPNOTSUPP;
                goto done;
                                   HCI_AUTO_OFF_TIMEOUT);
        }
 
-       if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags))
-               mgmt_index_added(hdev);
+       if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags)) {
+               if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+                       mgmt_index_added(hdev);
+       }
 }
 
 static void hci_power_off(struct work_struct *work)
        list_add(&hdev->list, &hci_dev_list);
        write_unlock(&hci_dev_list_lock);
 
+       /* Devices that are marked for raw-only usage need to set
+        * the HCI_RAW flag to indicate that only user channel is
+        * supported.
+        */
+       if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+               set_bit(HCI_RAW, &hdev->flags);
+
        hci_notify(hdev, HCI_DEV_REG);
        hci_dev_hold(hdev);
 
        cancel_work_sync(&hdev->power_on);
 
        if (!test_bit(HCI_INIT, &hdev->flags) &&
-           !test_bit(HCI_SETUP, &hdev->dev_flags)) {
+           !test_bit(HCI_SETUP, &hdev->dev_flags) &&
+           !test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
                hci_dev_lock(hdev);
                mgmt_index_removed(hdev);
                hci_dev_unlock(hdev);
 
 static void __check_timeout(struct hci_dev *hdev, unsigned int cnt)
 {
-       if (!test_bit(HCI_RAW, &hdev->flags)) {
+       if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
                /* ACL tx timeout must be longer than maximum
                 * link supervision timeout (40.9 seconds) */
                if (!cnt && time_after(jiffies, hdev->acl_last_tx +
        if (!hci_conn_num(hdev, LE_LINK))
                return;
 
-       if (!test_bit(HCI_RAW, &hdev->flags)) {
+       if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
                /* LE tx timeout must be longer than maximum
                 * link supervision timeout (40.9 seconds) */
                if (!hdev->le_cnt && hdev->le_pkts &&
                        hci_send_to_sock(hdev, skb);
                }
 
-               if (test_bit(HCI_RAW, &hdev->flags) ||
-                   test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+               if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
                        kfree_skb(skb);
                        continue;
                }
 
 
        if (hdev) {
                if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
-                       mgmt_index_added(hdev);
+                       if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+                               mgmt_index_added(hdev);
                        clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags);
                        hci_dev_close(hdev->id);
                }
        if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
                return -EBUSY;
 
+       if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+               return -EOPNOTSUPP;
+
        if (hdev->dev_type != HCI_BREDR)
                return -EOPNOTSUPP;
 
                        goto done;
                }
 
-               mgmt_index_removed(hdev);
+               if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+                       mgmt_index_removed(hdev);
 
                err = hci_dev_open(hdev->id);
                if (err) {
                        clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags);
-                       mgmt_index_added(hdev);
+                       if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+                               mgmt_index_added(hdev);
                        hci_dev_put(hdev);
                        goto done;
                }
                        goto drop;
                }
 
-               if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) {
+               if (ogf == 0x3f) {
                        skb_queue_tail(&hdev->raw_q, skb);
                        queue_work(hdev->workqueue, &hdev->tx_work);
                } else {