Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 #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         struct mmc_host *host;
 61 
 62         host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
 63         if (!host)
 64                 return NULL;
 65 
 66         host->parent = dev;
 67         host->class_dev.parent = dev;
 68         host->class_dev.class = &mmc_host_class;
 69         device_initialize(&host->class_dev);
 70 
 71         spin_lock_init(&host->lock);
 72         init_waitqueue_head(&host->wq);
 73         INIT_DELAYED_WORK(&host->detect, mmc_rescan);
 74 
 75         /*
 76          * By default, hosts do not support SGIO or large requests.
 77          * They have to set these according to their abilities.
 78          */
 79         host->max_hw_segs = 1;
 80         host->max_phys_segs = 1;
 81         host->max_seg_size = PAGE_CACHE_SIZE;
 82 
 83         host->max_req_size = PAGE_CACHE_SIZE;
 84         host->max_blk_size = 512;
 85         host->max_blk_count = PAGE_CACHE_SIZE / 512;
 86 
 87         return host;
 88 }
 89 
 90 EXPORT_SYMBOL(mmc_alloc_host);
 91 
 92 /**
 93  *      mmc_add_host - initialise host hardware
 94  *      @host: mmc host
 95  *
 96  *      Register the host with the driver model. The host must be
 97  *      prepared to start servicing requests before this function
 98  *      completes.
 99  */
100 int mmc_add_host(struct mmc_host *host)
101 {
102         int err;
103 
104         WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
105                 !host->ops->enable_sdio_irq);
106 
107         if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
108                 return -ENOMEM;
109 
110         spin_lock(&mmc_host_lock);
111         err = idr_get_new(&mmc_host_idr, host, &host->index);
112         spin_unlock(&mmc_host_lock);
113         if (err)
114                 return err;
115 
116         snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
117                  "mmc%d", host->index);
118 
119         led_trigger_register_simple(host->class_dev.bus_id, &host->led);
120 
121         err = device_add(&host->class_dev);
122         if (err)
123                 return err;
124 
125         mmc_start_host(host);
126 
127         return 0;
128 }
129 
130 EXPORT_SYMBOL(mmc_add_host);
131 
132 /**
133  *      mmc_remove_host - remove host hardware
134  *      @host: mmc host
135  *
136  *      Unregister and remove all cards associated with this host,
137  *      and power down the MMC bus. No new requests will be issued
138  *      after this function has returned.
139  */
140 void mmc_remove_host(struct mmc_host *host)
141 {
142         mmc_stop_host(host);
143 
144         device_del(&host->class_dev);
145 
146         led_trigger_unregister_simple(host->led);
147 
148         spin_lock(&mmc_host_lock);
149         idr_remove(&mmc_host_idr, host->index);
150         spin_unlock(&mmc_host_lock);
151 }
152 
153 EXPORT_SYMBOL(mmc_remove_host);
154 
155 /**
156  *      mmc_free_host - free the host structure
157  *      @host: mmc host
158  *
159  *      Free the host once all references to it have been dropped.
160  */
161 void mmc_free_host(struct mmc_host *host)
162 {
163         put_device(&host->class_dev);
164 }
165 
166 EXPORT_SYMBOL(mmc_free_host);
167 
168 
  This page was automatically generated by the LXR engine.