Commit 4dd8b26a authored by Hante Meuleman's avatar Hante Meuleman Committed by Kalle Valo
Browse files

brcmfmac: use SDIO DPC for control frames.



Control frames are normally handled outside DPC, but sometimes
within DPC. To simplify code always handle control within DPC.

Reviewed-by: default avatarArend Van Spriel <arend@broadcom.com>
Reviewed-by: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: default avatarDaniel (Deognyoun) Kim <dekim@broadcom.com>
Signed-off-by: default avatarHante Meuleman <meuleman@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 69d03ee0
Loading
Loading
Loading
Loading
+33 −54
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#include "firmware.h"

#define DCMD_RESP_TIMEOUT	2000	/* In milli second */
#define CTL_DONE_TIMEOUT	2000	/* In milli second */

#ifdef DEBUG

@@ -495,9 +496,9 @@ struct brcmf_sdio {
	u8 *ctrl_frame_buf;
	u16 ctrl_frame_len;
	bool ctrl_frame_stat;
	int ctrl_frame_err;

	spinlock_t txq_lock;		/* protect bus->txq */
	struct semaphore tx_seq_lock;	/* protect bus->tx_seq */
	wait_queue_head_t ctrl_wait;
	wait_queue_head_t dcmd_resp_wait;

@@ -2376,8 +2377,6 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes)
	/* Send frames until the limit or some other event */
	for (cnt = 0; (cnt < maxframes) && data_ok(bus);) {
		pkt_num = 1;
		if (down_interruptible(&bus->tx_seq_lock))
			return cnt;
		if (bus->txglom)
			pkt_num = min_t(u8, bus->tx_max - bus->tx_seq,
					bus->sdiodev->txglomsz);
@@ -2393,13 +2392,10 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes)
			__skb_queue_tail(&pktq, pkt);
		}
		spin_unlock_bh(&bus->txq_lock);
		if (i == 0) {
			up(&bus->tx_seq_lock);
		if (i == 0)
			break;
		}

		ret = brcmf_sdio_txpkt(bus, &pktq, SDPCM_DATA_CHANNEL);
		up(&bus->tx_seq_lock);

		cnt += i;

@@ -2743,18 +2739,15 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
	brcmf_sdio_clrintr(bus);

	if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) &&
	    (down_interruptible(&bus->tx_seq_lock) == 0)) {
		if (data_ok(bus)) {
	    data_ok(bus)) {
		sdio_claim_host(bus->sdiodev->func[1]);
		err = brcmf_sdio_tx_ctrlframe(bus,  bus->ctrl_frame_buf,
					      bus->ctrl_frame_len);
		sdio_release_host(bus->sdiodev->func[1]);

		bus->ctrl_frame_err = err;
		bus->ctrl_frame_stat = false;
		brcmf_sdio_wait_event_wakeup(bus);
	}
		up(&bus->tx_seq_lock);
	}
	/* Send queued frames (limit 1 if rx may still be pending) */
	if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) &&
	    brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit &&
@@ -2965,43 +2958,30 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
	struct brcmf_sdio *bus = sdiodev->bus;
	int ret = -1;
	int ret;

	brcmf_dbg(TRACE, "Enter\n");

	if (down_interruptible(&bus->tx_seq_lock))
		return -EINTR;

	if (!data_ok(bus)) {
		brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n",
			  bus->tx_max, bus->tx_seq);
		up(&bus->tx_seq_lock);
	/* Send from dpc */
	bus->ctrl_frame_buf = msg;
	bus->ctrl_frame_len = msglen;
	bus->ctrl_frame_stat = true;
	if (atomic_read(&bus->dpc_tskcnt) == 0) {
		atomic_inc(&bus->dpc_tskcnt);
		queue_work(bus->brcmf_wq, &bus->datawork);
	}

		wait_event_interruptible_timeout(bus->ctrl_wait,
						 !bus->ctrl_frame_stat,
						 msecs_to_jiffies(2000));
	wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat,
					 msecs_to_jiffies(CTL_DONE_TIMEOUT));

	if (!bus->ctrl_frame_stat) {
			brcmf_dbg(SDIO, "ctrl_frame_stat == false\n");
			ret = 0;
		brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
			  bus->ctrl_frame_err);
		ret = bus->ctrl_frame_err;
	} else {
			brcmf_dbg(SDIO, "ctrl_frame_stat == true\n");
		brcmf_dbg(SDIO, "ctrl_frame timeout\n");
		bus->ctrl_frame_stat = false;
			if (down_interruptible(&bus->tx_seq_lock))
				return -EINTR;
			ret = -1;
		}
	}
	if (ret == -1) {
		sdio_claim_host(bus->sdiodev->func[1]);
		brcmf_sdio_bus_sleep(bus, false, false);
		ret = brcmf_sdio_tx_ctrlframe(bus, msg, msglen);
		sdio_release_host(bus->sdiodev->func[1]);
		up(&bus->tx_seq_lock);
		ret = -ETIMEDOUT;
	}

	if (ret)
@@ -3009,7 +2989,7 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
	else
		bus->sdcnt.tx_ctlpkts++;

	return ret ? -EIO : 0;
	return ret;
}

#ifdef DEBUG
@@ -4165,7 +4145,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)

	spin_lock_init(&bus->rxctl_lock);
	spin_lock_init(&bus->txq_lock);
	sema_init(&bus->tx_seq_lock, 1);
	init_waitqueue_head(&bus->ctrl_wait);
	init_waitqueue_head(&bus->dcmd_resp_wait);