netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper
@ 2008-07-29  7:15 Dominik Brodowski
  2008-07-29  7:21 ` [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers Dominik Brodowski
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Dominik Brodowski @ 2008-07-29  7:15 UTC (permalink / raw)
  To: linux-pcmcia
  Cc: Tejun Heo, Alan Cox, linux-ide, Marcel Holtmann, linux-bluetooth,
	James E.J. Bottomley, linux-scsi, Karsten Keil, isdn4linux,
	Jeff Garzik, netdev, Harald Welte, linux-parport, Russell King,
	Ed Okerson, linux-serial

By calling pcmcia_loop_config(), a pcmcia driver can iterate over all
available configuration options. During a driver's probe() phase, one
doesn't need to use pcmcia_get_{first,next}_tuple, pcmcia_get_tuple_data
and pcmcia_parse_tuple directly in most if not all cases.

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
---
 Documentation/pcmcia/driver-changes.txt |    6 +++
 drivers/pcmcia/pcmcia_resource.c        |   57 +++++++++++++++++++++++++++++++
 include/pcmcia/cistpl.h                 |    6 +++
 3 files changed, 69 insertions(+), 0 deletions(-)

By calling pcmcia_loop_config(), a pcmcia driver can iterate over all
available configuration options. During a driver's probe() phase, one
doesn't need to use pcmcia_get_{first,next}_tuple, pcmcia_get_tuple_data
and pcmcia_parse_tuple directly in most if not all cases.

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
---
 Documentation/pcmcia/driver-changes.txt |    6 +++
 drivers/pcmcia/pcmcia_resource.c        |   63 +++++++++++++++++++++++++++++++
 include/pcmcia/cistpl.h                 |    6 +++
 3 files changed, 75 insertions(+), 0 deletions(-)

diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 96f155e..44085c1 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,5 +1,11 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
 
+* New configuration loop helper (as of 2.6.28)
+   By calling pcmcia_loop_config(), a driver can iterate over all available
+   configuration options. During a driver's probe() phase, one doesn't need
+   to use pcmcia_get_{first,next}_tuple, pcmcia_get_tuple_data and
+   pcmcia_parse_tuple directly in most if not all cases.  
+
 * New release helper (as of 2.6.17)
    Instead of calling pcmcia_release_{configuration,io,irq,win}, all that's
    necessary now is calling pcmcia_disable_device. As there is no valid
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 4884a18..0fa48aa 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -909,3 +909,66 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) {
 		pcmcia_release_window(p_dev->win);
 }
 EXPORT_SYMBOL(pcmcia_disable_device);
+
+
+/**
+ * pcmcia_loop_config() - loop over configuration options
+ * @p_dev:	the struct pcmcia_device which we need to loop for.
+ * @conf_check:	function to call for each configuration option.
+ *		It gets passed the struct pcmcia_device, the CIS data
+ *		describing the configuration option, and private data
+ *		being passed to pcmcia_loop_config()
+ * @priv_data:	private data to be passed to the conf_check function.
+ *
+ * pcmcia_loop_config() loops over all configuration options, and calls
+ * the driver-specific conf_check() for each one, checking whether
+ * it is a valid one.
+ */
+
+struct pcmcia_cfg_mem {
+	tuple_t tuple;
+	cisparse_t parse;
+	u8 buf[256];
+};
+
+int pcmcia_loop_config(struct pcmcia_device *p_dev,
+		       int	(*conf_check)	(struct pcmcia_device *p_dev,
+						 cistpl_cftable_entry_t *cfg,
+						 void *priv_data),
+		       void *priv_data)
+{
+	struct pcmcia_cfg_mem *cfg_mem;
+	tuple_t *tuple;
+	int ret = -ENODEV;
+
+	cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL);
+	if (cfg_mem == NULL)
+		return -ENOMEM;
+
+	tuple = &cfg_mem->tuple;
+	tuple->TupleData = cfg_mem->buf;
+	tuple->TupleDataMax = 255;
+	tuple->TupleOffset = 0;
+	tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
+	tuple->Attributes = 0;
+
+	ret = pcmcia_get_first_tuple(p_dev, tuple);
+	while (!ret) {
+		if (pcmcia_get_tuple_data(p_dev, tuple))
+			goto next_entry;
+
+		if (pcmcia_parse_tuple(p_dev, tuple, &cfg_mem->parse))
+			goto next_entry;
+
+		ret = conf_check(p_dev, &cfg_mem->parse.cftable_entry,
+				 priv_data);
+		if (!ret)
+			break;
+
+	next_entry:
+		ret = pcmcia_get_next_tuple(p_dev, tuple);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(pcmcia_loop_config);
diff --git a/include/pcmcia/cistpl.h b/include/pcmcia/cistpl.h
index 552a332..9830b34 100644
--- a/include/pcmcia/cistpl.h
+++ b/include/pcmcia/cistpl.h
@@ -607,4 +607,10 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned
 #define pcmcia_validate_cis(p_dev, info) \
 		pccard_validate_cis(p_dev->socket, p_dev->func, info)
 
+int pcmcia_loop_config(struct pcmcia_device *p_dev,
+		       int	(*conf_check)	(struct pcmcia_device *p_dev,
+						 cistpl_cftable_entry_t *cf,
+						 void *priv_data),
+		       void *priv_data);
+
 #endif /* LINUX_CISTPL_H */
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers
  2008-07-29  7:15 [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper Dominik Brodowski
@ 2008-07-29  7:21 ` Dominik Brodowski
  2008-07-29 20:21   ` Larry Finger
       [not found] ` <20080729072025.GH27385@comet.dominikbrodowski.net>
  2008-07-29 21:16 ` [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper Randy Dunlap
  2 siblings, 1 reply; 5+ messages in thread
From: Dominik Brodowski @ 2008-07-29  7:21 UTC (permalink / raw)
  To: linux-pcmcia; +Cc: Jeff Garzik, netdev

Use the config loop helper in (some) net pcmcia drivers.

CC: Jeff Garzik <jgarzik@pobox.com>
CC: <netdev@vger.kernel.org>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
---
 drivers/net/pcmcia/axnet_cs.c    |   71 ++++++++++++++-------------------
 drivers/net/pcmcia/pcnet_cs.c    |   79 ++++++++++++++++++--------------------
 drivers/net/pcmcia/smc91c92_cs.c |   46 ++++++----------------
 3 files changed, 80 insertions(+), 116 deletions(-)

diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 3f682d4..04ece0b 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -284,58 +284,47 @@ static int try_io_port(struct pcmcia_device *link)
     }
 }
 
+static int axnet_configcheck(struct pcmcia_device *p_dev,
+			     cistpl_cftable_entry_t *cfg,
+			     void *priv_data)
+{
+	int i;
+	cistpl_io_t *io = &cfg->io;
+
+	if (cfg->index == 0 || cfg->io.nwin == 0)
+		return -ENODEV;
+
+	p_dev->conf.ConfigIndex = 0x05;
+	/* For multifunction cards, by convention, we configure the
+	   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;
+	} else {
+		i = p_dev->io.NumPorts2 = 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)
+		return try_io_port(p_dev);
+
+	return -ENODEV;
+}
+
 static int axnet_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     axnet_dev_t *info = PRIV(dev);
-    tuple_t tuple;
-    cisparse_t parse;
     int i, j, last_ret, last_fn;
-    u_short buf[64];
     DECLARE_MAC_BUF(mac);
 
     DEBUG(0, "axnet_config(0x%p)\n", link);
 
-    tuple.Attributes = 0;
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleDataMax = sizeof(buf);
-    tuple.TupleOffset = 0;
-
     /* don't trust the CIS on this; Linksys got it wrong */
     link->conf.Present = 0x63;
-
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-    while (last_ret == CS_SUCCESS) {
-	cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-	cistpl_io_t *io = &(parse.cftable_entry.io);
-	
-	if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-		pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
-		cfg->index == 0 || cfg->io.nwin == 0)
-	    goto next_entry;
-	
-	link->conf.ConfigIndex = 0x05;
-	/* For multifunction cards, by convention, we configure the
-	   network function with window 0, and serial with window 1 */
-	if (io->nwin > 1) {
-	    i = (io->win[1].len > io->win[0].len);
-	    link->io.BasePort2 = io->win[1-i].base;
-	    link->io.NumPorts2 = io->win[1-i].len;
-	} else {
-	    i = link->io.NumPorts2 = 0;
-	}
-	link->io.BasePort1 = io->win[i].base;
-	link->io.NumPorts1 = io->win[i].len;
-	link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-	if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
-	    last_ret = try_io_port(link);
-	    if (last_ret == CS_SUCCESS) break;
-	}
-    next_entry:
-	last_ret = pcmcia_get_next_tuple(link, &tuple);
-    }
+    last_ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
     if (last_ret != CS_SUCCESS) {
 	cs_error(link, RequestIO, last_ret);
 	goto failed;
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 2d4c4ad..7a9eeca 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -512,58 +512,53 @@ static int try_io_port(struct pcmcia_device *link)
     }
 }
 
+static int pcnet_confcheck(struct pcmcia_device *p_dev,
+			   cistpl_cftable_entry_t *cfg,
+			   void *priv_data)
+{
+	int *has_shmem = priv_data;
+	int i;
+	cistpl_io_t *io = &cfg->io;
+
+	if (cfg->index == 0 || cfg->io.nwin == 0)
+		return -EINVAL;
+
+	p_dev->conf.ConfigIndex = cfg->index;
+
+	/* For multifunction cards, by convention, we configure the
+	   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;
+	} else {
+		i = p_dev->io.NumPorts2 = 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)
+		return try_io_port(p_dev);
+
+	return 0;
+}
+
 static int pcnet_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     pcnet_dev_t *info = PRIV(dev);
-    tuple_t tuple;
-    cisparse_t parse;
-    int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
+    int last_ret, last_fn, start_pg, stop_pg, cm_offset;
     int has_shmem = 0;
-    u_short buf[64];
     hw_info_t *local_hw_info;
     DECLARE_MAC_BUF(mac);
 
     DEBUG(0, "pcnet_config(0x%p)\n", link);
 
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleDataMax = sizeof(buf);
-    tuple.TupleOffset = 0;
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    tuple.Attributes = 0;
-    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-    while (last_ret == CS_SUCCESS) {
-	cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-	cistpl_io_t *io = &(parse.cftable_entry.io);
-
-	if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
-			pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
-			cfg->index == 0 || cfg->io.nwin == 0)
-		goto next_entry;
-
-	link->conf.ConfigIndex = cfg->index;
-	/* For multifunction cards, by convention, we configure the
-	   network function with window 0, and serial with window 1 */
-	if (io->nwin > 1) {
-	    i = (io->win[1].len > io->win[0].len);
-	    link->io.BasePort2 = io->win[1-i].base;
-	    link->io.NumPorts2 = io->win[1-i].len;
-	} else {
-	    i = link->io.NumPorts2 = 0;
-	}
-	has_shmem = ((cfg->mem.nwin == 1) &&
-		     (cfg->mem.win[0].len >= 0x4000));
-	link->io.BasePort1 = io->win[i].base;
-	link->io.NumPorts1 = io->win[i].len;
-	link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-	if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
-	    last_ret = try_io_port(link);
-	    if (last_ret == CS_SUCCESS) break;
-	}
-    next_entry:
-	last_ret = pcmcia_get_next_tuple(link, &tuple);
-    }
-    if (last_ret != CS_SUCCESS) {
+    last_ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem);
+    if (last_ret) {
 	cs_error(link, RequestIO, last_ret);
 	goto failed;
     }
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 250eb19..9edd2d6 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -660,46 +660,26 @@ static int mot_setup(struct pcmcia_device *link)
 
 /*====================================================================*/
 
+static int smc_configcheck(struct pcmcia_device *p_dev,
+			   cistpl_cftable_entry_t *cf,
+			   void *priv_data)
+{
+	p_dev->conf.ConfigIndex = cf->index;
+	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);
+}
+
 static int smc_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
-    struct smc_cfg_mem *cfg_mem;
-    tuple_t *tuple;
-    cisparse_t *parse;
-    cistpl_cftable_entry_t *cf;
-    u_char *buf;
     int i;
 
-    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
-    if (!cfg_mem)
-	return CS_OUT_OF_RESOURCE;
-
-    tuple = &cfg_mem->tuple;
-    parse = &cfg_mem->parse;
-    cf = &parse->cftable_entry;
-    buf = cfg_mem->buf;
-
-    tuple->Attributes = tuple->TupleOffset = 0;
-    tuple->TupleData = (cisdata_t *)buf;
-    tuple->TupleDataMax = 255;
-    tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
     link->io.NumPorts1 = 16;
-    i = first_tuple(link, tuple, parse);
-    while (i != CS_NO_MORE_ITEMS) {
-	if (i == CS_SUCCESS) {
-	    link->conf.ConfigIndex = cf->index;
-	    link->io.BasePort1 = cf->io.win[0].base;
-	    link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-	    i = pcmcia_request_io(link, &link->io);
-	    if (i == CS_SUCCESS) break;
-	}
-	i = next_tuple(link, tuple, parse);
-    }
-    if (i == CS_SUCCESS)
-	dev->base_addr = link->io.BasePort1;
+    i = pcmcia_loop_config(link, smc_configcheck, NULL);
+    if (!i)
+	    dev->base_addr = link->io.BasePort1;
 
-    kfree(cfg_mem);
     return i;
 }
 
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC] [PATCH 5/7] pcmcia: use pcmcia_loop_config in ISDN pcmcia drivers
       [not found] ` <20080729072025.GH27385@comet.dominikbrodowski.net>
@ 2008-07-29 15:45   ` Karsten Keil
  0 siblings, 0 replies; 5+ messages in thread
From: Karsten Keil @ 2008-07-29 15:45 UTC (permalink / raw)
  To: Dominik Brodowski; +Cc: linux-pcmcia, isdn4linux, netdev

On Tue, Jul 29, 2008 at 09:20:25AM +0200, Dominik Brodowski wrote:
> Use the config loop helper in ISDN pcmcia drivers.
> 

Acked-by: Karsten Keil <kkeil@suse.de>

> CC: isdn4linux@listserv.isdn4linux.de
> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
> ---
>  drivers/isdn/hardware/avm/avm_cs.c |   80 ++++++++++-------------------------
>  drivers/isdn/hisax/avma1_cs.c      |   76 +++++++++-------------------------
>  drivers/isdn/hisax/elsa_cs.c       |   71 ++++++++++----------------------
>  drivers/isdn/hisax/teles_cs.c      |   71 ++++++++++----------------------
>  4 files changed, 87 insertions(+), 211 deletions(-)
> 
> diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
> index a5b941c..7a1ead1 100644
> --- a/drivers/isdn/hardware/avm/avm_cs.c
> +++ b/drivers/isdn/hardware/avm/avm_cs.c
> @@ -154,78 +154,44 @@ static void avmcs_detach(struct pcmcia_device *link)
>      
>  ======================================================================*/
>  
> -static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -		     cisparse_t *parse)
> +static int avmcs_configcheck(struct pcmcia_device *p_dev,
> +			     cistpl_cftable_entry_t *cf,
> +			     void *priv_data)
>  {
> -    int i = pcmcia_get_tuple_data(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return pcmcia_parse_tuple(handle, tuple, parse);
> -}
> -
> -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -		     cisparse_t *parse)
> -{
> -    int i = pcmcia_get_first_tuple(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return get_tuple(handle, tuple, parse);
> -}
> -
> -static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -		     cisparse_t *parse)
> -{
> -    int i = pcmcia_get_next_tuple(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return get_tuple(handle, tuple, parse);
> +	if (cf->io.nwin <= 0)
> +		return -ENODEV;
> +
> +	p_dev->conf.ConfigIndex = cf->index;
> +	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);
>  }
>  
>  static int avmcs_config(struct pcmcia_device *link)
>  {
> -    tuple_t tuple;
> -    cisparse_t parse;
> -    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
>      local_info_t *dev;
>      int i;
> -    u_char buf[64];
>      char devname[128];
>      int cardtype;
>      int (*addcard)(unsigned int port, unsigned irq);
>  
>      dev = link->priv;
>  
> -    do {
> -	devname[0] = 0;
> -	if (link->prod_id[1])
> -		strlcpy(devname, link->prod_id[1], sizeof(devname));
> -
> -	/*
> -         * find IO port
> -         */
> -	tuple.TupleData = (cisdata_t *)buf;
> -	tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
> -	tuple.Attributes = 0;
> -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
> -	i = first_tuple(link, &tuple, &parse);
> -	while (i == CS_SUCCESS) {
> -	    if (cf->io.nwin > 0) {
> -		link->conf.ConfigIndex = cf->index;
> -		link->io.BasePort1 = cf->io.win[0].base;
> -		link->io.NumPorts1 = cf->io.win[0].len;
> -		link->io.NumPorts2 = 0;
> -                printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
> -			link->io.BasePort1,
> -		        link->io.BasePort1+link->io.NumPorts1-1);
> -		i = pcmcia_request_io(link, &link->io);
> -		if (i == CS_SUCCESS) goto found_port;
> -	    }
> -	    i = next_tuple(link, &tuple, &parse);
> -	}
> +    devname[0] = 0;
> +    if (link->prod_id[1])
> +	    strlcpy(devname, link->prod_id[1], sizeof(devname));
>  
> -found_port:
> -	if (i != CS_SUCCESS) {
> -	    cs_error(link, RequestIO, i);
> -	    break;
> -	}
> +    /*
> +     * find IO port
> +     */
> +    if (pcmcia_loop_config(link, avmcs_configcheck, NULL))
> +	    return -ENODEV;
>  
> +    do {
>  	/*
>  	 * allocate an interrupt line
>  	 */
> diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
> index fc6cc2c..8142d9f 100644
> --- a/drivers/isdn/hisax/avma1_cs.c
> +++ b/drivers/isdn/hisax/avma1_cs.c
> @@ -174,38 +174,28 @@ static void avma1cs_detach(struct pcmcia_device *link)
>      
>  ======================================================================*/
>  
> -static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -		     cisparse_t *parse)
> +static int avma1cs_configcheck(struct pcmcia_device *p_dev,
> +			     cistpl_cftable_entry_t *cf,
> +			     void *priv_data)
>  {
> -    int i = pcmcia_get_tuple_data(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return pcmcia_parse_tuple(handle, tuple, parse);
> +	if (cf->io.nwin <= 0)
> +		return -ENODEV;
> +
> +	p_dev->conf.ConfigIndex = cf->index;
> +	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);
>  }
>  
> -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -		     cisparse_t *parse)
> -{
> -    int i = pcmcia_get_first_tuple(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return get_tuple(handle, tuple, parse);
> -}
> -
> -static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -		     cisparse_t *parse)
> -{
> -    int i = pcmcia_get_next_tuple(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return get_tuple(handle, tuple, parse);
> -}
>  
>  static int avma1cs_config(struct pcmcia_device *link)
>  {
> -    tuple_t tuple;
> -    cisparse_t parse;
> -    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
>      local_info_t *dev;
>      int i;
> -    u_char buf[64];
>      char devname[128];
>      IsdnCard_t	icard;
>      int busy = 0;
> @@ -214,40 +204,14 @@ static int avma1cs_config(struct pcmcia_device *link)
>  
>      DEBUG(0, "avma1cs_config(0x%p)\n", link);
>  
> -    do {
> -	devname[0] = 0;
> -	if (link->prod_id[1])
> -		strlcpy(devname, link->prod_id[1], sizeof(devname));
> +    devname[0] = 0;
> +    if (link->prod_id[1])
> +	    strlcpy(devname, link->prod_id[1], sizeof(devname));
>  
> -	/*
> -         * find IO port
> -         */
> -	tuple.TupleData = (cisdata_t *)buf;
> -	tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
> -	tuple.Attributes = 0;
> -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
> -	i = first_tuple(link, &tuple, &parse);
> -	while (i == CS_SUCCESS) {
> -	    if (cf->io.nwin > 0) {
> -		link->conf.ConfigIndex = cf->index;
> -		link->io.BasePort1 = cf->io.win[0].base;
> -		link->io.NumPorts1 = cf->io.win[0].len;
> -		link->io.NumPorts2 = 0;
> -		printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
> -			link->io.BasePort1,
> -			link->io.BasePort1+link->io.NumPorts1 - 1);
> -		i = pcmcia_request_io(link, &link->io);
> -		if (i == CS_SUCCESS) goto found_port;
> -	    }
> -	    i = next_tuple(link, &tuple, &parse);
> -	}
> +    if (pcmcia_loop_config(link, avma1cs_configcheck, NULL))
> +	    return -ENODEV;
>  
> -found_port:
> -	if (i != CS_SUCCESS) {
> -	    cs_error(link, RequestIO, i);
> -	    break;
> -	}
> -	
> +    do {
>  	/*
>  	 * allocate an interrupt line
>  	 */
> diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
> index db7e644..b85b07d 100644
> --- a/drivers/isdn/hisax/elsa_cs.c
> +++ b/drivers/isdn/hisax/elsa_cs.c
> @@ -203,68 +203,41 @@ static void elsa_cs_detach(struct pcmcia_device *link)
>      device available to the system.
>  
>  ======================================================================*/
> -static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -                     cisparse_t *parse)
> -{
> -    int i = pcmcia_get_tuple_data(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return pcmcia_parse_tuple(handle, tuple, parse);
> -}
>  
> -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -                     cisparse_t *parse)
> +static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
> +			       cistpl_cftable_entry_t *cf,
> +			       void *priv_data)
>  {
> -    int i = pcmcia_get_first_tuple(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return get_tuple(handle, tuple, parse);
> -}
> +	int j;
>  
> -static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -                     cisparse_t *parse)
> -{
> -    int i = pcmcia_get_next_tuple(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return get_tuple(handle, tuple, parse);
> +        if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
> +		printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
> +		p_dev->conf.ConfigIndex = cf->index;
> +		p_dev->io.BasePort1 = cf->io.win[0].base;
> +		if (!pcmcia_request_io(p_dev, &p_dev->io))
> +			return 0;
> +        } else {
> +		printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
> +		p_dev->conf.ConfigIndex = cf->index;
> +		for (j = 0x2f0; j > 0x100; j -= 0x10) {
> +			p_dev->io.BasePort1 = j;
> +			if (!pcmcia_request_io(p_dev, &p_dev->io))
> +				return 0;
> +		}
> +        }
> +	return -ENODEV;
>  }
>  
>  static int elsa_cs_config(struct pcmcia_device *link)
>  {
> -    tuple_t tuple;
> -    cisparse_t parse;
>      local_info_t *dev;
> -    int i, j, last_fn;
> -    u_short buf[128];
> -    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
> +    int i, last_fn;
>      IsdnCard_t icard;
>  
>      DEBUG(0, "elsa_config(0x%p)\n", link);
>      dev = link->priv;
>  
> -    tuple.TupleData = (cisdata_t *)buf;
> -    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
> -    tuple.Attributes = 0;
> -    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
> -    i = first_tuple(link, &tuple, &parse);
> -    while (i == CS_SUCCESS) {
> -        if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
> -            printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
> -            link->conf.ConfigIndex = cf->index;
> -            link->io.BasePort1 = cf->io.win[0].base;
> -            i = pcmcia_request_io(link, &link->io);
> -            if (i == CS_SUCCESS) break;
> -        } else {
> -          printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
> -          link->conf.ConfigIndex = cf->index;
> -          for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
> -            link->io.BasePort1 = j;
> -            i = pcmcia_request_io(link, &link->io);
> -            if (i == CS_SUCCESS) break;
> -          }
> -          break;
> -        }
> -        i = next_tuple(link, &tuple, &parse);
> -    }
> -
> +    i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL);
>      if (i != CS_SUCCESS) {
>  	last_fn = RequestIO;
>  	goto cs_failed;
> diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
> index ab4bd45..fc4d024 100644
> --- a/drivers/isdn/hisax/teles_cs.c
> +++ b/drivers/isdn/hisax/teles_cs.c
> @@ -193,68 +193,41 @@ static void teles_detach(struct pcmcia_device *link)
>      device available to the system.
>  
>  ======================================================================*/
> -static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -                     cisparse_t *parse)
> -{
> -    int i = pcmcia_get_tuple_data(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return pcmcia_parse_tuple(handle, tuple, parse);
> -}
>  
> -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -                     cisparse_t *parse)
> +static int teles_cs_configcheck(struct pcmcia_device *p_dev,
> +				cistpl_cftable_entry_t *cf,
> +				void *priv_data)
>  {
> -    int i = pcmcia_get_first_tuple(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return get_tuple(handle, tuple, parse);
> -}
> +	int j;
>  
> -static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
> -                     cisparse_t *parse)
> -{
> -    int i = pcmcia_get_next_tuple(handle, tuple);
> -    if (i != CS_SUCCESS) return i;
> -    return get_tuple(handle, tuple, parse);
> +        if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
> +		printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
> +		p_dev->conf.ConfigIndex = cf->index;
> +		p_dev->io.BasePort1 = cf->io.win[0].base;
> +		if (!pcmcia_request_io(p_dev, &p_dev->io))
> +			return 0;
> +        } else {
> +		printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
> +		p_dev->conf.ConfigIndex = cf->index;
> +		for (j = 0x2f0; j > 0x100; j -= 0x10) {
> +			p_dev->io.BasePort1 = j;
> +			if (!pcmcia_request_io(p_dev, &p_dev->io))
> +				return 0;
> +		}
> +        }
> +	return -ENODEV;
>  }
>  
>  static int teles_cs_config(struct pcmcia_device *link)
>  {
> -    tuple_t tuple;
> -    cisparse_t parse;
>      local_info_t *dev;
> -    int i, j, last_fn;
> -    u_short buf[128];
> -    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
> +    int i, last_fn;
>      IsdnCard_t icard;
>  
>      DEBUG(0, "teles_config(0x%p)\n", link);
>      dev = link->priv;
>  
> -    tuple.TupleData = (cisdata_t *)buf;
> -    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
> -    tuple.Attributes = 0;
> -    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
> -    i = first_tuple(link, &tuple, &parse);
> -    while (i == CS_SUCCESS) {
> -        if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
> -            printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
> -            link->conf.ConfigIndex = cf->index;
> -            link->io.BasePort1 = cf->io.win[0].base;
> -            i = pcmcia_request_io(link, &link->io);
> -            if (i == CS_SUCCESS) break;
> -        } else {
> -          printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
> -          link->conf.ConfigIndex = cf->index;
> -          for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
> -            link->io.BasePort1 = j;
> -            i = pcmcia_request_io(link, &link->io);
> -            if (i == CS_SUCCESS) break;
> -          }
> -          break;
> -        }
> -        i = next_tuple(link, &tuple, &parse);
> -    }
> -
> +    i = pcmcia_loop_config(link, teles_cs_configcheck, NULL);
>      if (i != CS_SUCCESS) {
>  	last_fn = RequestIO;
>  	goto cs_failed;
> -- 
> 1.5.4.3

-- 
Karsten Keil
SuSE Labs
ISDN and VOIP development
SUSE LINUX Products GmbH, Maxfeldstr.5 90409 Nuernberg, GF: Markus Rex, HRB 16746 (AG Nuernberg)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers
  2008-07-29  7:21 ` [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers Dominik Brodowski
@ 2008-07-29 20:21   ` Larry Finger
  0 siblings, 0 replies; 5+ messages in thread
From: Larry Finger @ 2008-07-29 20:21 UTC (permalink / raw)
  To: Dominik Brodowski; +Cc: linux-pcmcia, Jeff Garzik, netdev

Dominik Brodowski wrote:
> Use the config loop helper in (some) net pcmcia drivers.
> 
> CC: Jeff Garzik <jgarzik@pobox.com>
> CC: <netdev@vger.kernel.org>
> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
> ---
>  drivers/net/pcmcia/axnet_cs.c    |   71 ++++++++++++++-------------------
>  drivers/net/pcmcia/pcnet_cs.c    |   79 ++++++++++++++++++--------------------
>  drivers/net/pcmcia/smc91c92_cs.c |   46 ++++++----------------
>  3 files changed, 80 insertions(+), 116 deletions(-)

ACK for pcnet_cs.c by Larry Finger <Larry.Finger@lwfinger.net>.

Tested with 2.6.27-rc1.

Larry

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper
  2008-07-29  7:15 [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper Dominik Brodowski
  2008-07-29  7:21 ` [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers Dominik Brodowski
       [not found] ` <20080729072025.GH27385@comet.dominikbrodowski.net>
@ 2008-07-29 21:16 ` Randy Dunlap
  2 siblings, 0 replies; 5+ messages in thread
From: Randy Dunlap @ 2008-07-29 21:16 UTC (permalink / raw)
  To: Dominik Brodowski
  Cc: linux-pcmcia, Tejun Heo, Alan Cox, linux-ide, Marcel Holtmann,
	linux-bluetooth, James E.J. Bottomley, linux-scsi, Karsten Keil,
	isdn4linux, Jeff Garzik, netdev, Harald Welte, linux-parport,
	Russell King, Ed Okerson, linux-serial

On Tue, 29 Jul 2008 09:15:39 +0200 Dominik Brodowski wrote:

> By calling pcmcia_loop_config(), a pcmcia driver can iterate over all
> available configuration options. During a driver's probe() phase, one
> doesn't need to use pcmcia_get_{first,next}_tuple, pcmcia_get_tuple_data
> and pcmcia_parse_tuple directly in most if not all cases.
> 
> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
> ---
>  Documentation/pcmcia/driver-changes.txt |    6 +++
>  drivers/pcmcia/pcmcia_resource.c        |   57 +++++++++++++++++++++++++++++++
>  include/pcmcia/cistpl.h                 |    6 +++
>  3 files changed, 69 insertions(+), 0 deletions(-)
> 
> By calling pcmcia_loop_config(), a pcmcia driver can iterate over all
> available configuration options. During a driver's probe() phase, one
> doesn't need to use pcmcia_get_{first,next}_tuple, pcmcia_get_tuple_data
> and pcmcia_parse_tuple directly in most if not all cases.
> 
> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
> ---
>  Documentation/pcmcia/driver-changes.txt |    6 +++
>  drivers/pcmcia/pcmcia_resource.c        |   63 +++++++++++++++++++++++++++++++
>  include/pcmcia/cistpl.h                 |    6 +++
>  3 files changed, 75 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
> index 4884a18..0fa48aa 100644
> --- a/drivers/pcmcia/pcmcia_resource.c
> +++ b/drivers/pcmcia/pcmcia_resource.c
> @@ -909,3 +909,66 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) {
>  		pcmcia_release_window(p_dev->win);
>  }
>  EXPORT_SYMBOL(pcmcia_disable_device);
> +
> +

Hi,

One more comment here (sorry I missed it earlier):

The kernel-doc comment needs to immediately precede the function, so that
struct pcmcia_cfg_mem needs to be moved to before the kernel-doc block...


> +/**
> + * pcmcia_loop_config() - loop over configuration options
> + * @p_dev:	the struct pcmcia_device which we need to loop for.
> + * @conf_check:	function to call for each configuration option.
> + *		It gets passed the struct pcmcia_device, the CIS data
> + *		describing the configuration option, and private data
> + *		being passed to pcmcia_loop_config()
> + * @priv_data:	private data to be passed to the conf_check function.
> + *
> + * pcmcia_loop_config() loops over all configuration options, and calls
> + * the driver-specific conf_check() for each one, checking whether
> + * it is a valid one.
> + */
> +
> +struct pcmcia_cfg_mem {
> +	tuple_t tuple;
> +	cisparse_t parse;
> +	u8 buf[256];
> +};
> +
> +int pcmcia_loop_config(struct pcmcia_device *p_dev,
> +		       int	(*conf_check)	(struct pcmcia_device *p_dev,
> +						 cistpl_cftable_entry_t *cfg,
> +						 void *priv_data),
> +		       void *priv_data)
> +{
...
> +}
> +EXPORT_SYMBOL(pcmcia_loop_config);


---
~Randy
Linux Plumbers Conference, 17-19 September 2008, Portland, Oregon USA
http://linuxplumbersconf.org/

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-07-29 21:16 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-29  7:15 [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper Dominik Brodowski
2008-07-29  7:21 ` [RFC] [PATCH 6/7] pcmcia: use pcmcia_loop_config in net pcmcia drivers Dominik Brodowski
2008-07-29 20:21   ` Larry Finger
     [not found] ` <20080729072025.GH27385@comet.dominikbrodowski.net>
2008-07-29 15:45   ` [RFC] [PATCH 5/7] pcmcia: use pcmcia_loop_config in ISDN " Karsten Keil
2008-07-29 21:16 ` [RFC] [PATCH 1/7] pcmcia: add pcmcia_loop_config() helper Randy Dunlap

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).