diff options
Diffstat (limited to 'drivers/net/wireless')
52 files changed, 2971 insertions, 1201 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 2e8ac995d56f..bd4a68c85a47 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -271,25 +271,14 @@ config IPW2200_DEBUG | |||
271 | bool "Enable full debugging output in IPW2200 module." | 271 | bool "Enable full debugging output in IPW2200 module." |
272 | depends on IPW2200 | 272 | depends on IPW2200 |
273 | ---help--- | 273 | ---help--- |
274 | This option will enable debug tracing output for the IPW2200. | 274 | This option will enable low level debug tracing output for IPW2200. |
275 | 275 | ||
276 | This will result in the kernel module being ~100k larger. You can | 276 | Note, normal debug code is already compiled in. This low level |
277 | control which debug output is sent to the kernel log by setting the | 277 | debug option enables debug on hot paths (e.g Tx, Rx, ISR) and |
278 | value in | 278 | will result in the kernel module being ~70 larger. Most users |
279 | 279 | will typically not need this high verbosity debug information. | |
280 | /sys/bus/pci/drivers/ipw2200/debug_level | ||
281 | |||
282 | This entry will only exist if this option is enabled. | ||
283 | 280 | ||
284 | To set a value, simply echo an 8-byte hex value to the same file: | 281 | If you are not sure, say N here. |
285 | |||
286 | % echo 0x00000FFO > /sys/bus/pci/drivers/ipw2200/debug_level | ||
287 | |||
288 | You can find the list of debug mask values in | ||
289 | drivers/net/wireless/ipw2200.h | ||
290 | |||
291 | If you are not trying to debug or develop the IPW2200 driver, you | ||
292 | most likely want to say N here. | ||
293 | 282 | ||
294 | config AIRO | 283 | config AIRO |
295 | tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards" | 284 | tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards" |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index a4dd13942714..e088ceefb4a3 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/pci.h> | 47 | #include <linux/pci.h> |
48 | #include <asm/uaccess.h> | 48 | #include <asm/uaccess.h> |
49 | #include <net/ieee80211.h> | 49 | #include <net/ieee80211.h> |
50 | #include <linux/kthread.h> | ||
50 | 51 | ||
51 | #include "airo.h" | 52 | #include "airo.h" |
52 | 53 | ||
@@ -1187,11 +1188,10 @@ struct airo_info { | |||
1187 | int whichbap); | 1188 | int whichbap); |
1188 | unsigned short *flash; | 1189 | unsigned short *flash; |
1189 | tdsRssiEntry *rssi; | 1190 | tdsRssiEntry *rssi; |
1190 | struct task_struct *task; | 1191 | struct task_struct *list_bss_task; |
1192 | struct task_struct *airo_thread_task; | ||
1191 | struct semaphore sem; | 1193 | struct semaphore sem; |
1192 | pid_t thr_pid; | ||
1193 | wait_queue_head_t thr_wait; | 1194 | wait_queue_head_t thr_wait; |
1194 | struct completion thr_exited; | ||
1195 | unsigned long expires; | 1195 | unsigned long expires; |
1196 | struct { | 1196 | struct { |
1197 | struct sk_buff *skb; | 1197 | struct sk_buff *skb; |
@@ -1733,12 +1733,12 @@ static int readBSSListRid(struct airo_info *ai, int first, | |||
1733 | cmd.cmd=CMD_LISTBSS; | 1733 | cmd.cmd=CMD_LISTBSS; |
1734 | if (down_interruptible(&ai->sem)) | 1734 | if (down_interruptible(&ai->sem)) |
1735 | return -ERESTARTSYS; | 1735 | return -ERESTARTSYS; |
1736 | ai->list_bss_task = current; | ||
1736 | issuecommand(ai, &cmd, &rsp); | 1737 | issuecommand(ai, &cmd, &rsp); |
1737 | up(&ai->sem); | 1738 | up(&ai->sem); |
1738 | /* Let the command take effect */ | 1739 | /* Let the command take effect */ |
1739 | ai->task = current; | 1740 | schedule_timeout_uninterruptible(3 * HZ); |
1740 | ssleep(3); | 1741 | ai->list_bss_task = NULL; |
1741 | ai->task = NULL; | ||
1742 | } | 1742 | } |
1743 | rc = PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext, | 1743 | rc = PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext, |
1744 | list, ai->bssListRidLen, 1); | 1744 | list, ai->bssListRidLen, 1); |
@@ -2400,8 +2400,7 @@ void stop_airo_card( struct net_device *dev, int freeres ) | |||
2400 | clear_bit(FLAG_REGISTERED, &ai->flags); | 2400 | clear_bit(FLAG_REGISTERED, &ai->flags); |
2401 | } | 2401 | } |
2402 | set_bit(JOB_DIE, &ai->jobs); | 2402 | set_bit(JOB_DIE, &ai->jobs); |
2403 | kill_proc(ai->thr_pid, SIGTERM, 1); | 2403 | kthread_stop(ai->airo_thread_task); |
2404 | wait_for_completion(&ai->thr_exited); | ||
2405 | 2404 | ||
2406 | /* | 2405 | /* |
2407 | * Clean out tx queue | 2406 | * Clean out tx queue |
@@ -2811,9 +2810,8 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, | |||
2811 | ai->config.len = 0; | 2810 | ai->config.len = 0; |
2812 | ai->pci = pci; | 2811 | ai->pci = pci; |
2813 | init_waitqueue_head (&ai->thr_wait); | 2812 | init_waitqueue_head (&ai->thr_wait); |
2814 | init_completion (&ai->thr_exited); | 2813 | ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name); |
2815 | ai->thr_pid = kernel_thread(airo_thread, dev, CLONE_FS | CLONE_FILES); | 2814 | if (IS_ERR(ai->airo_thread_task)) |
2816 | if (ai->thr_pid < 0) | ||
2817 | goto err_out_free; | 2815 | goto err_out_free; |
2818 | ai->tfm = NULL; | 2816 | ai->tfm = NULL; |
2819 | rc = add_airo_dev( dev ); | 2817 | rc = add_airo_dev( dev ); |
@@ -2930,8 +2928,7 @@ err_out_unlink: | |||
2930 | del_airo_dev(dev); | 2928 | del_airo_dev(dev); |
2931 | err_out_thr: | 2929 | err_out_thr: |
2932 | set_bit(JOB_DIE, &ai->jobs); | 2930 | set_bit(JOB_DIE, &ai->jobs); |
2933 | kill_proc(ai->thr_pid, SIGTERM, 1); | 2931 | kthread_stop(ai->airo_thread_task); |
2934 | wait_for_completion(&ai->thr_exited); | ||
2935 | err_out_free: | 2932 | err_out_free: |
2936 | free_netdev(dev); | 2933 | free_netdev(dev); |
2937 | return NULL; | 2934 | return NULL; |
@@ -3063,13 +3060,7 @@ static int airo_thread(void *data) { | |||
3063 | struct airo_info *ai = dev->priv; | 3060 | struct airo_info *ai = dev->priv; |
3064 | int locked; | 3061 | int locked; |
3065 | 3062 | ||
3066 | daemonize("%s", dev->name); | ||
3067 | allow_signal(SIGTERM); | ||
3068 | |||
3069 | while(1) { | 3063 | while(1) { |
3070 | if (signal_pending(current)) | ||
3071 | flush_signals(current); | ||
3072 | |||
3073 | /* make swsusp happy with our thread */ | 3064 | /* make swsusp happy with our thread */ |
3074 | try_to_freeze(); | 3065 | try_to_freeze(); |
3075 | 3066 | ||
@@ -3097,7 +3088,7 @@ static int airo_thread(void *data) { | |||
3097 | set_bit(JOB_AUTOWEP, &ai->jobs); | 3088 | set_bit(JOB_AUTOWEP, &ai->jobs); |
3098 | break; | 3089 | break; |
3099 | } | 3090 | } |
3100 | if (!signal_pending(current)) { | 3091 | if (!kthread_should_stop()) { |
3101 | unsigned long wake_at; | 3092 | unsigned long wake_at; |
3102 | if (!ai->expires || !ai->scan_timeout) { | 3093 | if (!ai->expires || !ai->scan_timeout) { |
3103 | wake_at = max(ai->expires, | 3094 | wake_at = max(ai->expires, |
@@ -3109,7 +3100,7 @@ static int airo_thread(void *data) { | |||
3109 | schedule_timeout(wake_at - jiffies); | 3100 | schedule_timeout(wake_at - jiffies); |
3110 | continue; | 3101 | continue; |
3111 | } | 3102 | } |
3112 | } else if (!signal_pending(current)) { | 3103 | } else if (!kthread_should_stop()) { |
3113 | schedule(); | 3104 | schedule(); |
3114 | continue; | 3105 | continue; |
3115 | } | 3106 | } |
@@ -3154,7 +3145,8 @@ static int airo_thread(void *data) { | |||
3154 | else /* Shouldn't get here, but we make sure to unlock */ | 3145 | else /* Shouldn't get here, but we make sure to unlock */ |
3155 | up(&ai->sem); | 3146 | up(&ai->sem); |
3156 | } | 3147 | } |
3157 | complete_and_exit (&ai->thr_exited, 0); | 3148 | |
3149 | return 0; | ||
3158 | } | 3150 | } |
3159 | 3151 | ||
3160 | static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) { | 3152 | static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) { |
@@ -3235,8 +3227,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) | |||
3235 | if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) { | 3227 | if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) { |
3236 | if (auto_wep) | 3228 | if (auto_wep) |
3237 | apriv->expires = 0; | 3229 | apriv->expires = 0; |
3238 | if (apriv->task) | 3230 | if (apriv->list_bss_task) |
3239 | wake_up_process (apriv->task); | 3231 | wake_up_process(apriv->list_bss_task); |
3240 | set_bit(FLAG_UPDATE_UNI, &apriv->flags); | 3232 | set_bit(FLAG_UPDATE_UNI, &apriv->flags); |
3241 | set_bit(FLAG_UPDATE_MULTI, &apriv->flags); | 3233 | set_bit(FLAG_UPDATE_MULTI, &apriv->flags); |
3242 | 3234 | ||
@@ -3950,13 +3942,11 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { | |||
3950 | pRsp->rsp0 = IN4500(ai, RESP0); | 3942 | pRsp->rsp0 = IN4500(ai, RESP0); |
3951 | pRsp->rsp1 = IN4500(ai, RESP1); | 3943 | pRsp->rsp1 = IN4500(ai, RESP1); |
3952 | pRsp->rsp2 = IN4500(ai, RESP2); | 3944 | pRsp->rsp2 = IN4500(ai, RESP2); |
3953 | if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) { | 3945 | if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) |
3954 | airo_print_err(ai->dev->name, "cmd= %x\n", pCmd->cmd); | 3946 | airo_print_err(ai->dev->name, |
3955 | airo_print_err(ai->dev->name, "status= %x\n", pRsp->status); | 3947 | "cmd:%x status:%x rsp0:%x rsp1:%x rsp2:%x", |
3956 | airo_print_err(ai->dev->name, "Rsp0= %x\n", pRsp->rsp0); | 3948 | pCmd->cmd, pRsp->status, pRsp->rsp0, pRsp->rsp1, |
3957 | airo_print_err(ai->dev->name, "Rsp1= %x\n", pRsp->rsp1); | 3949 | pRsp->rsp2); |
3958 | airo_print_err(ai->dev->name, "Rsp2= %x\n", pRsp->rsp2); | ||
3959 | } | ||
3960 | 3950 | ||
3961 | // clear stuck command busy if necessary | 3951 | // clear stuck command busy if necessary |
3962 | if (IN4500(ai, COMMAND) & COMMAND_BUSY) { | 3952 | if (IN4500(ai, COMMAND) & COMMAND_BUSY) { |
diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c index d425c3cefded..3bfa791c323d 100644 --- a/drivers/net/wireless/atmel_pci.c +++ b/drivers/net/wireless/atmel_pci.c | |||
@@ -76,7 +76,7 @@ static void __devexit atmel_pci_remove(struct pci_dev *pdev) | |||
76 | 76 | ||
77 | static int __init atmel_init_module(void) | 77 | static int __init atmel_init_module(void) |
78 | { | 78 | { |
79 | return pci_module_init(&atmel_driver); | 79 | return pci_register_driver(&atmel_driver); |
80 | } | 80 | } |
81 | 81 | ||
82 | static void __exit atmel_cleanup_module(void) | 82 | static void __exit atmel_cleanup_module(void) |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 17a56828e232..6d4ea36bc564 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h | |||
@@ -33,14 +33,18 @@ | |||
33 | #define BCM43xx_PCICFG_ICR 0x94 | 33 | #define BCM43xx_PCICFG_ICR 0x94 |
34 | 34 | ||
35 | /* MMIO offsets */ | 35 | /* MMIO offsets */ |
36 | #define BCM43xx_MMIO_DMA1_REASON 0x20 | 36 | #define BCM43xx_MMIO_DMA0_REASON 0x20 |
37 | #define BCM43xx_MMIO_DMA1_IRQ_MASK 0x24 | 37 | #define BCM43xx_MMIO_DMA0_IRQ_MASK 0x24 |
38 | #define BCM43xx_MMIO_DMA2_REASON 0x28 | 38 | #define BCM43xx_MMIO_DMA1_REASON 0x28 |
39 | #define BCM43xx_MMIO_DMA2_IRQ_MASK 0x2C | 39 | #define BCM43xx_MMIO_DMA1_IRQ_MASK 0x2C |
40 | #define BCM43xx_MMIO_DMA3_REASON 0x30 | 40 | #define BCM43xx_MMIO_DMA2_REASON 0x30 |
41 | #define BCM43xx_MMIO_DMA3_IRQ_MASK 0x34 | 41 | #define BCM43xx_MMIO_DMA2_IRQ_MASK 0x34 |
42 | #define BCM43xx_MMIO_DMA4_REASON 0x38 | 42 | #define BCM43xx_MMIO_DMA3_REASON 0x38 |
43 | #define BCM43xx_MMIO_DMA4_IRQ_MASK 0x3C | 43 | #define BCM43xx_MMIO_DMA3_IRQ_MASK 0x3C |
44 | #define BCM43xx_MMIO_DMA4_REASON 0x40 | ||
45 | #define BCM43xx_MMIO_DMA4_IRQ_MASK 0x44 | ||
46 | #define BCM43xx_MMIO_DMA5_REASON 0x48 | ||
47 | #define BCM43xx_MMIO_DMA5_IRQ_MASK 0x4C | ||
44 | #define BCM43xx_MMIO_STATUS_BITFIELD 0x120 | 48 | #define BCM43xx_MMIO_STATUS_BITFIELD 0x120 |
45 | #define BCM43xx_MMIO_STATUS2_BITFIELD 0x124 | 49 | #define BCM43xx_MMIO_STATUS2_BITFIELD 0x124 |
46 | #define BCM43xx_MMIO_GEN_IRQ_REASON 0x128 | 50 | #define BCM43xx_MMIO_GEN_IRQ_REASON 0x128 |
@@ -56,14 +60,27 @@ | |||
56 | #define BCM43xx_MMIO_XMITSTAT_1 0x174 | 60 | #define BCM43xx_MMIO_XMITSTAT_1 0x174 |
57 | #define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ | 61 | #define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ |
58 | #define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ | 62 | #define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ |
59 | #define BCM43xx_MMIO_DMA1_BASE 0x200 | 63 | |
60 | #define BCM43xx_MMIO_DMA2_BASE 0x220 | 64 | /* 32-bit DMA */ |
61 | #define BCM43xx_MMIO_DMA3_BASE 0x240 | 65 | #define BCM43xx_MMIO_DMA32_BASE0 0x200 |
62 | #define BCM43xx_MMIO_DMA4_BASE 0x260 | 66 | #define BCM43xx_MMIO_DMA32_BASE1 0x220 |
67 | #define BCM43xx_MMIO_DMA32_BASE2 0x240 | ||
68 | #define BCM43xx_MMIO_DMA32_BASE3 0x260 | ||
69 | #define BCM43xx_MMIO_DMA32_BASE4 0x280 | ||
70 | #define BCM43xx_MMIO_DMA32_BASE5 0x2A0 | ||
71 | /* 64-bit DMA */ | ||
72 | #define BCM43xx_MMIO_DMA64_BASE0 0x200 | ||
73 | #define BCM43xx_MMIO_DMA64_BASE1 0x240 | ||
74 | #define BCM43xx_MMIO_DMA64_BASE2 0x280 | ||
75 | #define BCM43xx_MMIO_DMA64_BASE3 0x2C0 | ||
76 | #define BCM43xx_MMIO_DMA64_BASE4 0x300 | ||
77 | #define BCM43xx_MMIO_DMA64_BASE5 0x340 | ||
78 | /* PIO */ | ||
63 | #define BCM43xx_MMIO_PIO1_BASE 0x300 | 79 | #define BCM43xx_MMIO_PIO1_BASE 0x300 |
64 | #define BCM43xx_MMIO_PIO2_BASE 0x310 | 80 | #define BCM43xx_MMIO_PIO2_BASE 0x310 |
65 | #define BCM43xx_MMIO_PIO3_BASE 0x320 | 81 | #define BCM43xx_MMIO_PIO3_BASE 0x320 |
66 | #define BCM43xx_MMIO_PIO4_BASE 0x330 | 82 | #define BCM43xx_MMIO_PIO4_BASE 0x330 |
83 | |||
67 | #define BCM43xx_MMIO_PHY_VER 0x3E0 | 84 | #define BCM43xx_MMIO_PHY_VER 0x3E0 |
68 | #define BCM43xx_MMIO_PHY_RADIO 0x3E2 | 85 | #define BCM43xx_MMIO_PHY_RADIO 0x3E2 |
69 | #define BCM43xx_MMIO_ANTENNA 0x3E8 | 86 | #define BCM43xx_MMIO_ANTENNA 0x3E8 |
@@ -233,8 +250,14 @@ | |||
233 | #define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000 | 250 | #define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000 |
234 | 251 | ||
235 | /* sbtmstatehigh state flags */ | 252 | /* sbtmstatehigh state flags */ |
236 | #define BCM43xx_SBTMSTATEHIGH_SERROR 0x1 | 253 | #define BCM43xx_SBTMSTATEHIGH_SERROR 0x00000001 |
237 | #define BCM43xx_SBTMSTATEHIGH_BUSY 0x4 | 254 | #define BCM43xx_SBTMSTATEHIGH_BUSY 0x00000004 |
255 | #define BCM43xx_SBTMSTATEHIGH_TIMEOUT 0x00000020 | ||
256 | #define BCM43xx_SBTMSTATEHIGH_COREFLAGS 0x1FFF0000 | ||
257 | #define BCM43xx_SBTMSTATEHIGH_DMA64BIT 0x10000000 | ||
258 | #define BCM43xx_SBTMSTATEHIGH_GATEDCLK 0x20000000 | ||
259 | #define BCM43xx_SBTMSTATEHIGH_BISTFAILED 0x40000000 | ||
260 | #define BCM43xx_SBTMSTATEHIGH_BISTCOMPLETE 0x80000000 | ||
238 | 261 | ||
239 | /* sbimstate flags */ | 262 | /* sbimstate flags */ |
240 | #define BCM43xx_SBIMSTATE_IB_ERROR 0x20000 | 263 | #define BCM43xx_SBIMSTATE_IB_ERROR 0x20000 |
@@ -283,6 +306,13 @@ | |||
283 | #define BCM43xx_SBF_TIME_UPDATE 0x10000000 | 306 | #define BCM43xx_SBF_TIME_UPDATE 0x10000000 |
284 | #define BCM43xx_SBF_80000000 0x80000000 /*FIXME: fix name*/ | 307 | #define BCM43xx_SBF_80000000 0x80000000 /*FIXME: fix name*/ |
285 | 308 | ||
309 | /* Microcode */ | ||
310 | #define BCM43xx_UCODE_REVISION 0x0000 | ||
311 | #define BCM43xx_UCODE_PATCHLEVEL 0x0002 | ||
312 | #define BCM43xx_UCODE_DATE 0x0004 | ||
313 | #define BCM43xx_UCODE_TIME 0x0006 | ||
314 | #define BCM43xx_UCODE_STATUS 0x0040 | ||
315 | |||
286 | /* MicrocodeFlagsBitfield (addr + lo-word values?)*/ | 316 | /* MicrocodeFlagsBitfield (addr + lo-word values?)*/ |
287 | #define BCM43xx_UCODEFLAGS_OFFSET 0x005E | 317 | #define BCM43xx_UCODEFLAGS_OFFSET 0x005E |
288 | 318 | ||
@@ -504,6 +534,12 @@ struct bcm43xx_phyinfo { | |||
504 | * This lock is only used by bcm43xx_phy_{un}lock() | 534 | * This lock is only used by bcm43xx_phy_{un}lock() |
505 | */ | 535 | */ |
506 | spinlock_t lock; | 536 | spinlock_t lock; |
537 | |||
538 | /* Firmware. */ | ||
539 | const struct firmware *ucode; | ||
540 | const struct firmware *pcm; | ||
541 | const struct firmware *initvals0; | ||
542 | const struct firmware *initvals1; | ||
507 | }; | 543 | }; |
508 | 544 | ||
509 | 545 | ||
@@ -568,8 +604,11 @@ struct bcm43xx_dma { | |||
568 | struct bcm43xx_dmaring *tx_ring1; | 604 | struct bcm43xx_dmaring *tx_ring1; |
569 | struct bcm43xx_dmaring *tx_ring2; | 605 | struct bcm43xx_dmaring *tx_ring2; |
570 | struct bcm43xx_dmaring *tx_ring3; | 606 | struct bcm43xx_dmaring *tx_ring3; |
607 | struct bcm43xx_dmaring *tx_ring4; | ||
608 | struct bcm43xx_dmaring *tx_ring5; | ||
609 | |||
571 | struct bcm43xx_dmaring *rx_ring0; | 610 | struct bcm43xx_dmaring *rx_ring0; |
572 | struct bcm43xx_dmaring *rx_ring1; /* only available on core.rev < 5 */ | 611 | struct bcm43xx_dmaring *rx_ring3; /* only available on core.rev < 5 */ |
573 | }; | 612 | }; |
574 | 613 | ||
575 | /* Data structures for PIO transmission, per 80211 core. */ | 614 | /* Data structures for PIO transmission, per 80211 core. */ |
@@ -593,12 +632,14 @@ struct bcm43xx_coreinfo { | |||
593 | u8 available:1, | 632 | u8 available:1, |
594 | enabled:1, | 633 | enabled:1, |
595 | initialized:1; | 634 | initialized:1; |
596 | /** core_id ID number */ | ||
597 | u16 id; | ||
598 | /** core_rev revision number */ | 635 | /** core_rev revision number */ |
599 | u8 rev; | 636 | u8 rev; |
600 | /** Index number for _switch_core() */ | 637 | /** Index number for _switch_core() */ |
601 | u8 index; | 638 | u8 index; |
639 | /** core_id ID number */ | ||
640 | u16 id; | ||
641 | /** Core-specific data. */ | ||
642 | void *priv; | ||
602 | }; | 643 | }; |
603 | 644 | ||
604 | /* Additional information for each 80211 core. */ | 645 | /* Additional information for each 80211 core. */ |
@@ -647,7 +688,23 @@ enum { | |||
647 | BCM43xx_STAT_RESTARTING, /* controller_restart() called. */ | 688 | BCM43xx_STAT_RESTARTING, /* controller_restart() called. */ |
648 | }; | 689 | }; |
649 | #define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status) | 690 | #define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status) |
650 | #define bcm43xx_set_status(bcm, stat) atomic_set(&(bcm)->init_status, (stat)) | 691 | #define bcm43xx_set_status(bcm, stat) do { \ |
692 | atomic_set(&(bcm)->init_status, (stat)); \ | ||
693 | smp_wmb(); \ | ||
694 | } while (0) | ||
695 | |||
696 | /* *** THEORY OF LOCKING *** | ||
697 | * | ||
698 | * We have two different locks in the bcm43xx driver. | ||
699 | * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private | ||
700 | * and the device registers. This mutex does _not_ protect | ||
701 | * against concurrency from the IRQ handler. | ||
702 | * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. | ||
703 | * | ||
704 | * Please note that, if you only take the irq_lock, you are not protected | ||
705 | * against concurrency from the periodic work handlers. | ||
706 | * Most times you want to take _both_ locks. | ||
707 | */ | ||
651 | 708 | ||
652 | struct bcm43xx_private { | 709 | struct bcm43xx_private { |
653 | struct ieee80211_device *ieee; | 710 | struct ieee80211_device *ieee; |
@@ -659,7 +716,6 @@ struct bcm43xx_private { | |||
659 | 716 | ||
660 | void __iomem *mmio_addr; | 717 | void __iomem *mmio_addr; |
661 | 718 | ||
662 | /* Locking, see "theory of locking" text below. */ | ||
663 | spinlock_t irq_lock; | 719 | spinlock_t irq_lock; |
664 | struct mutex mutex; | 720 | struct mutex mutex; |
665 | 721 | ||
@@ -691,6 +747,7 @@ struct bcm43xx_private { | |||
691 | struct bcm43xx_sprominfo sprom; | 747 | struct bcm43xx_sprominfo sprom; |
692 | #define BCM43xx_NR_LEDS 4 | 748 | #define BCM43xx_NR_LEDS 4 |
693 | struct bcm43xx_led leds[BCM43xx_NR_LEDS]; | 749 | struct bcm43xx_led leds[BCM43xx_NR_LEDS]; |
750 | spinlock_t leds_lock; | ||
694 | 751 | ||
695 | /* The currently active core. */ | 752 | /* The currently active core. */ |
696 | struct bcm43xx_coreinfo *current_core; | 753 | struct bcm43xx_coreinfo *current_core; |
@@ -708,10 +765,6 @@ struct bcm43xx_private { | |||
708 | struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ]; | 765 | struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ]; |
709 | /* Additional information, specific to the 80211 cores. */ | 766 | /* Additional information, specific to the 80211 cores. */ |
710 | struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ]; | 767 | struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ]; |
711 | /* Index of the current 80211 core. If current_core is not | ||
712 | * an 80211 core, this is -1. | ||
713 | */ | ||
714 | int current_80211_core_idx; | ||
715 | /* Number of available 80211 cores. */ | 768 | /* Number of available 80211 cores. */ |
716 | int nr_80211_available; | 769 | int nr_80211_available; |
717 | 770 | ||
@@ -719,11 +772,13 @@ struct bcm43xx_private { | |||
719 | 772 | ||
720 | /* Reason code of the last interrupt. */ | 773 | /* Reason code of the last interrupt. */ |
721 | u32 irq_reason; | 774 | u32 irq_reason; |
722 | u32 dma_reason[4]; | 775 | u32 dma_reason[6]; |
723 | /* saved irq enable/disable state bitfield. */ | 776 | /* saved irq enable/disable state bitfield. */ |
724 | u32 irq_savedstate; | 777 | u32 irq_savedstate; |
725 | /* Link Quality calculation context. */ | 778 | /* Link Quality calculation context. */ |
726 | struct bcm43xx_noise_calculation noisecalc; | 779 | struct bcm43xx_noise_calculation noisecalc; |
780 | /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ | ||
781 | int mac_suspended; | ||
727 | 782 | ||
728 | /* Threshold values. */ | 783 | /* Threshold values. */ |
729 | //TODO: The RTS thr has to be _used_. Currently, it is only set via WX. | 784 | //TODO: The RTS thr has to be _used_. Currently, it is only set via WX. |
@@ -746,12 +801,6 @@ struct bcm43xx_private { | |||
746 | struct bcm43xx_key key[54]; | 801 | struct bcm43xx_key key[54]; |
747 | u8 default_key_idx; | 802 | u8 default_key_idx; |
748 | 803 | ||
749 | /* Firmware. */ | ||
750 | const struct firmware *ucode; | ||
751 | const struct firmware *pcm; | ||
752 | const struct firmware *initvals0; | ||
753 | const struct firmware *initvals1; | ||
754 | |||
755 | /* Random Number Generator. */ | 804 | /* Random Number Generator. */ |
756 | struct hwrng rng; | 805 | struct hwrng rng; |
757 | char rng_name[20 + 1]; | 806 | char rng_name[20 + 1]; |
@@ -763,55 +812,6 @@ struct bcm43xx_private { | |||
763 | }; | 812 | }; |
764 | 813 | ||
765 | 814 | ||
766 | /* *** THEORY OF LOCKING *** | ||
767 | * | ||
768 | * We have two different locks in the bcm43xx driver. | ||
769 | * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private | ||
770 | * and the device registers. | ||
771 | * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. | ||
772 | * | ||
773 | * We have three types of helper function pairs to utilize these locks. | ||
774 | * (Always use the helper functions.) | ||
775 | * 1) bcm43xx_{un}lock_noirq(): | ||
776 | * Takes bcm->mutex. Does _not_ protect against IRQ concurrency, | ||
777 | * so it is almost always unsafe, if device IRQs are enabled. | ||
778 | * So only use this, if device IRQs are masked. | ||
779 | * Locking may sleep. | ||
780 | * You can sleep within the critical section. | ||
781 | * 2) bcm43xx_{un}lock_irqonly(): | ||
782 | * Takes bcm->irq_lock. Does _not_ protect against | ||
783 | * bcm43xx_lock_noirq() critical sections. | ||
784 | * Does only protect against the IRQ handler path and other | ||
785 | * irqonly() critical sections. | ||
786 | * Locking does not sleep. | ||
787 | * You must not sleep within the critical section. | ||
788 | * 3) bcm43xx_{un}lock_irqsafe(): | ||
789 | * This is the cummulative lock and takes both, mutex and irq_lock. | ||
790 | * Protects against noirq() and irqonly() critical sections (and | ||
791 | * the IRQ handler path). | ||
792 | * Locking may sleep. | ||
793 | * You must not sleep within the critical section. | ||
794 | */ | ||
795 | |||
796 | /* Lock type 1 */ | ||
797 | #define bcm43xx_lock_noirq(bcm) mutex_lock(&(bcm)->mutex) | ||
798 | #define bcm43xx_unlock_noirq(bcm) mutex_unlock(&(bcm)->mutex) | ||
799 | /* Lock type 2 */ | ||
800 | #define bcm43xx_lock_irqonly(bcm, flags) \ | ||
801 | spin_lock_irqsave(&(bcm)->irq_lock, flags) | ||
802 | #define bcm43xx_unlock_irqonly(bcm, flags) \ | ||
803 | spin_unlock_irqrestore(&(bcm)->irq_lock, flags) | ||
804 | /* Lock type 3 */ | ||
805 | #define bcm43xx_lock_irqsafe(bcm, flags) do { \ | ||
806 | bcm43xx_lock_noirq(bcm); \ | ||
807 | bcm43xx_lock_irqonly(bcm, flags); \ | ||
808 | } while (0) | ||
809 | #define bcm43xx_unlock_irqsafe(bcm, flags) do { \ | ||
810 | bcm43xx_unlock_irqonly(bcm, flags); \ | ||
811 | bcm43xx_unlock_noirq(bcm); \ | ||
812 | } while (0) | ||
813 | |||
814 | |||
815 | static inline | 815 | static inline |
816 | struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) | 816 | struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) |
817 | { | 817 | { |
@@ -863,34 +863,33 @@ int bcm43xx_using_pio(struct bcm43xx_private *bcm) | |||
863 | * any of these functions. | 863 | * any of these functions. |
864 | */ | 864 | */ |
865 | static inline | 865 | static inline |
866 | struct bcm43xx_coreinfo_80211 * | ||
867 | bcm43xx_current_80211_priv(struct bcm43xx_private *bcm) | ||
868 | { | ||
869 | assert(bcm->current_core->id == BCM43xx_COREID_80211); | ||
870 | return bcm->current_core->priv; | ||
871 | } | ||
872 | static inline | ||
866 | struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm) | 873 | struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm) |
867 | { | 874 | { |
868 | assert(bcm43xx_using_pio(bcm)); | 875 | assert(bcm43xx_using_pio(bcm)); |
869 | assert(bcm->current_80211_core_idx >= 0); | 876 | return &(bcm43xx_current_80211_priv(bcm)->pio); |
870 | assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); | ||
871 | return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio); | ||
872 | } | 877 | } |
873 | static inline | 878 | static inline |
874 | struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm) | 879 | struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm) |
875 | { | 880 | { |
876 | assert(!bcm43xx_using_pio(bcm)); | 881 | assert(!bcm43xx_using_pio(bcm)); |
877 | assert(bcm->current_80211_core_idx >= 0); | 882 | return &(bcm43xx_current_80211_priv(bcm)->dma); |
878 | assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); | ||
879 | return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma); | ||
880 | } | 883 | } |
881 | static inline | 884 | static inline |
882 | struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm) | 885 | struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm) |
883 | { | 886 | { |
884 | assert(bcm->current_80211_core_idx >= 0); | 887 | return &(bcm43xx_current_80211_priv(bcm)->phy); |
885 | assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); | ||
886 | return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy); | ||
887 | } | 888 | } |
888 | static inline | 889 | static inline |
889 | struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm) | 890 | struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm) |
890 | { | 891 | { |
891 | assert(bcm->current_80211_core_idx >= 0); | 892 | return &(bcm43xx_current_80211_priv(bcm)->radio); |
892 | assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); | ||
893 | return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio); | ||
894 | } | 893 | } |
895 | 894 | ||
896 | 895 | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index ce2e40b29b4f..923275ea0789 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | |||
@@ -77,7 +77,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, | |||
77 | 77 | ||
78 | down(&big_buffer_sem); | 78 | down(&big_buffer_sem); |
79 | 79 | ||
80 | bcm43xx_lock_irqsafe(bcm, flags); | 80 | mutex_lock(&bcm->mutex); |
81 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
81 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { | 82 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { |
82 | fappend("Board not initialized.\n"); | 83 | fappend("Board not initialized.\n"); |
83 | goto out; | 84 | goto out; |
@@ -121,7 +122,8 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, | |||
121 | fappend("\n"); | 122 | fappend("\n"); |
122 | 123 | ||
123 | out: | 124 | out: |
124 | bcm43xx_unlock_irqsafe(bcm, flags); | 125 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
126 | mutex_unlock(&bcm->mutex); | ||
125 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 127 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
126 | up(&big_buffer_sem); | 128 | up(&big_buffer_sem); |
127 | return res; | 129 | return res; |
@@ -159,7 +161,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, | |||
159 | unsigned long flags; | 161 | unsigned long flags; |
160 | 162 | ||
161 | down(&big_buffer_sem); | 163 | down(&big_buffer_sem); |
162 | bcm43xx_lock_irqsafe(bcm, flags); | 164 | mutex_lock(&bcm->mutex); |
165 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
163 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { | 166 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { |
164 | fappend("Board not initialized.\n"); | 167 | fappend("Board not initialized.\n"); |
165 | goto out; | 168 | goto out; |
@@ -169,7 +172,8 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, | |||
169 | fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); | 172 | fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); |
170 | 173 | ||
171 | out: | 174 | out: |
172 | bcm43xx_unlock_irqsafe(bcm, flags); | 175 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
176 | mutex_unlock(&bcm->mutex); | ||
173 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 177 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
174 | up(&big_buffer_sem); | 178 | up(&big_buffer_sem); |
175 | return res; | 179 | return res; |
@@ -188,7 +192,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, | |||
188 | u64 tsf; | 192 | u64 tsf; |
189 | 193 | ||
190 | down(&big_buffer_sem); | 194 | down(&big_buffer_sem); |
191 | bcm43xx_lock_irqsafe(bcm, flags); | 195 | mutex_lock(&bcm->mutex); |
196 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
192 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { | 197 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { |
193 | fappend("Board not initialized.\n"); | 198 | fappend("Board not initialized.\n"); |
194 | goto out; | 199 | goto out; |
@@ -199,7 +204,8 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, | |||
199 | (unsigned int)(tsf & 0xFFFFFFFFULL)); | 204 | (unsigned int)(tsf & 0xFFFFFFFFULL)); |
200 | 205 | ||
201 | out: | 206 | out: |
202 | bcm43xx_unlock_irqsafe(bcm, flags); | 207 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
208 | mutex_unlock(&bcm->mutex); | ||
203 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 209 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
204 | up(&big_buffer_sem); | 210 | up(&big_buffer_sem); |
205 | return res; | 211 | return res; |
@@ -221,7 +227,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, | |||
221 | res = -EFAULT; | 227 | res = -EFAULT; |
222 | goto out_up; | 228 | goto out_up; |
223 | } | 229 | } |
224 | bcm43xx_lock_irqsafe(bcm, flags); | 230 | mutex_lock(&bcm->mutex); |
231 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
225 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { | 232 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { |
226 | printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); | 233 | printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); |
227 | res = -EFAULT; | 234 | res = -EFAULT; |
@@ -237,7 +244,8 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, | |||
237 | res = buf_size; | 244 | res = buf_size; |
238 | 245 | ||
239 | out_unlock: | 246 | out_unlock: |
240 | bcm43xx_unlock_irqsafe(bcm, flags); | 247 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
248 | mutex_unlock(&bcm->mutex); | ||
241 | out_up: | 249 | out_up: |
242 | up(&big_buffer_sem); | 250 | up(&big_buffer_sem); |
243 | return res; | 251 | return res; |
@@ -258,7 +266,8 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, | |||
258 | int i, cnt, j = 0; | 266 | int i, cnt, j = 0; |
259 | 267 | ||
260 | down(&big_buffer_sem); | 268 | down(&big_buffer_sem); |
261 | bcm43xx_lock_irqsafe(bcm, flags); | 269 | mutex_lock(&bcm->mutex); |
270 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
262 | 271 | ||
263 | fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", | 272 | fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", |
264 | BCM43xx_NR_LOGGED_XMITSTATUS); | 273 | BCM43xx_NR_LOGGED_XMITSTATUS); |
@@ -294,14 +303,51 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, | |||
294 | i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; | 303 | i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; |
295 | } | 304 | } |
296 | 305 | ||
297 | bcm43xx_unlock_irqsafe(bcm, flags); | 306 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
298 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 307 | res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
299 | bcm43xx_lock_irqsafe(bcm, flags); | 308 | spin_lock_irqsave(&bcm->irq_lock, flags); |
300 | if (*ppos == pos) { | 309 | if (*ppos == pos) { |
301 | /* Done. Drop the copied data. */ | 310 | /* Done. Drop the copied data. */ |
302 | e->xmitstatus_printing = 0; | 311 | e->xmitstatus_printing = 0; |
303 | } | 312 | } |
304 | bcm43xx_unlock_irqsafe(bcm, flags); | 313 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
314 | mutex_unlock(&bcm->mutex); | ||
315 | up(&big_buffer_sem); | ||
316 | return res; | ||
317 | } | ||
318 | |||
319 | static ssize_t restart_write_file(struct file *file, const char __user *user_buf, | ||
320 | size_t count, loff_t *ppos) | ||
321 | { | ||
322 | struct bcm43xx_private *bcm = file->private_data; | ||
323 | char *buf = really_big_buffer; | ||
324 | ssize_t buf_size; | ||
325 | ssize_t res; | ||
326 | unsigned long flags; | ||
327 | |||
328 | buf_size = min(count, sizeof (really_big_buffer) - 1); | ||
329 | down(&big_buffer_sem); | ||
330 | if (copy_from_user(buf, user_buf, buf_size)) { | ||
331 | res = -EFAULT; | ||
332 | goto out_up; | ||
333 | } | ||
334 | mutex_lock(&(bcm)->mutex); | ||
335 | spin_lock_irqsave(&(bcm)->irq_lock, flags); | ||
336 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { | ||
337 | printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); | ||
338 | res = -EFAULT; | ||
339 | goto out_unlock; | ||
340 | } | ||
341 | if (count > 0 && buf[0] == '1') { | ||
342 | bcm43xx_controller_restart(bcm, "manually restarted"); | ||
343 | res = count; | ||
344 | } else | ||
345 | res = -EINVAL; | ||
346 | |||
347 | out_unlock: | ||
348 | spin_unlock_irqrestore(&(bcm)->irq_lock, flags); | ||
349 | mutex_unlock(&(bcm)->mutex); | ||
350 | out_up: | ||
305 | up(&big_buffer_sem); | 351 | up(&big_buffer_sem); |
306 | return res; | 352 | return res; |
307 | } | 353 | } |
@@ -339,6 +385,11 @@ static struct file_operations txstat_fops = { | |||
339 | .open = open_file_generic, | 385 | .open = open_file_generic, |
340 | }; | 386 | }; |
341 | 387 | ||
388 | static struct file_operations restart_fops = { | ||
389 | .write = restart_write_file, | ||
390 | .open = open_file_generic, | ||
391 | }; | ||
392 | |||
342 | 393 | ||
343 | void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) | 394 | void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) |
344 | { | 395 | { |
@@ -390,6 +441,10 @@ void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) | |||
390 | bcm, &txstat_fops); | 441 | bcm, &txstat_fops); |
391 | if (!e->dentry_txstat) | 442 | if (!e->dentry_txstat) |
392 | printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir); | 443 | printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir); |
444 | e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir, | ||
445 | bcm, &restart_fops); | ||
446 | if (!e->dentry_restart) | ||
447 | printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir); | ||
393 | } | 448 | } |
394 | 449 | ||
395 | void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) | 450 | void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) |
@@ -405,6 +460,7 @@ void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) | |||
405 | debugfs_remove(e->dentry_devinfo); | 460 | debugfs_remove(e->dentry_devinfo); |
406 | debugfs_remove(e->dentry_tsf); | 461 | debugfs_remove(e->dentry_tsf); |
407 | debugfs_remove(e->dentry_txstat); | 462 | debugfs_remove(e->dentry_txstat); |
463 | debugfs_remove(e->dentry_restart); | ||
408 | debugfs_remove(e->subdir); | 464 | debugfs_remove(e->subdir); |
409 | kfree(e->xmitstatus_buffer); | 465 | kfree(e->xmitstatus_buffer); |
410 | kfree(e->xmitstatus_print_buffer); | 466 | kfree(e->xmitstatus_print_buffer); |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h index 50ce267f794d..a40d1af35545 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h | |||
@@ -20,6 +20,7 @@ struct bcm43xx_dfsentry { | |||
20 | struct dentry *dentry_spromdump; | 20 | struct dentry *dentry_spromdump; |
21 | struct dentry *dentry_tsf; | 21 | struct dentry *dentry_tsf; |
22 | struct dentry *dentry_txstat; | 22 | struct dentry *dentry_txstat; |
23 | struct dentry *dentry_restart; | ||
23 | 24 | ||
24 | struct bcm43xx_private *bcm; | 25 | struct bcm43xx_private *bcm; |
25 | 26 | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index d0318e525ba7..76e3aed4b471 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | DMA ringbuffer and descriptor allocation/management | 5 | DMA ringbuffer and descriptor allocation/management |
6 | 6 | ||
7 | Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de> | 7 | Copyright (c) 2005, 2006 Michael Buesch <mbuesch@freenet.de> |
8 | 8 | ||
9 | Some code in this file is derived from the b44.c driver | 9 | Some code in this file is derived from the b44.c driver |
10 | Copyright (C) 2002 David S. Miller | 10 | Copyright (C) 2002 David S. Miller |
@@ -109,6 +109,35 @@ void return_slot(struct bcm43xx_dmaring *ring, int slot) | |||
109 | } | 109 | } |
110 | } | 110 | } |
111 | 111 | ||
112 | u16 bcm43xx_dmacontroller_base(int dma64bit, int controller_idx) | ||
113 | { | ||
114 | static const u16 map64[] = { | ||
115 | BCM43xx_MMIO_DMA64_BASE0, | ||
116 | BCM43xx_MMIO_DMA64_BASE1, | ||
117 | BCM43xx_MMIO_DMA64_BASE2, | ||
118 | BCM43xx_MMIO_DMA64_BASE3, | ||
119 | BCM43xx_MMIO_DMA64_BASE4, | ||
120 | BCM43xx_MMIO_DMA64_BASE5, | ||
121 | }; | ||
122 | static const u16 map32[] = { | ||
123 | BCM43xx_MMIO_DMA32_BASE0, | ||
124 | BCM43xx_MMIO_DMA32_BASE1, | ||
125 | BCM43xx_MMIO_DMA32_BASE2, | ||
126 | BCM43xx_MMIO_DMA32_BASE3, | ||
127 | BCM43xx_MMIO_DMA32_BASE4, | ||
128 | BCM43xx_MMIO_DMA32_BASE5, | ||
129 | }; | ||
130 | |||
131 | if (dma64bit) { | ||
132 | assert(controller_idx >= 0 && | ||
133 | controller_idx < ARRAY_SIZE(map64)); | ||
134 | return map64[controller_idx]; | ||
135 | } | ||
136 | assert(controller_idx >= 0 && | ||
137 | controller_idx < ARRAY_SIZE(map32)); | ||
138 | return map32[controller_idx]; | ||
139 | } | ||
140 | |||
112 | static inline | 141 | static inline |
113 | dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring, | 142 | dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring, |
114 | unsigned char *buf, | 143 | unsigned char *buf, |
@@ -172,7 +201,6 @@ void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring, | |||
172 | /* Unmap and free a descriptor buffer. */ | 201 | /* Unmap and free a descriptor buffer. */ |
173 | static inline | 202 | static inline |
174 | void free_descriptor_buffer(struct bcm43xx_dmaring *ring, | 203 | void free_descriptor_buffer(struct bcm43xx_dmaring *ring, |
175 | struct bcm43xx_dmadesc *desc, | ||
176 | struct bcm43xx_dmadesc_meta *meta, | 204 | struct bcm43xx_dmadesc_meta *meta, |
177 | int irq_context) | 205 | int irq_context) |
178 | { | 206 | { |
@@ -188,23 +216,13 @@ static int alloc_ringmemory(struct bcm43xx_dmaring *ring) | |||
188 | { | 216 | { |
189 | struct device *dev = &(ring->bcm->pci_dev->dev); | 217 | struct device *dev = &(ring->bcm->pci_dev->dev); |
190 | 218 | ||
191 | ring->vbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, | 219 | ring->descbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, |
192 | &(ring->dmabase), GFP_KERNEL); | 220 | &(ring->dmabase), GFP_KERNEL); |
193 | if (!ring->vbase) { | 221 | if (!ring->descbase) { |
194 | printk(KERN_ERR PFX "DMA ringmemory allocation failed\n"); | 222 | printk(KERN_ERR PFX "DMA ringmemory allocation failed\n"); |
195 | return -ENOMEM; | 223 | return -ENOMEM; |
196 | } | 224 | } |
197 | if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) { | 225 | memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE); |
198 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G " | ||
199 | "(0x%llx, len: %lu)\n", | ||
200 | (unsigned long long)ring->dmabase, | ||
201 | BCM43xx_DMA_RINGMEMSIZE); | ||
202 | dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, | ||
203 | ring->vbase, ring->dmabase); | ||
204 | return -ENOMEM; | ||
205 | } | ||
206 | assert(!(ring->dmabase & 0x000003FF)); | ||
207 | memset(ring->vbase, 0, BCM43xx_DMA_RINGMEMSIZE); | ||
208 | 226 | ||
209 | return 0; | 227 | return 0; |
210 | } | 228 | } |
@@ -214,26 +232,34 @@ static void free_ringmemory(struct bcm43xx_dmaring *ring) | |||
214 | struct device *dev = &(ring->bcm->pci_dev->dev); | 232 | struct device *dev = &(ring->bcm->pci_dev->dev); |
215 | 233 | ||
216 | dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, | 234 | dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, |
217 | ring->vbase, ring->dmabase); | 235 | ring->descbase, ring->dmabase); |
218 | } | 236 | } |
219 | 237 | ||
220 | /* Reset the RX DMA channel */ | 238 | /* Reset the RX DMA channel */ |
221 | int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, | 239 | int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, |
222 | u16 mmio_base) | 240 | u16 mmio_base, int dma64) |
223 | { | 241 | { |
224 | int i; | 242 | int i; |
225 | u32 value; | 243 | u32 value; |
244 | u16 offset; | ||
226 | 245 | ||
227 | bcm43xx_write32(bcm, | 246 | offset = dma64 ? BCM43xx_DMA64_RXCTL : BCM43xx_DMA32_RXCTL; |
228 | mmio_base + BCM43xx_DMA_RX_CONTROL, | 247 | bcm43xx_write32(bcm, mmio_base + offset, 0); |
229 | 0x00000000); | ||
230 | for (i = 0; i < 1000; i++) { | 248 | for (i = 0; i < 1000; i++) { |
231 | value = bcm43xx_read32(bcm, | 249 | offset = dma64 ? BCM43xx_DMA64_RXSTATUS : BCM43xx_DMA32_RXSTATUS; |
232 | mmio_base + BCM43xx_DMA_RX_STATUS); | 250 | value = bcm43xx_read32(bcm, mmio_base + offset); |
233 | value &= BCM43xx_DMA_RXSTAT_STAT_MASK; | 251 | if (dma64) { |
234 | if (value == BCM43xx_DMA_RXSTAT_STAT_DISABLED) { | 252 | value &= BCM43xx_DMA64_RXSTAT; |
235 | i = -1; | 253 | if (value == BCM43xx_DMA64_RXSTAT_DISABLED) { |
236 | break; | 254 | i = -1; |
255 | break; | ||
256 | } | ||
257 | } else { | ||
258 | value &= BCM43xx_DMA32_RXSTATE; | ||
259 | if (value == BCM43xx_DMA32_RXSTAT_DISABLED) { | ||
260 | i = -1; | ||
261 | break; | ||
262 | } | ||
237 | } | 263 | } |
238 | udelay(10); | 264 | udelay(10); |
239 | } | 265 | } |
@@ -247,31 +273,47 @@ int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, | |||
247 | 273 | ||
248 | /* Reset the RX DMA channel */ | 274 | /* Reset the RX DMA channel */ |
249 | int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, | 275 | int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, |
250 | u16 mmio_base) | 276 | u16 mmio_base, int dma64) |
251 | { | 277 | { |
252 | int i; | 278 | int i; |
253 | u32 value; | 279 | u32 value; |
280 | u16 offset; | ||
254 | 281 | ||
255 | for (i = 0; i < 1000; i++) { | 282 | for (i = 0; i < 1000; i++) { |
256 | value = bcm43xx_read32(bcm, | 283 | offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS; |
257 | mmio_base + BCM43xx_DMA_TX_STATUS); | 284 | value = bcm43xx_read32(bcm, mmio_base + offset); |
258 | value &= BCM43xx_DMA_TXSTAT_STAT_MASK; | 285 | if (dma64) { |
259 | if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED || | 286 | value &= BCM43xx_DMA64_TXSTAT; |
260 | value == BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT || | 287 | if (value == BCM43xx_DMA64_TXSTAT_DISABLED || |
261 | value == BCM43xx_DMA_TXSTAT_STAT_STOPPED) | 288 | value == BCM43xx_DMA64_TXSTAT_IDLEWAIT || |
262 | break; | 289 | value == BCM43xx_DMA64_TXSTAT_STOPPED) |
290 | break; | ||
291 | } else { | ||
292 | value &= BCM43xx_DMA32_TXSTATE; | ||
293 | if (value == BCM43xx_DMA32_TXSTAT_DISABLED || | ||
294 | value == BCM43xx_DMA32_TXSTAT_IDLEWAIT || | ||
295 | value == BCM43xx_DMA32_TXSTAT_STOPPED) | ||
296 | break; | ||
297 | } | ||
263 | udelay(10); | 298 | udelay(10); |
264 | } | 299 | } |
265 | bcm43xx_write32(bcm, | 300 | offset = dma64 ? BCM43xx_DMA64_TXCTL : BCM43xx_DMA32_TXCTL; |
266 | mmio_base + BCM43xx_DMA_TX_CONTROL, | 301 | bcm43xx_write32(bcm, mmio_base + offset, 0); |
267 | 0x00000000); | ||
268 | for (i = 0; i < 1000; i++) { | 302 | for (i = 0; i < 1000; i++) { |
269 | value = bcm43xx_read32(bcm, | 303 | offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS; |
270 | mmio_base + BCM43xx_DMA_TX_STATUS); | 304 | value = bcm43xx_read32(bcm, mmio_base + offset); |
271 | value &= BCM43xx_DMA_TXSTAT_STAT_MASK; | 305 | if (dma64) { |
272 | if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED) { | 306 | value &= BCM43xx_DMA64_TXSTAT; |
273 | i = -1; | 307 | if (value == BCM43xx_DMA64_TXSTAT_DISABLED) { |
274 | break; | 308 | i = -1; |
309 | break; | ||
310 | } | ||
311 | } else { | ||
312 | value &= BCM43xx_DMA32_TXSTATE; | ||
313 | if (value == BCM43xx_DMA32_TXSTAT_DISABLED) { | ||
314 | i = -1; | ||
315 | break; | ||
316 | } | ||
275 | } | 317 | } |
276 | udelay(10); | 318 | udelay(10); |
277 | } | 319 | } |
@@ -285,47 +327,98 @@ int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, | |||
285 | return 0; | 327 | return 0; |
286 | } | 328 | } |
287 | 329 | ||
330 | static void fill_descriptor(struct bcm43xx_dmaring *ring, | ||
331 | struct bcm43xx_dmadesc_generic *desc, | ||
332 | dma_addr_t dmaaddr, | ||
333 | u16 bufsize, | ||
334 | int start, int end, int irq) | ||
335 | { | ||
336 | int slot; | ||
337 | |||
338 | slot = bcm43xx_dma_desc2idx(ring, desc); | ||
339 | assert(slot >= 0 && slot < ring->nr_slots); | ||
340 | |||
341 | if (ring->dma64) { | ||
342 | u32 ctl0 = 0, ctl1 = 0; | ||
343 | u32 addrlo, addrhi; | ||
344 | u32 addrext; | ||
345 | |||
346 | addrlo = (u32)(dmaaddr & 0xFFFFFFFF); | ||
347 | addrhi = (((u64)dmaaddr >> 32) & ~BCM43xx_DMA64_ROUTING); | ||
348 | addrext = (((u64)dmaaddr >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); | ||
349 | addrhi |= ring->routing; | ||
350 | if (slot == ring->nr_slots - 1) | ||
351 | ctl0 |= BCM43xx_DMA64_DCTL0_DTABLEEND; | ||
352 | if (start) | ||
353 | ctl0 |= BCM43xx_DMA64_DCTL0_FRAMESTART; | ||
354 | if (end) | ||
355 | ctl0 |= BCM43xx_DMA64_DCTL0_FRAMEEND; | ||
356 | if (irq) | ||
357 | ctl0 |= BCM43xx_DMA64_DCTL0_IRQ; | ||
358 | ctl1 |= (bufsize - ring->frameoffset) | ||
359 | & BCM43xx_DMA64_DCTL1_BYTECNT; | ||
360 | ctl1 |= (addrext << BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT) | ||
361 | & BCM43xx_DMA64_DCTL1_ADDREXT_MASK; | ||
362 | |||
363 | desc->dma64.control0 = cpu_to_le32(ctl0); | ||
364 | desc->dma64.control1 = cpu_to_le32(ctl1); | ||
365 | desc->dma64.address_low = cpu_to_le32(addrlo); | ||
366 | desc->dma64.address_high = cpu_to_le32(addrhi); | ||
367 | } else { | ||
368 | u32 ctl; | ||
369 | u32 addr; | ||
370 | u32 addrext; | ||
371 | |||
372 | addr = (u32)(dmaaddr & ~BCM43xx_DMA32_ROUTING); | ||
373 | addrext = (u32)(dmaaddr & BCM43xx_DMA32_ROUTING) | ||
374 | >> BCM43xx_DMA32_ROUTING_SHIFT; | ||
375 | addr |= ring->routing; | ||
376 | ctl = (bufsize - ring->frameoffset) | ||
377 | & BCM43xx_DMA32_DCTL_BYTECNT; | ||
378 | if (slot == ring->nr_slots - 1) | ||
379 | ctl |= BCM43xx_DMA32_DCTL_DTABLEEND; | ||
380 | if (start) | ||
381 | ctl |= BCM43xx_DMA32_DCTL_FRAMESTART; | ||
382 | if (end) | ||
383 | ctl |= BCM43xx_DMA32_DCTL_FRAMEEND; | ||
384 | if (irq) | ||
385 | ctl |= BCM43xx_DMA32_DCTL_IRQ; | ||
386 | ctl |= (addrext << BCM43xx_DMA32_DCTL_ADDREXT_SHIFT) | ||
387 | & BCM43xx_DMA32_DCTL_ADDREXT_MASK; | ||
388 | |||
389 | desc->dma32.control = cpu_to_le32(ctl); | ||
390 | desc->dma32.address = cpu_to_le32(addr); | ||
391 | } | ||
392 | } | ||
393 | |||
288 | static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, | 394 | static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, |
289 | struct bcm43xx_dmadesc *desc, | 395 | struct bcm43xx_dmadesc_generic *desc, |
290 | struct bcm43xx_dmadesc_meta *meta, | 396 | struct bcm43xx_dmadesc_meta *meta, |
291 | gfp_t gfp_flags) | 397 | gfp_t gfp_flags) |
292 | { | 398 | { |
293 | struct bcm43xx_rxhdr *rxhdr; | 399 | struct bcm43xx_rxhdr *rxhdr; |
400 | struct bcm43xx_hwxmitstatus *xmitstat; | ||
294 | dma_addr_t dmaaddr; | 401 | dma_addr_t dmaaddr; |
295 | u32 desc_addr; | ||
296 | u32 desc_ctl; | ||
297 | const int slot = (int)(desc - ring->vbase); | ||
298 | struct sk_buff *skb; | 402 | struct sk_buff *skb; |
299 | 403 | ||
300 | assert(slot >= 0 && slot < ring->nr_slots); | ||
301 | assert(!ring->tx); | 404 | assert(!ring->tx); |
302 | 405 | ||
303 | skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); | 406 | skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); |
304 | if (unlikely(!skb)) | 407 | if (unlikely(!skb)) |
305 | return -ENOMEM; | 408 | return -ENOMEM; |
306 | dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); | 409 | dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); |
307 | if (unlikely(dmaaddr + ring->rx_buffersize > BCM43xx_DMA_BUSADDRMAX)) { | ||
308 | unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); | ||
309 | dev_kfree_skb_any(skb); | ||
310 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G " | ||
311 | "(0x%llx, len: %u)\n", | ||
312 | (unsigned long long)dmaaddr, ring->rx_buffersize); | ||
313 | return -ENOMEM; | ||
314 | } | ||
315 | meta->skb = skb; | 410 | meta->skb = skb; |
316 | meta->dmaaddr = dmaaddr; | 411 | meta->dmaaddr = dmaaddr; |
317 | skb->dev = ring->bcm->net_dev; | 412 | skb->dev = ring->bcm->net_dev; |
318 | desc_addr = (u32)(dmaaddr + ring->memoffset); | 413 | |
319 | desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK & | 414 | fill_descriptor(ring, desc, dmaaddr, |
320 | (u32)(ring->rx_buffersize - ring->frameoffset)); | 415 | ring->rx_buffersize, 0, 0, 0); |
321 | if (slot == ring->nr_slots - 1) | ||
322 | desc_ctl |= BCM43xx_DMADTOR_DTABLEEND; | ||
323 | set_desc_addr(desc, desc_addr); | ||
324 | set_desc_ctl(desc, desc_ctl); | ||
325 | 416 | ||
326 | rxhdr = (struct bcm43xx_rxhdr *)(skb->data); | 417 | rxhdr = (struct bcm43xx_rxhdr *)(skb->data); |
327 | rxhdr->frame_length = 0; | 418 | rxhdr->frame_length = 0; |
328 | rxhdr->flags1 = 0; | 419 | rxhdr->flags1 = 0; |
420 | xmitstat = (struct bcm43xx_hwxmitstatus *)(skb->data); | ||
421 | xmitstat->cookie = 0; | ||
329 | 422 | ||
330 | return 0; | 423 | return 0; |
331 | } | 424 | } |
@@ -336,17 +429,17 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, | |||
336 | static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring) | 429 | static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring) |
337 | { | 430 | { |
338 | int i, err = -ENOMEM; | 431 | int i, err = -ENOMEM; |
339 | struct bcm43xx_dmadesc *desc; | 432 | struct bcm43xx_dmadesc_generic *desc; |
340 | struct bcm43xx_dmadesc_meta *meta; | 433 | struct bcm43xx_dmadesc_meta *meta; |
341 | 434 | ||
342 | for (i = 0; i < ring->nr_slots; i++) { | 435 | for (i = 0; i < ring->nr_slots; i++) { |
343 | desc = ring->vbase + i; | 436 | desc = bcm43xx_dma_idx2desc(ring, i, &meta); |
344 | meta = ring->meta + i; | ||
345 | 437 | ||
346 | err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); | 438 | err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); |
347 | if (err) | 439 | if (err) |
348 | goto err_unwind; | 440 | goto err_unwind; |
349 | } | 441 | } |
442 | mb(); | ||
350 | ring->used_slots = ring->nr_slots; | 443 | ring->used_slots = ring->nr_slots; |
351 | err = 0; | 444 | err = 0; |
352 | out: | 445 | out: |
@@ -354,8 +447,7 @@ out: | |||
354 | 447 | ||
355 | err_unwind: | 448 | err_unwind: |
356 | for (i--; i >= 0; i--) { | 449 | for (i--; i >= 0; i--) { |
357 | desc = ring->vbase + i; | 450 | desc = bcm43xx_dma_idx2desc(ring, i, &meta); |
358 | meta = ring->meta + i; | ||
359 | 451 | ||
360 | unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); | 452 | unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); |
361 | dev_kfree_skb(meta->skb); | 453 | dev_kfree_skb(meta->skb); |
@@ -371,27 +463,67 @@ static int dmacontroller_setup(struct bcm43xx_dmaring *ring) | |||
371 | { | 463 | { |
372 | int err = 0; | 464 | int err = 0; |
373 | u32 value; | 465 | u32 value; |
466 | u32 addrext; | ||
374 | 467 | ||
375 | if (ring->tx) { | 468 | if (ring->tx) { |
376 | /* Set Transmit Control register to "transmit enable" */ | 469 | if (ring->dma64) { |
377 | bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, | 470 | u64 ringbase = (u64)(ring->dmabase); |
378 | BCM43xx_DMA_TXCTRL_ENABLE); | 471 | |
379 | /* Set Transmit Descriptor ring address. */ | 472 | addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); |
380 | bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, | 473 | value = BCM43xx_DMA64_TXENABLE; |
381 | ring->dmabase + ring->memoffset); | 474 | value |= (addrext << BCM43xx_DMA64_TXADDREXT_SHIFT) |
475 | & BCM43xx_DMA64_TXADDREXT_MASK; | ||
476 | bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, value); | ||
477 | bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, | ||
478 | (ringbase & 0xFFFFFFFF)); | ||
479 | bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, | ||
480 | ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING) | ||
481 | | ring->routing); | ||
482 | } else { | ||
483 | u32 ringbase = (u32)(ring->dmabase); | ||
484 | |||
485 | addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT); | ||
486 | value = BCM43xx_DMA32_TXENABLE; | ||
487 | value |= (addrext << BCM43xx_DMA32_TXADDREXT_SHIFT) | ||
488 | & BCM43xx_DMA32_TXADDREXT_MASK; | ||
489 | bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, value); | ||
490 | bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, | ||
491 | (ringbase & ~BCM43xx_DMA32_ROUTING) | ||
492 | | ring->routing); | ||
493 | } | ||
382 | } else { | 494 | } else { |
383 | err = alloc_initial_descbuffers(ring); | 495 | err = alloc_initial_descbuffers(ring); |
384 | if (err) | 496 | if (err) |
385 | goto out; | 497 | goto out; |
386 | /* Set Receive Control "receive enable" and frame offset */ | 498 | if (ring->dma64) { |
387 | value = (ring->frameoffset << BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT); | 499 | u64 ringbase = (u64)(ring->dmabase); |
388 | value |= BCM43xx_DMA_RXCTRL_ENABLE; | 500 | |
389 | bcm43xx_dma_write(ring, BCM43xx_DMA_RX_CONTROL, value); | 501 | addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); |
390 | /* Set Receive Descriptor ring address. */ | 502 | value = (ring->frameoffset << BCM43xx_DMA64_RXFROFF_SHIFT); |
391 | bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, | 503 | value |= BCM43xx_DMA64_RXENABLE; |
392 | ring->dmabase + ring->memoffset); | 504 | value |= (addrext << BCM43xx_DMA64_RXADDREXT_SHIFT) |
393 | /* Init the descriptor pointer. */ | 505 | & BCM43xx_DMA64_RXADDREXT_MASK; |
394 | bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, 200); | 506 | bcm43xx_dma_write(ring, BCM43xx_DMA64_RXCTL, value); |
507 | bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, | ||
508 | (ringbase & 0xFFFFFFFF)); | ||
509 | bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, | ||
510 | ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING) | ||
511 | | ring->routing); | ||
512 | bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, 200); | ||
513 | } else { | ||
514 | u32 ringbase = (u32)(ring->dmabase); | ||
515 | |||
516 | addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT); | ||
517 | value = (ring->frameoffset << BCM43xx_DMA32_RXFROFF_SHIFT); | ||
518 | value |= BCM43xx_DMA32_RXENABLE; | ||
519 | value |= (addrext << BCM43xx_DMA32_RXADDREXT_SHIFT) | ||
520 | & BCM43xx_DMA32_RXADDREXT_MASK; | ||
521 | bcm43xx_dma_write(ring, BCM43xx_DMA32_RXCTL, value); | ||
522 | bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, | ||
523 | (ringbase & ~BCM43xx_DMA32_ROUTING) | ||
524 | | ring->routing); | ||
525 | bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, 200); | ||
526 | } | ||
395 | } | 527 | } |
396 | 528 | ||
397 | out: | 529 | out: |
@@ -402,27 +534,32 @@ out: | |||
402 | static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring) | 534 | static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring) |
403 | { | 535 | { |
404 | if (ring->tx) { | 536 | if (ring->tx) { |
405 | bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base); | 537 | bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base, ring->dma64); |
406 | /* Zero out Transmit Descriptor ring address. */ | 538 | if (ring->dma64) { |
407 | bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, 0); | 539 | bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, 0); |
540 | bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, 0); | ||
541 | } else | ||
542 | bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, 0); | ||
408 | } else { | 543 | } else { |
409 | bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base); | 544 | bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base, ring->dma64); |
410 | /* Zero out Receive Descriptor ring address. */ | 545 | if (ring->dma64) { |
411 | bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, 0); | 546 | bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, 0); |
547 | bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, 0); | ||
548 | } else | ||
549 | bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, 0); | ||
412 | } | 550 | } |
413 | } | 551 | } |
414 | 552 | ||
415 | static void free_all_descbuffers(struct bcm43xx_dmaring *ring) | 553 | static void free_all_descbuffers(struct bcm43xx_dmaring *ring) |
416 | { | 554 | { |
417 | struct bcm43xx_dmadesc *desc; | 555 | struct bcm43xx_dmadesc_generic *desc; |
418 | struct bcm43xx_dmadesc_meta *meta; | 556 | struct bcm43xx_dmadesc_meta *meta; |
419 | int i; | 557 | int i; |
420 | 558 | ||
421 | if (!ring->used_slots) | 559 | if (!ring->used_slots) |
422 | return; | 560 | return; |
423 | for (i = 0; i < ring->nr_slots; i++) { | 561 | for (i = 0; i < ring->nr_slots; i++) { |
424 | desc = ring->vbase + i; | 562 | desc = bcm43xx_dma_idx2desc(ring, i, &meta); |
425 | meta = ring->meta + i; | ||
426 | 563 | ||
427 | if (!meta->skb) { | 564 | if (!meta->skb) { |
428 | assert(ring->tx); | 565 | assert(ring->tx); |
@@ -430,62 +567,67 @@ static void free_all_descbuffers(struct bcm43xx_dmaring *ring) | |||
430 | } | 567 | } |
431 | if (ring->tx) { | 568 | if (ring->tx) { |
432 | unmap_descbuffer(ring, meta->dmaaddr, | 569 | unmap_descbuffer(ring, meta->dmaaddr, |
433 | meta->skb->len, 1); | 570 | meta->skb->len, 1); |
434 | } else { | 571 | } else { |
435 | unmap_descbuffer(ring, meta->dmaaddr, | 572 | unmap_descbuffer(ring, meta->dmaaddr, |
436 | ring->rx_buffersize, 0); | 573 | ring->rx_buffersize, 0); |
437 | } | 574 | } |
438 | free_descriptor_buffer(ring, desc, meta, 0); | 575 | free_descriptor_buffer(ring, meta, 0); |
439 | } | 576 | } |
440 | } | 577 | } |
441 | 578 | ||
442 | /* Main initialization function. */ | 579 | /* Main initialization function. */ |
443 | static | 580 | static |
444 | struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm, | 581 | struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm, |
445 | u16 dma_controller_base, | 582 | int controller_index, |
446 | int nr_descriptor_slots, | 583 | int for_tx, |
447 | int tx) | 584 | int dma64) |
448 | { | 585 | { |
449 | struct bcm43xx_dmaring *ring; | 586 | struct bcm43xx_dmaring *ring; |
450 | int err; | 587 | int err; |
588 | int nr_slots; | ||
451 | 589 | ||
452 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); | 590 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); |
453 | if (!ring) | 591 | if (!ring) |
454 | goto out; | 592 | goto out; |
455 | 593 | ||
456 | ring->meta = kzalloc(sizeof(*ring->meta) * nr_descriptor_slots, | 594 | nr_slots = BCM43xx_RXRING_SLOTS; |
595 | if (for_tx) | ||
596 | nr_slots = BCM43xx_TXRING_SLOTS; | ||
597 | |||
598 | ring->meta = kcalloc(nr_slots, sizeof(struct bcm43xx_dmadesc_meta), | ||
457 | GFP_KERNEL); | 599 | GFP_KERNEL); |
458 | if (!ring->meta) | 600 | if (!ring->meta) |
459 | goto err_kfree_ring; | 601 | goto err_kfree_ring; |
460 | 602 | ||
461 | ring->memoffset = BCM43xx_DMA_DMABUSADDROFFSET; | 603 | ring->routing = BCM43xx_DMA32_CLIENTTRANS; |
604 | if (dma64) | ||
605 | ring->routing = BCM43xx_DMA64_CLIENTTRANS; | ||
462 | #ifdef CONFIG_BCM947XX | 606 | #ifdef CONFIG_BCM947XX |
463 | if (bcm->pci_dev->bus->number == 0) | 607 | if (bcm->pci_dev->bus->number == 0) |
464 | ring->memoffset = 0; | 608 | ring->routing = dma64 ? BCM43xx_DMA64_NOTRANS : BCM43xx_DMA32_NOTRANS; |
465 | #endif | 609 | #endif |
466 | 610 | ||
467 | ring->bcm = bcm; | 611 | ring->bcm = bcm; |
468 | ring->nr_slots = nr_descriptor_slots; | 612 | ring->nr_slots = nr_slots; |
469 | ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100; | 613 | ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100; |
470 | ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100; | 614 | ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100; |
471 | assert(ring->suspend_mark < ring->resume_mark); | 615 | assert(ring->suspend_mark < ring->resume_mark); |
472 | ring->mmio_base = dma_controller_base; | 616 | ring->mmio_base = bcm43xx_dmacontroller_base(dma64, controller_index); |
473 | if (tx) { | 617 | ring->index = controller_index; |
618 | ring->dma64 = !!dma64; | ||
619 | if (for_tx) { | ||
474 | ring->tx = 1; | 620 | ring->tx = 1; |
475 | ring->current_slot = -1; | 621 | ring->current_slot = -1; |
476 | } else { | 622 | } else { |
477 | switch (dma_controller_base) { | 623 | if (ring->index == 0) { |
478 | case BCM43xx_MMIO_DMA1_BASE: | 624 | ring->rx_buffersize = BCM43xx_DMA0_RX_BUFFERSIZE; |
479 | ring->rx_buffersize = BCM43xx_DMA1_RXBUFFERSIZE; | 625 | ring->frameoffset = BCM43xx_DMA0_RX_FRAMEOFFSET; |
480 | ring->frameoffset = BCM43xx_DMA1_RX_FRAMEOFFSET; | 626 | } else if (ring->index == 3) { |
481 | break; | 627 | ring->rx_buffersize = BCM43xx_DMA3_RX_BUFFERSIZE; |
482 | case BCM43xx_MMIO_DMA4_BASE: | 628 | ring->frameoffset = BCM43xx_DMA3_RX_FRAMEOFFSET; |
483 | ring->rx_buffersize = BCM43xx_DMA4_RXBUFFERSIZE; | 629 | } else |
484 | ring->frameoffset = BCM43xx_DMA4_RX_FRAMEOFFSET; | ||
485 | break; | ||
486 | default: | ||
487 | assert(0); | 630 | assert(0); |
488 | } | ||
489 | } | 631 | } |
490 | 632 | ||
491 | err = alloc_ringmemory(ring); | 633 | err = alloc_ringmemory(ring); |
@@ -514,7 +656,8 @@ static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring) | |||
514 | if (!ring) | 656 | if (!ring) |
515 | return; | 657 | return; |
516 | 658 | ||
517 | dprintk(KERN_INFO PFX "DMA 0x%04x (%s) max used slots: %d/%d\n", | 659 | dprintk(KERN_INFO PFX "DMA-%s 0x%04X (%s) max used slots: %d/%d\n", |
660 | (ring->dma64) ? "64" : "32", | ||
518 | ring->mmio_base, | 661 | ring->mmio_base, |
519 | (ring->tx) ? "TX" : "RX", | 662 | (ring->tx) ? "TX" : "RX", |
520 | ring->max_used_slots, ring->nr_slots); | 663 | ring->max_used_slots, ring->nr_slots); |
@@ -537,10 +680,15 @@ void bcm43xx_dma_free(struct bcm43xx_private *bcm) | |||
537 | return; | 680 | return; |
538 | dma = bcm43xx_current_dma(bcm); | 681 | dma = bcm43xx_current_dma(bcm); |
539 | 682 | ||
540 | bcm43xx_destroy_dmaring(dma->rx_ring1); | 683 | bcm43xx_destroy_dmaring(dma->rx_ring3); |
541 | dma->rx_ring1 = NULL; | 684 | dma->rx_ring3 = NULL; |
542 | bcm43xx_destroy_dmaring(dma->rx_ring0); | 685 | bcm43xx_destroy_dmaring(dma->rx_ring0); |
543 | dma->rx_ring0 = NULL; | 686 | dma->rx_ring0 = NULL; |
687 | |||
688 | bcm43xx_destroy_dmaring(dma->tx_ring5); | ||
689 | dma->tx_ring5 = NULL; | ||
690 | bcm43xx_destroy_dmaring(dma->tx_ring4); | ||
691 | dma->tx_ring4 = NULL; | ||
544 | bcm43xx_destroy_dmaring(dma->tx_ring3); | 692 | bcm43xx_destroy_dmaring(dma->tx_ring3); |
545 | dma->tx_ring3 = NULL; | 693 | dma->tx_ring3 = NULL; |
546 | bcm43xx_destroy_dmaring(dma->tx_ring2); | 694 | bcm43xx_destroy_dmaring(dma->tx_ring2); |
@@ -556,48 +704,59 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm) | |||
556 | struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); | 704 | struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); |
557 | struct bcm43xx_dmaring *ring; | 705 | struct bcm43xx_dmaring *ring; |
558 | int err = -ENOMEM; | 706 | int err = -ENOMEM; |
707 | int dma64 = 0; | ||
708 | u32 sbtmstatehi; | ||
709 | |||
710 | sbtmstatehi = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); | ||
711 | if (sbtmstatehi & BCM43xx_SBTMSTATEHIGH_DMA64BIT) | ||
712 | dma64 = 1; | ||
559 | 713 | ||
560 | /* setup TX DMA channels. */ | 714 | /* setup TX DMA channels. */ |
561 | ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE, | 715 | ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64); |
562 | BCM43xx_TXRING_SLOTS, 1); | ||
563 | if (!ring) | 716 | if (!ring) |
564 | goto out; | 717 | goto out; |
565 | dma->tx_ring0 = ring; | 718 | dma->tx_ring0 = ring; |
566 | 719 | ||
567 | ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA2_BASE, | 720 | ring = bcm43xx_setup_dmaring(bcm, 1, 1, dma64); |
568 | BCM43xx_TXRING_SLOTS, 1); | ||
569 | if (!ring) | 721 | if (!ring) |
570 | goto err_destroy_tx0; | 722 | goto err_destroy_tx0; |
571 | dma->tx_ring1 = ring; | 723 | dma->tx_ring1 = ring; |
572 | 724 | ||
573 | ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA3_BASE, | 725 | ring = bcm43xx_setup_dmaring(bcm, 2, 1, dma64); |
574 | BCM43xx_TXRING_SLOTS, 1); | ||
575 | if (!ring) | 726 | if (!ring) |
576 | goto err_destroy_tx1; | 727 | goto err_destroy_tx1; |
577 | dma->tx_ring2 = ring; | 728 | dma->tx_ring2 = ring; |
578 | 729 | ||
579 | ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, | 730 | ring = bcm43xx_setup_dmaring(bcm, 3, 1, dma64); |
580 | BCM43xx_TXRING_SLOTS, 1); | ||
581 | if (!ring) | 731 | if (!ring) |
582 | goto err_destroy_tx2; | 732 | goto err_destroy_tx2; |
583 | dma->tx_ring3 = ring; | 733 | dma->tx_ring3 = ring; |
584 | 734 | ||
585 | /* setup RX DMA channels. */ | 735 | ring = bcm43xx_setup_dmaring(bcm, 4, 1, dma64); |
586 | ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE, | ||
587 | BCM43xx_RXRING_SLOTS, 0); | ||
588 | if (!ring) | 736 | if (!ring) |
589 | goto err_destroy_tx3; | 737 | goto err_destroy_tx3; |
738 | dma->tx_ring4 = ring; | ||
739 | |||
740 | ring = bcm43xx_setup_dmaring(bcm, 5, 1, dma64); | ||
741 | if (!ring) | ||
742 | goto err_destroy_tx4; | ||
743 | dma->tx_ring5 = ring; | ||
744 | |||
745 | /* setup RX DMA channels. */ | ||
746 | ring = bcm43xx_setup_dmaring(bcm, 0, 0, dma64); | ||
747 | if (!ring) | ||
748 | goto err_destroy_tx5; | ||
590 | dma->rx_ring0 = ring; | 749 | dma->rx_ring0 = ring; |
591 | 750 | ||
592 | if (bcm->current_core->rev < 5) { | 751 | if (bcm->current_core->rev < 5) { |
593 | ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, | 752 | ring = bcm43xx_setup_dmaring(bcm, 3, 0, dma64); |
594 | BCM43xx_RXRING_SLOTS, 0); | ||
595 | if (!ring) | 753 | if (!ring) |
596 | goto err_destroy_rx0; | 754 | goto err_destroy_rx0; |
597 | dma->rx_ring1 = ring; | 755 | dma->rx_ring3 = ring; |
598 | } | 756 | } |
599 | 757 | ||
600 | dprintk(KERN_INFO PFX "DMA initialized\n"); | 758 | dprintk(KERN_INFO PFX "%s DMA initialized\n", |
759 | dma64 ? "64-bit" : "32-bit"); | ||
601 | err = 0; | 760 | err = 0; |
602 | out: | 761 | out: |
603 | return err; | 762 | return err; |
@@ -605,6 +764,12 @@ out: | |||
605 | err_destroy_rx0: | 764 | err_destroy_rx0: |
606 | bcm43xx_destroy_dmaring(dma->rx_ring0); | 765 | bcm43xx_destroy_dmaring(dma->rx_ring0); |
607 | dma->rx_ring0 = NULL; | 766 | dma->rx_ring0 = NULL; |
767 | err_destroy_tx5: | ||
768 | bcm43xx_destroy_dmaring(dma->tx_ring5); | ||
769 | dma->tx_ring5 = NULL; | ||
770 | err_destroy_tx4: | ||
771 | bcm43xx_destroy_dmaring(dma->tx_ring4); | ||
772 | dma->tx_ring4 = NULL; | ||
608 | err_destroy_tx3: | 773 | err_destroy_tx3: |
609 | bcm43xx_destroy_dmaring(dma->tx_ring3); | 774 | bcm43xx_destroy_dmaring(dma->tx_ring3); |
610 | dma->tx_ring3 = NULL; | 775 | dma->tx_ring3 = NULL; |
@@ -624,7 +789,7 @@ err_destroy_tx0: | |||
624 | static u16 generate_cookie(struct bcm43xx_dmaring *ring, | 789 | static u16 generate_cookie(struct bcm43xx_dmaring *ring, |
625 | int slot) | 790 | int slot) |
626 | { | 791 | { |
627 | u16 cookie = 0xF000; | 792 | u16 cookie = 0x1000; |
628 | 793 | ||
629 | /* Use the upper 4 bits of the cookie as | 794 | /* Use the upper 4 bits of the cookie as |
630 | * DMA controller ID and store the slot number | 795 | * DMA controller ID and store the slot number |
@@ -632,21 +797,25 @@ static u16 generate_cookie(struct bcm43xx_dmaring *ring, | |||
632 | * Note that the cookie must never be 0, as this | 797 | * Note that the cookie must never be 0, as this |
633 | * is a special value used in RX path. | 798 | * is a special value used in RX path. |
634 | */ | 799 | */ |
635 | switch (ring->mmio_base) { | 800 | switch (ring->index) { |
636 | default: | 801 | case 0: |
637 | assert(0); | ||
638 | case BCM43xx_MMIO_DMA1_BASE: | ||
639 | cookie = 0xA000; | 802 | cookie = 0xA000; |
640 | break; | 803 | break; |
641 | case BCM43xx_MMIO_DMA2_BASE: | 804 | case 1: |
642 | cookie = 0xB000; | 805 | cookie = 0xB000; |
643 | break; | 806 | break; |
644 | case BCM43xx_MMIO_DMA3_BASE: | 807 | case 2: |
645 | cookie = 0xC000; | 808 | cookie = 0xC000; |
646 | break; | 809 | break; |
647 | case BCM43xx_MMIO_DMA4_BASE: | 810 | case 3: |
648 | cookie = 0xD000; | 811 | cookie = 0xD000; |
649 | break; | 812 | break; |
813 | case 4: | ||
814 | cookie = 0xE000; | ||
815 | break; | ||
816 | case 5: | ||
817 | cookie = 0xF000; | ||
818 | break; | ||
650 | } | 819 | } |
651 | assert(((u16)slot & 0xF000) == 0x0000); | 820 | assert(((u16)slot & 0xF000) == 0x0000); |
652 | cookie |= (u16)slot; | 821 | cookie |= (u16)slot; |
@@ -675,6 +844,12 @@ struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, | |||
675 | case 0xD000: | 844 | case 0xD000: |
676 | ring = dma->tx_ring3; | 845 | ring = dma->tx_ring3; |
677 | break; | 846 | break; |
847 | case 0xE000: | ||
848 | ring = dma->tx_ring4; | ||
849 | break; | ||
850 | case 0xF000: | ||
851 | ring = dma->tx_ring5; | ||
852 | break; | ||
678 | default: | 853 | default: |
679 | assert(0); | 854 | assert(0); |
680 | } | 855 | } |
@@ -687,6 +862,9 @@ struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, | |||
687 | static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, | 862 | static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, |
688 | int slot) | 863 | int slot) |
689 | { | 864 | { |
865 | u16 offset; | ||
866 | int descsize; | ||
867 | |||
690 | /* Everything is ready to start. Buffers are DMA mapped and | 868 | /* Everything is ready to start. Buffers are DMA mapped and |
691 | * associated with slots. | 869 | * associated with slots. |
692 | * "slot" is the last slot of the new frame we want to transmit. | 870 | * "slot" is the last slot of the new frame we want to transmit. |
@@ -694,25 +872,26 @@ static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, | |||
694 | */ | 872 | */ |
695 | wmb(); | 873 | wmb(); |
696 | slot = next_slot(ring, slot); | 874 | slot = next_slot(ring, slot); |
697 | bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_INDEX, | 875 | offset = (ring->dma64) ? BCM43xx_DMA64_TXINDEX : BCM43xx_DMA32_TXINDEX; |
698 | (u32)(slot * sizeof(struct bcm43xx_dmadesc))); | 876 | descsize = (ring->dma64) ? sizeof(struct bcm43xx_dmadesc64) |
877 | : sizeof(struct bcm43xx_dmadesc32); | ||
878 | bcm43xx_dma_write(ring, offset, | ||
879 | (u32)(slot * descsize)); | ||
699 | } | 880 | } |
700 | 881 | ||
701 | static int dma_tx_fragment(struct bcm43xx_dmaring *ring, | 882 | static void dma_tx_fragment(struct bcm43xx_dmaring *ring, |
702 | struct sk_buff *skb, | 883 | struct sk_buff *skb, |
703 | u8 cur_frag) | 884 | u8 cur_frag) |
704 | { | 885 | { |
705 | int slot; | 886 | int slot; |
706 | struct bcm43xx_dmadesc *desc; | 887 | struct bcm43xx_dmadesc_generic *desc; |
707 | struct bcm43xx_dmadesc_meta *meta; | 888 | struct bcm43xx_dmadesc_meta *meta; |
708 | u32 desc_ctl; | 889 | dma_addr_t dmaaddr; |
709 | u32 desc_addr; | ||
710 | 890 | ||
711 | assert(skb_shinfo(skb)->nr_frags == 0); | 891 | assert(skb_shinfo(skb)->nr_frags == 0); |
712 | 892 | ||
713 | slot = request_slot(ring); | 893 | slot = request_slot(ring); |
714 | desc = ring->vbase + slot; | 894 | desc = bcm43xx_dma_idx2desc(ring, slot, &meta); |
715 | meta = ring->meta + slot; | ||
716 | 895 | ||
717 | /* Add a device specific TX header. */ | 896 | /* Add a device specific TX header. */ |
718 | assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); | 897 | assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); |
@@ -729,29 +908,14 @@ static int dma_tx_fragment(struct bcm43xx_dmaring *ring, | |||
729 | generate_cookie(ring, slot)); | 908 | generate_cookie(ring, slot)); |
730 | 909 | ||
731 | meta->skb = skb; | 910 | meta->skb = skb; |
732 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); | 911 | dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); |
733 | if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) { | 912 | meta->dmaaddr = dmaaddr; |
734 | return_slot(ring, slot); | ||
735 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G " | ||
736 | "(0x%llx, len: %u)\n", | ||
737 | (unsigned long long)meta->dmaaddr, skb->len); | ||
738 | return -ENOMEM; | ||
739 | } | ||
740 | 913 | ||
741 | desc_addr = (u32)(meta->dmaaddr + ring->memoffset); | 914 | fill_descriptor(ring, desc, dmaaddr, |
742 | desc_ctl = BCM43xx_DMADTOR_FRAMESTART | BCM43xx_DMADTOR_FRAMEEND; | 915 | skb->len, 1, 1, 1); |
743 | desc_ctl |= BCM43xx_DMADTOR_COMPIRQ; | ||
744 | desc_ctl |= (BCM43xx_DMADTOR_BYTECNT_MASK & | ||
745 | (u32)(meta->skb->len - ring->frameoffset)); | ||
746 | if (slot == ring->nr_slots - 1) | ||
747 | desc_ctl |= BCM43xx_DMADTOR_DTABLEEND; | ||
748 | 916 | ||
749 | set_desc_ctl(desc, desc_ctl); | ||
750 | set_desc_addr(desc, desc_addr); | ||
751 | /* Now transfer the whole frame. */ | 917 | /* Now transfer the whole frame. */ |
752 | dmacontroller_poke_tx(ring, slot); | 918 | dmacontroller_poke_tx(ring, slot); |
753 | |||
754 | return 0; | ||
755 | } | 919 | } |
756 | 920 | ||
757 | int bcm43xx_dma_tx(struct bcm43xx_private *bcm, | 921 | int bcm43xx_dma_tx(struct bcm43xx_private *bcm, |
@@ -781,7 +945,6 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, | |||
781 | /* Take skb from ieee80211_txb_free */ | 945 | /* Take skb from ieee80211_txb_free */ |
782 | txb->fragments[i] = NULL; | 946 | txb->fragments[i] = NULL; |
783 | dma_tx_fragment(ring, skb, i); | 947 | dma_tx_fragment(ring, skb, i); |
784 | //TODO: handle failure of dma_tx_fragment | ||
785 | } | 948 | } |
786 | ieee80211_txb_free(txb); | 949 | ieee80211_txb_free(txb); |
787 | 950 | ||
@@ -792,23 +955,28 @@ void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
792 | struct bcm43xx_xmitstatus *status) | 955 | struct bcm43xx_xmitstatus *status) |
793 | { | 956 | { |
794 | struct bcm43xx_dmaring *ring; | 957 | struct bcm43xx_dmaring *ring; |
795 | struct bcm43xx_dmadesc *desc; | 958 | struct bcm43xx_dmadesc_generic *desc; |
796 | struct bcm43xx_dmadesc_meta *meta; | 959 | struct bcm43xx_dmadesc_meta *meta; |
797 | int is_last_fragment; | 960 | int is_last_fragment; |
798 | int slot; | 961 | int slot; |
962 | u32 tmp; | ||
799 | 963 | ||
800 | ring = parse_cookie(bcm, status->cookie, &slot); | 964 | ring = parse_cookie(bcm, status->cookie, &slot); |
801 | assert(ring); | 965 | assert(ring); |
802 | assert(ring->tx); | 966 | assert(ring->tx); |
803 | assert(get_desc_ctl(ring->vbase + slot) & BCM43xx_DMADTOR_FRAMESTART); | ||
804 | while (1) { | 967 | while (1) { |
805 | assert(slot >= 0 && slot < ring->nr_slots); | 968 | assert(slot >= 0 && slot < ring->nr_slots); |
806 | desc = ring->vbase + slot; | 969 | desc = bcm43xx_dma_idx2desc(ring, slot, &meta); |
807 | meta = ring->meta + slot; | ||
808 | 970 | ||
809 | is_last_fragment = !!(get_desc_ctl(desc) & BCM43xx_DMADTOR_FRAMEEND); | 971 | if (ring->dma64) { |
972 | tmp = le32_to_cpu(desc->dma64.control0); | ||
973 | is_last_fragment = !!(tmp & BCM43xx_DMA64_DCTL0_FRAMEEND); | ||
974 | } else { | ||
975 | tmp = le32_to_cpu(desc->dma32.control); | ||
976 | is_last_fragment = !!(tmp & BCM43xx_DMA32_DCTL_FRAMEEND); | ||
977 | } | ||
810 | unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); | 978 | unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); |
811 | free_descriptor_buffer(ring, desc, meta, 1); | 979 | free_descriptor_buffer(ring, meta, 1); |
812 | /* Everything belonging to the slot is unmapped | 980 | /* Everything belonging to the slot is unmapped |
813 | * and freed, so we can return it. | 981 | * and freed, so we can return it. |
814 | */ | 982 | */ |
@@ -824,7 +992,7 @@ void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
824 | static void dma_rx(struct bcm43xx_dmaring *ring, | 992 | static void dma_rx(struct bcm43xx_dmaring *ring, |
825 | int *slot) | 993 | int *slot) |
826 | { | 994 | { |
827 | struct bcm43xx_dmadesc *desc; | 995 | struct bcm43xx_dmadesc_generic *desc; |
828 | struct bcm43xx_dmadesc_meta *meta; | 996 | struct bcm43xx_dmadesc_meta *meta; |
829 | struct bcm43xx_rxhdr *rxhdr; | 997 | struct bcm43xx_rxhdr *rxhdr; |
830 | struct sk_buff *skb; | 998 | struct sk_buff *skb; |
@@ -832,13 +1000,12 @@ static void dma_rx(struct bcm43xx_dmaring *ring, | |||
832 | int err; | 1000 | int err; |
833 | dma_addr_t dmaaddr; | 1001 | dma_addr_t dmaaddr; |
834 | 1002 | ||
835 | desc = ring->vbase + *slot; | 1003 | desc = bcm43xx_dma_idx2desc(ring, *slot, &meta); |
836 | meta = ring->meta + *slot; | ||
837 | 1004 | ||
838 | sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); | 1005 | sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); |
839 | skb = meta->skb; | 1006 | skb = meta->skb; |
840 | 1007 | ||
841 | if (ring->mmio_base == BCM43xx_MMIO_DMA4_BASE) { | 1008 | if (ring->index == 3) { |
842 | /* We received an xmit status. */ | 1009 | /* We received an xmit status. */ |
843 | struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data; | 1010 | struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data; |
844 | struct bcm43xx_xmitstatus stat; | 1011 | struct bcm43xx_xmitstatus stat; |
@@ -894,8 +1061,7 @@ static void dma_rx(struct bcm43xx_dmaring *ring, | |||
894 | s32 tmp = len; | 1061 | s32 tmp = len; |
895 | 1062 | ||
896 | while (1) { | 1063 | while (1) { |
897 | desc = ring->vbase + *slot; | 1064 | desc = bcm43xx_dma_idx2desc(ring, *slot, &meta); |
898 | meta = ring->meta + *slot; | ||
899 | /* recycle the descriptor buffer. */ | 1065 | /* recycle the descriptor buffer. */ |
900 | sync_descbuffer_for_device(ring, meta->dmaaddr, | 1066 | sync_descbuffer_for_device(ring, meta->dmaaddr, |
901 | ring->rx_buffersize); | 1067 | ring->rx_buffersize); |
@@ -906,8 +1072,8 @@ static void dma_rx(struct bcm43xx_dmaring *ring, | |||
906 | break; | 1072 | break; |
907 | } | 1073 | } |
908 | printkl(KERN_ERR PFX "DMA RX buffer too small " | 1074 | printkl(KERN_ERR PFX "DMA RX buffer too small " |
909 | "(len: %u, buffer: %u, nr-dropped: %d)\n", | 1075 | "(len: %u, buffer: %u, nr-dropped: %d)\n", |
910 | len, ring->rx_buffersize, cnt); | 1076 | len, ring->rx_buffersize, cnt); |
911 | goto drop; | 1077 | goto drop; |
912 | } | 1078 | } |
913 | len -= IEEE80211_FCS_LEN; | 1079 | len -= IEEE80211_FCS_LEN; |
@@ -945,9 +1111,15 @@ void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) | |||
945 | #endif | 1111 | #endif |
946 | 1112 | ||
947 | assert(!ring->tx); | 1113 | assert(!ring->tx); |
948 | status = bcm43xx_dma_read(ring, BCM43xx_DMA_RX_STATUS); | 1114 | if (ring->dma64) { |
949 | descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK); | 1115 | status = bcm43xx_dma_read(ring, BCM43xx_DMA64_RXSTATUS); |
950 | current_slot = descptr / sizeof(struct bcm43xx_dmadesc); | 1116 | descptr = (status & BCM43xx_DMA64_RXSTATDPTR); |
1117 | current_slot = descptr / sizeof(struct bcm43xx_dmadesc64); | ||
1118 | } else { | ||
1119 | status = bcm43xx_dma_read(ring, BCM43xx_DMA32_RXSTATUS); | ||
1120 | descptr = (status & BCM43xx_DMA32_RXDPTR); | ||
1121 | current_slot = descptr / sizeof(struct bcm43xx_dmadesc32); | ||
1122 | } | ||
951 | assert(current_slot >= 0 && current_slot < ring->nr_slots); | 1123 | assert(current_slot >= 0 && current_slot < ring->nr_slots); |
952 | 1124 | ||
953 | slot = ring->current_slot; | 1125 | slot = ring->current_slot; |
@@ -958,8 +1130,13 @@ void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) | |||
958 | ring->max_used_slots = used_slots; | 1130 | ring->max_used_slots = used_slots; |
959 | #endif | 1131 | #endif |
960 | } | 1132 | } |
961 | bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, | 1133 | if (ring->dma64) { |
962 | (u32)(slot * sizeof(struct bcm43xx_dmadesc))); | 1134 | bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, |
1135 | (u32)(slot * sizeof(struct bcm43xx_dmadesc64))); | ||
1136 | } else { | ||
1137 | bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, | ||
1138 | (u32)(slot * sizeof(struct bcm43xx_dmadesc32))); | ||
1139 | } | ||
963 | ring->current_slot = slot; | 1140 | ring->current_slot = slot; |
964 | } | 1141 | } |
965 | 1142 | ||
@@ -967,16 +1144,28 @@ void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) | |||
967 | { | 1144 | { |
968 | assert(ring->tx); | 1145 | assert(ring->tx); |
969 | bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1); | 1146 | bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1); |
970 | bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, | 1147 | if (ring->dma64) { |
971 | bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL) | 1148 | bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, |
972 | | BCM43xx_DMA_TXCTRL_SUSPEND); | 1149 | bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL) |
1150 | | BCM43xx_DMA64_TXSUSPEND); | ||
1151 | } else { | ||
1152 | bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, | ||
1153 | bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL) | ||
1154 | | BCM43xx_DMA32_TXSUSPEND); | ||
1155 | } | ||
973 | } | 1156 | } |
974 | 1157 | ||
975 | void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) | 1158 | void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) |
976 | { | 1159 | { |
977 | assert(ring->tx); | 1160 | assert(ring->tx); |
978 | bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, | 1161 | if (ring->dma64) { |
979 | bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL) | 1162 | bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, |
980 | & ~BCM43xx_DMA_TXCTRL_SUSPEND); | 1163 | bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL) |
1164 | & ~BCM43xx_DMA64_TXSUSPEND); | ||
1165 | } else { | ||
1166 | bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, | ||
1167 | bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL) | ||
1168 | & ~BCM43xx_DMA32_TXSUSPEND); | ||
1169 | } | ||
981 | bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1); | 1170 | bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1); |
982 | } | 1171 | } |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index b7d77638ba8c..e04bcaddd1d0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h | |||
@@ -14,63 +14,179 @@ | |||
14 | #define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13) | 14 | #define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13) |
15 | #define BCM43xx_DMAIRQ_RX_DONE (1 << 16) | 15 | #define BCM43xx_DMAIRQ_RX_DONE (1 << 16) |
16 | 16 | ||
17 | /* DMA controller register offsets. (relative to BCM43xx_DMA#_BASE) */ | 17 | |
18 | #define BCM43xx_DMA_TX_CONTROL 0x00 | 18 | /*** 32-bit DMA Engine. ***/ |
19 | #define BCM43xx_DMA_TX_DESC_RING 0x04 | 19 | |
20 | #define BCM43xx_DMA_TX_DESC_INDEX 0x08 | 20 | /* 32-bit DMA controller registers. */ |
21 | #define BCM43xx_DMA_TX_STATUS 0x0c | 21 | #define BCM43xx_DMA32_TXCTL 0x00 |
22 | #define BCM43xx_DMA_RX_CONTROL 0x10 | 22 | #define BCM43xx_DMA32_TXENABLE 0x00000001 |
23 | #define BCM43xx_DMA_RX_DESC_RING 0x14 | 23 | #define BCM43xx_DMA32_TXSUSPEND 0x00000002 |
24 | #define BCM43xx_DMA_RX_DESC_INDEX 0x18 | 24 | #define BCM43xx_DMA32_TXLOOPBACK 0x00000004 |
25 | #define BCM43xx_DMA_RX_STATUS 0x1c | 25 | #define BCM43xx_DMA32_TXFLUSH 0x00000010 |
26 | 26 | #define BCM43xx_DMA32_TXADDREXT_MASK 0x00030000 | |
27 | /* DMA controller channel control word values. */ | 27 | #define BCM43xx_DMA32_TXADDREXT_SHIFT 16 |
28 | #define BCM43xx_DMA_TXCTRL_ENABLE (1 << 0) | 28 | #define BCM43xx_DMA32_TXRING 0x04 |
29 | #define BCM43xx_DMA_TXCTRL_SUSPEND (1 << 1) | 29 | #define BCM43xx_DMA32_TXINDEX 0x08 |
30 | #define BCM43xx_DMA_TXCTRL_LOOPBACK (1 << 2) | 30 | #define BCM43xx_DMA32_TXSTATUS 0x0C |
31 | #define BCM43xx_DMA_TXCTRL_FLUSH (1 << 4) | 31 | #define BCM43xx_DMA32_TXDPTR 0x00000FFF |
32 | #define BCM43xx_DMA_RXCTRL_ENABLE (1 << 0) | 32 | #define BCM43xx_DMA32_TXSTATE 0x0000F000 |
33 | #define BCM43xx_DMA_RXCTRL_FRAMEOFF_MASK 0x000000fe | 33 | #define BCM43xx_DMA32_TXSTAT_DISABLED 0x00000000 |
34 | #define BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT 1 | 34 | #define BCM43xx_DMA32_TXSTAT_ACTIVE 0x00001000 |
35 | #define BCM43xx_DMA_RXCTRL_PIO (1 << 8) | 35 | #define BCM43xx_DMA32_TXSTAT_IDLEWAIT 0x00002000 |
36 | /* DMA controller channel status word values. */ | 36 | #define BCM43xx_DMA32_TXSTAT_STOPPED 0x00003000 |
37 | #define BCM43xx_DMA_TXSTAT_DPTR_MASK 0x00000fff | 37 | #define BCM43xx_DMA32_TXSTAT_SUSP 0x00004000 |
38 | #define BCM43xx_DMA_TXSTAT_STAT_MASK 0x0000f000 | 38 | #define BCM43xx_DMA32_TXERROR 0x000F0000 |
39 | #define BCM43xx_DMA_TXSTAT_STAT_DISABLED 0x00000000 | 39 | #define BCM43xx_DMA32_TXERR_NOERR 0x00000000 |
40 | #define BCM43xx_DMA_TXSTAT_STAT_ACTIVE 0x00001000 | 40 | #define BCM43xx_DMA32_TXERR_PROT 0x00010000 |
41 | #define BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT 0x00002000 | 41 | #define BCM43xx_DMA32_TXERR_UNDERRUN 0x00020000 |
42 | #define BCM43xx_DMA_TXSTAT_STAT_STOPPED 0x00003000 | 42 | #define BCM43xx_DMA32_TXERR_BUFREAD 0x00030000 |
43 | #define BCM43xx_DMA_TXSTAT_STAT_SUSP 0x00004000 | 43 | #define BCM43xx_DMA32_TXERR_DESCREAD 0x00040000 |
44 | #define BCM43xx_DMA_TXSTAT_ERROR_MASK 0x000f0000 | 44 | #define BCM43xx_DMA32_TXACTIVE 0xFFF00000 |
45 | #define BCM43xx_DMA_TXSTAT_FLUSHED (1 << 20) | 45 | #define BCM43xx_DMA32_RXCTL 0x10 |
46 | #define BCM43xx_DMA_RXSTAT_DPTR_MASK 0x00000fff | 46 | #define BCM43xx_DMA32_RXENABLE 0x00000001 |
47 | #define BCM43xx_DMA_RXSTAT_STAT_MASK 0x0000f000 | 47 | #define BCM43xx_DMA32_RXFROFF_MASK 0x000000FE |
48 | #define BCM43xx_DMA_RXSTAT_STAT_DISABLED 0x00000000 | 48 | #define BCM43xx_DMA32_RXFROFF_SHIFT 1 |
49 | #define BCM43xx_DMA_RXSTAT_STAT_ACTIVE 0x00001000 | 49 | #define BCM43xx_DMA32_RXDIRECTFIFO 0x00000100 |
50 | #define BCM43xx_DMA_RXSTAT_STAT_IDLEWAIT 0x00002000 | 50 | #define BCM43xx_DMA32_RXADDREXT_MASK 0x00030000 |
51 | #define BCM43xx_DMA_RXSTAT_STAT_RESERVED 0x00003000 | 51 | #define BCM43xx_DMA32_RXADDREXT_SHIFT 16 |
52 | #define BCM43xx_DMA_RXSTAT_STAT_ERRORS 0x00004000 | 52 | #define BCM43xx_DMA32_RXRING 0x14 |
53 | #define BCM43xx_DMA_RXSTAT_ERROR_MASK 0x000f0000 | 53 | #define BCM43xx_DMA32_RXINDEX 0x18 |
54 | 54 | #define BCM43xx_DMA32_RXSTATUS 0x1C | |
55 | /* DMA descriptor control field values. */ | 55 | #define BCM43xx_DMA32_RXDPTR 0x00000FFF |
56 | #define BCM43xx_DMADTOR_BYTECNT_MASK 0x00001fff | 56 | #define BCM43xx_DMA32_RXSTATE 0x0000F000 |
57 | #define BCM43xx_DMADTOR_DTABLEEND (1 << 28) /* End of descriptor table */ | 57 | #define BCM43xx_DMA32_RXSTAT_DISABLED 0x00000000 |
58 | #define BCM43xx_DMADTOR_COMPIRQ (1 << 29) /* IRQ on completion request */ | 58 | #define BCM43xx_DMA32_RXSTAT_ACTIVE 0x00001000 |
59 | #define BCM43xx_DMADTOR_FRAMEEND (1 << 30) | 59 | #define BCM43xx_DMA32_RXSTAT_IDLEWAIT 0x00002000 |
60 | #define BCM43xx_DMADTOR_FRAMESTART (1 << 31) | 60 | #define BCM43xx_DMA32_RXSTAT_STOPPED 0x00003000 |
61 | #define BCM43xx_DMA32_RXERROR 0x000F0000 | ||
62 | #define BCM43xx_DMA32_RXERR_NOERR 0x00000000 | ||
63 | #define BCM43xx_DMA32_RXERR_PROT 0x00010000 | ||
64 | #define BCM43xx_DMA32_RXERR_OVERFLOW 0x00020000 | ||
65 | #define BCM43xx_DMA32_RXERR_BUFWRITE 0x00030000 | ||
66 | #define BCM43xx_DMA32_RXERR_DESCREAD 0x00040000 | ||
67 | #define BCM43xx_DMA32_RXACTIVE 0xFFF00000 | ||
68 | |||
69 | /* 32-bit DMA descriptor. */ | ||
70 | struct bcm43xx_dmadesc32 { | ||
71 | __le32 control; | ||
72 | __le32 address; | ||
73 | } __attribute__((__packed__)); | ||
74 | #define BCM43xx_DMA32_DCTL_BYTECNT 0x00001FFF | ||
75 | #define BCM43xx_DMA32_DCTL_ADDREXT_MASK 0x00030000 | ||
76 | #define BCM43xx_DMA32_DCTL_ADDREXT_SHIFT 16 | ||
77 | #define BCM43xx_DMA32_DCTL_DTABLEEND 0x10000000 | ||
78 | #define BCM43xx_DMA32_DCTL_IRQ 0x20000000 | ||
79 | #define BCM43xx_DMA32_DCTL_FRAMEEND 0x40000000 | ||
80 | #define BCM43xx_DMA32_DCTL_FRAMESTART 0x80000000 | ||
81 | |||
82 | /* Address field Routing value. */ | ||
83 | #define BCM43xx_DMA32_ROUTING 0xC0000000 | ||
84 | #define BCM43xx_DMA32_ROUTING_SHIFT 30 | ||
85 | #define BCM43xx_DMA32_NOTRANS 0x00000000 | ||
86 | #define BCM43xx_DMA32_CLIENTTRANS 0x40000000 | ||
87 | |||
88 | |||
89 | |||
90 | /*** 64-bit DMA Engine. ***/ | ||
91 | |||
92 | /* 64-bit DMA controller registers. */ | ||
93 | #define BCM43xx_DMA64_TXCTL 0x00 | ||
94 | #define BCM43xx_DMA64_TXENABLE 0x00000001 | ||
95 | #define BCM43xx_DMA64_TXSUSPEND 0x00000002 | ||
96 | #define BCM43xx_DMA64_TXLOOPBACK 0x00000004 | ||
97 | #define BCM43xx_DMA64_TXFLUSH 0x00000010 | ||
98 | #define BCM43xx_DMA64_TXADDREXT_MASK 0x00030000 | ||
99 | #define BCM43xx_DMA64_TXADDREXT_SHIFT 16 | ||
100 | #define BCM43xx_DMA64_TXINDEX 0x04 | ||
101 | #define BCM43xx_DMA64_TXRINGLO 0x08 | ||
102 | #define BCM43xx_DMA64_TXRINGHI 0x0C | ||
103 | #define BCM43xx_DMA64_TXSTATUS 0x10 | ||
104 | #define BCM43xx_DMA64_TXSTATDPTR 0x00001FFF | ||
105 | #define BCM43xx_DMA64_TXSTAT 0xF0000000 | ||
106 | #define BCM43xx_DMA64_TXSTAT_DISABLED 0x00000000 | ||
107 | #define BCM43xx_DMA64_TXSTAT_ACTIVE 0x10000000 | ||
108 | #define BCM43xx_DMA64_TXSTAT_IDLEWAIT 0x20000000 | ||
109 | #define BCM43xx_DMA64_TXSTAT_STOPPED 0x30000000 | ||
110 | #define BCM43xx_DMA64_TXSTAT_SUSP 0x40000000 | ||
111 | #define BCM43xx_DMA64_TXERROR 0x14 | ||
112 | #define BCM43xx_DMA64_TXERRDPTR 0x0001FFFF | ||
113 | #define BCM43xx_DMA64_TXERR 0xF0000000 | ||
114 | #define BCM43xx_DMA64_TXERR_NOERR 0x00000000 | ||
115 | #define BCM43xx_DMA64_TXERR_PROT 0x10000000 | ||
116 | #define BCM43xx_DMA64_TXERR_UNDERRUN 0x20000000 | ||
117 | #define BCM43xx_DMA64_TXERR_TRANSFER 0x30000000 | ||
118 | #define BCM43xx_DMA64_TXERR_DESCREAD 0x40000000 | ||
119 | #define BCM43xx_DMA64_TXERR_CORE 0x50000000 | ||
120 | #define BCM43xx_DMA64_RXCTL 0x20 | ||
121 | #define BCM43xx_DMA64_RXENABLE 0x00000001 | ||
122 | #define BCM43xx_DMA64_RXFROFF_MASK 0x000000FE | ||
123 | #define BCM43xx_DMA64_RXFROFF_SHIFT 1 | ||
124 | #define BCM43xx_DMA64_RXDIRECTFIFO 0x00000100 | ||
125 | #define BCM43xx_DMA64_RXADDREXT_MASK 0x00030000 | ||
126 | #define BCM43xx_DMA64_RXADDREXT_SHIFT 16 | ||
127 | #define BCM43xx_DMA64_RXINDEX 0x24 | ||
128 | #define BCM43xx_DMA64_RXRINGLO 0x28 | ||
129 | #define BCM43xx_DMA64_RXRINGHI 0x2C | ||
130 | #define BCM43xx_DMA64_RXSTATUS 0x30 | ||
131 | #define BCM43xx_DMA64_RXSTATDPTR 0x00001FFF | ||
132 | #define BCM43xx_DMA64_RXSTAT 0xF0000000 | ||
133 | #define BCM43xx_DMA64_RXSTAT_DISABLED 0x00000000 | ||
134 | #define BCM43xx_DMA64_RXSTAT_ACTIVE 0x10000000 | ||
135 | #define BCM43xx_DMA64_RXSTAT_IDLEWAIT 0x20000000 | ||
136 | #define BCM43xx_DMA64_RXSTAT_STOPPED 0x30000000 | ||
137 | #define BCM43xx_DMA64_RXSTAT_SUSP 0x40000000 | ||
138 | #define BCM43xx_DMA64_RXERROR 0x34 | ||
139 | #define BCM43xx_DMA64_RXERRDPTR 0x0001FFFF | ||
140 | #define BCM43xx_DMA64_RXERR 0xF0000000 | ||
141 | #define BCM43xx_DMA64_RXERR_NOERR 0x00000000 | ||
142 | #define BCM43xx_DMA64_RXERR_PROT 0x10000000 | ||
143 | #define BCM43xx_DMA64_RXERR_UNDERRUN 0x20000000 | ||
144 | #define BCM43xx_DMA64_RXERR_TRANSFER 0x30000000 | ||
145 | #define BCM43xx_DMA64_RXERR_DESCREAD 0x40000000 | ||
146 | #define BCM43xx_DMA64_RXERR_CORE 0x50000000 | ||
147 | |||
148 | /* 64-bit DMA descriptor. */ | ||
149 | struct bcm43xx_dmadesc64 { | ||
150 | __le32 control0; | ||
151 | __le32 control1; | ||
152 | __le32 address_low; | ||
153 | __le32 address_high; | ||
154 | } __attribute__((__packed__)); | ||
155 | #define BCM43xx_DMA64_DCTL0_DTABLEEND 0x10000000 | ||
156 | #define BCM43xx_DMA64_DCTL0_IRQ 0x20000000 | ||
157 | #define BCM43xx_DMA64_DCTL0_FRAMEEND 0x40000000 | ||
158 | #define BCM43xx_DMA64_DCTL0_FRAMESTART 0x80000000 | ||
159 | #define BCM43xx_DMA64_DCTL1_BYTECNT 0x00001FFF | ||
160 | #define BCM43xx_DMA64_DCTL1_ADDREXT_MASK 0x00030000 | ||
161 | #define BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT 16 | ||
162 | |||
163 | /* Address field Routing value. */ | ||
164 | #define BCM43xx_DMA64_ROUTING 0xC0000000 | ||
165 | #define BCM43xx_DMA64_ROUTING_SHIFT 30 | ||
166 | #define BCM43xx_DMA64_NOTRANS 0x00000000 | ||
167 | #define BCM43xx_DMA64_CLIENTTRANS 0x80000000 | ||
168 | |||
169 | |||
170 | |||
171 | struct bcm43xx_dmadesc_generic { | ||
172 | union { | ||
173 | struct bcm43xx_dmadesc32 dma32; | ||
174 | struct bcm43xx_dmadesc64 dma64; | ||
175 | } __attribute__((__packed__)); | ||
176 | } __attribute__((__packed__)); | ||
177 | |||
61 | 178 | ||
62 | /* Misc DMA constants */ | 179 | /* Misc DMA constants */ |
63 | #define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE | 180 | #define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE |
64 | #define BCM43xx_DMA_BUSADDRMAX 0x3FFFFFFF | 181 | #define BCM43xx_DMA0_RX_FRAMEOFFSET 30 |
65 | #define BCM43xx_DMA_DMABUSADDROFFSET (1 << 30) | 182 | #define BCM43xx_DMA3_RX_FRAMEOFFSET 0 |
66 | #define BCM43xx_DMA1_RX_FRAMEOFFSET 30 | 183 | |
67 | #define BCM43xx_DMA4_RX_FRAMEOFFSET 0 | ||
68 | 184 | ||
69 | /* DMA engine tuning knobs */ | 185 | /* DMA engine tuning knobs */ |
70 | #define BCM43xx_TXRING_SLOTS 512 | 186 | #define BCM43xx_TXRING_SLOTS 512 |
71 | #define BCM43xx_RXRING_SLOTS 64 | 187 | #define BCM43xx_RXRING_SLOTS 64 |
72 | #define BCM43xx_DMA1_RXBUFFERSIZE (2304 + 100) | 188 | #define BCM43xx_DMA0_RX_BUFFERSIZE (2304 + 100) |
73 | #define BCM43xx_DMA4_RXBUFFERSIZE 16 | 189 | #define BCM43xx_DMA3_RX_BUFFERSIZE 16 |
74 | /* Suspend the tx queue, if less than this percent slots are free. */ | 190 | /* Suspend the tx queue, if less than this percent slots are free. */ |
75 | #define BCM43xx_TXSUSPEND_PERCENT 20 | 191 | #define BCM43xx_TXSUSPEND_PERCENT 20 |
76 | /* Resume the tx queue, if more than this percent slots are free. */ | 192 | /* Resume the tx queue, if more than this percent slots are free. */ |
@@ -86,17 +202,6 @@ struct bcm43xx_private; | |||
86 | struct bcm43xx_xmitstatus; | 202 | struct bcm43xx_xmitstatus; |
87 | 203 | ||
88 | 204 | ||
89 | struct bcm43xx_dmadesc { | ||
90 | __le32 _control; | ||
91 | __le32 _address; | ||
92 | } __attribute__((__packed__)); | ||
93 | |||
94 | /* Macros to access the bcm43xx_dmadesc struct */ | ||
95 | #define get_desc_ctl(desc) le32_to_cpu((desc)->_control) | ||
96 | #define set_desc_ctl(desc, ctl) do { (desc)->_control = cpu_to_le32(ctl); } while (0) | ||
97 | #define get_desc_addr(desc) le32_to_cpu((desc)->_address) | ||
98 | #define set_desc_addr(desc, addr) do { (desc)->_address = cpu_to_le32(addr); } while (0) | ||
99 | |||
100 | struct bcm43xx_dmadesc_meta { | 205 | struct bcm43xx_dmadesc_meta { |
101 | /* The kernel DMA-able buffer. */ | 206 | /* The kernel DMA-able buffer. */ |
102 | struct sk_buff *skb; | 207 | struct sk_buff *skb; |
@@ -105,15 +210,14 @@ struct bcm43xx_dmadesc_meta { | |||
105 | }; | 210 | }; |
106 | 211 | ||
107 | struct bcm43xx_dmaring { | 212 | struct bcm43xx_dmaring { |
108 | struct bcm43xx_private *bcm; | ||
109 | /* Kernel virtual base address of the ring memory. */ | 213 | /* Kernel virtual base address of the ring memory. */ |
110 | struct bcm43xx_dmadesc *vbase; | 214 | void *descbase; |
111 | /* DMA memory offset */ | ||
112 | dma_addr_t memoffset; | ||
113 | /* (Unadjusted) DMA base bus-address of the ring memory. */ | ||
114 | dma_addr_t dmabase; | ||
115 | /* Meta data about all descriptors. */ | 215 | /* Meta data about all descriptors. */ |
116 | struct bcm43xx_dmadesc_meta *meta; | 216 | struct bcm43xx_dmadesc_meta *meta; |
217 | /* DMA Routing value. */ | ||
218 | u32 routing; | ||
219 | /* (Unadjusted) DMA base bus-address of the ring memory. */ | ||
220 | dma_addr_t dmabase; | ||
117 | /* Number of descriptor slots in the ring. */ | 221 | /* Number of descriptor slots in the ring. */ |
118 | int nr_slots; | 222 | int nr_slots; |
119 | /* Number of used descriptor slots. */ | 223 | /* Number of used descriptor slots. */ |
@@ -127,12 +231,17 @@ struct bcm43xx_dmaring { | |||
127 | u32 frameoffset; | 231 | u32 frameoffset; |
128 | /* Descriptor buffer size. */ | 232 | /* Descriptor buffer size. */ |
129 | u16 rx_buffersize; | 233 | u16 rx_buffersize; |
130 | /* The MMIO base register of the DMA controller, this | 234 | /* The MMIO base register of the DMA controller. */ |
131 | * ring is posted to. | ||
132 | */ | ||
133 | u16 mmio_base; | 235 | u16 mmio_base; |
134 | u8 tx:1, /* TRUE, if this is a TX ring. */ | 236 | /* DMA controller index number (0-5). */ |
135 | suspended:1; /* TRUE, if transfers are suspended on this ring. */ | 237 | int index; |
238 | /* Boolean. Is this a TX ring? */ | ||
239 | u8 tx; | ||
240 | /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */ | ||
241 | u8 dma64; | ||
242 | /* Boolean. Are transfers suspended on this ring? */ | ||
243 | u8 suspended; | ||
244 | struct bcm43xx_private *bcm; | ||
136 | #ifdef CONFIG_BCM43XX_DEBUG | 245 | #ifdef CONFIG_BCM43XX_DEBUG |
137 | /* Maximum number of used slots. */ | 246 | /* Maximum number of used slots. */ |
138 | int max_used_slots; | 247 | int max_used_slots; |
@@ -141,6 +250,34 @@ struct bcm43xx_dmaring { | |||
141 | 250 | ||
142 | 251 | ||
143 | static inline | 252 | static inline |
253 | int bcm43xx_dma_desc2idx(struct bcm43xx_dmaring *ring, | ||
254 | struct bcm43xx_dmadesc_generic *desc) | ||
255 | { | ||
256 | if (ring->dma64) { | ||
257 | struct bcm43xx_dmadesc64 *dd64 = ring->descbase; | ||
258 | return (int)(&(desc->dma64) - dd64); | ||
259 | } else { | ||
260 | struct bcm43xx_dmadesc32 *dd32 = ring->descbase; | ||
261 | return (int)(&(desc->dma32) - dd32); | ||
262 | } | ||
263 | } | ||
264 | |||
265 | static inline | ||
266 | struct bcm43xx_dmadesc_generic * bcm43xx_dma_idx2desc(struct bcm43xx_dmaring *ring, | ||
267 | int slot, | ||
268 | struct bcm43xx_dmadesc_meta **meta) | ||
269 | { | ||
270 | *meta = &(ring->meta[slot]); | ||
271 | if (ring->dma64) { | ||
272 | struct bcm43xx_dmadesc64 *dd64 = ring->descbase; | ||
273 | return (struct bcm43xx_dmadesc_generic *)(&(dd64[slot])); | ||
274 | } else { | ||
275 | struct bcm43xx_dmadesc32 *dd32 = ring->descbase; | ||
276 | return (struct bcm43xx_dmadesc_generic *)(&(dd32[slot])); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | static inline | ||
144 | u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring, | 281 | u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring, |
145 | u16 offset) | 282 | u16 offset) |
146 | { | 283 | { |
@@ -159,9 +296,13 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm); | |||
159 | void bcm43xx_dma_free(struct bcm43xx_private *bcm); | 296 | void bcm43xx_dma_free(struct bcm43xx_private *bcm); |
160 | 297 | ||
161 | int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, | 298 | int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, |
162 | u16 dmacontroller_mmio_base); | 299 | u16 dmacontroller_mmio_base, |
300 | int dma64); | ||
163 | int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, | 301 | int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, |
164 | u16 dmacontroller_mmio_base); | 302 | u16 dmacontroller_mmio_base, |
303 | int dma64); | ||
304 | |||
305 | u16 bcm43xx_dmacontroller_base(int dma64bit, int dmacontroller_idx); | ||
165 | 306 | ||
166 | void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring); | 307 | void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring); |
167 | void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring); | 308 | void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring); |
@@ -173,7 +314,6 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, | |||
173 | struct ieee80211_txb *txb); | 314 | struct ieee80211_txb *txb); |
174 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); | 315 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); |
175 | 316 | ||
176 | |||
177 | #else /* CONFIG_BCM43XX_DMA */ | 317 | #else /* CONFIG_BCM43XX_DMA */ |
178 | 318 | ||
179 | 319 | ||
@@ -188,13 +328,15 @@ void bcm43xx_dma_free(struct bcm43xx_private *bcm) | |||
188 | } | 328 | } |
189 | static inline | 329 | static inline |
190 | int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, | 330 | int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, |
191 | u16 dmacontroller_mmio_base) | 331 | u16 dmacontroller_mmio_base, |
332 | int dma64) | ||
192 | { | 333 | { |
193 | return 0; | 334 | return 0; |
194 | } | 335 | } |
195 | static inline | 336 | static inline |
196 | int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, | 337 | int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, |
197 | u16 dmacontroller_mmio_base) | 338 | u16 dmacontroller_mmio_base, |
339 | int dma64) | ||
198 | { | 340 | { |
199 | return 0; | 341 | return 0; |
200 | } | 342 | } |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c index e386dcc32e8c..c947025d655f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c | |||
@@ -44,7 +44,7 @@ static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo * | |||
44 | strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN); | 44 | strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN); |
45 | } | 45 | } |
46 | 46 | ||
47 | struct ethtool_ops bcm43xx_ethtool_ops = { | 47 | const struct ethtool_ops bcm43xx_ethtool_ops = { |
48 | .get_drvinfo = bcm43xx_get_drvinfo, | 48 | .get_drvinfo = bcm43xx_get_drvinfo, |
49 | .get_link = ethtool_op_get_link, | 49 | .get_link = ethtool_op_get_link, |
50 | }; | 50 | }; |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h index 813704991f62..6f8d42d3cdf5 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h | |||
@@ -3,6 +3,6 @@ | |||
3 | 3 | ||
4 | #include <linux/ethtool.h> | 4 | #include <linux/ethtool.h> |
5 | 5 | ||
6 | extern struct ethtool_ops bcm43xx_ethtool_ops; | 6 | extern const struct ethtool_ops bcm43xx_ethtool_ops; |
7 | 7 | ||
8 | #endif /* BCM43xx_ETHTOOL_H_ */ | 8 | #endif /* BCM43xx_ETHTOOL_H_ */ |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index ec80692d638a..c3f90c8563d9 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c | |||
@@ -51,12 +51,12 @@ static void bcm43xx_led_blink(unsigned long d) | |||
51 | struct bcm43xx_private *bcm = led->bcm; | 51 | struct bcm43xx_private *bcm = led->bcm; |
52 | unsigned long flags; | 52 | unsigned long flags; |
53 | 53 | ||
54 | bcm43xx_lock_irqonly(bcm, flags); | 54 | spin_lock_irqsave(&bcm->leds_lock, flags); |
55 | if (led->blink_interval) { | 55 | if (led->blink_interval) { |
56 | bcm43xx_led_changestate(led); | 56 | bcm43xx_led_changestate(led); |
57 | mod_timer(&led->blink_timer, jiffies + led->blink_interval); | 57 | mod_timer(&led->blink_timer, jiffies + led->blink_interval); |
58 | } | 58 | } |
59 | bcm43xx_unlock_irqonly(bcm, flags); | 59 | spin_unlock_irqrestore(&bcm->leds_lock, flags); |
60 | } | 60 | } |
61 | 61 | ||
62 | static void bcm43xx_led_blink_start(struct bcm43xx_led *led, | 62 | static void bcm43xx_led_blink_start(struct bcm43xx_led *led, |
@@ -177,7 +177,9 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) | |||
177 | int i, turn_on; | 177 | int i, turn_on; |
178 | unsigned long interval = 0; | 178 | unsigned long interval = 0; |
179 | u16 ledctl; | 179 | u16 ledctl; |
180 | unsigned long flags; | ||
180 | 181 | ||
182 | spin_lock_irqsave(&bcm->leds_lock, flags); | ||
181 | ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); | 183 | ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); |
182 | for (i = 0; i < BCM43xx_NR_LEDS; i++) { | 184 | for (i = 0; i < BCM43xx_NR_LEDS; i++) { |
183 | led = &(bcm->leds[i]); | 185 | led = &(bcm->leds[i]); |
@@ -266,6 +268,7 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) | |||
266 | ledctl &= ~(1 << i); | 268 | ledctl &= ~(1 << i); |
267 | } | 269 | } |
268 | bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); | 270 | bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); |
271 | spin_unlock_irqrestore(&bcm->leds_lock, flags); | ||
269 | } | 272 | } |
270 | 273 | ||
271 | void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) | 274 | void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) |
@@ -274,7 +277,9 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) | |||
274 | u16 ledctl; | 277 | u16 ledctl; |
275 | int i; | 278 | int i; |
276 | int bit_on; | 279 | int bit_on; |
280 | unsigned long flags; | ||
277 | 281 | ||
282 | spin_lock_irqsave(&bcm->leds_lock, flags); | ||
278 | ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); | 283 | ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); |
279 | for (i = 0; i < BCM43xx_NR_LEDS; i++) { | 284 | for (i = 0; i < BCM43xx_NR_LEDS; i++) { |
280 | led = &(bcm->leds[i]); | 285 | led = &(bcm->leds[i]); |
@@ -290,4 +295,5 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) | |||
290 | ledctl &= ~(1 << i); | 295 | ledctl &= ~(1 << i); |
291 | } | 296 | } |
292 | bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); | 297 | bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); |
298 | spin_unlock_irqrestore(&bcm->leds_lock, flags); | ||
293 | } | 299 | } |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index df317c1e12a8..cb9a3ae8463a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c | |||
@@ -509,23 +509,20 @@ static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm) | |||
509 | } | 509 | } |
510 | 510 | ||
511 | /* Make sure we don't receive more data from the device. */ | 511 | /* Make sure we don't receive more data from the device. */ |
512 | static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate) | 512 | static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm) |
513 | { | 513 | { |
514 | unsigned long flags; | 514 | unsigned long flags; |
515 | u32 old; | ||
516 | 515 | ||
517 | bcm43xx_lock_irqonly(bcm, flags); | 516 | spin_lock_irqsave(&bcm->irq_lock, flags); |
518 | if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { | 517 | if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { |
519 | bcm43xx_unlock_irqonly(bcm, flags); | 518 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
520 | return -EBUSY; | 519 | return -EBUSY; |
521 | } | 520 | } |
522 | old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | 521 | bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); |
523 | bcm43xx_unlock_irqonly(bcm, flags); | 522 | bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); /* flush */ |
523 | spin_unlock_irqrestore(&bcm->irq_lock, flags); | ||
524 | bcm43xx_synchronize_irq(bcm); | 524 | bcm43xx_synchronize_irq(bcm); |
525 | 525 | ||
526 | if (oldstate) | ||
527 | *oldstate = old; | ||
528 | |||
529 | return 0; | 526 | return 0; |
530 | } | 527 | } |
531 | 528 | ||
@@ -537,7 +534,6 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) | |||
537 | u16 manufact; | 534 | u16 manufact; |
538 | u16 version; | 535 | u16 version; |
539 | u8 revision; | 536 | u8 revision; |
540 | s8 i; | ||
541 | 537 | ||
542 | if (bcm->chip_id == 0x4317) { | 538 | if (bcm->chip_id == 0x4317) { |
543 | if (bcm->chip_rev == 0x00) | 539 | if (bcm->chip_rev == 0x00) |
@@ -580,20 +576,11 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) | |||
580 | radio->version = version; | 576 | radio->version = version; |
581 | radio->revision = revision; | 577 | radio->revision = revision; |
582 | 578 | ||
583 | /* Set default attenuation values. */ | ||
584 | radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm); | ||
585 | radio->radio_atten = bcm43xx_default_radio_attenuation(bcm); | ||
586 | radio->txctl1 = bcm43xx_default_txctl1(bcm); | ||
587 | radio->txctl2 = 0xFFFF; | ||
588 | if (phy->type == BCM43xx_PHYTYPE_A) | 579 | if (phy->type == BCM43xx_PHYTYPE_A) |
589 | radio->txpower_desired = bcm->sprom.maxpower_aphy; | 580 | radio->txpower_desired = bcm->sprom.maxpower_aphy; |
590 | else | 581 | else |
591 | radio->txpower_desired = bcm->sprom.maxpower_bgphy; | 582 | radio->txpower_desired = bcm->sprom.maxpower_bgphy; |
592 | 583 | ||
593 | /* Initialize the in-memory nrssi Lookup Table. */ | ||
594 | for (i = 0; i < 64; i++) | ||
595 | radio->nrssi_lt[i] = i; | ||
596 | |||
597 | return 0; | 584 | return 0; |
598 | 585 | ||
599 | err_unsupported_radio: | 586 | err_unsupported_radio: |
@@ -1250,10 +1237,6 @@ int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *ne | |||
1250 | goto out; | 1237 | goto out; |
1251 | 1238 | ||
1252 | bcm->current_core = new_core; | 1239 | bcm->current_core = new_core; |
1253 | bcm->current_80211_core_idx = -1; | ||
1254 | if (new_core->id == BCM43xx_COREID_80211) | ||
1255 | bcm->current_80211_core_idx = (int)(new_core - &(bcm->core_80211[0])); | ||
1256 | |||
1257 | out: | 1240 | out: |
1258 | return err; | 1241 | return err; |
1259 | } | 1242 | } |
@@ -1389,6 +1372,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) | |||
1389 | if ((bcm43xx_core_enabled(bcm)) && | 1372 | if ((bcm43xx_core_enabled(bcm)) && |
1390 | !bcm43xx_using_pio(bcm)) { | 1373 | !bcm43xx_using_pio(bcm)) { |
1391 | //FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here? | 1374 | //FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here? |
1375 | #if 0 | ||
1392 | #ifndef CONFIG_BCM947XX | 1376 | #ifndef CONFIG_BCM947XX |
1393 | /* reset all used DMA controllers. */ | 1377 | /* reset all used DMA controllers. */ |
1394 | bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE); | 1378 | bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE); |
@@ -1399,6 +1383,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) | |||
1399 | if (bcm->current_core->rev < 5) | 1383 | if (bcm->current_core->rev < 5) |
1400 | bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); | 1384 | bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); |
1401 | #endif | 1385 | #endif |
1386 | #endif | ||
1402 | } | 1387 | } |
1403 | if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) { | 1388 | if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) { |
1404 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, | 1389 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, |
@@ -1423,43 +1408,23 @@ static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm) | |||
1423 | bcm43xx_core_disable(bcm, 0); | 1408 | bcm43xx_core_disable(bcm, 0); |
1424 | } | 1409 | } |
1425 | 1410 | ||
1426 | /* Mark the current 80211 core inactive. | 1411 | /* Mark the current 80211 core inactive. */ |
1427 | * "active_80211_core" is the other 80211 core, which is used. | 1412 | static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm) |
1428 | */ | ||
1429 | static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm, | ||
1430 | struct bcm43xx_coreinfo *active_80211_core) | ||
1431 | { | 1413 | { |
1432 | u32 sbtmstatelow; | 1414 | u32 sbtmstatelow; |
1433 | struct bcm43xx_coreinfo *old_core; | ||
1434 | int err = 0; | ||
1435 | 1415 | ||
1436 | bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | 1416 | bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); |
1437 | bcm43xx_radio_turn_off(bcm); | 1417 | bcm43xx_radio_turn_off(bcm); |
1438 | sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); | 1418 | sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); |
1439 | sbtmstatelow &= ~0x200a0000; | 1419 | sbtmstatelow &= 0xDFF5FFFF; |
1440 | sbtmstatelow |= 0xa0000; | 1420 | sbtmstatelow |= 0x000A0000; |
1441 | bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); | 1421 | bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); |
1442 | udelay(1); | 1422 | udelay(1); |
1443 | sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); | 1423 | sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); |
1444 | sbtmstatelow &= ~0xa0000; | 1424 | sbtmstatelow &= 0xFFF5FFFF; |
1445 | sbtmstatelow |= 0x80000; | 1425 | sbtmstatelow |= 0x00080000; |
1446 | bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); | 1426 | bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); |
1447 | udelay(1); | 1427 | udelay(1); |
1448 | |||
1449 | if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G) { | ||
1450 | old_core = bcm->current_core; | ||
1451 | err = bcm43xx_switch_core(bcm, active_80211_core); | ||
1452 | if (err) | ||
1453 | goto out; | ||
1454 | sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); | ||
1455 | sbtmstatelow &= ~0x20000000; | ||
1456 | sbtmstatelow |= 0x20000000; | ||
1457 | bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); | ||
1458 | err = bcm43xx_switch_core(bcm, old_core); | ||
1459 | } | ||
1460 | |||
1461 | out: | ||
1462 | return err; | ||
1463 | } | 1428 | } |
1464 | 1429 | ||
1465 | static void handle_irq_transmit_status(struct bcm43xx_private *bcm) | 1430 | static void handle_irq_transmit_status(struct bcm43xx_private *bcm) |
@@ -1581,17 +1546,7 @@ static void handle_irq_noise(struct bcm43xx_private *bcm) | |||
1581 | else | 1546 | else |
1582 | average -= 48; | 1547 | average -= 48; |
1583 | 1548 | ||
1584 | /* FIXME: This is wrong, but people want fancy stats. well... */ | 1549 | bcm->stats.noise = average; |
1585 | bcm->stats.noise = average; | ||
1586 | if (average > -65) | ||
1587 | bcm->stats.link_quality = 0; | ||
1588 | else if (average > -75) | ||
1589 | bcm->stats.link_quality = 1; | ||
1590 | else if (average > -85) | ||
1591 | bcm->stats.link_quality = 2; | ||
1592 | else | ||
1593 | bcm->stats.link_quality = 3; | ||
1594 | // dprintk(KERN_INFO PFX "Link Quality: %u (avg was %d)\n", bcm->stats.link_quality, average); | ||
1595 | drop_calculation: | 1550 | drop_calculation: |
1596 | bcm->noisecalc.calculation_running = 0; | 1551 | bcm->noisecalc.calculation_running = 0; |
1597 | return; | 1552 | return; |
@@ -1709,8 +1664,9 @@ static void handle_irq_beacon(struct bcm43xx_private *bcm) | |||
1709 | static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) | 1664 | static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) |
1710 | { | 1665 | { |
1711 | u32 reason; | 1666 | u32 reason; |
1712 | u32 dma_reason[4]; | 1667 | u32 dma_reason[6]; |
1713 | int activity = 0; | 1668 | u32 merged_dma_reason = 0; |
1669 | int i, activity = 0; | ||
1714 | unsigned long flags; | 1670 | unsigned long flags; |
1715 | 1671 | ||
1716 | #ifdef CONFIG_BCM43XX_DEBUG | 1672 | #ifdef CONFIG_BCM43XX_DEBUG |
@@ -1720,12 +1676,12 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) | |||
1720 | # define bcmirq_handled(irq) do { /* nothing */ } while (0) | 1676 | # define bcmirq_handled(irq) do { /* nothing */ } while (0) |
1721 | #endif /* CONFIG_BCM43XX_DEBUG*/ | 1677 | #endif /* CONFIG_BCM43XX_DEBUG*/ |
1722 | 1678 | ||
1723 | bcm43xx_lock_irqonly(bcm, flags); | 1679 | spin_lock_irqsave(&bcm->irq_lock, flags); |
1724 | reason = bcm->irq_reason; | 1680 | reason = bcm->irq_reason; |
1725 | dma_reason[0] = bcm->dma_reason[0]; | 1681 | for (i = 5; i >= 0; i--) { |
1726 | dma_reason[1] = bcm->dma_reason[1]; | 1682 | dma_reason[i] = bcm->dma_reason[i]; |
1727 | dma_reason[2] = bcm->dma_reason[2]; | 1683 | merged_dma_reason |= dma_reason[i]; |
1728 | dma_reason[3] = bcm->dma_reason[3]; | 1684 | } |
1729 | 1685 | ||
1730 | if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) { | 1686 | if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) { |
1731 | /* TX error. We get this when Template Ram is written in wrong endianess | 1687 | /* TX error. We get this when Template Ram is written in wrong endianess |
@@ -1736,27 +1692,25 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) | |||
1736 | printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n"); | 1692 | printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n"); |
1737 | bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR); | 1693 | bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR); |
1738 | } | 1694 | } |
1739 | if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_FATALMASK) | | 1695 | if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_FATALMASK)) { |
1740 | (dma_reason[1] & BCM43xx_DMAIRQ_FATALMASK) | | ||
1741 | (dma_reason[2] & BCM43xx_DMAIRQ_FATALMASK) | | ||
1742 | (dma_reason[3] & BCM43xx_DMAIRQ_FATALMASK))) { | ||
1743 | printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: " | 1696 | printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: " |
1744 | "0x%08X, 0x%08X, 0x%08X, 0x%08X\n", | 1697 | "0x%08X, 0x%08X, 0x%08X, " |
1698 | "0x%08X, 0x%08X, 0x%08X\n", | ||
1745 | dma_reason[0], dma_reason[1], | 1699 | dma_reason[0], dma_reason[1], |
1746 | dma_reason[2], dma_reason[3]); | 1700 | dma_reason[2], dma_reason[3], |
1701 | dma_reason[4], dma_reason[5]); | ||
1747 | bcm43xx_controller_restart(bcm, "DMA error"); | 1702 | bcm43xx_controller_restart(bcm, "DMA error"); |
1748 | mmiowb(); | 1703 | mmiowb(); |
1749 | bcm43xx_unlock_irqonly(bcm, flags); | 1704 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
1750 | return; | 1705 | return; |
1751 | } | 1706 | } |
1752 | if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) | | 1707 | if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_NONFATALMASK)) { |
1753 | (dma_reason[1] & BCM43xx_DMAIRQ_NONFATALMASK) | | ||
1754 | (dma_reason[2] & BCM43xx_DMAIRQ_NONFATALMASK) | | ||
1755 | (dma_reason[3] & BCM43xx_DMAIRQ_NONFATALMASK))) { | ||
1756 | printkl(KERN_ERR PFX "DMA error: " | 1708 | printkl(KERN_ERR PFX "DMA error: " |
1757 | "0x%08X, 0x%08X, 0x%08X, 0x%08X\n", | 1709 | "0x%08X, 0x%08X, 0x%08X, " |
1710 | "0x%08X, 0x%08X, 0x%08X\n", | ||
1758 | dma_reason[0], dma_reason[1], | 1711 | dma_reason[0], dma_reason[1], |
1759 | dma_reason[2], dma_reason[3]); | 1712 | dma_reason[2], dma_reason[3], |
1713 | dma_reason[4], dma_reason[5]); | ||
1760 | } | 1714 | } |
1761 | 1715 | ||
1762 | if (reason & BCM43xx_IRQ_PS) { | 1716 | if (reason & BCM43xx_IRQ_PS) { |
@@ -1791,8 +1745,6 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) | |||
1791 | } | 1745 | } |
1792 | 1746 | ||
1793 | /* Check the DMA reason registers for received data. */ | 1747 | /* Check the DMA reason registers for received data. */ |
1794 | assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE)); | ||
1795 | assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); | ||
1796 | if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { | 1748 | if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { |
1797 | if (bcm43xx_using_pio(bcm)) | 1749 | if (bcm43xx_using_pio(bcm)) |
1798 | bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0); | 1750 | bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0); |
@@ -1800,13 +1752,17 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) | |||
1800 | bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0); | 1752 | bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0); |
1801 | /* We intentionally don't set "activity" to 1, here. */ | 1753 | /* We intentionally don't set "activity" to 1, here. */ |
1802 | } | 1754 | } |
1755 | assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE)); | ||
1756 | assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); | ||
1803 | if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { | 1757 | if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { |
1804 | if (bcm43xx_using_pio(bcm)) | 1758 | if (bcm43xx_using_pio(bcm)) |
1805 | bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3); | 1759 | bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3); |
1806 | else | 1760 | else |
1807 | bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring1); | 1761 | bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring3); |
1808 | activity = 1; | 1762 | activity = 1; |
1809 | } | 1763 | } |
1764 | assert(!(dma_reason[4] & BCM43xx_DMAIRQ_RX_DONE)); | ||
1765 | assert(!(dma_reason[5] & BCM43xx_DMAIRQ_RX_DONE)); | ||
1810 | bcmirq_handled(BCM43xx_IRQ_RX); | 1766 | bcmirq_handled(BCM43xx_IRQ_RX); |
1811 | 1767 | ||
1812 | if (reason & BCM43xx_IRQ_XMIT_STATUS) { | 1768 | if (reason & BCM43xx_IRQ_XMIT_STATUS) { |
@@ -1834,7 +1790,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) | |||
1834 | bcm43xx_leds_update(bcm, activity); | 1790 | bcm43xx_leds_update(bcm, activity); |
1835 | bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); | 1791 | bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); |
1836 | mmiowb(); | 1792 | mmiowb(); |
1837 | bcm43xx_unlock_irqonly(bcm, flags); | 1793 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
1838 | } | 1794 | } |
1839 | 1795 | ||
1840 | static void pio_irq_workaround(struct bcm43xx_private *bcm, | 1796 | static void pio_irq_workaround(struct bcm43xx_private *bcm, |
@@ -1863,14 +1819,18 @@ static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason) | |||
1863 | 1819 | ||
1864 | bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason); | 1820 | bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason); |
1865 | 1821 | ||
1866 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON, | 1822 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_REASON, |
1867 | bcm->dma_reason[0]); | 1823 | bcm->dma_reason[0]); |
1868 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON, | 1824 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON, |
1869 | bcm->dma_reason[1]); | 1825 | bcm->dma_reason[1]); |
1870 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON, | 1826 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON, |
1871 | bcm->dma_reason[2]); | 1827 | bcm->dma_reason[2]); |
1872 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON, | 1828 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON, |
1873 | bcm->dma_reason[3]); | 1829 | bcm->dma_reason[3]); |
1830 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON, | ||
1831 | bcm->dma_reason[4]); | ||
1832 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_REASON, | ||
1833 | bcm->dma_reason[5]); | ||
1874 | } | 1834 | } |
1875 | 1835 | ||
1876 | /* Interrupt handler top-half */ | 1836 | /* Interrupt handler top-half */ |
@@ -1885,14 +1845,8 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re | |||
1885 | 1845 | ||
1886 | spin_lock(&bcm->irq_lock); | 1846 | spin_lock(&bcm->irq_lock); |
1887 | 1847 | ||
1888 | /* Only accept IRQs, if we are initialized properly. | 1848 | assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); |
1889 | * This avoids an RX race while initializing. | 1849 | assert(bcm->current_core->id == BCM43xx_COREID_80211); |
1890 | * We should probably not enable IRQs before we are initialized | ||
1891 | * completely, but some careful work is needed to fix this. I think it | ||
1892 | * is best to stay with this cheap workaround for now... . | ||
1893 | */ | ||
1894 | if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) | ||
1895 | goto out; | ||
1896 | 1850 | ||
1897 | reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); | 1851 | reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); |
1898 | if (reason == 0xffffffff) { | 1852 | if (reason == 0xffffffff) { |
@@ -1904,14 +1858,18 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re | |||
1904 | if (!reason) | 1858 | if (!reason) |
1905 | goto out; | 1859 | goto out; |
1906 | 1860 | ||
1907 | bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) | 1861 | bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON) |
1908 | & 0x0001dc00; | 1862 | & 0x0001DC00; |
1909 | bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) | 1863 | bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) |
1910 | & 0x0000dc00; | 1864 | & 0x0000DC00; |
1911 | bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) | 1865 | bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) |
1912 | & 0x0000dc00; | 1866 | & 0x0000DC00; |
1913 | bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) | 1867 | bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) |
1914 | & 0x0001dc00; | 1868 | & 0x0001DC00; |
1869 | bcm->dma_reason[4] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) | ||
1870 | & 0x0000DC00; | ||
1871 | bcm->dma_reason[5] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA5_REASON) | ||
1872 | & 0x0000DC00; | ||
1915 | 1873 | ||
1916 | bcm43xx_interrupt_ack(bcm, reason); | 1874 | bcm43xx_interrupt_ack(bcm, reason); |
1917 | 1875 | ||
@@ -1930,16 +1888,18 @@ out: | |||
1930 | 1888 | ||
1931 | static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) | 1889 | static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) |
1932 | { | 1890 | { |
1891 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); | ||
1892 | |||
1933 | if (bcm->firmware_norelease && !force) | 1893 | if (bcm->firmware_norelease && !force) |
1934 | return; /* Suspending or controller reset. */ | 1894 | return; /* Suspending or controller reset. */ |
1935 | release_firmware(bcm->ucode); | 1895 | release_firmware(phy->ucode); |
1936 | bcm->ucode = NULL; | 1896 | phy->ucode = NULL; |
1937 | release_firmware(bcm->pcm); | 1897 | release_firmware(phy->pcm); |
1938 | bcm->pcm = NULL; | 1898 | phy->pcm = NULL; |
1939 | release_firmware(bcm->initvals0); | 1899 | release_firmware(phy->initvals0); |
1940 | bcm->initvals0 = NULL; | 1900 | phy->initvals0 = NULL; |
1941 | release_firmware(bcm->initvals1); | 1901 | release_firmware(phy->initvals1); |
1942 | bcm->initvals1 = NULL; | 1902 | phy->initvals1 = NULL; |
1943 | } | 1903 | } |
1944 | 1904 | ||
1945 | static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) | 1905 | static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) |
@@ -1950,11 +1910,11 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) | |||
1950 | int nr; | 1910 | int nr; |
1951 | char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 }; | 1911 | char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 }; |
1952 | 1912 | ||
1953 | if (!bcm->ucode) { | 1913 | if (!phy->ucode) { |
1954 | snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw", | 1914 | snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw", |
1955 | (rev >= 5 ? 5 : rev), | 1915 | (rev >= 5 ? 5 : rev), |
1956 | modparam_fwpostfix); | 1916 | modparam_fwpostfix); |
1957 | err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev); | 1917 | err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev); |
1958 | if (err) { | 1918 | if (err) { |
1959 | printk(KERN_ERR PFX | 1919 | printk(KERN_ERR PFX |
1960 | "Error: Microcode \"%s\" not available or load failed.\n", | 1920 | "Error: Microcode \"%s\" not available or load failed.\n", |
@@ -1963,12 +1923,12 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) | |||
1963 | } | 1923 | } |
1964 | } | 1924 | } |
1965 | 1925 | ||
1966 | if (!bcm->pcm) { | 1926 | if (!phy->pcm) { |
1967 | snprintf(buf, ARRAY_SIZE(buf), | 1927 | snprintf(buf, ARRAY_SIZE(buf), |
1968 | "bcm43xx_pcm%d%s.fw", | 1928 | "bcm43xx_pcm%d%s.fw", |
1969 | (rev < 5 ? 4 : 5), | 1929 | (rev < 5 ? 4 : 5), |
1970 | modparam_fwpostfix); | 1930 | modparam_fwpostfix); |
1971 | err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev); | 1931 | err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev); |
1972 | if (err) { | 1932 | if (err) { |
1973 | printk(KERN_ERR PFX | 1933 | printk(KERN_ERR PFX |
1974 | "Error: PCM \"%s\" not available or load failed.\n", | 1934 | "Error: PCM \"%s\" not available or load failed.\n", |
@@ -1977,7 +1937,7 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) | |||
1977 | } | 1937 | } |
1978 | } | 1938 | } |
1979 | 1939 | ||
1980 | if (!bcm->initvals0) { | 1940 | if (!phy->initvals0) { |
1981 | if (rev == 2 || rev == 4) { | 1941 | if (rev == 2 || rev == 4) { |
1982 | switch (phy->type) { | 1942 | switch (phy->type) { |
1983 | case BCM43xx_PHYTYPE_A: | 1943 | case BCM43xx_PHYTYPE_A: |
@@ -2008,20 +1968,20 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) | |||
2008 | snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", | 1968 | snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", |
2009 | nr, modparam_fwpostfix); | 1969 | nr, modparam_fwpostfix); |
2010 | 1970 | ||
2011 | err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev); | 1971 | err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev); |
2012 | if (err) { | 1972 | if (err) { |
2013 | printk(KERN_ERR PFX | 1973 | printk(KERN_ERR PFX |
2014 | "Error: InitVals \"%s\" not available or load failed.\n", | 1974 | "Error: InitVals \"%s\" not available or load failed.\n", |
2015 | buf); | 1975 | buf); |
2016 | goto error; | 1976 | goto error; |
2017 | } | 1977 | } |
2018 | if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) { | 1978 | if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) { |
2019 | printk(KERN_ERR PFX "InitVals fileformat error.\n"); | 1979 | printk(KERN_ERR PFX "InitVals fileformat error.\n"); |
2020 | goto error; | 1980 | goto error; |
2021 | } | 1981 | } |
2022 | } | 1982 | } |
2023 | 1983 | ||
2024 | if (!bcm->initvals1) { | 1984 | if (!phy->initvals1) { |
2025 | if (rev >= 5) { | 1985 | if (rev >= 5) { |
2026 | u32 sbtmstatehigh; | 1986 | u32 sbtmstatehigh; |
2027 | 1987 | ||
@@ -2043,14 +2003,14 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) | |||
2043 | snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", | 2003 | snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", |
2044 | nr, modparam_fwpostfix); | 2004 | nr, modparam_fwpostfix); |
2045 | 2005 | ||
2046 | err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev); | 2006 | err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev); |
2047 | if (err) { | 2007 | if (err) { |
2048 | printk(KERN_ERR PFX | 2008 | printk(KERN_ERR PFX |
2049 | "Error: InitVals \"%s\" not available or load failed.\n", | 2009 | "Error: InitVals \"%s\" not available or load failed.\n", |
2050 | buf); | 2010 | buf); |
2051 | goto error; | 2011 | goto error; |
2052 | } | 2012 | } |
2053 | if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) { | 2013 | if (phy->initvals1->size % sizeof(struct bcm43xx_initval)) { |
2054 | printk(KERN_ERR PFX "InitVals fileformat error.\n"); | 2014 | printk(KERN_ERR PFX "InitVals fileformat error.\n"); |
2055 | goto error; | 2015 | goto error; |
2056 | } | 2016 | } |
@@ -2070,12 +2030,13 @@ err_noinitval: | |||
2070 | 2030 | ||
2071 | static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) | 2031 | static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) |
2072 | { | 2032 | { |
2033 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); | ||
2073 | const u32 *data; | 2034 | const u32 *data; |
2074 | unsigned int i, len; | 2035 | unsigned int i, len; |
2075 | 2036 | ||
2076 | /* Upload Microcode. */ | 2037 | /* Upload Microcode. */ |
2077 | data = (u32 *)(bcm->ucode->data); | 2038 | data = (u32 *)(phy->ucode->data); |
2078 | len = bcm->ucode->size / sizeof(u32); | 2039 | len = phy->ucode->size / sizeof(u32); |
2079 | bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000); | 2040 | bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000); |
2080 | for (i = 0; i < len; i++) { | 2041 | for (i = 0; i < len; i++) { |
2081 | bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, | 2042 | bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, |
@@ -2084,8 +2045,8 @@ static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) | |||
2084 | } | 2045 | } |
2085 | 2046 | ||
2086 | /* Upload PCM data. */ | 2047 | /* Upload PCM data. */ |
2087 | data = (u32 *)(bcm->pcm->data); | 2048 | data = (u32 *)(phy->pcm->data); |
2088 | len = bcm->pcm->size / sizeof(u32); | 2049 | len = phy->pcm->size / sizeof(u32); |
2089 | bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea); | 2050 | bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea); |
2090 | bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000); | 2051 | bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000); |
2091 | bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb); | 2052 | bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb); |
@@ -2131,15 +2092,16 @@ err_format: | |||
2131 | 2092 | ||
2132 | static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) | 2093 | static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) |
2133 | { | 2094 | { |
2095 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); | ||
2134 | int err; | 2096 | int err; |
2135 | 2097 | ||
2136 | err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, | 2098 | err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data, |
2137 | bcm->initvals0->size / sizeof(struct bcm43xx_initval)); | 2099 | phy->initvals0->size / sizeof(struct bcm43xx_initval)); |
2138 | if (err) | 2100 | if (err) |
2139 | goto out; | 2101 | goto out; |
2140 | if (bcm->initvals1) { | 2102 | if (phy->initvals1) { |
2141 | err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data, | 2103 | err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data, |
2142 | bcm->initvals1->size / sizeof(struct bcm43xx_initval)); | 2104 | phy->initvals1->size / sizeof(struct bcm43xx_initval)); |
2143 | if (err) | 2105 | if (err) |
2144 | goto out; | 2106 | goto out; |
2145 | } | 2107 | } |
@@ -2156,9 +2118,7 @@ static struct pci_device_id bcm43xx_47xx_ids[] = { | |||
2156 | 2118 | ||
2157 | static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) | 2119 | static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) |
2158 | { | 2120 | { |
2159 | int res; | 2121 | int err; |
2160 | unsigned int i; | ||
2161 | u32 data; | ||
2162 | 2122 | ||
2163 | bcm->irq = bcm->pci_dev->irq; | 2123 | bcm->irq = bcm->pci_dev->irq; |
2164 | #ifdef CONFIG_BCM947XX | 2124 | #ifdef CONFIG_BCM947XX |
@@ -2175,32 +2135,12 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) | |||
2175 | } | 2135 | } |
2176 | } | 2136 | } |
2177 | #endif | 2137 | #endif |
2178 | res = request_irq(bcm->irq, bcm43xx_interrupt_handler, | 2138 | err = request_irq(bcm->irq, bcm43xx_interrupt_handler, |
2179 | IRQF_SHARED, KBUILD_MODNAME, bcm); | 2139 | IRQF_SHARED, KBUILD_MODNAME, bcm); |
2180 | if (res) { | 2140 | if (err) |
2181 | printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); | 2141 | printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); |
2182 | return -ENODEV; | ||
2183 | } | ||
2184 | bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff); | ||
2185 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402); | ||
2186 | i = 0; | ||
2187 | while (1) { | ||
2188 | data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); | ||
2189 | if (data == BCM43xx_IRQ_READY) | ||
2190 | break; | ||
2191 | i++; | ||
2192 | if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) { | ||
2193 | printk(KERN_ERR PFX "Card IRQ register not responding. " | ||
2194 | "Giving up.\n"); | ||
2195 | free_irq(bcm->irq, bcm); | ||
2196 | return -ENODEV; | ||
2197 | } | ||
2198 | udelay(10); | ||
2199 | } | ||
2200 | // dummy read | ||
2201 | bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); | ||
2202 | 2142 | ||
2203 | return 0; | 2143 | return err; |
2204 | } | 2144 | } |
2205 | 2145 | ||
2206 | /* Switch to the core used to write the GPIO register. | 2146 | /* Switch to the core used to write the GPIO register. |
@@ -2298,13 +2238,17 @@ static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm) | |||
2298 | /* http://bcm-specs.sipsolutions.net/EnableMac */ | 2238 | /* http://bcm-specs.sipsolutions.net/EnableMac */ |
2299 | void bcm43xx_mac_enable(struct bcm43xx_private *bcm) | 2239 | void bcm43xx_mac_enable(struct bcm43xx_private *bcm) |
2300 | { | 2240 | { |
2301 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, | 2241 | bcm->mac_suspended--; |
2302 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) | 2242 | assert(bcm->mac_suspended >= 0); |
2303 | | BCM43xx_SBF_MAC_ENABLED); | 2243 | if (bcm->mac_suspended == 0) { |
2304 | bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY); | 2244 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, |
2305 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ | 2245 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) |
2306 | bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ | 2246 | | BCM43xx_SBF_MAC_ENABLED); |
2307 | bcm43xx_power_saving_ctl_bits(bcm, -1, -1); | 2247 | bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY); |
2248 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ | ||
2249 | bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ | ||
2250 | bcm43xx_power_saving_ctl_bits(bcm, -1, -1); | ||
2251 | } | ||
2308 | } | 2252 | } |
2309 | 2253 | ||
2310 | /* http://bcm-specs.sipsolutions.net/SuspendMAC */ | 2254 | /* http://bcm-specs.sipsolutions.net/SuspendMAC */ |
@@ -2313,18 +2257,23 @@ void bcm43xx_mac_suspend(struct bcm43xx_private *bcm) | |||
2313 | int i; | 2257 | int i; |
2314 | u32 tmp; | 2258 | u32 tmp; |
2315 | 2259 | ||
2316 | bcm43xx_power_saving_ctl_bits(bcm, -1, 1); | 2260 | assert(bcm->mac_suspended >= 0); |
2317 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, | 2261 | if (bcm->mac_suspended == 0) { |
2318 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) | 2262 | bcm43xx_power_saving_ctl_bits(bcm, -1, 1); |
2319 | & ~BCM43xx_SBF_MAC_ENABLED); | 2263 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, |
2320 | bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ | 2264 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) |
2321 | for (i = 100000; i; i--) { | 2265 | & ~BCM43xx_SBF_MAC_ENABLED); |
2322 | tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); | 2266 | bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ |
2323 | if (tmp & BCM43xx_IRQ_READY) | 2267 | for (i = 10000; i; i--) { |
2324 | return; | 2268 | tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); |
2325 | udelay(10); | 2269 | if (tmp & BCM43xx_IRQ_READY) |
2270 | goto out; | ||
2271 | udelay(1); | ||
2272 | } | ||
2273 | printkl(KERN_ERR PFX "MAC suspend failed\n"); | ||
2326 | } | 2274 | } |
2327 | printkl(KERN_ERR PFX "MAC suspend failed\n"); | 2275 | out: |
2276 | bcm->mac_suspended++; | ||
2328 | } | 2277 | } |
2329 | 2278 | ||
2330 | void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, | 2279 | void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, |
@@ -2394,7 +2343,6 @@ static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm) | |||
2394 | if (!modparam_noleds) | 2343 | if (!modparam_noleds) |
2395 | bcm43xx_leds_exit(bcm); | 2344 | bcm43xx_leds_exit(bcm); |
2396 | bcm43xx_gpio_cleanup(bcm); | 2345 | bcm43xx_gpio_cleanup(bcm); |
2397 | free_irq(bcm->irq, bcm); | ||
2398 | bcm43xx_release_firmware(bcm, 0); | 2346 | bcm43xx_release_firmware(bcm, 0); |
2399 | } | 2347 | } |
2400 | 2348 | ||
@@ -2406,7 +2354,7 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) | |||
2406 | struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); | 2354 | struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); |
2407 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); | 2355 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); |
2408 | int err; | 2356 | int err; |
2409 | int tmp; | 2357 | int i, tmp; |
2410 | u32 value32; | 2358 | u32 value32; |
2411 | u16 value16; | 2359 | u16 value16; |
2412 | 2360 | ||
@@ -2419,13 +2367,53 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) | |||
2419 | goto out; | 2367 | goto out; |
2420 | bcm43xx_upload_microcode(bcm); | 2368 | bcm43xx_upload_microcode(bcm); |
2421 | 2369 | ||
2422 | err = bcm43xx_initialize_irq(bcm); | 2370 | bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF); |
2423 | if (err) | 2371 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402); |
2372 | i = 0; | ||
2373 | while (1) { | ||
2374 | value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); | ||
2375 | if (value32 == BCM43xx_IRQ_READY) | ||
2376 | break; | ||
2377 | i++; | ||
2378 | if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) { | ||
2379 | printk(KERN_ERR PFX "IRQ_READY timeout\n"); | ||
2380 | err = -ENODEV; | ||
2381 | goto err_release_fw; | ||
2382 | } | ||
2383 | udelay(10); | ||
2384 | } | ||
2385 | bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ | ||
2386 | |||
2387 | value16 = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, | ||
2388 | BCM43xx_UCODE_REVISION); | ||
2389 | |||
2390 | dprintk(KERN_INFO PFX "Microcode rev 0x%x, pl 0x%x " | ||
2391 | "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", value16, | ||
2392 | bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, | ||
2393 | BCM43xx_UCODE_PATCHLEVEL), | ||
2394 | (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, | ||
2395 | BCM43xx_UCODE_DATE) >> 12) & 0xf, | ||
2396 | (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, | ||
2397 | BCM43xx_UCODE_DATE) >> 8) & 0xf, | ||
2398 | bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, | ||
2399 | BCM43xx_UCODE_DATE) & 0xff, | ||
2400 | (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, | ||
2401 | BCM43xx_UCODE_TIME) >> 11) & 0x1f, | ||
2402 | (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, | ||
2403 | BCM43xx_UCODE_TIME) >> 5) & 0x3f, | ||
2404 | bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, | ||
2405 | BCM43xx_UCODE_TIME) & 0x1f); | ||
2406 | |||
2407 | if ( value16 > 0x128 ) { | ||
2408 | dprintk(KERN_ERR PFX | ||
2409 | "Firmware: no support for microcode rev > 0x128\n"); | ||
2410 | err = -1; | ||
2424 | goto err_release_fw; | 2411 | goto err_release_fw; |
2412 | } | ||
2425 | 2413 | ||
2426 | err = bcm43xx_gpio_init(bcm); | 2414 | err = bcm43xx_gpio_init(bcm); |
2427 | if (err) | 2415 | if (err) |
2428 | goto err_free_irq; | 2416 | goto err_release_fw; |
2429 | 2417 | ||
2430 | err = bcm43xx_upload_initvals(bcm); | 2418 | err = bcm43xx_upload_initvals(bcm); |
2431 | if (err) | 2419 | if (err) |
@@ -2489,10 +2477,12 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) | |||
2489 | bcm43xx_write32(bcm, 0x018C, 0x02000000); | 2477 | bcm43xx_write32(bcm, 0x018C, 0x02000000); |
2490 | } | 2478 | } |
2491 | bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000); | 2479 | bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000); |
2492 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0001DC00); | 2480 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_IRQ_MASK, 0x0001DC00); |
2481 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0000DC00); | ||
2493 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00); | 2482 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00); |
2494 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0000DC00); | 2483 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0001DC00); |
2495 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0001DC00); | 2484 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0000DC00); |
2485 | bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_IRQ_MASK, 0x0000DC00); | ||
2496 | 2486 | ||
2497 | value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); | 2487 | value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); |
2498 | value32 |= 0x00100000; | 2488 | value32 |= 0x00100000; |
@@ -2509,8 +2499,6 @@ err_radio_off: | |||
2509 | bcm43xx_radio_turn_off(bcm); | 2499 | bcm43xx_radio_turn_off(bcm); |
2510 | err_gpio_cleanup: | 2500 | err_gpio_cleanup: |
2511 | bcm43xx_gpio_cleanup(bcm); | 2501 | bcm43xx_gpio_cleanup(bcm); |
2512 | err_free_irq: | ||
2513 | free_irq(bcm->irq, bcm); | ||
2514 | err_release_fw: | 2502 | err_release_fw: |
2515 | bcm43xx_release_firmware(bcm, 1); | 2503 | bcm43xx_release_firmware(bcm, 1); |
2516 | goto out; | 2504 | goto out; |
@@ -2550,11 +2538,9 @@ static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy) | |||
2550 | { | 2538 | { |
2551 | /* Initialize a "phyinfo" structure. The structure is already | 2539 | /* Initialize a "phyinfo" structure. The structure is already |
2552 | * zeroed out. | 2540 | * zeroed out. |
2541 | * This is called on insmod time to initialize members. | ||
2553 | */ | 2542 | */ |
2554 | phy->antenna_diversity = 0xFFFF; | ||
2555 | phy->savedpctlreg = 0xFFFF; | 2543 | phy->savedpctlreg = 0xFFFF; |
2556 | phy->minlowsig[0] = 0xFFFF; | ||
2557 | phy->minlowsig[1] = 0xFFFF; | ||
2558 | spin_lock_init(&phy->lock); | 2544 | spin_lock_init(&phy->lock); |
2559 | } | 2545 | } |
2560 | 2546 | ||
@@ -2562,14 +2548,11 @@ static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio) | |||
2562 | { | 2548 | { |
2563 | /* Initialize a "radioinfo" structure. The structure is already | 2549 | /* Initialize a "radioinfo" structure. The structure is already |
2564 | * zeroed out. | 2550 | * zeroed out. |
2551 | * This is called on insmod time to initialize members. | ||
2565 | */ | 2552 | */ |
2566 | radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; | 2553 | radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; |
2567 | radio->channel = 0xFF; | 2554 | radio->channel = 0xFF; |
2568 | radio->initial_channel = 0xFF; | 2555 | radio->initial_channel = 0xFF; |
2569 | radio->lofcal = 0xFFFF; | ||
2570 | radio->initval = 0xFFFF; | ||
2571 | radio->nrssi[0] = -1000; | ||
2572 | radio->nrssi[1] = -1000; | ||
2573 | } | 2556 | } |
2574 | 2557 | ||
2575 | static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) | 2558 | static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) |
@@ -2587,7 +2570,6 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) | |||
2587 | * BCM43xx_MAX_80211_CORES); | 2570 | * BCM43xx_MAX_80211_CORES); |
2588 | memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211) | 2571 | memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211) |
2589 | * BCM43xx_MAX_80211_CORES); | 2572 | * BCM43xx_MAX_80211_CORES); |
2590 | bcm->current_80211_core_idx = -1; | ||
2591 | bcm->nr_80211_available = 0; | 2573 | bcm->nr_80211_available = 0; |
2592 | bcm->current_core = NULL; | 2574 | bcm->current_core = NULL; |
2593 | bcm->active_80211_core = NULL; | 2575 | bcm->active_80211_core = NULL; |
@@ -2757,6 +2739,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) | |||
2757 | goto out; | 2739 | goto out; |
2758 | } | 2740 | } |
2759 | bcm->nr_80211_available++; | 2741 | bcm->nr_80211_available++; |
2742 | core->priv = ext_80211; | ||
2760 | bcm43xx_init_struct_phyinfo(&ext_80211->phy); | 2743 | bcm43xx_init_struct_phyinfo(&ext_80211->phy); |
2761 | bcm43xx_init_struct_radioinfo(&ext_80211->radio); | 2744 | bcm43xx_init_struct_radioinfo(&ext_80211->radio); |
2762 | break; | 2745 | break; |
@@ -2857,7 +2840,8 @@ static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm) | |||
2857 | } | 2840 | } |
2858 | 2841 | ||
2859 | /* http://bcm-specs.sipsolutions.net/80211Init */ | 2842 | /* http://bcm-specs.sipsolutions.net/80211Init */ |
2860 | static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) | 2843 | static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm, |
2844 | int active_wlcore) | ||
2861 | { | 2845 | { |
2862 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); | 2846 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); |
2863 | struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); | 2847 | struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); |
@@ -2939,19 +2923,26 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) | |||
2939 | if (bcm->current_core->rev >= 5) | 2923 | if (bcm->current_core->rev >= 5) |
2940 | bcm43xx_write16(bcm, 0x043C, 0x000C); | 2924 | bcm43xx_write16(bcm, 0x043C, 0x000C); |
2941 | 2925 | ||
2942 | if (bcm43xx_using_pio(bcm)) | 2926 | if (active_wlcore) { |
2943 | err = bcm43xx_pio_init(bcm); | 2927 | if (bcm43xx_using_pio(bcm)) |
2944 | else | 2928 | err = bcm43xx_pio_init(bcm); |
2945 | err = bcm43xx_dma_init(bcm); | 2929 | else |
2946 | if (err) | 2930 | err = bcm43xx_dma_init(bcm); |
2947 | goto err_chip_cleanup; | 2931 | if (err) |
2932 | goto err_chip_cleanup; | ||
2933 | } | ||
2948 | bcm43xx_write16(bcm, 0x0612, 0x0050); | 2934 | bcm43xx_write16(bcm, 0x0612, 0x0050); |
2949 | bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); | 2935 | bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); |
2950 | bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); | 2936 | bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); |
2951 | 2937 | ||
2952 | bcm43xx_mac_enable(bcm); | 2938 | if (active_wlcore) { |
2953 | bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); | 2939 | if (radio->initial_channel != 0xFF) |
2940 | bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0); | ||
2941 | } | ||
2954 | 2942 | ||
2943 | /* Don't enable MAC/IRQ here, as it will race with the IRQ handler. | ||
2944 | * We enable it later. | ||
2945 | */ | ||
2955 | bcm->current_core->initialized = 1; | 2946 | bcm->current_core->initialized = 1; |
2956 | out: | 2947 | out: |
2957 | return err; | 2948 | return err; |
@@ -3066,11 +3057,6 @@ out: | |||
3066 | return err; | 3057 | return err; |
3067 | } | 3058 | } |
3068 | 3059 | ||
3069 | static void bcm43xx_softmac_init(struct bcm43xx_private *bcm) | ||
3070 | { | ||
3071 | ieee80211softmac_start(bcm->net_dev); | ||
3072 | } | ||
3073 | |||
3074 | static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) | 3060 | static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) |
3075 | { | 3061 | { |
3076 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); | 3062 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); |
@@ -3182,47 +3168,46 @@ static void bcm43xx_periodic_work_handler(void *d) | |||
3182 | /* Periodic work will take a long time, so we want it to | 3168 | /* Periodic work will take a long time, so we want it to |
3183 | * be preemtible. | 3169 | * be preemtible. |
3184 | */ | 3170 | */ |
3185 | bcm43xx_lock_irqonly(bcm, flags); | 3171 | mutex_lock(&bcm->mutex); |
3186 | netif_stop_queue(bcm->net_dev); | 3172 | netif_stop_queue(bcm->net_dev); |
3173 | synchronize_net(); | ||
3174 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
3175 | bcm43xx_mac_suspend(bcm); | ||
3187 | if (bcm43xx_using_pio(bcm)) | 3176 | if (bcm43xx_using_pio(bcm)) |
3188 | bcm43xx_pio_freeze_txqueues(bcm); | 3177 | bcm43xx_pio_freeze_txqueues(bcm); |
3189 | savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | 3178 | savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); |
3190 | bcm43xx_unlock_irqonly(bcm, flags); | 3179 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
3191 | bcm43xx_lock_noirq(bcm); | ||
3192 | bcm43xx_synchronize_irq(bcm); | 3180 | bcm43xx_synchronize_irq(bcm); |
3193 | } else { | 3181 | } else { |
3194 | /* Periodic work should take short time, so we want low | 3182 | /* Periodic work should take short time, so we want low |
3195 | * locking overhead. | 3183 | * locking overhead. |
3196 | */ | 3184 | */ |
3197 | bcm43xx_lock_irqsafe(bcm, flags); | 3185 | mutex_lock(&bcm->mutex); |
3186 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
3198 | } | 3187 | } |
3199 | 3188 | ||
3200 | do_periodic_work(bcm); | 3189 | do_periodic_work(bcm); |
3201 | 3190 | ||
3202 | if (badness > BADNESS_LIMIT) { | 3191 | if (badness > BADNESS_LIMIT) { |
3203 | bcm43xx_lock_irqonly(bcm, flags); | 3192 | spin_lock_irqsave(&bcm->irq_lock, flags); |
3204 | if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) { | 3193 | tasklet_enable(&bcm->isr_tasklet); |
3205 | tasklet_enable(&bcm->isr_tasklet); | 3194 | bcm43xx_interrupt_enable(bcm, savedirqs); |
3206 | bcm43xx_interrupt_enable(bcm, savedirqs); | 3195 | if (bcm43xx_using_pio(bcm)) |
3207 | if (bcm43xx_using_pio(bcm)) | 3196 | bcm43xx_pio_thaw_txqueues(bcm); |
3208 | bcm43xx_pio_thaw_txqueues(bcm); | 3197 | bcm43xx_mac_enable(bcm); |
3209 | } | ||
3210 | netif_wake_queue(bcm->net_dev); | 3198 | netif_wake_queue(bcm->net_dev); |
3211 | mmiowb(); | ||
3212 | bcm43xx_unlock_irqonly(bcm, flags); | ||
3213 | bcm43xx_unlock_noirq(bcm); | ||
3214 | } else { | ||
3215 | mmiowb(); | ||
3216 | bcm43xx_unlock_irqsafe(bcm, flags); | ||
3217 | } | 3199 | } |
3200 | mmiowb(); | ||
3201 | spin_unlock_irqrestore(&bcm->irq_lock, flags); | ||
3202 | mutex_unlock(&bcm->mutex); | ||
3218 | } | 3203 | } |
3219 | 3204 | ||
3220 | static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) | 3205 | void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) |
3221 | { | 3206 | { |
3222 | cancel_rearming_delayed_work(&bcm->periodic_work); | 3207 | cancel_rearming_delayed_work(&bcm->periodic_work); |
3223 | } | 3208 | } |
3224 | 3209 | ||
3225 | static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) | 3210 | void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) |
3226 | { | 3211 | { |
3227 | struct work_struct *work = &(bcm->periodic_work); | 3212 | struct work_struct *work = &(bcm->periodic_work); |
3228 | 3213 | ||
@@ -3243,9 +3228,9 @@ static int bcm43xx_rng_read(struct hwrng *rng, u32 *data) | |||
3243 | struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv; | 3228 | struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv; |
3244 | unsigned long flags; | 3229 | unsigned long flags; |
3245 | 3230 | ||
3246 | bcm43xx_lock_irqonly(bcm, flags); | 3231 | spin_lock_irqsave(&(bcm)->irq_lock, flags); |
3247 | *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG); | 3232 | *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG); |
3248 | bcm43xx_unlock_irqonly(bcm, flags); | 3233 | spin_unlock_irqrestore(&(bcm)->irq_lock, flags); |
3249 | 3234 | ||
3250 | return (sizeof(u16)); | 3235 | return (sizeof(u16)); |
3251 | } | 3236 | } |
@@ -3271,139 +3256,329 @@ static int bcm43xx_rng_init(struct bcm43xx_private *bcm) | |||
3271 | return err; | 3256 | return err; |
3272 | } | 3257 | } |
3273 | 3258 | ||
3274 | /* This is the opposite of bcm43xx_init_board() */ | 3259 | static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm) |
3275 | static void bcm43xx_free_board(struct bcm43xx_private *bcm) | ||
3276 | { | 3260 | { |
3261 | int ret = 0; | ||
3277 | int i, err; | 3262 | int i, err; |
3263 | struct bcm43xx_coreinfo *core; | ||
3278 | 3264 | ||
3279 | bcm43xx_lock_noirq(bcm); | 3265 | bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); |
3266 | for (i = 0; i < bcm->nr_80211_available; i++) { | ||
3267 | core = &(bcm->core_80211[i]); | ||
3268 | assert(core->available); | ||
3269 | if (!core->initialized) | ||
3270 | continue; | ||
3271 | err = bcm43xx_switch_core(bcm, core); | ||
3272 | if (err) { | ||
3273 | dprintk(KERN_ERR PFX "shutdown_all_wireless_cores " | ||
3274 | "switch_core failed (%d)\n", err); | ||
3275 | ret = err; | ||
3276 | continue; | ||
3277 | } | ||
3278 | bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | ||
3279 | bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ | ||
3280 | bcm43xx_wireless_core_cleanup(bcm); | ||
3281 | if (core == bcm->active_80211_core) | ||
3282 | bcm->active_80211_core = NULL; | ||
3283 | } | ||
3284 | free_irq(bcm->irq, bcm); | ||
3285 | bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); | ||
3286 | |||
3287 | return ret; | ||
3288 | } | ||
3289 | |||
3290 | /* This is the opposite of bcm43xx_init_board() */ | ||
3291 | static void bcm43xx_free_board(struct bcm43xx_private *bcm) | ||
3292 | { | ||
3293 | bcm43xx_rng_exit(bcm); | ||
3280 | bcm43xx_sysfs_unregister(bcm); | 3294 | bcm43xx_sysfs_unregister(bcm); |
3281 | bcm43xx_periodic_tasks_delete(bcm); | 3295 | bcm43xx_periodic_tasks_delete(bcm); |
3282 | 3296 | ||
3283 | bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); | 3297 | mutex_lock(&(bcm)->mutex); |
3298 | bcm43xx_shutdown_all_wireless_cores(bcm); | ||
3299 | bcm43xx_pctl_set_crystal(bcm, 0); | ||
3300 | mutex_unlock(&(bcm)->mutex); | ||
3301 | } | ||
3284 | 3302 | ||
3285 | bcm43xx_rng_exit(bcm); | 3303 | static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy) |
3304 | { | ||
3305 | phy->antenna_diversity = 0xFFFF; | ||
3306 | memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig)); | ||
3307 | memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos)); | ||
3308 | |||
3309 | /* Flags */ | ||
3310 | phy->calibrated = 0; | ||
3311 | phy->is_locked = 0; | ||
3312 | |||
3313 | if (phy->_lo_pairs) { | ||
3314 | memset(phy->_lo_pairs, 0, | ||
3315 | sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT); | ||
3316 | } | ||
3317 | memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain)); | ||
3318 | } | ||
3319 | |||
3320 | static void prepare_radiodata_for_init(struct bcm43xx_private *bcm, | ||
3321 | struct bcm43xx_radioinfo *radio) | ||
3322 | { | ||
3323 | int i; | ||
3324 | |||
3325 | /* Set default attenuation values. */ | ||
3326 | radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm); | ||
3327 | radio->radio_atten = bcm43xx_default_radio_attenuation(bcm); | ||
3328 | radio->txctl1 = bcm43xx_default_txctl1(bcm); | ||
3329 | radio->txctl2 = 0xFFFF; | ||
3330 | radio->txpwr_offset = 0; | ||
3331 | |||
3332 | /* NRSSI */ | ||
3333 | radio->nrssislope = 0; | ||
3334 | for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++) | ||
3335 | radio->nrssi[i] = -1000; | ||
3336 | for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++) | ||
3337 | radio->nrssi_lt[i] = i; | ||
3338 | |||
3339 | radio->lofcal = 0xFFFF; | ||
3340 | radio->initval = 0xFFFF; | ||
3341 | |||
3342 | radio->aci_enable = 0; | ||
3343 | radio->aci_wlan_automatic = 0; | ||
3344 | radio->aci_hw_rssi = 0; | ||
3345 | } | ||
3346 | |||
3347 | static void prepare_priv_for_init(struct bcm43xx_private *bcm) | ||
3348 | { | ||
3349 | int i; | ||
3350 | struct bcm43xx_coreinfo *core; | ||
3351 | struct bcm43xx_coreinfo_80211 *wlext; | ||
3352 | |||
3353 | assert(!bcm->active_80211_core); | ||
3354 | |||
3355 | bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); | ||
3356 | |||
3357 | /* Flags */ | ||
3358 | bcm->was_initialized = 0; | ||
3359 | bcm->reg124_set_0x4 = 0; | ||
3360 | |||
3361 | /* Stats */ | ||
3362 | memset(&bcm->stats, 0, sizeof(bcm->stats)); | ||
3363 | |||
3364 | /* Wireless core data */ | ||
3286 | for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { | 3365 | for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { |
3287 | if (!bcm->core_80211[i].available) | 3366 | core = &(bcm->core_80211[i]); |
3288 | continue; | 3367 | wlext = core->priv; |
3289 | if (!bcm->core_80211[i].initialized) | 3368 | |
3369 | if (!core->available) | ||
3290 | continue; | 3370 | continue; |
3371 | assert(wlext == &(bcm->core_80211_ext[i])); | ||
3291 | 3372 | ||
3292 | err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); | 3373 | prepare_phydata_for_init(&wlext->phy); |
3293 | assert(err == 0); | 3374 | prepare_radiodata_for_init(bcm, &wlext->radio); |
3294 | bcm43xx_wireless_core_cleanup(bcm); | ||
3295 | } | 3375 | } |
3296 | 3376 | ||
3297 | bcm43xx_pctl_set_crystal(bcm, 0); | 3377 | /* IRQ related flags */ |
3378 | bcm->irq_reason = 0; | ||
3379 | memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason)); | ||
3380 | bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; | ||
3298 | 3381 | ||
3299 | bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); | 3382 | bcm->mac_suspended = 1; |
3300 | bcm43xx_unlock_noirq(bcm); | 3383 | |
3384 | /* Noise calculation context */ | ||
3385 | memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc)); | ||
3386 | |||
3387 | /* Periodic work context */ | ||
3388 | bcm->periodic_state = 0; | ||
3301 | } | 3389 | } |
3302 | 3390 | ||
3303 | static int bcm43xx_init_board(struct bcm43xx_private *bcm) | 3391 | static int wireless_core_up(struct bcm43xx_private *bcm, |
3392 | int active_wlcore) | ||
3393 | { | ||
3394 | int err; | ||
3395 | |||
3396 | if (!bcm43xx_core_enabled(bcm)) | ||
3397 | bcm43xx_wireless_core_reset(bcm, 1); | ||
3398 | if (!active_wlcore) | ||
3399 | bcm43xx_wireless_core_mark_inactive(bcm); | ||
3400 | err = bcm43xx_wireless_core_init(bcm, active_wlcore); | ||
3401 | if (err) | ||
3402 | goto out; | ||
3403 | if (!active_wlcore) | ||
3404 | bcm43xx_radio_turn_off(bcm); | ||
3405 | out: | ||
3406 | return err; | ||
3407 | } | ||
3408 | |||
3409 | /* Select and enable the "to be used" wireless core. | ||
3410 | * Locking: bcm->mutex must be aquired before calling this. | ||
3411 | * bcm->irq_lock must not be aquired. | ||
3412 | */ | ||
3413 | int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm, | ||
3414 | int phytype) | ||
3304 | { | 3415 | { |
3305 | int i, err; | 3416 | int i, err; |
3306 | int connect_phy; | 3417 | struct bcm43xx_coreinfo *active_core = NULL; |
3418 | struct bcm43xx_coreinfo_80211 *active_wlext = NULL; | ||
3419 | struct bcm43xx_coreinfo *core; | ||
3420 | struct bcm43xx_coreinfo_80211 *wlext; | ||
3421 | int adjust_active_sbtmstatelow = 0; | ||
3307 | 3422 | ||
3308 | might_sleep(); | 3423 | might_sleep(); |
3309 | 3424 | ||
3310 | bcm43xx_lock_noirq(bcm); | 3425 | if (phytype < 0) { |
3311 | bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); | 3426 | /* If no phytype is requested, select the first core. */ |
3427 | assert(bcm->core_80211[0].available); | ||
3428 | wlext = bcm->core_80211[0].priv; | ||
3429 | phytype = wlext->phy.type; | ||
3430 | } | ||
3431 | /* Find the requested core. */ | ||
3432 | for (i = 0; i < bcm->nr_80211_available; i++) { | ||
3433 | core = &(bcm->core_80211[i]); | ||
3434 | wlext = core->priv; | ||
3435 | if (wlext->phy.type == phytype) { | ||
3436 | active_core = core; | ||
3437 | active_wlext = wlext; | ||
3438 | break; | ||
3439 | } | ||
3440 | } | ||
3441 | if (!active_core) | ||
3442 | return -ESRCH; /* No such PHYTYPE on this board. */ | ||
3443 | |||
3444 | if (bcm->active_80211_core) { | ||
3445 | /* We already selected a wl core in the past. | ||
3446 | * So first clean up everything. | ||
3447 | */ | ||
3448 | dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n"); | ||
3449 | ieee80211softmac_stop(bcm->net_dev); | ||
3450 | bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); | ||
3451 | err = bcm43xx_disable_interrupts_sync(bcm); | ||
3452 | assert(!err); | ||
3453 | tasklet_enable(&bcm->isr_tasklet); | ||
3454 | err = bcm43xx_shutdown_all_wireless_cores(bcm); | ||
3455 | if (err) | ||
3456 | goto error; | ||
3457 | /* Ok, everything down, continue to re-initialize. */ | ||
3458 | bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); | ||
3459 | } | ||
3460 | |||
3461 | /* Reset all data structures. */ | ||
3462 | prepare_priv_for_init(bcm); | ||
3312 | 3463 | ||
3313 | err = bcm43xx_pctl_set_crystal(bcm, 1); | ||
3314 | if (err) | ||
3315 | goto out; | ||
3316 | err = bcm43xx_pctl_init(bcm); | ||
3317 | if (err) | ||
3318 | goto err_crystal_off; | ||
3319 | err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST); | 3464 | err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST); |
3320 | if (err) | 3465 | if (err) |
3321 | goto err_crystal_off; | 3466 | goto error; |
3322 | 3467 | ||
3323 | tasklet_enable(&bcm->isr_tasklet); | 3468 | /* Mark all unused cores "inactive". */ |
3324 | for (i = 0; i < bcm->nr_80211_available; i++) { | 3469 | for (i = 0; i < bcm->nr_80211_available; i++) { |
3325 | err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); | 3470 | core = &(bcm->core_80211[i]); |
3326 | assert(err != -ENODEV); | 3471 | wlext = core->priv; |
3327 | if (err) | ||
3328 | goto err_80211_unwind; | ||
3329 | 3472 | ||
3330 | /* Enable the selected wireless core. | 3473 | if (core == active_core) |
3331 | * Connect PHY only on the first core. | 3474 | continue; |
3332 | */ | 3475 | err = bcm43xx_switch_core(bcm, core); |
3333 | if (!bcm43xx_core_enabled(bcm)) { | 3476 | if (err) { |
3334 | if (bcm->nr_80211_available == 1) { | 3477 | dprintk(KERN_ERR PFX "Could not switch to inactive " |
3335 | connect_phy = bcm43xx_current_phy(bcm)->connected; | 3478 | "802.11 core (%d)\n", err); |
3336 | } else { | 3479 | goto error; |
3337 | if (i == 0) | ||
3338 | connect_phy = 1; | ||
3339 | else | ||
3340 | connect_phy = 0; | ||
3341 | } | ||
3342 | bcm43xx_wireless_core_reset(bcm, connect_phy); | ||
3343 | } | 3480 | } |
3481 | err = wireless_core_up(bcm, 0); | ||
3482 | if (err) { | ||
3483 | dprintk(KERN_ERR PFX "core_up for inactive 802.11 core " | ||
3484 | "failed (%d)\n", err); | ||
3485 | goto error; | ||
3486 | } | ||
3487 | adjust_active_sbtmstatelow = 1; | ||
3488 | } | ||
3344 | 3489 | ||
3345 | if (i != 0) | 3490 | /* Now initialize the active 802.11 core. */ |
3346 | bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]); | 3491 | err = bcm43xx_switch_core(bcm, active_core); |
3347 | 3492 | if (err) { | |
3348 | err = bcm43xx_wireless_core_init(bcm); | 3493 | dprintk(KERN_ERR PFX "Could not switch to active " |
3349 | if (err) | 3494 | "802.11 core (%d)\n", err); |
3350 | goto err_80211_unwind; | 3495 | goto error; |
3496 | } | ||
3497 | if (adjust_active_sbtmstatelow && | ||
3498 | active_wlext->phy.type == BCM43xx_PHYTYPE_G) { | ||
3499 | u32 sbtmstatelow; | ||
3351 | 3500 | ||
3352 | if (i != 0) { | 3501 | sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); |
3353 | bcm43xx_mac_suspend(bcm); | 3502 | sbtmstatelow |= 0x20000000; |
3354 | bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | 3503 | bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); |
3355 | bcm43xx_radio_turn_off(bcm); | ||
3356 | } | ||
3357 | } | 3504 | } |
3358 | bcm->active_80211_core = &bcm->core_80211[0]; | 3505 | err = wireless_core_up(bcm, 1); |
3359 | if (bcm->nr_80211_available >= 2) { | 3506 | if (err) { |
3360 | bcm43xx_switch_core(bcm, &bcm->core_80211[0]); | 3507 | dprintk(KERN_ERR PFX "core_up for active 802.11 core " |
3361 | bcm43xx_mac_enable(bcm); | 3508 | "failed (%d)\n", err); |
3509 | goto error; | ||
3362 | } | 3510 | } |
3363 | err = bcm43xx_rng_init(bcm); | 3511 | err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); |
3364 | if (err) | 3512 | if (err) |
3365 | goto err_80211_unwind; | 3513 | goto error; |
3514 | bcm->active_80211_core = active_core; | ||
3515 | |||
3366 | bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); | 3516 | bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); |
3367 | bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); | 3517 | bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); |
3368 | dprintk(KERN_INFO PFX "80211 cores initialized\n"); | ||
3369 | bcm43xx_security_init(bcm); | 3518 | bcm43xx_security_init(bcm); |
3370 | bcm43xx_softmac_init(bcm); | 3519 | ieee80211softmac_start(bcm->net_dev); |
3371 | 3520 | ||
3372 | bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); | 3521 | /* Let's go! Be careful after enabling the IRQs. |
3522 | * Don't switch cores, for example. | ||
3523 | */ | ||
3524 | bcm43xx_mac_enable(bcm); | ||
3525 | bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); | ||
3526 | err = bcm43xx_initialize_irq(bcm); | ||
3527 | if (err) | ||
3528 | goto error; | ||
3529 | bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); | ||
3373 | 3530 | ||
3374 | if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) { | 3531 | dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n", |
3375 | bcm43xx_mac_suspend(bcm); | 3532 | active_wlext->phy.type); |
3376 | bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0); | ||
3377 | bcm43xx_mac_enable(bcm); | ||
3378 | } | ||
3379 | 3533 | ||
3380 | /* Initialization of the board is done. Flag it as such. */ | 3534 | return 0; |
3381 | bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); | 3535 | |
3536 | error: | ||
3537 | bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); | ||
3538 | bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); | ||
3539 | return err; | ||
3540 | } | ||
3382 | 3541 | ||
3542 | static int bcm43xx_init_board(struct bcm43xx_private *bcm) | ||
3543 | { | ||
3544 | int err; | ||
3545 | |||
3546 | mutex_lock(&(bcm)->mutex); | ||
3547 | |||
3548 | tasklet_enable(&bcm->isr_tasklet); | ||
3549 | err = bcm43xx_pctl_set_crystal(bcm, 1); | ||
3550 | if (err) | ||
3551 | goto err_tasklet; | ||
3552 | err = bcm43xx_pctl_init(bcm); | ||
3553 | if (err) | ||
3554 | goto err_crystal_off; | ||
3555 | err = bcm43xx_select_wireless_core(bcm, -1); | ||
3556 | if (err) | ||
3557 | goto err_crystal_off; | ||
3558 | err = bcm43xx_sysfs_register(bcm); | ||
3559 | if (err) | ||
3560 | goto err_wlshutdown; | ||
3561 | err = bcm43xx_rng_init(bcm); | ||
3562 | if (err) | ||
3563 | goto err_sysfs_unreg; | ||
3383 | bcm43xx_periodic_tasks_setup(bcm); | 3564 | bcm43xx_periodic_tasks_setup(bcm); |
3384 | bcm43xx_sysfs_register(bcm); | ||
3385 | //FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though... | ||
3386 | 3565 | ||
3387 | /*FIXME: This should be handled by softmac instead. */ | 3566 | /*FIXME: This should be handled by softmac instead. */ |
3388 | schedule_work(&bcm->softmac->associnfo.work); | 3567 | schedule_work(&bcm->softmac->associnfo.work); |
3389 | 3568 | ||
3390 | assert(err == 0); | ||
3391 | out: | 3569 | out: |
3392 | bcm43xx_unlock_noirq(bcm); | 3570 | mutex_unlock(&(bcm)->mutex); |
3393 | 3571 | ||
3394 | return err; | 3572 | return err; |
3395 | 3573 | ||
3396 | err_80211_unwind: | 3574 | err_sysfs_unreg: |
3397 | tasklet_disable(&bcm->isr_tasklet); | 3575 | bcm43xx_sysfs_unregister(bcm); |
3398 | /* unwind all 80211 initialization */ | 3576 | err_wlshutdown: |
3399 | for (i = 0; i < bcm->nr_80211_available; i++) { | 3577 | bcm43xx_shutdown_all_wireless_cores(bcm); |
3400 | if (!bcm->core_80211[i].initialized) | ||
3401 | continue; | ||
3402 | bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | ||
3403 | bcm43xx_wireless_core_cleanup(bcm); | ||
3404 | } | ||
3405 | err_crystal_off: | 3578 | err_crystal_off: |
3406 | bcm43xx_pctl_set_crystal(bcm, 0); | 3579 | bcm43xx_pctl_set_crystal(bcm, 0); |
3580 | err_tasklet: | ||
3581 | tasklet_disable(&bcm->isr_tasklet); | ||
3407 | goto out; | 3582 | goto out; |
3408 | } | 3583 | } |
3409 | 3584 | ||
@@ -3647,7 +3822,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, | |||
3647 | struct bcm43xx_radioinfo *radio; | 3822 | struct bcm43xx_radioinfo *radio; |
3648 | unsigned long flags; | 3823 | unsigned long flags; |
3649 | 3824 | ||
3650 | bcm43xx_lock_irqsafe(bcm, flags); | 3825 | mutex_lock(&bcm->mutex); |
3826 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
3651 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { | 3827 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { |
3652 | bcm43xx_mac_suspend(bcm); | 3828 | bcm43xx_mac_suspend(bcm); |
3653 | bcm43xx_radio_selectchannel(bcm, channel, 0); | 3829 | bcm43xx_radio_selectchannel(bcm, channel, 0); |
@@ -3656,7 +3832,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, | |||
3656 | radio = bcm43xx_current_radio(bcm); | 3832 | radio = bcm43xx_current_radio(bcm); |
3657 | radio->initial_channel = channel; | 3833 | radio->initial_channel = channel; |
3658 | } | 3834 | } |
3659 | bcm43xx_unlock_irqsafe(bcm, flags); | 3835 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
3836 | mutex_unlock(&bcm->mutex); | ||
3660 | } | 3837 | } |
3661 | 3838 | ||
3662 | /* set_security() callback in struct ieee80211_device */ | 3839 | /* set_security() callback in struct ieee80211_device */ |
@@ -3670,7 +3847,8 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, | |||
3670 | 3847 | ||
3671 | dprintk(KERN_INFO PFX "set security called"); | 3848 | dprintk(KERN_INFO PFX "set security called"); |
3672 | 3849 | ||
3673 | bcm43xx_lock_irqsafe(bcm, flags); | 3850 | mutex_lock(&bcm->mutex); |
3851 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
3674 | 3852 | ||
3675 | for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) | 3853 | for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) |
3676 | if (sec->flags & (1<<keyidx)) { | 3854 | if (sec->flags & (1<<keyidx)) { |
@@ -3739,7 +3917,8 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, | |||
3739 | } else | 3917 | } else |
3740 | bcm43xx_clear_keys(bcm); | 3918 | bcm43xx_clear_keys(bcm); |
3741 | } | 3919 | } |
3742 | bcm43xx_unlock_irqsafe(bcm, flags); | 3920 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
3921 | mutex_unlock(&bcm->mutex); | ||
3743 | } | 3922 | } |
3744 | 3923 | ||
3745 | /* hard_start_xmit() callback in struct ieee80211_device */ | 3924 | /* hard_start_xmit() callback in struct ieee80211_device */ |
@@ -3751,12 +3930,14 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, | |||
3751 | int err = -ENODEV; | 3930 | int err = -ENODEV; |
3752 | unsigned long flags; | 3931 | unsigned long flags; |
3753 | 3932 | ||
3754 | bcm43xx_lock_irqonly(bcm, flags); | 3933 | spin_lock_irqsave(&bcm->irq_lock, flags); |
3755 | if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) | 3934 | if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) |
3756 | err = bcm43xx_tx(bcm, txb); | 3935 | err = bcm43xx_tx(bcm, txb); |
3757 | bcm43xx_unlock_irqonly(bcm, flags); | 3936 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
3758 | 3937 | ||
3759 | return err; | 3938 | if (unlikely(err)) |
3939 | return NETDEV_TX_BUSY; | ||
3940 | return NETDEV_TX_OK; | ||
3760 | } | 3941 | } |
3761 | 3942 | ||
3762 | static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev) | 3943 | static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev) |
@@ -3769,9 +3950,9 @@ static void bcm43xx_net_tx_timeout(struct net_device *net_dev) | |||
3769 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 3950 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
3770 | unsigned long flags; | 3951 | unsigned long flags; |
3771 | 3952 | ||
3772 | bcm43xx_lock_irqonly(bcm, flags); | 3953 | spin_lock_irqsave(&bcm->irq_lock, flags); |
3773 | bcm43xx_controller_restart(bcm, "TX timeout"); | 3954 | bcm43xx_controller_restart(bcm, "TX timeout"); |
3774 | bcm43xx_unlock_irqonly(bcm, flags); | 3955 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
3775 | } | 3956 | } |
3776 | 3957 | ||
3777 | #ifdef CONFIG_NET_POLL_CONTROLLER | 3958 | #ifdef CONFIG_NET_POLL_CONTROLLER |
@@ -3781,7 +3962,8 @@ static void bcm43xx_net_poll_controller(struct net_device *net_dev) | |||
3781 | unsigned long flags; | 3962 | unsigned long flags; |
3782 | 3963 | ||
3783 | local_irq_save(flags); | 3964 | local_irq_save(flags); |
3784 | bcm43xx_interrupt_handler(bcm->irq, bcm, NULL); | 3965 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) |
3966 | bcm43xx_interrupt_handler(bcm->irq, bcm, NULL); | ||
3785 | local_irq_restore(flags); | 3967 | local_irq_restore(flags); |
3786 | } | 3968 | } |
3787 | #endif /* CONFIG_NET_POLL_CONTROLLER */ | 3969 | #endif /* CONFIG_NET_POLL_CONTROLLER */ |
@@ -3799,9 +3981,10 @@ static int bcm43xx_net_stop(struct net_device *net_dev) | |||
3799 | int err; | 3981 | int err; |
3800 | 3982 | ||
3801 | ieee80211softmac_stop(net_dev); | 3983 | ieee80211softmac_stop(net_dev); |
3802 | err = bcm43xx_disable_interrupts_sync(bcm, NULL); | 3984 | err = bcm43xx_disable_interrupts_sync(bcm); |
3803 | assert(!err); | 3985 | assert(!err); |
3804 | bcm43xx_free_board(bcm); | 3986 | bcm43xx_free_board(bcm); |
3987 | flush_scheduled_work(); | ||
3805 | 3988 | ||
3806 | return 0; | 3989 | return 0; |
3807 | } | 3990 | } |
@@ -3818,10 +4001,12 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, | |||
3818 | bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; | 4001 | bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; |
3819 | 4002 | ||
3820 | bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; | 4003 | bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; |
4004 | bcm->mac_suspended = 1; | ||
3821 | bcm->pci_dev = pci_dev; | 4005 | bcm->pci_dev = pci_dev; |
3822 | bcm->net_dev = net_dev; | 4006 | bcm->net_dev = net_dev; |
3823 | bcm->bad_frames_preempt = modparam_bad_frames_preempt; | 4007 | bcm->bad_frames_preempt = modparam_bad_frames_preempt; |
3824 | spin_lock_init(&bcm->irq_lock); | 4008 | spin_lock_init(&bcm->irq_lock); |
4009 | spin_lock_init(&bcm->leds_lock); | ||
3825 | mutex_init(&bcm->mutex); | 4010 | mutex_init(&bcm->mutex); |
3826 | tasklet_init(&bcm->isr_tasklet, | 4011 | tasklet_init(&bcm->isr_tasklet, |
3827 | (void (*)(unsigned long))bcm43xx_interrupt_tasklet, | 4012 | (void (*)(unsigned long))bcm43xx_interrupt_tasklet, |
@@ -3940,7 +4125,6 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) | |||
3940 | bcm43xx_debugfs_remove_device(bcm); | 4125 | bcm43xx_debugfs_remove_device(bcm); |
3941 | unregister_netdev(net_dev); | 4126 | unregister_netdev(net_dev); |
3942 | bcm43xx_detach_board(bcm); | 4127 | bcm43xx_detach_board(bcm); |
3943 | assert(bcm->ucode == NULL); | ||
3944 | free_ieee80211softmac(net_dev); | 4128 | free_ieee80211softmac(net_dev); |
3945 | } | 4129 | } |
3946 | 4130 | ||
@@ -3950,47 +4134,31 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) | |||
3950 | static void bcm43xx_chip_reset(void *_bcm) | 4134 | static void bcm43xx_chip_reset(void *_bcm) |
3951 | { | 4135 | { |
3952 | struct bcm43xx_private *bcm = _bcm; | 4136 | struct bcm43xx_private *bcm = _bcm; |
3953 | struct net_device *net_dev = bcm->net_dev; | 4137 | struct bcm43xx_phyinfo *phy; |
3954 | struct pci_dev *pci_dev = bcm->pci_dev; | 4138 | int err = -ENODEV; |
3955 | int err; | ||
3956 | int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); | ||
3957 | |||
3958 | netif_stop_queue(bcm->net_dev); | ||
3959 | tasklet_disable(&bcm->isr_tasklet); | ||
3960 | 4139 | ||
3961 | bcm->firmware_norelease = 1; | 4140 | mutex_lock(&(bcm)->mutex); |
3962 | if (was_initialized) | 4141 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { |
3963 | bcm43xx_free_board(bcm); | 4142 | bcm43xx_periodic_tasks_delete(bcm); |
3964 | bcm->firmware_norelease = 0; | 4143 | phy = bcm43xx_current_phy(bcm); |
3965 | bcm43xx_detach_board(bcm); | 4144 | err = bcm43xx_select_wireless_core(bcm, phy->type); |
3966 | err = bcm43xx_init_private(bcm, net_dev, pci_dev); | 4145 | if (!err) |
3967 | if (err) | 4146 | bcm43xx_periodic_tasks_setup(bcm); |
3968 | goto failure; | ||
3969 | err = bcm43xx_attach_board(bcm); | ||
3970 | if (err) | ||
3971 | goto failure; | ||
3972 | if (was_initialized) { | ||
3973 | err = bcm43xx_init_board(bcm); | ||
3974 | if (err) | ||
3975 | goto failure; | ||
3976 | } | 4147 | } |
3977 | netif_wake_queue(bcm->net_dev); | 4148 | mutex_unlock(&(bcm)->mutex); |
3978 | printk(KERN_INFO PFX "Controller restarted\n"); | ||
3979 | 4149 | ||
3980 | return; | 4150 | printk(KERN_ERR PFX "Controller restart%s\n", |
3981 | failure: | 4151 | (err == 0) ? "ed" : " failed"); |
3982 | printk(KERN_ERR PFX "Controller restart failed\n"); | ||
3983 | } | 4152 | } |
3984 | 4153 | ||
3985 | /* Hard-reset the chip. | 4154 | /* Hard-reset the chip. |
3986 | * This can be called from interrupt or process context. | 4155 | * This can be called from interrupt or process context. |
3987 | * Make sure to _not_ re-enable device interrupts after this has been called. | 4156 | * bcm->irq_lock must be locked. |
3988 | */ | 4157 | */ |
3989 | void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) | 4158 | void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) |
3990 | { | 4159 | { |
3991 | bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING); | 4160 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) |
3992 | bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); | 4161 | return; |
3993 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ | ||
3994 | printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); | 4162 | printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); |
3995 | INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); | 4163 | INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); |
3996 | schedule_work(&bcm->restart_work); | 4164 | schedule_work(&bcm->restart_work); |
@@ -4002,21 +4170,16 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state) | |||
4002 | { | 4170 | { |
4003 | struct net_device *net_dev = pci_get_drvdata(pdev); | 4171 | struct net_device *net_dev = pci_get_drvdata(pdev); |
4004 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 4172 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
4005 | unsigned long flags; | 4173 | int err; |
4006 | int try_to_shutdown = 0, err; | ||
4007 | 4174 | ||
4008 | dprintk(KERN_INFO PFX "Suspending...\n"); | 4175 | dprintk(KERN_INFO PFX "Suspending...\n"); |
4009 | 4176 | ||
4010 | bcm43xx_lock_irqsafe(bcm, flags); | ||
4011 | bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); | ||
4012 | if (bcm->was_initialized) | ||
4013 | try_to_shutdown = 1; | ||
4014 | bcm43xx_unlock_irqsafe(bcm, flags); | ||
4015 | |||
4016 | netif_device_detach(net_dev); | 4177 | netif_device_detach(net_dev); |
4017 | if (try_to_shutdown) { | 4178 | bcm->was_initialized = 0; |
4179 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { | ||
4180 | bcm->was_initialized = 1; | ||
4018 | ieee80211softmac_stop(net_dev); | 4181 | ieee80211softmac_stop(net_dev); |
4019 | err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate); | 4182 | err = bcm43xx_disable_interrupts_sync(bcm); |
4020 | if (unlikely(err)) { | 4183 | if (unlikely(err)) { |
4021 | dprintk(KERN_ERR PFX "Suspend failed.\n"); | 4184 | dprintk(KERN_ERR PFX "Suspend failed.\n"); |
4022 | return -EAGAIN; | 4185 | return -EAGAIN; |
@@ -4049,17 +4212,14 @@ static int bcm43xx_resume(struct pci_dev *pdev) | |||
4049 | pci_restore_state(pdev); | 4212 | pci_restore_state(pdev); |
4050 | 4213 | ||
4051 | bcm43xx_chipset_attach(bcm); | 4214 | bcm43xx_chipset_attach(bcm); |
4052 | if (bcm->was_initialized) { | 4215 | if (bcm->was_initialized) |
4053 | bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; | ||
4054 | err = bcm43xx_init_board(bcm); | 4216 | err = bcm43xx_init_board(bcm); |
4055 | } | ||
4056 | if (err) { | 4217 | if (err) { |
4057 | printk(KERN_ERR PFX "Resume failed!\n"); | 4218 | printk(KERN_ERR PFX "Resume failed!\n"); |
4058 | return err; | 4219 | return err; |
4059 | } | 4220 | } |
4060 | |||
4061 | netif_device_attach(net_dev); | 4221 | netif_device_attach(net_dev); |
4062 | 4222 | ||
4063 | dprintk(KERN_INFO PFX "Device resumed.\n"); | 4223 | dprintk(KERN_INFO PFX "Device resumed.\n"); |
4064 | 4224 | ||
4065 | return 0; | 4225 | return 0; |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 116493671f88..f76357178e4d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h | |||
@@ -133,11 +133,17 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm); | |||
133 | 133 | ||
134 | int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core); | 134 | int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core); |
135 | 135 | ||
136 | int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm, | ||
137 | int phytype); | ||
138 | |||
136 | void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); | 139 | void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); |
137 | 140 | ||
138 | void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); | 141 | void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); |
139 | void bcm43xx_mac_enable(struct bcm43xx_private *bcm); | 142 | void bcm43xx_mac_enable(struct bcm43xx_private *bcm); |
140 | 143 | ||
144 | void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm); | ||
145 | void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm); | ||
146 | |||
141 | void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); | 147 | void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); |
142 | 148 | ||
143 | int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom); | 149 | int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom); |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index f8200deecc8a..eafd0f662686 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c | |||
@@ -81,6 +81,16 @@ static const s8 bcm43xx_tssi2dbm_g_table[] = { | |||
81 | static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); | 81 | static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); |
82 | 82 | ||
83 | 83 | ||
84 | static inline | ||
85 | void bcm43xx_voluntary_preempt(void) | ||
86 | { | ||
87 | assert(!in_atomic() && !in_irq() && | ||
88 | !in_interrupt() && !irqs_disabled()); | ||
89 | #ifndef CONFIG_PREEMPT | ||
90 | cond_resched(); | ||
91 | #endif /* CONFIG_PREEMPT */ | ||
92 | } | ||
93 | |||
84 | void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) | 94 | void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) |
85 | { | 95 | { |
86 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); | 96 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); |
@@ -133,22 +143,14 @@ void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val) | |||
133 | void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) | 143 | void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) |
134 | { | 144 | { |
135 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); | 145 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); |
136 | unsigned long flags; | ||
137 | 146 | ||
138 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ | 147 | bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ |
139 | if (phy->calibrated) | 148 | if (phy->calibrated) |
140 | return; | 149 | return; |
141 | if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) { | 150 | if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) { |
142 | /* We do not want to be preempted while calibrating | ||
143 | * the hardware. | ||
144 | */ | ||
145 | local_irq_save(flags); | ||
146 | |||
147 | bcm43xx_wireless_core_reset(bcm, 0); | 151 | bcm43xx_wireless_core_reset(bcm, 0); |
148 | bcm43xx_phy_initg(bcm); | 152 | bcm43xx_phy_initg(bcm); |
149 | bcm43xx_wireless_core_reset(bcm, 1); | 153 | bcm43xx_wireless_core_reset(bcm, 1); |
150 | |||
151 | local_irq_restore(flags); | ||
152 | } | 154 | } |
153 | phy->calibrated = 1; | 155 | phy->calibrated = 1; |
154 | } | 156 | } |
@@ -1299,7 +1301,9 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) | |||
1299 | { | 1301 | { |
1300 | int i; | 1302 | int i; |
1301 | u16 ret = 0; | 1303 | u16 ret = 0; |
1304 | unsigned long flags; | ||
1302 | 1305 | ||
1306 | local_irq_save(flags); | ||
1303 | for (i = 0; i < 10; i++){ | 1307 | for (i = 0; i < 10; i++){ |
1304 | bcm43xx_phy_write(bcm, 0x0015, 0xAFA0); | 1308 | bcm43xx_phy_write(bcm, 0x0015, 0xAFA0); |
1305 | udelay(1); | 1309 | udelay(1); |
@@ -1309,6 +1313,8 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) | |||
1309 | udelay(40); | 1313 | udelay(40); |
1310 | ret += bcm43xx_phy_read(bcm, 0x002C); | 1314 | ret += bcm43xx_phy_read(bcm, 0x002C); |
1311 | } | 1315 | } |
1316 | local_irq_restore(flags); | ||
1317 | bcm43xx_voluntary_preempt(); | ||
1312 | 1318 | ||
1313 | return ret; | 1319 | return ret; |
1314 | } | 1320 | } |
@@ -1435,6 +1441,7 @@ u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) | |||
1435 | } | 1441 | } |
1436 | ret = bcm43xx_phy_read(bcm, 0x002D); | 1442 | ret = bcm43xx_phy_read(bcm, 0x002D); |
1437 | local_irq_restore(flags); | 1443 | local_irq_restore(flags); |
1444 | bcm43xx_voluntary_preempt(); | ||
1438 | 1445 | ||
1439 | return ret; | 1446 | return ret; |
1440 | } | 1447 | } |
@@ -1760,6 +1767,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) | |||
1760 | bcm43xx_radio_write16(bcm, 0x43, i); | 1767 | bcm43xx_radio_write16(bcm, 0x43, i); |
1761 | bcm43xx_radio_write16(bcm, 0x52, radio->txctl2); | 1768 | bcm43xx_radio_write16(bcm, 0x52, radio->txctl2); |
1762 | udelay(10); | 1769 | udelay(10); |
1770 | bcm43xx_voluntary_preempt(); | ||
1763 | 1771 | ||
1764 | bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); | 1772 | bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); |
1765 | 1773 | ||
@@ -1803,6 +1811,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) | |||
1803 | radio->txctl2 | 1811 | radio->txctl2 |
1804 | | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? | 1812 | | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? |
1805 | udelay(10); | 1813 | udelay(10); |
1814 | bcm43xx_voluntary_preempt(); | ||
1806 | 1815 | ||
1807 | bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); | 1816 | bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); |
1808 | 1817 | ||
@@ -1824,6 +1833,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) | |||
1824 | bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2); | 1833 | bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2); |
1825 | udelay(2); | 1834 | udelay(2); |
1826 | bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3); | 1835 | bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3); |
1836 | bcm43xx_voluntary_preempt(); | ||
1827 | } else | 1837 | } else |
1828 | bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0); | 1838 | bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0); |
1829 | bcm43xx_phy_lo_adjust(bcm, is_initializing); | 1839 | bcm43xx_phy_lo_adjust(bcm, is_initializing); |
@@ -2188,12 +2198,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm) | |||
2188 | { | 2198 | { |
2189 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); | 2199 | struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); |
2190 | int err = -ENODEV; | 2200 | int err = -ENODEV; |
2191 | unsigned long flags; | ||
2192 | |||
2193 | /* We do not want to be preempted while calibrating | ||
2194 | * the hardware. | ||
2195 | */ | ||
2196 | local_irq_save(flags); | ||
2197 | 2201 | ||
2198 | switch (phy->type) { | 2202 | switch (phy->type) { |
2199 | case BCM43xx_PHYTYPE_A: | 2203 | case BCM43xx_PHYTYPE_A: |
@@ -2227,7 +2231,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm) | |||
2227 | err = 0; | 2231 | err = 0; |
2228 | break; | 2232 | break; |
2229 | } | 2233 | } |
2230 | local_irq_restore(flags); | ||
2231 | if (err) | 2234 | if (err) |
2232 | printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n"); | 2235 | printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n"); |
2233 | 2236 | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 574085c46152..c60c1743ea06 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c | |||
@@ -262,7 +262,7 @@ static void tx_tasklet(unsigned long d) | |||
262 | int err; | 262 | int err; |
263 | u16 txctl; | 263 | u16 txctl; |
264 | 264 | ||
265 | bcm43xx_lock_irqonly(bcm, flags); | 265 | spin_lock_irqsave(&bcm->irq_lock, flags); |
266 | 266 | ||
267 | if (queue->tx_frozen) | 267 | if (queue->tx_frozen) |
268 | goto out_unlock; | 268 | goto out_unlock; |
@@ -300,7 +300,7 @@ static void tx_tasklet(unsigned long d) | |||
300 | continue; | 300 | continue; |
301 | } | 301 | } |
302 | out_unlock: | 302 | out_unlock: |
303 | bcm43xx_unlock_irqonly(bcm, flags); | 303 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
304 | } | 304 | } |
305 | 305 | ||
306 | static void setup_txqueues(struct bcm43xx_pioqueue *queue) | 306 | static void setup_txqueues(struct bcm43xx_pioqueue *queue) |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index 6a23bdc75412..c71b998a3694 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | |||
@@ -120,12 +120,14 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev, | |||
120 | GFP_KERNEL); | 120 | GFP_KERNEL); |
121 | if (!sprom) | 121 | if (!sprom) |
122 | return -ENOMEM; | 122 | return -ENOMEM; |
123 | bcm43xx_lock_irqsafe(bcm, flags); | 123 | mutex_lock(&bcm->mutex); |
124 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
124 | err = bcm43xx_sprom_read(bcm, sprom); | 125 | err = bcm43xx_sprom_read(bcm, sprom); |
125 | if (!err) | 126 | if (!err) |
126 | err = sprom2hex(sprom, buf, PAGE_SIZE); | 127 | err = sprom2hex(sprom, buf, PAGE_SIZE); |
127 | mmiowb(); | 128 | mmiowb(); |
128 | bcm43xx_unlock_irqsafe(bcm, flags); | 129 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
130 | mutex_unlock(&bcm->mutex); | ||
129 | kfree(sprom); | 131 | kfree(sprom); |
130 | 132 | ||
131 | return err; | 133 | return err; |
@@ -150,10 +152,14 @@ static ssize_t bcm43xx_attr_sprom_store(struct device *dev, | |||
150 | err = hex2sprom(sprom, buf, count); | 152 | err = hex2sprom(sprom, buf, count); |
151 | if (err) | 153 | if (err) |
152 | goto out_kfree; | 154 | goto out_kfree; |
153 | bcm43xx_lock_irqsafe(bcm, flags); | 155 | mutex_lock(&bcm->mutex); |
156 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
157 | spin_lock(&bcm->leds_lock); | ||
154 | err = bcm43xx_sprom_write(bcm, sprom); | 158 | err = bcm43xx_sprom_write(bcm, sprom); |
155 | mmiowb(); | 159 | mmiowb(); |
156 | bcm43xx_unlock_irqsafe(bcm, flags); | 160 | spin_unlock(&bcm->leds_lock); |
161 | spin_unlock_irqrestore(&bcm->irq_lock, flags); | ||
162 | mutex_unlock(&bcm->mutex); | ||
157 | out_kfree: | 163 | out_kfree: |
158 | kfree(sprom); | 164 | kfree(sprom); |
159 | 165 | ||
@@ -170,13 +176,12 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, | |||
170 | char *buf) | 176 | char *buf) |
171 | { | 177 | { |
172 | struct bcm43xx_private *bcm = dev_to_bcm(dev); | 178 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
173 | int err; | ||
174 | ssize_t count = 0; | 179 | ssize_t count = 0; |
175 | 180 | ||
176 | if (!capable(CAP_NET_ADMIN)) | 181 | if (!capable(CAP_NET_ADMIN)) |
177 | return -EPERM; | 182 | return -EPERM; |
178 | 183 | ||
179 | bcm43xx_lock_noirq(bcm); | 184 | mutex_lock(&bcm->mutex); |
180 | 185 | ||
181 | switch (bcm43xx_current_radio(bcm)->interfmode) { | 186 | switch (bcm43xx_current_radio(bcm)->interfmode) { |
182 | case BCM43xx_RADIO_INTERFMODE_NONE: | 187 | case BCM43xx_RADIO_INTERFMODE_NONE: |
@@ -191,11 +196,10 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, | |||
191 | default: | 196 | default: |
192 | assert(0); | 197 | assert(0); |
193 | } | 198 | } |
194 | err = 0; | ||
195 | 199 | ||
196 | bcm43xx_unlock_noirq(bcm); | 200 | mutex_unlock(&bcm->mutex); |
197 | 201 | ||
198 | return err ? err : count; | 202 | return count; |
199 | 203 | ||
200 | } | 204 | } |
201 | 205 | ||
@@ -229,7 +233,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, | |||
229 | return -EINVAL; | 233 | return -EINVAL; |
230 | } | 234 | } |
231 | 235 | ||
232 | bcm43xx_lock_irqsafe(bcm, flags); | 236 | mutex_lock(&bcm->mutex); |
237 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
233 | 238 | ||
234 | err = bcm43xx_radio_set_interference_mitigation(bcm, mode); | 239 | err = bcm43xx_radio_set_interference_mitigation(bcm, mode); |
235 | if (err) { | 240 | if (err) { |
@@ -237,7 +242,8 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, | |||
237 | "supported by device\n"); | 242 | "supported by device\n"); |
238 | } | 243 | } |
239 | mmiowb(); | 244 | mmiowb(); |
240 | bcm43xx_unlock_irqsafe(bcm, flags); | 245 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
246 | mutex_unlock(&bcm->mutex); | ||
241 | 247 | ||
242 | return err ? err : count; | 248 | return err ? err : count; |
243 | } | 249 | } |
@@ -251,23 +257,21 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, | |||
251 | char *buf) | 257 | char *buf) |
252 | { | 258 | { |
253 | struct bcm43xx_private *bcm = dev_to_bcm(dev); | 259 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
254 | int err; | ||
255 | ssize_t count; | 260 | ssize_t count; |
256 | 261 | ||
257 | if (!capable(CAP_NET_ADMIN)) | 262 | if (!capable(CAP_NET_ADMIN)) |
258 | return -EPERM; | 263 | return -EPERM; |
259 | 264 | ||
260 | bcm43xx_lock_noirq(bcm); | 265 | mutex_lock(&bcm->mutex); |
261 | 266 | ||
262 | if (bcm->short_preamble) | 267 | if (bcm->short_preamble) |
263 | count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); | 268 | count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); |
264 | else | 269 | else |
265 | count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); | 270 | count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); |
266 | 271 | ||
267 | err = 0; | 272 | mutex_unlock(&bcm->mutex); |
268 | bcm43xx_unlock_noirq(bcm); | ||
269 | 273 | ||
270 | return err ? err : count; | 274 | return count; |
271 | } | 275 | } |
272 | 276 | ||
273 | static ssize_t bcm43xx_attr_preamble_store(struct device *dev, | 277 | static ssize_t bcm43xx_attr_preamble_store(struct device *dev, |
@@ -276,7 +280,6 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, | |||
276 | { | 280 | { |
277 | struct bcm43xx_private *bcm = dev_to_bcm(dev); | 281 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
278 | unsigned long flags; | 282 | unsigned long flags; |
279 | int err; | ||
280 | int value; | 283 | int value; |
281 | 284 | ||
282 | if (!capable(CAP_NET_ADMIN)) | 285 | if (!capable(CAP_NET_ADMIN)) |
@@ -285,20 +288,141 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, | |||
285 | value = get_boolean(buf, count); | 288 | value = get_boolean(buf, count); |
286 | if (value < 0) | 289 | if (value < 0) |
287 | return value; | 290 | return value; |
288 | bcm43xx_lock_irqsafe(bcm, flags); | 291 | mutex_lock(&bcm->mutex); |
292 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
289 | 293 | ||
290 | bcm->short_preamble = !!value; | 294 | bcm->short_preamble = !!value; |
291 | 295 | ||
292 | err = 0; | 296 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
293 | bcm43xx_unlock_irqsafe(bcm, flags); | 297 | mutex_unlock(&bcm->mutex); |
294 | 298 | ||
295 | return err ? err : count; | 299 | return count; |
296 | } | 300 | } |
297 | 301 | ||
298 | static DEVICE_ATTR(shortpreamble, 0644, | 302 | static DEVICE_ATTR(shortpreamble, 0644, |
299 | bcm43xx_attr_preamble_show, | 303 | bcm43xx_attr_preamble_show, |
300 | bcm43xx_attr_preamble_store); | 304 | bcm43xx_attr_preamble_store); |
301 | 305 | ||
306 | static ssize_t bcm43xx_attr_phymode_store(struct device *dev, | ||
307 | struct device_attribute *attr, | ||
308 | const char *buf, size_t count) | ||
309 | { | ||
310 | struct bcm43xx_private *bcm = dev_to_bcm(dev); | ||
311 | int phytype; | ||
312 | int err = -EINVAL; | ||
313 | |||
314 | if (count < 1) | ||
315 | goto out; | ||
316 | switch (buf[0]) { | ||
317 | case 'a': case 'A': | ||
318 | phytype = BCM43xx_PHYTYPE_A; | ||
319 | break; | ||
320 | case 'b': case 'B': | ||
321 | phytype = BCM43xx_PHYTYPE_B; | ||
322 | break; | ||
323 | case 'g': case 'G': | ||
324 | phytype = BCM43xx_PHYTYPE_G; | ||
325 | break; | ||
326 | default: | ||
327 | goto out; | ||
328 | } | ||
329 | |||
330 | bcm43xx_periodic_tasks_delete(bcm); | ||
331 | mutex_lock(&(bcm)->mutex); | ||
332 | err = bcm43xx_select_wireless_core(bcm, phytype); | ||
333 | if (!err) | ||
334 | bcm43xx_periodic_tasks_setup(bcm); | ||
335 | mutex_unlock(&(bcm)->mutex); | ||
336 | if (err == -ESRCH) | ||
337 | err = -ENODEV; | ||
338 | |||
339 | out: | ||
340 | return err ? err : count; | ||
341 | } | ||
342 | |||
343 | static ssize_t bcm43xx_attr_phymode_show(struct device *dev, | ||
344 | struct device_attribute *attr, | ||
345 | char *buf) | ||
346 | { | ||
347 | struct bcm43xx_private *bcm = dev_to_bcm(dev); | ||
348 | ssize_t count = 0; | ||
349 | |||
350 | mutex_lock(&(bcm)->mutex); | ||
351 | switch (bcm43xx_current_phy(bcm)->type) { | ||
352 | case BCM43xx_PHYTYPE_A: | ||
353 | snprintf(buf, PAGE_SIZE, "A"); | ||
354 | break; | ||
355 | case BCM43xx_PHYTYPE_B: | ||
356 | snprintf(buf, PAGE_SIZE, "B"); | ||
357 | break; | ||
358 | case BCM43xx_PHYTYPE_G: | ||
359 | snprintf(buf, PAGE_SIZE, "G"); | ||
360 | break; | ||
361 | default: | ||
362 | assert(0); | ||
363 | } | ||
364 | mutex_unlock(&(bcm)->mutex); | ||
365 | |||
366 | return count; | ||
367 | } | ||
368 | |||
369 | static DEVICE_ATTR(phymode, 0644, | ||
370 | bcm43xx_attr_phymode_show, | ||
371 | bcm43xx_attr_phymode_store); | ||
372 | |||
373 | static ssize_t bcm43xx_attr_microcode_show(struct device *dev, | ||
374 | struct device_attribute *attr, | ||
375 | char *buf) | ||
376 | { | ||
377 | unsigned long flags; | ||
378 | struct bcm43xx_private *bcm = dev_to_bcm(dev); | ||
379 | ssize_t count = 0; | ||
380 | u16 status; | ||
381 | |||
382 | if (!capable(CAP_NET_ADMIN)) | ||
383 | return -EPERM; | ||
384 | |||
385 | mutex_lock(&(bcm)->mutex); | ||
386 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
387 | status = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, | ||
388 | BCM43xx_UCODE_STATUS); | ||
389 | |||
390 | spin_unlock_irqrestore(&bcm->irq_lock, flags); | ||
391 | mutex_unlock(&(bcm)->mutex); | ||
392 | switch (status) { | ||
393 | case 0x0000: | ||
394 | count = snprintf(buf, PAGE_SIZE, "0x%.4x (invalid)\n", | ||
395 | status); | ||
396 | break; | ||
397 | case 0x0001: | ||
398 | count = snprintf(buf, PAGE_SIZE, "0x%.4x (init)\n", | ||
399 | status); | ||
400 | break; | ||
401 | case 0x0002: | ||
402 | count = snprintf(buf, PAGE_SIZE, "0x%.4x (active)\n", | ||
403 | status); | ||
404 | break; | ||
405 | case 0x0003: | ||
406 | count = snprintf(buf, PAGE_SIZE, "0x%.4x (suspended)\n", | ||
407 | status); | ||
408 | break; | ||
409 | case 0x0004: | ||
410 | count = snprintf(buf, PAGE_SIZE, "0x%.4x (asleep)\n", | ||
411 | status); | ||
412 | break; | ||
413 | default: | ||
414 | count = snprintf(buf, PAGE_SIZE, "0x%.4x (unknown)\n", | ||
415 | status); | ||
416 | break; | ||
417 | } | ||
418 | |||
419 | return count; | ||
420 | } | ||
421 | |||
422 | static DEVICE_ATTR(microcodestatus, 0444, | ||
423 | bcm43xx_attr_microcode_show, | ||
424 | NULL); | ||
425 | |||
302 | int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) | 426 | int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) |
303 | { | 427 | { |
304 | struct device *dev = &bcm->pci_dev->dev; | 428 | struct device *dev = &bcm->pci_dev->dev; |
@@ -315,9 +439,19 @@ int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) | |||
315 | err = device_create_file(dev, &dev_attr_shortpreamble); | 439 | err = device_create_file(dev, &dev_attr_shortpreamble); |
316 | if (err) | 440 | if (err) |
317 | goto err_remove_interfmode; | 441 | goto err_remove_interfmode; |
442 | err = device_create_file(dev, &dev_attr_phymode); | ||
443 | if (err) | ||
444 | goto err_remove_shortpreamble; | ||
445 | err = device_create_file(dev, &dev_attr_microcodestatus); | ||
446 | if (err) | ||
447 | goto err_remove_phymode; | ||
318 | 448 | ||
319 | out: | 449 | out: |
320 | return err; | 450 | return err; |
451 | err_remove_phymode: | ||
452 | device_remove_file(dev, &dev_attr_phymode); | ||
453 | err_remove_shortpreamble: | ||
454 | device_remove_file(dev, &dev_attr_shortpreamble); | ||
321 | err_remove_interfmode: | 455 | err_remove_interfmode: |
322 | device_remove_file(dev, &dev_attr_interference); | 456 | device_remove_file(dev, &dev_attr_interference); |
323 | err_remove_sprom: | 457 | err_remove_sprom: |
@@ -329,6 +463,8 @@ void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm) | |||
329 | { | 463 | { |
330 | struct device *dev = &bcm->pci_dev->dev; | 464 | struct device *dev = &bcm->pci_dev->dev; |
331 | 465 | ||
466 | device_remove_file(dev, &dev_attr_microcodestatus); | ||
467 | device_remove_file(dev, &dev_attr_phymode); | ||
332 | device_remove_file(dev, &dev_attr_shortpreamble); | 468 | device_remove_file(dev, &dev_attr_shortpreamble); |
333 | device_remove_file(dev, &dev_attr_interference); | 469 | device_remove_file(dev, &dev_attr_interference); |
334 | device_remove_file(dev, &dev_attr_sprom); | 470 | device_remove_file(dev, &dev_attr_sprom); |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 5c36e29efff7..888077fc14c4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #define BCM43xx_WX_VERSION 18 | 47 | #define BCM43xx_WX_VERSION 18 |
48 | 48 | ||
49 | #define MAX_WX_STRING 80 | 49 | #define MAX_WX_STRING 80 |
50 | /* FIXME: the next line is a guess as to what the maximum RSSI value might be */ | ||
51 | #define RX_RSSI_MAX 60 | ||
50 | 52 | ||
51 | 53 | ||
52 | static int bcm43xx_wx_get_name(struct net_device *net_dev, | 54 | static int bcm43xx_wx_get_name(struct net_device *net_dev, |
@@ -56,12 +58,11 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, | |||
56 | { | 58 | { |
57 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 59 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
58 | int i; | 60 | int i; |
59 | unsigned long flags; | ||
60 | struct bcm43xx_phyinfo *phy; | 61 | struct bcm43xx_phyinfo *phy; |
61 | char suffix[7] = { 0 }; | 62 | char suffix[7] = { 0 }; |
62 | int have_a = 0, have_b = 0, have_g = 0; | 63 | int have_a = 0, have_b = 0, have_g = 0; |
63 | 64 | ||
64 | bcm43xx_lock_irqsafe(bcm, flags); | 65 | mutex_lock(&bcm->mutex); |
65 | for (i = 0; i < bcm->nr_80211_available; i++) { | 66 | for (i = 0; i < bcm->nr_80211_available; i++) { |
66 | phy = &(bcm->core_80211_ext[i].phy); | 67 | phy = &(bcm->core_80211_ext[i].phy); |
67 | switch (phy->type) { | 68 | switch (phy->type) { |
@@ -77,7 +78,7 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, | |||
77 | assert(0); | 78 | assert(0); |
78 | } | 79 | } |
79 | } | 80 | } |
80 | bcm43xx_unlock_irqsafe(bcm, flags); | 81 | mutex_unlock(&bcm->mutex); |
81 | 82 | ||
82 | i = 0; | 83 | i = 0; |
83 | if (have_a) { | 84 | if (have_a) { |
@@ -111,7 +112,9 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, | |||
111 | int freq; | 112 | int freq; |
112 | int err = -EINVAL; | 113 | int err = -EINVAL; |
113 | 114 | ||
114 | bcm43xx_lock_irqsafe(bcm, flags); | 115 | mutex_lock(&bcm->mutex); |
116 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
117 | |||
115 | if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { | 118 | if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { |
116 | channel = data->freq.m; | 119 | channel = data->freq.m; |
117 | freq = bcm43xx_channel_to_freq(bcm, channel); | 120 | freq = bcm43xx_channel_to_freq(bcm, channel); |
@@ -131,7 +134,8 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, | |||
131 | err = 0; | 134 | err = 0; |
132 | } | 135 | } |
133 | out_unlock: | 136 | out_unlock: |
134 | bcm43xx_unlock_irqsafe(bcm, flags); | 137 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
138 | mutex_unlock(&bcm->mutex); | ||
135 | 139 | ||
136 | return err; | 140 | return err; |
137 | } | 141 | } |
@@ -143,11 +147,10 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, | |||
143 | { | 147 | { |
144 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 148 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
145 | struct bcm43xx_radioinfo *radio; | 149 | struct bcm43xx_radioinfo *radio; |
146 | unsigned long flags; | ||
147 | int err = -ENODEV; | 150 | int err = -ENODEV; |
148 | u16 channel; | 151 | u16 channel; |
149 | 152 | ||
150 | bcm43xx_lock_irqsafe(bcm, flags); | 153 | mutex_lock(&bcm->mutex); |
151 | radio = bcm43xx_current_radio(bcm); | 154 | radio = bcm43xx_current_radio(bcm); |
152 | channel = radio->channel; | 155 | channel = radio->channel; |
153 | if (channel == 0xFF) { | 156 | if (channel == 0xFF) { |
@@ -162,7 +165,7 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, | |||
162 | 165 | ||
163 | err = 0; | 166 | err = 0; |
164 | out_unlock: | 167 | out_unlock: |
165 | bcm43xx_unlock_irqsafe(bcm, flags); | 168 | mutex_unlock(&bcm->mutex); |
166 | 169 | ||
167 | return err; | 170 | return err; |
168 | } | 171 | } |
@@ -180,13 +183,15 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev, | |||
180 | if (mode == IW_MODE_AUTO) | 183 | if (mode == IW_MODE_AUTO) |
181 | mode = BCM43xx_INITIAL_IWMODE; | 184 | mode = BCM43xx_INITIAL_IWMODE; |
182 | 185 | ||
183 | bcm43xx_lock_irqsafe(bcm, flags); | 186 | mutex_lock(&bcm->mutex); |
187 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
184 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { | 188 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { |
185 | if (bcm->ieee->iw_mode != mode) | 189 | if (bcm->ieee->iw_mode != mode) |
186 | bcm43xx_set_iwmode(bcm, mode); | 190 | bcm43xx_set_iwmode(bcm, mode); |
187 | } else | 191 | } else |
188 | bcm->ieee->iw_mode = mode; | 192 | bcm->ieee->iw_mode = mode; |
189 | bcm43xx_unlock_irqsafe(bcm, flags); | 193 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
194 | mutex_unlock(&bcm->mutex); | ||
190 | 195 | ||
191 | return 0; | 196 | return 0; |
192 | } | 197 | } |
@@ -197,11 +202,10 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev, | |||
197 | char *extra) | 202 | char *extra) |
198 | { | 203 | { |
199 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 204 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
200 | unsigned long flags; | ||
201 | 205 | ||
202 | bcm43xx_lock_irqsafe(bcm, flags); | 206 | mutex_lock(&bcm->mutex); |
203 | data->mode = bcm->ieee->iw_mode; | 207 | data->mode = bcm->ieee->iw_mode; |
204 | bcm43xx_unlock_irqsafe(bcm, flags); | 208 | mutex_unlock(&bcm->mutex); |
205 | 209 | ||
206 | return 0; | 210 | return 0; |
207 | } | 211 | } |
@@ -214,7 +218,6 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, | |||
214 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 218 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
215 | struct iw_range *range = (struct iw_range *)extra; | 219 | struct iw_range *range = (struct iw_range *)extra; |
216 | const struct ieee80211_geo *geo; | 220 | const struct ieee80211_geo *geo; |
217 | unsigned long flags; | ||
218 | int i, j; | 221 | int i, j; |
219 | struct bcm43xx_phyinfo *phy; | 222 | struct bcm43xx_phyinfo *phy; |
220 | 223 | ||
@@ -226,15 +229,14 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, | |||
226 | range->throughput = 27 * 1000 * 1000; | 229 | range->throughput = 27 * 1000 * 1000; |
227 | 230 | ||
228 | range->max_qual.qual = 100; | 231 | range->max_qual.qual = 100; |
229 | /* TODO: Real max RSSI */ | 232 | range->max_qual.level = 146; /* set floor at -110 dBm (146 - 256) */ |
230 | range->max_qual.level = 3; | 233 | range->max_qual.noise = 146; |
231 | range->max_qual.noise = 100; | 234 | range->max_qual.updated = IW_QUAL_ALL_UPDATED; |
232 | range->max_qual.updated = 7; | ||
233 | 235 | ||
234 | range->avg_qual.qual = 70; | 236 | range->avg_qual.qual = 50; |
235 | range->avg_qual.level = 2; | 237 | range->avg_qual.level = 0; |
236 | range->avg_qual.noise = 40; | 238 | range->avg_qual.noise = 0; |
237 | range->avg_qual.updated = 7; | 239 | range->avg_qual.updated = IW_QUAL_ALL_UPDATED; |
238 | 240 | ||
239 | range->min_rts = BCM43xx_MIN_RTS_THRESHOLD; | 241 | range->min_rts = BCM43xx_MIN_RTS_THRESHOLD; |
240 | range->max_rts = BCM43xx_MAX_RTS_THRESHOLD; | 242 | range->max_rts = BCM43xx_MAX_RTS_THRESHOLD; |
@@ -254,7 +256,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, | |||
254 | IW_ENC_CAPA_CIPHER_TKIP | | 256 | IW_ENC_CAPA_CIPHER_TKIP | |
255 | IW_ENC_CAPA_CIPHER_CCMP; | 257 | IW_ENC_CAPA_CIPHER_CCMP; |
256 | 258 | ||
257 | bcm43xx_lock_irqsafe(bcm, flags); | 259 | mutex_lock(&bcm->mutex); |
258 | phy = bcm43xx_current_phy(bcm); | 260 | phy = bcm43xx_current_phy(bcm); |
259 | 261 | ||
260 | range->num_bitrates = 0; | 262 | range->num_bitrates = 0; |
@@ -301,7 +303,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, | |||
301 | } | 303 | } |
302 | range->num_frequency = j; | 304 | range->num_frequency = j; |
303 | 305 | ||
304 | bcm43xx_unlock_irqsafe(bcm, flags); | 306 | mutex_unlock(&bcm->mutex); |
305 | 307 | ||
306 | return 0; | 308 | return 0; |
307 | } | 309 | } |
@@ -314,11 +316,11 @@ static int bcm43xx_wx_set_nick(struct net_device *net_dev, | |||
314 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 316 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
315 | size_t len; | 317 | size_t len; |
316 | 318 | ||
317 | bcm43xx_lock_noirq(bcm); | 319 | mutex_lock(&bcm->mutex); |
318 | len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); | 320 | len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); |
319 | memcpy(bcm->nick, extra, len); | 321 | memcpy(bcm->nick, extra, len); |
320 | bcm->nick[len] = '\0'; | 322 | bcm->nick[len] = '\0'; |
321 | bcm43xx_unlock_noirq(bcm); | 323 | mutex_unlock(&bcm->mutex); |
322 | 324 | ||
323 | return 0; | 325 | return 0; |
324 | } | 326 | } |
@@ -331,12 +333,12 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev, | |||
331 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 333 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
332 | size_t len; | 334 | size_t len; |
333 | 335 | ||
334 | bcm43xx_lock_noirq(bcm); | 336 | mutex_lock(&bcm->mutex); |
335 | len = strlen(bcm->nick) + 1; | 337 | len = strlen(bcm->nick) + 1; |
336 | memcpy(extra, bcm->nick, len); | 338 | memcpy(extra, bcm->nick, len); |
337 | data->data.length = (__u16)len; | 339 | data->data.length = (__u16)len; |
338 | data->data.flags = 1; | 340 | data->data.flags = 1; |
339 | bcm43xx_unlock_noirq(bcm); | 341 | mutex_unlock(&bcm->mutex); |
340 | 342 | ||
341 | return 0; | 343 | return 0; |
342 | } | 344 | } |
@@ -350,7 +352,8 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, | |||
350 | unsigned long flags; | 352 | unsigned long flags; |
351 | int err = -EINVAL; | 353 | int err = -EINVAL; |
352 | 354 | ||
353 | bcm43xx_lock_irqsafe(bcm, flags); | 355 | mutex_lock(&bcm->mutex); |
356 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
354 | if (data->rts.disabled) { | 357 | if (data->rts.disabled) { |
355 | bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; | 358 | bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; |
356 | err = 0; | 359 | err = 0; |
@@ -361,7 +364,8 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, | |||
361 | err = 0; | 364 | err = 0; |
362 | } | 365 | } |
363 | } | 366 | } |
364 | bcm43xx_unlock_irqsafe(bcm, flags); | 367 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
368 | mutex_unlock(&bcm->mutex); | ||
365 | 369 | ||
366 | return err; | 370 | return err; |
367 | } | 371 | } |
@@ -372,13 +376,12 @@ static int bcm43xx_wx_get_rts(struct net_device *net_dev, | |||
372 | char *extra) | 376 | char *extra) |
373 | { | 377 | { |
374 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 378 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
375 | unsigned long flags; | ||
376 | 379 | ||
377 | bcm43xx_lock_irqsafe(bcm, flags); | 380 | mutex_lock(&bcm->mutex); |
378 | data->rts.value = bcm->rts_threshold; | 381 | data->rts.value = bcm->rts_threshold; |
379 | data->rts.fixed = 0; | 382 | data->rts.fixed = 0; |
380 | data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); | 383 | data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); |
381 | bcm43xx_unlock_irqsafe(bcm, flags); | 384 | mutex_unlock(&bcm->mutex); |
382 | 385 | ||
383 | return 0; | 386 | return 0; |
384 | } | 387 | } |
@@ -392,7 +395,8 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, | |||
392 | unsigned long flags; | 395 | unsigned long flags; |
393 | int err = -EINVAL; | 396 | int err = -EINVAL; |
394 | 397 | ||
395 | bcm43xx_lock_irqsafe(bcm, flags); | 398 | mutex_lock(&bcm->mutex); |
399 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
396 | if (data->frag.disabled) { | 400 | if (data->frag.disabled) { |
397 | bcm->ieee->fts = MAX_FRAG_THRESHOLD; | 401 | bcm->ieee->fts = MAX_FRAG_THRESHOLD; |
398 | err = 0; | 402 | err = 0; |
@@ -403,7 +407,8 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, | |||
403 | err = 0; | 407 | err = 0; |
404 | } | 408 | } |
405 | } | 409 | } |
406 | bcm43xx_unlock_irqsafe(bcm, flags); | 410 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
411 | mutex_unlock(&bcm->mutex); | ||
407 | 412 | ||
408 | return err; | 413 | return err; |
409 | } | 414 | } |
@@ -414,13 +419,12 @@ static int bcm43xx_wx_get_frag(struct net_device *net_dev, | |||
414 | char *extra) | 419 | char *extra) |
415 | { | 420 | { |
416 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 421 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
417 | unsigned long flags; | ||
418 | 422 | ||
419 | bcm43xx_lock_irqsafe(bcm, flags); | 423 | mutex_lock(&bcm->mutex); |
420 | data->frag.value = bcm->ieee->fts; | 424 | data->frag.value = bcm->ieee->fts; |
421 | data->frag.fixed = 0; | 425 | data->frag.fixed = 0; |
422 | data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); | 426 | data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); |
423 | bcm43xx_unlock_irqsafe(bcm, flags); | 427 | mutex_unlock(&bcm->mutex); |
424 | 428 | ||
425 | return 0; | 429 | return 0; |
426 | } | 430 | } |
@@ -442,7 +446,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, | |||
442 | return -EOPNOTSUPP; | 446 | return -EOPNOTSUPP; |
443 | } | 447 | } |
444 | 448 | ||
445 | bcm43xx_lock_irqsafe(bcm, flags); | 449 | mutex_lock(&bcm->mutex); |
450 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
446 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) | 451 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) |
447 | goto out_unlock; | 452 | goto out_unlock; |
448 | radio = bcm43xx_current_radio(bcm); | 453 | radio = bcm43xx_current_radio(bcm); |
@@ -466,7 +471,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, | |||
466 | err = 0; | 471 | err = 0; |
467 | 472 | ||
468 | out_unlock: | 473 | out_unlock: |
469 | bcm43xx_unlock_irqsafe(bcm, flags); | 474 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
475 | mutex_unlock(&bcm->mutex); | ||
470 | 476 | ||
471 | return err; | 477 | return err; |
472 | } | 478 | } |
@@ -478,10 +484,9 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, | |||
478 | { | 484 | { |
479 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 485 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
480 | struct bcm43xx_radioinfo *radio; | 486 | struct bcm43xx_radioinfo *radio; |
481 | unsigned long flags; | ||
482 | int err = -ENODEV; | 487 | int err = -ENODEV; |
483 | 488 | ||
484 | bcm43xx_lock_irqsafe(bcm, flags); | 489 | mutex_lock(&bcm->mutex); |
485 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) | 490 | if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) |
486 | goto out_unlock; | 491 | goto out_unlock; |
487 | radio = bcm43xx_current_radio(bcm); | 492 | radio = bcm43xx_current_radio(bcm); |
@@ -493,7 +498,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, | |||
493 | 498 | ||
494 | err = 0; | 499 | err = 0; |
495 | out_unlock: | 500 | out_unlock: |
496 | bcm43xx_unlock_irqsafe(bcm, flags); | 501 | mutex_unlock(&bcm->mutex); |
497 | 502 | ||
498 | return err; | 503 | return err; |
499 | } | 504 | } |
@@ -580,7 +585,8 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, | |||
580 | return -EINVAL; | 585 | return -EINVAL; |
581 | } | 586 | } |
582 | 587 | ||
583 | bcm43xx_lock_irqsafe(bcm, flags); | 588 | mutex_lock(&bcm->mutex); |
589 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
584 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { | 590 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { |
585 | err = bcm43xx_radio_set_interference_mitigation(bcm, mode); | 591 | err = bcm43xx_radio_set_interference_mitigation(bcm, mode); |
586 | if (err) { | 592 | if (err) { |
@@ -595,7 +601,8 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, | |||
595 | } else | 601 | } else |
596 | bcm43xx_current_radio(bcm)->interfmode = mode; | 602 | bcm43xx_current_radio(bcm)->interfmode = mode; |
597 | } | 603 | } |
598 | bcm43xx_unlock_irqsafe(bcm, flags); | 604 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
605 | mutex_unlock(&bcm->mutex); | ||
599 | 606 | ||
600 | return err; | 607 | return err; |
601 | } | 608 | } |
@@ -606,12 +613,11 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, | |||
606 | char *extra) | 613 | char *extra) |
607 | { | 614 | { |
608 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 615 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
609 | unsigned long flags; | ||
610 | int mode; | 616 | int mode; |
611 | 617 | ||
612 | bcm43xx_lock_irqsafe(bcm, flags); | 618 | mutex_lock(&bcm->mutex); |
613 | mode = bcm43xx_current_radio(bcm)->interfmode; | 619 | mode = bcm43xx_current_radio(bcm)->interfmode; |
614 | bcm43xx_unlock_irqsafe(bcm, flags); | 620 | mutex_unlock(&bcm->mutex); |
615 | 621 | ||
616 | switch (mode) { | 622 | switch (mode) { |
617 | case BCM43xx_RADIO_INTERFMODE_NONE: | 623 | case BCM43xx_RADIO_INTERFMODE_NONE: |
@@ -641,9 +647,11 @@ static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, | |||
641 | int on; | 647 | int on; |
642 | 648 | ||
643 | on = *((int *)extra); | 649 | on = *((int *)extra); |
644 | bcm43xx_lock_irqsafe(bcm, flags); | 650 | mutex_lock(&bcm->mutex); |
651 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
645 | bcm->short_preamble = !!on; | 652 | bcm->short_preamble = !!on; |
646 | bcm43xx_unlock_irqsafe(bcm, flags); | 653 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
654 | mutex_unlock(&bcm->mutex); | ||
647 | 655 | ||
648 | return 0; | 656 | return 0; |
649 | } | 657 | } |
@@ -654,12 +662,11 @@ static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, | |||
654 | char *extra) | 662 | char *extra) |
655 | { | 663 | { |
656 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 664 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
657 | unsigned long flags; | ||
658 | int on; | 665 | int on; |
659 | 666 | ||
660 | bcm43xx_lock_irqsafe(bcm, flags); | 667 | mutex_lock(&bcm->mutex); |
661 | on = bcm->short_preamble; | 668 | on = bcm->short_preamble; |
662 | bcm43xx_unlock_irqsafe(bcm, flags); | 669 | mutex_unlock(&bcm->mutex); |
663 | 670 | ||
664 | if (on) | 671 | if (on) |
665 | strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); | 672 | strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); |
@@ -681,11 +688,13 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, | |||
681 | 688 | ||
682 | on = *((int *)extra); | 689 | on = *((int *)extra); |
683 | 690 | ||
684 | bcm43xx_lock_irqsafe(bcm, flags); | 691 | mutex_lock(&bcm->mutex); |
692 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
685 | bcm->ieee->host_encrypt = !!on; | 693 | bcm->ieee->host_encrypt = !!on; |
686 | bcm->ieee->host_decrypt = !!on; | 694 | bcm->ieee->host_decrypt = !!on; |
687 | bcm->ieee->host_build_iv = !on; | 695 | bcm->ieee->host_build_iv = !on; |
688 | bcm43xx_unlock_irqsafe(bcm, flags); | 696 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
697 | mutex_unlock(&bcm->mutex); | ||
689 | 698 | ||
690 | return 0; | 699 | return 0; |
691 | } | 700 | } |
@@ -696,12 +705,11 @@ static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, | |||
696 | char *extra) | 705 | char *extra) |
697 | { | 706 | { |
698 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 707 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
699 | unsigned long flags; | ||
700 | int on; | 708 | int on; |
701 | 709 | ||
702 | bcm43xx_lock_irqsafe(bcm, flags); | 710 | mutex_lock(&bcm->mutex); |
703 | on = bcm->ieee->host_encrypt; | 711 | on = bcm->ieee->host_encrypt; |
704 | bcm43xx_unlock_irqsafe(bcm, flags); | 712 | mutex_unlock(&bcm->mutex); |
705 | 713 | ||
706 | if (on) | 714 | if (on) |
707 | strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); | 715 | strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); |
@@ -764,11 +772,13 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev, | |||
764 | if (!sprom) | 772 | if (!sprom) |
765 | goto out; | 773 | goto out; |
766 | 774 | ||
767 | bcm43xx_lock_irqsafe(bcm, flags); | 775 | mutex_lock(&bcm->mutex); |
776 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
768 | err = -ENODEV; | 777 | err = -ENODEV; |
769 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) | 778 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) |
770 | err = bcm43xx_sprom_read(bcm, sprom); | 779 | err = bcm43xx_sprom_read(bcm, sprom); |
771 | bcm43xx_unlock_irqsafe(bcm, flags); | 780 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
781 | mutex_unlock(&bcm->mutex); | ||
772 | if (!err) | 782 | if (!err) |
773 | data->data.length = sprom2hex(sprom, extra); | 783 | data->data.length = sprom2hex(sprom, extra); |
774 | kfree(sprom); | 784 | kfree(sprom); |
@@ -809,11 +819,15 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, | |||
809 | if (err) | 819 | if (err) |
810 | goto out_kfree; | 820 | goto out_kfree; |
811 | 821 | ||
812 | bcm43xx_lock_irqsafe(bcm, flags); | 822 | mutex_lock(&bcm->mutex); |
823 | spin_lock_irqsave(&bcm->irq_lock, flags); | ||
824 | spin_lock(&bcm->leds_lock); | ||
813 | err = -ENODEV; | 825 | err = -ENODEV; |
814 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) | 826 | if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) |
815 | err = bcm43xx_sprom_write(bcm, sprom); | 827 | err = bcm43xx_sprom_write(bcm, sprom); |
816 | bcm43xx_unlock_irqsafe(bcm, flags); | 828 | spin_unlock(&bcm->leds_lock); |
829 | spin_unlock_irqrestore(&bcm->irq_lock, flags); | ||
830 | mutex_unlock(&bcm->mutex); | ||
817 | out_kfree: | 831 | out_kfree: |
818 | kfree(sprom); | 832 | kfree(sprom); |
819 | out: | 833 | out: |
@@ -827,6 +841,10 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d | |||
827 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); | 841 | struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); |
828 | struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); | 842 | struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); |
829 | struct iw_statistics *wstats; | 843 | struct iw_statistics *wstats; |
844 | struct ieee80211_network *network = NULL; | ||
845 | static int tmp_level = 0; | ||
846 | static int tmp_qual = 0; | ||
847 | unsigned long flags; | ||
830 | 848 | ||
831 | wstats = &bcm->stats.wstats; | 849 | wstats = &bcm->stats.wstats; |
832 | if (!mac->associated) { | 850 | if (!mac->associated) { |
@@ -844,16 +862,28 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d | |||
844 | wstats->qual.level = 0; | 862 | wstats->qual.level = 0; |
845 | wstats->qual.noise = 0; | 863 | wstats->qual.noise = 0; |
846 | wstats->qual.updated = 7; | 864 | wstats->qual.updated = 7; |
847 | wstats->qual.updated |= IW_QUAL_NOISE_INVALID | | 865 | wstats->qual.updated |= IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; |
848 | IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; | ||
849 | return wstats; | 866 | return wstats; |
850 | } | 867 | } |
851 | /* fill in the real statistics when iface associated */ | 868 | /* fill in the real statistics when iface associated */ |
852 | wstats->qual.qual = 100; // TODO: get the real signal quality | 869 | spin_lock_irqsave(&mac->ieee->lock, flags); |
853 | wstats->qual.level = 3 - bcm->stats.link_quality; | 870 | list_for_each_entry(network, &mac->ieee->network_list, list) { |
871 | if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) { | ||
872 | if (!tmp_level) { /* get initial values */ | ||
873 | tmp_level = network->stats.signal; | ||
874 | tmp_qual = network->stats.rssi; | ||
875 | } else { /* smooth results */ | ||
876 | tmp_level = (15 * tmp_level + network->stats.signal)/16; | ||
877 | tmp_qual = (15 * tmp_qual + network->stats.rssi)/16; | ||
878 | } | ||
879 | break; | ||
880 | } | ||
881 | } | ||
882 | spin_unlock_irqrestore(&mac->ieee->lock, flags); | ||
883 | wstats->qual.level = tmp_level; | ||
884 | wstats->qual.qual = 100 * tmp_qual / RX_RSSI_MAX; | ||
854 | wstats->qual.noise = bcm->stats.noise; | 885 | wstats->qual.noise = bcm->stats.noise; |
855 | wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | | 886 | wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; |
856 | IW_QUAL_NOISE_UPDATED; | ||
857 | wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable; | 887 | wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable; |
858 | wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded; | 888 | wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded; |
859 | wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa; | 889 | wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa; |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c index 6dbd855b3647..c0efbfe605a5 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | |||
@@ -492,16 +492,15 @@ int bcm43xx_rx(struct bcm43xx_private *bcm, | |||
492 | 492 | ||
493 | memset(&stats, 0, sizeof(stats)); | 493 | memset(&stats, 0, sizeof(stats)); |
494 | stats.mac_time = le16_to_cpu(rxhdr->mactime); | 494 | stats.mac_time = le16_to_cpu(rxhdr->mactime); |
495 | stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, | 495 | stats.rssi = rxhdr->rssi; |
496 | stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, | ||
496 | !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), | 497 | !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), |
497 | !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); | 498 | !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); |
498 | stats.signal = rxhdr->signal_quality; //FIXME | ||
499 | //TODO stats.noise = | 499 | //TODO stats.noise = |
500 | if (is_ofdm) | 500 | if (is_ofdm) |
501 | stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp); | 501 | stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp); |
502 | else | 502 | else |
503 | stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp); | 503 | stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp); |
504 | //printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate); | ||
505 | stats.received_channel = radio->channel; | 504 | stats.received_channel = radio->channel; |
506 | //TODO stats.control = | 505 | //TODO stats.control = |
507 | stats.mask = IEEE80211_STATMASK_SIGNAL | | 506 | stats.mask = IEEE80211_STATMASK_SIGNAL | |
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h index 5e63765219fe..e663518bd570 100644 --- a/drivers/net/wireless/hostap/hostap.h +++ b/drivers/net/wireless/hostap/hostap.h | |||
@@ -86,7 +86,7 @@ void hostap_info_process(local_info_t *local, struct sk_buff *skb); | |||
86 | /* hostap_ioctl.c */ | 86 | /* hostap_ioctl.c */ |
87 | 87 | ||
88 | extern const struct iw_handler_def hostap_iw_handler_def; | 88 | extern const struct iw_handler_def hostap_iw_handler_def; |
89 | extern struct ethtool_ops prism2_ethtool_ops; | 89 | extern const struct ethtool_ops prism2_ethtool_ops; |
90 | 90 | ||
91 | int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); | 91 | int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); |
92 | 92 | ||
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 52e6df5c1a92..686d895116de 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -847,6 +847,7 @@ static struct pcmcia_device_id hostap_cs_ids[] = { | |||
847 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), | 847 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), |
848 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), | 848 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), |
849 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010), | 849 | PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010), |
850 | PCMCIA_DEVICE_MANF_CARD(0x0126, 0x0002), | ||
850 | PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "INTERSIL", | 851 | PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "INTERSIL", |
851 | 0x74c5e40d), | 852 | 0x74c5e40d), |
852 | PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "Intersil", | 853 | PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "Intersil", |
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 8399de581893..7a4978516eac 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
@@ -3908,7 +3908,7 @@ static void prism2_get_drvinfo(struct net_device *dev, | |||
3908 | local->sta_fw_ver & 0xff); | 3908 | local->sta_fw_ver & 0xff); |
3909 | } | 3909 | } |
3910 | 3910 | ||
3911 | struct ethtool_ops prism2_ethtool_ops = { | 3911 | const struct ethtool_ops prism2_ethtool_ops = { |
3912 | .get_drvinfo = prism2_get_drvinfo | 3912 | .get_drvinfo = prism2_get_drvinfo |
3913 | }; | 3913 | }; |
3914 | 3914 | ||
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index e955db435b30..b4d81a04c895 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c | |||
@@ -5911,7 +5911,7 @@ static u32 ipw2100_ethtool_get_link(struct net_device *dev) | |||
5911 | return (priv->status & STATUS_ASSOCIATED) ? 1 : 0; | 5911 | return (priv->status & STATUS_ASSOCIATED) ? 1 : 0; |
5912 | } | 5912 | } |
5913 | 5913 | ||
5914 | static struct ethtool_ops ipw2100_ethtool_ops = { | 5914 | static const struct ethtool_ops ipw2100_ethtool_ops = { |
5915 | .get_link = ipw2100_ethtool_get_link, | 5915 | .get_link = ipw2100_ethtool_get_link, |
5916 | .get_drvinfo = ipw_ethtool_get_drvinfo, | 5916 | .get_drvinfo = ipw_ethtool_get_drvinfo, |
5917 | }; | 5917 | }; |
@@ -6254,13 +6254,14 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, | |||
6254 | * member to call a function that then just turns and calls ipw2100_up. | 6254 | * member to call a function that then just turns and calls ipw2100_up. |
6255 | * net_dev->init is called after name allocation but before the | 6255 | * net_dev->init is called after name allocation but before the |
6256 | * notifier chain is called */ | 6256 | * notifier chain is called */ |
6257 | mutex_lock(&priv->action_mutex); | ||
6258 | err = register_netdev(dev); | 6257 | err = register_netdev(dev); |
6259 | if (err) { | 6258 | if (err) { |
6260 | printk(KERN_WARNING DRV_NAME | 6259 | printk(KERN_WARNING DRV_NAME |
6261 | "Error calling register_netdev.\n"); | 6260 | "Error calling register_netdev.\n"); |
6262 | goto fail_unlock; | 6261 | goto fail; |
6263 | } | 6262 | } |
6263 | |||
6264 | mutex_lock(&priv->action_mutex); | ||
6264 | registered = 1; | 6265 | registered = 1; |
6265 | 6266 | ||
6266 | IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev)); | 6267 | IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev)); |
@@ -6531,7 +6532,7 @@ static int __init ipw2100_init(void) | |||
6531 | printk(KERN_INFO DRV_NAME ": %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); | 6532 | printk(KERN_INFO DRV_NAME ": %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); |
6532 | printk(KERN_INFO DRV_NAME ": %s\n", DRV_COPYRIGHT); | 6533 | printk(KERN_INFO DRV_NAME ": %s\n", DRV_COPYRIGHT); |
6533 | 6534 | ||
6534 | ret = pci_module_init(&ipw2100_pci_driver); | 6535 | ret = pci_register_driver(&ipw2100_pci_driver); |
6535 | 6536 | ||
6536 | #ifdef CONFIG_IPW2100_DEBUG | 6537 | #ifdef CONFIG_IPW2100_DEBUG |
6537 | ipw2100_debug_level = debug; | 6538 | ipw2100_debug_level = debug; |
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index b3300ffe4eec..7358664e0908 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
@@ -70,7 +70,7 @@ | |||
70 | #define VQ | 70 | #define VQ |
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | #define IPW2200_VERSION "1.1.2" VK VD VM VP VR VQ | 73 | #define IPW2200_VERSION "1.1.4" VK VD VM VP VR VQ |
74 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" | 74 | #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" |
75 | #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" | 75 | #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" |
76 | #define DRV_VERSION IPW2200_VERSION | 76 | #define DRV_VERSION IPW2200_VERSION |
@@ -83,9 +83,7 @@ MODULE_AUTHOR(DRV_COPYRIGHT); | |||
83 | MODULE_LICENSE("GPL"); | 83 | MODULE_LICENSE("GPL"); |
84 | 84 | ||
85 | static int cmdlog = 0; | 85 | static int cmdlog = 0; |
86 | #ifdef CONFIG_IPW2200_DEBUG | ||
87 | static int debug = 0; | 86 | static int debug = 0; |
88 | #endif | ||
89 | static int channel = 0; | 87 | static int channel = 0; |
90 | static int mode = 0; | 88 | static int mode = 0; |
91 | 89 | ||
@@ -567,7 +565,6 @@ static inline void ipw_disable_interrupts(struct ipw_priv *priv) | |||
567 | spin_unlock_irqrestore(&priv->irq_lock, flags); | 565 | spin_unlock_irqrestore(&priv->irq_lock, flags); |
568 | } | 566 | } |
569 | 567 | ||
570 | #ifdef CONFIG_IPW2200_DEBUG | ||
571 | static char *ipw_error_desc(u32 val) | 568 | static char *ipw_error_desc(u32 val) |
572 | { | 569 | { |
573 | switch (val) { | 570 | switch (val) { |
@@ -634,7 +631,6 @@ static void ipw_dump_error_log(struct ipw_priv *priv, | |||
634 | error->log[i].time, | 631 | error->log[i].time, |
635 | error->log[i].data, error->log[i].event); | 632 | error->log[i].data, error->log[i].event); |
636 | } | 633 | } |
637 | #endif | ||
638 | 634 | ||
639 | static inline int ipw_is_init(struct ipw_priv *priv) | 635 | static inline int ipw_is_init(struct ipw_priv *priv) |
640 | { | 636 | { |
@@ -1435,9 +1431,7 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, | |||
1435 | const char *buf, size_t count) | 1431 | const char *buf, size_t count) |
1436 | { | 1432 | { |
1437 | struct ipw_priv *priv = dev_get_drvdata(d); | 1433 | struct ipw_priv *priv = dev_get_drvdata(d); |
1438 | #ifdef CONFIG_IPW2200_DEBUG | ||
1439 | struct net_device *dev = priv->net_dev; | 1434 | struct net_device *dev = priv->net_dev; |
1440 | #endif | ||
1441 | char buffer[] = "00000000"; | 1435 | char buffer[] = "00000000"; |
1442 | unsigned long len = | 1436 | unsigned long len = |
1443 | (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1; | 1437 | (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1; |
@@ -1958,14 +1952,12 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
1958 | IPW_WARNING("Firmware error detected. Restarting.\n"); | 1952 | IPW_WARNING("Firmware error detected. Restarting.\n"); |
1959 | if (priv->error) { | 1953 | if (priv->error) { |
1960 | IPW_DEBUG_FW("Sysfs 'error' log already exists.\n"); | 1954 | IPW_DEBUG_FW("Sysfs 'error' log already exists.\n"); |
1961 | #ifdef CONFIG_IPW2200_DEBUG | ||
1962 | if (ipw_debug_level & IPW_DL_FW_ERRORS) { | 1955 | if (ipw_debug_level & IPW_DL_FW_ERRORS) { |
1963 | struct ipw_fw_error *error = | 1956 | struct ipw_fw_error *error = |
1964 | ipw_alloc_error_log(priv); | 1957 | ipw_alloc_error_log(priv); |
1965 | ipw_dump_error_log(priv, error); | 1958 | ipw_dump_error_log(priv, error); |
1966 | kfree(error); | 1959 | kfree(error); |
1967 | } | 1960 | } |
1968 | #endif | ||
1969 | } else { | 1961 | } else { |
1970 | priv->error = ipw_alloc_error_log(priv); | 1962 | priv->error = ipw_alloc_error_log(priv); |
1971 | if (priv->error) | 1963 | if (priv->error) |
@@ -1973,10 +1965,8 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
1973 | else | 1965 | else |
1974 | IPW_DEBUG_FW("Error allocating sysfs 'error' " | 1966 | IPW_DEBUG_FW("Error allocating sysfs 'error' " |
1975 | "log.\n"); | 1967 | "log.\n"); |
1976 | #ifdef CONFIG_IPW2200_DEBUG | ||
1977 | if (ipw_debug_level & IPW_DL_FW_ERRORS) | 1968 | if (ipw_debug_level & IPW_DL_FW_ERRORS) |
1978 | ipw_dump_error_log(priv, priv->error); | 1969 | ipw_dump_error_log(priv, priv->error); |
1979 | #endif | ||
1980 | } | 1970 | } |
1981 | 1971 | ||
1982 | /* XXX: If hardware encryption is for WPA/WPA2, | 1972 | /* XXX: If hardware encryption is for WPA/WPA2, |
@@ -2287,7 +2277,7 @@ static int ipw_send_scan_abort(struct ipw_priv *priv) | |||
2287 | static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens) | 2277 | static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens) |
2288 | { | 2278 | { |
2289 | struct ipw_sensitivity_calib calib = { | 2279 | struct ipw_sensitivity_calib calib = { |
2290 | .beacon_rssi_raw = sens, | 2280 | .beacon_rssi_raw = cpu_to_le16(sens), |
2291 | }; | 2281 | }; |
2292 | 2282 | ||
2293 | return ipw_send_cmd_pdu(priv, IPW_CMD_SENSITIVITY_CALIB, sizeof(calib), | 2283 | return ipw_send_cmd_pdu(priv, IPW_CMD_SENSITIVITY_CALIB, sizeof(calib), |
@@ -2353,6 +2343,7 @@ static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) | |||
2353 | return -1; | 2343 | return -1; |
2354 | } | 2344 | } |
2355 | 2345 | ||
2346 | phy_off = cpu_to_le32(phy_off); | ||
2356 | return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(phy_off), | 2347 | return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(phy_off), |
2357 | &phy_off); | 2348 | &phy_off); |
2358 | } | 2349 | } |
@@ -2414,7 +2405,7 @@ static int ipw_set_tx_power(struct ipw_priv *priv) | |||
2414 | static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts) | 2405 | static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts) |
2415 | { | 2406 | { |
2416 | struct ipw_rts_threshold rts_threshold = { | 2407 | struct ipw_rts_threshold rts_threshold = { |
2417 | .rts_threshold = rts, | 2408 | .rts_threshold = cpu_to_le16(rts), |
2418 | }; | 2409 | }; |
2419 | 2410 | ||
2420 | if (!priv) { | 2411 | if (!priv) { |
@@ -2429,7 +2420,7 @@ static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts) | |||
2429 | static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) | 2420 | static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) |
2430 | { | 2421 | { |
2431 | struct ipw_frag_threshold frag_threshold = { | 2422 | struct ipw_frag_threshold frag_threshold = { |
2432 | .frag_threshold = frag, | 2423 | .frag_threshold = cpu_to_le16(frag), |
2433 | }; | 2424 | }; |
2434 | 2425 | ||
2435 | if (!priv) { | 2426 | if (!priv) { |
@@ -2464,6 +2455,7 @@ static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) | |||
2464 | break; | 2455 | break; |
2465 | } | 2456 | } |
2466 | 2457 | ||
2458 | param = cpu_to_le32(mode); | ||
2467 | return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param), | 2459 | return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param), |
2468 | ¶m); | 2460 | ¶m); |
2469 | } | 2461 | } |
@@ -2667,7 +2659,7 @@ static void ipw_fw_dma_abort(struct ipw_priv *priv) | |||
2667 | 2659 | ||
2668 | IPW_DEBUG_FW(">> :\n"); | 2660 | IPW_DEBUG_FW(">> :\n"); |
2669 | 2661 | ||
2670 | //set the Stop and Abort bit | 2662 | /* set the Stop and Abort bit */ |
2671 | control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT; | 2663 | control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT; |
2672 | ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); | 2664 | ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); |
2673 | priv->sram_desc.last_cb_index = 0; | 2665 | priv->sram_desc.last_cb_index = 0; |
@@ -3002,8 +2994,6 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) | |||
3002 | if (rc < 0) | 2994 | if (rc < 0) |
3003 | return rc; | 2995 | return rc; |
3004 | 2996 | ||
3005 | // spin_lock_irqsave(&priv->lock, flags); | ||
3006 | |||
3007 | for (addr = IPW_SHARED_LOWER_BOUND; | 2997 | for (addr = IPW_SHARED_LOWER_BOUND; |
3008 | addr < IPW_REGISTER_DOMAIN1_END; addr += 4) { | 2998 | addr < IPW_REGISTER_DOMAIN1_END; addr += 4) { |
3009 | ipw_write32(priv, addr, 0); | 2999 | ipw_write32(priv, addr, 0); |
@@ -3097,8 +3087,6 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) | |||
3097 | firmware have problem getting alive resp. */ | 3087 | firmware have problem getting alive resp. */ |
3098 | ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0); | 3088 | ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0); |
3099 | 3089 | ||
3100 | // spin_unlock_irqrestore(&priv->lock, flags); | ||
3101 | |||
3102 | return rc; | 3090 | return rc; |
3103 | } | 3091 | } |
3104 | 3092 | ||
@@ -3919,7 +3907,6 @@ static const struct ipw_status_code ipw_status_codes[] = { | |||
3919 | {0x2E, "Cipher suite is rejected per security policy"}, | 3907 | {0x2E, "Cipher suite is rejected per security policy"}, |
3920 | }; | 3908 | }; |
3921 | 3909 | ||
3922 | #ifdef CONFIG_IPW2200_DEBUG | ||
3923 | static const char *ipw_get_status_code(u16 status) | 3910 | static const char *ipw_get_status_code(u16 status) |
3924 | { | 3911 | { |
3925 | int i; | 3912 | int i; |
@@ -3928,7 +3915,6 @@ static const char *ipw_get_status_code(u16 status) | |||
3928 | return ipw_status_codes[i].reason; | 3915 | return ipw_status_codes[i].reason; |
3929 | return "Unknown status value."; | 3916 | return "Unknown status value."; |
3930 | } | 3917 | } |
3931 | #endif | ||
3932 | 3918 | ||
3933 | static void inline average_init(struct average *avg) | 3919 | static void inline average_init(struct average *avg) |
3934 | { | 3920 | { |
@@ -4398,7 +4384,6 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4398 | if (priv-> | 4384 | if (priv-> |
4399 | status & (STATUS_ASSOCIATED | | 4385 | status & (STATUS_ASSOCIATED | |
4400 | STATUS_AUTH)) { | 4386 | STATUS_AUTH)) { |
4401 | #ifdef CONFIG_IPW2200_DEBUG | ||
4402 | struct notif_authenticate *auth | 4387 | struct notif_authenticate *auth |
4403 | = ¬if->u.auth; | 4388 | = ¬if->u.auth; |
4404 | IPW_DEBUG(IPW_DL_NOTIF | | 4389 | IPW_DEBUG(IPW_DL_NOTIF | |
@@ -4416,7 +4401,6 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4416 | ipw_get_status_code | 4401 | ipw_get_status_code |
4417 | (ntohs | 4402 | (ntohs |
4418 | (auth->status))); | 4403 | (auth->status))); |
4419 | #endif | ||
4420 | 4404 | ||
4421 | priv->status &= | 4405 | priv->status &= |
4422 | ~(STATUS_ASSOCIATING | | 4406 | ~(STATUS_ASSOCIATING | |
@@ -5059,7 +5043,6 @@ static void ipw_rx_queue_replenish(void *data) | |||
5059 | } | 5043 | } |
5060 | list_del(element); | 5044 | list_del(element); |
5061 | 5045 | ||
5062 | rxb->rxb = (struct ipw_rx_buffer *)rxb->skb->data; | ||
5063 | rxb->dma_addr = | 5046 | rxb->dma_addr = |
5064 | pci_map_single(priv->pci_dev, rxb->skb->data, | 5047 | pci_map_single(priv->pci_dev, rxb->skb->data, |
5065 | IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); | 5048 | IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); |
@@ -5838,8 +5821,8 @@ static void ipw_send_tgi_tx_key(struct ipw_priv *priv, int type, int index) | |||
5838 | key.station_index = 0; /* always 0 for BSS */ | 5821 | key.station_index = 0; /* always 0 for BSS */ |
5839 | key.flags = 0; | 5822 | key.flags = 0; |
5840 | /* 0 for new key; previous value of counter (after fatal error) */ | 5823 | /* 0 for new key; previous value of counter (after fatal error) */ |
5841 | key.tx_counter[0] = 0; | 5824 | key.tx_counter[0] = cpu_to_le32(0); |
5842 | key.tx_counter[1] = 0; | 5825 | key.tx_counter[1] = cpu_to_le32(0); |
5843 | 5826 | ||
5844 | ipw_send_cmd_pdu(priv, IPW_CMD_TGI_TX_KEY, sizeof(key), &key); | 5827 | ipw_send_cmd_pdu(priv, IPW_CMD_TGI_TX_KEY, sizeof(key), &key); |
5845 | } | 5828 | } |
@@ -5973,7 +5956,6 @@ static void ipw_bg_adhoc_check(void *data) | |||
5973 | mutex_unlock(&priv->mutex); | 5956 | mutex_unlock(&priv->mutex); |
5974 | } | 5957 | } |
5975 | 5958 | ||
5976 | #ifdef CONFIG_IPW2200_DEBUG | ||
5977 | static void ipw_debug_config(struct ipw_priv *priv) | 5959 | static void ipw_debug_config(struct ipw_priv *priv) |
5978 | { | 5960 | { |
5979 | IPW_DEBUG_INFO("Scan completed, no valid APs matched " | 5961 | IPW_DEBUG_INFO("Scan completed, no valid APs matched " |
@@ -5998,9 +5980,6 @@ static void ipw_debug_config(struct ipw_priv *priv) | |||
5998 | IPW_DEBUG_INFO("PRIVACY off\n"); | 5980 | IPW_DEBUG_INFO("PRIVACY off\n"); |
5999 | IPW_DEBUG_INFO("RATE MASK: 0x%08X\n", priv->rates_mask); | 5981 | IPW_DEBUG_INFO("RATE MASK: 0x%08X\n", priv->rates_mask); |
6000 | } | 5982 | } |
6001 | #else | ||
6002 | #define ipw_debug_config(x) do {} while (0) | ||
6003 | #endif | ||
6004 | 5983 | ||
6005 | static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) | 5984 | static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) |
6006 | { | 5985 | { |
@@ -6188,7 +6167,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, | |||
6188 | } | 6167 | } |
6189 | } | 6168 | } |
6190 | 6169 | ||
6191 | static int ipw_request_scan(struct ipw_priv *priv) | 6170 | static int ipw_request_scan_helper(struct ipw_priv *priv, int type) |
6192 | { | 6171 | { |
6193 | struct ipw_scan_request_ext scan; | 6172 | struct ipw_scan_request_ext scan; |
6194 | int err = 0, scan_type; | 6173 | int err = 0, scan_type; |
@@ -6219,19 +6198,29 @@ static int ipw_request_scan(struct ipw_priv *priv) | |||
6219 | } | 6198 | } |
6220 | 6199 | ||
6221 | memset(&scan, 0, sizeof(scan)); | 6200 | memset(&scan, 0, sizeof(scan)); |
6201 | scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); | ||
6222 | 6202 | ||
6223 | if (priv->config & CFG_SPEED_SCAN) | 6203 | if (type == IW_SCAN_TYPE_PASSIVE) { |
6204 | IPW_DEBUG_WX("use passive scanning\n"); | ||
6205 | scan_type = IPW_SCAN_PASSIVE_FULL_DWELL_SCAN; | ||
6206 | scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = | ||
6207 | cpu_to_le16(120); | ||
6208 | ipw_add_scan_channels(priv, &scan, scan_type); | ||
6209 | goto send_request; | ||
6210 | } | ||
6211 | |||
6212 | /* Use active scan by default. */ | ||
6213 | if (priv->config & CFG_SPEED_SCAN) | ||
6224 | scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = | 6214 | scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = |
6225 | cpu_to_le16(30); | 6215 | cpu_to_le16(30); |
6226 | else | 6216 | else |
6227 | scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = | 6217 | scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = |
6228 | cpu_to_le16(20); | 6218 | cpu_to_le16(20); |
6229 | 6219 | ||
6230 | scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = | 6220 | scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = |
6231 | cpu_to_le16(20); | 6221 | cpu_to_le16(20); |
6232 | scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120); | ||
6233 | 6222 | ||
6234 | scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); | 6223 | scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120); |
6235 | 6224 | ||
6236 | #ifdef CONFIG_IPW2200_MONITOR | 6225 | #ifdef CONFIG_IPW2200_MONITOR |
6237 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { | 6226 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { |
@@ -6268,7 +6257,7 @@ static int ipw_request_scan(struct ipw_priv *priv) | |||
6268 | * | 6257 | * |
6269 | * TODO: Move SPEED SCAN support to all modes and bands */ | 6258 | * TODO: Move SPEED SCAN support to all modes and bands */ |
6270 | scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = | 6259 | scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = |
6271 | cpu_to_le16(2000); | 6260 | cpu_to_le16(2000); |
6272 | } else { | 6261 | } else { |
6273 | #endif /* CONFIG_IPW2200_MONITOR */ | 6262 | #endif /* CONFIG_IPW2200_MONITOR */ |
6274 | /* If we are roaming, then make this a directed scan for the | 6263 | /* If we are roaming, then make this a directed scan for the |
@@ -6294,6 +6283,7 @@ static int ipw_request_scan(struct ipw_priv *priv) | |||
6294 | } | 6283 | } |
6295 | #endif | 6284 | #endif |
6296 | 6285 | ||
6286 | send_request: | ||
6297 | err = ipw_send_scan_request_ext(priv, &scan); | 6287 | err = ipw_send_scan_request_ext(priv, &scan); |
6298 | if (err) { | 6288 | if (err) { |
6299 | IPW_DEBUG_HC("Sending scan command failed: %08X\n", err); | 6289 | IPW_DEBUG_HC("Sending scan command failed: %08X\n", err); |
@@ -6304,11 +6294,19 @@ static int ipw_request_scan(struct ipw_priv *priv) | |||
6304 | priv->status &= ~STATUS_SCAN_PENDING; | 6294 | priv->status &= ~STATUS_SCAN_PENDING; |
6305 | queue_delayed_work(priv->workqueue, &priv->scan_check, | 6295 | queue_delayed_work(priv->workqueue, &priv->scan_check, |
6306 | IPW_SCAN_CHECK_WATCHDOG); | 6296 | IPW_SCAN_CHECK_WATCHDOG); |
6307 | done: | 6297 | done: |
6308 | mutex_unlock(&priv->mutex); | 6298 | mutex_unlock(&priv->mutex); |
6309 | return err; | 6299 | return err; |
6310 | } | 6300 | } |
6311 | 6301 | ||
6302 | static int ipw_request_passive_scan(struct ipw_priv *priv) { | ||
6303 | return ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); | ||
6304 | } | ||
6305 | |||
6306 | static int ipw_request_scan(struct ipw_priv *priv) { | ||
6307 | return ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); | ||
6308 | } | ||
6309 | |||
6312 | static void ipw_bg_abort_scan(void *data) | 6310 | static void ipw_bg_abort_scan(void *data) |
6313 | { | 6311 | { |
6314 | struct ipw_priv *priv = data; | 6312 | struct ipw_priv *priv = data; |
@@ -6387,13 +6385,6 @@ static int ipw_wx_set_genie(struct net_device *dev, | |||
6387 | (wrqu->data.length && extra == NULL)) | 6385 | (wrqu->data.length && extra == NULL)) |
6388 | return -EINVAL; | 6386 | return -EINVAL; |
6389 | 6387 | ||
6390 | //mutex_lock(&priv->mutex); | ||
6391 | |||
6392 | //if (!ieee->wpa_enabled) { | ||
6393 | // err = -EOPNOTSUPP; | ||
6394 | // goto out; | ||
6395 | //} | ||
6396 | |||
6397 | if (wrqu->data.length) { | 6388 | if (wrqu->data.length) { |
6398 | buf = kmalloc(wrqu->data.length, GFP_KERNEL); | 6389 | buf = kmalloc(wrqu->data.length, GFP_KERNEL); |
6399 | if (buf == NULL) { | 6390 | if (buf == NULL) { |
@@ -6413,7 +6404,6 @@ static int ipw_wx_set_genie(struct net_device *dev, | |||
6413 | 6404 | ||
6414 | ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); | 6405 | ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); |
6415 | out: | 6406 | out: |
6416 | //mutex_unlock(&priv->mutex); | ||
6417 | return err; | 6407 | return err; |
6418 | } | 6408 | } |
6419 | 6409 | ||
@@ -6426,13 +6416,6 @@ static int ipw_wx_get_genie(struct net_device *dev, | |||
6426 | struct ieee80211_device *ieee = priv->ieee; | 6416 | struct ieee80211_device *ieee = priv->ieee; |
6427 | int err = 0; | 6417 | int err = 0; |
6428 | 6418 | ||
6429 | //mutex_lock(&priv->mutex); | ||
6430 | |||
6431 | //if (!ieee->wpa_enabled) { | ||
6432 | // err = -EOPNOTSUPP; | ||
6433 | // goto out; | ||
6434 | //} | ||
6435 | |||
6436 | if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) { | 6419 | if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) { |
6437 | wrqu->data.length = 0; | 6420 | wrqu->data.length = 0; |
6438 | goto out; | 6421 | goto out; |
@@ -6447,7 +6430,6 @@ static int ipw_wx_get_genie(struct net_device *dev, | |||
6447 | memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); | 6430 | memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); |
6448 | 6431 | ||
6449 | out: | 6432 | out: |
6450 | //mutex_unlock(&priv->mutex); | ||
6451 | return err; | 6433 | return err; |
6452 | } | 6434 | } |
6453 | 6435 | ||
@@ -6558,7 +6540,6 @@ static int ipw_wx_set_auth(struct net_device *dev, | |||
6558 | ieee->ieee802_1x = param->value; | 6540 | ieee->ieee802_1x = param->value; |
6559 | break; | 6541 | break; |
6560 | 6542 | ||
6561 | //case IW_AUTH_ROAMING_CONTROL: | ||
6562 | case IW_AUTH_PRIVACY_INVOKED: | 6543 | case IW_AUTH_PRIVACY_INVOKED: |
6563 | ieee->privacy_invoked = param->value; | 6544 | ieee->privacy_invoked = param->value; |
6564 | break; | 6545 | break; |
@@ -6680,7 +6661,7 @@ static int ipw_wx_set_mlme(struct net_device *dev, | |||
6680 | 6661 | ||
6681 | switch (mlme->cmd) { | 6662 | switch (mlme->cmd) { |
6682 | case IW_MLME_DEAUTH: | 6663 | case IW_MLME_DEAUTH: |
6683 | // silently ignore | 6664 | /* silently ignore */ |
6684 | break; | 6665 | break; |
6685 | 6666 | ||
6686 | case IW_MLME_DISASSOC: | 6667 | case IW_MLME_DISASSOC: |
@@ -6811,7 +6792,7 @@ static int ipw_qos_activate(struct ipw_priv *priv, | |||
6811 | burst_duration = ipw_qos_get_burst_duration(priv); | 6792 | burst_duration = ipw_qos_get_burst_duration(priv); |
6812 | for (i = 0; i < QOS_QUEUE_NUM; i++) | 6793 | for (i = 0; i < QOS_QUEUE_NUM; i++) |
6813 | qos_parameters[QOS_PARAM_SET_ACTIVE].tx_op_limit[i] = | 6794 | qos_parameters[QOS_PARAM_SET_ACTIVE].tx_op_limit[i] = |
6814 | (u16) burst_duration; | 6795 | (u16)burst_duration; |
6815 | } else if (priv->ieee->iw_mode == IW_MODE_ADHOC) { | 6796 | } else if (priv->ieee->iw_mode == IW_MODE_ADHOC) { |
6816 | if (type == IEEE_B) { | 6797 | if (type == IEEE_B) { |
6817 | IPW_DEBUG_QOS("QoS activate IBSS nework mode %d\n", | 6798 | IPW_DEBUG_QOS("QoS activate IBSS nework mode %d\n", |
@@ -6843,11 +6824,20 @@ static int ipw_qos_activate(struct ipw_priv *priv, | |||
6843 | burst_duration = ipw_qos_get_burst_duration(priv); | 6824 | burst_duration = ipw_qos_get_burst_duration(priv); |
6844 | for (i = 0; i < QOS_QUEUE_NUM; i++) | 6825 | for (i = 0; i < QOS_QUEUE_NUM; i++) |
6845 | qos_parameters[QOS_PARAM_SET_ACTIVE]. | 6826 | qos_parameters[QOS_PARAM_SET_ACTIVE]. |
6846 | tx_op_limit[i] = (u16) burst_duration; | 6827 | tx_op_limit[i] = (u16)burst_duration; |
6847 | } | 6828 | } |
6848 | } | 6829 | } |
6849 | 6830 | ||
6850 | IPW_DEBUG_QOS("QoS sending IPW_CMD_QOS_PARAMETERS\n"); | 6831 | IPW_DEBUG_QOS("QoS sending IPW_CMD_QOS_PARAMETERS\n"); |
6832 | for (i = 0; i < 3; i++) { | ||
6833 | int j; | ||
6834 | for (j = 0; j < QOS_QUEUE_NUM; j++) { | ||
6835 | qos_parameters[i].cw_min[j] = cpu_to_le16(qos_parameters[i].cw_min[j]); | ||
6836 | qos_parameters[i].cw_max[j] = cpu_to_le16(qos_parameters[i].cw_max[j]); | ||
6837 | qos_parameters[i].tx_op_limit[j] = cpu_to_le16(qos_parameters[i].tx_op_limit[j]); | ||
6838 | } | ||
6839 | } | ||
6840 | |||
6851 | err = ipw_send_qos_params_command(priv, | 6841 | err = ipw_send_qos_params_command(priv, |
6852 | (struct ieee80211_qos_parameters *) | 6842 | (struct ieee80211_qos_parameters *) |
6853 | &(qos_parameters[0])); | 6843 | &(qos_parameters[0])); |
@@ -7086,7 +7076,7 @@ static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, | |||
7086 | 7076 | ||
7087 | if (priv->qos_data.qos_no_ack_mask & (1UL << tx_queue_id)) { | 7077 | if (priv->qos_data.qos_no_ack_mask & (1UL << tx_queue_id)) { |
7088 | tfd->tx_flags &= ~DCT_FLAG_ACK_REQD; | 7078 | tfd->tx_flags &= ~DCT_FLAG_ACK_REQD; |
7089 | tfd->tfd.tfd_26.mchdr.qos_ctrl |= CTRL_QOS_NO_ACK; | 7079 | tfd->tfd.tfd_26.mchdr.qos_ctrl |= cpu_to_le16(CTRL_QOS_NO_ACK); |
7090 | } | 7080 | } |
7091 | return 0; | 7081 | return 0; |
7092 | } | 7082 | } |
@@ -7667,7 +7657,6 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | |||
7667 | /* Big bitfield of all the fields we provide in radiotap */ | 7657 | /* Big bitfield of all the fields we provide in radiotap */ |
7668 | ipw_rt->rt_hdr.it_present = | 7658 | ipw_rt->rt_hdr.it_present = |
7669 | ((1 << IEEE80211_RADIOTAP_FLAGS) | | 7659 | ((1 << IEEE80211_RADIOTAP_FLAGS) | |
7670 | (1 << IEEE80211_RADIOTAP_TSFT) | | ||
7671 | (1 << IEEE80211_RADIOTAP_RATE) | | 7660 | (1 << IEEE80211_RADIOTAP_RATE) | |
7672 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | 7661 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
7673 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | 7662 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | |
@@ -7676,6 +7665,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | |||
7676 | 7665 | ||
7677 | /* Zero the flags, we'll add to them as we go */ | 7666 | /* Zero the flags, we'll add to them as we go */ |
7678 | ipw_rt->rt_flags = 0; | 7667 | ipw_rt->rt_flags = 0; |
7668 | ipw_rt->rt_tsf = 0ULL; | ||
7679 | 7669 | ||
7680 | /* Convert signal to DBM */ | 7670 | /* Convert signal to DBM */ |
7681 | ipw_rt->rt_dbmsignal = antsignal; | 7671 | ipw_rt->rt_dbmsignal = antsignal; |
@@ -7794,7 +7784,6 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, | |||
7794 | s8 noise = frame->noise; | 7784 | s8 noise = frame->noise; |
7795 | u8 rate = frame->rate; | 7785 | u8 rate = frame->rate; |
7796 | short len = le16_to_cpu(pkt->u.frame.length); | 7786 | short len = le16_to_cpu(pkt->u.frame.length); |
7797 | u64 tsf = 0; | ||
7798 | struct sk_buff *skb; | 7787 | struct sk_buff *skb; |
7799 | int hdr_only = 0; | 7788 | int hdr_only = 0; |
7800 | u16 filter = priv->prom_priv->filter; | 7789 | u16 filter = priv->prom_priv->filter; |
@@ -7829,17 +7818,17 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, | |||
7829 | } | 7818 | } |
7830 | 7819 | ||
7831 | hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE; | 7820 | hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE; |
7832 | if (ieee80211_is_management(hdr->frame_ctl)) { | 7821 | if (ieee80211_is_management(le16_to_cpu(hdr->frame_ctl))) { |
7833 | if (filter & IPW_PROM_NO_MGMT) | 7822 | if (filter & IPW_PROM_NO_MGMT) |
7834 | return; | 7823 | return; |
7835 | if (filter & IPW_PROM_MGMT_HEADER_ONLY) | 7824 | if (filter & IPW_PROM_MGMT_HEADER_ONLY) |
7836 | hdr_only = 1; | 7825 | hdr_only = 1; |
7837 | } else if (ieee80211_is_control(hdr->frame_ctl)) { | 7826 | } else if (ieee80211_is_control(le16_to_cpu(hdr->frame_ctl))) { |
7838 | if (filter & IPW_PROM_NO_CTL) | 7827 | if (filter & IPW_PROM_NO_CTL) |
7839 | return; | 7828 | return; |
7840 | if (filter & IPW_PROM_CTL_HEADER_ONLY) | 7829 | if (filter & IPW_PROM_CTL_HEADER_ONLY) |
7841 | hdr_only = 1; | 7830 | hdr_only = 1; |
7842 | } else if (ieee80211_is_data(hdr->frame_ctl)) { | 7831 | } else if (ieee80211_is_data(le16_to_cpu(hdr->frame_ctl))) { |
7843 | if (filter & IPW_PROM_NO_DATA) | 7832 | if (filter & IPW_PROM_NO_DATA) |
7844 | return; | 7833 | return; |
7845 | if (filter & IPW_PROM_DATA_HEADER_ONLY) | 7834 | if (filter & IPW_PROM_DATA_HEADER_ONLY) |
@@ -7857,7 +7846,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, | |||
7857 | ipw_rt = (void *)skb->data; | 7846 | ipw_rt = (void *)skb->data; |
7858 | 7847 | ||
7859 | if (hdr_only) | 7848 | if (hdr_only) |
7860 | len = ieee80211_get_hdrlen(hdr->frame_ctl); | 7849 | len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); |
7861 | 7850 | ||
7862 | memcpy(ipw_rt->payload, hdr, len); | 7851 | memcpy(ipw_rt->payload, hdr, len); |
7863 | 7852 | ||
@@ -7880,7 +7869,6 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, | |||
7880 | /* Big bitfield of all the fields we provide in radiotap */ | 7869 | /* Big bitfield of all the fields we provide in radiotap */ |
7881 | ipw_rt->rt_hdr.it_present = | 7870 | ipw_rt->rt_hdr.it_present = |
7882 | ((1 << IEEE80211_RADIOTAP_FLAGS) | | 7871 | ((1 << IEEE80211_RADIOTAP_FLAGS) | |
7883 | (1 << IEEE80211_RADIOTAP_TSFT) | | ||
7884 | (1 << IEEE80211_RADIOTAP_RATE) | | 7872 | (1 << IEEE80211_RADIOTAP_RATE) | |
7885 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | 7873 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
7886 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | | 7874 | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | |
@@ -7889,8 +7877,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, | |||
7889 | 7877 | ||
7890 | /* Zero the flags, we'll add to them as we go */ | 7878 | /* Zero the flags, we'll add to them as we go */ |
7891 | ipw_rt->rt_flags = 0; | 7879 | ipw_rt->rt_flags = 0; |
7892 | 7880 | ipw_rt->rt_tsf = 0ULL; | |
7893 | ipw_rt->rt_tsf = tsf; | ||
7894 | 7881 | ||
7895 | /* Convert to DBM */ | 7882 | /* Convert to DBM */ |
7896 | ipw_rt->rt_dbmsignal = signal; | 7883 | ipw_rt->rt_dbmsignal = signal; |
@@ -8163,8 +8150,7 @@ static void ipw_rx(struct ipw_priv *priv) | |||
8163 | switch (pkt->header.message_type) { | 8150 | switch (pkt->header.message_type) { |
8164 | case RX_FRAME_TYPE: /* 802.11 frame */ { | 8151 | case RX_FRAME_TYPE: /* 802.11 frame */ { |
8165 | struct ieee80211_rx_stats stats = { | 8152 | struct ieee80211_rx_stats stats = { |
8166 | .rssi = | 8153 | .rssi = pkt->u.frame.rssi_dbm - |
8167 | le16_to_cpu(pkt->u.frame.rssi_dbm) - | ||
8168 | IPW_RSSI_TO_DBM, | 8154 | IPW_RSSI_TO_DBM, |
8169 | .signal = | 8155 | .signal = |
8170 | le16_to_cpu(pkt->u.frame.rssi_dbm) - | 8156 | le16_to_cpu(pkt->u.frame.rssi_dbm) - |
@@ -8599,9 +8585,26 @@ static int ipw_wx_get_freq(struct net_device *dev, | |||
8599 | * configured CHANNEL then return that; otherwise return ANY */ | 8585 | * configured CHANNEL then return that; otherwise return ANY */ |
8600 | mutex_lock(&priv->mutex); | 8586 | mutex_lock(&priv->mutex); |
8601 | if (priv->config & CFG_STATIC_CHANNEL || | 8587 | if (priv->config & CFG_STATIC_CHANNEL || |
8602 | priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) | 8588 | priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) { |
8603 | wrqu->freq.m = priv->channel; | 8589 | int i; |
8604 | else | 8590 | |
8591 | i = ieee80211_channel_to_index(priv->ieee, priv->channel); | ||
8592 | BUG_ON(i == -1); | ||
8593 | wrqu->freq.e = 1; | ||
8594 | |||
8595 | switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { | ||
8596 | case IEEE80211_52GHZ_BAND: | ||
8597 | wrqu->freq.m = priv->ieee->geo.a[i].freq * 100000; | ||
8598 | break; | ||
8599 | |||
8600 | case IEEE80211_24GHZ_BAND: | ||
8601 | wrqu->freq.m = priv->ieee->geo.bg[i].freq * 100000; | ||
8602 | break; | ||
8603 | |||
8604 | default: | ||
8605 | BUG(); | ||
8606 | } | ||
8607 | } else | ||
8605 | wrqu->freq.m = 0; | 8608 | wrqu->freq.m = 0; |
8606 | 8609 | ||
8607 | mutex_unlock(&priv->mutex); | 8610 | mutex_unlock(&priv->mutex); |
@@ -8857,42 +8860,38 @@ static int ipw_wx_set_essid(struct net_device *dev, | |||
8857 | union iwreq_data *wrqu, char *extra) | 8860 | union iwreq_data *wrqu, char *extra) |
8858 | { | 8861 | { |
8859 | struct ipw_priv *priv = ieee80211_priv(dev); | 8862 | struct ipw_priv *priv = ieee80211_priv(dev); |
8860 | char *essid = ""; /* ANY */ | 8863 | int length; |
8861 | int length = 0; | ||
8862 | mutex_lock(&priv->mutex); | ||
8863 | if (wrqu->essid.flags && wrqu->essid.length) { | ||
8864 | length = wrqu->essid.length - 1; | ||
8865 | essid = extra; | ||
8866 | } | ||
8867 | if (length == 0) { | ||
8868 | IPW_DEBUG_WX("Setting ESSID to ANY\n"); | ||
8869 | if ((priv->config & CFG_STATIC_ESSID) && | ||
8870 | !(priv->status & (STATUS_ASSOCIATED | | ||
8871 | STATUS_ASSOCIATING))) { | ||
8872 | IPW_DEBUG_ASSOC("Attempting to associate with new " | ||
8873 | "parameters.\n"); | ||
8874 | priv->config &= ~CFG_STATIC_ESSID; | ||
8875 | ipw_associate(priv); | ||
8876 | } | ||
8877 | mutex_unlock(&priv->mutex); | ||
8878 | return 0; | ||
8879 | } | ||
8880 | 8864 | ||
8881 | length = min(length, IW_ESSID_MAX_SIZE); | 8865 | mutex_lock(&priv->mutex); |
8866 | |||
8867 | if (!wrqu->essid.flags) | ||
8868 | { | ||
8869 | IPW_DEBUG_WX("Setting ESSID to ANY\n"); | ||
8870 | ipw_disassociate(priv); | ||
8871 | priv->config &= ~CFG_STATIC_ESSID; | ||
8872 | ipw_associate(priv); | ||
8873 | mutex_unlock(&priv->mutex); | ||
8874 | return 0; | ||
8875 | } | ||
8876 | |||
8877 | length = min((int)wrqu->essid.length, IW_ESSID_MAX_SIZE); | ||
8878 | if (!extra[length - 1]) | ||
8879 | length--; | ||
8882 | 8880 | ||
8883 | priv->config |= CFG_STATIC_ESSID; | 8881 | priv->config |= CFG_STATIC_ESSID; |
8884 | 8882 | ||
8885 | if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) { | 8883 | if (priv->essid_len == length && !memcmp(priv->essid, extra, length) |
8884 | && (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) { | ||
8886 | IPW_DEBUG_WX("ESSID set to current ESSID.\n"); | 8885 | IPW_DEBUG_WX("ESSID set to current ESSID.\n"); |
8887 | mutex_unlock(&priv->mutex); | 8886 | mutex_unlock(&priv->mutex); |
8888 | return 0; | 8887 | return 0; |
8889 | } | 8888 | } |
8890 | 8889 | ||
8891 | IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(essid, length), | 8890 | IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(extra, length), |
8892 | length); | 8891 | length); |
8893 | 8892 | ||
8894 | priv->essid_len = length; | 8893 | priv->essid_len = length; |
8895 | memcpy(priv->essid, essid, priv->essid_len); | 8894 | memcpy(priv->essid, extra, priv->essid_len); |
8896 | 8895 | ||
8897 | /* Network configuration changed -- force [re]association */ | 8896 | /* Network configuration changed -- force [re]association */ |
8898 | IPW_DEBUG_ASSOC("[re]association triggered due to ESSID change.\n"); | 8897 | IPW_DEBUG_ASSOC("[re]association triggered due to ESSID change.\n"); |
@@ -9273,7 +9272,7 @@ static int ipw_wx_set_retry(struct net_device *dev, | |||
9273 | if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) | 9272 | if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) |
9274 | return 0; | 9273 | return 0; |
9275 | 9274 | ||
9276 | if (wrqu->retry.value < 0 || wrqu->retry.value > 255) | 9275 | if (wrqu->retry.value < 0 || wrqu->retry.value >= 255) |
9277 | return -EINVAL; | 9276 | return -EINVAL; |
9278 | 9277 | ||
9279 | mutex_lock(&priv->mutex); | 9278 | mutex_lock(&priv->mutex); |
@@ -9396,15 +9395,19 @@ static int ipw_wx_set_scan(struct net_device *dev, | |||
9396 | union iwreq_data *wrqu, char *extra) | 9395 | union iwreq_data *wrqu, char *extra) |
9397 | { | 9396 | { |
9398 | struct ipw_priv *priv = ieee80211_priv(dev); | 9397 | struct ipw_priv *priv = ieee80211_priv(dev); |
9399 | struct iw_scan_req *req = NULL; | 9398 | struct iw_scan_req *req = (struct iw_scan_req *)extra; |
9400 | if (wrqu->data.length | 9399 | |
9401 | && wrqu->data.length == sizeof(struct iw_scan_req)) { | 9400 | if (wrqu->data.length == sizeof(struct iw_scan_req)) { |
9402 | req = (struct iw_scan_req *)extra; | ||
9403 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { | 9401 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { |
9404 | ipw_request_direct_scan(priv, req->essid, | 9402 | ipw_request_direct_scan(priv, req->essid, |
9405 | req->essid_len); | 9403 | req->essid_len); |
9406 | return 0; | 9404 | return 0; |
9407 | } | 9405 | } |
9406 | if (req->scan_type == IW_SCAN_TYPE_PASSIVE) { | ||
9407 | queue_work(priv->workqueue, | ||
9408 | &priv->request_passive_scan); | ||
9409 | return 0; | ||
9410 | } | ||
9408 | } | 9411 | } |
9409 | 9412 | ||
9410 | IPW_DEBUG_WX("Start scan\n"); | 9413 | IPW_DEBUG_WX("Start scan\n"); |
@@ -9766,7 +9769,7 @@ static int ipw_wx_set_monitor(struct net_device *dev, | |||
9766 | return 0; | 9769 | return 0; |
9767 | } | 9770 | } |
9768 | 9771 | ||
9769 | #endif // CONFIG_IPW2200_MONITOR | 9772 | #endif /* CONFIG_IPW2200_MONITOR */ |
9770 | 9773 | ||
9771 | static int ipw_wx_reset(struct net_device *dev, | 9774 | static int ipw_wx_reset(struct net_device *dev, |
9772 | struct iw_request_info *info, | 9775 | struct iw_request_info *info, |
@@ -10009,7 +10012,7 @@ static void init_sys_config(struct ipw_sys_config *sys_config) | |||
10009 | sys_config->dot11g_auto_detection = 0; | 10012 | sys_config->dot11g_auto_detection = 0; |
10010 | sys_config->enable_cts_to_self = 0; | 10013 | sys_config->enable_cts_to_self = 0; |
10011 | sys_config->bt_coexist_collision_thr = 0; | 10014 | sys_config->bt_coexist_collision_thr = 0; |
10012 | sys_config->pass_noise_stats_to_host = 1; //1 -- fix for 256 | 10015 | sys_config->pass_noise_stats_to_host = 1; /* 1 -- fix for 256 */ |
10013 | sys_config->silence_threshold = 0x1e; | 10016 | sys_config->silence_threshold = 0x1e; |
10014 | } | 10017 | } |
10015 | 10018 | ||
@@ -10113,7 +10116,7 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
10113 | switch (priv->ieee->sec.level) { | 10116 | switch (priv->ieee->sec.level) { |
10114 | case SEC_LEVEL_3: | 10117 | case SEC_LEVEL_3: |
10115 | tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= | 10118 | tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= |
10116 | IEEE80211_FCTL_PROTECTED; | 10119 | cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
10117 | /* XXX: ACK flag must be set for CCMP even if it | 10120 | /* XXX: ACK flag must be set for CCMP even if it |
10118 | * is a multicast/broadcast packet, because CCMP | 10121 | * is a multicast/broadcast packet, because CCMP |
10119 | * group communication encrypted by GTK is | 10122 | * group communication encrypted by GTK is |
@@ -10128,14 +10131,14 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
10128 | break; | 10131 | break; |
10129 | case SEC_LEVEL_2: | 10132 | case SEC_LEVEL_2: |
10130 | tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= | 10133 | tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= |
10131 | IEEE80211_FCTL_PROTECTED; | 10134 | cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
10132 | tfd->u.data.tx_flags &= ~DCT_FLAG_NO_WEP; | 10135 | tfd->u.data.tx_flags &= ~DCT_FLAG_NO_WEP; |
10133 | tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_SECURITY_TKIP; | 10136 | tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_SECURITY_TKIP; |
10134 | tfd->u.data.key_index = DCT_WEP_INDEX_USE_IMMEDIATE; | 10137 | tfd->u.data.key_index = DCT_WEP_INDEX_USE_IMMEDIATE; |
10135 | break; | 10138 | break; |
10136 | case SEC_LEVEL_1: | 10139 | case SEC_LEVEL_1: |
10137 | tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= | 10140 | tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= |
10138 | IEEE80211_FCTL_PROTECTED; | 10141 | cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
10139 | tfd->u.data.key_index = priv->ieee->tx_keyidx; | 10142 | tfd->u.data.key_index = priv->ieee->tx_keyidx; |
10140 | if (priv->ieee->sec.key_sizes[priv->ieee->tx_keyidx] <= | 10143 | if (priv->ieee->sec.key_sizes[priv->ieee->tx_keyidx] <= |
10141 | 40) | 10144 | 40) |
@@ -10267,17 +10270,17 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, | |||
10267 | 10270 | ||
10268 | /* Filtering of fragment chains is done agains the first fragment */ | 10271 | /* Filtering of fragment chains is done agains the first fragment */ |
10269 | hdr = (void *)txb->fragments[0]->data; | 10272 | hdr = (void *)txb->fragments[0]->data; |
10270 | if (ieee80211_is_management(hdr->frame_ctl)) { | 10273 | if (ieee80211_is_management(le16_to_cpu(hdr->frame_ctl))) { |
10271 | if (filter & IPW_PROM_NO_MGMT) | 10274 | if (filter & IPW_PROM_NO_MGMT) |
10272 | return; | 10275 | return; |
10273 | if (filter & IPW_PROM_MGMT_HEADER_ONLY) | 10276 | if (filter & IPW_PROM_MGMT_HEADER_ONLY) |
10274 | hdr_only = 1; | 10277 | hdr_only = 1; |
10275 | } else if (ieee80211_is_control(hdr->frame_ctl)) { | 10278 | } else if (ieee80211_is_control(le16_to_cpu(hdr->frame_ctl))) { |
10276 | if (filter & IPW_PROM_NO_CTL) | 10279 | if (filter & IPW_PROM_NO_CTL) |
10277 | return; | 10280 | return; |
10278 | if (filter & IPW_PROM_CTL_HEADER_ONLY) | 10281 | if (filter & IPW_PROM_CTL_HEADER_ONLY) |
10279 | hdr_only = 1; | 10282 | hdr_only = 1; |
10280 | } else if (ieee80211_is_data(hdr->frame_ctl)) { | 10283 | } else if (ieee80211_is_data(le16_to_cpu(hdr->frame_ctl))) { |
10281 | if (filter & IPW_PROM_NO_DATA) | 10284 | if (filter & IPW_PROM_NO_DATA) |
10282 | return; | 10285 | return; |
10283 | if (filter & IPW_PROM_DATA_HEADER_ONLY) | 10286 | if (filter & IPW_PROM_DATA_HEADER_ONLY) |
@@ -10292,7 +10295,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, | |||
10292 | 10295 | ||
10293 | if (hdr_only) { | 10296 | if (hdr_only) { |
10294 | hdr = (void *)src->data; | 10297 | hdr = (void *)src->data; |
10295 | len = ieee80211_get_hdrlen(hdr->frame_ctl); | 10298 | len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); |
10296 | } else | 10299 | } else |
10297 | len = src->len; | 10300 | len = src->len; |
10298 | 10301 | ||
@@ -10458,7 +10461,7 @@ static int ipw_ethtool_set_eeprom(struct net_device *dev, | |||
10458 | return 0; | 10461 | return 0; |
10459 | } | 10462 | } |
10460 | 10463 | ||
10461 | static struct ethtool_ops ipw_ethtool_ops = { | 10464 | static const struct ethtool_ops ipw_ethtool_ops = { |
10462 | .get_link = ipw_ethtool_get_link, | 10465 | .get_link = ipw_ethtool_get_link, |
10463 | .get_drvinfo = ipw_ethtool_get_drvinfo, | 10466 | .get_drvinfo = ipw_ethtool_get_drvinfo, |
10464 | .get_eeprom_len = ipw_ethtool_get_eeprom_len, | 10467 | .get_eeprom_len = ipw_ethtool_get_eeprom_len, |
@@ -10636,6 +10639,8 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) | |||
10636 | INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv); | 10639 | INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv); |
10637 | INIT_WORK(&priv->request_scan, | 10640 | INIT_WORK(&priv->request_scan, |
10638 | (void (*)(void *))ipw_request_scan, priv); | 10641 | (void (*)(void *))ipw_request_scan, priv); |
10642 | INIT_WORK(&priv->request_passive_scan, | ||
10643 | (void (*)(void *))ipw_request_passive_scan, priv); | ||
10639 | INIT_WORK(&priv->gather_stats, | 10644 | INIT_WORK(&priv->gather_stats, |
10640 | (void (*)(void *))ipw_bg_gather_stats, priv); | 10645 | (void (*)(void *))ipw_bg_gather_stats, priv); |
10641 | INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv); | 10646 | INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv); |
@@ -11488,9 +11493,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
11488 | 11493 | ||
11489 | priv->net_dev = net_dev; | 11494 | priv->net_dev = net_dev; |
11490 | priv->pci_dev = pdev; | 11495 | priv->pci_dev = pdev; |
11491 | #ifdef CONFIG_IPW2200_DEBUG | ||
11492 | ipw_debug_level = debug; | 11496 | ipw_debug_level = debug; |
11493 | #endif | ||
11494 | spin_lock_init(&priv->irq_lock); | 11497 | spin_lock_init(&priv->irq_lock); |
11495 | spin_lock_init(&priv->lock); | 11498 | spin_lock_init(&priv->lock); |
11496 | for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) | 11499 | for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) |
@@ -11755,6 +11758,16 @@ static int ipw_pci_resume(struct pci_dev *pdev) | |||
11755 | } | 11758 | } |
11756 | #endif | 11759 | #endif |
11757 | 11760 | ||
11761 | static void ipw_pci_shutdown(struct pci_dev *pdev) | ||
11762 | { | ||
11763 | struct ipw_priv *priv = pci_get_drvdata(pdev); | ||
11764 | |||
11765 | /* Take down the device; powers it off, etc. */ | ||
11766 | ipw_down(priv); | ||
11767 | |||
11768 | pci_disable_device(pdev); | ||
11769 | } | ||
11770 | |||
11758 | /* driver initialization stuff */ | 11771 | /* driver initialization stuff */ |
11759 | static struct pci_driver ipw_driver = { | 11772 | static struct pci_driver ipw_driver = { |
11760 | .name = DRV_NAME, | 11773 | .name = DRV_NAME, |
@@ -11765,6 +11778,7 @@ static struct pci_driver ipw_driver = { | |||
11765 | .suspend = ipw_pci_suspend, | 11778 | .suspend = ipw_pci_suspend, |
11766 | .resume = ipw_pci_resume, | 11779 | .resume = ipw_pci_resume, |
11767 | #endif | 11780 | #endif |
11781 | .shutdown = ipw_pci_shutdown, | ||
11768 | }; | 11782 | }; |
11769 | 11783 | ||
11770 | static int __init ipw_init(void) | 11784 | static int __init ipw_init(void) |
@@ -11774,7 +11788,7 @@ static int __init ipw_init(void) | |||
11774 | printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); | 11788 | printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); |
11775 | printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); | 11789 | printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); |
11776 | 11790 | ||
11777 | ret = pci_module_init(&ipw_driver); | 11791 | ret = pci_register_driver(&ipw_driver); |
11778 | if (ret) { | 11792 | if (ret) { |
11779 | IPW_ERROR("Unable to initialize PCI module\n"); | 11793 | IPW_ERROR("Unable to initialize PCI module\n"); |
11780 | return ret; | 11794 | return ret; |
@@ -11808,10 +11822,8 @@ MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); | |||
11808 | module_param(led, int, 0444); | 11822 | module_param(led, int, 0444); |
11809 | MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)\n"); | 11823 | MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)\n"); |
11810 | 11824 | ||
11811 | #ifdef CONFIG_IPW2200_DEBUG | ||
11812 | module_param(debug, int, 0444); | 11825 | module_param(debug, int, 0444); |
11813 | MODULE_PARM_DESC(debug, "debug output mask"); | 11826 | MODULE_PARM_DESC(debug, "debug output mask"); |
11814 | #endif | ||
11815 | 11827 | ||
11816 | module_param(channel, int, 0444); | 11828 | module_param(channel, int, 0444); |
11817 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); | 11829 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); |
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index 8b1cd7c749a4..dad5eedefbf1 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h | |||
@@ -713,7 +713,6 @@ struct ipw_rx_packet { | |||
713 | 713 | ||
714 | struct ipw_rx_mem_buffer { | 714 | struct ipw_rx_mem_buffer { |
715 | dma_addr_t dma_addr; | 715 | dma_addr_t dma_addr; |
716 | struct ipw_rx_buffer *rxb; | ||
717 | struct sk_buff *skb; | 716 | struct sk_buff *skb; |
718 | struct list_head list; | 717 | struct list_head list; |
719 | }; /* Not transferred over network, so not __attribute__ ((packed)) */ | 718 | }; /* Not transferred over network, so not __attribute__ ((packed)) */ |
@@ -1297,6 +1296,7 @@ struct ipw_priv { | |||
1297 | struct work_struct system_config; | 1296 | struct work_struct system_config; |
1298 | struct work_struct rx_replenish; | 1297 | struct work_struct rx_replenish; |
1299 | struct work_struct request_scan; | 1298 | struct work_struct request_scan; |
1299 | struct work_struct request_passive_scan; | ||
1300 | struct work_struct adapter_restart; | 1300 | struct work_struct adapter_restart; |
1301 | struct work_struct rf_kill; | 1301 | struct work_struct rf_kill; |
1302 | struct work_struct up; | 1302 | struct work_struct up; |
@@ -1381,13 +1381,18 @@ BITC(x,19),BITC(x,18),BITC(x,17),BITC(x,16),\ | |||
1381 | BIT_ARG16(x) | 1381 | BIT_ARG16(x) |
1382 | 1382 | ||
1383 | 1383 | ||
1384 | #ifdef CONFIG_IPW2200_DEBUG | ||
1385 | #define IPW_DEBUG(level, fmt, args...) \ | 1384 | #define IPW_DEBUG(level, fmt, args...) \ |
1386 | do { if (ipw_debug_level & (level)) \ | 1385 | do { if (ipw_debug_level & (level)) \ |
1387 | printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \ | 1386 | printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \ |
1388 | in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) | 1387 | in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) |
1388 | |||
1389 | #ifdef CONFIG_IPW2200_DEBUG | ||
1390 | #define IPW_LL_DEBUG(level, fmt, args...) \ | ||
1391 | do { if (ipw_debug_level & (level)) \ | ||
1392 | printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \ | ||
1393 | in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) | ||
1389 | #else | 1394 | #else |
1390 | #define IPW_DEBUG(level, fmt, args...) do {} while (0) | 1395 | #define IPW_LL_DEBUG(level, fmt, args...) do {} while (0) |
1391 | #endif /* CONFIG_IPW2200_DEBUG */ | 1396 | #endif /* CONFIG_IPW2200_DEBUG */ |
1392 | 1397 | ||
1393 | /* | 1398 | /* |
@@ -1457,28 +1462,27 @@ do { if (ipw_debug_level & (level)) \ | |||
1457 | 1462 | ||
1458 | #define IPW_DEBUG_WX(f, a...) IPW_DEBUG(IPW_DL_WX, f, ## a) | 1463 | #define IPW_DEBUG_WX(f, a...) IPW_DEBUG(IPW_DL_WX, f, ## a) |
1459 | #define IPW_DEBUG_SCAN(f, a...) IPW_DEBUG(IPW_DL_SCAN, f, ## a) | 1464 | #define IPW_DEBUG_SCAN(f, a...) IPW_DEBUG(IPW_DL_SCAN, f, ## a) |
1460 | #define IPW_DEBUG_STATUS(f, a...) IPW_DEBUG(IPW_DL_STATUS, f, ## a) | 1465 | #define IPW_DEBUG_TRACE(f, a...) IPW_LL_DEBUG(IPW_DL_TRACE, f, ## a) |
1461 | #define IPW_DEBUG_TRACE(f, a...) IPW_DEBUG(IPW_DL_TRACE, f, ## a) | 1466 | #define IPW_DEBUG_RX(f, a...) IPW_LL_DEBUG(IPW_DL_RX, f, ## a) |
1462 | #define IPW_DEBUG_RX(f, a...) IPW_DEBUG(IPW_DL_RX, f, ## a) | 1467 | #define IPW_DEBUG_TX(f, a...) IPW_LL_DEBUG(IPW_DL_TX, f, ## a) |
1463 | #define IPW_DEBUG_TX(f, a...) IPW_DEBUG(IPW_DL_TX, f, ## a) | 1468 | #define IPW_DEBUG_ISR(f, a...) IPW_LL_DEBUG(IPW_DL_ISR, f, ## a) |
1464 | #define IPW_DEBUG_ISR(f, a...) IPW_DEBUG(IPW_DL_ISR, f, ## a) | ||
1465 | #define IPW_DEBUG_MANAGEMENT(f, a...) IPW_DEBUG(IPW_DL_MANAGE, f, ## a) | 1469 | #define IPW_DEBUG_MANAGEMENT(f, a...) IPW_DEBUG(IPW_DL_MANAGE, f, ## a) |
1466 | #define IPW_DEBUG_LED(f, a...) IPW_DEBUG(IPW_DL_LED, f, ## a) | 1470 | #define IPW_DEBUG_LED(f, a...) IPW_LL_DEBUG(IPW_DL_LED, f, ## a) |
1467 | #define IPW_DEBUG_WEP(f, a...) IPW_DEBUG(IPW_DL_WEP, f, ## a) | 1471 | #define IPW_DEBUG_WEP(f, a...) IPW_LL_DEBUG(IPW_DL_WEP, f, ## a) |
1468 | #define IPW_DEBUG_HC(f, a...) IPW_DEBUG(IPW_DL_HOST_COMMAND, f, ## a) | 1472 | #define IPW_DEBUG_HC(f, a...) IPW_LL_DEBUG(IPW_DL_HOST_COMMAND, f, ## a) |
1469 | #define IPW_DEBUG_FRAG(f, a...) IPW_DEBUG(IPW_DL_FRAG, f, ## a) | 1473 | #define IPW_DEBUG_FRAG(f, a...) IPW_LL_DEBUG(IPW_DL_FRAG, f, ## a) |
1470 | #define IPW_DEBUG_FW(f, a...) IPW_DEBUG(IPW_DL_FW, f, ## a) | 1474 | #define IPW_DEBUG_FW(f, a...) IPW_LL_DEBUG(IPW_DL_FW, f, ## a) |
1471 | #define IPW_DEBUG_RF_KILL(f, a...) IPW_DEBUG(IPW_DL_RF_KILL, f, ## a) | 1475 | #define IPW_DEBUG_RF_KILL(f, a...) IPW_DEBUG(IPW_DL_RF_KILL, f, ## a) |
1472 | #define IPW_DEBUG_DROP(f, a...) IPW_DEBUG(IPW_DL_DROP, f, ## a) | 1476 | #define IPW_DEBUG_DROP(f, a...) IPW_DEBUG(IPW_DL_DROP, f, ## a) |
1473 | #define IPW_DEBUG_IO(f, a...) IPW_DEBUG(IPW_DL_IO, f, ## a) | 1477 | #define IPW_DEBUG_IO(f, a...) IPW_LL_DEBUG(IPW_DL_IO, f, ## a) |
1474 | #define IPW_DEBUG_ORD(f, a...) IPW_DEBUG(IPW_DL_ORD, f, ## a) | 1478 | #define IPW_DEBUG_ORD(f, a...) IPW_LL_DEBUG(IPW_DL_ORD, f, ## a) |
1475 | #define IPW_DEBUG_FW_INFO(f, a...) IPW_DEBUG(IPW_DL_FW_INFO, f, ## a) | 1479 | #define IPW_DEBUG_FW_INFO(f, a...) IPW_LL_DEBUG(IPW_DL_FW_INFO, f, ## a) |
1476 | #define IPW_DEBUG_NOTIF(f, a...) IPW_DEBUG(IPW_DL_NOTIF, f, ## a) | 1480 | #define IPW_DEBUG_NOTIF(f, a...) IPW_DEBUG(IPW_DL_NOTIF, f, ## a) |
1477 | #define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) | 1481 | #define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) |
1478 | #define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) | 1482 | #define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) |
1479 | #define IPW_DEBUG_STATS(f, a...) IPW_DEBUG(IPW_DL_STATS, f, ## a) | 1483 | #define IPW_DEBUG_STATS(f, a...) IPW_LL_DEBUG(IPW_DL_STATS, f, ## a) |
1480 | #define IPW_DEBUG_MERGE(f, a...) IPW_DEBUG(IPW_DL_MERGE, f, ## a) | 1484 | #define IPW_DEBUG_MERGE(f, a...) IPW_LL_DEBUG(IPW_DL_MERGE, f, ## a) |
1481 | #define IPW_DEBUG_QOS(f, a...) IPW_DEBUG(IPW_DL_QOS, f, ## a) | 1485 | #define IPW_DEBUG_QOS(f, a...) IPW_LL_DEBUG(IPW_DL_QOS, f, ## a) |
1482 | 1486 | ||
1483 | #include <linux/ctype.h> | 1487 | #include <linux/ctype.h> |
1484 | 1488 | ||
@@ -1947,10 +1951,17 @@ struct host_cmd { | |||
1947 | u32 *param; | 1951 | u32 *param; |
1948 | } __attribute__ ((packed)); | 1952 | } __attribute__ ((packed)); |
1949 | 1953 | ||
1954 | struct cmdlog_host_cmd { | ||
1955 | u8 cmd; | ||
1956 | u8 len; | ||
1957 | u16 reserved; | ||
1958 | char param[124]; | ||
1959 | } __attribute__ ((packed)); | ||
1960 | |||
1950 | struct ipw_cmd_log { | 1961 | struct ipw_cmd_log { |
1951 | unsigned long jiffies; | 1962 | unsigned long jiffies; |
1952 | int retcode; | 1963 | int retcode; |
1953 | struct host_cmd cmd; | 1964 | struct cmdlog_host_cmd cmd; |
1954 | }; | 1965 | }; |
1955 | 1966 | ||
1956 | /* SysConfig command parameters ... */ | 1967 | /* SysConfig command parameters ... */ |
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 317ace7f9aae..1840b69e3cb5 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
@@ -82,6 +82,7 @@ | |||
82 | #include <linux/netdevice.h> | 82 | #include <linux/netdevice.h> |
83 | #include <linux/etherdevice.h> | 83 | #include <linux/etherdevice.h> |
84 | #include <linux/ethtool.h> | 84 | #include <linux/ethtool.h> |
85 | #include <linux/if_arp.h> | ||
85 | #include <linux/wireless.h> | 86 | #include <linux/wireless.h> |
86 | #include <net/iw_handler.h> | 87 | #include <net/iw_handler.h> |
87 | #include <net/ieee80211.h> | 88 | #include <net/ieee80211.h> |
@@ -164,7 +165,7 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | |||
164 | #define MAX_RID_LEN 1024 | 165 | #define MAX_RID_LEN 1024 |
165 | 166 | ||
166 | static const struct iw_handler_def orinoco_handler_def; | 167 | static const struct iw_handler_def orinoco_handler_def; |
167 | static struct ethtool_ops orinoco_ethtool_ops; | 168 | static const struct ethtool_ops orinoco_ethtool_ops; |
168 | 169 | ||
169 | /********************************************************************/ | 170 | /********************************************************************/ |
170 | /* Data tables */ | 171 | /* Data tables */ |
@@ -4292,7 +4293,7 @@ static void orinoco_get_drvinfo(struct net_device *dev, | |||
4292 | "PCMCIA %p", priv->hw.iobase); | 4293 | "PCMCIA %p", priv->hw.iobase); |
4293 | } | 4294 | } |
4294 | 4295 | ||
4295 | static struct ethtool_ops orinoco_ethtool_ops = { | 4296 | static const struct ethtool_ops orinoco_ethtool_ops = { |
4296 | .get_drvinfo = orinoco_get_drvinfo, | 4297 | .get_drvinfo = orinoco_get_drvinfo, |
4297 | .get_link = ethtool_op_get_link, | 4298 | .get_link = ethtool_op_get_link, |
4298 | }; | 4299 | }; |
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h index 16db3e14b7d2..fb5700d6c454 100644 --- a/drivers/net/wireless/orinoco.h +++ b/drivers/net/wireless/orinoco.h | |||
@@ -134,11 +134,7 @@ extern irqreturn_t orinoco_interrupt(int irq, void * dev_id, struct pt_regs *reg | |||
134 | /* Locking and synchronization functions */ | 134 | /* Locking and synchronization functions */ |
135 | /********************************************************************/ | 135 | /********************************************************************/ |
136 | 136 | ||
137 | /* These functions *must* be inline or they will break horribly on | 137 | static inline int orinoco_lock(struct orinoco_private *priv, |
138 | * SPARC, due to its weird semantics for save/restore flags. extern | ||
139 | * inline should prevent the kernel from linking or module from | ||
140 | * loading if they are not inlined. */ | ||
141 | extern inline int orinoco_lock(struct orinoco_private *priv, | ||
142 | unsigned long *flags) | 138 | unsigned long *flags) |
143 | { | 139 | { |
144 | spin_lock_irqsave(&priv->lock, *flags); | 140 | spin_lock_irqsave(&priv->lock, *flags); |
@@ -151,7 +147,7 @@ extern inline int orinoco_lock(struct orinoco_private *priv, | |||
151 | return 0; | 147 | return 0; |
152 | } | 148 | } |
153 | 149 | ||
154 | extern inline void orinoco_unlock(struct orinoco_private *priv, | 150 | static inline void orinoco_unlock(struct orinoco_private *priv, |
155 | unsigned long *flags) | 151 | unsigned long *flags) |
156 | { | 152 | { |
157 | spin_unlock_irqrestore(&priv->lock, *flags); | 153 | spin_unlock_irqrestore(&priv->lock, *flags); |
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c index bf05b907747e..eaf3d13b851c 100644 --- a/drivers/net/wireless/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco_nortel.c | |||
@@ -304,7 +304,7 @@ MODULE_LICENSE("Dual MPL/GPL"); | |||
304 | static int __init orinoco_nortel_init(void) | 304 | static int __init orinoco_nortel_init(void) |
305 | { | 305 | { |
306 | printk(KERN_DEBUG "%s\n", version); | 306 | printk(KERN_DEBUG "%s\n", version); |
307 | return pci_module_init(&orinoco_nortel_driver); | 307 | return pci_register_driver(&orinoco_nortel_driver); |
308 | } | 308 | } |
309 | 309 | ||
310 | static void __exit orinoco_nortel_exit(void) | 310 | static void __exit orinoco_nortel_exit(void) |
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c index 1759c543fbee..97a8b4ff32bd 100644 --- a/drivers/net/wireless/orinoco_pci.c +++ b/drivers/net/wireless/orinoco_pci.c | |||
@@ -244,7 +244,7 @@ MODULE_LICENSE("Dual MPL/GPL"); | |||
244 | static int __init orinoco_pci_init(void) | 244 | static int __init orinoco_pci_init(void) |
245 | { | 245 | { |
246 | printk(KERN_DEBUG "%s\n", version); | 246 | printk(KERN_DEBUG "%s\n", version); |
247 | return pci_module_init(&orinoco_pci_driver); | 247 | return pci_register_driver(&orinoco_pci_driver); |
248 | } | 248 | } |
249 | 249 | ||
250 | static void __exit orinoco_pci_exit(void) | 250 | static void __exit orinoco_pci_exit(void) |
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c index 7f006f624171..31162ac25a92 100644 --- a/drivers/net/wireless/orinoco_plx.c +++ b/drivers/net/wireless/orinoco_plx.c | |||
@@ -351,7 +351,7 @@ MODULE_LICENSE("Dual MPL/GPL"); | |||
351 | static int __init orinoco_plx_init(void) | 351 | static int __init orinoco_plx_init(void) |
352 | { | 352 | { |
353 | printk(KERN_DEBUG "%s\n", version); | 353 | printk(KERN_DEBUG "%s\n", version); |
354 | return pci_module_init(&orinoco_plx_driver); | 354 | return pci_register_driver(&orinoco_plx_driver); |
355 | } | 355 | } |
356 | 356 | ||
357 | static void __exit orinoco_plx_exit(void) | 357 | static void __exit orinoco_plx_exit(void) |
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c index 0831721e4d6c..7c7b960c91df 100644 --- a/drivers/net/wireless/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco_tmd.c | |||
@@ -228,7 +228,7 @@ MODULE_LICENSE("Dual MPL/GPL"); | |||
228 | static int __init orinoco_tmd_init(void) | 228 | static int __init orinoco_tmd_init(void) |
229 | { | 229 | { |
230 | printk(KERN_DEBUG "%s\n", version); | 230 | printk(KERN_DEBUG "%s\n", version); |
231 | return pci_module_init(&orinoco_tmd_driver); | 231 | return pci_register_driver(&orinoco_tmd_driver); |
232 | } | 232 | } |
233 | 233 | ||
234 | static void __exit orinoco_tmd_exit(void) | 234 | static void __exit orinoco_tmd_exit(void) |
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 989599ad33ef..c09fbf733b3a 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c | |||
@@ -35,13 +35,21 @@ | |||
35 | 35 | ||
36 | #include <net/iw_handler.h> /* New driver API */ | 36 | #include <net/iw_handler.h> /* New driver API */ |
37 | 37 | ||
38 | #define KEY_SIZE_WEP104 13 /* 104/128-bit WEP keys */ | ||
39 | #define KEY_SIZE_WEP40 5 /* 40/64-bit WEP keys */ | ||
40 | /* KEY_SIZE_TKIP should match isl_oid.h, struct obj_key.key[] size */ | ||
41 | #define KEY_SIZE_TKIP 32 /* TKIP keys */ | ||
38 | 42 | ||
39 | static void prism54_wpa_ie_add(islpci_private *priv, u8 *bssid, | 43 | static void prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid, |
40 | u8 *wpa_ie, size_t wpa_ie_len); | 44 | u8 *wpa_ie, size_t wpa_ie_len); |
41 | static size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie); | 45 | static size_t prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie); |
42 | static int prism54_set_wpa(struct net_device *, struct iw_request_info *, | 46 | static int prism54_set_wpa(struct net_device *, struct iw_request_info *, |
43 | __u32 *, char *); | 47 | __u32 *, char *); |
44 | 48 | ||
49 | /* In 500 kbps */ | ||
50 | static const unsigned char scan_rate_list[] = { 2, 4, 11, 22, | ||
51 | 12, 18, 24, 36, | ||
52 | 48, 72, 96, 108 }; | ||
45 | 53 | ||
46 | /** | 54 | /** |
47 | * prism54_mib_mode_helper - MIB change mode helper function | 55 | * prism54_mib_mode_helper - MIB change mode helper function |
@@ -468,6 +476,9 @@ prism54_get_range(struct net_device *ndev, struct iw_request_info *info, | |||
468 | range->event_capa[1] = IW_EVENT_CAPA_K_1; | 476 | range->event_capa[1] = IW_EVENT_CAPA_K_1; |
469 | range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM); | 477 | range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM); |
470 | 478 | ||
479 | range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | | ||
480 | IW_ENC_CAPA_CIPHER_TKIP; | ||
481 | |||
471 | if (islpci_get_state(priv) < PRV_STATE_INIT) | 482 | if (islpci_get_state(priv) < PRV_STATE_INIT) |
472 | return 0; | 483 | return 0; |
473 | 484 | ||
@@ -567,6 +578,8 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev, | |||
567 | struct iw_event iwe; /* Temporary buffer */ | 578 | struct iw_event iwe; /* Temporary buffer */ |
568 | short cap; | 579 | short cap; |
569 | islpci_private *priv = netdev_priv(ndev); | 580 | islpci_private *priv = netdev_priv(ndev); |
581 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
582 | size_t wpa_ie_len; | ||
570 | 583 | ||
571 | /* The first entry must be the MAC address */ | 584 | /* The first entry must be the MAC address */ |
572 | memcpy(iwe.u.ap_addr.sa_data, bss->address, 6); | 585 | memcpy(iwe.u.ap_addr.sa_data, bss->address, 6); |
@@ -627,28 +640,40 @@ prism54_translate_bss(struct net_device *ndev, char *current_ev, | |||
627 | current_ev = | 640 | current_ev = |
628 | iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); | 641 | iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); |
629 | 642 | ||
630 | if (priv->wpa) { | 643 | /* Add WPA/RSN Information Element, if any */ |
631 | u8 wpa_ie[MAX_WPA_IE_LEN]; | 644 | wpa_ie_len = prism54_wpa_bss_ie_get(priv, bss->address, wpa_ie); |
632 | char *buf, *p; | 645 | if (wpa_ie_len > 0) { |
633 | size_t wpa_ie_len; | 646 | iwe.cmd = IWEVGENIE; |
647 | iwe.u.data.length = min(wpa_ie_len, (size_t)MAX_WPA_IE_LEN); | ||
648 | current_ev = iwe_stream_add_point(current_ev, end_buf, | ||
649 | &iwe, wpa_ie); | ||
650 | } | ||
651 | /* Do the bitrates */ | ||
652 | { | ||
653 | char * current_val = current_ev + IW_EV_LCP_LEN; | ||
634 | int i; | 654 | int i; |
635 | 655 | int mask; | |
636 | wpa_ie_len = prism54_wpa_ie_get(priv, bss->address, wpa_ie); | 656 | |
637 | if (wpa_ie_len > 0 && | 657 | iwe.cmd = SIOCGIWRATE; |
638 | (buf = kmalloc(wpa_ie_len * 2 + 10, GFP_ATOMIC))) { | 658 | /* Those two flags are ignored... */ |
639 | p = buf; | 659 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; |
640 | p += sprintf(p, "wpa_ie="); | 660 | |
641 | for (i = 0; i < wpa_ie_len; i++) { | 661 | /* Parse the bitmask */ |
642 | p += sprintf(p, "%02x", wpa_ie[i]); | 662 | mask = 0x1; |
663 | for(i = 0; i < sizeof(scan_rate_list); i++) { | ||
664 | if(bss->rates & mask) { | ||
665 | iwe.u.bitrate.value = (scan_rate_list[i] * 500000); | ||
666 | current_val = iwe_stream_add_value(current_ev, current_val, | ||
667 | end_buf, &iwe, | ||
668 | IW_EV_PARAM_LEN); | ||
643 | } | 669 | } |
644 | memset(&iwe, 0, sizeof (iwe)); | 670 | mask <<= 1; |
645 | iwe.cmd = IWEVCUSTOM; | ||
646 | iwe.u.data.length = strlen(buf); | ||
647 | current_ev = iwe_stream_add_point(current_ev, end_buf, | ||
648 | &iwe, buf); | ||
649 | kfree(buf); | ||
650 | } | 671 | } |
672 | /* Check if we added any event */ | ||
673 | if ((current_val - current_ev) > IW_EV_LCP_LEN) | ||
674 | current_ev = current_val; | ||
651 | } | 675 | } |
676 | |||
652 | return current_ev; | 677 | return current_ev; |
653 | } | 678 | } |
654 | 679 | ||
@@ -1051,12 +1076,24 @@ prism54_set_encode(struct net_device *ndev, struct iw_request_info *info, | |||
1051 | current_index = r.u; | 1076 | current_index = r.u; |
1052 | /* Verify that the key is not marked as invalid */ | 1077 | /* Verify that the key is not marked as invalid */ |
1053 | if (!(dwrq->flags & IW_ENCODE_NOKEY)) { | 1078 | if (!(dwrq->flags & IW_ENCODE_NOKEY)) { |
1054 | key.length = dwrq->length > sizeof (key.key) ? | 1079 | if (dwrq->length > KEY_SIZE_TKIP) { |
1055 | sizeof (key.key) : dwrq->length; | 1080 | /* User-provided key data too big */ |
1056 | memcpy(key.key, extra, key.length); | 1081 | return -EINVAL; |
1057 | if (key.length == 32) | 1082 | } |
1058 | /* we want WPA-PSK */ | 1083 | if (dwrq->length > KEY_SIZE_WEP104) { |
1084 | /* WPA-PSK TKIP */ | ||
1059 | key.type = DOT11_PRIV_TKIP; | 1085 | key.type = DOT11_PRIV_TKIP; |
1086 | key.length = KEY_SIZE_TKIP; | ||
1087 | } else if (dwrq->length > KEY_SIZE_WEP40) { | ||
1088 | /* WEP 104/128 */ | ||
1089 | key.length = KEY_SIZE_WEP104; | ||
1090 | } else { | ||
1091 | /* WEP 40/64 */ | ||
1092 | key.length = KEY_SIZE_WEP40; | ||
1093 | } | ||
1094 | memset(key.key, 0, sizeof (key.key)); | ||
1095 | memcpy(key.key, extra, dwrq->length); | ||
1096 | |||
1060 | if ((index < 0) || (index > 3)) | 1097 | if ((index < 0) || (index > 3)) |
1061 | /* no index provided use the current one */ | 1098 | /* no index provided use the current one */ |
1062 | index = current_index; | 1099 | index = current_index; |
@@ -1210,6 +1247,489 @@ prism54_set_txpower(struct net_device *ndev, struct iw_request_info *info, | |||
1210 | } | 1247 | } |
1211 | } | 1248 | } |
1212 | 1249 | ||
1250 | static int prism54_set_genie(struct net_device *ndev, | ||
1251 | struct iw_request_info *info, | ||
1252 | struct iw_point *data, char *extra) | ||
1253 | { | ||
1254 | islpci_private *priv = netdev_priv(ndev); | ||
1255 | int alen, ret = 0; | ||
1256 | struct obj_attachment *attach; | ||
1257 | |||
1258 | if (data->length > MAX_WPA_IE_LEN || | ||
1259 | (data->length && extra == NULL)) | ||
1260 | return -EINVAL; | ||
1261 | |||
1262 | memcpy(priv->wpa_ie, extra, data->length); | ||
1263 | priv->wpa_ie_len = data->length; | ||
1264 | |||
1265 | alen = sizeof(*attach) + priv->wpa_ie_len; | ||
1266 | attach = kzalloc(alen, GFP_KERNEL); | ||
1267 | if (attach == NULL) | ||
1268 | return -ENOMEM; | ||
1269 | |||
1270 | #define WLAN_FC_TYPE_MGMT 0 | ||
1271 | #define WLAN_FC_STYPE_ASSOC_REQ 0 | ||
1272 | #define WLAN_FC_STYPE_REASSOC_REQ 2 | ||
1273 | |||
1274 | /* Note: endianness is covered by mgt_set_varlen */ | ||
1275 | attach->type = (WLAN_FC_TYPE_MGMT << 2) | | ||
1276 | (WLAN_FC_STYPE_ASSOC_REQ << 4); | ||
1277 | attach->id = -1; | ||
1278 | attach->size = priv->wpa_ie_len; | ||
1279 | memcpy(attach->data, extra, priv->wpa_ie_len); | ||
1280 | |||
1281 | ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, | ||
1282 | priv->wpa_ie_len); | ||
1283 | if (ret == 0) { | ||
1284 | attach->type = (WLAN_FC_TYPE_MGMT << 2) | | ||
1285 | (WLAN_FC_STYPE_REASSOC_REQ << 4); | ||
1286 | |||
1287 | ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, | ||
1288 | priv->wpa_ie_len); | ||
1289 | if (ret == 0) | ||
1290 | printk(KERN_DEBUG "%s: WPA IE Attachment was set\n", | ||
1291 | ndev->name); | ||
1292 | } | ||
1293 | |||
1294 | kfree(attach); | ||
1295 | return ret; | ||
1296 | } | ||
1297 | |||
1298 | |||
1299 | static int prism54_get_genie(struct net_device *ndev, | ||
1300 | struct iw_request_info *info, | ||
1301 | struct iw_point *data, char *extra) | ||
1302 | { | ||
1303 | islpci_private *priv = netdev_priv(ndev); | ||
1304 | int len = priv->wpa_ie_len; | ||
1305 | |||
1306 | if (len <= 0) { | ||
1307 | data->length = 0; | ||
1308 | return 0; | ||
1309 | } | ||
1310 | |||
1311 | if (data->length < len) | ||
1312 | return -E2BIG; | ||
1313 | |||
1314 | data->length = len; | ||
1315 | memcpy(extra, priv->wpa_ie, len); | ||
1316 | |||
1317 | return 0; | ||
1318 | } | ||
1319 | |||
1320 | static int prism54_set_auth(struct net_device *ndev, | ||
1321 | struct iw_request_info *info, | ||
1322 | union iwreq_data *wrqu, char *extra) | ||
1323 | { | ||
1324 | islpci_private *priv = netdev_priv(ndev); | ||
1325 | struct iw_param *param = &wrqu->param; | ||
1326 | u32 mlmelevel = 0, authen = 0, dot1x = 0; | ||
1327 | u32 exunencrypt = 0, privinvoked = 0, wpa = 0; | ||
1328 | u32 old_wpa; | ||
1329 | int ret = 0; | ||
1330 | union oid_res_t r; | ||
1331 | |||
1332 | if (islpci_get_state(priv) < PRV_STATE_INIT) | ||
1333 | return 0; | ||
1334 | |||
1335 | /* first get the flags */ | ||
1336 | down_write(&priv->mib_sem); | ||
1337 | wpa = old_wpa = priv->wpa; | ||
1338 | up_write(&priv->mib_sem); | ||
1339 | ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); | ||
1340 | authen = r.u; | ||
1341 | ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); | ||
1342 | privinvoked = r.u; | ||
1343 | ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); | ||
1344 | exunencrypt = r.u; | ||
1345 | ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r); | ||
1346 | dot1x = r.u; | ||
1347 | ret = mgt_get_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, NULL, &r); | ||
1348 | mlmelevel = r.u; | ||
1349 | |||
1350 | if (ret < 0) | ||
1351 | goto out; | ||
1352 | |||
1353 | switch (param->flags & IW_AUTH_INDEX) { | ||
1354 | case IW_AUTH_CIPHER_PAIRWISE: | ||
1355 | case IW_AUTH_CIPHER_GROUP: | ||
1356 | case IW_AUTH_KEY_MGMT: | ||
1357 | break; | ||
1358 | |||
1359 | case IW_AUTH_WPA_ENABLED: | ||
1360 | /* Do the same thing as IW_AUTH_WPA_VERSION */ | ||
1361 | if (param->value) { | ||
1362 | wpa = 1; | ||
1363 | privinvoked = 1; /* For privacy invoked */ | ||
1364 | exunencrypt = 1; /* Filter out all unencrypted frames */ | ||
1365 | dot1x = 0x01; /* To enable eap filter */ | ||
1366 | mlmelevel = DOT11_MLME_EXTENDED; | ||
1367 | authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */ | ||
1368 | } else { | ||
1369 | wpa = 0; | ||
1370 | privinvoked = 0; | ||
1371 | exunencrypt = 0; /* Do not filter un-encrypted data */ | ||
1372 | dot1x = 0; | ||
1373 | mlmelevel = DOT11_MLME_AUTO; | ||
1374 | } | ||
1375 | break; | ||
1376 | |||
1377 | case IW_AUTH_WPA_VERSION: | ||
1378 | if (param->value & IW_AUTH_WPA_VERSION_DISABLED) { | ||
1379 | wpa = 0; | ||
1380 | privinvoked = 0; | ||
1381 | exunencrypt = 0; /* Do not filter un-encrypted data */ | ||
1382 | dot1x = 0; | ||
1383 | mlmelevel = DOT11_MLME_AUTO; | ||
1384 | } else { | ||
1385 | if (param->value & IW_AUTH_WPA_VERSION_WPA) | ||
1386 | wpa = 1; | ||
1387 | else if (param->value & IW_AUTH_WPA_VERSION_WPA2) | ||
1388 | wpa = 2; | ||
1389 | privinvoked = 1; /* For privacy invoked */ | ||
1390 | exunencrypt = 1; /* Filter out all unencrypted frames */ | ||
1391 | dot1x = 0x01; /* To enable eap filter */ | ||
1392 | mlmelevel = DOT11_MLME_EXTENDED; | ||
1393 | authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */ | ||
1394 | } | ||
1395 | break; | ||
1396 | |||
1397 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | ||
1398 | dot1x = param->value ? 1 : 0; | ||
1399 | break; | ||
1400 | |||
1401 | case IW_AUTH_PRIVACY_INVOKED: | ||
1402 | privinvoked = param->value ? 1 : 0; | ||
1403 | |||
1404 | case IW_AUTH_DROP_UNENCRYPTED: | ||
1405 | exunencrypt = param->value ? 1 : 0; | ||
1406 | break; | ||
1407 | |||
1408 | case IW_AUTH_80211_AUTH_ALG: | ||
1409 | if (param->value & IW_AUTH_ALG_SHARED_KEY) { | ||
1410 | /* Only WEP uses _SK and _BOTH */ | ||
1411 | if (wpa > 0) { | ||
1412 | ret = -EINVAL; | ||
1413 | goto out; | ||
1414 | } | ||
1415 | authen = DOT11_AUTH_SK; | ||
1416 | } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { | ||
1417 | authen = DOT11_AUTH_OS; | ||
1418 | } else { | ||
1419 | ret = -EINVAL; | ||
1420 | goto out; | ||
1421 | } | ||
1422 | break; | ||
1423 | |||
1424 | default: | ||
1425 | return -EOPNOTSUPP; | ||
1426 | } | ||
1427 | |||
1428 | /* Set all the values */ | ||
1429 | down_write(&priv->mib_sem); | ||
1430 | priv->wpa = wpa; | ||
1431 | up_write(&priv->mib_sem); | ||
1432 | mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); | ||
1433 | mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &privinvoked); | ||
1434 | mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &exunencrypt); | ||
1435 | mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x); | ||
1436 | mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlmelevel); | ||
1437 | |||
1438 | out: | ||
1439 | return ret; | ||
1440 | } | ||
1441 | |||
1442 | static int prism54_get_auth(struct net_device *ndev, | ||
1443 | struct iw_request_info *info, | ||
1444 | union iwreq_data *wrqu, char *extra) | ||
1445 | { | ||
1446 | islpci_private *priv = netdev_priv(ndev); | ||
1447 | struct iw_param *param = &wrqu->param; | ||
1448 | u32 wpa = 0; | ||
1449 | int ret = 0; | ||
1450 | union oid_res_t r; | ||
1451 | |||
1452 | if (islpci_get_state(priv) < PRV_STATE_INIT) | ||
1453 | return 0; | ||
1454 | |||
1455 | /* first get the flags */ | ||
1456 | down_write(&priv->mib_sem); | ||
1457 | wpa = priv->wpa; | ||
1458 | up_write(&priv->mib_sem); | ||
1459 | |||
1460 | switch (param->flags & IW_AUTH_INDEX) { | ||
1461 | case IW_AUTH_CIPHER_PAIRWISE: | ||
1462 | case IW_AUTH_CIPHER_GROUP: | ||
1463 | case IW_AUTH_KEY_MGMT: | ||
1464 | /* | ||
1465 | * wpa_supplicant will control these internally | ||
1466 | */ | ||
1467 | ret = -EOPNOTSUPP; | ||
1468 | break; | ||
1469 | |||
1470 | case IW_AUTH_WPA_VERSION: | ||
1471 | switch (wpa) { | ||
1472 | case 1: | ||
1473 | param->value = IW_AUTH_WPA_VERSION_WPA; | ||
1474 | break; | ||
1475 | case 2: | ||
1476 | param->value = IW_AUTH_WPA_VERSION_WPA2; | ||
1477 | break; | ||
1478 | case 0: | ||
1479 | default: | ||
1480 | param->value = IW_AUTH_WPA_VERSION_DISABLED; | ||
1481 | break; | ||
1482 | } | ||
1483 | break; | ||
1484 | |||
1485 | case IW_AUTH_DROP_UNENCRYPTED: | ||
1486 | ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); | ||
1487 | if (ret >= 0) | ||
1488 | param->value = r.u > 0 ? 1 : 0; | ||
1489 | break; | ||
1490 | |||
1491 | case IW_AUTH_80211_AUTH_ALG: | ||
1492 | ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); | ||
1493 | if (ret >= 0) { | ||
1494 | switch (r.u) { | ||
1495 | case DOT11_AUTH_OS: | ||
1496 | param->value = IW_AUTH_ALG_OPEN_SYSTEM; | ||
1497 | break; | ||
1498 | case DOT11_AUTH_BOTH: | ||
1499 | case DOT11_AUTH_SK: | ||
1500 | param->value = IW_AUTH_ALG_SHARED_KEY; | ||
1501 | case DOT11_AUTH_NONE: | ||
1502 | default: | ||
1503 | param->value = 0; | ||
1504 | break; | ||
1505 | } | ||
1506 | } | ||
1507 | break; | ||
1508 | |||
1509 | case IW_AUTH_WPA_ENABLED: | ||
1510 | param->value = wpa > 0 ? 1 : 0; | ||
1511 | break; | ||
1512 | |||
1513 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | ||
1514 | ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r); | ||
1515 | if (ret >= 0) | ||
1516 | param->value = r.u > 0 ? 1 : 0; | ||
1517 | break; | ||
1518 | |||
1519 | case IW_AUTH_PRIVACY_INVOKED: | ||
1520 | ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); | ||
1521 | if (ret >= 0) | ||
1522 | param->value = r.u > 0 ? 1 : 0; | ||
1523 | break; | ||
1524 | |||
1525 | default: | ||
1526 | return -EOPNOTSUPP; | ||
1527 | } | ||
1528 | return ret; | ||
1529 | } | ||
1530 | |||
1531 | static int prism54_set_encodeext(struct net_device *ndev, | ||
1532 | struct iw_request_info *info, | ||
1533 | union iwreq_data *wrqu, | ||
1534 | char *extra) | ||
1535 | { | ||
1536 | islpci_private *priv = netdev_priv(ndev); | ||
1537 | struct iw_point *encoding = &wrqu->encoding; | ||
1538 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | ||
1539 | int idx, alg = ext->alg, set_key = 1; | ||
1540 | union oid_res_t r; | ||
1541 | int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; | ||
1542 | int ret = 0; | ||
1543 | |||
1544 | if (islpci_get_state(priv) < PRV_STATE_INIT) | ||
1545 | return 0; | ||
1546 | |||
1547 | /* Determine and validate the key index */ | ||
1548 | idx = (encoding->flags & IW_ENCODE_INDEX) - 1; | ||
1549 | if (idx) { | ||
1550 | if (idx < 0 || idx > 3) | ||
1551 | return -EINVAL; | ||
1552 | } else { | ||
1553 | ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); | ||
1554 | if (ret < 0) | ||
1555 | goto out; | ||
1556 | idx = r.u; | ||
1557 | } | ||
1558 | |||
1559 | if (encoding->flags & IW_ENCODE_DISABLED) | ||
1560 | alg = IW_ENCODE_ALG_NONE; | ||
1561 | |||
1562 | if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { | ||
1563 | /* Only set transmit key index here, actual | ||
1564 | * key is set below if needed. | ||
1565 | */ | ||
1566 | ret = mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, &idx); | ||
1567 | set_key = ext->key_len > 0 ? 1 : 0; | ||
1568 | } | ||
1569 | |||
1570 | if (set_key) { | ||
1571 | struct obj_key key = { DOT11_PRIV_WEP, 0, "" }; | ||
1572 | switch (alg) { | ||
1573 | case IW_ENCODE_ALG_NONE: | ||
1574 | break; | ||
1575 | case IW_ENCODE_ALG_WEP: | ||
1576 | if (ext->key_len > KEY_SIZE_WEP104) { | ||
1577 | ret = -EINVAL; | ||
1578 | goto out; | ||
1579 | } | ||
1580 | if (ext->key_len > KEY_SIZE_WEP40) | ||
1581 | key.length = KEY_SIZE_WEP104; | ||
1582 | else | ||
1583 | key.length = KEY_SIZE_WEP40; | ||
1584 | break; | ||
1585 | case IW_ENCODE_ALG_TKIP: | ||
1586 | if (ext->key_len > KEY_SIZE_TKIP) { | ||
1587 | ret = -EINVAL; | ||
1588 | goto out; | ||
1589 | } | ||
1590 | key.type = DOT11_PRIV_TKIP; | ||
1591 | key.length = KEY_SIZE_TKIP; | ||
1592 | default: | ||
1593 | return -EINVAL; | ||
1594 | } | ||
1595 | |||
1596 | if (key.length) { | ||
1597 | memset(key.key, 0, sizeof(key.key)); | ||
1598 | memcpy(key.key, ext->key, ext->key_len); | ||
1599 | ret = mgt_set_request(priv, DOT11_OID_DEFKEYX, idx, | ||
1600 | &key); | ||
1601 | if (ret < 0) | ||
1602 | goto out; | ||
1603 | } | ||
1604 | } | ||
1605 | |||
1606 | /* Read the flags */ | ||
1607 | if (encoding->flags & IW_ENCODE_DISABLED) { | ||
1608 | /* Encoding disabled, | ||
1609 | * authen = DOT11_AUTH_OS; | ||
1610 | * invoke = 0; | ||
1611 | * exunencrypt = 0; */ | ||
1612 | } | ||
1613 | if (encoding->flags & IW_ENCODE_OPEN) { | ||
1614 | /* Encode but accept non-encoded packets. No auth */ | ||
1615 | invoke = 1; | ||
1616 | } | ||
1617 | if (encoding->flags & IW_ENCODE_RESTRICTED) { | ||
1618 | /* Refuse non-encoded packets. Auth */ | ||
1619 | authen = DOT11_AUTH_BOTH; | ||
1620 | invoke = 1; | ||
1621 | exunencrypt = 1; | ||
1622 | } | ||
1623 | |||
1624 | /* do the change if requested */ | ||
1625 | if (encoding->flags & IW_ENCODE_MODE) { | ||
1626 | ret = mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, | ||
1627 | &authen); | ||
1628 | ret = mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, | ||
1629 | &invoke); | ||
1630 | ret = mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, | ||
1631 | &exunencrypt); | ||
1632 | } | ||
1633 | |||
1634 | out: | ||
1635 | return ret; | ||
1636 | } | ||
1637 | |||
1638 | |||
1639 | static int prism54_get_encodeext(struct net_device *ndev, | ||
1640 | struct iw_request_info *info, | ||
1641 | union iwreq_data *wrqu, | ||
1642 | char *extra) | ||
1643 | { | ||
1644 | islpci_private *priv = netdev_priv(ndev); | ||
1645 | struct iw_point *encoding = &wrqu->encoding; | ||
1646 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | ||
1647 | int idx, max_key_len; | ||
1648 | union oid_res_t r; | ||
1649 | int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0, wpa = 0; | ||
1650 | int ret = 0; | ||
1651 | |||
1652 | if (islpci_get_state(priv) < PRV_STATE_INIT) | ||
1653 | return 0; | ||
1654 | |||
1655 | /* first get the flags */ | ||
1656 | ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); | ||
1657 | authen = r.u; | ||
1658 | ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); | ||
1659 | invoke = r.u; | ||
1660 | ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); | ||
1661 | exunencrypt = r.u; | ||
1662 | if (ret < 0) | ||
1663 | goto out; | ||
1664 | |||
1665 | max_key_len = encoding->length - sizeof(*ext); | ||
1666 | if (max_key_len < 0) | ||
1667 | return -EINVAL; | ||
1668 | |||
1669 | idx = (encoding->flags & IW_ENCODE_INDEX) - 1; | ||
1670 | if (idx) { | ||
1671 | if (idx < 0 || idx > 3) | ||
1672 | return -EINVAL; | ||
1673 | } else { | ||
1674 | ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); | ||
1675 | if (ret < 0) | ||
1676 | goto out; | ||
1677 | idx = r.u; | ||
1678 | } | ||
1679 | |||
1680 | encoding->flags = idx + 1; | ||
1681 | memset(ext, 0, sizeof(*ext)); | ||
1682 | |||
1683 | switch (authen) { | ||
1684 | case DOT11_AUTH_BOTH: | ||
1685 | case DOT11_AUTH_SK: | ||
1686 | wrqu->encoding.flags |= IW_ENCODE_RESTRICTED; | ||
1687 | case DOT11_AUTH_OS: | ||
1688 | default: | ||
1689 | wrqu->encoding.flags |= IW_ENCODE_OPEN; | ||
1690 | break; | ||
1691 | } | ||
1692 | |||
1693 | down_write(&priv->mib_sem); | ||
1694 | wpa = priv->wpa; | ||
1695 | up_write(&priv->mib_sem); | ||
1696 | |||
1697 | if (authen == DOT11_AUTH_OS && !exunencrypt && !invoke && !wpa) { | ||
1698 | /* No encryption */ | ||
1699 | ext->alg = IW_ENCODE_ALG_NONE; | ||
1700 | ext->key_len = 0; | ||
1701 | wrqu->encoding.flags |= IW_ENCODE_DISABLED; | ||
1702 | } else { | ||
1703 | struct obj_key *key; | ||
1704 | |||
1705 | ret = mgt_get_request(priv, DOT11_OID_DEFKEYX, idx, NULL, &r); | ||
1706 | if (ret < 0) | ||
1707 | goto out; | ||
1708 | key = r.ptr; | ||
1709 | if (max_key_len < key->length) { | ||
1710 | ret = -E2BIG; | ||
1711 | goto out; | ||
1712 | } | ||
1713 | memcpy(ext->key, key->key, key->length); | ||
1714 | ext->key_len = key->length; | ||
1715 | |||
1716 | switch (key->type) { | ||
1717 | case DOT11_PRIV_TKIP: | ||
1718 | ext->alg = IW_ENCODE_ALG_TKIP; | ||
1719 | break; | ||
1720 | default: | ||
1721 | case DOT11_PRIV_WEP: | ||
1722 | ext->alg = IW_ENCODE_ALG_WEP; | ||
1723 | break; | ||
1724 | } | ||
1725 | wrqu->encoding.flags |= IW_ENCODE_ENABLED; | ||
1726 | } | ||
1727 | |||
1728 | out: | ||
1729 | return ret; | ||
1730 | } | ||
1731 | |||
1732 | |||
1213 | static int | 1733 | static int |
1214 | prism54_reset(struct net_device *ndev, struct iw_request_info *info, | 1734 | prism54_reset(struct net_device *ndev, struct iw_request_info *info, |
1215 | __u32 * uwrq, char *extra) | 1735 | __u32 * uwrq, char *extra) |
@@ -1591,8 +2111,8 @@ static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 }; | |||
1591 | #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" | 2111 | #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" |
1592 | 2112 | ||
1593 | static void | 2113 | static void |
1594 | prism54_wpa_ie_add(islpci_private *priv, u8 *bssid, | 2114 | prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid, |
1595 | u8 *wpa_ie, size_t wpa_ie_len) | 2115 | u8 *wpa_ie, size_t wpa_ie_len) |
1596 | { | 2116 | { |
1597 | struct list_head *ptr; | 2117 | struct list_head *ptr; |
1598 | struct islpci_bss_wpa_ie *bss = NULL; | 2118 | struct islpci_bss_wpa_ie *bss = NULL; |
@@ -1658,7 +2178,7 @@ prism54_wpa_ie_add(islpci_private *priv, u8 *bssid, | |||
1658 | } | 2178 | } |
1659 | 2179 | ||
1660 | static size_t | 2180 | static size_t |
1661 | prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie) | 2181 | prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie) |
1662 | { | 2182 | { |
1663 | struct list_head *ptr; | 2183 | struct list_head *ptr; |
1664 | struct islpci_bss_wpa_ie *bss = NULL; | 2184 | struct islpci_bss_wpa_ie *bss = NULL; |
@@ -1683,14 +2203,14 @@ prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie) | |||
1683 | } | 2203 | } |
1684 | 2204 | ||
1685 | void | 2205 | void |
1686 | prism54_wpa_ie_init(islpci_private *priv) | 2206 | prism54_wpa_bss_ie_init(islpci_private *priv) |
1687 | { | 2207 | { |
1688 | INIT_LIST_HEAD(&priv->bss_wpa_list); | 2208 | INIT_LIST_HEAD(&priv->bss_wpa_list); |
1689 | sema_init(&priv->wpa_sem, 1); | 2209 | sema_init(&priv->wpa_sem, 1); |
1690 | } | 2210 | } |
1691 | 2211 | ||
1692 | void | 2212 | void |
1693 | prism54_wpa_ie_clean(islpci_private *priv) | 2213 | prism54_wpa_bss_ie_clean(islpci_private *priv) |
1694 | { | 2214 | { |
1695 | struct list_head *ptr, *n; | 2215 | struct list_head *ptr, *n; |
1696 | 2216 | ||
@@ -1722,7 +2242,7 @@ prism54_process_bss_data(islpci_private *priv, u32 oid, u8 *addr, | |||
1722 | } | 2242 | } |
1723 | if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 && | 2243 | if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 && |
1724 | memcmp(pos + 2, wpa_oid, 4) == 0) { | 2244 | memcmp(pos + 2, wpa_oid, 4) == 0) { |
1725 | prism54_wpa_ie_add(priv, addr, pos, pos[1] + 2); | 2245 | prism54_wpa_bss_ie_add(priv, addr, pos, pos[1] + 2); |
1726 | return; | 2246 | return; |
1727 | } | 2247 | } |
1728 | pos += 2 + pos[1]; | 2248 | pos += 2 + pos[1]; |
@@ -1879,7 +2399,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, | |||
1879 | send_formatted_event(priv, "Associate request (ex)", mlme, 1); | 2399 | send_formatted_event(priv, "Associate request (ex)", mlme, 1); |
1880 | 2400 | ||
1881 | if (priv->iw_mode != IW_MODE_MASTER | 2401 | if (priv->iw_mode != IW_MODE_MASTER |
1882 | && mlmeex->state != DOT11_STATE_AUTHING) | 2402 | && mlmeex->state != DOT11_STATE_ASSOCING) |
1883 | break; | 2403 | break; |
1884 | 2404 | ||
1885 | confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); | 2405 | confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); |
@@ -1893,7 +2413,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, | |||
1893 | confirm->state = 0; /* not used */ | 2413 | confirm->state = 0; /* not used */ |
1894 | confirm->code = 0; | 2414 | confirm->code = 0; |
1895 | 2415 | ||
1896 | wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie); | 2416 | wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie); |
1897 | 2417 | ||
1898 | if (!wpa_ie_len) { | 2418 | if (!wpa_ie_len) { |
1899 | printk(KERN_DEBUG "No WPA IE found from " | 2419 | printk(KERN_DEBUG "No WPA IE found from " |
@@ -1937,7 +2457,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, | |||
1937 | confirm->state = 0; /* not used */ | 2457 | confirm->state = 0; /* not used */ |
1938 | confirm->code = 0; | 2458 | confirm->code = 0; |
1939 | 2459 | ||
1940 | wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie); | 2460 | wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie); |
1941 | 2461 | ||
1942 | if (!wpa_ie_len) { | 2462 | if (!wpa_ie_len) { |
1943 | printk(KERN_DEBUG "No WPA IE found from " | 2463 | printk(KERN_DEBUG "No WPA IE found from " |
@@ -2553,6 +3073,15 @@ static const iw_handler prism54_handler[] = { | |||
2553 | (iw_handler) prism54_get_encode, /* SIOCGIWENCODE */ | 3073 | (iw_handler) prism54_get_encode, /* SIOCGIWENCODE */ |
2554 | (iw_handler) NULL, /* SIOCSIWPOWER */ | 3074 | (iw_handler) NULL, /* SIOCSIWPOWER */ |
2555 | (iw_handler) NULL, /* SIOCGIWPOWER */ | 3075 | (iw_handler) NULL, /* SIOCGIWPOWER */ |
3076 | NULL, /* -- hole -- */ | ||
3077 | NULL, /* -- hole -- */ | ||
3078 | (iw_handler) prism54_set_genie, /* SIOCSIWGENIE */ | ||
3079 | (iw_handler) prism54_get_genie, /* SIOCGIWGENIE */ | ||
3080 | (iw_handler) prism54_set_auth, /* SIOCSIWAUTH */ | ||
3081 | (iw_handler) prism54_get_auth, /* SIOCGIWAUTH */ | ||
3082 | (iw_handler) prism54_set_encodeext, /* SIOCSIWENCODEEXT */ | ||
3083 | (iw_handler) prism54_get_encodeext, /* SIOCGIWENCODEEXT */ | ||
3084 | NULL, /* SIOCSIWPMKSA */ | ||
2556 | }; | 3085 | }; |
2557 | 3086 | ||
2558 | /* The low order bit identify a SET (0) or a GET (1) ioctl. */ | 3087 | /* The low order bit identify a SET (0) or a GET (1) ioctl. */ |
diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h index 46d5cde80c85..65f33acd0a42 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.h +++ b/drivers/net/wireless/prism54/isl_ioctl.h | |||
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | #include <net/iw_handler.h> /* New driver API */ | 28 | #include <net/iw_handler.h> /* New driver API */ |
29 | 29 | ||
30 | #define SUPPORTED_WIRELESS_EXT 16 | 30 | #define SUPPORTED_WIRELESS_EXT 19 |
31 | 31 | ||
32 | void prism54_mib_init(islpci_private *); | 32 | void prism54_mib_init(islpci_private *); |
33 | 33 | ||
@@ -39,8 +39,8 @@ void prism54_acl_clean(struct islpci_acl *); | |||
39 | 39 | ||
40 | void prism54_process_trap(void *); | 40 | void prism54_process_trap(void *); |
41 | 41 | ||
42 | void prism54_wpa_ie_init(islpci_private *priv); | 42 | void prism54_wpa_bss_ie_init(islpci_private *priv); |
43 | void prism54_wpa_ie_clean(islpci_private *priv); | 43 | void prism54_wpa_bss_ie_clean(islpci_private *priv); |
44 | 44 | ||
45 | int prism54_set_mac_address(struct net_device *, void *); | 45 | int prism54_set_mac_address(struct net_device *, void *); |
46 | 46 | ||
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 5ddf29599032..ab3c5a27efd9 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c | |||
@@ -715,7 +715,7 @@ islpci_alloc_memory(islpci_private *priv) | |||
715 | } | 715 | } |
716 | 716 | ||
717 | prism54_acl_init(&priv->acl); | 717 | prism54_acl_init(&priv->acl); |
718 | prism54_wpa_ie_init(priv); | 718 | prism54_wpa_bss_ie_init(priv); |
719 | if (mgt_init(priv)) | 719 | if (mgt_init(priv)) |
720 | goto out_free; | 720 | goto out_free; |
721 | 721 | ||
@@ -774,7 +774,7 @@ islpci_free_memory(islpci_private *priv) | |||
774 | 774 | ||
775 | /* Free the acces control list and the WPA list */ | 775 | /* Free the acces control list and the WPA list */ |
776 | prism54_acl_clean(&priv->acl); | 776 | prism54_acl_clean(&priv->acl); |
777 | prism54_wpa_ie_clean(priv); | 777 | prism54_wpa_bss_ie_clean(priv); |
778 | mgt_clean(priv); | 778 | mgt_clean(priv); |
779 | 779 | ||
780 | return 0; | 780 | return 0; |
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index 07053165e4c5..5049f37455b1 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h | |||
@@ -179,6 +179,8 @@ typedef struct { | |||
179 | struct list_head bss_wpa_list; | 179 | struct list_head bss_wpa_list; |
180 | int num_bss_wpa; | 180 | int num_bss_wpa; |
181 | struct semaphore wpa_sem; | 181 | struct semaphore wpa_sem; |
182 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
183 | size_t wpa_ie_len; | ||
182 | 184 | ||
183 | struct work_struct reset_task; | 185 | struct work_struct reset_task; |
184 | int reset_task_pending; | 186 | int reset_task_pending; |
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index 09fc17a0f029..f692dccf0d07 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c | |||
@@ -313,7 +313,7 @@ prism54_module_init(void) | |||
313 | 313 | ||
314 | __bug_on_wrong_struct_sizes (); | 314 | __bug_on_wrong_struct_sizes (); |
315 | 315 | ||
316 | return pci_module_init(&prism54_driver); | 316 | return pci_register_driver(&prism54_driver); |
317 | } | 317 | } |
318 | 318 | ||
319 | /* by the time prism54_module_exit() terminates, as a postcondition | 319 | /* by the time prism54_module_exit() terminates, as a postcondition |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 61b83a5e737a..4574290f971f 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -52,8 +52,8 @@ | |||
52 | #include <pcmcia/ds.h> | 52 | #include <pcmcia/ds.h> |
53 | #include <pcmcia/mem_op.h> | 53 | #include <pcmcia/mem_op.h> |
54 | 54 | ||
55 | #include <net/ieee80211.h> | ||
56 | #include <linux/wireless.h> | 55 | #include <linux/wireless.h> |
56 | #include <net/iw_handler.h> | ||
57 | 57 | ||
58 | #include <asm/io.h> | 58 | #include <asm/io.h> |
59 | #include <asm/system.h> | 59 | #include <asm/system.h> |
@@ -99,7 +99,7 @@ static int ray_dev_config(struct net_device *dev, struct ifmap *map); | |||
99 | static struct net_device_stats *ray_get_stats(struct net_device *dev); | 99 | static struct net_device_stats *ray_get_stats(struct net_device *dev); |
100 | static int ray_dev_init(struct net_device *dev); | 100 | static int ray_dev_init(struct net_device *dev); |
101 | 101 | ||
102 | static struct ethtool_ops netdev_ethtool_ops; | 102 | static const struct ethtool_ops netdev_ethtool_ops; |
103 | 103 | ||
104 | static int ray_open(struct net_device *dev); | 104 | static int ray_open(struct net_device *dev); |
105 | static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev); | 105 | static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev); |
@@ -1092,7 +1092,7 @@ static void netdev_get_drvinfo(struct net_device *dev, | |||
1092 | strcpy(info->driver, "ray_cs"); | 1092 | strcpy(info->driver, "ray_cs"); |
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | static struct ethtool_ops netdev_ethtool_ops = { | 1095 | static const struct ethtool_ops netdev_ethtool_ops = { |
1096 | .get_drvinfo = netdev_get_drvinfo, | 1096 | .get_drvinfo = netdev_get_drvinfo, |
1097 | }; | 1097 | }; |
1098 | 1098 | ||
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 561250f73fd3..0065f057bb1c 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c | |||
@@ -1837,7 +1837,7 @@ static void wl_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | |||
1837 | strncpy(info->driver, "wavelan_cs", sizeof(info->driver)-1); | 1837 | strncpy(info->driver, "wavelan_cs", sizeof(info->driver)-1); |
1838 | } | 1838 | } |
1839 | 1839 | ||
1840 | static struct ethtool_ops ops = { | 1840 | static const struct ethtool_ops ops = { |
1841 | .get_drvinfo = wl_get_drvinfo | 1841 | .get_drvinfo = wl_get_drvinfo |
1842 | }; | 1842 | }; |
1843 | 1843 | ||
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index c03e400facee..e0d294c12970 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -1464,7 +1464,7 @@ static void wl3501_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i | |||
1464 | strlcpy(info->driver, wl3501_dev_info, sizeof(info->driver)); | 1464 | strlcpy(info->driver, wl3501_dev_info, sizeof(info->driver)); |
1465 | } | 1465 | } |
1466 | 1466 | ||
1467 | static struct ethtool_ops ops = { | 1467 | static const struct ethtool_ops ops = { |
1468 | .get_drvinfo = wl3501_get_drvinfo | 1468 | .get_drvinfo = wl3501_get_drvinfo |
1469 | }; | 1469 | }; |
1470 | 1470 | ||
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile index 500314fc74d2..6603ad5be63d 100644 --- a/drivers/net/wireless/zd1211rw/Makefile +++ b/drivers/net/wireless/zd1211rw/Makefile | |||
@@ -3,6 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o | |||
3 | zd1211rw-objs := zd_chip.o zd_ieee80211.o \ | 3 | zd1211rw-objs := zd_chip.o zd_ieee80211.o \ |
4 | zd_mac.o zd_netdev.o \ | 4 | zd_mac.o zd_netdev.o \ |
5 | zd_rf_al2230.o zd_rf_rf2959.o \ | 5 | zd_rf_al2230.o zd_rf_rf2959.o \ |
6 | zd_rf_al7230b.o \ | ||
6 | zd_rf.o zd_usb.o zd_util.o | 7 | zd_rf.o zd_usb.o zd_util.o |
7 | 8 | ||
8 | ifeq ($(CONFIG_ZD1211RW_DEBUG),y) | 9 | ifeq ($(CONFIG_ZD1211RW_DEBUG),y) |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index aa792821854e..7c4e32cf0d47 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -42,12 +42,11 @@ void zd_chip_init(struct zd_chip *chip, | |||
42 | 42 | ||
43 | void zd_chip_clear(struct zd_chip *chip) | 43 | void zd_chip_clear(struct zd_chip *chip) |
44 | { | 44 | { |
45 | mutex_lock(&chip->mutex); | 45 | ZD_ASSERT(!mutex_is_locked(&chip->mutex)); |
46 | zd_usb_clear(&chip->usb); | 46 | zd_usb_clear(&chip->usb); |
47 | zd_rf_clear(&chip->rf); | 47 | zd_rf_clear(&chip->rf); |
48 | mutex_unlock(&chip->mutex); | ||
49 | mutex_destroy(&chip->mutex); | 48 | mutex_destroy(&chip->mutex); |
50 | memset(chip, 0, sizeof(*chip)); | 49 | ZD_MEMCLEAR(chip, sizeof(*chip)); |
51 | } | 50 | } |
52 | 51 | ||
53 | static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size) | 52 | static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size) |
@@ -68,10 +67,11 @@ static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size) | |||
68 | i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i); | 67 | i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i); |
69 | i += scnprintf(buffer+i, size-i, " "); | 68 | i += scnprintf(buffer+i, size-i, " "); |
70 | i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i); | 69 | i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i); |
71 | i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c", chip->pa_type, | 70 | i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c", chip->pa_type, |
72 | chip->patch_cck_gain ? 'g' : '-', | 71 | chip->patch_cck_gain ? 'g' : '-', |
73 | chip->patch_cr157 ? '7' : '-', | 72 | chip->patch_cr157 ? '7' : '-', |
74 | chip->patch_6m_band_edge ? '6' : '-'); | 73 | chip->patch_6m_band_edge ? '6' : '-', |
74 | chip->new_phy_layout ? 'N' : '-'); | ||
75 | return i; | 75 | return i; |
76 | } | 76 | } |
77 | 77 | ||
@@ -330,13 +330,14 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type) | |||
330 | chip->patch_cck_gain = (value >> 8) & 0x1; | 330 | chip->patch_cck_gain = (value >> 8) & 0x1; |
331 | chip->patch_cr157 = (value >> 13) & 0x1; | 331 | chip->patch_cr157 = (value >> 13) & 0x1; |
332 | chip->patch_6m_band_edge = (value >> 21) & 0x1; | 332 | chip->patch_6m_band_edge = (value >> 21) & 0x1; |
333 | chip->new_phy_layout = (value >> 31) & 0x1; | ||
333 | 334 | ||
334 | dev_dbg_f(zd_chip_dev(chip), | 335 | dev_dbg_f(zd_chip_dev(chip), |
335 | "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " | 336 | "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " |
336 | "patch 6M %d\n", | 337 | "patch 6M %d new PHY %d\n", |
337 | zd_rf_name(*rf_type), *rf_type, | 338 | zd_rf_name(*rf_type), *rf_type, |
338 | chip->pa_type, chip->patch_cck_gain, | 339 | chip->pa_type, chip->patch_cck_gain, |
339 | chip->patch_cr157, chip->patch_6m_band_edge); | 340 | chip->patch_cr157, chip->patch_6m_band_edge, chip->new_phy_layout); |
340 | return 0; | 341 | return 0; |
341 | error: | 342 | error: |
342 | *rf_type = 0; | 343 | *rf_type = 0; |
@@ -344,6 +345,7 @@ error: | |||
344 | chip->patch_cck_gain = 0; | 345 | chip->patch_cck_gain = 0; |
345 | chip->patch_cr157 = 0; | 346 | chip->patch_cr157 = 0; |
346 | chip->patch_6m_band_edge = 0; | 347 | chip->patch_6m_band_edge = 0; |
348 | chip->new_phy_layout = 0; | ||
347 | return r; | 349 | return r; |
348 | } | 350 | } |
349 | 351 | ||
@@ -717,7 +719,7 @@ static int zd1211b_hw_reset_phy(struct zd_chip *chip) | |||
717 | { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, | 719 | { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, |
718 | { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, | 720 | { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, |
719 | { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, | 721 | { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, |
720 | { CR30, 0x49 }, /* jointly decoder, no ASIC */ | 722 | { CR30, 0x4b }, /* ASIC/FWT, no jointly decoder */ |
721 | { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, | 723 | { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, |
722 | { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, | 724 | { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, |
723 | { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, | 725 | { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, |
@@ -807,7 +809,6 @@ static int zd1211_hw_init_hmac(struct zd_chip *chip) | |||
807 | { CR_ACK_TIMEOUT_EXT, 0x80 }, | 809 | { CR_ACK_TIMEOUT_EXT, 0x80 }, |
808 | { CR_ADDA_PWR_DWN, 0x00 }, | 810 | { CR_ADDA_PWR_DWN, 0x00 }, |
809 | { CR_ACK_TIME_80211, 0x100 }, | 811 | { CR_ACK_TIME_80211, 0x100 }, |
810 | { CR_IFS_VALUE, 0x547c032 }, | ||
811 | { CR_RX_PE_DELAY, 0x70 }, | 812 | { CR_RX_PE_DELAY, 0x70 }, |
812 | { CR_PS_CTRL, 0x10000000 }, | 813 | { CR_PS_CTRL, 0x10000000 }, |
813 | { CR_RTS_CTS_RATE, 0x02030203 }, | 814 | { CR_RTS_CTS_RATE, 0x02030203 }, |
@@ -854,11 +855,10 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip) | |||
854 | { CR_ACK_TIMEOUT_EXT, 0x80 }, | 855 | { CR_ACK_TIMEOUT_EXT, 0x80 }, |
855 | { CR_ADDA_PWR_DWN, 0x00 }, | 856 | { CR_ADDA_PWR_DWN, 0x00 }, |
856 | { CR_ACK_TIME_80211, 0x100 }, | 857 | { CR_ACK_TIME_80211, 0x100 }, |
857 | { CR_IFS_VALUE, 0x547c032 }, | ||
858 | { CR_RX_PE_DELAY, 0x70 }, | 858 | { CR_RX_PE_DELAY, 0x70 }, |
859 | { CR_PS_CTRL, 0x10000000 }, | 859 | { CR_PS_CTRL, 0x10000000 }, |
860 | { CR_RTS_CTS_RATE, 0x02030203 }, | 860 | { CR_RTS_CTS_RATE, 0x02030203 }, |
861 | { CR_RX_THRESHOLD, 0x000c0640 }, | 861 | { CR_RX_THRESHOLD, 0x000c0eff, }, |
862 | { CR_AFTER_PNP, 0x1 }, | 862 | { CR_AFTER_PNP, 0x1 }, |
863 | { CR_WEP_PROTECT, 0x114 }, | 863 | { CR_WEP_PROTECT, 0x114 }, |
864 | }; | 864 | }; |
@@ -970,10 +970,15 @@ static int hw_init(struct zd_chip *chip) | |||
970 | r = hw_init_hmac(chip); | 970 | r = hw_init_hmac(chip); |
971 | if (r) | 971 | if (r) |
972 | return r; | 972 | return r; |
973 | r = set_beacon_interval(chip, 100); | 973 | |
974 | /* Although the vendor driver defaults to a different value during | ||
975 | * init, it overwrites the IFS value with the following every time | ||
976 | * the channel changes. We should aim to be more intelligent... */ | ||
977 | r = zd_iowrite32_locked(chip, IFS_VALUE_DEFAULT, CR_IFS_VALUE); | ||
974 | if (r) | 978 | if (r) |
975 | return r; | 979 | return r; |
976 | return 0; | 980 | |
981 | return set_beacon_interval(chip, 100); | ||
977 | } | 982 | } |
978 | 983 | ||
979 | #ifdef DEBUG | 984 | #ifdef DEBUG |
@@ -1644,3 +1649,34 @@ int zd_rfwritev_locked(struct zd_chip *chip, | |||
1644 | 1649 | ||
1645 | return 0; | 1650 | return 0; |
1646 | } | 1651 | } |
1652 | |||
1653 | /* | ||
1654 | * We can optionally program the RF directly through CR regs, if supported by | ||
1655 | * the hardware. This is much faster than the older method. | ||
1656 | */ | ||
1657 | int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value) | ||
1658 | { | ||
1659 | struct zd_ioreq16 ioreqs[] = { | ||
1660 | { CR244, (value >> 16) & 0xff }, | ||
1661 | { CR243, (value >> 8) & 0xff }, | ||
1662 | { CR242, value & 0xff }, | ||
1663 | }; | ||
1664 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | ||
1665 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
1666 | } | ||
1667 | |||
1668 | int zd_rfwritev_cr_locked(struct zd_chip *chip, | ||
1669 | const u32 *values, unsigned int count) | ||
1670 | { | ||
1671 | int r; | ||
1672 | unsigned int i; | ||
1673 | |||
1674 | for (i = 0; i < count; i++) { | ||
1675 | r = zd_rfwrite_cr_locked(chip, values[i]); | ||
1676 | if (r) | ||
1677 | return r; | ||
1678 | } | ||
1679 | |||
1680 | return 0; | ||
1681 | } | ||
1682 | |||
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 069d2b467339..4b1250859897 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h | |||
@@ -473,7 +473,15 @@ | |||
473 | 473 | ||
474 | #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) | 474 | #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) |
475 | #define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694) | 475 | #define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694) |
476 | |||
476 | #define CR_IFS_VALUE CTL_REG(0x0698) | 477 | #define CR_IFS_VALUE CTL_REG(0x0698) |
478 | #define IFS_VALUE_DIFS_SH 0 | ||
479 | #define IFS_VALUE_EIFS_SH 12 | ||
480 | #define IFS_VALUE_SIFS_SH 24 | ||
481 | #define IFS_VALUE_DEFAULT (( 50 << IFS_VALUE_DIFS_SH) | \ | ||
482 | (1148 << IFS_VALUE_EIFS_SH) | \ | ||
483 | ( 10 << IFS_VALUE_SIFS_SH)) | ||
484 | |||
477 | #define CR_RX_TIME_OUT CTL_REG(0x069C) | 485 | #define CR_RX_TIME_OUT CTL_REG(0x069C) |
478 | #define CR_TOTAL_RX_FRM CTL_REG(0x06A0) | 486 | #define CR_TOTAL_RX_FRM CTL_REG(0x06A0) |
479 | #define CR_CRC32_CNT CTL_REG(0x06A4) | 487 | #define CR_CRC32_CNT CTL_REG(0x06A4) |
@@ -630,6 +638,7 @@ enum { | |||
630 | LOAD_CODE_SIZE = 0xe, /* words */ | 638 | LOAD_CODE_SIZE = 0xe, /* words */ |
631 | LOAD_VECT_SIZE = 0x10000 - 0xfff7, /* words */ | 639 | LOAD_VECT_SIZE = 0x10000 - 0xfff7, /* words */ |
632 | EEPROM_REGS_OFFSET = LOAD_CODE_SIZE + LOAD_VECT_SIZE, | 640 | EEPROM_REGS_OFFSET = LOAD_CODE_SIZE + LOAD_VECT_SIZE, |
641 | EEPROM_REGS_SIZE = 0x7e, /* words */ | ||
633 | E2P_BASE_OFFSET = EEPROM_START_OFFSET + | 642 | E2P_BASE_OFFSET = EEPROM_START_OFFSET + |
634 | EEPROM_REGS_OFFSET, | 643 | EEPROM_REGS_OFFSET, |
635 | }; | 644 | }; |
@@ -655,7 +664,7 @@ struct zd_chip { | |||
655 | /* SetPointOFDM in the vendor driver */ | 664 | /* SetPointOFDM in the vendor driver */ |
656 | u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT]; | 665 | u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT]; |
657 | u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, | 666 | u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, |
658 | is_zd1211b:1; | 667 | new_phy_layout:1, is_zd1211b:1; |
659 | }; | 668 | }; |
660 | 669 | ||
661 | static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb) | 670 | static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb) |
@@ -739,8 +748,12 @@ static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits) | |||
739 | return zd_usb_rfwrite(&chip->usb, value, bits); | 748 | return zd_usb_rfwrite(&chip->usb, value, bits); |
740 | } | 749 | } |
741 | 750 | ||
751 | int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value); | ||
752 | |||
742 | int zd_rfwritev_locked(struct zd_chip *chip, | 753 | int zd_rfwritev_locked(struct zd_chip *chip, |
743 | const u32* values, unsigned int count, u8 bits); | 754 | const u32* values, unsigned int count, u8 bits); |
755 | int zd_rfwritev_cr_locked(struct zd_chip *chip, | ||
756 | const u32* values, unsigned int count); | ||
744 | 757 | ||
745 | /* Locking functions for reading and writing registers. | 758 | /* Locking functions for reading and writing registers. |
746 | * The different parameters are intentional. | 759 | * The different parameters are intentional. |
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h index 465906812fc4..a13ec72eb304 100644 --- a/drivers/net/wireless/zd1211rw/zd_def.h +++ b/drivers/net/wireless/zd1211rw/zd_def.h | |||
@@ -45,4 +45,10 @@ do { \ | |||
45 | # define ZD_ASSERT(x) do { } while (0) | 45 | # define ZD_ASSERT(x) do { } while (0) |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #ifdef DEBUG | ||
49 | # define ZD_MEMCLEAR(pointer, size) memset((pointer), 0xff, (size)) | ||
50 | #else | ||
51 | # define ZD_MEMCLEAR(pointer, size) do { } while (0) | ||
52 | #endif | ||
53 | |||
48 | #endif /* _ZD_DEF_H */ | 54 | #endif /* _ZD_DEF_H */ |
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h index 36329890dfec..f63245b0d966 100644 --- a/drivers/net/wireless/zd1211rw/zd_ieee80211.h +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.h | |||
@@ -64,7 +64,7 @@ struct cck_plcp_header { | |||
64 | u8 service; | 64 | u8 service; |
65 | __le16 length; | 65 | __le16 length; |
66 | __le16 crc16; | 66 | __le16 crc16; |
67 | } __attribute__((packed)); | 67 | }; |
68 | 68 | ||
69 | static inline u8 zd_cck_plcp_header_rate(const struct cck_plcp_header *header) | 69 | static inline u8 zd_cck_plcp_header_rate(const struct cck_plcp_header *header) |
70 | { | 70 | { |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a9bd80a08613..1989f1c05fbe 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -127,11 +127,9 @@ out: | |||
127 | 127 | ||
128 | void zd_mac_clear(struct zd_mac *mac) | 128 | void zd_mac_clear(struct zd_mac *mac) |
129 | { | 129 | { |
130 | /* Aquire the lock. */ | ||
131 | spin_lock(&mac->lock); | ||
132 | spin_unlock(&mac->lock); | ||
133 | zd_chip_clear(&mac->chip); | 130 | zd_chip_clear(&mac->chip); |
134 | memset(mac, 0, sizeof(*mac)); | 131 | ZD_ASSERT(!spin_is_locked(&mac->lock)); |
132 | ZD_MEMCLEAR(mac, sizeof(struct zd_mac)); | ||
135 | } | 133 | } |
136 | 134 | ||
137 | static int reset_mode(struct zd_mac *mac) | 135 | static int reset_mode(struct zd_mac *mac) |
@@ -716,7 +714,7 @@ struct zd_rt_hdr { | |||
716 | u8 rt_rate; | 714 | u8 rt_rate; |
717 | u16 rt_channel; | 715 | u16 rt_channel; |
718 | u16 rt_chbitmask; | 716 | u16 rt_chbitmask; |
719 | } __attribute__((packed)); | 717 | }; |
720 | 718 | ||
721 | static void fill_rt_header(void *buffer, struct zd_mac *mac, | 719 | static void fill_rt_header(void *buffer, struct zd_mac *mac, |
722 | const struct ieee80211_rx_stats *stats, | 720 | const struct ieee80211_rx_stats *stats, |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index b3ba49b84634..29b51fd7d4e5 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
@@ -82,7 +82,7 @@ struct zd_ctrlset { | |||
82 | struct rx_length_info { | 82 | struct rx_length_info { |
83 | __le16 length[3]; | 83 | __le16 length[3]; |
84 | __le16 tag; | 84 | __le16 tag; |
85 | } __attribute__((packed)); | 85 | }; |
86 | 86 | ||
87 | #define RX_LENGTH_INFO_TAG 0x697e | 87 | #define RX_LENGTH_INFO_TAG 0x697e |
88 | 88 | ||
@@ -93,7 +93,7 @@ struct rx_status { | |||
93 | u8 signal_quality_ofdm; | 93 | u8 signal_quality_ofdm; |
94 | u8 decryption_type; | 94 | u8 decryption_type; |
95 | u8 frame_status; | 95 | u8 frame_status; |
96 | } __attribute__((packed)); | 96 | }; |
97 | 97 | ||
98 | /* rx_status field decryption_type */ | 98 | /* rx_status field decryption_type */ |
99 | #define ZD_RX_NO_WEP 0 | 99 | #define ZD_RX_NO_WEP 0 |
@@ -123,9 +123,9 @@ enum mac_flags { | |||
123 | #define ZD_MAC_STATS_BUFFER_SIZE 16 | 123 | #define ZD_MAC_STATS_BUFFER_SIZE 16 |
124 | 124 | ||
125 | struct zd_mac { | 125 | struct zd_mac { |
126 | struct net_device *netdev; | ||
127 | struct zd_chip chip; | 126 | struct zd_chip chip; |
128 | spinlock_t lock; | 127 | spinlock_t lock; |
128 | struct net_device *netdev; | ||
129 | /* Unlocked reading possible */ | 129 | /* Unlocked reading possible */ |
130 | struct iw_statistics iw_stats; | 130 | struct iw_statistics iw_stats; |
131 | unsigned int stats_count; | 131 | unsigned int stats_count; |
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c index 9df232c2c863..440ef24b5fd1 100644 --- a/drivers/net/wireless/zd1211rw/zd_netdev.c +++ b/drivers/net/wireless/zd1211rw/zd_netdev.c | |||
@@ -72,10 +72,18 @@ static int iw_get_name(struct net_device *netdev, | |||
72 | struct iw_request_info *info, | 72 | struct iw_request_info *info, |
73 | union iwreq_data *req, char *extra) | 73 | union iwreq_data *req, char *extra) |
74 | { | 74 | { |
75 | /* FIXME: check whether 802.11a will also supported, add also | 75 | /* FIXME: check whether 802.11a will also supported */ |
76 | * zd1211B, if we support it. | 76 | strlcpy(req->name, "IEEE 802.11b/g", IFNAMSIZ); |
77 | */ | 77 | return 0; |
78 | strlcpy(req->name, "802.11g zd1211", IFNAMSIZ); | 78 | } |
79 | |||
80 | static int iw_get_nick(struct net_device *netdev, | ||
81 | struct iw_request_info *info, | ||
82 | union iwreq_data *req, char *extra) | ||
83 | { | ||
84 | strcpy(extra, "zd1211"); | ||
85 | req->data.length = strlen(extra) + 1; | ||
86 | req->data.flags = 1; | ||
79 | return 0; | 87 | return 0; |
80 | } | 88 | } |
81 | 89 | ||
@@ -181,6 +189,7 @@ static int iw_get_encodeext(struct net_device *netdev, | |||
181 | 189 | ||
182 | static const iw_handler zd_standard_iw_handlers[] = { | 190 | static const iw_handler zd_standard_iw_handlers[] = { |
183 | WX(SIOCGIWNAME) = iw_get_name, | 191 | WX(SIOCGIWNAME) = iw_get_name, |
192 | WX(SIOCGIWNICKN) = iw_get_nick, | ||
184 | WX(SIOCSIWFREQ) = iw_set_freq, | 193 | WX(SIOCSIWFREQ) = iw_set_freq, |
185 | WX(SIOCGIWFREQ) = iw_get_freq, | 194 | WX(SIOCGIWFREQ) = iw_get_freq, |
186 | WX(SIOCSIWMODE) = iw_set_mode, | 195 | WX(SIOCSIWMODE) = iw_set_mode, |
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c index d3770d2c61bc..f50cff3db916 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf.c +++ b/drivers/net/wireless/zd1211rw/zd_rf.c | |||
@@ -56,7 +56,7 @@ void zd_rf_init(struct zd_rf *rf) | |||
56 | 56 | ||
57 | void zd_rf_clear(struct zd_rf *rf) | 57 | void zd_rf_clear(struct zd_rf *rf) |
58 | { | 58 | { |
59 | memset(rf, 0, sizeof(*rf)); | 59 | ZD_MEMCLEAR(rf, sizeof(*rf)); |
60 | } | 60 | } |
61 | 61 | ||
62 | int zd_rf_init_hw(struct zd_rf *rf, u8 type) | 62 | int zd_rf_init_hw(struct zd_rf *rf, u8 type) |
@@ -76,6 +76,11 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type) | |||
76 | if (r) | 76 | if (r) |
77 | return r; | 77 | return r; |
78 | break; | 78 | break; |
79 | case AL7230B_RF: | ||
80 | r = zd_rf_init_al7230b(rf); | ||
81 | if (r) | ||
82 | return r; | ||
83 | break; | ||
79 | default: | 84 | default: |
80 | dev_err(zd_chip_dev(chip), | 85 | dev_err(zd_chip_dev(chip), |
81 | "RF %s %#x is not supported\n", zd_rf_name(type), type); | 86 | "RF %s %#x is not supported\n", zd_rf_name(type), type); |
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h index ea30f693fcc8..676b3734f1ed 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf.h +++ b/drivers/net/wireless/zd1211rw/zd_rf.h | |||
@@ -78,5 +78,6 @@ int zd_switch_radio_off(struct zd_rf *rf); | |||
78 | 78 | ||
79 | int zd_rf_init_rf2959(struct zd_rf *rf); | 79 | int zd_rf_init_rf2959(struct zd_rf *rf); |
80 | int zd_rf_init_al2230(struct zd_rf *rf); | 80 | int zd_rf_init_al2230(struct zd_rf *rf); |
81 | int zd_rf_init_al7230b(struct zd_rf *rf); | ||
81 | 82 | ||
82 | #endif /* _ZD_RF_H */ | 83 | #endif /* _ZD_RF_H */ |
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c index 0948b25f660d..25323a13a3db 100644 --- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c +++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include "zd_usb.h" | 21 | #include "zd_usb.h" |
22 | #include "zd_chip.h" | 22 | #include "zd_chip.h" |
23 | 23 | ||
24 | static const u32 al2230_table[][3] = { | 24 | static const u32 zd1211_al2230_table[][3] = { |
25 | RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, }, | 25 | RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, }, |
26 | RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, }, | 26 | RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, }, |
27 | RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, }, | 27 | RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, }, |
@@ -38,6 +38,53 @@ static const u32 al2230_table[][3] = { | |||
38 | RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, }, | 38 | RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, }, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | static const u32 zd1211b_al2230_table[][3] = { | ||
42 | RF_CHANNEL( 1) = { 0x09efc0, 0x8cccc0, 0xb00000, }, | ||
43 | RF_CHANNEL( 2) = { 0x09efc0, 0x8cccd0, 0xb00000, }, | ||
44 | RF_CHANNEL( 3) = { 0x09e7c0, 0x8cccc0, 0xb00000, }, | ||
45 | RF_CHANNEL( 4) = { 0x09e7c0, 0x8cccd0, 0xb00000, }, | ||
46 | RF_CHANNEL( 5) = { 0x05efc0, 0x8cccc0, 0xb00000, }, | ||
47 | RF_CHANNEL( 6) = { 0x05efc0, 0x8cccd0, 0xb00000, }, | ||
48 | RF_CHANNEL( 7) = { 0x05e7c0, 0x8cccc0, 0xb00000, }, | ||
49 | RF_CHANNEL( 8) = { 0x05e7c0, 0x8cccd0, 0xb00000, }, | ||
50 | RF_CHANNEL( 9) = { 0x0defc0, 0x8cccc0, 0xb00000, }, | ||
51 | RF_CHANNEL(10) = { 0x0defc0, 0x8cccd0, 0xb00000, }, | ||
52 | RF_CHANNEL(11) = { 0x0de7c0, 0x8cccc0, 0xb00000, }, | ||
53 | RF_CHANNEL(12) = { 0x0de7c0, 0x8cccd0, 0xb00000, }, | ||
54 | RF_CHANNEL(13) = { 0x03efc0, 0x8cccc0, 0xb00000, }, | ||
55 | RF_CHANNEL(14) = { 0x03e7c0, 0x866660, 0xb00000, }, | ||
56 | }; | ||
57 | |||
58 | static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = { | ||
59 | { CR240, 0x57 }, { CR9, 0xe0 }, | ||
60 | }; | ||
61 | |||
62 | static int zd1211b_al2230_finalize_rf(struct zd_chip *chip) | ||
63 | { | ||
64 | int r; | ||
65 | static const struct zd_ioreq16 ioreqs[] = { | ||
66 | { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, | ||
67 | { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, | ||
68 | { CR203, 0x06 }, | ||
69 | { }, | ||
70 | |||
71 | { CR240, 0x80 }, | ||
72 | }; | ||
73 | |||
74 | r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
75 | if (r) | ||
76 | return r; | ||
77 | |||
78 | /* related to antenna selection? */ | ||
79 | if (chip->new_phy_layout) { | ||
80 | r = zd_iowrite16_locked(chip, 0xe1, CR9); | ||
81 | if (r) | ||
82 | return r; | ||
83 | } | ||
84 | |||
85 | return zd_iowrite16_locked(chip, 0x06, CR203); | ||
86 | } | ||
87 | |||
41 | static int zd1211_al2230_init_hw(struct zd_rf *rf) | 88 | static int zd1211_al2230_init_hw(struct zd_rf *rf) |
42 | { | 89 | { |
43 | int r; | 90 | int r; |
@@ -139,7 +186,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) | |||
139 | { CR47, 0x1e }, | 186 | { CR47, 0x1e }, |
140 | 187 | ||
141 | /* ZD1211B 05.06.10 */ | 188 | /* ZD1211B 05.06.10 */ |
142 | { CR48, 0x00 }, { CR49, 0x00 }, { CR51, 0x01 }, | 189 | { CR48, 0x06 }, { CR49, 0xf9 }, { CR51, 0x01 }, |
143 | { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, | 190 | { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, |
144 | { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, | 191 | { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, |
145 | { CR69, 0x28 }, | 192 | { CR69, 0x28 }, |
@@ -172,79 +219,78 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) | |||
172 | { CR137, 0x50 }, /* 5614 */ | 219 | { CR137, 0x50 }, /* 5614 */ |
173 | { CR138, 0xa8 }, | 220 | { CR138, 0xa8 }, |
174 | { CR144, 0xac }, /* 5621 */ | 221 | { CR144, 0xac }, /* 5621 */ |
175 | { CR150, 0x0d }, { CR252, 0x00 }, { CR253, 0x00 }, | 222 | { CR150, 0x0d }, { CR252, 0x34 }, { CR253, 0x34 }, |
176 | }; | 223 | }; |
177 | 224 | ||
178 | static const u32 rv1[] = { | 225 | static const u32 rv1[] = { |
179 | /* channel 1 */ | 226 | 0x8cccd0, |
180 | 0x03f790, | 227 | 0x481dc0, |
181 | 0x033331, | 228 | 0xcfff00, |
182 | 0x00000d, | 229 | 0x25a000, |
183 | 230 | ||
184 | 0x0b3331, | 231 | /* To improve AL2230 yield, improve phase noise, 4713 */ |
185 | 0x03b812, | 232 | 0x25a000, |
186 | 0x00fff3, | 233 | 0xa3b2f0, |
187 | 0x0005a4, | 234 | |
188 | 0x0f4dc5, /* fix freq shift 0x044dc5 */ | 235 | 0x6da010, /* Reg6 update for MP versio */ |
189 | 0x0805b6, | 236 | 0xe36280, /* Modified by jxiao for Bor-Chin on 2004/08/02 */ |
190 | 0x0146c7, | 237 | 0x116000, |
191 | 0x000688, | 238 | 0x9dc020, /* External control TX power (CR31) */ |
192 | 0x0403b9, /* External control TX power (CR31) */ | 239 | 0x5ddb00, /* RegA update for MP version */ |
193 | 0x00dbba, | 240 | 0xd99000, /* RegB update for MP version */ |
194 | 0x00099b, | 241 | 0x3ffbd0, /* RegC update for MP version */ |
195 | 0x0bdffc, | 242 | 0xb00000, /* RegD update for MP version */ |
196 | 0x00000d, | 243 | |
197 | 0x00580f, | 244 | /* improve phase noise and remove phase calibration,4713 */ |
245 | 0xf01a00, | ||
198 | }; | 246 | }; |
199 | 247 | ||
200 | static const struct zd_ioreq16 ioreqs2[] = { | 248 | static const struct zd_ioreq16 ioreqs2[] = { |
201 | { CR47, 0x1e }, { CR_RFCFG, 0x03 }, | 249 | { CR251, 0x2f }, /* shdnb(PLL_ON)=0 */ |
250 | { CR251, 0x7f }, /* shdnb(PLL_ON)=1 */ | ||
202 | }; | 251 | }; |
203 | 252 | ||
204 | static const u32 rv2[] = { | 253 | static const u32 rv2[] = { |
205 | 0x00880f, | 254 | /* To improve AL2230 yield, 4713 */ |
206 | 0x00080f, | 255 | 0xf01b00, |
256 | 0xf01e00, | ||
257 | 0xf01a00, | ||
207 | }; | 258 | }; |
208 | 259 | ||
209 | static const struct zd_ioreq16 ioreqs3[] = { | 260 | static const struct zd_ioreq16 ioreqs3[] = { |
210 | { CR_RFCFG, 0x00 }, { CR47, 0x1e }, { CR251, 0x7f }, | 261 | /* related to 6M band edge patching, happens unconditionally */ |
211 | }; | 262 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, |
212 | |||
213 | static const u32 rv3[] = { | ||
214 | 0x00d80f, | ||
215 | 0x00780f, | ||
216 | 0x00580f, | ||
217 | }; | ||
218 | |||
219 | static const struct zd_ioreq16 ioreqs4[] = { | ||
220 | { CR138, 0x28 }, { CR203, 0x06 }, | ||
221 | }; | 263 | }; |
222 | 264 | ||
265 | r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1, | ||
266 | ARRAY_SIZE(zd1211b_ioreqs_shared_1)); | ||
267 | if (r) | ||
268 | return r; | ||
223 | r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1)); | 269 | r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1)); |
224 | if (r) | 270 | if (r) |
225 | return r; | 271 | return r; |
226 | r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS); | 272 | r = zd_rfwritev_cr_locked(chip, zd1211b_al2230_table[0], 3); |
227 | if (r) | 273 | if (r) |
228 | return r; | 274 | return r; |
229 | r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2)); | 275 | r = zd_rfwritev_cr_locked(chip, rv1, ARRAY_SIZE(rv1)); |
230 | if (r) | 276 | if (r) |
231 | return r; | 277 | return r; |
232 | r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS); | 278 | r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2)); |
233 | if (r) | 279 | if (r) |
234 | return r; | 280 | return r; |
235 | r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3)); | 281 | r = zd_rfwritev_cr_locked(chip, rv2, ARRAY_SIZE(rv2)); |
236 | if (r) | 282 | if (r) |
237 | return r; | 283 | return r; |
238 | r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS); | 284 | r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3)); |
239 | if (r) | 285 | if (r) |
240 | return r; | 286 | return r; |
241 | return zd_iowrite16a_locked(chip, ioreqs4, ARRAY_SIZE(ioreqs4)); | 287 | return zd1211b_al2230_finalize_rf(chip); |
242 | } | 288 | } |
243 | 289 | ||
244 | static int al2230_set_channel(struct zd_rf *rf, u8 channel) | 290 | static int zd1211_al2230_set_channel(struct zd_rf *rf, u8 channel) |
245 | { | 291 | { |
246 | int r; | 292 | int r; |
247 | const u32 *rv = al2230_table[channel-1]; | 293 | const u32 *rv = zd1211_al2230_table[channel-1]; |
248 | struct zd_chip *chip = zd_rf_to_chip(rf); | 294 | struct zd_chip *chip = zd_rf_to_chip(rf); |
249 | static const struct zd_ioreq16 ioreqs[] = { | 295 | static const struct zd_ioreq16 ioreqs[] = { |
250 | { CR138, 0x28 }, | 296 | { CR138, 0x28 }, |
@@ -257,6 +303,24 @@ static int al2230_set_channel(struct zd_rf *rf, u8 channel) | |||
257 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | 303 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); |
258 | } | 304 | } |
259 | 305 | ||
306 | static int zd1211b_al2230_set_channel(struct zd_rf *rf, u8 channel) | ||
307 | { | ||
308 | int r; | ||
309 | const u32 *rv = zd1211b_al2230_table[channel-1]; | ||
310 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
311 | |||
312 | r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1, | ||
313 | ARRAY_SIZE(zd1211b_ioreqs_shared_1)); | ||
314 | if (r) | ||
315 | return r; | ||
316 | |||
317 | r = zd_rfwritev_cr_locked(chip, rv, 3); | ||
318 | if (r) | ||
319 | return r; | ||
320 | |||
321 | return zd1211b_al2230_finalize_rf(chip); | ||
322 | } | ||
323 | |||
260 | static int zd1211_al2230_switch_radio_on(struct zd_rf *rf) | 324 | static int zd1211_al2230_switch_radio_on(struct zd_rf *rf) |
261 | { | 325 | { |
262 | struct zd_chip *chip = zd_rf_to_chip(rf); | 326 | struct zd_chip *chip = zd_rf_to_chip(rf); |
@@ -294,13 +358,14 @@ int zd_rf_init_al2230(struct zd_rf *rf) | |||
294 | { | 358 | { |
295 | struct zd_chip *chip = zd_rf_to_chip(rf); | 359 | struct zd_chip *chip = zd_rf_to_chip(rf); |
296 | 360 | ||
297 | rf->set_channel = al2230_set_channel; | ||
298 | rf->switch_radio_off = al2230_switch_radio_off; | 361 | rf->switch_radio_off = al2230_switch_radio_off; |
299 | if (chip->is_zd1211b) { | 362 | if (chip->is_zd1211b) { |
300 | rf->init_hw = zd1211b_al2230_init_hw; | 363 | rf->init_hw = zd1211b_al2230_init_hw; |
364 | rf->set_channel = zd1211b_al2230_set_channel; | ||
301 | rf->switch_radio_on = zd1211b_al2230_switch_radio_on; | 365 | rf->switch_radio_on = zd1211b_al2230_switch_radio_on; |
302 | } else { | 366 | } else { |
303 | rf->init_hw = zd1211_al2230_init_hw; | 367 | rf->init_hw = zd1211_al2230_init_hw; |
368 | rf->set_channel = zd1211_al2230_set_channel; | ||
304 | rf->switch_radio_on = zd1211_al2230_switch_radio_on; | 369 | rf->switch_radio_on = zd1211_al2230_switch_radio_on; |
305 | } | 370 | } |
306 | rf->patch_6m_band_edge = 1; | 371 | rf->patch_6m_band_edge = 1; |
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c new file mode 100644 index 000000000000..a289f95187ec --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c | |||
@@ -0,0 +1,274 @@ | |||
1 | /* zd_rf_al7230b.c: Functions for the AL7230B RF controller | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | |||
20 | #include "zd_rf.h" | ||
21 | #include "zd_usb.h" | ||
22 | #include "zd_chip.h" | ||
23 | |||
24 | static const u32 chan_rv[][2] = { | ||
25 | RF_CHANNEL( 1) = { 0x09ec00, 0x8cccc8 }, | ||
26 | RF_CHANNEL( 2) = { 0x09ec00, 0x8cccd8 }, | ||
27 | RF_CHANNEL( 3) = { 0x09ec00, 0x8cccc0 }, | ||
28 | RF_CHANNEL( 4) = { 0x09ec00, 0x8cccd0 }, | ||
29 | RF_CHANNEL( 5) = { 0x05ec00, 0x8cccc8 }, | ||
30 | RF_CHANNEL( 6) = { 0x05ec00, 0x8cccd8 }, | ||
31 | RF_CHANNEL( 7) = { 0x05ec00, 0x8cccc0 }, | ||
32 | RF_CHANNEL( 8) = { 0x05ec00, 0x8cccd0 }, | ||
33 | RF_CHANNEL( 9) = { 0x0dec00, 0x8cccc8 }, | ||
34 | RF_CHANNEL(10) = { 0x0dec00, 0x8cccd8 }, | ||
35 | RF_CHANNEL(11) = { 0x0dec00, 0x8cccc0 }, | ||
36 | RF_CHANNEL(12) = { 0x0dec00, 0x8cccd0 }, | ||
37 | RF_CHANNEL(13) = { 0x03ec00, 0x8cccc8 }, | ||
38 | RF_CHANNEL(14) = { 0x03ec00, 0x866660 }, | ||
39 | }; | ||
40 | |||
41 | static const u32 std_rv[] = { | ||
42 | 0x4ff821, | ||
43 | 0xc5fbfc, | ||
44 | 0x21ebfe, | ||
45 | 0xafd401, /* freq shift 0xaad401 */ | ||
46 | 0x6cf56a, | ||
47 | 0xe04073, | ||
48 | 0x193d76, | ||
49 | 0x9dd844, | ||
50 | 0x500007, | ||
51 | 0xd8c010, | ||
52 | }; | ||
53 | |||
54 | static int al7230b_init_hw(struct zd_rf *rf) | ||
55 | { | ||
56 | int i, r; | ||
57 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
58 | |||
59 | /* All of these writes are identical to AL2230 unless otherwise | ||
60 | * specified */ | ||
61 | static const struct zd_ioreq16 ioreqs_1[] = { | ||
62 | /* This one is 7230-specific, and happens before the rest */ | ||
63 | { CR240, 0x57 }, | ||
64 | { }, | ||
65 | |||
66 | { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, | ||
67 | { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, | ||
68 | { CR44, 0x33 }, | ||
69 | /* This value is different for 7230 (was: 0x2a) */ | ||
70 | { CR106, 0x22 }, | ||
71 | { CR107, 0x1a }, { CR109, 0x09 }, { CR110, 0x27 }, | ||
72 | { CR111, 0x2b }, { CR112, 0x2b }, { CR119, 0x0a }, | ||
73 | /* This happened further down in AL2230, | ||
74 | * and the value changed (was: 0xe0) */ | ||
75 | { CR122, 0xfc }, | ||
76 | { CR10, 0x89 }, | ||
77 | /* for newest (3rd cut) AL2300 */ | ||
78 | { CR17, 0x28 }, | ||
79 | { CR26, 0x93 }, { CR34, 0x30 }, | ||
80 | /* for newest (3rd cut) AL2300 */ | ||
81 | { CR35, 0x3e }, | ||
82 | { CR41, 0x24 }, { CR44, 0x32 }, | ||
83 | /* for newest (3rd cut) AL2300 */ | ||
84 | { CR46, 0x96 }, | ||
85 | { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, | ||
86 | { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, | ||
87 | { CR92, 0x0a }, { CR99, 0x28 }, | ||
88 | /* This value is different for 7230 (was: 0x00) */ | ||
89 | { CR100, 0x02 }, | ||
90 | { CR101, 0x13 }, { CR102, 0x27 }, | ||
91 | /* This value is different for 7230 (was: 0x24) */ | ||
92 | { CR106, 0x22 }, | ||
93 | /* This value is different for 7230 (was: 0x2a) */ | ||
94 | { CR107, 0x3f }, | ||
95 | { CR109, 0x09 }, | ||
96 | /* This value is different for 7230 (was: 0x13) */ | ||
97 | { CR110, 0x1f }, | ||
98 | { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, | ||
99 | { CR114, 0x27 }, | ||
100 | /* for newest (3rd cut) AL2300 */ | ||
101 | { CR115, 0x24 }, | ||
102 | /* This value is different for 7230 (was: 0x24) */ | ||
103 | { CR116, 0x3f }, | ||
104 | /* This value is different for 7230 (was: 0xf4) */ | ||
105 | { CR117, 0xfa }, | ||
106 | { CR118, 0xfc }, { CR119, 0x10 }, { CR120, 0x4f }, | ||
107 | { CR121, 0x77 }, { CR137, 0x88 }, | ||
108 | /* This one is 7230-specific */ | ||
109 | { CR138, 0xa8 }, | ||
110 | /* This value is different for 7230 (was: 0xff) */ | ||
111 | { CR252, 0x34 }, | ||
112 | /* This value is different for 7230 (was: 0xff) */ | ||
113 | { CR253, 0x34 }, | ||
114 | |||
115 | /* PLL_OFF */ | ||
116 | { CR251, 0x2f }, | ||
117 | }; | ||
118 | |||
119 | static const struct zd_ioreq16 ioreqs_2[] = { | ||
120 | /* PLL_ON */ | ||
121 | { CR251, 0x3f }, | ||
122 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, | ||
123 | { CR38, 0x38 }, { CR136, 0xdf }, | ||
124 | }; | ||
125 | |||
126 | r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); | ||
127 | if (r) | ||
128 | return r; | ||
129 | |||
130 | r = zd_rfwrite_cr_locked(chip, 0x09ec04); | ||
131 | if (r) | ||
132 | return r; | ||
133 | r = zd_rfwrite_cr_locked(chip, 0x8cccc8); | ||
134 | if (r) | ||
135 | return r; | ||
136 | |||
137 | for (i = 0; i < ARRAY_SIZE(std_rv); i++) { | ||
138 | r = zd_rfwrite_cr_locked(chip, std_rv[i]); | ||
139 | if (r) | ||
140 | return r; | ||
141 | } | ||
142 | |||
143 | r = zd_rfwrite_cr_locked(chip, 0x3c9000); | ||
144 | if (r) | ||
145 | return r; | ||
146 | r = zd_rfwrite_cr_locked(chip, 0xbfffff); | ||
147 | if (r) | ||
148 | return r; | ||
149 | r = zd_rfwrite_cr_locked(chip, 0x700000); | ||
150 | if (r) | ||
151 | return r; | ||
152 | r = zd_rfwrite_cr_locked(chip, 0xf15d58); | ||
153 | if (r) | ||
154 | return r; | ||
155 | |||
156 | r = zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2)); | ||
157 | if (r) | ||
158 | return r; | ||
159 | |||
160 | r = zd_rfwrite_cr_locked(chip, 0xf15d59); | ||
161 | if (r) | ||
162 | return r; | ||
163 | r = zd_rfwrite_cr_locked(chip, 0xf15d5c); | ||
164 | if (r) | ||
165 | return r; | ||
166 | r = zd_rfwrite_cr_locked(chip, 0xf15d58); | ||
167 | if (r) | ||
168 | return r; | ||
169 | |||
170 | r = zd_iowrite16_locked(chip, 0x06, CR203); | ||
171 | if (r) | ||
172 | return r; | ||
173 | r = zd_iowrite16_locked(chip, 0x80, CR240); | ||
174 | if (r) | ||
175 | return r; | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int al7230b_set_channel(struct zd_rf *rf, u8 channel) | ||
181 | { | ||
182 | int i, r; | ||
183 | const u32 *rv = chan_rv[channel-1]; | ||
184 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
185 | |||
186 | struct zd_ioreq16 ioreqs_1[] = { | ||
187 | { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, | ||
188 | { CR38, 0x38 }, { CR136, 0xdf }, | ||
189 | }; | ||
190 | |||
191 | struct zd_ioreq16 ioreqs_2[] = { | ||
192 | /* PLL_ON */ | ||
193 | { CR251, 0x3f }, | ||
194 | { CR203, 0x06 }, { CR240, 0x08 }, | ||
195 | }; | ||
196 | |||
197 | r = zd_iowrite16_locked(chip, 0x57, CR240); | ||
198 | if (r) | ||
199 | return r; | ||
200 | |||
201 | /* PLL_OFF */ | ||
202 | r = zd_iowrite16_locked(chip, 0x2f, CR251); | ||
203 | if (r) | ||
204 | return r; | ||
205 | |||
206 | for (i = 0; i < ARRAY_SIZE(std_rv); i++) { | ||
207 | r = zd_rfwrite_cr_locked(chip, std_rv[i]); | ||
208 | if (r) | ||
209 | return r; | ||
210 | } | ||
211 | |||
212 | r = zd_rfwrite_cr_locked(chip, 0x3c9000); | ||
213 | if (r) | ||
214 | return r; | ||
215 | r = zd_rfwrite_cr_locked(chip, 0xf15d58); | ||
216 | if (r) | ||
217 | return r; | ||
218 | |||
219 | r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); | ||
220 | if (r) | ||
221 | return r; | ||
222 | |||
223 | for (i = 0; i < 2; i++) { | ||
224 | r = zd_rfwrite_cr_locked(chip, rv[i]); | ||
225 | if (r) | ||
226 | return r; | ||
227 | } | ||
228 | |||
229 | r = zd_rfwrite_cr_locked(chip, 0x3c9000); | ||
230 | if (r) | ||
231 | return r; | ||
232 | |||
233 | return zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2)); | ||
234 | } | ||
235 | |||
236 | static int al7230b_switch_radio_on(struct zd_rf *rf) | ||
237 | { | ||
238 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
239 | static const struct zd_ioreq16 ioreqs[] = { | ||
240 | { CR11, 0x00 }, | ||
241 | { CR251, 0x3f }, | ||
242 | }; | ||
243 | |||
244 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
245 | } | ||
246 | |||
247 | static int al7230b_switch_radio_off(struct zd_rf *rf) | ||
248 | { | ||
249 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
250 | static const struct zd_ioreq16 ioreqs[] = { | ||
251 | { CR11, 0x04 }, | ||
252 | { CR251, 0x2f }, | ||
253 | }; | ||
254 | |||
255 | return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); | ||
256 | } | ||
257 | |||
258 | int zd_rf_init_al7230b(struct zd_rf *rf) | ||
259 | { | ||
260 | struct zd_chip *chip = zd_rf_to_chip(rf); | ||
261 | |||
262 | if (chip->is_zd1211b) { | ||
263 | dev_err(zd_chip_dev(chip), "AL7230B is currently not " | ||
264 | "supported for ZD1211B devices\n"); | ||
265 | return -ENODEV; | ||
266 | } | ||
267 | |||
268 | rf->init_hw = al7230b_init_hw; | ||
269 | rf->set_channel = al7230b_set_channel; | ||
270 | rf->switch_radio_on = al7230b_switch_radio_on; | ||
271 | rf->switch_radio_off = al7230b_switch_radio_off; | ||
272 | rf->patch_6m_band_edge = 1; | ||
273 | return 0; | ||
274 | } | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 6320984126c7..31027e52b04b 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <asm/unaligned.h> | 18 | #include <asm/unaligned.h> |
19 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | #include <linux/firmware.h> | 22 | #include <linux/firmware.h> |
@@ -39,9 +40,19 @@ static struct usb_device_id usb_ids[] = { | |||
39 | { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, | 40 | { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, |
40 | { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, | 41 | { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, |
41 | { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, | 42 | { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, |
43 | { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 }, | ||
44 | { USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 }, | ||
45 | { USB_DEVICE(0x157e, 0x3204), .driver_info = DEVICE_ZD1211 }, | ||
46 | { USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 }, | ||
47 | { USB_DEVICE(0x0b3b, 0x5630), .driver_info = DEVICE_ZD1211 }, | ||
48 | { USB_DEVICE(0x0b05, 0x170c), .driver_info = DEVICE_ZD1211 }, | ||
42 | /* ZD1211B */ | 49 | /* ZD1211B */ |
43 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, | 50 | { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, |
44 | { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, | 51 | { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, |
52 | { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, | ||
53 | { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, | ||
54 | /* "Driverless" devices that need ejecting */ | ||
55 | { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, | ||
45 | {} | 56 | {} |
46 | }; | 57 | }; |
47 | 58 | ||
@@ -263,6 +274,39 @@ static char *get_fw_name(char *buffer, size_t size, u8 device_type, | |||
263 | return buffer; | 274 | return buffer; |
264 | } | 275 | } |
265 | 276 | ||
277 | static int handle_version_mismatch(struct usb_device *udev, u8 device_type, | ||
278 | const struct firmware *ub_fw) | ||
279 | { | ||
280 | const struct firmware *ur_fw = NULL; | ||
281 | int offset; | ||
282 | int r = 0; | ||
283 | char fw_name[128]; | ||
284 | |||
285 | r = request_fw_file(&ur_fw, | ||
286 | get_fw_name(fw_name, sizeof(fw_name), device_type, "ur"), | ||
287 | &udev->dev); | ||
288 | if (r) | ||
289 | goto error; | ||
290 | |||
291 | r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START_OFFSET, | ||
292 | REBOOT); | ||
293 | if (r) | ||
294 | goto error; | ||
295 | |||
296 | offset = ((EEPROM_REGS_OFFSET + EEPROM_REGS_SIZE) * sizeof(u16)); | ||
297 | r = upload_code(udev, ub_fw->data + offset, ub_fw->size - offset, | ||
298 | E2P_BASE_OFFSET + EEPROM_REGS_SIZE, REBOOT); | ||
299 | |||
300 | /* At this point, the vendor driver downloads the whole firmware | ||
301 | * image, hacks around with version IDs, and uploads it again, | ||
302 | * completely overwriting the boot code. We do not do this here as | ||
303 | * it is not required on any tested devices, and it is suspected to | ||
304 | * cause problems. */ | ||
305 | error: | ||
306 | release_firmware(ur_fw); | ||
307 | return r; | ||
308 | } | ||
309 | |||
266 | static int upload_firmware(struct usb_device *udev, u8 device_type) | 310 | static int upload_firmware(struct usb_device *udev, u8 device_type) |
267 | { | 311 | { |
268 | int r; | 312 | int r; |
@@ -282,15 +326,17 @@ static int upload_firmware(struct usb_device *udev, u8 device_type) | |||
282 | 326 | ||
283 | fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET); | 327 | fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET); |
284 | 328 | ||
285 | /* FIXME: do we have any reason to perform the kludge that the vendor | ||
286 | * driver does when there is a version mismatch? (their driver uploads | ||
287 | * different firmwares and stuff) | ||
288 | */ | ||
289 | if (fw_bcdDevice != bcdDevice) { | 329 | if (fw_bcdDevice != bcdDevice) { |
290 | dev_info(&udev->dev, | 330 | dev_info(&udev->dev, |
291 | "firmware device id %#06x and actual device id " | 331 | "firmware version %#06x and device bootcode version " |
292 | "%#06x differ, continuing anyway\n", | 332 | "%#06x differ\n", fw_bcdDevice, bcdDevice); |
293 | fw_bcdDevice, bcdDevice); | 333 | if (bcdDevice <= 0x4313) |
334 | dev_warn(&udev->dev, "device has old bootcode, please " | ||
335 | "report success or failure\n"); | ||
336 | |||
337 | r = handle_version_mismatch(udev, device_type, ub_fw); | ||
338 | if (r) | ||
339 | goto error; | ||
294 | } else { | 340 | } else { |
295 | dev_dbg_f(&udev->dev, | 341 | dev_dbg_f(&udev->dev, |
296 | "firmware device id %#06x is equal to the " | 342 | "firmware device id %#06x is equal to the " |
@@ -620,7 +666,7 @@ resubmit: | |||
620 | usb_submit_urb(urb, GFP_ATOMIC); | 666 | usb_submit_urb(urb, GFP_ATOMIC); |
621 | } | 667 | } |
622 | 668 | ||
623 | struct urb *alloc_urb(struct zd_usb *usb) | 669 | static struct urb *alloc_urb(struct zd_usb *usb) |
624 | { | 670 | { |
625 | struct usb_device *udev = zd_usb_to_usbdev(usb); | 671 | struct usb_device *udev = zd_usb_to_usbdev(usb); |
626 | struct urb *urb; | 672 | struct urb *urb; |
@@ -644,7 +690,7 @@ struct urb *alloc_urb(struct zd_usb *usb) | |||
644 | return urb; | 690 | return urb; |
645 | } | 691 | } |
646 | 692 | ||
647 | void free_urb(struct urb *urb) | 693 | static void free_urb(struct urb *urb) |
648 | { | 694 | { |
649 | if (!urb) | 695 | if (!urb) |
650 | return; | 696 | return; |
@@ -864,7 +910,7 @@ void zd_usb_clear(struct zd_usb *usb) | |||
864 | { | 910 | { |
865 | usb_set_intfdata(usb->intf, NULL); | 911 | usb_set_intfdata(usb->intf, NULL); |
866 | usb_put_intf(usb->intf); | 912 | usb_put_intf(usb->intf); |
867 | memset(usb, 0, sizeof(*usb)); | 913 | ZD_MEMCLEAR(usb, sizeof(*usb)); |
868 | /* FIXME: usb_interrupt, usb_tx, usb_rx? */ | 914 | /* FIXME: usb_interrupt, usb_tx, usb_rx? */ |
869 | } | 915 | } |
870 | 916 | ||
@@ -910,6 +956,55 @@ static void print_id(struct usb_device *udev) | |||
910 | #define print_id(udev) do { } while (0) | 956 | #define print_id(udev) do { } while (0) |
911 | #endif | 957 | #endif |
912 | 958 | ||
959 | static int eject_installer(struct usb_interface *intf) | ||
960 | { | ||
961 | struct usb_device *udev = interface_to_usbdev(intf); | ||
962 | struct usb_host_interface *iface_desc = &intf->altsetting[0]; | ||
963 | struct usb_endpoint_descriptor *endpoint; | ||
964 | unsigned char *cmd; | ||
965 | u8 bulk_out_ep; | ||
966 | int r; | ||
967 | |||
968 | /* Find bulk out endpoint */ | ||
969 | endpoint = &iface_desc->endpoint[1].desc; | ||
970 | if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT && | ||
971 | (endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
972 | USB_ENDPOINT_XFER_BULK) { | ||
973 | bulk_out_ep = endpoint->bEndpointAddress; | ||
974 | } else { | ||
975 | dev_err(&udev->dev, | ||
976 | "zd1211rw: Could not find bulk out endpoint\n"); | ||
977 | return -ENODEV; | ||
978 | } | ||
979 | |||
980 | cmd = kzalloc(31, GFP_KERNEL); | ||
981 | if (cmd == NULL) | ||
982 | return -ENODEV; | ||
983 | |||
984 | /* USB bulk command block */ | ||
985 | cmd[0] = 0x55; /* bulk command signature */ | ||
986 | cmd[1] = 0x53; /* bulk command signature */ | ||
987 | cmd[2] = 0x42; /* bulk command signature */ | ||
988 | cmd[3] = 0x43; /* bulk command signature */ | ||
989 | cmd[14] = 6; /* command length */ | ||
990 | |||
991 | cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */ | ||
992 | cmd[19] = 0x2; /* eject disc */ | ||
993 | |||
994 | dev_info(&udev->dev, "Ejecting virtual installer media...\n"); | ||
995 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep), | ||
996 | cmd, 31, NULL, 2000); | ||
997 | kfree(cmd); | ||
998 | if (r) | ||
999 | return r; | ||
1000 | |||
1001 | /* At this point, the device disconnects and reconnects with the real | ||
1002 | * ID numbers. */ | ||
1003 | |||
1004 | usb_set_intfdata(intf, NULL); | ||
1005 | return 0; | ||
1006 | } | ||
1007 | |||
913 | static int probe(struct usb_interface *intf, const struct usb_device_id *id) | 1008 | static int probe(struct usb_interface *intf, const struct usb_device_id *id) |
914 | { | 1009 | { |
915 | int r; | 1010 | int r; |
@@ -918,6 +1013,9 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
918 | 1013 | ||
919 | print_id(udev); | 1014 | print_id(udev); |
920 | 1015 | ||
1016 | if (id->driver_info & DEVICE_INSTALLER) | ||
1017 | return eject_installer(intf); | ||
1018 | |||
921 | switch (udev->speed) { | 1019 | switch (udev->speed) { |
922 | case USB_SPEED_LOW: | 1020 | case USB_SPEED_LOW: |
923 | case USB_SPEED_FULL: | 1021 | case USB_SPEED_FULL: |
@@ -983,6 +1081,11 @@ static void disconnect(struct usb_interface *intf) | |||
983 | struct zd_mac *mac = zd_netdev_mac(netdev); | 1081 | struct zd_mac *mac = zd_netdev_mac(netdev); |
984 | struct zd_usb *usb = &mac->chip.usb; | 1082 | struct zd_usb *usb = &mac->chip.usb; |
985 | 1083 | ||
1084 | /* Either something really bad happened, or we're just dealing with | ||
1085 | * a DEVICE_INSTALLER. */ | ||
1086 | if (netdev == NULL) | ||
1087 | return; | ||
1088 | |||
986 | dev_dbg_f(zd_usb_dev(usb), "\n"); | 1089 | dev_dbg_f(zd_usb_dev(usb), "\n"); |
987 | 1090 | ||
988 | zd_netdev_disconnect(netdev); | 1091 | zd_netdev_disconnect(netdev); |
@@ -998,7 +1101,6 @@ static void disconnect(struct usb_interface *intf) | |||
998 | */ | 1101 | */ |
999 | usb_reset_device(interface_to_usbdev(intf)); | 1102 | usb_reset_device(interface_to_usbdev(intf)); |
1000 | 1103 | ||
1001 | /* If somebody still waits on this lock now, this is an error. */ | ||
1002 | zd_netdev_free(netdev); | 1104 | zd_netdev_free(netdev); |
1003 | dev_dbg(&intf->dev, "disconnected\n"); | 1105 | dev_dbg(&intf->dev, "disconnected\n"); |
1004 | } | 1106 | } |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h index d6420283bd5a..ded39de5f72d 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/drivers/net/wireless/zd1211rw/zd_usb.h | |||
@@ -30,6 +30,7 @@ | |||
30 | enum devicetype { | 30 | enum devicetype { |
31 | DEVICE_ZD1211 = 0, | 31 | DEVICE_ZD1211 = 0, |
32 | DEVICE_ZD1211B = 1, | 32 | DEVICE_ZD1211B = 1, |
33 | DEVICE_INSTALLER = 2, | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | enum endpoints { | 36 | enum endpoints { |
@@ -73,17 +74,17 @@ enum control_requests { | |||
73 | struct usb_req_read_regs { | 74 | struct usb_req_read_regs { |
74 | __le16 id; | 75 | __le16 id; |
75 | __le16 addr[0]; | 76 | __le16 addr[0]; |
76 | } __attribute__((packed)); | 77 | }; |
77 | 78 | ||
78 | struct reg_data { | 79 | struct reg_data { |
79 | __le16 addr; | 80 | __le16 addr; |
80 | __le16 value; | 81 | __le16 value; |
81 | } __attribute__((packed)); | 82 | }; |
82 | 83 | ||
83 | struct usb_req_write_regs { | 84 | struct usb_req_write_regs { |
84 | __le16 id; | 85 | __le16 id; |
85 | struct reg_data reg_writes[0]; | 86 | struct reg_data reg_writes[0]; |
86 | } __attribute__((packed)); | 87 | }; |
87 | 88 | ||
88 | enum { | 89 | enum { |
89 | RF_IF_LE = 0x02, | 90 | RF_IF_LE = 0x02, |
@@ -100,7 +101,7 @@ struct usb_req_rfwrite { | |||
100 | /* RF2595: 24 */ | 101 | /* RF2595: 24 */ |
101 | __le16 bit_values[0]; | 102 | __le16 bit_values[0]; |
102 | /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ | 103 | /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ |
103 | } __attribute__((packed)); | 104 | }; |
104 | 105 | ||
105 | /* USB interrupt */ | 106 | /* USB interrupt */ |
106 | 107 | ||
@@ -117,12 +118,12 @@ enum usb_int_flags { | |||
117 | struct usb_int_header { | 118 | struct usb_int_header { |
118 | u8 type; /* must always be 1 */ | 119 | u8 type; /* must always be 1 */ |
119 | u8 id; | 120 | u8 id; |
120 | } __attribute__((packed)); | 121 | }; |
121 | 122 | ||
122 | struct usb_int_regs { | 123 | struct usb_int_regs { |
123 | struct usb_int_header hdr; | 124 | struct usb_int_header hdr; |
124 | struct reg_data regs[0]; | 125 | struct reg_data regs[0]; |
125 | } __attribute__((packed)); | 126 | }; |
126 | 127 | ||
127 | struct usb_int_retry_fail { | 128 | struct usb_int_retry_fail { |
128 | struct usb_int_header hdr; | 129 | struct usb_int_header hdr; |
@@ -130,7 +131,7 @@ struct usb_int_retry_fail { | |||
130 | u8 _dummy; | 131 | u8 _dummy; |
131 | u8 addr[ETH_ALEN]; | 132 | u8 addr[ETH_ALEN]; |
132 | u8 ibss_wakeup_dest; | 133 | u8 ibss_wakeup_dest; |
133 | } __attribute__((packed)); | 134 | }; |
134 | 135 | ||
135 | struct read_regs_int { | 136 | struct read_regs_int { |
136 | struct completion completion; | 137 | struct completion completion; |