diff options
Diffstat (limited to 'drivers/firmware/edd.c')
| -rw-r--r-- | drivers/firmware/edd.c | 103 |
1 files changed, 57 insertions, 46 deletions
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index 6996476669f..e2295766580 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c @@ -1,5 +1,5 @@ /* - * linux/arch/i386/kernel/edd.c + * linux/drivers/firmware/edd.c * Copyright (C) 2002, 2003, 2004 Dell Inc. * by Matt Domsch <Matt_Domsch@dell.com> * disk signature by Matt Domsch, Andrew Wilks, and Sandeep K. Shandilya @@ -11,11 +11,11 @@ * * This code takes information provided by BIOS EDD calls * fn41 - Check Extensions Present and - * fn48 - Get Device Parametes with EDD extensions + * fn48 - Get Device Parameters with EDD extensions * made in setup.S, copied to safe structures in setup.c, * and presents it in sysfs. * - * Please see http://linux.dell.com/edd30/results.html for + * Please see http://linux.dell.com/edd/results.html for * the list of BIOSs which have been reported to implement EDD. * * This program is free software; you can redistribute it and/or modify @@ -74,7 +74,7 @@ static struct edd_device *edd_devices[EDD_MBR_SIG_MAX]; #define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \ struct edd_attribute edd_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ .show = _show, \ .test = _test, \ }; @@ -122,7 +122,7 @@ edd_attr_show(struct kobject * kobj, struct attribute *attr, char *buf) return ret; } -static struct sysfs_ops edd_attr_ops = { +static const struct sysfs_ops edd_attr_ops = { .show = edd_attr_show, }; @@ -151,7 +151,8 @@ edd_show_host_bus(struct edd_device *edev, char *buf) p += scnprintf(p, left, "\tbase_address: %x\n", info->params.interface_path.isa.base_address); } else if (!strncmp(info->params.host_bus_type, "PCIX", 4) || - !strncmp(info->params.host_bus_type, "PCI", 3)) { + !strncmp(info->params.host_bus_type, "PCI", 3) || + !strncmp(info->params.host_bus_type, "XPRS", 4)) { p += scnprintf(p, left, "\t%02x:%02x.%d channel: %u\n", info->params.interface_path.pci.bus, @@ -159,7 +160,6 @@ edd_show_host_bus(struct edd_device *edev, char *buf) info->params.interface_path.pci.function, info->params.interface_path.pci.channel); } else if (!strncmp(info->params.host_bus_type, "IBND", 4) || - !strncmp(info->params.host_bus_type, "XPRS", 4) || !strncmp(info->params.host_bus_type, "HTPT", 4)) { p += scnprintf(p, left, "\tTBD: %llx\n", @@ -233,6 +233,8 @@ edd_show_interface(struct edd_device *edev, char *buf) /** * edd_show_raw_data() - copies raw data to buffer for userspace to parse + * @edev: target edd_device + * @buf: output buffer * * Returns: number of bytes written, or -EINVAL on failure */ @@ -529,8 +531,8 @@ static int edd_has_edd30(struct edd_device *edev) { struct edd_info *info; - int i, nonzero_path = 0; - char c; + int i; + u8 csum = 0; if (!edev) return 0; @@ -542,16 +544,16 @@ edd_has_edd30(struct edd_device *edev) return 0; } - for (i = 30; i <= 73; i++) { - c = *(((uint8_t *) info) + i + 4); - if (c) { - nonzero_path++; - break; - } - } - if (!nonzero_path) { + + /* We support only T13 spec */ + if (info->params.device_path_info_length != 44) + return 0; + + for (i = 30; i < info->params.device_path_info_length + 30; i++) + csum += *(((u8 *)&info->params) + i); + + if (csum) return 0; - } return 1; } @@ -623,19 +625,19 @@ static void edd_release(struct kobject * kobj) kfree(dev); } -static struct kobj_type ktype_edd = { +static struct kobj_type edd_ktype = { .release = edd_release, .sysfs_ops = &edd_attr_ops, .default_attrs = def_attrs, }; -static decl_subsys(edd,&ktype_edd,NULL); +static struct kset *edd_kset; /** * edd_dev_is_type() - is this EDD device a 'type' device? - * @edev - * @type - a host bus or interface identifier string per the EDD spec + * @edev: target edd_device + * @type: a host bus or interface identifier string per the EDD spec * * Returns 1 (TRUE) if it is a 'type' device, 0 otherwise. */ @@ -657,7 +659,7 @@ edd_dev_is_type(struct edd_device *edev, const char *type) /** * edd_get_pci_dev() - finds pci_dev that matches edev - * @edev - edd_device + * @edev: edd_device * * Returns pci_dev if found, or NULL */ @@ -666,8 +668,8 @@ edd_get_pci_dev(struct edd_device *edev) { struct edd_info *info = edd_dev_get_info(edev); - if (edd_dev_is_type(edev, "PCI")) { - return pci_find_slot(info->params.interface_path.pci.bus, + if (edd_dev_is_type(edev, "PCI") || edd_dev_is_type(edev, "XPRS")) { + return pci_get_bus_and_slot(info->params.interface_path.pci.bus, PCI_DEVFN(info->params.interface_path.pci.slot, info->params.interface_path.pci. function)); @@ -680,15 +682,18 @@ edd_create_symlink_to_pcidev(struct edd_device *edev) { struct pci_dev *pci_dev = edd_get_pci_dev(edev); + int ret; if (!pci_dev) return 1; - return sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev"); + ret = sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev"); + pci_dev_put(pci_dev); + return ret; } static inline void edd_device_unregister(struct edd_device *edev) { - kobject_unregister(&edev->kobj); + kobject_put(&edev->kobj); } static void edd_populate_dir(struct edd_device * edev) @@ -715,14 +720,14 @@ edd_device_register(struct edd_device *edev, int i) if (!edev) return 1; - memset(edev, 0, sizeof (*edev)); edd_dev_set_info(edev, i); - kobject_set_name(&edev->kobj, "int13_dev%02x", - 0x80 + i); - kobj_set_kset_s(edev,edd_subsys); - error = kobject_register(&edev->kobj); - if (!error) + edev->kobj.kset = edd_kset; + error = kobject_init_and_add(&edev->kobj, &edd_ktype, NULL, + "int13_dev%02x", 0x80 + i); + if (!error) { edd_populate_dir(edev); + kobject_uevent(&edev->kobj, KOBJ_ADD); + } return error; } @@ -739,7 +744,7 @@ static inline int edd_num_devices(void) static int __init edd_init(void) { - unsigned int i; + int i; int rc=0; struct edd_device *edev; @@ -748,28 +753,34 @@ edd_init(void) if (!edd_num_devices()) { printk(KERN_INFO "EDD information not available.\n"); - return 1; + return -ENODEV; } - rc = firmware_register(&edd_subsys); - if (rc) - return rc; + edd_kset = kset_create_and_add("edd", NULL, firmware_kobj); + if (!edd_kset) + return -ENOMEM; - for (i = 0; i < edd_num_devices() && !rc; i++) { - edev = kmalloc(sizeof (*edev), GFP_KERNEL); - if (!edev) - return -ENOMEM; + for (i = 0; i < edd_num_devices(); i++) { + edev = kzalloc(sizeof (*edev), GFP_KERNEL); + if (!edev) { + rc = -ENOMEM; + goto out; + } rc = edd_device_register(edev, i); if (rc) { kfree(edev); - break; + goto out; } edd_devices[i] = edev; } - if (rc) - firmware_unregister(&edd_subsys); + return 0; + +out: + while (--i >= 0) + edd_device_unregister(edd_devices[i]); + kset_unregister(edd_kset); return rc; } @@ -783,7 +794,7 @@ edd_exit(void) if ((edev = edd_devices[i])) edd_device_unregister(edev); } - firmware_unregister(&edd_subsys); + kset_unregister(edd_kset); } late_initcall(edd_init); |
