struct tasklet_struct tasklet;
        struct task_struct *dpc_tsk;
        struct completion dpc_wait;
+
+       bool threads_only;
+       struct semaphore sdsem;
+       spinlock_t sdlock;
 } dhd_bus_t;
 
 typedef volatile struct _sbconfig {
 static void brcmf_sdbrcm_sdiod_drive_strength_init(struct dhd_bus *bus,
                                        u32 drivestrength);
 static void brcmf_sdbrcm_chip_detach(struct dhd_bus *bus);
-static void brcmf_sdbrcm_wait_for_event(dhd_pub_t *dhd, bool *lockvar);
+static void brcmf_sdbrcm_wait_for_event(dhd_bus_t *bus, bool *lockvar);
 static void brcmf_sdbrcm_wait_event_wakeup(dhd_bus_t *bus);
 static void brcmf_sdbrcm_watchdog(unsigned long data);
 static int brcmf_sdbrcm_watchdog_thread(void *data);
 static int brcmf_sdbrcm_dpc_thread(void *data);
 static void brcmf_sdbrcm_dpc_tasklet(unsigned long data);
 static void brcmf_sdbrcm_sched_dpc(dhd_bus_t *bus);
+static void brcmf_sdbrcm_sdlock(dhd_bus_t *bus);
+static void brcmf_sdbrcm_sdunlock(dhd_bus_t *bus);
 
 /* Packet free applicable unconditionally for sdio and sdspi.
  * Conditional if bufpool was present for gspi bus.
 done:
        /* restore pkt buffer pointer before calling tx complete routine */
        skb_pull(pkt, SDPCM_HDRLEN + pad);
-       brcmf_os_sdunlock(bus->dhd);
+       brcmf_sdbrcm_sdunlock(bus);
        brcmf_txcomplete(bus->dhd, pkt, ret != 0);
-       brcmf_os_sdlock(bus->dhd);
+       brcmf_sdbrcm_sdlock(bus);
 
        if (free_pkt)
                brcmu_pkt_buf_free_skb(pkt);
                }
        } else {
                /* Lock: we're about to use shared data/code (and SDIO) */
-               brcmf_os_sdlock(bus->dhd);
+               brcmf_sdbrcm_sdlock(bus);
 
                /* Otherwise, send it now */
                BUS_WAKE(bus);
                        brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
                }
 
-               brcmf_os_sdunlock(bus->dhd);
+               brcmf_sdbrcm_sdunlock(bus);
        }
 
        return ret;
        ASSERT(IS_ALIGNED((unsigned long)frame, 2));
 
        /* Need to lock here to protect txseq and SDIO tx calls */
-       brcmf_os_sdlock(bus->dhd);
+       brcmf_sdbrcm_sdlock(bus);
 
        BUS_WAKE(bus);
 
                bus->ctrl_frame_buf = frame;
                bus->ctrl_frame_len = len;
 
-               brcmf_sdbrcm_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
+               brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat);
 
                if (bus->ctrl_frame_stat == false) {
                        DHD_INFO(("%s: ctrl_frame_stat == false\n", __func__));
                brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
        }
 
-       brcmf_os_sdunlock(bus->dhd);
+       brcmf_sdbrcm_sdunlock(bus);
 
        if (ret)
                bus->dhd->tx_ctlerrs++;
        /* Wait until control frame is available */
        timeleft = brcmf_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending);
 
-       brcmf_os_sdlock(bus->dhd);
+       brcmf_sdbrcm_sdlock(bus);
        rxlen = bus->rxlen;
        memcpy(msg, bus->rxctl, min(msglen, rxlen));
        bus->rxlen = 0;
-       brcmf_os_sdunlock(bus->dhd);
+       brcmf_sdbrcm_sdunlock(bus);
 
        if (rxlen) {
                DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
        } else if (timeleft == 0) {
                DHD_ERROR(("%s: resumed on timeout\n", __func__));
 #ifdef BCMDBG
-               brcmf_os_sdlock(bus->dhd);
+               brcmf_sdbrcm_sdlock(bus);
                brcmf_sdbrcm_checkdied(bus, NULL, 0);
-               brcmf_os_sdunlock(bus->dhd);
-#endif                         /* BCMDBG */
+               brcmf_sdbrcm_sdunlock(bus);
+#endif                         /* DHD_DEBUG */
        } else if (pending == true) {
                DHD_CTL(("%s: cancelled\n", __func__));
                return -ERESTARTSYS;
        } else {
                DHD_CTL(("%s: resumed for unknown reason?\n", __func__));
 #ifdef BCMDBG
-               brcmf_os_sdlock(bus->dhd);
+               brcmf_sdbrcm_sdlock(bus);
                brcmf_sdbrcm_checkdied(bus, NULL, 0);
-               brcmf_os_sdunlock(bus->dhd);
-#endif                         /* BCMDBG */
+               brcmf_sdbrcm_sdunlock(bus);
+#endif                         /* DHD_DEBUG */
        }
 
        if (rxlen)
        bool_val = (int_val != 0) ? true : false;
 
        /* Some ioctls use the bus */
-       brcmf_os_sdlock(bus->dhd);
+       brcmf_sdbrcm_sdlock(bus);
 
        /* Check if dongle is in reset. If so, only allow DEVRESET iovars */
        if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
                brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
        }
 
-       brcmf_os_sdunlock(bus->dhd);
+       brcmf_sdbrcm_sdunlock(bus);
 
        if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == false)
                brcmf_c_preinit_ioctls((dhd_pub_t *) bus->dhd);
        /* Look up var locally; if not found pass to host driver */
        vi = brcmu_iovar_lookup(dhdsdio_iovars, name);
        if (vi == NULL) {
-               brcmf_os_sdlock(bus->dhd);
+               brcmf_sdbrcm_sdlock(bus);
 
                BUS_WAKE(bus);
 
                        brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
                }
 
-               brcmf_os_sdunlock(bus->dhd);
+               brcmf_sdbrcm_sdunlock(bus);
                goto exit;
        }
 
        DHD_TRACE(("%s: Enter\n", __func__));
 
        if (enforce_mutex)
-               brcmf_os_sdlock(bus->dhd);
+               brcmf_sdbrcm_sdlock(bus);
 
        BUS_WAKE(bus);
 
        bus->tx_seq = bus->rx_seq = 0;
 
        if (enforce_mutex)
-               brcmf_os_sdunlock(bus->dhd);
+               brcmf_sdbrcm_sdunlock(bus);
 
 #if defined(OOB_INTR_ONLY)
        brcmf_sdio_unregister_oob_intr();
        brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms);
 
        if (enforce_mutex)
-               brcmf_os_sdlock(bus->dhd);
+               brcmf_sdbrcm_sdlock(bus);
 
        /* Make sure backplane clock is on, needed to generate F2 interrupt */
        brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 
 exit:
        if (enforce_mutex)
-               brcmf_os_sdunlock(bus->dhd);
+               brcmf_sdbrcm_sdunlock(bus);
 
        return ret;
 }
 #endif                         /* BCMDBG */
                }
                if (num) {
-                       brcmf_os_sdunlock(bus->dhd);
+                       brcmf_sdbrcm_sdunlock(bus);
                        brcmf_rx_frame(bus->dhd, ifidx, save_pfirst, num);
-                       brcmf_os_sdlock(bus->dhd);
+                       brcmf_sdbrcm_sdlock(bus);
                }
 
                bus->rxglomframes++;
                }
 
                /* Unlock during rx call */
-               brcmf_os_sdunlock(bus->dhd);
+               brcmf_sdbrcm_sdunlock(bus);
                brcmf_rx_frame(bus->dhd, ifidx, pkt, 1);
-               brcmf_os_sdlock(bus->dhd);
+               brcmf_sdbrcm_sdlock(bus);
        }
        rxcount = maxframes - rxleft;
 #ifdef BCMDBG
        /* Start with leftover status bits */
        intstatus = bus->intstatus;
 
-       brcmf_os_sdlock(bus->dhd);
+       brcmf_sdbrcm_sdlock(bus);
 
        /* If waiting for HTAVAIL, check status */
        if (bus->clkstate == CLK_PENDING) {
                brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
        }
 
-       brcmf_os_sdunlock(bus->dhd);
+       brcmf_sdbrcm_sdunlock(bus);
 
        return resched;
 }
        if (bus->sleeping)
                return false;
 
-       brcmf_os_sdlock(bus->dhd);
+       brcmf_sdbrcm_sdlock(bus);
 
        /* Poll period: check device if appropriate. */
        if (bus->poll && (++bus->polltick >= bus->pollrate)) {
                }
        }
 
-       brcmf_os_sdunlock(bus->dhd);
+       brcmf_sdbrcm_sdunlock(bus);
 
        return bus->ipend;
 }
                return -ENOTSUPP;
 
        /* Exclusive bus access */
-       brcmf_os_sdlock(bus->dhd);
+       brcmf_sdbrcm_sdlock(bus);
 
        /* Don't allow input if dongle is in reset */
        if (bus->dhd->dongle_reset) {
-               brcmf_os_sdunlock(bus->dhd);
+               brcmf_sdbrcm_sdunlock(bus);
                return -EPERM;
        }
 
                brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
        }
 
-       brcmf_os_sdunlock(bus->dhd);
+       brcmf_sdbrcm_sdunlock(bus);
 
        return rv;
 }
        bus->timer.data = (unsigned long)bus;
        bus->timer.function = brcmf_sdbrcm_watchdog;
 
+       /* Initialize thread based operation and lock */
+       if ((brcmf_watchdog_prio >= 0) && (brcmf_dpc_prio >= 0)) {
+               bus->threads_only = true;
+               sema_init(&bus->sdsem, 1);
+       } else {
+               bus->threads_only = false;
+               spin_lock_init(&bus->sdlock);
+       }
+
        if (brcmf_dpc_prio >= 0) {
                /* Initialize watchdog thread */
                init_completion(&bus->watchdog_wait);
 }
 
 static void
-brcmf_sdbrcm_wait_for_event(dhd_pub_t *dhd, bool *lockvar)
+brcmf_sdbrcm_wait_for_event(dhd_bus_t *bus, bool *lockvar)
 {
-       brcmf_os_sdunlock(dhd);
-       wait_event_interruptible_timeout(dhd->bus->ctrl_wait,
+       brcmf_sdbrcm_sdunlock(bus);
+       wait_event_interruptible_timeout(bus->ctrl_wait,
                                         (*lockvar == false), HZ * 2);
-       brcmf_os_sdlock(dhd);
+       brcmf_sdbrcm_sdlock(bus);
        return;
 }
 
 
        tasklet_schedule(&bus->tasklet);
 }
+
+static void brcmf_sdbrcm_sdlock(dhd_bus_t *bus)
+{
+       if (bus->threads_only)
+               down(&bus->sdsem);
+       else
+               spin_lock_bh(&bus->sdlock);
+}
+
+static void brcmf_sdbrcm_sdunlock(dhd_bus_t *bus)
+{
+       if (bus->threads_only)
+               up(&bus->sdsem);
+       else
+               spin_unlock_bh(&bus->sdlock);
+}