#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
+#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
- set_bit(STATUS_INIT_UCODE_ALIVE, &priv->status);
- wake_up_interruptible(&priv->wait_command_queue);
memcpy(&priv->card_alive_init,
&pkt->u.alive_frame,
sizeof(struct iwl_init_alive_resp));
pwork = &priv->init_alive_start;
} else {
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
- set_bit(STATUS_RT_UCODE_ALIVE, &priv->status);
- wake_up_interruptible(&priv->wait_command_queue);
memcpy(&priv->card_alive, &pkt->u.alive_frame,
sizeof(struct iwl_alive_resp));
pwork = &priv->alive_start;
iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & IWL_DL_ISR) {
+ if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
/* just for debug */
inta_mask = iwl_read32(priv, CSR_INT_MASK);
IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & (IWL_DL_ISR)) {
+ if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if (inta & CSR_INT_BIT_SCD) {
IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
iwl_enable_interrupts(priv);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & (IWL_DL_ISR)) {
+ if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
inta = iwl_read32(priv, CSR_INT);
inta_mask = iwl_read32(priv, CSR_INT_MASK);
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
inta = priv->inta;
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & IWL_DL_ISR) {
+ if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
/* just for debug */
inta_mask = iwl_read32(priv, CSR_INT_MASK);
IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ",
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & (IWL_DL_ISR)) {
+ if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if (inta & CSR_INT_BIT_SCD) {
IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
size_t len;
u32 api_ver, build;
u32 inst_size, data_size, init_size, init_data_size, boot_size;
+ u16 eeprom_ver;
/* Ask kernel firmware_class module to get the boot firmware off disk.
* request_firmware() is synchronous, file is in memory on return. */
if (build)
IWL_DEBUG_INFO(priv, "Build %u\n", build);
+ eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+ IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n",
+ (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
+ ? "OTP" : "EEPROM", eeprom_ver);
+
IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
priv->ucode_ver);
IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
return ret;
}
+#ifdef CONFIG_IWLWIFI_DEBUG
+static const char *desc_lookup_text[] = {
+ "OK",
+ "FAIL",
+ "BAD_PARAM",
+ "BAD_CHECKSUM",
+ "NMI_INTERRUPT_WDG",
+ "SYSASSERT",
+ "FATAL_ERROR",
+ "BAD_COMMAND",
+ "HW_ERROR_TUNE_LOCK",
+ "HW_ERROR_TEMPERATURE",
+ "ILLEGAL_CHAN_FREQ",
+ "VCC_NOT_STABLE",
+ "FH_ERROR",
+ "NMI_INTERRUPT_HOST",
+ "NMI_INTERRUPT_ACTION_PT",
+ "NMI_INTERRUPT_UNKNOWN",
+ "UCODE_VERSION_MISMATCH",
+ "HW_ERROR_ABS_LOCK",
+ "HW_ERROR_CAL_LOCK_FAIL",
+ "NMI_INTERRUPT_INST_ACTION_PT",
+ "NMI_INTERRUPT_DATA_ACTION_PT",
+ "NMI_TRM_HW_ER",
+ "NMI_INTERRUPT_TRM",
+ "NMI_INTERRUPT_BREAK_POINT"
+ "DEBUG_0",
+ "DEBUG_1",
+ "DEBUG_2",
+ "DEBUG_3",
+ "UNKNOWN"
+};
+
+static const char *desc_lookup(int i)
+{
+ int max = ARRAY_SIZE(desc_lookup_text) - 1;
+
+ if (i < 0 || i > max)
+ i = max;
+
+ return desc_lookup_text[i];
+}
+
+#define ERROR_START_OFFSET (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE (7 * sizeof(u32))
+
+void iwl_dump_nic_error_log(struct iwl_priv *priv)
+{
+ u32 data2, line;
+ u32 desc, time, count, base, data1;
+ u32 blink1, blink2, ilink1, ilink2;
+
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
+ return;
+ }
+
+ count = iwl_read_targ_mem(priv, base);
+
+ if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ IWL_ERR(priv, "Start IWL Error Log Dump:\n");
+ IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
+ priv->status, count);
+ }
+
+ desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
+ blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
+ blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
+ ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
+ ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
+ data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
+ data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
+ line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
+ time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
+
+ IWL_ERR(priv, "Desc Time "
+ "data1 data2 line\n");
+ IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
+ desc_lookup(desc), desc, time, data1, data2, line);
+ IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n");
+ IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
+ ilink1, ilink2);
+
+}
+
+#define EVENT_START_OFFSET (4 * sizeof(u32))
+
+/**
+ * iwl_print_event_log - Dump error event log to syslog
+ *
+ */
+static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
+ u32 num_events, u32 mode)
+{
+ u32 i;
+ u32 base; /* SRAM byte address of event log header */
+ u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
+ u32 ptr; /* SRAM byte address of log data */
+ u32 ev, time, data; /* event log data */
+
+ if (num_events == 0)
+ return;
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
+ if (mode == 0)
+ event_size = 2 * sizeof(u32);
+ else
+ event_size = 3 * sizeof(u32);
+
+ ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+ /* "time" is actually "data" for mode 0 (no timestamp).
+ * place event id # at far right for easier visual parsing. */
+ for (i = 0; i < num_events; i++) {
+ ev = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ time = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ if (mode == 0) {
+ /* data, ev */
+ IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
+ } else {
+ data = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
+ time, data, ev);
+ }
+ }
+}
+
+void iwl_dump_nic_event_log(struct iwl_priv *priv)
+{
+ u32 base; /* SRAM byte address of event log header */
+ u32 capacity; /* event log capacity in # entries */
+ 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 */
+ u32 size; /* # entries that we'll print */
+
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
+ return;
+ }
+
+ /* event log header */
+ capacity = iwl_read_targ_mem(priv, base);
+ mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
+ num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
+ next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
+
+ size = num_wraps ? capacity : next_entry;
+
+ /* bail out if nothing in log */
+ if (size == 0) {
+ IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
+ return;
+ }
+
+ IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
+ size, num_wraps);
+
+ /* if uCode has wrapped back to top of log, start at the oldest entry,
+ * i.e the next one that uCode would fill. */
+ if (num_wraps)
+ iwl_print_event_log(priv, next_entry,
+ capacity - next_entry, mode);
+ /* (then/else) start at top of log */
+ iwl_print_event_log(priv, 0, next_entry, mode);
+
+}
+#endif
+
/**
* iwl_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
set_bit(STATUS_READY, &priv->status);
wake_up_interruptible(&priv->wait_command_queue);
- iwl_power_update_mode(priv, 1);
+ iwl_power_update_mode(priv, true);
/* reassociate for ADHOC mode */
if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
{
int i;
int ret;
- unsigned long status;
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
/* start card; "initialize" will load runtime ucode */
iwl_nic_start(priv);
- /* Just finish download Init or Runtime uCode image to device
- * now we wait here for uCode send REPLY_ALIVE notification
- * to indicate uCode is ready.
- * 1) For Init uCode image, all iwlagn devices should wait here
- * on STATUS_INIT_UCODE_ALIVE status bit; if timeout before
- * receive the REPLY_ALIVE notification, go back and try to
- * download the Init uCode image again.
- * 2) For Runtime uCode image, all iwlagn devices except 4965
- * wait here on STATUS_RT_UCODE_ALIVE status bit; if
- * timeout before receive the REPLY_ALIVE notification, go back
- * and download the Runtime uCode image again.
- * 3) For 4965 Runtime uCode, it will not go through this path,
- * need to wait for STATUS_RT_UCODE_ALIVE status bit in
- * iwl4965_init_alive_start() function; if timeout, need to
- * restart and download Init uCode image.
- */
- if (priv->ucode_type == UCODE_INIT)
- status = STATUS_INIT_UCODE_ALIVE;
- else
- status = STATUS_RT_UCODE_ALIVE;
- if (test_bit(status, &priv->status)) {
- IWL_WARN(priv,
- "%s uCode already alive? "
- "Waiting for alive anyway\n",
- (status == STATUS_INIT_UCODE_ALIVE)
- ? "INIT" : "Runtime");
- clear_bit(status, &priv->status);
- }
- ret = wait_event_interruptible_timeout(
- priv->wait_command_queue,
- test_bit(status, &priv->status),
- UCODE_ALIVE_TIMEOUT);
- if (!ret) {
- if (!test_bit(status, &priv->status)) {
- priv->ucode_type =
- (status == STATUS_INIT_UCODE_ALIVE)
- ? UCODE_NONE : UCODE_INIT;
- IWL_ERR(priv,
- "%s timeout after %dms\n",
- (status == STATUS_INIT_UCODE_ALIVE)
- ? "INIT" : "Runtime",
- jiffies_to_msecs(UCODE_ALIVE_TIMEOUT));
- continue;
- }
- }
IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
return 0;
* If chain noise has already been run, then we need to enable
* power management here */
if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
- iwl_power_update_mode(priv, 0);
+ iwl_power_update_mode(priv, false);
/* Enable Rx differential gain and sensitivity calibrations */
iwl_chain_noise_reset(priv);
priv->is_open = 0;
- if (iwl_is_ready_rf(priv)) {
+ if (iwl_is_ready_rf(priv) || test_bit(STATUS_SCAN_HW, &priv->status)) {
/* stop mac, cancel any scan request and clear
* RXON_FILTER_ASSOC_MSK BIT
*/
*
* See the level definitions in iwl for details.
*
- * FIXME This file can be deprecated as the module parameter is
- * writable and users can thus also change the debug level
- * using the /sys/module/iwl3945/parameters/debug file.
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
*/
-
static ssize_t show_debug_level(struct device *d,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "0x%08X\n", iwl_debug_level);
+ struct iwl_priv *priv = dev_get_drvdata(d);
+ return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
}
static ssize_t store_debug_level(struct device *d,
struct device_attribute *attr,
ret = strict_strtoul(buf, 0, &val);
if (ret)
IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
- else
- iwl_debug_level = val;
-
+ else {
+ priv->debug_level = val;
+ if (iwl_alloc_traffic_mem(priv))
+ IWL_ERR(priv,
+ "Not enough memory to generate traffic log\n");
+ }
return strnlen(buf, count);
}
#endif /* CONFIG_IWLWIFI_DEBUG */
-static ssize_t show_version(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- struct iwl_alive_resp *palive = &priv->card_alive;
- ssize_t pos = 0;
- u16 eeprom_ver;
-
- if (palive->is_valid)
- pos += sprintf(buf + pos,
- "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
- "fw type: 0x%01X 0x%01X\n",
- palive->ucode_major, palive->ucode_minor,
- palive->sw_rev[0], palive->sw_rev[1],
- palive->ver_type, palive->ver_subtype);
- else
- pos += sprintf(buf + pos, "fw not loaded\n");
-
- if (priv->eeprom) {
- eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
- pos += sprintf(buf + pos, "NVM Type: %s, version: 0x%x\n",
- (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
- ? "OTP" : "EEPROM", eeprom_ver);
-
- } else {
- pos += sprintf(buf + pos, "EEPROM not initialzed\n");
- }
-
- return pos;
-}
-
-static DEVICE_ATTR(version, S_IWUSR | S_IRUGO, show_version, NULL);
-
static ssize_t show_temperature(struct device *d,
struct device_attribute *attr, char *buf)
{
ret = strict_strtoul(buf, 10, &val);
if (ret)
IWL_INFO(priv, "%s is not in decimal form.\n", buf);
- else
- iwl_set_tx_power(priv, val, false);
-
- return count;
+ else {
+ ret = iwl_set_tx_power(priv, val, false);
+ if (ret)
+ IWL_ERR(priv, "failed setting tx power (0x%d).\n",
+ ret);
+ else
+ ret = count;
+ }
+ return ret;
}
static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
store_filter_flags);
-static ssize_t store_power_level(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- int ret;
- unsigned long mode;
-
-
- mutex_lock(&priv->mutex);
-
- ret = strict_strtoul(buf, 10, &mode);
- if (ret)
- goto out;
-
- ret = iwl_power_set_user_mode(priv, mode);
- if (ret) {
- IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n");
- goto out;
- }
- ret = count;
-
- out:
- mutex_unlock(&priv->mutex);
- return ret;
-}
-
-static ssize_t show_power_level(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- int level = priv->power_data.power_mode;
- char *p = buf;
-
- p += sprintf(p, "%d\n", level);
- return p - buf + 1;
-}
-
-static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
- store_power_level);
-
static ssize_t show_statistics(struct device *d,
struct device_attribute *attr, char *buf)
static struct attribute *iwl_sysfs_entries[] = {
&dev_attr_flags.attr,
&dev_attr_filter_flags.attr,
- &dev_attr_power_level.attr,
&dev_attr_statistics.attr,
&dev_attr_temperature.attr,
&dev_attr_tx_power.attr,
#ifdef CONFIG_IWLWIFI_DEBUG
&dev_attr_debug_level.attr,
#endif
- &dev_attr_version.attr,
NULL
};
#ifdef CONFIG_IWLWIFI_DEBUG
atomic_set(&priv->restrict_refcnt, 0);
#endif
+ if (iwl_alloc_traffic_mem(priv))
+ IWL_ERR(priv, "Not enough memory to generate traffic log\n");
/**************************
* 2. Initializing PCI bus
pci_disable_device(pdev);
out_ieee80211_free_hw:
ieee80211_free_hw(priv->hw);
+ iwl_free_traffic_mem(priv);
out:
return err;
}
* until now... */
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
+ iwl_free_traffic_mem(priv);
free_irq(priv->pci_dev->irq, priv);
pci_disable_msi(priv->pci_dev);
{IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)},
{IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
/* 6000/6050 Series */
- {IWL_PCI_DEVICE(0x0082, 0x1102, iwl6000_2ag_cfg)},
- {IWL_PCI_DEVICE(0x0085, 0x1112, iwl6000_2ag_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1122, iwl6000_2ag_cfg)},
+ {IWL_PCI_DEVICE(0x008D, PCI_ANY_ID, iwl6000h_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x008E, PCI_ANY_ID, iwl6000h_2agn_cfg)},
{IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000i_2agn_cfg)},
{IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)},
- {IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0082, PCI_ANY_ID, iwl6000_2agn_cfg)},
- {IWL_PCI_DEVICE(0x0085, PCI_ANY_ID, iwl6000_3agn_cfg)},
+ {IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000i_2agn_cfg)},
{IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)},
{IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)},
{IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)},