Commit af757923 authored by Dominik Brodowski's avatar Dominik Brodowski

ipwireless: make more use of pcmcia_loop_config()

Within the pcmcia_loop_config() callback, we already have all
tuple data available we need. Also add a fix to release the IO
resource (at least within pcmcia_loop_config() error path).

CC: Jiri Kosina <jkosina@suse.cz>
CC: David Sterba <dsterba@suse.cz>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent aaa8cfda
...@@ -79,12 +79,18 @@ static void signalled_reboot_callback(void *callback_data) ...@@ -79,12 +79,18 @@ static void signalled_reboot_callback(void *callback_data)
schedule_work(&ipw->work_reboot); schedule_work(&ipw->work_reboot);
} }
static int ipwireless_ioprobe(struct pcmcia_device *p_dev, static int ipwireless_probe(struct pcmcia_device *p_dev,
cistpl_cftable_entry_t *cfg, cistpl_cftable_entry_t *cfg,
cistpl_cftable_entry_t *dflt, cistpl_cftable_entry_t *dflt,
unsigned int vcc, unsigned int vcc,
void *priv_data) void *priv_data)
{ {
struct ipw_dev *ipw = priv_data;
struct resource *io_resource;
memreq_t memreq_attr_memory;
memreq_t memreq_common_memory;
int ret;
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
p_dev->io.BasePort1 = cfg->io.win[0].base; p_dev->io.BasePort1 = cfg->io.win[0].base;
p_dev->io.NumPorts1 = cfg->io.win[0].len; p_dev->io.NumPorts1 = cfg->io.win[0].len;
...@@ -95,102 +101,50 @@ static int ipwireless_ioprobe(struct pcmcia_device *p_dev, ...@@ -95,102 +101,50 @@ static int ipwireless_ioprobe(struct pcmcia_device *p_dev,
/* 0x40 causes it to generate level mode interrupts. */ /* 0x40 causes it to generate level mode interrupts. */
/* 0x04 enables IREQ pin. */ /* 0x04 enables IREQ pin. */
p_dev->conf.ConfigIndex = cfg->index | 0x44; p_dev->conf.ConfigIndex = cfg->index | 0x44;
return pcmcia_request_io(p_dev, &p_dev->io); ret = pcmcia_request_io(p_dev, &p_dev->io);
} if (ret)
return ret;
static int config_ipwireless(struct ipw_dev *ipw)
{
struct pcmcia_device *link = ipw->link;
int ret = 0;
tuple_t tuple;
unsigned short buf[64];
cisparse_t parse;
memreq_t memreq_attr_memory;
memreq_t memreq_common_memory;
ipw->is_v2_card = 0;
tuple.Attributes = 0;
tuple.TupleData = (cisdata_t *) buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
ret = pcmcia_loop_config(link, ipwireless_ioprobe, NULL);
if (ret != 0) {
cs_error(link, RequestIO, ret);
goto exit0;
}
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.Handler = ipwireless_interrupt;
link->irq.Instance = ipw->hardware;
request_region(link->io.BasePort1, link->io.NumPorts1, io_resource = request_region(p_dev->io.BasePort1, p_dev->io.NumPorts1,
IPWIRELESS_PCCARD_NAME); IPWIRELESS_PCCARD_NAME);
/* memory settings */ if (cfg->mem.nwin == 0)
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; return 0;
ret = pcmcia_get_first_tuple(link, &tuple);
if (ret != 0) {
cs_error(link, GetFirstTuple, ret);
goto exit1;
}
ret = pcmcia_get_tuple_data(link, &tuple);
if (ret != 0) {
cs_error(link, GetTupleData, ret);
goto exit1;
}
ret = pcmcia_parse_tuple(&tuple, &parse);
if (ret != 0) {
cs_error(link, ParseTuple, ret);
goto exit1;
}
if (parse.cftable_entry.mem.nwin > 0) {
ipw->request_common_memory.Attributes = ipw->request_common_memory.Attributes =
WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
ipw->request_common_memory.Base = ipw->request_common_memory.Base = cfg->mem.win[0].host_addr;
parse.cftable_entry.mem.win[0].host_addr; ipw->request_common_memory.Size = cfg->mem.win[0].len;
ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len;
if (ipw->request_common_memory.Size < 0x1000) if (ipw->request_common_memory.Size < 0x1000)
ipw->request_common_memory.Size = 0x1000; ipw->request_common_memory.Size = 0x1000;
ipw->request_common_memory.AccessSpeed = 0; ipw->request_common_memory.AccessSpeed = 0;
ret = pcmcia_request_window(&link, &ipw->request_common_memory, ret = pcmcia_request_window(&p_dev, &ipw->request_common_memory,
&ipw->handle_common_memory); &ipw->handle_common_memory);
if (ret != 0) { if (ret != 0) {
cs_error(link, RequestWindow, ret); cs_error(p_dev, RequestWindow, ret);
goto exit1; goto exit1;
} }
memreq_common_memory.CardOffset = memreq_common_memory.CardOffset = cfg->mem.win[0].card_addr;
parse.cftable_entry.mem.win[0].card_addr;
memreq_common_memory.Page = 0; memreq_common_memory.Page = 0;
ret = pcmcia_map_mem_page(ipw->handle_common_memory, ret = pcmcia_map_mem_page(ipw->handle_common_memory,
&memreq_common_memory); &memreq_common_memory);
if (ret != 0) { if (ret != 0) {
cs_error(link, MapMemPage, ret); cs_error(p_dev, MapMemPage, ret);
goto exit1; goto exit2;
} }
ipw->is_v2_card = ipw->is_v2_card = cfg->mem.win[0].len == 0x100;
parse.cftable_entry.mem.win[0].len == 0x100;
ipw->common_memory = ioremap(ipw->request_common_memory.Base, ipw->common_memory = ioremap(ipw->request_common_memory.Base,
ipw->request_common_memory.Size); ipw->request_common_memory.Size);
request_mem_region(ipw->request_common_memory.Base, request_mem_region(ipw->request_common_memory.Base,
ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME); ipw->request_common_memory.Size,
IPWIRELESS_PCCARD_NAME);
ipw->request_attr_memory.Attributes = ipw->request_attr_memory.Attributes =
WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
...@@ -198,11 +152,11 @@ static int config_ipwireless(struct ipw_dev *ipw) ...@@ -198,11 +152,11 @@ static int config_ipwireless(struct ipw_dev *ipw)
ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */
ipw->request_attr_memory.AccessSpeed = 0; ipw->request_attr_memory.AccessSpeed = 0;
ret = pcmcia_request_window(&link, &ipw->request_attr_memory, ret = pcmcia_request_window(&p_dev, &ipw->request_attr_memory,
&ipw->handle_attr_memory); &ipw->handle_attr_memory);
if (ret != 0) { if (ret != 0) {
cs_error(link, RequestWindow, ret); cs_error(p_dev, RequestWindow, ret);
goto exit2; goto exit2;
} }
...@@ -213,16 +167,53 @@ static int config_ipwireless(struct ipw_dev *ipw) ...@@ -213,16 +167,53 @@ static int config_ipwireless(struct ipw_dev *ipw)
&memreq_attr_memory); &memreq_attr_memory);
if (ret != 0) { if (ret != 0) {
cs_error(link, MapMemPage, ret); cs_error(p_dev, MapMemPage, ret);
goto exit2; goto exit3;
} }
ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, ipw->attr_memory = ioremap(ipw->request_attr_memory.Base,
ipw->request_attr_memory.Size); ipw->request_attr_memory.Size);
request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size, request_mem_region(ipw->request_attr_memory.Base,
IPWIRELESS_PCCARD_NAME); ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME);
return 0;
exit3:
pcmcia_release_window(ipw->handle_attr_memory);
exit2:
if (ipw->common_memory) {
release_mem_region(ipw->request_common_memory.Base,
ipw->request_common_memory.Size);
iounmap(ipw->common_memory);
pcmcia_release_window(ipw->handle_common_memory);
} else
pcmcia_release_window(ipw->handle_common_memory);
exit1:
release_resource(io_resource);
pcmcia_disable_device(p_dev);
return -1;
}
static int config_ipwireless(struct ipw_dev *ipw)
{
struct pcmcia_device *link = ipw->link;
int ret = 0;
ipw->is_v2_card = 0;
ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
if (ret != 0) {
cs_error(link, RequestIO, ret);
return ret;
} }
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.Handler = ipwireless_interrupt;
link->irq.Instance = ipw->hardware;
INIT_WORK(&ipw->work_reboot, signalled_reboot_work); INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
ipwireless_init_hardware_v1(ipw->hardware, link->io.BasePort1, ipwireless_init_hardware_v1(ipw->hardware, link->io.BasePort1,
...@@ -234,7 +225,7 @@ static int config_ipwireless(struct ipw_dev *ipw) ...@@ -234,7 +225,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
if (ret != 0) { if (ret != 0) {
cs_error(link, RequestIRQ, ret); cs_error(link, RequestIRQ, ret);
goto exit3; goto exit;
} }
printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
...@@ -257,12 +248,12 @@ static int config_ipwireless(struct ipw_dev *ipw) ...@@ -257,12 +248,12 @@ static int config_ipwireless(struct ipw_dev *ipw)
ipw->network = ipwireless_network_create(ipw->hardware); ipw->network = ipwireless_network_create(ipw->hardware);
if (!ipw->network) if (!ipw->network)
goto exit3; goto exit;
ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network, ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network,
ipw->nodes); ipw->nodes);
if (!ipw->tty) if (!ipw->tty)
goto exit3; goto exit;
ipwireless_init_hardware_v2_v3(ipw->hardware); ipwireless_init_hardware_v2_v3(ipw->hardware);
...@@ -274,33 +265,27 @@ static int config_ipwireless(struct ipw_dev *ipw) ...@@ -274,33 +265,27 @@ static int config_ipwireless(struct ipw_dev *ipw)
if (ret != 0) { if (ret != 0) {
cs_error(link, RequestConfiguration, ret); cs_error(link, RequestConfiguration, ret);
goto exit4; goto exit;
} }
link->dev_node = &ipw->nodes[0]; link->dev_node = &ipw->nodes[0];
return 0; return 0;
exit4: exit:
pcmcia_disable_device(link);
exit3:
if (ipw->attr_memory) { if (ipw->attr_memory) {
release_mem_region(ipw->request_attr_memory.Base, release_mem_region(ipw->request_attr_memory.Base,
ipw->request_attr_memory.Size); ipw->request_attr_memory.Size);
iounmap(ipw->attr_memory); iounmap(ipw->attr_memory);
pcmcia_release_window(ipw->handle_attr_memory); pcmcia_release_window(ipw->handle_attr_memory);
pcmcia_disable_device(link);
} }
exit2:
if (ipw->common_memory) { if (ipw->common_memory) {
release_mem_region(ipw->request_common_memory.Base, release_mem_region(ipw->request_common_memory.Base,
ipw->request_common_memory.Size); ipw->request_common_memory.Size);
iounmap(ipw->common_memory); iounmap(ipw->common_memory);
pcmcia_release_window(ipw->handle_common_memory); pcmcia_release_window(ipw->handle_common_memory);
} }
exit1:
pcmcia_disable_device(link); pcmcia_disable_device(link);
exit0:
return -1; return -1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment