rework linkstatus notification to defer processing to outside of
interrupt context.
This commit is contained in:
parent
8bb3eed864
commit
6638fcb8fb
3
CHANGES
3
CHANGES
|
@ -41,6 +41,9 @@
|
|||
* Intersil Corporation as part of PRISM(R) chipset product development.
|
||||
*
|
||||
* --------------------------------------------------------------------
|
||||
- Rework the prism2sta_inf_linkstatus call to defer processing of
|
||||
results until outside interrupt context. Should fix the SMP
|
||||
deadlocks seen on some machines.
|
||||
- Rework the usb_disconnect code to hopefully alleviate the occasional
|
||||
crash-on-disconnect some people see. Solution is not SMP-safe yet.
|
||||
- Add the D-Link DCF-660W ident info.
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/tqueue.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
@ -566,22 +567,6 @@ static void prism2sta_inf_authreq(
|
|||
static void prism2sta_inf_psusercnt(
|
||||
wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
|
||||
|
||||
#if (WLAN_HOSTIF == WLAN_USB)
|
||||
static void
|
||||
prism2sta_getbssid_cb(
|
||||
hfa384x_t *hw,
|
||||
UINT result,
|
||||
void *ctlxresult,
|
||||
void *usercb_data);
|
||||
|
||||
static void
|
||||
prism2sta_getportstatus_cb(
|
||||
hfa384x_t *hw,
|
||||
UINT result,
|
||||
void *ctlxresult,
|
||||
void *usercb_data);
|
||||
#endif /* WLANHOSTIF == WLAN_USB */
|
||||
|
||||
/*================================================================*/
|
||||
/* Function Definitions */
|
||||
|
||||
|
@ -1922,34 +1907,15 @@ void prism2sta_inf_chinforesults(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* prism2sta_inf_linkstatus
|
||||
*
|
||||
* Handles the receipt of a Link Status info frame.
|
||||
*
|
||||
* Arguments:
|
||||
* wlandev wlan device structure
|
||||
* inf ptr to info frame (contents in hfa384x order)
|
||||
*
|
||||
* Returns:
|
||||
* nothing
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
* Call context:
|
||||
* interrupt
|
||||
----------------------------------------------------------------*/
|
||||
void prism2sta_inf_linkstatus(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
|
||||
void prism2sta_linkstatus_defer(void *data)
|
||||
{
|
||||
wlandevice_t *wlandev = (wlandevice_t *) data;
|
||||
prism2sta_priv_t *priv = wlandev->priv;
|
||||
hfa384x_t *hw = priv->hw;
|
||||
UINT16 linkstatus = priv->link_status;
|
||||
|
||||
DBFENTER;
|
||||
/* Convert */
|
||||
inf->info.linkstatus.linkstatus =
|
||||
hfa384x2host_16(inf->info.linkstatus.linkstatus);
|
||||
/* Handle */
|
||||
switch (inf->info.linkstatus.linkstatus) {
|
||||
switch(linkstatus) {
|
||||
case HFA384x_LINK_NOTCONNECTED:
|
||||
/* I'm currently assuming that this is the initial link
|
||||
* state. It should only be possible immediately
|
||||
|
@ -1977,53 +1943,36 @@ void prism2sta_inf_linkstatus(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
|
|||
hw->join_retries = 60;
|
||||
|
||||
WLAN_LOG_DEBUG0(1,"linkstatus=CONNECTED\n");
|
||||
#if (WLAN_HOSTIF == WLAN_USB)
|
||||
/* For USB devices, all the [get|set]config calls that
|
||||
* occur in an 'event (i.e. interrupt) context must
|
||||
* use the async version.
|
||||
*/
|
||||
/* Collect the BSSID, and set state to allow tx */
|
||||
hfa384x_drvr_getconfig_async(hw,
|
||||
HFA384x_RID_CURRENTBSSID,
|
||||
prism2sta_getbssid_cb, wlandev);
|
||||
|
||||
|
||||
/* Collect the port status */
|
||||
hfa384x_drvr_getconfig_async(hw,
|
||||
HFA384x_RID_PORTSTATUS,
|
||||
prism2sta_getportstatus_cb, wlandev);
|
||||
|
||||
#else /* !USB */
|
||||
{
|
||||
UINT16 portstatus;
|
||||
int result;
|
||||
/* For non-usb devices, we can use the sync versions */
|
||||
/* Collect the BSSID, and set state to allow tx */
|
||||
result = hfa384x_drvr_getconfig(hw,
|
||||
UINT16 portstatus;
|
||||
int result;
|
||||
/* For non-usb devices, we can use the sync versions */
|
||||
/* Collect the BSSID, and set state to allow tx */
|
||||
|
||||
result = hfa384x_drvr_getconfig(hw,
|
||||
HFA384x_RID_CURRENTBSSID,
|
||||
wlandev->bssid, WLAN_BSSID_LEN);
|
||||
if ( result ) {
|
||||
if ( result ) {
|
||||
WLAN_LOG_DEBUG2(1,
|
||||
"getconfig(0x%02x) failed, result = %d\n",
|
||||
HFA384x_RID_CURRENTBSSID, result);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Collect the port status */
|
||||
result = hfa384x_drvr_getconfig16(hw,
|
||||
/* Collect the port status */
|
||||
result = hfa384x_drvr_getconfig16(hw,
|
||||
HFA384x_RID_PORTSTATUS, &portstatus);
|
||||
if ( result ) {
|
||||
if ( result ) {
|
||||
WLAN_LOG_DEBUG2(1,
|
||||
"getconfig(0x%02x) failed, result = %d\n",
|
||||
HFA384x_RID_PORTSTATUS, result);
|
||||
goto failed;
|
||||
}
|
||||
portstatus = hfa384x2host_16(portstatus);
|
||||
wlandev->macmode =
|
||||
portstatus == HFA384x_PSTATUS_CONN_IBSS ?
|
||||
}
|
||||
portstatus = hfa384x2host_16(portstatus);
|
||||
wlandev->macmode =
|
||||
(portstatus == HFA384x_PSTATUS_CONN_IBSS) ?
|
||||
WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA;
|
||||
}
|
||||
#endif /* WLANHOSTIF == WLAN_USB */
|
||||
break;
|
||||
|
||||
case HFA384x_LINK_DISCONNECTED:
|
||||
|
@ -2124,28 +2073,23 @@ void prism2sta_inf_linkstatus(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
|
|||
default:
|
||||
/* This is bad, IO port problems? */
|
||||
WLAN_LOG_WARNING1(
|
||||
"unknown linkstatus=0x%02x\n", inf->info.linkstatus.linkstatus);
|
||||
"unknown linkstatus=0x%02x\n", linkstatus);
|
||||
goto failed;
|
||||
break;
|
||||
}
|
||||
|
||||
failed:
|
||||
failed:
|
||||
DBFEXIT;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#if (WLAN_HOSTIF == WLAN_USB)
|
||||
/*----------------------------------------------------------------
|
||||
* prism2sta_getbssid_cb
|
||||
* prism2sta_inf_linkstatus
|
||||
*
|
||||
* Completion callback for getconfig_async() of CNFBSSID
|
||||
* Handles the receipt of a Link Status info frame.
|
||||
*
|
||||
* Arguments:
|
||||
* hw hw struct
|
||||
* result command result, 0==success
|
||||
* ctlxresult structure containing getconfig_async() results
|
||||
* usercb_data ptr that was passed into getconfig_async()
|
||||
* wlandev wlan device structure
|
||||
* inf ptr to info frame (contents in hfa384x order)
|
||||
*
|
||||
* Returns:
|
||||
* nothing
|
||||
|
@ -2155,68 +2099,29 @@ failed:
|
|||
* Call context:
|
||||
* interrupt
|
||||
----------------------------------------------------------------*/
|
||||
void
|
||||
prism2sta_getbssid_cb(
|
||||
hfa384x_t *hw,
|
||||
UINT result,
|
||||
void *ctlxresult,
|
||||
void *usercb_data)
|
||||
void prism2sta_inf_linkstatus(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
|
||||
{
|
||||
wlandevice_t *wlandev = usercb_data;
|
||||
hfa384x_async_rridresult_t *rrid = ctlxresult;
|
||||
prism2sta_priv_t *priv = wlandev->priv;
|
||||
|
||||
DBFENTER;
|
||||
WLAN_LOG_DEBUG1(3,"result=%d\n", result);
|
||||
if (result == 0) {
|
||||
memcpy( wlandev->bssid, rrid->riddata, WLAN_BSSID_LEN);
|
||||
}
|
||||
/* Convert */
|
||||
inf->info.linkstatus.linkstatus =
|
||||
hfa384x2host_16(inf->info.linkstatus.linkstatus);
|
||||
|
||||
/* Fire off a task. */
|
||||
priv->link_tq.routine = prism2sta_linkstatus_defer;
|
||||
priv->link_tq.data = wlandev;
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
|
||||
queue_task(&priv->link_tq, tq_scheduler);
|
||||
#else
|
||||
schedule_task(&priv->link_tq);
|
||||
#endif
|
||||
|
||||
DBFEXIT;
|
||||
return;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* prism2sta_getportstatus_cb
|
||||
*
|
||||
* Completion callback for getconfig_async() of PORTSTATUS.
|
||||
* Sets wlandev->macmode based on the PORTSTATUS.
|
||||
*
|
||||
* Arguments:
|
||||
* hw hw struct
|
||||
* result command result, 0==success
|
||||
* ctlxresult structure containing getconfig_async() results
|
||||
* usercb_data ptr that was passed into getconfig_async()
|
||||
*
|
||||
* Returns:
|
||||
* nothing
|
||||
*
|
||||
* Side effects:
|
||||
*
|
||||
* Call context:
|
||||
* interrupt
|
||||
----------------------------------------------------------------*/
|
||||
void prism2sta_getportstatus_cb(
|
||||
hfa384x_t *hw,
|
||||
UINT result,
|
||||
void *ctlxresult,
|
||||
void *usercb_data)
|
||||
{
|
||||
wlandevice_t *wlandev = usercb_data;
|
||||
hfa384x_async_rridresult_t *rrid = ctlxresult;
|
||||
UINT16 portstatus;
|
||||
|
||||
DBFENTER;
|
||||
WLAN_LOG_DEBUG1(3,"result=%d\n", result);
|
||||
if (result == 0) {
|
||||
portstatus = hfa384x2host_16(*((UINT16*)rrid->riddata));
|
||||
wlandev->macmode =
|
||||
portstatus == HFA384x_PSTATUS_CONN_IBSS ?
|
||||
WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA;
|
||||
}
|
||||
DBFEXIT;
|
||||
return;
|
||||
}
|
||||
#endif /* WLANHOSTIF == WLAN_USB */
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
* prism2sta_inf_assocstatus
|
||||
*
|
||||
|
|
|
@ -115,10 +115,9 @@ typedef struct prism2sta_priv
|
|||
char name[WLAN_DEVNAMELEN_MAX];
|
||||
#endif
|
||||
|
||||
#if (WLAN_HOSTIF == WLAN_USB)
|
||||
/* Timer to handle waiting for canceled urbs */
|
||||
struct timer_list postdisconnect;
|
||||
#endif
|
||||
/* Timer to allow for the deferred processing of linkstatus messages */
|
||||
struct tq_struct link_tq;
|
||||
UINT16 link_status;
|
||||
|
||||
/* Structure for MAC data */
|
||||
hfa384x_t *hw;
|
||||
|
|
Loading…
Reference in a new issue