Commit b884c872 authored by Pavel Roskin's avatar Pavel Roskin Committed by John W. Linville
Browse files

[PATCH] orinoco: reduce differences between PCI drivers, create orinoco_pci.h



Make all Orinoco PCI drivers (orinoco_pci, orinoco_plx, orinoco_tmd and
orinoco_nortel) as similar as possible.  Use the best implementation of
error handling, the best error messages, the best comments.

Put common code to orinoco_pci.h.  For now, it's suspend and resume
functions and function for registering the network device.

Signed-off-by: default avatarPavel Roskin <proski@gnu.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c6fb2e9a
Loading
Loading
Loading
Loading
+87 −153
Original line number Diff line number Diff line
@@ -50,17 +50,12 @@
#include <pcmcia/cisreg.h>

#include "orinoco.h"
#include "orinoco_pci.h"

#define COR_OFFSET    (0xe0)	/* COR attribute offset of Prism2 PC card */
#define COR_VALUE     (COR_LEVEL_REQ | COR_FUNC_ENA)	/* Enable PC card with interrupt in level trigger */


/* Nortel specific data */
struct nortel_pci_card {
	unsigned long iobase1;
	unsigned long iobase2;
};

/*
 * Do a soft reset of the PCI card using the Configuration Option Register
 * We need this to get going...
@@ -69,48 +64,48 @@ struct nortel_pci_card {
 * Note bis : Don't try to access HERMES_CMD during the reset phase.
 * It just won't work !
 */
static int nortel_pci_cor_reset(struct orinoco_private *priv)
static int orinoco_nortel_cor_reset(struct orinoco_private *priv)
{
	struct nortel_pci_card *card = priv->card;
	struct orinoco_pci_card *card = priv->card;

	/* Assert the reset until the card notice */
	outw_p(8, card->iobase1 + 2);
	inw(card->iobase2 + COR_OFFSET);
	outw_p(0x80, card->iobase2 + COR_OFFSET);
	iowrite16(8, card->bridge_io + 2);
	ioread16(card->attr_io + COR_OFFSET);
	iowrite16(0x80, card->attr_io + COR_OFFSET);
	mdelay(1);

	/* Give time for the card to recover from this hard effort */
	outw_p(0, card->iobase2 + COR_OFFSET);
	outw_p(0, card->iobase2 + COR_OFFSET);
	iowrite16(0, card->attr_io + COR_OFFSET);
	iowrite16(0, card->attr_io + COR_OFFSET);
	mdelay(1);

	/* set COR as usual */
	outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
	outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
	/* Set COR as usual */
	iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
	iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
	mdelay(1);

	outw_p(0x228, card->iobase1 + 2);
	iowrite16(0x228, card->bridge_io + 2);

	return 0;
}

static int nortel_pci_hw_init(struct nortel_pci_card *card)
static int orinoco_nortel_hw_init(struct orinoco_pci_card *card)
{
	int i;
	u32 reg;

	/* setup bridge */
	if (inw(card->iobase1) & 1) {
	/* Setup bridge */
	if (ioread16(card->bridge_io) & 1) {
		printk(KERN_ERR PFX "brg1 answer1 wrong\n");
		return -EBUSY;
	}
	outw_p(0x118, card->iobase1 + 2);
	outw_p(0x108, card->iobase1 + 2);
	iowrite16(0x118, card->bridge_io + 2);
	iowrite16(0x108, card->bridge_io + 2);
	mdelay(30);
	outw_p(0x8, card->iobase1 + 2);
	iowrite16(0x8, card->bridge_io + 2);
	for (i = 0; i < 30; i++) {
		mdelay(30);
		if (inw(card->iobase1) & 0x10) {
		if (ioread16(card->bridge_io) & 0x10) {
			break;
		}
	}
@@ -118,42 +113,42 @@ static int nortel_pci_hw_init(struct nortel_pci_card *card)
		printk(KERN_ERR PFX "brg1 timed out\n");
		return -EBUSY;
	}
	if (inw(card->iobase2 + 0xe0) & 1) {
	if (ioread16(card->attr_io + COR_OFFSET) & 1) {
		printk(KERN_ERR PFX "brg2 answer1 wrong\n");
		return -EBUSY;
	}
	if (inw(card->iobase2 + 0xe2) & 1) {
	if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) {
		printk(KERN_ERR PFX "brg2 answer2 wrong\n");
		return -EBUSY;
	}
	if (inw(card->iobase2 + 0xe4) & 1) {
	if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) {
		printk(KERN_ERR PFX "brg2 answer3 wrong\n");
		return -EBUSY;
	}

	/* set the PCMCIA COR-Register */
	outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
	/* Set the PCMCIA COR-Register */
	iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
	mdelay(1);
	reg = inw(card->iobase2 + COR_OFFSET);
	reg = ioread16(card->attr_io + COR_OFFSET);
	if (reg != COR_VALUE) {
		printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n",
		       reg);
		return -EBUSY;
	}

	/* set leds */
	outw_p(1, card->iobase1 + 10);
	/* Set LEDs */
	iowrite16(1, card->bridge_io + 10);
	return 0;
}

static int nortel_pci_init_one(struct pci_dev *pdev,
static int orinoco_nortel_init_one(struct pci_dev *pdev,
				   const struct pci_device_id *ent)
{
	int err;
	struct orinoco_private *priv;
	struct nortel_pci_card *card;
	struct orinoco_pci_card *card;
	struct net_device *dev;
	void __iomem *iomem;
	void __iomem *hermes_io, *bridge_io, *attr_io;

	err = pci_enable_device(pdev);
	if (err) {
@@ -162,19 +157,34 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
	}

	err = pci_request_regions(pdev, DRIVER_NAME);
	if (err != 0) {
	if (err) {
		printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
		goto fail_resources;
	}

	iomem = pci_iomap(pdev, 2, 0);
	if (!iomem) {
		err = -ENOMEM;
		goto fail_map_io;
	bridge_io = pci_iomap(pdev, 0, 0);
	if (!bridge_io) {
		printk(KERN_ERR PFX "Cannot map bridge registers\n");
		err = -EIO;
		goto fail_map_bridge;
	}

	attr_io = pci_iomap(pdev, 1, 0);
	if (!attr_io) {
		printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
		err = -EIO;
		goto fail_map_attr;
	}

	hermes_io = pci_iomap(pdev, 2, 0);
	if (!hermes_io) {
		printk(KERN_ERR PFX "Cannot map chipset registers\n");
		err = -EIO;
		goto fail_map_hermes;
	}

	/* Allocate network device */
	dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset);
	dev = alloc_orinocodev(sizeof(*card), orinoco_nortel_cor_reset);
	if (!dev) {
		printk(KERN_ERR PFX "Cannot allocate network device\n");
		err = -ENOMEM;
@@ -183,16 +193,12 @@ static int nortel_pci_init_one(struct pci_dev *pdev,

	priv = netdev_priv(dev);
	card = priv->card;
	card->iobase1 = pci_resource_start(pdev, 0);
	card->iobase2 = pci_resource_start(pdev, 1);
	dev->base_addr = pci_resource_start(pdev, 2);
	card->bridge_io = bridge_io;
	card->attr_io = attr_io;
	SET_MODULE_OWNER(dev);
	SET_NETDEV_DEV(dev, &pdev->dev);

	hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING);

	printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, "
	       "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr);
	hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);

	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
			  dev->name, dev);
@@ -201,21 +207,20 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
		err = -EBUSY;
		goto fail_irq;
	}
	dev->irq = pdev->irq;
	orinoco_pci_setup_netdev(dev, pdev, 2);

	err = nortel_pci_hw_init(card);
	err = orinoco_nortel_hw_init(card);
	if (err) {
		printk(KERN_ERR PFX "Hardware initialization failed\n");
		goto fail;
	}

	err = nortel_pci_cor_reset(priv);
	err = orinoco_nortel_cor_reset(priv);
	if (err) {
		printk(KERN_ERR PFX "Initial reset failed\n");
		goto fail;
	}


	err = register_netdev(dev);
	if (err) {
		printk(KERN_ERR PFX "Cannot register network device\n");
@@ -234,9 +239,15 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
	free_orinocodev(dev);

 fail_alloc:
	pci_iounmap(pdev, iomem);
	pci_iounmap(pdev, hermes_io);

 fail_map_hermes:
	pci_iounmap(pdev, attr_io);

 fail_map_attr:
	pci_iounmap(pdev, bridge_io);

 fail_map_io:
 fail_map_bridge:
	pci_release_regions(pdev);

 fail_resources:
@@ -245,103 +256,27 @@ static int nortel_pci_init_one(struct pci_dev *pdev,
	return err;
}

static void __devexit nortel_pci_remove_one(struct pci_dev *pdev)
static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev)
{
	struct net_device *dev = pci_get_drvdata(pdev);
	struct orinoco_private *priv = netdev_priv(dev);
	struct nortel_pci_card *card = priv->card;
	struct orinoco_pci_card *card = priv->card;

	/* clear leds */
	outw_p(0, card->iobase1 + 10);
	/* Clear LEDs */
	iowrite16(0, card->bridge_io + 10);

	unregister_netdev(dev);
	free_irq(dev->irq, dev);
	pci_set_drvdata(pdev, NULL);
	free_orinocodev(dev);
	pci_iounmap(pdev, priv->hw.iobase);
	pci_iounmap(pdev, card->attr_io);
	pci_iounmap(pdev, card->bridge_io);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
}

static int orinoco_nortel_suspend(struct pci_dev *pdev, pm_message_t state)
{
	struct net_device *dev = pci_get_drvdata(pdev);
	struct orinoco_private *priv = netdev_priv(dev);
	unsigned long flags;
	int err;

	err = orinoco_lock(priv, &flags);
	if (err) {
		printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
		       dev->name);
		return err;
	}

	err = __orinoco_down(dev);
	if (err)
		printk(KERN_WARNING "%s: error %d bringing interface down "
		       "for suspend\n", dev->name, err);
	
	netif_device_detach(dev);

	priv->hw_unavailable++;
	
	orinoco_unlock(priv, &flags);

	free_irq(pdev->irq, dev);
	pci_save_state(pdev);
	pci_disable_device(pdev);
	pci_set_power_state(pdev, PCI_D3hot);

	return 0;
}

static int orinoco_nortel_resume(struct pci_dev *pdev)
{
	struct net_device *dev = pci_get_drvdata(pdev);
	struct orinoco_private *priv = netdev_priv(dev);
	unsigned long flags;
	int err;

	pci_set_power_state(pdev, 0);
	pci_enable_device(pdev);
	pci_restore_state(pdev);

	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
			  dev->name, dev);
	if (err) {
		printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
		       dev->name);
		pci_disable_device(pdev);
		return -EBUSY;
	}

	err = orinoco_reinit_firmware(dev);
	if (err) {
		printk(KERN_ERR "%s: error %d re-initializing firmware "
		       "on resume\n", dev->name, err);
		return err;
	}

	spin_lock_irqsave(&priv->lock, flags);

	netif_device_attach(dev);

	priv->hw_unavailable--;

	if (priv->open && (! priv->hw_unavailable)) {
		err = __orinoco_up(dev);
		if (err)
			printk(KERN_ERR "%s: Error %d restarting card on resume\n",
			       dev->name, err);
	}
	
	spin_unlock_irqrestore(&priv->lock, flags);

	return 0;
}

static struct pci_device_id nortel_pci_id_table[] = {
static struct pci_device_id orinoco_nortel_id_table[] = {
	/* Nortel emobility PCI */
	{0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
	/* Symbol LA-4123 PCI */
@@ -349,15 +284,15 @@ static struct pci_device_id nortel_pci_id_table[] = {
	{0,},
};

MODULE_DEVICE_TABLE(pci, nortel_pci_id_table);
MODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table);

static struct pci_driver nortel_pci_driver = {
static struct pci_driver orinoco_nortel_driver = {
	.name		= DRIVER_NAME,
	.id_table	= nortel_pci_id_table,
	.probe		= nortel_pci_init_one,
	.remove		= __devexit_p(nortel_pci_remove_one),
	.suspend	= orinoco_nortel_suspend,
	.resume		= orinoco_nortel_resume,
	.id_table	= orinoco_nortel_id_table,
	.probe		= orinoco_nortel_init_one,
	.remove		= __devexit_p(orinoco_nortel_remove_one),
	.suspend	= orinoco_pci_suspend,
	.resume		= orinoco_pci_resume,
};

static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
@@ -367,20 +302,19 @@ MODULE_DESCRIPTION
    ("Driver for wireless LAN cards using the Nortel PCI bridge");
MODULE_LICENSE("Dual MPL/GPL");

static int __init nortel_pci_init(void)
static int __init orinoco_nortel_init(void)
{
	printk(KERN_DEBUG "%s\n", version);
	return pci_module_init(&nortel_pci_driver);
	return pci_module_init(&orinoco_nortel_driver);
}

static void __exit nortel_pci_exit(void)
static void __exit orinoco_nortel_exit(void)
{
	pci_unregister_driver(&nortel_pci_driver);
	ssleep(1);
	pci_unregister_driver(&orinoco_nortel_driver);
}

module_init(nortel_pci_init);
module_exit(nortel_pci_exit);
module_init(orinoco_nortel_init);
module_exit(orinoco_nortel_exit);

/*
 * Local variables:
+24 −120
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@
#include <linux/pci.h>

#include "orinoco.h"
#include "orinoco_pci.h"

/* All the magic there is from wlan-ng */
/* Magic offset of the reset register of the PCI card */
@@ -113,11 +114,6 @@
#define HERMES_PCI_COR_OFFT	(500)		/* ms */
#define HERMES_PCI_COR_BUSYT	(500)		/* ms */

/* Orinoco PCI specific data */
struct orinoco_pci_card {
	void __iomem *pci_ioaddr;
};

/*
 * Do a soft reset of the PCI card using the Configuration Option Register
 * We need this to get going...
@@ -131,8 +127,7 @@ struct orinoco_pci_card {
 * Note bis : Don't try to access HERMES_CMD during the reset phase.
 * It just won't work !
 */
static int
orinoco_pci_cor_reset(struct orinoco_private *priv)
static int orinoco_pci_cor_reset(struct orinoco_private *priv)
{
	hermes_t *hw = &priv->hw;
	unsigned long timeout;
@@ -163,17 +158,14 @@ orinoco_pci_cor_reset(struct orinoco_private *priv)
	return 0;
}

/*
 * Initialise a card. Mostly similar to PLX code.
 */
static int orinoco_pci_init_one(struct pci_dev *pdev,
				const struct pci_device_id *ent)
{
	int err = 0;
	void __iomem *pci_ioaddr = NULL;
	struct orinoco_private *priv = NULL;
	int err;
	struct orinoco_private *priv;
	struct orinoco_pci_card *card;
	struct net_device *dev = NULL;
	struct net_device *dev;
	void __iomem *hermes_io;

	err = pci_enable_device(pdev);
	if (err) {
@@ -182,38 +174,32 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
	}

	err = pci_request_regions(pdev, DRIVER_NAME);
	if (err != 0) {
	if (err) {
		printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
		goto fail_resources;
	}

	/* Resource 0 is mapped to the hermes registers */
	pci_ioaddr = pci_iomap(pdev, 0, 0);
	if (!pci_ioaddr) {
	hermes_io = pci_iomap(pdev, 0, 0);
	if (!hermes_io) {
		printk(KERN_ERR PFX "Cannot remap chipset registers\n");
		err = -EIO;
		printk(KERN_ERR PFX "Cannot remap hardware registers\n");
		goto fail_map;
		goto fail_map_hermes;
	}

	/* Allocate network device */
	dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset);
	if (!dev) {
		printk(KERN_ERR PFX "Cannot allocate network device\n");
		err = -ENOMEM;
		goto fail_alloc;
	}

	priv = netdev_priv(dev);
	card = priv->card;
	card->pci_ioaddr = pci_ioaddr;
	dev->mem_start = pci_resource_start(pdev, 0);
	dev->mem_end = dev->mem_start + pci_resource_len(pdev, 0) - 1;
	SET_MODULE_OWNER(dev);
	SET_NETDEV_DEV(dev, &pdev->dev);

	hermes_struct_init(&priv->hw, pci_ioaddr, HERMES_32BIT_REGSPACING);

	printk(KERN_DEBUG PFX "Detected device %s, mem:0x%lx-0x%lx, irq %d\n",
	       pci_name(pdev), dev->mem_start, dev->mem_end, pdev->irq);
	hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING);

	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
			  dev->name, dev);
@@ -222,9 +208,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
		err = -EBUSY;
		goto fail_irq;
	}
	dev->irq = pdev->irq;
	orinoco_pci_setup_netdev(dev, pdev, 0);

	/* Perform a COR reset to start the card */
	err = orinoco_pci_cor_reset(priv);
	if (err) {
		printk(KERN_ERR PFX "Initial reset failed\n");
@@ -233,7 +218,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,

	err = register_netdev(dev);
	if (err) {
		printk(KERN_ERR PFX "Failed to register net device\n");
		printk(KERN_ERR PFX "Cannot register network device\n");
		goto fail;
	}

@@ -249,9 +234,9 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
	free_orinocodev(dev);

 fail_alloc:
	iounmap(pci_ioaddr);
	pci_iounmap(pdev, hermes_io);

 fail_map:
 fail_map_hermes:
	pci_release_regions(pdev);

 fail_resources:
@@ -264,98 +249,17 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
{
	struct net_device *dev = pci_get_drvdata(pdev);
	struct orinoco_private *priv = netdev_priv(dev);
	struct orinoco_pci_card *card = priv->card;

	unregister_netdev(dev);
	free_irq(dev->irq, dev);
	pci_set_drvdata(pdev, NULL);
	free_orinocodev(dev);
	iounmap(card->pci_ioaddr);
	pci_iounmap(pdev, priv->hw.iobase);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
}

static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
	struct net_device *dev = pci_get_drvdata(pdev);
	struct orinoco_private *priv = netdev_priv(dev);
	unsigned long flags;
	int err;
	

	err = orinoco_lock(priv, &flags);
	if (err) {
		printk(KERN_ERR "%s: hw_unavailable on orinoco_pci_suspend\n",
		       dev->name);
		return err;
	}

	err = __orinoco_down(dev);
	if (err)
		printk(KERN_WARNING "%s: orinoco_pci_suspend(): Error %d downing interface\n",
		       dev->name, err);
	
	netif_device_detach(dev);

	priv->hw_unavailable++;
	
	orinoco_unlock(priv, &flags);

	free_irq(pdev->irq, dev);
	pci_save_state(pdev);
	pci_disable_device(pdev);
	pci_set_power_state(pdev, PCI_D3hot);

	return 0;
}

static int orinoco_pci_resume(struct pci_dev *pdev)
{
	struct net_device *dev = pci_get_drvdata(pdev);
	struct orinoco_private *priv = netdev_priv(dev);
	unsigned long flags;
	int err;

	printk(KERN_DEBUG "%s: Orinoco-PCI waking up\n", dev->name);

	pci_set_power_state(pdev, 0);
	pci_enable_device(pdev);
	pci_restore_state(pdev);

	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
			  dev->name, dev);
	if (err) {
		printk(KERN_ERR "%s: Cannot re-allocate IRQ\n", dev->name);
		pci_disable_device(pdev);
		return -EBUSY;
	}

	err = orinoco_reinit_firmware(dev);
	if (err) {
		printk(KERN_ERR "%s: Error %d re-initializing firmware on orinoco_pci_resume()\n",
		       dev->name, err);
		return err;
	}

	spin_lock_irqsave(&priv->lock, flags);

	netif_device_attach(dev);

	priv->hw_unavailable--;

	if (priv->open && (! priv->hw_unavailable)) {
		err = __orinoco_up(dev);
		if (err)
			printk(KERN_ERR "%s: Error %d restarting card on orinoco_pci_resume()\n",
			       dev->name, err);
	}
	
	spin_unlock_irqrestore(&priv->lock, flags);

	return 0;
}

static struct pci_device_id orinoco_pci_pci_id_table[] = {
static struct pci_device_id orinoco_pci_id_table[] = {
	/* Intersil Prism 3 */
	{0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
	/* Intersil Prism 2.5 */
@@ -365,11 +269,11 @@ static struct pci_device_id orinoco_pci_pci_id_table[] = {
	{0,},
};

MODULE_DEVICE_TABLE(pci, orinoco_pci_pci_id_table);
MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table);

static struct pci_driver orinoco_pci_driver = {
	.name		= DRIVER_NAME,
	.id_table	= orinoco_pci_pci_id_table,
	.id_table	= orinoco_pci_id_table,
	.probe		= orinoco_pci_init_one,
	.remove		= __devexit_p(orinoco_pci_remove_one),
	.suspend	= orinoco_pci_suspend,
+125 −0
Original line number Diff line number Diff line
/* orinoco_pci.h
 * 
 * Common code for all Orinoco drivers for PCI devices, including
 * both native PCI and PCMCIA-to-PCI bridges.
 *
 * Copyright (C) 2005, Pavel Roskin.
 * See orinoco.c for license.
 */

#ifndef _ORINOCO_PCI_H
#define _ORINOCO_PCI_H

#include <linux/netdevice.h>

/* Driver specific data */
struct orinoco_pci_card {
	void __iomem *bridge_io;
	void __iomem *attr_io;
};

/* Set base address or memory range of the network device based on
 * the PCI device it's using.  Specify BAR of the "main" resource.
 * To be used after request_irq().  */
static inline void orinoco_pci_setup_netdev(struct net_device *dev,
					    struct pci_dev *pdev, int bar)
{
	char *range_type;
	unsigned long start = pci_resource_start(pdev, bar);
	unsigned long len = pci_resource_len(pdev, bar);
	unsigned long flags = pci_resource_flags(pdev, bar);
	unsigned long end = start + len - 1;

	dev->irq = pdev->irq;
	if (flags & IORESOURCE_IO) {
		dev->base_addr = start;
		range_type = "ports";
	} else {
		dev->mem_start = start;
		dev->mem_end = end;
		range_type = "memory";
	}

	printk(KERN_DEBUG PFX "%s: irq %d, %s 0x%lx-0x%lx\n",
	       pci_name(pdev), pdev->irq, range_type, start, end);
}

static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
	struct net_device *dev = pci_get_drvdata(pdev);
	struct orinoco_private *priv = netdev_priv(dev);
	unsigned long flags;
	int err;

	err = orinoco_lock(priv, &flags);
	if (err) {
		printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
		       dev->name);
		return err;
	}

	err = __orinoco_down(dev);
	if (err)
		printk(KERN_WARNING "%s: error %d bringing interface down "
		       "for suspend\n", dev->name, err);
	
	netif_device_detach(dev);

	priv->hw_unavailable++;
	
	orinoco_unlock(priv, &flags);

	free_irq(pdev->irq, dev);
	pci_save_state(pdev);
	pci_disable_device(pdev);
	pci_set_power_state(pdev, PCI_D3hot);

	return 0;
}

static int orinoco_pci_resume(struct pci_dev *pdev)
{
	struct net_device *dev = pci_get_drvdata(pdev);
	struct orinoco_private *priv = netdev_priv(dev);
	unsigned long flags;
	int err;

	pci_set_power_state(pdev, 0);
	pci_enable_device(pdev);
	pci_restore_state(pdev);

	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
			  dev->name, dev);
	if (err) {
		printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
		       dev->name);
		pci_disable_device(pdev);
		return -EBUSY;
	}

	err = orinoco_reinit_firmware(dev);
	if (err) {
		printk(KERN_ERR "%s: error %d re-initializing firmware "
		       "on resume\n", dev->name, err);
		return err;
	}

	spin_lock_irqsave(&priv->lock, flags);

	netif_device_attach(dev);

	priv->hw_unavailable--;

	if (priv->open && (! priv->hw_unavailable)) {
		err = __orinoco_up(dev);
		if (err)
			printk(KERN_ERR "%s: Error %d restarting card on resume\n",
			       dev->name, err);
	}
	
	spin_unlock_irqrestore(&priv->lock, flags);

	return 0;
}

#endif /* _ORINOCO_PCI_H */
+89 −170

File changed.

Preview size limit exceeded, changes collapsed.

+43 −122

File changed.

Preview size limit exceeded, changes collapsed.