]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/ide/ide-gd.c
ide-disk: use IDE_DFLAG_MEDIA_CHANGED
[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 static ide_driver_t ide_gd_driver = {
123         .gen_driver = {
124                 .owner          = THIS_MODULE,
125                 .name           = "ide-disk",
126                 .bus            = &ide_bus_type,
127         },
128         .probe                  = ide_gd_probe,
129         .remove                 = ide_gd_remove,
130         .resume                 = ide_gd_resume,
131         .shutdown               = ide_gd_shutdown,
132         .version                = IDE_GD_VERSION,
133         .do_request             = ide_do_rw_disk,
134         .end_request            = ide_end_request,
135         .error                  = __ide_error,
136 #ifdef CONFIG_IDE_PROC_FS
137         .proc                   = ide_disk_proc,
138         .settings               = ide_disk_settings,
139 #endif
140 };
141
142 static int ide_gd_open(struct inode *inode, struct file *filp)
143 {
144         struct gendisk *disk = inode->i_bdev->bd_disk;
145         struct ide_disk_obj *idkp;
146         ide_drive_t *drive;
147
148         idkp = ide_disk_get(disk);
149         if (idkp == NULL)
150                 return -ENXIO;
151
152         drive = idkp->drive;
153
154         idkp->openers++;
155
156         if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
157                 /*
158                  * Ignore the return code from door_lock,
159                  * since the open() has already succeeded,
160                  * and the door_lock is irrelevant at this point.
161                  */
162                 ide_disk_set_doorlock(drive, 1);
163                 drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
164                 check_disk_change(inode->i_bdev);
165         }
166         return 0;
167 }
168
169 static int ide_gd_release(struct inode *inode, struct file *filp)
170 {
171         struct gendisk *disk = inode->i_bdev->bd_disk;
172         struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
173         ide_drive_t *drive = idkp->drive;
174
175         if (idkp->openers == 1)
176                 ide_disk_flush(drive);
177
178         if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1)
179                 ide_disk_set_doorlock(drive, 0);
180
181         idkp->openers--;
182
183         ide_disk_put(idkp);
184
185         return 0;
186 }
187
188 static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
189 {
190         struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
191         ide_drive_t *drive = idkp->drive;
192
193         geo->heads = drive->bios_head;
194         geo->sectors = drive->bios_sect;
195         geo->cylinders = (u16)drive->bios_cyl; /* truncate */
196         return 0;
197 }
198
199 static int ide_gd_media_changed(struct gendisk *disk)
200 {
201         struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
202         ide_drive_t *drive = idkp->drive;
203         int ret;
204
205         /* do not scan partitions twice if this is a removable device */
206         if (drive->dev_flags & IDE_DFLAG_ATTACH) {
207                 drive->dev_flags &= ~IDE_DFLAG_ATTACH;
208                 return 0;
209         }
210
211         ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
212         drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
213
214         return ret;
215 }
216
217 static int ide_gd_revalidate_disk(struct gendisk *disk)
218 {
219         struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
220         set_capacity(disk, ide_gd_capacity(idkp->drive));
221         return 0;
222 }
223
224 static struct block_device_operations ide_gd_ops = {
225         .owner                  = THIS_MODULE,
226         .open                   = ide_gd_open,
227         .release                = ide_gd_release,
228         .ioctl                  = ide_disk_ioctl,
229         .getgeo                 = ide_gd_getgeo,
230         .media_changed          = ide_gd_media_changed,
231         .revalidate_disk        = ide_gd_revalidate_disk
232 };
233
234 static int ide_gd_probe(ide_drive_t *drive)
235 {
236         struct ide_disk_obj *idkp;
237         struct gendisk *g;
238
239         /* strstr("foo", "") is non-NULL */
240         if (!strstr("ide-disk", drive->driver_req))
241                 goto failed;
242
243         if (drive->media != ide_disk)
244                 goto failed;
245
246         idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
247         if (!idkp)
248                 goto failed;
249
250         g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
251         if (!g)
252                 goto out_free_idkp;
253
254         ide_init_disk(g, drive);
255
256         kref_init(&idkp->kref);
257
258         idkp->drive = drive;
259         idkp->driver = &ide_gd_driver;
260         idkp->disk = g;
261
262         g->private_data = &idkp->driver;
263
264         drive->driver_data = idkp;
265
266         ide_disk_setup(drive);
267
268         set_capacity(g, ide_gd_capacity(drive));
269
270         g->minors = IDE_DISK_MINORS;
271         g->driverfs_dev = &drive->gendev;
272         g->flags |= GENHD_FL_EXT_DEVT;
273         if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
274                 g->flags = GENHD_FL_REMOVABLE;
275         g->fops = &ide_gd_ops;
276         add_disk(g);
277         return 0;
278
279 out_free_idkp:
280         kfree(idkp);
281 failed:
282         return -ENODEV;
283 }
284
285 static int __init ide_gd_init(void)
286 {
287         return driver_register(&ide_gd_driver.gen_driver);
288 }
289
290 static void __exit ide_gd_exit(void)
291 {
292         driver_unregister(&ide_gd_driver.gen_driver);
293 }
294
295 MODULE_ALIAS("ide:*m-disk*");
296 MODULE_ALIAS("ide-disk");
297 module_init(ide_gd_init);
298 module_exit(ide_gd_exit);
299 MODULE_LICENSE("GPL");
300 MODULE_DESCRIPTION("ATA DISK Driver");