From e1eeb7f8620733fe9f6640eef48d449b925b3c23 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Tue, 12 Sep 2017 15:40:53 -0500 Subject: [PATCH] ipmi_si: Move io setup into io structure Where it belongs, and getting ready for pulling the platform handling into its own file. Signed-off-by: Corey Minyard --- drivers/char/ipmi/ipmi_si_intf.c | 173 +++++++++++++++---------------- drivers/char/ipmi/ipmi_si_sm.h | 4 + 2 files changed, 85 insertions(+), 92 deletions(-) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 4b832b96d02b..d0a0a5d9e5ff 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -173,9 +173,6 @@ struct smi_info { * IPMI */ struct si_sm_io io; - int (*io_setup)(struct smi_info *info); - void (*io_cleanup)(struct smi_info *info); - unsigned int io_size; /* * Per-OEM handler, called from handle_flags(). Returns 1 @@ -1488,48 +1485,48 @@ static void port_outl(const struct si_sm_io *io, unsigned int offset, outl(b << io->regshift, addr+(offset * io->regspacing)); } -static void port_cleanup(struct smi_info *info) +static void port_cleanup(struct si_sm_io *io) { - unsigned int addr = info->io.addr_data; + unsigned int addr = io->addr_data; int idx; if (addr) { - for (idx = 0; idx < info->io_size; idx++) - release_region(addr + idx * info->io.regspacing, - info->io.regsize); + for (idx = 0; idx < io->io_size; idx++) + release_region(addr + idx * io->regspacing, + io->regsize); } } -static int port_setup(struct smi_info *info) +static int port_setup(struct si_sm_io *io) { - unsigned int addr = info->io.addr_data; + unsigned int addr = io->addr_data; int idx; if (!addr) return -ENODEV; - info->io_cleanup = port_cleanup; + io->io_cleanup = port_cleanup; /* * Figure out the actual inb/inw/inl/etc routine to use based * upon the register size. */ - switch (info->io.regsize) { + switch (io->regsize) { case 1: - info->io.inputb = port_inb; - info->io.outputb = port_outb; + io->inputb = port_inb; + io->outputb = port_outb; break; case 2: - info->io.inputb = port_inw; - info->io.outputb = port_outw; + io->inputb = port_inw; + io->outputb = port_outw; break; case 4: - info->io.inputb = port_inl; - info->io.outputb = port_outl; + io->inputb = port_inl; + io->outputb = port_outl; break; default: - dev_warn(info->io.dev, "Invalid register size: %d\n", - info->io.regsize); + dev_warn(io->dev, "Invalid register size: %d\n", + io->regsize); return -EINVAL; } @@ -1539,13 +1536,13 @@ static int port_setup(struct smi_info *info) * entire I/O region. Therefore we must register each I/O * port separately. */ - for (idx = 0; idx < info->io_size; idx++) { - if (request_region(addr + idx * info->io.regspacing, - info->io.regsize, DEVICE_NAME) == NULL) { + for (idx = 0; idx < io->io_size; idx++) { + if (request_region(addr + idx * io->regspacing, + io->regsize, DEVICE_NAME) == NULL) { /* Undo allocations */ while (idx--) - release_region(addr + idx * info->io.regspacing, - info->io.regsize); + release_region(addr + idx * io->regspacing, + io->regsize); return -EIO; } } @@ -1604,60 +1601,60 @@ static void mem_outq(const struct si_sm_io *io, unsigned int offset, } #endif -static void mem_region_cleanup(struct smi_info *info, int num) +static void mem_region_cleanup(struct si_sm_io *io, int num) { - unsigned long addr = info->io.addr_data; + unsigned long addr = io->addr_data; int idx; for (idx = 0; idx < num; idx++) - release_mem_region(addr + idx * info->io.regspacing, - info->io.regsize); + release_mem_region(addr + idx * io->regspacing, + io->regsize); } -static void mem_cleanup(struct smi_info *info) +static void mem_cleanup(struct si_sm_io *io) { - if (info->io.addr) { - iounmap(info->io.addr); - mem_region_cleanup(info, info->io_size); + if (io->addr) { + iounmap(io->addr); + mem_region_cleanup(io, io->io_size); } } -static int mem_setup(struct smi_info *info) +static int mem_setup(struct si_sm_io *io) { - unsigned long addr = info->io.addr_data; + unsigned long addr = io->addr_data; int mapsize, idx; if (!addr) return -ENODEV; - info->io_cleanup = mem_cleanup; + io->io_cleanup = mem_cleanup; /* * Figure out the actual readb/readw/readl/etc routine to use based * upon the register size. */ - switch (info->io.regsize) { + switch (io->regsize) { case 1: - info->io.inputb = intf_mem_inb; - info->io.outputb = intf_mem_outb; + io->inputb = intf_mem_inb; + io->outputb = intf_mem_outb; break; case 2: - info->io.inputb = intf_mem_inw; - info->io.outputb = intf_mem_outw; + io->inputb = intf_mem_inw; + io->outputb = intf_mem_outw; break; case 4: - info->io.inputb = intf_mem_inl; - info->io.outputb = intf_mem_outl; + io->inputb = intf_mem_inl; + io->outputb = intf_mem_outl; break; #ifdef readq case 8: - info->io.inputb = mem_inq; - info->io.outputb = mem_outq; + io->inputb = mem_inq; + io->outputb = mem_outq; break; #endif default: - dev_warn(info->io.dev, "Invalid register size: %d\n", - info->io.regsize); + dev_warn(io->dev, "Invalid register size: %d\n", + io->regsize); return -EINVAL; } @@ -1667,11 +1664,11 @@ static int mem_setup(struct smi_info *info) * 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) { + for (idx = 0; idx < io->io_size; idx++) { + if (request_mem_region(addr + idx * io->regspacing, + io->regsize, DEVICE_NAME) == NULL) { /* Undo allocations */ - mem_region_cleanup(info, idx); + mem_region_cleanup(io, idx); return -EIO; } } @@ -1683,11 +1680,11 @@ static int mem_setup(struct smi_info *info) * between the first address to the end of the last full * register. */ - mapsize = ((info->io_size * info->io.regspacing) - - (info->io.regspacing - info->io.regsize)); - info->io.addr = ioremap(addr, mapsize); - if (info->io.addr == NULL) { - mem_region_cleanup(info, info->io_size); + mapsize = ((io->io_size * io->regspacing) + - (io->regspacing - io->regsize)); + io->addr = ioremap(addr, mapsize); + if (io->addr == NULL) { + mem_region_cleanup(io, io->io_size); return -EIO; } return 0; @@ -1903,10 +1900,6 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) info->io.si_type = si_type; info->io.addr_data = addr; info->io.addr_type = addr_space; - if (addr_space == IPMI_MEM_ADDR_SPACE) - info->io_setup = mem_setup; - else - info->io_setup = port_setup; info->io.addr = NULL; info->io.regspacing = regspacing; @@ -1987,12 +1980,10 @@ static int hardcode_find_bmc(void) if (ports[i]) { /* An I/O port */ - info->io_setup = port_setup; info->io.addr_data = ports[i]; info->io.addr_type = IPMI_IO_ADDR_SPACE; } else if (addrs[i]) { /* A memory port */ - info->io_setup = mem_setup; info->io.addr_data = addrs[i]; info->io.addr_type = IPMI_MEM_ADDR_SPACE; } else { @@ -2192,10 +2183,8 @@ static int try_init_spmi(struct SPMITable *spmi) info->io.regshift = spmi->addr.bit_offset; if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { - info->io_setup = mem_setup; info->io.addr_type = IPMI_MEM_ADDR_SPACE; } else if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_IO) { - info->io_setup = port_setup; info->io.addr_type = IPMI_IO_ADDR_SPACE; } else { kfree(info); @@ -2248,14 +2237,11 @@ ipmi_get_info_from_resources(struct platform_device *pdev, res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (res) { - info->io_setup = port_setup; info->io.addr_type = IPMI_IO_ADDR_SPACE; } else { res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res) { - info->io_setup = mem_setup; + if (res) info->io.addr_type = IPMI_MEM_ADDR_SPACE; - } } if (!res) { dev_err(&pdev->dev, "no I/O or memory address\n"); @@ -2389,13 +2375,13 @@ static int ipmi_pci_probe_regspacing(struct smi_info *info) info->io.regsize = DEFAULT_REGSIZE; info->io.regshift = 0; - info->io_size = 2; + info->io.io_size = 2; info->handlers = &kcs_smi_handlers; /* detect 1, 4, 16byte spacing */ for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) { info->io.regspacing = regspacing; - if (info->io_setup(info)) { + if (info->io.io_setup(&info->io)) { dev_err(info->io.dev, "Could not setup I/O space\n"); return DEFAULT_REGSPACING; @@ -2404,7 +2390,7 @@ static int ipmi_pci_probe_regspacing(struct smi_info *info) info->io.outputb(&info->io, 1, 0x10); /* read status back */ status = info->io.inputb(&info->io, 1); - info->io_cleanup(info); + info->io.io_cleanup(&info->io); if (status) return regspacing; regspacing *= 4; @@ -2456,13 +2442,10 @@ static int ipmi_pci_probe(struct pci_dev *pdev, info->io.addr_source_cleanup = ipmi_pci_cleanup; info->io.addr_source_data = pdev; - if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { - info->io_setup = port_setup; + if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) info->io.addr_type = IPMI_IO_ADDR_SPACE; - } else { - info->io_setup = mem_setup; + else info->io.addr_type = IPMI_MEM_ADDR_SPACE; - } info->io.addr_data = pci_resource_start(pdev, 0); info->io.regspacing = ipmi_pci_probe_regspacing(info); @@ -2577,13 +2560,10 @@ static int of_ipmi_probe(struct platform_device *pdev) info->io.addr_source = SI_DEVICETREE; info->io.irq_setup = ipmi_std_irq_setup; - if (resource.flags & IORESOURCE_IO) { - info->io_setup = port_setup; - info->io.addr_type = IPMI_IO_ADDR_SPACE; - } else { - info->io_setup = mem_setup; - info->io.addr_type = IPMI_MEM_ADDR_SPACE; - } + if (resource.flags & IORESOURCE_IO) + info->io.addr_type = IPMI_IO_ADDR_SPACE; + else + info->io.addr_type = IPMI_MEM_ADDR_SPACE; info->io.addr_data = resource.start; @@ -2794,7 +2774,6 @@ static int __init ipmi_parisc_probe(struct parisc_device *dev) info->io.si_type = SI_KCS; info->io.addr_source = SI_DEVICETREE; - info->io_setup = mem_setup; info->io.addr_type = IPMI_MEM_ADDR_SPACE; info->io.addr_data = dev->hpa.start; info->io.regsize = 1; @@ -3419,6 +3398,16 @@ int ipmi_si_add_smi(struct smi_info *new_smi) int rv = 0; struct smi_info *dup; + if (!new_smi->io.io_setup) { + if (new_smi->io.addr_type == IPMI_IO_ADDR_SPACE) { + new_smi->io.io_setup = port_setup; + } else if (new_smi->io.addr_type == IPMI_MEM_ADDR_SPACE) { + new_smi->io.io_setup = mem_setup; + } else { + return -EINVAL; + } + } + mutex_lock(&smi_infos_lock); dup = find_dup_si(new_smi); if (dup) { @@ -3522,11 +3511,11 @@ static int try_smi_init(struct smi_info *new_smi) rv = -ENOMEM; goto out_err; } - new_smi->io_size = new_smi->handlers->init_data(new_smi->si_sm, - &new_smi->io); + new_smi->io.io_size = new_smi->handlers->init_data(new_smi->si_sm, + &new_smi->io); /* Now that we know the I/O size, we can set up the I/O. */ - rv = new_smi->io_setup(new_smi); + rv = new_smi->io.io_setup(&new_smi->io); if (rv) { dev_err(new_smi->io.dev, "Could not set up I/O space\n"); goto out_err; @@ -3679,9 +3668,9 @@ out_err: new_smi->io.addr_source_cleanup(&new_smi->io); new_smi->io.addr_source_cleanup = NULL; } - if (new_smi->io_cleanup) { - new_smi->io_cleanup(new_smi); - new_smi->io_cleanup = NULL; + if (new_smi->io.io_cleanup) { + new_smi->io.io_cleanup(&new_smi->io); + new_smi->io.io_cleanup = NULL; } if (new_smi->pdev) { @@ -3861,8 +3850,8 @@ static void cleanup_one_si(struct smi_info *to_clean) if (to_clean->io.addr_source_cleanup) to_clean->io.addr_source_cleanup(&to_clean->io); - if (to_clean->io_cleanup) - to_clean->io_cleanup(to_clean); + if (to_clean->io.io_cleanup) + to_clean->io.io_cleanup(&to_clean->io); if (to_clean->pdev) platform_device_unregister(to_clean->pdev); diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h index bf3f50cede44..9df77c664908 100644 --- a/drivers/char/ipmi/ipmi_si_sm.h +++ b/drivers/char/ipmi/ipmi_si_sm.h @@ -71,6 +71,10 @@ struct si_sm_io { void (*addr_source_cleanup)(struct si_sm_io *io); void *addr_source_data; + int (*io_setup)(struct si_sm_io *info); + void (*io_cleanup)(struct si_sm_io *info); + unsigned int io_size; + int irq; int (*irq_setup)(struct si_sm_io *io); void *irq_handler_data;