static int pd6729_pci_probe()

in pd6729.c [623:739]


static int pd6729_pci_probe(struct pci_dev *dev,
				      const struct pci_device_id *id)
{
	int i, j, ret;
	u_int mask;
	char configbyte;
	struct pd6729_socket *socket;

	socket = kcalloc(MAX_SOCKETS, sizeof(struct pd6729_socket),
			 GFP_KERNEL);
	if (!socket) {
		dev_warn(&dev->dev, "failed to kzalloc socket.\n");
		return -ENOMEM;
	}

	ret = pci_enable_device(dev);
	if (ret) {
		dev_warn(&dev->dev, "failed to enable pci_device.\n");
		goto err_out_free_mem;
	}

	if (!pci_resource_start(dev, 0)) {
		dev_warn(&dev->dev, "refusing to load the driver as the "
			"io_base is NULL.\n");
		ret = -ENOMEM;
		goto err_out_disable;
	}

	dev_info(&dev->dev, "Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx "
		"on irq %d\n",
		(unsigned long long)pci_resource_start(dev, 0), dev->irq);
	/*
	 * Since we have no memory BARs some firmware may not
	 * have had PCI_COMMAND_MEMORY enabled, yet the device needs it.
	 */
	pci_read_config_byte(dev, PCI_COMMAND, &configbyte);
	if (!(configbyte & PCI_COMMAND_MEMORY)) {
		dev_dbg(&dev->dev, "pd6729: Enabling PCI_COMMAND_MEMORY.\n");
		configbyte |= PCI_COMMAND_MEMORY;
		pci_write_config_byte(dev, PCI_COMMAND, configbyte);
	}

	ret = pci_request_regions(dev, "pd6729");
	if (ret) {
		dev_warn(&dev->dev, "pci request region failed.\n");
		goto err_out_disable;
	}

	if (dev->irq == NO_IRQ)
		irq_mode = 0;	/* fall back to ISA interrupt mode */

	mask = pd6729_isa_scan();
	if (irq_mode == 0 && mask == 0) {
		dev_warn(&dev->dev, "no ISA interrupt is available.\n");
		ret = -ENODEV;
		goto err_out_free_res;
	}

	for (i = 0; i < MAX_SOCKETS; i++) {
		socket[i].io_base = pci_resource_start(dev, 0);
		socket[i].socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD;
		socket[i].socket.map_size = 0x1000;
		socket[i].socket.irq_mask = mask;
		socket[i].socket.pci_irq  = dev->irq;
		socket[i].socket.cb_dev = dev;
		socket[i].socket.owner = THIS_MODULE;

		socket[i].number = i;

		socket[i].socket.ops = &pd6729_operations;
		socket[i].socket.resource_ops = &pccard_nonstatic_ops;
		socket[i].socket.dev.parent = &dev->dev;
		socket[i].socket.driver_data = &socket[i];
	}

	pci_set_drvdata(dev, socket);
	if (irq_mode == 1) {
		/* Register the interrupt handler */
		ret = request_irq(dev->irq, pd6729_interrupt, IRQF_SHARED,
				  "pd6729", socket);
		if (ret) {
			dev_err(&dev->dev, "Failed to register irq %d\n",
				dev->irq);
			goto err_out_free_res;
		}
	} else {
		/* poll Card status change */
		timer_setup(&socket->poll_timer, pd6729_interrupt_wrapper, 0);
		mod_timer(&socket->poll_timer, jiffies + HZ);
	}

	for (i = 0; i < MAX_SOCKETS; i++) {
		ret = pcmcia_register_socket(&socket[i].socket);
		if (ret) {
			dev_warn(&dev->dev, "pcmcia_register_socket failed.\n");
			for (j = 0; j < i ; j++)
				pcmcia_unregister_socket(&socket[j].socket);
			goto err_out_free_res2;
		}
	}

	return 0;

err_out_free_res2:
	if (irq_mode == 1)
		free_irq(dev->irq, socket);
	else
		del_timer_sync(&socket->poll_timer);
err_out_free_res:
	pci_release_regions(dev);
err_out_disable:
	pci_disable_device(dev);

err_out_free_mem:
	kfree(socket);
	return ret;
}