/**
 * Clean up the radio control resources
 *
 * When we up the command semaphore, everybody possibly held trying to
 * execute a command should be granted entry and then they'll see the
 * host is quiescing and up it (so it will chain to the next waiter).
 * This should not happen (in any case), as we can only remove when
 * there are no handles open...
 */
static void whcrc_remove(struct umc_dev *umc_dev)
{
	struct whcrc *whcrc = umc_get_drvdata(umc_dev);
	struct uwb_rc *uwb_rc = whcrc->uwb_rc;

	umc_set_drvdata(umc_dev, NULL);
	uwb_rc_rm(uwb_rc);
	whcrc_release_rc_umc(whcrc);
	kfree(whcrc);
	uwb_rc_put(uwb_rc);
}
Example #2
0
static void i1480u_rm(struct i1480u *i1480u)
{
	struct uwb_rc *rc = i1480u->wlp.rc;
	usb_set_intfdata(i1480u->usb_iface, NULL);
#ifdef i1480u_FLOW_CONTROL
	usb_kill_urb(i1480u->notif_urb);
	usb_free_urb(i1480u->notif_urb);
#endif
	wlp_remove(&i1480u->wlp);
	uwb_rc_put(rc);
	usb_put_dev(i1480u->usb_dev);
}
/**
 * Initialize the radio controller.
 *
 * NOTE: we setup whcrc->uwb_rc before calling uwb_rc_add(); in the
 *       IRQ handler we use that to determine if the hw is ready to
 *       handle events. Looks like a race condition, but it really is
 *       not.
 */
static
int whcrc_probe(struct umc_dev *umc_dev)
{
	int result;
	struct uwb_rc *uwb_rc;
	struct whcrc *whcrc;
	struct device *dev = &umc_dev->dev;

	result = -ENOMEM;
	uwb_rc = uwb_rc_alloc();
	if (uwb_rc == NULL) {
		dev_err(dev, "unable to allocate RC instance\n");
		goto error_rc_alloc;
	}
	whcrc = kzalloc(sizeof(*whcrc), GFP_KERNEL);
	if (whcrc == NULL) {
		dev_err(dev, "unable to allocate WHC-RC instance\n");
		goto error_alloc;
	}
	whcrc_init(whcrc);
	whcrc->umc_dev = umc_dev;

	result = whcrc_setup_rc_umc(whcrc);
	if (result < 0) {
		dev_err(dev, "Can't setup RC UMC interface: %d\n", result);
		goto error_setup_rc_umc;
	}
	whcrc->uwb_rc = uwb_rc;

	uwb_rc->owner = THIS_MODULE;
	uwb_rc->cmd   = whcrc_cmd;
	uwb_rc->reset = whcrc_reset;
	uwb_rc->start = whcrc_start_rc;
	uwb_rc->stop  = whcrc_stop_rc;

	result = uwb_rc_add(uwb_rc, dev, whcrc);
	if (result < 0)
		goto error_rc_add;
	umc_set_drvdata(umc_dev, whcrc);
	return 0;

error_rc_add:
	whcrc_release_rc_umc(whcrc);
error_setup_rc_umc:
	kfree(whcrc);
error_alloc:
	uwb_rc_put(uwb_rc);
error_rc_alloc:
	return result;
}
Example #4
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);
	}
}
Example #5
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;
}
Example #6
0
static
int i1480u_add(struct i1480u *i1480u, struct usb_interface *iface)
{
	int result = -ENODEV;
	struct wlp *wlp = &i1480u->wlp;
	struct usb_device *usb_dev = interface_to_usbdev(iface);
	struct net_device *net_dev = i1480u->net_dev;
	struct uwb_rc *rc;
	struct uwb_dev *uwb_dev;
#ifdef i1480u_FLOW_CONTROL
	struct usb_endpoint_descriptor *epd;
#endif

	i1480u->usb_dev = usb_get_dev(usb_dev);
	i1480u->usb_iface = iface;
	rc = uwb_rc_get_by_grandpa(&i1480u->usb_dev->dev);
	if (rc == NULL) {
		dev_err(&iface->dev, "Cannot get associated UWB Radio "
			"Controller\n");
		goto out;
	}
	wlp->xmit_frame = i1480u_xmit_frame;
	wlp->fill_device_info = i1480u_fill_device_info;
	wlp->stop_queue = i1480u_stop_queue;
	wlp->start_queue = i1480u_start_queue;
	result = wlp_setup(wlp, rc, net_dev);
	if (result < 0) {
		dev_err(&iface->dev, "Cannot setup WLP\n");
		goto error_wlp_setup;
	}
	result = 0;
	ether_setup(net_dev);			/* make it an etherdevice */
	uwb_dev = &rc->uwb_dev;
	/* FIXME: hookup address change notifications? */

	memcpy(net_dev->dev_addr, uwb_dev->mac_addr.data,
	       sizeof(net_dev->dev_addr));

	net_dev->hard_header_len = sizeof(struct untd_hdr_cmp)
		+ sizeof(struct wlp_tx_hdr)
		+ WLP_DATA_HLEN
		+ ETH_HLEN;
	net_dev->mtu = 3500;
	net_dev->tx_queue_len = 20;		/* FIXME: maybe use 1000? */

/*	net_dev->flags &= ~IFF_BROADCAST;	FIXME: BUG in firmware */
	/* FIXME: multicast disabled */
	net_dev->flags &= ~IFF_MULTICAST;
	net_dev->features &= ~NETIF_F_SG;
	net_dev->features &= ~NETIF_F_FRAGLIST;
	/* All NETIF_F_*_CSUM disabled */
	net_dev->features |= NETIF_F_HIGHDMA;
	net_dev->watchdog_timeo = 5*HZ;		/* FIXME: a better default? */

	net_dev->netdev_ops = &i1480u_netdev_ops;

#ifdef i1480u_FLOW_CONTROL
	/* Notification endpoint setup (submitted when we open the device) */
	i1480u->notif_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (i1480u->notif_urb == NULL) {
		dev_err(&iface->dev, "Unable to allocate notification URB\n");
		result = -ENOMEM;
		goto error_urb_alloc;
	}
	epd = &iface->cur_altsetting->endpoint[0].desc;
	usb_fill_int_urb(i1480u->notif_urb, usb_dev,
			 usb_rcvintpipe(usb_dev, epd->bEndpointAddress),
			 i1480u->notif_buffer, sizeof(i1480u->notif_buffer),
			 i1480u_notif_cb, i1480u, epd->bInterval);

#endif

	i1480u->tx_inflight.max = i1480u_TX_INFLIGHT_MAX;
	i1480u->tx_inflight.threshold = i1480u_TX_INFLIGHT_THRESHOLD;
	i1480u->tx_inflight.restart_ts = jiffies;
	usb_set_intfdata(iface, i1480u);
	return result;

#ifdef i1480u_FLOW_CONTROL
error_urb_alloc:
#endif
	wlp_remove(wlp);
error_wlp_setup:
	uwb_rc_put(rc);
out:
	usb_put_dev(i1480u->usb_dev);
	return result;
}