blob: 1bb99b5563930c810855d2fe2f23e83e8d619147 [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);
Bartlomiej Zolnierkiewiczcedd1202008-10-17 18:09:12 +0200228 drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
Al Virob2f21e02008-10-16 10:34:00 -0400229 check_disk_change(bdev);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200230 } else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) {
231 ret = -EBUSY;
232 goto out_put_idkp;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200233 }
234 return 0;
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200235
236out_put_idkp:
237 idkp->openers--;
238 ide_disk_put(idkp);
239 return ret;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200240}
241
Arnd Bergmann6e9624b2010-08-07 18:25:34 +0200242static int ide_gd_unlocked_open(struct block_device *bdev, fmode_t mode)
243{
244 int ret;
245
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200246 mutex_lock(&ide_gd_mutex);
Arnd Bergmann6e9624b2010-08-07 18:25:34 +0200247 ret = ide_gd_open(bdev, mode);
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200248 mutex_unlock(&ide_gd_mutex);
Arnd Bergmann6e9624b2010-08-07 18:25:34 +0200249
250 return ret;
251}
252
253
Al Virodb2a1442013-05-05 21:52:57 -0400254static void ide_gd_release(struct gendisk *disk, fmode_t mode)
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200255{
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200256 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
257 ide_drive_t *drive = idkp->drive;
258
Borislav Petkov088b1b82009-01-02 13:34:47 +0100259 ide_debug_log(IDE_DBG_FUNC, "enter");
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200260
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200261 mutex_lock(&ide_gd_mutex);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200262 if (idkp->openers == 1)
263 drive->disk_ops->flush(drive);
264
265 if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
266 drive->disk_ops->set_doorlock(drive, disk, 0);
267 drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
268 }
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200269
270 idkp->openers--;
271
272 ide_disk_put(idkp);
Arnd Bergmann2a48fc02010-06-02 14:28:52 +0200273 mutex_unlock(&ide_gd_mutex);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200274}
275
276static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
277{
278 struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
279 ide_drive_t *drive = idkp->drive;
280
281 geo->heads = drive->bios_head;
282 geo->sectors = drive->bios_sect;
283 geo->cylinders = (u16)drive->bios_cyl; /* truncate */
284 return 0;
285}
286
Tejun Heo5b03a1b2011-03-09 19:54:27 +0100287static unsigned int ide_gd_check_events(struct gendisk *disk,
288 unsigned int clearing)
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200289{
290 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
291 ide_drive_t *drive = idkp->drive;
Tejun Heo5b03a1b2011-03-09 19:54:27 +0100292 bool ret;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200293
294 /* do not scan partitions twice if this is a removable device */
295 if (drive->dev_flags & IDE_DFLAG_ATTACH) {
296 drive->dev_flags &= ~IDE_DFLAG_ATTACH;
297 return 0;
298 }
299
Tejun Heo7eec77a2011-04-21 19:43:59 +0200300 /*
301 * The following is used to force revalidation on the first open on
302 * removeable devices, and never gets reported to userland as
Martin Wilck3c12c8e2019-03-27 14:51:03 +0100303 * DISK_EVENT_FLAG_UEVENT isn't set in genhd->event_flags.
304 * This is intended as removable ide disk can't really detect
305 * MEDIA_CHANGE events.
Tejun Heo7eec77a2011-04-21 19:43:59 +0200306 */
Tejun Heo5b03a1b2011-03-09 19:54:27 +0100307 ret = drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED;
Bartlomiej Zolnierkiewiczcedd1202008-10-17 18:09:12 +0200308 drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
309
Tejun Heo5b03a1b2011-03-09 19:54:27 +0100310 return ret ? DISK_EVENT_MEDIA_CHANGE : 0;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200311}
312
Tejun Heoc3e33e02010-05-15 20:09:29 +0200313static void ide_gd_unlock_native_capacity(struct gendisk *disk)
Bartlomiej Zolnierkiewicze957b602009-06-07 13:52:52 +0200314{
315 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
316 ide_drive_t *drive = idkp->drive;
317 const struct ide_disk_ops *disk_ops = drive->disk_ops;
318
Tejun Heoc3e33e02010-05-15 20:09:29 +0200319 if (disk_ops->unlock_native_capacity)
320 disk_ops->unlock_native_capacity(drive);
Bartlomiej Zolnierkiewicze957b602009-06-07 13:52:52 +0200321}
322
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200323static int ide_gd_revalidate_disk(struct gendisk *disk)
324{
325 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
Borislav Petkov52ebb432008-11-02 21:40:10 +0100326 ide_drive_t *drive = idkp->drive;
327
Tejun Heo5b03a1b2011-03-09 19:54:27 +0100328 if (ide_gd_check_events(disk, 0))
Borislav Petkov52ebb432008-11-02 21:40:10 +0100329 drive->disk_ops->get_capacity(drive);
330
331 set_capacity(disk, ide_gd_capacity(drive));
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200332 return 0;
333}
334
Al Virob2f21e02008-10-16 10:34:00 -0400335static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode,
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200336 unsigned int cmd, unsigned long arg)
337{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200338 struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
339 ide_drive_t *drive = idkp->drive;
340
Al Virob2f21e02008-10-16 10:34:00 -0400341 return drive->disk_ops->ioctl(drive, bdev, mode, cmd, arg);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200342}
343
Arnd Bergmannc103d6e2019-03-15 17:26:56 +0100344#ifdef CONFIG_COMPAT
345static int ide_gd_compat_ioctl(struct block_device *bdev, fmode_t mode,
346 unsigned int cmd, unsigned long arg)
347{
348 struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
349 ide_drive_t *drive = idkp->drive;
350
351 if (!drive->disk_ops->compat_ioctl)
352 return -ENOIOCTLCMD;
353
354 return drive->disk_ops->compat_ioctl(drive, bdev, mode, cmd, arg);
355}
356#endif
357
Alexey Dobriyan83d5cde2009-09-21 17:01:13 -0700358static const struct block_device_operations ide_gd_ops = {
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200359 .owner = THIS_MODULE,
Arnd Bergmann6e9624b2010-08-07 18:25:34 +0200360 .open = ide_gd_unlocked_open,
Al Virob2f21e02008-10-16 10:34:00 -0400361 .release = ide_gd_release,
Arnd Bergmann8a6cfeb2010-07-08 10:18:46 +0200362 .ioctl = ide_gd_ioctl,
Arnd Bergmannc103d6e2019-03-15 17:26:56 +0100363#ifdef CONFIG_COMPAT
364 .ioctl = ide_gd_compat_ioctl,
365#endif
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200366 .getgeo = ide_gd_getgeo,
Tejun Heo5b03a1b2011-03-09 19:54:27 +0100367 .check_events = ide_gd_check_events,
Tejun Heoc3e33e02010-05-15 20:09:29 +0200368 .unlock_native_capacity = ide_gd_unlock_native_capacity,
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200369 .revalidate_disk = ide_gd_revalidate_disk
370};
371
372static int ide_gd_probe(ide_drive_t *drive)
373{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200374 const struct ide_disk_ops *disk_ops = NULL;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200375 struct ide_disk_obj *idkp;
376 struct gendisk *g;
377
378 /* strstr("foo", "") is non-NULL */
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200379 if (!strstr("ide-gd", drive->driver_req))
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200380 goto failed;
381
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200382#ifdef CONFIG_IDE_GD_ATA
383 if (drive->media == ide_disk)
384 disk_ops = &ide_ata_disk_ops;
385#endif
386#ifdef CONFIG_IDE_GD_ATAPI
387 if (drive->media == ide_floppy)
388 disk_ops = &ide_atapi_disk_ops;
389#endif
390 if (disk_ops == NULL)
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200391 goto failed;
392
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200393 if (disk_ops->check(drive, DRV_NAME) == 0) {
394 printk(KERN_ERR PFX "%s: not supported by this driver\n",
395 drive->name);
396 goto failed;
397 }
398
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200399 idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200400 if (!idkp) {
401 printk(KERN_ERR PFX "%s: can't allocate a disk structure\n",
402 drive->name);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200403 goto failed;
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200404 }
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200405
406 g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
407 if (!g)
408 goto out_free_idkp;
409
410 ide_init_disk(g, drive);
411
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +0100412 idkp->dev.parent = &drive->gendev;
413 idkp->dev.release = ide_disk_release;
Kees Cook02aa2a32013-07-03 15:04:56 -0700414 dev_set_name(&idkp->dev, "%s", dev_name(&drive->gendev));
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +0100415
416 if (device_register(&idkp->dev))
417 goto out_free_disk;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200418
419 idkp->drive = drive;
420 idkp->driver = &ide_gd_driver;
421 idkp->disk = g;
422
423 g->private_data = &idkp->driver;
424
425 drive->driver_data = idkp;
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200426 drive->debug_mask = debug_mask;
427 drive->disk_ops = disk_ops;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200428
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200429 disk_ops->setup(drive);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200430
431 set_capacity(g, ide_gd_capacity(drive));
432
433 g->minors = IDE_DISK_MINORS;
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200434 g->flags |= GENHD_FL_EXT_DEVT;
435 if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
436 g->flags = GENHD_FL_REMOVABLE;
437 g->fops = &ide_gd_ops;
Martin Wilck3c12c8e2019-03-27 14:51:03 +0100438 g->events = DISK_EVENT_MEDIA_CHANGE;
Hannes Reineckefef912b2018-09-28 08:17:19 +0200439 device_add_disk(&drive->gendev, g, NULL);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200440 return 0;
441
Bartlomiej Zolnierkiewicz8fed4362009-02-25 20:28:24 +0100442out_free_disk:
443 put_disk(g);
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200444out_free_idkp:
445 kfree(idkp);
446failed:
447 return -ENODEV;
448}
449
450static int __init ide_gd_init(void)
451{
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200452 printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "\n");
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200453 return driver_register(&ide_gd_driver.gen_driver);
454}
455
456static void __exit ide_gd_exit(void)
457{
458 driver_unregister(&ide_gd_driver.gen_driver);
459}
460
461MODULE_ALIAS("ide:*m-disk*");
462MODULE_ALIAS("ide-disk");
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200463MODULE_ALIAS("ide:*m-floppy*");
464MODULE_ALIAS("ide-floppy");
Bartlomiej Zolnierkiewicz5fef0e52008-10-17 18:09:12 +0200465module_init(ide_gd_init);
466module_exit(ide_gd_exit);
467MODULE_LICENSE("GPL");
Bartlomiej Zolnierkiewicz806f80a2008-10-17 18:09:14 +0200468MODULE_DESCRIPTION("generic ATA/ATAPI disk driver");