blob: e2b6c82586ce8bb6e57f605a1ad54a57522994d5 [file] [log] [blame]
Thomas Gleixner09c434b2019-05-19 13:08:20 +01001// SPDX-License-Identifier: GPL-2.0-only
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +02002#include <linux/module.h>
3#include <linux/types.h>
4#include <linux/string.h>
5#include <linux/kernel.h>
6#include <linux/errno.h>
7#include <linux/genhd.h>
8#include <linux/mutex.h>
9#include <linux/ide.h>
10#include <linux/hdreg.h>
Bruno Prémontb0aedb02009-04-22 20:33:41 +020011#include <linux/dmi.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090012#include <linux/slab.h>
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020013
14#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
15#define IDE_DISK_MINORS (1 << PARTN_BITS)
16#else
17#define IDE_DISK_MINORS 0
18#endif
19
20#include "ide-disk.h"
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +020021#include "ide-floppy.h"
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020022
23#define IDE_GD_VERSION "1.18"
24
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +020025/* module parameters */
Arnd Bergmann2a48fc02010-06-02 14:28:52 +020026static DEFINE_MUTEX(ide_gd_mutex);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +020027static unsigned long debug_mask;
28module_param(debug_mask, ulong, 0644);
29
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020030static DEFINE_MUTEX(ide_disk_ref_mutex);
31
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010032static void ide_disk_release(struct device *);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020033
34static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
35{
36 struct ide_disk_obj *idkp = NULL;
37
38 mutex_lock(&ide_disk_ref_mutex);
39 idkp = ide_drv_g(disk, ide_disk_obj);
40 if (idkp) {
41 if (ide_device_get(idkp->drive))
42 idkp = NULL;
43 else
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010044 get_device(&idkp->dev);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020045 }
46 mutex_unlock(&ide_disk_ref_mutex);
47 return idkp;
48}
49
50static void ide_disk_put(struct ide_disk_obj *idkp)
51{
52 ide_drive_t *drive = idkp->drive;
53
54 mutex_lock(&ide_disk_ref_mutex);
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010055 put_device(&idkp->dev);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020056 ide_device_put(drive);
57 mutex_unlock(&ide_disk_ref_mutex);
58}
59
60sector_t ide_gd_capacity(ide_drive_t *drive)
61{
62 return drive->capacity64;
63}
64
65static int ide_gd_probe(ide_drive_t *);
66
67static void ide_gd_remove(ide_drive_t *drive)
68{
69 struct ide_disk_obj *idkp = drive->driver_data;
70 struct gendisk *g = idkp->disk;
71
72 ide_proc_unregister_driver(drive, idkp->driver);
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010073 device_del(&idkp->dev);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020074 del_gendisk(g);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +020075 drive->disk_ops->flush(drive);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020076
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010077 mutex_lock(&ide_disk_ref_mutex);
78 put_device(&idkp->dev);
79 mutex_unlock(&ide_disk_ref_mutex);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020080}
81
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010082static void ide_disk_release(struct device *dev)
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020083{
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +010084 struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020085 ide_drive_t *drive = idkp->drive;
86 struct gendisk *g = idkp->disk;
87
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +020088 drive->disk_ops = NULL;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020089 drive->driver_data = NULL;
90 g->private_data = NULL;
91 put_disk(g);
92 kfree(idkp);
93}
94
95/*
96 * On HPA drives the capacity needs to be
Uwe Kleine-König421f91d2010-06-11 12:17:00 +020097 * reinitialized on resume otherwise the disk
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +020098 * can not be used and a hard reset is required
99 */
100static void ide_gd_resume(ide_drive_t *drive)
101{
102 if (ata_id_hpa_enabled(drive->id))
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200103 (void)drive->disk_ops->get_capacity(drive);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200104}
105
Bruno Prémontb0aedb02009-04-22 20:33:41 +0200106static const struct dmi_system_id ide_coldreboot_table[] = {
107 {
108 /* Acer TravelMate 66x cuts power during reboot */
109 .ident = "Acer TravelMate 660",
110 .matches = {
111 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
112 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
113 },
114 },
115
116 { } /* terminate list */
117};
118
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200119static void ide_gd_shutdown(ide_drive_t *drive)
120{
121#ifdef CONFIG_ALPHA
122 /* On Alpha, halt(8) doesn't actually turn the machine off,
123 it puts you into the sort of firmware monitor. Typically,
124 it's used to boot another kernel image, so it's not much
125 different from reboot(8). Therefore, we don't need to
126 spin down the disk in this case, especially since Alpha
127 firmware doesn't handle disks in standby mode properly.
128 On the other hand, it's reasonably safe to turn the power
129 off when the shutdown process reaches the firmware prompt,
130 as the firmware initialization takes rather long time -
131 at least 10 seconds, which should be sufficient for
132 the disk to expire its write cache. */
133 if (system_state != SYSTEM_POWER_OFF) {
134#else
Bruno Prémontb0aedb02009-04-22 20:33:41 +0200135 if (system_state == SYSTEM_RESTART &&
136 !dmi_check_system(ide_coldreboot_table)) {
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200137#endif
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200138 drive->disk_ops->flush(drive);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200139 return;
140 }
141
142 printk(KERN_INFO "Shutdown: %s\n", drive->name);
143
144 drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
145}
146
Bartlomiej Zolnierkiewicz79cb3802008-10-17 18:09:13 +0200147#ifdef CONFIG_IDE_PROC_FS
148static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive)
149{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200150 return (drive->media == ide_disk) ? ide_disk_proc : ide_floppy_proc;
Bartlomiej Zolnierkiewicz79cb3802008-10-17 18:09:13 +0200151}
152
153static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive)
154{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200155 return (drive->media == ide_disk) ? ide_disk_settings
156 : ide_floppy_settings;
Bartlomiej Zolnierkiewicz79cb3802008-10-17 18:09:13 +0200157}
158#endif
159
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200160static ide_startstop_t ide_gd_do_request(ide_drive_t *drive,
161 struct request *rq, sector_t sector)
162{
163 return drive->disk_ops->do_request(drive, rq, sector);
164}
165
Bartlomiej Zolnierkiewicz7f3c8682009-01-06 17:20:53 +0100166static struct ide_driver ide_gd_driver = {
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200167 .gen_driver = {
168 .owner = THIS_MODULE,
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200169 .name = "ide-gd",
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200170 .bus = &ide_bus_type,
171 },
172 .probe = ide_gd_probe,
173 .remove = ide_gd_remove,
174 .resume = ide_gd_resume,
175 .shutdown = ide_gd_shutdown,
176 .version = IDE_GD_VERSION,
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200177 .do_request = ide_gd_do_request,
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200178#ifdef CONFIG_IDE_PROC_FS
Bartlomiej Zolnierkiewicz79cb3802008-10-17 18:09:13 +0200179 .proc_entries = ide_disk_proc_entries,
180 .proc_devsets = ide_disk_proc_devsets,
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200181#endif
182};
183
Al Virob2f21e02008-10-16 10:34:00 -0400184static int ide_gd_open(struct block_device *bdev, fmode_t mode)
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200185{
Al Virob2f21e02008-10-16 10:34:00 -0400186 struct gendisk *disk = bdev->bd_disk;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200187 struct ide_disk_obj *idkp;
188 ide_drive_t *drive;
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200189 int ret = 0;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200190
191 idkp = ide_disk_get(disk);
192 if (idkp == NULL)
193 return -ENXIO;
194
195 drive = idkp->drive;
196
Borislav Petkov088b1b82009-01-02 13:34:47 +0100197 ide_debug_log(IDE_DBG_FUNC, "enter");
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200198
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200199 idkp->openers++;
200
201 if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200202 drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
203 /* Just in case */
204
205 ret = drive->disk_ops->init_media(drive, disk);
206
207 /*
208 * Allow O_NDELAY to open a drive without a disk, or with an
209 * unreadable disk, so that we can get the format capacity
210 * of the drive or begin the format - Sam
211 */
Al Virob2f21e02008-10-16 10:34:00 -0400212 if (ret && (mode & FMODE_NDELAY) == 0) {
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200213 ret = -EIO;
214 goto out_put_idkp;
215 }
216
Al Virob2f21e02008-10-16 10:34:00 -0400217 if ((drive->dev_flags & IDE_DFLAG_WP) && (mode & FMODE_WRITE)) {
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200218 ret = -EROFS;
219 goto out_put_idkp;
220 }
221
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200222 /*
223 * Ignore the return code from door_lock,
224 * since the open() has already succeeded,
225 * and the door_lock is irrelevant at this point.
226 */
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200227 drive->disk_ops->set_doorlock(drive, disk, 1);
Christoph Hellwigfec2cf62020-09-08 16:53:42 +0200228 if (__invalidate_device(bdev, true))
229 pr_warn("VFS: busy inodes on changed media %s\n",
230 bdev->bd_disk->disk_name);
231 drive->disk_ops->get_capacity(drive);
232 set_capacity(disk, ide_gd_capacity(drive));
Christoph Hellwig38430f02020-09-21 09:19:45 +0200233 set_bit(GD_NEED_PART_SCAN, &disk->state);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200234 } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) {
235 ret = -EBUSY;
236 goto out_put_idkp;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200237 }
238 return 0;
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200239
240out_put_idkp:
241 idkp->openers--;
242 ide_disk_put(idkp);
243 return ret;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200244}
245
Arnd Bergmann6e9624b2010-08-07 18:25:34 +0200246static int ide_gd_unlocked_open(struct block_device *bdev, fmode_t mode)
247{
248 int ret;
249
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200250 mutex_lock(&ide_gd_mutex);
Arnd Bergmann6e9624b2010-08-07 18:25:34 +0200251 ret = ide_gd_open(bdev, mode);
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200252 mutex_unlock(&ide_gd_mutex);
Arnd Bergmann6e9624b2010-08-07 18:25:34 +0200253
254 return ret;
255}
256
257
Al Virodb2a1442013-05-05 21:52:57 -0400258static void ide_gd_release(struct gendisk *disk, fmode_t mode)
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200259{
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200260 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
261 ide_drive_t *drive = idkp->drive;
262
Borislav Petkov088b1b82009-01-02 13:34:47 +0100263 ide_debug_log(IDE_DBG_FUNC, "enter");
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200264
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200265 mutex_lock(&ide_gd_mutex);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200266 if (idkp->openers == 1)
267 drive->disk_ops->flush(drive);
268
269 if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
270 drive->disk_ops->set_doorlock(drive, disk, 0);
271 drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
272 }
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200273
274 idkp->openers--;
275
276 ide_disk_put(idkp);
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200277 mutex_unlock(&ide_gd_mutex);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200278}
279
280static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
281{
282 struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
283 ide_drive_t *drive = idkp->drive;
284
285 geo->heads = drive->bios_head;
286 geo->sectors = drive->bios_sect;
287 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
288 return 0;
289}
290
Tejun Heoc3e33e02010-05-15 20:09:29 +0200291static void ide_gd_unlock_native_capacity(struct gendisk *disk)
Bartlomiej Zolnierkiewicze957b602009-06-07 13:52:52 +0200292{
293 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
294 ide_drive_t *drive = idkp->drive;
295 const struct ide_disk_ops *disk_ops = drive->disk_ops;
296
Tejun Heoc3e33e02010-05-15 20:09:29 +0200297 if (disk_ops->unlock_native_capacity)
298 disk_ops->unlock_native_capacity(drive);
Bartlomiej Zolnierkiewicze957b602009-06-07 13:52:52 +0200299}
300
Al Virob2f21e02008-10-16 10:34:00 -0400301static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode,
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200302 unsigned int cmd, unsigned long arg)
303{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200304 struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
305 ide_drive_t *drive = idkp->drive;
306
Al Virob2f21e02008-10-16 10:34:00 -0400307 return drive->disk_ops->ioctl(drive, bdev, mode, cmd, arg);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200308}
309
Arnd Bergmannc103d6e2019-03-15 17:26:56 +0100310#ifdef CONFIG_COMPAT
311static int ide_gd_compat_ioctl(struct block_device *bdev, fmode_t mode,
312 unsigned int cmd, unsigned long arg)
313{
314 struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
315 ide_drive_t *drive = idkp->drive;
316
317 if (!drive->disk_ops->compat_ioctl)
318 return -ENOIOCTLCMD;
319
320 return drive->disk_ops->compat_ioctl(drive, bdev, mode, cmd, arg);
321}
322#endif
323
Alexey Dobriyan83d5cde2009-09-21 17:01:13 -0700324static const struct block_device_operations ide_gd_ops = {
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200325 .owner = THIS_MODULE,
Arnd Bergmann6e9624b2010-08-07 18:25:34 +0200326 .open = ide_gd_unlocked_open,
Al Virob2f21e02008-10-16 10:34:00 -0400327 .release = ide_gd_release,
Arnd Bergmann8a6cfeb2010-07-08 10:18:46 +0200328 .ioctl = ide_gd_ioctl,
Arnd Bergmannc103d6e2019-03-15 17:26:56 +0100329#ifdef CONFIG_COMPAT
Adam Williamson03264dd2020-02-19 17:50:07 +0100330 .compat_ioctl = ide_gd_compat_ioctl,
Arnd Bergmannc103d6e2019-03-15 17:26:56 +0100331#endif
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200332 .getgeo = ide_gd_getgeo,
Tejun Heoc3e33e02010-05-15 20:09:29 +0200333 .unlock_native_capacity = ide_gd_unlock_native_capacity,
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200334};
335
336static int ide_gd_probe(ide_drive_t *drive)
337{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200338 const struct ide_disk_ops *disk_ops = NULL;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200339 struct ide_disk_obj *idkp;
340 struct gendisk *g;
341
342 /* strstr("foo", "") is non-NULL */
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200343 if (!strstr("ide-gd", drive->driver_req))
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200344 goto failed;
345
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200346#ifdef CONFIG_IDE_GD_ATA
347 if (drive->media == ide_disk)
348 disk_ops = &ide_ata_disk_ops;
349#endif
350#ifdef CONFIG_IDE_GD_ATAPI
351 if (drive->media == ide_floppy)
352 disk_ops = &ide_atapi_disk_ops;
353#endif
354 if (disk_ops == NULL)
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200355 goto failed;
356
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200357 if (disk_ops->check(drive, DRV_NAME) == 0) {
358 printk(KERN_ERR PFX "%s: not supported by this driver\n",
359 drive->name);
360 goto failed;
361 }
362
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200363 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200364 if (!idkp) {
365 printk(KERN_ERR PFX "%s: can't allocate a disk structure\n",
366 drive->name);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200367 goto failed;
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200368 }
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200369
370 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
371 if (!g)
372 goto out_free_idkp;
373
374 ide_init_disk(g, drive);
375
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +0100376 idkp->dev.parent = &drive->gendev;
377 idkp->dev.release = ide_disk_release;
Kees Cook02aa2a32013-07-03 15:04:56 -0700378 dev_set_name(&idkp->dev, "%s", dev_name(&drive->gendev));
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +0100379
380 if (device_register(&idkp->dev))
381 goto out_free_disk;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200382
383 idkp->drive = drive;
384 idkp->driver = &ide_gd_driver;
385 idkp->disk = g;
386
387 g->private_data = &idkp->driver;
388
389 drive->driver_data = idkp;
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200390 drive->debug_mask = debug_mask;
391 drive->disk_ops = disk_ops;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200392
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200393 disk_ops->setup(drive);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200394
395 set_capacity(g, ide_gd_capacity(drive));
396
397 g->minors = IDE_DISK_MINORS;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200398 g->flags |= GENHD_FL_EXT_DEVT;
399 if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
400 g->flags = GENHD_FL_REMOVABLE;
401 g->fops = &ide_gd_ops;
Martin Wilck3c12c8e2019-03-27 14:51:03 +0100402 g->events = DISK_EVENT_MEDIA_CHANGE;
Hannes Reineckefef912b2018-09-28 08:17:19 +0200403 device_add_disk(&drive->gendev, g, NULL);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200404 return 0;
405
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +0100406out_free_disk:
407 put_disk(g);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200408out_free_idkp:
409 kfree(idkp);
410failed:
411 return -ENODEV;
412}
413
414static int __init ide_gd_init(void)
415{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200416 printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "\n");
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200417 return driver_register(&ide_gd_driver.gen_driver);
418}
419
420static void __exit ide_gd_exit(void)
421{
422 driver_unregister(&ide_gd_driver.gen_driver);
423}
424
425MODULE_ALIAS("ide:*m-disk*");
426MODULE_ALIAS("ide-disk");
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200427MODULE_ALIAS("ide:*m-floppy*");
428MODULE_ALIAS("ide-floppy");
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200429module_init(ide_gd_init);
430module_exit(ide_gd_exit);
431MODULE_LICENSE("GPL");
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200432MODULE_DESCRIPTION("generic ATA/ATAPI disk driver");