aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/smsc47m1.c
Commit message (Expand)AuthorAge
* hwmon: (smsc47m1) Fix section mismatchJeff Mahoney2010-01-25
* hwmon: (smsc47m1) Enable device if neededJean Delvare2009-12-16
* hwmon: (smsc47m1) Fail module loading on errorJean Delvare2009-12-16
* hwmon: (smsc47m1) Only request I/O ports we really useJean Delvare2009-12-16
* hwmon: Include <linux/io.h> instead of <asm/io.h>H Hartley Sweeten2009-09-15
* hwmon: (smsc47m1) Differentiate between LPC47M233 and LPC47M292Jean Delvare2009-07-28
* hwmon: Check for ACPI resource conflictsJean Delvare2009-01-07
* hwmon: (smsc47m1) Add individual alarm filesJean Delvare2008-02-17
* hwmon: Let the user override the detected Super-I/O device IDJean Delvare2008-02-07
* hwmon: Convert from class_device to deviceTony Jones2007-10-09
* hwmon: (smsc47m1) No confusing debugging messagesJean Delvare2007-10-09
* hwmon: (smsc47m1) restore missing name attributeJean Delvare2007-08-12
* hwmon: Add missing __devexit tags in various driversJean Delvare2007-07-30
* hwmon: Fix a potential race condition on unloadJean Delvare2007-07-19
* hwmon: Use platform_device_add_data()Jean Delvare2007-07-19
* hwmon/smsc47m1: Use dynamic sysfs callbacksJean Delvare2007-05-08
* hwmon/smsc47m1: Use DRVNAME consistentlyJean Delvare2007-05-08
* hwmon/smsc47m1: Convert to a platform driverJean Delvare2007-05-08
* hwmon/smsc47m1: Get rid of a useless mutexJean Delvare2007-05-08
* hwmon/smsc47m1: Add support for the LPC47M292Jean Delvare2007-05-08
* smsc47m1: List the SMSC LPC47M112 as supportedJean Delvare2006-10-18
* hwmon: Fix unchecked return status, SMSC chipsJean Delvare2006-09-28
* smsc47m1: dev_warn fixJean Delvare2006-09-28
* i2c-isa: Restore driver ownerJean Delvare2006-09-26
* spelling fixesAndreas Mohr2006-06-26
* [PATCH] hwmon: Semaphore to mutex conversionsIngo Molnar2006-03-23
* [PATCH] I2C: Remove .owner setting from i2c_driver as it's no longer neededGreg Kroah-Hartman2006-01-06
* [PATCH] i2c: Drop i2c_driver.{owner,name}, 3 of 11Laurent Riffard2006-01-06
* [PATCH] hwmon: smsc47m1 documentation updateJean Delvare2005-10-28
* [PATCH] hwmon: kzalloc conversionDeepak Saxena2005-10-28
* [PATCH] hwmon: Update smsc47m1 head commentJean Delvare2005-09-09
* [PATCH] hwmon: hwmon vs i2c, second round (06/11)Jean Delvare2005-09-05
* [PATCH] hwmon: tag super-i/o find functions __initJean Delvare2005-09-05
* [PATCH] I2C: refactor message in i2c_detach_clientJean Delvare2005-09-05
* [PATCH] I2C: Separate non-i2c hwmon drivers from i2c-core (5/9)Jean Delvare2005-09-05
* [PATCH] I2C: Separate non-i2c hwmon drivers from i2c-core (3/9)Jean Delvare2005-09-05
* [PATCH] I2C hwmon: add hwmon sysfs class to driversMark M. Hoffman2005-09-05
* [PATCH] drivers/hwmon/*: kfree() correct pointersAlexey Dobriyan2005-08-26
* [PATCH] I2C: Move hwmon drivers (2/3)Jean Delvare2005-07-11
s='alt'>
ee959b00c335
d569d5bb3fd9

cb6b7f40630f

d569d5bb3fd9



















ee959b00c335
d569d5bb3fd9












ee959b00c335
d569d5bb3fd9
ee959b00c335
d569d5bb3fd9
ee959b00c335
d569d5bb3fd9
cb6b7f40630f


ee959b00c335
d569d5bb3fd9























ee959b00c335
d569d5bb3fd9



ee959b00c335
d569d5bb3fd9
cb6b7f40630f


ee959b00c335
d569d5bb3fd9
cb6b7f40630f
d569d5bb3fd9












ee959b00c335
d569d5bb3fd9



ee959b00c335
d569d5bb3fd9
ee959b00c335

d569d5bb3fd9
ee959b00c335
d569d5bb3fd9






ee959b00c335


d569d5bb3fd9





ee959b00c335
d569d5bb3fd9






ee959b00c335

d569d5bb3fd9

















ee959b00c335

d569d5bb3fd9








ee959b00c335


d569d5bb3fd9









ee959b00c335

d569d5bb3fd9








ee959b00c335


d569d5bb3fd9



















ee959b00c335

d569d5bb3fd9








ee959b00c335


d569d5bb3fd9









ee959b00c335

d569d5bb3fd9








ee959b00c335


d569d5bb3fd9









ee959b00c335

d569d5bb3fd9






cb6b7f40630f
















d569d5bb3fd9

cb6b7f40630f






d569d5bb3fd9








d569d5bb3fd9

d569d5bb3fd9



d569d5bb3fd9








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
































                                                                               







                                                                 
                                                   


                                                           
                                      


                                                          

                                                


































































                                                                           

                                            
                      

                                                             












                                                    
                                      





















                                                                     
                                                                    


                                                     
                                       


                                        

































                                                                                
                                                  


                                                                  
                                 


                    
                                                           
 

                                                                       



                                             
                                

 

                                                  



















                                                                            
                            












                                         
                                               
                 
                                                                
            
                                                                  
 


                                                    
                                    























                                                                      
                                         



                                                   
                                           
 


                                             
                              
                                    
                                         












                                                                         
                                         



                                                   
                                           
 

                                
                         
                                       






                                           


                                                                       





                                                                  
                                                    






                                                                     

                                                    

















                                                            

                                                                            








                                                                          


                                                                 









                                                                          

                                                                            








                                                                          


                                                                  



















                                                                          

                                                                             








                                                                          


                                                                  









                                                                          

                                                                             








                                                                          


                                                                  









                                                                          

                                                                           






                                                                         
















                                                                   

  






                                                     








                                               

                 



                                       








                                           
/*
 * Enclosure Services
 *
 * Copyright (C) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
 *
**-----------------------------------------------------------------------------
**
**  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.
**
**  This program is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this program; if not, write to the Free Software
**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
*/
#include <linux/device.h>
#include <linux/enclosure.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>

static LIST_HEAD(container_list);
static DEFINE_MUTEX(container_list_lock);
static struct class enclosure_class;

/**
 * enclosure_find - find an enclosure given a device
 * @dev:	the device to find for
 *
 * Looks through the list of registered enclosures to see
 * if it can find a match for a device.  Returns NULL if no
 * enclosure is found. Obtains a reference to the enclosure class
 * device which must be released with device_put().
 */
struct enclosure_device *enclosure_find(struct device *dev)
{
	struct enclosure_device *edev;

	mutex_lock(&container_list_lock);
	list_for_each_entry(edev, &container_list, node) {
		if (edev->edev.parent == dev) {
			get_device(&edev->edev);
			mutex_unlock(&container_list_lock);
			return edev;
		}
	}
	mutex_unlock(&container_list_lock);

	return NULL;
}
EXPORT_SYMBOL_GPL(enclosure_find);

/**
 * enclosure_for_each_device - calls a function for each enclosure
 * @fn:		the function to call
 * @data:	the data to pass to each call
 *
 * Loops over all the enclosures calling the function.
 *
 * Note, this function uses a mutex which will be held across calls to
 * @fn, so it must have non atomic context, and @fn may (although it
 * should not) sleep or otherwise cause the mutex to be held for
 * indefinite periods
 */
int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *),
			      void *data)
{
	int error = 0;
	struct enclosure_device *edev;

	mutex_lock(&container_list_lock);
	list_for_each_entry(edev, &container_list, node) {
		error = fn(edev, data);
		if (error)
			break;
	}
	mutex_unlock(&container_list_lock);

	return error;
}
EXPORT_SYMBOL_GPL(enclosure_for_each_device);

/**
 * enclosure_register - register device as an enclosure
 *
 * @dev:	device containing the enclosure
 * @components:	number of components in the enclosure
 *
 * This sets up the device for being an enclosure.  Note that @dev does
 * not have to be a dedicated enclosure device.  It may be some other type
 * of device that additionally responds to enclosure services
 */
struct enclosure_device *
enclosure_register(struct device *dev, const char *name, int components,
		   struct enclosure_component_callbacks *cb)
{
	struct enclosure_device *edev =
		kzalloc(sizeof(struct enclosure_device) +
			sizeof(struct enclosure_component)*components,
			GFP_KERNEL);
	int err, i;

	BUG_ON(!cb);

	if (!edev)
		return ERR_PTR(-ENOMEM);

	edev->components = components;

	edev->edev.class = &enclosure_class;
	edev->edev.parent = get_device(dev);
	edev->cb = cb;
	snprintf(edev->edev.bus_id, BUS_ID_SIZE, "%s", name);
	err = device_register(&edev->edev);
	if (err)
		goto err;

	for (i = 0; i < components; i++)
		edev->component[i].number = -1;

	mutex_lock(&container_list_lock);
	list_add_tail(&edev->node, &container_list);
	mutex_unlock(&container_list_lock);

	return edev;

 err:
	put_device(edev->edev.parent);
	kfree(edev);
	return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(enclosure_register);

static struct enclosure_component_callbacks enclosure_null_callbacks;

/**
 * enclosure_unregister - remove an enclosure
 *
 * @edev:	the registered enclosure to remove;
 */
void enclosure_unregister(struct enclosure_device *edev)
{
	int i;

	mutex_lock(&container_list_lock);
	list_del(&edev->node);
	mutex_unlock(&container_list_lock);

	for (i = 0; i < edev->components; i++)
		if (edev->component[i].number != -1)
			device_unregister(&edev->component[i].cdev);

	/* prevent any callbacks into service user */
	edev->cb = &enclosure_null_callbacks;
	device_unregister(&edev->edev);
}
EXPORT_SYMBOL_GPL(enclosure_unregister);

#define ENCLOSURE_NAME_SIZE	64

static void enclosure_link_name(struct enclosure_component *cdev, char *name)
{
	strcpy(name, "enclosure_device:");
	strcat(name, cdev->cdev.bus_id);
}

static void enclosure_remove_links(struct enclosure_component *cdev)
{
	char name[ENCLOSURE_NAME_SIZE];

	enclosure_link_name(cdev, name);
	sysfs_remove_link(&cdev->dev->kobj, name);
	sysfs_remove_link(&cdev->cdev.kobj, "device");
}

static int enclosure_add_links(struct enclosure_component *cdev)
{
	int error;
	char name[ENCLOSURE_NAME_SIZE];

	error = sysfs_create_link(&cdev->cdev.kobj, &cdev->dev->kobj, "device");
	if (error)
		return error;

	enclosure_link_name(cdev, name);
	error = sysfs_create_link(&cdev->dev->kobj, &cdev->cdev.kobj, name);
	if (error)
		sysfs_remove_link(&cdev->cdev.kobj, "device");

	return error;
}

static void enclosure_release(struct device *cdev)
{
	struct enclosure_device *edev = to_enclosure_device(cdev);

	put_device(cdev->parent);
	kfree(edev);
}

static void enclosure_component_release(struct device *dev)
{
	struct enclosure_component *cdev = to_enclosure_component(dev);

	if (cdev->dev) {
		enclosure_remove_links(cdev);
		put_device(cdev->dev);
	}
	put_device(dev->parent);
}

static struct attribute_group *enclosure_groups[];

/**
 * enclosure_component_register - add a particular component to an enclosure
 * @edev:	the enclosure to add the component
 * @num:	the device number
 * @type:	the type of component being added
 * @name:	an optional name to appear in sysfs (leave NULL if none)
 *
 * Registers the component.  The name is optional for enclosures that
 * give their components a unique name.  If not, leave the field NULL
 * and a name will be assigned.
 *
 * Returns a pointer to the enclosure component or an error.
 */
struct enclosure_component *
enclosure_component_register(struct enclosure_device *edev,
			     unsigned int number,
			     enum enclosure_component_type type,
			     const char *name)
{
	struct enclosure_component *ecomp;
	struct device *cdev;
	int err;

	if (number >= edev->components)
		return ERR_PTR(-EINVAL);

	ecomp = &edev->component[number];

	if (ecomp->number != -1)
		return ERR_PTR(-EINVAL);

	ecomp->type = type;
	ecomp->number = number;
	cdev = &ecomp->cdev;
	cdev->parent = get_device(&edev->edev);
	if (name)
		snprintf(cdev->bus_id, BUS_ID_SIZE, "%s", name);
	else
		snprintf(cdev->bus_id, BUS_ID_SIZE, "%u", number);

	cdev->release = enclosure_component_release;
	cdev->groups = enclosure_groups;

	err = device_register(cdev);
	if (err)
		ERR_PTR(err);

	return ecomp;
}
EXPORT_SYMBOL_GPL(enclosure_component_register);

/**
 * enclosure_add_device - add a device as being part of an enclosure
 * @edev:	the enclosure device being added to.
 * @num:	the number of the component
 * @dev:	the device being added
 *
 * Declares a real device to reside in slot (or identifier) @num of an
 * enclosure.  This will cause the relevant sysfs links to appear.
 * This function may also be used to change a device associated with
 * an enclosure without having to call enclosure_remove_device() in
 * between.
 *
 * Returns zero on success or an error.
 */
int enclosure_add_device(struct enclosure_device *edev, int component,
			 struct device *dev)
{
	struct enclosure_component *cdev;

	if (!edev || component >= edev->components)
		return -EINVAL;

	cdev = &edev->component[component];

	if (cdev->dev)
		enclosure_remove_links(cdev);

	put_device(cdev->dev);
	cdev->dev = get_device(dev);
	return enclosure_add_links(cdev);
}
EXPORT_SYMBOL_GPL(enclosure_add_device);

/**
 * enclosure_remove_device - remove a device from an enclosure
 * @edev:	the enclosure device
 * @num:	the number of the component to remove
 *
 * Returns zero on success or an error.
 *
 */
int enclosure_remove_device(struct enclosure_device *edev, int component)
{
	struct enclosure_component *cdev;

	if (!edev || component >= edev->components)
		return -EINVAL;

	cdev = &edev->component[component];

	device_del(&cdev->cdev);
	put_device(cdev->dev);
	cdev->dev = NULL;
	return device_add(&cdev->cdev);
}
EXPORT_SYMBOL_GPL(enclosure_remove_device);

/*
 * sysfs pieces below
 */

static ssize_t enclosure_show_components(struct device *cdev,
					 struct device_attribute *attr,
					 char *buf)
{
	struct enclosure_device *edev = to_enclosure_device(cdev);

	return snprintf(buf, 40, "%d\n", edev->components);
}

static struct device_attribute enclosure_attrs[] = {
	__ATTR(components, S_IRUGO, enclosure_show_components, NULL),
	__ATTR_NULL
};

static struct class enclosure_class = {
	.name			= "enclosure",
	.owner			= THIS_MODULE,
	.dev_release		= enclosure_release,
	.dev_attrs		= enclosure_attrs,
};

static const char *const enclosure_status [] = {
	[ENCLOSURE_STATUS_UNSUPPORTED] = "unsupported",
	[ENCLOSURE_STATUS_OK] = "OK",
	[ENCLOSURE_STATUS_CRITICAL] = "critical",
	[ENCLOSURE_STATUS_NON_CRITICAL] = "non-critical",
	[ENCLOSURE_STATUS_UNRECOVERABLE] = "unrecoverable",
	[ENCLOSURE_STATUS_NOT_INSTALLED] = "not installed",
	[ENCLOSURE_STATUS_UNKNOWN] = "unknown",
	[ENCLOSURE_STATUS_UNAVAILABLE] = "unavailable",
};

static const char *const enclosure_type [] = {
	[ENCLOSURE_COMPONENT_DEVICE] = "device",
	[ENCLOSURE_COMPONENT_ARRAY_DEVICE] = "array device",
};

static ssize_t get_component_fault(struct device *cdev,
				   struct device_attribute *attr, char *buf)
{
	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
	struct enclosure_component *ecomp = to_enclosure_component(cdev);

	if (edev->cb->get_fault)
		edev->cb->get_fault(edev, ecomp);
	return snprintf(buf, 40, "%d\n", ecomp->fault);
}

static ssize_t set_component_fault(struct device *cdev,
				   struct device_attribute *attr,
				   const char *buf, size_t count)
{
	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
	struct enclosure_component *ecomp = to_enclosure_component(cdev);
	int val = simple_strtoul(buf, NULL, 0);

	if (edev->cb->set_fault)
		edev->cb->set_fault(edev, ecomp, val);
	return count;
}

static ssize_t get_component_status(struct device *cdev,
				    struct device_attribute *attr,char *buf)
{
	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
	struct enclosure_component *ecomp = to_enclosure_component(cdev);

	if (edev->cb->get_status)
		edev->cb->get_status(edev, ecomp);
	return snprintf(buf, 40, "%s\n", enclosure_status[ecomp->status]);
}

static ssize_t set_component_status(struct device *cdev,
				    struct device_attribute *attr,
				    const char *buf, size_t count)
{
	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
	struct enclosure_component *ecomp = to_enclosure_component(cdev);
	int i;

	for (i = 0; enclosure_status[i]; i++) {
		if (strncmp(buf, enclosure_status[i],
			    strlen(enclosure_status[i])) == 0 &&
		    (buf[strlen(enclosure_status[i])] == '\n' ||
		     buf[strlen(enclosure_status[i])] == '\0'))
			break;
	}

	if (enclosure_status[i] && edev->cb->set_status) {
		edev->cb->set_status(edev, ecomp, i);
		return count;
	} else
		return -EINVAL;
}

static ssize_t get_component_active(struct device *cdev,
				    struct device_attribute *attr, char *buf)
{
	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
	struct enclosure_component *ecomp = to_enclosure_component(cdev);

	if (edev->cb->get_active)
		edev->cb->get_active(edev, ecomp);
	return snprintf(buf, 40, "%d\n", ecomp->active);
}

static ssize_t set_component_active(struct device *cdev,
				    struct device_attribute *attr,
				    const char *buf, size_t count)
{
	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
	struct enclosure_component *ecomp = to_enclosure_component(cdev);
	int val = simple_strtoul(buf, NULL, 0);

	if (edev->cb->set_active)
		edev->cb->set_active(edev, ecomp, val);
	return count;
}

static ssize_t get_component_locate(struct device *cdev,
				    struct device_attribute *attr, char *buf)
{
	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
	struct enclosure_component *ecomp = to_enclosure_component(cdev);

	if (edev->cb->get_locate)
		edev->cb->get_locate(edev, ecomp);
	return snprintf(buf, 40, "%d\n", ecomp->locate);
}

static ssize_t set_component_locate(struct device *cdev,
				    struct device_attribute *attr,
				    const char *buf, size_t count)
{
	struct enclosure_device *edev = to_enclosure_device(cdev->parent);
	struct enclosure_component *ecomp = to_enclosure_component(cdev);
	int val = simple_strtoul(buf, NULL, 0);

	if (edev->cb->set_locate)
		edev->cb->set_locate(edev, ecomp, val);
	return count;
}

static ssize_t get_component_type(struct device *cdev,
				  struct device_attribute *attr, char *buf)
{
	struct enclosure_component *ecomp = to_enclosure_component(cdev);

	return snprintf(buf, 40, "%s\n", enclosure_type[ecomp->type]);
}


static DEVICE_ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault,
		    set_component_fault);
static DEVICE_ATTR(status, S_IRUGO | S_IWUSR, get_component_status,
		   set_component_status);
static DEVICE_ATTR(active, S_IRUGO | S_IWUSR, get_component_active,
		   set_component_active);
static DEVICE_ATTR(locate, S_IRUGO | S_IWUSR, get_component_locate,
		   set_component_locate);
static DEVICE_ATTR(type, S_IRUGO, get_component_type, NULL);

static struct attribute *enclosure_component_attrs[] = {
	&dev_attr_fault.attr,
	&dev_attr_status.attr,
	&dev_attr_active.attr,
	&dev_attr_locate.attr,
	&dev_attr_type.attr,
	NULL
};

static struct attribute_group enclosure_group = {
	.attrs = enclosure_component_attrs,
};

static struct attribute_group *enclosure_groups[] = {
	&enclosure_group,
	NULL
};

static int __init enclosure_init(void)
{
	int err;

	err = class_register(&enclosure_class);
	if (err)
		return err;

	return 0;
}

static void __exit enclosure_exit(void)
{
	class_unregister(&enclosure_class);
}

module_init(enclosure_init);
module_exit(enclosure_exit);

MODULE_AUTHOR("James Bottomley");
MODULE_DESCRIPTION("Enclosure Services");
MODULE_LICENSE("GPL v2");