示例#1
0
static void whc_remove(struct umc_dev *umc)
{
	struct usb_hcd *usb_hcd = dev_get_drvdata(&umc->dev);
	struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
	struct whc *whc = wusbhc_to_whc(wusbhc);

	if (usb_hcd) {
		whc_dbg_clean_up(whc);
		wusbhc_b_destroy(wusbhc);
		usb_remove_hcd(usb_hcd);
		wusbhc_destroy(wusbhc);
		uwb_rc_put(wusbhc->uwb_rc);
		whc_clean_up(whc);
		usb_put_hcd(usb_hcd);
	}
}
示例#2
0
文件: init.c 项目: AlexShiLucky/linux
int whc_init(struct whc *whc)
{
	u32 whcsparams;
	int ret, i;
	resource_size_t start, len;

	spin_lock_init(&whc->lock);
	mutex_init(&whc->mutex);
	init_waitqueue_head(&whc->cmd_wq);
	init_waitqueue_head(&whc->async_list_wq);
	init_waitqueue_head(&whc->periodic_list_wq);
	whc->workqueue = alloc_ordered_workqueue(dev_name(&whc->umc->dev), 0);
	if (whc->workqueue == NULL) {
		ret = -ENOMEM;
		goto error;
	}
	INIT_WORK(&whc->dn_work, whc_dn_work);

	INIT_WORK(&whc->async_work, scan_async_work);
	INIT_LIST_HEAD(&whc->async_list);
	INIT_LIST_HEAD(&whc->async_removed_list);

	INIT_WORK(&whc->periodic_work, scan_periodic_work);
	for (i = 0; i < 5; i++)
		INIT_LIST_HEAD(&whc->periodic_list[i]);
	INIT_LIST_HEAD(&whc->periodic_removed_list);

	/* Map HC registers. */
	start = whc->umc->resource.start;
	len   = whc->umc->resource.end - start + 1;
	if (!request_mem_region(start, len, "whci-hc")) {
		dev_err(&whc->umc->dev, "can't request HC region\n");
		ret = -EBUSY;
		goto error;
	}
	whc->base_phys = start;
	whc->base = ioremap(start, len);
	if (!whc->base) {
		dev_err(&whc->umc->dev, "ioremap\n");
		ret = -ENOMEM;
		goto error;
	}

	whc_hw_reset(whc);

	/* Read maximum number of devices, keys and MMC IEs. */
	whcsparams = le_readl(whc->base + WHCSPARAMS);
	whc->n_devices = WHCSPARAMS_TO_N_DEVICES(whcsparams);
	whc->n_keys    = WHCSPARAMS_TO_N_KEYS(whcsparams);
	whc->n_mmc_ies = WHCSPARAMS_TO_N_MMC_IES(whcsparams);

	dev_dbg(&whc->umc->dev, "N_DEVICES = %d, N_KEYS = %d, N_MMC_IES = %d\n",
		whc->n_devices, whc->n_keys, whc->n_mmc_ies);

	whc->qset_pool = dma_pool_create("qset", &whc->umc->dev,
					 sizeof(struct whc_qset), 64, 0);
	if (whc->qset_pool == NULL) {
		ret = -ENOMEM;
		goto error;
	}

	ret = asl_init(whc);
	if (ret < 0)
		goto error;
	ret = pzl_init(whc);
	if (ret < 0)
		goto error;

	/* Allocate and initialize a buffer for generic commands, the
	   Device Information buffer, and the Device Notification
	   buffer. */

	whc->gen_cmd_buf = dma_alloc_coherent(&whc->umc->dev, WHC_GEN_CMD_DATA_LEN,
					      &whc->gen_cmd_buf_dma, GFP_KERNEL);
	if (whc->gen_cmd_buf == NULL) {
		ret = -ENOMEM;
		goto error;
	}

	whc->dn_buf = dma_alloc_coherent(&whc->umc->dev,
					 sizeof(struct dn_buf_entry) * WHC_N_DN_ENTRIES,
					 &whc->dn_buf_dma, GFP_KERNEL);
	if (!whc->dn_buf) {
		ret = -ENOMEM;
		goto error;
	}
	whc_hw_init_dn_buf(whc);

	whc->di_buf = dma_alloc_coherent(&whc->umc->dev,
					 sizeof(struct di_buf_entry) * whc->n_devices,
					 &whc->di_buf_dma, GFP_KERNEL);
	if (!whc->di_buf) {
		ret = -ENOMEM;
		goto error;
	}
	whc_hw_init_di_buf(whc);

	return 0;

error:
	whc_clean_up(whc);
	return ret;
}
示例#3
0
static int whc_probe(struct umc_dev *umc)
{
	int ret = -ENOMEM;
	struct usb_hcd *usb_hcd;
	struct wusbhc *wusbhc = NULL;
	struct whc *whc = NULL;
	struct device *dev = &umc->dev;

	usb_hcd = usb_create_hcd(&whc_hc_driver, dev, "whci");
	if (usb_hcd == NULL) {
		dev_err(dev, "unable to create hcd\n");
		goto error;
	}

	usb_hcd->wireless = 1;
	usb_hcd->self.sg_tablesize = 2048; /* somewhat arbitrary */

	wusbhc = usb_hcd_to_wusbhc(usb_hcd);
	whc = wusbhc_to_whc(wusbhc);
	whc->umc = umc;

	ret = whc_init(whc);
	if (ret)
		goto error;

	wusbhc->dev = dev;
	wusbhc->uwb_rc = uwb_rc_get_by_grandpa(umc->dev.parent);
	if (!wusbhc->uwb_rc) {
		ret = -ENODEV;
		dev_err(dev, "cannot get radio controller\n");
		goto error;
	}

	if (whc->n_devices > USB_MAXCHILDREN) {
		dev_warn(dev, "USB_MAXCHILDREN too low for WUSB adapter (%u ports)\n",
			 whc->n_devices);
		wusbhc->ports_max = USB_MAXCHILDREN;
	} else
		wusbhc->ports_max = whc->n_devices;
	wusbhc->mmcies_max      = whc->n_mmc_ies;
	wusbhc->start           = whc_wusbhc_start;
	wusbhc->stop            = whc_wusbhc_stop;
	wusbhc->mmcie_add       = whc_mmcie_add;
	wusbhc->mmcie_rm        = whc_mmcie_rm;
	wusbhc->dev_info_set    = whc_dev_info_set;
	wusbhc->bwa_set         = whc_bwa_set;
	wusbhc->set_num_dnts    = whc_set_num_dnts;
	wusbhc->set_ptk         = whc_set_ptk;
	wusbhc->set_gtk         = whc_set_gtk;

	ret = wusbhc_create(wusbhc);
	if (ret)
		goto error_wusbhc_create;

	ret = usb_add_hcd(usb_hcd, whc->umc->irq, IRQF_SHARED);
	if (ret) {
		dev_err(dev, "cannot add HCD: %d\n", ret);
		goto error_usb_add_hcd;
	}

	ret = wusbhc_b_create(wusbhc);
	if (ret) {
		dev_err(dev, "WUSBHC phase B setup failed: %d\n", ret);
		goto error_wusbhc_b_create;
	}

	whc_dbg_init(whc);

	return 0;

error_wusbhc_b_create:
	usb_remove_hcd(usb_hcd);
error_usb_add_hcd:
	wusbhc_destroy(wusbhc);
error_wusbhc_create:
	uwb_rc_put(wusbhc->uwb_rc);
error:
	whc_clean_up(whc);
	if (usb_hcd)
		usb_put_hcd(usb_hcd);
	return ret;
}