aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c228
1 files changed, 123 insertions, 105 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 29b1f24c2d0f..82f9140f3d35 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -422,9 +422,12 @@ struct brcmf_fws_macdesc_table {
422 422
423struct brcmf_fws_info { 423struct brcmf_fws_info {
424 struct brcmf_pub *drvr; 424 struct brcmf_pub *drvr;
425 spinlock_t spinlock;
426 ulong flags;
425 struct brcmf_fws_stats stats; 427 struct brcmf_fws_stats stats;
426 struct brcmf_fws_hanger hanger; 428 struct brcmf_fws_hanger hanger;
427 enum brcmf_fws_fcmode fcmode; 429 enum brcmf_fws_fcmode fcmode;
430 bool fw_signals;
428 bool bcmc_credit_check; 431 bool bcmc_credit_check;
429 struct brcmf_fws_macdesc_table desc; 432 struct brcmf_fws_macdesc_table desc;
430 struct workqueue_struct *fws_wq; 433 struct workqueue_struct *fws_wq;
@@ -483,6 +486,18 @@ static int brcmf_fws_get_tlv_len(struct brcmf_fws_info *fws,
483} 486}
484#undef BRCMF_FWS_TLV_DEF 487#undef BRCMF_FWS_TLV_DEF
485 488
489static void brcmf_fws_lock(struct brcmf_fws_info *fws)
490 __acquires(&fws->spinlock)
491{
492 spin_lock_irqsave(&fws->spinlock, fws->flags);
493}
494
495static void brcmf_fws_unlock(struct brcmf_fws_info *fws)
496 __releases(&fws->spinlock)
497{
498 spin_unlock_irqrestore(&fws->spinlock, fws->flags);
499}
500
486static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg) 501static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg)
487{ 502{
488 u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX); 503 u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
@@ -869,8 +884,11 @@ static bool brcmf_fws_tim_update(struct brcmf_fws_info *fws,
869 skcb->state = BRCMF_FWS_SKBSTATE_TIM; 884 skcb->state = BRCMF_FWS_SKBSTATE_TIM;
870 bus = fws->drvr->bus_if; 885 bus = fws->drvr->bus_if;
871 err = brcmf_fws_hdrpush(fws, skb); 886 err = brcmf_fws_hdrpush(fws, skb);
872 if (err == 0) 887 if (err == 0) {
888 brcmf_fws_unlock(fws);
873 err = brcmf_bus_txdata(bus, skb); 889 err = brcmf_bus_txdata(bus, skb);
890 brcmf_fws_lock(fws);
891 }
874 if (err) 892 if (err)
875 brcmu_pkt_buf_free_skb(skb); 893 brcmu_pkt_buf_free_skb(skb);
876 return true; 894 return true;
@@ -905,26 +923,10 @@ static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
905 return 0; 923 return 0;
906} 924}
907 925
908/* using macro so sparse checking does not complain
909 * about locking imbalance.
910 */
911#define brcmf_fws_lock(drvr, flags) \
912do { \
913 flags = 0; \
914 spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \
915} while (0)
916
917/* using macro so sparse checking does not complain
918 * about locking imbalance.
919 */
920#define brcmf_fws_unlock(drvr, flags) \
921 spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags))
922
923static 926static
924int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) 927int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
925{ 928{
926 struct brcmf_fws_mac_descriptor *entry, *existing; 929 struct brcmf_fws_mac_descriptor *entry, *existing;
927 ulong flags;
928 u8 mac_handle; 930 u8 mac_handle;
929 u8 ifidx; 931 u8 ifidx;
930 u8 *addr; 932 u8 *addr;
@@ -938,10 +940,10 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
938 if (entry->occupied) { 940 if (entry->occupied) {
939 brcmf_dbg(TRACE, "deleting %s mac %pM\n", 941 brcmf_dbg(TRACE, "deleting %s mac %pM\n",
940 entry->name, addr); 942 entry->name, addr);
941 brcmf_fws_lock(fws->drvr, flags); 943 brcmf_fws_lock(fws);
942 brcmf_fws_macdesc_cleanup(fws, entry, -1); 944 brcmf_fws_macdesc_cleanup(fws, entry, -1);
943 brcmf_fws_macdesc_deinit(entry); 945 brcmf_fws_macdesc_deinit(entry);
944 brcmf_fws_unlock(fws->drvr, flags); 946 brcmf_fws_unlock(fws);
945 } else 947 } else
946 fws->stats.mac_update_failed++; 948 fws->stats.mac_update_failed++;
947 return 0; 949 return 0;
@@ -950,13 +952,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
950 existing = brcmf_fws_macdesc_lookup(fws, addr); 952 existing = brcmf_fws_macdesc_lookup(fws, addr);
951 if (IS_ERR(existing)) { 953 if (IS_ERR(existing)) {
952 if (!entry->occupied) { 954 if (!entry->occupied) {
953 brcmf_fws_lock(fws->drvr, flags); 955 brcmf_fws_lock(fws);
954 entry->mac_handle = mac_handle; 956 entry->mac_handle = mac_handle;
955 brcmf_fws_macdesc_init(entry, addr, ifidx); 957 brcmf_fws_macdesc_init(entry, addr, ifidx);
956 brcmf_fws_macdesc_set_name(fws, entry); 958 brcmf_fws_macdesc_set_name(fws, entry);
957 brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, 959 brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
958 BRCMF_FWS_PSQ_LEN); 960 BRCMF_FWS_PSQ_LEN);
959 brcmf_fws_unlock(fws->drvr, flags); 961 brcmf_fws_unlock(fws);
960 brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr); 962 brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr);
961 } else { 963 } else {
962 fws->stats.mac_update_failed++; 964 fws->stats.mac_update_failed++;
@@ -964,13 +966,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
964 } else { 966 } else {
965 if (entry != existing) { 967 if (entry != existing) {
966 brcmf_dbg(TRACE, "copy mac %s\n", existing->name); 968 brcmf_dbg(TRACE, "copy mac %s\n", existing->name);
967 brcmf_fws_lock(fws->drvr, flags); 969 brcmf_fws_lock(fws);
968 memcpy(entry, existing, 970 memcpy(entry, existing,
969 offsetof(struct brcmf_fws_mac_descriptor, psq)); 971 offsetof(struct brcmf_fws_mac_descriptor, psq));
970 entry->mac_handle = mac_handle; 972 entry->mac_handle = mac_handle;
971 brcmf_fws_macdesc_deinit(existing); 973 brcmf_fws_macdesc_deinit(existing);
972 brcmf_fws_macdesc_set_name(fws, entry); 974 brcmf_fws_macdesc_set_name(fws, entry);
973 brcmf_fws_unlock(fws->drvr, flags); 975 brcmf_fws_unlock(fws);
974 brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name, 976 brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name,
975 addr); 977 addr);
976 } else { 978 } else {
@@ -986,7 +988,6 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
986 u8 type, u8 *data) 988 u8 type, u8 *data)
987{ 989{
988 struct brcmf_fws_mac_descriptor *entry; 990 struct brcmf_fws_mac_descriptor *entry;
989 ulong flags;
990 u8 mac_handle; 991 u8 mac_handle;
991 int ret; 992 int ret;
992 993
@@ -996,7 +997,7 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
996 fws->stats.mac_ps_update_failed++; 997 fws->stats.mac_ps_update_failed++;
997 return -ESRCH; 998 return -ESRCH;
998 } 999 }
999 brcmf_fws_lock(fws->drvr, flags); 1000 brcmf_fws_lock(fws);
1000 /* a state update should wipe old credits */ 1001 /* a state update should wipe old credits */
1001 entry->requested_credit = 0; 1002 entry->requested_credit = 0;
1002 entry->requested_packet = 0; 1003 entry->requested_packet = 0;
@@ -1011,7 +1012,7 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
1011 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true); 1012 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true);
1012 ret = BRCMF_FWS_RET_OK_NOSCHEDULE; 1013 ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
1013 } 1014 }
1014 brcmf_fws_unlock(fws->drvr, flags); 1015 brcmf_fws_unlock(fws);
1015 return ret; 1016 return ret;
1016} 1017}
1017 1018
@@ -1019,7 +1020,6 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
1019 u8 type, u8 *data) 1020 u8 type, u8 *data)
1020{ 1021{
1021 struct brcmf_fws_mac_descriptor *entry; 1022 struct brcmf_fws_mac_descriptor *entry;
1022 ulong flags;
1023 u8 ifidx; 1023 u8 ifidx;
1024 int ret; 1024 int ret;
1025 1025
@@ -1038,7 +1038,7 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
1038 1038
1039 brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type, 1039 brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type,
1040 entry->name); 1040 entry->name);
1041 brcmf_fws_lock(fws->drvr, flags); 1041 brcmf_fws_lock(fws);
1042 switch (type) { 1042 switch (type) {
1043 case BRCMF_FWS_TYPE_INTERFACE_OPEN: 1043 case BRCMF_FWS_TYPE_INTERFACE_OPEN:
1044 entry->state = BRCMF_FWS_STATE_OPEN; 1044 entry->state = BRCMF_FWS_STATE_OPEN;
@@ -1050,10 +1050,10 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
1050 break; 1050 break;
1051 default: 1051 default:
1052 ret = -EINVAL; 1052 ret = -EINVAL;
1053 brcmf_fws_unlock(fws->drvr, flags); 1053 brcmf_fws_unlock(fws);
1054 goto fail; 1054 goto fail;
1055 } 1055 }
1056 brcmf_fws_unlock(fws->drvr, flags); 1056 brcmf_fws_unlock(fws);
1057 return ret; 1057 return ret;
1058 1058
1059fail: 1059fail:
@@ -1065,7 +1065,6 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
1065 u8 *data) 1065 u8 *data)
1066{ 1066{
1067 struct brcmf_fws_mac_descriptor *entry; 1067 struct brcmf_fws_mac_descriptor *entry;
1068 ulong flags;
1069 1068
1070 entry = &fws->desc.nodes[data[1] & 0x1F]; 1069 entry = &fws->desc.nodes[data[1] & 0x1F];
1071 if (!entry->occupied) { 1070 if (!entry->occupied) {
@@ -1079,14 +1078,14 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
1079 brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n", 1078 brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n",
1080 brcmf_fws_get_tlv_name(type), type, entry->name, 1079 brcmf_fws_get_tlv_name(type), type, entry->name,
1081 data[0], data[2]); 1080 data[0], data[2]);
1082 brcmf_fws_lock(fws->drvr, flags); 1081 brcmf_fws_lock(fws);
1083 if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT) 1082 if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT)
1084 entry->requested_credit = data[0]; 1083 entry->requested_credit = data[0];
1085 else 1084 else
1086 entry->requested_packet = data[0]; 1085 entry->requested_packet = data[0];
1087 1086
1088 entry->ac_bitmap = data[2]; 1087 entry->ac_bitmap = data[2];
1089 brcmf_fws_unlock(fws->drvr, flags); 1088 brcmf_fws_unlock(fws);
1090 return BRCMF_FWS_RET_OK_SCHEDULE; 1089 return BRCMF_FWS_RET_OK_SCHEDULE;
1091} 1090}
1092 1091
@@ -1160,7 +1159,8 @@ static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
1160static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws) 1159static void brcmf_fws_schedule_deq(struct brcmf_fws_info *fws)
1161{ 1160{
1162 /* only schedule dequeue when there are credits for delayed traffic */ 1161 /* only schedule dequeue when there are credits for delayed traffic */
1163 if (fws->fifo_credit_map & fws->fifo_delay_map) 1162 if ((fws->fifo_credit_map & fws->fifo_delay_map) ||
1163 (!brcmf_fws_fc_active(fws) && fws->fifo_delay_map))
1164 queue_work(fws->fws_wq, &fws->fws_dequeue_work); 1164 queue_work(fws->fws_wq, &fws->fws_dequeue_work);
1165} 1165}
1166 1166
@@ -1383,7 +1383,6 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
1383static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws, 1383static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
1384 u8 *data) 1384 u8 *data)
1385{ 1385{
1386 ulong flags;
1387 int i; 1386 int i;
1388 1387
1389 if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) { 1388 if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
@@ -1392,19 +1391,18 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
1392 } 1391 }
1393 1392
1394 brcmf_dbg(DATA, "enter: data %pM\n", data); 1393 brcmf_dbg(DATA, "enter: data %pM\n", data);
1395 brcmf_fws_lock(fws->drvr, flags); 1394 brcmf_fws_lock(fws);
1396 for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++) 1395 for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++)
1397 brcmf_fws_return_credits(fws, i, data[i]); 1396 brcmf_fws_return_credits(fws, i, data[i]);
1398 1397
1399 brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map, 1398 brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map,
1400 fws->fifo_delay_map); 1399 fws->fifo_delay_map);
1401 brcmf_fws_unlock(fws->drvr, flags); 1400 brcmf_fws_unlock(fws);
1402 return BRCMF_FWS_RET_OK_SCHEDULE; 1401 return BRCMF_FWS_RET_OK_SCHEDULE;
1403} 1402}
1404 1403
1405static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) 1404static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
1406{ 1405{
1407 ulong lflags;
1408 __le32 status_le; 1406 __le32 status_le;
1409 u32 status; 1407 u32 status;
1410 u32 hslot; 1408 u32 hslot;
@@ -1418,9 +1416,9 @@ static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
1418 hslot = brcmf_txstatus_get_field(status, HSLOT); 1416 hslot = brcmf_txstatus_get_field(status, HSLOT);
1419 genbit = brcmf_txstatus_get_field(status, GENERATION); 1417 genbit = brcmf_txstatus_get_field(status, GENERATION);
1420 1418
1421 brcmf_fws_lock(fws->drvr, lflags); 1419 brcmf_fws_lock(fws);
1422 brcmf_fws_txs_process(fws, flags, hslot, genbit); 1420 brcmf_fws_txs_process(fws, flags, hslot, genbit);
1423 brcmf_fws_unlock(fws->drvr, lflags); 1421 brcmf_fws_unlock(fws);
1424 return BRCMF_FWS_RET_OK_NOSCHEDULE; 1422 return BRCMF_FWS_RET_OK_NOSCHEDULE;
1425} 1423}
1426 1424
@@ -1440,7 +1438,6 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
1440{ 1438{
1441 struct brcmf_fws_info *fws = ifp->drvr->fws; 1439 struct brcmf_fws_info *fws = ifp->drvr->fws;
1442 int i; 1440 int i;
1443 ulong flags;
1444 u8 *credits = data; 1441 u8 *credits = data;
1445 1442
1446 if (e->datalen < BRCMF_FWS_FIFO_COUNT) { 1443 if (e->datalen < BRCMF_FWS_FIFO_COUNT) {
@@ -1453,7 +1450,7 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
1453 fws->creditmap_received = true; 1450 fws->creditmap_received = true;
1454 1451
1455 brcmf_dbg(TRACE, "enter: credits %pM\n", credits); 1452 brcmf_dbg(TRACE, "enter: credits %pM\n", credits);
1456 brcmf_fws_lock(ifp->drvr, flags); 1453 brcmf_fws_lock(fws);
1457 for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) { 1454 for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++) {
1458 if (*credits) 1455 if (*credits)
1459 fws->fifo_credit_map |= 1 << i; 1456 fws->fifo_credit_map |= 1 << i;
@@ -1462,7 +1459,7 @@ static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
1462 fws->fifo_credit[i] = *credits++; 1459 fws->fifo_credit[i] = *credits++;
1463 } 1460 }
1464 brcmf_fws_schedule_deq(fws); 1461 brcmf_fws_schedule_deq(fws);
1465 brcmf_fws_unlock(ifp->drvr, flags); 1462 brcmf_fws_unlock(fws);
1466 return 0; 1463 return 0;
1467} 1464}
1468 1465
@@ -1471,18 +1468,18 @@ static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp,
1471 void *data) 1468 void *data)
1472{ 1469{
1473 struct brcmf_fws_info *fws = ifp->drvr->fws; 1470 struct brcmf_fws_info *fws = ifp->drvr->fws;
1474 ulong flags;
1475 1471
1476 brcmf_fws_lock(ifp->drvr, flags); 1472 brcmf_fws_lock(fws);
1477 if (fws) 1473 if (fws)
1478 fws->bcmc_credit_check = true; 1474 fws->bcmc_credit_check = true;
1479 brcmf_fws_unlock(ifp->drvr, flags); 1475 brcmf_fws_unlock(fws);
1480 return 0; 1476 return 0;
1481} 1477}
1482 1478
1483int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, 1479int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
1484 struct sk_buff *skb) 1480 struct sk_buff *skb)
1485{ 1481{
1482 struct brcmf_skb_reorder_data *rd;
1486 struct brcmf_fws_info *fws = drvr->fws; 1483 struct brcmf_fws_info *fws = drvr->fws;
1487 u8 *signal_data; 1484 u8 *signal_data;
1488 s16 data_len; 1485 s16 data_len;
@@ -1497,8 +1494,10 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
1497 1494
1498 WARN_ON(signal_len > skb->len); 1495 WARN_ON(signal_len > skb->len);
1499 1496
1497 if (!signal_len)
1498 return 0;
1500 /* if flow control disabled, skip to packet data and leave */ 1499 /* if flow control disabled, skip to packet data and leave */
1501 if (!signal_len || !drvr->fw_signals) { 1500 if (!fws->fw_signals) {
1502 skb_pull(skb, signal_len); 1501 skb_pull(skb, signal_len);
1503 return 0; 1502 return 0;
1504 } 1503 }
@@ -1536,9 +1535,12 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
1536 1535
1537 err = BRCMF_FWS_RET_OK_NOSCHEDULE; 1536 err = BRCMF_FWS_RET_OK_NOSCHEDULE;
1538 switch (type) { 1537 switch (type) {
1539 case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
1540 case BRCMF_FWS_TYPE_COMP_TXSTATUS: 1538 case BRCMF_FWS_TYPE_COMP_TXSTATUS:
1541 break; 1539 break;
1540 case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
1541 rd = (struct brcmf_skb_reorder_data *)skb->cb;
1542 rd->reorder = data;
1543 break;
1542 case BRCMF_FWS_TYPE_MACDESC_ADD: 1544 case BRCMF_FWS_TYPE_MACDESC_ADD:
1543 case BRCMF_FWS_TYPE_MACDESC_DEL: 1545 case BRCMF_FWS_TYPE_MACDESC_DEL:
1544 brcmf_fws_macdesc_indicate(fws, type, data); 1546 brcmf_fws_macdesc_indicate(fws, type, data);
@@ -1694,17 +1696,22 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
1694 return PTR_ERR(entry); 1696 return PTR_ERR(entry);
1695 1697
1696 brcmf_fws_precommit_skb(fws, fifo, skb); 1698 brcmf_fws_precommit_skb(fws, fifo, skb);
1699 entry->transit_count++;
1700 if (entry->suppressed)
1701 entry->suppr_transit_count++;
1702 brcmf_fws_unlock(fws);
1697 rc = brcmf_bus_txdata(bus, skb); 1703 rc = brcmf_bus_txdata(bus, skb);
1704 brcmf_fws_lock(fws);
1698 brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name, 1705 brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name,
1699 skcb->if_flags, skcb->htod, rc); 1706 skcb->if_flags, skcb->htod, rc);
1700 if (rc < 0) { 1707 if (rc < 0) {
1708 entry->transit_count--;
1709 if (entry->suppressed)
1710 entry->suppr_transit_count--;
1701 brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); 1711 brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
1702 goto rollback; 1712 goto rollback;
1703 } 1713 }
1704 1714
1705 entry->transit_count++;
1706 if (entry->suppressed)
1707 entry->suppr_transit_count++;
1708 fws->stats.pkt2bus++; 1715 fws->stats.pkt2bus++;
1709 fws->stats.send_pkts[fifo]++; 1716 fws->stats.send_pkts[fifo]++;
1710 if (brcmf_skb_if_flags_get_field(skb, REQUESTED)) 1717 if (brcmf_skb_if_flags_get_field(skb, REQUESTED))
@@ -1741,11 +1748,11 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
1741 struct brcmf_fws_info *fws = drvr->fws; 1748 struct brcmf_fws_info *fws = drvr->fws;
1742 struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb); 1749 struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
1743 struct ethhdr *eh = (struct ethhdr *)(skb->data); 1750 struct ethhdr *eh = (struct ethhdr *)(skb->data);
1744 ulong flags;
1745 int fifo = BRCMF_FWS_FIFO_BCMC; 1751 int fifo = BRCMF_FWS_FIFO_BCMC;
1746 bool multicast = is_multicast_ether_addr(eh->h_dest); 1752 bool multicast = is_multicast_ether_addr(eh->h_dest);
1747 bool pae = eh->h_proto == htons(ETH_P_PAE); 1753 bool pae = eh->h_proto == htons(ETH_P_PAE);
1748 1754
1755 brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto));
1749 /* determine the priority */ 1756 /* determine the priority */
1750 if (!skb->priority) 1757 if (!skb->priority)
1751 skb->priority = cfg80211_classify8021d(skb); 1758 skb->priority = cfg80211_classify8021d(skb);
@@ -1754,14 +1761,6 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
1754 if (pae) 1761 if (pae)
1755 atomic_inc(&ifp->pend_8021x_cnt); 1762 atomic_inc(&ifp->pend_8021x_cnt);
1756 1763
1757 if (!brcmf_fws_fc_active(fws)) {
1758 /* If the protocol uses a data header, apply it */
1759 brcmf_proto_hdrpush(drvr, ifp->ifidx, 0, skb);
1760
1761 /* Use bus module to send data frame */
1762 return brcmf_bus_txdata(drvr->bus_if, skb);
1763 }
1764
1765 /* set control buffer information */ 1764 /* set control buffer information */
1766 skcb->if_flags = 0; 1765 skcb->if_flags = 0;
1767 skcb->state = BRCMF_FWS_SKBSTATE_NEW; 1766 skcb->state = BRCMF_FWS_SKBSTATE_NEW;
@@ -1769,7 +1768,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
1769 if (!multicast) 1768 if (!multicast)
1770 fifo = brcmf_fws_prio2fifo[skb->priority]; 1769 fifo = brcmf_fws_prio2fifo[skb->priority];
1771 1770
1772 brcmf_fws_lock(drvr, flags); 1771 brcmf_fws_lock(fws);
1773 if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC) 1772 if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC)
1774 fws->borrow_defer_timestamp = jiffies + 1773 fws->borrow_defer_timestamp = jiffies +
1775 BRCMF_FWS_BORROW_DEFER_PERIOD; 1774 BRCMF_FWS_BORROW_DEFER_PERIOD;
@@ -1789,7 +1788,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
1789 } 1788 }
1790 brcmu_pkt_buf_free_skb(skb); 1789 brcmu_pkt_buf_free_skb(skb);
1791 } 1790 }
1792 brcmf_fws_unlock(drvr, flags); 1791 brcmf_fws_unlock(fws);
1793 return 0; 1792 return 0;
1794} 1793}
1795 1794
@@ -1809,7 +1808,7 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
1809 struct brcmf_fws_info *fws = ifp->drvr->fws; 1808 struct brcmf_fws_info *fws = ifp->drvr->fws;
1810 struct brcmf_fws_mac_descriptor *entry; 1809 struct brcmf_fws_mac_descriptor *entry;
1811 1810
1812 if (!ifp->ndev || !ifp->drvr->fw_signals) 1811 if (!ifp->ndev)
1813 return; 1812 return;
1814 1813
1815 entry = &fws->desc.iface[ifp->ifidx]; 1814 entry = &fws->desc.iface[ifp->ifidx];
@@ -1824,31 +1823,54 @@ void brcmf_fws_add_interface(struct brcmf_if *ifp)
1824void brcmf_fws_del_interface(struct brcmf_if *ifp) 1823void brcmf_fws_del_interface(struct brcmf_if *ifp)
1825{ 1824{
1826 struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc; 1825 struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
1827 ulong flags;
1828 1826
1829 if (!entry) 1827 if (!entry)
1830 return; 1828 return;
1831 1829
1832 brcmf_fws_lock(ifp->drvr, flags); 1830 brcmf_fws_lock(ifp->drvr->fws);
1833 ifp->fws_desc = NULL; 1831 ifp->fws_desc = NULL;
1834 brcmf_dbg(TRACE, "deleting %s\n", entry->name); 1832 brcmf_dbg(TRACE, "deleting %s\n", entry->name);
1835 brcmf_fws_macdesc_deinit(entry); 1833 brcmf_fws_macdesc_deinit(entry);
1836 brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx); 1834 brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx);
1837 brcmf_fws_unlock(ifp->drvr, flags); 1835 brcmf_fws_unlock(ifp->drvr->fws);
1838} 1836}
1839 1837
1840static void brcmf_fws_dequeue_worker(struct work_struct *worker) 1838static void brcmf_fws_dequeue_worker(struct work_struct *worker)
1841{ 1839{
1842 struct brcmf_fws_info *fws; 1840 struct brcmf_fws_info *fws;
1841 struct brcmf_pub *drvr;
1843 struct sk_buff *skb; 1842 struct sk_buff *skb;
1844 ulong flags;
1845 int fifo; 1843 int fifo;
1844 u32 hslot;
1845 u32 ifidx;
1846 int ret;
1846 1847
1847 fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work); 1848 fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work);
1849 drvr = fws->drvr;
1848 1850
1849 brcmf_fws_lock(fws->drvr, flags); 1851 brcmf_fws_lock(fws);
1850 for (fifo = BRCMF_FWS_FIFO_BCMC; fifo >= 0 && !fws->bus_flow_blocked; 1852 for (fifo = BRCMF_FWS_FIFO_BCMC; fifo >= 0 && !fws->bus_flow_blocked;
1851 fifo--) { 1853 fifo--) {
1854 if (!brcmf_fws_fc_active(fws)) {
1855 while ((skb = brcmf_fws_deq(fws, fifo)) != NULL) {
1856 hslot = brcmf_skb_htod_tag_get_field(skb,
1857 HSLOT);
1858 brcmf_fws_hanger_poppkt(&fws->hanger, hslot,
1859 &skb, true);
1860 ifidx = brcmf_skb_if_flags_get_field(skb,
1861 INDEX);
1862 brcmf_proto_hdrpush(drvr, ifidx, 0, skb);
1863 /* Use bus module to send data frame */
1864 brcmf_fws_unlock(fws);
1865 ret = brcmf_bus_txdata(drvr->bus_if, skb);
1866 brcmf_fws_lock(fws);
1867 if (ret < 0)
1868 brcmf_txfinalize(drvr, skb, false);
1869 if (fws->bus_flow_blocked)
1870 break;
1871 }
1872 continue;
1873 }
1852 while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) && 1874 while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) &&
1853 (fifo == BRCMF_FWS_FIFO_BCMC))) { 1875 (fifo == BRCMF_FWS_FIFO_BCMC))) {
1854 skb = brcmf_fws_deq(fws, fifo); 1876 skb = brcmf_fws_deq(fws, fifo);
@@ -1876,42 +1898,43 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
1876 } 1898 }
1877 } 1899 }
1878 } 1900 }
1879 brcmf_fws_unlock(fws->drvr, flags); 1901 brcmf_fws_unlock(fws);
1880} 1902}
1881 1903
1882int brcmf_fws_init(struct brcmf_pub *drvr) 1904int brcmf_fws_init(struct brcmf_pub *drvr)
1883{ 1905{
1906 struct brcmf_fws_info *fws;
1884 u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS; 1907 u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS;
1885 int rc; 1908 int rc;
1886 1909
1887 if (!drvr->fw_signals)
1888 return 0;
1889
1890 spin_lock_init(&drvr->fws_spinlock);
1891
1892 drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL); 1910 drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL);
1893 if (!drvr->fws) { 1911 if (!drvr->fws) {
1894 rc = -ENOMEM; 1912 rc = -ENOMEM;
1895 goto fail; 1913 goto fail;
1896 } 1914 }
1897 1915
1916 fws = drvr->fws;
1917
1918 spin_lock_init(&fws->spinlock);
1919
1898 /* set linkage back */ 1920 /* set linkage back */
1899 drvr->fws->drvr = drvr; 1921 fws->drvr = drvr;
1900 drvr->fws->fcmode = fcmode; 1922 fws->fcmode = fcmode;
1901 1923
1902 drvr->fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq"); 1924 fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
1903 if (drvr->fws->fws_wq == NULL) { 1925 if (fws->fws_wq == NULL) {
1904 brcmf_err("workqueue creation failed\n"); 1926 brcmf_err("workqueue creation failed\n");
1905 rc = -EBADF; 1927 rc = -EBADF;
1906 goto fail; 1928 goto fail;
1907 } 1929 }
1908 INIT_WORK(&drvr->fws->fws_dequeue_work, brcmf_fws_dequeue_worker); 1930 INIT_WORK(&fws->fws_dequeue_work, brcmf_fws_dequeue_worker);
1909 1931
1910 /* enable firmware signalling if fcmode active */ 1932 /* enable firmware signalling if fcmode active */
1911 if (drvr->fws->fcmode != BRCMF_FWS_FCMODE_NONE) 1933 if (fws->fcmode != BRCMF_FWS_FCMODE_NONE)
1912 tlv |= BRCMF_FWS_FLAGS_XONXOFF_SIGNALS | 1934 tlv |= BRCMF_FWS_FLAGS_XONXOFF_SIGNALS |
1913 BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS | 1935 BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS |
1914 BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE; 1936 BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE |
1937 BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE;
1915 1938
1916 rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP, 1939 rc = brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
1917 brcmf_fws_notify_credit_map); 1940 brcmf_fws_notify_credit_map);
@@ -1927,31 +1950,33 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
1927 goto fail; 1950 goto fail;
1928 } 1951 }
1929 1952
1930 /* setting the iovar may fail if feature is unsupported 1953 /* Setting the iovar may fail if feature is unsupported
1931 * so leave the rc as is so driver initialization can 1954 * so leave the rc as is so driver initialization can
1932 * continue. 1955 * continue. Set mode back to none indicating not enabled.
1933 */ 1956 */
1957 fws->fw_signals = true;
1934 if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) { 1958 if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) {
1935 brcmf_err("failed to set bdcv2 tlv signaling\n"); 1959 brcmf_err("failed to set bdcv2 tlv signaling\n");
1936 goto fail_event; 1960 fws->fcmode = BRCMF_FWS_FCMODE_NONE;
1961 fws->fw_signals = false;
1937 } 1962 }
1938 1963
1939 brcmf_fws_hanger_init(&drvr->fws->hanger); 1964 if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1))
1940 brcmf_fws_macdesc_init(&drvr->fws->desc.other, NULL, 0); 1965 brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n");
1941 brcmf_fws_macdesc_set_name(drvr->fws, &drvr->fws->desc.other); 1966
1942 brcmu_pktq_init(&drvr->fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT, 1967 brcmf_fws_hanger_init(&fws->hanger);
1968 brcmf_fws_macdesc_init(&fws->desc.other, NULL, 0);
1969 brcmf_fws_macdesc_set_name(fws, &fws->desc.other);
1970 brcmu_pktq_init(&fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT,
1943 BRCMF_FWS_PSQ_LEN); 1971 BRCMF_FWS_PSQ_LEN);
1944 1972
1945 /* create debugfs file for statistics */ 1973 /* create debugfs file for statistics */
1946 brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats); 1974 brcmf_debugfs_create_fws_stats(drvr, &fws->stats);
1947 1975
1948 brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n", 1976 brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n",
1949 drvr->fw_signals ? "enabled" : "disabled", tlv); 1977 fws->fw_signals ? "enabled" : "disabled", tlv);
1950 return 0; 1978 return 0;
1951 1979
1952fail_event:
1953 brcmf_fweh_unregister(drvr, BRCMF_E_BCMC_CREDIT_SUPPORT);
1954 brcmf_fweh_unregister(drvr, BRCMF_E_FIFO_CREDIT_MAP);
1955fail: 1980fail:
1956 brcmf_fws_deinit(drvr); 1981 brcmf_fws_deinit(drvr);
1957 return rc; 1982 return rc;
@@ -1960,24 +1985,18 @@ fail:
1960void brcmf_fws_deinit(struct brcmf_pub *drvr) 1985void brcmf_fws_deinit(struct brcmf_pub *drvr)
1961{ 1986{
1962 struct brcmf_fws_info *fws = drvr->fws; 1987 struct brcmf_fws_info *fws = drvr->fws;
1963 ulong flags;
1964 1988
1965 if (!fws) 1989 if (!fws)
1966 return; 1990 return;
1967 1991
1968 /* disable firmware signalling entirely
1969 * to avoid using the workqueue.
1970 */
1971 drvr->fw_signals = false;
1972
1973 if (drvr->fws->fws_wq) 1992 if (drvr->fws->fws_wq)
1974 destroy_workqueue(drvr->fws->fws_wq); 1993 destroy_workqueue(drvr->fws->fws_wq);
1975 1994
1976 /* cleanup */ 1995 /* cleanup */
1977 brcmf_fws_lock(drvr, flags); 1996 brcmf_fws_lock(fws);
1978 brcmf_fws_cleanup(fws, -1); 1997 brcmf_fws_cleanup(fws, -1);
1979 drvr->fws = NULL; 1998 drvr->fws = NULL;
1980 brcmf_fws_unlock(drvr, flags); 1999 brcmf_fws_unlock(fws);
1981 2000
1982 /* free top structure */ 2001 /* free top structure */
1983 kfree(fws); 2002 kfree(fws);
@@ -1985,7 +2004,7 @@ void brcmf_fws_deinit(struct brcmf_pub *drvr)
1985 2004
1986bool brcmf_fws_fc_active(struct brcmf_fws_info *fws) 2005bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
1987{ 2006{
1988 if (!fws) 2007 if (!fws->creditmap_received)
1989 return false; 2008 return false;
1990 2009
1991 return fws->fcmode != BRCMF_FWS_FCMODE_NONE; 2010 return fws->fcmode != BRCMF_FWS_FCMODE_NONE;
@@ -1993,17 +2012,16 @@ bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
1993 2012
1994void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb) 2013void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
1995{ 2014{
1996 ulong flags;
1997 u32 hslot; 2015 u32 hslot;
1998 2016
1999 if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_TIM) { 2017 if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_TIM) {
2000 brcmu_pkt_buf_free_skb(skb); 2018 brcmu_pkt_buf_free_skb(skb);
2001 return; 2019 return;
2002 } 2020 }
2003 brcmf_fws_lock(fws->drvr, flags); 2021 brcmf_fws_lock(fws);
2004 hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); 2022 hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
2005 brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0); 2023 brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0);
2006 brcmf_fws_unlock(fws->drvr, flags); 2024 brcmf_fws_unlock(fws);
2007} 2025}
2008 2026
2009void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked) 2027void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked)