X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fipmi%2Fipmi_si_intf.c;h=82f0ed43ea32a61ec72635597f43fdcde3ccdf2a;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=835d6a431a00c00fbe19cbd0e183ca77695cc681;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 835d6a431..82f0ed43e 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -923,34 +923,34 @@ MODULE_PARM_DESC(type, "Defines the type of each interface, each" " interface separated by commas. The types are 'kcs'," " 'smic', and 'bt'. For example si_type=kcs,bt will set" " the first interface to kcs and the second to bt"); -module_param_array(addrs, long, num_addrs, 0); +module_param_array(addrs, long, &num_addrs, 0); MODULE_PARM_DESC(addrs, "Sets the memory address of each interface, the" " addresses separated by commas. Only use if an interface" " is in memory. Otherwise, set it to zero or leave" " it blank."); -module_param_array(ports, int, num_ports, 0); +module_param_array(ports, int, &num_ports, 0); MODULE_PARM_DESC(ports, "Sets the port address of each interface, the" " addresses separated by commas. Only use if an interface" " is a port. Otherwise, set it to zero or leave" " it blank."); -module_param_array(irqs, int, num_irqs, 0); +module_param_array(irqs, int, &num_irqs, 0); MODULE_PARM_DESC(irqs, "Sets the interrupt of each interface, the" " addresses separated by commas. Only use if an interface" " has an interrupt. Otherwise, set it to zero or leave" " it blank."); -module_param_array(regspacings, int, num_regspacings, 0); +module_param_array(regspacings, int, &num_regspacings, 0); MODULE_PARM_DESC(regspacings, "The number of bytes between the start address" " and each successive register used by the interface. For" " instance, if the start address is 0xca2 and the spacing" " is 2, then the second address is at 0xca4. Defaults" " to 1."); -module_param_array(regsizes, int, num_regsizes, 0); +module_param_array(regsizes, int, &num_regsizes, 0); MODULE_PARM_DESC(regsizes, "The size of the specific IPMI register in bytes." " This should generally be 1, 2, 4, or 8 for an 8-bit," " 16-bit, 32-bit, or 64-bit register. Use this if you" " the 8-bit IPMI register has to be read from a larger" " register."); -module_param_array(regshifts, int, num_regshifts, 0); +module_param_array(regshifts, int, &num_regshifts, 0); MODULE_PARM_DESC(regshifts, "The amount to shift the data read from the." " IPMI register, in bits. For instance, if the data" " is read from a 32-bit word and the IPMI data is in" @@ -959,7 +959,7 @@ MODULE_PARM_DESC(regshifts, "The amount to shift the data read from the." #define IPMI_MEM_ADDR_SPACE 1 #define IPMI_IO_ADDR_SPACE 2 -#if defined(CONFIG_ACPI_INTERPETER) || defined(CONFIG_X86) || defined(CONFIG_PCI) +#if defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_X86) || defined(CONFIG_PCI) static int is_new_interface(int intf, u8 addr_space, unsigned long base_addr) { int i; @@ -1299,7 +1299,7 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) memset(info, 0, sizeof(*info)); info->io_setup = mem_setup; - info->io.info = (void *) addrs[intf_num]; + info->io.info = &addrs[intf_num]; info->io.addr = NULL; info->io.regspacing = regspacings[intf_num]; if (!info->io.regspacing) @@ -1331,7 +1331,7 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) static int acpi_failure = 0; /* For GPE-type interrupts. */ -u32 ipmi_acpi_gpe(void *context) +static u32 ipmi_acpi_gpe(void *context) { struct smi_info *smi_info = context; unsigned long flags; @@ -1370,7 +1370,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) status = acpi_install_gpe_handler(NULL, info->irq, ACPI_GPE_LEVEL_TRIGGERED, - ipmi_acpi_gpe, + &ipmi_acpi_gpe, info); if (status != AE_OK) { printk(KERN_WARNING @@ -1390,7 +1390,7 @@ static void acpi_gpe_irq_cleanup(struct smi_info *info) if (!info->irq) return; - acpi_remove_gpe_handler(NULL, info->irq, ipmi_acpi_gpe); + acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); } /* @@ -1564,47 +1564,54 @@ static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data) u8 *data = (u8 *)dm; unsigned long base_addr; u8 reg_spacing; + u8 len = dm->length; - ipmi_data->type = data[0x04]; + ipmi_data->type = data[4]; - memcpy(&base_addr,&data[0x08],sizeof(unsigned long)); - if (base_addr & 1) { - /* I/O */ - base_addr &= 0xFFFE; + memcpy(&base_addr, data+8, sizeof(unsigned long)); + if (len >= 0x11) { + if (base_addr & 1) { + /* I/O */ + base_addr &= 0xFFFE; + ipmi_data->addr_space = IPMI_IO_ADDR_SPACE; + } + else { + /* Memory */ + ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE; + } + /* If bit 4 of byte 0x10 is set, then the lsb for the address + is odd. */ + ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); + + ipmi_data->irq = data[0x11]; + + /* The top two bits of byte 0x10 hold the register spacing. */ + reg_spacing = (data[0x10] & 0xC0) >> 6; + switch(reg_spacing){ + case 0x00: /* Byte boundaries */ + ipmi_data->offset = 1; + break; + case 0x01: /* 32-bit boundaries */ + ipmi_data->offset = 4; + break; + case 0x02: /* 16-byte boundaries */ + ipmi_data->offset = 16; + break; + default: + /* Some other interface, just ignore it. */ + return -EIO; + } + } else { + /* Old DMI spec. */ + ipmi_data->base_addr = base_addr; ipmi_data->addr_space = IPMI_IO_ADDR_SPACE; - } - else { - /* Memory */ - ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE; - } - - /* The top two bits of byte 0x10 hold the register spacing. */ - reg_spacing = (data[0x10] & 0xC0) >> 6; - switch(reg_spacing){ - case 0x00: /* Byte boundaries */ ipmi_data->offset = 1; - break; - case 0x01: /* 32-bit boundaries */ - ipmi_data->offset = 4; - break; - case 0x02: /* 16-bit boundaries */ - ipmi_data->offset = 2; - default: - printk("ipmi_si: Unknown SMBIOS IPMI Base Addr" - " Modifier: 0x%x\n", reg_spacing); - return -EIO; } - /* If bit 4 of byte 0x10 is set, then the lsb for the address - is odd. */ - ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); - - ipmi_data->irq = data[0x11]; - if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) - return 0; + return 0; - memset(ipmi_data,0,sizeof(dmi_ipmi_data_t)); + memset(ipmi_data, 0, sizeof(dmi_ipmi_data_t)); return -1; } @@ -1777,10 +1784,10 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) pci_smic_checked = 1; - if ((pci_dev = pci_find_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, + if ((pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL))) ; - else if ((pci_dev = pci_find_class(PCI_ERMC_CLASSCODE, NULL)) && + else if ((pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL)) && pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID) fe_rmc = 1; else @@ -1789,6 +1796,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); if (error) { + pci_dev_put(pci_dev); printk(KERN_ERR "ipmi_si: pci_read_config_word() failed (%d).\n", error); @@ -1798,6 +1806,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ if (!(base_addr & 0x0001)) { + pci_dev_put(pci_dev); printk(KERN_ERR "ipmi_si: memory mapped I/O not supported for PCI" " smic.\n"); @@ -1809,11 +1818,14 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) /* Data register starts at base address + 1 in eRMC */ ++base_addr; - if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) - return -ENODEV; + if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { + pci_dev_put(pci_dev); + return -ENODEV; + } info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) { + pci_dev_put(pci_dev); printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); return -ENOMEM; } @@ -1836,6 +1848,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) printk("ipmi_si: Found PCI SMIC at I/O address 0x%lx\n", (long unsigned int) base_addr); + pci_dev_put(pci_dev); return 0; } #endif /* CONFIG_PCI */ @@ -2247,7 +2260,7 @@ static __init int init_ipmi_si(void) } module_init(init_ipmi_si); -void __exit cleanup_one_si(struct smi_info *to_clean) +static void __exit cleanup_one_si(struct smi_info *to_clean) { int rv; unsigned long flags; @@ -2283,6 +2296,7 @@ void __exit cleanup_one_si(struct smi_info *to_clean) interface is in a clean state. */ while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) { poll(to_clean); + set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); }