Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4061f895 authored by Arend van Spriel's avatar Arend van Spriel Committed by John W. Linville
Browse files

brcmfmac: use irq safe spinlock in brcmf_sdbrcm_txdata()



Firmware-signalling needs transmit to firmware to be atomic and
uses a spinlock with irq disabled. Therefor, brcmf_sdbrcm_txdata()
should not use spin_unlock_bh() as it would enable the interrupts.

Reviewed-by: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 74ea1f45
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -36,7 +36,11 @@ struct brcmf_bus_dcmd {
 *
 * @init: prepare for communication with dongle.
 * @stop: clear pending frames, disable data flow.
 * @txdata: send a data frame to the dongle (callee disposes skb).
 * @txdata: send a data frame to the dongle. When the data
 *	has been transferred, the common driver must be
 *	notified using brcmf_txcomplete(). The common
 *	driver calls this function with interrupts
 *	disabled.
 * @txctl: transmit a control request message to dongle.
 * @rxctl: receive a control response message from dongle.
 * @gettxq: obtain a reference of bus transmit queue (optional).
+3 −2
Original line number Diff line number Diff line
@@ -2276,6 +2276,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
	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;
	ulong flags;

	brcmf_dbg(TRACE, "Enter\n");

@@ -2293,7 +2294,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
	bus->sdcnt.fcqueued++;

	/* Priority based enq */
	spin_lock_bh(&bus->txqlock);
	spin_lock_irqsave(&bus->txqlock, flags);
	if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) {
		skb_pull(pkt, SDPCM_HDRLEN);
		brcmf_txcomplete(bus->sdiodev->dev, pkt, false);
@@ -2307,7 +2308,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
		bus->txoff = true;
		brcmf_txflowblock(bus->sdiodev->dev, true);
	}
	spin_unlock_bh(&bus->txqlock);
	spin_unlock_irqrestore(&bus->txqlock, flags);

#ifdef DEBUG
	if (pktq_plen(&bus->txq, prec) > qcount[prec])