/** * 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); }
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; }
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); } }
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; }
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; }