forked from Minki/linux
5a0e3ad6af
percpu.h is included by sched.h and module.h and thus ends up being included when building most .c files. percpu.h includes slab.h which in turn includes gfp.h making everything defined by the two files universally available and complicating inclusion dependencies. percpu.h -> slab.h dependency is about to be removed. Prepare for this change by updating users of gfp and slab facilities include those headers directly instead of assuming availability. As this conversion needs to touch large number of source files, the following script is used as the basis of conversion. http://userweb.kernel.org/~tj/misc/slabh-sweep.py The script does the followings. * Scan files for gfp and slab usages and update includes such that only the necessary includes are there. ie. if only gfp is used, gfp.h, if slab is used, slab.h. * When the script inserts a new include, it looks at the include blocks and try to put the new include such that its order conforms to its surrounding. It's put in the include block which contains core kernel includes, in the same order that the rest are ordered - alphabetical, Christmas tree, rev-Xmas-tree or at the end if there doesn't seem to be any matching order. * If the script can't find a place to put a new include (mostly because the file doesn't have fitting include block), it prints out an error message indicating which .h file needs to be added to the file. The conversion was done in the following steps. 1. The initial automatic conversion of all .c files updated slightly over 4000 files, deleting around 700 includes and adding ~480 gfp.h and ~3000 slab.h inclusions. The script emitted errors for ~400 files. 2. Each error was manually checked. Some didn't need the inclusion, some needed manual addition while adding it to implementation .h or embedding .c file was more appropriate for others. This step added inclusions to around 150 files. 3. The script was run again and the output was compared to the edits from #2 to make sure no file was left behind. 4. Several build tests were done and a couple of problems were fixed. e.g. lib/decompress_*.c used malloc/free() wrappers around slab APIs requiring slab.h to be added manually. 5. The script was run on all .h files but without automatically editing them as sprinkling gfp.h and slab.h inclusions around .h files could easily lead to inclusion dependency hell. Most gfp.h inclusion directives were ignored as stuff from gfp.h was usually wildly available and often used in preprocessor macros. Each slab.h inclusion directive was examined and added manually as necessary. 6. percpu.h was updated not to include slab.h. 7. Build test were done on the following configurations and failures were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my distributed build env didn't work with gcov compiles) and a few more options had to be turned off depending on archs to make things build (like ipr on powerpc/64 which failed due to missing writeq). * x86 and x86_64 UP and SMP allmodconfig and a custom test config. * powerpc and powerpc64 SMP allmodconfig * sparc and sparc64 SMP allmodconfig * ia64 SMP allmodconfig * s390 SMP allmodconfig * alpha SMP allmodconfig * um on x86_64 SMP allmodconfig 8. percpu.h modifications were reverted so that it could be applied as a separate patch and serve as bisection point. Given the fact that I had only a couple of failures from tests on step 6, I'm fairly confident about the coverage of this conversion patch. If there is a breakage, it's likely to be something in one of the arch headers which should be easily discoverable easily on most builds of the specific arch. Signed-off-by: Tejun Heo <tj@kernel.org> Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
410 lines
10 KiB
C
410 lines
10 KiB
C
/*
|
|
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
|
|
* Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz
|
|
*/
|
|
|
|
/*
|
|
* Mostly written by Mark Lord <mlord@pobox.com>
|
|
* and Gadi Oxman <gadio@netvision.net.il>
|
|
* and Andre Hedrick <andre@linux-ide.org>
|
|
*
|
|
* See linux/MAINTAINERS for address of current maintainer.
|
|
*
|
|
* This is the multiple IDE interface driver, as evolved from hd.c.
|
|
* It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs
|
|
* (usually 14 & 15).
|
|
* There can be up to two drives per interface, as per the ATA-2 spec.
|
|
*
|
|
* ...
|
|
*
|
|
* From hd.c:
|
|
* |
|
|
* | It traverses the request-list, using interrupts to jump between functions.
|
|
* | As nearly all functions can be called within interrupts, we may not sleep.
|
|
* | Special care is recommended. Have Fun!
|
|
* |
|
|
* | modified by Drew Eckhardt to check nr of hd's from the CMOS.
|
|
* |
|
|
* | Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
|
|
* | in the early extended-partition checks and added DM partitions.
|
|
* |
|
|
* | Early work on error handling by Mika Liljeberg (liljeber@cs.Helsinki.FI).
|
|
* |
|
|
* | IRQ-unmask, drive-id, multiple-mode, support for ">16 heads",
|
|
* | and general streamlining by Mark Lord (mlord@pobox.com).
|
|
*
|
|
* October, 1994 -- Complete line-by-line overhaul for linux 1.1.x, by:
|
|
*
|
|
* Mark Lord (mlord@pobox.com) (IDE Perf.Pkg)
|
|
* Delman Lee (delman@ieee.org) ("Mr. atdisk2")
|
|
* Scott Snyder (snyder@fnald0.fnal.gov) (ATAPI IDE cd-rom)
|
|
*
|
|
* This was a rewrite of just about everything from hd.c, though some original
|
|
* code is still sprinkled about. Think of it as a major evolution, with
|
|
* inspiration from lots of linux users, esp. hamish@zot.apana.org.au
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/types.h>
|
|
#include <linux/string.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/major.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/genhd.h>
|
|
#include <linux/init.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/ide.h>
|
|
#include <linux/hdreg.h>
|
|
#include <linux/completion.h>
|
|
#include <linux/device.h>
|
|
|
|
struct class *ide_port_class;
|
|
|
|
/**
|
|
* ide_device_get - get an additional reference to a ide_drive_t
|
|
* @drive: device to get a reference to
|
|
*
|
|
* Gets a reference to the ide_drive_t and increments the use count of the
|
|
* underlying LLDD module.
|
|
*/
|
|
int ide_device_get(ide_drive_t *drive)
|
|
{
|
|
struct device *host_dev;
|
|
struct module *module;
|
|
|
|
if (!get_device(&drive->gendev))
|
|
return -ENXIO;
|
|
|
|
host_dev = drive->hwif->host->dev[0];
|
|
module = host_dev ? host_dev->driver->owner : NULL;
|
|
|
|
if (module && !try_module_get(module)) {
|
|
put_device(&drive->gendev);
|
|
return -ENXIO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(ide_device_get);
|
|
|
|
/**
|
|
* ide_device_put - release a reference to a ide_drive_t
|
|
* @drive: device to release a reference on
|
|
*
|
|
* Release a reference to the ide_drive_t and decrements the use count of
|
|
* the underlying LLDD module.
|
|
*/
|
|
void ide_device_put(ide_drive_t *drive)
|
|
{
|
|
#ifdef CONFIG_MODULE_UNLOAD
|
|
struct device *host_dev = drive->hwif->host->dev[0];
|
|
struct module *module = host_dev ? host_dev->driver->owner : NULL;
|
|
|
|
if (module)
|
|
module_put(module);
|
|
#endif
|
|
put_device(&drive->gendev);
|
|
}
|
|
EXPORT_SYMBOL_GPL(ide_device_put);
|
|
|
|
static int ide_bus_match(struct device *dev, struct device_driver *drv)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static int ide_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|
{
|
|
ide_drive_t *drive = to_ide_device(dev);
|
|
|
|
add_uevent_var(env, "MEDIA=%s", ide_media_string(drive));
|
|
add_uevent_var(env, "DRIVENAME=%s", drive->name);
|
|
add_uevent_var(env, "MODALIAS=ide:m-%s", ide_media_string(drive));
|
|
return 0;
|
|
}
|
|
|
|
static int generic_ide_probe(struct device *dev)
|
|
{
|
|
ide_drive_t *drive = to_ide_device(dev);
|
|
struct ide_driver *drv = to_ide_driver(dev->driver);
|
|
|
|
return drv->probe ? drv->probe(drive) : -ENODEV;
|
|
}
|
|
|
|
static int generic_ide_remove(struct device *dev)
|
|
{
|
|
ide_drive_t *drive = to_ide_device(dev);
|
|
struct ide_driver *drv = to_ide_driver(dev->driver);
|
|
|
|
if (drv->remove)
|
|
drv->remove(drive);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void generic_ide_shutdown(struct device *dev)
|
|
{
|
|
ide_drive_t *drive = to_ide_device(dev);
|
|
struct ide_driver *drv = to_ide_driver(dev->driver);
|
|
|
|
if (dev->driver && drv->shutdown)
|
|
drv->shutdown(drive);
|
|
}
|
|
|
|
struct bus_type ide_bus_type = {
|
|
.name = "ide",
|
|
.match = ide_bus_match,
|
|
.uevent = ide_uevent,
|
|
.probe = generic_ide_probe,
|
|
.remove = generic_ide_remove,
|
|
.shutdown = generic_ide_shutdown,
|
|
.dev_attrs = ide_dev_attrs,
|
|
.suspend = generic_ide_suspend,
|
|
.resume = generic_ide_resume,
|
|
};
|
|
|
|
EXPORT_SYMBOL_GPL(ide_bus_type);
|
|
|
|
int ide_vlb_clk;
|
|
EXPORT_SYMBOL_GPL(ide_vlb_clk);
|
|
|
|
module_param_named(vlb_clock, ide_vlb_clk, int, 0);
|
|
MODULE_PARM_DESC(vlb_clock, "VLB clock frequency (in MHz)");
|
|
|
|
int ide_pci_clk;
|
|
EXPORT_SYMBOL_GPL(ide_pci_clk);
|
|
|
|
module_param_named(pci_clock, ide_pci_clk, int, 0);
|
|
MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)");
|
|
|
|
static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp)
|
|
{
|
|
int a, b, i, j = 1;
|
|
unsigned int *dev_param_mask = (unsigned int *)kp->arg;
|
|
|
|
/* controller . device (0 or 1) [ : 1 (set) | 0 (clear) ] */
|
|
if (sscanf(s, "%d.%d:%d", &a, &b, &j) != 3 &&
|
|
sscanf(s, "%d.%d", &a, &b) != 2)
|
|
return -EINVAL;
|
|
|
|
i = a * MAX_DRIVES + b;
|
|
|
|
if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1)
|
|
return -EINVAL;
|
|
|
|
if (j)
|
|
*dev_param_mask |= (1 << i);
|
|
else
|
|
*dev_param_mask &= ~(1 << i);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static unsigned int ide_nodma;
|
|
|
|
module_param_call(nodma, ide_set_dev_param_mask, NULL, &ide_nodma, 0);
|
|
MODULE_PARM_DESC(nodma, "disallow DMA for a device");
|
|
|
|
static unsigned int ide_noflush;
|
|
|
|
module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0);
|
|
MODULE_PARM_DESC(noflush, "disable flush requests for a device");
|
|
|
|
static unsigned int ide_nohpa;
|
|
|
|
module_param_call(nohpa, ide_set_dev_param_mask, NULL, &ide_nohpa, 0);
|
|
MODULE_PARM_DESC(nohpa, "disable Host Protected Area for a device");
|
|
|
|
static unsigned int ide_noprobe;
|
|
|
|
module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0);
|
|
MODULE_PARM_DESC(noprobe, "skip probing for a device");
|
|
|
|
static unsigned int ide_nowerr;
|
|
|
|
module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0);
|
|
MODULE_PARM_DESC(nowerr, "ignore the ATA_DF bit for a device");
|
|
|
|
static unsigned int ide_cdroms;
|
|
|
|
module_param_call(cdrom, ide_set_dev_param_mask, NULL, &ide_cdroms, 0);
|
|
MODULE_PARM_DESC(cdrom, "force device as a CD-ROM");
|
|
|
|
struct chs_geom {
|
|
unsigned int cyl;
|
|
u8 head;
|
|
u8 sect;
|
|
};
|
|
|
|
static unsigned int ide_disks;
|
|
static struct chs_geom ide_disks_chs[MAX_HWIFS * MAX_DRIVES];
|
|
|
|
static int ide_set_disk_chs(const char *str, struct kernel_param *kp)
|
|
{
|
|
int a, b, c = 0, h = 0, s = 0, i, j = 1;
|
|
|
|
/* controller . device (0 or 1) : Cylinders , Heads , Sectors */
|
|
/* controller . device (0 or 1) : 1 (use CHS) | 0 (ignore CHS) */
|
|
if (sscanf(str, "%d.%d:%d,%d,%d", &a, &b, &c, &h, &s) != 5 &&
|
|
sscanf(str, "%d.%d:%d", &a, &b, &j) != 3)
|
|
return -EINVAL;
|
|
|
|
i = a * MAX_DRIVES + b;
|
|
|
|
if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1)
|
|
return -EINVAL;
|
|
|
|
if (c > INT_MAX || h > 255 || s > 255)
|
|
return -EINVAL;
|
|
|
|
if (j)
|
|
ide_disks |= (1 << i);
|
|
else
|
|
ide_disks &= ~(1 << i);
|
|
|
|
ide_disks_chs[i].cyl = c;
|
|
ide_disks_chs[i].head = h;
|
|
ide_disks_chs[i].sect = s;
|
|
|
|
return 0;
|
|
}
|
|
|
|
module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0);
|
|
MODULE_PARM_DESC(chs, "force device as a disk (using CHS)");
|
|
|
|
static void ide_dev_apply_params(ide_drive_t *drive, u8 unit)
|
|
{
|
|
int i = drive->hwif->index * MAX_DRIVES + unit;
|
|
|
|
if (ide_nodma & (1 << i)) {
|
|
printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name);
|
|
drive->dev_flags |= IDE_DFLAG_NODMA;
|
|
}
|
|
if (ide_noflush & (1 << i)) {
|
|
printk(KERN_INFO "ide: disabling flush requests for %s\n",
|
|
drive->name);
|
|
drive->dev_flags |= IDE_DFLAG_NOFLUSH;
|
|
}
|
|
if (ide_nohpa & (1 << i)) {
|
|
printk(KERN_INFO "ide: disabling Host Protected Area for %s\n",
|
|
drive->name);
|
|
drive->dev_flags |= IDE_DFLAG_NOHPA;
|
|
}
|
|
if (ide_noprobe & (1 << i)) {
|
|
printk(KERN_INFO "ide: skipping probe for %s\n", drive->name);
|
|
drive->dev_flags |= IDE_DFLAG_NOPROBE;
|
|
}
|
|
if (ide_nowerr & (1 << i)) {
|
|
printk(KERN_INFO "ide: ignoring the ATA_DF bit for %s\n",
|
|
drive->name);
|
|
drive->bad_wstat = BAD_R_STAT;
|
|
}
|
|
if (ide_cdroms & (1 << i)) {
|
|
printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name);
|
|
drive->dev_flags |= IDE_DFLAG_PRESENT;
|
|
drive->media = ide_cdrom;
|
|
/* an ATAPI device ignores DRDY */
|
|
drive->ready_stat = 0;
|
|
}
|
|
if (ide_disks & (1 << i)) {
|
|
drive->cyl = drive->bios_cyl = ide_disks_chs[i].cyl;
|
|
drive->head = drive->bios_head = ide_disks_chs[i].head;
|
|
drive->sect = drive->bios_sect = ide_disks_chs[i].sect;
|
|
|
|
printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n",
|
|
drive->name,
|
|
drive->cyl, drive->head, drive->sect);
|
|
|
|
drive->dev_flags |= IDE_DFLAG_FORCED_GEOM | IDE_DFLAG_PRESENT;
|
|
drive->media = ide_disk;
|
|
drive->ready_stat = ATA_DRDY;
|
|
}
|
|
}
|
|
|
|
static unsigned int ide_ignore_cable;
|
|
|
|
static int ide_set_ignore_cable(const char *s, struct kernel_param *kp)
|
|
{
|
|
int i, j = 1;
|
|
|
|
/* controller (ignore) */
|
|
/* controller : 1 (ignore) | 0 (use) */
|
|
if (sscanf(s, "%d:%d", &i, &j) != 2 && sscanf(s, "%d", &i) != 1)
|
|
return -EINVAL;
|
|
|
|
if (i >= MAX_HWIFS || j < 0 || j > 1)
|
|
return -EINVAL;
|
|
|
|
if (j)
|
|
ide_ignore_cable |= (1 << i);
|
|
else
|
|
ide_ignore_cable &= ~(1 << i);
|
|
|
|
return 0;
|
|
}
|
|
|
|
module_param_call(ignore_cable, ide_set_ignore_cable, NULL, NULL, 0);
|
|
MODULE_PARM_DESC(ignore_cable, "ignore cable detection");
|
|
|
|
void ide_port_apply_params(ide_hwif_t *hwif)
|
|
{
|
|
ide_drive_t *drive;
|
|
int i;
|
|
|
|
if (ide_ignore_cable & (1 << hwif->index)) {
|
|
printk(KERN_INFO "ide: ignoring cable detection for %s\n",
|
|
hwif->name);
|
|
hwif->cbl = ATA_CBL_PATA40_SHORT;
|
|
}
|
|
|
|
ide_port_for_each_dev(i, drive, hwif)
|
|
ide_dev_apply_params(drive, i);
|
|
}
|
|
|
|
/*
|
|
* This is gets invoked once during initialization, to set *everything* up
|
|
*/
|
|
static int __init ide_init(void)
|
|
{
|
|
int ret;
|
|
|
|
printk(KERN_INFO "Uniform Multi-Platform E-IDE driver\n");
|
|
|
|
ret = bus_register(&ide_bus_type);
|
|
if (ret < 0) {
|
|
printk(KERN_WARNING "IDE: bus_register error: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
ide_port_class = class_create(THIS_MODULE, "ide_port");
|
|
if (IS_ERR(ide_port_class)) {
|
|
ret = PTR_ERR(ide_port_class);
|
|
goto out_port_class;
|
|
}
|
|
|
|
ide_acpi_init();
|
|
|
|
proc_ide_create();
|
|
|
|
return 0;
|
|
|
|
out_port_class:
|
|
bus_unregister(&ide_bus_type);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void __exit ide_exit(void)
|
|
{
|
|
proc_ide_destroy();
|
|
|
|
class_destroy(ide_port_class);
|
|
|
|
bus_unregister(&ide_bus_type);
|
|
}
|
|
|
|
module_init(ide_init);
|
|
module_exit(ide_exit);
|
|
|
|
MODULE_LICENSE("GPL");
|