mirror of
https://github.com/torvalds/linux.git
synced 2024-12-15 07:33:56 +00:00
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:
parent
4f3e8199c3
commit
e1eeb7f862
@ -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);
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user