Re: No association with WPA and kernel 2.6.23.9

François Valenduc <[email protected]> Thu, 06 Dec 2007 20:43:09 +0100
Newsgroups gmane.linux.drivers.ipw2100.devel
Message-ID <[email protected]>
Paolo a écrit :
> On Thu, Dec 06, 2007 at 07:18:20AM +0100, Fran?ois Valenduc wrote:
>   
>> problem with the rf_kill switch. However, with kernel 2.6.22.14 it works
>> and with kernel 2.6.23.9, it doesn't work. So there really seems to be a
>> problem with the ipw2200 driver and kernel 2.6.23.9 (and newer).
>>     
>
> hm, check in both case:
>
> $ modinfo ipw2200|grep ^version
>
> and of course:
>
> $ wpa_supplicant -v
>
> You may want to try the latest wpa_supplicant, before tinckering further.
>
> Failing that, if you have both kernel src tree, check
>
> $ diff -u linux-2.6.22/drivers/net/wireless/ipw2200.c \
> 	linux-2.6.23/drivers/net/wireless/ipw2200.c
> $ diff -u linux-2.6.22/drivers/net/wireless/ipw2200.h \
> 	linux-2.6.23/drivers/net/wireless/ipw2200.h
>
> if no diffs show up, then the culprit is likely in changes in ieee802.
>
> If you're just interested in running .23.9 with a working ipw, you can try 
> to patch .23.9 with latest tarballs from ieee80211.sf.net and 
> ipw2200.sf.net (of course, do a suitable bakcup first, in case).
>
>
> HTH
> --
> paolo
>
>
> -------------------------------------------------------------------------
> SF.Net email is sponsored by: The Future of Linux Business White Paper
> from Novell.  From the desktop to the data center, Linux is going
> mainstream.  Let it simplify your IT future.
> http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
> _______________________________________________
> ipw2100-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/ipw2100-devel
>
>
>   
So, I tried with a newer version of wpa_supplicant (0.6.0 instead of
0.5.8) and it doesn't work better. I also tried with the latest
ieee80211 drivers (1.2.18) but that doesn't work too. I have tried WPA
with TKIP and AES encryption and I could never connect to my router.
However it works in unencrypted mode. Furthermore, there are well
differences between 2.6.22.14 and 2.6.23.9 in the ipw2200 driver. The
diff files are attached to this mail.
As you suggested, I will open a bug on bughost.org.

François

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell.  From the desktop to the data center, Linux is going
mainstream.  Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4

_______________________________________________
ipw2100-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ipw2100-devel
ipw2200.c.diff (text/plain, 6.7 KB)
--- drivers/net/wireless/ipw2200.c	2007-11-02 17:09:43.000000000 +0100
+++ ../linux-2.6.23/drivers/net/wireless/ipw2200.c	2007-11-29 18:48:10.000000000 +0100
@@ -70,7 +70,7 @@
 #define VQ
 #endif
 
-#define IPW2200_VERSION "1.2.0" VK VD VM VP VR VQ
+#define IPW2200_VERSION "1.2.2" VK VD VM VP VR VQ
 #define DRV_DESCRIPTION	"Intel(R) PRO/Wireless 2200/2915 Network Driver"
 #define DRV_COPYRIGHT	"Copyright(c) 2003-2006 Intel Corporation"
 #define DRV_VERSION     IPW2200_VERSION
@@ -1740,8 +1740,10 @@ static int ipw_radio_kill_sw(struct ipw_
 	if (disable_radio) {
 		priv->status |= STATUS_RF_KILL_SW;
 
-		if (priv->workqueue)
+		if (priv->workqueue) {
 			cancel_delayed_work(&priv->request_scan);
+			cancel_delayed_work(&priv->scan_event);
+		}
 		queue_work(priv->workqueue, &priv->down);
 	} else {
 		priv->status &= ~STATUS_RF_KILL_SW;
@@ -1751,7 +1753,7 @@ static int ipw_radio_kill_sw(struct ipw_
 			/* Make sure the RF_KILL check timer is running */
 			cancel_delayed_work(&priv->rf_kill);
 			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   2 * HZ);
+					   round_jiffies(2 * HZ));
 		} else
 			queue_work(priv->workqueue, &priv->up);
 	}
@@ -1992,6 +1994,7 @@ static void ipw_irq_tasklet(struct ipw_p
 		wake_up_interruptible(&priv->wait_command_queue);
 		priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
 		cancel_delayed_work(&priv->request_scan);
+		cancel_delayed_work(&priv->scan_event);
 		schedule_work(&priv->link_down);
 		queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);
 		handled |= IPW_INTA_BIT_RF_KILL_DONE;
@@ -2506,7 +2509,7 @@ static int ipw_send_power_mode(struct ip
 		break;
 	}
 
-	param = cpu_to_le32(mode);
+	param = cpu_to_le32(param);
 	return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param),
 				&param);
 }
@@ -4341,6 +4344,37 @@ static void ipw_handle_missed_beacon(str
 	IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count);
 }
 
+static void ipw_scan_event(struct work_struct *work)
+{
+	union iwreq_data wrqu;
+
+	struct ipw_priv *priv =
+		container_of(work, struct ipw_priv, scan_event.work);
+
+	wrqu.data.length = 0;
+	wrqu.data.flags = 0;
+	wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL);
+}
+
+static void handle_scan_event(struct ipw_priv *priv)
+{
+	/* Only userspace-requested scan completion events go out immediately */
+	if (!priv->user_requested_scan) {
+		if (!delayed_work_pending(&priv->scan_event))
+			queue_delayed_work(priv->workqueue, &priv->scan_event,
+					 round_jiffies(msecs_to_jiffies(4000)));
+	} else {
+		union iwreq_data wrqu;
+
+		priv->user_requested_scan = 0;
+		cancel_delayed_work(&priv->scan_event);
+
+		wrqu.data.length = 0;
+		wrqu.data.flags = 0;
+		wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL);
+	}
+}
+
 /**
  * Handle host notification packet.
  * Called from interrupt routine
@@ -4690,7 +4724,8 @@ static void ipw_rx_notification(struct i
 			else if (priv->config & CFG_BACKGROUND_SCAN
 				 && priv->status & STATUS_ASSOCIATED)
 				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan, HZ);
+						   &priv->request_scan,
+						   round_jiffies(HZ));
 
 			/* Send an empty event to user space.
 			 * We don't send the received data on the event because
@@ -4701,14 +4736,8 @@ static void ipw_rx_notification(struct i
 			 * on how the scan was initiated. User space can just
 			 * sync on periodic scan to get fresh data...
 			 * Jean II */
-			if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) {
-				union iwreq_data wrqu;
-
-				wrqu.data.length = 0;
-				wrqu.data.flags = 0;
-				wireless_send_event(priv->net_dev, SIOCGIWSCAN,
-						    &wrqu, NULL);
-			}
+			if (x->status == SCAN_COMPLETED_STATUS_COMPLETE)
+				handle_scan_event(priv);
 			break;
 		}
 
@@ -9471,6 +9500,10 @@ static int ipw_wx_set_scan(struct net_de
 	struct ipw_priv *priv = ieee80211_priv(dev);
 	struct iw_scan_req *req = (struct iw_scan_req *)extra;
 
+	mutex_lock(&priv->mutex);
+	priv->user_requested_scan = 1;
+	mutex_unlock(&priv->mutex);
+
 	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
 		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
 			ipw_request_direct_scan(priv, req->essid,
@@ -9567,6 +9600,7 @@ static int ipw_wx_set_power(struct net_d
 		priv->power_mode = IPW_POWER_ENABLED | IPW_POWER_BATTERY;
 	else
 		priv->power_mode = IPW_POWER_ENABLED | priv->power_mode;
+
 	err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode));
 	if (err) {
 		IPW_DEBUG_WX("failed setting power mode.\n");
@@ -9603,22 +9637,19 @@ static int ipw_wx_set_powermode(struct n
 	struct ipw_priv *priv = ieee80211_priv(dev);
 	int mode = *(int *)extra;
 	int err;
+
 	mutex_lock(&priv->mutex);
-	if ((mode < 1) || (mode > IPW_POWER_LIMIT)) {
+	if ((mode < 1) || (mode > IPW_POWER_LIMIT))
 		mode = IPW_POWER_AC;
-		priv->power_mode = mode;
-	} else {
-		priv->power_mode = IPW_POWER_ENABLED | mode;
-	}
 
-	if (priv->power_mode != mode) {
+	if (IPW_POWER_LEVEL(priv->power_mode) != mode) {
 		err = ipw_send_power_mode(priv, mode);
-
 		if (err) {
 			IPW_DEBUG_WX("failed setting power mode.\n");
 			mutex_unlock(&priv->mutex);
 			return err;
 		}
+		priv->power_mode = IPW_POWER_ENABLED | mode;
 	}
 	mutex_unlock(&priv->mutex);
 	return 0;
@@ -10554,7 +10585,7 @@ static irqreturn_t ipw_isr(int irq, void
 	spin_lock(&priv->irq_lock);
 
 	if (!(priv->status & STATUS_INT_ENABLED)) {
-		/* Shared IRQ */
+		/* IRQ is disabled */
 		goto none;
 	}
 
@@ -10648,6 +10679,7 @@ static void ipw_link_up(struct ipw_priv 
 	}
 
 	cancel_delayed_work(&priv->request_scan);
+	cancel_delayed_work(&priv->scan_event);
 	ipw_reset_stats(priv);
 	/* Ensure the rate is updated immediately */
 	priv->last_rate = ipw_get_current_rate(priv);
@@ -10685,7 +10717,8 @@ static void ipw_link_down(struct ipw_pri
 	if (!(priv->status & STATUS_EXIT_PENDING)) {
 		/* Queue up another scan... */
 		queue_delayed_work(priv->workqueue, &priv->request_scan, 0);
-	}
+	} else
+		cancel_delayed_work(&priv->scan_event);
 }
 
 static void ipw_bg_link_down(struct work_struct *work)
@@ -10715,6 +10748,7 @@ static int ipw_setup_deferred_work(struc
 	INIT_WORK(&priv->up, ipw_bg_up);
 	INIT_WORK(&priv->down, ipw_bg_down);
 	INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan);
+	INIT_DELAYED_WORK(&priv->scan_event, ipw_scan_event);
 	INIT_WORK(&priv->request_passive_scan, ipw_request_passive_scan);
 	INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats);
 	INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan);
@@ -11747,6 +11781,7 @@ static void ipw_pci_remove(struct pci_de
 	cancel_delayed_work(&priv->adhoc_check);
 	cancel_delayed_work(&priv->gather_stats);
 	cancel_delayed_work(&priv->request_scan);
+	cancel_delayed_work(&priv->scan_event);
 	cancel_delayed_work(&priv->rf_kill);
 	cancel_delayed_work(&priv->scan_check);
 	destroy_workqueue(priv->workqueue);
ipw2200.h.diff (text/plain, 640 B)
--- drivers/net/wireless/ipw2200.h	2007-10-09 22:31:38.000000000 +0200
+++ ../linux-2.6.23/drivers/net/wireless/ipw2200.h	2007-11-29 18:48:10.000000000 +0100
@@ -1288,6 +1288,8 @@ struct ipw_priv {
 
 	struct iw_public_data wireless_data;
 
+	int user_requested_scan;
+
 	struct workqueue_struct *workqueue;
 
 	struct delayed_work adhoc_check;
@@ -1296,6 +1298,7 @@ struct ipw_priv {
 	struct work_struct system_config;
 	struct work_struct rx_replenish;
 	struct delayed_work request_scan;
+	struct delayed_work scan_event;
   	struct work_struct request_passive_scan;
 	struct work_struct adapter_restart;
 	struct delayed_work rf_kill;