Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b1538bcf75e2e11459947ec4d4329ed04fbe2b2c
Commit:     b1538bcf75e2e11459947ec4d4329ed04fbe2b2c
Parent:     b726126196d54cbbba0924191e5c4dd5ba747fa2
Author:     Nicolas Pitre <[EMAIL PROTECTED]>
AuthorDate: Sat Jun 16 02:06:47 2007 -0400
Committer:  Pierre Ossman <[EMAIL PROTECTED]>
CommitDate: Sun Sep 23 20:31:43 2007 +0200

    sdio: link unknown CIS tuples to the sdio_func structure
    
    This way those tuples that the core cares about are consumed by the core
    code, and tuples that only function drivers might make sense of are
    available to drivers.
    
    Signed-off-by: Nicolas Pitre <[EMAIL PROTECTED]>
    Signed-off-by: Pierre Ossman <[EMAIL PROTECTED]>
---
 drivers/mmc/core/sdio_bus.c   |    3 +
 drivers/mmc/core/sdio_cis.c   |   83 ++++++++++++++++++++++++++--------------
 drivers/mmc/core/sdio_cis.h   |    1 +
 include/linux/mmc/sdio_func.h |   12 ++++++
 4 files changed, 70 insertions(+), 29 deletions(-)

diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index fa488ce..78e0381 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -17,6 +17,7 @@
 #include <linux/mmc/card.h>
 #include <linux/mmc/sdio_func.h>
 
+#include "sdio_cis.h"
 #include "sdio_bus.h"
 
 #define dev_to_sdio_func(d)    container_of(d, struct sdio_func, dev)
@@ -94,6 +95,8 @@ static void sdio_release_func(struct device *dev)
 {
        struct sdio_func *func = dev_to_sdio_func(dev);
 
+       sdio_free_cis(func);
+
        kfree(func);
 }
 
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index 114b600..b6c7342 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -5,6 +5,8 @@
  * Created:    June 11, 2007
  * Copyright:  MontaVista Software Inc.
  *
+ * Copyright 2007 Pierre Ossman
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or (at
@@ -49,7 +51,7 @@ static const struct cis_tpl cis_tpl_list[] = {
 int sdio_read_cis(struct sdio_func *func)
 {
        int ret;
-       unsigned char *buf;
+       struct sdio_func_tuple *this, **prev;
        unsigned i, ptr = 0;
 
        for (i = 0; i < 3; i++) {
@@ -61,13 +63,11 @@ int sdio_read_cis(struct sdio_func *func)
                ptr |= x << (i * 8);
        }
 
-       buf = kmalloc(256, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
+       /* find the list tail */
+       for (prev = &func->tuples; *prev; prev = &(*prev)->next);
 
        do {
                unsigned char tpl_code, tpl_link;
-               const struct cis_tpl *tpl;
 
                ret = mmc_io_rw_direct(func->card, 0, 0, ptr++, 0, &tpl_code);
                if (ret)
@@ -81,39 +81,64 @@ int sdio_read_cis(struct sdio_func *func)
                if (ret)
                        break;
 
-               for (i = 0; i < ARRAY_SIZE(cis_tpl_list); i++)
-                       if (cis_tpl_list[i].code == tpl_code)
+               this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL);
+               if (!this)
+                       return -ENOMEM;
+
+               for (i = 0; i < tpl_link; i++) {
+                       ret = mmc_io_rw_direct(func->card, 0, 0,
+                                              ptr + i, 0, &this->data[i]);
+                       if (ret)
                                break;
-               if (i >= ARRAY_SIZE(cis_tpl_list)) {
-                       printk(KERN_WARNING
-                              "%s: unknown CIS tuple 0x%02x of length %u\n",
-                              sdio_func_id(func), tpl_code, tpl_link);
-                       ptr += tpl_link;
-                       continue;
                }
-               tpl = cis_tpl_list + i;
-
-               if (tpl_link < tpl->min_size) {
-                       printk(KERN_ERR
-                              "%s: bad CIS tuple 0x%02x (length = %u, expected 
>= %u\n",
-                              sdio_func_id(func), tpl_code, tpl_link, 
tpl->min_size);
-                       ret = -EINVAL;
+               if (ret) {
+                       kfree(this);
                        break;
                }
 
-               for (i = 0; i < tpl_link; i++) {
-                       ret = mmc_io_rw_direct(func->card, 0, 0, ptr + i, 0, 
&buf[i]);
-                       if (ret)
+               for (i = 0; i < ARRAY_SIZE(cis_tpl_list); i++)
+                       if (cis_tpl_list[i].code == tpl_code)
                                break;
+               if (i >= ARRAY_SIZE(cis_tpl_list)) {
+                       /* this tuple is unknown to the core */
+                       this->next = NULL;
+                       this->code = tpl_code;
+                       this->size = tpl_link;
+                       *prev = this;
+                       prev = &this->next;
+                       printk(KERN_DEBUG
+                              "%s: queuing CIS tuple 0x%02x length %u\n",
+                              sdio_func_id(func), tpl_code, tpl_link);
+               } else {
+                       const struct cis_tpl *tpl = cis_tpl_list + i;
+                       if (tpl_link < tpl->min_size) {
+                               printk(KERN_ERR
+                                      "%s: bad CIS tuple 0x%02x (length = %u, 
expected >= %u)\n",
+                                      sdio_func_id(func), tpl_code, tpl_link, 
tpl->min_size);
+                               ret = -EINVAL;
+                       } else if (tpl->parse)
+                               ret = tpl->parse(func, this->data, tpl_link);
+                       kfree(this);
                }
-               if (ret)
-                       break;
-               ptr += tpl_link;
 
-               if (tpl->parse)
-                       ret = tpl->parse(func, buf, tpl_link);
+               ptr += tpl_link;
        } while (!ret);
 
-       kfree(buf);
        return ret;
 }
+
+void sdio_free_cis(struct sdio_func *func)
+{
+       struct sdio_func_tuple *tuple, *victim;
+
+       tuple = func->tuples;
+
+       while (tuple) {
+               victim = tuple;
+               tuple = tuple->next;
+               kfree(victim);
+       }
+
+       func->tuples = NULL;
+}
+
diff --git a/drivers/mmc/core/sdio_cis.h b/drivers/mmc/core/sdio_cis.h
index df21c49..863d3d5 100644
--- a/drivers/mmc/core/sdio_cis.h
+++ b/drivers/mmc/core/sdio_cis.h
@@ -15,5 +15,6 @@
 #define _MMC_SDIO_CIS_H
 
 int sdio_read_cis(struct sdio_func *func);
+void sdio_free_cis(struct sdio_func *func);
 
 #endif
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
index 4164809..2690676 100644
--- a/include/linux/mmc/sdio_func.h
+++ b/include/linux/mmc/sdio_func.h
@@ -15,6 +15,16 @@
 struct mmc_card;
 
 /*
+ * SDIO function CIS tuple (unknown to the core)
+ */
+struct sdio_func_tuple {
+       struct sdio_func_tuple *next;
+       unsigned char code;
+       unsigned char size;
+       unsigned char data[0];
+};
+
+/*
  * SDIO function devices
  */
 struct sdio_func {
@@ -28,6 +38,8 @@ struct sdio_func {
 
        unsigned int            state;          /* function state */
 #define SDIO_STATE_PRESENT     (1<<0)          /* present in sysfs */
+
+       struct sdio_func_tuple *tuples;
 };
 
 #define sdio_func_present(f)   ((f)->state & SDIO_STATE_PRESENT)
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to