u8 bssidx;
};
-struct brcmf_timeout {
- u32 limit; /* Expiration time (usec) */
- u32 increment; /* Current expiration increment (usec) */
- u32 elapsed; /* Current elapsed time (usec) */
- u32 tick; /* O/S tick time (usec) */
-};
-
struct bcmevent_name {
uint event;
const char *name;
extern int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size);
#endif /* BCMDBG */
-extern void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec);
-extern int brcmf_timeout_expired(struct brcmf_timeout *tmo);
-
extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name);
extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx,
void *pktdata, struct brcmf_event_msg *,
struct brcmf_event_msg *event_ptr,
void **data_ptr);
-/*
- * Generalized timeout mechanism. Uses spin sleep with exponential
- * back-off until
- * the sleep time reaches one jiffy, then switches over to task delay. Usage:
- *
- * brcmf_timeout_start(&tmo, usec);
- * while (!brcmf_timeout_expired(&tmo))
- * if (poll_something())
- * break;
- * if (brcmf_timeout_expired(&tmo))
- * fatal();
- */
-
-void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec)
-{
- tmo->limit = usec;
- tmo->increment = 0;
- tmo->elapsed = 0;
- tmo->tick = 1000000 / HZ;
-}
-
-int brcmf_timeout_expired(struct brcmf_timeout *tmo)
-{
- /* Does nothing the first call */
- if (tmo->increment == 0) {
- tmo->increment = 1;
- return 0;
- }
-
- if (tmo->elapsed >= tmo->limit)
- return 1;
-
- /* Add the delay that's about to take place */
- tmo->elapsed += tmo->increment;
-
- if (tmo->increment < tmo->tick) {
- udelay(tmo->increment);
- tmo->increment *= 2;
- if (tmo->increment > tmo->tick)
- tmo->increment = tmo->tick;
- } else {
- wait_queue_head_t delay_wait;
- DECLARE_WAITQUEUE(wait, current);
- int pending;
- init_waitqueue_head(&delay_wait);
- add_wait_queue(&delay_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- pending = signal_pending(current);
- remove_wait_queue(&delay_wait, &wait);
- set_current_state(TASK_RUNNING);
- if (pending)
- return 1; /* Interrupted */
- }
-
- return 0;
-}
-
static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *net)
{
int i = 0;
int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex)
{
struct brcmf_bus *bus = drvr->bus;
- struct brcmf_timeout tmo;
+ unsigned long timeout;
uint retries = 0;
u8 ready, enable;
int err, ret = 0;
brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_0, SDIO_CCCR_IOEx, enable,
NULL);
- /* Give the dongle some time to do its thing and set IOR2 */
- brcmf_timeout_start(&tmo, BRCMF_WAIT_F2RDY * 1000);
-
+ timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY);
ready = 0;
- while (ready != enable && !brcmf_timeout_expired(&tmo))
+ while (enable != ready) {
ready = brcmf_sdcard_cfg_read(bus->card, SDIO_FUNC_0,
SDIO_CCCR_IORx, NULL);
+ if (time_after(jiffies, timeout))
+ break;
+ else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50))
+ /* prevent busy waiting if it takes too long */
+ msleep_interruptible(20);
+ }
- BRCMF_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
- __func__, enable, ready, tmo.elapsed));
+ BRCMF_INFO(("%s: enable 0x%02x, ready 0x%02x\n",
+ __func__, enable, ready));
/* If F2 successfully enabled, set core and enable interrupts */
if (ready == enable) {