aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2007-05-19 08:06:24 -0400
committerPierre Ossman <drzeus@drzeus.cx>2007-07-09 15:28:01 -0400
commitb93931a61a119575f84c33af2438b9384fde9eb7 (patch)
treef424d886c1ef255bfa3d3ca60ae245491e7f9432 /drivers
parent4101c16a910b15afd190c6bc7d45864461cf5c25 (diff)
mmc: refactor host class handling
Move basic host class device handling to its own file for clarity. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/core/Makefile2
-rw-r--r--drivers/mmc/core/core.c82
-rw-r--r--drivers/mmc/core/core.h4
-rw-r--r--drivers/mmc/core/host.c156
-rw-r--r--drivers/mmc/core/host.h18
-rw-r--r--drivers/mmc/core/sysfs.c84
-rw-r--r--drivers/mmc/core/sysfs.h5
7 files changed, 187 insertions, 164 deletions
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 54261e3724c4..3fdd08c7f143 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -7,6 +7,6 @@ ifeq ($(CONFIG_MMC_DEBUG),y)
7endif 7endif
8 8
9obj-$(CONFIG_MMC) += mmc_core.o 9obj-$(CONFIG_MMC) += mmc_core.o
10mmc_core-y := core.o sysfs.o bus.o \ 10mmc_core-y := core.o sysfs.o bus.o host.o \
11 mmc.o mmc_ops.o sd.o sd_ops.o 11 mmc.o mmc_ops.o sd.o sd_ops.o
12 12
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d876adf4bd4e..66e463d100c5 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -496,7 +496,7 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay)
496EXPORT_SYMBOL(mmc_detect_change); 496EXPORT_SYMBOL(mmc_detect_change);
497 497
498 498
499static void mmc_rescan(struct work_struct *work) 499void mmc_rescan(struct work_struct *work)
500{ 500{
501 struct mmc_host *host = 501 struct mmc_host *host =
502 container_of(work, struct mmc_host, detect.work); 502 container_of(work, struct mmc_host, detect.work);
@@ -545,69 +545,13 @@ static void mmc_rescan(struct work_struct *work)
545 } 545 }
546} 546}
547 547
548 548void mmc_start_host(struct mmc_host *host)
549/**
550 * mmc_alloc_host - initialise the per-host structure.
551 * @extra: sizeof private data structure
552 * @dev: pointer to host device model structure
553 *
554 * Initialise the per-host structure.
555 */
556struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
557{
558 struct mmc_host *host;
559
560 host = mmc_alloc_host_sysfs(extra, dev);
561 if (host) {
562 spin_lock_init(&host->lock);
563 init_waitqueue_head(&host->wq);
564 INIT_DELAYED_WORK(&host->detect, mmc_rescan);
565
566 /*
567 * By default, hosts do not support SGIO or large requests.
568 * They have to set these according to their abilities.
569 */
570 host->max_hw_segs = 1;
571 host->max_phys_segs = 1;
572 host->max_seg_size = PAGE_CACHE_SIZE;
573
574 host->max_req_size = PAGE_CACHE_SIZE;
575 host->max_blk_size = 512;
576 host->max_blk_count = PAGE_CACHE_SIZE / 512;
577 }
578
579 return host;
580}
581
582EXPORT_SYMBOL(mmc_alloc_host);
583
584/**
585 * mmc_add_host - initialise host hardware
586 * @host: mmc host
587 */
588int mmc_add_host(struct mmc_host *host)
589{ 549{
590 int ret; 550 mmc_power_off(host);
591 551 mmc_detect_change(host, 0);
592 ret = mmc_add_host_sysfs(host);
593 if (ret == 0) {
594 mmc_power_off(host);
595 mmc_detect_change(host, 0);
596 }
597
598 return ret;
599} 552}
600 553
601EXPORT_SYMBOL(mmc_add_host); 554void mmc_stop_host(struct mmc_host *host)
602
603/**
604 * mmc_remove_host - remove host hardware
605 * @host: mmc host
606 *
607 * Unregister and remove all cards associated with this host,
608 * and power down the MMC bus.
609 */
610void mmc_remove_host(struct mmc_host *host)
611{ 555{
612#ifdef CONFIG_MMC_DEBUG 556#ifdef CONFIG_MMC_DEBUG
613 unsigned long flags; 557 unsigned long flags;
@@ -632,24 +576,8 @@ void mmc_remove_host(struct mmc_host *host)
632 BUG_ON(host->card); 576 BUG_ON(host->card);
633 577
634 mmc_power_off(host); 578 mmc_power_off(host);
635 mmc_remove_host_sysfs(host);
636} 579}
637 580
638EXPORT_SYMBOL(mmc_remove_host);
639
640/**
641 * mmc_free_host - free the host structure
642 * @host: mmc host
643 *
644 * Free the host once all references to it have been dropped.
645 */
646void mmc_free_host(struct mmc_host *host)
647{
648 mmc_free_host_sysfs(host);
649}
650
651EXPORT_SYMBOL(mmc_free_host);
652
653#ifdef CONFIG_PM 581#ifdef CONFIG_PM
654 582
655/** 583/**
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 1be86c792a52..ae006b30dd86 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -66,5 +66,9 @@ static inline void mmc_delay(unsigned int ms)
66 } 66 }
67} 67}
68 68
69void mmc_rescan(struct work_struct *work);
70void mmc_start_host(struct mmc_host *host);
71void mmc_stop_host(struct mmc_host *host);
72
69#endif 73#endif
70 74
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
new file mode 100644
index 000000000000..1433d95c40bb
--- /dev/null
+++ b/drivers/mmc/core/host.c
@@ -0,0 +1,156 @@
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
26static 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
32static struct class mmc_host_class = {
33 .name = "mmc_host",
34 .dev_release = mmc_host_classdev_release,
35};
36
37int mmc_register_host_class(void)
38{
39 return class_register(&mmc_host_class);
40}
41
42void mmc_unregister_host_class(void)
43{
44 class_unregister(&mmc_host_class);
45}
46
47static DEFINE_IDR(mmc_host_idr);
48static 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 */
57struct 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
91EXPORT_SYMBOL(mmc_alloc_host);
92
93/**
94 * mmc_add_host - initialise host hardware
95 * @host: mmc host
96 */
97int mmc_add_host(struct mmc_host *host)
98{
99 int err;
100
101 if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
102 return -ENOMEM;
103
104 spin_lock(&mmc_host_lock);
105 err = idr_get_new(&mmc_host_idr, host, &host->index);
106 spin_unlock(&mmc_host_lock);
107 if (err)
108 return err;
109
110 snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
111 "mmc%d", host->index);
112
113 err = device_add(&host->class_dev);
114 if (err)
115 return err;
116
117 mmc_start_host(host);
118
119 return 0;
120}
121
122EXPORT_SYMBOL(mmc_add_host);
123
124/**
125 * mmc_remove_host - remove host hardware
126 * @host: mmc host
127 *
128 * Unregister and remove all cards associated with this host,
129 * and power down the MMC bus.
130 */
131void mmc_remove_host(struct mmc_host *host)
132{
133 mmc_stop_host(host);
134
135 device_del(&host->class_dev);
136
137 spin_lock(&mmc_host_lock);
138 idr_remove(&mmc_host_idr, host->index);
139 spin_unlock(&mmc_host_lock);
140}
141
142EXPORT_SYMBOL(mmc_remove_host);
143
144/**
145 * mmc_free_host - free the host structure
146 * @host: mmc host
147 *
148 * Free the host once all references to it have been dropped.
149 */
150void mmc_free_host(struct mmc_host *host)
151{
152 put_device(&host->class_dev);
153}
154
155EXPORT_SYMBOL(mmc_free_host);
156
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
new file mode 100644
index 000000000000..c2dc3d2d9f9a
--- /dev/null
+++ b/drivers/mmc/core/host.h
@@ -0,0 +1,18 @@
1/*
2 * linux/drivers/mmc/core/host.h
3 *
4 * Copyright (C) 2003 Russell King, All Rights Reserved.
5 * Copyright 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#ifndef _MMC_CORE_HOST_H
12#define _MMC_CORE_HOST_H
13
14int mmc_register_host_class(void);
15void mmc_unregister_host_class(void);
16
17#endif
18
diff --git a/drivers/mmc/core/sysfs.c b/drivers/mmc/core/sysfs.c
index a43a96c22811..fbf99f9a0b83 100644
--- a/drivers/mmc/core/sysfs.c
+++ b/drivers/mmc/core/sysfs.c
@@ -20,11 +20,9 @@
20#include <linux/mmc/host.h> 20#include <linux/mmc/host.h>
21 21
22#include "bus.h" 22#include "bus.h"
23#include "host.h"
23#include "sysfs.h" 24#include "sysfs.h"
24 25
25#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
26#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
27
28int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs) 26int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs)
29{ 27{
30 int error = 0; 28 int error = 0;
@@ -50,82 +48,6 @@ void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs)
50 device_remove_file(&card->dev, &attrs[i]); 48 device_remove_file(&card->dev, &attrs[i]);
51} 49}
52 50
53static void mmc_host_classdev_release(struct device *dev)
54{
55 struct mmc_host *host = cls_dev_to_mmc_host(dev);
56 kfree(host);
57}
58
59static struct class mmc_host_class = {
60 .name = "mmc_host",
61 .dev_release = mmc_host_classdev_release,
62};
63
64static DEFINE_IDR(mmc_host_idr);
65static DEFINE_SPINLOCK(mmc_host_lock);
66
67/*
68 * Internal function. Allocate a new MMC host.
69 */
70struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
71{
72 struct mmc_host *host;
73
74 host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
75 if (host) {
76 memset(host, 0, sizeof(struct mmc_host) + extra);
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
84 return host;
85}
86
87/*
88 * Internal function. Register a new MMC host with the MMC class.
89 */
90int mmc_add_host_sysfs(struct mmc_host *host)
91{
92 int err;
93
94 if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
95 return -ENOMEM;
96
97 spin_lock(&mmc_host_lock);
98 err = idr_get_new(&mmc_host_idr, host, &host->index);
99 spin_unlock(&mmc_host_lock);
100 if (err)
101 return err;
102
103 snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
104 "mmc%d", host->index);
105
106 return device_add(&host->class_dev);
107}
108
109/*
110 * Internal function. Unregister a MMC host with the MMC class.
111 */
112void mmc_remove_host_sysfs(struct mmc_host *host)
113{
114 device_del(&host->class_dev);
115
116 spin_lock(&mmc_host_lock);
117 idr_remove(&mmc_host_idr, host->index);
118 spin_unlock(&mmc_host_lock);
119}
120
121/*
122 * Internal function. Free a MMC host.
123 */
124void mmc_free_host_sysfs(struct mmc_host *host)
125{
126 put_device(&host->class_dev);
127}
128
129static struct workqueue_struct *workqueue; 51static struct workqueue_struct *workqueue;
130 52
131/* 53/*
@@ -154,7 +76,7 @@ static int __init mmc_init(void)
154 76
155 ret = mmc_register_bus(); 77 ret = mmc_register_bus();
156 if (ret == 0) { 78 if (ret == 0) {
157 ret = class_register(&mmc_host_class); 79 ret = mmc_register_host_class();
158 if (ret) 80 if (ret)
159 mmc_unregister_bus(); 81 mmc_unregister_bus();
160 } 82 }
@@ -163,7 +85,7 @@ static int __init mmc_init(void)
163 85
164static void __exit mmc_exit(void) 86static void __exit mmc_exit(void)
165{ 87{
166 class_unregister(&mmc_host_class); 88 mmc_unregister_host_class();
167 mmc_unregister_bus(); 89 mmc_unregister_bus();
168 destroy_workqueue(workqueue); 90 destroy_workqueue(workqueue);
169} 91}
diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h
index 2a326a5b83c6..2f60c79b203b 100644
--- a/drivers/mmc/core/sysfs.h
+++ b/drivers/mmc/core/sysfs.h
@@ -23,11 +23,6 @@ static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *a
23int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs); 23int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs);
24void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs); 24void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs);
25 25
26struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
27int mmc_add_host_sysfs(struct mmc_host *host);
28void mmc_remove_host_sysfs(struct mmc_host *host);
29void mmc_free_host_sysfs(struct mmc_host *host);
30
31int mmc_schedule_work(struct work_struct *work); 26int mmc_schedule_work(struct work_struct *work);
32int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay); 27int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
33void mmc_flush_scheduled_work(void); 28void mmc_flush_scheduled_work(void);