Blame view

drivers/pcmcia/ds.c 34.4 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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  struct pcmcia_dynid {
  	struct list_head 		node;
  	struct pcmcia_device_id 	id;
  };
  
  /**
   * 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
  pcmcia_store_new_id(struct device_driver *driver, const char *buf, size_t count)
  {
  	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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  
  	if (get_driver(&pdrv->drv)) {
  		retval = driver_attach(&pdrv->drv);
  		put_driver(&pdrv->drv);
  	}
  
  	if (retval)
  		return retval;
  	return count;
  }
  static DRIVER_ATTR(new_id, S_IWUSR, NULL, pcmcia_store_new_id);
  
  static void
  pcmcia_free_dynids(struct pcmcia_driver *drv)
  {
  	struct pcmcia_dynid *dynid, *n;
3f565232c   Dominik Brodowski   pcmcia: use mutex...
140
  	mutex_lock(&drv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
141
142
143
144
  	list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
  		list_del(&dynid->node);
  		kfree(dynid);
  	}
3f565232c   Dominik Brodowski   pcmcia: use mutex...
145
  	mutex_unlock(&drv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
146
147
148
149
150
151
152
  }
  
  static int
  pcmcia_create_newid_file(struct pcmcia_driver *drv)
  {
  	int error = 0;
  	if (drv->probe != NULL)
2344c6de6   Greg Kroah-Hartman   PCMCIA: use prope...
153
  		error = driver_create_file(&drv->drv, &driver_attr_new_id);
6179b5562   Bernhard Walle   add new_id to PCM...
154
155
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
157
  /**
   * pcmcia_register_driver - register a PCMCIA driver with the bus core
78187865e   Randy Dunlap   pcmcia: fix kerne...
158
   * @driver: the &driver being registered
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
   *
   * Registers a PCMCIA driver with the PCMCIA bus core.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
  int pcmcia_register_driver(struct pcmcia_driver *driver)
  {
6179b5562   Bernhard Walle   add new_id to PCM...
164
  	int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
  	if (!driver)
  		return -EINVAL;
23a83bfe6   Dominik Brodowski   [PATCH] pcmcia: c...
167
  	pcmcia_check_driver(driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
  	/* initialize common fields */
  	driver->drv.bus = &pcmcia_bus_type;
  	driver->drv.owner = driver->owner;
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
171
  	driver->drv.name = driver->name;
3f565232c   Dominik Brodowski   pcmcia: use mutex...
172
  	mutex_init(&driver->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
173
  	INIT_LIST_HEAD(&driver->dynids.list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174

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

6179b5562   Bernhard Walle   add new_id to PCM...
178
179
180
181
182
183
184
185
186
  	error = driver_register(&driver->drv);
  	if (error < 0)
  		return error;
  
  	error = pcmcia_create_newid_file(driver);
  	if (error)
  		driver_unregister(&driver->drv);
  
  	return error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
190
191
  }
  EXPORT_SYMBOL(pcmcia_register_driver);
  
  /**
   * pcmcia_unregister_driver - unregister a PCMCIA driver with the bus core
78187865e   Randy Dunlap   pcmcia: fix kerne...
192
   * @driver: the &driver being unregistered
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
   */
  void pcmcia_unregister_driver(struct pcmcia_driver *driver)
  {
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
196
197
  	pr_debug("unregistering driver %s
  ", driver->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  	driver_unregister(&driver->drv);
6179b5562   Bernhard Walle   add new_id to PCM...
199
  	pcmcia_free_dynids(driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
201
  }
  EXPORT_SYMBOL(pcmcia_unregister_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
  
  /* pcmcia_device handling */
5716d415f   Dominik Brodowski   pcmcia: remove ob...
204
  static struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
206
207
208
209
210
211
  {
  	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...
212
  static void pcmcia_put_dev(struct pcmcia_device *p_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
216
  {
  	if (p_dev)
  		put_device(&p_dev->dev);
  }
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
217
218
219
  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...
220
221
  	pr_debug("releasing config_t
  ");
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
222
223
  	kfree(c);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
  static void pcmcia_release_dev(struct device *dev)
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
44961a03a   Dominik Brodowski   pcmcia: avoid pro...
227
  	int i;
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
228
229
  	dev_dbg(dev, "releasing device
  ");
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
230
  	pcmcia_put_socket(p_dev->socket);
44961a03a   Dominik Brodowski   pcmcia: avoid pro...
231
232
  	for (i = 0; i < 4; i++)
  		kfree(p_dev->prod_id[i]);
bd65a6857   Brice Goglin   [PATCH] pcmcia: a...
233
  	kfree(p_dev->devname);
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
234
  	kref_put(&p_dev->function_config->ref, pcmcia_release_function);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
  	kfree(p_dev);
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
237
  static int pcmcia_device_probe(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
  {
  	struct pcmcia_device *p_dev;
  	struct pcmcia_driver *p_drv;
f8cfa618d   Dominik Brodowski   [PATCH] pcmcia: u...
241
  	struct pcmcia_socket *s;
af2b3b503   Dominik Brodowski   [PATCH] pcmcia: c...
242
  	cistpl_config_t cis_config;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
248
249
250
  	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...
251
  	s = p_dev->socket;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252

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

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

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

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

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

00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
316
  	mutex_lock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
317
318
319
320
  	if (!leftover)
  		s->device_count = 0;
  	else
  		s->device_count = 1;
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
321
  	mutex_unlock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
322
323
324
325
326
  
  	/* 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 ...
327
  		mutex_lock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
328
  		list_del(&p_dev->socket_device_list);
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
329
  		mutex_unlock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
330

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

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

d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
347
348
  	dev_dbg(dev, "removing device
  ");
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
349

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

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

f39907155   Dominik Brodowski   [PATCH] pcmcia: r...
366
  	/* check for proper unloading */
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
367
  	if (p_dev->_irq || p_dev->_io || p_dev->_locked)
ac449d6e2   Dominik Brodowski   pcmcia: use dev_p...
368
369
370
  		dev_printk(KERN_INFO, dev,
  			"pcmcia: driver %s did not release config properly
  ",
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
371
  			p_drv->name);
cc3b4866b   Dominik Brodowski   [PATCH] pcmcia: u...
372

f39907155   Dominik Brodowski   [PATCH] pcmcia: r...
373
  	for (i = 0; i < MAX_WIN; i++)
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
374
  		if (p_dev->_win & CLIENT_WIN_REQ(i))
ac449d6e2   Dominik Brodowski   pcmcia: use dev_p...
375
376
377
  			dev_printk(KERN_INFO, dev,
  			  "pcmcia: driver %s did not release window properly
  ",
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
378
  			   p_drv->name);
cc3b4866b   Dominik Brodowski   [PATCH] pcmcia: u...
379

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

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

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

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

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

7d7ba8d31   Dominik Brodowski   pcmcia: allow for...
485
486
487
488
489
490
  	/* 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...
491
492
493
  		goto err_free;
  
  	p_dev->socket = s;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
496
  	p_dev->func   = function;
  
  	p_dev->dev.bus = &pcmcia_bus_type;
873733188   Greg Kroah-Hartman   Driver core: conv...
497
  	p_dev->dev.parent = s->dev.parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
  	p_dev->dev.release = pcmcia_release_dev;
43d9f7fda   James Bottomley   pcmcia: use DMA_M...
499
500
501
  	/* 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...
502
503
504
505
  	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...
506
507
  	if (!p_dev->devname)
  		goto err_free;
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
508
509
  	dev_dbg(&p_dev->dev, "devname is %s
  ", p_dev->devname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510

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

6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
528
529
530
531
  	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
532

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

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

ac449d6e2   Dominik Brodowski   pcmcia: use dev_p...
560
  	dev_printk(KERN_NOTICE, &p_dev->dev,
6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
561
562
  		   "pcmcia: registering new device %s (IRQ: %d)
  ",
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
563
  		   p_dev->devname, p_dev->irq);
807277cbf   Dominik Brodowski   [PCMCIA] inform u...
564

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

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

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

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

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

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

84897fc05   Dominik Brodowski   pcmcia: pccard_re...
615
  	ret = pccard_validate_cis(s, &no_chains);
c5081d5f4   Dominik Brodowski   pcmcia: simplify ...
616
  	if (ret || !no_chains) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
617
618
  		dev_dbg(&s->dev, "invalid CIS or invalid resources
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
620
621
622
623
624
625
  		return -ENODEV;
  	}
  
  	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...
626
  	s->functions = no_funcs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627

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

9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
631
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
  }
af461fc18   Dominik Brodowski   pcmcia: delay re-...
633
  static int pcmcia_requery_callback(struct device *dev, void * _data)
ff1fa9ef3   Dominik Brodowski   [PATCH] pcmcia: C...
634
  {
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
635
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
636
  	if (!p_dev->dev.driver) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
637
638
  		dev_dbg(dev, "update device information
  ");
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
639
  		pcmcia_device_query(p_dev);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
640
  	}
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
641
642
643
  
  	return 0;
  }
aa584ca4c   Dominik Brodowski   pcmcia: use state...
644

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

af461fc18   Dominik Brodowski   pcmcia: delay re-...
649
650
651
  	if (s->functions == 0) {
  		pcmcia_card_add(s);
  		return;
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
652
653
654
655
656
  	}
  
  	/* 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-...
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
  	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 ...
673
674
  		if (old_funcs != new_funcs) {
  			/* we need to re-start */
af461fc18   Dominik Brodowski   pcmcia: delay re-...
675
  			pcmcia_card_remove(s, NULL);
b83156b52   Dominik Brodowski   pcmcia: avoid val...
676
  			s->functions = 0;
af461fc18   Dominik Brodowski   pcmcia: delay re-...
677
  			pcmcia_card_add(s);
af461fc18   Dominik Brodowski   pcmcia: delay re-...
678
679
  		}
  	}
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
680

aa584ca4c   Dominik Brodowski   pcmcia: use state...
681
682
683
684
  	/* 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...
685
  	has_pfc = s->pcmcia_pfc;
aa584ca4c   Dominik Brodowski   pcmcia: use state...
686
687
688
  	mutex_unlock(&s->ops_mutex);
  	if (has_pfc)
  		pcmcia_device_add(s, 0);
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
689
690
  	/* we re-scan all devices, not just the ones connected to this
  	 * socket. This does not matter, though. */
af461fc18   Dominik Brodowski   pcmcia: delay re-...
691
692
693
  	if (bus_rescan_devices(&pcmcia_bus_type))
  		dev_warn(&s->dev, "rescanning the bus failed
  ");
ff1fa9ef3   Dominik Brodowski   [PATCH] pcmcia: C...
694
  }
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
695

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

1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
697
698
699
700
  #ifdef CONFIG_PCMCIA_LOAD_CIS
  
  /**
   * pcmcia_load_firmware - load CIS from userspace if device-provided is broken
78187865e   Randy Dunlap   pcmcia: fix kerne...
701
702
   * @dev: the pcmcia device which needs a CIS override
   * @filename: requested filename in /lib/firmware/
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
703
704
705
706
707
708
709
710
711
   *
   * 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.
   */
  static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
  {
  	struct pcmcia_socket *s = dev->socket;
  	const struct firmware *fw;
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
712
  	int ret = -ENOMEM;
b1095afe6   Dominik Brodowski   pcmcia: re-start ...
713
714
  	cistpl_longlink_mfc_t mfc;
  	int old_funcs, new_funcs = 1;
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
715
716
717
  
  	if (!filename)
  		return -EINVAL;
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
718
719
  	dev_dbg(&dev->dev, "trying to load CIS file %s
  ", filename);
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
720

ed62acec2   Samuel Ortiz   firmware: pcmcia/...
721
  	if (request_firmware(&fw, filename, &dev->dev) == 0) {
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
722
723
  		if (fw->size >= CISTPL_MAX_CIS_SIZE) {
  			ret = -EINVAL;
ac449d6e2   Dominik Brodowski   pcmcia: use dev_p...
724
725
726
  			dev_printk(KERN_ERR, &dev->dev,
  				   "pcmcia: CIS override is too big
  ");
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
727
  			goto release;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
728
  		}
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
729

53efec951   Dominik Brodowski   pcmcia: only copy...
730
  		if (!pcmcia_replace_cis(s, fw->data, fw->size))
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
731
  			ret = 0;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
732
  		else {
ac449d6e2   Dominik Brodowski   pcmcia: use dev_p...
733
734
735
  			dev_printk(KERN_ERR, &dev->dev,
  				   "pcmcia: CIS override failed
  ");
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
736
737
  			goto release;
  		}
b1095afe6   Dominik Brodowski   pcmcia: re-start ...
738
739
740
741
742
743
744
745
  		/* 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...
746
747
748
  
  		/* update information */
  		pcmcia_device_query(dev);
aa584ca4c   Dominik Brodowski   pcmcia: use state...
749
750
  		/* requery (as number of functions might have changed) */
  		pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY);
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
751
752
753
  	}
   release:
  	release_firmware(fw);
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
754
  	return ret;
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
755
756
757
758
759
760
761
762
763
764
  }
  
  #else /* !CONFIG_PCMCIA_LOAD_CIS */
  
  static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
  {
  	return -ENODEV;
  }
  
  #endif
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
765
  static inline int pcmcia_devmatch(struct pcmcia_device *dev,
e9fb13bfe   Joe Perches   pcmcia: Make decl...
766
  				  const struct pcmcia_device_id *did)
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
  {
  	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...
812
813
  		dev_dbg(&dev->dev, "this is a pseudo-multi-function device
  ");
aa584ca4c   Dominik Brodowski   pcmcia: use state...
814
  		mutex_lock(&dev->socket->ops_mutex);
ce3f9d71b   Dominik Brodowski   pcmcia: remove un...
815
  		dev->socket->pcmcia_pfc = 1;
aa584ca4c   Dominik Brodowski   pcmcia: use state...
816
  		mutex_unlock(&dev->socket->ops_mutex);
83bf6f11e   Alexander Kurz   pcmcia: fix match...
817
818
  		if (dev->device_no != did->device_no)
  			return 0;
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
819
820
821
  	}
  
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) {
94a819f80   Dominik Brodowski   pcmcia: assert lo...
822
  		int ret;
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
823
824
825
826
827
  		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...
828
  		if (dev->socket->pcmcia_pfc)
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
829
830
831
832
833
834
835
836
  			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...
837
838
839
840
841
842
843
844
  		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...
845
  			return 0;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
846
  		}
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
847
  	}
ea7b38825   Dominik Brodowski   [PATCH] pcmcia: m...
848
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
849
850
  		dev_dbg(&dev->dev, "device needs a fake CIS
  ");
daa9517d9   Dominik Brodowski   [PATCH] pcmcia: r...
851
  		if (!dev->socket->fake_cis)
b1095afe6   Dominik Brodowski   pcmcia: re-start ...
852
853
  			if (pcmcia_load_firmware(dev, did->cisfile))
  				return 0;
ea7b38825   Dominik Brodowski   [PATCH] pcmcia: m...
854
  	}
f602ff7eb   Dominik Brodowski   [PATCH] pcmcia: m...
855
856
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) {
  		int i;
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
857
  		for (i = 0; i < 4; i++)
f602ff7eb   Dominik Brodowski   [PATCH] pcmcia: m...
858
859
860
861
862
  			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...
863
864
  	return 1;
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
865
866
867
868
  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...
869
  	const struct pcmcia_device_id *did = p_drv->id_table;
6179b5562   Bernhard Walle   add new_id to PCM...
870
871
872
  	struct pcmcia_dynid *dynid;
  
  	/* match dynamic devices first */
3f565232c   Dominik Brodowski   pcmcia: use mutex...
873
  	mutex_lock(&p_drv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
874
  	list_for_each_entry(dynid, &p_drv->dynids.list, node) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
875
876
  		dev_dbg(dev, "trying to match to %s
  ", drv->name);
6179b5562   Bernhard Walle   add new_id to PCM...
877
  		if (pcmcia_devmatch(p_dev, &dynid->id)) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
878
879
  			dev_dbg(dev, "matched to %s
  ", drv->name);
3f565232c   Dominik Brodowski   pcmcia: use mutex...
880
  			mutex_unlock(&p_drv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
881
882
883
  			return 1;
  		}
  	}
3f565232c   Dominik Brodowski   pcmcia: use mutex...
884
  	mutex_unlock(&p_drv->dynids.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885

1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
886
  	while (did && did->match_flags) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
887
888
  		dev_dbg(dev, "trying to match to %s
  ", drv->name);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
889
  		if (pcmcia_devmatch(p_dev, did)) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
890
891
  			dev_dbg(dev, "matched to %s
  ", drv->name);
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
892
  			return 1;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
893
  		}
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
894
895
  		did++;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
896
897
  	return 0;
  }
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
898
  #ifdef CONFIG_HOTPLUG
7eff2e7a8   Kay Sievers   Driver core: chan...
899
  static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
900
901
  {
  	struct pcmcia_device *p_dev;
7eff2e7a8   Kay Sievers   Driver core: chan...
902
  	int i;
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
903
904
905
906
907
908
909
910
  	u32 hash[4] = { 0, 0, 0, 0};
  
  	if (!dev)
  		return -ENODEV;
  
  	p_dev = to_pcmcia_dev(dev);
  
  	/* calculate hashes */
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
911
  	for (i = 0; i < 4; i++) {
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
912
913
914
915
  		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...
916
  	if (add_uevent_var(env, "SOCKET_NO=%u", p_dev->socket->sock))
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
917
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
918
  	if (add_uevent_var(env, "DEVICE_NO=%02X", p_dev->device_no))
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
919
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
920
  	if (add_uevent_var(env, "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
312c004d3   Kay Sievers   [PATCH] driver co...
921
922
923
924
925
926
927
928
929
930
  			   "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...
931
  		return -ENOMEM;
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
932
933
934
935
  	return 0;
  }
  
  #else
7eff2e7a8   Kay Sievers   Driver core: chan...
936
  static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
937
938
939
940
941
  {
  	return -ENODEV;
  }
  
  #endif
3f8df781f   Alan Stern   PM: remove deprec...
942
943
944
945
946
947
948
949
  /************************ runtime PM support ***************************/
  
  static int pcmcia_dev_suspend(struct device *dev, pm_message_t state);
  static int pcmcia_dev_resume(struct device *dev);
  
  static int runtime_suspend(struct device *dev)
  {
  	int rc;
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
950
  	device_lock(dev);
3f8df781f   Alan Stern   PM: remove deprec...
951
  	rc = pcmcia_dev_suspend(dev, PMSG_SUSPEND);
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
952
  	device_unlock(dev);
3f8df781f   Alan Stern   PM: remove deprec...
953
954
  	return rc;
  }
933a838aa   Dominik Brodowski   pcmcia: make use ...
955
  static int runtime_resume(struct device *dev)
3f8df781f   Alan Stern   PM: remove deprec...
956
957
  {
  	int rc;
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
958
  	device_lock(dev);
3f8df781f   Alan Stern   PM: remove deprec...
959
  	rc = pcmcia_dev_resume(dev);
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
960
  	device_unlock(dev);
933a838aa   Dominik Brodowski   pcmcia: make use ...
961
  	return rc;
3f8df781f   Alan Stern   PM: remove deprec...
962
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
964
965
  /************************ per-device sysfs output ***************************/
  
  #define pcmcia_device_attr(field, test, format)				\
e404e274f   Yani Ioannou   [PATCH] Driver Co...
966
  static ssize_t field##_show (struct device *dev, struct device_attribute *attr, char *buf)		\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
968
  {									\
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
969
  	return p_dev->test ? sprintf(buf, format, p_dev->field) : -ENODEV; \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
971
972
  }
  
  #define pcmcia_device_stringattr(name, field)					\
e404e274f   Yani Ioannou   [PATCH] Driver Co...
973
  static ssize_t name##_show (struct device *dev, struct device_attribute *attr, char *buf)		\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
974
975
  {									\
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
976
977
  	return p_dev->field ? sprintf(buf, "%s
  ", p_dev->field) : -ENODEV; \
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978
979
980
981
982
983
984
985
986
987
988
989
990
991
  }
  
  pcmcia_device_attr(func, socket, "0x%02x
  ");
  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]);
8f677ea07   Dominik Brodowski   pcmcia: export re...
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
  static ssize_t pcmcia_show_resources(struct device *dev,
  				     struct device_attribute *attr, char *buf)
  {
  	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;
  }
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1005
1006
1007
1008
  
  static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute *attr, char *buf)
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1009
  	if (p_dev->suspended)
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
  		return sprintf(buf, "off
  ");
  	else
  		return sprintf(buf, "on
  ");
  }
  
  static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute *attr,
  				     const char *buf, size_t count)
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
  	int ret = 0;
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1022
1023
  	if (!count)
  		return -EINVAL;
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1024

f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1025
  	if ((!p_dev->suspended) && !strncmp(buf, "off", 3))
3f8df781f   Alan Stern   PM: remove deprec...
1026
  		ret = runtime_suspend(dev);
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1027
  	else if (p_dev->suspended && !strncmp(buf, "on", 2))
933a838aa   Dominik Brodowski   pcmcia: make use ...
1028
  		ret = runtime_resume(dev);
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1029
1030
1031
  
  	return ret ? ret : count;
  }
3704511b2   Dominik Brodowski   [PATCH] pcmcia: f...
1032
  static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
3248ff43f   Dominik Brodowski   [PATCH] pcmcia: e...
1033
1034
1035
1036
1037
1038
  {
  	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...
1039
  	for (i = 0; i < 4; i++) {
3248ff43f   Dominik Brodowski   [PATCH] pcmcia: e...
1040
1041
  		if (!p_dev->prod_id[i])
  			continue;
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1042
1043
  		hash[i] = crc32(0, p_dev->prod_id[i],
  				strlen(p_dev->prod_id[i]));
3248ff43f   Dominik Brodowski   [PATCH] pcmcia: e...
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
  	}
  	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]);
  }
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1054

3248ff43f   Dominik Brodowski   [PATCH] pcmcia: e...
1055
1056
  static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
  		struct device_attribute *attr, const char *buf, size_t count)
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1057
1058
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1059
1060
1061
  
  	if (!count)
  		return -EINVAL;
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1062

94a819f80   Dominik Brodowski   pcmcia: assert lo...
1063
  	mutex_lock(&p_dev->socket->ops_mutex);
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1064
  	p_dev->allow_func_id_match = 1;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
1065
  	mutex_unlock(&p_dev->socket->ops_mutex);
af461fc18   Dominik Brodowski   pcmcia: delay re-...
1066
  	pcmcia_parse_uevents(p_dev->socket, PCMCIA_UEVENT_REQUERY);
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1067
1068
1069
  
  	return count;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070
1071
  static struct device_attribute pcmcia_dev_attrs[] = {
  	__ATTR(function, 0444, func_show, NULL),
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1072
  	__ATTR(pm_state, 0644, pcmcia_show_pm_state, pcmcia_store_pm_state),
8f677ea07   Dominik Brodowski   pcmcia: export re...
1073
  	__ATTR(resources, 0444, pcmcia_show_resources, NULL),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1074
1075
1076
1077
1078
1079
1080
  	__ATTR_RO(func_id),
  	__ATTR_RO(manf_id),
  	__ATTR_RO(card_id),
  	__ATTR_RO(prod_id1),
  	__ATTR_RO(prod_id2),
  	__ATTR_RO(prod_id3),
  	__ATTR_RO(prod_id4),
3248ff43f   Dominik Brodowski   [PATCH] pcmcia: e...
1081
  	__ATTR_RO(modalias),
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1082
  	__ATTR(allow_func_id_match, 0200, NULL, pcmcia_store_allow_func_id_match),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
1084
  	__ATTR_NULL,
  };
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1085
  /* PM support, also needed for reset */
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1086
  static int pcmcia_dev_suspend(struct device *dev, pm_message_t state)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1087
1088
1089
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
  	struct pcmcia_driver *p_drv = NULL;
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1090
  	int ret = 0;
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1091

94a819f80   Dominik Brodowski   pcmcia: assert lo...
1092
1093
1094
  	mutex_lock(&p_dev->socket->ops_mutex);
  	if (p_dev->suspended) {
  		mutex_unlock(&p_dev->socket->ops_mutex);
d6b4fa6d6   David Brownell   pcmcia: stop upda...
1095
  		return 0;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
1096
1097
1098
  	}
  	p_dev->suspended = 1;
  	mutex_unlock(&p_dev->socket->ops_mutex);
d6b4fa6d6   David Brownell   pcmcia: stop upda...
1099

d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1100
1101
  	dev_dbg(dev, "suspending
  ");
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1102

8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1103
1104
  	if (dev->driver)
  		p_drv = to_pcmcia_drv(dev->driver);
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1105
1106
1107
1108
  	if (!p_drv)
  		goto out;
  
  	if (p_drv->suspend) {
8661bb5b4   Dominik Brodowski   [PATCH] pcmcia: d...
1109
  		ret = p_drv->suspend(p_dev);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1110
  		if (ret) {
ac449d6e2   Dominik Brodowski   pcmcia: use dev_p...
1111
1112
1113
1114
  			dev_printk(KERN_ERR, dev,
  				   "pcmcia: device %s (driver %s) did "
  				   "not want to go to sleep (%d)
  ",
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
1115
  				   p_dev->devname, p_drv->name, ret);
94a819f80   Dominik Brodowski   pcmcia: assert lo...
1116
1117
1118
  			mutex_lock(&p_dev->socket->ops_mutex);
  			p_dev->suspended = 0;
  			mutex_unlock(&p_dev->socket->ops_mutex);
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1119
  			goto out;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1120
  		}
8661bb5b4   Dominik Brodowski   [PATCH] pcmcia: d...
1121
  	}
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1122

d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1123
  	if (p_dev->device_no == p_dev->func) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1124
1125
  		dev_dbg(dev, "releasing configuration
  ");
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1126
  		pcmcia_release_configuration(p_dev);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1127
  	}
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1128

f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1129
   out:
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1130
  	return ret;
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1131
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1132
  static int pcmcia_dev_resume(struct device *dev)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1133
1134
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1135
  	struct pcmcia_driver *p_drv = NULL;
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1136
  	int ret = 0;
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1137

94a819f80   Dominik Brodowski   pcmcia: assert lo...
1138
1139
1140
  	mutex_lock(&p_dev->socket->ops_mutex);
  	if (!p_dev->suspended) {
  		mutex_unlock(&p_dev->socket->ops_mutex);
d6b4fa6d6   David Brownell   pcmcia: stop upda...
1141
  		return 0;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
1142
1143
1144
  	}
  	p_dev->suspended = 0;
  	mutex_unlock(&p_dev->socket->ops_mutex);
d6b4fa6d6   David Brownell   pcmcia: stop upda...
1145

d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1146
1147
  	dev_dbg(dev, "resuming
  ");
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1148

8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1149
1150
  	if (dev->driver)
  		p_drv = to_pcmcia_drv(dev->driver);
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1151
1152
1153
1154
  	if (!p_drv)
  		goto out;
  
  	if (p_dev->device_no == p_dev->func) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1155
1156
  		dev_dbg(dev, "requesting configuration
  ");
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
1157
  		ret = pcmcia_enable_device(p_dev);
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1158
1159
  		if (ret)
  			goto out;
8661bb5b4   Dominik Brodowski   [PATCH] pcmcia: d...
1160
  	}
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1161

e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1162
1163
  	if (p_drv->resume)
  		ret = p_drv->resume(p_dev);
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1164
   out:
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1165
  	return ret;
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1166
1167
1168
1169
1170
1171
1172
  }
  
  
  static int pcmcia_bus_suspend_callback(struct device *dev, void * _data)
  {
  	struct pcmcia_socket *skt = _data;
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
3f8df781f   Alan Stern   PM: remove deprec...
1173
  	if (p_dev->socket != skt || p_dev->suspended)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1174
  		return 0;
3f8df781f   Alan Stern   PM: remove deprec...
1175
  	return runtime_suspend(dev);
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1176
1177
1178
1179
1180
1181
  }
  
  static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
  {
  	struct pcmcia_socket *skt = _data;
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
3f8df781f   Alan Stern   PM: remove deprec...
1182
  	if (p_dev->socket != skt || !p_dev->suspended)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1183
  		return 0;
3f8df781f   Alan Stern   PM: remove deprec...
1184
  	runtime_resume(dev);
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1185
1186
1187
1188
1189
1190
  
  	return 0;
  }
  
  static int pcmcia_bus_resume(struct pcmcia_socket *skt)
  {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1191
1192
  	dev_dbg(&skt->dev, "resuming socket %d
  ", skt->sock);
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1193
1194
1195
1196
1197
1198
  	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...
1199
1200
  	dev_dbg(&skt->dev, "suspending socket %d
  ", skt->sock);
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1201
1202
1203
1204
1205
1206
1207
  	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 ...
1208
1209
1210
1211
  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
1212

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1213
1214
1215
1216
  	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
1217

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1218
1219
  	return 0;
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1220

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

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

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

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1232
1233
  	return 0;
  }
1617406a7   Florin Malita   [PATCH] pcmcia: m...
1234

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1235
1236
1237
1238
1239
1240
  static int pcmcia_bus_early_resume(struct pcmcia_socket *skt)
  {
  	if (!verify_cis_cache(skt)) {
  		pcmcia_put_socket(skt);
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1241

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

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

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1248
1249
1250
1251
1252
1253
  	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
1254

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1255
1256
1257
1258
  	/* now, add the new card */
  	pcmcia_bus_add(skt);
  	return 0;
  }
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1259

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260

04de08161   Dominik Brodowski   pcmcia: pcmcia_de...
1261
1262
1263
1264
1265
1266
1267
  /*
   * 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...
1268
  struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev)
9940ec361   Dominik Brodowski   [PATCH] pcmcia: c...
1269
1270
1271
1272
1273
1274
1275
  {
  	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...
1276
1277
  	if (atomic_read(&p_dev->socket->present) != 0)
  		ret = p_dev;
9940ec361   Dominik Brodowski   [PATCH] pcmcia: c...
1278

9940ec361   Dominik Brodowski   [PATCH] pcmcia: c...
1279
1280
1281
1282
  	pcmcia_put_dev(p_dev);
  	return ret;
  }
  EXPORT_SYMBOL(pcmcia_dev_present);
90c6cdd1f   Dominik Brodowski   [PATCH] pcmcia: c...
1283
1284
  static struct pcmcia_callback pcmcia_bus_callback = {
  	.owner = THIS_MODULE,
7b24e7988   Dominik Brodowski   pcmcia: split up ...
1285
1286
  	.add = pcmcia_bus_add,
  	.remove = pcmcia_bus_remove,
af461fc18   Dominik Brodowski   pcmcia: delay re-...
1287
  	.requery = pcmcia_requery,
6e7b51a73   Dominik Brodowski   pcmcia: move cist...
1288
  	.validate = pccard_validate_cis,
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1289
  	.suspend = pcmcia_bus_suspend,
7b24e7988   Dominik Brodowski   pcmcia: split up ...
1290
  	.early_resume = pcmcia_bus_early_resume,
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1291
  	.resume = pcmcia_bus_resume,
90c6cdd1f   Dominik Brodowski   [PATCH] pcmcia: c...
1292
  };
873733188   Greg Kroah-Hartman   Driver core: conv...
1293
  static int __devinit pcmcia_bus_add_socket(struct device *dev,
d8539d81a   Dmitry Torokhov   [PATCH] Driver co...
1294
  					   struct class_interface *class_intf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1295
  {
873733188   Greg Kroah-Hartman   Driver core: conv...
1296
  	struct pcmcia_socket *socket = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1297
  	int ret;
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1298
1299
  	socket = pcmcia_get_socket(socket);
  	if (!socket) {
ac449d6e2   Dominik Brodowski   pcmcia: use dev_p...
1300
1301
1302
  		dev_printk(KERN_ERR, dev,
  			   "PCMCIA obtaining reference to socket failed
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1303
1304
  		return -ENODEV;
  	}
6e7b51a73   Dominik Brodowski   pcmcia: move cist...
1305
1306
1307
1308
1309
1310
1311
  	ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr);
  	if (ret) {
  		dev_printk(KERN_ERR, dev, "PCMCIA registration failed
  ");
  		pcmcia_put_socket(socket);
  		return ret;
  	}
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1312
  	INIT_LIST_HEAD(&socket->devices_list);
ce3f9d71b   Dominik Brodowski   pcmcia: remove un...
1313
  	socket->pcmcia_pfc = 0;
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1314
  	socket->device_count = 0;
e4f1ac212   Dominik Brodowski   pcmcia: do not in...
1315
  	atomic_set(&socket->present, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316

90c6cdd1f   Dominik Brodowski   [PATCH] pcmcia: c...
1317
  	ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
  	if (ret) {
ac449d6e2   Dominik Brodowski   pcmcia: use dev_p...
1319
1320
  		dev_printk(KERN_ERR, dev, "PCMCIA registration failed
  ");
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1321
  		pcmcia_put_socket(socket);
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1322
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
1324
1325
1326
  	}
  
  	return 0;
  }
873733188   Greg Kroah-Hartman   Driver core: conv...
1327
  static void pcmcia_bus_remove_socket(struct device *dev,
d8539d81a   Dmitry Torokhov   [PATCH] Driver co...
1328
  				     struct class_interface *class_intf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1329
  {
873733188   Greg Kroah-Hartman   Driver core: conv...
1330
  	struct pcmcia_socket *socket = dev_get_drvdata(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1331

dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1332
  	if (!socket)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
1334
1335
  		return;
  
  	pccard_register_pcmcia(socket, NULL);
dfbc9e9d3   Daniel Ritz   [PATCH] pcmcia: f...
1336
  	/* unregister any unbound devices */
8e4d9dcb4   Daniel Ritz   [PATCH] fix "pcmc...
1337
  	mutex_lock(&socket->skt_mutex);
dfbc9e9d3   Daniel Ritz   [PATCH] pcmcia: f...
1338
  	pcmcia_card_remove(socket, NULL);
180c33ee4   Dominik Brodowski   pcmcia: call CIS ...
1339
  	release_cis_mem(socket);
8e4d9dcb4   Daniel Ritz   [PATCH] fix "pcmc...
1340
  	mutex_unlock(&socket->skt_mutex);
dfbc9e9d3   Daniel Ritz   [PATCH] pcmcia: f...
1341

6e7b51a73   Dominik Brodowski   pcmcia: move cist...
1342
  	sysfs_remove_bin_file(&dev->kobj, &pccard_cis_attr);
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
1343
  	pcmcia_put_socket(socket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344
1345
1346
1347
1348
1349
  
  	return;
  }
  
  
  /* the pcmcia_bus_interface is used to handle pcmcia socket devices */
ed49f5d00   Sam Ravnborg   pcmcia: silence s...
1350
  static struct class_interface pcmcia_bus_interface __refdata = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1351
  	.class = &pcmcia_socket_class,
873733188   Greg Kroah-Hartman   Driver core: conv...
1352
1353
  	.add_dev = &pcmcia_bus_add_socket,
  	.remove_dev = &pcmcia_bus_remove_socket,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1354
  };
e7a480d22   Dominik Brodowski   [PATCH] pcmcia: m...
1355
  struct bus_type pcmcia_bus_type = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
  	.name = "pcmcia",
312c004d3   Kay Sievers   [PATCH] driver co...
1357
  	.uevent = pcmcia_bus_uevent,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1358
1359
  	.match = pcmcia_bus_match,
  	.dev_attrs = pcmcia_dev_attrs,
1d0baa3a1   Russell King   [PATCH] Add pcmci...
1360
1361
  	.probe = pcmcia_device_probe,
  	.remove = pcmcia_device_remove,
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1362
1363
  	.suspend = pcmcia_dev_suspend,
  	.resume = pcmcia_dev_resume,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1365
1366
1367
1368
  
  
  static int __init init_pcmcia_bus(void)
  {
ace7d4772   Randy Dunlap   [PATCH] pcmcia/ds...
1369
  	int ret;
ace7d4772   Randy Dunlap   [PATCH] pcmcia/ds...
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
  	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
1384

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1385
1386
  	return 0;
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1387
  fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388
1389
1390
1391
1392
  			       * pcmcia_socket_class is already registered */
  
  
  static void __exit exit_pcmcia_bus(void)
  {
e7a480d22   Dominik Brodowski   [PATCH] pcmcia: m...
1393
  	class_interface_unregister(&pcmcia_bus_interface);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
1395
1396
1397
  
  	bus_unregister(&pcmcia_bus_type);
  }
  module_exit(exit_pcmcia_bus);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1398
  MODULE_ALIAS("ds");