diff options
author | Dan Williams <dcbw@redhat.com> | 2007-06-18 12:01:12 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2007-06-28 07:48:47 -0400 |
commit | 18c96c3497aa871608d57ca5e08de3558159a6c9 (patch) | |
tree | 4dfcef0cef103a0312c8aa15dbbbed9056a211e0 /drivers/net/wireless | |
parent | f8f551089b0ca571b8f95465b6c3e1dd7bcea28e (diff) |
[PATCH] libertas: fix WPA associations by handling ENABLE_RSN correctly
Don't clobber the firmware's internal state machine by setting
ENABLE_RSN more than once during the 4-way handshake. Check what
the ENABLE_RSN status is and only set if it should be changed.
Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/libertas/assoc.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/cmdresp.c | 21 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/hostcmd.h | 2 |
4 files changed, 55 insertions, 8 deletions
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index f67efa0815fe..afd5617dd92b 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -323,6 +323,8 @@ static int assoc_helper_secinfo(wlan_private *priv, | |||
323 | { | 323 | { |
324 | wlan_adapter *adapter = priv->adapter; | 324 | wlan_adapter *adapter = priv->adapter; |
325 | int ret = 0; | 325 | int ret = 0; |
326 | u32 do_wpa; | ||
327 | u32 rsn = 0; | ||
326 | 328 | ||
327 | lbs_deb_enter(LBS_DEB_ASSOC); | 329 | lbs_deb_enter(LBS_DEB_ASSOC); |
328 | 330 | ||
@@ -333,12 +335,34 @@ static int assoc_helper_secinfo(wlan_private *priv, | |||
333 | if (ret) | 335 | if (ret) |
334 | goto out; | 336 | goto out; |
335 | 337 | ||
336 | /* enable/disable RSN */ | 338 | /* If RSN is already enabled, don't try to enable it again, since |
339 | * ENABLE_RSN resets internal state machines and will clobber the | ||
340 | * 4-way WPA handshake. | ||
341 | */ | ||
342 | |||
343 | /* Get RSN enabled/disabled */ | ||
337 | ret = libertas_prepare_and_send_command(priv, | 344 | ret = libertas_prepare_and_send_command(priv, |
338 | cmd_802_11_enable_rsn, | 345 | cmd_802_11_enable_rsn, |
339 | cmd_act_set, | 346 | cmd_act_set, |
340 | cmd_option_waitforrsp, | 347 | cmd_option_waitforrsp, |
341 | 0, assoc_req); | 348 | 0, &rsn); |
349 | if (ret) { | ||
350 | lbs_deb_assoc("Failed to get RSN status: %d", ret); | ||
351 | goto out; | ||
352 | } | ||
353 | |||
354 | /* Don't re-enable RSN if it's already enabled */ | ||
355 | do_wpa = (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled); | ||
356 | if (do_wpa == rsn) | ||
357 | goto out; | ||
358 | |||
359 | /* Set RSN enabled/disabled */ | ||
360 | rsn = do_wpa; | ||
361 | ret = libertas_prepare_and_send_command(priv, | ||
362 | cmd_802_11_enable_rsn, | ||
363 | cmd_act_set, | ||
364 | cmd_option_waitforrsp, | ||
365 | 0, &rsn); | ||
342 | 366 | ||
343 | out: | 367 | out: |
344 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 368 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 124e029f1bf4..13f6528abb00 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -228,17 +228,19 @@ static int wlan_cmd_802_11_enable_rsn(wlan_private * priv, | |||
228 | void * pdata_buf) | 228 | void * pdata_buf) |
229 | { | 229 | { |
230 | struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn; | 230 | struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn; |
231 | struct assoc_request * assoc_req = pdata_buf; | 231 | u32 * enable = pdata_buf; |
232 | 232 | ||
233 | lbs_deb_enter(LBS_DEB_CMD); | 233 | lbs_deb_enter(LBS_DEB_CMD); |
234 | 234 | ||
235 | cmd->command = cpu_to_le16(cmd_802_11_enable_rsn); | 235 | cmd->command = cpu_to_le16(cmd_802_11_enable_rsn); |
236 | cmd->size = cpu_to_le16(sizeof(*penableRSN) + S_DS_GEN); | 236 | cmd->size = cpu_to_le16(sizeof(*penableRSN) + S_DS_GEN); |
237 | penableRSN->action = cpu_to_le16(cmd_action); | 237 | penableRSN->action = cpu_to_le16(cmd_action); |
238 | if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { | 238 | |
239 | penableRSN->enable = cpu_to_le16(cmd_enable_rsn); | 239 | if (cmd_action == cmd_act_set) { |
240 | } else { | 240 | if (*enable) |
241 | penableRSN->enable = cpu_to_le16(cmd_disable_rsn); | 241 | penableRSN->enable = cpu_to_le16(cmd_enable_rsn); |
242 | else | ||
243 | penableRSN->enable = cpu_to_le16(cmd_enable_rsn); | ||
242 | } | 244 | } |
243 | 245 | ||
244 | lbs_deb_leave(LBS_DEB_CMD); | 246 | lbs_deb_leave(LBS_DEB_CMD); |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 0c3b9a583d83..6ac0d4752fa4 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -537,6 +537,24 @@ static int wlan_ret_get_log(wlan_private * priv, | |||
537 | return 0; | 537 | return 0; |
538 | } | 538 | } |
539 | 539 | ||
540 | static int libertas_ret_802_11_enable_rsn(wlan_private * priv, | ||
541 | struct cmd_ds_command *resp) | ||
542 | { | ||
543 | struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn; | ||
544 | wlan_adapter *adapter = priv->adapter; | ||
545 | u32 * pdata_buf = adapter->cur_cmd->pdata_buf; | ||
546 | |||
547 | lbs_deb_enter(LBS_DEB_CMD); | ||
548 | |||
549 | if (enable_rsn->action == cpu_to_le16(cmd_act_get)) { | ||
550 | if (pdata_buf) | ||
551 | *pdata_buf = (u32) le16_to_cpu(enable_rsn->enable); | ||
552 | } | ||
553 | |||
554 | lbs_deb_enter(LBS_DEB_CMD); | ||
555 | return 0; | ||
556 | } | ||
557 | |||
540 | static inline int handle_cmd_response(u16 respcmd, | 558 | static inline int handle_cmd_response(u16 respcmd, |
541 | struct cmd_ds_command *resp, | 559 | struct cmd_ds_command *resp, |
542 | wlan_private *priv) | 560 | wlan_private *priv) |
@@ -610,7 +628,10 @@ static inline int handle_cmd_response(u16 respcmd, | |||
610 | case cmd_ret_802_11_authenticate: | 628 | case cmd_ret_802_11_authenticate: |
611 | case cmd_ret_802_11_radio_control: | 629 | case cmd_ret_802_11_radio_control: |
612 | case cmd_ret_802_11_beacon_stop: | 630 | case cmd_ret_802_11_beacon_stop: |
631 | break; | ||
632 | |||
613 | case cmd_ret_802_11_enable_rsn: | 633 | case cmd_ret_802_11_enable_rsn: |
634 | ret = libertas_ret_802_11_enable_rsn(priv, resp); | ||
614 | break; | 635 | break; |
615 | 636 | ||
616 | case cmd_ret_802_11_data_rate: | 637 | case cmd_ret_802_11_data_rate: |
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index 3acf93988125..09b898f6719c 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h | |||
@@ -503,7 +503,7 @@ struct cmd_ds_802_11_ad_hoc_join { | |||
503 | struct cmd_ds_802_11_enable_rsn { | 503 | struct cmd_ds_802_11_enable_rsn { |
504 | __le16 action; | 504 | __le16 action; |
505 | __le16 enable; | 505 | __le16 enable; |
506 | }; | 506 | } __attribute__ ((packed)); |
507 | 507 | ||
508 | struct MrvlIEtype_keyParamSet { | 508 | struct MrvlIEtype_keyParamSet { |
509 | /* type ID */ | 509 | /* type ID */ |