aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco/orinoco.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/orinoco/orinoco.c')
-rw-r--r--drivers/net/wireless/orinoco/orinoco.c60
1 files changed, 39 insertions, 21 deletions
diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c
index bc84e2792f8a..45a04faa7818 100644
--- a/drivers/net/wireless/orinoco/orinoco.c
+++ b/drivers/net/wireless/orinoco/orinoco.c
@@ -1610,6 +1610,16 @@ static void orinoco_rx_isr_tasklet(unsigned long data)
1610 struct orinoco_rx_data *rx_data, *temp; 1610 struct orinoco_rx_data *rx_data, *temp;
1611 struct hermes_rx_descriptor *desc; 1611 struct hermes_rx_descriptor *desc;
1612 struct sk_buff *skb; 1612 struct sk_buff *skb;
1613 unsigned long flags;
1614
1615 /* orinoco_rx requires the driver lock, and we also need to
1616 * protect priv->rx_list, so just hold the lock over the
1617 * lot.
1618 *
1619 * If orinoco_lock fails, we've unplugged the card. In this
1620 * case just abort. */
1621 if (orinoco_lock(priv, &flags) != 0)
1622 return;
1613 1623
1614 /* extract desc and skb from queue */ 1624 /* extract desc and skb from queue */
1615 list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) { 1625 list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
@@ -1622,6 +1632,8 @@ static void orinoco_rx_isr_tasklet(unsigned long data)
1622 1632
1623 kfree(desc); 1633 kfree(desc);
1624 } 1634 }
1635
1636 orinoco_unlock(priv, &flags);
1625} 1637}
1626 1638
1627/********************************************************************/ 1639/********************************************************************/
@@ -1661,7 +1673,7 @@ static void print_linkstatus(struct net_device *dev, u16 status)
1661 s = "UNKNOWN"; 1673 s = "UNKNOWN";
1662 } 1674 }
1663 1675
1664 printk(KERN_INFO "%s: New link status: %s (%04x)\n", 1676 printk(KERN_DEBUG "%s: New link status: %s (%04x)\n",
1665 dev->name, s, status); 1677 dev->name, s, status);
1666} 1678}
1667 1679
@@ -3645,12 +3657,22 @@ struct net_device
3645void free_orinocodev(struct net_device *dev) 3657void free_orinocodev(struct net_device *dev)
3646{ 3658{
3647 struct orinoco_private *priv = netdev_priv(dev); 3659 struct orinoco_private *priv = netdev_priv(dev);
3660 struct orinoco_rx_data *rx_data, *temp;
3648 3661
3649 /* No need to empty priv->rx_list: if the tasklet is scheduled 3662 /* If the tasklet is scheduled when we call tasklet_kill it
3650 * when we call tasklet_kill it will run one final time, 3663 * will run one final time. However the tasklet will only
3651 * emptying the list */ 3664 * drain priv->rx_list if the hw is still available. */
3652 tasklet_kill(&priv->rx_tasklet); 3665 tasklet_kill(&priv->rx_tasklet);
3653 3666
3667 /* Explicitly drain priv->rx_list */
3668 list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
3669 list_del(&rx_data->list);
3670
3671 dev_kfree_skb(rx_data->skb);
3672 kfree(rx_data->desc);
3673 kfree(rx_data);
3674 }
3675
3654 unregister_pm_notifier(&priv->pm_notifier); 3676 unregister_pm_notifier(&priv->pm_notifier);
3655 orinoco_uncache_fw(priv); 3677 orinoco_uncache_fw(priv);
3656 3678
@@ -5046,33 +5068,30 @@ static int orinoco_ioctl_set_genie(struct net_device *dev,
5046 struct orinoco_private *priv = netdev_priv(dev); 5068 struct orinoco_private *priv = netdev_priv(dev);
5047 u8 *buf; 5069 u8 *buf;
5048 unsigned long flags; 5070 unsigned long flags;
5049 int err = 0;
5050 5071
5051 /* cut off at IEEE80211_MAX_DATA_LEN */ 5072 /* cut off at IEEE80211_MAX_DATA_LEN */
5052 if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) || 5073 if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
5053 (wrqu->data.length && (extra == NULL))) 5074 (wrqu->data.length && (extra == NULL)))
5054 return -EINVAL; 5075 return -EINVAL;
5055 5076
5056 if (orinoco_lock(priv, &flags) != 0)
5057 return -EBUSY;
5058
5059 if (wrqu->data.length) { 5077 if (wrqu->data.length) {
5060 buf = kmalloc(wrqu->data.length, GFP_KERNEL); 5078 buf = kmalloc(wrqu->data.length, GFP_KERNEL);
5061 if (buf == NULL) { 5079 if (buf == NULL)
5062 err = -ENOMEM; 5080 return -ENOMEM;
5063 goto out;
5064 }
5065 5081
5066 memcpy(buf, extra, wrqu->data.length); 5082 memcpy(buf, extra, wrqu->data.length);
5067 kfree(priv->wpa_ie); 5083 } else
5068 priv->wpa_ie = buf; 5084 buf = NULL;
5069 priv->wpa_ie_len = wrqu->data.length; 5085
5070 } else { 5086 if (orinoco_lock(priv, &flags) != 0) {
5071 kfree(priv->wpa_ie); 5087 kfree(buf);
5072 priv->wpa_ie = NULL; 5088 return -EBUSY;
5073 priv->wpa_ie_len = 0;
5074 } 5089 }
5075 5090
5091 kfree(priv->wpa_ie);
5092 priv->wpa_ie = buf;
5093 priv->wpa_ie_len = wrqu->data.length;
5094
5076 if (priv->wpa_ie) { 5095 if (priv->wpa_ie) {
5077 /* Looks like wl_lkm wants to check the auth alg, and 5096 /* Looks like wl_lkm wants to check the auth alg, and
5078 * somehow pass it to the firmware. 5097 * somehow pass it to the firmware.
@@ -5081,9 +5100,8 @@ static int orinoco_ioctl_set_genie(struct net_device *dev,
5081 */ 5100 */
5082 } 5101 }
5083 5102
5084out:
5085 orinoco_unlock(priv, &flags); 5103 orinoco_unlock(priv, &flags);
5086 return err; 5104 return 0;
5087} 5105}
5088 5106
5089static int orinoco_ioctl_get_genie(struct net_device *dev, 5107static int orinoco_ioctl_get_genie(struct net_device *dev,