brcmfmac: schedule dequeue upon firmware-signal reception
authorArend van Spriel <arend@broadcom.com>
Wed, 17 Apr 2013 19:25:54 +0000 (21:25 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 22 Apr 2013 19:20:22 +0000 (15:20 -0400)
Several firmware signals should be considered as opportunity to
send packets to the firmware. This patch adds conditional scheduling
of the dequeue worker thread while handling those signals.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c

index 0d2ff60e925d4083a6189f128a500426ce358aa4..648f9bd89dacc086a0fb9290c2ee778085cb9b8a 100644 (file)
@@ -147,6 +147,9 @@ static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
 #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST                        0x01
 #define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED              0x02
 
+#define BRCMF_FWS_RET_OK_NOSCHEDULE    0
+#define BRCMF_FWS_RET_OK_SCHEDULE      1
+
 /**
  * enum brcmf_fws_skb_state - indicates processing state of skb.
  *
@@ -920,12 +923,13 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
        entry->requested_credit = 0;
        if (type == BRCMF_FWS_TYPE_MAC_OPEN) {
                entry->state = BRCMF_FWS_STATE_OPEN;
+               return BRCMF_FWS_RET_OK_SCHEDULE;
        } else {
                entry->state = BRCMF_FWS_STATE_CLOSE;
                for (i = BRCMF_FWS_FIFO_AC_BE; i < NL80211_NUM_ACS; i++)
                        brcmf_fws_tim_update(fws, entry, i);
        }
-       return 0;
+       return BRCMF_FWS_RET_OK_NOSCHEDULE;
 }
 
 static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
@@ -952,10 +956,10 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
        switch (type) {
        case BRCMF_FWS_TYPE_INTERFACE_OPEN:
                entry->state = BRCMF_FWS_STATE_OPEN;
-               return 0;
+               return BRCMF_FWS_RET_OK_SCHEDULE;
        case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
                entry->state = BRCMF_FWS_STATE_CLOSE;
-               return 0;
+               return BRCMF_FWS_RET_OK_NOSCHEDULE;
        default:
                ret = -EINVAL;
                break;
@@ -985,7 +989,7 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
                entry->requested_packet = data[0];
 
        entry->ac_bitmap = data[2];
-       return 0;
+       return BRCMF_FWS_RET_OK_SCHEDULE;
 }
 
 static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
@@ -1259,7 +1263,7 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
 
        if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
                brcmf_dbg(INFO, "ignored\n");
-               return 0;
+               return BRCMF_FWS_RET_OK_NOSCHEDULE;
        }
 
        brcmf_dbg(TRACE, "enter: data %pM\n", data);
@@ -1268,8 +1272,7 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
 
        brcmf_dbg(INFO, "map: credit %x delay %x\n", fws->fifo_credit_map,
                  fws->fifo_delay_map);
-       brcmf_fws_schedule_deq(fws);
-       return 0;
+       return BRCMF_FWS_RET_OK_SCHEDULE;
 }
 
 static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
@@ -1353,6 +1356,8 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
        u8 type;
        u8 len;
        u8 *data;
+       s32 status;
+       s32 err;
 
        brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n",
                  ifidx, skb->len, signal_len);
@@ -1372,6 +1377,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
        data_len = signal_len;
        signal_data = skb->data;
 
+       status = BRCMF_FWS_RET_OK_NOSCHEDULE;
        while (data_len > 0) {
                /* extract tlv info */
                type = signal_data[0];
@@ -1397,6 +1403,7 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
                if (len != brcmf_fws_get_tlv_len(fws, type))
                        break;
 
+               err = BRCMF_FWS_RET_OK_NOSCHEDULE;
                switch (type) {
                case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
                case BRCMF_FWS_TYPE_COMP_TXSTATUS:
@@ -1407,21 +1414,22 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
                        break;
                case BRCMF_FWS_TYPE_MAC_OPEN:
                case BRCMF_FWS_TYPE_MAC_CLOSE:
-                       brcmf_fws_macdesc_state_indicate(fws, type, data);
+                       err = brcmf_fws_macdesc_state_indicate(fws, type, data);
                        break;
                case BRCMF_FWS_TYPE_INTERFACE_OPEN:
                case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
-                       brcmf_fws_interface_state_indicate(fws, type, data);
+                       err = brcmf_fws_interface_state_indicate(fws, type,
+                                                                data);
                        break;
                case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT:
                case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET:
-                       brcmf_fws_request_indicate(fws, type, data);
+                       err = brcmf_fws_request_indicate(fws, type, data);
                        break;
                case BRCMF_FWS_TYPE_TXSTATUS:
                        brcmf_fws_txstatus_indicate(fws, data);
                        break;
                case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
-                       brcmf_fws_fifocreditback_indicate(fws, data);
+                       err = brcmf_fws_fifocreditback_indicate(fws, data);
                        break;
                case BRCMF_FWS_TYPE_RSSI:
                        brcmf_fws_rssi_indicate(fws, *data);
@@ -1435,7 +1443,8 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
                        fws->stats.tlv_invalid_type++;
                        break;
                }
-
+               if (err == BRCMF_FWS_RET_OK_SCHEDULE)
+                       status = BRCMF_FWS_RET_OK_SCHEDULE;
                signal_data += len + 2;
                data_len -= len + 2;
        }
@@ -1443,6 +1452,9 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
        if (data_len != 0)
                fws->stats.tlv_parse_failed++;
 
+       if (status == BRCMF_FWS_RET_OK_SCHEDULE)
+               brcmf_fws_schedule_deq(fws);
+
        /* signalling processing result does
         * not affect the actual ethernet packet.
         */