[RFC AR6000 patch V4] Set hardware unavailable during wext_ioctl when the suspend or rfkill is send

Michael Trimarchi trimarchi at gandalf.sssup.it
Tue Mar 31 18:24:03 CEST 2009


The ioctl wext etc, seems to be broken because they don't take any lock
during shutdown. If the user do an echo to the state variabile of the
rfkill during the network scanning the system can go in panic. It
introduces a semaphore variable to the ar priv data.

Signed-off-by: Michael Trimarchi <michael at panicking.kicks-ass.org>
---
 drivers/ar6000/ar6000/ar6000_drv.c   |    5 +-
 drivers/ar6000/ar6000/ar6000_drv.h   |    1 +
 drivers/ar6000/ar6000/wireless_ext.c |  136 ++++++++++++++++++++++++----------
 3 files changed, 101 insertions(+), 41 deletions(-)

diff --git a/drivers/ar6000/ar6000/ar6000_drv.c b/drivers/ar6000/ar6000/ar6000_drv.c
index 21504f2..87194d4 100644
--- a/drivers/ar6000/ar6000/ar6000_drv.c
+++ b/drivers/ar6000/ar6000/ar6000_drv.c
@@ -902,6 +902,7 @@ ar6000_avail_ev(HTC_HANDLE HTCHandle)
     AR_DEBUG_PRINTF("ar6000_avail: name=%s htcTarget=0x%x, dev=0x%x (%d), ar=0x%x\n",
                     dev->name, (A_UINT32)HTCHandle, (A_UINT32)dev, device_index,
                     (A_UINT32)ar);
+    init_rwsem(&ar->arHwAvail);
 }

 static void ar6000_target_failure(void *Instance, A_STATUS Status)
@@ -942,7 +943,9 @@ static void
 ar6000_unavail_ev(void *Instance)
 {
     AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance;
-        /* NULL out it's entry in the global list */
+    /* NULL out it's entry in the global list */
+
+    down_write(&ar->arHwAvail);
     ar6000_devices[ar->arDeviceIndex] = NULL;
     ar6000_destroy(ar->arNetDev, 1);
 }
diff --git a/drivers/ar6000/ar6000/ar6000_drv.h b/drivers/ar6000/ar6000/ar6000_drv.h
index 784f158..c8c273c 100644
--- a/drivers/ar6000/ar6000/ar6000_drv.h
+++ b/drivers/ar6000/ar6000/ar6000_drv.h
@@ -205,6 +205,7 @@ typedef struct ar6_softc {
     HTC_HANDLE              arHtcTarget;
     void                    *arHifDevice;
     spinlock_t              arLock;
+    struct rw_semaphore     arHwAvail;
     struct semaphore        arSem;
     int                     arRxBuffers[WMI_PRI_MAX_COUNT];
     int                     arSsidLen;
diff --git a/drivers/ar6000/ar6000/wireless_ext.c b/drivers/ar6000/ar6000/wireless_ext.c
index d9a5920..55f78d6 100644
--- a/drivers/ar6000/ar6000/wireless_ext.c
+++ b/drivers/ar6000/ar6000/wireless_ext.c
@@ -25,6 +25,20 @@ extern unsigned int wmitimeout;
 extern A_WAITQUEUE_HEAD arEvent;
 extern wait_queue_head_t ar6000_scan_queue;

+#define DECLARE_LOCKED_VERSION(_name) \
+int lock_##_name(struct net_device *dev, struct iw_request_info *info, \
+                void *p, char *data) \
+{ \
+	AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);	\
+	int ret = -EAGAIN;					\
+								\
+	if (down_read_trylock(&ar->arHwAvail)) {		\
+		ret = _name(dev, info, p, data);		\
+		up_read(&ar->arHwAvail);			\
+	}							\
+	return ret;						\
+}
+
 /*
  * Encode a WPA or RSN information element as a custom
  * element using the hostap format.
@@ -1849,21 +1863,63 @@ ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi)
     iq->updated = 7;
 }

+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwname)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwfreq)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwmode)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwfreq)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwmode)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwsens)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwsens)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwrange)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwap)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwap)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_iwaplist)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwscan)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwscan)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwessid)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwessid)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwrate)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwrate)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwtxpow)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwtxpow)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwretry)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwretry)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwencode)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwencode)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwpower)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwpower)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwgenie)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwgenie)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwauth)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwauth)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_siwencodeext)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_giwencodeext)
+
+/* private handler */
+DECLARE_LOCKED_VERSION(ar6000_ioctl_setparam)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_getparam)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_setkey)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_setwmmparams)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_delkey)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_getwmmparams)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_setoptie)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_setmlme)
+DECLARE_LOCKED_VERSION(ar6000_ioctl_addpmkid)

 /* Structures to export the Wireless Handlers */
 static const iw_handler ath_handlers[] = {
     (iw_handler) NULL,                          /* SIOCSIWCOMMIT */
-    (iw_handler) ar6000_ioctl_giwname,          /* SIOCGIWNAME */
+    (iw_handler) lock_ar6000_ioctl_giwname,          /* SIOCGIWNAME */
     (iw_handler) NULL,                          /* SIOCSIWNWID */
     (iw_handler) NULL,                          /* SIOCGIWNWID */
-    (iw_handler) ar6000_ioctl_siwfreq,          /* SIOCSIWFREQ */
-    (iw_handler) ar6000_ioctl_giwfreq,          /* SIOCGIWFREQ */
-    (iw_handler) ar6000_ioctl_siwmode,          /* SIOCSIWMODE */
-    (iw_handler) ar6000_ioctl_giwmode,          /* SIOCGIWMODE */
-    (iw_handler) ar6000_ioctl_siwsens,          /* SIOCSIWSENS */
-    (iw_handler) ar6000_ioctl_giwsens,          /* SIOCGIWSENS */
+    (iw_handler) lock_ar6000_ioctl_siwfreq,          /* SIOCSIWFREQ */
+    (iw_handler) lock_ar6000_ioctl_giwfreq,          /* SIOCGIWFREQ */
+    (iw_handler) lock_ar6000_ioctl_siwmode,          /* SIOCSIWMODE */
+    (iw_handler) lock_ar6000_ioctl_giwmode,          /* SIOCGIWMODE */
+    (iw_handler) lock_ar6000_ioctl_siwsens,          /* SIOCSIWSENS */
+    (iw_handler) lock_ar6000_ioctl_giwsens,          /* SIOCGIWSENS */
     (iw_handler) NULL /* not _used */,          /* SIOCSIWRANGE */
-    (iw_handler) ar6000_ioctl_giwrange,         /* SIOCGIWRANGE */
+    (iw_handler) lock_ar6000_ioctl_giwrange,         /* SIOCGIWRANGE */
     (iw_handler) NULL /* not used */,           /* SIOCSIWPRIV */
     (iw_handler) NULL /* kernel code */,        /* SIOCGIWPRIV */
     (iw_handler) NULL /* not used */,           /* SIOCSIWSTATS */
@@ -1872,53 +1928,53 @@ static const iw_handler ath_handlers[] = {
     (iw_handler) NULL,                          /* SIOCGIWSPY */
     (iw_handler) NULL,                          /* SIOCSIWTHRSPY */
     (iw_handler) NULL,                          /* SIOCGIWTHRSPY */
-    (iw_handler) ar6000_ioctl_siwap,            /* SIOCSIWAP */
-    (iw_handler) ar6000_ioctl_giwap,            /* SIOCGIWAP */
+    (iw_handler) lock_ar6000_ioctl_siwap,            /* SIOCSIWAP */
+    (iw_handler) lock_ar6000_ioctl_giwap,            /* SIOCGIWAP */
     (iw_handler) NULL,                          /* -- hole -- */
-    (iw_handler) ar6000_ioctl_iwaplist,         /* SIOCGIWAPLIST */
-    (iw_handler) ar6000_ioctl_siwscan,          /* SIOCSIWSCAN */
-    (iw_handler) ar6000_ioctl_giwscan,          /* SIOCGIWSCAN */
-    (iw_handler) ar6000_ioctl_siwessid,         /* SIOCSIWESSID */
-    (iw_handler) ar6000_ioctl_giwessid,         /* SIOCGIWESSID */
+    (iw_handler) lock_ar6000_ioctl_iwaplist,         /* SIOCGIWAPLIST */
+    (iw_handler) lock_ar6000_ioctl_siwscan,          /* SIOCSIWSCAN */
+    (iw_handler) lock_ar6000_ioctl_giwscan,          /* SIOCGIWSCAN */
+    (iw_handler) lock_ar6000_ioctl_siwessid,         /* SIOCSIWESSID */
+    (iw_handler) lock_ar6000_ioctl_giwessid,         /* SIOCGIWESSID */
     (iw_handler) NULL,                          /* SIOCSIWNICKN */
     (iw_handler) NULL,                          /* SIOCGIWNICKN */
     (iw_handler) NULL,                          /* -- hole -- */
     (iw_handler) NULL,                          /* -- hole -- */
-    (iw_handler) ar6000_ioctl_siwrate,          /* SIOCSIWRATE */
-    (iw_handler) ar6000_ioctl_giwrate,          /* SIOCGIWRATE */
+    (iw_handler) lock_ar6000_ioctl_siwrate,          /* SIOCSIWRATE */
+    (iw_handler) lock_ar6000_ioctl_giwrate,          /* SIOCGIWRATE */
     (iw_handler) NULL,           /* SIOCSIWRTS */
     (iw_handler) NULL,           /* SIOCGIWRTS */
     (iw_handler) NULL,          /* SIOCSIWFRAG */
     (iw_handler) NULL,          /* SIOCGIWFRAG */
-    (iw_handler) ar6000_ioctl_siwtxpow,         /* SIOCSIWTXPOW */
-    (iw_handler) ar6000_ioctl_giwtxpow,         /* SIOCGIWTXPOW */
-    (iw_handler) ar6000_ioctl_siwretry,         /* SIOCSIWRETRY */
-    (iw_handler) ar6000_ioctl_giwretry,         /* SIOCGIWRETRY */
-    (iw_handler) ar6000_ioctl_siwencode,        /* SIOCSIWENCODE */
-    (iw_handler) ar6000_ioctl_giwencode,        /* SIOCGIWENCODE */
-    (iw_handler) ar6000_ioctl_siwpower,         /* SIOCSIWPOWER */
-    (iw_handler) ar6000_ioctl_giwpower,         /* SIOCGIWPOWER */
+    (iw_handler) lock_ar6000_ioctl_siwtxpow,         /* SIOCSIWTXPOW */
+    (iw_handler) lock_ar6000_ioctl_giwtxpow,         /* SIOCGIWTXPOW */
+    (iw_handler) lock_ar6000_ioctl_siwretry,         /* SIOCSIWRETRY */
+    (iw_handler) lock_ar6000_ioctl_giwretry,         /* SIOCGIWRETRY */
+    (iw_handler) lock_ar6000_ioctl_siwencode,        /* SIOCSIWENCODE */
+    (iw_handler) lock_ar6000_ioctl_giwencode,        /* SIOCGIWENCODE */
+    (iw_handler) lock_ar6000_ioctl_siwpower,         /* SIOCSIWPOWER */
+    (iw_handler) lock_ar6000_ioctl_giwpower,         /* SIOCGIWPOWER */
     (iw_handler) NULL,	/* -- hole -- */
     (iw_handler) NULL,	/* -- hole -- */
-    (iw_handler) ar6000_ioctl_siwgenie,	/* SIOCSIWGENIE */
-    (iw_handler) ar6000_ioctl_giwgenie,	/* SIOCGIWGENIE */
-    (iw_handler) ar6000_ioctl_siwauth,	/* SIOCSIWAUTH */
-    (iw_handler) ar6000_ioctl_giwauth,	/* SIOCGIWAUTH */
-    (iw_handler) ar6000_ioctl_siwencodeext,/* SIOCSIWENCODEEXT */
-    (iw_handler) ar6000_ioctl_giwencodeext,/* SIOCGIWENCODEEXT */
+    (iw_handler) lock_ar6000_ioctl_siwgenie,	/* SIOCSIWGENIE */
+    (iw_handler) lock_ar6000_ioctl_giwgenie,	/* SIOCGIWGENIE */
+    (iw_handler) lock_ar6000_ioctl_siwauth,	/* SIOCSIWAUTH */
+    (iw_handler) lock_ar6000_ioctl_giwauth,	/* SIOCGIWAUTH */
+    (iw_handler) lock_ar6000_ioctl_siwencodeext,/* SIOCSIWENCODEEXT */
+    (iw_handler) lock_ar6000_ioctl_giwencodeext,/* SIOCGIWENCODEEXT */
     (iw_handler) NULL,		/* SIOCSIWPMKSA */
 };

 static const iw_handler ath_priv_handlers[] = {
-    (iw_handler) ar6000_ioctl_setparam,         /* SIOCWFIRSTPRIV+0 */
-    (iw_handler) ar6000_ioctl_getparam,         /* SIOCWFIRSTPRIV+1 */
-    (iw_handler) ar6000_ioctl_setkey,           /* SIOCWFIRSTPRIV+2 */
-    (iw_handler) ar6000_ioctl_setwmmparams,     /* SIOCWFIRSTPRIV+3 */
-    (iw_handler) ar6000_ioctl_delkey,           /* SIOCWFIRSTPRIV+4 */
-    (iw_handler) ar6000_ioctl_getwmmparams,     /* SIOCWFIRSTPRIV+5 */
-    (iw_handler) ar6000_ioctl_setoptie,         /* SIOCWFIRSTPRIV+6 */
-    (iw_handler) ar6000_ioctl_setmlme,          /* SIOCWFIRSTPRIV+7 */
-    (iw_handler) ar6000_ioctl_addpmkid,         /* SIOCWFIRSTPRIV+8 */
+    (iw_handler) lock_ar6000_ioctl_setparam,         /* SIOCWFIRSTPRIV+0 */
+    (iw_handler) lock_ar6000_ioctl_getparam,         /* SIOCWFIRSTPRIV+1 */
+    (iw_handler) lock_ar6000_ioctl_setkey,           /* SIOCWFIRSTPRIV+2 */
+    (iw_handler) lock_ar6000_ioctl_setwmmparams,     /* SIOCWFIRSTPRIV+3 */
+    (iw_handler) lock_ar6000_ioctl_delkey,           /* SIOCWFIRSTPRIV+4 */
+    (iw_handler) lock_ar6000_ioctl_getwmmparams,     /* SIOCWFIRSTPRIV+5 */
+    (iw_handler) lock_ar6000_ioctl_setoptie,         /* SIOCWFIRSTPRIV+6 */
+    (iw_handler) lock_ar6000_ioctl_setmlme,          /* SIOCWFIRSTPRIV+7 */
+    (iw_handler) lock_ar6000_ioctl_addpmkid,         /* SIOCWFIRSTPRIV+8 */
 };

 #define IW_PRIV_TYPE_KEY \
--
1.5.6.5




More information about the openmoko-kernel mailing list