rework linkstatus notification to defer processing to outside of

interrupt context.
This commit is contained in:
solomon 2002-10-15 20:25:19 +00:00
parent 8bb3eed864
commit 6638fcb8fb
3 changed files with 49 additions and 142 deletions

View File

@ -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.

View File

@ -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
*

View File

@ -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;