Blame view
drivers/pcmcia/ds.c
34.8 KB
d2912cb15 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 |
/* * ds.c -- 16-bit PCMCIA core support * |
1da177e4c Linux-2.6.12-rc2 |
5 6 7 8 9 |
* The initial developer of the original code is David A. Hinds * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * (C) 1999 David A. Hinds |
7b24e7988 pcmcia: split up ... |
10 |
* (C) 2003 - 2010 Dominik Brodowski |
1da177e4c Linux-2.6.12-rc2 |
11 |
*/ |
3b659fb86 [PATCH] pcmcia: r... |
12 |
#include <linux/kernel.h> |
1da177e4c Linux-2.6.12-rc2 |
13 |
#include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
14 |
#include <linux/init.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include <linux/errno.h> |
1da177e4c Linux-2.6.12-rc2 |
16 17 |
#include <linux/list.h> #include <linux/delay.h> |
1da177e4c Linux-2.6.12-rc2 |
18 |
#include <linux/workqueue.h> |
840c2ac5d [PATCH] pcmcia: h... |
19 |
#include <linux/crc32.h> |
daa9517d9 [PATCH] pcmcia: r... |
20 |
#include <linux/firmware.h> |
360b65b95 [PATCH] pcmcia: m... |
21 |
#include <linux/kref.h> |
43d9f7fda pcmcia: use DMA_M... |
22 |
#include <linux/dma-mapping.h> |
5a0e3ad6a include cleanup: ... |
23 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
24 |
|
1da177e4c Linux-2.6.12-rc2 |
25 26 27 28 29 30 31 32 33 34 35 36 37 |
#include <pcmcia/cistpl.h> #include <pcmcia/ds.h> #include <pcmcia/ss.h> #include "cs_internal.h" /*====================================================================*/ /* Module parameters */ MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); MODULE_DESCRIPTION("PCMCIA Driver Services"); MODULE_LICENSE("GPL"); |
1da177e4c Linux-2.6.12-rc2 |
38 |
|
1da177e4c Linux-2.6.12-rc2 |
39 |
/*====================================================================*/ |
23a83bfe6 [PATCH] pcmcia: c... |
40 41 |
static void pcmcia_check_driver(struct pcmcia_driver *p_drv) { |
e9fb13bfe pcmcia: Make decl... |
42 |
const struct pcmcia_device_id *did = p_drv->id_table; |
23a83bfe6 [PATCH] pcmcia: c... |
43 44 |
unsigned int i; u32 hash; |
f8cfa618d [PATCH] pcmcia: u... |
45 |
if (!p_drv->probe || !p_drv->remove) |
ba5bb6b58 [PATCH] pcmcia: f... |
46 |
printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback " |
2e9b981a7 pcmcia: move driv... |
47 48 |
"function ", p_drv->name); |
1e212f364 [PATCH] pcmcia: m... |
49 |
|
23a83bfe6 [PATCH] pcmcia: c... |
50 |
while (did && did->match_flags) { |
9fea84f46 pcmcia: CodingSty... |
51 |
for (i = 0; i < 4; i++) { |
23a83bfe6 [PATCH] pcmcia: c... |
52 53 54 55 56 57 58 59 60 |
if (!did->prod_id[i]) continue; hash = crc32(0, did->prod_id[i], strlen(did->prod_id[i])); if (hash == did->prod_id_hash[i]) continue; printk(KERN_DEBUG "pcmcia: %s: invalid hash for " "product string \"%s\": is 0x%x, should " |
2e9b981a7 pcmcia: move driv... |
61 62 |
"be 0x%x ", p_drv->name, did->prod_id[i], |
23a83bfe6 [PATCH] pcmcia: c... |
63 |
did->prod_id_hash[i], hash); |
5085cb265 [PATCH] pcmcia: a... |
64 |
printk(KERN_DEBUG "pcmcia: see " |
3bdab16c5 docs: pcmcia: con... |
65 |
"Documentation/pcmcia/devicetable.rst for " |
5085cb265 [PATCH] pcmcia: a... |
66 67 |
"details "); |
23a83bfe6 [PATCH] pcmcia: c... |
68 69 70 71 72 73 |
} did++; } return; } |
daa9517d9 [PATCH] pcmcia: r... |
74 |
|
1da177e4c Linux-2.6.12-rc2 |
75 |
/*======================================================================*/ |
1da177e4c Linux-2.6.12-rc2 |
76 |
|
6179b5562 add new_id to PCM... |
77 |
struct pcmcia_dynid { |
46f533ccb drivers: pcmcia: ... |
78 79 |
struct list_head node; struct pcmcia_device_id id; |
6179b5562 add new_id to PCM... |
80 81 82 83 84 85 86 87 88 89 90 91 |
}; /** * pcmcia_store_new_id - add a new PCMCIA device ID to this driver and re-probe devices * @driver: target device driver * @buf: buffer for scanning device ID data * @count: input size * * Adds a new dynamic PCMCIA device ID to this driver, * and causes the driver to probe for all devices again. */ static ssize_t |
ad8f20a45 pcmcia: ds: conve... |
92 |
new_id_store(struct device_driver *driver, const char *buf, size_t count) |
6179b5562 add new_id to PCM... |
93 94 95 96 97 98 |
{ struct pcmcia_dynid *dynid; struct pcmcia_driver *pdrv = to_pcmcia_drv(driver); __u16 match_flags, manf_id, card_id; __u8 func_id, function, device_no; __u32 prod_id_hash[4] = {0, 0, 0, 0}; |
9fea84f46 pcmcia: CodingSty... |
99 |
int fields = 0; |
6179b5562 add new_id to PCM... |
100 101 102 103 104 105 106 107 108 109 110 |
int retval = 0; fields = sscanf(buf, "%hx %hx %hx %hhx %hhx %hhx %x %x %x %x", &match_flags, &manf_id, &card_id, &func_id, &function, &device_no, &prod_id_hash[0], &prod_id_hash[1], &prod_id_hash[2], &prod_id_hash[3]); if (fields < 6) return -EINVAL; dynid = kzalloc(sizeof(struct pcmcia_dynid), GFP_KERNEL); if (!dynid) return -ENOMEM; |
6179b5562 add new_id to PCM... |
111 112 113 114 115 116 117 |
dynid->id.match_flags = match_flags; dynid->id.manf_id = manf_id; dynid->id.card_id = card_id; dynid->id.func_id = func_id; dynid->id.function = function; dynid->id.device_no = device_no; memcpy(dynid->id.prod_id_hash, prod_id_hash, sizeof(__u32) * 4); |
3f565232c pcmcia: use mutex... |
118 |
mutex_lock(&pdrv->dynids.lock); |
b4b3d7bbe pcmcia: fix incor... |
119 |
list_add_tail(&dynid->node, &pdrv->dynids.list); |
3f565232c pcmcia: use mutex... |
120 |
mutex_unlock(&pdrv->dynids.lock); |
6179b5562 add new_id to PCM... |
121 |
|
cef9bc56e Dynamic ID additi... |
122 |
retval = driver_attach(&pdrv->drv); |
6179b5562 add new_id to PCM... |
123 124 125 126 127 |
if (retval) return retval; return count; } |
ad8f20a45 pcmcia: ds: conve... |
128 |
static DRIVER_ATTR_WO(new_id); |
6179b5562 add new_id to PCM... |
129 130 131 132 133 |
static void pcmcia_free_dynids(struct pcmcia_driver *drv) { struct pcmcia_dynid *dynid, *n; |
3f565232c pcmcia: use mutex... |
134 |
mutex_lock(&drv->dynids.lock); |
6179b5562 add new_id to PCM... |
135 136 137 138 |
list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) { list_del(&dynid->node); kfree(dynid); } |
3f565232c pcmcia: use mutex... |
139 |
mutex_unlock(&drv->dynids.lock); |
6179b5562 add new_id to PCM... |
140 141 142 143 144 145 146 |
} static int pcmcia_create_newid_file(struct pcmcia_driver *drv) { int error = 0; if (drv->probe != NULL) |
2344c6de6 PCMCIA: use prope... |
147 |
error = driver_create_file(&drv->drv, &driver_attr_new_id); |
6179b5562 add new_id to PCM... |
148 149 |
return error; } |
ed283e9f0 USB/PCI/PCMCIA: C... |
150 151 152 153 154 |
static void pcmcia_remove_newid_file(struct pcmcia_driver *drv) { driver_remove_file(&drv->drv, &driver_attr_new_id); } |
6179b5562 add new_id to PCM... |
155 |
|
1da177e4c Linux-2.6.12-rc2 |
156 157 |
/** * pcmcia_register_driver - register a PCMCIA driver with the bus core |
78187865e pcmcia: fix kerne... |
158 |
* @driver: the &driver being registered |
1da177e4c Linux-2.6.12-rc2 |
159 160 161 |
* * Registers a PCMCIA driver with the PCMCIA bus core. */ |
1da177e4c Linux-2.6.12-rc2 |
162 163 |
int pcmcia_register_driver(struct pcmcia_driver *driver) { |
6179b5562 add new_id to PCM... |
164 |
int error; |
1da177e4c Linux-2.6.12-rc2 |
165 166 |
if (!driver) return -EINVAL; |
23a83bfe6 [PATCH] pcmcia: c... |
167 |
pcmcia_check_driver(driver); |
1da177e4c Linux-2.6.12-rc2 |
168 169 170 |
/* initialize common fields */ driver->drv.bus = &pcmcia_bus_type; driver->drv.owner = driver->owner; |
2e9b981a7 pcmcia: move driv... |
171 |
driver->drv.name = driver->name; |
3f565232c pcmcia: use mutex... |
172 |
mutex_init(&driver->dynids.lock); |
6179b5562 add new_id to PCM... |
173 |
INIT_LIST_HEAD(&driver->dynids.list); |
1da177e4c Linux-2.6.12-rc2 |
174 |
|
2e9b981a7 pcmcia: move driv... |
175 176 |
pr_debug("registering driver %s ", driver->name); |
d9d9ea016 [PATCH] pcmcia: d... |
177 |
|
6179b5562 add new_id to PCM... |
178 179 180 181 182 183 184 185 186 |
error = driver_register(&driver->drv); if (error < 0) return error; error = pcmcia_create_newid_file(driver); if (error) driver_unregister(&driver->drv); return error; |
1da177e4c Linux-2.6.12-rc2 |
187 188 189 190 191 |
} EXPORT_SYMBOL(pcmcia_register_driver); /** * pcmcia_unregister_driver - unregister a PCMCIA driver with the bus core |
78187865e pcmcia: fix kerne... |
192 |
* @driver: the &driver being unregistered |
1da177e4c Linux-2.6.12-rc2 |
193 194 195 |
*/ void pcmcia_unregister_driver(struct pcmcia_driver *driver) { |
2e9b981a7 pcmcia: move driv... |
196 197 |
pr_debug("unregistering driver %s ", driver->name); |
ed283e9f0 USB/PCI/PCMCIA: C... |
198 |
pcmcia_remove_newid_file(driver); |
1da177e4c Linux-2.6.12-rc2 |
199 |
driver_unregister(&driver->drv); |
6179b5562 add new_id to PCM... |
200 |
pcmcia_free_dynids(driver); |
1da177e4c Linux-2.6.12-rc2 |
201 202 |
} EXPORT_SYMBOL(pcmcia_unregister_driver); |
1da177e4c Linux-2.6.12-rc2 |
203 204 |
/* pcmcia_device handling */ |
5716d415f pcmcia: remove ob... |
205 |
static struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev) |
1da177e4c Linux-2.6.12-rc2 |
206 207 208 209 210 211 212 |
{ struct device *tmp_dev; tmp_dev = get_device(&p_dev->dev); if (!tmp_dev) return NULL; return to_pcmcia_dev(tmp_dev); } |
5716d415f pcmcia: remove ob... |
213 |
static void pcmcia_put_dev(struct pcmcia_device *p_dev) |
1da177e4c Linux-2.6.12-rc2 |
214 215 216 217 |
{ if (p_dev) put_device(&p_dev->dev); } |
360b65b95 [PATCH] pcmcia: m... |
218 219 220 |
static void pcmcia_release_function(struct kref *ref) { struct config_t *c = container_of(ref, struct config_t, ref); |
d50dbec3c pcmcia: use dynam... |
221 222 |
pr_debug("releasing config_t "); |
360b65b95 [PATCH] pcmcia: m... |
223 224 |
kfree(c); } |
1da177e4c Linux-2.6.12-rc2 |
225 226 227 |
static void pcmcia_release_dev(struct device *dev) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
44961a03a pcmcia: avoid pro... |
228 |
int i; |
d50dbec3c pcmcia: use dynam... |
229 230 |
dev_dbg(dev, "releasing device "); |
dc109497b [PATCH] pcmcia: m... |
231 |
pcmcia_put_socket(p_dev->socket); |
44961a03a pcmcia: avoid pro... |
232 233 |
for (i = 0; i < 4; i++) kfree(p_dev->prod_id[i]); |
bd65a6857 [PATCH] pcmcia: a... |
234 |
kfree(p_dev->devname); |
360b65b95 [PATCH] pcmcia: m... |
235 |
kref_put(&p_dev->function_config->ref, pcmcia_release_function); |
1da177e4c Linux-2.6.12-rc2 |
236 237 |
kfree(p_dev); } |
9fea84f46 pcmcia: CodingSty... |
238 |
static int pcmcia_device_probe(struct device *dev) |
1da177e4c Linux-2.6.12-rc2 |
239 240 241 |
{ struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; |
f8cfa618d [PATCH] pcmcia: u... |
242 |
struct pcmcia_socket *s; |
af2b3b503 [PATCH] pcmcia: c... |
243 |
cistpl_config_t cis_config; |
1da177e4c Linux-2.6.12-rc2 |
244 245 246 247 248 249 250 251 |
int ret = 0; dev = get_device(dev); if (!dev) return -ENODEV; p_dev = to_pcmcia_dev(dev); p_drv = to_pcmcia_drv(dev->driver); |
f8cfa618d [PATCH] pcmcia: u... |
252 |
s = p_dev->socket; |
1da177e4c Linux-2.6.12-rc2 |
253 |
|
2e9b981a7 pcmcia: move driv... |
254 255 |
dev_dbg(dev, "trying to bind to %s ", p_drv->name); |
d9d9ea016 [PATCH] pcmcia: d... |
256 |
|
360b65b95 [PATCH] pcmcia: m... |
257 258 |
if ((!p_drv->probe) || (!p_dev->function_config) || (!try_module_get(p_drv->owner))) { |
1da177e4c Linux-2.6.12-rc2 |
259 260 261 |
ret = -EINVAL; goto put_dev; } |
af2b3b503 [PATCH] pcmcia: c... |
262 263 264 265 |
/* set up some more device information */ ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG, &cis_config); if (!ret) { |
7feabb641 pcmcia: move conf... |
266 267 |
p_dev->config_base = cis_config.base; p_dev->config_regs = cis_config.rmask[0]; |
1cc745d1c pcmcia: remove th... |
268 269 |
dev_dbg(dev, "base %x, regs %x", p_dev->config_base, p_dev->config_regs); |
af2b3b503 [PATCH] pcmcia: c... |
270 |
} else { |
f2e6cf767 pcmcia: Convert d... |
271 272 273 |
dev_info(dev, "pcmcia: could not parse base and rmask0 of CIS "); |
7feabb641 pcmcia: move conf... |
274 275 |
p_dev->config_base = 0; p_dev->config_regs = 0; |
af2b3b503 [PATCH] pcmcia: c... |
276 |
} |
f8cfa618d [PATCH] pcmcia: u... |
277 |
ret = p_drv->probe(p_dev); |
d9d9ea016 [PATCH] pcmcia: d... |
278 |
if (ret) { |
d50dbec3c pcmcia: use dynam... |
279 280 |
dev_dbg(dev, "binding to %s failed with %d ", |
2e9b981a7 pcmcia: move driv... |
281 |
p_drv->name, ret); |
82d56e6d2 [PATCH] pcmcia: p... |
282 |
goto put_module; |
d9d9ea016 [PATCH] pcmcia: d... |
283 |
} |
2e9b981a7 pcmcia: move driv... |
284 |
dev_dbg(dev, "%s bound: Vpp %d.%d, idx %x, IRQ %d", p_drv->name, |
1cc745d1c pcmcia: remove th... |
285 286 287 288 |
p_dev->vpp/10, p_dev->vpp%10, p_dev->config_index, p_dev->irq); dev_dbg(dev, "resources: ioport %pR %pR iomem %pR %pR %pR", p_dev->resource[0], p_dev->resource[1], p_dev->resource[2], p_dev->resource[3], p_dev->resource[4]); |
82d56e6d2 [PATCH] pcmcia: p... |
289 |
|
00ce99ff5 pcmcia: simplify ... |
290 |
mutex_lock(&s->ops_mutex); |
ce3f9d71b pcmcia: remove un... |
291 |
if ((s->pcmcia_pfc) && |
82d56e6d2 [PATCH] pcmcia: p... |
292 |
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) |
aa584ca4c pcmcia: use state... |
293 |
pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY); |
00ce99ff5 pcmcia: simplify ... |
294 |
mutex_unlock(&s->ops_mutex); |
f8cfa618d [PATCH] pcmcia: u... |
295 |
|
cec5eb7be pcmcia: Fix broke... |
296 |
put_module: |
1da177e4c Linux-2.6.12-rc2 |
297 298 |
if (ret) module_put(p_drv->owner); |
cec5eb7be pcmcia: Fix broke... |
299 |
put_dev: |
f8cfa618d [PATCH] pcmcia: u... |
300 |
if (ret) |
1da177e4c Linux-2.6.12-rc2 |
301 |
put_device(dev); |
9fea84f46 pcmcia: CodingSty... |
302 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
303 |
} |
d6ff5a853 [PATCH] pcmcia: p... |
304 305 306 307 308 309 310 |
/* * Removes a PCMCIA card from the device tree and socket list. */ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *leftover) { struct pcmcia_device *p_dev; struct pcmcia_device *tmp; |
d6ff5a853 [PATCH] pcmcia: p... |
311 |
|
d50dbec3c pcmcia: use dynam... |
312 |
dev_dbg(leftover ? &leftover->dev : &s->dev, |
ac449d6e2 pcmcia: use dev_p... |
313 314 315 |
"pcmcia_card_remove(%d) %s ", s->sock, leftover ? leftover->devname : ""); |
d6ff5a853 [PATCH] pcmcia: p... |
316 |
|
00ce99ff5 pcmcia: simplify ... |
317 |
mutex_lock(&s->ops_mutex); |
d6ff5a853 [PATCH] pcmcia: p... |
318 319 320 321 |
if (!leftover) s->device_count = 0; else s->device_count = 1; |
00ce99ff5 pcmcia: simplify ... |
322 |
mutex_unlock(&s->ops_mutex); |
d6ff5a853 [PATCH] pcmcia: p... |
323 324 325 326 327 |
/* unregister all pcmcia_devices registered with this socket, except leftover */ list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) { if (p_dev == leftover) continue; |
00ce99ff5 pcmcia: simplify ... |
328 |
mutex_lock(&s->ops_mutex); |
d6ff5a853 [PATCH] pcmcia: p... |
329 |
list_del(&p_dev->socket_device_list); |
00ce99ff5 pcmcia: simplify ... |
330 |
mutex_unlock(&s->ops_mutex); |
d6ff5a853 [PATCH] pcmcia: p... |
331 |
|
d50dbec3c pcmcia: use dynam... |
332 333 |
dev_dbg(&p_dev->dev, "unregistering device "); |
d6ff5a853 [PATCH] pcmcia: p... |
334 335 336 337 338 |
device_unregister(&p_dev->dev); } return; } |
9fea84f46 pcmcia: CodingSty... |
339 |
static int pcmcia_device_remove(struct device *dev) |
1da177e4c Linux-2.6.12-rc2 |
340 341 342 |
{ struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; |
cc3b4866b [PATCH] pcmcia: u... |
343 |
int i; |
1da177e4c Linux-2.6.12-rc2 |
344 |
|
1da177e4c Linux-2.6.12-rc2 |
345 346 |
p_dev = to_pcmcia_dev(dev); p_drv = to_pcmcia_drv(dev->driver); |
d6ff5a853 [PATCH] pcmcia: p... |
347 |
|
d50dbec3c pcmcia: use dynam... |
348 349 |
dev_dbg(dev, "removing device "); |
d9d9ea016 [PATCH] pcmcia: d... |
350 |
|
d6ff5a853 [PATCH] pcmcia: p... |
351 352 353 354 |
/* If we're removing the primary module driving a * pseudo multi-function card, we need to unbind * all devices */ |
ce3f9d71b pcmcia: remove un... |
355 |
if ((p_dev->socket->pcmcia_pfc) && |
e6e4f397e pcmcia: protect s... |
356 |
(p_dev->socket->device_count > 0) && |
d6ff5a853 [PATCH] pcmcia: p... |
357 358 359 360 |
(p_dev->device_no == 0)) pcmcia_card_remove(p_dev->socket, p_dev); /* detach the "instance" */ |
f39907155 [PATCH] pcmcia: r... |
361 362 |
if (!p_drv) return 0; |
1da177e4c Linux-2.6.12-rc2 |
363 |
|
f39907155 [PATCH] pcmcia: r... |
364 |
if (p_drv->remove) |
9fea84f46 pcmcia: CodingSty... |
365 |
p_drv->remove(p_dev); |
cc3b4866b [PATCH] pcmcia: u... |
366 |
|
f39907155 [PATCH] pcmcia: r... |
367 |
/* check for proper unloading */ |
e2d409636 [PATCH] pcmcia: u... |
368 |
if (p_dev->_irq || p_dev->_io || p_dev->_locked) |
f2e6cf767 pcmcia: Convert d... |
369 370 371 372 |
dev_info(dev, "pcmcia: driver %s did not release config properly ", p_drv->name); |
cc3b4866b [PATCH] pcmcia: u... |
373 |
|
f39907155 [PATCH] pcmcia: r... |
374 |
for (i = 0; i < MAX_WIN; i++) |
e2d409636 [PATCH] pcmcia: u... |
375 |
if (p_dev->_win & CLIENT_WIN_REQ(i)) |
f2e6cf767 pcmcia: Convert d... |
376 377 378 379 |
dev_info(dev, "pcmcia: driver %s did not release window properly ", p_drv->name); |
cc3b4866b [PATCH] pcmcia: u... |
380 |
|
f39907155 [PATCH] pcmcia: r... |
381 382 383 |
/* references from pcmcia_probe_device */ pcmcia_put_dev(p_dev); module_put(p_drv->owner); |
1da177e4c Linux-2.6.12-rc2 |
384 385 386 |
return 0; } |
cc3b4866b [PATCH] pcmcia: u... |
387 |
/* |
1da177e4c Linux-2.6.12-rc2 |
388 389 390 391 392 393 |
* pcmcia_device_query -- determine information about a pcmcia device */ static int pcmcia_device_query(struct pcmcia_device *p_dev) { cistpl_manfid_t manf_id; cistpl_funcid_t func_id; |
76fa82fb7 [PATCH] pcmcia: r... |
394 |
cistpl_vers_1_t *vers1; |
1da177e4c Linux-2.6.12-rc2 |
395 |
unsigned int i; |
76fa82fb7 [PATCH] pcmcia: r... |
396 397 398 |
vers1 = kmalloc(sizeof(*vers1), GFP_KERNEL); if (!vers1) return -ENOMEM; |
84897fc05 pcmcia: pccard_re... |
399 |
if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, |
1da177e4c Linux-2.6.12-rc2 |
400 |
CISTPL_MANFID, &manf_id)) { |
af461fc18 pcmcia: delay re-... |
401 |
mutex_lock(&p_dev->socket->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
402 403 404 405 |
p_dev->manf_id = manf_id.manf; p_dev->card_id = manf_id.card; p_dev->has_manf_id = 1; p_dev->has_card_id = 1; |
af461fc18 pcmcia: delay re-... |
406 |
mutex_unlock(&p_dev->socket->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
407 408 409 410 |
} if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_FUNCID, &func_id)) { |
af461fc18 pcmcia: delay re-... |
411 |
mutex_lock(&p_dev->socket->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
412 413 |
p_dev->func_id = func_id.func; p_dev->has_func_id = 1; |
af461fc18 pcmcia: delay re-... |
414 |
mutex_unlock(&p_dev->socket->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
415 416 417 418 |
} else { /* rule of thumb: cards with no FUNCID, but with * common memory device geometry information, are * probably memory cards (from pcmcia-cs) */ |
76fa82fb7 [PATCH] pcmcia: r... |
419 420 421 422 423 424 425 |
cistpl_device_geo_t *devgeo; devgeo = kmalloc(sizeof(*devgeo), GFP_KERNEL); if (!devgeo) { kfree(vers1); return -ENOMEM; } |
1da177e4c Linux-2.6.12-rc2 |
426 |
if (!pccard_read_tuple(p_dev->socket, p_dev->func, |
76fa82fb7 [PATCH] pcmcia: r... |
427 |
CISTPL_DEVICE_GEO, devgeo)) { |
d50dbec3c pcmcia: use dynam... |
428 |
dev_dbg(&p_dev->dev, |
ac449d6e2 pcmcia: use dev_p... |
429 430 431 |
"mem device geometry probably means " "FUNCID_MEMORY "); |
af461fc18 pcmcia: delay re-... |
432 |
mutex_lock(&p_dev->socket->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
433 434 |
p_dev->func_id = CISTPL_FUNCID_MEMORY; p_dev->has_func_id = 1; |
af461fc18 pcmcia: delay re-... |
435 |
mutex_unlock(&p_dev->socket->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
436 |
} |
76fa82fb7 [PATCH] pcmcia: r... |
437 |
kfree(devgeo); |
1da177e4c Linux-2.6.12-rc2 |
438 |
} |
84897fc05 pcmcia: pccard_re... |
439 |
if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, CISTPL_VERS_1, |
76fa82fb7 [PATCH] pcmcia: r... |
440 |
vers1)) { |
af461fc18 pcmcia: delay re-... |
441 |
mutex_lock(&p_dev->socket->ops_mutex); |
c5e09528b pcmcia: do not tr... |
442 |
for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) { |
1da177e4c Linux-2.6.12-rc2 |
443 444 |
char *tmp; unsigned int length; |
44961a03a pcmcia: avoid pro... |
445 |
char *new; |
1da177e4c Linux-2.6.12-rc2 |
446 |
|
76fa82fb7 [PATCH] pcmcia: r... |
447 |
tmp = vers1->str + vers1->ofs[i]; |
1da177e4c Linux-2.6.12-rc2 |
448 449 |
length = strlen(tmp) + 1; |
6e3d4f25a [PATCH] pcmcia: p... |
450 |
if ((length < 2) || (length > 255)) |
1da177e4c Linux-2.6.12-rc2 |
451 |
continue; |
7c22e645c pcmcia: use kstrd... |
452 |
new = kstrdup(tmp, GFP_KERNEL); |
44961a03a pcmcia: avoid pro... |
453 |
if (!new) |
1da177e4c Linux-2.6.12-rc2 |
454 |
continue; |
44961a03a pcmcia: avoid pro... |
455 456 457 |
tmp = p_dev->prod_id[i]; p_dev->prod_id[i] = new; kfree(tmp); |
1da177e4c Linux-2.6.12-rc2 |
458 |
} |
af461fc18 pcmcia: delay re-... |
459 |
mutex_unlock(&p_dev->socket->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
460 |
} |
76fa82fb7 [PATCH] pcmcia: r... |
461 |
kfree(vers1); |
1da177e4c Linux-2.6.12-rc2 |
462 463 |
return 0; } |
5716d415f pcmcia: remove ob... |
464 465 |
static struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) |
1da177e4c Linux-2.6.12-rc2 |
466 |
{ |
360b65b95 [PATCH] pcmcia: m... |
467 |
struct pcmcia_device *p_dev, *tmp_dev; |
44961a03a pcmcia: avoid pro... |
468 |
int i; |
1da177e4c Linux-2.6.12-rc2 |
469 |
|
dc109497b [PATCH] pcmcia: m... |
470 |
s = pcmcia_get_socket(s); |
1da177e4c Linux-2.6.12-rc2 |
471 472 |
if (!s) return NULL; |
d50dbec3c pcmcia: use dynam... |
473 474 |
pr_debug("adding device to %d, function %d ", s->sock, function); |
d9d9ea016 [PATCH] pcmcia: d... |
475 |
|
8084b372a [PATCH] pcmcia: k... |
476 |
p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
477 478 |
if (!p_dev) goto err_put; |
1da177e4c Linux-2.6.12-rc2 |
479 |
|
00ce99ff5 pcmcia: simplify ... |
480 |
mutex_lock(&s->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
481 |
p_dev->device_no = (s->device_count++); |
00ce99ff5 pcmcia: simplify ... |
482 |
mutex_unlock(&s->ops_mutex); |
e6e4f397e pcmcia: protect s... |
483 |
|
7d7ba8d31 pcmcia: allow for... |
484 485 486 487 488 489 |
/* max of 2 PFC devices */ if ((p_dev->device_no >= 2) && (function == 0)) goto err_free; /* max of 4 devices overall */ if (p_dev->device_no >= 4) |
e6e4f397e pcmcia: protect s... |
490 491 492 |
goto err_free; p_dev->socket = s; |
1da177e4c Linux-2.6.12-rc2 |
493 494 495 |
p_dev->func = function; p_dev->dev.bus = &pcmcia_bus_type; |
873733188 Driver core: conv... |
496 |
p_dev->dev.parent = s->dev.parent; |
1da177e4c Linux-2.6.12-rc2 |
497 |
p_dev->dev.release = pcmcia_release_dev; |
43d9f7fda pcmcia: use DMA_M... |
498 499 500 |
/* by default don't allow DMA */ p_dev->dma_mask = DMA_MASK_NONE; p_dev->dev.dma_mask = &p_dev->dma_mask; |
250969868 pcmcia: struct de... |
501 502 503 504 |
dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no); if (!dev_name(&p_dev->dev)) goto err_free; p_dev->devname = kasprintf(GFP_KERNEL, "pcmcia%s", dev_name(&p_dev->dev)); |
bd65a6857 [PATCH] pcmcia: a... |
505 506 |
if (!p_dev->devname) goto err_free; |
d50dbec3c pcmcia: use dynam... |
507 508 |
dev_dbg(&p_dev->dev, "devname is %s ", p_dev->devname); |
1da177e4c Linux-2.6.12-rc2 |
509 |
|
00ce99ff5 pcmcia: simplify ... |
510 |
mutex_lock(&s->ops_mutex); |
360b65b95 [PATCH] pcmcia: m... |
511 512 513 |
/* * p_dev->function_config must be the same for all card functions. |
a60f22c4a pcmcia: remove pc... |
514 515 |
* Note that this is serialized by ops_mutex, so that only one * such struct will be created. |
360b65b95 [PATCH] pcmcia: m... |
516 |
*/ |
9fea84f46 pcmcia: CodingSty... |
517 518 |
list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) if (p_dev->func == tmp_dev->func) { |
360b65b95 [PATCH] pcmcia: m... |
519 |
p_dev->function_config = tmp_dev->function_config; |
3e879f614 pcmcia: setup res... |
520 |
p_dev->irq = tmp_dev->irq; |
360b65b95 [PATCH] pcmcia: m... |
521 522 523 524 |
kref_get(&p_dev->function_config->ref); } /* Add to the list in pcmcia_bus_socket */ |
6171b88b4 [PATCH] pcmcia: u... |
525 |
list_add(&p_dev->socket_device_list, &s->devices_list); |
360b65b95 [PATCH] pcmcia: m... |
526 |
|
6f0f38c45 pcmcia: setup IRQ... |
527 528 529 530 |
if (pcmcia_setup_irq(p_dev)) dev_warn(&p_dev->dev, "IRQ setup failed -- device might not work "); |
1da177e4c Linux-2.6.12-rc2 |
531 |
|
360b65b95 [PATCH] pcmcia: m... |
532 |
if (!p_dev->function_config) { |
2ce4905e4 pcmcia: use struc... |
533 |
config_t *c; |
d50dbec3c pcmcia: use dynam... |
534 535 |
dev_dbg(&p_dev->dev, "creating config_t "); |
2ce4905e4 pcmcia: use struc... |
536 537 |
c = kzalloc(sizeof(struct config_t), GFP_KERNEL); if (!c) { |
6f0f38c45 pcmcia: setup IRQ... |
538 |
mutex_unlock(&s->ops_mutex); |
360b65b95 [PATCH] pcmcia: m... |
539 |
goto err_unreg; |
6f0f38c45 pcmcia: setup IRQ... |
540 |
} |
2ce4905e4 pcmcia: use struc... |
541 542 543 |
p_dev->function_config = c; kref_init(&c->ref); for (i = 0; i < MAX_IO_WIN; i++) { |
ad0c7be28 pcmcia: insert PC... |
544 |
c->io[i].name = p_dev->devname; |
2ce4905e4 pcmcia: use struc... |
545 546 |
c->io[i].flags = IORESOURCE_IO; } |
46f533ccb drivers: pcmcia: ... |
547 |
for (i = 0; i < MAX_WIN; i++) { |
ad0c7be28 pcmcia: insert PC... |
548 |
c->mem[i].name = p_dev->devname; |
0ca724d37 pcmcia: use struc... |
549 550 |
c->mem[i].flags = IORESOURCE_MEM; } |
360b65b95 [PATCH] pcmcia: m... |
551 |
} |
2ce4905e4 pcmcia: use struc... |
552 553 |
for (i = 0; i < MAX_IO_WIN; i++) p_dev->resource[i] = &p_dev->function_config->io[i]; |
0ca724d37 pcmcia: use struc... |
554 555 |
for (; i < (MAX_IO_WIN + MAX_WIN); i++) p_dev->resource[i] = &p_dev->function_config->mem[i-MAX_IO_WIN]; |
2ce4905e4 pcmcia: use struc... |
556 |
|
6f0f38c45 pcmcia: setup IRQ... |
557 |
mutex_unlock(&s->ops_mutex); |
360b65b95 [PATCH] pcmcia: m... |
558 |
|
f2e6cf767 pcmcia: Convert d... |
559 560 |
dev_notice(&p_dev->dev, "pcmcia: registering new device %s (IRQ: %d) ", |
eb14120f7 pcmcia: re-work p... |
561 |
p_dev->devname, p_dev->irq); |
807277cbf [PCMCIA] inform u... |
562 |
|
1ad275e3e [PATCH] pcmcia: d... |
563 |
pcmcia_device_query(p_dev); |
360b65b95 [PATCH] pcmcia: m... |
564 565 |
if (device_register(&p_dev->dev)) goto err_unreg; |
1da177e4c Linux-2.6.12-rc2 |
566 |
|
1da177e4c Linux-2.6.12-rc2 |
567 |
return p_dev; |
360b65b95 [PATCH] pcmcia: m... |
568 |
err_unreg: |
00ce99ff5 pcmcia: simplify ... |
569 |
mutex_lock(&s->ops_mutex); |
360b65b95 [PATCH] pcmcia: m... |
570 |
list_del(&p_dev->socket_device_list); |
00ce99ff5 pcmcia: simplify ... |
571 |
mutex_unlock(&s->ops_mutex); |
360b65b95 [PATCH] pcmcia: m... |
572 |
|
1da177e4c Linux-2.6.12-rc2 |
573 |
err_free: |
00ce99ff5 pcmcia: simplify ... |
574 |
mutex_lock(&s->ops_mutex); |
e6e4f397e pcmcia: protect s... |
575 |
s->device_count--; |
00ce99ff5 pcmcia: simplify ... |
576 |
mutex_unlock(&s->ops_mutex); |
e6e4f397e pcmcia: protect s... |
577 |
|
44961a03a pcmcia: avoid pro... |
578 579 |
for (i = 0; i < 4; i++) kfree(p_dev->prod_id[i]); |
bd65a6857 [PATCH] pcmcia: a... |
580 |
kfree(p_dev->devname); |
1da177e4c Linux-2.6.12-rc2 |
581 |
kfree(p_dev); |
1da177e4c Linux-2.6.12-rc2 |
582 |
err_put: |
dc109497b [PATCH] pcmcia: m... |
583 |
pcmcia_put_socket(s); |
1da177e4c Linux-2.6.12-rc2 |
584 585 586 587 588 589 590 |
return NULL; } static int pcmcia_card_add(struct pcmcia_socket *s) { |
1da177e4c Linux-2.6.12-rc2 |
591 |
cistpl_longlink_mfc_t mfc; |
c5081d5f4 pcmcia: simplify ... |
592 |
unsigned int no_funcs, i, no_chains; |
cfe5d8095 pcmcia: use ops_m... |
593 |
int ret = -EAGAIN; |
1da177e4c Linux-2.6.12-rc2 |
594 |
|
cfe5d8095 pcmcia: use ops_m... |
595 |
mutex_lock(&s->ops_mutex); |
d9d9ea016 [PATCH] pcmcia: d... |
596 |
if (!(s->resource_setup_done)) { |
d50dbec3c pcmcia: use dynam... |
597 |
dev_dbg(&s->dev, |
ac449d6e2 pcmcia: use dev_p... |
598 599 |
"no resources available, delaying card_add "); |
cfe5d8095 pcmcia: use ops_m... |
600 |
mutex_unlock(&s->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
601 |
return -EAGAIN; /* try again, but later... */ |
d9d9ea016 [PATCH] pcmcia: d... |
602 |
} |
1da177e4c Linux-2.6.12-rc2 |
603 |
|
d9d9ea016 [PATCH] pcmcia: d... |
604 |
if (pcmcia_validate_mem(s)) { |
d50dbec3c pcmcia: use dynam... |
605 |
dev_dbg(&s->dev, "validating mem resources failed, " |
d9d9ea016 [PATCH] pcmcia: d... |
606 607 |
"delaying card_add "); |
cfe5d8095 pcmcia: use ops_m... |
608 |
mutex_unlock(&s->ops_mutex); |
de75914ee [PATCH] pcmcia: v... |
609 |
return -EAGAIN; /* try again, but later... */ |
d9d9ea016 [PATCH] pcmcia: d... |
610 |
} |
cfe5d8095 pcmcia: use ops_m... |
611 |
mutex_unlock(&s->ops_mutex); |
de75914ee [PATCH] pcmcia: v... |
612 |
|
84897fc05 pcmcia: pccard_re... |
613 |
ret = pccard_validate_cis(s, &no_chains); |
c5081d5f4 pcmcia: simplify ... |
614 |
if (ret || !no_chains) { |
e8e68fd86 pcmcia: do not br... |
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 |
#if defined(CONFIG_MTD_PCMCIA_ANONYMOUS) /* Set up as an anonymous card. If we don't have anonymous memory support then just error the card as there is no point trying to second guess. Note: some cards have just a device entry, it may be worth extending support to cover these in future */ if (ret == -EIO) { dev_info(&s->dev, "no CIS, assuming an anonymous memory card. "); pcmcia_replace_cis(s, "\xFF", 1); no_chains = 1; ret = 0; } else #endif { dev_dbg(&s->dev, "invalid CIS or invalid resources "); return -ENODEV; } |
1da177e4c Linux-2.6.12-rc2 |
635 636 637 638 639 640 |
} if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC, &mfc)) no_funcs = mfc.nfn; else no_funcs = 1; |
1d2c90425 [PATCH] pcmcia: m... |
641 |
s->functions = no_funcs; |
1da177e4c Linux-2.6.12-rc2 |
642 |
|
9fea84f46 pcmcia: CodingSty... |
643 |
for (i = 0; i < no_funcs; i++) |
dc109497b [PATCH] pcmcia: m... |
644 |
pcmcia_device_add(s, i); |
1da177e4c Linux-2.6.12-rc2 |
645 |
|
9fea84f46 pcmcia: CodingSty... |
646 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
647 |
} |
46f533ccb drivers: pcmcia: ... |
648 |
static int pcmcia_requery_callback(struct device *dev, void *_data) |
ff1fa9ef3 [PATCH] pcmcia: C... |
649 |
{ |
e2f0b5344 [PATCH] pcmcia: r... |
650 |
struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
d9d9ea016 [PATCH] pcmcia: d... |
651 |
if (!p_dev->dev.driver) { |
d50dbec3c pcmcia: use dynam... |
652 653 |
dev_dbg(dev, "update device information "); |
e2f0b5344 [PATCH] pcmcia: r... |
654 |
pcmcia_device_query(p_dev); |
d9d9ea016 [PATCH] pcmcia: d... |
655 |
} |
e2f0b5344 [PATCH] pcmcia: r... |
656 657 658 |
return 0; } |
aa584ca4c pcmcia: use state... |
659 |
|
af461fc18 pcmcia: delay re-... |
660 |
static void pcmcia_requery(struct pcmcia_socket *s) |
e2f0b5344 [PATCH] pcmcia: r... |
661 |
{ |
04de08161 pcmcia: pcmcia_de... |
662 |
int has_pfc; |
4ae1cbf17 [PATCH] pcmcia: s... |
663 |
|
8402641b2 pcmcia: Fix requery |
664 665 |
if (!(s->state & SOCKET_PRESENT)) return; |
af461fc18 pcmcia: delay re-... |
666 667 668 |
if (s->functions == 0) { pcmcia_card_add(s); return; |
e2f0b5344 [PATCH] pcmcia: r... |
669 670 671 672 673 |
} /* some device information might have changed because of a CIS * update or because we can finally read it correctly... so * determine it again, overwriting old values if necessary. */ |
af461fc18 pcmcia: delay re-... |
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 |
bus_for_each_dev(&pcmcia_bus_type, NULL, NULL, pcmcia_requery_callback); /* if the CIS changed, we need to check whether the number of * functions changed. */ if (s->fake_cis) { int old_funcs, new_funcs; cistpl_longlink_mfc_t mfc; /* does this cis override add or remove functions? */ old_funcs = s->functions; if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC, &mfc)) new_funcs = mfc.nfn; else new_funcs = 1; |
b1095afe6 pcmcia: re-start ... |
690 691 |
if (old_funcs != new_funcs) { /* we need to re-start */ |
af461fc18 pcmcia: delay re-... |
692 |
pcmcia_card_remove(s, NULL); |
b83156b52 pcmcia: avoid val... |
693 |
s->functions = 0; |
af461fc18 pcmcia: delay re-... |
694 |
pcmcia_card_add(s); |
af461fc18 pcmcia: delay re-... |
695 696 |
} } |
e2f0b5344 [PATCH] pcmcia: r... |
697 |
|
aa584ca4c pcmcia: use state... |
698 699 700 701 |
/* If the PCMCIA device consists of two pseudo devices, * call pcmcia_device_add() -- which will fail if both * devices are already registered. */ mutex_lock(&s->ops_mutex); |
ce3f9d71b pcmcia: remove un... |
702 |
has_pfc = s->pcmcia_pfc; |
aa584ca4c pcmcia: use state... |
703 704 705 |
mutex_unlock(&s->ops_mutex); if (has_pfc) pcmcia_device_add(s, 0); |
e2f0b5344 [PATCH] pcmcia: r... |
706 707 |
/* we re-scan all devices, not just the ones connected to this * socket. This does not matter, though. */ |
af461fc18 pcmcia: delay re-... |
708 709 710 |
if (bus_rescan_devices(&pcmcia_bus_type)) dev_warn(&s->dev, "rescanning the bus failed "); |
ff1fa9ef3 [PATCH] pcmcia: C... |
711 |
} |
1ad275e3e [PATCH] pcmcia: d... |
712 |
|
af461fc18 pcmcia: delay re-... |
713 |
|
1d2c90425 [PATCH] pcmcia: m... |
714 715 716 717 |
#ifdef CONFIG_PCMCIA_LOAD_CIS /** * pcmcia_load_firmware - load CIS from userspace if device-provided is broken |
78187865e pcmcia: fix kerne... |
718 719 |
* @dev: the pcmcia device which needs a CIS override * @filename: requested filename in /lib/firmware/ |
1d2c90425 [PATCH] pcmcia: m... |
720 721 722 723 724 |
* * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if * the one provided by the card is broken. The firmware files reside in * /lib/firmware/ in userspace. */ |
46f533ccb drivers: pcmcia: ... |
725 |
static int pcmcia_load_firmware(struct pcmcia_device *dev, char *filename) |
1d2c90425 [PATCH] pcmcia: m... |
726 727 728 |
{ struct pcmcia_socket *s = dev->socket; const struct firmware *fw; |
1d2c90425 [PATCH] pcmcia: m... |
729 |
int ret = -ENOMEM; |
b1095afe6 pcmcia: re-start ... |
730 731 |
cistpl_longlink_mfc_t mfc; int old_funcs, new_funcs = 1; |
1d2c90425 [PATCH] pcmcia: m... |
732 733 734 |
if (!filename) return -EINVAL; |
d50dbec3c pcmcia: use dynam... |
735 736 |
dev_dbg(&dev->dev, "trying to load CIS file %s ", filename); |
1d2c90425 [PATCH] pcmcia: m... |
737 |
|
ed62acec2 firmware: pcmcia/... |
738 |
if (request_firmware(&fw, filename, &dev->dev) == 0) { |
d9d9ea016 [PATCH] pcmcia: d... |
739 740 |
if (fw->size >= CISTPL_MAX_CIS_SIZE) { ret = -EINVAL; |
f2e6cf767 pcmcia: Convert d... |
741 742 |
dev_err(&dev->dev, "pcmcia: CIS override is too big "); |
1d2c90425 [PATCH] pcmcia: m... |
743 |
goto release; |
d9d9ea016 [PATCH] pcmcia: d... |
744 |
} |
1d2c90425 [PATCH] pcmcia: m... |
745 |
|
53efec951 pcmcia: only copy... |
746 |
if (!pcmcia_replace_cis(s, fw->data, fw->size)) |
1d2c90425 [PATCH] pcmcia: m... |
747 |
ret = 0; |
d9d9ea016 [PATCH] pcmcia: d... |
748 |
else { |
f2e6cf767 pcmcia: Convert d... |
749 750 |
dev_err(&dev->dev, "pcmcia: CIS override failed "); |
d9d9ea016 [PATCH] pcmcia: d... |
751 752 |
goto release; } |
b1095afe6 pcmcia: re-start ... |
753 754 755 756 757 758 759 760 |
/* we need to re-start if the number of functions changed */ old_funcs = s->functions; if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC, &mfc)) new_funcs = mfc.nfn; if (old_funcs != new_funcs) ret = -EBUSY; |
1d2c90425 [PATCH] pcmcia: m... |
761 762 763 |
/* update information */ pcmcia_device_query(dev); |
aa584ca4c pcmcia: use state... |
764 765 |
/* requery (as number of functions might have changed) */ pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY); |
1d2c90425 [PATCH] pcmcia: m... |
766 767 768 |
} release: release_firmware(fw); |
9fea84f46 pcmcia: CodingSty... |
769 |
return ret; |
1d2c90425 [PATCH] pcmcia: m... |
770 771 772 |
} #else /* !CONFIG_PCMCIA_LOAD_CIS */ |
46f533ccb drivers: pcmcia: ... |
773 774 |
static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char *filename) |
1d2c90425 [PATCH] pcmcia: m... |
775 776 777 778 779 |
{ return -ENODEV; } #endif |
1ad275e3e [PATCH] pcmcia: d... |
780 |
static inline int pcmcia_devmatch(struct pcmcia_device *dev, |
e9fb13bfe pcmcia: Make decl... |
781 |
const struct pcmcia_device_id *did) |
1ad275e3e [PATCH] pcmcia: d... |
782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 |
{ if (did->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID) { if ((!dev->has_manf_id) || (dev->manf_id != did->manf_id)) return 0; } if (did->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID) { if ((!dev->has_card_id) || (dev->card_id != did->card_id)) return 0; } if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION) { if (dev->func != did->function) return 0; } if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1) { if (!dev->prod_id[0]) return 0; if (strcmp(did->prod_id[0], dev->prod_id[0])) return 0; } if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2) { if (!dev->prod_id[1]) return 0; if (strcmp(did->prod_id[1], dev->prod_id[1])) return 0; } if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3) { if (!dev->prod_id[2]) return 0; if (strcmp(did->prod_id[2], dev->prod_id[2])) return 0; } if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4) { if (!dev->prod_id[3]) return 0; if (strcmp(did->prod_id[3], dev->prod_id[3])) return 0; } if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { |
83bf6f11e pcmcia: fix match... |
827 828 |
dev_dbg(&dev->dev, "this is a pseudo-multi-function device "); |
aa584ca4c pcmcia: use state... |
829 |
mutex_lock(&dev->socket->ops_mutex); |
ce3f9d71b pcmcia: remove un... |
830 |
dev->socket->pcmcia_pfc = 1; |
aa584ca4c pcmcia: use state... |
831 |
mutex_unlock(&dev->socket->ops_mutex); |
83bf6f11e pcmcia: fix match... |
832 833 |
if (dev->device_no != did->device_no) return 0; |
1ad275e3e [PATCH] pcmcia: d... |
834 835 836 |
} if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) { |
94a819f80 pcmcia: assert lo... |
837 |
int ret; |
1ad275e3e [PATCH] pcmcia: d... |
838 839 840 841 842 |
if ((!dev->has_func_id) || (dev->func_id != did->func_id)) return 0; /* if this is a pseudo-multi-function device, * we need explicit matches */ |
ce3f9d71b pcmcia: remove un... |
843 |
if (dev->socket->pcmcia_pfc) |
1ad275e3e [PATCH] pcmcia: d... |
844 845 846 847 848 849 850 851 |
return 0; if (dev->device_no) return 0; /* also, FUNC_ID matching needs to be activated by userspace * after it has re-checked that there is no possible module * with a prod_id/manf_id/card_id match. */ |
94a819f80 pcmcia: assert lo... |
852 853 854 855 856 857 858 859 |
mutex_lock(&dev->socket->ops_mutex); ret = dev->allow_func_id_match; mutex_unlock(&dev->socket->ops_mutex); if (!ret) { dev_dbg(&dev->dev, "skipping FUNC_ID match until userspace ACK "); |
1ad275e3e [PATCH] pcmcia: d... |
860 |
return 0; |
94a819f80 pcmcia: assert lo... |
861 |
} |
1ad275e3e [PATCH] pcmcia: d... |
862 |
} |
ea7b38825 [PATCH] pcmcia: m... |
863 |
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { |
d50dbec3c pcmcia: use dynam... |
864 865 |
dev_dbg(&dev->dev, "device needs a fake CIS "); |
daa9517d9 [PATCH] pcmcia: r... |
866 |
if (!dev->socket->fake_cis) |
b1095afe6 pcmcia: re-start ... |
867 868 |
if (pcmcia_load_firmware(dev, did->cisfile)) return 0; |
ea7b38825 [PATCH] pcmcia: m... |
869 |
} |
f602ff7eb [PATCH] pcmcia: m... |
870 871 |
if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) { int i; |
9fea84f46 pcmcia: CodingSty... |
872 |
for (i = 0; i < 4; i++) |
f602ff7eb [PATCH] pcmcia: m... |
873 874 875 876 877 |
if (dev->prod_id[i]) return 0; if (dev->has_manf_id || dev->has_card_id || dev->has_func_id) return 0; } |
1ad275e3e [PATCH] pcmcia: d... |
878 879 |
return 1; } |
9fea84f46 pcmcia: CodingSty... |
880 881 882 883 |
static int pcmcia_bus_match(struct device *dev, struct device_driver *drv) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct pcmcia_driver *p_drv = to_pcmcia_drv(drv); |
e9fb13bfe pcmcia: Make decl... |
884 |
const struct pcmcia_device_id *did = p_drv->id_table; |
6179b5562 add new_id to PCM... |
885 886 887 |
struct pcmcia_dynid *dynid; /* match dynamic devices first */ |
3f565232c pcmcia: use mutex... |
888 |
mutex_lock(&p_drv->dynids.lock); |
6179b5562 add new_id to PCM... |
889 |
list_for_each_entry(dynid, &p_drv->dynids.list, node) { |
d50dbec3c pcmcia: use dynam... |
890 891 |
dev_dbg(dev, "trying to match to %s ", drv->name); |
6179b5562 add new_id to PCM... |
892 |
if (pcmcia_devmatch(p_dev, &dynid->id)) { |
d50dbec3c pcmcia: use dynam... |
893 894 |
dev_dbg(dev, "matched to %s ", drv->name); |
3f565232c pcmcia: use mutex... |
895 |
mutex_unlock(&p_drv->dynids.lock); |
6179b5562 add new_id to PCM... |
896 897 898 |
return 1; } } |
3f565232c pcmcia: use mutex... |
899 |
mutex_unlock(&p_drv->dynids.lock); |
1da177e4c Linux-2.6.12-rc2 |
900 |
|
1ad275e3e [PATCH] pcmcia: d... |
901 |
while (did && did->match_flags) { |
d50dbec3c pcmcia: use dynam... |
902 903 |
dev_dbg(dev, "trying to match to %s ", drv->name); |
d9d9ea016 [PATCH] pcmcia: d... |
904 |
if (pcmcia_devmatch(p_dev, did)) { |
d50dbec3c pcmcia: use dynam... |
905 906 |
dev_dbg(dev, "matched to %s ", drv->name); |
1ad275e3e [PATCH] pcmcia: d... |
907 |
return 1; |
d9d9ea016 [PATCH] pcmcia: d... |
908 |
} |
1ad275e3e [PATCH] pcmcia: d... |
909 910 |
did++; } |
1da177e4c Linux-2.6.12-rc2 |
911 912 |
return 0; } |
7eff2e7a8 Driver core: chan... |
913 |
static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env) |
840c2ac5d [PATCH] pcmcia: h... |
914 915 |
{ struct pcmcia_device *p_dev; |
7eff2e7a8 Driver core: chan... |
916 |
int i; |
840c2ac5d [PATCH] pcmcia: h... |
917 918 919 920 921 922 923 924 |
u32 hash[4] = { 0, 0, 0, 0}; if (!dev) return -ENODEV; p_dev = to_pcmcia_dev(dev); /* calculate hashes */ |
9fea84f46 pcmcia: CodingSty... |
925 |
for (i = 0; i < 4; i++) { |
840c2ac5d [PATCH] pcmcia: h... |
926 927 928 929 |
if (!p_dev->prod_id[i]) continue; hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i])); } |
7eff2e7a8 Driver core: chan... |
930 |
if (add_uevent_var(env, "SOCKET_NO=%u", p_dev->socket->sock)) |
840c2ac5d [PATCH] pcmcia: h... |
931 |
return -ENOMEM; |
7eff2e7a8 Driver core: chan... |
932 |
if (add_uevent_var(env, "DEVICE_NO=%02X", p_dev->device_no)) |
840c2ac5d [PATCH] pcmcia: h... |
933 |
return -ENOMEM; |
7eff2e7a8 Driver core: chan... |
934 |
if (add_uevent_var(env, "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" |
312c004d3 [PATCH] driver co... |
935 936 937 938 939 940 941 942 943 944 |
"pa%08Xpb%08Xpc%08Xpd%08X", p_dev->has_manf_id ? p_dev->manf_id : 0, p_dev->has_card_id ? p_dev->card_id : 0, p_dev->has_func_id ? p_dev->func_id : 0, p_dev->func, p_dev->device_no, hash[0], hash[1], hash[2], hash[3])) |
840c2ac5d [PATCH] pcmcia: h... |
945 |
return -ENOMEM; |
840c2ac5d [PATCH] pcmcia: h... |
946 947 |
return 0; } |
3f8df781f PM: remove deprec... |
948 |
/************************ runtime PM support ***************************/ |
ad8d52b89 pcmcia: ds: fix s... |
949 |
static int pcmcia_dev_suspend(struct device *dev); |
3f8df781f PM: remove deprec... |
950 951 952 953 954 |
static int pcmcia_dev_resume(struct device *dev); static int runtime_suspend(struct device *dev) { int rc; |
8e9394ce2 Driver core: crea... |
955 |
device_lock(dev); |
ad8d52b89 pcmcia: ds: fix s... |
956 |
rc = pcmcia_dev_suspend(dev); |
8e9394ce2 Driver core: crea... |
957 |
device_unlock(dev); |
3f8df781f PM: remove deprec... |
958 959 |
return rc; } |
933a838aa pcmcia: make use ... |
960 |
static int runtime_resume(struct device *dev) |
3f8df781f PM: remove deprec... |
961 962 |
{ int rc; |
8e9394ce2 Driver core: crea... |
963 |
device_lock(dev); |
3f8df781f PM: remove deprec... |
964 |
rc = pcmcia_dev_resume(dev); |
8e9394ce2 Driver core: crea... |
965 |
device_unlock(dev); |
933a838aa pcmcia: make use ... |
966 |
return rc; |
3f8df781f PM: remove deprec... |
967 |
} |
1da177e4c Linux-2.6.12-rc2 |
968 969 970 |
/************************ per-device sysfs output ***************************/ #define pcmcia_device_attr(field, test, format) \ |
e404e274f [PATCH] Driver Co... |
971 |
static ssize_t field##_show (struct device *dev, struct device_attribute *attr, char *buf) \ |
1da177e4c Linux-2.6.12-rc2 |
972 973 |
{ \ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \ |
9fea84f46 pcmcia: CodingSty... |
974 |
return p_dev->test ? sprintf(buf, format, p_dev->field) : -ENODEV; \ |
b9b2f3676 pcmcia: convert b... |
975 976 |
} \ static DEVICE_ATTR_RO(field); |
1da177e4c Linux-2.6.12-rc2 |
977 978 |
#define pcmcia_device_stringattr(name, field) \ |
e404e274f [PATCH] Driver Co... |
979 |
static ssize_t name##_show (struct device *dev, struct device_attribute *attr, char *buf) \ |
1da177e4c Linux-2.6.12-rc2 |
980 981 |
{ \ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \ |
9fea84f46 pcmcia: CodingSty... |
982 983 |
return p_dev->field ? sprintf(buf, "%s ", p_dev->field) : -ENODEV; \ |
b9b2f3676 pcmcia: convert b... |
984 985 |
} \ static DEVICE_ATTR_RO(name); |
1da177e4c Linux-2.6.12-rc2 |
986 |
|
1da177e4c Linux-2.6.12-rc2 |
987 988 989 990 991 992 993 994 995 996 |
pcmcia_device_attr(func_id, has_func_id, "0x%02x "); pcmcia_device_attr(manf_id, has_manf_id, "0x%04x "); pcmcia_device_attr(card_id, has_card_id, "0x%04x "); pcmcia_device_stringattr(prod_id1, prod_id[0]); pcmcia_device_stringattr(prod_id2, prod_id[1]); pcmcia_device_stringattr(prod_id3, prod_id[2]); pcmcia_device_stringattr(prod_id4, prod_id[3]); |
b9b2f3676 pcmcia: convert b... |
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 |
static ssize_t function_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); return p_dev->socket ? sprintf(buf, "0x%02x ", p_dev->func) : -ENODEV; } static DEVICE_ATTR_RO(function); static ssize_t resources_show(struct device *dev, struct device_attribute *attr, char *buf) |
8f677ea07 pcmcia: export re... |
1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 |
{ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); char *str = buf; int i; for (i = 0; i < PCMCIA_NUM_RESOURCES; i++) str += sprintf(str, "%pr ", p_dev->resource[i]); return str - buf; } |
b9b2f3676 pcmcia: convert b... |
1019 |
static DEVICE_ATTR_RO(resources); |
db1019ca0 [PATCH] pcmcia: r... |
1020 |
|
b9b2f3676 pcmcia: convert b... |
1021 |
static ssize_t pm_state_show(struct device *dev, struct device_attribute *attr, char *buf) |
db1019ca0 [PATCH] pcmcia: r... |
1022 1023 |
{ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
f6fbe01ac [PATCH] pcmcia: r... |
1024 |
if (p_dev->suspended) |
db1019ca0 [PATCH] pcmcia: r... |
1025 1026 1027 1028 1029 1030 |
return sprintf(buf, "off "); else return sprintf(buf, "on "); } |
b9b2f3676 pcmcia: convert b... |
1031 1032 |
static ssize_t pm_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
db1019ca0 [PATCH] pcmcia: r... |
1033 1034 1035 |
{ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); int ret = 0; |
9fea84f46 pcmcia: CodingSty... |
1036 1037 |
if (!count) return -EINVAL; |
db1019ca0 [PATCH] pcmcia: r... |
1038 |
|
f6fbe01ac [PATCH] pcmcia: r... |
1039 |
if ((!p_dev->suspended) && !strncmp(buf, "off", 3)) |
3f8df781f PM: remove deprec... |
1040 |
ret = runtime_suspend(dev); |
f6fbe01ac [PATCH] pcmcia: r... |
1041 |
else if (p_dev->suspended && !strncmp(buf, "on", 2)) |
933a838aa pcmcia: make use ... |
1042 |
ret = runtime_resume(dev); |
db1019ca0 [PATCH] pcmcia: r... |
1043 1044 1045 |
return ret ? ret : count; } |
b9b2f3676 pcmcia: convert b... |
1046 |
static DEVICE_ATTR_RW(pm_state); |
db1019ca0 [PATCH] pcmcia: r... |
1047 |
|
3704511b2 [PATCH] pcmcia: f... |
1048 |
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) |
3248ff43f [PATCH] pcmcia: e... |
1049 1050 1051 1052 1053 1054 |
{ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); int i; u32 hash[4] = { 0, 0, 0, 0}; /* calculate hashes */ |
9fea84f46 pcmcia: CodingSty... |
1055 |
for (i = 0; i < 4; i++) { |
3248ff43f [PATCH] pcmcia: e... |
1056 1057 |
if (!p_dev->prod_id[i]) continue; |
9fea84f46 pcmcia: CodingSty... |
1058 1059 |
hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i])); |
3248ff43f [PATCH] pcmcia: e... |
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 |
} return sprintf(buf, "pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" "pa%08Xpb%08Xpc%08Xpd%08X ", p_dev->has_manf_id ? p_dev->manf_id : 0, p_dev->has_card_id ? p_dev->card_id : 0, p_dev->has_func_id ? p_dev->func_id : 0, p_dev->func, p_dev->device_no, hash[0], hash[1], hash[2], hash[3]); } |
b9b2f3676 pcmcia: convert b... |
1070 |
static DEVICE_ATTR_RO(modalias); |
a5b557789 [PATCH] pcmcia: a... |
1071 |
|
b9b2f3676 pcmcia: convert b... |
1072 |
static ssize_t allow_func_id_match_store(struct device *dev, |
3248ff43f [PATCH] pcmcia: e... |
1073 |
struct device_attribute *attr, const char *buf, size_t count) |
a5b557789 [PATCH] pcmcia: a... |
1074 1075 |
{ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
db1019ca0 [PATCH] pcmcia: r... |
1076 1077 1078 |
if (!count) return -EINVAL; |
a5b557789 [PATCH] pcmcia: a... |
1079 |
|
94a819f80 pcmcia: assert lo... |
1080 |
mutex_lock(&p_dev->socket->ops_mutex); |
a5b557789 [PATCH] pcmcia: a... |
1081 |
p_dev->allow_func_id_match = 1; |
94a819f80 pcmcia: assert lo... |
1082 |
mutex_unlock(&p_dev->socket->ops_mutex); |
af461fc18 pcmcia: delay re-... |
1083 |
pcmcia_parse_uevents(p_dev->socket, PCMCIA_UEVENT_REQUERY); |
a5b557789 [PATCH] pcmcia: a... |
1084 1085 1086 |
return count; } |
b9b2f3676 pcmcia: convert b... |
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 |
static DEVICE_ATTR_WO(allow_func_id_match); static struct attribute *pcmcia_dev_attrs[] = { &dev_attr_resources.attr, &dev_attr_pm_state.attr, &dev_attr_function.attr, &dev_attr_func_id.attr, &dev_attr_manf_id.attr, &dev_attr_card_id.attr, &dev_attr_prod_id1.attr, &dev_attr_prod_id2.attr, &dev_attr_prod_id3.attr, &dev_attr_prod_id4.attr, &dev_attr_modalias.attr, &dev_attr_allow_func_id_match.attr, NULL, |
1da177e4c Linux-2.6.12-rc2 |
1103 |
}; |
b9b2f3676 pcmcia: convert b... |
1104 |
ATTRIBUTE_GROUPS(pcmcia_dev); |
1da177e4c Linux-2.6.12-rc2 |
1105 |
|
8e9e793d6 [PATCH] pcmcia: m... |
1106 |
/* PM support, also needed for reset */ |
ad8d52b89 pcmcia: ds: fix s... |
1107 |
static int pcmcia_dev_suspend(struct device *dev) |
8e9e793d6 [PATCH] pcmcia: m... |
1108 1109 1110 |
{ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct pcmcia_driver *p_drv = NULL; |
f6fbe01ac [PATCH] pcmcia: r... |
1111 |
int ret = 0; |
8e9e793d6 [PATCH] pcmcia: m... |
1112 |
|
94a819f80 pcmcia: assert lo... |
1113 1114 1115 |
mutex_lock(&p_dev->socket->ops_mutex); if (p_dev->suspended) { mutex_unlock(&p_dev->socket->ops_mutex); |
d6b4fa6d6 pcmcia: stop upda... |
1116 |
return 0; |
94a819f80 pcmcia: assert lo... |
1117 1118 1119 |
} p_dev->suspended = 1; mutex_unlock(&p_dev->socket->ops_mutex); |
d6b4fa6d6 pcmcia: stop upda... |
1120 |
|
d50dbec3c pcmcia: use dynam... |
1121 1122 |
dev_dbg(dev, "suspending "); |
d9d9ea016 [PATCH] pcmcia: d... |
1123 |
|
8e9e793d6 [PATCH] pcmcia: m... |
1124 1125 |
if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); |
e2d409636 [PATCH] pcmcia: u... |
1126 1127 1128 1129 |
if (!p_drv) goto out; if (p_drv->suspend) { |
8661bb5b4 [PATCH] pcmcia: d... |
1130 |
ret = p_drv->suspend(p_dev); |
d9d9ea016 [PATCH] pcmcia: d... |
1131 |
if (ret) { |
f2e6cf767 pcmcia: Convert d... |
1132 1133 1134 1135 |
dev_err(dev, "pcmcia: device %s (driver %s) did not want to go to sleep (%d) ", p_dev->devname, p_drv->name, ret); |
94a819f80 pcmcia: assert lo... |
1136 1137 1138 |
mutex_lock(&p_dev->socket->ops_mutex); p_dev->suspended = 0; mutex_unlock(&p_dev->socket->ops_mutex); |
f6fbe01ac [PATCH] pcmcia: r... |
1139 |
goto out; |
d9d9ea016 [PATCH] pcmcia: d... |
1140 |
} |
8661bb5b4 [PATCH] pcmcia: d... |
1141 |
} |
8e9e793d6 [PATCH] pcmcia: m... |
1142 |
|
d9d9ea016 [PATCH] pcmcia: d... |
1143 |
if (p_dev->device_no == p_dev->func) { |
d50dbec3c pcmcia: use dynam... |
1144 1145 |
dev_dbg(dev, "releasing configuration "); |
e2d409636 [PATCH] pcmcia: u... |
1146 |
pcmcia_release_configuration(p_dev); |
d9d9ea016 [PATCH] pcmcia: d... |
1147 |
} |
e2d409636 [PATCH] pcmcia: u... |
1148 |
|
f6fbe01ac [PATCH] pcmcia: r... |
1149 |
out: |
f6fbe01ac [PATCH] pcmcia: r... |
1150 |
return ret; |
8e9e793d6 [PATCH] pcmcia: m... |
1151 |
} |
9fea84f46 pcmcia: CodingSty... |
1152 |
static int pcmcia_dev_resume(struct device *dev) |
8e9e793d6 [PATCH] pcmcia: m... |
1153 1154 |
{ struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
9fea84f46 pcmcia: CodingSty... |
1155 |
struct pcmcia_driver *p_drv = NULL; |
f6fbe01ac [PATCH] pcmcia: r... |
1156 |
int ret = 0; |
8e9e793d6 [PATCH] pcmcia: m... |
1157 |
|
94a819f80 pcmcia: assert lo... |
1158 1159 1160 |
mutex_lock(&p_dev->socket->ops_mutex); if (!p_dev->suspended) { mutex_unlock(&p_dev->socket->ops_mutex); |
d6b4fa6d6 pcmcia: stop upda... |
1161 |
return 0; |
94a819f80 pcmcia: assert lo... |
1162 1163 1164 |
} p_dev->suspended = 0; mutex_unlock(&p_dev->socket->ops_mutex); |
d6b4fa6d6 pcmcia: stop upda... |
1165 |
|
d50dbec3c pcmcia: use dynam... |
1166 1167 |
dev_dbg(dev, "resuming "); |
d9d9ea016 [PATCH] pcmcia: d... |
1168 |
|
8e9e793d6 [PATCH] pcmcia: m... |
1169 1170 |
if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); |
e2d409636 [PATCH] pcmcia: u... |
1171 1172 1173 1174 |
if (!p_drv) goto out; if (p_dev->device_no == p_dev->func) { |
d50dbec3c pcmcia: use dynam... |
1175 1176 |
dev_dbg(dev, "requesting configuration "); |
1ac71e5a3 pcmcia: convert p... |
1177 |
ret = pcmcia_enable_device(p_dev); |
e2d409636 [PATCH] pcmcia: u... |
1178 1179 |
if (ret) goto out; |
8661bb5b4 [PATCH] pcmcia: d... |
1180 |
} |
8e9e793d6 [PATCH] pcmcia: m... |
1181 |
|
e2d409636 [PATCH] pcmcia: u... |
1182 1183 |
if (p_drv->resume) ret = p_drv->resume(p_dev); |
f6fbe01ac [PATCH] pcmcia: r... |
1184 |
out: |
f6fbe01ac [PATCH] pcmcia: r... |
1185 |
return ret; |
8e9e793d6 [PATCH] pcmcia: m... |
1186 |
} |
46f533ccb drivers: pcmcia: ... |
1187 |
static int pcmcia_bus_suspend_callback(struct device *dev, void *_data) |
8e9e793d6 [PATCH] pcmcia: m... |
1188 1189 1190 |
{ struct pcmcia_socket *skt = _data; struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
3f8df781f PM: remove deprec... |
1191 |
if (p_dev->socket != skt || p_dev->suspended) |
8e9e793d6 [PATCH] pcmcia: m... |
1192 |
return 0; |
3f8df781f PM: remove deprec... |
1193 |
return runtime_suspend(dev); |
8e9e793d6 [PATCH] pcmcia: m... |
1194 |
} |
46f533ccb drivers: pcmcia: ... |
1195 |
static int pcmcia_bus_resume_callback(struct device *dev, void *_data) |
8e9e793d6 [PATCH] pcmcia: m... |
1196 1197 1198 |
{ struct pcmcia_socket *skt = _data; struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
3f8df781f PM: remove deprec... |
1199 |
if (p_dev->socket != skt || !p_dev->suspended) |
8e9e793d6 [PATCH] pcmcia: m... |
1200 |
return 0; |
3f8df781f PM: remove deprec... |
1201 |
runtime_resume(dev); |
8e9e793d6 [PATCH] pcmcia: m... |
1202 1203 1204 1205 1206 1207 |
return 0; } static int pcmcia_bus_resume(struct pcmcia_socket *skt) { |
d50dbec3c pcmcia: use dynam... |
1208 1209 |
dev_dbg(&skt->dev, "resuming socket %d ", skt->sock); |
8e9e793d6 [PATCH] pcmcia: m... |
1210 1211 1212 1213 1214 1215 |
bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback); return 0; } static int pcmcia_bus_suspend(struct pcmcia_socket *skt) { |
d50dbec3c pcmcia: use dynam... |
1216 1217 |
dev_dbg(&skt->dev, "suspending socket %d ", skt->sock); |
8e9e793d6 [PATCH] pcmcia: m... |
1218 1219 1220 1221 1222 1223 1224 |
if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_suspend_callback)) { pcmcia_bus_resume(skt); return -EIO; } return 0; } |
7b24e7988 pcmcia: split up ... |
1225 1226 1227 1228 |
static int pcmcia_bus_remove(struct pcmcia_socket *skt) { atomic_set(&skt->present, 0); pcmcia_card_remove(skt, NULL); |
1da177e4c Linux-2.6.12-rc2 |
1229 |
|
7b24e7988 pcmcia: split up ... |
1230 1231 1232 1233 |
mutex_lock(&skt->ops_mutex); destroy_cis_cache(skt); pcmcia_cleanup_irq(skt); mutex_unlock(&skt->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
1234 |
|
7b24e7988 pcmcia: split up ... |
1235 1236 |
return 0; } |
9fea84f46 pcmcia: CodingSty... |
1237 |
|
7b24e7988 pcmcia: split up ... |
1238 1239 1240 |
static int pcmcia_bus_add(struct pcmcia_socket *skt) { atomic_set(&skt->present, 1); |
1da177e4c Linux-2.6.12-rc2 |
1241 |
|
7b24e7988 pcmcia: split up ... |
1242 |
mutex_lock(&skt->ops_mutex); |
ce3f9d71b pcmcia: remove un... |
1243 |
skt->pcmcia_pfc = 0; |
7b24e7988 pcmcia: split up ... |
1244 1245 |
destroy_cis_cache(skt); /* to be on the safe side... */ mutex_unlock(&skt->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
1246 |
|
7b24e7988 pcmcia: split up ... |
1247 |
pcmcia_card_add(skt); |
1da177e4c Linux-2.6.12-rc2 |
1248 |
|
7b24e7988 pcmcia: split up ... |
1249 1250 |
return 0; } |
1617406a7 [PATCH] pcmcia: m... |
1251 |
|
7b24e7988 pcmcia: split up ... |
1252 1253 |
static int pcmcia_bus_early_resume(struct pcmcia_socket *skt) { |
025e4ab3d pcmcia: fix socke... |
1254 |
if (!verify_cis_cache(skt)) |
7b24e7988 pcmcia: split up ... |
1255 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1256 |
|
7b24e7988 pcmcia: split up ... |
1257 1258 |
dev_dbg(&skt->dev, "cis mismatch - different card "); |
f8cfa618d [PATCH] pcmcia: u... |
1259 |
|
7b24e7988 pcmcia: split up ... |
1260 1261 |
/* first, remove the card */ pcmcia_bus_remove(skt); |
88b060d6c pcmcia: improve c... |
1262 |
|
7b24e7988 pcmcia: split up ... |
1263 1264 1265 1266 1267 1268 |
mutex_lock(&skt->ops_mutex); destroy_cis_cache(skt); kfree(skt->fake_cis); skt->fake_cis = NULL; skt->functions = 0; mutex_unlock(&skt->ops_mutex); |
1da177e4c Linux-2.6.12-rc2 |
1269 |
|
7b24e7988 pcmcia: split up ... |
1270 1271 1272 1273 |
/* now, add the new card */ pcmcia_bus_add(skt); return 0; } |
dc109497b [PATCH] pcmcia: m... |
1274 |
|
1da177e4c Linux-2.6.12-rc2 |
1275 |
|
04de08161 pcmcia: pcmcia_de... |
1276 1277 1278 1279 1280 1281 1282 |
/* * NOTE: This is racy. There's no guarantee the card will still be * physically present, even if the call to this function returns * non-NULL. Furthermore, the device driver most likely is unbound * almost immediately, so the timeframe where pcmcia_dev_present * returns NULL is probably really really small. */ |
9fea84f46 pcmcia: CodingSty... |
1283 |
struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev) |
9940ec361 [PATCH] pcmcia: c... |
1284 1285 1286 1287 1288 1289 1290 |
{ struct pcmcia_device *p_dev; struct pcmcia_device *ret = NULL; p_dev = pcmcia_get_dev(_p_dev); if (!p_dev) return NULL; |
04de08161 pcmcia: pcmcia_de... |
1291 1292 |
if (atomic_read(&p_dev->socket->present) != 0) ret = p_dev; |
9940ec361 [PATCH] pcmcia: c... |
1293 |
|
9940ec361 [PATCH] pcmcia: c... |
1294 1295 1296 1297 |
pcmcia_put_dev(p_dev); return ret; } EXPORT_SYMBOL(pcmcia_dev_present); |
90c6cdd1f [PATCH] pcmcia: c... |
1298 1299 |
static struct pcmcia_callback pcmcia_bus_callback = { .owner = THIS_MODULE, |
7b24e7988 pcmcia: split up ... |
1300 1301 |
.add = pcmcia_bus_add, .remove = pcmcia_bus_remove, |
af461fc18 pcmcia: delay re-... |
1302 |
.requery = pcmcia_requery, |
6e7b51a73 pcmcia: move cist... |
1303 |
.validate = pccard_validate_cis, |
8e9e793d6 [PATCH] pcmcia: m... |
1304 |
.suspend = pcmcia_bus_suspend, |
7b24e7988 pcmcia: split up ... |
1305 |
.early_resume = pcmcia_bus_early_resume, |
8e9e793d6 [PATCH] pcmcia: m... |
1306 |
.resume = pcmcia_bus_resume, |
90c6cdd1f [PATCH] pcmcia: c... |
1307 |
}; |
34cdf25a1 pcmcia: remove us... |
1308 |
static int pcmcia_bus_add_socket(struct device *dev, |
d8539d81a [PATCH] Driver co... |
1309 |
struct class_interface *class_intf) |
1da177e4c Linux-2.6.12-rc2 |
1310 |
{ |
873733188 Driver core: conv... |
1311 |
struct pcmcia_socket *socket = dev_get_drvdata(dev); |
1da177e4c Linux-2.6.12-rc2 |
1312 |
int ret; |
dc109497b [PATCH] pcmcia: m... |
1313 1314 |
socket = pcmcia_get_socket(socket); if (!socket) { |
f2e6cf767 pcmcia: Convert d... |
1315 1316 |
dev_err(dev, "PCMCIA obtaining reference to socket failed "); |
1da177e4c Linux-2.6.12-rc2 |
1317 1318 |
return -ENODEV; } |
6e7b51a73 pcmcia: move cist... |
1319 1320 |
ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr); if (ret) { |
f2e6cf767 pcmcia: Convert d... |
1321 1322 |
dev_err(dev, "PCMCIA registration failed "); |
6e7b51a73 pcmcia: move cist... |
1323 1324 1325 |
pcmcia_put_socket(socket); return ret; } |
dc109497b [PATCH] pcmcia: m... |
1326 |
INIT_LIST_HEAD(&socket->devices_list); |
ce3f9d71b pcmcia: remove un... |
1327 |
socket->pcmcia_pfc = 0; |
dc109497b [PATCH] pcmcia: m... |
1328 |
socket->device_count = 0; |
e4f1ac212 pcmcia: do not in... |
1329 |
atomic_set(&socket->present, 0); |
1da177e4c Linux-2.6.12-rc2 |
1330 |
|
90c6cdd1f [PATCH] pcmcia: c... |
1331 |
ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback); |
1da177e4c Linux-2.6.12-rc2 |
1332 |
if (ret) { |
f2e6cf767 pcmcia: Convert d... |
1333 1334 |
dev_err(dev, "PCMCIA registration failed "); |
dc109497b [PATCH] pcmcia: m... |
1335 |
pcmcia_put_socket(socket); |
9fea84f46 pcmcia: CodingSty... |
1336 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
1337 1338 1339 1340 |
} return 0; } |
873733188 Driver core: conv... |
1341 |
static void pcmcia_bus_remove_socket(struct device *dev, |
d8539d81a [PATCH] Driver co... |
1342 |
struct class_interface *class_intf) |
1da177e4c Linux-2.6.12-rc2 |
1343 |
{ |
873733188 Driver core: conv... |
1344 |
struct pcmcia_socket *socket = dev_get_drvdata(dev); |
1da177e4c Linux-2.6.12-rc2 |
1345 |
|
dc109497b [PATCH] pcmcia: m... |
1346 |
if (!socket) |
1da177e4c Linux-2.6.12-rc2 |
1347 1348 1349 |
return; pccard_register_pcmcia(socket, NULL); |
dfbc9e9d3 [PATCH] pcmcia: f... |
1350 |
/* unregister any unbound devices */ |
8e4d9dcb4 [PATCH] fix "pcmc... |
1351 |
mutex_lock(&socket->skt_mutex); |
dfbc9e9d3 [PATCH] pcmcia: f... |
1352 |
pcmcia_card_remove(socket, NULL); |
180c33ee4 pcmcia: call CIS ... |
1353 |
release_cis_mem(socket); |
8e4d9dcb4 [PATCH] fix "pcmc... |
1354 |
mutex_unlock(&socket->skt_mutex); |
dfbc9e9d3 [PATCH] pcmcia: f... |
1355 |
|
6e7b51a73 pcmcia: move cist... |
1356 |
sysfs_remove_bin_file(&dev->kobj, &pccard_cis_attr); |
dc109497b [PATCH] pcmcia: m... |
1357 |
pcmcia_put_socket(socket); |
1da177e4c Linux-2.6.12-rc2 |
1358 1359 1360 1361 1362 1363 |
return; } /* the pcmcia_bus_interface is used to handle pcmcia socket devices */ |
ed49f5d00 pcmcia: silence s... |
1364 |
static struct class_interface pcmcia_bus_interface __refdata = { |
1da177e4c Linux-2.6.12-rc2 |
1365 |
.class = &pcmcia_socket_class, |
873733188 Driver core: conv... |
1366 1367 |
.add_dev = &pcmcia_bus_add_socket, .remove_dev = &pcmcia_bus_remove_socket, |
1da177e4c Linux-2.6.12-rc2 |
1368 |
}; |
ad8d52b89 pcmcia: ds: fix s... |
1369 1370 1371 |
static const struct dev_pm_ops pcmcia_bus_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(pcmcia_dev_suspend, pcmcia_dev_resume) }; |
1da177e4c Linux-2.6.12-rc2 |
1372 |
|
e7a480d22 [PATCH] pcmcia: m... |
1373 |
struct bus_type pcmcia_bus_type = { |
1da177e4c Linux-2.6.12-rc2 |
1374 |
.name = "pcmcia", |
312c004d3 [PATCH] driver co... |
1375 |
.uevent = pcmcia_bus_uevent, |
1da177e4c Linux-2.6.12-rc2 |
1376 |
.match = pcmcia_bus_match, |
b9b2f3676 pcmcia: convert b... |
1377 |
.dev_groups = pcmcia_dev_groups, |
1d0baa3a1 [PATCH] Add pcmci... |
1378 1379 |
.probe = pcmcia_device_probe, .remove = pcmcia_device_remove, |
ad8d52b89 pcmcia: ds: fix s... |
1380 |
.pm = &pcmcia_bus_pm_ops, |
1da177e4c Linux-2.6.12-rc2 |
1381 |
}; |
1da177e4c Linux-2.6.12-rc2 |
1382 1383 1384 1385 |
static int __init init_pcmcia_bus(void) { |
ace7d4772 [PATCH] pcmcia/ds... |
1386 |
int ret; |
ace7d4772 [PATCH] pcmcia/ds... |
1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 |
ret = bus_register(&pcmcia_bus_type); if (ret < 0) { printk(KERN_WARNING "pcmcia: bus_register error: %d ", ret); return ret; } ret = class_interface_register(&pcmcia_bus_interface); if (ret < 0) { printk(KERN_WARNING "pcmcia: class_interface_register error: %d ", ret); bus_unregister(&pcmcia_bus_type); return ret; } |
1da177e4c Linux-2.6.12-rc2 |
1401 |
|
1da177e4c Linux-2.6.12-rc2 |
1402 1403 |
return 0; } |
9fea84f46 pcmcia: CodingSty... |
1404 |
fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that |
1da177e4c Linux-2.6.12-rc2 |
1405 1406 1407 1408 1409 |
* pcmcia_socket_class is already registered */ static void __exit exit_pcmcia_bus(void) { |
e7a480d22 [PATCH] pcmcia: m... |
1410 |
class_interface_unregister(&pcmcia_bus_interface); |
1da177e4c Linux-2.6.12-rc2 |
1411 1412 1413 1414 |
bus_unregister(&pcmcia_bus_type); } module_exit(exit_pcmcia_bus); |
1da177e4c Linux-2.6.12-rc2 |
1415 |
MODULE_ALIAS("ds"); |