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