aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/zd1211rw
diff options
context:
space:
mode:
authorUlrich Kunitz <kune@deine-taler.de>2006-12-10 14:13:12 -0500
committerJohn W. Linville <linville@linville-t43.mobile>2006-12-19 16:09:59 -0500
commit4d1feabcbf41f875447a392015acd0796f57baf6 (patch)
treeb47ceb21cfed93f410e6329040784d43864dab33 /drivers/net/wireless/zd1211rw
parente25db641c0e6dd49c5db24dbe154048d4a466727 (diff)
[PATCH] zd1211rw: Call ieee80211_rx in tasklet
The driver called ieee80211_rx in hardware interrupt context. This has been against the intention of the ieee80211_rx function. It caused a bug in the crypto routines used by WPA. This patch calls ieee80211_rx in a tasklet. Signed-off-by: Ulrich Kunitz <kune@deine-taler.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/zd1211rw')
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c96
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.h5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c4
3 files changed, 76 insertions, 29 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 00ca704ece35..a08524191b5d 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -41,6 +41,8 @@ static void housekeeping_disable(struct zd_mac *mac);
41 41
42static void set_multicast_hash_handler(struct work_struct *work); 42static void set_multicast_hash_handler(struct work_struct *work);
43 43
44static void do_rx(unsigned long mac_ptr);
45
44int zd_mac_init(struct zd_mac *mac, 46int zd_mac_init(struct zd_mac *mac,
45 struct net_device *netdev, 47 struct net_device *netdev,
46 struct usb_interface *intf) 48 struct usb_interface *intf)
@@ -53,6 +55,10 @@ int zd_mac_init(struct zd_mac *mac,
53 INIT_DELAYED_WORK(&mac->set_rts_cts_work, set_rts_cts_work); 55 INIT_DELAYED_WORK(&mac->set_rts_cts_work, set_rts_cts_work);
54 INIT_DELAYED_WORK(&mac->set_basic_rates_work, set_basic_rates_work); 56 INIT_DELAYED_WORK(&mac->set_basic_rates_work, set_basic_rates_work);
55 57
58 skb_queue_head_init(&mac->rx_queue);
59 tasklet_init(&mac->rx_tasklet, do_rx, (unsigned long)mac);
60 tasklet_disable(&mac->rx_tasklet);
61
56 ieee_init(ieee); 62 ieee_init(ieee);
57 softmac_init(ieee80211_priv(netdev)); 63 softmac_init(ieee80211_priv(netdev));
58 zd_chip_init(&mac->chip, netdev, intf); 64 zd_chip_init(&mac->chip, netdev, intf);
@@ -140,6 +146,8 @@ out:
140void zd_mac_clear(struct zd_mac *mac) 146void zd_mac_clear(struct zd_mac *mac)
141{ 147{
142 flush_workqueue(zd_workqueue); 148 flush_workqueue(zd_workqueue);
149 skb_queue_purge(&mac->rx_queue);
150 tasklet_kill(&mac->rx_tasklet);
143 zd_chip_clear(&mac->chip); 151 zd_chip_clear(&mac->chip);
144 ZD_ASSERT(!spin_is_locked(&mac->lock)); 152 ZD_ASSERT(!spin_is_locked(&mac->lock));
145 ZD_MEMCLEAR(mac, sizeof(struct zd_mac)); 153 ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
@@ -168,6 +176,8 @@ int zd_mac_open(struct net_device *netdev)
168 struct zd_chip *chip = &mac->chip; 176 struct zd_chip *chip = &mac->chip;
169 int r; 177 int r;
170 178
179 tasklet_enable(&mac->rx_tasklet);
180
171 r = zd_chip_enable_int(chip); 181 r = zd_chip_enable_int(chip);
172 if (r < 0) 182 if (r < 0)
173 goto out; 183 goto out;
@@ -218,6 +228,8 @@ int zd_mac_stop(struct net_device *netdev)
218 */ 228 */
219 229
220 zd_chip_disable_rx(chip); 230 zd_chip_disable_rx(chip);
231 skb_queue_purge(&mac->rx_queue);
232 tasklet_disable(&mac->rx_tasklet);
221 housekeeping_disable(mac); 233 housekeeping_disable(mac);
222 ieee80211softmac_stop(netdev); 234 ieee80211softmac_stop(netdev);
223 235
@@ -470,13 +482,13 @@ static void bssinfo_change(struct net_device *netdev, u32 changes)
470 482
471 if (changes & IEEE80211SOFTMAC_BSSINFOCHG_RATES) { 483 if (changes & IEEE80211SOFTMAC_BSSINFOCHG_RATES) {
472 /* Set RTS rate to highest available basic rate */ 484 /* Set RTS rate to highest available basic rate */
473 u8 rate = ieee80211softmac_highest_supported_rate(softmac, 485 u8 hi_rate = ieee80211softmac_highest_supported_rate(softmac,
474 &bssinfo->supported_rates, 1); 486 &bssinfo->supported_rates, 1);
475 rate = rate_to_zd_rate(rate); 487 hi_rate = rate_to_zd_rate(hi_rate);
476 488
477 spin_lock_irqsave(&mac->lock, flags); 489 spin_lock_irqsave(&mac->lock, flags);
478 if (rate != mac->rts_rate) { 490 if (hi_rate != mac->rts_rate) {
479 mac->rts_rate = rate; 491 mac->rts_rate = hi_rate;
480 need_set_rts_cts = 1; 492 need_set_rts_cts = 1;
481 } 493 }
482 spin_unlock_irqrestore(&mac->lock, flags); 494 spin_unlock_irqrestore(&mac->lock, flags);
@@ -1072,43 +1084,75 @@ static int fill_rx_stats(struct ieee80211_rx_stats *stats,
1072 return 0; 1084 return 0;
1073} 1085}
1074 1086
1075int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length) 1087static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
1076{ 1088{
1077 int r; 1089 int r;
1078 struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); 1090 struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
1079 struct ieee80211_rx_stats stats; 1091 struct ieee80211_rx_stats stats;
1080 const struct rx_status *status; 1092 const struct rx_status *status;
1081 struct sk_buff *skb;
1082 1093
1083 if (length < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN + 1094 if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
1084 IEEE80211_FCS_LEN + sizeof(struct rx_status)) 1095 IEEE80211_FCS_LEN + sizeof(struct rx_status))
1085 return -EINVAL; 1096 {
1097 dev_dbg_f(zd_mac_dev(mac), "Packet with length %u to small.\n",
1098 skb->len);
1099 goto free_skb;
1100 }
1086 1101
1087 r = fill_rx_stats(&stats, &status, mac, buffer, length); 1102 r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
1088 if (r) 1103 if (r) {
1089 return r; 1104 /* Only packets with rx errors are included here. */
1105 goto free_skb;
1106 }
1090 1107
1091 length -= ZD_PLCP_HEADER_SIZE+IEEE80211_FCS_LEN+ 1108 __skb_pull(skb, ZD_PLCP_HEADER_SIZE);
1092 sizeof(struct rx_status); 1109 __skb_trim(skb, skb->len -
1093 buffer += ZD_PLCP_HEADER_SIZE; 1110 (IEEE80211_FCS_LEN + sizeof(struct rx_status)));
1094 1111
1095 update_qual_rssi(mac, buffer, length, stats.signal, stats.rssi); 1112 update_qual_rssi(mac, skb->data, skb->len, stats.signal,
1113 status->signal_strength);
1096 1114
1097 r = filter_rx(ieee, buffer, length, &stats); 1115 r = filter_rx(ieee, skb->data, skb->len, &stats);
1098 if (r <= 0) 1116 if (r <= 0) {
1099 return r; 1117 if (r < 0)
1118 dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
1119 goto free_skb;
1120 }
1100 1121
1101 skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
1102 if (!skb)
1103 return -ENOMEM;
1104 if (ieee->iw_mode == IW_MODE_MONITOR) 1122 if (ieee->iw_mode == IW_MODE_MONITOR)
1105 fill_rt_header(skb_put(skb, sizeof(struct zd_rt_hdr)), mac, 1123 fill_rt_header(skb_push(skb, sizeof(struct zd_rt_hdr)), mac,
1106 &stats, status); 1124 &stats, status);
1107 memcpy(skb_put(skb, length), buffer, length);
1108 1125
1109 r = ieee80211_rx(ieee, skb, &stats); 1126 r = ieee80211_rx(ieee, skb, &stats);
1110 if (!r) 1127 if (r)
1111 dev_kfree_skb_any(skb); 1128 return;
1129free_skb:
1130 /* We are always in a soft irq. */
1131 dev_kfree_skb(skb);
1132}
1133
1134static void do_rx(unsigned long mac_ptr)
1135{
1136 struct zd_mac *mac = (struct zd_mac *)mac_ptr;
1137 struct sk_buff *skb;
1138
1139 while ((skb = skb_dequeue(&mac->rx_queue)) != NULL)
1140 zd_mac_rx(mac, skb);
1141}
1142
1143int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
1144{
1145 struct sk_buff *skb;
1146
1147 skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
1148 if (!skb) {
1149 dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
1150 return -ENOMEM;
1151 }
1152 skb_reserve(skb, sizeof(struct zd_rt_hdr));
1153 memcpy(__skb_put(skb, length), buffer, length);
1154 skb_queue_tail(&mac->rx_queue, skb);
1155 tasklet_schedule(&mac->rx_tasklet);
1112 return 0; 1156 return 0;
1113} 1157}
1114 1158
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index f0cf05dc7d3e..faf4c7828d4e 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -138,6 +138,9 @@ struct zd_mac {
138 struct delayed_work set_rts_cts_work; 138 struct delayed_work set_rts_cts_work;
139 struct delayed_work set_basic_rates_work; 139 struct delayed_work set_basic_rates_work;
140 140
141 struct tasklet_struct rx_tasklet;
142 struct sk_buff_head rx_queue;
143
141 unsigned int stats_count; 144 unsigned int stats_count;
142 u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE]; 145 u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
143 u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE]; 146 u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE];
@@ -193,7 +196,7 @@ int zd_mac_stop(struct net_device *netdev);
193int zd_mac_set_mac_address(struct net_device *dev, void *p); 196int zd_mac_set_mac_address(struct net_device *dev, void *p);
194void zd_mac_set_multicast_list(struct net_device *netdev); 197void zd_mac_set_multicast_list(struct net_device *netdev);
195 198
196int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length); 199int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length);
197 200
198int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain); 201int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain);
199u8 zd_mac_get_regdomain(struct zd_mac *zd_mac); 202u8 zd_mac_get_regdomain(struct zd_mac *zd_mac);
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index aa782e88754b..605e96e74057 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -598,13 +598,13 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
598 n = l+k; 598 n = l+k;
599 if (n > length) 599 if (n > length)
600 return; 600 return;
601 zd_mac_rx(mac, buffer+l, k); 601 zd_mac_rx_irq(mac, buffer+l, k);
602 if (i >= 2) 602 if (i >= 2)
603 return; 603 return;
604 l = (n+3) & ~3; 604 l = (n+3) & ~3;
605 } 605 }
606 } else { 606 } else {
607 zd_mac_rx(mac, buffer, length); 607 zd_mac_rx_irq(mac, buffer, length);
608 } 608 }
609} 609}
610 610