Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 290299
b: refs/heads/master
c: 98d4bf0
h: refs/heads/master
i:
  290297: ca5f3c7
  290295: dd52ffb
v: v3
  • Loading branch information
Johannes Berg authored and Wey-Yi Guy committed Jan 28, 2012
1 parent 35a2936 commit 3e5b0bd
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 33 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: de46fb079ff16fabb3bdf7892c9a2900a9880329
refs/heads/master: 98d4bf0c49de0d7c68fa7e1f7bd0a37420f712ca
99 changes: 71 additions & 28 deletions trunk/drivers/net/wireless/iwlwifi/iwl-agn.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ static void iwl_bg_statistics_periodic(unsigned long data)

static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
u32 start_idx, u32 num_events,
u32 mode)
u32 capacity, u32 mode)
{
u32 i;
u32 ptr; /* SRAM byte address of log data */
Expand All @@ -338,6 +338,15 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
iwl_write32(bus(priv), HBUS_TARG_MEM_RADDR, ptr);
rmb();

/*
* Refuse to read more than would have fit into the log from
* the current start_idx. This used to happen due to the race
* described below, but now WARN because the code below should
* prevent it from happening here.
*/
if (WARN_ON(num_events > capacity - start_idx))
num_events = capacity - start_idx;

/*
* "time" is actually "data" for mode 0 (no timestamp).
* place event id # at far right for easier visual parsing.
Expand All @@ -346,12 +355,11 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
ev = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
time = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
if (mode == 0) {
trace_iwlwifi_dev_ucode_cont_event(priv,
0, time, ev);
trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev);
} else {
data = iwl_read32(bus(priv), HBUS_TARG_MEM_RDAT);
trace_iwlwifi_dev_ucode_cont_event(priv,
time, data, ev);
trace_iwlwifi_dev_ucode_cont_event(priv, time,
data, ev);
}
}
/* Allow device to power down */
Expand All @@ -362,53 +370,83 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
static void iwl_continuous_event_trace(struct iwl_priv *priv)
{
u32 capacity; /* event log capacity in # entries */
struct {
u32 capacity;
u32 mode;
u32 wrap_counter;
u32 write_counter;
} __packed read;
u32 base; /* SRAM byte address of event log header */
u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
u32 num_wraps; /* # times uCode wrapped to top of log */
u32 next_entry; /* index of next entry to be written by uCode */

base = priv->shrd->device_pointers.error_event_table;
base = priv->shrd->device_pointers.log_event_table;
if (iwlagn_hw_valid_rtc_data_addr(base)) {
capacity = iwl_read_targ_mem(bus(priv), base);
num_wraps = iwl_read_targ_mem(bus(priv),
base + (2 * sizeof(u32)));
mode = iwl_read_targ_mem(bus(priv), base + (1 * sizeof(u32)));
next_entry = iwl_read_targ_mem(bus(priv),
base + (3 * sizeof(u32)));
iwl_read_targ_mem_words(bus(priv), base, &read, sizeof(read));

capacity = read.capacity;
mode = read.mode;
num_wraps = read.wrap_counter;
next_entry = read.write_counter;
} else
return;

/*
* Unfortunately, the uCode doesn't use temporary variables.
* Therefore, it can happen that we read next_entry == capacity,
* which really means next_entry == 0.
*/
if (unlikely(next_entry == capacity))
next_entry = 0;
/*
* Additionally, the uCode increases the write pointer before
* the wraps counter, so if the write pointer is smaller than
* the old write pointer (wrap occurred) but we read that no
* wrap occurred, we actually read between the next_entry and
* num_wraps update (this does happen in practice!!) -- take
* that into account by increasing num_wraps.
*/
if (unlikely(next_entry < priv->event_log.next_entry &&
num_wraps == priv->event_log.num_wraps))
num_wraps++;

if (num_wraps == priv->event_log.num_wraps) {
iwl_print_cont_event_trace(priv,
base, priv->event_log.next_entry,
next_entry - priv->event_log.next_entry,
mode);
iwl_print_cont_event_trace(
priv, base, priv->event_log.next_entry,
next_entry - priv->event_log.next_entry,
capacity, mode);

priv->event_log.non_wraps_count++;
} else {
if ((num_wraps - priv->event_log.num_wraps) > 1)
if (num_wraps - priv->event_log.num_wraps > 1)
priv->event_log.wraps_more_count++;
else
priv->event_log.wraps_once_count++;

trace_iwlwifi_dev_ucode_wrap_event(priv,
num_wraps - priv->event_log.num_wraps,
next_entry, priv->event_log.next_entry);

if (next_entry < priv->event_log.next_entry) {
iwl_print_cont_event_trace(priv, base,
priv->event_log.next_entry,
capacity - priv->event_log.next_entry,
mode);
iwl_print_cont_event_trace(
priv, base, priv->event_log.next_entry,
capacity - priv->event_log.next_entry,
capacity, mode);

iwl_print_cont_event_trace(priv, base, 0,
next_entry, mode);
iwl_print_cont_event_trace(
priv, base, 0, next_entry, capacity, mode);
} else {
iwl_print_cont_event_trace(priv, base,
next_entry, capacity - next_entry,
mode);
iwl_print_cont_event_trace(
priv, base, next_entry,
capacity - next_entry,
capacity, mode);

iwl_print_cont_event_trace(priv, base, 0,
next_entry, mode);
iwl_print_cont_event_trace(
priv, base, 0, next_entry, capacity, mode);
}
}

priv->event_log.num_wraps = num_wraps;
priv->event_log.next_entry = next_entry;
}
Expand Down Expand Up @@ -1219,6 +1257,11 @@ int iwl_alive_start(struct iwl_priv *priv)
if (iwl_is_rfkill(priv->shrd))
return -ERFKILL;

if (priv->event_log.ucode_trace) {
/* start collecting data now */
mod_timer(&priv->ucode_trace, jiffies);
}

/* download priority table before any calibration request */
if (cfg(priv)->bt_params &&
cfg(priv)->bt_params->advanced_bt_coexist) {
Expand Down
7 changes: 4 additions & 3 deletions trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2131,9 +2131,10 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,

if (trace) {
priv->event_log.ucode_trace = true;
/* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
mod_timer(&priv->ucode_trace,
jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
if (iwl_is_alive(priv->shrd)) {
/* start collecting data now */
mod_timer(&priv->ucode_trace, jiffies);
}
} else {
priv->event_log.ucode_trace = false;
del_timer_sync(&priv->ucode_trace);
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/net/wireless/iwlwifi/iwl-dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ struct traffic_stats {
* schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
* to perform continuous uCode event logging operation if enabled
*/
#define UCODE_TRACE_PERIOD (100)
#define UCODE_TRACE_PERIOD (10)

/*
* iwl_event_log: current uCode event log position
Expand Down

0 comments on commit 3e5b0bd

Please sign in to comment.