1 /* 2 * linux/drivers/mmc/core/host.c 3 * 4 * Copyright (C) 2003 Russell King, All Rights Reserved. 5 * Copyright (C) 2007-2008 Pierre Ossman 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * MMC host class device management 12 */ 13 14 #include <linux/device.h> 15 #include <linux/err.h> 16 #include <linux/idr.h> 17 #include <linux/pagemap.h> 18 #include <linux/leds.h> 19 20 #include <linux/mmc/host.h> 21 22 #include "core.h" 23 #include "host.h" 24 25 #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) 26 27 static void mmc_host_classdev_release(struct device *dev) 28 { 29 struct mmc_host *host = cls_dev_to_mmc_host(dev); 30 kfree(host); 31 } 32 33 static struct class mmc_host_class = { 34 .name = "mmc_host", 35 .dev_release = mmc_host_classdev_release, 36 }; 37 38 int mmc_register_host_class(void) 39 { 40 return class_register(&mmc_host_class); 41 } 42 43 void mmc_unregister_host_class(void) 44 { 45 class_unregister(&mmc_host_class); 46 } 47 48 static DEFINE_IDR(mmc_host_idr); 49 static DEFINE_SPINLOCK(mmc_host_lock); 50 51 /** 52 * mmc_alloc_host - initialise the per-host structure. 53 * @extra: sizeof private data structure 54 * @dev: pointer to host device model structure 55 * 56 * Initialise the per-host structure. 57 */ 58 struct mmc_host *mmc_alloc_host(int extra, struct device *dev) 59 { 60 int err; 61 struct mmc_host *host; 62 63 if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL)) 64 return NULL; 65 66 host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); 67 if (!host) 68 return NULL; 69 70 spin_lock(&mmc_host_lock); 71 err = idr_get_new(&mmc_host_idr, host, &host->index); 72 spin_unlock(&mmc_host_lock); 73 if (err) 74 goto free; 75 76 dev_set_name(&host->class_dev, "mmc%d", host->index); 77 78 host->parent = dev; 79 host->class_dev.parent = dev; 80 host->class_dev.class = &mmc_host_class; 81 device_initialize(&host->class_dev); 82 83 spin_lock_init(&host->lock); 84 init_waitqueue_head(&host->wq); 85 INIT_DELAYED_WORK(&host->detect, mmc_rescan); 86 87 /* 88 * By default, hosts do not support SGIO or large requests. 89 * They have to set these according to their abilities. 90 */ 91 host->max_hw_segs = 1; 92 host->max_phys_segs = 1; 93 host->max_seg_size = PAGE_CACHE_SIZE; 94 95 host->max_req_size = PAGE_CACHE_SIZE; 96 host->max_blk_size = 512; 97 host->max_blk_count = PAGE_CACHE_SIZE / 512; 98 99 return host; 100 101 free: 102 kfree(host); 103 return NULL; 104 } 105 106 EXPORT_SYMBOL(mmc_alloc_host); 107 108 /** 109 * mmc_add_host - initialise host hardware 110 * @host: mmc host 111 * 112 * Register the host with the driver model. The host must be 113 * prepared to start servicing requests before this function 114 * completes. 115 */ 116 int mmc_add_host(struct mmc_host *host) 117 { 118 int err; 119 120 WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) && 121 !host->ops->enable_sdio_irq); 122 123 led_trigger_register_simple(dev_name(&host->class_dev), &host->led); 124 125 err = device_add(&host->class_dev); 126 if (err) 127 return err; 128 129 #ifdef CONFIG_DEBUG_FS 130 mmc_add_host_debugfs(host); 131 #endif 132 133 mmc_start_host(host); 134 135 return 0; 136 } 137 138 EXPORT_SYMBOL(mmc_add_host); 139 140 /** 141 * mmc_remove_host - remove host hardware 142 * @host: mmc host 143 * 144 * Unregister and remove all cards associated with this host, 145 * and power down the MMC bus. No new requests will be issued 146 * after this function has returned. 147 */ 148 void mmc_remove_host(struct mmc_host *host) 149 { 150 mmc_stop_host(host); 151 152 #ifdef CONFIG_DEBUG_FS 153 mmc_remove_host_debugfs(host); 154 #endif 155 156 device_del(&host->class_dev); 157 158 led_trigger_unregister_simple(host->led); 159 } 160 161 EXPORT_SYMBOL(mmc_remove_host); 162 163 /** 164 * mmc_free_host - free the host structure 165 * @host: mmc host 166 * 167 * Free the host once all references to it have been dropped. 168 */ 169 void mmc_free_host(struct mmc_host *host) 170 { 171 spin_lock(&mmc_host_lock); 172 idr_remove(&mmc_host_idr, host->index); 173 spin_unlock(&mmc_host_lock); 174 175 put_device(&host->class_dev); 176 } 177 178 EXPORT_SYMBOL(mmc_free_host); 179 180