Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/mmc/core/sdio_bus.c
15109 views
1
/*
2
* linux/drivers/mmc/core/sdio_bus.c
3
*
4
* Copyright 2007 Pierre Ossman
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or (at
9
* your option) any later version.
10
*
11
* SDIO function driver model
12
*/
13
14
#include <linux/device.h>
15
#include <linux/err.h>
16
#include <linux/slab.h>
17
#include <linux/pm_runtime.h>
18
19
#include <linux/mmc/card.h>
20
#include <linux/mmc/host.h>
21
#include <linux/mmc/sdio_func.h>
22
23
#include "sdio_cis.h"
24
#include "sdio_bus.h"
25
26
/* show configuration fields */
27
#define sdio_config_attr(field, format_string) \
28
static ssize_t \
29
field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
30
{ \
31
struct sdio_func *func; \
32
\
33
func = dev_to_sdio_func (dev); \
34
return sprintf (buf, format_string, func->field); \
35
}
36
37
sdio_config_attr(class, "0x%02x\n");
38
sdio_config_attr(vendor, "0x%04x\n");
39
sdio_config_attr(device, "0x%04x\n");
40
41
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
42
{
43
struct sdio_func *func = dev_to_sdio_func (dev);
44
45
return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n",
46
func->class, func->vendor, func->device);
47
}
48
49
static struct device_attribute sdio_dev_attrs[] = {
50
__ATTR_RO(class),
51
__ATTR_RO(vendor),
52
__ATTR_RO(device),
53
__ATTR_RO(modalias),
54
__ATTR_NULL,
55
};
56
57
static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,
58
const struct sdio_device_id *id)
59
{
60
if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class)
61
return NULL;
62
if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor)
63
return NULL;
64
if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device)
65
return NULL;
66
return id;
67
}
68
69
static const struct sdio_device_id *sdio_match_device(struct sdio_func *func,
70
struct sdio_driver *sdrv)
71
{
72
const struct sdio_device_id *ids;
73
74
ids = sdrv->id_table;
75
76
if (ids) {
77
while (ids->class || ids->vendor || ids->device) {
78
if (sdio_match_one(func, ids))
79
return ids;
80
ids++;
81
}
82
}
83
84
return NULL;
85
}
86
87
static int sdio_bus_match(struct device *dev, struct device_driver *drv)
88
{
89
struct sdio_func *func = dev_to_sdio_func(dev);
90
struct sdio_driver *sdrv = to_sdio_driver(drv);
91
92
if (sdio_match_device(func, sdrv))
93
return 1;
94
95
return 0;
96
}
97
98
static int
99
sdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
100
{
101
struct sdio_func *func = dev_to_sdio_func(dev);
102
103
if (add_uevent_var(env,
104
"SDIO_CLASS=%02X", func->class))
105
return -ENOMEM;
106
107
if (add_uevent_var(env,
108
"SDIO_ID=%04X:%04X", func->vendor, func->device))
109
return -ENOMEM;
110
111
if (add_uevent_var(env,
112
"MODALIAS=sdio:c%02Xv%04Xd%04X",
113
func->class, func->vendor, func->device))
114
return -ENOMEM;
115
116
return 0;
117
}
118
119
static int sdio_bus_probe(struct device *dev)
120
{
121
struct sdio_driver *drv = to_sdio_driver(dev->driver);
122
struct sdio_func *func = dev_to_sdio_func(dev);
123
const struct sdio_device_id *id;
124
int ret;
125
126
id = sdio_match_device(func, drv);
127
if (!id)
128
return -ENODEV;
129
130
/* Unbound SDIO functions are always suspended.
131
* During probe, the function is set active and the usage count
132
* is incremented. If the driver supports runtime PM,
133
* it should call pm_runtime_put_noidle() in its probe routine and
134
* pm_runtime_get_noresume() in its remove routine.
135
*/
136
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
137
ret = pm_runtime_get_sync(dev);
138
if (ret < 0)
139
goto out;
140
}
141
142
/* Set the default block size so the driver is sure it's something
143
* sensible. */
144
sdio_claim_host(func);
145
ret = sdio_set_block_size(func, 0);
146
sdio_release_host(func);
147
if (ret)
148
goto disable_runtimepm;
149
150
ret = drv->probe(func, id);
151
if (ret)
152
goto disable_runtimepm;
153
154
return 0;
155
156
disable_runtimepm:
157
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
158
pm_runtime_put_noidle(dev);
159
out:
160
return ret;
161
}
162
163
static int sdio_bus_remove(struct device *dev)
164
{
165
struct sdio_driver *drv = to_sdio_driver(dev->driver);
166
struct sdio_func *func = dev_to_sdio_func(dev);
167
int ret = 0;
168
169
/* Make sure card is powered before invoking ->remove() */
170
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
171
ret = pm_runtime_get_sync(dev);
172
if (ret < 0)
173
goto out;
174
}
175
176
drv->remove(func);
177
178
if (func->irq_handler) {
179
printk(KERN_WARNING "WARNING: driver %s did not remove "
180
"its interrupt handler!\n", drv->name);
181
sdio_claim_host(func);
182
sdio_release_irq(func);
183
sdio_release_host(func);
184
}
185
186
/* First, undo the increment made directly above */
187
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
188
pm_runtime_put_noidle(dev);
189
190
/* Then undo the runtime PM settings in sdio_bus_probe() */
191
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
192
pm_runtime_put_sync(dev);
193
194
out:
195
return ret;
196
}
197
198
#ifdef CONFIG_PM_RUNTIME
199
200
static const struct dev_pm_ops sdio_bus_pm_ops = {
201
SET_RUNTIME_PM_OPS(
202
pm_generic_runtime_suspend,
203
pm_generic_runtime_resume,
204
pm_generic_runtime_idle
205
)
206
};
207
208
#define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops)
209
210
#else /* !CONFIG_PM_RUNTIME */
211
212
#define SDIO_PM_OPS_PTR NULL
213
214
#endif /* !CONFIG_PM_RUNTIME */
215
216
static struct bus_type sdio_bus_type = {
217
.name = "sdio",
218
.dev_attrs = sdio_dev_attrs,
219
.match = sdio_bus_match,
220
.uevent = sdio_bus_uevent,
221
.probe = sdio_bus_probe,
222
.remove = sdio_bus_remove,
223
.pm = SDIO_PM_OPS_PTR,
224
};
225
226
int sdio_register_bus(void)
227
{
228
return bus_register(&sdio_bus_type);
229
}
230
231
void sdio_unregister_bus(void)
232
{
233
bus_unregister(&sdio_bus_type);
234
}
235
236
/**
237
* sdio_register_driver - register a function driver
238
* @drv: SDIO function driver
239
*/
240
int sdio_register_driver(struct sdio_driver *drv)
241
{
242
drv->drv.name = drv->name;
243
drv->drv.bus = &sdio_bus_type;
244
return driver_register(&drv->drv);
245
}
246
EXPORT_SYMBOL_GPL(sdio_register_driver);
247
248
/**
249
* sdio_unregister_driver - unregister a function driver
250
* @drv: SDIO function driver
251
*/
252
void sdio_unregister_driver(struct sdio_driver *drv)
253
{
254
drv->drv.bus = &sdio_bus_type;
255
driver_unregister(&drv->drv);
256
}
257
EXPORT_SYMBOL_GPL(sdio_unregister_driver);
258
259
static void sdio_release_func(struct device *dev)
260
{
261
struct sdio_func *func = dev_to_sdio_func(dev);
262
263
sdio_free_func_cis(func);
264
265
if (func->info)
266
kfree(func->info);
267
268
kfree(func);
269
}
270
271
/*
272
* Allocate and initialise a new SDIO function structure.
273
*/
274
struct sdio_func *sdio_alloc_func(struct mmc_card *card)
275
{
276
struct sdio_func *func;
277
278
func = kzalloc(sizeof(struct sdio_func), GFP_KERNEL);
279
if (!func)
280
return ERR_PTR(-ENOMEM);
281
282
func->card = card;
283
284
device_initialize(&func->dev);
285
286
func->dev.parent = &card->dev;
287
func->dev.bus = &sdio_bus_type;
288
func->dev.release = sdio_release_func;
289
290
return func;
291
}
292
293
/*
294
* Register a new SDIO function with the driver model.
295
*/
296
int sdio_add_func(struct sdio_func *func)
297
{
298
int ret;
299
300
dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
301
302
ret = device_add(&func->dev);
303
if (ret == 0)
304
sdio_func_set_present(func);
305
306
return ret;
307
}
308
309
/*
310
* Unregister a SDIO function with the driver model, and
311
* (eventually) free it.
312
* This function can be called through error paths where sdio_add_func() was
313
* never executed (because a failure occurred at an earlier point).
314
*/
315
void sdio_remove_func(struct sdio_func *func)
316
{
317
if (!sdio_func_present(func))
318
return;
319
320
device_del(&func->dev);
321
put_device(&func->dev);
322
}
323
324
325