no need to free_irq in remove, done in close
[openwrt.git] / package / acx-mac80211 / patches / 002-acx_vlynq.diff
1 diff -Nru 1/acx_struct.h 2/acx_struct.h
2 --- 1/acx_struct.h      2007-10-03 23:42:39.000000000 +0800
3 +++ 2/acx_struct.h      2007-10-06 01:15:32.000000000 +0800
4 @@ -1425,7 +1425,13 @@
5  
6         const u16       *io;            /* points to ACX100 or ACX111 PCI I/O register address set */
7  
8 +#ifdef CONFIG_PCI
9         struct pci_dev  *pdev;
10 +#endif
11 +#ifdef CONFIG_VLYNQ
12 +       struct vlynq_device     *vdev;
13 +#endif
14 +       struct device *bus_dev;
15  
16         unsigned long   membase;
17         unsigned long   membase2;
18 diff -Nru 1/pci.c 2/pci.c
19 --- 1/pci.c     2007-10-03 23:42:39.000000000 +0800
20 +++ 2/pci.c     2007-10-06 01:15:32.000000000 +0800
21 @@ -33,11 +33,15 @@
22  #include <linux/ethtool.h>
23  #include <linux/dma-mapping.h>
24  #include <linux/workqueue.h>
25 +#ifdef CONFIG_VLYNQ
26 +#include <linux/vlynq.h>
27 +#endif
28  
29  #include "acx.h"
30  
31  /***********************************************************************
32  */
33 +#ifdef CONFIG_PCI
34  #define PCI_TYPE               (PCI_USES_MEM | PCI_ADDR0 | PCI_NO_ACPI_WAKE)
35  #define PCI_ACX100_REGION1             0x01
36  #define PCI_ACX100_REGION1_SIZE                0x1000  /* Memory size - 4K bytes */
37 @@ -74,7 +78,7 @@
38  #define PCI_UNKNOWN    5
39  #define PCI_POWER_ERROR        -1
40  #endif
41 -
42 +#endif /* CONFIG_PCI */
43  /***********************************************************************
44  */
45  
46 @@ -87,12 +91,6 @@
47  static void acxpci_s_up(struct ieee80211_hw *hw);
48  static void acxpci_s_down(struct ieee80211_hw *hw);
49  
50 -void acxpci_put_devname(acx_device_t *adev, struct ethtool_drvinfo *info)
51 -{
52 -
53 -        strncpy(info->bus_info,pci_name(adev->pdev), ETHTOOL_BUSINFO_LEN);
54 -}
55 -
56  /***********************************************************************
57  ** Register access
58  **
59 @@ -605,12 +603,12 @@
60         snprintf(filename, sizeof(filename), "tiacx1%02dc%02X",
61                  IS_ACX111(adev) * 11, adev->radio_type);
62  
63 -       fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
64 +       fw_image = acx_s_read_fw(adev->bus_dev, filename, &file_size);
65         if (!fw_image) {
66                 adev->need_radio_fw = 1;
67                 filename[sizeof("tiacx1NN") - 1] = '\0';
68                 fw_image =
69 -                   acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
70 +                   acx_s_read_fw(adev->bus_dev, filename, &file_size);
71                 if (!fw_image) {
72                         FN_EXIT1(NOT_OK);
73                         return NOT_OK;
74 @@ -670,7 +668,7 @@
75  
76         snprintf(filename, sizeof(filename), "tiacx1%02dr%02X",
77                  IS_ACX111(adev) * 11, adev->radio_type);
78 -       radio_image = acx_s_read_fw(&adev->pdev->dev, filename, &size);
79 +       radio_image = acx_s_read_fw(adev->bus_dev, filename, &size);
80         if (!radio_image) {
81                 printk("acx: can't load radio module '%s'\n", filename);
82                 goto fail;
83 @@ -886,7 +884,9 @@
84  
85         acx_lock(adev, flags);
86  
87 +#ifdef CONFIG_PCI
88         acxpci_l_reset_mac(adev);
89 +#endif
90  
91         ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
92         if (!ecpu_ctrl) {
93 @@ -1426,6 +1426,7 @@
94  };
95  
96  
97 +#ifdef CONFIG_PCI
98  static int __devinit
99  acxpci_e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
100  {
101 @@ -1477,6 +1478,7 @@
102         /* acx_sem_lock(adev); */
103         adev->ieee = ieee;
104         adev->pdev = pdev;
105 +       adev->bus_dev = &pdev->dev;
106         adev->dev_type = DEVTYPE_PCI;
107  
108  /** Finished with private interface **/
109 @@ -1916,7 +1918,7 @@
110         return OK;
111  }
112  #endif /* CONFIG_PM */
113 -
114 +#endif /* CONFIG_PCI */
115  
116  /***********************************************************************
117  ** acxpci_s_up
118 @@ -1998,7 +2000,7 @@
119         /* then wait until interrupts have finished executing on other CPUs */
120         acx_lock(adev, flags);
121         disable_acx_irq(adev);
122 -        synchronize_irq(adev->pdev->irq);
123 +        synchronize_irq(adev->irq);
124         acx_unlock(adev, flags);
125  
126         /* we really don't want to have an asynchronous tasklet disturb us
127 @@ -3449,8 +3451,7 @@
128  {
129         void *ptr;
130  
131 -       ptr = dma_alloc_coherent(adev->pdev ? &adev->pdev->dev : NULL,
132 -                                size, phy, GFP_KERNEL);
133 +       ptr = dma_alloc_coherent(adev->bus_dev, size, phy, GFP_KERNEL);
134  
135         if (ptr) {
136                 log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
137 @@ -4016,10 +4017,370 @@
138         return OK;
139  }
140  
141 +#ifdef CONFIG_VLYNQ
142 +struct vlynq_reg_config {
143 +       u32 offset;
144 +       u32 value;
145 +};
146 +
147 +struct vlynq_known {
148 +       u32 chip_id;
149 +       char name[32];
150 +       struct vlynq_mapping rx_mapping[4];
151 +       int irq;
152 +       int irq_type;
153 +       int num_regs;
154 +       struct vlynq_reg_config regs[10];
155 +};
156 +
157 +#define CHIP_TNETW1130 0x00000009
158 +#define CHIP_TNETW1350 0x00000029
159 +
160 +static struct vlynq_known known_devices[] = {
161 +       {
162 +               .chip_id = CHIP_TNETW1130, .name = "TI TNETW1130",
163 +               .rx_mapping = {
164 +                       { .size = 0x22000, .offset = 0xf0000000 },
165 +                       { .size = 0x40000, .offset = 0xc0000000 },
166 +                       { .size = 0x0, .offset = 0x0 },
167 +                       { .size = 0x0, .offset = 0x0 },
168 +               },
169 +               .irq = 0,
170 +               .irq_type = IRQ_TYPE_EDGE_RISING,
171 +               .num_regs = 5,
172 +               .regs = {
173 +                       {
174 +                               .offset = 0x790,
175 +                               .value = (0xd0000000 - PHYS_OFFSET)
176 +                       },
177 +                       {
178 +                               .offset = 0x794,
179 +                               .value = (0xd0000000 - PHYS_OFFSET)
180 +                       },
181 +                       { .offset = 0x740, .value = 0 },
182 +                       { .offset = 0x744, .value = 0x00010000 },
183 +                       { .offset = 0x764, .value = 0x00010000 },
184 +               },
185 +       },
186 +       {
187 +               .chip_id = CHIP_TNETW1350, .name = "TI TNETW1350",
188 +               .rx_mapping = {
189 +                       { .size = 0x100000, .offset = 0x00300000 },
190 +                       { .size = 0x80000, .offset = 0x00000000 },
191 +                       { .size = 0x0, .offset = 0x0 },
192 +                       { .size = 0x0, .offset = 0x0 },
193 +               },
194 +               .irq = 0,
195 +               .irq_type = IRQ_TYPE_EDGE_RISING,
196 +               .num_regs = 5,
197 +               .regs = {
198 +                       {
199 +                               .offset = 0x790,
200 +                               .value = (0x60000000 - PHYS_OFFSET)
201 +                       },
202 +                       {
203 +                               .offset = 0x794,
204 +                               .value = (0x60000000 - PHYS_OFFSET)
205 +                       },
206 +                       { .offset = 0x740, .value = 0 },
207 +                       { .offset = 0x744, .value = 0x00010000 },
208 +                       { .offset = 0x764, .value = 0x00010000 },
209 +               },
210 +       },
211 +};
212 +
213 +static struct vlynq_device_id acx_vlynq_id[] = {
214 +       { CHIP_TNETW1130, vlynq_div_auto, 0 },
215 +       { CHIP_TNETW1350, vlynq_div_auto, 1 },
216 +       { 0, 0, 0 },
217 +};
218 +
219 +static __devinit int vlynq_probe(struct vlynq_device *vdev,
220 +                                struct vlynq_device_id *id)
221 +{
222 +       int result = -EIO, i;
223 +       u32 addr;
224 +       struct ieee80211_hw *ieee;
225 +       acx_device_t *adev = NULL;
226 +       acx111_ie_configoption_t co;
227 +       struct vlynq_mapping mapping[4] = { { 0, }, };
228 +       struct vlynq_known *match = NULL;
229 +
230 +       FN_ENTER;
231 +       result = vlynq_enable_device(vdev);
232 +       if (result)
233 +               return result;
234 +
235 +       match = &known_devices[id->driver_data];
236 +
237 +       if (!match) {
238 +               result = -ENODEV;
239 +               goto fail;
240 +       }
241 +
242 +       mapping[0].offset = ARCH_PFN_OFFSET << PAGE_SHIFT;
243 +       mapping[0].size = 0x02000000;
244 +       vlynq_set_local_mapping(vdev, vdev->mem_start, mapping);
245 +       vlynq_set_remote_mapping(vdev, 0, match->rx_mapping);
246 +
247 +       set_irq_type(vlynq_virq_to_irq(vdev, match->irq), match->irq_type);
248 +
249 +       addr = (u32)ioremap(vdev->mem_start, 0x1000);
250 +       if (!addr) {
251 +               printk(KERN_ERR "%s: failed to remap io memory\n",
252 +                      vdev->dev.bus_id);
253 +               result = -ENXIO;
254 +               goto fail;
255 +       }
256 +
257 +       for (i = 0; i < match->num_regs; i++)
258 +               iowrite32(match->regs[i].value,
259 +                         (u32 *)(addr + match->regs[i].offset));
260 +
261 +       iounmap((void *)addr);
262 +
263 +       ieee = ieee80211_alloc_hw(sizeof(struct acx_device), &acxpci_hw_ops);
264 +       if (!ieee) {
265 +               printk("acx: could not allocate ieee80211 structure %s\n",
266 +                      vdev->dev.bus_id);
267 +               goto fail_alloc_netdev;
268 +       }
269 +       ieee->flags &=   (~IEEE80211_HW_RX_INCLUDES_FCS &
270 +                         ~IEEE80211_HW_MONITOR_DURING_OPER) |
271 +                        IEEE80211_HW_WEP_INCLUDE_IV;
272 +       ieee->queues = 1;
273 +
274 +       adev = ieee2adev(ieee);
275 +
276 +       memset(adev, 0, sizeof(*adev));
277 +       /** Set up our private interface **/
278 +       spin_lock_init(&adev->lock);    /* initial state: unlocked */
279 +       /* We do not start with downed sem: we want PARANOID_LOCKING to work */
280 +       mutex_init(&adev->mutex);
281 +       /* since nobody can see new netdev yet, we can as well
282 +        ** just _presume_ that we're under sem (instead of actually taking it): */
283 +       /* acx_sem_lock(adev); */
284 +       adev->ieee = ieee;
285 +       adev->vdev = vdev;
286 +       adev->bus_dev = &vdev->dev;
287 +       adev->dev_type = DEVTYPE_PCI;
288 +
289 +/** Finished with private interface **/
290 +
291 +       vlynq_set_drvdata(vdev, ieee);
292 +       if (!request_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start, "acx")) {
293 +               printk("acx: cannot reserve VLYNQ memory region\n");
294 +               goto fail_request_mem_region;
295 +       }
296 +       adev->iobase = ioremap(vdev->mem_start, vdev->mem_end - vdev->mem_start);
297 +       if (!adev->iobase) {
298 +               printk("acx: ioremap() FAILED\n");
299 +               goto fail_ioremap;
300 +       }
301 +       adev->iobase2 = adev->iobase + match->rx_mapping[0].size;
302 +       adev->chip_type = CHIPTYPE_ACX111;
303 +       adev->chip_name = match->name;
304 +       adev->io = IO_ACX111;
305 +       adev->irq = vlynq_virq_to_irq(vdev, match->irq);
306 +
307 +       printk("acx: found %s-based wireless network card at %s, irq:%d, "
308 +              "phymem:0x%x, mem:0x%p\n",
309 +              match->name, vdev->dev.bus_id, adev->irq,
310 +              vdev->mem_start, adev->iobase);
311 +       log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
312 +
313 +       if (0 == adev->irq) {
314 +               printk("acx: can't use IRQ 0\n");
315 +               goto fail_irq;
316 +       }
317 +       SET_IEEE80211_DEV(ieee, &vdev->dev);
318 +
319 +
320 +       /* to find crashes due to weird driver access
321 +        * to unconfigured interface (ifup) */
322 +       adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
323 +
324 +
325 +       /* ok, pci setup is finished, now start initializing the card */
326 +
327 +       /* NB: read_reg() reads may return bogus data before reset_dev(),
328 +        * since the firmware which directly controls large parts of the I/O
329 +        * registers isn't initialized yet.
330 +        * acx100 seems to be more affected than acx111 */
331 +       if (OK != acxpci_s_reset_dev(adev))
332 +               goto fail_reset;
333 +
334 +       if (OK != acx_s_init_mac(adev))
335 +               goto fail_init_mac;
336 +
337 +       acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS);
338 +/* TODO: merge them into one function, they are called just once and are the same for pci & usb */
339 +       if (OK != acxpci_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
340 +               goto fail_read_eeprom_version;
341 +
342 +       acx_s_parse_configoption(adev, &co);
343 +       acx_s_set_defaults(adev);
344 +       acx_s_get_firmware_version(adev);       /* needs to be after acx_s_init_mac() */
345 +       acx_display_hardware_details(adev);
346 +
347 +       /* Register the card, AFTER everything else has been set up,
348 +        * since otherwise an ioctl could step on our feet due to
349 +        * firmware operations happening in parallel or uninitialized data */
350 +
351 +
352 +       acx_proc_register_entries(ieee);
353 +
354 +       /* Now we have our device, so make sure the kernel doesn't try
355 +        * to send packets even though we're not associated to a network yet */
356 +
357 +       /* after register_netdev() userspace may start working with dev
358 +        * (in particular, on other CPUs), we only need to up the sem */
359 +       /* acx_sem_unlock(adev); */
360 +
361 +       printk("acx " ACX_RELEASE ": net device %s, driver compiled "
362 +              "against wireless extensions %d and Linux %s\n",
363 +              wiphy_name(adev->ieee->wiphy), WIRELESS_EXT, UTS_RELEASE);
364 +
365 +       MAC_COPY(adev->ieee->wiphy->perm_addr, adev->dev_addr);
366 +
367 +       log(L_IRQ | L_INIT, "using IRQ %d\n", adev->irq);
368 +
369 +/** done with board specific setup **/
370 +
371 +       acx_init_task_scheduler(adev);
372 +       result = ieee80211_register_hw(adev->ieee);
373 +       if (OK != result) {
374 +               printk("acx: ieee80211_register_hw() FAILED: %d\n", result);
375 +               goto fail_register_netdev;
376 +       }
377 +#if CMD_DISCOVERY
378 +       great_inquisitor(adev);
379 +#endif
380 +
381 +       result = OK;
382 +       goto done;
383 +
384 +       /* error paths: undo everything in reverse order... */
385 +
386 +
387 +       acxpci_s_delete_dma_regions(adev);
388 +
389 +      fail_init_mac:
390 +      fail_read_eeprom_version:
391 +      fail_reset:
392 +
393 +      fail_alloc_netdev:
394 +      fail_irq:
395 +
396 +       iounmap(adev->iobase);
397 +      fail_ioremap:
398 +
399 +       release_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start);
400 +      fail_request_mem_region:
401 +      fail_register_netdev:
402 +       ieee80211_free_hw(ieee);
403 +      fail:
404 +       vlynq_disable_device(vdev);
405 +      done:
406 +       FN_EXIT1(result);
407 +       return result;
408 +}
409 +
410 +static void vlynq_remove(struct vlynq_device *vdev)
411 +{
412 +       struct ieee80211_hw *hw = vlynq_get_drvdata(vdev);
413 +       acx_device_t *adev = ieee2adev(hw);
414 +       unsigned long flags;
415 +       FN_ENTER;
416 +
417 +       if (!hw) {
418 +               log(L_DEBUG, "%s: card is unused. Skipping any release code\n",
419 +                   __func__);
420 +               goto end;
421 +       }
422 +
423 +
424 +       acx_lock(adev, flags);
425 +       acx_unlock(adev, flags);
426 +       adev->initialized = 0;
427 +
428 +       /* If device wasn't hot unplugged... */
429 +       if (adev_present(adev)) {
430 +
431 +               acx_sem_lock(adev);
432 +
433 +               /* disable both Tx and Rx to shut radio down properly */
434 +               if (adev->initialized) {
435 +                       acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
436 +                       acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
437 +               }
438 +               acx_lock(adev, flags);
439 +               /* disable power LED to save power :-) */
440 +               log(L_INIT, "switching off power LED to save power\n");
441 +               acxpci_l_power_led(adev, 0);
442 +               /* stop our eCPU */
443 +               acx_unlock(adev, flags);
444 +
445 +               acx_sem_unlock(adev);
446 +       }
447 +
448 +       /* unregister the device to not let the kernel
449 +        * (e.g. ioctls) access a half-deconfigured device
450 +        * NB: this will cause acxpci_e_close() to be called,
451 +        * thus we shouldn't call it under sem!
452 +        * Well, netdev did, but ieee80211 stack does not, so we
453 +        * have to do so manually...
454 +        */
455 +       acxpci_e_close(hw);
456 +       log(L_INIT, "removing device %s\n", wiphy_name(adev->ieee->wiphy));
457 +       ieee80211_unregister_hw(adev->ieee);
458 +
459 +       /* unregister_netdev ensures that no references to us left.
460 +        * For paranoid reasons we continue to follow the rules */
461 +       acx_sem_lock(adev);
462 +
463 +       if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
464 +               acxpci_s_down(hw);
465 +               CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
466 +       }
467 +
468 +       acx_proc_unregister_entries(adev->ieee);
469 +
470 +       /* finally, clean up PCI bus state */
471 +       acxpci_s_delete_dma_regions(adev);
472 +       if (adev->iobase)
473 +               iounmap(adev->iobase);
474 +       if (adev->iobase2)
475 +               iounmap(adev->iobase2);
476 +       release_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start);
477 +
478 +       /* remove dev registration */
479 +
480 +       acx_sem_unlock(adev);
481 +       vlynq_disable_device(vdev);
482 +
483 +       /* Free netdev (quite late,
484 +        * since otherwise we might get caught off-guard
485 +        * by a netdev timeout handler execution
486 +        * expecting to see a working dev...) */
487 +       ieee80211_free_hw(adev->ieee);
488 +
489 +      end:
490 +       FN_EXIT0;
491 +}
492 +
493 +static struct vlynq_driver vlynq_acx = {
494 +       .name = "acx_vlynq",
495 +       .id_table = acx_vlynq_id,
496 +       .probe = vlynq_probe,
497 +       .remove = __devexit_p(vlynq_remove),
498 +};
499 +#endif
500  
501  /***********************************************************************
502  ** Data for init_module/cleanup_module
503  */
504 +#ifdef CONFIG_PCI
505  static const struct pci_device_id acxpci_id_tbl[] __devinitdata = {
506         {
507          .vendor = PCI_VENDOR_ID_TI,
508 @@ -4071,7 +4432,7 @@
509         .resume = acxpci_e_resume
510  #endif /* CONFIG_PM */
511  };
512 -
513 +#endif /* CONFIG_PCI */
514  
515  /***********************************************************************
516  ** acxpci_e_init_module
517 @@ -4080,7 +4441,7 @@
518  */
519  int __init acxpci_e_init_module(void)
520  {
521 -       int res;
522 +       int res = 0;
523  
524         FN_ENTER;
525  
526 @@ -4100,10 +4461,15 @@
527  #endif
528         log(L_INIT,
529             "acx: " ENDIANNESS_STRING
530 -           "acx: PCI module " ACX_RELEASE " initialized, "
531 +           "acx: PCI/VLYNQ module " ACX_RELEASE " initialized, "
532             "waiting for cards to probe...\n");
533  
534 +#ifdef CONFIG_PCI
535         res = pci_register_driver(&acxpci_drv_id);
536 +#endif
537 +#ifdef CONFIG_VLYNQ
538 +       res = vlynq_register_driver(&vlynq_acx);
539 +#endif
540         FN_EXIT1(res);
541         return res;
542  }
543 @@ -4119,7 +4485,12 @@
544  {
545         FN_ENTER;
546  
547 +#ifdef CONFIG_VLYNQ
548 +       vlynq_unregister_driver(&vlynq_acx);
549 +#endif
550 +#ifdef CONFIG_PCI
551         pci_unregister_driver(&acxpci_drv_id);
552 +#endif
553  
554         FN_EXIT0;
555  }