]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/ide/ide-gd.c
ide: allow device drivers to specify per-device type /proc settings
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-gd.c
1 #include <linux/module.h>
2 #include <linux/types.h>
3 #include <linux/string.h>
4 #include <linux/kernel.h>
5 #include <linux/errno.h>
6 #include <linux/genhd.h>
7 #include <linux/mutex.h>
8 #include <linux/ide.h>
9 #include <linux/hdreg.h>
10
11 #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
12 #define IDE_DISK_MINORS         (1 << PARTN_BITS)
13 #else
14 #define IDE_DISK_MINORS         0
15 #endif
16
17 #include "ide-disk.h"
18
19 #define IDE_GD_VERSION  "1.18"
20
21 static DEFINE_MUTEX(ide_disk_ref_mutex);
22
23 static void ide_disk_release(struct kref *);
24
25 static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
26 {
27         struct ide_disk_obj *idkp = NULL;
28
29         mutex_lock(&ide_disk_ref_mutex);
30         idkp = ide_drv_g(disk, ide_disk_obj);
31         if (idkp) {
32                 if (ide_device_get(idkp->drive))
33                         idkp = NULL;
34                 else
35                         kref_get(&idkp->kref);
36         }
37         mutex_unlock(&ide_disk_ref_mutex);
38         return idkp;
39 }
40
41 static void ide_disk_put(struct ide_disk_obj *idkp)
42 {
43         ide_drive_t *drive = idkp->drive;
44
45         mutex_lock(&ide_disk_ref_mutex);
46         kref_put(&idkp->kref, ide_disk_release);
47         ide_device_put(drive);
48         mutex_unlock(&ide_disk_ref_mutex);
49 }
50
51 sector_t ide_gd_capacity(ide_drive_t *drive)
52 {
53         return drive->capacity64;
54 }
55
56 static int ide_gd_probe(ide_drive_t *);
57
58 static void ide_gd_remove(ide_drive_t *drive)
59 {
60         struct ide_disk_obj *idkp = drive->driver_data;
61         struct gendisk *g = idkp->disk;
62
63         ide_proc_unregister_driver(drive, idkp->driver);
64
65         del_gendisk(g);
66
67         ide_disk_flush(drive);
68
69         ide_disk_put(idkp);
70 }
71
72 static void ide_disk_release(struct kref *kref)
73 {
74         struct ide_disk_obj *idkp = to_ide_drv(kref, ide_disk_obj);
75         ide_drive_t *drive = idkp->drive;
76         struct gendisk *g = idkp->disk;
77
78         drive->driver_data = NULL;
79         g->private_data = NULL;
80         put_disk(g);
81         kfree(idkp);
82 }
83
84 /*
85  * On HPA drives the capacity needs to be
86  * reinitilized on resume otherwise the disk
87  * can not be used and a hard reset is required
88  */
89 static void ide_gd_resume(ide_drive_t *drive)
90 {
91         if (ata_id_hpa_enabled(drive->id))
92                 ide_disk_init_capacity(drive);
93 }
94
95 static void ide_gd_shutdown(ide_drive_t *drive)
96 {
97 #ifdef  CONFIG_ALPHA
98         /* On Alpha, halt(8) doesn't actually turn the machine off,
99            it puts you into the sort of firmware monitor. Typically,
100            it's used to boot another kernel image, so it's not much
101            different from reboot(8). Therefore, we don't need to
102            spin down the disk in this case, especially since Alpha
103            firmware doesn't handle disks in standby mode properly.
104            On the other hand, it's reasonably safe to turn the power
105            off when the shutdown process reaches the firmware prompt,
106            as the firmware initialization takes rather long time -
107            at least 10 seconds, which should be sufficient for
108            the disk to expire its write cache. */
109         if (system_state != SYSTEM_POWER_OFF) {
110 #else
111         if (system_state == SYSTEM_RESTART) {
112 #endif
113                 ide_disk_flush(drive);
114                 return;
115         }
116
117         printk(KERN_INFO "Shutdown: %s\n", drive->name);
118
119         drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
120 }
121
122 #ifdef CONFIG_IDE_PROC_FS
123 static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive)
124 {
125         return ide_disk_proc;
126 }
127
128 static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive)
129 {
130         return ide_disk_settings;
131 }
132 #endif
133
134 static ide_driver_t ide_gd_driver = {
135         .gen_driver = {
136                 .owner          = THIS_MODULE,
137                 .name           = "ide-disk",
138                 .bus            = &ide_bus_type,
139         },
140         .probe                  = ide_gd_probe,
141         .remove                 = ide_gd_remove,
142         .resume                 = ide_gd_resume,
143         .shutdown               = ide_gd_shutdown,
144         .version                = IDE_GD_VERSION,
145         .do_request             = ide_do_rw_disk,
146         .end_request            = ide_end_request,
147         .error                  = __ide_error,
148 #ifdef CONFIG_IDE_PROC_FS
149         .proc_entries           = ide_disk_proc_entries,
150         .proc_devsets           = ide_disk_proc_devsets,
151 #endif
152 };
153
154 static int ide_gd_open(struct inode *inode, struct file *filp)
155 {
156         struct gendisk *disk = inode->i_bdev->bd_disk;
157         struct ide_disk_obj *idkp;
158         ide_drive_t *drive;
159
160         idkp = ide_disk_get(disk);
161         if (idkp == NULL)
162                 return -ENXIO;
163
164         drive = idkp->drive;
165
166         idkp->openers++;
167
168         if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
169                 /*
170                  * Ignore the return code from door_lock,
171                  * since the open() has already succeeded,
172                  * and the door_lock is irrelevant at this point.
173                  */
174                 ide_disk_set_doorlock(drive, 1);
175                 drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
176                 check_disk_change(inode->i_bdev);
177         }
178         return 0;
179 }
180
181 static int ide_gd_release(struct inode *inode, struct file *filp)
182 {
183         struct gendisk *disk = inode->i_bdev->bd_disk;
184         struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
185         ide_drive_t *drive = idkp->drive;
186
187         if (idkp->openers == 1)
188                 ide_disk_flush(drive);
189
190         if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1)
191                 ide_disk_set_doorlock(drive, 0);
192
193         idkp->openers--;
194
195         ide_disk_put(idkp);
196
197         return 0;
198 }
199
200 static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
201 {
202         struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
203         ide_drive_t *drive = idkp->drive;
204
205         geo->heads = drive->bios_head;
206         geo->sectors = drive->bios_sect;
207         geo->cylinders = (u16)drive->bios_cyl; /* truncate */
208         return 0;
209 }
210
211 static int ide_gd_media_changed(struct gendisk *disk)
212 {
213         struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
214         ide_drive_t *drive = idkp->drive;
215         int ret;
216
217         /* do not scan partitions twice if this is a removable device */
218         if (drive->dev_flags & IDE_DFLAG_ATTACH) {
219                 drive->dev_flags &= ~IDE_DFLAG_ATTACH;
220                 return 0;
221         }
222
223         ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
224         drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
225
226         return ret;
227 }
228
229 static int ide_gd_revalidate_disk(struct gendisk *disk)
230 {
231         struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
232         set_capacity(disk, ide_gd_capacity(idkp->drive));
233         return 0;
234 }
235
236 static struct block_device_operations ide_gd_ops = {
237         .owner                  = THIS_MODULE,
238         .open                   = ide_gd_open,
239         .release                = ide_gd_release,
240         .ioctl                  = ide_disk_ioctl,
241         .getgeo                 = ide_gd_getgeo,
242         .media_changed          = ide_gd_media_changed,
243         .revalidate_disk        = ide_gd_revalidate_disk
244 };
245
246 static int ide_gd_probe(ide_drive_t *drive)
247 {
248         struct ide_disk_obj *idkp;
249         struct gendisk *g;
250
251         /* strstr("foo", "") is non-NULL */
252         if (!strstr("ide-disk", drive->driver_req))
253                 goto failed;
254
255         if (drive->media != ide_disk)
256                 goto failed;
257
258         idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
259         if (!idkp)
260                 goto failed;
261
262         g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
263         if (!g)
264                 goto out_free_idkp;
265
266         ide_init_disk(g, drive);
267
268         kref_init(&idkp->kref);
269
270         idkp->drive = drive;
271         idkp->driver = &ide_gd_driver;
272         idkp->disk = g;
273
274         g->private_data = &idkp->driver;
275
276         drive->driver_data = idkp;
277
278         ide_disk_setup(drive);
279
280         set_capacity(g, ide_gd_capacity(drive));
281
282         g->minors = IDE_DISK_MINORS;
283         g->driverfs_dev = &drive->gendev;
284         g->flags |= GENHD_FL_EXT_DEVT;
285         if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
286                 g->flags = GENHD_FL_REMOVABLE;
287         g->fops = &ide_gd_ops;
288         add_disk(g);
289         return 0;
290
291 out_free_idkp:
292         kfree(idkp);
293 failed:
294         return -ENODEV;
295 }
296
297 static int __init ide_gd_init(void)
298 {
299         return driver_register(&ide_gd_driver.gen_driver);
300 }
301
302 static void __exit ide_gd_exit(void)
303 {
304         driver_unregister(&ide_gd_driver.gen_driver);
305 }
306
307 MODULE_ALIAS("ide:*m-disk*");
308 MODULE_ALIAS("ide-disk");
309 module_init(ide_gd_init);
310 module_exit(ide_gd_exit);
311 MODULE_LICENSE("GPL");
312 MODULE_DESCRIPTION("ATA DISK Driver");