rtl8xxxu: Check return value of kmemdup()
[cascardo/linux.git] / drivers / net / wireless / realtek / rtl8xxxu / rtl8xxxu.c
index 6aed923..08d8e1f 100644 (file)
@@ -2089,7 +2089,7 @@ exit:
 static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
 {
        int pages, remainder, i, ret;
-       u8 val8;
+       u8 val8, sys_func;
        u16 val16;
        u32 val32;
        u8 *fwptr;
@@ -2100,19 +2100,40 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
 
        /* 8051 enable */
        val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
-       rtl8xxxu_write16(priv, REG_SYS_FUNC, val16 | SYS_FUNC_CPU_ENABLE);
+       val16 |= SYS_FUNC_CPU_ENABLE;
+       rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
+
+       val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL);
+       if (val8 & MCU_FW_RAM_SEL) {
+               pr_info("do the RAM reset\n");
+               rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
+               val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1);
+               val8 &= ~BIT(3);
+               rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8);
+               sys_func = rtl8xxxu_read8(priv, REG_SYS_FUNC + 1);
+               sys_func &= ~BIT(2);
+               rtl8xxxu_write8(priv, REG_SYS_FUNC + 1, sys_func);
+               val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1);
+               val8 |= BIT(3);
+               rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8);
+               sys_func |= BIT(2);
+               rtl8xxxu_write8(priv, REG_SYS_FUNC + 1, sys_func);
+       }
 
        /* MCU firmware download enable */
        val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL);
-       rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8 | MCU_FW_DL_ENABLE);
+       val8 |= MCU_FW_DL_ENABLE;
+       rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8);
 
        /* 8051 reset */
        val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL);
-       rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32 & ~BIT(19));
+       val32 &= ~BIT(19);
+       rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32);
 
        /* Reset firmware download checksum */
        val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL);
-       rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8 | MCU_FW_DL_CSUM_REPORT);
+       val8 |= MCU_FW_DL_CSUM_REPORT;
+       rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8);
 
        pages = priv->fw_size / RTL_FW_PAGE_SIZE;
        remainder = priv->fw_size % RTL_FW_PAGE_SIZE;
@@ -2121,7 +2142,8 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
 
        for (i = 0; i < pages; i++) {
                val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8;
-               rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8 | i);
+               val8 |= i;
+               rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8);
 
                ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS,
                                      fwptr, RTL_FW_PAGE_SIZE);
@@ -2135,7 +2157,8 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
 
        if (remainder) {
                val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8;
-               rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8 | i);
+               val8 |= i;
+               rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8);
                ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS,
                                      fwptr, remainder);
                if (ret != remainder) {
@@ -2148,8 +2171,8 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv)
 fw_abort:
        /* MCU firmware download disable */
        val16 = rtl8xxxu_read16(priv, REG_MCU_FW_DL);
-       rtl8xxxu_write16(priv, REG_MCU_FW_DL,
-                        val16 & (~MCU_FW_DL_ENABLE & 0xff));
+       val16 &= ~MCU_FW_DL_ENABLE;
+       rtl8xxxu_write16(priv, REG_MCU_FW_DL, val16);
 
        return ret;
 }
@@ -2174,6 +2197,10 @@ static int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, char *fw_name)
        }
 
        priv->fw_data = kmemdup(fw->data, fw->size, GFP_KERNEL);
+       if (!priv->fw_data) {
+               ret = -ENOMEM;
+               goto exit;
+       }
        priv->fw_size = fw->size - sizeof(struct rtl8xxxu_firmware_header);
 
        signature = le16_to_cpu(priv->fw_data->signature);