rpms/kernel/F-12 linux-2.6-iwlwifi-fix-unloading-driver-while-scanning.patch, NONE, 1.1 linux-2.6-iwlwifi-remove-deprecated-6000-series-adapters.patch, NONE, 1.1 linux-2.6-iwlwifi-traverse-linklist-to-find-the-valid-OTP-block.patch, NONE, 1.1 kernel.spec, 1.1810, 1.1811

John W. Linville linville at fedoraproject.org
Thu Sep 17 14:49:58 UTC 2009


Author: linville

Update of /cvs/pkgs/rpms/kernel/F-12
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv6530

Modified Files:
	kernel.spec 
Added Files:
	linux-2.6-iwlwifi-fix-unloading-driver-while-scanning.patch 
	linux-2.6-iwlwifi-remove-deprecated-6000-series-adapters.patch 
	linux-2.6-iwlwifi-traverse-linklist-to-find-the-valid-OTP-block.patch 
Log Message:
Add a few more iwl1000 support patches. Remove support for deprecated iwl6000 parts.

linux-2.6-iwlwifi-fix-unloading-driver-while-scanning.patch:
 iwl-agn.c  |    2 +-
 iwl-scan.c |    3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

--- NEW FILE linux-2.6-iwlwifi-fix-unloading-driver-while-scanning.patch ---
commit 5bddf54962bf68002816df710348ba197d6391bb
Author: Wey-Yi Guy <wey-yi.w.guy at intel.com>
Date:   Fri Aug 21 13:34:25 2009 -0700

    iwlwifi: fix unloading driver while scanning
    
    If NetworkManager is busy scanning when user
    tries to unload the module, the driver can not be unloaded
    because HW still scanning.
    
    Make sure driver sends abort scan host command to uCode if it
    is in the middle of scanning during driver unload.
    
    Signed-off-by: Wey-Yi Guy <wey-yi.w.guy at intel.com>
    Signed-off-by: Reinette Chatre <reinette.chatre at intel.com>
    Signed-off-by: John W. Linville <linville at tuxdriver.com>

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 533b393..00457bf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2155,7 +2155,7 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
 
 	priv->is_open = 0;
 
-	if (iwl_is_ready_rf(priv)) {
+	if (iwl_is_ready_rf(priv) || test_bit(STATUS_SCAN_HW, &priv->status)) {
 		/* stop mac, cancel any scan request and clear
 		 * RXON_FILTER_ASSOC_MSK BIT
 		 */
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index c4c916d..4f3a108 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -796,7 +796,8 @@ void iwl_bg_abort_scan(struct work_struct *work)
 {
 	struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
 
-	if (!iwl_is_ready(priv))
+	if (!test_bit(STATUS_READY, &priv->status) ||
+	    !test_bit(STATUS_GEO_CONFIGURED, &priv->status))
 		return;
 
 	mutex_lock(&priv->mutex);

linux-2.6-iwlwifi-remove-deprecated-6000-series-adapters.patch:
 iwl-6000.c |   18 ------------------
 iwl-agn.c  |    5 -----
 iwl-dev.h  |    1 -
 3 files changed, 24 deletions(-)

--- NEW FILE linux-2.6-iwlwifi-remove-deprecated-6000-series-adapters.patch ---
commit a11c4d000b84f7f49ebefc018c24bbfa3c9c0f3b
Author: Wey-Yi Guy <wey-yi.w.guy at intel.com>
Date:   Fri Jul 31 14:28:08 2009 -0700

    iwlwifi: remove deprecated 6000 series adapters
    
    Remove the support for deprecated devices. These devices are
    engineering samples and no longer supported by the uCode.
    
    Signed-off-by: Wey-Yi Guy <wey-yi.w.guy at intel.com>
    Signed-off-by: Reinette Chatre <reinette.chatre at intel.com>
    Signed-off-by: John W. Linville <linville at tuxdriver.com>

diff -up linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c.orig linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c
--- linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c.orig	2009-09-17 10:35:39.000000000 -0400
+++ linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c	2009-09-17 10:38:22.000000000 -0400
@@ -75,24 +75,6 @@ static struct iwl_ops iwl6000_ops = {
 	.utils = &iwl6000_hcmd_utils,
 };
 
-struct iwl_cfg iwl6000_2ag_cfg = {
-	.name = "6000 Series 2x2 AG",
-	.fw_name_pre = IWL6000_FW_PRE,
-	.ucode_api_max = IWL6000_UCODE_API_MAX,
-	.ucode_api_min = IWL6000_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G,
-	.ops = &iwl6000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
-	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
-	.mod_params = &iwl50_mod_params,
-	.valid_tx_ant = ANT_BC,
-	.valid_rx_ant = ANT_BC,
-	.need_pll_cfg = false,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.shadow_ram_support = true,
-};
-
 struct iwl_cfg iwl6000_2agn_cfg = {
 	.name = "6000 Series 2x2 AGN",
 	.fw_name_pre = IWL6000_FW_PRE,
diff -up linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-agn.c.orig linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-agn.c
--- linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-agn.c.orig	2009-09-17 10:35:39.000000000 -0400
+++ linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-agn.c	2009-09-17 10:37:46.000000000 -0400
@@ -3172,15 +3172,10 @@ static struct pci_device_id iwl_hw_card_
 	{IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)},
 	{IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
 /* 6000/6050 Series */
-	{IWL_PCI_DEVICE(0x0082, 0x1102, iwl6000_2ag_cfg)},
-	{IWL_PCI_DEVICE(0x0085, 0x1112, iwl6000_2ag_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1122, iwl6000_2ag_cfg)},
 	{IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0082, PCI_ANY_ID, iwl6000_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0085, PCI_ANY_ID, iwl6000_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)},
diff -up linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h
--- linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig	2009-09-17 10:35:39.000000000 -0400
+++ linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h	2009-09-17 10:38:00.000000000 -0400
@@ -56,7 +56,6 @@ extern struct iwl_cfg iwl5350_agn_cfg;
 extern struct iwl_cfg iwl5100_bg_cfg;
 extern struct iwl_cfg iwl5100_abg_cfg;
 extern struct iwl_cfg iwl5150_agn_cfg;
-extern struct iwl_cfg iwl6000_2ag_cfg;
 extern struct iwl_cfg iwl6000_2agn_cfg;
 extern struct iwl_cfg iwl6000_3agn_cfg;
 extern struct iwl_cfg iwl6050_2agn_cfg;

linux-2.6-iwlwifi-traverse-linklist-to-find-the-valid-OTP-block.patch:
 iwl-1000.c   |    4 -
 iwl-6000.c   |   18 ++++-
 iwl-core.h   |    4 +
 iwl-dev.h    |   12 +++
 iwl-eeprom.c |  185 +++++++++++++++++++++++++++++++++++++++++++++++------------
 iwl-eeprom.h |   10 ++-
 6 files changed, 191 insertions(+), 42 deletions(-)

--- NEW FILE linux-2.6-iwlwifi-traverse-linklist-to-find-the-valid-OTP-block.patch ---
Backport of the following upstream commit...

commit 415e49936b4b29b34c2fb561eeab867d41fc43a6
Author: Wey-Yi Guy <wey-yi.w.guy at intel.com>
Date:   Thu Aug 13 13:30:54 2009 -0700

    iwlwifi: traverse linklist to find the valid OTP block
    
    For devices using OTP memory, EEPROM image can start from
    any one of the OTP blocks. If shadow RAM is disabled, we need to
    traverse link list to find the last valid block, then start the EEPROM
    image reading.
    
    If OTP is not full, the valid block is the block _before_ the last block
    on the link list; the last block on the link list is the empty block
    ready for next OTP refresh/update.
    
    If OTP is full, then the last block is the valid block to be used for
    configure the device.
    
    Signed-off-by: Wey-Yi Guy <wey-yi.w.guy at intel.com>
    Signed-off-by: Reinette Chatre <reinette.chatre at intel.com>
    Signed-off-by: John W. Linville <linville at tuxdriver.com>

diff -up linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-1000.c.orig linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-1000.c
--- linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-1000.c.orig	2009-09-17 09:22:27.000000000 -0400
+++ linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-1000.c	2009-09-17 09:26:23.000000000 -0400
@@ -62,12 +62,14 @@ struct iwl_cfg iwl1000_bgn_cfg = {
 	.ucode_api_min = IWL1000_UCODE_API_MIN,
 	.sku = IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl5000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
 	.valid_tx_ant = ANT_A,
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = true,
+	.max_ll_items = OTP_MAX_LL_ITEMS_1000,
+	.shadow_ram_support = false,
 };
 
diff -up linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c.orig linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c
--- linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c.orig	2009-09-17 09:22:27.000000000 -0400
+++ linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-6000.c	2009-09-17 09:55:14.000000000 -0400
@@ -89,6 +89,8 @@ struct iwl_cfg iwl6000_2ag_cfg = {
 	.valid_tx_ant = ANT_BC,
 	.valid_rx_ant = ANT_BC,
 	.need_pll_cfg = false,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
 };
 
 struct iwl_cfg iwl6000_2agn_cfg = {
@@ -98,13 +100,15 @@ struct iwl_cfg iwl6000_2agn_cfg = {
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl6000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
 	.valid_tx_ant = ANT_AB,
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = false,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
 };
 
 struct iwl_cfg iwl6050_2agn_cfg = {
@@ -114,13 +118,15 @@ struct iwl_cfg iwl6050_2agn_cfg = {
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl6000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
 	.valid_tx_ant = ANT_AB,
 	.valid_rx_ant = ANT_AB,
 	.need_pll_cfg = false,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
 };
 
 struct iwl_cfg iwl6000_3agn_cfg = {
@@ -130,13 +136,15 @@ struct iwl_cfg iwl6000_3agn_cfg = {
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl6000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
 	.valid_tx_ant = ANT_ABC,
 	.valid_rx_ant = ANT_ABC,
 	.need_pll_cfg = false,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
 };
 
 struct iwl_cfg iwl6050_3agn_cfg = {
@@ -146,13 +154,15 @@ struct iwl_cfg iwl6050_3agn_cfg = {
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
 	.ops = &iwl6000_ops,
-	.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
 	.mod_params = &iwl50_mod_params,
 	.valid_tx_ant = ANT_ABC,
 	.valid_rx_ant = ANT_ABC,
 	.need_pll_cfg = false,
+	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
+	.shadow_ram_support = true,
 };
 
 MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
diff -up linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-core.h.orig linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-core.h
--- linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-core.h.orig	2009-09-17 09:22:27.000000000 -0400
+++ linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-core.h	2009-09-17 09:35:58.000000000 -0400
@@ -207,6 +207,8 @@ struct iwl_mod_params {
  * 	filename is constructed as fw_name_pre<api>.ucode.
  * @ucode_api_max: Highest version of uCode API supported by driver.
  * @ucode_api_min: Lowest version of uCode API supported by driver.
+ * @max_ll_items: max number of OTP blocks
+ * @shadow_ram_support: shadow support for OTP memory
  *
  * We enable the driver to be backward compatible wrt API version. The
  * driver specifies which APIs it supports (with @ucode_api_max being the
@@ -243,6 +245,8 @@ struct iwl_cfg {
 	u8   valid_rx_ant;
 	bool need_pll_cfg;
 	bool use_isr_legacy;
+	const u16 max_ll_items;
+	const bool shadow_ram_support;
 };
 
 /***************************
diff -up linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h
--- linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h.orig	2009-09-17 09:22:27.000000000 -0400
+++ linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-dev.h	2009-09-17 09:40:55.000000000 -0400
@@ -835,6 +835,18 @@ enum iwl_nvm_type {
 	NVM_DEVICE_TYPE_OTP,
 };
 
+/*
+ * Two types of OTP memory access modes
+ *   IWL_OTP_ACCESS_ABSOLUTE - absolute address mode,
+ * 			        based on physical memory addressing
+ *   IWL_OTP_ACCESS_RELATIVE - relative address mode,
+ * 			       based on logical memory addressing
+ */
+enum iwl_access_mode {
+	IWL_OTP_ACCESS_ABSOLUTE,
+	IWL_OTP_ACCESS_RELATIVE,
+};
+
 /* interrupt statistics */
 struct isr_statistics {
 	u32 hw;
diff -up linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-eeprom.c.orig linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-eeprom.c
--- linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-eeprom.c.orig	2009-09-09 18:13:59.000000000 -0400
+++ linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-eeprom.c	2009-09-17 09:37:20.000000000 -0400
@@ -152,6 +152,19 @@ int iwlcore_eeprom_verify_signature(stru
 }
 EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
 
+static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
+{
+	u32 otpgp;
+
+	otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+	if (mode == IWL_OTP_ACCESS_ABSOLUTE)
+		iwl_clear_bit(priv, CSR_OTP_GP_REG,
+				CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+	else
+		iwl_set_bit(priv, CSR_OTP_GP_REG,
+				CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+}
+
 static int iwlcore_get_nvm_type(struct iwl_priv *priv)
 {
 	u32 otpgp;
@@ -249,6 +262,124 @@ static int iwl_init_otp_access(struct iw
 	return ret;
 }
 
+static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data)
+{
+	int ret = 0;
+	u32 r;
+	u32 otpgp;
+
+	_iwl_write32(priv, CSR_EEPROM_REG,
+		     CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+	ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
+				  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);
+	/* check for ECC errors: */
+	otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
+	if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
+		/* stop in this case */
+		/* set the uncorrectable OTP ECC bit for acknowledgement */
+		iwl_set_bit(priv, CSR_OTP_GP_REG,
+			CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
+		IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n");
+		return -EINVAL;
+	}
+	if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
+		/* continue in this case */
+		/* set the correctable OTP ECC bit for acknowledgement */
+		iwl_set_bit(priv, CSR_OTP_GP_REG,
+				CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
+		IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
+	}
+	*eeprom_data = le16_to_cpu((__force __le16)(r >> 16));
+	return 0;
+}
+
+/*
+ * iwl_is_otp_empty: check for empty OTP
+ */
+static bool iwl_is_otp_empty(struct iwl_priv *priv)
+{
+	u16 next_link_addr = 0, link_value;
+	bool is_empty = false;
+
+	/* locate the beginning of OTP link list */
+	if (!iwl_read_otp_word(priv, next_link_addr, &link_value)) {
+		if (!link_value) {
+			IWL_ERR(priv, "OTP is empty\n");
+			is_empty = true;
+		}
+	} else {
+		IWL_ERR(priv, "Unable to read first block of OTP list.\n");
+		is_empty = true;
+	}
+
+	return is_empty;
+}
+
+
+/*
+ * iwl_find_otp_image: find EEPROM image in OTP
+ *   finding the OTP block that contains the EEPROM image.
+ *   the last valid block on the link list (the block _before_ the last block)
+ *   is the block we should read and used to configure the device.
+ *   If all the available OTP blocks are full, the last block will be the block
+ *   we should read and used to configure the device.
+ *   only perform this operation if shadow RAM is disabled
+ */
+static int iwl_find_otp_image(struct iwl_priv *priv,
+					u16 *validblockaddr)
+{
+	u16 next_link_addr = 0, link_value = 0, valid_addr;
+	int ret = 0;
+	int usedblocks = 0;
+
+	/* set addressing mode to absolute to traverse the link list */
+	iwl_set_otp_access(priv, IWL_OTP_ACCESS_ABSOLUTE);
+
+	/* checking for empty OTP or error */
+	if (iwl_is_otp_empty(priv))
+		return -EINVAL;
+
+	/*
+	 * start traverse link list
+	 * until reach the max number of OTP blocks
+	 * different devices have different number of OTP blocks
+	 */
+	do {
+		/* save current valid block address
+		 * check for more block on the link list
+		 */
+		valid_addr = next_link_addr;
+		next_link_addr = link_value;
+		IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
+			       usedblocks, next_link_addr);
+		if (iwl_read_otp_word(priv, next_link_addr, &link_value))
+			return -EINVAL;
+		if (!link_value) {
+			/*
+			 * reach the end of link list,
+			 * set address point to the starting address
+			 * of the image
+			 */
+			goto done;
+		}
+		/* more in the link list, continue */
+		usedblocks++;
+	} while (usedblocks < priv->cfg->max_ll_items);
+	/* OTP full, use last block */
+	IWL_DEBUG_INFO(priv, "OTP is full, use last block\n");
+done:
+	*validblockaddr = valid_addr;
+	/* skip first 2 bytes (link list pointer) */
+	*validblockaddr += 2;
+	return ret;
+}
+
 /**
  * iwl_eeprom_init - read EEPROM contents
  *
@@ -263,14 +394,13 @@ int iwl_eeprom_init(struct iwl_priv *pri
 	int sz;
 	int ret;
 	u16 addr;
-	u32 otpgp;
+	u16 validblockaddr = 0;
+	u16 cache_addr = 0;
 
 	priv->nvm_device_type = iwlcore_get_nvm_type(priv);
 
 	/* allocate eeprom */
-	if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
-		priv->cfg->eeprom_size =
-			OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL;
+	IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size);
 	sz = priv->cfg->eeprom_size;
 	priv->eeprom = kzalloc(sz, GFP_KERNEL);
 	if (!priv->eeprom) {
@@ -298,46 +428,31 @@ int iwl_eeprom_init(struct iwl_priv *pri
 		if (ret) {
 			IWL_ERR(priv, "Failed to initialize OTP access.\n");
 			ret = -ENOENT;
-			goto err;
+			goto done;
 		}
 		_iwl_write32(priv, CSR_EEPROM_GP,
 			     iwl_read32(priv, CSR_EEPROM_GP) &
 			     ~CSR_EEPROM_GP_IF_OWNER_MSK);
-		/* clear */
-		_iwl_write32(priv, CSR_OTP_GP_REG,
-			     iwl_read32(priv, CSR_OTP_GP_REG) |
+
+		iwl_set_bit(priv, CSR_OTP_GP_REG,
 			     CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
 			     CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
-
-		for (addr = 0; addr < sz; addr += sizeof(u16)) {
-			u32 r;
-
-			_iwl_write32(priv, CSR_EEPROM_REG,
-				     CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
-
-			ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
-						  CSR_EEPROM_REG_READ_VALID_MSK,
-						  IWL_EEPROM_ACCESS_TIMEOUT);
-			if (ret < 0) {
-				IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
+		/* traversing the linked list if no shadow ram supported */
+		if (!priv->cfg->shadow_ram_support) {
+			if (iwl_find_otp_image(priv, &validblockaddr)) {
+				ret = -ENOENT;
 				goto done;
 			}
-			r = _iwl_read_direct32(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) {
-				/* stop in this case */
-				IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n");
+		}
+		for (addr = validblockaddr; addr < validblockaddr + sz;
+		     addr += sizeof(u16)) {
+			u16 eeprom_data;
+
+			ret = iwl_read_otp_word(priv, addr, &eeprom_data);
+			if (ret)
 				goto done;
-			}
-			if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
-				/* continue in this case */
-				_iwl_write32(priv, CSR_OTP_GP_REG,
-					     iwl_read32(priv, CSR_OTP_GP_REG) |
-					     CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
-				IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
-			}
-			e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
+			e[cache_addr / 2] = eeprom_data;
+			cache_addr += sizeof(u16);
 		}
 	} else {
 		/* eeprom is an array of 16bit values */
diff -up linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-eeprom.h.orig linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-eeprom.h
--- linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-eeprom.h.orig	2009-09-09 18:13:59.000000000 -0400
+++ linux-2.6.31.noarch/drivers/net/wireless/iwlwifi/iwl-eeprom.h	2009-09-17 09:24:20.000000000 -0400
@@ -180,8 +180,14 @@ struct iwl_eeprom_channel {
 #define EEPROM_5050_EEPROM_VERSION	(0x21E)
 
 /* OTP */
-#define OTP_LOWER_BLOCKS_TOTAL		(3)
-#define OTP_BLOCK_SIZE			(0x400)
+/* lower blocks contain EEPROM image and calibration data */
+#define OTP_LOW_IMAGE_SIZE		(2 * 512 * sizeof(u16)) /* 2 KB */
+/* high blocks contain PAPD data */
+#define OTP_HIGH_IMAGE_SIZE_6x00        (6 * 512 * sizeof(u16)) /* 6 KB */
+#define OTP_HIGH_IMAGE_SIZE_1000        (0x200 * sizeof(u16)) /* 1024 bytes */
+#define OTP_MAX_LL_ITEMS_1000		(3)	/* OTP blocks for 1000 */
+#define OTP_MAX_LL_ITEMS_6x00		(4)	/* OTP blocks for 6x00 */
+#define OTP_MAX_LL_ITEMS_6x50		(7)	/* OTP blocks for 6x50 */
 
 /* 2.4 GHz */
 extern const u8 iwl_eeprom_band_1[14];


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-12/kernel.spec,v
retrieving revision 1.1810
retrieving revision 1.1811
diff -u -p -r1.1810 -r1.1811
--- kernel.spec	16 Sep 2009 19:58:23 -0000	1.1810
+++ kernel.spec	17 Sep 2009 14:49:58 -0000	1.1811
@@ -668,6 +668,9 @@ Patch680: linux-2.6-iwlagn-modify-digita
 Patch681: linux-2.6-iwlwifi-update-1000-series-API-version-to-match-firmware.patch
 Patch682: linux-2.6-iwlwifi-Handle-new-firmware-file-with-ucode-build-number-in-header.patch
 Patch683: linux-2.6-iwlwifi-fix-debugfs-buffer-handling.patch
+Patch684: linux-2.6-iwlwifi-traverse-linklist-to-find-the-valid-OTP-block.patch
+Patch685: linux-2.6-iwlwifi-fix-unloading-driver-while-scanning.patch
+Patch686: linux-2.6-iwlwifi-remove-deprecated-6000-series-adapters.patch
 
 Patch700: linux-2.6.31-nx-data.patch
 Patch701: linux-2.6.31-modules-ro-nx.patch
@@ -1313,6 +1316,11 @@ ApplyPatch linux-2.6-iwlagn-modify-digit
 ApplyPatch linux-2.6-iwlwifi-Handle-new-firmware-file-with-ucode-build-number-in-header.patch
 ApplyPatch linux-2.6-iwlwifi-update-1000-series-API-version-to-match-firmware.patch
 ApplyPatch linux-2.6-iwlwifi-fix-debugfs-buffer-handling.patch
+ApplyPatch linux-2.6-iwlwifi-traverse-linklist-to-find-the-valid-OTP-block.patch
+ApplyPatch linux-2.6-iwlwifi-fix-unloading-driver-while-scanning.patch
+
+# remove support for deprecated iwl6000 parts
+ApplyPatch linux-2.6-iwlwifi-remove-deprecated-6000-series-adapters.patch
 
 # Mark kernel data as NX
 ApplyPatch linux-2.6.31-nx-data.patch
@@ -2055,6 +2063,10 @@ fi
 # and build.
 
 %changelog
+* Wed Sep 17 2009 John W. Linville <linville at redhat.com>
+- Add a few more iwl1000 support patches.
+- Remove support for deprecated iwl6000 parts.
+
 * Wed Sep 16 2009 Eric Paris <eparis at redhat.com>
 - Do not check CAP_SYS_MODULE when networking tres to autoload a module
 




More information about the scm-commits mailing list