summaryrefslogtreecommitdiff
path: root/drivers/char/ipmi
diff options
context:
space:
mode:
authorCorey Minyard <cminyard@mvista.com>2017-09-12 23:40:53 +0300
committerCorey Minyard <cminyard@mvista.com>2017-09-28 00:03:45 +0300
commite1eeb7f8620733fe9f6640eef48d449b925b3c23 (patch)
tree33622e0272b190a10ac7b37625af672c982f0b6b /drivers/char/ipmi
parent4f3e8199c34dda46b6554191fe7a444dd6fa911f (diff)
downloadlinux-e1eeb7f8620733fe9f6640eef48d449b925b3c23.tar.xz
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 <cminyard@mvista.com>
Diffstat (limited to 'drivers/char/ipmi')
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c173
-rw-r--r--drivers/char/ipmi/ipmi_si_sm.h4
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;