0001
0002
0003
0004
0005
0006 #include <linux/netdevice.h>
0007 #include <linux/module.h>
0008
0009 #include <brcm_hw_ids.h>
0010 #include <brcmu_wifi.h>
0011 #include "core.h"
0012 #include "bus.h"
0013 #include "debug.h"
0014 #include "fwil.h"
0015 #include "fwil_types.h"
0016 #include "feature.h"
0017 #include "common.h"
0018
0019 #define BRCMF_FW_UNSUPPORTED 23
0020
0021
0022
0023
0024 #define BRCMF_FEAT_DEF(_f) \
0025 #_f,
0026 static const char *brcmf_feat_names[] = {
0027 BRCMF_FEAT_LIST
0028 };
0029 #undef BRCMF_FEAT_DEF
0030
0031 struct brcmf_feat_fwcap {
0032 enum brcmf_feat_id feature;
0033 const char * const fwcap_id;
0034 };
0035
0036 static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
0037 { BRCMF_FEAT_MBSS, "mbss" },
0038 { BRCMF_FEAT_MCHAN, "mchan" },
0039 { BRCMF_FEAT_P2P, "p2p" },
0040 { BRCMF_FEAT_MONITOR, "monitor" },
0041 { BRCMF_FEAT_MONITOR_FLAG, "rtap" },
0042 { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
0043 { BRCMF_FEAT_DOT11H, "802.11h" },
0044 { BRCMF_FEAT_SAE, "sae" },
0045 { BRCMF_FEAT_FWAUTH, "idauth" },
0046 };
0047
0048 #ifdef DEBUG
0049
0050
0051
0052 #define BRCMF_QUIRK_DEF(_q) \
0053 #_q,
0054 static const char * const brcmf_quirk_names[] = {
0055 BRCMF_QUIRK_LIST
0056 };
0057 #undef BRCMF_QUIRK_DEF
0058
0059
0060
0061
0062
0063
0064
0065 static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
0066 {
0067 struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
0068 u32 feats = bus_if->drvr->feat_flags;
0069 u32 quirks = bus_if->drvr->chip_quirks;
0070 int id;
0071
0072 seq_printf(seq, "Features: %08x\n", feats);
0073 for (id = 0; id < BRCMF_FEAT_LAST; id++)
0074 if (feats & BIT(id))
0075 seq_printf(seq, "\t%s\n", brcmf_feat_names[id]);
0076 seq_printf(seq, "\nQuirks: %08x\n", quirks);
0077 for (id = 0; id < BRCMF_FEAT_QUIRK_LAST; id++)
0078 if (quirks & BIT(id))
0079 seq_printf(seq, "\t%s\n", brcmf_quirk_names[id]);
0080 return 0;
0081 }
0082 #else
0083 static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
0084 {
0085 return 0;
0086 }
0087 #endif
0088
0089 struct brcmf_feat_fwfeat {
0090 const char * const fwid;
0091 u32 feat_flags;
0092 };
0093
0094 static const struct brcmf_feat_fwfeat brcmf_feat_fwfeat_map[] = {
0095
0096 { "01-6cb8e269", BIT(BRCMF_FEAT_MONITOR) },
0097
0098 { "01-c47a91a4", BIT(BRCMF_FEAT_MONITOR) },
0099
0100 { "01-801fb449", BIT(BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR) },
0101
0102 { "01-d2cbb8fd", BIT(BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR) },
0103 };
0104
0105 static void brcmf_feat_firmware_overrides(struct brcmf_pub *drv)
0106 {
0107 const struct brcmf_feat_fwfeat *e;
0108 u32 feat_flags = 0;
0109 int i;
0110
0111 for (i = 0; i < ARRAY_SIZE(brcmf_feat_fwfeat_map); i++) {
0112 e = &brcmf_feat_fwfeat_map[i];
0113 if (!strcmp(e->fwid, drv->fwver)) {
0114 feat_flags = e->feat_flags;
0115 break;
0116 }
0117 }
0118
0119 if (!feat_flags)
0120 return;
0121
0122 for (i = 0; i < BRCMF_FEAT_LAST; i++)
0123 if (feat_flags & BIT(i))
0124 brcmf_dbg(INFO, "enabling firmware feature: %s\n",
0125 brcmf_feat_names[i]);
0126 drv->feat_flags |= feat_flags;
0127 }
0128
0129
0130
0131
0132
0133
0134
0135
0136 static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
0137 enum brcmf_feat_id id, char *name)
0138 {
0139 u32 data;
0140 int err;
0141
0142
0143 ifp->fwil_fwerr = true;
0144
0145 err = brcmf_fil_iovar_int_get(ifp, name, &data);
0146 if (err == 0) {
0147 brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
0148 ifp->drvr->feat_flags |= BIT(id);
0149 } else {
0150 brcmf_dbg(TRACE, "%s feature check failed: %d\n",
0151 brcmf_feat_names[id], err);
0152 }
0153
0154 ifp->fwil_fwerr = false;
0155 }
0156
0157 static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
0158 enum brcmf_feat_id id, char *name,
0159 const void *data, size_t len)
0160 {
0161 int err;
0162
0163
0164 ifp->fwil_fwerr = true;
0165
0166 err = brcmf_fil_iovar_data_set(ifp, name, data, len);
0167 if (err != -BRCMF_FW_UNSUPPORTED) {
0168 brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
0169 ifp->drvr->feat_flags |= BIT(id);
0170 } else {
0171 brcmf_dbg(TRACE, "%s feature check failed: %d\n",
0172 brcmf_feat_names[id], err);
0173 }
0174
0175 ifp->fwil_fwerr = false;
0176 }
0177
0178 #define MAX_CAPS_BUFFER_SIZE 768
0179 static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp)
0180 {
0181 struct brcmf_pub *drvr = ifp->drvr;
0182 char caps[MAX_CAPS_BUFFER_SIZE];
0183 enum brcmf_feat_id id;
0184 int i, err;
0185
0186 err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
0187 if (err) {
0188 bphy_err(drvr, "could not get firmware cap (%d)\n", err);
0189 return;
0190 }
0191
0192 brcmf_dbg(INFO, "[ %s]\n", caps);
0193
0194 for (i = 0; i < ARRAY_SIZE(brcmf_fwcap_map); i++) {
0195 if (strnstr(caps, brcmf_fwcap_map[i].fwcap_id, sizeof(caps))) {
0196 id = brcmf_fwcap_map[i].feature;
0197 brcmf_dbg(INFO, "enabling feature: %s\n",
0198 brcmf_feat_names[id]);
0199 ifp->drvr->feat_flags |= BIT(id);
0200 }
0201 }
0202 }
0203
0204
0205
0206
0207
0208
0209
0210 static int brcmf_feat_fwcap_debugfs_read(struct seq_file *seq, void *data)
0211 {
0212 struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
0213 struct brcmf_pub *drvr = bus_if->drvr;
0214 struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
0215 char caps[MAX_CAPS_BUFFER_SIZE + 1] = { };
0216 char *tmp;
0217 int err;
0218
0219 err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
0220 if (err) {
0221 bphy_err(drvr, "could not get firmware cap (%d)\n", err);
0222 return err;
0223 }
0224
0225
0226 for (tmp = caps; *tmp; tmp++) {
0227 if (*tmp == ' ')
0228 *tmp = '\n';
0229 }
0230
0231
0232 seq_printf(seq, "%s", caps);
0233
0234 if (tmp > caps && *(tmp - 1) != '\n')
0235 seq_printf(seq, "\n");
0236
0237 return 0;
0238 }
0239
0240 void brcmf_feat_attach(struct brcmf_pub *drvr)
0241 {
0242 struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
0243 struct brcmf_pno_macaddr_le pfn_mac;
0244 struct brcmf_gscan_config gscan_cfg;
0245 u32 wowl_cap;
0246 s32 err;
0247
0248 brcmf_feat_firmware_capabilities(ifp);
0249 memset(&gscan_cfg, 0, sizeof(gscan_cfg));
0250 if (drvr->bus_if->chip != BRCM_CC_43430_CHIP_ID &&
0251 drvr->bus_if->chip != BRCM_CC_4345_CHIP_ID &&
0252 drvr->bus_if->chip != BRCM_CC_43454_CHIP_ID)
0253 brcmf_feat_iovar_data_set(ifp, BRCMF_FEAT_GSCAN,
0254 "pfn_gscan_cfg",
0255 &gscan_cfg, sizeof(gscan_cfg));
0256 brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
0257 if (drvr->bus_if->wowl_supported)
0258 brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
0259 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL)) {
0260 err = brcmf_fil_iovar_int_get(ifp, "wowl_cap", &wowl_cap);
0261 if (!err) {
0262 ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_WOWL_ARP_ND);
0263 if (wowl_cap & BRCMF_WOWL_PFN_FOUND)
0264 ifp->drvr->feat_flags |=
0265 BIT(BRCMF_FEAT_WOWL_ND);
0266 if (wowl_cap & BRCMF_WOWL_GTK_FAILURE)
0267 ifp->drvr->feat_flags |=
0268 BIT(BRCMF_FEAT_WOWL_GTK);
0269 }
0270 }
0271
0272 switch (drvr->bus_if->chip) {
0273 case BRCM_CC_4330_CHIP_ID:
0274 case BRCM_CC_43362_CHIP_ID:
0275 ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS);
0276 break;
0277 default:
0278 break;
0279 }
0280 brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode");
0281 brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_TDLS, "tdls_enable");
0282 brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MFP, "mfp");
0283
0284 pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
0285 err = brcmf_fil_iovar_data_get(ifp, "pfn_macaddr", &pfn_mac,
0286 sizeof(pfn_mac));
0287 if (!err)
0288 ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_SCAN_RANDOM_MAC);
0289
0290 brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
0291
0292 if (drvr->settings->feature_disable) {
0293 brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
0294 ifp->drvr->feat_flags,
0295 drvr->settings->feature_disable);
0296 ifp->drvr->feat_flags &= ~drvr->settings->feature_disable;
0297 }
0298
0299 brcmf_feat_firmware_overrides(drvr);
0300
0301
0302 switch (drvr->bus_if->chip) {
0303 case BRCM_CC_43236_CHIP_ID:
0304 drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_AUTO_AUTH);
0305 break;
0306 case BRCM_CC_4329_CHIP_ID:
0307 drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_NEED_MPC);
0308 break;
0309 default:
0310
0311 break;
0312 }
0313 }
0314
0315 void brcmf_feat_debugfs_create(struct brcmf_pub *drvr)
0316 {
0317 brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read);
0318 brcmf_debugfs_add_entry(drvr, "fwcap", brcmf_feat_fwcap_debugfs_read);
0319 }
0320
0321 bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id)
0322 {
0323 return (ifp->drvr->feat_flags & BIT(id));
0324 }
0325
0326 bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
0327 enum brcmf_feat_quirk quirk)
0328 {
0329 return (ifp->drvr->chip_quirks & BIT(quirk));
0330 }