bcm43xx_xmit.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /*
  2. Broadcom BCM43xx wireless driver
  3. Transmission (TX/RX) related functions.
  4. Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
  5. Stefano Brivio <st3@riseup.net>
  6. Michael Buesch <mbuesch@freenet.de>
  7. Danny van Dyk <kugelfang@gentoo.org>
  8. Andreas Jaggi <andreas.jaggi@waterwave.ch>
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. GNU General Public License for more details.
  17. You should have received a copy of the GNU General Public License
  18. along with this program; see the file COPYING. If not, write to
  19. the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
  20. Boston, MA 02110-1301, USA.
  21. */
  22. #include "bcm43xx_xmit.h"
  23. #include <linux/etherdevice.h>
  24. /* Extract the bitrate out of a CCK PLCP header. */
  25. static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp)
  26. {
  27. switch (plcp->raw[0]) {
  28. case 0x0A:
  29. return IEEE80211_CCK_RATE_1MB;
  30. case 0x14:
  31. return IEEE80211_CCK_RATE_2MB;
  32. case 0x37:
  33. return IEEE80211_CCK_RATE_5MB;
  34. case 0x6E:
  35. return IEEE80211_CCK_RATE_11MB;
  36. }
  37. assert(0);
  38. return 0;
  39. }
  40. /* Extract the bitrate out of an OFDM PLCP header. */
  41. static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp)
  42. {
  43. switch (plcp->raw[0] & 0xF) {
  44. case 0xB:
  45. return IEEE80211_OFDM_RATE_6MB;
  46. case 0xF:
  47. return IEEE80211_OFDM_RATE_9MB;
  48. case 0xA:
  49. return IEEE80211_OFDM_RATE_12MB;
  50. case 0xE:
  51. return IEEE80211_OFDM_RATE_18MB;
  52. case 0x9:
  53. return IEEE80211_OFDM_RATE_24MB;
  54. case 0xD:
  55. return IEEE80211_OFDM_RATE_36MB;
  56. case 0x8:
  57. return IEEE80211_OFDM_RATE_48MB;
  58. case 0xC:
  59. return IEEE80211_OFDM_RATE_54MB;
  60. }
  61. assert(0);
  62. return 0;
  63. }
  64. u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
  65. {
  66. switch (bitrate) {
  67. case IEEE80211_CCK_RATE_1MB:
  68. return 0x0A;
  69. case IEEE80211_CCK_RATE_2MB:
  70. return 0x14;
  71. case IEEE80211_CCK_RATE_5MB:
  72. return 0x37;
  73. case IEEE80211_CCK_RATE_11MB:
  74. return 0x6E;
  75. }
  76. assert(0);
  77. return 0;
  78. }
  79. u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
  80. {
  81. switch (bitrate) {
  82. case IEEE80211_OFDM_RATE_6MB:
  83. return 0xB;
  84. case IEEE80211_OFDM_RATE_9MB:
  85. return 0xF;
  86. case IEEE80211_OFDM_RATE_12MB:
  87. return 0xA;
  88. case IEEE80211_OFDM_RATE_18MB:
  89. return 0xE;
  90. case IEEE80211_OFDM_RATE_24MB:
  91. return 0x9;
  92. case IEEE80211_OFDM_RATE_36MB:
  93. return 0xD;
  94. case IEEE80211_OFDM_RATE_48MB:
  95. return 0x8;
  96. case IEEE80211_OFDM_RATE_54MB:
  97. return 0xC;
  98. }
  99. assert(0);
  100. return 0;
  101. }
  102. static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
  103. const u16 octets, const u8 bitrate,
  104. const int ofdm_modulation)
  105. {
  106. __le32 *data = &(plcp->data);
  107. __u8 *raw = plcp->raw;
  108. if (ofdm_modulation) {
  109. *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
  110. assert(!(octets & 0xF000));
  111. *data |= (octets << 5);
  112. *data = cpu_to_le32(*data);
  113. } else {
  114. u32 plen;
  115. plen = octets * 16 / bitrate;
  116. if ((octets * 16 % bitrate) > 0) {
  117. plen++;
  118. if ((bitrate == IEEE80211_CCK_RATE_11MB)
  119. && ((octets * 8 % 11) < 4)) {
  120. raw[1] = 0x84;
  121. } else
  122. raw[1] = 0x04;
  123. } else
  124. raw[1] = 0x04;
  125. *data |= cpu_to_le32(plen << 16);
  126. raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
  127. }
  128. }
  129. static u8 bcm43xx_calc_fallback_rate(u8 bitrate)
  130. {
  131. switch (bitrate) {
  132. case IEEE80211_CCK_RATE_1MB:
  133. return IEEE80211_CCK_RATE_1MB;
  134. case IEEE80211_CCK_RATE_2MB:
  135. return IEEE80211_CCK_RATE_1MB;
  136. case IEEE80211_CCK_RATE_5MB:
  137. return IEEE80211_CCK_RATE_2MB;
  138. case IEEE80211_CCK_RATE_11MB:
  139. return IEEE80211_CCK_RATE_5MB;
  140. case IEEE80211_OFDM_RATE_6MB:
  141. return IEEE80211_CCK_RATE_5MB;
  142. case IEEE80211_OFDM_RATE_9MB:
  143. return IEEE80211_OFDM_RATE_6MB;
  144. case IEEE80211_OFDM_RATE_12MB:
  145. return IEEE80211_OFDM_RATE_9MB;
  146. case IEEE80211_OFDM_RATE_18MB:
  147. return IEEE80211_OFDM_RATE_12MB;
  148. case IEEE80211_OFDM_RATE_24MB:
  149. return IEEE80211_OFDM_RATE_18MB;
  150. case IEEE80211_OFDM_RATE_36MB:
  151. return IEEE80211_OFDM_RATE_24MB;
  152. case IEEE80211_OFDM_RATE_48MB:
  153. return IEEE80211_OFDM_RATE_36MB;
  154. case IEEE80211_OFDM_RATE_54MB:
  155. return IEEE80211_OFDM_RATE_48MB;
  156. }
  157. assert(0);
  158. return 0;
  159. }
  160. static
  161. __le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header,
  162. u8 bitrate)
  163. {
  164. const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl);
  165. __le16 duration_id = wireless_header->duration_id;
  166. switch (WLAN_FC_GET_TYPE(frame_ctl)) {
  167. case IEEE80211_FTYPE_DATA:
  168. case IEEE80211_FTYPE_MGMT:
  169. //TODO: Steal the code from ieee80211, once it is completed there.
  170. break;
  171. case IEEE80211_FTYPE_CTL:
  172. /* Use the original duration/id. */
  173. break;
  174. default:
  175. assert(0);
  176. }
  177. return duration_id;
  178. }
  179. static inline
  180. u16 ceiling_div(u16 dividend, u16 divisor)
  181. {
  182. return ((dividend + divisor - 1) / divisor);
  183. }
  184. static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy,
  185. struct bcm43xx_txhdr *txhdr,
  186. u16 *flags,
  187. u8 bitrate,
  188. const struct ieee80211_hdr_4addr *wlhdr)
  189. {
  190. u16 fctl;
  191. u16 dur;
  192. u8 fallback_bitrate;
  193. int ofdm_modulation;
  194. int fallback_ofdm_modulation;
  195. // u8 *sa, *da;
  196. u16 flen;
  197. //FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr);
  198. //FIXME da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr);
  199. fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
  200. ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
  201. fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
  202. flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN,
  203. bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp),
  204. flen, bitrate,
  205. !ieee80211_is_cck_rate(bitrate));
  206. bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp),
  207. flen, fallback_bitrate,
  208. !ieee80211_is_cck_rate(fallback_bitrate));
  209. fctl = IEEE80211_FTYPE_CTL;
  210. fctl |= IEEE80211_STYPE_RTS;
  211. dur = le16_to_cpu(wlhdr->duration_id);
  212. /*FIXME: should we test for dur==0 here and let it unmodified in this case?
  213. * The following assert checks for this case...
  214. */
  215. assert(dur);
  216. /*FIXME: The duration calculation is not really correct.
  217. * I am not 100% sure which bitrate to use. We use the RTS rate here,
  218. * but this is likely to be wrong.
  219. */
  220. if (phy->type == BCM43xx_PHYTYPE_A) {
  221. /* Three times SIFS */
  222. dur += 16 * 3;
  223. /* Add ACK duration. */
  224. dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
  225. bitrate * 4);
  226. /* Add CTS duration. */
  227. dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
  228. bitrate * 4);
  229. } else {
  230. /* Three times SIFS */
  231. dur += 10 * 3;
  232. /* Add ACK duration. */
  233. dur += ceiling_div(8 * (14 /*bytes*/) * 10,
  234. bitrate);
  235. /* Add CTS duration. */
  236. dur += ceiling_div(8 * (14 /*bytes*/) * 10,
  237. bitrate);
  238. }
  239. txhdr->rts_cts_frame_control = cpu_to_le16(fctl);
  240. txhdr->rts_cts_dur = cpu_to_le16(dur);
  241. //printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3));
  242. //printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da));
  243. memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME!
  244. // memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN);
  245. *flags |= BCM43xx_TXHDRFLAG_RTSCTS;
  246. *flags |= BCM43xx_TXHDRFLAG_RTS;
  247. if (ofdm_modulation)
  248. *flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM;
  249. if (fallback_ofdm_modulation)
  250. *flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM;
  251. }
  252. void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
  253. struct bcm43xx_txhdr *txhdr,
  254. const unsigned char *fragment_data,
  255. const unsigned int fragment_len,
  256. const int is_first_fragment,
  257. const u16 cookie)
  258. {
  259. const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
  260. const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data;
  261. const struct ieee80211_security *secinfo = &bcm->ieee->sec;
  262. u8 bitrate;
  263. u8 fallback_bitrate;
  264. int ofdm_modulation;
  265. int fallback_ofdm_modulation;
  266. u16 plcp_fragment_len = fragment_len;
  267. u16 flags = 0;
  268. u16 control = 0;
  269. u16 wsec_rate = 0;
  270. u16 encrypt_frame;
  271. const u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(wireless_header->frame_ctl));
  272. const int is_mgt = (ftype == IEEE80211_FTYPE_MGMT);
  273. /* Now construct the TX header. */
  274. memset(txhdr, 0, sizeof(*txhdr));
  275. bitrate = ieee80211softmac_suggest_txrate(bcm->softmac,
  276. is_multicast_ether_addr(wireless_header->addr1), is_mgt);
  277. ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
  278. fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
  279. fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
  280. /* Set Frame Control from 80211 header. */
  281. txhdr->frame_control = wireless_header->frame_ctl;
  282. /* Copy address1 from 80211 header. */
  283. memcpy(txhdr->mac1, wireless_header->addr1, 6);
  284. /* Set the fallback duration ID. */
  285. txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header,
  286. fallback_bitrate);
  287. /* Set the cookie (used as driver internal ID for the frame) */
  288. txhdr->cookie = cpu_to_le16(cookie);
  289. /* Hardware appends FCS. */
  290. plcp_fragment_len += IEEE80211_FCS_LEN;
  291. /* Hardware encryption. */
  292. encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
  293. if (encrypt_frame && !bcm->ieee->host_encrypt) {
  294. const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
  295. memcpy(txhdr->wep_iv, hdr->payload, 4);
  296. /* Hardware appends ICV. */
  297. plcp_fragment_len += 4;
  298. wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
  299. & BCM43xx_TXHDR_WSEC_ALGO_MASK;
  300. wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
  301. & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
  302. }
  303. /* Generate the PLCP header and the fallback PLCP header. */
  304. bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
  305. plcp_fragment_len,
  306. bitrate, ofdm_modulation);
  307. bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len,
  308. fallback_bitrate, fallback_ofdm_modulation);
  309. /* Set the CONTROL field */
  310. if (ofdm_modulation)
  311. control |= BCM43xx_TXHDRCTL_OFDM;
  312. if (bcm->short_preamble) //FIXME: could be the other way around, please test
  313. control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
  314. control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
  315. & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
  316. /* Set the FLAGS field */
  317. if (!is_multicast_ether_addr(wireless_header->addr1) &&
  318. !is_broadcast_ether_addr(wireless_header->addr1))
  319. flags |= BCM43xx_TXHDRFLAG_EXPECTACK;
  320. if (1 /* FIXME: PS poll?? */)
  321. flags |= 0x10; // FIXME: unknown meaning.
  322. if (fallback_ofdm_modulation)
  323. flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
  324. if (is_first_fragment)
  325. flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
  326. /* Set WSEC/RATE field */
  327. wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT)
  328. & BCM43xx_TXHDR_RATE_MASK;
  329. /* Generate the RTS/CTS packet, if required. */
  330. /* FIXME: We should first try with CTS-to-self,
  331. * if we are on 80211g. If we get too many
  332. * failures (hidden nodes), we should switch back to RTS/CTS.
  333. */
  334. if (0/*FIXME txctl->use_rts_cts*/) {
  335. bcm43xx_generate_rts(phy, txhdr, &flags,
  336. 0/*FIXME txctl->rts_cts_rate*/,
  337. wireless_header);
  338. }
  339. txhdr->flags = cpu_to_le16(flags);
  340. txhdr->control = cpu_to_le16(control);
  341. txhdr->wsec_rate = cpu_to_le16(wsec_rate);
  342. }
  343. static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
  344. u8 in_rssi, int ofdm,
  345. int adjust_2053, int adjust_2050)
  346. {
  347. struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
  348. struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
  349. s32 tmp;
  350. switch (radio->version) {
  351. case 0x2050:
  352. if (ofdm) {
  353. tmp = in_rssi;
  354. if (tmp > 127)
  355. tmp -= 256;
  356. tmp *= 73;
  357. tmp /= 64;
  358. if (adjust_2050)
  359. tmp += 25;
  360. else
  361. tmp -= 3;
  362. } else {
  363. if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
  364. if (in_rssi > 63)
  365. in_rssi = 63;
  366. tmp = radio->nrssi_lt[in_rssi];
  367. tmp = 31 - tmp;
  368. tmp *= -131;
  369. tmp /= 128;
  370. tmp -= 57;
  371. } else {
  372. tmp = in_rssi;
  373. tmp = 31 - tmp;
  374. tmp *= -149;
  375. tmp /= 128;
  376. tmp -= 68;
  377. }
  378. if (phy->type == BCM43xx_PHYTYPE_G &&
  379. adjust_2050)
  380. tmp += 25;
  381. }
  382. break;
  383. case 0x2060:
  384. if (in_rssi > 127)
  385. tmp = in_rssi - 256;
  386. else
  387. tmp = in_rssi;
  388. break;
  389. default:
  390. tmp = in_rssi;
  391. tmp -= 11;
  392. tmp *= 103;
  393. tmp /= 64;
  394. if (adjust_2053)
  395. tmp -= 109;
  396. else
  397. tmp -= 83;
  398. }
  399. return (s8)tmp;
  400. }
  401. //TODO
  402. #if 0
  403. static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
  404. u8 in_rssi)
  405. {
  406. struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
  407. s8 ret;
  408. if (phy->type == BCM43xx_PHYTYPE_A) {
  409. //TODO: Incomplete specs.
  410. ret = 0;
  411. } else
  412. ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
  413. return ret;
  414. }
  415. #endif
  416. int bcm43xx_rx(struct bcm43xx_private *bcm,
  417. struct sk_buff *skb,
  418. struct bcm43xx_rxhdr *rxhdr)
  419. {
  420. struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
  421. struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
  422. struct bcm43xx_plcp_hdr4 *plcp;
  423. struct ieee80211_rx_stats stats;
  424. struct ieee80211_hdr_4addr *wlhdr;
  425. u16 frame_ctl;
  426. int is_packet_for_us = 0;
  427. int err = -EINVAL;
  428. const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
  429. const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
  430. const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
  431. const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
  432. if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
  433. plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
  434. /* Skip two unknown bytes and the PLCP header. */
  435. skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
  436. } else {
  437. plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
  438. /* Skip the PLCP header. */
  439. skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
  440. }
  441. /* The SKB contains the PAYLOAD (wireless header + data)
  442. * at this point. The FCS at the end is stripped.
  443. */
  444. memset(&stats, 0, sizeof(stats));
  445. stats.mac_time = le16_to_cpu(rxhdr->mactime);
  446. stats.rssi = rxhdr->rssi;
  447. stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
  448. !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
  449. !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
  450. stats.noise = bcm->stats.noise;
  451. if (is_ofdm)
  452. stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
  453. else
  454. stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
  455. stats.received_channel = radio->channel;
  456. stats.mask = IEEE80211_STATMASK_SIGNAL |
  457. IEEE80211_STATMASK_NOISE |
  458. IEEE80211_STATMASK_RATE |
  459. IEEE80211_STATMASK_RSSI;
  460. if (phy->type == BCM43xx_PHYTYPE_A)
  461. stats.freq = IEEE80211_52GHZ_BAND;
  462. else
  463. stats.freq = IEEE80211_24GHZ_BAND;
  464. stats.len = skb->len;
  465. bcm->stats.last_rx = jiffies;
  466. if (bcm->ieee->iw_mode == IW_MODE_MONITOR) {
  467. err = ieee80211_rx(bcm->ieee, skb, &stats);
  468. return (err == 0) ? -EINVAL : 0;
  469. }
  470. wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
  471. switch (bcm->ieee->iw_mode) {
  472. case IW_MODE_ADHOC:
  473. if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
  474. memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
  475. is_broadcast_ether_addr(wlhdr->addr1) ||
  476. is_multicast_ether_addr(wlhdr->addr1) ||
  477. bcm->net_dev->flags & IFF_PROMISC)
  478. is_packet_for_us = 1;
  479. break;
  480. case IW_MODE_INFRA:
  481. default:
  482. /* When receiving multicast or broadcast packets, filter out
  483. the packets we send ourself; we shouldn't see those */
  484. if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
  485. memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
  486. (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
  487. (is_broadcast_ether_addr(wlhdr->addr1) ||
  488. is_multicast_ether_addr(wlhdr->addr1) ||
  489. bcm->net_dev->flags & IFF_PROMISC)))
  490. is_packet_for_us = 1;
  491. break;
  492. }
  493. frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
  494. switch (WLAN_FC_GET_TYPE(frame_ctl)) {
  495. case IEEE80211_FTYPE_MGMT:
  496. ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
  497. break;
  498. case IEEE80211_FTYPE_DATA:
  499. if (is_packet_for_us) {
  500. err = ieee80211_rx(bcm->ieee, skb, &stats);
  501. err = (err == 0) ? -EINVAL : 0;
  502. }
  503. break;
  504. case IEEE80211_FTYPE_CTL:
  505. break;
  506. default:
  507. assert(0);
  508. return -EINVAL;
  509. }
  510. return err;
  511. }