madwifi: improve reliability of the wds modes
[openwrt.git] / package / madwifi / patches / 384-hwdetect.patch
1 --- a/ath/if_ath.c
2 +++ b/ath/if_ath.c
3 @@ -62,6 +62,7 @@
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>
9  
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;
14  
15 +static const struct ath_hw_detect generic_hw_info = {
16 +       .vendor_name = "Unknown",
17 +       .card_name = "Generic",
18 +       .vendor = PCI_ANY_ID,
19 +       .id = PCI_ANY_ID,
20 +       .subvendor = PCI_ANY_ID,
21 +       .subid = PCI_ANY_ID
22 +};
23 +
24  static const char *hal_status_desc[] = {
25         "No error",
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);
29  #endif
30  
31 +       sc->sc_hwinfo = &generic_hw_info;
32 +
33         /* Allocate space for dynamically determined maximum VAP count */
34         sc->sc_bslot = 
35                 kmalloc(ath_maxvaps * sizeof(struct ieee80211vap*), GFP_KERNEL);
36 @@ -1507,6 +1519,28 @@ ath_vap_create(struct ieee80211com *ic, 
37         return vap;
38  }
39  
40 +void
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)
42 +{
43 +       int i;
44 +
45 +       for (i = 0; i < n_cards; i++) {
46 +               const struct ath_hw_detect *c = &cards[i];
47 +
48 +               if ((c->vendor != PCI_ANY_ID) && c->vendor != vendor)
49 +                       continue;
50 +               if ((c->id != PCI_ANY_ID) && c->id != id)
51 +                       continue;
52 +               if ((c->subvendor != PCI_ANY_ID) && c->subvendor != subvendor)
53 +                       continue;
54 +               if ((c->subid != PCI_ANY_ID) && c->subid != subid)
55 +                       continue;
56 +
57 +               sc->sc_hwinfo = c;
58 +               break;
59 +       }
60 +}
61 +
62  static void
63  ath_vap_delete(struct ieee80211vap *vap)
64  {
65 @@ -10818,6 +10852,12 @@ ath_ioctl(struct net_device *dev, struct
66   * is to add module parameters.
67   */
68  
69 +/* sysctls for hardware info */
70 +enum {
71 +       ATH_CARD_VENDOR,
72 +       ATH_CARD_NAME,
73 +};
74 +
75  /*
76   * Dynamic (i.e. per-device) sysctls.  These are automatically
77   * mirrored in /proc/sys.
78 @@ -10897,6 +10937,38 @@ ath_sysctl_get_intmit(struct ath_softc *
79  }
80  
81  static int
82 +ATH_SYSCTL_DECL(ath_sysctl_hwinfo, ctl, write, filp, buffer, lenp, ppos)
83 +{
84 +       struct ath_softc *sc = ctl->extra1;
85 +       struct ath_hal *ah = sc->sc_ah;
86 +       int ret = 0;
87 +
88 +       if (write)
89 +               return -EINVAL;
90 +
91 +       ATH_LOCK(sc);
92 +       switch((long)ctl->extra2) {
93 +       case ATH_CARD_VENDOR:
94 +               ctl->data = (char *)sc->sc_hwinfo->vendor_name;
95 +               break;
96 +       case ATH_CARD_NAME:
97 +               ctl->data = (char *)sc->sc_hwinfo->card_name;
98 +               break;
99 +       default:
100 +               ret = -EINVAL;
101 +               break;
102 +       }
103 +       if (ret == 0) {
104 +               ctl->maxlen = strlen(ctl->data);
105 +               ret = ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp,
106 +                               buffer, lenp, ppos);
107 +       }
108 +       ATH_UNLOCK(sc);
109 +
110 +       return ret;
111 +}
112 +
113 +static int
114  ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl, write, filp, buffer, lenp, ppos)
115  {
116         struct ath_softc *sc = ctl->extra1;
117 @@ -11176,6 +11248,24 @@ static int maxint = 0x7fffffff;                /* 32-b
118  
119  static const ctl_table ath_sysctl_template[] = {
120         { .ctl_name     = CTL_AUTO,
121 +         .procname     = "dev_vendor",
122 +         .mode         = 0644,
123 +         .proc_handler = ath_sysctl_hwinfo,
124 +         .strategy   = &sysctl_string,
125 +         .data         = "N/A",
126 +         .maxlen   = 1,
127 +         .extra2       = (void *)ATH_CARD_VENDOR,
128 +       },
129 +       { .ctl_name     = CTL_AUTO,
130 +         .procname     = "dev_name",
131 +         .mode         = 0644,
132 +         .proc_handler = ath_sysctl_hwinfo,
133 +         .strategy   = &sysctl_string,
134 +         .data         = "N/A",
135 +         .maxlen   = 1,
136 +         .extra2       = (void *)ATH_CARD_NAME,
137 +       },
138 +       { .ctl_name     = CTL_AUTO,
139           .procname     = "slottime",
140           .mode         = 0644,
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)
158  #endif
159  
160  #define        ATH_TIMEOUT     1000
161 @@ -469,6 +473,7 @@ struct ath_hal;
162  struct ath_desc;
163  struct ath_ratectrl;
164  struct ath_tx99;
165 +struct ath_hw_detect;
166  struct proc_dir_entry;
167  
168  /*
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;
174  
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);
178  
179  void ath_radar_detected(struct ath_softc *sc, const char* message);
180  
181 +struct ath_hw_detect {
182 +       const char *vendor_name;
183 +       const char *card_name;
184 +       u32 vendor;
185 +       u32 id;
186 +       u32 subvendor;
187 +       u32 subid;
188 +};
189 +
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);
191 +
192  #endif /* _DEV_ATH_ATHVAR_H */
193 --- a/ath/if_ath_ahb.c
194 +++ b/ath/if_ath_ahb.c
195 @@ -20,6 +20,7 @@
196  #include <linux/netdevice.h>
197  #include <linux/cache.h>
198  #include <linux/platform_device.h>
199 +#include <linux/pci.h>
200  
201  #include <asm/io.h>
202  #include <asm/uaccess.h>
203 @@ -181,12 +182,97 @@ exit_ath_wmac(u_int16_t wlanNum, struct 
204         return 0;
205  }
206  
207 +static const char ubnt[] = "Ubiquiti Networks";
208 +static const struct ath_hw_detect cards[] = {
209 +       {
210 +               .vendor_name = ubnt,
211 +               .card_name = "PowerStation2 (18V)",
212 +               .vendor = PCI_ANY_ID,
213 +               .id = PCI_ANY_ID,
214 +               .subvendor = PCI_ANY_ID,
215 +               .subid = 0xb102,
216 +       },
217 +       {
218 +               .vendor_name = ubnt,
219 +               .card_name = "PowerStation2 (16D)",
220 +               .vendor = PCI_ANY_ID,
221 +               .id = PCI_ANY_ID,
222 +               .subvendor = PCI_ANY_ID,
223 +               .subid = 0xb202,
224 +       },
225 +       {
226 +               .vendor_name = ubnt,
227 +               .card_name = "PowerStation2 (EXT)",
228 +               .vendor = PCI_ANY_ID,
229 +               .id = PCI_ANY_ID,
230 +               .subvendor = PCI_ANY_ID,
231 +               .subid = 0xb302,
232 +       },
233 +       {
234 +               .vendor_name = ubnt,
235 +               .card_name = "PowerStation5 (22V)",
236 +               .vendor = PCI_ANY_ID,
237 +               .id = PCI_ANY_ID,
238 +               .subvendor = PCI_ANY_ID,
239 +               .subid = 0xb105,
240 +       },
241 +       {
242 +               .vendor_name = ubnt,
243 +               .card_name = "PowerStation5 (EXT)",
244 +               .vendor = PCI_ANY_ID,
245 +               .id = PCI_ANY_ID,
246 +               .subvendor = PCI_ANY_ID,
247 +               .subid = 0xb305,
248 +       },
249 +       {
250 +               .vendor_name = ubnt,
251 +               .card_name = "WispStation5",
252 +               .vendor = PCI_ANY_ID,
253 +               .id = PCI_ANY_ID,
254 +               .subvendor = PCI_ANY_ID,
255 +               .subid = 0xa105,
256 +       },
257 +       {
258 +               .vendor_name = ubnt,
259 +               .card_name = "LiteStation2",
260 +               .vendor = PCI_ANY_ID,
261 +               .id = PCI_ANY_ID,
262 +               .subvendor = PCI_ANY_ID,
263 +               .subid = 0xa002,
264 +       },
265 +       {
266 +               .vendor_name = ubnt,
267 +               .card_name = "LiteStation5",
268 +               .vendor = PCI_ANY_ID,
269 +               .id = PCI_ANY_ID,
270 +               .subvendor = PCI_ANY_ID,
271 +               .subid = 0xa005,
272 +       },
273 +       {
274 +               .vendor_name = ubnt,
275 +               .card_name = "NanoStation2",
276 +               .vendor = PCI_ANY_ID,
277 +               .id = PCI_ANY_ID,
278 +               .subvendor = PCI_ANY_ID,
279 +               .subid = 0xc002,
280 +       },
281 +       {
282 +               .vendor_name = ubnt,
283 +               .card_name = "NanoStation5",
284 +               .vendor = PCI_ANY_ID,
285 +               .id = PCI_ANY_ID,
286 +               .subvendor = PCI_ANY_ID,
287 +               .subid = 0xc005,
288 +       },
289 +};
290 +
291  static int
292  init_ath_wmac(u_int16_t devid, u_int16_t wlanNum, struct ar531x_config *config)
293  {
294         const char *athname;
295         struct net_device *dev;
296         struct ath_ahb_softc *sc;
297 +       u16 *radio_data;
298  
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;
306 +       if (radio_data) {
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);
313 +       }
314 +
315         return 0;
316  
317   bad4: