Blame view

drivers/pcmcia/ds.c 34.8 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
  /*
   * ds.c -- 16-bit PCMCIA core support
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
   * The initial developer of the original code is David A. Hinds
   * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
   * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
   *
   * (C) 1999		David A. Hinds
7b24e7988   Dominik Brodowski   pcmcia: split up ...
10
   * (C) 2003 - 2010	Dominik Brodowski
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
   */
3b659fb86   Dominik Brodowski   [PATCH] pcmcia: r...
12
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
  #include <linux/errno.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
  #include <linux/list.h>
  #include <linux/delay.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <linux/workqueue.h>
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
19
  #include <linux/crc32.h>
daa9517d9   Dominik Brodowski   [PATCH] pcmcia: r...
20
  #include <linux/firmware.h>
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
21
  #include <linux/kref.h>
43d9f7fda   James Bottomley   pcmcia: use DMA_M...
22
  #include <linux/dma-mapping.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
23
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
29
30
31
32
33
34
35
36
37
  #include <pcmcia/cistpl.h>
  #include <pcmcia/ds.h>
  #include <pcmcia/ss.h>
  
  #include "cs_internal.h"
  
  /*====================================================================*/
  
  /* Module parameters */
  
  MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
  MODULE_DESCRIPTION("PCMCIA Driver Services");
  MODULE_LICENSE("GPL");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

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

23a83bfe6   Dominik Brodowski   [PATCH] pcmcia: c...
50
  	while (did && did->match_flags) {
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
51
  		for (i = 0; i < 4; i++) {
23a83bfe6   Dominik Brodowski   [PATCH] pcmcia: c...
52
53
54
55
56
57
58
59
60
  			if (!did->prod_id[i])
  				continue;
  
  			hash = crc32(0, did->prod_id[i], strlen(did->prod_id[i]));
  			if (hash == did->prod_id_hash[i])
  				continue;
  
  			printk(KERN_DEBUG "pcmcia: %s: invalid hash for "
  			       "product string \"%s\": is 0x%x, should "
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
61
62
  			       "be 0x%x
  ", p_drv->name, did->prod_id[i],
23a83bfe6   Dominik Brodowski   [PATCH] pcmcia: c...
63
  			       did->prod_id_hash[i], hash);
5085cb265   Dominik Brodowski   [PATCH] pcmcia: a...
64
  			printk(KERN_DEBUG "pcmcia: see "
3bdab16c5   Mauro Carvalho Chehab   docs: pcmcia: con...
65
  				"Documentation/pcmcia/devicetable.rst for "
5085cb265   Dominik Brodowski   [PATCH] pcmcia: a...
66
67
  				"details
  ");
23a83bfe6   Dominik Brodowski   [PATCH] pcmcia: c...
68
69
70
71
72
73
  		}
  		did++;
  	}
  
  	return;
  }
daa9517d9   Dominik Brodowski   [PATCH] pcmcia: r...
74

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
  /*======================================================================*/
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76

6179b5562   Bernhard Walle   add new_id to PCM...
77
  struct pcmcia_dynid {
46f533ccb   Laurent Navet   drivers: pcmcia: ...
78
79
  	struct list_head		node;
  	struct pcmcia_device_id		id;
6179b5562   Bernhard Walle   add new_id to PCM...
80
81
82
83
84
85
86
87
88
89
90
91
  };
  
  /**
   * pcmcia_store_new_id - add a new PCMCIA device ID to this driver and re-probe devices
   * @driver: target device driver
   * @buf: buffer for scanning device ID data
   * @count: input size
   *
   * Adds a new dynamic PCMCIA device ID to this driver,
   * and causes the driver to probe for all devices again.
   */
  static ssize_t
ad8f20a45   Greg Kroah-Hartman   pcmcia: ds: conve...
92
  new_id_store(struct device_driver *driver, const char *buf, size_t count)
6179b5562   Bernhard Walle   add new_id to PCM...
93
94
95
96
97
98
  {
  	struct pcmcia_dynid *dynid;
  	struct pcmcia_driver *pdrv = to_pcmcia_drv(driver);
  	__u16 match_flags, manf_id, card_id;
  	__u8 func_id, function, device_no;
  	__u32 prod_id_hash[4] = {0, 0, 0, 0};
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
99
  	int fields = 0;
6179b5562   Bernhard Walle   add new_id to PCM...
100
101
102
103
104
105
106
107
108
109
110
  	int retval = 0;
  
  	fields = sscanf(buf, "%hx %hx %hx %hhx %hhx %hhx %x %x %x %x",
  			&match_flags, &manf_id, &card_id, &func_id, &function, &device_no,
  			&prod_id_hash[0], &prod_id_hash[1], &prod_id_hash[2], &prod_id_hash[3]);
  	if (fields < 6)
  		return -EINVAL;
  
  	dynid = kzalloc(sizeof(struct pcmcia_dynid), GFP_KERNEL);
  	if (!dynid)
  		return -ENOMEM;
6179b5562   Bernhard Walle   add new_id to PCM...
111
112
113
114
115
116
117
  	dynid->id.match_flags = match_flags;
  	dynid->id.manf_id = manf_id;
  	dynid->id.card_id = card_id;
  	dynid->id.func_id = func_id;
  	dynid->id.function = function;
  	dynid->id.device_no = device_no;
  	memcpy(dynid->id.prod_id_hash, prod_id_hash, sizeof(__u32) * 4);
3f565232c   Dominik Brodowski   pcmcia: use mutex...
118
  	mutex_lock(&pdrv->dynids.lock);
b4b3d7bbe   Wolfram Sang   pcmcia: fix incor...
119
  	list_add_tail(&dynid->node, &pdrv->dynids.list);
3f565232c   Dominik Brodowski   pcmcia: use mutex...
120
  	mutex_unlock(&pdrv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
121

cef9bc56e   Alan Stern   Dynamic ID additi...
122
  	retval = driver_attach(&pdrv->drv);
6179b5562   Bernhard Walle   add new_id to PCM...
123
124
125
126
127
  
  	if (retval)
  		return retval;
  	return count;
  }
ad8f20a45   Greg Kroah-Hartman   pcmcia: ds: conve...
128
  static DRIVER_ATTR_WO(new_id);
6179b5562   Bernhard Walle   add new_id to PCM...
129
130
131
132
133
  
  static void
  pcmcia_free_dynids(struct pcmcia_driver *drv)
  {
  	struct pcmcia_dynid *dynid, *n;
3f565232c   Dominik Brodowski   pcmcia: use mutex...
134
  	mutex_lock(&drv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
135
136
137
138
  	list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
  		list_del(&dynid->node);
  		kfree(dynid);
  	}
3f565232c   Dominik Brodowski   pcmcia: use mutex...
139
  	mutex_unlock(&drv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
140
141
142
143
144
145
146
  }
  
  static int
  pcmcia_create_newid_file(struct pcmcia_driver *drv)
  {
  	int error = 0;
  	if (drv->probe != NULL)
2344c6de6   Greg Kroah-Hartman   PCMCIA: use prope...
147
  		error = driver_create_file(&drv->drv, &driver_attr_new_id);
6179b5562   Bernhard Walle   add new_id to PCM...
148
149
  	return error;
  }
ed283e9f0   Alan Stern   USB/PCI/PCMCIA: C...
150
151
152
153
154
  static void
  pcmcia_remove_newid_file(struct pcmcia_driver *drv)
  {
  	driver_remove_file(&drv->drv, &driver_attr_new_id);
  }
6179b5562   Bernhard Walle   add new_id to PCM...
155

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);
ed283e9f0   Alan Stern   USB/PCI/PCMCIA: C...
198
  	pcmcia_remove_newid_file(driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  	driver_unregister(&driver->drv);
6179b5562   Bernhard Walle   add new_id to PCM...
200
  	pcmcia_free_dynids(driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
  }
  EXPORT_SYMBOL(pcmcia_unregister_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
  
  /* pcmcia_device handling */
5716d415f   Dominik Brodowski   pcmcia: remove ob...
205
  static struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
208
209
210
211
212
  {
  	struct device *tmp_dev;
  	tmp_dev = get_device(&p_dev->dev);
  	if (!tmp_dev)
  		return NULL;
  	return to_pcmcia_dev(tmp_dev);
  }
5716d415f   Dominik Brodowski   pcmcia: remove ob...
213
  static void pcmcia_put_dev(struct pcmcia_device *p_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
216
217
  {
  	if (p_dev)
  		put_device(&p_dev->dev);
  }
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
218
219
220
  static void pcmcia_release_function(struct kref *ref)
  {
  	struct config_t *c = container_of(ref, struct config_t, ref);
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
221
222
  	pr_debug("releasing config_t
  ");
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
223
224
  	kfree(c);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
  static void pcmcia_release_dev(struct device *dev)
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
44961a03a   Dominik Brodowski   pcmcia: avoid pro...
228
  	int i;
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
229
230
  	dev_dbg(dev, "releasing device
  ");
dc109497b   Dominik Brodowski   [PATCH] pcmcia: m...
231
  	pcmcia_put_socket(p_dev->socket);
44961a03a   Dominik Brodowski   pcmcia: avoid pro...
232
233
  	for (i = 0; i < 4; i++)
  		kfree(p_dev->prod_id[i]);
bd65a6857   Brice Goglin   [PATCH] pcmcia: a...
234
  	kfree(p_dev->devname);
360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
235
  	kref_put(&p_dev->function_config->ref, pcmcia_release_function);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
237
  	kfree(p_dev);
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
238
  static int pcmcia_device_probe(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
  {
  	struct pcmcia_device *p_dev;
  	struct pcmcia_driver *p_drv;
f8cfa618d   Dominik Brodowski   [PATCH] pcmcia: u...
242
  	struct pcmcia_socket *s;
af2b3b503   Dominik Brodowski   [PATCH] pcmcia: c...
243
  	cistpl_config_t cis_config;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
245
246
247
248
249
250
251
  	int ret = 0;
  
  	dev = get_device(dev);
  	if (!dev)
  		return -ENODEV;
  
  	p_dev = to_pcmcia_dev(dev);
  	p_drv = to_pcmcia_drv(dev->driver);
f8cfa618d   Dominik Brodowski   [PATCH] pcmcia: u...
252
  	s = p_dev->socket;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253

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

360b65b95   Dominik Brodowski   [PATCH] pcmcia: m...
257
258
  	if ((!p_drv->probe) || (!p_dev->function_config) ||
  	    (!try_module_get(p_drv->owner))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
261
  		ret = -EINVAL;
  		goto put_dev;
  	}
af2b3b503   Dominik Brodowski   [PATCH] pcmcia: c...
262
263
264
265
  	/* set up some more device information */
  	ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG,
  				&cis_config);
  	if (!ret) {
7feabb641   Dominik Brodowski   pcmcia: move conf...
266
267
  		p_dev->config_base = cis_config.base;
  		p_dev->config_regs = cis_config.rmask[0];
1cc745d1c   Dominik Brodowski   pcmcia: remove th...
268
269
  		dev_dbg(dev, "base %x, regs %x", p_dev->config_base,
  			p_dev->config_regs);
af2b3b503   Dominik Brodowski   [PATCH] pcmcia: c...
270
  	} else {
f2e6cf767   Joe Perches   pcmcia: Convert d...
271
272
273
  		dev_info(dev,
  			 "pcmcia: could not parse base and rmask0 of CIS
  ");
7feabb641   Dominik Brodowski   pcmcia: move conf...
274
275
  		p_dev->config_base = 0;
  		p_dev->config_regs = 0;
af2b3b503   Dominik Brodowski   [PATCH] pcmcia: c...
276
  	}
f8cfa618d   Dominik Brodowski   [PATCH] pcmcia: u...
277
  	ret = p_drv->probe(p_dev);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
278
  	if (ret) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
279
280
  		dev_dbg(dev, "binding to %s failed with %d
  ",
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
281
  			   p_drv->name, ret);
82d56e6d2   Dominik Brodowski   [PATCH] pcmcia: p...
282
  		goto put_module;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
283
  	}
2e9b981a7   Dominik Brodowski   pcmcia: move driv...
284
  	dev_dbg(dev, "%s bound: Vpp %d.%d, idx %x, IRQ %d", p_drv->name,
1cc745d1c   Dominik Brodowski   pcmcia: remove th...
285
286
287
288
  		p_dev->vpp/10, p_dev->vpp%10, p_dev->config_index, p_dev->irq);
  	dev_dbg(dev, "resources: ioport %pR %pR iomem %pR %pR %pR",
  		p_dev->resource[0], p_dev->resource[1], p_dev->resource[2],
  		p_dev->resource[3], p_dev->resource[4]);
82d56e6d2   Dominik Brodowski   [PATCH] pcmcia: p...
289

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

cec5eb7be   Alan Cox   pcmcia: Fix broke...
296
  put_module:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
298
  	if (ret)
  		module_put(p_drv->owner);
cec5eb7be   Alan Cox   pcmcia: Fix broke...
299
  put_dev:
f8cfa618d   Dominik Brodowski   [PATCH] pcmcia: u...
300
  	if (ret)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
  		put_device(dev);
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
302
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
  }
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
304
305
306
307
308
309
310
  /*
   * Removes a PCMCIA card from the device tree and socket list.
   */
  static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *leftover)
  {
  	struct pcmcia_device	*p_dev;
  	struct pcmcia_device	*tmp;
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
311

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

00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
317
  	mutex_lock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
318
319
320
321
  	if (!leftover)
  		s->device_count = 0;
  	else
  		s->device_count = 1;
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
322
  	mutex_unlock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
323
324
325
326
327
  
  	/* unregister all pcmcia_devices registered with this socket, except leftover */
  	list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) {
  		if (p_dev == leftover)
  			continue;
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
328
  		mutex_lock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
329
  		list_del(&p_dev->socket_device_list);
00ce99ff5   Dominik Brodowski   pcmcia: simplify ...
330
  		mutex_unlock(&s->ops_mutex);
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
331

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

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

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

d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
351
352
353
354
  	/* If we're removing the primary module driving a
  	 * pseudo multi-function card, we need to unbind
  	 * all devices
  	 */
ce3f9d71b   Dominik Brodowski   pcmcia: remove un...
355
  	if ((p_dev->socket->pcmcia_pfc) &&
e6e4f397e   Dominik Brodowski   pcmcia: protect s...
356
  	    (p_dev->socket->device_count > 0) &&
d6ff5a853   Dominik Brodowski   [PATCH] pcmcia: p...
357
358
359
360
  	    (p_dev->device_no == 0))
  		pcmcia_card_remove(p_dev->socket, p_dev);
  
  	/* detach the "instance" */
f39907155   Dominik Brodowski   [PATCH] pcmcia: r...
361
362
  	if (!p_drv)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363

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

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

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

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

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

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

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

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

7d7ba8d31   Dominik Brodowski   pcmcia: allow for...
484
485
486
487
488
489
  	/* max of 2 PFC devices */
  	if ((p_dev->device_no >= 2) && (function == 0))
  		goto err_free;
  
  	/* max of 4 devices overall */
  	if (p_dev->device_no >= 4)
e6e4f397e   Dominik Brodowski   pcmcia: protect s...
490
491
492
  		goto err_free;
  
  	p_dev->socket = s;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
494
495
  	p_dev->func   = function;
  
  	p_dev->dev.bus = &pcmcia_bus_type;
873733188   Greg Kroah-Hartman   Driver core: conv...
496
  	p_dev->dev.parent = s->dev.parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
  	p_dev->dev.release = pcmcia_release_dev;
43d9f7fda   James Bottomley   pcmcia: use DMA_M...
498
  	/* by default don't allow DMA */
7ae10eb90   Christoph Hellwig   dma-mapping: remo...
499
  	p_dev->dma_mask = 0;
43d9f7fda   James Bottomley   pcmcia: use DMA_M...
500
  	p_dev->dev.dma_mask = &p_dev->dma_mask;
250969868   Kay Sievers   pcmcia: struct de...
501
502
503
504
  	dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no);
  	if (!dev_name(&p_dev->dev))
  		goto err_free;
  	p_dev->devname = kasprintf(GFP_KERNEL, "pcmcia%s", dev_name(&p_dev->dev));
bd65a6857   Brice Goglin   [PATCH] pcmcia: a...
505
506
  	if (!p_dev->devname)
  		goto err_free;
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
507
508
  	dev_dbg(&p_dev->dev, "devname is %s
  ", p_dev->devname);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509

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

6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
527
528
529
530
  	if (pcmcia_setup_irq(p_dev))
  		dev_warn(&p_dev->dev,
  			"IRQ setup failed -- device might not work
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531

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

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

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

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

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

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

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

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

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

84897fc05   Dominik Brodowski   pcmcia: pccard_re...
613
  	ret = pccard_validate_cis(s, &no_chains);
c5081d5f4   Dominik Brodowski   pcmcia: simplify ...
614
  	if (ret || !no_chains) {
e8e68fd86   Dominik Brodowski   pcmcia: do not br...
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
  #if defined(CONFIG_MTD_PCMCIA_ANONYMOUS)
  		/* Set up as an anonymous card. If we don't have anonymous
  		   memory support then just error the card as there is no
  		   point trying to second guess.
  
  		   Note: some cards have just a device entry, it may be
  		   worth extending support to cover these in future */
  		if (ret == -EIO) {
  			dev_info(&s->dev, "no CIS, assuming an anonymous memory card.
  ");
  			pcmcia_replace_cis(s, "\xFF", 1);
  			no_chains = 1;
  			ret = 0;
  		} else
  #endif
  		{
  			dev_dbg(&s->dev, "invalid CIS or invalid resources
  ");
  			return -ENODEV;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
636
637
638
639
640
  	}
  
  	if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC, &mfc))
  		no_funcs = mfc.nfn;
  	else
  		no_funcs = 1;
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
641
  	s->functions = no_funcs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642

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

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

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

8402641b2   Alan Cox   pcmcia: Fix requery
664
665
  	if (!(s->state & SOCKET_PRESENT))
  		return;
af461fc18   Dominik Brodowski   pcmcia: delay re-...
666
667
668
  	if (s->functions == 0) {
  		pcmcia_card_add(s);
  		return;
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
669
670
671
672
673
  	}
  
  	/* some device information might have changed because of a CIS
  	 * update or because we can finally read it correctly... so
  	 * determine it again, overwriting old values if necessary. */
af461fc18   Dominik Brodowski   pcmcia: delay re-...
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
  	bus_for_each_dev(&pcmcia_bus_type, NULL, NULL, pcmcia_requery_callback);
  
  	/* if the CIS changed, we need to check whether the number of
  	 * functions changed. */
  	if (s->fake_cis) {
  		int old_funcs, new_funcs;
  		cistpl_longlink_mfc_t mfc;
  
  		/* does this cis override add or remove functions? */
  		old_funcs = s->functions;
  
  		if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC,
  					&mfc))
  			new_funcs = mfc.nfn;
  		else
  			new_funcs = 1;
b1095afe6   Dominik Brodowski   pcmcia: re-start ...
690
691
  		if (old_funcs != new_funcs) {
  			/* we need to re-start */
af461fc18   Dominik Brodowski   pcmcia: delay re-...
692
  			pcmcia_card_remove(s, NULL);
b83156b52   Dominik Brodowski   pcmcia: avoid val...
693
  			s->functions = 0;
af461fc18   Dominik Brodowski   pcmcia: delay re-...
694
  			pcmcia_card_add(s);
af461fc18   Dominik Brodowski   pcmcia: delay re-...
695
696
  		}
  	}
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
697

aa584ca4c   Dominik Brodowski   pcmcia: use state...
698
699
700
701
  	/* If the PCMCIA device consists of two pseudo devices,
  	 * call pcmcia_device_add() -- which will fail if both
  	 * devices are already registered. */
  	mutex_lock(&s->ops_mutex);
ce3f9d71b   Dominik Brodowski   pcmcia: remove un...
702
  	has_pfc = s->pcmcia_pfc;
aa584ca4c   Dominik Brodowski   pcmcia: use state...
703
704
705
  	mutex_unlock(&s->ops_mutex);
  	if (has_pfc)
  		pcmcia_device_add(s, 0);
e2f0b5344   Dominik Brodowski   [PATCH] pcmcia: r...
706
707
  	/* we re-scan all devices, not just the ones connected to this
  	 * socket. This does not matter, though. */
af461fc18   Dominik Brodowski   pcmcia: delay re-...
708
709
710
  	if (bus_rescan_devices(&pcmcia_bus_type))
  		dev_warn(&s->dev, "rescanning the bus failed
  ");
ff1fa9ef3   Dominik Brodowski   [PATCH] pcmcia: C...
711
  }
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
712

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

1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
714
715
716
717
  #ifdef CONFIG_PCMCIA_LOAD_CIS
  
  /**
   * pcmcia_load_firmware - load CIS from userspace if device-provided is broken
78187865e   Randy Dunlap   pcmcia: fix kerne...
718
719
   * @dev: the pcmcia device which needs a CIS override
   * @filename: requested filename in /lib/firmware/
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
720
721
722
723
724
   *
   * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if
   * the one provided by the card is broken. The firmware files reside in
   * /lib/firmware/ in userspace.
   */
46f533ccb   Laurent Navet   drivers: pcmcia: ...
725
  static int pcmcia_load_firmware(struct pcmcia_device *dev, char *filename)
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
726
727
728
  {
  	struct pcmcia_socket *s = dev->socket;
  	const struct firmware *fw;
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
729
  	int ret = -ENOMEM;
b1095afe6   Dominik Brodowski   pcmcia: re-start ...
730
731
  	cistpl_longlink_mfc_t mfc;
  	int old_funcs, new_funcs = 1;
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
732
733
734
  
  	if (!filename)
  		return -EINVAL;
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
735
736
  	dev_dbg(&dev->dev, "trying to load CIS file %s
  ", filename);
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
737

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

53efec951   Dominik Brodowski   pcmcia: only copy...
746
  		if (!pcmcia_replace_cis(s, fw->data, fw->size))
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
747
  			ret = 0;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
748
  		else {
f2e6cf767   Joe Perches   pcmcia: Convert d...
749
750
  			dev_err(&dev->dev, "pcmcia: CIS override failed
  ");
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
751
752
  			goto release;
  		}
b1095afe6   Dominik Brodowski   pcmcia: re-start ...
753
754
755
756
757
758
759
760
  		/* we need to re-start if the number of functions changed */
  		old_funcs = s->functions;
  		if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC,
  					&mfc))
  			new_funcs = mfc.nfn;
  
  		if (old_funcs != new_funcs)
  			ret = -EBUSY;
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
761
762
763
  
  		/* update information */
  		pcmcia_device_query(dev);
aa584ca4c   Dominik Brodowski   pcmcia: use state...
764
765
  		/* requery (as number of functions might have changed) */
  		pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY);
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
766
767
768
  	}
   release:
  	release_firmware(fw);
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
769
  	return ret;
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
770
771
772
  }
  
  #else /* !CONFIG_PCMCIA_LOAD_CIS */
46f533ccb   Laurent Navet   drivers: pcmcia: ...
773
774
  static inline int pcmcia_load_firmware(struct pcmcia_device *dev,
  				       char *filename)
1d2c90425   Dominik Brodowski   [PATCH] pcmcia: m...
775
776
777
778
779
  {
  	return -ENODEV;
  }
  
  #endif
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
780
  static inline int pcmcia_devmatch(struct pcmcia_device *dev,
e9fb13bfe   Joe Perches   pcmcia: Make decl...
781
  				  const struct pcmcia_device_id *did)
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
  {
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID) {
  		if ((!dev->has_manf_id) || (dev->manf_id != did->manf_id))
  			return 0;
  	}
  
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID) {
  		if ((!dev->has_card_id) || (dev->card_id != did->card_id))
  			return 0;
  	}
  
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION) {
  		if (dev->func != did->function)
  			return 0;
  	}
  
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1) {
  		if (!dev->prod_id[0])
  			return 0;
  		if (strcmp(did->prod_id[0], dev->prod_id[0]))
  			return 0;
  	}
  
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2) {
  		if (!dev->prod_id[1])
  			return 0;
  		if (strcmp(did->prod_id[1], dev->prod_id[1]))
  			return 0;
  	}
  
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3) {
  		if (!dev->prod_id[2])
  			return 0;
  		if (strcmp(did->prod_id[2], dev->prod_id[2]))
  			return 0;
  	}
  
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4) {
  		if (!dev->prod_id[3])
  			return 0;
  		if (strcmp(did->prod_id[3], dev->prod_id[3]))
  			return 0;
  	}
  
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) {
83bf6f11e   Alexander Kurz   pcmcia: fix match...
827
828
  		dev_dbg(&dev->dev, "this is a pseudo-multi-function device
  ");
aa584ca4c   Dominik Brodowski   pcmcia: use state...
829
  		mutex_lock(&dev->socket->ops_mutex);
ce3f9d71b   Dominik Brodowski   pcmcia: remove un...
830
  		dev->socket->pcmcia_pfc = 1;
aa584ca4c   Dominik Brodowski   pcmcia: use state...
831
  		mutex_unlock(&dev->socket->ops_mutex);
83bf6f11e   Alexander Kurz   pcmcia: fix match...
832
833
  		if (dev->device_no != did->device_no)
  			return 0;
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
834
835
836
  	}
  
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) {
94a819f80   Dominik Brodowski   pcmcia: assert lo...
837
  		int ret;
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
838
839
840
841
842
  		if ((!dev->has_func_id) || (dev->func_id != did->func_id))
  			return 0;
  
  		/* if this is a pseudo-multi-function device,
  		 * we need explicit matches */
ce3f9d71b   Dominik Brodowski   pcmcia: remove un...
843
  		if (dev->socket->pcmcia_pfc)
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
844
845
846
847
848
849
850
851
  			return 0;
  		if (dev->device_no)
  			return 0;
  
  		/* also, FUNC_ID matching needs to be activated by userspace
  		 * after it has re-checked that there is no possible module
  		 * with a prod_id/manf_id/card_id match.
  		 */
94a819f80   Dominik Brodowski   pcmcia: assert lo...
852
853
854
855
856
857
858
859
  		mutex_lock(&dev->socket->ops_mutex);
  		ret = dev->allow_func_id_match;
  		mutex_unlock(&dev->socket->ops_mutex);
  
  		if (!ret) {
  			dev_dbg(&dev->dev,
  				"skipping FUNC_ID match until userspace ACK
  ");
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
860
  			return 0;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
861
  		}
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
862
  	}
ea7b38825   Dominik Brodowski   [PATCH] pcmcia: m...
863
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
864
865
  		dev_dbg(&dev->dev, "device needs a fake CIS
  ");
daa9517d9   Dominik Brodowski   [PATCH] pcmcia: r...
866
  		if (!dev->socket->fake_cis)
b1095afe6   Dominik Brodowski   pcmcia: re-start ...
867
868
  			if (pcmcia_load_firmware(dev, did->cisfile))
  				return 0;
ea7b38825   Dominik Brodowski   [PATCH] pcmcia: m...
869
  	}
f602ff7eb   Dominik Brodowski   [PATCH] pcmcia: m...
870
871
  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_ANONYMOUS) {
  		int i;
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
872
  		for (i = 0; i < 4; i++)
f602ff7eb   Dominik Brodowski   [PATCH] pcmcia: m...
873
874
875
876
877
  			if (dev->prod_id[i])
  				return 0;
  		if (dev->has_manf_id || dev->has_card_id || dev->has_func_id)
  			return 0;
  	}
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
878
879
  	return 1;
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
880
881
882
883
  static int pcmcia_bus_match(struct device *dev, struct device_driver *drv)
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
  	struct pcmcia_driver *p_drv = to_pcmcia_drv(drv);
e9fb13bfe   Joe Perches   pcmcia: Make decl...
884
  	const struct pcmcia_device_id *did = p_drv->id_table;
6179b5562   Bernhard Walle   add new_id to PCM...
885
886
887
  	struct pcmcia_dynid *dynid;
  
  	/* match dynamic devices first */
3f565232c   Dominik Brodowski   pcmcia: use mutex...
888
  	mutex_lock(&p_drv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
889
  	list_for_each_entry(dynid, &p_drv->dynids.list, node) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
890
891
  		dev_dbg(dev, "trying to match to %s
  ", drv->name);
6179b5562   Bernhard Walle   add new_id to PCM...
892
  		if (pcmcia_devmatch(p_dev, &dynid->id)) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
893
894
  			dev_dbg(dev, "matched to %s
  ", drv->name);
3f565232c   Dominik Brodowski   pcmcia: use mutex...
895
  			mutex_unlock(&p_drv->dynids.lock);
6179b5562   Bernhard Walle   add new_id to PCM...
896
897
898
  			return 1;
  		}
  	}
3f565232c   Dominik Brodowski   pcmcia: use mutex...
899
  	mutex_unlock(&p_drv->dynids.lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900

1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
901
  	while (did && did->match_flags) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
902
903
  		dev_dbg(dev, "trying to match to %s
  ", drv->name);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
904
  		if (pcmcia_devmatch(p_dev, did)) {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
905
906
  			dev_dbg(dev, "matched to %s
  ", drv->name);
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
907
  			return 1;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
908
  		}
1ad275e3e   Dominik Brodowski   [PATCH] pcmcia: d...
909
910
  		did++;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
912
  	return 0;
  }
7eff2e7a8   Kay Sievers   Driver core: chan...
913
  static int pcmcia_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
914
915
  {
  	struct pcmcia_device *p_dev;
7eff2e7a8   Kay Sievers   Driver core: chan...
916
  	int i;
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
917
918
919
920
921
922
923
924
  	u32 hash[4] = { 0, 0, 0, 0};
  
  	if (!dev)
  		return -ENODEV;
  
  	p_dev = to_pcmcia_dev(dev);
  
  	/* calculate hashes */
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
925
  	for (i = 0; i < 4; i++) {
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
926
927
928
929
  		if (!p_dev->prod_id[i])
  			continue;
  		hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i]));
  	}
7eff2e7a8   Kay Sievers   Driver core: chan...
930
  	if (add_uevent_var(env, "SOCKET_NO=%u", p_dev->socket->sock))
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
931
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
932
  	if (add_uevent_var(env, "DEVICE_NO=%02X", p_dev->device_no))
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
933
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
934
  	if (add_uevent_var(env, "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
312c004d3   Kay Sievers   [PATCH] driver co...
935
936
937
938
939
940
941
942
943
944
  			   "pa%08Xpb%08Xpc%08Xpd%08X",
  			   p_dev->has_manf_id ? p_dev->manf_id : 0,
  			   p_dev->has_card_id ? p_dev->card_id : 0,
  			   p_dev->has_func_id ? p_dev->func_id : 0,
  			   p_dev->func,
  			   p_dev->device_no,
  			   hash[0],
  			   hash[1],
  			   hash[2],
  			   hash[3]))
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
945
  		return -ENOMEM;
840c2ac5d   Dominik Brodowski   [PATCH] pcmcia: h...
946
947
  	return 0;
  }
3f8df781f   Alan Stern   PM: remove deprec...
948
  /************************ runtime PM support ***************************/
ad8d52b89   Russell King   pcmcia: ds: fix s...
949
  static int pcmcia_dev_suspend(struct device *dev);
3f8df781f   Alan Stern   PM: remove deprec...
950
951
952
953
954
  static int pcmcia_dev_resume(struct device *dev);
  
  static int runtime_suspend(struct device *dev)
  {
  	int rc;
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
955
  	device_lock(dev);
ad8d52b89   Russell King   pcmcia: ds: fix s...
956
  	rc = pcmcia_dev_suspend(dev);
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
957
  	device_unlock(dev);
3f8df781f   Alan Stern   PM: remove deprec...
958
959
  	return rc;
  }
933a838aa   Dominik Brodowski   pcmcia: make use ...
960
  static int runtime_resume(struct device *dev)
3f8df781f   Alan Stern   PM: remove deprec...
961
962
  {
  	int rc;
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
963
  	device_lock(dev);
3f8df781f   Alan Stern   PM: remove deprec...
964
  	rc = pcmcia_dev_resume(dev);
8e9394ce2   Greg Kroah-Hartman   Driver core: crea...
965
  	device_unlock(dev);
933a838aa   Dominik Brodowski   pcmcia: make use ...
966
  	return rc;
3f8df781f   Alan Stern   PM: remove deprec...
967
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968
969
970
  /************************ per-device sysfs output ***************************/
  
  #define pcmcia_device_attr(field, test, format)				\
e404e274f   Yani Ioannou   [PATCH] Driver Co...
971
  static ssize_t field##_show (struct device *dev, struct device_attribute *attr, char *buf)		\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
972
973
  {									\
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
974
  	return p_dev->test ? sprintf(buf, format, p_dev->field) : -ENODEV; \
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
975
976
  }									\
  static DEVICE_ATTR_RO(field);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
977
978
  
  #define pcmcia_device_stringattr(name, field)					\
e404e274f   Yani Ioannou   [PATCH] Driver Co...
979
  static ssize_t name##_show (struct device *dev, struct device_attribute *attr, char *buf)		\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
  {									\
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
982
983
  	return p_dev->field ? sprintf(buf, "%s
  ", p_dev->field) : -ENODEV; \
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
984
985
  }									\
  static DEVICE_ATTR_RO(name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
986

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
988
989
990
991
992
993
994
995
996
  pcmcia_device_attr(func_id, has_func_id, "0x%02x
  ");
  pcmcia_device_attr(manf_id, has_manf_id, "0x%04x
  ");
  pcmcia_device_attr(card_id, has_card_id, "0x%04x
  ");
  pcmcia_device_stringattr(prod_id1, prod_id[0]);
  pcmcia_device_stringattr(prod_id2, prod_id[1]);
  pcmcia_device_stringattr(prod_id3, prod_id[2]);
  pcmcia_device_stringattr(prod_id4, prod_id[3]);
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
  static ssize_t function_show(struct device *dev, struct device_attribute *attr,
  			     char *buf)
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
  	return p_dev->socket ? sprintf(buf, "0x%02x
  ", p_dev->func) : -ENODEV;
  }
  static DEVICE_ATTR_RO(function);
  
  static ssize_t resources_show(struct device *dev,
  			      struct device_attribute *attr, char *buf)
8f677ea07   Dominik Brodowski   pcmcia: export re...
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
  	char *str = buf;
  	int i;
  
  	for (i = 0; i < PCMCIA_NUM_RESOURCES; i++)
  		str += sprintf(str, "%pr
  ", p_dev->resource[i]);
  
  	return str - buf;
  }
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
1019
  static DEVICE_ATTR_RO(resources);
db1019ca0   Dominik Brodowski   [PATCH] pcmcia: r...
1020

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

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

3704511b2   Dominik Brodowski   [PATCH] pcmcia: f...
1048
  static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
3248ff43f   Dominik Brodowski   [PATCH] pcmcia: e...
1049
1050
1051
1052
1053
1054
  {
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
  	int i;
  	u32 hash[4] = { 0, 0, 0, 0};
  
  	/* calculate hashes */
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1055
  	for (i = 0; i < 4; i++) {
3248ff43f   Dominik Brodowski   [PATCH] pcmcia: e...
1056
1057
  		if (!p_dev->prod_id[i])
  			continue;
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1058
1059
  		hash[i] = crc32(0, p_dev->prod_id[i],
  				strlen(p_dev->prod_id[i]));
3248ff43f   Dominik Brodowski   [PATCH] pcmcia: e...
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
  	}
  	return sprintf(buf, "pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
  				"pa%08Xpb%08Xpc%08Xpd%08X
  ",
  				p_dev->has_manf_id ? p_dev->manf_id : 0,
  				p_dev->has_card_id ? p_dev->card_id : 0,
  				p_dev->has_func_id ? p_dev->func_id : 0,
  				p_dev->func, p_dev->device_no,
  				hash[0], hash[1], hash[2], hash[3]);
  }
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
1070
  static DEVICE_ATTR_RO(modalias);
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1071

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

94a819f80   Dominik Brodowski   pcmcia: assert lo...
1080
  	mutex_lock(&p_dev->socket->ops_mutex);
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1081
  	p_dev->allow_func_id_match = 1;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
1082
  	mutex_unlock(&p_dev->socket->ops_mutex);
af461fc18   Dominik Brodowski   pcmcia: delay re-...
1083
  	pcmcia_parse_uevents(p_dev->socket, PCMCIA_UEVENT_REQUERY);
a5b557789   Dominik Brodowski   [PATCH] pcmcia: a...
1084
1085
1086
  
  	return count;
  }
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
  static DEVICE_ATTR_WO(allow_func_id_match);
  
  static struct attribute *pcmcia_dev_attrs[] = {
  	&dev_attr_resources.attr,
  	&dev_attr_pm_state.attr,
  	&dev_attr_function.attr,
  	&dev_attr_func_id.attr,
  	&dev_attr_manf_id.attr,
  	&dev_attr_card_id.attr,
  	&dev_attr_prod_id1.attr,
  	&dev_attr_prod_id2.attr,
  	&dev_attr_prod_id3.attr,
  	&dev_attr_prod_id4.attr,
  	&dev_attr_modalias.attr,
  	&dev_attr_allow_func_id_match.attr,
  	NULL,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1103
  };
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
1104
  ATTRIBUTE_GROUPS(pcmcia_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1105

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

94a819f80   Dominik Brodowski   pcmcia: assert lo...
1113
1114
1115
  	mutex_lock(&p_dev->socket->ops_mutex);
  	if (p_dev->suspended) {
  		mutex_unlock(&p_dev->socket->ops_mutex);
d6b4fa6d6   David Brownell   pcmcia: stop upda...
1116
  		return 0;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
1117
1118
1119
  	}
  	p_dev->suspended = 1;
  	mutex_unlock(&p_dev->socket->ops_mutex);
d6b4fa6d6   David Brownell   pcmcia: stop upda...
1120

d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1121
1122
  	dev_dbg(dev, "suspending
  ");
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1123

8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1124
1125
  	if (dev->driver)
  		p_drv = to_pcmcia_drv(dev->driver);
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1126
1127
1128
1129
  	if (!p_drv)
  		goto out;
  
  	if (p_drv->suspend) {
8661bb5b4   Dominik Brodowski   [PATCH] pcmcia: d...
1130
  		ret = p_drv->suspend(p_dev);
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1131
  		if (ret) {
f2e6cf767   Joe Perches   pcmcia: Convert d...
1132
1133
1134
1135
  			dev_err(dev,
  				"pcmcia: device %s (driver %s) did not want to go to sleep (%d)
  ",
  				p_dev->devname, p_drv->name, ret);
94a819f80   Dominik Brodowski   pcmcia: assert lo...
1136
1137
1138
  			mutex_lock(&p_dev->socket->ops_mutex);
  			p_dev->suspended = 0;
  			mutex_unlock(&p_dev->socket->ops_mutex);
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1139
  			goto out;
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1140
  		}
8661bb5b4   Dominik Brodowski   [PATCH] pcmcia: d...
1141
  	}
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1142

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

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

94a819f80   Dominik Brodowski   pcmcia: assert lo...
1158
1159
1160
  	mutex_lock(&p_dev->socket->ops_mutex);
  	if (!p_dev->suspended) {
  		mutex_unlock(&p_dev->socket->ops_mutex);
d6b4fa6d6   David Brownell   pcmcia: stop upda...
1161
  		return 0;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
1162
1163
1164
  	}
  	p_dev->suspended = 0;
  	mutex_unlock(&p_dev->socket->ops_mutex);
d6b4fa6d6   David Brownell   pcmcia: stop upda...
1165

d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1166
1167
  	dev_dbg(dev, "resuming
  ");
d9d9ea016   Dominik Brodowski   [PATCH] pcmcia: d...
1168

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

e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
1182
1183
  	if (p_drv->resume)
  		ret = p_drv->resume(p_dev);
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1184
   out:
f6fbe01ac   Dominik Brodowski   [PATCH] pcmcia: r...
1185
  	return ret;
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1186
  }
46f533ccb   Laurent Navet   drivers: pcmcia: ...
1187
  static int pcmcia_bus_suspend_callback(struct device *dev, void *_data)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1188
1189
1190
  {
  	struct pcmcia_socket *skt = _data;
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
3f8df781f   Alan Stern   PM: remove deprec...
1191
  	if (p_dev->socket != skt || p_dev->suspended)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1192
  		return 0;
3f8df781f   Alan Stern   PM: remove deprec...
1193
  	return runtime_suspend(dev);
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1194
  }
46f533ccb   Laurent Navet   drivers: pcmcia: ...
1195
  static int pcmcia_bus_resume_callback(struct device *dev, void *_data)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1196
1197
1198
  {
  	struct pcmcia_socket *skt = _data;
  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
3f8df781f   Alan Stern   PM: remove deprec...
1199
  	if (p_dev->socket != skt || !p_dev->suspended)
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1200
  		return 0;
3f8df781f   Alan Stern   PM: remove deprec...
1201
  	runtime_resume(dev);
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1202
1203
1204
1205
1206
1207
  
  	return 0;
  }
  
  static int pcmcia_bus_resume(struct pcmcia_socket *skt)
  {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1208
1209
  	dev_dbg(&skt->dev, "resuming socket %d
  ", skt->sock);
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1210
1211
1212
1213
1214
1215
  	bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback);
  	return 0;
  }
  
  static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
  {
d50dbec3c   Dominik Brodowski   pcmcia: use dynam...
1216
1217
  	dev_dbg(&skt->dev, "suspending socket %d
  ", skt->sock);
8e9e793d6   Dominik Brodowski   [PATCH] pcmcia: m...
1218
1219
1220
1221
1222
1223
1224
  	if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt,
  			     pcmcia_bus_suspend_callback)) {
  		pcmcia_bus_resume(skt);
  		return -EIO;
  	}
  	return 0;
  }
7b24e7988   Dominik Brodowski   pcmcia: split up ...
1225
1226
1227
1228
  static int pcmcia_bus_remove(struct pcmcia_socket *skt)
  {
  	atomic_set(&skt->present, 0);
  	pcmcia_card_remove(skt, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1229

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1230
1231
1232
1233
  	mutex_lock(&skt->ops_mutex);
  	destroy_cis_cache(skt);
  	pcmcia_cleanup_irq(skt);
  	mutex_unlock(&skt->ops_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1235
1236
  	return 0;
  }
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1237

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

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

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

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1249
1250
  	return 0;
  }
1617406a7   Florin Malita   [PATCH] pcmcia: m...
1251

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

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

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

7b24e7988   Dominik Brodowski   pcmcia: split up ...
1263
1264
1265
1266
1267
1268
  	mutex_lock(&skt->ops_mutex);
  	destroy_cis_cache(skt);
  	kfree(skt->fake_cis);
  	skt->fake_cis = NULL;
  	skt->functions = 0;
  	mutex_unlock(&skt->ops_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1269

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1275

04de08161   Dominik Brodowski   pcmcia: pcmcia_de...
1276
1277
1278
1279
1280
1281
1282
  /*
   * NOTE: This is racy. There's no guarantee the card will still be
   * physically present, even if the call to this function returns
   * non-NULL. Furthermore, the device driver most likely is unbound
   * almost immediately, so the timeframe where pcmcia_dev_present
   * returns NULL is probably really really small.
   */
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
1283
  struct pcmcia_device *pcmcia_dev_present(struct pcmcia_device *_p_dev)
9940ec361   Dominik Brodowski   [PATCH] pcmcia: c...
1284
1285
1286
1287
1288
1289
1290
  {
  	struct pcmcia_device *p_dev;
  	struct pcmcia_device *ret = NULL;
  
  	p_dev = pcmcia_get_dev(_p_dev);
  	if (!p_dev)
  		return NULL;
04de08161   Dominik Brodowski   pcmcia: pcmcia_de...
1291
1292
  	if (atomic_read(&p_dev->socket->present) != 0)
  		ret = p_dev;
9940ec361   Dominik Brodowski   [PATCH] pcmcia: c...
1293

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

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

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

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

e7a480d22   Dominik Brodowski   [PATCH] pcmcia: m...
1373
  struct bus_type pcmcia_bus_type = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1374
  	.name = "pcmcia",
312c004d3   Kay Sievers   [PATCH] driver co...
1375
  	.uevent = pcmcia_bus_uevent,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1376
  	.match = pcmcia_bus_match,
b9b2f3676   Greg Kroah-Hartman   pcmcia: convert b...
1377
  	.dev_groups = pcmcia_dev_groups,
1d0baa3a1   Russell King   [PATCH] Add pcmci...
1378
1379
  	.probe = pcmcia_device_probe,
  	.remove = pcmcia_device_remove,
ad8d52b89   Russell King   pcmcia: ds: fix s...
1380
  	.pm = &pcmcia_bus_pm_ops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1381
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1382
1383
1384
1385
  
  
  static int __init init_pcmcia_bus(void)
  {
ace7d4772   Randy Dunlap   [PATCH] pcmcia/ds...
1386
  	int ret;
ace7d4772   Randy Dunlap   [PATCH] pcmcia/ds...
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
  	ret = bus_register(&pcmcia_bus_type);
  	if (ret < 0) {
  		printk(KERN_WARNING "pcmcia: bus_register error: %d
  ", ret);
  		return ret;
  	}
  	ret = class_interface_register(&pcmcia_bus_interface);
  	if (ret < 0) {
  		printk(KERN_WARNING
  			"pcmcia: class_interface_register error: %d
  ", ret);
  		bus_unregister(&pcmcia_bus_type);
  		return ret;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1401

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