diff options
Diffstat (limited to 'drivers/net/wireless/rtlwifi/usb.c')
| -rw-r--r-- | drivers/net/wireless/rtlwifi/usb.c | 54 |
1 files changed, 32 insertions, 22 deletions
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 1535efda3d52..5847d6d0881e 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
| @@ -42,8 +42,12 @@ | |||
| 42 | 42 | ||
| 43 | static void usbctrl_async_callback(struct urb *urb) | 43 | static void usbctrl_async_callback(struct urb *urb) |
| 44 | { | 44 | { |
| 45 | if (urb) | 45 | if (urb) { |
| 46 | kfree(urb->context); | 46 | /* free dr */ |
| 47 | kfree(urb->setup_packet); | ||
| 48 | /* free databuf */ | ||
| 49 | kfree(urb->transfer_buffer); | ||
| 50 | } | ||
| 47 | } | 51 | } |
| 48 | 52 | ||
| 49 | static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, | 53 | static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, |
| @@ -55,39 +59,47 @@ static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, | |||
| 55 | u8 reqtype; | 59 | u8 reqtype; |
| 56 | struct usb_ctrlrequest *dr; | 60 | struct usb_ctrlrequest *dr; |
| 57 | struct urb *urb; | 61 | struct urb *urb; |
| 58 | struct rtl819x_async_write_data { | 62 | const u16 databuf_maxlen = REALTEK_USB_VENQT_MAX_BUF_SIZE; |
| 59 | u8 data[REALTEK_USB_VENQT_MAX_BUF_SIZE]; | 63 | u8 *databuf; |
| 60 | struct usb_ctrlrequest dr; | 64 | |
| 61 | } *buf; | 65 | if (WARN_ON_ONCE(len > databuf_maxlen)) |
| 66 | len = databuf_maxlen; | ||
| 62 | 67 | ||
| 63 | pipe = usb_sndctrlpipe(udev, 0); /* write_out */ | 68 | pipe = usb_sndctrlpipe(udev, 0); /* write_out */ |
| 64 | reqtype = REALTEK_USB_VENQT_WRITE; | 69 | reqtype = REALTEK_USB_VENQT_WRITE; |
| 65 | 70 | ||
| 66 | buf = kmalloc(sizeof(*buf), GFP_ATOMIC); | 71 | dr = kmalloc(sizeof(*dr), GFP_ATOMIC); |
| 67 | if (!buf) | 72 | if (!dr) |
| 73 | return -ENOMEM; | ||
| 74 | |||
| 75 | databuf = kmalloc(databuf_maxlen, GFP_ATOMIC); | ||
| 76 | if (!databuf) { | ||
| 77 | kfree(dr); | ||
| 68 | return -ENOMEM; | 78 | return -ENOMEM; |
| 79 | } | ||
| 69 | 80 | ||
| 70 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 81 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
| 71 | if (!urb) { | 82 | if (!urb) { |
| 72 | kfree(buf); | 83 | kfree(databuf); |
| 84 | kfree(dr); | ||
| 73 | return -ENOMEM; | 85 | return -ENOMEM; |
| 74 | } | 86 | } |
| 75 | 87 | ||
| 76 | dr = &buf->dr; | ||
| 77 | |||
| 78 | dr->bRequestType = reqtype; | 88 | dr->bRequestType = reqtype; |
| 79 | dr->bRequest = request; | 89 | dr->bRequest = request; |
| 80 | dr->wValue = cpu_to_le16(value); | 90 | dr->wValue = cpu_to_le16(value); |
| 81 | dr->wIndex = cpu_to_le16(index); | 91 | dr->wIndex = cpu_to_le16(index); |
| 82 | dr->wLength = cpu_to_le16(len); | 92 | dr->wLength = cpu_to_le16(len); |
| 83 | /* data are already in little-endian order */ | 93 | /* data are already in little-endian order */ |
| 84 | memcpy(buf, pdata, len); | 94 | memcpy(databuf, pdata, len); |
| 85 | usb_fill_control_urb(urb, udev, pipe, | 95 | usb_fill_control_urb(urb, udev, pipe, |
| 86 | (unsigned char *)dr, buf, len, | 96 | (unsigned char *)dr, databuf, len, |
| 87 | usbctrl_async_callback, buf); | 97 | usbctrl_async_callback, NULL); |
| 88 | rc = usb_submit_urb(urb, GFP_ATOMIC); | 98 | rc = usb_submit_urb(urb, GFP_ATOMIC); |
| 89 | if (rc < 0) | 99 | if (rc < 0) { |
| 90 | kfree(buf); | 100 | kfree(databuf); |
| 101 | kfree(dr); | ||
| 102 | } | ||
| 91 | usb_free_urb(urb); | 103 | usb_free_urb(urb); |
| 92 | return rc; | 104 | return rc; |
| 93 | } | 105 | } |
| @@ -825,8 +837,6 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
| 825 | u32 ep_num; | 837 | u32 ep_num; |
| 826 | struct urb *_urb = NULL; | 838 | struct urb *_urb = NULL; |
| 827 | struct sk_buff *_skb = NULL; | 839 | struct sk_buff *_skb = NULL; |
| 828 | struct sk_buff_head *skb_list; | ||
| 829 | struct usb_anchor *urb_list; | ||
| 830 | 840 | ||
| 831 | WARN_ON(NULL == rtlusb->usb_tx_aggregate_hdl); | 841 | WARN_ON(NULL == rtlusb->usb_tx_aggregate_hdl); |
| 832 | if (unlikely(IS_USB_STOP(rtlusb))) { | 842 | if (unlikely(IS_USB_STOP(rtlusb))) { |
| @@ -836,15 +846,14 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
| 836 | return; | 846 | return; |
| 837 | } | 847 | } |
| 838 | ep_num = rtlusb->ep_map.ep_mapping[qnum]; | 848 | ep_num = rtlusb->ep_map.ep_mapping[qnum]; |
| 839 | skb_list = &rtlusb->tx_skb_queue[ep_num]; | ||
| 840 | _skb = skb; | 849 | _skb = skb; |
| 841 | _urb = _rtl_usb_tx_urb_setup(hw, _skb, ep_num); | 850 | _urb = _rtl_usb_tx_urb_setup(hw, _skb, ep_num); |
| 842 | if (unlikely(!_urb)) { | 851 | if (unlikely(!_urb)) { |
| 843 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 852 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
| 844 | "Can't allocate urb. Drop skb!\n"); | 853 | "Can't allocate urb. Drop skb!\n"); |
| 854 | kfree_skb(skb); | ||
| 845 | return; | 855 | return; |
| 846 | } | 856 | } |
| 847 | urb_list = &rtlusb->tx_pending[ep_num]; | ||
| 848 | _rtl_submit_tx_urb(hw, _urb); | 857 | _rtl_submit_tx_urb(hw, _urb); |
| 849 | } | 858 | } |
| 850 | 859 | ||
| @@ -941,7 +950,8 @@ static struct rtl_intf_ops rtl_usb_ops = { | |||
| 941 | }; | 950 | }; |
| 942 | 951 | ||
| 943 | int rtl_usb_probe(struct usb_interface *intf, | 952 | int rtl_usb_probe(struct usb_interface *intf, |
| 944 | const struct usb_device_id *id) | 953 | const struct usb_device_id *id, |
| 954 | struct rtl_hal_cfg *rtl_hal_cfg) | ||
| 945 | { | 955 | { |
| 946 | int err; | 956 | int err; |
| 947 | struct ieee80211_hw *hw = NULL; | 957 | struct ieee80211_hw *hw = NULL; |
| @@ -976,7 +986,7 @@ int rtl_usb_probe(struct usb_interface *intf, | |||
| 976 | usb_set_intfdata(intf, hw); | 986 | usb_set_intfdata(intf, hw); |
| 977 | /* init cfg & intf_ops */ | 987 | /* init cfg & intf_ops */ |
| 978 | rtlpriv->rtlhal.interface = INTF_USB; | 988 | rtlpriv->rtlhal.interface = INTF_USB; |
| 979 | rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_info); | 989 | rtlpriv->cfg = rtl_hal_cfg; |
| 980 | rtlpriv->intf_ops = &rtl_usb_ops; | 990 | rtlpriv->intf_ops = &rtl_usb_ops; |
| 981 | rtl_dbgp_flag_init(hw); | 991 | rtl_dbgp_flag_init(hw); |
| 982 | /* Init IO handler */ | 992 | /* Init IO handler */ |
