aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rtl818x
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2008-12-10 00:34:27 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-12-12 14:02:06 -0500
commitc1db52b9d27ee6e15a7136e67e4a21dc916cd07f (patch)
treeecccf2807efe8e2f50e0a71b6a66751f17b8f16b /drivers/net/wireless/rtl818x
parent388cdf31db6dfc3d175786a76989266380e12c26 (diff)
rtl8187: Use usb anchor facilities to manage urbs
When SLUB debugging is enabled in the kernel, and the boot command includes the option "slub_debug=P", rtl8187 encounters a GPF due to a read-after-free of a urb. Following the example of changes in p54usb to fix the same problem, the code has been modified to use the usb_anchor_urb() method. With this change, the USB core handles the freeing of urb's. This patch fixes the problem reported in Kernel Bugzilla #12185 (http://bugzilla.kernel.org/show_bug.cgi?id=12185). Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Tested-by: Hin-Tak Leung <htl10@users.sourceforge.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rtl818x')
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187.h2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c75
2 files changed, 52 insertions, 25 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h
index c385407a9941..3b1e1c2aad26 100644
--- a/drivers/net/wireless/rtl818x/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187.h
@@ -99,6 +99,7 @@ struct rtl8187_priv {
99 struct ieee80211_supported_band band; 99 struct ieee80211_supported_band band;
100 struct usb_device *udev; 100 struct usb_device *udev;
101 u32 rx_conf; 101 u32 rx_conf;
102 struct usb_anchor anchored;
102 u16 txpwr_base; 103 u16 txpwr_base;
103 u8 asic_rev; 104 u8 asic_rev;
104 u8 is_rtl8187b; 105 u8 is_rtl8187b;
@@ -115,7 +116,6 @@ struct rtl8187_priv {
115 u8 aifsn[4]; 116 u8 aifsn[4];
116 struct { 117 struct {
117 __le64 buf; 118 __le64 buf;
118 struct urb *urb;
119 struct sk_buff_head queue; 119 struct sk_buff_head queue;
120 } b_tx_status; 120 } b_tx_status;
121}; 121};
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 417a2d7b5764..74f5449b7924 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -99,7 +99,6 @@ static const struct ieee80211_channel rtl818x_channels[] = {
99static void rtl8187_iowrite_async_cb(struct urb *urb) 99static void rtl8187_iowrite_async_cb(struct urb *urb)
100{ 100{
101 kfree(urb->context); 101 kfree(urb->context);
102 usb_free_urb(urb);
103} 102}
104 103
105static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr, 104static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr,
@@ -136,11 +135,13 @@ static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr,
136 usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0), 135 usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0),
137 (unsigned char *)dr, buf, len, 136 (unsigned char *)dr, buf, len,
138 rtl8187_iowrite_async_cb, buf); 137 rtl8187_iowrite_async_cb, buf);
138 usb_anchor_urb(urb, &priv->anchored);
139 rc = usb_submit_urb(urb, GFP_ATOMIC); 139 rc = usb_submit_urb(urb, GFP_ATOMIC);
140 if (rc < 0) { 140 if (rc < 0) {
141 kfree(buf); 141 kfree(buf);
142 usb_free_urb(urb); 142 usb_unanchor_urb(urb);
143 } 143 }
144 usb_free_urb(urb);
144} 145}
145 146
146static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv, 147static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv,
@@ -172,7 +173,6 @@ static void rtl8187_tx_cb(struct urb *urb)
172 struct ieee80211_hw *hw = info->rate_driver_data[0]; 173 struct ieee80211_hw *hw = info->rate_driver_data[0];
173 struct rtl8187_priv *priv = hw->priv; 174 struct rtl8187_priv *priv = hw->priv;
174 175
175 usb_free_urb(info->rate_driver_data[1]);
176 skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : 176 skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
177 sizeof(struct rtl8187_tx_hdr)); 177 sizeof(struct rtl8187_tx_hdr));
178 ieee80211_tx_info_clear_status(info); 178 ieee80211_tx_info_clear_status(info);
@@ -273,11 +273,13 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
273 273
274 usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), 274 usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep),
275 buf, skb->len, rtl8187_tx_cb, skb); 275 buf, skb->len, rtl8187_tx_cb, skb);
276 usb_anchor_urb(urb, &priv->anchored);
276 rc = usb_submit_urb(urb, GFP_ATOMIC); 277 rc = usb_submit_urb(urb, GFP_ATOMIC);
277 if (rc < 0) { 278 if (rc < 0) {
278 usb_free_urb(urb); 279 usb_unanchor_urb(urb);
279 kfree_skb(skb); 280 kfree_skb(skb);
280 } 281 }
282 usb_free_urb(urb);
281 283
282 return 0; 284 return 0;
283} 285}
@@ -301,14 +303,13 @@ static void rtl8187_rx_cb(struct urb *urb)
301 return; 303 return;
302 } 304 }
303 spin_unlock(&priv->rx_queue.lock); 305 spin_unlock(&priv->rx_queue.lock);
306 skb_put(skb, urb->actual_length);
304 307
305 if (unlikely(urb->status)) { 308 if (unlikely(urb->status)) {
306 usb_free_urb(urb);
307 dev_kfree_skb_irq(skb); 309 dev_kfree_skb_irq(skb);
308 return; 310 return;
309 } 311 }
310 312
311 skb_put(skb, urb->actual_length);
312 if (!priv->is_rtl8187b) { 313 if (!priv->is_rtl8187b) {
313 struct rtl8187_rx_hdr *hdr = 314 struct rtl8187_rx_hdr *hdr =
314 (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); 315 (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
@@ -361,7 +362,6 @@ static void rtl8187_rx_cb(struct urb *urb)
361 362
362 skb = dev_alloc_skb(RTL8187_MAX_RX); 363 skb = dev_alloc_skb(RTL8187_MAX_RX);
363 if (unlikely(!skb)) { 364 if (unlikely(!skb)) {
364 usb_free_urb(urb);
365 /* TODO check rx queue length and refill *somewhere* */ 365 /* TODO check rx queue length and refill *somewhere* */
366 return; 366 return;
367 } 367 }
@@ -373,24 +373,32 @@ static void rtl8187_rx_cb(struct urb *urb)
373 urb->context = skb; 373 urb->context = skb;
374 skb_queue_tail(&priv->rx_queue, skb); 374 skb_queue_tail(&priv->rx_queue, skb);
375 375
376 usb_submit_urb(urb, GFP_ATOMIC); 376 usb_anchor_urb(urb, &priv->anchored);
377 if (usb_submit_urb(urb, GFP_ATOMIC)) {
378 usb_unanchor_urb(urb);
379 skb_unlink(skb, &priv->rx_queue);
380 dev_kfree_skb_irq(skb);
381 }
377} 382}
378 383
379static int rtl8187_init_urbs(struct ieee80211_hw *dev) 384static int rtl8187_init_urbs(struct ieee80211_hw *dev)
380{ 385{
381 struct rtl8187_priv *priv = dev->priv; 386 struct rtl8187_priv *priv = dev->priv;
382 struct urb *entry; 387 struct urb *entry = NULL;
383 struct sk_buff *skb; 388 struct sk_buff *skb;
384 struct rtl8187_rx_info *info; 389 struct rtl8187_rx_info *info;
390 int ret = 0;
385 391
386 while (skb_queue_len(&priv->rx_queue) < 8) { 392 while (skb_queue_len(&priv->rx_queue) < 8) {
387 skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL); 393 skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
388 if (!skb) 394 if (!skb) {
389 break; 395 ret = -ENOMEM;
396 goto err;
397 }
390 entry = usb_alloc_urb(0, GFP_KERNEL); 398 entry = usb_alloc_urb(0, GFP_KERNEL);
391 if (!entry) { 399 if (!entry) {
392 kfree_skb(skb); 400 ret = -ENOMEM;
393 break; 401 goto err;
394 } 402 }
395 usb_fill_bulk_urb(entry, priv->udev, 403 usb_fill_bulk_urb(entry, priv->udev,
396 usb_rcvbulkpipe(priv->udev, 404 usb_rcvbulkpipe(priv->udev,
@@ -401,10 +409,22 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
401 info->urb = entry; 409 info->urb = entry;
402 info->dev = dev; 410 info->dev = dev;
403 skb_queue_tail(&priv->rx_queue, skb); 411 skb_queue_tail(&priv->rx_queue, skb);
404 usb_submit_urb(entry, GFP_KERNEL); 412 usb_anchor_urb(entry, &priv->anchored);
413 ret = usb_submit_urb(entry, GFP_KERNEL);
414 if (ret) {
415 skb_unlink(skb, &priv->rx_queue);
416 usb_unanchor_urb(entry);
417 goto err;
418 }
419 usb_free_urb(entry);
405 } 420 }
421 return ret;
406 422
407 return 0; 423err:
424 usb_free_urb(entry);
425 kfree_skb(skb);
426 usb_kill_anchored_urbs(&priv->anchored);
427 return ret;
408} 428}
409 429
410static void rtl8187b_status_cb(struct urb *urb) 430static void rtl8187b_status_cb(struct urb *urb)
@@ -414,10 +434,8 @@ static void rtl8187b_status_cb(struct urb *urb)
414 u64 val; 434 u64 val;
415 unsigned int cmd_type; 435 unsigned int cmd_type;
416 436
417 if (unlikely(urb->status)) { 437 if (unlikely(urb->status))
418 usb_free_urb(urb);
419 return; 438 return;
420 }
421 439
422 /* 440 /*
423 * Read from status buffer: 441 * Read from status buffer:
@@ -488,26 +506,32 @@ static void rtl8187b_status_cb(struct urb *urb)
488 spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags); 506 spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags);
489 } 507 }
490 508
491 usb_submit_urb(urb, GFP_ATOMIC); 509 usb_anchor_urb(urb, &priv->anchored);
510 if (usb_submit_urb(urb, GFP_ATOMIC))
511 usb_unanchor_urb(urb);
492} 512}
493 513
494static int rtl8187b_init_status_urb(struct ieee80211_hw *dev) 514static int rtl8187b_init_status_urb(struct ieee80211_hw *dev)
495{ 515{
496 struct rtl8187_priv *priv = dev->priv; 516 struct rtl8187_priv *priv = dev->priv;
497 struct urb *entry; 517 struct urb *entry;
518 int ret = 0;
498 519
499 entry = usb_alloc_urb(0, GFP_KERNEL); 520 entry = usb_alloc_urb(0, GFP_KERNEL);
500 if (!entry) 521 if (!entry)
501 return -ENOMEM; 522 return -ENOMEM;
502 priv->b_tx_status.urb = entry;
503 523
504 usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9), 524 usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9),
505 &priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf), 525 &priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf),
506 rtl8187b_status_cb, dev); 526 rtl8187b_status_cb, dev);
507 527
508 usb_submit_urb(entry, GFP_KERNEL); 528 usb_anchor_urb(entry, &priv->anchored);
529 ret = usb_submit_urb(entry, GFP_KERNEL);
530 if (ret)
531 usb_unanchor_urb(entry);
532 usb_free_urb(entry);
509 533
510 return 0; 534 return ret;
511} 535}
512 536
513static int rtl8187_cmd_reset(struct ieee80211_hw *dev) 537static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
@@ -841,6 +865,9 @@ static int rtl8187_start(struct ieee80211_hw *dev)
841 return ret; 865 return ret;
842 866
843 mutex_lock(&priv->conf_mutex); 867 mutex_lock(&priv->conf_mutex);
868
869 init_usb_anchor(&priv->anchored);
870
844 if (priv->is_rtl8187b) { 871 if (priv->is_rtl8187b) {
845 reg = RTL818X_RX_CONF_MGMT | 872 reg = RTL818X_RX_CONF_MGMT |
846 RTL818X_RX_CONF_DATA | 873 RTL818X_RX_CONF_DATA |
@@ -936,12 +963,12 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
936 963
937 while ((skb = skb_dequeue(&priv->rx_queue))) { 964 while ((skb = skb_dequeue(&priv->rx_queue))) {
938 info = (struct rtl8187_rx_info *)skb->cb; 965 info = (struct rtl8187_rx_info *)skb->cb;
939 usb_kill_urb(info->urb);
940 kfree_skb(skb); 966 kfree_skb(skb);
941 } 967 }
942 while ((skb = skb_dequeue(&priv->b_tx_status.queue))) 968 while ((skb = skb_dequeue(&priv->b_tx_status.queue)))
943 dev_kfree_skb_any(skb); 969 dev_kfree_skb_any(skb);
944 usb_kill_urb(priv->b_tx_status.urb); 970
971 usb_kill_anchored_urbs(&priv->anchored);
945 mutex_unlock(&priv->conf_mutex); 972 mutex_unlock(&priv->conf_mutex);
946} 973}
947 974