From 7f366784f5c2b8fc0658b5b374f4c63ee42c789f Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Thu, 24 Sep 2009 16:27:46 -0300 Subject: TPM: increase default TPM buffer The TPM Working Group requested this communication buffer increase given that a particular TPM vendor can support a TPM_SHA1Start command input bigger than the current size. Signed-off-by: Rajiv Andrade Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index b0603b2e5684..f4c68abf2a15 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -31,7 +31,7 @@ enum tpm_const { TPM_MINOR = 224, /* officially assigned */ - TPM_BUFSIZE = 2048, + TPM_BUFSIZE = 4096, TPM_NUM_DEVICES = 256, }; -- cgit v1.2.3 From 23acb98de5a4109a60b5fe3f0439389218b039d7 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Wed, 30 Sep 2009 12:26:55 -0300 Subject: TPM: fix pcrread The previously sent patch: http://marc.info/?l=tpmdd-devel&m=125208945007834&w=2 Had its first hunk cropped when merged, submitting only this first hunk again. Signed-off-by: Jason Gunthorpe Cc: Debora Velarde Cc: Marcel Selhorst Cc: James Morris Signed-off-by: Andrew Morton Signed-off-by: Rajiv Andrade Acked-by: Mimi Zohar Tested-by: Mimi Zohar Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index aeafac5bde8c..f06bb37defb1 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -696,8 +696,7 @@ int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) cmd.header.in = pcrread_header; cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); - BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE); - rc = transmit_cmd(chip, &cmd, cmd.header.in.length, + rc = transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, "attempting to read a pcr value"); if (rc == 0) -- cgit v1.2.3 From bb015f0c85362aa767f8f00f50a40d85e489414f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 19 Oct 2009 11:43:32 +0200 Subject: pcmcia: drop already defined PCI_IDs Out of 10 PCI_IDs found in the PCMCIA subsystem, only two were not defined in pci_ids.h. Move them and drop the duplicates. Successfully build-tested. Signed-off-by: Wolfram Sang Cc: Jesse Barnes Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cirrus.h | 10 ---------- drivers/pcmcia/o2micro.h | 22 ---------------------- 2 files changed, 32 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/cirrus.h b/drivers/pcmcia/cirrus.h index ecd4fc7f666f..446a4576e73e 100644 --- a/drivers/pcmcia/cirrus.h +++ b/drivers/pcmcia/cirrus.h @@ -30,16 +30,6 @@ #ifndef _LINUX_CIRRUS_H #define _LINUX_CIRRUS_H -#ifndef PCI_VENDOR_ID_CIRRUS -#define PCI_VENDOR_ID_CIRRUS 0x1013 -#endif -#ifndef PCI_DEVICE_ID_CIRRUS_6729 -#define PCI_DEVICE_ID_CIRRUS_6729 0x1100 -#endif -#ifndef PCI_DEVICE_ID_CIRRUS_6832 -#define PCI_DEVICE_ID_CIRRUS_6832 0x1110 -#endif - #define PD67_MISC_CTL_1 0x16 /* Misc control 1 */ #define PD67_FIFO_CTL 0x17 /* FIFO control */ #define PD67_MISC_CTL_2 0x1E /* Misc control 2 */ diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h index 72188c462c9c..624442fc0d35 100644 --- a/drivers/pcmcia/o2micro.h +++ b/drivers/pcmcia/o2micro.h @@ -30,28 +30,6 @@ #ifndef _LINUX_O2MICRO_H #define _LINUX_O2MICRO_H -#ifndef PCI_VENDOR_ID_O2 -#define PCI_VENDOR_ID_O2 0x1217 -#endif -#ifndef PCI_DEVICE_ID_O2_6729 -#define PCI_DEVICE_ID_O2_6729 0x6729 -#endif -#ifndef PCI_DEVICE_ID_O2_6730 -#define PCI_DEVICE_ID_O2_6730 0x673a -#endif -#ifndef PCI_DEVICE_ID_O2_6832 -#define PCI_DEVICE_ID_O2_6832 0x6832 -#endif -#ifndef PCI_DEVICE_ID_O2_6836 -#define PCI_DEVICE_ID_O2_6836 0x6836 -#endif -#ifndef PCI_DEVICE_ID_O2_6812 -#define PCI_DEVICE_ID_O2_6812 0x6872 -#endif -#ifndef PCI_DEVICE_ID_O2_6933 -#define PCI_DEVICE_ID_O2_6933 0x6933 -#endif - /* Additional PCI configuration registers */ #define O2_MUX_CONTROL 0x90 /* 32 bit */ -- cgit v1.2.3 From 6ae3b84d979308671bf6f6a2123c258a8603d61c Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 18 Oct 2009 18:14:32 +0200 Subject: serial_cs: use pcmcia_loop_config() and pre-determined values As the PCMCIA core already determines the multifunction count, the ConfigBase address and the Present value, we can use them directly instead of parsing the CIS again. By making use of pcmcia_loop_config(), we can further remove the remaining call to pcmcia_get_first_tuple() and friends. CC: linux-serial@vger.kernel.org CC: Russell King Signed-off-by: Dominik Brodowski --- drivers/serial/serial_cs.c | 87 ++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index ff4617e21426..7bf02cf3123f 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -426,21 +426,6 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, /*====================================================================*/ -static int -first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse) -{ - int i; - i = pcmcia_get_first_tuple(handle, tuple); - if (i != 0) - return i; - i = pcmcia_get_tuple_data(handle, tuple); - if (i != 0) - return i; - return pcmcia_parse_tuple(tuple, parse); -} - -/*====================================================================*/ - static int simple_config_check(struct pcmcia_device *p_dev, cistpl_cftable_entry_t *cf, cistpl_cftable_entry_t *dflt, @@ -665,6 +650,25 @@ static int multi_config(struct pcmcia_device *link) return 0; } +static int serial_check_for_multi(struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cf, + cistpl_cftable_entry_t *dflt, + unsigned int vcc, + void *priv_data) +{ + struct serial_info *info = p_dev->priv; + + if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) + info->multi = cf->io.win[0].len >> 3; + + if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && + (cf->io.win[1].len == 8)) + info->multi = 2; + + return 0; /* break */ +} + + /*====================================================================== serial_config() is scheduled to run after a CARD_INSERTION event @@ -676,46 +680,14 @@ static int multi_config(struct pcmcia_device *link) static int serial_config(struct pcmcia_device * link) { struct serial_info *info = link->priv; - struct serial_cfg_mem *cfg_mem; - tuple_t *tuple; - u_char *buf; - cisparse_t *parse; - cistpl_cftable_entry_t *cf; - int i, last_ret, last_fn; + int i; DEBUG(0, "serial_config(0x%p)\n", link); - cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); - if (!cfg_mem) - goto failed; - - tuple = &cfg_mem->tuple; - parse = &cfg_mem->parse; - cf = &parse->cftable_entry; - buf = cfg_mem->buf; - - tuple->TupleData = (cisdata_t *) buf; - tuple->TupleOffset = 0; - tuple->TupleDataMax = 255; - tuple->Attributes = 0; - - /* Get configuration register information */ - tuple->DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(link, tuple, parse); - if (last_ret != 0) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse->config.base; - link->conf.Present = parse->config.rmask[0]; - /* Is this a compliant multifunction card? */ - tuple->DesiredTuple = CISTPL_LONGLINK_MFC; - tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; - info->multi = (first_tuple(link, tuple, parse) == 0); + info->multi = (link->socket->functions > 1); /* Is this a multiport card? */ - tuple->DesiredTuple = CISTPL_MANFID; info->manfid = link->manf_id; info->prodid = link->card_id; @@ -730,20 +702,11 @@ static int serial_config(struct pcmcia_device * link) /* Another check for dual-serial cards: look for either serial or multifunction cards that ask for appropriate IO port ranges */ - tuple->DesiredTuple = CISTPL_FUNCID; if ((info->multi == 0) && (link->has_func_id) && ((link->func_id == CISTPL_FUNCID_MULTI) || - (link->func_id == CISTPL_FUNCID_SERIAL))) { - tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; - if (first_tuple(link, tuple, parse) == 0) { - if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) - info->multi = cf->io.win[0].len >> 3; - if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && - (cf->io.win[1].len == 8)) - info->multi = 2; - } - } + (link->func_id == CISTPL_FUNCID_SERIAL))) + pcmcia_loop_config(link, serial_check_for_multi, info); /* * Apply any multi-port quirk. @@ -768,14 +731,10 @@ static int serial_config(struct pcmcia_device * link) goto failed; link->dev_node = &info->node[0]; - kfree(cfg_mem); return 0; -cs_failed: - cs_error(link, last_fn, last_ret); failed: serial_remove(link); - kfree(cfg_mem); return -ENODEV; } -- cgit v1.2.3 From 4f65ae36f0291ef97b7d4de2f59b2e68f3c8420b Mon Sep 17 00:00:00 2001 From: Pavel Vasilyev Date: Thu, 29 Oct 2009 17:16:00 +0100 Subject: agp/amd64: Remove GART dependency on AGP_AMD64 The GART IOMMU code has no strong dependency to the AMD64 AGP code. So the automatic selection of AGP_AMD64 for GART can be removed. Cc: Dave Jones Signed-off-by: Pavel Vasilyev Signed-off-by: Joerg Roedel --- drivers/char/agp/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index ccb1fa89de29..2fb3a480f6b0 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -56,9 +56,8 @@ config AGP_AMD X on AMD Irongate, 761, and 762 chipsets. config AGP_AMD64 - tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU + tristate "AMD Opteron/Athlon64 on-CPU GART support" depends on AGP && X86 - default y if GART_IOMMU help This option gives you AGP support for the GLX component of X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. -- cgit v1.2.3 From 3507d612366a4e81226295f646410130a1f62a5c Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Thu, 10 Sep 2009 17:09:35 -0300 Subject: tpm_tis: TPM_STS_DATA_EXPECT workaround Some newer Lenovo models are shipped with a TPM that doesn't seem to set the TPM_STS_DATA_EXPECT status bit when sending it a burst of data, so the code understands it as a failure and doesn't proceed sending the chip the intended data. In this patch we bypass this bit check in case the itpm module parameter was set. This patch is based on Andy Isaacson's one: http://marc.info/?l=linux-kernel&m=124650185023495&w=2 It was heavily discussed how should we deal with identifying the chip in kernel space, but the required patch to do so was NACK'd: http://marc.info/?l=linux-kernel&m=124650186423711&w=2 This way we let the user choose using this workaround or not based on his observations on this code behavior when trying to use the TPM. Fixed a checkpatch issue present on the previous patch, thanks to Daniel Walker. Signed-off-by: Rajiv Andrade Acked-by: Eric Paris Tested-by: Seiji Munetoh Signed-off-by: James Morris --- drivers/char/tpm/tpm_tis.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 0b73e4ec1add..27e8de415309 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -257,6 +257,10 @@ out: return size; } +static int itpm; +module_param(itpm, bool, 0444); +MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)"); + /* * If interrupts are used (signaled by an irq set in the vendor structure) * tpm.c can skip polling for the data to be available as the interrupt is @@ -293,7 +297,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &chip->vendor.int_queue); status = tpm_tis_status(chip); - if ((status & TPM_STS_DATA_EXPECT) == 0) { + if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { rc = -EIO; goto out_err; } @@ -467,6 +471,10 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, "1.2 TPM (device-id 0x%X, rev-id %d)\n", vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); + if (itpm) + dev_info(dev, "Intel iTPM workaround enabled\n"); + + /* Figure out the capabilities */ intfcaps = ioread32(chip->vendor.iobase + -- cgit v1.2.3 From 31bde71c202722a76686c3cf69a254c8a912275a Mon Sep 17 00:00:00 2001 From: Matt Domsch Date: Tue, 3 Nov 2009 12:05:50 +1100 Subject: tpm: autoload tpm_tis based on system PnP IDs The tpm_tis driver already has a list of supported pnp_device_ids. This patch simply exports that list as a MODULE_DEVICE_TABLE() so that the module autoloader will discover and load the module at boottime. Signed-off-by: Matt Domsch Acked-by: Rajiv Andrade Signed-off-by: Andrew Morton Signed-off-by: James Morris --- drivers/char/tpm/tpm_tis.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 27e8de415309..2405f17b29dd 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -637,6 +637,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { {"", 0}, /* User Specified */ {"", 0} /* Terminator */ }; +MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev) { -- cgit v1.2.3 From 7d2e8d00b47b973c92db4df7444d5e6d3bb945f9 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 18 Oct 2009 18:22:32 +0200 Subject: pcmcia: use pre-determined values A few PCMCIA network drivers can make use of values provided by the pcmcia core, instead of tedious, independent CIS parsing. xirc32ps_cs.c: manf_id hostap_cs.c: multifunction count b43/pcmcia.c: ConfigBase address and "Present" smc91c92_cs.c: By default, mhz_setup() can use VERS_1 as it is stored in struct pcmcia_device. Only some cards require workarounds, such as reading out VERS_1 twice. CC: David S. Miller CC: netdev@vger.kernel.org CC: linux-wireless@vger.kernel.org Acked-by: John W. Linville Signed-off-by: Dominik Brodowski --- drivers/net/pcmcia/smc91c92_cs.c | 11 +++++++++-- drivers/net/pcmcia/xirc2ps_cs.c | 12 +++++++++--- drivers/net/wireless/b43/pcmcia.c | 20 -------------------- drivers/net/wireless/hostap/hostap_cs.c | 21 +-------------------- 4 files changed, 19 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 7bde2cd34c7e..af03759d186d 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -545,6 +545,14 @@ static int mhz_setup(struct pcmcia_device *link) u_char *buf, *station_addr; int rc; + /* Read the station address from the CIS. It is stored as the last + (fourth) string in the Version 1 Version/ID tuple. */ + if ((link->prod_id[3]) && + (cvt_ascii_address(dev, link->prod_id[3]) == 0)) + return 0; + + /* Workarounds for broken cards start here. */ + cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); if (!cfg_mem) return -1; @@ -557,8 +565,7 @@ static int mhz_setup(struct pcmcia_device *link) tuple->TupleData = (cisdata_t *)buf; tuple->TupleDataMax = 255; - /* Read the station address from the CIS. It is stored as the last - (fourth) string in the Version 1 Version/ID tuple. */ + /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ tuple->DesiredTuple = CISTPL_VERS_1; if (first_tuple(link, tuple, parse) != 0) { rc = -1; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index cf8423102538..5e203230144f 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -792,13 +792,12 @@ xirc2ps_config(struct pcmcia_device * link) tuple.TupleOffset = 0; /* Is this a valid card */ - tuple.DesiredTuple = CISTPL_MANFID; - if ((err=first_tuple(link, &tuple, &parse))) { + if (link->has_manf_id == 0) { printk(KNOT_XIRC "manfid not found in CIS\n"); goto failure; } - switch(parse.manfid.manf) { + switch (link->manf_id) { case MANFID_XIRCOM: local->manf_str = "Xircom"; break; @@ -822,6 +821,13 @@ xirc2ps_config(struct pcmcia_device * link) } DEBUG(0, "found %s card\n", local->manf_str); + /* needed for the additional fields to be parsed by set_card_type() */ + tuple.DesiredTuple = CISTPL_MANFID; + err = first_tuple(link, &tuple, &parse) + if (err) { + printk(KNOT_XIRC "manfid not found in CIS\n"); + goto failure; + } if (!set_card_type(link, buf)) { printk(KNOT_XIRC "this card is not supported\n"); goto failure; diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index 6c3a74964ab8..cd14b7e8ba80 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -65,35 +65,15 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) struct ssb_bus *ssb; win_req_t win; memreq_t mem; - tuple_t tuple; - cisparse_t parse; int err = -ENOMEM; int res = 0; - unsigned char buf[64]; ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); if (!ssb) goto out_error; err = -ENODEV; - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - res = pcmcia_get_first_tuple(dev, &tuple); - if (res != 0) - goto err_kfree_ssb; - res = pcmcia_get_tuple_data(dev, &tuple); - if (res != 0) - goto err_kfree_ssb; - res = pcmcia_parse_tuple(&tuple, &parse); - if (res != 0) - goto err_kfree_ssb; - - dev->conf.ConfigBase = parse.config.base; - dev->conf.Present = parse.config.rmask[0]; dev->conf.Attributes = CONF_ENABLE_IRQ; dev->conf.IntType = INT_MEMORY_AND_IO; diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index ad8eab4a639b..31b60dd87bfe 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -274,9 +274,6 @@ static int sandisk_enable_wireless(struct net_device *dev) conf_reg_t reg; struct hostap_interface *iface = netdev_priv(dev); local_info_t *local = iface->local; - tuple_t tuple; - cisparse_t *parse = NULL; - u_char buf[64]; struct hostap_cs_priv *hw_priv = local->hw_priv; if (hw_priv->link->io.NumPorts1 < 0x42) { @@ -285,28 +282,13 @@ static int sandisk_enable_wireless(struct net_device *dev) goto done; } - parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); - if (parse == NULL) { - ret = -ENOMEM; - goto done; - } - - tuple.Attributes = TUPLE_RETURN_COMMON; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - if (hw_priv->link->manf_id != 0xd601 || hw_priv->link->card_id != 0x0101) { /* No SanDisk manfid found */ ret = -ENODEV; goto done; } - tuple.DesiredTuple = CISTPL_LONGLINK_MFC; - if (pcmcia_get_first_tuple(hw_priv->link, &tuple) || - pcmcia_get_tuple_data(hw_priv->link, &tuple) || - pcmcia_parse_tuple(&tuple, parse) || - parse->longlink_mfc.nfn < 2) { + if (hw_priv->link->socket->functions < 2) { /* No multi-function links found */ ret = -ENODEV; goto done; @@ -354,7 +336,6 @@ static int sandisk_enable_wireless(struct net_device *dev) udelay(10); done: - kfree(parse); return ret; } -- cgit v1.2.3 From aaa8cfdada648a6bae32f62df76cc60137a2b323 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 18 Oct 2009 18:28:39 +0200 Subject: pcmcia: use pcmcia_loop_config in misc pcmcia drivers Use pcmcia_loop_config() in a few drivers missed during the first round. On fmvj18x_cs.c it -- strangely -- only requries us to set conf.ConfigIndex, which is done by the core, so include an empty loop function which returns 0 unconditionally. CC: David S. Miller CC: David Sterba CC: netdev@vger.kernel.org CC: linux-wireless@vger.kernel.org For the ipwireless part: Acked-by: Jiri Kosina Acked-by: John W. Linville Signed-off-by: Dominik Brodowski --- drivers/char/pcmcia/ipwireless/main.c | 103 ++++++++-------------------------- drivers/char/pcmcia/synclink_cs.c | 64 ++++++++------------- drivers/net/pcmcia/fmvj18x_cs.c | 22 +++++--- drivers/net/wireless/libertas/if_cs.c | 67 +++++++++------------- 4 files changed, 88 insertions(+), 168 deletions(-) (limited to 'drivers') diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index 5216fce0c62d..263a18f381b3 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c @@ -79,14 +79,32 @@ static void signalled_reboot_callback(void *callback_data) schedule_work(&ipw->work_reboot); } +static int ipwireless_ioprobe(struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cfg, + cistpl_cftable_entry_t *dflt, + 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->io.IOAddrLines = 16; + + p_dev->irq.IRQInfo1 = cfg->irq.IRQInfo1; + + /* 0x40 causes it to generate level mode interrupts. */ + /* 0x04 enables IREQ pin. */ + p_dev->conf.ConfigIndex = cfg->index | 0x44; + return pcmcia_request_io(p_dev, &p_dev->io); +} + static int config_ipwireless(struct ipw_dev *ipw) { struct pcmcia_device *link = ipw->link; - int ret; + int ret = 0; tuple_t tuple; unsigned short buf[64]; cisparse_t parse; - unsigned short cor_value; memreq_t memreq_attr_memory; memreq_t memreq_common_memory; @@ -97,103 +115,26 @@ static int config_ipwireless(struct ipw_dev *ipw) tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - tuple.DesiredTuple = RETURN_FIRST_TUPLE; - - ret = pcmcia_get_first_tuple(link, &tuple); - - while (ret == 0) { - ret = pcmcia_get_tuple_data(link, &tuple); - - if (ret != 0) { - cs_error(link, GetTupleData, ret); - goto exit0; - } - ret = pcmcia_get_next_tuple(link, &tuple); - } - - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - - ret = pcmcia_get_first_tuple(link, &tuple); - - if (ret != 0) { - cs_error(link, GetFirstTuple, ret); - goto exit0; - } - - ret = pcmcia_get_tuple_data(link, &tuple); - - if (ret != 0) { - cs_error(link, GetTupleData, ret); - goto exit0; - } - - ret = pcmcia_parse_tuple(&tuple, &parse); - - if (ret != 0) { - cs_error(link, ParseTuple, ret); - goto exit0; - } - - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.BasePort1 = parse.cftable_entry.io.win[0].base; - link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; - link->io.IOAddrLines = 16; - - link->irq.IRQInfo1 = parse.cftable_entry.irq.IRQInfo1; - - /* 0x40 causes it to generate level mode interrupts. */ - /* 0x04 enables IREQ pin. */ - cor_value = parse.cftable_entry.index | 0x44; - link->conf.ConfigIndex = cor_value; - - /* IRQ and I/O settings */ - tuple.DesiredTuple = CISTPL_CONFIG; - - ret = pcmcia_get_first_tuple(link, &tuple); - + ret = pcmcia_loop_config(link, ipwireless_ioprobe, NULL); if (ret != 0) { - cs_error(link, GetFirstTuple, ret); - goto exit0; - } - - ret = pcmcia_get_tuple_data(link, &tuple); - - if (ret != 0) { - cs_error(link, GetTupleData, ret); + cs_error(link, RequestIO, ret); goto exit0; } - ret = pcmcia_parse_tuple(&tuple, &parse); - - if (ret != 0) { - cs_error(link, GetTupleData, ret); - goto exit0; - } link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; link->conf.IntType = INT_MEMORY_AND_IO; link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; link->irq.Handler = ipwireless_interrupt; link->irq.Instance = ipw->hardware; - ret = pcmcia_request_io(link, &link->io); - - if (ret != 0) { - cs_error(link, RequestIO, ret); - goto exit0; - } - request_region(link->io.BasePort1, link->io.NumPorts1, IPWIRELESS_PCCARD_NAME); /* memory settings */ - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; ret = pcmcia_get_first_tuple(link, &tuple); - if (ret != 0) { cs_error(link, GetFirstTuple, ret); goto exit1; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index caf6e4d19469..429b7313119b 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -575,55 +575,39 @@ static int mgslpc_probe(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) +static int mgslpc_ioprobe(struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cfg, + cistpl_cftable_entry_t *dflt, + 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; +} + static int mgslpc_config(struct pcmcia_device *link) { MGSLPC_INFO *info = link->priv; - tuple_t tuple; - cisparse_t parse; - int last_fn, last_ret; - u_char buf[64]; - cistpl_cftable_entry_t dflt = { 0 }; - cistpl_cftable_entry_t *cfg; + int last_fn = RequestIO; + int last_ret; if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_config(0x%p)\n", link); - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - - /* get CIS configuration entry */ - - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - - cfg = &(parse.cftable_entry); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(&tuple, &parse)); - - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; - if (cfg->index == 0) + last_ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL); + if (last_ret != 0) goto cs_failed; - link->conf.ConfigIndex = cfg->index; - link->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - link->io.NumPorts1 = 0; - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - link->io.BasePort1 = io->win[0].base; - link->io.NumPorts1 = io->win[0].len; - CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); - } - link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 8; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 7e01fbdb87e0..c7a2bbfaf821 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -341,14 +341,23 @@ static int ungermann_try_io_port(struct pcmcia_device *link) return ret; /* RequestIO failed */ } +static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cfg, + cistpl_cftable_entry_t *dflt, + unsigned int vcc, + void *priv_data) +{ + return 0; /* strange, but that's what the code did already before... */ +} + + static int fmvj18x_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; local_info_t *lp = netdev_priv(dev); tuple_t tuple; - cisparse_t parse; u_short buf[32]; - int i, last_fn = 0, last_ret = 0, ret; + int i, last_fn = RequestIO, last_ret = 0, ret; unsigned int ioaddr; cardtype_t cardtype; char *card_name = "unknown"; @@ -362,12 +371,11 @@ static int fmvj18x_config(struct pcmcia_device *link) tuple.DesiredTuple = CISTPL_FUNCE; tuple.TupleOffset = 0; if (pcmcia_get_first_tuple(link, &tuple) == 0) { + last_ret = pcmcia_loop_config(link, fmvj18x_ioprobe, NULL); + if (last_ret != 0) + goto cs_failed; + /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(&tuple, &parse)); - link->conf.ConfigIndex = parse.cftable_entry.index; switch (link->manf_id) { case MANFID_TDK: cardtype = TDK; diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 62381768f2d5..cb40c386fc77 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -793,18 +793,37 @@ static void if_cs_release(struct pcmcia_device *p_dev) * configure the card at this point -- we wait until we receive a card * insertion event. */ + +static int if_cs_ioprobe(struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cfg, + cistpl_cftable_entry_t *dflt, + 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; + + /* Do we need to allocate an interrupt? */ + if (cfg->irq.IRQInfo1) + p_dev->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + if (cfg->io.nwin != 1) { + lbs_pr_err("wrong CIS (check number of IO windows)\n"); + return -ENODEV; + } + + /* This reserves IO space but doesn't actually enable it */ + return pcmcia_request_io(p_dev, &p_dev->io); +} + static int if_cs_probe(struct pcmcia_device *p_dev) { int ret = -ENOMEM; unsigned int prod_id; struct lbs_private *priv; struct if_cs_card *card; - /* CIS parsing */ - tuple_t tuple; - cisparse_t parse; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_io_t *io = &cfg->io; - u_char buf[64]; lbs_deb_enter(LBS_DEB_CS); @@ -823,43 +842,11 @@ static int if_cs_probe(struct pcmcia_device *p_dev) p_dev->conf.Attributes = 0; p_dev->conf.IntType = INT_MEMORY_AND_IO; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - if ((ret = pcmcia_get_first_tuple(p_dev, &tuple)) != 0 || - (ret = pcmcia_get_tuple_data(p_dev, &tuple)) != 0 || - (ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) - { - lbs_pr_err("error in pcmcia_get_first_tuple etc\n"); - goto out1; - } - - p_dev->conf.ConfigIndex = cfg->index; - - /* Do we need to allocate an interrupt? */ - if (cfg->irq.IRQInfo1) { - p_dev->conf.Attributes |= CONF_ENABLE_IRQ; - } - - /* IO window settings */ - if (cfg->io.nwin != 1) { - lbs_pr_err("wrong CIS (check number of IO windows)\n"); - ret = -ENODEV; + if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) { + lbs_pr_err("error in pcmcia_loop_config\n"); goto out1; } - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; - /* This reserves IO space but doesn't actually enable it */ - ret = pcmcia_request_io(p_dev, &p_dev->io); - if (ret) { - lbs_pr_err("error in pcmcia_request_io\n"); - goto out1; - } /* * Allocate an interrupt line. Note that this does not assign -- cgit v1.2.3 From af757923a92e6e9dbfdb6b0264be14c564e1c466 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 18 Oct 2009 19:48:39 +0200 Subject: ipwireless: make more use of pcmcia_loop_config() Within the pcmcia_loop_config() callback, we already have all tuple data available we need. Also add a fix to release the IO resource (at least within pcmcia_loop_config() error path). CC: Jiri Kosina CC: David Sterba Signed-off-by: Dominik Brodowski --- drivers/char/pcmcia/ipwireless/main.c | 213 ++++++++++++++++------------------ 1 file changed, 99 insertions(+), 114 deletions(-) (limited to 'drivers') diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index 263a18f381b3..0f4674959917 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c @@ -79,12 +79,18 @@ static void signalled_reboot_callback(void *callback_data) schedule_work(&ipw->work_reboot); } -static int ipwireless_ioprobe(struct pcmcia_device *p_dev, - cistpl_cftable_entry_t *cfg, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) +static int ipwireless_probe(struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cfg, + cistpl_cftable_entry_t *dflt, + unsigned int vcc, + void *priv_data) { + struct ipw_dev *ipw = priv_data; + struct resource *io_resource; + memreq_t memreq_attr_memory; + 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; @@ -95,133 +101,118 @@ static int ipwireless_ioprobe(struct pcmcia_device *p_dev, /* 0x40 causes it to generate level mode interrupts. */ /* 0x04 enables IREQ pin. */ p_dev->conf.ConfigIndex = cfg->index | 0x44; - return pcmcia_request_io(p_dev, &p_dev->io); -} + ret = pcmcia_request_io(p_dev, &p_dev->io); + if (ret) + return ret; -static int config_ipwireless(struct ipw_dev *ipw) -{ - struct pcmcia_device *link = ipw->link; - int ret = 0; - tuple_t tuple; - unsigned short buf[64]; - cisparse_t parse; - memreq_t memreq_attr_memory; - memreq_t memreq_common_memory; + io_resource = request_region(p_dev->io.BasePort1, p_dev->io.NumPorts1, + IPWIRELESS_PCCARD_NAME); - ipw->is_v2_card = 0; + if (cfg->mem.nwin == 0) + return 0; - tuple.Attributes = 0; - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; + ipw->request_common_memory.Attributes = + WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; + ipw->request_common_memory.Base = cfg->mem.win[0].host_addr; + ipw->request_common_memory.Size = cfg->mem.win[0].len; + if (ipw->request_common_memory.Size < 0x1000) + ipw->request_common_memory.Size = 0x1000; + ipw->request_common_memory.AccessSpeed = 0; + + ret = pcmcia_request_window(&p_dev, &ipw->request_common_memory, + &ipw->handle_common_memory); - ret = pcmcia_loop_config(link, ipwireless_ioprobe, NULL); if (ret != 0) { - cs_error(link, RequestIO, ret); - goto exit0; + cs_error(p_dev, RequestWindow, ret); + goto exit1; } - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; - link->irq.Handler = ipwireless_interrupt; - link->irq.Instance = ipw->hardware; + memreq_common_memory.CardOffset = cfg->mem.win[0].card_addr; + memreq_common_memory.Page = 0; - request_region(link->io.BasePort1, link->io.NumPorts1, - IPWIRELESS_PCCARD_NAME); - - /* memory settings */ - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + ret = pcmcia_map_mem_page(ipw->handle_common_memory, + &memreq_common_memory); - ret = pcmcia_get_first_tuple(link, &tuple); if (ret != 0) { - cs_error(link, GetFirstTuple, ret); - goto exit1; + cs_error(p_dev, MapMemPage, ret); + goto exit2; } - ret = pcmcia_get_tuple_data(link, &tuple); + ipw->is_v2_card = cfg->mem.win[0].len == 0x100; - if (ret != 0) { - cs_error(link, GetTupleData, ret); - goto exit1; - } + ipw->common_memory = ioremap(ipw->request_common_memory.Base, + ipw->request_common_memory.Size); + request_mem_region(ipw->request_common_memory.Base, + ipw->request_common_memory.Size, + IPWIRELESS_PCCARD_NAME); + + ipw->request_attr_memory.Attributes = + WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; + ipw->request_attr_memory.Base = 0; + ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ + ipw->request_attr_memory.AccessSpeed = 0; - ret = pcmcia_parse_tuple(&tuple, &parse); + ret = pcmcia_request_window(&p_dev, &ipw->request_attr_memory, + &ipw->handle_attr_memory); if (ret != 0) { - cs_error(link, ParseTuple, ret); - goto exit1; + cs_error(p_dev, RequestWindow, ret); + goto exit2; } - if (parse.cftable_entry.mem.nwin > 0) { - ipw->request_common_memory.Attributes = - WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; - ipw->request_common_memory.Base = - parse.cftable_entry.mem.win[0].host_addr; - ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len; - if (ipw->request_common_memory.Size < 0x1000) - ipw->request_common_memory.Size = 0x1000; - ipw->request_common_memory.AccessSpeed = 0; - - ret = pcmcia_request_window(&link, &ipw->request_common_memory, - &ipw->handle_common_memory); - - if (ret != 0) { - cs_error(link, RequestWindow, ret); - goto exit1; - } + memreq_attr_memory.CardOffset = 0; + memreq_attr_memory.Page = 0; - memreq_common_memory.CardOffset = - parse.cftable_entry.mem.win[0].card_addr; - memreq_common_memory.Page = 0; + ret = pcmcia_map_mem_page(ipw->handle_attr_memory, + &memreq_attr_memory); - ret = pcmcia_map_mem_page(ipw->handle_common_memory, - &memreq_common_memory); + if (ret != 0) { + cs_error(p_dev, MapMemPage, ret); + goto exit3; + } - if (ret != 0) { - cs_error(link, MapMemPage, ret); - goto exit1; - } + ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, + ipw->request_attr_memory.Size); + request_mem_region(ipw->request_attr_memory.Base, + ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME); - ipw->is_v2_card = - parse.cftable_entry.mem.win[0].len == 0x100; + return 0; - ipw->common_memory = ioremap(ipw->request_common_memory.Base, +exit3: + pcmcia_release_window(ipw->handle_attr_memory); +exit2: + if (ipw->common_memory) { + release_mem_region(ipw->request_common_memory.Base, ipw->request_common_memory.Size); - request_mem_region(ipw->request_common_memory.Base, - ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME); - - ipw->request_attr_memory.Attributes = - WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; - ipw->request_attr_memory.Base = 0; - ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ - ipw->request_attr_memory.AccessSpeed = 0; - - ret = pcmcia_request_window(&link, &ipw->request_attr_memory, - &ipw->handle_attr_memory); + iounmap(ipw->common_memory); + pcmcia_release_window(ipw->handle_common_memory); + } else + pcmcia_release_window(ipw->handle_common_memory); +exit1: + release_resource(io_resource); + pcmcia_disable_device(p_dev); + return -1; +} - if (ret != 0) { - cs_error(link, RequestWindow, ret); - goto exit2; - } +static int config_ipwireless(struct ipw_dev *ipw) +{ + struct pcmcia_device *link = ipw->link; + int ret = 0; - memreq_attr_memory.CardOffset = 0; - memreq_attr_memory.Page = 0; + ipw->is_v2_card = 0; - ret = pcmcia_map_mem_page(ipw->handle_attr_memory, - &memreq_attr_memory); + ret = pcmcia_loop_config(link, ipwireless_probe, ipw); + if (ret != 0) { + cs_error(link, RequestIO, ret); + return ret; + } - if (ret != 0) { - cs_error(link, MapMemPage, ret); - goto exit2; - } + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.IntType = INT_MEMORY_AND_IO; - ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, - ipw->request_attr_memory.Size); - request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size, - IPWIRELESS_PCCARD_NAME); - } + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; + link->irq.Handler = ipwireless_interrupt; + link->irq.Instance = ipw->hardware; INIT_WORK(&ipw->work_reboot, signalled_reboot_work); @@ -234,7 +225,7 @@ static int config_ipwireless(struct ipw_dev *ipw) if (ret != 0) { cs_error(link, RequestIRQ, ret); - goto exit3; + goto exit; } printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", @@ -257,12 +248,12 @@ static int config_ipwireless(struct ipw_dev *ipw) ipw->network = ipwireless_network_create(ipw->hardware); if (!ipw->network) - goto exit3; + goto exit; ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network, ipw->nodes); if (!ipw->tty) - goto exit3; + goto exit; ipwireless_init_hardware_v2_v3(ipw->hardware); @@ -274,33 +265,27 @@ static int config_ipwireless(struct ipw_dev *ipw) if (ret != 0) { cs_error(link, RequestConfiguration, ret); - goto exit4; + goto exit; } link->dev_node = &ipw->nodes[0]; return 0; -exit4: - pcmcia_disable_device(link); -exit3: +exit: if (ipw->attr_memory) { release_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size); iounmap(ipw->attr_memory); pcmcia_release_window(ipw->handle_attr_memory); - pcmcia_disable_device(link); } -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(ipw->handle_common_memory); } -exit1: pcmcia_disable_device(link); -exit0: return -1; } -- cgit v1.2.3 From 91284224da5b15ec6c2b45e10fa5eccd1c92a204 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 18 Oct 2009 23:32:33 +0200 Subject: pcmcia: add new CIS access helpers As a replacement to pcmcia_get_{first,next}_tuple() and pcmcia_get_tuple_data(), three new -- and easier to use -- functions are added: - pcmcia_get_tuple() to get the very first CIS entry of one type. - pcmcia_loop_tuple() to loop over all CIS entries of one type. - pcmcia_get_mac_from_cis() to read out the hardware MAC address from CISTPL_FUNCE. Only a handful of drivers need these functions anyway, as most CIS access is already handled by pcmcia_loop_config(), which now shares the same backed (pccard_loop_tuple()) with pcmcia_loop_tuple(). A pcmcia_get_mac_from_cis() bug noted by Komuro has been fixed in this revision. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cistpl.c | 61 +++++++++++ drivers/pcmcia/cs_internal.h | 7 ++ drivers/pcmcia/pcmcia_resource.c | 217 +++++++++++++++++++++++++++++++++------ drivers/pcmcia/rsrc_mgr.c | 1 + 4 files changed, 254 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 6c4a4fc83630..24dd3c1eac0b 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -1482,6 +1482,67 @@ done: } EXPORT_SYMBOL(pccard_read_tuple); + +/** + * pccard_loop_tuple() - loop over tuples in the CIS + * @s: the struct pcmcia_socket where the card is inserted + * @function: the device function we loop for + * @code: which CIS code shall we look for? + * @parse: buffer where the tuple shall be parsed (or NULL, if no parse) + * @priv_data: private data to be passed to the loop_tuple function. + * @loop_tuple: function to call for each CIS entry of type @function. IT + * gets passed the raw tuple, the paresed tuple (if @parse is + * set) and @priv_data. + * + * pccard_loop_tuple() loops over all CIS entries of type @function, and + * calls the @loop_tuple function for each entry. If the call to @loop_tuple + * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. + */ +int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, + cisdata_t code, cisparse_t *parse, void *priv_data, + int (*loop_tuple) (tuple_t *tuple, + cisparse_t *parse, + void *priv_data)) +{ + tuple_t tuple; + cisdata_t *buf; + int ret; + + buf = kzalloc(256, GFP_KERNEL); + if (buf == NULL) { + dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n"); + return -ENOMEM; + } + + tuple.TupleData = buf; + tuple.TupleDataMax = 255; + tuple.TupleOffset = 0; + tuple.DesiredTuple = code; + tuple.Attributes = 0; + + ret = pccard_get_first_tuple(s, function, &tuple); + while (!ret) { + if (pccard_get_tuple_data(s, &tuple)) + goto next_entry; + + if (parse) + if (pcmcia_parse_tuple(&tuple, parse)) + goto next_entry; + + ret = loop_tuple(&tuple, parse, priv_data); + if (!ret) + break; + +next_entry: + ret = pccard_get_next_tuple(s, function, &tuple); + } + + kfree(buf); + return ret; +} +EXPORT_SYMBOL(pccard_loop_tuple); + + /*====================================================================== This tries to determine if a card has a sensible CIS. It returns diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 1f4098f1354d..06a14c951e92 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -199,6 +199,13 @@ int pcmcia_replace_cis(struct pcmcia_socket *s, const u8 *data, const size_t len); int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *count); +/* loop over CIS entries */ +int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, + cisdata_t code, cisparse_t *parse, void *priv_data, + int (*loop_tuple) (tuple_t *tuple, + cisparse_t *parse, + void *priv_data)); + /* rsrc_mgr.c */ int pcmcia_validate_mem(struct pcmcia_socket *s); struct resource *pcmcia_find_io_region(unsigned long base, diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index d919e96c0afd..0bfb05aa8f85 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -885,12 +886,39 @@ EXPORT_SYMBOL(pcmcia_disable_device); struct pcmcia_cfg_mem { - tuple_t tuple; + struct pcmcia_device *p_dev; + void *priv_data; + int (*conf_check) (struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cfg, + cistpl_cftable_entry_t *dflt, + unsigned int vcc, + void *priv_data); cisparse_t parse; - u8 buf[256]; cistpl_cftable_entry_t dflt; }; +/** + * pcmcia_do_loop_config() - internal helper for pcmcia_loop_config() + * + * pcmcia_do_loop_config() is the internal callback for the call from + * pcmcia_loop_config() to pccard_loop_tuple(). Data is transferred + * by a struct pcmcia_cfg_mem. + */ +static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv) +{ + cistpl_cftable_entry_t *cfg = &parse->cftable_entry; + struct pcmcia_cfg_mem *cfg_mem = priv; + + /* default values */ + cfg_mem->p_dev->conf.ConfigIndex = cfg->index; + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) + cfg_mem->dflt = *cfg; + + return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt, + cfg_mem->p_dev->socket->socket.Vcc, + cfg_mem->priv_data); +} + /** * pcmcia_loop_config() - loop over configuration options * @p_dev: the struct pcmcia_device which we need to loop for. @@ -913,48 +941,173 @@ int pcmcia_loop_config(struct pcmcia_device *p_dev, void *priv_data) { struct pcmcia_cfg_mem *cfg_mem; - - tuple_t *tuple; int ret; - unsigned int vcc; cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL); if (cfg_mem == NULL) return -ENOMEM; - /* get the current Vcc setting */ - vcc = p_dev->socket->socket.Vcc; + cfg_mem->p_dev = p_dev; + cfg_mem->conf_check = conf_check; + cfg_mem->priv_data = priv_data; - tuple = &cfg_mem->tuple; - tuple->TupleData = cfg_mem->buf; - tuple->TupleDataMax = 255; - tuple->TupleOffset = 0; - tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; - tuple->Attributes = 0; + ret = pccard_loop_tuple(p_dev->socket, p_dev->func, + CISTPL_CFTABLE_ENTRY, &cfg_mem->parse, + cfg_mem, pcmcia_do_loop_config); - ret = pcmcia_get_first_tuple(p_dev, tuple); - while (!ret) { - cistpl_cftable_entry_t *cfg = &cfg_mem->parse.cftable_entry; + kfree(cfg_mem); + return ret; +} +EXPORT_SYMBOL(pcmcia_loop_config); - if (pcmcia_get_tuple_data(p_dev, tuple)) - goto next_entry; - if (pcmcia_parse_tuple(tuple, &cfg_mem->parse)) - goto next_entry; +struct pcmcia_loop_mem { + struct pcmcia_device *p_dev; + void *priv_data; + int (*loop_tuple) (struct pcmcia_device *p_dev, + tuple_t *tuple, + void *priv_data); +}; - /* default values */ - p_dev->conf.ConfigIndex = cfg->index; - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) - cfg_mem->dflt = *cfg; +/** + * pcmcia_do_loop_tuple() - internal helper for pcmcia_loop_config() + * + * pcmcia_do_loop_tuple() is the internal callback for the call from + * pcmcia_loop_tuple() to pccard_loop_tuple(). Data is transferred + * by a struct pcmcia_cfg_mem. + */ +static int pcmcia_do_loop_tuple(tuple_t *tuple, cisparse_t *parse, void *priv) +{ + struct pcmcia_loop_mem *loop = priv; - ret = conf_check(p_dev, cfg, &cfg_mem->dflt, vcc, priv_data); - if (!ret) - break; + return loop->loop_tuple(loop->p_dev, tuple, loop->priv_data); +}; + +/** + * pcmcia_loop_tuple() - loop over tuples in the CIS + * @p_dev: the struct pcmcia_device which we need to loop for. + * @code: which CIS code shall we look for? + * @priv_data: private data to be passed to the loop_tuple function. + * @loop_tuple: function to call for each CIS entry of type @function. IT + * gets passed the raw tuple and @priv_data. + * + * pcmcia_loop_tuple() loops over all CIS entries of type @function, and + * calls the @loop_tuple function for each entry. If the call to @loop_tuple + * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. + */ +int pcmcia_loop_tuple(struct pcmcia_device *p_dev, cisdata_t code, + int (*loop_tuple) (struct pcmcia_device *p_dev, + tuple_t *tuple, + void *priv_data), + void *priv_data) +{ + struct pcmcia_loop_mem loop = { + .p_dev = p_dev, + .loop_tuple = loop_tuple, + .priv_data = priv_data}; + + return pccard_loop_tuple(p_dev->socket, p_dev->func, code, NULL, + &loop, pcmcia_do_loop_tuple); +}; +EXPORT_SYMBOL(pcmcia_loop_tuple); -next_entry: - ret = pcmcia_get_next_tuple(p_dev, tuple); + +struct pcmcia_loop_get { + size_t len; + cisdata_t **buf; +}; + +/** + * pcmcia_do_get_tuple() - internal helper for pcmcia_get_tuple() + * + * pcmcia_do_get_tuple() is the internal callback for the call from + * pcmcia_get_tuple() to pcmcia_loop_tuple(). As we're only interested in + * the first tuple, return 0 unconditionally. Create a memory buffer large + * enough to hold the content of the tuple, and fill it with the tuple data. + * The caller is responsible to free the buffer. + */ +static int pcmcia_do_get_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, + void *priv) +{ + struct pcmcia_loop_get *get = priv; + + *get->buf = kzalloc(tuple->TupleDataLen, GFP_KERNEL); + if (*get->buf) { + get->len = tuple->TupleDataLen; + memcpy(*get->buf, tuple->TupleData, tuple->TupleDataLen); } + return 0; +}; + +/** + * pcmcia_get_tuple() - get first tuple from CIS + * @p_dev: the struct pcmcia_device which we need to loop for. + * @code: which CIS code shall we look for? + * @buf: pointer to store the buffer to. + * + * pcmcia_get_tuple() gets the content of the first CIS entry of type @code. + * It returns the buffer length (or zero). The caller is responsible to free + * the buffer passed in @buf. + */ +size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code, + unsigned char **buf) +{ + struct pcmcia_loop_get get = { + .len = 0, + .buf = buf, + }; + + *get.buf = NULL; + pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get); + + return get.len; +}; +EXPORT_SYMBOL(pcmcia_get_tuple); + + +/** + * pcmcia_do_get_mac() - internal helper for pcmcia_get_mac_from_cis() + * + * pcmcia_do_get_mac() is the internal callback for the call from + * pcmcia_get_mac_from_cis() to pcmcia_loop_tuple(). We check whether the + * tuple contains a proper LAN_NODE_ID of length 6, and copy the data + * to struct net_device->dev_addr[i]. + */ +static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple, + void *priv) +{ + struct net_device *dev = priv; + int i; + + if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID) + return -EINVAL; + if (tuple->TupleDataLen < ETH_ALEN + 2) { + dev_warn(&p_dev->dev, "Invalid CIS tuple length for " + "LAN_NODE_ID\n"); + return -EINVAL; + } + + if (tuple->TupleData[1] != ETH_ALEN) { + dev_warn(&p_dev->dev, "Invalid header for LAN_NODE_ID\n"); + return -EINVAL; + } + for (i = 0; i < 6; i++) + dev->dev_addr[i] = tuple->TupleData[i+2]; + return 0; +}; + +/** + * pcmcia_get_mac_from_cis() - read out MAC address from CISTPL_FUNCE + * @p_dev: the struct pcmcia_device for which we want the address. + * @dev: a properly prepared struct net_device to store the info to. + * + * pcmcia_get_mac_from_cis() reads out the hardware MAC address from + * CISTPL_FUNCE and stores it into struct net_device *dev->dev_addr which + * must be set up properly by the driver (see examples!). + */ +int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev) +{ + return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev); +}; +EXPORT_SYMBOL(pcmcia_get_mac_from_cis); - return ret; -} -EXPORT_SYMBOL(pcmcia_loop_config); diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index e592e0e0d7ed..de0e770ce6a3 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "cs_internal.h" -- cgit v1.2.3 From dddfbd824b96a25da0b2f1cf35c0be33ef2422fe Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 18 Oct 2009 23:54:24 +0200 Subject: pcmcia: convert net pcmcia drivers to use new CIS helpers Use the new CIS helpers in net pcmcia drivers, which allows for a few code cleanups. This revision does not remove the phys_addr assignment in 3c589_cs.c -- a bug noted by Komuro CC: David S. Miller CC: netdev@vger.kernel.org Signed-off-by: Dominik Brodowski --- drivers/net/pcmcia/3c574_cs.c | 18 ++- drivers/net/pcmcia/3c589_cs.c | 21 ++-- drivers/net/pcmcia/fmvj18x_cs.c | 50 ++++---- drivers/net/pcmcia/nmclan_cs.c | 19 ++-- drivers/net/pcmcia/smc91c92_cs.c | 238 +++++++++++---------------------------- drivers/net/pcmcia/xirc2ps_cs.c | 147 ++++++++++-------------- 6 files changed, 171 insertions(+), 322 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index b58965a2b3ae..6449290c62ff 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -344,13 +344,13 @@ static int tc574_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); - tuple_t tuple; - __le16 buf[32]; int last_fn, last_ret, i, j; unsigned int ioaddr; __be16 *phys_addr; char *cardname; __u32 config; + u8 *buf; + size_t len; phys_addr = (__be16 *)dev->dev_addr; @@ -378,16 +378,14 @@ static int tc574_config(struct pcmcia_device *link) /* The 3c574 normally uses an EEPROM for configuration info, including the hardware address. The future products may include a modem chip and put the address in the CIS. */ - tuple.Attributes = 0; - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - tuple.DesiredTuple = 0x88; - if (pcmcia_get_first_tuple(link, &tuple) == 0) { - pcmcia_get_tuple_data(link, &tuple); + + len = pcmcia_get_tuple(link, 0x88, &buf); + if (buf && len >= 6) { for (i = 0; i < 3; i++) - phys_addr[i] = htons(le16_to_cpu(buf[i])); + phys_addr[i] = htons(le16_to_cpu(buf[i * 2])); + kfree(buf); } else { + kfree(buf); /* 0 < len < 6 */ EL3WINDOW(0); for (i = 0; i < 3; i++) phys_addr[i] = htons(read_eeprom(ioaddr, i + 10)); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 569fb06793cf..fc6123ea6fa7 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -256,22 +256,16 @@ static int tc589_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); - tuple_t tuple; - __le16 buf[32]; __be16 *phys_addr; int last_fn, last_ret, i, j, multi = 0, fifo; unsigned int ioaddr; char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; + u8 *buf; + size_t len; DEBUG(0, "3c589_config(0x%p)\n", link); phys_addr = (__be16 *)dev->dev_addr; - tuple.Attributes = 0; - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - tuple.Attributes = TUPLE_RETURN_COMMON; - /* Is this a 3c562? */ if (link->manf_id != MANFID_3COM) printk(KERN_INFO "3c589_cs: hmmm, is this really a " @@ -301,12 +295,13 @@ static int tc589_config(struct pcmcia_device *link) /* The 3c589 has an extra EEPROM for configuration info, including the hardware address. The 3c562 puts the address in the CIS. */ - tuple.DesiredTuple = 0x88; - if (pcmcia_get_first_tuple(link, &tuple) == 0) { - pcmcia_get_tuple_data(link, &tuple); - for (i = 0; i < 3; i++) - phys_addr[i] = htons(le16_to_cpu(buf[i])); + len = pcmcia_get_tuple(link, 0x88, &buf); + if (buf && len >= 6) { + for (i = 0; i < 3; i++) + phys_addr[i] = htons(le16_to_cpu(buf[i*2])); + kfree(buf); } else { + kfree(buf); /* 0 < len < 6 */ for (i = 0; i < 3; i++) phys_addr[i] = htons(read_eeprom(ioaddr, i)); if (phys_addr[0] == htons(0x6060)) { diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index c7a2bbfaf821..5b73b11411c8 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -350,32 +350,29 @@ static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, return 0; /* strange, but that's what the code did already before... */ } - static int fmvj18x_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; local_info_t *lp = netdev_priv(dev); - tuple_t tuple; - u_short buf[32]; int i, last_fn = RequestIO, last_ret = 0, ret; unsigned int ioaddr; cardtype_t cardtype; char *card_name = "unknown"; - u_char *node_id; + u8 *buf; + size_t len; + u_char buggybuf[32]; DEBUG(0, "fmvj18x_config(0x%p)\n", link); - tuple.TupleData = (u_char *)buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_FUNCE; - tuple.TupleOffset = 0; - if (pcmcia_get_first_tuple(link, &tuple) == 0) { + len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf); + kfree(buf); + + if (len) { + /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ last_ret = pcmcia_loop_config(link, fmvj18x_ioprobe, NULL); if (last_ret != 0) goto cs_failed; - /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ switch (link->manf_id) { case MANFID_TDK: cardtype = TDK; @@ -482,21 +479,21 @@ static int fmvj18x_config(struct pcmcia_device *link) case CONTEC: case NEC: case KME: - tuple.DesiredTuple = CISTPL_FUNCE; - tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); if (cardtype == MBH10304) { - /* MBH10304's CIS_FUNCE is corrupted */ - node_id = &(tuple.TupleData[5]); card_name = "FMV-J182"; - } else { - while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) { - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + + len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf); + if (len < 11) { + kfree(buf); + goto failed; } - node_id = &(tuple.TupleData[2]); + /* Read MACID from CIS */ + for (i = 5; i < 11; i++) + dev->dev_addr[i] = buf[i]; + kfree(buf); + } else { + if (pcmcia_get_mac_from_cis(link, dev)) + goto failed; if( cardtype == TDK ) { card_name = "TDK LAK-CD021"; } else if( cardtype == LA501 ) { @@ -509,9 +506,6 @@ static int fmvj18x_config(struct pcmcia_device *link) card_name = "C-NET(PC)C"; } } - /* Read MACID from CIS */ - for (i = 0; i < 6; i++) - dev->dev_addr[i] = node_id[i]; break; case UNGERMANN: /* Read MACID from register */ @@ -521,12 +515,12 @@ static int fmvj18x_config(struct pcmcia_device *link) break; case XXX10304: /* Read MACID from Buggy CIS */ - if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) { + if (fmvj18x_get_hwinfo(link, buggybuf) == -1) { printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n"); goto failed; } for (i = 0 ; i < 6; i++) { - dev->dev_addr[i] = tuple.TupleData[i]; + dev->dev_addr[i] = buggybuf[i]; } card_name = "FMV-J182"; break; diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 5ed6339c52bc..4b96b356d979 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -661,8 +661,8 @@ static int nmclan_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; mace_private *lp = netdev_priv(dev); - tuple_t tuple; - u_char buf[64]; + u8 *buf; + size_t len; int i, last_ret, last_fn; unsigned int ioaddr; @@ -677,14 +677,13 @@ static int nmclan_config(struct pcmcia_device *link) ioaddr = dev->base_addr; /* Read the ethernet address from the CIS. */ - tuple.DesiredTuple = 0x80 /* CISTPL_CFTABLE_ENTRY_MISC */; - tuple.TupleData = buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - tuple.Attributes = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN); + len = pcmcia_get_tuple(link, 0x80, &buf); + if (!buf || len < ETHER_ADDR_LEN) { + kfree(buf); + goto failed; + } + memcpy(dev->dev_addr, buf, ETHER_ADDR_LEN); + kfree(buf); /* Verify configuration by reading the MACE ID. */ { diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index af03759d186d..df92bcde9bcf 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -126,12 +126,6 @@ struct smc_private { int rx_ovrn; }; -struct smc_cfg_mem { - tuple_t tuple; - cisparse_t parse; - u_char buf[255]; -}; - /* Special definitions for Megahertz multifunction cards */ #define MEGAHERTZ_ISR 0x0380 @@ -408,34 +402,7 @@ static int cvt_ascii_address(struct net_device *dev, char *s) return 0; } -/*====================================================================*/ - -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, - cisparse_t *parse) -{ - int i; - - i = pcmcia_get_first_tuple(handle, tuple); - if (i != 0) - return i; - i = pcmcia_get_tuple_data(handle, tuple); - if (i != 0) - return i; - return pcmcia_parse_tuple(tuple, parse); -} - -static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, - cisparse_t *parse) -{ - int i; - - if ((i = pcmcia_get_next_tuple(handle, tuple)) != 0 || - (i = pcmcia_get_tuple_data(handle, tuple)) != 0) - return i; - return pcmcia_parse_tuple(tuple, parse); -} - -/*====================================================================== +/*==================================================================== Configuration stuff for Megahertz cards @@ -49