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>
This commit is contained in:
Corey Minyard 2017-09-12 15:40:53 -05:00
parent 4f3e8199c3
commit e1eeb7f862
2 changed files with 85 additions and 92 deletions

View File

@ -173,9 +173,6 @@ struct smi_info {
* IPMI * IPMI
*/ */
struct si_sm_io io; 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 * 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)); 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; int idx;
if (addr) { if (addr) {
for (idx = 0; idx < info->io_size; idx++) for (idx = 0; idx < io->io_size; idx++)
release_region(addr + idx * info->io.regspacing, release_region(addr + idx * io->regspacing,
info->io.regsize); 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; int idx;
if (!addr) if (!addr)
return -ENODEV; return -ENODEV;
info->io_cleanup = port_cleanup; io->io_cleanup = port_cleanup;
/* /*
* Figure out the actual inb/inw/inl/etc routine to use based * Figure out the actual inb/inw/inl/etc routine to use based
* upon the register size. * upon the register size.
*/ */
switch (info->io.regsize) { switch (io->regsize) {
case 1: case 1:
info->io.inputb = port_inb; io->inputb = port_inb;
info->io.outputb = port_outb; io->outputb = port_outb;
break; break;
case 2: case 2:
info->io.inputb = port_inw; io->inputb = port_inw;
info->io.outputb = port_outw; io->outputb = port_outw;
break; break;
case 4: case 4:
info->io.inputb = port_inl; io->inputb = port_inl;
info->io.outputb = port_outl; io->outputb = port_outl;
break; break;
default: default:
dev_warn(info->io.dev, "Invalid register size: %d\n", dev_warn(io->dev, "Invalid register size: %d\n",
info->io.regsize); io->regsize);
return -EINVAL; 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 * entire I/O region. Therefore we must register each I/O
* port separately. * port separately.
*/ */
for (idx = 0; idx < info->io_size; idx++) { for (idx = 0; idx < io->io_size; idx++) {
if (request_region(addr + idx * info->io.regspacing, if (request_region(addr + idx * io->regspacing,
info->io.regsize, DEVICE_NAME) == NULL) { io->regsize, DEVICE_NAME) == NULL) {
/* Undo allocations */ /* Undo allocations */
while (idx--) while (idx--)
release_region(addr + idx * info->io.regspacing, release_region(addr + idx * io->regspacing,
info->io.regsize); io->regsize);
return -EIO; return -EIO;
} }
} }
@ -1604,60 +1601,60 @@ static void mem_outq(const struct si_sm_io *io, unsigned int offset,
} }
#endif #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; int idx;
for (idx = 0; idx < num; idx++) for (idx = 0; idx < num; idx++)
release_mem_region(addr + idx * info->io.regspacing, release_mem_region(addr + idx * io->regspacing,
info->io.regsize); io->regsize);
} }
static void mem_cleanup(struct smi_info *info) static void mem_cleanup(struct si_sm_io *io)
{ {
if (info->io.addr) { if (io->addr) {
iounmap(info->io.addr); iounmap(io->addr);
mem_region_cleanup(info, info->io_size); 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; int mapsize, idx;
if (!addr) if (!addr)
return -ENODEV; return -ENODEV;
info->io_cleanup = mem_cleanup; io->io_cleanup = mem_cleanup;
/* /*
* Figure out the actual readb/readw/readl/etc routine to use based * Figure out the actual readb/readw/readl/etc routine to use based
* upon the register size. * upon the register size.
*/ */
switch (info->io.regsize) { switch (io->regsize) {
case 1: case 1:
info->io.inputb = intf_mem_inb; io->inputb = intf_mem_inb;
info->io.outputb = intf_mem_outb; io->outputb = intf_mem_outb;
break; break;
case 2: case 2:
info->io.inputb = intf_mem_inw; io->inputb = intf_mem_inw;
info->io.outputb = intf_mem_outw; io->outputb = intf_mem_outw;
break; break;
case 4: case 4:
info->io.inputb = intf_mem_inl; io->inputb = intf_mem_inl;
info->io.outputb = intf_mem_outl; io->outputb = intf_mem_outl;
break; break;
#ifdef readq #ifdef readq
case 8: case 8:
info->io.inputb = mem_inq; io->inputb = mem_inq;
info->io.outputb = mem_outq; io->outputb = mem_outq;
break; break;
#endif #endif
default: default:
dev_warn(info->io.dev, "Invalid register size: %d\n", dev_warn(io->dev, "Invalid register size: %d\n",
info->io.regsize); io->regsize);
return -EINVAL; return -EINVAL;
} }
@ -1667,11 +1664,11 @@ static int mem_setup(struct smi_info *info)
* entire region. Therefore we must request each register * entire region. Therefore we must request each register
* separately. * separately.
*/ */
for (idx = 0; idx < info->io_size; idx++) { for (idx = 0; idx < io->io_size; idx++) {
if (request_mem_region(addr + idx * info->io.regspacing, if (request_mem_region(addr + idx * io->regspacing,
info->io.regsize, DEVICE_NAME) == NULL) { io->regsize, DEVICE_NAME) == NULL) {
/* Undo allocations */ /* Undo allocations */
mem_region_cleanup(info, idx); mem_region_cleanup(io, idx);
return -EIO; 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 * between the first address to the end of the last full
* register. * register.
*/ */
mapsize = ((info->io_size * info->io.regspacing) mapsize = ((io->io_size * io->regspacing)
- (info->io.regspacing - info->io.regsize)); - (io->regspacing - io->regsize));
info->io.addr = ioremap(addr, mapsize); io->addr = ioremap(addr, mapsize);
if (info->io.addr == NULL) { if (io->addr == NULL) {
mem_region_cleanup(info, info->io_size); mem_region_cleanup(io, io->io_size);
return -EIO; return -EIO;
} }
return 0; 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.si_type = si_type;
info->io.addr_data = addr; info->io.addr_data = addr;
info->io.addr_type = addr_space; 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.addr = NULL;
info->io.regspacing = regspacing; info->io.regspacing = regspacing;
@ -1987,12 +1980,10 @@ static int hardcode_find_bmc(void)
if (ports[i]) { if (ports[i]) {
/* An I/O port */ /* An I/O port */
info->io_setup = port_setup;
info->io.addr_data = ports[i]; info->io.addr_data = ports[i];
info->io.addr_type = IPMI_IO_ADDR_SPACE; info->io.addr_type = IPMI_IO_ADDR_SPACE;
} else if (addrs[i]) { } else if (addrs[i]) {
/* A memory port */ /* A memory port */
info->io_setup = mem_setup;
info->io.addr_data = addrs[i]; info->io.addr_data = addrs[i];
info->io.addr_type = IPMI_MEM_ADDR_SPACE; info->io.addr_type = IPMI_MEM_ADDR_SPACE;
} else { } else {
@ -2192,10 +2183,8 @@ static int try_init_spmi(struct SPMITable *spmi)
info->io.regshift = spmi->addr.bit_offset; info->io.regshift = spmi->addr.bit_offset;
if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
info->io_setup = mem_setup;
info->io.addr_type = IPMI_MEM_ADDR_SPACE; info->io.addr_type = IPMI_MEM_ADDR_SPACE;
} else if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_IO) { } else if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
info->io_setup = port_setup;
info->io.addr_type = IPMI_IO_ADDR_SPACE; info->io.addr_type = IPMI_IO_ADDR_SPACE;
} else { } else {
kfree(info); kfree(info);
@ -2248,15 +2237,12 @@ ipmi_get_info_from_resources(struct platform_device *pdev,
res = platform_get_resource(pdev, IORESOURCE_IO, 0); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (res) { if (res) {
info->io_setup = port_setup;
info->io.addr_type = IPMI_IO_ADDR_SPACE; info->io.addr_type = IPMI_IO_ADDR_SPACE;
} else { } else {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res) { if (res)
info->io_setup = mem_setup;
info->io.addr_type = IPMI_MEM_ADDR_SPACE; info->io.addr_type = IPMI_MEM_ADDR_SPACE;
} }
}
if (!res) { if (!res) {
dev_err(&pdev->dev, "no I/O or memory address\n"); dev_err(&pdev->dev, "no I/O or memory address\n");
return NULL; return NULL;
@ -2389,13 +2375,13 @@ static int ipmi_pci_probe_regspacing(struct smi_info *info)
info->io.regsize = DEFAULT_REGSIZE; info->io.regsize = DEFAULT_REGSIZE;
info->io.regshift = 0; info->io.regshift = 0;
info->io_size = 2; info->io.io_size = 2;
info->handlers = &kcs_smi_handlers; info->handlers = &kcs_smi_handlers;
/* detect 1, 4, 16byte spacing */ /* detect 1, 4, 16byte spacing */
for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) { for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) {
info->io.regspacing = regspacing; info->io.regspacing = regspacing;
if (info->io_setup(info)) { if (info->io.io_setup(&info->io)) {
dev_err(info->io.dev, dev_err(info->io.dev,
"Could not setup I/O space\n"); "Could not setup I/O space\n");
return DEFAULT_REGSPACING; return DEFAULT_REGSPACING;
@ -2404,7 +2390,7 @@ static int ipmi_pci_probe_regspacing(struct smi_info *info)
info->io.outputb(&info->io, 1, 0x10); info->io.outputb(&info->io, 1, 0x10);
/* read status back */ /* read status back */
status = info->io.inputb(&info->io, 1); status = info->io.inputb(&info->io, 1);
info->io_cleanup(info); info->io.io_cleanup(&info->io);
if (status) if (status)
return regspacing; return regspacing;
regspacing *= 4; 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_cleanup = ipmi_pci_cleanup;
info->io.addr_source_data = pdev; info->io.addr_source_data = pdev;
if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { if (pci_resource_flags(pdev, 0) & IORESOURCE_IO)
info->io_setup = port_setup;
info->io.addr_type = IPMI_IO_ADDR_SPACE; info->io.addr_type = IPMI_IO_ADDR_SPACE;
} else { else
info->io_setup = mem_setup;
info->io.addr_type = IPMI_MEM_ADDR_SPACE; info->io.addr_type = IPMI_MEM_ADDR_SPACE;
}
info->io.addr_data = pci_resource_start(pdev, 0); info->io.addr_data = pci_resource_start(pdev, 0);
info->io.regspacing = ipmi_pci_probe_regspacing(info); 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.addr_source = SI_DEVICETREE;
info->io.irq_setup = ipmi_std_irq_setup; info->io.irq_setup = ipmi_std_irq_setup;
if (resource.flags & IORESOURCE_IO) { if (resource.flags & IORESOURCE_IO)
info->io_setup = port_setup;
info->io.addr_type = IPMI_IO_ADDR_SPACE; info->io.addr_type = IPMI_IO_ADDR_SPACE;
} else { else
info->io_setup = mem_setup;
info->io.addr_type = IPMI_MEM_ADDR_SPACE; info->io.addr_type = IPMI_MEM_ADDR_SPACE;
}
info->io.addr_data = resource.start; 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.si_type = SI_KCS;
info->io.addr_source = SI_DEVICETREE; info->io.addr_source = SI_DEVICETREE;
info->io_setup = mem_setup;
info->io.addr_type = IPMI_MEM_ADDR_SPACE; info->io.addr_type = IPMI_MEM_ADDR_SPACE;
info->io.addr_data = dev->hpa.start; info->io.addr_data = dev->hpa.start;
info->io.regsize = 1; info->io.regsize = 1;
@ -3419,6 +3398,16 @@ int ipmi_si_add_smi(struct smi_info *new_smi)
int rv = 0; int rv = 0;
struct smi_info *dup; 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); mutex_lock(&smi_infos_lock);
dup = find_dup_si(new_smi); dup = find_dup_si(new_smi);
if (dup) { if (dup) {
@ -3522,11 +3511,11 @@ static int try_smi_init(struct smi_info *new_smi)
rv = -ENOMEM; rv = -ENOMEM;
goto out_err; goto out_err;
} }
new_smi->io_size = new_smi->handlers->init_data(new_smi->si_sm, new_smi->io.io_size = new_smi->handlers->init_data(new_smi->si_sm,
&new_smi->io); &new_smi->io);
/* Now that we know the I/O size, we can set up the I/O. */ /* 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) { if (rv) {
dev_err(new_smi->io.dev, "Could not set up I/O space\n"); dev_err(new_smi->io.dev, "Could not set up I/O space\n");
goto out_err; goto out_err;
@ -3679,9 +3668,9 @@ out_err:
new_smi->io.addr_source_cleanup(&new_smi->io); new_smi->io.addr_source_cleanup(&new_smi->io);
new_smi->io.addr_source_cleanup = NULL; new_smi->io.addr_source_cleanup = NULL;
} }
if (new_smi->io_cleanup) { if (new_smi->io.io_cleanup) {
new_smi->io_cleanup(new_smi); new_smi->io.io_cleanup(&new_smi->io);
new_smi->io_cleanup = NULL; new_smi->io.io_cleanup = NULL;
} }
if (new_smi->pdev) { 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) if (to_clean->io.addr_source_cleanup)
to_clean->io.addr_source_cleanup(&to_clean->io); to_clean->io.addr_source_cleanup(&to_clean->io);
if (to_clean->io_cleanup) if (to_clean->io.io_cleanup)
to_clean->io_cleanup(to_clean); to_clean->io.io_cleanup(&to_clean->io);
if (to_clean->pdev) if (to_clean->pdev)
platform_device_unregister(to_clean->pdev); platform_device_unregister(to_clean->pdev);

View File

@ -71,6 +71,10 @@ struct si_sm_io {
void (*addr_source_cleanup)(struct si_sm_io *io); void (*addr_source_cleanup)(struct si_sm_io *io);
void *addr_source_data; 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;
int (*irq_setup)(struct si_sm_io *io); int (*irq_setup)(struct si_sm_io *io);
void *irq_handler_data; void *irq_handler_data;