4 #include <linux/if_arp.h>
5 #include <linux/rtnetlink.h>
6 #include <linux/time.h>
7 +#include <linux/pci.h>
8 #include <asm/uaccess.h>
10 #include "if_ethersubr.h" /* for ETHER_IS_MULTICAST */
11 @@ -401,6 +402,15 @@ static int outdoor = -1;
12 static int xchanmode = -1;
13 static int beacon_cal = 1;
15 +static const struct ath_hw_detect generic_hw_info = {
16 + .vendor_name = "Unknown",
17 + .card_name = "Generic",
18 + .vendor = PCI_ANY_ID,
20 + .subvendor = PCI_ANY_ID,
24 static const char *hal_status_desc[] = {
26 "No hardware present or device not yet supported",
27 @@ -542,6 +552,8 @@ ath_attach(u_int16_t devid, struct net_d
28 DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
31 + sc->sc_hwinfo = &generic_hw_info;
33 /* Allocate space for dynamically determined maximum VAP count */
35 kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL);
36 @@ -1508,6 +1520,28 @@ ath_vap_create(struct ieee80211com *ic,
41 +ath_hw_detect(struct ath_softc *sc, const struct ath_hw_detect *cards, int n_cards, u32 vendor, u32 id, u32 subvendor, u32 subid)
45 + for (i = 0; i < n_cards; i++) {
46 + const struct ath_hw_detect *c = &cards[i];
48 + if ((c->vendor != PCI_ANY_ID) && c->vendor != vendor)
50 + if ((c->id != PCI_ANY_ID) && c->id != id)
52 + if ((c->subvendor != PCI_ANY_ID) && c->subvendor != subvendor)
54 + if ((c->subid != PCI_ANY_ID) && c->subid != subid)
63 ath_vap_delete(struct ieee80211vap *vap)
65 @@ -10821,6 +10855,12 @@ ath_ioctl(struct net_device *dev, struct
66 * is to add module parameters.
69 +/* sysctls for hardware info */
76 * Dynamic (i.e. per-device) sysctls. These are automatically
77 * mirrored in /proc/sys.
78 @@ -10900,6 +10940,38 @@ ath_sysctl_get_intmit(struct ath_softc *
82 +ATH_SYSCTL_DECL(ath_sysctl_hwinfo, ctl, write, filp, buffer, lenp, ppos)
84 + struct ath_softc *sc = ctl->extra1;
85 + struct ath_hal *ah = sc->sc_ah;
92 + switch((long)ctl->extra2) {
93 + case ATH_CARD_VENDOR:
94 + ctl->data = (char *)sc->sc_hwinfo->vendor_name;
97 + ctl->data = (char *)sc->sc_hwinfo->card_name;
104 + ctl->maxlen = strlen(ctl->data);
105 + ret = ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp,
106 + buffer, lenp, ppos);
114 ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
116 struct ath_softc *sc = ctl->extra1;
117 @@ -11179,6 +11251,24 @@ static int maxint = 0x7fffffff; /* 32-b
119 static const ctl_table ath_sysctl_template[] = {
120 { .ctl_name = CTL_AUTO,
121 + .procname = "dev_vendor",
123 + .proc_handler = ath_sysctl_hwinfo,
124 + .strategy = &sysctl_string,
127 + .extra2 = (void *)ATH_CARD_VENDOR,
129 + { .ctl_name = CTL_AUTO,
130 + .procname = "dev_name",
132 + .proc_handler = ath_sysctl_hwinfo,
133 + .strategy = &sysctl_string,
136 + .extra2 = (void *)ATH_CARD_NAME,
138 + { .ctl_name = CTL_AUTO,
139 .procname = "slottime",
141 .proc_handler = ath_sysctl_halparam,
142 --- a/ath/if_athvar.h
143 +++ b/ath/if_athvar.h
144 @@ -168,12 +168,16 @@ static inline struct net_device *_alloc_
145 void __user *buffer, size_t *lenp)
146 #define ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \
147 proc_dointvec(ctl, write, filp, buffer, lenp)
148 +#define ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
149 + proc_dostring(ctl, write, filp, buffer, lenp)
150 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) */
151 #define ATH_SYSCTL_DECL(f, ctl, write, filp, buffer, lenp, ppos) \
152 f(ctl_table *ctl, int write, struct file *filp, \
153 void __user *buffer, size_t *lenp, loff_t *ppos)
154 #define ATH_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \
155 proc_dointvec(ctl, write, filp, buffer, lenp, ppos)
156 +#define ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \
157 + proc_dostring(ctl, write, filp, buffer, lenp, ppos)
160 #define ATH_TIMEOUT 1000
161 @@ -469,6 +473,7 @@ struct ath_hal;
165 +struct ath_hw_detect;
166 struct proc_dir_entry;
169 @@ -629,6 +634,7 @@ struct ath_softc {
170 struct ath_ratectrl *sc_rc; /* tx rate control support */
171 struct ath_tx99 *sc_tx99; /* tx99 support */
172 void (*sc_setdefantenna)(struct ath_softc *, u_int);
173 + const struct ath_hw_detect *sc_hwinfo;
175 unsigned int sc_invalid:1; /* being detached */
176 unsigned int sc_mrretry:1; /* multi-rate retry support */
177 @@ -929,4 +935,15 @@ int ar_device(int devid);
179 void ath_radar_detected(struct ath_softc *sc, const char* message);
181 +struct ath_hw_detect {
182 + const char *vendor_name;
183 + const char *card_name;
190 +extern void ath_hw_detect(struct ath_softc *sc, const struct ath_hw_detect *cards, int n_cards, u32 vendor, u32 id, u32 subvendor, u32 subid);
192 #endif /* _DEV_ATH_ATHVAR_H */
193 --- a/ath/if_ath_ahb.c
194 +++ b/ath/if_ath_ahb.c
196 #include <linux/netdevice.h>
197 #include <linux/cache.h>
198 #include <linux/platform_device.h>
199 +#include <linux/pci.h>
202 #include <asm/uaccess.h>
203 @@ -181,12 +182,97 @@ exit_ath_wmac(u_int16_t wlanNum, struct
207 +static const char ubnt[] = "Ubiquiti Networks";
208 +static const struct ath_hw_detect cards[] = {
210 + .vendor_name = ubnt,
211 + .card_name = "PowerStation2 (18V)",
212 + .vendor = PCI_ANY_ID,
214 + .subvendor = PCI_ANY_ID,
218 + .vendor_name = ubnt,
219 + .card_name = "PowerStation2 (16D)",
220 + .vendor = PCI_ANY_ID,
222 + .subvendor = PCI_ANY_ID,
226 + .vendor_name = ubnt,
227 + .card_name = "PowerStation2 (EXT)",
228 + .vendor = PCI_ANY_ID,
230 + .subvendor = PCI_ANY_ID,
234 + .vendor_name = ubnt,
235 + .card_name = "PowerStation5 (22V)",
236 + .vendor = PCI_ANY_ID,
238 + .subvendor = PCI_ANY_ID,
242 + .vendor_name = ubnt,
243 + .card_name = "PowerStation5 (EXT)",
244 + .vendor = PCI_ANY_ID,
246 + .subvendor = PCI_ANY_ID,
250 + .vendor_name = ubnt,
251 + .card_name = "WispStation5",
252 + .vendor = PCI_ANY_ID,
254 + .subvendor = PCI_ANY_ID,
258 + .vendor_name = ubnt,
259 + .card_name = "LiteStation2",
260 + .vendor = PCI_ANY_ID,
262 + .subvendor = PCI_ANY_ID,
266 + .vendor_name = ubnt,
267 + .card_name = "LiteStation5",
268 + .vendor = PCI_ANY_ID,
270 + .subvendor = PCI_ANY_ID,
274 + .vendor_name = ubnt,
275 + .card_name = "NanoStation2",
276 + .vendor = PCI_ANY_ID,
278 + .subvendor = PCI_ANY_ID,
282 + .vendor_name = ubnt,
283 + .card_name = "NanoStation5",
284 + .vendor = PCI_ANY_ID,
286 + .subvendor = PCI_ANY_ID,
292 init_ath_wmac(u_int16_t devid, u_int16_t wlanNum, struct ar531x_config *config)
295 struct net_device *dev;
296 struct ath_ahb_softc *sc;
299 if (((wlanNum != 0) && (wlanNum != 1)) ||
300 (sclist[wlanNum] != NULL))
301 @@ -248,6 +334,16 @@ init_ath_wmac(u_int16_t devid, u_int16_t
302 sc->aps_sc.sc_softled = 1; /* SoftLED over GPIO */
303 sc->aps_sc.sc_ledpin = config->board->sysLedGpio;
304 sc->aps_sc.sc_invalid = 0;
305 + radio_data = (u16 *) config->radio;
307 + u16 vendor, id, subvendor, subid;
308 + vendor = radio_data[1];
309 + id = radio_data[0];
310 + subvendor = radio_data[8];
311 + subid = radio_data[7];
312 + ath_hw_detect(&sc->aps_sc, cards, ARRAY_SIZE(cards), vendor, id, subvendor, subid);