Commit a2ca44c3 authored by Jeff Garzik's avatar Jeff Garzik

Merge branch 'fixes-jgarzik' of...

Merge branch 'fixes-jgarzik' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream-fixes
parents a041fe2e 53c57255
...@@ -3183,6 +3183,9 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work) ...@@ -3183,6 +3183,9 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work)
unsigned long orig_trans_start = 0; unsigned long orig_trans_start = 0;
mutex_lock(&bcm->mutex); mutex_lock(&bcm->mutex);
/* keep from doing and rearming periodic work if shutting down */
if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT)
goto unlock_mutex;
if (unlikely(bcm->periodic_state % 60 == 0)) { if (unlikely(bcm->periodic_state % 60 == 0)) {
/* Periodic work will take a long time, so we want it to /* Periodic work will take a long time, so we want it to
* be preemtible. * be preemtible.
...@@ -3228,14 +3231,10 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work) ...@@ -3228,14 +3231,10 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work)
mmiowb(); mmiowb();
bcm->periodic_state++; bcm->periodic_state++;
spin_unlock_irqrestore(&bcm->irq_lock, flags); spin_unlock_irqrestore(&bcm->irq_lock, flags);
unlock_mutex:
mutex_unlock(&bcm->mutex); mutex_unlock(&bcm->mutex);
} }
void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
{
cancel_rearming_delayed_work(&bcm->periodic_work);
}
void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
{ {
struct delayed_work *work = &bcm->periodic_work; struct delayed_work *work = &bcm->periodic_work;
...@@ -3285,6 +3284,14 @@ static int bcm43xx_rng_init(struct bcm43xx_private *bcm) ...@@ -3285,6 +3284,14 @@ static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
return err; return err;
} }
void bcm43xx_cancel_work(struct bcm43xx_private *bcm)
{
/* The system must be unlocked when this routine is entered.
* If not, the next 2 steps may deadlock */
cancel_work_sync(&bcm->restart_work);
cancel_delayed_work_sync(&bcm->periodic_work);
}
static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm) static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
{ {
int ret = 0; int ret = 0;
...@@ -3321,7 +3328,12 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) ...@@ -3321,7 +3328,12 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm)
{ {
bcm43xx_rng_exit(bcm); bcm43xx_rng_exit(bcm);
bcm43xx_sysfs_unregister(bcm); bcm43xx_sysfs_unregister(bcm);
bcm43xx_periodic_tasks_delete(bcm);
mutex_lock(&(bcm)->mutex);
bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
mutex_unlock(&(bcm)->mutex);
bcm43xx_cancel_work(bcm);
mutex_lock(&(bcm)->mutex); mutex_lock(&(bcm)->mutex);
bcm43xx_shutdown_all_wireless_cores(bcm); bcm43xx_shutdown_all_wireless_cores(bcm);
...@@ -4016,7 +4028,7 @@ static int bcm43xx_net_stop(struct net_device *net_dev) ...@@ -4016,7 +4028,7 @@ static int bcm43xx_net_stop(struct net_device *net_dev)
err = bcm43xx_disable_interrupts_sync(bcm); err = bcm43xx_disable_interrupts_sync(bcm);
assert(!err); assert(!err);
bcm43xx_free_board(bcm); bcm43xx_free_board(bcm);
flush_scheduled_work(); bcm43xx_cancel_work(bcm);
return 0; return 0;
} }
...@@ -4148,9 +4160,9 @@ static void bcm43xx_chip_reset(struct work_struct *work) ...@@ -4148,9 +4160,9 @@ static void bcm43xx_chip_reset(struct work_struct *work)
struct bcm43xx_phyinfo *phy; struct bcm43xx_phyinfo *phy;
int err = -ENODEV; int err = -ENODEV;
bcm43xx_cancel_work(bcm);
mutex_lock(&(bcm)->mutex); mutex_lock(&(bcm)->mutex);
if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
bcm43xx_periodic_tasks_delete(bcm);
phy = bcm43xx_current_phy(bcm); phy = bcm43xx_current_phy(bcm);
err = bcm43xx_select_wireless_core(bcm, phy->type); err = bcm43xx_select_wireless_core(bcm, phy->type);
if (!err) if (!err)
......
...@@ -122,7 +122,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); ...@@ -122,7 +122,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
void bcm43xx_mac_enable(struct bcm43xx_private *bcm); void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm); void bcm43xx_cancel_work(struct bcm43xx_private *bcm);
void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm); void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm);
void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
......
...@@ -327,7 +327,7 @@ static ssize_t bcm43xx_attr_phymode_store(struct device *dev, ...@@ -327,7 +327,7 @@ static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
goto out; goto out;
} }
bcm43xx_periodic_tasks_delete(bcm); bcm43xx_cancel_work(bcm);
mutex_lock(&(bcm)->mutex); mutex_lock(&(bcm)->mutex);
err = bcm43xx_select_wireless_core(bcm, phytype); err = bcm43xx_select_wireless_core(bcm, phytype);
if (!err) if (!err)
......
...@@ -2311,8 +2311,10 @@ static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long ar ...@@ -2311,8 +2311,10 @@ static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long ar
struct iwreq __user *iwr_u; struct iwreq __user *iwr_u;
struct iw_point __user *iwp; struct iw_point __user *iwp;
struct compat_iw_point __user *iwp_u; struct compat_iw_point __user *iwp_u;
compat_caddr_t pointer; compat_caddr_t pointer_u;
void __user *pointer;
__u16 length, flags; __u16 length, flags;
int ret;
iwr_u = compat_ptr(arg); iwr_u = compat_ptr(arg);
iwp_u = (struct compat_iw_point __user *) &iwr_u->u.data; iwp_u = (struct compat_iw_point __user *) &iwr_u->u.data;
...@@ -2330,17 +2332,29 @@ static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long ar ...@@ -2330,17 +2332,29 @@ static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long ar
sizeof(iwr->ifr_ifrn.ifrn_name))) sizeof(iwr->ifr_ifrn.ifrn_name)))
return -EFAULT; return -EFAULT;
if (__get_user(pointer, &iwp_u->pointer) || if (__get_user(pointer_u, &iwp_u->pointer) ||
__get_user(length, &iwp_u->length) || __get_user(length, &iwp_u->length) ||
__get_user(flags, &iwp_u->flags)) __get_user(flags, &iwp_u->flags))
return -EFAULT; return -EFAULT;
if (__put_user(compat_ptr(pointer), &iwp->pointer) || if (__put_user(compat_ptr(pointer_u), &iwp->pointer) ||
__put_user(length, &iwp->length) || __put_user(length, &iwp->length) ||
__put_user(flags, &iwp->flags)) __put_user(flags, &iwp->flags))
return -EFAULT; return -EFAULT;
return sys_ioctl(fd, cmd, (unsigned long) iwr); ret = sys_ioctl(fd, cmd, (unsigned long) iwr);
if (__get_user(pointer, &iwp->pointer) ||
__get_user(length, &iwp->length) ||
__get_user(flags, &iwp->flags))
return -EFAULT;
if (__put_user(ptr_to_compat(pointer), &iwp_u->pointer) ||
__put_user(length, &iwp_u->length) ||
__put_user(flags, &iwp_u->flags))
return -EFAULT;
return ret;
} }
/* Since old style bridge ioctl's endup using SIOCDEVPRIVATE /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment