Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e1eeb7f8 authored by Corey Minyard's avatar Corey Minyard
Browse files

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: default avatarCorey Minyard <cminyard@mvista.com>
parent 4f3e8199
Loading
Loading
Loading
Loading
+81 −92
Original line number Original line Diff line number Diff line
@@ -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 @@ static int try_smi_init(struct smi_info *new_smi)
		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);
+4 −0
Original line number Original line Diff line number Diff line
@@ -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;