pcmcia: clarify alloc_io_space, move it to resource handlers
Dominik Brodowski [Sat, 20 Mar 2010 12:10:47 +0000 (13:10 +0100)]
Clean up the alloc_io_space() function by moving most of it to
the actual resource_ops. This allows for a bit less re-directions.
Future cleanups will follow, and will make up for the code
duplication currently present between rsrc_iodyn and rsrc_nonstatic
(which are hardly ever built at the same time anyway, therefore no
increase in built size).

Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>

drivers/pcmcia/cs_internal.h
drivers/pcmcia/pcmcia_resource.c
drivers/pcmcia/rsrc_iodyn.c
drivers/pcmcia/rsrc_mgr.c
drivers/pcmcia/rsrc_nonstatic.c
include/pcmcia/ds.h

index ab000ea..4126a75 100644 (file)
@@ -52,13 +52,11 @@ struct cis_cache_entry {
 
 struct pccard_resource_ops {
        int     (*validate_mem)         (struct pcmcia_socket *s);
-       int     (*adjust_io_region)     (struct resource *res,
-                                        unsigned long r_start,
-                                        unsigned long r_end,
-                                        struct pcmcia_socket *s);
-       struct resource* (*find_io)     (unsigned long base, int num,
-                                        unsigned long align,
-                                        struct pcmcia_socket *s);
+       int     (*find_io)              (struct pcmcia_socket *s,
+                                        unsigned int attr,
+                                        unsigned int *base,
+                                        unsigned int num,
+                                        unsigned int align);
        struct resource* (*find_mem)    (unsigned long base, unsigned long num,
                                         unsigned long align, int low,
                                         struct pcmcia_socket *s);
index 9c5f9cd..c6419c1 100644 (file)
@@ -40,23 +40,6 @@ static int io_speed;
 module_param(io_speed, int, 0444);
 
 
-static int pcmcia_adjust_io_region(struct resource *res, unsigned long start,
-                                  unsigned long end, struct pcmcia_socket *s)
-{
-       if (s->resource_ops->adjust_io_region)
-               return s->resource_ops->adjust_io_region(res, start, end, s);
-       return -ENOMEM;
-}
-
-static struct resource *pcmcia_find_io_region(unsigned long base, int num,
-                                             unsigned long align,
-                                             struct pcmcia_socket *s)
-{
-       if (s->resource_ops->find_io)
-               return s->resource_ops->find_io(base, num, align, s);
-       return NULL;
-}
-
 int pcmcia_validate_mem(struct pcmcia_socket *s)
 {
        if (s->resource_ops->validate_mem)
@@ -82,8 +65,7 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
 static int alloc_io_space(struct pcmcia_socket *s, u_int attr,
                          unsigned int *base, unsigned int num, u_int lines)
 {
-       int i;
-       unsigned int try, align;
+       unsigned int align;
 
        align = (*base) ? (lines ? 1<<lines : 0) : 1;
        if (align && (align < num)) {
@@ -100,50 +82,8 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr,
                       *base, align);
                align = 0;
        }
-       if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) {
-               *base = s->io_offset | (*base & 0x0fff);
-               return 0;
-       }
-       /* Check for an already-allocated window that must conflict with
-        * what was asked for.  It is a hack because it does not catch all
-        * potential conflicts, just the most obvious ones.
-        */
-       for (i = 0; i < MAX_IO_WIN; i++)
-               if ((s->io[i].res) && *base &&
-                   ((s->io[i].res->start & (align-1)) == *base))
-                       return 1;
-       for (i = 0; i < MAX_IO_WIN; i++) {
-               if (!s->io[i].res) {
-                       s->io[i].res = pcmcia_find_io_region(*base, num, align, s);
-                       if (s->io[i].res) {
-                               *base = s->io[i].res->start;
-                               s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS);
-                               s->io[i].InUse = num;
-                               break;
-                       } else
-                               return 1;
-               } else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS))
-                       continue;
-               /* Try to extend top of window */
-               try = s->io[i].res->end + 1;
-               if ((*base == 0) || (*base == try))
-                       if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start,
-                                                   s->io[i].res->end + num, s) == 0) {
-                               *base = try;
-                               s->io[i].InUse += num;
-                               break;
-                       }
-               /* Try to extend bottom of window */
-               try = s->io[i].res->start - num;
-               if ((*base == 0) || (*base == try))
-                       if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num,
-                                                   s->io[i].res->end, s) == 0) {
-                               *base = try;
-                               s->io[i].InUse += num;
-                               break;
-                       }
-       }
-       return (i == MAX_IO_WIN);
+
+       return s->resource_ops->find_io(s, attr, base, num, align);
 } /* alloc_io_space */
 
 
@@ -683,7 +623,8 @@ EXPORT_SYMBOL(pcmcia_request_irq);
  * free_irq themselves, too), or the pcmcia_request_irq() function.
  */
 int __must_check
-pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, irq_handler_t handler)
+__pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
+                       irq_handler_t handler)
 {
        int ret;
 
@@ -705,7 +646,7 @@ pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev, irq_handler_t handler)
 
        return ret;
 } /* pcmcia_request_exclusive_irq */
-EXPORT_SYMBOL(pcmcia_request_exclusive_irq);
+EXPORT_SYMBOL(__pcmcia_request_exclusive_irq);
 
 
 #ifdef CONFIG_PCMCIA_PROBE
index 3fa808b..7791375 100644 (file)
@@ -56,15 +56,9 @@ static resource_size_t pcmcia_align(void *align_data,
 }
 
 
-static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start,
-               unsigned long r_end, struct pcmcia_socket *s)
-{
-       return adjust_resource(res, r_start, r_end - r_start + 1);
-}
-
-
-static struct resource *iodyn_find_io_region(unsigned long base, int num,
-               unsigned long align, struct pcmcia_socket *s)
+static struct resource *__iodyn_find_io_region(struct pcmcia_socket *s,
+                                       unsigned long base, int num,
+                                       unsigned long align)
 {
        struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO,
                                                dev_name(&s->dev));
@@ -72,9 +66,6 @@ static struct resource *iodyn_find_io_region(unsigned long base, int num,
        unsigned long min = base;
        int ret;
 
-       if (align == 0)
-               align = 0x10000;
-
        data.mask = align - 1;
        data.offset = base & data.mask;
 
@@ -94,10 +85,83 @@ static struct resource *iodyn_find_io_region(unsigned long base, int num,
        return res;
 }
 
+static int iodyn_find_io(struct pcmcia_socket *s, unsigned int attr,
+                       unsigned int *base, unsigned int num,
+                       unsigned int align)
+{
+       int i, ret = 0;
+
+       /* Check for an already-allocated window that must conflict with
+        * what was asked for.  It is a hack because it does not catch all
+        * potential conflicts, just the most obvious ones.
+        */
+       for (i = 0; i < MAX_IO_WIN; i++) {
+               if (!s->io[i].res)
+                       continue;
+
+               if (!*base)
+                       continue;
+
+               if ((s->io[i].res->start & (align-1)) == *base)
+                       return -EBUSY;
+       }
+
+       for (i = 0; i < MAX_IO_WIN; i++) {
+               struct resource *res = s->io[i].res;
+               unsigned int try;
+
+               if (res && (res->flags & IORESOURCE_BITS) !=
+                       (attr & IORESOURCE_BITS))
+                       continue;
+
+               if (!res) {
+                       if (align == 0)
+                               align = 0x10000;
+
+                       res = s->io[i].res = __iodyn_find_io_region(s, *base,
+                                                               num, align);
+                       if (!res)
+                               return -EINVAL;
+
+                       *base = res->start;
+                       s->io[i].res->flags =
+                               ((res->flags & ~IORESOURCE_BITS) |
+                                       (attr & IORESOURCE_BITS));
+                       s->io[i].InUse = num;
+                       return 0;
+               }
+
+               /* Try to extend top of window */
+               try = res->end + 1;
+               if ((*base == 0) || (*base == try)) {
+                       if (adjust_resource(s->io[i].res, res->start,
+                                       res->end - res->start + num + 1))
+                               continue;
+                       *base = try;
+                       s->io[i].InUse += num;
+                       return 0;
+               }
+
+               /* Try to extend bottom of window */
+               try = res->start - num;
+               if ((*base == 0) || (*base == try)) {
+                       if (adjust_resource(s->io[i].res,
+                                       res->start - num,
+                                       res->end - res->start + num + 1))
+                               continue;
+                       *base = try;
+                       s->io[i].InUse += num;
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+
 struct pccard_resource_ops pccard_iodyn_ops = {
        .validate_mem = NULL,
-       .adjust_io_region = iodyn_adjust_io_region,
-       .find_io = iodyn_find_io_region,
+       .find_io = iodyn_find_io,
        .find_mem = NULL,
        .add_io = NULL,
        .add_mem = NULL,
index 71838ca..142efac 100644 (file)
@@ -46,11 +46,21 @@ struct resource *pcmcia_make_resource(unsigned long start, unsigned long end,
        return res;
 }
 
+static int static_find_io(struct pcmcia_socket *s, unsigned int attr,
+                       unsigned int *base, unsigned int num,
+                       unsigned int align)
+{
+       if (!s->io_offset)
+               return -EINVAL;
+       *base = s->io_offset | (*base & 0x0fff);
+
+       return 0;
+}
+
 
 struct pccard_resource_ops pccard_static_ops = {
        .validate_mem = NULL,
-       .adjust_io_region = NULL,
-       .find_io = NULL,
+       .find_io = static_find_io,
        .find_mem = NULL,
        .add_io = NULL,
        .add_mem = NULL,
index c5ebc60..ba5256d 100644 (file)
@@ -649,8 +649,9 @@ pcmcia_align(void *align_data, const struct resource *res,
  * Adjust an existing IO region allocation, but making sure that we don't
  * encroach outside the resources which the user supplied.
  */
-static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_start,
-                                     unsigned long r_end, struct pcmcia_socket *s)
+static int __nonstatic_adjust_io_region(struct pcmcia_socket *s,
+                                       unsigned long r_start,
+                                       unsigned long r_end)
 {
        struct resource_map *m;
        struct socket_data *s_data = s->resource_data;
@@ -663,8 +664,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
                if (start > r_start || r_end > end)
                        continue;
 
-               ret = adjust_resource(res, r_start, r_end - r_start + 1);
-               break;
+               ret = 0;
        }
 
        return ret;
@@ -683,8 +683,9 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star
 
 ======================================================================*/
 
-static struct resource *nonstatic_find_io_region(unsigned long base, int num,
-                  unsigned long align, struct pcmcia_socket *s)
+static struct resource *__nonstatic_find_io_region(struct pcmcia_socket *s,
+                                               unsigned long base, int num,
+                                               unsigned long align)
 {
        struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO,
                                                dev_name(&s->dev));
@@ -693,9 +694,6 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
        unsigned long min = base;
        int ret;
 
-       if (align == 0)
-               align = 0x10000;
-
        data.mask = align - 1;
        data.offset = base & data.mask;
        data.map = &s_data->io_db;
@@ -716,6 +714,92 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
        return res;
 }
 
+static int nonstatic_find_io(struct pcmcia_socket *s, unsigned int attr,
+                       unsigned int *base, unsigned int num,
+                       unsigned int align)
+{
+       int i, ret = 0;
+
+       /* Check for an already-allocated window that must conflict with
+        * what was asked for.  It is a hack because it does not catch all
+        * potential conflicts, just the most obvious ones.
+        */
+       for (i = 0; i < MAX_IO_WIN; i++) {
+               if (!s->io[i].res)
+                       continue;
+
+               if (!*base)
+                       continue;
+
+               if ((s->io[i].res->start & (align-1)) == *base)
+                       return -EBUSY;
+       }
+
+       for (i = 0; i < MAX_IO_WIN; i++) {
+               struct resource *res = s->io[i].res;
+               unsigned int try;
+
+               if (res && (res->flags & IORESOURCE_BITS) !=
+                       (attr & IORESOURCE_BITS))
+                       continue;
+
+               if (!res) {
+                       if (align == 0)
+                               align = 0x10000;
+
+                       res = s->io[i].res = __nonstatic_find_io_region(s,
+                                                               *base, num,
+                                                               align);
+                       if (!res)
+                               return -EINVAL;
+
+                       *base = res->start;
+                       s->io[i].res->flags =
+                               ((res->flags & ~IORESOURCE_BITS) |
+                                       (attr & IORESOURCE_BITS));
+                       s->io[i].InUse = num;
+                       return 0;
+               }
+
+               /* Try to extend top of window */
+               try = res->end + 1;
+               if ((*base == 0) || (*base == try)) {
+                       ret =  __nonstatic_adjust_io_region(s, res->start,
+                                                       res->end + num);
+                       if (!ret) {
+                               ret = adjust_resource(s->io[i].res, res->start,
+                                              res->end - res->start + num + 1);
+                               if (ret)
+                                       continue;
+                               *base = try;
+                               s->io[i].InUse += num;
+                               return 0;
+                       }
+               }
+
+               /* Try to extend bottom of window */
+               try = res->start - num;
+               if ((*base == 0) || (*base == try)) {
+                       ret =  __nonstatic_adjust_io_region(s,
+                                                       res->start - num,
+                                                       res->end);
+                       if (!ret) {
+                               ret = adjust_resource(s->io[i].res,
+                                              res->start - num,
+                                              res->end - res->start + num + 1);
+                               if (ret)
+                                       continue;
+                               *base = try;
+                               s->io[i].InUse += num;
+                               return 0;
+                       }
+               }
+       }
+
+       return -EINVAL;
+}
+
+
 static struct resource *nonstatic_find_mem_region(u_long base, u_long num,
                u_long align, int low, struct pcmcia_socket *s)
 {
@@ -946,8 +1030,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s)
 
 struct pccard_resource_ops pccard_nonstatic_ops = {
        .validate_mem = pcmcia_nonstatic_validate_mem,
-       .adjust_io_region = nonstatic_adjust_io_region,
-       .find_io = nonstatic_find_io_region,
+       .find_io = nonstatic_find_io,
        .find_mem = nonstatic_find_mem_region,
        .add_io = adjust_io,
        .add_mem = adjust_memory,
index b4429f7..c180165 100644 (file)
@@ -184,9 +184,16 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
 /* device configuration */
 int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req);
 
-int __must_check __deprecated
-pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
+int __must_check
+__pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
                                irq_handler_t handler);
+static inline __must_check __deprecated int
+pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
+                               irq_handler_t handler)
+{
+       return __pcmcia_request_exclusive_irq(p_dev, handler);
+}
+
 int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
                                irq_handler_t handler);