Skip to content

Commit

Permalink
ipw2x00: age scan results on resume
Browse files Browse the repository at this point in the history
Scanned BSS entries are timestamped with jiffies, which doesn't
increment across suspend and hibernate.  On resume, every BSS in the
scan list looks like it was scanned within the last 10 seconds,
irregardless of how long the machine was actually asleep.  Age scan
results on resume with the time spent during sleep so userspace has a
clue how old they really are.

Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Dan Williams authored and John W. Linville committed Feb 27, 2009
1 parent bc8263f commit c3d72b9
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 9 deletions.
3 changes: 3 additions & 0 deletions drivers/net/wireless/ipw2x00/ieee80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,9 @@ static inline int ieee80211_is_cck_rate(u8 rate)
extern void free_ieee80211(struct net_device *dev);
extern struct net_device *alloc_ieee80211(int sizeof_priv);

extern void ieee80211_networks_age(struct ieee80211_device *ieee,
unsigned long age_secs);

extern int ieee80211_set_encryption(struct ieee80211_device *ieee);

/* ieee80211_tx.c */
Expand Down
12 changes: 11 additions & 1 deletion drivers/net/wireless/ipw2x00/ipw2100.c
Original file line number Diff line number Diff line change
Expand Up @@ -1692,7 +1692,13 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
u32 lock;
u32 ord_len = sizeof(lock);

/* Quite if manually disabled. */
/* Age scan list entries found before suspend */
if (priv->suspend_time) {
ieee80211_networks_age(priv->ieee, priv->suspend_time);
priv->suspend_time = 0;
}

/* Quiet if manually disabled. */
if (priv->status & STATUS_RF_KILL_SW) {
IPW_DEBUG_INFO("%s: Radio is disabled by Manual Disable "
"switch\n", priv->net_dev->name);
Expand Down Expand Up @@ -6415,6 +6421,8 @@ static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state)
pci_disable_device(pci_dev);
pci_set_power_state(pci_dev, PCI_D3hot);

priv->suspend_at = get_seconds();

mutex_unlock(&priv->action_mutex);

return 0;
Expand Down Expand Up @@ -6458,6 +6466,8 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
* the queue of needed */
netif_device_attach(dev);

priv->suspend_time = get_seconds() - priv->suspend_at;

/* Bring the device back up */
if (!(priv->status & STATUS_RF_KILL_SW))
ipw2100_up(priv, 0);
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/wireless/ipw2x00/ipw2100.h
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,10 @@ struct ipw2100_priv {

int user_requested_scan;

/* Track time in suspend */
unsigned long suspend_at;
unsigned long suspend_time;

u32 interrupts;
int tx_interrupts;
int rx_interrupts;
Expand Down
10 changes: 10 additions & 0 deletions drivers/net/wireless/ipw2x00/ipw2200.c
Original file line number Diff line number Diff line change
Expand Up @@ -11238,6 +11238,12 @@ static int ipw_up(struct ipw_priv *priv)
{
int rc, i, j;

/* Age scan list entries found before suspend */
if (priv->suspend_time) {
ieee80211_networks_age(priv->ieee, priv->suspend_time);
priv->suspend_time = 0;
}

if (priv->status & STATUS_EXIT_PENDING)
return -EIO;

Expand Down Expand Up @@ -11838,6 +11844,8 @@ static int ipw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));

priv->suspend_at = get_seconds();

return 0;
}

Expand Down Expand Up @@ -11873,6 +11881,8 @@ static int ipw_pci_resume(struct pci_dev *pdev)
* the queue of needed */
netif_device_attach(dev);

priv->suspend_time = get_seconds() - priv->suspend_at;

/* Bring the device back up */
queue_work(priv->workqueue, &priv->up);

Expand Down
4 changes: 4 additions & 0 deletions drivers/net/wireless/ipw2x00/ipw2200.h
Original file line number Diff line number Diff line change
Expand Up @@ -1347,6 +1347,10 @@ struct ipw_priv {

s8 tx_power;

/* Track time in suspend */
unsigned long suspend_at;
unsigned long suspend_time;

#ifdef CONFIG_PM
u32 pm_state[16];
#endif
Expand Down
15 changes: 15 additions & 0 deletions drivers/net/wireless/ipw2x00/libipw_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,21 @@ static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
ieee->networks = NULL;
}

void ieee80211_networks_age(struct ieee80211_device *ieee,
unsigned long age_secs)
{
struct ieee80211_network *network = NULL;
unsigned long flags;
unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);

spin_lock_irqsave(&ieee->lock, flags);
list_for_each_entry(network, &ieee->network_list, list) {
network->last_scanned -= age_jiffies;
}
spin_unlock_irqrestore(&ieee->lock, flags);
}
EXPORT_SYMBOL(ieee80211_networks_age);

static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
{
int i;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ipw2x00/libipw_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1616,7 +1616,7 @@ static void ieee80211_process_probe_response(struct ieee80211_device
break;

if ((oldest == NULL) ||
(target->last_scanned < oldest->last_scanned))
time_before(target->last_scanned, oldest->last_scanned))
oldest = target;
}

Expand Down
24 changes: 17 additions & 7 deletions drivers/net/wireless/ipw2x00/libipw_wx.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ static const char *ieee80211_modes[] = {
"?", "a", "b", "ab", "g", "ag", "bg", "abg"
};

static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
{
unsigned long end = jiffies;

if (end >= start)
return jiffies_to_msecs(end - start);

return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1);
}

#define MAX_CUSTOM_LEN 64
static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
char *start, char *stop,
Expand Down Expand Up @@ -216,8 +226,8 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
iwe.cmd = IWEVCUSTOM;
p = custom;
p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
" Last beacon: %dms ago",
jiffies_to_msecs(jiffies - network->last_scanned));
" Last beacon: %ums ago",
elapsed_jiffies_msecs(network->last_scanned));
iwe.u.data.length = p - custom;
if (iwe.u.data.length)
start = iwe_stream_add_point(info, start, stop, &iwe, custom);
Expand Down Expand Up @@ -277,15 +287,15 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
time_after(network->last_scanned + ieee->scan_age, jiffies))
ev = ieee80211_translate_scan(ieee, ev, stop, network,
info);
else
else {
IEEE80211_DEBUG_SCAN("Not showing network '%s ("
"%pM)' due to age (%dms).\n",
"%pM)' due to age (%ums).\n",
print_ssid(ssid, network->ssid,
network->ssid_len),
network->bssid,
jiffies_to_msecs(jiffies -
network->
last_scanned));
elapsed_jiffies_msecs(
network->last_scanned));
}
}

spin_unlock_irqrestore(&ieee->lock, flags);
Expand Down

0 comments on commit c3d72b9

Please sign in to comment.