I'm getting a "slow-path" warning that I don't really comprehend:
[ 33.357576] libertas leave: lbs_cfg_scan_worker()
[ 33.368197] libertas enter: lbs_cfg_auth()
[ 33.368356] libertas leave: lbs_cfg_auth(), ret 0
[ 33.368554] libertas enter: lbs_cfg_ret_auth()
[ 33.368746] libertas leave: lbs_cfg_ret_auth()
Next comes the .assoc function. This isn't yet coded so I return -ENOTSUPP
[ 33.368832] libertas enter: lbs_cfg_assoc()
[ 33.368902] libertas leave: lbs_cfg_assoc(-ENOTSUPP)
... with makes mlme.c call my .deauth function:
[ 33.368970] libertas enter: lbs_cfg_deauth()
[ 33.369768] libertas enter: lbs_cfg_ret_deauth()
[ 33.369838] ------------[ cut here ]------------
[ 33.369923] WARNING: at net/wireless/mlme.c:135 __cfg80211_send_deauth+0x3f/0x1e1 [cfg80211]()
[ 33.370028] Hardware name: Amilo M1425
[ 33.370096] Modules linked in: libertas_cs libertas cfg80211 lib80211 psmouse uhci_hcd [last unloaded: cfg80211]
[ 33.370461] Pid: 1700, comm: lbs_main Not tainted 2.6.32-rc3-wl #21
[ 33.370532] Call Trace:
[ 33.370604] [<c012395a>] warn_slowpath_common+0x60/0x77
[ 33.370676] [<c012397e>] warn_slowpath_null+0xd/0x10
[ 33.370754] [<f91205c0>] __cfg80211_send_deauth+0x3f/0x1e1 [cfg80211]
[ 33.370834] [<f9120c85>] cfg80211_send_deauth+0x33/0x5a [cfg80211]
[ 33.370916] [<f93324cc>] lbs_cfg_ret_deauth+0x9d/0xe7 [libertas]
[ 33.370993] [<f933242f>] ? lbs_cfg_ret_deauth+0x0/0xe7 [libertas]
[ 33.371071] [<f93380bc>] lbs_process_command_response+0x538/0xa96 [libertas]
[ 33.371147] [<c0399f7a>] ? _spin_unlock_irq+0x22/0x3b
[ 33.371225] [<f933ca77>] lbs_thread+0x358/0x747 [libertas]
[ 33.371300] [<c011ebbc>] ? default_wake_function+0x0/0xd
[ 33.371377] [<f933c71f>] ? lbs_thread+0x0/0x747 [libertas]
[ 33.371450] [<c0133c9c>] kthread+0x61/0x69
[ 33.371520] [<c0133c3b>] ? kthread+0x0/0x69
[ 33.371591] [<c010334b>] kernel_thread_helper+0x7/0x10
[ 33.371661] ---[ end trace f5da223917368c61 ]---
[ 33.371756] libertas leave: lbs_cfg_ret_deauth()
Bellow is lbs_cfg_deauth. I know from friday's debugging, that
__lbs_cmd_async also does a preempt (CONFIG_PREEMPT). That
might have something do to with it.
static int lbs_cfg_deauth(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_deauth_request *req,
void *cookie)
{
struct lbs_private *priv = wiphy_priv(wiphy);
struct cmd_ds_802_11_deauthenticate cmd;
lbs_deb_enter(LBS_DEB_CFG80211);
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
memcpy(cmd.macaddr, &req->bss->bssid, ETH_ALEN);
cmd.reasoncode = cpu_to_le16(req->reason_code);
__lbs_cmd_async(priv, CMD_802_11_DEAUTHENTICATE,
&cmd.hdr, sizeof(cmd),
lbs_cfg_ret_deauth, (unsigned long) cookie);
return 0;
}
lbs_cfg_ret_deauth() get's called as soon as the
firmware sends me back some response.
static int lbs_cfg_ret_deauth(struct lbs_private *priv, unsigned long dummy,
struct cmd_header *resp)
{
struct cmd_ds_802_11_deauthenticate *deauth_resp = (void *)resp;
struct ieee80211_mgmt mgmt;
lbs_deb_enter(LBS_DEB_CFG80211);
/* Fake a management frame */
memset(&mgmt, 0, sizeof(mgmt));
memcpy(mgmt.bssid, deauth_resp->macaddr, ETH_ALEN);
memcpy(mgmt.sa, deauth_resp->macaddr, ETH_ALEN);
memcpy(mgmt.da, priv->current_addr, ETH_ALEN);
cfg80211_send_deauth(priv->dev, (u8 *)&mgmt, sizeof(mgmt),
(void *)dummy);
lbs_deb_leave(LBS_DEB_CFG80211);
return 0;
}
Any idea on how to fix that?
--
http://www.holgerschurig.de
On Mon, 2009-10-12 at 13:35 +0200, Holger Schurig wrote:
> [ 33.369923] WARNING: at net/wireless/mlme.c:135 __cfg80211_send_deauth+0x3f/0x1e1 [cfg80211]()
You're triggering the warning at line 135 of net/wireless/mlme.c, which
is 'ASSERT_WDEV_LOCK(wdev)' -- it's complaining that the lock isn't
held.
> static int lbs_cfg_ret_deauth(struct lbs_private *priv, unsigned long dummy,
> struct cmd_header *resp)
> cfg80211_send_deauth(priv->dev, (u8 *)&mgmt, sizeof(mgmt),
> (void *)dummy);
What happens if you make that last argument NULL instead of passing
'dummy' back to it? That makes cfg80211_send_deauth() magically do
different things w.r.t. locking. Johannes, this is _evil_:
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
void *cookie)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
BUG_ON(cookie && wdev != cookie);
if (cookie) {
/* called within callback */
__cfg80211_send_deauth(dev, buf, len);
} else {
wdev_lock(wdev);
__cfg80211_send_deauth(dev, buf, len);
wdev_unlock(wdev);
}
}
--
David Woodhouse Open Source Technology Centre
[email protected] Intel Corporation
> What happens if you make that last argument NULL instead of
> passing 'dummy' back to it? That makes cfg80211_send_deauth()
> magically do different things w.r.t. locking.
That worked, thanks.
> Johannes, this is _evil_:
It's not only _evil_, it's also undocumented. I was just
following include/net/cfg80211.h. There is no kernel-doc in the
comments for "cookie", neither in
[struct cfg80211_ops:]
int (*deauth)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_deauth_request *req,
void *cookie);
nor in
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
void *cookie);
so I automatically assumed that I have to provide the "cookie" I
got in my deauth()-handler to cfg80211_send_deauth().
/me says "I can haz a cookie?"
--
http://www.holgerschurig.de