sdio_bus.c revision bcfe66e21ef78a078bb0de0bab532701996695d3
1e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 2e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * linux/drivers/mmc/core/sdio_bus.c 3e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * 4e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Copyright 2007 Pierre Ossman 5e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * 6e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * This program is free software; you can redistribute it and/or modify 7e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * it under the terms of the GNU General Public License as published by 8e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * the Free Software Foundation; either version 2 of the License, or (at 9e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * your option) any later version. 10e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * 11e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * SDIO function driver model 12e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 13e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 14e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/device.h> 15e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/err.h> 16e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 17e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/mmc/card.h> 18e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include <linux/mmc/sdio_func.h> 19e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 20b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre#include "sdio_cis.h" 21e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#include "sdio_bus.h" 22e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 23e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) 243b38bea0d976513970f947806b08b9faca418e7aPierre Ossman#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) 253b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 26bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman/* show configuration fields */ 27bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman#define sdio_config_attr(field, format_string) \ 28bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmanstatic ssize_t \ 29bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmanfield##_show(struct device *dev, struct device_attribute *attr, char *buf) \ 30bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman{ \ 31bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman struct sdio_func *func; \ 32bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman \ 33bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman func = dev_to_sdio_func (dev); \ 34bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman return sprintf (buf, format_string, func->field); \ 35bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman} 36bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman 37bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmansdio_config_attr(class, "0x%02x\n"); 38bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmansdio_config_attr(vendor, "0x%04x\n"); 39bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmansdio_config_attr(device, "0x%04x\n"); 40bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman 41bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmanstatic ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) 42bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman{ 43bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman struct sdio_func *func = dev_to_sdio_func (dev); 44bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman 45bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n", 46bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman func->class, func->vendor, func->device); 47bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman} 48bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman 49bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossmanstruct device_attribute sdio_dev_attrs[] = { 50bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman __ATTR_RO(class), 51bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman __ATTR_RO(vendor), 52bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman __ATTR_RO(device), 53bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman __ATTR_RO(modalias), 54bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman __ATTR_NULL, 55bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman}; 56bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman 573b38bea0d976513970f947806b08b9faca418e7aPierre Ossmanstatic const struct sdio_device_id *sdio_match_one(struct sdio_func *func, 583b38bea0d976513970f947806b08b9faca418e7aPierre Ossman const struct sdio_device_id *id) 593b38bea0d976513970f947806b08b9faca418e7aPierre Ossman{ 603b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class) 613b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return NULL; 623b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor) 633b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return NULL; 643b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device) 653b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return NULL; 663b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return id; 673b38bea0d976513970f947806b08b9faca418e7aPierre Ossman} 683b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 693b38bea0d976513970f947806b08b9faca418e7aPierre Ossmanstatic const struct sdio_device_id *sdio_match_device(struct sdio_func *func, 703b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_driver *sdrv) 713b38bea0d976513970f947806b08b9faca418e7aPierre Ossman{ 723b38bea0d976513970f947806b08b9faca418e7aPierre Ossman const struct sdio_device_id *ids; 733b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 743b38bea0d976513970f947806b08b9faca418e7aPierre Ossman ids = sdrv->id_table; 753b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 763b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (ids) { 773b38bea0d976513970f947806b08b9faca418e7aPierre Ossman while (ids->class || ids->vendor || ids->device) { 783b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (sdio_match_one(func, ids)) 793b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return ids; 803b38bea0d976513970f947806b08b9faca418e7aPierre Ossman ids++; 813b38bea0d976513970f947806b08b9faca418e7aPierre Ossman } 823b38bea0d976513970f947806b08b9faca418e7aPierre Ossman } 833b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 843b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return NULL; 853b38bea0d976513970f947806b08b9faca418e7aPierre Ossman} 86e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 87e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_match(struct device *dev, struct device_driver *drv) 88e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 893b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 903b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_driver *sdrv = to_sdio_driver(drv); 913b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 923b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (sdio_match_device(func, sdrv)) 933b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return 1; 943b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 953b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return 0; 96e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 97e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 98e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int 99e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmansdio_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, 100e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman int buf_size) 101e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 102d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 103d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman int i = 0, length = 0; 104d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 105d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman if (add_uevent_var(envp, num_envp, &i, 106d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman buf, buf_size, &length, 107d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman "SDIO_CLASS=%02X", func->class)) 108d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman return -ENOMEM; 109d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 110d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman if (add_uevent_var(envp, num_envp, &i, 111d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman buf, buf_size, &length, 112d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman "SDIO_ID=%04X:%04X", func->vendor, func->device)) 113d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman return -ENOMEM; 114d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 115d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman if (add_uevent_var(envp, num_envp, &i, 116d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman buf, buf_size, &length, 117d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman "MODALIAS=sdio:c%02Xv%04Xd%04X", 118d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman func->class, func->vendor, func->device)) 119d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman return -ENOMEM; 120d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman 121d59b66c7a575cfa8e01f483875d131e42b539bbcPierre Ossman envp[i] = NULL; 122e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 123e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return 0; 124e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 125e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 126e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_probe(struct device *dev) 127e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 1283b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_driver *drv = to_sdio_driver(dev->driver); 1293b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 1303b38bea0d976513970f947806b08b9faca418e7aPierre Ossman const struct sdio_device_id *id; 1313b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 1323b38bea0d976513970f947806b08b9faca418e7aPierre Ossman id = sdio_match_device(func, drv); 1333b38bea0d976513970f947806b08b9faca418e7aPierre Ossman if (!id) 1343b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return -ENODEV; 1353b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 1363b38bea0d976513970f947806b08b9faca418e7aPierre Ossman return drv->probe(func, id); 137e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 138e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 139e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic int sdio_bus_remove(struct device *dev) 140e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 1413b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_driver *drv = to_sdio_driver(dev->driver); 1423b38bea0d976513970f947806b08b9faca418e7aPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 1433b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 1443b38bea0d976513970f947806b08b9faca418e7aPierre Ossman drv->remove(func); 1453b38bea0d976513970f947806b08b9faca418e7aPierre Ossman 146e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return 0; 147e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 148e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 149e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic struct bus_type sdio_bus_type = { 150e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .name = "sdio", 151bcfe66e21ef78a078bb0de0bab532701996695d3Pierre Ossman .dev_attrs = sdio_dev_attrs, 152e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .match = sdio_bus_match, 153e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .uevent = sdio_bus_uevent, 154e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .probe = sdio_bus_probe, 155e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman .remove = sdio_bus_remove, 156e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman}; 157e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 158e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_register_bus(void) 159e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 160e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return bus_register(&sdio_bus_type); 161e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 162e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 163e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_unregister_bus(void) 164e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 165e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman bus_unregister(&sdio_bus_type); 166e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 167e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 168f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/** 169f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * sdio_register_driver - register a function driver 170f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * @drv: SDIO function driver 171f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */ 172f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanint sdio_register_driver(struct sdio_driver *drv) 173f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{ 174f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.name = drv->name; 175f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.bus = &sdio_bus_type; 176f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman return driver_register(&drv->drv); 177f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman} 178f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_register_driver); 179f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman 180f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman/** 181f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * sdio_unregister_driver - unregister a function driver 182f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman * @drv: SDIO function driver 183f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman */ 184f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossmanvoid sdio_unregister_driver(struct sdio_driver *drv) 185f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman{ 186f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman drv->drv.bus = &sdio_bus_type; 187f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman driver_unregister(&drv->drv); 188f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman} 189f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre OssmanEXPORT_SYMBOL_GPL(sdio_unregister_driver); 190f76c85154d320497bf1a939a98d6c432edcbd4a9Pierre Ossman 191e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstatic void sdio_release_func(struct device *dev) 192e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 193e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman struct sdio_func *func = dev_to_sdio_func(dev); 194b1538bcf75e2e11459947ec4d4329ed04fbe2b2cNicolas Pitre 1951a632f8cdc33e7f8edca352164f0c96a75d08f08Pierre Ossman sdio_free_func_cis(func); 196e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 197e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman kfree(func); 198e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 199e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 200e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 201e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Allocate and initialise a new SDIO function structure. 202e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 203e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanstruct sdio_func *sdio_alloc_func(struct mmc_card *card) 204e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 205e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman struct sdio_func *func; 206e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 207e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func = kmalloc(sizeof(struct sdio_func), GFP_KERNEL); 208e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (!func) 209e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return ERR_PTR(-ENOMEM); 210e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 211e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman memset(func, 0, sizeof(struct sdio_func)); 212e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 213e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->card = card; 214e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 215e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman device_initialize(&func->dev); 216e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 217e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.parent = &card->dev; 218e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.bus = &sdio_bus_type; 219e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman func->dev.release = sdio_release_func; 220e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 221e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return func; 222e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 223e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 224e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 225e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Register a new SDIO function with the driver model. 226e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 227e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanint sdio_add_func(struct sdio_func *func) 228e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 229e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman int ret; 230e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 231e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman snprintf(func->dev.bus_id, sizeof(func->dev.bus_id), 232e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman "%s:%d", mmc_card_id(func->card), func->num); 233e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 234e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman ret = device_add(&func->dev); 235e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (ret == 0) 236e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman sdio_func_set_present(func); 237e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 238e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman return ret; 239e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 240e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 241e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman/* 242e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * Unregister a SDIO function with the driver model, and 243e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman * (eventually) free it. 244e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman */ 245e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossmanvoid sdio_remove_func(struct sdio_func *func) 246e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman{ 247e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman if (sdio_func_present(func)) 248e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman device_del(&func->dev); 249e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 250e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman put_device(&func->dev); 251e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman} 252e29a7d73f4277eb92aa64e17017dea33460828efPierre Ossman 253