USB: cdc_acm: Fix memory leak after hangup
[safe/jmp/linux-2.6] / drivers / pcmcia / ds.c
index 7142fd6..f5b7079 100644 (file)
@@ -32,7 +32,6 @@
 #include <pcmcia/ss.h>
 
 #include "cs_internal.h"
-#include "ds_internal.h"
 
 /*====================================================================*/
 
@@ -69,32 +68,19 @@ spinlock_t pcmcia_dev_list_lock;
 /* String tables for error messages */
 
 typedef struct lookup_t {
-    int key;
-    char *msg;
+    const int key;
+    const char *msg;
 } lookup_t;
 
 static const lookup_t error_table[] = {
-    { CS_SUCCESS,              "Operation succeeded" },
-    { CS_BAD_ATTRIBUTE,        "Bad attribute", },
-    { CS_BAD_BASE,             "Bad base address" },
-    { CS_BAD_IRQ,              "Bad IRQ" },
-    { CS_BAD_OFFSET,           "Bad offset" },
-    { CS_BAD_PAGE,             "Bad page number" },
-    { CS_BAD_SIZE,             "Bad size" },
-    { CS_BAD_TYPE,             "Bad type" },
-    { CS_BAD_VCC,              "Bad Vcc" },
-    { CS_BAD_VPP,              "Bad Vpp" },
-    { CS_NO_CARD,              "No card present" },
-    { CS_UNSUPPORTED_FUNCTION, "Usupported function" },
-    { CS_UNSUPPORTED_MODE,     "Unsupported mode" },
-    { CS_GENERAL_FAILURE,      "General failure" },
-    { CS_BAD_ARGS,             "Bad arguments" },
-    { CS_CONFIGURATION_LOCKED, "Configuration locked" },
-    { CS_IN_USE,               "Resource in use" },
-    { CS_NO_MORE_ITEMS,                "No more items" },
-    { CS_OUT_OF_RESOURCE,      "Out of resource" },
-    { CS_BAD_HANDLE,           "Bad handle" },
-    { CS_BAD_TUPLE,            "Bad CIS tuple" }
+    { 0,                       "Operation succeeded" },
+    { -EIO,                    "Input/Output error" },
+    { -ENODEV,                 "No card present" },
+    { -EINVAL,                 "Bad parameter" },
+    { -EACCES,                 "Configuration locked" },
+    { -EBUSY,                  "Resource in use" },
+    { -ENOSPC,                 "No more items" },
+    { -ENOMEM,                 "Out of resource" },
 };
 
 
@@ -150,46 +136,32 @@ static const lookup_t service_table[] = {
     { ReplaceCIS,                      "ReplaceCIS" }
 };
 
-
-static int pcmcia_report_error(struct pcmcia_device *p_dev, error_info_t *err)
+const char *pcmcia_error_func(int func)
 {
        int i;
-       char *serv;
-
-       if (!p_dev)
-               printk(KERN_NOTICE);
-       else
-               printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id);
 
        for (i = 0; i < ARRAY_SIZE(service_table); i++)
-               if (service_table[i].key == err->func)
-                       break;
-       if (i < ARRAY_SIZE(service_table))
-               serv = service_table[i].msg;
-       else
-               serv = "Unknown service number";
+               if (service_table[i].key == func)
+                       return service_table[i].msg;
 
-       for (i = 0; i < ARRAY_SIZE(error_table); i++)
-               if (error_table[i].key == err->retcode)
-                       break;
-       if (i < ARRAY_SIZE(error_table))
-               printk("%s: %s\n", serv, error_table[i].msg);
-       else
-               printk("%s: Unknown error code %#x\n", serv, err->retcode);
+       return "Unknown service number";
+}
+EXPORT_SYMBOL(pcmcia_error_func);
 
-       return 0;
-} /* report_error */
+const char *pcmcia_error_ret(int ret)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(error_table); i++)
+               if (error_table[i].key == ret)
+                       return error_table[i].msg;
 
-/* end of code which was in cs.c before */
+       return "unknown";
+}
+EXPORT_SYMBOL(pcmcia_error_ret);
 
 /*======================================================================*/
 
-void cs_error(struct pcmcia_device *p_dev, int func, int ret)
-{
-       error_info_t err = { func, ret };
-       pcmcia_report_error(p_dev, &err);
-}
-EXPORT_SYMBOL(cs_error);
 
 
 static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
@@ -264,7 +236,6 @@ pcmcia_store_new_id(struct device_driver *driver, const char *buf, size_t count)
        if (!dynid)
                return -ENOMEM;
 
-       INIT_LIST_HEAD(&dynid->node);
        dynid->id.match_flags = match_flags;
        dynid->id.manf_id = manf_id;
        dynid->id.card_id = card_id;
@@ -274,7 +245,7 @@ pcmcia_store_new_id(struct device_driver *driver, const char *buf, size_t count)
        memcpy(dynid->id.prod_id_hash, prod_id_hash, sizeof(__u32) * 4);
 
        spin_lock(&pdrv->dynids.lock);
-       list_add_tail(&pdrv->dynids.list, &dynid->node);
+       list_add_tail(&dynid->node, &pdrv->dynids.list);
        spin_unlock(&pdrv->dynids.lock);
 
        if (get_driver(&pdrv->drv)) {
@@ -422,6 +393,18 @@ static int pcmcia_device_probe(struct device * dev)
        p_drv = to_pcmcia_drv(dev->driver);
        s = p_dev->socket;
 
+       /* The PCMCIA code passes the match data in via dev_set_drvdata(dev)
+        * which is an ugly hack. Once the driver probe is called it may
+        * and often will overwrite the match data so we must save it first
+        *
+        * handle pseudo multifunction devices:
+        * there are at most two pseudo multifunction devices.
+        * if we're matching against the first, schedule a
+        * call which will then check whether there are two
+        * pseudo devices, and if not, add the second one.
+        */
+       did = dev_get_drvdata(&p_dev->dev);
+
        ds_dev_dbg(1, dev, "trying to bind to %s\n", p_drv->drv.name);
 
        if ((!p_drv->probe) || (!p_dev->function_config) ||
@@ -450,21 +433,14 @@ static int pcmcia_device_probe(struct device * dev)
                goto put_module;
        }
 
-       /* handle pseudo multifunction devices:
-        * there are at most two pseudo multifunction devices.
-        * if we're matching against the first, schedule a
-        * call which will then check whether there are two
-        * pseudo devices, and if not, add the second one.
-        */
-       did = p_dev->dev.driver_data;
        if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
            (p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
                pcmcia_add_device_later(p_dev->socket, 0);
 
- put_module:
+put_module:
        if (ret)
                module_put(p_drv->owner);
- put_dev:
+put_dev:
        if (ret)
                put_device(dev);
        return (ret);
@@ -522,7 +498,7 @@ static int pcmcia_device_remove(struct device * dev)
         * pseudo multi-function card, we need to unbind
         * all devices
         */
-       did = p_dev->dev.driver_data;
+       did = dev_get_drvdata(&p_dev->dev);
        if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
            (p_dev->socket->device_count != 0) &&
            (p_dev->device_no == 0))
@@ -571,7 +547,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
        if (!vers1)
                return -ENOMEM;
 
-       if (!pccard_read_tuple(p_dev->socket, p_dev->func,
+       if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL,
                               CISTPL_MANFID, &manf_id)) {
                p_dev->manf_id = manf_id.manf;
                p_dev->card_id = manf_id.card;
@@ -605,9 +581,9 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
                kfree(devgeo);
        }
 
-       if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_VERS_1,
+       if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, CISTPL_VERS_1,
                               vers1)) {
-               for (i=0; i < vers1->ns; i++) {
+               for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) {
                        char *tmp;
                        unsigned int length;
 
@@ -645,7 +621,6 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
 {
        struct pcmcia_device *p_dev, *tmp_dev;
        unsigned long flags;
-       int bus_id_len;
 
        s = pcmcia_get_socket(s);
        if (!s)
@@ -673,12 +648,12 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
        /* by default don't allow DMA */
        p_dev->dma_mask = DMA_MASK_NONE;
        p_dev->dev.dma_mask = &p_dev->dma_mask;
-       bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no);
-
-       p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL);
+       dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+       if (!dev_name(&p_dev->dev))
+               goto err_free;
+       p_dev->devname = kasprintf(GFP_KERNEL, "pcmcia%s", dev_name(&p_dev->dev));
        if (!p_dev->devname)
                goto err_free;
-       sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
        ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname);
 
        spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
@@ -691,6 +666,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
         list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list)
                 if (p_dev->func == tmp_dev->func) {
                        p_dev->function_config = tmp_dev->function_config;
+                       p_dev->io = tmp_dev->io;
+                       p_dev->irq = tmp_dev->irq;
                        kref_get(&p_dev->function_config->ref);
                }
 
@@ -756,7 +733,7 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
                return -EAGAIN; /* try again, but later... */
        }
 
-       ret = pccard_validate_cis(s, BIND_FN_ALL, &no_chains);
+       ret = pccard_validate_cis(s, &no_chains);
        if (ret || !no_chains) {
                ds_dev_dbg(0, &s->dev, "invalid CIS or invalid resources\n");
                return -ENODEV;
@@ -850,7 +827,6 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
 {
        struct pcmcia_socket *s = dev->socket;
        const struct firmware *fw;
-       char path[FIRMWARE_NAME_MAX];
        int ret = -ENOMEM;
        int no_funcs;
        int old_funcs;
@@ -861,16 +837,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
 
        ds_dev_dbg(1, &dev->dev, "trying to load CIS file %s\n", filename);
 
-       if (strlen(filename) > (FIRMWARE_NAME_MAX - 1)) {
-               dev_printk(KERN_WARNING, &dev->dev,
-                          "pcmcia: CIS filename is too long [%s]\n",
-                          filename);
-               return -EINVAL;
-       }
-
-       snprintf(path, sizeof(path), "%s", filename);
-
-       if (request_firmware(&fw, path, &dev->dev) == 0) {
+       if (request_firmware(&fw, filename, &dev->dev) == 0) {
                if (fw->size >= CISTPL_MAX_CIS_SIZE) {
                        ret = -EINVAL;
                        dev_printk(KERN_ERR, &dev->dev,
@@ -1010,7 +977,7 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
                        return 0;
        }
 
-       dev->dev.driver_data = (void *) did;
+       dev_set_drvdata(&dev->dev, did);
 
        return 1;
 }