From 863981e96738983919de841ec669e157e6bdaeb0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Sun, 11 Sep 2016 04:34:46 -0300 Subject: Linux-libre 4.7.1-gnu --- drivers/char/ipmi/ipmi_si_intf.c | 65 ++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 26 deletions(-) (limited to 'drivers/char/ipmi/ipmi_si_intf.c') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 1e25b5205..7b1c412b4 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -104,7 +104,7 @@ enum si_intf_state { #define IPMI_BT_INTMASK_ENABLE_IRQ_BIT 1 enum si_type { - SI_KCS, SI_SMIC, SI_BT + SI_KCS, SI_SMIC, SI_BT }; static const char * const si_to_str[] = { "kcs", "smic", "bt" }; @@ -410,7 +410,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) rv = SI_SM_CALL_WITHOUT_DELAY; } - out: +out: return rv; } @@ -539,7 +539,7 @@ static struct ipmi_smi_msg *alloc_msg_handle_irq(struct smi_info *smi_info) static void handle_flags(struct smi_info *smi_info) { - retry: +retry: if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) { /* Watchdog pre-timeout */ smi_inc_stat(smi_info, watchdog_pretimeouts); @@ -831,7 +831,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, { enum si_sm_result si_sm_result; - restart: +restart: /* * There used to be a loop here that waited a little while * (around 25us) before giving up. That turned out to be @@ -944,7 +944,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, smi_info->timer_running = false; } - out: +out: return si_sm_result; } @@ -1190,7 +1190,7 @@ static void smi_timeout(unsigned long data) timeout = jiffies + SI_TIMEOUT_JIFFIES; } - do_mod_timer: +do_mod_timer: if (smi_result != SI_SM_IDLE) smi_mod_timer(smi_info, timeout); else @@ -1576,10 +1576,9 @@ static int port_setup(struct smi_info *info) if (request_region(addr + idx * info->io.regspacing, info->io.regsize, DEVICE_NAME) == NULL) { /* Undo allocations */ - while (idx--) { + while (idx--) release_region(addr + idx * info->io.regspacing, info->io.regsize); - } return -EIO; } } @@ -1638,25 +1637,28 @@ static void mem_outq(const struct si_sm_io *io, unsigned int offset, } #endif -static void mem_cleanup(struct smi_info *info) +static void mem_region_cleanup(struct smi_info *info, int num) { unsigned long addr = info->io.addr_data; - int mapsize; + int idx; + for (idx = 0; idx < num; idx++) + release_mem_region(addr + idx * info->io.regspacing, + info->io.regsize); +} + +static void mem_cleanup(struct smi_info *info) +{ if (info->io.addr) { iounmap(info->io.addr); - - mapsize = ((info->io_size * info->io.regspacing) - - (info->io.regspacing - info->io.regsize)); - - release_mem_region(addr, mapsize); + mem_region_cleanup(info, info->io_size); } } static int mem_setup(struct smi_info *info) { unsigned long addr = info->io.addr_data; - int mapsize; + int mapsize, idx; if (!addr) return -ENODEV; @@ -1692,6 +1694,21 @@ static int mem_setup(struct smi_info *info) return -EINVAL; } + /* + * Some BIOSes reserve disjoint memory regions in their ACPI + * tables. This causes problems when trying to request the + * entire region. Therefore we must request each register + * separately. + */ + for (idx = 0; idx < info->io_size; idx++) { + if (request_mem_region(addr + idx * info->io.regspacing, + info->io.regsize, DEVICE_NAME) == NULL) { + /* Undo allocations */ + mem_region_cleanup(info, idx); + return -EIO; + } + } + /* * Calculate the total amount of memory to claim. This is an * unusual looking calculation, but it avoids claiming any @@ -1701,13 +1718,9 @@ static int mem_setup(struct smi_info *info) */ mapsize = ((info->io_size * info->io.regspacing) - (info->io.regspacing - info->io.regsize)); - - if (request_mem_region(addr, mapsize, DEVICE_NAME) == NULL) - return -EIO; - info->io.addr = ioremap(addr, mapsize); if (info->io.addr == NULL) { - release_mem_region(addr, mapsize); + mem_region_cleanup(info, info->io_size); return -EIO; } return 0; @@ -1975,7 +1988,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) } } rv = len; - out: +out: kfree(str); return rv; } @@ -2945,7 +2958,7 @@ static int try_get_dev_id(struct smi_info *smi_info) /* Check and record info from the get device id, in case we need it. */ rv = ipmi_demangle_device_id(resp, resp_len, &smi_info->device_id); - out: +out: kfree(resp); return rv; } @@ -3192,7 +3205,7 @@ static int try_enable_event_buffer(struct smi_info *smi_info) else smi_info->supports_event_msg_buff = true; - out: +out: kfree(resp); return rv; } @@ -3718,10 +3731,10 @@ static int try_smi_init(struct smi_info *new_smi) return 0; - out_err_stop_timer: +out_err_stop_timer: wait_for_timer_and_thread(new_smi); - out_err: +out_err: new_smi->interrupt_disabled = true; if (new_smi->intf) { -- cgit v1.2.3-54-g00ecf