fwsignal.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307
  1. /*
  2. * Copyright (c) 2010 Broadcom Corporation
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <linux/types.h>
  17. #include <linux/module.h>
  18. #include <linux/if_ether.h>
  19. #include <linux/spinlock.h>
  20. #include <linux/skbuff.h>
  21. #include <linux/netdevice.h>
  22. #include <linux/etherdevice.h>
  23. #include <linux/err.h>
  24. #include <uapi/linux/nl80211.h>
  25. #include <net/cfg80211.h>
  26. #include <brcmu_utils.h>
  27. #include <brcmu_wifi.h>
  28. #include "dhd.h"
  29. #include "dhd_proto.h"
  30. #include "dhd_dbg.h"
  31. #include "dhd_bus.h"
  32. #include "fwil.h"
  33. #include "fweh.h"
  34. #include "fwsignal.h"
  35. /**
  36. * DOC: Firmware Signalling
  37. *
  38. * Firmware can send signals to host and vice versa, which are passed in the
  39. * data packets using TLV based header. This signalling layer is on top of the
  40. * BDC bus protocol layer.
  41. */
  42. /*
  43. * single definition for firmware-driver flow control tlv's.
  44. *
  45. * each tlv is specified by BRCMF_FWS_TLV_DEF(name, ID, length).
  46. * A length value 0 indicates variable length tlv.
  47. */
  48. #define BRCMF_FWS_TLV_DEFLIST \
  49. BRCMF_FWS_TLV_DEF(MAC_OPEN, 1, 1) \
  50. BRCMF_FWS_TLV_DEF(MAC_CLOSE, 2, 1) \
  51. BRCMF_FWS_TLV_DEF(MAC_REQUEST_CREDIT, 3, 2) \
  52. BRCMF_FWS_TLV_DEF(TXSTATUS, 4, 4) \
  53. BRCMF_FWS_TLV_DEF(PKTTAG, 5, 4) \
  54. BRCMF_FWS_TLV_DEF(MACDESC_ADD, 6, 8) \
  55. BRCMF_FWS_TLV_DEF(MACDESC_DEL, 7, 8) \
  56. BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \
  57. BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \
  58. BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \
  59. BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 6) \
  60. BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \
  61. BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \
  62. BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \
  63. BRCMF_FWS_TLV_DEF(TRANS_ID, 18, 6) \
  64. BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \
  65. BRCMF_FWS_TLV_DEF(FILLER, 255, 0)
  66. /*
  67. * enum brcmf_fws_tlv_type - definition of tlv identifiers.
  68. */
  69. #define BRCMF_FWS_TLV_DEF(name, id, len) \
  70. BRCMF_FWS_TYPE_ ## name = id,
  71. enum brcmf_fws_tlv_type {
  72. BRCMF_FWS_TLV_DEFLIST
  73. BRCMF_FWS_TYPE_INVALID
  74. };
  75. #undef BRCMF_FWS_TLV_DEF
  76. /*
  77. * enum brcmf_fws_tlv_len - definition of tlv lengths.
  78. */
  79. #define BRCMF_FWS_TLV_DEF(name, id, len) \
  80. BRCMF_FWS_TYPE_ ## name ## _LEN = (len),
  81. enum brcmf_fws_tlv_len {
  82. BRCMF_FWS_TLV_DEFLIST
  83. };
  84. #undef BRCMF_FWS_TLV_DEF
  85. #ifdef DEBUG
  86. /*
  87. * brcmf_fws_tlv_names - array of tlv names.
  88. */
  89. #define BRCMF_FWS_TLV_DEF(name, id, len) \
  90. { id, #name },
  91. static struct {
  92. enum brcmf_fws_tlv_type id;
  93. const char *name;
  94. } brcmf_fws_tlv_names[] = {
  95. BRCMF_FWS_TLV_DEFLIST
  96. };
  97. #undef BRCMF_FWS_TLV_DEF
  98. static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
  99. {
  100. int i;
  101. for (i = 0; i < ARRAY_SIZE(brcmf_fws_tlv_names); i++)
  102. if (brcmf_fws_tlv_names[i].id == id)
  103. return brcmf_fws_tlv_names[i].name;
  104. return "INVALID";
  105. }
  106. #else
  107. static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
  108. {
  109. return "NODEBUG";
  110. }
  111. #endif /* DEBUG */
  112. /*
  113. * flags used to enable tlv signalling from firmware.
  114. */
  115. #define BRCMF_FWS_FLAGS_RSSI_SIGNALS 0x0001
  116. #define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS 0x0002
  117. #define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS 0x0004
  118. #define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE 0x0008
  119. #define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE 0x0010
  120. #define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE 0x0020
  121. #define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE 0x0040
  122. #define BRCMF_FWS_STATE_OPEN 1
  123. #define BRCMF_FWS_STATE_CLOSE 2
  124. #define BRCMF_FWS_MAC_DESC_TABLE_SIZE 32
  125. #define BRCMF_FWS_MAX_IFNUM 16
  126. #define BRCMF_FWS_MAC_DESC_ID_INVALID 0xff
  127. #define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF 0
  128. #define BRCMF_FWS_HOSTIF_FLOWSTATE_ON 1
  129. #define BRCMF_FWS_PSQ_PREC_COUNT ((NL80211_NUM_ACS + 1) * 2)
  130. #define BRCMF_FWS_PSQ_LEN 256
  131. #define BRCMF_FWS_HTOD_FLAG_PKTFROMHOST 0x01
  132. #define BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED 0x02
  133. /**
  134. * enum brcmf_fws_skb_state - indicates processing state of skb.
  135. *
  136. * @BRCMF_FWS_SKBSTATE_NEW: sk_buff is newly arrived in the driver.
  137. * @BRCMF_FWS_SKBSTATE_DELAYED: sk_buff had to wait on queue.
  138. * @BRCMF_FWS_SKBSTATE_SUPPRESSED: sk_buff has been suppressed by firmware.
  139. */
  140. enum brcmf_fws_skb_state {
  141. BRCMF_FWS_SKBSTATE_NEW,
  142. BRCMF_FWS_SKBSTATE_DELAYED,
  143. BRCMF_FWS_SKBSTATE_SUPPRESSED
  144. };
  145. /**
  146. * struct brcmf_skbuff_cb - control buffer associated with skbuff.
  147. *
  148. * @if_flags: holds interface index and packet related flags.
  149. * @htod: host to device packet identifier (used in PKTTAG tlv).
  150. * @state: transmit state of the packet.
  151. * @mac: descriptor related to destination for this packet.
  152. *
  153. * This information is stored in control buffer struct sk_buff::cb, which
  154. * provides 48 bytes of storage so this structure should not exceed that.
  155. */
  156. struct brcmf_skbuff_cb {
  157. u16 if_flags;
  158. u32 htod;
  159. enum brcmf_fws_skb_state state;
  160. struct brcmf_fws_mac_descriptor *mac;
  161. };
  162. /*
  163. * macro casting skbuff control buffer to struct brcmf_skbuff_cb.
  164. */
  165. #define brcmf_skbcb(skb) ((struct brcmf_skbuff_cb *)((skb)->cb))
  166. /*
  167. * sk_buff control if flags
  168. *
  169. * b[11] - packet sent upon firmware request.
  170. * b[10] - packet only contains signalling data.
  171. * b[9] - packet is a tx packet.
  172. * b[8] - packet uses FIFO credit (non-pspoll).
  173. * b[7] - interface in AP mode.
  174. * b[6:4] - AC FIFO number.
  175. * b[3:0] - interface index.
  176. */
  177. #define BRCMF_SKB_IF_FLAGS_REQUESTED_MASK 0x0800
  178. #define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT 11
  179. #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_MASK 0x0400
  180. #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_SHIFT 10
  181. #define BRCMF_SKB_IF_FLAGS_TRANSMIT_MASK 0x0200
  182. #define BRCMF_SKB_IF_FLAGS_TRANSMIT_SHIFT 9
  183. #define BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK 0x0100
  184. #define BRCMF_SKB_IF_FLAGS_CREDITCHECK_SHIFT 8
  185. #define BRCMF_SKB_IF_FLAGS_IF_AP_MASK 0x0080
  186. #define BRCMF_SKB_IF_FLAGS_IF_AP_SHIFT 7
  187. #define BRCMF_SKB_IF_FLAGS_FIFO_MASK 0x0070
  188. #define BRCMF_SKB_IF_FLAGS_FIFO_SHIFT 4
  189. #define BRCMF_SKB_IF_FLAGS_INDEX_MASK 0x000f
  190. #define BRCMF_SKB_IF_FLAGS_INDEX_SHIFT 0
  191. #define brcmf_skb_if_flags_set_field(skb, field, value) \
  192. brcmu_maskset16(&(brcmf_skbcb(skb)->if_flags), \
  193. BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \
  194. BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT, (value))
  195. #define brcmf_skb_if_flags_get_field(skb, field) \
  196. brcmu_maskget16(brcmf_skbcb(skb)->if_flags, \
  197. BRCMF_SKB_IF_FLAGS_ ## field ## _MASK, \
  198. BRCMF_SKB_IF_FLAGS_ ## field ## _SHIFT)
  199. /*
  200. * sk_buff control packet identifier
  201. *
  202. * 32-bit packet identifier used in PKTTAG tlv from host to dongle.
  203. *
  204. * - Generated at the host (e.g. dhd)
  205. * - Seen as a generic sequence number by firmware except for the flags field.
  206. *
  207. * Generation : b[31] => generation number for this packet [host->fw]
  208. * OR, current generation number [fw->host]
  209. * Flags : b[30:27] => command, status flags
  210. * FIFO-AC : b[26:24] => AC-FIFO id
  211. * h-slot : b[23:8] => hanger-slot
  212. * freerun : b[7:0] => A free running counter
  213. */
  214. #define BRCMF_SKB_HTOD_TAG_GENERATION_MASK 0x80000000
  215. #define BRCMF_SKB_HTOD_TAG_GENERATION_SHIFT 31
  216. #define BRCMF_SKB_HTOD_TAG_FLAGS_MASK 0x78000000
  217. #define BRCMF_SKB_HTOD_TAG_FLAGS_SHIFT 27
  218. #define BRCMF_SKB_HTOD_TAG_FIFO_MASK 0x07000000
  219. #define BRCMF_SKB_HTOD_TAG_FIFO_SHIFT 24
  220. #define BRCMF_SKB_HTOD_TAG_HSLOT_MASK 0x00ffff00
  221. #define BRCMF_SKB_HTOD_TAG_HSLOT_SHIFT 8
  222. #define BRCMF_SKB_HTOD_TAG_FREERUN_MASK 0x000000ff
  223. #define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT 0
  224. #define brcmf_skb_htod_tag_set_field(skb, field, value) \
  225. brcmu_maskset32(&(brcmf_skbcb(skb)->htod), \
  226. BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \
  227. BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT, (value))
  228. #define brcmf_skb_htod_tag_get_field(skb, field) \
  229. brcmu_maskget32(brcmf_skbcb(skb)->htod, \
  230. BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \
  231. BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT)
  232. #define BRCMF_FWS_TXSTAT_GENERATION_MASK 0x80000000
  233. #define BRCMF_FWS_TXSTAT_GENERATION_SHIFT 31
  234. #define BRCMF_FWS_TXSTAT_FLAGS_MASK 0x78000000
  235. #define BRCMF_FWS_TXSTAT_FLAGS_SHIFT 27
  236. #define BRCMF_FWS_TXSTAT_FIFO_MASK 0x07000000
  237. #define BRCMF_FWS_TXSTAT_FIFO_SHIFT 24
  238. #define BRCMF_FWS_TXSTAT_HSLOT_MASK 0x00FFFF00
  239. #define BRCMF_FWS_TXSTAT_HSLOT_SHIFT 8
  240. #define BRCMF_FWS_TXSTAT_PKTID_MASK 0x00FFFFFF
  241. #define BRCMF_FWS_TXSTAT_PKTID_SHIFT 0
  242. #define brcmf_txstatus_get_field(txs, field) \
  243. brcmu_maskget32(txs, BRCMF_FWS_TXSTAT_ ## field ## _MASK, \
  244. BRCMF_FWS_TXSTAT_ ## field ## _SHIFT)
  245. /**
  246. * enum brcmf_fws_fifo - fifo indices used by dongle firmware.
  247. *
  248. * @BRCMF_FWS_FIFO_AC_BK: fifo for background traffic.
  249. * @BRCMF_FWS_FIFO_AC_BE: fifo for best-effort traffic.
  250. * @BRCMF_FWS_FIFO_AC_VI: fifo for video traffic.
  251. * @BRCMF_FWS_FIFO_AC_VO: fifo for voice traffic.
  252. * @BRCMF_FWS_FIFO_BCMC: fifo for broadcast/multicast (AP only).
  253. * @BRCMF_FWS_FIFO_ATIM: fifo for ATIM (AP only).
  254. * @BRCMF_FWS_FIFO_COUNT: number of fifos.
  255. */
  256. enum brcmf_fws_fifo {
  257. BRCMF_FWS_FIFO_AC_BK,
  258. BRCMF_FWS_FIFO_AC_BE,
  259. BRCMF_FWS_FIFO_AC_VI,
  260. BRCMF_FWS_FIFO_AC_VO,
  261. BRCMF_FWS_FIFO_BCMC,
  262. BRCMF_FWS_FIFO_ATIM,
  263. BRCMF_FWS_FIFO_COUNT
  264. };
  265. /**
  266. * enum brcmf_fws_txstatus - txstatus flag values.
  267. *
  268. * @BRCMF_FWS_TXSTATUS_DISCARD:
  269. * host is free to discard the packet.
  270. * @BRCMF_FWS_TXSTATUS_CORE_SUPPRESS:
  271. * 802.11 core suppressed the packet.
  272. * @BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS:
  273. * firmware suppress the packet as device is already in PS mode.
  274. * @BRCMF_FWS_TXSTATUS_FW_TOSSED:
  275. * firmware tossed the packet.
  276. */
  277. enum brcmf_fws_txstatus {
  278. BRCMF_FWS_TXSTATUS_DISCARD,
  279. BRCMF_FWS_TXSTATUS_CORE_SUPPRESS,
  280. BRCMF_FWS_TXSTATUS_FW_PS_SUPPRESS,
  281. BRCMF_FWS_TXSTATUS_FW_TOSSED
  282. };
  283. enum brcmf_fws_fcmode {
  284. BRCMF_FWS_FCMODE_NONE,
  285. BRCMF_FWS_FCMODE_IMPLIED_CREDIT,
  286. BRCMF_FWS_FCMODE_EXPLICIT_CREDIT
  287. };
  288. /**
  289. * struct brcmf_fws_mac_descriptor - firmware signalling data per node/interface
  290. *
  291. * @occupied: slot is in use.
  292. * @mac_handle: handle for mac entry determined by firmware.
  293. * @interface_id: interface index.
  294. * @state: current state.
  295. * @suppressed: mac entry is suppressed.
  296. * @generation: generation bit.
  297. * @ac_bitmap: ac queue bitmap.
  298. * @requested_credit: credits requested by firmware.
  299. * @ea: ethernet address.
  300. * @seq: per-node free-running sequence.
  301. * @psq: power-save queue.
  302. * @transit_count: packet in transit to firmware.
  303. */
  304. struct brcmf_fws_mac_descriptor {
  305. u8 occupied;
  306. u8 mac_handle;
  307. u8 interface_id;
  308. u8 state;
  309. bool suppressed;
  310. u8 generation;
  311. u8 ac_bitmap;
  312. u8 requested_credit;
  313. u8 ea[ETH_ALEN];
  314. u8 seq[BRCMF_FWS_FIFO_COUNT];
  315. struct pktq psq;
  316. int transit_count;
  317. };
  318. #define BRCMF_FWS_HANGER_MAXITEMS 1024
  319. /**
  320. * enum brcmf_fws_hanger_item_state - state of hanger item.
  321. *
  322. * @BRCMF_FWS_HANGER_ITEM_STATE_FREE: item is free for use.
  323. * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE: item is in use.
  324. * @BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED: item was suppressed.
  325. */
  326. enum brcmf_fws_hanger_item_state {
  327. BRCMF_FWS_HANGER_ITEM_STATE_FREE = 1,
  328. BRCMF_FWS_HANGER_ITEM_STATE_INUSE,
  329. BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED
  330. };
  331. /**
  332. * struct brcmf_fws_hanger_item - single entry for tx pending packet.
  333. *
  334. * @state: entry is either free or occupied.
  335. * @gen: generation.
  336. * @pkt: packet itself.
  337. */
  338. struct brcmf_fws_hanger_item {
  339. enum brcmf_fws_hanger_item_state state;
  340. u8 gen;
  341. struct sk_buff *pkt;
  342. };
  343. /**
  344. * struct brcmf_fws_hanger - holds packets awaiting firmware txstatus.
  345. *
  346. * @pushed: packets pushed to await txstatus.
  347. * @popped: packets popped upon handling txstatus.
  348. * @failed_to_push: packets that could not be pushed.
  349. * @failed_to_pop: packets that could not be popped.
  350. * @failed_slotfind: packets for which failed to find an entry.
  351. * @slot_pos: last returned item index for a free entry.
  352. * @items: array of hanger items.
  353. */
  354. struct brcmf_fws_hanger {
  355. u32 pushed;
  356. u32 popped;
  357. u32 failed_to_push;
  358. u32 failed_to_pop;
  359. u32 failed_slotfind;
  360. u32 slot_pos;
  361. struct brcmf_fws_hanger_item items[BRCMF_FWS_HANGER_MAXITEMS];
  362. };
  363. struct brcmf_fws_info {
  364. struct brcmf_pub *drvr;
  365. struct brcmf_fws_stats stats;
  366. struct brcmf_fws_hanger hanger;
  367. struct brcmf_fws_mac_descriptor nodes[BRCMF_FWS_MAC_DESC_TABLE_SIZE];
  368. struct brcmf_fws_mac_descriptor other;
  369. enum brcmf_fws_fcmode fcmode;
  370. int fifo_credit[BRCMF_FWS_FIFO_COUNT];
  371. };
  372. /*
  373. * brcmf_fws_prio2fifo - mapping from 802.1d priority to firmware fifo index.
  374. */
  375. static const int brcmf_fws_prio2fifo[] = {
  376. BRCMF_FWS_FIFO_AC_BE,
  377. BRCMF_FWS_FIFO_AC_BK,
  378. BRCMF_FWS_FIFO_AC_BK,
  379. BRCMF_FWS_FIFO_AC_BE,
  380. BRCMF_FWS_FIFO_AC_VI,
  381. BRCMF_FWS_FIFO_AC_VI,
  382. BRCMF_FWS_FIFO_AC_VO,
  383. BRCMF_FWS_FIFO_AC_VO
  384. };
  385. static int fcmode;
  386. module_param(fcmode, int, S_IRUSR);
  387. MODULE_PARM_DESC(fcmode, "mode of firmware signalled flow control");
  388. #define BRCMF_FWS_TLV_DEF(name, id, len) \
  389. case BRCMF_FWS_TYPE_ ## name: \
  390. return len;
  391. /**
  392. * brcmf_fws_get_tlv_len() - returns defined length for given tlv id.
  393. *
  394. * @fws: firmware-signalling information.
  395. * @id: identifier of the TLV.
  396. *
  397. * Return: the specified length for the given TLV; Otherwise -EINVAL.
  398. */
  399. static int brcmf_fws_get_tlv_len(struct brcmf_fws_info *fws,
  400. enum brcmf_fws_tlv_type id)
  401. {
  402. switch (id) {
  403. BRCMF_FWS_TLV_DEFLIST
  404. default:
  405. fws->stats.tlv_invalid_type++;
  406. break;
  407. }
  408. return -EINVAL;
  409. }
  410. #undef BRCMF_FWS_TLV_DEF
  411. static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg)
  412. {
  413. u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX);
  414. return ifidx == *(int *)arg;
  415. }
  416. static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q,
  417. int ifidx)
  418. {
  419. bool (*matchfn)(struct sk_buff *, void *) = NULL;
  420. struct sk_buff *skb;
  421. int prec;
  422. if (ifidx != -1)
  423. matchfn = brcmf_fws_ifidx_match;
  424. for (prec = 0; prec < q->num_prec; prec++) {
  425. skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
  426. while (skb) {
  427. brcmf_txfinalize(fws->drvr, skb, false);
  428. skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
  429. }
  430. }
  431. }
  432. static void brcmf_fws_hanger_init(struct brcmf_fws_hanger *hanger)
  433. {
  434. int i;
  435. brcmf_dbg(TRACE, "enter\n");
  436. memset(hanger, 0, sizeof(*hanger));
  437. for (i = 0; i < ARRAY_SIZE(hanger->items); i++)
  438. hanger->items[i].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
  439. }
  440. static u32 brcmf_fws_hanger_get_free_slot(struct brcmf_fws_hanger *h)
  441. {
  442. u32 i;
  443. brcmf_dbg(TRACE, "enter\n");
  444. i = (h->slot_pos + 1) % BRCMF_FWS_HANGER_MAXITEMS;
  445. while (i != h->slot_pos) {
  446. if (h->items[i].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
  447. h->slot_pos = i;
  448. return i;
  449. }
  450. i++;
  451. if (i == BRCMF_FWS_HANGER_MAXITEMS)
  452. i = 0;
  453. }
  454. brcmf_err("all slots occupied\n");
  455. h->failed_slotfind++;
  456. return BRCMF_FWS_HANGER_MAXITEMS;
  457. }
  458. static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h,
  459. struct sk_buff *pkt, u32 slot_id)
  460. {
  461. brcmf_dbg(TRACE, "enter\n");
  462. if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
  463. return -ENOENT;
  464. if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
  465. brcmf_err("slot is not free\n");
  466. h->failed_to_push++;
  467. return -EINVAL;
  468. }
  469. h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE;
  470. h->items[slot_id].pkt = pkt;
  471. h->pushed++;
  472. return 0;
  473. }
  474. static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
  475. u32 slot_id, struct sk_buff **pktout,
  476. bool remove_item)
  477. {
  478. brcmf_dbg(TRACE, "enter\n");
  479. if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
  480. return -ENOENT;
  481. if (h->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
  482. brcmf_err("entry not in use\n");
  483. h->failed_to_pop++;
  484. return -EINVAL;
  485. }
  486. *pktout = h->items[slot_id].pkt;
  487. if (remove_item) {
  488. h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
  489. h->items[slot_id].pkt = NULL;
  490. h->items[slot_id].gen = 0xff;
  491. h->popped++;
  492. }
  493. return 0;
  494. }
  495. static __used int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h,
  496. u32 slot_id, u8 gen)
  497. {
  498. brcmf_dbg(TRACE, "enter\n");
  499. if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
  500. return -ENOENT;
  501. h->items[slot_id].gen = gen;
  502. if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_INUSE) {
  503. brcmf_err("entry not in use\n");
  504. return -EINVAL;
  505. }
  506. h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED;
  507. return 0;
  508. }
  509. static int brcmf_fws_hanger_get_genbit(struct brcmf_fws_hanger *hanger,
  510. struct sk_buff *pkt, u32 slot_id,
  511. int *gen)
  512. {
  513. brcmf_dbg(TRACE, "enter\n");
  514. *gen = 0xff;
  515. if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
  516. return -ENOENT;
  517. if (hanger->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
  518. brcmf_err("slot not in use\n");
  519. return -EINVAL;
  520. }
  521. *gen = hanger->items[slot_id].gen;
  522. return 0;
  523. }
  524. static void brcmf_fws_hanger_cleanup(struct brcmf_fws_hanger *h,
  525. bool (*fn)(struct sk_buff *, void *),
  526. int ifidx)
  527. {
  528. struct sk_buff *skb;
  529. int i;
  530. enum brcmf_fws_hanger_item_state s;
  531. brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx);
  532. for (i = 0; i < ARRAY_SIZE(h->items); i++) {
  533. s = h->items[i].state;
  534. if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE ||
  535. s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED) {
  536. skb = h->items[i].pkt;
  537. if (fn == NULL || fn(skb, &ifidx)) {
  538. /* suppress packets freed from psq */
  539. if (s == BRCMF_FWS_HANGER_ITEM_STATE_INUSE)
  540. brcmu_pkt_buf_free_skb(skb);
  541. h->items[i].state =
  542. BRCMF_FWS_HANGER_ITEM_STATE_FREE;
  543. }
  544. }
  545. }
  546. }
  547. static void brcmf_fws_init_mac_descriptor(struct brcmf_fws_mac_descriptor *desc,
  548. u8 *addr, u8 ifidx)
  549. {
  550. brcmf_dbg(TRACE, "enter: ea=%pM, ifidx=%u\n", addr, ifidx);
  551. desc->occupied = 1;
  552. desc->state = BRCMF_FWS_STATE_OPEN;
  553. desc->requested_credit = 0;
  554. /* depending on use may need ifp->bssidx instead */
  555. desc->interface_id = ifidx;
  556. desc->ac_bitmap = 0xff; /* update this when handling APSD */
  557. memcpy(&desc->ea[0], addr, ETH_ALEN);
  558. }
  559. static
  560. void brcmf_fws_clear_mac_descriptor(struct brcmf_fws_mac_descriptor *desc)
  561. {
  562. brcmf_dbg(TRACE,
  563. "enter: ea=%pM, ifidx=%u\n", desc->ea, desc->interface_id);
  564. desc->occupied = 0;
  565. desc->state = BRCMF_FWS_STATE_CLOSE;
  566. desc->requested_credit = 0;
  567. }
  568. static struct brcmf_fws_mac_descriptor *
  569. brcmf_fws_mac_descriptor_lookup(struct brcmf_fws_info *fws, u8 *ea)
  570. {
  571. struct brcmf_fws_mac_descriptor *entry;
  572. int i;
  573. brcmf_dbg(TRACE, "enter: ea=%pM\n", ea);
  574. if (ea == NULL)
  575. return ERR_PTR(-EINVAL);
  576. entry = &fws->nodes[0];
  577. for (i = 0; i < ARRAY_SIZE(fws->nodes); i++) {
  578. if (entry->occupied && !memcmp(entry->ea, ea, ETH_ALEN))
  579. return entry;
  580. entry++;
  581. }
  582. return ERR_PTR(-ENOENT);
  583. }
  584. static struct brcmf_fws_mac_descriptor*
  585. brcmf_fws_find_mac_desc(struct brcmf_fws_info *fws, int ifidx, u8 *da)
  586. {
  587. struct brcmf_fws_mac_descriptor *entry = &fws->other;
  588. struct brcmf_if *ifp;
  589. bool multicast;
  590. brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx);
  591. multicast = is_multicast_ether_addr(da);
  592. ifp = fws->drvr->iflist[ifidx ? ifidx + 1 : 0];
  593. if (WARN_ON(!ifp))
  594. goto done;
  595. /* Multicast destination and P2P clients get the interface entry.
  596. * STA gets the interface entry if there is no exact match. For
  597. * example, TDLS destinations have their own entry.
  598. */
  599. entry = NULL;
  600. if ((/* ifp->iftype == 0 ||*/ multicast) && ifp->fws_desc)
  601. entry = ifp->fws_desc;
  602. if (entry != NULL && multicast)
  603. goto done;
  604. entry = brcmf_fws_mac_descriptor_lookup(fws, da);
  605. if (IS_ERR(entry))
  606. entry = &fws->other;
  607. done:
  608. brcmf_dbg(TRACE, "exit: entry=%p\n", entry);
  609. return entry;
  610. }
  611. static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_info *fws,
  612. struct brcmf_fws_mac_descriptor *entry,
  613. int ifidx)
  614. {
  615. brcmf_dbg(TRACE, "enter: entry=(ea=%pM, ifid=%d), ifidx=%d\n",
  616. entry->ea, entry->interface_id, ifidx);
  617. if (entry->occupied && (ifidx == -1 || ifidx == entry->interface_id)) {
  618. brcmf_dbg(TRACE, "flush psq: ifidx=%d, qlen=%d\n",
  619. ifidx, entry->psq.len);
  620. brcmf_fws_psq_flush(fws, &entry->psq, ifidx);
  621. entry->occupied = !!(entry->psq.len);
  622. }
  623. }
  624. static void brcmf_fws_bus_txq_cleanup(struct brcmf_fws_info *fws,
  625. bool (*fn)(struct sk_buff *, void *),
  626. int ifidx)
  627. {
  628. struct brcmf_fws_hanger_item *hi;
  629. struct pktq *txq;
  630. struct sk_buff *skb;
  631. int prec;
  632. u32 hslot;
  633. brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx);
  634. txq = brcmf_bus_gettxq(fws->drvr->bus_if);
  635. if (IS_ERR(txq)) {
  636. brcmf_dbg(TRACE, "no txq to clean up\n");
  637. return;
  638. }
  639. for (prec = 0; prec < txq->num_prec; prec++) {
  640. skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx);
  641. while (skb) {
  642. hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
  643. hi = &fws->hanger.items[hslot];
  644. WARN_ON(skb != hi->pkt);
  645. hi->state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
  646. brcmu_pkt_buf_free_skb(skb);
  647. skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx);
  648. }
  649. }
  650. }
  651. static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx)
  652. {
  653. int i;
  654. struct brcmf_fws_mac_descriptor *table;
  655. bool (*matchfn)(struct sk_buff *, void *) = NULL;
  656. brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx);
  657. if (fws == NULL)
  658. return;
  659. if (ifidx != -1)
  660. matchfn = brcmf_fws_ifidx_match;
  661. /* cleanup individual nodes */
  662. table = &fws->nodes[0];
  663. for (i = 0; i < ARRAY_SIZE(fws->nodes); i++)
  664. brcmf_fws_mac_desc_cleanup(fws, &table[i], ifidx);
  665. brcmf_fws_mac_desc_cleanup(fws, &fws->other, ifidx);
  666. brcmf_fws_bus_txq_cleanup(fws, matchfn, ifidx);
  667. brcmf_fws_hanger_cleanup(&fws->hanger, matchfn, ifidx);
  668. }
  669. static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
  670. {
  671. brcmf_dbg(CTL, "rssi %d\n", rssi);
  672. return 0;
  673. }
  674. static
  675. int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
  676. {
  677. struct brcmf_fws_mac_descriptor *entry, *existing;
  678. u8 mac_handle;
  679. u8 ifidx;
  680. u8 *addr;
  681. mac_handle = *data++;
  682. ifidx = *data++;
  683. addr = data;
  684. entry = &fws->nodes[mac_handle & 0x1F];
  685. if (type == BRCMF_FWS_TYPE_MACDESC_DEL) {
  686. brcmf_dbg(TRACE, "deleting mac %pM idx %d\n", addr, ifidx);
  687. if (entry->occupied)
  688. brcmf_fws_clear_mac_descriptor(entry);
  689. else
  690. fws->stats.mac_update_failed++;
  691. return 0;
  692. }
  693. brcmf_dbg(TRACE,
  694. "add mac %pM handle %u idx %d\n", addr, mac_handle, ifidx);
  695. existing = brcmf_fws_mac_descriptor_lookup(fws, addr);
  696. if (IS_ERR(existing)) {
  697. if (!entry->occupied) {
  698. entry->mac_handle = mac_handle;
  699. brcmf_fws_init_mac_descriptor(entry, addr, ifidx);
  700. brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
  701. BRCMF_FWS_PSQ_LEN);
  702. } else {
  703. fws->stats.mac_update_failed++;
  704. }
  705. } else {
  706. if (entry != existing) {
  707. brcmf_dbg(TRACE, "relocate mac\n");
  708. memcpy(entry, existing,
  709. offsetof(struct brcmf_fws_mac_descriptor, psq));
  710. entry->mac_handle = mac_handle;
  711. brcmf_fws_clear_mac_descriptor(existing);
  712. } else {
  713. brcmf_dbg(TRACE, "use existing\n");
  714. WARN_ON(entry->mac_handle != mac_handle);
  715. /* TODO: what should we do here: continue, reinit, .. */
  716. }
  717. }
  718. return 0;
  719. }
  720. static int
  721. brcmf_fws_txstatus_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot)
  722. {
  723. int ret;
  724. struct sk_buff *skb;
  725. struct brcmf_fws_mac_descriptor *entry = NULL;
  726. brcmf_dbg(TRACE, "status: flags=0x%X, hslot=%d\n",
  727. flags, hslot);
  728. if (flags == BRCMF_FWS_TXSTATUS_DISCARD)
  729. fws->stats.txs_discard++;
  730. else if (flags == BRCMF_FWS_TXSTATUS_FW_TOSSED)
  731. fws->stats.txs_tossed++;
  732. else
  733. brcmf_err("unexpected txstatus\n");
  734. ret = brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
  735. true);
  736. if (ret != 0) {
  737. brcmf_err("no packet in hanger slot: hslot=%d\n", hslot);
  738. return ret;
  739. }
  740. entry = brcmf_skbcb(skb)->mac;
  741. if (WARN_ON(!entry)) {
  742. ret = -EINVAL;
  743. goto done;
  744. }
  745. entry->transit_count--;
  746. done:
  747. brcmf_txfinalize(fws->drvr, skb, true);
  748. return ret;
  749. }
  750. static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
  751. {
  752. u32 status;
  753. u32 hslot;
  754. u8 flags;
  755. fws->stats.txs_indicate++;
  756. status = le32_to_cpu(*(__le32 *)data);
  757. flags = brcmf_txstatus_get_field(status, FLAGS);
  758. hslot = brcmf_txstatus_get_field(status, HSLOT);
  759. return brcmf_fws_txstatus_process(fws, flags, hslot);
  760. }
  761. static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
  762. {
  763. __le32 timestamp;
  764. memcpy(&timestamp, &data[2], sizeof(timestamp));
  765. brcmf_dbg(INFO, "received: seq %d, timestamp %d\n", data[1],
  766. le32_to_cpu(timestamp));
  767. return 0;
  768. }
  769. /* using macro so sparse checking does not complain
  770. * about locking imbalance.
  771. */
  772. #define brcmf_fws_lock(drvr, flags) \
  773. do { \
  774. flags = 0; \
  775. spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \
  776. } while (0)
  777. /* using macro so sparse checking does not complain
  778. * about locking imbalance.
  779. */
  780. #define brcmf_fws_unlock(drvr, flags) \
  781. spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags))
  782. static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
  783. const struct brcmf_event_msg *e,
  784. void *data)
  785. {
  786. struct brcmf_fws_info *fws = ifp->drvr->fws;
  787. int i;
  788. ulong flags;
  789. u8 *credits = data;
  790. brcmf_fws_lock(ifp->drvr, flags);
  791. for (i = 0; i < ARRAY_SIZE(fws->fifo_credit); i++)
  792. fws->fifo_credit[i] = *credits++;
  793. brcmf_fws_unlock(ifp->drvr, flags);
  794. return 0;
  795. }
  796. int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
  797. struct sk_buff *skb)
  798. {
  799. struct brcmf_fws_info *fws = drvr->fws;
  800. ulong flags;
  801. u8 *signal_data;
  802. s16 data_len;
  803. u8 type;
  804. u8 len;
  805. u8 *data;
  806. brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n",
  807. ifidx, skb->len, signal_len);
  808. WARN_ON(signal_len > skb->len);
  809. /* if flow control disabled, skip to packet data and leave */
  810. if (!signal_len || !drvr->fw_signals) {
  811. skb_pull(skb, signal_len);
  812. return 0;
  813. }
  814. /* lock during tlv parsing */
  815. brcmf_fws_lock(drvr, flags);
  816. fws->stats.header_pulls++;
  817. data_len = signal_len;
  818. signal_data = skb->data;
  819. while (data_len > 0) {
  820. /* extract tlv info */
  821. type = signal_data[0];
  822. /* FILLER type is actually not a TLV, but
  823. * a single byte that can be skipped.
  824. */
  825. if (type == BRCMF_FWS_TYPE_FILLER) {
  826. signal_data += 1;
  827. data_len -= 1;
  828. continue;
  829. }
  830. len = signal_data[1];
  831. data = signal_data + 2;
  832. brcmf_dbg(INFO, "tlv type=%d (%s), len=%d, data[0]=%d\n", type,
  833. brcmf_fws_get_tlv_name(type), len, *data);
  834. /* abort parsing when length invalid */
  835. if (data_len < len + 2)
  836. break;
  837. if (len != brcmf_fws_get_tlv_len(fws, type))
  838. break;
  839. switch (type) {
  840. case BRCMF_FWS_TYPE_MAC_OPEN:
  841. case BRCMF_FWS_TYPE_MAC_CLOSE:
  842. case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT:
  843. case BRCMF_FWS_TYPE_PKTTAG:
  844. case BRCMF_FWS_TYPE_INTERFACE_OPEN:
  845. case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
  846. case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
  847. case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP:
  848. case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET:
  849. case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
  850. case BRCMF_FWS_TYPE_COMP_TXSTATUS:
  851. break;
  852. case BRCMF_FWS_TYPE_MACDESC_ADD:
  853. case BRCMF_FWS_TYPE_MACDESC_DEL:
  854. brcmf_fws_macdesc_indicate(fws, type, data);
  855. break;
  856. case BRCMF_FWS_TYPE_TXSTATUS:
  857. brcmf_fws_txstatus_indicate(fws, data);
  858. break;
  859. case BRCMF_FWS_TYPE_RSSI:
  860. brcmf_fws_rssi_indicate(fws, *data);
  861. break;
  862. case BRCMF_FWS_TYPE_TRANS_ID:
  863. brcmf_fws_dbg_seqnum_check(fws, data);
  864. break;
  865. default:
  866. fws->stats.tlv_invalid_type++;
  867. break;
  868. }
  869. signal_data += len + 2;
  870. data_len -= len + 2;
  871. }
  872. if (data_len != 0)
  873. fws->stats.tlv_parse_failed++;
  874. /* signalling processing result does
  875. * not affect the actual ethernet packet.
  876. */
  877. skb_pull(skb, signal_len);
  878. /* this may be a signal-only packet
  879. */
  880. if (skb->len == 0)
  881. fws->stats.header_only_pkt++;
  882. brcmf_fws_unlock(drvr, flags);
  883. return 0;
  884. }
  885. static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
  886. {
  887. struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
  888. u8 *wlh;
  889. u16 data_offset;
  890. u8 fillers;
  891. __le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod);
  892. brcmf_dbg(TRACE, "enter: ea=%pM, ifidx=%u, pkttag=0x%08X\n",
  893. entry->ea, entry->interface_id, le32_to_cpu(pkttag));
  894. /* +2 is for Type[1] and Len[1] in TLV, plus TIM signal */
  895. data_offset = 2 + BRCMF_FWS_TYPE_PKTTAG_LEN;
  896. fillers = round_up(data_offset, 4) - data_offset;
  897. data_offset += fillers;
  898. skb_push(skb, data_offset);
  899. wlh = skb->data;
  900. wlh[0] = BRCMF_FWS_TYPE_PKTTAG;
  901. wlh[1] = BRCMF_FWS_TYPE_PKTTAG_LEN;
  902. memcpy(&wlh[2], &pkttag, sizeof(pkttag));
  903. wlh += BRCMF_FWS_TYPE_PKTTAG_LEN + 2;
  904. if (fillers)
  905. memset(wlh, BRCMF_FWS_TYPE_FILLER, fillers);
  906. brcmf_proto_hdrpush(fws->drvr, brcmf_skb_if_flags_get_field(skb, INDEX),
  907. data_offset >> 2, skb);
  908. return 0;
  909. }
  910. static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
  911. struct sk_buff *p)
  912. {
  913. struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
  914. struct brcmf_fws_mac_descriptor *entry = skcb->mac;
  915. int rc = 0;
  916. bool header_needed;
  917. int hslot = BRCMF_FWS_HANGER_MAXITEMS;
  918. u8 free_ctr;
  919. u8 ifidx;
  920. u8 flags;
  921. header_needed = skcb->state == BRCMF_FWS_SKBSTATE_NEW;
  922. if (header_needed) {
  923. /* obtaining free slot may fail, but that will be caught
  924. * by the hanger push. This assures the packet has a BDC
  925. * header upon return.
  926. */
  927. hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
  928. free_ctr = entry->seq[fifo];
  929. brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
  930. brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr);
  931. brcmf_skb_htod_tag_set_field(p, GENERATION, 1);
  932. entry->transit_count++;
  933. }
  934. brcmf_skb_if_flags_set_field(p, TRANSMIT, 1);
  935. brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
  936. flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST;
  937. if (!(skcb->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) {
  938. /*
  939. Indicate that this packet is being sent in response to an
  940. explicit request from the firmware side.
  941. */
  942. flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
  943. }
  944. brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
  945. if (header_needed) {
  946. brcmf_fws_hdrpush(fws, p);
  947. rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
  948. if (rc)
  949. brcmf_err("hanger push failed: rc=%d\n", rc);
  950. } else {
  951. int gen;
  952. /* remove old header */
  953. rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, p);
  954. if (rc == 0) {
  955. hslot = brcmf_skb_htod_tag_get_field(p, HSLOT);
  956. brcmf_fws_hanger_get_genbit(&fws->hanger, p,
  957. hslot, &gen);
  958. brcmf_skb_htod_tag_set_field(p, GENERATION, gen);
  959. /* push new header */
  960. brcmf_fws_hdrpush(fws, p);
  961. }
  962. }
  963. return rc;
  964. }
  965. static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
  966. struct sk_buff *skb)
  967. {
  968. struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
  969. struct brcmf_fws_mac_descriptor *entry;
  970. struct brcmf_bus *bus = fws->drvr->bus_if;
  971. int rc;
  972. entry = skcb->mac;
  973. if (IS_ERR(entry))
  974. return PTR_ERR(entry);
  975. rc = brcmf_fws_precommit_skb(fws, fifo, skb);
  976. if (rc < 0) {
  977. fws->stats.generic_error++;
  978. goto done;
  979. }
  980. rc = brcmf_bus_txdata(bus, skb);
  981. if (rc < 0)
  982. goto done;
  983. entry->seq[fifo]++;
  984. fws->stats.pkt2bus++;
  985. return rc;
  986. done:
  987. brcmf_txfinalize(fws->drvr, skb, false);
  988. return rc;
  989. }
  990. int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
  991. {
  992. struct brcmf_pub *drvr = ifp->drvr;
  993. struct brcmf_skbuff_cb *skcb = brcmf_skbcb(skb);
  994. struct ethhdr *eh = (struct ethhdr *)(skb->data);
  995. ulong flags;
  996. u8 ifidx = ifp->ifidx;
  997. int fifo = BRCMF_FWS_FIFO_BCMC;
  998. bool multicast = is_multicast_ether_addr(eh->h_dest);
  999. /* determine the priority */
  1000. if (!skb->priority)
  1001. skb->priority = cfg80211_classify8021d(skb);
  1002. drvr->tx_multicast += !!multicast;
  1003. if (ntohs(eh->h_proto) == ETH_P_PAE)
  1004. atomic_inc(&ifp->pend_8021x_cnt);
  1005. if (!brcmf_fws_fc_active(drvr->fws)) {
  1006. /* If the protocol uses a data header, apply it */
  1007. brcmf_proto_hdrpush(drvr, ifidx, 0, skb);
  1008. /* Use bus module to send data frame */
  1009. return brcmf_bus_txdata(drvr->bus_if, skb);
  1010. }
  1011. /* set control buffer information */
  1012. skcb->mac = brcmf_fws_find_mac_desc(drvr->fws, ifidx, eh->h_dest);
  1013. skcb->state = BRCMF_FWS_SKBSTATE_NEW;
  1014. brcmf_skb_if_flags_set_field(skb, INDEX, ifidx);
  1015. if (!multicast)
  1016. fifo = brcmf_fws_prio2fifo[skb->priority];
  1017. brcmf_skb_if_flags_set_field(skb, FIFO, fifo);
  1018. brcmf_skb_if_flags_set_field(skb, CREDITCHECK, 0);
  1019. brcmf_dbg(TRACE, "ea=%pM, multi=%d, fifo=%d\n", eh->h_dest,
  1020. multicast, fifo);
  1021. brcmf_fws_lock(drvr, flags);
  1022. brcmf_fws_commit_skb(drvr->fws, fifo, skb);
  1023. brcmf_fws_unlock(drvr, flags);
  1024. return 0;
  1025. }
  1026. void brcmf_fws_reset_interface(struct brcmf_if *ifp)
  1027. {
  1028. struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
  1029. brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
  1030. if (!entry)
  1031. return;
  1032. brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx);
  1033. }
  1034. void brcmf_fws_add_interface(struct brcmf_if *ifp)
  1035. {
  1036. struct brcmf_fws_mac_descriptor *entry;
  1037. brcmf_dbg(TRACE, "enter: idx=%d, mac=%pM\n",
  1038. ifp->bssidx, ifp->mac_addr);
  1039. if (!ifp->drvr->fw_signals)
  1040. return;
  1041. entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
  1042. if (entry) {
  1043. ifp->fws_desc = entry;
  1044. brcmf_fws_init_mac_descriptor(entry, ifp->mac_addr, ifp->ifidx);
  1045. brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
  1046. BRCMF_FWS_PSQ_LEN);
  1047. } else {
  1048. brcmf_err("no firmware signalling\n");
  1049. }
  1050. }
  1051. void brcmf_fws_del_interface(struct brcmf_if *ifp)
  1052. {
  1053. struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
  1054. brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx);
  1055. if (!entry)
  1056. return;
  1057. ifp->fws_desc = NULL;
  1058. brcmf_fws_clear_mac_descriptor(entry);
  1059. brcmf_fws_cleanup(ifp->drvr->fws, ifp->ifidx);
  1060. kfree(entry);
  1061. }
  1062. int brcmf_fws_init(struct brcmf_pub *drvr)
  1063. {
  1064. u32 tlv = 0;
  1065. int rc;
  1066. /* enable rssi signals */
  1067. if (drvr->fw_signals)
  1068. tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS |
  1069. BRCMF_FWS_FLAGS_XONXOFF_SIGNALS |
  1070. BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS;
  1071. spin_lock_init(&drvr->fws_spinlock);
  1072. drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL);
  1073. if (!drvr->fws) {
  1074. rc = -ENOMEM;
  1075. goto fail;
  1076. }
  1077. /* set linkage back */
  1078. drvr->fws->drvr = drvr;
  1079. drvr->fws->fcmode = fcmode;
  1080. /* enable proptxtstatus signaling by default */
  1081. rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv);
  1082. if (rc < 0) {
  1083. brcmf_err("failed to set bdcv2 tlv signaling\n");
  1084. goto fail;
  1085. }
  1086. if (brcmf_fweh_register(drvr, BRCMF_E_FIFO_CREDIT_MAP,
  1087. brcmf_fws_notify_credit_map)) {
  1088. brcmf_err("register credit map handler failed\n");
  1089. goto fail;
  1090. }
  1091. brcmf_fws_hanger_init(&drvr->fws->hanger);
  1092. /* create debugfs file for statistics */
  1093. brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats);
  1094. /* TODO: remove upon feature delivery */
  1095. brcmf_err("%s bdcv2 tlv signaling [%x]\n",
  1096. drvr->fw_signals ? "enabled" : "disabled", tlv);
  1097. return 0;
  1098. fail:
  1099. /* disable flow control entirely */
  1100. drvr->fw_signals = false;
  1101. brcmf_fws_deinit(drvr);
  1102. return rc;
  1103. }
  1104. void brcmf_fws_deinit(struct brcmf_pub *drvr)
  1105. {
  1106. struct brcmf_fws_info *fws = drvr->fws;
  1107. ulong flags;
  1108. /* cleanup */
  1109. brcmf_fws_lock(drvr, flags);
  1110. brcmf_fws_cleanup(fws, -1);
  1111. drvr->fws = NULL;
  1112. brcmf_fws_unlock(drvr, flags);
  1113. /* free top structure */
  1114. kfree(fws);
  1115. }
  1116. bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
  1117. {
  1118. if (!fws)
  1119. return false;
  1120. brcmf_dbg(TRACE, "enter: mode=%d\n", fws->fcmode);
  1121. return fws->fcmode != BRCMF_FWS_FCMODE_NONE;
  1122. }
  1123. void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
  1124. {
  1125. ulong flags;
  1126. brcmf_fws_lock(fws->drvr, flags);
  1127. brcmf_fws_txstatus_process(fws, BRCMF_FWS_TXSTATUS_FW_TOSSED,
  1128. brcmf_skb_htod_tag_get_field(skb, HSLOT));
  1129. brcmf_fws_unlock(fws->drvr, flags);
  1130. }