···2929#include "core.h"3030#include "bus.h"3131#include "host.h"3232+#include "sdio_bus.h"32333334#include "mmc_ops.h"3435#include "sd_ops.h"···740739 return -ENOMEM;741740742741 ret = mmc_register_bus();743743- if (ret == 0) {744744- ret = mmc_register_host_class();745745- if (ret)746746- mmc_unregister_bus();747747- }742742+ if (ret)743743+ goto destroy_workqueue;744744+745745+ ret = mmc_register_host_class();746746+ if (ret)747747+ goto unregister_bus;748748+749749+ ret = sdio_register_bus();750750+ if (ret)751751+ goto unregister_host_class;752752+753753+ return 0;754754+755755+unregister_host_class:756756+ mmc_unregister_host_class();757757+unregister_bus:758758+ mmc_unregister_bus();759759+destroy_workqueue:760760+ destroy_workqueue(workqueue);761761+748762 return ret;749763}750764751765static void __exit mmc_exit(void)752766{767767+ sdio_unregister_bus();753768 mmc_unregister_host_class();754769 mmc_unregister_bus();755770 destroy_workqueue(workqueue);
+63-9
drivers/mmc/core/sdio.c
···13131414#include <linux/mmc/host.h>1515#include <linux/mmc/card.h>1616+#include <linux/mmc/sdio_func.h>16171718#include "core.h"1819#include "bus.h"2020+#include "sdio_bus.h"1921#include "mmc_ops.h"2022#include "sd_ops.h"2123#include "sdio_ops.h"2424+2525+static int sdio_init_func(struct mmc_card *card, unsigned int fn)2626+{2727+ struct sdio_func *func;2828+2929+ BUG_ON(fn > SDIO_MAX_FUNCS);3030+3131+ func = sdio_alloc_func(card);3232+ if (IS_ERR(func))3333+ return PTR_ERR(func);3434+3535+ func->num = fn;3636+3737+ card->sdio_func[fn - 1] = func;3838+3939+ return 0;4040+}22412342/*2443 * Host is being removed. Free up the current card.2544 */2645static void mmc_sdio_remove(struct mmc_host *host)2746{4747+ int i;4848+2849 BUG_ON(!host);2950 BUG_ON(!host->card);5151+5252+ for (i = 0;i < host->card->sdio_funcs;i++) {5353+ if (host->card->sdio_func[i]) {5454+ sdio_remove_func(host->card->sdio_func[i]);5555+ host->card->sdio_func[i] = NULL;5656+ }5757+ }30583159 mmc_remove_card(host->card);3260 host->card = NULL;···10173int mmc_attach_sdio(struct mmc_host *host, u32 ocr)10274{10375 int err;104104- int funcs;7676+ int i, funcs;10577 struct mmc_card *card;1067810779 BUG_ON(!host);···160132 }161133162134 card->type = MMC_TYPE_SDIO;135135+ card->sdio_funcs = funcs;136136+137137+ host->card = card;163138164139 /*165140 * Set card RCA.166141 */167142 err = mmc_send_relative_addr(host, &card->rca);168143 if (err)169169- goto free_card;144144+ goto remove;170145171146 mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);172147···178147 */179148 err = mmc_select_card(card);180149 if (err)181181- goto free_card;150150+ goto remove;182151183183- host->card = card;152152+ /*153153+ * Initialize (but don't add) all present functions.154154+ */155155+ for (i = 0;i < funcs;i++) {156156+ err = sdio_init_func(host->card, i + 1);157157+ if (err)158158+ goto remove;159159+ }184160185161 mmc_release_host(host);186162163163+ /*164164+ * First add the card to the driver model...165165+ */187166 err = mmc_add_card(host->card);188167 if (err)189189- goto reclaim_host;168168+ goto remove_added;169169+170170+ /*171171+ * ...then the SDIO functions.172172+ */173173+ for (i = 0;i < funcs;i++) {174174+ err = sdio_add_func(host->card->sdio_func[i]);175175+ if (err)176176+ goto remove_added;177177+ }190178191179 return 0;192180193193-reclaim_host:181181+182182+remove_added:183183+ /* Remove without lock if the device has been added. */184184+ mmc_sdio_remove(host);194185 mmc_claim_host(host);195195-free_card:196196- mmc_remove_card(card);197197- host->card = NULL;186186+remove:187187+ /* And with lock if it hasn't been added. */188188+ if (host->card)189189+ mmc_sdio_remove(host);198190err:199191 mmc_detach_bus(host);200192 mmc_release_host(host);
+129
drivers/mmc/core/sdio_bus.c
···11+/*22+ * linux/drivers/mmc/core/sdio_bus.c33+ *44+ * Copyright 2007 Pierre Ossman55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or (at99+ * your option) any later version.1010+ *1111+ * SDIO function driver model1212+ */1313+1414+#include <linux/device.h>1515+#include <linux/err.h>1616+1717+#include <linux/mmc/card.h>1818+#include <linux/mmc/sdio_func.h>1919+2020+#include "sdio_bus.h"2121+2222+#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev)2323+2424+/*2525+ * This currently matches any SDIO function to any driver in order2626+ * to help initial development and testing.2727+ */2828+static int sdio_bus_match(struct device *dev, struct device_driver *drv)2929+{3030+ return 1;3131+}3232+3333+static int3434+sdio_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,3535+ int buf_size)3636+{3737+ envp[0] = NULL;3838+3939+ return 0;4040+}4141+4242+static int sdio_bus_probe(struct device *dev)4343+{4444+ return -ENODEV;4545+}4646+4747+static int sdio_bus_remove(struct device *dev)4848+{4949+ return 0;5050+}5151+5252+static struct bus_type sdio_bus_type = {5353+ .name = "sdio",5454+ .match = sdio_bus_match,5555+ .uevent = sdio_bus_uevent,5656+ .probe = sdio_bus_probe,5757+ .remove = sdio_bus_remove,5858+};5959+6060+int sdio_register_bus(void)6161+{6262+ return bus_register(&sdio_bus_type);6363+}6464+6565+void sdio_unregister_bus(void)6666+{6767+ bus_unregister(&sdio_bus_type);6868+}6969+7070+static void sdio_release_func(struct device *dev)7171+{7272+ struct sdio_func *func = dev_to_sdio_func(dev);7373+7474+ kfree(func);7575+}7676+7777+/*7878+ * Allocate and initialise a new SDIO function structure.7979+ */8080+struct sdio_func *sdio_alloc_func(struct mmc_card *card)8181+{8282+ struct sdio_func *func;8383+8484+ func = kmalloc(sizeof(struct sdio_func), GFP_KERNEL);8585+ if (!func)8686+ return ERR_PTR(-ENOMEM);8787+8888+ memset(func, 0, sizeof(struct sdio_func));8989+9090+ func->card = card;9191+9292+ device_initialize(&func->dev);9393+9494+ func->dev.parent = &card->dev;9595+ func->dev.bus = &sdio_bus_type;9696+ func->dev.release = sdio_release_func;9797+9898+ return func;9999+}100100+101101+/*102102+ * Register a new SDIO function with the driver model.103103+ */104104+int sdio_add_func(struct sdio_func *func)105105+{106106+ int ret;107107+108108+ snprintf(func->dev.bus_id, sizeof(func->dev.bus_id),109109+ "%s:%d", mmc_card_id(func->card), func->num);110110+111111+ ret = device_add(&func->dev);112112+ if (ret == 0)113113+ sdio_func_set_present(func);114114+115115+ return ret;116116+}117117+118118+/*119119+ * Unregister a SDIO function with the driver model, and120120+ * (eventually) free it.121121+ */122122+void sdio_remove_func(struct sdio_func *func)123123+{124124+ if (sdio_func_present(func))125125+ device_del(&func->dev);126126+127127+ put_device(&func->dev);128128+}129129+
+22
drivers/mmc/core/sdio_bus.h
···11+/*22+ * linux/drivers/mmc/core/sdio_bus.h33+ *44+ * Copyright 2007 Pierre Ossman55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or (at99+ * your option) any later version.1010+ */1111+#ifndef _MMC_CORE_SDIO_BUS_H1212+#define _MMC_CORE_SDIO_BUS_H1313+1414+struct sdio_func *sdio_alloc_func(struct mmc_card *card);1515+int sdio_add_func(struct sdio_func *func);1616+void sdio_remove_func(struct sdio_func *func);1717+1818+int sdio_register_bus(void);1919+void sdio_unregister_bus(void);2020+2121+#endif2222+
+7
include/linux/mmc/card.h
···5656};57575858struct mmc_host;5959+struct sdio_func;6060+6161+#define SDIO_MAX_FUNCS 759626063/*6164 * MMC device···7673#define MMC_STATE_READONLY (1<<1) /* card is read-only */7774#define MMC_STATE_HIGHSPEED (1<<2) /* card is in high speed mode */7875#define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */7676+7977 u32 raw_cid[4]; /* raw card CID */8078 u32 raw_csd[4]; /* raw card CSD */8179 u32 raw_scr[2]; /* raw card SCR */···8581 struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */8682 struct sd_scr scr; /* extra SD information */8783 struct sd_switch_caps sw_caps; /* switch (CMD6) caps */8484+8585+ unsigned int sdio_funcs; /* number of SDIO functions */8686+ struct sdio_func *sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */8887};89889089#define mmc_card_mmc(c) ((c)->type == MMC_TYPE_MMC)
+35
include/linux/mmc/sdio_func.h
···11+/*22+ * include/linux/mmc/sdio_func.h33+ *44+ * Copyright 2007 Pierre Ossman55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or (at99+ * your option) any later version.1010+ */1111+1212+#ifndef MMC_SDIO_FUNC_H1313+#define MMC_SDIO_FUNC_H1414+1515+struct mmc_card;1616+1717+/*1818+ * SDIO function devices1919+ */2020+struct sdio_func {2121+ struct mmc_card *card; /* the card this device belongs to */2222+ struct device dev; /* the device */2323+ unsigned int num; /* function number */2424+ unsigned int state; /* function state */2525+#define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */2626+};2727+2828+#define sdio_func_present(f) ((f)->state & SDIO_STATE_PRESENT)2929+3030+#define sdio_func_set_present(f) ((f)->state |= SDIO_STATE_PRESENT)3131+3232+#define sdio_func_id(f) ((f)->dev.bus_id)3333+3434+#endif3535+