Commit 534f0e29 authored by John W. Linville's avatar John W. Linville

Merge branch 'wireless-next-2.6' of...

Merge branch 'wireless-next-2.6' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6
parents e55034e9 4cd2bf76
...@@ -483,8 +483,6 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv) ...@@ -483,8 +483,6 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv)
/* init calibration handlers */ /* init calibration handlers */
priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
iwlagn_rx_calib_result; iwlagn_rx_calib_result;
priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
iwlagn_rx_calib_complete;
priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
/* set up notification wait support */ /* set up notification wait support */
...@@ -2256,34 +2254,44 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) ...@@ -2256,34 +2254,44 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
/* notification wait support */ /* notification wait support */
void iwlagn_init_notification_wait(struct iwl_priv *priv, void iwlagn_init_notification_wait(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry, struct iwl_notification_wait *wait_entry,
u8 cmd,
void (*fn)(struct iwl_priv *priv, void (*fn)(struct iwl_priv *priv,
struct iwl_rx_packet *pkt), struct iwl_rx_packet *pkt,
u8 cmd) void *data),
void *fn_data)
{ {
wait_entry->fn = fn; wait_entry->fn = fn;
wait_entry->fn_data = fn_data;
wait_entry->cmd = cmd; wait_entry->cmd = cmd;
wait_entry->triggered = false; wait_entry->triggered = false;
wait_entry->aborted = false;
spin_lock_bh(&priv->_agn.notif_wait_lock); spin_lock_bh(&priv->_agn.notif_wait_lock);
list_add(&wait_entry->list, &priv->_agn.notif_waits); list_add(&wait_entry->list, &priv->_agn.notif_waits);
spin_unlock_bh(&priv->_agn.notif_wait_lock); spin_unlock_bh(&priv->_agn.notif_wait_lock);
} }
signed long iwlagn_wait_notification(struct iwl_priv *priv, int iwlagn_wait_notification(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry, struct iwl_notification_wait *wait_entry,
unsigned long timeout) unsigned long timeout)
{ {
int ret; int ret;
ret = wait_event_timeout(priv->_agn.notif_waitq, ret = wait_event_timeout(priv->_agn.notif_waitq,
wait_entry->triggered, wait_entry->triggered || wait_entry->aborted,
timeout); timeout);
spin_lock_bh(&priv->_agn.notif_wait_lock); spin_lock_bh(&priv->_agn.notif_wait_lock);
list_del(&wait_entry->list); list_del(&wait_entry->list);
spin_unlock_bh(&priv->_agn.notif_wait_lock); spin_unlock_bh(&priv->_agn.notif_wait_lock);
return ret; if (wait_entry->aborted)
return -EIO;
/* return value is always >= 0 */
if (ret <= 0)
return -ETIMEDOUT;
return 0;
} }
void iwlagn_remove_notification(struct iwl_priv *priv, void iwlagn_remove_notification(struct iwl_priv *priv,
...@@ -2293,3 +2301,78 @@ void iwlagn_remove_notification(struct iwl_priv *priv, ...@@ -2293,3 +2301,78 @@ void iwlagn_remove_notification(struct iwl_priv *priv,
list_del(&wait_entry->list); list_del(&wait_entry->list);
spin_unlock_bh(&priv->_agn.notif_wait_lock); spin_unlock_bh(&priv->_agn.notif_wait_lock);
} }
int iwlagn_start_device(struct iwl_priv *priv)
{
int ret;
if (iwl_prepare_card_hw(priv)) {
IWL_WARN(priv, "Exit HW not ready\n");
return -EIO;
}
/* If platform's RF_KILL switch is NOT set to KILL */
if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
clear_bit(STATUS_RF_KILL_HW, &priv->status);
else
set_bit(STATUS_RF_KILL_HW, &priv->status);
if (iwl_is_rfkill(priv)) {
wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
iwl_enable_interrupts(priv);
return -ERFKILL;
}
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
ret = iwlagn_hw_nic_init(priv);
if (ret) {
IWL_ERR(priv, "Unable to init nic\n");
return ret;
}
/* make sure rfkill handshake bits are cleared */
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
/* clear (again), then enable host interrupts */
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
iwl_enable_interrupts(priv);
/* really make sure rfkill handshake bits are cleared */
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
return 0;
}
void iwlagn_stop_device(struct iwl_priv *priv)
{
unsigned long flags;
/* stop and reset the on-board processor */
iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
/* tell the device to stop sending interrupts */
spin_lock_irqsave(&priv->lock, flags);
iwl_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->lock, flags);
iwl_synchronize_irq(priv);
/* device going down, Stop using ICT table */
iwl_disable_ict(priv);
iwlagn_txq_ctx_stop(priv);
iwlagn_rxq_stop(priv);
/* Power-down device's busmaster DMA clocks */
iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
udelay(5);
/* Make sure (redundant) we've released our request to stay awake */
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/* Stop the device, and put it in low power state */
iwl_apm_stop(priv);
}
...@@ -58,8 +58,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, ...@@ -58,8 +58,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
u8 old_dev_type = send->dev_type; u8 old_dev_type = send->dev_type;
int ret; int ret;
iwlagn_init_notification_wait(priv, &disable_wait, NULL, iwlagn_init_notification_wait(priv, &disable_wait,
REPLY_WIPAN_DEACTIVATION_COMPLETE); REPLY_WIPAN_DEACTIVATION_COMPLETE,
NULL, NULL);
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
send->dev_type = RXON_DEV_TYPE_P2P; send->dev_type = RXON_DEV_TYPE_P2P;
...@@ -72,13 +73,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, ...@@ -72,13 +73,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
iwlagn_remove_notification(priv, &disable_wait); iwlagn_remove_notification(priv, &disable_wait);
} else { } else {
signed long wait_res; ret = iwlagn_wait_notification(priv, &disable_wait, HZ);
if (ret)
wait_res = iwlagn_wait_notification(priv, &disable_wait, HZ);
if (wait_res == 0) {
IWL_ERR(priv, "Timed out waiting for PAN disable\n"); IWL_ERR(priv, "Timed out waiting for PAN disable\n");
ret = -EIO;
}
} }
return ret; return ret;
......
...@@ -161,47 +161,19 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name, ...@@ -161,47 +161,19 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
} }
static int iwlagn_load_given_ucode(struct iwl_priv *priv, static int iwlagn_load_given_ucode(struct iwl_priv *priv,
struct fw_desc *inst_image, struct fw_img *image)
struct fw_desc *data_image)
{ {
int ret = 0; int ret = 0;
ret = iwlagn_load_section(priv, "INST", inst_image, ret = iwlagn_load_section(priv, "INST", &image->code,
IWLAGN_RTC_INST_LOWER_BOUND); IWLAGN_RTC_INST_LOWER_BOUND);
if (ret) if (ret)
return ret; return ret;
return iwlagn_load_section(priv, "DATA", data_image, return iwlagn_load_section(priv, "DATA", &image->data,
IWLAGN_RTC_DATA_LOWER_BOUND); IWLAGN_RTC_DATA_LOWER_BOUND);
} }
int iwlagn_load_ucode(struct iwl_priv *priv)
{
int ret = 0;
/* check whether init ucode should be loaded, or rather runtime ucode */
if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) {
IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n");
ret = iwlagn_load_given_ucode(priv,
&priv->ucode_init, &priv->ucode_init_data);
if (!ret) {
IWL_DEBUG_INFO(priv, "Init ucode load complete.\n");
priv->ucode_type = UCODE_INIT;
}
} else {
IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. "
"Loading runtime ucode...\n");
ret = iwlagn_load_given_ucode(priv,
&priv->ucode_code, &priv->ucode_data);
if (!ret) {
IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n");
priv->ucode_type = UCODE_RT;
}
}
return ret;
}
/* /*
* Calibration * Calibration
*/ */
...@@ -297,33 +269,9 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv, ...@@ -297,33 +269,9 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv,
iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len);
} }
void iwlagn_rx_calib_complete(struct iwl_priv *priv, static int iwlagn_init_alive_start(struct iwl_priv *priv)
struct iwl_rx_mem_buffer *rxb)
{ {
IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); int ret;
queue_work(priv->workqueue, &priv->restart);
}
void iwlagn_init_alive_start(struct iwl_priv *priv)
{
int ret = 0;
/* initialize uCode was loaded... verify inst image.
* This is a paranoid check, because we would not have gotten the
* "initialize" alive if code weren't properly loaded. */
if (iwl_verify_ucode(priv, &priv->ucode_init)) {
/* Runtime instruction load was bad;
* take it all the way back down so we can try again */
IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
goto restart;
}
ret = iwlagn_alive_notify(priv);
if (ret) {
IWL_WARN(priv,
"Could not complete ALIVE transition: %d\n", ret);
goto restart;
}
if (priv->cfg->bt_params && if (priv->cfg->bt_params &&
priv->cfg->bt_params->advanced_bt_coexist) { priv->cfg->bt_params->advanced_bt_coexist) {
...@@ -333,24 +281,25 @@ void iwlagn_init_alive_start(struct iwl_priv *priv) ...@@ -333,24 +281,25 @@ void iwlagn_init_alive_start(struct iwl_priv *priv)
* no need to close the envlope since we are going * no need to close the envlope since we are going
* to load the runtime uCode later. * to load the runtime uCode later.
*/ */
iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret)
return ret;
} }
iwlagn_send_calib_cfg(priv);
ret = iwlagn_send_calib_cfg(priv);
if (ret)
return ret;
/** /**
* temperature offset calibration is only needed for runtime ucode, * temperature offset calibration is only needed for runtime ucode,
* so prepare the value now. * so prepare the value now.
*/ */
if (priv->cfg->need_temp_offset_calib) if (priv->cfg->need_temp_offset_calib)
iwlagn_set_temperature_offset_calib(priv); return iwlagn_set_temperature_offset_calib(priv);
return;
restart: return 0;
/* real restart (first load init_ucode) */
queue_work(priv->workqueue, &priv->restart);
} }
static int iwlagn_send_wimax_coex(struct iwl_priv *priv) static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
...@@ -413,19 +362,22 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv) ...@@ -413,19 +362,22 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv)
IWL_ERR(priv, "failed to send BT prio tbl command\n"); IWL_ERR(priv, "failed to send BT prio tbl command\n");
} }
void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
{ {
struct iwl_bt_coex_prot_env_cmd env_cmd; struct iwl_bt_coex_prot_env_cmd env_cmd;
int ret;
env_cmd.action = action; env_cmd.action = action;
env_cmd.type = type; env_cmd.type = type;
if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, ret = iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV,
sizeof(env_cmd), &env_cmd)) sizeof(env_cmd), &env_cmd);
if (ret)
IWL_ERR(priv, "failed to send BT env command\n"); IWL_ERR(priv, "failed to send BT env command\n");
return ret;
} }
int iwlagn_alive_notify(struct iwl_priv *priv) static int iwlagn_alive_notify(struct iwl_priv *priv)
{ {
const struct queue_to_fifo_ac *queue_to_fifo; const struct queue_to_fifo_ac *queue_to_fifo;
struct iwl_rxon_context *ctx; struct iwl_rxon_context *ctx;
...@@ -604,15 +556,164 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv, ...@@ -604,15 +556,164 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
* iwl_verify_ucode - determine which instruction image is in SRAM, * iwl_verify_ucode - determine which instruction image is in SRAM,
* and verify its contents * and verify its contents
*/ */
int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc) static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img)
{ {
if (!iwlcore_verify_inst_sparse(priv, fw_desc)) { if (!iwlcore_verify_inst_sparse(priv, &img->code)) {
IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n"); IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n");
return 0; return 0;
} }
IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n"); IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
iwl_print_mismatch_inst(priv, fw_desc); iwl_print_mismatch_inst(priv, &img->code);
return -EIO;
}
struct iwlagn_alive_data {
bool valid;
u8 subtype;
};
static void iwlagn_alive_fn(struct iwl_priv *priv,
struct iwl_rx_packet *pkt,
void *data)
{
struct iwlagn_alive_data *alive_data = data;
struct iwl_alive_resp *palive;
palive = &pkt->u.alive_frame;
IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
"0x%01X 0x%01X\n",
palive->is_valid, palive->ver_type,
palive->ver_subtype);
priv->device_pointers.error_event_table =
le32_to_cpu(palive->error_event_table_ptr);
priv->device_pointers.log_event_table =
le32_to_cpu(palive->log_event_table_ptr);
alive_data->subtype = palive->ver_subtype;
alive_data->valid = palive->is_valid == UCODE_VALID_OK;
}
#define UCODE_ALIVE_TIMEOUT HZ
#define UCODE_CALIB_TIMEOUT (2*HZ)
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
struct fw_img *image,
int subtype, int alternate_subtype)
{
struct iwl_notification_wait alive_wait;
struct iwlagn_alive_data alive_data;
int ret;
enum iwlagn_ucode_subtype old_type;
ret = iwlagn_start_device(priv);
if (ret)
return ret;
iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE,
iwlagn_alive_fn, &alive_data);
old_type = priv->ucode_type;
priv->ucode_type = subtype;
ret = iwlagn_load_given_ucode(priv, image);
if (ret) {
priv->ucode_type = old_type;
iwlagn_remove_notification(priv, &alive_wait);
return ret;
}
/* Remove all resets to allow NIC to operate */
iwl_write32(priv, CSR_RESET, 0);
/*
* Some things may run in the background now, but we
* just wait for the ALIVE notification here.
*/
ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT);
if (ret) {
priv->ucode_type = old_type;
return ret;
}
if (!alive_data.valid) {
IWL_ERR(priv, "Loaded ucode is not valid!\n");
priv->ucode_type = old_type;
return -EIO; return -EIO;
}
if (alive_data.subtype != subtype &&
alive_data.subtype != alternate_subtype) {
IWL_ERR(priv,
"Loaded ucode is not expected type (got %d, expected %d)!\n",
alive_data.subtype, subtype);
priv->ucode_type = old_type;
return -EIO;
}
ret = iwl_verify_ucode(priv, image);
if (ret) {
priv->ucode_type = old_type;
return ret;
}
/* delay a bit to give rfkill time to run */
msleep(5);
ret = iwlagn_alive_notify(priv);
if (ret) {
IWL_WARN(priv,
"Could not complete ALIVE transition: %d\n", ret);
priv->ucode_type = old_type;
return ret;
}
return 0;
}
int iwlagn_run_init_ucode(struct iwl_priv *priv)
{
struct iwl_notification_wait calib_wait;
int ret;
lockdep_assert_held(&priv->mutex);
/* No init ucode required? Curious, but maybe ok */
if (!priv->ucode_init.code.len)
return 0;
if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED)
return 0;
iwlagn_init_notification_wait(priv, &calib_wait,
CALIBRATION_COMPLETE_NOTIFICATION,
NULL, NULL);
/* Will also start the device */
ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
UCODE_SUBTYPE_INIT, -1);
if (ret)
goto error;
ret = iwlagn_init_alive_start(priv);
if (ret)
goto error;
/*
* Some things may run in the background now, but we
* just wait for the calibration complete notification.
*/
ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT);
goto out;
error:
iwlagn_remove_notification(priv, &calib_wait);
out:
/* Whatever happened, stop the device */
iwlagn_stop_device(priv);
return ret;
} }
...@@ -769,7 +769,7 @@ static void iwl_rx_handle(struct iwl_priv *priv) ...@@ -769,7 +769,7 @@ static void iwl_rx_handle(struct iwl_priv *priv)
if (w->cmd == pkt->hdr.cmd) { if (w->cmd == pkt->hdr.cmd) {
w->triggered = true; w->triggered = true;
if (w->fn) if (w->fn)
w->fn(priv, pkt); w->fn(priv, pkt, w->fn_data);
} }
} }
spin_unlock(&priv->_agn.notif_wait_lock); spin_unlock(&priv->_agn.notif_wait_lock);
...@@ -846,14 +846,6 @@ static void iwl_rx_handle(struct iwl_priv *priv) ...@@ -846,14 +846,6 @@ static void iwl_rx_handle(struct iwl_priv *priv)
iwlagn_rx_queue_restock(priv); iwlagn_rx_queue_restock(priv);
} }
/* call this function to flush any scheduled tasklet */
static inline void iwl_synchronize_irq(struct iwl_priv *priv)
{
/* wait to make sure we flush pending tasklet*/
synchronize_irq(priv->pci_dev->irq);
tasklet_kill(&priv->irq_tasklet);
}
/* tasklet for iwlagn interrupt */ /* tasklet for iwlagn interrupt */
static void iwl_irq_tasklet(struct iwl_priv *priv) static void iwl_irq_tasklet(struct iwl_priv *priv)
{ {
...@@ -1181,18 +1173,42 @@ static struct attribute_group iwl_attribute_group = { ...@@ -1181,18 +1173,42 @@ static struct attribute_group iwl_attribute_group = {
* *
******************************************************************************/ ******************************************************************************/
static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
{
if (desc->v_addr)
dma_free_coherent(&pci_dev->dev, desc->len,
desc->v_addr, desc->p_addr);
desc->v_addr = NULL;
desc->len = 0;
}
static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img)
{ {
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code); iwl_free_fw_desc(pci_dev, &img->code);
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data); iwl_free_fw_desc(pci_dev, &img->data);
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init);
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
} }
static void iwl_nic_start(struct iwl_priv *priv) static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
const void *data, size_t len)
{ {
/* Remove all resets to allow NIC to operate */ if (!len) {
iwl_write32(priv, CSR_RESET, 0); desc->v_addr = NULL;
return -EINVAL;
}
desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len,
&desc->p_addr, GFP_KERNEL);
if (!desc->v_addr)
return -ENOMEM;
desc->len = len;
memcpy(desc->v_addr, data, len);
return 0;
}
static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
{
iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt);
iwl_free_fw_img(priv->pci_dev, &priv->ucode_init);
} }
struct iwlagn_ucode_capabilities { struct iwlagn_ucode_capabilities {
...@@ -1661,24 +1677,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) ...@@ -1661,24 +1677,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
/* Runtime instructions and 2 copies of data: /* Runtime instructions and 2 copies of data:
* 1) unmodified from disk * 1) unmodified from disk
* 2) backup cache for save/restore during power-downs */ * 2) backup cache for save/restore during power-downs */
priv->ucode_code.len = pieces.inst_size; if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code,
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); pieces.inst, pieces.inst_size))
goto err_pci_alloc;
priv->ucode_data.len = pieces.data_size; if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data,
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); pieces.data, pieces.data_size))
if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr)
goto err_pci_alloc; goto err_pci_alloc;
/* Initialization instructions and data */ /* Initialization instructions and data */
if (pieces.init_size && pieces.init_data_size) { if (pieces.init_size && pieces.init_data_size) {
priv->ucode_init.len = pieces.init_size; if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code,
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); pieces.init, pieces.init_size))
goto err_pci_alloc;
priv->ucode_init_data.len = pieces.init_data_size; if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data,
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); pieces.init_data, pieces.init_data_size))
if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
goto err_pci_alloc; goto err_pci_alloc;
} }
...@@ -1715,39 +1727,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) ...@@ -1715,39 +1727,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
else else
priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n",
pieces.inst_size);
memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size);
IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
/*
* Runtime data
* NOTE: Copy into backup buffer will be done in iwl_up()
*/
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n",
pieces.data_size);
memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size);
/* Initialization instructions */
if (pieces.init_size) {
IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n",
pieces.init_size);
memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size);
}
/* Initialization data */
if (pieces.init_data_size) {
IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n",
pieces.init_data_size);
memcpy(priv->ucode_init_data.v_addr, pieces.init_data,
pieces.init_data_size);
}
/* /*
* figure out the offset of chain noise reset and gain commands * figure out the offset of chain noise reset and gain commands
* base on the size of standard phy calibration commands table size * base on the size of standard phy calibration commands table size
...@@ -1878,9 +1857,10 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) ...@@ -1878,9 +1857,10 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
u32 desc, time, count, base, data1; u32 desc, time, count, base, data1;
u32 blink1, blink2, ilink1, ilink2; u32 blink1, blink2, ilink1, ilink2;
u32 pc, hcmd; u32 pc, hcmd;
struct iwl_error_event_table table;
base = priv->device_pointers.error_event_table; base = priv->device_pointers.error_event_table;
if (priv->ucode_type == UCODE_INIT) { if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
if (!base) if (!base)
base = priv->_agn.init_errlog_ptr; base = priv->_agn.init_errlog_ptr;
} else { } else {
...@@ -1891,11 +1871,15 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) ...@@ -1891,11 +1871,15 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
IWL_ERR(priv, IWL_ERR(priv,
"Not valid error log pointer 0x%08X for %s uCode\n", "Not valid error log pointer 0x%08X for %s uCode\n",
base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); base,
(priv->ucode_type == UCODE_SUBTYPE_INIT)
? "Init" : "RT");
return; return;
} }
count = iwl_read_targ_mem(priv, base); iwl_read_targ_mem_words(priv, base, &table, sizeof(table));
count = table.valid;
if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
IWL_ERR(priv, "Start IWL Error Log Dump:\n"); IWL_ERR(priv, "Start IWL Error Log Dump:\n");
...@@ -1903,18 +1887,18 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) ...@@ -1903,18 +1887,18 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
priv->status, count); priv->status, count);
} }
desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); desc = table.error_id;
priv->isr_stats.err_code = desc; priv->isr_stats.err_code = desc;
pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32)); pc = table.pc;
blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); blink1 = table.blink1;
blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); blink2 = table.blink2;
ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); ilink1 = table.ilink1;
ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32)); ilink2 = table.ilink2;
data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32)); data1 = table.data1;
data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); data2 = table.data2;
line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); line = table.line;
time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); time = table.tsf_low;
hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32)); hcmd = table.hcmd;
trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line,
blink1, blink2, ilink1, ilink2); blink1, blink2, ilink1, ilink2);
...@@ -1949,7 +1933,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, ...@@ -1949,7 +1933,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
return pos; return pos;
base = priv->device_pointers.log_event_table; base = priv->device_pointers.log_event_table;
if (priv->ucode_type == UCODE_INIT) { if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
if (!base) if (!base)
base = priv->_agn.init_evtlog_ptr; base = priv->_agn.init_evtlog_ptr;
} else { } else {
...@@ -2062,7 +2046,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, ...@@ -2062,7 +2046,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
size_t bufsz = 0; size_t bufsz = 0;
base = priv->device_pointers.log_event_table; base = priv->device_pointers.log_event_table;
if (priv->ucode_type == UCODE_INIT) { if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
logsize = priv->_agn.init_evtlog_size; logsize = priv->_agn.init_evtlog_size;
if (!base) if (!base)
base = priv->_agn.init_evtlog_ptr; base = priv->_agn.init_evtlog_ptr;
...@@ -2075,7 +2059,9 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, ...@@ -2075,7 +2059,9 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
IWL_ERR(priv, IWL_ERR(priv,
"Invalid event log pointer 0x%08X for %s uCode\n", "Invalid event log pointer 0x%08X for %s uCode\n",
base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); base,
(priv->ucode_type == UCODE_SUBTYPE_INIT)
? "Init" : "RT");
return -EINVAL; return -EINVAL;
} }
...@@ -2222,30 +2208,14 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) ...@@ -2222,30 +2208,14 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
* from protocol/runtime uCode (initialization uCode's * from protocol/runtime uCode (initialization uCode's
* Alive gets handled by iwl_init_alive_start()). * Alive gets handled by iwl_init_alive_start()).
*/ */
static void iwl_alive_start(struct iwl_priv *priv) static int iwl_alive_start(struct iwl_priv *priv)
{ {
int ret = 0; int ret = 0;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); iwl_reset_ict(priv);
/* Initialize uCode has loaded Runtime uCode ... verify inst image.
* This is a paranoid check, because we would not have gotten the
* "runtime" alive if code weren't properly loaded. */
if (iwl_verify_ucode(priv, &priv->ucode_code)) {
/* Runtime instruction load was bad;
* take it all the way back down so we can try again */
IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n");
goto restart;
}
ret = iwlagn_alive_notify(priv);
if (ret) {
IWL_WARN(priv,
"Could not complete ALIVE transition [ntf]: %d\n", ret);
goto restart;
}
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
/* After the ALIVE response, we can send host commands to the uCode */ /* After the ALIVE response, we can send host commands to the uCode */
set_bit(STATUS_ALIVE, &priv->status); set_bit(STATUS_ALIVE, &priv->status);
...@@ -2254,7 +2224,7 @@ static void iwl_alive_start(struct iwl_priv *priv) ...@@ -2254,7 +2224,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
iwl_setup_watchdog(priv); iwl_setup_watchdog(priv);
if (iwl_is_rfkill(priv)) if (iwl_is_rfkill(priv))
return; return -ERFKILL;
/* download priority table before any calibration request */ /* download priority table before any calibration request */
if (priv->cfg->bt_params && if (priv->cfg->bt_params &&
...@@ -2268,10 +2238,14 @@ static void iwl_alive_start(struct iwl_priv *priv) ...@@ -2268,10 +2238,14 @@ static void iwl_alive_start(struct iwl_priv *priv)
iwlagn_send_prio_tbl(priv); iwlagn_send_prio_tbl(priv);
/* FIXME: w/a to force change uCode BT state machine */ /* FIXME: w/a to force change uCode BT state machine */
iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, if (ret)
return ret;
ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret)
return ret;
} }
if (priv->hw_params.calib_rt_cfg) if (priv->hw_params.calib_rt_cfg)
iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg);
...@@ -2313,29 +2287,22 @@ static void iwl_alive_start(struct iwl_priv *priv) ...@@ -2313,29 +2287,22 @@ static void iwl_alive_start(struct iwl_priv *priv)
set_bit(STATUS_READY, &priv->status); set_bit(STATUS_READY, &priv->status);
/* Configure the adapter for unassociated operation */ /* Configure the adapter for unassociated operation */
iwlcore_commit_rxon(priv, ctx); ret = iwlcore_commit_rxon(priv, ctx);
if (ret)
return ret;
/* At this point, the NIC is initialized and operational */ /* At this point, the NIC is initialized and operational */
iwl_rf_kill_ct_config(priv); iwl_rf_kill_ct_config(priv);
IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
wake_up_interruptible(&priv->wait_command_queue);
iwl_power_update_mode(priv, true); return iwl_power_update_mode(priv, true);
IWL_DEBUG_INFO(priv, "Updated power mode\n");
return;
restart:
queue_work(priv->workqueue, &priv->restart);
} }
static void iwl_cancel_deferred_work(struct iwl_priv *priv); static void iwl_cancel_deferred_work(struct iwl_priv *priv);
static void __iwl_down(struct iwl_priv *priv) static void __iwl_down(struct iwl_priv *priv)
{ {
unsigned long flags;
int exit_pending; int exit_pending;
IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
...@@ -2367,32 +2334,10 @@ static void __iwl_down(struct iwl_priv *priv) ...@@ -2367,32 +2334,10 @@ static void __iwl_down(struct iwl_priv *priv)
if (!exit_pending) if (!exit_pending)
clear_bit(STATUS_EXIT_PENDING, &priv->status); clear_bit(STATUS_EXIT_PENDING, &priv->status);
/* stop and reset the on-board processor */
iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
/* tell the device to stop sending interrupts */
spin_lock_irqsave(&priv->lock, flags);
iwl_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->lock, flags);
iwl_synchronize_irq(priv);
if (priv->mac80211_registered) if (priv->mac80211_registered)
ieee80211_stop_queues(priv->hw); ieee80211_stop_queues(priv->hw);
/* If we have not previously called iwl_init() then /* Clear out all status bits but a few that are stable across reset */
* clear all bits but the RF Kill bit and return */
if (!iwl_is_init(priv)) {
priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
STATUS_RF_KILL_HW |
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
STATUS_GEO_CONFIGURED |
test_bit(STATUS_EXIT_PENDING, &priv->status) <<
STATUS_EXIT_PENDING;
goto exit;
}
/* ...otherwise clear out all the status bits but the RF Kill
* bit and continue taking the NIC down. */
priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
STATUS_RF_KILL_HW | STATUS_RF_KILL_HW |
test_bit(STATUS_GEO_CONFIGURED, &priv->status) << test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
...@@ -2402,23 +2347,8 @@ static void __iwl_down(struct iwl_priv *priv) ...@@ -2402,23 +2347,8 @@ static void __iwl_down(struct iwl_priv *priv)
test_bit(STATUS_EXIT_PENDING, &priv->status) << test_bit(STATUS_EXIT_PENDING, &priv->status) <<
STATUS_EXIT_PENDING; STATUS_EXIT_PENDING;
/* device going down, Stop using ICT table */ iwlagn_stop_device(priv);
iwl_disable_ict(priv);
iwlagn_txq_ctx_stop(priv);
iwlagn_rxq_stop(priv);
/* Power-down device's busmaster DMA clocks */
iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
udelay(5);
/* Make sure (redundant) we've released our request to stay awake */
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
/* Stop the device, and put it in low power state */
iwl_apm_stop(priv);
exit:
dev_kfree_skb(priv->beacon_skb); dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = NULL; priv->beacon_skb = NULL;
...@@ -2437,9 +2367,10 @@ static void iwl_down(struct iwl_priv *priv) ...@@ -2437,9 +2367,10 @@ static void iwl_down(struct iwl_priv *priv)
#define HW_READY_TIMEOUT (50) #define HW_READY_TIMEOUT (50)
/* Note: returns poll_bit return value, which is >= 0 if success */
static int iwl_set_hw_ready(struct iwl_priv *priv) static int iwl_set_hw_ready(struct iwl_priv *priv)
{ {
int ret = 0; int ret;
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
...@@ -2449,25 +2380,21 @@ static int iwl_set_hw_ready(struct iwl_priv *priv) ...@@ -2449,25 +2380,21 @@ static int iwl_set_hw_ready(struct iwl_priv *priv)
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
HW_READY_TIMEOUT); HW_READY_TIMEOUT);
if (ret != -ETIMEDOUT)
priv->hw_ready = true;
else
priv->hw_ready = false;
IWL_DEBUG_INFO(priv, "hardware %s\n", IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : "");
(priv->hw_ready == 1) ? "ready" : "not ready");
return ret; return ret;
} }
static int iwl_prepare_card_hw(struct iwl_priv *priv) /* Note: returns standard 0/-ERROR code */
int iwl_prepare_card_hw(struct iwl_priv *priv)
{ {
int ret = 0; int ret;
IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n");
ret = iwl_set_hw_ready(priv); ret = iwl_set_hw_ready(priv);
if (priv->hw_ready) if (ret >= 0)
return ret; return 0;
/* If HW is not ready, prepare the conditions to check again */ /* If HW is not ready, prepare the conditions to check again */
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
...@@ -2477,10 +2404,13 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv) ...@@ -2477,10 +2404,13 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv)
~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
/* HW should be ready by now, check again. */ if (ret < 0)
if (ret != -ETIMEDOUT) return ret;
iwl_set_hw_ready(priv);
/* HW should be ready by now, check again. */
ret = iwl_set_hw_ready(priv);
if (ret >= 0)
return 0;
return ret; return ret;
} }
...@@ -2489,9 +2419,10 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv) ...@@ -2489,9 +2419,10 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv)
static int __iwl_up(struct iwl_priv *priv) static int __iwl_up(struct iwl_priv *priv)
{ {
struct iwl_rxon_context *ctx; struct iwl_rxon_context *ctx;
int i;
int ret; int ret;
lockdep_assert_held(&priv->mutex);
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
return -EIO; return -EIO;
...@@ -2505,77 +2436,33 @@ static int __iwl_up(struct iwl_priv *priv) ...@@ -2505,77 +2436,33 @@ static int __iwl_up(struct iwl_priv *priv)
} }
} }
iwl_prepare_card_hw(priv); ret = iwlagn_run_init_ucode(priv);
if (!priv->hw_ready) {
IWL_WARN(priv, "Exit HW not ready\n");
return -EIO;
}
/* If platform's RF_KILL switch is NOT set to KILL */
if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
clear_bit(STATUS_RF_KILL_HW, &priv->status);
else
set_bit(STATUS_RF_KILL_HW, &priv->status);
if (iwl_is_rfkill(priv)) {
wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
iwl_enable_interrupts(priv);
IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
return 0;
}
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
ret = iwlagn_hw_nic_init(priv);
if (ret) { if (ret) {
IWL_ERR(priv, "Unable to init nic\n"); IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret);
return ret; goto error;
} }
/* make sure rfkill handshake bits are cleared */ ret = iwlagn_load_ucode_wait_alive(priv,
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); &priv->ucode_rt,
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, UCODE_SUBTYPE_REGULAR,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); UCODE_SUBTYPE_REGULAR_NEW);
/* clear (again), then enable host interrupts */
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
iwl_enable_interrupts(priv);
/* really make sure rfkill handshake bits are cleared */
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
for (i = 0; i < MAX_HW_RESTARTS; i++) {
/* load bootstrap state machine,
* load bootstrap program into processor's memory,
* prepare to load the "initialize" uCode */
ret = iwlagn_load_ucode(priv);
if (ret) { if (ret) {
IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n", IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
ret); goto error;
continue;
} }
/* start card; "initialize" will load runtime ucode */ ret = iwl_alive_start(priv);
iwl_nic_start(priv); if (ret)
goto error;
IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
return 0; return 0;
}
error:
set_bit(STATUS_EXIT_PENDING, &priv->status); set_bit(STATUS_EXIT_PENDING, &priv->status);
__iwl_down(priv); __iwl_down(priv);
clear_bit(STATUS_EXIT_PENDING, &priv->status); clear_bit(STATUS_EXIT_PENDING, &priv->status);
/* tried to restart and config the device for as long as our IWL_ERR(priv, "Unable to initialize device.\n");
* patience could withstand */ return ret;
IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
return -EIO;
} }
...@@ -2585,39 +2472,6 @@ static int __iwl_up(struct iwl_priv *priv) ...@@ -2585,39 +2472,6 @@ static int __iwl_up(struct iwl_priv *priv)
* *
*****************************************************************************/ *****************************************************************************/
static void iwl_bg_init_alive_start(struct work_struct *data)
{
struct iwl_priv *priv =
container_of(data, struct iwl_priv, init_alive_start.work);
mutex_lock(&priv->mutex);
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
mutex_unlock(&priv->mutex);
return;
}
iwlagn_init_alive_start(priv);
mutex_unlock(&priv->mutex);
}
static void iwl_bg_alive_start(struct work_struct *data)
{
struct iwl_priv *priv =
container_of(data, struct iwl_priv, alive_start.work);
mutex_lock(&priv->mutex);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
goto unlock;
/* enable dram interrupt */
iwl_reset_ict(priv);
iwl_alive_start(priv);
unlock:
mutex_unlock(&priv->mutex);
}
static void iwl_bg_run_time_calib_work(struct work_struct *work) static void iwl_bg_run_time_calib_work(struct work_struct *work)
{ {
struct iwl_priv *priv = container_of(work, struct iwl_priv, struct iwl_priv *priv = container_of(work, struct iwl_priv,
...@@ -2683,14 +2537,7 @@ static void iwl_bg_restart(struct work_struct *data) ...@@ -2683,14 +2537,7 @@ static void iwl_bg_restart(struct work_struct *data)
iwl_cancel_deferred_work(priv); iwl_cancel_deferred_work(priv);
ieee80211_restart_hw(priv->hw); ieee80211_restart_hw(priv->hw);
} else { } else {
iwl_down(priv); WARN_ON(1);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
mutex_lock(&priv->mutex);
__iwl_up(priv);
mutex_unlock(&priv->mutex);
} }
} }
...@@ -2801,8 +2648,6 @@ static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw) ...@@ -2801,8 +2648,6 @@ static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw)
* *
*****************************************************************************/ *****************************************************************************/
#define UCODE_READY_TIMEOUT (4 * HZ)
/* /*
* Not a mac80211 entry point function, but it fits in with all the * Not a mac80211 entry point function, but it fits in with all the
* other mac80211 functions grouped here. * other mac80211 functions grouped here.
...@@ -2895,31 +2740,17 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) ...@@ -2895,31 +2740,17 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
ret = __iwl_up(priv); ret = __iwl_up(priv);
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
if (ret) if (ret)
return ret; return ret;
if (iwl_is_rfkill(priv))
goto out;
IWL_DEBUG_INFO(priv, "Start UP work done.\n"); IWL_DEBUG_INFO(priv, "Start UP work done.\n");
/* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from /* Now we should be done, and the READY bit should be set. */
* mac80211 will not be run successfully. */ if (WARN_ON(!test_bit(STATUS_READY, &priv->status)))
ret = wait_event_interruptible_timeout(priv->wait_command_queue, ret = -EIO;
test_bit(STATUS_READY, &priv->status),
UCODE_READY_TIMEOUT);
if (!ret) {
if (!test_bit(STATUS_READY, &priv->status)) {
IWL_ERR(priv, "START_ALIVE timeout after %dms.\n",
jiffies_to_msecs(UCODE_READY_TIMEOUT));
return -ETIMEDOUT;
}
}
iwlagn_led_enable(priv); iwlagn_led_enable(priv);
out:
priv->is_open = 1; priv->is_open = 1;
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
return 0; return 0;
...@@ -3506,8 +3337,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) ...@@ -3506,8 +3337,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done); INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done);
iwl_setup_scan_deferred_work(priv); iwl_setup_scan_deferred_work(priv);
...@@ -3536,8 +3365,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) ...@@ -3536,8 +3365,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
if (priv->cfg->ops->lib->cancel_deferred_work) if (priv->cfg->ops->lib->cancel_deferred_work)
priv->cfg->ops->lib->cancel_deferred_work(priv); priv->cfg->ops->lib->cancel_deferred_work(priv);
cancel_delayed_work_sync(&priv->init_alive_start);
cancel_delayed_work(&priv->alive_start);
cancel_work_sync(&priv->run_time_calib_work); cancel_work_sync(&priv->run_time_calib_work);
cancel_work_sync(&priv->beacon_update); cancel_work_sync(&priv->beacon_update);
...@@ -3772,6 +3599,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3772,6 +3599,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv = hw->priv; priv = hw->priv;
/* At this point both hw and priv are allocated. */ /* At this point both hw and priv are allocated. */
priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED;
/* /*
* The default context is always valid, * The default context is always valid,
* more may be discovered when firmware * more may be discovered when firmware
...@@ -3912,8 +3741,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3912,8 +3741,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* PCI Tx retries from interfering with C3 CPU state */ * PCI Tx retries from interfering with C3 CPU state */
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
iwl_prepare_card_hw(priv); if (iwl_prepare_card_hw(priv)) {
if (!priv->hw_ready) {
IWL_WARN(priv, "Failed, HW not ready\n"); IWL_WARN(priv, "Failed, HW not ready\n");
goto out_iounmap; goto out_iounmap;
} }
...@@ -4069,17 +3897,9 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) ...@@ -4069,17 +3897,9 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
if (priv->mac80211_registered) { if (priv->mac80211_registered) {
ieee80211_unregister_hw(priv->hw); ieee80211_unregister_hw(priv->hw);
priv->mac80211_registered = 0; priv->mac80211_registered = 0;
} else {
iwl_down(priv);
} }
/* /* Reset to low power before unloading driver. */
* Make sure device is reset to low power before unloading driver.
* This may be redundant with iwl_down(), but there are paths to
* run iwl_down() without calling apm_ops.stop(), and there are
* paths to avoid running iwl_down() at all before leaving driver.
* This (inexpensive) call *makes sure* device is reset.
*/
iwl_apm_stop(priv); iwl_apm_stop(priv);
iwl_tt_exit(priv); iwl_tt_exit(priv);
......
...@@ -120,6 +120,19 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv); ...@@ -120,6 +120,19 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv);
void iwl_free_isr_ict(struct iwl_priv *priv); void iwl_free_isr_ict(struct iwl_priv *priv);
irqreturn_t iwl_isr_ict(int irq, void *data); irqreturn_t iwl_isr_ict(int irq, void *data);
/* call this function to flush any scheduled tasklet */
static inline void iwl_synchronize_irq(struct iwl_priv *priv)
{
/* wait to make sure we flush pending tasklet*/
synchronize_irq(priv->pci_dev->irq);
tasklet_kill(&priv->irq_tasklet);
}
int iwl_prepare_card_hw(struct iwl_priv *priv);
int iwlagn_start_device(struct iwl_priv *priv);
void iwlagn_stop_device(struct iwl_priv *priv);
/* tx queue */ /* tx queue */
void iwlagn_set_wr_ptrs(struct iwl_priv *priv, void iwlagn_set_wr_ptrs(struct iwl_priv *priv,
int txq_id, u32 index); int txq_id, u32 index);
...@@ -145,16 +158,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, ...@@ -145,16 +158,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
u32 changes); u32 changes);
/* uCode */ /* uCode */
int iwlagn_load_ucode(struct iwl_priv *priv);
void iwlagn_rx_calib_result(struct iwl_priv *priv, void iwlagn_rx_calib_result(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb); struct iwl_rx_mem_buffer *rxb);
void iwlagn_rx_calib_complete(struct iwl_priv *priv, int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
struct iwl_rx_mem_buffer *rxb);
void iwlagn_init_alive_start(struct iwl_priv *priv);
int iwlagn_alive_notify(struct iwl_priv *priv);
int iwl_verify_ucode(struct iwl_priv *priv, struct fw_desc *fw_desc);
void iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
void iwlagn_send_prio_tbl(struct iwl_priv *priv); void iwlagn_send_prio_tbl(struct iwl_priv *priv);
int iwlagn_run_init_ucode(struct iwl_priv *priv);
int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
struct fw_img *image,
int subtype, int alternate_subtype);
/* lib */ /* lib */
void iwl_check_abort_status(struct iwl_priv *priv, void iwl_check_abort_status(struct iwl_priv *priv,
...@@ -325,10 +336,12 @@ void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); ...@@ -325,10 +336,12 @@ void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
void __acquires(wait_entry) void __acquires(wait_entry)
iwlagn_init_notification_wait(struct iwl_priv *priv, iwlagn_init_notification_wait(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry, struct iwl_notification_wait *wait_entry,
u8 cmd,
void (*fn)(struct iwl_priv *priv, void (*fn)(struct iwl_priv *priv,
struct iwl_rx_packet *pkt), struct iwl_rx_packet *pkt,
u8 cmd); void *data),
signed long __releases(wait_entry) void *fn_data);
int __must_check __releases(wait_entry)
iwlagn_wait_notification(struct iwl_priv *priv, iwlagn_wait_notification(struct iwl_priv *priv,
struct iwl_notification_wait *wait_entry, struct iwl_notification_wait *wait_entry,
unsigned long timeout); unsigned long timeout);
......
...@@ -386,7 +386,18 @@ struct iwl_tx_ant_config_cmd { ...@@ -386,7 +386,18 @@ struct iwl_tx_ant_config_cmd {
*****************************************************************************/ *****************************************************************************/
#define UCODE_VALID_OK cpu_to_le32(0x1) #define UCODE_VALID_OK cpu_to_le32(0x1)
#define INITIALIZE_SUBTYPE (9)
enum iwlagn_ucode_subtype {
UCODE_SUBTYPE_REGULAR = 0,
UCODE_SUBTYPE_REGULAR_NEW = 1,
UCODE_SUBTYPE_INIT = 9,
/*
* Not a valid subtype, the ucode has just a u8, so
* we can use something > 0xff for this value.
*/
UCODE_SUBTYPE_NONE_LOADED = 0x100,
};
/** /**
* REPLY_ALIVE = 0x1 (response only, not a command) * REPLY_ALIVE = 0x1 (response only, not a command)
...@@ -422,49 +433,61 @@ struct iwl_tx_ant_config_cmd { ...@@ -422,49 +433,61 @@ struct iwl_tx_ant_config_cmd {
* *
* 2) error_event_table_ptr indicates base of the error log. This contains * 2) error_event_table_ptr indicates base of the error log. This contains
* information about any uCode error that occurs. For agn, the format * information about any uCode error that occurs. For agn, the format
* of the error log is: * of the error log is defined by struct iwl_error_event_table.
*
* __le32 valid; (nonzero) valid, (0) log is empty
* __le32 error_id; type of error
* __le32 pc; program counter
* __le32 blink1; branch link
* __le32 blink2; branch link
* __le32 ilink1; interrupt link
* __le32 ilink2; interrupt link
* __le32 data1; error-specific data
* __le32 data2; error-specific data
* __le32 line; source code line of error
* __le32 bcon_time; beacon timer
* __le32 tsf_low; network timestamp function timer
* __le32 tsf_hi; network timestamp function timer
* __le32 gp1; GP1 timer register
* __le32 gp2; GP2 timer register
* __le32 gp3; GP3 timer register
* __le32 ucode_ver; uCode version
* __le32 hw_ver; HW Silicon version
* __le32 brd_ver; HW board version
* __le32 log_pc; log program counter
* __le32 frame_ptr; frame pointer
* __le32 stack_ptr; stack pointer
* __le32 hcmd; last host command
* __le32 isr0; isr status register LMPM_NIC_ISR0: rxtx_flag
* __le32 isr1; isr status register LMPM_NIC_ISR1: host_flag
* __le32 isr2; isr status register LMPM_NIC_ISR2: enc_flag
* __le32 isr3; isr status register LMPM_NIC_ISR3: time_flag
* __le32 isr4; isr status register LMPM_NIC_ISR4: wico interrupt
* __le32 isr_pref; isr status register LMPM_NIC_PREF_STAT
* __le32 wait_event; wait event() caller address
* __le32 l2p_control; L2pControlField
* __le32 l2p_duration; L2pDurationField
* __le32 l2p_mhvalid; L2pMhValidBits
* __le32 l2p_addr_match; L2pAddrMatchStat
* __le32 lmpm_pmg_sel; indicate which clocks are turned on (LMPM_PMG_SEL)
* __le32 u_timestamp; indicate when the date and time of the compilation
* __le32 reserved;
* *
* The Linux driver can print both logs to the system log when a uCode error * The Linux driver can print both logs to the system log when a uCode error
* occurs. * occurs.
*/ */
/*
* Note: This structure is read from the device with IO accesses,
* and the reading already does the endian conversion. As it is
* read with u32-sized accesses, any members with a different size
* need to be ordered correctly though!
*/
struct iwl_error_event_table {
u32 valid; /* (nonzero) valid, (0) log is empty */
u32 error_id; /* type of error */
u32 pc; /* program counter */
u32 blink1; /* branch link */
u32 blink2; /* branch link */
u32 ilink1; /* interrupt link */
u32 ilink2; /* interrupt link */
u32 data1; /* error-specific data */
u32 data2; /* error-specific data */
u32 line; /* source code line of error */
u32 bcon_time; /* beacon timer */
u32 tsf_low; /* network timestamp function timer */
u32 tsf_hi; /* network timestamp function timer */
u32 gp1; /* GP1 timer register */
u32 gp2; /* GP2 timer register */
u32 gp3; /* GP3 timer register */
u32 ucode_ver; /* uCode version */
u32 hw_ver; /* HW Silicon version */
u32 brd_ver; /* HW board version */
u32 log_pc; /* log program counter */
u32 frame_ptr; /* frame pointer */
u32 stack_ptr; /* stack pointer */
u32 hcmd; /* last host command header */
#if 0
/* no need to read the remainder, we don't use the values */
u32 isr0; /* isr status register LMPM_NIC_ISR0: rxtx_flag */
u32 isr1; /* isr status register LMPM_NIC_ISR1: host_flag */
u32 isr2; /* isr status register LMPM_NIC_ISR2: enc_flag */
u32 isr3; /* isr status register LMPM_NIC_ISR3: time_flag */
u32 isr4; /* isr status register LMPM_NIC_ISR4: wico interrupt */
u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */
u32 wait_event; /* wait event() caller address */
u32 l2p_control; /* L2pControlField */
u32 l2p_duration; /* L2pDurationField */
u32 l2p_mhvalid; /* L2pMhValidBits */
u32 l2p_addr_match; /* L2pAddrMatchStat */
u32 lmpm_pmg_sel; /* indicate which clocks are turned on (LMPM_PMG_SEL) */
u32 u_timestamp; /* indicate when the date and time of the compilation */
u32 flow_handler; /* FH read/write pointers, RX credit */
#endif
} __packed;
struct iwl_alive_resp { struct iwl_alive_resp {
u8 ucode_minor; u8 ucode_minor;
u8 ucode_major; u8 ucode_major;
......
...@@ -867,6 +867,19 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, ...@@ -867,6 +867,19 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv,
} }
#endif #endif
static void iwlagn_abort_notification_waits(struct iwl_priv *priv)
{
unsigned long flags;
struct iwl_notification_wait *wait_entry;
spin_lock_irqsave(&priv->_agn.notif_wait_lock, flags);
list_for_each_entry(wait_entry, &priv->_agn.notif_waits, list)
wait_entry->aborted = true;
spin_unlock_irqrestore(&priv->_agn.notif_wait_lock, flags);
wake_up_all(&priv->_agn.notif_waitq);
}
void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
{ {
unsigned int reload_msec; unsigned int reload_msec;
...@@ -878,6 +891,8 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) ...@@ -878,6 +891,8 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
/* Cancel currently queued command. */ /* Cancel currently queued command. */
clear_bit(STATUS_HCMD_ACTIVE, &priv->status); clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
iwlagn_abort_notification_waits(priv);
/* Keep the restart process from trying to send host /* Keep the restart process from trying to send host
* commands by clearing the ready bit */ * commands by clearing the ready bit */
clear_bit(STATUS_READY, &priv->status); clear_bit(STATUS_READY, &priv->status);
......
...@@ -226,10 +226,10 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, ...@@ -226,10 +226,10 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
/* default is to dump the entire data segment */ /* default is to dump the entire data segment */
if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
priv->dbgfs_sram_offset = 0x800000; priv->dbgfs_sram_offset = 0x800000;
if (priv->ucode_type == UCODE_INIT) if (priv->ucode_type == UCODE_SUBTYPE_INIT)
priv->dbgfs_sram_len = priv->ucode_init_data.len; priv->dbgfs_sram_len = priv->ucode_init.data.len;
else else
priv->dbgfs_sram_len = priv->ucode_data.len; priv->dbgfs_sram_len = priv->ucode_rt.data.len;
} }
len = priv->dbgfs_sram_len; len = priv->dbgfs_sram_len;
......
...@@ -479,6 +479,10 @@ struct fw_desc { ...@@ -479,6 +479,10 @@ struct fw_desc {
u32 len; /* bytes */ u32 len; /* bytes */
}; };
struct fw_img {
struct fw_desc code, data;
};
/* v1/v2 uCode file layout */ /* v1/v2 uCode file layout */
struct iwl_ucode_header { struct iwl_ucode_header {
__le32 ver; /* major/minor/API/serial */ __le32 ver; /* major/minor/API/serial */
...@@ -794,12 +798,6 @@ struct iwl_calib_result { ...@@ -794,12 +798,6 @@ struct iwl_calib_result {
size_t buf_len; size_t buf_len;
}; };
enum ucode_type {
UCODE_NONE = 0,
UCODE_INIT,
UCODE_RT
};
/* Sensitivity calib data */ /* Sensitivity calib data */
struct iwl_sensitivity_data { struct iwl_sensitivity_data {
u32 auto_corr_ofdm; u32 auto_corr_ofdm;
...@@ -1105,10 +1103,12 @@ struct iwl_force_reset { ...@@ -1105,10 +1103,12 @@ struct iwl_force_reset {
struct iwl_notification_wait { struct iwl_notification_wait {
struct list_head list; struct list_head list;
void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt); void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt,
void *data);
void *fn_data;
u8 cmd; u8 cmd;
bool triggered; bool triggered, aborted;
}; };
enum iwl_rxon_context_id { enum iwl_rxon_context_id {
...@@ -1270,11 +1270,10 @@ struct iwl_priv { ...@@ -1270,11 +1270,10 @@ struct iwl_priv {
int fw_index; /* firmware we're trying to load */ int fw_index; /* firmware we're trying to load */
u32 ucode_ver; /* version of ucode, copy of u32 ucode_ver; /* version of ucode, copy of
iwl_ucode.ver */ iwl_ucode.ver */
struct fw_desc ucode_code; /* runtime inst */ struct fw_img ucode_rt;
struct fw_desc ucode_data; /* runtime data original */ struct fw_img ucode_init;
struct fw_desc ucode_init; /* initialization inst */
struct fw_desc ucode_init_data; /* initialization data */ enum iwlagn_ucode_subtype ucode_type;
enum ucode_type ucode_type;
u8 ucode_write_complete; /* the image write is complete */ u8 ucode_write_complete; /* the image write is complete */
char firmware_name[25]; char firmware_name[25];
...@@ -1472,8 +1471,6 @@ struct iwl_priv { ...@@ -1472,8 +1471,6 @@ struct iwl_priv {
struct tasklet_struct irq_tasklet; struct tasklet_struct irq_tasklet;
struct delayed_work init_alive_start;
struct delayed_work alive_start;
struct delayed_work scan_check; struct delayed_work scan_check;
/* TX Power */ /* TX Power */
...@@ -1506,7 +1503,6 @@ struct iwl_priv { ...@@ -1506,7 +1503,6 @@ struct iwl_priv {
struct timer_list statistics_periodic; struct timer_list statistics_periodic;
struct timer_list ucode_trace; struct timer_list ucode_trace;
struct timer_list watchdog; struct timer_list watchdog;
bool hw_ready;
struct iwl_event_log event_log; struct iwl_event_log event_log;
......
...@@ -64,30 +64,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd) ...@@ -64,30 +64,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd)
return --index & (n_bd - 1); return --index & (n_bd - 1);
} }
/* TODO: Move fw_desc functions to iwl-pci.ko */
static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
struct fw_desc *desc)
{
if (desc->v_addr)
dma_free_coherent(&pci_dev->dev, desc->len,
desc->v_addr, desc->p_addr);
desc->v_addr = NULL;
desc->len = 0;
}
static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev,
struct fw_desc *desc)
{
if (!desc->len) {
desc->v_addr = NULL;
return -EINVAL;
}
desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
&desc->p_addr, GFP_KERNEL);
return (desc->v_addr != NULL) ? 0 : -ENOMEM;
}
/* /*
* we have 8 bits used like this: * we have 8 bits used like this:
* *
......
...@@ -242,20 +242,32 @@ void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) ...@@ -242,20 +242,32 @@ void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask)
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&priv->reg_lock, flags);
} }
u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr,
void *buf, int words)
{ {
unsigned long flags; unsigned long flags;
u32 value; int offs;
u32 *vals = buf;
spin_lock_irqsave(&priv->reg_lock, flags); spin_lock_irqsave(&priv->reg_lock, flags);
iwl_grab_nic_access(priv); iwl_grab_nic_access(priv);
iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr); iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr);
rmb(); rmb();
value = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
for (offs = 0; offs < words; offs++)
vals[offs] = iwl_read32(priv, HBUS_TARG_MEM_RDAT);
iwl_release_nic_access(priv); iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->reg_lock, flags); spin_unlock_irqrestore(&priv->reg_lock, flags);
}
u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr)
{
u32 value;
_iwl_read_targ_mem_words(priv, addr, &value, 1);
return value; return value;
} }
......
...@@ -76,6 +76,16 @@ void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, ...@@ -76,6 +76,16 @@ void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg,
u32 bits, u32 mask); u32 bits, u32 mask);
void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask); void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask);
void _iwl_read_targ_mem_words(struct iwl_priv *priv, u32 addr,
void *buf, int words);
#define iwl_read_targ_mem_words(priv, addr, buf, bufsize) \
do { \
BUILD_BUG_ON((bufsize) % sizeof(u32)); \
_iwl_read_targ_mem_words(priv, addr, buf, \
(bufsize) / sizeof(u32));\
} while (0)
u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr); u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr);
void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val); void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val);
#endif #endif
...@@ -225,55 +225,6 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) ...@@ -225,55 +225,6 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
* *
******************************************************************************/ ******************************************************************************/
static void iwl_rx_reply_alive(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_alive_resp *palive;
struct delayed_work *pwork;
palive = &pkt->u.alive_frame;
IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
"0x%01X 0x%01X\n",
palive->is_valid, palive->ver_type,
palive->ver_subtype);
priv->device_pointers.log_event_table =
le32_to_cpu(palive->log_event_table_ptr);
priv->device_pointers.error_event_table =
le32_to_cpu(palive->error_event_table_ptr);
if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
pwork = &priv->init_alive_start;
} else {
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
pwork = &priv->alive_start;
}
/* We delay the ALIVE response by 5ms to
* give the HW RF Kill time to activate... */
if (palive->is_valid == UCODE_VALID_OK)
queue_delayed_work(priv->workqueue, pwork,
msecs_to_jiffies(5));
else {
IWL_WARN(priv, "%s uCode did not respond OK.\n",
(palive->ver_subtype == INITIALIZE_SUBTYPE) ?
"init" : "runtime");
/*
* If fail to load init uCode,
* let's try to load the init uCode again.
* We should not get into this situation, but if it
* does happen, we should not move on and loading "runtime"
* without proper calibrate the device.
*/
if (palive->ver_subtype == INITIALIZE_SUBTYPE)
priv->ucode_type = UCODE_NONE;
queue_work(priv->workqueue, &priv->restart);
}
}
static void iwl_rx_reply_error(struct iwl_priv *priv, static void iwl_rx_reply_error(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb) struct iwl_rx_mem_buffer *rxb)
{ {
...@@ -1125,7 +1076,6 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) ...@@ -1125,7 +1076,6 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
handlers = priv->rx_handlers; handlers = priv->rx_handlers;
handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
handlers[REPLY_ERROR] = iwl_rx_reply_error; handlers[REPLY_ERROR] = iwl_rx_reply_error;
handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
handlers[SPECTRUM_MEASURE_NOTIFICATION] = iwl_rx_spectrum_measure_notif; handlers[SPECTRUM_MEASURE_NOTIFICATION] = iwl_rx_spectrum_measure_notif;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment