Commit af757923 authored by Dominik Brodowski's avatar Dominik Brodowski
Browse files

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
Loading
Loading
Loading
Loading
+99 −114
Original line number Diff line number Diff line
@@ -79,12 +79,18 @@ static void signalled_reboot_callback(void *callback_data)
	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 *dflt,
			    unsigned int vcc,
			    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.BasePort1 = cfg->io.win[0].base;
	p_dev->io.NumPorts1 = cfg->io.win[0].len;
@@ -95,102 +101,50 @@ static int ipwireless_ioprobe(struct pcmcia_device *p_dev,
	/* 0x40 causes it to generate level mode interrupts. */
	/* 0x04 enables IREQ pin. */
	p_dev->conf.ConfigIndex = cfg->index | 0x44;
	return pcmcia_request_io(p_dev, &p_dev->io);
}

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;
	ret = pcmcia_request_io(p_dev, &p_dev->io);
	if (ret)
		return ret;

	request_region(link->io.BasePort1, link->io.NumPorts1,
	io_resource = request_region(p_dev->io.BasePort1, p_dev->io.NumPorts1,
				IPWIRELESS_PCCARD_NAME);

	/* memory settings */
	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;

	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 (cfg->mem.nwin == 0)
		return 0;

	if (parse.cftable_entry.mem.nwin > 0) {
	ipw->request_common_memory.Attributes =
		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
		ipw->request_common_memory.Base =
			parse.cftable_entry.mem.win[0].host_addr;
		ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len;
	ipw->request_common_memory.Base = cfg->mem.win[0].host_addr;
	ipw->request_common_memory.Size = cfg->mem.win[0].len;
	if (ipw->request_common_memory.Size < 0x1000)
		ipw->request_common_memory.Size = 0x1000;
	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);

	if (ret != 0) {
			cs_error(link, RequestWindow, ret);
		cs_error(p_dev, RequestWindow, ret);
		goto exit1;
	}

		memreq_common_memory.CardOffset =
			parse.cftable_entry.mem.win[0].card_addr;
	memreq_common_memory.CardOffset = cfg->mem.win[0].card_addr;
	memreq_common_memory.Page = 0;

	ret = pcmcia_map_mem_page(ipw->handle_common_memory,
				&memreq_common_memory);

	if (ret != 0) {
			cs_error(link, MapMemPage, ret);
			goto exit1;
		cs_error(p_dev, MapMemPage, ret);
		goto exit2;
	}

		ipw->is_v2_card =
			parse.cftable_entry.mem.win[0].len == 0x100;
	ipw->is_v2_card = cfg->mem.win[0].len == 0x100;

	ipw->common_memory = ioremap(ipw->request_common_memory.Base,
				ipw->request_common_memory.Size);
	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 =
		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
@@ -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.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);

	if (ret != 0) {
			cs_error(link, RequestWindow, ret);
		cs_error(p_dev, RequestWindow, ret);
		goto exit2;
	}

@@ -213,16 +167,53 @@ static int config_ipwireless(struct ipw_dev *ipw)
				&memreq_attr_memory);

	if (ret != 0) {
			cs_error(link, MapMemPage, ret);
			goto exit2;
		cs_error(p_dev, MapMemPage, ret);
		goto exit3;
	}

	ipw->attr_memory = ioremap(ipw->request_attr_memory.Base,
				ipw->request_attr_memory.Size);
		request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size,
				IPWIRELESS_PCCARD_NAME);
	request_mem_region(ipw->request_attr_memory.Base,
			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);

	ipwireless_init_hardware_v1(ipw->hardware, link->io.BasePort1,
@@ -234,7 +225,7 @@ static int config_ipwireless(struct ipw_dev *ipw)

	if (ret != 0) {
		cs_error(link, RequestIRQ, ret);
		goto exit3;
		goto exit;
	}

	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
@@ -257,12 +248,12 @@ static int config_ipwireless(struct ipw_dev *ipw)

	ipw->network = ipwireless_network_create(ipw->hardware);
	if (!ipw->network)
		goto exit3;
		goto exit;

	ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network,
			ipw->nodes);
	if (!ipw->tty)
		goto exit3;
		goto exit;

	ipwireless_init_hardware_v2_v3(ipw->hardware);

@@ -274,33 +265,27 @@ static int config_ipwireless(struct ipw_dev *ipw)

	if (ret != 0) {
		cs_error(link, RequestConfiguration, ret);
		goto exit4;
		goto exit;
	}

	link->dev_node = &ipw->nodes[0];

	return 0;

exit4:
	pcmcia_disable_device(link);
exit3:
exit:
	if (ipw->attr_memory) {
		release_mem_region(ipw->request_attr_memory.Base,
				ipw->request_attr_memory.Size);
		iounmap(ipw->attr_memory);
		pcmcia_release_window(ipw->handle_attr_memory);
		pcmcia_disable_device(link);
	}
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);
	}
exit1:
	pcmcia_disable_device(link);
exit0:
	return -1;
}