LCOV - code coverage report
Current view: top level - lkbce/drivers/mmc/core - sdio_bus.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 77 108 71.3 %
Date: 2017-01-25 Functions: 13 18 72.2 %

          Line data    Source code
       1             : /*
       2             :  *  linux/drivers/mmc/core/sdio_bus.c
       3             :  *
       4             :  *  Copyright 2007 Pierre Ossman
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 2 of the License, or (at
       9             :  * your option) any later version.
      10             :  *
      11             :  * SDIO function driver model
      12             :  */
      13             : 
      14             : #include <linux/device.h>
      15             : #include <linux/err.h>
      16             : 
      17             : #include <linux/mmc/card.h>
      18             : #include <linux/mmc/sdio_func.h>
      19             : 
      20             : #include "sdio_cis.h"
      21             : #include "sdio_bus.h"
      22             : 
      23             : /* show configuration fields */
      24             : #define sdio_config_attr(field, format_string)                          \
      25             : static ssize_t                                                          \
      26             : field##_show(struct device *dev, struct device_attribute *attr, char *buf)                              \
      27             : {                                                                       \
      28             :         struct sdio_func *func;                                         \
      29             :                                                                         \
      30             :         func = dev_to_sdio_func (dev);                                  \
      31             :         return sprintf (buf, format_string, func->field);            \
      32             : }
      33             : 
      34           5 : sdio_config_attr(class, "0x%02x\n");
      35          20 : sdio_config_attr(vendor, "0x%04x\n");
      36           6 : sdio_config_attr(device, "0x%04x\n");
      37           5 : 
      38           6 : static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
      39           5 : {
      40           3 :         struct sdio_func *func = dev_to_sdio_func (dev);
      41           1 : 
      42           6 :         return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n",
      43           1 :                         func->class, func->vendor, func->device);
      44             : }
      45             : 
      46           1 : static struct device_attribute sdio_dev_attrs[] = {
      47             :         __ATTR_RO(class),
      48             :         __ATTR_RO(vendor),
      49             :         __ATTR_RO(device),
      50             :         __ATTR_RO(modalias),
      51             :         __ATTR_NULL,
      52             : };
      53             : 
      54             : static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,
      55             :         const struct sdio_device_id *id)
      56             : {
      57         168 :         if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class)
      58          24 :                 return NULL;
      59         168 :         if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor)
      60          24 :                 return NULL;
      61         168 :         if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device)
      62          24 :                 return NULL;
      63          24 :         return id;
      64             : }
      65             : 
      66             : static const struct sdio_device_id *sdio_match_device(struct sdio_func *func,
      67             :         struct sdio_driver *sdrv)
      68          24 : {
      69          24 :         const struct sdio_device_id *ids;
      70             : 
      71          24 :         ids = sdrv->id_table;
      72             : 
      73          48 :         if (ids) {
      74          72 :                 while (ids->class || ids->vendor || ids->device) {
      75         120 :                         if (sdio_match_one(func, ids))
      76          48 :                                 return ids;
      77          24 :                         ids++;
      78          24 :                 }
      79             :         }
      80             : 
      81          48 :         return NULL;
      82             : }
      83             : 
      84             : static int sdio_bus_match(struct device *dev, struct device_driver *drv)
      85             : {
      86          36 :         struct sdio_func *func = dev_to_sdio_func(dev);
      87          36 :         struct sdio_driver *sdrv = to_sdio_driver(drv);
      88          12 : 
      89          84 :         if (sdio_match_device(func, sdrv))
      90          24 :                 return 1;
      91             : 
      92          12 :         return 0;
      93             : }
      94             : 
      95             : static int
      96             : sdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
      97             : {
      98          51 :         struct sdio_func *func = dev_to_sdio_func(dev);
      99          17 : 
     100         102 :         if (add_uevent_var(env,
     101          17 :                         "SDIO_CLASS=%02X", func->class))
     102          34 :                 return -ENOMEM;
     103             : 
     104         102 :         if (add_uevent_var(env, 
     105             :                         "SDIO_ID=%04X:%04X", func->vendor, func->device))
     106          17 :                 return -ENOMEM;
     107             : 
     108         119 :         if (add_uevent_var(env,
     109             :                         "MODALIAS=sdio:c%02Xv%04Xd%04X",
     110             :                         func->class, func->vendor, func->device))
     111          17 :                 return -ENOMEM;
     112             : 
     113          17 :         return 0;
     114             : }
     115             : 
     116             : static int sdio_bus_probe(struct device *dev)
     117             : {
     118          48 :         struct sdio_driver *drv = to_sdio_driver(dev->driver);
     119          36 :         struct sdio_func *func = dev_to_sdio_func(dev);
     120          12 :         const struct sdio_device_id *id;
     121          12 :         int ret;
     122          12 : 
     123          60 :         id = sdio_match_device(func, drv);
     124          36 :         if (!id)
     125          12 :                 return -ENODEV;
     126             : 
     127             :         /* Set the default block size so the driver is sure it's something
     128             :          * sensible. */
     129          24 :         sdio_claim_host(func);
     130          48 :         ret = sdio_set_block_size(func, 0);
     131          24 :         sdio_release_host(func);
     132          24 :         if (ret)
     133          12 :                 return ret;
     134             : 
     135          24 :         return drv->probe(func, id);
     136             : }
     137             : 
     138             : static int sdio_bus_remove(struct device *dev)
     139             : {
     140          48 :         struct sdio_driver *drv = to_sdio_driver(dev->driver);
     141          36 :         struct sdio_func *func = dev_to_sdio_func(dev);
     142          12 : 
     143          24 :         drv->remove(func);
     144             : 
     145          36 :         if (func->irq_handler) {
     146          12 :                 printk(KERN_WARNING "WARNING: driver %s did not remove "
     147             :                         "its interrupt handler!\n", drv->name);
     148          24 :                 sdio_claim_host(func);
     149          36 :                 sdio_release_irq(func);
     150          24 :                 sdio_release_host(func);
     151             :         }
     152             : 
     153          24 :         return 0;
     154             : }
     155             : 
     156           1 : static struct bus_type sdio_bus_type = {
     157             :         .name           = "sdio",
     158             :         .dev_attrs      = sdio_dev_attrs,
     159             :         .match          = sdio_bus_match,
     160             :         .uevent         = sdio_bus_uevent,
     161             :         .probe          = sdio_bus_probe,
     162             :         .remove         = sdio_bus_remove,
     163             : };
     164             : 
     165             : int sdio_register_bus(void)
     166             : {
     167           3 :         return bus_register(&sdio_bus_type);
     168             : }
     169             : 
     170             : void sdio_unregister_bus(void)
     171             : {
     172           2 :         bus_unregister(&sdio_bus_type);
     173           2 : }
     174             : 
     175             : /**
     176             :  *      sdio_register_driver - register a function driver
     177             :  *      @drv: SDIO function driver
     178             :  */
     179             : int sdio_register_driver(struct sdio_driver *drv)
     180             : {
     181           0 :         drv->drv.name = drv->name;
     182           0 :         drv->drv.bus = &sdio_bus_type;
     183           0 :         return driver_register(&drv->drv);
     184             : }
     185             : EXPORT_SYMBOL_GPL(sdio_register_driver);
     186             : 
     187             : /**
     188             :  *      sdio_unregister_driver - unregister a function driver
     189             :  *      @drv: SDIO function driver
     190             :  */
     191             : void sdio_unregister_driver(struct sdio_driver *drv)
     192             : {
     193           0 :         drv->drv.bus = &sdio_bus_type;
     194           0 :         driver_unregister(&drv->drv);
     195           0 : }
     196             : EXPORT_SYMBOL_GPL(sdio_unregister_driver);
     197             : 
     198             : static void sdio_release_func(struct device *dev)
     199             : {
     200           0 :         struct sdio_func *func = dev_to_sdio_func(dev);
     201           0 : 
     202           0 :         sdio_free_func_cis(func);
     203             : 
     204           0 :         if (func->info)
     205           0 :                 kfree(func->info);
     206             : 
     207           0 :         kfree(func);
     208           0 : }
     209             : 
     210             : /*
     211             :  * Allocate and initialise a new SDIO function structure.
     212             :  */
     213             : struct sdio_func *sdio_alloc_func(struct mmc_card *card)
     214             : {
     215           0 :         struct sdio_func *func;
     216           0 : 
     217           0 :         func = kzalloc(sizeof(struct sdio_func), GFP_KERNEL);
     218           0 :         if (!func)
     219           0 :                 return ERR_PTR(-ENOMEM);
     220             : 
     221           0 :         func->card = card;
     222             : 
     223           0 :         device_initialize(&func->dev);
     224             : 
     225           0 :         func->dev.parent = &card->dev;
     226           0 :         func->dev.bus = &sdio_bus_type;
     227           0 :         func->dev.release = sdio_release_func;
     228             : 
     229           0 :         return func;
     230             : }
     231             : 
     232             : /*
     233             :  * Register a new SDIO function with the driver model.
     234             :  */
     235             : int sdio_add_func(struct sdio_func *func)
     236             : {
     237           0 :         int ret;
     238           0 : 
     239           0 :         dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
     240             : 
     241           0 :         ret = device_add(&func->dev);
     242           0 :         if (ret == 0)
     243           0 :                 sdio_func_set_present(func);
     244             : 
     245           0 :         return ret;
     246             : }
     247             : 
     248             : /*
     249             :  * Unregister a SDIO function with the driver model, and
     250             :  * (eventually) free it.
     251             :  * This function can be called through error paths where sdio_add_func() was
     252             :  * never executed (because a failure occurred at an earlier point).
     253             :  */
     254             : void sdio_remove_func(struct sdio_func *func)
     255             : {
     256           4 :         if (!sdio_func_present(func))
     257           2 :                 return;
     258             : 
     259           2 :         device_del(&func->dev);
     260           2 :         put_device(&func->dev);
     261           2 : }
     262             : 

Generated by: LCOV version 1.10