Adapt PowerMac "airport" driver to new driver model

parent fa56cc98
......@@ -25,8 +25,6 @@
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/wireless.h>
#include <linux/adb.h>
#include <linux/pmu.h>
#include <asm/io.h>
#include <asm/system.h>
......@@ -48,44 +46,22 @@ struct airport {
int ndev_registered;
};
#ifdef CONFIG_PMAC_PBOOK
static int airport_sleep_notify(struct pmu_sleep_notifier *self, int when);
static struct pmu_sleep_notifier airport_sleep_notifier = {
airport_sleep_notify, SLEEP_LEVEL_NET,
};
#endif
/*
* Function prototypes
*/
static struct net_device *airport_attach(struct device_node *of_node);
static void airport_detach(struct net_device *dev);
static struct net_device *airport_dev;
#ifdef CONFIG_PMAC_PBOOK
static int
airport_sleep_notify(struct pmu_sleep_notifier *self, int when)
airport_suspend(struct macio_dev *mdev, u32 state)
{
struct net_device *dev = airport_dev;
struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
struct orinoco_private *priv = dev->priv;
struct airport *card = priv->card;
unsigned long flags;
int err;
if (! airport_dev)
return PBOOK_SLEEP_OK;
switch (when) {
case PBOOK_SLEEP_NOW:
printk(KERN_DEBUG "%s: Airport entering sleep mode\n", dev->name);
err = orinoco_lock(priv, &flags);
if (err) {
printk(KERN_ERR "%s: hw_unavailable on PBOOK_SLEEP_NOW\n",
dev->name);
break;
return 0;
}
err = __orinoco_down(dev);
......@@ -101,10 +77,21 @@ airport_sleep_notify(struct pmu_sleep_notifier *self, int when)
disable_irq(dev->irq);
pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
break;
case PBOOK_WAKE:
return 0;
}
static int
airport_resume(struct macio_dev *mdev)
{
struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
struct orinoco_private *priv = dev->priv;
struct airport *card = priv->card;
unsigned long flags;
int err;
printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 1);
mdelay(200);
......@@ -114,7 +101,7 @@ airport_sleep_notify(struct pmu_sleep_notifier *self, int when)
if (err) {
printk(KERN_ERR "%s: Error %d re-initializing firmware on PBOOK_WAKE\n",
dev->name, err);
break;
return 0;
}
spin_lock_irqsave(&priv->lock, flags);
......@@ -133,11 +120,41 @@ airport_sleep_notify(struct pmu_sleep_notifier *self, int when)
spin_unlock_irqrestore(&priv->lock, flags);
break;
}
return PBOOK_SLEEP_OK;
return 0;
}
static int
airport_detach(struct macio_dev *mdev)
{
struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
struct orinoco_private *priv = dev->priv;
struct airport *card = priv->card;
if (card->ndev_registered)
unregister_netdev(dev);
card->ndev_registered = 0;
if (card->irq_requested)
free_irq(dev->irq, dev);
card->irq_requested = 0;
if (card->vaddr)
iounmap(card->vaddr);
card->vaddr = 0;
dev->base_addr = 0;
release_OF_resource(card->node, 0);
pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout(HZ);
dev_set_drvdata(&mdev->ofdev.dev, NULL);
free_netdev(dev);
return 0;
}
#endif /* CONFIG_PMAC_PBOOK */
static int airport_hard_reset(struct orinoco_private *priv)
{
......@@ -170,25 +187,26 @@ static int airport_hard_reset(struct orinoco_private *priv)
return 0;
}
static struct net_device *
airport_attach(struct device_node *of_node)
static int
airport_attach(struct macio_dev *mdev, const struct of_match *match)
{
struct orinoco_private *priv;
struct net_device *dev;
struct airport *card;
unsigned long phys_addr;
struct device_node *of_node = mdev->ofdev.node;
hermes_t *hw;
if (of_node->n_addrs < 1 || of_node->n_intrs < 1) {
printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n");
return NULL;
return -ENODEV;
}
/* Allocate space for private device-specific data */
dev = alloc_orinocodev(sizeof(*card), airport_hard_reset);
if (! dev) {
printk(KERN_ERR "airport: can't allocate device datas\n");
return NULL;
return -ENODEV;
}
priv = dev->priv;
card = priv->card;
......@@ -199,11 +217,14 @@ airport_attach(struct device_node *of_node)
if (! request_OF_resource(of_node, 0, " (airport)")) {
printk(KERN_ERR "airport: can't request IO resource !\n");
kfree(dev);
return NULL;
return -ENODEV;
}
dev->name[0] = '\0'; /* register_netdev will give us an ethX name */
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
dev_set_drvdata(&mdev->ofdev.dev, dev);
/* Setup interrupts & base address */
dev->irq = of_node->intrs[0].line;
......@@ -240,79 +261,50 @@ airport_attach(struct device_node *of_node)
}
printk(KERN_DEBUG "airport: card registered for interface %s\n", dev->name);
card->ndev_registered = 1;
#ifdef CONFIG_PMAC_PBOOK
pmu_register_sleep_notifier(&airport_sleep_notifier);
#endif
return dev;
return 0;
failed:
airport_detach(dev);
return NULL;
airport_detach(mdev);
return -ENODEV;
} /* airport_attach */
/*======================================================================
This deletes a driver "instance".
======================================================================*/
static void
airport_detach(struct net_device *dev)
{
struct orinoco_private *priv = dev->priv;
struct airport *card = priv->card;
#ifdef CONFIG_PMAC_PBOOK
pmu_unregister_sleep_notifier(&airport_sleep_notifier);
#endif
if (card->ndev_registered)
unregister_netdev(dev);
card->ndev_registered = 0;
if (card->irq_requested)
free_irq(dev->irq, dev);
card->irq_requested = 0;
if (card->vaddr)
iounmap(card->vaddr);
card->vaddr = 0;
dev->base_addr = 0;
release_OF_resource(card->node, 0);
pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0);
current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout(HZ);
free_netdev(dev);
} /* airport_detach */
static char version[] __initdata = "airport.c 0.13e (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
MODULE_LICENSE("Dual MPL/GPL");
static struct of_match airport_match[] =
{
{
.name = "radio",
.type = OF_ANY_MATCH,
.compatible = OF_ANY_MATCH
},
{},
};
static struct macio_driver airport_driver =
{
.name = "airport",
.match_table = airport_match,
.probe = airport_attach,
.remove = airport_detach,
.suspend = airport_suspend,
.resume = airport_resume,
};
static int __init
init_airport(void)
{
struct device_node *airport_node;
printk(KERN_DEBUG "%s\n", version);
/* Lookup card in device tree */
airport_node = find_devices("radio");
if (airport_node && !strcmp(airport_node->parent->name, "mac-io"))
airport_dev = airport_attach(airport_node);
return airport_dev ? 0 : -ENODEV;
return macio_register_driver(&airport_driver);
}
static void __exit
exit_airport(void)
{
if (airport_dev)
airport_detach(airport_dev);
airport_dev = NULL;
return macio_unregister_driver(&airport_driver);
}
module_init(init_airport);
......
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