aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2013-06-26 08:20:21 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-06-27 13:42:19 -0400
commitc6a681ab2c73c1296b4214307216dffeb52558df (patch)
treedd332a6536e23bd59b12ca0533a6cff172cad5b6
parent80898a117895235587b7dde63e3240e4f4d440c1 (diff)
brcmfmac: reduce firmware-signalling locking scope in rx path
In the receive path a spinlock is taken upon parsing the TLV signal header. This moves to locking to the TLV handling functions where it protects the data structures. 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>
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c77
1 files changed, 51 insertions, 26 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index e92a3ce58c02..f0d9f7f6c83d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -905,10 +905,26 @@ static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
905 return 0; 905 return 0;
906} 906}
907 907
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
908static 923static
909int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data) 924int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
910{ 925{
911 struct brcmf_fws_mac_descriptor *entry, *existing; 926 struct brcmf_fws_mac_descriptor *entry, *existing;
927 ulong flags;
912 u8 mac_handle; 928 u8 mac_handle;
913 u8 ifidx; 929 u8 ifidx;
914 u8 *addr; 930 u8 *addr;
@@ -922,8 +938,10 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
922 if (entry->occupied) { 938 if (entry->occupied) {
923 brcmf_dbg(TRACE, "deleting %s mac %pM\n", 939 brcmf_dbg(TRACE, "deleting %s mac %pM\n",
924 entry->name, addr); 940 entry->name, addr);
941 brcmf_fws_lock(fws->drvr, flags);
925 brcmf_fws_macdesc_cleanup(fws, entry, -1); 942 brcmf_fws_macdesc_cleanup(fws, entry, -1);
926 brcmf_fws_macdesc_deinit(entry); 943 brcmf_fws_macdesc_deinit(entry);
944 brcmf_fws_unlock(fws->drvr, flags);
927 } else 945 } else
928 fws->stats.mac_update_failed++; 946 fws->stats.mac_update_failed++;
929 return 0; 947 return 0;
@@ -932,11 +950,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
932 existing = brcmf_fws_macdesc_lookup(fws, addr); 950 existing = brcmf_fws_macdesc_lookup(fws, addr);
933 if (IS_ERR(existing)) { 951 if (IS_ERR(existing)) {
934 if (!entry->occupied) { 952 if (!entry->occupied) {
953 brcmf_fws_lock(fws->drvr, flags);
935 entry->mac_handle = mac_handle; 954 entry->mac_handle = mac_handle;
936 brcmf_fws_macdesc_init(entry, addr, ifidx); 955 brcmf_fws_macdesc_init(entry, addr, ifidx);
937 brcmf_fws_macdesc_set_name(fws, entry); 956 brcmf_fws_macdesc_set_name(fws, entry);
938 brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT, 957 brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
939 BRCMF_FWS_PSQ_LEN); 958 BRCMF_FWS_PSQ_LEN);
959 brcmf_fws_unlock(fws->drvr, flags);
940 brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr); 960 brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr);
941 } else { 961 } else {
942 fws->stats.mac_update_failed++; 962 fws->stats.mac_update_failed++;
@@ -944,11 +964,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
944 } else { 964 } else {
945 if (entry != existing) { 965 if (entry != existing) {
946 brcmf_dbg(TRACE, "copy mac %s\n", existing->name); 966 brcmf_dbg(TRACE, "copy mac %s\n", existing->name);
967 brcmf_fws_lock(fws->drvr, flags);
947 memcpy(entry, existing, 968 memcpy(entry, existing,
948 offsetof(struct brcmf_fws_mac_descriptor, psq)); 969 offsetof(struct brcmf_fws_mac_descriptor, psq));
949 entry->mac_handle = mac_handle; 970 entry->mac_handle = mac_handle;
950 brcmf_fws_macdesc_deinit(existing); 971 brcmf_fws_macdesc_deinit(existing);
951 brcmf_fws_macdesc_set_name(fws, entry); 972 brcmf_fws_macdesc_set_name(fws, entry);
973 brcmf_fws_unlock(fws->drvr, flags);
952 brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name, 974 brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name,
953 addr); 975 addr);
954 } else { 976 } else {
@@ -964,7 +986,9 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
964 u8 type, u8 *data) 986 u8 type, u8 *data)
965{ 987{
966 struct brcmf_fws_mac_descriptor *entry; 988 struct brcmf_fws_mac_descriptor *entry;
989 ulong flags;
967 u8 mac_handle; 990 u8 mac_handle;
991 int ret;
968 992
969 mac_handle = data[0]; 993 mac_handle = data[0];
970 entry = &fws->desc.nodes[mac_handle & 0x1F]; 994 entry = &fws->desc.nodes[mac_handle & 0x1F];
@@ -972,26 +996,30 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
972 fws->stats.mac_ps_update_failed++; 996 fws->stats.mac_ps_update_failed++;
973 return -ESRCH; 997 return -ESRCH;
974 } 998 }
999 brcmf_fws_lock(fws->drvr, flags);
975 /* a state update should wipe old credits */ 1000 /* a state update should wipe old credits */
976 entry->requested_credit = 0; 1001 entry->requested_credit = 0;
977 entry->requested_packet = 0; 1002 entry->requested_packet = 0;
978 if (type == BRCMF_FWS_TYPE_MAC_OPEN) { 1003 if (type == BRCMF_FWS_TYPE_MAC_OPEN) {
979 entry->state = BRCMF_FWS_STATE_OPEN; 1004 entry->state = BRCMF_FWS_STATE_OPEN;
980 return BRCMF_FWS_RET_OK_SCHEDULE; 1005 ret = BRCMF_FWS_RET_OK_SCHEDULE;
981 } else { 1006 } else {
982 entry->state = BRCMF_FWS_STATE_CLOSE; 1007 entry->state = BRCMF_FWS_STATE_CLOSE;
983 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BK, false); 1008 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BK, false);
984 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BE, false); 1009 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BE, false);
985 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VI, false); 1010 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VI, false);
986 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true); 1011 brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true);
1012 ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
987 } 1013 }
988 return BRCMF_FWS_RET_OK_NOSCHEDULE; 1014 brcmf_fws_unlock(fws->drvr, flags);
1015 return ret;
989} 1016}
990 1017
991static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws, 1018static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
992 u8 type, u8 *data) 1019 u8 type, u8 *data)
993{ 1020{
994 struct brcmf_fws_mac_descriptor *entry; 1021 struct brcmf_fws_mac_descriptor *entry;
1022 ulong flags;
995 u8 ifidx; 1023 u8 ifidx;
996 int ret; 1024 int ret;
997 1025
@@ -1010,17 +1038,24 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
1010 1038
1011 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,
1012 entry->name); 1040 entry->name);
1041 brcmf_fws_lock(fws->drvr, flags);
1013 switch (type) { 1042 switch (type) {
1014 case BRCMF_FWS_TYPE_INTERFACE_OPEN: 1043 case BRCMF_FWS_TYPE_INTERFACE_OPEN:
1015 entry->state = BRCMF_FWS_STATE_OPEN; 1044 entry->state = BRCMF_FWS_STATE_OPEN;
1016 return BRCMF_FWS_RET_OK_SCHEDULE; 1045 ret = BRCMF_FWS_RET_OK_SCHEDULE;
1046 break;
1017 case BRCMF_FWS_TYPE_INTERFACE_CLOSE: 1047 case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
1018 entry->state = BRCMF_FWS_STATE_CLOSE; 1048 entry->state = BRCMF_FWS_STATE_CLOSE;
1019 return BRCMF_FWS_RET_OK_NOSCHEDULE; 1049 ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
1050 break;
1020 default: 1051 default:
1021 ret = -EINVAL; 1052 ret = -EINVAL;
1022 break; 1053 brcmf_fws_unlock(fws->drvr, flags);
1054 goto fail;
1023 } 1055 }
1056 brcmf_fws_unlock(fws->drvr, flags);
1057 return ret;
1058
1024fail: 1059fail:
1025 fws->stats.if_update_failed++; 1060 fws->stats.if_update_failed++;
1026 return ret; 1061 return ret;
@@ -1030,6 +1065,7 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
1030 u8 *data) 1065 u8 *data)
1031{ 1066{
1032 struct brcmf_fws_mac_descriptor *entry; 1067 struct brcmf_fws_mac_descriptor *entry;
1068 ulong flags;
1033 1069
1034 entry = &fws->desc.nodes[data[1] & 0x1F]; 1070 entry = &fws->desc.nodes[data[1] & 0x1F];
1035 if (!entry->occupied) { 1071 if (!entry->occupied) {
@@ -1043,12 +1079,14 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
1043 brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n", 1079 brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n",
1044 brcmf_fws_get_tlv_name(type), type, entry->name, 1080 brcmf_fws_get_tlv_name(type), type, entry->name,
1045 data[0], data[2]); 1081 data[0], data[2]);
1082 brcmf_fws_lock(fws->drvr, flags);
1046 if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT) 1083 if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT)
1047 entry->requested_credit = data[0]; 1084 entry->requested_credit = data[0];
1048 else 1085 else
1049 entry->requested_packet = data[0]; 1086 entry->requested_packet = data[0];
1050 1087
1051 entry->ac_bitmap = data[2]; 1088 entry->ac_bitmap = data[2];
1089 brcmf_fws_unlock(fws->drvr, flags);
1052 return BRCMF_FWS_RET_OK_SCHEDULE; 1090 return BRCMF_FWS_RET_OK_SCHEDULE;
1053} 1091}
1054 1092
@@ -1345,6 +1383,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
1345static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws, 1383static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
1346 u8 *data) 1384 u8 *data)
1347{ 1385{
1386 ulong flags;
1348 int i; 1387 int i;
1349 1388
1350 if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) { 1389 if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
@@ -1353,16 +1392,19 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
1353 } 1392 }
1354 1393
1355 brcmf_dbg(DATA, "enter: data %pM\n", data); 1394 brcmf_dbg(DATA, "enter: data %pM\n", data);
1395 brcmf_fws_lock(fws->drvr, flags);
1356 for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++) 1396 for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++)
1357 brcmf_fws_return_credits(fws, i, data[i]); 1397 brcmf_fws_return_credits(fws, i, data[i]);
1358 1398
1359 brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map, 1399 brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map,
1360 fws->fifo_delay_map); 1400 fws->fifo_delay_map);
1401 brcmf_fws_unlock(fws->drvr, flags);
1361 return BRCMF_FWS_RET_OK_SCHEDULE; 1402 return BRCMF_FWS_RET_OK_SCHEDULE;
1362} 1403}
1363 1404
1364static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data) 1405static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
1365{ 1406{
1407 ulong lflags;
1366 __le32 status_le; 1408 __le32 status_le;
1367 u32 status; 1409 u32 status;
1368 u32 hslot; 1410 u32 hslot;
@@ -1376,7 +1418,10 @@ static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
1376 hslot = brcmf_txstatus_get_field(status, HSLOT); 1418 hslot = brcmf_txstatus_get_field(status, HSLOT);
1377 genbit = brcmf_txstatus_get_field(status, GENERATION); 1419 genbit = brcmf_txstatus_get_field(status, GENERATION);
1378 1420
1379 return brcmf_fws_txs_process(fws, flags, hslot, genbit); 1421 brcmf_fws_lock(fws->drvr, lflags);
1422 brcmf_fws_txs_process(fws, flags, hslot, genbit);
1423 brcmf_fws_unlock(fws->drvr, lflags);
1424 return BRCMF_FWS_RET_OK_NOSCHEDULE;
1380} 1425}
1381 1426
1382static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data) 1427static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
@@ -1389,21 +1434,6 @@ static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
1389 return 0; 1434 return 0;
1390} 1435}
1391 1436
1392/* using macro so sparse checking does not complain
1393 * about locking imbalance.
1394 */
1395#define brcmf_fws_lock(drvr, flags) \
1396do { \
1397 flags = 0; \
1398 spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \
1399} while (0)
1400
1401/* using macro so sparse checking does not complain
1402 * about locking imbalance.
1403 */
1404#define brcmf_fws_unlock(drvr, flags) \
1405 spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags))
1406
1407static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp, 1437static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
1408 const struct brcmf_event_msg *e, 1438 const struct brcmf_event_msg *e,
1409 void *data) 1439 void *data)
@@ -1454,7 +1484,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
1454 struct sk_buff *skb) 1484 struct sk_buff *skb)
1455{ 1485{
1456 struct brcmf_fws_info *fws = drvr->fws; 1486 struct brcmf_fws_info *fws = drvr->fws;
1457 ulong flags;
1458 u8 *signal_data; 1487 u8 *signal_data;
1459 s16 data_len; 1488 s16 data_len;
1460 u8 type; 1489 u8 type;
@@ -1474,9 +1503,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
1474 return 0; 1503 return 0;
1475 } 1504 }
1476 1505
1477 /* lock during tlv parsing */
1478 brcmf_fws_lock(drvr, flags);
1479
1480 fws->stats.header_pulls++; 1506 fws->stats.header_pulls++;
1481 data_len = signal_len; 1507 data_len = signal_len;
1482 signal_data = skb->data; 1508 signal_data = skb->data;
@@ -1570,7 +1596,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
1570 if (skb->len == 0) 1596 if (skb->len == 0)
1571 fws->stats.header_only_pkt++; 1597 fws->stats.header_only_pkt++;
1572 1598
1573 brcmf_fws_unlock(drvr, flags);
1574 return 0; 1599 return 0;
1575} 1600}
1576 1601