2009-10-12 11:36:40

by Holger Schurig

[permalink] [raw]
Subject: WARNING: slow-path

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


2009-10-12 13:09:05

by David Woodhouse

[permalink] [raw]
Subject: Re: WARNING: slow-path

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


2009-10-12 14:04:24

by Holger Schurig

[permalink] [raw]
Subject: Re: WARNING: slow-path

> 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