Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / drivers / net / wireless / rtlwifi / usb.c
index e7a7ea9..a6049d7 100644 (file)
@@ -124,46 +124,38 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
        return status;
 }
 
-static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len)
+static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len)
 {
+       struct device *dev = rtlpriv->io.dev;
+       struct usb_device *udev = to_usb_device(dev);
        u8 request;
        u16 wvalue;
        u16 index;
-       u32 *data;
-       u32 ret;
+       __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index];
 
-       data = kmalloc(sizeof(u32), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
        request = REALTEK_USB_VENQT_CMD_REQ;
        index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
 
        wvalue = (u16)addr;
        _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len);
-       ret = le32_to_cpu(*data);
-       kfree(data);
-       return ret;
+       if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT)
+               rtlpriv->usb_data_index = 0;
+       return le32_to_cpu(*data);
 }
 
 static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-       struct device *dev = rtlpriv->io.dev;
-
-       return (u8)_usb_read_sync(to_usb_device(dev), addr, 1);
+       return (u8)_usb_read_sync(rtlpriv, addr, 1);
 }
 
 static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-       struct device *dev = rtlpriv->io.dev;
-
-       return (u16)_usb_read_sync(to_usb_device(dev), addr, 2);
+       return (u16)_usb_read_sync(rtlpriv, addr, 2);
 }
 
 static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-       struct device *dev = rtlpriv->io.dev;
-
-       return _usb_read_sync(to_usb_device(dev), addr, 4);
+       return _usb_read_sync(rtlpriv, addr, 4);
 }
 
 static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val,
@@ -346,9 +338,14 @@ static int _rtl_usb_init(struct ieee80211_hw *hw)
                         pep_desc->bEndpointAddress, pep_desc->wMaxPacketSize,
                         pep_desc->bInterval);
        }
-       if (rtlusb->in_ep_nums <  rtlpriv->cfg->usb_interface_cfg->in_ep_num)
-               return -EINVAL ;
-
+       if (rtlusb->in_ep_nums <  rtlpriv->cfg->usb_interface_cfg->in_ep_num) {
+               pr_err("Too few input end points found\n");
+               return -EINVAL;
+       }
+       if (rtlusb->out_ep_nums == 0) {
+               pr_err("No output end points found\n");
+               return -EINVAL;
+       }
        /* usb endpoint mapping */
        err = rtlpriv->cfg->usb_interface_cfg->usb_endpoint_mapping(hw);
        rtlusb->usb_mq_to_hwq =  rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq;
@@ -357,7 +354,7 @@ static int _rtl_usb_init(struct ieee80211_hw *hw)
        return err;
 }
 
-static int _rtl_usb_init_sw(struct ieee80211_hw *hw)
+static void rtl_usb_init_sw(struct ieee80211_hw *hw)
 {
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -392,7 +389,6 @@ static int _rtl_usb_init_sw(struct ieee80211_hw *hw)
        /* HIMR_EX - turn all on */
        rtlusb->irq_mask[1] = 0xFFFFFFFF;
        rtlusb->disableHWSM =  true;
-       return 0;
 }
 
 #define __RADIO_TAP_SIZE_RSV   32
@@ -664,15 +660,17 @@ static int rtl_usb_start(struct ieee80211_hw *hw)
        struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
 
        err = rtlpriv->cfg->ops->hw_init(hw);
-       rtl_init_rx_config(hw);
+       if (!err) {
+               rtl_init_rx_config(hw);
 
-       /* Enable software */
-       SET_USB_START(rtlusb);
-       /* should after adapter start and interrupt enable. */
-       set_hal_start(rtlhal);
+               /* Enable software */
+               SET_USB_START(rtlusb);
+               /* should after adapter start and interrupt enable. */
+               set_hal_start(rtlhal);
 
-       /* Start bulk IN */
-       _rtl_usb_receive(hw);
+               /* Start bulk IN */
+               _rtl_usb_receive(hw);
+       }
 
        return err;
 }
@@ -949,6 +947,12 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
                return -ENOMEM;
        }
        rtlpriv = hw->priv;
+       rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32),
+                                   GFP_KERNEL);
+       if (!rtlpriv->usb_data)
+               return -ENOMEM;
+       rtlpriv->usb_data_index = 0;
+       init_completion(&rtlpriv->firmware_loading_complete);
        SET_IEEE80211_DEV(hw, &intf->dev);
        udev = interface_to_usbdev(intf);
        usb_get_dev(udev);
@@ -967,13 +971,10 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
        rtlpriv->cfg->ops->read_chip_version(hw);
        /*like read eeprom and so on */
        rtlpriv->cfg->ops->read_eeprom_info(hw);
-       if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
-               RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
-               goto error_out;
-       }
-       rtlpriv->cfg->ops->init_sw_leds(hw);
        err = _rtl_usb_init(hw);
-       err = _rtl_usb_init_sw(hw);
+       if (err)
+               goto error_out;
+       rtl_usb_init_sw(hw);
        /* Init mac80211 sw */
        err = rtl_init_core(hw);
        if (err) {
@@ -981,25 +982,18 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
                         "Can't allocate sw for mac80211\n");
                goto error_out;
        }
-
-       /*init rfkill */
-       /* rtl_init_rfkill(hw); */
-
-       err = ieee80211_register_hw(hw);
-       if (err) {
-               RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
-                        "Can't register mac80211 hw\n");
+       if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
                goto error_out;
-       } else {
-               rtlpriv->mac80211.mac80211_registered = 1;
        }
-       set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
+       rtlpriv->cfg->ops->init_sw_leds(hw);
+
        return 0;
 error_out:
        rtl_deinit_core(hw);
        _rtl_usb_io_handler_release(hw);
-       ieee80211_free_hw(hw);
        usb_put_dev(udev);
+       complete(&rtlpriv->firmware_loading_complete);
        return -ENODEV;
 }
 EXPORT_SYMBOL(rtl_usb_probe);
@@ -1013,6 +1007,9 @@ void rtl_usb_disconnect(struct usb_interface *intf)
 
        if (unlikely(!rtlpriv))
                return;
+
+       /* just in case driver is removed before firmware callback */
+       wait_for_completion(&rtlpriv->firmware_loading_complete);
        /*ieee80211_unregister_hw will call ops_stop */
        if (rtlmac->mac80211_registered == 1) {
                ieee80211_unregister_hw(hw);
@@ -1025,6 +1022,7 @@ void rtl_usb_disconnect(struct usb_interface *intf)
        /* rtl_deinit_rfkill(hw); */
        rtl_usb_deinit(hw);
        rtl_deinit_core(hw);
+       kfree(rtlpriv->usb_data);
        rtlpriv->cfg->ops->deinit_sw_leds(hw);
        rtlpriv->cfg->ops->deinit_sw_vars(hw);
        _rtl_usb_io_handler_release(hw);