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);
+}