source: G950FXXS5DSI1
[GitHub/exynos8895/android_kernel_samsung_universal8895.git] / drivers / net / wireless / bcmdhd4361 / dhd_sdio.c
index 07bb0fde911726a6faef2e0ec51287660827b6cf..be60ac7a8d72b51a1fb58cc292112c0234ae6f2a 100644 (file)
@@ -24,7 +24,7 @@
  *
  * <<Broadcom-WL-IPTag/Open:>>
  *
- * $Id: dhd_sdio.c 796833 2018-12-27 05:52:37Z $
+ * $Id: dhd_sdio.c 814373 2019-04-11 02:01:55Z $
  */
 
 #include <typedefs.h>
@@ -252,6 +252,8 @@ typedef struct dhd_console {
 
 #endif /* defined (BT_OVER_SDIO) */
 
+#define SBSDIO_CIS_TINY_SIZE_LIMIT 26
+
 /* Private data for SDIO bus interaction */
 typedef struct dhd_bus {
        dhd_pub_t       *dhd;
@@ -7759,7 +7761,7 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
        uint8 clkctl = 0;
 #endif /* !BCMSPI */
        uint fn, numfn;
-       uint8 *cis[SDIOD_MAX_IOFUNCS];
+       uint8 *cis = NULL;
        int32 value;
        int err = 0;
 
@@ -7809,47 +7811,56 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
                numfn = 0; /* internally func is hardcoded to 1 as gSPI has cis on F1 only */
 #endif /* !BCMSPI */
 #ifndef BCMSDIOLITE
+               if (!(cis = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) {
+                       DHD_INFO(("dhdsdio_probe: cis malloc failed\n"));
+                       goto fail;
+               }
+               bzero(cis, SBSDIO_CIS_SIZE_LIMIT);
+
                for (fn = 0; fn <= numfn; fn++) {
-                       if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) {
-                               DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn));
-                               break;
+                       if (DHD_INFO_ON()) {
+                               if ((err = bcmsdh_cis_read(sdh, fn, cis,
+                                               SBSDIO_CIS_SIZE_LIMIT))) {
+                                       DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n",
+                                               fn, err));
+                                       break;
+                               }
+#ifdef DHD_DEBUG
+                               dhd_dump_cis(fn, cis);
+#endif /* DHD_DEBUG */
                        }
-                       bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT);
-
-                       if ((err = bcmsdh_cis_read(sdh, fn, cis[fn],
-                                                        SBSDIO_CIS_SIZE_LIMIT))) {
-                               DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n", fn, err));
-                               MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
-                               break;
+                       else
+                       {
+                               if (fn > 0) {
+                                       if ((err = bcmsdh_cis_read(sdh, fn, cis,
+                                                       SBSDIO_CIS_TINY_SIZE_LIMIT))) {
+                                               DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n",
+                                                       fn, err));
+                                               break;
+                                       }
+                               }
                        }
 
-               /* Reading the F1, F2 and F3 max blocksize values from CIS
-                 * and writing into the F1, F2 and F3  block size registers.
-                 * There is no max block size register value available for F0 in CIS register.
-                 * So, setting default value for F0 block size as 32 (which was set earlier
-                 * in iovar). IOVAR takes only one arguement.
-                 * So, we are passing the function number alongwith the value (fn<<16)
-               */
+                       /* Reading the F1, F2 and F3 max blocksize values from CIS
+                        * and writing into the F1, F2 and F3   block size registers.
+                        * There is no max block size register value available for F0 in CIS
+                        * register.
+                        * So, setting default value for F0 block size as 32 (which was set earlier
+                        * in iovar). IOVAR takes only one arguement.
+                        * So, we are passing the function number alongwith the value (fn<<16)
+                        */
                        if (!fn)
                                value = F0_BLOCK_SIZE;
                        else
-                               value = (cis[fn][25]<<8) | cis[fn][24] | (fn<<16);
+                               value = (cis[25]<<8) | cis[24] | (fn<<16);
                        if (bcmsdh_iovar_op(sdh, "sd_blocksize", NULL, 0, &value,
-                               sizeof(value), TRUE) != BCME_OK) {
+                                       sizeof(value), TRUE) != BCME_OK) {
                                bus->blocksize = 0;
                                DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__,
                                        "sd_blocksize"));
                        }
-#ifdef DHD_DEBUG
-                       if (DHD_INFO_ON()) {
-                               dhd_dump_cis(fn, cis[fn]);
-                       }
-#endif /* DHD_DEBUG */
                }
-       while (fn-- > 0) {
-               ASSERT(cis[fn]);
-               MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
-       }
+               MFREE(osh, cis, SBSDIO_CIS_SIZE_LIMIT);
 #else
        BCM_REFERENCE(cis);
        BCM_REFERENCE(fn);
@@ -8365,10 +8376,14 @@ dhdsdio_suspend(void *context)
        }
 
        DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
+       /* stop all interface network queue. */
+       dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
        bus->dhd->busstate = DHD_BUS_SUSPEND;
        if (DHD_BUS_BUSY_CHECK_IN_TX(bus->dhd)) {
                DHD_ERROR(("Tx Request is not ended\n"));
                bus->dhd->busstate = DHD_BUS_DATA;
+               /* resume all interface network queue. */
+               dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
                DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
                return -EBUSY;
        }
@@ -8394,6 +8409,8 @@ dhdsdio_suspend(void *context)
        DHD_LINUX_GENERAL_LOCK(bus->dhd, flags);
        if (ret) {
                bus->dhd->busstate = DHD_BUS_DATA;
+               /* resume all interface network queue. */
+               dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
        }
        DHD_BUS_BUSY_CLEAR_SUSPEND_IN_PROGRESS(bus->dhd);
        dhd_os_busbusy_wake(bus->dhd);
@@ -8426,6 +8443,8 @@ dhdsdio_resume(void *context)
        DHD_BUS_BUSY_CLEAR_RESUME_IN_PROGRESS(bus->dhd);
        bus->dhd->busstate = DHD_BUS_DATA;
        dhd_os_busbusy_wake(bus->dhd);
+       /* resume all interface network queue. */
+       dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
        DHD_LINUX_GENERAL_UNLOCK(bus->dhd, flags);
 
        return 0;
@@ -9330,6 +9349,38 @@ concate_revision_bcm43455(dhd_bus_t *bus, char *fw_path, char *nv_path)
 }
 #endif /* SUPPORT_MULTIPLE_CHIP_4345X */
 
+static int
+concate_revision_bcm43430(dhd_bus_t *bus, char *fw_path, char *nv_path)
+{
+
+       uint chipver;
+       char chipver_tag[4] = {0, };
+
+       DHD_TRACE(("%s: BCM43430 Multiple Revision Check\n", __FUNCTION__));
+       if (bus->sih->chip != BCM43430_CHIP_ID) {
+               DHD_ERROR(("%s:Chip is not BCM43430\n", __FUNCTION__));
+               return BCME_ERROR;
+       }
+       chipver = bus->sih->chiprev;
+       DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
+       if (chipver == 0x0) {
+               DHD_ERROR(("----- CHIP bcm4343S -----\n"));
+               strcat(chipver_tag, "_3s");
+       } else if (chipver == 0x1) {
+               DHD_ERROR(("----- CHIP bcm43438 -----\n"));
+       } else if (chipver == 0x2) {
+               DHD_ERROR(("----- CHIP bcm43436L -----\n"));
+               strcat(chipver_tag, "_36");
+       } else {
+               DHD_ERROR(("----- CHIP bcm43430 unknown revision %d -----\n",
+                       chipver));
+       }
+
+       strcat(fw_path, chipver_tag);
+       strcat(nv_path, chipver_tag);
+       return 0;
+}
+
 int
 concate_revision(dhd_bus_t *bus, char *fw_path, char *nv_path)
 {
@@ -9366,6 +9417,9 @@ concate_revision(dhd_bus_t *bus, char *fw_path, char *nv_path)
                res = concate_revision_bcm43455(bus, fw_path, nv_path);
                break;
 #endif /* SUPPORT_MULTIPLE_CHIP_4345X */
+       case BCM43430_CHIP_ID:
+               res = concate_revision_bcm43430(bus, fw_path, nv_path);
+               break;
 
        default:
                DHD_ERROR(("REVISION SPECIFIC feature is not required\n"));