static void ln_rwsem_setup(unsigned buckets) { int lock; locks = (struct percpu_rw_semaphore *) vmalloc(sizeof(struct percpu_rw_semaphore) * buckets); for (lock = 0; lock < buckets; lock++) percpu_init_rwsem(&locks[lock]); return; }
int hci_uart_register_device(struct hci_uart *hu, const struct hci_uart_proto *p) { int err; struct hci_dev *hdev; BT_DBG(""); serdev_device_set_client_ops(hu->serdev, &hci_serdev_client_ops); err = serdev_device_open(hu->serdev); if (err) return err; err = p->open(hu); if (err) goto err_open; hu->proto = p; set_bit(HCI_UART_PROTO_READY, &hu->flags); /* Initialize and register HCI device */ hdev = hci_alloc_dev(); if (!hdev) { BT_ERR("Can't allocate HCI device"); err = -ENOMEM; goto err_alloc; } hu->hdev = hdev; hdev->bus = HCI_UART; hci_set_drvdata(hdev, hu); INIT_WORK(&hu->init_ready, hci_uart_init_work); INIT_WORK(&hu->write_work, hci_uart_write_work); percpu_init_rwsem(&hu->proto_lock); /* Only when vendor specific setup callback is provided, consider * the manufacturer information valid. This avoids filling in the * value for Ericsson when nothing is specified. */ if (hu->proto->setup) hdev->manufacturer = hu->proto->manufacturer; hdev->open = hci_uart_open; hdev->close = hci_uart_close; hdev->flush = hci_uart_flush; hdev->send = hci_uart_send_frame; hdev->setup = hci_uart_setup; SET_HCIDEV_DEV(hdev, &hu->serdev->dev); if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags)) set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags)) hdev->dev_type = HCI_AMP; else hdev->dev_type = HCI_PRIMARY; if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags)) return 0; if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); err = -ENODEV; goto err_register; } set_bit(HCI_UART_REGISTERED, &hu->flags); return 0; err_register: hci_free_dev(hdev); err_alloc: clear_bit(HCI_UART_PROTO_READY, &hu->flags); p->close(hu); err_open: serdev_device_close(hu->serdev); return err; }