Merge branch 'wireless-next-2.6' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6
This commit is contained in:
commit
534f0e2928
|
@ -483,8 +483,6 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv)
|
|||
/* init calibration handlers */
|
||||
priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
|
||||
iwlagn_rx_calib_result;
|
||||
priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
|
||||
iwlagn_rx_calib_complete;
|
||||
priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
|
||||
|
||||
/* set up notification wait support */
|
||||
|
@ -2256,34 +2254,44 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
|
|||
/* notification wait support */
|
||||
void iwlagn_init_notification_wait(struct iwl_priv *priv,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
u8 cmd,
|
||||
void (*fn)(struct iwl_priv *priv,
|
||||
struct iwl_rx_packet *pkt),
|
||||
u8 cmd)
|
||||
struct iwl_rx_packet *pkt,
|
||||
void *data),
|
||||
void *fn_data)
|
||||
{
|
||||
wait_entry->fn = fn;
|
||||
wait_entry->fn_data = fn_data;
|
||||
wait_entry->cmd = cmd;
|
||||
wait_entry->triggered = false;
|
||||
wait_entry->aborted = false;
|
||||
|
||||
spin_lock_bh(&priv->_agn.notif_wait_lock);
|
||||
list_add(&wait_entry->list, &priv->_agn.notif_waits);
|
||||
spin_unlock_bh(&priv->_agn.notif_wait_lock);
|
||||
}
|
||||
|
||||
signed long iwlagn_wait_notification(struct iwl_priv *priv,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
unsigned long timeout)
|
||||
int iwlagn_wait_notification(struct iwl_priv *priv,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
unsigned long timeout)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wait_event_timeout(priv->_agn.notif_waitq,
|
||||
wait_entry->triggered,
|
||||
wait_entry->triggered || wait_entry->aborted,
|
||||
timeout);
|
||||
|
||||
spin_lock_bh(&priv->_agn.notif_wait_lock);
|
||||
list_del(&wait_entry->list);
|
||||
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,
|
||||
|
@ -2293,3 +2301,78 @@ void iwlagn_remove_notification(struct iwl_priv *priv,
|
|||
list_del(&wait_entry->list);
|
||||
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,
|
|||
u8 old_dev_type = send->dev_type;
|
||||
int ret;
|
||||
|
||||
iwlagn_init_notification_wait(priv, &disable_wait, NULL,
|
||||
REPLY_WIPAN_DEACTIVATION_COMPLETE);
|
||||
iwlagn_init_notification_wait(priv, &disable_wait,
|
||||
REPLY_WIPAN_DEACTIVATION_COMPLETE,
|
||||
NULL, NULL);
|
||||
|
||||
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
send->dev_type = RXON_DEV_TYPE_P2P;
|
||||
|
@ -72,13 +73,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
|
|||
IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
|
||||
iwlagn_remove_notification(priv, &disable_wait);
|
||||
} else {
|
||||
signed long wait_res;
|
||||
|
||||
wait_res = iwlagn_wait_notification(priv, &disable_wait, HZ);
|
||||
if (wait_res == 0) {
|
||||
ret = iwlagn_wait_notification(priv, &disable_wait, HZ);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Timed out waiting for PAN disable\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -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,
|
||||
struct fw_desc *inst_image,
|
||||
struct fw_desc *data_image)
|
||||
struct fw_img *image)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = iwlagn_load_section(priv, "INST", inst_image,
|
||||
ret = iwlagn_load_section(priv, "INST", &image->code,
|
||||
IWLAGN_RTC_INST_LOWER_BOUND);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return iwlagn_load_section(priv, "DATA", data_image,
|
||||
return iwlagn_load_section(priv, "DATA", &image->data,
|
||||
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
|
||||
*/
|
||||
|
@ -297,33 +269,9 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv,
|
|||
iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len);
|
||||
}
|
||||
|
||||
void iwlagn_rx_calib_complete(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwlagn_init_alive_start(struct iwl_priv *priv)
|
||||
{
|
||||
IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n");
|
||||
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;
|
||||
}
|
||||
int ret;
|
||||
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
|
@ -333,24 +281,25 @@ void iwlagn_init_alive_start(struct iwl_priv *priv)
|
|||
* no need to close the envlope since we are going
|
||||
* 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);
|
||||
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,
|
||||
* so prepare the value now.
|
||||
*/
|
||||
if (priv->cfg->need_temp_offset_calib)
|
||||
iwlagn_set_temperature_offset_calib(priv);
|
||||
return iwlagn_set_temperature_offset_calib(priv);
|
||||
|
||||
return;
|
||||
|
||||
restart:
|
||||
/* real restart (first load init_ucode) */
|
||||
queue_work(priv->workqueue, &priv->restart);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwlagn_send_wimax_coex(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");
|
||||
}
|
||||
|
||||
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;
|
||||
int ret;
|
||||
|
||||
env_cmd.action = action;
|
||||
env_cmd.type = type;
|
||||
if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV,
|
||||
sizeof(env_cmd), &env_cmd))
|
||||
ret = iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV,
|
||||
sizeof(env_cmd), &env_cmd);
|
||||
if (ret)
|
||||
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;
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
@ -604,15 +556,164 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
|
|||
* iwl_verify_ucode - determine which instruction image is in SRAM,
|
||||
* 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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
|||
if (w->cmd == pkt->hdr.cmd) {
|
||||
w->triggered = true;
|
||||
if (w->fn)
|
||||
w->fn(priv, pkt);
|
||||
w->fn(priv, pkt, w->fn_data);
|
||||
}
|
||||
}
|
||||
spin_unlock(&priv->_agn.notif_wait_lock);
|
||||
|
@ -846,14 +846,6 @@ static void iwl_rx_handle(struct iwl_priv *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 */
|
||||
static void iwl_irq_tasklet(struct iwl_priv *priv)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
|
||||
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
|
||||
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init);
|
||||
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
|
||||
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_nic_start(struct iwl_priv *priv)
|
||||
static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img)
|
||||
{
|
||||
/* Remove all resets to allow NIC to operate */
|
||||
iwl_write32(priv, CSR_RESET, 0);
|
||||
iwl_free_fw_desc(pci_dev, &img->code);
|
||||
iwl_free_fw_desc(pci_dev, &img->data);
|
||||
}
|
||||
|
||||
static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
if (!len) {
|
||||
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 {
|
||||
|
@ -1661,24 +1677,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
/* Runtime instructions and 2 copies of data:
|
||||
* 1) unmodified from disk
|
||||
* 2) backup cache for save/restore during power-downs */
|
||||
priv->ucode_code.len = pieces.inst_size;
|
||||
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
|
||||
|
||||
priv->ucode_data.len = pieces.data_size;
|
||||
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
|
||||
|
||||
if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr)
|
||||
if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code,
|
||||
pieces.inst, pieces.inst_size))
|
||||
goto err_pci_alloc;
|
||||
if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data,
|
||||
pieces.data, pieces.data_size))
|
||||
goto err_pci_alloc;
|
||||
|
||||
/* Initialization instructions and data */
|
||||
if (pieces.init_size && pieces.init_data_size) {
|
||||
priv->ucode_init.len = pieces.init_size;
|
||||
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
|
||||
|
||||
priv->ucode_init_data.len = pieces.init_data_size;
|
||||
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
|
||||
|
||||
if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
|
||||
if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code,
|
||||
pieces.init, pieces.init_size))
|
||||
goto err_pci_alloc;
|
||||
if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data,
|
||||
pieces.init_data, pieces.init_data_size))
|
||||
goto err_pci_alloc;
|
||||
}
|
||||
|
||||
|
@ -1715,39 +1727,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
else
|
||||
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
|
||||
* 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)
|
|||
u32 desc, time, count, base, data1;
|
||||
u32 blink1, blink2, ilink1, ilink2;
|
||||
u32 pc, hcmd;
|
||||
struct iwl_error_event_table table;
|
||||
|
||||
base = priv->device_pointers.error_event_table;
|
||||
if (priv->ucode_type == UCODE_INIT) {
|
||||
if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
|
||||
if (!base)
|
||||
base = priv->_agn.init_errlog_ptr;
|
||||
} else {
|
||||
|
@ -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)) {
|
||||
IWL_ERR(priv,
|
||||
"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;
|
||||
}
|
||||
|
||||
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) {
|
||||
IWL_ERR(priv, "Start IWL Error Log Dump:\n");
|
||||
|
@ -1903,18 +1887,18 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
|
|||
priv->status, count);
|
||||
}
|
||||
|
||||
desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
|
||||
desc = table.error_id;
|
||||
priv->isr_stats.err_code = desc;
|
||||
pc = iwl_read_targ_mem(priv, base + 2 * 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));
|
||||
hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32));
|
||||
pc = table.pc;
|
||||
blink1 = table.blink1;
|
||||
blink2 = table.blink2;
|
||||
ilink1 = table.ilink1;
|
||||
ilink2 = table.ilink2;
|
||||
data1 = table.data1;
|
||||
data2 = table.data2;
|
||||
line = table.line;
|
||||
time = table.tsf_low;
|
||||
hcmd = table.hcmd;
|
||||
|
||||
trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line,
|
||||
blink1, blink2, ilink1, ilink2);
|
||||
|
@ -1949,7 +1933,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
|||
return pos;
|
||||
|
||||
base = priv->device_pointers.log_event_table;
|
||||
if (priv->ucode_type == UCODE_INIT) {
|
||||
if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
|
||||
if (!base)
|
||||
base = priv->_agn.init_evtlog_ptr;
|
||||
} else {
|
||||
|
@ -2062,7 +2046,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
|
|||
size_t bufsz = 0;
|
||||
|
||||
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;
|
||||
if (!base)
|
||||
base = priv->_agn.init_evtlog_ptr;
|
||||
|
@ -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)) {
|
||||
IWL_ERR(priv,
|
||||
"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;
|
||||
}
|
||||
|
||||
|
@ -2222,31 +2208,15 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
|
|||
* from protocol/runtime uCode (initialization uCode's
|
||||
* 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;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
iwl_reset_ict(priv);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
/* After the ALIVE response, we can send host commands to the uCode */
|
||||
set_bit(STATUS_ALIVE, &priv->status);
|
||||
|
||||
|
@ -2254,7 +2224,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
|||
iwl_setup_watchdog(priv);
|
||||
|
||||
if (iwl_is_rfkill(priv))
|
||||
return;
|
||||
return -ERFKILL;
|
||||
|
||||
/* download priority table before any calibration request */
|
||||
if (priv->cfg->bt_params &&
|
||||
|
@ -2268,10 +2238,14 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
|||
iwlagn_send_prio_tbl(priv);
|
||||
|
||||
/* FIXME: w/a to force change uCode BT state machine */
|
||||
iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
||||
iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
||||
ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
if (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)
|
|||
set_bit(STATUS_READY, &priv->status);
|
||||
|
||||
/* 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 */
|
||||
iwl_rf_kill_ct_config(priv);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
|
||||
iwl_power_update_mode(priv, true);
|
||||
IWL_DEBUG_INFO(priv, "Updated power mode\n");
|
||||
|
||||
|
||||
return;
|
||||
|
||||
restart:
|
||||
queue_work(priv->workqueue, &priv->restart);
|
||||
return iwl_power_update_mode(priv, true);
|
||||
}
|
||||
|
||||
static void iwl_cancel_deferred_work(struct iwl_priv *priv);
|
||||
|
||||
static void __iwl_down(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
int exit_pending;
|
||||
|
||||
IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
|
||||
|
@ -2367,32 +2334,10 @@ static void __iwl_down(struct iwl_priv *priv)
|
|||
if (!exit_pending)
|
||||
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)
|
||||
ieee80211_stop_queues(priv->hw);
|
||||
|
||||
/* If we have not previously called iwl_init() then
|
||||
* 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. */
|
||||
/* Clear out all status bits but a few that are stable across reset */
|
||||
priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
|
||||
STATUS_RF_KILL_HW |
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
|
||||
|
@ -2402,23 +2347,8 @@ static void __iwl_down(struct iwl_priv *priv)
|
|||
test_bit(STATUS_EXIT_PENDING, &priv->status) <<
|
||||
STATUS_EXIT_PENDING;
|
||||
|
||||
/* device going down, Stop using ICT table */
|
||||
iwl_disable_ict(priv);
|
||||
iwlagn_stop_device(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);
|
||||
priv->beacon_skb = NULL;
|
||||
|
||||
|
@ -2437,9 +2367,10 @@ static void iwl_down(struct iwl_priv *priv)
|
|||
|
||||
#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)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
|
||||
|
@ -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,
|
||||
HW_READY_TIMEOUT);
|
||||
if (ret != -ETIMEDOUT)
|
||||
priv->hw_ready = true;
|
||||
else
|
||||
priv->hw_ready = false;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "hardware %s\n",
|
||||
(priv->hw_ready == 1) ? "ready" : "not ready");
|
||||
IWL_DEBUG_INFO(priv, "hardware%s ready\n", ret < 0 ? " not" : "");
|
||||
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");
|
||||
|
||||
ret = iwl_set_hw_ready(priv);
|
||||
if (priv->hw_ready)
|
||||
return ret;
|
||||
if (ret >= 0)
|
||||
return 0;
|
||||
|
||||
/* If HW is not ready, prepare the conditions to check again */
|
||||
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
|
@ -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, 150000);
|
||||
|
||||
/* HW should be ready by now, check again. */
|
||||
if (ret != -ETIMEDOUT)
|
||||
iwl_set_hw_ready(priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* HW should be ready by now, check again. */
|
||||
ret = iwl_set_hw_ready(priv);
|
||||
if (ret >= 0)
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2489,9 +2419,10 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv)
|
|||
static int __iwl_up(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
|
||||
IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
|
||||
return -EIO;
|
||||
|
@ -2505,77 +2436,33 @@ static int __iwl_up(struct iwl_priv *priv)
|
|||
}
|
||||
}
|
||||
|
||||
iwl_prepare_card_hw(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);
|
||||
ret = iwlagn_run_init_ucode(priv);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Unable to init nic\n");
|
||||
return ret;
|
||||
IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
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) {
|
||||
IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n",
|
||||
ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* start card; "initialize" will load runtime ucode */
|
||||
iwl_nic_start(priv);
|
||||
|
||||
IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
|
||||
|
||||
return 0;
|
||||
ret = iwlagn_load_ucode_wait_alive(priv,
|
||||
&priv->ucode_rt,
|
||||
UCODE_SUBTYPE_REGULAR,
|
||||
UCODE_SUBTYPE_REGULAR_NEW);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = iwl_alive_start(priv);
|
||||
if (ret)
|
||||
goto error;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
set_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
__iwl_down(priv);
|
||||
clear_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
|
||||
/* tried to restart and config the device for as long as our
|
||||
* patience could withstand */
|
||||
IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
|
||||
return -EIO;
|
||||
IWL_ERR(priv, "Unable to initialize device.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv,
|
||||
|
@ -2683,14 +2537,7 @@ static void iwl_bg_restart(struct work_struct *data)
|
|||
iwl_cancel_deferred_work(priv);
|
||||
ieee80211_restart_hw(priv->hw);
|
||||
} else {
|
||||
iwl_down(priv);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
__iwl_up(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2801,8 +2648,6 @@ unlock:
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define UCODE_READY_TIMEOUT (4 * HZ)
|
||||
|
||||
/*
|
||||
* Not a mac80211 entry point function, but it fits in with all the
|
||||
* other mac80211 functions grouped here.
|
||||
|
@ -2895,31 +2740,17 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw)
|
|||
mutex_lock(&priv->mutex);
|
||||
ret = __iwl_up(priv);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (iwl_is_rfkill(priv))
|
||||
goto out;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Start UP work done.\n");
|
||||
|
||||
/* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
|
||||
* mac80211 will not be run successfully. */
|
||||
ret = wait_event_interruptible_timeout(priv->wait_command_queue,
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* Now we should be done, and the READY bit should be set. */
|
||||
if (WARN_ON(!test_bit(STATUS_READY, &priv->status)))
|
||||
ret = -EIO;
|
||||
|
||||
iwlagn_led_enable(priv);
|
||||
|
||||
out:
|
||||
priv->is_open = 1;
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
return 0;
|
||||
|
@ -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->bt_full_concurrency, iwl_bg_bt_full_concurrency);
|
||||
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);
|
||||
|
||||
iwl_setup_scan_deferred_work(priv);
|
||||
|
@ -3536,8 +3365,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
|
|||
if (priv->cfg->ops->lib->cancel_deferred_work)
|
||||
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->beacon_update);
|
||||
|
||||
|
@ -3772,6 +3599,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
priv = hw->priv;
|
||||
/* At this point both hw and priv are allocated. */
|
||||
|
||||
priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED;
|
||||
|
||||
/*
|
||||
* The default context is always valid,
|
||||
* 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)
|
|||
* PCI Tx retries from interfering with C3 CPU state */
|
||||
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
|
||||
|
||||
iwl_prepare_card_hw(priv);
|
||||
if (!priv->hw_ready) {
|
||||
if (iwl_prepare_card_hw(priv)) {
|
||||
IWL_WARN(priv, "Failed, HW not ready\n");
|
||||
goto out_iounmap;
|
||||
}
|
||||
|
@ -4069,17 +3897,9 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
|
|||
if (priv->mac80211_registered) {
|
||||
ieee80211_unregister_hw(priv->hw);
|
||||
priv->mac80211_registered = 0;
|
||||
} else {
|
||||
iwl_down(priv);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/* Reset to low power before unloading driver. */
|
||||
iwl_apm_stop(priv);
|
||||
|
||||
iwl_tt_exit(priv);
|
||||
|
|
|
@ -120,6 +120,19 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv);
|
|||
void iwl_free_isr_ict(struct iwl_priv *priv);
|
||||
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 */
|
||||
void iwlagn_set_wr_ptrs(struct iwl_priv *priv,
|
||||
int txq_id, u32 index);
|
||||
|
@ -145,16 +158,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
|||
u32 changes);
|
||||
|
||||
/* uCode */
|
||||
int iwlagn_load_ucode(struct iwl_priv *priv);
|
||||
void iwlagn_rx_calib_result(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwlagn_rx_calib_complete(struct iwl_priv *priv,
|
||||
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);
|
||||
int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
|
||||
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 */
|
||||
void iwl_check_abort_status(struct iwl_priv *priv,
|
||||
|
@ -325,10 +336,12 @@ void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
|
|||
void __acquires(wait_entry)
|
||||
iwlagn_init_notification_wait(struct iwl_priv *priv,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
u8 cmd,
|
||||
void (*fn)(struct iwl_priv *priv,
|
||||
struct iwl_rx_packet *pkt),
|
||||
u8 cmd);
|
||||
signed long __releases(wait_entry)
|
||||
struct iwl_rx_packet *pkt,
|
||||
void *data),
|
||||
void *fn_data);
|
||||
int __must_check __releases(wait_entry)
|
||||
iwlagn_wait_notification(struct iwl_priv *priv,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
unsigned long timeout);
|
||||
|
|
|
@ -386,7 +386,18 @@ struct iwl_tx_ant_config_cmd {
|
|||
*****************************************************************************/
|
||||
|
||||
#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)
|
||||
|
@ -422,49 +433,61 @@ struct iwl_tx_ant_config_cmd {
|
|||
*
|
||||
* 2) error_event_table_ptr indicates base of the error log. This contains
|
||||
* information about any uCode error that occurs. For agn, the format
|
||||
* of the error log is:
|
||||
*
|
||||
* __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;
|
||||
* of the error log is defined by struct iwl_error_event_table.
|
||||
*
|
||||
* The Linux driver can print both logs to the system log when a uCode error
|
||||
* 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 {
|
||||
u8 ucode_minor;
|
||||
u8 ucode_major;
|
||||
|
|
|
@ -867,6 +867,19 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
|||
}
|
||||
#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)
|
||||
{
|
||||
unsigned int reload_msec;
|
||||
|
@ -878,6 +891,8 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
|||
/* Cancel currently queued command. */
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
|
||||
|
||||
iwlagn_abort_notification_waits(priv);
|
||||
|
||||
/* Keep the restart process from trying to send host
|
||||
* commands by clearing the ready bit */
|
||||
clear_bit(STATUS_READY, &priv->status);
|
||||
|
|
|
@ -226,10 +226,10 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
|
|||
/* default is to dump the entire data segment */
|
||||
if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
|
||||
priv->dbgfs_sram_offset = 0x800000;
|
||||
if (priv->ucode_type == UCODE_INIT)
|
||||
priv->dbgfs_sram_len = priv->ucode_init_data.len;
|
||||
if (priv->ucode_type == UCODE_SUBTYPE_INIT)
|
||||
priv->dbgfs_sram_len = priv->ucode_init.data.len;
|
||||
else
|
||||
priv->dbgfs_sram_len = priv->ucode_data.len;
|
||||
priv->dbgfs_sram_len = priv->ucode_rt.data.len;
|
||||
}
|
||||
len = priv->dbgfs_sram_len;
|
||||
|
||||
|
|
|
@ -479,6 +479,10 @@ struct fw_desc {
|
|||
u32 len; /* bytes */
|
||||
};
|
||||
|
||||
struct fw_img {
|
||||
struct fw_desc code, data;
|
||||
};
|
||||
|
||||
/* v1/v2 uCode file layout */
|
||||
struct iwl_ucode_header {
|
||||
__le32 ver; /* major/minor/API/serial */
|
||||
|
@ -794,12 +798,6 @@ struct iwl_calib_result {
|
|||
size_t buf_len;
|
||||
};
|
||||
|
||||
enum ucode_type {
|
||||
UCODE_NONE = 0,
|
||||
UCODE_INIT,
|
||||
UCODE_RT
|
||||
};
|
||||
|
||||
/* Sensitivity calib data */
|
||||
struct iwl_sensitivity_data {
|
||||
u32 auto_corr_ofdm;
|
||||
|
@ -1105,10 +1103,12 @@ struct iwl_force_reset {
|
|||
struct iwl_notification_wait {
|
||||
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;
|
||||
bool triggered;
|
||||
bool triggered, aborted;
|
||||
};
|
||||
|
||||
enum iwl_rxon_context_id {
|
||||
|
@ -1270,11 +1270,10 @@ struct iwl_priv {
|
|||
int fw_index; /* firmware we're trying to load */
|
||||
u32 ucode_ver; /* version of ucode, copy of
|
||||
iwl_ucode.ver */
|
||||
struct fw_desc ucode_code; /* runtime inst */
|
||||
struct fw_desc ucode_data; /* runtime data original */
|
||||
struct fw_desc ucode_init; /* initialization inst */
|
||||
struct fw_desc ucode_init_data; /* initialization data */
|
||||
enum ucode_type ucode_type;
|
||||
struct fw_img ucode_rt;
|
||||
struct fw_img ucode_init;
|
||||
|
||||
enum iwlagn_ucode_subtype ucode_type;
|
||||
u8 ucode_write_complete; /* the image write is complete */
|
||||
char firmware_name[25];
|
||||
|
||||
|
@ -1472,8 +1471,6 @@ struct iwl_priv {
|
|||
|
||||
struct tasklet_struct irq_tasklet;
|
||||
|
||||
struct delayed_work init_alive_start;
|
||||
struct delayed_work alive_start;
|
||||
struct delayed_work scan_check;
|
||||
|
||||
/* TX Power */
|
||||
|
@ -1506,7 +1503,6 @@ struct iwl_priv {
|
|||
struct timer_list statistics_periodic;
|
||||
struct timer_list ucode_trace;
|
||||
struct timer_list watchdog;
|
||||
bool hw_ready;
|
||||
|
||||
struct iwl_event_log event_log;
|
||||
|
||||
|
|
|
@ -64,30 +64,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd)
|
|||
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:
|
||||
*
|
||||
|
|
|
@ -242,20 +242,32 @@ void iwl_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask)
|
|||
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;
|
||||
u32 value;
|
||||
int offs;
|
||||
u32 *vals = buf;
|
||||
|
||||
spin_lock_irqsave(&priv->reg_lock, flags);
|
||||
iwl_grab_nic_access(priv);
|
||||
|
||||
iwl_write32(priv, HBUS_TARG_MEM_RADDR, addr);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,16 @@ void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg,
|
|||
u32 bits, 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);
|
||||
void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val);
|
||||
#endif
|
||||
|
|
|
@ -225,55 +225,6 @@ err_bd:
|
|||
*
|
||||
******************************************************************************/
|
||||
|
||||
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,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
|
@ -1125,7 +1076,6 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
|
|||
|
||||
handlers = priv->rx_handlers;
|
||||
|
||||
handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
|
||||
handlers[REPLY_ERROR] = iwl_rx_reply_error;
|
||||
handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
|
||||
handlers[SPECTRUM_MEASURE_NOTIFICATION] = iwl_rx_spectrum_measure_notif;
|
||||
|
|
Loading…
Reference in New Issue