The driver places a 254-byte buffer on the stack when writing long output.
To reduce stack usage, a buffer of the required length is acquired using
kmemdup().

Signed-off-by: Larry Finger <larry.fin...@lwfinger.net>
---
 drivers/staging/rtl8188eu/hal/usb_ops_linux.c | 58 +++++++++++++++++++--------
 1 file changed, 42 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/rtl8188eu/hal/usb_ops_linux.c b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
index 787763e..7ba52a1 100644
--- a/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
+++ b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c
@@ -267,28 +267,54 @@ static int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
  static int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 
*pdata)
 {
-       u8 request;
-       u8 requesttype;
-       u16 wvalue;
-       u16 index;
-       u16 len;
-       u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0};
+       struct adapter  *adapt = pintfhdl->padapter;
+       struct dvobj_priv  *dvobjpriv = adapter_to_dvobj(adapt);
+       struct usb_device *udev = dvobjpriv->pusbdev;
+       u8 request = REALTEK_USB_VENQT_CMD_REQ;
+       u8 reqtype =  REALTEK_USB_VENQT_WRITE;
+       u16 value = (u16)(addr & 0x0000ffff);
+       u16 index = REALTEK_USB_VENQT_CMD_IDX;
+       int pipe = usb_sndctrlpipe(udev, 0); /* write_out */
+       u8 *buffer;
        int ret;
+       int vendorreq_times = 0;
 -      _func_enter_;
-
-       request = 0x05;
-       requesttype = 0x00;/* write_out */
-       index = 0;/* n/a */
+       buffer = kmemdup(pdata, length, GFP_ATOMIC);
+       if (!buffer)
+               return -ENOMEM;
+       while (++vendorreq_times <= MAX_USBCTRL_VENDORREQ_TIMES) {
+               pipe = usb_sndctrlpipe(udev, 0);/* write_out */
 -      wvalue = (u16)(addr&0x0000ffff);
-       len = length;
-        memcpy(buf, pdata, len);
+               ret = rtw_usb_control_msg(udev, pipe, request, reqtype,
+                                         value, index, buffer, length,
+                                         RTW_USB_CONTROL_MSG_TIMEOUT);
- ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index, buf, len, requesttype);
+               if (ret == length) {   /*  Success this control transfer. */
+                       rtw_reset_continual_urb_error(dvobjpriv);
+               } else { /*  error cases */
+ DBG_88E("reg 0x%x, usb %u write fail, status:%d value=0x%x, vendorreq_times:%d\n",
+                               value, length, ret, *(u32 *)pdata, 
vendorreq_times);
 -      _func_exit_;
+                       if (ret < 0) {
+                               if (ret == (-ESHUTDOWN) || ret == -ENODEV) {
+                                       adapt->bSurpriseRemoved = true;
+                               } else {
+                                       struct hal_data_8188e   *haldata = 
GET_HAL_DATA(adapt);
+                                       haldata->srestpriv.Wifi_Error_Status = 
USB_VEN_REQ_CMD_FAIL;
+                               }
+                       }
+                       if (rtw_inc_and_chk_continual_urb_error(dvobjpriv)) {
+                               adapt->bSurpriseRemoved = true;
+                               break;
+                       }
+               }
 +              /*  firmware download is checksumed, don't retry */
+               if ((value >= FW_8188E_START_ADDRESS &&
+                   value <= FW_8188E_END_ADDRESS) || ret == length)
+                       break;
+       }
+       kfree(buffer);
        return ret;
 }
 -- 1.8.4


_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to