1 /* 2 * linux/drivers/mmc/core/host.c 3 * 4 * Copyright (C) 2003 Russell King, All Rights Reserved. 5 * Copyright (C) 2007 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 19 #include <linux/mmc/host.h> 20 21 #include "core.h" 22 #include "host.h" 23 24 #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) 25 26 static void mmc_host_classdev_release(struct device *dev) 27 { 28 struct mmc_host *host = cls_dev_to_mmc_host(dev); 29 kfree(host); 30 } 31 32 static struct class mmc_host_class = { 33 .name = "mmc_host", 34 .dev_release = mmc_host_classdev_release, 35 }; 36 37 int mmc_register_host_class(void) 38 { 39 return class_register(&mmc_host_class); 40 } 41 42 void mmc_unregister_host_class(void) 43 { 44 class_unregister(&mmc_host_class); 45 } 46 47 static DEFINE_IDR(mmc_host_idr); 48 static DEFINE_SPINLOCK(mmc_host_lock); 49 50 /** 51 * mmc_alloc_host - initialise the per-host structure. 52 * @extra: sizeof private data structure 53 * @dev: pointer to host device model structure 54 * 55 * Initialise the per-host structure. 56 */ 57 struct mmc_host *mmc_alloc_host(int extra, struct device *dev) 58 { 59 struct mmc_host *host; 60 61 host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); 62 if (!host) 63 return NULL; 64 65 memset(host, 0, sizeof(struct mmc_host) + extra); 66 67 host->parent = dev; 68 host->class_dev.parent = dev; 69 host->class_dev.class = &mmc_host_class; 70 device_initialize(&host->class_dev); 71 72 spin_lock_init(&host->lock); 73 init_waitqueue_head(&host->wq); 74 INIT_DELAYED_WORK(&host->detect, mmc_rescan); 75 76 /* 77 * By default, hosts do not support SGIO or large requests. 78 * They have to set these according to their abilities. 79 */ 80 host->max_hw_segs = 1; 81 host->max_phys_segs = 1; 82 host->max_seg_size = PAGE_CACHE_SIZE; 83 84 host->max_req_size = PAGE_CACHE_SIZE; 85 host->max_blk_size = 512; 86 host->max_blk_count = PAGE_CACHE_SIZE / 512; 87 88 return host; 89 } 90 91 EXPORT_SYMBOL(mmc_alloc_host); 92 93 /** 94 * mmc_add_host - initialise host hardware 95 * @host: mmc host 96 * 97 * Register the host with the driver model. The host must be 98 * prepared to start servicing requests before this function 99 * completes. 100 */ 101 int mmc_add_host(struct mmc_host *host) 102 { 103 int err; 104 105 if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL)) 106 return -ENOMEM; 107 108 spin_lock(&mmc_host_lock); 109 err = idr_get_new(&mmc_host_idr, host, &host->index); 110 spin_unlock(&mmc_host_lock); 111 if (err) 112 return err; 113 114 snprintf(host->class_dev.bus_id, BUS_ID_SIZE, 115 "mmc%d", host->index); 116 117 err = device_add(&host->class_dev); 118 if (err) 119 return err; 120 121 mmc_start_host(host); 122 123 return 0; 124 } 125 126 EXPORT_SYMBOL(mmc_add_host); 127 128 /** 129 * mmc_remove_host - remove host hardware 130 * @host: mmc host 131 * 132 * Unregister and remove all cards associated with this host, 133 * and power down the MMC bus. No new requests will be issued 134 * after this function has returned. 135 */ 136 void mmc_remove_host(struct mmc_host *host) 137 { 138 mmc_stop_host(host); 139 140 device_del(&host->class_dev); 141 142 spin_lock(&mmc_host_lock); 143 idr_remove(&mmc_host_idr, host->index); 144 spin_unlock(&mmc_host_lock); 145 } 146 147 EXPORT_SYMBOL(mmc_remove_host); 148 149 /** 150 * mmc_free_host - free the host structure 151 * @host: mmc host 152 * 153 * Free the host once all references to it have been dropped. 154 */ 155 void mmc_free_host(struct mmc_host *host) 156 { 157 put_device(&host->class_dev); 158 } 159 160 EXPORT_SYMBOL(mmc_free_host); 161 162