diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-21 00:43:21 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-21 00:43:21 +0400 |
commit | 06f4e926d256d902dd9a53dcb400fd74974ce087 (patch) | |
tree | 0b438b67f5f0eff6fd617bc497a9dace6164a488 /drivers/net/wireless/iwlwifi/iwl-eeprom.c | |
parent | 8e7bfcbab3825d1b404d615cb1b54f44ff81f981 (diff) | |
parent | d93515611bbc70c2fe4db232e5feb448ed8e4cc9 (diff) | |
download | linux-06f4e926d256d902dd9a53dcb400fd74974ce087.tar.xz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1446 commits)
macvlan: fix panic if lowerdev in a bond
tg3: Add braces around 5906 workaround.
tg3: Fix NETIF_F_LOOPBACK error
macvlan: remove one synchronize_rcu() call
networking: NET_CLS_ROUTE4 depends on INET
irda: Fix error propagation in ircomm_lmp_connect_response()
irda: Kill set but unused variable 'bytes' in irlan_check_command_param()
irda: Kill set but unused variable 'clen' in ircomm_connect_indication()
rxrpc: Fix set but unused variable 'usage' in rxrpc_get_transport()
be2net: Kill set but unused variable 'req' in lancer_fw_download()
irda: Kill set but unused vars 'saddr' and 'daddr' in irlan_provider_connect_indication()
atl1c: atl1c_resume() is only used when CONFIG_PM_SLEEP is defined.
rxrpc: Fix set but unused variable 'usage' in rxrpc_get_peer().
rxrpc: Kill set but unused variable 'local' in rxrpc_UDP_error_handler()
rxrpc: Kill set but unused variable 'sp' in rxrpc_process_connection()
rxrpc: Kill set but unused variable 'sp' in rxrpc_rotate_tx_window()
pkt_sched: Kill set but unused variable 'protocol' in tc_classify()
isdn: capi: Use pr_debug() instead of ifdefs.
tg3: Update version to 3.119
tg3: Apply rx_discards fix to 5719/5720
...
Fix up trivial conflicts in arch/x86/Kconfig and net/mac80211/agg-tx.c
as per Davem.
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-eeprom.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-eeprom.c | 106 |
1 files changed, 65 insertions, 41 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 833194a2c639..c8397962632c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -142,6 +142,45 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ * ******************************************************************************/ +/* + * The device's EEPROM semaphore prevents conflicts between driver and uCode + * when accessing the EEPROM; each access is a series of pulses to/from the + * EEPROM chip, not a single event, so even reads could conflict if they + * weren't arbitrated by the semaphore. + */ +static int iwl_eeprom_acquire_semaphore(struct iwl_priv *priv) +{ + u16 count; + int ret; + + for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { + /* Request semaphore */ + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); + + /* See if we got it */ + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, + EEPROM_SEM_TIMEOUT); + if (ret >= 0) { + IWL_DEBUG_EEPROM(priv, + "Acquired semaphore after %d tries.\n", + count+1); + return ret; + } + } + + return ret; +} + +static void iwl_eeprom_release_semaphore(struct iwl_priv *priv) +{ + iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); + +} + static int iwl_eeprom_verify_signature(struct iwl_priv *priv) { u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; @@ -188,18 +227,16 @@ static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) CSR_OTP_GP_REG_OTP_ACCESS_MODE); } -static int iwlcore_get_nvm_type(struct iwl_priv *priv) +static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev) { u32 otpgp; int nvm_type; /* OTP only valid for CP/PP and after */ - switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { + switch (hw_rev & CSR_HW_REV_TYPE_MSK) { case CSR_HW_REV_TYPE_NONE: IWL_ERR(priv, "Unknown hardware type\n"); return -ENOENT; - case CSR_HW_REV_TYPE_3945: - case CSR_HW_REV_TYPE_4965: case CSR_HW_REV_TYPE_5300: case CSR_HW_REV_TYPE_5350: case CSR_HW_REV_TYPE_5100: @@ -217,26 +254,20 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv) return nvm_type; } -const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) -{ - BUG_ON(offset >= priv->cfg->base_params->eeprom_size); - return &priv->eeprom[offset]; -} - static int iwl_init_otp_access(struct iwl_priv *priv) { int ret; /* Enable 40MHz radio clock */ - _iwl_write32(priv, CSR_GP_CNTRL, - _iwl_read32(priv, CSR_GP_CNTRL) | - CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + iwl_write32(priv, CSR_GP_CNTRL, + iwl_read32(priv, CSR_GP_CNTRL) | + CSR_GP_CNTRL_REG_FLAG_INIT_DONE); /* wait for clock to be ready */ ret = iwl_poll_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, - 25000); + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + 25000); if (ret < 0) IWL_ERR(priv, "Time out access OTP\n"); else { @@ -263,17 +294,17 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_dat u32 r; u32 otpgp; - _iwl_write32(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); + iwl_write32(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); ret = iwl_poll_bit(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_READ_VALID_MSK, - CSR_EEPROM_REG_READ_VALID_MSK, - IWL_EEPROM_ACCESS_TIMEOUT); + CSR_EEPROM_REG_READ_VALID_MSK, + CSR_EEPROM_REG_READ_VALID_MSK, + IWL_EEPROM_ACCESS_TIMEOUT); if (ret < 0) { IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); return ret; } - r = _iwl_read_direct32(priv, CSR_EEPROM_REG); + r = iwl_read32(priv, CSR_EEPROM_REG); /* check for ECC errors: */ otpgp = iwl_read32(priv, CSR_OTP_GP_REG); if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { @@ -396,7 +427,7 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) * * NOTE: This routine uses the non-debug IO access functions. */ -int iwl_eeprom_init(struct iwl_priv *priv) +int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev) { __le16 *e; u32 gp = iwl_read32(priv, CSR_EEPROM_GP); @@ -406,7 +437,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) u16 validblockaddr = 0; u16 cache_addr = 0; - priv->nvm_device_type = iwlcore_get_nvm_type(priv); + priv->nvm_device_type = iwlcore_get_nvm_type(priv, hw_rev); if (priv->nvm_device_type == -ENOENT) return -ENOENT; /* allocate eeprom */ @@ -429,7 +460,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) } /* Make sure driver (instead of uCode) is allowed to read EEPROM */ - ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv); + ret = iwl_eeprom_acquire_semaphore(priv); if (ret < 0) { IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); ret = -ENOENT; @@ -444,9 +475,9 @@ int iwl_eeprom_init(struct iwl_priv *priv) ret = -ENOENT; goto done; } - _iwl_write32(priv, CSR_EEPROM_GP, - iwl_read32(priv, CSR_EEPROM_GP) & - ~CSR_EEPROM_GP_IF_OWNER_MSK); + iwl_write32(priv, CSR_EEPROM_GP, + iwl_read32(priv, CSR_EEPROM_GP) & + ~CSR_EEPROM_GP_IF_OWNER_MSK); iwl_set_bit(priv, CSR_OTP_GP_REG, CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | @@ -473,8 +504,8 @@ int iwl_eeprom_init(struct iwl_priv *priv) for (addr = 0; addr < sz; addr += sizeof(u16)) { u32 r; - _iwl_write32(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); + iwl_write32(priv, CSR_EEPROM_REG, + CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); ret = iwl_poll_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_READ_VALID_MSK, @@ -484,7 +515,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); goto done; } - r = _iwl_read_direct32(priv, CSR_EEPROM_REG); + r = iwl_read32(priv, CSR_EEPROM_REG); e[addr / 2] = cpu_to_le16(r >> 16); } } @@ -496,7 +527,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) ret = 0; done: - priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); + iwl_eeprom_release_semaphore(priv); err: if (ret) @@ -719,13 +750,6 @@ int iwl_init_channel_map(struct iwl_priv *priv) flags & EEPROM_CHANNEL_RADAR)) ? "" : "not "); - /* Set the tx_power_user_lmt to the highest power - * supported by any channel */ - if (eeprom_ch_info[ch].max_power_avg > - priv->tx_power_user_lmt) - priv->tx_power_user_lmt = - eeprom_ch_info[ch].max_power_avg; - ch_info++; } } |