diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211')
18 files changed, 1124 insertions, 930 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 4cffb2ee3673..de0cff3df389 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile | |||
@@ -34,6 +34,7 @@ brcmfmac-objs += \ | |||
34 | dhd_common.o \ | 34 | dhd_common.o \ |
35 | dhd_linux.o \ | 35 | dhd_linux.o \ |
36 | firmware.o \ | 36 | firmware.o \ |
37 | feature.o \ | ||
37 | btcoex.o \ | 38 | btcoex.o \ |
38 | vendor.o | 39 | vendor.o |
39 | brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ | 40 | brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index a16e644e7c08..f467cafe3e8f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/mmc/sdio.h> | 25 | #include <linux/mmc/sdio.h> |
26 | #include <linux/mmc/core.h> | 26 | #include <linux/mmc/core.h> |
27 | #include <linux/mmc/sdio_func.h> | 27 | #include <linux/mmc/sdio_func.h> |
28 | #include <linux/mmc/sdio_ids.h> | ||
29 | #include <linux/mmc/card.h> | 28 | #include <linux/mmc/card.h> |
30 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
31 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
@@ -979,18 +978,20 @@ out: | |||
979 | return ret; | 978 | return ret; |
980 | } | 979 | } |
981 | 980 | ||
981 | #define BRCMF_SDIO_DEVICE(dev_id) \ | ||
982 | {SDIO_DEVICE(BRCM_SDIO_VENDOR_ID_BROADCOM, dev_id)} | ||
983 | |||
982 | /* devices we support, null terminated */ | 984 | /* devices we support, null terminated */ |
983 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { | 985 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { |
984 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)}, | 986 | BRCMF_SDIO_DEVICE(BRCM_SDIO_43143_DEVICE_ID), |
985 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)}, | 987 | BRCMF_SDIO_DEVICE(BRCM_SDIO_43241_DEVICE_ID), |
986 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, | 988 | BRCMF_SDIO_DEVICE(BRCM_SDIO_4329_DEVICE_ID), |
987 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, | 989 | BRCMF_SDIO_DEVICE(BRCM_SDIO_4330_DEVICE_ID), |
988 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, | 990 | BRCMF_SDIO_DEVICE(BRCM_SDIO_4334_DEVICE_ID), |
989 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)}, | 991 | BRCMF_SDIO_DEVICE(BRCM_SDIO_43362_DEVICE_ID), |
990 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, | 992 | BRCMF_SDIO_DEVICE(BRCM_SDIO_4335_4339_DEVICE_ID), |
991 | SDIO_DEVICE_ID_BROADCOM_4335_4339)}, | 993 | BRCMF_SDIO_DEVICE(BRCM_SDIO_4354_DEVICE_ID), |
992 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4354)}, | 994 | { /* end: all zeroes */ } |
993 | { /* end: all zeroes */ }, | ||
994 | }; | 995 | }; |
995 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | 996 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); |
996 | 997 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index c7c9f15c0fe0..96800db0536b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c | |||
@@ -482,30 +482,30 @@ static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) | |||
482 | static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) | 482 | static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) |
483 | { | 483 | { |
484 | switch (ci->pub.chip) { | 484 | switch (ci->pub.chip) { |
485 | case BCM4329_CHIP_ID: | 485 | case BRCM_CC_4329_CHIP_ID: |
486 | ci->pub.ramsize = BCM4329_RAMSIZE; | 486 | ci->pub.ramsize = BCM4329_RAMSIZE; |
487 | break; | 487 | break; |
488 | case BCM43143_CHIP_ID: | 488 | case BRCM_CC_43143_CHIP_ID: |
489 | ci->pub.ramsize = BCM43143_RAMSIZE; | 489 | ci->pub.ramsize = BCM43143_RAMSIZE; |
490 | break; | 490 | break; |
491 | case BCM43241_CHIP_ID: | 491 | case BRCM_CC_43241_CHIP_ID: |
492 | ci->pub.ramsize = 0x90000; | 492 | ci->pub.ramsize = 0x90000; |
493 | break; | 493 | break; |
494 | case BCM4330_CHIP_ID: | 494 | case BRCM_CC_4330_CHIP_ID: |
495 | ci->pub.ramsize = 0x48000; | 495 | ci->pub.ramsize = 0x48000; |
496 | break; | 496 | break; |
497 | case BCM4334_CHIP_ID: | 497 | case BRCM_CC_4334_CHIP_ID: |
498 | ci->pub.ramsize = 0x80000; | 498 | ci->pub.ramsize = 0x80000; |
499 | break; | 499 | break; |
500 | case BCM4335_CHIP_ID: | 500 | case BRCM_CC_4335_CHIP_ID: |
501 | ci->pub.ramsize = 0xc0000; | 501 | ci->pub.ramsize = 0xc0000; |
502 | ci->pub.rambase = 0x180000; | 502 | ci->pub.rambase = 0x180000; |
503 | break; | 503 | break; |
504 | case BCM43362_CHIP_ID: | 504 | case BRCM_CC_43362_CHIP_ID: |
505 | ci->pub.ramsize = 0x3c000; | 505 | ci->pub.ramsize = 0x3c000; |
506 | break; | 506 | break; |
507 | case BCM4339_CHIP_ID: | 507 | case BRCM_CC_4339_CHIP_ID: |
508 | case BCM4354_CHIP_ID: | 508 | case BRCM_CC_4354_CHIP_ID: |
509 | ci->pub.ramsize = 0xc0000; | 509 | ci->pub.ramsize = 0xc0000; |
510 | ci->pub.rambase = 0x180000; | 510 | ci->pub.rambase = 0x180000; |
511 | break; | 511 | break; |
@@ -682,7 +682,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) | |||
682 | ci->pub.chiprev); | 682 | ci->pub.chiprev); |
683 | 683 | ||
684 | if (socitype == SOCI_SB) { | 684 | if (socitype == SOCI_SB) { |
685 | if (ci->pub.chip != BCM4329_CHIP_ID) { | 685 | if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) { |
686 | brcmf_err("SB chip is not supported\n"); | 686 | brcmf_err("SB chip is not supported\n"); |
687 | return -ENODEV; | 687 | return -ENODEV; |
688 | } | 688 | } |
@@ -1008,13 +1008,13 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) | |||
1008 | chip = container_of(pub, struct brcmf_chip_priv, pub); | 1008 | chip = container_of(pub, struct brcmf_chip_priv, pub); |
1009 | 1009 | ||
1010 | switch (pub->chip) { | 1010 | switch (pub->chip) { |
1011 | case BCM4354_CHIP_ID: | 1011 | case BRCM_CC_4354_CHIP_ID: |
1012 | /* explicitly check SR engine enable bit */ | 1012 | /* explicitly check SR engine enable bit */ |
1013 | pmu_cc3_mask = BIT(2); | 1013 | pmu_cc3_mask = BIT(2); |
1014 | /* fall-through */ | 1014 | /* fall-through */ |
1015 | case BCM43241_CHIP_ID: | 1015 | case BRCM_CC_43241_CHIP_ID: |
1016 | case BCM4335_CHIP_ID: | 1016 | case BRCM_CC_4335_CHIP_ID: |
1017 | case BCM4339_CHIP_ID: | 1017 | case BRCM_CC_4339_CHIP_ID: |
1018 | /* read PMU chipcontrol register 3 */ | 1018 | /* read PMU chipcontrol register 3 */ |
1019 | addr = CORE_CC_REG(base, chipcontrol_addr); | 1019 | addr = CORE_CC_REG(base, chipcontrol_addr); |
1020 | chip->ops->write32(chip->ctx, addr, 3); | 1020 | chip->ops->write32(chip->ctx, addr, 3); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index a8998eb60d22..7da6441bcfa8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -103,6 +103,10 @@ struct brcmf_pub { | |||
103 | 103 | ||
104 | struct brcmf_ampdu_rx_reorder | 104 | struct brcmf_ampdu_rx_reorder |
105 | *reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS]; | 105 | *reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS]; |
106 | |||
107 | u32 feat_flags; | ||
108 | u32 chip_quirks; | ||
109 | |||
106 | #ifdef DEBUG | 110 | #ifdef DEBUG |
107 | struct dentry *dbgfs_dir; | 111 | struct dentry *dbgfs_dir; |
108 | #endif | 112 | #endif |
@@ -175,7 +179,6 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, | |||
175 | void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); | 179 | void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); |
176 | void brcmf_txflowblock_if(struct brcmf_if *ifp, | 180 | void brcmf_txflowblock_if(struct brcmf_if *ifp, |
177 | enum brcmf_netif_stop_reason reason, bool state); | 181 | enum brcmf_netif_stop_reason reason, bool state); |
178 | u32 brcmf_get_chip_info(struct brcmf_if *ifp); | ||
179 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, | 182 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, |
180 | bool success); | 183 | bool success); |
181 | 184 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c index 03fe8aca4d32..be9f4f829192 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c | |||
@@ -41,37 +41,12 @@ void brcmf_debugfs_exit(void) | |||
41 | root_folder = NULL; | 41 | root_folder = NULL; |
42 | } | 42 | } |
43 | 43 | ||
44 | static | 44 | static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data) |
45 | ssize_t brcmf_debugfs_chipinfo_read(struct file *f, char __user *data, | ||
46 | size_t count, loff_t *ppos) | ||
47 | { | 45 | { |
48 | struct brcmf_pub *drvr = f->private_data; | 46 | struct brcmf_bus *bus = dev_get_drvdata(seq->private); |
49 | struct brcmf_bus *bus = drvr->bus_if; | ||
50 | char buf[40]; | ||
51 | int res; | ||
52 | |||
53 | /* only allow read from start */ | ||
54 | if (*ppos > 0) | ||
55 | return 0; | ||
56 | |||
57 | res = scnprintf(buf, sizeof(buf), "chip: %x(%u) rev %u\n", | ||
58 | bus->chip, bus->chip, bus->chiprev); | ||
59 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
60 | } | ||
61 | |||
62 | static const struct file_operations brcmf_debugfs_chipinfo_ops = { | ||
63 | .owner = THIS_MODULE, | ||
64 | .open = simple_open, | ||
65 | .read = brcmf_debugfs_chipinfo_read | ||
66 | }; | ||
67 | |||
68 | static int brcmf_debugfs_create_chipinfo(struct brcmf_pub *drvr) | ||
69 | { | ||
70 | struct dentry *dentry = drvr->dbgfs_dir; | ||
71 | 47 | ||
72 | if (!IS_ERR_OR_NULL(dentry)) | 48 | seq_printf(seq, "chip: %x(%u) rev %u\n", |
73 | debugfs_create_file("chipinfo", S_IRUGO, dentry, drvr, | 49 | bus->chip, bus->chip, bus->chiprev); |
74 | &brcmf_debugfs_chipinfo_ops); | ||
75 | return 0; | 50 | return 0; |
76 | } | 51 | } |
77 | 52 | ||
@@ -83,7 +58,8 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr) | |||
83 | return -ENODEV; | 58 | return -ENODEV; |
84 | 59 | ||
85 | drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); | 60 | drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); |
86 | brcmf_debugfs_create_chipinfo(drvr); | 61 | brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read); |
62 | |||
87 | return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); | 63 | return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); |
88 | } | 64 | } |
89 | 65 | ||
@@ -98,148 +74,44 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr) | |||
98 | return drvr->dbgfs_dir; | 74 | return drvr->dbgfs_dir; |
99 | } | 75 | } |
100 | 76 | ||
101 | static | 77 | struct brcmf_debugfs_entry { |
102 | ssize_t brcmf_debugfs_sdio_counter_read(struct file *f, char __user *data, | 78 | int (*read)(struct seq_file *seq, void *data); |
103 | size_t count, loff_t *ppos) | 79 | struct brcmf_pub *drvr; |
104 | { | ||
105 | struct brcmf_sdio_count *sdcnt = f->private_data; | ||
106 | char buf[750]; | ||
107 | int res; | ||
108 | |||
109 | /* only allow read from start */ | ||
110 | if (*ppos > 0) | ||
111 | return 0; | ||
112 | |||
113 | res = scnprintf(buf, sizeof(buf), | ||
114 | "intrcount: %u\nlastintrs: %u\n" | ||
115 | "pollcnt: %u\nregfails: %u\n" | ||
116 | "tx_sderrs: %u\nfcqueued: %u\n" | ||
117 | "rxrtx: %u\nrx_toolong: %u\n" | ||
118 | "rxc_errors: %u\nrx_hdrfail: %u\n" | ||
119 | "rx_badhdr: %u\nrx_badseq: %u\n" | ||
120 | "fc_rcvd: %u\nfc_xoff: %u\n" | ||
121 | "fc_xon: %u\nrxglomfail: %u\n" | ||
122 | "rxglomframes: %u\nrxglompkts: %u\n" | ||
123 | "f2rxhdrs: %u\nf2rxdata: %u\n" | ||
124 | "f2txdata: %u\nf1regdata: %u\n" | ||
125 | "tickcnt: %u\ntx_ctlerrs: %lu\n" | ||
126 | "tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n" | ||
127 | "rx_ctlpkts: %lu\nrx_readahead: %lu\n", | ||
128 | sdcnt->intrcount, sdcnt->lastintrs, | ||
129 | sdcnt->pollcnt, sdcnt->regfails, | ||
130 | sdcnt->tx_sderrs, sdcnt->fcqueued, | ||
131 | sdcnt->rxrtx, sdcnt->rx_toolong, | ||
132 | sdcnt->rxc_errors, sdcnt->rx_hdrfail, | ||
133 | sdcnt->rx_badhdr, sdcnt->rx_badseq, | ||
134 | sdcnt->fc_rcvd, sdcnt->fc_xoff, | ||
135 | sdcnt->fc_xon, sdcnt->rxglomfail, | ||
136 | sdcnt->rxglomframes, sdcnt->rxglompkts, | ||
137 | sdcnt->f2rxhdrs, sdcnt->f2rxdata, | ||
138 | sdcnt->f2txdata, sdcnt->f1regdata, | ||
139 | sdcnt->tickcnt, sdcnt->tx_ctlerrs, | ||
140 | sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs, | ||
141 | sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt); | ||
142 | |||
143 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
144 | } | ||
145 | |||
146 | static const struct file_operations brcmf_debugfs_sdio_counter_ops = { | ||
147 | .owner = THIS_MODULE, | ||
148 | .open = simple_open, | ||
149 | .read = brcmf_debugfs_sdio_counter_read | ||
150 | }; | 80 | }; |
151 | 81 | ||
152 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, | 82 | static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f) |
153 | struct brcmf_sdio_count *sdcnt) | ||
154 | { | 83 | { |
155 | struct dentry *dentry = drvr->dbgfs_dir; | 84 | struct brcmf_debugfs_entry *entry = inode->i_private; |
156 | 85 | ||
157 | if (!IS_ERR_OR_NULL(dentry)) | 86 | return single_open(f, entry->read, entry->drvr->bus_if->dev); |
158 | debugfs_create_file("counters", S_IRUGO, dentry, | ||
159 | sdcnt, &brcmf_debugfs_sdio_counter_ops); | ||
160 | } | ||
161 | |||
162 | static | ||
163 | ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data, | ||
164 | size_t count, loff_t *ppos) | ||
165 | { | ||
166 | struct brcmf_fws_stats *fwstats = f->private_data; | ||
167 | char buf[650]; | ||
168 | int res; | ||
169 | |||
170 | /* only allow read from start */ | ||
171 | if (*ppos > 0) | ||
172 | return 0; | ||
173 | |||
174 | res = scnprintf(buf, sizeof(buf), | ||
175 | "header_pulls: %u\n" | ||
176 | "header_only_pkt: %u\n" | ||
177 | "tlv_parse_failed: %u\n" | ||
178 | "tlv_invalid_type: %u\n" | ||
179 | "mac_update_fails: %u\n" | ||
180 | "ps_update_fails: %u\n" | ||
181 | "if_update_fails: %u\n" | ||
182 | "pkt2bus: %u\n" | ||
183 | "generic_error: %u\n" | ||
184 | "rollback_success: %u\n" | ||
185 | "rollback_failed: %u\n" | ||
186 | "delayq_full: %u\n" | ||
187 | "supprq_full: %u\n" | ||
188 | "txs_indicate: %u\n" | ||
189 | "txs_discard: %u\n" | ||
190 | "txs_suppr_core: %u\n" | ||
191 | "txs_suppr_ps: %u\n" | ||
192 | "txs_tossed: %u\n" | ||
193 | "txs_host_tossed: %u\n" | ||
194 | "bus_flow_block: %u\n" | ||
195 | "fws_flow_block: %u\n" | ||
196 | "send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n" | ||
197 | "requested_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n", | ||
198 | fwstats->header_pulls, | ||
199 | fwstats->header_only_pkt, | ||
200 | fwstats->tlv_parse_failed, | ||
201 | fwstats->tlv_invalid_type, | ||
202 | fwstats->mac_update_failed, | ||
203 | fwstats->mac_ps_update_failed, | ||
204 | fwstats->if_update_failed, | ||
205 | fwstats->pkt2bus, | ||
206 | fwstats->generic_error, | ||
207 | fwstats->rollback_success, | ||
208 | fwstats->rollback_failed, | ||
209 | fwstats->delayq_full_error, | ||
210 | fwstats->supprq_full_error, | ||
211 | fwstats->txs_indicate, | ||
212 | fwstats->txs_discard, | ||
213 | fwstats->txs_supp_core, | ||
214 | fwstats->txs_supp_ps, | ||
215 | fwstats->txs_tossed, | ||
216 | fwstats->txs_host_tossed, | ||
217 | fwstats->bus_flow_block, | ||
218 | fwstats->fws_flow_block, | ||
219 | fwstats->send_pkts[0], fwstats->send_pkts[1], | ||
220 | fwstats->send_pkts[2], fwstats->send_pkts[3], | ||
221 | fwstats->send_pkts[4], | ||
222 | fwstats->requested_sent[0], | ||
223 | fwstats->requested_sent[1], | ||
224 | fwstats->requested_sent[2], | ||
225 | fwstats->requested_sent[3], | ||
226 | fwstats->requested_sent[4]); | ||
227 | |||
228 | return simple_read_from_buffer(data, count, ppos, buf, res); | ||
229 | } | 87 | } |
230 | 88 | ||
231 | static const struct file_operations brcmf_debugfs_fws_stats_ops = { | 89 | static const struct file_operations brcmf_debugfs_def_ops = { |
232 | .owner = THIS_MODULE, | 90 | .owner = THIS_MODULE, |
233 | .open = simple_open, | 91 | .open = brcmf_debugfs_entry_open, |
234 | .read = brcmf_debugfs_fws_stats_read | 92 | .release = single_release, |
93 | .read = seq_read, | ||
94 | .llseek = seq_lseek | ||
235 | }; | 95 | }; |
236 | 96 | ||
237 | void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | 97 | int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, |
238 | struct brcmf_fws_stats *stats) | 98 | int (*read_fn)(struct seq_file *seq, void *data)) |
239 | { | 99 | { |
240 | struct dentry *dentry = drvr->dbgfs_dir; | 100 | struct dentry *dentry = drvr->dbgfs_dir; |
101 | struct brcmf_debugfs_entry *entry; | ||
102 | |||
103 | if (IS_ERR_OR_NULL(dentry)) | ||
104 | return -ENOENT; | ||
105 | |||
106 | entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL); | ||
107 | if (!entry) | ||
108 | return -ENOMEM; | ||
109 | |||
110 | entry->read = read_fn; | ||
111 | entry->drvr = drvr; | ||
112 | |||
113 | dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry, | ||
114 | &brcmf_debugfs_def_ops); | ||
241 | 115 | ||
242 | if (!IS_ERR_OR_NULL(dentry)) | 116 | return PTR_ERR_OR_ZERO(dentry); |
243 | debugfs_create_file("fws_stats", S_IRUGO, dentry, | ||
244 | stats, &brcmf_debugfs_fws_stats_ops); | ||
245 | } | 117 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index ef52ed7abc69..6eade7c60c63 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | |||
@@ -100,68 +100,6 @@ do { \ | |||
100 | 100 | ||
101 | extern int brcmf_msg_level; | 101 | extern int brcmf_msg_level; |
102 | 102 | ||
103 | /* | ||
104 | * hold counter variables used in brcmfmac sdio driver. | ||
105 | */ | ||
106 | struct brcmf_sdio_count { | ||
107 | uint intrcount; /* Count of device interrupt callbacks */ | ||
108 | uint lastintrs; /* Count as of last watchdog timer */ | ||
109 | uint pollcnt; /* Count of active polls */ | ||
110 | uint regfails; /* Count of R_REG failures */ | ||
111 | uint tx_sderrs; /* Count of tx attempts with sd errors */ | ||
112 | uint fcqueued; /* Tx packets that got queued */ | ||
113 | uint rxrtx; /* Count of rtx requests (NAK to dongle) */ | ||
114 | uint rx_toolong; /* Receive frames too long to receive */ | ||
115 | uint rxc_errors; /* SDIO errors when reading control frames */ | ||
116 | uint rx_hdrfail; /* SDIO errors on header reads */ | ||
117 | uint rx_badhdr; /* Bad received headers (roosync?) */ | ||
118 | uint rx_badseq; /* Mismatched rx sequence number */ | ||
119 | uint fc_rcvd; /* Number of flow-control events received */ | ||
120 | uint fc_xoff; /* Number which turned on flow-control */ | ||
121 | uint fc_xon; /* Number which turned off flow-control */ | ||
122 | uint rxglomfail; /* Failed deglom attempts */ | ||
123 | uint rxglomframes; /* Number of glom frames (superframes) */ | ||
124 | uint rxglompkts; /* Number of packets from glom frames */ | ||
125 | uint f2rxhdrs; /* Number of header reads */ | ||
126 | uint f2rxdata; /* Number of frame data reads */ | ||
127 | uint f2txdata; /* Number of f2 frame writes */ | ||
128 | uint f1regdata; /* Number of f1 register accesses */ | ||
129 | uint tickcnt; /* Number of watchdog been schedule */ | ||
130 | ulong tx_ctlerrs; /* Err of sending ctrl frames */ | ||
131 | ulong tx_ctlpkts; /* Ctrl frames sent to dongle */ | ||
132 | ulong rx_ctlerrs; /* Err of processing rx ctrl frames */ | ||
133 | ulong rx_ctlpkts; /* Ctrl frames processed from dongle */ | ||
134 | ulong rx_readahead_cnt; /* packets where header read-ahead was used */ | ||
135 | }; | ||
136 | |||
137 | struct brcmf_fws_stats { | ||
138 | u32 tlv_parse_failed; | ||
139 | u32 tlv_invalid_type; | ||
140 | u32 header_only_pkt; | ||
141 | u32 header_pulls; | ||
142 | u32 pkt2bus; | ||
143 | u32 send_pkts[5]; | ||
144 | u32 requested_sent[5]; | ||
145 | u32 generic_error; | ||
146 | u32 mac_update_failed; | ||
147 | u32 mac_ps_update_failed; | ||
148 | u32 if_update_failed; | ||
149 | u32 packet_request_failed; | ||
150 | u32 credit_request_failed; | ||
151 | u32 rollback_success; | ||
152 | u32 rollback_failed; | ||
153 | u32 delayq_full_error; | ||
154 | u32 supprq_full_error; | ||
155 | u32 txs_indicate; | ||
156 | u32 txs_discard; | ||
157 | u32 txs_supp_core; | ||
158 | u32 txs_supp_ps; | ||
159 | u32 txs_tossed; | ||
160 | u32 txs_host_tossed; | ||
161 | u32 bus_flow_block; | ||
162 | u32 fws_flow_block; | ||
163 | }; | ||
164 | |||
165 | struct brcmf_pub; | 103 | struct brcmf_pub; |
166 | #ifdef DEBUG | 104 | #ifdef DEBUG |
167 | void brcmf_debugfs_init(void); | 105 | void brcmf_debugfs_init(void); |
@@ -169,10 +107,8 @@ void brcmf_debugfs_exit(void); | |||
169 | int brcmf_debugfs_attach(struct brcmf_pub *drvr); | 107 | int brcmf_debugfs_attach(struct brcmf_pub *drvr); |
170 | void brcmf_debugfs_detach(struct brcmf_pub *drvr); | 108 | void brcmf_debugfs_detach(struct brcmf_pub *drvr); |
171 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); | 109 | struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); |
172 | void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, | 110 | int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, |
173 | struct brcmf_sdio_count *sdcnt); | 111 | int (*read_fn)(struct seq_file *seq, void *data)); |
174 | void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | ||
175 | struct brcmf_fws_stats *stats); | ||
176 | #else | 112 | #else |
177 | static inline void brcmf_debugfs_init(void) | 113 | static inline void brcmf_debugfs_init(void) |
178 | { | 114 | { |
@@ -187,9 +123,11 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr) | |||
187 | static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) | 123 | static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) |
188 | { | 124 | { |
189 | } | 125 | } |
190 | static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, | 126 | static inline |
191 | struct brcmf_fws_stats *stats) | 127 | int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, |
128 | int (*read_fn)(struct seq_file *seq, void *data)) | ||
192 | { | 129 | { |
130 | return 0; | ||
193 | } | 131 | } |
194 | #endif | 132 | #endif |
195 | 133 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 2699441d4f41..347b4260f45b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "wl_cfg80211.h" | 30 | #include "wl_cfg80211.h" |
31 | #include "fwil.h" | 31 | #include "fwil.h" |
32 | #include "fwsignal.h" | 32 | #include "fwsignal.h" |
33 | #include "feature.h" | ||
33 | #include "proto.h" | 34 | #include "proto.h" |
34 | 35 | ||
35 | MODULE_AUTHOR("Broadcom Corporation"); | 36 | MODULE_AUTHOR("Broadcom Corporation"); |
@@ -937,6 +938,8 @@ int brcmf_bus_start(struct device *dev) | |||
937 | if (ret < 0) | 938 | if (ret < 0) |
938 | goto fail; | 939 | goto fail; |
939 | 940 | ||
941 | brcmf_feat_attach(drvr); | ||
942 | |||
940 | ret = brcmf_fws_init(drvr); | 943 | ret = brcmf_fws_init(drvr); |
941 | if (ret < 0) | 944 | if (ret < 0) |
942 | goto fail; | 945 | goto fail; |
@@ -1074,16 +1077,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev) | |||
1074 | return !err; | 1077 | return !err; |
1075 | } | 1078 | } |
1076 | 1079 | ||
1077 | /* | ||
1078 | * return chip id and rev of the device encoded in u32. | ||
1079 | */ | ||
1080 | u32 brcmf_get_chip_info(struct brcmf_if *ifp) | ||
1081 | { | ||
1082 | struct brcmf_bus *bus = ifp->drvr->bus_if; | ||
1083 | |||
1084 | return bus->chip << 4 | bus->chiprev; | ||
1085 | } | ||
1086 | |||
1087 | static void brcmf_driver_register(struct work_struct *work) | 1080 | static void brcmf_driver_register(struct work_struct *work) |
1088 | { | 1081 | { |
1089 | #ifdef CONFIG_BRCMFMAC_SDIO | 1082 | #ifdef CONFIG_BRCMFMAC_SDIO |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 8fa0dbbbda72..67d91d5cc13d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -391,6 +391,40 @@ struct brcmf_sdio_hdrinfo { | |||
391 | u16 tail_pad; | 391 | u16 tail_pad; |
392 | }; | 392 | }; |
393 | 393 | ||
394 | /* | ||
395 | * hold counter variables | ||
396 | */ | ||
397 | struct brcmf_sdio_count { | ||
398 | uint intrcount; /* Count of device interrupt callbacks */ | ||
399 | uint lastintrs; /* Count as of last watchdog timer */ | ||
400 | uint pollcnt; /* Count of active polls */ | ||
401 | uint regfails; /* Count of R_REG failures */ | ||
402 | uint tx_sderrs; /* Count of tx attempts with sd errors */ | ||
403 | uint fcqueued; /* Tx packets that got queued */ | ||
404 | uint rxrtx; /* Count of rtx requests (NAK to dongle) */ | ||
405 | uint rx_toolong; /* Receive frames too long to receive */ | ||
406 | uint rxc_errors; /* SDIO errors when reading control frames */ | ||
407 | uint rx_hdrfail; /* SDIO errors on header reads */ | ||
408 | uint rx_badhdr; /* Bad received headers (roosync?) */ | ||
409 | uint rx_badseq; /* Mismatched rx sequence number */ | ||
410 | uint fc_rcvd; /* Number of flow-control events received */ | ||
411 | uint fc_xoff; /* Number which turned on flow-control */ | ||
412 | uint fc_xon; /* Number which turned off flow-control */ | ||
413 | uint rxglomfail; /* Failed deglom attempts */ | ||
414 | uint rxglomframes; /* Number of glom frames (superframes) */ | ||
415 | uint rxglompkts; /* Number of packets from glom frames */ | ||
416 | uint f2rxhdrs; /* Number of header reads */ | ||
417 | uint f2rxdata; /* Number of frame data reads */ | ||
418 | uint f2txdata; /* Number of f2 frame writes */ | ||
419 | uint f1regdata; /* Number of f1 register accesses */ | ||
420 | uint tickcnt; /* Number of watchdog been schedule */ | ||
421 | ulong tx_ctlerrs; /* Err of sending ctrl frames */ | ||
422 | ulong tx_ctlpkts; /* Ctrl frames sent to dongle */ | ||
423 | ulong rx_ctlerrs; /* Err of processing rx ctrl frames */ | ||
424 | ulong rx_ctlpkts; /* Ctrl frames processed from dongle */ | ||
425 | ulong rx_readahead_cnt; /* packets where header read-ahead was used */ | ||
426 | }; | ||
427 | |||
394 | /* misc chip info needed by some of the routines */ | 428 | /* misc chip info needed by some of the routines */ |
395 | /* Private data for SDIO bus interaction */ | 429 | /* Private data for SDIO bus interaction */ |
396 | struct brcmf_sdio { | 430 | struct brcmf_sdio { |
@@ -620,40 +654,46 @@ enum brcmf_firmware_type { | |||
620 | name ## _FIRMWARE_NAME, name ## _NVRAM_NAME | 654 | name ## _FIRMWARE_NAME, name ## _NVRAM_NAME |
621 | 655 | ||
622 | static const struct brcmf_firmware_names brcmf_fwname_data[] = { | 656 | static const struct brcmf_firmware_names brcmf_fwname_data[] = { |
623 | { BCM43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) }, | 657 | { BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) }, |
624 | { BCM43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) }, | 658 | { BRCM_CC_43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) }, |
625 | { BCM43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) }, | 659 | { BRCM_CC_43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) }, |
626 | { BCM4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) }, | 660 | { BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) }, |
627 | { BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, | 661 | { BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, |
628 | { BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, | 662 | { BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, |
629 | { BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, | 663 | { BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, |
630 | { BCM43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, | 664 | { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, |
631 | { BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, | 665 | { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, |
632 | { BCM4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } | 666 | { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } |
633 | }; | 667 | }; |
634 | 668 | ||
635 | static const char *brcmf_sdio_get_fwname(struct brcmf_chip *ci, | 669 | static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci, |
636 | enum brcmf_firmware_type type) | 670 | struct brcmf_sdio_dev *sdiodev) |
637 | { | 671 | { |
638 | int i; | 672 | int i; |
639 | 673 | ||
640 | for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) { | 674 | for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) { |
641 | if (brcmf_fwname_data[i].chipid == ci->chip && | 675 | if (brcmf_fwname_data[i].chipid == ci->chip && |
642 | brcmf_fwname_data[i].revmsk & BIT(ci->chiprev)) { | 676 | brcmf_fwname_data[i].revmsk & BIT(ci->chiprev)) |
643 | switch (type) { | 677 | break; |
644 | case BRCMF_FIRMWARE_BIN: | ||
645 | return brcmf_fwname_data[i].bin; | ||
646 | case BRCMF_FIRMWARE_NVRAM: | ||
647 | return brcmf_fwname_data[i].nv; | ||
648 | default: | ||
649 | brcmf_err("invalid firmware type (%d)\n", type); | ||
650 | return NULL; | ||
651 | } | ||
652 | } | ||
653 | } | 678 | } |
654 | brcmf_err("Unknown chipid %d [%d]\n", | 679 | |
655 | ci->chip, ci->chiprev); | 680 | if (i == ARRAY_SIZE(brcmf_fwname_data)) { |
656 | return NULL; | 681 | brcmf_err("Unknown chipid %d [%d]\n", ci->chip, ci->chiprev); |
682 | return -ENODEV; | ||
683 | } | ||
684 | |||
685 | /* check if firmware path is provided by module parameter */ | ||
686 | if (brcmf_firmware_path[0] != '\0') { | ||
687 | if (brcmf_firmware_path[strlen(brcmf_firmware_path) - 1] != '/') | ||
688 | strcat(brcmf_firmware_path, "/"); | ||
689 | |||
690 | strcpy(sdiodev->fw_name, brcmf_firmware_path); | ||
691 | strcpy(sdiodev->nvram_name, brcmf_firmware_path); | ||
692 | } | ||
693 | strcat(sdiodev->fw_name, brcmf_fwname_data[i].bin); | ||
694 | strcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv); | ||
695 | |||
696 | return 0; | ||
657 | } | 697 | } |
658 | 698 | ||
659 | static void pkt_align(struct sk_buff *p, int len, int align) | 699 | static void pkt_align(struct sk_buff *p, int len, int align) |
@@ -2898,16 +2938,13 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) | |||
2898 | } | 2938 | } |
2899 | 2939 | ||
2900 | #ifdef DEBUG | 2940 | #ifdef DEBUG |
2901 | static int brcmf_sdio_dump_console(struct brcmf_sdio *bus, | 2941 | static int brcmf_sdio_dump_console(struct seq_file *seq, struct brcmf_sdio *bus, |
2902 | struct sdpcm_shared *sh, char __user *data, | 2942 | struct sdpcm_shared *sh) |
2903 | size_t count) | ||
2904 | { | 2943 | { |
2905 | u32 addr, console_ptr, console_size, console_index; | 2944 | u32 addr, console_ptr, console_size, console_index; |
2906 | char *conbuf = NULL; | 2945 | char *conbuf = NULL; |
2907 | __le32 sh_val; | 2946 | __le32 sh_val; |
2908 | int rv; | 2947 | int rv; |
2909 | loff_t pos = 0; | ||
2910 | int nbytes = 0; | ||
2911 | 2948 | ||
2912 | /* obtain console information from device memory */ | 2949 | /* obtain console information from device memory */ |
2913 | addr = sh->console_addr + offsetof(struct rte_console, log_le); | 2950 | addr = sh->console_addr + offsetof(struct rte_console, log_le); |
@@ -2945,33 +2982,24 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus, | |||
2945 | if (rv < 0) | 2982 | if (rv < 0) |
2946 | goto done; | 2983 | goto done; |
2947 | 2984 | ||
2948 | rv = simple_read_from_buffer(data, count, &pos, | 2985 | rv = seq_write(seq, conbuf + console_index, |
2949 | conbuf + console_index, | 2986 | console_size - console_index); |
2950 | console_size - console_index); | ||
2951 | if (rv < 0) | 2987 | if (rv < 0) |
2952 | goto done; | 2988 | goto done; |
2953 | 2989 | ||
2954 | nbytes = rv; | 2990 | if (console_index > 0) |
2955 | if (console_index > 0) { | 2991 | rv = seq_write(seq, conbuf, console_index - 1); |
2956 | pos = 0; | 2992 | |
2957 | rv = simple_read_from_buffer(data+nbytes, count, &pos, | ||
2958 | conbuf, console_index - 1); | ||
2959 | if (rv < 0) | ||
2960 | goto done; | ||
2961 | rv += nbytes; | ||
2962 | } | ||
2963 | done: | 2993 | done: |
2964 | vfree(conbuf); | 2994 | vfree(conbuf); |
2965 | return rv; | 2995 | return rv; |
2966 | } | 2996 | } |
2967 | 2997 | ||
2968 | static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, | 2998 | static int brcmf_sdio_trap_info(struct seq_file *seq, struct brcmf_sdio *bus, |
2969 | char __user *data, size_t count) | 2999 | struct sdpcm_shared *sh) |
2970 | { | 3000 | { |
2971 | int error, res; | 3001 | int error; |
2972 | char buf[350]; | ||
2973 | struct brcmf_trap_info tr; | 3002 | struct brcmf_trap_info tr; |
2974 | loff_t pos = 0; | ||
2975 | 3003 | ||
2976 | if ((sh->flags & SDPCM_SHARED_TRAP) == 0) { | 3004 | if ((sh->flags & SDPCM_SHARED_TRAP) == 0) { |
2977 | brcmf_dbg(INFO, "no trap in firmware\n"); | 3005 | brcmf_dbg(INFO, "no trap in firmware\n"); |
@@ -2983,34 +3011,30 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, | |||
2983 | if (error < 0) | 3011 | if (error < 0) |
2984 | return error; | 3012 | return error; |
2985 | 3013 | ||
2986 | res = scnprintf(buf, sizeof(buf), | 3014 | seq_printf(seq, |
2987 | "dongle trap info: type 0x%x @ epc 0x%08x\n" | 3015 | "dongle trap info: type 0x%x @ epc 0x%08x\n" |
2988 | " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" | 3016 | " cpsr 0x%08x spsr 0x%08x sp 0x%08x\n" |
2989 | " lr 0x%08x pc 0x%08x offset 0x%x\n" | 3017 | " lr 0x%08x pc 0x%08x offset 0x%x\n" |
2990 | " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n" | 3018 | " r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n" |
2991 | " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", | 3019 | " r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n", |
2992 | le32_to_cpu(tr.type), le32_to_cpu(tr.epc), | 3020 | le32_to_cpu(tr.type), le32_to_cpu(tr.epc), |
2993 | le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr), | 3021 | le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr), |
2994 | le32_to_cpu(tr.r13), le32_to_cpu(tr.r14), | 3022 | le32_to_cpu(tr.r13), le32_to_cpu(tr.r14), |
2995 | le32_to_cpu(tr.pc), sh->trap_addr, | 3023 | le32_to_cpu(tr.pc), sh->trap_addr, |
2996 | le32_to_cpu(tr.r0), le32_to_cpu(tr.r1), | 3024 | le32_to_cpu(tr.r0), le32_to_cpu(tr.r1), |
2997 | le32_to_cpu(tr.r2), le32_to_cpu(tr.r3), | 3025 | le32_to_cpu(tr.r2), le32_to_cpu(tr.r3), |
2998 | le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), | 3026 | le32_to_cpu(tr.r4), le32_to_cpu(tr.r5), |
2999 | le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); | 3027 | le32_to_cpu(tr.r6), le32_to_cpu(tr.r7)); |
3000 | 3028 | ||
3001 | return simple_read_from_buffer(data, count, &pos, buf, res); | 3029 | return 0; |
3002 | } | 3030 | } |
3003 | 3031 | ||
3004 | static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, | 3032 | static int brcmf_sdio_assert_info(struct seq_file *seq, struct brcmf_sdio *bus, |
3005 | struct sdpcm_shared *sh, char __user *data, | 3033 | struct sdpcm_shared *sh) |
3006 | size_t count) | ||
3007 | { | 3034 | { |
3008 | int error = 0; | 3035 | int error = 0; |
3009 | char buf[200]; | ||
3010 | char file[80] = "?"; | 3036 | char file[80] = "?"; |
3011 | char expr[80] = "<???>"; | 3037 | char expr[80] = "<???>"; |
3012 | int res; | ||
3013 | loff_t pos = 0; | ||
3014 | 3038 | ||
3015 | if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { | 3039 | if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { |
3016 | brcmf_dbg(INFO, "firmware not built with -assert\n"); | 3040 | brcmf_dbg(INFO, "firmware not built with -assert\n"); |
@@ -3035,10 +3059,9 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus, | |||
3035 | } | 3059 | } |
3036 | sdio_release_host(bus->sdiodev->func[1]); | 3060 | sdio_release_host(bus->sdiodev->func[1]); |
3037 | 3061 | ||
3038 | res = scnprintf(buf, sizeof(buf), | 3062 | seq_printf(seq, "dongle assert: %s:%d: assert(%s)\n", |
3039 | "dongle assert: %s:%d: assert(%s)\n", | 3063 | file, sh->assert_line, expr); |
3040 | file, sh->assert_line, expr); | 3064 | return 0; |
3041 | return simple_read_from_buffer(data, count, &pos, buf, res); | ||
3042 | } | 3065 | } |
3043 | 3066 | ||
3044 | static int brcmf_sdio_checkdied(struct brcmf_sdio *bus) | 3067 | static int brcmf_sdio_checkdied(struct brcmf_sdio *bus) |
@@ -3062,59 +3085,75 @@ static int brcmf_sdio_checkdied(struct brcmf_sdio *bus) | |||
3062 | return 0; | 3085 | return 0; |
3063 | } | 3086 | } |
3064 | 3087 | ||
3065 | static int brcmf_sdio_died_dump(struct brcmf_sdio *bus, char __user *data, | 3088 | static int brcmf_sdio_died_dump(struct seq_file *seq, struct brcmf_sdio *bus) |
3066 | size_t count, loff_t *ppos) | ||
3067 | { | 3089 | { |
3068 | int error = 0; | 3090 | int error = 0; |
3069 | struct sdpcm_shared sh; | 3091 | struct sdpcm_shared sh; |
3070 | int nbytes = 0; | ||
3071 | loff_t pos = *ppos; | ||
3072 | |||
3073 | if (pos != 0) | ||
3074 | return 0; | ||
3075 | 3092 | ||
3076 | error = brcmf_sdio_readshared(bus, &sh); | 3093 | error = brcmf_sdio_readshared(bus, &sh); |
3077 | if (error < 0) | 3094 | if (error < 0) |
3078 | goto done; | 3095 | goto done; |
3079 | 3096 | ||
3080 | error = brcmf_sdio_assert_info(bus, &sh, data, count); | 3097 | error = brcmf_sdio_assert_info(seq, bus, &sh); |
3081 | if (error < 0) | 3098 | if (error < 0) |
3082 | goto done; | 3099 | goto done; |
3083 | nbytes = error; | ||
3084 | 3100 | ||
3085 | error = brcmf_sdio_trap_info(bus, &sh, data+nbytes, count); | 3101 | error = brcmf_sdio_trap_info(seq, bus, &sh); |
3086 | if (error < 0) | 3102 | if (error < 0) |
3087 | goto done; | 3103 | goto done; |
3088 | nbytes += error; | ||
3089 | 3104 | ||
3090 | error = brcmf_sdio_dump_console(bus, &sh, data+nbytes, count); | 3105 | error = brcmf_sdio_dump_console(seq, bus, &sh); |
3091 | if (error < 0) | ||
3092 | goto done; | ||
3093 | nbytes += error; | ||
3094 | 3106 | ||
3095 | error = nbytes; | ||
3096 | *ppos += nbytes; | ||
3097 | done: | 3107 | done: |
3098 | return error; | 3108 | return error; |
3099 | } | 3109 | } |
3100 | 3110 | ||
3101 | static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data, | 3111 | static int brcmf_sdio_forensic_read(struct seq_file *seq, void *data) |
3102 | size_t count, loff_t *ppos) | ||
3103 | { | 3112 | { |
3104 | struct brcmf_sdio *bus = f->private_data; | 3113 | struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); |
3105 | int res; | 3114 | struct brcmf_sdio *bus = bus_if->bus_priv.sdio->bus; |
3106 | 3115 | ||
3107 | res = brcmf_sdio_died_dump(bus, data, count, ppos); | 3116 | return brcmf_sdio_died_dump(seq, bus); |
3108 | if (res > 0) | ||
3109 | *ppos += res; | ||
3110 | return (ssize_t)res; | ||
3111 | } | 3117 | } |
3112 | 3118 | ||
3113 | static const struct file_operations brcmf_sdio_forensic_ops = { | 3119 | static int brcmf_debugfs_sdio_count_read(struct seq_file *seq, void *data) |
3114 | .owner = THIS_MODULE, | 3120 | { |
3115 | .open = simple_open, | 3121 | struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); |
3116 | .read = brcmf_sdio_forensic_read | 3122 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
3117 | }; | 3123 | struct brcmf_sdio_count *sdcnt = &sdiodev->bus->sdcnt; |
3124 | |||
3125 | seq_printf(seq, | ||
3126 | "intrcount: %u\nlastintrs: %u\n" | ||
3127 | "pollcnt: %u\nregfails: %u\n" | ||
3128 | "tx_sderrs: %u\nfcqueued: %u\n" | ||
3129 | "rxrtx: %u\nrx_toolong: %u\n" | ||
3130 | "rxc_errors: %u\nrx_hdrfail: %u\n" | ||
3131 | "rx_badhdr: %u\nrx_badseq: %u\n" | ||
3132 | "fc_rcvd: %u\nfc_xoff: %u\n" | ||
3133 | "fc_xon: %u\nrxglomfail: %u\n" | ||
3134 | "rxglomframes: %u\nrxglompkts: %u\n" | ||
3135 | "f2rxhdrs: %u\nf2rxdata: %u\n" | ||
3136 | "f2txdata: %u\nf1regdata: %u\n" | ||
3137 | "tickcnt: %u\ntx_ctlerrs: %lu\n" | ||
3138 | "tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n" | ||
3139 | "rx_ctlpkts: %lu\nrx_readahead: %lu\n", | ||
3140 | sdcnt->intrcount, sdcnt->lastintrs, | ||
3141 | sdcnt->pollcnt, sdcnt->regfails, | ||
3142 | sdcnt->tx_sderrs, sdcnt->fcqueued, | ||
3143 | sdcnt->rxrtx, sdcnt->rx_toolong, | ||
3144 | sdcnt->rxc_errors, sdcnt->rx_hdrfail, | ||
3145 | sdcnt->rx_badhdr, sdcnt->rx_badseq, | ||
3146 | sdcnt->fc_rcvd, sdcnt->fc_xoff, | ||
3147 | sdcnt->fc_xon, sdcnt->rxglomfail, | ||
3148 | sdcnt->rxglomframes, sdcnt->rxglompkts, | ||
3149 | sdcnt->f2rxhdrs, sdcnt->f2rxdata, | ||
3150 | sdcnt->f2txdata, sdcnt->f1regdata, | ||
3151 | sdcnt->tickcnt, sdcnt->tx_ctlerrs, | ||
3152 | sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs, | ||
3153 | sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt); | ||
3154 | |||
3155 | return 0; | ||
3156 | } | ||
3118 | 3157 | ||
3119 | static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) | 3158 | static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) |
3120 | { | 3159 | { |
@@ -3124,9 +3163,9 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) | |||
3124 | if (IS_ERR_OR_NULL(dentry)) | 3163 | if (IS_ERR_OR_NULL(dentry)) |
3125 | return; | 3164 | return; |
3126 | 3165 | ||
3127 | debugfs_create_file("forensics", S_IRUGO, dentry, bus, | 3166 | brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read); |
3128 | &brcmf_sdio_forensic_ops); | 3167 | brcmf_debugfs_add_entry(drvr, "counters", |
3129 | brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt); | 3168 | brcmf_debugfs_sdio_count_read); |
3130 | debugfs_create_u32("console_interval", 0644, dentry, | 3169 | debugfs_create_u32("console_interval", 0644, dentry, |
3131 | &bus->console_interval); | 3170 | &bus->console_interval); |
3132 | } | 3171 | } |
@@ -3598,17 +3637,17 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
3598 | return; | 3637 | return; |
3599 | 3638 | ||
3600 | switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { | 3639 | switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) { |
3601 | case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): | 3640 | case SDIOD_DRVSTR_KEY(BRCM_CC_4330_CHIP_ID, 12): |
3602 | str_tab = sdiod_drvstr_tab1_1v8; | 3641 | str_tab = sdiod_drvstr_tab1_1v8; |
3603 | str_mask = 0x00003800; | 3642 | str_mask = 0x00003800; |
3604 | str_shift = 11; | 3643 | str_shift = 11; |
3605 | break; | 3644 | break; |
3606 | case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17): | 3645 | case SDIOD_DRVSTR_KEY(BRCM_CC_4334_CHIP_ID, 17): |
3607 | str_tab = sdiod_drvstr_tab6_1v8; | 3646 | str_tab = sdiod_drvstr_tab6_1v8; |
3608 | str_mask = 0x00001800; | 3647 | str_mask = 0x00001800; |
3609 | str_shift = 11; | 3648 | str_shift = 11; |
3610 | break; | 3649 | break; |
3611 | case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17): | 3650 | case SDIOD_DRVSTR_KEY(BRCM_CC_43143_CHIP_ID, 17): |
3612 | /* note: 43143 does not support tristate */ | 3651 | /* note: 43143 does not support tristate */ |
3613 | i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1; | 3652 | i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1; |
3614 | if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) { | 3653 | if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) { |
@@ -3619,7 +3658,7 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
3619 | brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n", | 3658 | brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n", |
3620 | ci->name, drivestrength); | 3659 | ci->name, drivestrength); |
3621 | break; | 3660 | break; |
3622 | case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13): | 3661 | case SDIOD_DRVSTR_KEY(BRCM_CC_43362_CHIP_ID, 13): |
3623 | str_tab = sdiod_drive_strength_tab5_1v8; | 3662 | str_tab = sdiod_drive_strength_tab5_1v8; |
3624 | str_mask = 0x00003800; | 3663 | str_mask = 0x00003800; |
3625 | str_shift = 11; | 3664 | str_shift = 11; |
@@ -3720,12 +3759,12 @@ static u32 brcmf_sdio_buscore_read32(void *ctx, u32 addr) | |||
3720 | u32 val, rev; | 3759 | u32 val, rev; |
3721 | 3760 | ||
3722 | val = brcmf_sdiod_regrl(sdiodev, addr, NULL); | 3761 | val = brcmf_sdiod_regrl(sdiodev, addr, NULL); |
3723 | if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 && | 3762 | if (sdiodev->func[0]->device == BRCM_SDIO_4335_4339_DEVICE_ID && |
3724 | addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) { | 3763 | addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) { |
3725 | rev = (val & CID_REV_MASK) >> CID_REV_SHIFT; | 3764 | rev = (val & CID_REV_MASK) >> CID_REV_SHIFT; |
3726 | if (rev >= 2) { | 3765 | if (rev >= 2) { |
3727 | val &= ~CID_ID_MASK; | 3766 | val &= ~CID_ID_MASK; |
3728 | val |= BCM4339_CHIP_ID; | 3767 | val |= BRCM_CC_4339_CHIP_ID; |
3729 | } | 3768 | } |
3730 | } | 3769 | } |
3731 | return val; | 3770 | return val; |
@@ -4127,11 +4166,12 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4127 | brcmf_sdio_debugfs_create(bus); | 4166 | brcmf_sdio_debugfs_create(bus); |
4128 | brcmf_dbg(INFO, "completed!!\n"); | 4167 | brcmf_dbg(INFO, "completed!!\n"); |
4129 | 4168 | ||
4169 | ret = brcmf_sdio_get_fwnames(bus->ci, sdiodev); | ||
4170 | if (ret) | ||
4171 | goto fail; | ||
4172 | |||
4130 | ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM, | 4173 | ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM, |
4131 | brcmf_sdio_get_fwname(bus->ci, | 4174 | sdiodev->fw_name, sdiodev->nvram_name, |
4132 | BRCMF_FIRMWARE_BIN), | ||
4133 | brcmf_sdio_get_fwname(bus->ci, | ||
4134 | BRCMF_FIRMWARE_NVRAM), | ||
4135 | brcmf_sdio_firmware_callback); | 4175 | brcmf_sdio_firmware_callback); |
4136 | if (ret != 0) { | 4176 | if (ret != 0) { |
4137 | brcmf_err("async firmware request failed: %d\n", ret); | 4177 | brcmf_err("async firmware request failed: %d\n", ret); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c new file mode 100644 index 000000000000..50877e3c5d2f --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 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 | |||
17 | #include <linux/netdevice.h> | ||
18 | |||
19 | #include <brcm_hw_ids.h> | ||
20 | #include "dhd.h" | ||
21 | #include "dhd_bus.h" | ||
22 | #include "dhd_dbg.h" | ||
23 | #include "fwil.h" | ||
24 | #include "feature.h" | ||
25 | |||
26 | /* | ||
27 | * firmware error code received if iovar is unsupported. | ||
28 | */ | ||
29 | #define EBRCMF_FEAT_UNSUPPORTED 23 | ||
30 | |||
31 | /* | ||
32 | * expand feature list to array of feature strings. | ||
33 | */ | ||
34 | #define BRCMF_FEAT_DEF(_f) \ | ||
35 | #_f, | ||
36 | static const char *brcmf_feat_names[] = { | ||
37 | BRCMF_FEAT_LIST | ||
38 | }; | ||
39 | #undef BRCMF_FEAT_DEF | ||
40 | |||
41 | #ifdef DEBUG | ||
42 | /* | ||
43 | * expand quirk list to array of quirk strings. | ||
44 | */ | ||
45 | #define BRCMF_QUIRK_DEF(_q) \ | ||
46 | #_q, | ||
47 | static const char * const brcmf_quirk_names[] = { | ||
48 | BRCMF_QUIRK_LIST | ||
49 | }; | ||
50 | #undef BRCMF_QUIRK_DEF | ||
51 | |||
52 | /** | ||
53 | * brcmf_feat_debugfs_read() - expose feature info to debugfs. | ||
54 | * | ||
55 | * @seq: sequence for debugfs entry. | ||
56 | * @data: raw data pointer. | ||
57 | */ | ||
58 | static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data) | ||
59 | { | ||
60 | struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); | ||
61 | u32 feats = bus_if->drvr->feat_flags; | ||
62 | u32 quirks = bus_if->drvr->chip_quirks; | ||
63 | int id; | ||
64 | |||
65 | seq_printf(seq, "Features: %08x\n", feats); | ||
66 | for (id = 0; id < BRCMF_FEAT_LAST; id++) | ||
67 | if (feats & BIT(id)) | ||
68 | seq_printf(seq, "\t%s\n", brcmf_feat_names[id]); | ||
69 | seq_printf(seq, "\nQuirks: %08x\n", quirks); | ||
70 | for (id = 0; id < BRCMF_FEAT_QUIRK_LAST; id++) | ||
71 | if (quirks & BIT(id)) | ||
72 | seq_printf(seq, "\t%s\n", brcmf_quirk_names[id]); | ||
73 | return 0; | ||
74 | } | ||
75 | #else | ||
76 | static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data) | ||
77 | { | ||
78 | return 0; | ||
79 | } | ||
80 | #endif /* DEBUG */ | ||
81 | |||
82 | /** | ||
83 | * brcmf_feat_iovar_int_get() - determine feature through iovar query. | ||
84 | * | ||
85 | * @ifp: interface to query. | ||
86 | * @id: feature id. | ||
87 | * @name: iovar name. | ||
88 | */ | ||
89 | static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp, | ||
90 | enum brcmf_feat_id id, char *name) | ||
91 | { | ||
92 | u32 data; | ||
93 | int err; | ||
94 | |||
95 | err = brcmf_fil_iovar_int_get(ifp, name, &data); | ||
96 | if (err == 0) { | ||
97 | brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]); | ||
98 | ifp->drvr->feat_flags |= BIT(id); | ||
99 | } else { | ||
100 | brcmf_dbg(TRACE, "%s feature check failed: %d\n", | ||
101 | brcmf_feat_names[id], err); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | void brcmf_feat_attach(struct brcmf_pub *drvr) | ||
106 | { | ||
107 | struct brcmf_if *ifp = drvr->iflist[0]; | ||
108 | |||
109 | brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan"); | ||
110 | |||
111 | /* set chip related quirks */ | ||
112 | switch (drvr->bus_if->chip) { | ||
113 | case BRCM_CC_43236_CHIP_ID: | ||
114 | drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_AUTO_AUTH); | ||
115 | break; | ||
116 | case BRCM_CC_4329_CHIP_ID: | ||
117 | drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_NEED_MPC); | ||
118 | break; | ||
119 | default: | ||
120 | /* no quirks */ | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read); | ||
125 | } | ||
126 | |||
127 | bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id) | ||
128 | { | ||
129 | return (ifp->drvr->feat_flags & BIT(id)); | ||
130 | } | ||
131 | |||
132 | bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp, | ||
133 | enum brcmf_feat_quirk quirk) | ||
134 | { | ||
135 | return (ifp->drvr->chip_quirks & BIT(quirk)); | ||
136 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/brcm80211/brcmfmac/feature.h new file mode 100644 index 000000000000..961d175f8afb --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 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 | #ifndef _BRCMF_FEATURE_H | ||
17 | #define _BRCMF_FEATURE_H | ||
18 | |||
19 | /* | ||
20 | * Features: | ||
21 | * | ||
22 | * MCHAN: multi-channel for concurrent P2P. | ||
23 | */ | ||
24 | #define BRCMF_FEAT_LIST \ | ||
25 | BRCMF_FEAT_DEF(MCHAN) | ||
26 | /* | ||
27 | * Quirks: | ||
28 | * | ||
29 | * AUTO_AUTH: workaround needed for automatic authentication type. | ||
30 | * NEED_MPC: driver needs to disable MPC during scanning operation. | ||
31 | */ | ||
32 | #define BRCMF_QUIRK_LIST \ | ||
33 | BRCMF_QUIRK_DEF(AUTO_AUTH) \ | ||
34 | BRCMF_QUIRK_DEF(NEED_MPC) | ||
35 | |||
36 | #define BRCMF_FEAT_DEF(_f) \ | ||
37 | BRCMF_FEAT_ ## _f, | ||
38 | /* | ||
39 | * expand feature list to enumeration. | ||
40 | */ | ||
41 | enum brcmf_feat_id { | ||
42 | BRCMF_FEAT_LIST | ||
43 | BRCMF_FEAT_LAST | ||
44 | }; | ||
45 | #undef BRCMF_FEAT_DEF | ||
46 | |||
47 | #define BRCMF_QUIRK_DEF(_q) \ | ||
48 | BRCMF_FEAT_QUIRK_ ## _q, | ||
49 | /* | ||
50 | * expand quirk list to enumeration. | ||
51 | */ | ||
52 | enum brcmf_feat_quirk { | ||
53 | BRCMF_QUIRK_LIST | ||
54 | BRCMF_FEAT_QUIRK_LAST | ||
55 | }; | ||
56 | #undef BRCMF_QUIRK_DEF | ||
57 | |||
58 | /** | ||
59 | * brcmf_feat_attach() - determine features and quirks. | ||
60 | * | ||
61 | * @drvr: driver instance. | ||
62 | */ | ||
63 | void brcmf_feat_attach(struct brcmf_pub *drvr); | ||
64 | |||
65 | /** | ||
66 | * brcmf_feat_is_enabled() - query feature. | ||
67 | * | ||
68 | * @ifp: interface instance. | ||
69 | * @id: feature id to check. | ||
70 | * | ||
71 | * Return: true is feature is enabled; otherwise false. | ||
72 | */ | ||
73 | bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id); | ||
74 | |||
75 | /** | ||
76 | * brcmf_feat_is_quirk_enabled() - query chip quirk. | ||
77 | * | ||
78 | * @ifp: interface instance. | ||
79 | * @quirk: quirk id to check. | ||
80 | * | ||
81 | * Return: true is quirk is enabled; otherwise false. | ||
82 | */ | ||
83 | bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp, | ||
84 | enum brcmf_feat_quirk quirk); | ||
85 | |||
86 | #endif /* _BRCMF_FEATURE_H */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c index 7b7d237c1ddb..8ea9f283d2b8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c | |||
@@ -18,10 +18,15 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
20 | #include <linux/firmware.h> | 20 | #include <linux/firmware.h> |
21 | #include <linux/module.h> | ||
21 | 22 | ||
22 | #include "dhd_dbg.h" | 23 | #include "dhd_dbg.h" |
23 | #include "firmware.h" | 24 | #include "firmware.h" |
24 | 25 | ||
26 | char brcmf_firmware_path[BRCMF_FW_PATH_LEN]; | ||
27 | module_param_string(firmware_path, brcmf_firmware_path, | ||
28 | BRCMF_FW_PATH_LEN, 0440); | ||
29 | |||
25 | enum nvram_parser_state { | 30 | enum nvram_parser_state { |
26 | IDLE, | 31 | IDLE, |
27 | KEY, | 32 | KEY, |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h index 6431bfd7afff..4d3482356b77 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h | |||
@@ -21,6 +21,11 @@ | |||
21 | #define BRCMF_FW_REQ_FLAGS 0x00F0 | 21 | #define BRCMF_FW_REQ_FLAGS 0x00F0 |
22 | #define BRCMF_FW_REQ_NV_OPTIONAL 0x0010 | 22 | #define BRCMF_FW_REQ_NV_OPTIONAL 0x0010 |
23 | 23 | ||
24 | #define BRCMF_FW_PATH_LEN 256 | ||
25 | #define BRCMF_FW_NAME_LEN 32 | ||
26 | |||
27 | extern char brcmf_firmware_path[]; | ||
28 | |||
24 | void brcmf_fw_nvram_free(void *nvram); | 29 | void brcmf_fw_nvram_free(void *nvram); |
25 | /* | 30 | /* |
26 | * Request firmware(s) asynchronously. When the asynchronous request | 31 | * Request firmware(s) asynchronously. When the asynchronous request |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 699908de314a..d42f7d04b65f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -454,6 +454,34 @@ struct brcmf_fws_macdesc_table { | |||
454 | struct brcmf_fws_mac_descriptor other; | 454 | struct brcmf_fws_mac_descriptor other; |
455 | }; | 455 | }; |
456 | 456 | ||
457 | struct brcmf_fws_stats { | ||
458 | u32 tlv_parse_failed; | ||
459 | u32 tlv_invalid_type; | ||
460 | u32 header_only_pkt; | ||
461 | u32 header_pulls; | ||
462 | u32 pkt2bus; | ||
463 | u32 send_pkts[5]; | ||
464 | u32 requested_sent[5]; | ||
465 | u32 generic_error; | ||
466 | u32 mac_update_failed; | ||
467 | u32 mac_ps_update_failed; | ||
468 | u32 if_update_failed; | ||
469 | u32 packet_request_failed; | ||
470 | u32 credit_request_failed; | ||
471 | u32 rollback_success; | ||
472 | u32 rollback_failed; | ||
473 | u32 delayq_full_error; | ||
474 | u32 supprq_full_error; | ||
475 | u32 txs_indicate; | ||
476 | u32 txs_discard; | ||
477 | u32 txs_supp_core; | ||
478 | u32 txs_supp_ps; | ||
479 | u32 txs_tossed; | ||
480 | u32 txs_host_tossed; | ||
481 | u32 bus_flow_block; | ||
482 | u32 fws_flow_block; | ||
483 | }; | ||
484 | |||
457 | struct brcmf_fws_info { | 485 | struct brcmf_fws_info { |
458 | struct brcmf_pub *drvr; | 486 | struct brcmf_pub *drvr; |
459 | spinlock_t spinlock; | 487 | spinlock_t spinlock; |
@@ -2017,6 +2045,75 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) | |||
2017 | brcmf_fws_unlock(fws); | 2045 | brcmf_fws_unlock(fws); |
2018 | } | 2046 | } |
2019 | 2047 | ||
2048 | #ifdef DEBUG | ||
2049 | static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data) | ||
2050 | { | ||
2051 | struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); | ||
2052 | struct brcmf_fws_stats *fwstats = &bus_if->drvr->fws->stats; | ||
2053 | |||
2054 | seq_printf(seq, | ||
2055 | "header_pulls: %u\n" | ||
2056 | "header_only_pkt: %u\n" | ||
2057 | "tlv_parse_failed: %u\n" | ||
2058 | "tlv_invalid_type: %u\n" | ||
2059 | "mac_update_fails: %u\n" | ||
2060 | "ps_update_fails: %u\n" | ||
2061 | "if_update_fails: %u\n" | ||
2062 | "pkt2bus: %u\n" | ||
2063 | "generic_error: %u\n" | ||
2064 | "rollback_success: %u\n" | ||
2065 | "rollback_failed: %u\n" | ||
2066 | "delayq_full: %u\n" | ||
2067 | "supprq_full: %u\n" | ||
2068 | "txs_indicate: %u\n" | ||
2069 | "txs_discard: %u\n" | ||
2070 | "txs_suppr_core: %u\n" | ||
2071 | "txs_suppr_ps: %u\n" | ||
2072 | "txs_tossed: %u\n" | ||
2073 | "txs_host_tossed: %u\n" | ||
2074 | "bus_flow_block: %u\n" | ||
2075 | "fws_flow_block: %u\n" | ||
2076 | "send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n" | ||
2077 | "requested_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n", | ||
2078 | fwstats->header_pulls, | ||
2079 | fwstats->header_only_pkt, | ||
2080 | fwstats->tlv_parse_failed, | ||
2081 | fwstats->tlv_invalid_type, | ||
2082 | fwstats->mac_update_failed, | ||
2083 | fwstats->mac_ps_update_failed, | ||
2084 | fwstats->if_update_failed, | ||
2085 | fwstats->pkt2bus, | ||
2086 | fwstats->generic_error, | ||
2087 | fwstats->rollback_success, | ||
2088 | fwstats->rollback_failed, | ||
2089 | fwstats->delayq_full_error, | ||
2090 | fwstats->supprq_full_error, | ||
2091 | fwstats->txs_indicate, | ||
2092 | fwstats->txs_discard, | ||
2093 | fwstats->txs_supp_core, | ||
2094 | fwstats->txs_supp_ps, | ||
2095 | fwstats->txs_tossed, | ||
2096 | fwstats->txs_host_tossed, | ||
2097 | fwstats->bus_flow_block, | ||
2098 | fwstats->fws_flow_block, | ||
2099 | fwstats->send_pkts[0], fwstats->send_pkts[1], | ||
2100 | fwstats->send_pkts[2], fwstats->send_pkts[3], | ||
2101 | fwstats->send_pkts[4], | ||
2102 | fwstats->requested_sent[0], | ||
2103 | fwstats->requested_sent[1], | ||
2104 | fwstats->requested_sent[2], | ||
2105 | fwstats->requested_sent[3], | ||
2106 | fwstats->requested_sent[4]); | ||
2107 | |||
2108 | return 0; | ||
2109 | } | ||
2110 | #else | ||
2111 | static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data) | ||
2112 | { | ||
2113 | return 0; | ||
2114 | } | ||
2115 | #endif | ||
2116 | |||
2020 | int brcmf_fws_init(struct brcmf_pub *drvr) | 2117 | int brcmf_fws_init(struct brcmf_pub *drvr) |
2021 | { | 2118 | { |
2022 | struct brcmf_fws_info *fws; | 2119 | struct brcmf_fws_info *fws; |
@@ -2107,7 +2204,8 @@ int brcmf_fws_init(struct brcmf_pub *drvr) | |||
2107 | BRCMF_FWS_PSQ_LEN); | 2204 | BRCMF_FWS_PSQ_LEN); |
2108 | 2205 | ||
2109 | /* create debugfs file for statistics */ | 2206 | /* create debugfs file for statistics */ |
2110 | brcmf_debugfs_create_fws_stats(drvr, &fws->stats); | 2207 | brcmf_debugfs_add_entry(drvr, "fws_stats", |
2208 | brcmf_debugfs_fws_stats_read); | ||
2111 | 2209 | ||
2112 | brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n", | 2210 | brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n", |
2113 | fws->fw_signals ? "enabled" : "disabled", tlv); | 2211 | fws->fw_signals ? "enabled" : "disabled", tlv); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 3deab7959a0d..6c5e585ccda9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
@@ -18,6 +18,8 @@ | |||
18 | #define _BRCM_SDH_H_ | 18 | #define _BRCM_SDH_H_ |
19 | 19 | ||
20 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
21 | #include <linux/firmware.h> | ||
22 | #include "firmware.h" | ||
21 | 23 | ||
22 | #define SDIO_FUNC_0 0 | 24 | #define SDIO_FUNC_0 0 |
23 | #define SDIO_FUNC_1 1 | 25 | #define SDIO_FUNC_1 1 |
@@ -182,6 +184,8 @@ struct brcmf_sdio_dev { | |||
182 | uint max_segment_size; | 184 | uint max_segment_size; |
183 | uint txglomsz; | 185 | uint txglomsz; |
184 | struct sg_table sgtable; | 186 | struct sg_table sgtable; |
187 | char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | ||
188 | char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | ||
185 | }; | 189 | }; |
186 | 190 | ||
187 | /* sdio core registers */ | 191 | /* sdio core registers */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index b732a99e402c..dc135915470d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/vmalloc.h> | 21 | #include <linux/vmalloc.h> |
22 | 22 | ||
23 | #include <brcmu_utils.h> | 23 | #include <brcmu_utils.h> |
24 | #include <brcm_hw_ids.h> | ||
24 | #include <brcmu_wifi.h> | 25 | #include <brcmu_wifi.h> |
25 | #include <dhd_bus.h> | 26 | #include <dhd_bus.h> |
26 | #include <dhd_dbg.h> | 27 | #include <dhd_dbg.h> |
@@ -913,16 +914,16 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo) | |||
913 | static bool brcmf_usb_chip_support(int chipid, int chiprev) | 914 | static bool brcmf_usb_chip_support(int chipid, int chiprev) |
914 | { | 915 | { |
915 | switch(chipid) { | 916 | switch(chipid) { |
916 | case 43143: | 917 | case BRCM_CC_43143_CHIP_ID: |
917 | return true; | 918 | return true; |
918 | case 43235: | 919 | case BRCM_CC_43235_CHIP_ID: |
919 | case 43236: | 920 | case BRCM_CC_43236_CHIP_ID: |
920 | case 43238: | 921 | case BRCM_CC_43238_CHIP_ID: |
921 | return (chiprev == 3); | 922 | return (chiprev == 3); |
922 | case 43242: | 923 | case BRCM_CC_43242_CHIP_ID: |
923 | return true; | 924 | return true; |
924 | case 43566: | 925 | case BRCM_CC_43566_CHIP_ID: |
925 | case 43569: | 926 | case BRCM_CC_43569_CHIP_ID: |
926 | return true; | 927 | return true; |
927 | default: | 928 | default: |
928 | break; | 929 | break; |
@@ -1016,16 +1017,16 @@ static int check_file(const u8 *headers) | |||
1016 | static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo) | 1017 | static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo) |
1017 | { | 1018 | { |
1018 | switch (devinfo->bus_pub.devid) { | 1019 | switch (devinfo->bus_pub.devid) { |
1019 | case 43143: | 1020 | case BRCM_CC_43143_CHIP_ID: |
1020 | return BRCMF_USB_43143_FW_NAME; | 1021 | return BRCMF_USB_43143_FW_NAME; |
1021 | case 43235: | 1022 | case BRCM_CC_43235_CHIP_ID: |
1022 | case 43236: | 1023 | case BRCM_CC_43236_CHIP_ID: |
1023 | case 43238: | 1024 | case BRCM_CC_43238_CHIP_ID: |
1024 | return BRCMF_USB_43236_FW_NAME; | 1025 | return BRCMF_USB_43236_FW_NAME; |
1025 | case 43242: | 1026 | case BRCM_CC_43242_CHIP_ID: |
1026 | return BRCMF_USB_43242_FW_NAME; | 1027 | return BRCMF_USB_43242_FW_NAME; |
1027 | case 43566: | 1028 | case BRCM_CC_43566_CHIP_ID: |
1028 | case 43569: | 1029 | case BRCM_CC_43569_CHIP_ID: |
1029 | return BRCMF_USB_43569_FW_NAME; | 1030 | return BRCMF_USB_43569_FW_NAME; |
1030 | default: | 1031 | default: |
1031 | return NULL; | 1032 | return NULL; |
@@ -1366,21 +1367,17 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf) | |||
1366 | brcmf_usb_probe_phase2); | 1367 | brcmf_usb_probe_phase2); |
1367 | } | 1368 | } |
1368 | 1369 | ||
1369 | #define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c | 1370 | #define BRCMF_USB_DEVICE(dev_id) \ |
1370 | #define BRCMF_USB_DEVICE_ID_43143 0xbd1e | 1371 | { USB_DEVICE(BRCM_USB_VENDOR_ID_BROADCOM, dev_id) } |
1371 | #define BRCMF_USB_DEVICE_ID_43236 0xbd17 | ||
1372 | #define BRCMF_USB_DEVICE_ID_43242 0xbd1f | ||
1373 | #define BRCMF_USB_DEVICE_ID_43569 0xbd27 | ||
1374 | #define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc | ||
1375 | 1372 | ||
1376 | static struct usb_device_id brcmf_usb_devid_table[] = { | 1373 | static struct usb_device_id brcmf_usb_devid_table[] = { |
1377 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43143) }, | 1374 | BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID), |
1378 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) }, | 1375 | BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID), |
1379 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43242) }, | 1376 | BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID), |
1380 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43569) }, | 1377 | BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID), |
1381 | /* special entry for device with firmware loaded and running */ | 1378 | /* special entry for device with firmware loaded and running */ |
1382 | { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, | 1379 | BRCMF_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID), |
1383 | { } | 1380 | { /* end: all zeroes */ } |
1384 | }; | 1381 | }; |
1385 | 1382 | ||
1386 | MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); | 1383 | MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 9682cf213ec4..48078a321716 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include "p2p.h" | 33 | #include "p2p.h" |
34 | #include "btcoex.h" | 34 | #include "btcoex.h" |
35 | #include "wl_cfg80211.h" | 35 | #include "wl_cfg80211.h" |
36 | #include "feature.h" | ||
36 | #include "fwil.h" | 37 | #include "fwil.h" |
37 | #include "vendor.h" | 38 | #include "vendor.h" |
38 | 39 | ||
@@ -102,24 +103,6 @@ static bool check_vif_up(struct brcmf_cfg80211_vif *vif) | |||
102 | return true; | 103 | return true; |
103 | } | 104 | } |
104 | 105 | ||
105 | #define CHAN2G(_channel, _freq, _flags) { \ | ||
106 | .band = IEEE80211_BAND_2GHZ, \ | ||
107 | .center_freq = (_freq), \ | ||
108 | .hw_value = (_channel), \ | ||
109 | .flags = (_flags), \ | ||
110 | .max_antenna_gain = 0, \ | ||
111 | .max_power = 30, \ | ||
112 | } | ||
113 | |||
114 | #define CHAN5G(_channel, _flags) { \ | ||
115 | .band = IEEE80211_BAND_5GHZ, \ | ||
116 | .center_freq = 5000 + (5 * (_channel)), \ | ||
117 | .hw_value = (_channel), \ | ||
118 | .flags = (_flags), \ | ||
119 | .max_antenna_gain = 0, \ | ||
120 | .max_power = 30, \ | ||
121 | } | ||
122 | |||
123 | #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) | 106 | #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) |
124 | #define RATETAB_ENT(_rateid, _flags) \ | 107 | #define RATETAB_ENT(_rateid, _flags) \ |
125 | { \ | 108 | { \ |
@@ -148,58 +131,17 @@ static struct ieee80211_rate __wl_rates[] = { | |||
148 | #define wl_g_rates (__wl_rates + 0) | 131 | #define wl_g_rates (__wl_rates + 0) |
149 | #define wl_g_rates_size 12 | 132 | #define wl_g_rates_size 12 |
150 | 133 | ||
151 | static struct ieee80211_channel __wl_2ghz_channels[] = { | 134 | /* Band templates duplicated per wiphy. The channel info |
152 | CHAN2G(1, 2412, 0), | 135 | * is filled in after querying the device. |
153 | CHAN2G(2, 2417, 0), | 136 | */ |
154 | CHAN2G(3, 2422, 0), | 137 | static const struct ieee80211_supported_band __wl_band_2ghz = { |
155 | CHAN2G(4, 2427, 0), | ||
156 | CHAN2G(5, 2432, 0), | ||
157 | CHAN2G(6, 2437, 0), | ||
158 | CHAN2G(7, 2442, 0), | ||
159 | CHAN2G(8, 2447, 0), | ||
160 | CHAN2G(9, 2452, 0), | ||
161 | CHAN2G(10, 2457, 0), | ||
162 | CHAN2G(11, 2462, 0), | ||
163 | CHAN2G(12, 2467, 0), | ||
164 | CHAN2G(13, 2472, 0), | ||
165 | CHAN2G(14, 2484, 0), | ||
166 | }; | ||
167 | |||
168 | static struct ieee80211_channel __wl_5ghz_a_channels[] = { | ||
169 | CHAN5G(34, 0), CHAN5G(36, 0), | ||
170 | CHAN5G(38, 0), CHAN5G(40, 0), | ||
171 | CHAN5G(42, 0), CHAN5G(44, 0), | ||
172 | CHAN5G(46, 0), CHAN5G(48, 0), | ||
173 | CHAN5G(52, 0), CHAN5G(56, 0), | ||
174 | CHAN5G(60, 0), CHAN5G(64, 0), | ||
175 | CHAN5G(100, 0), CHAN5G(104, 0), | ||
176 | CHAN5G(108, 0), CHAN5G(112, 0), | ||
177 | CHAN5G(116, 0), CHAN5G(120, 0), | ||
178 | CHAN5G(124, 0), CHAN5G(128, 0), | ||
179 | CHAN5G(132, 0), CHAN5G(136, 0), | ||
180 | CHAN5G(140, 0), CHAN5G(149, 0), | ||
181 | CHAN5G(153, 0), CHAN5G(157, 0), | ||
182 | CHAN5G(161, 0), CHAN5G(165, 0), | ||
183 | CHAN5G(184, 0), CHAN5G(188, 0), | ||
184 | CHAN5G(192, 0), CHAN5G(196, 0), | ||
185 | CHAN5G(200, 0), CHAN5G(204, 0), | ||
186 | CHAN5G(208, 0), CHAN5G(212, 0), | ||
187 | CHAN5G(216, 0), | ||
188 | }; | ||
189 | |||
190 | static struct ieee80211_supported_band __wl_band_2ghz = { | ||
191 | .band = IEEE80211_BAND_2GHZ, | 138 | .band = IEEE80211_BAND_2GHZ, |
192 | .channels = __wl_2ghz_channels, | ||
193 | .n_channels = ARRAY_SIZE(__wl_2ghz_channels), | ||
194 | .bitrates = wl_g_rates, | 139 | .bitrates = wl_g_rates, |
195 | .n_bitrates = wl_g_rates_size, | 140 | .n_bitrates = wl_g_rates_size, |
196 | .ht_cap = {IEEE80211_HT_CAP_SUP_WIDTH_20_40, true}, | ||
197 | }; | 141 | }; |
198 | 142 | ||
199 | static struct ieee80211_supported_band __wl_band_5ghz_a = { | 143 | static const struct ieee80211_supported_band __wl_band_5ghz_a = { |
200 | .band = IEEE80211_BAND_5GHZ, | 144 | .band = IEEE80211_BAND_5GHZ, |
201 | .channels = __wl_5ghz_a_channels, | ||
202 | .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), | ||
203 | .bitrates = wl_a_rates, | 145 | .bitrates = wl_a_rates, |
204 | .n_bitrates = wl_a_rates_size, | 146 | .n_bitrates = wl_a_rates_size, |
205 | }; | 147 | }; |
@@ -592,7 +534,7 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, | |||
592 | 534 | ||
593 | static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc) | 535 | static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc) |
594 | { | 536 | { |
595 | if ((brcmf_get_chip_info(ifp) >> 4) == 0x4329) | 537 | if (brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_NEED_MPC)) |
596 | brcmf_set_mpc(ifp, mpc); | 538 | brcmf_set_mpc(ifp, mpc); |
597 | } | 539 | } |
598 | 540 | ||
@@ -1619,17 +1561,10 @@ static | |||
1619 | enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp, | 1561 | enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp, |
1620 | enum nl80211_auth_type type) | 1562 | enum nl80211_auth_type type) |
1621 | { | 1563 | { |
1622 | u32 ci; | 1564 | if (type == NL80211_AUTHTYPE_AUTOMATIC && |
1623 | if (type == NL80211_AUTHTYPE_AUTOMATIC) { | 1565 | brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_AUTO_AUTH)) { |
1624 | /* shift to ignore chip revision */ | 1566 | brcmf_dbg(CONN, "WAR: use OPEN instead of AUTO\n"); |
1625 | ci = brcmf_get_chip_info(ifp) >> 4; | 1567 | type = NL80211_AUTHTYPE_OPEN_SYSTEM; |
1626 | switch (ci) { | ||
1627 | case 43236: | ||
1628 | brcmf_dbg(CONN, "43236 WAR: use OPEN instead of AUTO\n"); | ||
1629 | return NL80211_AUTHTYPE_OPEN_SYSTEM; | ||
1630 | default: | ||
1631 | break; | ||
1632 | } | ||
1633 | } | 1568 | } |
1634 | return type; | 1569 | return type; |
1635 | } | 1570 | } |
@@ -4284,122 +4219,6 @@ static struct cfg80211_ops wl_cfg80211_ops = { | |||
4284 | .tdls_oper = brcmf_cfg80211_tdls_oper, | 4219 | .tdls_oper = brcmf_cfg80211_tdls_oper, |
4285 | }; | 4220 | }; |
4286 | 4221 | ||
4287 | static void brcmf_wiphy_pno_params(struct wiphy *wiphy) | ||
4288 | { | ||
4289 | /* scheduled scan settings */ | ||
4290 | wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; | ||
4291 | wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; | ||
4292 | wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | ||
4293 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
4294 | } | ||
4295 | |||
4296 | static const struct ieee80211_iface_limit brcmf_iface_limits[] = { | ||
4297 | { | ||
4298 | .max = 2, | ||
4299 | .types = BIT(NL80211_IFTYPE_STATION) | | ||
4300 | BIT(NL80211_IFTYPE_ADHOC) | | ||
4301 | BIT(NL80211_IFTYPE_AP) | ||
4302 | }, | ||
4303 | { | ||
4304 | .max = 1, | ||
4305 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
4306 | BIT(NL80211_IFTYPE_P2P_GO) | ||
4307 | }, | ||
4308 | { | ||
4309 | .max = 1, | ||
4310 | .types = BIT(NL80211_IFTYPE_P2P_DEVICE) | ||
4311 | } | ||
4312 | }; | ||
4313 | static const struct ieee80211_iface_combination brcmf_iface_combos[] = { | ||
4314 | { | ||
4315 | .max_interfaces = BRCMF_IFACE_MAX_CNT, | ||
4316 | .num_different_channels = 2, | ||
4317 | .n_limits = ARRAY_SIZE(brcmf_iface_limits), | ||
4318 | .limits = brcmf_iface_limits | ||
4319 | } | ||
4320 | }; | ||
4321 | |||
4322 | static const struct ieee80211_txrx_stypes | ||
4323 | brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { | ||
4324 | [NL80211_IFTYPE_STATION] = { | ||
4325 | .tx = 0xffff, | ||
4326 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
4327 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
4328 | }, | ||
4329 | [NL80211_IFTYPE_P2P_CLIENT] = { | ||
4330 | .tx = 0xffff, | ||
4331 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
4332 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
4333 | }, | ||
4334 | [NL80211_IFTYPE_P2P_GO] = { | ||
4335 | .tx = 0xffff, | ||
4336 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
4337 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
4338 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
4339 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
4340 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
4341 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
4342 | BIT(IEEE80211_STYPE_ACTION >> 4) | ||
4343 | }, | ||
4344 | [NL80211_IFTYPE_P2P_DEVICE] = { | ||
4345 | .tx = 0xffff, | ||
4346 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
4347 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
4348 | } | ||
4349 | }; | ||
4350 | |||
4351 | static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | ||
4352 | { | ||
4353 | struct wiphy *wiphy; | ||
4354 | s32 err = 0; | ||
4355 | |||
4356 | wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info)); | ||
4357 | if (!wiphy) { | ||
4358 | brcmf_err("Could not allocate wiphy device\n"); | ||
4359 | return ERR_PTR(-ENOMEM); | ||
4360 | } | ||
4361 | set_wiphy_dev(wiphy, phydev); | ||
4362 | wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; | ||
4363 | wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | ||
4364 | wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; | ||
4365 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
4366 | BIT(NL80211_IFTYPE_ADHOC) | | ||
4367 | BIT(NL80211_IFTYPE_AP) | | ||
4368 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
4369 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
4370 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
4371 | wiphy->iface_combinations = brcmf_iface_combos; | ||
4372 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); | ||
4373 | wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; | ||
4374 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
4375 | wiphy->cipher_suites = __wl_cipher_suites; | ||
4376 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | ||
4377 | wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT | | ||
4378 | WIPHY_FLAG_OFFCHAN_TX | | ||
4379 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
4380 | WIPHY_FLAG_SUPPORTS_TDLS; | ||
4381 | if (!brcmf_roamoff) | ||
4382 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; | ||
4383 | wiphy->mgmt_stypes = brcmf_txrx_stypes; | ||
4384 | wiphy->max_remain_on_channel_duration = 5000; | ||
4385 | brcmf_wiphy_pno_params(wiphy); | ||
4386 | brcmf_dbg(INFO, "Registering custom regulatory\n"); | ||
4387 | wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; | ||
4388 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); | ||
4389 | |||
4390 | /* vendor commands/events support */ | ||
4391 | wiphy->vendor_commands = brcmf_vendor_cmds; | ||
4392 | wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1; | ||
4393 | |||
4394 | err = wiphy_register(wiphy); | ||
4395 | if (err < 0) { | ||
4396 | brcmf_err("Could not register wiphy device (%d)\n", err); | ||
4397 | wiphy_free(wiphy); | ||
4398 | return ERR_PTR(err); | ||
4399 | } | ||
4400 | return wiphy; | ||
4401 | } | ||
4402 | |||
4403 | struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, | 4222 | struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, |
4404 | enum nl80211_iftype type, | 4223 | enum nl80211_iftype type, |
4405 | bool pm_block) | 4224 | bool pm_block) |
@@ -4943,138 +4762,6 @@ static void init_vif_event(struct brcmf_cfg80211_vif_event *event) | |||
4943 | mutex_init(&event->vif_event_lock); | 4762 | mutex_init(&event->vif_event_lock); |
4944 | } | 4763 | } |
4945 | 4764 | ||
4946 | static int brcmf_enable_bw40_2g(struct brcmf_if *ifp) | ||
4947 | { | ||
4948 | struct brcmf_fil_bwcap_le band_bwcap; | ||
4949 | u32 val; | ||
4950 | int err; | ||
4951 | |||
4952 | /* verify support for bw_cap command */ | ||
4953 | val = WLC_BAND_5G; | ||
4954 | err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val); | ||
4955 | |||
4956 | if (!err) { | ||
4957 | /* only set 2G bandwidth using bw_cap command */ | ||
4958 | band_bwcap.band = cpu_to_le32(WLC_BAND_2G); | ||
4959 | band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ); | ||
4960 | err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap, | ||
4961 | sizeof(band_bwcap)); | ||
4962 | } else { | ||
4963 | brcmf_dbg(INFO, "fallback to mimo_bw_cap\n"); | ||
4964 | val = WLC_N_BW_40ALL; | ||
4965 | err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val); | ||
4966 | } | ||
4967 | return err; | ||
4968 | } | ||
4969 | |||
4970 | struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | ||
4971 | struct device *busdev) | ||
4972 | { | ||
4973 | struct net_device *ndev = drvr->iflist[0]->ndev; | ||
4974 | struct brcmf_cfg80211_info *cfg; | ||
4975 | struct wiphy *wiphy; | ||
4976 | struct brcmf_cfg80211_vif *vif; | ||
4977 | struct brcmf_if *ifp; | ||
4978 | s32 err = 0; | ||
4979 | s32 io_type; | ||
4980 | |||
4981 | if (!ndev) { | ||
4982 | brcmf_err("ndev is invalid\n"); | ||
4983 | return NULL; | ||
4984 | } | ||
4985 | |||
4986 | ifp = netdev_priv(ndev); | ||
4987 | wiphy = brcmf_setup_wiphy(busdev); | ||
4988 | if (IS_ERR(wiphy)) | ||
4989 | return NULL; | ||
4990 | |||
4991 | cfg = wiphy_priv(wiphy); | ||
4992 | cfg->wiphy = wiphy; | ||
4993 | cfg->pub = drvr; | ||
4994 | init_vif_event(&cfg->vif_event); | ||
4995 | INIT_LIST_HEAD(&cfg->vif_list); | ||
4996 | |||
4997 | vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false); | ||
4998 | if (IS_ERR(vif)) { | ||
4999 | wiphy_free(wiphy); | ||
5000 | return NULL; | ||
5001 | } | ||
5002 | |||
5003 | vif->ifp = ifp; | ||
5004 | vif->wdev.netdev = ndev; | ||
5005 | ndev->ieee80211_ptr = &vif->wdev; | ||
5006 | SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy)); | ||
5007 | |||
5008 | err = wl_init_priv(cfg); | ||
5009 | if (err) { | ||
5010 | brcmf_err("Failed to init iwm_priv (%d)\n", err); | ||
5011 | goto cfg80211_attach_out; | ||
5012 | } | ||
5013 | ifp->vif = vif; | ||
5014 | |||
5015 | err = brcmf_p2p_attach(cfg); | ||
5016 | if (err) { | ||
5017 | brcmf_err("P2P initilisation failed (%d)\n", err); | ||
5018 | goto cfg80211_p2p_attach_out; | ||
5019 | } | ||
5020 | err = brcmf_btcoex_attach(cfg); | ||
5021 | if (err) { | ||
5022 | brcmf_err("BT-coex initialisation failed (%d)\n", err); | ||
5023 | brcmf_p2p_detach(&cfg->p2p); | ||
5024 | goto cfg80211_p2p_attach_out; | ||
5025 | } | ||
5026 | |||
5027 | /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(), | ||
5028 | * setup 40MHz in 2GHz band and enable OBSS scanning. | ||
5029 | */ | ||
5030 | if (wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap & | ||
5031 | IEEE80211_HT_CAP_SUP_WIDTH_20_40) { | ||
5032 | err = brcmf_enable_bw40_2g(ifp); | ||
5033 | if (!err) | ||
5034 | err = brcmf_fil_iovar_int_set(ifp, "obss_coex", | ||
5035 | BRCMF_OBSS_COEX_AUTO); | ||
5036 | } | ||
5037 | /* clear for now and rely on update later */ | ||
5038 | wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.ht_supported = false; | ||
5039 | wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap = 0; | ||
5040 | |||
5041 | err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1); | ||
5042 | if (err) { | ||
5043 | brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err); | ||
5044 | wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS; | ||
5045 | } | ||
5046 | |||
5047 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, | ||
5048 | &io_type); | ||
5049 | if (err) { | ||
5050 | brcmf_err("Failed to get D11 version (%d)\n", err); | ||
5051 | goto cfg80211_p2p_attach_out; | ||
5052 | } | ||
5053 | cfg->d11inf.io_type = (u8)io_type; | ||
5054 | brcmu_d11_attach(&cfg->d11inf); | ||
5055 | |||
5056 | return cfg; | ||
5057 | |||
5058 | cfg80211_p2p_attach_out: | ||
5059 | wl_deinit_priv(cfg); | ||
5060 | |||
5061 | cfg80211_attach_out: | ||
5062 | brcmf_free_vif(vif); | ||
5063 | return NULL; | ||
5064 | } | ||
5065 | |||
5066 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | ||
5067 | { | ||
5068 | if (!cfg) | ||
5069 | return; | ||
5070 | |||
5071 | WARN_ON(!list_empty(&cfg->vif_list)); | ||
5072 | wiphy_unregister(cfg->wiphy); | ||
5073 | brcmf_btcoex_detach(cfg); | ||
5074 | wl_deinit_priv(cfg); | ||
5075 | wiphy_free(cfg->wiphy); | ||
5076 | } | ||
5077 | |||
5078 | static s32 | 4765 | static s32 |
5079 | brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout) | 4766 | brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout) |
5080 | { | 4767 | { |
@@ -5167,25 +4854,77 @@ dongle_scantime_out: | |||
5167 | return err; | 4854 | return err; |
5168 | } | 4855 | } |
5169 | 4856 | ||
4857 | /* Filter the list of channels received from firmware counting only | ||
4858 | * the 20MHz channels. The wiphy band data only needs those which get | ||
4859 | * flagged to indicate if they can take part in higher bandwidth. | ||
4860 | */ | ||
4861 | static void brcmf_count_20mhz_channels(struct brcmf_cfg80211_info *cfg, | ||
4862 | struct brcmf_chanspec_list *chlist, | ||
4863 | u32 chcnt[]) | ||
4864 | { | ||
4865 | u32 total = le32_to_cpu(chlist->count); | ||
4866 | struct brcmu_chan ch; | ||
4867 | int i; | ||
4868 | |||
4869 | for (i = 0; i <= total; i++) { | ||
4870 | ch.chspec = (u16)le32_to_cpu(chlist->element[i]); | ||
4871 | cfg->d11inf.decchspec(&ch); | ||
4872 | |||
4873 | /* Firmware gives a ordered list. We skip non-20MHz | ||
4874 | * channels is 2G. For 5G we can abort upon reaching | ||
4875 | * a non-20MHz channel in the list. | ||
4876 | */ | ||
4877 | if (ch.bw != BRCMU_CHAN_BW_20) { | ||
4878 | if (ch.band == BRCMU_CHAN_BAND_5G) | ||
4879 | break; | ||
4880 | else | ||
4881 | continue; | ||
4882 | } | ||
4883 | |||
4884 | if (ch.band == BRCMU_CHAN_BAND_2G) | ||
4885 | chcnt[0] += 1; | ||
4886 | else if (ch.band == BRCMU_CHAN_BAND_5G) | ||
4887 | chcnt[1] += 1; | ||
4888 | } | ||
4889 | } | ||
4890 | |||
4891 | static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel, | ||
4892 | struct brcmu_chan *ch) | ||
4893 | { | ||
4894 | u32 ht40_flag; | ||
5170 | 4895 | ||
5171 | static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, | 4896 | ht40_flag = channel->flags & IEEE80211_CHAN_NO_HT40; |
5172 | u32 bw_cap[]) | 4897 | if (ch->sb == BRCMU_CHAN_SB_U) { |
4898 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | ||
4899 | channel->flags &= ~IEEE80211_CHAN_NO_HT40; | ||
4900 | channel->flags |= IEEE80211_CHAN_NO_HT40PLUS; | ||
4901 | } else { | ||
4902 | /* It should be one of | ||
4903 | * IEEE80211_CHAN_NO_HT40 or | ||
4904 | * IEEE80211_CHAN_NO_HT40PLUS | ||
4905 | */ | ||
4906 | channel->flags &= ~IEEE80211_CHAN_NO_HT40; | ||
4907 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | ||
4908 | channel->flags |= IEEE80211_CHAN_NO_HT40MINUS; | ||
4909 | } | ||
4910 | } | ||
4911 | |||
4912 | static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, | ||
4913 | u32 bw_cap[]) | ||
5173 | { | 4914 | { |
5174 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | 4915 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
5175 | struct ieee80211_channel *band_chan_arr; | 4916 | struct ieee80211_supported_band *band; |
4917 | struct ieee80211_channel *channel; | ||
4918 | struct wiphy *wiphy; | ||
5176 | struct brcmf_chanspec_list *list; | 4919 | struct brcmf_chanspec_list *list; |
5177 | struct brcmu_chan ch; | 4920 | struct brcmu_chan ch; |
5178 | s32 err; | 4921 | int err; |
5179 | u8 *pbuf; | 4922 | u8 *pbuf; |
5180 | u32 i, j; | 4923 | u32 i, j; |
5181 | u32 total; | 4924 | u32 total; |
5182 | enum ieee80211_band band; | 4925 | u32 chaninfo; |
5183 | u32 channel; | 4926 | u32 chcnt[2] = { 0, 0 }; |
5184 | u32 *n_cnt; | ||
5185 | u32 index; | 4927 | u32 index; |
5186 | u32 ht40_flag; | ||
5187 | bool update; | ||
5188 | u32 array_size; | ||
5189 | 4928 | ||
5190 | pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); | 4929 | pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); |
5191 | 4930 | ||
@@ -5198,11 +4937,45 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, | |||
5198 | BRCMF_DCMD_MEDLEN); | 4937 | BRCMF_DCMD_MEDLEN); |
5199 | if (err) { | 4938 | if (err) { |
5200 | brcmf_err("get chanspecs error (%d)\n", err); | 4939 | brcmf_err("get chanspecs error (%d)\n", err); |
5201 | goto exit; | 4940 | goto fail_pbuf; |
5202 | } | 4941 | } |
5203 | 4942 | ||
5204 | __wl_band_2ghz.n_channels = 0; | 4943 | brcmf_count_20mhz_channels(cfg, list, chcnt); |
5205 | __wl_band_5ghz_a.n_channels = 0; | 4944 | wiphy = cfg_to_wiphy(cfg); |
4945 | if (chcnt[0]) { | ||
4946 | band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz), | ||
4947 | GFP_KERNEL); | ||
4948 | if (band == NULL) { | ||
4949 | err = -ENOMEM; | ||
4950 | goto fail_pbuf; | ||
4951 | } | ||
4952 | band->channels = kcalloc(chcnt[0], sizeof(*channel), | ||
4953 | GFP_KERNEL); | ||
4954 | if (band->channels == NULL) { | ||
4955 | kfree(band); | ||
4956 | err = -ENOMEM; | ||
4957 | goto fail_pbuf; | ||
4958 | } | ||
4959 | band->n_channels = 0; | ||
4960 | wiphy->bands[IEEE80211_BAND_2GHZ] = band; | ||
4961 | } | ||
4962 | if (chcnt[1]) { | ||
4963 | band = kmemdup(&__wl_band_5ghz_a, sizeof(__wl_band_5ghz_a), | ||
4964 | GFP_KERNEL); | ||
4965 | if (band == NULL) { | ||
4966 | err = -ENOMEM; | ||
4967 | goto fail_band2g; | ||
4968 | } | ||
4969 | band->channels = kcalloc(chcnt[1], sizeof(*channel), | ||
4970 | GFP_KERNEL); | ||
4971 | if (band->channels == NULL) { | ||
4972 | kfree(band); | ||
4973 | err = -ENOMEM; | ||
4974 | goto fail_band2g; | ||
4975 | } | ||
4976 | band->n_channels = 0; | ||
4977 | wiphy->bands[IEEE80211_BAND_5GHZ] = band; | ||
4978 | } | ||
5206 | 4979 | ||
5207 | total = le32_to_cpu(list->count); | 4980 | total = le32_to_cpu(list->count); |
5208 | for (i = 0; i < total; i++) { | 4981 | for (i = 0; i < total; i++) { |
@@ -5210,100 +4983,151 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, | |||
5210 | cfg->d11inf.decchspec(&ch); | 4983 | cfg->d11inf.decchspec(&ch); |
5211 | 4984 | ||
5212 | if (ch.band == BRCMU_CHAN_BAND_2G) { | 4985 | if (ch.band == BRCMU_CHAN_BAND_2G) { |
5213 | band_chan_arr = __wl_2ghz_channels; | 4986 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; |
5214 | array_size = ARRAY_SIZE(__wl_2ghz_channels); | ||
5215 | n_cnt = &__wl_band_2ghz.n_channels; | ||
5216 | band = IEEE80211_BAND_2GHZ; | ||
5217 | } else if (ch.band == BRCMU_CHAN_BAND_5G) { | 4987 | } else if (ch.band == BRCMU_CHAN_BAND_5G) { |
5218 | band_chan_arr = __wl_5ghz_a_channels; | 4988 | band = wiphy->bands[IEEE80211_BAND_5GHZ]; |
5219 | array_size = ARRAY_SIZE(__wl_5ghz_a_channels); | ||
5220 | n_cnt = &__wl_band_5ghz_a.n_channels; | ||
5221 | band = IEEE80211_BAND_5GHZ; | ||
5222 | } else { | 4989 | } else { |
5223 | brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec); | 4990 | brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec); |
5224 | continue; | 4991 | continue; |
5225 | } | 4992 | } |
5226 | if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) && | 4993 | if (!(bw_cap[band->band] & WLC_BW_40MHZ_BIT) && |
5227 | ch.bw == BRCMU_CHAN_BW_40) | 4994 | ch.bw == BRCMU_CHAN_BW_40) |
5228 | continue; | 4995 | continue; |
5229 | if (!(bw_cap[band] & WLC_BW_80MHZ_BIT) && | 4996 | if (!(bw_cap[band->band] & WLC_BW_80MHZ_BIT) && |
5230 | ch.bw == BRCMU_CHAN_BW_80) | 4997 | ch.bw == BRCMU_CHAN_BW_80) |
5231 | continue; | 4998 | continue; |
5232 | update = false; | 4999 | |
5233 | for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { | 5000 | channel = band->channels; |
5234 | if (band_chan_arr[j].hw_value == ch.chnum) { | 5001 | index = band->n_channels; |
5235 | update = true; | 5002 | for (j = 0; j < band->n_channels; j++) { |
5003 | if (channel[j].hw_value == ch.chnum) { | ||
5004 | index = j; | ||
5236 | break; | 5005 | break; |
5237 | } | 5006 | } |
5238 | } | 5007 | } |
5239 | if (update) | 5008 | channel[index].center_freq = |
5240 | index = j; | 5009 | ieee80211_channel_to_frequency(ch.chnum, band->band); |
5241 | else | 5010 | channel[index].hw_value = ch.chnum; |
5242 | index = *n_cnt; | 5011 | |
5243 | if (index < array_size) { | 5012 | /* assuming the chanspecs order is HT20, |
5244 | band_chan_arr[index].center_freq = | 5013 | * HT40 upper, HT40 lower, and VHT80. |
5245 | ieee80211_channel_to_frequency(ch.chnum, band); | 5014 | */ |
5246 | band_chan_arr[index].hw_value = ch.chnum; | 5015 | if (ch.bw == BRCMU_CHAN_BW_80) { |
5247 | 5016 | channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ; | |
5248 | /* assuming the chanspecs order is HT20, | 5017 | } else if (ch.bw == BRCMU_CHAN_BW_40) { |
5249 | * HT40 upper, HT40 lower, and VHT80. | 5018 | brcmf_update_bw40_channel_flag(&channel[index], &ch); |
5019 | } else { | ||
5020 | /* disable other bandwidths for now as mentioned | ||
5021 | * order assure they are enabled for subsequent | ||
5022 | * chanspecs. | ||
5250 | */ | 5023 | */ |
5251 | if (ch.bw == BRCMU_CHAN_BW_80) { | 5024 | channel[index].flags = IEEE80211_CHAN_NO_HT40 | |
5252 | band_chan_arr[index].flags &= | 5025 | IEEE80211_CHAN_NO_80MHZ; |
5253 | ~IEEE80211_CHAN_NO_80MHZ; | 5026 | ch.bw = BRCMU_CHAN_BW_20; |
5254 | } else if (ch.bw == BRCMU_CHAN_BW_40) { | 5027 | cfg->d11inf.encchspec(&ch); |
5255 | ht40_flag = band_chan_arr[index].flags & | 5028 | chaninfo = ch.chspec; |
5256 | IEEE80211_CHAN_NO_HT40; | 5029 | err = brcmf_fil_bsscfg_int_get(ifp, "per_chan_info", |
5257 | if (ch.sb == BRCMU_CHAN_SB_U) { | 5030 | &chaninfo); |
5258 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | 5031 | if (!err) { |
5259 | band_chan_arr[index].flags &= | 5032 | if (chaninfo & WL_CHAN_RADAR) |
5260 | ~IEEE80211_CHAN_NO_HT40; | 5033 | channel[index].flags |= |
5261 | band_chan_arr[index].flags |= | 5034 | (IEEE80211_CHAN_RADAR | |
5262 | IEEE80211_CHAN_NO_HT40PLUS; | 5035 | IEEE80211_CHAN_NO_IR); |
5263 | } else { | 5036 | if (chaninfo & WL_CHAN_PASSIVE) |
5264 | /* It should be one of | 5037 | channel[index].flags |= |
5265 | * IEEE80211_CHAN_NO_HT40 or | 5038 | IEEE80211_CHAN_NO_IR; |
5266 | * IEEE80211_CHAN_NO_HT40PLUS | ||
5267 | */ | ||
5268 | band_chan_arr[index].flags &= | ||
5269 | ~IEEE80211_CHAN_NO_HT40; | ||
5270 | if (ht40_flag == IEEE80211_CHAN_NO_HT40) | ||
5271 | band_chan_arr[index].flags |= | ||
5272 | IEEE80211_CHAN_NO_HT40MINUS; | ||
5273 | } | ||
5274 | } else { | ||
5275 | /* disable other bandwidths for now as mentioned | ||
5276 | * order assure they are enabled for subsequent | ||
5277 | * chanspecs. | ||
5278 | */ | ||
5279 | band_chan_arr[index].flags = | ||
5280 | IEEE80211_CHAN_NO_HT40 | | ||
5281 | IEEE80211_CHAN_NO_80MHZ; | ||
5282 | ch.bw = BRCMU_CHAN_BW_20; | ||
5283 | cfg->d11inf.encchspec(&ch); | ||
5284 | channel = ch.chspec; | ||
5285 | err = brcmf_fil_bsscfg_int_get(ifp, | ||
5286 | "per_chan_info", | ||
5287 | &channel); | ||
5288 | if (!err) { | ||
5289 | if (channel & WL_CHAN_RADAR) | ||
5290 | band_chan_arr[index].flags |= | ||
5291 | (IEEE80211_CHAN_RADAR | | ||
5292 | IEEE80211_CHAN_NO_IR); | ||
5293 | if (channel & WL_CHAN_PASSIVE) | ||
5294 | band_chan_arr[index].flags |= | ||
5295 | IEEE80211_CHAN_NO_IR; | ||
5296 | } | ||
5297 | } | 5039 | } |
5298 | if (!update) | ||
5299 | (*n_cnt)++; | ||
5300 | } | 5040 | } |
5041 | if (index == band->n_channels) | ||
5042 | band->n_channels++; | ||
5301 | } | 5043 | } |
5302 | exit: | 5044 | kfree(pbuf); |
5045 | return 0; | ||
5046 | |||
5047 | fail_band2g: | ||
5048 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); | ||
5049 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]); | ||
5050 | wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; | ||
5051 | fail_pbuf: | ||
5303 | kfree(pbuf); | 5052 | kfree(pbuf); |
5304 | return err; | 5053 | return err; |
5305 | } | 5054 | } |
5306 | 5055 | ||
5056 | static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) | ||
5057 | { | ||
5058 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | ||
5059 | struct ieee80211_supported_band *band; | ||
5060 | struct brcmf_fil_bwcap_le band_bwcap; | ||
5061 | struct brcmf_chanspec_list *list; | ||
5062 | u8 *pbuf; | ||
5063 | u32 val; | ||
5064 | int err; | ||
5065 | struct brcmu_chan ch; | ||
5066 | u32 num_chan; | ||
5067 | int i, j; | ||
5068 | |||
5069 | /* verify support for bw_cap command */ | ||
5070 | val = WLC_BAND_5G; | ||
5071 | err = brcmf_fil_iovar_int_get(ifp, "bw_cap", &val); | ||
5072 | |||
5073 | if (!err) { | ||
5074 | /* only set 2G bandwidth using bw_cap command */ | ||
5075 | band_bwcap.band = cpu_to_le32(WLC_BAND_2G); | ||
5076 | band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ); | ||
5077 | err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap, | ||
5078 | sizeof(band_bwcap)); | ||
5079 | } else { | ||
5080 | brcmf_dbg(INFO, "fallback to mimo_bw_cap\n"); | ||
5081 | val = WLC_N_BW_40ALL; | ||
5082 | err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val); | ||
5083 | } | ||
5084 | |||
5085 | if (!err) { | ||
5086 | /* update channel info in 2G band */ | ||
5087 | pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); | ||
5088 | |||
5089 | if (pbuf == NULL) | ||
5090 | return -ENOMEM; | ||
5091 | |||
5092 | ch.band = BRCMU_CHAN_BAND_2G; | ||
5093 | ch.bw = BRCMU_CHAN_BW_40; | ||
5094 | ch.chnum = 0; | ||
5095 | cfg->d11inf.encchspec(&ch); | ||
5096 | |||
5097 | /* pass encoded chanspec in query */ | ||
5098 | *(__le16 *)pbuf = cpu_to_le16(ch.chspec); | ||
5099 | |||
5100 | err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf, | ||
5101 | BRCMF_DCMD_MEDLEN); | ||
5102 | if (err) { | ||
5103 | brcmf_err("get chanspecs error (%d)\n", err); | ||
5104 | kfree(pbuf); | ||
5105 | return err; | ||
5106 | } | ||
5107 | |||
5108 | band = cfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ]; | ||
5109 | list = (struct brcmf_chanspec_list *)pbuf; | ||
5110 | num_chan = le32_to_cpu(list->count); | ||
5111 | for (i = 0; i < num_chan; i++) { | ||
5112 | ch.chspec = (u16)le32_to_cpu(list->element[i]); | ||
5113 | cfg->d11inf.decchspec(&ch); | ||
5114 | if (WARN_ON(ch.band != BRCMU_CHAN_BAND_2G)) | ||
5115 | continue; | ||
5116 | if (WARN_ON(ch.bw != BRCMU_CHAN_BW_40)) | ||
5117 | continue; | ||
5118 | for (j = 0; j < band->n_channels; j++) { | ||
5119 | if (band->channels[j].hw_value == ch.chnum) | ||
5120 | break; | ||
5121 | } | ||
5122 | if (WARN_ON(j == band->n_channels)) | ||
5123 | continue; | ||
5124 | |||
5125 | brcmf_update_bw40_channel_flag(&band->channels[j], &ch); | ||
5126 | } | ||
5127 | } | ||
5128 | return err; | ||
5129 | } | ||
5130 | |||
5307 | static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) | 5131 | static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[]) |
5308 | { | 5132 | { |
5309 | u32 band, mimo_bwcap; | 5133 | u32 band, mimo_bwcap; |
@@ -5394,44 +5218,19 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band, | |||
5394 | band->vht_cap.vht_mcs.tx_mcs_map = mcs_map; | 5218 | band->vht_cap.vht_mcs.tx_mcs_map = mcs_map; |
5395 | } | 5219 | } |
5396 | 5220 | ||
5397 | static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | 5221 | static int brcmf_setup_wiphybands(struct wiphy *wiphy) |
5398 | { | 5222 | { |
5223 | struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); | ||
5399 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | 5224 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
5400 | struct wiphy *wiphy; | ||
5401 | s32 phy_list; | ||
5402 | u32 band_list[3]; | ||
5403 | u32 nmode = 0; | 5225 | u32 nmode = 0; |
5404 | u32 vhtmode = 0; | 5226 | u32 vhtmode = 0; |
5405 | u32 bw_cap[2] = { 0, 0 }; | 5227 | u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT }; |
5406 | u32 rxchain; | 5228 | u32 rxchain; |
5407 | u32 nchain; | 5229 | u32 nchain; |
5408 | s8 phy; | 5230 | int err; |
5409 | s32 err; | ||
5410 | u32 nband; | ||
5411 | s32 i; | 5231 | s32 i; |
5412 | struct ieee80211_supported_band *bands[2] = { NULL, NULL }; | ||
5413 | struct ieee80211_supported_band *band; | 5232 | struct ieee80211_supported_band *band; |
5414 | 5233 | ||
5415 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST, | ||
5416 | &phy_list, sizeof(phy_list)); | ||
5417 | if (err) { | ||
5418 | brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err); | ||
5419 | return err; | ||
5420 | } | ||
5421 | |||
5422 | phy = ((char *)&phy_list)[0]; | ||
5423 | brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy); | ||
5424 | |||
5425 | |||
5426 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, | ||
5427 | &band_list, sizeof(band_list)); | ||
5428 | if (err) { | ||
5429 | brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err); | ||
5430 | return err; | ||
5431 | } | ||
5432 | brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n", | ||
5433 | band_list[0], band_list[1], band_list[2]); | ||
5434 | |||
5435 | (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode); | 5234 | (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode); |
5436 | err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); | 5235 | err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); |
5437 | if (err) { | 5236 | if (err) { |
@@ -5453,44 +5252,129 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg) | |||
5453 | } | 5252 | } |
5454 | brcmf_dbg(INFO, "nchain=%d\n", nchain); | 5253 | brcmf_dbg(INFO, "nchain=%d\n", nchain); |
5455 | 5254 | ||
5456 | err = brcmf_construct_reginfo(cfg, bw_cap); | 5255 | err = brcmf_construct_chaninfo(cfg, bw_cap); |
5457 | if (err) { | 5256 | if (err) { |
5458 | brcmf_err("brcmf_construct_reginfo failed (%d)\n", err); | 5257 | brcmf_err("brcmf_construct_chaninfo failed (%d)\n", err); |
5459 | return err; | 5258 | return err; |
5460 | } | 5259 | } |
5461 | 5260 | ||
5462 | nband = band_list[0]; | 5261 | wiphy = cfg_to_wiphy(cfg); |
5463 | 5262 | for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) { | |
5464 | for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) { | 5263 | band = wiphy->bands[i]; |
5465 | band = NULL; | 5264 | if (band == NULL) |
5466 | if ((band_list[i] == WLC_BAND_5G) && | ||
5467 | (__wl_band_5ghz_a.n_channels > 0)) | ||
5468 | band = &__wl_band_5ghz_a; | ||
5469 | else if ((band_list[i] == WLC_BAND_2G) && | ||
5470 | (__wl_band_2ghz.n_channels > 0)) | ||
5471 | band = &__wl_band_2ghz; | ||
5472 | else | ||
5473 | continue; | 5265 | continue; |
5474 | 5266 | ||
5475 | if (nmode) | 5267 | if (nmode) |
5476 | brcmf_update_ht_cap(band, bw_cap, nchain); | 5268 | brcmf_update_ht_cap(band, bw_cap, nchain); |
5477 | if (vhtmode) | 5269 | if (vhtmode) |
5478 | brcmf_update_vht_cap(band, bw_cap, nchain); | 5270 | brcmf_update_vht_cap(band, bw_cap, nchain); |
5479 | bands[band->band] = band; | ||
5480 | } | 5271 | } |
5481 | 5272 | ||
5482 | wiphy = cfg_to_wiphy(cfg); | 5273 | return 0; |
5483 | wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ]; | ||
5484 | wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ]; | ||
5485 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); | ||
5486 | |||
5487 | return err; | ||
5488 | } | 5274 | } |
5489 | 5275 | ||
5276 | static const struct ieee80211_iface_limit brcmf_iface_limits[] = { | ||
5277 | { | ||
5278 | .max = 2, | ||
5279 | .types = BIT(NL80211_IFTYPE_STATION) | | ||
5280 | BIT(NL80211_IFTYPE_ADHOC) | | ||
5281 | BIT(NL80211_IFTYPE_AP) | ||
5282 | }, | ||
5283 | { | ||
5284 | .max = 1, | ||
5285 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5286 | BIT(NL80211_IFTYPE_P2P_GO) | ||
5287 | }, | ||
5288 | { | ||
5289 | .max = 1, | ||
5290 | .types = BIT(NL80211_IFTYPE_P2P_DEVICE) | ||
5291 | } | ||
5292 | }; | ||
5293 | static struct ieee80211_iface_combination brcmf_iface_combos[] = { | ||
5294 | { | ||
5295 | .max_interfaces = BRCMF_IFACE_MAX_CNT, | ||
5296 | .num_different_channels = 1, | ||
5297 | .n_limits = ARRAY_SIZE(brcmf_iface_limits), | ||
5298 | .limits = brcmf_iface_limits | ||
5299 | } | ||
5300 | }; | ||
5301 | |||
5302 | static const struct ieee80211_txrx_stypes | ||
5303 | brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { | ||
5304 | [NL80211_IFTYPE_STATION] = { | ||
5305 | .tx = 0xffff, | ||
5306 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
5307 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
5308 | }, | ||
5309 | [NL80211_IFTYPE_P2P_CLIENT] = { | ||
5310 | .tx = 0xffff, | ||
5311 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
5312 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
5313 | }, | ||
5314 | [NL80211_IFTYPE_P2P_GO] = { | ||
5315 | .tx = 0xffff, | ||
5316 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
5317 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
5318 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
5319 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
5320 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
5321 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
5322 | BIT(IEEE80211_STYPE_ACTION >> 4) | ||
5323 | }, | ||
5324 | [NL80211_IFTYPE_P2P_DEVICE] = { | ||
5325 | .tx = 0xffff, | ||
5326 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
5327 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
5328 | } | ||
5329 | }; | ||
5490 | 5330 | ||
5491 | static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg) | 5331 | static void brcmf_wiphy_pno_params(struct wiphy *wiphy) |
5492 | { | 5332 | { |
5493 | return brcmf_update_wiphybands(cfg); | 5333 | /* scheduled scan settings */ |
5334 | wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; | ||
5335 | wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; | ||
5336 | wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | ||
5337 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
5338 | } | ||
5339 | |||
5340 | static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) | ||
5341 | { | ||
5342 | struct ieee80211_iface_combination ifc_combo; | ||
5343 | wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; | ||
5344 | wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | ||
5345 | wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; | ||
5346 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
5347 | BIT(NL80211_IFTYPE_ADHOC) | | ||
5348 | BIT(NL80211_IFTYPE_AP) | | ||
5349 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5350 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
5351 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
5352 | /* need VSDB firmware feature for concurrent channels */ | ||
5353 | ifc_combo = brcmf_iface_combos[0]; | ||
5354 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) | ||
5355 | ifc_combo.num_different_channels = 2; | ||
5356 | wiphy->iface_combinations = kmemdup(&ifc_combo, | ||
5357 | sizeof(ifc_combo), | ||
5358 | GFP_KERNEL); | ||
5359 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); | ||
5360 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
5361 | wiphy->cipher_suites = __wl_cipher_suites; | ||
5362 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | ||
5363 | wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT | | ||
5364 | WIPHY_FLAG_OFFCHAN_TX | | ||
5365 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | | ||
5366 | WIPHY_FLAG_SUPPORTS_TDLS; | ||
5367 | if (!brcmf_roamoff) | ||
5368 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; | ||
5369 | wiphy->mgmt_stypes = brcmf_txrx_stypes; | ||
5370 | wiphy->max_remain_on_channel_duration = 5000; | ||
5371 | brcmf_wiphy_pno_params(wiphy); | ||
5372 | |||
5373 | /* vendor commands/events support */ | ||
5374 | wiphy->vendor_commands = brcmf_vendor_cmds; | ||
5375 | wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1; | ||
5376 | |||
5377 | return brcmf_setup_wiphybands(wiphy); | ||
5494 | } | 5378 | } |
5495 | 5379 | ||
5496 | static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | 5380 | static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) |
@@ -5528,9 +5412,6 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | |||
5528 | NULL, NULL); | 5412 | NULL, NULL); |
5529 | if (err) | 5413 | if (err) |
5530 | goto default_conf_out; | 5414 | goto default_conf_out; |
5531 | err = brcmf_dongle_probecap(cfg); | ||
5532 | if (err) | ||
5533 | goto default_conf_out; | ||
5534 | 5415 | ||
5535 | brcmf_configure_arp_offload(ifp, true); | 5416 | brcmf_configure_arp_offload(ifp, true); |
5536 | 5417 | ||
@@ -5658,3 +5539,150 @@ int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, | |||
5658 | vif_event_equals(event, action), timeout); | 5539 | vif_event_equals(event, action), timeout); |
5659 | } | 5540 | } |
5660 | 5541 | ||
5542 | static void brcmf_free_wiphy(struct wiphy *wiphy) | ||
5543 | { | ||
5544 | kfree(wiphy->iface_combinations); | ||
5545 | if (wiphy->bands[IEEE80211_BAND_2GHZ]) { | ||
5546 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); | ||
5547 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]); | ||
5548 | } | ||
5549 | if (wiphy->bands[IEEE80211_BAND_5GHZ]) { | ||
5550 | kfree(wiphy->bands[IEEE80211_BAND_5GHZ]->channels); | ||
5551 | kfree(wiphy->bands[IEEE80211_BAND_5GHZ]); | ||
5552 | } | ||
5553 | wiphy_free(wiphy); | ||
5554 | } | ||
5555 | |||
5556 | struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | ||
5557 | struct device *busdev) | ||
5558 | { | ||
5559 | struct net_device *ndev = drvr->iflist[0]->ndev; | ||
5560 | struct brcmf_cfg80211_info *cfg; | ||
5561 | struct wiphy *wiphy; | ||
5562 | struct brcmf_cfg80211_vif *vif; | ||
5563 | struct brcmf_if *ifp; | ||
5564 | s32 err = 0; | ||
5565 | s32 io_type; | ||
5566 | u16 *cap = NULL; | ||
5567 | |||
5568 | if (!ndev) { | ||
5569 | brcmf_err("ndev is invalid\n"); | ||
5570 | return NULL; | ||
5571 | } | ||
5572 | |||
5573 | ifp = netdev_priv(ndev); | ||
5574 | wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info)); | ||
5575 | if (!wiphy) { | ||
5576 | brcmf_err("Could not allocate wiphy device\n"); | ||
5577 | return NULL; | ||
5578 | } | ||
5579 | set_wiphy_dev(wiphy, busdev); | ||
5580 | |||
5581 | cfg = wiphy_priv(wiphy); | ||
5582 | cfg->wiphy = wiphy; | ||
5583 | cfg->pub = drvr; | ||
5584 | init_vif_event(&cfg->vif_event); | ||
5585 | INIT_LIST_HEAD(&cfg->vif_list); | ||
5586 | |||
5587 | vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false); | ||
5588 | if (IS_ERR(vif)) | ||
5589 | goto wiphy_out; | ||
5590 | |||
5591 | vif->ifp = ifp; | ||
5592 | vif->wdev.netdev = ndev; | ||
5593 | ndev->ieee80211_ptr = &vif->wdev; | ||
5594 | SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy)); | ||
5595 | |||
5596 | err = wl_init_priv(cfg); | ||
5597 | if (err) { | ||
5598 | brcmf_err("Failed to init iwm_priv (%d)\n", err); | ||
5599 | brcmf_free_vif(vif); | ||
5600 | goto wiphy_out; | ||
5601 | } | ||
5602 | ifp->vif = vif; | ||
5603 | |||
5604 | /* determine d11 io type before wiphy setup */ | ||
5605 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, &io_type); | ||
5606 | if (err) { | ||
5607 | brcmf_err("Failed to get D11 version (%d)\n", err); | ||
5608 | goto priv_out; | ||
5609 | } | ||
5610 | cfg->d11inf.io_type = (u8)io_type; | ||
5611 | brcmu_d11_attach(&cfg->d11inf); | ||
5612 | |||
5613 | err = brcmf_setup_wiphy(wiphy, ifp); | ||
5614 | if (err < 0) | ||
5615 | goto priv_out; | ||
5616 | |||
5617 | brcmf_dbg(INFO, "Registering custom regulatory\n"); | ||
5618 | wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; | ||
5619 | wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom); | ||
5620 | |||
5621 | /* firmware defaults to 40MHz disabled in 2G band. We signal | ||
5622 | * cfg80211 here that we do and have it decide we can enable | ||
5623 | * it. But first check if device does support 2G operation. | ||
5624 | */ | ||
5625 | if (wiphy->bands[IEEE80211_BAND_2GHZ]) { | ||
5626 | cap = &wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap.cap; | ||
5627 | *cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
5628 | } | ||
5629 | err = wiphy_register(wiphy); | ||
5630 | if (err < 0) { | ||
5631 | brcmf_err("Could not register wiphy device (%d)\n", err); | ||
5632 | goto priv_out; | ||
5633 | } | ||
5634 | |||
5635 | /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(), | ||
5636 | * setup 40MHz in 2GHz band and enable OBSS scanning. | ||
5637 | */ | ||
5638 | if (cap && (*cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) { | ||
5639 | err = brcmf_enable_bw40_2g(cfg); | ||
5640 | if (!err) | ||
5641 | err = brcmf_fil_iovar_int_set(ifp, "obss_coex", | ||
5642 | BRCMF_OBSS_COEX_AUTO); | ||
5643 | else | ||
5644 | *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
5645 | } | ||
5646 | |||
5647 | err = brcmf_p2p_attach(cfg); | ||
5648 | if (err) { | ||
5649 | brcmf_err("P2P initilisation failed (%d)\n", err); | ||
5650 | goto wiphy_unreg_out; | ||
5651 | } | ||
5652 | err = brcmf_btcoex_attach(cfg); | ||
5653 | if (err) { | ||
5654 | brcmf_err("BT-coex initialisation failed (%d)\n", err); | ||
5655 | brcmf_p2p_detach(&cfg->p2p); | ||
5656 | goto wiphy_unreg_out; | ||
5657 | } | ||
5658 | |||
5659 | err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1); | ||
5660 | if (err) { | ||
5661 | brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err); | ||
5662 | wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS; | ||
5663 | } | ||
5664 | |||
5665 | return cfg; | ||
5666 | |||
5667 | wiphy_unreg_out: | ||
5668 | wiphy_unregister(cfg->wiphy); | ||
5669 | priv_out: | ||
5670 | wl_deinit_priv(cfg); | ||
5671 | brcmf_free_vif(vif); | ||
5672 | wiphy_out: | ||
5673 | brcmf_free_wiphy(wiphy); | ||
5674 | return NULL; | ||
5675 | } | ||
5676 | |||
5677 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | ||
5678 | { | ||
5679 | if (!cfg) | ||
5680 | return; | ||
5681 | |||
5682 | WARN_ON(!list_empty(&cfg->vif_list)); | ||
5683 | wiphy_unregister(cfg->wiphy); | ||
5684 | brcmf_btcoex_detach(cfg); | ||
5685 | brcmf_p2p_detach(&cfg->p2p); | ||
5686 | wl_deinit_priv(cfg); | ||
5687 | brcmf_free_wiphy(cfg->wiphy); | ||
5688 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index af8ba64ace39..1b474828d5b8 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -4707,41 +4707,6 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
4707 | return err; | 4707 | return err; |
4708 | } | 4708 | } |
4709 | 4709 | ||
4710 | static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc) | ||
4711 | { | ||
4712 | uint unit; | ||
4713 | unit = wlc->pub->unit; | ||
4714 | |||
4715 | if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) { | ||
4716 | /* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */ | ||
4717 | wlc->band->antgain = 8; | ||
4718 | } else if (wlc->band->antgain == -1) { | ||
4719 | wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" | ||
4720 | " srom, using 2dB\n", unit, __func__); | ||
4721 | wlc->band->antgain = 8; | ||
4722 | } else { | ||
4723 | s8 gain, fract; | ||
4724 | /* Older sroms specified gain in whole dbm only. In order | ||
4725 | * be able to specify qdbm granularity and remain backward | ||
4726 | * compatible the whole dbms are now encoded in only | ||
4727 | * low 6 bits and remaining qdbms are encoded in the hi 2 bits. | ||
4728 | * 6 bit signed number ranges from -32 - 31. | ||
4729 | * | ||
4730 | * Examples: | ||
4731 | * 0x1 = 1 db, | ||
4732 | * 0xc1 = 1.75 db (1 + 3 quarters), | ||
4733 | * 0x3f = -1 (-1 + 0 quarters), | ||
4734 | * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm. | ||
4735 | * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm. | ||
4736 | */ | ||
4737 | gain = wlc->band->antgain & 0x3f; | ||
4738 | gain <<= 2; /* Sign extend */ | ||
4739 | gain >>= 2; | ||
4740 | fract = (wlc->band->antgain & 0xc0) >> 6; | ||
4741 | wlc->band->antgain = 4 * gain + fract; | ||
4742 | } | ||
4743 | } | ||
4744 | |||
4745 | static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) | 4710 | static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) |
4746 | { | 4711 | { |
4747 | int aa; | 4712 | int aa; |
@@ -4780,8 +4745,6 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) | |||
4780 | else | 4745 | else |
4781 | wlc->band->antgain = sprom->antenna_gain.a0; | 4746 | wlc->band->antgain = sprom->antenna_gain.a0; |
4782 | 4747 | ||
4783 | brcms_c_attach_antgain_init(wlc); | ||
4784 | |||
4785 | return true; | 4748 | return true; |
4786 | } | 4749 | } |
4787 | 4750 | ||
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index d816270db3be..64d1a7ba040c 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | |||
@@ -17,32 +17,56 @@ | |||
17 | #ifndef _BRCM_HW_IDS_H_ | 17 | #ifndef _BRCM_HW_IDS_H_ |
18 | #define _BRCM_HW_IDS_H_ | 18 | #define _BRCM_HW_IDS_H_ |
19 | 19 | ||
20 | #define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ | 20 | #include <linux/pci_ids.h> |
21 | #include <linux/mmc/sdio_ids.h> | ||
22 | |||
23 | #define BRCM_USB_VENDOR_ID_BROADCOM 0x0a5c | ||
24 | #define BRCM_PCIE_VENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM | ||
25 | #define BRCM_SDIO_VENDOR_ID_BROADCOM SDIO_VENDOR_ID_BROADCOM | ||
26 | |||
27 | /* Chipcommon Core Chip IDs */ | ||
28 | #define BRCM_CC_43143_CHIP_ID 43143 | ||
29 | #define BRCM_CC_43235_CHIP_ID 43235 | ||
30 | #define BRCM_CC_43236_CHIP_ID 43236 | ||
31 | #define BRCM_CC_43238_CHIP_ID 43238 | ||
32 | #define BRCM_CC_43241_CHIP_ID 0x4324 | ||
33 | #define BRCM_CC_43242_CHIP_ID 43242 | ||
34 | #define BRCM_CC_4329_CHIP_ID 0x4329 | ||
35 | #define BRCM_CC_4330_CHIP_ID 0x4330 | ||
36 | #define BRCM_CC_4334_CHIP_ID 0x4334 | ||
37 | #define BRCM_CC_43362_CHIP_ID 43362 | ||
38 | #define BRCM_CC_4335_CHIP_ID 0x4335 | ||
39 | #define BRCM_CC_4339_CHIP_ID 0x4339 | ||
40 | #define BRCM_CC_4354_CHIP_ID 0x4354 | ||
41 | #define BRCM_CC_43566_CHIP_ID 43566 | ||
42 | #define BRCM_CC_43569_CHIP_ID 43569 | ||
43 | |||
44 | /* SDIO Device IDs */ | ||
45 | #define BRCM_SDIO_43143_DEVICE_ID BRCM_CC_43143_CHIP_ID | ||
46 | #define BRCM_SDIO_43241_DEVICE_ID BRCM_CC_43241_CHIP_ID | ||
47 | #define BRCM_SDIO_4329_DEVICE_ID BRCM_CC_4329_CHIP_ID | ||
48 | #define BRCM_SDIO_4330_DEVICE_ID BRCM_CC_4330_CHIP_ID | ||
49 | #define BRCM_SDIO_4334_DEVICE_ID BRCM_CC_4334_CHIP_ID | ||
50 | #define BRCM_SDIO_43362_DEVICE_ID BRCM_CC_43362_CHIP_ID | ||
51 | #define BRCM_SDIO_4335_4339_DEVICE_ID BRCM_CC_4335_CHIP_ID | ||
52 | #define BRCM_SDIO_4354_DEVICE_ID BRCM_CC_4354_CHIP_ID | ||
21 | 53 | ||
54 | /* USB Device IDs */ | ||
55 | #define BRCM_USB_43143_DEVICE_ID 0xbd1e | ||
56 | #define BRCM_USB_43236_DEVICE_ID 0xbd17 | ||
57 | #define BRCM_USB_43242_DEVICE_ID 0xbd1f | ||
58 | #define BRCM_USB_43569_DEVICE_ID 0xbd27 | ||
59 | #define BRCM_USB_BCMFW_DEVICE_ID 0x0bdc | ||
60 | |||
61 | /* brcmsmac IDs */ | ||
62 | #define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ | ||
22 | #define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ | 63 | #define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ |
23 | #define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */ | 64 | #define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */ |
24 | |||
25 | #define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ | 65 | #define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ |
26 | |||
27 | #define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ | 66 | #define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ |
28 | #define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ | 67 | #define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ |
29 | 68 | ||
30 | /* Chipcommon Core Chip IDs */ | ||
31 | #define BCM4313_CHIP_ID 0x4313 | 69 | #define BCM4313_CHIP_ID 0x4313 |
32 | #define BCM43143_CHIP_ID 43143 | ||
33 | #define BCM43224_CHIP_ID 43224 | 70 | #define BCM43224_CHIP_ID 43224 |
34 | #define BCM43225_CHIP_ID 43225 | ||
35 | #define BCM43235_CHIP_ID 43235 | ||
36 | #define BCM43236_CHIP_ID 43236 | ||
37 | #define BCM43238_CHIP_ID 43238 | ||
38 | #define BCM43241_CHIP_ID 0x4324 | ||
39 | #define BCM4329_CHIP_ID 0x4329 | ||
40 | #define BCM4330_CHIP_ID 0x4330 | ||
41 | #define BCM4331_CHIP_ID 0x4331 | ||
42 | #define BCM4334_CHIP_ID 0x4334 | ||
43 | #define BCM4335_CHIP_ID 0x4335 | ||
44 | #define BCM43362_CHIP_ID 43362 | ||
45 | #define BCM4339_CHIP_ID 0x4339 | ||
46 | #define BCM4354_CHIP_ID 0x4354 | ||
47 | 71 | ||
48 | #endif /* _BRCM_HW_IDS_H_ */ | 72 | #endif /* _BRCM_HW_IDS_H_ */ |