Blame view

drivers/pcmcia/ds.c 35 KB
1da177e4c   Linus Torvalds   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   Dominik Brodowski   pcmcia: split up ...
13
   * (C) 2003 - 2010	Dominik Brodowski
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
   */
3b659fb86   Dominik Brodowski   [PATCH] pcmcia: r...
15
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <linux/errno.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
  #include <linux/list.h>
  #include <linux/delay.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
  #include <linux/workqueue.h>
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
22
  #include <linux/crc32.h>
daa9517d9   Dominik Brodowski   [PATCH] pcmcia: r...
23
  #include <linux/firmware.h>
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
24
  #include <linux/kref.h>
43d9f7fda   James Bottomley   pcmcia: use DMA_M...
25
  #include <linux/dma-mapping.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
26
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27

1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
41

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  /*====================================================================*/
23a83bfe6   Dominik Brodowski   [PATCH] pcmcia: c...
43
44
  static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
  {
e9fb13bfe   Joe Perches   pcmcia: Make decl...
45
  	const struct pcmcia_device_id *did = p_drv->id_table;
23a83bfe6   Dominik Brodowski   [PATCH] pcmcia: c...
46
47
  	unsigned int i;
  	u32 hash;
f8cfa618d   Dominik Brodowski   [PATCH] pcmcia: u...
48
  	if (!p_drv->probe || !p_drv->remove)
ba5bb6b58   Pavel Roskin   [PATCH] pcmcia: f...
49
  		printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
50
51
  		       "function
  ", p_drv->name);
1e212f364   Dominik Brodowski   [PATCH] pcmcia: m...
52

23a83bfe6   Dominik Brodowski   [PATCH] pcmcia: c...
53
  	while (did && did->match_flags) {
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
54
  		for (i = 0; i < 4; i++) {
23a83bfe6   Dominik Brodowski   [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   Dominik Brodowski   pcmcia: move driv...
64
65
  			       "be 0x%x
  ", p_drv->name, did->prod_id[i],
23a83bfe6   Dominik Brodowski   [PATCH] pcmcia: c...
66
  			       did->prod_id_hash[i], hash);
5085cb265   Dominik Brodowski   [PATCH] pcmcia: a...
67
68
69
70
  			printk(KERN_DEBUG "pcmcia: see "
  				"Documentation/pcmcia/devicetable.txt for "
  				"details
  ");
23a83bfe6   Dominik Brodowski   [PATCH] pcmcia: c...
71
72
73
74
75
76
  		}
  		did++;
  	}
  
  	return;
  }
daa9517d9   Dominik Brodowski   [PATCH] pcmcia: r...
77

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  /*======================================================================*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79

6179b5562   Bernhard Walle   add new_id to PCM...
80
  struct pcmcia_dynid {
46f533ccb   Laurent Navet   drivers: pcmcia: ...
81
82
  	struct list_head		node;
  	struct pcmcia_device_id		id;
6179b5562   Bernhard Walle   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   Greg Kroah-Hartman   pcmcia: ds: conve...
95
  new_id_store(struct device_driver *driver, const char *buf, size_t count)
6179b5562   Bernhard Walle   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   Dominik Brodowski   pcmcia: CodingSty...
102
  	int fields = 0;
6179b5562   Bernhard Walle   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   Bernhard Walle   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   Dominik Brodowski   pcmcia: use mutex...
121
  	mutex_lock(&pdrv->dynids.lock);
b4b3d7bbe   Wolfram Sang   pcmcia: fix incor...
122
  	list_add_tail(&dynid->node, &pdrv->dynids.list);
3f565232c   Dominik Brodowski   pcmcia: use mutex...
123
  	mutex_unlock(&pdrv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
124

cef9bc56e   Alan Stern   Dynamic ID additi...
125
  	retval = driver_attach(&pdrv->drv);
6179b5562   Bernhard Walle   add new_id to PCM...
126
127
128
129
130
  
  	if (retval)
  		return retval;
  	return count;
  }
ad8f20a45   Greg Kroah-Hartman   pcmcia: ds: conve...
131
  static DRIVER_ATTR_WO(new_id);
6179b5562   Bernhard Walle   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   Dominik Brodowski   pcmcia: use mutex...
137
  	mutex_lock(&drv->dynids.lock);
6179b5562   Bernhard Walle   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   Dominik Brodowski   pcmcia: use mutex...
142
  	mutex_unlock(&drv->dynids.lock);
6179b5562   Bernhard Walle   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   Greg Kroah-Hartman   PCMCIA: use prope...
150
  		error = driver_create_file(&drv->drv, &driver_attr_new_id);
6179b5562   Bernhard Walle   add new_id to PCM...
151
152
  	return error;
  }
ed283e9f0   Alan Stern   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   Bernhard Walle   add new_id to PCM...
158

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
  /**
   * pcmcia_register_driver - register a PCMCIA driver with the bus core
78187865e   Randy Dunlap   pcmcia: fix kerne...
161
   * @driver: the &driver being registered
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
164
   *
   * Registers a PCMCIA driver with the PCMCIA bus core.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
  int pcmcia_register_driver(struct pcmcia_driver *driver)
  {
6179b5562   Bernhard Walle   add new_id to PCM...
167
  	int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
  	if (!driver)
  		return -EINVAL;
23a83bfe6   Dominik Brodowski   [PATCH] pcmcia: c...
170
  	pcmcia_check_driver(driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
173
  	/* initialize common fields */
  	driver->drv.bus = &pcmcia_bus_type;
  	driver->drv.owner = driver->owner;
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
174
  	driver->drv.name = driver->name;
3f565232c   Dominik Brodowski   pcmcia: use mutex...
175
  	mutex_init(&driver->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
176
  	INIT_LIST_HEAD(&driver->dynids.list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177

2e9b981a7   Dominik Brodowski   pcmcia: move driv...
178
179
  	pr_debug("registering driver %s
  ", driver->name);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
180

6179b5562   Bernhard Walle   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   Linus Torvalds   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   Randy Dunlap   pcmcia: fix kerne...
195
   * @driver: the &driver being unregistered
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
198
   */
  void pcmcia_unregister_driver(struct pcmcia_driver *driver)
  {
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
199
200
  	pr_debug("unregistering driver %s
  ", driver->name);
ed283e9f0   Alan Stern   USB/PCI/PCMCIA: C...
201
  	pcmcia_remove_newid_file(driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  	driver_unregister(&driver->drv);
6179b5562   Bernhard Walle   add new_id to PCM...
203
  	pcmcia_free_dynids(driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
  }
  EXPORT_SYMBOL(pcmcia_unregister_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
  
  /* pcmcia_device handling */
5716d415f   Dominik Brodowski   pcmcia: remove ob...
208
  static struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev)
1da177e4c   Linus Torvalds   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   Dominik Brodowski   pcmcia: remove ob...
216
  static void pcmcia_put_dev(struct pcmcia_device *p_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
220
  {
  	if (p_dev)
  		put_device(&p_dev->dev);
  }
360b65b95   Dominik Brodowski   [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   Dominik Brodowski   pcmcia: use dynam...
224
225
  	pr_debug("releasing config_t
  ");
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
226
227
  	kfree(c);
  }
1da177e4c   Linus Torvalds   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   Dominik Brodowski   pcmcia: avoid pro...
231
  	int i;
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
232
233
  	dev_dbg(dev, "releasing device
  ");
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
234
  	pcmcia_put_socket(p_dev->socket);
44961a03a   Dominik Brodowski   pcmcia: avoid pro...
235
236
  	for (i = 0; i < 4; i++)
  		kfree(p_dev->prod_id[i]);
bd65a6857   Brice Goglin   [PATCH] pcmcia: a...
237
  	kfree(p_dev->devname);
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
238
  	kref_put(&p_dev->function_config->ref, pcmcia_release_function);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
  	kfree(p_dev);
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
241
  static int pcmcia_device_probe(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
  {
  	struct pcmcia_device *p_dev;
  	struct pcmcia_driver *p_drv;
f8cfa618d   Dominik Brodowski   [PATCH] pcmcia: u...
245
  	struct pcmcia_socket *s;
af2b3b503   Dominik Brodowski   [PATCH] pcmcia: c...
246
  	cistpl_config_t cis_config;
1da177e4c   Linus Torvalds   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   Dominik Brodowski   [PATCH] pcmcia: u...
255
  	s = p_dev->socket;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256

2e9b981a7   Dominik Brodowski   pcmcia: move driv...
257
258
  	dev_dbg(dev, "trying to bind to %s
  ", p_drv->name);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
259

360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
260
261
  	if ((!p_drv->probe) || (!p_dev->function_config) ||
  	    (!try_module_get(p_drv->owner))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
  		ret = -EINVAL;
  		goto put_dev;
  	}
af2b3b503   Dominik Brodowski   [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   Dominik Brodowski   pcmcia: move conf...
269
270
  		p_dev->config_base = cis_config.base;
  		p_dev->config_regs = cis_config.rmask[0];
1cc745d1c   Dominik Brodowski   pcmcia: remove th...
271
272
  		dev_dbg(dev, "base %x, regs %x", p_dev->config_base,
  			p_dev->config_regs);
af2b3b503   Dominik Brodowski   [PATCH] pcmcia: c...
273
  	} else {
f2e6cf767   Joe Perches   pcmcia: Convert d...
274
275
276
  		dev_info(dev,
  			 "pcmcia: could not parse base and rmask0 of CIS
  ");
7feabb641   Dominik Brodowski   pcmcia: move conf...
277
278
  		p_dev->config_base = 0;
  		p_dev->config_regs = 0;
af2b3b503   Dominik Brodowski   [PATCH] pcmcia: c...
279
  	}
f8cfa618d   Dominik Brodowski   [PATCH] pcmcia: u...
280
  	ret = p_drv->probe(p_dev);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
281
  	if (ret) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
282
283
  		dev_dbg(dev, "binding to %s failed with %d
  ",
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
284
  			   p_drv->name, ret);
82d56e6d2   Dominik Brodowski   [PATCH] pcmcia: p...
285
  		goto put_module;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
286
  	}
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
287
  	dev_dbg(dev, "%s bound: Vpp %d.%d, idx %x, IRQ %d", p_drv->name,
1cc745d1c   Dominik Brodowski   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   Dominik Brodowski   [PATCH] pcmcia: p...
292

00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
293
  	mutex_lock(&s->ops_mutex);
ce3f9d71b   Dominik Brodowski   pcmcia: remove un...
294
  	if ((s->pcmcia_pfc) &&
82d56e6d2   Dominik Brodowski   [PATCH] pcmcia: p...
295
  	    (p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
aa584ca4c   Dominik Brodowski   pcmcia: use state...
296
  		pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY);
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
297
  	mutex_unlock(&s->ops_mutex);
f8cfa618d   Dominik Brodowski   [PATCH] pcmcia: u...
298

cec5eb7be   Alan Cox   pcmcia: Fix broke...
299
  put_module:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
301
  	if (ret)
  		module_put(p_drv->owner);
cec5eb7be   Alan Cox   pcmcia: Fix broke...
302
  put_dev:
f8cfa618d   Dominik Brodowski   [PATCH] pcmcia: u...
303
  	if (ret)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
  		put_device(dev);
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
305
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
  }
d6ff5a853   Dominik Brodowski   [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   Dominik Brodowski   [PATCH] pcmcia: p...
314

d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
315
  	dev_dbg(leftover ? &leftover->dev : &s->dev,
ac449d6e2   Dominik Brodowski   pcmcia: use dev_p...
316
317
318
  		   "pcmcia_card_remove(%d) %s
  ", s->sock,
  		   leftover ? leftover->devname : "");
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
319

00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
320
  	mutex_lock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
321
322
323
324
  	if (!leftover)
  		s->device_count = 0;
  	else
  		s->device_count = 1;
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
325
  	mutex_unlock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [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   Dominik Brodowski   pcmcia: simplify ...
331
  		mutex_lock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
332
  		list_del(&p_dev->socket_device_list);
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
333
  		mutex_unlock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
334

d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
335
336
  		dev_dbg(&p_dev->dev, "unregistering device
  ");
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
337
338
339
340
341
  		device_unregister(&p_dev->dev);
  	}
  
  	return;
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
342
  static int pcmcia_device_remove(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
  {
  	struct pcmcia_device *p_dev;
  	struct pcmcia_driver *p_drv;
cc3b4866b   Dominik Brodowski   [PATCH] pcmcia: u...
346
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
  	p_dev = to_pcmcia_dev(dev);
  	p_drv = to_pcmcia_drv(dev->driver);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
350

d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
351
352
  	dev_dbg(dev, "removing device
  ");
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
353

d6ff5a853   Dominik Brodowski   [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   Dominik Brodowski   pcmcia: remove un...
358
  	if ((p_dev->socket->pcmcia_pfc) &&
e6e4f397e   Dominik Brodowski   pcmcia: protect s...
359
  	    (p_dev->socket->device_count > 0) &&
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
360
361
362
363
  	    (p_dev->device_no == 0))
  		pcmcia_card_remove(p_dev->socket, p_dev);
  
  	/* detach the "instance" */
f39907155   Dominik Brodowski   [PATCH] pcmcia: r...
364
365
  	if (!p_drv)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366

f39907155   Dominik Brodowski   [PATCH] pcmcia: r...
367
  	if (p_drv->remove)
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
368
  		p_drv->remove(p_dev);
cc3b4866b   Dominik Brodowski   [PATCH] pcmcia: u...
369

f39907155   Dominik Brodowski   [PATCH] pcmcia: r...
370
  	/* check for proper unloading */
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
371
  	if (p_dev->_irq || p_dev->_io || p_dev->_locked)
f2e6cf767   Joe Perches   pcmcia: Convert d...
372
373
374
375
  		dev_info(dev,
  			 "pcmcia: driver %s did not release config properly
  ",
  			 p_drv->name);
cc3b4866b   Dominik Brodowski   [PATCH] pcmcia: u...
376

f39907155   Dominik Brodowski   [PATCH] pcmcia: r...
377
  	for (i = 0; i < MAX_WIN; i++)
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
378
  		if (p_dev->_win & CLIENT_WIN_REQ(i))
f2e6cf767   Joe Perches   pcmcia: Convert d...
379
380
381
382
  			dev_info(dev,
  				 "pcmcia: driver %s did not release window properly
  ",
  				 p_drv->name);
cc3b4866b   Dominik Brodowski   [PATCH] pcmcia: u...
383

f39907155   Dominik Brodowski   [PATCH] pcmcia: r...
384
385
386
  	/* references from pcmcia_probe_device */
  	pcmcia_put_dev(p_dev);
  	module_put(p_drv->owner);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
389
  
  	return 0;
  }
cc3b4866b   Dominik Brodowski   [PATCH] pcmcia: u...
390
  /*
1da177e4c   Linus Torvalds   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   Ingo Molnar   [PATCH] pcmcia: r...
397
  	cistpl_vers_1_t	*vers1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
  	unsigned int i;
76fa82fb7   Ingo Molnar   [PATCH] pcmcia: r...
399
400
401
  	vers1 = kmalloc(sizeof(*vers1), GFP_KERNEL);
  	if (!vers1)
  		return -ENOMEM;
84897fc05   Dominik Brodowski   pcmcia: pccard_re...
402
  	if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
  			       CISTPL_MANFID, &manf_id)) {
af461fc18   Dominik Brodowski   pcmcia: delay re-...
404
  		mutex_lock(&p_dev->socket->ops_mutex);
1da177e4c   Linus Torvalds   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   Dominik Brodowski   pcmcia: delay re-...
409
  		mutex_unlock(&p_dev->socket->ops_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
412
413
  	}
  
  	if (!pccard_read_tuple(p_dev->socket, p_dev->func,
  			       CISTPL_FUNCID, &func_id)) {
af461fc18   Dominik Brodowski   pcmcia: delay re-...
414
  		mutex_lock(&p_dev->socket->ops_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
  		p_dev->func_id = func_id.func;
  		p_dev->has_func_id = 1;
af461fc18   Dominik Brodowski   pcmcia: delay re-...
417
  		mutex_unlock(&p_dev->socket->ops_mutex);
1da177e4c   Linus Torvalds   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   Ingo Molnar   [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   Linus Torvalds   Linux-2.6.12-rc2
429
  		if (!pccard_read_tuple(p_dev->socket, p_dev->func,
76fa82fb7   Ingo Molnar   [PATCH] pcmcia: r...
430
  				      CISTPL_DEVICE_GEO, devgeo)) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
431
  			dev_dbg(&p_dev->dev,
ac449d6e2   Dominik Brodowski   pcmcia: use dev_p...
432
433
434
  				   "mem device geometry probably means "
  				   "FUNCID_MEMORY
  ");
af461fc18   Dominik Brodowski   pcmcia: delay re-...
435
  			mutex_lock(&p_dev->socket->ops_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
437
  			p_dev->func_id = CISTPL_FUNCID_MEMORY;
  			p_dev->has_func_id = 1;
af461fc18   Dominik Brodowski   pcmcia: delay re-...
438
  			mutex_unlock(&p_dev->socket->ops_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
  		}
76fa82fb7   Ingo Molnar   [PATCH] pcmcia: r...
440
  		kfree(devgeo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  	}
84897fc05   Dominik Brodowski   pcmcia: pccard_re...
442
  	if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, CISTPL_VERS_1,
76fa82fb7   Ingo Molnar   [PATCH] pcmcia: r...
443
  			       vers1)) {
af461fc18   Dominik Brodowski   pcmcia: delay re-...
444
  		mutex_lock(&p_dev->socket->ops_mutex);
c5e09528b   Dominik Brodowski   pcmcia: do not tr...
445
  		for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
  			char *tmp;
  			unsigned int length;
44961a03a   Dominik Brodowski   pcmcia: avoid pro...
448
  			char *new;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449

76fa82fb7   Ingo Molnar   [PATCH] pcmcia: r...
450
  			tmp = vers1->str + vers1->ofs[i];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
  
  			length = strlen(tmp) + 1;
6e3d4f25a   Janos Farkas   [PATCH] pcmcia: p...
453
  			if ((length < 2) || (length > 255))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
  				continue;
7c22e645c   Geliang Tang   pcmcia: use kstrd...
455
  			new = kstrdup(tmp, GFP_KERNEL);
44961a03a   Dominik Brodowski   pcmcia: avoid pro...
456
  			if (!new)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
  				continue;
44961a03a   Dominik Brodowski   pcmcia: avoid pro...
458
459
460
  			tmp = p_dev->prod_id[i];
  			p_dev->prod_id[i] = new;
  			kfree(tmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
  		}
af461fc18   Dominik Brodowski   pcmcia: delay re-...
462
  		mutex_unlock(&p_dev->socket->ops_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
  	}
76fa82fb7   Ingo Molnar   [PATCH] pcmcia: r...
464
  	kfree(vers1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
  	return 0;
  }
5716d415f   Dominik Brodowski   pcmcia: remove ob...
467
468
  static struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s,
  					       unsigned int function)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  {
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
470
  	struct pcmcia_device *p_dev, *tmp_dev;
44961a03a   Dominik Brodowski   pcmcia: avoid pro...
471
  	int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472

dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
473
  	s = pcmcia_get_socket(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
  	if (!s)
  		return NULL;
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
476
477
  	pr_debug("adding device to %d, function %d
  ", s->sock, function);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
478

8084b372a   Dominik Brodowski   [PATCH] pcmcia: k...
479
  	p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
  	if (!p_dev)
  		goto err_put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482

00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
483
  	mutex_lock(&s->ops_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
  	p_dev->device_no = (s->device_count++);
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
485
  	mutex_unlock(&s->ops_mutex);
e6e4f397e   Dominik Brodowski   pcmcia: protect s...
486

7d7ba8d31   Dominik Brodowski   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   Dominik Brodowski   pcmcia: protect s...
493
494
495
  		goto err_free;
  
  	p_dev->socket = s;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
498
  	p_dev->func   = function;
  
  	p_dev->dev.bus = &pcmcia_bus_type;
873733188   Greg Kroah-Hartman   Driver core: conv...
499
  	p_dev->dev.parent = s->dev.parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
  	p_dev->dev.release = pcmcia_release_dev;
43d9f7fda   James Bottomley   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   Kay Sievers   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   Brice Goglin   [PATCH] pcmcia: a...
508
509
  	if (!p_dev->devname)
  		goto err_free;
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
510
511
  	dev_dbg(&p_dev->dev, "devname is %s
  ", p_dev->devname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512

00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
513
  	mutex_lock(&s->ops_mutex);
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
514
515
516
  
  	/*
  	 * p_dev->function_config must be the same for all card functions.
a60f22c4a   Dominik Brodowski   pcmcia: remove pc...
517
518
  	 * Note that this is serialized by ops_mutex, so that only one
  	 * such struct will be created.
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
519
  	 */
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
520
521
  	list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list)
  		if (p_dev->func == tmp_dev->func) {
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
522
  			p_dev->function_config = tmp_dev->function_config;
3e879f614   Komuro   pcmcia: setup res...
523
  			p_dev->irq = tmp_dev->irq;
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
524
525
526
527
  			kref_get(&p_dev->function_config->ref);
  		}
  
  	/* Add to the list in pcmcia_bus_socket */
6171b88b4   Komuro   [PATCH] pcmcia: u...
528
  	list_add(&p_dev->socket_device_list, &s->devices_list);
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
529

6f0f38c45   Dominik Brodowski   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   Linus Torvalds   Linux-2.6.12-rc2
534

360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
535
  	if (!p_dev->function_config) {
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
536
  		config_t *c;
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
537
538
  		dev_dbg(&p_dev->dev, "creating config_t
  ");
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
539
540
  		c = kzalloc(sizeof(struct config_t), GFP_KERNEL);
  		if (!c) {
6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
541
  			mutex_unlock(&s->ops_mutex);
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
542
  			goto err_unreg;
6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
543
  		}
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
544
545
546
  		p_dev->function_config = c;
  		kref_init(&c->ref);
  		for (i = 0; i < MAX_IO_WIN; i++) {
ad0c7be28   Dominik Brodowski   pcmcia: insert PC...
547
  			c->io[i].name = p_dev->devname;
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
548
549
  			c->io[i].flags = IORESOURCE_IO;
  		}
46f533ccb   Laurent Navet   drivers: pcmcia: ...
550
  		for (i = 0; i < MAX_WIN; i++) {
ad0c7be28   Dominik Brodowski   pcmcia: insert PC...
551
  			c->mem[i].name = p_dev->devname;
0ca724d37   Dominik Brodowski   pcmcia: use struc...
552
553
  			c->mem[i].flags = IORESOURCE_MEM;
  		}
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
554
  	}
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
555
556
  	for (i = 0; i < MAX_IO_WIN; i++)
  		p_dev->resource[i] = &p_dev->function_config->io[i];
0ca724d37   Dominik Brodowski   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   Dominik Brodowski   pcmcia: use struc...
559

6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
560
  	mutex_unlock(&s->ops_mutex);
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
561

f2e6cf767   Joe Perches   pcmcia: Convert d...
562
563
  	dev_notice(&p_dev->dev, "pcmcia: registering new device %s (IRQ: %d)
  ",
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
564
  		   p_dev->devname, p_dev->irq);
807277cbf   Dominik Brodowski   [PCMCIA] inform u...
565

1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
566
  	pcmcia_device_query(p_dev);
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
567
568
  	if (device_register(&p_dev->dev))
  		goto err_unreg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570
  	return p_dev;
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
571
   err_unreg:
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
572
  	mutex_lock(&s->ops_mutex);
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
573
  	list_del(&p_dev->socket_device_list);
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
574
  	mutex_unlock(&s->ops_mutex);
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
575

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
   err_free:
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
577
  	mutex_lock(&s->ops_mutex);
e6e4f397e   Dominik Brodowski   pcmcia: protect s...
578
  	s->device_count--;
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
579
  	mutex_unlock(&s->ops_mutex);
e6e4f397e   Dominik Brodowski   pcmcia: protect s...
580

44961a03a   Dominik Brodowski   pcmcia: avoid pro...
581
582
  	for (i = 0; i < 4; i++)
  		kfree(p_dev->prod_id[i]);
bd65a6857   Brice Goglin   [PATCH] pcmcia: a...
583
  	kfree(p_dev->devname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
  	kfree(p_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
   err_put:
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
586
  	pcmcia_put_socket(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587
588
589
590
591
592
593
  
  	return NULL;
  }
  
  
  static int pcmcia_card_add(struct pcmcia_socket *s)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
  	cistpl_longlink_mfc_t mfc;
c5081d5f4   Dominik Brodowski   pcmcia: simplify ...
595
  	unsigned int no_funcs, i, no_chains;
cfe5d8095   Dominik Brodowski   pcmcia: use ops_m...
596
  	int ret = -EAGAIN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597

cfe5d8095   Dominik Brodowski   pcmcia: use ops_m...
598
  	mutex_lock(&s->ops_mutex);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
599
  	if (!(s->resource_setup_done)) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
600
  		dev_dbg(&s->dev,
ac449d6e2   Dominik Brodowski   pcmcia: use dev_p...
601
602
  			   "no resources available, delaying card_add
  ");
cfe5d8095   Dominik Brodowski   pcmcia: use ops_m...
603
  		mutex_unlock(&s->ops_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
  		return -EAGAIN; /* try again, but later... */
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
605
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606

d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
607
  	if (pcmcia_validate_mem(s)) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
608
  		dev_dbg(&s->dev, "validating mem resources failed, "
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
609
610
  		       "delaying card_add
  ");
cfe5d8095   Dominik Brodowski   pcmcia: use ops_m...
611
  		mutex_unlock(&s->ops_mutex);
de75914ee   Dominik Brodowski   [PATCH] pcmcia: v...
612
  		return -EAGAIN; /* try again, but later... */
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
613
  	}
cfe5d8095   Dominik Brodowski   pcmcia: use ops_m...
614
  	mutex_unlock(&s->ops_mutex);
de75914ee   Dominik Brodowski   [PATCH] pcmcia: v...
615

84897fc05   Dominik Brodowski   pcmcia: pccard_re...
616
  	ret = pccard_validate_cis(s, &no_chains);
c5081d5f4   Dominik Brodowski   pcmcia: simplify ...
617
  	if (ret || !no_chains) {
e8e68fd86   Dominik Brodowski   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   Linus Torvalds   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   Dominik Brodowski   [PATCH] pcmcia: m...
644
  	s->functions = no_funcs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645

9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
646
  	for (i = 0; i < no_funcs; i++)
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
647
  		pcmcia_device_add(s, i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648

9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
649
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
  }
46f533ccb   Laurent Navet   drivers: pcmcia: ...
651
  static int pcmcia_requery_callback(struct device *dev, void *_data)
ff1fa9ef3   Dominik Brodowski   [PATCH] pcmcia: C...
652
  {
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
653
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
654
  	if (!p_dev->dev.driver) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
655
656
  		dev_dbg(dev, "update device information
  ");
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
657
  		pcmcia_device_query(p_dev);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
658
  	}
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
659
660
661
  
  	return 0;
  }
aa584ca4c   Dominik Brodowski   pcmcia: use state...
662

af461fc18   Dominik Brodowski   pcmcia: delay re-...
663
  static void pcmcia_requery(struct pcmcia_socket *s)
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
664
  {
04de08161   Dominik Brodowski   pcmcia: pcmcia_de...
665
  	int has_pfc;
4ae1cbf17   Dominik Brodowski   [PATCH] pcmcia: s...
666

8402641b2   Alan Cox   pcmcia: Fix requery
667
668
  	if (!(s->state & SOCKET_PRESENT))
  		return;
af461fc18   Dominik Brodowski   pcmcia: delay re-...
669
670
671
  	if (s->functions == 0) {
  		pcmcia_card_add(s);
  		return;
e2f0b5344   Dominik Brodowski   [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   Dominik Brodowski   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   Dominik Brodowski   pcmcia: re-start ...
693
694
  		if (old_funcs != new_funcs) {
  			/* we need to re-start */
af461fc18   Dominik Brodowski   pcmcia: delay re-...
695
  			pcmcia_card_remove(s, NULL);
b83156b52   Dominik Brodowski   pcmcia: avoid val...
696
  			s->functions = 0;
af461fc18   Dominik Brodowski   pcmcia: delay re-...
697
  			pcmcia_card_add(s);
af461fc18   Dominik Brodowski   pcmcia: delay re-...
698
699
  		}
  	}
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
700

aa584ca4c   Dominik Brodowski   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   Dominik Brodowski   pcmcia: remove un...
705
  	has_pfc = s->pcmcia_pfc;
aa584ca4c   Dominik Brodowski   pcmcia: use state...
706
707
708
  	mutex_unlock(&s->ops_mutex);
  	if (has_pfc)
  		pcmcia_device_add(s, 0);
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
709
710
  	/* we re-scan all devices, not just the ones connected to this
  	 * socket. This does not matter, though. */
af461fc18   Dominik Brodowski   pcmcia: delay re-...
711
712
713
  	if (bus_rescan_devices(&pcmcia_bus_type))
  		dev_warn(&s->dev, "rescanning the bus failed
  ");
ff1fa9ef3   Dominik Brodowski   [PATCH] pcmcia: C...
714
  }
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
715

af461fc18   Dominik Brodowski   pcmcia: delay re-...
716

1d2c90425   Dominik Brodowski   [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   Randy Dunlap   pcmcia: fix kerne...
721
722
   * @dev: the pcmcia device which needs a CIS override
   * @filename: requested filename in /lib/firmware/
1d2c90425   Dominik Brodowski   [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   Laurent Navet   drivers: pcmcia: ...
728
  static int pcmcia_load_firmware(struct pcmcia_device *dev, char *filename)
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
729
730
731
  {
  	struct pcmcia_socket *s = dev->socket;
  	const struct firmware *fw;
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
732
  	int ret = -ENOMEM;
b1095afe6   Dominik Brodowski   pcmcia: re-start ...
733
734
  	cistpl_longlink_mfc_t mfc;
  	int old_funcs, new_funcs = 1;
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
735
736
737
  
  	if (!filename)
  		return -EINVAL;
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
738
739
  	dev_dbg(&dev->dev, "trying to load CIS file %s
  ", filename);
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
740

ed62acec2   Samuel Ortiz   firmware: pcmcia/...
741
  	if (request_firmware(&fw, filename, &dev->dev) == 0) {
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
742
743
  		if (fw->size >= CISTPL_MAX_CIS_SIZE) {
  			ret = -EINVAL;
f2e6cf767   Joe Perches   pcmcia: Convert d...
744
745
  			dev_err(&dev->dev, "pcmcia: CIS override is too big
  ");
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
746
  			goto release;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
747
  		}
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
748

53efec951   Dominik Brodowski   pcmcia: only copy...
749
  		if (!pcmcia_replace_cis(s, fw->data, fw->size))
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
750
  			ret = 0;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
751
  		else {
f2e6cf767   Joe Perches   pcmcia: Convert d...
752
753
  			dev_err(&dev->dev, "pcmcia: CIS override failed
  ");
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
754
755
  			goto release;
  		}
b1095afe6   Dominik Brodowski   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   Dominik Brodowski   [PATCH] pcmcia: m...
764
765
766
  
  		/* update information */
  		pcmcia_device_query(dev);
aa584ca4c   Dominik Brodowski   pcmcia: use state...
767
768
  		/* requery (as number of functions might have changed) */
  		pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY);
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
769
770
771
  	}
   release:
  	release_firmware(fw);
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
772
  	return ret;
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
773
774
775
  }
  
  #else /* !CONFIG_PCMCIA_LOAD_CIS */
46f533ccb   Laurent Navet   drivers: pcmcia: ...
776
777
  static inline int pcmcia_load_firmware(struct pcmcia_device *dev,
  				       char *filename)
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
778
779
780
781
782
  {
  	return -ENODEV;
  }
  
  #endif
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
783
  static inline int pcmcia_devmatch(struct pcmcia_device *dev,
e9fb13bfe   Joe Perches   pcmcia: Make decl...
784
  				  const struct pcmcia_device_id *did)
1ad275e3e   Dominik Brodowski   [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   Alexander Kurz   pcmcia: fix match...
830
831
  		dev_dbg(&dev->dev, "this is a pseudo-multi-function device
  ");
aa584ca4c   Dominik Brodowski   pcmcia: use state...
832
  		mutex_lock(&dev->socket->ops_mutex);
ce3f9d71b   Dominik Brodowski   pcmcia: remove un...
833
  		dev->socket->pcmcia_pfc = 1;
aa584ca4c   Dominik Brodowski   pcmcia: use state...
834
  		mutex_unlock(&dev->socket->ops_mutex);
83bf6f11e   Alexander Kurz   pcmcia: fix match...
835
836
  		if (dev->device_no != did->device_no)
  			return 0;
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
837
838
839
  	}
  
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) {
94a819f80   Dominik Brodowski   pcmcia: assert lo...
840
  		int ret;
1ad275e3e   Dominik Brodowski   [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   Dominik Brodowski   pcmcia: remove un...
846
  		if (dev->socket->pcmcia_pfc)
1ad275e3e   Dominik Brodowski   [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   Dominik Brodowski   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   Dominik Brodowski   [PATCH] pcmcia: d...
863
  			return 0;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
864
  		}
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
865
  	}
ea7b38825   Dominik Brodowski   [PATCH] pcmcia: m...
866
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
867
868
  		dev_dbg(&dev->dev, "device needs a fake CIS
  ");
daa9517d9   Dominik Brodowski   [PATCH] pcmcia: r...
869
  		if (!dev->socket->fake_cis)
b1095afe6   Dominik Brodowski   pcmcia: re-start ...
870
871
  			if (pcmcia_load_firmware(dev, did->cisfile))
  				return 0;
ea7b38825   Dominik Brodowski   [PATCH] pcmcia: m...
872
  	}
f602ff7eb   Dominik Brodowski   [PATCH] pcmcia: m...
873
874
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) {
  		int i;
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
875
  		for (i = 0; i < 4; i++)
f602ff7eb   Dominik Brodowski   [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   Dominik Brodowski   [PATCH] pcmcia: d...
881
882
  	return 1;
  }
9fea84f46   Dominik Brodowski   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   Joe Perches   pcmcia: Make decl...
887
  	const struct pcmcia_device_id *did = p_drv->id_table;
6179b5562   Bernhard Walle   add new_id to PCM...
888
889
890
  	struct pcmcia_dynid *dynid;
  
  	/* match dynamic devices first */
3f565232c   Dominik Brodowski   pcmcia: use mutex...
891
  	mutex_lock(&p_drv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
892
  	list_for_each_entry(dynid, &p_drv->dynids.list, node) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
893
894
  		dev_dbg(dev, "trying to match to %s
  ", drv->name);
6179b5562   Bernhard Walle   add new_id to PCM...
895
  		if (pcmcia_devmatch(p_dev, &dynid->id)) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
896
897
  			dev_dbg(dev, "matched to %s
  ", drv->name);
3f565232c   Dominik Brodowski   pcmcia: use mutex...
898
  			mutex_unlock(&p_drv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
899
900
901
  			return 1;
  		}
  	}
3f565232c   Dominik Brodowski   pcmcia: use mutex...
902
  	mutex_unlock(&p_drv->dynids.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903

1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
904
  	while (did && did->match_flags) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
905
906
  		dev_dbg(dev, "trying to match to %s
  ", drv->name);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
907
  		if (pcmcia_devmatch(p_dev, did)) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
908
909
  			dev_dbg(dev, "matched to %s
  ", drv->name);
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
910
  			return 1;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
911
  		}
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
912
913
  		did++;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
914
915
  	return 0;
  }
7eff2e7a8   Kay Sievers   Driver core: chan...
916
  static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
917
918
  {
  	struct pcmcia_device *p_dev;
7eff2e7a8   Kay Sievers   Driver core: chan...
919
  	int i;
840c2ac5d   Dominik Brodowski   [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   Dominik Brodowski   pcmcia: CodingSty...
928
  	for (i = 0; i < 4; i++) {
840c2ac5d   Dominik Brodowski   [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   Kay Sievers   Driver core: chan...
933
  	if (add_uevent_var(env, "SOCKET_NO=%u", p_dev->socket->sock))
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
934
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
935
  	if (add_uevent_var(env, "DEVICE_NO=%02X", p_dev->device_no))
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
936
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
937
  	if (add_uevent_var(env, "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
312c004d3   Kay Sievers   [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   Dominik Brodowski   [PATCH] pcmcia: h...
948
  		return -ENOMEM;
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
949
950
  	return 0;
  }
3f8df781f   Alan Stern   PM: remove deprec...
951
  /************************ runtime PM support ***************************/
ad8d52b89   Russell King   pcmcia: ds: fix s...
952
  static int pcmcia_dev_suspend(struct device *dev);
3f8df781f   Alan Stern   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   Greg Kroah-Hartman   Driver core: crea...
958
  	device_lock(dev);
ad8d52b89   Russell King   pcmcia: ds: fix s...
959
  	rc = pcmcia_dev_suspend(dev);
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
960
  	device_unlock(dev);
3f8df781f   Alan Stern   PM: remove deprec...
961
962
  	return rc;
  }
933a838aa   Dominik Brodowski   pcmcia: make use ...
963
  static int runtime_resume(struct device *dev)
3f8df781f   Alan Stern   PM: remove deprec...
964
965
  {
  	int rc;
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
966
  	device_lock(dev);
3f8df781f   Alan Stern   PM: remove deprec...
967
  	rc = pcmcia_dev_resume(dev);
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
968
  	device_unlock(dev);
933a838aa   Dominik Brodowski   pcmcia: make use ...
969
  	return rc;
3f8df781f   Alan Stern   PM: remove deprec...
970
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
972
973
  /************************ per-device sysfs output ***************************/
  
  #define pcmcia_device_attr(field, test, format)				\
e404e274f   Yani Ioannou   [PATCH] Driver Co...
974
  static ssize_t field##_show (struct device *dev, struct device_attribute *attr, char *buf)		\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
976
  {									\
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
977
  	return p_dev->test ? sprintf(buf, format, p_dev->field) : -ENODEV; \
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
978
979
  }									\
  static DEVICE_ATTR_RO(field);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
  
  #define pcmcia_device_stringattr(name, field)					\
e404e274f   Yani Ioannou   [PATCH] Driver Co...
982
  static ssize_t name##_show (struct device *dev, struct device_attribute *attr, char *buf)		\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
984
  {									\
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
985
986
  	return p_dev->field ? sprintf(buf, "%s
  ", p_dev->field) : -ENODEV; \
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
987
988
  }									\
  static DEVICE_ATTR_RO(name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989

1da177e4c   Linus Torvalds   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   Greg Kroah-Hartman   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   Dominik Brodowski   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   Greg Kroah-Hartman   pcmcia: convert b...
1022
  static DEVICE_ATTR_RO(resources);
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1023

b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
1024
  static ssize_t pm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1025
1026
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1027
  	if (p_dev->suspended)
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1028
1029
1030
1031
1032
1033
  		return sprintf(buf, "off
  ");
  	else
  		return sprintf(buf, "on
  ");
  }
b9b2f3676   Greg Kroah-Hartman   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   Dominik Brodowski   [PATCH] pcmcia: r...
1036
1037
1038
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
  	int ret = 0;
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1039
1040
  	if (!count)
  		return -EINVAL;
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1041

f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1042
  	if ((!p_dev->suspended) && !strncmp(buf, "off", 3))
3f8df781f   Alan Stern   PM: remove deprec...
1043
  		ret = runtime_suspend(dev);
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1044
  	else if (p_dev->suspended && !strncmp(buf, "on", 2))
933a838aa   Dominik Brodowski   pcmcia: make use ...
1045
  		ret = runtime_resume(dev);
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1046
1047
1048
  
  	return ret ? ret : count;
  }
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
1049
  static DEVICE_ATTR_RW(pm_state);
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1050

3704511b2   Dominik Brodowski   [PATCH] pcmcia: f...
1051
  static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
3248ff43f   Dominik Brodowski   [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   Dominik Brodowski   pcmcia: CodingSty...
1058
  	for (i = 0; i < 4; i++) {
3248ff43f   Dominik Brodowski   [PATCH] pcmcia: e...
1059
1060
  		if (!p_dev->prod_id[i])
  			continue;
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1061
1062
  		hash[i] = crc32(0, p_dev->prod_id[i],
  				strlen(p_dev->prod_id[i]));
3248ff43f   Dominik Brodowski   [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   Greg Kroah-Hartman   pcmcia: convert b...
1073
  static DEVICE_ATTR_RO(modalias);
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1074

b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
1075
  static ssize_t allow_func_id_match_store(struct device *dev,
3248ff43f   Dominik Brodowski   [PATCH] pcmcia: e...
1076
  		struct device_attribute *attr, const char *buf, size_t count)
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1077
1078
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1079
1080
1081
  
  	if (!count)
  		return -EINVAL;
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1082

94a819f80   Dominik Brodowski   pcmcia: assert lo...
1083
  	mutex_lock(&p_dev->socket->ops_mutex);
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1084
  	p_dev->allow_func_id_match = 1;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
1085
  	mutex_unlock(&p_dev->socket->ops_mutex);
af461fc18   Dominik Brodowski   pcmcia: delay re-...
1086
  	pcmcia_parse_uevents(p_dev->socket, PCMCIA_UEVENT_REQUERY);
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1087
1088
1089
  
  	return count;
  }
b9b2f3676   Greg Kroah-Hartman   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   Linus Torvalds   Linux-2.6.12-rc2
1106
  };
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
1107
  ATTRIBUTE_GROUPS(pcmcia_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108

8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1109
  /* PM support, also needed for reset */
ad8d52b89   Russell King   pcmcia: ds: fix s...
1110
  static int pcmcia_dev_suspend(struct device *dev)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1111
1112
1113
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
  	struct pcmcia_driver *p_drv = NULL;
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1114
  	int ret = 0;
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1115

94a819f80   Dominik Brodowski   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   David Brownell   pcmcia: stop upda...
1119
  		return 0;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
1120
1121
1122
  	}
  	p_dev->suspended = 1;
  	mutex_unlock(&p_dev->socket->ops_mutex);
d6b4fa6d6   David Brownell   pcmcia: stop upda...
1123

d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1124
1125
  	dev_dbg(dev, "suspending
  ");
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1126

8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1127
1128
  	if (dev->driver)
  		p_drv = to_pcmcia_drv(dev->driver);
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1129
1130
1131
1132
  	if (!p_drv)
  		goto out;
  
  	if (p_drv->suspend) {
8661bb5b4   Dominik Brodowski   [PATCH] pcmcia: d...
1133
  		ret = p_drv->suspend(p_dev);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1134
  		if (ret) {
f2e6cf767   Joe Perches   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   Dominik Brodowski   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   Dominik Brodowski   [PATCH] pcmcia: r...
1142
  			goto out;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1143
  		}
8661bb5b4   Dominik Brodowski   [PATCH] pcmcia: d...
1144
  	}
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1145

d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1146
  	if (p_dev->device_no == p_dev->func) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1147
1148
  		dev_dbg(dev, "releasing configuration
  ");
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1149
  		pcmcia_release_configuration(p_dev);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1150
  	}
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1151

f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1152
   out:
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1153
  	return ret;
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1154
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1155
  static int pcmcia_dev_resume(struct device *dev)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1156
1157
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1158
  	struct pcmcia_driver *p_drv = NULL;
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1159
  	int ret = 0;
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1160

94a819f80   Dominik Brodowski   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   David Brownell   pcmcia: stop upda...
1164
  		return 0;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
1165
1166
1167
  	}
  	p_dev->suspended = 0;
  	mutex_unlock(&p_dev->socket->ops_mutex);
d6b4fa6d6   David Brownell   pcmcia: stop upda...
1168

d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1169
1170
  	dev_dbg(dev, "resuming
  ");
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1171

8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1172
1173
  	if (dev->driver)
  		p_drv = to_pcmcia_drv(dev->driver);
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1174
1175
1176
1177
  	if (!p_drv)
  		goto out;
  
  	if (p_dev->device_no == p_dev->func) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1178
1179
  		dev_dbg(dev, "requesting configuration
  ");
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
1180
  		ret = pcmcia_enable_device(p_dev);
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1181
1182
  		if (ret)
  			goto out;
8661bb5b4   Dominik Brodowski   [PATCH] pcmcia: d...
1183
  	}
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1184

e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1185
1186
  	if (p_drv->resume)
  		ret = p_drv->resume(p_dev);
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1187
   out:
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1188
  	return ret;
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1189
  }
46f533ccb   Laurent Navet   drivers: pcmcia: ...
1190
  static int pcmcia_bus_suspend_callback(struct device *dev, void *_data)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1191
1192
1193
  {
  	struct pcmcia_socket *skt = _data;
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
3f8df781f   Alan Stern   PM: remove deprec...
1194
  	if (p_dev->socket != skt || p_dev->suspended)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1195
  		return 0;
3f8df781f   Alan Stern   PM: remove deprec...
1196
  	return runtime_suspend(dev);
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1197
  }
46f533ccb   Laurent Navet   drivers: pcmcia: ...
1198
  static int pcmcia_bus_resume_callback(struct device *dev, void *_data)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1199
1200
1201
  {
  	struct pcmcia_socket *skt = _data;
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
3f8df781f   Alan Stern   PM: remove deprec...
1202
  	if (p_dev->socket != skt || !p_dev->suspended)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1203
  		return 0;
3f8df781f   Alan Stern   PM: remove deprec...
1204
  	runtime_resume(dev);
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1205
1206
1207
1208
1209
1210
  
  	return 0;
  }
  
  static int pcmcia_bus_resume(struct pcmcia_socket *skt)
  {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1211
1212
  	dev_dbg(&skt->dev, "resuming socket %d
  ", skt->sock);
8e9e793d6   Dominik Brodowski   [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   Dominik Brodowski   pcmcia: use dynam...
1219
1220
  	dev_dbg(&skt->dev, "suspending socket %d
  ", skt->sock);
8e9e793d6   Dominik Brodowski   [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   Dominik Brodowski   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   Linus Torvalds   Linux-2.6.12-rc2
1232

7b24e7988   Dominik Brodowski   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   Linus Torvalds   Linux-2.6.12-rc2
1237

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1238
1239
  	return 0;
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1240

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1241
1242
1243
  static int pcmcia_bus_add(struct pcmcia_socket *skt)
  {
  	atomic_set(&skt->present, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1244

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1245
  	mutex_lock(&skt->ops_mutex);
ce3f9d71b   Dominik Brodowski   pcmcia: remove un...
1246
  	skt->pcmcia_pfc = 0;
7b24e7988   Dominik Brodowski   pcmcia: split up ...
1247
1248
  	destroy_cis_cache(skt); /* to be on the safe side... */
  	mutex_unlock(&skt->ops_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1249

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1250
  	pcmcia_card_add(skt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1251

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1252
1253
  	return 0;
  }
1617406a7   Florin Malita   [PATCH] pcmcia: m...
1254

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1255
1256
  static int pcmcia_bus_early_resume(struct pcmcia_socket *skt)
  {
025e4ab3d   Russell King   pcmcia: fix socke...
1257
  	if (!verify_cis_cache(skt))
7b24e7988   Dominik Brodowski   pcmcia: split up ...
1258
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1259

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1260
1261
  	dev_dbg(&skt->dev, "cis mismatch - different card
  ");
f8cfa618d   Dominik Brodowski   [PATCH] pcmcia: u...
1262

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1263
1264
  	/* first, remove the card */
  	pcmcia_bus_remove(skt);
88b060d6c   Dominik Brodowski   pcmcia: improve c...
1265

7b24e7988   Dominik Brodowski   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   Linus Torvalds   Linux-2.6.12-rc2
1272

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1273
1274
1275
1276
  	/* now, add the new card */
  	pcmcia_bus_add(skt);
  	return 0;
  }
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1277

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278

04de08161   Dominik Brodowski   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   Dominik Brodowski   pcmcia: CodingSty...
1286
  struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev)
9940ec361   Dominik Brodowski   [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   Dominik Brodowski   pcmcia: pcmcia_de...
1294
1295
  	if (atomic_read(&p_dev->socket->present) != 0)
  		ret = p_dev;
9940ec361   Dominik Brodowski   [PATCH] pcmcia: c...
1296

9940ec361   Dominik Brodowski   [PATCH] pcmcia: c...
1297
1298
1299
1300
  	pcmcia_put_dev(p_dev);
  	return ret;
  }
  EXPORT_SYMBOL(pcmcia_dev_present);
90c6cdd1f   Dominik Brodowski   [PATCH] pcmcia: c...
1301
1302
  static struct pcmcia_callback pcmcia_bus_callback = {
  	.owner = THIS_MODULE,
7b24e7988   Dominik Brodowski   pcmcia: split up ...
1303
1304
  	.add = pcmcia_bus_add,
  	.remove = pcmcia_bus_remove,
af461fc18   Dominik Brodowski   pcmcia: delay re-...
1305
  	.requery = pcmcia_requery,
6e7b51a73   Dominik Brodowski   pcmcia: move cist...
1306
  	.validate = pccard_validate_cis,
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1307
  	.suspend = pcmcia_bus_suspend,
7b24e7988   Dominik Brodowski   pcmcia: split up ...
1308
  	.early_resume = pcmcia_bus_early_resume,
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1309
  	.resume = pcmcia_bus_resume,
90c6cdd1f   Dominik Brodowski   [PATCH] pcmcia: c...
1310
  };
34cdf25a1   Bill Pemberton   pcmcia: remove us...
1311
  static int pcmcia_bus_add_socket(struct device *dev,
d8539d81a   Dmitry Torokhov   [PATCH] Driver co...
1312
  					   struct class_interface *class_intf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1313
  {
873733188   Greg Kroah-Hartman   Driver core: conv...
1314
  	struct pcmcia_socket *socket = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1315
  	int ret;
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1316
1317
  	socket = pcmcia_get_socket(socket);
  	if (!socket) {
f2e6cf767   Joe Perches   pcmcia: Convert d...
1318
1319
  		dev_err(dev, "PCMCIA obtaining reference to socket failed
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
1321
  		return -ENODEV;
  	}
6e7b51a73   Dominik Brodowski   pcmcia: move cist...
1322
1323
  	ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr);
  	if (ret) {
f2e6cf767   Joe Perches   pcmcia: Convert d...
1324
1325
  		dev_err(dev, "PCMCIA registration failed
  ");
6e7b51a73   Dominik Brodowski   pcmcia: move cist...
1326
1327
1328
  		pcmcia_put_socket(socket);
  		return ret;
  	}
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1329
  	INIT_LIST_HEAD(&socket->devices_list);
ce3f9d71b   Dominik Brodowski   pcmcia: remove un...
1330
  	socket->pcmcia_pfc = 0;
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1331
  	socket->device_count = 0;
e4f1ac212   Dominik Brodowski   pcmcia: do not in...
1332
  	atomic_set(&socket->present, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333

90c6cdd1f   Dominik Brodowski   [PATCH] pcmcia: c...
1334
  	ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
  	if (ret) {
f2e6cf767   Joe Perches   pcmcia: Convert d...
1336
1337
  		dev_err(dev, "PCMCIA registration failed
  ");
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1338
  		pcmcia_put_socket(socket);
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1339
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1340
1341
1342
1343
  	}
  
  	return 0;
  }
873733188   Greg Kroah-Hartman   Driver core: conv...
1344
  static void pcmcia_bus_remove_socket(struct device *dev,
d8539d81a   Dmitry Torokhov   [PATCH] Driver co...
1345
  				     struct class_interface *class_intf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1346
  {
873733188   Greg Kroah-Hartman   Driver core: conv...
1347
  	struct pcmcia_socket *socket = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348

dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1349
  	if (!socket)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1350
1351
1352
  		return;
  
  	pccard_register_pcmcia(socket, NULL);
dfbc9e9d3   Daniel Ritz   [PATCH] pcmcia: f...
1353
  	/* unregister any unbound devices */
8e4d9dcb4   Daniel Ritz   [PATCH] fix "pcmc...
1354
  	mutex_lock(&socket->skt_mutex);
dfbc9e9d3   Daniel Ritz   [PATCH] pcmcia: f...
1355
  	pcmcia_card_remove(socket, NULL);
180c33ee4   Dominik Brodowski   pcmcia: call CIS ...
1356
  	release_cis_mem(socket);
8e4d9dcb4   Daniel Ritz   [PATCH] fix "pcmc...
1357
  	mutex_unlock(&socket->skt_mutex);
dfbc9e9d3   Daniel Ritz   [PATCH] pcmcia: f...
1358

6e7b51a73   Dominik Brodowski   pcmcia: move cist...
1359
  	sysfs_remove_bin_file(&dev->kobj, &pccard_cis_attr);
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1360
  	pcmcia_put_socket(socket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
1362
1363
1364
1365
1366
  
  	return;
  }
  
  
  /* the pcmcia_bus_interface is used to handle pcmcia socket devices */
ed49f5d00   Sam Ravnborg   pcmcia: silence s...
1367
  static struct class_interface pcmcia_bus_interface __refdata = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1368
  	.class = &pcmcia_socket_class,
873733188   Greg Kroah-Hartman   Driver core: conv...
1369
1370
  	.add_dev = &pcmcia_bus_add_socket,
  	.remove_dev = &pcmcia_bus_remove_socket,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1371
  };
ad8d52b89   Russell King   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   Linus Torvalds   Linux-2.6.12-rc2
1375

e7a480d22   Dominik Brodowski   [PATCH] pcmcia: m...
1376
  struct bus_type pcmcia_bus_type = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1377
  	.name = "pcmcia",
312c004d3   Kay Sievers   [PATCH] driver co...
1378
  	.uevent = pcmcia_bus_uevent,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1379
  	.match = pcmcia_bus_match,
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
1380
  	.dev_groups = pcmcia_dev_groups,
1d0baa3a1   Russell King   [PATCH] Add pcmci...
1381
1382
  	.probe = pcmcia_device_probe,
  	.remove = pcmcia_device_remove,
ad8d52b89   Russell King   pcmcia: ds: fix s...
1383
  	.pm = &pcmcia_bus_pm_ops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1384
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1385
1386
1387
1388
  
  
  static int __init init_pcmcia_bus(void)
  {
ace7d4772   Randy Dunlap   [PATCH] pcmcia/ds...
1389
  	int ret;
ace7d4772   Randy Dunlap   [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   Linus Torvalds   Linux-2.6.12-rc2
1404

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1405
1406
  	return 0;
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1407
  fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1408
1409
1410
1411
1412
  			       * pcmcia_socket_class is already registered */
  
  
  static void __exit exit_pcmcia_bus(void)
  {
e7a480d22   Dominik Brodowski   [PATCH] pcmcia: m...
1413
  	class_interface_unregister(&pcmcia_bus_interface);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1414
1415
1416
1417
  
  	bus_unregister(&pcmcia_bus_type);
  }
  module_exit(exit_pcmcia_bus);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1418
  MODULE_ALIAS("ds");