static int r92su_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct r92su *r92su; int err; r92su = r92su_alloc(&intf->dev); if (IS_ERR(r92su)) return PTR_ERR(r92su); r92su->ep_num = intf->cur_altsetting->desc.bNumEndpoints; r92su->ep_map = ep_maps[r92su->ep_num]; if (!r92su->ep_map) { err = -EINVAL; goto err_out; } if (id->driver_info & DISABLE_HT) r92su->disable_ht = true; r92su_set_state(r92su, R92SU_PROBE); r92su->intf = intf; intf->needs_binding = 1; r92su->udev = interface_to_usbdev(intf); usb_set_intfdata(intf, r92su); init_usb_anchor(&r92su->rx_submitted); init_usb_anchor(&r92su->tx_submitted); init_usb_anchor(&r92su->tx_wait); err = r92su_usb_init(r92su); if (err) goto err_out; err = r92su_setup(r92su); if (err) goto err_out; err = r92su_register(r92su); if (err) goto err_out; return 0; err_out: r92su_unregister(r92su); r92su_free(r92su); return err; }
static void r92su_usb_disconnect(struct usb_interface *intf) { struct r92su *r92su = usb_get_intfdata(intf); struct urb *urb; r92su_unregister(r92su); /* give the disconnect command some time to finish... */ usb_wait_anchor_empty_timeout(&r92su->tx_submitted, USB_CTRL_SET_TIMEOUT); /* ... before everything is forcefully terminated */ usb_poison_anchored_urbs(&r92su->tx_submitted); usb_poison_anchored_urbs(&r92su->rx_submitted); while ((urb = usb_get_from_anchor(&r92su->tx_wait))) { kfree_skb(urb->context); usb_free_urb(urb); } r92su_free(r92su); }
struct r92su *r92su_alloc(struct device *main_dev) { struct r92su *r92su = NULL; struct wiphy *wiphy; int err; wiphy = wiphy_new(&r92su_cfg80211_ops, sizeof(struct r92su)); if (!wiphy) { err = -ENOMEM; goto err_out; } r92su = wiphy_priv(wiphy); r92su->wdev.wiphy = wiphy; mutex_init(&r92su->lock); spin_lock_init(&r92su->rx_path); if (modparam_noht) r92su->disable_ht = true; INIT_LIST_HEAD(&r92su->sta_list); /* Note: The sta_lock is only needed, if an entry in the * station list is updated. The station data itself is * protected by RCU. */ spin_lock_init(&r92su->sta_lock); set_wiphy_dev(r92su->wdev.wiphy, main_dev); r92su->wdev.iftype = NL80211_IFTYPE_STATION; wiphy->privid = r92su_priv_id; wiphy->mgmt_stypes = r92su_default_mgmt_stypes; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MONITOR); wiphy->max_scan_ssids = 1; wiphy->max_scan_ie_len = 256; wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; wiphy->cipher_suites = r92su_chiper_suites; wiphy->n_cipher_suites = ARRAY_SIZE(r92su_chiper_suites); wiphy->bss_priv_size = sizeof(struct r92su_bss_priv); init_completion(&r92su->scan_done); init_llist_head(&r92su->add_bss_list); INIT_WORK(&r92su->add_bss_work, r92su_bss_add_work); INIT_WORK(&r92su->connect_bss_work, r92su_bss_connect_work); INIT_WORK(&r92su->disconnect_work, r92su_disconnect_work); INIT_DELAYED_WORK(&r92su->survey_done_work, r92su_survey_done_work); r92su_hw_init(r92su); r92su->wq = create_singlethread_workqueue(R92SU_DRVNAME); if (!r92su->wq) { err = -ENOMEM; goto err_out; } return r92su; err_out: r92su_unregister(r92su); r92su_free(r92su); return ERR_PTR(err); }