diff options
author | Franky Lin <frankyl@broadcom.com> | 2013-08-10 06:27:28 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-08-15 16:07:55 -0400 |
commit | 6bc52319c2c688fdcbb203a4917576ca4cd4d51e (patch) | |
tree | df3ecfe4d68a3b9441ef219c06b9e1956b20aaf6 /drivers/net/wireless/brcm80211/brcmfmac | |
parent | cb7f79682a9289634094e2c3b5180611635332f5 (diff) |
brcmfmac: streamline sdio bus header code
Streamlining sdio bus specific header related code as preparation for host
tx glomming
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 243 |
1 files changed, 120 insertions, 123 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 25638753b214..02ab5cdbe29b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -201,13 +201,6 @@ struct rte_console { | |||
201 | #define SFC_CRC4WOOS (1 << 2) /* CRC error for write out of sync */ | 201 | #define SFC_CRC4WOOS (1 << 2) /* CRC error for write out of sync */ |
202 | #define SFC_ABORTALL (1 << 3) /* Abort all in-progress frames */ | 202 | #define SFC_ABORTALL (1 << 3) /* Abort all in-progress frames */ |
203 | 203 | ||
204 | /* HW frame tag */ | ||
205 | #define SDPCM_FRAMETAG_LEN 4 /* 2 bytes len, 2 bytes check val */ | ||
206 | |||
207 | /* Total length of frame header for dongle protocol */ | ||
208 | #define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) | ||
209 | #define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN) | ||
210 | |||
211 | /* | 204 | /* |
212 | * Software allocation of To SB Mailbox resources | 205 | * Software allocation of To SB Mailbox resources |
213 | */ | 206 | */ |
@@ -250,38 +243,6 @@ struct rte_console { | |||
250 | /* Current protocol version */ | 243 | /* Current protocol version */ |
251 | #define SDPCM_PROT_VERSION 4 | 244 | #define SDPCM_PROT_VERSION 4 |
252 | 245 | ||
253 | /* SW frame header */ | ||
254 | #define SDPCM_PACKET_SEQUENCE(p) (((u8 *)p)[0] & 0xff) | ||
255 | |||
256 | #define SDPCM_CHANNEL_MASK 0x00000f00 | ||
257 | #define SDPCM_CHANNEL_SHIFT 8 | ||
258 | #define SDPCM_PACKET_CHANNEL(p) (((u8 *)p)[1] & 0x0f) | ||
259 | |||
260 | #define SDPCM_NEXTLEN_OFFSET 2 | ||
261 | |||
262 | /* Data Offset from SOF (HW Tag, SW Tag, Pad) */ | ||
263 | #define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ | ||
264 | #define SDPCM_DOFFSET_VALUE(p) (((u8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) | ||
265 | #define SDPCM_DOFFSET_MASK 0xff000000 | ||
266 | #define SDPCM_DOFFSET_SHIFT 24 | ||
267 | #define SDPCM_FCMASK_OFFSET 4 /* Flow control */ | ||
268 | #define SDPCM_FCMASK_VALUE(p) (((u8 *)p)[SDPCM_FCMASK_OFFSET] & 0xff) | ||
269 | #define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */ | ||
270 | #define SDPCM_WINDOW_VALUE(p) (((u8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff) | ||
271 | |||
272 | #define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */ | ||
273 | |||
274 | /* logical channel numbers */ | ||
275 | #define SDPCM_CONTROL_CHANNEL 0 /* Control channel Id */ | ||
276 | #define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */ | ||
277 | #define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */ | ||
278 | #define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets */ | ||
279 | #define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */ | ||
280 | |||
281 | #define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for 8bit frame seq */ | ||
282 | |||
283 | #define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80) | ||
284 | |||
285 | /* | 246 | /* |
286 | * Shared structure between dongle and the host. | 247 | * Shared structure between dongle and the host. |
287 | * The structure contains pointers to trap or assert information. | 248 | * The structure contains pointers to trap or assert information. |
@@ -396,8 +357,8 @@ struct sdpcm_shared_le { | |||
396 | __le32 brpt_addr; | 357 | __le32 brpt_addr; |
397 | }; | 358 | }; |
398 | 359 | ||
399 | /* SDIO read frame info */ | 360 | /* dongle SDIO bus specific header info */ |
400 | struct brcmf_sdio_read { | 361 | struct brcmf_sdio_hdrinfo { |
401 | u8 seq_num; | 362 | u8 seq_num; |
402 | u8 channel; | 363 | u8 channel; |
403 | u16 len; | 364 | u16 len; |
@@ -431,7 +392,7 @@ struct brcmf_sdio { | |||
431 | u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; | 392 | u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; |
432 | u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ | 393 | u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ |
433 | u8 rx_seq; /* Receive sequence number (expected) */ | 394 | u8 rx_seq; /* Receive sequence number (expected) */ |
434 | struct brcmf_sdio_read cur_read; | 395 | struct brcmf_sdio_hdrinfo cur_read; |
435 | /* info of current read frame */ | 396 | /* info of current read frame */ |
436 | bool rxskip; /* Skip receive (awaiting NAK ACK) */ | 397 | bool rxskip; /* Skip receive (awaiting NAK ACK) */ |
437 | bool rxpending; /* Data frame pending in dongle */ | 398 | bool rxpending; /* Data frame pending in dongle */ |
@@ -1042,18 +1003,64 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) | |||
1042 | } | 1003 | } |
1043 | } | 1004 | } |
1044 | 1005 | ||
1045 | static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | 1006 | /** |
1046 | struct brcmf_sdio_read *rd, | 1007 | * brcmfmac sdio bus specific header |
1047 | enum brcmf_sdio_frmtype type) | 1008 | * This is the lowest layer header wrapped on the packets transmitted between |
1009 | * host and WiFi dongle which contains information needed for SDIO core and | ||
1010 | * firmware | ||
1011 | * | ||
1012 | * It consists of 2 parts: hw header and software header | ||
1013 | * hardware header (frame tag) - 4 bytes | ||
1014 | * Byte 0~1: Frame length | ||
1015 | * Byte 2~3: Checksum, bit-wise inverse of frame length | ||
1016 | * software header - 8 bytes | ||
1017 | * Byte 0: Rx/Tx sequence number | ||
1018 | * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag | ||
1019 | * Byte 2: Length of next data frame, reserved for Tx | ||
1020 | * Byte 3: Data offset | ||
1021 | * Byte 4: Flow control bits, reserved for Tx | ||
1022 | * Byte 5: Maximum Sequence number allowed by firmware for Tx, N/A for Tx packet | ||
1023 | * Byte 6~7: Reserved | ||
1024 | */ | ||
1025 | #define SDPCM_HWHDR_LEN 4 | ||
1026 | #define SDPCM_SWHDR_LEN 8 | ||
1027 | #define SDPCM_HDRLEN (SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN) | ||
1028 | #define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN) | ||
1029 | /* software header */ | ||
1030 | #define SDPCM_SEQ_MASK 0x000000ff | ||
1031 | #define SDPCM_SEQ_WRAP 256 | ||
1032 | #define SDPCM_CHANNEL_MASK 0x00000f00 | ||
1033 | #define SDPCM_CHANNEL_SHIFT 8 | ||
1034 | #define SDPCM_CONTROL_CHANNEL 0 /* Control */ | ||
1035 | #define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication */ | ||
1036 | #define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv */ | ||
1037 | #define SDPCM_GLOM_CHANNEL 3 /* Coalesced packets */ | ||
1038 | #define SDPCM_TEST_CHANNEL 15 /* Test/debug packets */ | ||
1039 | #define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80) | ||
1040 | #define SDPCM_NEXTLEN_MASK 0x00ff0000 | ||
1041 | #define SDPCM_NEXTLEN_SHIFT 16 | ||
1042 | #define SDPCM_DOFFSET_MASK 0xff000000 | ||
1043 | #define SDPCM_DOFFSET_SHIFT 24 | ||
1044 | #define SDPCM_FCMASK_MASK 0x000000ff | ||
1045 | #define SDPCM_WINDOW_MASK 0x0000ff00 | ||
1046 | #define SDPCM_WINDOW_SHIFT 8 | ||
1047 | |||
1048 | static inline u8 brcmf_sdio_getdatoffset(u8 *swheader) | ||
1049 | { | ||
1050 | u32 hdrvalue; | ||
1051 | hdrvalue = *(u32 *)swheader; | ||
1052 | return (u8)((hdrvalue & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT); | ||
1053 | } | ||
1054 | |||
1055 | static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header, | ||
1056 | struct brcmf_sdio_hdrinfo *rd, | ||
1057 | enum brcmf_sdio_frmtype type) | ||
1048 | { | 1058 | { |
1049 | u16 len, checksum; | 1059 | u16 len, checksum; |
1050 | u8 rx_seq, fc, tx_seq_max; | 1060 | u8 rx_seq, fc, tx_seq_max; |
1061 | u32 swheader; | ||
1051 | 1062 | ||
1052 | /* | 1063 | /* hw header */ |
1053 | * 4 bytes hardware header (frame tag) | ||
1054 | * Byte 0~1: Frame length | ||
1055 | * Byte 2~3: Checksum, bit-wise inverse of frame length | ||
1056 | */ | ||
1057 | len = get_unaligned_le16(header); | 1064 | len = get_unaligned_le16(header); |
1058 | checksum = get_unaligned_le16(header + sizeof(u16)); | 1065 | checksum = get_unaligned_le16(header + sizeof(u16)); |
1059 | /* All zero means no more to read */ | 1066 | /* All zero means no more to read */ |
@@ -1082,24 +1089,16 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | |||
1082 | } | 1089 | } |
1083 | rd->len = len; | 1090 | rd->len = len; |
1084 | 1091 | ||
1085 | /* | 1092 | /* software header */ |
1086 | * 8 bytes hardware header | 1093 | header += SDPCM_HWHDR_LEN; |
1087 | * Byte 0: Rx sequence number | 1094 | swheader = le32_to_cpu(*(__le32 *)header); |
1088 | * Byte 1: 4 MSB Channel number, 4 LSB arbitrary flag | 1095 | if (type == BRCMF_SDIO_FT_SUPER && SDPCM_GLOMDESC(header)) { |
1089 | * Byte 2: Length of next data frame | ||
1090 | * Byte 3: Data offset | ||
1091 | * Byte 4: Flow control bits | ||
1092 | * Byte 5: Maximum Sequence number allow for Tx | ||
1093 | * Byte 6~7: Reserved | ||
1094 | */ | ||
1095 | if (type == BRCMF_SDIO_FT_SUPER && | ||
1096 | SDPCM_GLOMDESC(&header[SDPCM_FRAMETAG_LEN])) { | ||
1097 | brcmf_err("Glom descriptor found in superframe head\n"); | 1096 | brcmf_err("Glom descriptor found in superframe head\n"); |
1098 | rd->len = 0; | 1097 | rd->len = 0; |
1099 | return -EINVAL; | 1098 | return -EINVAL; |
1100 | } | 1099 | } |
1101 | rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]); | 1100 | rx_seq = (u8)(swheader & SDPCM_SEQ_MASK); |
1102 | rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]); | 1101 | rd->channel = (swheader & SDPCM_CHANNEL_MASK) >> SDPCM_CHANNEL_SHIFT; |
1103 | if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL && | 1102 | if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL && |
1104 | type != BRCMF_SDIO_FT_SUPER) { | 1103 | type != BRCMF_SDIO_FT_SUPER) { |
1105 | brcmf_err("HW header length too long\n"); | 1104 | brcmf_err("HW header length too long\n"); |
@@ -1119,7 +1118,7 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | |||
1119 | rd->len = 0; | 1118 | rd->len = 0; |
1120 | return -EINVAL; | 1119 | return -EINVAL; |
1121 | } | 1120 | } |
1122 | rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]); | 1121 | rd->dat_offset = brcmf_sdio_getdatoffset(header); |
1123 | if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) { | 1122 | if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) { |
1124 | brcmf_err("seq %d: bad data offset\n", rx_seq); | 1123 | brcmf_err("seq %d: bad data offset\n", rx_seq); |
1125 | bus->sdcnt.rx_badhdr++; | 1124 | bus->sdcnt.rx_badhdr++; |
@@ -1136,14 +1135,15 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | |||
1136 | /* no need to check the reset for subframe */ | 1135 | /* no need to check the reset for subframe */ |
1137 | if (type == BRCMF_SDIO_FT_SUB) | 1136 | if (type == BRCMF_SDIO_FT_SUB) |
1138 | return 0; | 1137 | return 0; |
1139 | rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; | 1138 | rd->len_nxtfrm = (swheader & SDPCM_NEXTLEN_MASK) >> SDPCM_NEXTLEN_SHIFT; |
1140 | if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) { | 1139 | if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) { |
1141 | /* only warm for NON glom packet */ | 1140 | /* only warm for NON glom packet */ |
1142 | if (rd->channel != SDPCM_GLOM_CHANNEL) | 1141 | if (rd->channel != SDPCM_GLOM_CHANNEL) |
1143 | brcmf_err("seq %d: next length error\n", rx_seq); | 1142 | brcmf_err("seq %d: next length error\n", rx_seq); |
1144 | rd->len_nxtfrm = 0; | 1143 | rd->len_nxtfrm = 0; |
1145 | } | 1144 | } |
1146 | fc = SDPCM_FCMASK_VALUE(&header[SDPCM_FRAMETAG_LEN]); | 1145 | swheader = le32_to_cpu(*(__le32 *)(header + 4)); |
1146 | fc = swheader & SDPCM_FCMASK_MASK; | ||
1147 | if (bus->flowcontrol != fc) { | 1147 | if (bus->flowcontrol != fc) { |
1148 | if (~bus->flowcontrol & fc) | 1148 | if (~bus->flowcontrol & fc) |
1149 | bus->sdcnt.fc_xoff++; | 1149 | bus->sdcnt.fc_xoff++; |
@@ -1152,7 +1152,7 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | |||
1152 | bus->sdcnt.fc_rcvd++; | 1152 | bus->sdcnt.fc_rcvd++; |
1153 | bus->flowcontrol = fc; | 1153 | bus->flowcontrol = fc; |
1154 | } | 1154 | } |
1155 | tx_seq_max = SDPCM_WINDOW_VALUE(&header[SDPCM_FRAMETAG_LEN]); | 1155 | tx_seq_max = (swheader & SDPCM_WINDOW_MASK) >> SDPCM_WINDOW_SHIFT; |
1156 | if ((u8)(tx_seq_max - bus->tx_seq) > 0x40) { | 1156 | if ((u8)(tx_seq_max - bus->tx_seq) > 0x40) { |
1157 | brcmf_err("seq %d: max tx seq number error\n", rx_seq); | 1157 | brcmf_err("seq %d: max tx seq number error\n", rx_seq); |
1158 | tx_seq_max = bus->tx_seq + 2; | 1158 | tx_seq_max = bus->tx_seq + 2; |
@@ -1162,6 +1162,28 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | |||
1162 | return 0; | 1162 | return 0; |
1163 | } | 1163 | } |
1164 | 1164 | ||
1165 | static inline void brcmf_sdio_update_hwhdr(u8 *header, u16 frm_length) | ||
1166 | { | ||
1167 | *(__le16 *)header = cpu_to_le16(frm_length); | ||
1168 | *(((__le16 *)header) + 1) = cpu_to_le16(~frm_length); | ||
1169 | } | ||
1170 | |||
1171 | static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header, | ||
1172 | struct brcmf_sdio_hdrinfo *hd_info) | ||
1173 | { | ||
1174 | u32 sw_header; | ||
1175 | |||
1176 | brcmf_sdio_update_hwhdr(header, hd_info->len); | ||
1177 | |||
1178 | sw_header = bus->tx_seq; | ||
1179 | sw_header |= (hd_info->channel << SDPCM_CHANNEL_SHIFT) & | ||
1180 | SDPCM_CHANNEL_MASK; | ||
1181 | sw_header |= (hd_info->dat_offset << SDPCM_DOFFSET_SHIFT) & | ||
1182 | SDPCM_DOFFSET_MASK; | ||
1183 | *(((__le32 *)header) + 1) = cpu_to_le32(sw_header); | ||
1184 | *(((__le32 *)header) + 2) = 0; | ||
1185 | } | ||
1186 | |||
1165 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | 1187 | static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) |
1166 | { | 1188 | { |
1167 | u16 dlen, totlen; | 1189 | u16 dlen, totlen; |
@@ -1173,7 +1195,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1173 | int errcode; | 1195 | int errcode; |
1174 | u8 doff, sfdoff; | 1196 | u8 doff, sfdoff; |
1175 | 1197 | ||
1176 | struct brcmf_sdio_read rd_new; | 1198 | struct brcmf_sdio_hdrinfo rd_new; |
1177 | 1199 | ||
1178 | /* If packets, issue read(s) and send up packet chain */ | 1200 | /* If packets, issue read(s) and send up packet chain */ |
1179 | /* Return sequence numbers consumed? */ | 1201 | /* Return sequence numbers consumed? */ |
@@ -1309,8 +1331,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1309 | rd_new.seq_num = rxseq; | 1331 | rd_new.seq_num = rxseq; |
1310 | rd_new.len = dlen; | 1332 | rd_new.len = dlen; |
1311 | sdio_claim_host(bus->sdiodev->func[1]); | 1333 | sdio_claim_host(bus->sdiodev->func[1]); |
1312 | errcode = brcmf_sdio_hdparser(bus, pfirst->data, &rd_new, | 1334 | errcode = brcmf_sdio_hdparse(bus, pfirst->data, &rd_new, |
1313 | BRCMF_SDIO_FT_SUPER); | 1335 | BRCMF_SDIO_FT_SUPER); |
1314 | sdio_release_host(bus->sdiodev->func[1]); | 1336 | sdio_release_host(bus->sdiodev->func[1]); |
1315 | bus->cur_read.len = rd_new.len_nxtfrm << 4; | 1337 | bus->cur_read.len = rd_new.len_nxtfrm << 4; |
1316 | 1338 | ||
@@ -1328,8 +1350,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1328 | rd_new.len = pnext->len; | 1350 | rd_new.len = pnext->len; |
1329 | rd_new.seq_num = rxseq++; | 1351 | rd_new.seq_num = rxseq++; |
1330 | sdio_claim_host(bus->sdiodev->func[1]); | 1352 | sdio_claim_host(bus->sdiodev->func[1]); |
1331 | errcode = brcmf_sdio_hdparser(bus, pnext->data, &rd_new, | 1353 | errcode = brcmf_sdio_hdparse(bus, pnext->data, &rd_new, |
1332 | BRCMF_SDIO_FT_SUB); | 1354 | BRCMF_SDIO_FT_SUB); |
1333 | sdio_release_host(bus->sdiodev->func[1]); | 1355 | sdio_release_host(bus->sdiodev->func[1]); |
1334 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), | 1356 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), |
1335 | pnext->data, 32, "subframe:\n"); | 1357 | pnext->data, 32, "subframe:\n"); |
@@ -1361,7 +1383,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1361 | skb_queue_walk_safe(&bus->glom, pfirst, pnext) { | 1383 | skb_queue_walk_safe(&bus->glom, pfirst, pnext) { |
1362 | dptr = (u8 *) (pfirst->data); | 1384 | dptr = (u8 *) (pfirst->data); |
1363 | sublen = get_unaligned_le16(dptr); | 1385 | sublen = get_unaligned_le16(dptr); |
1364 | doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | 1386 | doff = brcmf_sdio_getdatoffset(&dptr[SDPCM_HWHDR_LEN]); |
1365 | 1387 | ||
1366 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), | 1388 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), |
1367 | dptr, pfirst->len, | 1389 | dptr, pfirst->len, |
@@ -1539,7 +1561,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1539 | uint rxleft = 0; /* Remaining number of frames allowed */ | 1561 | uint rxleft = 0; /* Remaining number of frames allowed */ |
1540 | int ret; /* Return code from calls */ | 1562 | int ret; /* Return code from calls */ |
1541 | uint rxcount = 0; /* Total frames read */ | 1563 | uint rxcount = 0; /* Total frames read */ |
1542 | struct brcmf_sdio_read *rd = &bus->cur_read, rd_new; | 1564 | struct brcmf_sdio_hdrinfo *rd = &bus->cur_read, rd_new; |
1543 | u8 head_read = 0; | 1565 | u8 head_read = 0; |
1544 | 1566 | ||
1545 | brcmf_dbg(TRACE, "Enter\n"); | 1567 | brcmf_dbg(TRACE, "Enter\n"); |
@@ -1587,8 +1609,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1587 | bus->rxhdr, SDPCM_HDRLEN, | 1609 | bus->rxhdr, SDPCM_HDRLEN, |
1588 | "RxHdr:\n"); | 1610 | "RxHdr:\n"); |
1589 | 1611 | ||
1590 | if (brcmf_sdio_hdparser(bus, bus->rxhdr, rd, | 1612 | if (brcmf_sdio_hdparse(bus, bus->rxhdr, rd, |
1591 | BRCMF_SDIO_FT_NORMAL)) { | 1613 | BRCMF_SDIO_FT_NORMAL)) { |
1592 | sdio_release_host(bus->sdiodev->func[1]); | 1614 | sdio_release_host(bus->sdiodev->func[1]); |
1593 | if (!bus->rxpending) | 1615 | if (!bus->rxpending) |
1594 | break; | 1616 | break; |
@@ -1652,8 +1674,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1652 | memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN); | 1674 | memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN); |
1653 | rd_new.seq_num = rd->seq_num; | 1675 | rd_new.seq_num = rd->seq_num; |
1654 | sdio_claim_host(bus->sdiodev->func[1]); | 1676 | sdio_claim_host(bus->sdiodev->func[1]); |
1655 | if (brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new, | 1677 | if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new, |
1656 | BRCMF_SDIO_FT_NORMAL)) { | 1678 | BRCMF_SDIO_FT_NORMAL)) { |
1657 | rd->len = 0; | 1679 | rd->len = 0; |
1658 | brcmu_pkt_buf_free_skb(pkt); | 1680 | brcmu_pkt_buf_free_skb(pkt); |
1659 | } | 1681 | } |
@@ -1697,7 +1719,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1697 | 1719 | ||
1698 | /* Save superframe descriptor and allocate packet frame */ | 1720 | /* Save superframe descriptor and allocate packet frame */ |
1699 | if (rd->channel == SDPCM_GLOM_CHANNEL) { | 1721 | if (rd->channel == SDPCM_GLOM_CHANNEL) { |
1700 | if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { | 1722 | if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_HWHDR_LEN])) { |
1701 | brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n", | 1723 | brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n", |
1702 | rd->len); | 1724 | rd->len); |
1703 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), | 1725 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), |
@@ -1783,13 +1805,12 @@ static int | |||
1783 | brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, | 1805 | brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, |
1784 | uint chan) | 1806 | uint chan) |
1785 | { | 1807 | { |
1786 | u16 head_pad, tail_pad, tail_chop, pkt_len; | 1808 | u16 head_pad, tail_pad, tail_chop, head_align, sg_align; |
1787 | u16 head_align, sg_align; | ||
1788 | u32 sw_header; | ||
1789 | int ntail; | 1809 | int ntail; |
1790 | struct sk_buff *pkt_next, *pkt_new; | 1810 | struct sk_buff *pkt_next, *pkt_new; |
1791 | u8 *dat_buf; | 1811 | u8 *dat_buf; |
1792 | unsigned blksize = bus->sdiodev->func[SDIO_FUNC_2]->cur_blksize; | 1812 | unsigned blksize = bus->sdiodev->func[SDIO_FUNC_2]->cur_blksize; |
1813 | struct brcmf_sdio_hdrinfo hd_info = {0}; | ||
1793 | 1814 | ||
1794 | /* SDIO ADMA requires at least 32 bit alignment */ | 1815 | /* SDIO ADMA requires at least 32 bit alignment */ |
1795 | head_align = 4; | 1816 | head_align = 4; |
@@ -1848,34 +1869,18 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, | |||
1848 | } | 1869 | } |
1849 | 1870 | ||
1850 | /* Now prep the header */ | 1871 | /* Now prep the header */ |
1851 | /* 4 bytes hardware header (frame tag) | ||
1852 | * Byte 0~1: Frame length | ||
1853 | * Byte 2~3: Checksum, bit-wise inverse of frame length | ||
1854 | */ | ||
1855 | if (pkt_new) | 1872 | if (pkt_new) |
1856 | pkt_len = pkt_next->len + tail_chop; | 1873 | hd_info.len = pkt_next->len + tail_chop; |
1857 | else | 1874 | else |
1858 | pkt_len = pkt_next->len - tail_pad; | 1875 | hd_info.len = pkt_next->len - tail_pad; |
1859 | *(__le16 *)dat_buf = cpu_to_le16(pkt_len); | 1876 | hd_info.channel = chan; |
1860 | *(((__le16 *)dat_buf) + 1) = cpu_to_le16(~pkt_len); | 1877 | hd_info.dat_offset = head_pad + SDPCM_HDRLEN; |
1861 | /* 8 bytes software header | 1878 | brcmf_sdio_hdpack(bus, dat_buf, &hd_info); |
1862 | * Byte 0: Tx sequence number | ||
1863 | * Byte 1: 4 MSB Channel number | ||
1864 | * Byte 2: Reserved | ||
1865 | * Byte 3: Data offset | ||
1866 | * Byte 4~7: Reserved | ||
1867 | */ | ||
1868 | sw_header = bus->tx_seq; | ||
1869 | sw_header |= ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK); | ||
1870 | sw_header |= ((head_pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & | ||
1871 | SDPCM_DOFFSET_MASK; | ||
1872 | *(((__le32 *)dat_buf) + 1) = cpu_to_le32(sw_header); | ||
1873 | *(((__le32 *)dat_buf) + 2) = 0; | ||
1874 | 1879 | ||
1875 | if (BRCMF_BYTES_ON() && | 1880 | if (BRCMF_BYTES_ON() && |
1876 | ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) || | 1881 | ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) || |
1877 | (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL))) | 1882 | (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL))) |
1878 | brcmf_dbg_hex_dump(true, pkt_next, pkt_len, "Tx Frame:\n"); | 1883 | brcmf_dbg_hex_dump(true, pkt_next, hd_info.len, "Tx Frame:\n"); |
1879 | else if (BRCMF_HDRS_ON()) | 1884 | else if (BRCMF_HDRS_ON()) |
1880 | brcmf_dbg_hex_dump(true, pkt_next, head_pad + SDPCM_HDRLEN, | 1885 | brcmf_dbg_hex_dump(true, pkt_next, head_pad + SDPCM_HDRLEN, |
1881 | "Tx Header:\n"); | 1886 | "Tx Header:\n"); |
@@ -1913,7 +1918,7 @@ brcmf_sdio_txpkt_postp(struct brcmf_sdio *bus, struct sk_buff_head *pktq) | |||
1913 | __skb_unlink(pkt_next, pktq); | 1918 | __skb_unlink(pkt_next, pktq); |
1914 | brcmu_pkt_buf_free_skb(pkt_next); | 1919 | brcmu_pkt_buf_free_skb(pkt_next); |
1915 | } else { | 1920 | } else { |
1916 | hdr = pkt_next->data + SDPCM_FRAMETAG_LEN; | 1921 | hdr = pkt_next->data + SDPCM_HWHDR_LEN; |
1917 | dat_offset = le32_to_cpu(*(__le32 *)hdr); | 1922 | dat_offset = le32_to_cpu(*(__le32 *)hdr); |
1918 | dat_offset = (dat_offset & SDPCM_DOFFSET_MASK) >> | 1923 | dat_offset = (dat_offset & SDPCM_DOFFSET_MASK) >> |
1919 | SDPCM_DOFFSET_SHIFT; | 1924 | SDPCM_DOFFSET_SHIFT; |
@@ -1969,7 +1974,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
1969 | } | 1974 | } |
1970 | sdio_release_host(bus->sdiodev->func[1]); | 1975 | sdio_release_host(bus->sdiodev->func[1]); |
1971 | if (ret == 0) | 1976 | if (ret == 0) |
1972 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; | 1977 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP; |
1973 | 1978 | ||
1974 | done: | 1979 | done: |
1975 | brcmf_sdio_txpkt_postp(bus, &localq); | 1980 | brcmf_sdio_txpkt_postp(bus, &localq); |
@@ -2325,7 +2330,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2325 | } | 2330 | } |
2326 | 2331 | ||
2327 | } else { | 2332 | } else { |
2328 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; | 2333 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP; |
2329 | } | 2334 | } |
2330 | sdio_release_host(bus->sdiodev->func[1]); | 2335 | sdio_release_host(bus->sdiodev->func[1]); |
2331 | bus->ctrl_frame_stat = false; | 2336 | bus->ctrl_frame_stat = false; |
@@ -2540,7 +2545,7 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) | |||
2540 | return ret; | 2545 | return ret; |
2541 | } | 2546 | } |
2542 | 2547 | ||
2543 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; | 2548 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQ_WRAP; |
2544 | 2549 | ||
2545 | return ret; | 2550 | return ret; |
2546 | } | 2551 | } |
@@ -2550,13 +2555,13 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2550 | { | 2555 | { |
2551 | u8 *frame; | 2556 | u8 *frame; |
2552 | u16 len; | 2557 | u16 len; |
2553 | u32 swheader; | ||
2554 | uint retries = 0; | 2558 | uint retries = 0; |
2555 | u8 doff = 0; | 2559 | u8 doff = 0; |
2556 | int ret = -1; | 2560 | int ret = -1; |
2557 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2561 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2558 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2562 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
2559 | struct brcmf_sdio *bus = sdiodev->bus; | 2563 | struct brcmf_sdio *bus = sdiodev->bus; |
2564 | struct brcmf_sdio_hdrinfo hd_info = {0}; | ||
2560 | 2565 | ||
2561 | brcmf_dbg(TRACE, "Enter\n"); | 2566 | brcmf_dbg(TRACE, "Enter\n"); |
2562 | 2567 | ||
@@ -2595,18 +2600,10 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2595 | brcmf_sdbrcm_bus_sleep(bus, false, false); | 2600 | brcmf_sdbrcm_bus_sleep(bus, false, false); |
2596 | sdio_release_host(bus->sdiodev->func[1]); | 2601 | sdio_release_host(bus->sdiodev->func[1]); |
2597 | 2602 | ||
2598 | /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ | 2603 | hd_info.len = (u16)msglen; |
2599 | *(__le16 *) frame = cpu_to_le16((u16) msglen); | 2604 | hd_info.channel = SDPCM_CONTROL_CHANNEL; |
2600 | *(((__le16 *) frame) + 1) = cpu_to_le16(~msglen); | 2605 | hd_info.dat_offset = doff; |
2601 | 2606 | brcmf_sdio_hdpack(bus, frame, &hd_info); | |
2602 | /* Software tag: channel, sequence number, data offset */ | ||
2603 | swheader = | ||
2604 | ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & | ||
2605 | SDPCM_CHANNEL_MASK) | ||
2606 | | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & | ||
2607 | SDPCM_DOFFSET_MASK); | ||
2608 | put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); | ||
2609 | put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); | ||
2610 | 2607 | ||
2611 | if (!data_ok(bus)) { | 2608 | if (!data_ok(bus)) { |
2612 | brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", | 2609 | brcmf_dbg(INFO, "No bus credit bus->tx_max %d, bus->tx_seq %d\n", |
@@ -3856,7 +3853,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
3856 | bus->txbound = BRCMF_TXBOUND; | 3853 | bus->txbound = BRCMF_TXBOUND; |
3857 | bus->rxbound = BRCMF_RXBOUND; | 3854 | bus->rxbound = BRCMF_RXBOUND; |
3858 | bus->txminmax = BRCMF_TXMINMAX; | 3855 | bus->txminmax = BRCMF_TXMINMAX; |
3859 | bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; | 3856 | bus->tx_seq = SDPCM_SEQ_WRAP - 1; |
3860 | 3857 | ||
3861 | INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); | 3858 | INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); |
3862 | bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq"); | 3859 | bus->brcmf_wq = create_singlethread_workqueue("brcmf_wq"); |