344-0004-brcmfmac-Configure-country-code-using-device-specifi.patch 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. From: Hante Meuleman <meuleman@broadcom.com>
  2. Date: Wed, 17 Feb 2016 11:26:53 +0100
  3. Subject: [PATCH] brcmfmac: Configure country code using device specific
  4. settings
  5. Country code configuration in a device is a device specific
  6. operation. For this the country code as specified by reg notifier
  7. (iso3166 alpha2) needs to be translated to a device specific
  8. country locale and revision number. This patch adds this
  9. translation and puts a placeholder in the device specific settings
  10. where the translation table can be stored. Additional patches will
  11. be needed to read these tables from for example device platform
  12. data.
  13. Reviewed-by: Arend Van Spriel <arend@broadcom.com>
  14. Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
  15. Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
  16. Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
  17. Signed-off-by: Arend van Spriel <arend@broadcom.com>
  18. Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  19. ---
  20. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
  21. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
  22. @@ -6405,28 +6405,85 @@ int brcmf_cfg80211_wait_vif_event(struct
  23. vif_event_equals(event, action), timeout);
  24. }
  25. +static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2],
  26. + struct brcmf_fil_country_le *ccreq)
  27. +{
  28. + struct cc_translate *country_codes;
  29. + struct cc_entry *cc;
  30. + s32 found_index;
  31. + int i;
  32. +
  33. + country_codes = drvr->settings->country_codes;
  34. + if (!country_codes) {
  35. + brcmf_dbg(TRACE, "No country codes configured for device\n");
  36. + return -EINVAL;
  37. + }
  38. +
  39. + if ((alpha2[0] == ccreq->country_abbrev[0]) &&
  40. + (alpha2[1] == ccreq->country_abbrev[1])) {
  41. + brcmf_dbg(TRACE, "Country code already set\n");
  42. + return -EAGAIN;
  43. + }
  44. +
  45. + found_index = -1;
  46. + for (i = 0; i < country_codes->table_size; i++) {
  47. + cc = &country_codes->table[i];
  48. + if ((cc->iso3166[0] == '\0') && (found_index == -1))
  49. + found_index = i;
  50. + if ((cc->iso3166[0] == alpha2[0]) &&
  51. + (cc->iso3166[1] == alpha2[1])) {
  52. + found_index = i;
  53. + break;
  54. + }
  55. + }
  56. + if (found_index == -1) {
  57. + brcmf_dbg(TRACE, "No country code match found\n");
  58. + return -EINVAL;
  59. + }
  60. + memset(ccreq, 0, sizeof(*ccreq));
  61. + ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev);
  62. + memcpy(ccreq->ccode, country_codes->table[found_index].cc,
  63. + BRCMF_COUNTRY_BUF_SZ);
  64. + ccreq->country_abbrev[0] = alpha2[0];
  65. + ccreq->country_abbrev[1] = alpha2[1];
  66. + ccreq->country_abbrev[2] = 0;
  67. +
  68. + return 0;
  69. +}
  70. +
  71. static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
  72. struct regulatory_request *req)
  73. {
  74. struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
  75. struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
  76. struct brcmf_fil_country_le ccreq;
  77. + s32 err;
  78. int i;
  79. - brcmf_dbg(TRACE, "enter: initiator=%d, alpha=%c%c\n", req->initiator,
  80. - req->alpha2[0], req->alpha2[1]);
  81. -
  82. /* ignore non-ISO3166 country codes */
  83. for (i = 0; i < sizeof(req->alpha2); i++)
  84. if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
  85. - brcmf_err("not a ISO3166 code\n");
  86. + brcmf_err("not a ISO3166 code (0x%02x 0x%02x)\n",
  87. + req->alpha2[0], req->alpha2[1]);
  88. return;
  89. }
  90. - memset(&ccreq, 0, sizeof(ccreq));
  91. - ccreq.rev = cpu_to_le32(-1);
  92. - memcpy(ccreq.ccode, req->alpha2, sizeof(req->alpha2));
  93. - if (brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq))) {
  94. - brcmf_err("firmware rejected country setting\n");
  95. +
  96. + brcmf_dbg(TRACE, "Enter: initiator=%d, alpha=%c%c\n", req->initiator,
  97. + req->alpha2[0], req->alpha2[1]);
  98. +
  99. + err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq));
  100. + if (err) {
  101. + brcmf_err("Country code iovar returned err = %d\n", err);
  102. + return;
  103. + }
  104. +
  105. + err = brcmf_translate_country_code(ifp->drvr, req->alpha2, &ccreq);
  106. + if (err)
  107. + return;
  108. +
  109. + err = brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq));
  110. + if (err) {
  111. + brcmf_err("Firmware rejected country setting\n");
  112. return;
  113. }
  114. brcmf_setup_wiphybands(wiphy);
  115. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
  116. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
  117. @@ -230,10 +230,8 @@ void brcmf_mp_attach(void)
  118. int brcmf_mp_device_attach(struct brcmf_pub *drvr)
  119. {
  120. drvr->settings = kzalloc(sizeof(*drvr->settings), GFP_ATOMIC);
  121. - if (!drvr->settings) {
  122. - brcmf_err("Failed to alloca storage space for settings\n");
  123. + if (!drvr->settings)
  124. return -ENOMEM;
  125. - }
  126. drvr->settings->sdiod_txglomsz = brcmf_sdiod_txglomsz;
  127. drvr->settings->p2p_enable = !!brcmf_p2p_enable;
  128. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
  129. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
  130. @@ -15,6 +15,8 @@
  131. #ifndef BRCMFMAC_COMMON_H
  132. #define BRCMFMAC_COMMON_H
  133. +#include "fwil_types.h"
  134. +
  135. extern const u8 ALLFFMAC[ETH_ALEN];
  136. #define BRCMF_FW_ALTPATH_LEN 256
  137. @@ -39,6 +41,33 @@ struct brcmf_mp_global_t {
  138. extern struct brcmf_mp_global_t brcmf_mp_global;
  139. /**
  140. + * struct cc_entry - Struct for translating user space country code (iso3166) to
  141. + * firmware country code and revision.
  142. + *
  143. + * @iso3166: iso3166 alpha 2 country code string.
  144. + * @cc: firmware country code string.
  145. + * @rev: firmware country code revision.
  146. + */
  147. +struct cc_entry {
  148. + char iso3166[BRCMF_COUNTRY_BUF_SZ];
  149. + char cc[BRCMF_COUNTRY_BUF_SZ];
  150. + s32 rev;
  151. +};
  152. +
  153. +/**
  154. + * struct cc_translate - Struct for translating country codes as set by user
  155. + * space to a country code and rev which can be used by
  156. + * firmware.
  157. + *
  158. + * @table_size: number of entries in table (> 0)
  159. + * @table: dynamic array of 1 or more elements with translation information.
  160. + */
  161. +struct cc_translate {
  162. + int table_size;
  163. + struct cc_entry table[0];
  164. +};
  165. +
  166. +/**
  167. * struct brcmf_mp_device - Device module paramaters.
  168. *
  169. * @sdiod_txglomsz: SDIO txglom size.
  170. @@ -47,6 +76,7 @@ extern struct brcmf_mp_global_t brcmf_mp
  171. * @feature_disable: Feature_disable bitmask.
  172. * @fcmode: FWS flow control.
  173. * @roamoff: Firmware roaming off?
  174. + * @country_codes: If available, pointer to struct for translating country codes
  175. */
  176. struct brcmf_mp_device {
  177. int sdiod_txglomsz;
  178. @@ -56,6 +86,7 @@ struct brcmf_mp_device {
  179. int fcmode;
  180. bool roamoff;
  181. bool ignore_probe_fail;
  182. + struct cc_translate *country_codes;
  183. };
  184. void brcmf_mp_attach(void);
  185. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
  186. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
  187. @@ -134,6 +134,8 @@
  188. #define BRCMF_PFN_MAC_OUI_ONLY BIT(0)
  189. #define BRCMF_PFN_SET_MAC_UNASSOC BIT(1)
  190. +#define BRCMF_MCSSET_LEN 16
  191. +
  192. /* join preference types for join_pref iovar */
  193. enum brcmf_join_pref_types {
  194. BRCMF_JOIN_PREF_RSSI = 1,
  195. @@ -279,7 +281,7 @@ struct brcmf_bss_info_le {
  196. __le32 reserved32[1]; /* Reserved for expansion of BSS properties */
  197. u8 flags; /* flags */
  198. u8 reserved[3]; /* Reserved for expansion of BSS properties */
  199. - u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */
  200. + u8 basic_mcs[BRCMF_MCSSET_LEN]; /* 802.11N BSS required MCS set */
  201. __le16 ie_offset; /* offset at which IEs start, from beginning */
  202. __le32 ie_length; /* byte length of Information Elements */