return ret;
        sdiodev->irq_wake = true;
 
+       sdio_claim_host(sdiodev->func[1]);
+
        /* must configure SDIO_CCCR_IENx to enable irq */
        data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
        data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
                data |= SDIO_SEPINT_ACT_HI;
        brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
 
+       sdio_release_host(sdiodev->func[1]);
+
        return 0;
 }
 
 {
        brcmf_dbg(TRACE, "Entering\n");
 
+       sdio_claim_host(sdiodev->func[1]);
        brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
        brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
+       sdio_release_host(sdiodev->func[1]);
 
        if (sdiodev->irq_wake) {
                disable_irq_wake(sdiodev->irq);
        int retval;
 
        brcmf_dbg(INFO, "addr:0x%08x\n", addr);
-       sdio_claim_host(sdiodev->func[1]);
        retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
-       sdio_release_host(sdiodev->func[1]);
        brcmf_dbg(INFO, "data:0x%02x\n", data);
 
        if (ret)
        int retval;
 
        brcmf_dbg(INFO, "addr:0x%08x\n", addr);
-       sdio_claim_host(sdiodev->func[1]);
        retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false);
-       sdio_release_host(sdiodev->func[1]);
        brcmf_dbg(INFO, "data:0x%08x\n", data);
 
        if (ret)
        int retval;
 
        brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data);
-       sdio_claim_host(sdiodev->func[1]);
        retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
-       sdio_release_host(sdiodev->func[1]);
 
        if (ret)
                *ret = retval;
        int retval;
 
        brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data);
-       sdio_claim_host(sdiodev->func[1]);
        retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true);
-       sdio_release_host(sdiodev->func[1]);
 
        if (ret)
                *ret = retval;
        brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
                  fn, addr, pkt->len);
 
-       sdio_claim_host(sdiodev->func[1]);
-
        width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
        err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
        if (err)
                                         fn, addr, pkt);
 
 done:
-       sdio_release_host(sdiodev->func[1]);
-
        return err;
 }
 
        brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n",
                  fn, addr, pktq->qlen);
 
-       sdio_claim_host(sdiodev->func[1]);
-
        width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
        err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
        if (err)
                                        pktq);
 
 done:
-       sdio_release_host(sdiodev->func[1]);
-
        return err;
 }
 
        if (flags & SDIO_REQ_ASYNC)
                return -ENOTSUPP;
 
-       sdio_claim_host(sdiodev->func[1]);
-
        if (bar0 != sdiodev->sbwad) {
                err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
                if (err)
                                         addr, pkt);
 
 done:
-       sdio_release_host(sdiodev->func[1]);
-
        return err;
 }
 
        brcmf_dbg(TRACE, "Enter\n");
 
        /* issue abort cmd52 command through F0 */
-       sdio_claim_host(sdiodev->func[1]);
        brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, SDIO_FUNC_0,
                                 SDIO_CCCR_ABORT, &t_func);
-       sdio_release_host(sdiodev->func[1]);
 
        brcmf_dbg(TRACE, "Exit\n");
        return 0;
 
        struct list_head dpc_tsklst;
        spinlock_t dpc_tl_lock;
 
-       struct semaphore sdsem;
-
        const struct firmware *firmware;
        u32 fw_ptr;
 
                 * read directly into the chained packet, or allocate a large
                 * packet and and copy into the chain.
                 */
-               down(&bus->sdsem);
+               sdio_claim_host(bus->sdiodev->func[1]);
                if (usechain) {
                        errcode = brcmf_sdcard_recv_chain(bus->sdiodev,
                                        bus->sdiodev->sbwad,
                                  dlen);
                        errcode = -1;
                }
-               up(&bus->sdsem);
+               sdio_release_host(bus->sdiodev->func[1]);
                bus->sdcnt.f2rxdata++;
 
                /* On failure, kill the superframe, allow a couple retries */
                                  dlen, errcode);
                        bus->sdiodev->bus_if->dstats.rx_errors++;
 
+                       sdio_claim_host(bus->sdiodev->func[1]);
                        if (bus->glomerr++ < 3) {
                                brcmf_sdbrcm_rxfail(bus, true, true);
                        } else {
                                bus->sdcnt.rxglomfail++;
                                brcmf_sdbrcm_free_glom(bus);
                        }
+                       sdio_release_host(bus->sdiodev->func[1]);
                        return 0;
                }
 
 
                rd_new.seq_num = rxseq;
                rd_new.len = dlen;
+               sdio_claim_host(bus->sdiodev->func[1]);
                errcode = -!brcmf_sdio_hdparser(bus, pfirst->data, &rd_new,
                                                   BRCMF_SDIO_FT_SUPER);
+               sdio_release_host(bus->sdiodev->func[1]);
                bus->cur_read.len = rd_new.len_nxtfrm << 4;
 
                /* Remove superframe header, remember offset */
 
                        rd_new.len = pnext->len;
                        rd_new.seq_num = rxseq++;
+                       sdio_claim_host(bus->sdiodev->func[1]);
                        errcode = -!brcmf_sdio_hdparser(bus, pnext->data,
                                                           &rd_new,
                                                           BRCMF_SDIO_FT_SUB);
+                       sdio_release_host(bus->sdiodev->func[1]);
                        brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
                                           pnext->data, 32, "subframe:\n");
 
                if (errcode) {
                        /* Terminate frame on error, request
                                 a couple retries */
+                       sdio_claim_host(bus->sdiodev->func[1]);
                        if (bus->glomerr++ < 3) {
                                /* Restore superframe header space */
                                skb_push(pfirst, sfdoff);
                                bus->sdcnt.rxglomfail++;
                                brcmf_sdbrcm_free_glom(bus);
                        }
+                       sdio_release_host(bus->sdiodev->func[1]);
                        bus->cur_read.len = 0;
                        return 0;
                }
 
                rd->len_left = rd->len;
                /* read header first for unknow frame length */
-               down(&bus->sdsem);
+               sdio_claim_host(bus->sdiodev->func[1]);
                if (!rd->len) {
                        sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
                                                      bus->sdiodev->sbwad,
                                          sdret);
                                bus->sdcnt.rx_hdrfail++;
                                brcmf_sdbrcm_rxfail(bus, true, true);
-                               up(&bus->sdsem);
+                               sdio_release_host(bus->sdiodev->func[1]);
                                continue;
                        }
 
 
                        if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd,
                                                 BRCMF_SDIO_FT_NORMAL)) {
-                               up(&bus->sdsem);
+                               sdio_release_host(bus->sdiodev->func[1]);
                                if (!bus->rxpending)
                                        break;
                                else
                                rd->len_nxtfrm = 0;
                                /* treat all packet as event if we don't know */
                                rd->channel = SDPCM_EVENT_CHANNEL;
-                               up(&bus->sdsem);
+                               sdio_release_host(bus->sdiodev->func[1]);
                                continue;
                        }
                        rd->len_left = rd->len > BRCMF_FIRSTREAD ?
                        bus->sdiodev->bus_if->dstats.rx_dropped++;
                        brcmf_sdbrcm_rxfail(bus, false,
                                            RETRYCHAN(rd->channel));
-                       up(&bus->sdsem);
+                       sdio_release_host(bus->sdiodev->func[1]);
                        continue;
                }
                skb_pull(pkt, head_read);
                sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
                                              SDIO_FUNC_2, F2SYNC, pkt);
                bus->sdcnt.f2rxdata++;
-               up(&bus->sdsem);
+               sdio_release_host(bus->sdiodev->func[1]);
 
                if (sdret < 0) {
                        brcmf_dbg(ERROR, "read %d bytes from channel %d failed: %d\n",
                                  rd->len, rd->channel, sdret);
                        brcmu_pkt_buf_free_skb(pkt);
                        bus->sdiodev->bus_if->dstats.rx_errors++;
+                       sdio_claim_host(bus->sdiodev->func[1]);
                        brcmf_sdbrcm_rxfail(bus, true,
                                            RETRYCHAN(rd->channel));
+                       sdio_release_host(bus->sdiodev->func[1]);
                        continue;
                }
 
                } else {
                        memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN);
                        rd_new.seq_num = rd->seq_num;
+                       sdio_claim_host(bus->sdiodev->func[1]);
                        if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new,
                                                 BRCMF_SDIO_FT_NORMAL)) {
                                rd->len = 0;
                                          roundup(rd_new.len, 16) >> 4);
                                rd->len = 0;
                                brcmf_sdbrcm_rxfail(bus, true, true);
+                               sdio_release_host(bus->sdiodev->func[1]);
                                brcmu_pkt_buf_free_skb(pkt);
                                continue;
                        }
+                       sdio_release_host(bus->sdiodev->func[1]);
                        rd->len_nxtfrm = rd_new.len_nxtfrm;
                        rd->channel = rd_new.channel;
                        rd->dat_offset = rd_new.dat_offset;
                                          rd_new.seq_num);
                                /* Force retry w/normal header read */
                                rd->len = 0;
+                               sdio_claim_host(bus->sdiodev->func[1]);
                                brcmf_sdbrcm_rxfail(bus, false, true);
+                               sdio_release_host(bus->sdiodev->func[1]);
                                brcmu_pkt_buf_free_skb(pkt);
                                continue;
                        }
                        } else {
                                brcmf_dbg(ERROR, "%s: glom superframe w/o "
                                          "descriptor!\n", __func__);
+                               sdio_claim_host(bus->sdiodev->func[1]);
                                brcmf_sdbrcm_rxfail(bus, false, false);
+                               sdio_release_host(bus->sdiodev->func[1]);
                        }
                        /* prepare the descriptor for the next read */
                        rd->len = rd->len_nxtfrm << 4;
        if (len & (ALIGNMENT - 1))
                        len = roundup(len, ALIGNMENT);
 
-       down(&bus->sdsem);
+       sdio_claim_host(bus->sdiodev->func[1]);
        ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad,
                                    SDIO_FUNC_2, F2SYNC, pkt);
        bus->sdcnt.f2txdata++;
                }
 
        }
-       up(&bus->sdsem);
+       sdio_release_host(bus->sdiodev->func[1]);
        if (ret == 0)
                bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
 
                /* In poll mode, need to check for other events */
                if (!bus->intr && cnt) {
                        /* Check device status, signal pending interrupt */
-                       down(&bus->sdsem);
+                       sdio_claim_host(bus->sdiodev->func[1]);
                        ret = r_sdreg32(bus, &intstatus,
                                        offsetof(struct sdpcmd_regs,
                                                 intstatus));
-                       up(&bus->sdsem);
+                       sdio_release_host(bus->sdiodev->func[1]);
                        bus->sdcnt.f2txdata++;
                        if (ret != 0)
                                break;
                bus->watchdog_tsk = NULL;
        }
 
-       down(&bus->sdsem);
+       sdio_claim_host(bus->sdiodev->func[1]);
 
        /* Enable clock for device interrupts */
        brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 
        /* Turn off the backplane clock (only) */
        brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
-       up(&bus->sdsem);
+       sdio_release_host(bus->sdiodev->func[1]);
 
        /* Clear the data packet queues */
        brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       down(&bus->sdsem);
+       sdio_claim_host(bus->sdiodev->func[1]);
 
        /* If waiting for HTAVAIL, check status */
        if (bus->clkstate == CLK_PENDING) {
        /* Pending interrupt indicates new device status */
        if (atomic_read(&bus->ipend) > 0) {
                atomic_set(&bus->ipend, 0);
-               sdio_claim_host(bus->sdiodev->func[1]);
                err = brcmf_sdio_intr_rstatus(bus);
-               sdio_release_host(bus->sdiodev->func[1]);
        }
 
        /* Start with leftover status bits */
                intstatus |= brcmf_sdbrcm_hostmail(bus);
        }
 
-       up(&bus->sdsem);
+       sdio_release_host(bus->sdiodev->func[1]);
 
        /* Generally don't ask for these, can get CRC errors... */
        if (intstatus & I_WR_OOSYNC) {
                (bus->clkstate == CLK_AVAIL)) {
                int i;
 
-               down(&bus->sdsem);
+               sdio_claim_host(bus->sdiodev->func[1]);
                err = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad,
                        SDIO_FUNC_2, F2SYNC, bus->ctrl_frame_buf,
                        (u32) bus->ctrl_frame_len);
                } else {
                        bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
                }
-               up(&bus->sdsem);
+               sdio_release_host(bus->sdiodev->func[1]);
                bus->ctrl_frame_stat = false;
                brcmf_sdbrcm_wait_event_wakeup(bus);
        }
        if ((bus->clkstate != CLK_PENDING)
            && bus->idletime == BRCMF_IDLE_IMMEDIATE) {
                bus->activity = false;
+               sdio_claim_host(bus->sdiodev->func[1]);
                brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+               sdio_release_host(bus->sdiodev->func[1]);
        }
 }
 
        /* precondition: IS_ALIGNED((unsigned long)frame, 2) */
 
        /* Make sure backplane clock is on */
-       down(&bus->sdsem);
+       sdio_claim_host(bus->sdiodev->func[1]);
        brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
-       up(&bus->sdsem);
+       sdio_release_host(bus->sdiodev->func[1]);
 
        /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
        *(__le16 *) frame = cpu_to_le16((u16) msglen);
                                   frame, min_t(u16, len, 16), "TxHdr:\n");
 
                do {
-                       down(&bus->sdsem);
+                       sdio_claim_host(bus->sdiodev->func[1]);
                        ret = brcmf_tx_frame(bus, frame, len);
-                       up(&bus->sdsem);
+                       sdio_release_host(bus->sdiodev->func[1]);
                } while (ret < 0 && retries++ < TXRETRIES);
        }
 
                spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
 
                bus->activity = false;
-               down(&bus->sdsem);
+               sdio_claim_host(bus->sdiodev->func[1]);
                brcmf_sdbrcm_clkctl(bus, CLK_NONE, true);
-               up(&bus->sdsem);
+               sdio_release_host(bus->sdiodev->func[1]);
        } else {
                spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
        }
         * Read last word in socram to determine
         * address of sdpcm_shared structure
         */
-       down(&bus->sdsem);
+       sdio_claim_host(bus->sdiodev->func[1]);
        rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
                                   (u8 *)&addr_le, 4);
-       up(&bus->sdsem);
+       sdio_claim_host(bus->sdiodev->func[1]);
        if (rv < 0)
                return rv;
 
        }
 
        /* Read hndrte_shared structure */
+       sdio_claim_host(bus->sdiodev->func[1]);
        rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
                                   sizeof(struct sdpcm_shared_le));
+       sdio_release_host(bus->sdiodev->func[1]);
        if (rv < 0)
                return rv;
 
        if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
                return 0;
 
-       down(&bus->sdsem);
+       sdio_claim_host(bus->sdiodev->func[1]);
        error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
                                      sizeof(struct brcmf_trap_info));
        if (error < 0)
                return error;
 
        nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
-       up(&bus->sdsem);
+       sdio_release_host(bus->sdiodev->func[1]);
        if (nbytes < 0)
                return nbytes;
 
                return 0;
        }
 
-       down(&bus->sdsem);
+       sdio_claim_host(bus->sdiodev->func[1]);
        if (sh->assert_file_addr != 0) {
                error = brcmf_sdbrcm_membytes(bus, false, sh->assert_file_addr,
                                              (u8 *)file, 80);
                if (error < 0)
                        return error;
        }
-       up(&bus->sdsem);
+       sdio_release_host(bus->sdiodev->func[1]);
 
        res = scnprintf(buf, sizeof(buf),
                        "dongle assert: %s:%d: assert(%s)\n",
 {
        bool ret;
 
-       /* Download the firmware */
+       sdio_claim_host(bus->sdiodev->func[1]);
+
        brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
 
        ret = _brcmf_sdbrcm_download_firmware(bus) == 0;
 
        brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false);
 
+       sdio_release_host(bus->sdiodev->func[1]);
+
        return ret;
 }
 
        bus->sdcnt.tickcnt = 0;
        brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
 
-       down(&bus->sdsem);
+       sdio_claim_host(bus->sdiodev->func[1]);
 
        /* Make sure backplane clock is on, needed to generate F2 interrupt */
        brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
                brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
 
 exit:
-       up(&bus->sdsem);
+       sdio_release_host(bus->sdiodev->func[1]);
 
        return ret;
 }
                                u8 devpend;
                                spin_unlock_irqrestore(&bus->dpc_tl_lock,
                                                       flags);
+                               sdio_claim_host(bus->sdiodev->func[1]);
                                devpend = brcmf_sdio_regrb(bus->sdiodev,
                                                           SDIO_CCCR_INTx,
                                                           NULL);
+                               sdio_release_host(bus->sdiodev->func[1]);
                                intstatus =
                                    devpend & (INTR_STATUS_FUNC1 |
                                               INTR_STATUS_FUNC2);
                bus->console.count += BRCMF_WD_POLL_MS;
                if (bus->console.count >= bus->console_interval) {
                        bus->console.count -= bus->console_interval;
-                       down(&bus->sdsem);
+                       sdio_claim_host(bus->sdiodev->func[1]);
                        /* Make sure backplane clock is on */
                        brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
                        if (brcmf_sdbrcm_readconsole(bus) < 0)
                                /* stop on error */
                                bus->console_interval = 0;
-                       up(&bus->sdsem);
+                       sdio_release_host(bus->sdiodev->func[1]);
                }
        }
 #endif                         /* DEBUG */
                                bus->activity = false;
                                brcmf_sdbrcm_wd_timer(bus, BRCMF_WD_POLL_MS);
                        } else {
-                               down(&bus->sdsem);
+                               sdio_claim_host(bus->sdiodev->func[1]);
                                brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
-                               up(&bus->sdsem);
+                               sdio_release_host(bus->sdiodev->func[1]);
                        }
                }
        }
 
        bus->alp_only = true;
 
+       sdio_claim_host(bus->sdiodev->func[1]);
+
        pr_debug("F1 signature read @0x18000000=0x%4x\n",
                 brcmf_sdio_regrl(bus->sdiodev, SI_ENUM_BASE, NULL));
 
        reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL);
        brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL);
 
+       sdio_release_host(bus->sdiodev->func[1]);
+
        brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
 
        /* Locate an appropriately-aligned portion of hdrbuf */
        return true;
 
 fail:
+       sdio_release_host(bus->sdiodev->func[1]);
        return false;
 }
 
 {
        brcmf_dbg(TRACE, "Enter\n");
 
+       sdio_claim_host(bus->sdiodev->func[1]);
+
        /* Disable F2 to clear any intermediate frame state on the dongle */
        brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx,
                         SDIO_FUNC_ENABLE_1, NULL);
        /* Done with backplane-dependent accesses, can drop clock... */
        brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
 
+       sdio_release_host(bus->sdiodev->func[1]);
+
        /* ...and initialize clock/power states */
        bus->clkstate = CLK_SDONLY;
        bus->idletime = BRCMF_IDLE_INTERVAL;
        brcmf_dbg(TRACE, "Enter\n");
 
        if (bus->ci) {
+               sdio_claim_host(bus->sdiodev->func[1]);
                brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
                brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
+               sdio_release_host(bus->sdiodev->func[1]);
                brcmf_sdio_chip_detach(&bus->ci);
                if (bus->vars && bus->varsz)
                        kfree(bus->vars);
        bus->timer.data = (unsigned long)bus;
        bus->timer.function = brcmf_sdbrcm_watchdog;
 
-       /* Initialize thread based operation and lock */
-       sema_init(&bus->sdsem, 1);
-
        /* Initialize watchdog thread */
        init_completion(&bus->watchdog_wait);
        bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread,