Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 7/8] iwlwifi: BA scd_flow not match condition detected
From: Wey-Yi Guy @ 2010-07-31 15:34 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy
In-Reply-To: <1280590452-10655-1-git-send-email-wey-yi.w.guy@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

It is a uCode bug which cause the tx queue id not match scd_flow
in compressed block ack frame, and it need to be addressed in uCode.
Currently, driver will log the information when it happen.

Since it is possible happen very often and we do not want to fill the syslog,
so don't enable the logging by default.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn-tx.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 55a1b31..ecb953f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -1331,7 +1331,14 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
 	tid = ba_resp->tid;
 	agg = &priv->stations[sta_id].tid[tid].agg;
 	if (unlikely(agg->txq_id != scd_flow)) {
-		IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n",
+		/*
+		 * FIXME: this is a uCode bug which need to be addressed,
+		 * log the information and return for now!
+		 * since it is possible happen very often and in order
+		 * not to fill the syslog, don't enable the logging by default
+		 */
+		IWL_DEBUG_TX_REPLY(priv,
+			"BA scd_flow %d does not match txq_id %d\n",
 			scd_flow, agg->txq_id);
 		return;
 	}
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 8/8] iwlagn: fix typo in ucode_bt_stats_read debugfs
From: Wey-Yi Guy @ 2010-07-31 15:34 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy
In-Reply-To: <1280590452-10655-1-git-send-email-wey-yi.w.guy@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

small typo fix in ucode_bt_stats_read debugfs file

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
index f052c6d..d706b8a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
@@ -980,7 +980,7 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file,
 			 le32_to_cpu(bt->lo_priority_tx_req_cnt),
 			 accum_bt->lo_priority_tx_req_cnt);
 	pos += scnprintf(buf + pos, bufsz - pos,
-			 "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n",
+			 "lo_priority_tx_denied_cnt:\t%u\t\t\t%u\n",
 			 le32_to_cpu(bt->lo_priority_tx_denied_cnt),
 			 accum_bt->lo_priority_tx_denied_cnt);
 	pos += scnprintf(buf + pos, bufsz - pos,
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 1/8] iwlwifi: make iwl_hw_detect static to _agn
From: Wey-Yi Guy @ 2010-07-31 15:34 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy
In-Reply-To: <1280590452-10655-1-git-send-email-wey-yi.w.guy@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

iwl_hw_detect() only used by _agn, make it static

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn.c  |    7 +++++++
 drivers/net/wireless/iwlwifi/iwl-core.c |    8 --------
 drivers/net/wireless/iwlwifi/iwl-core.h |    1 -
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 35337b1..74b917c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3925,6 +3925,13 @@ static struct ieee80211_ops iwl_hw_ops = {
 	.flush = iwl_mac_flush,
 };
 
+static void iwl_hw_detect(struct iwl_priv *priv)
+{
+	priv->hw_rev = _iwl_read32(priv, CSR_HW_REV);
+	priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG);
+	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id);
+}
+
 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int err = 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 8024d44..dbc279d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -183,14 +183,6 @@ out:
 }
 EXPORT_SYMBOL(iwl_alloc_all);
 
-void iwl_hw_detect(struct iwl_priv *priv)
-{
-	priv->hw_rev = _iwl_read32(priv, CSR_HW_REV);
-	priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG);
-	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id);
-}
-EXPORT_SYMBOL(iwl_hw_detect);
-
 /*
  * QoS  support
 */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index e9d23f2..7e51a9b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -346,7 +346,6 @@ struct iwl_cfg {
 
 struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
 		struct ieee80211_ops *hw_ops);
-void iwl_hw_detect(struct iwl_priv *priv);
 void iwl_activate_qos(struct iwl_priv *priv);
 int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 		    const struct ieee80211_tx_queue_params *params);
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 2/8] iwlagn: log pci revision id
From: Wey-Yi Guy @ 2010-07-31 15:34 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy
In-Reply-To: <1280590452-10655-1-git-send-email-wey-yi.w.guy@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

Log the information after reading the PCI_REVISION_ID
from pci config space,

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 74b917c..982e2c7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3930,6 +3930,7 @@ static void iwl_hw_detect(struct iwl_priv *priv)
 	priv->hw_rev = _iwl_read32(priv, CSR_HW_REV);
 	priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG);
 	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id);
+	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
 }
 
 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 3/8] iwlwifi: separate thermal throttling function
From: Wey-Yi Guy @ 2010-07-31 15:34 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy
In-Reply-To: <1280590452-10655-1-git-send-email-wey-yi.w.guy@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

"Thermal Throttling" is an advance feature which only available for
newer _agn devices. Move from iwl-core to iwl-agn for better code
organization.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/Makefile     |    1 +
 drivers/net/wireless/iwlwifi/iwl-1000.c   |    5 +
 drivers/net/wireless/iwlwifi/iwl-5000.c   |   10 +
 drivers/net/wireless/iwlwifi/iwl-6000.c   |    5 +
 drivers/net/wireless/iwlwifi/iwl-agn-tt.c |  697 +++++++++++++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-agn-tt.h |  129 ++++++
 drivers/net/wireless/iwlwifi/iwl-agn.c    |   46 ++
 drivers/net/wireless/iwlwifi/iwl-core.c   |   48 --
 drivers/net/wireless/iwlwifi/iwl-core.h   |   10 +-
 drivers/net/wireless/iwlwifi/iwl-dev.h    |    1 +
 drivers/net/wireless/iwlwifi/iwl-power.c  |  640 +--------------------------
 drivers/net/wireless/iwlwifi/iwl-power.h  |   93 ----
 drivers/net/wireless/iwlwifi/iwl-tx.c     |    9 +-
 13 files changed, 918 insertions(+), 776 deletions(-)
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-tt.c
 create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-tt.h

diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 728bb85..4931639 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_IWLAGN)	+= iwlagn.o
 iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
 iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
 iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
+iwlagn-objs		+= iwl-agn-tt.o
 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
 
 iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 8848333..5ed2441 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -229,6 +229,11 @@ static struct iwl_lib_ops iwl1000_lib = {
 	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+	.tt_ops = {
+		.lower_power_detection = iwl_tt_is_low_power_state,
+		.tt_power_mode = iwl_tt_current_power_mode,
+		.ct_kill_check = iwl_check_for_ct_kill,
+	}
 };
 
 static const struct iwl_ops iwl1000_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 8093ce2..68e282b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -405,6 +405,11 @@ static struct iwl_lib_ops iwl5000_lib = {
 	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+	.tt_ops = {
+		.lower_power_detection = iwl_tt_is_low_power_state,
+		.tt_power_mode = iwl_tt_current_power_mode,
+		.ct_kill_check = iwl_check_for_ct_kill,
+	}
 };
 
 static struct iwl_lib_ops iwl5150_lib = {
@@ -470,6 +475,11 @@ static struct iwl_lib_ops iwl5150_lib = {
 	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+	.tt_ops = {
+		.lower_power_detection = iwl_tt_is_low_power_state,
+		.tt_power_mode = iwl_tt_current_power_mode,
+		.ct_kill_check = iwl_check_for_ct_kill,
+	}
 };
 
 static const struct iwl_ops iwl5000_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 5827052..f900e98 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -330,6 +330,11 @@ static struct iwl_lib_ops iwl6000_lib = {
 	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+	.tt_ops = {
+		.lower_power_detection = iwl_tt_is_low_power_state,
+		.tt_power_mode = iwl_tt_current_power_mode,
+		.ct_kill_check = iwl_check_for_ct_kill,
+	}
 };
 
 static const struct iwl_ops iwl6000_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
new file mode 100644
index 0000000..e4b8ebb
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
@@ -0,0 +1,697 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-commands.h"
+#include "iwl-debug.h"
+#include "iwl-agn-tt.h"
+
+/* default Thermal Throttling transaction table
+ * Current state   |         Throttling Down               |  Throttling Up
+ *=============================================================================
+ *                 Condition Nxt State  Condition Nxt State Condition Nxt State
+ *-----------------------------------------------------------------------------
+ *     IWL_TI_0     T >= 114   CT_KILL  114>T>=105   TI_1      N/A      N/A
+ *     IWL_TI_1     T >= 114   CT_KILL  114>T>=110   TI_2     T<=95     TI_0
+ *     IWL_TI_2     T >= 114   CT_KILL                        T<=100    TI_1
+ *    IWL_CT_KILL      N/A       N/A       N/A        N/A     T<=95     TI_0
+ *=============================================================================
+ */
+static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
+	{IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
+	{IWL_TI_1, 105, CT_KILL_THRESHOLD - 1},
+	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
+	{IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
+	{IWL_TI_2, 110, CT_KILL_THRESHOLD - 1},
+	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
+	{IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
+	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX},
+	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
+};
+static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
+	{IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
+	{IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
+	{IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
+};
+
+/* Advance Thermal Throttling default restriction table */
+static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
+	{IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true },
+	{IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true },
+	{IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false },
+	{IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
+};
+
+bool iwl_tt_is_low_power_state(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	if (tt->state >= IWL_TI_1)
+		return true;
+	return false;
+}
+
+u8 iwl_tt_current_power_mode(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	return tt->tt_power_mode;
+}
+
+bool iwl_ht_enabled(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	struct iwl_tt_restriction *restriction;
+
+	if (!priv->thermal_throttle.advanced_tt)
+		return true;
+	restriction = tt->restriction + tt->state;
+	return restriction->is_ht;
+}
+
+static bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
+{
+	s32 temp = priv->temperature; /* degrees CELSIUS except specified */
+	bool within_margin = false;
+
+	if (priv->cfg->temperature_kelvin)
+		temp = KELVIN_TO_CELSIUS(priv->temperature);
+
+	if (!priv->thermal_throttle.advanced_tt)
+		within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
+				CT_KILL_THRESHOLD_LEGACY) ? true : false;
+	else
+		within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
+				CT_KILL_THRESHOLD) ? true : false;
+	return within_margin;
+}
+
+bool iwl_check_for_ct_kill(struct iwl_priv *priv)
+{
+	bool is_ct_kill = false;
+
+	if (iwl_within_ct_kill_margin(priv)) {
+		iwl_tt_enter_ct_kill(priv);
+		is_ct_kill = true;
+	}
+	return is_ct_kill;
+}
+
+enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	struct iwl_tt_restriction *restriction;
+
+	if (!priv->thermal_throttle.advanced_tt)
+		return IWL_ANT_OK_MULTI;
+	restriction = tt->restriction + tt->state;
+	return restriction->tx_stream;
+}
+
+enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	struct iwl_tt_restriction *restriction;
+
+	if (!priv->thermal_throttle.advanced_tt)
+		return IWL_ANT_OK_MULTI;
+	restriction = tt->restriction + tt->state;
+	return restriction->rx_stream;
+}
+
+#define CT_KILL_EXIT_DURATION (5)	/* 5 seconds duration */
+#define CT_KILL_WAITING_DURATION (300)	/* 300ms duration */
+
+/*
+ * toggle the bit to wake up uCode and check the temperature
+ * if the temperature is below CT, uCode will stay awake and send card
+ * state notification with CT_KILL bit clear to inform Thermal Throttling
+ * Management to change state. Otherwise, uCode will go back to sleep
+ * without doing anything, driver should continue the 5 seconds timer
+ * to wake up uCode for temperature check until temperature drop below CT
+ */
+static void iwl_tt_check_exit_ct_kill(unsigned long data)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)data;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	unsigned long flags;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (tt->state == IWL_TI_CT_KILL) {
+		if (priv->thermal_throttle.ct_kill_toggle) {
+			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+			priv->thermal_throttle.ct_kill_toggle = false;
+		} else {
+			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+			priv->thermal_throttle.ct_kill_toggle = true;
+		}
+		iwl_read32(priv, CSR_UCODE_DRV_GP1);
+		spin_lock_irqsave(&priv->reg_lock, flags);
+		if (!iwl_grab_nic_access(priv))
+			iwl_release_nic_access(priv);
+		spin_unlock_irqrestore(&priv->reg_lock, flags);
+
+		/* Reschedule the ct_kill timer to occur in
+		 * CT_KILL_EXIT_DURATION seconds to ensure we get a
+		 * thermal update */
+		IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
+		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
+			  jiffies + CT_KILL_EXIT_DURATION * HZ);
+	}
+}
+
+static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
+			   bool stop)
+{
+	if (stop) {
+		IWL_DEBUG_POWER(priv, "Stop all queues\n");
+		if (priv->mac80211_registered)
+			ieee80211_stop_queues(priv->hw);
+		IWL_DEBUG_POWER(priv,
+				"Schedule 5 seconds CT_KILL Timer\n");
+		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
+			  jiffies + CT_KILL_EXIT_DURATION * HZ);
+	} else {
+		IWL_DEBUG_POWER(priv, "Wake all queues\n");
+		if (priv->mac80211_registered)
+			ieee80211_wake_queues(priv->hw);
+	}
+}
+
+static void iwl_tt_ready_for_ct_kill(unsigned long data)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)data;
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* temperature timer expired, ready to go into CT_KILL state */
+	if (tt->state != IWL_TI_CT_KILL) {
+		IWL_DEBUG_POWER(priv, "entering CT_KILL state when "
+				"temperature timer expired\n");
+		tt->state = IWL_TI_CT_KILL;
+		set_bit(STATUS_CT_KILL, &priv->status);
+		iwl_perform_ct_kill_task(priv, true);
+	}
+}
+
+static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
+{
+	IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
+	/* make request to retrieve statistics information */
+	iwl_send_statistics_request(priv, CMD_SYNC, false);
+	/* Reschedule the ct_kill wait timer */
+	mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
+		 jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
+}
+
+#define IWL_MINIMAL_POWER_THRESHOLD		(CT_KILL_THRESHOLD_LEGACY)
+#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2	(100)
+#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1	(90)
+
+/*
+ * Legacy thermal throttling
+ * 1) Avoid NIC destruction due to high temperatures
+ *	Chip will identify dangerously high temperatures that can
+ *	harm the device and will power down
+ * 2) Avoid the NIC power down due to high temperature
+ *	Throttle early enough to lower the power consumption before
+ *	drastic steps are needed
+ */
+static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	enum iwl_tt_state old_state;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+	if ((tt->tt_previous_temp) &&
+	    (temp > tt->tt_previous_temp) &&
+	    ((temp - tt->tt_previous_temp) >
+	    IWL_TT_INCREASE_MARGIN)) {
+		IWL_DEBUG_POWER(priv,
+			"Temperature increase %d degree Celsius\n",
+			(temp - tt->tt_previous_temp));
+	}
+#endif
+	old_state = tt->state;
+	/* in Celsius */
+	if (temp >= IWL_MINIMAL_POWER_THRESHOLD)
+		tt->state = IWL_TI_CT_KILL;
+	else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)
+		tt->state = IWL_TI_2;
+	else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)
+		tt->state = IWL_TI_1;
+	else
+		tt->state = IWL_TI_0;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+	tt->tt_previous_temp = temp;
+#endif
+	/* stop ct_kill_waiting_tm timer */
+	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
+	if (tt->state != old_state) {
+		switch (tt->state) {
+		case IWL_TI_0:
+			/*
+			 * When the system is ready to go back to IWL_TI_0
+			 * we only have to call iwl_power_update_mode() to
+			 * do so.
+			 */
+			break;
+		case IWL_TI_1:
+			tt->tt_power_mode = IWL_POWER_INDEX_3;
+			break;
+		case IWL_TI_2:
+			tt->tt_power_mode = IWL_POWER_INDEX_4;
+			break;
+		default:
+			tt->tt_power_mode = IWL_POWER_INDEX_5;
+			break;
+		}
+		mutex_lock(&priv->mutex);
+		if (old_state == IWL_TI_CT_KILL)
+			clear_bit(STATUS_CT_KILL, &priv->status);
+		if (tt->state != IWL_TI_CT_KILL &&
+		    iwl_power_update_mode(priv, true)) {
+			/* TT state not updated
+			 * try again during next temperature read
+			 */
+			if (old_state == IWL_TI_CT_KILL)
+				set_bit(STATUS_CT_KILL, &priv->status);
+			tt->state = old_state;
+			IWL_ERR(priv, "Cannot update power mode, "
+					"TT state not updated\n");
+		} else {
+			if (tt->state == IWL_TI_CT_KILL) {
+				if (force) {
+					set_bit(STATUS_CT_KILL, &priv->status);
+					iwl_perform_ct_kill_task(priv, true);
+				} else {
+					iwl_prepare_ct_kill_task(priv);
+					tt->state = old_state;
+				}
+			} else if (old_state == IWL_TI_CT_KILL &&
+				 tt->state != IWL_TI_CT_KILL)
+				iwl_perform_ct_kill_task(priv, false);
+			IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
+					tt->state);
+			IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
+					tt->tt_power_mode);
+		}
+		mutex_unlock(&priv->mutex);
+	}
+}
+
+/*
+ * Advance thermal throttling
+ * 1) Avoid NIC destruction due to high temperatures
+ *	Chip will identify dangerously high temperatures that can
+ *	harm the device and will power down
+ * 2) Avoid the NIC power down due to high temperature
+ *	Throttle early enough to lower the power consumption before
+ *	drastic steps are needed
+ *	Actions include relaxing the power down sleep thresholds and
+ *	decreasing the number of TX streams
+ * 3) Avoid throughput performance impact as much as possible
+ *
+ *=============================================================================
+ *                 Condition Nxt State  Condition Nxt State Condition Nxt State
+ *-----------------------------------------------------------------------------
+ *     IWL_TI_0     T >= 114   CT_KILL  114>T>=105   TI_1      N/A      N/A
+ *     IWL_TI_1     T >= 114   CT_KILL  114>T>=110   TI_2     T<=95     TI_0
+ *     IWL_TI_2     T >= 114   CT_KILL                        T<=100    TI_1
+ *    IWL_CT_KILL      N/A       N/A       N/A        N/A     T<=95     TI_0
+ *=============================================================================
+ */
+static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	int i;
+	bool changed = false;
+	enum iwl_tt_state old_state;
+	struct iwl_tt_trans *transaction;
+
+	old_state = tt->state;
+	for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) {
+		/* based on the current TT state,
+		 * find the curresponding transaction table
+		 * each table has (IWL_TI_STATE_MAX - 1) entries
+		 * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1))
+		 * will advance to the correct table.
+		 * then based on the current temperature
+		 * find the next state need to transaction to
+		 * go through all the possible (IWL_TI_STATE_MAX - 1) entries
+		 * in the current table to see if transaction is needed
+		 */
+		transaction = tt->transaction +
+			((old_state * (IWL_TI_STATE_MAX - 1)) + i);
+		if (temp >= transaction->tt_low &&
+		    temp <= transaction->tt_high) {
+#ifdef CONFIG_IWLWIFI_DEBUG
+			if ((tt->tt_previous_temp) &&
+			    (temp > tt->tt_previous_temp) &&
+			    ((temp - tt->tt_previous_temp) >
+			    IWL_TT_INCREASE_MARGIN)) {
+				IWL_DEBUG_POWER(priv,
+					"Temperature increase %d "
+					"degree Celsius\n",
+					(temp - tt->tt_previous_temp));
+			}
+			tt->tt_previous_temp = temp;
+#endif
+			if (old_state !=
+			    transaction->next_state) {
+				changed = true;
+				tt->state =
+					transaction->next_state;
+			}
+			break;
+		}
+	}
+	/* stop ct_kill_waiting_tm timer */
+	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
+	if (changed) {
+		struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+
+		if (tt->state >= IWL_TI_1) {
+			/* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
+			tt->tt_power_mode = IWL_POWER_INDEX_5;
+			if (!iwl_ht_enabled(priv))
+				/* disable HT */
+				rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
+					RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
+					RXON_FLG_HT40_PROT_MSK |
+					RXON_FLG_HT_PROT_MSK);
+			else {
+				/* check HT capability and set
+				 * according to the system HT capability
+				 * in case get disabled before */
+				iwl_set_rxon_ht(priv, &priv->current_ht_config);
+			}
+
+		} else {
+			/*
+			 * restore system power setting -- it will be
+			 * recalculated automatically.
+			 */
+
+			/* check HT capability and set
+			 * according to the system HT capability
+			 * in case get disabled before */
+			iwl_set_rxon_ht(priv, &priv->current_ht_config);
+		}
+		mutex_lock(&priv->mutex);
+		if (old_state == IWL_TI_CT_KILL)
+			clear_bit(STATUS_CT_KILL, &priv->status);
+		if (tt->state != IWL_TI_CT_KILL &&
+		    iwl_power_update_mode(priv, true)) {
+			/* TT state not updated
+			 * try again during next temperature read
+			 */
+			IWL_ERR(priv, "Cannot update power mode, "
+					"TT state not updated\n");
+			if (old_state == IWL_TI_CT_KILL)
+				set_bit(STATUS_CT_KILL, &priv->status);
+			tt->state = old_state;
+		} else {
+			IWL_DEBUG_POWER(priv,
+					"Thermal Throttling to new state: %u\n",
+					tt->state);
+			if (old_state != IWL_TI_CT_KILL &&
+			    tt->state == IWL_TI_CT_KILL) {
+				if (force) {
+					IWL_DEBUG_POWER(priv,
+						"Enter IWL_TI_CT_KILL\n");
+					set_bit(STATUS_CT_KILL, &priv->status);
+					iwl_perform_ct_kill_task(priv, true);
+				} else {
+					iwl_prepare_ct_kill_task(priv);
+					tt->state = old_state;
+				}
+			} else if (old_state == IWL_TI_CT_KILL &&
+				  tt->state != IWL_TI_CT_KILL) {
+				IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
+				iwl_perform_ct_kill_task(priv, false);
+			}
+		}
+		mutex_unlock(&priv->mutex);
+	}
+}
+
+/* Card State Notification indicated reach critical temperature
+ * if PSP not enable, no Thermal Throttling function will be performed
+ * just set the GP1 bit to acknowledge the event
+ * otherwise, go into IWL_TI_CT_KILL state
+ * since Card State Notification will not provide any temperature reading
+ * for Legacy mode
+ * so just pass the CT_KILL temperature to iwl_legacy_tt_handler()
+ * for advance mode
+ * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
+ */
+static void iwl_bg_ct_enter(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (!iwl_is_ready(priv))
+		return;
+
+	if (tt->state != IWL_TI_CT_KILL) {
+		IWL_ERR(priv, "Device reached critical temperature "
+			      "- ucode going to sleep!\n");
+		if (!priv->thermal_throttle.advanced_tt)
+			iwl_legacy_tt_handler(priv,
+					      IWL_MINIMAL_POWER_THRESHOLD,
+					      true);
+		else
+			iwl_advance_tt_handler(priv,
+					       CT_KILL_THRESHOLD + 1, true);
+	}
+}
+
+/* Card State Notification indicated out of critical temperature
+ * since Card State Notification will not provide any temperature reading
+ * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature
+ * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state
+ */
+static void iwl_bg_ct_exit(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (!iwl_is_ready(priv))
+		return;
+
+	/* stop ct_kill_exit_tm timer */
+	del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
+
+	if (tt->state == IWL_TI_CT_KILL) {
+		IWL_ERR(priv,
+			"Device temperature below critical"
+			"- ucode awake!\n");
+		/*
+		 * exit from CT_KILL state
+		 * reset the current temperature reading
+		 */
+		priv->temperature = 0;
+		if (!priv->thermal_throttle.advanced_tt)
+			iwl_legacy_tt_handler(priv,
+				      IWL_REDUCED_PERFORMANCE_THRESHOLD_2,
+				      true);
+		else
+			iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,
+					       true);
+	}
+}
+
+void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
+	queue_work(priv->workqueue, &priv->ct_enter);
+}
+EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
+
+void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
+	queue_work(priv->workqueue, &priv->ct_exit);
+}
+EXPORT_SYMBOL(iwl_tt_exit_ct_kill);
+
+static void iwl_bg_tt_work(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
+	s32 temp = priv->temperature; /* degrees CELSIUS except specified */
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (priv->cfg->temperature_kelvin)
+		temp = KELVIN_TO_CELSIUS(priv->temperature);
+
+	if (!priv->thermal_throttle.advanced_tt)
+		iwl_legacy_tt_handler(priv, temp, false);
+	else
+		iwl_advance_tt_handler(priv, temp, false);
+}
+
+void iwl_tt_handler(struct iwl_priv *priv)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
+	queue_work(priv->workqueue, &priv->tt_work);
+}
+EXPORT_SYMBOL(iwl_tt_handler);
+
+/* Thermal throttling initialization
+ * For advance thermal throttling:
+ *     Initialize Thermal Index and temperature threshold table
+ *     Initialize thermal throttling restriction table
+ */
+void iwl_tt_initialize(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+	int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
+	struct iwl_tt_trans *transaction;
+
+	IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n");
+
+	memset(tt, 0, sizeof(struct iwl_tt_mgmt));
+
+	tt->state = IWL_TI_0;
+	init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
+	priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
+	priv->thermal_throttle.ct_kill_exit_tm.function =
+		iwl_tt_check_exit_ct_kill;
+	init_timer(&priv->thermal_throttle.ct_kill_waiting_tm);
+	priv->thermal_throttle.ct_kill_waiting_tm.data =
+		(unsigned long)priv;
+	priv->thermal_throttle.ct_kill_waiting_tm.function =
+		iwl_tt_ready_for_ct_kill;
+	/* setup deferred ct kill work */
+	INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
+	INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
+	INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
+
+	if (priv->cfg->adv_thermal_throttle) {
+		IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
+		tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
+					 IWL_TI_STATE_MAX, GFP_KERNEL);
+		tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
+			IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1),
+			GFP_KERNEL);
+		if (!tt->restriction || !tt->transaction) {
+			IWL_ERR(priv, "Fallback to Legacy Throttling\n");
+			priv->thermal_throttle.advanced_tt = false;
+			kfree(tt->restriction);
+			tt->restriction = NULL;
+			kfree(tt->transaction);
+			tt->transaction = NULL;
+		} else {
+			transaction = tt->transaction +
+				(IWL_TI_0 * (IWL_TI_STATE_MAX - 1));
+			memcpy(transaction, &tt_range_0[0], size);
+			transaction = tt->transaction +
+				(IWL_TI_1 * (IWL_TI_STATE_MAX - 1));
+			memcpy(transaction, &tt_range_1[0], size);
+			transaction = tt->transaction +
+				(IWL_TI_2 * (IWL_TI_STATE_MAX - 1));
+			memcpy(transaction, &tt_range_2[0], size);
+			transaction = tt->transaction +
+				(IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1));
+			memcpy(transaction, &tt_range_3[0], size);
+			size = sizeof(struct iwl_tt_restriction) *
+				IWL_TI_STATE_MAX;
+			memcpy(tt->restriction,
+				&restriction_range[0], size);
+			priv->thermal_throttle.advanced_tt = true;
+		}
+	} else {
+		IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
+		priv->thermal_throttle.advanced_tt = false;
+	}
+}
+EXPORT_SYMBOL(iwl_tt_initialize);
+
+/* cleanup thermal throttling management related memory and timer */
+void iwl_tt_exit(struct iwl_priv *priv)
+{
+	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
+
+	/* stop ct_kill_exit_tm timer if activated */
+	del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
+	/* stop ct_kill_waiting_tm timer if activated */
+	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
+	cancel_work_sync(&priv->tt_work);
+	cancel_work_sync(&priv->ct_enter);
+	cancel_work_sync(&priv->ct_exit);
+
+	if (priv->thermal_throttle.advanced_tt) {
+		/* free advance thermal throttling memory */
+		kfree(tt->restriction);
+		tt->restriction = NULL;
+		kfree(tt->transaction);
+		tt->transaction = NULL;
+	}
+}
+EXPORT_SYMBOL(iwl_tt_exit);
+
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h
new file mode 100644
index 0000000..d550604
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+#ifndef __iwl_tt_setting_h__
+#define __iwl_tt_setting_h__
+
+#include "iwl-commands.h"
+
+#define IWL_ABSOLUTE_ZERO		0
+#define IWL_ABSOLUTE_MAX		0xFFFFFFFF
+#define IWL_TT_INCREASE_MARGIN	5
+#define IWL_TT_CT_KILL_MARGIN	3
+
+enum iwl_antenna_ok {
+	IWL_ANT_OK_NONE,
+	IWL_ANT_OK_SINGLE,
+	IWL_ANT_OK_MULTI,
+};
+
+/* Thermal Throttling State Machine states */
+enum  iwl_tt_state {
+	IWL_TI_0,	/* normal temperature, system power state */
+	IWL_TI_1,	/* high temperature detect, low power state */
+	IWL_TI_2,	/* higher temperature detected, lower power state */
+	IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */
+	IWL_TI_STATE_MAX
+};
+
+/**
+ * struct iwl_tt_restriction - Thermal Throttling restriction table
+ * @tx_stream: number of tx stream allowed
+ * @is_ht: ht enable/disable
+ * @rx_stream: number of rx stream allowed
+ *
+ * This table is used by advance thermal throttling management
+ * based on the current thermal throttling state, and determines
+ * the number of tx/rx streams and the status of HT operation.
+ */
+struct iwl_tt_restriction {
+	enum iwl_antenna_ok tx_stream;
+	enum iwl_antenna_ok rx_stream;
+	bool is_ht;
+};
+
+/**
+ * struct iwl_tt_trans - Thermal Throttling transaction table
+ * @next_state:  next thermal throttling mode
+ * @tt_low: low temperature threshold to change state
+ * @tt_high: high temperature threshold to change state
+ *
+ * This is used by the advanced thermal throttling algorithm
+ * to determine the next thermal state to go based on the
+ * current temperature.
+ */
+struct iwl_tt_trans {
+	enum iwl_tt_state next_state;
+	u32 tt_low;
+	u32 tt_high;
+};
+
+/**
+ * struct iwl_tt_mgnt - Thermal Throttling Management structure
+ * @advanced_tt:    advanced thermal throttle required
+ * @state:          current Thermal Throttling state
+ * @tt_power_mode:  Thermal Throttling power mode index
+ *		    being used to set power level when
+ *		    when thermal throttling state != IWL_TI_0
+ *		    the tt_power_mode should set to different
+ *		    power mode based on the current tt state
+ * @tt_previous_temperature: last measured temperature
+ * @iwl_tt_restriction: ptr to restriction tbl, used by advance
+ *		    thermal throttling to determine how many tx/rx streams
+ *		    should be used in tt state; and can HT be enabled or not
+ * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling
+ *		    state transaction
+ * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature
+ * @ct_kill_exit_tm: timer to exit thermal kill
+ */
+struct iwl_tt_mgmt {
+	enum iwl_tt_state state;
+	bool advanced_tt;
+	u8 tt_power_mode;
+	bool ct_kill_toggle;
+#ifdef CONFIG_IWLWIFI_DEBUG
+	s32 tt_previous_temp;
+#endif
+	struct iwl_tt_restriction *restriction;
+	struct iwl_tt_trans *transaction;
+	struct timer_list ct_kill_exit_tm;
+	struct timer_list ct_kill_waiting_tm;
+};
+
+u8 iwl_tt_current_power_mode(struct iwl_priv *priv);
+bool iwl_tt_is_low_power_state(struct iwl_priv *priv);
+bool iwl_ht_enabled(struct iwl_priv *priv);
+bool iwl_check_for_ct_kill(struct iwl_priv *priv);
+enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
+enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
+void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
+void iwl_tt_exit_ct_kill(struct iwl_priv *priv);
+void iwl_tt_handler(struct iwl_priv *priv);
+void iwl_tt_initialize(struct iwl_priv *priv);
+void iwl_tt_exit(struct iwl_priv *priv);
+
+#endif  /* __iwl_tt_setting_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 982e2c7..fcbc42c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2632,6 +2632,52 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
 	return pos;
 }
 
+static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
+{
+	struct iwl_ct_kill_config cmd;
+	struct iwl_ct_kill_throttling_config adv_cmd;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+		    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	priv->thermal_throttle.ct_kill_toggle = false;
+
+	if (priv->cfg->support_ct_kill_exit) {
+		adv_cmd.critical_temperature_enter =
+			cpu_to_le32(priv->hw_params.ct_kill_threshold);
+		adv_cmd.critical_temperature_exit =
+			cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
+
+		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+				       sizeof(adv_cmd), &adv_cmd);
+		if (ret)
+			IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
+		else
+			IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
+					"succeeded, "
+					"critical temperature enter is %d,"
+					"exit is %d\n",
+				       priv->hw_params.ct_kill_threshold,
+				       priv->hw_params.ct_kill_exit_threshold);
+	} else {
+		cmd.critical_temperature_R =
+			cpu_to_le32(priv->hw_params.ct_kill_threshold);
+
+		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+				       sizeof(cmd), &cmd);
+		if (ret)
+			IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
+		else
+			IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
+					"succeeded, "
+					"critical temperature is %d\n",
+					priv->hw_params.ct_kill_threshold);
+	}
+}
+
 /**
  * iwl_alive_start - called after REPLY_ALIVE notification received
  *                   from protocol/runtime uCode (initialization uCode's
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index dbc279d..5af5e23 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1516,54 +1516,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
 }
 EXPORT_SYMBOL(iwl_send_statistics_request);
 
-void iwl_rf_kill_ct_config(struct iwl_priv *priv)
-{
-	struct iwl_ct_kill_config cmd;
-	struct iwl_ct_kill_throttling_config adv_cmd;
-	unsigned long flags;
-	int ret = 0;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-		    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	priv->thermal_throttle.ct_kill_toggle = false;
-
-	if (priv->cfg->support_ct_kill_exit) {
-		adv_cmd.critical_temperature_enter =
-			cpu_to_le32(priv->hw_params.ct_kill_threshold);
-		adv_cmd.critical_temperature_exit =
-			cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
-
-		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
-				       sizeof(adv_cmd), &adv_cmd);
-		if (ret)
-			IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
-		else
-			IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
-					"succeeded, "
-					"critical temperature enter is %d,"
-					"exit is %d\n",
-				       priv->hw_params.ct_kill_threshold,
-				       priv->hw_params.ct_kill_exit_threshold);
-	} else {
-		cmd.critical_temperature_R =
-			cpu_to_le32(priv->hw_params.ct_kill_threshold);
-
-		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
-				       sizeof(cmd), &cmd);
-		if (ret)
-			IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
-		else
-			IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
-					"succeeded, "
-					"critical temperature is %d\n",
-					priv->hw_params.ct_kill_threshold);
-	}
-}
-EXPORT_SYMBOL(iwl_rf_kill_ct_config);
-
-
 /*
  * CARD_STATE_CMD
  *
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 7e51a9b..4c3bf4d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -135,6 +135,12 @@ struct iwl_temp_ops {
 	void (*set_calib_version)(struct iwl_priv *priv);
 };
 
+struct iwl_tt_ops {
+	bool (*lower_power_detection)(struct iwl_priv *priv);
+	u8 (*tt_power_mode)(struct iwl_priv *priv);
+	bool (*ct_kill_check)(struct iwl_priv *priv);
+};
+
 struct iwl_lib_ops {
 	/* set hw dependent parameters */
 	int (*set_hw_params)(struct iwl_priv *priv);
@@ -211,6 +217,9 @@ struct iwl_lib_ops {
 	void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
 
 	struct iwl_debugfs_ops debugfs_ops;
+
+	/* thermal throttling */
+	struct iwl_tt_ops tt_ops;
 };
 
 struct iwl_led_ops {
@@ -695,7 +704,6 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv)
 	return iwl_is_ready(priv);
 }
 
-extern void iwl_rf_kill_ct_config(struct iwl_priv *priv);
 extern void iwl_send_bt_config(struct iwl_priv *priv);
 extern int iwl_send_statistics_request(struct iwl_priv *priv,
 				       u8 flags, bool clear);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index f35bcad..3d9b656 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -47,6 +47,7 @@
 #include "iwl-led.h"
 #include "iwl-power.h"
 #include "iwl-agn-rs.h"
+#include "iwl-agn-tt.h"
 
 struct iwl_tx_queue;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index cda6a94..da1f2ae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -192,47 +192,6 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
 	IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
 }
 
-/* default Thermal Throttling transaction table
- * Current state   |         Throttling Down               |  Throttling Up
- *=============================================================================
- *                 Condition Nxt State  Condition Nxt State Condition Nxt State
- *-----------------------------------------------------------------------------
- *     IWL_TI_0     T >= 114   CT_KILL  114>T>=105   TI_1      N/A      N/A
- *     IWL_TI_1     T >= 114   CT_KILL  114>T>=110   TI_2     T<=95     TI_0
- *     IWL_TI_2     T >= 114   CT_KILL                        T<=100    TI_1
- *    IWL_CT_KILL      N/A       N/A       N/A        N/A     T<=95     TI_0
- *=============================================================================
- */
-static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = {
-	{IWL_TI_0, IWL_ABSOLUTE_ZERO, 104},
-	{IWL_TI_1, 105, CT_KILL_THRESHOLD - 1},
-	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
-};
-static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = {
-	{IWL_TI_0, IWL_ABSOLUTE_ZERO, 95},
-	{IWL_TI_2, 110, CT_KILL_THRESHOLD - 1},
-	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
-};
-static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = {
-	{IWL_TI_1, IWL_ABSOLUTE_ZERO, 100},
-	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX},
-	{IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}
-};
-static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
-	{IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD},
-	{IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX},
-	{IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}
-};
-
-/* Advance Thermal Throttling default restriction table */
-static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
-	{IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true },
-	{IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true },
-	{IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false },
-	{IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
-};
-
-
 static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
 				    struct iwl_powertable_cmd *cmd)
 {
@@ -308,7 +267,6 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
 int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 {
 	int ret = 0;
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
 	bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
 	bool update_chains;
 	struct iwl_powertable_cmd cmd;
@@ -325,9 +283,15 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 	else if (priv->cfg->supports_idle &&
 		 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
 		iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20);
-	else if (tt->state >= IWL_TI_1)
-		iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper);
-	else if (!enabled)
+	else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
+		 priv->cfg->ops->lib->tt_ops.tt_power_mode) {
+		if (priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) {
+			/* in thermal throttling low power state */
+			iwl_static_sleep_cmd(priv, &cmd,
+			    priv->cfg->ops->lib->tt_ops.tt_power_mode(priv),
+			    dtimper);
+		}
+	} else if (!enabled)
 		iwl_power_sleep_cam_cmd(priv, &cmd);
 	else if (priv->power_data.debug_sleep_level_override >= 0)
 		iwl_static_sleep_cmd(priv, &cmd,
@@ -367,592 +331,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 }
 EXPORT_SYMBOL(iwl_power_update_mode);
 
-bool iwl_ht_enabled(struct iwl_priv *priv)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	struct iwl_tt_restriction *restriction;
-
-	if (!priv->thermal_throttle.advanced_tt)
-		return true;
-	restriction = tt->restriction + tt->state;
-	return restriction->is_ht;
-}
-EXPORT_SYMBOL(iwl_ht_enabled);
-
-bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
-{
-	s32 temp = priv->temperature; /* degrees CELSIUS except specified */
-	bool within_margin = false;
-
-	if (priv->cfg->temperature_kelvin)
-		temp = KELVIN_TO_CELSIUS(priv->temperature);
-
-	if (!priv->thermal_throttle.advanced_tt)
-		within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
-				CT_KILL_THRESHOLD_LEGACY) ? true : false;
-	else
-		within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
-				CT_KILL_THRESHOLD) ? true : false;
-	return within_margin;
-}
-
-enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	struct iwl_tt_restriction *restriction;
-
-	if (!priv->thermal_throttle.advanced_tt)
-		return IWL_ANT_OK_MULTI;
-	restriction = tt->restriction + tt->state;
-	return restriction->tx_stream;
-}
-EXPORT_SYMBOL(iwl_tx_ant_restriction);
-
-enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	struct iwl_tt_restriction *restriction;
-
-	if (!priv->thermal_throttle.advanced_tt)
-		return IWL_ANT_OK_MULTI;
-	restriction = tt->restriction + tt->state;
-	return restriction->rx_stream;
-}
-
-#define CT_KILL_EXIT_DURATION (5)	/* 5 seconds duration */
-#define CT_KILL_WAITING_DURATION (300)	/* 300ms duration */
-
-/*
- * toggle the bit to wake up uCode and check the temperature
- * if the temperature is below CT, uCode will stay awake and send card
- * state notification with CT_KILL bit clear to inform Thermal Throttling
- * Management to change state. Otherwise, uCode will go back to sleep
- * without doing anything, driver should continue the 5 seconds timer
- * to wake up uCode for temperature check until temperature drop below CT
- */
-static void iwl_tt_check_exit_ct_kill(unsigned long data)
-{
-	struct iwl_priv *priv = (struct iwl_priv *)data;
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	unsigned long flags;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (tt->state == IWL_TI_CT_KILL) {
-		if (priv->thermal_throttle.ct_kill_toggle) {
-			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-			priv->thermal_throttle.ct_kill_toggle = false;
-		} else {
-			iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-				    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-			priv->thermal_throttle.ct_kill_toggle = true;
-		}
-		iwl_read32(priv, CSR_UCODE_DRV_GP1);
-		spin_lock_irqsave(&priv->reg_lock, flags);
-		if (!iwl_grab_nic_access(priv))
-			iwl_release_nic_access(priv);
-		spin_unlock_irqrestore(&priv->reg_lock, flags);
-
-		/* Reschedule the ct_kill timer to occur in
-		 * CT_KILL_EXIT_DURATION seconds to ensure we get a
-		 * thermal update */
-		IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
-		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
-			  CT_KILL_EXIT_DURATION * HZ);
-	}
-}
-
-static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
-			   bool stop)
-{
-	if (stop) {
-		IWL_DEBUG_POWER(priv, "Stop all queues\n");
-		if (priv->mac80211_registered)
-			ieee80211_stop_queues(priv->hw);
-		IWL_DEBUG_POWER(priv,
-				"Schedule 5 seconds CT_KILL Timer\n");
-		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
-			  CT_KILL_EXIT_DURATION * HZ);
-	} else {
-		IWL_DEBUG_POWER(priv, "Wake all queues\n");
-		if (priv->mac80211_registered)
-			ieee80211_wake_queues(priv->hw);
-	}
-}
-
-static void iwl_tt_ready_for_ct_kill(unsigned long data)
-{
-	struct iwl_priv *priv = (struct iwl_priv *)data;
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	/* temperature timer expired, ready to go into CT_KILL state */
-	if (tt->state != IWL_TI_CT_KILL) {
-		IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n");
-		tt->state = IWL_TI_CT_KILL;
-		set_bit(STATUS_CT_KILL, &priv->status);
-		iwl_perform_ct_kill_task(priv, true);
-	}
-}
-
-static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
-{
-	IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
-	/* make request to retrieve statistics information */
-	iwl_send_statistics_request(priv, CMD_SYNC, false);
-	/* Reschedule the ct_kill wait timer */
-	mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
-		 jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
-}
-
-#define IWL_MINIMAL_POWER_THRESHOLD		(CT_KILL_THRESHOLD_LEGACY)
-#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2	(100)
-#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1	(90)
-
-/*
- * Legacy thermal throttling
- * 1) Avoid NIC destruction due to high temperatures
- *	Chip will identify dangerously high temperatures that can
- *	harm the device and will power down
- * 2) Avoid the NIC power down due to high temperature
- *	Throttle early enough to lower the power consumption before
- *	drastic steps are needed
- */
-static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	enum iwl_tt_state old_state;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if ((tt->tt_previous_temp) &&
-	    (temp > tt->tt_previous_temp) &&
-	    ((temp - tt->tt_previous_temp) >
-	    IWL_TT_INCREASE_MARGIN)) {
-		IWL_DEBUG_POWER(priv,
-			"Temperature increase %d degree Celsius\n",
-			(temp - tt->tt_previous_temp));
-	}
-#endif
-	old_state = tt->state;
-	/* in Celsius */
-	if (temp >= IWL_MINIMAL_POWER_THRESHOLD)
-		tt->state = IWL_TI_CT_KILL;
-	else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)
-		tt->state = IWL_TI_2;
-	else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)
-		tt->state = IWL_TI_1;
-	else
-		tt->state = IWL_TI_0;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	tt->tt_previous_temp = temp;
-#endif
-	/* stop ct_kill_waiting_tm timer */
-	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
-	if (tt->state != old_state) {
-		switch (tt->state) {
-		case IWL_TI_0:
-			/*
-			 * When the system is ready to go back to IWL_TI_0
-			 * we only have to call iwl_power_update_mode() to
-			 * do so.
-			 */
-			break;
-		case IWL_TI_1:
-			tt->tt_power_mode = IWL_POWER_INDEX_3;
-			break;
-		case IWL_TI_2:
-			tt->tt_power_mode = IWL_POWER_INDEX_4;
-			break;
-		default:
-			tt->tt_power_mode = IWL_POWER_INDEX_5;
-			break;
-		}
-		mutex_lock(&priv->mutex);
-		if (old_state == IWL_TI_CT_KILL)
-			clear_bit(STATUS_CT_KILL, &priv->status);
-		if (tt->state != IWL_TI_CT_KILL &&
-		    iwl_power_update_mode(priv, true)) {
-			/* TT state not updated
-			 * try again during next temperature read
-			 */
-			if (old_state == IWL_TI_CT_KILL)
-				set_bit(STATUS_CT_KILL, &priv->status);
-			tt->state = old_state;
-			IWL_ERR(priv, "Cannot update power mode, "
-					"TT state not updated\n");
-		} else {
-			if (tt->state == IWL_TI_CT_KILL) {
-				if (force) {
-					set_bit(STATUS_CT_KILL, &priv->status);
-					iwl_perform_ct_kill_task(priv, true);
-				} else {
-					iwl_prepare_ct_kill_task(priv);
-					tt->state = old_state;
-				}
-			} else if (old_state == IWL_TI_CT_KILL &&
-				 tt->state != IWL_TI_CT_KILL)
-				iwl_perform_ct_kill_task(priv, false);
-			IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
-					tt->state);
-			IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
-					tt->tt_power_mode);
-		}
-		mutex_unlock(&priv->mutex);
-	}
-}
-
-/*
- * Advance thermal throttling
- * 1) Avoid NIC destruction due to high temperatures
- *	Chip will identify dangerously high temperatures that can
- *	harm the device and will power down
- * 2) Avoid the NIC power down due to high temperature
- *	Throttle early enough to lower the power consumption before
- *	drastic steps are needed
- *	Actions include relaxing the power down sleep thresholds and
- *	decreasing the number of TX streams
- * 3) Avoid throughput performance impact as much as possible
- *
- *=============================================================================
- *                 Condition Nxt State  Condition Nxt State Condition Nxt State
- *-----------------------------------------------------------------------------
- *     IWL_TI_0     T >= 114   CT_KILL  114>T>=105   TI_1      N/A      N/A
- *     IWL_TI_1     T >= 114   CT_KILL  114>T>=110   TI_2     T<=95     TI_0
- *     IWL_TI_2     T >= 114   CT_KILL                        T<=100    TI_1
- *    IWL_CT_KILL      N/A       N/A       N/A        N/A     T<=95     TI_0
- *=============================================================================
- */
-static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	int i;
-	bool changed = false;
-	enum iwl_tt_state old_state;
-	struct iwl_tt_trans *transaction;
-
-	old_state = tt->state;
-	for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) {
-		/* based on the current TT state,
-		 * find the curresponding transaction table
-		 * each table has (IWL_TI_STATE_MAX - 1) entries
-		 * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1))
-		 * will advance to the correct table.
-		 * then based on the current temperature
-		 * find the next state need to transaction to
-		 * go through all the possible (IWL_TI_STATE_MAX - 1) entries
-		 * in the current table to see if transaction is needed
-		 */
-		transaction = tt->transaction +
-			((old_state * (IWL_TI_STATE_MAX - 1)) + i);
-		if (temp >= transaction->tt_low &&
-		    temp <= transaction->tt_high) {
-#ifdef CONFIG_IWLWIFI_DEBUG
-			if ((tt->tt_previous_temp) &&
-			    (temp > tt->tt_previous_temp) &&
-			    ((temp - tt->tt_previous_temp) >
-			    IWL_TT_INCREASE_MARGIN)) {
-				IWL_DEBUG_POWER(priv,
-					"Temperature increase %d "
-					"degree Celsius\n",
-					(temp - tt->tt_previous_temp));
-			}
-			tt->tt_previous_temp = temp;
-#endif
-			if (old_state !=
-			    transaction->next_state) {
-				changed = true;
-				tt->state =
-					transaction->next_state;
-			}
-			break;
-		}
-	}
-	/* stop ct_kill_waiting_tm timer */
-	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
-	if (changed) {
-		struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
-
-		if (tt->state >= IWL_TI_1) {
-			/* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
-			tt->tt_power_mode = IWL_POWER_INDEX_5;
-			if (!iwl_ht_enabled(priv))
-				/* disable HT */
-				rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
-					RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
-					RXON_FLG_HT40_PROT_MSK |
-					RXON_FLG_HT_PROT_MSK);
-			else {
-				/* check HT capability and set
-				 * according to the system HT capability
-				 * in case get disabled before */
-				iwl_set_rxon_ht(priv, &priv->current_ht_config);
-			}
-
-		} else {
-			/*
-			 * restore system power setting -- it will be
-			 * recalculated automatically.
-			 */
-
-			/* check HT capability and set
-			 * according to the system HT capability
-			 * in case get disabled before */
-			iwl_set_rxon_ht(priv, &priv->current_ht_config);
-		}
-		mutex_lock(&priv->mutex);
-		if (old_state == IWL_TI_CT_KILL)
-			clear_bit(STATUS_CT_KILL, &priv->status);
-		if (tt->state != IWL_TI_CT_KILL &&
-		    iwl_power_update_mode(priv, true)) {
-			/* TT state not updated
-			 * try again during next temperature read
-			 */
-			IWL_ERR(priv, "Cannot update power mode, "
-					"TT state not updated\n");
-			if (old_state == IWL_TI_CT_KILL)
-				set_bit(STATUS_CT_KILL, &priv->status);
-			tt->state = old_state;
-		} else {
-			IWL_DEBUG_POWER(priv,
-					"Thermal Throttling to new state: %u\n",
-					tt->state);
-			if (old_state != IWL_TI_CT_KILL &&
-			    tt->state == IWL_TI_CT_KILL) {
-				if (force) {
-					IWL_DEBUG_POWER(priv,
-						"Enter IWL_TI_CT_KILL\n");
-					set_bit(STATUS_CT_KILL, &priv->status);
-					iwl_perform_ct_kill_task(priv, true);
-				} else {
-					iwl_prepare_ct_kill_task(priv);
-					tt->state = old_state;
-				}
-			} else if (old_state == IWL_TI_CT_KILL &&
-				  tt->state != IWL_TI_CT_KILL) {
-				IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
-				iwl_perform_ct_kill_task(priv, false);
-			}
-		}
-		mutex_unlock(&priv->mutex);
-	}
-}
-
-/* Card State Notification indicated reach critical temperature
- * if PSP not enable, no Thermal Throttling function will be performed
- * just set the GP1 bit to acknowledge the event
- * otherwise, go into IWL_TI_CT_KILL state
- * since Card State Notification will not provide any temperature reading
- * for Legacy mode
- * so just pass the CT_KILL temperature to iwl_legacy_tt_handler()
- * for advance mode
- * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
- */
-static void iwl_bg_ct_enter(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (!iwl_is_ready(priv))
-		return;
-
-	if (tt->state != IWL_TI_CT_KILL) {
-		IWL_ERR(priv, "Device reached critical temperature "
-			      "- ucode going to sleep!\n");
-		if (!priv->thermal_throttle.advanced_tt)
-			iwl_legacy_tt_handler(priv,
-					      IWL_MINIMAL_POWER_THRESHOLD,
-					      true);
-		else
-			iwl_advance_tt_handler(priv,
-					       CT_KILL_THRESHOLD + 1, true);
-	}
-}
-
-/* Card State Notification indicated out of critical temperature
- * since Card State Notification will not provide any temperature reading
- * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature
- * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state
- */
-static void iwl_bg_ct_exit(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (!iwl_is_ready(priv))
-		return;
-
-	/* stop ct_kill_exit_tm timer */
-	del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
-
-	if (tt->state == IWL_TI_CT_KILL) {
-		IWL_ERR(priv,
-			"Device temperature below critical"
-			"- ucode awake!\n");
-		/*
-		 * exit from CT_KILL state
-		 * reset the current temperature reading
-		 */
-		priv->temperature = 0;
-		if (!priv->thermal_throttle.advanced_tt)
-			iwl_legacy_tt_handler(priv,
-					      IWL_REDUCED_PERFORMANCE_THRESHOLD_2,
-					      true);
-		else
-			iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD,
-					       true);
-	}
-}
-
-void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
-	queue_work(priv->workqueue, &priv->ct_enter);
-}
-EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
-
-void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
-	queue_work(priv->workqueue, &priv->ct_exit);
-}
-EXPORT_SYMBOL(iwl_tt_exit_ct_kill);
-
-static void iwl_bg_tt_work(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
-	s32 temp = priv->temperature; /* degrees CELSIUS except specified */
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (priv->cfg->temperature_kelvin)
-		temp = KELVIN_TO_CELSIUS(priv->temperature);
-
-	if (!priv->thermal_throttle.advanced_tt)
-		iwl_legacy_tt_handler(priv, temp, false);
-	else
-		iwl_advance_tt_handler(priv, temp, false);
-}
-
-void iwl_tt_handler(struct iwl_priv *priv)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
-	queue_work(priv->workqueue, &priv->tt_work);
-}
-EXPORT_SYMBOL(iwl_tt_handler);
-
-/* Thermal throttling initialization
- * For advance thermal throttling:
- *     Initialize Thermal Index and temperature threshold table
- *     Initialize thermal throttling restriction table
- */
-void iwl_tt_initialize(struct iwl_priv *priv)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-	int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
-	struct iwl_tt_trans *transaction;
-
-	IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n");
-
-	memset(tt, 0, sizeof(struct iwl_tt_mgmt));
-
-	tt->state = IWL_TI_0;
-	init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
-	priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
-	priv->thermal_throttle.ct_kill_exit_tm.function =
-		iwl_tt_check_exit_ct_kill;
-	init_timer(&priv->thermal_throttle.ct_kill_waiting_tm);
-	priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv;
-	priv->thermal_throttle.ct_kill_waiting_tm.function =
-		iwl_tt_ready_for_ct_kill;
-	/* setup deferred ct kill work */
-	INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
-	INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
-	INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
-
-	if (priv->cfg->adv_thermal_throttle) {
-		IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
-		tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
-					 IWL_TI_STATE_MAX, GFP_KERNEL);
-		tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
-			IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1),
-			GFP_KERNEL);
-		if (!tt->restriction || !tt->transaction) {
-			IWL_ERR(priv, "Fallback to Legacy Throttling\n");
-			priv->thermal_throttle.advanced_tt = false;
-			kfree(tt->restriction);
-			tt->restriction = NULL;
-			kfree(tt->transaction);
-			tt->transaction = NULL;
-		} else {
-			transaction = tt->transaction +
-				(IWL_TI_0 * (IWL_TI_STATE_MAX - 1));
-			memcpy(transaction, &tt_range_0[0], size);
-			transaction = tt->transaction +
-				(IWL_TI_1 * (IWL_TI_STATE_MAX - 1));
-			memcpy(transaction, &tt_range_1[0], size);
-			transaction = tt->transaction +
-				(IWL_TI_2 * (IWL_TI_STATE_MAX - 1));
-			memcpy(transaction, &tt_range_2[0], size);
-			transaction = tt->transaction +
-				(IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1));
-			memcpy(transaction, &tt_range_3[0], size);
-			size = sizeof(struct iwl_tt_restriction) *
-				IWL_TI_STATE_MAX;
-			memcpy(tt->restriction,
-				&restriction_range[0], size);
-			priv->thermal_throttle.advanced_tt = true;
-		}
-	} else {
-		IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
-		priv->thermal_throttle.advanced_tt = false;
-	}
-}
-EXPORT_SYMBOL(iwl_tt_initialize);
-
-/* cleanup thermal throttling management related memory and timer */
-void iwl_tt_exit(struct iwl_priv *priv)
-{
-	struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
-
-	/* stop ct_kill_exit_tm timer if activated */
-	del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
-	/* stop ct_kill_waiting_tm timer if activated */
-	del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm);
-	cancel_work_sync(&priv->tt_work);
-	cancel_work_sync(&priv->ct_enter);
-	cancel_work_sync(&priv->ct_exit);
-
-	if (priv->thermal_throttle.advanced_tt) {
-		/* free advance thermal throttling memory */
-		kfree(tt->restriction);
-		tt->restriction = NULL;
-		kfree(tt->transaction);
-		tt->transaction = NULL;
-	}
-}
-EXPORT_SYMBOL(iwl_tt_exit);
-
 /* initialize to default */
 void iwl_power_initialize(struct iwl_priv *priv)
 {
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 5db91c1..df81565 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -30,90 +30,6 @@
 
 #include "iwl-commands.h"
 
-#define IWL_ABSOLUTE_ZERO		0
-#define IWL_ABSOLUTE_MAX		0xFFFFFFFF
-#define IWL_TT_INCREASE_MARGIN	5
-#define IWL_TT_CT_KILL_MARGIN	3
-
-enum iwl_antenna_ok {
-	IWL_ANT_OK_NONE,
-	IWL_ANT_OK_SINGLE,
-	IWL_ANT_OK_MULTI,
-};
-
-/* Thermal Throttling State Machine states */
-enum  iwl_tt_state {
-	IWL_TI_0,	/* normal temperature, system power state */
-	IWL_TI_1,	/* high temperature detect, low power state */
-	IWL_TI_2,	/* higher temperature detected, lower power state */
-	IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */
-	IWL_TI_STATE_MAX
-};
-
-/**
- * struct iwl_tt_restriction - Thermal Throttling restriction table
- * @tx_stream: number of tx stream allowed
- * @is_ht: ht enable/disable
- * @rx_stream: number of rx stream allowed
- *
- * This table is used by advance thermal throttling management
- * based on the current thermal throttling state, and determines
- * the number of tx/rx streams and the status of HT operation.
- */
-struct iwl_tt_restriction {
-	enum iwl_antenna_ok tx_stream;
-	enum iwl_antenna_ok rx_stream;
-	bool is_ht;
-};
-
-/**
- * struct iwl_tt_trans - Thermal Throttling transaction table
- * @next_state:  next thermal throttling mode
- * @tt_low: low temperature threshold to change state
- * @tt_high: high temperature threshold to change state
- *
- * This is used by the advanced thermal throttling algorithm
- * to determine the next thermal state to go based on the
- * current temperature.
- */
-struct iwl_tt_trans {
-	enum iwl_tt_state next_state;
-	u32 tt_low;
-	u32 tt_high;
-};
-
-/**
- * struct iwl_tt_mgnt - Thermal Throttling Management structure
- * @advanced_tt:    advanced thermal throttle required
- * @state:          current Thermal Throttling state
- * @tt_power_mode:  Thermal Throttling power mode index
- *		    being used to set power level when
- * 		    when thermal throttling state != IWL_TI_0
- *		    the tt_power_mode should set to different
- *		    power mode based on the current tt state
- * @tt_previous_temperature: last measured temperature
- * @iwl_tt_restriction: ptr to restriction tbl, used by advance
- *		    thermal throttling to determine how many tx/rx streams
- *		    should be used in tt state; and can HT be enabled or not
- * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling
- *		    state transaction
- * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature
- * @ct_kill_exit_tm: timer to exit thermal kill
- */
-struct iwl_tt_mgmt {
-	enum iwl_tt_state state;
-	bool advanced_tt;
-	u8 tt_power_mode;
-	bool ct_kill_toggle;
-#ifdef CONFIG_IWLWIFI_DEBUG
-	s32 tt_previous_temp;
-#endif
-	struct iwl_tt_restriction *restriction;
-	struct iwl_tt_trans *transaction;
-	struct timer_list ct_kill_exit_tm;
-	struct timer_list ct_kill_waiting_tm;
-};
-
 enum iwl_power_level {
 	IWL_POWER_INDEX_1,
 	IWL_POWER_INDEX_2,
@@ -130,15 +46,6 @@ struct iwl_power_mgr {
 };
 
 int iwl_power_update_mode(struct iwl_priv *priv, bool force);
-bool iwl_ht_enabled(struct iwl_priv *priv);
-bool iwl_within_ct_kill_margin(struct iwl_priv *priv);
-enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
-enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
-void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
-void iwl_tt_exit_ct_kill(struct iwl_priv *priv);
-void iwl_tt_handler(struct iwl_priv *priv);
-void iwl_tt_initialize(struct iwl_priv *priv);
-void iwl_tt_exit(struct iwl_priv *priv);
 void iwl_power_initialize(struct iwl_priv *priv);
 
 extern bool no_sleep_autoadjust;
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index a81989c..c308dab 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -422,6 +422,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 	int len;
 	u32 idx;
 	u16 fix_size;
+	bool is_ct_kill = false;
 
 	cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
 	fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
@@ -443,9 +444,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 
 	if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
 		IWL_ERR(priv, "No space in command queue\n");
-		if (iwl_within_ct_kill_margin(priv))
-			iwl_tt_enter_ct_kill(priv);
-		else {
+		if (priv->cfg->ops->lib->tt_ops.ct_kill_check) {
+			is_ct_kill =
+				priv->cfg->ops->lib->tt_ops.ct_kill_check(priv);
+		}
+		if (!is_ct_kill) {
 			IWL_ERR(priv, "Restarting adapter due to queue full\n");
 			queue_work(priv->workqueue, &priv->restart);
 		}
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 5/8] iwlwifi: fix compile warning
From: Wey-Yi Guy @ 2010-07-31 15:34 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Johannes Berg, Wey-Yi Guy
In-Reply-To: <1280590452-10655-1-git-send-email-wey-yi.w.guy@intel.com>

From: Johannes Berg <johannes.berg@intel.com>

When iwlwifi is compiled w/o debug, we get
this warning:
iwl-agn.c: In function ‘iwlagn_load_firmware’:
iwl-agn.c:2014: warning: passing argument 3 of ‘iwl_print_hex_dump’ discards qualifiers from pointer target type
iwl-debug.h:73: note: expected ‘void *’ but argument is of type ‘const u8 *’

because the const qualifier is missing in the
inline stub. Fix this.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-debug.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 5c2bcef..0b961a3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -71,7 +71,7 @@ do {                                            			\
 #define IWL_DEBUG(__priv, level, fmt, args...)
 #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)
 static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
-				      void *p, u32 len)
+				      const void *p, u32 len)
 {}
 #endif				/* CONFIG_IWLWIFI_DEBUG */
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 4/8] iwlwifi: make iwl_set_hw_params static to _agn
From: Wey-Yi Guy @ 2010-07-31 15:34 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Wey-Yi Guy
In-Reply-To: <1280590452-10655-1-git-send-email-wey-yi.w.guy@intel.com>

From: Wey-Yi Guy <wey-yi.w.guy@intel.com>

iwl_set_hw_params() only used by _agn, make it static

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-agn.c  |   18 ++++++++++++++++++
 drivers/net/wireless/iwlwifi/iwl-core.c |   19 -------------------
 drivers/net/wireless/iwlwifi/iwl-core.h |    1 -
 3 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index fcbc42c..32fdc5a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3979,6 +3979,24 @@ static void iwl_hw_detect(struct iwl_priv *priv)
 	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
 }
 
+static int iwl_set_hw_params(struct iwl_priv *priv)
+{
+	priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
+	priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
+	if (priv->cfg->mod_params->amsdu_size_8K)
+		priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
+	else
+		priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
+
+	priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
+
+	if (priv->cfg->mod_params->disable_11n)
+		priv->cfg->sku &= ~IWL_SKU_N;
+
+	/* Device-specific setup */
+	return priv->cfg->ops->lib->set_hw_params(priv);
+}
+
 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int err = 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 5af5e23..78d8eb8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1348,25 +1348,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(iwl_configure_filter);
 
-int iwl_set_hw_params(struct iwl_priv *priv)
-{
-	priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
-	priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
-	if (priv->cfg->mod_params->amsdu_size_8K)
-		priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
-	else
-		priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
-
-	priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
-
-	if (priv->cfg->mod_params->disable_11n)
-		priv->cfg->sku &= ~IWL_SKU_N;
-
-	/* Device-specific setup */
-	return priv->cfg->ops->lib->set_hw_params(priv);
-}
-EXPORT_SYMBOL(iwl_set_hw_params);
-
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 {
 	int ret = 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 4c3bf4d..a166f3a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -382,7 +382,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv);
 void iwl_configure_filter(struct ieee80211_hw *hw,
 			  unsigned int changed_flags,
 			  unsigned int *total_flags, u64 multicast);
-int iwl_set_hw_params(struct iwl_priv *priv);
 void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif);
 void iwl_bss_info_changed(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH -next] iwlwifi: make scan workqueue functions static
From: Guy, Wey-Yi @ 2010-07-31 15:36 UTC (permalink / raw)
  To: Stanislaw Gruszka
  Cc: John W. Linville, Chatre, Reinette,
	linux-wireless@vger.kernel.org
In-Reply-To: <20100730164108.6270e76f@dhcp-lab-109.englab.brq.redhat.com>

Hi Gruszka,

On Fri, 2010-07-30 at 07:41 -0700, Stanislaw Gruszka wrote:
> We do not need export iwl_bg.*scan.*() functions just for initialize
> workqueue in other module. Making that functions static helps with
> iwl-scan.c code review a bit.
> 
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
> ---
>  drivers/net/wireless/iwlwifi/iwl-core.h     |    4 ----
>  drivers/net/wireless/iwlwifi/iwl-scan.c     |   12 ++++--------
>  drivers/net/wireless/iwlwifi/iwl3945-base.c |    6 ++----
>  3 files changed, 6 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
> index e9d23f2..fe8f704 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-core.h
> +++ b/drivers/net/wireless/iwlwifi/iwl-core.h
> @@ -528,7 +528,6 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
>  int iwl_mac_hw_scan(struct ieee80211_hw *hw,
>  		    struct ieee80211_vif *vif,
>  		    struct cfg80211_scan_request *req);
> -void iwl_bg_start_internal_scan(struct work_struct *work);
>  void iwl_internal_short_hw_scan(struct iwl_priv *priv);
>  int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
>  u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
> @@ -540,9 +539,6 @@ u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
>  u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
>  			       enum ieee80211_band band,
>  			       struct ieee80211_vif *vif);
> -void iwl_bg_scan_check(struct work_struct *data);
> -void iwl_bg_abort_scan(struct work_struct *work);
> -void iwl_bg_scan_completed(struct work_struct *work);
>  void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
>  
>  /* For faster active scanning, scan will move to the next channel if fewer than
> diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
> index b0c6b04..247e4c3 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-scan.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
> @@ -378,7 +378,7 @@ void iwl_internal_short_hw_scan(struct iwl_priv *priv)
>  	queue_work(priv->workqueue, &priv->start_internal_scan);
>  }
>  
> -void iwl_bg_start_internal_scan(struct work_struct *work)
> +static void iwl_bg_start_internal_scan(struct work_struct *work)
>  {
>  	struct iwl_priv *priv =
>  		container_of(work, struct iwl_priv, start_internal_scan);
> @@ -418,9 +418,8 @@ void iwl_bg_start_internal_scan(struct work_struct *work)
>   unlock:
>  	mutex_unlock(&priv->mutex);
>  }
> -EXPORT_SYMBOL(iwl_bg_start_internal_scan);
>  
> -void iwl_bg_scan_check(struct work_struct *data)
> +static void iwl_bg_scan_check(struct work_struct *data)
>  {
>  	struct iwl_priv *priv =
>  	    container_of(data, struct iwl_priv, scan_check.work);
> @@ -439,7 +438,6 @@ void iwl_bg_scan_check(struct work_struct *data)
>  	}
>  	mutex_unlock(&priv->mutex);
>  }
> -EXPORT_SYMBOL(iwl_bg_scan_check);
>  
>  /**
>   * iwl_fill_probe_req - fill in all required fields and IE for probe request
> @@ -489,7 +487,7 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
>  }
>  EXPORT_SYMBOL(iwl_fill_probe_req);
>  
> -void iwl_bg_abort_scan(struct work_struct *work)
> +static void iwl_bg_abort_scan(struct work_struct *work)
>  {
>  	struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
>  
> @@ -504,9 +502,8 @@ void iwl_bg_abort_scan(struct work_struct *work)
>  		iwl_send_scan_abort(priv);
>  	mutex_unlock(&priv->mutex);
>  }
> -EXPORT_SYMBOL(iwl_bg_abort_scan);
>  
> -void iwl_bg_scan_completed(struct work_struct *work)
> +static void iwl_bg_scan_completed(struct work_struct *work)
>  {
>  	struct iwl_priv *priv =
>  	    container_of(work, struct iwl_priv, scan_completed);
> @@ -555,7 +552,6 @@ void iwl_bg_scan_completed(struct work_struct *work)
>  	if (!internal)
>  		ieee80211_scan_completed(priv->hw, false);
>  }
> -EXPORT_SYMBOL(iwl_bg_scan_completed);
>  
>  void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
>  {
> diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> index d24eb47..f590753 100644
> --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
> +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
> @@ -3739,10 +3739,8 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
>  	INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
>  	INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
>  	INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
> -	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
> -	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
> -	INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
> -	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
> +
> +	iwl_setup_scan_deferred_work(priv);
>  
>  	iwl3945_hw_setup_deferred_work(priv);

It make sense, thanks very much!

Wey



^ permalink raw reply

* Re: Issues with ath9k dropping connectivity - now no connectivity
From: Norman Henderson @ 2010-07-31 17:51 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <AANLkTinakXaO7Ba7ThhBRCDhn9GuWE433LTHSdMAzL-x@mail.gmail.com>

Felix, in case anyone else has the same problem, your suggestion was
correct. I installed the 2.6.32 kernel backport for Debian Lenny (from
backports.org), built the latest daily "bleeding edge" compat-wireless
from wireless.kernel.org and built the development version of hostapd
(0.7.2). It wasn't as scary as I expected; the only significant
complication was with nl80211 when building hostapd, and this was
resolved by removing CONFIG_DRIVER_NL80211=y from hostapd.config.

Everything seems to be completely stable, including with eth0 and wlan0 bridged.

Thanks for your help!

- Norm

> On Sat, Jul 10, 2010 at 21:21, Felix Fietkau <nbd@openwrt.org> wrote:
>>
>> On 2010-07-10 9:40 PM, Norman Henderson wrote:
>> > Thanks very much Felix for the quick comment. I'll follow up on it
>> > over the next few days as I get time to move to "bleeding edge"
>> > (something I've sworn from my youth to never do...).
>> >
>> > However I guess I was more concerned about the regression from an
>> > environment that worked (with disconnections) to one that doesn't
>> > connect at all - is that just the luck of the draw or did I do
>> > something stupid? (more precisely, what was it that I did stupid,
>> > because that's inevitably true :~
>> No idea if it was a configuration error or if it broke somewhere. To be
>> honest, I stopped caring about AP mode in old kernels completely,
>> because of the large number of known bugs that are fixed in newer versions.
>>
>> - Felix
>
> ==================================
> Original message:
>
> Hi,
>
> I'm a bit new to all of this - here's the short story. I would
> appreciate any help available!
>
> I was building a WAP using a PC Engines ALIX board (AMD Geode LX800),
> DNMA92 wireless card (Atheros 92xx) and Voyage Linux (based on Debian
> Lenny, 2.6.30 kernel with hostapd 0.6.9 and libnl1.1). It was all
> working but, the wireless card would drop connectivity for no apparent
> reason after an undetermined time (minutes to hours). Stations (Win or
> cellphone) would no longer see it at all, as if it was no longer
> transmitting.
>
> The Voyage maintainer advised that ath9k isn't that stable at 2.6.30.
> So, I upgraded the kernel to 2.6.32 using the Debian Lenny backport. I
> then installed the "stable" compat-wireless, 2.6.32.16.
>
> Hostapd appears to start OK. However, the wireless SSID is only
> visible to the Windows clients for a short time - seconds/minutes -
> and they aren't able to connect. There were no errors in the hostapd
> startup and it does its key rotations periodically. All that's logged
> from hostapd -dd during the actual time that the Win clients can see
> it and are trying to connect is:
> 1278785975.350851: STA 00:13:02:be:7b:f9 sent probe request for broadcast SSID
> 1278785975.353034: MGMT (TX callback) ACK
> 1278785975.353073: mgmt::proberesp cb
> (repeated a few times)
>
> The Win7 station used to connect automatically but now doesn't and
> when I click "connect" it fails and shortly thereafter the SSID
> disappears from the list.
>
> Nothing in /var/log. iw phy phy0 info and iw dev wlan0 info appear to
> report sensible info as does iwconfig.
>
> During boot I do get messages about "VIA Padlock Hash Engine not detected" and
> modprobe: FATAL: Error inserting padlock_sha
> (/lib/modules/2.6.32-bpo.5-
> 686/kern...): No such device
> From googling it's not clear to me at least whether this is relevant.
>
> Suggestions? What further diagnostics could I do?
>
> Thanks,
> Norm Henderson

^ permalink raw reply

* Re: [PATCH 1/2] ath9k_htc: Add AP mode to supported modes
From: Sujith @ 2010-07-31 18:26 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Pavel Roskin, linville@tuxdriver.com,
	linux-wireless@vger.kernel.org
In-Reply-To: <87pqy4dq10.fsf@purkki.adurom.net>

Kalle Valo wrote:
> Sorry for a late reply, I'm really backlogged :)
> 
> > I confirm that the AP mode is working on TP-Link TL-WN422G (0cf3:1006).
> > I tested both patched of the series at once.
> >
> > That's great news!  TL-WN422G has an external antenna, connects over USB
> > and supports AP mode.  Users keep asking about that combination of
> > features.  Now we have an answer :-)
> 
> Cool, this would be really handy for testing wireless clients. Does it
> also support proper multicast/broadcast buffering?

Nope, the firmware lacks CAB queue support, which is required for PS buffering
in Atheros' chipsets. Which is exactly why those patches were dropped. :(

Sujith

^ permalink raw reply

* Re: [PATCH 1/2] ath9k_htc: Add AP mode to supported modes
From: Kalle Valo @ 2010-07-31 19:00 UTC (permalink / raw)
  To: Sujith; +Cc: Pavel Roskin, linville@tuxdriver.com,
	linux-wireless@vger.kernel.org
In-Reply-To: <19540.27325.74223.869026@gargle.gargle.HOWL>

Sujith <Sujith.Manoharan@atheros.com> writes:

> Kalle Valo wrote:
>> 
>> > I confirm that the AP mode is working on TP-Link TL-WN422G (0cf3:1006).
>> > I tested both patched of the series at once.
>> >
>> > That's great news!  TL-WN422G has an external antenna, connects over USB
>> > and supports AP mode.  Users keep asking about that combination of
>> > features.  Now we have an answer :-)
>> 
>> Cool, this would be really handy for testing wireless clients. Does it
>> also support proper multicast/broadcast buffering?
>
> Nope, the firmware lacks CAB queue support, which is required for PS
> buffering in Atheros' chipsets. Which is exactly why those patches
> were dropped. :(

I was just afraid of this. Oh well, AP support, USB and cheap sounded
like an impossible combination :/

Thank you for letting me know.

-- 
Kalle Valo

^ permalink raw reply

* Compat-wireless release for 2010-07-31 is baked
From: Compat-wireless cronjob account @ 2010-07-31 19:02 UTC (permalink / raw)
  To: linux-wireless


compat-wireless code metrics

    494088 - Total upstream lines of code being pulled
      1447 - backport code changes
      1211 - backport code additions
       236 - backport code deletions
      5764 - backport from compat module
      7211 - total backport code
    1.4595 - % of code consists of backport work
      1218 - Crap changes not yet posted
      1179 - Crap additions not yet posted
        39 - Crap deletions not yet posted
    0.2465 - % of crap code

Base tree: linux-next.git
Base tree version: next-20100730
compat-wireless release: compat-wireless-2010-07-13-4-g04898a5

^ permalink raw reply

* Re: iw reg set does not work because udev and crda do not respond to boot-time request.
From: Luis R. Rodriguez @ 2010-07-31 21:05 UTC (permalink / raw)
  To: Daniel Haid; +Cc: linux-wireless, linux-kernel, netdev, Kay Sievers
In-Reply-To: <201007311448.06959.d.haid@gogi.tv>

Netlink / udev folks, please review.

On Sat, Jul 31, 2010 at 5:48 AM, Daniel Haid <d.haid@gogi.tv> wrote:
> Hello,
>
> the driver of my wireless card seems to ask for "US"
> regulatory data during boot, but since udev is not
> running at that point (I think not even the root filesystem
> is mounted) crda does not respond.

CRDA is not the only thing called by the kernel where there would be
an issue due to a delay with udev during bootup to react to a message.
The kernel calls CRDA for udev through kobject_uevent_env(). Uevent
messages are now broadcasted through
netlinknetlink_broadcast_filtered() since the old method of using a
direct call to /sbin/hotplug would lead to many processes being
spawned and in some cases OOM. You can still use this though through
CONFIG_UEVENT_HELPER_PATH which will issue call_usermodehelper()
during early boot on an initramfs for example, if you so need it.

I am not sure though if netlink broadcast messages would be reissued
by the kernel during early boot if no one replied back to the send
message but it is worth looking into. As far as I can tell you would
be the first to notice this. In fact we actually had reports of two
consecutive messages being being sent to userspace when only one was
being sent to userspace so it may indeed be in fact true that messages
are rebroadcasted somehow, I am just not sure so Cc'ing netdev and
lkml.

> The effect is that "iw reg set" does not work, because
> the kernel seems to be still waiting for the "US"
> regulatory data. Running
> COUNTRY="US" crda
> manually once fixes the problem (until the next reboot).

iw reg set will be ignored by net/wireless/reg.c as it is still
waiting for last_request to be processed. It seems in your case the
assumption that the request will be reissued in case udev is running
at early boot is incorrect and we need to further understand exactly
how these messages get queued and perhaps reissued or not.

I considered recently changing the way we handle requests to userspace
to use a completion handler but that would sit idle there for a while
blocking on the reg_mutex... so decided against it. But could take a
look again.

> What is the correct way of solving this? Should udev not
> pick up the request later when it is started?

We need a better understanding of how netlink broadcast messages get
processed during early boot. Right now cfg80211 will drop duplicate
requests or any request while we're still pending for the last one.
Once we find out more details about how netlink broadcast messages get
processed during early boot we can then rework things a bit. In the
meantime can you try using CONFIG_UEVENT_HELPER_PATH during the
initramfs?

  Luis

^ permalink raw reply

* Regulatory domain
From: Sebastien Cayetanot @ 2010-07-31 23:08 UTC (permalink / raw)
  To: linux-wireless

  All,

I have used the CRDA capability using the "iw" tool to set the country code.

When I use the 'iw reg get' command, the return below is diplayed.

country JP:
         (2402 - 2472 @ 40), (N/A, 20)
         (2457 - 2482 @ 20), (N/A, 20)
         (2474 - 2494 @ 20), (N/A, 20), NO-OFDM
         (4910 - 4930 @ 10), (N/A, 23)
         (4910 - 4990 @ 40), (N/A, 23)
         (4930 - 4950 @ 10), (N/A, 23)
         (5030 - 5045 @ 10), (N/A, 23)
         (5030 - 5090 @ 40), (N/A, 23)
         (5050 - 5060 @ 10), (N/A, 23)
         (5170 - 5250 @ 40), (N/A, 20)
         (5250 - 5330 @ 40), (N/A, 20), DFS
         (5490 - 5710 @ 40), (N/A, 23), DFS

I would like to understand exactly what is displayed.

- the number of line (xxx-xxx @ xx), (xx,xx) is equal to the number of 
channel which can be accessed
- What is the meaning of each line and details on each parameter.

Thx and regards


^ permalink raw reply

* virtual access poitns (ath5k/mac80211)
From: Ryszard @ 2010-08-01  1:53 UTC (permalink / raw)
  To: linux-wireless

Hi all,

i'm working on a project that requires i can create multiple access
points on the one bit of hardware.  After an insane amount of googling
and reading the lists the closest i've been able to come up with is
something along the lines of:
iw dev wlan0 interface add vap0 type __ap
iw dev wlan0 interface add vap1 type __ap

then using macchanger to assign unique mac addresses.

I've also seen something from March 2009
(http://lwn.net/Articles/321690/) that hints at the functionality
available with the ath9k which gave me a bit of hope!

My question is, is it possible to create multiple virtual access
points with my hardware ( Atheros Communications Inc. AR5413 802.11abg
) and the ath5k/mac80211 drivers (or is there some other method to
achieve what i'm after) ?  i'm not too fussed about different
channels, but different SSID's and WPA keys are a requirement for the
project.

regs
ryszard

^ permalink raw reply

* Re: Regulatory domain
From: Emmanuel Grumbach @ 2010-08-01  6:08 UTC (permalink / raw)
  To: Sebastien Cayetanot; +Cc: linux-wireless
In-Reply-To: <4C54ACE7.1000205@linux.intel.com>

> country JP:
>        (2402 - 2472 @ 40), (N/A, 20)
>        (2457 - 2482 @ 20), (N/A, 20)
>        (2474 - 2494 @ 20), (N/A, 20), NO-OFDM
>        (4910 - 4930 @ 10), (N/A, 23)
>        (4910 - 4990 @ 40), (N/A, 23)
>        (4930 - 4950 @ 10), (N/A, 23)
>        (5030 - 5045 @ 10), (N/A, 23)
>        (5030 - 5090 @ 40), (N/A, 23)
>        (5050 - 5060 @ 10), (N/A, 23)
>        (5170 - 5250 @ 40), (N/A, 20)
>        (5250 - 5330 @ 40), (N/A, 20), DFS
>        (5490 - 5710 @ 40), (N/A, 23), DFS
>
> I would like to understand exactly what is displayed.
>
> - the number of line (xxx-xxx @ xx), (xx,xx) is equal to the number of channel which can be accessed
> - What is the meaning of each line and details on each parameter.
>

http://wireless.kernel.org/en/developers/Regulatory

(aaaa-bbbb @ c),(n/a, 23), XXX

each line is a range in frequencies (channels that fall between aaaa
and bbbb. c is the channel width (10 Mhz for Japan's narrow channels,
20 Mhz for regular channels and 40 Mhz for wide channels). 23 is the
maximum Tx power e.i.r.p. in db.

^ permalink raw reply

* [PATCH] ath9k_hw: Fix regulatory CTL index usage for AR9003
From: Luis R. Rodriguez @ 2010-08-01  6:25 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Luis R. Rodriguez

AR9003 was not relying on the CTL indexes from the EEPROM for capping the
max output power. The CTL indexes from the EEPROM provide calibrated
limits for output power for each tested and supported frequency. Without
this the device operates at a power level which only conforms to the
transmit spectrum mask as specified by IEEE Annex I.2.3.

The regulatory limit by CRDA is always used but does not provide
calibrated values for optimal performance, specially on band edges.
Using the calibrated data from the EEPROM ensures the device
operates at optimal output power while still ensuring proper
regulatory compliance. The device uses the minimum of these tree
values, the value from CRDA, the calibrated value from CTL indexex,
and the value to conform to the IEEE transmit spectrum mask.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---
 drivers/net/wireless/ath/ath9k/ar9003_eeprom.c |  388 +++++++++++++++++++++++-
 1 files changed, 381 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index ace8d26..b883b17 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -41,6 +41,20 @@
 #define LE16(x) __constant_cpu_to_le16(x)
 #define LE32(x) __constant_cpu_to_le32(x)
 
+/* Local defines to distinguish between extension and control CTL's */
+#define EXT_ADDITIVE (0x8000)
+#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE)
+#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE)
+#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE)
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN     6  /* 10*log10(2)*2 */
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN   9  /* 10*log10(3)*2 */
+#define PWRINCR_3_TO_1_CHAIN      9             /* 10*log(3)*2 */
+#define PWRINCR_3_TO_2_CHAIN      3             /* floor(10*log(3/2)*2) */
+#define PWRINCR_2_TO_1_CHAIN      6             /* 10*log(2)*2 */
+
+#define SUB_NUM_CTL_MODES_AT_5G_40 2    /* excluding HT40, EXT-OFDM */
+#define SUB_NUM_CTL_MODES_AT_2G_40 3    /* excluding HT40, EXT-OFDM, EXT-CCK */
+
 static const struct ar9300_eeprom ar9300_default = {
 	.eepromVersion = 2,
 	.templateVersion = 2,
@@ -609,6 +623,14 @@ static const struct ar9300_eeprom ar9300_default = {
 	 }
 };
 
+static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
+{
+	if (fbin == AR9300_BCHAN_UNUSED)
+		return fbin;
+
+	return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
 static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah)
 {
 	return 0;
@@ -1417,9 +1439,9 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
 #undef POW_SM
 }
 
-static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq)
+static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq,
+					      u8 *targetPowerValT2)
 {
-	u8 targetPowerValT2[ar9300RateSize];
 	/* XXX: hard code for now, need to get from eeprom struct */
 	u8 ht40PowerIncForPdadc = 0;
 	bool is2GHz = false;
@@ -1553,9 +1575,6 @@ static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq)
 			  "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
 		i++;
 	}
-
-	/* Write target power array to registers */
-	ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
 }
 
 static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
@@ -1799,14 +1818,369 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency)
 	return 0;
 }
 
+static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep,
+					   int idx,
+					   int edge,
+					   bool is2GHz)
+{
+	struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
+	struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
+
+	if (is2GHz)
+		return ctl_2g[idx].ctlEdges[edge].tPower;
+	else
+		return ctl_5g[idx].ctlEdges[edge].tPower;
+}
+
+static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
+					     int idx,
+					     unsigned int edge,
+					     u16 freq,
+					     bool is2GHz)
+{
+	struct cal_ctl_data_2g *ctl_2g = eep->ctlPowerData_2G;
+	struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G;
+
+	u8 *ctl_freqbin = is2GHz ?
+		&eep->ctl_freqbin_2G[idx][0] :
+		&eep->ctl_freqbin_5G[idx][0];
+
+	if (is2GHz) {
+		if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq &&
+		    ctl_2g[idx].ctlEdges[edge - 1].flag)
+			return ctl_2g[idx].ctlEdges[edge - 1].tPower;
+	} else {
+		if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq &&
+		    ctl_5g[idx].ctlEdges[edge - 1].flag)
+			return ctl_5g[idx].ctlEdges[edge - 1].tPower;
+	}
+
+	return AR9300_MAX_RATE_POWER;
+}
+
+/*
+ * Find the maximum conformance test limit for the given channel and CTL info
+ */
+static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
+					u16 freq, int idx, bool is2GHz)
+{
+	u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
+	u8 *ctl_freqbin = is2GHz ?
+		&eep->ctl_freqbin_2G[idx][0] :
+		&eep->ctl_freqbin_5G[idx][0];
+	u16 num_edges = is2GHz ?
+		AR9300_NUM_BAND_EDGES_2G : AR9300_NUM_BAND_EDGES_5G;
+	unsigned int edge;
+
+	/* Get the edge power */
+	for (edge = 0;
+	     (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED);
+	     edge++) {
+		/*
+		 * If there's an exact channel match or an inband flag set
+		 * on the lower channel use the given rdEdgePower
+		 */
+		if (freq == ath9k_hw_fbin2freq(ctl_freqbin[edge], is2GHz)) {
+			twiceMaxEdgePower =
+				ar9003_hw_get_direct_edge_power(eep, idx,
+								edge, is2GHz);
+			break;
+		} else if ((edge > 0) &&
+			   (freq < ath9k_hw_fbin2freq(ctl_freqbin[edge],
+						      is2GHz))) {
+			twiceMaxEdgePower =
+				ar9003_hw_get_indirect_edge_power(eep, idx,
+								  edge, freq,
+								  is2GHz);
+			/*
+			 * Leave loop - no more affecting edges possible in
+			 * this monotonic increasing list
+			 */
+			break;
+		}
+	}
+	return twiceMaxEdgePower;
+}
+
+static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
+					       struct ath9k_channel *chan,
+					       u8 *pPwrArray, u16 cfgCtl,
+					       u8 twiceAntennaReduction,
+					       u8 twiceMaxRegulatoryPower,
+					       u16 powerLimit)
+{
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
+	u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
+	static const u16 tpScaleReductionTable[5] = {
+		0, 3, 6, 9, AR9300_MAX_RATE_POWER
+	};
+	int i;
+	int16_t  twiceLargestAntenna;
+	u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+	u16 ctlModesFor11a[] = {
+		CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
+	};
+	u16 ctlModesFor11g[] = {
+		CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
+		CTL_11G_EXT, CTL_2GHT40
+	};
+	u16 numCtlModes, *pCtlMode, ctlMode, freq;
+	struct chan_centers centers;
+	u8 *ctlIndex;
+	u8 ctlNum;
+	u16 twiceMinEdgePower;
+	bool is2ghz = IS_CHAN_2GHZ(chan);
+
+	ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+	/* Compute TxPower reduction due to Antenna Gain */
+	if (is2ghz)
+		twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
+	else
+		twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
+
+	twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
+				twiceLargestAntenna, 0);
+
+	/*
+	 * scaledPower is the minimum of the user input power level
+	 * and the regulatory allowed power level
+	 */
+	maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+	if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
+		maxRegAllowedPower -=
+			(tpScaleReductionTable[(regulatory->tp_scale)] * 2);
+	}
+
+	scaledPower = min(powerLimit, maxRegAllowedPower);
+
+	/*
+	 * Reduce scaled Power by number of chains active to get
+	 * to per chain tx power level
+	 */
+	switch (ar5416_get_ntxchains(ah->txchainmask)) {
+	case 1:
+		break;
+	case 2:
+		scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+		break;
+	case 3:
+		scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+		break;
+	}
+
+	scaledPower = max((u16)0, scaledPower);
+
+	/*
+	 * Get target powers from EEPROM - our baseline for TX Power
+	 */
+	if (is2ghz) {
+		/* Setup for CTL modes */
+		/* CTL_11B, CTL_11G, CTL_2GHT20 */
+		numCtlModes =
+			ARRAY_SIZE(ctlModesFor11g) -
+				   SUB_NUM_CTL_MODES_AT_2G_40;
+		pCtlMode = ctlModesFor11g;
+		if (IS_CHAN_HT40(chan))
+			/* All 2G CTL's */
+			numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+	} else {
+		/* Setup for CTL modes */
+		/* CTL_11A, CTL_5GHT20 */
+		numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
+					 SUB_NUM_CTL_MODES_AT_5G_40;
+		pCtlMode = ctlModesFor11a;
+		if (IS_CHAN_HT40(chan))
+			/* All 5G CTL's */
+			numCtlModes = ARRAY_SIZE(ctlModesFor11a);
+	}
+
+	/*
+	 * For MIMO, need to apply regulatory caps individually across
+	 * dynamically running modes: CCK, OFDM, HT20, HT40
+	 *
+	 * The outer loop walks through each possible applicable runtime mode.
+	 * The inner loop walks through each ctlIndex entry in EEPROM.
+	 * The ctl value is encoded as [7:4] == test group, [3:0] == test mode.
+	 */
+	for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+		bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+			(pCtlMode[ctlMode] == CTL_2GHT40);
+		if (isHt40CtlMode)
+			freq = centers.synth_center;
+		else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+			freq = centers.ext_center;
+		else
+			freq = centers.ctl_center;
+
+		ath_print(common, ATH_DBG_REGULATORY,
+			  "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
+			  "EXT_ADDITIVE %d\n",
+			  ctlMode, numCtlModes, isHt40CtlMode,
+			  (pCtlMode[ctlMode] & EXT_ADDITIVE));
+
+		/* walk through each CTL index stored in EEPROM */
+		if (is2ghz) {
+			ctlIndex = pEepData->ctlIndex_2G;
+			ctlNum = AR9300_NUM_CTLS_2G;
+		} else {
+			ctlIndex = pEepData->ctlIndex_5G;
+			ctlNum = AR9300_NUM_CTLS_5G;
+		}
+
+		for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) {
+			ath_print(common, ATH_DBG_REGULATORY,
+				  "LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
+				  "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
+				  "chan %dn",
+				  i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i],
+				  chan->channel);
+
+				/*
+				 * compare test group from regulatory
+				 * channel list with test mode from pCtlMode
+				 * list
+				 */
+				if ((((cfgCtl & ~CTL_MODE_M) |
+				       (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+					ctlIndex[i]) ||
+				    (((cfgCtl & ~CTL_MODE_M) |
+				       (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+				     ((ctlIndex[i] & CTL_MODE_M) |
+				       SD_NO_CTL))) {
+					twiceMinEdgePower =
+					  ar9003_hw_get_max_edge_power(pEepData,
+								       freq, i,
+								       is2ghz);
+
+					if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
+						/*
+						 * Find the minimum of all CTL
+						 * edge powers that apply to
+						 * this channel
+						 */
+						twiceMaxEdgePower =
+							min(twiceMaxEdgePower,
+							    twiceMinEdgePower);
+						else {
+							/* specific */
+							twiceMaxEdgePower =
+							  twiceMinEdgePower;
+							break;
+						}
+				}
+			}
+
+			minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
+
+			ath_print(common, ATH_DBG_REGULATORY,
+				  "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d "
+				  "sP %d minCtlPwr %d\n",
+				  ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
+				  scaledPower, minCtlPower);
+
+			/* Apply ctl mode to correct target power set */
+			switch (pCtlMode[ctlMode]) {
+			case CTL_11B:
+				for (i = ALL_TARGET_LEGACY_1L_5L;
+				     i <= ALL_TARGET_LEGACY_11S; i++)
+					pPwrArray[i] =
+					  (u8)min((u16)pPwrArray[i],
+						  minCtlPower);
+				break;
+			case CTL_11A:
+			case CTL_11G:
+				for (i = ALL_TARGET_LEGACY_6_24;
+				     i <= ALL_TARGET_LEGACY_54; i++)
+					pPwrArray[i] =
+					  (u8)min((u16)pPwrArray[i],
+						  minCtlPower);
+				break;
+			case CTL_5GHT20:
+			case CTL_2GHT20:
+				for (i = ALL_TARGET_HT20_0_8_16;
+				     i <= ALL_TARGET_HT20_21; i++)
+					pPwrArray[i] =
+					  (u8)min((u16)pPwrArray[i],
+						  minCtlPower);
+				pPwrArray[ALL_TARGET_HT20_22] =
+				  (u8)min((u16)pPwrArray[ALL_TARGET_HT20_22],
+					  minCtlPower);
+				pPwrArray[ALL_TARGET_HT20_23] =
+				  (u8)min((u16)pPwrArray[ALL_TARGET_HT20_23],
+					   minCtlPower);
+				break;
+			case CTL_5GHT40:
+			case CTL_2GHT40:
+				for (i = ALL_TARGET_HT40_0_8_16;
+				     i <= ALL_TARGET_HT40_23; i++)
+					pPwrArray[i] =
+					  (u8)min((u16)pPwrArray[i],
+						  minCtlPower);
+				break;
+			default:
+			    break;
+			}
+	} /* end ctl mode checking */
+}
+
 static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
 					struct ath9k_channel *chan, u16 cfgCtl,
 					u8 twiceAntennaReduction,
 					u8 twiceMaxRegulatoryPower,
 					u8 powerLimit)
 {
-	ah->txpower_limit = powerLimit;
-	ar9003_hw_set_target_power_eeprom(ah, chan->channel);
+	struct ath_common *common = ath9k_hw_common(ah);
+	u8 targetPowerValT2[ar9300RateSize];
+	unsigned int i = 0;
+
+	ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2);
+	ar9003_hw_set_power_per_rate_table(ah, chan,
+					   targetPowerValT2, cfgCtl,
+					   twiceAntennaReduction,
+					   twiceMaxRegulatoryPower,
+					   powerLimit);
+
+	while (i < ar9300RateSize) {
+		ath_print(common, ATH_DBG_EEPROM,
+			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
+		i++;
+		ath_print(common, ATH_DBG_EEPROM,
+			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
+		i++;
+		ath_print(common, ATH_DBG_EEPROM,
+			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
+		i++;
+		ath_print(common, ATH_DBG_EEPROM,
+			  "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]);
+		i++;
+	}
+
+	/* Write target power array to registers */
+	ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
+
+	/*
+	 * This is the TX power we send back to driver core,
+	 * and it can use to pass to userspace to display our
+	 * currently configured TX power setting.
+	 *
+	 * Since power is rate dependent, use one of the indices
+	 * from the AR9300_Rates enum to select an entry from
+	 * targetPowerValT2[] to report. Currently returns the
+	 * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
+	 * as CCK power is less interesting (?).
+	 */
+	i = ALL_TARGET_LEGACY_6_24; /* legacy */
+	if (IS_CHAN_HT40(chan))
+		i = ALL_TARGET_HT40_0_8_16; /* ht40 */
+	else if (IS_CHAN_HT20(chan))
+		i = ALL_TARGET_HT20_0_8_16; /* ht20 */
+
+	ah->txpower_limit = targetPowerValT2[i];
+
 	ar9003_hw_calibration_apply(ah, chan->channel);
 }
 
-- 
1.7.0.4


^ permalink raw reply related

* Re: virtual access poitns (ath5k/mac80211)
From: Florian Fainelli @ 2010-08-01  9:37 UTC (permalink / raw)
  To: Ryszard, Patrick McHardy, Ben Greear; +Cc: linux-wireless
In-Reply-To: <AANLkTi=W=vkgb0gM7ZWsBeE79Fe3iabtKFgu2S7N5uLe@mail.gmail.com>

Hi,

Le Sunday 1 August 2010 03:53:13, Ryszard a écrit :
> Hi all,
> 
> i'm working on a project that requires i can create multiple access
> points on the one bit of hardware.  After an insane amount of googling
> and reading the lists the closest i've been able to come up with is
> something along the lines of:
> iw dev wlan0 interface add vap0 type __ap
> iw dev wlan0 interface add vap1 type __ap
> 
> then using macchanger to assign unique mac addresses.
> 
> I've also seen something from March 2009
> (http://lwn.net/Articles/321690/) that hints at the functionality
> available with the ath9k which gave me a bit of hope!
> 
> My question is, is it possible to create multiple virtual access
> points with my hardware ( Atheros Communications Inc. AR5413 802.11abg
> ) and the ath5k/mac80211 drivers (or is there some other method to
> achieve what i'm after) ?  i'm not too fussed about different
> channels, but different SSID's and WPA keys are a requirement for the
> project.

There is support for creating virtual interfaces using iw and ath5k here: 
http://www.candelatech.com/oss/vsta.html

I really wish someone could submit this mainline, unfortunately it is pretty 
hard to isolate the commits in this tree which are implementing virtual 
interfaces support.

Ben, Patrick, could you rebase your patches on top of wireless-testing and 
send them for review/testing?
--
Florian

^ permalink raw reply

* [PATCH 01/11] pcmcia: use pcmica_{read,write}_config_byte
From: Dominik Brodowski @ 2010-08-01 12:59 UTC (permalink / raw)
  To: linux-pcmcia
  Cc: Dominik Brodowski, netdev, linux-wireless, linux-serial,
	Michael Buesch
In-Reply-To: <20100801125749.GA2564@comet.dominikbrodowski.net>

Use pcmcia_read_config_byte and pcmcia_write_config_byte instead
of pcmcia_access_configuration_register.

CC: netdev@vger.kernel.org
CC: linux-wireless@vger.kernel.org
CC: linux-serial@vger.kernel.org
CC: Michael Buesch <mb@bu3sch.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
---
 drivers/net/pcmcia/axnet_cs.c              |    3 +-
 drivers/net/pcmcia/nmclan_cs.c             |   21 ++-----
 drivers/net/pcmcia/xirc2ps_cs.c            |   16 ++---
 drivers/net/wireless/hostap/hostap_cs.c    |   91 ++++++++--------------------
 drivers/net/wireless/orinoco/spectrum_cs.c |   32 +++-------
 drivers/pcmcia/cistpl.c                    |    7 +-
 drivers/pcmcia/cs_internal.h               |    4 +-
 drivers/pcmcia/pcmcia_resource.c           |   72 +++++++++++++---------
 drivers/serial/serial_cs.c                 |    8 +--
 drivers/ssb/pcmcia.c                       |   14 +----
 include/pcmcia/cs.h                        |   12 ----
 include/pcmcia/ds.h                        |    4 +-
 12 files changed, 105 insertions(+), 179 deletions(-)

diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 467fd4b..ee0a6d0 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -378,8 +378,7 @@ static int axnet_config(struct pcmcia_device *link)
     /* Maybe PHY is in power down mode. (PPD_SET = 1) 
        Bit 2 of CCSR is active low. */ 
     if (i == 32) {
-	conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 };
- 	pcmcia_access_configuration_register(link, &reg);
+	pcmcia_write_config_byte(link, CISREG_CCSR, 0x04);
 	for (i = 0; i < 32; i++) {
 	    j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
 	    j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2);
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index c0eacfa..c0d85af 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -757,29 +757,20 @@ static void nmclan_reset(struct net_device *dev)
 
 #if RESET_XILINX
   struct pcmcia_device *link = &lp->link;
-  conf_reg_t reg;
-  u_long OrigCorValue; 
+  u8 OrigCorValue;
 
   /* Save original COR value */
-  reg.Function = 0;
-  reg.Action = CS_READ;
-  reg.Offset = CISREG_COR;
-  reg.Value = 0;
-  pcmcia_access_configuration_register(link, &reg);
-  OrigCorValue = reg.Value;
+  pcmcia_read_config_byte(link, CISREG_COR, &OrigCorValue);
 
   /* Reset Xilinx */
-  reg.Action = CS_WRITE;
-  reg.Offset = CISREG_COR;
-  dev_dbg(&link->dev, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n",
+  dev_dbg(&link->dev, "nmclan_reset: OrigCorValue=0x%x, resetting...\n",
 	OrigCorValue);
-  reg.Value = COR_SOFT_RESET;
-  pcmcia_access_configuration_register(link, &reg);
+  pcmcia_write_config_byte(link, CISREG_COR, COR_SOFT_RESET);
   /* Need to wait for 20 ms for PCMCIA to finish reset. */
 
   /* Restore original COR configuration index */
-  reg.Value = COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK);
-  pcmcia_access_configuration_register(link, &reg);
+  pcmcia_write_config_byte(link, CISREG_COR,
+			  (COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK)));
   /* Xilinx is now completely reset along with the MACE chip. */
   lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
 
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index a7662f0..add6c82 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -869,7 +869,6 @@ xirc2ps_config(struct pcmcia_device * link)
 	goto config_error;
 
     if (local->dingo) {
-	conf_reg_t reg;
 	win_req_t req;
 	memreq_t mem;
 
@@ -878,15 +877,14 @@ xirc2ps_config(struct pcmcia_device * link)
 	 * the base address of the ethernet port (BasePort1) is written
 	 * to the BAR registers of the modem.
 	 */
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_IOBASE_0;
-	reg.Value = link->io.BasePort2 & 0xff;
-	if ((err = pcmcia_access_configuration_register(link, &reg)))
+	err = pcmcia_write_config_byte(link, CISREG_IOBASE_0,
+				link->io.BasePort2 & 0xff);
+	if (err)
 	    goto config_error;
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_IOBASE_1;
-	reg.Value = (link->io.BasePort2 >> 8) & 0xff;
-	if ((err = pcmcia_access_configuration_register(link, &reg)))
+
+	err = pcmcia_write_config_byte(link, CISREG_IOBASE_1,
+				link->io.BasePort2 & 0xff);
+	if (err)
 	    goto config_error;
 
 	/* There is no config entry for the Ethernet part which
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 2f4b6d4..def63bf 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -224,27 +224,18 @@ static int prism2_pccard_card_present(local_info_t *local)
 static void sandisk_set_iobase(local_info_t *local)
 {
 	int res;
-	conf_reg_t reg;
 	struct hostap_cs_priv *hw_priv = local->hw_priv;
 
-	reg.Function = 0;
-	reg.Action = CS_WRITE;
-	reg.Offset = 0x10; /* 0x3f0 IO base 1 */
-	reg.Value = hw_priv->link->io.BasePort1 & 0x00ff;
-	res = pcmcia_access_configuration_register(hw_priv->link,
-						   &reg);
+	res = pcmcia_write_config_byte(hw_priv->link, 0x10,
+				hw_priv->link->io.BasePort1 & 0x00ff);
 	if (res != 0) {
 		printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
 		       " res=%d\n", res);
 	}
 	udelay(10);
 
-	reg.Function = 0;
-	reg.Action = CS_WRITE;
-	reg.Offset = 0x12; /* 0x3f2 IO base 2 */
-	reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8;
-	res = pcmcia_access_configuration_register(hw_priv->link,
-						   &reg);
+	res = pcmcia_write_config_byte(hw_priv->link, 0x12,
+				hw_priv->link->io.BasePort1 & 0x00ff);
 	if (res != 0) {
 		printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
 		       " res=%d\n", res);
@@ -270,7 +261,6 @@ static void sandisk_write_hcr(local_info_t *local, int hcr)
 static int sandisk_enable_wireless(struct net_device *dev)
 {
 	int res, ret = 0;
-	conf_reg_t reg;
 	struct hostap_interface *iface = netdev_priv(dev);
 	local_info_t *local = iface->local;
 	struct hostap_cs_priv *hw_priv = local->hw_priv;
@@ -297,12 +287,8 @@ static int sandisk_enable_wireless(struct net_device *dev)
 	       " - using vendor-specific initialization\n", dev->name);
 	hw_priv->sandisk_connectplus = 1;
 
-	reg.Function = 0;
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_COR;
-	reg.Value = COR_SOFT_RESET;
-	res = pcmcia_access_configuration_register(hw_priv->link,
-						   &reg);
+	res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR,
+				COR_SOFT_RESET);
 	if (res != 0) {
 		printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
 		       dev->name, res);
@@ -310,16 +296,13 @@ static int sandisk_enable_wireless(struct net_device *dev)
 	}
 	mdelay(5);
 
-	reg.Function = 0;
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_COR;
 	/*
 	 * Do not enable interrupts here to avoid some bogus events. Interrupts
 	 * will be enabled during the first cor_sreset call.
 	 */
-	reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA;
-	res = pcmcia_access_configuration_register(hw_priv->link,
-						   &reg);
+	res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR,
+				(COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE |
+					COR_FUNC_ENA));
 	if (res != 0) {
 		printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n",
 		       dev->name, res);
@@ -342,30 +325,23 @@ done:
 static void prism2_pccard_cor_sreset(local_info_t *local)
 {
 	int res;
-	conf_reg_t reg;
+	u8 val;
 	struct hostap_cs_priv *hw_priv = local->hw_priv;
 
 	if (!prism2_pccard_card_present(local))
 	       return;
 
-	reg.Function = 0;
-	reg.Action = CS_READ;
-	reg.Offset = CISREG_COR;
-	reg.Value = 0;
-	res = pcmcia_access_configuration_register(hw_priv->link,
-						   &reg);
+	res = pcmcia_read_config_byte(hw_priv->link, CISREG_COR, &val);
 	if (res != 0) {
 		printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n",
 		       res);
 		return;
 	}
 	printk(KERN_DEBUG "prism2_pccard_cor_sreset: original COR %02x\n",
-	       reg.Value);
+		val);
 
-	reg.Action = CS_WRITE;
-	reg.Value |= COR_SOFT_RESET;
-	res = pcmcia_access_configuration_register(hw_priv->link,
-						   &reg);
+	val |= COR_SOFT_RESET;
+	res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR, val);
 	if (res != 0) {
 		printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n",
 		       res);
@@ -374,11 +350,10 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
 
 	mdelay(hw_priv->sandisk_connectplus ? 5 : 2);
 
-	reg.Value &= ~COR_SOFT_RESET;
+	val &= ~COR_SOFT_RESET;
 	if (hw_priv->sandisk_connectplus)
-		reg.Value |= COR_IREQ_ENA;
-	res = pcmcia_access_configuration_register(hw_priv->link,
-						   &reg);
+		val |= COR_IREQ_ENA;
+	res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR, val);
 	if (res != 0) {
 		printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n",
 		       res);
@@ -395,8 +370,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local)
 static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
 {
 	int res;
-	conf_reg_t reg;
-	int old_cor;
+	u8 old_cor;
 	struct hostap_cs_priv *hw_priv = local->hw_priv;
 
 	if (!prism2_pccard_card_present(local))
@@ -407,25 +381,17 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
 		return;
 	}
 
-	reg.Function = 0;
-	reg.Action = CS_READ;
-	reg.Offset = CISREG_COR;
-	reg.Value = 0;
-	res = pcmcia_access_configuration_register(hw_priv->link,
-						   &reg);
+	res = pcmcia_read_config_byte(hw_priv->link, CISREG_COR, &old_cor);
 	if (res != 0) {
 		printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 "
 		       "(%d)\n", res);
 		return;
 	}
 	printk(KERN_DEBUG "prism2_pccard_genesis_sreset: original COR %02x\n",
-	       reg.Value);
-	old_cor = reg.Value;
+		old_cor);
 
-	reg.Action = CS_WRITE;
-	reg.Value |= COR_SOFT_RESET;
-	res = pcmcia_access_configuration_register(hw_priv->link,
-						   &reg);
+	res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR,
+				old_cor | COR_SOFT_RESET);
 	if (res != 0) {
 		printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 "
 		       "(%d)\n", res);
@@ -435,11 +401,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
 	mdelay(10);
 
 	/* Setup Genesis mode */
-	reg.Action = CS_WRITE;
-	reg.Value = hcr;
-	reg.Offset = CISREG_CCSR;
-	res = pcmcia_access_configuration_register(hw_priv->link,
-						   &reg);
+	res = pcmcia_write_config_byte(hw_priv->link, CISREG_CCSR, hcr);
 	if (res != 0) {
 		printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 "
 		       "(%d)\n", res);
@@ -447,11 +409,8 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr)
 	}
 	mdelay(10);
 
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_COR;
-	reg.Value = old_cor & ~COR_SOFT_RESET;
-	res = pcmcia_access_configuration_register(hw_priv->link,
-						   &reg);
+	res = pcmcia_write_config_byte(hw_priv->link, CISREG_COR,
+				old_cor & ~COR_SOFT_RESET);
 	if (res != 0) {
 		printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 "
 		       "(%d)\n", res);
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index cad30e4..39399cd 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -79,35 +79,27 @@ static int
 spectrum_reset(struct pcmcia_device *link, int idle)
 {
 	int ret;
-	conf_reg_t reg;
-	u_int save_cor;
+	u8 save_cor;
+	u8 ccsr;
 
 	/* Doing it if hardware is gone is guaranteed crash */
 	if (!pcmcia_dev_present(link))
 		return -ENODEV;
 
 	/* Save original COR value */
-	reg.Function = 0;
-	reg.Action = CS_READ;
-	reg.Offset = CISREG_COR;
-	ret = pcmcia_access_configuration_register(link, &reg);
+	ret = pcmcia_read_config_byte(link, CISREG_COR, &save_cor);
 	if (ret)
 		goto failed;
-	save_cor = reg.Value;
 
 	/* Soft-Reset card */
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_COR;
-	reg.Value = (save_cor | COR_SOFT_RESET);
-	ret = pcmcia_access_configuration_register(link, &reg);
+	ret = pcmcia_write_config_byte(link, CISREG_COR,
+				(save_cor | COR_SOFT_RESET));
 	if (ret)
 		goto failed;
 	udelay(1000);
 
 	/* Read CCSR */
-	reg.Action = CS_READ;
-	reg.Offset = CISREG_CCSR;
-	ret = pcmcia_access_configuration_register(link, &reg);
+	ret = pcmcia_read_config_byte(link, CISREG_CCSR, &ccsr);
 	if (ret)
 		goto failed;
 
@@ -115,19 +107,15 @@ spectrum_reset(struct pcmcia_device *link, int idle)
 	 * Start or stop the firmware.  Memory width bit should be
 	 * preserved from the value we've just read.
 	 */
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_CCSR;
-	reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16);
-	ret = pcmcia_access_configuration_register(link, &reg);
+	ccsr = (idle ? HCR_IDLE : HCR_RUN) | (ccsr & HCR_MEM16);
+	ret = pcmcia_write_config_byte(link, CISREG_CCSR, ccsr);
 	if (ret)
 		goto failed;
 	udelay(1000);
 
 	/* Restore original COR configuration index */
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_COR;
-	reg.Value = (save_cor & ~COR_SOFT_RESET);
-	ret = pcmcia_access_configuration_register(link, &reg);
+	ret = pcmcia_write_config_byte(link, CISREG_COR,
+				(save_cor & ~COR_SOFT_RESET));
 	if (ret)
 		goto failed;
 	udelay(1000);
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index ba4a5ac..1733fab 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -209,7 +209,7 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
  * Probably only useful for writing one-byte registers. Must be called
  * with ops_mutex held.
  */
-void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
+int pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 		   u_int len, void *ptr)
 {
 	void __iomem *sys, *end;
@@ -231,7 +231,7 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 				((cis_width) ? MAP_16BIT : 0));
 		if (!sys) {
 			dev_dbg(&s->dev, "could not map memory\n");
-			return; /* FIXME: Error */
+			return -EINVAL;
 		}
 
 		writeb(flags, sys+CISREG_ICTRL0);
@@ -256,7 +256,7 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 			sys = set_cis_map(s, card_offset, flags);
 			if (!sys) {
 				dev_dbg(&s->dev, "could not map memory\n");
-				return; /* FIXME: error */
+				return -EINVAL;
 			}
 
 			end = sys + s->map_size;
@@ -270,6 +270,7 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 			addr = 0;
 		}
 	}
+	return 0;
 }
 
 
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 45e7fd1..cebd40d 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -158,8 +158,8 @@ extern struct bin_attribute pccard_cis_attr;
 
 int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr,
 			u_int addr, u_int len, void *ptr);
-void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr,
-			  u_int addr, u_int len, void *ptr);
+int pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr,
+			u_int addr, u_int len, void *ptr);
 void release_cis_mem(struct pcmcia_socket *s);
 void destroy_cis_cache(struct pcmcia_socket *s);
 int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 2394de4..563750e 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -108,25 +108,25 @@ static void release_io_space(struct pcmcia_socket *s, unsigned int base,
 } /* release_io_space */
 
 
-/** pccard_access_configuration_register
+/**
+ * pcmcia_access_config() - read or write card configuration registers
  *
- * Access_configuration_register() reads and writes configuration
- * registers in attribute memory.  Memory window 0 is reserved for
- * this and the tuple reading services.
+ * pcmcia_access_config() reads and writes configuration registers in
+ * attribute memory.  Memory window 0 is reserved for this and the tuple
+ * reading services. Drivers must use pcmcia_read_config_byte() or
+ * pcmcia_write_config_byte().
  */
-
-int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
-					 conf_reg_t *reg)
+static int pcmcia_access_config(struct pcmcia_device *p_dev,
+				off_t where, u8 *val,
+				int (*accessf) (struct pcmcia_socket *s,
+						int attr, unsigned int addr,
+						unsigned int len, void *ptr))
 {
 	struct pcmcia_socket *s;
 	config_t *c;
 	int addr;
-	u_char val;
 	int ret = 0;
 
-	if (!p_dev || !p_dev->function_config)
-		return -EINVAL;
-
 	s = p_dev->socket;
 
 	mutex_lock(&s->ops_mutex);
@@ -138,26 +138,40 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
 		return -EACCES;
 	}
 
-	addr = (c->ConfigBase + reg->Offset) >> 1;
+	addr = (c->ConfigBase + where) >> 1;
+
+	ret = accessf(s, 1, addr, 1, val);
 
-	switch (reg->Action) {
-	case CS_READ:
-		ret = pcmcia_read_cis_mem(s, 1, addr, 1, &val);
-		reg->Value = val;
-		break;
-	case CS_WRITE:
-		val = reg->Value;
-		pcmcia_write_cis_mem(s, 1, addr, 1, &val);
-		break;
-	default:
-		dev_dbg(&s->dev, "Invalid conf register request\n");
-		ret = -EINVAL;
-		break;
-	}
 	mutex_unlock(&s->ops_mutex);
+
 	return ret;
-} /* pcmcia_access_configuration_register */
-EXPORT_SYMBOL(pcmcia_access_configuration_register);
+} /* pcmcia_access_config */
+
+
+/**
+ * pcmcia_read_config_byte() - read a byte from a card configuration register
+ *
+ * pcmcia_read_config_byte() reads a byte from a configuration register in
+ * attribute memory.
+ */
+int pcmcia_read_config_byte(struct pcmcia_device *p_dev, off_t where, u8 *val)
+{
+	return pcmcia_access_config(p_dev, where, val, pcmcia_read_cis_mem);
+}
+EXPORT_SYMBOL(pcmcia_read_config_byte);
+
+
+/**
+ * pcmcia_write_config_byte() - write a byte to a card configuration register
+ *
+ * pcmcia_write_config_byte() writes a byte to a configuration register in
+ * attribute memory.
+ */
+int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val)
+{
+	return pcmcia_access_config(p_dev, where, &val, pcmcia_write_cis_mem);
+}
+EXPORT_SYMBOL(pcmcia_write_config_byte);
 
 
 int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 2b99c7b..2be8b10 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -114,16 +114,14 @@ static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_
 
 static int quirk_post_ibm(struct pcmcia_device *link)
 {
-	conf_reg_t reg = { 0, CS_READ, 0x800, 0 };
+	u8 val;
 	int ret;
 
-	ret = pcmcia_access_configuration_register(link, &reg);
+	ret = pcmcia_read_config_byte(link, 0x800, &val);
 	if (ret)
 		goto failed;
 
-	reg.Action = CS_WRITE;
-	reg.Value = reg.Value | 1;
-	ret = pcmcia_access_configuration_register(link, &reg);
+	ret = pcmcia_write_config_byte(link, 0x800, val | 1);
 	if (ret)
 		goto failed;
 	return 0;
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index 2152030..526682d 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -71,14 +71,9 @@
 /* Write to a PCMCIA configuration register. */
 static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)
 {
-	conf_reg_t reg;
 	int res;
 
-	memset(&reg, 0, sizeof(reg));
-	reg.Offset = offset;
-	reg.Action = CS_WRITE;
-	reg.Value = value;
-	res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
+	res = pcmcia_write_config_byte(bus->host_pcmcia, offset, value);
 	if (unlikely(res != 0))
 		return -EBUSY;
 
@@ -88,16 +83,11 @@ static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)
 /* Read from a PCMCIA configuration register. */
 static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)
 {
-	conf_reg_t reg;
 	int res;
 
-	memset(&reg, 0, sizeof(reg));
-	reg.Offset = offset;
-	reg.Action = CS_READ;
-	res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
+	res = pcmcia_read_config_byte(bus->host_pcmcia, offset, value);
 	if (unlikely(res != 0))
 		return -EBUSY;
-	*value = reg.Value;
 
 	return 0;
 }
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index c78d9b1..64e853d 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -19,18 +19,6 @@
 #include <linux/interrupt.h>
 #endif
 
-/* For AccessConfigurationRegister */
-typedef struct conf_reg_t {
-    u_char	Function;
-    u_int	Action;
-    off_t	Offset;
-    u_int	Value;
-} conf_reg_t;
-
-/* Actions */
-#define CS_READ		1
-#define CS_WRITE	2
-
 /* for AdjustResourceInfo */
 /* Action field */
 #define REMOVE_MANAGED_RESOURCE		1
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index e614aa0..d494ce4 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -174,8 +174,8 @@ struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *p_dev);
 int pcmcia_reset_card(struct pcmcia_socket *skt);
 
 /* CIS config */
-int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
-					 conf_reg_t *reg);
+int pcmcia_read_config_byte(struct pcmcia_device *p_dev, off_t where, u8 *val);
+int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val);
 
 /* device configuration */
 int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req);
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 07/11] pcmcia: remove memreq_t
From: Dominik Brodowski @ 2010-08-01 12:59 UTC (permalink / raw)
  To: linux-pcmcia
  Cc: Dominik Brodowski, netdev, linux-wireless, linux-ide, linux-usb,
	laforge, linux-mtd, linux-bluetooth, alsa-devel, linux-serial,
	Michael Buesch
In-Reply-To: <20100801125749.GA2564@comet.dominikbrodowski.net>

Page already had to be set to 0; Offset can easily be passed as
parameter to pcmcia_map_mem_page.

CC: netdev@vger.kernel.org
CC: linux-wireless@vger.kernel.org
CC: linux-ide@vger.kernel.org
CC: linux-usb@vger.kernel.org
CC: laforge@gnumonks.org
CC: linux-mtd@lists.infradead.org
CC: linux-bluetooth@vger.kernel.org
CC: alsa-devel@alsa-project.org
CC: linux-serial@vger.kernel.org
CC: Michael Buesch <mb@bu3sch.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
---
 drivers/char/pcmcia/ipwireless/main.c         |   14 ++------------
 drivers/isdn/hisax/sedlbauer_cs.c             |    7 +++----
 drivers/mtd/maps/pcmciamtd.c                  |   13 ++++++-------
 drivers/net/pcmcia/fmvj18x_cs.c               |   10 ++--------
 drivers/net/pcmcia/ibmtr_cs.c                 |   11 +++--------
 drivers/net/pcmcia/pcnet_cs.c                 |   14 ++++----------
 drivers/net/pcmcia/smc91c92_cs.c              |    9 +++------
 drivers/net/pcmcia/xirc2ps_cs.c               |    5 +----
 drivers/net/wireless/airo_cs.c                |    6 ++----
 drivers/net/wireless/b43/pcmcia.c             |    5 +----
 drivers/net/wireless/ray_cs.c                 |   13 +++----------
 drivers/pcmcia/pcmcia_resource.c              |    9 +++------
 drivers/scsi/pcmcia/nsp_cs.c                  |    5 ++---
 drivers/staging/comedi/drivers/ni_daq_700.c   |    6 ++----
 drivers/staging/comedi/drivers/ni_daq_dio24.c |    6 ++----
 drivers/staging/comedi/drivers/ni_labpc_cs.c  |    6 ++----
 include/pcmcia/cs.h                           |    6 ------
 include/pcmcia/ds.h                           |    2 +-
 18 files changed, 42 insertions(+), 105 deletions(-)

diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 5f87b9f..6c4aa4b 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -84,8 +84,6 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
 {
 	struct ipw_dev *ipw = priv_data;
 	struct resource *io_resource;
-	memreq_t memreq_attr_memory;
-	memreq_t memreq_common_memory;
 	int ret;
 
 	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
@@ -121,11 +119,8 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
 	if (ret != 0)
 		goto exit1;
 
-	memreq_common_memory.CardOffset = cfg->mem.win[0].card_addr;
-	memreq_common_memory.Page = 0;
-
 	ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory,
-				&memreq_common_memory);
+				cfg->mem.win[0].card_addr);
 
 	if (ret != 0)
 		goto exit2;
@@ -150,12 +145,7 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
 	if (ret != 0)
 		goto exit2;
 
-	memreq_attr_memory.CardOffset = 0;
-	memreq_attr_memory.Page = 0;
-
-	ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory,
-				&memreq_attr_memory);
-
+	ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, 0);
 	if (ret != 0)
 		goto exit3;
 
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 4755eb4..0b06dbb 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -232,7 +232,6 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev,
 	*/
 	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
 		cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
-		memreq_t map;
 		req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
 		req->Attributes |= WIN_ENABLE;
 		req->Base = mem->win[0].host_addr;
@@ -240,9 +239,9 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev,
 		req->AccessSpeed = 0;
 		if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0)
 			return -ENODEV;
-		map.Page = 0;
-		map.CardOffset = mem->win[0].card_addr;
-		if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0)
+
+		if (pcmcia_map_mem_page(p_dev, p_dev->win,
+						mem->win[0].card_addr) != 0)
 			return -ENODEV;
 	}
 	return 0;
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 7948816..f97463e 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -102,7 +102,7 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
 {
 	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 	window_handle_t win = (window_handle_t)map->map_priv_2;
-	memreq_t mrq;
+	unsigned int offset;
 	int ret;
 
 	if (!pcmcia_dev_present(dev->p_dev)) {
@@ -110,15 +110,14 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
 		return 0;
 	}
 
-	mrq.CardOffset = to & ~(dev->win_size-1);
-	if(mrq.CardOffset != dev->offset) {
+	offset = to & ~(dev->win_size-1);
+	if (offset != dev->offset) {
 		DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",
-		      dev->offset, mrq.CardOffset);
-		mrq.Page = 0;
-		ret = pcmcia_map_mem_page(dev->p_dev, win, &mrq);
+		      dev->offset, offset);
+		ret = pcmcia_map_mem_page(dev->p_dev, win, offset);
 		if (ret != 0)
 			return NULL;
-		dev->offset = mrq.CardOffset;
+		dev->offset = offset;
 	}
 	return dev->win_base + (to & (dev->win_size-1));
 }
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 6993044..98fffb0 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -545,7 +545,6 @@ failed:
 static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 {
     win_req_t req;
-    memreq_t mem;
     u_char __iomem *base;
     int i, j;
 
@@ -558,9 +557,7 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 	return -1;
 
     base = ioremap(req.Base, req.Size);
-    mem.Page = 0;
-    mem.CardOffset = 0;
-    pcmcia_map_mem_page(link, link->win, &mem);
+    pcmcia_map_mem_page(link, link->win, 0);
 
     /*
      *  MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
@@ -594,7 +591,6 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 {
     win_req_t req;
-    memreq_t mem;
     int i;
     struct net_device *dev = link->priv;
     unsigned int ioaddr;
@@ -614,9 +610,7 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 	return -1;
     }
 
-    mem.Page = 0;
-    mem.CardOffset = 0;
-    i = pcmcia_map_mem_page(link, link->win, &mem);
+    i = pcmcia_map_mem_page(link, link->win, 0);
     if (i != 0) {
 	iounmap(lp->base);
 	lp->base = NULL;
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index 3fd8595..c0b3cdd 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -211,7 +211,6 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
     struct net_device *dev = info->dev;
     struct tok_info *ti = netdev_priv(dev);
     win_req_t req;
-    memreq_t mem;
     int i, ret;
 
     dev_dbg(&link->dev, "ibmtr_config\n");
@@ -250,9 +249,7 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
     if (ret)
 	    goto failed;
 
-    mem.CardOffset = mmiobase;
-    mem.Page = 0;
-    ret = pcmcia_map_mem_page(link, link->win, &mem);
+    ret = pcmcia_map_mem_page(link, link->win, mmiobase);
     if (ret)
 	    goto failed;
     ti->mmio = ioremap(req.Base, req.Size);
@@ -267,13 +264,11 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
     if (ret)
 	    goto failed;
 
-    mem.CardOffset = srambase;
-    mem.Page = 0;
-    ret = pcmcia_map_mem_page(link, info->sram_win_handle, &mem);
+    ret = pcmcia_map_mem_page(link, info->sram_win_handle, srambase);
     if (ret)
 	    goto failed;
 
-    ti->sram_base = mem.CardOffset >> 12;
+    ti->sram_base = srambase >> 12;
     ti->sram_virt = ioremap(req.Base, req.Size);
     ti->sram_phys = req.Base;
 
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 9c5fc9d..c3edfe4 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -301,7 +301,6 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     win_req_t req;
-    memreq_t mem;
     u_char __iomem *base, *virt;
     int i, j;
 
@@ -314,10 +313,8 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
 	return NULL;
 
     virt = ioremap(req.Base, req.Size);
-    mem.Page = 0;
     for (i = 0; i < NR_INFO; i++) {
-	mem.CardOffset = hw_info[i].offset & ~(req.Size-1);
-	pcmcia_map_mem_page(link, link->win, &mem);
+	pcmcia_map_mem_page(link, link->win, hw_info[i].offset & ~(req.Size-1));
 	base = &virt[hw_info[i].offset & (req.Size-1)];
 	if ((readb(base+0) == hw_info[i].a0) &&
 	    (readb(base+2) == hw_info[i].a1) &&
@@ -1463,7 +1460,6 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
     struct net_device *dev = link->priv;
     pcnet_dev_t *info = PRIV(dev);
     win_req_t req;
-    memreq_t mem;
     int i, window_size, offset, ret;
 
     window_size = (stop_pg - start_pg) << 8;
@@ -1482,11 +1478,9 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
     if (ret)
 	    goto failed;
 
-    mem.CardOffset = (start_pg << 8) + cm_offset;
-    offset = mem.CardOffset % window_size;
-    mem.CardOffset -= offset;
-    mem.Page = 0;
-    ret = pcmcia_map_mem_page(link, link->win, &mem);
+    offset = (start_pg << 8) + cm_offset;
+    offset -= offset % window_size;
+    ret = pcmcia_map_mem_page(link, link->win, offset);
     if (ret)
 	    goto failed;
 
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index a5e4779..377367d 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -443,7 +443,7 @@ static int mhz_mfc_config(struct pcmcia_device *link)
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
     win_req_t req;
-    memreq_t mem;
+    unsigned int offset;
     int i;
 
     link->conf.Attributes |= CONF_ENABLE_SPKR;
@@ -467,11 +467,8 @@ static int mhz_mfc_config(struct pcmcia_device *link)
 	    return -ENODEV;
 
     smc->base = ioremap(req.Base, req.Size);
-    mem.CardOffset = mem.Page = 0;
-    if (smc->manfid == MANFID_MOTOROLA)
-	mem.CardOffset = link->conf.ConfigBase;
-    i = pcmcia_map_mem_page(link, link->win, &mem);
-
+    offset = (smc->manfid == MANFID_MOTOROLA) ? link->conf.ConfigBase : 0;
+    i = pcmcia_map_mem_page(link, link->win, offset);
     if ((i == 0) &&
 	(smc->manfid == MANFID_MEGAHERTZ) &&
 	(smc->cardid == PRODID_MEGAHERTZ_EM3288))
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index e051d3a..931d28e 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -870,7 +870,6 @@ xirc2ps_config(struct pcmcia_device * link)
 
     if (local->dingo) {
 	win_req_t req;
-	memreq_t mem;
 
 	/* Reset the modem's BAR to the correct value
 	 * This is necessary because in the RequestConfiguration call,
@@ -898,9 +897,7 @@ xirc2ps_config(struct pcmcia_device * link)
 	    goto config_error;
 
 	local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;
-	mem.CardOffset = 0x0;
-	mem.Page = 0;
-	if ((err = pcmcia_map_mem_page(link, link->win, &mem)))
+	if ((err = pcmcia_map_mem_page(link, link->win, 0)))
 	    goto config_error;
 
 	/* Setup the CCRs; there are no infos in the CIS about the Ethernet
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index d241b4a..d47672c 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -207,16 +207,14 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev,
 	*/
 	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
 		cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
-		memreq_t map;
 		req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
 		req->Base = mem->win[0].host_addr;
 		req->Size = mem->win[0].len;
 		req->AccessSpeed = 0;
 		if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0)
 			return -ENODEV;
-		map.Page = 0;
-		map.CardOffset = mem->win[0].card_addr;
-		if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0)
+		if (pcmcia_map_mem_page(p_dev, p_dev->win,
+						mem->win[0].card_addr) != 0)
 			return -ENODEV;
 	}
 	/* If we got this far, we're cool! */
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index 7c9af82..ffe1f89 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -64,7 +64,6 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 {
 	struct ssb_bus *ssb;
 	win_req_t win;
-	memreq_t mem;
 	int err = -ENOMEM;
 	int res = 0;
 
@@ -87,9 +86,7 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 	if (res != 0)
 		goto err_kfree_ssb;
 
-	mem.CardOffset = 0;
-	mem.Page = 0;
-	res = pcmcia_map_mem_page(dev, dev->win, &mem);
+	res = pcmcia_map_mem_page(dev, dev->win, 0);
 	if (res != 0)
 		goto err_disable;
 
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index b83d5ef..7eb339a 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -393,7 +393,6 @@ static int ray_config(struct pcmcia_device *link)
 	int ret = 0;
 	int i;
 	win_req_t req;
-	memreq_t mem;
 	struct net_device *dev = (struct net_device *)link->priv;
 	ray_dev_t *local = netdev_priv(dev);
 
@@ -430,9 +429,7 @@ static int ray_config(struct pcmcia_device *link)
 	ret = pcmcia_request_window(link, &req, &link->win);
 	if (ret)
 		goto failed;
-	mem.CardOffset = 0x0000;
-	mem.Page = 0;
-	ret = pcmcia_map_mem_page(link, link->win, &mem);
+	ret = pcmcia_map_mem_page(link, link->win, 0);
 	if (ret)
 		goto failed;
 	local->sram = ioremap(req.Base, req.Size);
@@ -446,9 +443,7 @@ static int ray_config(struct pcmcia_device *link)
 	ret = pcmcia_request_window(link, &req, &local->rmem_handle);
 	if (ret)
 		goto failed;
-	mem.CardOffset = 0x8000;
-	mem.Page = 0;
-	ret = pcmcia_map_mem_page(link, local->rmem_handle, &mem);
+	ret = pcmcia_map_mem_page(link, local->rmem_handle, 0x8000);
 	if (ret)
 		goto failed;
 	local->rmem = ioremap(req.Base, req.Size);
@@ -462,9 +457,7 @@ static int ray_config(struct pcmcia_device *link)
 	ret = pcmcia_request_window(link, &req, &local->amem_handle);
 	if (ret)
 		goto failed;
-	mem.CardOffset = 0x0000;
-	mem.Page = 0;
-	ret = pcmcia_map_mem_page(link, local->amem_handle, &mem);
+	ret = pcmcia_map_mem_page(link, local->amem_handle, 0);
 	if (ret)
 		goto failed;
 	local->amem = ioremap(req.Base, req.Size);
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index a48d4a9..975baaa 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -193,7 +193,7 @@ EXPORT_SYMBOL(pcmcia_write_config_byte);
 
 
 int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
-			memreq_t *req)
+			unsigned int offset)
 {
 	struct pcmcia_socket *s = p_dev->socket;
 	int ret;
@@ -201,12 +201,9 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
 	wh--;
 	if (wh >= MAX_WIN)
 		return -EINVAL;
-	if (req->Page != 0) {
-		dev_dbg(&s->dev, "failure: requested page is zero\n");
-		return -EINVAL;
-	}
+
 	mutex_lock(&s->ops_mutex);
-	s->win[wh].card_start = req->CardOffset;
+	s->win[wh].card_start = offset;
 	ret = s->ops->set_mem_map(s, &s->win[wh]);
 	if (ret)
 		dev_warn(&s->dev, "failed to set_mem_map\n");
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index ad8e896..5688fc3 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1661,7 +1661,6 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev,
 		}
 
 		if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
-			memreq_t	map;
 			cistpl_mem_t	*mem =
 				(cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
 			cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
@@ -1673,8 +1672,8 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev,
 			cfg_mem->req.AccessSpeed = 0;
 			if (pcmcia_request_window(p_dev, &cfg_mem->req, &p_dev->win) != 0)
 				goto next_entry;
-			map.Page = 0; map.CardOffset = mem->win[0].card_addr;
-			if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0)
+			if (pcmcia_map_mem_page(p_dev, p_dev->win,
+					mem->win[0].card_addr) != 0)
 				goto next_entry;
 
 			cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size);
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 7e41ad9..abaa40b 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -556,7 +556,6 @@ static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				void *priv_data)
 {
 	win_req_t *req = priv_data;
-	memreq_t map;
 
 	if (cfg->index == 0)
 		return -ENODEV;
@@ -602,9 +601,8 @@ static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
 		req->AccessSpeed = 0;
 		if (pcmcia_request_window(p_dev, req, &p_dev->win))
 			return -ENODEV;
-		map.Page = 0;
-		map.CardOffset = mem->win[0].card_addr;
-		if (pcmcia_map_mem_page(p_dev, p_dev->win, &map))
+		if (pcmcia_map_mem_page(p_dev, p_dev->win,
+				mem->win[0].card_addr))
 			return -ENODEV;
 	}
 	/* If we got this far, we're cool! */
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index b2483f8..caccece 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -308,7 +308,6 @@ static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				void *priv_data)
 {
 	win_req_t *req = priv_data;
-	memreq_t map;
 
 	if (cfg->index == 0)
 		return -ENODEV;
@@ -354,9 +353,8 @@ static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
 		req->AccessSpeed = 0;
 		if (pcmcia_request_window(p_dev, req, &p_dev->win))
 			return -ENODEV;
-		map.Page = 0;
-		map.CardOffset = mem->win[0].card_addr;
-		if (pcmcia_map_mem_page(p_dev, p_dev->win, &map))
+		if (pcmcia_map_mem_page(p_dev, p_dev->win,
+						mem->win[0].card_addr))
 			return -ENODEV;
 	}
 	/* If we got this far, we're cool! */
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index c1444b4..94d9f7f 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -286,7 +286,6 @@ static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				void *priv_data)
 {
 	win_req_t *req = priv_data;
-	memreq_t map;
 
 	if (cfg->index == 0)
 		return -ENODEV;
@@ -332,9 +331,8 @@ static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
 		req->AccessSpeed = 0;
 		if (pcmcia_request_window(p_dev, req, &p_dev->win))
 			return -ENODEV;
-		map.Page = 0;
-		map.CardOffset = mem->win[0].card_addr;
-		if (pcmcia_map_mem_page(p_dev, p_dev->win, &map))
+		if (pcmcia_map_mem_page(p_dev, p_dev->win,
+						mem->win[0].card_addr))
 			return -ENODEV;
 	}
 	/* If we got this far, we're cool! */
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 583a4e3..e4faf44 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -68,12 +68,6 @@ typedef struct config_req_t {
 #define PRESENT_IOBASE_3	0x100
 #define PRESENT_IOSIZE		0x200
 
-/* For GetMemPage, MapMemPage */
-typedef struct memreq_t {
-    u_int	CardOffset;
-    u_short	Page;
-} memreq_t;
-
 /* For RequestWindow */
 typedef struct win_req_t {
     u_int	Attributes;
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 0748bec..a2bf3a7 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -202,7 +202,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req,
 			  window_handle_t *wh);
 int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t win);
 int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t win,
-			memreq_t *req);
+			unsigned int offset);
 
 int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
 void pcmcia_disable_device(struct pcmcia_device *p_dev);
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 11/11] pcmcia: do not request windows if you don't need to
From: Dominik Brodowski @ 2010-08-01 12:59 UTC (permalink / raw)
  To: linux-pcmcia; +Cc: Dominik Brodowski, netdev, linux-wireless
In-Reply-To: <20100801125749.GA2564@comet.dominikbrodowski.net>

Several drivers contained dummy code to request for memory windows,
even though they never made use of it. Remove all such code
snippets.

CC: netdev@vger.kernel.org
CC: linux-wireless@vger.kernel.org
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
---
 drivers/isdn/hisax/sedlbauer_cs.c             |   37 +------------------------
 drivers/net/wireless/airo_cs.c                |   37 +------------------------
 drivers/staging/comedi/drivers/ni_daq_700.c   |   23 +---------------
 drivers/staging/comedi/drivers/ni_daq_dio24.c |   24 +---------------
 drivers/staging/comedi/drivers/ni_labpc_cs.c  |   24 +---------------
 5 files changed, 5 insertions(+), 140 deletions(-)

diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 0b06dbb..a024192 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -171,8 +171,6 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev,
 				  unsigned int vcc,
 				  void *priv_data)
 {
-	win_req_t *req = priv_data;
-
 	if (cfg->index == 0)
 		return -ENODEV;
 
@@ -219,31 +217,6 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev,
 			return -ENODEV;
 	}
 
-	/*
-	  Now set up a common memory window, if needed.  There is room
-	  in the struct pcmcia_device structure for one memory window handle,
-	  but if the base addresses need to be saved, or if multiple
-	  windows are needed, the info should go in the private data
-	  structure for this device.
-
-	  Note that the memory window base is a physical address, and
-	  needs to be mapped to virtual space with ioremap() before it
-	  is used.
-	*/
-	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
-		cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
-		req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
-		req->Attributes |= WIN_ENABLE;
-		req->Base = mem->win[0].host_addr;
-		req->Size = mem->win[0].len;
-		req->AccessSpeed = 0;
-		if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0)
-			return -ENODEV;
-
-		if (pcmcia_map_mem_page(p_dev, p_dev->win,
-						mem->win[0].card_addr) != 0)
-			return -ENODEV;
-	}
 	return 0;
 }
 
@@ -251,16 +224,11 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev,
 
 static int __devinit sedlbauer_config(struct pcmcia_device *link)
 {
-    win_req_t *req;
     int ret;
     IsdnCard_t  icard;
 
     dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link);
 
-    req = kzalloc(sizeof(win_req_t), GFP_KERNEL);
-    if (!req)
-	    return -ENOMEM;
-
     /*
       In this loop, we scan the CIS for configuration table entries,
       each of which describes a valid card configuration, including
@@ -273,7 +241,7 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
       these things without consulting the CIS, and most client drivers
       will only use the CIS to fill in implementation-defined details.
     */
-    ret = pcmcia_loop_config(link, sedlbauer_config_check, req);
+    ret = pcmcia_loop_config(link, sedlbauer_config_check, NULL);
     if (ret)
 	    goto failed;
 
@@ -297,9 +265,6 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
 	printk(" & %pR", link->resource[0]);
     if (link->resource[1])
 	printk(" & %pR", link->resource[1]);
-    if (link->win)
-	printk(", mem 0x%06lx-0x%06lx", req->Base,
-	       req->Base+req->Size-1);
     printk("\n");
 
     icard.para[0] = link->irq;
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index d47672c..9a121a5 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -154,8 +154,6 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev,
 				unsigned int vcc,
 				void *priv_data)
 {
-	win_req_t *req = priv_data;
-
 	if (cfg->index == 0)
 		return -ENODEV;
 
@@ -194,29 +192,6 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev,
 	if (pcmcia_request_io(p_dev) != 0)
 		return -ENODEV;
 
-	/*
-	  Now set up a common memory window, if needed.  There is room
-	  in the struct pcmcia_device structure for one memory window handle,
-	  but if the base addresses need to be saved, or if multiple
-	  windows are needed, the info should go in the private data
-	  structure for this device.
-
-	  Note that the memory window base is a physical address, and
-	  needs to be mapped to virtual space with ioremap() before it
-	  is used.
-	*/
-	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
-		cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
-		req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
-		req->Base = mem->win[0].host_addr;
-		req->Size = mem->win[0].len;
-		req->AccessSpeed = 0;
-		if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0)
-			return -ENODEV;
-		if (pcmcia_map_mem_page(p_dev, p_dev->win,
-						mem->win[0].card_addr) != 0)
-			return -ENODEV;
-	}
 	/* If we got this far, we're cool! */
 	return 0;
 }
@@ -225,17 +200,12 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev,
 static int airo_config(struct pcmcia_device *link)
 {
 	local_info_t *dev;
-	win_req_t *req;
 	int ret;
 
 	dev = link->priv;
 
 	dev_dbg(&link->dev, "airo_config\n");
 
-	req = kzalloc(sizeof(win_req_t), GFP_KERNEL);
-	if (!req)
-		return -ENOMEM;
-
 	/*
 	 * In this loop, we scan the CIS for configuration table
 	 * entries, each of which describes a valid card
@@ -250,7 +220,7 @@ static int airo_config(struct pcmcia_device *link)
 	 * and most client drivers will only use the CIS to fill in
 	 * implementation-defined details.
 	 */
-	ret = pcmcia_loop_config(link, airo_cs_config_check, req);
+	ret = pcmcia_loop_config(link, airo_cs_config_check, NULL);
 	if (ret)
 		goto failed;
 
@@ -281,16 +251,11 @@ static int airo_config(struct pcmcia_device *link)
 		printk(" & %pR", link->resource[0]);
 	if (link->resource[1])
 		printk(" & %pR", link->resource[1]);
-	if (link->win)
-		printk(", mem 0x%06lx-0x%06lx", req->Base,
-		       req->Base+req->Size-1);
 	printk("\n");
-	kfree(req);
 	return 0;
 
  failed:
 	airo_release(link);
-	kfree(req);
 	return -ENODEV;
 } /* airo_config */
 
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index abaa40b..bf2e84a 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -555,8 +555,6 @@ static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				unsigned int vcc,
 				void *priv_data)
 {
-	win_req_t *req = priv_data;
-
 	if (cfg->index == 0)
 		return -ENODEV;
 
@@ -589,22 +587,6 @@ static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
 			return -ENODEV;
 	}
 
-	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
-		cistpl_mem_t *mem =
-			(cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
-		req->Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM;
-		req->Attributes |= WIN_ENABLE;
-		req->Base = mem->win[0].host_addr;
-		req->Size = mem->win[0].len;
-		if (req->Size < 0x1000)
-			req->Size = 0x1000;
-		req->AccessSpeed = 0;
-		if (pcmcia_request_window(p_dev, req, &p_dev->win))
-			return -ENODEV;
-		if (pcmcia_map_mem_page(p_dev, p_dev->win,
-				mem->win[0].card_addr))
-			return -ENODEV;
-	}
 	/* If we got this far, we're cool! */
 	return 0;
 }
@@ -618,7 +600,7 @@ static void dio700_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "dio700_config\n");
 
-	ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, &req);
+	ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
 		goto failed;
@@ -644,9 +626,6 @@ static void dio700_config(struct pcmcia_device *link)
 		printk(", io %pR", link->resource[0]);
 	if (link->resource[1])
 		printk(" & %pR", link->resource[1]);
-	if (link->win)
-		printk(", mem 0x%06lx-0x%06lx", req.Base,
-		       req.Base + req.Size - 1);
 	printk("\n");
 
 	return;
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index caccece..9112e70 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -307,8 +307,6 @@ static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				unsigned int vcc,
 				void *priv_data)
 {
-	win_req_t *req = priv_data;
-
 	if (cfg->index == 0)
 		return -ENODEV;
 
@@ -341,22 +339,6 @@ static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
 			return -ENODEV;
 	}
 
-	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
-		cistpl_mem_t *mem =
-			(cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
-		req->Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM;
-		req->Attributes |= WIN_ENABLE;
-		req->Base = mem->win[0].host_addr;
-		req->Size = mem->win[0].len;
-		if (req->Size < 0x1000)
-			req->Size = 0x1000;
-		req->AccessSpeed = 0;
-		if (pcmcia_request_window(p_dev, req, &p_dev->win))
-			return -ENODEV;
-		if (pcmcia_map_mem_page(p_dev, p_dev->win,
-						mem->win[0].card_addr))
-			return -ENODEV;
-	}
 	/* If we got this far, we're cool! */
 	return 0;
 }
@@ -364,13 +346,12 @@ static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
 static void dio24_config(struct pcmcia_device *link)
 {
 	int ret;
-	win_req_t req;
 
 	printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO! - config\n");
 
 	dev_dbg(&link->dev, "dio24_config\n");
 
-	ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, &req);
+	ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
 		goto failed;
@@ -396,9 +377,6 @@ static void dio24_config(struct pcmcia_device *link)
 		printk(" & %pR", link->resource[0]);
 	if (link->resource[1])
 		printk(" & %pR", link->resource[1]);
-	if (link->win)
-		printk(", mem 0x%06lx-0x%06lx", req.Base,
-		       req.Base + req.Size - 1);
 	printk("\n");
 
 	return;
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index 94d9f7f..f204961 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -285,8 +285,6 @@ static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				unsigned int vcc,
 				void *priv_data)
 {
-	win_req_t *req = priv_data;
-
 	if (cfg->index == 0)
 		return -ENODEV;
 
@@ -319,22 +317,6 @@ static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
 			return -ENODEV;
 	}
 
-	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
-		cistpl_mem_t *mem =
-			(cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
-		req->Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM;
-		req->Attributes |= WIN_ENABLE;
-		req->Base = mem->win[0].host_addr;
-		req->Size = mem->win[0].len;
-		if (req->Size < 0x1000)
-			req->Size = 0x1000;
-		req->AccessSpeed = 0;
-		if (pcmcia_request_window(p_dev, req, &p_dev->win))
-			return -ENODEV;
-		if (pcmcia_map_mem_page(p_dev, p_dev->win,
-						mem->win[0].card_addr))
-			return -ENODEV;
-	}
 	/* If we got this far, we're cool! */
 	return 0;
 }
@@ -343,11 +325,10 @@ static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
 static void labpc_config(struct pcmcia_device *link)
 {
 	int ret;
-	win_req_t req;
 
 	dev_dbg(&link->dev, "labpc_config\n");
 
-	ret = pcmcia_loop_config(link, labpc_pcmcia_config_loop, &req);
+	ret = pcmcia_loop_config(link, labpc_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
 		goto failed;
@@ -373,9 +354,6 @@ static void labpc_config(struct pcmcia_device *link)
 		printk(" & %pR", link->resource[0]);
 	if (link->resource[1])
 		printk(" & %pR", link->resource[1]);
-	if (link->win)
-		printk(", mem 0x%06lx-0x%06lx", req.Base,
-		       req.Base + req.Size - 1);
 	printk("\n");
 
 	return;
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 08/11] pcmcia: use struct resource for PCMCIA devices, part 2
From: Dominik Brodowski @ 2010-08-01 12:59 UTC (permalink / raw)
  To: linux-pcmcia
  Cc: Dominik Brodowski, linux-mtd, netdev, linux-wireless, Jiri Kosina
In-Reply-To: <20100801125749.GA2564@comet.dominikbrodowski.net>

Use struct resource * also for iomem resources.

CC: linux-mtd@lists.infradead.org
CC: netdev@vger.kernel.org
CC: linux-wireless@vger.kernel.org
CC: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
---
 drivers/char/pcmcia/ipwireless/main.c |   13 +-----
 drivers/mtd/maps/pcmciamtd.c          |    1 -
 drivers/net/pcmcia/ibmtr_cs.c         |    1 -
 drivers/net/wireless/b43/pcmcia.c     |    3 +-
 drivers/net/wireless/ray_cs.c         |    8 ----
 drivers/pcmcia/cs_internal.h          |    1 +
 drivers/pcmcia/ds.c                   |    7 ++-
 drivers/pcmcia/pcmcia_resource.c      |   70 ++++++++++++++++++---------------
 include/pcmcia/cs.h                   |   35 +++++++----------
 include/pcmcia/ds.h                   |   15 ++++++-
 10 files changed, 74 insertions(+), 80 deletions(-)

diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 6c4aa4b..67bdb05 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -157,15 +157,12 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
 	return 0;
 
 exit3:
-	pcmcia_release_window(p_dev, ipw->handle_attr_memory);
 exit2:
 	if (ipw->common_memory) {
 		release_mem_region(ipw->request_common_memory.Base,
 				ipw->request_common_memory.Size);
 		iounmap(ipw->common_memory);
-		pcmcia_release_window(p_dev, ipw->handle_common_memory);
-	} else
-		pcmcia_release_window(p_dev, ipw->handle_common_memory);
+	}
 exit1:
 	release_resource(io_resource);
 	pcmcia_disable_device(p_dev);
@@ -238,13 +235,12 @@ exit:
 		release_mem_region(ipw->request_attr_memory.Base,
 				ipw->request_attr_memory.Size);
 		iounmap(ipw->attr_memory);
-		pcmcia_release_window(link, ipw->handle_attr_memory);
+
 	}
 	if (ipw->common_memory) {
 		release_mem_region(ipw->request_common_memory.Base,
 				ipw->request_common_memory.Size);
 		iounmap(ipw->common_memory);
-		pcmcia_release_window(link, ipw->handle_common_memory);
 	}
 	pcmcia_disable_device(link);
 	return -1;
@@ -262,11 +258,6 @@ static void release_ipwireless(struct ipw_dev *ipw)
 				ipw->request_attr_memory.Size);
 		iounmap(ipw->attr_memory);
 	}
-	if (ipw->common_memory)
-		pcmcia_release_window(ipw->link, ipw->handle_common_memory);
-	if (ipw->attr_memory)
-		pcmcia_release_window(ipw->link, ipw->handle_attr_memory);
-
 	pcmcia_disable_device(ipw->link);
 }
 
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index f97463e..e9ca5ba 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -344,7 +344,6 @@ static void pcmciamtd_release(struct pcmcia_device *link)
 			iounmap(dev->win_base);
 			dev->win_base = NULL;
 		}
-		pcmcia_release_window(link, link->win);
 	}
 	pcmcia_disable_device(link);
 }
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index c0b3cdd..b0d06a3 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -319,7 +319,6 @@ static void ibmtr_release(struct pcmcia_device *link)
 	if (link->win) {
 		struct tok_info *ti = netdev_priv(dev);
 		iounmap(ti->mmio);
-		pcmcia_release_window(link, info->sram_win_handle);
 	}
 	pcmcia_disable_device(link);
 }
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index ffe1f89..dfbc41d 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -76,8 +76,7 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 	dev->conf.Attributes = CONF_ENABLE_IRQ;
 	dev->conf.IntType = INT_MEMORY_AND_IO;
 
-	win.Attributes = WIN_ADDR_SPACE_MEM | WIN_MEMORY_TYPE_CM |
-			 WIN_ENABLE | WIN_DATA_WIDTH_16 |
+	win.Attributes =  WIN_ENABLE | WIN_DATA_WIDTH_16 |
 			 WIN_USE_WAIT;
 	win.Base = 0;
 	win.Size = SSB_CORE_SIZE;
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 7eb339a..a860bce 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -785,7 +785,6 @@ static void ray_release(struct pcmcia_device *link)
 {
 	struct net_device *dev = link->priv;
 	ray_dev_t *local = netdev_priv(dev);
-	int i;
 
 	dev_dbg(&link->dev, "ray_release\n");
 
@@ -794,13 +793,6 @@ static void ray_release(struct pcmcia_device *link)
 	iounmap(local->sram);
 	iounmap(local->rmem);
 	iounmap(local->amem);
-	/* Do bother checking to see if these succeed or not */
-	i = pcmcia_release_window(link, local->amem_handle);
-	if (i != 0)
-		dev_dbg(&link->dev, "ReleaseWindow(local->amem) ret = %x\n", i);
-	i = pcmcia_release_window(link, local->rmem_handle);
-	if (i != 0)
-		dev_dbg(&link->dev, "ReleaseWindow(local->rmem) ret = %x\n", i);
 	pcmcia_disable_device(link);
 
 	dev_dbg(&link->dev, "ray_release ending\n");
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 511ac75..37d38b5 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -40,6 +40,7 @@ typedef struct config_t {
 	unsigned int	CardValues;
 
 	struct resource io[MAX_IO_WIN]; /* io ports */
+	struct resource mem[MAX_WIN];   /* mem areas */
 
 	struct {
 		u_int	Attributes;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 7ddd19a..61de128 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -552,13 +552,16 @@ static struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s,
 		}
 		p_dev->function_config = c;
 		kref_init(&c->ref);
-		for (i = 0; i < MAX_IO_WIN; i++) {
+		for (i = 0; i < (MAX_IO_WIN + MAX_WIN); i++) {
 			c->io[i].name = dev_name(&p_dev->dev);
-			c->io[i].flags = IORESOURCE_IO;
+			c->io[i].flags = i < MAX_IO_WIN ? IORESOURCE_IO :
+				IORESOURCE_MEM;
 		}
 	}
 	for (i = 0; i < MAX_IO_WIN; i++)
 		p_dev->resource[i] = &p_dev->function_config->io[i];
+	for (; i < (MAX_IO_WIN + MAX_WIN); i++)
+		p_dev->resource[i] = &p_dev->function_config->mem[i-MAX_IO_WIN];
 
 	mutex_unlock(&s->ops_mutex);
 
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 975baaa..01f8e56 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -196,15 +196,17 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
 			unsigned int offset)
 {
 	struct pcmcia_socket *s = p_dev->socket;
+	struct resource *res = wh;
+	unsigned int w;
 	int ret;
 
-	wh--;
-	if (wh >= MAX_WIN)
+	w = ((res->flags & IORESOURCE_BITS & WIN_FLAGS_REQ) >> 2) - 1;
+	if (w >= MAX_WIN)
 		return -EINVAL;
 
 	mutex_lock(&s->ops_mutex);
-	s->win[wh].card_start = offset;
-	ret = s->ops->set_mem_map(s, &s->win[wh]);
+	s->win[w].card_start = offset;
+	ret = s->ops->set_mem_map(s, &s->win[w]);
 	if (ret)
 		dev_warn(&s->dev, "failed to set_mem_map\n");
 	mutex_unlock(&s->ops_mutex);
@@ -371,19 +373,22 @@ out:
 } /* pcmcia_release_io */
 
 
-int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
+int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
 {
 	struct pcmcia_socket *s = p_dev->socket;
 	pccard_mem_map *win;
+	unsigned int w;
 
-	wh--;
-	if (wh >= MAX_WIN)
+	dev_dbg(&p_dev->dev, "releasing window %pR\n", res);
+
+	w = ((res->flags & IORESOURCE_BITS & WIN_FLAGS_REQ) >> 2) - 1;
+	if (w >= MAX_WIN)
 		return -EINVAL;
 
 	mutex_lock(&s->ops_mutex);
-	win = &s->win[wh];
+	win = &s->win[w];
 
-	if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) {
+	if (!(p_dev->_win & CLIENT_WIN_REQ(w))) {
 		dev_dbg(&s->dev, "not releasing unknown window\n");
 		mutex_unlock(&s->ops_mutex);
 		return -EINVAL;
@@ -392,7 +397,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
 	/* Shut down memory window */
 	win->flags &= ~MAP_ACTIVE;
 	s->ops->set_mem_map(s, win);
-	s->state &= ~SOCKET_WIN_REQ(wh);
+	s->state &= ~SOCKET_WIN_REQ(w);
 
 	/* Release system memory */
 	if (win->res) {
@@ -400,7 +405,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
 		kfree(win->res);
 		win->res = NULL;
 	}
-	p_dev->_win &= ~CLIENT_WIN_REQ(wh);
+	p_dev->_win &= ~CLIENT_WIN_REQ(w);
 	mutex_unlock(&s->ops_mutex);
 
 	return 0;
@@ -775,23 +780,18 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 	struct pcmcia_socket *s = p_dev->socket;
 	pccard_mem_map *win;
 	u_long align;
+	struct resource *res;
 	int w;
 
 	if (!(s->state & SOCKET_PRESENT)) {
 		dev_dbg(&s->dev, "No card present\n");
 		return -ENODEV;
 	}
-	if (req->Attributes & (WIN_PAGED | WIN_SHARED)) {
-		dev_dbg(&s->dev, "bad attribute setting for iomem region\n");
-		return -EINVAL;
-	}
 
 	/* Window size defaults to smallest available */
 	if (req->Size == 0)
 		req->Size = s->map_size;
-	align = (((s->features & SS_CAP_MEM_ALIGN) ||
-		  (req->Attributes & WIN_STRICT_ALIGN)) ?
-		 req->Size : s->map_size);
+	align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size;
 	if (req->Size & (s->map_size-1)) {
 		dev_dbg(&s->dev, "invalid map size\n");
 		return -EINVAL;
@@ -805,20 +805,21 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 		align = 0;
 
 	/* Allocate system memory window */
+	mutex_lock(&s->ops_mutex);
 	for (w = 0; w < MAX_WIN; w++)
 		if (!(s->state & SOCKET_WIN_REQ(w)))
 			break;
 	if (w == MAX_WIN) {
 		dev_dbg(&s->dev, "all windows are used already\n");
+		mutex_unlock(&s->ops_mutex);
 		return -EINVAL;
 	}
 
-	mutex_lock(&s->ops_mutex);
 	win = &s->win[w];
 
 	if (!(s->features & SS_CAP_STATIC_MAP)) {
 		win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
-						      (req->Attributes & WIN_MAP_BELOW_1MB), s);
+						0, s);
 		if (!win->res) {
 			dev_dbg(&s->dev, "allocating mem region failed\n");
 			mutex_unlock(&s->ops_mutex);
@@ -829,16 +830,8 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 
 	/* Configure the socket controller */
 	win->map = w+1;
-	win->flags = 0;
+	win->flags = req->Attributes;
 	win->speed = req->AccessSpeed;
-	if (req->Attributes & WIN_MEMORY_TYPE)
-		win->flags |= MAP_ATTRIB;
-	if (req->Attributes & WIN_ENABLE)
-		win->flags |= MAP_ACTIVE;
-	if (req->Attributes & WIN_DATA_WIDTH_16)
-		win->flags |= MAP_16BIT;
-	if (req->Attributes & WIN_USE_WAIT)
-		win->flags |= MAP_USE_WAIT;
 	win->card_start = 0;
 
 	if (s->ops->set_mem_map(s, win) != 0) {
@@ -854,8 +847,16 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 	else
 		req->Base = win->res->start;
 
+	/* convert to new-style resources */
+	res = p_dev->resource[w + MAX_IO_WIN];
+	res->start = req->Base;
+	res->end = req->Base + req->Size - 1;
+	res->flags &= ~IORESOURCE_BITS;
+	res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2);
+	dev_dbg(&s->dev, "request_window results in %pR\n", res);
+
 	mutex_unlock(&s->ops_mutex);
-	*wh = w + 1;
+	*wh = res;
 
 	return 0;
 } /* pcmcia_request_window */
@@ -863,13 +864,18 @@ EXPORT_SYMBOL(pcmcia_request_window);
 
 void pcmcia_disable_device(struct pcmcia_device *p_dev)
 {
+	int i;
+	for (i = 0; i < MAX_WIN; i++) {
+		struct resource *res = p_dev->resource[MAX_IO_WIN + i];
+		if (res->flags & WIN_FLAGS_REQ)
+			pcmcia_release_window(p_dev, res);
+	}
+
 	pcmcia_release_configuration(p_dev);
 	pcmcia_release_io(p_dev);
 	if (p_dev->_irq) {
 		free_irq(p_dev->irq, p_dev->priv);
 		p_dev->_irq = 0;
 	}
-	if (p_dev->win)
-		pcmcia_release_window(p_dev, p_dev->win);
 }
 EXPORT_SYMBOL(pcmcia_disable_device);
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index e4faf44..68d8bde 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -77,26 +77,19 @@ typedef struct win_req_t {
 } win_req_t;
 
 /* Attributes for RequestWindow */
-#define WIN_ADDR_SPACE		0x0001
-#define WIN_ADDR_SPACE_MEM	0x0000
-#define WIN_ADDR_SPACE_IO	0x0001
-#define WIN_MEMORY_TYPE		0x0002
-#define WIN_MEMORY_TYPE_CM	0x0000
-#define WIN_MEMORY_TYPE_AM	0x0002
-#define WIN_ENABLE		0x0004
-#define WIN_DATA_WIDTH		0x0018
-#define WIN_DATA_WIDTH_8	0x0000
-#define WIN_DATA_WIDTH_16	0x0008
-#define WIN_DATA_WIDTH_32	0x0010
-#define WIN_PAGED		0x0020
-#define WIN_SHARED		0x0040
-#define WIN_FIRST_SHARED	0x0080
-#define WIN_USE_WAIT		0x0100
-#define WIN_STRICT_ALIGN	0x0200
-#define WIN_MAP_BELOW_1MB	0x0400
-#define WIN_PREFETCH		0x0800
-#define WIN_CACHEABLE		0x1000
-#define WIN_BAR_MASK		0xe000
-#define WIN_BAR_SHIFT		13
+#define WIN_MEMORY_TYPE_CM	0x00 /* default */
+#define WIN_MEMORY_TYPE_AM	0x20 /* MAP_ATTRIB */
+#define WIN_DATA_WIDTH_8	0x00 /* default */
+#define WIN_DATA_WIDTH_16	0x02 /* MAP_16BIT */
+#define WIN_ENABLE		0x01 /* MAP_ACTIVE */
+#define WIN_USE_WAIT		0x40 /* MAP_USE_WAIT */
+
+#define WIN_FLAGS_MAP		0x63 /* MAP_ATTRIB | MAP_16BIT | MAP_ACTIVE |
+					MAP_USE_WAIT */
+#define WIN_FLAGS_REQ		0x1c /* mapping to socket->win[i]:
+					0x04 -> 0
+					0x08 -> 1
+					0x0c -> 2
+					0x10 -> 3 */
 
 #endif /* _LINUX_CS_H */
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index a2bf3a7..70c58ed 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -36,7 +36,7 @@ struct pcmcia_device;
 struct config_t;
 struct net_device;
 
-typedef unsigned long window_handle_t;
+typedef struct resource *window_handle_t;
 
 /* dynamic device IDs for PCMCIA device drivers. See
  * Documentation/pcmcia/driver.txt for details.
@@ -63,6 +63,17 @@ struct pcmcia_driver {
 int pcmcia_register_driver(struct pcmcia_driver *driver);
 void pcmcia_unregister_driver(struct pcmcia_driver *driver);
 
+/* for struct resource * array embedded in struct pcmcia_device */
+enum {
+	PCMCIA_IOPORT_0,
+	PCMCIA_IOPORT_1,
+	PCMCIA_IOMEM_0,
+	PCMCIA_IOMEM_1,
+	PCMCIA_IOMEM_2,
+	PCMCIA_IOMEM_3,
+	PCMCIA_NUM_RESOURCES,
+};
+
 struct pcmcia_device {
 	/* the socket and the device_no [for multifunction devices]
 	   uniquely define a pcmcia_device */
@@ -85,7 +96,7 @@ struct pcmcia_device {
 
 	/* device setup */
 	unsigned int		irq;
-	struct resource		*resource[MAX_IO_WIN];
+	struct resource		*resource[PCMCIA_NUM_RESOURCES];
 
 	unsigned int		io_lines; /* number of I/O lines */
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 05/11] pcmcia: do not use io_req_t when calling pcmcia_request_io()
From: Dominik Brodowski @ 2010-08-01 12:59 UTC (permalink / raw)
  To: linux-pcmcia
  Cc: Dominik Brodowski, netdev, linux-wireless, linux-ide, linux-usb,
	laforge, linux-mtd, linux-bluetooth, alsa-devel, linux-serial,
	Michael Buesch
In-Reply-To: <20100801125749.GA2564@comet.dominikbrodowski.net>

Instead of io_req_t, drivers are now requested to fill out
struct pcmcia_device *p_dev->resource[0,1] for up to two ioport
ranges. After a call to pcmcia_request_io(), the ports found there
are reserved, after calling pcmcia_request_configuration(), they may
be used.

CC: netdev@vger.kernel.org
CC: linux-wireless@vger.kernel.org
CC: linux-ide@vger.kernel.org
CC: linux-usb@vger.kernel.org
CC: laforge@gnumonks.org
CC: linux-mtd@lists.infradead.org
CC: linux-bluetooth@vger.kernel.org
CC: alsa-devel@alsa-project.org
CC: linux-serial@vger.kernel.org
CC: Michael Buesch <mb@bu3sch.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
---
 Documentation/pcmcia/driver-changes.txt          |    7 ++++
 drivers/ata/pata_pcmcia.c                        |   29 ++++++++-------
 drivers/bluetooth/bluecard_cs.c                  |   13 +++----
 drivers/bluetooth/bt3c_cs.c                      |   18 +++++-----
 drivers/bluetooth/btuart_cs.c                    |   18 +++++-----
 drivers/bluetooth/dtl1_cs.c                      |   21 +++++------
 drivers/char/pcmcia/cm4000_cs.c                  |   17 +++------
 drivers/char/pcmcia/cm4040_cs.c                  |   20 +++-------
 drivers/char/pcmcia/ipwireless/main.c            |   10 +++---
 drivers/char/pcmcia/synclink_cs.c                |   21 +++++------
 drivers/ide/ide-cs.c                             |   30 ++++++++-------
 drivers/isdn/hardware/avm/avm_cs.c               |   15 +++-----
 drivers/isdn/hisax/avma1_cs.c                    |   20 ++++------
 drivers/isdn/hisax/elsa_cs.c                     |   15 ++++----
 drivers/isdn/hisax/sedlbauer_cs.c                |   28 +++++++--------
 drivers/isdn/hisax/teles_cs.c                    |   15 ++++----
 drivers/net/pcmcia/3c574_cs.c                    |   11 +++---
 drivers/net/pcmcia/3c589_cs.c                    |   11 +++---
 drivers/net/pcmcia/axnet_cs.c                    |   40 +++++++++++----------
 drivers/net/pcmcia/com20020_cs.c                 |   19 ++++++----
 drivers/net/pcmcia/fmvj18x_cs.c                  |   31 ++++++++--------
 drivers/net/pcmcia/ibmtr_cs.c                    |   14 ++++----
 drivers/net/pcmcia/nmclan_cs.c                   |    8 ++--
 drivers/net/pcmcia/pcnet_cs.c                    |   40 +++++++++++----------
 drivers/net/pcmcia/smc91c92_cs.c                 |   43 +++++++++++-----------
 drivers/net/pcmcia/xirc2ps_cs.c                  |   34 +++++++++---------
 drivers/net/wireless/airo_cs.c                   |   22 +++++------
 drivers/net/wireless/atmel_cs.c                  |   22 +++++------
 drivers/net/wireless/b43/pcmcia.c                |    4 --
 drivers/net/wireless/hostap/hostap_cs.c          |   28 ++++++---------
 drivers/net/wireless/libertas/if_cs.c            |    8 ++--
 drivers/net/wireless/orinoco/orinoco_cs.c        |   24 ++++++-------
 drivers/net/wireless/orinoco/spectrum_cs.c       |   24 ++++++-------
 drivers/net/wireless/ray_cs.c                    |    5 +--
 drivers/net/wireless/wl3501_cs.c                 |   12 +++---
 drivers/parport/parport_cs.c                     |   16 ++++----
 drivers/pcmcia/pcmcia_resource.c                 |   37 +++++--------------
 drivers/scsi/pcmcia/aha152x_stub.c               |   14 ++++----
 drivers/scsi/pcmcia/fdomain_stub.c               |   10 +++---
 drivers/scsi/pcmcia/nsp_cs.c                     |   30 +++++++--------
 drivers/scsi/pcmcia/qlogic_stub.c                |   14 ++++----
 drivers/scsi/pcmcia/sym53c500_cs.c               |   14 ++++----
 drivers/serial/serial_cs.c                       |   37 ++++++++++---------
 drivers/staging/comedi/drivers/cb_das16_cs.c     |   24 ++++++-------
 drivers/staging/comedi/drivers/das08_cs.c        |   23 ++++++------
 drivers/staging/comedi/drivers/ni_daq_700.c      |   24 ++++++-------
 drivers/staging/comedi/drivers/ni_daq_dio24.c    |   24 ++++++-------
 drivers/staging/comedi/drivers/ni_labpc_cs.c     |   24 ++++++-------
 drivers/staging/comedi/drivers/ni_mio_cs.c       |   13 +++----
 drivers/staging/comedi/drivers/quatech_daqp_cs.c |   24 ++++++-------
 drivers/staging/wlags49_h2/wl_cs.c               |    8 ++--
 drivers/telephony/ixj_pcmcia.c                   |   16 ++++----
 drivers/usb/host/sl811_cs.c                      |   12 +++---
 include/pcmcia/cs.h                              |   17 ---------
 include/pcmcia/ds.h                              |   21 ++++++++++-
 sound/pcmcia/pdaudiocf/pdaudiocf.c               |    6 ++--
 sound/pcmcia/vx/vxpocket.c                       |    6 ++--
 57 files changed, 527 insertions(+), 584 deletions(-)

diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index ff5f0be..26c0f9c 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,4 +1,11 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
+* pcmcia_request_io changes (as of 2.6.36)
+   Instead of io_req_t, drivers are now requested to fill out
+   struct pcmcia_device *p_dev->resource[0,1] for up to two ioport
+   ranges. After a call to pcmcia_request_io(), the ports found there
+   are reserved, after calling pcmcia_request_configuration(), they may
+   be used.
+
 * No dev_info_t, no cs_types.h (as of 2.6.36)
    dev_info_t and a few other typedefs are removed. No longer use them
    in PCMCIA device drivers. Also, do not include pcmcia/cs_types.h, as
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 1fcd065..e944aa0 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -200,21 +200,23 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev,
 
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		pdev->io.BasePort1 = io->win[0].base;
-		pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+		pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+		pdev->resource[0]->start = io->win[0].base;
+		if (!(io->flags & CISTPL_IO_16BIT)) {
+			pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+			pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+		}
 		if (io->nwin == 2) {
-			pdev->io.NumPorts1 = 8;
-			pdev->io.BasePort2 = io->win[1].base;
-			pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
-			if (pcmcia_request_io(pdev, &pdev->io) != 0)
+			pdev->resource[0]->end = 8;
+			pdev->resource[1]->start = io->win[1].base;
+			pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
+			if (pcmcia_request_io(pdev) != 0)
 				return -ENODEV;
 			stk->ctl_base = pdev->resource[1]->start;
 		} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
-			pdev->io.NumPorts1 = io->win[0].len;
-			pdev->io.NumPorts2 = 0;
-			if (pcmcia_request_io(pdev, &pdev->io) != 0)
+			pdev->resource[0]->end = io->win[0].len;
+			pdev->resource[1]->end = 0;
+			if (pcmcia_request_io(pdev) != 0)
 				return -ENODEV;
 			stk->ctl_base = pdev->resource[0]->start + 0x0e;
 		} else
@@ -245,9 +247,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 	struct ata_port_operations *ops = &pcmcia_port_ops;
 
 	/* Set up attributes in order to probe card and get resources */
-	pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-	pdev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-	pdev->io.IOAddrLines = 3;
+	pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+	pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 	pdev->conf.Attributes = CONF_ENABLE_IRQ;
 	pdev->conf.IntType = INT_MEMORY_AND_IO;
 
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 24d2007..d52e90a 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -865,9 +865,6 @@ static int bluecard_probe(struct pcmcia_device *link)
 	info->p_dev = link;
 	link->priv = info;
 
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	link->io.NumPorts1 = 8;
-
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
@@ -890,12 +887,14 @@ static int bluecard_config(struct pcmcia_device *link)
 	int i, n;
 
 	link->conf.ConfigIndex = 0x20;
-	link->io.NumPorts1 = 64;
-	link->io.IOAddrLines = 6;
+
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	link->resource[0]->end = 64;
+	link->io_lines = 6;
 
 	for (n = 0; n < 0x400; n += 0x40) {
-		link->io.BasePort1 = n ^ 0x300;
-		i = pcmcia_request_io(link, &link->io);
+		link->resource[0]->start = n ^ 0x300;
+		i = pcmcia_request_io(link);
 		if (i == 0)
 			break;
 	}
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 8ab494c..7ab8f29 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -657,8 +657,8 @@ static int bt3c_probe(struct pcmcia_device *link)
 	info->p_dev = link;
 	link->priv = info;
 
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	link->io.NumPorts1 = 8;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	link->resource[0]->end = 8;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
@@ -683,14 +683,14 @@ static int bt3c_check_config(struct pcmcia_device *p_dev,
 {
 	unsigned long try = (unsigned long) priv_data;
 
+	p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+
 	if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
 		p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
 	    (cf->io.win[0].base != 0)) {
-		p_dev->io.BasePort1 = cf->io.win[0].base;
-		p_dev->io.IOAddrLines = (try == 0) ? 16 :
-			cf->io.flags & CISTPL_IO_LINES_MASK;
-		if (!pcmcia_request_io(p_dev, &p_dev->io))
+		p_dev->resource[0]->start = cf->io.win[0].base;
+		if (!pcmcia_request_io(p_dev))
 			return 0;
 	}
 	return -ENODEV;
@@ -707,9 +707,9 @@ static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
 
 	if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
 		for (j = 0; j < 5; j++) {
-			p_dev->io.BasePort1 = base[j];
-			p_dev->io.IOAddrLines = base[j] ? 16 : 3;
-			if (!pcmcia_request_io(p_dev, &p_dev->io))
+			p_dev->resource[0]->start = base[j];
+			p_dev->io_lines = base[j] ? 16 : 3;
+			if (!pcmcia_request_io(p_dev))
 				return 0;
 		}
 	}
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 7e770d4..1c4f5e8 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -586,8 +586,8 @@ static int btuart_probe(struct pcmcia_device *link)
 	info->p_dev = link;
 	link->priv = info;
 
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	link->io.NumPorts1 = 8;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	link->resource[0]->end = 8;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
@@ -612,14 +612,14 @@ static int btuart_check_config(struct pcmcia_device *p_dev,
 {
 	int *try = priv_data;
 
+	p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+
 	if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
 		p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
 	    (cf->io.win[0].base != 0)) {
-		p_dev->io.BasePort1 = cf->io.win[0].base;
-		p_dev->io.IOAddrLines = (*try == 0) ? 16 :
-			cf->io.flags & CISTPL_IO_LINES_MASK;
-		if (!pcmcia_request_io(p_dev, &p_dev->io))
+		p_dev->resource[0]->start = cf->io.win[0].base;
+		if (!pcmcia_request_io(p_dev))
 			return 0;
 	}
 	return -ENODEV;
@@ -636,9 +636,9 @@ static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
 
 	if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
 		for (j = 0; j < 5; j++) {
-			p_dev->io.BasePort1 = base[j];
-			p_dev->io.IOAddrLines = base[j] ? 16 : 3;
-			if (!pcmcia_request_io(p_dev, &p_dev->io))
+			p_dev->resource[0]->start = base[j];
+			p_dev->io_lines = base[j] ? 16 : 3;
+			if (!pcmcia_request_io(p_dev))
 				return 0;
 		}
 	}
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index bfe9313..18ecc57 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -572,8 +572,8 @@ static int dtl1_probe(struct pcmcia_device *link)
 	info->p_dev = link;
 	link->priv = info;
 
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	link->io.NumPorts1 = 8;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	link->resource[0]->end = 8;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
@@ -597,14 +597,13 @@ static int dtl1_confcheck(struct pcmcia_device *p_dev,
 			  unsigned int vcc,
 			  void *priv_data)
 {
-	if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
-		p_dev->io.BasePort1 = cf->io.win[0].base;
-		p_dev->io.NumPorts1 = cf->io.win[0].len;	/*yo */
-		p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-		if (!pcmcia_request_io(p_dev, &p_dev->io))
-			return 0;
-	}
-	return -ENODEV;
+	if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8))
+		return -ENODEV;
+
+	p_dev->resource[0]->start = cf->io.win[0].base;
+	p_dev->resource[0]->end = cf->io.win[0].len;	/*yo */
+	p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+	return pcmcia_request_io(p_dev);
 }
 
 static int dtl1_config(struct pcmcia_device *link)
@@ -613,7 +612,7 @@ static int dtl1_config(struct pcmcia_device *link)
 	int i;
 
 	/* Look for a generic full-sized window */
-	link->io.NumPorts1 = 8;
+	link->resource[0]->end = 8;
 	if (pcmcia_loop_config(link, dtl1_confcheck, NULL) < 0)
 		goto failed;
 
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 18484ed..ec73d9f 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1751,17 +1751,12 @@ static int cm4000_config_check(struct pcmcia_device *p_dev,
 	if (!cfg->io.nwin)
 		return -ENODEV;
 
-	/* Get the IOaddr */
-	p_dev->io.BasePort1 = cfg->io.win[0].base;
-	p_dev->io.NumPorts1 = cfg->io.win[0].len;
-	p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-	if (!(cfg->io.flags & CISTPL_IO_8BIT))
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-	if (!(cfg->io.flags & CISTPL_IO_16BIT))
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
-	return pcmcia_request_io(p_dev, &p_dev->io);
+	p_dev->resource[0]->start = cfg->io.win[0].base;
+	p_dev->resource[0]->end = cfg->io.win[0].len;
+	p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
+	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int cm4000_config(struct pcmcia_device * link, int devno)
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index a6bbf19..815cde1 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -527,16 +527,12 @@ static int cm4040_config_check(struct pcmcia_device *p_dev,
 		return -ENODEV;
 
 	/* Get the IOaddr */
-	p_dev->io.BasePort1 = cfg->io.win[0].base;
-	p_dev->io.NumPorts1 = cfg->io.win[0].len;
-	p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-	if (!(cfg->io.flags & CISTPL_IO_8BIT))
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-	if (!(cfg->io.flags & CISTPL_IO_16BIT))
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
-	rc = pcmcia_request_io(p_dev, &p_dev->io);
+	p_dev->resource[0]->start = cfg->io.win[0].base;
+	p_dev->resource[0]->end = cfg->io.win[0].len;
+	p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
+	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
+	rc = pcmcia_request_io(p_dev);
+
 	dev_printk(KERN_INFO, &p_dev->dev,
 		   "pcmcia_request_io returned 0x%x\n", rc);
 	return rc;
@@ -548,10 +544,6 @@ static int reader_config(struct pcmcia_device *link, int devno)
 	struct reader_dev *dev;
 	int fail_rc;
 
-	link->io.BasePort2 = 0;
-	link->io.NumPorts2 = 0;
-	link->io.Attributes2 = 0;
-
 	if (pcmcia_loop_config(link, cm4040_config_check, NULL))
 		goto cs_release;
 
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 9467994..5f87b9f 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -88,15 +88,15 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
 	memreq_t memreq_common_memory;
 	int ret;
 
-	p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-	p_dev->io.BasePort1 = cfg->io.win[0].base;
-	p_dev->io.NumPorts1 = cfg->io.win[0].len;
-	p_dev->io.IOAddrLines = 16;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+	p_dev->resource[0]->start = cfg->io.win[0].base;
+	p_dev->resource[0]->end = cfg->io.win[0].len;
 
 	/* 0x40 causes it to generate level mode interrupts. */
 	/* 0x04 enables IREQ pin. */
 	p_dev->conf.ConfigIndex = cfg->index | 0x44;
-	ret = pcmcia_request_io(p_dev, &p_dev->io);
+	p_dev->io_lines = 16;
+	ret = pcmcia_request_io(p_dev);
 	if (ret)
 		return ret;
 
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 8ded9b0..9ecd6be 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -571,18 +571,15 @@ static int mgslpc_ioprobe(struct pcmcia_device *p_dev,
 			  unsigned int vcc,
 			  void *priv_data)
 {
-	if (cfg->io.nwin > 0) {
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(cfg->io.flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(cfg->io.flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-		p_dev->io.BasePort1 = cfg->io.win[0].base;
-		p_dev->io.NumPorts1 = cfg->io.win[0].len;
-		return pcmcia_request_io(p_dev, &p_dev->io);
-	}
-	return -ENODEV;
+	if (!cfg->io.nwin)
+		return -ENODEV;
+
+	p_dev->resource[0]->start = cfg->io.win[0].base;
+	p_dev->resource[0]->end = cfg->io.win[0].len;
+	p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
+	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int mgslpc_config(struct pcmcia_device *link)
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index 34eafaf..c1a16f3 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -97,9 +97,8 @@ static int ide_probe(struct pcmcia_device *link)
     info->p_dev = link;
     link->priv = info;
 
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-    link->io.IOAddrLines = 3;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
@@ -228,22 +227,25 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev,
 
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+		pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+
 		pdev->conf.ConfigIndex = cfg->index;
-		pdev->io.BasePort1 = io->win[0].base;
-		pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+		pdev->resource[0]->start = io->win[0].base;
+		if (!(io->flags & CISTPL_IO_16BIT)) {
+			pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+			pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+		}
 		if (io->nwin == 2) {
-			pdev->io.NumPorts1 = 8;
-			pdev->io.BasePort2 = io->win[1].base;
-			pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
-			if (pcmcia_request_io(pdev, &pdev->io) != 0)
+			pdev->resource[0]->end = 8;
+			pdev->resource[1]->start = io->win[1].base;
+			pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
+			if (pcmcia_request_io(pdev) != 0)
 				return -ENODEV;
 			stk->ctl_base = pdev->resource[1]->start;
 		} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
-			pdev->io.NumPorts1 = io->win[0].len;
-			pdev->io.NumPorts2 = 0;
-			if (pcmcia_request_io(pdev, &pdev->io) != 0)
+			pdev->resource[0]->end = io->win[0].len;
+			pdev->resource[1]->end = 0;
+			if (pcmcia_request_io(pdev) != 0)
 				return -ENODEV;
 			stk->ctl_base = pdev->resource[1]->start + 0x0e;
 		} else
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 7c8c51f..09b1795 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -75,9 +75,8 @@ static int avmcs_probe(struct pcmcia_device *p_dev)
 {
 
     /* The io structure describes IO port mapping */
-    p_dev->io.NumPorts1 = 16;
-    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    p_dev->io.NumPorts2 = 0;
+    p_dev->resource[0]->end = 16;
+    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
     /* General socket configuration */
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
@@ -119,13 +118,9 @@ static int avmcs_configcheck(struct pcmcia_device *p_dev,
 	if (cf->io.nwin <= 0)
 		return -ENODEV;
 
-	p_dev->io.BasePort1 = cf->io.win[0].base;
-	p_dev->io.NumPorts1 = cf->io.win[0].len;
-	p_dev->io.NumPorts2 = 0;
-	printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
-	       p_dev->io.BasePort1,
-	       p_dev->io.BasePort1+p_dev->io.NumPorts1-1);
-	return pcmcia_request_io(p_dev, &p_dev->io);
+	p_dev->resource[0]->start = cf->io.win[0].base;
+	p_dev->resource[0]->end = cf->io.win[0].len;
+	return pcmcia_request_io(p_dev);
 }
 
 static int avmcs_config(struct pcmcia_device *link)
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 8889963..94263c2 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -78,11 +78,10 @@ static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
     dev_dbg(&p_dev->dev, "avma1cs_attach()\n");
 
     /* The io structure describes IO port mapping */
-    p_dev->io.NumPorts1 = 16;
-    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    p_dev->io.NumPorts2 = 16;
-    p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
-    p_dev->io.IOAddrLines = 5;
+    p_dev->resource[0]->end = 16;
+    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+    p_dev->resource[1]->end = 16;
+    p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
 
     /* General socket configuration */
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
@@ -126,13 +125,10 @@ static int avma1cs_configcheck(struct pcmcia_device *p_dev,
 	if (cf->io.nwin <= 0)
 		return -ENODEV;
 
-	p_dev->io.BasePort1 = cf->io.win[0].base;
-	p_dev->io.NumPorts1 = cf->io.win[0].len;
-	p_dev->io.NumPorts2 = 0;
-	printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
-	       p_dev->io.BasePort1,
-	       p_dev->io.BasePort1+p_dev->io.NumPorts1-1);
-	return pcmcia_request_io(p_dev, &p_dev->io);
+	p_dev->resource[0]->start = cf->io.win[0].base;
+	p_dev->resource[0]->end = cf->io.win[0].len;
+	p_dev->io_lines = 5;
+	return pcmcia_request_io(p_dev);
 }
 
 
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index c10bfd3..b3c08aa 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -126,9 +126,8 @@ static int __devinit elsa_cs_probe(struct pcmcia_device *link)
       and attributes of IO windows) are fixed by the nature of the
       device, and can be hard-wired here.
     */
-    link->io.NumPorts1 = 8;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-    link->io.IOAddrLines = 3;
+    link->resource[0]->end = 8;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
@@ -173,16 +172,18 @@ static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
 {
 	int j;
 
+	p_dev->io_lines = 3;
+
 	if ((cf->io.nwin > 0) && cf->io.win[0].base) {
 		printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
-		p_dev->io.BasePort1 = cf->io.win[0].base;
-		if (!pcmcia_request_io(p_dev, &p_dev->io))
+		p_dev->resource[0]->start = cf->io.win[0].base;
+		if (!pcmcia_request_io(p_dev))
 			return 0;
 	} else {
 		printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
 		for (j = 0x2f0; j > 0x100; j -= 0x10) {
-			p_dev->io.BasePort1 = j;
-			if (!pcmcia_request_io(p_dev, &p_dev->io))
+			p_dev->resource[0]->start = j;
+			if (!pcmcia_request_io(p_dev))
 				return 0;
 		}
 	}
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index cecb35a..4755eb4 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -129,9 +129,8 @@ static int __devinit sedlbauer_probe(struct pcmcia_device *link)
     /* from old sedl_cs 
     */
     /* The io structure describes IO port mapping */
-    link->io.NumPorts1 = 8;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    link->io.IOAddrLines = 3;
+    link->resource[0]->end = 8;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
     link->conf.Attributes = 0;
     link->conf.IntType = INT_MEMORY_AND_IO;
@@ -201,23 +200,22 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+					pcmcia_io_cfg_data_width(io->flags);
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+		p_dev->io_lines = 3;
+		if (pcmcia_request_io(p_dev) != 0)
 			return -ENODEV;
 	}
 
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 3787fc7..7296102 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -106,9 +106,8 @@ static int __devinit teles_probe(struct pcmcia_device *link)
       and attributes of IO windows) are fixed by the nature of the
       device, and can be hard-wired here.
     */
-    link->io.NumPorts1 = 96;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-    link->io.IOAddrLines = 5;
+    link->resource[0]->end = 96;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
@@ -153,16 +152,18 @@ static int teles_cs_configcheck(struct pcmcia_device *p_dev,
 {
 	int j;
 
+	p_dev->io_lines = 5;
+
 	if ((cf->io.nwin > 0) && cf->io.win[0].base) {
 		printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
-		p_dev->io.BasePort1 = cf->io.win[0].base;
-		if (!pcmcia_request_io(p_dev, &p_dev->io))
+		p_dev->resource[0]->start = cf->io.win[0].base;
+		if (!pcmcia_request_io(p_dev))
 			return 0;
 	} else {
 		printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
 		for (j = 0x2f0; j > 0x100; j -= 0x10) {
-			p_dev->io.BasePort1 = j;
-			if (!pcmcia_request_io(p_dev, &p_dev->io))
+			p_dev->resource[0]->start = j;
+			if (!pcmcia_request_io(p_dev))
 				return 0;
 		}
 	}
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index b5ea9b8..c683f77 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -278,8 +278,8 @@ static int tc574_probe(struct pcmcia_device *link)
 	lp->p_dev = link;
 
 	spin_lock_init(&lp->window_lock);
-	link->io.NumPorts1 = 32;
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+	link->resource[0]->end = 32;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.ConfigIndex = 1;
@@ -337,10 +337,11 @@ static int tc574_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "3c574_config()\n");
 
-	link->io.IOAddrLines = 16;
+	link->io_lines = 16;
+
 	for (i = j = 0; j < 0x400; j += 0x20) {
-		link->io.BasePort1 = j ^ 0x300;
-		i = pcmcia_request_io(link, &link->io);
+		link->resource[0]->start = j ^ 0x300;
+		i = pcmcia_request_io(link);
 		if (i == 0)
 			break;
 	}
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 122ef4a..61f9cf2 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -213,8 +213,8 @@ static int tc589_probe(struct pcmcia_device *link)
     lp->p_dev = link;
 
     spin_lock_init(&lp->lock);
-    link->io.NumPorts1 = 16;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+    link->resource[0]->end = 16;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
@@ -277,12 +277,13 @@ static int tc589_config(struct pcmcia_device *link)
 		   "3Com card??\n");
     multi = (link->card_id == PRODID_3COM_3C562);
 
+    link->io_lines = 16;
+
     /* For the 3c562, the base address must be xx00-xx7f */
-    link->io.IOAddrLines = 16;
     for (i = j = 0; j < 0x400; j += 0x10) {
 	if (multi && (j & 0x80)) continue;
-	link->io.BasePort1 = j ^ 0x300;
-	i = pcmcia_request_io(link, &link->io);
+	link->resource[0]->start = j ^ 0x300;
+	i = pcmcia_request_io(link);
 	if (i == 0)
 		break;
     }
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index c52fdf3..5f05ffb 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -259,28 +259,30 @@ static int get_prom(struct pcmcia_device *link)
 static int try_io_port(struct pcmcia_device *link)
 {
     int j, ret;
-    if (link->io.NumPorts1 == 32) {
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+    link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+    link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+    if (link->resource[0]->end == 32) {
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	/* for master/slave multifunction cards */
-	if (link->io.NumPorts2 > 0)
-	    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
+	if (link->resource[1]->end > 0)
+	    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
     } else {
 	/* This should be two 16-port windows */
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
     }
-    if (link->io.BasePort1 == 0) {
-	link->io.IOAddrLines = 16;
+    if (link->resource[0]->start == 0) {
 	for (j = 0; j < 0x400; j += 0x20) {
-	    link->io.BasePort1 = j ^ 0x300;
-	    link->io.BasePort2 = (j ^ 0x300) + 0x10;
-	    ret = pcmcia_request_io(link, &link->io);
+	    link->resource[0]->start = j ^ 0x300;
+	    link->resource[1]->start = (j ^ 0x300) + 0x10;
+	    link->io_lines = 16;
+	    ret = pcmcia_request_io(link);
 	    if (ret == 0)
 		    return ret;
 	}
 	return ret;
     } else {
-	return pcmcia_request_io(link, &link->io);
+	return pcmcia_request_io(link);
     }
 }
 
@@ -301,15 +303,15 @@ static int axnet_configcheck(struct pcmcia_device *p_dev,
 	   network function with window 0, and serial with window 1 */
 	if (io->nwin > 1) {
 		i = (io->win[1].len > io->win[0].len);
-		p_dev->io.BasePort2 = io->win[1-i].base;
-		p_dev->io.NumPorts2 = io->win[1-i].len;
+		p_dev->resource[1]->start = io->win[1-i].base;
+		p_dev->resource[1]->end = io->win[1-i].len;
 	} else {
-		i = p_dev->io.NumPorts2 = 0;
+		i = p_dev->resource[1]->end = 0;
 	}
-	p_dev->io.BasePort1 = io->win[i].base;
-	p_dev->io.NumPorts1 = io->win[i].len;
-	p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-	if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
+	p_dev->resource[0]->start = io->win[i].base;
+	p_dev->resource[0]->end = io->win[i].len;
+	p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+	if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
 		return try_io_port(p_dev);
 
 	return -ENODEV;
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 3b53818..3c400cf 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -158,9 +158,8 @@ static int com20020_probe(struct pcmcia_device *p_dev)
     /* fill in our module parameters as defaults */
     dev->dev_addr[0] = node;
 
-    p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    p_dev->io.NumPorts1 = 16;
-    p_dev->io.IOAddrLines = 16;
+    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+    p_dev->resource[0]->end = 16;
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
     p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
@@ -245,20 +244,24 @@ static int com20020_config(struct pcmcia_device *link)
 
     dev_dbg(&link->dev, "com20020_config\n");
 
-    dev_dbg(&link->dev, "baseport1 is %Xh\n", link->io.BasePort1);
+    dev_dbg(&link->dev, "baseport1 is %Xh\n",
+	    (unsigned int) link->resource[0]->start);
+
     i = -ENODEV;
-    if (!link->io.BasePort1)
+    link->io_lines = 16;
+
+    if (!link->resource[0]->start)
     {
 	for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10)
 	{
-	    link->io.BasePort1 = ioaddr;
-	    i = pcmcia_request_io(link, &link->io);
+	    link->resource[0]->start = ioaddr;
+	    i = pcmcia_request_io(link);
 	    if (i == 0)
 		break;
 	}
     }
     else
-	i = pcmcia_request_io(link, &link->io);
+	i = pcmcia_request_io(link);
     
     if (i != 0)
     {
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index bba6369..6993044 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -248,9 +248,8 @@ static int fmvj18x_probe(struct pcmcia_device *link)
     lp->base = NULL;
 
     /* The io structure describes IO port mapping */
-    link->io.NumPorts1 = 32;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-    link->io.IOAddrLines = 5;
+    link->resource[0]->end = 32;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
@@ -288,13 +287,13 @@ static int mfc_try_io_port(struct pcmcia_device *link)
 	{ 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
 
     for (i = 0; i < 5; i++) {
-	link->io.BasePort2 = serial_base[i];
-	link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-	if (link->io.BasePort2 == 0) {
-	    link->io.NumPorts2 = 0;
+	link->resource[1]->start = serial_base[i];
+	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+	if (link->resource[1]->start == 0) {
+	    link->resource[1]->end = 0;
 	    printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
 	}
-	ret = pcmcia_request_io(link, &link->io);
+	ret = pcmcia_request_io(link);
 	if (ret == 0)
 		return ret;
     }
@@ -310,8 +309,8 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
 	0x380,0x3c0 only for ioport.
     */
     for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
-	link->io.BasePort1 = ioaddr;
-	ret = pcmcia_request_io(link, &link->io);
+	link->resource[0]->start = ioaddr;
+	ret = pcmcia_request_io(link);
 	if (ret == 0) {
 	    /* calculate ConfigIndex value */
 	    link->conf.ConfigIndex = 
@@ -345,6 +344,8 @@ static int fmvj18x_config(struct pcmcia_device *link)
 
     dev_dbg(&link->dev, "fmvj18x_config\n");
 
+    link->io_lines = 5;
+
     len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf);
     kfree(buf);
 
@@ -363,20 +364,20 @@ static int fmvj18x_config(struct pcmcia_device *link)
 		/* MultiFunction Card */
 		link->conf.ConfigBase = 0x800;
 		link->conf.ConfigIndex = 0x47;
-		link->io.NumPorts2 = 8;
+		link->resource[1]->end = 8;
 	    }
 	    break;
 	case MANFID_NEC:
 	    cardtype = NEC; /* MultiFunction Card */
 	    link->conf.ConfigBase = 0x800;
 	    link->conf.ConfigIndex = 0x47;
-	    link->io.NumPorts2 = 8;
+	    link->resource[1]->end = 8;
 	    break;
 	case MANFID_KME:
 	    cardtype = KME; /* MultiFunction Card */
 	    link->conf.ConfigBase = 0x800;
 	    link->conf.ConfigIndex = 0x47;
-	    link->io.NumPorts2 = 8;
+	    link->resource[1]->end = 8;
 	    break;
 	case MANFID_CONTEC:
 	    cardtype = CONTEC;
@@ -417,14 +418,14 @@ static int fmvj18x_config(struct pcmcia_device *link)
 	}
     }
 
-    if (link->io.NumPorts2 != 0) {
+    if (link->resource[1]->end != 0) {
 	ret = mfc_try_io_port(link);
 	if (ret != 0) goto failed;
     } else if (cardtype == UNGERMANN) {
 	ret = ungermann_try_io_port(link);
 	if (ret != 0) goto failed;
     } else { 
-	    ret = pcmcia_request_io(link, &link->io);
+	    ret = pcmcia_request_io(link);
 	    if (ret)
 		    goto failed;
     }
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index e99abaa..3fd8595 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -151,9 +151,8 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link)
     link->priv = info;
     info->ti = netdev_priv(dev);
 
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    link->io.NumPorts1 = 4;
-    link->io.IOAddrLines = 16;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+    link->resource[0]->end = 4;
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
@@ -218,16 +217,17 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
     dev_dbg(&link->dev, "ibmtr_config\n");
 
     link->conf.ConfigIndex = 0x61;
+    link->io_lines = 16;
 
     /* Determine if this is PRIMARY or ALTERNATE. */
 
     /* Try PRIMARY card at 0xA20-0xA23 */
-    link->io.BasePort1 = 0xA20;
-    i = pcmcia_request_io(link, &link->io);
+    link->resource[0]->start = 0xA20;
+    i = pcmcia_request_io(link);
     if (i != 0) {
 	/* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */
-	link->io.BasePort1 = 0xA24;
-	ret = pcmcia_request_io(link, &link->io);
+	link->resource[0]->start = 0xA24;
+	ret = pcmcia_request_io(link);
 	if (ret)
 		goto failed;
     }
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 9980cbb..68f2dee 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -458,9 +458,8 @@ static int nmclan_probe(struct pcmcia_device *link)
     link->priv = dev;
     
     spin_lock_init(&lp->bank_lock);
-    link->io.NumPorts1 = 32;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-    link->io.IOAddrLines = 5;
+    link->resource[0]->end = 32;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
@@ -644,7 +643,8 @@ static int nmclan_config(struct pcmcia_device *link)
 
   dev_dbg(&link->dev, "nmclan_config\n");
 
-  ret = pcmcia_request_io(link, &link->io);
+  link->io_lines = 5;
+  ret = pcmcia_request_io(link);
   if (ret)
 	  goto failed;
   ret = pcmcia_request_exclusive_irq(link, mace_interrupt);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index c9cd237..9c5fc9d 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -477,29 +477,31 @@ static hw_info_t *get_hwired(struct pcmcia_device *link)
 static int try_io_port(struct pcmcia_device *link)
 {
     int j, ret;
-    if (link->io.NumPorts1 == 32) {
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-	if (link->io.NumPorts2 > 0) {
+    link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+    link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+    if (link->resource[0]->end == 32) {
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+	if (link->resource[1]->end > 0) {
 	    /* for master/slave multifunction cards */
-	    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
+	    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 	}
     } else {
 	/* This should be two 16-port windows */
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
     }
-    if (link->io.BasePort1 == 0) {
-	link->io.IOAddrLines = 16;
+    if (link->resource[0]->start == 0) {
 	for (j = 0; j < 0x400; j += 0x20) {
-	    link->io.BasePort1 = j ^ 0x300;
-	    link->io.BasePort2 = (j ^ 0x300) + 0x10;
-	    ret = pcmcia_request_io(link, &link->io);
+	    link->resource[0]->start = j ^ 0x300;
+	    link->resource[1]->start = (j ^ 0x300) + 0x10;
+	    link->io_lines = 16;
+	    ret = pcmcia_request_io(link);
 	    if (ret == 0)
 		    return ret;
 	}
 	return ret;
     } else {
-	return pcmcia_request_io(link, &link->io);
+	return pcmcia_request_io(link);
     }
 }
 
@@ -520,18 +522,18 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev,
 	   network function with window 0, and serial with window 1 */
 	if (io->nwin > 1) {
 		i = (io->win[1].len > io->win[0].len);
-		p_dev->io.BasePort2 = io->win[1-i].base;
-		p_dev->io.NumPorts2 = io->win[1-i].len;
+		p_dev->resource[1]->start = io->win[1-i].base;
+		p_dev->resource[1]->end = io->win[1-i].len;
 	} else {
-		i = p_dev->io.NumPorts2 = 0;
+		i = p_dev->resource[1]->end = 0;
 	}
 
 	*has_shmem = ((cfg->mem.nwin == 1) &&
 		      (cfg->mem.win[0].len >= 0x4000));
-	p_dev->io.BasePort1 = io->win[i].base;
-	p_dev->io.NumPorts1 = io->win[i].len;
-	p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-	if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
+	p_dev->resource[0]->start = io->win[i].base;
+	p_dev->resource[0]->end = io->win[i].len;
+	p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+	if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
 		return try_io_port(p_dev);
 
 	return 0;
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 1b0b323..a5e4779 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -324,9 +324,8 @@ static int smc91c92_probe(struct pcmcia_device *link)
     link->priv = dev;
 
     spin_lock_init(&smc->lock);
-    link->io.NumPorts1 = 16;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-    link->io.IOAddrLines = 4;
+    link->resource[0]->end = 16;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
@@ -427,12 +426,13 @@ static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
 				void *priv_data)
 {
 	int k;
-	p_dev->io.BasePort2 = cf->io.win[0].base;
+	p_dev->resource[1]->start = cf->io.win[0].base;
 	for (k = 0; k < 0x400; k += 0x10) {
 		if (k & 0x80)
 			continue;
-		p_dev->io.BasePort1 = k ^ 0x300;
-		if (!pcmcia_request_io(p_dev, &p_dev->io))
+		p_dev->resource[0]->start = k ^ 0x300;
+		p_dev->io_lines = 16;
+		if (!pcmcia_request_io(p_dev))
 			return 0;
 	}
 	return -ENODEV;
@@ -448,9 +448,8 @@ static int mhz_mfc_config(struct pcmcia_device *link)
 
     link->conf.Attributes |= CONF_ENABLE_SPKR;
     link->conf.Status = CCSR_AUDIO_ENA;
-    link->io.IOAddrLines = 16;
-    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-    link->io.NumPorts2 = 8;
+    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+    link->resource[1]->end = 8;
 
     /* The Megahertz combo cards have modem-like CIS entries, so
        we have to explicitly try a bunch of port combinations. */
@@ -601,9 +600,9 @@ static int smc_configcheck(struct pcmcia_device *p_dev,
 			   unsigned int vcc,
 			   void *priv_data)
 {
-	p_dev->io.BasePort1 = cf->io.win[0].base;
-	p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-	return pcmcia_request_io(p_dev, &p_dev->io);
+	p_dev->resource[0]->start = cf->io.win[0].base;
+	p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+	return pcmcia_request_io(p_dev);
 }
 
 static int smc_config(struct pcmcia_device *link)
@@ -611,7 +610,7 @@ static int smc_config(struct pcmcia_device *link)
     struct net_device *dev = link->priv;
     int i;
 
-    link->io.NumPorts1 = 16;
+    link->resource[0]->end = 16;
     i = pcmcia_loop_config(link, smc_configcheck, NULL);
     if (!i)
 	    dev->base_addr = link->resource[0]->start;
@@ -646,25 +645,25 @@ static int osi_config(struct pcmcia_device *link)
 
     link->conf.Attributes |= CONF_ENABLE_SPKR;
     link->conf.Status = CCSR_AUDIO_ENA;
-    link->io.NumPorts1 = 64;
-    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-    link->io.NumPorts2 = 8;
-    link->io.IOAddrLines = 16;
+    link->resource[0]->end = 64;
+    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+    link->resource[1]->end = 8;
 
     /* Enable Hard Decode, LAN, Modem */
     link->conf.ConfigIndex = 0x23;
+    link->io_lines = 16;
 
     for (i = j = 0; j < 4; j++) {
-	link->io.BasePort2 = com[j];
-	i = pcmcia_request_io(link, &link->io);
+	link->resource[1]->start = com[j];
+	i = pcmcia_request_io(link);
 	if (i == 0)
 		break;
     }
     if (i != 0) {
 	/* Fallback: turn off hard decode */
 	link->conf.ConfigIndex = 0x03;
-	link->io.NumPorts2 = 0;
-	i = pcmcia_request_io(link, &link->io);
+	link->resource[1]->end = 0;
+	i = pcmcia_request_io(link);
     }
     dev->base_addr = link->resource[0]->start + 0x10;
     return i;
@@ -803,7 +802,7 @@ static int check_sig(struct pcmcia_device *link)
     }
 
     /* Try setting bus width */
-    width = (link->io.Attributes1 == IO_DATA_PATH_WIDTH_AUTO);
+    width = (link->resource[0]->flags == IO_DATA_PATH_WIDTH_AUTO);
     s = inb(ioaddr + CONFIG);
     if (width)
 	s |= CFG_16BIT;
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 1577b00..e051d3a 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -677,9 +677,9 @@ xirc2ps_config_modem(struct pcmcia_device *p_dev,
 
 	if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8) {
 		for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
-			p_dev->io.BasePort2 = cf->io.win[0].base;
-			p_dev->io.BasePort1 = ioaddr;
-			if (!pcmcia_request_io(p_dev, &p_dev->io))
+			p_dev->resource[1]->start = cf->io.win[0].base;
+			p_dev->resource[0]->start = ioaddr;
+			if (!pcmcia_request_io(p_dev))
 				return 0;
 		}
 	}
@@ -696,11 +696,11 @@ xirc2ps_config_check(struct pcmcia_device *p_dev,
 	int *pass = priv_data;
 
 	if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
-		p_dev->io.BasePort2 = cf->io.win[0].base;
-		p_dev->io.BasePort1 = p_dev->io.BasePort2
+		p_dev->resource[1]->start = cf->io.win[0].base;
+		p_dev->resource[0]->start = p_dev->resource[1]->start
 			+ (*pass ? (cf->index & 0x20 ? -24:8)
 			   : (cf->index & 0x20 ?   8:-24));
-		if (!pcmcia_request_io(p_dev, &p_dev->io))
+		if (!pcmcia_request_io(p_dev))
 			return 0;
 	}
 	return -ENODEV;
@@ -807,8 +807,7 @@ xirc2ps_config(struct pcmcia_device * link)
 	goto failure;
     }
 
-    link->io.IOAddrLines =10;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
     if (local->modem) {
 	int pass;
 
@@ -816,16 +815,16 @@ xirc2ps_config(struct pcmcia_device * link)
 	    link->conf.Attributes |= CONF_ENABLE_SPKR;
 	    link->conf.Status |= CCSR_AUDIO_ENA;
 	}
-	link->io.NumPorts2 = 8;
-	link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
+	link->resource[1]->end = 8;
+	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 	if (local->dingo) {
 	    /* Take the Modem IO port from the CIS and scan for a free
 	     * Ethernet port */
-	    link->io.NumPorts1 = 16; /* no Mako stuff anymore */
+	    link->resource[0]->end = 16; /* no Mako stuff anymore */
 	    if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL))
 		    goto port_found;
 	} else {
-	    link->io.NumPorts1 = 18;
+	    link->resource[0]->end = 18;
 	    /* We do 2 passes here: The first one uses the regular mapping and
 	     * the second tries again, thereby considering that the 32 ports are
 	     * mirrored every 32 bytes. Actually we use a mirrored port for
@@ -840,14 +839,15 @@ xirc2ps_config(struct pcmcia_device * link)
 	}
 	printk(KNOT_XIRC "no ports available\n");
     } else {
-	link->io.NumPorts1 = 16;
+	link->io_lines = 10;
+	link->resource[0]->end = 16;
 	for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
-	    link->io.BasePort1 = ioaddr;
-	    if (!(err=pcmcia_request_io(link, &link->io)))
+	    link->resource[0]->start = ioaddr;
+	    if (!(err = pcmcia_request_io(link)))
 		goto port_found;
 	}
-	link->io.BasePort1 = 0; /* let CS decide */
-	if ((err=pcmcia_request_io(link, &link->io)))
+	link->resource[0]->start = 0; /* let CS decide */
+	if ((err = pcmcia_request_io(link)))
 	    goto config_error;
     }
   port_found:
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index b7e7f50..d241b4a 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -175,25 +175,23 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+					pcmcia_io_cfg_data_width(io->flags);
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 	}
 
 	/* This reserves IO space but doesn't actually enable it */
-	if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+	if (pcmcia_request_io(p_dev) != 0)
 		return -ENODEV;
 
 	/*
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 65b3aed..3b63216 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -190,25 +190,23 @@ static int atmel_config_check(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+					pcmcia_io_cfg_data_width(io->flags);
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 	}
 
 	/* This reserves IO space but doesn't actually enable it */
-	return pcmcia_request_io(p_dev, &p_dev->io);
+	return pcmcia_request_io(p_dev);
 }
 
 static int atmel_config(struct pcmcia_device *link)
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index f71bc78..7c9af82 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -77,10 +77,6 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 	dev->conf.Attributes = CONF_ENABLE_IRQ;
 	dev->conf.IntType = INT_MEMORY_AND_IO;
 
-	dev->io.BasePort2 = 0;
-	dev->io.NumPorts2 = 0;
-	dev->io.Attributes2 = 0;
-
 	win.Attributes = WIN_ADDR_SPACE_MEM | WIN_MEMORY_TYPE_CM |
 			 WIN_ENABLE | WIN_DATA_WIDTH_16 |
 			 WIN_USE_WAIT;
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 6db7fd1..04edfa9 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -519,30 +519,24 @@ static int prism2_config_check(struct pcmcia_device *p_dev,
 	PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
 	       "dflt->io.nwin=%d\n",
 	       cfg->io.nwin, dflt->io.nwin);
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, "
-		       "io.base=0x%04x, len=%d\n", io->flags,
-		       io->win[0].base, io->win[0].len);
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.IOAddrLines = io->flags &
-			CISTPL_IO_LINES_MASK;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+					pcmcia_io_cfg_data_width(io->flags);
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 	}
 
 	/* This reserves IO space but doesn't actually enable it */
-	return pcmcia_request_io(p_dev, &p_dev->io);
+	return pcmcia_request_io(p_dev);
 }
 
 static int prism2_config(struct pcmcia_device *link)
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index be4c475..9c29839 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -801,9 +801,9 @@ static int if_cs_ioprobe(struct pcmcia_device *p_dev,
 			 unsigned int vcc,
 			 void *priv_data)
 {
-	p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-	p_dev->io.BasePort1 = cfg->io.win[0].base;
-	p_dev->io.NumPorts1 = cfg->io.win[0].len;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+	p_dev->resource[0]->start = cfg->io.win[0].base;
+	p_dev->resource[0]->end = cfg->io.win[0].len;
 
 	/* Do we need to allocate an interrupt? */
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
@@ -815,7 +815,7 @@ static int if_cs_ioprobe(struct pcmcia_device *p_dev,
 	}
 
 	/* This reserves IO space but doesn't actually enable it */
-	return pcmcia_request_io(p_dev, &p_dev->io);
+	return pcmcia_request_io(p_dev);
 }
 
 static int if_cs_probe(struct pcmcia_device *p_dev)
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index 6d514b5..ef46a2d 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -191,25 +191,23 @@ static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+			pcmcia_io_cfg_data_width(io->flags);
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 
 		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+		if (pcmcia_request_io(p_dev) != 0)
 			goto next_entry;
 	}
 	return 0;
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 4f8f55e..873877e 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -253,25 +253,23 @@ static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+			pcmcia_io_cfg_data_width(io->flags);
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 
 		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+		if (pcmcia_request_io(p_dev) != 0)
 			goto next_entry;
 	}
 	return 0;
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 165beb6..b83d5ef 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -315,9 +315,8 @@ static int ray_probe(struct pcmcia_device *p_dev)
 	local->finder = p_dev;
 
 	/* The io structure describes IO port mapping. None used here */
-	p_dev->io.NumPorts1 = 0;
-	p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	p_dev->io.IOAddrLines = 5;
+	p_dev->resource[0]->end = 0;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
 	/* General socket configuration */
 	p_dev->conf.Attributes = CONF_ENABLE_IRQ;
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index a32f220..a1cc2d4 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1884,9 +1884,8 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
 	struct wl3501_card *this;
 
 	/* The io structure describes IO port mapping */
-	p_dev->io.NumPorts1	= 16;
-	p_dev->io.Attributes1	= IO_DATA_PATH_WIDTH_8;
-	p_dev->io.IOAddrLines	= 5;
+	p_dev->resource[0]->end	= 16;
+	p_dev->resource[0]->flags	= IO_DATA_PATH_WIDTH_8;
 
 	/* General socket configuration */
 	p_dev->conf.Attributes	= CONF_ENABLE_IRQ;
@@ -1932,13 +1931,14 @@ static int wl3501_config(struct pcmcia_device *link)
 	/* Try allocating IO ports.  This tries a few fixed addresses.  If you
 	 * want, you can also read the card's config table to pick addresses --
 	 * see the serial driver for an example. */
+	link->io_lines = 5;
 
 	for (j = 0x280; j < 0x400; j += 0x20) {
 		/* The '^0x300' is so that we probe 0x300-0x3ff first, then
 		 * 0x200-0x2ff, and so on, because this seems safer */
-		link->io.BasePort1 = j;
-		link->io.BasePort2 = link->io.BasePort1 + 0x10;
-		i = pcmcia_request_io(link, &link->io);
+		link->resource[0]->start = j;
+		link->resource[1]->start = link->resource[0]->start + 0x10;
+		i = pcmcia_request_io(link);
 		if (i == 0)
 			break;
 	}
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index fc1639c..23e50f4 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -101,8 +101,8 @@ static int parport_probe(struct pcmcia_device *link)
     link->priv = info;
     info->p_dev = link;
 
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
@@ -143,16 +143,16 @@ static int parport_config_check(struct pcmcia_device *p_dev,
 {
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
 		if (epp_mode)
 			p_dev->conf.ConfigIndex |= FORCE_EPP_MODE;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
-		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin == 2) {
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
-		if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+		if (pcmcia_request_io(p_dev) != 0)
 			return -ENODEV;
 		return 0;
 	}
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index fcd48da..a48d4a9 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -70,7 +70,8 @@ static int alloc_io_space(struct pcmcia_socket *s, struct resource *res,
 
 	res->flags |= IORESOURCE_IO;
 
-	dev_dbg(&s->dev, "alloc_io_space request for %pR\n", res);
+	dev_dbg(&s->dev, "alloc_io_space request for %pR, %d lines\n",
+		res, lines);
 
 	align = base ? (lines ? 1<<lines : 0) : 1;
 	if (align && (align < num)) {
@@ -541,38 +542,25 @@ EXPORT_SYMBOL(pcmcia_request_configuration);
  * pcmcia_request_io() - attempt to reserve port ranges for PCMCIA devices
  *
  * pcmcia_request_io() attepts to reserve the IO port ranges specified in
- * struct pcmcia_device *p_dev->resource[0] and *p_dev->resource[1]. The
+ * &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The
  * "start" value is the requested start of the IO port resource; "end"
- * relfects the number of ports requested.
- *
- * If io_req_t is passed, those values are converted automatically.
+ * reflects the number of ports requested. The number of IO lines requested
+ * is specified in &struct pcmcia_device @p_dev->io_lines.
  */
-int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
+int pcmcia_request_io(struct pcmcia_device *p_dev)
 {
 	struct pcmcia_socket *s = p_dev->socket;
-	config_t *c;
+	config_t *c = p_dev->function_config;
 	int ret = -EINVAL;
-	unsigned int lines = req->IOAddrLines;
 
 	mutex_lock(&s->ops_mutex);
+	dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]);
 
 	if (!(s->state & SOCKET_PRESENT)) {
 		dev_dbg(&s->dev, "pcmcia_request_io: No card present\n");
 		goto out;
 	}
 
-	c = p_dev->function_config;
-	if (req) {
-		c->io[0].start = req->BasePort1;
-		c->io[0].end = req->NumPorts1;
-		c->io[0].flags |= req->Attributes1;
-		c->io[1].start = req->BasePort2;
-		c->io[1].end = req->NumPorts2;
-		c->io[1].flags |= req->Attributes2;
-	}
-
-	dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]);
-
 	if (c->state & CONFIG_LOCKED) {
 		dev_dbg(&s->dev, "Configuration is locked\n");
 		goto out;
@@ -582,12 +570,12 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
 		goto out;
 	}
 
-	ret = alloc_io_space(s, &c->io[0], lines);
+	ret = alloc_io_space(s, &c->io[0], p_dev->io_lines);
 	if (ret)
 		goto out;
 
 	if (c->io[1].end) {
-		ret = alloc_io_space(s, &c->io[1], lines);
+		ret = alloc_io_space(s, &c->io[1], p_dev->io_lines);
 		if (ret) {
 			release_io_space(s, &c->io[0]);
 			goto out;
@@ -598,11 +586,6 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
 	c->state |= CONFIG_IO_REQ;
 	p_dev->_io = 1;
 
-	if (!ret) {
-		req->BasePort1 = c->io[0].start;
-		req->BasePort2 = c->io[1].start;
-	}
-
 	dev_dbg(&s->dev, "pcmcia_request_io succeeded: %pR , %pR",
 		&c->io[0], &c->io[1]);
 out:
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 3e040f5..61f49bd 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -100,9 +100,8 @@ static int aha152x_probe(struct pcmcia_device *link)
     info->p_dev = link;
     link->priv = info;
 
-    link->io.NumPorts1 = 0x20;
-    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-    link->io.IOAddrLines = 10;
+    link->resource[0]->end = 0x20;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
@@ -130,15 +129,16 @@ static int aha152x_config_check(struct pcmcia_device *p_dev,
 				unsigned int vcc,
 				void *priv_data)
 {
+	p_dev->io_lines = 10;
 	/* For New Media T&J, look for a SCSI window */
 	if (cfg->io.win[0].len >= 0x20)
-		p_dev->io.BasePort1 = cfg->io.win[0].base;
+		p_dev->resource[0]->start = cfg->io.win[0].base;
 	else if ((cfg->io.nwin > 1) &&
 		 (cfg->io.win[1].len >= 0x20))
-		p_dev->io.BasePort1 = cfg->io.win[1].base;
+		p_dev->resource[0]->start = cfg->io.win[1].base;
 	if ((cfg->io.nwin > 0) &&
-	    (p_dev->io.BasePort1 < 0xffff)) {
-		if (!pcmcia_request_io(p_dev, &p_dev->io))
+	    (p_dev->resource[0]->start < 0xffff)) {
+		if (!pcmcia_request_io(p_dev))
 			return 0;
 	}
 	return -EINVAL;
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 49a9a0a..13dbe5c 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -83,9 +83,8 @@ static int fdomain_probe(struct pcmcia_device *link)
 
 	info->p_dev = link;
 	link->priv = info;
-	link->io.NumPorts1 = 0x10;
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-	link->io.IOAddrLines = 10;
+	link->resource[0]->end = 0x10;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.Present = PRESENT_OPTION;
@@ -112,8 +111,9 @@ static int fdomain_config_check(struct pcmcia_device *p_dev,
 				unsigned int vcc,
 				void *priv_data)
 {
-	p_dev->io.BasePort1 = cfg->io.win[0].base;
-	return pcmcia_request_io(p_dev, &p_dev->io);
+	p_dev->io_lines = 10;
+	p_dev->resource[0]->start = cfg->io.win[0].base;
+	return pcmcia_request_io(p_dev);
 }
 
 
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 964c913..ad8e896 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1558,9 +1558,8 @@ static int nsp_cs_probe(struct pcmcia_device *link)
 	nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info);
 
 	/* The io structure describes IO port mapping */
-	link->io.NumPorts1	 = 0x10;
-	link->io.Attributes1	 = IO_DATA_PATH_WIDTH_AUTO;
-	link->io.IOAddrLines	 = 10;	/* not used */
+	link->resource[0]->end	 = 0x10;
+	link->resource[0]->flags = IO_DATA_PATH_WIDTH_AUTO;
 
 	/* General socket configuration */
 	link->conf.Attributes	 = CONF_ENABLE_IRQ;
@@ -1641,24 +1640,23 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev,
 		p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 		/* IO window settings */
-		p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+		p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 		if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-			if (!(io->flags & CISTPL_IO_8BIT))
-				p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-			if (!(io->flags & CISTPL_IO_16BIT))
-				p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-			p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-			p_dev->io.BasePort1 = io->win[0].base;
-			p_dev->io.NumPorts1 = io->win[0].len;
+			p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+			p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+			p_dev->resource[0]->flags |=
+				pcmcia_io_cfg_data_width(io->flags);
+			p_dev->resource[0]->start = io->win[0].base;
+			p_dev->resource[0]->end = io->win[0].len;
 			if (io->nwin > 1) {
-				p_dev->io.Attributes2 = p_dev->io.Attributes1;
-				p_dev->io.BasePort2 = io->win[1].base;
-				p_dev->io.NumPorts2 = io->win[1].len;
+				p_dev->resource[1]->flags =
+					p_dev->resource[0]->flags;
+				p_dev->resource[1]->start = io->win[1].base;
+				p_dev->resource[1]->end = io->win[1].len;
 			}
 			/* This reserves IO space but doesn't actually enable it */
-			if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+			if (pcmcia_request_io(p_dev) != 0)
 				goto next_entry;
 		}
 
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 4e2b83f..eb775f1 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -156,9 +156,8 @@ static int qlogic_probe(struct pcmcia_device *link)
 		return -ENOMEM;
 	info->p_dev = link;
 	link->priv = info;
-	link->io.NumPorts1 = 16;
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-	link->io.IOAddrLines = 10;
+	link->resource[0]->end = 16;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.Present = PRESENT_OPTION;
@@ -185,13 +184,14 @@ static int qlogic_config_check(struct pcmcia_device *p_dev,
 			       unsigned int vcc,
 			       void *priv_data)
 {
-	p_dev->io.BasePort1 = cfg->io.win[0].base;
-	p_dev->io.NumPorts1 = cfg->io.win[0].len;
+	p_dev->io_lines = 10;
+	p_dev->resource[0]->start = cfg->io.win[0].base;
+	p_dev->resource[0]->end = cfg->io.win[0].len;
 
-	if (p_dev->io.BasePort1 == 0)
+	if (p_dev->resource[0]->start == 0)
 		return -ENODEV;
 
-	return pcmcia_request_io(p_dev, &p_dev->io);
+	return pcmcia_request_io(p_dev);
 }
 
 static int qlogic_config(struct pcmcia_device * link)
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index d99c0cb..321e390 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -690,13 +690,14 @@ static int SYM53C500_config_check(struct pcmcia_device *p_dev,
 				  unsigned int vcc,
 				  void *priv_data)
 {
-	p_dev->io.BasePort1 = cfg->io.win[0].base;
-	p_dev->io.NumPorts1 = cfg->io.win[0].len;
+	p_dev->io_lines = 10;
+	p_dev->resource[0]->start = cfg->io.win[0].base;
+	p_dev->resource[0]->end = cfg->io.win[0].len;
 
-	if (p_dev->io.BasePort1 == 0)
+	if (p_dev->resource[0]->start == 0)
 		return -ENODEV;
 
-	return pcmcia_request_io(p_dev, &p_dev->io);
+	return pcmcia_request_io(p_dev);
 }
 
 static int
@@ -858,9 +859,8 @@ SYM53C500_probe(struct pcmcia_device *link)
 		return -ENOMEM;
 	info->p_dev = link;
 	link->priv = info;
-	link->io.NumPorts1 = 16;
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-	link->io.IOAddrLines = 10;
+	link->resource[0]->end = 16;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index fe7adcd..141c695 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -335,8 +335,8 @@ static int serial_probe(struct pcmcia_device *link)
 	info->p_dev = link;
 	link->priv = info;
 
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	link->io.NumPorts1 = 8;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	link->resource[0]->end = 8;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	if (do_sound) {
 		link->conf.Attributes |= CONF_ENABLE_SPKR;
@@ -424,12 +424,13 @@ static int simple_config_check(struct pcmcia_device *p_dev,
 		p_dev->conf.Vpp =
 			cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
+	p_dev->io_lines = ((*try & 0x1) == 0) ?
+			16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+
 	if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)])
 	    && (cf->io.win[0].base != 0)) {
-		p_dev->io.BasePort1 = cf->io.win[0].base;
-		p_dev->io.IOAddrLines = ((*try & 0x1) == 0) ?
-			16 : cf->io.flags & CISTPL_IO_LINES_MASK;
-		if (!pcmcia_request_io(p_dev, &p_dev->io))
+		p_dev->resource[0]->start = cf->io.win[0].base;
+		if (!pcmcia_request_io(p_dev))
 			return 0;
 	}
 	return -EINVAL;
@@ -446,9 +447,9 @@ static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
 
 	if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
 		for (j = 0; j < 5; j++) {
-			p_dev->io.BasePort1 = base[j];
-			p_dev->io.IOAddrLines = base[j] ? 16 : 3;
-			if (!pcmcia_request_io(p_dev, &p_dev->io))
+			p_dev->resource[0]->start = base[j];
+			p_dev->io_lines = base[j] ? 16 : 3;
+			if (!pcmcia_request_io(p_dev))
 				return 0;
 		}
 	}
@@ -521,9 +522,9 @@ static int multi_config_check(struct pcmcia_device *p_dev,
 	/* The quad port cards have bad CIS's, so just look for a
 	   window larger than 8 ports and assume it will be right */
 	if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
-		p_dev->io.BasePort1 = cf->io.win[0].base;
-		p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-		if (!pcmcia_request_io(p_dev, &p_dev->io)) {
+		p_dev->resource[0]->start = cf->io.win[0].base;
+		p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+		if (!pcmcia_request_io(p_dev)) {
 			*base2 = p_dev->resource[0]->start + 8;
 			return 0;
 		}
@@ -540,10 +541,10 @@ static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
 	int *base2 = priv_data;
 
 	if (cf->io.nwin == 2) {
-		p_dev->io.BasePort1 = cf->io.win[0].base;
-		p_dev->io.BasePort2 = cf->io.win[1].base;
-		p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-		if (!pcmcia_request_io(p_dev, &p_dev->io)) {
+		p_dev->resource[0]->start = cf->io.win[0].base;
+		p_dev->resource[1]->start = cf->io.win[1].base;
+		p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+		if (!pcmcia_request_io(p_dev)) {
 			*base2 = p_dev->resource[1]->start;
 			return 0;
 		}
@@ -557,10 +558,10 @@ static int multi_config(struct pcmcia_device *link)
 	int i, base2 = 0;
 
 	/* First, look for a generic full-sized window */
-	link->io.NumPorts1 = info->multi * 8;
+	link->resource[0]->end = info->multi * 8;
 	if (pcmcia_loop_config(link, multi_config_check, &base2)) {
 		/* If that didn't work, look for two windows */
-		link->io.NumPorts1 = link->io.NumPorts2 = 8;
+		link->resource[0]->end = link->resource[1]->end = 8;
 		info->multi = 2;
 		if (pcmcia_loop_config(link, multi_config_check_notpicky,
 				       &base2)) {
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 208f1b7..7cf0ccb 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -736,24 +736,22 @@ static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+			pcmcia_io_cfg_data_width(io->flags);
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 		/* This reserves IO space but doesn't actually enable it */
-		return pcmcia_request_io(p_dev, &p_dev->io);
+		return pcmcia_request_io(p_dev);
 	}
 
 	return 0;
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index c4cfcff..9ee677f 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -224,24 +224,23 @@ static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+			pcmcia_io_cfg_data_width(io->flags);
 		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 		/* This reserves IO space but doesn't actually enable it */
-		return pcmcia_request_io(p_dev, &p_dev->io);
+		return pcmcia_request_io(p_dev);
 	}
 	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 6d56957..7e41ad9 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -571,24 +571,22 @@ static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+			pcmcia_io_cfg_data_width(io->flags);
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+		if (pcmcia_request_io(p_dev) != 0)
 			return -ENODEV;
 	}
 
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index 29e1daf..b2483f8 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -323,24 +323,22 @@ static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+			pcmcia_io_cfg_data_width(io->flags);
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+		if (pcmcia_request_io(p_dev) != 0)
 			return -ENODEV;
 	}
 
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index fb10987..c1444b4 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -301,24 +301,22 @@ static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+			pcmcia_io_cfg_data_width(io->flags);
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+		if (pcmcia_request_io(p_dev) != 0)
 			return -ENODEV;
 	}
 
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index f37dc22..d50b6c4 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -264,8 +264,8 @@ static const dev_info_t dev_info = "ni_mio_cs";
 
 static int cs_attach(struct pcmcia_device *link)
 {
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-	link->io.NumPorts1 = 16;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+	link->resource[0]->end = 16;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 
@@ -310,13 +310,12 @@ static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev,
 {
 	int base, ret;
 
-	p_dev->io.NumPorts1 = cfg->io.win[0].len;
-	p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-	p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = cfg->io.win[0].len;
+	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
 
 	for (base = 0x000; base < 0x400; base += 0x20) {
-		p_dev->io.BasePort1 = base;
-		ret = pcmcia_request_io(p_dev, &p_dev->io);
+		p_dev->resource[0]->start = base;
+		ret = pcmcia_request_io(p_dev);
 		if (!ret)
 			return 0;
 	}
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index 80b8d57..25f4e67 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -1102,26 +1102,24 @@ static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-		if (!(io->flags & CISTPL_IO_8BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-		if (!(io->flags & CISTPL_IO_16BIT))
-			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+			pcmcia_io_cfg_data_width(io->flags);
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin > 1) {
-			p_dev->io.Attributes2 = p_dev->io.Attributes1;
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
 	}
 
 	/* This reserves IO space but doesn't actually enable it */
-	return pcmcia_request_io(p_dev, &p_dev->io);
+	return pcmcia_request_io(p_dev);
 }
 
 static void daqp_cs_config(struct pcmcia_device *link)
diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c
index 2361537..f15afd2 100644
--- a/drivers/staging/wlags49_h2/wl_cs.c
+++ b/drivers/staging/wlags49_h2/wl_cs.c
@@ -145,9 +145,8 @@ static int wl_adapter_attach(struct pcmcia_device *link)
 	return -ENOMEM;
     }
 
-    link->io.NumPorts1      = HCF_NUM_IO_PORTS;
-    link->io.Attributes1    = IO_DATA_PATH_WIDTH_16;
-    link->io.IOAddrLines    = 6;
+    link->resource[0]->end      = HCF_NUM_IO_PORTS;
+    link->resource[0]->flags    = IO_DATA_PATH_WIDTH_16;
     link->conf.Attributes   = CONF_ENABLE_IRQ;
     link->conf.IntType      = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex  = 5;
@@ -305,8 +304,9 @@ void wl_adapter_insert( struct pcmcia_device *link )
 
     /* Do we need to allocate an interrupt? */
     link->conf.Attributes |= CONF_ENABLE_IRQ;
+    link->io_lines = 6;
 
-    ret = pcmcia_request_io(link, &link->io);
+    ret = pcmcia_request_io(link);
     if (ret != 0)
         goto failed;
 
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index a801036..a1900e5 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -32,9 +32,8 @@ static int ixj_probe(struct pcmcia_device *p_dev)
 {
 	dev_dbg(&p_dev->dev, "ixj_attach()\n");
 	/* Create new ixj device */
-	p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-	p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-	p_dev->io.IOAddrLines = 3;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 	p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
 	if (!p_dev->priv) {
@@ -120,13 +119,14 @@ static int ixj_config_check(struct pcmcia_device *p_dev,
 {
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
+		p_dev->io_lines = 3;
 		if (io->nwin == 2) {
-			p_dev->io.BasePort2 = io->win[1].base;
-			p_dev->io.NumPorts2 = io->win[1].len;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
-		if (!pcmcia_request_io(p_dev, &p_dev->io))
+		if (!pcmcia_request_io(p_dev))
 			return 0;
 	}
 	return -ENODEV;
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 22e04f2..0e13a00 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -162,16 +162,16 @@ static int sl811_cs_config_check(struct pcmcia_device *p_dev,
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
-	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
 
-		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->io.BasePort1 = io->win[0].base;
-		p_dev->io.NumPorts1 = io->win[0].len;
+		p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
 
-		return pcmcia_request_io(p_dev, &p_dev->io);
+		return pcmcia_request_io(p_dev);
 	}
 	pcmcia_disable_device(p_dev);
 	return -ENODEV;
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 0cd8c70..ad71bb5 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -56,23 +56,6 @@ typedef struct config_req_t {
 #define INT_CARDBUS		0x04
 #define INT_ZOOMED_VIDEO	0x08
 
-/* For RequestIO and ReleaseIO */
-typedef struct io_req_t {
-    u_int	BasePort1;
-    u_int	NumPorts1;
-    u_int	Attributes1;
-    u_int	BasePort2;
-    u_int	NumPorts2;
-    u_int	Attributes2;
-    u_int	IOAddrLines;
-} io_req_t;
-
-/* Attributes for RequestIO and ReleaseIO */
-#define IO_DATA_PATH_WIDTH	0x18
-#define IO_DATA_PATH_WIDTH_8	0x00
-#define IO_DATA_PATH_WIDTH_16	0x08
-#define IO_DATA_PATH_WIDTH_AUTO	0x10
-
 /* Bits in IRQInfo1 field */
 #define IRQ_NMI_ID		0x01
 #define IRQ_IOCK_ID		0x02
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 3dafd7d..0748bec 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -80,7 +80,6 @@ struct pcmcia_device {
 	struct list_head	socket_device_list;
 
 	/* deprecated, will be cleaned up soon */
-	io_req_t		io;
 	config_req_t		conf;
 	window_handle_t		win;
 
@@ -88,6 +87,8 @@ struct pcmcia_device {
 	unsigned int		irq;
 	struct resource		*resource[MAX_IO_WIN];
 
+	unsigned int		io_lines; /* number of I/O lines */
+
 	/* Is the device suspended? */
 	u16			suspended:1;
 
@@ -179,7 +180,7 @@ int pcmcia_read_config_byte(struct pcmcia_device *p_dev, off_t where, u8 *val);
 int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val);
 
 /* device configuration */
-int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req);
+int pcmcia_request_io(struct pcmcia_device *p_dev);
 
 int __must_check
 __pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
@@ -206,6 +207,22 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t win,
 int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
 void pcmcia_disable_device(struct pcmcia_device *p_dev);
 
+/* IO ports */
+#define IO_DATA_PATH_WIDTH	0x18
+#define IO_DATA_PATH_WIDTH_8	0x00
+#define IO_DATA_PATH_WIDTH_16	0x08
+#define IO_DATA_PATH_WIDTH_AUTO	0x10
+
+/* convert flag found in cfgtable to data path width parameter */
+static inline int pcmcia_io_cfg_data_width(unsigned int flags)
+{
+	if (!(flags & CISTPL_IO_8BIT))
+		return IO_DATA_PATH_WIDTH_16;
+	if (!(flags & CISTPL_IO_16BIT))
+		return IO_DATA_PATH_WIDTH_8;
+	return IO_DATA_PATH_WIDTH_AUTO;
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_DS_H */
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 9f897bc..7ab9174 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -139,8 +139,8 @@ static int snd_pdacf_probe(struct pcmcia_device *link)
 	pdacf->p_dev = link;
 	link->priv = pdacf;
 
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-	link->io.NumPorts1 = 16;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+	link->resource[0]->end = 16;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
@@ -219,7 +219,7 @@ static int pdacf_config(struct pcmcia_device *link)
 	snd_printdd(KERN_DEBUG "pdacf_config called\n");
 	link->conf.ConfigIndex = 0x5;
 
-	ret = pcmcia_request_io(link, &link->io);
+	ret = pcmcia_request_io(link);
 	if (ret)
 		goto failed;
 
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index f23c235..a6edfc3 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -159,8 +159,8 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl,
 	vxp->p_dev = link;
 	link->priv = chip;
 
-	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-	link->io.NumPorts1 = 16;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+	link->resource[0]->end = 16;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
 	link->conf.IntType = INT_MEMORY_AND_IO;
@@ -226,7 +226,7 @@ static int vxpocket_config(struct pcmcia_device *link)
 		strcpy(chip->card->driver, vxp440_hw.name);
 	}
 
-	ret = pcmcia_request_io(link, &link->io);
+	ret = pcmcia_request_io(link);
 	if (ret)
 		goto failed;
 
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH 04/11] pcmcia: do not use io_req_t after call to pcmcia_request_io()
From: Dominik Brodowski @ 2010-08-01 12:59 UTC (permalink / raw)
  To: linux-pcmcia
  Cc: Dominik Brodowski, netdev, linux-wireless, linux-ide, linux-usb,
	laforge, linux-mtd, linux-bluetooth, alsa-devel, linux-serial
In-Reply-To: <20100801125749.GA2564@comet.dominikbrodowski.net>

After pcmcia_request_io(), do not make use of the values stored in
io_req_t, but instead use those found in struct pcmcia_device->resource[].

CC: netdev@vger.kernel.org
CC: linux-wireless@vger.kernel.org
CC: linux-ide@vger.kernel.org
CC: linux-usb@vger.kernel.org
CC: laforge@gnumonks.org
CC: linux-mtd@lists.infradead.org
CC: linux-bluetooth@vger.kernel.org
CC: alsa-devel@alsa-project.org
CC: linux-serial@vger.kernel.org
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
---
 drivers/ata/pata_pcmcia.c                        |    8 +++---
 drivers/bluetooth/bluecard_cs.c                  |   18 ++++++++--------
 drivers/bluetooth/bt3c_cs.c                      |    8 +++---
 drivers/bluetooth/btuart_cs.c                    |   12 +++++-----
 drivers/bluetooth/dtl1_cs.c                      |   13 ++++++-----
 drivers/char/pcmcia/cm4000_cs.c                  |   12 +++++-----
 drivers/char/pcmcia/cm4040_cs.c                  |   16 +++++++-------
 drivers/char/pcmcia/ipwireless/main.c            |   10 +++-----
 drivers/char/pcmcia/synclink_cs.c                |    7 ++---
 drivers/ide/ide-cs.c                             |    8 +++---
 drivers/isdn/hardware/avm/avm_cs.c               |    9 ++++---
 drivers/isdn/hisax/avma1_cs.c                    |    8 ++++--
 drivers/isdn/hisax/elsa_cs.c                     |   16 ++++++--------
 drivers/isdn/hisax/sedlbauer_cs.c                |   16 ++++++--------
 drivers/isdn/hisax/teles_cs.c                    |   14 +++++-------
 drivers/net/pcmcia/3c574_cs.c                    |    2 +-
 drivers/net/pcmcia/3c589_cs.c                    |    2 +-
 drivers/net/pcmcia/axnet_cs.c                    |    4 +-
 drivers/net/pcmcia/com20020_cs.c                 |    2 +-
 drivers/net/pcmcia/fmvj18x_cs.c                  |    6 ++--
 drivers/net/pcmcia/ibmtr_cs.c                    |    2 +-
 drivers/net/pcmcia/nmclan_cs.c                   |    2 +-
 drivers/net/pcmcia/pcnet_cs.c                    |    4 +-
 drivers/net/pcmcia/smc91c92_cs.c                 |   18 ++++++++--------
 drivers/net/pcmcia/xirc2ps_cs.c                  |   12 +++++-----
 drivers/net/wireless/airo_cs.c                   |   12 ++++------
 drivers/net/wireless/atmel_cs.c                  |    2 +-
 drivers/net/wireless/hostap/hostap_cs.c          |   18 +++++++--------
 drivers/net/wireless/libertas/if_cs.c            |    7 ++---
 drivers/net/wireless/orinoco/orinoco_cs.c        |    5 ++-
 drivers/net/wireless/orinoco/spectrum_cs.c       |    5 ++-
 drivers/net/wireless/wl3501_cs.c                 |    2 +-
 drivers/parport/parport_cs.c                     |    6 +++-
 drivers/scsi/pcmcia/aha152x_stub.c               |    2 +-
 drivers/scsi/pcmcia/fdomain_stub.c               |    4 +-
 drivers/scsi/pcmcia/nsp_cs.c                     |   25 ++++++++++-----------
 drivers/scsi/pcmcia/qlogic_stub.c                |   18 ++++++++--------
 drivers/scsi/pcmcia/sym53c500_cs.c               |   16 +++++++-------
 drivers/serial/serial_cs.c                       |   22 +++++++++---------
 drivers/staging/comedi/drivers/cb_das16_cs.c     |   12 ++++------
 drivers/staging/comedi/drivers/das08_cs.c        |   12 ++++------
 drivers/staging/comedi/drivers/ni_daq_700.c      |   12 ++++------
 drivers/staging/comedi/drivers/ni_daq_dio24.c    |   12 ++++------
 drivers/staging/comedi/drivers/ni_labpc_cs.c     |   12 ++++------
 drivers/staging/comedi/drivers/ni_mio_cs.c       |    2 +-
 drivers/staging/comedi/drivers/quatech_daqp_cs.c |   12 ++++------
 drivers/staging/wlags49_h2/wl_cs.c               |    2 +-
 drivers/telephony/ixj_pcmcia.c                   |    3 +-
 drivers/usb/host/sl811_cs.c                      |    7 ++---
 sound/pcmcia/pdaudiocf/pdaudiocf.c               |    3 +-
 sound/pcmcia/vx/vxpocket.c                       |    3 +-
 51 files changed, 224 insertions(+), 241 deletions(-)

diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 3dcb2b1..1fcd065 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -210,13 +210,13 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev,
 			pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
 			if (pcmcia_request_io(pdev, &pdev->io) != 0)
 				return -ENODEV;
-			stk->ctl_base = pdev->io.BasePort2;
+			stk->ctl_base = pdev->resource[1]->start;
 		} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
 			pdev->io.NumPorts1 = io->win[0].len;
 			pdev->io.NumPorts2 = 0;
 			if (pcmcia_request_io(pdev, &pdev->io) != 0)
 				return -ENODEV;
-			stk->ctl_base = pdev->io.BasePort1 + 0x0e;
+			stk->ctl_base = pdev->resource[0]->start + 0x0e;
 		} else
 			return -ENODEV;
 		/* If we've got this far, we're done */
@@ -270,7 +270,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 		if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
 			goto failed; /* No suitable config found */
 	}
-	io_base = pdev->io.BasePort1;
+	io_base = pdev->resource[0]->start;
 	ctl_base = stk->ctl_base;
 	if (!pdev->irq)
 		goto failed;
@@ -293,7 +293,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 
 	/* FIXME: Could be more ports at base + 0x10 but we only deal with
 	   one right now */
-	if (pdev->io.NumPorts1 >= 0x20)
+	if (resource_size(pdev->resource[0]) >= 0x20)
 		n_ports = 2;
 
 	if (pdev->manf_id == 0x0097 && pdev->card_id == 0x1620)
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index eb085de..24d2007 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -159,7 +159,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev);
 static void bluecard_activity_led_timeout(u_long arg)
 {
 	bluecard_info_t *info = (bluecard_info_t *)arg;
-	unsigned int iobase = info->p_dev->io.BasePort1;
+	unsigned int iobase = info->p_dev->resource[0]->start;
 
 	if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
 		return;
@@ -176,7 +176,7 @@ static void bluecard_activity_led_timeout(u_long arg)
 
 static void bluecard_enable_activity_led(bluecard_info_t *info)
 {
-	unsigned int iobase = info->p_dev->io.BasePort1;
+	unsigned int iobase = info->p_dev->resource[0]->start;
 
 	if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
 		return;
@@ -232,7 +232,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
 	}
 
 	do {
-		register unsigned int iobase = info->p_dev->io.BasePort1;
+		register unsigned int iobase = info->p_dev->resource[0]->start;
 		register unsigned int offset;
 		register unsigned char command;
 		register unsigned long ready_bit;
@@ -379,7 +379,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
 		return;
 	}
 
-	iobase = info->p_dev->io.BasePort1;
+	iobase = info->p_dev->resource[0]->start;
 
 	if (test_bit(XMIT_SENDING_READY, &(info->tx_state)))
 		bluecard_enable_activity_led(info);
@@ -508,7 +508,7 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst)
 	if (!test_bit(CARD_READY, &(info->hw_state)))
 		return IRQ_HANDLED;
 
-	iobase = info->p_dev->io.BasePort1;
+	iobase = info->p_dev->resource[0]->start;
 
 	spin_lock(&(info->lock));
 
@@ -622,7 +622,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev)
 static int bluecard_hci_open(struct hci_dev *hdev)
 {
 	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
-	unsigned int iobase = info->p_dev->io.BasePort1;
+	unsigned int iobase = info->p_dev->resource[0]->start;
 
 	if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
 		bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
@@ -642,7 +642,7 @@ static int bluecard_hci_open(struct hci_dev *hdev)
 static int bluecard_hci_close(struct hci_dev *hdev)
 {
 	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
-	unsigned int iobase = info->p_dev->io.BasePort1;
+	unsigned int iobase = info->p_dev->resource[0]->start;
 
 	if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
 		return 0;
@@ -709,7 +709,7 @@ static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned l
 
 static int bluecard_open(bluecard_info_t *info)
 {
-	unsigned int iobase = info->p_dev->io.BasePort1;
+	unsigned int iobase = info->p_dev->resource[0]->start;
 	struct hci_dev *hdev;
 	unsigned char id;
 
@@ -828,7 +828,7 @@ static int bluecard_open(bluecard_info_t *info)
 
 static int bluecard_close(bluecard_info_t *info)
 {
-	unsigned int iobase = info->p_dev->io.BasePort1;
+	unsigned int iobase = info->p_dev->resource[0]->start;
 	struct hci_dev *hdev = info->hdev;
 
 	if (!hdev)
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 457b603..8ab494c 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -188,7 +188,7 @@ static void bt3c_write_wakeup(bt3c_info_t *info)
 		return;
 
 	do {
-		register unsigned int iobase = info->p_dev->io.BasePort1;
+		register unsigned int iobase = info->p_dev->resource[0]->start;
 		register struct sk_buff *skb;
 		register int len;
 
@@ -226,7 +226,7 @@ static void bt3c_receive(bt3c_info_t *info)
 		return;
 	}
 
-	iobase = info->p_dev->io.BasePort1;
+	iobase = info->p_dev->resource[0]->start;
 
 	avail = bt3c_read(iobase, 0x7006);
 	//printk("bt3c_cs: receiving %d bytes\n", avail);
@@ -347,7 +347,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
 		/* our irq handler is shared */
 		return IRQ_NONE;
 
-	iobase = info->p_dev->io.BasePort1;
+	iobase = info->p_dev->resource[0]->start;
 
 	spin_lock(&(info->lock));
 
@@ -480,7 +480,7 @@ static int bt3c_load_firmware(bt3c_info_t *info, const unsigned char *firmware,
 	unsigned int iobase, size, addr, fcs, tmp;
 	int i, err = 0;
 
-	iobase = info->p_dev->io.BasePort1;
+	iobase = info->p_dev->resource[0]->start;
 
 	/* Reset */
 	bt3c_io_write(iobase, 0x8040, 0x0404);
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index e7e0a17..7e770d4 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -142,7 +142,7 @@ static void btuart_write_wakeup(btuart_info_t *info)
 	}
 
 	do {
-		register unsigned int iobase = info->p_dev->io.BasePort1;
+		register unsigned int iobase = info->p_dev->resource[0]->start;
 		register struct sk_buff *skb;
 		register int len;
 
@@ -183,7 +183,7 @@ static void btuart_receive(btuart_info_t *info)
 		return;
 	}
 
-	iobase = info->p_dev->io.BasePort1;
+	iobase = info->p_dev->resource[0]->start;
 
 	do {
 		info->hdev->stat.byte_rx++;
@@ -297,7 +297,7 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst)
 		/* our irq handler is shared */
 		return IRQ_NONE;
 
-	iobase = info->p_dev->io.BasePort1;
+	iobase = info->p_dev->resource[0]->start;
 
 	spin_lock(&(info->lock));
 
@@ -354,7 +354,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
 		return;
 	}
 
-	iobase = info->p_dev->io.BasePort1;
+	iobase = info->p_dev->resource[0]->start;
 
 	spin_lock_irqsave(&(info->lock), flags);
 
@@ -478,7 +478,7 @@ static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned lon
 static int btuart_open(btuart_info_t *info)
 {
 	unsigned long flags;
-	unsigned int iobase = info->p_dev->io.BasePort1;
+	unsigned int iobase = info->p_dev->resource[0]->start;
 	struct hci_dev *hdev;
 
 	spin_lock_init(&(info->lock));
@@ -548,7 +548,7 @@ static int btuart_open(btuart_info_t *info)
 static int btuart_close(btuart_info_t *info)
 {
 	unsigned long flags;
-	unsigned int iobase = info->p_dev->io.BasePort1;
+	unsigned int iobase = info->p_dev->resource[0]->start;
 	struct hci_dev *hdev = info->hdev;
 
 	if (!hdev)
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 7c94aad..bfe9313 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -149,7 +149,7 @@ static void dtl1_write_wakeup(dtl1_info_t *info)
 	}
 
 	do {
-		register unsigned int iobase = info->p_dev->io.BasePort1;
+		register unsigned int iobase = info->p_dev->resource[0]->start;
 		register struct sk_buff *skb;
 		register int len;
 
@@ -214,7 +214,7 @@ static void dtl1_receive(dtl1_info_t *info)
 		return;
 	}
 
-	iobase = info->p_dev->io.BasePort1;
+	iobase = info->p_dev->resource[0]->start;
 
 	do {
 		info->hdev->stat.byte_rx++;
@@ -301,7 +301,7 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
 		/* our irq handler is shared */
 		return IRQ_NONE;
 
-	iobase = info->p_dev->io.BasePort1;
+	iobase = info->p_dev->resource[0]->start;
 
 	spin_lock(&(info->lock));
 
@@ -461,7 +461,7 @@ static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd,  unsigned long
 static int dtl1_open(dtl1_info_t *info)
 {
 	unsigned long flags;
-	unsigned int iobase = info->p_dev->io.BasePort1;
+	unsigned int iobase = info->p_dev->resource[0]->start;
 	struct hci_dev *hdev;
 
 	spin_lock_init(&(info->lock));
@@ -508,7 +508,8 @@ static int dtl1_open(dtl1_info_t *info)
 	outb(UART_LCR_WLEN8, iobase + UART_LCR);	/* Reset DLAB */
 	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
 
-	info->ri_latch = inb(info->p_dev->io.BasePort1 + UART_MSR) & UART_MSR_RI;
+	info->ri_latch = inb(info->p_dev->resource[0]->start + UART_MSR)
+				& UART_MSR_RI;
 
 	/* Turn on interrupts */
 	outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
@@ -533,7 +534,7 @@ static int dtl1_open(dtl1_info_t *info)
 static int dtl1_close(dtl1_info_t *info)
 {
 	unsigned long flags;
-	unsigned int iobase = info->p_dev->io.BasePort1;
+	unsigned int iobase = info->p_dev->resource[0]->start;
 	struct hci_dev *hdev = info->hdev;
 
 	if (!hdev)
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index a8be2a7..18484ed 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -421,7 +421,7 @@ static struct card_fixup card_fixups[] = {
 static void set_cardparameter(struct cm4000_dev *dev)
 {
 	int i;
-	unsigned int iobase = dev->p_dev->io.BasePort1;
+	unsigned int iobase = dev->p_dev->resource[0]->start;
 	u_int8_t stopbits = 0x02; /* ISO default */
 
 	DEBUGP(3, dev, "-> set_cardparameter\n");
@@ -454,7 +454,7 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)
 	unsigned short num_bytes_read;
 	unsigned char pts_reply[4];
 	ssize_t rc;
-	unsigned int iobase = dev->p_dev->io.BasePort1;
+	unsigned int iobase = dev->p_dev->resource[0]->start;
 
 	rc = 0;
 
@@ -663,7 +663,7 @@ static void terminate_monitor(struct cm4000_dev *dev)
 static void monitor_card(unsigned long p)
 {
 	struct cm4000_dev *dev = (struct cm4000_dev *) p;
-	unsigned int iobase = dev->p_dev->io.BasePort1;
+	unsigned int iobase = dev->p_dev->resource[0]->start;
 	unsigned short s;
 	struct ptsreq ptsreq;
 	int i, atrc;
@@ -924,7 +924,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,
 			loff_t *ppos)
 {
 	struct cm4000_dev *dev = filp->private_data;
-	unsigned int iobase = dev->p_dev->io.BasePort1;
+	unsigned int iobase = dev->p_dev->resource[0]->start;
 	ssize_t rc;
 	int i, j, k;
 
@@ -1047,7 +1047,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf,
 			 size_t count, loff_t *ppos)
 {
 	struct cm4000_dev *dev = filp->private_data;
-	unsigned int iobase = dev->p_dev->io.BasePort1;
+	unsigned int iobase = dev->p_dev->resource[0]->start;
 	unsigned short s;
 	unsigned char tmp;
 	unsigned char infolen;
@@ -1400,7 +1400,7 @@ static void stop_monitor(struct cm4000_dev *dev)
 static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct cm4000_dev *dev = filp->private_data;
-	unsigned int iobase = dev->p_dev->io.BasePort1;
+	unsigned int iobase = dev->p_dev->resource[0]->start;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	struct pcmcia_device *link;
 	int size;
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 44adae9..a6bbf19 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -109,7 +109,7 @@ static inline unsigned char xinb(unsigned short port)
 static void cm4040_do_poll(unsigned long dummy)
 {
 	struct reader_dev *dev = (struct reader_dev *) dummy;
-	unsigned int obs = xinb(dev->p_dev->io.BasePort1
+	unsigned int obs = xinb(dev->p_dev->resource[0]->start
 				+ REG_OFFSET_BUFFER_STATUS);
 
 	if ((obs & BSR_BULK_IN_FULL)) {
@@ -140,7 +140,7 @@ static void cm4040_stop_poll(struct reader_dev *dev)
 static int wait_for_bulk_out_ready(struct reader_dev *dev)
 {
 	int i, rc;
-	int iobase = dev->p_dev->io.BasePort1;
+	int iobase = dev->p_dev->resource[0]->start;
 
 	for (i = 0; i < POLL_LOOP_COUNT; i++) {
 		if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
@@ -170,7 +170,7 @@ static int wait_for_bulk_out_ready(struct reader_dev *dev)
 /* Write to Sync Control Register */
 static int write_sync_reg(unsigned char val, struct reader_dev *dev)
 {
-	int iobase = dev->p_dev->io.BasePort1;
+	int iobase = dev->p_dev->resource[0]->start;
 	int rc;
 
 	rc = wait_for_bulk_out_ready(dev);
@@ -188,7 +188,7 @@ static int write_sync_reg(unsigned char val, struct reader_dev *dev)
 static int wait_for_bulk_in_ready(struct reader_dev *dev)
 {
 	int i, rc;
-	int iobase = dev->p_dev->io.BasePort1;
+	int iobase = dev->p_dev->resource[0]->start;
 
 	for (i = 0; i < POLL_LOOP_COUNT; i++) {
 		if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS)
@@ -218,7 +218,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,
 			size_t count, loff_t *ppos)
 {
 	struct reader_dev *dev = filp->private_data;
-	int iobase = dev->p_dev->io.BasePort1;
+	int iobase = dev->p_dev->resource[0]->start;
 	size_t bytes_to_read;
 	unsigned long i;
 	size_t min_bytes_to_read;
@@ -320,7 +320,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf,
 			 size_t count, loff_t *ppos)
 {
 	struct reader_dev *dev = filp->private_data;
-	int iobase = dev->p_dev->io.BasePort1;
+	int iobase = dev->p_dev->resource[0]->start;
 	ssize_t rc;
 	int i;
 	unsigned int bytes_to_write;
@@ -567,8 +567,8 @@ static int reader_config(struct pcmcia_device *link, int devno)
 
 	dev = link->priv;
 
-	DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno,
-	      link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1);
+	DEBUGP(2, dev, "device " DEVICE_NAME "%d at %pR\n", devno,
+	      link->resource[0]);
 	DEBUGP(2, dev, "<- reader_config (succ)\n");
 
 	return 0;
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 63c32e3..9467994 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -100,7 +100,8 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
 	if (ret)
 		return ret;
 
-	io_resource = request_region(p_dev->io.BasePort1, p_dev->io.NumPorts1,
+	io_resource = request_region(p_dev->resource[0]->start,
+				resource_size(p_dev->resource[0]),
 				IPWIRELESS_PCCARD_NAME);
 
 	if (cfg->mem.nwin == 0)
@@ -197,7 +198,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
 
 	INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
 
-	ipwireless_init_hardware_v1(ipw->hardware, link->io.BasePort1,
+	ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
 				    ipw->attr_memory, ipw->common_memory,
 				    ipw->is_v2_card, signalled_reboot_callback,
 				    ipw);
@@ -209,10 +210,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
 	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
 			ipw->is_v2_card ? "V2/V3" : "V1");
 	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			": I/O ports 0x%04x-0x%04x, irq %d\n",
-			(unsigned int) link->io.BasePort1,
-			(unsigned int) (link->io.BasePort1 +
-				link->io.NumPorts1 - 1),
+		": I/O ports %pR, irq %d\n", link->resource[0],
 			(unsigned int) link->irq);
 	if (ipw->attr_memory && ipw->common_memory)
 		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 522992e..8ded9b0 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -609,16 +609,15 @@ static int mgslpc_config(struct pcmcia_device *link)
     if (ret)
 	    goto failed;
 
-    info->io_base = link->io.BasePort1;
+    info->io_base = link->resource[0]->start;
     info->irq_level = link->irq;
 
     dev_info(&link->dev, "index 0x%02x:",
 	    link->conf.ConfigIndex);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
 	    printk(", irq %d", link->irq);
-    if (link->io.NumPorts1)
-	    printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		   link->io.BasePort1+link->io.NumPorts1-1);
+    if (link->resource[0])
+	    printk(", io %pR", link->resource[0]);
     printk("\n");
     return 0;
 
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index 27dbab8..34eafaf 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -239,13 +239,13 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev,
 			pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
 			if (pcmcia_request_io(pdev, &pdev->io) != 0)
 				return -ENODEV;
-			stk->ctl_base = pdev->io.BasePort2;
+			stk->ctl_base = pdev->resource[1]->start;
 		} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
 			pdev->io.NumPorts1 = io->win[0].len;
 			pdev->io.NumPorts2 = 0;
 			if (pcmcia_request_io(pdev, &pdev->io) != 0)
 				return -ENODEV;
-			stk->ctl_base = pdev->io.BasePort1 + 0x0e;
+			stk->ctl_base = pdev->resource[1]->start + 0x0e;
 		} else
 			return -ENODEV;
 		/* If we've got this far, we're done */
@@ -279,7 +279,7 @@ static int ide_config(struct pcmcia_device *link)
 	    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
 		    goto failed; /* No suitable config found */
     }
-    io_base = link->io.BasePort1;
+    io_base = link->resource[0]->start;
     ctl_base = stk->ctl_base;
 
     if (!link->irq)
@@ -296,7 +296,7 @@ static int ide_config(struct pcmcia_device *link)
 	outb(0x81, ctl_base+1);
 
      host = idecs_register(io_base, ctl_base, link->irq, link);
-     if (host == NULL && link->io.NumPorts1 == 0x20) {
+     if (host == NULL && resource_size(link->resource[0]) == 0x20) {
 	    outb(0x02, ctl_base + 0x10);
 	    host = idecs_register(io_base + 0x10, ctl_base + 0x10,
 				  link->irq, link);
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index e804a01..7c8c51f 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -191,9 +191,10 @@ static int avmcs_config(struct pcmcia_device *link)
 	default:
         case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break;
     }
-    if ((i = (*addcard)(link->io.BasePort1, link->irq)) < 0) {
-	    dev_err(&link->dev, "avm_cs: failed to add AVM-Controller at i/o %#x, irq %d\n",
-		    link->io.BasePort1, link->irq);
+    if ((i = (*addcard)(link->resource[0]->start, link->irq)) < 0) {
+	    dev_err(&link->dev,
+		    "avm_cs: failed to add AVM-Controller at i/o %#x, irq %d\n",
+		    (unsigned int) link->resource[0]->start, link->irq);
 	    avmcs_release(link);
 	    return -ENODEV;
     }
@@ -211,7 +212,7 @@ static int avmcs_config(struct pcmcia_device *link)
 
 static void avmcs_release(struct pcmcia_device *link)
 {
-	b1pcmcia_delcard(link->io.BasePort1, link->irq);
+	b1pcmcia_delcard(link->resource[0]->start, link->irq);
 	pcmcia_disable_device(link);
 } /* avmcs_release */
 
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 49e141e..8889963 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -180,16 +180,18 @@ static int __devinit avma1cs_config(struct pcmcia_device *link)
     }
 
     printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
-				link->io.BasePort1, link->irq);
+		(unsigned int) link->resource[0]->start, link->irq);
 
     icard.para[0] = link->irq;
-    icard.para[1] = link->io.BasePort1;
+    icard.para[1] = link->resource[0]->start;
     icard.protocol = isdnprot;
     icard.typ = ISDN_CTYPE_A1_PCMCIA;
     
     i = hisax_init_pcmcia(link, &busy, &icard);
     if (i < 0) {
-    	printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
+	printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 "
+			"PCMCIA %d at i/o %#x\n", i,
+			(unsigned int) link->resource[0]->start);
 	avma1cs_release(link);
 	return -ENODEV;
     }
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 425deea..c10bfd3 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -214,23 +214,21 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link)
 	    link->conf.ConfigIndex);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
 	printk(", irq %d", link->irq);
-    if (link->io.NumPorts1)
-        printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-               link->io.BasePort1+link->io.NumPorts1-1);
-    if (link->io.NumPorts2)
-        printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-               link->io.BasePort2+link->io.NumPorts2-1);
+    if (link->resource[0])
+	printk(" & %pR", link->resource[0]);
+    if (link->resource[1])
+	printk(" & %pR", link->resource[1]);
     printk("\n");
 
     icard.para[0] = link->irq;
-    icard.para[1] = link->io.BasePort1;
+    icard.para[1] = link->resource[0]->start;
     icard.protocol = protocol;
     icard.typ = ISDN_CTYPE_ELSA_PCMCIA;
     
     i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
     if (i < 0) {
-    	printk(KERN_ERR "elsa_cs: failed to initialize Elsa PCMCIA %d at i/o %#x\n",
-    		i, link->io.BasePort1);
+	printk(KERN_ERR "elsa_cs: failed to initialize Elsa "
+		"PCMCIA %d with %pR\n", i, link->resource[0]);
     	elsa_cs_release(link);
     } else
     	((local_info_t*)link->priv)->cardnr = i;
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 5dbad96..cecb35a 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -296,27 +296,25 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
 	printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
 	printk(", irq %d", link->irq);
-    if (link->io.NumPorts1)
-	printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-	       link->io.BasePort1+link->io.NumPorts1-1);
-    if (link->io.NumPorts2)
-	printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-	       link->io.BasePort2+link->io.NumPorts2-1);
+    if (link->resource[0])
+	printk(" & %pR", link->resource[0]);
+    if (link->resource[1])
+	printk(" & %pR", link->resource[1]);
     if (link->win)
 	printk(", mem 0x%06lx-0x%06lx", req->Base,
 	       req->Base+req->Size-1);
     printk("\n");
 
     icard.para[0] = link->irq;
-    icard.para[1] = link->io.BasePort1;
+    icard.para[1] = link->resource[0]->start;
     icard.protocol = protocol;
     icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
     
     ret = hisax_init_pcmcia(link, 
 			    &(((local_info_t *)link->priv)->stop), &icard);
     if (ret < 0) {
-	printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n",
-		ret, link->io.BasePort1);
+	printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d with %pR\n",
+		ret, link->resource[0]);
     	sedlbauer_release(link);
 	return -ENODEV;
     } else
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index d3fb1b7..3787fc7 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -194,23 +194,21 @@ static int __devinit teles_cs_config(struct pcmcia_device *link)
 	    link->conf.ConfigIndex);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
 	    printk(", irq %d", link->irq);
-    if (link->io.NumPorts1)
-        printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-               link->io.BasePort1+link->io.NumPorts1-1);
-    if (link->io.NumPorts2)
-        printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-               link->io.BasePort2+link->io.NumPorts2-1);
+    if (link->resource[0])
+	printk(" & %pR", link->resource[0]);
+    if (link->resource[1])
+	printk(" & %pR", link->resource[1]);
     printk("\n");
 
     icard.para[0] = link->irq;
-    icard.para[1] = link->io.BasePort1;
+    icard.para[1] = link->resource[0]->start;
     icard.protocol = protocol;
     icard.typ = ISDN_CTYPE_TELESPCMCIA;
     
     i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
     if (i < 0) {
     	printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n",
-    		i, link->io.BasePort1);
+			i, (unsigned int) link->resource[0]->start);
     	teles_cs_release(link);
 	return -ENODEV;
     }
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index e249b89..b5ea9b8 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -356,7 +356,7 @@ static int tc574_config(struct pcmcia_device *link)
 		goto failed;
 
 	dev->irq = link->irq;
-	dev->base_addr = link->io.BasePort1;
+	dev->base_addr = link->resource[0]->start;
 
 	ioaddr = dev->base_addr;
 
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index b0772df..122ef4a 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -298,7 +298,7 @@ static int tc589_config(struct pcmcia_device *link)
 	    goto failed;
 
     dev->irq = link->irq;
-    dev->base_addr = link->io.BasePort1;
+    dev->base_addr = link->resource[0]->start;
     ioaddr = dev->base_addr;
     EL3WINDOW(0);
 
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index ee0a6d0..c52fdf3 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -332,7 +332,7 @@ static int axnet_config(struct pcmcia_device *link)
     if (!link->irq)
 	    goto failed;
     
-    if (link->io.NumPorts2 == 8) {
+    if (resource_size(link->resource[1]) == 8) {
 	link->conf.Attributes |= CONF_ENABLE_SPKR;
 	link->conf.Status = CCSR_AUDIO_ENA;
     }
@@ -342,7 +342,7 @@ static int axnet_config(struct pcmcia_device *link)
 	    goto failed;
 
     dev->irq = link->irq;
-    dev->base_addr = link->io.BasePort1;
+    dev->base_addr = link->resource[0]->start;
 
     if (!get_prom(link)) {
 	printk(KERN_NOTICE "axnet_cs: this is not an AX88190 card!\n");
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 99957af..3b53818 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -266,7 +266,7 @@ static int com20020_config(struct pcmcia_device *link)
 	goto failed;
     }
 	
-    ioaddr = dev->base_addr = link->io.BasePort1;
+    ioaddr = dev->base_addr = link->resource[0]->start;
     dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);
 
     dev_dbg(&link->dev, "request IRQ %d\n",
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 95a991b..bba6369 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -315,7 +315,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
 	if (ret == 0) {
 	    /* calculate ConfigIndex value */
 	    link->conf.ConfigIndex = 
-		((link->io.BasePort1 & 0x0f0) >> 3) | 0x22;
+		((link->resource[0]->start & 0x0f0) >> 3) | 0x22;
 	    return ret;
 	}
     }
@@ -436,9 +436,9 @@ static int fmvj18x_config(struct pcmcia_device *link)
 	    goto failed;
 
     dev->irq = link->irq;
-    dev->base_addr = link->io.BasePort1;
+    dev->base_addr = link->resource[0]->start;
 
-    if (link->io.BasePort2 != 0) {
+    if (resource_size(link->resource[1]) != 0) {
 	ret = fmvj18x_setup_mfc(link);
 	if (ret != 0) goto failed;
     }
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index c36dcd1..e99abaa 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -231,7 +231,7 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
 	if (ret)
 		goto failed;
     }
-    dev->base_addr = link->io.BasePort1;
+    dev->base_addr = link->resource[0]->start;
 
     ret = pcmcia_request_exclusive_irq(link, ibmtr_interrupt);
     if (ret)
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index c0d85af..9980cbb 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -655,7 +655,7 @@ static int nmclan_config(struct pcmcia_device *link)
 	  goto failed;
 
   dev->irq = link->irq;
-  dev->base_addr = link->io.BasePort1;
+  dev->base_addr = link->resource[0]->start;
 
   ioaddr = dev->base_addr;
 
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index db6dbda..c9cd237 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -554,7 +554,7 @@ static int pcnet_config(struct pcmcia_device *link)
     if (!link->irq)
 	    goto failed;
 
-    if (link->io.NumPorts2 == 8) {
+    if (resource_size(link->resource[1]) == 8) {
 	link->conf.Attributes |= CONF_ENABLE_SPKR;
 	link->conf.Status = CCSR_AUDIO_ENA;
     }
@@ -566,7 +566,7 @@ static int pcnet_config(struct pcmcia_device *link)
     if (ret)
 	    goto failed;
     dev->irq = link->irq;
-    dev->base_addr = link->io.BasePort1;
+    dev->base_addr = link->resource[0]->start;
     if (info->flags & HAS_MISC_REG) {
 	if ((if_port == 1) || (if_port == 2))
 	    dev->if_port = if_port;
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 88f503a..1b0b323 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -457,7 +457,7 @@ static int mhz_mfc_config(struct pcmcia_device *link)
     if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL))
 	    return -ENODEV;
 
-    dev->base_addr = link->io.BasePort1;
+    dev->base_addr = link->resource[0]->start;
 
     /* Allocate a memory window, for accessing the ISR */
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
@@ -545,7 +545,7 @@ static void mot_config(struct pcmcia_device *link)
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
-    unsigned int iouart = link->io.BasePort2;
+    unsigned int iouart = link->resource[1]->start;
 
     /* Set UART base address and force map with COR bit 1 */
     writeb(iouart & 0xff,        smc->base + MOT_UART + CISREG_IOBASE_0);
@@ -614,7 +614,7 @@ static int smc_config(struct pcmcia_device *link)
     link->io.NumPorts1 = 16;
     i = pcmcia_loop_config(link, smc_configcheck, NULL);
     if (!i)
-	    dev->base_addr = link->io.BasePort1;
+	    dev->base_addr = link->resource[0]->start;
 
     return i;
 }
@@ -666,7 +666,7 @@ static int osi_config(struct pcmcia_device *link)
 	link->io.NumPorts2 = 0;
 	i = pcmcia_request_io(link, &link->io);
     }
-    dev->base_addr = link->io.BasePort1 + 0x10;
+    dev->base_addr = link->resource[0]->start + 0x10;
     return i;
 }
 
@@ -683,7 +683,7 @@ static int osi_load_firmware(struct pcmcia_device *link)
 
 	/* Download the Seven of Diamonds firmware */
 	for (i = 0; i < fw->size; i++) {
-	    outb(fw->data[i], link->io.BasePort1 + 2);
+	    outb(fw->data[i], link->resource[0]->start + 2);
 	    udelay(50);
 	}
 	release_firmware(fw);
@@ -725,12 +725,12 @@ static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
 		return rc;
     } else if (manfid == MANFID_OSITECH) {
 	/* Make sure both functions are powered up */
-	set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR);
+	set_bits(0x300, link->resource[0]->start + OSITECH_AUI_PWR);
 	/* Now, turn on the interrupt for both card functions */
-	set_bits(0x300, link->io.BasePort1 + OSITECH_RESET_ISR);
+	set_bits(0x300, link->resource[0]->start + OSITECH_RESET_ISR);
 	dev_dbg(&link->dev, "AUI/PWR: %4.4x RESET/ISR: %4.4x\n",
-	      inw(link->io.BasePort1 + OSITECH_AUI_PWR),
-	      inw(link->io.BasePort1 + OSITECH_RESET_ISR));
+	      inw(link->resource[0]->start + OSITECH_AUI_PWR),
+	      inw(link->resource[0]->start + OSITECH_RESET_ISR));
     }
     return 0;
 }
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index add6c82..1577b00 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -877,13 +877,13 @@ xirc2ps_config(struct pcmcia_device * link)
 	 * the base address of the ethernet port (BasePort1) is written
 	 * to the BAR registers of the modem.
 	 */
-	err = pcmcia_write_config_byte(link, CISREG_IOBASE_0,
-				link->io.BasePort2 & 0xff);
+	err = pcmcia_write_config_byte(link, CISREG_IOBASE_0, (u8)
+				link->resource[1]->start & 0xff);
 	if (err)
 	    goto config_error;
 
-	err = pcmcia_write_config_byte(link, CISREG_IOBASE_1,
-				link->io.BasePort2 & 0xff);
+	err = pcmcia_write_config_byte(link, CISREG_IOBASE_1, (u8)
+				link->resource[1]->start & 0xff);
 	if (err)
 	    goto config_error;
 
@@ -907,7 +907,7 @@ xirc2ps_config(struct pcmcia_device * link)
 	 * part.
 	 */
 	writeb(0x47, local->dingo_ccr + CISREG_COR);
-	ioaddr = link->io.BasePort1;
+	ioaddr = link->resource[0]->start;
 	writeb(ioaddr & 0xff	  , local->dingo_ccr + CISREG_IOBASE_0);
 	writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1);
 
@@ -954,7 +954,7 @@ xirc2ps_config(struct pcmcia_device * link)
 
     /* we can now register the device with the net subsystem */
     dev->irq = link->irq;
-    dev->base_addr = link->io.BasePort1;
+    dev->base_addr = link->resource[0]->start;
 
     if (local->dingo)
 	do_reset(dev, 1); /* a kludge to make the cem56 work */
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 9389ba0..b7e7f50 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -271,7 +271,7 @@ static int airo_config(struct pcmcia_device *link)
 		goto failed;
 	((local_info_t *)link->priv)->eth_dev =
 		init_airo_card(link->irq,
-			       link->io.BasePort1, 1, &link->dev);
+			       link->resource[0]->start, 1, &link->dev);
 	if (!((local_info_t *)link->priv)->eth_dev)
 		goto failed;
 
@@ -281,12 +281,10 @@ static int airo_config(struct pcmcia_device *link)
 	if (link->conf.Vpp)
 		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
 	printk(", irq %d", link->irq);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1+link->io.NumPorts1-1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2+link->io.NumPorts2-1);
+	if (link->resource[0])
+		printk(" & %pR", link->resource[0]);
+	if (link->resource[1])
+		printk(" & %pR", link->resource[1]);
 	if (link->win)
 		printk(", mem 0x%06lx-0x%06lx", req->Base,
 		       req->Base+req->Size-1);
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 91ee74a..65b3aed 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -253,7 +253,7 @@ static int atmel_config(struct pcmcia_device *link)
 
 	((local_info_t*)link->priv)->eth_dev =
 		init_atmel_card(link->irq,
-				link->io.BasePort1,
+				link->resource[0]->start,
 				did ? did->driver_info : ATMEL_FW_TYPE_NONE,
 				&link->dev,
 				card_present,
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index def63bf..6db7fd1 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -227,7 +227,7 @@ static void sandisk_set_iobase(local_info_t *local)
 	struct hostap_cs_priv *hw_priv = local->hw_priv;
 
 	res = pcmcia_write_config_byte(hw_priv->link, 0x10,
-				hw_priv->link->io.BasePort1 & 0x00ff);
+				hw_priv->link->resource[0]->start & 0x00ff);
 	if (res != 0) {
 		printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -"
 		       " res=%d\n", res);
@@ -235,7 +235,7 @@ static void sandisk_set_iobase(local_info_t *local)
 	udelay(10);
 
 	res = pcmcia_write_config_byte(hw_priv->link, 0x12,
-				hw_priv->link->io.BasePort1 & 0x00ff);
+				hw_priv->link->resource[0]->start & 0x00ff);
 	if (res != 0) {
 		printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -"
 		       " res=%d\n", res);
@@ -265,7 +265,7 @@ static int sandisk_enable_wireless(struct net_device *dev)
 	local_info_t *local = iface->local;
 	struct hostap_cs_priv *hw_priv = local->hw_priv;
 
-	if (hw_priv->link->io.NumPorts1 < 0x42) {
+	if (resource_size(hw_priv->link->resource[0]) < 0x42) {
 		/* Not enough ports to be SanDisk multi-function card */
 		ret = -ENODEV;
 		goto done;
@@ -604,7 +604,7 @@ static int prism2_config(struct pcmcia_device *link)
 		goto failed_unlock;
 
 	dev->irq = link->irq;
-	dev->base_addr = link->io.BasePort1;
+	dev->base_addr = link->resource[0]->start;
 
 	spin_unlock_irqrestore(&local->irq_init_lock, flags);
 
@@ -616,12 +616,10 @@ static int prism2_config(struct pcmcia_device *link)
 		       link->conf.Vpp % 10);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %d", link->irq);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1+link->io.NumPorts1-1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2+link->io.NumPorts2-1);
+	if (link->resource[0])
+		printk(" & %pR", link->resource[0]);
+	if (link->resource[1])
+		printk(" & %pR", link->resource[1]);
 	printk("\n");
 
 	local->shutdown = 0;
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 1d3a7e0..be4c475 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -853,7 +853,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 		goto out1;
 
 	/* Initialize io access */
-	card->iobase = ioport_map(p_dev->io.BasePort1, p_dev->io.NumPorts1);
+	card->iobase = ioport_map(p_dev->resource[0]->start,
+				resource_size(p_dev->resource[0]));
 	if (!card->iobase) {
 		lbs_pr_err("error in ioport_map\n");
 		ret = -EIO;
@@ -872,9 +873,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 	}
 
 	/* Finally, report what we've done */
-	lbs_deb_cs("irq %d, io 0x%04x-0x%04x\n",
-	       p_dev->irq, p_dev->io.BasePort1,
-	       p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1);
+	lbs_deb_cs("irq %d, io %pR", p_dev->irq, p_dev->resource[0]);
 
 	/*
 	 * Most of the libertas cards can do unaligned register access, but some
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index 41ca4f1..6d514b5 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -257,7 +257,8 @@ orinoco_cs_config(struct pcmcia_device *link)
 	/* We initialize the hermes structure before completing PCMCIA
 	 * configuration just in case the interrupt handler gets
 	 * called. */
-	mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
+	mem = ioport_map(link->resource[0]->start,
+			resource_size(link->resource[0]));
 	if (!mem)
 		goto failed;
 
@@ -279,7 +280,7 @@ orinoco_cs_config(struct pcmcia_device *link)
 	}
 
 	/* Register an interface with the stack */
-	if (orinoco_if_add(priv, link->io.BasePort1,
+	if (orinoco_if_add(priv, link->resource[0]->start,
 			   link->irq, NULL) != 0) {
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		goto failed;
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 39399cd..4f8f55e 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -319,7 +319,8 @@ spectrum_cs_config(struct pcmcia_device *link)
 	/* We initialize the hermes structure before completing PCMCIA
 	 * configuration just in case the interrupt handler gets
 	 * called. */
-	mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
+	mem = ioport_map(link->resource[0]->start,
+			resource_size(link->resource[0]));
 	if (!mem)
 		goto failed;
 
@@ -346,7 +347,7 @@ spectrum_cs_config(struct pcmcia_device *link)
 	}
 
 	/* Register an interface with the stack */
-	if (orinoco_if_add(priv, link->io.BasePort1,
+	if (orinoco_if_add(priv, link->resource[0]->start,
 			   link->irq, NULL) != 0) {
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		goto failed;
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 35f431b..a32f220 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1960,7 +1960,7 @@ static int wl3501_config(struct pcmcia_device *link)
 		goto failed;
 
 	dev->irq = link->irq;
-	dev->base_addr = link->io.BasePort1;
+	dev->base_addr = link->resource[0]->start;
 	SET_NETDEV_DEV(dev, &link->dev);
 	if (register_netdev(dev)) {
 		printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index ee56fd6..fc1639c 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -177,12 +177,14 @@ static int parport_config(struct pcmcia_device *link)
     if (ret)
 	    goto failed;
 
-    p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,
+    p = parport_pc_probe_port(link->resource[0]->start,
+			      link->resource[1]->start,
 			      link->irq, PARPORT_DMA_NONE,
 			      &link->dev, IRQF_SHARED);
     if (p == NULL) {
 	printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at "
-	       "0x%3x, irq %u failed\n", link->io.BasePort1,
+	       "0x%3x, irq %u failed\n",
+	       (unsigned int) link->resource[0]->start,
 	       link->irq);
 	goto failed;
     }
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index b07b53e..3e040f5 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -167,7 +167,7 @@ static int aha152x_config_cs(struct pcmcia_device *link)
     /* Set configuration options for the aha152x driver */
     memset(&s, 0, sizeof(s));
     s.conf        = "PCMCIA setup";
-    s.io_port     = link->io.BasePort1;
+    s.io_port     = link->resource[0]->start;
     s.irq         = link->irq;
     s.scsiid      = host_id;
     s.reconnect   = reconnect;
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index ee04897..49a9a0a 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -137,10 +137,10 @@ static int fdomain_config(struct pcmcia_device *link)
 	    goto failed;
 
     /* A bad hack... */
-    release_region(link->io.BasePort1, link->io.NumPorts1);
+    release_region(link->resource[0]->start, resource_size(link->resource[0]));
 
     /* Set configuration options for the fdomain driver */
-    sprintf(str, "%d,%d", link->io.BasePort1, link->irq);
+    sprintf(str, "%d,%d", (unsigned int) link->resource[0]->start, link->irq);
     fdomain_setup(str);
 
     host = __fdomain_16x0_detect(&fdomain_driver_template);
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index d414207..964c913 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1719,17 +1719,19 @@ static int nsp_cs_config(struct pcmcia_device *link)
 		goto cs_failed;
 
 	if (free_ports) {
-		if (link->io.BasePort1) {
-			release_region(link->io.BasePort1, link->io.NumPorts1);
+		if (link->resource[0]) {
+			release_region(link->resource[0]->start,
+					resource_size(link->resource[0]);
 		}
-		if (link->io.BasePort2) {
-			release_region(link->io.BasePort2, link->io.NumPorts2);
+		if (link->resource[1]) {
+			release_region(link->resource[1]->start,
+					resource_size(link->resource[1]);
 		}
 	}
 
 	/* Set port and IRQ */
-	data->BaseAddress = link->io.BasePort1;
-	data->NumAddress  = link->io.NumPorts1;
+	data->BaseAddress = link->resource[0]->start;
+	data->NumAddress  = resurce_size(link->resource[0]);
 	data->IrqNumber   = link->irq;
 
 	nsp_dbg(NSP_DEBUG_INIT, "I/O[0x%x+0x%x] IRQ %d",
@@ -1764,13 +1766,10 @@ static int nsp_cs_config(struct pcmcia_device *link)
 	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
 		printk(", irq %d", link->irq);
 	}
-	if (link->io.NumPorts1) {
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1+link->io.NumPorts1-1);
-	}
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2+link->io.NumPorts2-1);
+	if (link->resource[0])
+		printk(", io %pR", link->resource[0]);
+	if (link->resource[1])
+		printk(" & %pR", link->resource[1]);
 	if (link->win)
 		printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
 		       cfg_mem->req.Base+cfg_mem->req.Size-1);
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index c1cf7f4..4e2b83f 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -215,18 +215,18 @@ static int qlogic_config(struct pcmcia_device * link)
 
 	if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
 		/* set ATAcmd */
-		outb(0xb4, link->io.BasePort1 + 0xd);
-		outb(0x24, link->io.BasePort1 + 0x9);
-		outb(0x04, link->io.BasePort1 + 0xd);
+		outb(0xb4, link->resource[0]->start + 0xd);
+		outb(0x24, link->resource[0]->start + 0x9);
+		outb(0x04, link->resource[0]->start + 0xd);
 	}
 
 	/* The KXL-810AN has a bigger IO port window */
-	if (link->io.NumPorts1 == 32)
+	if (resource_size(link->resource[0]) == 32)
 		host = qlogic_detect(&qlogicfas_driver_template, link,
-			link->io.BasePort1 + 16, link->irq);
+			link->resource[0]->start + 16, link->irq);
 	else
 		host = qlogic_detect(&qlogicfas_driver_template, link,
-			link->io.BasePort1, link->irq);
+			link->resource[0]->start, link->irq);
 	
 	if (!host) {
 		printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name);
@@ -268,9 +268,9 @@ static int qlogic_resume(struct pcmcia_device *link)
 	if ((info->manf_id == MANFID_MACNICA) ||
 	    (info->manf_id == MANFID_PIONEER) ||
 	    (info->manf_id == 0x0098)) {
-		outb(0x80, link->io.BasePort1 + 0xd);
-		outb(0x24, link->io.BasePort1 + 0x9);
-		outb(0x04, link->io.BasePort1 + 0xd);
+		outb(0x80, link->resource[0]->start + 0xd);
+		outb(0x24, link->resource[0]->start + 0x9);
+		outb(0x04, link->resource[0]->start + 0xd);
 	}
 	/* Ugggglllyyyy!!! */
 	qlogicfas408_bus_reset(NULL);
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index bd79e45..d99c0cb 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -733,9 +733,9 @@ SYM53C500_config(struct pcmcia_device *link)
 	    (info->manf_id == MANFID_PIONEER) ||
 	    (info->manf_id == 0x0098)) {
 		/* set ATAcmd */
-		outb(0xb4, link->io.BasePort1 + 0xd);
-		outb(0x24, link->io.BasePort1 + 0x9);
-		outb(0x04, link->io.BasePort1 + 0xd);
+		outb(0xb4, link->resource[0]->start + 0xd);
+		outb(0x24, link->resource[0]->start + 0x9);
+		outb(0x04, link->resource[0]->start + 0xd);
 	}
 
 	/*
@@ -748,7 +748,7 @@ SYM53C500_config(struct pcmcia_device *link)
 	*	0x130, 0x230, 0x280, 0x290,
 	*	0x320, 0x330, 0x340, 0x350
 	*/
-	port_base = link->io.BasePort1;
+	port_base = link->resource[0]->start;
 	irq_level = link->irq;
 
 	DEB(printk("SYM53C500: port_base=0x%x, irq=%d, fast_pio=%d\n",
@@ -821,15 +821,15 @@ static int sym53c500_resume(struct pcmcia_device *link)
 	if ((info->manf_id == MANFID_MACNICA) ||
 	    (info->manf_id == MANFID_PIONEER) ||
 	    (info->manf_id == 0x0098)) {
-		outb(0x80, link->io.BasePort1 + 0xd);
-		outb(0x24, link->io.BasePort1 + 0x9);
-		outb(0x04, link->io.BasePort1 + 0xd);
+		outb(0x80, link->resource[0]->start + 0xd);
+		outb(0x24, link->resource[0]->start + 0x9);
+		outb(0x04, link->resource[0]->start + 0xd);
 	}
 	/*
 	 *  If things don't work after a "resume",
 	 *  this is a good place to start looking.
 	 */
-	SYM53C500_int_host_reset(link->io.BasePort1);
+	SYM53C500_int_host_reset(link->resource[0]->start);
 
 	return 0;
 }
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 2be8b10..fe7adcd 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -463,13 +463,13 @@ static int simple_config(struct pcmcia_device *link)
 	/* If the card is already configured, look up the port and irq */
 	if (link->function_config) {
 		unsigned int port = 0;
-		if ((link->io.BasePort2 != 0) &&
-		    (link->io.NumPorts2 == 8)) {
-			port = link->io.BasePort2;
+		if ((link->resource[1]->end != 0) &&
+			(resource_size(link->resource[1]) == 8)) {
+			port = link->resource[1]->end;
 			info->slave = 1;
 		} else if ((info->manfid == MANFID_OSITECH) &&
-			   (link->io.NumPorts1 == 0x40)) {
-			port = link->io.BasePort1 + 0x28;
+			(resource_size(link->resource[0]) == 0x40)) {
+			port = link->resource[0]->start + 0x28;
 			info->slave = 1;
 		}
 		if (info->slave) {
@@ -507,7 +507,7 @@ found_port:
 	i = pcmcia_request_configuration(link, &link->conf);
 	if (i != 0)
 		return -1;
-	return setup_serial(link, info, link->io.BasePort1, link->irq);
+	return setup_serial(link, info, link->resource[0]->start, link->irq);
 }
 
 static int multi_config_check(struct pcmcia_device *p_dev,
@@ -524,7 +524,7 @@ static int multi_config_check(struct pcmcia_device *p_dev,
 		p_dev->io.BasePort1 = cf->io.win[0].base;
 		p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
 		if (!pcmcia_request_io(p_dev, &p_dev->io)) {
-			*base2 = p_dev->io.BasePort1 + 8;
+			*base2 = p_dev->resource[0]->start + 8;
 			return 0;
 		}
 	}
@@ -544,7 +544,7 @@ static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
 		p_dev->io.BasePort2 = cf->io.win[1].base;
 		p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
 		if (!pcmcia_request_io(p_dev, &p_dev->io)) {
-			*base2 = p_dev->io.BasePort2;
+			*base2 = p_dev->resource[1]->start;
 			return 0;
 		}
 	}
@@ -596,9 +596,9 @@ static int multi_config(struct pcmcia_device *link)
 		    link->conf.ConfigIndex == 3) {
 			err = setup_serial(link, info, base2,
 					link->irq);
-			base2 = link->io.BasePort1;
+			base2 = link->resource[0]->start;;
 		} else {
-			err = setup_serial(link, info, link->io.BasePort1,
+			err = setup_serial(link, info, link->resource[0]->start,
 					link->irq);
 		}
 		info->c950ctrl = base2;
@@ -613,7 +613,7 @@ static int multi_config(struct pcmcia_device *link)
 		return 0;
 	}
 
-	setup_serial(link, info, link->io.BasePort1, link->irq);
+	setup_serial(link, info, link->resource[0]->start, link->irq);
 	for (i = 0; i < info->multi - 1; i++)
 		setup_serial(link, info, base2 + (8 * i),
 				link->irq);
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index acef29c..208f1b7 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -170,7 +170,7 @@ static int das16cs_attach(struct comedi_device *dev,
 	if (!link)
 		return -EIO;
 
-	dev->iobase = link->io.BasePort1;
+	dev->iobase = link->resource[0]->start;;
 	printk("I/O base=0x%04lx ", dev->iobase);
 
 	printk("fingerprint:\n");
@@ -787,12 +787,10 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
 	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %u", link->irq);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1 + link->io.NumPorts1 - 1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2 + link->io.NumPorts2 - 1);
+	if (link->resource[0])
+		printk(", io %pR", link->resource[0]);
+	if (link->resource[1])
+		printk(", io %pR", link->resource[1]);
 	printk("\n");
 
 	return;
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index 3eddb7c..c4cfcff 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -88,7 +88,7 @@ static int das08_cs_attach(struct comedi_device *dev,
 			printk(" no pcmcia cards found\n");
 			return -EIO;
 		}
-		iobase = link->io.BasePort1;
+		iobase = link->resource[0]->start;
 	} else {
 		printk(" bug! board does not have PCMCIA bustype\n");
 		return -EINVAL;
@@ -283,12 +283,10 @@ static void das08_pcmcia_config(struct pcmcia_device *link)
 	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %u", link->irq);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1 + link->io.NumPorts1 - 1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2 + link->io.NumPorts2 - 1);
+	if (link->resource[0])
+		printk(", io %pR", link->resource[0]);
+	if (link->resource[1])
+		printk(" & %pR", link->resource[1]);
 	printk("\n");
 
 	return;
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index f3c4d2f..6d56957 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -376,7 +376,7 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		link = pcmcia_cur_dev;	/* XXX hack */
 		if (!link)
 			return -EIO;
-		iobase = link->io.BasePort1;
+		iobase = link->resource[0]->start;
 #ifdef incomplete
 		irq = link->irq;
 #endif
@@ -644,12 +644,10 @@ static void dio700_config(struct pcmcia_device *link)
 	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %d", link->irq);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1 + link->io.NumPorts1 - 1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2 + link->io.NumPorts2 - 1);
+	if (link->resource[0])
+		printk(", io %pR", link->resource[0]);
+	if (link->resource[1])
+		printk(" & %pR", link->resource[1]);
 	if (link->win)
 		printk(", mem 0x%06lx-0x%06lx", req.Base,
 		       req.Base + req.Size - 1);
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index f0c4367..29e1daf 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -128,7 +128,7 @@ static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		link = pcmcia_cur_dev;	/* XXX hack */
 		if (!link)
 			return -EIO;
-		iobase = link->io.BasePort1;
+		iobase = link->resource[0]->start;
 #ifdef incomplete
 		irq = link->irq;
 #endif
@@ -396,12 +396,10 @@ static void dio24_config(struct pcmcia_device *link)
 	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %d", link->irq);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1 + link->io.NumPorts1 - 1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2 + link->io.NumPorts2 - 1);
+	if (link->resource[0])
+		printk(" & %pR", link->resource[0]);
+	if (link->resource[1])
+		printk(" & %pR", link->resource[1]);
 	if (link->win)
 		printk(", mem 0x%06lx-0x%06lx", req.Base,
 		       req.Base + req.Size - 1);
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index 1ee78f8..fb10987 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -142,7 +142,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		link = pcmcia_cur_dev;	/* XXX hack */
 		if (!link)
 			return -EIO;
-		iobase = link->io.BasePort1;
+		iobase = link->resource[0]->start;
 		irq = link->irq;
 		break;
 	default:
@@ -373,12 +373,10 @@ static void labpc_config(struct pcmcia_device *link)
 	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %d", link->irq);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1 + link->io.NumPorts1 - 1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2 + link->io.NumPorts2 - 1);
+	if (link->resource[0])
+		printk(" & %pR", link->resource[0]);
+	if (link->resource[1])
+		printk(" & %pR", link->resource[1]);
 	if (link->win)
 		printk(", mem 0x%06lx-0x%06lx", req.Base,
 		       req.Base + req.Size - 1);
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index 0bce220..f37dc22 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -355,7 +355,7 @@ static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		return -EIO;
 
 	dev->driver = &driver_ni_mio_cs;
-	dev->iobase = link->io.BasePort1;
+	dev->iobase = link->resource[0]->start;
 
 	irq = link->irq;
 
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index 67c0fa6..80b8d57 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -871,7 +871,7 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		}
 	}
 
-	dev->iobase = local->link->io.BasePort1;
+	dev->iobase = local->link->resource[0]->start;
 
 	ret = alloc_subdevices(dev, 4);
 	if (ret < 0)
@@ -1153,12 +1153,10 @@ static void daqp_cs_config(struct pcmcia_device *link)
 	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %u", link->irq);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1 + link->io.NumPorts1 - 1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2 + link->io.NumPorts2 - 1);
+	if (link->resource[0])
+		printk(" & %pR", link->resource[0]);
+	if (link->resource[1])
+		printk(" & %pR", link->resource[1]);
 	printk("\n");
 
 	return;
diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c
index afe4575..2361537 100644
--- a/drivers/staging/wlags49_h2/wl_cs.c
+++ b/drivers/staging/wlags49_h2/wl_cs.c
@@ -319,7 +319,7 @@ void wl_adapter_insert( struct pcmcia_device *link )
         goto failed;
 
     dev->irq        = link->irq;
-    dev->base_addr  = link->io.BasePort1;
+    dev->base_addr  = link->resource[0]->start;
 
     SET_NETDEV_DEV(dev, &link->dev);
     if (register_netdev(dev) != 0) {
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index f6c7e6f..a801036 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -150,7 +150,8 @@ static int ixj_config(struct pcmcia_device * link)
 	/*
  	 *	Register the card with the core.
 	 */
-	j = ixj_pcmcia_probe(link->io.BasePort1, link->io.BasePort1 + 0x10);
+	j = ixj_pcmcia_probe(link->resource[0]->start,
+			     link->resource[0]->start + 0x10);
 
 	info->ndev = 1;
 	ixj_get_serial(link, j);
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index acb7e25..22e04f2 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -189,7 +189,7 @@ static int sl811_cs_config(struct pcmcia_device *link)
 		goto failed;
 
 	/* require an IRQ and two registers */
-	if (!link->io.NumPorts1 || link->io.NumPorts1 < 2)
+	if (resource_size(link->resource[0]) < 2)
 		goto failed;
 
 	if (!link->irq)
@@ -204,11 +204,10 @@ static int sl811_cs_config(struct pcmcia_device *link)
 	if (link->conf.Vpp)
 		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
 	printk(", irq %d", link->irq);
-	printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-	       link->io.BasePort1+link->io.NumPorts1-1);
+	printk(", io %pR", link->resource[0]);
 	printk("\n");
 
-	if (sl811_hc_init(parent, link->io.BasePort1, link->irq)
+	if (sl811_hc_init(parent, link->resource[0]->start, link->irq)
 			< 0) {
 failed:
 		printk(KERN_WARNING "sl811_cs_config failed\n");
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index df110df..9f897bc 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -231,7 +231,8 @@ static int pdacf_config(struct pcmcia_device *link)
 	if (ret)
 		goto failed;
 
-	if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq) < 0)
+	if (snd_pdacf_assign_resources(pdacf, link->resource[0]->start,
+					link->irq) < 0)
 		goto failed;
 
 	return 0;
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 624b47a..f23c235 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -241,7 +241,8 @@ static int vxpocket_config(struct pcmcia_device *link)
 	chip->dev = &link->dev;
 	snd_card_set_dev(chip->card, chip->dev);
 
-	if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq) < 0)
+	if (snd_vxpocket_assign_resources(chip, link->resource[0]->start,
+						link->irq) < 0)
 		goto failed;
 
 	return 0;
-- 
1.7.0.4


^ permalink raw reply related

* [PATCH] ath9k: fix an issue in ath_atx_tid paused flag management
From: Felix Fietkau @ 2010-08-01 13:47 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Luis R. Rodriguez, Lorenzo Bianconi

From: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>

I noticed a possible issue in the paused flag management of the
ath_atx_tid data structure. In particular, in a noisy environment and
under heavy load, I observed that the AGGR session establishment could
fail several times consecutively causing values of the paused flag
greater than one for this TID (ath_tx_pause_tid is called more than
once from ath_tx_aggr_start).

Considering that the session for this TID can not be established also
after the mac80211 stack calls the ieee80211_agg_tx_operational() since
the ath_tx_aggr_resume() lowers the paused flag only by one.

This patch also replaces some BUG_ON calls with WARN_ON, as even if
these unlikely conditions happen, it's not fatal enough to justify a
BUG_ON.

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -120,26 +120,14 @@ static void ath_tx_queue_tid(struct ath_
 	list_add_tail(&ac->list, &txq->axq_acq);
 }
 
-static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
-{
-	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
-
-	spin_lock_bh(&txq->axq_lock);
-	tid->paused++;
-	spin_unlock_bh(&txq->axq_lock);
-}
-
 static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 {
 	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
 
-	BUG_ON(tid->paused <= 0);
-	spin_lock_bh(&txq->axq_lock);
-
-	tid->paused--;
+	WARN_ON(!tid->paused);
 
-	if (tid->paused > 0)
-		goto unlock;
+	spin_lock_bh(&txq->axq_lock);
+	tid->paused = false;
 
 	if (list_empty(&tid->buf_q))
 		goto unlock;
@@ -157,15 +145,10 @@ static void ath_tx_flush_tid(struct ath_
 	struct list_head bf_head;
 	INIT_LIST_HEAD(&bf_head);
 
-	BUG_ON(tid->paused <= 0);
-	spin_lock_bh(&txq->axq_lock);
+	WARN_ON(!tid->paused);
 
-	tid->paused--;
-
-	if (tid->paused > 0) {
-		spin_unlock_bh(&txq->axq_lock);
-		return;
-	}
+	spin_lock_bh(&txq->axq_lock);
+	tid->paused = false;
 
 	while (!list_empty(&tid->buf_q)) {
 		bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
@@ -811,7 +794,7 @@ void ath_tx_aggr_start(struct ath_softc 
 	an = (struct ath_node *)sta->drv_priv;
 	txtid = ATH_AN_2_TID(an, tid);
 	txtid->state |= AGGR_ADDBA_PROGRESS;
-	ath_tx_pause_tid(sc, txtid);
+	txtid->paused = true;
 	*ssn = txtid->seq_start;
 }
 
@@ -835,10 +818,9 @@ void ath_tx_aggr_stop(struct ath_softc *
 		return;
 	}
 
-	ath_tx_pause_tid(sc, txtid);
-
 	/* drop all software retried frames and mark this TID */
 	spin_lock_bh(&txq->axq_lock);
+	txtid->paused = true;
 	while (!list_empty(&txtid->buf_q)) {
 		bf = list_first_entry(&txtid->buf_q, struct ath_buf, list);
 		if (!bf_isretried(bf)) {

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox