Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/ide/ide-gd.c
15109 views
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
#include <linux/dmi.h>
11
#include <linux/slab.h>
12
13
#if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
14
#define IDE_DISK_MINORS (1 << PARTN_BITS)
15
#else
16
#define IDE_DISK_MINORS 0
17
#endif
18
19
#include "ide-disk.h"
20
#include "ide-floppy.h"
21
22
#define IDE_GD_VERSION "1.18"
23
24
/* module parameters */
25
static DEFINE_MUTEX(ide_gd_mutex);
26
static unsigned long debug_mask;
27
module_param(debug_mask, ulong, 0644);
28
29
static DEFINE_MUTEX(ide_disk_ref_mutex);
30
31
static void ide_disk_release(struct device *);
32
33
static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
34
{
35
struct ide_disk_obj *idkp = NULL;
36
37
mutex_lock(&ide_disk_ref_mutex);
38
idkp = ide_drv_g(disk, ide_disk_obj);
39
if (idkp) {
40
if (ide_device_get(idkp->drive))
41
idkp = NULL;
42
else
43
get_device(&idkp->dev);
44
}
45
mutex_unlock(&ide_disk_ref_mutex);
46
return idkp;
47
}
48
49
static void ide_disk_put(struct ide_disk_obj *idkp)
50
{
51
ide_drive_t *drive = idkp->drive;
52
53
mutex_lock(&ide_disk_ref_mutex);
54
put_device(&idkp->dev);
55
ide_device_put(drive);
56
mutex_unlock(&ide_disk_ref_mutex);
57
}
58
59
sector_t ide_gd_capacity(ide_drive_t *drive)
60
{
61
return drive->capacity64;
62
}
63
64
static int ide_gd_probe(ide_drive_t *);
65
66
static void ide_gd_remove(ide_drive_t *drive)
67
{
68
struct ide_disk_obj *idkp = drive->driver_data;
69
struct gendisk *g = idkp->disk;
70
71
ide_proc_unregister_driver(drive, idkp->driver);
72
device_del(&idkp->dev);
73
del_gendisk(g);
74
drive->disk_ops->flush(drive);
75
76
mutex_lock(&ide_disk_ref_mutex);
77
put_device(&idkp->dev);
78
mutex_unlock(&ide_disk_ref_mutex);
79
}
80
81
static void ide_disk_release(struct device *dev)
82
{
83
struct ide_disk_obj *idkp = to_ide_drv(dev, ide_disk_obj);
84
ide_drive_t *drive = idkp->drive;
85
struct gendisk *g = idkp->disk;
86
87
drive->disk_ops = NULL;
88
drive->driver_data = NULL;
89
g->private_data = NULL;
90
put_disk(g);
91
kfree(idkp);
92
}
93
94
/*
95
* On HPA drives the capacity needs to be
96
* reinitialized on resume otherwise the disk
97
* can not be used and a hard reset is required
98
*/
99
static void ide_gd_resume(ide_drive_t *drive)
100
{
101
if (ata_id_hpa_enabled(drive->id))
102
(void)drive->disk_ops->get_capacity(drive);
103
}
104
105
static const struct dmi_system_id ide_coldreboot_table[] = {
106
{
107
/* Acer TravelMate 66x cuts power during reboot */
108
.ident = "Acer TravelMate 660",
109
.matches = {
110
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
111
DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
112
},
113
},
114
115
{ } /* terminate list */
116
};
117
118
static void ide_gd_shutdown(ide_drive_t *drive)
119
{
120
#ifdef CONFIG_ALPHA
121
/* On Alpha, halt(8) doesn't actually turn the machine off,
122
it puts you into the sort of firmware monitor. Typically,
123
it's used to boot another kernel image, so it's not much
124
different from reboot(8). Therefore, we don't need to
125
spin down the disk in this case, especially since Alpha
126
firmware doesn't handle disks in standby mode properly.
127
On the other hand, it's reasonably safe to turn the power
128
off when the shutdown process reaches the firmware prompt,
129
as the firmware initialization takes rather long time -
130
at least 10 seconds, which should be sufficient for
131
the disk to expire its write cache. */
132
if (system_state != SYSTEM_POWER_OFF) {
133
#else
134
if (system_state == SYSTEM_RESTART &&
135
!dmi_check_system(ide_coldreboot_table)) {
136
#endif
137
drive->disk_ops->flush(drive);
138
return;
139
}
140
141
printk(KERN_INFO "Shutdown: %s\n", drive->name);
142
143
drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
144
}
145
146
#ifdef CONFIG_IDE_PROC_FS
147
static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive)
148
{
149
return (drive->media == ide_disk) ? ide_disk_proc : ide_floppy_proc;
150
}
151
152
static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive)
153
{
154
return (drive->media == ide_disk) ? ide_disk_settings
155
: ide_floppy_settings;
156
}
157
#endif
158
159
static ide_startstop_t ide_gd_do_request(ide_drive_t *drive,
160
struct request *rq, sector_t sector)
161
{
162
return drive->disk_ops->do_request(drive, rq, sector);
163
}
164
165
static struct ide_driver ide_gd_driver = {
166
.gen_driver = {
167
.owner = THIS_MODULE,
168
.name = "ide-gd",
169
.bus = &ide_bus_type,
170
},
171
.probe = ide_gd_probe,
172
.remove = ide_gd_remove,
173
.resume = ide_gd_resume,
174
.shutdown = ide_gd_shutdown,
175
.version = IDE_GD_VERSION,
176
.do_request = ide_gd_do_request,
177
#ifdef CONFIG_IDE_PROC_FS
178
.proc_entries = ide_disk_proc_entries,
179
.proc_devsets = ide_disk_proc_devsets,
180
#endif
181
};
182
183
static int ide_gd_open(struct block_device *bdev, fmode_t mode)
184
{
185
struct gendisk *disk = bdev->bd_disk;
186
struct ide_disk_obj *idkp;
187
ide_drive_t *drive;
188
int ret = 0;
189
190
idkp = ide_disk_get(disk);
191
if (idkp == NULL)
192
return -ENXIO;
193
194
drive = idkp->drive;
195
196
ide_debug_log(IDE_DBG_FUNC, "enter");
197
198
idkp->openers++;
199
200
if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
201
drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
202
/* Just in case */
203
204
ret = drive->disk_ops->init_media(drive, disk);
205
206
/*
207
* Allow O_NDELAY to open a drive without a disk, or with an
208
* unreadable disk, so that we can get the format capacity
209
* of the drive or begin the format - Sam
210
*/
211
if (ret && (mode & FMODE_NDELAY) == 0) {
212
ret = -EIO;
213
goto out_put_idkp;
214
}
215
216
if ((drive->dev_flags & IDE_DFLAG_WP) && (mode & FMODE_WRITE)) {
217
ret = -EROFS;
218
goto out_put_idkp;
219
}
220
221
/*
222
* Ignore the return code from door_lock,
223
* since the open() has already succeeded,
224
* and the door_lock is irrelevant at this point.
225
*/
226
drive->disk_ops->set_doorlock(drive, disk, 1);
227
drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
228
check_disk_change(bdev);
229
} else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) {
230
ret = -EBUSY;
231
goto out_put_idkp;
232
}
233
return 0;
234
235
out_put_idkp:
236
idkp->openers--;
237
ide_disk_put(idkp);
238
return ret;
239
}
240
241
static int ide_gd_unlocked_open(struct block_device *bdev, fmode_t mode)
242
{
243
int ret;
244
245
mutex_lock(&ide_gd_mutex);
246
ret = ide_gd_open(bdev, mode);
247
mutex_unlock(&ide_gd_mutex);
248
249
return ret;
250
}
251
252
253
static int ide_gd_release(struct gendisk *disk, fmode_t mode)
254
{
255
struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
256
ide_drive_t *drive = idkp->drive;
257
258
ide_debug_log(IDE_DBG_FUNC, "enter");
259
260
mutex_lock(&ide_gd_mutex);
261
if (idkp->openers == 1)
262
drive->disk_ops->flush(drive);
263
264
if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
265
drive->disk_ops->set_doorlock(drive, disk, 0);
266
drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
267
}
268
269
idkp->openers--;
270
271
ide_disk_put(idkp);
272
mutex_unlock(&ide_gd_mutex);
273
274
return 0;
275
}
276
277
static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
278
{
279
struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
280
ide_drive_t *drive = idkp->drive;
281
282
geo->heads = drive->bios_head;
283
geo->sectors = drive->bios_sect;
284
geo->cylinders = (u16)drive->bios_cyl; /* truncate */
285
return 0;
286
}
287
288
static unsigned int ide_gd_check_events(struct gendisk *disk,
289
unsigned int clearing)
290
{
291
struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
292
ide_drive_t *drive = idkp->drive;
293
bool ret;
294
295
/* do not scan partitions twice if this is a removable device */
296
if (drive->dev_flags & IDE_DFLAG_ATTACH) {
297
drive->dev_flags &= ~IDE_DFLAG_ATTACH;
298
return 0;
299
}
300
301
/*
302
* The following is used to force revalidation on the first open on
303
* removeable devices, and never gets reported to userland as
304
* genhd->events is 0. This is intended as removeable ide disk
305
* can't really detect MEDIA_CHANGE events.
306
*/
307
ret = drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED;
308
drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
309
310
return ret ? DISK_EVENT_MEDIA_CHANGE : 0;
311
}
312
313
static void ide_gd_unlock_native_capacity(struct gendisk *disk)
314
{
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
319
if (disk_ops->unlock_native_capacity)
320
disk_ops->unlock_native_capacity(drive);
321
}
322
323
static int ide_gd_revalidate_disk(struct gendisk *disk)
324
{
325
struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
326
ide_drive_t *drive = idkp->drive;
327
328
if (ide_gd_check_events(disk, 0))
329
drive->disk_ops->get_capacity(drive);
330
331
set_capacity(disk, ide_gd_capacity(drive));
332
return 0;
333
}
334
335
static int ide_gd_ioctl(struct block_device *bdev, fmode_t mode,
336
unsigned int cmd, unsigned long arg)
337
{
338
struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
339
ide_drive_t *drive = idkp->drive;
340
341
return drive->disk_ops->ioctl(drive, bdev, mode, cmd, arg);
342
}
343
344
static const struct block_device_operations ide_gd_ops = {
345
.owner = THIS_MODULE,
346
.open = ide_gd_unlocked_open,
347
.release = ide_gd_release,
348
.ioctl = ide_gd_ioctl,
349
.getgeo = ide_gd_getgeo,
350
.check_events = ide_gd_check_events,
351
.unlock_native_capacity = ide_gd_unlock_native_capacity,
352
.revalidate_disk = ide_gd_revalidate_disk
353
};
354
355
static int ide_gd_probe(ide_drive_t *drive)
356
{
357
const struct ide_disk_ops *disk_ops = NULL;
358
struct ide_disk_obj *idkp;
359
struct gendisk *g;
360
361
/* strstr("foo", "") is non-NULL */
362
if (!strstr("ide-gd", drive->driver_req))
363
goto failed;
364
365
#ifdef CONFIG_IDE_GD_ATA
366
if (drive->media == ide_disk)
367
disk_ops = &ide_ata_disk_ops;
368
#endif
369
#ifdef CONFIG_IDE_GD_ATAPI
370
if (drive->media == ide_floppy)
371
disk_ops = &ide_atapi_disk_ops;
372
#endif
373
if (disk_ops == NULL)
374
goto failed;
375
376
if (disk_ops->check(drive, DRV_NAME) == 0) {
377
printk(KERN_ERR PFX "%s: not supported by this driver\n",
378
drive->name);
379
goto failed;
380
}
381
382
idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
383
if (!idkp) {
384
printk(KERN_ERR PFX "%s: can't allocate a disk structure\n",
385
drive->name);
386
goto failed;
387
}
388
389
g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
390
if (!g)
391
goto out_free_idkp;
392
393
ide_init_disk(g, drive);
394
395
idkp->dev.parent = &drive->gendev;
396
idkp->dev.release = ide_disk_release;
397
dev_set_name(&idkp->dev, dev_name(&drive->gendev));
398
399
if (device_register(&idkp->dev))
400
goto out_free_disk;
401
402
idkp->drive = drive;
403
idkp->driver = &ide_gd_driver;
404
idkp->disk = g;
405
406
g->private_data = &idkp->driver;
407
408
drive->driver_data = idkp;
409
drive->debug_mask = debug_mask;
410
drive->disk_ops = disk_ops;
411
412
disk_ops->setup(drive);
413
414
set_capacity(g, ide_gd_capacity(drive));
415
416
g->minors = IDE_DISK_MINORS;
417
g->driverfs_dev = &drive->gendev;
418
g->flags |= GENHD_FL_EXT_DEVT;
419
if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
420
g->flags = GENHD_FL_REMOVABLE;
421
g->fops = &ide_gd_ops;
422
add_disk(g);
423
return 0;
424
425
out_free_disk:
426
put_disk(g);
427
out_free_idkp:
428
kfree(idkp);
429
failed:
430
return -ENODEV;
431
}
432
433
static int __init ide_gd_init(void)
434
{
435
printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "\n");
436
return driver_register(&ide_gd_driver.gen_driver);
437
}
438
439
static void __exit ide_gd_exit(void)
440
{
441
driver_unregister(&ide_gd_driver.gen_driver);
442
}
443
444
MODULE_ALIAS("ide:*m-disk*");
445
MODULE_ALIAS("ide-disk");
446
MODULE_ALIAS("ide:*m-floppy*");
447
MODULE_ALIAS("ide-floppy");
448
module_init(ide_gd_init);
449
module_exit(ide_gd_exit);
450
MODULE_LICENSE("GPL");
451
MODULE_DESCRIPTION("generic ATA/ATAPI disk driver");
452
453