From e676c232e670e27d8b3783e1167f34288e17c83f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Sun, 19 Feb 2006 00:21:46 -0500 Subject: Input: input core - semaphore to mutex conversion Signed-off-by: Jes Sorensen Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/input/input.c b/drivers/input/input.c index 4fe3da3c66..3e22bb11ee 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -21,6 +21,7 @@ #include #include #include +#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Input core"); @@ -224,7 +225,7 @@ int input_open_device(struct input_handle *handle) struct input_dev *dev = handle->dev; int err; - err = down_interruptible(&dev->sem); + err = mutex_lock_interruptible(&dev->mutex); if (err) return err; @@ -236,7 +237,7 @@ int input_open_device(struct input_handle *handle) if (err) handle->open--; - up(&dev->sem); + mutex_unlock(&dev->mutex); return err; } @@ -255,13 +256,13 @@ void input_close_device(struct input_handle *handle) input_release_device(handle); - down(&dev->sem); + mutex_lock(&dev->mutex); if (!--dev->users && dev->close) dev->close(dev); handle->open--; - up(&dev->sem); + mutex_unlock(&dev->mutex); } static void input_link_handle(struct input_handle *handle) @@ -512,13 +513,13 @@ static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \ struct input_dev *input_dev = to_input_dev(dev); \ int retval; \ \ - retval = down_interruptible(&input_dev->sem); \ + retval = mutex_lock_interruptible(&input_dev->mutex); \ if (retval) \ return retval; \ \ retval = sprintf(buf, "%s\n", input_dev->name ? input_dev->name : ""); \ \ - up(&input_dev->sem); \ + mutex_unlock(&input_dev->mutex); \ \ return retval; \ } \ @@ -790,7 +791,7 @@ int input_register_device(struct input_dev *dev) return -EINVAL; } - init_MUTEX(&dev->sem); + mutex_init(&dev->mutex); set_bit(EV_SYN, dev->evbit); /* -- cgit v1.2.2 From c4e32e9faaaa83340dbbc00e07c48d38f032b7dc Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 19 Feb 2006 00:21:55 -0500 Subject: Input: serio - semaphore to mutex conversion The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/serio/libps2.c | 10 ++++----- drivers/input/serio/serio.c | 45 +++++++++++++++++++++-------------------- drivers/input/serio/serio_raw.c | 23 +++++++++++---------- 3 files changed, 40 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index d4c990f7c8..79c97f94bc 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -84,7 +84,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) maxbytes = sizeof(ps2dev->cmdbuf); } - down(&ps2dev->cmd_sem); + mutex_lock(&ps2dev->cmd_mutex); serio_pause_rx(ps2dev->serio); ps2dev->flags = PS2_FLAG_CMD; @@ -94,7 +94,7 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) wait_event_timeout(ps2dev->wait, !(ps2dev->flags & PS2_FLAG_CMD), msecs_to_jiffies(timeout)); - up(&ps2dev->cmd_sem); + mutex_unlock(&ps2dev->cmd_mutex); } /* @@ -177,7 +177,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) return -1; } - down(&ps2dev->cmd_sem); + mutex_lock(&ps2dev->cmd_mutex); serio_pause_rx(ps2dev->serio); ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; @@ -229,7 +229,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) ps2dev->flags = 0; serio_continue_rx(ps2dev->serio); - up(&ps2dev->cmd_sem); + mutex_unlock(&ps2dev->cmd_mutex); return rc; } @@ -281,7 +281,7 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman void ps2_init(struct ps2dev *ps2dev, struct serio *serio) { - init_MUTEX(&ps2dev->cmd_sem); + mutex_init(&ps2dev->cmd_mutex); init_waitqueue_head(&ps2dev->wait); ps2dev->serio = serio; } diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 2f76813c3a..79e5e77ce0 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -34,6 +34,7 @@ #include #include #include +#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Serio abstraction core"); @@ -52,10 +53,10 @@ EXPORT_SYMBOL(serio_rescan); EXPORT_SYMBOL(serio_reconnect); /* - * serio_sem protects entire serio subsystem and is taken every time + * serio_mutex protects entire serio subsystem and is taken every time * serio port or driver registrered or unregistered. */ -static DECLARE_MUTEX(serio_sem); +static DEFINE_MUTEX(serio_mutex); static LIST_HEAD(serio_list); @@ -70,9 +71,9 @@ static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) { int retval; - down(&serio->drv_sem); + mutex_lock(&serio->drv_mutex); retval = drv->connect(serio, drv); - up(&serio->drv_sem); + mutex_unlock(&serio->drv_mutex); return retval; } @@ -81,20 +82,20 @@ static int serio_reconnect_driver(struct serio *serio) { int retval = -1; - down(&serio->drv_sem); + mutex_lock(&serio->drv_mutex); if (serio->drv && serio->drv->reconnect) retval = serio->drv->reconnect(serio); - up(&serio->drv_sem); + mutex_unlock(&serio->drv_mutex); return retval; } static void serio_disconnect_driver(struct serio *serio) { - down(&serio->drv_sem); + mutex_lock(&serio->drv_mutex); if (serio->drv) serio->drv->disconnect(serio); - up(&serio->drv_sem); + mutex_unlock(&serio->drv_mutex); } static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) @@ -272,7 +273,7 @@ static void serio_handle_event(void) struct serio_event *event; struct serio_driver *serio_drv; - down(&serio_sem); + mutex_lock(&serio_mutex); /* * Note that we handle only one event here to give swsusp @@ -314,7 +315,7 @@ static void serio_handle_event(void) serio_free_event(event); } - up(&serio_sem); + mutex_unlock(&serio_mutex); } /* @@ -449,7 +450,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * struct device_driver *drv; int retval; - retval = down_interruptible(&serio_sem); + retval = mutex_lock_interruptible(&serio_mutex); if (retval) return retval; @@ -469,7 +470,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * retval = -EINVAL; } - up(&serio_sem); + mutex_unlock(&serio_mutex); return retval; } @@ -524,7 +525,7 @@ static void serio_init_port(struct serio *serio) __module_get(THIS_MODULE); spin_lock_init(&serio->lock); - init_MUTEX(&serio->drv_sem); + mutex_init(&serio->drv_mutex); device_initialize(&serio->dev); snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), "serio%ld", (long)atomic_inc_return(&serio_no) - 1); @@ -661,10 +662,10 @@ void __serio_register_port(struct serio *serio, struct module *owner) */ void serio_unregister_port(struct serio *serio) { - down(&serio_sem); + mutex_lock(&serio_mutex); serio_disconnect_port(serio); serio_destroy_port(serio); - up(&serio_sem); + mutex_unlock(&serio_mutex); } /* @@ -672,17 +673,17 @@ void serio_unregister_port(struct serio *serio) */ void serio_unregister_child_port(struct serio *serio) { - down(&serio_sem); + mutex_lock(&serio_mutex); if (serio->child) { serio_disconnect_port(serio->child); serio_destroy_port(serio->child); } - up(&serio_sem); + mutex_unlock(&serio_mutex); } /* * Submits register request to kseriod for subsequent execution. - * Can be used when it is not obvious whether the serio_sem is + * Can be used when it is not obvious whether the serio_mutex is * taken or not and when delayed execution is feasible. */ void __serio_unregister_port_delayed(struct serio *serio, struct module *owner) @@ -765,7 +766,7 @@ void serio_unregister_driver(struct serio_driver *drv) { struct serio *serio; - down(&serio_sem); + mutex_lock(&serio_mutex); drv->manual_bind = 1; /* so serio_find_driver ignores it */ start_over: @@ -779,7 +780,7 @@ start_over: } driver_unregister(&drv->driver); - up(&serio_sem); + mutex_unlock(&serio_mutex); } static void serio_set_drv(struct serio *serio, struct serio_driver *drv) @@ -858,7 +859,7 @@ static int serio_resume(struct device *dev) return 0; } -/* called from serio_driver->connect/disconnect methods under serio_sem */ +/* called from serio_driver->connect/disconnect methods under serio_mutex */ int serio_open(struct serio *serio, struct serio_driver *drv) { serio_set_drv(serio, drv); @@ -870,7 +871,7 @@ int serio_open(struct serio *serio, struct serio_driver *drv) return 0; } -/* called from serio_driver->connect/disconnect methods under serio_sem */ +/* called from serio_driver->connect/disconnect methods under serio_mutex */ void serio_close(struct serio *serio) { if (serio->close) diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 47e08de18d..8734e7f75b 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -19,6 +19,7 @@ #include #include #include +#include #define DRIVER_DESC "Raw serio driver" @@ -46,7 +47,7 @@ struct serio_raw_list { struct list_head node; }; -static DECLARE_MUTEX(serio_raw_sem); +static DEFINE_MUTEX(serio_raw_mutex); static LIST_HEAD(serio_raw_list); static unsigned int serio_raw_no; @@ -81,7 +82,7 @@ static int serio_raw_open(struct inode *inode, struct file *file) struct serio_raw_list *list; int retval = 0; - retval = down_interruptible(&serio_raw_sem); + retval = mutex_lock_interruptible(&serio_raw_mutex); if (retval) return retval; @@ -108,7 +109,7 @@ static int serio_raw_open(struct inode *inode, struct file *file) list_add_tail(&list->node, &serio_raw->list); out: - up(&serio_raw_sem); + mutex_unlock(&serio_raw_mutex); return retval; } @@ -130,12 +131,12 @@ static int serio_raw_release(struct inode *inode, struct file *file) struct serio_raw_list *list = file->private_data; struct serio_raw *serio_raw = list->serio_raw; - down(&serio_raw_sem); + mutex_lock(&serio_raw_mutex); serio_raw_fasync(-1, file, 0); serio_raw_cleanup(serio_raw); - up(&serio_raw_sem); + mutex_unlock(&serio_raw_mutex); return 0; } @@ -194,7 +195,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz int retval; unsigned char c; - retval = down_interruptible(&serio_raw_sem); + retval = mutex_lock_interruptible(&serio_raw_mutex); if (retval) return retval; @@ -219,7 +220,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, siz }; out: - up(&serio_raw_sem); + mutex_unlock(&serio_raw_mutex); return written; } @@ -280,7 +281,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) return -ENOMEM; } - down(&serio_raw_sem); + mutex_lock(&serio_raw_mutex); memset(serio_raw, 0, sizeof(struct serio_raw)); snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++); @@ -325,7 +326,7 @@ out_free: serio_set_drvdata(serio, NULL); kfree(serio_raw); out: - up(&serio_raw_sem); + mutex_unlock(&serio_raw_mutex); return err; } @@ -350,7 +351,7 @@ static void serio_raw_disconnect(struct serio *serio) { struct serio_raw *serio_raw; - down(&serio_raw_sem); + mutex_lock(&serio_raw_mutex); serio_raw = serio_get_drvdata(serio); @@ -361,7 +362,7 @@ static void serio_raw_disconnect(struct serio *serio) if (!serio_raw_cleanup(serio_raw)) wake_up_interruptible(&serio_raw->wait); - up(&serio_raw_sem); + mutex_unlock(&serio_raw_mutex); } static struct serio_device_id serio_raw_serio_ids[] = { -- cgit v1.2.2 From 286295eb936e76347173639c218134e6342440f9 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 19 Feb 2006 00:22:03 -0500 Subject: Input: gameport - semaphore to mutex conversion The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/gameport.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index b765a155c0..9444702630 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -22,6 +22,7 @@ #include #include #include /* HZ */ +#include /*#include */ @@ -43,10 +44,10 @@ EXPORT_SYMBOL(gameport_start_polling); EXPORT_SYMBOL(gameport_stop_polling); /* - * gameport_sem protects entire gameport subsystem and is taken + * gameport_mutex protects entire gameport subsystem and is taken * every time gameport port or driver registrered or unregistered. */ -static DECLARE_MUTEX(gameport_sem); +static DEFINE_MUTEX(gameport_mutex); static LIST_HEAD(gameport_list); @@ -342,7 +343,7 @@ static void gameport_handle_event(void) struct gameport_event *event; struct gameport_driver *gameport_drv; - down(&gameport_sem); + mutex_lock(&gameport_mutex); /* * Note that we handle only one event here to give swsusp @@ -379,7 +380,7 @@ static void gameport_handle_event(void) gameport_free_event(event); } - up(&gameport_sem); + mutex_unlock(&gameport_mutex); } /* @@ -464,7 +465,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut struct device_driver *drv; int retval; - retval = down_interruptible(&gameport_sem); + retval = mutex_lock_interruptible(&gameport_mutex); if (retval) return retval; @@ -484,7 +485,7 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut retval = -EINVAL; } - up(&gameport_sem); + mutex_unlock(&gameport_mutex); return retval; } @@ -521,7 +522,7 @@ static void gameport_init_port(struct gameport *gameport) __module_get(THIS_MODULE); - init_MUTEX(&gameport->drv_sem); + mutex_init(&gameport->drv_mutex); device_initialize(&gameport->dev); snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id), "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1); @@ -661,10 +662,10 @@ void __gameport_register_port(struct gameport *gameport, struct module *owner) */ void gameport_unregister_port(struct gameport *gameport) { - down(&gameport_sem); + mutex_lock(&gameport_mutex); gameport_disconnect_port(gameport); gameport_destroy_port(gameport); - up(&gameport_sem); + mutex_unlock(&gameport_mutex); } @@ -717,7 +718,7 @@ void gameport_unregister_driver(struct gameport_driver *drv) { struct gameport *gameport; - down(&gameport_sem); + mutex_lock(&gameport_mutex); drv->ignore = 1; /* so gameport_find_driver ignores it */ start_over: @@ -731,7 +732,7 @@ start_over: } driver_unregister(&drv->driver); - up(&gameport_sem); + mutex_unlock(&gameport_mutex); } static int gameport_bus_match(struct device *dev, struct device_driver *drv) @@ -743,9 +744,9 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv) static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv) { - down(&gameport->drv_sem); + mutex_lock(&gameport->drv_mutex); gameport->drv = drv; - up(&gameport->drv_sem); + mutex_unlock(&gameport->drv_mutex); } int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode) -- cgit v1.2.2 From c14471dc2e014f9508ea1ac48394e5437ee970d7 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 19 Feb 2006 00:22:11 -0500 Subject: Input: psmouse - semaphore to mutex conversion The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 19b1b01217..b1cdd70862 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -20,6 +20,8 @@ #include #include #include +#include + #include "psmouse.h" #include "synaptics.h" #include "logips2pp.h" @@ -98,13 +100,13 @@ __obsolete_setup("psmouse_resetafter="); __obsolete_setup("psmouse_rate="); /* - * psmouse_sem protects all operations changing state of mouse + * psmouse_mutex protects all operations changing state of mouse * (connecting, disconnecting, changing rate or resolution via * sysfs). We could use a per-device semaphore but since there * rarely more than one PS/2 mouse connected and since semaphore * is taken in "slow" paths it is not worth it. */ -static DECLARE_MUTEX(psmouse_sem); +static DEFINE_MUTEX(psmouse_mutex); static struct workqueue_struct *kpsmoused_wq; @@ -868,7 +870,7 @@ static void psmouse_resync(void *p) int failed = 0, enabled = 0; int i; - down(&psmouse_sem); + mutex_lock(&psmouse_mutex); if (psmouse->state != PSMOUSE_RESYNCING) goto out; @@ -948,7 +950,7 @@ static void psmouse_resync(void *p) if (parent) psmouse_activate(parent); out: - up(&psmouse_sem); + mutex_unlock(&psmouse_mutex); } /* @@ -974,14 +976,14 @@ static void psmouse_disconnect(struct serio *serio) sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group); - down(&psmouse_sem); + mutex_lock(&psmouse_mutex); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); /* make sure we don't have a resync in progress */ - up(&psmouse_sem); + mutex_unlock(&psmouse_mutex); flush_workqueue(kpsmoused_wq); - down(&psmouse_sem); + mutex_lock(&psmouse_mutex); if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { parent = serio_get_drvdata(serio->parent); @@ -1004,7 +1006,7 @@ static void psmouse_disconnect(struct serio *serio) if (parent) psmouse_activate(parent); - up(&psmouse_sem); + mutex_unlock(&psmouse_mutex); } static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto) @@ -1076,7 +1078,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int retval = -ENOMEM; - down(&psmouse_sem); + mutex_lock(&psmouse_mutex); /* * If this is a pass-through port deactivate parent so the device @@ -1144,7 +1146,7 @@ out: if (parent) psmouse_activate(parent); - up(&psmouse_sem); + mutex_unlock(&psmouse_mutex); return retval; } @@ -1161,7 +1163,7 @@ static int psmouse_reconnect(struct serio *serio) return -1; } - down(&psmouse_sem); + mutex_lock(&psmouse_mutex); if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { parent = serio_get_drvdata(serio->parent); @@ -1195,7 +1197,7 @@ out: if (parent) psmouse_activate(parent); - up(&psmouse_sem); + mutex_unlock(&psmouse_mutex); return rc; } @@ -1273,7 +1275,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev goto out_unpin; } - retval = down_interruptible(&psmouse_sem); + retval = mutex_lock_interruptible(&psmouse_mutex); if (retval) goto out_unpin; @@ -1281,7 +1283,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev if (psmouse->state == PSMOUSE_IGNORE) { retval = -ENODEV; - goto out_up; + goto out_unlock; } if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { @@ -1299,8 +1301,8 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev if (parent) psmouse_activate(parent); - out_up: - up(&psmouse_sem); + out_unlock: + mutex_unlock(&psmouse_mutex); out_unpin: serio_unpin_driver(serio); return retval; @@ -1357,11 +1359,11 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co return -EIO; } - up(&psmouse_sem); + mutex_unlock(&psmouse_mutex); serio_unpin_driver(serio); serio_unregister_child_port(serio); serio_pin_driver_uninterruptible(serio); - down(&psmouse_sem); + mutex_lock(&psmouse_mutex); if (serio->drv != &psmouse_drv) { input_free_device(new_dev); -- cgit v1.2.2 From 33d3f07ae17c0060dc01f26180c94cf0a39efdf1 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 19 Feb 2006 00:22:18 -0500 Subject: Input: atkbd - semaphore to mutex conversion The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index ffacf6eca5..b45981870c 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -27,6 +27,7 @@ #include #include #include +#include #define DRIVER_DESC "AT and PS/2 keyboard driver" @@ -216,7 +217,7 @@ struct atkbd { unsigned long time; struct work_struct event_work; - struct semaphore event_sem; + struct mutex event_mutex; unsigned long event_mask; }; @@ -449,7 +450,7 @@ static void atkbd_event_work(void *data) unsigned char param[2]; int i, j; - down(&atkbd->event_sem); + mutex_lock(&atkbd->event_mutex); if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) { param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0) @@ -480,7 +481,7 @@ static void atkbd_event_work(void *data) ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP); } - up(&atkbd->event_sem); + mutex_unlock(&atkbd->event_mutex); } /* @@ -846,7 +847,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd->dev = dev; ps2_init(&atkbd->ps2dev, serio); INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd); - init_MUTEX(&atkbd->event_sem); + mutex_init(&atkbd->event_mutex); switch (serio->id.type) { -- cgit v1.2.2 From 72ba9f0ce09c5508ec4b0cf30e88899872a83f75 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 19 Feb 2006 00:22:30 -0500 Subject: Input: joysticks - semaphore to mutex conversion The conversion was generated via scripts, and the result was validated automatically via a script as well. Amijoy conversion was done by Arjan van de Ven. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/amijoy.c | 11 ++++++----- drivers/input/joystick/db9.c | 13 +++++++------ drivers/input/joystick/gamecon.c | 13 +++++++------ drivers/input/joystick/iforce/iforce-ff.c | 24 ++++++++++++------------ drivers/input/joystick/iforce/iforce-main.c | 2 +- drivers/input/joystick/iforce/iforce.h | 5 +++-- drivers/input/joystick/turbografx.c | 13 +++++++------ 7 files changed, 43 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index ec55a29fc8..7249d32429 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,7 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of , (default is __obsolete_setup("amijoy="); static int amijoy_used; -static DECLARE_MUTEX(amijoy_sem); +static DEFINE_MUTEX(amijoy_mutex); static struct input_dev *amijoy_dev[2]; static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; @@ -85,7 +86,7 @@ static int amijoy_open(struct input_dev *dev) { int err; - err = down_interruptible(&amijoy_sem); + err = mutex_lock_interruptible(&amijoy_mutex); if (err) return err; @@ -97,16 +98,16 @@ static int amijoy_open(struct input_dev *dev) amijoy_used++; out: - up(&amijoy_sem); + mutex_unlock(&amijoy_mutex); return err; } static void amijoy_close(struct input_dev *dev) { - down(&amijoy_sem); + mutex_lock(&amijoy_mutex); if (!--amijoy_used) free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); - up(&amijoy_sem); + mutex_unlock(&amijoy_mutex); } static int __init amijoy_init(void) diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index dcffc34f30..e61894685c 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -38,6 +38,7 @@ #include #include #include +#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver"); @@ -111,7 +112,7 @@ struct db9 { struct pardevice *pd; int mode; int used; - struct semaphore sem; + struct mutex mutex; char phys[DB9_MAX_DEVICES][32]; }; @@ -525,7 +526,7 @@ static int db9_open(struct input_dev *dev) struct parport *port = db9->pd->port; int err; - err = down_interruptible(&db9->sem); + err = mutex_lock_interruptible(&db9->mutex); if (err) return err; @@ -539,7 +540,7 @@ static int db9_open(struct input_dev *dev) mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); } - up(&db9->sem); + mutex_unlock(&db9->mutex); return 0; } @@ -548,14 +549,14 @@ static void db9_close(struct input_dev *dev) struct db9 *db9 = dev->private; struct parport *port = db9->pd->port; - down(&db9->sem); + mutex_lock(&db9->mutex); if (!--db9->used) { del_timer_sync(&db9->timer); parport_write_control(port, 0x00); parport_data_forward(port); parport_release(db9->pd); } - up(&db9->sem); + mutex_unlock(&db9->mutex); } static struct db9 __init *db9_probe(int parport, int mode) @@ -603,7 +604,7 @@ static struct db9 __init *db9_probe(int parport, int mode) goto err_unreg_pardev; } - init_MUTEX(&db9->sem); + mutex_init(&db9->mutex); db9->pd = pd; db9->mode = mode; init_timer(&db9->timer); diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 900587acdb..aa3ef89d81 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -36,6 +36,7 @@ #include #include #include +#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); @@ -83,7 +84,7 @@ struct gc { struct timer_list timer; unsigned char pads[GC_MAX + 1]; int used; - struct semaphore sem; + struct mutex mutex; char phys[GC_MAX_DEVICES][32]; }; @@ -552,7 +553,7 @@ static int gc_open(struct input_dev *dev) struct gc *gc = dev->private; int err; - err = down_interruptible(&gc->sem); + err = mutex_lock_interruptible(&gc->mutex); if (err) return err; @@ -562,7 +563,7 @@ static int gc_open(struct input_dev *dev) mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); } - up(&gc->sem); + mutex_unlock(&gc->mutex); return 0; } @@ -570,13 +571,13 @@ static void gc_close(struct input_dev *dev) { struct gc *gc = dev->private; - down(&gc->sem); + mutex_lock(&gc->mutex); if (!--gc->used) { del_timer_sync(&gc->timer); parport_write_control(gc->pd->port, 0x00); parport_release(gc->pd); } - up(&gc->sem); + mutex_unlock(&gc->mutex); } static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) @@ -693,7 +694,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) goto err_unreg_pardev; } - init_MUTEX(&gc->sem); + mutex_init(&gc->mutex); gc->pd = pd; init_timer(&gc->timer); gc->timer.data = (long) gc; diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c index 4678b6dab4..2b8e8456c9 100644 --- a/drivers/input/joystick/iforce/iforce-ff.c +++ b/drivers/input/joystick/iforce/iforce-ff.c @@ -42,14 +42,14 @@ static int make_magnitude_modifier(struct iforce* iforce, unsigned char data[3]; if (!no_alloc) { - down(&iforce->mem_mutex); + mutex_lock(&iforce->mem_mutex); if (allocate_resource(&(iforce->device_memory), mod_chunk, 2, iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { - up(&iforce->mem_mutex); + mutex_unlock(&iforce->mem_mutex); return -ENOMEM; } - up(&iforce->mem_mutex); + mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); @@ -75,14 +75,14 @@ static int make_period_modifier(struct iforce* iforce, period = TIME_SCALE(period); if (!no_alloc) { - down(&iforce->mem_mutex); + mutex_lock(&iforce->mem_mutex); if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c, iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { - up(&iforce->mem_mutex); + mutex_unlock(&iforce->mem_mutex); return -ENOMEM; } - up(&iforce->mem_mutex); + mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); @@ -115,14 +115,14 @@ static int make_envelope_modifier(struct iforce* iforce, fade_duration = TIME_SCALE(fade_duration); if (!no_alloc) { - down(&iforce->mem_mutex); + mutex_lock(&iforce->mem_mutex); if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e, iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { - up(&iforce->mem_mutex); + mutex_unlock(&iforce->mem_mutex); return -ENOMEM; } - up(&iforce->mem_mutex); + mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); @@ -152,14 +152,14 @@ static int make_condition_modifier(struct iforce* iforce, unsigned char data[10]; if (!no_alloc) { - down(&iforce->mem_mutex); + mutex_lock(&iforce->mem_mutex); if (allocate_resource(&(iforce->device_memory), mod_chunk, 8, iforce->device_memory.start, iforce->device_memory.end, 2L, NULL, NULL)) { - up(&iforce->mem_mutex); + mutex_unlock(&iforce->mem_mutex); return -ENOMEM; } - up(&iforce->mem_mutex); + mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index b6bc049980..ab0a26b924 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -350,7 +350,7 @@ int iforce_init_device(struct iforce *iforce) init_waitqueue_head(&iforce->wait); spin_lock_init(&iforce->xmit_lock); - init_MUTEX(&iforce->mem_mutex); + mutex_init(&iforce->mem_mutex); iforce->xmit.buf = iforce->xmit_data; iforce->dev = input_dev; diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index 146f406b8f..668f24535b 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -37,7 +37,7 @@ #include #include #include -#include +#include /* This module provides arbitrary resource management routines. * I use it to manage the device's memory. @@ -45,6 +45,7 @@ */ #include + #define IFORCE_MAX_LENGTH 16 /* iforce::bus */ @@ -146,7 +147,7 @@ struct iforce { wait_queue_head_t wait; struct resource device_memory; struct iforce_core_effect core_effects[FF_EFFECTS_MAX]; - struct semaphore mem_mutex; + struct mutex mem_mutex; }; /* Get hi and low bytes of a 16-bits int */ diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index b154938e88..5570fd5487 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -37,6 +37,7 @@ #include #include #include +#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("TurboGraFX parallel port interface driver"); @@ -86,7 +87,7 @@ static struct tgfx { char phys[TGFX_MAX_DEVICES][32]; int sticks; int used; - struct semaphore sem; + struct mutex sem; } *tgfx_base[TGFX_MAX_PORTS]; /* @@ -128,7 +129,7 @@ static int tgfx_open(struct input_dev *dev) struct tgfx *tgfx = dev->private; int err; - err = down_interruptible(&tgfx->sem); + err = mutex_lock_interruptible(&tgfx->sem); if (err) return err; @@ -138,7 +139,7 @@ static int tgfx_open(struct input_dev *dev) mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); } - up(&tgfx->sem); + mutex_unlock(&tgfx->sem); return 0; } @@ -146,13 +147,13 @@ static void tgfx_close(struct input_dev *dev) { struct tgfx *tgfx = dev->private; - down(&tgfx->sem); + mutex_lock(&tgfx->sem); if (!--tgfx->used) { del_timer_sync(&tgfx->timer); parport_write_control(tgfx->pd->port, 0x00); parport_release(tgfx->pd); } - up(&tgfx->sem); + mutex_unlock(&tgfx->sem); } @@ -191,7 +192,7 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs) goto err_unreg_pardev; } - init_MUTEX(&tgfx->sem); + mutex_init(&tgfx->sem); tgfx->pd = pd; init_timer(&tgfx->timer); tgfx->timer.data = (long) tgfx; -- cgit v1.2.2 From 221979aad6ab4792617f2e58973aa6fc349d4036 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 19 Feb 2006 00:22:36 -0500 Subject: Input: uinput - semaphore to mutex conversion Signed-off-by: Dmitry Torokhov --- drivers/input/misc/uinput.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 546ed9b490..d723e9ad7c 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -194,7 +194,7 @@ static int uinput_open(struct inode *inode, struct file *file) if (!newdev) return -ENOMEM; - init_MUTEX(&newdev->sem); + mutex_init(&newdev->mutex); spin_lock_init(&newdev->requests_lock); init_waitqueue_head(&newdev->requests_waitq); init_waitqueue_head(&newdev->waitq); @@ -340,7 +340,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t struct uinput_device *udev = file->private_data; int retval; - retval = down_interruptible(&udev->sem); + retval = mutex_lock_interruptible(&udev->mutex); if (retval) return retval; @@ -348,7 +348,7 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t uinput_inject_event(udev, buffer, count) : uinput_setup_device(udev, buffer, count); - up(&udev->sem); + mutex_unlock(&udev->mutex); return retval; } @@ -369,7 +369,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, if (retval) return retval; - retval = down_interruptible(&udev->sem); + retval = mutex_lock_interruptible(&udev->mutex); if (retval) return retval; @@ -388,7 +388,7 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, } out: - up(&udev->sem); + mutex_unlock(&udev->mutex); return retval; } @@ -439,7 +439,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg) udev = file->private_data; - retval = down_interruptible(&udev->sem); + retval = mutex_lock_interruptible(&udev->mutex); if (retval) return retval; @@ -589,7 +589,7 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } out: - up(&udev->sem); + mutex_unlock(&udev->mutex); return retval; } -- cgit v1.2.2 From 51c38f9bce274a1e8a90aa457fb433be738f7458 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 19 Feb 2006 00:22:51 -0500 Subject: Input: initialize serio and gameport at subsystem level Serio and gameport cores do not depend on other drivers and are used by code living outside of drivers/input/{gameport|serio}. Registering them at subsystem level guarantees that they are fully initialized before anyone tries to use them. Signed-off-by: Dmitry Torokhov --- drivers/Makefile | 4 +--- drivers/input/gameport/gameport.c | 2 +- drivers/input/serio/serio.c | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/Makefile b/drivers/Makefile index 5c69b86db6..6495411337 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -25,9 +25,6 @@ obj-$(CONFIG_CONNECTOR) += connector/ obj-$(CONFIG_FB_I810) += video/i810/ obj-$(CONFIG_FB_INTEL) += video/intelfb/ -# we also need input/serio early so serio bus is initialized by the time -# serial drivers start registering their serio ports -obj-$(CONFIG_SERIO) += input/serio/ obj-y += serial/ obj-$(CONFIG_PARPORT) += parport/ obj-y += base/ block/ misc/ mfd/ net/ media/ @@ -53,6 +50,7 @@ obj-$(CONFIG_TC) += tc/ obj-$(CONFIG_USB) += usb/ obj-$(CONFIG_PCI) += usb/ obj-$(CONFIG_USB_GADGET) += usb/gadget/ +obj-$(CONFIG_SERIO) += input/serio/ obj-$(CONFIG_GAMEPORT) += input/gameport/ obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_I2O) += message/ diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 9444702630..bcfd700829 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -797,5 +797,5 @@ static void __exit gameport_exit(void) kthread_stop(gameport_task); } -module_init(gameport_init); +subsys_initcall(gameport_init); module_exit(gameport_exit); diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 79e5e77ce0..966600779b 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -924,5 +924,5 @@ static void __exit serio_exit(void) kthread_stop(serio_task); } -module_init(serio_init); +subsys_initcall(serio_init); module_exit(serio_exit); -- cgit v1.2.2 From b39787a972042ded183343b177d9c595b5704575 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Tue, 14 Mar 2006 00:09:16 -0500 Subject: Input: use kzalloc() throughout the code Signed-off-by: Eric Sesterhenn Signed-off-by: Dmitry Torokhov --- drivers/input/evbug.c | 3 +-- drivers/input/evdev.c | 6 ++---- drivers/input/joydev.c | 6 ++---- drivers/input/keyboard/hil_kbd.c | 3 +-- drivers/input/mouse/hil_ptr.c | 7 ++++--- drivers/input/mouse/synaptics.c | 7 ++----- drivers/input/mousedev.c | 6 ++---- drivers/input/power.c | 3 +-- drivers/input/serio/hil_mlc.c | 3 +-- drivers/input/serio/parkbd.c | 3 +-- drivers/input/serio/rpckbd.c | 3 +-- drivers/input/serio/serio_raw.c | 6 ++---- drivers/input/tsdev.c | 6 ++---- 13 files changed, 22 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c index d7828936fd..07358fb51b 100644 --- a/drivers/input/evbug.c +++ b/drivers/input/evbug.c @@ -49,9 +49,8 @@ static struct input_handle *evbug_connect(struct input_handler *handler, struct { struct input_handle *handle; - if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) + if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL))) return NULL; - memset(handle, 0, sizeof(struct input_handle)); handle->dev = dev; handle->handler = handler; diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 745979f33d..a34e3d91d9 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -130,9 +130,8 @@ static int evdev_open(struct inode * inode, struct file * file) if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file))) return accept_err; - if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) + if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL))) return -ENOMEM; - memset(list, 0, sizeof(struct evdev_list)); list->evdev = evdev_table[i]; list_add_tail(&list->node, &evdev_table[i]->list); @@ -609,9 +608,8 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct return NULL; } - if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL))) + if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL))) return NULL; - memset(evdev, 0, sizeof(struct evdev)); INIT_LIST_HEAD(&evdev->list); init_waitqueue_head(&evdev->wait); diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 20e2972b92..949bdcef8c 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -171,9 +171,8 @@ static int joydev_open(struct inode *inode, struct file *file) if (i >= JOYDEV_MINORS || !joydev_table[i]) return -ENODEV; - if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) + if (!(list = kzalloc(sizeof(struct joydev_list), GFP_KERNEL))) return -ENOMEM; - memset(list, 0, sizeof(struct joydev_list)); list->joydev = joydev_table[i]; list_add_tail(&list->node, &joydev_table[i]->list); @@ -457,9 +456,8 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct return NULL; } - if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL))) + if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL))) return NULL; - memset(joydev, 0, sizeof(struct joydev)); INIT_LIST_HEAD(&joydev->list); init_waitqueue_head(&joydev->wait); diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 0a90962c38..ed3271b714 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -251,10 +251,9 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) uint8_t did, *idd; int i; - kbd = kmalloc(sizeof(*kbd), GFP_KERNEL); + kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); if (!kbd) return -ENOMEM; - memset(kbd, 0, sizeof(struct hil_kbd)); if (serio_open(serio, drv)) goto bail0; diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c index c2bf2ed07d..798f4a3ad7 100644 --- a/drivers/input/mouse/hil_ptr.c +++ b/drivers/input/mouse/hil_ptr.c @@ -245,10 +245,11 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) unsigned int i, naxsets, btntype; uint8_t did, *idd; - if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return -ENOMEM; - memset(ptr, 0, sizeof(struct hil_ptr)); + if (!(ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL))) + return -ENOMEM; - if (serio_open(serio, driver)) goto bail0; + if (serio_open(serio, driver)) + goto bail0; serio_set_drvdata(serio, ptr); ptr->serio = serio; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 2051bec2c3..d27d52c3c6 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -247,14 +247,12 @@ static void synaptics_pt_create(struct psmouse *psmouse) { struct serio *serio; - serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(struct serio), GFP_KERNEL); if (!serio) { printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n"); return; } - memset(serio, 0, sizeof(struct serio)); - serio->id.type = SERIO_PS_PSTHRU; strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); @@ -623,10 +621,9 @@ int synaptics_init(struct psmouse *psmouse) { struct synaptics_data *priv; - psmouse->private = priv = kmalloc(sizeof(struct synaptics_data), GFP_KERNEL); + psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); if (!priv) return -1; - memset(priv, 0, sizeof(struct synaptics_data)); if (synaptics_query_hardware(psmouse)) { printk(KERN_ERR "Unable to query Synaptics hardware.\n"); diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 9abed18d2e..b685a50795 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -412,9 +412,8 @@ static int mousedev_open(struct inode * inode, struct file * file) if (i >= MOUSEDEV_MINORS || !mousedev_table[i]) return -ENODEV; - if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL))) + if (!(list = kzalloc(sizeof(struct mousedev_list), GFP_KERNEL))) return -ENOMEM; - memset(list, 0, sizeof(struct mousedev_list)); spin_lock_init(&list->packet_lock); list->pos_x = xres / 2; @@ -626,9 +625,8 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru return NULL; } - if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL))) + if (!(mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL))) return NULL; - memset(mousedev, 0, sizeof(struct mousedev)); INIT_LIST_HEAD(&mousedev->list); init_waitqueue_head(&mousedev->wait); diff --git a/drivers/input/power.c b/drivers/input/power.c index bfc5c63ebf..526e607060 100644 --- a/drivers/input/power.c +++ b/drivers/input/power.c @@ -103,9 +103,8 @@ static struct input_handle *power_connect(struct input_handler *handler, { struct input_handle *handle; - if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) + if (!(handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL))) return NULL; - memset(handle, 0, sizeof(struct input_handle)); handle->dev = dev; handle->handler = handler; diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 5704204964..73aa8df84b 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c @@ -872,9 +872,8 @@ int hil_mlc_register(hil_mlc *mlc) { for (i = 0; i < HIL_MLC_DEVMEM; i++) { struct serio *mlc_serio; hil_mlc_copy_di_scratch(mlc, i); - mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL); + mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL); mlc->serio[i] = mlc_serio; - memset(mlc_serio, 0, sizeof(*mlc_serio)); mlc_serio->id = hil_mlc_serio_id; mlc_serio->write = hil_mlc_serio_write; mlc_serio->open = hil_mlc_serio_open; diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c index 1d15c28198..a5c1fb3a4a 100644 --- a/drivers/input/serio/parkbd.c +++ b/drivers/input/serio/parkbd.c @@ -171,9 +171,8 @@ static struct serio * __init parkbd_allocate_serio(void) { struct serio *serio; - serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(struct serio), GFP_KERNEL); if (serio) { - memset(serio, 0, sizeof(struct serio)); serio->id.type = parkbd_mode; serio->write = parkbd_write, strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name)); diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index a3bd11589b..513d37fc1a 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c @@ -111,11 +111,10 @@ static int __devinit rpckbd_probe(struct platform_device *dev) { struct serio *serio; - serio = kmalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(struct serio), GFP_KERNEL); if (!serio) return -ENOMEM; - memset(serio, 0, sizeof(struct serio)); serio->id.type = SERIO_8042; serio->write = rpckbd_write; serio->open = rpckbd_open; diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 8734e7f75b..5a2703b536 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -96,12 +96,11 @@ static int serio_raw_open(struct inode *inode, struct file *file) goto out; } - if (!(list = kmalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) { + if (!(list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) { retval = -ENOMEM; goto out; } - memset(list, 0, sizeof(struct serio_raw_list)); list->serio_raw = serio_raw; file->private_data = list; @@ -276,14 +275,13 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) struct serio_raw *serio_raw; int err; - if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) { + if (!(serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL))) { printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n"); return -ENOMEM; } mutex_lock(&serio_raw_mutex); - memset(serio_raw, 0, sizeof(struct serio_raw)); snprintf(serio_raw->name, sizeof(serio_raw->name), "serio_raw%d", serio_raw_no++); serio_raw->refcnt = 1; serio_raw->serio = serio; diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c index ca1547929d..d678d144bb 100644 --- a/drivers/input/tsdev.c +++ b/drivers/input/tsdev.c @@ -157,9 +157,8 @@ static int tsdev_open(struct inode *inode, struct file *file) if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK]) return -ENODEV; - if (!(list = kmalloc(sizeof(struct tsdev_list), GFP_KERNEL))) + if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL))) return -ENOMEM; - memset(list, 0, sizeof(struct tsdev_list)); list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0; @@ -379,9 +378,8 @@ static struct input_handle *tsdev_connect(struct input_handler *handler, return NULL; } - if (!(tsdev = kmalloc(sizeof(struct tsdev), GFP_KERNEL))) + if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL))) return NULL; - memset(tsdev, 0, sizeof(struct tsdev)); INIT_LIST_HEAD(&tsdev->list); init_waitqueue_head(&tsdev->wait); -- cgit v1.2.2 From 50a598de407ea2e2f4e20bc34eeefe8bb5a8071e Mon Sep 17 00:00:00 2001 From: "Micah F. Galizia" Date: Tue, 14 Mar 2006 00:09:34 -0500 Subject: Input: HID - fix duplicate key mapping for Logitech UltraX remote This patch makes the "cc/teletext" key emit "KEY_TEXT" event instead of "KEY_SUBTITLE" which is already mapped to "subtitle" button. Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/usb/input/hid-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index cb0d80f492..25bc85f8ce 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -510,7 +510,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x025: map_key_clear(KEY_TV); break; case 0x026: map_key_clear(KEY_MENU); break; case 0x031: map_key_clear(KEY_AUDIO); break; - case 0x032: map_key_clear(KEY_SUBTITLE); break; + case 0x032: map_key_clear(KEY_TEXT); break; case 0x033: map_key_clear(KEY_LAST); break; case 0x047: map_key_clear(KEY_MP3); break; case 0x048: map_key_clear(KEY_DVD); break; -- cgit v1.2.2 From 9b104c12f12d6b9923e3b779a1f3e45efab7bae6 Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Tue, 14 Mar 2006 00:09:52 -0500 Subject: Input: atkbd - fix complaints about 'releasing unknown key 0x7f' Fix bat_xl and err_xl logic causing atkbd to complain about 'unknown key 0x7f'. Noted by Ben LaHaise. Signed-off-by: Vojtech Pavlik Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index b45981870c..7d26ab4818 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -303,19 +303,19 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, if (atkbd->translated) { if (atkbd->emul || - !(code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1 || - code == ATKBD_RET_HANGUEL || code == ATKBD_RET_HANJA || - (code == ATKBD_RET_ERR && !atkbd->err_xl) || - (code == ATKBD_RET_BAT && !atkbd->bat_xl))) { + (code != ATKBD_RET_EMUL0 && code != ATKBD_RET_EMUL1 && + code != ATKBD_RET_HANGUEL && code != ATKBD_RET_HANJA && + (code != ATKBD_RET_ERR || atkbd->err_xl) && + (code != ATKBD_RET_BAT || atkbd->bat_xl))) { atkbd->release = code >> 7; code &= 0x7f; } if (!atkbd->emul) { if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f)) - atkbd->bat_xl = !atkbd->release; + atkbd->bat_xl = !(data >> 7); if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f)) - atkbd->err_xl = !atkbd->release; + atkbd->err_xl = !(data >> 7); } } -- cgit v1.2.2 From 380e19e2d8aa8fd4739503d890755a717ce20b4f Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Tue, 14 Mar 2006 00:10:08 -0500 Subject: Input: atkbd - disable softrepeat for dumb keyboards Do not activate softrepeat by default on dumb keyboards as it clashes with their own hardware repeat (for example Dell DRAC3). Softrepeat can still be activated manually via module parameter or sysfs. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 7d26ab4818..fad04b66d2 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -863,9 +863,6 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd->softrepeat = atkbd_softrepeat; atkbd->scroll = atkbd_scroll; - if (!atkbd->write) - atkbd->softrepeat = 1; - if (atkbd->softrepeat) atkbd->softraw = 1; -- cgit v1.2.2 From aaef685d5726768d25cbdc672a59c284d820b82e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 14 Mar 2006 00:10:23 -0500 Subject: Input: atkbd - allow disabling on X86_PC (if EMBEDDED) Allow disabling atkbd driver if CONFIG_EMBEDDED is enabled. Previously it was impossible to disable atkbd on X86_PC. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 3b0ac3b43c..a9dda56f62 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -13,7 +13,7 @@ menuconfig INPUT_KEYBOARD if INPUT_KEYBOARD config KEYBOARD_ATKBD - tristate "AT keyboard" if !X86_PC + tristate "AT keyboard" if EMBEDDED || !X86_PC default y select SERIO select SERIO_LIBPS2 -- cgit v1.2.2 From e5c6c8e457d16c7cbc12f849ad18d4d508950de2 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Tue, 14 Mar 2006 00:11:50 -0500 Subject: Input: pcspkr - separate device and driver registration The current pcspkr code combines the device and driver registration. This patch splits these, putting the device registration in the arch specific code. PowerPC and MIPS only have the pcspkr present sometimes. Signed-off-by: Michael Neuling Signed-off-by: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/misc/pcspkr.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 1ef477f446..afd322185b 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -24,7 +24,6 @@ MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("PC Speaker beeper driver"); MODULE_LICENSE("GPL"); -static struct platform_device *pcspkr_platform_device; static DEFINE_SPINLOCK(i8253_beep_lock); static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) @@ -135,35 +134,11 @@ static struct platform_driver pcspkr_platform_driver = { static int __init pcspkr_init(void) { - int err; - - err = platform_driver_register(&pcspkr_platform_driver); - if (err) - return err; - - pcspkr_platform_device = platform_device_alloc("pcspkr", -1); - if (!pcspkr_platform_device) { - err = -ENOMEM; - goto err_unregister_driver; - } - - err = platform_device_add(pcspkr_platform_device); - if (err) - goto err_free_device; - - return 0; - - err_free_device: - platform_device_put(pcspkr_platform_device); - err_unregister_driver: - platform_driver_unregister(&pcspkr_platform_driver); - - return err; + return platform_driver_register(&pcspkr_platform_driver); } static void __exit pcspkr_exit(void) { - platform_device_unregister(pcspkr_platform_device); platform_driver_unregister(&pcspkr_platform_driver); } -- cgit v1.2.2 From dd55563f635751327eb06ae569d4761a0220f2e0 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 14 Mar 2006 00:12:08 -0500 Subject: Input: ns558 - fix logic around pnp_register_driver() Do not assume that pnp_register_driver() returns the number of devices claimed. Signed-off-by: Bjorn Helgaas Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/ns558.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index d2e55dc956..3e2d28f263 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c @@ -252,14 +252,14 @@ static struct pnp_driver ns558_pnp_driver; #endif -static int pnp_registered = 0; - static int __init ns558_init(void) { int i = 0; + int error; - if (pnp_register_driver(&ns558_pnp_driver) >= 0) - pnp_registered = 1; + error = pnp_register_driver(&ns558_pnp_driver); + if (error && error != -ENODEV) /* should be ENOSYS really */ + return error; /* * Probe ISA ports after PnP, so that PnP ports that are already @@ -270,7 +270,7 @@ static int __init ns558_init(void) while (ns558_isa_portlist[i]) ns558_isa_probe(ns558_isa_portlist[i++]); - return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; + return list_empty(&ns558_list) && error ? -ENODEV : 0; } static void __exit ns558_exit(void) @@ -283,8 +283,7 @@ static void __exit ns558_exit(void) kfree(ns558); } - if (pnp_registered) - pnp_unregister_driver(&ns558_pnp_driver); + pnp_unregister_driver(&ns558_pnp_driver); } module_init(ns558_init); -- cgit v1.2.2 From 2bfc3c6e9516ece6856ec7904319650a5d4d9871 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 14 Mar 2006 00:12:24 -0500 Subject: Input: i8042 - fix logic around pnp_register_driver() Do not assume that pnp_register_driver() returns the number of devices claimed. Signed-off-by: Bjorn Helgaas Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index a4c6f35227..f606e96bc2 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -192,7 +192,9 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { #include static int i8042_pnp_kbd_registered; +static unsigned int i8042_pnp_kbd_devices; static int i8042_pnp_aux_registered; +static unsigned int i8042_pnp_aux_devices; static int i8042_pnp_command_reg; static int i8042_pnp_data_reg; @@ -219,6 +221,7 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id * strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name)); } + i8042_pnp_kbd_devices++; return 0; } @@ -239,6 +242,7 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id * strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name)); } + i8042_pnp_aux_devices++; return 0; } @@ -287,21 +291,23 @@ static void i8042_pnp_exit(void) static int __init i8042_pnp_init(void) { - int result_kbd = 0, result_aux = 0; char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 }; + int err; if (i8042_nopnp) { printk(KERN_INFO "i8042: PNP detection disabled\n"); return 0; } - if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0) + err = pnp_register_driver(&i8042_pnp_kbd_driver); + if (!err) i8042_pnp_kbd_registered = 1; - if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0) + err = pnp_register_driver(&i8042_pnp_aux_driver); + if (!err) i8042_pnp_aux_registered = 1; - if (result_kbd <= 0 && result_aux <= 0) { + if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) { i8042_pnp_exit(); #if defined(__ia64__) return -ENODEV; @@ -311,24 +317,24 @@ static int __init i8042_pnp_init(void) #endif } - if (result_kbd > 0) + if (i8042_pnp_kbd_devices) snprintf(kbd_irq_str, sizeof(kbd_irq_str), "%d", i8042_pnp_kbd_irq); - if (result_aux > 0) + if (i8042_pnp_aux_devices) snprintf(aux_irq_str, sizeof(aux_irq_str), "%d", i8042_pnp_aux_irq); printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n", - i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", + i8042_pnp_kbd_name, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "", i8042_pnp_aux_name, i8042_pnp_data_reg, i8042_pnp_command_reg, - kbd_irq_str, (result_kbd > 0 && result_aux > 0) ? "," : "", + kbd_irq_str, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "", aux_irq_str); #if defined(__ia64__) - if (result_kbd <= 0) + if (!i8042_pnp_kbd_devices) i8042_nokbd = 1; - if (result_aux <= 0) + if (!i8042_pnp_aux_devices) i8042_noaux = 1; #endif -- cgit v1.2.2 From 4872f7888855fa52182f3d69de1ff3746fd43c07 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Tue, 14 Mar 2006 00:12:32 -0500 Subject: Input: zaurus keyboard driver updates * Change the scan interval from 100ms to 50ms. This stops the key repeat from triggering on double letter presses. * Remove unneeded stale hinge code from corgikbd * Change unneeded corgi GPIO pins to inputs when suspended * Add support for the headphone jack switch for both corgi and spitz (as switch SW_2) Signed-off-by: Richard Purdie Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/corgikbd.c | 35 ++++++++++++++++++++++++----------- drivers/input/keyboard/spitzkbd.c | 10 +++++++++- 2 files changed, 33 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index e301ee4ca2..96c6bf7724 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c @@ -29,11 +29,11 @@ #define KB_COLS 12 #define KB_ROWMASK(r) (1 << (r)) #define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 ) -/* zero code, 124 scancodes + 3 hinge combinations */ -#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 ) -#define SCAN_INTERVAL (HZ/10) +/* zero code, 124 scancodes */ +#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 ) -#define HINGE_SCAN_INTERVAL (HZ/4) +#define SCAN_INTERVAL (50) /* ms */ +#define HINGE_SCAN_INTERVAL (250) /* ms */ #define CORGI_KEY_CALENDER KEY_F1 #define CORGI_KEY_ADDRESS KEY_F2 @@ -49,9 +49,6 @@ #define CORGI_KEY_MAIL KEY_F10 #define CORGI_KEY_OK KEY_F11 #define CORGI_KEY_MENU KEY_F12 -#define CORGI_HINGE_0 KEY_KP0 -#define CORGI_HINGE_1 KEY_KP1 -#define CORGI_HINGE_2 KEY_KP2 static unsigned char corgikbd_keycode[NR_SCANCODES] = { 0, /* 0 */ @@ -63,7 +60,6 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = { CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ - CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */ }; @@ -187,7 +183,7 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs /* if any keys are pressed, enable the timer */ if (num_pressed) - mod_timer(&corgikbd_data->timer, jiffies + SCAN_INTERVAL); + mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); spin_unlock_irqrestore(&corgikbd_data->lock, flags); } @@ -228,6 +224,7 @@ static void corgikbd_timer_callback(unsigned long data) * 0x0c - Keyboard and Screen Closed */ +#define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x)) #define HINGE_STABLE_COUNT 2 static int sharpsl_hinge_state; static int hinge_count; @@ -239,6 +236,7 @@ static void corgikbd_hinge_timer(unsigned long data) unsigned long flags; gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); + gprr |= (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0); if (gprr != sharpsl_hinge_state) { hinge_count = 0; sharpsl_hinge_state = gprr; @@ -249,27 +247,38 @@ static void corgikbd_hinge_timer(unsigned long data) input_report_switch(corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0)); input_report_switch(corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0)); + input_report_switch(corgikbd_data->input, SW_2, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0)); input_sync(corgikbd_data->input); spin_unlock_irqrestore(&corgikbd_data->lock, flags); } } - mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL); + mod_timer(&corgikbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); } #ifdef CONFIG_PM static int corgikbd_suspend(struct platform_device *dev, pm_message_t state) { + int i; struct corgikbd *corgikbd = platform_get_drvdata(dev); + corgikbd->suspended = 1; + /* strobe 0 is the power key so this can't be made an input for + powersaving therefore i = 1 */ + for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) + pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_IN); return 0; } static int corgikbd_resume(struct platform_device *dev) { + int i; struct corgikbd *corgikbd = platform_get_drvdata(dev); + for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) + pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); + /* Upon resume, ignore the suspend key for a short while */ corgikbd->suspend_jiffies=jiffies; corgikbd->suspended = 0; @@ -333,10 +342,11 @@ static int __init corgikbd_probe(struct platform_device *pdev) clear_bit(0, input_dev->keybit); set_bit(SW_0, input_dev->swbit); set_bit(SW_1, input_dev->swbit); + set_bit(SW_2, input_dev->swbit); input_register_device(corgikbd->input); - mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL); + mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { @@ -351,6 +361,9 @@ static int __init corgikbd_probe(struct platform_device *pdev) for (i = 0; i < CORGI_KEY_STROBE_NUM; i++) pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); + /* Setup the headphone jack as an input */ + pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN); + return 0; } diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index 83999d5831..bc61cf8cfc 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c @@ -30,6 +30,7 @@ #define SCANCODE(r,c) (((r)<<4) + (c) + 1) #define NR_SCANCODES ((KB_ROWS<<4) + 1) +#define SCAN_INTERVAL (50) /* ms */ #define HINGE_SCAN_INTERVAL (150) /* ms */ #define SPITZ_KEY_CALENDER KEY_F1 @@ -230,7 +231,7 @@ static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs /* if any keys are pressed, enable the timer */ if (num_pressed) - mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(100)); + mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); spin_unlock_irqrestore(&spitzkbd_data->lock, flags); } @@ -287,6 +288,7 @@ static void spitzkbd_hinge_timer(unsigned long data) unsigned long flags; state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB)); + state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)); if (state != sharpsl_hinge_state) { hinge_count = 0; sharpsl_hinge_state = state; @@ -299,6 +301,7 @@ static void spitzkbd_hinge_timer(unsigned long data) input_report_switch(spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0)); input_report_switch(spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0)); + input_report_switch(spitzkbd_data->input, SW_2, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0)); input_sync(spitzkbd_data->input); spin_unlock_irqrestore(&spitzkbd_data->lock, flags); @@ -397,6 +400,7 @@ static int __init spitzkbd_probe(struct platform_device *dev) clear_bit(0, input_dev->keybit); set_bit(SW_0, input_dev->swbit); set_bit(SW_1, input_dev->swbit); + set_bit(SW_2, input_dev->swbit); input_register_device(input_dev); @@ -432,6 +436,9 @@ static int __init spitzkbd_probe(struct platform_device *dev) request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, "Spitzkbd SWB", spitzkbd); + request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr, + SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, + "Spitzkbd HP", spitzkbd); printk(KERN_INFO "input: Spitz Keyboard Registered\n"); @@ -450,6 +457,7 @@ static int spitzkbd_remove(struct platform_device *dev) free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd); free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd); free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd); + free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd); del_timer_sync(&spitzkbd->htimer); del_timer_sync(&spitzkbd->timer); -- cgit v1.2.2 From 9d921116cc5e27c1950b7e7508fdefec04a69963 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 14 Mar 2006 00:13:29 -0500 Subject: Input: serio - fix memory leak Signed-off-by: Adrian Bunk Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 966600779b..6521034bc9 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -196,6 +196,7 @@ static void serio_queue_event(void *object, struct module *owner, if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) { if (!try_module_get(owner)) { printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type); + kfree(event); goto out; } -- cgit v1.2.2 From 642fde17dceceb56c7ba2762733ac688666ae657 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 14 Mar 2006 00:13:34 -0500 Subject: Input: gameport - fix memory leak Signed-off-by: Adrian Bunk Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/gameport.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index bcfd700829..36644bff37 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -266,6 +266,7 @@ static void gameport_queue_event(void *object, struct module *owner, if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) { if (!try_module_get(owner)) { printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type); + kfree(event); goto out; } -- cgit v1.2.2 From ddf19b973be5a96d77c8467f657fe5bd7d126e0f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 18:56:12 +1100 Subject: drm: fixup PCI DMA support This patch makes the PCI support use the correct Linux interfaces finally. Tested in DRM CVS on PCI MGA card. Signed-off-by: Dave Airlie --- drivers/char/drm/drmP.h | 14 +++++++------- drivers/char/drm/drm_bufs.c | 20 +++++++++++--------- drivers/char/drm/drm_dma.c | 4 +--- drivers/char/drm/drm_pci.c | 29 +++++++++++++++++++++++++---- 4 files changed, 44 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 107df9fdba..dbe952f899 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -357,6 +357,12 @@ typedef struct drm_freelist { spinlock_t lock; } drm_freelist_t; +typedef struct drm_dma_handle { + dma_addr_t busaddr; + void *vaddr; + size_t size; +} drm_dma_handle_t; + /** * Buffer entry. There is one of this for each buffer size order. */ @@ -366,7 +372,7 @@ typedef struct drm_buf_entry { drm_buf_t *buflist; /**< buffer list */ int seg_count; int page_order; - unsigned long *seglist; + drm_dma_handle_t **seglist; drm_freelist_t freelist; } drm_buf_entry_t; @@ -483,12 +489,6 @@ typedef struct drm_sigdata { drm_hw_lock_t *lock; } drm_sigdata_t; -typedef struct drm_dma_handle { - dma_addr_t busaddr; - void *vaddr; - size_t size; -} drm_dma_handle_t; - /** * Mappings list */ diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index e2637b4d51..8a9cf12e61 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c @@ -474,8 +474,7 @@ static void drm_cleanup_buf_error(drm_device_t * dev, drm_buf_entry_t * entry) if (entry->seg_count) { for (i = 0; i < entry->seg_count; i++) { if (entry->seglist[i]) { - drm_free_pages(entry->seglist[i], - entry->page_order, DRM_MEM_DMA); + drm_pci_free(dev, entry->seglist[i]); } } drm_free(entry->seglist, @@ -678,7 +677,7 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) int total; int page_order; drm_buf_entry_t *entry; - unsigned long page; + drm_dma_handle_t *dmah; drm_buf_t *buf; int alignment; unsigned long offset; @@ -781,8 +780,10 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) page_count = 0; while (entry->buf_count < count) { - page = drm_alloc_pages(page_order, DRM_MEM_DMA); - if (!page) { + + dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful); + + if (!dmah) { /* Set count correctly so we free the proper amount. */ entry->buf_count = count; entry->seg_count = count; @@ -794,13 +795,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) atomic_dec(&dev->buf_alloc); return -ENOMEM; } - entry->seglist[entry->seg_count++] = page; + entry->seglist[entry->seg_count++] = dmah; for (i = 0; i < (1 << page_order); i++) { DRM_DEBUG("page %d @ 0x%08lx\n", dma->page_count + page_count, - page + PAGE_SIZE * i); + (unsigned long)dmah->vaddr + PAGE_SIZE * i); temp_pagelist[dma->page_count + page_count++] - = page + PAGE_SIZE * i; + = (unsigned long)dmah->vaddr + PAGE_SIZE * i; } for (offset = 0; offset + size <= total && entry->buf_count < count; @@ -811,7 +812,8 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) buf->order = order; buf->used = 0; buf->offset = (dma->byte_count + byte_count + offset); - buf->address = (void *)(page + offset); + buf->address = (void *)(dmah->vaddr + offset); + buf->bus_address = dmah->busaddr + offset; buf->next = NULL; buf->waiting = 0; buf->pending = 0; diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c index 2afab95ca0..892db70969 100644 --- a/drivers/char/drm/drm_dma.c +++ b/drivers/char/drm/drm_dma.c @@ -85,9 +85,7 @@ void drm_dma_takedown(drm_device_t * dev) dma->bufs[i].seg_count); for (j = 0; j < dma->bufs[i].seg_count; j++) { if (dma->bufs[i].seglist[j]) { - drm_free_pages(dma->bufs[i].seglist[j], - dma->bufs[i].page_order, - DRM_MEM_DMA); + drm_pci_free(dev, dma->bufs[i].seglist[j]); } } drm_free(dma->bufs[i].seglist, diff --git a/drivers/char/drm/drm_pci.c b/drivers/char/drm/drm_pci.c index 1fd7ff1648..b28ca9cea8 100644 --- a/drivers/char/drm/drm_pci.c +++ b/drivers/char/drm/drm_pci.c @@ -50,6 +50,10 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, dma_addr_t maxaddr) { drm_dma_handle_t *dmah; +#if 1 + unsigned long addr; + size_t sz; +#endif #ifdef DRM_DEBUG_MEMORY int area = DRM_MEM_DMA; @@ -79,7 +83,7 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, return NULL; dmah->size = size; - dmah->vaddr = pci_alloc_consistent(dev->pdev, size, &dmah->busaddr); + dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, GFP_KERNEL | __GFP_COMP); #ifdef DRM_DEBUG_MEMORY if (dmah->vaddr == NULL) { @@ -104,18 +108,29 @@ drm_dma_handle_t *drm_pci_alloc(drm_device_t * dev, size_t size, size_t align, memset(dmah->vaddr, 0, size); + /* XXX - Is virt_to_page() legal for consistent mem? */ + /* Reserve */ + for (addr = (unsigned long)dmah->vaddr, sz = size; + sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { + SetPageReserved(virt_to_page(addr)); + } + return dmah; } EXPORT_SYMBOL(drm_pci_alloc); /** - * \brief Free a PCI consistent memory block with freeing its descriptor. + * \brief Free a PCI consistent memory block without freeing its descriptor. * * This function is for internal use in the Linux-specific DRM core code. */ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) { +#if 1 + unsigned long addr; + size_t sz; +#endif #ifdef DRM_DEBUG_MEMORY int area = DRM_MEM_DMA; int alloc_count; @@ -127,8 +142,14 @@ void __drm_pci_free(drm_device_t * dev, drm_dma_handle_t * dmah) DRM_MEM_ERROR(area, "Attempt to free address 0\n"); #endif } else { - pci_free_consistent(dev->pdev, dmah->size, dmah->vaddr, - dmah->busaddr); + /* XXX - Is virt_to_page() legal for consistent mem? */ + /* Unreserve */ + for (addr = (unsigned long)dmah->vaddr, sz = dmah->size; + sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { + ClearPageReserved(virt_to_page(addr)); + } + dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr, + dmah->busaddr); } #ifdef DRM_DEBUG_MEMORY -- cgit v1.2.2 From 45f17100bfd18c99d6479e94598f4e533bbe30d8 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 19:12:10 +1100 Subject: drm: update r300 register names Update some of the DRM register names from DRM CVS Signed-off-by: Dave Airlie --- drivers/char/drm/r300_cmdbuf.c | 4 ++-- drivers/char/drm/r300_reg.h | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index c08fa5076f..9fbadb9658 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c @@ -214,13 +214,13 @@ void r300_init_reg_flags(void) ADD_RANGE(0x4F54, 1); ADD_RANGE(R300_TX_FILTER_0, 16); - ADD_RANGE(R300_TX_UNK1_0, 16); + ADD_RANGE(R300_TX_FILTER1_0, 16); ADD_RANGE(R300_TX_SIZE_0, 16); ADD_RANGE(R300_TX_FORMAT_0, 16); ADD_RANGE(R300_TX_PITCH_0, 16); /* Texture offset is dangerous and needs more checking */ ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); - ADD_RANGE(R300_TX_UNK4_0, 16); + ADD_RANGE(R300_TX_CHROMA_KEY_0, 16); ADD_RANGE(R300_TX_BORDER_COLOR_0, 16); /* Sporadic registers used as primitives are emitted */ diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h index d1e1995440..a881f96c98 100644 --- a/drivers/char/drm/r300_reg.h +++ b/drivers/char/drm/r300_reg.h @@ -711,8 +711,22 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_MAX_ANISO_16_TO_1 (8 << 21) # define R300_TX_MAX_ANISO_MASK (14 << 21) -#define R300_TX_UNK1_0 0x4440 +#define R300_TX_FILTER1_0 0x4440 +# define R300_CHROMA_KEY_MODE_DISABLE 0 +# define R300_CHROMA_KEY_FORCE 1 +# define R300_CHROMA_KEY_BLEND 2 +# define R300_MC_ROUND_NORMAL (0<<2) +# define R300_MC_ROUND_MPEG4 (1<<2) # define R300_LOD_BIAS_MASK 0x1fff +# define R300_EDGE_ANISO_EDGE_DIAG (0<<13) +# define R300_EDGE_ANISO_EDGE_ONLY (1<<13) +# define R300_MC_COORD_TRUNCATE_DISABLE (0<<14) +# define R300_MC_COORD_TRUNCATE_MPEG (1<<14) +# define R300_TX_TRI_PERF_0_8 (0<<15) +# define R300_TX_TRI_PERF_1_8 (1<<15) +# define R300_TX_TRI_PERF_1_4 (2<<15) +# define R300_TX_TRI_PERF_3_8 (3<<15) +# define R300_ANISO_THRESHOLD_MASK (7<<17) #define R300_TX_SIZE_0 0x4480 # define R300_TX_WIDTHMASK_SHIFT 0 @@ -722,6 +736,8 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_UNK23 (1 << 23) # define R300_TX_SIZE_SHIFT 26 /* largest of width, height */ # define R300_TX_SIZE_MASK (15 << 26) +# define R300_TX_SIZE_PROJECTED (1<<30) +# define R300_TX_SIZE_TXPITCH_EN (1<<31) #define R300_TX_FORMAT_0 0x44C0 /* The interpretation of the format word by Wladimir van der Laan */ /* The X, Y, Z and W refer to the layout of the components. @@ -750,7 +766,8 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ # define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ /* 0x16 - some 16 bit green format.. ?? */ -# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ +# define R300_TX_FORMAT_UNK25 (1 << 25) /* no swizzle */ +# define R300_TX_FORMAT_CUBIC_MAP (1 << 26) /* gap */ /* Floating point formats */ @@ -800,18 +817,20 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_TX_FORMAT_YUV_MODE 0x00800000 -#define R300_TX_PITCH_0 0x4500 +#define R300_TX_PITCH_0 0x4500 /* obvious missing in gap */ #define R300_TX_OFFSET_0 0x4540 /* BEGIN: Guess from R200 */ # define R300_TXO_ENDIAN_NO_SWAP (0 << 0) # define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0) # define R300_TXO_ENDIAN_WORD_SWAP (2 << 0) # define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0) +# define R300_TXO_MACRO_TILE (1 << 2) +# define R300_TXO_MICRO_TILE (1 << 3) # define R300_TXO_OFFSET_MASK 0xffffffe0 # define R300_TXO_OFFSET_SHIFT 5 /* END */ -#define R300_TX_UNK4_0 0x4580 -#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 } +#define R300_TX_CHROMA_KEY_0 0x4580 /* 32 bit chroma key */ +#define R300_TX_BORDER_COLOR_0 0x45C0 //ff00ff00 == { 0, 1.0, 0, 1.0 } /* END */ @@ -868,7 +887,9 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_PFS_NODE_TEX_OFFSET_MASK (31 << 12) # define R300_PFS_NODE_TEX_END_SHIFT 17 # define R300_PFS_NODE_TEX_END_MASK (31 << 17) -# define R300_PFS_NODE_LAST_NODE (1 << 22) +/*# define R300_PFS_NODE_LAST_NODE (1 << 22) */ +# define R300_PFS_NODE_OUTPUT_COLOR (1 << 22) +# define R300_PFS_NODE_OUTPUT_DEPTH (1 << 23) /* TEX // As far as I can tell, texture instructions cannot write into output @@ -887,6 +908,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. */ # define R300_FPITX_OPCODE_SHIFT 15 # define R300_FPITX_OP_TEX 1 +# define R300_FPITX_OP_KIL 2 # define R300_FPITX_OP_TXP 3 # define R300_FPITX_OP_TXB 4 @@ -962,9 +984,11 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_FPI1_SRC2C_CONST (1 << 17) # define R300_FPI1_DSTC_SHIFT 18 # define R300_FPI1_DSTC_MASK (31 << 18) +# define R300_FPI1_DSTC_REG_MASK_SHIFT 23 # define R300_FPI1_DSTC_REG_X (1 << 23) # define R300_FPI1_DSTC_REG_Y (1 << 24) # define R300_FPI1_DSTC_REG_Z (1 << 25) +# define R300_FPI1_DSTC_OUTPUT_MASK_SHIFT 26 # define R300_FPI1_DSTC_OUTPUT_X (1 << 26) # define R300_FPI1_DSTC_OUTPUT_Y (1 << 27) # define R300_FPI1_DSTC_OUTPUT_Z (1 << 28) @@ -983,6 +1007,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_FPI3_DSTA_MASK (31 << 18) # define R300_FPI3_DSTA_REG (1 << 23) # define R300_FPI3_DSTA_OUTPUT (1 << 24) +# define R300_FPI3_DSTA_DEPTH (1 << 27) #define R300_PFS_INSTR0_0 0x48C0 # define R300_FPI0_ARGC_SRC0C_XYZ 0 @@ -1036,7 +1061,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_FPI0_OUTC_FRC (9 << 23) # define R300_FPI0_OUTC_REPL_ALPHA (10 << 23) # define R300_FPI0_OUTC_SAT (1 << 30) -# define R300_FPI0_UNKNOWN_31 (1 << 31) +# define R300_FPI0_INSERT_NOP (1 << 31) #define R300_PFS_INSTR2_0 0x49C0 # define R300_FPI2_ARGA_SRC0C_X 0 -- cgit v1.2.2 From d5ea702f1e8e3edeea6b673a58281bf99f3dbec5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 19:37:55 +1100 Subject: drm: rework radeon memory map (radeon 1.23) This code reworks the radeon memory map so it works better for newer r300 chips and for a lot of older PCI chips. It really requires a new X driver in order to take advantage of this code. From: Ben Herrenschmidt Signed-off-by: Dave Airlie --- drivers/char/drm/r300_cmdbuf.c | 15 +++-- drivers/char/drm/radeon_cp.c | 143 ++++++++++++++++++++++++++++------------ drivers/char/drm/radeon_drm.h | 1 + drivers/char/drm/radeon_drv.h | 10 ++- drivers/char/drm/radeon_state.c | 58 ++++++++++++---- 5 files changed, 163 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 9fbadb9658..20b6cb3921 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c @@ -242,8 +242,10 @@ static __inline__ int r300_check_range(unsigned reg, int count) return 0; } - /* we expect offsets passed to the framebuffer to be either within video memory or - within AGP space */ +/* + * we expect offsets passed to the framebuffer to be either within video + * memory or within AGP space + */ static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, u32 offset) { @@ -251,11 +253,11 @@ static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, but this value is not being kept. This code is correct for now (does the same thing as the code that sets MC_FB_LOCATION) in radeon_cp.c */ - if ((offset >= dev_priv->fb_location) && - (offset < dev_priv->gart_vm_start)) + if (offset >= dev_priv->fb_location && + offset < (dev_priv->fb_location + dev_priv->fb_size)) return 0; - if ((offset >= dev_priv->gart_vm_start) && - (offset < dev_priv->gart_vm_start + dev_priv->gart_size)) + if (offset >= dev_priv->gart_vm_start && + offset < (dev_priv->gart_vm_start + dev_priv->gart_size)) return 0; return 1; } @@ -490,6 +492,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, return 0; } + static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, drm_radeon_kcmd_buffer_t *cmdbuf) { diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 9bb8ae0c1c..cc4942a112 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -1118,14 +1118,20 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, { u32 ring_start, cur_read_ptr; u32 tmp; - - /* Initialize the memory controller */ - RADEON_WRITE(RADEON_MC_FB_LOCATION, - ((dev_priv->gart_vm_start - 1) & 0xffff0000) - | (dev_priv->fb_location >> 16)); + + /* Initialize the memory controller. With new memory map, the fb location + * is not changed, it should have been properly initialized already. Part + * of the problem is that the code below is bogus, assuming the GART is + * always appended to the fb which is not necessarily the case + */ + if (!dev_priv->new_memmap) + RADEON_WRITE(RADEON_MC_FB_LOCATION, + ((dev_priv->gart_vm_start - 1) & 0xffff0000) + | (dev_priv->fb_location >> 16)); #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { + RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); RADEON_WRITE(RADEON_MC_AGP_LOCATION, (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & 0xffff0000) | @@ -1153,8 +1159,6 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) { - /* set RADEON_AGP_BASE here instead of relying on X from user space */ - RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset - dev->agp->base + dev_priv->gart_vm_start); @@ -1174,6 +1178,17 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, entry->handle + tmp_ofs); } + /* Set ring buffer size */ +#ifdef __BIG_ENDIAN + RADEON_WRITE(RADEON_CP_RB_CNTL, + dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT); +#else + RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw); +#endif + + /* Start with assuming that writeback doesn't work */ + dev_priv->writeback_works = 0; + /* Initialize the scratch register pointer. This will cause * the scratch register values to be written out to memory * whenever they are updated. @@ -1190,28 +1205,9 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); - /* Writeback doesn't seem to work everywhere, test it first */ - DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); - RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); - - for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { - if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) == - 0xdeadbeef) - break; - DRM_UDELAY(1); - } - - if (tmp < dev_priv->usec_timeout) { - dev_priv->writeback_works = 1; - DRM_DEBUG("writeback test succeeded, tmp=%d\n", tmp); - } else { - dev_priv->writeback_works = 0; - DRM_DEBUG("writeback test failed\n"); - } - if (radeon_no_wb == 1) { - dev_priv->writeback_works = 0; - DRM_DEBUG("writeback forced off\n"); - } + /* Turn on bus mastering */ + tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; + RADEON_WRITE(RADEON_BUS_CNTL, tmp); dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0; RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); @@ -1223,26 +1219,45 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0; RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear); - /* Set ring buffer size */ -#ifdef __BIG_ENDIAN - RADEON_WRITE(RADEON_CP_RB_CNTL, - dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT); -#else - RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw); -#endif - radeon_do_wait_for_idle(dev_priv); - /* Turn on bus mastering */ - tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; - RADEON_WRITE(RADEON_BUS_CNTL, tmp); - /* Sync everything up */ RADEON_WRITE(RADEON_ISYNC_CNTL, (RADEON_ISYNC_ANY2D_IDLE3D | RADEON_ISYNC_ANY3D_IDLE2D | RADEON_ISYNC_WAIT_IDLEGUI | RADEON_ISYNC_CPSCRATCH_IDLEGUI)); + +} + +static void radeon_test_writeback(drm_radeon_private_t * dev_priv) +{ + u32 tmp; + + /* Writeback doesn't seem to work everywhere, test it here and possibly + * enable it if it appears to work + */ + DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0); + RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); + + for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { + if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) == + 0xdeadbeef) + break; + DRM_UDELAY(1); + } + + if (tmp < dev_priv->usec_timeout) { + dev_priv->writeback_works = 1; + DRM_INFO("writeback test succeeded in %d usecs\n", tmp); + } else { + dev_priv->writeback_works = 0; + DRM_INFO("writeback test failed\n"); + } + if (radeon_no_wb == 1) { + dev_priv->writeback_works = 0; + DRM_INFO("writeback forced off\n"); + } } /* Enable or disable PCI-E GART on the chip */ @@ -1496,6 +1511,9 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff) << 16; + dev_priv->fb_size = + ((RADEON_READ(RADEON_MC_FB_LOCATION) & 0xffff0000u) + 0x10000) + - dev_priv->fb_location; dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | ((dev_priv->front_offset @@ -1510,8 +1528,46 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) + dev_priv->fb_location) >> 10)); dev_priv->gart_size = init->gart_size; - dev_priv->gart_vm_start = dev_priv->fb_location - + RADEON_READ(RADEON_CONFIG_APER_SIZE); + + /* New let's set the memory map ... */ + if (dev_priv->new_memmap) { + u32 base = 0; + + DRM_INFO("Setting GART location based on new memory map\n"); + + /* If using AGP, try to locate the AGP aperture at the same + * location in the card and on the bus, though we have to + * align it down. + */ +#if __OS_HAS_AGP + if (dev_priv->flags & CHIP_IS_AGP) { + base = dev->agp->base; + /* Check if valid */ + if ((base + dev_priv->gart_size) > dev_priv->fb_location && + base < (dev_priv->fb_location + dev_priv->fb_size)) { + DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", + dev->agp->base); + base = 0; + } + } +#endif + /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ + if (base == 0) { + base = dev_priv->fb_location + dev_priv->fb_size; + if (((base + dev_priv->gart_size) & 0xfffffffful) + < base) + base = dev_priv->fb_location + - dev_priv->gart_size; + } + dev_priv->gart_vm_start = base & 0xffc00000u; + if (dev_priv->gart_vm_start != base) + DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n", + base, dev_priv->gart_vm_start); + } else { + DRM_INFO("Setting GART location based on old memory map\n"); + dev_priv->gart_vm_start = dev_priv->fb_location + + RADEON_READ(RADEON_CONFIG_APER_SIZE); + } #if __OS_HAS_AGP if (dev_priv->flags & CHIP_IS_AGP) @@ -1596,6 +1652,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) dev_priv->last_buf = 0; radeon_do_engine_reset(dev); + radeon_test_writeback(dev_priv); return 0; } diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index 9c177a6b2a..bb63e6806f 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h @@ -697,6 +697,7 @@ typedef struct drm_radeon_setparam { #define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ +#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ /* 1.14: Clients can allocate/free a surface */ diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 1f7d2ab8c4..a0c198895a 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -38,7 +38,7 @@ #define DRIVER_NAME "radeon" #define DRIVER_DESC "ATI Radeon" -#define DRIVER_DATE "20051229" +#define DRIVER_DATE "20060225" /* Interface history: * @@ -91,9 +91,10 @@ * 1.20- Add support for r300 texrect * 1.21- Add support for card type getparam * 1.22- Add support for texture cache flushes (R300_TX_CNTL) + * 1.23- Add new radeon memory map work from benh */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 22 +#define DRIVER_MINOR 23 #define DRIVER_PATCHLEVEL 0 /* @@ -138,7 +139,8 @@ enum radeon_chip_flags { CHIP_IS_PCIE = 0x00200000UL, }; -#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 ) +#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ + DRM_READ32( (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR)) #define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) ) typedef struct drm_radeon_freelist { @@ -199,6 +201,8 @@ typedef struct drm_radeon_private { drm_radeon_sarea_t *sarea_priv; u32 fb_location; + u32 fb_size; + int new_memmap; int gart_size; u32 gart_vm_start; diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 7bc27516d4..56e56b8736 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -45,22 +45,53 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * u32 off = *offset; struct drm_radeon_driver_file_fields *radeon_priv; - if (off >= dev_priv->fb_location && - off < (dev_priv->gart_vm_start + dev_priv->gart_size)) - return 0; - - radeon_priv = filp_priv->driver_priv; - off += radeon_priv->radeon_fb_delta; + /* Hrm ... the story of the offset ... So this function converts + * the various ideas of what userland clients might have for an + * offset in the card address space into an offset into the card + * address space :) So with a sane client, it should just keep + * the value intact and just do some boundary checking. However, + * not all clients are sane. Some older clients pass us 0 based + * offsets relative to the start of the framebuffer and some may + * assume the AGP aperture it appended to the framebuffer, so we + * try to detect those cases and fix them up. + * + * Note: It might be a good idea here to make sure the offset lands + * in some "allowed" area to protect things like the PCIE GART... + */ - DRM_DEBUG("offset fixed up to 0x%x\n", off); + /* First, the best case, the offset already lands in either the + * framebuffer or the GART mapped space + */ + if ((off >= dev_priv->fb_location && + off < (dev_priv->fb_location + dev_priv->fb_size)) || + (off >= dev_priv->gart_vm_start && + off < (dev_priv->gart_vm_start + dev_priv->gart_size))) + return 0; - if (off < dev_priv->fb_location || - off >= (dev_priv->gart_vm_start + dev_priv->gart_size)) - return DRM_ERR(EINVAL); + /* Ok, that didn't happen... now check if we have a zero based + * offset that fits in the framebuffer + gart space, apply the + * magic offset we get from SETPARAM or calculated from fb_location + */ + if (off < (dev_priv->fb_size + dev_priv->gart_size)) { + radeon_priv = filp_priv->driver_priv; + off += radeon_priv->radeon_fb_delta; + } - *offset = off; + /* Finally, assume we aimed at a GART offset if beyond the fb */ + if (off > (dev_priv->fb_location + dev_priv->fb_size)) + off = off - (dev_priv->fb_location + dev_priv->fb_size) + + dev_priv->gart_vm_start; - return 0; + /* Now recheck and fail if out of bounds */ + if ((off >= dev_priv->fb_location && + off < (dev_priv->fb_location + dev_priv->fb_size)) || + (off >= dev_priv->gart_vm_start && + off < (dev_priv->gart_vm_start + dev_priv->gart_size))) { + DRM_DEBUG("offset fixed up to 0x%x\n", off); + *offset = off; + return 0; + } + return DRM_ERR(EINVAL); } static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * @@ -3012,6 +3043,9 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) case RADEON_SETPARAM_PCIGART_LOCATION: dev_priv->pcigart_offset = sp.value; break; + case RADEON_SETPARAM_NEW_MEMMAP: + dev_priv->new_memmap = sp.value; + break; default: DRM_DEBUG("Invalid parameter %d\n", sp.param); return DRM_ERR(EINVAL); -- cgit v1.2.2 From ee4621f011750a6eff9f56631e12ab7fd9503aaa Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 19:45:26 +1100 Subject: drm: Add general-purpose packet for manipulating scratch registers (r300) From: Aapo Tahkola (via DRM CVS) Signed-off-by: Dave Airlie --- drivers/char/drm/r300_cmdbuf.c | 67 ++++++++++++++++++++++++++++++++++++++++++ drivers/char/drm/radeon_drm.h | 4 +++ drivers/char/drm/radeon_drv.h | 5 +++- 3 files changed, 75 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 20b6cb3921..b108c7f913 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c @@ -704,6 +704,64 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf) buf->used = 0; } +static int r300_scratch(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf, + drm_r300_cmd_header_t header) +{ + u32 *ref_age_base; + u32 i, buf_idx, h_pending; + RING_LOCALS; + + if (cmdbuf->bufsz < + (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) { + return DRM_ERR(EINVAL); + } + + if (header.scratch.reg >= 5) { + return DRM_ERR(EINVAL); + } + + dev_priv->scratch_ages[header.scratch.reg]++; + + ref_age_base = *(u32 **)cmdbuf->buf; + + cmdbuf->buf += sizeof(u64); + cmdbuf->bufsz -= sizeof(u64); + + for (i=0; i < header.scratch.n_bufs; i++) { + buf_idx = *(u32 *)cmdbuf->buf; + buf_idx *= 2; /* 8 bytes per buf */ + + if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + if (h_pending == 0) { + return DRM_ERR(EINVAL); + } + + h_pending--; + + if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) { + return DRM_ERR(EINVAL); + } + + cmdbuf->buf += sizeof(buf_idx); + cmdbuf->bufsz -= sizeof(buf_idx); + } + + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0)); + OUT_RING(dev_priv->scratch_ages[header.scratch.reg]); + ADVANCE_RING(); + + return 0; +} + /** * Parses and validates a user-supplied command buffer and emits appropriate * commands on the DMA ring buffer. @@ -841,6 +899,15 @@ int r300_do_cp_cmdbuf(drm_device_t *dev, } break; + case R300_CMD_SCRATCH: + DRM_DEBUG("R300_CMD_SCRATCH\n"); + ret = r300_scratch(dev_priv, cmdbuf, header); + if (ret) { + DRM_ERROR("r300_scratch failed\n"); + goto cleanup; + } + break; + default: DRM_ERROR("bad cmd_type %i at %p\n", header.header.cmd_type, diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index bb63e6806f..c8e279e89c 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h @@ -222,6 +222,7 @@ typedef union { # define R300_WAIT_3D 0x2 # define R300_WAIT_2D_CLEAN 0x3 # define R300_WAIT_3D_CLEAN 0x4 +#define R300_CMD_SCRATCH 8 typedef union { unsigned int u; @@ -247,6 +248,9 @@ typedef union { struct { unsigned char cmd_type, flags, pad0, pad1; } wait; + struct { + unsigned char cmd_type, reg, n_bufs, flags; + } scratch; } drm_r300_cmd_header_t; #define RADEON_FRONT 0x1 diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index a0c198895a..5cf555e463 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -92,9 +92,10 @@ * 1.21- Add support for card type getparam * 1.22- Add support for texture cache flushes (R300_TX_CNTL) * 1.23- Add new radeon memory map work from benh + * 1.24- Add general-purpose packet for manipulating scratch registers (r300) */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 23 +#define DRIVER_MINOR 24 #define DRIVER_PATCHLEVEL 0 /* @@ -276,6 +277,8 @@ typedef struct drm_radeon_private { unsigned long pcigart_offset; drm_ati_pcigart_info gart_info; + u32 scratch_ages[5]; + /* starting from here on, data is preserved accross an open */ uint32_t flags; /* see radeon_chip_flags */ } drm_radeon_private_t; -- cgit v1.2.2 From dfab11542fbecd8539c092fe36155909b4812f73 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 20:01:37 +1100 Subject: drm: rationalise some pci ids This is the start of some work from Roland Scheidegger to align the X DDX pci ids and the drm ones, however we don't want to put r300 ids in the kernel just yet, they destabilise a few machines. From: Roland Scheidegger (via DRM CVS) Signed-off-by: Dave Airlie --- drivers/char/drm/drm_pciids.h | 19 ++++++++----------- drivers/char/drm/radeon_drv.h | 11 ++++++----- 2 files changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 2c17e88a88..24b80357b9 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -3,7 +3,7 @@ Please contact dri-devel@lists.sf.net to add new cards to this list */ #define radeon_PCI_IDS \ - {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350},\ + {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY},\ {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ @@ -16,26 +16,23 @@ {0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ - {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP}, \ + {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS250|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ - {0x1002, 0x4965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ - {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ - {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250}, \ + {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ + {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ - {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R250|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 5cf555e463..31bacfa2ed 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -103,20 +103,21 @@ */ enum radeon_family { CHIP_R100, - CHIP_RS100, CHIP_RV100, + CHIP_RS100, CHIP_RV200, - CHIP_R200, CHIP_RS200, - CHIP_R250, - CHIP_RS250, + CHIP_R200, CHIP_RV250, + CHIP_RS300, CHIP_RV280, CHIP_R300, - CHIP_RS300, CHIP_R350, CHIP_RV350, + CHIP_RV380, CHIP_R420, + CHIP_RV410, + CHIP_RS400, CHIP_LAST, }; -- cgit v1.2.2 From f15e92d702bba47f451bd5f63e170252c6e1bba2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 20:12:23 +1100 Subject: drm: fixup improper cast. Signed-off-by: Dave Airlie --- drivers/char/drm/radeon_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 56e56b8736..b006b1c5d8 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -1996,7 +1996,7 @@ static int radeon_surface_free(DRM_IOCTL_ARGS) return DRM_ERR(EINVAL); } - DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data, + DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data, sizeof(memfree)); if (free_surface(filp, dev_priv, memfree.address)) -- cgit v1.2.2 From 2fab58d1a18c752887c2b9f6ee7b6997ced4a77a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 20:15:41 +1100 Subject: drm: remove pointless checks in radeon_state If these were valid checks, we'd have already oopsed several lines above where we were already dereferencing them. DA: these used to be valid but other changes made them unnecessary. Coverity: 776,777,778 Signed-off-by: Dave Jones Signed-off-by: Dave Airlie --- drivers/char/drm/radeon_state.c | 45 ----------------------------------------- 1 file changed, 45 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index b006b1c5d8..c5b8f774a5 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -1970,11 +1970,6 @@ static int radeon_surface_alloc(DRM_IOCTL_ARGS) drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_surface_alloc_t alloc; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_surface_alloc_t __user *) data, sizeof(alloc)); @@ -1991,11 +1986,6 @@ static int radeon_surface_free(DRM_IOCTL_ARGS) drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_surface_free_t memfree; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data, sizeof(memfree)); @@ -2131,11 +2121,6 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data, @@ -2220,11 +2205,6 @@ static int radeon_cp_indices(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data, @@ -2371,11 +2351,6 @@ static int radeon_cp_indirect(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_COPY_FROM_USER_IOCTL(indirect, (drm_radeon_indirect_t __user *) data, sizeof(indirect)); @@ -2448,11 +2423,6 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data, @@ -2769,11 +2739,6 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) LOCK_TEST_WITH_RETURN(dev, filp); - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(cmdbuf, @@ -2928,11 +2893,6 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) drm_radeon_getparam_t param; int value; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data, sizeof(param)); @@ -3012,11 +2972,6 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) drm_radeon_setparam_t sp; struct drm_radeon_driver_file_fields *radeon_priv; - if (!dev_priv) { - DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); - } - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data, -- cgit v1.2.2 From e7f947b908921a661efcbc08ce42d7de67691b07 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 19 Mar 2006 20:28:19 +1100 Subject: drm: fixup i915 breadcrumb read/write Some minor issues in the i915 breadcrumb code. Signed-off-by: Dave Airlie --- drivers/char/drm/i915_dma.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 1ff4c7ca0b..9f4b8ce4c0 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c @@ -495,8 +495,6 @@ static int i915_dispatch_batchbuffer(drm_device_t * dev, } } - dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; - i915_emit_breadcrumb(dev); return 0; -- cgit v1.2.2 From 6e5fca53c72c95da92c092411c7ec81e926af632 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 20 Mar 2006 18:34:29 +1100 Subject: drm: read breadcrumb in IRQ handler From: Keith Whitwell Signed-off-by: Dave Airlie --- drivers/char/drm/i915_irq.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index d3879ac997..a752afd86a 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c @@ -53,6 +53,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_WRITE16(I915REG_INT_IDENTITY_R, temp); + dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + if (temp & USER_INT_FLAG) DRM_WAKEUP(&dev_priv->irq_queue); -- cgit v1.2.2 From aec5c3c1a929d7d79a420e943285cf3ba26a7c0d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 25 Mar 2006 01:33:34 +0900 Subject: [PATCH] libata: kill E.D.D. E.D.D. has no user in-tree and mostly useless. Kill it. For possible out-of-tree users, add a nice warning message and error handling if LLDD doesn't report any useable reset mechanism (and thus tries to use E.D.D.). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 98 ++++++---------------------------------------- 1 file changed, 13 insertions(+), 85 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index d279666dcb..0aff888d9e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1081,9 +1081,8 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * * Read ID data from the specified device. ATA_CMD_ID_ATA is * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI - * devices. This function also takes care of EDD signature - * misreporting (to be removed once EDD support is gone) and - * issues ATA_CMD_INIT_DEV_PARAMS for pre-ATA4 drives. + * devices. This function also issues ATA_CMD_INIT_DEV_PARAMS + * for pre-ATA4 drives. * * LOCKING: * Kernel thread context (may sleep) @@ -1095,7 +1094,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, unsigned int *p_class, int post_reset, u16 **p_id) { unsigned int class = *p_class; - unsigned int using_edd; struct ata_taskfile tf; unsigned int err_mask = 0; u16 *id; @@ -1104,12 +1102,6 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); - if (ap->ops->probe_reset || - ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET)) - using_edd = 0; - else - using_edd = 1; - ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL); @@ -1139,32 +1131,9 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE, id, sizeof(id[0]) * ATA_ID_WORDS); - if (err_mask) { rc = -EIO; reason = "I/O error"; - - if (err_mask & ~AC_ERR_DEV) - goto err_out; - - /* - * arg! EDD works for all test cases, but seems to return - * the ATA signature for some ATAPI devices. Until the - * reason for this is found and fixed, we fix up the mess - * here. If IDENTIFY DEVICE returns command aborted - * (as ATAPI devices do), then we issue an - * IDENTIFY PACKET DEVICE. - * - * ATA software reset (SRST, the default) does not appear - * to have this problem. - */ - if ((using_edd) && (class == ATA_DEV_ATA)) { - u8 err = tf.feature; - if (err & ATA_ABORTED) { - class = ATA_DEV_ATAPI; - goto retry; - } - } goto err_out; } @@ -2005,45 +1974,6 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask) ap->ops->dev_select(ap, 0); } -/** - * ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command. - * @ap: Port to reset and probe - * - * Use the EXECUTE DEVICE DIAGNOSTIC command to reset and - * probe the bus. Not often used these days. - * - * LOCKING: - * PCI/etc. bus probe sem. - * Obtains host_set lock. - * - */ - -static unsigned int ata_bus_edd(struct ata_port *ap) -{ - struct ata_taskfile tf; - unsigned long flags; - - /* set up execute-device-diag (bus reset) taskfile */ - /* also, take interrupts to a known state (disabled) */ - DPRINTK("execute-device-diag\n"); - ata_tf_init(ap, &tf, 0); - tf.ctl |= ATA_NIEN; - tf.command = ATA_CMD_EDD; - tf.protocol = ATA_PROT_NODATA; - - /* do bus reset */ - spin_lock_irqsave(&ap->host_set->lock, flags); - ata_tf_to_host(ap, &tf); - spin_unlock_irqrestore(&ap->host_set->lock, flags); - - /* spec says at least 2ms. but who knows with those - * crazy ATAPI devices... - */ - msleep(150); - - return ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); -} - static unsigned int ata_bus_softreset(struct ata_port *ap, unsigned int devmask) { @@ -2116,7 +2046,7 @@ void ata_bus_reset(struct ata_port *ap) struct ata_ioports *ioaddr = &ap->ioaddr; unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; u8 err; - unsigned int dev0, dev1 = 0, rc = 0, devmask = 0; + unsigned int dev0, dev1 = 0, devmask = 0; DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no); @@ -2139,18 +2069,8 @@ void ata_bus_reset(struct ata_port *ap) /* issue bus reset */ if (ap->flags & ATA_FLAG_SRST) - rc = ata_bus_softreset(ap, devmask); - else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) { - /* set up device control */ - if (ap->flags & ATA_FLAG_MMIO) - writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr); - else - outb(ap->ctl, ioaddr->ctl_addr); - rc = ata_bus_edd(ap); - } - - if (rc) - goto err_out; + if (ata_bus_softreset(ap, devmask)) + goto err_out; /* * determine by signature whether we have ATA or ATAPI devices @@ -4536,6 +4456,14 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, int rc; DPRINTK("ENTER\n"); + + if (!ent->port_ops->probe_reset && + !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) { + printk(KERN_ERR "ata%u: no reset mechanism available\n", + port_no); + return NULL; + } + host = scsi_host_alloc(ent->sht, sizeof(struct ata_port)); if (!host) return NULL; -- cgit v1.2.2 From 298a41ca41b4c933adc7b5a56a0adb0e1df2e556 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 25 Mar 2006 02:58:13 +0900 Subject: [PATCH] libata: cosmetic changes in ata_bus_softreset() ata_bus_softreset() should return AC_ERR_* on failure not arbitrary positive number. While at it, reformat comment above it. Signed-off-by: Tejun Heo Acked-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 0aff888d9e..64f71df19e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2008,13 +2008,12 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, */ msleep(150); - /* Before we perform post reset processing we want to see if - the bus shows 0xFF because the odd clown forgets the D7 pulldown - resistor */ - + * the bus shows 0xFF because the odd clown forgets the D7 + * pulldown resistor. + */ if (ata_check_status(ap) == 0xFF) - return 1; /* Positive is failure for some reason */ + return AC_ERR_OTHER; ata_bus_post_reset(ap, devmask); -- cgit v1.2.2 From 600511e86babe3727264a0883a3a264f6fb6caf5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 25 Mar 2006 11:14:07 +0900 Subject: [PATCH] libata: add FIXME above ata_dev_xfermask() Add FIXME above ata_dev_xfermask noting that the current implementation limits all transfer modes to the fastest of the slowest device on a port which isn't necessary. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 64f71df19e..1cb9813753 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2633,6 +2633,10 @@ static int ata_dma_blacklisted(const struct ata_device *dev) * known limits including host controller limits, device * blacklist, etc... * + * FIXME: The current implementation limits all transfer modes to + * the fastest of the lowested device on the port. This is not + * required on most controllers. + * * LOCKING: * None. */ -- cgit v1.2.2 From f3dd5c37382472a8b245ad791ed768771594e60c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 25 Mar 2006 18:09:46 +1100 Subject: drm: add new radeon PCI ids.. This adds all the r300 and r400 PCI ids from DRM CVS, it also makes these cards only initialise when the new xorg driver is used, as otherwise the DRM can cause lockups. Signed-off-by: Dave Airlie --- drivers/char/drm/drm_pciids.h | 99 +++++++++++++++++++++++++++++++------------ drivers/char/drm/radeon_cp.c | 8 ++++ drivers/char/drm/radeon_drv.h | 1 + 3 files changed, 81 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 24b80357b9..b1bb3c7b56 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -3,18 +3,27 @@ Please contact dri-devel@lists.sf.net to add new cards to this list */ #define radeon_PCI_IDS \ - {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY},\ + {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ + {0x1002, 0x4148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x4149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x414A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x414B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4153, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ + {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ @@ -24,8 +33,20 @@ {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ - {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ - {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ + {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ @@ -35,14 +56,16 @@ {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ - {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ + {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E47, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ {0x1002, 0x4E48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ - {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ + {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ + {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ @@ -50,44 +73,66 @@ {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x5149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x514F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ {0x1002, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \ {0x1002, 0x5158, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200}, \ {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ - {0x1002, 0x5168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x5169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x516A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ - {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ - {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ + {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ + {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ - {0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ - {0x1002, 0x5837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x5963, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x5968, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ + {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ - {0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ + {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ - {0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ - {0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ - {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ - {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ + {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_NEW_MEMMAP}, \ + {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ {0, 0, 0} #define r128_PCI_IDS \ diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index cc4942a112..7f949c9c96 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -1332,6 +1332,14 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) DRM_DEBUG("\n"); + /* if we require new memory map but we don't have it fail */ + if ((dev_priv->flags & CHIP_NEW_MEMMAP) && !dev_priv->new_memmap) + { + DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX\n"); + radeon_do_cleanup_cp(dev); + return DRM_ERR(EINVAL); + } + if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP)) { DRM_DEBUG("Forcing AGP card to PCI mode\n"); diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 31bacfa2ed..78345cee8f 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -139,6 +139,7 @@ enum radeon_chip_flags { CHIP_IS_AGP = 0x00080000UL, CHIP_HAS_HIERZ = 0x00100000UL, CHIP_IS_PCIE = 0x00200000UL, + CHIP_NEW_MEMMAP = 0x00400000UL, }; #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ -- cgit v1.2.2 From b8c7b976a570aede21327e7d64781801e1641606 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 25 Mar 2006 17:31:30 +1100 Subject: [PATCH] powerpc: Compile warning in hvcs driver We ended up with an unused variable after the tty updates went in. Fix it. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- drivers/char/hvcs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index f7ac318565..327b00c3c4 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -439,7 +439,6 @@ static int hvcs_io(struct hvcs_struct *hvcsd) char buf[HVCS_BUFF_LEN] __ALIGNED__; unsigned long flags; int got = 0; - int i; spin_lock_irqsave(&hvcsd->lock, flags); -- cgit v1.2.2 From 55aab8cd3a498201b769a19de861c77516bdfd45 Mon Sep 17 00:00:00 2001 From: Michael Neuling Date: Sat, 25 Mar 2006 17:30:00 +1100 Subject: [PATCH] powerpc: HVC init race I've been hitting a crash on boot where tty_open is being called before the hvc console driver setup is complete. This fixes the problem. Thanks to benh for his help on this. Signed-off-by: Michael Neuling Acked-by: Anton Blanchard Signed-off-by: Paul Mackerras --- drivers/char/hvc_console.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index f65b2e14a4..a94c5b0cac 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -823,34 +823,38 @@ EXPORT_SYMBOL(hvc_remove); * interfaces start to become available. */ int __init hvc_init(void) { + struct tty_driver *drv; + /* We need more than hvc_count adapters due to hotplug additions. */ - hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS); - if (!hvc_driver) + drv = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS); + if (!drv) return -ENOMEM; - hvc_driver->owner = THIS_MODULE; - hvc_driver->devfs_name = "hvc/"; - hvc_driver->driver_name = "hvc"; - hvc_driver->name = "hvc"; - hvc_driver->major = HVC_MAJOR; - hvc_driver->minor_start = HVC_MINOR; - hvc_driver->type = TTY_DRIVER_TYPE_SYSTEM; - hvc_driver->init_termios = tty_std_termios; - hvc_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(hvc_driver, &hvc_ops); + drv->owner = THIS_MODULE; + drv->devfs_name = "hvc/"; + drv->driver_name = "hvc"; + drv->name = "hvc"; + drv->major = HVC_MAJOR; + drv->minor_start = HVC_MINOR; + drv->type = TTY_DRIVER_TYPE_SYSTEM; + drv->init_termios = tty_std_termios; + drv->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(drv, &hvc_ops); /* Always start the kthread because there can be hotplug vty adapters * added later. */ hvc_task = kthread_run(khvcd, NULL, "khvcd"); if (IS_ERR(hvc_task)) { panic("Couldn't create kthread for console.\n"); - put_tty_driver(hvc_driver); + put_tty_driver(drv); return -EIO; } - if (tty_register_driver(hvc_driver)) + if (tty_register_driver(drv)) panic("Couldn't register hvc console driver\n"); + mb(); + hvc_driver = drv; return 0; } module_init(hvc_init); -- cgit v1.2.2 From f222313a61a5e134de80767b35c672b91e78383c Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 23 Jan 2006 16:59:58 -0500 Subject: [PATCH] wireless: import bcm43xx sources Import the bcm43xx driver from the upstream sources here: ftp://ftp.berlios.de/pub/bcm43xx/snapshots/bcm43xx/bcm43xx-20060123.tar.bz2 Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/COPYING | 340 ++ drivers/net/wireless/bcm43xx/Makefile | 87 + drivers/net/wireless/bcm43xx/README | 36 + drivers/net/wireless/bcm43xx/bcm43xx.h | 961 +++++ drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 503 +++ drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h | 117 + drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 1009 ++++++ drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 176 + drivers/net/wireless/bcm43xx/bcm43xx_ilt.c | 367 ++ drivers/net/wireless/bcm43xx/bcm43xx_ilt.h | 34 + drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 261 ++ drivers/net/wireless/bcm43xx/bcm43xx_leds.h | 47 + drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4597 ++++++++++++++++++++++++ drivers/net/wireless/bcm43xx/bcm43xx_main.h | 283 ++ drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 2122 +++++++++++ drivers/net/wireless/bcm43xx/bcm43xx_phy.h | 74 + drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 592 +++ drivers/net/wireless/bcm43xx/bcm43xx_pio.h | 88 + drivers/net/wireless/bcm43xx/bcm43xx_power.c | 358 ++ drivers/net/wireless/bcm43xx/bcm43xx_power.h | 47 + drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 1766 +++++++++ drivers/net/wireless/bcm43xx/bcm43xx_radio.h | 93 + drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 1099 ++++++ drivers/net/wireless/bcm43xx/bcm43xx_wx.h | 36 + 24 files changed, 15093 insertions(+) create mode 100644 drivers/net/wireless/bcm43xx/COPYING create mode 100644 drivers/net/wireless/bcm43xx/Makefile create mode 100644 drivers/net/wireless/bcm43xx/README create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_dma.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_dma.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ilt.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ilt.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_leds.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_leds.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_main.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_main.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_phy.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_phy.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_pio.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_pio.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_power.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_power.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_radio.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_radio.h create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_wx.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_wx.h (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/COPYING b/drivers/net/wireless/bcm43xx/COPYING new file mode 100644 index 0000000000..5b6e7c66c2 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile new file mode 100644 index 0000000000..98d4efb1d1 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -0,0 +1,87 @@ +# Makefile for bcm43xx driver + +VERSION := 0.0.1 +RELEASE_NAME := bcm43xx-$(VERSION) + +# Optional path, where the SoftMAC subsystem is located. +# You may set SOFTMAC_DIR in your bashrc, for example. +SOFTMAC_DIR ?= + +KVER := $(shell uname -r) +KDIR ?= /lib/modules/$(KVER)/build +PWD := $(shell pwd) +MODPATH := $(DESTDIR)/lib/modules/$(KVER)/kernel/drivers/net/bcm43xx + +# Comment/uncomment to enable/disable debugging +DEBUG = y + + +ifeq ($(DEBUG),y) +DEBUGFS_OBJ = bcm43xx_debugfs.o +CFLAGS += -O2 -DCONFIG_BCM43XX_DEBUG +else +DEBUGFS_OBJ = +CFLAGS += -O2 +endif + +CFLAGS += -DBCM43xx_VERSION=$(VERSION) -I/lib/modules/$(KVER)/include +ifneq ($(SOFTMAC_DIR),) +CPPFLAGS := -I$(SOFTMAC_DIR) $(CPPFLAGS) +endif + +ifneq ($(KERNELRELEASE),) +# call from kernel build system + +obj-m := bcm43xx.o +bcm43xx-objs := bcm43xx_main.o bcm43xx_dma.o $(DEBUGFS_OBJ) \ + bcm43xx_radio.o bcm43xx_phy.o \ + bcm43xx_power.o bcm43xx_wx.o \ + bcm43xx_pio.o bcm43xx_ilt.o \ + bcm43xx_leds.o + +else + +default: modules + +modules: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +install: bcm43xx.ko + install -d $(MODPATH) + install -m 644 -c bcm43xx.ko $(MODPATH) + /sbin/depmod -a + +uninstall: + rm -rf $(MODPATH) + /sbin/depmod -a + +endif + +clean: + find . \( -name '*.ko' -o -name '*.o' -o -name '.tmp_versions' -o -name '*~' -o -name '.*.cmd' \ + -o -name '*.mod.c' -o -name '*.tar.bz2' -o -name '*.rej' -o -name '*.orig' \)\ + -print | xargs rm -Rf + +depend .depend dep: + $(CC) $(CFLAGS) -M *.c > .depend + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif + +DISTFILES = $(shell find . \( -not -name '.' \) -print | grep -v "\.tar\.bz2" | grep -v "\/\." ) +DISTDIR = $(RELEASE_NAME) + +release: clean + @rm -rf $(DISTDIR) + @mkdir $(DISTDIR) + @chmod 777 $(DISTDIR) + @for file in $(DISTFILES); do \ + if test -d $$file; then \ + mkdir $(DISTDIR)/$$file; \ + else \ + cp -p $$file $(DISTDIR)/$$file; \ + fi; \ + done + @tar -c $(DISTDIR) | bzip2 -9 > $(RELEASE_NAME).tar.bz2 + @rm -rf $(DISTDIR) diff --git a/drivers/net/wireless/bcm43xx/README b/drivers/net/wireless/bcm43xx/README new file mode 100644 index 0000000000..64d9022de7 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/README @@ -0,0 +1,36 @@ + + BCM43xx Linux Driver Project + ============================ + +About this software +------------------- + +The goal of this project is to develop a linux driver for Broadcom +BCM43xx chips, based on the specification at +http://bcm-specs.sipsolutions.net/ + +The project page is http://bcm43xx.berlios.de/ + + +Requirements +------------ + +1) Linux Kernel 2.6.15 or later + http://www.kernel.org/ + + You may want to configure your kernel with: + + CONFIG_DEBUG_FS (optional): + -> Kernel hacking + -> Debug Filesystem + +2) SoftMAC IEEE 802.11 Networking Stack extension and patched ieee80211 + modules: + http://softmac.sipsolutions.net/ + +3) Firmware Files + + Please try fwcutter. Fwcutter can extract the firmware from various + binary driver files. It supports driver files from Windows, MacOS and + Linux. You can get fwcutter from http://bcm43xx.berlios.de/. + Also, fwcutter comes with a README file for further instructions. diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h new file mode 100644 index 0000000000..aca1601e5b --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -0,0 +1,961 @@ +#ifndef BCM43xx_H_ +#define BCM43xx_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "bcm43xx_debugfs.h" +#include "bcm43xx_leds.h" + + +#define DRV_NAME __stringify(KBUILD_MODNAME) +#define DRV_VERSION __stringify(BCM43xx_VERSION) +#define BCM43xx_DRIVER_NAME DRV_NAME " driver " DRV_VERSION +#define PFX DRV_NAME ": " + +#define BCM43xx_SWITCH_CORE_MAX_RETRIES 10 +#define BCM43xx_IRQWAIT_MAX_RETRIES 50 +#define BCM43xx_TX_TIMEOUT (10 * HZ) + +#define BCM43xx_IO_SIZE 8192 +#define BCM43xx_REG_ACTIVE_CORE 0x80 + +/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */ +#define BCM43xx_PCICFG_ICR 0x94 +/* SPROM control register. */ +#define BCM43xx_PCICFG_SPROMCTL 0x88 + +/* MMIO offsets */ +#define BCM43xx_MMIO_DMA1_REASON 0x20 +#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x24 +#define BCM43xx_MMIO_DMA2_REASON 0x28 +#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x2C +#define BCM43xx_MMIO_DMA3_REASON 0x30 +#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x34 +#define BCM43xx_MMIO_DMA4_REASON 0x38 +#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x3C +#define BCM43xx_MMIO_STATUS_BITFIELD 0x120 +#define BCM43xx_MMIO_STATUS2_BITFIELD 0x124 +#define BCM43xx_MMIO_GEN_IRQ_REASON 0x128 +#define BCM43xx_MMIO_GEN_IRQ_MASK 0x12C +#define BCM43xx_MMIO_RAM_CONTROL 0x130 +#define BCM43xx_MMIO_RAM_DATA 0x134 +#define BCM43xx_MMIO_PS_STATUS 0x140 +#define BCM43xx_MMIO_RADIO_HWENABLED_HI 0x158 +#define BCM43xx_MMIO_SHM_CONTROL 0x160 +#define BCM43xx_MMIO_SHM_DATA 0x164 +#define BCM43xx_MMIO_SHM_DATA_UNALIGNED 0x166 +#define BCM43xx_MMIO_XMITSTAT_0 0x170 +#define BCM43xx_MMIO_XMITSTAT_1 0x174 +#define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ +#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ +#define BCM43xx_MMIO_DMA1_BASE 0x200 +#define BCM43xx_MMIO_DMA2_BASE 0x220 +#define BCM43xx_MMIO_DMA3_BASE 0x240 +#define BCM43xx_MMIO_DMA4_BASE 0x260 +#define BCM43xx_MMIO_PIO1_BASE 0x300 +#define BCM43xx_MMIO_PIO2_BASE 0x310 +#define BCM43xx_MMIO_PIO3_BASE 0x320 +#define BCM43xx_MMIO_PIO4_BASE 0x330 +#define BCM43xx_MMIO_PHY_VER 0x3E0 +#define BCM43xx_MMIO_PHY_RADIO 0x3E2 +#define BCM43xx_MMIO_ANTENNA 0x3E8 +#define BCM43xx_MMIO_CHANNEL 0x3F0 +#define BCM43xx_MMIO_CHANNEL_EXT 0x3F4 +#define BCM43xx_MMIO_RADIO_CONTROL 0x3F6 +#define BCM43xx_MMIO_RADIO_DATA_HIGH 0x3F8 +#define BCM43xx_MMIO_RADIO_DATA_LOW 0x3FA +#define BCM43xx_MMIO_PHY_CONTROL 0x3FC +#define BCM43xx_MMIO_PHY_DATA 0x3FE +#define BCM43xx_MMIO_MACFILTER_CONTROL 0x420 +#define BCM43xx_MMIO_MACFILTER_DATA 0x422 +#define BCM43xx_MMIO_RADIO_HWENABLED_LO 0x49A +#define BCM43xx_MMIO_GPIO_CONTROL 0x49C +#define BCM43xx_MMIO_GPIO_MASK 0x49E +#define BCM43xx_MMIO_TSF_0 0x632 /* core rev < 3 only */ +#define BCM43xx_MMIO_TSF_1 0x634 /* core rev < 3 only */ +#define BCM43xx_MMIO_TSF_2 0x636 /* core rev < 3 only */ +#define BCM43xx_MMIO_TSF_3 0x638 /* core rev < 3 only */ +#define BCM43xx_MMIO_POWERUP_DELAY 0x6A8 + +/* SPROM offsets. */ +#define BCM43xx_SPROM_BASE 0x1000 +#define BCM43xx_SPROM_BOARDFLAGS2 0x1c +#define BCM43xx_SPROM_IL0MACADDR 0x24 +#define BCM43xx_SPROM_ET0MACADDR 0x27 +#define BCM43xx_SPROM_ET1MACADDR 0x2a +#define BCM43xx_SPROM_ETHPHY 0x2d +#define BCM43xx_SPROM_BOARDREV 0x2e +#define BCM43xx_SPROM_PA0B0 0x2f +#define BCM43xx_SPROM_PA0B1 0x30 +#define BCM43xx_SPROM_PA0B2 0x31 +#define BCM43xx_SPROM_WL0GPIO0 0x32 +#define BCM43xx_SPROM_WL0GPIO2 0x33 +#define BCM43xx_SPROM_MAXPWR 0x34 +#define BCM43xx_SPROM_PA1B0 0x35 +#define BCM43xx_SPROM_PA1B1 0x36 +#define BCM43xx_SPROM_PA1B2 0x37 +#define BCM43xx_SPROM_IDL_TSSI_TGT 0x38 +#define BCM43xx_SPROM_BOARDFLAGS 0x39 +#define BCM43xx_SPROM_ANTENNA_GAIN 0x3a +#define BCM43xx_SPROM_VERSION 0x3f + +/* BCM43xx_SPROM_BOARDFLAGS values */ +#define BCM43xx_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */ +#define BCM43xx_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */ +#define BCM43xx_BFL_AIRLINEMODE 0x0004 /* implements GPIO 13 radio disable indication */ +#define BCM43xx_BFL_RSSI 0x0008 /* software calculates nrssi slope. */ +#define BCM43xx_BFL_ENETSPI 0x0010 /* has ephy roboswitch spi */ +#define BCM43xx_BFL_XTAL_NOSLOW 0x0020 /* no slow clock available */ +#define BCM43xx_BFL_CCKHIPWR 0x0040 /* can do high power CCK transmission */ +#define BCM43xx_BFL_ENETADM 0x0080 /* has ADMtek switch */ +#define BCM43xx_BFL_ENETVLAN 0x0100 /* can do vlan */ +#define BCM43xx_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */ +#define BCM43xx_BFL_NOPCI 0x0400 /* leaves PCI floating */ +#define BCM43xx_BFL_FEM 0x0800 /* supports the Front End Module */ + +/* GPIO register offset, in both ChipCommon and PCI core. */ +#define BCM43xx_GPIO_CONTROL 0x6c + +/* SHM Routing */ +#define BCM43xx_SHM_SHARED 0x0001 +#define BCM43xx_SHM_WIRELESS 0x0002 +#define BCM43xx_SHM_PCM 0x0003 +#define BCM43xx_SHM_HWMAC 0x0004 +#define BCM43xx_SHM_UCODE 0x0300 + +/* MacFilter offsets. */ +#define BCM43xx_MACFILTER_SELF 0x0000 +#define BCM43xx_MACFILTER_ASSOC 0x0003 + +/* Chipcommon registers. */ +#define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04 +#define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0 +#define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4 +#define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8 +#define BCM43xx_CHIPCOMMON_SYSCLKCTL 0xC0 + +/* PCI core specific registers. */ +#define BCM43xx_PCICORE_BCAST_ADDR 0x50 +#define BCM43xx_PCICORE_BCAST_DATA 0x54 +#define BCM43xx_PCICORE_SBTOPCI2 0x108 + +/* SBTOPCI2 values. */ +#define BCM43xx_SBTOPCI2_PREFETCH 0x4 +#define BCM43xx_SBTOPCI2_BURST 0x8 + +/* Chipcommon capabilities. */ +#define BCM43xx_CAPABILITIES_PCTL 0x00040000 +#define BCM43xx_CAPABILITIES_PLLMASK 0x00030000 +#define BCM43xx_CAPABILITIES_PLLSHIFT 16 +#define BCM43xx_CAPABILITIES_FLASHMASK 0x00000700 +#define BCM43xx_CAPABILITIES_FLASHSHIFT 8 +#define BCM43xx_CAPABILITIES_EXTBUSPRESENT 0x00000040 +#define BCM43xx_CAPABILITIES_UARTGPIO 0x00000020 +#define BCM43xx_CAPABILITIES_UARTCLOCKMASK 0x00000018 +#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT 3 +#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN 0x00000004 +#define BCM43xx_CAPABILITIES_NRUARTSMASK 0x00000003 + +/* PowerControl */ +#define BCM43xx_PCTL_IN 0xB0 +#define BCM43xx_PCTL_OUT 0xB4 +#define BCM43xx_PCTL_OUTENABLE 0xB8 +#define BCM43xx_PCTL_XTAL_POWERUP 0x40 +#define BCM43xx_PCTL_PLL_POWERDOWN 0x80 + +/* PowerControl Clock Modes */ +#define BCM43xx_PCTL_CLK_FAST 0x00 +#define BCM43xx_PCTL_CLK_SLOW 0x01 +#define BCM43xx_PCTL_CLK_DYNAMIC 0x02 + +#define BCM43xx_PCTL_FORCE_SLOW 0x0800 +#define BCM43xx_PCTL_FORCE_PLL 0x1000 +#define BCM43xx_PCTL_DYN_XTAL 0x2000 + +/* COREIDs */ +#define BCM43xx_COREID_CHIPCOMMON 0x800 +#define BCM43xx_COREID_ILINE20 0x801 +#define BCM43xx_COREID_SDRAM 0x803 +#define BCM43xx_COREID_PCI 0x804 +#define BCM43xx_COREID_MIPS 0x805 +#define BCM43xx_COREID_ETHERNET 0x806 +#define BCM43xx_COREID_V90 0x807 +#define BCM43xx_COREID_USB11_HOSTDEV 0x80a +#define BCM43xx_COREID_IPSEC 0x80b +#define BCM43xx_COREID_PCMCIA 0x80d +#define BCM43xx_COREID_EXT_IF 0x80f +#define BCM43xx_COREID_80211 0x812 +#define BCM43xx_COREID_MIPS_3302 0x816 +#define BCM43xx_COREID_USB11_HOST 0x817 +#define BCM43xx_COREID_USB11_DEV 0x818 +#define BCM43xx_COREID_USB20_HOST 0x819 +#define BCM43xx_COREID_USB20_DEV 0x81a +#define BCM43xx_COREID_SDIO_HOST 0x81b + +/* Core Information Registers */ +#define BCM43xx_CIR_BASE 0xf00 +#define BCM43xx_CIR_SBTPSFLAG (BCM43xx_CIR_BASE + 0x18) +#define BCM43xx_CIR_SBIMSTATE (BCM43xx_CIR_BASE + 0x90) +#define BCM43xx_CIR_SBINTVEC (BCM43xx_CIR_BASE + 0x94) +#define BCM43xx_CIR_SBTMSTATELOW (BCM43xx_CIR_BASE + 0x98) +#define BCM43xx_CIR_SBTMSTATEHIGH (BCM43xx_CIR_BASE + 0x9c) +#define BCM43xx_CIR_SBIMCONFIGLOW (BCM43xx_CIR_BASE + 0xa8) +#define BCM43xx_CIR_SB_ID_HI (BCM43xx_CIR_BASE + 0xfc) + +/* Mask to get the Backplane Flag Number from SBTPSFLAG. */ +#define BCM43xx_BACKPLANE_FLAG_NR_MASK 0x3f + +/* SBIMCONFIGLOW values/masks. */ +#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK 0x00000007 +#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT 0 +#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK 0x00000070 +#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT 4 +#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK 0x00ff0000 +#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT 16 + +/* sbtmstatelow state flags */ +#define BCM43xx_SBTMSTATELOW_RESET 0x01 +#define BCM43xx_SBTMSTATELOW_REJECT 0x02 +#define BCM43xx_SBTMSTATELOW_CLOCK 0x10000 +#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000 + +/* sbtmstatehigh state flags */ +#define BCM43xx_SBTMSTATEHIGH_SERROR 0x1 +#define BCM43xx_SBTMSTATEHIGH_BUSY 0x4 + +/* sbimstate flags */ +#define BCM43xx_SBIMSTATE_IB_ERROR 0x20000 +#define BCM43xx_SBIMSTATE_TIMEOUT 0x40000 + +/* PHYVersioning */ +#define BCM43xx_PHYTYPE_A 0x00 +#define BCM43xx_PHYTYPE_B 0x01 +#define BCM43xx_PHYTYPE_G 0x02 + +/* PHYRegisters */ +#define BCM43xx_PHY_ILT_A_CTRL 0x0072 +#define BCM43xx_PHY_ILT_A_DATA1 0x0073 +#define BCM43xx_PHY_ILT_A_DATA2 0x0074 +#define BCM43xx_PHY_G_LO_CONTROL 0x0810 +#define BCM43xx_PHY_ILT_G_CTRL 0x0472 +#define BCM43xx_PHY_ILT_G_DATA1 0x0473 +#define BCM43xx_PHY_ILT_G_DATA2 0x0474 +#define BCM43xx_PHY_A_PCTL 0x007B +#define BCM43xx_PHY_G_PCTL 0x0029 +#define BCM43xx_PHY_A_CRS 0x0029 +#define BCM43xx_PHY_RADIO_BITFIELD 0x0401 +#define BCM43xx_PHY_G_CRS 0x0429 +#define BCM43xx_PHY_NRSSILT_CTRL 0x0803 +#define BCM43xx_PHY_NRSSILT_DATA 0x0804 + +/* RadioRegisters */ +#define BCM43xx_RADIOCTL_ID 0x01 + +/* StatusBitField */ +#define BCM43xx_SBF_MAC_ENABLED 0x00000001 +#define BCM43xx_SBF_2 0x00000002 /*FIXME: fix name*/ +#define BCM43xx_SBF_CORE_READY 0x00000004 +#define BCM43xx_SBF_400 0x00000400 /*FIXME: fix name*/ +#define BCM43xx_SBF_4000 0x00004000 /*FIXME: fix name*/ +#define BCM43xx_SBF_8000 0x00008000 /*FIXME: fix name*/ +#define BCM43xx_SBF_XFER_REG_BYTESWAP 0x00010000 +#define BCM43xx_SBF_MODE_NOTADHOC 0x00020000 +#define BCM43xx_SBF_MODE_AP 0x00040000 +#define BCM43xx_SBF_RADIOREG_LOCK 0x00080000 +#define BCM43xx_SBF_MODE_MONITOR 0x00400000 +#define BCM43xx_SBF_MODE_PROMISC 0x01000000 +#define BCM43xx_SBF_PS1 0x02000000 +#define BCM43xx_SBF_PS2 0x04000000 +#define BCM43xx_SBF_NO_SSID_BCAST 0x08000000 +#define BCM43xx_SBF_TIME_UPDATE 0x10000000 +#define BCM43xx_SBF_80000000 0x80000000 /*FIXME: fix name*/ + +/* MicrocodeFlagsBitfield (addr + lo-word values?)*/ +#define BCM43xx_UCODEFLAGS_OFFSET 0x005E + +#define BCM43xx_UCODEFLAG_AUTODIV 0x0001 +#define BCM43xx_UCODEFLAG_UNKBGPHY 0x0002 +#define BCM43xx_UCODEFLAG_UNKBPHY 0x0004 +#define BCM43xx_UCODEFLAG_UNKGPHY 0x0020 +#define BCM43xx_UCODEFLAG_UNKPACTRL 0x0040 +#define BCM43xx_UCODEFLAG_JAPAN 0x0080 + +/* Generic-Interrupt reasons. */ +#define BCM43xx_IRQ_READY (1 << 0) +#define BCM43xx_IRQ_BEACON (1 << 1) +#define BCM43xx_IRQ_PS (1 << 2) +#define BCM43xx_IRQ_REG124 (1 << 5) +#define BCM43xx_IRQ_PMQ (1 << 6) +#define BCM43xx_IRQ_PIO_WORKAROUND (1 << 8) +#define BCM43xx_IRQ_XMIT_ERROR (1 << 11) +#define BCM43xx_IRQ_RX (1 << 15) +#define BCM43xx_IRQ_SCAN (1 << 16) +#define BCM43xx_IRQ_NOISE (1 << 18) +#define BCM43xx_IRQ_XMIT_STATUS (1 << 29) + +#define BCM43xx_IRQ_ALL 0xffffffff +#define BCM43xx_IRQ_INITIAL (BCM43xx_IRQ_PS | \ + BCM43xx_IRQ_REG124 | \ + BCM43xx_IRQ_PMQ | \ + BCM43xx_IRQ_XMIT_ERROR | \ + BCM43xx_IRQ_RX | \ + BCM43xx_IRQ_SCAN | \ + BCM43xx_IRQ_NOISE | \ + BCM43xx_IRQ_XMIT_STATUS) + + +/* Initial default iw_mode */ +#define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA + +/* Values/Masks for the device TX header */ +#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001 +#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008 +#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020 +#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100 +#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800 + +#define BCM43xx_TXHDRCTL_OFDM 0x0001 +#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010 +#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030 +#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8 + +#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0 +#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4 +#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003 +#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0 + +/* Bus type PCI. */ +#define BCM43xx_BUSTYPE_PCI 0 +/* Bus type Silicone Backplane Bus. */ +#define BCM43xx_BUSTYPE_SB 1 +/* Bus type PCMCIA. */ +#define BCM43xx_BUSTYPE_PCMCIA 2 + +/* Threshold values. */ +#define BCM43xx_MIN_RTS_THRESHOLD 1U +#define BCM43xx_MAX_RTS_THRESHOLD 2304U +#define BCM43xx_DEFAULT_RTS_THRESHOLD BCM43xx_MAX_RTS_THRESHOLD + +#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT 7 +#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT 4 + +/* Max size of a security key */ +#define BCM43xx_SEC_KEYSIZE 16 +/* Security algorithms. */ +enum { + BCM43xx_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */ + BCM43xx_SEC_ALGO_WEP, + BCM43xx_SEC_ALGO_UNKNOWN, + BCM43xx_SEC_ALGO_AES, + BCM43xx_SEC_ALGO_WEP104, + BCM43xx_SEC_ALGO_TKIP, +}; + +#ifdef assert +# undef assert +#endif +#ifdef CONFIG_BCM43XX_DEBUG +#define assert(expr) \ + do { \ + if (unlikely(!(expr))) { \ + printk(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", \ + #expr, __FILE__, __LINE__, __FUNCTION__); \ + } \ + } while (0) +#else +#define assert(expr) do { /* nothing */ } while (0) +#endif + +/* rate limited printk(). */ +#ifdef printkl +# undef printkl +#endif +#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0) +/* rate limited printk() for debugging */ +#ifdef dprintkl +# undef dprintkl +#endif +#ifdef CONFIG_BCM43XX_DEBUG +# define dprintkl printkl +#else +# define dprintkl(f, x...) do { /* nothing */ } while (0) +#endif + +/* Helper macro for if branches. + * An if branch marked with this macro is only taken in DEBUG mode. + * Example: + * if (DEBUG_ONLY(foo == bar)) { + * do something + * } + * In DEBUG mode, the branch will be taken if (foo == bar). + * In non-DEBUG mode, the branch will never be taken. + */ +#ifdef DEBUG_ONLY +# undef DEBUG_ONLY +#endif +#ifdef CONFIG_BCM43XX_DEBUG +# define DEBUG_ONLY(x) (x) +#else +# define DEBUG_ONLY(x) 0 +#endif + +/* debugging printk() */ +#ifdef dprintk +# undef dprintk +#endif +#ifdef CONFIG_BCM43XX_DEBUG +# define dprintk(f, x...) do { printk(f ,##x); } while (0) +#else +# define dprintk(f, x...) do { /* nothing */ } while (0) +#endif + + +struct net_device; +struct pci_dev; +struct workqueue_struct; +struct bcm43xx_dmaring; +struct bcm43xx_pioqueue; + +struct bcm43xx_initval { + u16 offset; + u16 size; + u32 value; +} __attribute__((__packed__)); + +/* Values for bcm430x_sprominfo.locale */ +enum { + BCM43xx_LOCALE_WORLD = 0, + BCM43xx_LOCALE_THAILAND, + BCM43xx_LOCALE_ISRAEL, + BCM43xx_LOCALE_JORDAN, + BCM43xx_LOCALE_CHINA, + BCM43xx_LOCALE_JAPAN, + BCM43xx_LOCALE_USA_CANADA_ANZ, + BCM43xx_LOCALE_EUROPE, + BCM43xx_LOCALE_USA_LOW, + BCM43xx_LOCALE_JAPAN_HIGH, + BCM43xx_LOCALE_ALL, + BCM43xx_LOCALE_NONE, +}; + +#define BCM43xx_SPROM_SIZE 64 /* in 16-bit words. */ +struct bcm43xx_sprominfo { + u16 boardflags2; + u8 il0macaddr[6]; + u8 et0macaddr[6]; + u8 et1macaddr[6]; + u8 et0phyaddr:5; + u8 et1phyaddr:5; + u8 et0mdcport:1; + u8 et1mdcport:1; + u8 boardrev; + u8 locale:4; + u8 antennas_aphy:2; + u8 antennas_bgphy:2; + u16 pa0b0; + u16 pa0b1; + u16 pa0b2; + u8 wl0gpio0; + u8 wl0gpio1; + u8 wl0gpio2; + u8 wl0gpio3; + u8 maxpower_aphy; + u8 maxpower_bgphy; + u16 pa1b0; + u16 pa1b1; + u16 pa1b2; + u8 idle_tssi_tgt_aphy; + u8 idle_tssi_tgt_bgphy; + u16 boardflags; + u16 antennagain_aphy; + u16 antennagain_bgphy; +}; + +/* Value pair to measure the LocalOscillator. */ +struct bcm43xx_lopair { + s8 low; + s8 high; + u8 used:1; +}; +#define BCM43xx_LO_COUNT (14*4) + +struct bcm43xx_phyinfo { + /* Hardware Data */ + u8 version; + u8 type; + u8 rev; + u16 antenna_diversity; + u16 savedpctlreg; + u16 minlowsig[2]; + u16 minlowsigpos[2]; + u8 connected:1, + calibrated:1, + is_locked:1, /* used in bcm43xx_phy_{un}lock() */ + dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */ + /* LO Measurement Data. + * Use bcm43xx_get_lopair() to get a value. + */ + struct bcm43xx_lopair *_lo_pairs; + + /* TSSI to dBm table in use */ + const s8 *tssi2dbm; + /* idle TSSI value */ + s8 idle_tssi; + /* PHY lock for core.rev < 3 + * This lock is only used by bcm43xx_phy_{un}lock() + */ + spinlock_t lock; +}; + + +struct bcm43xx_radioinfo { + u16 manufact; + u16 version; + u8 revision; + + /* 0: baseband attenuation, + * 1: radio attenuation, + * 2: tx_CTL1 + * 3: tx_CTL2 + */ + u16 txpower[4]; + /* Current Interference Mitigation mode */ + int interfmode; + /* Stack of saved values from the Interference Mitigation code */ + u16 interfstack[20]; + /* Saved values from the NRSSI Slope calculation */ + s16 nrssi[2]; + s32 nrssislope; + /* In memory nrssi lookup table. */ + s8 nrssi_lt[64]; + + /* current channel */ + u8 channel; + u8 initial_channel; + + u16 lofcal; + + u16 initval; + + u8 enabled:1; + /* ACI (adjacent channel interference) flags. */ + u8 aci_enable:1, + aci_wlan_automatic:1, + aci_hw_rssi:1; +}; + +/* Data structures for DMA transmission, per 80211 core. */ +struct bcm43xx_dma { + struct bcm43xx_dmaring *tx_ring0; + struct bcm43xx_dmaring *tx_ring1; + struct bcm43xx_dmaring *tx_ring2; + struct bcm43xx_dmaring *tx_ring3; + struct bcm43xx_dmaring *rx_ring0; + struct bcm43xx_dmaring *rx_ring1; /* only available on core.rev < 5 */ +}; + +/* Data structures for PIO transmission, per 80211 core. */ +struct bcm43xx_pio { + struct bcm43xx_pioqueue *queue0; + struct bcm43xx_pioqueue *queue1; + struct bcm43xx_pioqueue *queue2; + struct bcm43xx_pioqueue *queue3; +}; + +#define BCM43xx_MAX_80211_CORES 2 + +#define BCM43xx_COREFLAG_AVAILABLE (1 << 0) +#define BCM43xx_COREFLAG_ENABLED (1 << 1) +#define BCM43xx_COREFLAG_INITIALIZED (1 << 2) + +#ifdef CONFIG_BCM947XX +#define core_offset(bcm) (bcm)->current_core_offset +#else +#define core_offset(bcm) 0 +#endif + +struct bcm43xx_coreinfo { + /** Driver internal flags. See BCM43xx_COREFLAG_* */ + u32 flags; + /** core_id ID number */ + u16 id; + /** core_rev revision number */ + u8 rev; + /** Index number for _switch_core() */ + u8 index; + /* Pointer to the PHYinfo, which belongs to this core (if 80211 core) */ + struct bcm43xx_phyinfo *phy; + /* Pointer to the RadioInfo, which belongs to this core (if 80211 core) */ + struct bcm43xx_radioinfo *radio; + /* Pointer to the DMA rings, which belong to this core (if 80211 core) */ + struct bcm43xx_dma *dma; + /* Pointer to the PIO queues, which belong to this core (if 80211 core) */ + struct bcm43xx_pio *pio; +}; + +/* Context information for a noise calculation (Link Quality). */ +struct bcm43xx_noise_calculation { + struct bcm43xx_coreinfo *core_at_start; + u8 channel_at_start; + u8 calculation_running:1; + u8 nr_samples; + s8 samples[8][4]; +}; + +struct bcm43xx_stats { + u8 link_quality; + /* Store the last TX/RX times here for updating the leds. */ + unsigned long last_tx; + unsigned long last_rx; +}; + +struct bcm43xx_key { + u8 enabled:1; + u8 algorithm; +}; + +struct bcm43xx_private { + struct ieee80211_device *ieee; + struct ieee80211softmac_device *softmac; + + struct net_device *net_dev; + struct pci_dev *pci_dev; + unsigned int irq; + + void __iomem *mmio_addr; + unsigned int mmio_len; + + spinlock_t lock; + + /* Driver status flags. */ + u32 initialized:1, /* init_board() succeed */ + was_initialized:1, /* for PCI suspend/resume. */ + shutting_down:1, /* free_board() in progress */ + pio_mode:1, /* PIO (if true), or DMA (if false) used. */ + bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */ + reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */ + powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */ + short_preamble:1, /* TRUE, if short preamble is enabled. */ + firmware_norelease:1; /* Do not release the firmware. Used on suspend. */ + + struct bcm43xx_stats stats; + + /* Bus type we are connected to. + * This is currently always BCM43xx_BUSTYPE_PCI + */ + u8 bustype; + + u16 board_vendor; + u16 board_type; + u16 board_revision; + + u16 chip_id; + u8 chip_rev; + + struct bcm43xx_sprominfo sprom; +#define BCM43xx_NR_LEDS 4 + struct bcm43xx_led leds[BCM43xx_NR_LEDS]; + + /* The currently active core. NULL if not initialized, yet. */ + struct bcm43xx_coreinfo *current_core; +#ifdef CONFIG_BCM947XX + /** current core memory offset */ + u32 current_core_offset; +#endif + struct bcm43xx_coreinfo *active_80211_core; + /* coreinfo structs for all possible cores follow. + * Note that a core might not exist. + * So check the coreinfo flags before using it. + */ + struct bcm43xx_coreinfo core_chipcommon; + struct bcm43xx_coreinfo core_pci; + struct bcm43xx_coreinfo core_v90; + struct bcm43xx_coreinfo core_pcmcia; + struct bcm43xx_coreinfo core_ethernet; + struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ]; + /* Info about the PHY for each 80211 core. */ + struct bcm43xx_phyinfo phy[ BCM43xx_MAX_80211_CORES ]; + /* Info about the Radio for each 80211 core. */ + struct bcm43xx_radioinfo radio[ BCM43xx_MAX_80211_CORES ]; + /* DMA */ + struct bcm43xx_dma dma[ BCM43xx_MAX_80211_CORES ]; + /* PIO */ + struct bcm43xx_pio pio[ BCM43xx_MAX_80211_CORES ]; + + u32 chipcommon_capabilities; + + /* Reason code of the last interrupt. */ + u32 irq_reason; + u32 dma_reason[4]; + /* saved irq enable/disable state bitfield. */ + u32 irq_savedstate; + /* Link Quality calculation context. */ + struct bcm43xx_noise_calculation noisecalc; + + /* Threshold values. */ + //TODO: The RTS thr has to be _used_. Currently, it is only set via WX. + u32 rts_threshold; + + /* Interrupt Service Routine tasklet (bottom-half) */ + struct tasklet_struct isr_tasklet; + /* Custom driver work queue. */ + struct workqueue_struct *workqueue; + + /* Periodic tasks */ + struct work_struct periodic_work0; +#define BCM43xx_PERIODIC_0_DELAY (HZ * 15) + struct work_struct periodic_work1; +#define BCM43xx_PERIODIC_1_DELAY ((HZ * 60) + HZ / 2) + struct work_struct periodic_work2; +#define BCM43xx_PERIODIC_2_DELAY ((HZ * 120) + HZ) + struct work_struct periodic_work3; +#define BCM43xx_PERIODIC_3_DELAY ((HZ * 30) + HZ / 5) + + struct work_struct restart_work; + + /* Informational stuff. */ + char nick[IW_ESSID_MAX_SIZE + 1]; + + /* encryption/decryption */ + u16 security_offset; + struct bcm43xx_key key[54]; + u8 default_key_idx; + + /* Firmware. */ + const struct firmware *ucode; + const struct firmware *pcm; + const struct firmware *initvals0; + const struct firmware *initvals1; + + /* Debugging stuff follows. */ +#ifdef CONFIG_BCM43XX_DEBUG + struct bcm43xx_dfsentry *dfsentry; + atomic_t mmio_print_cnt; + atomic_t pcicfg_print_cnt; +#endif +}; + +static inline +struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) +{ + return ieee80211softmac_priv(dev); +} + +static inline +int bcm43xx_num_80211_cores(struct bcm43xx_private *bcm) +{ + int i, cnt = 0; + + for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { + if (bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE) + cnt++; + } + + return cnt; +} + +/* Are we running in init_board() context? */ +static inline +int bcm43xx_is_initializing(struct bcm43xx_private *bcm) +{ + if (bcm->initialized) + return 0; + if (bcm->shutting_down) + return 0; + return 1; +} + +static inline +struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy, + u16 radio_attenuation, + u16 baseband_attenuation) +{ + return phy->_lo_pairs + (radio_attenuation + 14 * (baseband_attenuation / 2)); +} + + +/* MMIO read/write functions. Debug and non-debug variants. */ +#ifdef CONFIG_BCM43XX_DEBUG + +static inline +u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset) +{ + u16 value; + + value = ioread16(bcm->mmio_addr + core_offset(bcm) + offset); + if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { + printk(KERN_INFO PFX "ioread16 offset: 0x%04x, value: 0x%04x\n", + offset, value); + } + + return value; +} + +static inline +void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value) +{ + iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset); + if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { + printk(KERN_INFO PFX "iowrite16 offset: 0x%04x, value: 0x%04x\n", + offset, value); + } +} + +static inline +u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset) +{ + u32 value; + + value = ioread32(bcm->mmio_addr + core_offset(bcm) + offset); + if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { + printk(KERN_INFO PFX "ioread32 offset: 0x%04x, value: 0x%08x\n", + offset, value); + } + + return value; +} + +static inline +void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value) +{ + iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset); + if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { + printk(KERN_INFO PFX "iowrite32 offset: 0x%04x, value: 0x%08x\n", + offset, value); + } +} + +static inline +int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value) +{ + int err; + + err = pci_read_config_word(bcm->pci_dev, offset, value); + if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { + printk(KERN_INFO PFX "pciread16 offset: 0x%08x, value: 0x%04x, err: %d\n", + offset, *value, err); + } + + return err; +} + +static inline +int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value) +{ + int err; + + err = pci_read_config_dword(bcm->pci_dev, offset, value); + if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { + printk(KERN_INFO PFX "pciread32 offset: 0x%08x, value: 0x%08x, err: %d\n", + offset, *value, err); + } + + return err; +} + +static inline +int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value) +{ + int err; + + err = pci_write_config_word(bcm->pci_dev, offset, value); + if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { + printk(KERN_INFO PFX "pciwrite16 offset: 0x%08x, value: 0x%04x, err: %d\n", + offset, value, err); + } + + return err; +} + +static inline +int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value) +{ + int err; + + err = pci_write_config_dword(bcm->pci_dev, offset, value); + if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { + printk(KERN_INFO PFX "pciwrite32 offset: 0x%08x, value: 0x%08x, err: %d\n", + offset, value, err); + } + + return err; +} + +#define bcm43xx_mmioprint_initial(bcm, value) atomic_set(&(bcm)->mmio_print_cnt, (value)) +#define bcm43xx_mmioprint_enable(bcm) atomic_inc(&(bcm)->mmio_print_cnt) +#define bcm43xx_mmioprint_disable(bcm) atomic_dec(&(bcm)->mmio_print_cnt) +#define bcm43xx_pciprint_initial(bcm, value) atomic_set(&(bcm)->pcicfg_print_cnt, (value)) +#define bcm43xx_pciprint_enable(bcm) atomic_inc(&(bcm)->pcicfg_print_cnt) +#define bcm43xx_pciprint_disable(bcm) atomic_dec(&(bcm)->pcicfg_print_cnt) + +#else /* CONFIG_BCM43XX_DEBUG*/ + +#define bcm43xx_read16(bcm, offset) ioread16((bcm)->mmio_addr + core_offset(bcm) + (offset)) +#define bcm43xx_write16(bcm, offset, value) iowrite16((value), (bcm)->mmio_addr + core_offset(bcm) + (offset)) +#define bcm43xx_read32(bcm, offset) ioread32((bcm)->mmio_addr + core_offset(bcm) + (offset)) +#define bcm43xx_write32(bcm, offset, value) iowrite32((value), (bcm)->mmio_addr + core_offset(bcm) + (offset)) +#define bcm43xx_pci_read_config16(bcm, o, v) pci_read_config_word((bcm)->pci_dev, (o), (v)) +#define bcm43xx_pci_read_config32(bcm, o, v) pci_read_config_dword((bcm)->pci_dev, (o), (v)) +#define bcm43xx_pci_write_config16(bcm, o, v) pci_write_config_word((bcm)->pci_dev, (o), (v)) +#define bcm43xx_pci_write_config32(bcm, o, v) pci_write_config_dword((bcm)->pci_dev, (o), (v)) + +#define bcm43xx_mmioprint_initial(x, y) do { /* nothing */ } while (0) +#define bcm43xx_mmioprint_enable(x) do { /* nothing */ } while (0) +#define bcm43xx_mmioprint_disable(x) do { /* nothing */ } while (0) +#define bcm43xx_pciprint_initial(bcm, value) do { /* nothing */ } while (0) +#define bcm43xx_pciprint_enable(bcm) do { /* nothing */ } while (0) +#define bcm43xx_pciprint_disable(bcm) do { /* nothing */ } while (0) + +#endif /* CONFIG_BCM43XX_DEBUG*/ + + +/** Limit a value between two limits */ +#ifdef limit_value +# undef limit_value +#endif +#define limit_value(value, min, max) \ + ({ \ + typeof(value) __value = (value); \ + typeof(value) __min = (min); \ + typeof(value) __max = (max); \ + if (__value < __min) \ + __value = __min; \ + else if (__value > __max) \ + __value = __max; \ + __value; \ + }) + + +/* + * Compatibility stuff follows + */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) +# error "The bcm43xx driver does not support kernels < 2.6.15" +# error "The driver will _NOT_ compile on your kernel. Please upgrade to the latest 2.6 kernel." +# error "DO NOT COMPLAIN ABOUT BUGS. UPDATE FIRST AND TRY AGAIN." +#else +# if !defined(CONFIG_IEEE80211_MODULE) && !defined(CONFIG_IEEE80211) +# error "Generic IEEE 802.11 Networking Stack (CONFIG_IEEE80211) not available." +# endif +#endif +#ifdef IEEE80211SOFTMAC_API +# if IEEE80211SOFTMAC_API != 0 +# warning "Incompatible SoftMAC subsystem installed." +# endif +#else +# error "The bcm43xx driver requires the SoftMAC subsystem." +# error "SEE >>>>>> http://softmac.sipsolutions.net/ <<<<<<" +#endif + +#endif /* BCM43xx_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c new file mode 100644 index 0000000000..f8cfc84ca0 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -0,0 +1,503 @@ +/* + + Broadcom BCM43xx wireless driver + + debugfs driver debugging code + + Copyright (c) 2005 Michael Buesch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + + + +#include +#include +#include +#include +#include +#include + +#include "bcm43xx.h" +#include "bcm43xx_main.h" +#include "bcm43xx_debugfs.h" +#include "bcm43xx_dma.h" +#include "bcm43xx_pio.h" + +#define REALLY_BIG_BUFFER_SIZE (1024*256) + +static struct bcm43xx_debugfs fs; +static char really_big_buffer[REALLY_BIG_BUFFER_SIZE]; +static DECLARE_MUTEX(big_buffer_sem); + + +static ssize_t write_file_dummy(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + return count; +} + +static int open_file_generic(struct inode *inode, struct file *file) +{ + file->private_data = inode->u.generic_ip; + return 0; +} + +#define fappend(fmt, x...) pos += snprintf(buf + pos, len - pos, fmt , ##x) + +static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + const size_t len = REALLY_BIG_BUFFER_SIZE; + + struct bcm43xx_private *bcm = file->private_data; + char *buf = really_big_buffer; + size_t pos = 0; + ssize_t res; + struct net_device *net_dev; + struct pci_dev *pci_dev; + unsigned long flags; + u16 tmp16; + int i; + + down(&big_buffer_sem); + + spin_lock_irqsave(&bcm->lock, flags); + if (!bcm->initialized) { + fappend("Board not initialized.\n"); + goto out; + } + net_dev = bcm->net_dev; + pci_dev = bcm->pci_dev; + + /* This is where the information is written to the "devinfo" file */ + fappend("*** %s devinfo ***\n", net_dev->name); + fappend("vendor: 0x%04x device: 0x%04x\n", + pci_dev->vendor, pci_dev->device); + fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n", + pci_dev->subsystem_vendor, pci_dev->subsystem_device); + fappend("IRQ: %d\n", bcm->irq); + fappend("mmio_addr: 0x%p mmio_len: %u\n", bcm->mmio_addr, bcm->mmio_len); + fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev); + if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16))) + fappend("Radio disabled by hardware!\n"); + if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4))) + fappend("Radio disabled by hardware!\n"); + fappend("board_vendor: 0x%04x board_type: 0x%04x\n", bcm->board_vendor, + bcm->board_type); + + fappend("\nCores:\n"); +#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, " \ + "rev: 0x%02x, index: 0x%02x\n", \ + (info).flags & BCM43xx_COREFLAG_AVAILABLE \ + ? "available" : "nonavailable", \ + (info).flags & BCM43xx_COREFLAG_ENABLED \ + ? "enabled" : "disabled", \ + (info).id, (info).rev, (info).index) + fappend_core("CHIPCOMMON", bcm->core_chipcommon); + fappend_core("PCI", bcm->core_pci); + fappend_core("V90", bcm->core_v90); + fappend_core("PCMCIA", bcm->core_pcmcia); + fappend_core("ETHERNET", bcm->core_ethernet); + fappend_core("first 80211", bcm->core_80211[0]); + fappend_core("second 80211", bcm->core_80211[1]); +#undef fappend_core + tmp16 = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); + fappend("LEDs: "); + for (i = 0; i < BCM43xx_NR_LEDS; i++) + fappend("%d ", !!(tmp16 & (1 << i))); + fappend("\n"); + +out: + spin_unlock_irqrestore(&bcm->lock, flags); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + up(&big_buffer_sem); + return res; +} + +static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + const size_t len = REALLY_BIG_BUFFER_SIZE; + + char *buf = really_big_buffer; + size_t pos = 0; + ssize_t res; + + down(&big_buffer_sem); + + /* This is where the information is written to the "driver" file */ + fappend(BCM43xx_DRIVER_NAME "\n"); + fappend("Compiled at: %s %s\n", __DATE__, __TIME__); + + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + up(&big_buffer_sem); + return res; +} + +static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + const size_t len = REALLY_BIG_BUFFER_SIZE; + + struct bcm43xx_private *bcm = file->private_data; + char *buf = really_big_buffer; + size_t pos = 0; + ssize_t res; + unsigned long flags; + + down(&big_buffer_sem); + spin_lock_irqsave(&bcm->lock, flags); + if (!bcm->initialized) { + fappend("Board not initialized.\n"); + goto out; + } + + /* This is where the information is written to the "sprom_dump" file */ + fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); + +out: + spin_unlock_irqrestore(&bcm->lock, flags); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + up(&big_buffer_sem); + return res; +} + +static ssize_t tsf_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + const size_t len = REALLY_BIG_BUFFER_SIZE; + + struct bcm43xx_private *bcm = file->private_data; + char *buf = really_big_buffer; + size_t pos = 0; + ssize_t res; + unsigned long flags; + u64 tsf; + + down(&big_buffer_sem); + spin_lock_irqsave(&bcm->lock, flags); + if (!bcm->initialized) { + fappend("Board not initialized.\n"); + goto out; + } + bcm43xx_tsf_read(bcm, &tsf); + fappend("0x%08x%08x\n", + (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32), + (unsigned int)(tsf & 0xFFFFFFFFULL)); + +out: + spin_unlock_irqrestore(&bcm->lock, flags); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + up(&big_buffer_sem); + return res; +} + +static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct bcm43xx_private *bcm = file->private_data; + char *buf = really_big_buffer; + ssize_t buf_size; + ssize_t res; + unsigned long flags; + u64 tsf; + + buf_size = min(count, sizeof (really_big_buffer) - 1); + down(&big_buffer_sem); + if (copy_from_user(buf, user_buf, buf_size)) { + res = -EFAULT; + goto out_up; + } + spin_lock_irqsave(&bcm->lock, flags); + if (!bcm->initialized) { + printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); + res = -EFAULT; + goto out_unlock; + } + if (sscanf(buf, "%lli", &tsf) != 1) { + printk(KERN_INFO PFX "debugfs: invalid values for \"tsf\"\n"); + res = -EINVAL; + goto out_unlock; + } + bcm43xx_tsf_write(bcm, tsf); + res = buf_size; + +out_unlock: + spin_unlock_irqrestore(&bcm->lock, flags); +out_up: + up(&big_buffer_sem); + return res; +} + +static ssize_t txstat_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + const size_t len = REALLY_BIG_BUFFER_SIZE; + + struct bcm43xx_private *bcm = file->private_data; + char *buf = really_big_buffer; + size_t pos = 0; + ssize_t res; + unsigned long flags; + struct bcm43xx_dfsentry *e; + struct bcm43xx_xmitstatus *status; + int i, cnt, j = 0; + + down(&big_buffer_sem); + spin_lock_irqsave(&bcm->lock, flags); + + fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", + BCM43xx_NR_LOGGED_XMITSTATUS); + e = bcm->dfsentry; + if (e->xmitstatus_printing == 0) { + /* At the beginning, make a copy of all data to avoid + * concurrency, as this function is called multiple + * times for big logs. Without copying, the data might + * change between reads. This would result in total trash. + */ + e->xmitstatus_printing = 1; + e->saved_xmitstatus_ptr = e->xmitstatus_ptr; + e->saved_xmitstatus_cnt = e->xmitstatus_cnt; + memcpy(e->xmitstatus_print_buffer, e->xmitstatus_buffer, + BCM43xx_NR_LOGGED_XMITSTATUS * sizeof(*(e->xmitstatus_buffer))); + } + i = e->saved_xmitstatus_ptr - 1; + if (i < 0) + i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; + cnt = e->saved_xmitstatus_cnt; + while (cnt) { + status = e->xmitstatus_print_buffer + i; + fappend("0x%02x: cookie: 0x%04x, flags: 0x%02x, " + "cnt1: 0x%02x, cnt2: 0x%02x, seq: 0x%04x, " + "unk: 0x%04x\n", j, + status->cookie, status->flags, + status->cnt1, status->cnt2, status->seq, + status->unknown); + j++; + cnt--; + i--; + if (i < 0) + i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; + } + + spin_unlock_irqrestore(&bcm->lock, flags); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + spin_lock_irqsave(&bcm->lock, flags); + if (*ppos == pos) { + /* Done. Drop the copied data. */ + e->xmitstatus_printing = 0; + } + spin_unlock_irqrestore(&bcm->lock, flags); + up(&big_buffer_sem); + return res; +} + +#undef fappend + + +static struct file_operations devinfo_fops = { + .read = devinfo_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations spromdump_fops = { + .read = spromdump_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations drvinfo_fops = { + .read = drvinfo_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations tsf_fops = { + .read = tsf_read_file, + .write = tsf_write_file, + .open = open_file_generic, +}; + +static struct file_operations txstat_fops = { + .read = txstat_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + + +void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) +{ + struct bcm43xx_dfsentry *e; + char devdir[IFNAMSIZ]; + + assert(bcm); + e = kzalloc(sizeof(*e), GFP_KERNEL); + if (!e) { + printk(KERN_ERR PFX "out of memory\n"); + return; + } + e->bcm = bcm; + e->xmitstatus_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS + * sizeof(*(e->xmitstatus_buffer)), + GFP_KERNEL); + if (!e->xmitstatus_buffer) { + printk(KERN_ERR PFX "out of memory\n"); + kfree(e); + return; + } + e->xmitstatus_print_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS + * sizeof(*(e->xmitstatus_buffer)), + GFP_KERNEL); + if (!e->xmitstatus_print_buffer) { + printk(KERN_ERR PFX "out of memory\n"); + kfree(e); + return; + } + + + bcm->dfsentry = e; + + strncpy(devdir, bcm->net_dev->name, ARRAY_SIZE(devdir)); + e->subdir = debugfs_create_dir(devdir, fs.root); + e->dentry_devinfo = debugfs_create_file("devinfo", 0444, e->subdir, + bcm, &devinfo_fops); + if (!e->dentry_devinfo) + printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir); + e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir, + bcm, &spromdump_fops); + if (!e->dentry_spromdump) + printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir); + e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir, + bcm, &tsf_fops); + if (!e->dentry_tsf) + printk(KERN_ERR PFX "debugfs: creating \"tsf\" for \"%s\" failed!\n", devdir); + e->dentry_txstat = debugfs_create_file("tx_status", 0444, e->subdir, + bcm, &txstat_fops); + if (!e->dentry_txstat) + printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir); +} + +void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) +{ + struct bcm43xx_dfsentry *e; + + if (!bcm) + return; + + e = bcm->dfsentry; + assert(e); + debugfs_remove(e->dentry_spromdump); + debugfs_remove(e->dentry_devinfo); + debugfs_remove(e->dentry_tsf); + debugfs_remove(e->dentry_txstat); + debugfs_remove(e->subdir); + kfree(e->xmitstatus_buffer); + kfree(e->xmitstatus_print_buffer); + kfree(e); +} + +void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) +{ + struct bcm43xx_dfsentry *e; + struct bcm43xx_xmitstatus *savedstatus; + + /* This is protected by bcm->lock */ + e = bcm->dfsentry; + assert(e); + savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr; + memcpy(savedstatus, status, sizeof(*status)); + e->xmitstatus_ptr++; + if (e->xmitstatus_ptr >= BCM43xx_NR_LOGGED_XMITSTATUS) + e->xmitstatus_ptr = 0; + if (e->xmitstatus_cnt < BCM43xx_NR_LOGGED_XMITSTATUS) + e->xmitstatus_cnt++; +} + +void bcm43xx_debugfs_init(void) +{ + memset(&fs, 0, sizeof(fs)); + fs.root = debugfs_create_dir(DRV_NAME, NULL); + if (!fs.root) + printk(KERN_ERR PFX "debugfs: creating \"" DRV_NAME "\" subdir failed!\n"); + fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops); + if (!fs.dentry_driverinfo) + printk(KERN_ERR PFX "debugfs: creating \"" DRV_NAME "/driver\" failed!\n"); +} + +void bcm43xx_debugfs_exit(void) +{ + debugfs_remove(fs.dentry_driverinfo); + debugfs_remove(fs.root); +} + +void bcm43xx_printk_dump(const char *data, + size_t size, + const char *description) +{ + size_t i; + char c; + + printk(KERN_INFO PFX "Data dump (%s, %u bytes):", + description, size); + for (i = 0; i < size; i++) { + c = data[i]; + if (i % 8 == 0) + printk("\n" KERN_INFO PFX "0x%08x: 0x%02x, ", i, c & 0xff); + else + printk("0x%02x, ", c & 0xff); + } + printk("\n"); +} + +void bcm43xx_printk_bitdump(const unsigned char *data, + size_t bytes, int msb_to_lsb, + const char *description) +{ + size_t i; + int j; + const unsigned char *d; + + printk(KERN_INFO PFX "*** Bitdump (%s, %u bytes, %s) ***", + description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB"); + for (i = 0; i < bytes; i++) { + d = data + i; + if (i % 8 == 0) + printk("\n" KERN_INFO PFX "0x%08x: ", i); + if (msb_to_lsb) { + for (j = 7; j >= 0; j--) { + if (*d & (1 << j)) + printk("1"); + else + printk("0"); + } + } else { + for (j = 0; j < 8; j++) { + if (*d & (1 << j)) + printk("1"); + else + printk("0"); + } + } + printk(" "); + } + printk("\n"); +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h new file mode 100644 index 0000000000..50ce267f79 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h @@ -0,0 +1,117 @@ +#ifndef BCM43xx_DEBUGFS_H_ +#define BCM43xx_DEBUGFS_H_ + +struct bcm43xx_private; +struct bcm43xx_xmitstatus; + +#ifdef CONFIG_BCM43XX_DEBUG + +#include +#include + +struct dentry; + +/* limited by the size of the "really_big_buffer" */ +#define BCM43xx_NR_LOGGED_XMITSTATUS 100 + +struct bcm43xx_dfsentry { + struct dentry *subdir; + struct dentry *dentry_devinfo; + struct dentry *dentry_spromdump; + struct dentry *dentry_tsf; + struct dentry *dentry_txstat; + + struct bcm43xx_private *bcm; + + /* saved xmitstatus. */ + struct bcm43xx_xmitstatus *xmitstatus_buffer; + int xmitstatus_ptr; + int xmitstatus_cnt; + /* We need a seperate buffer while printing to avoid + * concurrency issues. (New xmitstatus can arrive + * while we are printing). + */ + struct bcm43xx_xmitstatus *xmitstatus_print_buffer; + int saved_xmitstatus_ptr; + int saved_xmitstatus_cnt; + int xmitstatus_printing; +}; + +struct bcm43xx_debugfs { + struct dentry *root; + struct dentry *dentry_driverinfo; +}; + +void bcm43xx_debugfs_init(void); +void bcm43xx_debugfs_exit(void); +void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm); +void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm); +void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status); + +/* Debug helper: Dump binary data through printk. */ +void bcm43xx_printk_dump(const char *data, + size_t size, + const char *description); +/* Debug helper: Dump bitwise binary data through printk. */ +void bcm43xx_printk_bitdump(const unsigned char *data, + size_t bytes, int msb_to_lsb, + const char *description); +#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) \ + do { \ + bcm43xx_printk_bitdump((const unsigned char *)(pointer), \ + sizeof(*(pointer)), \ + (msb_to_lsb), \ + (description)); \ + } while (0) + +#else /* CONFIG_BCM43XX_DEBUG*/ + +static inline +void bcm43xx_debugfs_init(void) { } +static inline +void bcm43xx_debugfs_exit(void) { } +static inline +void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) { } +static inline +void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) { } +static inline +void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) { } + +static inline +void bcm43xx_printk_dump(const char *data, + size_t size, + const char *description) +{ +} +static inline +void bcm43xx_printk_bitdump(const unsigned char *data, + size_t bytes, int msb_to_lsb, + const char *description) +{ +} +#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) do { /* nothing */ } while (0) + +#endif /* CONFIG_BCM43XX_DEBUG*/ + +/* Ugly helper macros to make incomplete code more verbose on runtime */ +#ifdef TODO +# undef TODO +#endif +#define TODO() \ + do { \ + printk(KERN_INFO PFX "TODO: Incomplete code in %s() at %s:%d\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + } while (0) + +#ifdef FIXME +# undef FIXME +#endif +#define FIXME() \ + do { \ + printk(KERN_INFO PFX "FIXME: Possibly broken code in %s() at %s:%d\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + } while (0) + +#endif /* BCM43xx_DEBUGFS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c new file mode 100644 index 0000000000..df19fbfa9e --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -0,0 +1,1009 @@ +/* + + Broadcom BCM43xx wireless driver + + DMA ringbuffer and descriptor allocation/management + + Copyright (c) 2005 Michael Buesch + + Some code in this file is derived from the b44.c driver + Copyright (C) 2002 David S. Miller + Copyright (C) Pekka Pietikainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx.h" +#include "bcm43xx_dma.h" +#include "bcm43xx_main.h" +#include "bcm43xx_debugfs.h" +#include "bcm43xx_power.h" + +#include +#include +#include +#include +#include + + +static inline int free_slots(struct bcm43xx_dmaring *ring) +{ + return (ring->nr_slots - ring->used_slots); +} + +static inline int next_slot(struct bcm43xx_dmaring *ring, int slot) +{ + assert(slot >= -1 && slot <= ring->nr_slots - 1); + if (slot == ring->nr_slots - 1) + return 0; + return slot + 1; +} + +static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot) +{ + assert(slot >= 0 && slot <= ring->nr_slots - 1); + if (slot == 0) + return ring->nr_slots - 1; + return slot - 1; +} + +/* Request a slot for usage. */ +static inline +int request_slot(struct bcm43xx_dmaring *ring) +{ + int slot; + + assert(ring->tx); + assert(!ring->suspended); + assert(free_slots(ring) != 0); + + slot = next_slot(ring, ring->current_slot); + ring->current_slot = slot; + ring->used_slots++; + + /* Check the number of available slots and suspend TX, + * if we are running low on free slots. + */ + if (unlikely(free_slots(ring) < ring->suspend_mark)) { + netif_stop_queue(ring->bcm->net_dev); + ring->suspended = 1; + } +#ifdef CONFIG_BCM43XX_DEBUG + if (ring->used_slots > ring->max_used_slots) + ring->max_used_slots = ring->used_slots; +#endif /* CONFIG_BCM43XX_DEBUG*/ + + return slot; +} + +/* Return a slot to the free slots. */ +static inline +void return_slot(struct bcm43xx_dmaring *ring, int slot) +{ + assert(ring->tx); + + ring->used_slots--; + + /* Check if TX is suspended and check if we have + * enough free slots to resume it again. + */ + if (unlikely(ring->suspended)) { + if (free_slots(ring) >= ring->resume_mark) { + ring->suspended = 0; + netif_wake_queue(ring->bcm->net_dev); + } + } +} + +static inline +dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring, + unsigned char *buf, + size_t len, + int tx) +{ + dma_addr_t dmaaddr; + + if (tx) { + dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev, + buf, len, + DMA_TO_DEVICE); + } else { + dmaaddr = dma_map_single(&ring->bcm->pci_dev->dev, + buf, len, + DMA_FROM_DEVICE); + } + + return dmaaddr; +} + +static inline +void unmap_descbuffer(struct bcm43xx_dmaring *ring, + dma_addr_t addr, + size_t len, + int tx) +{ + if (tx) { + dma_unmap_single(&ring->bcm->pci_dev->dev, + addr, len, + DMA_TO_DEVICE); + } else { + dma_unmap_single(&ring->bcm->pci_dev->dev, + addr, len, + DMA_FROM_DEVICE); + } +} + +static inline +void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring, + dma_addr_t addr, + size_t len) +{ + assert(!ring->tx); + + dma_sync_single_for_cpu(&ring->bcm->pci_dev->dev, + addr, len, DMA_FROM_DEVICE); +} + +static inline +void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring, + dma_addr_t addr, + size_t len) +{ + assert(!ring->tx); + + dma_sync_single_for_device(&ring->bcm->pci_dev->dev, + addr, len, DMA_FROM_DEVICE); +} + +static inline +void mark_skb_mustfree(struct sk_buff *skb, + char mustfree) +{ + skb->cb[0] = mustfree; +} + +static inline +int skb_mustfree(struct sk_buff *skb) +{ + return (skb->cb[0] != 0); +} + +/* Unmap and free a descriptor buffer. */ +static inline +void free_descriptor_buffer(struct bcm43xx_dmaring *ring, + struct bcm43xx_dmadesc *desc, + struct bcm43xx_dmadesc_meta *meta, + int irq_context) +{ + assert(meta->skb); + if (skb_mustfree(meta->skb)) { + if (irq_context) + dev_kfree_skb_irq(meta->skb); + else + dev_kfree_skb(meta->skb); + } + meta->skb = NULL; + if (meta->txb) { + ieee80211_txb_free(meta->txb); + meta->txb = NULL; + } +} + +static int alloc_ringmemory(struct bcm43xx_dmaring *ring) +{ + struct device *dev = &(ring->bcm->pci_dev->dev); + + ring->vbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, + &(ring->dmabase), GFP_KERNEL); + if (!ring->vbase) { + printk(KERN_ERR PFX "DMA ringmemory allocation failed\n"); + return -ENOMEM; + } + if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) { + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G\n"); + dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, + ring->vbase, ring->dmabase); + return -ENOMEM; + } + assert(!(ring->dmabase & 0x000003FF)); + memset(ring->vbase, 0, BCM43xx_DMA_RINGMEMSIZE); + + return 0; +} + +static void free_ringmemory(struct bcm43xx_dmaring *ring) +{ + struct device *dev = &(ring->bcm->pci_dev->dev); + + dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, + ring->vbase, ring->dmabase); +} + +/* Reset the RX DMA channel */ +int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, + u16 mmio_base) +{ + int i; + u32 value; + + bcm43xx_write32(bcm, + mmio_base + BCM43xx_DMA_RX_CONTROL, + 0x00000000); + for (i = 0; i < 1000; i++) { + value = bcm43xx_read32(bcm, + mmio_base + BCM43xx_DMA_RX_STATUS); + value &= BCM43xx_DMA_RXSTAT_STAT_MASK; + if (value == BCM43xx_DMA_RXSTAT_STAT_DISABLED) { + i = -1; + break; + } + udelay(10); + } + if (i != -1) { + printk(KERN_ERR PFX "Error: Wait on DMA RX status timed out.\n"); + return -ENODEV; + } + + return 0; +} + +static inline int dmacontroller_rx_reset(struct bcm43xx_dmaring *ring) +{ + assert(!ring->tx); + + return bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base); +} + +/* Reset the RX DMA channel */ +int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, + u16 mmio_base) +{ + int i; + u32 value; + + for (i = 0; i < 1000; i++) { + value = bcm43xx_read32(bcm, + mmio_base + BCM43xx_DMA_TX_STATUS); + value &= BCM43xx_DMA_TXSTAT_STAT_MASK; + if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED || + value == BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT || + value == BCM43xx_DMA_TXSTAT_STAT_STOPPED) + break; + udelay(10); + } + bcm43xx_write32(bcm, + mmio_base + BCM43xx_DMA_TX_CONTROL, + 0x00000000); + for (i = 0; i < 1000; i++) { + value = bcm43xx_read32(bcm, + mmio_base + BCM43xx_DMA_TX_STATUS); + value &= BCM43xx_DMA_TXSTAT_STAT_MASK; + if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED) { + i = -1; + break; + } + udelay(10); + } + if (i != -1) { + printk(KERN_ERR PFX "Error: Wait on DMA TX status timed out.\n"); + return -ENODEV; + } + /* ensure the reset is completed. */ + udelay(300); + + return 0; +} + +static inline int dmacontroller_tx_reset(struct bcm43xx_dmaring *ring) +{ + assert(ring->tx); + + return bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base); +} + +static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, + struct bcm43xx_dmadesc *desc, + struct bcm43xx_dmadesc_meta *meta, + gfp_t gfp_flags) +{ + struct bcm43xx_rxhdr *rxhdr; + dma_addr_t dmaaddr; + u32 desc_addr; + u32 desc_ctl; + const int slot = (int)(desc - ring->vbase); + struct sk_buff *skb; + + assert(slot >= 0 && slot < ring->nr_slots); + assert(!ring->tx); + + skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); + if (unlikely(!skb)) + return -ENOMEM; + dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); + if (unlikely(dmaaddr + ring->rx_buffersize > BCM43xx_DMA_BUSADDRMAX)) { + unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); + dev_kfree_skb_any(skb); + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G\n"); + return -ENOMEM; + } + meta->skb = skb; + meta->dmaaddr = dmaaddr; + skb->dev = ring->bcm->net_dev; + mark_skb_mustfree(skb, 1); + desc_addr = (u32)(dmaaddr + ring->memoffset); + desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK & + (u32)(ring->rx_buffersize - ring->frameoffset)); + if (slot == ring->nr_slots - 1) + desc_ctl |= BCM43xx_DMADTOR_DTABLEEND; + set_desc_addr(desc, desc_addr); + set_desc_ctl(desc, desc_ctl); + + rxhdr = (struct bcm43xx_rxhdr *)(skb->data); + rxhdr->frame_length = 0; + rxhdr->flags1 = 0; + + return 0; +} + +/* Allocate the initial descbuffers. + * This is used for an RX ring only. + */ +static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring) +{ + int i, err = -ENOMEM; + struct bcm43xx_dmadesc *desc = NULL; + struct bcm43xx_dmadesc_meta *meta; + + for (i = 0; i < ring->nr_slots; i++) { + desc = ring->vbase + i; + meta = ring->meta + i; + + err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); + if (err) + goto err_unwind; + + assert(ring->used_slots <= ring->nr_slots); + } + ring->used_slots = ring->nr_slots; + + err = 0; +out: + return err; + +err_unwind: + for ( ; i >= 0; i--) { + desc = ring->vbase + i; + meta = ring->meta + i; + + unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); + dev_kfree_skb(meta->skb); + } + ring->used_slots = 0; + goto out; +} + +/* Do initial setup of the DMA controller. + * Reset the controller, write the ring busaddress + * and switch the "enable" bit on. + */ +static int dmacontroller_setup(struct bcm43xx_dmaring *ring) +{ + int err = 0; + u32 value; + + if (ring->tx) { + /* Set Transmit Control register to "transmit enable" */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_TX_CONTROL, + BCM43xx_DMA_TXCTRL_ENABLE); + /* Set Transmit Descriptor ring address. */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_TX_DESC_RING, + ring->dmabase + ring->memoffset); + } else { + err = alloc_initial_descbuffers(ring); + if (err) + goto out; + /* Set Receive Control "receive enable" and frame offset */ + value = (ring->frameoffset << BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT); + value |= BCM43xx_DMA_RXCTRL_ENABLE; + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_RX_CONTROL, + value); + /* Set Receive Descriptor ring address. */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_RX_DESC_RING, + ring->dmabase + ring->memoffset); + /* Init the descriptor pointer. */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_RX_DESC_INDEX, + 200); + } + +out: + return err; +} + +/* Shutdown the DMA controller. */ +static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring) +{ + if (ring->tx) { + dmacontroller_tx_reset(ring); + /* Zero out Transmit Descriptor ring address. */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_TX_DESC_RING, + 0x00000000); + } else { + dmacontroller_rx_reset(ring); + /* Zero out Receive Descriptor ring address. */ + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_RX_DESC_RING, + 0x00000000); + } +} + +static void free_all_descbuffers(struct bcm43xx_dmaring *ring) +{ + struct bcm43xx_dmadesc *desc; + struct bcm43xx_dmadesc_meta *meta; + int i; + + if (!ring->used_slots) + return; + for (i = 0; i < ring->nr_slots; i++) { + desc = ring->vbase + i; + meta = ring->meta + i; + + if (!meta->skb) { + assert(ring->tx); + assert(!meta->txb); + continue; + } + if (ring->tx) { + unmap_descbuffer(ring, meta->dmaaddr, + meta->skb->len, 1); + } else { + unmap_descbuffer(ring, meta->dmaaddr, + ring->rx_buffersize, 0); + } + free_descriptor_buffer(ring, desc, meta, 0); + } +} + +/* Main initialization function. */ +static +struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm, + u16 dma_controller_base, + int nr_descriptor_slots, + int tx) +{ + struct bcm43xx_dmaring *ring; + int err; + + ring = kzalloc(sizeof(*ring), GFP_KERNEL); + if (!ring) + goto out; + + ring->meta = kzalloc(sizeof(*ring->meta) * nr_descriptor_slots, + GFP_KERNEL); + if (!ring->meta) + goto err_kfree_ring; + + ring->memoffset = BCM43xx_DMA_DMABUSADDROFFSET; +#ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) + ring->memoffset = 0; +#endif + + + spin_lock_init(&ring->lock); + ring->bcm = bcm; + ring->nr_slots = nr_descriptor_slots; + ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100; + ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100; + assert(ring->suspend_mark < ring->resume_mark); + ring->mmio_base = dma_controller_base; + if (tx) { + ring->tx = 1; + ring->current_slot = -1; + } else { + switch (dma_controller_base) { + case BCM43xx_MMIO_DMA1_BASE: + ring->rx_buffersize = BCM43xx_DMA1_RXBUFFERSIZE; + ring->frameoffset = BCM43xx_DMA1_RX_FRAMEOFFSET; + break; + case BCM43xx_MMIO_DMA4_BASE: + ring->rx_buffersize = BCM43xx_DMA4_RXBUFFERSIZE; + ring->frameoffset = BCM43xx_DMA4_RX_FRAMEOFFSET; + break; + default: + assert(0); + } + } + + err = alloc_ringmemory(ring); + if (err) + goto err_kfree_meta; + err = dmacontroller_setup(ring); + if (err) + goto err_free_ringmemory; + +out: + return ring; + +err_free_ringmemory: + free_ringmemory(ring); +err_kfree_meta: + kfree(ring->meta); +err_kfree_ring: + kfree(ring); + ring = NULL; + goto out; +} + +/* Main cleanup function. */ +static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring) +{ + if (!ring) + return; + + dprintk(KERN_INFO PFX "DMA 0x%04x (%s) max used slots: %d/%d\n", + ring->mmio_base, + (ring->tx) ? "TX" : "RX", + ring->max_used_slots, ring->nr_slots); + /* Device IRQs are disabled prior entering this function, + * so no need to take care of concurrency with rx handler stuff. + */ + dmacontroller_cleanup(ring); + free_all_descbuffers(ring); + free_ringmemory(ring); + + kfree(ring->meta); + kfree(ring); +} + +void bcm43xx_dma_free(struct bcm43xx_private *bcm) +{ + bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring1); + bcm->current_core->dma->rx_ring1 = NULL; + bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring0); + bcm->current_core->dma->rx_ring0 = NULL; + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring3); + bcm->current_core->dma->tx_ring3 = NULL; + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring2); + bcm->current_core->dma->tx_ring2 = NULL; + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring1); + bcm->current_core->dma->tx_ring1 = NULL; + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring0); + bcm->current_core->dma->tx_ring0 = NULL; +} + +int bcm43xx_dma_init(struct bcm43xx_private *bcm) +{ + struct bcm43xx_dmaring *ring; + int err = -ENOMEM; + + /* setup TX DMA channels. */ + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE, + BCM43xx_TXRING_SLOTS, 1); + if (!ring) + goto out; + bcm->current_core->dma->tx_ring0 = ring; + + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA2_BASE, + BCM43xx_TXRING_SLOTS, 1); + if (!ring) + goto err_destroy_tx0; + bcm->current_core->dma->tx_ring1 = ring; + + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA3_BASE, + BCM43xx_TXRING_SLOTS, 1); + if (!ring) + goto err_destroy_tx1; + bcm->current_core->dma->tx_ring2 = ring; + + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, + BCM43xx_TXRING_SLOTS, 1); + if (!ring) + goto err_destroy_tx2; + bcm->current_core->dma->tx_ring3 = ring; + + /* setup RX DMA channels. */ + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE, + BCM43xx_RXRING_SLOTS, 0); + if (!ring) + goto err_destroy_tx3; + bcm->current_core->dma->rx_ring0 = ring; + + if (bcm->current_core->rev < 5) { + ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, + BCM43xx_RXRING_SLOTS, 0); + if (!ring) + goto err_destroy_rx0; + bcm->current_core->dma->rx_ring1 = ring; + } + + dprintk(KERN_INFO PFX "DMA initialized\n"); + err = 0; +out: + return err; + +err_destroy_rx0: + bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring0); + bcm->current_core->dma->rx_ring0 = NULL; +err_destroy_tx3: + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring3); + bcm->current_core->dma->tx_ring3 = NULL; +err_destroy_tx2: + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring2); + bcm->current_core->dma->tx_ring2 = NULL; +err_destroy_tx1: + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring1); + bcm->current_core->dma->tx_ring1 = NULL; +err_destroy_tx0: + bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring0); + bcm->current_core->dma->tx_ring0 = NULL; + goto out; +} + +/* Generate a cookie for the TX header. */ +static inline +u16 generate_cookie(struct bcm43xx_dmaring *ring, + int slot) +{ + u16 cookie = 0x0000; + + /* Use the upper 4 bits of the cookie as + * DMA controller ID and store the slot number + * in the lower 12 bits + */ + switch (ring->mmio_base) { + default: + assert(0); + case BCM43xx_MMIO_DMA1_BASE: + break; + case BCM43xx_MMIO_DMA2_BASE: + cookie = 0x1000; + break; + case BCM43xx_MMIO_DMA3_BASE: + cookie = 0x2000; + break; + case BCM43xx_MMIO_DMA4_BASE: + cookie = 0x3000; + break; + } + assert(((u16)slot & 0xF000) == 0x0000); + cookie |= (u16)slot; + + return cookie; +} + +/* Inspect a cookie and find out to which controller/slot it belongs. */ +static inline +struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, + u16 cookie, int *slot) +{ + struct bcm43xx_dmaring *ring = NULL; + + switch (cookie & 0xF000) { + case 0x0000: + ring = bcm->current_core->dma->tx_ring0; + break; + case 0x1000: + ring = bcm->current_core->dma->tx_ring1; + break; + case 0x2000: + ring = bcm->current_core->dma->tx_ring2; + break; + case 0x3000: + ring = bcm->current_core->dma->tx_ring3; + break; + default: + assert(0); + } + *slot = (cookie & 0x0FFF); + assert(*slot >= 0 && *slot < ring->nr_slots); + + return ring; +} + +static inline void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, + int slot) +{ + /* Everything is ready to start. Buffers are DMA mapped and + * associated with slots. + * "slot" is the last slot of the new frame we want to transmit. + * Close your seat belts now, please. + */ + wmb(); + slot = next_slot(ring, slot); + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_TX_DESC_INDEX, + (u32)(slot * sizeof(struct bcm43xx_dmadesc))); +} + +static inline +int dma_tx_fragment(struct bcm43xx_dmaring *ring, + struct sk_buff *skb, + struct ieee80211_txb *txb, + u8 cur_frag) +{ + int slot; + struct bcm43xx_dmadesc *desc; + struct bcm43xx_dmadesc_meta *meta; + u32 desc_ctl; + u32 desc_addr; + + assert(skb_shinfo(skb)->nr_frags == 0); + + slot = request_slot(ring); + desc = ring->vbase + slot; + meta = ring->meta + slot; + + if (cur_frag == 0) { + /* Save the txb pointer for freeing in xmitstatus IRQ */ + meta->txb = txb; + } + + /* Add a device specific TX header. */ + assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); + /* Reserve enough headroom for the device tx header. */ + __skb_push(skb, sizeof(struct bcm43xx_txhdr)); + /* Now calculate and add the tx header. + * The tx header includes the PLCP header. + */ + bcm43xx_generate_txhdr(ring->bcm, + (struct bcm43xx_txhdr *)skb->data, + skb->data + sizeof(struct bcm43xx_txhdr), + skb->len - sizeof(struct bcm43xx_txhdr), + (cur_frag == 0), + generate_cookie(ring, slot)); + + meta->skb = skb; + meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); + if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) { + return_slot(ring, slot); + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G\n"); + return -ENOMEM; + } + + desc_addr = (u32)(meta->dmaaddr + ring->memoffset); + desc_ctl = BCM43xx_DMADTOR_FRAMESTART | BCM43xx_DMADTOR_FRAMEEND; + desc_ctl |= BCM43xx_DMADTOR_COMPIRQ; + desc_ctl |= (BCM43xx_DMADTOR_BYTECNT_MASK & + (u32)(meta->skb->len - ring->frameoffset)); + if (slot == ring->nr_slots - 1) + desc_ctl |= BCM43xx_DMADTOR_DTABLEEND; + + set_desc_ctl(desc, desc_ctl); + set_desc_addr(desc, desc_addr); + /* Now transfer the whole frame. */ + dmacontroller_poke_tx(ring, slot); + + return 0; +} + +static inline int dma_transfer_txb(struct bcm43xx_dmaring *ring, + struct ieee80211_txb *txb) +{ + /* We just received a packet from the kernel network subsystem. + * Add headers and DMA map the memory. Poke + * the device to send the stuff. + * Note that this is called from atomic context. + */ + u8 i; + struct sk_buff *skb; + + assert(ring->tx); + if (unlikely(free_slots(ring) < txb->nr_frags)) { + /* The queue should be stopped, + * if we are low on free slots. + * If this ever triggers, we have to lower the suspend_mark. + */ + dprintkl(KERN_ERR PFX "Out of DMA descriptor slots!\n"); + return -ENOMEM; + } + + assert(irqs_disabled()); + spin_lock(&ring->lock); + for (i = 0; i < txb->nr_frags; i++) { + skb = txb->fragments[i]; + /* We do not free the skb, as it is freed as + * part of the txb freeing. + */ + mark_skb_mustfree(skb, 0); + dma_tx_fragment(ring, skb, txb, i); + //TODO: handle failure of dma_tx_fragment + } + spin_unlock(&ring->lock); + + return 0; +} + +int fastcall +bcm43xx_dma_transfer_txb(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) +{ + return dma_transfer_txb(bcm->current_core->dma->tx_ring1, + txb); +} + +void fastcall +bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) +{ + struct bcm43xx_dmaring *ring; + struct bcm43xx_dmadesc *desc; + struct bcm43xx_dmadesc_meta *meta; + int is_last_fragment; + int slot; + + ring = parse_cookie(bcm, status->cookie, &slot); + assert(ring); + assert(ring->tx); + assert(irqs_disabled()); + spin_lock(&ring->lock); + + assert(get_desc_ctl(ring->vbase + slot) & BCM43xx_DMADTOR_FRAMESTART); + while (1) { + assert(slot >= 0 && slot < ring->nr_slots); + desc = ring->vbase + slot; + meta = ring->meta + slot; + + is_last_fragment = !!(get_desc_ctl(desc) & BCM43xx_DMADTOR_FRAMEEND); + unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); + free_descriptor_buffer(ring, desc, meta, 1); + /* Everything belonging to the slot is unmapped + * and freed, so we can return it. + */ + return_slot(ring, slot); + + if (is_last_fragment) + break; + slot = next_slot(ring, slot); + } + bcm->stats.last_tx = jiffies; + + spin_unlock(&ring->lock); +} + +static inline +void dma_rx(struct bcm43xx_dmaring *ring, + int *slot) +{ + struct bcm43xx_dmadesc *desc; + struct bcm43xx_dmadesc_meta *meta; + struct bcm43xx_rxhdr *rxhdr; + struct sk_buff *skb; + u16 len; + int err; + dma_addr_t dmaaddr; + + desc = ring->vbase + *slot; + meta = ring->meta + *slot; + + sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); + skb = meta->skb; + + if (ring->mmio_base == BCM43xx_MMIO_DMA4_BASE) { + /* We received an xmit status. */ + struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data; + struct bcm43xx_xmitstatus stat; + + stat.cookie = le16_to_cpu(hw->cookie); + stat.flags = hw->flags; + stat.cnt1 = hw->cnt1; + stat.cnt2 = hw->cnt2; + stat.seq = le16_to_cpu(hw->seq); + stat.unknown = le16_to_cpu(hw->unknown); + + bcm43xx_debugfs_log_txstat(ring->bcm, &stat); + bcm43xx_dma_handle_xmitstatus(ring->bcm, &stat); + /* recycle the descriptor buffer. */ + sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize); + + return; + } + rxhdr = (struct bcm43xx_rxhdr *)skb->data; + len = le16_to_cpu(rxhdr->frame_length); + if (len == 0) { + int i = 0; + + do { + udelay(2); + barrier(); + len = le16_to_cpu(rxhdr->frame_length); + } while (len == 0 && i++ < 5); + if (len == 0) + goto drop; + } + if (unlikely(len > ring->rx_buffersize)) { + /* The data did not fit into one descriptor buffer + * and is split over multiple buffers. + * This should never happen, as we try to allocate buffers + * big enough. So simply ignore this packet. + */ + int cnt = 1; + s32 tmp = len - ring->rx_buffersize; + + for ( ; tmp > 0; tmp -= ring->rx_buffersize) { + *slot = next_slot(ring, *slot); + cnt++; + } + printkl(KERN_ERR PFX "DMA RX buffer too small. %d dropped.\n", + cnt); + goto drop; + } + len -= IEEE80211_FCS_LEN; + + dmaaddr = meta->dmaaddr; + err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC); + if (unlikely(err)) { + dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n"); + goto drop; + } + + unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); + skb_put(skb, len + ring->frameoffset); + skb_pull(skb, ring->frameoffset); + + err = bcm43xx_rx(ring->bcm, skb, rxhdr); + if (err) { + dev_kfree_skb_irq(skb); + goto drop; + } + +drop: + return; +} + +void fastcall +bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) +{ + u32 status; + u16 descptr; + int slot, current_slot; +#ifdef CONFIG_BCM43XX_DEBUG + int used_slots = 0; +#endif + + assert(!ring->tx); + assert(irqs_disabled()); + spin_lock(&ring->lock); + + status = bcm43xx_read32(ring->bcm, ring->mmio_base + BCM43xx_DMA_RX_STATUS); + descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK); + current_slot = descptr / sizeof(struct bcm43xx_dmadesc); + assert(current_slot >= 0 && current_slot < ring->nr_slots); + + slot = ring->current_slot; + for ( ; slot != current_slot; slot = next_slot(ring, slot)) { + dma_rx(ring, &slot); +#ifdef CONFIG_BCM43XX_DEBUG + if (++used_slots > ring->max_used_slots) + ring->max_used_slots = used_slots; +#endif + } + bcm43xx_write32(ring->bcm, + ring->mmio_base + BCM43xx_DMA_RX_DESC_INDEX, + (u32)(slot * sizeof(struct bcm43xx_dmadesc))); + ring->current_slot = slot; + + spin_unlock(&ring->lock); +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h new file mode 100644 index 0000000000..e32cf68f8e --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -0,0 +1,176 @@ +#ifndef BCM43xx_DMA_H_ +#define BCM43xx_DMA_H_ + +#include +#include +#include +#include +#include + + +/* DMA-Interrupt reasons. */ +/*TODO: add the missing ones. */ +#define BCM43xx_DMAIRQ_ERR0 (1 << 10) +#define BCM43xx_DMAIRQ_ERR1 (1 << 11) +#define BCM43xx_DMAIRQ_ERR2 (1 << 12) +#define BCM43xx_DMAIRQ_ERR3 (1 << 13) +#define BCM43xx_DMAIRQ_ERR4 (1 << 14) +#define BCM43xx_DMAIRQ_ERR5 (1 << 15) +#define BCM43xx_DMAIRQ_RX_DONE (1 << 16) +/* helpers */ +#define BCM43xx_DMAIRQ_ANYERR (BCM43xx_DMAIRQ_ERR0 | \ + BCM43xx_DMAIRQ_ERR1 | \ + BCM43xx_DMAIRQ_ERR2 | \ + BCM43xx_DMAIRQ_ERR3 | \ + BCM43xx_DMAIRQ_ERR4 | \ + BCM43xx_DMAIRQ_ERR5) +#define BCM43xx_DMAIRQ_FATALERR (BCM43xx_DMAIRQ_ERR0 | \ + BCM43xx_DMAIRQ_ERR1 | \ + BCM43xx_DMAIRQ_ERR2 | \ + BCM43xx_DMAIRQ_ERR4 | \ + BCM43xx_DMAIRQ_ERR5) +#define BCM43xx_DMAIRQ_NONFATALERR BCM43xx_DMAIRQ_ERR3 + +/* DMA controller register offsets. (relative to BCM43xx_DMA#_BASE) */ +#define BCM43xx_DMA_TX_CONTROL 0x00 +#define BCM43xx_DMA_TX_DESC_RING 0x04 +#define BCM43xx_DMA_TX_DESC_INDEX 0x08 +#define BCM43xx_DMA_TX_STATUS 0x0c +#define BCM43xx_DMA_RX_CONTROL 0x10 +#define BCM43xx_DMA_RX_DESC_RING 0x14 +#define BCM43xx_DMA_RX_DESC_INDEX 0x18 +#define BCM43xx_DMA_RX_STATUS 0x1c + +/* DMA controller channel control word values. */ +#define BCM43xx_DMA_TXCTRL_ENABLE (1 << 0) +#define BCM43xx_DMA_TXCTRL_SUSPEND (1 << 1) +#define BCM43xx_DMA_TXCTRL_LOOPBACK (1 << 2) +#define BCM43xx_DMA_TXCTRL_FLUSH (1 << 4) +#define BCM43xx_DMA_RXCTRL_ENABLE (1 << 0) +#define BCM43xx_DMA_RXCTRL_FRAMEOFF_MASK 0x000000fe +#define BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT 1 +#define BCM43xx_DMA_RXCTRL_PIO (1 << 8) +/* DMA controller channel status word values. */ +#define BCM43xx_DMA_TXSTAT_DPTR_MASK 0x00000fff +#define BCM43xx_DMA_TXSTAT_STAT_MASK 0x0000f000 +#define BCM43xx_DMA_TXSTAT_STAT_DISABLED 0x00000000 +#define BCM43xx_DMA_TXSTAT_STAT_ACTIVE 0x00001000 +#define BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT 0x00002000 +#define BCM43xx_DMA_TXSTAT_STAT_STOPPED 0x00003000 +#define BCM43xx_DMA_TXSTAT_STAT_SUSP 0x00004000 +#define BCM43xx_DMA_TXSTAT_ERROR_MASK 0x000f0000 +#define BCM43xx_DMA_TXSTAT_FLUSHED (1 << 20) +#define BCM43xx_DMA_RXSTAT_DPTR_MASK 0x00000fff +#define BCM43xx_DMA_RXSTAT_STAT_MASK 0x0000f000 +#define BCM43xx_DMA_RXSTAT_STAT_DISABLED 0x00000000 +#define BCM43xx_DMA_RXSTAT_STAT_ACTIVE 0x00001000 +#define BCM43xx_DMA_RXSTAT_STAT_IDLEWAIT 0x00002000 +#define BCM43xx_DMA_RXSTAT_STAT_RESERVED 0x00003000 +#define BCM43xx_DMA_RXSTAT_STAT_ERRORS 0x00004000 +#define BCM43xx_DMA_RXSTAT_ERROR_MASK 0x000f0000 + +/* DMA descriptor control field values. */ +#define BCM43xx_DMADTOR_BYTECNT_MASK 0x00001fff +#define BCM43xx_DMADTOR_DTABLEEND (1 << 28) /* End of descriptor table */ +#define BCM43xx_DMADTOR_COMPIRQ (1 << 29) /* IRQ on completion request */ +#define BCM43xx_DMADTOR_FRAMEEND (1 << 30) +#define BCM43xx_DMADTOR_FRAMESTART (1 << 31) + +/* Misc DMA constants */ +#define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE +#define BCM43xx_DMA_BUSADDRMAX 0x3FFFFFFF +#define BCM43xx_DMA_DMABUSADDROFFSET (1 << 30) +#define BCM43xx_DMA1_RX_FRAMEOFFSET 30 +#define BCM43xx_DMA4_RX_FRAMEOFFSET 0 + +/* DMA engine tuning knobs */ +#define BCM43xx_TXRING_SLOTS 512 +#define BCM43xx_RXRING_SLOTS 64 +#define BCM43xx_DMA1_RXBUFFERSIZE (2304 + 100) +#define BCM43xx_DMA4_RXBUFFERSIZE 16 +/* Suspend the tx queue, if less than this percent slots are free. */ +#define BCM43xx_TXSUSPEND_PERCENT 20 +/* Resume the tx queue, if more than this percent slots are free. */ +#define BCM43xx_TXRESUME_PERCENT 50 + + +struct sk_buff; +struct bcm43xx_private; +struct bcm43xx_xmitstatus; + + +struct bcm43xx_dmadesc { + __le32 _control; + __le32 _address; +} __attribute__((__packed__)); + +/* Macros to access the bcm43xx_dmadesc struct */ +#define get_desc_ctl(desc) le32_to_cpu((desc)->_control) +#define set_desc_ctl(desc, ctl) do { (desc)->_control = cpu_to_le32(ctl); } while (0) +#define get_desc_addr(desc) le32_to_cpu((desc)->_address) +#define set_desc_addr(desc, addr) do { (desc)->_address = cpu_to_le32(addr); } while (0) + +struct bcm43xx_dmadesc_meta { + /* The kernel DMA-able buffer. */ + struct sk_buff *skb; + /* DMA base bus-address of the descriptor buffer. */ + dma_addr_t dmaaddr; + /* Pointer to our txb (can be NULL). + * This should be freed in completion IRQ. + */ + struct ieee80211_txb *txb; +}; + +struct bcm43xx_dmaring { + spinlock_t lock; + struct bcm43xx_private *bcm; + /* Kernel virtual base address of the ring memory. */ + struct bcm43xx_dmadesc *vbase; + /* DMA memory offset */ + dma_addr_t memoffset; + /* (Unadjusted) DMA base bus-address of the ring memory. */ + dma_addr_t dmabase; + /* Meta data about all descriptors. */ + struct bcm43xx_dmadesc_meta *meta; + /* Number of descriptor slots in the ring. */ + int nr_slots; + /* Number of used descriptor slots. */ + int used_slots; + /* Currently used slot in the ring. */ + int current_slot; + /* Marks to suspend/resume the queue. */ + int suspend_mark; + int resume_mark; + /* Frameoffset in octets. */ + u32 frameoffset; + /* Descriptor buffer size. */ + u16 rx_buffersize; + /* The MMIO base register of the DMA controller, this + * ring is posted to. + */ + u16 mmio_base; + u8 tx:1, /* TRUE, if this is a TX ring. */ + suspended:1; /* TRUE, if transfers are suspended on this ring. */ +#ifdef CONFIG_BCM43XX_DEBUG + /* Maximum number of used slots. */ + int max_used_slots; +#endif /* CONFIG_BCM43XX_DEBUG*/ +}; + + +int bcm43xx_dma_init(struct bcm43xx_private *bcm); +void bcm43xx_dma_free(struct bcm43xx_private *bcm); + +int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, + u16 dmacontroller_mmio_base); +int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, + u16 dmacontroller_mmio_base); + +int FASTCALL(bcm43xx_dma_transfer_txb(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb)); +void FASTCALL(bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status)); + +void FASTCALL(bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)); + +#endif /* BCM43xx_DMA_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c new file mode 100644 index 0000000000..22587e0e1a --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c @@ -0,0 +1,367 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx.h" +#include "bcm43xx_ilt.h" +#include "bcm43xx_phy.h" + + +/**** Initial Internal Lookup Tables ****/ + +const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE] = { + 0xFEB93FFD, 0xFEC63FFD, /* 0 */ + 0xFED23FFD, 0xFEDF3FFD, + 0xFEEC3FFE, 0xFEF83FFE, + 0xFF053FFE, 0xFF113FFE, + 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */ + 0xFF373FFF, 0xFF443FFF, + 0xFF503FFF, 0xFF5D3FFF, + 0xFF693FFF, 0xFF763FFF, + 0xFF824000, 0xFF8F4000, /* 16 */ + 0xFF9B4000, 0xFFA84000, + 0xFFB54000, 0xFFC14000, + 0xFFCE4000, 0xFFDA4000, + 0xFFE74000, 0xFFF34000, /* 24 */ + 0x00004000, 0x000D4000, + 0x00194000, 0x00264000, + 0x00324000, 0x003F4000, + 0x004B4000, 0x00584000, /* 32 */ + 0x00654000, 0x00714000, + 0x007E4000, 0x008A3FFF, + 0x00973FFF, 0x00A33FFF, + 0x00B03FFF, 0x00BC3FFF, /* 40 */ + 0x00C93FFF, 0x00D63FFF, + 0x00E23FFE, 0x00EF3FFE, + 0x00FB3FFE, 0x01083FFE, + 0x01143FFE, 0x01213FFD, /* 48 */ + 0x012E3FFD, 0x013A3FFD, + 0x01473FFD, +}; + +const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE] = { + 0xDB93CB87, 0xD666CF64, /* 0 */ + 0xD1FDD358, 0xCDA6D826, + 0xCA38DD9F, 0xC729E2B4, + 0xC469E88E, 0xC26AEE2B, + 0xC0DEF46C, 0xC073FA62, /* 8 */ + 0xC01D00D5, 0xC0760743, + 0xC1560D1E, 0xC2E51369, + 0xC4ED18FF, 0xC7AC1ED7, + 0xCB2823B2, 0xCEFA28D9, /* 16 */ + 0xD2F62D3F, 0xD7BB3197, + 0xDCE53568, 0xE1FE3875, + 0xE7D13B35, 0xED663D35, + 0xF39B3EC4, 0xF98E3FA7, /* 24 */ + 0x00004000, 0x06723FA7, + 0x0C653EC4, 0x129A3D35, + 0x182F3B35, 0x1E023875, + 0x231B3568, 0x28453197, /* 32 */ + 0x2D0A2D3F, 0x310628D9, + 0x34D823B2, 0x38541ED7, + 0x3B1318FF, 0x3D1B1369, + 0x3EAA0D1E, 0x3F8A0743, /* 40 */ + 0x3FE300D5, 0x3F8DFA62, + 0x3F22F46C, 0x3D96EE2B, + 0x3B97E88E, 0x38D7E2B4, + 0x35C8DD9F, 0x325AD826, /* 48 */ + 0x2E03D358, 0x299ACF64, + 0x246DCB87, +}; + +const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE] = { + 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */ + 0x0202, 0x0282, 0x0302, 0x0382, + 0x0402, 0x0482, 0x0502, 0x0582, + 0x05E2, 0x0662, 0x06E2, 0x0762, + 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */ + 0x09C2, 0x0A22, 0x0AA2, 0x0B02, + 0x0B82, 0x0BE2, 0x0C62, 0x0CC2, + 0x0D42, 0x0DA2, 0x0E02, 0x0E62, + 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */ + 0x1062, 0x10C2, 0x1122, 0x1182, + 0x11E2, 0x1242, 0x12A2, 0x12E2, + 0x1342, 0x13A2, 0x1402, 0x1442, + 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */ + 0x15E2, 0x1622, 0x1662, 0x16C1, + 0x1701, 0x1741, 0x1781, 0x17E1, + 0x1821, 0x1861, 0x18A1, 0x18E1, + 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */ + 0x1A21, 0x1A61, 0x1AA1, 0x1AC1, + 0x1B01, 0x1B41, 0x1B81, 0x1BA1, + 0x1BE1, 0x1C21, 0x1C41, 0x1C81, + 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */ + 0x1D61, 0x1DA1, 0x1DC1, 0x1E01, + 0x1E21, 0x1E61, 0x1E81, 0x1EA1, + 0x1EE1, 0x1F01, 0x1F21, 0x1F41, + 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */ + 0x2001, 0x2041, 0x2061, 0x2081, + 0x20A1, 0x20C1, 0x20E1, 0x2101, + 0x2121, 0x2141, 0x2161, 0x2181, + 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */ + 0x2221, 0x2241, 0x2261, 0x2281, + 0x22A1, 0x22C1, 0x22C1, 0x22E1, + 0x2301, 0x2321, 0x2341, 0x2361, + 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */ + 0x23E1, 0x23E1, 0x2401, 0x2421, + 0x2441, 0x2441, 0x2461, 0x2481, + 0x2481, 0x24A1, 0x24C1, 0x24C1, + 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */ + 0x2541, 0x2541, 0x2561, 0x2561, + 0x2581, 0x25A1, 0x25A1, 0x25C1, + 0x25C1, 0x25E1, 0x2601, 0x2601, + 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */ + 0x2661, 0x2661, 0x2681, 0x2681, + 0x26A1, 0x26A1, 0x26C1, 0x26C1, + 0x26E1, 0x26E1, 0x2701, 0x2701, + 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */ + 0x2760, 0x2760, 0x2780, 0x2780, + 0x2780, 0x27A0, 0x27A0, 0x27C0, + 0x27C0, 0x27E0, 0x27E0, 0x27E0, + 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */ + 0x2820, 0x2840, 0x2840, 0x2840, + 0x2860, 0x2860, 0x2880, 0x2880, + 0x2880, 0x28A0, 0x28A0, 0x28A0, + 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */ + 0x28E0, 0x28E0, 0x2900, 0x2900, + 0x2900, 0x2920, 0x2920, 0x2920, + 0x2940, 0x2940, 0x2940, 0x2960, + 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */ + 0x2980, 0x2980, 0x29A0, 0x29A0, + 0x29A0, 0x29A0, 0x29C0, 0x29C0, + 0x29C0, 0x29E0, 0x29E0, 0x29E0, + 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */ + 0x2A00, 0x2A20, 0x2A20, 0x2A20, + 0x2A20, 0x2A40, 0x2A40, 0x2A40, + 0x2A40, 0x2A60, 0x2A60, 0x2A60, +}; + +const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE] = { + 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */ + 0x05A9, 0x0669, 0x0709, 0x0789, + 0x0829, 0x08A9, 0x0929, 0x0989, + 0x0A09, 0x0A69, 0x0AC9, 0x0B29, + 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */ + 0x0D09, 0x0D69, 0x0DA9, 0x0E09, + 0x0E69, 0x0EA9, 0x0F09, 0x0F49, + 0x0FA9, 0x0FE9, 0x1029, 0x1089, + 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */ + 0x11E9, 0x1229, 0x1289, 0x12C9, + 0x1309, 0x1349, 0x1389, 0x13C9, + 0x1409, 0x1449, 0x14A9, 0x14E9, + 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */ + 0x1629, 0x1669, 0x16A9, 0x16E8, + 0x1728, 0x1768, 0x17A8, 0x17E8, + 0x1828, 0x1868, 0x18A8, 0x18E8, + 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */ + 0x1A28, 0x1A68, 0x1AA8, 0x1AE8, + 0x1B28, 0x1B68, 0x1BA8, 0x1BE8, + 0x1C28, 0x1C68, 0x1CA8, 0x1CE8, + 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */ + 0x1E48, 0x1E88, 0x1EC8, 0x1F08, + 0x1F48, 0x1F88, 0x1FE8, 0x2028, + 0x2068, 0x20A8, 0x2108, 0x2148, + 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */ + 0x22C8, 0x2308, 0x2348, 0x23A8, + 0x23E8, 0x2448, 0x24A8, 0x24E8, + 0x2548, 0x25A8, 0x2608, 0x2668, + 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */ + 0x2847, 0x28C7, 0x2947, 0x29A7, + 0x2A27, 0x2AC7, 0x2B47, 0x2BE7, + 0x2CA7, 0x2D67, 0x2E47, 0x2F67, + 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */ + 0x3806, 0x38A6, 0x3946, 0x39E6, + 0x3A66, 0x3AE6, 0x3B66, 0x3BC6, + 0x3C45, 0x3CA5, 0x3D05, 0x3D85, + 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */ + 0x3F45, 0x3FA5, 0x4005, 0x4045, + 0x40A5, 0x40E5, 0x4145, 0x4185, + 0x41E5, 0x4225, 0x4265, 0x42C5, + 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */ + 0x4424, 0x4464, 0x44C4, 0x4504, + 0x4544, 0x4584, 0x45C4, 0x4604, + 0x4644, 0x46A4, 0x46E4, 0x4724, + 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */ + 0x4864, 0x48A4, 0x48E4, 0x4924, + 0x4964, 0x49A4, 0x49E4, 0x4A24, + 0x4A64, 0x4AA4, 0x4AE4, 0x4B23, + 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */ + 0x4C63, 0x4CA3, 0x4CE3, 0x4D23, + 0x4D63, 0x4DA3, 0x4DE3, 0x4E23, + 0x4E63, 0x4EA3, 0x4EE3, 0x4F23, + 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */ + 0x5083, 0x50C3, 0x5103, 0x5143, + 0x5183, 0x51E2, 0x5222, 0x5262, + 0x52A2, 0x52E2, 0x5342, 0x5382, + 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */ + 0x5502, 0x5542, 0x55A2, 0x55E2, + 0x5642, 0x5682, 0x56E2, 0x5722, + 0x5782, 0x57E1, 0x5841, 0x58A1, + 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */ + 0x5AA1, 0x5B01, 0x5B81, 0x5BE1, + 0x5C61, 0x5D01, 0x5D80, 0x5E20, + 0x5EE0, 0x5FA0, 0x6080, 0x61C0, +}; + +const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE] = { + 0x0001, 0x0001, 0x0001, 0xFFFE, + 0xFFFE, 0x3FFF, 0x1000, 0x0393, +}; + +const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE] = { + 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, + 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, +}; + +const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE] = { + 0x013C, 0x01F5, 0x031A, 0x0631, + 0x0001, 0x0001, 0x0001, 0x0001, +}; + +const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE] = { + 0x5484, 0x3C40, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, +}; + +const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE] = { + 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */ + 0x2F2D, 0x2A2A, 0x2527, 0x1F21, + 0x1A1D, 0x1719, 0x1616, 0x1414, + 0x1414, 0x1400, 0x1414, 0x1614, + 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */ + 0x2A27, 0x2F2A, 0x332D, 0x3B35, + 0x5140, 0x6C62, 0x0077, +}; + +const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE] = { + 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */ + 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1, + 0x969B, 0x9195, 0x8F8F, 0x8A8A, + 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A, + 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */ + 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7, + 0xCBC0, 0xD8D4, 0x00DD, +}; + +const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE] = { + 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */ + 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, + 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, + 0xA4A4, 0xA400, 0xA4A4, 0xA4A4, + 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */ + 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, + 0xA4A4, 0xA4A4, 0x00A4, +}; + +const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE] = { + 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */ + 0x0067, 0x0063, 0x005E, 0x0059, + 0x0054, 0x0050, 0x004B, 0x0046, + 0x0042, 0x003D, 0x003D, 0x003D, + 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */ + 0x003D, 0x003D, 0x003D, 0x003D, + 0x003D, 0x003D, 0x0000, 0x003D, + 0x003D, 0x003D, 0x003D, 0x003D, + 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */ + 0x003D, 0x003D, 0x003D, 0x003D, + 0x0042, 0x0046, 0x004B, 0x0050, + 0x0054, 0x0059, 0x005E, 0x0063, + 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */ + 0x007A, +}; + +const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = { + 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */ + 0x00D6, 0x00D4, 0x00D2, 0x00CF, + 0x00CD, 0x00CA, 0x00C7, 0x00C4, + 0x00C1, 0x00BE, 0x00BE, 0x00BE, + 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */ + 0x00BE, 0x00BE, 0x00BE, 0x00BE, + 0x00BE, 0x00BE, 0x0000, 0x00BE, + 0x00BE, 0x00BE, 0x00BE, 0x00BE, + 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */ + 0x00BE, 0x00BE, 0x00BE, 0x00BE, + 0x00C1, 0x00C4, 0x00C7, 0x00CA, + 0x00CD, 0x00CF, 0x00D2, 0x00D4, + 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */ + 0x00DE, +}; + +/**** Helper functions to access the device Internal Lookup Tables ****/ + +void bcm43xx_ilt_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) +{ + if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val); + } else { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val); + } +} + +u16 bcm43xx_ilt_read16(struct bcm43xx_private *bcm, u16 offset) +{ + if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); + return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); + } else { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); + return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1); + } +} + +void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val) +{ + if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (u16)(val >> 16)); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, (u16)(val & 0x0000FFFF)); + } else { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (u16)(val >> 16)); + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, (u16)(val & 0x0000FFFF)); + } +} + +u32 bcm43xx_ilt_read32(struct bcm43xx_private *bcm, u16 offset) +{ + u32 ret; + + if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); + ret = bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA2); + ret <<= 16; + ret |= bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); + } else { + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); + ret = bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA2); + ret <<= 16; + ret |= bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1); + } + + return ret; +} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h new file mode 100644 index 0000000000..d92527fd83 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h @@ -0,0 +1,34 @@ +#ifndef BCM43xx_ILT_H_ +#define BCM43xx_ILT_H_ + +#define BCM43xx_ILT_ROTOR_SIZE 53 +extern const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE]; +#define BCM43xx_ILT_RETARD_SIZE 53 +extern const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE]; +#define BCM43xx_ILT_FINEFREQA_SIZE 256 +extern const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE]; +#define BCM43xx_ILT_FINEFREQG_SIZE 256 +extern const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE]; +#define BCM43xx_ILT_NOISEA2_SIZE 8 +extern const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE]; +#define BCM43xx_ILT_NOISEA3_SIZE 8 +extern const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE]; +#define BCM43xx_ILT_NOISEG1_SIZE 8 +extern const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE]; +#define BCM43xx_ILT_NOISEG2_SIZE 8 +extern const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE]; +#define BCM43xx_ILT_NOISESCALEG_SIZE 27 +extern const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE]; +extern const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE]; +extern const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE]; +#define BCM43xx_ILT_SIGMASQR_SIZE 53 +extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE]; +extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE]; + + +void bcm43xx_ilt_write16(struct bcm43xx_private *bcm, u16 offset, u16 val); +u16 bcm43xx_ilt_read16(struct bcm43xx_private *bcm, u16 offset); +void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val); +u32 bcm43xx_ilt_read32(struct bcm43xx_private *bcm, u16 offset); + +#endif /* BCM43xx_ILT_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c new file mode 100644 index 0000000000..455a0c743f --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -0,0 +1,261 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx_leds.h" +#include "bcm43xx.h" + +#include + + +static void bcm43xx_led_changestate(struct bcm43xx_led *led) +{ + struct bcm43xx_private *bcm = led->bcm; + const int index = bcm43xx_led_index(led); + u16 ledctl; + + assert(index >= 0 && index < BCM43xx_NR_LEDS); + assert(led->blink_interval); + ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); + __change_bit(index, (unsigned long *)(&ledctl)); + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); +} + +static void bcm43xx_led_blink(unsigned long d) +{ + struct bcm43xx_led *led = (struct bcm43xx_led *)d; + struct bcm43xx_private *bcm = led->bcm; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + if (led->blink_interval) { + bcm43xx_led_changestate(led); + mod_timer(&led->blink_timer, jiffies + led->blink_interval); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +static void bcm43xx_led_blink_start(struct bcm43xx_led *led, + unsigned long interval) +{ + led->blink_interval = interval; + bcm43xx_led_changestate(led); + led->blink_timer.expires = jiffies + interval; + add_timer(&led->blink_timer); +} + +static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync) +{ + struct bcm43xx_private *bcm = led->bcm; + const int index = bcm43xx_led_index(led); + u16 ledctl; + + if (!led->blink_interval) + return; + if (unlikely(sync)) + del_timer_sync(&led->blink_timer); + else + del_timer(&led->blink_timer); + led->blink_interval = 0; + + /* Make sure the LED is turned off. */ + assert(index >= 0 && index < BCM43xx_NR_LEDS); + ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); + if (led->activelow) + ledctl |= (1 << index); + else + ledctl &= ~(1 << index); + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); +} + +int bcm43xx_leds_init(struct bcm43xx_private *bcm) +{ + struct bcm43xx_led *led; + u8 sprom[4]; + int i; + + sprom[0] = bcm->sprom.wl0gpio0; + sprom[1] = bcm->sprom.wl0gpio1; + sprom[2] = bcm->sprom.wl0gpio2; + sprom[3] = bcm->sprom.wl0gpio3; + + for (i = 0; i < BCM43xx_NR_LEDS; i++) { + led = &(bcm->leds[i]); + led->bcm = bcm; + init_timer(&led->blink_timer); + led->blink_timer.data = (unsigned long)led; + led->blink_timer.function = bcm43xx_led_blink; + + if (sprom[i] == 0xFF) { + /* SPROM information not set. */ + switch (i) { + case 0: + if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ) + led->behaviour = BCM43xx_LED_RADIO_ALL; + else + led->behaviour = BCM43xx_LED_ACTIVITY; + break; + case 1: + led->behaviour = BCM43xx_LED_RADIO_B; + break; + case 2: + led->behaviour = BCM43xx_LED_RADIO_A; + break; + case 3: + led->behaviour = BCM43xx_LED_OFF; + break; + default: + assert(0); + } + } else { + led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR; + led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW); + } + } + + return 0; +} + +void bcm43xx_leds_exit(struct bcm43xx_private *bcm) +{ + struct bcm43xx_led *led; + int i; + + for (i = 0; i < BCM43xx_NR_LEDS; i++) { + led = &(bcm->leds[i]); + bcm43xx_led_blink_stop(led, 1); + } + bcm43xx_leds_turn_off(bcm); +} + +void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) +{ + struct bcm43xx_led *led; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES; + int i, turn_on = 0; + unsigned long interval = 0; + u16 ledctl; + + ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); + for (i = 0; i < BCM43xx_NR_LEDS; i++) { + led = &(bcm->leds[i]); + if (led->behaviour == BCM43xx_LED_INACTIVE) + continue; + + switch (led->behaviour) { + case BCM43xx_LED_OFF: + turn_on = 0; + break; + case BCM43xx_LED_ON: + turn_on = 1; + break; + case BCM43xx_LED_ACTIVITY: + turn_on = activity; + break; + case BCM43xx_LED_RADIO_ALL: + turn_on = radio->enabled; + break; + case BCM43xx_LED_RADIO_A: + turn_on = (radio->enabled && phy->type == BCM43xx_PHYTYPE_A); + break; + case BCM43xx_LED_RADIO_B: + turn_on = (radio->enabled && + (phy->type == BCM43xx_PHYTYPE_B || + phy->type == BCM43xx_PHYTYPE_G)); + break; + case BCM43xx_LED_MODE_BG: + turn_on = 0; + if (phy->type == BCM43xx_PHYTYPE_G && + 1/*FIXME: using G rates.*/) + turn_on = 1; + break; + case BCM43xx_LED_TRANSFER: + if (transferring) + bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM); + else + bcm43xx_led_blink_stop(led, 0); + continue; + case BCM43xx_LED_APTRANSFER: + if (bcm->ieee->iw_mode == IW_MODE_MASTER) { + if (transferring) { + interval = BCM43xx_LEDBLINK_FAST; + turn_on = 1; + } + } else { + turn_on = 1; + if (0/*TODO: not assoc*/) + interval = BCM43xx_LEDBLINK_SLOW; + else if (transferring) + interval = BCM43xx_LEDBLINK_FAST; + else + turn_on = 0; + } + if (turn_on) + bcm43xx_led_blink_start(led, interval); + else + bcm43xx_led_blink_stop(led, 0); + continue; + case BCM43xx_LED_WEIRD: + //TODO + turn_on = 0; + break; + case BCM43xx_LED_ASSOC: + if (1/*TODO: associated*/) + turn_on = 1; + break; + default: + assert(0); + }; + + if (led->activelow) + turn_on = !turn_on; + if (turn_on) + ledctl |= (1 << i); + else + ledctl &= ~(1 << i); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); +} + +void bcm43xx_leds_turn_off(struct bcm43xx_private *bcm) +{ + struct bcm43xx_led *led; + u16 ledctl = 0; + int i; + + for (i = 0; i < BCM43xx_NR_LEDS; i++) { + led = &(bcm->leds[i]); + if (led->behaviour == BCM43xx_LED_INACTIVE) + continue; + if (led->activelow) + ledctl |= (1 << i); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h new file mode 100644 index 0000000000..489a2b1e90 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h @@ -0,0 +1,47 @@ +#ifndef BCM43xx_LEDS_H_ +#define BCM43xx_LEDS_H_ + +#include +#include + + +struct bcm43xx_led { + u8 behaviour:7; + u8 activelow:1; + + struct bcm43xx_private *bcm; + struct timer_list blink_timer; + unsigned long blink_interval; +}; +#define bcm43xx_led_index(led) ((int)((led) - (led)->bcm->leds)) + +/* Delay between state changes when blinking in jiffies */ +#define BCM43xx_LEDBLINK_SLOW (HZ / 2) +#define BCM43xx_LEDBLINK_MEDIUM (HZ / 4) +#define BCM43xx_LEDBLINK_FAST (HZ / 8) + +#define BCM43xx_LED_XFER_THRES (HZ / 100) + +#define BCM43xx_LED_BEHAVIOUR 0x7F +#define BCM43xx_LED_ACTIVELOW 0x80 +enum { /* LED behaviour values */ + BCM43xx_LED_OFF, + BCM43xx_LED_ON, + BCM43xx_LED_ACTIVITY, + BCM43xx_LED_RADIO_ALL, + BCM43xx_LED_RADIO_A, + BCM43xx_LED_RADIO_B, + BCM43xx_LED_MODE_BG, + BCM43xx_LED_TRANSFER, + BCM43xx_LED_APTRANSFER, + BCM43xx_LED_WEIRD,//FIXME + BCM43xx_LED_ASSOC, + BCM43xx_LED_INACTIVE, +}; + +int bcm43xx_leds_init(struct bcm43xx_private *bcm); +void bcm43xx_leds_exit(struct bcm43xx_private *bcm); +void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity); +void bcm43xx_leds_turn_off(struct bcm43xx_private *bcm); + +#endif /* BCM43xx_LEDS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c new file mode 100644 index 0000000000..be60a6509f --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -0,0 +1,4597 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bcm43xx.h" +#include "bcm43xx_main.h" +#include "bcm43xx_debugfs.h" +#include "bcm43xx_radio.h" +#include "bcm43xx_phy.h" +#include "bcm43xx_dma.h" +#include "bcm43xx_pio.h" +#include "bcm43xx_power.h" +#include "bcm43xx_wx.h" + + +MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); +MODULE_AUTHOR("Martin Langer"); +MODULE_AUTHOR("Stefano Brivio"); +MODULE_AUTHOR("Michael Buesch"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_BCM947XX +extern char *nvram_get(char *name); +#endif + +/* Module parameters */ +static int modparam_pio; +module_param_named(pio, modparam_pio, int, 0444); +MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); + +static int modparam_bad_frames_preempt; +module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); +MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption"); + +static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT; +module_param_named(short_retry, modparam_short_retry, int, 0444); +MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)"); + +static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT; +module_param_named(long_retry, modparam_long_retry, int, 0444); +MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)"); + +static int modparam_locale = -1; +module_param_named(locale, modparam_locale, int, 0444); +MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)"); + +static int modparam_outdoor; +module_param_named(outdoor, modparam_outdoor, int, 0444); +MODULE_PARM_DESC(outdoor, "Set to 1, if you are using the device outdoor, 0 otherwise."); + +static int modparam_noleds; +module_param_named(noleds, modparam_noleds, int, 0444); +MODULE_PARM_DESC(noleds, "Turn off all LED activity"); + +#ifdef CONFIG_BCM43XX_DEBUG +static char modparam_fwpostfix[64]; +module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444); +MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging."); +#else +# define modparam_fwpostfix "" +#endif /* CONFIG_BCM43XX_DEBUG*/ + + +/* If you want to debug with just a single device, enable this, + * where the string is the pci device ID (as given by the kernel's + * pci_name function) of the device to be used. + */ +//#define DEBUG_SINGLE_DEVICE_ONLY "0001:11:00.0" + +/* If you want to enable printing of each MMIO access, enable this. */ +//#define DEBUG_ENABLE_MMIO_PRINT + +/* If you want to enable printing of MMIO access within + * ucode/pcm upload, initvals write, enable this. + */ +//#define DEBUG_ENABLE_UCODE_MMIO_PRINT + +/* If you want to enable printing of PCI Config Space access, enable this */ +//#define DEBUG_ENABLE_PCILOG + + +static struct pci_device_id bcm43xx_pci_tbl[] = { + + /* Detailed list maintained at: + * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices + */ + +#ifdef CONFIG_BCM947XX + /* SB bus on BCM947xx */ + { PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif + + /* Broadcom 4303 802.11b */ + { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 4307 802.11b */ + { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 4318 802.11b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 4306 802.11b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 4306 802.11a */ +// { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 4309 802.11a/b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* Broadcom 43XG 802.11b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + + /* required last entry */ + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl); + +static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val) +{ + u32 status; + + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP)) + val = swab32(val); + + bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset); + bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val); +} + +static inline +void bcm43xx_shm_control_word(struct bcm43xx_private *bcm, + u16 routing, u16 offset) +{ + u32 control; + + /* "offset" is the WORD offset. */ + + control = routing; + control <<= 16; + control |= offset; + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control); +} + +u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm, + u16 routing, u16 offset) +{ + u32 ret; + + if (routing == BCM43xx_SHM_SHARED) { + if (offset & 0x0003) { + /* Unaligned access */ + bcm43xx_shm_control_word(bcm, routing, offset >> 2); + ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED); + ret <<= 16; + bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1); + ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA); + + return ret; + } + offset >>= 2; + } + bcm43xx_shm_control_word(bcm, routing, offset); + ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA); + + return ret; +} + +u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm, + u16 routing, u16 offset) +{ + u16 ret; + + if (routing == BCM43xx_SHM_SHARED) { + if (offset & 0x0003) { + /* Unaligned access */ + bcm43xx_shm_control_word(bcm, routing, offset >> 2); + ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED); + + return ret; + } + offset >>= 2; + } + bcm43xx_shm_control_word(bcm, routing, offset); + ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA); + + return ret; +} + +void bcm43xx_shm_write32(struct bcm43xx_private *bcm, + u16 routing, u16 offset, + u32 value) +{ + if (routing == BCM43xx_SHM_SHARED) { + if (offset & 0x0003) { + /* Unaligned access */ + bcm43xx_shm_control_word(bcm, routing, offset >> 2); + bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, + (value >> 16) & 0xffff); + bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1); + bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, + value & 0xffff); + return; + } + offset >>= 2; + } + bcm43xx_shm_control_word(bcm, routing, offset); + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value); +} + +void bcm43xx_shm_write16(struct bcm43xx_private *bcm, + u16 routing, u16 offset, + u16 value) +{ + if (routing == BCM43xx_SHM_SHARED) { + if (offset & 0x0003) { + /* Unaligned access */ + bcm43xx_shm_control_word(bcm, routing, offset >> 2); + bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, + value); + return; + } + offset >>= 2; + } + bcm43xx_shm_control_word(bcm, routing, offset); + bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value); +} + +void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf) +{ + /* We need to be careful. As we read the TSF from multiple + * registers, we should take care of register overflows. + * In theory, the whole tsf read process should be atomic. + * We try to be atomic here, by restaring the read process, + * if any of the high registers changed (overflew). + */ + if (bcm->current_core->rev >= 3) { + u32 low, high, high2; + + do { + high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH); + low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW); + high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH); + } while (unlikely(high != high2)); + + *tsf = high; + *tsf <<= 32; + *tsf |= low; + } else { + u64 tmp; + u16 v0, v1, v2, v3; + u16 test1, test2, test3; + + do { + v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3); + v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2); + v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1); + v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0); + + test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3); + test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2); + test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1); + } while (v3 != test3 || v2 != test2 || v1 != test1); + + *tsf = v3; + *tsf <<= 48; + tmp = v2; + tmp <<= 32; + *tsf |= tmp; + tmp = v1; + tmp <<= 16; + *tsf |= tmp; + *tsf |= v0; + } +} + +void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) +{ + u32 status; + + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + status |= BCM43xx_SBF_TIME_UPDATE; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + + /* Be careful with the in-progress timer. + * First zero out the low register, so we have a full + * register-overflow duration to complete the operation. + */ + if (bcm->current_core->rev >= 3) { + u32 lo = (tsf & 0x00000000FFFFFFFFULL); + u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32; + + barrier(); + bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0); + bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi); + bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo); + } else { + u16 v0 = (tsf & 0x000000000000FFFFULL); + u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16; + u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32; + u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48; + + barrier(); + bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0); + bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3); + bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2); + bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1); + bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0); + } + + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + status &= ~BCM43xx_SBF_TIME_UPDATE; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); +} + +static inline +u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp, + const int ofdm_modulation) +{ + u8 rate; + + if (ofdm_modulation) { + switch (plcp->raw[0] & 0xF) { + case 0xB: + rate = IEEE80211_OFDM_RATE_6MB; + break; + case 0xF: + rate = IEEE80211_OFDM_RATE_9MB; + break; + case 0xA: + rate = IEEE80211_OFDM_RATE_12MB; + break; + case 0xE: + rate = IEEE80211_OFDM_RATE_18MB; + break; + case 0x9: + rate = IEEE80211_OFDM_RATE_24MB; + break; + case 0xD: + rate = IEEE80211_OFDM_RATE_36MB; + break; + case 0x8: + rate = IEEE80211_OFDM_RATE_48MB; + break; + case 0xC: + rate = IEEE80211_OFDM_RATE_54MB; + break; + default: + rate = 0; + assert(0); + } + } else { + switch (plcp->raw[0]) { + case 0x0A: + rate = IEEE80211_CCK_RATE_1MB; + break; + case 0x14: + rate = IEEE80211_CCK_RATE_2MB; + break; + case 0x37: + rate = IEEE80211_CCK_RATE_5MB; + break; + case 0x6E: + rate = IEEE80211_CCK_RATE_11MB; + break; + default: + rate = 0; + assert(0); + } + } + + return rate; +} + +static inline +u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) +{ + switch (bitrate) { + case IEEE80211_CCK_RATE_1MB: + return 0x0A; + case IEEE80211_CCK_RATE_2MB: + return 0x14; + case IEEE80211_CCK_RATE_5MB: + return 0x37; + case IEEE80211_CCK_RATE_11MB: + return 0x6E; + } + assert(0); + return 0; +} + +static inline +u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) +{ + switch (bitrate) { + case IEEE80211_OFDM_RATE_6MB: + return 0xB; + case IEEE80211_OFDM_RATE_9MB: + return 0xF; + case IEEE80211_OFDM_RATE_12MB: + return 0xA; + case IEEE80211_OFDM_RATE_18MB: + return 0xE; + case IEEE80211_OFDM_RATE_24MB: + return 0x9; + case IEEE80211_OFDM_RATE_36MB: + return 0xD; + case IEEE80211_OFDM_RATE_48MB: + return 0x8; + case IEEE80211_OFDM_RATE_54MB: + return 0xC; + } + assert(0); + return 0; +} + +static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, + u16 octets, const u8 bitrate, + const int ofdm_modulation) +{ + __le32 *data = &(plcp->data); + __u8 *raw = plcp->raw; + + /* Account for hardware-appended FCS. */ + octets += IEEE80211_FCS_LEN; + + if (ofdm_modulation) { + *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate); + assert(!(octets & 0xF000)); + *data |= (octets << 5); + *data = cpu_to_le32(*data); + } else { + u32 plen; + + plen = octets * 16 / bitrate; + if ((octets * 16 % bitrate) > 0) { + plen++; + if ((bitrate == IEEE80211_CCK_RATE_11MB) + && ((octets * 8 % 11) < 4)) { + raw[1] = 0x84; + } else + raw[1] = 0x04; + } else + raw[1] = 0x04; + *data |= cpu_to_le32(plen << 16); + raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate); + } + +//bcm43xx_printk_bitdump(raw, 4, 0, "PLCP"); +} + +void fastcall +bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie) +{ + const struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + const struct ieee80211_hdr_1addr *wireless_header = (const struct ieee80211_hdr_1addr *)fragment_data; + const struct ieee80211_security *secinfo = &bcm->ieee->sec; + u8 bitrate; + int ofdm_modulation; + u8 fallback_bitrate; + int fallback_ofdm_modulation; + u16 tmp; + u16 encrypt_frame; + + /* Now construct the TX header. */ + memset(txhdr, 0, sizeof(*txhdr)); + + //TODO: Some RTS/CTS stuff has to be done. + //TODO: Encryption stuff. + //TODO: others? + + bitrate = bcm->softmac->txrates.default_rate; + ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); + fallback_bitrate = bcm->softmac->txrates.default_fallback; + fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); + + /* Set Frame Control from 80211 header. */ + txhdr->frame_control = wireless_header->frame_ctl; + /* Copy address1 from 80211 header. */ + memcpy(txhdr->mac1, wireless_header->addr1, 6); + /* Set the fallback duration ID. */ + //FIXME: We use the original durid for now. + txhdr->fallback_dur_id = wireless_header->duration_id; + + /* Set the cookie (used as driver internal ID for the frame) */ + txhdr->cookie = cpu_to_le16(cookie); + + encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED; + if (encrypt_frame && !bcm->ieee->host_encrypt) { + const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header; + if (fragment_len <= sizeof(struct ieee80211_hdr_3addr)+4) { + dprintkl(KERN_ERR PFX "invalid packet with PROTECTED" + "flag set discarded"); + return; + } + memcpy(txhdr->wep_iv, hdr->payload, 4); + /* Hardware appends ICV. */ + fragment_len += 4; + } + + /* Generate the PLCP header and the fallback PLCP header. */ + bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp), + fragment_len, + bitrate, ofdm_modulation); + bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, fragment_len, + fallback_bitrate, fallback_ofdm_modulation); + + /* Set the CONTROL field */ + tmp = 0; + if (ofdm_modulation) + tmp |= BCM43xx_TXHDRCTL_OFDM; + if (bcm->short_preamble) //FIXME: could be the other way around, please test + tmp |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE; + tmp |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT) + & BCM43xx_TXHDRCTL_ANTENNADIV_MASK; + txhdr->control = cpu_to_le16(tmp); + + /* Set the FLAGS field */ + tmp = 0; + if (!is_multicast_ether_addr(wireless_header->addr1) && + !is_broadcast_ether_addr(wireless_header->addr1)) + tmp |= BCM43xx_TXHDRFLAG_EXPECTACK; + if (1 /* FIXME: PS poll?? */) + tmp |= 0x10; // FIXME: unknown meaning. + if (fallback_ofdm_modulation) + tmp |= BCM43xx_TXHDRFLAG_FALLBACKOFDM; + if (is_first_fragment) + tmp |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT; + txhdr->flags = cpu_to_le16(tmp); + + /* Set WSEC/RATE field */ + if (encrypt_frame && !bcm->ieee->host_encrypt) { + tmp = (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT) + & BCM43xx_TXHDR_WSEC_ALGO_MASK; + tmp |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT) + & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK; + txhdr->wsec_rate = cpu_to_le16(tmp); + } + +//bcm43xx_printk_bitdump((const unsigned char *)txhdr, sizeof(*txhdr), 1, "TX header"); +} + +static +void bcm43xx_macfilter_set(struct bcm43xx_private *bcm, + u16 offset, + const u8 *mac) +{ + u16 data; + + offset |= 0x0020; + bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset); + + data = mac[0]; + data |= mac[1] << 8; + bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); + data = mac[2]; + data |= mac[3] << 8; + bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); + data = mac[4]; + data |= mac[5] << 8; + bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); +} + +static inline +void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm, + u16 offset) +{ + const u8 zero_addr[ETH_ALEN] = { 0 }; + + bcm43xx_macfilter_set(bcm, offset, zero_addr); +} + +static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm) +{ + const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr); + const u8 *bssid = (const u8 *)(bcm->ieee->bssid); + u8 mac_bssid[ETH_ALEN * 2]; + int i; + + memcpy(mac_bssid, mac, ETH_ALEN); + memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN); + + /* Write our MAC address and BSSID to template ram */ + for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) + bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i))); + for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) + bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i))); + for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) + bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i))); +} + +static inline +void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) +{ + /* slot_time is in usec. */ + if (bcm->current_core->phy->type != BCM43xx_PHYTYPE_G) + return; + bcm43xx_write16(bcm, 0x684, 510 + slot_time); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time); +} + +static inline +void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm) +{ + bcm43xx_set_slot_time(bcm, 9); +} + +static inline +void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm) +{ + bcm43xx_set_slot_time(bcm, 20); +} + +//FIXME: rename this func? +static void bcm43xx_disassociate(struct bcm43xx_private *bcm) +{ + bcm43xx_mac_suspend(bcm); + bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); + + bcm43xx_ram_write(bcm, 0x0026, 0x0000); + bcm43xx_ram_write(bcm, 0x0028, 0x0000); + bcm43xx_ram_write(bcm, 0x007E, 0x0000); + bcm43xx_ram_write(bcm, 0x0080, 0x0000); + bcm43xx_ram_write(bcm, 0x047E, 0x0000); + bcm43xx_ram_write(bcm, 0x0480, 0x0000); + + if (bcm->current_core->rev < 3) { + bcm43xx_write16(bcm, 0x0610, 0x8000); + bcm43xx_write16(bcm, 0x060E, 0x0000); + } else + bcm43xx_write32(bcm, 0x0188, 0x80000000); + + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff); + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && + ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate)) + bcm43xx_short_slot_timing_enable(bcm); + + bcm43xx_mac_enable(bcm); +} + +//FIXME: rename this func? +static void bcm43xx_associate(struct bcm43xx_private *bcm, + const u8 *mac) +{ + memcpy(bcm->ieee->bssid, mac, ETH_ALEN); + + bcm43xx_mac_suspend(bcm); + bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac); + bcm43xx_write_mac_bssid_templates(bcm); + bcm43xx_mac_enable(bcm); +} + +/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. + * Returns the _previously_ enabled IRQ mask. + */ +static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask) +{ + u32 old_mask; + + old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask); + + return old_mask; +} + +/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable. + * Returns the _previously_ enabled IRQ mask. + */ +static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask) +{ + u32 old_mask; + + old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask); + + return old_mask; +} + +/* Make sure we don't receive more data from the device. */ +static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate) +{ + u32 old; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) { + spin_unlock_irqrestore(&bcm->lock, flags); + return -EBUSY; + } + old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + tasklet_disable(&bcm->isr_tasklet); + spin_unlock_irqrestore(&bcm->lock, flags); + if (oldstate) + *oldstate = old; + + return 0; +} + +static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) +{ + u32 radio_id; + u16 manufact; + u16 version; + u8 revision; + s8 i; + + if (bcm->chip_id == 0x4317) { + if (bcm->chip_rev == 0x00) + radio_id = 0x3205017F; + else if (bcm->chip_rev == 0x01) + radio_id = 0x4205017F; + else + radio_id = 0x5205017F; + } else { + bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID); + radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH); + radio_id <<= 16; + bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID); + radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW); + } + + manufact = (radio_id & 0x00000FFF); + version = (radio_id & 0x0FFFF000) >> 12; + revision = (radio_id & 0xF0000000) >> 28; + + dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n", + radio_id, manufact, version, revision); + + switch (bcm->current_core->phy->type) { + case BCM43xx_PHYTYPE_A: + if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f)) + goto err_unsupported_radio; + break; + case BCM43xx_PHYTYPE_B: + if ((version & 0xFFF0) != 0x2050) + goto err_unsupported_radio; + break; + case BCM43xx_PHYTYPE_G: + if (version != 0x2050) + goto err_unsupported_radio; + break; + } + + bcm->current_core->radio->manufact = manufact; + bcm->current_core->radio->version = version; + bcm->current_core->radio->revision = revision; + + /* Set default attenuation values. */ + bcm->current_core->radio->txpower[0] = 2; + bcm->current_core->radio->txpower[1] = 2; + if (revision == 1) + bcm->current_core->radio->txpower[2] = 3; + else + bcm->current_core->radio->txpower[2] = 0; + + /* Initialize the in-memory nrssi Lookup Table. */ + for (i = 0; i < 64; i++) + bcm->current_core->radio->nrssi_lt[i] = i; + + return 0; + +err_unsupported_radio: + printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n"); + return -ENODEV; +} + +static const char * bcm43xx_locale_iso(u8 locale) +{ + /* ISO 3166-1 country codes. + * Note that there aren't ISO 3166-1 codes for + * all or locales. (Not all locales are countries) + */ + switch (locale) { + case BCM43xx_LOCALE_WORLD: + case BCM43xx_LOCALE_ALL: + return "XX"; + case BCM43xx_LOCALE_THAILAND: + return "TH"; + case BCM43xx_LOCALE_ISRAEL: + return "IL"; + case BCM43xx_LOCALE_JORDAN: + return "JO"; + case BCM43xx_LOCALE_CHINA: + return "CN"; + case BCM43xx_LOCALE_JAPAN: + case BCM43xx_LOCALE_JAPAN_HIGH: + return "JP"; + case BCM43xx_LOCALE_USA_CANADA_ANZ: + case BCM43xx_LOCALE_USA_LOW: + return "US"; + case BCM43xx_LOCALE_EUROPE: + return "EU"; + case BCM43xx_LOCALE_NONE: + return " "; + } + assert(0); + return " "; +} + +static const char * bcm43xx_locale_string(u8 locale) +{ + switch (locale) { + case BCM43xx_LOCALE_WORLD: + return "World"; + case BCM43xx_LOCALE_THAILAND: + return "Thailand"; + case BCM43xx_LOCALE_ISRAEL: + return "Israel"; + case BCM43xx_LOCALE_JORDAN: + return "Jordan"; + case BCM43xx_LOCALE_CHINA: + return "China"; + case BCM43xx_LOCALE_JAPAN: + return "Japan"; + case BCM43xx_LOCALE_USA_CANADA_ANZ: + return "USA/Canada/ANZ"; + case BCM43xx_LOCALE_EUROPE: + return "Europe"; + case BCM43xx_LOCALE_USA_LOW: + return "USAlow"; + case BCM43xx_LOCALE_JAPAN_HIGH: + return "JapanHigh"; + case BCM43xx_LOCALE_ALL: + return "All"; + case BCM43xx_LOCALE_NONE: + return "None"; + } + assert(0); + return ""; +} + +static inline u8 bcm43xx_crc8(u8 crc, u8 data) +{ + static const u8 t[] = { + 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, + 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, + 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, + 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, + 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, + 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, + 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, + 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, + 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, + 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, + 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, + 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, + 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, + 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, + 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, + 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, + 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, + 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, + 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, + 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, + 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, + 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, + 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, + 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, + 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, + 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, + 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, + 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, + 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, + 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, + 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, + 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, + }; + return t[crc ^ data]; +} + +u8 bcm43xx_sprom_crc(const u16 *sprom) +{ + int word; + u8 crc = 0xFF; + + for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) { + crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF); + crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8); + } + crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF); + crc ^= 0xFF; + + return crc; +} + + +static int bcm43xx_read_sprom(struct bcm43xx_private *bcm) +{ + int i; + u16 value; + u16 *sprom; + u8 crc, expected_crc; +#ifdef CONFIG_BCM947XX + char *c; +#endif + + sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16), + GFP_KERNEL); + if (!sprom) { + printk(KERN_ERR PFX "read_sprom OOM\n"); + return -ENOMEM; + } +#ifdef CONFIG_BCM947XX + sprom[BCM43xx_SPROM_BOARDFLAGS2] = atoi(nvram_get("boardflags2")); + sprom[BCM43xx_SPROM_BOARDFLAGS] = atoi(nvram_get("boardflags")); + + if ((c = nvram_get("il0macaddr")) != NULL) + e_aton(c, (char *) &(sprom[BCM43xx_SPROM_IL0MACADDR])); + + if ((c = nvram_get("et1macaddr")) != NULL) + e_aton(c, (char *) &(sprom[BCM43xx_SPROM_ET1MACADDR])); + + sprom[BCM43xx_SPROM_PA0B0] = atoi(nvram_get("pa0b0")); + sprom[BCM43xx_SPROM_PA0B1] = atoi(nvram_get("pa0b1")); + sprom[BCM43xx_SPROM_PA0B2] = atoi(nvram_get("pa0b2")); + + sprom[BCM43xx_SPROM_PA1B0] = atoi(nvram_get("pa1b0")); + sprom[BCM43xx_SPROM_PA1B1] = atoi(nvram_get("pa1b1")); + sprom[BCM43xx_SPROM_PA1B2] = atoi(nvram_get("pa1b2")); + + sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev")); +#else + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) + sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); + + /* CRC-8 check. */ + crc = bcm43xx_sprom_crc(sprom); + expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; + if (crc != expected_crc) { + printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum " + "(0x%02X, expected: 0x%02X)\n", + crc, expected_crc); + } +#endif + + /* boardflags2 */ + value = sprom[BCM43xx_SPROM_BOARDFLAGS2]; + bcm->sprom.boardflags2 = value; + + /* il0macaddr */ + value = sprom[BCM43xx_SPROM_IL0MACADDR + 0]; + *(((u16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_IL0MACADDR + 1]; + *(((u16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_IL0MACADDR + 2]; + *(((u16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value); + + /* et0macaddr */ + value = sprom[BCM43xx_SPROM_ET0MACADDR + 0]; + *(((u16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_ET0MACADDR + 1]; + *(((u16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_ET0MACADDR + 2]; + *(((u16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value); + + /* et1macaddr */ + value = sprom[BCM43xx_SPROM_ET1MACADDR + 0]; + *(((u16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_ET1MACADDR + 1]; + *(((u16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value); + value = sprom[BCM43xx_SPROM_ET1MACADDR + 2]; + *(((u16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value); + + /* ethernet phy settings */ + value = sprom[BCM43xx_SPROM_ETHPHY]; + bcm->sprom.et0phyaddr = (value & 0x001F); + bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5; + bcm->sprom.et0mdcport = (value & (1 << 14)) >> 14; + bcm->sprom.et1mdcport = (value & (1 << 15)) >> 15; + + /* boardrev, antennas, locale */ + value = sprom[BCM43xx_SPROM_BOARDREV]; + bcm->sprom.boardrev = (value & 0x00FF); + bcm->sprom.locale = (value & 0x0F00) >> 8; + bcm->sprom.antennas_aphy = (value & 0x3000) >> 12; + bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14; + if (modparam_locale != -1) { + if (modparam_locale >= 0 && modparam_locale <= 11) { + bcm->sprom.locale = modparam_locale; + printk(KERN_WARNING PFX "Operating with modified " + "LocaleCode %u (%s)\n", + bcm->sprom.locale, + bcm43xx_locale_string(bcm->sprom.locale)); + } else { + printk(KERN_WARNING PFX "Module parameter \"locale\" " + "invalid value. (0 - 11)\n"); + } + } + + /* pa0b* */ + value = sprom[BCM43xx_SPROM_PA0B0]; + bcm->sprom.pa0b0 = value; + value = sprom[BCM43xx_SPROM_PA0B1]; + bcm->sprom.pa0b1 = value; + value = sprom[BCM43xx_SPROM_PA0B2]; + bcm->sprom.pa0b2 = value; + + /* wl0gpio* */ + value = sprom[BCM43xx_SPROM_WL0GPIO0]; + if (value == 0x0000) + value = 0xFFFF; + bcm->sprom.wl0gpio0 = value & 0x00FF; + bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8; + value = sprom[BCM43xx_SPROM_WL0GPIO2]; + if (value == 0x0000) + value = 0xFFFF; + bcm->sprom.wl0gpio2 = value & 0x00FF; + bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8; + + /* maxpower */ + value = sprom[BCM43xx_SPROM_MAXPWR]; + bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8; + bcm->sprom.maxpower_bgphy = value & 0x00FF; + + /* pa1b* */ + value = sprom[BCM43xx_SPROM_PA1B0]; + bcm->sprom.pa1b0 = value; + value = sprom[BCM43xx_SPROM_PA1B1]; + bcm->sprom.pa1b1 = value; + value = sprom[BCM43xx_SPROM_PA1B2]; + bcm->sprom.pa1b2 = value; + + /* idle tssi target */ + value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT]; + bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF; + bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8; + + /* boardflags */ + value = sprom[BCM43xx_SPROM_BOARDFLAGS]; + if (value == 0xFFFF) + value = 0x0000; + bcm->sprom.boardflags = value; + + /* antenna gain */ + value = sprom[BCM43xx_SPROM_ANTENNA_GAIN]; + if (value == 0x0000 || value == 0xFFFF) + value = 0x0202; + /* convert values to Q5.2 */ + bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4; + bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4; + + kfree(sprom); + + return 0; +} + +static int bcm43xx_channel_is_allowed(struct bcm43xx_private *bcm, u8 channel, + u8 *max_power, u8 *flags) +{ + /* THIS FUNCTION DOES _NOT_ ENFORCE REGULATORY DOMAIN COMPLIANCE. + * It is only a helper function to make life easier to + * select legal channels and transmission powers. + */ + + u8 phytype = bcm->current_core->phy->type; + int allowed = 0; + + *max_power = 0; + *flags = 0; + + //FIXME: Set max_power and maybe flags + /*FIXME: Allowed channels are sometimes different for outdoor + * or indoor use. See modparam_outdoor. + */ + /* From b specs Max Power BPHY: + * USA: 1000mW + * Europe: 100mW + * Japan: 10mW/MHz + */ + + switch (bcm->sprom.locale) { + case BCM43xx_LOCALE_WORLD: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 13) + allowed = 1; + } else { + if (channel >= 1 && channel <= 13) + allowed = 1; + } + break; + case BCM43xx_LOCALE_THAILAND: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 14) + allowed = 1; + } else { + if (channel >= 1 && channel <= 14) + allowed = 1; + } + break; + case BCM43xx_LOCALE_ISRAEL: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 5 && channel <= 7) + allowed = 1; + } else { + if (channel >= 5 && channel <= 7) + allowed = 1; + } + break; + case BCM43xx_LOCALE_JORDAN: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 10 && channel <= 13) + allowed = 1; + } else { + if (channel >= 10 && channel <= 13) + allowed = 1; + } + break; + case BCM43xx_LOCALE_CHINA: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 13) + allowed = 1; + } else { + if (channel >= 1 && channel <= 13) + allowed = 1; + } + break; + case BCM43xx_LOCALE_JAPAN: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + //FIXME: This seems to be wrong. + if (channel >= 1 && channel <= 14) + allowed = 1; + } else { + //FIXME: This seems to be wrong. + if (channel >= 1 && channel <= 14) + allowed = 1; + } + break; + case BCM43xx_LOCALE_USA_CANADA_ANZ: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 13) + allowed = 1; + } else { + if (channel >= 1 && channel <= 11) + allowed = 1; + } + break; + case BCM43xx_LOCALE_EUROPE: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 13) + allowed = 1; + } else { + if (channel >= 1 && channel <= 13) + allowed = 1; + } + break; + case BCM43xx_LOCALE_USA_LOW: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + if (channel >= 1 && channel <= 13) + allowed = 1; + } else { + if (channel >= 1 && channel <= 11) + allowed = 1; + } + break; + case BCM43xx_LOCALE_JAPAN_HIGH: + if (phytype == BCM43xx_PHYTYPE_A) { + allowed = 1;//FIXME + } else if (phytype == BCM43xx_PHYTYPE_B) { + //FIXME? + if (channel >= 1 && channel <= 14) + allowed = 1; + } else { + if (channel >= 1 && channel <= 14) + allowed = 1; + } + break; + case BCM43xx_LOCALE_ALL: + allowed = 1; + break; + case BCM43xx_LOCALE_NONE: + break; + default: + assert(0); + } + + return allowed; +} + +static void bcm43xx_geo_init(struct bcm43xx_private *bcm) +{ + struct ieee80211_geo geo; + struct ieee80211_channel *chan; + int have_a = 0, have_bg = 0; + int i, num80211; + u8 channel, flags, max_power; + struct bcm43xx_phyinfo *phy; + const char *iso_country; + + memset(&geo, 0, sizeof(geo)); + num80211 = bcm43xx_num_80211_cores(bcm); + for (i = 0; i < num80211; i++) { + phy = bcm->phy + i; + switch (phy->type) { + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + have_bg = 1; + break; + case BCM43xx_PHYTYPE_A: + have_a = 1; + break; + default: + assert(0); + } + } + iso_country = bcm43xx_locale_iso(bcm->sprom.locale); + + if (have_a) { + for (i = 0, channel = 0; channel < 201; channel++) { + if (!bcm43xx_channel_is_allowed(bcm, channel, + &max_power, &flags)) + continue; + chan = &geo.a[i++]; + chan->freq = bcm43xx_channel_to_freq(bcm, channel); + chan->channel = channel; + chan->flags = flags; + chan->max_power = max_power; + } + geo.a_channels = i; + } + if (have_bg) { + for (i = 0, channel = 1; channel < 15; channel++) { + if (!bcm43xx_channel_is_allowed(bcm, channel, + &max_power, &flags)) + continue; + chan = &geo.bg[i++]; + chan->freq = bcm43xx_channel_to_freq(bcm, channel); + chan->channel = channel; + chan->flags = flags; + chan->max_power = max_power; + } + geo.bg_channels = i; + } + memcpy(geo.name, iso_country, 2); + if (0 /*TODO: Outdoor use only */) + geo.name[2] = 'O'; + else if (0 /*TODO: Indoor use only */) + geo.name[2] = 'I'; + else + geo.name[2] = ' '; + geo.name[3] = '\0'; + + ieee80211_set_geo(bcm->ieee, &geo); +} + +/* DummyTransmission function, as documented on + * http://bcm-specs.sipsolutions.net/DummyTransmission + */ +void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) +{ + unsigned int i, max_loop; + u16 value = 0; + u32 buffer[5] = { + 0x00000000, + 0x0000D400, + 0x00000000, + 0x00000001, + 0x00000000, + }; + + switch (bcm->current_core->phy->type) { + case BCM43xx_PHYTYPE_A: + max_loop = 0x1E; + buffer[0] = 0xCC010200; + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + max_loop = 0xFA; + buffer[0] = 0x6E840B00; + break; + default: + assert(0); + return; + } + + for (i = 0; i < 5; i++) + bcm43xx_ram_write(bcm, i * 4, buffer[i]); + + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ + + bcm43xx_write16(bcm, 0x0568, 0x0000); + bcm43xx_write16(bcm, 0x07C0, 0x0000); + bcm43xx_write16(bcm, 0x050C, ((bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0)); + bcm43xx_write16(bcm, 0x0508, 0x0000); + bcm43xx_write16(bcm, 0x050A, 0x0000); + bcm43xx_write16(bcm, 0x054C, 0x0000); + bcm43xx_write16(bcm, 0x056A, 0x0014); + bcm43xx_write16(bcm, 0x0568, 0x0826); + bcm43xx_write16(bcm, 0x0500, 0x0000); + bcm43xx_write16(bcm, 0x0502, 0x0030); + + for (i = 0x00; i < max_loop; i++) { + value = bcm43xx_read16(bcm, 0x050E); + if ((value & 0x0080) != 0) + break; + udelay(10); + } + for (i = 0x00; i < 0x0A; i++) { + value = bcm43xx_read16(bcm, 0x050E); + if ((value & 0x0400) != 0) + break; + udelay(10); + } + for (i = 0x00; i < 0x0A; i++) { + value = bcm43xx_read16(bcm, 0x0690); + if ((value & 0x0100) == 0) + break; + udelay(10); + } +} + +static void key_write(struct bcm43xx_private *bcm, + u8 index, u8 algorithm, const u16 *key) +{ + unsigned int i, basic_wep = 0; + u32 offset; + u16 value; + + /* Write associated key information */ + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2), + ((index << 4) | (algorithm & 0x0F))); + + /* The first 4 WEP keys need extra love */ + if (((algorithm == BCM43xx_SEC_ALGO_WEP) || + (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4)) + basic_wep = 1; + + /* Write key payload, 8 little endian words */ + offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE); + for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) { + value = cpu_to_le16(key[i]); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, + offset + (i * 2), value); + + if (!basic_wep) + continue; + + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, + offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE, + value); + } +} + +static void keymac_write(struct bcm43xx_private *bcm, + u8 index, const u32 *addr) +{ + /* for keys 0-3 there is no associated mac address */ + if (index < 4) + return; + + index -= 4; + if (bcm->current_core->rev >= 5) { + bcm43xx_shm_write32(bcm, + BCM43xx_SHM_HWMAC, + index * 2, + cpu_to_be32(*addr)); + bcm43xx_shm_write16(bcm, + BCM43xx_SHM_HWMAC, + (index * 2) + 1, + cpu_to_be16(*((u16 *)(addr + 1)))); + } else { + if (index < 8) { + TODO(); /* Put them in the macaddress filter */ + } else { + TODO(); + /* Put them BCM43xx_SHM_SHARED, stating index 0x0120. + Keep in mind to update the count of keymacs in 0x003E as well! */ + } + } +} + +static int bcm43xx_key_write(struct bcm43xx_private *bcm, + u8 index, u8 algorithm, + const u8 *_key, int key_len, + const u8 *mac_addr) +{ + u8 key[BCM43xx_SEC_KEYSIZE] = { 0 }; + + if (index >= ARRAY_SIZE(bcm->key)) + return -EINVAL; + if (key_len > ARRAY_SIZE(key)) + return -EINVAL; + if (algorithm < 1 || algorithm > 5) + return -EINVAL; + + memcpy(key, _key, key_len); + key_write(bcm, index, algorithm, (const u16 *)key); + keymac_write(bcm, index, (const u32 *)mac_addr); + + bcm->key[index].algorithm = algorithm; + + return 0; +} + +static void bcm43xx_clear_keys(struct bcm43xx_private *bcm) +{ + static const u32 zero_mac[2] = { 0 }; + unsigned int i,j, nr_keys = 54; + u16 offset; + + if (bcm->current_core->rev < 5) + nr_keys = 16; + assert(nr_keys <= ARRAY_SIZE(bcm->key)); + + for (i = 0; i < nr_keys; i++) { + bcm->key[i].enabled = 0; + /* returns for i < 4 immediately */ + keymac_write(bcm, i, zero_mac); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, + 0x100 + (i * 2), 0x0000); + for (j = 0; j < 8; j++) { + offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, + offset, 0x0000); + } + } + dprintk(KERN_INFO PFX "Keys cleared\n"); +} + +/* Puts the index of the current core into user supplied core variable. + * This function reads the value from the device. + * Almost always you don't want to call this, but use bcm->current_core + */ +static inline +int _get_current_core(struct bcm43xx_private *bcm, int *core) +{ + int err; + + err = bcm43xx_pci_read_config32(bcm, BCM43xx_REG_ACTIVE_CORE, core); + if (unlikely(err)) { + dprintk(KERN_ERR PFX "BCM43xx_REG_ACTIVE_CORE read failed!\n"); + return -ENODEV; + } + *core = (*core - 0x18000000) / 0x1000; + + return 0; +} + +/* Lowlevel core-switch function. This is only to be used in + * bcm43xx_switch_core() and bcm43xx_probe_cores() + */ +static int _switch_core(struct bcm43xx_private *bcm, int core) +{ + int err; + int attempts = 0; + int current_core = -1; + + assert(core >= 0); + + err = _get_current_core(bcm, ¤t_core); + if (unlikely(err)) + goto out; + + /* Write the computed value to the register. This doesn't always + succeed so we retry BCM43xx_SWITCH_CORE_MAX_RETRIES times */ + while (current_core != core) { + if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES)) { + err = -ENODEV; + printk(KERN_ERR PFX + "unable to switch to core %u, retried %i times\n", + core, attempts); + goto out; + } + err = bcm43xx_pci_write_config32(bcm, BCM43xx_REG_ACTIVE_CORE, + (core * 0x1000) + 0x18000000); + if (unlikely(err)) { + dprintk(KERN_ERR PFX "BCM43xx_REG_ACTIVE_CORE write failed!\n"); + continue; + } + _get_current_core(bcm, ¤t_core); +#ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) + bcm->current_core_offset = 0x1000 * core; + else + bcm->current_core_offset = 0; +#endif + } + + assert(err == 0); +out: + return err; +} + +int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core) +{ + int err; + + if (!new_core) + return 0; + + if (!(new_core->flags & BCM43xx_COREFLAG_AVAILABLE)) + return -ENODEV; + if (bcm->current_core == new_core) + return 0; + err = _switch_core(bcm, new_core->index); + if (!err) + bcm->current_core = new_core; + + return err; +} + +static inline int bcm43xx_core_enabled(struct bcm43xx_private *bcm) +{ + u32 value; + + value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET + | BCM43xx_SBTMSTATELOW_REJECT; + + return (value == BCM43xx_SBTMSTATELOW_CLOCK); +} + +/* disable current core */ +static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags) +{ + u32 sbtmstatelow; + u32 sbtmstatehigh; + int i; + + /* fetch sbtmstatelow from core information registers */ + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + + /* core is already in reset */ + if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET) + goto out; + + if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) { + sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | + BCM43xx_SBTMSTATELOW_REJECT; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + + for (i = 0; i < 1000; i++) { + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) { + i = -1; + break; + } + udelay(10); + } + if (i != -1) { + printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n"); + return -EBUSY; + } + + for (i = 0; i < 1000; i++) { + sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); + if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) { + i = -1; + break; + } + udelay(10); + } + if (i != -1) { + printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n"); + return -EBUSY; + } + + sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | + BCM43xx_SBTMSTATELOW_REJECT | + BCM43xx_SBTMSTATELOW_RESET | + BCM43xx_SBTMSTATELOW_CLOCK | + core_flags; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(10); + } + + sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET | + BCM43xx_SBTMSTATELOW_REJECT | + core_flags; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + +out: + bcm->current_core->flags &= ~ BCM43xx_COREFLAG_ENABLED; + return 0; +} + +/* enable (reset) current core */ +static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags) +{ + u32 sbtmstatelow; + u32 sbtmstatehigh; + u32 sbimstate; + int err; + + err = bcm43xx_core_disable(bcm, core_flags); + if (err) + goto out; + + sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | + BCM43xx_SBTMSTATELOW_RESET | + BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | + core_flags; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); + + sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); + if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) { + sbtmstatehigh = 0x00000000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh); + } + + sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE); + if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) { + sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT); + bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate); + } + + sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | + BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | + core_flags; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); + + sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); + + bcm->current_core->flags |= BCM43xx_COREFLAG_ENABLED; + assert(err == 0); +out: + return err; +} + +/* http://bcm-specs.sipsolutions.net/80211CoreReset */ +void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) +{ + u32 flags = 0x00040000; + + if ((bcm43xx_core_enabled(bcm)) && (!bcm->pio_mode)) { +//FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here? +#ifndef CONFIG_BCM947XX + /* reset all used DMA controllers. */ + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA2_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA3_BASE); + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); + bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA1_BASE); + if (bcm->current_core->rev < 5) + bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); +#endif + } + if (bcm->shutting_down) { + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002)); + } else { + if (connect_phy) + flags |= 0x20000000; + bcm43xx_phy_connect(bcm, connect_phy); + bcm43xx_core_enable(bcm, flags); + bcm43xx_write16(bcm, 0x03E6, 0x0000); + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + | BCM43xx_SBF_400); + } +} + +static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm) +{ + bcm43xx_radio_turn_off(bcm); + bcm43xx_write16(bcm, 0x03E6, 0x00F4); + bcm43xx_core_disable(bcm, 0); +} + +/* Mark the current 80211 core inactive. + * "active_80211_core" is the other 80211 core, which is used. + */ +static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm, + struct bcm43xx_coreinfo *active_80211_core) +{ + u32 sbtmstatelow; + struct bcm43xx_coreinfo *old_core; + int err = 0; + + bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + bcm43xx_radio_turn_off(bcm); + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + sbtmstatelow &= ~0x200a0000; + sbtmstatelow |= 0xa0000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + sbtmstatelow &= ~0xa0000; + sbtmstatelow |= 0x80000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, active_80211_core); + if (err) + goto out; + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + sbtmstatelow &= ~0x20000000; + sbtmstatelow |= 0x20000000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + err = bcm43xx_switch_core(bcm, old_core); + } + +out: + return err; +} + +static inline void handle_irq_transmit_status(struct bcm43xx_private *bcm) +{ + u32 v0, v1; + u16 tmp; + struct bcm43xx_xmitstatus stat; + + assert(bcm->current_core->id == BCM43xx_COREID_80211); + assert(bcm->current_core->rev >= 5); + + while (1) { + v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0); + if (!v0) + break; + v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1); + + stat.cookie = (v0 >> 16) & 0x0000FFFF; + tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1)); + stat.flags = tmp & 0xFF; + stat.cnt1 = (tmp & 0x0F00) >> 8; + stat.cnt2 = (tmp & 0xF000) >> 12; + stat.seq = (u16)(v1 & 0xFFFF); + stat.unknown = (u16)((v1 >> 16) & 0xFF); + + bcm43xx_debugfs_log_txstat(bcm, &stat); + + if (stat.flags & BCM43xx_TXSTAT_FLAG_IGNORE) + continue; + if (!(stat.flags & BCM43xx_TXSTAT_FLAG_ACK)) { + //TODO: packet was not acked (was lost) + } + //TODO: There are more (unknown) flags to test. see bcm43xx_main.h + + if (bcm->pio_mode) + bcm43xx_pio_handle_xmitstatus(bcm, &stat); + else + bcm43xx_dma_handle_xmitstatus(bcm, &stat); + } +} + +static inline void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) +{ + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F); + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4)); + assert(bcm->noisecalc.core_at_start == bcm->current_core); + assert(bcm->noisecalc.channel_at_start == bcm->current_core->radio->channel); +} + +static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) +{ + /* Top half of Link Quality calculation. */ + + if (bcm->noisecalc.calculation_running) + return; + bcm->noisecalc.core_at_start = bcm->current_core; + bcm->noisecalc.channel_at_start = bcm->current_core->radio->channel; + bcm->noisecalc.calculation_running = 1; + bcm->noisecalc.nr_samples = 0; + + bcm43xx_generate_noise_sample(bcm); +} + +static inline void handle_irq_noise(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 tmp; + u8 noise[4]; + u8 i, j; + s32 average; + + /* Bottom half of Link Quality calculation. */ + + assert(bcm->noisecalc.calculation_running); + if (bcm->noisecalc.core_at_start != bcm->current_core || + bcm->noisecalc.channel_at_start != radio->channel) + goto drop_calculation; + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408); + noise[0] = (tmp & 0x00FF); + noise[1] = (tmp & 0xFF00) >> 8; + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A); + noise[2] = (tmp & 0x00FF); + noise[3] = (tmp & 0xFF00) >> 8; + if (noise[0] == 0x7F || noise[1] == 0x7F || + noise[2] == 0x7F || noise[3] == 0x7F) + goto generate_new; + + /* Get the noise samples. */ + assert(bcm->noisecalc.nr_samples <= 8); + i = bcm->noisecalc.nr_samples; + noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); + noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); + noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); + noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); + bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]]; + bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]]; + bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]]; + bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]]; + bcm->noisecalc.nr_samples++; + if (bcm->noisecalc.nr_samples == 8) { + /* Calculate the Link Quality by the noise samples. */ + average = 0; + for (i = 0; i < 8; i++) { + for (j = 0; j < 4; j++) + average += bcm->noisecalc.samples[i][j]; + } + average /= (8 * 4); + average *= 125; + average += 64; + average /= 128; + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C); + tmp = (tmp / 128) & 0x1F; + if (tmp >= 8) + average += 2; + else + average -= 25; + if (tmp == 8) + average -= 72; + else + average -= 48; + + if (average > -65) + bcm->stats.link_quality = 0; + else if (average > -75) + bcm->stats.link_quality = 1; + else if (average > -85) + bcm->stats.link_quality = 2; + else + bcm->stats.link_quality = 3; +// dprintk(KERN_INFO PFX "Link Quality: %u (avg was %d)\n", bcm->stats.link_quality, average); +drop_calculation: + bcm->noisecalc.calculation_running = 0; + return; + } +generate_new: + bcm43xx_generate_noise_sample(bcm); +} + +static inline +void handle_irq_ps(struct bcm43xx_private *bcm) +{ + if (bcm->ieee->iw_mode == IW_MODE_MASTER) { + ///TODO: PS TBTT + } else { + if (1/*FIXME: the last PSpoll frame was sent successfully */) + bcm43xx_power_saving_ctl_bits(bcm, -1, -1); + } + if (bcm->ieee->iw_mode == IW_MODE_ADHOC) + bcm->reg124_set_0x4 = 1; + //FIXME else set to false? +} + +static inline +void handle_irq_reg124(struct bcm43xx_private *bcm) +{ + if (!bcm->reg124_set_0x4) + return; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) + | 0x4); + //FIXME: reset reg124_set_0x4 to false? +} + +static inline +void handle_irq_pmq(struct bcm43xx_private *bcm) +{ + u32 tmp; + + //TODO: AP mode. + + while (1) { + tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS); + if (!(tmp & 0x00000008)) + break; + } + /* 16bit write is odd, but correct. */ + bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002); +} + +static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm, + u16 ram_offset, u16 shm_size_offset) +{ + u32 value; + u16 size = 0; + + /* Timestamp. */ + //FIXME: assumption: The chip sets the timestamp + value = 0; + bcm43xx_ram_write(bcm, ram_offset++, value); + bcm43xx_ram_write(bcm, ram_offset++, value); + size += 8; + + /* Beacon Interval / Capability Information */ + value = 0x0000;//FIXME: Which interval? + value |= (1 << 0) << 16; /* ESS */ + value |= (1 << 2) << 16; /* CF Pollable */ //FIXME? + value |= (1 << 3) << 16; /* CF Poll Request */ //FIXME? + if (!bcm->ieee->open_wep) + value |= (1 << 4) << 16; /* Privacy */ + bcm43xx_ram_write(bcm, ram_offset++, value); + size += 4; + + /* SSID */ + //TODO + + /* FH Parameter Set */ + //TODO + + /* DS Parameter Set */ + //TODO + + /* CF Parameter Set */ + //TODO + + /* TIM */ + //TODO + + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size); +} + +static inline +void handle_irq_beacon(struct bcm43xx_private *bcm) +{ + u32 status; + + bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON; + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD); + + if ((status & 0x1) && (status & 0x2)) { + /* ACK beacon IRQ. */ + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, + BCM43xx_IRQ_BEACON); + bcm->irq_savedstate |= BCM43xx_IRQ_BEACON; + return; + } + if (!(status & 0x1)) { + bcm43xx_generate_beacon_template(bcm, 0x68, 0x18); + status |= 0x1; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status); + } + if (!(status & 0x2)) { + bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A); + status |= 0x2; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status); + } +} + +/* Debug helper for irq bottom-half to print all reason registers. */ +#define bcmirq_print_reasons(description) \ + do { \ + dprintkl(KERN_ERR PFX description "\n" \ + KERN_ERR PFX " Generic Reason: 0x%08x\n" \ + KERN_ERR PFX " DMA reasons: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n" \ + KERN_ERR PFX " DMA TX status: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", \ + reason, \ + dma_reason[0], dma_reason[1], \ + dma_reason[2], dma_reason[3], \ + bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_BASE + BCM43xx_DMA_TX_STATUS), \ + bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_BASE + BCM43xx_DMA_TX_STATUS), \ + bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_BASE + BCM43xx_DMA_TX_STATUS), \ + bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_BASE + BCM43xx_DMA_TX_STATUS)); \ + } while (0) + +/* Interrupt handler bottom-half */ +static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) +{ + u32 reason; + u32 dma_reason[4]; + int activity = 0; + unsigned long flags; + +#ifdef CONFIG_BCM43XX_DEBUG + u32 _handled = 0x00000000; +# define bcmirq_handled(irq) do { _handled |= (irq); } while (0) +#else +# define bcmirq_handled(irq) do { /* nothing */ } while (0) +#endif /* CONFIG_BCM43XX_DEBUG*/ + + spin_lock_irqsave(&bcm->lock, flags); + reason = bcm->irq_reason; + dma_reason[0] = bcm->dma_reason[0]; + dma_reason[1] = bcm->dma_reason[1]; + dma_reason[2] = bcm->dma_reason[2]; + dma_reason[3] = bcm->dma_reason[3]; + + if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) { + /* TX error. We get this when Template Ram is written in wrong endianess + * in dummy_tx(). We also get this if something is wrong with the TX header + * on DMA or PIO queues. + * Maybe we get this in other error conditions, too. + */ + bcmirq_print_reasons("XMIT ERROR"); + bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR); + } + + if (reason & BCM43xx_IRQ_PS) { + handle_irq_ps(bcm); + bcmirq_handled(BCM43xx_IRQ_PS); + } + + if (reason & BCM43xx_IRQ_REG124) { + handle_irq_reg124(bcm); + bcmirq_handled(BCM43xx_IRQ_REG124); + } + + if (reason & BCM43xx_IRQ_BEACON) { + if (bcm->ieee->iw_mode == IW_MODE_MASTER) + handle_irq_beacon(bcm); + bcmirq_handled(BCM43xx_IRQ_BEACON); + } + + if (reason & BCM43xx_IRQ_PMQ) { + handle_irq_pmq(bcm); + bcmirq_handled(BCM43xx_IRQ_PMQ); + } + + if (reason & BCM43xx_IRQ_SCAN) { + /*TODO*/ + //bcmirq_handled(BCM43xx_IRQ_SCAN); + } + + if (reason & BCM43xx_IRQ_NOISE) { + handle_irq_noise(bcm); + bcmirq_handled(BCM43xx_IRQ_NOISE); + } + + /* Check the DMA reason registers for received data. */ + assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE)); + assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); + if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { + if (bcm->pio_mode) + bcm43xx_pio_rx(bcm->current_core->pio->queue0); + else + bcm43xx_dma_rx(bcm->current_core->dma->rx_ring0); + activity = 1; + } + if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { + if (likely(bcm->current_core->rev < 5)) { + if (bcm->pio_mode) + bcm43xx_pio_rx(bcm->current_core->pio->queue3); + else + bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1); + activity = 1; + } else + assert(0); + } + bcmirq_handled(BCM43xx_IRQ_RX); + + if (reason & BCM43xx_IRQ_XMIT_STATUS) { + if (bcm->current_core->rev >= 5) { + handle_irq_transmit_status(bcm); + activity = 1; + } + //TODO: In AP mode, this also causes sending of powersave responses. + bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS); + } + + /* We get spurious IRQs, althought they are masked. + * Assume they are void and ignore them. + */ + bcmirq_handled(~(bcm->irq_savedstate)); + /* IRQ_PIO_WORKAROUND is handled in the top-half. */ + bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND); +#ifdef CONFIG_BCM43XX_DEBUG + if (unlikely(reason & ~_handled)) { + printkl(KERN_WARNING PFX + "Unhandled IRQ! Reason: 0x%08x, Unhandled: 0x%08x, " + "DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + reason, (reason & ~_handled), + dma_reason[0], dma_reason[1], + dma_reason[2], dma_reason[3]); + } +#endif +#undef bcmirq_handled + + if (!modparam_noleds) + bcm43xx_leds_update(bcm, activity); + bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); + spin_unlock_irqrestore(&bcm->lock, flags); +} + +#undef bcmirq_print_reasons + +static inline +void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, + u32 reason, u32 mask) +{ + bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) + & 0x0001dc00; + bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) + & 0x0000dc00; + bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) + & 0x0000dc00; + bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) + & 0x0001dc00; + + if ((bcm->pio_mode) && + (bcm->current_core->rev < 3) && + (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) { + /* Apply a PIO specific workaround to the dma_reasons */ + +#define apply_pio_workaround(BASE, QNUM) \ + do { \ + if (bcm43xx_read16(bcm, BASE + BCM43xx_PIO_RXCTL) & BCM43xx_PIO_RXCTL_DATAAVAILABLE) \ + bcm->dma_reason[QNUM] |= 0x00010000; \ + else \ + bcm->dma_reason[QNUM] &= ~0x00010000; \ + } while (0) + + apply_pio_workaround(BCM43xx_MMIO_PIO1_BASE, 0); + apply_pio_workaround(BCM43xx_MMIO_PIO2_BASE, 1); + apply_pio_workaround(BCM43xx_MMIO_PIO3_BASE, 2); + apply_pio_workaround(BCM43xx_MMIO_PIO4_BASE, 3); + +#undef apply_pio_workaround + } + + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, + reason & mask); + + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON, + bcm->dma_reason[0]); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON, + bcm->dma_reason[1]); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON, + bcm->dma_reason[2]); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON, + bcm->dma_reason[3]); +} + +/* Interrupt handler top-half */ +static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + struct bcm43xx_private *bcm = dev_id; + u32 reason, mask; + + if (!bcm) + return IRQ_NONE; + + spin_lock(&bcm->lock); + + reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + if (reason == 0xffffffff) { + /* irq not for us (shared irq) */ + spin_unlock(&bcm->lock); + return IRQ_NONE; + } + mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); + if (!(reason & mask)) { + spin_unlock(&bcm->lock); + return IRQ_HANDLED; + } + + bcm43xx_interrupt_ack(bcm, reason, mask); + + /* disable all IRQs. They are enabled again in the bottom half. */ + bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + + /* save the reason code and call our bottom half. */ + bcm->irq_reason = reason; + tasklet_schedule(&bcm->isr_tasklet); + + spin_unlock(&bcm->lock); + + return IRQ_HANDLED; +} + +static void bcm43xx_release_firmware(struct bcm43xx_private *bcm) +{ + if (bcm->firmware_norelease) + return; /* Suspending or controller reset. */ + release_firmware(bcm->ucode); + bcm->ucode = NULL; + release_firmware(bcm->pcm); + bcm->pcm = NULL; + release_firmware(bcm->initvals0); + bcm->initvals0 = NULL; + release_firmware(bcm->initvals1); + bcm->initvals1 = NULL; +} + +static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u8 rev = bcm->current_core->rev; + int err = 0; + int nr; + char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 }; + + if (!bcm->ucode) { + snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw", + (rev >= 5 ? 5 : rev), + modparam_fwpostfix); + err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: Microcode \"%s\" not available or load failed.\n", + buf); + goto error; + } + } + + if (!bcm->pcm) { + snprintf(buf, ARRAY_SIZE(buf), + "bcm43xx_pcm%d%s.fw", + (rev < 5 ? 4 : 5), + modparam_fwpostfix); + err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: PCM \"%s\" not available or load failed.\n", + buf); + goto error; + } + } + + if (!bcm->initvals0) { + if (rev == 2 || rev == 4) { + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + nr = 3; + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + nr = 1; + break; + default: + goto err_noinitval; + } + + } else if (rev >= 5) { + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + nr = 7; + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + nr = 5; + break; + default: + goto err_noinitval; + } + } else + goto err_noinitval; + snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", + nr, modparam_fwpostfix); + + err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: InitVals \"%s\" not available or load failed.\n", + buf); + goto error; + } + if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) { + printk(KERN_ERR PFX "InitVals fileformat error.\n"); + goto error; + } + } + + if (!bcm->initvals1) { + if (rev >= 5) { + u32 sbtmstatehigh; + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); + if (sbtmstatehigh & 0x00010000) + nr = 9; + else + nr = 10; + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + nr = 6; + break; + default: + goto err_noinitval; + } + snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", + nr, modparam_fwpostfix); + + err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: InitVals \"%s\" not available or load failed.\n", + buf); + goto error; + } + if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) { + printk(KERN_ERR PFX "InitVals fileformat error.\n"); + goto error; + } + } + } + +out: + return err; +error: + bcm43xx_release_firmware(bcm); + goto out; +err_noinitval: + printk(KERN_ERR PFX "Error: No InitVals available!\n"); + err = -ENOENT; + goto error; +} + +static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) +{ + const u32 *data; + unsigned int i, len; + +#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT + bcm43xx_mmioprint_enable(bcm); +#else + bcm43xx_mmioprint_disable(bcm); +#endif + + /* Upload Microcode. */ + data = (u32 *)(bcm->ucode->data); + len = bcm->ucode->size / sizeof(u32); + bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000); + for (i = 0; i < len; i++) { + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, + be32_to_cpu(data[i])); + udelay(10); + } + + /* Upload PCM data. */ + data = (u32 *)(bcm->pcm->data); + len = bcm->pcm->size / sizeof(u32); + bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea); + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000); + bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb); + for (i = 0; i < len; i++) { + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, + be32_to_cpu(data[i])); + udelay(10); + } + +#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT + bcm43xx_mmioprint_disable(bcm); +#else + bcm43xx_mmioprint_enable(bcm); +#endif +} + +static void bcm43xx_write_initvals(struct bcm43xx_private *bcm, + const struct bcm43xx_initval *data, + const unsigned int len) +{ + u16 offset, size; + u32 value; + unsigned int i; + + for (i = 0; i < len; i++) { + offset = be16_to_cpu(data[i].offset); + size = be16_to_cpu(data[i].size); + value = be32_to_cpu(data[i].value); + + if (size == 2) + bcm43xx_write16(bcm, offset, value); + else if (size == 4) + bcm43xx_write32(bcm, offset, value); + else + printk(KERN_ERR PFX "InitVals fileformat error.\n"); + } +} + +static void bcm43xx_upload_initvals(struct bcm43xx_private *bcm) +{ +#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT + bcm43xx_mmioprint_enable(bcm); +#else + bcm43xx_mmioprint_disable(bcm); +#endif + + bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, + bcm->initvals0->size / sizeof(struct bcm43xx_initval)); + if (bcm->initvals1) { + bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data, + bcm->initvals1->size / sizeof(struct bcm43xx_initval)); + } + +#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT + bcm43xx_mmioprint_disable(bcm); +#else + bcm43xx_mmioprint_enable(bcm); +#endif +} + +static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) +{ + int res; + unsigned int i; + u32 data; + + bcm->irq = bcm->pci_dev->irq; +#ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) { + struct pci_dev *d = NULL; + /* FIXME: we will probably need more device IDs here... */ + d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL); + if (d != NULL) { + bcm->irq = d->irq; + } + } +#endif + res = request_irq(bcm->irq, bcm43xx_interrupt_handler, + SA_SHIRQ, DRV_NAME, bcm); + if (res) { + printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); + return -EFAULT; + } + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff); + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402); + i = 0; + while (1) { + data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + if (data == BCM43xx_IRQ_READY) + break; + i++; + if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) { + printk(KERN_ERR PFX "Card IRQ register not responding. " + "Giving up.\n"); + free_irq(bcm->irq, bcm); + return -ENODEV; + } + udelay(10); + } + // dummy read + bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + + return 0; +} + +/* Switch to the core used to write the GPIO register. + * This is either the ChipCommon, or the PCI core. + */ +static inline int switch_to_gpio_core(struct bcm43xx_private *bcm) +{ + int err; + + /* Where to find the GPIO register depends on the chipset. + * If it has a ChipCommon, its register at offset 0x6c is the GPIO + * control register. Otherwise the register at offset 0x6c in the + * PCI core is the GPIO control register. + */ + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err == -ENODEV) { + err = bcm43xx_switch_core(bcm, &bcm->core_pci); + if (err == -ENODEV) { + printk(KERN_ERR PFX "gpio error: " + "Neither ChipCommon nor PCI core available!\n"); + return -ENODEV; + } else if (err != 0) + return -ENODEV; + } else if (err != 0) + return -ENODEV; + + return 0; +} + +/* Initialize the GPIOs + * http://bcm-specs.sipsolutions.net/GPIO + */ +static int bcm43xx_gpio_init(struct bcm43xx_private *bcm) +{ + struct bcm43xx_coreinfo *old_core; + int err; + u32 mask, value; + + value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value &= ~0xc000; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); + + mask = 0x0000001F; + value = 0x0000000F; + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, + bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL) & 0xFFF0); + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, + bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F); + + old_core = bcm->current_core; + + err = switch_to_gpio_core(bcm); + if (err) + return err; + + if (bcm->current_core->rev >= 2){ + mask |= 0x10; + value |= 0x10; + } + if (bcm->chip_id == 0x4301) { + mask |= 0x60; + value |= 0x60; + } + if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) { + mask |= 0x200; + value |= 0x200; + } + + bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, + (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | value); + + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + + return 0; +} + +/* Turn off all GPIO stuff. Call this on module unload, for example. */ +static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm) +{ + struct bcm43xx_coreinfo *old_core; + int err; + + old_core = bcm->current_core; + err = switch_to_gpio_core(bcm); + if (err) + return err; + bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000); + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + + return 0; +} + +/* http://bcm-specs.sipsolutions.net/EnableMac */ +void bcm43xx_mac_enable(struct bcm43xx_private *bcm) +{ + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + | BCM43xx_SBF_MAC_ENABLED); + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY); + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ + bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ + bcm43xx_power_saving_ctl_bits(bcm, -1, -1); +} + +/* http://bcm-specs.sipsolutions.net/SuspendMAC */ +void bcm43xx_mac_suspend(struct bcm43xx_private *bcm) +{ + int i; + u32 tmp; + + bcm43xx_power_saving_ctl_bits(bcm, -1, 1); + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + & ~BCM43xx_SBF_MAC_ENABLED); + bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ + for (i = 1000; i > 0; i--) { + tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + if (tmp & BCM43xx_IRQ_READY) { + i = -1; + break; + } + udelay(10); + } + if (!i) + printkl(KERN_ERR PFX "Failed to suspend mac!\n"); +} + +void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, + int iw_mode) +{ + unsigned long flags; + u32 status; + + spin_lock_irqsave(&bcm->ieee->lock, flags); + bcm->ieee->iw_mode = iw_mode; + spin_unlock_irqrestore(&bcm->ieee->lock, flags); + if (iw_mode == IW_MODE_MONITOR) + bcm->net_dev->type = ARPHRD_IEEE80211; + else + bcm->net_dev->type = ARPHRD_ETHER; + + if (!bcm->initialized) + return; + + bcm43xx_mac_suspend(bcm); + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + /* Reset status to infrastructured mode */ + status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR); + /*FIXME: We actually set promiscuous mode as well, until we don't + * get the HW mac filter working */ + status |= BCM43xx_SBF_MODE_NOTADHOC | BCM43xx_SBF_MODE_PROMISC; + + switch (iw_mode) { + case IW_MODE_MONITOR: + status |= (BCM43xx_SBF_MODE_PROMISC | + BCM43xx_SBF_MODE_MONITOR); + break; + case IW_MODE_ADHOC: + status &= ~BCM43xx_SBF_MODE_NOTADHOC; + break; + case IW_MODE_MASTER: + case IW_MODE_SECOND: + case IW_MODE_REPEAT: + /* TODO: No AP/Repeater mode for now :-/ */ + TODO(); + break; + case IW_MODE_INFRA: + /* nothing to be done here... */ + break; + default: + printk(KERN_ERR PFX "Unknown iwmode %d\n", iw_mode); + } + + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + bcm43xx_mac_enable(bcm); +} + +/* This is the opposite of bcm43xx_chip_init() */ +static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm) +{ + bcm43xx_radio_turn_off(bcm); + if (!modparam_noleds) + bcm43xx_leds_exit(bcm); + bcm43xx_gpio_cleanup(bcm); + free_irq(bcm->irq, bcm); + bcm43xx_release_firmware(bcm); +} + +/* Initialize the chip + * http://bcm-specs.sipsolutions.net/ChipInit + */ +static int bcm43xx_chip_init(struct bcm43xx_private *bcm) +{ + int err; + int iw_mode = bcm->ieee->iw_mode; + int tmp; + u32 value32; + u16 value16; + + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + BCM43xx_SBF_CORE_READY + | BCM43xx_SBF_400); + + err = bcm43xx_request_firmware(bcm); + if (err) + goto out; + bcm43xx_upload_microcode(bcm); + + err = bcm43xx_initialize_irq(bcm); + if (err) + goto out; + + err = bcm43xx_gpio_init(bcm); + if (err) + goto err_free_irq; + + bcm43xx_upload_initvals(bcm); + bcm43xx_radio_turn_on(bcm); + + if (modparam_noleds) + bcm43xx_leds_turn_off(bcm); + else + bcm43xx_leds_update(bcm, 0); + + bcm43xx_write16(bcm, 0x03E6, 0x0000); + err = bcm43xx_phy_init(bcm); + if (err) + goto err_radio_off; + + /* Select initial Interference Mitigation. */ + tmp = bcm->current_core->radio->interfmode; + bcm->current_core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; + bcm43xx_radio_set_interference_mitigation(bcm, tmp); + + bcm43xx_phy_set_antenna_diversity(bcm); + bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT); + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) { + value16 = bcm43xx_read16(bcm, 0x005E); + value16 |= 0x0004; + bcm43xx_write16(bcm, 0x005E, value16); + } + bcm43xx_write32(bcm, 0x0100, 0x01000000); + if (bcm->current_core->rev < 5) + bcm43xx_write32(bcm, 0x010C, 0x01000000); + + value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); + value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value32 |= BCM43xx_SBF_MODE_NOTADHOC; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); + /*FIXME: For now, use promiscuous mode at all times; otherwise we don't + get broadcast or multicast packets */ + value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value32 |= BCM43xx_SBF_MODE_PROMISC; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); + + if (iw_mode == IW_MODE_MONITOR) { + value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value32 |= BCM43xx_SBF_MODE_PROMISC; + value32 |= BCM43xx_SBF_MODE_MONITOR; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); + } + value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value32 |= 0x100000; //FIXME: What's this? Is this correct? + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); + + if (bcm->pio_mode) { + bcm43xx_write32(bcm, 0x0210, 0x00000100); + bcm43xx_write32(bcm, 0x0230, 0x00000100); + bcm43xx_write32(bcm, 0x0250, 0x00000100); + bcm43xx_write32(bcm, 0x0270, 0x00000100); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000); + } + + /* Probe Response Timeout value */ + /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000); + + if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) { + if ((bcm->chip_id == 0x4306) && (bcm->chip_rev == 3)) + bcm43xx_write16(bcm, 0x0612, 0x0064); + else + bcm43xx_write16(bcm, 0x0612, 0x0032); + } else + bcm43xx_write16(bcm, 0x0612, 0x0002); + + if (bcm->current_core->rev < 3) { + bcm43xx_write16(bcm, 0x060E, 0x0000); + bcm43xx_write16(bcm, 0x0610, 0x8000); + bcm43xx_write16(bcm, 0x0604, 0x0000); + bcm43xx_write16(bcm, 0x0606, 0x0200); + } else { + bcm43xx_write32(bcm, 0x0188, 0x80000000); + bcm43xx_write32(bcm, 0x018C, 0x02000000); + } + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0001DC00); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0000DC00); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0001DC00); + + value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + value32 |= 0x00100000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32); + + bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm)); + + assert(err == 0); + dprintk(KERN_INFO PFX "Chip initialized\n"); +out: + return err; + +err_radio_off: + bcm43xx_radio_turn_off(bcm); + bcm43xx_gpio_cleanup(bcm); +err_free_irq: + free_irq(bcm->irq, bcm); + goto out; +} + +/* Validate chip access + * http://bcm-specs.sipsolutions.net/ValidateChipAccess */ +static int bcm43xx_validate_chip(struct bcm43xx_private *bcm) +{ + int err = -ENODEV; + u32 value; + u32 shm_backup; + + shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA); + if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA) { + printk(KERN_ERR PFX "Error: SHM mismatch (1) validating chip\n"); + goto out; + } + + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55); + if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55) { + printk(KERN_ERR PFX "Error: SHM mismatch (2) validating chip\n"); + goto out; + } + + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup); + + value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + if ((value | 0x80000000) != 0x80000400) { + printk(KERN_ERR PFX "Error: Bad Status Bitfield while validating chip\n"); + goto out; + } + + value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + if (value != 0x00000000) { + printk(KERN_ERR PFX "Error: Bad interrupt reason code while validating chip\n"); + goto out; + } + + err = 0; +out: + return err; +} + +static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) +{ + int err, i; + int current_core; + u32 core_vendor, core_id, core_rev; + u32 sb_id_hi, chip_id_32 = 0; + u16 pci_device, chip_id_16; + u8 core_count; + + memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo)); + memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo)); + memset(&bcm->core_v90, 0, sizeof(struct bcm43xx_coreinfo)); + memset(&bcm->core_pcmcia, 0, sizeof(struct bcm43xx_coreinfo)); + memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo) + * BCM43xx_MAX_80211_CORES); + + memset(&bcm->phy, 0, sizeof(struct bcm43xx_phyinfo) + * BCM43xx_MAX_80211_CORES); + memset(&bcm->radio, 0, sizeof(struct bcm43xx_radioinfo) + * BCM43xx_MAX_80211_CORES); + + /* map core 0 */ + err = _switch_core(bcm, 0); + if (err) + goto out; + + /* fetch sb_id_hi from core information registers */ + sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI); + + core_id = (sb_id_hi & 0xFFF0) >> 4; + core_rev = (sb_id_hi & 0xF); + core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; + + /* if present, chipcommon is always core 0; read the chipid from it */ + if (core_id == BCM43xx_COREID_CHIPCOMMON) { + chip_id_32 = bcm43xx_read32(bcm, 0); + chip_id_16 = chip_id_32 & 0xFFFF; + bcm->core_chipcommon.flags |= BCM43xx_COREFLAG_AVAILABLE; + bcm->core_chipcommon.id = core_id; + bcm->core_chipcommon.rev = core_rev; + bcm->core_chipcommon.index = 0; + /* While we are at it, also read the capabilities. */ + bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES); + } else { + /* without a chipCommon, use a hard coded table. */ + pci_device = bcm->pci_dev->device; + if (pci_device == 0x4301) + chip_id_16 = 0x4301; + else if ((pci_device >= 0x4305) && (pci_device <= 0x4307)) + chip_id_16 = 0x4307; + else if ((pci_device >= 0x4402) && (pci_device <= 0x4403)) + chip_id_16 = 0x4402; + else if ((pci_device >= 0x4610) && (pci_device <= 0x4615)) + chip_id_16 = 0x4610; + else if ((pci_device >= 0x4710) && (pci_device <= 0x4715)) + chip_id_16 = 0x4710; +#ifdef CONFIG_BCM947XX + else if ((pci_device >= 0x4320) && (pci_device <= 0x4325)) + chip_id_16 = 0x4309; +#endif + else { + printk(KERN_ERR PFX "Could not determine Chip ID\n"); + return -ENODEV; + } + } + + /* ChipCommon with Core Rev >=4 encodes number of cores, + * otherwise consult hardcoded table */ + if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) { + core_count = (chip_id_32 & 0x0F000000) >> 24; + } else { + switch (chip_id_16) { + case 0x4610: + case 0x4704: + case 0x4710: + core_count = 9; + break; + case 0x4310: + core_count = 8; + break; + case 0x5365: + core_count = 7; + break; + case 0x4306: + core_count = 6; + break; + case 0x4301: + case 0x4307: + core_count = 5; + break; + case 0x4402: + core_count = 3; + break; + default: + /* SOL if we get here */ + assert(0); + core_count = 1; + } + } + + bcm->chip_id = chip_id_16; + bcm->chip_rev = (chip_id_32 & 0x000f0000) >> 16; + + dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n", + bcm->chip_id, bcm->chip_rev); + dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count); + if (bcm->core_chipcommon.flags & BCM43xx_COREFLAG_AVAILABLE) { + dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n", + core_id, core_rev, core_vendor, + bcm43xx_core_enabled(bcm) ? "enabled" : "disabled"); + } + + if (bcm->core_chipcommon.flags & BCM43xx_COREFLAG_AVAILABLE) + current_core = 1; + else + current_core = 0; + for ( ; current_core < core_count; current_core++) { + struct bcm43xx_coreinfo *core; + + err = _switch_core(bcm, current_core); + if (err) + goto out; + /* Gather information */ + /* fetch sb_id_hi from core information registers */ + sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI); + + /* extract core_id, core_rev, core_vendor */ + core_id = (sb_id_hi & 0xFFF0) >> 4; + core_rev = (sb_id_hi & 0xF); + core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; + + dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n", + current_core, core_id, core_rev, core_vendor, + bcm43xx_core_enabled(bcm) ? "enabled" : "disabled" ); + + core = NULL; + switch (core_id) { + case BCM43xx_COREID_PCI: + core = &bcm->core_pci; + if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { + printk(KERN_WARNING PFX "Multiple PCI cores found.\n"); + continue; + } + break; + case BCM43xx_COREID_V90: + core = &bcm->core_v90; + if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { + printk(KERN_WARNING PFX "Multiple V90 cores found.\n"); + continue; + } + break; + case BCM43xx_COREID_PCMCIA: + core = &bcm->core_pcmcia; + if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { + printk(KERN_WARNING PFX "Multiple PCMCIA cores found.\n"); + continue; + } + break; + case BCM43xx_COREID_ETHERNET: + core = &bcm->core_ethernet; + if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { + printk(KERN_WARNING PFX "Multiple Ethernet cores found.\n"); + continue; + } + break; + case BCM43xx_COREID_80211: + for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { + core = &(bcm->core_80211[i]); + if (!(core->flags & BCM43xx_COREFLAG_AVAILABLE)) + break; + core = NULL; + } + if (!core) { + printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n", + BCM43xx_MAX_80211_CORES); + continue; + } + if (i != 0) { + /* More than one 80211 core is only supported + * by special chips. + * There are chips with two 80211 cores, but with + * dangling pins on the second core. Be careful + * and ignore these cores here. + */ + if (bcm->pci_dev->device != 0x4324) { + dprintk(KERN_INFO PFX "Ignoring additional 802.11 core.\n"); + continue; + } + } + switch (core_rev) { + case 2: + case 4: + case 5: + case 6: + case 7: + case 9: + break; + default: + printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n", + core_rev); + err = -ENODEV; + goto out; + } + core->phy = &bcm->phy[i]; + core->phy->antenna_diversity = 0xffff; + core->phy->savedpctlreg = 0xFFFF; + core->phy->minlowsig[0] = 0xFFFF; + core->phy->minlowsig[1] = 0xFFFF; + core->phy->minlowsigpos[0] = 0; + core->phy->minlowsigpos[1] = 0; + spin_lock_init(&core->phy->lock); + core->radio = &bcm->radio[i]; + core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; + core->radio->channel = 0xFF; + core->radio->initial_channel = 0xFF; + core->radio->lofcal = 0xFFFF; + core->radio->initval = 0xFFFF; + core->radio->nrssi[0] = -1000; + core->radio->nrssi[1] = -1000; + core->dma = &bcm->dma[i]; + core->pio = &bcm->pio[i]; + break; + case BCM43xx_COREID_CHIPCOMMON: + printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n"); + break; + default: + printk(KERN_WARNING PFX "Unknown core found (ID 0x%x)\n", core_id); + } + if (core) { + core->flags |= BCM43xx_COREFLAG_AVAILABLE; + core->id = core_id; + core->rev = core_rev; + core->index = current_core; + } + } + + if (!(bcm->core_80211[0].flags & BCM43xx_COREFLAG_AVAILABLE)) { + printk(KERN_ERR PFX "Error: No 80211 core found!\n"); + err = -ENODEV; + goto out; + } + + err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]); + + assert(err == 0); +out: + return err; +} + +static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm) +{ + const u8 *mac = (const u8*)(bcm->net_dev->dev_addr); + u8 *bssid = bcm->ieee->bssid; + + switch (bcm->ieee->iw_mode) { + case IW_MODE_ADHOC: + random_ether_addr(bssid); + break; + case IW_MODE_MASTER: + case IW_MODE_INFRA: + case IW_MODE_REPEAT: + case IW_MODE_SECOND: + case IW_MODE_MONITOR: + memcpy(bssid, mac, ETH_ALEN); + break; + default: + assert(0); + } +} + +static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm, + u16 rate, + int is_ofdm) +{ + u16 offset; + + if (is_ofdm) { + offset = 0x480; + offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2; + } + else { + offset = 0x4C0; + offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2; + } + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20, + bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset)); +} + +static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm) +{ + switch (bcm->current_core->phy->type) { + case BCM43xx_PHYTYPE_A: + case BCM43xx_PHYTYPE_G: + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1); + bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1); + case BCM43xx_PHYTYPE_B: + bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0); + bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0); + bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0); + bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0); + break; + default: + assert(0); + } +} + +static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm) +{ + bcm43xx_chip_cleanup(bcm); + bcm43xx_pio_free(bcm); + bcm43xx_dma_free(bcm); + + bcm->current_core->flags &= ~ BCM43xx_COREFLAG_INITIALIZED; +} + +/* http://bcm-specs.sipsolutions.net/80211Init */ +static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) +{ + u32 ucodeflags; + int err; + u32 sbimconfiglow; + u8 limit; + + if (bcm->chip_rev < 5) { + sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); + sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; + sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; + if (bcm->bustype == BCM43xx_BUSTYPE_PCI) + sbimconfiglow |= 0x32; + else if (bcm->bustype == BCM43xx_BUSTYPE_SB) + sbimconfiglow |= 0x53; + else + assert(0); + bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow); + } + + bcm43xx_phy_calibrate(bcm); + err = bcm43xx_chip_init(bcm); + if (err) + goto out; + + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev); + ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET); + + if (0 /*FIXME: which condition has to be used here? */) + ucodeflags |= 0x00000010; + + /* HW decryption needs to be set now */ + ucodeflags |= 0x40000000; + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; + if (bcm->current_core->phy->rev == 1) + ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY; + if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) + ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL; + } else if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) { + ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; + if ((bcm->current_core->phy->rev >= 2) && + (bcm->current_core->radio->version == 0x2050)) + ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY; + } + + if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET)) { + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, ucodeflags); + } + + /* Short/Long Retry Limit. + * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing + * the chip-internal counter. + */ + limit = limit_value(modparam_short_retry, 0, 0xF); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit); + limit = limit_value(modparam_long_retry, 0, 0xF); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit); + + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2); + + bcm43xx_rate_memory_init(bcm); + + /* Minimum Contention Window */ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f); + else + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f); + /* Maximum Contention Window */ + bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff); + + bcm43xx_gen_bssid(bcm); + bcm43xx_write_mac_bssid_templates(bcm); + + if (bcm->current_core->rev >= 5) + bcm43xx_write16(bcm, 0x043C, 0x000C); + + if (!bcm->pio_mode) { + err = bcm43xx_dma_init(bcm); + if (err) + goto err_chip_cleanup; + } else { + err = bcm43xx_pio_init(bcm); + if (err) + goto err_chip_cleanup; + } + bcm43xx_write16(bcm, 0x0612, 0x0050); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); + + bcm43xx_mac_enable(bcm); + bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); + + bcm->current_core->flags |= BCM43xx_COREFLAG_INITIALIZED; +out: + return err; + +err_chip_cleanup: + bcm43xx_chip_cleanup(bcm); + goto out; +} + +static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm) +{ + int err; + u16 pci_status; + + err = bcm43xx_pctl_set_crystal(bcm, 1); + if (err) + goto out; + bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status); + bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT); + +out: + return err; +} + +static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm) +{ + bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); + bcm43xx_pctl_set_crystal(bcm, 0); +} + +static inline void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm, + u32 address, + u32 data) +{ + bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address); + bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data); +} + +static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm) +{ + int err; + struct bcm43xx_coreinfo *old_core; + + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_pci); + if (err) + goto out; + + bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); + + bcm43xx_switch_core(bcm, old_core); + assert(err == 0); +out: + return err; +} + +/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable. + * To enable core 0, pass a core_mask of 1<<0 + */ +static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm, + u32 core_mask) +{ + u32 backplane_flag_nr; + u32 value; + struct bcm43xx_coreinfo *old_core; + int err = 0; + + value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG); + backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK; + + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_pci); + if (err) + goto out; + + if (bcm->core_pci.rev < 6) { + value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC); + value |= (1 << backplane_flag_nr); + bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value); + } else { + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value); + if (err) { + printk(KERN_ERR PFX "Error: ICR setup failure!\n"); + goto out_switch_back; + } + value |= core_mask << 8; + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value); + if (err) { + printk(KERN_ERR PFX "Error: ICR setup failure!\n"); + goto out_switch_back; + } + } + + value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); + value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST; + bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); + + if (bcm->core_pci.rev < 5) { + value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); + value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT) + & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; + value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT) + & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; + bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value); + err = bcm43xx_pcicore_commit_settings(bcm); + assert(err == 0); + } + +out_switch_back: + err = bcm43xx_switch_core(bcm, old_core); +out: + return err; +} + +static void bcm43xx_softmac_init(struct bcm43xx_private *bcm) +{ + ieee80211softmac_start(bcm->net_dev); +} + +static void bcm43xx_periodic_work0_handler(void *d) +{ + struct bcm43xx_private *bcm = d; + unsigned long flags; + //TODO: unsigned int aci_average; + + spin_lock_irqsave(&bcm->lock, flags); + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + //FIXME: aci_average = bcm43xx_update_aci_average(bcm); + if (bcm->current_core->radio->aci_enable && bcm->current_core->radio->aci_wlan_automatic) { + bcm43xx_mac_suspend(bcm); + if (!bcm->current_core->radio->aci_enable && + 1 /*FIXME: We are not scanning? */) { + /*FIXME: First add bcm43xx_update_aci_average() before + * uncommenting this: */ + //if (bcm43xx_radio_aci_scan) + // bcm43xx_radio_set_interference_mitigation(bcm, + // BCM43xx_RADIO_INTERFMODE_MANUALWLAN); + } else if (1/*FIXME*/) { + //if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) + // bcm43xx_radio_set_interference_mitigation(bcm, + // BCM43xx_RADIO_INTERFMODE_MANUALWLAN); + } + bcm43xx_mac_enable(bcm); + } else if (bcm->current_core->radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) { + if (bcm->current_core->phy->rev == 1) { + //FIXME: implement rev1 workaround + } + } + } + bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning? + //TODO for APHY (temperature?) + + if (likely(!bcm->shutting_down)) { + queue_delayed_work(bcm->workqueue, &bcm->periodic_work0, + BCM43xx_PERIODIC_0_DELAY); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +static void bcm43xx_periodic_work1_handler(void *d) +{ + struct bcm43xx_private *bcm = d; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + + bcm43xx_phy_lo_mark_all_unused(bcm); + if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { + bcm43xx_mac_suspend(bcm); + bcm43xx_calc_nrssi_slope(bcm); + bcm43xx_mac_enable(bcm); + } + + if (likely(!bcm->shutting_down)) { + queue_delayed_work(bcm->workqueue, &bcm->periodic_work1, + BCM43xx_PERIODIC_1_DELAY); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +static void bcm43xx_periodic_work2_handler(void *d) +{ + struct bcm43xx_private *bcm = d; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + + assert(bcm->current_core->phy->type == BCM43xx_PHYTYPE_G); + assert(bcm->current_core->phy->rev >= 2); + + bcm43xx_mac_suspend(bcm); + bcm43xx_phy_lo_g_measure(bcm); + bcm43xx_mac_enable(bcm); + + if (likely(!bcm->shutting_down)) { + queue_delayed_work(bcm->workqueue, &bcm->periodic_work2, + BCM43xx_PERIODIC_2_DELAY); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +static void bcm43xx_periodic_work3_handler(void *d) +{ + struct bcm43xx_private *bcm = d; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + + /* Update device statistics. */ + bcm43xx_calculate_link_quality(bcm); + + if (likely(!bcm->shutting_down)) { + queue_delayed_work(bcm->workqueue, &bcm->periodic_work3, + BCM43xx_PERIODIC_3_DELAY); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +/* Delete all periodic tasks and make + * sure they are not running any longer + */ +static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) +{ + cancel_delayed_work(&bcm->periodic_work0); + cancel_delayed_work(&bcm->periodic_work1); + cancel_delayed_work(&bcm->periodic_work2); + cancel_delayed_work(&bcm->periodic_work3); + flush_workqueue(bcm->workqueue); +} + +/* Setup all periodic tasks. */ +static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) +{ + INIT_WORK(&bcm->periodic_work0, bcm43xx_periodic_work0_handler, bcm); + INIT_WORK(&bcm->periodic_work1, bcm43xx_periodic_work1_handler, bcm); + INIT_WORK(&bcm->periodic_work2, bcm43xx_periodic_work2_handler, bcm); + INIT_WORK(&bcm->periodic_work3, bcm43xx_periodic_work3_handler, bcm); + + /* Periodic task 0: Delay ~15sec */ + queue_delayed_work(bcm->workqueue, &bcm->periodic_work0, + BCM43xx_PERIODIC_0_DELAY); + + /* Periodic task 1: Delay ~60sec */ + queue_delayed_work(bcm->workqueue, &bcm->periodic_work1, + BCM43xx_PERIODIC_1_DELAY); + + /* Periodic task 2: Delay ~120sec */ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && + bcm->current_core->phy->rev >= 2) { + queue_delayed_work(bcm->workqueue, &bcm->periodic_work2, + BCM43xx_PERIODIC_2_DELAY); + } + + /* Periodic task 3: Delay ~30sec */ + queue_delayed_work(bcm->workqueue, &bcm->periodic_work3, + BCM43xx_PERIODIC_3_DELAY); +} + +static void bcm43xx_security_init(struct bcm43xx_private *bcm) +{ + bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, + 0x0056) * 2; + bcm43xx_clear_keys(bcm); +} + +/* This is the opposite of bcm43xx_init_board() */ +static void bcm43xx_free_board(struct bcm43xx_private *bcm) +{ + int i, err; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + bcm->initialized = 0; + bcm->shutting_down = 1; + spin_unlock_irqrestore(&bcm->lock, flags); + + bcm43xx_periodic_tasks_delete(bcm); + + for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { + if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE)) + continue; + if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_INITIALIZED)) + continue; + + err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); + assert(err == 0); + bcm43xx_wireless_core_cleanup(bcm); + } + + bcm43xx_pctl_set_crystal(bcm, 0); + + spin_lock_irqsave(&bcm->lock, flags); + bcm->shutting_down = 0; + spin_unlock_irqrestore(&bcm->lock, flags); +} + +static int bcm43xx_init_board(struct bcm43xx_private *bcm) +{ + int i, err; + int num_80211_cores; + int connect_phy; + unsigned long flags; + + might_sleep(); + + spin_lock_irqsave(&bcm->lock, flags); + bcm->initialized = 0; + bcm->shutting_down = 0; + spin_unlock_irqrestore(&bcm->lock, flags); + + err = bcm43xx_pctl_set_crystal(bcm, 1); + if (err) + goto out; + err = bcm43xx_pctl_init(bcm); + if (err) + goto err_crystal_off; + err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST); + if (err) + goto err_crystal_off; + + tasklet_enable(&bcm->isr_tasklet); + num_80211_cores = bcm43xx_num_80211_cores(bcm); + for (i = 0; i < num_80211_cores; i++) { + err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); + assert(err != -ENODEV); + if (err) + goto err_80211_unwind; + + /* Enable the selected wireless core. + * Connect PHY only on the first core. + */ + if (!bcm43xx_core_enabled(bcm)) { + if (num_80211_cores == 1) { + connect_phy = bcm->current_core->phy->connected; + } else { + if (i == 0) + connect_phy = 1; + else + connect_phy = 0; + } + bcm43xx_wireless_core_reset(bcm, connect_phy); + } + + if (i != 0) + bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]); + + err = bcm43xx_wireless_core_init(bcm); + if (err) + goto err_80211_unwind; + + if (i != 0) { + bcm43xx_mac_suspend(bcm); + bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + bcm43xx_radio_turn_off(bcm); + } + } + bcm->active_80211_core = &bcm->core_80211[0]; + if (num_80211_cores >= 2) { + bcm43xx_switch_core(bcm, &bcm->core_80211[0]); + bcm43xx_mac_enable(bcm); + } + bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); + bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); + dprintk(KERN_INFO PFX "80211 cores initialized\n"); + bcm43xx_security_init(bcm); + bcm43xx_softmac_init(bcm); + + bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); + + spin_lock_irqsave(&bcm->lock, flags); + bcm->initialized = 1; + spin_unlock_irqrestore(&bcm->lock, flags); + + if (bcm->current_core->radio->initial_channel != 0xFF) { + bcm43xx_mac_suspend(bcm); + bcm43xx_radio_selectchannel(bcm, bcm->current_core->radio->initial_channel, 0); + bcm43xx_mac_enable(bcm); + } + bcm43xx_periodic_tasks_setup(bcm); + + assert(err == 0); +out: + return err; + +err_80211_unwind: + tasklet_disable(&bcm->isr_tasklet); + /* unwind all 80211 initialization */ + for (i = 0; i < num_80211_cores; i++) { + if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_INITIALIZED)) + continue; + bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + bcm43xx_wireless_core_cleanup(bcm); + } +err_crystal_off: + bcm43xx_pctl_set_crystal(bcm, 0); + goto out; +} + +static void bcm43xx_detach_board(struct bcm43xx_private *bcm) +{ + struct pci_dev *pci_dev = bcm->pci_dev; + int i; + + bcm43xx_chipset_detach(bcm); + /* Do _not_ access the chip, after it is detached. */ + iounmap(bcm->mmio_addr); + + pci_release_regions(pci_dev); + pci_disable_device(pci_dev); + + /* Free allocated structures/fields */ + for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { + kfree(bcm->phy[i]._lo_pairs); + if (bcm->phy[i].dyn_tssi_tbl) + kfree(bcm->phy[i].tssi2dbm); + } +} + +static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) +{ + u16 value; + u8 phy_version; + u8 phy_type; + u8 phy_rev; + int phy_rev_ok = 1; + void *p; + + value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); + + phy_version = (value & 0xF000) >> 12; + phy_type = (value & 0x0F00) >> 8; + phy_rev = (value & 0x000F); + + dprintk(KERN_INFO PFX "Detected PHY: Version: %x, Type %x, Revision %x\n", + phy_version, phy_type, phy_rev); + + switch (phy_type) { + case BCM43xx_PHYTYPE_A: + if (phy_rev >= 4) + phy_rev_ok = 0; + /*FIXME: We need to switch the ieee->modulation, etc.. flags, + * if we switch 80211 cores after init is done. + * As we do not implement on the fly switching between + * wireless cores, I will leave this as a future task. + */ + bcm->ieee->modulation = IEEE80211_OFDM_MODULATION; + bcm->ieee->mode = IEEE_A; + bcm->ieee->freq_band = IEEE80211_52GHZ_BAND | + IEEE80211_24GHZ_BAND; + break; + case BCM43xx_PHYTYPE_B: + if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7) + phy_rev_ok = 0; + bcm->ieee->modulation = IEEE80211_CCK_MODULATION; + bcm->ieee->mode = IEEE_B; + bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; + break; + case BCM43xx_PHYTYPE_G: + if (phy_rev > 7) + phy_rev_ok = 0; + bcm->ieee->modulation = IEEE80211_OFDM_MODULATION | + IEEE80211_CCK_MODULATION; + bcm->ieee->mode = IEEE_G; + bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; + break; + default: + printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n", + phy_type); + return -ENODEV; + }; + if (!phy_rev_ok) { + printk(KERN_WARNING PFX "Invalid PHY Revision %x\n", + phy_rev); + } + + bcm->current_core->phy->version = phy_version; + bcm->current_core->phy->type = phy_type; + bcm->current_core->phy->rev = phy_rev; + if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) { + p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT, + GFP_KERNEL); + if (!p) + return -ENOMEM; + bcm->current_core->phy->_lo_pairs = p; + } + + return 0; +} + +static int bcm43xx_attach_board(struct bcm43xx_private *bcm) +{ + struct pci_dev *pci_dev = bcm->pci_dev; + struct net_device *net_dev = bcm->net_dev; + int err; + int i; + void __iomem *ioaddr; + unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; + int num_80211_cores; + u32 coremask; + + err = pci_enable_device(pci_dev); + if (err) { + printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err); + err = -ENODEV; + goto out; + } + + mmio_start = pci_resource_start(pci_dev, 0); + mmio_end = pci_resource_end(pci_dev, 0); + mmio_flags = pci_resource_flags(pci_dev, 0); + mmio_len = pci_resource_len(pci_dev, 0); + + /* make sure PCI base addr is MMIO */ + if (!(mmio_flags & IORESOURCE_MEM)) { + printk(KERN_ERR PFX + "%s, region #0 not an MMIO resource, aborting\n", + pci_name(pci_dev)); + err = -ENODEV; + goto err_pci_disable; + } +//FIXME: Why is this check disabled for BCM947XX? What is the IO_SIZE there? +#ifndef CONFIG_BCM947XX + if (mmio_len != BCM43xx_IO_SIZE) { + printk(KERN_ERR PFX + "%s: invalid PCI mem region size(s), aborting\n", + pci_name(pci_dev)); + err = -ENODEV; + goto err_pci_disable; + } +#endif + + err = pci_request_regions(pci_dev, DRV_NAME); + if (err) { + printk(KERN_ERR PFX + "could not access PCI resources (%i)\n", err); + goto err_pci_disable; + } + + /* enable PCI bus-mastering */ + pci_set_master(pci_dev); + + /* ioremap MMIO region */ + ioaddr = ioremap(mmio_start, mmio_len); + if (!ioaddr) { + printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", + pci_name(pci_dev)); + err = -EIO; + goto err_pci_release; + } + + net_dev->base_addr = (unsigned long)ioaddr; + bcm->mmio_addr = ioaddr; + bcm->mmio_len = mmio_len; + + bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID, + &bcm->board_vendor); + bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID, + &bcm->board_type); + bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID, + &bcm->board_revision); + + err = bcm43xx_chipset_attach(bcm); + if (err) + goto err_iounmap; + err = bcm43xx_pctl_init(bcm); + if (err) + goto err_chipset_detach; + err = bcm43xx_probe_cores(bcm); + if (err) + goto err_chipset_detach; + + num_80211_cores = bcm43xx_num_80211_cores(bcm); + + /* Attach all IO cores to the backplane. */ + coremask = 0; + for (i = 0; i < num_80211_cores; i++) + coremask |= (1 << bcm->core_80211[i].index); + //FIXME: Also attach some non80211 cores? + err = bcm43xx_setup_backplane_pci_connection(bcm, coremask); + if (err) { + printk(KERN_ERR PFX "Backplane->PCI connection failed!\n"); + goto err_chipset_detach; + } + + err = bcm43xx_read_sprom(bcm); + if (err) + goto err_chipset_detach; + err = bcm43xx_leds_init(bcm); + if (err) + goto err_chipset_detach; + + for (i = 0; i < num_80211_cores; i++) { + err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); + assert(err != -ENODEV); + if (err) + goto err_80211_unwind; + + /* Enable the selected wireless core. + * Connect PHY only on the first core. + */ + bcm43xx_wireless_core_reset(bcm, (i == 0)); + + err = bcm43xx_read_phyinfo(bcm); + if (err && (i == 0)) + goto err_80211_unwind; + + err = bcm43xx_read_radioinfo(bcm); + if (err && (i == 0)) + goto err_80211_unwind; + + err = bcm43xx_validate_chip(bcm); + if (err && (i == 0)) + goto err_80211_unwind; + + bcm43xx_radio_turn_off(bcm); + err = bcm43xx_phy_init_tssi2dbm_table(bcm); + if (err) + goto err_80211_unwind; + bcm43xx_wireless_core_disable(bcm); + } + bcm43xx_pctl_set_crystal(bcm, 0); + + /* Set the MAC address in the networking subsystem */ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6); + else + memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6); + + bcm43xx_geo_init(bcm); + + snprintf(bcm->nick, IW_ESSID_MAX_SIZE, + "Broadcom %04X", bcm->chip_id); + + assert(err == 0); +out: + return err; + +err_80211_unwind: + for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { + kfree(bcm->phy[i]._lo_pairs); + if (bcm->phy[i].dyn_tssi_tbl) + kfree(bcm->phy[i].tssi2dbm); + } +err_chipset_detach: + bcm43xx_chipset_detach(bcm); +err_iounmap: + iounmap(bcm->mmio_addr); +err_pci_release: + pci_release_regions(pci_dev); +err_pci_disable: + pci_disable_device(pci_dev); + goto out; +} + +static inline +s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, u8 in_rssi, + int ofdm, int adjust_2053, int adjust_2050) +{ + s32 tmp; + + switch (bcm->current_core->radio->version) { + case 0x2050: + if (ofdm) { + tmp = in_rssi; + if (tmp > 127) + tmp -= 256; + tmp *= 73; + tmp /= 64; + if (adjust_2050) + tmp += 25; + else + tmp -= 3; + } else { + if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { + if (in_rssi > 63) + in_rssi = 63; + tmp = bcm->current_core->radio->nrssi_lt[in_rssi]; + tmp = 31 - tmp; + tmp *= -131; + tmp /= 128; + tmp -= 57; + } else { + tmp = in_rssi; + tmp = 31 - tmp; + tmp *= -149; + tmp /= 128; + tmp -= 68; + } + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && + adjust_2050) + tmp += 25; + } + break; + case 0x2060: + if (in_rssi > 127) + tmp = in_rssi - 256; + else + tmp = in_rssi; + break; + default: + tmp = in_rssi; + tmp -= 11; + tmp *= 103; + tmp /= 64; + if (adjust_2053) + tmp -= 109; + else + tmp -= 83; + } + + return (s8)tmp; +} + +static inline +s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, u8 in_rssi) +{ + s8 ret; + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + //TODO: Incomplete specs. + ret = 0; + } else + ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1); + + return ret; +} + +static inline +int bcm43xx_rx_packet(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct ieee80211_rx_stats *stats) +{ + int err; + + err = ieee80211_rx(bcm->ieee, skb, stats); + if (unlikely(err == 0)) + return -EINVAL; + return 0; +} + +int fastcall bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr) +{ + struct bcm43xx_plcp_hdr4 *plcp; + struct ieee80211_rx_stats stats; + struct ieee80211_hdr_4addr *wlhdr; + u16 frame_ctl; + int is_packet_for_us = 0; + int err = -EINVAL; + const u16 rxflags1 = le16_to_cpu(rxhdr->flags1); + const u16 rxflags2 = le16_to_cpu(rxhdr->flags2); + const u16 rxflags3 = le16_to_cpu(rxhdr->flags3); + const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM); + + if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) { + plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2); + /* Skip two unknown bytes and the PLCP header. */ + skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6)); + } else { + plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data); + /* Skip the PLCP header. */ + skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6)); + } + /* The SKB contains the PAYLOAD (wireless header + data) + * at this point. The FCS at the end is stripped. + */ + + memset(&stats, 0, sizeof(stats)); + stats.mac_time = le16_to_cpu(rxhdr->mactime); + stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, + !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), + !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); + stats.signal = rxhdr->signal_quality; //FIXME +//TODO stats.noise = + stats.rate = bcm43xx_plcp_get_bitrate(plcp, is_ofdm); +//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate); + stats.received_channel = bcm->current_core->radio->channel; +//TODO stats.control = + stats.mask = IEEE80211_STATMASK_SIGNAL | +//TODO IEEE80211_STATMASK_NOISE | + IEEE80211_STATMASK_RATE | + IEEE80211_STATMASK_RSSI; + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + stats.freq = IEEE80211_52GHZ_BAND; + else + stats.freq = IEEE80211_24GHZ_BAND; + stats.len = skb->len; + + bcm->stats.last_rx = jiffies; + if (bcm->ieee->iw_mode == IW_MODE_MONITOR) + return bcm43xx_rx_packet(bcm, skb, &stats); + + wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); + + switch (bcm->ieee->iw_mode) { + case IW_MODE_ADHOC: + if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || + memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || + is_broadcast_ether_addr(wlhdr->addr1) || + is_multicast_ether_addr(wlhdr->addr1) || + bcm->net_dev->flags & IFF_PROMISC) + is_packet_for_us = 1; + break; + case IW_MODE_INFRA: + default: + /* When receiving multicast or broadcast packets, filter out + the packets we send ourself; we shouldn't see those */ + if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || + memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || + (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) && + (is_broadcast_ether_addr(wlhdr->addr1) || + is_multicast_ether_addr(wlhdr->addr1) || + bcm->net_dev->flags & IFF_PROMISC))) + is_packet_for_us = 1; + break; + } + + frame_ctl = le16_to_cpu(wlhdr->frame_ctl); + + if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { + frame_ctl &= ~IEEE80211_FCTL_PROTECTED; + wlhdr->frame_ctl = cpu_to_le16(frame_ctl); + /* trim IV and ICV */ + /* FIXME: this must be done only for WEP encrypted packets */ + if (skb->len < 32) { + dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag " + "set and length < 32)\n"); + return -EINVAL; + } else { + memmove(skb->data + 4, skb->data, 24); + skb_pull(skb, 4); + skb_trim(skb, skb->len - 4); + stats.len -= 8; + } + /* do _not_ use wlhdr again without reassigning it */ + } + + switch (WLAN_FC_GET_TYPE(frame_ctl)) { + case IEEE80211_FTYPE_MGMT: + ieee80211_rx_mgt(bcm->ieee, skb->data, &stats); + break; + case IEEE80211_FTYPE_DATA: + if (is_packet_for_us) + err = bcm43xx_rx_packet(bcm, skb, &stats); + break; + case IEEE80211_FTYPE_CTL: + break; + default: + assert(0); + return -EINVAL; + } + + return err; +} + +/* Do the Hardware IO operations to send the txb */ +static inline int bcm43xx_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) +{ + int err = -ENODEV; + + if (bcm->pio_mode) + err = bcm43xx_pio_transfer_txb(bcm, txb); + else + err = bcm43xx_dma_transfer_txb(bcm, txb); + + return err; +} + +static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, + u8 channel) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_mac_suspend(bcm); + bcm43xx_radio_selectchannel(bcm, channel, 0); + bcm43xx_mac_enable(bcm); + spin_unlock_irqrestore(&bcm->lock, flags); +} + +/* set_security() callback in struct ieee80211_device */ +static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, + struct ieee80211_security *sec) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct ieee80211_security *secinfo = &bcm->ieee->sec; + unsigned long flags; + int keyidx; + + dprintk(KERN_INFO PFX "set security called\n"); + + spin_lock_irqsave(&bcm->lock, flags); + + for (keyidx = 0; keyidxflags & (1<encode_alg[keyidx] = sec->encode_alg[keyidx]; + secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx]; + memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN); + } + + if (sec->flags & SEC_ACTIVE_KEY) { + secinfo->active_key = sec->active_key; + dprintk(KERN_INFO PFX " .active_key = %d\n", sec->active_key); + } + if (sec->flags & SEC_UNICAST_GROUP) { + secinfo->unicast_uses_group = sec->unicast_uses_group; + dprintk(KERN_INFO PFX " .unicast_uses_group = %d\n", sec->unicast_uses_group); + } + if (sec->flags & SEC_LEVEL) { + secinfo->level = sec->level; + dprintk(KERN_INFO PFX " .level = %d\n", sec->level); + } + if (sec->flags & SEC_ENABLED) { + secinfo->enabled = sec->enabled; + dprintk(KERN_INFO PFX " .enabled = %d\n", sec->enabled); + } + if (sec->flags & SEC_ENCRYPT) { + secinfo->encrypt = sec->encrypt; + dprintk(KERN_INFO PFX " .encrypt = %d\n", sec->encrypt); + } + if (bcm->initialized && !bcm->ieee->host_encrypt) { + if (secinfo->enabled) { + /* upload WEP keys to hardware */ + char null_address[6] = { 0 }; + u8 algorithm = 0; + for (keyidx = 0; keyidxflags & (1<encode_alg[keyidx]) { + case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break; + case SEC_ALG_WEP: + algorithm = BCM43xx_SEC_ALGO_WEP; + if (secinfo->key_sizes[keyidx] == 13) + algorithm = BCM43xx_SEC_ALGO_WEP104; + break; + case SEC_ALG_TKIP: + FIXME(); + algorithm = BCM43xx_SEC_ALGO_TKIP; + break; + case SEC_ALG_CCMP: + FIXME(); + algorithm = BCM43xx_SEC_ALGO_AES; + break; + default: + assert(0); + break; + } + bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]); + bcm->key[keyidx].enabled = 1; + bcm->key[keyidx].algorithm = algorithm; + } + } else + bcm43xx_clear_keys(bcm); + } + spin_unlock_irqrestore(&bcm->lock, flags); +} + +/* hard_start_xmit() callback in struct ieee80211_device */ +static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, + struct net_device *net_dev, + int pri) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err = -ENODEV; + unsigned long flags; + + spin_lock_irqsave(&bcm->lock, flags); + if (likely(bcm->initialized)) + err = bcm43xx_tx(bcm, txb); + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev) +{ + return &(bcm43xx_priv(net_dev)->ieee->stats); +} + +static void bcm43xx_net_tx_timeout(struct net_device *net_dev) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + + bcm43xx_controller_restart(bcm, "TX timeout"); +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void bcm43xx_net_poll_controller(struct net_device *net_dev) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + local_irq_save(flags); + bcm43xx_interrupt_handler(bcm->irq, bcm, NULL); + local_irq_restore(flags); +} +#endif /* CONFIG_NET_POLL_CONTROLLER */ + +static int bcm43xx_net_open(struct net_device *net_dev) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + + return bcm43xx_init_board(bcm); +} + +static int bcm43xx_net_stop(struct net_device *net_dev) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + + ieee80211softmac_stop(net_dev); + bcm43xx_disable_interrupts_sync(bcm, NULL); + bcm43xx_free_board(bcm); + + return 0; +} + +static void bcm43xx_init_private(struct bcm43xx_private *bcm, + struct net_device *net_dev, + struct pci_dev *pci_dev, + struct workqueue_struct *wq) +{ + bcm->ieee = netdev_priv(net_dev); + bcm->softmac = ieee80211_priv(net_dev); + bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; + bcm->workqueue = wq; + +#ifdef DEBUG_ENABLE_MMIO_PRINT + bcm43xx_mmioprint_initial(bcm, 1); +#else + bcm43xx_mmioprint_initial(bcm, 0); +#endif +#ifdef DEBUG_ENABLE_PCILOG + bcm43xx_pciprint_initial(bcm, 1); +#else + bcm43xx_pciprint_initial(bcm, 0); +#endif + + bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; + bcm->pci_dev = pci_dev; + bcm->net_dev = net_dev; + if (modparam_bad_frames_preempt) + bcm->bad_frames_preempt = 1; + spin_lock_init(&bcm->lock); + tasklet_init(&bcm->isr_tasklet, + (void (*)(unsigned long))bcm43xx_interrupt_tasklet, + (unsigned long)bcm); + tasklet_disable_nosync(&bcm->isr_tasklet); + if (modparam_pio) { + bcm->pio_mode = 1; + } else { + if (pci_set_dma_mask(pci_dev, DMA_30BIT_MASK) == 0) { + bcm->pio_mode = 0; + } else { + printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n"); + bcm->pio_mode = 1; + } + } + bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; + + /* default to sw encryption for now */ + bcm->ieee->host_build_iv = 0; + bcm->ieee->host_encrypt = 1; + bcm->ieee->host_decrypt = 1; + + bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE; + bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr); + bcm->ieee->set_security = bcm43xx_ieee80211_set_security; + bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit; +} + +static int __devinit bcm43xx_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *net_dev; + struct bcm43xx_private *bcm; + struct workqueue_struct *wq; + int err; + +#ifdef CONFIG_BCM947XX + if ((pdev->bus->number == 0) && (pdev->device != 0x0800)) + return -ENODEV; +#endif + +#ifdef DEBUG_SINGLE_DEVICE_ONLY + if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY)) + return -ENODEV; +#endif + + net_dev = alloc_ieee80211softmac(sizeof(*bcm)); + if (!net_dev) { + printk(KERN_ERR PFX + "could not allocate ieee80211 device %s\n", + pci_name(pdev)); + err = -ENOMEM; + goto out; + } + /* initialize the net_device struct */ + SET_MODULE_OWNER(net_dev); + SET_NETDEV_DEV(net_dev, &pdev->dev); + + net_dev->open = bcm43xx_net_open; + net_dev->stop = bcm43xx_net_stop; + net_dev->get_stats = bcm43xx_net_get_stats; + net_dev->tx_timeout = bcm43xx_net_tx_timeout; +#ifdef CONFIG_NET_POLL_CONTROLLER + net_dev->poll_controller = bcm43xx_net_poll_controller; +#endif + net_dev->wireless_handlers = &bcm43xx_wx_handlers_def; + net_dev->irq = pdev->irq; + net_dev->watchdog_timeo = BCM43xx_TX_TIMEOUT; + + /* initialize the bcm43xx_private struct */ + bcm = bcm43xx_priv(net_dev); + memset(bcm, 0, sizeof(*bcm)); + wq = create_workqueue(DRV_NAME "_wq"); + if (!wq) { + err = -ENOMEM; + goto err_free_netdev; + } + bcm43xx_init_private(bcm, net_dev, pdev, wq); + + pci_set_drvdata(pdev, net_dev); + + err = bcm43xx_attach_board(bcm); + if (err) + goto err_destroy_wq; + + err = register_netdev(net_dev); + if (err) { + printk(KERN_ERR PFX "Cannot register net device, " + "aborting.\n"); + err = -ENOMEM; + goto err_detach_board; + } + + bcm43xx_debugfs_add_device(bcm); + + assert(err == 0); +out: + return err; + +err_detach_board: + bcm43xx_detach_board(bcm); +err_destroy_wq: + destroy_workqueue(wq); +err_free_netdev: + free_ieee80211softmac(net_dev); + goto out; +} + +static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) +{ + struct net_device *net_dev = pci_get_drvdata(pdev); + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + + bcm43xx_debugfs_remove_device(bcm); + unregister_netdev(net_dev); + bcm43xx_detach_board(bcm); + assert(bcm->ucode == NULL); + destroy_workqueue(bcm->workqueue); + free_ieee80211softmac(net_dev); +} + +/* Hard-reset the chip. Do not call this directly. + * Use bcm43xx_controller_restart() + */ +static void bcm43xx_chip_reset(void *_bcm) +{ + struct bcm43xx_private *bcm = _bcm; + struct net_device *net_dev = bcm->net_dev; + struct pci_dev *pci_dev = bcm->pci_dev; + struct workqueue_struct *wq = bcm->workqueue; + int err; + int was_initialized = bcm->initialized; + + netif_stop_queue(bcm->net_dev); + tasklet_disable(&bcm->isr_tasklet); + + bcm->firmware_norelease = 1; + if (was_initialized) + bcm43xx_free_board(bcm); + bcm->firmware_norelease = 0; + bcm43xx_detach_board(bcm); + bcm43xx_init_private(bcm, net_dev, pci_dev, wq); + err = bcm43xx_attach_board(bcm); + if (err) + goto failure; + if (was_initialized) { + err = bcm43xx_init_board(bcm); + if (err) + goto failure; + } + netif_wake_queue(bcm->net_dev); + printk(KERN_INFO PFX "Controller restarted\n"); + + return; +failure: + printk(KERN_ERR PFX "Controller restart failed\n"); +} + +/* Hard-reset the chip. + * This can be called from interrupt or process context. + * Make sure to _not_ re-enable device interrupts after this has been called. +*/ +void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) +{ + bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); + INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); + queue_work(bcm->workqueue, &bcm->restart_work); +} + +#ifdef CONFIG_PM + +static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *net_dev = pci_get_drvdata(pdev); + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int try_to_shutdown = 0, err; + + dprintk(KERN_INFO PFX "Suspending...\n"); + + spin_lock_irqsave(&bcm->lock, flags); + bcm->was_initialized = bcm->initialized; + if (bcm->initialized) + try_to_shutdown = 1; + spin_unlock_irqrestore(&bcm->lock, flags); + + netif_device_detach(net_dev); + if (try_to_shutdown) { + ieee80211softmac_stop(net_dev); + err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate); + if (unlikely(err)) { + dprintk(KERN_ERR PFX "Suspend failed.\n"); + return -EAGAIN; + } + bcm->firmware_norelease = 1; + bcm43xx_free_board(bcm); + bcm->firmware_norelease = 0; + } + bcm43xx_chipset_detach(bcm); + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + dprintk(KERN_INFO PFX "Device suspended.\n"); + + return 0; +} + +static int bcm43xx_resume(struct pci_dev *pdev) +{ + struct net_device *net_dev = pci_get_drvdata(pdev); + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err = 0; + + dprintk(KERN_INFO PFX "Resuming...\n"); + + pci_set_power_state(pdev, 0); + pci_enable_device(pdev); + pci_restore_state(pdev); + + bcm43xx_chipset_attach(bcm); + if (bcm->was_initialized) { + bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; + err = bcm43xx_init_board(bcm); + } + if (err) { + printk(KERN_ERR PFX "Resume failed!\n"); + return err; + } + + netif_device_attach(net_dev); + + /*FIXME: This should be handled by softmac instead. */ + schedule_work(&bcm->softmac->associnfo.work); + + dprintk(KERN_INFO PFX "Device resumed.\n"); + + return 0; +} + +#endif /* CONFIG_PM */ + +static struct pci_driver bcm43xx_pci_driver = { + .name = BCM43xx_DRIVER_NAME, + .id_table = bcm43xx_pci_tbl, + .probe = bcm43xx_init_one, + .remove = __devexit_p(bcm43xx_remove_one), +#ifdef CONFIG_PM + .suspend = bcm43xx_suspend, + .resume = bcm43xx_resume, +#endif /* CONFIG_PM */ +}; + +static int __init bcm43xx_init(void) +{ + printk(KERN_INFO BCM43xx_DRIVER_NAME "\n"); + bcm43xx_debugfs_init(); + return pci_register_driver(&bcm43xx_pci_driver); +} + +static void __exit bcm43xx_exit(void) +{ + pci_unregister_driver(&bcm43xx_pci_driver); + bcm43xx_debugfs_exit(); +} + +module_init(bcm43xx_init) +module_exit(bcm43xx_exit) + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h new file mode 100644 index 0000000000..1d3eddd314 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -0,0 +1,283 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef BCM43xx_MAIN_H_ +#define BCM43xx_MAIN_H_ + +#include "bcm43xx.h" + +#ifdef CONFIG_BCM947XX +#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0) + +static inline void e_aton(char *str, char *dest) +{ + int i = 0; + u16 *d = (u16 *) dest; + + for (;;) { + dest[i++] = (char) simple_strtoul(str, NULL, 16); + str += 2; + if (!*str++ || i == 6) + break; + } + for (i = 0; i < 3; i++) + d[i] = cpu_to_be16(d[i]); +} +#endif + + +#define _bcm43xx_declare_plcp_hdr(size) \ + struct bcm43xx_plcp_hdr##size { \ + union { \ + __le32 data; \ + __u8 raw[size]; \ + } __attribute__((__packed__)); \ + } __attribute__((__packed__)) + +/* struct bcm43xx_plcp_hdr4 */ +_bcm43xx_declare_plcp_hdr(4); +/* struct bcm430c_plcp_hdr6 */ +_bcm43xx_declare_plcp_hdr(6); + +#undef _bcm43xx_declare_plcp_hdr + + +#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] +#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) +/* Magic helper macro to pad structures. Ignore those above. It's magic. */ +#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) + + +/* Device specific TX header. To be prepended to TX frames. */ +struct bcm43xx_txhdr { + union { + struct { + u16 flags; + u16 wsec_rate; + u16 frame_control; + u16 unknown_zeroed_0; + u16 control; + unsigned char wep_iv[10]; + unsigned char unknown_wsec_tkip_data[3]; //FIXME + PAD_BYTES(3); + unsigned char mac1[6]; + u16 unknown_zeroed_1; + struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp; + u16 rts_cts_dur_fallback; + struct bcm43xx_plcp_hdr4 fallback_plcp; + u16 fallback_dur_id; + PAD_BYTES(2); + u16 cookie; + u16 unknown_scb_stuff; //FIXME + struct bcm43xx_plcp_hdr6 rts_cts_plcp; + u16 rts_cts_frame_type; + u16 rts_cts_dur; + unsigned char rts_cts_mac1[6]; + unsigned char rts_cts_mac2[6]; + PAD_BYTES(2); + struct bcm43xx_plcp_hdr6 plcp; + } __attribute__((__packed__)); + + unsigned char raw[82]; + } __attribute__((__packed__)); +} __attribute__((__packed__)); + +struct sk_buff; + +void FASTCALL(bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + const unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie)); + +/* RX header as received from the hardware. */ +struct bcm43xx_rxhdr { + /* Frame Length. Must be generated explicitely in PIO mode. */ + __le16 frame_length; + PAD_BYTES(2); + /* Flags field 1 */ + __le16 flags1; + u8 rssi; + u8 signal_quality; + PAD_BYTES(2); + /* Flags field 3 */ + __le16 flags3; + /* Flags field 2 */ + __le16 flags2; + /* Lower 16bits of the TSF at the time the frame started. */ + __le16 mactime; + PAD_BYTES(14); +} __attribute__((__packed__)); + +#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0) +/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */ +#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7) +#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14) + +#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0) +#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2) +/*FIXME: WEP related flags */ + +#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10) + +/* Transmit Status as received from the hardware. */ +struct bcm43xx_hwxmitstatus { + PAD_BYTES(4); + __le16 cookie; + u8 flags; + u8 cnt1:4, + cnt2:4; + PAD_BYTES(2); + __le16 seq; + __le16 unknown; //FIXME +} __attribute__((__packed__)); + +/* Transmit Status in CPU byteorder. */ +struct bcm43xx_xmitstatus { + u16 cookie; + u8 flags; + u8 cnt1:4, + cnt2:4; + u16 seq; + u16 unknown; //FIXME +}; + +#define BCM43xx_TXSTAT_FLAG_ACK 0x01 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x02 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x04 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x08 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x10 +#define BCM43xx_TXSTAT_FLAG_IGNORE 0x20 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80 + +struct bcm43xx_xmitstatus_queue { + struct list_head list; + struct bcm43xx_hwxmitstatus status; +}; + + +/* Lightweight function to convert a frequency (in Mhz) to a channel number. */ +static inline +u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm, + int freq) +{ + u8 channel; + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + channel = (freq - 5000) / 5; + } else { + if (freq == 2484) + channel = 14; + else + channel = (freq - 2407) / 5; + } + + return channel; +} + +/* Lightweight function to convert a channel number to a frequency (in Mhz). */ +static inline +int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm, + u8 channel) +{ + int freq; + + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + freq = 5000 + (5 * channel); + } else { + if (channel == 14) + freq = 2484; + else + freq = 2407 + (5 * channel); + } + + return freq; +} + +/* Lightweight function to check if a channel number is valid. + * Note that this does _NOT_ check for geographical restrictions! + */ +static inline +int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, + u8 channel) +{ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + if (channel <= 200) + return 1; + } else { + if (channel >= 1 && channel <= 14) + return 1; + } + + return 0; +} + +void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); +void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf); + +int FASTCALL(bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr)); + +void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, + int iw_mode); + +u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm, + u16 routing, u16 offset); +u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm, + u16 routing, u16 offset); +void bcm43xx_shm_write32(struct bcm43xx_private *bcm, + u16 routing, u16 offset, + u32 value); +void bcm43xx_shm_write16(struct bcm43xx_private *bcm, + u16 routing, u16 offset, + u16 value); + +void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm); + +int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core); + +void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); + +int bcm43xx_pci_read_config_16(struct pci_dev *pdev, u16 offset, u16 *val); +int bcm43xx_pci_read_config_32(struct pci_dev *pdev, u16 offset, u32 *val); +int bcm43xx_pci_write_config_16(struct pci_dev *pdev, int offset, u16 val); +int bcm43xx_pci_write_config_32(struct pci_dev *pdev, int offset, u32 val); + +void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); +void bcm43xx_mac_enable(struct bcm43xx_private *bcm); + +u8 bcm43xx_sprom_crc(const u16 *sprom); + +void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); + +#endif /* BCM43xx_MAIN_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c new file mode 100644 index 0000000000..41b9cd7fc9 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -0,0 +1,2122 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include + +#include "bcm43xx.h" +#include "bcm43xx_phy.h" +#include "bcm43xx_main.h" +#include "bcm43xx_radio.h" +#include "bcm43xx_ilt.h" +#include "bcm43xx_power.h" + + +static const s8 bcm43xx_tssi2dbm_b_table[] = { + 0x4D, 0x4C, 0x4B, 0x4A, + 0x4A, 0x49, 0x48, 0x47, + 0x47, 0x46, 0x45, 0x45, + 0x44, 0x43, 0x42, 0x42, + 0x41, 0x40, 0x3F, 0x3E, + 0x3D, 0x3C, 0x3B, 0x3A, + 0x39, 0x38, 0x37, 0x36, + 0x35, 0x34, 0x32, 0x31, + 0x30, 0x2F, 0x2D, 0x2C, + 0x2B, 0x29, 0x28, 0x26, + 0x25, 0x23, 0x21, 0x1F, + 0x1D, 0x1A, 0x17, 0x14, + 0x10, 0x0C, 0x06, 0x00, + -7, -7, -7, -7, + -7, -7, -7, -7, + -7, -7, -7, -7, +}; + +static const s8 bcm43xx_tssi2dbm_g_table[] = { + 77, 77, 77, 76, + 76, 76, 75, 75, + 74, 74, 73, 73, + 73, 72, 72, 71, + 71, 70, 70, 69, + 68, 68, 67, 67, + 66, 65, 65, 64, + 63, 63, 62, 61, + 60, 59, 58, 57, + 56, 55, 54, 53, + 52, 50, 49, 47, + 45, 43, 40, 37, + 33, 28, 22, 14, + 5, -7, -20, -20, + -20, -20, -20, -20, + -20, -20, -20, -20, +}; + +static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); + + +void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + + assert(irqs_disabled()); + if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) { + phy->is_locked = 0; + return; + } + if (bcm->current_core->rev < 3) { + bcm43xx_mac_suspend(bcm); + spin_lock(&phy->lock); + } else { + if (bcm->ieee->iw_mode != IW_MODE_MASTER) + bcm43xx_power_saving_ctl_bits(bcm, -1, 1); + } + phy->is_locked = 1; +} + +void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + + assert(irqs_disabled()); + if (bcm->current_core->rev < 3) { + if (phy->is_locked) { + spin_unlock(&phy->lock); + bcm43xx_mac_enable(bcm); + } + } else { + if (bcm->ieee->iw_mode != IW_MODE_MASTER) + bcm43xx_power_saving_ctl_bits(bcm, -1, -1); + } + phy->is_locked = 0; +} + +u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset) +{ + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset); + return bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_DATA); +} + +void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val) +{ + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset); + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val); +} + +void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + unsigned long flags; + + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ + if (phy->calibrated) + return; + if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) { + /* We do not want to be preempted while calibrating + * the hardware. + */ + local_irq_save(flags); + + bcm43xx_wireless_core_reset(bcm, 0); + bcm43xx_phy_initg(bcm); + bcm43xx_wireless_core_reset(bcm, 1); + + local_irq_restore(flags); + } + phy->calibrated = 1; +} + +/* Connect the PHY + * http://bcm-specs.sipsolutions.net/SetPHY + */ +int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect) +{ + u32 flags; + + if (bcm->current_core->rev < 5) { + if (connect) { + bcm->current_core->phy->connected = 1; + dprintk(KERN_INFO PFX "PHY connected\n"); + } else { + bcm->current_core->phy->connected = 0; + dprintk(KERN_INFO PFX "PHY disconnected\n"); + } + return 0; + } + + flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); + if (connect) { + if (!(flags & 0x00010000)) + return -ENODEV; + bcm->current_core->phy->connected = 1; + + flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + flags |= (0x800 << 18); + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); + dprintk(KERN_INFO PFX "PHY connected\n"); + } else { + if (!(flags & 0x00020000)) + return -ENODEV; + bcm->current_core->phy->connected = 0; + + flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + flags &= ~(0x800 << 18); + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); + dprintk(KERN_INFO PFX "PHY disconnected\n"); + } + + return 0; +} + +/* intialize B PHY power control + * as described in http://bcm-specs.sipsolutions.net/InitPowerControl + */ +static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0; + int must_reset_txpower = 0; + + assert(phy->type != BCM43xx_PHYTYPE_A); + if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && + (bcm->board_type == 0x0416)) + return; + + bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF); + bcm43xx_phy_write(bcm, 0x0028, 0x8018); + + if (phy->type == BCM43xx_PHYTYPE_G) { + if (!phy->connected) + return; + bcm43xx_phy_write(bcm, 0x047A, 0xC111); + } + if (phy->savedpctlreg != 0xFFFF) + return; + + if (phy->type == BCM43xx_PHYTYPE_B && + phy->rev >= 2 && + radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x0076, + bcm43xx_radio_read16(bcm, 0x0076) | 0x0084); + } else { + saved_batt = radio->txpower[0]; + saved_ratt = radio->txpower[1]; + saved_txctl1 = radio->txpower[2]; + if ((radio->revision >= 6) && (radio->revision <= 8) + && /*FIXME: incomplete specs for 5 < revision < 9 */ 0) + bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0); + else + bcm43xx_radio_set_txpower_bg(bcm, 0xB, 9, 0); + must_reset_txpower = 1; + } + bcm43xx_dummy_transmission(bcm); + + phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_PCTL); + + if (must_reset_txpower) + bcm43xx_radio_set_txpower_bg(bcm, saved_batt, saved_ratt, saved_txctl1); + else + bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) & 0xFF7B); + bcm43xx_radio_clear_tssi(bcm); +} + +static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 offset = 0x0000; + + if (phy->rev == 1) + offset = 0x4C00; + + bcm43xx_ilt_write16(bcm, offset, 0x00FE); + bcm43xx_ilt_write16(bcm, offset + 1, 0x000D); + bcm43xx_ilt_write16(bcm, offset + 2, 0x0013); + bcm43xx_ilt_write16(bcm, offset + 3, 0x0019); + + if (phy->rev == 1) { + bcm43xx_ilt_write16(bcm, 0x1800, 0x2710); + bcm43xx_ilt_write16(bcm, 0x1801, 0x9B83); + bcm43xx_ilt_write16(bcm, 0x1802, 0x9B83); + bcm43xx_ilt_write16(bcm, 0x1803, 0x0F8D); + bcm43xx_phy_write(bcm, 0x0455, 0x0004); + } + + bcm43xx_phy_write(bcm, 0x04A5, (bcm43xx_phy_read(bcm, 0x04A5) & 0x00FF) | 0x5700); + bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xFF80) | 0x000F); + bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xC07F) | 0x2B80); + bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xF0FF) | 0x0300); + + bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0008); + + bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFF0) | 0x0008); + bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xF0FF) | 0x0600); + bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0700); + bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0100); + + if (phy->rev == 1) + bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x0007); + + bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xFF00) | 0x001C); + bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xC0FF) | 0x0200); + bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0xFF00) | 0x001C); + bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xFF00) | 0x0020); + bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xC0FF) | 0x0200); + bcm43xx_phy_write(bcm, 0x0482, (bcm43xx_phy_read(bcm, 0x0482) & 0xFF00) | 0x002E); + bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0x00FF) | 0x1A00); + bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0xFF00) | 0x0028); + bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0x00FF) | 0x2C00); + + if (phy->rev == 1) { + bcm43xx_phy_write(bcm, 0x0430, 0x092B); + bcm43xx_phy_write(bcm, 0x041B, (bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1) | 0x0002); + } else { + bcm43xx_phy_write(bcm, 0x041B, bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1); + bcm43xx_phy_write(bcm, 0x041F, 0x287A); + bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0xFFF0) | 0x0004); + } + + if (phy->rev > 2) { + bcm43xx_phy_write(bcm, 0x0422, 0x287A); + bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0x0FFF) | 0x3000); + } + + bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0x8080) | 0x7874); + bcm43xx_phy_write(bcm, 0x048E, 0x1C00); + + if (phy->rev == 1) { + bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) & 0xF0FF) | 0x0600); + bcm43xx_phy_write(bcm, 0x048B, 0x005E); + bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xFF00) | 0x001E); + bcm43xx_phy_write(bcm, 0x048D, 0x0002); + } + + bcm43xx_ilt_write16(bcm, offset + 0x0800, 0); + bcm43xx_ilt_write16(bcm, offset + 0x0801, 7); + bcm43xx_ilt_write16(bcm, offset + 0x0802, 16); + bcm43xx_ilt_write16(bcm, offset + 0x0803, 28); +} + +static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 i; + + assert(phy->type == BCM43xx_PHYTYPE_G); + if (phy->rev == 1) { + bcm43xx_phy_write(bcm, 0x0406, 0x4F19); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xFC3F) | 0x0340); + bcm43xx_phy_write(bcm, 0x042C, 0x005A); + bcm43xx_phy_write(bcm, 0x0427, 0x001A); + + for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]); + for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]); + for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); + } else { + /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */ + bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654); + + if (phy->rev == 2) { + bcm43xx_phy_write(bcm, 0x04C0, 0x1861); + bcm43xx_phy_write(bcm, 0x04C1, 0x0271); + } else if (phy->rev > 2) { + bcm43xx_phy_write(bcm, 0x04C0, 0x0098); + bcm43xx_phy_write(bcm, 0x04C1, 0x0070); + bcm43xx_phy_write(bcm, 0x04C9, 0x0080); + } + bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800); + + for (i = 0; i < 64; i++) + bcm43xx_ilt_write16(bcm, 0x4000 + i, i); + for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]); + } + + if (phy->rev <= 2) + for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]); + else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200)) + for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]); + else + for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]); + + if (phy->rev == 2) + for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); + else if ((phy->rev > 2) && (phy->rev <= 7)) + for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]); + + if (phy->rev == 1) { + for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); + for (i = 0; i < 4; i++) { + bcm43xx_ilt_write16(bcm, 0x5404 + i, 0x0020); + bcm43xx_ilt_write16(bcm, 0x5408 + i, 0x0020); + bcm43xx_ilt_write16(bcm, 0x540C + i, 0x0020); + bcm43xx_ilt_write16(bcm, 0x5410 + i, 0x0020); + } + bcm43xx_phy_agcsetup(bcm); + + if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && + (bcm->board_type == 0x0416) && + (bcm->board_revision == 0x0017)) + return; + + bcm43xx_ilt_write16(bcm, 0x5001, 0x0002); + bcm43xx_ilt_write16(bcm, 0x5002, 0x0001); + } else { + for (i = 0; i <= 0x2F; i++) + bcm43xx_ilt_write16(bcm, 0x1000 + i, 0x0820); + bcm43xx_phy_agcsetup(bcm); + bcm43xx_phy_read(bcm, 0x0400); /* dummy read */ + bcm43xx_phy_write(bcm, 0x0403, 0x1000); + bcm43xx_ilt_write16(bcm, 0x3C02, 0x000F); + bcm43xx_ilt_write16(bcm, 0x3C03, 0x0014); + + if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && + (bcm->board_type == 0x0416) && + (bcm->board_revision == 0x0017)) + return; + + bcm43xx_ilt_write16(bcm, 0x0401, 0x0002); + bcm43xx_ilt_write16(bcm, 0x0402, 0x0001); + } +} + +/* Initialize the noisescaletable for APHY */ +static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + int i; + + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400); + for (i = 0; i < 12; i++) { + if (phy->rev == 2) + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767); + else + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323); + } + if (phy->rev == 2) + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6700); + else + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2300); + for (i = 0; i < 11; i++) { + if (phy->rev == 2) + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767); + else + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323); + } + if (phy->rev == 2) + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0067); + else + bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0023); +} + +static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) +{ + u16 i; + + assert(bcm->current_core->phy->type == BCM43xx_PHYTYPE_A); + switch (bcm->current_core->phy->rev) { + case 2: + bcm43xx_phy_write(bcm, 0x008E, 0x3800); + bcm43xx_phy_write(bcm, 0x0035, 0x03FF); + bcm43xx_phy_write(bcm, 0x0036, 0x0400); + + bcm43xx_ilt_write16(bcm, 0x3807, 0x0051); + + bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); + bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); + bcm43xx_ilt_write16(bcm, 0x3C0C, 0x07BF); + bcm43xx_radio_write16(bcm, 0x0002, 0x07BF); + + bcm43xx_phy_write(bcm, 0x0024, 0x4680); + bcm43xx_phy_write(bcm, 0x0020, 0x0003); + bcm43xx_phy_write(bcm, 0x001D, 0x0F40); + bcm43xx_phy_write(bcm, 0x001F, 0x1C00); + + bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400); + bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF); + bcm43xx_phy_write(bcm, 0x008E, 0x58C1); + + bcm43xx_ilt_write16(bcm, 0x0803, 0x000F); + bcm43xx_ilt_write16(bcm, 0x0804, 0x001F); + bcm43xx_ilt_write16(bcm, 0x0805, 0x002A); + bcm43xx_ilt_write16(bcm, 0x0805, 0x0030); + bcm43xx_ilt_write16(bcm, 0x0807, 0x003A); + + bcm43xx_ilt_write16(bcm, 0x0000, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0001, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0002, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0003, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0004, 0x0015); + bcm43xx_ilt_write16(bcm, 0x0005, 0x0015); + bcm43xx_ilt_write16(bcm, 0x0006, 0x0019); + + bcm43xx_ilt_write16(bcm, 0x0404, 0x0003); + bcm43xx_ilt_write16(bcm, 0x0405, 0x0003); + bcm43xx_ilt_write16(bcm, 0x0406, 0x0007); + + for (i = 0; i < 16; i++) + bcm43xx_ilt_write16(bcm, 0x4000 + i, (0x8 + i) & 0x000F); + + bcm43xx_ilt_write16(bcm, 0x3003, 0x1044); + bcm43xx_ilt_write16(bcm, 0x3004, 0x7201); + bcm43xx_ilt_write16(bcm, 0x3006, 0x0040); + bcm43xx_ilt_write16(bcm, 0x3001, (bcm43xx_ilt_read16(bcm, 0x3001) & 0x0010) | 0x0008); + + for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]); + for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]); + for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); + bcm43xx_phy_init_noisescaletbl(bcm); + for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); + break; + case 3: + for (i = 0; i < 64; i++) + bcm43xx_ilt_write16(bcm, 0x4000 + i, i); + + bcm43xx_ilt_write16(bcm, 0x3807, 0x0051); + + bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); + bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); + bcm43xx_radio_write16(bcm, 0x0002, 0x07BF); + + bcm43xx_phy_write(bcm, 0x0024, 0x4680); + bcm43xx_phy_write(bcm, 0x0020, 0x0003); + bcm43xx_phy_write(bcm, 0x001D, 0x0F40); + bcm43xx_phy_write(bcm, 0x001F, 0x1C00); + bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400); + + bcm43xx_ilt_write16(bcm, 0x3001, (bcm43xx_ilt_read16(bcm, 0x3001) & 0x0010) | 0x0008); + for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]); + bcm43xx_phy_init_noisescaletbl(bcm); + for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) + bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); + + bcm43xx_phy_write(bcm, 0x0003, 0x1808); + + bcm43xx_ilt_write16(bcm, 0x0803, 0x000F); + bcm43xx_ilt_write16(bcm, 0x0804, 0x001F); + bcm43xx_ilt_write16(bcm, 0x0805, 0x002A); + bcm43xx_ilt_write16(bcm, 0x0805, 0x0030); + bcm43xx_ilt_write16(bcm, 0x0807, 0x003A); + + bcm43xx_ilt_write16(bcm, 0x0000, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0001, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0002, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0003, 0x0013); + bcm43xx_ilt_write16(bcm, 0x0004, 0x0015); + bcm43xx_ilt_write16(bcm, 0x0005, 0x0015); + bcm43xx_ilt_write16(bcm, 0x0006, 0x0019); + + bcm43xx_ilt_write16(bcm, 0x0404, 0x0003); + bcm43xx_ilt_write16(bcm, 0x0405, 0x0003); + bcm43xx_ilt_write16(bcm, 0x0406, 0x0007); + + bcm43xx_ilt_write16(bcm, 0x3C02, 0x000F); + bcm43xx_ilt_write16(bcm, 0x3C03, 0x0014); + break; + default: + assert(0); + } +} + +/* Initialize APHY. This is also called for the GPHY in some cases. */ +static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 tval; + + if (phy->type == BCM43xx_PHYTYPE_A) { + bcm43xx_phy_setupa(bcm); + } else { + bcm43xx_phy_setupg(bcm); + if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) + bcm43xx_phy_write(bcm, 0x046E, 0x03CF); + return; + } + + bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS, + (bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340); + bcm43xx_phy_write(bcm, 0x0034, 0x0001); + + TODO();//TODO: RSSI AGC + bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) | (1 << 14)); + bcm43xx_radio_init2060(bcm); + + if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) + && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) { + if (bcm->current_core->radio->lofcal == 0xFFFF) { + TODO();//TODO: LOF Cal + bcm43xx_radio_set_tx_iq(bcm); + } else + bcm43xx_radio_write16(bcm, 0x001E, bcm->current_core->radio->lofcal); + } + + bcm43xx_phy_write(bcm, 0x007A, 0xF111); + + if (phy->savedpctlreg == 0xFFFF) { + bcm43xx_radio_write16(bcm, 0x0019, 0x0000); + bcm43xx_radio_write16(bcm, 0x0017, 0x0020); + + tval = bcm43xx_ilt_read16(bcm, 0x3001); + if (phy->rev == 1) { + bcm43xx_ilt_write16(bcm, 0x3001, + (bcm43xx_ilt_read16(bcm, 0x3001) & 0xFF87) + | 0x0058); + } else { + bcm43xx_ilt_write16(bcm, 0x3001, + (bcm43xx_ilt_read16(bcm, 0x3001) & 0xFFC3) + | 0x002C); + } + bcm43xx_dummy_transmission(bcm); + phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL); + bcm43xx_ilt_write16(bcm, 0x3001, tval); + + bcm43xx_radio_set_txpower_a(bcm, 0x0018); + } + bcm43xx_radio_clear_tssi(bcm); +} + +static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 offset, val; + + bcm43xx_write16(bcm, 0x03EC, 0x3F22); + bcm43xx_phy_write(bcm, 0x0020, 0x301C); + bcm43xx_phy_write(bcm, 0x0026, 0x0000); + bcm43xx_phy_write(bcm, 0x0030, 0x00C6); + bcm43xx_phy_write(bcm, 0x0088, 0x3E00); + val = 0x3C3D; + for (offset = 0x0089; offset < 0x00A7; offset++) { + bcm43xx_phy_write(bcm, offset, val); + val -= 0x0202; + } + bcm43xx_phy_write(bcm, 0x03E4, 0x3000); + if (radio->channel == 0xFF) + bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); + else + bcm43xx_radio_selectchannel(bcm, radio->channel, 0); + if (radio->version != 0x2050) { + bcm43xx_radio_write16(bcm, 0x0075, 0x0080); + bcm43xx_radio_write16(bcm, 0x0079, 0x0081); + } + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x0050, 0x0023); + if (radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x005A, 0x0070); + bcm43xx_radio_write16(bcm, 0x005B, 0x007B); + bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); + bcm43xx_radio_write16(bcm, 0x007A, 0x000F); + bcm43xx_phy_write(bcm, 0x0038, 0x0677); + bcm43xx_radio_init2050(bcm); + } + bcm43xx_phy_write(bcm, 0x0014, 0x0080); + bcm43xx_phy_write(bcm, 0x0032, 0x00CA); + bcm43xx_phy_write(bcm, 0x0032, 0x00CC); + bcm43xx_phy_write(bcm, 0x0035, 0x07C2); + bcm43xx_phy_lo_b_measure(bcm); + bcm43xx_phy_write(bcm, 0x0026, 0xCC00); + if (radio->version != 0x2050) + bcm43xx_phy_write(bcm, 0x0026, 0xCE00); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1000); + bcm43xx_phy_write(bcm, 0x002A, 0x88A3); + if (radio->version != 0x2050) + bcm43xx_phy_write(bcm, 0x002A, 0x88C2); + bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); + bcm43xx_phy_init_pctl(bcm); +} + +static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 offset, val; + + bcm43xx_write16(bcm, 0x03EC, 0x3F22); + bcm43xx_phy_write(bcm, 0x0020, 0x301C); + bcm43xx_phy_write(bcm, 0x0026, 0x0000); + bcm43xx_phy_write(bcm, 0x0030, 0x00C6); + bcm43xx_phy_write(bcm, 0x0088, 0x3E00); + val = 0x3C3D; + for (offset = 0x0089; offset < 0x00A7; offset++) { + bcm43xx_phy_write(bcm, offset, val); + val -= 0x0202; + } + bcm43xx_phy_write(bcm, 0x03E4, 0x3000); + if (radio->channel == 0xFF) + bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); + else + bcm43xx_radio_selectchannel(bcm, radio->channel, 0); + if (radio->version != 0x2050) { + bcm43xx_radio_write16(bcm, 0x0075, 0x0080); + bcm43xx_radio_write16(bcm, 0x0079, 0x0081); + } + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x0050, 0x0023); + if (radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x005A, 0x0070); + bcm43xx_radio_write16(bcm, 0x005B, 0x007B); + bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); + bcm43xx_radio_write16(bcm, 0x007A, 0x000F); + bcm43xx_phy_write(bcm, 0x0038, 0x0677); + bcm43xx_radio_init2050(bcm); + } + bcm43xx_phy_write(bcm, 0x0014, 0x0080); + bcm43xx_phy_write(bcm, 0x0032, 0x00CA); + if (radio->version == 0x2050) + bcm43xx_phy_write(bcm, 0x0032, 0x00E0); + bcm43xx_phy_write(bcm, 0x0035, 0x07C2); + + bcm43xx_phy_lo_b_measure(bcm); + + bcm43xx_phy_write(bcm, 0x0026, 0xCC00); + if (radio->version == 0x2050) + bcm43xx_phy_write(bcm, 0x0026, 0xCE00); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1100); + bcm43xx_phy_write(bcm, 0x002A, 0x88A3); + if (radio->version == 0x2050) + bcm43xx_phy_write(bcm, 0x002A, 0x88C2); + bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); + if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { + bcm43xx_calc_nrssi_slope(bcm); + bcm43xx_calc_nrssi_threshold(bcm); + } + bcm43xx_phy_init_pctl(bcm); +} + +static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 offset; + + if (phy->version == 1 && + radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) + | 0x0050); + } + if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) && + (bcm->board_type != 0x0416)) { + for (offset = 0x00A8 ; offset < 0x00C7; offset++) { + bcm43xx_phy_write(bcm, offset, + (bcm43xx_phy_read(bcm, offset) + 0x2020) + & 0x3F3F); + } + } + bcm43xx_phy_write(bcm, 0x0035, + (bcm43xx_phy_read(bcm, 0x0035) & 0xF0FF) + | 0x0700); + if (radio->version == 0x2050) + bcm43xx_phy_write(bcm, 0x0038, 0x0667); + + if (phy->connected) { + if (radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) + | 0x0020); + bcm43xx_radio_write16(bcm, 0x0051, + bcm43xx_radio_read16(bcm, 0x0051) + | 0x0004); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, 0x0000); + + bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x0100); + bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000); + + bcm43xx_phy_write(bcm, 0x001C, 0x186A); + + bcm43xx_phy_write(bcm, 0x0013, (bcm43xx_phy_read(bcm, 0x0013) & 0x00FF) | 0x1900); + bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFFC0) | 0x0064); + bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) & 0xFF80) | 0x000A); + } + + if (bcm->bad_frames_preempt) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11)); + } + + if (phy->version == 1 && radio->version == 0x2050) { + bcm43xx_phy_write(bcm, 0x0026, 0xCE00); + bcm43xx_phy_write(bcm, 0x0021, 0x3763); + bcm43xx_phy_write(bcm, 0x0022, 0x1BC3); + bcm43xx_phy_write(bcm, 0x0023, 0x06F9); + bcm43xx_phy_write(bcm, 0x0024, 0x037E); + } else + bcm43xx_phy_write(bcm, 0x0026, 0xCC00); + bcm43xx_phy_write(bcm, 0x0030, 0x00C6); + bcm43xx_write16(bcm, 0x03EC, 0x3F22); + + if (phy->version == 1 && radio->version == 0x2050) + bcm43xx_phy_write(bcm, 0x0020, 0x3E1C); + else + bcm43xx_phy_write(bcm, 0x0020, 0x301C); + + if (phy->version == 0) + bcm43xx_write16(bcm, 0x03E4, 0x3000); + + /* Force to channel 7, even if not supported. */ + bcm43xx_radio_selectchannel(bcm, 7, 0); + + if (radio->version != 0x2050) { + bcm43xx_radio_write16(bcm, 0x0075, 0x0080); + bcm43xx_radio_write16(bcm, 0x0079, 0x0081); + } + + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x0050, 0x0023); + + if (radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x005A, 0x0070); + } + + bcm43xx_radio_write16(bcm, 0x005B, 0x007B); + bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); + + bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007); + + bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); + + bcm43xx_phy_write(bcm, 0x0014, 0x0080); + bcm43xx_phy_write(bcm, 0x0032, 0x00CA); + bcm43xx_phy_write(bcm, 0x88A3, 0x002A); + + bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); + + if (radio->version == 0x2050) + bcm43xx_radio_write16(bcm, 0x005D, 0x000D); + + bcm43xx_write16(bcm, 0x03E4, (bcm43xx_read16(bcm, 0x03E4) & 0xFFC0) | 0x0004); +} + +static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 offset, val; + + bcm43xx_phy_write(bcm, 0x003E, 0x817A); + bcm43xx_radio_write16(bcm, 0x007A, + (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058)); + if ((radio->manufact == 0x17F) && + (radio->version == 0x2050) && + (radio->revision == 3 || + radio->revision == 4 || + radio->revision == 5)) { + bcm43xx_radio_write16(bcm, 0x0051, 0x001F); + bcm43xx_radio_write16(bcm, 0x0052, 0x0040); + bcm43xx_radio_write16(bcm, 0x0053, 0x005B); + bcm43xx_radio_write16(bcm, 0x0054, 0x0098); + bcm43xx_radio_write16(bcm, 0x005A, 0x0088); + bcm43xx_radio_write16(bcm, 0x005B, 0x0088); + bcm43xx_radio_write16(bcm, 0x005D, 0x0088); + bcm43xx_radio_write16(bcm, 0x005E, 0x0088); + bcm43xx_radio_write16(bcm, 0x007D, 0x0088); + } + if ((radio->manufact == 0x17F) && + (radio->version == 0x2050) && + (radio->revision == 6)) { + bcm43xx_radio_write16(bcm, 0x0051, 0x0000); + bcm43xx_radio_write16(bcm, 0x0052, 0x0040); + bcm43xx_radio_write16(bcm, 0x0053, 0x00B7); + bcm43xx_radio_write16(bcm, 0x0054, 0x0098); + bcm43xx_radio_write16(bcm, 0x005A, 0x0088); + bcm43xx_radio_write16(bcm, 0x005B, 0x008B); + bcm43xx_radio_write16(bcm, 0x005C, 0x00B5); + bcm43xx_radio_write16(bcm, 0x005D, 0x0088); + bcm43xx_radio_write16(bcm, 0x005E, 0x0088); + bcm43xx_radio_write16(bcm, 0x007D, 0x0088); + bcm43xx_radio_write16(bcm, 0x007C, 0x0001); + bcm43xx_radio_write16(bcm, 0x007E, 0x0008); + } + if ((radio->manufact == 0x17F) && + (radio->version == 0x2050) && + (radio->revision == 7)) { + bcm43xx_radio_write16(bcm, 0x0051, 0x0000); + bcm43xx_radio_write16(bcm, 0x0052, 0x0040); + bcm43xx_radio_write16(bcm, 0x0053, 0x00B7); + bcm43xx_radio_write16(bcm, 0x0054, 0x0098); + bcm43xx_radio_write16(bcm, 0x005A, 0x0088); + bcm43xx_radio_write16(bcm, 0x005B, 0x00A8); + bcm43xx_radio_write16(bcm, 0x005C, 0x0075); + bcm43xx_radio_write16(bcm, 0x005D, 0x00F5); + bcm43xx_radio_write16(bcm, 0x005E, 0x00B8); + bcm43xx_radio_write16(bcm, 0x007D, 0x00E8); + bcm43xx_radio_write16(bcm, 0x007C, 0x0001); + bcm43xx_radio_write16(bcm, 0x007E, 0x0008); + bcm43xx_radio_write16(bcm, 0x007B, 0x0000); + } + if ((radio->manufact == 0x17F) && + (radio->version == 0x2050) && + (radio->revision == 8)) { + bcm43xx_radio_write16(bcm, 0x0051, 0x0000); + bcm43xx_radio_write16(bcm, 0x0052, 0x0040); + bcm43xx_radio_write16(bcm, 0x0053, 0x00B7); + bcm43xx_radio_write16(bcm, 0x0054, 0x0098); + bcm43xx_radio_write16(bcm, 0x005A, 0x0088); + bcm43xx_radio_write16(bcm, 0x005B, 0x006B); + bcm43xx_radio_write16(bcm, 0x005C, 0x000F); + if (bcm->sprom.boardflags & 0x8000) { + bcm43xx_radio_write16(bcm, 0x005D, 0x00FA); + bcm43xx_radio_write16(bcm, 0x005E, 0x00D8); + } else { + bcm43xx_radio_write16(bcm, 0x005D, 0x00F5); + bcm43xx_radio_write16(bcm, 0x005E, 0x00B8); + } + bcm43xx_radio_write16(bcm, 0x0073, 0x0003); + bcm43xx_radio_write16(bcm, 0x007D, 0x00A8); + bcm43xx_radio_write16(bcm, 0x007C, 0x0001); + bcm43xx_radio_write16(bcm, 0x007E, 0x0008); + } + val = 0x1E1F; + for (offset = 0x0088; offset < 0x0098; offset++) { + bcm43xx_phy_write(bcm, offset, val); + val -= 0x0202; + } + val = 0x3E3F; + for (offset = 0x0098; offset < 0x00A8; offset++) { + bcm43xx_phy_write(bcm, offset, val); + val -= 0x0202; + } + val = 0x2120; + for (offset = 0x00A8; offset < 0x00C8; offset++) { + bcm43xx_phy_write(bcm, offset, (val & 0x3F3F)); + val += 0x0202; + } + if (phy->type == BCM43xx_PHYTYPE_G) { + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0020); + bcm43xx_radio_write16(bcm, 0x0051, + bcm43xx_radio_read16(bcm, 0x0051) | 0x0004); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) | 0x0100); + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) | 0x2000); + } + + /* Force to channel 7, even if not supported. */ + bcm43xx_radio_selectchannel(bcm, 7, 0); + + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x0050, 0x0023); + udelay(40); + bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) | 0x0002)); + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + if ((bcm->current_core->radio->manufact == 0x17F) && + (bcm->current_core->radio->version == 0x2050) && + (bcm->current_core->radio->revision == 2)) { + bcm43xx_radio_write16(bcm, 0x0050, 0x0020); + bcm43xx_radio_write16(bcm, 0x005A, 0x0070); + bcm43xx_radio_write16(bcm, 0x005B, 0x007B); + bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); + } + bcm43xx_radio_write16(bcm, 0x007A, + (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007); + + bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); + + bcm43xx_phy_write(bcm, 0x0014, 0x0200); + if (radio->version == 0x2050){ + if (radio->revision == 3 || + radio->revision == 4 || + radio->revision == 5) + bcm43xx_phy_write(bcm, 0x002A, 0x8AC0); + else + bcm43xx_phy_write(bcm, 0x002A, 0x88C2); + } + bcm43xx_phy_write(bcm, 0x0038, 0x0668); + bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); + if (radio->version == 0x2050) { + if (radio->revision == 3 || + radio->revision == 4 || + radio->revision == 5) + bcm43xx_phy_write(bcm, 0x005D, bcm43xx_phy_read(bcm, 0x005D) | 0x0003); + else if (radio->revision <= 2) + bcm43xx_radio_write16(bcm, 0x005D, 0x000D); + } + + if (phy->rev == 4) + bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004); + else + bcm43xx_write16(bcm, 0x03E4, 0x0009); + if (phy->type == BCM43xx_PHYTYPE_B) { + bcm43xx_write16(bcm, 0x03E6, 0x8140); + bcm43xx_phy_write(bcm, 0x0016, 0x5410); + bcm43xx_phy_write(bcm, 0x0017, 0xA820); + bcm43xx_phy_write(bcm, 0x0007, 0x0062); + TODO();//TODO: calibrate stuff. + bcm43xx_phy_init_pctl(bcm); + } else + bcm43xx_write16(bcm, 0x03E6, 0x0); +} + +static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 tmp; + + if (phy->rev == 1) + bcm43xx_phy_initb5(bcm); + else if (phy->rev >= 2 && phy->rev <= 7) + bcm43xx_phy_initb6(bcm); + if (phy->rev >= 2 || phy->connected) + bcm43xx_phy_inita(bcm); + + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0814, 0x0000); + bcm43xx_phy_write(bcm, 0x0815, 0x0000); + if (phy->rev == 2) + bcm43xx_phy_write(bcm, 0x0811, 0x0000); + else if (phy->rev >= 3) + bcm43xx_phy_write(bcm, 0x0811, 0x0400); + bcm43xx_phy_write(bcm, 0x0015, 0x00C0); + tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; + if (tmp == 3) { + bcm43xx_phy_write(bcm, 0x04C2, 0x1816); + bcm43xx_phy_write(bcm, 0x04C3, 0x8606); + } else if (tmp == 4 || tmp == 5) { + bcm43xx_phy_write(bcm, 0x04C2, 0x1816); + bcm43xx_phy_write(bcm, 0x04C3, 0x8006); + bcm43xx_phy_write(bcm, 0x04CC, (bcm43xx_phy_read(bcm, 0x04CC) + & 0x00FF) | 0x1F00); + } + } + if (radio->revision <= 3 && phy->connected) + bcm43xx_phy_write(bcm, 0x047E, 0x0078); + if (radio->revision >= 6 && radio->revision <= 8) { + bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080); + bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004); + } + if (radio->initval == 0xFFFF) { + radio->initval = bcm43xx_radio_init2050(bcm); + bcm43xx_phy_lo_g_measure(bcm); + } else { + bcm43xx_radio_write16(bcm, 0x0078, radio->initval); + bcm43xx_radio_write16(bcm, 0x0052, + (bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0) + | radio->txpower[3]); + } + + if (phy->connected) { + bcm43xx_phy_lo_adjust(bcm, 0); + bcm43xx_phy_write(bcm, 0x080F, 0x8078); + + if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) + bcm43xx_phy_write(bcm, 0x002E, 0x807F); + else + bcm43xx_phy_write(bcm, 0x002E, 0x8075); + + if (phy->rev < 2) + bcm43xx_phy_write(bcm, 0x002F, 0x0101); + else + bcm43xx_phy_write(bcm, 0x002F, 0x0202); + } + + if ((bcm->sprom.boardflags & BCM43xx_BFL_RSSI) == 0) { + FIXME();//FIXME: 0x7FFFFFFF should be 16-bit ! + bcm43xx_nrssi_hw_update(bcm, (u16)0x7FFFFFFF); + bcm43xx_calc_nrssi_threshold(bcm); + } else if (phy->connected) { + if (radio->nrssi[0] == -1000) { + assert(radio->nrssi[1] == -1000); + bcm43xx_calc_nrssi_slope(bcm); + } else + bcm43xx_calc_nrssi_threshold(bcm); + } + bcm43xx_phy_init_pctl(bcm); +} + +static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) +{ + int i; + u16 ret = 0; + + for (i = 0; i < 10; i++){ + bcm43xx_phy_write(bcm, 0x0015, 0xAFA0); + udelay(1); + bcm43xx_phy_write(bcm, 0x0015, 0xEFA0); + udelay(10); + bcm43xx_phy_write(bcm, 0x0015, 0xFFA0); + udelay(40); + ret += bcm43xx_phy_read(bcm, 0x002C); + } + + return ret; +} + +void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 regstack[12] = { 0 }; + u16 mls; + u16 fval; + int i, j; + + regstack[0] = bcm43xx_phy_read(bcm, 0x0015); + regstack[1] = bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0; + + if (radio->version == 0x2053) { + regstack[2] = bcm43xx_phy_read(bcm, 0x000A); + regstack[3] = bcm43xx_phy_read(bcm, 0x002A); + regstack[4] = bcm43xx_phy_read(bcm, 0x0035); + regstack[5] = bcm43xx_phy_read(bcm, 0x0003); + regstack[6] = bcm43xx_phy_read(bcm, 0x0001); + regstack[7] = bcm43xx_phy_read(bcm, 0x0030); + + regstack[8] = bcm43xx_radio_read16(bcm, 0x0043); + regstack[9] = bcm43xx_radio_read16(bcm, 0x007A); + regstack[10] = bcm43xx_read16(bcm, 0x03EC); + regstack[11] = bcm43xx_radio_read16(bcm, 0x0052) & 0x00F0; + + bcm43xx_phy_write(bcm, 0x0030, 0x00FF); + bcm43xx_write16(bcm, 0x03EC, 0x3F3F); + bcm43xx_phy_write(bcm, 0x0035, regstack[4] & 0xFF7F); + bcm43xx_radio_write16(bcm, 0x007A, regstack[9] & 0xFFF0); + } + bcm43xx_phy_write(bcm, 0x0015, 0xB000); + bcm43xx_phy_write(bcm, 0x002B, 0x0004); + + if (radio->version == 0x2053) { + bcm43xx_phy_write(bcm, 0x002B, 0x0203); + bcm43xx_phy_write(bcm, 0x002A, 0x08A3); + } + + phy->minlowsig[0] = 0xFFFF; + + for (i = 0; i < 4; i++) { + bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i); + bcm43xx_phy_lo_b_r15_loop(bcm); + } + for (i = 0; i < 10; i++) { + bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i); + mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10; + if (mls < phy->minlowsig[0]) { + phy->minlowsig[0] = mls; + phy->minlowsigpos[0] = i; + } + } + bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | phy->minlowsigpos[0]); + + phy->minlowsig[1] = 0xFFFF; + + for (i = -4; i < 5; i += 2) { + for (j = -4; j < 5; j += 2) { + if (j < 0) + fval = (0x0100 * i) + j + 0x0100; + else + fval = (0x0100 * i) + j; + bcm43xx_phy_write(bcm, 0x002F, fval); + mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10; + if (mls < phy->minlowsig[1]) { + phy->minlowsig[1] = mls; + phy->minlowsigpos[1] = fval; + } + } + } + phy->minlowsigpos[1] += 0x0101; + + bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]); + if (radio->version == 2053) { + bcm43xx_phy_write(bcm, 0x000A, regstack[2]); + bcm43xx_phy_write(bcm, 0x002A, regstack[3]); + bcm43xx_phy_write(bcm, 0x0035, regstack[4]); + bcm43xx_phy_write(bcm, 0x0003, regstack[5]); + bcm43xx_phy_write(bcm, 0x0001, regstack[6]); + bcm43xx_phy_write(bcm, 0x0030, regstack[7]); + + bcm43xx_radio_write16(bcm, 0x0043, regstack[8]); + bcm43xx_radio_write16(bcm, 0x007A, regstack[9]); + + bcm43xx_radio_write16(bcm, 0x0052, + (bcm43xx_radio_read16(bcm, 0x0052) & 0x000F) + | regstack[11]); + + bcm43xx_write16(bcm, 0x03EC, regstack[10]); + } + bcm43xx_phy_write(bcm, 0x0015, regstack[0]); +} + +static inline +u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) +{ + if (bcm->current_core->phy->connected) { + bcm43xx_phy_write(bcm, 0x15, 0xE300); + control <<= 8; + bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0); + udelay(5); + bcm43xx_phy_write(bcm, 0x0812, control | 0x00B2); + udelay(2); + bcm43xx_phy_write(bcm, 0x0812, control | 0x00B3); + udelay(4); + bcm43xx_phy_write(bcm, 0x0015, 0xF300); + udelay(8); + } else { + bcm43xx_phy_write(bcm, 0x0015, control | 0xEFA0); + udelay(2); + bcm43xx_phy_write(bcm, 0x0015, control | 0xEFE0); + udelay(4); + bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0); + udelay(8); + } + + return bcm43xx_phy_read(bcm, 0x002D); +} + +static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control) +{ + int i; + u32 ret = 0; + + for (i = 0; i < 8; i++) + ret += bcm43xx_phy_lo_g_deviation_subval(bcm, control); + + return ret; +} + +/* Write the LocalOscillator CONTROL */ +static inline +void bcm43xx_lo_write(struct bcm43xx_private *bcm, + struct bcm43xx_lopair *pair) +{ + u16 value; + + value = (u8)(pair->low); + value |= ((u8)(pair->high)) << 8; + +#ifdef CONFIG_BCM43XX_DEBUG + /* Sanity check. */ + if (pair->low < -8 || pair->low > 8 || + pair->high < -8 || pair->high > 8) { + printk(KERN_WARNING PFX + "WARNING: Writing invalid LOpair " + "(low: %d, high: %d, index: %lu)\n", + pair->low, pair->high, + (unsigned long)(pair - bcm->current_core->phy->_lo_pairs)); + dump_stack(); + } +#endif + + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, value); +} + +static inline +struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm, + u16 baseband_attenuation, + u16 radio_attenuation, + u16 tx) +{ + static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 }; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + + if (baseband_attenuation > 6) + baseband_attenuation = 6; + assert(radio_attenuation < 10); + assert(tx == 0 || tx == 3); + + if (tx == 3) { + return bcm43xx_get_lopair(phy, + radio_attenuation, + baseband_attenuation); + } + return bcm43xx_get_lopair(phy, dict[radio_attenuation], baseband_attenuation); +} + +static inline +struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm) +{ + return bcm43xx_find_lopair(bcm, + bcm->current_core->radio->txpower[0], + bcm->current_core->radio->txpower[1], + bcm->current_core->radio->txpower[2]); +} + +/* Adjust B/G LO */ +void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed) +{ + struct bcm43xx_lopair *pair; + + if (fixed) { + /* Use fixed values. Only for initialization. */ + pair = bcm43xx_find_lopair(bcm, 2, 3, 0); + } else + pair = bcm43xx_current_lopair(bcm); + bcm43xx_lo_write(bcm, pair); +} + +static inline +void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) +{ + u16 txctl2 = 0, i; + u32 smallest, tmp; + + bcm43xx_radio_write16(bcm, 0x0052, 0x0000); + udelay(10); + smallest = bcm43xx_phy_lo_g_singledeviation(bcm, 0); + for (i = 0; i < 16; i++) { + bcm43xx_radio_write16(bcm, 0x0052, i); + udelay(10); + tmp = bcm43xx_phy_lo_g_singledeviation(bcm, 0); + if (tmp < smallest) { + smallest = tmp; + txctl2 = i; + } + } + bcm->current_core->radio->txpower[3] = txctl2; +} + +static +void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm, + const struct bcm43xx_lopair *in_pair, + struct bcm43xx_lopair *out_pair, + u16 r27) +{ + static const struct bcm43xx_lopair transitions[8] = { + { .high = 1, .low = 1, }, + { .high = 1, .low = 0, }, + { .high = 1, .low = -1, }, + { .high = 0, .low = -1, }, + { .high = -1, .low = -1, }, + { .high = -1, .low = 0, }, + { .high = -1, .low = 1, }, + { .high = 0, .low = 1, }, + }; + struct bcm43xx_lopair lowest_transition = { + .high = in_pair->high, + .low = in_pair->low, + }; + struct bcm43xx_lopair tmp_pair; + struct bcm43xx_lopair transition; + int i = 12; + int state = 0; + int found_lower; + int j, begin, end; + u32 lowest_deviation; + u32 tmp; + + /* Note that in_pair and out_pair can point to the same pair. Be careful. */ + + bcm43xx_lo_write(bcm, &lowest_transition); + lowest_deviation = bcm43xx_phy_lo_g_singledeviation(bcm, r27); + do { + found_lower = 0; + assert(state >= 0 && state <= 8); + if (state == 0) { + begin = 1; + end = 8; + } else if (state % 2 == 0) { + begin = state - 1; + end = state + 1; + } else { + begin = state - 2; + end = state + 2; + } + if (begin < 1) + begin += 8; + if (end > 8) + end -= 8; + + j = begin; + tmp_pair.high = lowest_transition.high; + tmp_pair.low = lowest_transition.low; + while (1) { + assert(j >= 1 && j <= 8); + transition.high = tmp_pair.high + transitions[j - 1].high; + transition.low = tmp_pair.low + transitions[j - 1].low; + if ((abs(transition.low) < 9) && (abs(transition.high) < 9)) { + bcm43xx_lo_write(bcm, &transition); + tmp = bcm43xx_phy_lo_g_singledeviation(bcm, r27); + if (tmp < lowest_deviation) { + lowest_deviation = tmp; + state = j; + found_lower = 1; + + lowest_transition.high = transition.high; + lowest_transition.low = transition.low; + } + } + if (j == end) + break; + if (j == 8) + j = 1; + else + j++; + } + } while (i-- && found_lower); + + out_pair->high = lowest_transition.high; + out_pair->low = lowest_transition.low; +} + +/* Set the baseband attenuation value on chip. */ +void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, + u16 baseband_attenuation) +{ + u16 value; + + if (bcm->current_core->phy->version == 0) { + value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0); + value |= (baseband_attenuation & 0x000F); + bcm43xx_write16(bcm, 0x03E6, value); + return; + } + + if (bcm->current_core->phy->version > 1) { + value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C; + value |= (baseband_attenuation << 2) & 0x003C; + } else { + value = bcm43xx_phy_read(bcm, 0x0060) & ~0x0078; + value |= (baseband_attenuation << 3) & 0x0078; + } + bcm43xx_phy_write(bcm, 0x0060, value); +} + +/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */ +void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) +{ + static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 }; + const int is_initializing = bcm43xx_is_initializing(bcm); + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 h, i, oldi = 0, j; + struct bcm43xx_lopair control; + struct bcm43xx_lopair *tmp_control; + u16 tmp; + u16 regstack[16] = { 0 }; + u8 oldchannel; + + //XXX: What are these? + u8 r27 = 0, r31; + + oldchannel = radio->channel; + /* Setup */ + if (phy->connected) { + regstack[0] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS); + regstack[1] = bcm43xx_phy_read(bcm, 0x0802); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF); + bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC); + } + regstack[3] = bcm43xx_read16(bcm, 0x03E2); + bcm43xx_write16(bcm, 0x03E2, regstack[3] | 0x8000); + regstack[4] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); + regstack[5] = bcm43xx_phy_read(bcm, 0x15); + regstack[6] = bcm43xx_phy_read(bcm, 0x2A); + regstack[7] = bcm43xx_phy_read(bcm, 0x35); + regstack[8] = bcm43xx_phy_read(bcm, 0x60); + regstack[9] = bcm43xx_radio_read16(bcm, 0x43); + regstack[10] = bcm43xx_radio_read16(bcm, 0x7A); + regstack[11] = bcm43xx_radio_read16(bcm, 0x52); + if (phy->connected) { + regstack[12] = bcm43xx_phy_read(bcm, 0x0811); + regstack[13] = bcm43xx_phy_read(bcm, 0x0812); + regstack[14] = bcm43xx_phy_read(bcm, 0x0814); + regstack[15] = bcm43xx_phy_read(bcm, 0x0815); + } + bcm43xx_radio_selectchannel(bcm, 6, 0); + if (phy->connected) { + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF); + bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC); + bcm43xx_dummy_transmission(bcm); + } + bcm43xx_radio_write16(bcm, 0x0043, 0x0006); + + bcm43xx_phy_set_baseband_attenuation(bcm, 2); + + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x0000); + bcm43xx_phy_write(bcm, 0x002E, 0x007F); + bcm43xx_phy_write(bcm, 0x080F, 0x0078); + bcm43xx_phy_write(bcm, 0x0035, regstack[7] & ~(1 << 7)); + bcm43xx_radio_write16(bcm, 0x007A, regstack[10] & 0xFFF0); + bcm43xx_phy_write(bcm, 0x002B, 0x0203); + bcm43xx_phy_write(bcm, 0x002A, 0x08A3); + if (phy->connected) { + bcm43xx_phy_write(bcm, 0x0814, regstack[14] | 0x0003); + bcm43xx_phy_write(bcm, 0x0815, regstack[15] & 0xFFFC); + bcm43xx_phy_write(bcm, 0x0811, 0x01B3); + bcm43xx_phy_write(bcm, 0x0812, 0x00B2); + } + if (is_initializing) + bcm43xx_phy_lo_g_measure_txctl2(bcm); + bcm43xx_phy_write(bcm, 0x080F, 0x8078); + + /* Measure */ + control.low = 0; + control.high = 0; + for (h = 0; h < 10; h++) { + /* Loop over each possible RadioAttenuation (0-9) */ + i = pairorder[h]; + if (is_initializing) { + if (i == 3) { + control.low = 0; + control.high = 0; + } else if (((i % 2 == 1) && (oldi % 2 == 1)) || + ((i % 2 == 0) && (oldi % 2 == 0))) { + tmp_control = bcm43xx_get_lopair(phy, oldi, 0); + memcpy(&control, tmp_control, sizeof(control)); + } else { + tmp_control = bcm43xx_get_lopair(phy, 3, 0); + memcpy(&control, tmp_control, sizeof(control)); + } + } + /* Loop over each possible BasebandAttenuation/2 */ + for (j = 0; j < 4; j++) { + if (is_initializing) { + tmp = i * 2 + j; + r27 = 0; + r31 = 0; + if (tmp > 14) { + r31 = 1; + if (tmp > 17) + r27 = 1; + if (tmp > 19) + r27 = 2; + } + } else { + tmp_control = bcm43xx_get_lopair(phy, i, j * 2); + if (!tmp_control->used) + continue; + memcpy(&control, tmp_control, sizeof(control)); + r27 = 3; + r31 = 0; + } + bcm43xx_radio_write16(bcm, 0x43, i); + bcm43xx_radio_write16(bcm, 0x52, + radio->txpower[3]); + udelay(10); + + bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); + + tmp = (regstack[10] & 0xFFF0); + if (r31) + tmp |= 0x0008; + bcm43xx_radio_write16(bcm, 0x007A, tmp); + + tmp_control = bcm43xx_get_lopair(phy, i, j * 2); + bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27); + } + oldi = i; + } + /* Loop over each possible RadioAttenuation (10-13) */ + for (i = 10; i < 14; i++) { + /* Loop over each possible BasebandAttenuation/2 */ + for (j = 0; j < 4; j++) { + if (is_initializing) { + tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2); + memcpy(&control, tmp_control, sizeof(control)); + tmp = (i - 9) * 2 + j - 5;//FIXME: This is wrong, as the following if statement can never trigger. + r27 = 0; + r31 = 0; + if (tmp > 14) { + r31 = 1; + if (tmp > 17) + r27 = 1; + if (tmp > 19) + r27 = 2; + } + } else { + tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2); + if (!tmp_control->used) + continue; + memcpy(&control, tmp_control, sizeof(control)); + r27 = 3; + r31 = 0; + } + bcm43xx_radio_write16(bcm, 0x43, i - 9); + bcm43xx_radio_write16(bcm, 0x52, + radio->txpower[3] + | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? + udelay(10); + + bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); + + tmp = (regstack[10] & 0xFFF0); + if (r31) + tmp |= 0x0008; + bcm43xx_radio_write16(bcm, 0x7A, tmp); + + tmp_control = bcm43xx_get_lopair(phy, i, j * 2); + bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27); + } + } + + /* Restoration */ + if (phy->connected) { + bcm43xx_phy_write(bcm, 0x0015, 0xE300); + bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA0); + udelay(5); + bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2); + udelay(2); + bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3); + } else + bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0); + bcm43xx_phy_lo_adjust(bcm, is_initializing); + bcm43xx_phy_write(bcm, 0x002E, 0x807F); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x002F, 0x0202); + else + bcm43xx_phy_write(bcm, 0x002F, 0x0101); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, regstack[4]); + bcm43xx_phy_write(bcm, 0x0015, regstack[5]); + bcm43xx_phy_write(bcm, 0x002A, regstack[6]); + bcm43xx_phy_write(bcm, 0x0035, regstack[7]); + bcm43xx_phy_write(bcm, 0x0060, regstack[8]); + bcm43xx_radio_write16(bcm, 0x0043, regstack[9]); + bcm43xx_radio_write16(bcm, 0x007A, regstack[10]); + regstack[11] &= 0x00F0; + regstack[11] |= (bcm43xx_radio_read16(bcm, 0x52) & 0x000F); + bcm43xx_radio_write16(bcm, 0x52, regstack[11]); + bcm43xx_write16(bcm, 0x03E2, regstack[3]); + if (phy->connected) { + bcm43xx_phy_write(bcm, 0x0811, regstack[12]); + bcm43xx_phy_write(bcm, 0x0812, regstack[13]); + bcm43xx_phy_write(bcm, 0x0814, regstack[14]); + bcm43xx_phy_write(bcm, 0x0815, regstack[15]); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0]); + bcm43xx_phy_write(bcm, 0x0802, regstack[1]); + } + bcm43xx_radio_selectchannel(bcm, oldchannel, 1); + +#ifdef CONFIG_BCM43XX_DEBUG + { + /* Sanity check for all lopairs. */ + for (i = 0; i < BCM43xx_LO_COUNT; i++) { + tmp_control = phy->_lo_pairs + i; + if (tmp_control->low < -8 || tmp_control->low > 8 || + tmp_control->high < -8 || tmp_control->high > 8) { + printk(KERN_WARNING PFX + "WARNING: Invalid LOpair (low: %d, high: %d, index: %d)\n", + tmp_control->low, tmp_control->high, i); + } + } + } +#endif /* CONFIG_BCM43XX_DEBUG */ +} + +static +void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm) +{ + struct bcm43xx_lopair *pair; + + pair = bcm43xx_current_lopair(bcm); + pair->used = 1; +} + +void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_lopair *pair; + int i; + + for (i = 0; i < BCM43xx_LO_COUNT; i++) { + pair = phy->_lo_pairs + i; + pair->used = 0; + } +} + +/* http://bcm-specs.sipsolutions.net/EstimatePowerOut + * This function converts a TSSI value to dBm in Q5.2 + */ +static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + s8 dbm = 0; + s32 tmp; + + tmp = phy->idle_tssi; + tmp += tssi; + tmp -= phy->savedpctlreg; + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + tmp += 0x80; + tmp = limit_value(tmp, 0x00, 0xFF); + dbm = phy->tssi2dbm[tmp]; + TODO(); //TODO: There's a FIXME on the specs + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + tmp = limit_value(tmp, 0x00, 0x3F); + dbm = phy->tssi2dbm[tmp]; + break; + default: + assert(0); + } + + return dbm; +} + +/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */ +void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + + if (phy->savedpctlreg == 0xFFFF) + return; + if ((bcm->board_type == 0x0416) && + (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM)) + return; + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: { + + TODO(); //TODO: Nothing for A PHYs yet :-/ + + break; + } + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: { + u16 tmp; + u16 txpower; + s8 v0, v1, v2, v3; + s8 average; + u8 max_pwr; + s16 desired_pwr, estimated_pwr, pwr_adjust; + s16 radio_att_delta, baseband_att_delta; + s16 radio_attenuation, baseband_attenuation; + unsigned long phylock_flags; + + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0058); + v0 = (s8)(tmp & 0x00FF); + v1 = (s8)((tmp & 0xFF00) >> 8); + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005A); + v2 = (s8)(tmp & 0x00FF); + v3 = (s8)((tmp & 0xFF00) >> 8); + tmp = 0; + + if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) { + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0070); + v0 = (s8)(tmp & 0x00FF); + v1 = (s8)((tmp & 0xFF00) >> 8); + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0072); + v2 = (s8)(tmp & 0x00FF); + v3 = (s8)((tmp & 0xFF00) >> 8); + if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) + return; + v0 = (v0 + 0x20) & 0x3F; + v1 = (v1 + 0x20) & 0x3F; + v2 = (v2 + 0x20) & 0x3F; + v3 = (v3 + 0x20) & 0x3F; + tmp = 1; + } + bcm43xx_radio_clear_tssi(bcm); + + average = (v0 + v1 + v2 + v3 + 2) / 4; + + if (tmp && (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005E) & 0x8)) + average -= 13; + + estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average); + + max_pwr = bcm->sprom.maxpower_bgphy; + + if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) && + (phy->type == BCM43xx_PHYTYPE_G)) + max_pwr -= 0x3; + + /*TODO: + max_pwr = min(REG - bcm->sprom.antennagain_bgphy - 0x6, max_pwr) + where REG is the max power as per the regulatory domain + */ + + /*TODO: Get desired_pwr from wx_handlers or the stack + limit_value(desired_pwr, 0, max_pwr); + */ + + desired_pwr = max_pwr; /* remove this when we have a real desired_pwr */ + + pwr_adjust = desired_pwr - estimated_pwr; + + radio_att_delta = -(pwr_adjust + 7) >> 3; + baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta); + if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { + bcm43xx_phy_lo_mark_current_used(bcm); + return; + } + + /* Calculate the new attenuation values. */ + baseband_attenuation = radio->txpower[0]; + baseband_attenuation += baseband_att_delta; + radio_attenuation = radio->txpower[1]; + radio_attenuation += radio_att_delta; + + /* Get baseband and radio attenuation values into their permitted ranges. + * baseband 0-11, radio 0-9. + * Radio attenuation affects power level 4 times as much as baseband. + */ + if (radio_attenuation < 0) { + baseband_attenuation -= (4 * -radio_attenuation); + radio_attenuation = 0; + } else if (radio_attenuation > 9) { + baseband_attenuation += (4 * (radio_attenuation - 9)); + radio_attenuation = 9; + } else { + while (baseband_attenuation < 0 && radio_attenuation > 0) { + baseband_attenuation += 4; + radio_attenuation--; + } + while (baseband_attenuation > 11 && radio_attenuation < 9) { + baseband_attenuation -= 4; + radio_attenuation++; + } + } + baseband_attenuation = limit_value(baseband_attenuation, 0, 11); + + txpower = radio->txpower[2]; + if ((radio->version == 0x2050) && (radio->revision == 2)) { + if (radio_attenuation <= 1) { + if (txpower == 0) { + txpower = 3; + radio_attenuation += 2; + baseband_attenuation += 2; + } else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) { + baseband_attenuation += 4 * (radio_attenuation - 2); + radio_attenuation = 2; + } + } else if (radio_attenuation > 4 && txpower != 0) { + txpower = 0; + if (baseband_attenuation < 3) { + radio_attenuation -= 3; + baseband_attenuation += 2; + } else { + radio_attenuation -= 2; + baseband_attenuation -= 2; + } + } + } + radio->txpower[2] = txpower; + baseband_attenuation = limit_value(baseband_attenuation, 0, 11); + radio_attenuation = limit_value(radio_attenuation, 0, 9); + + bcm43xx_phy_lock(bcm, phylock_flags); + bcm43xx_radio_lock(bcm); + bcm43xx_radio_set_txpower_bg(bcm, baseband_attenuation, + radio_attenuation, txpower); + bcm43xx_phy_lo_mark_current_used(bcm); + bcm43xx_radio_unlock(bcm); + bcm43xx_phy_unlock(bcm, phylock_flags); + break; + } + default: + assert(0); + } +} + +static inline +s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den) +{ + if (num < 0) + return num/den; + else + return (num+den/2)/den; +} + +static inline +s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2) +{ + s32 m1, m2, f = 256, q, delta; + s8 i = 0; + + m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32); + m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1); + do { + if (i > 15) + return -EINVAL; + q = bcm43xx_tssi2dbm_ad(f * 4096 - + bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048); + delta = abs(q - f); + f = q; + i++; + } while (delta >= 2); + entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128); + return 0; +} + +/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */ +int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + s16 pab0, pab1, pab2; + u8 idx; + s8 *dyn_tssi2dbm; + + if (phy->type == BCM43xx_PHYTYPE_A) { + pab0 = (s16)(bcm->sprom.pa1b0); + pab1 = (s16)(bcm->sprom.pa1b1); + pab2 = (s16)(bcm->sprom.pa1b2); + } else { + pab0 = (s16)(bcm->sprom.pa0b0); + pab1 = (s16)(bcm->sprom.pa0b1); + pab2 = (s16)(bcm->sprom.pa0b2); + } + + if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) { + phy->idle_tssi = 0x34; + phy->tssi2dbm = bcm43xx_tssi2dbm_b_table; + return 0; + } + + if (pab0 != 0 && pab1 != 0 && pab2 != 0 && + pab0 != -1 && pab1 != -1 && pab2 != -1) { + /* The pabX values are set in SPROM. Use them. */ + if (phy->type == BCM43xx_PHYTYPE_A) { + if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 && + (s8)bcm->sprom.idle_tssi_tgt_aphy != -1) + phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy); + else + phy->idle_tssi = 62; + } else { + if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 && + (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1) + phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy); + else + phy->idle_tssi = 62; + } + dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); + if (dyn_tssi2dbm == NULL) { + printk(KERN_ERR PFX "Could not allocate memory" + "for tssi2dbm table\n"); + return -ENOMEM; + } + for (idx = 0; idx < 64; idx++) + if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) { + phy->tssi2dbm = NULL; + printk(KERN_ERR PFX "Could not generate " + "tssi2dBm table\n"); + return -ENODEV; + } + phy->tssi2dbm = dyn_tssi2dbm; + phy->dyn_tssi_tbl = 1; + } else { + /* pabX values not set in SPROM. */ + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + /* APHY needs a generated table. */ + phy->tssi2dbm = NULL; + printk(KERN_ERR PFX "Could not generate tssi2dBm " + "table (wrong SPROM info)!\n"); + return -ENODEV; + case BCM43xx_PHYTYPE_B: + phy->idle_tssi = 0x34; + phy->tssi2dbm = bcm43xx_tssi2dbm_b_table; + break; + case BCM43xx_PHYTYPE_G: + phy->idle_tssi = 0x34; + phy->tssi2dbm = bcm43xx_tssi2dbm_g_table; + break; + } + } + + return 0; +} + +int bcm43xx_phy_init(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + int err = -ENODEV; + unsigned long flags; + + /* We do not want to be preempted while calibrating + * the hardware. + */ + local_irq_save(flags); + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + if (phy->rev == 2 || phy->rev == 3) { + bcm43xx_phy_inita(bcm); + err = 0; + } + break; + case BCM43xx_PHYTYPE_B: + switch (phy->rev) { + case 2: + bcm43xx_phy_initb2(bcm); + err = 0; + break; + case 4: + bcm43xx_phy_initb4(bcm); + err = 0; + break; + case 5: + bcm43xx_phy_initb5(bcm); + err = 0; + break; + case 6: + bcm43xx_phy_initb6(bcm); + err = 0; + break; + } + break; + case BCM43xx_PHYTYPE_G: + bcm43xx_phy_initg(bcm); + err = 0; + break; + } + local_irq_restore(flags); + if (err) + printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n"); + + return err; +} + +void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 antennadiv; + u16 offset; + u16 value; + u32 ucodeflags; + + antennadiv = phy->antenna_diversity; + + if (antennadiv == 0xFFFF) + antennadiv = 3; + assert(antennadiv <= 3); + + ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + ucodeflags & ~BCM43xx_UCODEFLAG_AUTODIV); + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + case BCM43xx_PHYTYPE_G: + if (phy->type == BCM43xx_PHYTYPE_A) + offset = 0x0000; + else + offset = 0x0400; + + if (antennadiv == 2) + value = (3/*automatic*/ << 7); + else + value = (antennadiv << 7); + bcm43xx_phy_write(bcm, offset + 1, + (bcm43xx_phy_read(bcm, offset + 1) + & 0x7E7F) | value); + + if (antennadiv >= 2) { + if (antennadiv == 2) + value = (antennadiv << 7); + else + value = (0/*force0*/ << 7); + bcm43xx_phy_write(bcm, offset + 0x2B, + (bcm43xx_phy_read(bcm, offset + 0x2B) + & 0xFEFF) | value); + } + + if (phy->type == BCM43xx_PHYTYPE_G) { + if (antennadiv >= 2) + bcm43xx_phy_write(bcm, 0x048C, + bcm43xx_phy_read(bcm, 0x048C) + | 0x2000); + else + bcm43xx_phy_write(bcm, 0x048C, + bcm43xx_phy_read(bcm, 0x048C) + & ~0x2000); + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0461, + bcm43xx_phy_read(bcm, 0x0461) + | 0x0010); + bcm43xx_phy_write(bcm, 0x04AD, + (bcm43xx_phy_read(bcm, 0x04AD) + & 0x00FF) | 0x0015); + if (phy->rev == 2) + bcm43xx_phy_write(bcm, 0x0427, 0x0008); + else + bcm43xx_phy_write(bcm, 0x0427, + (bcm43xx_phy_read(bcm, 0x0427) + & 0x00FF) | 0x0008); + } + else if (phy->rev >= 6) + bcm43xx_phy_write(bcm, 0x049B, 0x00DC); + } else { + if (phy->rev < 3) + bcm43xx_phy_write(bcm, 0x002B, + (bcm43xx_phy_read(bcm, 0x002B) + & 0x00FF) | 0x0024); + else { + bcm43xx_phy_write(bcm, 0x0061, + bcm43xx_phy_read(bcm, 0x0061) + | 0x0010); + if (phy->rev == 3) { + bcm43xx_phy_write(bcm, 0x0093, 0x001D); + bcm43xx_phy_write(bcm, 0x0027, 0x0008); + } else { + bcm43xx_phy_write(bcm, 0x0093, 0x003A); + bcm43xx_phy_write(bcm, 0x0027, + (bcm43xx_phy_read(bcm, 0x0027) + & 0x00FF) | 0x0008); + } + } + } + break; + case BCM43xx_PHYTYPE_B: + if (bcm->current_core->rev == 2) + value = (3/*automatic*/ << 7); + else + value = (antennadiv << 7); + bcm43xx_phy_write(bcm, 0x03E2, + (bcm43xx_phy_read(bcm, 0x03E2) + & 0xFE7F) | value); + break; + default: + assert(0); + } + + if (antennadiv >= 2) { + ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET); + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + ucodeflags | BCM43xx_UCODEFLAG_AUTODIV); + } + + phy->antenna_diversity = antennadiv; +} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h new file mode 100644 index 0000000000..1f321ef42b --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h @@ -0,0 +1,74 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef BCM43xx_PHY_H_ +#define BCM43xx_PHY_H_ + +#include + +struct bcm43xx_private; + +void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm); +#define bcm43xx_phy_lock(bcm, flags) \ + do { \ + local_irq_save(flags); \ + bcm43xx_raw_phy_lock(bcm); \ + } while (0) +void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm); +#define bcm43xx_phy_unlock(bcm, flags) \ + do { \ + bcm43xx_raw_phy_unlock(bcm); \ + local_irq_restore(flags); \ + } while (0) + +u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset); +void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val); + +int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm); +int bcm43xx_phy_init(struct bcm43xx_private *bcm); + +void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm); +void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm); +int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect); + +void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm); +void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm); +void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm); + +/* Adjust the LocalOscillator to the saved values. + * "fixed" is only set to 1 once in initialization. Set to 0 otherwise. + */ +void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed); +void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm); + +void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, + u16 baseband_attenuation); + +#endif /* BCM43xx_PHY_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c new file mode 100644 index 0000000000..9a55e9d005 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -0,0 +1,592 @@ +/* + + Broadcom BCM43xx wireless driver + + PIO Transmission + + Copyright (c) 2005 Michael Buesch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx.h" +#include "bcm43xx_pio.h" +#include "bcm43xx_main.h" + +#include + + +static inline +u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue, + u16 offset) +{ + return bcm43xx_read16(queue->bcm, queue->mmio_base + offset); +} + +static inline +void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, + u16 offset, u16 value) +{ + bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); +} + +static inline +void tx_start(struct bcm43xx_pioqueue *queue) +{ + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_INIT); +} + +static inline +void tx_octet(struct bcm43xx_pioqueue *queue, + u8 octet) +{ + if (queue->bcm->current_core->rev < 3) { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, octet); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_WRITEHI); + } else { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_WRITEHI); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, octet); + } +} + +static inline +void tx_data(struct bcm43xx_pioqueue *queue, + u8 *packet, + unsigned int octets) +{ + u16 data; + unsigned int i = 0; + + if (queue->bcm->current_core->rev < 3) { + data = be16_to_cpu( *((u16 *)packet) ); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); + i += 2; + } + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_WRITELO | BCM43xx_PIO_TXCTL_WRITEHI); + for ( ; i < octets - 1; i += 2) { + data = be16_to_cpu( *((u16 *)(packet + i)) ); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); + } + if (octets % 2) + tx_octet(queue, packet[octets - 1]); +} + +static inline +void tx_complete(struct bcm43xx_pioqueue *queue, + struct sk_buff *skb) +{ + u16 data; + + if (queue->bcm->current_core->rev < 3) { + data = be16_to_cpu( *((u16 *)(skb->data + skb->len - 2)) ); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_WRITEHI | BCM43xx_PIO_TXCTL_COMPLETE); + } else { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_COMPLETE); + } +} + +static inline +u16 generate_cookie(struct bcm43xx_pioqueue *queue, + int packetindex) +{ + u16 cookie = 0x0000; + + /* We use the upper 4 bits for the PIO + * controller ID and the lower 12 bits + * for the packet index (in the cache). + */ + switch (queue->mmio_base) { + default: + assert(0); + case BCM43xx_MMIO_PIO1_BASE: + break; + case BCM43xx_MMIO_PIO2_BASE: + cookie = 0x1000; + break; + case BCM43xx_MMIO_PIO3_BASE: + cookie = 0x2000; + break; + case BCM43xx_MMIO_PIO4_BASE: + cookie = 0x3000; + break; + } + assert(((u16)packetindex & 0xF000) == 0x0000); + cookie |= (u16)packetindex; + + return cookie; +} + +static inline +struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm, + u16 cookie, + struct bcm43xx_pio_txpacket **packet) +{ + struct bcm43xx_pioqueue *queue = NULL; + int packetindex; + + switch (cookie & 0xF000) { + case 0x0000: + queue = bcm->current_core->pio->queue0; + break; + case 0x1000: + queue = bcm->current_core->pio->queue1; + break; + case 0x2000: + queue = bcm->current_core->pio->queue2; + break; + case 0x3000: + queue = bcm->current_core->pio->queue3; + break; + default: + assert(0); + } + + packetindex = (cookie & 0x0FFF); + assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS); + *packet = queue->__tx_packets_cache + packetindex; + + return queue; +} + +static inline +void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, + struct sk_buff *skb, + struct bcm43xx_pio_txpacket *packet) +{ + unsigned int octets; + + assert(skb_shinfo(skb)->nr_frags == 0); + assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); + + __skb_push(skb, sizeof(struct bcm43xx_txhdr)); + bcm43xx_generate_txhdr(queue->bcm, + (struct bcm43xx_txhdr *)skb->data, + skb->data + sizeof(struct bcm43xx_txhdr), + skb->len - sizeof(struct bcm43xx_txhdr), + (packet->xmitted_frags == 0), + generate_cookie(queue, pio_txpacket_getindex(packet))); + + tx_start(queue); + octets = skb->len; + if (queue->bcm->current_core->rev < 3) //FIXME: && this is the last packet in the queue. + octets -= 2; + tx_data(queue, (u8 *)skb->data, octets); + tx_complete(queue, skb); +} + +static inline +int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) +{ + struct bcm43xx_pioqueue *queue = packet->queue; + struct ieee80211_txb *txb = packet->txb; + struct sk_buff *skb; + u16 octets; + int i; + + for (i = packet->xmitted_frags; i < txb->nr_frags; i++) { + skb = txb->fragments[i]; + + octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr); + + assert(queue->tx_devq_size >= octets); + assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS); + assert(queue->tx_devq_used <= queue->tx_devq_size); + /* Check if there is sufficient free space on the device + * TX queue. If not, return and let the TX-work-handler + * retry later. + */ + if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS) + return -EBUSY; + if (queue->tx_devq_used + octets > queue->tx_devq_size) + return -EBUSY; + /* Now poke the device. */ + pio_tx_write_fragment(queue, skb, packet); + + /* Account for the packet size. + * (We must not overflow the device TX queue) + */ + queue->tx_devq_packets++; + queue->tx_devq_used += octets; + + assert(packet->xmitted_frags <= packet->txb->nr_frags); + packet->xmitted_frags++; + packet->xmitted_octets += octets; + } + list_move_tail(&packet->list, &queue->txrunning); + + return 0; +} + +static void free_txpacket(struct bcm43xx_pio_txpacket *packet) +{ + struct bcm43xx_pioqueue *queue = packet->queue; + + ieee80211_txb_free(packet->txb); + + list_move(&packet->list, &packet->queue->txfree); + + assert(queue->tx_devq_used >= packet->xmitted_octets); + queue->tx_devq_used -= packet->xmitted_octets; + assert(queue->tx_devq_packets >= packet->xmitted_frags); + queue->tx_devq_packets -= packet->xmitted_frags; +} + +static void txwork_handler(void *d) +{ + struct bcm43xx_pioqueue *queue = d; + unsigned long flags; + struct bcm43xx_pio_txpacket *packet, *tmp_packet; + int err; + + spin_lock_irqsave(&queue->txlock, flags); + list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { + assert(packet->xmitted_frags < packet->txb->nr_frags); + if (packet->xmitted_frags == 0) { + int i; + struct sk_buff *skb; + + /* Check if the device queue is big + * enough for every fragment. If not, drop the + * whole packet. + */ + for (i = 0; i < packet->txb->nr_frags; i++) { + skb = packet->txb->fragments[i]; + if (unlikely(skb->len > queue->tx_devq_size)) { + dprintkl(KERN_ERR PFX "PIO TX device queue too small. " + "Dropping packet...\n"); + free_txpacket(packet); + goto next_packet; + } + } + } + /* Now try to transmit the packet. + * This may not completely succeed. + */ + err = pio_tx_packet(packet); + if (err) + break; +next_packet: + continue; + } + spin_unlock_irqrestore(&queue->txlock, flags); +} + +static void setup_txqueues(struct bcm43xx_pioqueue *queue) +{ + struct bcm43xx_pio_txpacket *packet; + int i; + + for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) { + packet = queue->__tx_packets_cache + i; + + packet->queue = queue; + INIT_LIST_HEAD(&packet->list); + + list_add(&packet->list, &queue->txfree); + } +} + +static +struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, + u16 pio_mmio_base) +{ + struct bcm43xx_pioqueue *queue; + u32 value; + u16 qsize; + + queue = kmalloc(sizeof(*queue), GFP_KERNEL); + if (!queue) + goto out; + memset(queue, 0, sizeof(*queue)); + + queue->bcm = bcm; + queue->mmio_base = pio_mmio_base; + + INIT_LIST_HEAD(&queue->txfree); + INIT_LIST_HEAD(&queue->txqueue); + INIT_LIST_HEAD(&queue->txrunning); + spin_lock_init(&queue->txlock); + INIT_WORK(&queue->txwork, txwork_handler, queue); + + value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + value |= BCM43xx_SBF_XFER_REG_BYTESWAP; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); + + qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); + if (qsize <= BCM43xx_PIO_TXQADJUST) { + printk(KERN_ERR PFX "PIO tx queue too small (%u)\n", qsize); + goto err_freequeue; + } + qsize -= BCM43xx_PIO_TXQADJUST; + queue->tx_devq_size = qsize; + + setup_txqueues(queue); + +out: + return queue; + +err_freequeue: + kfree(queue); + queue = NULL; + goto out; +} + +static void cancel_transfers(struct bcm43xx_pioqueue *queue) +{ + struct bcm43xx_pio_txpacket *packet, *tmp_packet; + + netif_tx_disable(queue->bcm->net_dev); + assert(queue->bcm->shutting_down); + cancel_delayed_work(&queue->txwork); + flush_workqueue(queue->bcm->workqueue); + + list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) + free_txpacket(packet); + list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) + free_txpacket(packet); +} + +static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) +{ + if (!queue) + return; + + cancel_transfers(queue); + kfree(queue); +} + +void bcm43xx_pio_free(struct bcm43xx_private *bcm) +{ + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue3); + bcm->current_core->pio->queue3 = NULL; + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue2); + bcm->current_core->pio->queue2 = NULL; + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue1); + bcm->current_core->pio->queue1 = NULL; + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue0); + bcm->current_core->pio->queue0 = NULL; +} + +int bcm43xx_pio_init(struct bcm43xx_private *bcm) +{ + struct bcm43xx_pioqueue *queue; + int err = -ENOMEM; + + queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE); + if (!queue) + goto out; + bcm->current_core->pio->queue0 = queue; + + queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE); + if (!queue) + goto err_destroy0; + bcm->current_core->pio->queue1 = queue; + + queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE); + if (!queue) + goto err_destroy1; + bcm->current_core->pio->queue2 = queue; + + queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE); + if (!queue) + goto err_destroy2; + bcm->current_core->pio->queue3 = queue; + + if (bcm->current_core->rev < 3) + bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND; + + dprintk(KERN_INFO PFX "PIO initialized\n"); + err = 0; +out: + return err; + +err_destroy2: + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue2); + bcm->current_core->pio->queue2 = NULL; +err_destroy1: + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue1); + bcm->current_core->pio->queue1 = NULL; +err_destroy0: + bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue0); + bcm->current_core->pio->queue0 = NULL; + goto out; +} + +static inline +int pio_transfer_txb(struct bcm43xx_pioqueue *queue, + struct ieee80211_txb *txb) +{ + struct bcm43xx_pio_txpacket *packet; + unsigned long flags; + u16 tmp; + + spin_lock_irqsave(&queue->txlock, flags); + assert(!queue->tx_suspended); + assert(!list_empty(&queue->txfree)); + + tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); + if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) { + spin_unlock_irqrestore(&queue->txlock, flags); + return -EBUSY; + } + + packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); + + packet->txb = txb; + list_move_tail(&packet->list, &queue->txqueue); + packet->xmitted_octets = 0; + packet->xmitted_frags = 0; + + /* Suspend TX, if we are out of packets in the "free" queue. */ + if (unlikely(list_empty(&queue->txfree))) { + netif_stop_queue(queue->bcm->net_dev); + queue->tx_suspended = 1; + } + + spin_unlock_irqrestore(&queue->txlock, flags); + queue_work(queue->bcm->workqueue, &queue->txwork); + + return 0; +} + +int fastcall bcm43xx_pio_transfer_txb(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) +{ + return pio_transfer_txb(bcm->current_core->pio->queue1, txb); +} + +void fastcall +bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) +{ + struct bcm43xx_pioqueue *queue; + struct bcm43xx_pio_txpacket *packet; + unsigned long flags; + + queue = parse_cookie(bcm, status->cookie, &packet); + assert(queue); + spin_lock_irqsave(&queue->txlock, flags); + free_txpacket(packet); + if (unlikely(queue->tx_suspended)) { + queue->tx_suspended = 0; + netif_wake_queue(queue->bcm->net_dev); + } + + /* If there are packets on the txqueue, + * start the work handler again. + */ + if (!list_empty(&queue->txqueue)) { + queue_work(queue->bcm->workqueue, + &queue->txwork); + } + spin_unlock_irqrestore(&queue->txlock, flags); +} + +static void pio_rx_error(struct bcm43xx_pioqueue *queue, + const char *error) +{ + printk("PIO RX error: %s\n", error); + bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, BCM43xx_PIO_RXCTL_READY); +} + +void fastcall +bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) +{ + u16 preamble[21] = { 0 }; + struct bcm43xx_rxhdr *rxhdr; + u16 tmp; + u16 len; + int i, err; + int preamble_readwords; + struct sk_buff *skb; + + tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); + if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) { + dprintkl(KERN_ERR PFX "PIO RX: No data available\n"); + return; + } + bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, BCM43xx_PIO_RXCTL_DATAAVAILABLE); + + for (i = 0; i < 10; i++) { + tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); + if (tmp & BCM43xx_PIO_RXCTL_READY) + goto data_ready; + udelay(10); + } + dprintkl(KERN_ERR PFX "PIO RX timed out\n"); + return; +data_ready: + + len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); + if (unlikely(len > 0x700)) { + pio_rx_error(queue, "len > 0x700"); + return; + } + if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) { + pio_rx_error(queue, "len == 0"); + return; + } + preamble[0] = cpu_to_le16(len); + if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) + preamble_readwords = 14 / sizeof(u16); + else + preamble_readwords = 18 / sizeof(u16); + for (i = 0; i < preamble_readwords; i++) { + tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); + preamble[i + 1] = cpu_to_be16(tmp); + } + rxhdr = (struct bcm43xx_rxhdr *)preamble; + if (unlikely(rxhdr->flags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) { + pio_rx_error(queue, "invalid frame"); + if (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE) { + for (i = 0; i < 15; i++) + bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); /* dummy read. */ + } + return; + } +//FIXME +#if 0 + if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) { + bcm43xx_rx_transmitstatus(queue->bcm, + (const struct bcm43xx_hwxmitstatus *)(preamble + 1)); + return; + } +#endif + skb = dev_alloc_skb(len); + if (unlikely(!skb)) { + pio_rx_error(queue, "out of memory"); + return; + } + skb_put(skb, len); + for (i = 0; i < len - 1; i += 2) { + tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); + *((u16 *)(skb->data + i)) = tmp; + } + if (len % 2) { + tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); + skb->data[len - 1] = (tmp & 0x00FF); + skb->data[0] = (tmp & 0xFF00) >> 8; + } + err = bcm43xx_rx(queue->bcm, skb, rxhdr); + if (unlikely(err)) + dev_kfree_skb_irq(skb); +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h new file mode 100644 index 0000000000..71b92ee341 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h @@ -0,0 +1,88 @@ +#ifndef BCM43xx_PIO_H_ +#define BCM43xx_PIO_H_ + +#include "bcm43xx.h" + +#include +#include +#include +#include + + +#define BCM43xx_PIO_TXCTL 0x00 +#define BCM43xx_PIO_TXDATA 0x02 +#define BCM43xx_PIO_TXQBUFSIZE 0x04 +#define BCM43xx_PIO_RXCTL 0x08 +#define BCM43xx_PIO_RXDATA 0x0A + +#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 0) +#define BCM43xx_PIO_TXCTL_WRITELO (1 << 1) +#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) +#define BCM43xx_PIO_TXCTL_INIT (1 << 3) +#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) + +#define BCM43xx_PIO_RXCTL_DATAAVAILABLE (1 << 0) +#define BCM43xx_PIO_RXCTL_READY (1 << 1) + +/* PIO constants */ +#define BCM43xx_PIO_MAXTXDEVQPACKETS 31 +#define BCM43xx_PIO_TXQADJUST 80 + +/* PIO tuning knobs */ +#define BCM43xx_PIO_MAXTXPACKETS 256 + + +struct bcm43xx_pioqueue; +struct bcm43xx_xmitstatus; + +struct bcm43xx_pio_txpacket { + struct bcm43xx_pioqueue *queue; + struct ieee80211_txb *txb; + struct list_head list; + + u8 xmitted_frags; + u16 xmitted_octets; +}; + +#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->__tx_packets_cache)) + +struct bcm43xx_pioqueue { + struct bcm43xx_private *bcm; + u16 mmio_base; + + u8 tx_suspended:1; + + /* Adjusted size of the device internal TX buffer. */ + u16 tx_devq_size; + /* Used octets of the device internal TX buffer. */ + u16 tx_devq_used; + /* Used packet slots in the device internal TX buffer. */ + u8 tx_devq_packets; + /* Packets from the txfree list can + * be taken on incoming TX requests. + */ + struct list_head txfree; + /* Packets on the txqueue are queued, + * but not completely written to the chip, yet. + */ + struct list_head txqueue; + /* Packets on the txrunning queue are completely + * posted to the device. We are waiting for the txstatus. + */ + struct list_head txrunning; + /* Locking of the TX queues and the accounting. */ + spinlock_t txlock; + struct work_struct txwork; + struct bcm43xx_pio_txpacket __tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS]; +}; + +int bcm43xx_pio_init(struct bcm43xx_private *bcm); +void bcm43xx_pio_free(struct bcm43xx_private *bcm); + +int FASTCALL(bcm43xx_pio_transfer_txb(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb)); +void FASTCALL(bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status)); + +void FASTCALL(bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)); +#endif /* BCM43xx_PIO_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c new file mode 100644 index 0000000000..3c92b62807 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c @@ -0,0 +1,358 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include + +#include "bcm43xx.h" +#include "bcm43xx_power.h" +#include "bcm43xx_main.h" + + +/* Get max/min slowclock frequency + * as described in http://bcm-specs.sipsolutions.net/PowerControl + */ +static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm, + int get_max) +{ + int limit = 0; + int divisor; + int selection; + int err; + u32 tmp; + struct bcm43xx_coreinfo *old_core; + + if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) + goto out; + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err) + goto out; + + if (bcm->current_core->rev < 6) { + if ((bcm->bustype == BCM43xx_BUSTYPE_PCMCIA) || + (bcm->bustype == BCM43xx_BUSTYPE_SB)) { + selection = 1; + divisor = 32; + } else { + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp); + if (err) { + printk(KERN_ERR PFX "clockfreqlimit pcicfg read failure\n"); + goto out_switchback; + } + if (tmp & 0x10) { + /* PCI */ + selection = 2; + divisor = 64; + } else { + /* XTAL */ + selection = 1; + divisor = 32; + } + } + } else if (bcm->current_core->rev < 10) { + selection = (tmp & 0x07); + if (selection) { + tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); + divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16)); + } else + divisor = 1; + } else { + tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL); + divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16)); + selection = 1; + } + + switch (selection) { + case 0: + /* LPO */ + if (get_max) + limit = 43000; + else + limit = 25000; + break; + case 1: + /* XTAL */ + if (get_max) + limit = 20200000; + else + limit = 19800000; + break; + case 2: + /* PCI */ + if (get_max) + limit = 34000000; + else + limit = 25000000; + break; + default: + assert(0); + } + limit /= divisor; + +out_switchback: + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + +out: + return limit; +} + +/* init power control + * as described in http://bcm-specs.sipsolutions.net/PowerControl + */ +int bcm43xx_pctl_init(struct bcm43xx_private *bcm) +{ + int err, maxfreq; + struct bcm43xx_coreinfo *old_core; + + if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) + return 0; + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err == -ENODEV) + return 0; + if (err) + goto out; + + maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1); + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY, + (maxfreq * 150 + 999999) / 1000000); + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY, + (maxfreq * 15 + 999999) / 1000000); + + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + +out: + return err; +} + +u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm) +{ + u16 delay = 0; + int err; + u32 pll_on_delay; + struct bcm43xx_coreinfo *old_core; + int minfreq; + + if (bcm->bustype != BCM43xx_BUSTYPE_PCI) + goto out; + if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) + goto out; + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err == -ENODEV) + goto out; + + minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0); + pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY); + delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq; + + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + +out: + return delay; +} + +/* set the powercontrol clock + * as described in http://bcm-specs.sipsolutions.net/PowerControl + */ +int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode) +{ + int err; + struct bcm43xx_coreinfo *old_core; + u32 tmp; + + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err == -ENODEV) + return 0; + if (err) + goto out; + + if (bcm->core_chipcommon.rev < 6) { + if (mode == BCM43xx_PCTL_CLK_FAST) { + err = bcm43xx_pctl_set_crystal(bcm, 1); + if (err) + goto out; + } + } else { + if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) && + (bcm->core_chipcommon.rev < 10)) { + switch (mode) { + case BCM43xx_PCTL_CLK_FAST: + tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); + tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL; + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); + break; + case BCM43xx_PCTL_CLK_SLOW: + tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); + tmp |= BCM43xx_PCTL_FORCE_SLOW; + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); + break; + case BCM43xx_PCTL_CLK_DYNAMIC: + tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); + tmp &= ~BCM43xx_PCTL_FORCE_SLOW; + tmp |= BCM43xx_PCTL_FORCE_PLL; + tmp &= ~BCM43xx_PCTL_DYN_XTAL; + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); + } + } + } + + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0); + +out: + return err; +} + +int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on) +{ + int err; + u32 in, out, outenable; + + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in); + if (err) + goto err_pci; + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &out); + if (err) + goto err_pci; + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUTENABLE, &outenable); + if (err) + goto err_pci; + + outenable |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN); + + if (on) { + if (in & 0x40) + return 0; + + out |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN); + + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); + if (err) + goto err_pci; + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable); + if (err) + goto err_pci; + udelay(1000); + + out &= ~BCM43xx_PCTL_PLL_POWERDOWN; + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); + if (err) + goto err_pci; + udelay(5000); + } else { + if (bcm->current_core->rev < 5) + return 0; + if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW) + return 0; + +/* XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time? + * err = bcm43xx_switch_core(bcm, bcm->active_80211_core); + * if (err) + * return err; + * if (((bcm->current_core->rev >= 3) && + * (bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) || + * ((bcm->current_core->rev < 3) && + * !(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4)))) + * return 0; + * err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + * if (err) + * return err; + */ + + err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); + if (err) + goto out; + out &= ~BCM43xx_PCTL_XTAL_POWERUP; + out |= BCM43xx_PCTL_PLL_POWERDOWN; + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); + if (err) + goto err_pci; + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable); + if (err) + goto err_pci; + } + +out: + return err; + +err_pci: + printk(KERN_ERR PFX "Error: pctl_set_clock() could not access PCI config space!\n"); + err = -EBUSY; + goto out; +} + +/* Set the PowerSavingControlBits. + * Bitvalues: + * 0 => unset the bit + * 1 => set the bit + * -1 => calculate the bit + */ +void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm, + int bit25, int bit26) +{ + int i; + u32 status; + +//FIXME: Force 25 to off and 26 to on for now: +bit25 = 0; +bit26 = 1; + + if (bit25 == -1) { + //TODO: If powersave is not off and FIXME is not set and we are not in adhoc + // and thus is not an AP and we are associated, set bit 25 + } + if (bit26 == -1) { + //TODO: If the device is awake or this is an AP, or we are scanning, or FIXME, + // or we are associated, or FIXME, or the latest PS-Poll packet sent was + // successful, set bit26 + } + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + if (bit25) + status |= BCM43xx_SBF_PS1; + else + status &= ~BCM43xx_SBF_PS1; + if (bit26) + status |= BCM43xx_SBF_PS2; + else + status &= ~BCM43xx_SBF_PS2; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + if (bit26 && bcm->current_core->rev >= 5) { + for (i = 0; i < 100; i++) { + if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4) + break; + udelay(10); + } + } +} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h new file mode 100644 index 0000000000..5f63640810 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.h @@ -0,0 +1,47 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef BCM43xx_POWER_H_ +#define BCM43xx_POWER_H_ + +#include + + +struct bcm43xx_private; + +int bcm43xx_pctl_init(struct bcm43xx_private *bcm); +int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode); +int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on); +u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm); + +void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm, + int bit25, int bit26); + +#endif /* BCM43xx_POWER_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c new file mode 100644 index 0000000000..1e65658552 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -0,0 +1,1766 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include + +#include "bcm43xx.h" +#include "bcm43xx_main.h" +#include "bcm43xx_phy.h" +#include "bcm43xx_radio.h" +#include "bcm43xx_ilt.h" + + +/* Table for bcm43xx_radio_calibrationvalue() */ +static const u16 rcc_table[16] = { + 0x0002, 0x0003, 0x0001, 0x000F, + 0x0006, 0x0007, 0x0005, 0x000F, + 0x000A, 0x000B, 0x0009, 0x000F, + 0x000E, 0x000F, 0x000D, 0x000F, +}; + +/* Reverse the bits of a 4bit value. + * Example: 1101 is flipped 1011 + */ +static u16 flip_4bit(u16 value) +{ + u16 flipped = 0x0000; + + assert((value & ~0x000F) == 0x0000); + + flipped |= (value & 0x0001) << 3; + flipped |= (value & 0x0002) << 1; + flipped |= (value & 0x0004) >> 1; + flipped |= (value & 0x0008) >> 3; + + return flipped; +} + +/* Get the freq, as it has to be written to the device. */ +static inline +u16 channel2freq_bg(u8 channel) +{ + /* Frequencies are given as frequencies_bg[index] + 2.4GHz + * Starting with channel 1 + */ + static const u16 frequencies_bg[14] = { + 12, 17, 22, 27, + 32, 37, 42, 47, + 52, 57, 62, 67, + 72, 84, + }; + + assert(channel >= 1 && channel <= 14); + + return frequencies_bg[channel - 1]; +} + +/* Get the freq, as it has to be written to the device. */ +static inline +u16 channel2freq_a(u8 channel) +{ + assert(channel <= 200); + + return (5000 + 5 * channel); +} + +void bcm43xx_radio_lock(struct bcm43xx_private *bcm) +{ + u32 status; + + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + status |= BCM43xx_SBF_RADIOREG_LOCK; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + udelay(10); +} + +void bcm43xx_radio_unlock(struct bcm43xx_private *bcm) +{ + u32 status; + + bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); /* dummy read */ + status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); + status &= ~BCM43xx_SBF_RADIOREG_LOCK; + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); +} + +u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + offset |= 0x0040; + break; + case BCM43xx_PHYTYPE_B: + if (radio->version == 0x2053) { + if (offset < 0x70) + offset += 0x80; + else if (offset < 0x80) + offset += 0x70; + } else if (radio->version == 0x2050) { + offset |= 0x80; + } else + assert(0); + break; + case BCM43xx_PHYTYPE_G: + offset |= 0x80; + break; + } + + bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset); + return bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW); +} + +void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) +{ + bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset); + bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val); +} + +static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm, + s16 first, s16 second, s16 third) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 i; + u16 start = 0x08, end = 0x18; + u16 offset = 0x0400; + u16 tmp; + + if (phy->rev <= 1) { + offset = 0x5000; + start = 0x10; + end = 0x20; + } + + for (i = 0; i < 4; i++) + bcm43xx_ilt_write16(bcm, offset + i, first); + + for (i = start; i < end; i++) + bcm43xx_ilt_write16(bcm, offset + i, second); + + if (third != -1) { + tmp = ((u16)third << 14) | ((u16)third << 6); + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | tmp); + bcm43xx_phy_write(bcm, 0x04A1, + (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | tmp); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | tmp); + } + bcm43xx_dummy_transmission(bcm); +} + +static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 i, tmp; + u16 offset = 0x0400; + u16 start = 0x0008, end = 0x0018; + + if (phy->rev <= 1) { + offset = 0x5000; + start = 0x0010; + end = 0x0020; + } + + for (i = 0; i < 4; i++) { + tmp = (i & 0xFFFC); + tmp |= (i & 0x0001) << 1; + tmp |= (i & 0x0002) >> 1; + + bcm43xx_ilt_write16(bcm, offset + i, tmp); + } + + for (i = start; i < end; i++) + bcm43xx_ilt_write16(bcm, offset + i, i - start); + + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040); + bcm43xx_phy_write(bcm, 0x04A1, + (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | 0x4040); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | 0x4000); + bcm43xx_dummy_transmission(bcm); +} + +/* Synthetic PU workaround */ +static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + + if (radio->version != 0x2050 || radio->revision >= 6) { + /* We do not need the workaround. */ + return; + } + + if (channel <= 10) { + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, + channel2freq_bg(channel + 4)); + } else { + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, + channel2freq_bg(1)); + } + udelay(100); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, + channel2freq_bg(channel)); +} + +u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u8 ret = 0; + u16 saved, rssi, temp; + int i, j = 0; + + saved = bcm43xx_phy_read(bcm, 0x0403); + bcm43xx_radio_selectchannel(bcm, channel, 0); + bcm43xx_phy_write(bcm, 0x0403, (saved & 0xFFF8) | 5); + if (radio->aci_hw_rssi) + rssi = bcm43xx_phy_read(bcm, 0x048A) & 0x3F; + else + rssi = saved & 0x3F; + /* clamp temp to signed 5bit */ + if (rssi > 32) + rssi -= 64; + for (i = 0;i < 100; i++) { + temp = (bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x3F; + if (temp > 32) + temp -= 64; + if (temp < rssi) + j++; + if (j >= 20) + ret = 1; + } + bcm43xx_phy_write(bcm, 0x0403, saved); + + return ret; +} + +u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u8 ret[13]; + unsigned int channel = radio->channel; + unsigned int i, j, start, end; + unsigned long phylock_flags; + + if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0))) + return 0; + + bcm43xx_phy_lock(bcm, phylock_flags); + bcm43xx_radio_lock(bcm); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF); + bcm43xx_set_all_gains(bcm, 3, 8, 1); + + start = (channel - 5 > 0) ? channel - 5 : 1; + end = (channel + 5 < 14) ? channel + 5 : 13; + + for (i = start; i <= end; i++) { + if (abs(channel - i) > 2) + ret[i-1] = bcm43xx_radio_aci_detect(bcm, i); + } + bcm43xx_radio_selectchannel(bcm, channel, 0); + bcm43xx_phy_write(bcm, 0x0802, + (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC) | 0x0003); + bcm43xx_phy_write(bcm, 0x0403, + bcm43xx_phy_read(bcm, 0x0403) & 0xFFF8); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000); + bcm43xx_set_original_gains(bcm); + for (i = 0; i < 13; i++) { + if (!ret[i]) + continue; + end = (i + 5 < 13) ? i + 5 : 13; + for (j = i; j < end; j++) + ret[j] = 1; + } + bcm43xx_radio_unlock(bcm); + bcm43xx_phy_unlock(bcm, phylock_flags); + + return ret[channel - 1]; +} + +/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ +void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val) +{ + bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset); + bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val); +} + +/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ +s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset) +{ + u16 val; + + bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset); + val = bcm43xx_phy_read(bcm, BCM43xx_PHY_NRSSILT_DATA); + + return (s16)val; +} + +/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ +void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val) +{ + u16 i; + s16 tmp; + + for (i = 0; i < 64; i++) { + tmp = bcm43xx_nrssi_hw_read(bcm, i); + tmp -= val; + tmp = limit_value(tmp, -32, 31); + bcm43xx_nrssi_hw_write(bcm, i, tmp); + } +} + +/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ +void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm) +{ + s16 i, delta; + s32 tmp; + + delta = 0x1F - bcm->current_core->radio->nrssi[0]; + for (i = 0; i < 64; i++) { + tmp = (i - delta) * bcm->current_core->radio->nrssislope; + tmp /= 0x10000; + tmp += 0x3A; + tmp = limit_value(tmp, 0, 0x3F); + bcm->current_core->radio->nrssi_lt[i] = tmp; + } +} + +static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + u16 backup[20] = { 0 }; + s16 v47F; + u16 i; + u16 saved = 0xFFFF; + + backup[0] = bcm43xx_phy_read(bcm, 0x0001); + backup[1] = bcm43xx_phy_read(bcm, 0x0811); + backup[2] = bcm43xx_phy_read(bcm, 0x0812); + backup[3] = bcm43xx_phy_read(bcm, 0x0814); + backup[4] = bcm43xx_phy_read(bcm, 0x0815); + backup[5] = bcm43xx_phy_read(bcm, 0x005A); + backup[6] = bcm43xx_phy_read(bcm, 0x0059); + backup[7] = bcm43xx_phy_read(bcm, 0x0058); + backup[8] = bcm43xx_phy_read(bcm, 0x000A); + backup[9] = bcm43xx_phy_read(bcm, 0x0003); + backup[10] = bcm43xx_radio_read16(bcm, 0x007A); + backup[11] = bcm43xx_radio_read16(bcm, 0x0043); + + bcm43xx_phy_write(bcm, 0x0429, + bcm43xx_phy_read(bcm, 0x0429) & 0x7FFF); + bcm43xx_phy_write(bcm, 0x0001, + (bcm43xx_phy_read(bcm, 0x0001) & 0x3FFF) | 0x4000); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x000C); + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) & 0xFFF3) | 0x0004); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) & ~(0x1 | 0x2)); + if (phy->rev >= 6) { + backup[12] = bcm43xx_phy_read(bcm, 0x002E); + backup[13] = bcm43xx_phy_read(bcm, 0x002F); + backup[14] = bcm43xx_phy_read(bcm, 0x080F); + backup[15] = bcm43xx_phy_read(bcm, 0x0810); + backup[16] = bcm43xx_phy_read(bcm, 0x0801); + backup[17] = bcm43xx_phy_read(bcm, 0x0060); + backup[18] = bcm43xx_phy_read(bcm, 0x0014); + backup[19] = bcm43xx_phy_read(bcm, 0x0478); + + bcm43xx_phy_write(bcm, 0x002E, 0); + bcm43xx_phy_write(bcm, 0x002F, 0); + bcm43xx_phy_write(bcm, 0x080F, 0); + bcm43xx_phy_write(bcm, 0x0810, 0); + bcm43xx_phy_write(bcm, 0x0478, + bcm43xx_phy_read(bcm, 0x0478) | 0x0100); + bcm43xx_phy_write(bcm, 0x0801, + bcm43xx_phy_read(bcm, 0x0801) | 0x0040); + bcm43xx_phy_write(bcm, 0x0060, + bcm43xx_phy_read(bcm, 0x0060) | 0x0040); + bcm43xx_phy_write(bcm, 0x0014, + bcm43xx_phy_read(bcm, 0x0014) | 0x0200); + } + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0070); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); + udelay(30); + + v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (v47F >= 0x20) + v47F -= 0x40; + if (v47F == 31) { + for (i = 7; i >= 4; i--) { + bcm43xx_radio_write16(bcm, 0x007B, i); + udelay(20); + v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (v47F >= 0x20) + v47F -= 0x40; + if (v47F < 31 && saved == 0xFFFF) + saved = i; + } + if (saved == 0xFFFF) + saved = 4; + } else { + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0001); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x000C); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) | 0x000C); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x0030); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) | 0x0030); + bcm43xx_phy_write(bcm, 0x005A, 0x0480); + bcm43xx_phy_write(bcm, 0x0059, 0x0810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + if (phy->rev == 0) { + bcm43xx_phy_write(bcm, 0x0003, 0x0122); + } else { + bcm43xx_phy_write(bcm, 0x000A, + bcm43xx_phy_read(bcm, 0x000A) + | 0x2000); + } + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0004); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); + bcm43xx_phy_write(bcm, 0x0003, + (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) + | 0x0040); + bcm43xx_phy_write(bcm, 0x007A, + bcm43xx_phy_read(bcm, 0x007A) | 0x000F); + bcm43xx_set_all_gains(bcm, 3, 0, 1); + bcm43xx_radio_write16(bcm, 0x0043, + (bcm43xx_radio_read16(bcm, 0x0043) + & 0x00F0) | 0x000F); + udelay(30); + v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (v47F >= 0x20) + v47F -= 0x40; + if (v47F == -32) { + for (i = 0; i < 4; i++) { + bcm43xx_radio_write16(bcm, 0x007B, i); + udelay(20); + v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (v47F >= 0x20) + v47F -= 0x40; + if (v47F > -31 && saved == 0xFFFF) + saved = i; + } + if (saved == 0xFFFF) + saved = 3; + } else + saved = 0; + } + bcm43xx_radio_write16(bcm, 0x007B, saved); + + if (phy->rev >= 6) { + bcm43xx_phy_write(bcm, 0x002E, backup[12]); + bcm43xx_phy_write(bcm, 0x002F, backup[13]); + bcm43xx_phy_write(bcm, 0x080F, backup[14]); + bcm43xx_phy_write(bcm, 0x0810, backup[15]); + } + bcm43xx_phy_write(bcm, 0x0814, backup[3]); + bcm43xx_phy_write(bcm, 0x0815, backup[4]); + bcm43xx_phy_write(bcm, 0x005A, backup[5]); + bcm43xx_phy_write(bcm, 0x0059, backup[6]); + bcm43xx_phy_write(bcm, 0x0058, backup[7]); + bcm43xx_phy_write(bcm, 0x000A, backup[8]); + bcm43xx_phy_write(bcm, 0x0003, backup[9]); + bcm43xx_radio_write16(bcm, 0x0043, backup[11]); + bcm43xx_radio_write16(bcm, 0x007A, backup[10]); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2); + bcm43xx_phy_write(bcm, 0x0429, + bcm43xx_phy_read(bcm, 0x0429) | 0x8000); + bcm43xx_set_original_gains(bcm); + if (phy->rev >= 6) { + bcm43xx_phy_write(bcm, 0x0801, backup[16]); + bcm43xx_phy_write(bcm, 0x0060, backup[17]); + bcm43xx_phy_write(bcm, 0x0014, backup[18]); + bcm43xx_phy_write(bcm, 0x0478, backup[19]); + } + bcm43xx_phy_write(bcm, 0x0001, backup[0]); + bcm43xx_phy_write(bcm, 0x0812, backup[2]); + bcm43xx_phy_write(bcm, 0x0811, backup[1]); +} + +void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 backup[18] = { 0 }; + u16 tmp; + s16 nrssi0, nrssi1; + + switch (phy->type) { + case BCM43xx_PHYTYPE_B: + backup[0] = bcm43xx_radio_read16(bcm, 0x007A); + backup[1] = bcm43xx_radio_read16(bcm, 0x0052); + backup[2] = bcm43xx_radio_read16(bcm, 0x0043); + backup[3] = bcm43xx_phy_read(bcm, 0x0030); + backup[4] = bcm43xx_phy_read(bcm, 0x0026); + backup[5] = bcm43xx_phy_read(bcm, 0x0015); + backup[6] = bcm43xx_phy_read(bcm, 0x002A); + backup[7] = bcm43xx_phy_read(bcm, 0x0020); + backup[8] = bcm43xx_phy_read(bcm, 0x005A); + backup[9] = bcm43xx_phy_read(bcm, 0x0059); + backup[10] = bcm43xx_phy_read(bcm, 0x0058); + backup[11] = bcm43xx_read16(bcm, 0x03E2); + backup[12] = bcm43xx_read16(bcm, 0x03E6); + backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); + + tmp = bcm43xx_radio_read16(bcm, 0x007A); + tmp &= (phy->rev >= 5) ? 0x007F : 0x000F; + bcm43xx_radio_write16(bcm, 0x007A, tmp); + bcm43xx_phy_write(bcm, 0x0030, 0x00FF); + bcm43xx_write16(bcm, 0x03EC, 0x7F7F); + bcm43xx_phy_write(bcm, 0x0026, 0x0000); + bcm43xx_phy_write(bcm, 0x0015, + bcm43xx_phy_read(bcm, 0x0015) | 0x0020); + bcm43xx_phy_write(bcm, 0x002A, 0x08A3); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); + + nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); + if (phy->rev >= 2) { + bcm43xx_write16(bcm, 0x03E6, 0x0040); + } else if (phy->rev == 0) { + bcm43xx_write16(bcm, 0x03E6, 0x0122); + } else { + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, + bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000); + } + bcm43xx_phy_write(bcm, 0x0020, 0x3F3F); + bcm43xx_phy_write(bcm, 0x0015, 0xF330); + bcm43xx_radio_write16(bcm, 0x005A, 0x0060); + bcm43xx_radio_write16(bcm, 0x0043, + bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0); + bcm43xx_phy_write(bcm, 0x005A, 0x0480); + bcm43xx_phy_write(bcm, 0x0059, 0x0810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + udelay(20); + + nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027); + bcm43xx_phy_write(bcm, 0x0030, backup[3]); + bcm43xx_radio_write16(bcm, 0x007A, backup[0]); + bcm43xx_write16(bcm, 0x03E2, backup[11]); + bcm43xx_phy_write(bcm, 0x0026, backup[4]); + bcm43xx_phy_write(bcm, 0x0015, backup[5]); + bcm43xx_phy_write(bcm, 0x002A, backup[6]); + bcm43xx_synth_pu_workaround(bcm, radio->channel); + if (phy->rev != 0) + bcm43xx_write16(bcm, 0x03F4, backup[13]); + + bcm43xx_phy_write(bcm, 0x0020, backup[7]); + bcm43xx_phy_write(bcm, 0x005A, backup[8]); + bcm43xx_phy_write(bcm, 0x0059, backup[9]); + bcm43xx_phy_write(bcm, 0x0058, backup[10]); + bcm43xx_radio_write16(bcm, 0x0052, backup[1]); + bcm43xx_radio_write16(bcm, 0x0043, backup[2]); + + if (nrssi0 == nrssi1) + radio->nrssislope = 0x00010000; + else + radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1); + + if (nrssi0 <= -4) { + radio->nrssi[0] = nrssi0; + radio->nrssi[1] = nrssi1; + } + break; + case BCM43xx_PHYTYPE_G: +//FIXME: Something is broken here. This is called when enabling WLAN interfmode. +// If this is done at runtime, I get an XMIT ERROR and transmission is +// broken. I guess some important register is overwritten by accident. +// The XMIT ERROR comes from the dummy_transmissions in set_gains. + if (radio->revision >= 9) + return; + if (radio->revision == 8) + bcm43xx_calc_nrssi_offset(bcm); + + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC); + backup[7] = bcm43xx_read16(bcm, 0x03E2); + bcm43xx_write16(bcm, 0x03E2, + bcm43xx_read16(bcm, 0x03E2) | 0x8000); + backup[0] = bcm43xx_radio_read16(bcm, 0x007A); + backup[1] = bcm43xx_radio_read16(bcm, 0x0052); + backup[2] = bcm43xx_radio_read16(bcm, 0x0043); + backup[3] = bcm43xx_phy_read(bcm, 0x0015); + backup[4] = bcm43xx_phy_read(bcm, 0x005A); + backup[5] = bcm43xx_phy_read(bcm, 0x0059); + backup[6] = bcm43xx_phy_read(bcm, 0x0058); + backup[8] = bcm43xx_read16(bcm, 0x03E6); + backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); + if (phy->rev >= 3) { + backup[10] = bcm43xx_phy_read(bcm, 0x002E); + backup[11] = bcm43xx_phy_read(bcm, 0x002F); + backup[12] = bcm43xx_phy_read(bcm, 0x080F); + backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL); + backup[14] = bcm43xx_phy_read(bcm, 0x0801); + backup[15] = bcm43xx_phy_read(bcm, 0x0060); + backup[16] = bcm43xx_phy_read(bcm, 0x0014); + backup[17] = bcm43xx_phy_read(bcm, 0x0478); + bcm43xx_phy_write(bcm, 0x002E, 0); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0); + switch (phy->rev) { + case 4: case 6: case 7: + bcm43xx_phy_write(bcm, 0x0478, + bcm43xx_phy_read(bcm, 0x0478) + | 0x0100); + bcm43xx_phy_write(bcm, 0x0801, + bcm43xx_phy_read(bcm, 0x0801) + | 0x0040); + break; + case 3: case 5: + bcm43xx_phy_write(bcm, 0x0801, + bcm43xx_phy_read(bcm, 0x0801) + & 0xFFBF); + break; + } + bcm43xx_phy_write(bcm, 0x0060, + bcm43xx_phy_read(bcm, 0x0060) + | 0x0040); + bcm43xx_phy_write(bcm, 0x0014, + bcm43xx_phy_read(bcm, 0x0014) + | 0x0200); + } + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0070); + bcm43xx_set_all_gains(bcm, 0, 8, 0); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7); + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0811, + (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030); + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010); + } + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); + udelay(20); + + nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (nrssi0 >= 0x0020) + nrssi0 -= 0x0040; + + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0003, + (bcm43xx_phy_read(bcm, 0x0003) + & 0xFF9F) | 0x0040); + } + + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, + bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) + | 0x2000); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x000F); + bcm43xx_phy_write(bcm, 0x0015, 0xF330); + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020); + bcm43xx_phy_write(bcm, 0x0811, + (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020); + } + + bcm43xx_set_all_gains(bcm, 3, 0, 1); + if (radio->revision == 8) { + bcm43xx_radio_write16(bcm, 0x0043, 0x001F); + } else { + tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F; + bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060); + tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0; + bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009); + } + bcm43xx_phy_write(bcm, 0x005A, 0x0480); + bcm43xx_phy_write(bcm, 0x0059, 0x0810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + udelay(20); + nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); + if (nrssi1 >= 0x0020) + nrssi1 -= 0x0040; + if (nrssi0 == nrssi1) + radio->nrssislope = 0x00010000; + else + radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1); + if (nrssi0 >= -4) { + radio->nrssi[0] = nrssi1; + radio->nrssi[1] = nrssi0; + } + if (phy->rev >= 3) { + bcm43xx_phy_write(bcm, 0x002E, backup[10]); + bcm43xx_phy_write(bcm, 0x002F, backup[11]); + bcm43xx_phy_write(bcm, 0x080F, backup[12]); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]); + } + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF); + } + + bcm43xx_radio_write16(bcm, 0x007A, backup[0]); + bcm43xx_radio_write16(bcm, 0x0052, backup[1]); + bcm43xx_radio_write16(bcm, 0x0043, backup[2]); + bcm43xx_write16(bcm, 0x03E2, backup[7]); + bcm43xx_write16(bcm, 0x03E6, backup[8]); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]); + bcm43xx_phy_write(bcm, 0x0015, backup[3]); + bcm43xx_phy_write(bcm, 0x005A, backup[4]); + bcm43xx_phy_write(bcm, 0x0059, backup[5]); + bcm43xx_phy_write(bcm, 0x0058, backup[6]); + bcm43xx_synth_pu_workaround(bcm, radio->channel); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002)); + bcm43xx_set_original_gains(bcm); + bcm43xx_phy_write(bcm, 0x0802, + bcm43xx_phy_read(bcm, 0x0802) | 0x8000); + if (phy->rev >= 3) { + bcm43xx_phy_write(bcm, 0x0801, backup[14]); + bcm43xx_phy_write(bcm, 0x0060, backup[15]); + bcm43xx_phy_write(bcm, 0x0014, backup[16]); + bcm43xx_phy_write(bcm, 0x0478, backup[17]); + } + bcm43xx_nrssi_mem_update(bcm); + bcm43xx_calc_nrssi_threshold(bcm); + break; + default: + assert(0); + } +} + +void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + s16 threshold; + s32 a, b; + int tmp; + s16 tmp16; + u16 tmp_u16; + + switch (phy->type) { + case BCM43xx_PHYTYPE_B: { + int radiotype = 0; + + if (phy->rev < 2) + return; + if (radio->version != 0x2050) + return; + if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) + return; + + tmp = radio->revision; + if ((radio->manufact == 0x175 && tmp == 5) || + (radio->manufact == 0x17F && (tmp == 3 || tmp == 4))) + radiotype = 1; + + if (radiotype == 1) { + threshold = bcm->current_core->radio->nrssi[1] - 5; + } else { + threshold = 40 * radio->nrssi[0]; + threshold += 33 * (radio->nrssi[1] - radio->nrssi[0]); + threshold += 20; + threshold /= 10; + } + threshold = limit_value(threshold, 0, 0x3E); + bcm43xx_phy_read(bcm, 0x0020); /* dummy read */ + bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C); + + if (radiotype == 1) { + bcm43xx_phy_write(bcm, 0x0087, 0x0E0D); + bcm43xx_phy_write(bcm, 0x0086, 0x0C0B); + bcm43xx_phy_write(bcm, 0x0085, 0x0A09); + bcm43xx_phy_write(bcm, 0x0084, 0x0808); + bcm43xx_phy_write(bcm, 0x0083, 0x0808); + bcm43xx_phy_write(bcm, 0x0082, 0x0604); + bcm43xx_phy_write(bcm, 0x0081, 0x0302); + bcm43xx_phy_write(bcm, 0x0080, 0x0100); + } + break; + } + case BCM43xx_PHYTYPE_G: + if (!phy->connected || + !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) { + tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20); + if (tmp16 >= 0x20) + tmp16 -= 0x40; + if (tmp16 < 3) { + bcm43xx_phy_write(bcm, 0x048A, + (bcm43xx_phy_read(bcm, 0x048A) + & 0xF000) | 0x09EB); + } else { + bcm43xx_phy_write(bcm, 0x048A, + (bcm43xx_phy_read(bcm, 0x048A) + & 0xF000) | 0x0AED); + } + } else { + tmp = radio->interfmode; + if (tmp == BCM43xx_RADIO_INTERFMODE_NONWLAN) { + a = -13; + b = -17; + } else if (tmp == BCM43xx_RADIO_INTERFMODE_NONE && + !radio->aci_enable) { + a = -13; + b = -10; + } else { + a = -8; + b = -9; + } + a += 0x1B; + a *= radio->nrssi[1] - radio->nrssi[0]; + a += radio->nrssi[0] * 0x40; + a /= 64; + b += 0x1B; + b *= radio->nrssi[1] - radio->nrssi[0]; + b += radio->nrssi[0] * 0x40; + b /= 64; + + a = limit_value(a, -31, 31); + b = limit_value(b, -31, 31); + + tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000; + tmp_u16 |= ((u32)a & 0x003F); + tmp_u16 |= (((u32)b & 0x003F) << 6); + bcm43xx_phy_write(bcm, 0x048A, tmp_u16); + } + break; + default: + assert(0); + } +} + +/* Helper macros to save on and restore values from the radio->interfstack */ +#ifdef stack_save +# undef stack_save +#endif +#ifdef stack_restore +# undef stack_restore +#endif +#define stack_save(value) \ + do { \ + assert(i < ARRAY_SIZE(radio->interfstack)); \ + stack[i++] = (value); \ + } while (0) + +#define stack_restore() \ + ({ \ + assert(i < ARRAY_SIZE(radio->interfstack)); \ + stack[i++]; \ + }) + +static void +bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, + int mode) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + int i = 0; + u16 *stack = radio->interfstack; + u16 tmp, flipped; + + switch (mode) { + case BCM43xx_RADIO_INTERFMODE_NONWLAN: + if (phy->rev != 1) { + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) & 0x0800); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000); + break; + } + tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); + flipped = flip_4bit(tmp); + if ((flipped >> 1) >= 4) + tmp = flipped - 3; + tmp = flip_4bit(tmp); + bcm43xx_radio_write16(bcm, 0x0078, tmp << 1); + + bcm43xx_calc_nrssi_threshold(bcm); + + if (bcm->current_core->rev < 5) { + stack_save(bcm43xx_phy_read(bcm, 0x0406)); + bcm43xx_phy_write(bcm, 0x0406, 0x7E28); + } else { + stack_save(bcm43xx_phy_read(bcm, 0x04C0)); + stack_save(bcm43xx_phy_read(bcm, 0x04C1)); + bcm43xx_phy_write(bcm, 0x04C0, 0x3E04); + bcm43xx_phy_write(bcm, 0x04C1, 0x0640); + } + + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) | 0x0800); + bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000); + + stack_save(bcm43xx_phy_read(bcm, 0x04A0)); + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008); + stack_save(bcm43xx_phy_read(bcm, 0x04A1)); + bcm43xx_phy_write(bcm, 0x04A1, + (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605); + stack_save(bcm43xx_phy_read(bcm, 0x04A2)); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204); + stack_save(bcm43xx_phy_read(bcm, 0x04A8)); + bcm43xx_phy_write(bcm, 0x04A8, + (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0403); + stack_save(bcm43xx_phy_read(bcm, 0x04AB)); + bcm43xx_phy_write(bcm, 0x04AB, + (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0504); + + stack_save(bcm43xx_phy_read(bcm, 0x04A7)); + bcm43xx_phy_write(bcm, 0x04A7, 0x0002); + stack_save(bcm43xx_phy_read(bcm, 0x04A3)); + bcm43xx_phy_write(bcm, 0x04A3, 0x287A); + stack_save(bcm43xx_phy_read(bcm, 0x04A9)); + bcm43xx_phy_write(bcm, 0x04A9, 0x2027); + stack_save(bcm43xx_phy_read(bcm, 0x0493)); + bcm43xx_phy_write(bcm, 0x0493, 0x32F5); + stack_save(bcm43xx_phy_read(bcm, 0x04AA)); + bcm43xx_phy_write(bcm, 0x04AA, 0x2027); + stack_save(bcm43xx_phy_read(bcm, 0x04AC)); + bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); + break; + case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: + if (bcm43xx_phy_read(bcm, 0x0033) == 0x0800) + break; + + radio->aci_enable = 1; + + stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)); + stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)); + if (bcm->current_core->rev < 5) { + stack_save(bcm43xx_phy_read(bcm, 0x0406)); + } else { + stack_save(bcm43xx_phy_read(bcm, 0x04C0)); + stack_save(bcm43xx_phy_read(bcm, 0x04C1)); + } + stack_save(bcm43xx_phy_read(bcm, 0x0033)); + stack_save(bcm43xx_phy_read(bcm, 0x04A7)); + stack_save(bcm43xx_phy_read(bcm, 0x04A3)); + stack_save(bcm43xx_phy_read(bcm, 0x04A9)); + stack_save(bcm43xx_phy_read(bcm, 0x04AA)); + stack_save(bcm43xx_phy_read(bcm, 0x04AC)); + stack_save(bcm43xx_phy_read(bcm, 0x0493)); + stack_save(bcm43xx_phy_read(bcm, 0x04A1)); + stack_save(bcm43xx_phy_read(bcm, 0x04A0)); + stack_save(bcm43xx_phy_read(bcm, 0x04A2)); + stack_save(bcm43xx_phy_read(bcm, 0x048A)); + stack_save(bcm43xx_phy_read(bcm, 0x04A8)); + stack_save(bcm43xx_phy_read(bcm, 0x04AB)); + + bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & 0xEFFF); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xEFFF) | 0x0002); + + bcm43xx_phy_write(bcm, 0x04A7, 0x0800); + bcm43xx_phy_write(bcm, 0x04A3, 0x287A); + bcm43xx_phy_write(bcm, 0x04A9, 0x2027); + bcm43xx_phy_write(bcm, 0x0493, 0x32F5); + bcm43xx_phy_write(bcm, 0x04AA, 0x2027); + bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); + + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFC0) | 0x001A); + if (bcm->current_core->rev < 5) { + bcm43xx_phy_write(bcm, 0x0406, 0x280D); + } else { + bcm43xx_phy_write(bcm, 0x04C0, 0x0640); + bcm43xx_phy_write(bcm, 0x04C1, 0x00A9); + } + + bcm43xx_phy_write(bcm, 0x04A1, + (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0FF) | 0x1800); + bcm43xx_phy_write(bcm, 0x04A1, + (bcm43xx_phy_read(bcm, 0x04A1) & 0xFFC0) | 0x0016); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0900); + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0700); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x000D); + bcm43xx_phy_write(bcm, 0x04A8, + (bcm43xx_phy_read(bcm, 0x04A8) & 0xCFFF) | 0x1000); + bcm43xx_phy_write(bcm, 0x04A8, + (bcm43xx_phy_read(bcm, 0x04A8) & 0xF0FF) | 0x0A00); + bcm43xx_phy_write(bcm, 0x04AB, + (bcm43xx_phy_read(bcm, 0x04AB) & 0xCFFF) | 0x1000); + bcm43xx_phy_write(bcm, 0x04AB, + (bcm43xx_phy_read(bcm, 0x04AB) & 0xF0FF) | 0x0800); + bcm43xx_phy_write(bcm, 0x04AB, + (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFCF) | 0x0010); + bcm43xx_phy_write(bcm, 0x04AB, + (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFF0) | 0x0006); + + bcm43xx_calc_nrssi_slope(bcm); + break; + default: + assert(0); + } +} + +static void +bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, + int mode) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + int i = 0; + u16 *stack = radio->interfstack; + u16 tmp, flipped; + + switch (mode) { + case BCM43xx_RADIO_INTERFMODE_NONWLAN: + if (phy->rev != 1) { + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); + break; + } + tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); + flipped = flip_4bit(tmp); + if ((flipped >> 1) >= 0x000C) + tmp = flipped + 3; + tmp = flip_4bit(tmp); + bcm43xx_radio_write16(bcm, 0x0078, tmp << 1); + + bcm43xx_calc_nrssi_threshold(bcm); + + if (bcm->current_core->rev < 5) { + bcm43xx_phy_write(bcm, 0x0406, stack_restore()); + } else { + bcm43xx_phy_write(bcm, 0x04C0, stack_restore()); + bcm43xx_phy_write(bcm, 0x04C1, stack_restore()); + } + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); + + if (!bcm->bad_frames_preempt) + bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & ~(1 << 11)); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); + bcm43xx_phy_write(bcm, 0x04A0, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A1, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A2, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A8, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AB, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A7, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A3, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A9, stack_restore()); + bcm43xx_phy_write(bcm, 0x0493, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AA, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AC, stack_restore()); + break; + case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: + if (bcm43xx_phy_read(bcm, 0x0033) != 0x0800) + break; + + radio->aci_enable = 0; + + bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, stack_restore()); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, stack_restore()); + if (bcm->current_core->rev < 5) { + bcm43xx_phy_write(bcm, 0x0406, stack_restore()); + } else { + bcm43xx_phy_write(bcm, 0x04C0, stack_restore()); + bcm43xx_phy_write(bcm, 0x04C1, stack_restore()); + } + bcm43xx_phy_write(bcm, 0x0033, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A7, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A3, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A9, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AA, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AC, stack_restore()); + bcm43xx_phy_write(bcm, 0x0493, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A1, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A0, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A2, stack_restore()); + bcm43xx_phy_write(bcm, 0x04A8, stack_restore()); + bcm43xx_phy_write(bcm, 0x04AB, stack_restore()); + + bcm43xx_calc_nrssi_slope(bcm); + break; + default: + assert(0); + } +} + +#undef stack_save +#undef stack_restore + +int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, + int mode) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + int currentmode; + + if ((phy->type != BCM43xx_PHYTYPE_G) || + (phy->rev == 0) || + (!phy->connected)) + return -ENODEV; + + radio->aci_wlan_automatic = 0; + switch (mode) { + case BCM43xx_RADIO_INTERFMODE_AUTOWLAN: + radio->aci_wlan_automatic = 1; + if (radio->aci_enable) + mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; + else + mode = BCM43xx_RADIO_INTERFMODE_NONE; + break; + case BCM43xx_RADIO_INTERFMODE_NONE: + case BCM43xx_RADIO_INTERFMODE_NONWLAN: + case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: + break; + default: + return -EINVAL; + } + + currentmode = radio->interfmode; + if (currentmode == mode) + return 0; + if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE) + bcm43xx_radio_interference_mitigation_disable(bcm, currentmode); + + if (mode == BCM43xx_RADIO_INTERFMODE_NONE) { + radio->aci_enable = 0; + radio->aci_hw_rssi = 0; + } else + bcm43xx_radio_interference_mitigation_enable(bcm, mode); + radio->interfmode = mode; + + return 0; +} + +static u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm) +{ + u16 reg, index, ret; + + reg = bcm43xx_radio_read16(bcm, 0x0060); + index = (reg & 0x001E) >> 1; + ret = rcc_table[index] << 1; + ret |= (reg & 0x0001); + ret |= 0x0020; + + return ret; +} + +u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 backup[19] = { 0 }; + u16 ret; + u16 i, j; + u32 tmp1 = 0, tmp2 = 0; + + backup[0] = bcm43xx_radio_read16(bcm, 0x0043); + backup[14] = bcm43xx_radio_read16(bcm, 0x0051); + backup[15] = bcm43xx_radio_read16(bcm, 0x0052); + backup[1] = bcm43xx_phy_read(bcm, 0x0015); + backup[16] = bcm43xx_phy_read(bcm, 0x005A); + backup[17] = bcm43xx_phy_read(bcm, 0x0059); + backup[18] = bcm43xx_phy_read(bcm, 0x0058); + if (phy->type == BCM43xx_PHYTYPE_B) { + backup[2] = bcm43xx_phy_read(bcm, 0x0030); + backup[3] = bcm43xx_read16(bcm, 0x03EC); + bcm43xx_phy_write(bcm, 0x0030, 0x00FF); + bcm43xx_write16(bcm, 0x03EC, 0x3F3F); + } else { + if (phy->connected) { + backup[4] = bcm43xx_phy_read(bcm, 0x0811); + backup[5] = bcm43xx_phy_read(bcm, 0x0812); + backup[6] = bcm43xx_phy_read(bcm, 0x0814); + backup[7] = bcm43xx_phy_read(bcm, 0x0815); + backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS); + backup[9] = bcm43xx_phy_read(bcm, 0x0802); + bcm43xx_phy_write(bcm, 0x0814, + (bcm43xx_phy_read(bcm, 0x0814) | 0x0003)); + bcm43xx_phy_write(bcm, 0x0815, + (bcm43xx_phy_read(bcm, 0x0815) & 0xFFFC)); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF)); + bcm43xx_phy_write(bcm, 0x0802, + (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC)); + bcm43xx_phy_write(bcm, 0x0811, 0x01B3); + bcm43xx_phy_write(bcm, 0x0812, 0x0FB2); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, + (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000)); + } + backup[10] = bcm43xx_phy_read(bcm, 0x0035); + bcm43xx_phy_write(bcm, 0x0035, + (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F)); + backup[11] = bcm43xx_read16(bcm, 0x03E6); + backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); + + // Initialization + if (phy->version == 0) { + bcm43xx_write16(bcm, 0x03E6, 0x0122); + } else { + if (phy->version >= 2) + bcm43xx_write16(bcm, 0x03E6, 0x0040); + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, + (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000)); + } + + ret = bcm43xx_radio_calibrationvalue(bcm); + + if (phy->type == BCM43xx_PHYTYPE_B) + bcm43xx_radio_write16(bcm, 0x0078, 0x0003); + + bcm43xx_phy_write(bcm, 0x0015, 0xBFAF); + bcm43xx_phy_write(bcm, 0x002B, 0x1403); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x00B2); + bcm43xx_phy_write(bcm, 0x0015, 0xBFA0); + bcm43xx_radio_write16(bcm, 0x0051, + (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004)); + bcm43xx_radio_write16(bcm, 0x0052, 0x0000); + bcm43xx_radio_write16(bcm, 0x0043, + bcm43xx_radio_read16(bcm, 0x0043) | 0x0009); + bcm43xx_phy_write(bcm, 0x0058, 0x0000); + + for (i = 0; i < 16; i++) { + bcm43xx_phy_write(bcm, 0x005A, 0x0480); + bcm43xx_phy_write(bcm, 0x0059, 0xC810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); + udelay(10); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); + udelay(10); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); + udelay(10); + tmp1 += bcm43xx_phy_read(bcm, 0x002D); + bcm43xx_phy_write(bcm, 0x0058, 0x0000); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); + } + + tmp1++; + tmp1 >>= 9; + udelay(10); + bcm43xx_phy_write(bcm, 0x0058, 0x0000); + + for (i = 0; i < 16; i++) { + bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020); + backup[13] = bcm43xx_radio_read16(bcm, 0x0078); + udelay(10); + for (j = 0; j < 16; j++) { + bcm43xx_phy_write(bcm, 0x005A, 0x0D80); + bcm43xx_phy_write(bcm, 0x0059, 0xC810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); + udelay(10); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); + udelay(10); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B3); /* 0x30B3 is not a typo */ + bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); + udelay(10); + tmp2 += bcm43xx_phy_read(bcm, 0x002D); + bcm43xx_phy_write(bcm, 0x0058, 0x0000); + if (phy->connected) + bcm43xx_phy_write(bcm, 0x0812, 0x30B2); + bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); + } + tmp2++; + tmp2 >>= 8; + if (tmp1 < tmp2) + break; + } + + /* Restore the registers */ + bcm43xx_phy_write(bcm, 0x0015, backup[1]); + bcm43xx_radio_write16(bcm, 0x0051, backup[14]); + bcm43xx_radio_write16(bcm, 0x0052, backup[15]); + bcm43xx_radio_write16(bcm, 0x0043, backup[0]); + bcm43xx_phy_write(bcm, 0x005A, backup[16]); + bcm43xx_phy_write(bcm, 0x0059, backup[17]); + bcm43xx_phy_write(bcm, 0x0058, backup[18]); + bcm43xx_write16(bcm, 0x03E6, backup[11]); + if (phy->version != 0) + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]); + bcm43xx_phy_write(bcm, 0x0035, backup[10]); + bcm43xx_radio_selectchannel(bcm, radio->channel, 1); + if (phy->type == BCM43xx_PHYTYPE_B) { + bcm43xx_phy_write(bcm, 0x0030, backup[2]); + bcm43xx_write16(bcm, 0x03EC, backup[3]); + } else { + bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, + (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) & 0x7FFF)); + if (phy->connected) { + bcm43xx_phy_write(bcm, 0x0811, backup[4]); + bcm43xx_phy_write(bcm, 0x0812, backup[5]); + bcm43xx_phy_write(bcm, 0x0814, backup[6]); + bcm43xx_phy_write(bcm, 0x0815, backup[7]); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]); + bcm43xx_phy_write(bcm, 0x0802, backup[9]); + } + } + if (i >= 15) + ret = backup[13]; + + return ret; +} + +void bcm43xx_radio_init2060(struct bcm43xx_private *bcm) +{ + int err; + + bcm43xx_radio_write16(bcm, 0x0004, 0x00C0); + bcm43xx_radio_write16(bcm, 0x0005, 0x0008); + bcm43xx_radio_write16(bcm, 0x0009, 0x0040); + bcm43xx_radio_write16(bcm, 0x0005, 0x00AA); + bcm43xx_radio_write16(bcm, 0x0032, 0x008F); + bcm43xx_radio_write16(bcm, 0x0006, 0x008F); + bcm43xx_radio_write16(bcm, 0x0034, 0x008F); + bcm43xx_radio_write16(bcm, 0x002C, 0x0007); + bcm43xx_radio_write16(bcm, 0x0082, 0x0080); + bcm43xx_radio_write16(bcm, 0x0080, 0x0000); + bcm43xx_radio_write16(bcm, 0x003F, 0x00DA); + bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008); + bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010); + bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020); + bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020); + udelay(400); + + bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010); + udelay(400); + + bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008); + bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010); + bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008); + bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040); + bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040); + bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008); + bcm43xx_phy_write(bcm, 0x0063, 0xDDC6); + bcm43xx_phy_write(bcm, 0x0069, 0x07BE); + bcm43xx_phy_write(bcm, 0x006A, 0x0000); + + err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0); + assert(err == 0); + udelay(1000); +} + +static inline +u16 freq_r3A_value(u16 frequency) +{ + u16 value; + + if (frequency < 5091) + value = 0x0040; + else if (frequency < 5321) + value = 0x0000; + else if (frequency < 5806) + value = 0x0080; + else + value = 0x0040; + + return value; +} + +void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm) +{ + static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; + static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; + u16 tmp = bcm43xx_radio_read16(bcm, 0x001E); + int i, j; + + for (i = 0; i < 5; i++) { + for (j = 0; j < 5; j++) { + if (tmp == (data_high[i] << 4 | data_low[j])) { + bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0); + return; + } + } + } +} + +int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, + u8 channel, + int synthetic_pu_workaround) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + u16 r8, tmp; + u16 freq; + + if ((radio->manufact == 0x17F) && + (radio->version == 0x2060) && + (radio->revision == 1)) { + if (channel > 200) + return -EINVAL; + freq = channel2freq_a(channel); + + r8 = bcm43xx_radio_read16(bcm, 0x0008); + bcm43xx_write16(bcm, 0x03F0, freq); + bcm43xx_radio_write16(bcm, 0x0008, r8); + + TODO();//TODO: write max channel TX power? to Radio 0x2D + tmp = bcm43xx_radio_read16(bcm, 0x002E); + tmp &= 0x0080; + TODO();//TODO: OR tmp with the Power out estimation for this channel? + bcm43xx_radio_write16(bcm, 0x002E, tmp); + + if (freq >= 4920 && freq <= 5500) { + /* + * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F; + * = (freq * 0.025862069 + */ + r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */ + } + bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8); + bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8); + bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8); + bcm43xx_radio_write16(bcm, 0x0022, + (bcm43xx_radio_read16(bcm, 0x0022) + & 0x000F) | (r8 << 4)); + bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4)); + bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4)); + bcm43xx_radio_write16(bcm, 0x0008, + (bcm43xx_radio_read16(bcm, 0x0008) + & 0x00F0) | (r8 << 4)); + bcm43xx_radio_write16(bcm, 0x0029, + (bcm43xx_radio_read16(bcm, 0x0029) + & 0xFF0F) | 0x00B0); + bcm43xx_radio_write16(bcm, 0x0035, 0x00AA); + bcm43xx_radio_write16(bcm, 0x0036, 0x0085); + bcm43xx_radio_write16(bcm, 0x003A, + (bcm43xx_radio_read16(bcm, 0x003A) + & 0xFF20) | freq_r3A_value(freq)); + bcm43xx_radio_write16(bcm, 0x003D, + bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF); + bcm43xx_radio_write16(bcm, 0x0081, + (bcm43xx_radio_read16(bcm, 0x0081) + & 0xFF7F) | 0x0080); + bcm43xx_radio_write16(bcm, 0x0035, + bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF); + bcm43xx_radio_write16(bcm, 0x0035, + (bcm43xx_radio_read16(bcm, 0x0035) + & 0xFFEF) | 0x0010); + bcm43xx_radio_set_tx_iq(bcm); + TODO(); //TODO: TSSI2dbm workaround + bcm43xx_phy_xmitpower(bcm);//FIXME correct? + } else { + if ((channel < 1) || (channel > 14)) + return -EINVAL; + + if (synthetic_pu_workaround) + bcm43xx_synth_pu_workaround(bcm, channel); + + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, + channel2freq_bg(channel)); + + if (channel == 14) { + if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) { + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET) + & ~(1 << 7)); + } else { + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET) + | (1 << 7)); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, + bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) + | (1 << 11)); + } else { + bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, + bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) + & 0xF7BF); + } + } + + radio->channel = channel; + //XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states + // that 2000 usecs might suffice. + udelay(8000); + + return 0; +} + +void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val) +{ + u16 tmp; + + val <<= 8; + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF; + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val); + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF; + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val); + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF; + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val); +} + +/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */ +static u16 bcm43xx_get_txgain_base_band(u16 txpower) +{ + u16 ret; + + assert(txpower <= 63); + + if (txpower >= 54) + ret = 2; + else if (txpower >= 49) + ret = 4; + else if (txpower >= 44) + ret = 5; + else + ret = 6; + + return ret; +} + +/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */ +static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower) +{ + u16 ret; + + assert(txpower <= 63); + + if (txpower >= 32) + ret = 0; + else if (txpower >= 25) + ret = 1; + else if (txpower >= 20) + ret = 2; + else if (txpower >= 12) + ret = 3; + else + ret = 4; + + return ret; +} + +/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */ +static u16 bcm43xx_get_txgain_dac(u16 txpower) +{ + u16 ret; + + assert(txpower <= 63); + + if (txpower >= 54) + ret = txpower - 53; + else if (txpower >= 49) + ret = txpower - 42; + else if (txpower >= 44) + ret = txpower - 37; + else if (txpower >= 32) + ret = txpower - 32; + else if (txpower >= 25) + ret = txpower - 20; + else if (txpower >= 20) + ret = txpower - 13; + else if (txpower >= 12) + ret = txpower - 8; + else + ret = txpower; + + return ret; +} + +void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) +{ + u16 pamp, base, dac, ilt; + + txpower = limit_value(txpower, 0, 63); + + pamp = bcm43xx_get_txgain_freq_power_amp(txpower); + pamp <<= 5; + pamp &= 0x00E0; + bcm43xx_phy_write(bcm, 0x0019, pamp); + + base = bcm43xx_get_txgain_base_band(txpower); + base &= 0x000F; + bcm43xx_phy_write(bcm, 0x0017, base | 0x0020); + + ilt = bcm43xx_ilt_read16(bcm, 0x3001); + ilt &= 0x0007; + + dac = bcm43xx_get_txgain_dac(txpower); + dac <<= 3; + dac |= ilt; + + bcm43xx_ilt_write16(bcm, 0x3001, dac); + + bcm->current_core->radio->txpower[0] = txpower; + + TODO(); + //TODO: FuncPlaceholder (Adjust BB loft cancel) +} + +void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, + u16 baseband_attenuation, u16 radio_attenuation, + u16 txpower) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + + if (baseband_attenuation == 0xFFFF) + baseband_attenuation = radio->txpower[0]; + else + radio->txpower[0] = baseband_attenuation; + if (radio_attenuation == 0xFFFF) + radio_attenuation = radio->txpower[1]; + else + radio->txpower[1] = radio_attenuation; + if (txpower == 0xFFFF) + txpower = radio->txpower[2]; + else + radio->txpower[2] = txpower; + + assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11); + if (radio->revision < 6) + assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9); + else + assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31); + assert(/*txpower >= 0 &&*/ txpower <= 7); + + bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation); + bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation); + if (radio->version == 0x2050) { + bcm43xx_radio_write16(bcm, 0x0052, + (bcm43xx_radio_read16(bcm, 0x0052) & 0xFF8F) + | (txpower << 4)); + } + if (phy->type == BCM43xx_PHYTYPE_G) + bcm43xx_phy_lo_adjust(bcm, 0); +} + + +void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + int err; + + if (radio->enabled) + return; + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + bcm43xx_radio_write16(bcm, 0x0004, 0x00C0); + bcm43xx_radio_write16(bcm, 0x0005, 0x0008); + bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7); + bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7); + bcm43xx_radio_init2060(bcm); + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + bcm43xx_phy_write(bcm, 0x0015, 0x8000); + bcm43xx_phy_write(bcm, 0x0015, 0xCC00); + bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000)); + err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1); + assert(err == 0); + break; + default: + assert(0); + } + radio->enabled = 1; + dprintk(KERN_INFO PFX "Radio turned on\n"); +} + +void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + + if (phy->type == BCM43xx_PHYTYPE_A) { + bcm43xx_radio_write16(bcm, 0x0004, 0x00FF); + bcm43xx_radio_write16(bcm, 0x0005, 0x00FB); + bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008); + bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008); + } + if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) { + bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C); + bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73); + } else + bcm43xx_phy_write(bcm, 0x0015, 0xAA00); + radio->enabled = 0; + dprintk(KERN_INFO PFX "Radio turned off\n"); +} + +void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm) +{ + switch (bcm->current_core->phy->type) { + case BCM43xx_PHYTYPE_A: + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F); + break; + case BCM43xx_PHYTYPE_B: + case BCM43xx_PHYTYPE_G: + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F); + break; + } +} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h new file mode 100644 index 0000000000..89fe292821 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h @@ -0,0 +1,93 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef BCM43xx_RADIO_H_ +#define BCM43xx_RADIO_H_ + +#include "bcm43xx.h" + + +#define BCM43xx_RADIO_DEFAULT_CHANNEL_A 36 +#define BCM43xx_RADIO_DEFAULT_CHANNEL_BG 6 + +/* Force antenna 0. */ +#define BCM43xx_RADIO_TXANTENNA_0 0 +/* Force antenna 1. */ +#define BCM43xx_RADIO_TXANTENNA_1 1 +/* Use the RX antenna, that was selected for the most recently + * received good PLCP header. + */ +#define BCM43xx_RADIO_TXANTENNA_LASTPLCP 3 +#define BCM43xx_RADIO_TXANTENNA_DEFAULT BCM43xx_RADIO_TXANTENNA_LASTPLCP + +#define BCM43xx_RADIO_INTERFMODE_NONE 0 +#define BCM43xx_RADIO_INTERFMODE_NONWLAN 1 +#define BCM43xx_RADIO_INTERFMODE_MANUALWLAN 2 +#define BCM43xx_RADIO_INTERFMODE_AUTOWLAN 3 + + +void bcm43xx_radio_lock(struct bcm43xx_private *bcm); +void bcm43xx_radio_unlock(struct bcm43xx_private *bcm); + +u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset); +void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val); + +u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm); +void bcm43xx_radio_init2060(struct bcm43xx_private *bcm); + +void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm); +void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm); + +int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel, + int synthetic_pu_workaround); + +void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower); +void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, + u16 baseband_attenuation, u16 attenuation, + u16 txpower); +void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val); + +void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm); + +u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel); +u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm); + +int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode); + +void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm); +void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm); +s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset); +void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val); +void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val); +void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm); + +void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm); + +#endif /* BCM43xx_RADIO_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c new file mode 100644 index 0000000000..fe6409a909 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -0,0 +1,1099 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include +#include +#include +#include /* for capable() */ +#include + +#include "bcm43xx.h" +#include "bcm43xx_wx.h" +#include "bcm43xx_main.h" +#include "bcm43xx_radio.h" + +/* Define to enable a printk on each wx handler function invocation */ +//#define BCM43xx_WX_DEBUG + + +#ifdef BCM43xx_WX_DEBUG +# define printk_wx printk +#else +# define printk_wx(x...) do { /* nothing */ } while (0) +#endif +#define wx_enter() printk_wx(KERN_INFO PFX "WX handler called: %s\n", __FUNCTION__); + +#define MAX_WX_STRING 80 + + +static int bcm43xx_wx_get_name(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int i, nr_80211; + struct bcm43xx_phyinfo *phy; + char suffix[7] = { 0 }; + int have_a = 0, have_b = 0, have_g = 0; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + nr_80211 = bcm43xx_num_80211_cores(bcm); + for (i = 0; i < nr_80211; i++) { + phy = bcm->phy + i; + switch (phy->type) { + case BCM43xx_PHYTYPE_A: + have_a = 1; + break; + case BCM43xx_PHYTYPE_G: + have_g = 1; + case BCM43xx_PHYTYPE_B: + have_b = 1; + break; + default: + assert(0); + } + } + spin_unlock_irqrestore(&bcm->lock, flags); + + i = 0; + if (have_a) { + suffix[i++] = 'a'; + suffix[i++] = '/'; + } + if (have_b) { + suffix[i++] = 'b'; + suffix[i++] = '/'; + } + if (have_g) { + suffix[i++] = 'g'; + suffix[i++] = '/'; + } + if (i != 0) + suffix[i - 1] = '\0'; + + snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix); + + return 0; +} + +static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct ieee80211softmac_device *softmac = bcm->softmac; + unsigned long flags; + u8 channel; + int freq; + int err = 0; + + wx_enter(); + + if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { + channel = data->freq.m; + freq = bcm43xx_channel_to_freq(bcm, channel); + } else { + channel = bcm43xx_freq_to_channel(bcm, data->freq.m); + freq = data->freq.m; + } + if (!bcm43xx_is_valid_channel(bcm, channel)) + return -EINVAL; + + spin_lock_irqsave(&bcm->lock, flags); + if (bcm->initialized) { + //ieee80211softmac_disassoc(softmac, $REASON); + bcm43xx_mac_suspend(bcm); + err = bcm43xx_radio_selectchannel(bcm, channel, 0); + bcm43xx_mac_enable(bcm); + } else + bcm->current_core->radio->initial_channel = channel; + spin_unlock_irqrestore(&bcm->lock, flags); + if (!err) + printk_wx(KERN_INFO PFX "Selected channel: %d\n", channel); + + return err; +} + +static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int err = -ENODEV; + u16 channel; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + channel = bcm->current_core->radio->channel; + if (channel == 0xFF) { + assert(!bcm->initialized); + channel = bcm->current_core->radio->initial_channel; + if (channel == 0xFF) + goto out_unlock; + } + assert(channel > 0 && channel <= 1000); + data->freq.e = 1; + data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000; + data->freq.flags = 1; + + err = 0; +out_unlock: + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static int bcm43xx_wx_set_mode(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int mode; + + wx_enter(); + + mode = data->mode; + if (mode == IW_MODE_AUTO) + mode = BCM43xx_INITIAL_IWMODE; + + spin_lock_irqsave(&bcm->lock, flags); + if (bcm->ieee->iw_mode != mode) + bcm43xx_set_iwmode(bcm, mode); + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_get_mode(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + data->mode = bcm->ieee->iw_mode; + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_sensitivity(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_get_sensitivity(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct iw_range *range = (struct iw_range *)extra; + const struct ieee80211_geo *geo; + unsigned long flags; + int i, j; + + wx_enter(); + + data->data.length = sizeof(*range); + memset(range, 0, sizeof(*range)); + + //TODO: What about 802.11b? + /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */ + range->throughput = 27 * 1000 * 1000; + + range->max_qual.qual = 100; + /* TODO: Real max RSSI */ + range->max_qual.level = 0; + range->max_qual.noise = 0; + range->max_qual.updated = 7; + + range->avg_qual.qual = 70; + range->avg_qual.level = 0; + range->avg_qual.noise = 0; + range->avg_qual.updated = 7; + + range->min_rts = BCM43xx_MIN_RTS_THRESHOLD; + range->max_rts = BCM43xx_MAX_RTS_THRESHOLD; + range->min_frag = MIN_FRAG_THRESHOLD; + range->max_frag = MAX_FRAG_THRESHOLD; + + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + range->num_encoding_sizes = 2; + range->max_encoding_tokens = WEP_KEYS; + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 16; + + spin_lock_irqsave(&bcm->lock, flags); + + range->num_bitrates = 0; + i = 0; + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A || + bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + range->num_bitrates = 8; + range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB; + range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB; + } + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B || + bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + range->num_bitrates += 4; + range->bitrate[i++] = IEEE80211_CCK_RATE_1MB; + range->bitrate[i++] = IEEE80211_CCK_RATE_2MB; + range->bitrate[i++] = IEEE80211_CCK_RATE_5MB; + range->bitrate[i++] = IEEE80211_CCK_RATE_11MB; + } + + geo = ieee80211_get_geo(bcm->ieee); + range->num_channels = geo->a_channels + geo->bg_channels; + j = 0; + for (i = 0; i < geo->a_channels; i++) { + if (j == IW_MAX_FREQUENCIES) + break; + range->freq[j].i = j + 1; + range->freq[j].m = geo->a[i].freq;//FIXME? + range->freq[j].e = 1; + j++; + } + for (i = 0; i < geo->bg_channels; i++) { + if (j == IW_MAX_FREQUENCIES) + break; + range->freq[j].i = j + 1; + range->freq[j].m = geo->bg[i].freq;//FIXME? + range->freq[j].e = 1; + j++; + } + range->num_frequency = j; + + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_nick(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + size_t len; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); + memcpy(bcm->nick, extra, len); + bcm->nick[len] = '\0'; + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_get_nick(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + size_t len; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + len = strlen(bcm->nick) + 1; + memcpy(extra, bcm->nick, len); + data->data.length = (__u16)len; + data->data.flags = 1; + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_rts(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int err = -EINVAL; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + if (data->rts.disabled) { + bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; + err = 0; + } else { + if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD && + data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) { + bcm->rts_threshold = data->rts.value; + err = 0; + } + } + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static int bcm43xx_wx_get_rts(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + data->rts.value = bcm->rts_threshold; + data->rts.fixed = 0; + data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_frag(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int err = -EINVAL; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + if (data->frag.disabled) { + bcm->ieee->fts = MAX_FRAG_THRESHOLD; + err = 0; + } else { + if (data->frag.value >= MIN_FRAG_THRESHOLD && + data->frag.value <= MAX_FRAG_THRESHOLD) { + bcm->ieee->fts = data->frag.value & ~0x1; + err = 0; + } + } + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static int bcm43xx_wx_get_frag(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + data->frag.value = bcm->ieee->fts; + data->frag.fixed = 0; + data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int err = -ENODEV; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + if (!bcm->initialized) + goto out_unlock; + if (data->power.disabled != (!(bcm->current_core->radio->enabled))) { + if (data->power.disabled) + bcm43xx_radio_turn_off(bcm); + else + bcm43xx_radio_turn_on(bcm); + } + //TODO: set txpower. + err = 0; + +out_unlock: + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); +//TODO data->power.value = ??? + data->power.fixed = 1; + data->power.flags = IW_TXPOW_DBM; + data->power.disabled = !(bcm->current_core->radio->enabled); + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_set_retry(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_get_retry(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_set_encoding(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err; + + wx_enter(); + + err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra); + + return err; +} + +static int bcm43xx_wx_set_encodingext(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err; + + wx_enter(); + + err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra); + + return err; +} + +static int bcm43xx_wx_get_encoding(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err; + + wx_enter(); + + err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra); + + return err; +} + +static int bcm43xx_wx_get_encodingext(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err; + + wx_enter(); + + err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra); + + return err; +} + +static int bcm43xx_wx_set_power(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_get_power(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + wx_enter(); + /*TODO*/ + return 0; +} + +static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int mode, err = 0; + + wx_enter(); + + mode = *((int *)extra); + switch (mode) { + case 0: + mode = BCM43xx_RADIO_INTERFMODE_NONE; + break; + case 1: + mode = BCM43xx_RADIO_INTERFMODE_NONWLAN; + break; + case 2: + mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; + break; + case 3: + mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; + break; + default: + printk(KERN_ERR PFX "set_interfmode allowed parameters are: " + "0 => None, 1 => Non-WLAN, 2 => WLAN, " + "3 => Auto-WLAN\n"); + return -EINVAL; + } + + spin_lock_irqsave(&bcm->lock, flags); + if (bcm->initialized) { + err = bcm43xx_radio_set_interference_mitigation(bcm, mode); + if (err) { + printk(KERN_ERR PFX "Interference Mitigation not " + "supported by device\n"); + } + } else { + if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) { + printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN " + "not supported while the interface is down.\n"); + err = -ENODEV; + } else + bcm->current_core->radio->interfmode = mode; + } + spin_unlock_irqrestore(&bcm->lock, flags); + + return err; +} + +static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int mode; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + mode = bcm->current_core->radio->interfmode; + spin_unlock_irqrestore(&bcm->lock, flags); + + switch (mode) { + case BCM43xx_RADIO_INTERFMODE_NONE: + strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING); + break; + case BCM43xx_RADIO_INTERFMODE_NONWLAN: + strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING); + break; + case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: + strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING); + break; + default: + assert(0); + } + data->data.length = strlen(extra) + 1; + + return 0; +} + +static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int on; + + wx_enter(); + + on = *((int *)extra); + spin_lock_irqsave(&bcm->lock, flags); + bcm->short_preamble = !!on; + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int on; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + on = bcm->short_preamble; + spin_unlock_irqrestore(&bcm->lock, flags); + + if (on) + strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); + else + strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING); + data->data.length = strlen(extra) + 1; + + return 0; +} + +static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int on; + + wx_enter(); + + on = *((int *)extra); + spin_lock_irqsave(&bcm->lock, flags); + bcm->ieee->host_encrypt = !!on; + bcm->ieee->host_decrypt = !!on; + bcm->ieee->host_build_iv = !on; + + spin_unlock_irqrestore(&bcm->lock, flags); + + return 0; +} + +static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + int on; + + wx_enter(); + + spin_lock_irqsave(&bcm->lock, flags); + on = bcm->ieee->host_encrypt; + spin_unlock_irqrestore(&bcm->lock, flags); + + if (on) + strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); + else + strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING); + data->data.length = strlen(extra + 1); + + return 0; +} + +/* Enough buffer to hold a hexdump of the sprom data. */ +#define SPROM_BUFFERSIZE 512 + +static int sprom2hex(const u16 *sprom, char *dump) +{ + int i, pos = 0; + + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { + pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1, + "%04X", swab16(sprom[i]) & 0xFFFF); + } + + return pos + 1; +} + +static int hex2sprom(u16 *sprom, const char *dump, unsigned int len) +{ + char tmp[5] = { 0 }; + int cnt = 0; + unsigned long parsed; + u8 crc, expected_crc; + + if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2) + return -EINVAL; + while (cnt < BCM43xx_SPROM_SIZE) { + memcpy(tmp, dump, 4); + dump += 4; + parsed = simple_strtoul(tmp, NULL, 16); + sprom[cnt++] = swab16((u16)parsed); + } + + crc = bcm43xx_sprom_crc(sprom); + expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; + if (crc != expected_crc) { + printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n"); + return -EINVAL; + } + + return 0; +} + +static int bcm43xx_wx_sprom_read(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err = -EPERM, i; + u16 *sprom; + unsigned long flags; + + if (!capable(CAP_SYS_RAWIO)) + goto out; + + err = -ENOMEM; + sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), + GFP_KERNEL); + if (!sprom) + goto out; + + spin_lock_irqsave(&bcm->lock, flags); + err = -ENODEV; + if (!bcm->initialized) { + spin_unlock_irqrestore(&bcm->lock, flags); + goto out_kfree; + } + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) + sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); + spin_unlock_irqrestore(&bcm->lock, flags); + + data->data.length = sprom2hex(sprom, extra); + + err = 0; +out_kfree: + kfree(sprom); +out: + return err; +} + +static int bcm43xx_wx_sprom_write(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int err = -EPERM; + u16 *sprom; + unsigned long flags; + char *input; + unsigned int len; + u32 spromctl; + int i; + + if (!capable(CAP_SYS_RAWIO)) + goto out; + + err = -ENOMEM; + sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), + GFP_KERNEL); + if (!sprom) + goto out; + + len = data->data.length; + extra[len - 1] = '\0'; + input = strchr(extra, ':'); + if (input) { + input++; + len -= input - extra; + } else + input = extra; + err = hex2sprom(sprom, input, len); + if (err) + goto out_kfree; + + spin_lock_irqsave(&bcm->lock, flags); + err = -ENODEV; + if (!bcm->initialized) { + spin_unlock_irqrestore(&bcm->lock, flags); + goto out_kfree; + } + + printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl); + if (err) { + printk(KERN_ERR PFX "Could not access SPROM control register.\n"); + goto out_unlock; + } + spromctl |= 0x10; /* SPROM WRITE enable. */ + bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); + if (err) { + printk(KERN_ERR PFX "Could not access SPROM control register.\n"); + goto out_unlock; + } + /* We must burn lots of CPU cycles here, but that does not + * really matter as one does not write the SPROM every other minute... + */ + printk(KERN_INFO PFX "[ 0%%"); + mdelay(500); + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { + if (i == 16) + printk("25%%"); + else if (i == 32) + printk("50%%"); + else if (i == 48) + printk("75%%"); + else if (i % 2) + printk("."); +//TODO bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); + mdelay(20); + } + spromctl &= ~0x10; /* SPROM WRITE enable. */ + bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); + if (err) { + printk(KERN_ERR PFX "Could not access SPROM control register.\n"); + goto out_unlock; + } + mdelay(500); + printk("100%% ]\n"); + printk(KERN_INFO PFX "SPROM written.\n"); + err = 0; +out_unlock: + spin_unlock_irqrestore(&bcm->lock, flags); +out_kfree: + kfree(sprom); +out: + return err; +} + + +#ifdef WX +# undef WX +#endif +#define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT] +static const iw_handler bcm43xx_wx_handlers[] = { + /* Wireless Identification */ + WX(SIOCGIWNAME) = bcm43xx_wx_get_name, + /* Basic operations */ + WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq, + WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq, + WX(SIOCSIWMODE) = bcm43xx_wx_set_mode, + WX(SIOCGIWMODE) = bcm43xx_wx_get_mode, + /* Informative stuff */ + WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams, + /* Access Point manipulation */ + WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap, + WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap, + WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan, + WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results, + /* 802.11 specific support */ + WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid, + WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid, + WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick, + WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick, + /* Other parameters */ + WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate, + WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate, + WX(SIOCSIWRTS) = bcm43xx_wx_set_rts, + WX(SIOCGIWRTS) = bcm43xx_wx_get_rts, + WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag, + WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag, + WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower, + WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower, +//TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry, +//TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry, + /* Encoding */ + WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding, + WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding, + WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext, + WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext, + /* Power saving */ +//TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power, +//TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power, + WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie, + WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie, + WX(SIOCSIWAUTH) = ieee80211_wx_set_auth, + WX(SIOCGIWAUTH) = ieee80211_wx_get_auth, +}; +#undef WX + +static const iw_handler bcm43xx_priv_wx_handlers[] = { + /* Set Interference Mitigation Mode. */ + bcm43xx_wx_set_interfmode, + /* Get Interference Mitigation Mode. */ + bcm43xx_wx_get_interfmode, + /* Enable/Disable Short Preamble mode. */ + bcm43xx_wx_set_shortpreamble, + /* Get Short Preamble mode. */ + bcm43xx_wx_get_shortpreamble, + /* Enable/Disable Software Encryption mode */ + bcm43xx_wx_set_swencryption, + /* Get Software Encryption mode */ + bcm43xx_wx_get_swencryption, + /* Write SRPROM data. */ + bcm43xx_wx_sprom_write, + /* Read SPROM data. */ + bcm43xx_wx_sprom_read, +}; + +#define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0) +#define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1) +#define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2) +#define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3) +#define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4) +#define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5) +#define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6) +#define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7) + +#define PRIV_WX_DUMMY(ioctl) \ + { \ + .cmd = (ioctl), \ + .name = "__unused" \ + } + +static const struct iw_priv_args bcm43xx_priv_wx_args[] = { + { + .cmd = PRIV_WX_SET_INTERFMODE, + .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + .name = "set_interfmode", + }, + { + .cmd = PRIV_WX_GET_INTERFMODE, + .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, + .name = "get_interfmode", + }, + { + .cmd = PRIV_WX_SET_SHORTPREAMBLE, + .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + .name = "set_shortpreambl", + }, + { + .cmd = PRIV_WX_GET_SHORTPREAMBLE, + .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, + .name = "get_shortpreambl", + }, + { + .cmd = PRIV_WX_SET_SWENCRYPTION, + .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + .name = "set_swencryption", + }, + { + .cmd = PRIV_WX_GET_SWENCRYPTION, + .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, + .name = "get_swencryption", + }, + { + .cmd = PRIV_WX_SPROM_WRITE, + .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE, + .name = "write_sprom", + }, + { + .cmd = PRIV_WX_SPROM_READ, + .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE, + .name = "read_sprom", + }, +}; + +const struct iw_handler_def bcm43xx_wx_handlers_def = { + .standard = bcm43xx_wx_handlers, + .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers), + .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers), + .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args), + .private = bcm43xx_priv_wx_handlers, + .private_args = bcm43xx_priv_wx_args, +}; + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h new file mode 100644 index 0000000000..1f29ff3aa4 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h @@ -0,0 +1,36 @@ +/* + + Broadcom BCM43xx wireless driver + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + Some parts of the code in this file are derived from the ipw2200 + driver Copyright(c) 2003 - 2004 Intel Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef BCM43xx_WX_H_ +#define BCM43xx_WX_H_ + +extern const struct iw_handler_def bcm43xx_wx_handlers_def; + +#endif /* BCM43xx_WX_H_ */ -- cgit v1.2.2 From 70e5e983f8a3f801a96bfeb0682cd2955ec3c8ce Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 23 Jan 2006 17:00:39 -0500 Subject: [PATCH] bcm43xx: patch Kconfig and wireless/Makefile for import Patch Kconfig and wireless/Makefile to merge bcm43xx 'properly' Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 8 ++++++++ drivers/net/wireless/Makefile | 1 + 2 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index fd17aa8491..7c7dca112b 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -501,6 +501,14 @@ config PRISM54 source "drivers/net/wireless/hostap/Kconfig" +config BCM43XX + tristate "Broadcom BCM43xx wireless support" + depends on PCI && IEEE80211 && NET_RADIO && IEEE80211_SOFTMAC && EXPERIMENTAL + select FW_LOADER + ---help--- + This is an experimental driver for the Broadcom 43xx wireless chip, + found in the Apple Airport Extreme and various other devices. + # yes, this works even when no drivers are selected config NET_WIRELESS bool diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 3a6f7ba326..c867798793 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o obj-$(CONFIG_PRISM54) += prism54/ obj-$(CONFIG_HOSTAP) += hostap/ +obj-$(CONFIG_BCM43XX) += bcm43xx/ # 16-bit wireless PCMCIA client drivers obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o -- cgit v1.2.2 From ea72ab229fe9cdfe3d3f70a6e64d98c725294b24 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 27 Jan 2006 17:26:20 +0100 Subject: [PATCH] bcm43xx: sync with svn.berlios.de Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 198 ++++++++++++--------------- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 11 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 7 +- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 8 +- 5 files changed, 102 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index df19fbfa9e..af5c27f9bf 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -214,7 +214,9 @@ static int alloc_ringmemory(struct bcm43xx_dmaring *ring) return -ENOMEM; } if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) { - printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G\n"); + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G " + "(0x%08x, len: %lu)\n", + ring->dmabase, BCM43xx_DMA_RINGMEMSIZE); dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, ring->vbase, ring->dmabase); return -ENOMEM; @@ -261,13 +263,6 @@ int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, return 0; } -static inline int dmacontroller_rx_reset(struct bcm43xx_dmaring *ring) -{ - assert(!ring->tx); - - return bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base); -} - /* Reset the RX DMA channel */ int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, u16 mmio_base) @@ -308,13 +303,6 @@ int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, return 0; } -static inline int dmacontroller_tx_reset(struct bcm43xx_dmaring *ring) -{ - assert(ring->tx); - - return bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base); -} - static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, struct bcm43xx_dmadesc *desc, struct bcm43xx_dmadesc_meta *meta, @@ -337,7 +325,9 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, if (unlikely(dmaaddr + ring->rx_buffersize > BCM43xx_DMA_BUSADDRMAX)) { unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); dev_kfree_skb_any(skb); - printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G\n"); + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G " + "(0x%08x, len: %u)\n", + dmaaddr, ring->rx_buffersize); return -ENOMEM; } meta->skb = skb; @@ -365,7 +355,7 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring) { int i, err = -ENOMEM; - struct bcm43xx_dmadesc *desc = NULL; + struct bcm43xx_dmadesc *desc; struct bcm43xx_dmadesc_meta *meta; for (i = 0; i < ring->nr_slots; i++) { @@ -375,24 +365,20 @@ static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring) err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); if (err) goto err_unwind; - - assert(ring->used_slots <= ring->nr_slots); } ring->used_slots = ring->nr_slots; - err = 0; out: return err; err_unwind: - for ( ; i >= 0; i--) { + for (i--; i >= 0; i--) { desc = ring->vbase + i; meta = ring->meta + i; unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); dev_kfree_skb(meta->skb); } - ring->used_slots = 0; goto out; } @@ -442,13 +428,13 @@ out: static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring) { if (ring->tx) { - dmacontroller_tx_reset(ring); + bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base); /* Zero out Transmit Descriptor ring address. */ bcm43xx_write32(ring->bcm, ring->mmio_base + BCM43xx_DMA_TX_DESC_RING, 0x00000000); } else { - dmacontroller_rx_reset(ring); + bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base); /* Zero out Receive Descriptor ring address. */ bcm43xx_write32(ring->bcm, ring->mmio_base + BCM43xx_DMA_RX_DESC_RING, @@ -508,9 +494,7 @@ struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm, if (bcm->pci_dev->bus->number == 0) ring->memoffset = 0; #endif - - - spin_lock_init(&ring->lock); + ring->bcm = bcm; ring->nr_slots = nr_descriptor_slots; ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100; @@ -578,22 +562,25 @@ static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring) void bcm43xx_dma_free(struct bcm43xx_private *bcm) { - bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring1); - bcm->current_core->dma->rx_ring1 = NULL; - bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring0); - bcm->current_core->dma->rx_ring0 = NULL; - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring3); - bcm->current_core->dma->tx_ring3 = NULL; - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring2); - bcm->current_core->dma->tx_ring2 = NULL; - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring1); - bcm->current_core->dma->tx_ring1 = NULL; - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring0); - bcm->current_core->dma->tx_ring0 = NULL; + struct bcm43xx_dma *dma = bcm->current_core->dma; + + bcm43xx_destroy_dmaring(dma->rx_ring1); + dma->rx_ring1 = NULL; + bcm43xx_destroy_dmaring(dma->rx_ring0); + dma->rx_ring0 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring3); + dma->tx_ring3 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring2); + dma->tx_ring2 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring1); + dma->tx_ring1 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring0); + dma->tx_ring0 = NULL; } int bcm43xx_dma_init(struct bcm43xx_private *bcm) { + struct bcm43xx_dma *dma = bcm->current_core->dma; struct bcm43xx_dmaring *ring; int err = -ENOMEM; @@ -602,39 +589,39 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm) BCM43xx_TXRING_SLOTS, 1); if (!ring) goto out; - bcm->current_core->dma->tx_ring0 = ring; + dma->tx_ring0 = ring; ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA2_BASE, BCM43xx_TXRING_SLOTS, 1); if (!ring) goto err_destroy_tx0; - bcm->current_core->dma->tx_ring1 = ring; + dma->tx_ring1 = ring; ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA3_BASE, BCM43xx_TXRING_SLOTS, 1); if (!ring) goto err_destroy_tx1; - bcm->current_core->dma->tx_ring2 = ring; + dma->tx_ring2 = ring; ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, BCM43xx_TXRING_SLOTS, 1); if (!ring) goto err_destroy_tx2; - bcm->current_core->dma->tx_ring3 = ring; + dma->tx_ring3 = ring; /* setup RX DMA channels. */ ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE, BCM43xx_RXRING_SLOTS, 0); if (!ring) goto err_destroy_tx3; - bcm->current_core->dma->rx_ring0 = ring; + dma->rx_ring0 = ring; if (bcm->current_core->rev < 5) { ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, BCM43xx_RXRING_SLOTS, 0); if (!ring) goto err_destroy_rx0; - bcm->current_core->dma->rx_ring1 = ring; + dma->rx_ring1 = ring; } dprintk(KERN_INFO PFX "DMA initialized\n"); @@ -643,27 +630,26 @@ out: return err; err_destroy_rx0: - bcm43xx_destroy_dmaring(bcm->current_core->dma->rx_ring0); - bcm->current_core->dma->rx_ring0 = NULL; + bcm43xx_destroy_dmaring(dma->rx_ring0); + dma->rx_ring0 = NULL; err_destroy_tx3: - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring3); - bcm->current_core->dma->tx_ring3 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring3); + dma->tx_ring3 = NULL; err_destroy_tx2: - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring2); - bcm->current_core->dma->tx_ring2 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring2); + dma->tx_ring2 = NULL; err_destroy_tx1: - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring1); - bcm->current_core->dma->tx_ring1 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring1); + dma->tx_ring1 = NULL; err_destroy_tx0: - bcm43xx_destroy_dmaring(bcm->current_core->dma->tx_ring0); - bcm->current_core->dma->tx_ring0 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring0); + dma->tx_ring0 = NULL; goto out; } /* Generate a cookie for the TX header. */ -static inline -u16 generate_cookie(struct bcm43xx_dmaring *ring, - int slot) +static u16 generate_cookie(struct bcm43xx_dmaring *ring, + int slot) { u16 cookie = 0x0000; @@ -693,24 +679,25 @@ u16 generate_cookie(struct bcm43xx_dmaring *ring, } /* Inspect a cookie and find out to which controller/slot it belongs. */ -static inline +static struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, u16 cookie, int *slot) { + struct bcm43xx_dma *dma = bcm->current_core->dma; struct bcm43xx_dmaring *ring = NULL; switch (cookie & 0xF000) { case 0x0000: - ring = bcm->current_core->dma->tx_ring0; + ring = dma->tx_ring0; break; case 0x1000: - ring = bcm->current_core->dma->tx_ring1; + ring = dma->tx_ring1; break; case 0x2000: - ring = bcm->current_core->dma->tx_ring2; + ring = dma->tx_ring2; break; case 0x3000: - ring = bcm->current_core->dma->tx_ring3; + ring = dma->tx_ring3; break; default: assert(0); @@ -721,8 +708,8 @@ struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, return ring; } -static inline void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, - int slot) +static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, + int slot) { /* Everything is ready to start. Buffers are DMA mapped and * associated with slots. @@ -736,11 +723,10 @@ static inline void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, (u32)(slot * sizeof(struct bcm43xx_dmadesc))); } -static inline -int dma_tx_fragment(struct bcm43xx_dmaring *ring, - struct sk_buff *skb, - struct ieee80211_txb *txb, - u8 cur_frag) +static int dma_tx_fragment(struct bcm43xx_dmaring *ring, + struct sk_buff *skb, + struct ieee80211_txb *txb, + u8 cur_frag) { int slot; struct bcm43xx_dmadesc *desc; @@ -777,7 +763,9 @@ int dma_tx_fragment(struct bcm43xx_dmaring *ring, meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) { return_slot(ring, slot); - printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G\n"); + printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G " + "(0x%08x, len: %u)\n", + meta->dmaaddr, skb->len); return -ENOMEM; } @@ -797,14 +785,15 @@ int dma_tx_fragment(struct bcm43xx_dmaring *ring, return 0; } -static inline int dma_transfer_txb(struct bcm43xx_dmaring *ring, - struct ieee80211_txb *txb) +int bcm43xx_dma_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) { /* We just received a packet from the kernel network subsystem. * Add headers and DMA map the memory. Poke * the device to send the stuff. * Note that this is called from atomic context. */ + struct bcm43xx_dmaring *ring = bcm->current_core->dma->tx_ring1; u8 i; struct sk_buff *skb; @@ -818,8 +807,6 @@ static inline int dma_transfer_txb(struct bcm43xx_dmaring *ring, return -ENOMEM; } - assert(irqs_disabled()); - spin_lock(&ring->lock); for (i = 0; i < txb->nr_frags; i++) { skb = txb->fragments[i]; /* We do not free the skb, as it is freed as @@ -829,22 +816,12 @@ static inline int dma_transfer_txb(struct bcm43xx_dmaring *ring, dma_tx_fragment(ring, skb, txb, i); //TODO: handle failure of dma_tx_fragment } - spin_unlock(&ring->lock); return 0; } -int fastcall -bcm43xx_dma_transfer_txb(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - return dma_transfer_txb(bcm->current_core->dma->tx_ring1, - txb); -} - -void fastcall -bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) +void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) { struct bcm43xx_dmaring *ring; struct bcm43xx_dmadesc *desc; @@ -855,9 +832,6 @@ bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, ring = parse_cookie(bcm, status->cookie, &slot); assert(ring); assert(ring->tx); - assert(irqs_disabled()); - spin_lock(&ring->lock); - assert(get_desc_ctl(ring->vbase + slot) & BCM43xx_DMADTOR_FRAMESTART); while (1) { assert(slot >= 0 && slot < ring->nr_slots); @@ -877,13 +851,10 @@ bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, slot = next_slot(ring, slot); } bcm->stats.last_tx = jiffies; - - spin_unlock(&ring->lock); } -static inline -void dma_rx(struct bcm43xx_dmaring *ring, - int *slot) +static void dma_rx(struct bcm43xx_dmaring *ring, + int *slot) { struct bcm43xx_dmadesc *desc; struct bcm43xx_dmadesc_meta *meta; @@ -928,8 +899,12 @@ void dma_rx(struct bcm43xx_dmaring *ring, barrier(); len = le16_to_cpu(rxhdr->frame_length); } while (len == 0 && i++ < 5); - if (len == 0) + if (unlikely(len == 0)) { + /* recycle the descriptor buffer. */ + sync_descbuffer_for_device(ring, meta->dmaaddr, + ring->rx_buffersize); goto drop; + } } if (unlikely(len > ring->rx_buffersize)) { /* The data did not fit into one descriptor buffer @@ -937,15 +912,24 @@ void dma_rx(struct bcm43xx_dmaring *ring, * This should never happen, as we try to allocate buffers * big enough. So simply ignore this packet. */ - int cnt = 1; - s32 tmp = len - ring->rx_buffersize; - - for ( ; tmp > 0; tmp -= ring->rx_buffersize) { + int cnt = 0; + s32 tmp = len; + + while (1) { + desc = ring->vbase + *slot; + meta = ring->meta + *slot; + /* recycle the descriptor buffer. */ + sync_descbuffer_for_device(ring, meta->dmaaddr, + ring->rx_buffersize); *slot = next_slot(ring, *slot); cnt++; + tmp -= ring->rx_buffersize; + if (tmp <= 0) + break; } - printkl(KERN_ERR PFX "DMA RX buffer too small. %d dropped.\n", - cnt); + printkl(KERN_ERR PFX "DMA RX buffer too small " + "(len: %u, buffer: %u, nr-dropped: %d)\n", + len, ring->rx_buffersize, cnt); goto drop; } len -= IEEE80211_FCS_LEN; @@ -954,6 +938,8 @@ void dma_rx(struct bcm43xx_dmaring *ring, err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC); if (unlikely(err)) { dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n"); + sync_descbuffer_for_device(ring, dmaaddr, + ring->rx_buffersize); goto drop; } @@ -971,8 +957,7 @@ drop: return; } -void fastcall -bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) +void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) { u32 status; u16 descptr; @@ -982,9 +967,6 @@ bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) #endif assert(!ring->tx); - assert(irqs_disabled()); - spin_lock(&ring->lock); - status = bcm43xx_read32(ring->bcm, ring->mmio_base + BCM43xx_DMA_RX_STATUS); descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK); current_slot = descptr / sizeof(struct bcm43xx_dmadesc); @@ -1002,8 +984,6 @@ bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) ring->mmio_base + BCM43xx_DMA_RX_DESC_INDEX, (u32)(slot * sizeof(struct bcm43xx_dmadesc))); ring->current_slot = slot; - - spin_unlock(&ring->lock); } /* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index e32cf68f8e..93e99d61f2 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -122,7 +122,6 @@ struct bcm43xx_dmadesc_meta { }; struct bcm43xx_dmaring { - spinlock_t lock; struct bcm43xx_private *bcm; /* Kernel virtual base address of the ring memory. */ struct bcm43xx_dmadesc *vbase; @@ -166,11 +165,11 @@ int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, u16 dmacontroller_mmio_base); -int FASTCALL(bcm43xx_dma_transfer_txb(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb)); -void FASTCALL(bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status)); +void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status); -void FASTCALL(bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)); +int bcm43xx_dma_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb); +void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); #endif /* BCM43xx_DMA_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index be60a6509f..4b4e60a22c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -4097,7 +4097,6 @@ int fastcall bcm43xx_rx(struct bcm43xx_private *bcm, } frame_ctl = le16_to_cpu(wlhdr->frame_ctl); - if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { frame_ctl &= ~IEEE80211_FCTL_PROTECTED; wlhdr->frame_ctl = cpu_to_le16(frame_ctl); @@ -4113,12 +4112,12 @@ int fastcall bcm43xx_rx(struct bcm43xx_private *bcm, skb_trim(skb, skb->len - 4); stats.len -= 8; } - /* do _not_ use wlhdr again without reassigning it */ + wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); } switch (WLAN_FC_GET_TYPE(frame_ctl)) { case IEEE80211_FTYPE_MGMT: - ieee80211_rx_mgt(bcm->ieee, skb->data, &stats); + ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); break; case IEEE80211_FTYPE_DATA: if (is_packet_for_us) @@ -4143,7 +4142,7 @@ static inline int bcm43xx_tx(struct bcm43xx_private *bcm, if (bcm->pio_mode) err = bcm43xx_pio_transfer_txb(bcm, txb); else - err = bcm43xx_dma_transfer_txb(bcm, txb); + err = bcm43xx_dma_tx(bcm, txb); return err; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 41b9cd7fc9..f5e7a6ab93 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -1161,7 +1161,7 @@ void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm) phy->minlowsigpos[1] += 0x0101; bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]); - if (radio->version == 2053) { + if (radio->version == 0x2053) { bcm43xx_phy_write(bcm, 0x000A, regstack[2]); bcm43xx_phy_write(bcm, 0x002A, regstack[3]); bcm43xx_phy_write(bcm, 0x0035, regstack[4]); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 1e65658552..5ce6acef2c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -467,8 +467,8 @@ static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) | 0x0040); - bcm43xx_phy_write(bcm, 0x007A, - bcm43xx_phy_read(bcm, 0x007A) | 0x000F); + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) | 0x000F); bcm43xx_set_all_gains(bcm, 3, 0, 1); bcm43xx_radio_write16(bcm, 0x0043, (bcm43xx_radio_read16(bcm, 0x0043) @@ -761,8 +761,8 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002)); bcm43xx_set_original_gains(bcm); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) | 0x8000); + bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000); if (phy->rev >= 3) { bcm43xx_phy_write(bcm, 0x0801, backup[14]); bcm43xx_phy_write(bcm, 0x0060, backup[15]); -- cgit v1.2.2 From 4a2a2792d0cb3f2797ff179beef7b8c2981979c2 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 27 Jan 2006 17:33:15 +0100 Subject: [PATCH] bcm43xx: remove linux version compatibility code. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index aca1601e5b..38e75ed2b6 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -935,27 +935,4 @@ int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 valu __value; \ }) - -/* - * Compatibility stuff follows - */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) -# error "The bcm43xx driver does not support kernels < 2.6.15" -# error "The driver will _NOT_ compile on your kernel. Please upgrade to the latest 2.6 kernel." -# error "DO NOT COMPLAIN ABOUT BUGS. UPDATE FIRST AND TRY AGAIN." -#else -# if !defined(CONFIG_IEEE80211_MODULE) && !defined(CONFIG_IEEE80211) -# error "Generic IEEE 802.11 Networking Stack (CONFIG_IEEE80211) not available." -# endif -#endif -#ifdef IEEE80211SOFTMAC_API -# if IEEE80211SOFTMAC_API != 0 -# warning "Incompatible SoftMAC subsystem installed." -# endif -#else -# error "The bcm43xx driver requires the SoftMAC subsystem." -# error "SEE >>>>>> http://softmac.sipsolutions.net/ <<<<<<" -#endif - #endif /* BCM43xx_H_ */ -- cgit v1.2.2 From 08ccd883f536d81d380522106c67bd5d7043fa4a Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 27 Jan 2006 17:37:05 +0100 Subject: [PATCH] bcm43xx: Move README file to Documentation directory. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/README | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 drivers/net/wireless/bcm43xx/README (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/README b/drivers/net/wireless/bcm43xx/README deleted file mode 100644 index 64d9022de7..0000000000 --- a/drivers/net/wireless/bcm43xx/README +++ /dev/null @@ -1,36 +0,0 @@ - - BCM43xx Linux Driver Project - ============================ - -About this software -------------------- - -The goal of this project is to develop a linux driver for Broadcom -BCM43xx chips, based on the specification at -http://bcm-specs.sipsolutions.net/ - -The project page is http://bcm43xx.berlios.de/ - - -Requirements ------------- - -1) Linux Kernel 2.6.15 or later - http://www.kernel.org/ - - You may want to configure your kernel with: - - CONFIG_DEBUG_FS (optional): - -> Kernel hacking - -> Debug Filesystem - -2) SoftMAC IEEE 802.11 Networking Stack extension and patched ieee80211 - modules: - http://softmac.sipsolutions.net/ - -3) Firmware Files - - Please try fwcutter. Fwcutter can extract the firmware from various - binary driver files. It supports driver files from Windows, MacOS and - Linux. You can get fwcutter from http://bcm43xx.berlios.de/. - Also, fwcutter comes with a README file for further instructions. -- cgit v1.2.2 From dda207ae2da37032524bbdd7a0133c37f2907ae8 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 27 Jan 2006 17:39:44 +0100 Subject: [PATCH] bcm43xx: remove redundant COPYING file. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/COPYING | 340 ----------------------------------- 1 file changed, 340 deletions(-) delete mode 100644 drivers/net/wireless/bcm43xx/COPYING (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/COPYING b/drivers/net/wireless/bcm43xx/COPYING deleted file mode 100644 index 5b6e7c66c2..0000000000 --- a/drivers/net/wireless/bcm43xx/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. -- cgit v1.2.2 From 6f3e2045cabd952a86bc819181d8a190cd0689c3 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 30 Jan 2006 17:43:20 +0100 Subject: [PATCH] bcm43xx: add DEBUG Kconfig option. Also fix indention. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 7c7dca112b..3b1363c971 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -502,12 +502,21 @@ config PRISM54 source "drivers/net/wireless/hostap/Kconfig" config BCM43XX - tristate "Broadcom BCM43xx wireless support" - depends on PCI && IEEE80211 && NET_RADIO && IEEE80211_SOFTMAC && EXPERIMENTAL + tristate "Broadcom BCM43xx wireless support" + depends on PCI && IEEE80211 && NET_RADIO && IEEE80211_SOFTMAC && EXPERIMENTAL select FW_LOADER - ---help--- - This is an experimental driver for the Broadcom 43xx wireless chip, - found in the Apple Airport Extreme and various other devices. + ---help--- + This is an experimental driver for the Broadcom 43xx wireless chip, + found in the Apple Airport Extreme and various other devices. + +config BCM43XX_DEBUG + bool "Broadcom BCM43xx debugging (RECOMMENDED)" + depends on BCM43XX + default y + ---help--- + Broadcom 43xx debugging messages. + Say Y, because the driver is still very experimental and + this will help you get it running. # yes, this works even when no drivers are selected config NET_WIRELESS -- cgit v1.2.2 From 65f3f19120cf32233f537562e69893b88727b634 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 31 Jan 2006 20:11:38 +0100 Subject: [PATCH] bcm43xx: Fix makefile. Remove all the "out-of-tree" stuff. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Makefile | 87 ++------------------------ drivers/net/wireless/bcm43xx/bcm43xx.h | 6 +- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 8 +-- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 11 ++-- 4 files changed, 14 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile index 98d4efb1d1..3e5ed77835 100644 --- a/drivers/net/wireless/bcm43xx/Makefile +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -1,87 +1,8 @@ -# Makefile for bcm43xx driver +obj-$(CONFIG_BCM43XX) += bcm43xx.o +bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o -VERSION := 0.0.1 -RELEASE_NAME := bcm43xx-$(VERSION) - -# Optional path, where the SoftMAC subsystem is located. -# You may set SOFTMAC_DIR in your bashrc, for example. -SOFTMAC_DIR ?= - -KVER := $(shell uname -r) -KDIR ?= /lib/modules/$(KVER)/build -PWD := $(shell pwd) -MODPATH := $(DESTDIR)/lib/modules/$(KVER)/kernel/drivers/net/bcm43xx - -# Comment/uncomment to enable/disable debugging -DEBUG = y - - -ifeq ($(DEBUG),y) -DEBUGFS_OBJ = bcm43xx_debugfs.o -CFLAGS += -O2 -DCONFIG_BCM43XX_DEBUG -else -DEBUGFS_OBJ = -CFLAGS += -O2 -endif - -CFLAGS += -DBCM43xx_VERSION=$(VERSION) -I/lib/modules/$(KVER)/include -ifneq ($(SOFTMAC_DIR),) -CPPFLAGS := -I$(SOFTMAC_DIR) $(CPPFLAGS) -endif - -ifneq ($(KERNELRELEASE),) -# call from kernel build system - -obj-m := bcm43xx.o -bcm43xx-objs := bcm43xx_main.o bcm43xx_dma.o $(DEBUGFS_OBJ) \ +bcm43xx-objs := bcm43xx_main.o bcm43xx_dma.o \ bcm43xx_radio.o bcm43xx_phy.o \ bcm43xx_power.o bcm43xx_wx.o \ bcm43xx_pio.o bcm43xx_ilt.o \ - bcm43xx_leds.o - -else - -default: modules - -modules: - $(MAKE) -C $(KDIR) M=$(PWD) modules - -install: bcm43xx.ko - install -d $(MODPATH) - install -m 644 -c bcm43xx.ko $(MODPATH) - /sbin/depmod -a - -uninstall: - rm -rf $(MODPATH) - /sbin/depmod -a - -endif - -clean: - find . \( -name '*.ko' -o -name '*.o' -o -name '.tmp_versions' -o -name '*~' -o -name '.*.cmd' \ - -o -name '*.mod.c' -o -name '*.tar.bz2' -o -name '*.rej' -o -name '*.orig' \)\ - -print | xargs rm -Rf - -depend .depend dep: - $(CC) $(CFLAGS) -M *.c > .depend - -ifeq (.depend,$(wildcard .depend)) -include .depend -endif - -DISTFILES = $(shell find . \( -not -name '.' \) -print | grep -v "\.tar\.bz2" | grep -v "\/\." ) -DISTDIR = $(RELEASE_NAME) - -release: clean - @rm -rf $(DISTDIR) - @mkdir $(DISTDIR) - @chmod 777 $(DISTDIR) - @for file in $(DISTFILES); do \ - if test -d $$file; then \ - mkdir $(DISTDIR)/$$file; \ - else \ - cp -p $$file $(DISTDIR)/$$file; \ - fi; \ - done - @tar -c $(DISTDIR) | bzip2 -9 > $(RELEASE_NAME).tar.bz2 - @rm -rf $(DISTDIR) + bcm43xx_leds.o $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 38e75ed2b6..7b97d8bf79 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -17,14 +17,10 @@ #include "bcm43xx_leds.h" -#define DRV_NAME __stringify(KBUILD_MODNAME) -#define DRV_VERSION __stringify(BCM43xx_VERSION) -#define BCM43xx_DRIVER_NAME DRV_NAME " driver " DRV_VERSION -#define PFX DRV_NAME ": " +#define PFX KBUILD_MODNAME ": " #define BCM43xx_SWITCH_CORE_MAX_RETRIES 10 #define BCM43xx_IRQWAIT_MAX_RETRIES 50 -#define BCM43xx_TX_TIMEOUT (10 * HZ) #define BCM43xx_IO_SIZE 8192 #define BCM43xx_REG_ACTIVE_CORE 0x80 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index f8cfc84ca0..5a7dc43cd6 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -141,7 +141,7 @@ static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf, down(&big_buffer_sem); /* This is where the information is written to the "driver" file */ - fappend(BCM43xx_DRIVER_NAME "\n"); + fappend(KBUILD_MODNAME " driver\n"); fappend("Compiled at: %s %s\n", __DATE__, __TIME__); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); @@ -433,12 +433,12 @@ void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, void bcm43xx_debugfs_init(void) { memset(&fs, 0, sizeof(fs)); - fs.root = debugfs_create_dir(DRV_NAME, NULL); + fs.root = debugfs_create_dir(KBUILD_MODNAME, NULL); if (!fs.root) - printk(KERN_ERR PFX "debugfs: creating \"" DRV_NAME "\" subdir failed!\n"); + printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "\" subdir failed!\n"); fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops); if (!fs.dentry_driverinfo) - printk(KERN_ERR PFX "debugfs: creating \"" DRV_NAME "/driver\" failed!\n"); + printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "/driver\" failed!\n"); } void bcm43xx_debugfs_exit(void) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 4b4e60a22c..cfb0f0a485 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2471,7 +2471,7 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) } #endif res = request_irq(bcm->irq, bcm43xx_interrupt_handler, - SA_SHIRQ, DRV_NAME, bcm); + SA_SHIRQ, KBUILD_MODNAME, bcm); if (res) { printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); return -EFAULT; @@ -3809,7 +3809,7 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) } #endif - err = pci_request_regions(pci_dev, DRV_NAME); + err = pci_request_regions(pci_dev, KBUILD_MODNAME); if (err) { printk(KERN_ERR PFX "could not access PCI resources (%i)\n", err); @@ -4389,12 +4389,11 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, #endif net_dev->wireless_handlers = &bcm43xx_wx_handlers_def; net_dev->irq = pdev->irq; - net_dev->watchdog_timeo = BCM43xx_TX_TIMEOUT; /* initialize the bcm43xx_private struct */ bcm = bcm43xx_priv(net_dev); memset(bcm, 0, sizeof(*bcm)); - wq = create_workqueue(DRV_NAME "_wq"); + wq = create_workqueue(KBUILD_MODNAME "_wq"); if (!wq) { err = -ENOMEM; goto err_free_netdev; @@ -4567,7 +4566,7 @@ static int bcm43xx_resume(struct pci_dev *pdev) #endif /* CONFIG_PM */ static struct pci_driver bcm43xx_pci_driver = { - .name = BCM43xx_DRIVER_NAME, + .name = KBUILD_MODNAME, .id_table = bcm43xx_pci_tbl, .probe = bcm43xx_init_one, .remove = __devexit_p(bcm43xx_remove_one), @@ -4579,7 +4578,7 @@ static struct pci_driver bcm43xx_pci_driver = { static int __init bcm43xx_init(void) { - printk(KERN_INFO BCM43xx_DRIVER_NAME "\n"); + printk(KERN_INFO KBUILD_MODNAME " driver\n"); bcm43xx_debugfs_init(); return pci_register_driver(&bcm43xx_pci_driver); } -- cgit v1.2.2 From a4a600d3e17f450666a9086465122103e96140d7 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 1 Feb 2006 22:09:52 +0100 Subject: [PATCH] bcm43xx: Add more initvals sanity checks and error out, if one sanity check fails. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 62 ++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index cfb0f0a485..521777f56a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2229,9 +2229,9 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re return IRQ_HANDLED; } -static void bcm43xx_release_firmware(struct bcm43xx_private *bcm) +static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) { - if (bcm->firmware_norelease) + if (bcm->firmware_norelease && !force) return; /* Suspending or controller reset. */ release_firmware(bcm->ucode); bcm->ucode = NULL; @@ -2361,7 +2361,7 @@ static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) out: return err; error: - bcm43xx_release_firmware(bcm); + bcm43xx_release_firmware(bcm, 1); goto out; err_noinitval: printk(KERN_ERR PFX "Error: No InitVals available!\n"); @@ -2409,9 +2409,9 @@ static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) #endif } -static void bcm43xx_write_initvals(struct bcm43xx_private *bcm, - const struct bcm43xx_initval *data, - const unsigned int len) +static int bcm43xx_write_initvals(struct bcm43xx_private *bcm, + const struct bcm43xx_initval *data, + const unsigned int len) { u16 offset, size; u32 value; @@ -2422,35 +2422,54 @@ static void bcm43xx_write_initvals(struct bcm43xx_private *bcm, size = be16_to_cpu(data[i].size); value = be32_to_cpu(data[i].value); - if (size == 2) - bcm43xx_write16(bcm, offset, value); - else if (size == 4) + if (unlikely(offset >= 0x1000)) + goto err_format; + if (size == 2) { + if (unlikely(value & 0xFFFF0000)) + goto err_format; + bcm43xx_write16(bcm, offset, (u16)value); + } else if (size == 4) { bcm43xx_write32(bcm, offset, value); - else - printk(KERN_ERR PFX "InitVals fileformat error.\n"); + } else + goto err_format; } + + return 0; + +err_format: + printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. " + "Please fix your bcm43xx firmware files.\n"); + return -EPROTO; } -static void bcm43xx_upload_initvals(struct bcm43xx_private *bcm) +static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) { + int err; + #ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT bcm43xx_mmioprint_enable(bcm); #else bcm43xx_mmioprint_disable(bcm); #endif - bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, - bcm->initvals0->size / sizeof(struct bcm43xx_initval)); + err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, + bcm->initvals0->size / sizeof(struct bcm43xx_initval)); + if (err) + goto out; if (bcm->initvals1) { - bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data, - bcm->initvals1->size / sizeof(struct bcm43xx_initval)); + err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data, + bcm->initvals1->size / sizeof(struct bcm43xx_initval)); + if (err) + goto out; } +out: #ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT bcm43xx_mmioprint_disable(bcm); #else bcm43xx_mmioprint_enable(bcm); #endif + return err; } static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) @@ -2683,7 +2702,7 @@ static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm) bcm43xx_leds_exit(bcm); bcm43xx_gpio_cleanup(bcm); free_irq(bcm->irq, bcm); - bcm43xx_release_firmware(bcm); + bcm43xx_release_firmware(bcm, 0); } /* Initialize the chip @@ -2708,13 +2727,15 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) err = bcm43xx_initialize_irq(bcm); if (err) - goto out; + goto err_release_fw; err = bcm43xx_gpio_init(bcm); if (err) goto err_free_irq; - bcm43xx_upload_initvals(bcm); + err = bcm43xx_upload_initvals(bcm); + if (err) + goto err_gpio_cleanup; bcm43xx_radio_turn_on(bcm); if (modparam_noleds) @@ -2813,9 +2834,12 @@ out: err_radio_off: bcm43xx_radio_turn_off(bcm); +err_gpio_cleanup: bcm43xx_gpio_cleanup(bcm); err_free_irq: free_irq(bcm->irq, bcm); +err_release_fw: + bcm43xx_release_firmware(bcm, 1); goto out; } -- cgit v1.2.2 From 9e4a375b15c9940b13e66e224570b35c471c0128 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 2 Feb 2006 18:43:25 +0100 Subject: [PATCH] bcm43xx: Remove function bcm43xx_channel_is_allowed() Geographical restriction should become part of the 80211 stack, so every driver does not have to duplicate it. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 166 +--------------------------- 1 file changed, 1 insertion(+), 165 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 521777f56a..c0ec503102 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -82,10 +82,6 @@ static int modparam_locale = -1; module_param_named(locale, modparam_locale, int, 0444); MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)"); -static int modparam_outdoor; -module_param_named(outdoor, modparam_outdoor, int, 0444); -MODULE_PARM_DESC(outdoor, "Set to 1, if you are using the device outdoor, 0 otherwise."); - static int modparam_noleds; module_param_named(noleds, modparam_noleds, int, 0444); MODULE_PARM_DESC(noleds, "Turn off all LED activity"); @@ -1088,163 +1084,13 @@ static int bcm43xx_read_sprom(struct bcm43xx_private *bcm) return 0; } -static int bcm43xx_channel_is_allowed(struct bcm43xx_private *bcm, u8 channel, - u8 *max_power, u8 *flags) -{ - /* THIS FUNCTION DOES _NOT_ ENFORCE REGULATORY DOMAIN COMPLIANCE. - * It is only a helper function to make life easier to - * select legal channels and transmission powers. - */ - - u8 phytype = bcm->current_core->phy->type; - int allowed = 0; - - *max_power = 0; - *flags = 0; - - //FIXME: Set max_power and maybe flags - /*FIXME: Allowed channels are sometimes different for outdoor - * or indoor use. See modparam_outdoor. - */ - /* From b specs Max Power BPHY: - * USA: 1000mW - * Europe: 100mW - * Japan: 10mW/MHz - */ - - switch (bcm->sprom.locale) { - case BCM43xx_LOCALE_WORLD: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 13) - allowed = 1; - } else { - if (channel >= 1 && channel <= 13) - allowed = 1; - } - break; - case BCM43xx_LOCALE_THAILAND: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 14) - allowed = 1; - } else { - if (channel >= 1 && channel <= 14) - allowed = 1; - } - break; - case BCM43xx_LOCALE_ISRAEL: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 5 && channel <= 7) - allowed = 1; - } else { - if (channel >= 5 && channel <= 7) - allowed = 1; - } - break; - case BCM43xx_LOCALE_JORDAN: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 10 && channel <= 13) - allowed = 1; - } else { - if (channel >= 10 && channel <= 13) - allowed = 1; - } - break; - case BCM43xx_LOCALE_CHINA: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 13) - allowed = 1; - } else { - if (channel >= 1 && channel <= 13) - allowed = 1; - } - break; - case BCM43xx_LOCALE_JAPAN: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - //FIXME: This seems to be wrong. - if (channel >= 1 && channel <= 14) - allowed = 1; - } else { - //FIXME: This seems to be wrong. - if (channel >= 1 && channel <= 14) - allowed = 1; - } - break; - case BCM43xx_LOCALE_USA_CANADA_ANZ: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 13) - allowed = 1; - } else { - if (channel >= 1 && channel <= 11) - allowed = 1; - } - break; - case BCM43xx_LOCALE_EUROPE: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 13) - allowed = 1; - } else { - if (channel >= 1 && channel <= 13) - allowed = 1; - } - break; - case BCM43xx_LOCALE_USA_LOW: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - if (channel >= 1 && channel <= 13) - allowed = 1; - } else { - if (channel >= 1 && channel <= 11) - allowed = 1; - } - break; - case BCM43xx_LOCALE_JAPAN_HIGH: - if (phytype == BCM43xx_PHYTYPE_A) { - allowed = 1;//FIXME - } else if (phytype == BCM43xx_PHYTYPE_B) { - //FIXME? - if (channel >= 1 && channel <= 14) - allowed = 1; - } else { - if (channel >= 1 && channel <= 14) - allowed = 1; - } - break; - case BCM43xx_LOCALE_ALL: - allowed = 1; - break; - case BCM43xx_LOCALE_NONE: - break; - default: - assert(0); - } - - return allowed; -} - static void bcm43xx_geo_init(struct bcm43xx_private *bcm) { struct ieee80211_geo geo; struct ieee80211_channel *chan; int have_a = 0, have_bg = 0; int i, num80211; - u8 channel, flags, max_power; + u8 channel; struct bcm43xx_phyinfo *phy; const char *iso_country; @@ -1268,27 +1114,17 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) if (have_a) { for (i = 0, channel = 0; channel < 201; channel++) { - if (!bcm43xx_channel_is_allowed(bcm, channel, - &max_power, &flags)) - continue; chan = &geo.a[i++]; chan->freq = bcm43xx_channel_to_freq(bcm, channel); chan->channel = channel; - chan->flags = flags; - chan->max_power = max_power; } geo.a_channels = i; } if (have_bg) { for (i = 0, channel = 1; channel < 15; channel++) { - if (!bcm43xx_channel_is_allowed(bcm, channel, - &max_power, &flags)) - continue; chan = &geo.bg[i++]; chan->freq = bcm43xx_channel_to_freq(bcm, channel); chan->channel = channel; - chan->flags = flags; - chan->max_power = max_power; } geo.bg_channels = i; } -- cgit v1.2.2 From 6465ce1bbf7fede82dccec342417105b10793b51 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 2 Feb 2006 19:11:08 +0100 Subject: [PATCH] bcm43xx: basic ethtool support This patch contains the beginnings of ethtool support for bcm43xx. It only implements get_drvinfo and get_link, but that's enough for ifplugd to use ethtool to know whether we're associated or not and then start or stop dhcp as necessary. Signed-off-by: Jason Lunz Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Makefile | 3 +- drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c | 50 ++++++++++++++++++++++++++ drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h | 8 +++++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 2 ++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile index 3e5ed77835..e025e9f052 100644 --- a/drivers/net/wireless/bcm43xx/Makefile +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -5,4 +5,5 @@ bcm43xx-objs := bcm43xx_main.o bcm43xx_dma.o \ bcm43xx_radio.o bcm43xx_phy.o \ bcm43xx_power.o bcm43xx_wx.o \ bcm43xx_pio.o bcm43xx_ilt.o \ - bcm43xx_leds.o $(bcm43xx-obj-y) + bcm43xx_leds.o bcm43xx_ethtool.o \ + $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c new file mode 100644 index 0000000000..b3ffcf5013 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c @@ -0,0 +1,50 @@ +/* + + Broadcom BCM43xx wireless driver + + ethtool support + + Copyright (c) 2006 Jason Lunz + + Some code in this file is derived from the 8139too.c driver + Copyright (C) 2002 Jeff Garzik + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx.h" +#include "bcm43xx_ethtool.h" + +#include +#include +#include +#include + + +static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(dev); + + strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); + strncpy(info->version, UTS_RELEASE, sizeof(info->version)); + strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN); +} + +struct ethtool_ops bcm43xx_ethtool_ops = { + .get_drvinfo = bcm43xx_get_drvinfo, + .get_link = ethtool_op_get_link, +}; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h new file mode 100644 index 0000000000..813704991f --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h @@ -0,0 +1,8 @@ +#ifndef BCM43xx_ETHTOOL_H_ +#define BCM43xx_ETHTOOL_H_ + +#include + +extern struct ethtool_ops bcm43xx_ethtool_ops; + +#endif /* BCM43xx_ETHTOOL_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index c0ec503102..1051a49dda 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -49,6 +49,7 @@ #include "bcm43xx_pio.h" #include "bcm43xx_power.h" #include "bcm43xx_wx.h" +#include "bcm43xx_ethtool.h" MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); @@ -4249,6 +4250,7 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, #endif net_dev->wireless_handlers = &bcm43xx_wx_handlers_def; net_dev->irq = pdev->irq; + SET_ETHTOOL_OPS(net_dev, &bcm43xx_ethtool_ops); /* initialize the bcm43xx_private struct */ bcm = bcm43xx_priv(net_dev); -- cgit v1.2.2 From 8fa252d099d864f8848a9890f26d1a51a9c7ad32 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 2 Feb 2006 19:49:15 +0100 Subject: [PATCH] bcm43xx: Wireless Ext update Wireless Ext update: update we_version_source set enc_capa Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index fe6409a909..c1d788d50f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -41,6 +41,11 @@ #include "bcm43xx_main.h" #include "bcm43xx_radio.h" + +/* The WIRELESS_EXT version, which is implemented by this driver. */ +#define BCM43xx_WX_VERSION 18 + + /* Define to enable a printk on each wx handler function invocation */ //#define BCM43xx_WX_DEBUG @@ -282,7 +287,12 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, range->max_encoding_tokens = WEP_KEYS; range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 16; + range->we_version_source = BCM43xx_WX_VERSION; + + range->enc_capa = IW_ENC_CAPA_WPA | + IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | + IW_ENC_CAPA_CIPHER_CCMP; spin_lock_irqsave(&bcm->lock, flags); -- cgit v1.2.2 From 67093a65c08dc45374f642b1ec1b86e7095a4dc8 Mon Sep 17 00:00:00 2001 From: Danny van Dyk Date: Wed, 1 Feb 2006 00:43:05 +0100 Subject: [PATCH] Sync bcm43xx_phy_initb6() with specs Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 15 ++++++++++----- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_radio.h | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index f5e7a6ab93..d90f207b24 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -947,7 +947,7 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x0050, 0x0020); if ((bcm->current_core->radio->manufact == 0x17F) && (bcm->current_core->radio->version == 0x2050) && - (bcm->current_core->radio->revision == 2)) { + (bcm->current_core->radio->revision <= 2)) { bcm43xx_radio_write16(bcm, 0x0050, 0x0020); bcm43xx_radio_write16(bcm, 0x005A, 0x0070); bcm43xx_radio_write16(bcm, 0x005B, 0x007B); @@ -984,10 +984,15 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) bcm43xx_write16(bcm, 0x03E4, 0x0009); if (phy->type == BCM43xx_PHYTYPE_B) { bcm43xx_write16(bcm, 0x03E6, 0x8140); - bcm43xx_phy_write(bcm, 0x0016, 0x5410); - bcm43xx_phy_write(bcm, 0x0017, 0xA820); - bcm43xx_phy_write(bcm, 0x0007, 0x0062); - TODO();//TODO: calibrate stuff. + bcm43xx_phy_write(bcm, 0x0016, 0x0410); + bcm43xx_phy_write(bcm, 0x0017, 0x0820); + bcm43xx_phy_write(bcm, 0x0062, 0x0007); + (void) bcm43xx_radio_calibrationvalue(bcm); + bcm43xx_phy_lo_b_measure(bcm); + if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { + bcm43xx_calc_nrssi_slope(bcm); + bcm43xx_calc_nrssi_threshold(bcm); + } bcm43xx_phy_init_pctl(bcm); } else bcm43xx_write16(bcm, 0x03E6, 0x0); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 5ce6acef2c..3901aa9946 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -1184,7 +1184,7 @@ int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, return 0; } -static u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm) +u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm) { u16 reg, index, ret; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h index 89fe292821..a5d2e10d5d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h @@ -89,5 +89,6 @@ void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val); void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm); void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm); +u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm); #endif /* BCM43xx_RADIO_H_ */ -- cgit v1.2.2 From 393344f67b598aaed594b9006e9eaa44ab62caa0 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 5 Feb 2006 15:28:20 +0100 Subject: [PATCH] bcm43xx: fix txpower reporting in WE. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 2 ++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4 +++ drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 9 ++---- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 44 +++++++++++++++++++++++------ 4 files changed, 44 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 7b97d8bf79..981d563f57 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -525,6 +525,8 @@ struct bcm43xx_radioinfo { * 3: tx_CTL2 */ u16 txpower[4]; + /* Desired TX power in dBm Q5.2 */ + u16 txpower_desired; /* Current Interference Mitigation mode */ int interfmode; /* Stack of saved values from the Interference Mitigation code */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 1051a49dda..8e08c41f86 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -793,6 +793,10 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) bcm->current_core->radio->txpower[2] = 3; else bcm->current_core->radio->txpower[2] = 0; + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + bcm->current_core->radio->txpower_desired = bcm->sprom.maxpower_aphy; + else + bcm->current_core->radio->txpower_desired = bcm->sprom.maxpower_bgphy; /* Initialize the in-memory nrssi Lookup Table. */ for (i = 0; i < 64; i++) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index d90f207b24..d3c2fc1df3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -1768,14 +1768,9 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) where REG is the max power as per the regulatory domain */ - /*TODO: Get desired_pwr from wx_handlers or the stack - limit_value(desired_pwr, 0, max_pwr); - */ - - desired_pwr = max_pwr; /* remove this when we have a real desired_pwr */ - + desired_pwr = limit_value(radio->txpower_desired, 0, max_pwr); + /* Check if we need to adjust the current power. */ pwr_adjust = desired_pwr - estimated_pwr; - radio_att_delta = -(pwr_adjust + 7) >> 3; baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta); if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index c1d788d50f..bed7cfbe81 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -484,21 +484,40 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct bcm43xx_radioinfo *radio; + struct bcm43xx_phyinfo *phy; unsigned long flags; int err = -ENODEV; + u16 maxpower; wx_enter(); + if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { + printk(PFX KERN_ERR "TX power not in dBm.\n"); + return -EOPNOTSUPP; + } + spin_lock_irqsave(&bcm->lock, flags); if (!bcm->initialized) goto out_unlock; - if (data->power.disabled != (!(bcm->current_core->radio->enabled))) { - if (data->power.disabled) + radio = bcm->current_core->radio; + phy = bcm->current_core->phy; + if (data->txpower.disabled != (!(radio->enabled))) { + if (data->txpower.disabled) bcm43xx_radio_turn_off(bcm); else bcm43xx_radio_turn_on(bcm); } - //TODO: set txpower. + if (data->txpower.value > 0) { + /* desired and maxpower dBm values are in Q5.2 */ + if (phy->type == BCM43xx_PHYTYPE_A) + maxpower = bcm->sprom.maxpower_aphy; + else + maxpower = bcm->sprom.maxpower_bgphy; + radio->txpower_desired = limit_value(data->txpower.value << 2, + 0, maxpower); + bcm43xx_phy_xmitpower(bcm); + } err = 0; out_unlock: @@ -513,18 +532,27 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct bcm43xx_radioinfo *radio; unsigned long flags; + int err = -ENODEV; wx_enter(); spin_lock_irqsave(&bcm->lock, flags); -//TODO data->power.value = ??? - data->power.fixed = 1; - data->power.flags = IW_TXPOW_DBM; - data->power.disabled = !(bcm->current_core->radio->enabled); + if (!bcm->initialized) + goto out_unlock; + radio = bcm->current_core->radio; + /* desired dBm value is in Q5.2 */ + data->txpower.value = radio->txpower_desired >> 2; + data->txpower.fixed = 1; + data->txpower.flags = IW_TXPOW_DBM; + data->txpower.disabled = !(radio->enabled); + + err = 0; +out_unlock: spin_unlock_irqrestore(&bcm->lock, flags); - return 0; + return err; } static int bcm43xx_wx_set_retry(struct net_device *net_dev, -- cgit v1.2.2 From 62b7f0dfab0508a45a93045d49eda26d5285188d Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 8 Feb 2006 17:36:46 +0100 Subject: [PATCH] bcm43xx: enable SPROM writing. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index bed7cfbe81..6f6f19aed3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -976,7 +976,7 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, printk("75%%"); else if (i % 2) printk("."); -//TODO bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); + bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); mdelay(20); } spromctl &= ~0x10; /* SPROM WRITE enable. */ -- cgit v1.2.2 From 921e485f98b11656cdcc39a37605e116e34cb315 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 8 Feb 2006 17:55:55 +0100 Subject: [PATCH] bcm43xx: heavily increase mac_suspend timeout. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 8e08c41f86..4c4a2d71ca 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2473,16 +2473,13 @@ void bcm43xx_mac_suspend(struct bcm43xx_private *bcm) bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) & ~BCM43xx_SBF_MAC_ENABLED); bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ - for (i = 1000; i > 0; i--) { + for (i = 100000; i; i--) { tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (tmp & BCM43xx_IRQ_READY) { - i = -1; - break; - } + if (tmp & BCM43xx_IRQ_READY) + return; udelay(10); } - if (!i) - printkl(KERN_ERR PFX "Failed to suspend mac!\n"); + printkl(KERN_ERR PFX "MAC suspend failed\n"); } void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, -- cgit v1.2.2 From b5488beba8030b791e035c4da0122f98c42e355b Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 8 Feb 2006 18:00:30 +0100 Subject: [PATCH] bcm43xx: fix compiletime warning (phy_xmitpower) Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 6f6f19aed3..d383337db9 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -40,6 +40,7 @@ #include "bcm43xx_wx.h" #include "bcm43xx_main.h" #include "bcm43xx_radio.h" +#include "bcm43xx_phy.h" /* The WIRELESS_EXT version, which is implemented by this driver. */ -- cgit v1.2.2 From 5c57807afcc28a6b8fb579ef2c79e49f0b688425 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 8 Feb 2006 18:04:02 +0100 Subject: [PATCH] bcm43xx: remove WX debugging. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 68 ------------------------------- 1 file changed, 68 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index d383337db9..4c972cdc0a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -46,18 +46,6 @@ /* The WIRELESS_EXT version, which is implemented by this driver. */ #define BCM43xx_WX_VERSION 18 - -/* Define to enable a printk on each wx handler function invocation */ -//#define BCM43xx_WX_DEBUG - - -#ifdef BCM43xx_WX_DEBUG -# define printk_wx printk -#else -# define printk_wx(x...) do { /* nothing */ } while (0) -#endif -#define wx_enter() printk_wx(KERN_INFO PFX "WX handler called: %s\n", __FUNCTION__); - #define MAX_WX_STRING 80 @@ -73,8 +61,6 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, char suffix[7] = { 0 }; int have_a = 0, have_b = 0, have_g = 0; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); nr_80211 = bcm43xx_num_80211_cores(bcm); for (i = 0; i < nr_80211; i++) { @@ -127,8 +113,6 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, int freq; int err = 0; - wx_enter(); - if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { channel = data->freq.m; freq = bcm43xx_channel_to_freq(bcm, channel); @@ -148,8 +132,6 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, } else bcm->current_core->radio->initial_channel = channel; spin_unlock_irqrestore(&bcm->lock, flags); - if (!err) - printk_wx(KERN_INFO PFX "Selected channel: %d\n", channel); return err; } @@ -164,8 +146,6 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, int err = -ENODEV; u16 channel; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); channel = bcm->current_core->radio->channel; if (channel == 0xFF) { @@ -195,8 +175,6 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev, unsigned long flags; int mode; - wx_enter(); - mode = data->mode; if (mode == IW_MODE_AUTO) mode = BCM43xx_INITIAL_IWMODE; @@ -217,8 +195,6 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); data->mode = bcm->ieee->iw_mode; spin_unlock_irqrestore(&bcm->lock, flags); @@ -231,7 +207,6 @@ static int bcm43xx_wx_set_sensitivity(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -241,7 +216,6 @@ static int bcm43xx_wx_get_sensitivity(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -257,8 +231,6 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, unsigned long flags; int i, j; - wx_enter(); - data->data.length = sizeof(*range); memset(range, 0, sizeof(*range)); @@ -355,8 +327,6 @@ static int bcm43xx_wx_set_nick(struct net_device *net_dev, unsigned long flags; size_t len; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); memcpy(bcm->nick, extra, len); @@ -375,8 +345,6 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev, unsigned long flags; size_t len; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); len = strlen(bcm->nick) + 1; memcpy(extra, bcm->nick, len); @@ -396,8 +364,6 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); if (data->rts.disabled) { bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; @@ -422,8 +388,6 @@ static int bcm43xx_wx_get_rts(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); data->rts.value = bcm->rts_threshold; data->rts.fixed = 0; @@ -442,8 +406,6 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); if (data->frag.disabled) { bcm->ieee->fts = MAX_FRAG_THRESHOLD; @@ -468,8 +430,6 @@ static int bcm43xx_wx_get_frag(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); data->frag.value = bcm->ieee->fts; data->frag.fixed = 0; @@ -491,8 +451,6 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, int err = -ENODEV; u16 maxpower; - wx_enter(); - if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { printk(PFX KERN_ERR "TX power not in dBm.\n"); return -EOPNOTSUPP; @@ -537,8 +495,6 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, unsigned long flags; int err = -ENODEV; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); if (!bcm->initialized) goto out_unlock; @@ -561,7 +517,6 @@ static int bcm43xx_wx_set_retry(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -571,7 +526,6 @@ static int bcm43xx_wx_get_retry(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -584,8 +538,6 @@ static int bcm43xx_wx_set_encoding(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); int err; - wx_enter(); - err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra); return err; @@ -599,8 +551,6 @@ static int bcm43xx_wx_set_encodingext(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); int err; - wx_enter(); - err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra); return err; @@ -614,8 +564,6 @@ static int bcm43xx_wx_get_encoding(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); int err; - wx_enter(); - err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra); return err; @@ -629,8 +577,6 @@ static int bcm43xx_wx_get_encodingext(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); int err; - wx_enter(); - err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra); return err; @@ -641,7 +587,6 @@ static int bcm43xx_wx_set_power(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -651,7 +596,6 @@ static int bcm43xx_wx_get_power(struct net_device *net_dev, union iwreq_data *data, char *extra) { - wx_enter(); /*TODO*/ return 0; } @@ -665,8 +609,6 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, unsigned long flags; int mode, err = 0; - wx_enter(); - mode = *((int *)extra); switch (mode) { case 0: @@ -717,8 +659,6 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, unsigned long flags; int mode; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); mode = bcm->current_core->radio->interfmode; spin_unlock_irqrestore(&bcm->lock, flags); @@ -750,8 +690,6 @@ static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, unsigned long flags; int on; - wx_enter(); - on = *((int *)extra); spin_lock_irqsave(&bcm->lock, flags); bcm->short_preamble = !!on; @@ -769,8 +707,6 @@ static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, unsigned long flags; int on; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); on = bcm->short_preamble; spin_unlock_irqrestore(&bcm->lock, flags); @@ -793,8 +729,6 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, unsigned long flags; int on; - wx_enter(); - on = *((int *)extra); spin_lock_irqsave(&bcm->lock, flags); bcm->ieee->host_encrypt = !!on; @@ -815,8 +749,6 @@ static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, unsigned long flags; int on; - wx_enter(); - spin_lock_irqsave(&bcm->lock, flags); on = bcm->ieee->host_encrypt; spin_unlock_irqrestore(&bcm->lock, flags); -- cgit v1.2.2 From 77db31ea4322f2dd12dc814d6664ae96517604c0 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Feb 2006 16:47:44 +0100 Subject: [PATCH] bcm43xx: Partially fix PIO code. Add Kconfig option for PIO or DMA mode (or both). Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 18 +- drivers/net/wireless/bcm43xx/Kconfig | 57 +++++ drivers/net/wireless/bcm43xx/Makefile | 6 +- drivers/net/wireless/bcm43xx/bcm43xx.h | 29 ++- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 46 ++++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 69 +++-- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 383 ++++++++++++++-------------- drivers/net/wireless/bcm43xx/bcm43xx_pio.h | 78 +++++- 8 files changed, 438 insertions(+), 248 deletions(-) create mode 100644 drivers/net/wireless/bcm43xx/Kconfig (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 3b1363c971..5c4d7b4ece 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -500,23 +500,7 @@ config PRISM54 will be called prism54.ko. source "drivers/net/wireless/hostap/Kconfig" - -config BCM43XX - tristate "Broadcom BCM43xx wireless support" - depends on PCI && IEEE80211 && NET_RADIO && IEEE80211_SOFTMAC && EXPERIMENTAL - select FW_LOADER - ---help--- - This is an experimental driver for the Broadcom 43xx wireless chip, - found in the Apple Airport Extreme and various other devices. - -config BCM43XX_DEBUG - bool "Broadcom BCM43xx debugging (RECOMMENDED)" - depends on BCM43XX - default y - ---help--- - Broadcom 43xx debugging messages. - Say Y, because the driver is still very experimental and - this will help you get it running. +source "drivers/net/wireless/bcm43xx/Kconfig" # yes, this works even when no drivers are selected config NET_WIRELESS diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig new file mode 100644 index 0000000000..d8d23155ee --- /dev/null +++ b/drivers/net/wireless/bcm43xx/Kconfig @@ -0,0 +1,57 @@ +config BCM43XX + tristate "Broadcom BCM43xx wireless support" + depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL + select FW_LOADER + ---help--- + This is an experimental driver for the Broadcom 43xx wireless chip, + found in the Apple Airport Extreme and various other devices. + +config BCM43XX_DEBUG + bool "Broadcom BCM43xx debugging (RECOMMENDED)" + depends on BCM43XX + default y + ---help--- + Broadcom 43xx debugging messages. + Say Y, because the driver is still very experimental and + this will help you get it running. + +config BCM43XX_DMA + bool +config BCM43XX_PIO + bool + +choice + prompt "BCM43xx data transfer mode" + depends on BCM43XX + default BCM43XX_DMA_AND_PIO + +config BCM43XX_DMA_AND_PIO_MODE + bool "DMA + PIO" + select BCM43XX_DMA + select BCM43XX_PIO + ---help--- + Include both, Direct Memory Access (DMA) and Programmed I/O (PIO) + data transfer modes. + The actually used mode is selectable through the module + parameter "pio". If the module parameter is pio=0, DMA is used. + Otherwise PIO is used. DMA is default. + + If unsure, choose this option. + +config BCM43XX_DMA_MODE + bool "DMA (Direct Memory Access) only" + select BCM43XX_DMA + ---help--- + Only include Direct Memory Access (DMA). + This reduces the size of the driver module, by omitting the PIO code. + +config BCM43XX_PIO_MODE + bool "PIO (Programmed I/O) only" + select BCM43XX_PIO + ---help--- + Only include Programmed I/O (PIO). + This reduces the size of the driver module, by omitting the DMA code. + Please note that PIO transfers are slow (compared to DMA). + Only use PIO, if DMA does not work for you. + +endchoice diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile index e025e9f052..c87c1525b3 100644 --- a/drivers/net/wireless/bcm43xx/Makefile +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -1,9 +1,11 @@ obj-$(CONFIG_BCM43XX) += bcm43xx.o bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o -bcm43xx-objs := bcm43xx_main.o bcm43xx_dma.o \ +bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o +bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o + +bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \ bcm43xx_radio.o bcm43xx_phy.o \ bcm43xx_power.o bcm43xx_wx.o \ - bcm43xx_pio.o bcm43xx_ilt.o \ bcm43xx_leds.o bcm43xx_ethtool.o \ $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 981d563f57..3d8ac7e952 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -639,7 +639,7 @@ struct bcm43xx_private { u32 initialized:1, /* init_board() succeed */ was_initialized:1, /* for PCI suspend/resume. */ shutting_down:1, /* free_board() in progress */ - pio_mode:1, /* PIO (if true), or DMA (if false) used. */ + __using_pio:1, /* Internal, use bcm43xx_using_pio(). */ bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */ reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */ powersaving:1, /* TRUE if we are in PowerSaving mode. FALSE otherwise. */ @@ -749,6 +749,33 @@ struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) return ieee80211softmac_priv(dev); } + +/* Helper function, which returns a boolean. + * TRUE, if PIO is used; FALSE, if DMA is used. + */ +#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO) +static inline +int bcm43xx_using_pio(struct bcm43xx_private *bcm) +{ + return bcm->__using_pio; +} +#elif defined(CONFIG_BCM43XX_DMA) +static inline +int bcm43xx_using_pio(struct bcm43xx_private *bcm) +{ + return 0; +} +#elif defined(CONFIG_BCM43XX_PIO) +static inline +int bcm43xx_using_pio(struct bcm43xx_private *bcm) +{ + return 1; +} +#else +# error "Using neither DMA nor PIO? Confused..." +#endif + + static inline int bcm43xx_num_80211_cores(struct bcm43xx_private *bcm) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index 93e99d61f2..88ad34dff2 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -94,6 +94,10 @@ #define BCM43xx_TXRESUME_PERCENT 50 + +#ifdef CONFIG_BCM43XX_DMA + + struct sk_buff; struct bcm43xx_private; struct bcm43xx_xmitstatus; @@ -172,4 +176,46 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, struct ieee80211_txb *txb); void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); + +#else /* CONFIG_BCM43XX_DMA */ + + +static inline +int bcm43xx_dma_init(struct bcm43xx_private *bcm) +{ + return 0; +} +static inline +void bcm43xx_dma_free(struct bcm43xx_private *bcm) +{ +} +static inline +int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, + u16 dmacontroller_mmio_base) +{ + return 0; +} +static inline +int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, + u16 dmacontroller_mmio_base) +{ + return 0; +} +static inline +int bcm43xx_dma_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) +{ + return 0; +} +static inline +void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) +{ +} +static inline +void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) +{ +} + +#endif /* CONFIG_BCM43XX_DMA */ #endif /* BCM43xx_DMA_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 4c4a2d71ca..4e49da9981 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -62,10 +62,15 @@ MODULE_LICENSE("GPL"); extern char *nvram_get(char *name); #endif -/* Module parameters */ +#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO) static int modparam_pio; module_param_named(pio, modparam_pio, int, 0444); MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); +#elif defined(CONFIG_BCM43XX_DMA) +# define modparam_pio 0 +#elif defined(CONFIG_BCM43XX_PIO) +# define modparam_pio 1 +#endif static int modparam_bad_frames_preempt; module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); @@ -1528,7 +1533,8 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) { u32 flags = 0x00040000; - if ((bcm43xx_core_enabled(bcm)) && (!bcm->pio_mode)) { + if ((bcm43xx_core_enabled(bcm)) && + !bcm43xx_using_pio(bcm)) { //FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here? #ifndef CONFIG_BCM947XX /* reset all used DMA controllers. */ @@ -1635,7 +1641,7 @@ static inline void handle_irq_transmit_status(struct bcm43xx_private *bcm) } //TODO: There are more (unknown) flags to test. see bcm43xx_main.h - if (bcm->pio_mode) + if (bcm43xx_using_pio(bcm)) bcm43xx_pio_handle_xmitstatus(bcm, &stat); else bcm43xx_dma_handle_xmitstatus(bcm, &stat); @@ -1933,7 +1939,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE)); assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { - if (bcm->pio_mode) + if (bcm43xx_using_pio(bcm)) bcm43xx_pio_rx(bcm->current_core->pio->queue0); else bcm43xx_dma_rx(bcm->current_core->dma->rx_ring0); @@ -1941,7 +1947,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) } if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { if (likely(bcm->current_core->rev < 5)) { - if (bcm->pio_mode) + if (bcm43xx_using_pio(bcm)) bcm43xx_pio_rx(bcm->current_core->pio->queue3); else bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1); @@ -1999,7 +2005,7 @@ void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) & 0x0001dc00; - if ((bcm->pio_mode) && + if (bcm43xx_using_pio(bcm) && (bcm->current_core->rev < 3) && (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) { /* Apply a PIO specific workaround to the dma_reasons */ @@ -2624,7 +2630,7 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) value32 |= 0x100000; //FIXME: What's this? Is this correct? bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - if (bcm->pio_mode) { + if (bcm43xx_using_pio(bcm)) { bcm43xx_write32(bcm, 0x0210, 0x00000100); bcm43xx_write32(bcm, 0x0230, 0x00000100); bcm43xx_write32(bcm, 0x0250, 0x00000100); @@ -3123,15 +3129,12 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) if (bcm->current_core->rev >= 5) bcm43xx_write16(bcm, 0x043C, 0x000C); - if (!bcm->pio_mode) { - err = bcm43xx_dma_init(bcm); - if (err) - goto err_chip_cleanup; - } else { + if (bcm43xx_using_pio(bcm)) err = bcm43xx_pio_init(bcm); - if (err) - goto err_chip_cleanup; - } + else + err = bcm43xx_dma_init(bcm); + if (err) + goto err_chip_cleanup; bcm43xx_write16(bcm, 0x0612, 0x0050); bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); @@ -4001,8 +4004,8 @@ static inline int bcm43xx_tx(struct bcm43xx_private *bcm, { int err = -ENODEV; - if (bcm->pio_mode) - err = bcm43xx_pio_transfer_txb(bcm, txb); + if (bcm43xx_using_pio(bcm)) + err = bcm43xx_pio_tx(bcm, txb); else err = bcm43xx_dma_tx(bcm, txb); @@ -4158,10 +4161,10 @@ static int bcm43xx_net_stop(struct net_device *net_dev) return 0; } -static void bcm43xx_init_private(struct bcm43xx_private *bcm, - struct net_device *net_dev, - struct pci_dev *pci_dev, - struct workqueue_struct *wq) +static int bcm43xx_init_private(struct bcm43xx_private *bcm, + struct net_device *net_dev, + struct pci_dev *pci_dev, + struct workqueue_struct *wq) { bcm->ieee = netdev_priv(net_dev); bcm->softmac = ieee80211_priv(net_dev); @@ -4190,13 +4193,17 @@ static void bcm43xx_init_private(struct bcm43xx_private *bcm, (unsigned long)bcm); tasklet_disable_nosync(&bcm->isr_tasklet); if (modparam_pio) { - bcm->pio_mode = 1; + bcm->__using_pio = 1; } else { - if (pci_set_dma_mask(pci_dev, DMA_30BIT_MASK) == 0) { - bcm->pio_mode = 0; - } else { + if (pci_set_dma_mask(pci_dev, DMA_30BIT_MASK)) { +#ifdef CONFIG_BCM43XX_PIO printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n"); - bcm->pio_mode = 1; + bcm->__using_pio = 1; +#else + printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. " + "Recompile the driver with PIO support, please.\n"); + return -ENODEV; +#endif /* CONFIG_BCM43XX_PIO */ } } bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; @@ -4210,6 +4217,8 @@ static void bcm43xx_init_private(struct bcm43xx_private *bcm, bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr); bcm->ieee->set_security = bcm43xx_ieee80211_set_security; bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit; + + return 0; } static int __devinit bcm43xx_init_one(struct pci_dev *pdev, @@ -4261,7 +4270,9 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, err = -ENOMEM; goto err_free_netdev; } - bcm43xx_init_private(bcm, net_dev, pdev, wq); + err = bcm43xx_init_private(bcm, net_dev, pdev, wq); + if (err) + goto err_destroy_wq; pci_set_drvdata(pdev, net_dev); @@ -4325,7 +4336,9 @@ static void bcm43xx_chip_reset(void *_bcm) bcm43xx_free_board(bcm); bcm->firmware_norelease = 0; bcm43xx_detach_board(bcm); - bcm43xx_init_private(bcm, net_dev, pci_dev, wq); + err = bcm43xx_init_private(bcm, net_dev, pci_dev, wq); + if (err) + goto failure; err = bcm43xx_attach_board(bcm); if (err) goto failure; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 9a55e9d005..0bf4b3e26f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -30,81 +30,88 @@ #include -static inline -u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue, - u16 offset) +static void tx_start(struct bcm43xx_pioqueue *queue) { - return bcm43xx_read16(queue->bcm, queue->mmio_base + offset); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_INIT); } -static inline -void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, - u16 offset, u16 value) +static void tx_octet(struct bcm43xx_pioqueue *queue, + u8 octet) { - bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); + if (queue->need_workarounds) { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, + octet); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_WRITEHI); + } else { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_WRITEHI); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, + octet); + } } -static inline -void tx_start(struct bcm43xx_pioqueue *queue) +static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr, + const u8 *packet, + unsigned int *pos) { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_INIT); -} + const u8 *source; + unsigned int i = *pos; + u16 ret; -static inline -void tx_octet(struct bcm43xx_pioqueue *queue, - u8 octet) -{ - if (queue->bcm->current_core->rev < 3) { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, octet); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_WRITEHI); + if (i < sizeof(*txhdr)) { + source = (const u8 *)txhdr; } else { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_WRITEHI); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, octet); + source = packet; + i -= sizeof(*txhdr); } + ret = le16_to_cpu( *((u16 *)(source + i)) ); + *pos += 2; + + return ret; } -static inline -void tx_data(struct bcm43xx_pioqueue *queue, - u8 *packet, - unsigned int octets) +static void tx_data(struct bcm43xx_pioqueue *queue, + struct bcm43xx_txhdr *txhdr, + const u8 *packet, + unsigned int octets) { u16 data; unsigned int i = 0; - if (queue->bcm->current_core->rev < 3) { - data = be16_to_cpu( *((u16 *)packet) ); + if (queue->need_workarounds) { + data = tx_get_next_word(txhdr, packet, &i); bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); - i += 2; } bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITELO | BCM43xx_PIO_TXCTL_WRITEHI); - for ( ; i < octets - 1; i += 2) { - data = be16_to_cpu( *((u16 *)(packet + i)) ); + BCM43xx_PIO_TXCTL_WRITELO | + BCM43xx_PIO_TXCTL_WRITEHI); + while (i < octets - 1) { + data = tx_get_next_word(txhdr, packet, &i); bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); } if (octets % 2) - tx_octet(queue, packet[octets - 1]); + tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]); } -static inline -void tx_complete(struct bcm43xx_pioqueue *queue, - struct sk_buff *skb) +static void tx_complete(struct bcm43xx_pioqueue *queue, + struct sk_buff *skb) { - u16 data; - - if (queue->bcm->current_core->rev < 3) { - data = be16_to_cpu( *((u16 *)(skb->data + skb->len - 2)) ); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); + if (queue->need_workarounds) { + bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, + skb->data[skb->len - 1]); bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITEHI | BCM43xx_PIO_TXCTL_COMPLETE); + BCM43xx_PIO_TXCTL_WRITEHI | + BCM43xx_PIO_TXCTL_COMPLETE); } else { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, BCM43xx_PIO_TXCTL_COMPLETE); + bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, + BCM43xx_PIO_TXCTL_COMPLETE); } } -static inline -u16 generate_cookie(struct bcm43xx_pioqueue *queue, - int packetindex) +static u16 generate_cookie(struct bcm43xx_pioqueue *queue, + int packetindex) { u16 cookie = 0x0000; @@ -113,8 +120,6 @@ u16 generate_cookie(struct bcm43xx_pioqueue *queue, * for the packet index (in the cache). */ switch (queue->mmio_base) { - default: - assert(0); case BCM43xx_MMIO_PIO1_BASE: break; case BCM43xx_MMIO_PIO2_BASE: @@ -126,6 +131,8 @@ u16 generate_cookie(struct bcm43xx_pioqueue *queue, case BCM43xx_MMIO_PIO4_BASE: cookie = 0x3000; break; + default: + assert(0); } assert(((u16)packetindex & 0xF000) == 0x0000); cookie |= (u16)packetindex; @@ -133,66 +140,75 @@ u16 generate_cookie(struct bcm43xx_pioqueue *queue, return cookie; } -static inline +static struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm, u16 cookie, struct bcm43xx_pio_txpacket **packet) { + struct bcm43xx_pio *pio = bcm->current_core->pio; struct bcm43xx_pioqueue *queue = NULL; int packetindex; switch (cookie & 0xF000) { case 0x0000: - queue = bcm->current_core->pio->queue0; + queue = pio->queue0; break; case 0x1000: - queue = bcm->current_core->pio->queue1; + queue = pio->queue1; break; case 0x2000: - queue = bcm->current_core->pio->queue2; + queue = pio->queue2; break; case 0x3000: - queue = bcm->current_core->pio->queue3; + queue = pio->queue3; break; default: assert(0); } - packetindex = (cookie & 0x0FFF); assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS); - *packet = queue->__tx_packets_cache + packetindex; + *packet = &(queue->tx_packets_cache[packetindex]); return queue; } -static inline -void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, - struct sk_buff *skb, - struct bcm43xx_pio_txpacket *packet) +static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, + struct sk_buff *skb, + struct bcm43xx_pio_txpacket *packet) { + struct bcm43xx_txhdr txhdr; unsigned int octets; assert(skb_shinfo(skb)->nr_frags == 0); - assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); - - __skb_push(skb, sizeof(struct bcm43xx_txhdr)); bcm43xx_generate_txhdr(queue->bcm, - (struct bcm43xx_txhdr *)skb->data, - skb->data + sizeof(struct bcm43xx_txhdr), - skb->len - sizeof(struct bcm43xx_txhdr), + &txhdr, skb->data, skb->len, (packet->xmitted_frags == 0), generate_cookie(queue, pio_txpacket_getindex(packet))); tx_start(queue); - octets = skb->len; - if (queue->bcm->current_core->rev < 3) //FIXME: && this is the last packet in the queue. - octets -= 2; - tx_data(queue, (u8 *)skb->data, octets); + octets = skb->len + sizeof(txhdr); + if (queue->need_workarounds) + octets--; + tx_data(queue, &txhdr, (u8 *)skb->data, octets); tx_complete(queue, skb); } -static inline -int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) +static void free_txpacket(struct bcm43xx_pio_txpacket *packet, + int irq_context) +{ + struct bcm43xx_pioqueue *queue = packet->queue; + + ieee80211_txb_free(packet->txb); + list_move(&packet->list, &queue->txfree); + queue->nr_txfree++; + + assert(queue->tx_devq_used >= packet->xmitted_octets); + assert(queue->tx_devq_packets >= packet->xmitted_frags); + queue->tx_devq_used -= packet->xmitted_octets; + queue->tx_devq_packets -= packet->xmitted_frags; +} + +static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) { struct bcm43xx_pioqueue *queue = packet->queue; struct ieee80211_txb *txb = packet->txb; @@ -204,12 +220,11 @@ int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) skb = txb->fragments[i]; octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr); - assert(queue->tx_devq_size >= octets); assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS); assert(queue->tx_devq_used <= queue->tx_devq_size); /* Check if there is sufficient free space on the device - * TX queue. If not, return and let the TX-work-handler + * TX queue. If not, return and let the TX tasklet * retry later. */ if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS) @@ -234,28 +249,15 @@ int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) return 0; } -static void free_txpacket(struct bcm43xx_pio_txpacket *packet) +static void tx_tasklet(unsigned long d) { - struct bcm43xx_pioqueue *queue = packet->queue; - - ieee80211_txb_free(packet->txb); - - list_move(&packet->list, &packet->queue->txfree); - - assert(queue->tx_devq_used >= packet->xmitted_octets); - queue->tx_devq_used -= packet->xmitted_octets; - assert(queue->tx_devq_packets >= packet->xmitted_frags); - queue->tx_devq_packets -= packet->xmitted_frags; -} - -static void txwork_handler(void *d) -{ - struct bcm43xx_pioqueue *queue = d; + struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d; + struct bcm43xx_private *bcm = queue->bcm; unsigned long flags; struct bcm43xx_pio_txpacket *packet, *tmp_packet; int err; - spin_lock_irqsave(&queue->txlock, flags); + spin_lock_irqsave(&bcm->lock, flags); list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { assert(packet->xmitted_frags < packet->txb->nr_frags); if (packet->xmitted_frags == 0) { @@ -270,22 +272,22 @@ static void txwork_handler(void *d) skb = packet->txb->fragments[i]; if (unlikely(skb->len > queue->tx_devq_size)) { dprintkl(KERN_ERR PFX "PIO TX device queue too small. " - "Dropping packet...\n"); - free_txpacket(packet); + "Dropping packet.\n"); + free_txpacket(packet, 1); goto next_packet; } } } - /* Now try to transmit the packet. + /* Try to transmit the packet. * This may not completely succeed. */ err = pio_tx_packet(packet); if (err) break; -next_packet: + next_packet: continue; } - spin_unlock_irqrestore(&queue->txlock, flags); + spin_unlock_irqrestore(&bcm->lock, flags); } static void setup_txqueues(struct bcm43xx_pioqueue *queue) @@ -293,8 +295,9 @@ static void setup_txqueues(struct bcm43xx_pioqueue *queue) struct bcm43xx_pio_txpacket *packet; int i; + queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS; for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) { - packet = queue->__tx_packets_cache + i; + packet = &(queue->tx_packets_cache[i]); packet->queue = queue; INIT_LIST_HEAD(&packet->list); @@ -311,19 +314,19 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, u32 value; u16 qsize; - queue = kmalloc(sizeof(*queue), GFP_KERNEL); + queue = kzalloc(sizeof(*queue), GFP_KERNEL); if (!queue) goto out; - memset(queue, 0, sizeof(*queue)); queue->bcm = bcm; queue->mmio_base = pio_mmio_base; + queue->need_workarounds = (bcm->current_core->rev < 3); INIT_LIST_HEAD(&queue->txfree); INIT_LIST_HEAD(&queue->txqueue); INIT_LIST_HEAD(&queue->txrunning); - spin_lock_init(&queue->txlock); - INIT_WORK(&queue->txwork, txwork_handler, queue); + tasklet_init(&queue->txtask, tx_tasklet, + (unsigned long)queue); value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); value |= BCM43xx_SBF_XFER_REG_BYTESWAP; @@ -331,7 +334,7 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); if (qsize <= BCM43xx_PIO_TXQADJUST) { - printk(KERN_ERR PFX "PIO tx queue too small (%u)\n", qsize); + printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize); goto err_freequeue; } qsize -= BCM43xx_PIO_TXQADJUST; @@ -354,13 +357,12 @@ static void cancel_transfers(struct bcm43xx_pioqueue *queue) netif_tx_disable(queue->bcm->net_dev); assert(queue->bcm->shutting_down); - cancel_delayed_work(&queue->txwork); - flush_workqueue(queue->bcm->workqueue); + tasklet_disable(&queue->txtask); list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) - free_txpacket(packet); + free_txpacket(packet, 0); list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) - free_txpacket(packet); + free_txpacket(packet, 0); } static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) @@ -374,40 +376,43 @@ static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) void bcm43xx_pio_free(struct bcm43xx_private *bcm) { - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue3); - bcm->current_core->pio->queue3 = NULL; - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue2); - bcm->current_core->pio->queue2 = NULL; - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue1); - bcm->current_core->pio->queue1 = NULL; - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue0); - bcm->current_core->pio->queue0 = NULL; + struct bcm43xx_pio *pio = bcm->current_core->pio; + + bcm43xx_destroy_pioqueue(pio->queue3); + pio->queue3 = NULL; + bcm43xx_destroy_pioqueue(pio->queue2); + pio->queue2 = NULL; + bcm43xx_destroy_pioqueue(pio->queue1); + pio->queue1 = NULL; + bcm43xx_destroy_pioqueue(pio->queue0); + pio->queue0 = NULL; } int bcm43xx_pio_init(struct bcm43xx_private *bcm) { + struct bcm43xx_pio *pio = bcm->current_core->pio; struct bcm43xx_pioqueue *queue; int err = -ENOMEM; queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE); if (!queue) goto out; - bcm->current_core->pio->queue0 = queue; + pio->queue0 = queue; queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE); if (!queue) goto err_destroy0; - bcm->current_core->pio->queue1 = queue; + pio->queue1 = queue; queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE); if (!queue) goto err_destroy1; - bcm->current_core->pio->queue2 = queue; + pio->queue2 = queue; queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE); if (!queue) goto err_destroy2; - bcm->current_core->pio->queue3 = queue; + pio->queue3 = queue; if (bcm->current_core->rev < 3) bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND; @@ -418,41 +423,38 @@ out: return err; err_destroy2: - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue2); - bcm->current_core->pio->queue2 = NULL; + bcm43xx_destroy_pioqueue(pio->queue2); + pio->queue2 = NULL; err_destroy1: - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue1); - bcm->current_core->pio->queue1 = NULL; + bcm43xx_destroy_pioqueue(pio->queue1); + pio->queue1 = NULL; err_destroy0: - bcm43xx_destroy_pioqueue(bcm->current_core->pio->queue0); - bcm->current_core->pio->queue0 = NULL; + bcm43xx_destroy_pioqueue(pio->queue0); + pio->queue0 = NULL; goto out; } -static inline -int pio_transfer_txb(struct bcm43xx_pioqueue *queue, - struct ieee80211_txb *txb) +int bcm43xx_pio_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) { + struct bcm43xx_pioqueue *queue = bcm->current_core->pio->queue1; struct bcm43xx_pio_txpacket *packet; - unsigned long flags; u16 tmp; - spin_lock_irqsave(&queue->txlock, flags); assert(!queue->tx_suspended); assert(!list_empty(&queue->txfree)); tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); - if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) { - spin_unlock_irqrestore(&queue->txlock, flags); + if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) return -EBUSY; - } packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); - packet->txb = txb; - list_move_tail(&packet->list, &queue->txqueue); - packet->xmitted_octets = 0; packet->xmitted_frags = 0; + packet->xmitted_octets = 0; + list_move_tail(&packet->list, &queue->txqueue); + queue->nr_txfree--; + assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); /* Suspend TX, if we are out of packets in the "free" queue. */ if (unlikely(list_empty(&queue->txfree))) { @@ -460,69 +462,66 @@ int pio_transfer_txb(struct bcm43xx_pioqueue *queue, queue->tx_suspended = 1; } - spin_unlock_irqrestore(&queue->txlock, flags); - queue_work(queue->bcm->workqueue, &queue->txwork); + tasklet_schedule(&queue->txtask); return 0; } -int fastcall bcm43xx_pio_transfer_txb(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - return pio_transfer_txb(bcm->current_core->pio->queue1, txb); -} - -void fastcall -bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) +void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) { struct bcm43xx_pioqueue *queue; struct bcm43xx_pio_txpacket *packet; - unsigned long flags; queue = parse_cookie(bcm, status->cookie, &packet); assert(queue); - spin_lock_irqsave(&queue->txlock, flags); - free_txpacket(packet); +//TODO +if (!queue) +return; + free_txpacket(packet, 1); if (unlikely(queue->tx_suspended)) { queue->tx_suspended = 0; netif_wake_queue(queue->bcm->net_dev); } - - /* If there are packets on the txqueue, - * start the work handler again. - */ - if (!list_empty(&queue->txqueue)) { - queue_work(queue->bcm->workqueue, - &queue->txwork); - } - spin_unlock_irqrestore(&queue->txlock, flags); + /* If there are packets on the txqueue, poke the tasklet. */ + if (!list_empty(&queue->txqueue)) + tasklet_schedule(&queue->txtask); } static void pio_rx_error(struct bcm43xx_pioqueue *queue, + int clear_buffers, const char *error) { - printk("PIO RX error: %s\n", error); - bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, BCM43xx_PIO_RXCTL_READY); + int i; + + printkl("PIO RX error: %s\n", error); + bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, + BCM43xx_PIO_RXCTL_READY); + if (clear_buffers) { + assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE); + for (i = 0; i < 15; i++) { + /* Dummy read. */ + bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); + } + } } -void fastcall -bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) +void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) { u16 preamble[21] = { 0 }; struct bcm43xx_rxhdr *rxhdr; - u16 tmp; - u16 len; - int i, err; - int preamble_readwords; + u16 tmp, len, rxflags2; + int i, preamble_readwords; struct sk_buff *skb; +return; tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) { - dprintkl(KERN_ERR PFX "PIO RX: No data available\n"); + dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk. return; } - bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, BCM43xx_PIO_RXCTL_DATAAVAILABLE); + bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, + BCM43xx_PIO_RXCTL_DATAAVAILABLE); for (i = 0; i < 10; i++) { tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); @@ -534,13 +533,14 @@ bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) return; data_ready: +//FIXME: endianess in this function. len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); if (unlikely(len > 0x700)) { - pio_rx_error(queue, "len > 0x700"); + pio_rx_error(queue, 0, "len > 0x700"); return; } if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) { - pio_rx_error(queue, "len == 0"); + pio_rx_error(queue, 0, "len == 0"); return; } preamble[0] = cpu_to_le16(len); @@ -550,28 +550,38 @@ data_ready: preamble_readwords = 18 / sizeof(u16); for (i = 0; i < preamble_readwords; i++) { tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - preamble[i + 1] = cpu_to_be16(tmp); + preamble[i + 1] = cpu_to_be16(tmp);//FIXME? } rxhdr = (struct bcm43xx_rxhdr *)preamble; - if (unlikely(rxhdr->flags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) { - pio_rx_error(queue, "invalid frame"); - if (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE) { - for (i = 0; i < 15; i++) - bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); /* dummy read. */ - } + rxflags2 = le16_to_cpu(rxhdr->flags2); + if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) { + pio_rx_error(queue, + (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE), + "invalid frame"); return; } -//FIXME -#if 0 if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) { - bcm43xx_rx_transmitstatus(queue->bcm, - (const struct bcm43xx_hwxmitstatus *)(preamble + 1)); + /* We received an xmit status. */ + struct bcm43xx_hwxmitstatus *hw; + struct bcm43xx_xmitstatus stat; + + hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1); + stat.cookie = le16_to_cpu(hw->cookie); + stat.flags = hw->flags; + stat.cnt1 = hw->cnt1; + stat.cnt2 = hw->cnt2; + stat.seq = le16_to_cpu(hw->seq); + stat.unknown = le16_to_cpu(hw->unknown); + + bcm43xx_debugfs_log_txstat(queue->bcm, &stat); + bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat); + return; } -#endif + skb = dev_alloc_skb(len); if (unlikely(!skb)) { - pio_rx_error(queue, "out of memory"); + pio_rx_error(queue, 1, "OOM"); return; } skb_put(skb, len); @@ -580,13 +590,14 @@ data_ready: *((u16 *)(skb->data + i)) = tmp; } if (len % 2) { - tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); + tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); skb->data[len - 1] = (tmp & 0x00FF); - skb->data[0] = (tmp & 0xFF00) >> 8; + if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) + skb->data[0x20] = (tmp & 0xFF00) >> 8; + else + skb->data[0x1E] = (tmp & 0xFF00) >> 8; } - err = bcm43xx_rx(queue->bcm, skb, rxhdr); - if (unlikely(err)) - dev_kfree_skb_irq(skb); + bcm43xx_rx(queue->bcm, skb, rxhdr); } /* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h index 71b92ee341..970627bc17 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h @@ -3,9 +3,8 @@ #include "bcm43xx.h" +#include #include -#include -#include #include @@ -32,6 +31,10 @@ #define BCM43xx_PIO_MAXTXPACKETS 256 + +#ifdef CONFIG_BCM43XX_PIO + + struct bcm43xx_pioqueue; struct bcm43xx_xmitstatus; @@ -44,13 +47,14 @@ struct bcm43xx_pio_txpacket { u16 xmitted_octets; }; -#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->__tx_packets_cache)) +#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache)) struct bcm43xx_pioqueue { struct bcm43xx_private *bcm; u16 mmio_base; - u8 tx_suspended:1; + u8 tx_suspended:1, + need_workarounds:1; /* Workarounds needed for core.rev < 3 */ /* Adjusted size of the device internal TX buffer. */ u16 tx_devq_size; @@ -62,6 +66,7 @@ struct bcm43xx_pioqueue { * be taken on incoming TX requests. */ struct list_head txfree; + unsigned int nr_txfree; /* Packets on the txqueue are queued, * but not completely written to the chip, yet. */ @@ -70,19 +75,64 @@ struct bcm43xx_pioqueue { * posted to the device. We are waiting for the txstatus. */ struct list_head txrunning; - /* Locking of the TX queues and the accounting. */ - spinlock_t txlock; - struct work_struct txwork; - struct bcm43xx_pio_txpacket __tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS]; + /* Total number or packets sent. + * (This counter can obviously wrap). + */ + unsigned int nr_tx_packets; + struct tasklet_struct txtask; + struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS]; }; +static inline +u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue, + u16 offset) +{ + return bcm43xx_read16(queue->bcm, queue->mmio_base + offset); +} + +static inline +void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, + u16 offset, u16 value) +{ + bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); +} + + int bcm43xx_pio_init(struct bcm43xx_private *bcm); void bcm43xx_pio_free(struct bcm43xx_private *bcm); -int FASTCALL(bcm43xx_pio_transfer_txb(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb)); -void FASTCALL(bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status)); - -void FASTCALL(bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)); +int bcm43xx_pio_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb); +void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status); +void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); + +#else /* CONFIG_BCM43XX_PIO */ + +static inline +int bcm43xx_pio_init(struct bcm43xx_private *bcm) +{ + return 0; +} +static inline +void bcm43xx_pio_free(struct bcm43xx_private *bcm) +{ +} +static inline +int bcm43xx_pio_tx(struct bcm43xx_private *bcm, + struct ieee80211_txb *txb) +{ + return 0; +} +static inline +void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, + struct bcm43xx_xmitstatus *status) +{ +} +static inline +void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) +{ +} + +#endif /* CONFIG_BCM43XX_PIO */ #endif /* BCM43xx_PIO_H_ */ -- cgit v1.2.2 From 8bcab3f55982cf28310f2303bef741424ad0f563 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Feb 2006 16:52:10 +0100 Subject: [PATCH] bcm43xx: add a note that not all devices support PIO. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig index d8d23155ee..1d677c15b2 100644 --- a/drivers/net/wireless/bcm43xx/Kconfig +++ b/drivers/net/wireless/bcm43xx/Kconfig @@ -52,6 +52,11 @@ config BCM43XX_PIO_MODE Only include Programmed I/O (PIO). This reduces the size of the driver module, by omitting the DMA code. Please note that PIO transfers are slow (compared to DMA). + + Also note that not all devices of the 43xx series support PIO. + The 4306 (Apple Airport Extreme and others) supports PIO, while + the 4318 is known to _not_ support PIO. + Only use PIO, if DMA does not work for you. endchoice -- cgit v1.2.2 From f1f566236dcc4cb57cfae89b539e19c1290e7f34 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Feb 2006 16:55:06 +0100 Subject: [PATCH] Apple Airport: Add Kconfig note that the bcm43xx driver has to be used for Airport Extreme cards. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 5c4d7b4ece..9c01fb26c8 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -309,7 +309,10 @@ config APPLE_AIRPORT Say Y here to support the Airport 802.11b wireless Ethernet hardware built into the Macintosh iBook and other recent PowerPC-based Macintosh machines. This is essentially a Lucent Orinoco card with - a non-standard interface + a non-standard interface. + + This driver does not support the Airport Extreme (802.11b/g). Use + the BCM43xx driver for Airport Extreme cards. config PLX_HERMES tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)" -- cgit v1.2.2 From dcfd720bd733544606b053e8e68b7419211ace72 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Feb 2006 20:25:55 +0100 Subject: [PATCH] bcm43xx: fix LED code. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 88 +++++++++++++++++++---------- drivers/net/wireless/bcm43xx/bcm43xx_leds.h | 11 +++- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 2 +- 3 files changed, 68 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 455a0c743f..8f550c1a92 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -35,12 +35,13 @@ static void bcm43xx_led_changestate(struct bcm43xx_led *led) { struct bcm43xx_private *bcm = led->bcm; const int index = bcm43xx_led_index(led); + const u16 mask = (1 << index); u16 ledctl; assert(index >= 0 && index < BCM43xx_NR_LEDS); assert(led->blink_interval); ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - __change_bit(index, (unsigned long *)(&ledctl)); + ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask); bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); } @@ -61,6 +62,8 @@ static void bcm43xx_led_blink(unsigned long d) static void bcm43xx_led_blink_start(struct bcm43xx_led *led, unsigned long interval) { + if (led->blink_interval) + return; led->blink_interval = interval; bcm43xx_led_changestate(led); led->blink_timer.expires = jiffies + interval; @@ -91,6 +94,39 @@ static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync) bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); } +static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm, + struct bcm43xx_led *led, + int led_index) +{ + /* This function is called, if the behaviour (and activelow) + * information for a LED is missing in the SPROM. + * We hardcode the behaviour values for various devices here. + * Note that the BCM43xx_LED_TEST_XXX behaviour values can + * be used to figure out which led is mapped to which index. + */ + + switch (led_index) { + case 0: + led->behaviour = BCM43xx_LED_ACTIVITY; + if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ) + led->behaviour = BCM43xx_LED_RADIO_ALL; + break; + case 1: + led->behaviour = BCM43xx_LED_RADIO_B; + if (bcm->board_vendor == PCI_VENDOR_ID_ASUSTEK) + led->behaviour = BCM43xx_LED_ASSOC; + break; + case 2: + led->behaviour = BCM43xx_LED_RADIO_A; + break; + case 3: + led->behaviour = BCM43xx_LED_OFF; + break; + default: + assert(0); + } +} + int bcm43xx_leds_init(struct bcm43xx_private *bcm) { struct bcm43xx_led *led; @@ -105,31 +141,12 @@ int bcm43xx_leds_init(struct bcm43xx_private *bcm) for (i = 0; i < BCM43xx_NR_LEDS; i++) { led = &(bcm->leds[i]); led->bcm = bcm; - init_timer(&led->blink_timer); - led->blink_timer.data = (unsigned long)led; - led->blink_timer.function = bcm43xx_led_blink; + setup_timer(&led->blink_timer, + bcm43xx_led_blink, + (unsigned long)led); if (sprom[i] == 0xFF) { - /* SPROM information not set. */ - switch (i) { - case 0: - if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ) - led->behaviour = BCM43xx_LED_RADIO_ALL; - else - led->behaviour = BCM43xx_LED_ACTIVITY; - break; - case 1: - led->behaviour = BCM43xx_LED_RADIO_B; - break; - case 2: - led->behaviour = BCM43xx_LED_RADIO_A; - break; - case 3: - led->behaviour = BCM43xx_LED_OFF; - break; - default: - assert(0); - } + bcm43xx_led_init_hardcoded(bcm, led, i); } else { led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR; led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW); @@ -157,19 +174,19 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) struct bcm43xx_radioinfo *radio = bcm->current_core->radio; struct bcm43xx_phyinfo *phy = bcm->current_core->phy; const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES; - int i, turn_on = 0; + int i, turn_on; unsigned long interval = 0; u16 ledctl; ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); for (i = 0; i < BCM43xx_NR_LEDS; i++) { led = &(bcm->leds[i]); - if (led->behaviour == BCM43xx_LED_INACTIVE) - continue; + turn_on = 0; switch (led->behaviour) { + case BCM43xx_LED_INACTIVE: + continue; case BCM43xx_LED_OFF: - turn_on = 0; break; case BCM43xx_LED_ON: turn_on = 1; @@ -189,7 +206,6 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) phy->type == BCM43xx_PHYTYPE_G)); break; case BCM43xx_LED_MODE_BG: - turn_on = 0; if (phy->type == BCM43xx_PHYTYPE_G && 1/*FIXME: using G rates.*/) turn_on = 1; @@ -222,12 +238,22 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) continue; case BCM43xx_LED_WEIRD: //TODO - turn_on = 0; break; case BCM43xx_LED_ASSOC: - if (1/*TODO: associated*/) + if (bcm->softmac->associated) turn_on = 1; break; +#ifdef CONFIG_BCM43XX_DEBUG + case BCM43xx_LED_TEST_BLINKSLOW: + bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_SLOW); + continue; + case BCM43xx_LED_TEST_BLINKMEDIUM: + bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM); + continue; + case BCM43xx_LED_TEST_BLINKFAST: + bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_FAST); + continue; +#endif /* CONFIG_BCM43XX_DEBUG */ default: assert(0); }; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h index 489a2b1e90..6f18e2f95d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h @@ -16,7 +16,7 @@ struct bcm43xx_led { #define bcm43xx_led_index(led) ((int)((led) - (led)->bcm->leds)) /* Delay between state changes when blinking in jiffies */ -#define BCM43xx_LEDBLINK_SLOW (HZ / 2) +#define BCM43xx_LEDBLINK_SLOW (HZ / 1) #define BCM43xx_LEDBLINK_MEDIUM (HZ / 4) #define BCM43xx_LEDBLINK_FAST (HZ / 8) @@ -37,6 +37,15 @@ enum { /* LED behaviour values */ BCM43xx_LED_WEIRD,//FIXME BCM43xx_LED_ASSOC, BCM43xx_LED_INACTIVE, + + /* Behaviour values for testing. + * With these values it is easier to figure out + * the real behaviour of leds, in case the SPROM + * is missing information. + */ + BCM43xx_LED_TEST_BLINKSLOW, + BCM43xx_LED_TEST_BLINKMEDIUM, + BCM43xx_LED_TEST_BLINKFAST, }; int bcm43xx_leds_init(struct bcm43xx_private *bcm); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 4e49da9981..fbf931d4a1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1943,7 +1943,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) bcm43xx_pio_rx(bcm->current_core->pio->queue0); else bcm43xx_dma_rx(bcm->current_core->dma->rx_ring0); - activity = 1; + /* We intentionally don't set "activity" to 1, here. */ } if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { if (likely(bcm->current_core->rev < 5)) { -- cgit v1.2.2 From ab4977f881fc23cb02ef6f20d1e8ebbdcfef75ad Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Feb 2006 22:40:39 +0100 Subject: [PATCH] bcm43xx: rewrite and simplify the periodic task handling. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 13 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 194 ++++++++++------------------ 2 files changed, 73 insertions(+), 134 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 3d8ac7e952..99b2e72281 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -418,7 +418,6 @@ enum { struct net_device; struct pci_dev; -struct workqueue_struct; struct bcm43xx_dmaring; struct bcm43xx_pioqueue; @@ -706,18 +705,10 @@ struct bcm43xx_private { /* Interrupt Service Routine tasklet (bottom-half) */ struct tasklet_struct isr_tasklet; - /* Custom driver work queue. */ - struct workqueue_struct *workqueue; /* Periodic tasks */ - struct work_struct periodic_work0; -#define BCM43xx_PERIODIC_0_DELAY (HZ * 15) - struct work_struct periodic_work1; -#define BCM43xx_PERIODIC_1_DELAY ((HZ * 60) + HZ / 2) - struct work_struct periodic_work2; -#define BCM43xx_PERIODIC_2_DELAY ((HZ * 120) + HZ) - struct work_struct periodic_work3; -#define BCM43xx_PERIODIC_3_DELAY ((HZ * 30) + HZ / 5) + struct timer_list periodic_tasks; + unsigned int periodic_state; struct work_struct restart_work; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index fbf931d4a1..18152b0b2d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2939,7 +2939,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) core->phy->minlowsigpos[1] = 0; spin_lock_init(&core->phy->lock); core->radio = &bcm->radio[i]; - core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; + core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; core->radio->channel = 0xFF; core->radio->initial_channel = 0xFF; core->radio->lofcal = 0xFFFF; @@ -3261,144 +3261,104 @@ static void bcm43xx_softmac_init(struct bcm43xx_private *bcm) ieee80211softmac_start(bcm->net_dev); } -static void bcm43xx_periodic_work0_handler(void *d) +static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) { - struct bcm43xx_private *bcm = d; - unsigned long flags; - //TODO: unsigned int aci_average; - - spin_lock_irqsave(&bcm->lock, flags); + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { - //FIXME: aci_average = bcm43xx_update_aci_average(bcm); - if (bcm->current_core->radio->aci_enable && bcm->current_core->radio->aci_wlan_automatic) { - bcm43xx_mac_suspend(bcm); - if (!bcm->current_core->radio->aci_enable && - 1 /*FIXME: We are not scanning? */) { - /*FIXME: First add bcm43xx_update_aci_average() before - * uncommenting this: */ - //if (bcm43xx_radio_aci_scan) - // bcm43xx_radio_set_interference_mitigation(bcm, - // BCM43xx_RADIO_INTERFMODE_MANUALWLAN); - } else if (1/*FIXME*/) { - //if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) - // bcm43xx_radio_set_interference_mitigation(bcm, - // BCM43xx_RADIO_INTERFMODE_MANUALWLAN); - } - bcm43xx_mac_enable(bcm); - } else if (bcm->current_core->radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) { - if (bcm->current_core->phy->rev == 1) { - //FIXME: implement rev1 workaround - } - } - } - bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning? - //TODO for APHY (temperature?) + if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2) + return; - if (likely(!bcm->shutting_down)) { - queue_delayed_work(bcm->workqueue, &bcm->periodic_work0, - BCM43xx_PERIODIC_0_DELAY); - } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_mac_suspend(bcm); + bcm43xx_phy_lo_g_measure(bcm); + bcm43xx_mac_enable(bcm); } -static void bcm43xx_periodic_work1_handler(void *d) +static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm) { - struct bcm43xx_private *bcm = d; - unsigned long flags; - - spin_lock_irqsave(&bcm->lock, flags); - bcm43xx_phy_lo_mark_all_unused(bcm); if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { bcm43xx_mac_suspend(bcm); bcm43xx_calc_nrssi_slope(bcm); bcm43xx_mac_enable(bcm); } - - if (likely(!bcm->shutting_down)) { - queue_delayed_work(bcm->workqueue, &bcm->periodic_work1, - BCM43xx_PERIODIC_1_DELAY); - } - spin_unlock_irqrestore(&bcm->lock, flags); } -static void bcm43xx_periodic_work2_handler(void *d) +static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm) { - struct bcm43xx_private *bcm = d; - unsigned long flags; - - spin_lock_irqsave(&bcm->lock, flags); - - assert(bcm->current_core->phy->type == BCM43xx_PHYTYPE_G); - assert(bcm->current_core->phy->rev >= 2); + /* Update device statistics. */ + bcm43xx_calculate_link_quality(bcm); +} - bcm43xx_mac_suspend(bcm); - bcm43xx_phy_lo_g_measure(bcm); - bcm43xx_mac_enable(bcm); +static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - if (likely(!bcm->shutting_down)) { - queue_delayed_work(bcm->workqueue, &bcm->periodic_work2, - BCM43xx_PERIODIC_2_DELAY); + if (phy->type == BCM43xx_PHYTYPE_G) { + //TODO: update_aci_moving_average + if (radio->aci_enable && radio->aci_wlan_automatic) { + bcm43xx_mac_suspend(bcm); + if (!radio->aci_enable && 1 /*TODO: not scanning? */) { + if (0 /*TODO: bunch of conditions*/) { + bcm43xx_radio_set_interference_mitigation(bcm, + BCM43xx_RADIO_INTERFMODE_MANUALWLAN); + } + } else if (1/*TODO*/) { + /* + if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) { + bcm43xx_radio_set_interference_mitigation(bcm, + BCM43xx_RADIO_INTERFMODE_NONE); + } + */ + } + bcm43xx_mac_enable(bcm); + } else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN && + phy->rev == 1) { + //TODO: implement rev1 workaround + } } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning? + //TODO for APHY (temperature?) } -static void bcm43xx_periodic_work3_handler(void *d) +static void bcm43xx_periodic_task_handler(unsigned long d) { - struct bcm43xx_private *bcm = d; + struct bcm43xx_private *bcm = (struct bcm43xx_private *)d; unsigned long flags; + unsigned int state; spin_lock_irqsave(&bcm->lock, flags); - /* Update device statistics. */ - bcm43xx_calculate_link_quality(bcm); + assert(bcm->initialized); + state = bcm->periodic_state; + if (state % 8 == 0) + bcm43xx_periodic_every120sec(bcm); + if (state % 4 == 0) + bcm43xx_periodic_every60sec(bcm); + if (state % 2 == 0) + bcm43xx_periodic_every30sec(bcm); + bcm43xx_periodic_every15sec(bcm); + bcm->periodic_state = state + 1; + + mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15)); - if (likely(!bcm->shutting_down)) { - queue_delayed_work(bcm->workqueue, &bcm->periodic_work3, - BCM43xx_PERIODIC_3_DELAY); - } spin_unlock_irqrestore(&bcm->lock, flags); } -/* Delete all periodic tasks and make - * sure they are not running any longer - */ static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) { - cancel_delayed_work(&bcm->periodic_work0); - cancel_delayed_work(&bcm->periodic_work1); - cancel_delayed_work(&bcm->periodic_work2); - cancel_delayed_work(&bcm->periodic_work3); - flush_workqueue(bcm->workqueue); + del_timer_sync(&bcm->periodic_tasks); } -/* Setup all periodic tasks. */ static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) { - INIT_WORK(&bcm->periodic_work0, bcm43xx_periodic_work0_handler, bcm); - INIT_WORK(&bcm->periodic_work1, bcm43xx_periodic_work1_handler, bcm); - INIT_WORK(&bcm->periodic_work2, bcm43xx_periodic_work2_handler, bcm); - INIT_WORK(&bcm->periodic_work3, bcm43xx_periodic_work3_handler, bcm); - - /* Periodic task 0: Delay ~15sec */ - queue_delayed_work(bcm->workqueue, &bcm->periodic_work0, - BCM43xx_PERIODIC_0_DELAY); - - /* Periodic task 1: Delay ~60sec */ - queue_delayed_work(bcm->workqueue, &bcm->periodic_work1, - BCM43xx_PERIODIC_1_DELAY); + struct timer_list *timer = &(bcm->periodic_tasks); - /* Periodic task 2: Delay ~120sec */ - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && - bcm->current_core->phy->rev >= 2) { - queue_delayed_work(bcm->workqueue, &bcm->periodic_work2, - BCM43xx_PERIODIC_2_DELAY); - } - - /* Periodic task 3: Delay ~30sec */ - queue_delayed_work(bcm->workqueue, &bcm->periodic_work3, - BCM43xx_PERIODIC_3_DELAY); + setup_timer(timer, + bcm43xx_periodic_task_handler, + (unsigned long)bcm); + timer->expires = jiffies; + add_timer(timer); } static void bcm43xx_security_init(struct bcm43xx_private *bcm) @@ -3414,13 +3374,13 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) int i, err; unsigned long flags; + bcm43xx_periodic_tasks_delete(bcm); + spin_lock_irqsave(&bcm->lock, flags); bcm->initialized = 0; bcm->shutting_down = 1; spin_unlock_irqrestore(&bcm->lock, flags); - bcm43xx_periodic_tasks_delete(bcm); - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE)) continue; @@ -4163,13 +4123,11 @@ static int bcm43xx_net_stop(struct net_device *net_dev) static int bcm43xx_init_private(struct bcm43xx_private *bcm, struct net_device *net_dev, - struct pci_dev *pci_dev, - struct workqueue_struct *wq) + struct pci_dev *pci_dev) { bcm->ieee = netdev_priv(net_dev); bcm->softmac = ieee80211_priv(net_dev); bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; - bcm->workqueue = wq; #ifdef DEBUG_ENABLE_MMIO_PRINT bcm43xx_mmioprint_initial(bcm, 1); @@ -4226,7 +4184,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, { struct net_device *net_dev; struct bcm43xx_private *bcm; - struct workqueue_struct *wq; int err; #ifdef CONFIG_BCM947XX @@ -4265,20 +4222,15 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, /* initialize the bcm43xx_private struct */ bcm = bcm43xx_priv(net_dev); memset(bcm, 0, sizeof(*bcm)); - wq = create_workqueue(KBUILD_MODNAME "_wq"); - if (!wq) { - err = -ENOMEM; - goto err_free_netdev; - } - err = bcm43xx_init_private(bcm, net_dev, pdev, wq); + err = bcm43xx_init_private(bcm, net_dev, pdev); if (err) - goto err_destroy_wq; + goto err_free_netdev; pci_set_drvdata(pdev, net_dev); err = bcm43xx_attach_board(bcm); if (err) - goto err_destroy_wq; + goto err_free_netdev; err = register_netdev(net_dev); if (err) { @@ -4296,8 +4248,6 @@ out: err_detach_board: bcm43xx_detach_board(bcm); -err_destroy_wq: - destroy_workqueue(wq); err_free_netdev: free_ieee80211softmac(net_dev); goto out; @@ -4312,7 +4262,6 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) unregister_netdev(net_dev); bcm43xx_detach_board(bcm); assert(bcm->ucode == NULL); - destroy_workqueue(bcm->workqueue); free_ieee80211softmac(net_dev); } @@ -4324,7 +4273,6 @@ static void bcm43xx_chip_reset(void *_bcm) struct bcm43xx_private *bcm = _bcm; struct net_device *net_dev = bcm->net_dev; struct pci_dev *pci_dev = bcm->pci_dev; - struct workqueue_struct *wq = bcm->workqueue; int err; int was_initialized = bcm->initialized; @@ -4336,7 +4284,7 @@ static void bcm43xx_chip_reset(void *_bcm) bcm43xx_free_board(bcm); bcm->firmware_norelease = 0; bcm43xx_detach_board(bcm); - err = bcm43xx_init_private(bcm, net_dev, pci_dev, wq); + err = bcm43xx_init_private(bcm, net_dev, pci_dev); if (err) goto failure; err = bcm43xx_attach_board(bcm); @@ -4364,7 +4312,7 @@ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); - queue_work(bcm->workqueue, &bcm->restart_work); + schedule_work(&bcm->restart_work); } #ifdef CONFIG_PM -- cgit v1.2.2 From 489423c8d0ba2b4311530502f7b5a331da9a60f9 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 13 Feb 2006 00:11:07 +0100 Subject: [PATCH] bcm43xx: Code cleanups. This removes various "inline" statements and reduces codesize. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 9 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 281 +++++++++++----------------- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 18 +- 3 files changed, 127 insertions(+), 181 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 99b2e72281..848717513b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -19,16 +19,17 @@ #define PFX KBUILD_MODNAME ": " -#define BCM43xx_SWITCH_CORE_MAX_RETRIES 10 +#define BCM43xx_SWITCH_CORE_MAX_RETRIES 50 #define BCM43xx_IRQWAIT_MAX_RETRIES 50 #define BCM43xx_IO_SIZE 8192 -#define BCM43xx_REG_ACTIVE_CORE 0x80 -/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */ -#define BCM43xx_PCICFG_ICR 0x94 +/* Active Core PCI Configuration Register. */ +#define BCM43xx_PCICFG_ACTIVE_CORE 0x80 /* SPROM control register. */ #define BCM43xx_PCICFG_SPROMCTL 0x88 +/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */ +#define BCM43xx_PCICFG_ICR 0x94 /* MMIO offsets */ #define BCM43xx_MMIO_DMA1_REASON 0x20 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 18152b0b2d..3443bd3c23 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -119,40 +119,29 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging."); //#define DEBUG_ENABLE_PCILOG -static struct pci_device_id bcm43xx_pci_tbl[] = { - - /* Detailed list maintained at: - * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices - */ - -#ifdef CONFIG_BCM947XX - /* SB bus on BCM947xx */ - { PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -#endif - +/* Detailed list maintained at: + * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices + */ + static struct pci_device_id bcm43xx_pci_tbl[] = { /* Broadcom 4303 802.11b */ { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - - /* Broadcom 4307 802.11b */ + /* Broadcom 4307 802.11b */ { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - - /* Broadcom 4318 802.11b/g */ + /* Broadcom 4318 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4306 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - - /* Broadcom 4306 802.11a */ + /* Broadcom 4306 802.11a */ // { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4309 802.11a/b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 43XG 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - - /* required last entry */ - { 0, }, +#ifdef CONFIG_BCM947XX + /* SB bus on BCM947xx */ + { PCI_VENDOR_ID_BROADCOM, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +#endif + { 0 }, }; MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl); @@ -353,9 +342,8 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); } -static inline -u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp, - const int ofdm_modulation) +static u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp, + const int ofdm_modulation) { u8 rate; @@ -412,8 +400,7 @@ u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp, return rate; } -static inline -u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) +static u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) { switch (bitrate) { case IEEE80211_CCK_RATE_1MB: @@ -429,8 +416,7 @@ u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) return 0; } -static inline -u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) +static u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) { switch (bitrate) { case IEEE80211_OFDM_RATE_6MB: @@ -489,13 +475,12 @@ static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, //bcm43xx_printk_bitdump(raw, 4, 0, "PLCP"); } -void fastcall -bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie) +void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie) { const struct bcm43xx_phyinfo *phy = bcm->current_core->phy; const struct ieee80211_hdr_1addr *wireless_header = (const struct ieee80211_hdr_1addr *)fragment_data; @@ -606,9 +591,8 @@ void bcm43xx_macfilter_set(struct bcm43xx_private *bcm, bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); } -static inline -void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm, - u16 offset) +static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm, + u16 offset) { const u8 zero_addr[ETH_ALEN] = { 0 }; @@ -634,8 +618,7 @@ static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm) bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i))); } -static inline -void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) +static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) { /* slot_time is in usec. */ if (bcm->current_core->phy->type != BCM43xx_PHYTYPE_G) @@ -644,14 +627,12 @@ void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time); } -static inline -void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm) +static void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm) { bcm43xx_set_slot_time(bcm, 9); } -static inline -void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm) +static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm) { bcm43xx_set_slot_time(bcm, 20); } @@ -744,6 +725,8 @@ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *old static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) { + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; u32 radio_id; u16 manufact; u16 version; @@ -769,10 +752,10 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) version = (radio_id & 0x0FFFF000) >> 12; revision = (radio_id & 0xF0000000) >> 28; - dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n", + dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n", radio_id, manufact, version, revision); - switch (bcm->current_core->phy->type) { + switch (phy->type) { case BCM43xx_PHYTYPE_A: if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f)) goto err_unsupported_radio; @@ -787,25 +770,25 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) break; } - bcm->current_core->radio->manufact = manufact; - bcm->current_core->radio->version = version; - bcm->current_core->radio->revision = revision; + radio->manufact = manufact; + radio->version = version; + radio->revision = revision; /* Set default attenuation values. */ - bcm->current_core->radio->txpower[0] = 2; - bcm->current_core->radio->txpower[1] = 2; + radio->txpower[0] = 2; + radio->txpower[1] = 2; if (revision == 1) - bcm->current_core->radio->txpower[2] = 3; + radio->txpower[2] = 3; else - bcm->current_core->radio->txpower[2] = 0; + radio->txpower[2] = 0; if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) - bcm->current_core->radio->txpower_desired = bcm->sprom.maxpower_aphy; + radio->txpower_desired = bcm->sprom.maxpower_aphy; else bcm->current_core->radio->txpower_desired = bcm->sprom.maxpower_bgphy; /* Initialize the in-memory nrssi Lookup Table. */ for (i = 0; i < 64; i++) - bcm->current_core->radio->nrssi_lt[i] = i; + radio->nrssi_lt[i] = i; return 0; @@ -1155,6 +1138,7 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) */ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) { + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; unsigned int i, max_loop; u16 value = 0; u32 buffer[5] = { @@ -1165,7 +1149,7 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) 0x00000000, }; - switch (bcm->current_core->phy->type) { + switch (phy->type) { case BCM43xx_PHYTYPE_A: max_loop = 0x1E; buffer[0] = 0xCC010200; @@ -1187,7 +1171,7 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) bcm43xx_write16(bcm, 0x0568, 0x0000); bcm43xx_write16(bcm, 0x07C0, 0x0000); - bcm43xx_write16(bcm, 0x050C, ((bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0)); + bcm43xx_write16(bcm, 0x050C, ((phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0)); bcm43xx_write16(bcm, 0x0508, 0x0000); bcm43xx_write16(bcm, 0x050A, 0x0000); bcm43xx_write16(bcm, 0x054C, 0x0000); @@ -1324,25 +1308,6 @@ static void bcm43xx_clear_keys(struct bcm43xx_private *bcm) dprintk(KERN_INFO PFX "Keys cleared\n"); } -/* Puts the index of the current core into user supplied core variable. - * This function reads the value from the device. - * Almost always you don't want to call this, but use bcm->current_core - */ -static inline -int _get_current_core(struct bcm43xx_private *bcm, int *core) -{ - int err; - - err = bcm43xx_pci_read_config32(bcm, BCM43xx_REG_ACTIVE_CORE, core); - if (unlikely(err)) { - dprintk(KERN_ERR PFX "BCM43xx_REG_ACTIVE_CORE read failed!\n"); - return -ENODEV; - } - *core = (*core - 0x18000000) / 0x1000; - - return 0; -} - /* Lowlevel core-switch function. This is only to be used in * bcm43xx_switch_core() and bcm43xx_probe_cores() */ @@ -1350,63 +1315,57 @@ static int _switch_core(struct bcm43xx_private *bcm, int core) { int err; int attempts = 0; - int current_core = -1; + u32 current_core; assert(core >= 0); - - err = _get_current_core(bcm, ¤t_core); - if (unlikely(err)) - goto out; - - /* Write the computed value to the register. This doesn't always - succeed so we retry BCM43xx_SWITCH_CORE_MAX_RETRIES times */ - while (current_core != core) { - if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES)) { - err = -ENODEV; - printk(KERN_ERR PFX - "unable to switch to core %u, retried %i times\n", - core, attempts); - goto out; - } - err = bcm43xx_pci_write_config32(bcm, BCM43xx_REG_ACTIVE_CORE, + while (1) { + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE, (core * 0x1000) + 0x18000000); - if (unlikely(err)) { - dprintk(KERN_ERR PFX "BCM43xx_REG_ACTIVE_CORE write failed!\n"); - continue; - } - _get_current_core(bcm, ¤t_core); + if (unlikely(err)) + goto error; + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE, + ¤t_core); + if (unlikely(err)) + goto error; + current_core = (current_core - 0x18000000) / 0x1000; + if (current_core == core) + break; + + if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES)) + goto error; + udelay(10); + } #ifdef CONFIG_BCM947XX - if (bcm->pci_dev->bus->number == 0) - bcm->current_core_offset = 0x1000 * core; - else - bcm->current_core_offset = 0; + if (bcm->pci_dev->bus->number == 0) + bcm->current_core_offset = 0x1000 * core; + else + bcm->current_core_offset = 0; #endif - } - assert(err == 0); -out: - return err; + return 0; +error: + printk(KERN_ERR PFX "Failed to switch to core %d\n", core); + return -ENODEV; } int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core) { int err; - if (!new_core) + if (unlikely(!new_core)) return 0; - if (!(new_core->flags & BCM43xx_COREFLAG_AVAILABLE)) return -ENODEV; if (bcm->current_core == new_core) return 0; err = _switch_core(bcm, new_core->index); - if (!err) + if (likely(!err)) bcm->current_core = new_core; return err; } -static inline int bcm43xx_core_enabled(struct bcm43xx_private *bcm) +static int bcm43xx_core_enabled(struct bcm43xx_private *bcm) { u32 value; @@ -1609,7 +1568,7 @@ out: return err; } -static inline void handle_irq_transmit_status(struct bcm43xx_private *bcm) +static void handle_irq_transmit_status(struct bcm43xx_private *bcm) { u32 v0, v1; u16 tmp; @@ -1648,7 +1607,7 @@ static inline void handle_irq_transmit_status(struct bcm43xx_private *bcm) } } -static inline void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) +static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) { bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F); bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F); @@ -1672,7 +1631,7 @@ static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) bcm43xx_generate_noise_sample(bcm); } -static inline void handle_irq_noise(struct bcm43xx_private *bcm) +static void handle_irq_noise(struct bcm43xx_private *bcm) { struct bcm43xx_radioinfo *radio = bcm->current_core->radio; u16 tmp; @@ -1747,8 +1706,7 @@ generate_new: bcm43xx_generate_noise_sample(bcm); } -static inline -void handle_irq_ps(struct bcm43xx_private *bcm) +static void handle_irq_ps(struct bcm43xx_private *bcm) { if (bcm->ieee->iw_mode == IW_MODE_MASTER) { ///TODO: PS TBTT @@ -1761,8 +1719,7 @@ void handle_irq_ps(struct bcm43xx_private *bcm) //FIXME else set to false? } -static inline -void handle_irq_reg124(struct bcm43xx_private *bcm) +static void handle_irq_reg124(struct bcm43xx_private *bcm) { if (!bcm->reg124_set_0x4) return; @@ -1772,8 +1729,7 @@ void handle_irq_reg124(struct bcm43xx_private *bcm) //FIXME: reset reg124_set_0x4 to false? } -static inline -void handle_irq_pmq(struct bcm43xx_private *bcm) +static void handle_irq_pmq(struct bcm43xx_private *bcm) { u32 tmp; @@ -1829,8 +1785,7 @@ static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm, bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size); } -static inline -void handle_irq_beacon(struct bcm43xx_private *bcm) +static void handle_irq_beacon(struct bcm43xx_private *bcm) { u32 status; @@ -1992,9 +1947,8 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) #undef bcmirq_print_reasons -static inline -void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, - u32 reason, u32 mask) +static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, + u32 reason, u32 mask) { bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) & 0x0001dc00; @@ -2340,7 +2294,7 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) SA_SHIRQ, KBUILD_MODNAME, bcm); if (res) { printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); - return -EFAULT; + return -ENODEV; } bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff); bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402); @@ -2367,7 +2321,7 @@ static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) /* Switch to the core used to write the GPIO register. * This is either the ChipCommon, or the PCI core. */ -static inline int switch_to_gpio_core(struct bcm43xx_private *bcm) +static int switch_to_gpio_core(struct bcm43xx_private *bcm) { int err; @@ -2379,13 +2333,13 @@ static inline int switch_to_gpio_core(struct bcm43xx_private *bcm) err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); if (err == -ENODEV) { err = bcm43xx_switch_core(bcm, &bcm->core_pci); - if (err == -ENODEV) { + if (unlikely(err == -ENODEV)) { printk(KERN_ERR PFX "gpio error: " "Neither ChipCommon nor PCI core available!\n"); return -ENODEV; - } else if (err != 0) + } else if (unlikely(err != 0)) return -ENODEV; - } else if (err != 0) + } else if (unlikely(err != 0)) return -ENODEV; return 0; @@ -2691,40 +2645,30 @@ err_release_fw: * http://bcm-specs.sipsolutions.net/ValidateChipAccess */ static int bcm43xx_validate_chip(struct bcm43xx_private *bcm) { - int err = -ENODEV; u32 value; u32 shm_backup; shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000); bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA); - if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA) { - printk(KERN_ERR PFX "Error: SHM mismatch (1) validating chip\n"); - goto out; - } - + if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA) + goto error; bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55); - if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55) { - printk(KERN_ERR PFX "Error: SHM mismatch (2) validating chip\n"); - goto out; - } - + if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55) + goto error; bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup); value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - if ((value | 0x80000000) != 0x80000400) { - printk(KERN_ERR PFX "Error: Bad Status Bitfield while validating chip\n"); - goto out; - } + if ((value | 0x80000000) != 0x80000400) + goto error; value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (value != 0x00000000) { - printk(KERN_ERR PFX "Error: Bad interrupt reason code while validating chip\n"); - goto out; - } + if (value != 0x00000000) + goto error; - err = 0; -out: - return err; + return 0; +error: + printk(KERN_ERR PFX "Failed to validate the chipaccess\n"); + return -ENODEV; } static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) @@ -3172,9 +3116,9 @@ static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm) bcm43xx_pctl_set_crystal(bcm, 0); } -static inline void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm, - u32 address, - u32 data) +static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm, + u32 address, + u32 data) { bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address); bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data); @@ -3523,6 +3467,7 @@ static void bcm43xx_detach_board(struct bcm43xx_private *bcm) static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) { + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; u16 value; u8 phy_version; u8 phy_type; @@ -3578,15 +3523,15 @@ static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) phy_rev); } - bcm->current_core->phy->version = phy_version; - bcm->current_core->phy->type = phy_type; - bcm->current_core->phy->rev = phy_rev; + phy->version = phy_version; + phy->type = phy_type; + phy->rev = phy_rev; if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) { p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT, GFP_KERNEL); if (!p) return -ENOMEM; - bcm->current_core->phy->_lo_pairs = p; + phy->_lo_pairs = p; } return 0; @@ -3757,9 +3702,9 @@ err_pci_disable: goto out; } -static inline -s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, u8 in_rssi, - int ofdm, int adjust_2053, int adjust_2050) +static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, + u8 in_rssi, int ofdm, + int adjust_2053, int adjust_2050) { s32 tmp; @@ -3816,8 +3761,8 @@ s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, u8 in_rssi, return (s8)tmp; } -static inline -s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, u8 in_rssi) +static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, + u8 in_rssi) { s8 ret; @@ -3843,9 +3788,9 @@ int bcm43xx_rx_packet(struct bcm43xx_private *bcm, return 0; } -int fastcall bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr) +int bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr) { struct bcm43xx_plcp_hdr4 *plcp; struct ieee80211_rx_stats stats; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 1d3eddd314..298e24b4ab 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -111,12 +111,12 @@ struct bcm43xx_txhdr { struct sk_buff; -void FASTCALL(bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - const unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie)); +void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + const unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie); /* RX header as received from the hardware. */ struct bcm43xx_rxhdr { @@ -244,9 +244,9 @@ int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf); -int FASTCALL(bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr)); +int bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr); void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, int iw_mode); -- cgit v1.2.2 From ea0922b067a0863f9a4198740651fd47a22af7f1 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Feb 2006 14:09:20 +0100 Subject: [PATCH] bcm43xx: Move sprom lowlevel reading/writing to its own functions. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 93 ++++++++++++++++++++++++----- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 3 + drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 66 ++------------------ 3 files changed, 86 insertions(+), 76 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 3443bd3c23..bcbd009a53 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -916,13 +916,84 @@ u8 bcm43xx_sprom_crc(const u16 *sprom) return crc; } - -static int bcm43xx_read_sprom(struct bcm43xx_private *bcm) +int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom) { int i; + u8 crc, expected_crc; + + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) + sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); + /* CRC-8 check. */ + crc = bcm43xx_sprom_crc(sprom); + expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; + if (crc != expected_crc) { + printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum " + "(0x%02X, expected: 0x%02X)\n", + crc, expected_crc); + return -EINVAL; + } + + return 0; +} + +int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom) +{ + int i, err; + u8 crc, expected_crc; + u32 spromctl; + + /* CRC-8 validation of the input data. */ + crc = bcm43xx_sprom_crc(sprom); + expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; + if (crc != expected_crc) { + printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n"); + return -EINVAL; + } + + printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); + err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl); + if (err) + goto err_ctlreg; + spromctl |= 0x10; /* SPROM WRITE enable. */ + bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); + if (err) + goto err_ctlreg; + /* We must burn lots of CPU cycles here, but that does not + * really matter as one does not write the SPROM every other minute... + */ + printk(KERN_INFO PFX "[ 0%%"); + mdelay(500); + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { + if (i == 16) + printk("25%%"); + else if (i == 32) + printk("50%%"); + else if (i == 48) + printk("75%%"); + else if (i % 2) + printk("."); + bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); + mdelay(20); + } + spromctl &= ~0x10; /* SPROM WRITE enable. */ + bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); + if (err) + goto err_ctlreg; + mdelay(500); + printk("100%% ]\n"); + printk(KERN_INFO PFX "SPROM written.\n"); + bcm43xx_controller_restart(bcm, "SPROM update"); + + return 0; +err_ctlreg: + printk(KERN_ERR PFX "Could not access SPROM control register.\n"); + return -ENODEV; +} + +static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) +{ u16 value; u16 *sprom; - u8 crc, expected_crc; #ifdef CONFIG_BCM947XX char *c; #endif @@ -930,7 +1001,7 @@ static int bcm43xx_read_sprom(struct bcm43xx_private *bcm) sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16), GFP_KERNEL); if (!sprom) { - printk(KERN_ERR PFX "read_sprom OOM\n"); + printk(KERN_ERR PFX "sprom_extract OOM\n"); return -ENOMEM; } #ifdef CONFIG_BCM947XX @@ -953,17 +1024,7 @@ static int bcm43xx_read_sprom(struct bcm43xx_private *bcm) sprom[BCM43xx_SPROM_BOARDREV] = atoi(nvram_get("boardrev")); #else - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) - sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); - - /* CRC-8 check. */ - crc = bcm43xx_sprom_crc(sprom); - expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; - if (crc != expected_crc) { - printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum " - "(0x%02X, expected: 0x%02X)\n", - crc, expected_crc); - } + bcm43xx_sprom_read(bcm, sprom); #endif /* boardflags2 */ @@ -3632,7 +3693,7 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) goto err_chipset_detach; } - err = bcm43xx_read_sprom(bcm); + err = bcm43xx_sprom_extract(bcm); if (err) goto err_chipset_detach; err = bcm43xx_leds_init(bcm); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 298e24b4ab..0c4bd08568 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -280,4 +280,7 @@ u8 bcm43xx_sprom_crc(const u16 *sprom); void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); +int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom); +int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom); + #endif /* BCM43xx_MAIN_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 4c972cdc0a..df37d28996 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -782,7 +782,6 @@ static int hex2sprom(u16 *sprom, const char *dump, unsigned int len) char tmp[5] = { 0 }; int cnt = 0; unsigned long parsed; - u8 crc, expected_crc; if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2) return -EINVAL; @@ -793,13 +792,6 @@ static int hex2sprom(u16 *sprom, const char *dump, unsigned int len) sprom[cnt++] = swab16((u16)parsed); } - crc = bcm43xx_sprom_crc(sprom); - expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; - if (crc != expected_crc) { - printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n"); - return -EINVAL; - } - return 0; } @@ -809,7 +801,7 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err = -EPERM, i; + int err = -EPERM; u16 *sprom; unsigned long flags; @@ -828,13 +820,10 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev, spin_unlock_irqrestore(&bcm->lock, flags); goto out_kfree; } - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) - sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); + err = bcm43xx_sprom_read(bcm, sprom); spin_unlock_irqrestore(&bcm->lock, flags); - - data->data.length = sprom2hex(sprom, extra); - - err = 0; + if (!err) + data->data.length = sprom2hex(sprom, extra); out_kfree: kfree(sprom); out: @@ -852,8 +841,6 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, unsigned long flags; char *input; unsigned int len; - u32 spromctl; - int i; if (!capable(CAP_SYS_RAWIO)) goto out; @@ -878,50 +865,9 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, spin_lock_irqsave(&bcm->lock, flags); err = -ENODEV; - if (!bcm->initialized) { - spin_unlock_irqrestore(&bcm->lock, flags); - goto out_kfree; - } - - printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl); - if (err) { - printk(KERN_ERR PFX "Could not access SPROM control register.\n"); - goto out_unlock; - } - spromctl |= 0x10; /* SPROM WRITE enable. */ - bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); - if (err) { - printk(KERN_ERR PFX "Could not access SPROM control register.\n"); - goto out_unlock; - } - /* We must burn lots of CPU cycles here, but that does not - * really matter as one does not write the SPROM every other minute... - */ - printk(KERN_INFO PFX "[ 0%%"); - mdelay(500); - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { - if (i == 16) - printk("25%%"); - else if (i == 32) - printk("50%%"); - else if (i == 48) - printk("75%%"); - else if (i % 2) - printk("."); - bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); - mdelay(20); - } - spromctl &= ~0x10; /* SPROM WRITE enable. */ - bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); - if (err) { - printk(KERN_ERR PFX "Could not access SPROM control register.\n"); + if (!bcm->initialized) goto out_unlock; - } - mdelay(500); - printk("100%% ]\n"); - printk(KERN_INFO PFX "SPROM written.\n"); - err = 0; + err = bcm43xx_sprom_write(bcm, sprom); out_unlock: spin_unlock_irqrestore(&bcm->lock, flags); out_kfree: -- cgit v1.2.2 From ad3f086c49aa682e493c935cda76f3850ee4a80e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Feb 2006 14:12:22 +0100 Subject: [PATCH] bcm43xx: make bcm43xx_sprom_crc() static. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index bcbd009a53..b4767e42e8 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -901,7 +901,7 @@ static inline u8 bcm43xx_crc8(u8 crc, u8 data) return t[crc ^ data]; } -u8 bcm43xx_sprom_crc(const u16 *sprom) +static u8 bcm43xx_sprom_crc(const u16 *sprom) { int word; u8 crc = 0xFF; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 0c4bd08568..0a22e83391 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -276,8 +276,6 @@ int bcm43xx_pci_write_config_32(struct pci_dev *pdev, int offset, u32 val); void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); void bcm43xx_mac_enable(struct bcm43xx_private *bcm); -u8 bcm43xx_sprom_crc(const u16 *sprom); - void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom); -- cgit v1.2.2 From 10d8dd88dcc2c8ebe8ac7dcf75a2da7c9f9ee0f3 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Feb 2006 22:08:48 +0100 Subject: [PATCH] bcm43xx: split the channel helper functions, so that they can be used without a valid running core. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 80 ++++++++++++++++++----------- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 12 +++-- 3 files changed, 59 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index b4767e42e8..6195c2a151 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1169,7 +1169,7 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) if (have_a) { for (i = 0, channel = 0; channel < 201; channel++) { chan = &geo.a[i++]; - chan->freq = bcm43xx_channel_to_freq(bcm, channel); + chan->freq = bcm43xx_channel_to_freq_a(channel); chan->channel = channel; } geo.a_channels = i; @@ -1177,7 +1177,7 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) if (have_bg) { for (i = 0, channel = 1; channel < 15; channel++) { chan = &geo.bg[i++]; - chan->freq = bcm43xx_channel_to_freq(bcm, channel); + chan->freq = bcm43xx_channel_to_freq_bg(channel); chan->channel = channel; } geo.bg_channels = i; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 0a22e83391..7d696d257f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -187,58 +187,78 @@ struct bcm43xx_xmitstatus_queue { /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ static inline -u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm, - int freq) +u8 bcm43xx_freq_to_channel_a(int freq) +{ + return ((freq - 5000) / 5); +} +static inline +u8 bcm43xx_freq_to_channel_bg(int freq) { u8 channel; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { - channel = (freq - 5000) / 5; - } else { - if (freq == 2484) - channel = 14; - else - channel = (freq - 2407) / 5; - } + if (freq == 2484) + channel = 14; + else + channel = (freq - 2407) / 5; return channel; } +static inline +u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm, + int freq) +{ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + return bcm43xx_freq_to_channel_a(freq); + return bcm43xx_freq_to_channel_bg(freq); +} /* Lightweight function to convert a channel number to a frequency (in Mhz). */ static inline -int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm, - u8 channel) +int bcm43xx_channel_to_freq_a(u8 channel) +{ + return (5000 + (5 * channel)); +} +static inline +int bcm43xx_channel_to_freq_bg(u8 channel) { int freq; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { - freq = 5000 + (5 * channel); - } else { - if (channel == 14) - freq = 2484; - else - freq = 2407 + (5 * channel); - } + if (channel == 14) + freq = 2484; + else + freq = 2407 + (5 * channel); return freq; } +static inline +int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm, + u8 channel) +{ + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + return bcm43xx_channel_to_freq_a(channel); + return bcm43xx_channel_to_freq_bg(channel); +} /* Lightweight function to check if a channel number is valid. * Note that this does _NOT_ check for geographical restrictions! */ static inline +int bcm43xx_is_valid_channel_a(u8 channel) +{ + return (channel <= 200); +} +static inline +int bcm43xx_is_valid_channel_bg(u8 channel) +{ + return (channel >= 1 && channel <= 14); +} +static inline int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, - u8 channel) + u8 channel) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { - if (channel <= 200) - return 1; - } else { - if (channel >= 1 && channel <= 14) - return 1; - } - - return 0; + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + return bcm43xx_is_valid_channel_a(channel); + return bcm43xx_is_valid_channel_bg(channel); } void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index df37d28996..aa2d9930c4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -111,8 +111,9 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, unsigned long flags; u8 channel; int freq; - int err = 0; + int err = -EINVAL; + spin_lock_irqsave(&bcm->lock, flags); if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { channel = data->freq.m; freq = bcm43xx_channel_to_freq(bcm, channel); @@ -121,16 +122,17 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, freq = data->freq.m; } if (!bcm43xx_is_valid_channel(bcm, channel)) - return -EINVAL; - - spin_lock_irqsave(&bcm->lock, flags); + goto out_unlock; if (bcm->initialized) { //ieee80211softmac_disassoc(softmac, $REASON); bcm43xx_mac_suspend(bcm); err = bcm43xx_radio_selectchannel(bcm, channel, 0); bcm43xx_mac_enable(bcm); - } else + } else { bcm->current_core->radio->initial_channel = channel; + err = 0; + } +out_unlock: spin_unlock_irqrestore(&bcm->lock, flags); return err; -- cgit v1.2.2 From 26533e7e292075df1daf94965a7f3f0d91bd08a8 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Feb 2006 22:25:09 +0100 Subject: [PATCH] bcm43xx: remove old unused struct. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 7d696d257f..d460393ed3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -179,11 +179,6 @@ struct bcm43xx_xmitstatus { //TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40 //TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80 -struct bcm43xx_xmitstatus_queue { - struct list_head list; - struct bcm43xx_hwxmitstatus status; -}; - /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ static inline -- cgit v1.2.2 From c4c3beb7d70ae9d1fe97b7b49bc5a10ad26c2b01 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 20 Feb 2006 22:48:55 +0100 Subject: [PATCH] bcm43xx: Fix Kconfig typo (transfer mode default) Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig index 1d677c15b2..418465600a 100644 --- a/drivers/net/wireless/bcm43xx/Kconfig +++ b/drivers/net/wireless/bcm43xx/Kconfig @@ -23,7 +23,7 @@ config BCM43XX_PIO choice prompt "BCM43xx data transfer mode" depends on BCM43XX - default BCM43XX_DMA_AND_PIO + default BCM43XX_DMA_AND_PIO_MODE config BCM43XX_DMA_AND_PIO_MODE bool "DMA + PIO" -- cgit v1.2.2 From bf7b876043e6e1390b1234d740f4fd9af20b3b9e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 21 Feb 2006 17:58:18 +0100 Subject: [PATCH] bcm43xx: Workaround init_board vs IRQ race. The proper fix for this is to move IRQ enabling to the end of init_board. But this is nontrivial and needs to be done with care. Stay with this cheap workaround for now. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 6195c2a151..57306a6584 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2079,12 +2079,19 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re bcm43xx_interrupt_ack(bcm, reason, mask); - /* disable all IRQs. They are enabled again in the bottom half. */ - bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - - /* save the reason code and call our bottom half. */ - bcm->irq_reason = reason; - tasklet_schedule(&bcm->isr_tasklet); + /* Only accept IRQs, if we are initialized properly. + * This avoids an RX race while initializing. + * We should probably not enable IRQs before we are initialized + * completely, but some careful work is needed to fix this. I think it + * is best to stay with this cheap workaround for now... . + */ + if (likely(bcm->initialized)) { + /* disable all IRQs. They are enabled again in the bottom half. */ + bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + /* save the reason code and call our bottom half. */ + bcm->irq_reason = reason; + tasklet_schedule(&bcm->isr_tasklet); + } spin_unlock(&bcm->lock); -- cgit v1.2.2 From cad2b31a76763d06048fb23a17b062acd5d46639 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 21 Feb 2006 18:08:55 +0100 Subject: [PATCH] bcm43xx: move initialized = 1 to the end of init_board. Note that the periodic work has to be started with initialized==1 Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 57306a6584..4a7d88d282 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3484,15 +3484,17 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); - spin_lock_irqsave(&bcm->lock, flags); - bcm->initialized = 1; - spin_unlock_irqrestore(&bcm->lock, flags); - if (bcm->current_core->radio->initial_channel != 0xFF) { bcm43xx_mac_suspend(bcm); bcm43xx_radio_selectchannel(bcm, bcm->current_core->radio->initial_channel, 0); bcm43xx_mac_enable(bcm); } + + /* Initialization of the board is done. Flag it as such. */ + spin_lock_irqsave(&bcm->lock, flags); + bcm->initialized = 1; + spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_periodic_tasks_setup(bcm); assert(err == 0); -- cgit v1.2.2 From 1d1a73ccdc618168f2a5c962aab250605c93e517 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 21 Feb 2006 18:19:59 +0100 Subject: [PATCH] bcm43xx: add assert(bcm->initialized) to periodic_tasks_setup(). Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 4a7d88d282..899c06fe0b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3366,6 +3366,7 @@ static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) { struct timer_list *timer = &(bcm->periodic_tasks); + assert(bcm->initialized); setup_timer(timer, bcm43xx_periodic_task_handler, (unsigned long)bcm); -- cgit v1.2.2 From f398f02d12cdc372e16c5e86246b10acf7211abc Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 23 Feb 2006 21:15:39 +0100 Subject: [PATCH] bcm43xx: Move TX/RX related functions to its own file. Add basic RTS/CTS code. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Makefile | 1 + drivers/net/wireless/bcm43xx/bcm43xx.h | 23 +- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 1 + drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 1 + drivers/net/wireless/bcm43xx/bcm43xx_main.c | 430 +----------------- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 131 ------ drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 1 + drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 579 +++++++++++++++++++++++++ drivers/net/wireless/bcm43xx/bcm43xx_xmit.h | 156 +++++++ 9 files changed, 746 insertions(+), 577 deletions(-) create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_xmit.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_xmit.h (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile index c87c1525b3..2962b5f9e3 100644 --- a/drivers/net/wireless/bcm43xx/Makefile +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -8,4 +8,5 @@ bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \ bcm43xx_radio.o bcm43xx_phy.o \ bcm43xx_power.o bcm43xx_wx.o \ bcm43xx_leds.o bcm43xx_ethtool.o \ + bcm43xx_xmit.o \ $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 848717513b..21c75cae14 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -314,23 +314,6 @@ /* Initial default iw_mode */ #define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA -/* Values/Masks for the device TX header */ -#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001 -#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008 -#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020 -#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100 -#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800 - -#define BCM43xx_TXHDRCTL_OFDM 0x0001 -#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010 -#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030 -#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8 - -#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0 -#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4 -#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003 -#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0 - /* Bus type PCI. */ #define BCM43xx_BUSTYPE_PCI 0 /* Bus type Silicone Backplane Bus. */ @@ -952,4 +935,10 @@ int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 valu __value; \ }) +/** Helpers to print MAC addresses. */ +#define BCM43xx_MACFMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define BCM43xx_MACARG(x) ((u8*)(x))[0], ((u8*)(x))[1], \ + ((u8*)(x))[2], ((u8*)(x))[3], \ + ((u8*)(x))[4], ((u8*)(x))[5] + #endif /* BCM43xx_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index 5a7dc43cd6..0bae0be4be 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -37,6 +37,7 @@ #include "bcm43xx_debugfs.h" #include "bcm43xx_dma.h" #include "bcm43xx_pio.h" +#include "bcm43xx_xmit.h" #define REALLY_BIG_BUFFER_SIZE (1024*256) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index af5c27f9bf..e20fbaf29e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -32,6 +32,7 @@ #include "bcm43xx_main.h" #include "bcm43xx_debugfs.h" #include "bcm43xx_power.h" +#include "bcm43xx_xmit.h" #include #include diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 899c06fe0b..f1ac9940f1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -50,6 +50,7 @@ #include "bcm43xx_power.h" #include "bcm43xx_wx.h" #include "bcm43xx_ethtool.h" +#include "bcm43xx_xmit.h" MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); @@ -342,234 +343,6 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); } -static u8 bcm43xx_plcp_get_bitrate(struct bcm43xx_plcp_hdr4 *plcp, - const int ofdm_modulation) -{ - u8 rate; - - if (ofdm_modulation) { - switch (plcp->raw[0] & 0xF) { - case 0xB: - rate = IEEE80211_OFDM_RATE_6MB; - break; - case 0xF: - rate = IEEE80211_OFDM_RATE_9MB; - break; - case 0xA: - rate = IEEE80211_OFDM_RATE_12MB; - break; - case 0xE: - rate = IEEE80211_OFDM_RATE_18MB; - break; - case 0x9: - rate = IEEE80211_OFDM_RATE_24MB; - break; - case 0xD: - rate = IEEE80211_OFDM_RATE_36MB; - break; - case 0x8: - rate = IEEE80211_OFDM_RATE_48MB; - break; - case 0xC: - rate = IEEE80211_OFDM_RATE_54MB; - break; - default: - rate = 0; - assert(0); - } - } else { - switch (plcp->raw[0]) { - case 0x0A: - rate = IEEE80211_CCK_RATE_1MB; - break; - case 0x14: - rate = IEEE80211_CCK_RATE_2MB; - break; - case 0x37: - rate = IEEE80211_CCK_RATE_5MB; - break; - case 0x6E: - rate = IEEE80211_CCK_RATE_11MB; - break; - default: - rate = 0; - assert(0); - } - } - - return rate; -} - -static u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) -{ - switch (bitrate) { - case IEEE80211_CCK_RATE_1MB: - return 0x0A; - case IEEE80211_CCK_RATE_2MB: - return 0x14; - case IEEE80211_CCK_RATE_5MB: - return 0x37; - case IEEE80211_CCK_RATE_11MB: - return 0x6E; - } - assert(0); - return 0; -} - -static u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) -{ - switch (bitrate) { - case IEEE80211_OFDM_RATE_6MB: - return 0xB; - case IEEE80211_OFDM_RATE_9MB: - return 0xF; - case IEEE80211_OFDM_RATE_12MB: - return 0xA; - case IEEE80211_OFDM_RATE_18MB: - return 0xE; - case IEEE80211_OFDM_RATE_24MB: - return 0x9; - case IEEE80211_OFDM_RATE_36MB: - return 0xD; - case IEEE80211_OFDM_RATE_48MB: - return 0x8; - case IEEE80211_OFDM_RATE_54MB: - return 0xC; - } - assert(0); - return 0; -} - -static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, - u16 octets, const u8 bitrate, - const int ofdm_modulation) -{ - __le32 *data = &(plcp->data); - __u8 *raw = plcp->raw; - - /* Account for hardware-appended FCS. */ - octets += IEEE80211_FCS_LEN; - - if (ofdm_modulation) { - *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate); - assert(!(octets & 0xF000)); - *data |= (octets << 5); - *data = cpu_to_le32(*data); - } else { - u32 plen; - - plen = octets * 16 / bitrate; - if ((octets * 16 % bitrate) > 0) { - plen++; - if ((bitrate == IEEE80211_CCK_RATE_11MB) - && ((octets * 8 % 11) < 4)) { - raw[1] = 0x84; - } else - raw[1] = 0x04; - } else - raw[1] = 0x04; - *data |= cpu_to_le32(plen << 16); - raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate); - } - -//bcm43xx_printk_bitdump(raw, 4, 0, "PLCP"); -} - -void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie) -{ - const struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - const struct ieee80211_hdr_1addr *wireless_header = (const struct ieee80211_hdr_1addr *)fragment_data; - const struct ieee80211_security *secinfo = &bcm->ieee->sec; - u8 bitrate; - int ofdm_modulation; - u8 fallback_bitrate; - int fallback_ofdm_modulation; - u16 tmp; - u16 encrypt_frame; - - /* Now construct the TX header. */ - memset(txhdr, 0, sizeof(*txhdr)); - - //TODO: Some RTS/CTS stuff has to be done. - //TODO: Encryption stuff. - //TODO: others? - - bitrate = bcm->softmac->txrates.default_rate; - ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); - fallback_bitrate = bcm->softmac->txrates.default_fallback; - fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); - - /* Set Frame Control from 80211 header. */ - txhdr->frame_control = wireless_header->frame_ctl; - /* Copy address1 from 80211 header. */ - memcpy(txhdr->mac1, wireless_header->addr1, 6); - /* Set the fallback duration ID. */ - //FIXME: We use the original durid for now. - txhdr->fallback_dur_id = wireless_header->duration_id; - - /* Set the cookie (used as driver internal ID for the frame) */ - txhdr->cookie = cpu_to_le16(cookie); - - encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED; - if (encrypt_frame && !bcm->ieee->host_encrypt) { - const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header; - if (fragment_len <= sizeof(struct ieee80211_hdr_3addr)+4) { - dprintkl(KERN_ERR PFX "invalid packet with PROTECTED" - "flag set discarded"); - return; - } - memcpy(txhdr->wep_iv, hdr->payload, 4); - /* Hardware appends ICV. */ - fragment_len += 4; - } - - /* Generate the PLCP header and the fallback PLCP header. */ - bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp), - fragment_len, - bitrate, ofdm_modulation); - bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, fragment_len, - fallback_bitrate, fallback_ofdm_modulation); - - /* Set the CONTROL field */ - tmp = 0; - if (ofdm_modulation) - tmp |= BCM43xx_TXHDRCTL_OFDM; - if (bcm->short_preamble) //FIXME: could be the other way around, please test - tmp |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE; - tmp |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT) - & BCM43xx_TXHDRCTL_ANTENNADIV_MASK; - txhdr->control = cpu_to_le16(tmp); - - /* Set the FLAGS field */ - tmp = 0; - if (!is_multicast_ether_addr(wireless_header->addr1) && - !is_broadcast_ether_addr(wireless_header->addr1)) - tmp |= BCM43xx_TXHDRFLAG_EXPECTACK; - if (1 /* FIXME: PS poll?? */) - tmp |= 0x10; // FIXME: unknown meaning. - if (fallback_ofdm_modulation) - tmp |= BCM43xx_TXHDRFLAG_FALLBACKOFDM; - if (is_first_fragment) - tmp |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT; - txhdr->flags = cpu_to_le16(tmp); - - /* Set WSEC/RATE field */ - if (encrypt_frame && !bcm->ieee->host_encrypt) { - tmp = (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT) - & BCM43xx_TXHDR_WSEC_ALGO_MASK; - tmp |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT) - & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK; - txhdr->wsec_rate = cpu_to_le16(tmp); - } - -//bcm43xx_printk_bitdump((const unsigned char *)txhdr, sizeof(*txhdr), 1, "TX header"); -} - static void bcm43xx_macfilter_set(struct bcm43xx_private *bcm, u16 offset, @@ -3773,207 +3546,6 @@ err_pci_disable: goto out; } -static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, - u8 in_rssi, int ofdm, - int adjust_2053, int adjust_2050) -{ - s32 tmp; - - switch (bcm->current_core->radio->version) { - case 0x2050: - if (ofdm) { - tmp = in_rssi; - if (tmp > 127) - tmp -= 256; - tmp *= 73; - tmp /= 64; - if (adjust_2050) - tmp += 25; - else - tmp -= 3; - } else { - if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { - if (in_rssi > 63) - in_rssi = 63; - tmp = bcm->current_core->radio->nrssi_lt[in_rssi]; - tmp = 31 - tmp; - tmp *= -131; - tmp /= 128; - tmp -= 57; - } else { - tmp = in_rssi; - tmp = 31 - tmp; - tmp *= -149; - tmp /= 128; - tmp -= 68; - } - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && - adjust_2050) - tmp += 25; - } - break; - case 0x2060: - if (in_rssi > 127) - tmp = in_rssi - 256; - else - tmp = in_rssi; - break; - default: - tmp = in_rssi; - tmp -= 11; - tmp *= 103; - tmp /= 64; - if (adjust_2053) - tmp -= 109; - else - tmp -= 83; - } - - return (s8)tmp; -} - -static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, - u8 in_rssi) -{ - s8 ret; - - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { - //TODO: Incomplete specs. - ret = 0; - } else - ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1); - - return ret; -} - -static inline -int bcm43xx_rx_packet(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct ieee80211_rx_stats *stats) -{ - int err; - - err = ieee80211_rx(bcm->ieee, skb, stats); - if (unlikely(err == 0)) - return -EINVAL; - return 0; -} - -int bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr) -{ - struct bcm43xx_plcp_hdr4 *plcp; - struct ieee80211_rx_stats stats; - struct ieee80211_hdr_4addr *wlhdr; - u16 frame_ctl; - int is_packet_for_us = 0; - int err = -EINVAL; - const u16 rxflags1 = le16_to_cpu(rxhdr->flags1); - const u16 rxflags2 = le16_to_cpu(rxhdr->flags2); - const u16 rxflags3 = le16_to_cpu(rxhdr->flags3); - const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM); - - if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) { - plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2); - /* Skip two unknown bytes and the PLCP header. */ - skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6)); - } else { - plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data); - /* Skip the PLCP header. */ - skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6)); - } - /* The SKB contains the PAYLOAD (wireless header + data) - * at this point. The FCS at the end is stripped. - */ - - memset(&stats, 0, sizeof(stats)); - stats.mac_time = le16_to_cpu(rxhdr->mactime); - stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, - !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), - !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); - stats.signal = rxhdr->signal_quality; //FIXME -//TODO stats.noise = - stats.rate = bcm43xx_plcp_get_bitrate(plcp, is_ofdm); -//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate); - stats.received_channel = bcm->current_core->radio->channel; -//TODO stats.control = - stats.mask = IEEE80211_STATMASK_SIGNAL | -//TODO IEEE80211_STATMASK_NOISE | - IEEE80211_STATMASK_RATE | - IEEE80211_STATMASK_RSSI; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) - stats.freq = IEEE80211_52GHZ_BAND; - else - stats.freq = IEEE80211_24GHZ_BAND; - stats.len = skb->len; - - bcm->stats.last_rx = jiffies; - if (bcm->ieee->iw_mode == IW_MODE_MONITOR) - return bcm43xx_rx_packet(bcm, skb, &stats); - - wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); - - switch (bcm->ieee->iw_mode) { - case IW_MODE_ADHOC: - if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || - memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || - is_broadcast_ether_addr(wlhdr->addr1) || - is_multicast_ether_addr(wlhdr->addr1) || - bcm->net_dev->flags & IFF_PROMISC) - is_packet_for_us = 1; - break; - case IW_MODE_INFRA: - default: - /* When receiving multicast or broadcast packets, filter out - the packets we send ourself; we shouldn't see those */ - if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || - memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || - (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) && - (is_broadcast_ether_addr(wlhdr->addr1) || - is_multicast_ether_addr(wlhdr->addr1) || - bcm->net_dev->flags & IFF_PROMISC))) - is_packet_for_us = 1; - break; - } - - frame_ctl = le16_to_cpu(wlhdr->frame_ctl); - if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { - frame_ctl &= ~IEEE80211_FCTL_PROTECTED; - wlhdr->frame_ctl = cpu_to_le16(frame_ctl); - /* trim IV and ICV */ - /* FIXME: this must be done only for WEP encrypted packets */ - if (skb->len < 32) { - dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag " - "set and length < 32)\n"); - return -EINVAL; - } else { - memmove(skb->data + 4, skb->data, 24); - skb_pull(skb, 4); - skb_trim(skb, skb->len - 4); - stats.len -= 8; - } - wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); - } - - switch (WLAN_FC_GET_TYPE(frame_ctl)) { - case IEEE80211_FTYPE_MGMT: - ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); - break; - case IEEE80211_FTYPE_DATA: - if (is_packet_for_us) - err = bcm43xx_rx_packet(bcm, skb, &stats); - break; - case IEEE80211_FTYPE_CTL: - break; - default: - assert(0); - return -EINVAL; - } - - return err; -} - /* Do the Hardware IO operations to send the txb */ static inline int bcm43xx_tx(struct bcm43xx_private *bcm, struct ieee80211_txb *txb) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index d460393ed3..086136c3d0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -52,134 +52,12 @@ static inline void e_aton(char *str, char *dest) } #endif - -#define _bcm43xx_declare_plcp_hdr(size) \ - struct bcm43xx_plcp_hdr##size { \ - union { \ - __le32 data; \ - __u8 raw[size]; \ - } __attribute__((__packed__)); \ - } __attribute__((__packed__)) - -/* struct bcm43xx_plcp_hdr4 */ -_bcm43xx_declare_plcp_hdr(4); -/* struct bcm430c_plcp_hdr6 */ -_bcm43xx_declare_plcp_hdr(6); - -#undef _bcm43xx_declare_plcp_hdr - - #define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] #define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) /* Magic helper macro to pad structures. Ignore those above. It's magic. */ #define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) -/* Device specific TX header. To be prepended to TX frames. */ -struct bcm43xx_txhdr { - union { - struct { - u16 flags; - u16 wsec_rate; - u16 frame_control; - u16 unknown_zeroed_0; - u16 control; - unsigned char wep_iv[10]; - unsigned char unknown_wsec_tkip_data[3]; //FIXME - PAD_BYTES(3); - unsigned char mac1[6]; - u16 unknown_zeroed_1; - struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp; - u16 rts_cts_dur_fallback; - struct bcm43xx_plcp_hdr4 fallback_plcp; - u16 fallback_dur_id; - PAD_BYTES(2); - u16 cookie; - u16 unknown_scb_stuff; //FIXME - struct bcm43xx_plcp_hdr6 rts_cts_plcp; - u16 rts_cts_frame_type; - u16 rts_cts_dur; - unsigned char rts_cts_mac1[6]; - unsigned char rts_cts_mac2[6]; - PAD_BYTES(2); - struct bcm43xx_plcp_hdr6 plcp; - } __attribute__((__packed__)); - - unsigned char raw[82]; - } __attribute__((__packed__)); -} __attribute__((__packed__)); - -struct sk_buff; - -void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - const unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie); - -/* RX header as received from the hardware. */ -struct bcm43xx_rxhdr { - /* Frame Length. Must be generated explicitely in PIO mode. */ - __le16 frame_length; - PAD_BYTES(2); - /* Flags field 1 */ - __le16 flags1; - u8 rssi; - u8 signal_quality; - PAD_BYTES(2); - /* Flags field 3 */ - __le16 flags3; - /* Flags field 2 */ - __le16 flags2; - /* Lower 16bits of the TSF at the time the frame started. */ - __le16 mactime; - PAD_BYTES(14); -} __attribute__((__packed__)); - -#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0) -/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */ -#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7) -#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14) - -#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0) -#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2) -/*FIXME: WEP related flags */ - -#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10) - -/* Transmit Status as received from the hardware. */ -struct bcm43xx_hwxmitstatus { - PAD_BYTES(4); - __le16 cookie; - u8 flags; - u8 cnt1:4, - cnt2:4; - PAD_BYTES(2); - __le16 seq; - __le16 unknown; //FIXME -} __attribute__((__packed__)); - -/* Transmit Status in CPU byteorder. */ -struct bcm43xx_xmitstatus { - u16 cookie; - u8 flags; - u8 cnt1:4, - cnt2:4; - u16 seq; - u16 unknown; //FIXME -}; - -#define BCM43xx_TXSTAT_FLAG_ACK 0x01 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x02 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x04 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x08 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x10 -#define BCM43xx_TXSTAT_FLAG_IGNORE 0x20 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40 -//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80 - - /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ static inline u8 bcm43xx_freq_to_channel_a(int freq) @@ -259,10 +137,6 @@ int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf); -int bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr); - void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, int iw_mode); @@ -283,11 +157,6 @@ int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *ne void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); -int bcm43xx_pci_read_config_16(struct pci_dev *pdev, u16 offset, u16 *val); -int bcm43xx_pci_read_config_32(struct pci_dev *pdev, u16 offset, u32 *val); -int bcm43xx_pci_write_config_16(struct pci_dev *pdev, int offset, u16 val); -int bcm43xx_pci_write_config_32(struct pci_dev *pdev, int offset, u32 val); - void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); void bcm43xx_mac_enable(struct bcm43xx_private *bcm); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 0bf4b3e26f..7b45fa1314 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -26,6 +26,7 @@ #include "bcm43xx.h" #include "bcm43xx_pio.h" #include "bcm43xx_main.h" +#include "bcm43xx_xmit.h" #include diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c new file mode 100644 index 0000000000..5ee572e79f --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c @@ -0,0 +1,579 @@ +/* + + Broadcom BCM43xx wireless driver + + Transmission (TX/RX) related functions. + + Copyright (c) 2005 Martin Langer , + Stefano Brivio + Michael Buesch + Danny van Dyk + Andreas Jaggi + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx_xmit.h" + +#include + + +/* Extract the bitrate out of a CCK PLCP header. */ +static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp) +{ + switch (plcp->raw[0]) { + case 0x0A: + return IEEE80211_CCK_RATE_1MB; + case 0x14: + return IEEE80211_CCK_RATE_2MB; + case 0x37: + return IEEE80211_CCK_RATE_5MB; + case 0x6E: + return IEEE80211_CCK_RATE_11MB; + } + assert(0); + return 0; +} + +/* Extract the bitrate out of an OFDM PLCP header. */ +static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp) +{ + switch (plcp->raw[0] & 0xF) { + case 0xB: + return IEEE80211_OFDM_RATE_6MB; + case 0xF: + return IEEE80211_OFDM_RATE_9MB; + case 0xA: + return IEEE80211_OFDM_RATE_12MB; + case 0xE: + return IEEE80211_OFDM_RATE_18MB; + case 0x9: + return IEEE80211_OFDM_RATE_24MB; + case 0xD: + return IEEE80211_OFDM_RATE_36MB; + case 0x8: + return IEEE80211_OFDM_RATE_48MB; + case 0xC: + return IEEE80211_OFDM_RATE_54MB; + } + assert(0); + return 0; +} + +u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) +{ + switch (bitrate) { + case IEEE80211_CCK_RATE_1MB: + return 0x0A; + case IEEE80211_CCK_RATE_2MB: + return 0x14; + case IEEE80211_CCK_RATE_5MB: + return 0x37; + case IEEE80211_CCK_RATE_11MB: + return 0x6E; + } + assert(0); + return 0; +} + +u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) +{ + switch (bitrate) { + case IEEE80211_OFDM_RATE_6MB: + return 0xB; + case IEEE80211_OFDM_RATE_9MB: + return 0xF; + case IEEE80211_OFDM_RATE_12MB: + return 0xA; + case IEEE80211_OFDM_RATE_18MB: + return 0xE; + case IEEE80211_OFDM_RATE_24MB: + return 0x9; + case IEEE80211_OFDM_RATE_36MB: + return 0xD; + case IEEE80211_OFDM_RATE_48MB: + return 0x8; + case IEEE80211_OFDM_RATE_54MB: + return 0xC; + } + assert(0); + return 0; +} + +static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, + const u16 octets, const u8 bitrate, + const int ofdm_modulation) +{ + __le32 *data = &(plcp->data); + __u8 *raw = plcp->raw; + + if (ofdm_modulation) { + *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate); + assert(!(octets & 0xF000)); + *data |= (octets << 5); + *data = cpu_to_le32(*data); + } else { + u32 plen; + + plen = octets * 16 / bitrate; + if ((octets * 16 % bitrate) > 0) { + plen++; + if ((bitrate == IEEE80211_CCK_RATE_11MB) + && ((octets * 8 % 11) < 4)) { + raw[1] = 0x84; + } else + raw[1] = 0x04; + } else + raw[1] = 0x04; + *data |= cpu_to_le32(plen << 16); + raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate); + } +} + +static u8 bcm43xx_calc_fallback_rate(u8 bitrate) +{ + switch (bitrate) { + case IEEE80211_CCK_RATE_1MB: + return IEEE80211_CCK_RATE_1MB; + case IEEE80211_CCK_RATE_2MB: + return IEEE80211_CCK_RATE_1MB; + case IEEE80211_CCK_RATE_5MB: + return IEEE80211_CCK_RATE_2MB; + case IEEE80211_CCK_RATE_11MB: + return IEEE80211_CCK_RATE_5MB; + case IEEE80211_OFDM_RATE_6MB: + return IEEE80211_CCK_RATE_5MB; + case IEEE80211_OFDM_RATE_9MB: + return IEEE80211_OFDM_RATE_6MB; + case IEEE80211_OFDM_RATE_12MB: + return IEEE80211_OFDM_RATE_9MB; + case IEEE80211_OFDM_RATE_18MB: + return IEEE80211_OFDM_RATE_12MB; + case IEEE80211_OFDM_RATE_24MB: + return IEEE80211_OFDM_RATE_18MB; + case IEEE80211_OFDM_RATE_36MB: + return IEEE80211_OFDM_RATE_24MB; + case IEEE80211_OFDM_RATE_48MB: + return IEEE80211_OFDM_RATE_36MB; + case IEEE80211_OFDM_RATE_54MB: + return IEEE80211_OFDM_RATE_48MB; + } + assert(0); + return 0; +} + +static +__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header, + u8 bitrate) +{ + const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl); + __le16 duration_id = wireless_header->duration_id; + + switch (WLAN_FC_GET_TYPE(frame_ctl)) { + case IEEE80211_FTYPE_DATA: + case IEEE80211_FTYPE_MGMT: + //TODO: Steal the code from ieee80211, once it is completed there. + break; + case IEEE80211_FTYPE_CTL: + /* Use the original duration/id. */ + break; + default: + assert(0); + } + + return duration_id; +} + +static inline +u16 ceiling_div(u16 dividend, u16 divisor) +{ + return ((dividend + divisor - 1) / divisor); +} + +static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy, + struct bcm43xx_txhdr *txhdr, + u16 *flags, + u8 bitrate, + const struct ieee80211_hdr_4addr *wlhdr) +{ + u16 fctl; + u16 dur; + u8 fallback_bitrate; + int ofdm_modulation; + int fallback_ofdm_modulation; + u8 *sa, *da; + u16 flen; + +//FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr); +//FIXME da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr); + fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate); + ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); + fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); + + flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN, + bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp), + flen, bitrate, + !ieee80211_is_cck_rate(bitrate)); + bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp), + flen, fallback_bitrate, + !ieee80211_is_cck_rate(fallback_bitrate)); + fctl = IEEE80211_FTYPE_CTL; + fctl |= IEEE80211_STYPE_RTS; + dur = le16_to_cpu(wlhdr->duration_id); +/*FIXME: should we test for dur==0 here and let it unmodified in this case? + * The following assert checks for this case... + */ +assert(dur); +/*FIXME: The duration calculation is not really correct. + * I am not 100% sure which bitrate to use. We use the RTS rate here, + * but this is likely to be wrong. + */ + if (phy->type == BCM43xx_PHYTYPE_A) { + /* Three times SIFS */ + dur += 16 * 3; + /* Add ACK duration. */ + dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10, + bitrate * 4); + /* Add CTS duration. */ + dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10, + bitrate * 4); + } else { + /* Three times SIFS */ + dur += 10 * 3; + /* Add ACK duration. */ + dur += ceiling_div(8 * (14 /*bytes*/) * 10, + bitrate); + /* Add CTS duration. */ + dur += ceiling_div(8 * (14 /*bytes*/) * 10, + bitrate); + } + + txhdr->rts_cts_frame_control = cpu_to_le16(fctl); + txhdr->rts_cts_dur = cpu_to_le16(dur); +//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3)); +//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da)); + memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME! + memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN); + + *flags |= BCM43xx_TXHDRFLAG_RTSCTS; + *flags |= BCM43xx_TXHDRFLAG_RTS; + if (ofdm_modulation) + *flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM; + if (fallback_ofdm_modulation) + *flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM; +} + +void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + const unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie) +{ + const struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data; + const struct ieee80211_security *secinfo = &bcm->ieee->sec; + u8 bitrate; + u8 fallback_bitrate; + int ofdm_modulation; + int fallback_ofdm_modulation; + u16 plcp_fragment_len = fragment_len; + u16 flags = 0; + u16 control = 0; + u16 wsec_rate = 0; + u16 encrypt_frame; + + /* Now construct the TX header. */ + memset(txhdr, 0, sizeof(*txhdr)); + + bitrate = bcm->softmac->txrates.default_rate; + ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); + fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate); + fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); + + /* Set Frame Control from 80211 header. */ + txhdr->frame_control = wireless_header->frame_ctl; + /* Copy address1 from 80211 header. */ + memcpy(txhdr->mac1, wireless_header->addr1, 6); + /* Set the fallback duration ID. */ + txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header, + fallback_bitrate); + /* Set the cookie (used as driver internal ID for the frame) */ + txhdr->cookie = cpu_to_le16(cookie); + + /* Hardware appends FCS. */ + plcp_fragment_len += IEEE80211_FCS_LEN; + + /* Hardware encryption. */ + encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED; + if (encrypt_frame && !bcm->ieee->host_encrypt) { + const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header; + memcpy(txhdr->wep_iv, hdr->payload, 4); + /* Hardware appends ICV. */ + plcp_fragment_len += 4; + + wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT) + & BCM43xx_TXHDR_WSEC_ALGO_MASK; + wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT) + & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK; + } + + /* Generate the PLCP header and the fallback PLCP header. */ + bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp), + plcp_fragment_len, + bitrate, ofdm_modulation); + bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len, + fallback_bitrate, fallback_ofdm_modulation); + + /* Set the CONTROL field */ + if (ofdm_modulation) + control |= BCM43xx_TXHDRCTL_OFDM; + if (bcm->short_preamble) //FIXME: could be the other way around, please test + control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE; + control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT) + & BCM43xx_TXHDRCTL_ANTENNADIV_MASK; + + /* Set the FLAGS field */ + if (!is_multicast_ether_addr(wireless_header->addr1) && + !is_broadcast_ether_addr(wireless_header->addr1)) + flags |= BCM43xx_TXHDRFLAG_EXPECTACK; + if (1 /* FIXME: PS poll?? */) + flags |= 0x10; // FIXME: unknown meaning. + if (fallback_ofdm_modulation) + flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM; + if (is_first_fragment) + flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT; + + /* Set WSEC/RATE field */ + wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT) + & BCM43xx_TXHDR_RATE_MASK; + + /* Generate the RTS/CTS packet, if required. */ + /* FIXME: We should first try with CTS-to-self, + * if we are on 80211g. If we get too many + * failures (hidden nodes), we should switch back to RTS/CTS. + */ + if (0/*FIXME txctl->use_rts_cts*/) { + bcm43xx_generate_rts(phy, txhdr, &flags, + 0/*FIXME txctl->rts_cts_rate*/, + wireless_header); + } + + txhdr->flags = cpu_to_le16(flags); + txhdr->control = cpu_to_le16(control); + txhdr->wsec_rate = cpu_to_le16(wsec_rate); +} + +static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, + u8 in_rssi, int ofdm, + int adjust_2053, int adjust_2050) +{ + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + s32 tmp; + + switch (radio->version) { + case 0x2050: + if (ofdm) { + tmp = in_rssi; + if (tmp > 127) + tmp -= 256; + tmp *= 73; + tmp /= 64; + if (adjust_2050) + tmp += 25; + else + tmp -= 3; + } else { + if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { + if (in_rssi > 63) + in_rssi = 63; + tmp = radio->nrssi_lt[in_rssi]; + tmp = 31 - tmp; + tmp *= -131; + tmp /= 128; + tmp -= 57; + } else { + tmp = in_rssi; + tmp = 31 - tmp; + tmp *= -149; + tmp /= 128; + tmp -= 68; + } + if (phy->type == BCM43xx_PHYTYPE_G && + adjust_2050) + tmp += 25; + } + break; + case 0x2060: + if (in_rssi > 127) + tmp = in_rssi - 256; + else + tmp = in_rssi; + break; + default: + tmp = in_rssi; + tmp -= 11; + tmp *= 103; + tmp /= 64; + if (adjust_2053) + tmp -= 109; + else + tmp -= 83; + } + + return (s8)tmp; +} + +static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, + u8 in_rssi) +{ + struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + s8 ret; + + if (phy->type == BCM43xx_PHYTYPE_A) { + //TODO: Incomplete specs. + ret = 0; + } else + ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1); + + return ret; +} + +int bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr) +{ + struct bcm43xx_plcp_hdr4 *plcp; + struct ieee80211_rx_stats stats; + struct ieee80211_hdr_4addr *wlhdr; + u16 frame_ctl; + int is_packet_for_us = 0; + int err = -EINVAL; + const u16 rxflags1 = le16_to_cpu(rxhdr->flags1); + const u16 rxflags2 = le16_to_cpu(rxhdr->flags2); + const u16 rxflags3 = le16_to_cpu(rxhdr->flags3); + const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM); + + if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) { + plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2); + /* Skip two unknown bytes and the PLCP header. */ + skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6)); + } else { + plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data); + /* Skip the PLCP header. */ + skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6)); + } + /* The SKB contains the PAYLOAD (wireless header + data) + * at this point. The FCS at the end is stripped. + */ + + memset(&stats, 0, sizeof(stats)); + stats.mac_time = le16_to_cpu(rxhdr->mactime); + stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, + !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), + !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); + stats.signal = rxhdr->signal_quality; //FIXME +//TODO stats.noise = + if (is_ofdm) + stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp); + else + stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp); +//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate); + stats.received_channel = bcm->current_core->radio->channel; +//TODO stats.control = + stats.mask = IEEE80211_STATMASK_SIGNAL | +//TODO IEEE80211_STATMASK_NOISE | + IEEE80211_STATMASK_RATE | + IEEE80211_STATMASK_RSSI; + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + stats.freq = IEEE80211_52GHZ_BAND; + else + stats.freq = IEEE80211_24GHZ_BAND; + stats.len = skb->len; + + bcm->stats.last_rx = jiffies; + if (bcm->ieee->iw_mode == IW_MODE_MONITOR) { + err = ieee80211_rx(bcm->ieee, skb, &stats); + return (err == 0) ? -EINVAL : 0; + } + + wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); + + switch (bcm->ieee->iw_mode) { + case IW_MODE_ADHOC: + if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || + memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || + is_broadcast_ether_addr(wlhdr->addr1) || + is_multicast_ether_addr(wlhdr->addr1) || + bcm->net_dev->flags & IFF_PROMISC) + is_packet_for_us = 1; + break; + case IW_MODE_INFRA: + default: + /* When receiving multicast or broadcast packets, filter out + the packets we send ourself; we shouldn't see those */ + if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || + memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || + (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) && + (is_broadcast_ether_addr(wlhdr->addr1) || + is_multicast_ether_addr(wlhdr->addr1) || + bcm->net_dev->flags & IFF_PROMISC))) + is_packet_for_us = 1; + break; + } + + frame_ctl = le16_to_cpu(wlhdr->frame_ctl); + if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { + frame_ctl &= ~IEEE80211_FCTL_PROTECTED; + wlhdr->frame_ctl = cpu_to_le16(frame_ctl); + /* trim IV and ICV */ + /* FIXME: this must be done only for WEP encrypted packets */ + if (skb->len < 32) { + dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag " + "set and length < 32)\n"); + return -EINVAL; + } else { + memmove(skb->data + 4, skb->data, 24); + skb_pull(skb, 4); + skb_trim(skb, skb->len - 4); + stats.len -= 8; + } + wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); + } + + switch (WLAN_FC_GET_TYPE(frame_ctl)) { + case IEEE80211_FTYPE_MGMT: + ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); + break; + case IEEE80211_FTYPE_DATA: + if (is_packet_for_us) { + err = ieee80211_rx(bcm->ieee, skb, &stats); + err = (err == 0) ? -EINVAL : 0; + } + break; + case IEEE80211_FTYPE_CTL: + break; + default: + assert(0); + return -EINVAL; + } + + return err; +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h new file mode 100644 index 0000000000..2aed19e35c --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h @@ -0,0 +1,156 @@ +#ifndef BCM43xx_XMIT_H_ +#define BCM43xx_XMIT_H_ + +#include "bcm43xx_main.h" + + +#define _bcm43xx_declare_plcp_hdr(size) \ + struct bcm43xx_plcp_hdr##size { \ + union { \ + __le32 data; \ + __u8 raw[size]; \ + } __attribute__((__packed__)); \ + } __attribute__((__packed__)) + +/* struct bcm43xx_plcp_hdr4 */ +_bcm43xx_declare_plcp_hdr(4); +/* struct bcm43xx_plcp_hdr6 */ +_bcm43xx_declare_plcp_hdr(6); + +#undef _bcm43xx_declare_plcp_hdr + +/* Device specific TX header. To be prepended to TX frames. */ +struct bcm43xx_txhdr { + union { + struct { + __le16 flags; + __le16 wsec_rate; + __le16 frame_control; + u16 unknown_zeroed_0; + __le16 control; + u8 wep_iv[10]; + u8 unknown_wsec_tkip_data[3]; //FIXME + PAD_BYTES(3); + u8 mac1[6]; + u16 unknown_zeroed_1; + struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp; + __le16 rts_cts_dur_fallback; + struct bcm43xx_plcp_hdr4 fallback_plcp; + __le16 fallback_dur_id; + PAD_BYTES(2); + __le16 cookie; + __le16 unknown_scb_stuff; //FIXME + struct bcm43xx_plcp_hdr6 rts_cts_plcp; + __le16 rts_cts_frame_control; + __le16 rts_cts_dur; + u8 rts_cts_mac1[6]; + u8 rts_cts_mac2[6]; + PAD_BYTES(2); + struct bcm43xx_plcp_hdr6 plcp; + } __attribute__((__packed__)); + u8 raw[82]; + } __attribute__((__packed__)); +} __attribute__((__packed__)); + +/* Values/Masks for the device TX header */ +#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001 +#define BCM43xx_TXHDRFLAG_RTSCTS 0x0002 +#define BCM43xx_TXHDRFLAG_RTS 0x0004 +#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008 +#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020 +#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM 0x0080 +#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100 +#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM 0x0200 +#define BCM43xx_TXHDRFLAG_CTS 0x0400 +#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800 + +#define BCM43xx_TXHDRCTL_OFDM 0x0001 +#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010 +#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030 +#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8 + +#define BCM43xx_TXHDR_RATE_MASK 0x0F00 +#define BCM43xx_TXHDR_RATE_SHIFT 8 +#define BCM43xx_TXHDR_RTSRATE_MASK 0xF000 +#define BCM43xx_TXHDR_RTSRATE_SHIFT 12 +#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0 +#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4 +#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003 +#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0 + +void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, + struct bcm43xx_txhdr *txhdr, + const unsigned char *fragment_data, + const unsigned int fragment_len, + const int is_first_fragment, + const u16 cookie); + +/* RX header as received from the hardware. */ +struct bcm43xx_rxhdr { + /* Frame Length. Must be generated explicitely in PIO mode. */ + __le16 frame_length; + PAD_BYTES(2); + /* Flags field 1 */ + __le16 flags1; + u8 rssi; + u8 signal_quality; + PAD_BYTES(2); + /* Flags field 3 */ + __le16 flags3; + /* Flags field 2 */ + __le16 flags2; + /* Lower 16bits of the TSF at the time the frame started. */ + __le16 mactime; + PAD_BYTES(14); +} __attribute__((__packed__)); + +#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0) +/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */ +#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7) +#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14) + +#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0) +#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2) +/*FIXME: WEP related flags */ + +#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10) + +/* Transmit Status as received from the hardware. */ +struct bcm43xx_hwxmitstatus { + PAD_BYTES(4); + __le16 cookie; + u8 flags; + u8 cnt1:4, + cnt2:4; + PAD_BYTES(2); + __le16 seq; + __le16 unknown; //FIXME +} __attribute__((__packed__)); + +/* Transmit Status in CPU byteorder. */ +struct bcm43xx_xmitstatus { + u16 cookie; + u8 flags; + u8 cnt1:4, + cnt2:4; + u16 seq; + u16 unknown; //FIXME +}; + +#define BCM43xx_TXSTAT_FLAG_ACK 0x01 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x02 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x04 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x08 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x10 +#define BCM43xx_TXSTAT_FLAG_IGNORE 0x20 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x40 +//TODO #define BCM43xx_TXSTAT_FLAG_??? 0x80 + +u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate); +u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate); + +int bcm43xx_rx(struct bcm43xx_private *bcm, + struct sk_buff *skb, + struct bcm43xx_rxhdr *rxhdr); + +#endif /* BCM43xx_XMIT_H_ */ -- cgit v1.2.2 From 367f899ac3b52cf4611cd291ec2bfbf774b15bc7 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 28 Feb 2006 15:32:19 +0100 Subject: [PATCH] bcm43xx: Add sysfs attributes for device specific tunables. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/Makefile | 2 +- drivers/net/wireless/bcm43xx/bcm43xx.h | 3 + drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4 + drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 323 +++++++++++++++++++++++++++ drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h | 25 +++ 5 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c create mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile index 2962b5f9e3..bb5220c629 100644 --- a/drivers/net/wireless/bcm43xx/Makefile +++ b/drivers/net/wireless/bcm43xx/Makefile @@ -8,5 +8,5 @@ bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \ bcm43xx_radio.o bcm43xx_phy.o \ bcm43xx_power.o bcm43xx_wx.o \ bcm43xx_leds.o bcm43xx_ethtool.o \ - bcm43xx_xmit.o \ + bcm43xx_xmit.o bcm43xx_sysfs.o \ $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 21c75cae14..fd9754b529 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -15,6 +15,7 @@ #include "bcm43xx_debugfs.h" #include "bcm43xx_leds.h" +#include "bcm43xx_sysfs.h" #define PFX KBUILD_MODNAME ": " @@ -606,6 +607,8 @@ struct bcm43xx_key { }; struct bcm43xx_private { + struct bcm43xx_sysfs sysfs; + struct ieee80211_device *ieee; struct ieee80211softmac_device *softmac; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index f1ac9940f1..1fe2fa9856 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3160,6 +3160,8 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) int i, err; unsigned long flags; + bcm43xx_sysfs_unregister(bcm); + bcm43xx_periodic_tasks_delete(bcm); spin_lock_irqsave(&bcm->lock, flags); @@ -3270,6 +3272,8 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) spin_unlock_irqrestore(&bcm->lock, flags); bcm43xx_periodic_tasks_setup(bcm); + bcm43xx_sysfs_register(bcm); + //FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though... assert(err == 0); out: diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c new file mode 100644 index 0000000000..2d31737372 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -0,0 +1,323 @@ +/* + + Broadcom BCM43xx wireless driver + + SYSFS support routines + + Copyright (c) 2006 Michael Buesch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "bcm43xx_sysfs.h" +#include "bcm43xx.h" +#include "bcm43xx_main.h" +#include "bcm43xx_radio.h" + +#include + + +#define GENERIC_FILESIZE 64 + + +static int get_integer(const char *buf, size_t count) +{ + char tmp[10 + 1] = { 0 }; + int ret = -EINVAL; + + if (count == 0) + goto out; + count = min(count, (size_t)10); + memcpy(tmp, buf, count); + ret = simple_strtol(tmp, NULL, 10); +out: + return ret; +} + +static int get_boolean(const char *buf, size_t count) +{ + if (count != 0) { + if (buf[0] == '1') + return 1; + if (buf[0] == '0') + return 0; + if (count >= 4 && memcmp(buf, "true", 4) == 0) + return 1; + if (count >= 5 && memcmp(buf, "false", 5) == 0) + return 0; + if (count >= 3 && memcmp(buf, "yes", 3) == 0) + return 1; + if (count >= 2 && memcmp(buf, "no", 2) == 0) + return 0; + if (count >= 2 && memcmp(buf, "on", 2) == 0) + return 1; + if (count >= 3 && memcmp(buf, "off", 3) == 0) + return 0; + } + return -EINVAL; +} + +static ssize_t bcm43xx_attr_sprom_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom); + u16 *sprom; + unsigned long flags; + int i, err; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE); + sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), + GFP_KERNEL); + if (!sprom) + return -ENOMEM; + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + err = bcm43xx_sprom_read(bcm, sprom); + if (!err) { + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { + buf[i * 2] = sprom[i] & 0x00FF; + buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8; + } + } + spin_unlock_irqrestore(&bcm->lock, flags); + kfree(sprom); + + return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16); +} + +static ssize_t bcm43xx_attr_sprom_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom); + u16 *sprom; + unsigned long flags; + int i, err; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (count != BCM43xx_SPROM_SIZE * sizeof(u16)) + return -EINVAL; + sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), + GFP_KERNEL); + if (!sprom) + return -ENOMEM; + for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { + sprom[i] = buf[i * 2] & 0xFF; + sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8; + } + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + err = bcm43xx_sprom_write(bcm, sprom); + spin_unlock_irqrestore(&bcm->lock, flags); + kfree(sprom); + + return err ? err : count; + +} + +static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode); + unsigned long flags; + int err; + ssize_t count = 0; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + + switch (bcm->current_core->radio->interfmode) { + case BCM43xx_RADIO_INTERFMODE_NONE: + count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n"); + break; + case BCM43xx_RADIO_INTERFMODE_NONWLAN: + count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference Mitigation)\n"); + break; + case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: + count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference Mitigation)\n"); + break; + default: + assert(0); + } + err = 0; + + spin_unlock_irqrestore(&bcm->lock, flags); + return err ? err : count; + +} + +static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode); + unsigned long flags; + int err; + int mode; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + mode = get_integer(buf, count); + switch (mode) { + case 0: + mode = BCM43xx_RADIO_INTERFMODE_NONE; + break; + case 1: + mode = BCM43xx_RADIO_INTERFMODE_NONWLAN; + break; + case 2: + mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; + break; + case 3: + mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; + break; + default: + return -EINVAL; + } + + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + + err = bcm43xx_radio_set_interference_mitigation(bcm, mode); + if (err) { + printk(KERN_ERR PFX "Interference Mitigation not " + "supported by device\n"); + } + + spin_unlock_irqrestore(&bcm->lock, flags); + + return err ? err : count; +} + +static ssize_t bcm43xx_attr_preamble_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble); + unsigned long flags; + int err; + ssize_t count; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + + if (bcm->short_preamble) + count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); + else + count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); + + err = 0; + spin_unlock_irqrestore(&bcm->lock, flags); + + return err ? err : count; +} + +static ssize_t bcm43xx_attr_preamble_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble); + unsigned long flags; + int err; + int value; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + value = get_boolean(buf, count); + if (value < 0) + return value; + spin_lock_irqsave(&bcm->lock, flags); + assert(bcm->initialized); + + bcm->short_preamble = !!value; + + err = 0; + spin_unlock_irqrestore(&bcm->lock, flags); + + return err ? err : count; +} + +int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) +{ + struct device *dev = &bcm->pci_dev->dev; + struct bcm43xx_sysfs *sysfs = &bcm->sysfs; + int err; + + assert(bcm->initialized); + + sysfs->attr_sprom.attr.name = "sprom"; + sysfs->attr_sprom.attr.owner = THIS_MODULE; + sysfs->attr_sprom.attr.mode = 0600; + sysfs->attr_sprom.show = bcm43xx_attr_sprom_show; + sysfs->attr_sprom.store = bcm43xx_attr_sprom_store; + err = device_create_file(dev, &sysfs->attr_sprom); + if (err) + goto out; + + sysfs->attr_interfmode.attr.name = "interference"; + sysfs->attr_interfmode.attr.owner = THIS_MODULE; + sysfs->attr_interfmode.attr.mode = 0600; + sysfs->attr_interfmode.show = bcm43xx_attr_interfmode_show; + sysfs->attr_interfmode.store = bcm43xx_attr_interfmode_store; + err = device_create_file(dev, &sysfs->attr_interfmode); + if (err) + goto err_remove_sprom; + + sysfs->attr_preamble.attr.name = "shortpreamble"; + sysfs->attr_preamble.attr.owner = THIS_MODULE; + sysfs->attr_preamble.attr.mode = 0600; + sysfs->attr_preamble.show = bcm43xx_attr_preamble_show; + sysfs->attr_preamble.store = bcm43xx_attr_preamble_store; + err = device_create_file(dev, &sysfs->attr_preamble); + if (err) + goto err_remove_interfmode; + +out: + return err; +err_remove_interfmode: + device_remove_file(dev, &sysfs->attr_interfmode); +err_remove_sprom: + device_remove_file(dev, &sysfs->attr_sprom); + goto out; +} + +void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm) +{ + struct device *dev = &bcm->pci_dev->dev; + struct bcm43xx_sysfs *sysfs = &bcm->sysfs; + + device_remove_file(dev, &sysfs->attr_preamble); + device_remove_file(dev, &sysfs->attr_interfmode); + device_remove_file(dev, &sysfs->attr_sprom); +} + +/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h new file mode 100644 index 0000000000..57f14514e3 --- /dev/null +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h @@ -0,0 +1,25 @@ +#ifndef BCM43xx_SYSFS_H_ +#define BCM43xx_SYSFS_H_ + +#include + + +struct bcm43xx_sysfs { + struct device_attribute attr_sprom; + struct device_attribute attr_interfmode; + struct device_attribute attr_preamble; +}; + +#define devattr_to_bcm(attr, attr_name) ({ \ + struct bcm43xx_sysfs *__s; struct bcm43xx_private *__p; \ + __s = container_of((attr), struct bcm43xx_sysfs, attr_name); \ + __p = container_of(__s, struct bcm43xx_private, sysfs); \ + __p; \ + }) + +struct bcm43xx_private; + +int bcm43xx_sysfs_register(struct bcm43xx_private *bcm); +void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm); + +#endif /* BCM43xx_SYSFS_H_ */ -- cgit v1.2.2 From 512a80916b8d04529c0915534c63529144f74e10 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Tue, 7 Mar 2006 01:37:51 +0100 Subject: [PATCH] bcm43xx: fix DMA TX skb freeing in case of fragmented packets. It seems to me that the today's wireless-2.6 git contains bcm43xx which does not free txb's correctly, if I understand it right. Consider a situation where a txb with two skb's is sent down. The dma_tx_fragment will save the pointer to meta->txb of the first fragment. If fragments are freed in order, ieee80211_txb_free frees both skb's when the first fragment is processed. This may result in reuse of the second skb's memory. This danger is rather remote, but it seems to me that the patch below not only fixes the problem, but also makes the code simpler, which is good, right? Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 44 ++++++------------------------ drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 4 --- 2 files changed, 8 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index e20fbaf29e..0cd2928479 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -170,19 +170,6 @@ void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring, addr, len, DMA_FROM_DEVICE); } -static inline -void mark_skb_mustfree(struct sk_buff *skb, - char mustfree) -{ - skb->cb[0] = mustfree; -} - -static inline -int skb_mustfree(struct sk_buff *skb) -{ - return (skb->cb[0] != 0); -} - /* Unmap and free a descriptor buffer. */ static inline void free_descriptor_buffer(struct bcm43xx_dmaring *ring, @@ -191,17 +178,11 @@ void free_descriptor_buffer(struct bcm43xx_dmaring *ring, int irq_context) { assert(meta->skb); - if (skb_mustfree(meta->skb)) { - if (irq_context) - dev_kfree_skb_irq(meta->skb); - else - dev_kfree_skb(meta->skb); - } + if (irq_context) + dev_kfree_skb_irq(meta->skb); + else + dev_kfree_skb(meta->skb); meta->skb = NULL; - if (meta->txb) { - ieee80211_txb_free(meta->txb); - meta->txb = NULL; - } } static int alloc_ringmemory(struct bcm43xx_dmaring *ring) @@ -334,7 +315,6 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, meta->skb = skb; meta->dmaaddr = dmaaddr; skb->dev = ring->bcm->net_dev; - mark_skb_mustfree(skb, 1); desc_addr = (u32)(dmaaddr + ring->memoffset); desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK & (u32)(ring->rx_buffersize - ring->frameoffset)); @@ -457,7 +437,6 @@ static void free_all_descbuffers(struct bcm43xx_dmaring *ring) if (!meta->skb) { assert(ring->tx); - assert(!meta->txb); continue; } if (ring->tx) { @@ -726,7 +705,6 @@ static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, static int dma_tx_fragment(struct bcm43xx_dmaring *ring, struct sk_buff *skb, - struct ieee80211_txb *txb, u8 cur_frag) { int slot; @@ -741,11 +719,6 @@ static int dma_tx_fragment(struct bcm43xx_dmaring *ring, desc = ring->vbase + slot; meta = ring->meta + slot; - if (cur_frag == 0) { - /* Save the txb pointer for freeing in xmitstatus IRQ */ - meta->txb = txb; - } - /* Add a device specific TX header. */ assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); /* Reserve enough headroom for the device tx header. */ @@ -810,13 +783,12 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, for (i = 0; i < txb->nr_frags; i++) { skb = txb->fragments[i]; - /* We do not free the skb, as it is freed as - * part of the txb freeing. - */ - mark_skb_mustfree(skb, 0); - dma_tx_fragment(ring, skb, txb, i); + /* Take skb from ieee80211_txb_free */ + txb->fragments[i] = NULL; + dma_tx_fragment(ring, skb, i); //TODO: handle failure of dma_tx_fragment } + ieee80211_txb_free(txb); return 0; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index 88ad34dff2..cab8e2ba4c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -119,10 +119,6 @@ struct bcm43xx_dmadesc_meta { struct sk_buff *skb; /* DMA base bus-address of the descriptor buffer. */ dma_addr_t dmaaddr; - /* Pointer to our txb (can be NULL). - * This should be freed in completion IRQ. - */ - struct ieee80211_txb *txb; }; struct bcm43xx_dmaring { -- cgit v1.2.2 From 4d5a9e0eeb7ec928c6bd55db410f09ed3779bc2a Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 11 Mar 2006 13:15:02 +0100 Subject: [PATCH] bcm43xx: Set both, the DMAmask and the coherent DMAmask. This has a potential to fix the >1G bug. But I can not test that, yet. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 1fe2fa9856..6da0beb0a9 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3717,6 +3717,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, struct net_device *net_dev, struct pci_dev *pci_dev) { + int err; + bcm->ieee = netdev_priv(net_dev); bcm->softmac = ieee80211_priv(net_dev); bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; @@ -3735,8 +3737,7 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; bcm->pci_dev = pci_dev; bcm->net_dev = net_dev; - if (modparam_bad_frames_preempt) - bcm->bad_frames_preempt = 1; + bcm->bad_frames_preempt = modparam_bad_frames_preempt; spin_lock_init(&bcm->lock); tasklet_init(&bcm->isr_tasklet, (void (*)(unsigned long))bcm43xx_interrupt_tasklet, @@ -3745,7 +3746,9 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, if (modparam_pio) { bcm->__using_pio = 1; } else { - if (pci_set_dma_mask(pci_dev, DMA_30BIT_MASK)) { + err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK); + err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK); + if (err) { #ifdef CONFIG_BCM43XX_PIO printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n"); bcm->__using_pio = 1; -- cgit v1.2.2 From efccb647f486ff8174b4db0ab8145df8dd42ce6d Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 11 Mar 2006 13:39:14 +0100 Subject: [PATCH] bcm43xx: Abstract the locking mechanism. This is the starting point to make the driver out-of-order-MMIO-stores safe. There are more mmiowb() needed. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 20 ++++- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 26 +++--- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 75 +++++++++-------- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 25 +++--- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 112 ++++++++++++------------- 7 files changed, 142 insertions(+), 124 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index fd9754b529..5f8c63fab8 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -619,7 +619,9 @@ struct bcm43xx_private { void __iomem *mmio_addr; unsigned int mmio_len; - spinlock_t lock; + /* Do not use the lock directly. Use the bcm43xx_lock* helper + * functions, to be MMIO-safe. */ + spinlock_t _lock; /* Driver status flags. */ u32 initialized:1, /* init_board() succeed */ @@ -721,6 +723,22 @@ struct bcm43xx_private { #endif }; +/* bcm43xx_(un)lock() protect struct bcm43xx_private. + * Note that _NO_ MMIO writes are allowed. If you want to + * write to the device through MMIO in the critical section, use + * the *_mmio lock functions. + * MMIO read-access is allowed, though. + */ +#define bcm43xx_lock(bcm, flags) spin_lock_irqsave(&(bcm)->_lock, flags) +#define bcm43xx_unlock(bcm, flags) spin_unlock_irqrestore(&(bcm)->_lock, flags) +/* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO. + * MMIO write-access to the device is allowed. + * All MMIO writes are flushed on unlock, so it is guaranteed to not + * interfere with other threads writing MMIO registers. + */ +#define bcm43xx_lock_mmio(bcm, flags) bcm43xx_lock(bcm, flags) +#define bcm43xx_unlock_mmio(bcm, flags) do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0) + static inline struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index 0bae0be4be..bcfcebe282 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -77,7 +77,7 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, down(&big_buffer_sem); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) { fappend("Board not initialized.\n"); goto out; @@ -124,7 +124,7 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, fappend("\n"); out: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -162,7 +162,7 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, unsigned long flags; down(&big_buffer_sem); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) { fappend("Board not initialized.\n"); goto out; @@ -172,7 +172,7 @@ static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); out: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -191,7 +191,7 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, u64 tsf; down(&big_buffer_sem); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) { fappend("Board not initialized.\n"); goto out; @@ -202,7 +202,7 @@ static ssize_t tsf_read_file(struct file *file, char __user *userbuf, (unsigned int)(tsf & 0xFFFFFFFFULL)); out: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); up(&big_buffer_sem); return res; @@ -224,7 +224,7 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, res = -EFAULT; goto out_up; } - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) { printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); res = -EFAULT; @@ -239,7 +239,7 @@ static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, res = buf_size; out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); out_up: up(&big_buffer_sem); return res; @@ -260,7 +260,7 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, int i, cnt, j = 0; down(&big_buffer_sem); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", BCM43xx_NR_LOGGED_XMITSTATUS); @@ -296,14 +296,14 @@ static ssize_t txstat_read_file(struct file *file, char __user *userbuf, i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); if (*ppos == pos) { /* Done. Drop the copied data. */ e->xmitstatus_printing = 0; } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); up(&big_buffer_sem); return res; } @@ -419,7 +419,7 @@ void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, struct bcm43xx_dfsentry *e; struct bcm43xx_xmitstatus *savedstatus; - /* This is protected by bcm->lock */ + /* This is protected by bcm->_lock */ e = bcm->dfsentry; assert(e); savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 8f550c1a92..949555da5a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -51,12 +51,12 @@ static void bcm43xx_led_blink(unsigned long d) struct bcm43xx_private *bcm = led->bcm; unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (led->blink_interval) { bcm43xx_led_changestate(led); mod_timer(&led->blink_timer, jiffies + led->blink_interval); } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); } static void bcm43xx_led_blink_start(struct bcm43xx_led *led, diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 6da0beb0a9..b719255983 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -482,14 +482,14 @@ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *old u32 old; unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) { - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return -EBUSY; } old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); tasklet_disable(&bcm->isr_tasklet); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); if (oldstate) *oldstate = old; @@ -746,6 +746,7 @@ int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom) else if (i % 2) printk("."); bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); + mmiowb(); mdelay(20); } spromctl &= ~0x10; /* SPROM WRITE enable. */ @@ -1676,7 +1677,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) # define bcmirq_handled(irq) do { /* nothing */ } while (0) #endif /* CONFIG_BCM43XX_DEBUG*/ - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); reason = bcm->irq_reason; dma_reason[0] = bcm->dma_reason[0]; dma_reason[1] = bcm->dma_reason[1]; @@ -1776,7 +1777,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) if (!modparam_noleds) bcm43xx_leds_update(bcm, activity); bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); } #undef bcmirq_print_reasons @@ -1830,25 +1831,24 @@ static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, /* Interrupt handler top-half */ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs) { + irqreturn_t ret = IRQ_HANDLED; struct bcm43xx_private *bcm = dev_id; u32 reason, mask; if (!bcm) return IRQ_NONE; - spin_lock(&bcm->lock); + spin_lock(&bcm->_lock); reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); if (reason == 0xffffffff) { /* irq not for us (shared irq) */ - spin_unlock(&bcm->lock); - return IRQ_NONE; + ret = IRQ_NONE; + goto out; } mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); - if (!(reason & mask)) { - spin_unlock(&bcm->lock); - return IRQ_HANDLED; - } + if (!(reason & mask)) + goto out; bcm43xx_interrupt_ack(bcm, reason, mask); @@ -1866,9 +1866,11 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re tasklet_schedule(&bcm->isr_tasklet); } - spin_unlock(&bcm->lock); +out: + mmiowb(); + spin_unlock(&bcm->_lock); - return IRQ_HANDLED; + return ret; } static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) @@ -3112,7 +3114,7 @@ static void bcm43xx_periodic_task_handler(unsigned long d) unsigned long flags; unsigned int state; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); assert(bcm->initialized); state = bcm->periodic_state; @@ -3127,7 +3129,7 @@ static void bcm43xx_periodic_task_handler(unsigned long d) mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15)); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); } static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) @@ -3164,10 +3166,10 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) bcm43xx_periodic_tasks_delete(bcm); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->initialized = 0; bcm->shutting_down = 1; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE)) @@ -3182,9 +3184,9 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) bcm43xx_pctl_set_crystal(bcm, 0); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->shutting_down = 0; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); } static int bcm43xx_init_board(struct bcm43xx_private *bcm) @@ -3196,10 +3198,10 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) might_sleep(); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->initialized = 0; bcm->shutting_down = 0; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); err = bcm43xx_pctl_set_crystal(bcm, 1); if (err) @@ -3267,9 +3269,9 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) } /* Initialization of the board is done. Flag it as such. */ - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->initialized = 1; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); bcm43xx_periodic_tasks_setup(bcm); bcm43xx_sysfs_register(bcm); @@ -3570,11 +3572,11 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); bcm43xx_mac_suspend(bcm); bcm43xx_radio_selectchannel(bcm, channel, 0); bcm43xx_mac_enable(bcm); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); } /* set_security() callback in struct ieee80211_device */ @@ -3587,9 +3589,9 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, int keyidx; dprintk(KERN_INFO PFX "set security called\n"); - - spin_lock_irqsave(&bcm->lock, flags); - + + bcm43xx_lock_mmio(bcm, flags); + for (keyidx = 0; keyidxflags & (1<encode_alg[keyidx] = sec->encode_alg[keyidx]; @@ -3651,7 +3653,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, } else bcm43xx_clear_keys(bcm); } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); } /* hard_start_xmit() callback in struct ieee80211_device */ @@ -3663,10 +3665,10 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, int err = -ENODEV; unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (likely(bcm->initialized)) err = bcm43xx_tx(bcm, txb); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return err; } @@ -3679,8 +3681,11 @@ static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_de static void bcm43xx_net_tx_timeout(struct net_device *net_dev) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + bcm43xx_lock_mmio(bcm, flags); bcm43xx_controller_restart(bcm, "TX timeout"); + bcm43xx_unlock_mmio(bcm, flags); } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -3738,7 +3743,7 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, bcm->pci_dev = pci_dev; bcm->net_dev = net_dev; bcm->bad_frames_preempt = modparam_bad_frames_preempt; - spin_lock_init(&bcm->lock); + spin_lock_init(&bcm->_lock); tasklet_init(&bcm->isr_tasklet, (void (*)(unsigned long))bcm43xx_interrupt_tasklet, (unsigned long)bcm); @@ -3921,11 +3926,11 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state) dprintk(KERN_INFO PFX "Suspending...\n"); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->was_initialized = bcm->initialized; if (bcm->initialized) try_to_shutdown = 1; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); netif_device_detach(net_dev); if (try_to_shutdown) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 7b45fa1314..26dc6047d4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -258,7 +258,7 @@ static void tx_tasklet(unsigned long d) struct bcm43xx_pio_txpacket *packet, *tmp_packet; int err; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { assert(packet->xmitted_frags < packet->txb->nr_frags); if (packet->xmitted_frags == 0) { @@ -288,7 +288,7 @@ static void tx_tasklet(unsigned long d) next_packet: continue; } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); } static void setup_txqueues(struct bcm43xx_pioqueue *queue) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index 2d31737372..713ec601c3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -88,7 +88,7 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev, GFP_KERNEL); if (!sprom) return -ENOMEM; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); assert(bcm->initialized); err = bcm43xx_sprom_read(bcm, sprom); if (!err) { @@ -97,7 +97,7 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev, buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8; } } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); kfree(sprom); return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16); @@ -125,10 +125,10 @@ static ssize_t bcm43xx_attr_sprom_store(struct device *dev, sprom[i] = buf[i * 2] & 0xFF; sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8; } - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); assert(bcm->initialized); err = bcm43xx_sprom_write(bcm, sprom); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); kfree(sprom); return err ? err : count; @@ -147,7 +147,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); assert(bcm->initialized); switch (bcm->current_core->radio->interfmode) { @@ -165,7 +165,8 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, } err = 0; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); + return err ? err : count; } @@ -200,7 +201,7 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, return -EINVAL; } - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); assert(bcm->initialized); err = bcm43xx_radio_set_interference_mitigation(bcm, mode); @@ -209,7 +210,7 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, "supported by device\n"); } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return err ? err : count; } @@ -226,7 +227,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, if (!capable(CAP_NET_ADMIN)) return -EPERM; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); assert(bcm->initialized); if (bcm->short_preamble) @@ -235,7 +236,7 @@ static ssize_t bcm43xx_attr_preamble_show(struct device *dev, count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); err = 0; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err ? err : count; } @@ -255,13 +256,13 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, value = get_boolean(buf, count); if (value < 0) return value; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); assert(bcm->initialized); bcm->short_preamble = !!value; err = 0; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err ? err : count; } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index aa2d9930c4..208193851e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -61,7 +61,7 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, char suffix[7] = { 0 }; int have_a = 0, have_b = 0, have_g = 0; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); nr_80211 = bcm43xx_num_80211_cores(bcm); for (i = 0; i < nr_80211; i++) { phy = bcm->phy + i; @@ -78,7 +78,7 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, assert(0); } } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); i = 0; if (have_a) { @@ -113,7 +113,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, int freq; int err = -EINVAL; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { channel = data->freq.m; freq = bcm43xx_channel_to_freq(bcm, channel); @@ -133,7 +133,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, err = 0; } out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return err; } @@ -148,7 +148,7 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, int err = -ENODEV; u16 channel; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); channel = bcm->current_core->radio->channel; if (channel == 0xFF) { assert(!bcm->initialized); @@ -163,7 +163,7 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, err = 0; out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err; } @@ -181,10 +181,10 @@ static int bcm43xx_wx_set_mode(struct net_device *net_dev, if (mode == IW_MODE_AUTO) mode = BCM43xx_INITIAL_IWMODE; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (bcm->ieee->iw_mode != mode) bcm43xx_set_iwmode(bcm, mode); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return 0; } @@ -197,9 +197,9 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); data->mode = bcm->ieee->iw_mode; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -269,7 +269,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); range->num_bitrates = 0; i = 0; @@ -315,7 +315,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, } range->num_frequency = j; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -329,11 +329,11 @@ static int bcm43xx_wx_set_nick(struct net_device *net_dev, unsigned long flags; size_t len; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); memcpy(bcm->nick, extra, len); bcm->nick[len] = '\0'; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -347,12 +347,12 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev, unsigned long flags; size_t len; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); len = strlen(bcm->nick) + 1; memcpy(extra, bcm->nick, len); data->data.length = (__u16)len; data->data.flags = 1; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -366,7 +366,7 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); if (data->rts.disabled) { bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; err = 0; @@ -377,7 +377,7 @@ static int bcm43xx_wx_set_rts(struct net_device *net_dev, err = 0; } } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err; } @@ -390,11 +390,11 @@ static int bcm43xx_wx_get_rts(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); data->rts.value = bcm->rts_threshold; data->rts.fixed = 0; data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -408,7 +408,7 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, unsigned long flags; int err = -EINVAL; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); if (data->frag.disabled) { bcm->ieee->fts = MAX_FRAG_THRESHOLD; err = 0; @@ -419,7 +419,7 @@ static int bcm43xx_wx_set_frag(struct net_device *net_dev, err = 0; } } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err; } @@ -432,11 +432,11 @@ static int bcm43xx_wx_get_frag(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); data->frag.value = bcm->ieee->fts; data->frag.fixed = 0; data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -458,7 +458,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, return -EOPNOTSUPP; } - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) goto out_unlock; radio = bcm->current_core->radio; @@ -482,7 +482,7 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, err = 0; out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return err; } @@ -497,7 +497,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, unsigned long flags; int err = -ENODEV; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); if (!bcm->initialized) goto out_unlock; radio = bcm->current_core->radio; @@ -509,7 +509,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, err = 0; out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return err; } @@ -632,7 +632,7 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, return -EINVAL; } - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); if (bcm->initialized) { err = bcm43xx_radio_set_interference_mitigation(bcm, mode); if (err) { @@ -647,7 +647,7 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, } else bcm->current_core->radio->interfmode = mode; } - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock_mmio(bcm, flags); return err; } @@ -661,9 +661,9 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, unsigned long flags; int mode; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); mode = bcm->current_core->radio->interfmode; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); switch (mode) { case BCM43xx_RADIO_INTERFMODE_NONE: @@ -693,9 +693,9 @@ static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, int on; on = *((int *)extra); - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); bcm->short_preamble = !!on; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); return 0; } @@ -709,9 +709,9 @@ static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, unsigned long flags; int on; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock(bcm, flags); on = bcm->short_preamble; - spin_unlock_irqrestore(&bcm->lock, flags); + bcm43xx_unlock(bcm, flags); if (on) strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); @@ -732,13 +732,13 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, int on; on = *((int *)extra); - spin_lock_irqsave(&bcm->lock, flags); + + bcm43xx_lock(bcm, flags); bcm->ieee->host_encrypt = !!on; bcm->ieee->host_decrypt = !!on; bcm->ieee->host_build_iv = !on; - - spin_unlock_irqrestore(&bcm->lock, flags); - + bcm43xx_unlock(bcm, flags); + return 0; } @@ -750,17 +750,17 @@ static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; int on; - - spin_lock_irqsave(&bcm->lock, flags); + + bcm43xx_lock(bcm, flags); on = bcm->ieee->host_encrypt; - spin_unlock_irqrestore(&bcm->lock, flags); - + bcm43xx_unlock(bcm, flags); + if (on) strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); else strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING); data->data.length = strlen(extra + 1); - + return 0; } @@ -816,17 +816,13 @@ static int bcm43xx_wx_sprom_read(struct net_device *net_dev, if (!sprom) goto out; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); err = -ENODEV; - if (!bcm->initialized) { - spin_unlock_irqrestore(&bcm->lock, flags); - goto out_kfree; - } - err = bcm43xx_sprom_read(bcm, sprom); - spin_unlock_irqrestore(&bcm->lock, flags); + if (bcm->initialized) + err = bcm43xx_sprom_read(bcm, sprom); + bcm43xx_unlock_mmio(bcm, flags); if (!err) data->data.length = sprom2hex(sprom, extra); -out_kfree: kfree(sprom); out: return err; @@ -865,13 +861,11 @@ static int bcm43xx_wx_sprom_write(struct net_device *net_dev, if (err) goto out_kfree; - spin_lock_irqsave(&bcm->lock, flags); + bcm43xx_lock_mmio(bcm, flags); err = -ENODEV; - if (!bcm->initialized) - goto out_unlock; - err = bcm43xx_sprom_write(bcm, sprom); -out_unlock: - spin_unlock_irqrestore(&bcm->lock, flags); + if (bcm->initialized) + err = bcm43xx_sprom_write(bcm, sprom); + bcm43xx_unlock_mmio(bcm, flags); out_kfree: kfree(sprom); out: -- cgit v1.2.2 From 7ce942d0ff5df145831631f4df391c7207e676bb Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 11 Mar 2006 13:43:06 +0100 Subject: [PATCH] bcm43xx: Remove the mmio access printing facility overhead. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 101 ++-------------------------- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 35 ---------- 2 files changed, 6 insertions(+), 130 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 5f8c63fab8..29c95b0712 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -718,8 +718,6 @@ struct bcm43xx_private { /* Debugging stuff follows. */ #ifdef CONFIG_BCM43XX_DEBUG struct bcm43xx_dfsentry *dfsentry; - atomic_t mmio_print_cnt; - atomic_t pcicfg_print_cnt; #endif }; @@ -805,141 +803,54 @@ struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy, } -/* MMIO read/write functions. Debug and non-debug variants. */ -#ifdef CONFIG_BCM43XX_DEBUG - static inline u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset) { - u16 value; - - value = ioread16(bcm->mmio_addr + core_offset(bcm) + offset); - if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { - printk(KERN_INFO PFX "ioread16 offset: 0x%04x, value: 0x%04x\n", - offset, value); - } - - return value; + return ioread16(bcm->mmio_addr + core_offset(bcm) + offset); } static inline void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value) { iowrite16(value, bcm->mmio_addr + core_offset(bcm) + offset); - if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { - printk(KERN_INFO PFX "iowrite16 offset: 0x%04x, value: 0x%04x\n", - offset, value); - } } static inline u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset) { - u32 value; - - value = ioread32(bcm->mmio_addr + core_offset(bcm) + offset); - if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { - printk(KERN_INFO PFX "ioread32 offset: 0x%04x, value: 0x%08x\n", - offset, value); - } - - return value; + return ioread32(bcm->mmio_addr + core_offset(bcm) + offset); } static inline void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value) { iowrite32(value, bcm->mmio_addr + core_offset(bcm) + offset); - if (unlikely(atomic_read(&bcm->mmio_print_cnt) > 0)) { - printk(KERN_INFO PFX "iowrite32 offset: 0x%04x, value: 0x%08x\n", - offset, value); - } } static inline int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value) { - int err; - - err = pci_read_config_word(bcm->pci_dev, offset, value); - if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { - printk(KERN_INFO PFX "pciread16 offset: 0x%08x, value: 0x%04x, err: %d\n", - offset, *value, err); - } - - return err; + return pci_read_config_word(bcm->pci_dev, offset, value); } static inline int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value) { - int err; - - err = pci_read_config_dword(bcm->pci_dev, offset, value); - if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { - printk(KERN_INFO PFX "pciread32 offset: 0x%08x, value: 0x%08x, err: %d\n", - offset, *value, err); - } - - return err; + return pci_read_config_dword(bcm->pci_dev, offset, value); } static inline int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value) { - int err; - - err = pci_write_config_word(bcm->pci_dev, offset, value); - if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { - printk(KERN_INFO PFX "pciwrite16 offset: 0x%08x, value: 0x%04x, err: %d\n", - offset, value, err); - } - - return err; + return pci_write_config_word(bcm->pci_dev, offset, value); } static inline int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value) { - int err; - - err = pci_write_config_dword(bcm->pci_dev, offset, value); - if (unlikely(atomic_read(&bcm->pcicfg_print_cnt) > 0)) { - printk(KERN_INFO PFX "pciwrite32 offset: 0x%08x, value: 0x%08x, err: %d\n", - offset, value, err); - } - - return err; + return pci_write_config_dword(bcm->pci_dev, offset, value); } -#define bcm43xx_mmioprint_initial(bcm, value) atomic_set(&(bcm)->mmio_print_cnt, (value)) -#define bcm43xx_mmioprint_enable(bcm) atomic_inc(&(bcm)->mmio_print_cnt) -#define bcm43xx_mmioprint_disable(bcm) atomic_dec(&(bcm)->mmio_print_cnt) -#define bcm43xx_pciprint_initial(bcm, value) atomic_set(&(bcm)->pcicfg_print_cnt, (value)) -#define bcm43xx_pciprint_enable(bcm) atomic_inc(&(bcm)->pcicfg_print_cnt) -#define bcm43xx_pciprint_disable(bcm) atomic_dec(&(bcm)->pcicfg_print_cnt) - -#else /* CONFIG_BCM43XX_DEBUG*/ - -#define bcm43xx_read16(bcm, offset) ioread16((bcm)->mmio_addr + core_offset(bcm) + (offset)) -#define bcm43xx_write16(bcm, offset, value) iowrite16((value), (bcm)->mmio_addr + core_offset(bcm) + (offset)) -#define bcm43xx_read32(bcm, offset) ioread32((bcm)->mmio_addr + core_offset(bcm) + (offset)) -#define bcm43xx_write32(bcm, offset, value) iowrite32((value), (bcm)->mmio_addr + core_offset(bcm) + (offset)) -#define bcm43xx_pci_read_config16(bcm, o, v) pci_read_config_word((bcm)->pci_dev, (o), (v)) -#define bcm43xx_pci_read_config32(bcm, o, v) pci_read_config_dword((bcm)->pci_dev, (o), (v)) -#define bcm43xx_pci_write_config16(bcm, o, v) pci_write_config_word((bcm)->pci_dev, (o), (v)) -#define bcm43xx_pci_write_config32(bcm, o, v) pci_write_config_dword((bcm)->pci_dev, (o), (v)) - -#define bcm43xx_mmioprint_initial(x, y) do { /* nothing */ } while (0) -#define bcm43xx_mmioprint_enable(x) do { /* nothing */ } while (0) -#define bcm43xx_mmioprint_disable(x) do { /* nothing */ } while (0) -#define bcm43xx_pciprint_initial(bcm, value) do { /* nothing */ } while (0) -#define bcm43xx_pciprint_enable(bcm) do { /* nothing */ } while (0) -#define bcm43xx_pciprint_disable(bcm) do { /* nothing */ } while (0) - -#endif /* CONFIG_BCM43XX_DEBUG*/ - - /** Limit a value between two limits */ #ifdef limit_value # undef limit_value diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index b719255983..f3cef345c8 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2018,12 +2018,6 @@ static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) const u32 *data; unsigned int i, len; -#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT - bcm43xx_mmioprint_enable(bcm); -#else - bcm43xx_mmioprint_disable(bcm); -#endif - /* Upload Microcode. */ data = (u32 *)(bcm->ucode->data); len = bcm->ucode->size / sizeof(u32); @@ -2045,12 +2039,6 @@ static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) be32_to_cpu(data[i])); udelay(10); } - -#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT - bcm43xx_mmioprint_disable(bcm); -#else - bcm43xx_mmioprint_enable(bcm); -#endif } static int bcm43xx_write_initvals(struct bcm43xx_private *bcm, @@ -2090,12 +2078,6 @@ static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) { int err; -#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT - bcm43xx_mmioprint_enable(bcm); -#else - bcm43xx_mmioprint_disable(bcm); -#endif - err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, bcm->initvals0->size / sizeof(struct bcm43xx_initval)); if (err) @@ -2106,13 +2088,7 @@ static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) if (err) goto out; } - out: -#ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT - bcm43xx_mmioprint_disable(bcm); -#else - bcm43xx_mmioprint_enable(bcm); -#endif return err; } @@ -3728,17 +3704,6 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, bcm->softmac = ieee80211_priv(net_dev); bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; -#ifdef DEBUG_ENABLE_MMIO_PRINT - bcm43xx_mmioprint_initial(bcm, 1); -#else - bcm43xx_mmioprint_initial(bcm, 0); -#endif -#ifdef DEBUG_ENABLE_PCILOG - bcm43xx_pciprint_initial(bcm, 1); -#else - bcm43xx_pciprint_initial(bcm, 0); -#endif - bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; bcm->pci_dev = pci_dev; bcm->net_dev = net_dev; -- cgit v1.2.2 From 73733847beead47dc31b1f8e1532e5eea9f8ddd3 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 12 Mar 2006 19:44:29 +0100 Subject: [PATCH] bcm43xx: fix some stuff, add a few missing mmiowb(), remove dead code. This may workaround the XMIT ERRORs some people are getting. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 23 +--- drivers/net/wireless/bcm43xx/bcm43xx_ilt.c | 42 +----- drivers/net/wireless/bcm43xx/bcm43xx_ilt.h | 6 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 76 +++++++---- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 187 ++++++++++++++------------- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 20 +-- 6 files changed, 167 insertions(+), 187 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index cab8e2ba4c..c07e34689b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -9,27 +9,10 @@ /* DMA-Interrupt reasons. */ -/*TODO: add the missing ones. */ -#define BCM43xx_DMAIRQ_ERR0 (1 << 10) -#define BCM43xx_DMAIRQ_ERR1 (1 << 11) -#define BCM43xx_DMAIRQ_ERR2 (1 << 12) -#define BCM43xx_DMAIRQ_ERR3 (1 << 13) -#define BCM43xx_DMAIRQ_ERR4 (1 << 14) -#define BCM43xx_DMAIRQ_ERR5 (1 << 15) +#define BCM43xx_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ + | (1 << 14) | (1 << 15)) +#define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13) #define BCM43xx_DMAIRQ_RX_DONE (1 << 16) -/* helpers */ -#define BCM43xx_DMAIRQ_ANYERR (BCM43xx_DMAIRQ_ERR0 | \ - BCM43xx_DMAIRQ_ERR1 | \ - BCM43xx_DMAIRQ_ERR2 | \ - BCM43xx_DMAIRQ_ERR3 | \ - BCM43xx_DMAIRQ_ERR4 | \ - BCM43xx_DMAIRQ_ERR5) -#define BCM43xx_DMAIRQ_FATALERR (BCM43xx_DMAIRQ_ERR0 | \ - BCM43xx_DMAIRQ_ERR1 | \ - BCM43xx_DMAIRQ_ERR2 | \ - BCM43xx_DMAIRQ_ERR4 | \ - BCM43xx_DMAIRQ_ERR5) -#define BCM43xx_DMAIRQ_NONFATALERR BCM43xx_DMAIRQ_ERR3 /* DMA controller register offsets. (relative to BCM43xx_DMA#_BASE) */ #define BCM43xx_DMA_TX_CONTROL 0x00 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c index 22587e0e1a..865ed5c336 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c @@ -312,20 +312,22 @@ const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = { /**** Helper functions to access the device Internal Lookup Tables ****/ -void bcm43xx_ilt_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) +void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val) { - if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); + mmiowb(); bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val); } else { bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); + mmiowb(); bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val); } } -u16 bcm43xx_ilt_read16(struct bcm43xx_private *bcm, u16 offset) +u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset) { - if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { + if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); } else { @@ -333,35 +335,3 @@ u16 bcm43xx_ilt_read16(struct bcm43xx_private *bcm, u16 offset) return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1); } } - -void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val) -{ - if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (u16)(val >> 16)); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, (u16)(val & 0x0000FFFF)); - } else { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (u16)(val >> 16)); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, (u16)(val & 0x0000FFFF)); - } -} - -u32 bcm43xx_ilt_read32(struct bcm43xx_private *bcm, u16 offset) -{ - u32 ret; - - if ( bcm->current_core->phy->type == BCM43xx_PHYTYPE_A ) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); - ret = bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA2); - ret <<= 16; - ret |= bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); - } else { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); - ret = bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA2); - ret <<= 16; - ret |= bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1); - } - - return ret; -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h index d92527fd83..464521abf7 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h @@ -26,9 +26,7 @@ extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE]; extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE]; -void bcm43xx_ilt_write16(struct bcm43xx_private *bcm, u16 offset, u16 val); -u16 bcm43xx_ilt_read16(struct bcm43xx_private *bcm, u16 offset); -void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val); -u32 bcm43xx_ilt_read32(struct bcm43xx_private *bcm, u16 offset); +void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val); +u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset); #endif /* BCM43xx_ILT_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index f3cef345c8..a563258cad 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -155,6 +155,7 @@ static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val) val = swab32(val); bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset); + mmiowb(); bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val); } @@ -225,9 +226,12 @@ void bcm43xx_shm_write32(struct bcm43xx_private *bcm, if (offset & 0x0003) { /* Unaligned access */ bcm43xx_shm_control_word(bcm, routing, offset >> 2); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, (value >> 16) & 0xffff); + mmiowb(); bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value & 0xffff); return; @@ -235,6 +239,7 @@ void bcm43xx_shm_write32(struct bcm43xx_private *bcm, offset >>= 2; } bcm43xx_shm_control_word(bcm, routing, offset); + mmiowb(); bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value); } @@ -246,6 +251,7 @@ void bcm43xx_shm_write16(struct bcm43xx_private *bcm, if (offset & 0x0003) { /* Unaligned access */ bcm43xx_shm_control_word(bcm, routing, offset >> 2); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, value); return; @@ -253,6 +259,7 @@ void bcm43xx_shm_write16(struct bcm43xx_private *bcm, offset >>= 2; } bcm43xx_shm_control_word(bcm, routing, offset); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value); } @@ -311,6 +318,7 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); status |= BCM43xx_SBF_TIME_UPDATE; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + mmiowb(); /* Be careful with the in-progress timer. * First zero out the low register, so we have a full @@ -320,9 +328,10 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) u32 lo = (tsf & 0x00000000FFFFFFFFULL); u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32; - barrier(); bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0); + mmiowb(); bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi); + mmiowb(); bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo); } else { u16 v0 = (tsf & 0x000000000000FFFFULL); @@ -330,11 +339,14 @@ void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32; u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48; - barrier(); bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0); } @@ -974,6 +986,7 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm->current_core->radio; unsigned int i, max_loop; u16 value = 0; u32 buffer[5] = { @@ -984,6 +997,13 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) 0x00000000, }; +/* FIXME: It seems like a dummy_transmission corrupts the DMA engines, + * once they are initialized. So avoid doing a dummy_transmission, + * if the DMA engines are running. + */ +if (bcm->initialized) +return; + switch (phy->type) { case BCM43xx_PHYTYPE_A: max_loop = 0x1E; @@ -1015,24 +1035,28 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) bcm43xx_write16(bcm, 0x0500, 0x0000); bcm43xx_write16(bcm, 0x0502, 0x0030); + if (radio->version == 0x2050 && radio->revision <= 0x5) + bcm43xx_radio_write16(bcm, 0x0051, 0x0017); for (i = 0x00; i < max_loop; i++) { value = bcm43xx_read16(bcm, 0x050E); - if ((value & 0x0080) != 0) + if (value & 0x0080) break; udelay(10); } for (i = 0x00; i < 0x0A; i++) { value = bcm43xx_read16(bcm, 0x050E); - if ((value & 0x0400) != 0) + if (value & 0x0400) break; udelay(10); } for (i = 0x00; i < 0x0A; i++) { value = bcm43xx_read16(bcm, 0x0690); - if ((value & 0x0100) == 0) + if (!(value & 0x0100)) break; udelay(10); } + if (radio->version == 0x2050 && radio->revision <= 0x5) + bcm43xx_radio_write16(bcm, 0x0051, 0x0037); } static void key_write(struct bcm43xx_private *bcm, @@ -1646,22 +1670,6 @@ static void handle_irq_beacon(struct bcm43xx_private *bcm) } } -/* Debug helper for irq bottom-half to print all reason registers. */ -#define bcmirq_print_reasons(description) \ - do { \ - dprintkl(KERN_ERR PFX description "\n" \ - KERN_ERR PFX " Generic Reason: 0x%08x\n" \ - KERN_ERR PFX " DMA reasons: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n" \ - KERN_ERR PFX " DMA TX status: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", \ - reason, \ - dma_reason[0], dma_reason[1], \ - dma_reason[2], dma_reason[3], \ - bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_BASE + BCM43xx_DMA_TX_STATUS), \ - bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_BASE + BCM43xx_DMA_TX_STATUS), \ - bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_BASE + BCM43xx_DMA_TX_STATUS), \ - bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_BASE + BCM43xx_DMA_TX_STATUS)); \ - } while (0) - /* Interrupt handler bottom-half */ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) { @@ -1690,9 +1698,30 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) * on DMA or PIO queues. * Maybe we get this in other error conditions, too. */ - bcmirq_print_reasons("XMIT ERROR"); + printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n"); bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR); } + if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_FATALMASK) | + (dma_reason[1] & BCM43xx_DMAIRQ_FATALMASK) | + (dma_reason[2] & BCM43xx_DMAIRQ_FATALMASK) | + (dma_reason[3] & BCM43xx_DMAIRQ_FATALMASK))) { + printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: " + "0x%08X, 0x%08X, 0x%08X, 0x%08X\n", + dma_reason[0], dma_reason[1], + dma_reason[2], dma_reason[3]); + bcm43xx_controller_restart(bcm, "DMA error"); + bcm43xx_unlock_mmio(bcm, flags); + return; + } + if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) | + (dma_reason[1] & BCM43xx_DMAIRQ_NONFATALMASK) | + (dma_reason[2] & BCM43xx_DMAIRQ_NONFATALMASK) | + (dma_reason[3] & BCM43xx_DMAIRQ_NONFATALMASK))) { + printkl(KERN_ERR PFX "DMA error: " + "0x%08X, 0x%08X, 0x%08X, 0x%08X\n", + dma_reason[0], dma_reason[1], + dma_reason[2], dma_reason[3]); + } if (reason & BCM43xx_IRQ_PS) { handle_irq_ps(bcm); @@ -1780,8 +1809,6 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) bcm43xx_unlock_mmio(bcm, flags); } -#undef bcmirq_print_reasons - static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason, u32 mask) { @@ -3875,6 +3902,7 @@ failure: void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) { bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); schedule_work(&bcm->restart_work); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index d3c2fc1df3..dbbef6ccd1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -126,6 +126,7 @@ u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset) void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val) { bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val); } @@ -255,16 +256,16 @@ static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) if (phy->rev == 1) offset = 0x4C00; - bcm43xx_ilt_write16(bcm, offset, 0x00FE); - bcm43xx_ilt_write16(bcm, offset + 1, 0x000D); - bcm43xx_ilt_write16(bcm, offset + 2, 0x0013); - bcm43xx_ilt_write16(bcm, offset + 3, 0x0019); + bcm43xx_ilt_write(bcm, offset, 0x00FE); + bcm43xx_ilt_write(bcm, offset + 1, 0x000D); + bcm43xx_ilt_write(bcm, offset + 2, 0x0013); + bcm43xx_ilt_write(bcm, offset + 3, 0x0019); if (phy->rev == 1) { - bcm43xx_ilt_write16(bcm, 0x1800, 0x2710); - bcm43xx_ilt_write16(bcm, 0x1801, 0x9B83); - bcm43xx_ilt_write16(bcm, 0x1802, 0x9B83); - bcm43xx_ilt_write16(bcm, 0x1803, 0x0F8D); + bcm43xx_ilt_write(bcm, 0x1800, 0x2710); + bcm43xx_ilt_write(bcm, 0x1801, 0x9B83); + bcm43xx_ilt_write(bcm, 0x1802, 0x9B83); + bcm43xx_ilt_write(bcm, 0x1803, 0x0F8D); bcm43xx_phy_write(bcm, 0x0455, 0x0004); } @@ -317,10 +318,10 @@ static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x048D, 0x0002); } - bcm43xx_ilt_write16(bcm, offset + 0x0800, 0); - bcm43xx_ilt_write16(bcm, offset + 0x0801, 7); - bcm43xx_ilt_write16(bcm, offset + 0x0802, 16); - bcm43xx_ilt_write16(bcm, offset + 0x0803, 28); + bcm43xx_ilt_write(bcm, offset + 0x0800, 0); + bcm43xx_ilt_write(bcm, offset + 0x0801, 7); + bcm43xx_ilt_write(bcm, offset + 0x0802, 16); + bcm43xx_ilt_write(bcm, offset + 0x0803, 28); } static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) @@ -337,11 +338,11 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0427, 0x001A); for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]); + bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]); for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]); + bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]); for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); + bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); } else { /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */ bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654); @@ -357,36 +358,36 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800); for (i = 0; i < 64; i++) - bcm43xx_ilt_write16(bcm, 0x4000 + i, i); + bcm43xx_ilt_write(bcm, 0x4000 + i, i); for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]); + bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]); } if (phy->rev <= 2) for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]); + bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]); else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200)) for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]); + bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]); else for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]); + bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]); if (phy->rev == 2) for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); + bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); else if ((phy->rev > 2) && (phy->rev <= 7)) for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]); + bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]); if (phy->rev == 1) { for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); + bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); for (i = 0; i < 4; i++) { - bcm43xx_ilt_write16(bcm, 0x5404 + i, 0x0020); - bcm43xx_ilt_write16(bcm, 0x5408 + i, 0x0020); - bcm43xx_ilt_write16(bcm, 0x540C + i, 0x0020); - bcm43xx_ilt_write16(bcm, 0x5410 + i, 0x0020); + bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020); + bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020); + bcm43xx_ilt_write(bcm, 0x540C + i, 0x0020); + bcm43xx_ilt_write(bcm, 0x5410 + i, 0x0020); } bcm43xx_phy_agcsetup(bcm); @@ -395,24 +396,24 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) (bcm->board_revision == 0x0017)) return; - bcm43xx_ilt_write16(bcm, 0x5001, 0x0002); - bcm43xx_ilt_write16(bcm, 0x5002, 0x0001); + bcm43xx_ilt_write(bcm, 0x5001, 0x0002); + bcm43xx_ilt_write(bcm, 0x5002, 0x0001); } else { for (i = 0; i <= 0x2F; i++) - bcm43xx_ilt_write16(bcm, 0x1000 + i, 0x0820); + bcm43xx_ilt_write(bcm, 0x1000 + i, 0x0820); bcm43xx_phy_agcsetup(bcm); bcm43xx_phy_read(bcm, 0x0400); /* dummy read */ bcm43xx_phy_write(bcm, 0x0403, 0x1000); - bcm43xx_ilt_write16(bcm, 0x3C02, 0x000F); - bcm43xx_ilt_write16(bcm, 0x3C03, 0x0014); + bcm43xx_ilt_write(bcm, 0x3C02, 0x000F); + bcm43xx_ilt_write(bcm, 0x3C03, 0x0014); if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && (bcm->board_type == 0x0416) && (bcm->board_revision == 0x0017)) return; - bcm43xx_ilt_write16(bcm, 0x0401, 0x0002); - bcm43xx_ilt_write16(bcm, 0x0402, 0x0001); + bcm43xx_ilt_write(bcm, 0x0401, 0x0002); + bcm43xx_ilt_write(bcm, 0x0402, 0x0001); } } @@ -456,11 +457,11 @@ static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x0035, 0x03FF); bcm43xx_phy_write(bcm, 0x0036, 0x0400); - bcm43xx_ilt_write16(bcm, 0x3807, 0x0051); + bcm43xx_ilt_write(bcm, 0x3807, 0x0051); bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); - bcm43xx_ilt_write16(bcm, 0x3C0C, 0x07BF); + bcm43xx_ilt_write(bcm, 0x3C0C, 0x07BF); bcm43xx_radio_write16(bcm, 0x0002, 0x07BF); bcm43xx_phy_write(bcm, 0x0024, 0x4680); @@ -472,47 +473,47 @@ static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF); bcm43xx_phy_write(bcm, 0x008E, 0x58C1); - bcm43xx_ilt_write16(bcm, 0x0803, 0x000F); - bcm43xx_ilt_write16(bcm, 0x0804, 0x001F); - bcm43xx_ilt_write16(bcm, 0x0805, 0x002A); - bcm43xx_ilt_write16(bcm, 0x0805, 0x0030); - bcm43xx_ilt_write16(bcm, 0x0807, 0x003A); + bcm43xx_ilt_write(bcm, 0x0803, 0x000F); + bcm43xx_ilt_write(bcm, 0x0804, 0x001F); + bcm43xx_ilt_write(bcm, 0x0805, 0x002A); + bcm43xx_ilt_write(bcm, 0x0805, 0x0030); + bcm43xx_ilt_write(bcm, 0x0807, 0x003A); - bcm43xx_ilt_write16(bcm, 0x0000, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0001, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0002, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0003, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0004, 0x0015); - bcm43xx_ilt_write16(bcm, 0x0005, 0x0015); - bcm43xx_ilt_write16(bcm, 0x0006, 0x0019); + bcm43xx_ilt_write(bcm, 0x0000, 0x0013); + bcm43xx_ilt_write(bcm, 0x0001, 0x0013); + bcm43xx_ilt_write(bcm, 0x0002, 0x0013); + bcm43xx_ilt_write(bcm, 0x0003, 0x0013); + bcm43xx_ilt_write(bcm, 0x0004, 0x0015); + bcm43xx_ilt_write(bcm, 0x0005, 0x0015); + bcm43xx_ilt_write(bcm, 0x0006, 0x0019); - bcm43xx_ilt_write16(bcm, 0x0404, 0x0003); - bcm43xx_ilt_write16(bcm, 0x0405, 0x0003); - bcm43xx_ilt_write16(bcm, 0x0406, 0x0007); + bcm43xx_ilt_write(bcm, 0x0404, 0x0003); + bcm43xx_ilt_write(bcm, 0x0405, 0x0003); + bcm43xx_ilt_write(bcm, 0x0406, 0x0007); for (i = 0; i < 16; i++) - bcm43xx_ilt_write16(bcm, 0x4000 + i, (0x8 + i) & 0x000F); + bcm43xx_ilt_write(bcm, 0x4000 + i, (0x8 + i) & 0x000F); - bcm43xx_ilt_write16(bcm, 0x3003, 0x1044); - bcm43xx_ilt_write16(bcm, 0x3004, 0x7201); - bcm43xx_ilt_write16(bcm, 0x3006, 0x0040); - bcm43xx_ilt_write16(bcm, 0x3001, (bcm43xx_ilt_read16(bcm, 0x3001) & 0x0010) | 0x0008); + bcm43xx_ilt_write(bcm, 0x3003, 0x1044); + bcm43xx_ilt_write(bcm, 0x3004, 0x7201); + bcm43xx_ilt_write(bcm, 0x3006, 0x0040); + bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008); for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]); + bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]); for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]); + bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]); for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); + bcm43xx_ilt_write(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); bcm43xx_phy_init_noisescaletbl(bcm); for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); + bcm43xx_ilt_write(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); break; case 3: for (i = 0; i < 64; i++) - bcm43xx_ilt_write16(bcm, 0x4000 + i, i); + bcm43xx_ilt_write(bcm, 0x4000 + i, i); - bcm43xx_ilt_write16(bcm, 0x3807, 0x0051); + bcm43xx_ilt_write(bcm, 0x3807, 0x0051); bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); @@ -524,35 +525,35 @@ static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x001F, 0x1C00); bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400); - bcm43xx_ilt_write16(bcm, 0x3001, (bcm43xx_ilt_read16(bcm, 0x3001) & 0x0010) | 0x0008); + bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008); for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]); + bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]); bcm43xx_phy_init_noisescaletbl(bcm); for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write16(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); + bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); bcm43xx_phy_write(bcm, 0x0003, 0x1808); - bcm43xx_ilt_write16(bcm, 0x0803, 0x000F); - bcm43xx_ilt_write16(bcm, 0x0804, 0x001F); - bcm43xx_ilt_write16(bcm, 0x0805, 0x002A); - bcm43xx_ilt_write16(bcm, 0x0805, 0x0030); - bcm43xx_ilt_write16(bcm, 0x0807, 0x003A); - - bcm43xx_ilt_write16(bcm, 0x0000, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0001, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0002, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0003, 0x0013); - bcm43xx_ilt_write16(bcm, 0x0004, 0x0015); - bcm43xx_ilt_write16(bcm, 0x0005, 0x0015); - bcm43xx_ilt_write16(bcm, 0x0006, 0x0019); - - bcm43xx_ilt_write16(bcm, 0x0404, 0x0003); - bcm43xx_ilt_write16(bcm, 0x0405, 0x0003); - bcm43xx_ilt_write16(bcm, 0x0406, 0x0007); - - bcm43xx_ilt_write16(bcm, 0x3C02, 0x000F); - bcm43xx_ilt_write16(bcm, 0x3C03, 0x0014); + bcm43xx_ilt_write(bcm, 0x0803, 0x000F); + bcm43xx_ilt_write(bcm, 0x0804, 0x001F); + bcm43xx_ilt_write(bcm, 0x0805, 0x002A); + bcm43xx_ilt_write(bcm, 0x0805, 0x0030); + bcm43xx_ilt_write(bcm, 0x0807, 0x003A); + + bcm43xx_ilt_write(bcm, 0x0000, 0x0013); + bcm43xx_ilt_write(bcm, 0x0001, 0x0013); + bcm43xx_ilt_write(bcm, 0x0002, 0x0013); + bcm43xx_ilt_write(bcm, 0x0003, 0x0013); + bcm43xx_ilt_write(bcm, 0x0004, 0x0015); + bcm43xx_ilt_write(bcm, 0x0005, 0x0015); + bcm43xx_ilt_write(bcm, 0x0006, 0x0019); + + bcm43xx_ilt_write(bcm, 0x0404, 0x0003); + bcm43xx_ilt_write(bcm, 0x0405, 0x0003); + bcm43xx_ilt_write(bcm, 0x0406, 0x0007); + + bcm43xx_ilt_write(bcm, 0x3C02, 0x000F); + bcm43xx_ilt_write(bcm, 0x3C03, 0x0014); break; default: assert(0); @@ -598,19 +599,19 @@ static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x0019, 0x0000); bcm43xx_radio_write16(bcm, 0x0017, 0x0020); - tval = bcm43xx_ilt_read16(bcm, 0x3001); + tval = bcm43xx_ilt_read(bcm, 0x3001); if (phy->rev == 1) { - bcm43xx_ilt_write16(bcm, 0x3001, - (bcm43xx_ilt_read16(bcm, 0x3001) & 0xFF87) - | 0x0058); + bcm43xx_ilt_write(bcm, 0x3001, + (bcm43xx_ilt_read(bcm, 0x3001) & 0xFF87) + | 0x0058); } else { - bcm43xx_ilt_write16(bcm, 0x3001, - (bcm43xx_ilt_read16(bcm, 0x3001) & 0xFFC3) - | 0x002C); + bcm43xx_ilt_write(bcm, 0x3001, + (bcm43xx_ilt_read(bcm, 0x3001) & 0xFFC3) + | 0x002C); } bcm43xx_dummy_transmission(bcm); phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL); - bcm43xx_ilt_write16(bcm, 0x3001, tval); + bcm43xx_ilt_write(bcm, 0x3001, tval); bcm43xx_radio_set_txpower_a(bcm, 0x0018); } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 3901aa9946..4d3b0e8587 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -97,6 +97,7 @@ void bcm43xx_radio_lock(struct bcm43xx_private *bcm) status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); status |= BCM43xx_SBF_RADIOREG_LOCK; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + mmiowb(); udelay(10); } @@ -108,6 +109,7 @@ void bcm43xx_radio_unlock(struct bcm43xx_private *bcm) status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); status &= ~BCM43xx_SBF_RADIOREG_LOCK; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); + mmiowb(); } u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset) @@ -142,6 +144,7 @@ u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset) void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) { bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset); + mmiowb(); bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val); } @@ -161,10 +164,10 @@ static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm, } for (i = 0; i < 4; i++) - bcm43xx_ilt_write16(bcm, offset + i, first); + bcm43xx_ilt_write(bcm, offset + i, first); for (i = start; i < end; i++) - bcm43xx_ilt_write16(bcm, offset + i, second); + bcm43xx_ilt_write(bcm, offset + i, second); if (third != -1) { tmp = ((u16)third << 14) | ((u16)third << 6); @@ -196,11 +199,11 @@ static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm) tmp |= (i & 0x0001) << 1; tmp |= (i & 0x0002) >> 1; - bcm43xx_ilt_write16(bcm, offset + i, tmp); + bcm43xx_ilt_write(bcm, offset + i, tmp); } for (i = start; i < end; i++) - bcm43xx_ilt_write16(bcm, offset + i, i - start); + bcm43xx_ilt_write(bcm, offset + i, i - start); bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040); @@ -316,6 +319,7 @@ u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm) void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val) { bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset); + mmiowb(); bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val); } @@ -612,10 +616,6 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) } break; case BCM43xx_PHYTYPE_G: -//FIXME: Something is broken here. This is called when enabling WLAN interfmode. -// If this is done at runtime, I get an XMIT ERROR and transmission is -// broken. I guess some important register is overwritten by accident. -// The XMIT ERROR comes from the dummy_transmissions in set_gains. if (radio->revision >= 9) return; if (radio->revision == 8) @@ -1641,14 +1641,14 @@ void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) base &= 0x000F; bcm43xx_phy_write(bcm, 0x0017, base | 0x0020); - ilt = bcm43xx_ilt_read16(bcm, 0x3001); + ilt = bcm43xx_ilt_read(bcm, 0x3001); ilt &= 0x0007; dac = bcm43xx_get_txgain_dac(txpower); dac <<= 3; dac |= ilt; - bcm43xx_ilt_write16(bcm, 0x3001, dac); + bcm43xx_ilt_write(bcm, 0x3001, dac); bcm->current_core->radio->txpower[0] = txpower; -- cgit v1.2.2 From e1b1b581b847a5ae9409a02a586476eaba2b3f89 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 13 Mar 2006 15:20:05 +0100 Subject: [PATCH] bcm43xx: receive TX status on MMIO or DMA unconditionally regarding the 80211 core rev. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index a563258cad..3ab02f4f8e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1765,22 +1765,17 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) /* We intentionally don't set "activity" to 1, here. */ } if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { - if (likely(bcm->current_core->rev < 5)) { - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_rx(bcm->current_core->pio->queue3); - else - bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1); - activity = 1; - } else - assert(0); + if (bcm43xx_using_pio(bcm)) + bcm43xx_pio_rx(bcm->current_core->pio->queue3); + else + bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1); + activity = 1; } bcmirq_handled(BCM43xx_IRQ_RX); if (reason & BCM43xx_IRQ_XMIT_STATUS) { - if (bcm->current_core->rev >= 5) { - handle_irq_transmit_status(bcm); - activity = 1; - } + handle_irq_transmit_status(bcm); + activity = 1; //TODO: In AP mode, this also causes sending of powersave responses. bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS); } -- cgit v1.2.2 From aae3778176ec7a57b1c4f539b7252acfd7d99a1b Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 13 Mar 2006 15:54:56 +0100 Subject: [PATCH] bcm43xx: add functions bcm43xx_dma_read/write, bcm43xx_dma_tx_suspend/resume. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 61 ++++++++++++++++-------------- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 18 +++++++++ 2 files changed, 51 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 0cd2928479..fbe19b922a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -374,13 +374,11 @@ static int dmacontroller_setup(struct bcm43xx_dmaring *ring) if (ring->tx) { /* Set Transmit Control register to "transmit enable" */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_TX_CONTROL, - BCM43xx_DMA_TXCTRL_ENABLE); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, + BCM43xx_DMA_TXCTRL_ENABLE); /* Set Transmit Descriptor ring address. */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_TX_DESC_RING, - ring->dmabase + ring->memoffset); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, + ring->dmabase + ring->memoffset); } else { err = alloc_initial_descbuffers(ring); if (err) @@ -388,17 +386,12 @@ static int dmacontroller_setup(struct bcm43xx_dmaring *ring) /* Set Receive Control "receive enable" and frame offset */ value = (ring->frameoffset << BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT); value |= BCM43xx_DMA_RXCTRL_ENABLE; - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_RX_CONTROL, - value); + bcm43xx_dma_write(ring, BCM43xx_DMA_RX_CONTROL, value); /* Set Receive Descriptor ring address. */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_RX_DESC_RING, - ring->dmabase + ring->memoffset); + bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, + ring->dmabase + ring->memoffset); /* Init the descriptor pointer. */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_RX_DESC_INDEX, - 200); + bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, 200); } out: @@ -411,15 +404,11 @@ static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring) if (ring->tx) { bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base); /* Zero out Transmit Descriptor ring address. */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_TX_DESC_RING, - 0x00000000); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, 0); } else { bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base); /* Zero out Receive Descriptor ring address. */ - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_RX_DESC_RING, - 0x00000000); + bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, 0); } } @@ -698,9 +687,8 @@ static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, */ wmb(); slot = next_slot(ring, slot); - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_TX_DESC_INDEX, - (u32)(slot * sizeof(struct bcm43xx_dmadesc))); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_INDEX, + (u32)(slot * sizeof(struct bcm43xx_dmadesc))); } static int dma_tx_fragment(struct bcm43xx_dmaring *ring, @@ -940,7 +928,7 @@ void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) #endif assert(!ring->tx); - status = bcm43xx_read32(ring->bcm, ring->mmio_base + BCM43xx_DMA_RX_STATUS); + status = bcm43xx_dma_read(ring, BCM43xx_DMA_RX_STATUS); descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK); current_slot = descptr / sizeof(struct bcm43xx_dmadesc); assert(current_slot >= 0 && current_slot < ring->nr_slots); @@ -953,10 +941,27 @@ void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) ring->max_used_slots = used_slots; #endif } - bcm43xx_write32(ring->bcm, - ring->mmio_base + BCM43xx_DMA_RX_DESC_INDEX, - (u32)(slot * sizeof(struct bcm43xx_dmadesc))); + bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, + (u32)(slot * sizeof(struct bcm43xx_dmadesc))); ring->current_slot = slot; } +void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) +{ + assert(ring->tx); + bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, + bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL) + | BCM43xx_DMA_TXCTRL_SUSPEND); +} + +void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) +{ + assert(ring->tx); + bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, + bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL) + & ~BCM43xx_DMA_TXCTRL_SUSPEND); + bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1); +} + /* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index c07e34689b..2d520e4b02 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -140,6 +140,21 @@ struct bcm43xx_dmaring { }; +static inline +u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring, + u16 offset) +{ + return bcm43xx_read32(ring->bcm, ring->mmio_base + offset); +} + +static inline +void bcm43xx_dma_write(struct bcm43xx_dmaring *ring, + u16 offset, u32 value) +{ + bcm43xx_write32(ring->bcm, ring->mmio_base + offset, value); +} + + int bcm43xx_dma_init(struct bcm43xx_private *bcm); void bcm43xx_dma_free(struct bcm43xx_private *bcm); @@ -148,6 +163,9 @@ int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, u16 dmacontroller_mmio_base); +void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring); +void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring); + void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, struct bcm43xx_xmitstatus *status); -- cgit v1.2.2 From e9357c056c5e62516f0044e60591d41f00ca7cfa Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 13 Mar 2006 19:27:34 +0100 Subject: [PATCH] bcm43xx: reduce the size of bcm43xx_private by removing unneeded members. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 94 ++++++---- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 7 +- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 9 +- drivers/net/wireless/bcm43xx/bcm43xx_ilt.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 238 ++++++++++++------------- drivers/net/wireless/bcm43xx/bcm43xx_main.h | 6 +- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 128 ++++++------- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 8 +- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 72 ++++---- drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 35 ++-- drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 14 +- 13 files changed, 320 insertions(+), 301 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 29c95b0712..a358646ad3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -556,33 +556,37 @@ struct bcm43xx_pio { #define BCM43xx_MAX_80211_CORES 2 -#define BCM43xx_COREFLAG_AVAILABLE (1 << 0) -#define BCM43xx_COREFLAG_ENABLED (1 << 1) -#define BCM43xx_COREFLAG_INITIALIZED (1 << 2) - #ifdef CONFIG_BCM947XX #define core_offset(bcm) (bcm)->current_core_offset #else #define core_offset(bcm) 0 #endif +/* Generic information about a core. */ struct bcm43xx_coreinfo { - /** Driver internal flags. See BCM43xx_COREFLAG_* */ - u32 flags; + u8 available:1, + enabled:1, + initialized:1; /** core_id ID number */ u16 id; /** core_rev revision number */ u8 rev; /** Index number for _switch_core() */ u8 index; - /* Pointer to the PHYinfo, which belongs to this core (if 80211 core) */ - struct bcm43xx_phyinfo *phy; - /* Pointer to the RadioInfo, which belongs to this core (if 80211 core) */ - struct bcm43xx_radioinfo *radio; - /* Pointer to the DMA rings, which belong to this core (if 80211 core) */ - struct bcm43xx_dma *dma; - /* Pointer to the PIO queues, which belong to this core (if 80211 core) */ - struct bcm43xx_pio *pio; +}; + +/* Additional information for each 80211 core. */ +struct bcm43xx_coreinfo_80211 { + /* PHY device. */ + struct bcm43xx_phyinfo phy; + /* Radio device. */ + struct bcm43xx_radioinfo radio; + union { + /* DMA context. */ + struct bcm43xx_dma dma; + /* PIO context. */ + struct bcm43xx_pio pio; + }; }; /* Context information for a noise calculation (Link Quality). */ @@ -652,7 +656,7 @@ struct bcm43xx_private { #define BCM43xx_NR_LEDS 4 struct bcm43xx_led leds[BCM43xx_NR_LEDS]; - /* The currently active core. NULL if not initialized, yet. */ + /* The currently active core. */ struct bcm43xx_coreinfo *current_core; #ifdef CONFIG_BCM947XX /** current core memory offset */ @@ -665,18 +669,15 @@ struct bcm43xx_private { */ struct bcm43xx_coreinfo core_chipcommon; struct bcm43xx_coreinfo core_pci; - struct bcm43xx_coreinfo core_v90; - struct bcm43xx_coreinfo core_pcmcia; - struct bcm43xx_coreinfo core_ethernet; struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ]; - /* Info about the PHY for each 80211 core. */ - struct bcm43xx_phyinfo phy[ BCM43xx_MAX_80211_CORES ]; - /* Info about the Radio for each 80211 core. */ - struct bcm43xx_radioinfo radio[ BCM43xx_MAX_80211_CORES ]; - /* DMA */ - struct bcm43xx_dma dma[ BCM43xx_MAX_80211_CORES ]; - /* PIO */ - struct bcm43xx_pio pio[ BCM43xx_MAX_80211_CORES ]; + /* Additional information, specific to the 80211 cores. */ + struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ]; + /* Index of the current 80211 core. If current_core is not + * an 80211 core, this is -1. + */ + int current_80211_core_idx; + /* Number of available 80211 cores. */ + int nr_80211_available; u32 chipcommon_capabilities; @@ -769,18 +770,39 @@ int bcm43xx_using_pio(struct bcm43xx_private *bcm) # error "Using neither DMA nor PIO? Confused..." #endif - +/* Helper functions to access data structures private to the 80211 cores. + * Note that we _must_ have an 80211 core mapped when calling + * any of these functions. + */ static inline -int bcm43xx_num_80211_cores(struct bcm43xx_private *bcm) +struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm) { - int i, cnt = 0; - - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - if (bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE) - cnt++; - } - - return cnt; + assert(bcm43xx_using_pio(bcm)); + assert(bcm->current_80211_core_idx >= 0); + assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); + return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio); +} +static inline +struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm) +{ + assert(!bcm43xx_using_pio(bcm)); + assert(bcm->current_80211_core_idx >= 0); + assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); + return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma); +} +static inline +struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm) +{ + assert(bcm->current_80211_core_idx >= 0); + assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); + return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy); +} +static inline +struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm) +{ + assert(bcm->current_80211_core_idx >= 0); + assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); + return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio); } /* Are we running in init_board() context? */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index bcfcebe282..f73d36b8e0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -104,16 +104,13 @@ static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, fappend("\nCores:\n"); #define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, " \ "rev: 0x%02x, index: 0x%02x\n", \ - (info).flags & BCM43xx_COREFLAG_AVAILABLE \ + (info).available \ ? "available" : "nonavailable", \ - (info).flags & BCM43xx_COREFLAG_ENABLED \ + (info).enabled \ ? "enabled" : "disabled", \ (info).id, (info).rev, (info).index) fappend_core("CHIPCOMMON", bcm->core_chipcommon); fappend_core("PCI", bcm->core_pci); - fappend_core("V90", bcm->core_v90); - fappend_core("PCMCIA", bcm->core_pcmcia); - fappend_core("ETHERNET", bcm->core_ethernet); fappend_core("first 80211", bcm->core_80211[0]); fappend_core("second 80211", bcm->core_80211[1]); #undef fappend_core diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index fbe19b922a..7ed368a587 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -531,7 +531,7 @@ static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring) void bcm43xx_dma_free(struct bcm43xx_private *bcm) { - struct bcm43xx_dma *dma = bcm->current_core->dma; + struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); bcm43xx_destroy_dmaring(dma->rx_ring1); dma->rx_ring1 = NULL; @@ -549,7 +549,7 @@ void bcm43xx_dma_free(struct bcm43xx_private *bcm) int bcm43xx_dma_init(struct bcm43xx_private *bcm) { - struct bcm43xx_dma *dma = bcm->current_core->dma; + struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); struct bcm43xx_dmaring *ring; int err = -ENOMEM; @@ -652,7 +652,7 @@ static struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, u16 cookie, int *slot) { - struct bcm43xx_dma *dma = bcm->current_core->dma; + struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); struct bcm43xx_dmaring *ring = NULL; switch (cookie & 0xF000) { @@ -755,7 +755,7 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, * the device to send the stuff. * Note that this is called from atomic context. */ - struct bcm43xx_dmaring *ring = bcm->current_core->dma->tx_ring1; + struct bcm43xx_dmaring *ring = bcm43xx_current_dma(bcm)->tx_ring1; u8 i; struct sk_buff *skb; @@ -784,6 +784,7 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, struct bcm43xx_xmitstatus *status) { + struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); struct bcm43xx_dmaring *ring; struct bcm43xx_dmadesc *desc; struct bcm43xx_dmadesc_meta *meta; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c index 865ed5c336..ad8e569d1f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c @@ -314,7 +314,7 @@ const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = { void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); mmiowb(); bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val); @@ -327,7 +327,7 @@ void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val) u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) { + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); } else { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 949555da5a..72a243aac6 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -171,8 +171,8 @@ void bcm43xx_leds_exit(struct bcm43xx_private *bcm) void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) { struct bcm43xx_led *led; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES; int i, turn_on; unsigned long interval = 0; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 3ab02f4f8e..88e9a125c2 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -406,7 +406,7 @@ static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm) static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) { /* slot_time is in usec. */ - if (bcm->current_core->phy->type != BCM43xx_PHYTYPE_G) + if (bcm43xx_current_phy(bcm)->type != BCM43xx_PHYTYPE_G) return; bcm43xx_write16(bcm, 0x684, 510 + slot_time); bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time); @@ -443,7 +443,7 @@ static void bcm43xx_disassociate(struct bcm43xx_private *bcm) bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff); - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G && + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G && ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate)) bcm43xx_short_slot_timing_enable(bcm); @@ -510,8 +510,8 @@ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *old static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u32 radio_id; u16 manufact; u16 version; @@ -566,10 +566,10 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) radio->txpower[2] = 3; else radio->txpower[2] = 0; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (phy->type == BCM43xx_PHYTYPE_A) radio->txpower_desired = bcm->sprom.maxpower_aphy; else - bcm->current_core->radio->txpower_desired = bcm->sprom.maxpower_bgphy; + radio->txpower_desired = bcm->sprom.maxpower_bgphy; /* Initialize the in-memory nrssi Lookup Table. */ for (i = 0; i < 64; i++) @@ -929,15 +929,14 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) struct ieee80211_geo geo; struct ieee80211_channel *chan; int have_a = 0, have_bg = 0; - int i, num80211; + int i; u8 channel; struct bcm43xx_phyinfo *phy; const char *iso_country; memset(&geo, 0, sizeof(geo)); - num80211 = bcm43xx_num_80211_cores(bcm); - for (i = 0; i < num80211; i++) { - phy = bcm->phy + i; + for (i = 0; i < bcm->nr_80211_available; i++) { + phy = &(bcm->core_80211_ext[i].phy); switch (phy->type) { case BCM43xx_PHYTYPE_B: case BCM43xx_PHYTYPE_G: @@ -985,8 +984,8 @@ static void bcm43xx_geo_init(struct bcm43xx_private *bcm) */ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); unsigned int i, max_loop; u16 value = 0; u32 buffer[5] = { @@ -1213,14 +1212,20 @@ int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *ne if (unlikely(!new_core)) return 0; - if (!(new_core->flags & BCM43xx_COREFLAG_AVAILABLE)) + if (!new_core->available) return -ENODEV; if (bcm->current_core == new_core) return 0; err = _switch_core(bcm, new_core->index); - if (likely(!err)) - bcm->current_core = new_core; + if (unlikely(err)) + goto out; + bcm->current_core = new_core; + bcm->current_80211_core_idx = -1; + if (new_core->id == BCM43xx_COREID_80211) + bcm->current_80211_core_idx = (int)(new_core - &(bcm->core_80211[0])); + +out: return err; } @@ -1295,7 +1300,8 @@ static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags) bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); out: - bcm->current_core->flags &= ~ BCM43xx_COREFLAG_ENABLED; + bcm->current_core->enabled = 0; + return 0; } @@ -1340,7 +1346,7 @@ static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags) bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); udelay(1); - bcm->current_core->flags |= BCM43xx_COREFLAG_ENABLED; + bcm->current_core->enabled = 1; assert(err == 0); out: return err; @@ -1411,7 +1417,7 @@ static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm, bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); udelay(1); - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G) { old_core = bcm->current_core; err = bcm43xx_switch_core(bcm, active_80211_core); if (err) @@ -1433,9 +1439,6 @@ static void handle_irq_transmit_status(struct bcm43xx_private *bcm) u16 tmp; struct bcm43xx_xmitstatus stat; - assert(bcm->current_core->id == BCM43xx_COREID_80211); - assert(bcm->current_core->rev >= 5); - while (1) { v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0); if (!v0) @@ -1473,7 +1476,7 @@ static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4)); assert(bcm->noisecalc.core_at_start == bcm->current_core); - assert(bcm->noisecalc.channel_at_start == bcm->current_core->radio->channel); + assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel); } static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) @@ -1483,7 +1486,7 @@ static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) if (bcm->noisecalc.calculation_running) return; bcm->noisecalc.core_at_start = bcm->current_core; - bcm->noisecalc.channel_at_start = bcm->current_core->radio->channel; + bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel; bcm->noisecalc.calculation_running = 1; bcm->noisecalc.nr_samples = 0; @@ -1492,7 +1495,7 @@ static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) static void handle_irq_noise(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 tmp; u8 noise[4]; u8 i, j; @@ -1759,16 +1762,16 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_rx(bcm->current_core->pio->queue0); + bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0); else - bcm43xx_dma_rx(bcm->current_core->dma->rx_ring0); + bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0); /* We intentionally don't set "activity" to 1, here. */ } if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_rx(bcm->current_core->pio->queue3); + bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3); else - bcm43xx_dma_rx(bcm->current_core->dma->rx_ring1); + bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring1); activity = 1; } bcmirq_handled(BCM43xx_IRQ_RX); @@ -1911,7 +1914,7 @@ static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u8 rev = bcm->current_core->rev; int err = 0; int nr; @@ -2349,6 +2352,8 @@ static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm) */ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); int err; int iw_mode = bcm->ieee->iw_mode; int tmp; @@ -2388,13 +2393,13 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) goto err_radio_off; /* Select initial Interference Mitigation. */ - tmp = bcm->current_core->radio->interfmode; - bcm->current_core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; + tmp = radio->interfmode; + radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; bcm43xx_radio_set_interference_mitigation(bcm, tmp); bcm43xx_phy_set_antenna_diversity(bcm); bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT); - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) { + if (phy->type == BCM43xx_PHYTYPE_B) { value16 = bcm43xx_read16(bcm, 0x005E); value16 |= 0x0004; bcm43xx_write16(bcm, 0x005E, value16); @@ -2512,6 +2517,32 @@ error: return -ENODEV; } +void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy) +{ + /* Initialize a "phyinfo" structure. The structure is already + * zeroed out. + */ + phy->antenna_diversity = 0xFFFF; + phy->savedpctlreg = 0xFFFF; + phy->minlowsig[0] = 0xFFFF; + phy->minlowsig[1] = 0xFFFF; + spin_lock_init(&phy->lock); +} + +void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio) +{ + /* Initialize a "radioinfo" structure. The structure is already + * zeroed out. + */ + radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; + radio->channel = 0xFF; + radio->initial_channel = 0xFF; + radio->lofcal = 0xFFFF; + radio->initval = 0xFFFF; + radio->nrssi[0] = -1000; + radio->nrssi[1] = -1000; +} + static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) { int err, i; @@ -2523,15 +2554,14 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo)); memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo)); - memset(&bcm->core_v90, 0, sizeof(struct bcm43xx_coreinfo)); - memset(&bcm->core_pcmcia, 0, sizeof(struct bcm43xx_coreinfo)); memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo) * BCM43xx_MAX_80211_CORES); - - memset(&bcm->phy, 0, sizeof(struct bcm43xx_phyinfo) - * BCM43xx_MAX_80211_CORES); - memset(&bcm->radio, 0, sizeof(struct bcm43xx_radioinfo) - * BCM43xx_MAX_80211_CORES); + memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211) + * BCM43xx_MAX_80211_CORES); + bcm->current_80211_core_idx = -1; + bcm->nr_80211_available = 0; + bcm->current_core = NULL; + bcm->active_80211_core = NULL; /* map core 0 */ err = _switch_core(bcm, 0); @@ -2549,7 +2579,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) if (core_id == BCM43xx_COREID_CHIPCOMMON) { chip_id_32 = bcm43xx_read32(bcm, 0); chip_id_16 = chip_id_32 & 0xFFFF; - bcm->core_chipcommon.flags |= BCM43xx_COREFLAG_AVAILABLE; + bcm->core_chipcommon.available = 1; bcm->core_chipcommon.id = core_id; bcm->core_chipcommon.rev = core_rev; bcm->core_chipcommon.index = 0; @@ -2618,18 +2648,19 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n", bcm->chip_id, bcm->chip_rev); dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count); - if (bcm->core_chipcommon.flags & BCM43xx_COREFLAG_AVAILABLE) { + if (bcm->core_chipcommon.available) { dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n", core_id, core_rev, core_vendor, bcm43xx_core_enabled(bcm) ? "enabled" : "disabled"); } - if (bcm->core_chipcommon.flags & BCM43xx_COREFLAG_AVAILABLE) + if (bcm->core_chipcommon.available) current_core = 1; else current_core = 0; for ( ; current_core < core_count; current_core++) { struct bcm43xx_coreinfo *core; + struct bcm43xx_coreinfo_80211 *ext_80211; err = _switch_core(bcm, current_core); if (err) @@ -2651,36 +2682,16 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) switch (core_id) { case BCM43xx_COREID_PCI: core = &bcm->core_pci; - if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { + if (core->available) { printk(KERN_WARNING PFX "Multiple PCI cores found.\n"); continue; } break; - case BCM43xx_COREID_V90: - core = &bcm->core_v90; - if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { - printk(KERN_WARNING PFX "Multiple V90 cores found.\n"); - continue; - } - break; - case BCM43xx_COREID_PCMCIA: - core = &bcm->core_pcmcia; - if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { - printk(KERN_WARNING PFX "Multiple PCMCIA cores found.\n"); - continue; - } - break; - case BCM43xx_COREID_ETHERNET: - core = &bcm->core_ethernet; - if (core->flags & BCM43xx_COREFLAG_AVAILABLE) { - printk(KERN_WARNING PFX "Multiple Ethernet cores found.\n"); - continue; - } - break; case BCM43xx_COREID_80211: for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { core = &(bcm->core_80211[i]); - if (!(core->flags & BCM43xx_COREFLAG_AVAILABLE)) + ext_80211 = &(bcm->core_80211_ext[i]); + if (!core->available) break; core = NULL; } @@ -2715,40 +2726,23 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) err = -ENODEV; goto out; } - core->phy = &bcm->phy[i]; - core->phy->antenna_diversity = 0xffff; - core->phy->savedpctlreg = 0xFFFF; - core->phy->minlowsig[0] = 0xFFFF; - core->phy->minlowsig[1] = 0xFFFF; - core->phy->minlowsigpos[0] = 0; - core->phy->minlowsigpos[1] = 0; - spin_lock_init(&core->phy->lock); - core->radio = &bcm->radio[i]; - core->radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; - core->radio->channel = 0xFF; - core->radio->initial_channel = 0xFF; - core->radio->lofcal = 0xFFFF; - core->radio->initval = 0xFFFF; - core->radio->nrssi[0] = -1000; - core->radio->nrssi[1] = -1000; - core->dma = &bcm->dma[i]; - core->pio = &bcm->pio[i]; + bcm->nr_80211_available++; + bcm43xx_init_struct_phyinfo(&ext_80211->phy); + bcm43xx_init_struct_radioinfo(&ext_80211->radio); break; case BCM43xx_COREID_CHIPCOMMON: printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n"); break; - default: - printk(KERN_WARNING PFX "Unknown core found (ID 0x%x)\n", core_id); } if (core) { - core->flags |= BCM43xx_COREFLAG_AVAILABLE; + core->available = 1; core->id = core_id; core->rev = core_rev; core->index = current_core; } } - if (!(bcm->core_80211[0].flags & BCM43xx_COREFLAG_AVAILABLE)) { + if (!bcm->core_80211[0].available) { printk(KERN_ERR PFX "Error: No 80211 core found!\n"); err = -ENODEV; goto out; @@ -2802,7 +2796,7 @@ static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm, static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm) { - switch (bcm->current_core->phy->type) { + switch (bcm43xx_current_phy(bcm)->type) { case BCM43xx_PHYTYPE_A: case BCM43xx_PHYTYPE_G: bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1); @@ -2829,12 +2823,14 @@ static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm) bcm43xx_pio_free(bcm); bcm43xx_dma_free(bcm); - bcm->current_core->flags &= ~ BCM43xx_COREFLAG_INITIALIZED; + bcm->current_core->initialized = 0; } /* http://bcm-specs.sipsolutions.net/80211Init */ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u32 ucodeflags; int err; u32 sbimconfiglow; @@ -2867,16 +2863,15 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) /* HW decryption needs to be set now */ ucodeflags |= 0x40000000; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + if (phy->type == BCM43xx_PHYTYPE_G) { ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; - if (bcm->current_core->phy->rev == 1) + if (phy->rev == 1) ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY; if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL; - } else if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) { + } else if (phy->type == BCM43xx_PHYTYPE_B) { ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; - if ((bcm->current_core->phy->rev >= 2) && - (bcm->current_core->radio->version == 0x2050)) + if (phy->rev >= 2 && radio->version == 0x2050) ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY; } @@ -2901,7 +2896,7 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) bcm43xx_rate_memory_init(bcm); /* Minimum Contention Window */ - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B) + if (phy->type == BCM43xx_PHYTYPE_B) bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f); else bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f); @@ -2927,7 +2922,7 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) bcm43xx_mac_enable(bcm); bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - bcm->current_core->flags |= BCM43xx_COREFLAG_INITIALIZED; + bcm->current_core->initialized = 1; out: return err; @@ -3048,7 +3043,7 @@ static void bcm43xx_softmac_init(struct bcm43xx_private *bcm) static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2) return; @@ -3076,8 +3071,8 @@ static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm) static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); if (phy->type == BCM43xx_PHYTYPE_G) { //TODO: update_aci_moving_average @@ -3170,9 +3165,9 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) bcm43xx_unlock(bcm, flags); for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_AVAILABLE)) + if (!bcm->core_80211[i].available) continue; - if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_INITIALIZED)) + if (!bcm->core_80211[i].initialized) continue; err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); @@ -3190,7 +3185,6 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm) static int bcm43xx_init_board(struct bcm43xx_private *bcm) { int i, err; - int num_80211_cores; int connect_phy; unsigned long flags; @@ -3212,8 +3206,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) goto err_crystal_off; tasklet_enable(&bcm->isr_tasklet); - num_80211_cores = bcm43xx_num_80211_cores(bcm); - for (i = 0; i < num_80211_cores; i++) { + for (i = 0; i < bcm->nr_80211_available; i++) { err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); assert(err != -ENODEV); if (err) @@ -3223,8 +3216,8 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) * Connect PHY only on the first core. */ if (!bcm43xx_core_enabled(bcm)) { - if (num_80211_cores == 1) { - connect_phy = bcm->current_core->phy->connected; + if (bcm->nr_80211_available == 1) { + connect_phy = bcm43xx_current_phy(bcm)->connected; } else { if (i == 0) connect_phy = 1; @@ -3248,7 +3241,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) } } bcm->active_80211_core = &bcm->core_80211[0]; - if (num_80211_cores >= 2) { + if (bcm->nr_80211_available >= 2) { bcm43xx_switch_core(bcm, &bcm->core_80211[0]); bcm43xx_mac_enable(bcm); } @@ -3260,9 +3253,9 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); - if (bcm->current_core->radio->initial_channel != 0xFF) { + if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) { bcm43xx_mac_suspend(bcm); - bcm43xx_radio_selectchannel(bcm, bcm->current_core->radio->initial_channel, 0); + bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0); bcm43xx_mac_enable(bcm); } @@ -3282,8 +3275,8 @@ out: err_80211_unwind: tasklet_disable(&bcm->isr_tasklet); /* unwind all 80211 initialization */ - for (i = 0; i < num_80211_cores; i++) { - if (!(bcm->core_80211[i].flags & BCM43xx_COREFLAG_INITIALIZED)) + for (i = 0; i < bcm->nr_80211_available; i++) { + if (!bcm->core_80211[i].initialized) continue; bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); bcm43xx_wireless_core_cleanup(bcm); @@ -3307,15 +3300,15 @@ static void bcm43xx_detach_board(struct bcm43xx_private *bcm) /* Free allocated structures/fields */ for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - kfree(bcm->phy[i]._lo_pairs); - if (bcm->phy[i].dyn_tssi_tbl) - kfree(bcm->phy[i].tssi2dbm); + kfree(bcm->core_80211_ext[i].phy._lo_pairs); + if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl) + kfree(bcm->core_80211_ext[i].phy.tssi2dbm); } } static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 value; u8 phy_version; u8 phy_type; @@ -3393,7 +3386,6 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) int i; void __iomem *ioaddr; unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; - int num_80211_cores; u32 coremask; err = pci_enable_device(pci_dev); @@ -3467,11 +3459,9 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) if (err) goto err_chipset_detach; - num_80211_cores = bcm43xx_num_80211_cores(bcm); - /* Attach all IO cores to the backplane. */ coremask = 0; - for (i = 0; i < num_80211_cores; i++) + for (i = 0; i < bcm->nr_80211_available; i++) coremask |= (1 << bcm->core_80211[i].index); //FIXME: Also attach some non80211 cores? err = bcm43xx_setup_backplane_pci_connection(bcm, coremask); @@ -3487,7 +3477,7 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) if (err) goto err_chipset_detach; - for (i = 0; i < num_80211_cores; i++) { + for (i = 0; i < bcm->nr_80211_available; i++) { err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); assert(err != -ENODEV); if (err) @@ -3519,7 +3509,7 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) bcm43xx_pctl_set_crystal(bcm, 0); /* Set the MAC address in the networking subsystem */ - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6); else memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6); @@ -3535,9 +3525,9 @@ out: err_80211_unwind: for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - kfree(bcm->phy[i]._lo_pairs); - if (bcm->phy[i].dyn_tssi_tbl) - kfree(bcm->phy[i].tssi2dbm); + kfree(bcm->core_80211_ext[i].phy._lo_pairs); + if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl) + kfree(bcm->core_80211_ext[i].phy.tssi2dbm); } err_chipset_detach: bcm43xx_chipset_detach(bcm); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h index 086136c3d0..eca79a3859 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h @@ -80,7 +80,7 @@ static inline u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm, int freq) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) return bcm43xx_freq_to_channel_a(freq); return bcm43xx_freq_to_channel_bg(freq); } @@ -107,7 +107,7 @@ static inline int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm, u8 channel) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) return bcm43xx_channel_to_freq_a(channel); return bcm43xx_channel_to_freq_bg(channel); } @@ -129,7 +129,7 @@ static inline int bcm43xx_is_valid_channel(struct bcm43xx_private *bcm, u8 channel) { - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) return bcm43xx_is_valid_channel_a(channel); return bcm43xx_is_valid_channel_bg(channel); } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index dbbef6ccd1..1ce9a45999 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -83,7 +83,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); assert(irqs_disabled()); if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) { @@ -102,7 +102,7 @@ void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); assert(irqs_disabled()); if (bcm->current_core->rev < 3) { @@ -132,7 +132,7 @@ void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val) void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); unsigned long flags; bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ @@ -158,39 +158,32 @@ void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) */ int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u32 flags; - if (bcm->current_core->rev < 5) { - if (connect) { - bcm->current_core->phy->connected = 1; - dprintk(KERN_INFO PFX "PHY connected\n"); - } else { - bcm->current_core->phy->connected = 0; - dprintk(KERN_INFO PFX "PHY disconnected\n"); - } - return 0; - } - + if (bcm->current_core->rev < 5) + goto out; + flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); if (connect) { if (!(flags & 0x00010000)) return -ENODEV; - bcm->current_core->phy->connected = 1; - flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); flags |= (0x800 << 18); bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); - dprintk(KERN_INFO PFX "PHY connected\n"); } else { if (!(flags & 0x00020000)) return -ENODEV; - bcm->current_core->phy->connected = 0; - flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); flags &= ~(0x800 << 18); bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); - dprintk(KERN_INFO PFX "PHY disconnected\n"); } +out: + phy->connected = connect; + if (connect) + dprintk(KERN_INFO PFX "PHY connected\n"); + else + dprintk(KERN_INFO PFX "PHY disconnected\n"); return 0; } @@ -200,8 +193,8 @@ int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect) */ static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0; int must_reset_txpower = 0; @@ -250,7 +243,7 @@ static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm) static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 offset = 0x0000; if (phy->rev == 1) @@ -326,7 +319,7 @@ static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 i; assert(phy->type == BCM43xx_PHYTYPE_G); @@ -420,7 +413,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) /* Initialize the noisescaletable for APHY */ static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); int i; bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400); @@ -448,10 +441,11 @@ static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm) static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 i; - assert(bcm->current_core->phy->type == BCM43xx_PHYTYPE_A); - switch (bcm->current_core->phy->rev) { + assert(phy->type == BCM43xx_PHYTYPE_A); + switch (phy->rev) { case 2: bcm43xx_phy_write(bcm, 0x008E, 0x3800); bcm43xx_phy_write(bcm, 0x0035, 0x03FF); @@ -563,7 +557,8 @@ static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) /* Initialize APHY. This is also called for the GPHY in some cases. */ static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 tval; if (phy->type == BCM43xx_PHYTYPE_A) { @@ -586,11 +581,11 @@ static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) { - if (bcm->current_core->radio->lofcal == 0xFFFF) { + if (radio->lofcal == 0xFFFF) { TODO();//TODO: LOF Cal bcm43xx_radio_set_tx_iq(bcm); } else - bcm43xx_radio_write16(bcm, 0x001E, bcm->current_core->radio->lofcal); + bcm43xx_radio_write16(bcm, 0x001E, radio->lofcal); } bcm43xx_phy_write(bcm, 0x007A, 0xF111); @@ -620,7 +615,7 @@ static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 offset, val; bcm43xx_write16(bcm, 0x03EC, 0x3F22); @@ -671,7 +666,7 @@ static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm) static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 offset, val; bcm43xx_write16(bcm, 0x03EC, 0x3F22); @@ -729,8 +724,8 @@ static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm) static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 offset; if (phy->version == 1 && @@ -835,8 +830,8 @@ static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm) static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 offset, val; bcm43xx_phy_write(bcm, 0x003E, 0x817A); @@ -946,9 +941,9 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) udelay(40); bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) | 0x0002)); bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - if ((bcm->current_core->radio->manufact == 0x17F) && - (bcm->current_core->radio->version == 0x2050) && - (bcm->current_core->radio->revision <= 2)) { + if (radio->manufact == 0x17F && + radio->version == 0x2050 && + radio->revision <= 2) { bcm43xx_radio_write16(bcm, 0x0050, 0x0020); bcm43xx_radio_write16(bcm, 0x005A, 0x0070); bcm43xx_radio_write16(bcm, 0x005B, 0x007B); @@ -1001,8 +996,8 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 tmp; if (phy->rev == 1) @@ -1096,8 +1091,8 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 regstack[12] = { 0 }; u16 mls; u16 fval; @@ -1190,7 +1185,9 @@ void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm) static inline u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) { - if (bcm->current_core->phy->connected) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + + if (phy->connected) { bcm43xx_phy_write(bcm, 0x15, 0xE300); control <<= 8; bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0); @@ -1242,7 +1239,7 @@ void bcm43xx_lo_write(struct bcm43xx_private *bcm, "WARNING: Writing invalid LOpair " "(low: %d, high: %d, index: %lu)\n", pair->low, pair->high, - (unsigned long)(pair - bcm->current_core->phy->_lo_pairs)); + (unsigned long)(pair - bcm43xx_current_phy(bcm)->_lo_pairs)); dump_stack(); } #endif @@ -1257,7 +1254,7 @@ struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm, u16 tx) { static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 }; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); if (baseband_attenuation > 6) baseband_attenuation = 6; @@ -1275,10 +1272,12 @@ struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm, static inline struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + return bcm43xx_find_lopair(bcm, - bcm->current_core->radio->txpower[0], - bcm->current_core->radio->txpower[1], - bcm->current_core->radio->txpower[2]); + radio->txpower[0], + radio->txpower[1], + radio->txpower[2]); } /* Adjust B/G LO */ @@ -1294,9 +1293,9 @@ void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed) bcm43xx_lo_write(bcm, pair); } -static inline -void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) +static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 txctl2 = 0, i; u32 smallest, tmp; @@ -1312,7 +1311,7 @@ void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) txctl2 = i; } } - bcm->current_core->radio->txpower[3] = txctl2; + radio->txpower[3] = txctl2; } static @@ -1402,16 +1401,17 @@ void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm, void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, u16 baseband_attenuation) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 value; - if (bcm->current_core->phy->version == 0) { + if (phy->version == 0) { value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0); value |= (baseband_attenuation & 0x000F); bcm43xx_write16(bcm, 0x03E6, value); return; } - if (bcm->current_core->phy->version > 1) { + if (phy->version > 1) { value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C; value |= (baseband_attenuation << 2) & 0x003C; } else { @@ -1426,8 +1426,8 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) { static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 }; const int is_initializing = bcm43xx_is_initializing(bcm); - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 h, i, oldi = 0, j; struct bcm43xx_lopair control; struct bcm43xx_lopair *tmp_control; @@ -1653,7 +1653,7 @@ void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm) void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_lopair *pair; int i; @@ -1668,7 +1668,7 @@ void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm) */ static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); s8 dbm = 0; s32 tmp; @@ -1698,8 +1698,8 @@ static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi) /* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); if (phy->savedpctlreg == 0xFFFF) return; @@ -1880,8 +1880,8 @@ s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2) /* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */ int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); s16 pab0, pab1, pab2; u8 idx; s8 *dyn_tssi2dbm; @@ -1958,7 +1958,7 @@ int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) int bcm43xx_phy_init(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); int err = -ENODEV; unsigned long flags; @@ -2008,7 +2008,7 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm) void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 antennadiv; u16 offset; u16 value; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 26dc6047d4..7bddae910d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -146,7 +146,7 @@ struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm, u16 cookie, struct bcm43xx_pio_txpacket **packet) { - struct bcm43xx_pio *pio = bcm->current_core->pio; + struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); struct bcm43xx_pioqueue *queue = NULL; int packetindex; @@ -377,7 +377,7 @@ static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) void bcm43xx_pio_free(struct bcm43xx_private *bcm) { - struct bcm43xx_pio *pio = bcm->current_core->pio; + struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); bcm43xx_destroy_pioqueue(pio->queue3); pio->queue3 = NULL; @@ -391,7 +391,7 @@ void bcm43xx_pio_free(struct bcm43xx_private *bcm) int bcm43xx_pio_init(struct bcm43xx_private *bcm) { - struct bcm43xx_pio *pio = bcm->current_core->pio; + struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); struct bcm43xx_pioqueue *queue; int err = -ENOMEM; @@ -438,7 +438,7 @@ err_destroy0: int bcm43xx_pio_tx(struct bcm43xx_private *bcm, struct ieee80211_txb *txb) { - struct bcm43xx_pioqueue *queue = bcm->current_core->pio->queue1; + struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; struct bcm43xx_pio_txpacket *packet; u16 tmp; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 4d3b0e8587..07a6169a0b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -114,8 +114,8 @@ void bcm43xx_radio_unlock(struct bcm43xx_private *bcm) u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); switch (phy->type) { case BCM43xx_PHYTYPE_A: @@ -151,7 +151,7 @@ void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm, s16 first, s16 second, s16 third) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 i; u16 start = 0x08, end = 0x18; u16 offset = 0x0400; @@ -183,7 +183,7 @@ static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm, static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 i, tmp; u16 offset = 0x0400; u16 start = 0x0008, end = 0x0018; @@ -217,7 +217,7 @@ static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm) /* Synthetic PU workaround */ static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); if (radio->version != 0x2050 || radio->revision >= 6) { /* We do not need the workaround. */ @@ -238,7 +238,7 @@ static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel) u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u8 ret = 0; u16 saved, rssi, temp; int i, j = 0; @@ -269,8 +269,8 @@ u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel) u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u8 ret[13]; unsigned int channel = radio->channel; unsigned int i, j, start, end; @@ -351,22 +351,23 @@ void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val) /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); s16 i, delta; s32 tmp; - delta = 0x1F - bcm->current_core->radio->nrssi[0]; + delta = 0x1F - radio->nrssi[0]; for (i = 0; i < 64; i++) { - tmp = (i - delta) * bcm->current_core->radio->nrssislope; + tmp = (i - delta) * radio->nrssislope; tmp /= 0x10000; tmp += 0x3A; tmp = limit_value(tmp, 0, 0x3F); - bcm->current_core->radio->nrssi_lt[i] = tmp; + radio->nrssi_lt[i] = tmp; } } static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); u16 backup[20] = { 0 }; s16 v47F; u16 i; @@ -531,8 +532,8 @@ static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 backup[18] = { 0 }; u16 tmp; s16 nrssi0, nrssi1; @@ -779,8 +780,8 @@ void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); s16 threshold; s32 a, b; int tmp; @@ -804,7 +805,7 @@ void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) radiotype = 1; if (radiotype == 1) { - threshold = bcm->current_core->radio->nrssi[1] - 5; + threshold = radio->nrssi[1] - 5; } else { threshold = 40 * radio->nrssi[0]; threshold += 33 * (radio->nrssi[1] - radio->nrssi[0]); @@ -901,8 +902,8 @@ static void bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, int mode) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); int i = 0; u16 *stack = radio->interfstack; u16 tmp, flipped; @@ -1052,8 +1053,8 @@ static void bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, int mode) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); int i = 0; u16 *stack = radio->interfstack; u16 tmp, flipped; @@ -1142,8 +1143,8 @@ bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); int currentmode; if ((phy->type != BCM43xx_PHYTYPE_G) || @@ -1199,8 +1200,8 @@ u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm) u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 backup[19] = { 0 }; u16 ret; u16 i, j; @@ -1444,7 +1445,7 @@ int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel, int synthetic_pu_workaround) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 r8, tmp; u16 freq; @@ -1628,6 +1629,7 @@ static u16 bcm43xx_get_txgain_dac(u16 txpower) void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 pamp, base, dac, ilt; txpower = limit_value(txpower, 0, 63); @@ -1650,7 +1652,7 @@ void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) bcm43xx_ilt_write(bcm, 0x3001, dac); - bcm->current_core->radio->txpower[0] = txpower; + radio->txpower[0] = txpower; TODO(); //TODO: FuncPlaceholder (Adjust BB loft cancel) @@ -1660,8 +1662,8 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, u16 baseband_attenuation, u16 radio_attenuation, u16 txpower) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); if (baseband_attenuation == 0xFFFF) baseband_attenuation = radio->txpower[0]; @@ -1698,8 +1700,8 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); int err; if (radio->enabled) @@ -1730,8 +1732,8 @@ void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm) void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); if (phy->type == BCM43xx_PHYTYPE_A) { bcm43xx_radio_write16(bcm, 0x0004, 0x00FF); @@ -1750,7 +1752,9 @@ void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm) void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm) { - switch (bcm->current_core->phy->type) { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + + switch (phy->type) { case BCM43xx_PHYTYPE_A: bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F); bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index 713ec601c3..35c3c9704c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -150,7 +150,7 @@ static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, bcm43xx_lock(bcm, flags); assert(bcm->initialized); - switch (bcm->current_core->radio->interfmode) { + switch (bcm43xx_current_radio(bcm)->interfmode) { case BCM43xx_RADIO_INTERFMODE_NONE: count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n"); break; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 208193851e..651ba60549 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -56,15 +56,14 @@ static int bcm43xx_wx_get_name(struct net_device *net_dev, { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); unsigned long flags; - int i, nr_80211; + int i; struct bcm43xx_phyinfo *phy; char suffix[7] = { 0 }; int have_a = 0, have_b = 0, have_g = 0; bcm43xx_lock(bcm, flags); - nr_80211 = bcm43xx_num_80211_cores(bcm); - for (i = 0; i < nr_80211; i++) { - phy = bcm->phy + i; + for (i = 0; i < bcm->nr_80211_available; i++) { + phy = &(bcm->core_80211_ext[i].phy); switch (phy->type) { case BCM43xx_PHYTYPE_A: have_a = 1; @@ -129,7 +128,7 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, err = bcm43xx_radio_selectchannel(bcm, channel, 0); bcm43xx_mac_enable(bcm); } else { - bcm->current_core->radio->initial_channel = channel; + bcm43xx_current_radio(bcm)->initial_channel = channel; err = 0; } out_unlock: @@ -144,15 +143,17 @@ static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct bcm43xx_radioinfo *radio; unsigned long flags; int err = -ENODEV; u16 channel; bcm43xx_lock(bcm, flags); - channel = bcm->current_core->radio->channel; + radio = bcm43xx_current_radio(bcm); + channel = radio->channel; if (channel == 0xFF) { assert(!bcm->initialized); - channel = bcm->current_core->radio->initial_channel; + channel = radio->initial_channel; if (channel == 0xFF) goto out_unlock; } @@ -232,6 +233,7 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, const struct ieee80211_geo *geo; unsigned long flags; int i, j; + struct bcm43xx_phyinfo *phy; data->data.length = sizeof(*range); memset(range, 0, sizeof(*range)); @@ -270,11 +272,12 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, IW_ENC_CAPA_CIPHER_CCMP; bcm43xx_lock(bcm, flags); + phy = bcm43xx_current_phy(bcm); range->num_bitrates = 0; i = 0; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A || - bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + if (phy->type == BCM43xx_PHYTYPE_A || + phy->type == BCM43xx_PHYTYPE_G) { range->num_bitrates = 8; range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB; range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB; @@ -285,8 +288,8 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB; range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB; } - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_B || - bcm->current_core->phy->type == BCM43xx_PHYTYPE_G) { + if (phy->type == BCM43xx_PHYTYPE_B || + phy->type == BCM43xx_PHYTYPE_G) { range->num_bitrates += 4; range->bitrate[i++] = IEEE80211_CCK_RATE_1MB; range->bitrate[i++] = IEEE80211_CCK_RATE_2MB; @@ -461,8 +464,8 @@ static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, bcm43xx_lock_mmio(bcm, flags); if (!bcm->initialized) goto out_unlock; - radio = bcm->current_core->radio; - phy = bcm->current_core->phy; + radio = bcm43xx_current_radio(bcm); + phy = bcm43xx_current_phy(bcm); if (data->txpower.disabled != (!(radio->enabled))) { if (data->txpower.disabled) bcm43xx_radio_turn_off(bcm); @@ -500,7 +503,7 @@ static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, bcm43xx_lock(bcm, flags); if (!bcm->initialized) goto out_unlock; - radio = bcm->current_core->radio; + radio = bcm43xx_current_radio(bcm); /* desired dBm value is in Q5.2 */ data->txpower.value = radio->txpower_desired >> 2; data->txpower.fixed = 1; @@ -645,7 +648,7 @@ static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, "not supported while the interface is down.\n"); err = -ENODEV; } else - bcm->current_core->radio->interfmode = mode; + bcm43xx_current_radio(bcm)->interfmode = mode; } bcm43xx_unlock_mmio(bcm, flags); @@ -662,7 +665,7 @@ static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, int mode; bcm43xx_lock(bcm, flags); - mode = bcm->current_core->radio->interfmode; + mode = bcm43xx_current_radio(bcm)->interfmode; bcm43xx_unlock(bcm, flags); switch (mode) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c index 5ee572e79f..c4809da8e9 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c @@ -284,7 +284,7 @@ void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, const int is_first_fragment, const u16 cookie) { - const struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data; const struct ieee80211_security *secinfo = &bcm->ieee->sec; u8 bitrate; @@ -382,8 +382,8 @@ static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, u8 in_rssi, int ofdm, int adjust_2053, int adjust_2050) { - struct bcm43xx_radioinfo *radio = bcm->current_core->radio; - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); s32 tmp; switch (radio->version) { @@ -442,7 +442,7 @@ static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, u8 in_rssi) { - struct bcm43xx_phyinfo *phy = bcm->current_core->phy; + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); s8 ret; if (phy->type == BCM43xx_PHYTYPE_A) { @@ -458,6 +458,8 @@ int bcm43xx_rx(struct bcm43xx_private *bcm, struct sk_buff *skb, struct bcm43xx_rxhdr *rxhdr) { + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_plcp_hdr4 *plcp; struct ieee80211_rx_stats stats; struct ieee80211_hdr_4addr *wlhdr; @@ -494,13 +496,13 @@ int bcm43xx_rx(struct bcm43xx_private *bcm, else stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp); //printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate); - stats.received_channel = bcm->current_core->radio->channel; + stats.received_channel = radio->channel; //TODO stats.control = stats.mask = IEEE80211_STATMASK_SIGNAL | //TODO IEEE80211_STATMASK_NOISE | IEEE80211_STATMASK_RATE | IEEE80211_STATMASK_RSSI; - if (bcm->current_core->phy->type == BCM43xx_PHYTYPE_A) + if (phy->type == BCM43xx_PHYTYPE_A) stats.freq = IEEE80211_52GHZ_BAND; else stats.freq = IEEE80211_24GHZ_BAND; -- cgit v1.2.2 From 49f29efa7f44a79b64c7882c68e171898d0495a0 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 14 Mar 2006 16:05:26 +0100 Subject: [PATCH] bcm43xx: Fix crash on ifdown, by being careful in pio/dma freeing. This bug was caused by the packing of the bcm43xx_dma and bcm43xx_pio structures into a union. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 6 +++++- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 7ed368a587..9c64438b76 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -531,7 +531,11 @@ static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring) void bcm43xx_dma_free(struct bcm43xx_private *bcm) { - struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); + struct bcm43xx_dma *dma; + + if (bcm43xx_using_pio(bcm)) + return; + dma = bcm43xx_current_dma(bcm); bcm43xx_destroy_dmaring(dma->rx_ring1); dma->rx_ring1 = NULL; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 7bddae910d..5b6f0a84d0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -377,7 +377,11 @@ static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) void bcm43xx_pio_free(struct bcm43xx_private *bcm) { - struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); + struct bcm43xx_pio *pio; + + if (!bcm43xx_using_pio(bcm)) + return; + pio = bcm43xx_current_pio(bcm); bcm43xx_destroy_pioqueue(pio->queue3); pio->queue3 = NULL; -- cgit v1.2.2 From 4cf6f03e067d6d416f5c9219471daf64703afae4 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 14 Mar 2006 18:23:43 +0100 Subject: [PATCH] bcm43xx: Remove the workaround in dummy_transmission, as it causes more trouble than it solves Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 88e9a125c2..cc8efe74f5 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -996,13 +996,6 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) 0x00000000, }; -/* FIXME: It seems like a dummy_transmission corrupts the DMA engines, - * once they are initialized. So avoid doing a dummy_transmission, - * if the DMA engines are running. - */ -if (bcm->initialized) -return; - switch (phy->type) { case BCM43xx_PHYTYPE_A: max_loop = 0x1E; -- cgit v1.2.2 From b3db5e553876c1743eefae5963aea431ec4d5ba6 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 15 Mar 2006 16:31:45 +0100 Subject: [PATCH] bcm43xx: Do boardflags workarounds for specific boards. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 4 ++++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 9 +++++++++ 2 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index a358646ad3..8820012b4b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -120,6 +120,10 @@ #define BCM43xx_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */ #define BCM43xx_BFL_NOPCI 0x0400 /* leaves PCI floating */ #define BCM43xx_BFL_FEM 0x0800 /* supports the Front End Module */ +#define BCM43xx_BFL_EXTLNA 0x1000 /* has an external LNA */ +#define BCM43xx_BFL_HGPA 0x2000 /* had high gain PA */ +#define BCM43xx_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */ +#define BCM43xx_BFL_ALTIQ 0x8000 /* alternate I/Q settings */ /* GPIO register offset, in both ChipCommon and PCI core. */ #define BCM43xx_GPIO_CONTROL 0x6c diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index cc8efe74f5..e26507b11f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -910,6 +910,15 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) if (value == 0xFFFF) value = 0x0000; bcm->sprom.boardflags = value; + /* boardflags workarounds */ + if (bcm->board_vendor == PCI_VENDOR_ID_DELL && + bcm->chip_id == 0x4301 && + bcm->board_revision == 0x74) + bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST; + if (bcm->board_vendor == PCI_VENDOR_ID_APPLE && + bcm->board_type == 0x4E && + bcm->board_revision > 0x40) + bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL; /* antenna gain */ value = sprom[BCM43xx_SPROM_ANTENNA_GAIN]; -- cgit v1.2.2 From 5808bbbdf8c095745f0cac9110b245102243b243 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 15 Mar 2006 18:13:53 +0100 Subject: [PATCH] bcm43xx: properly mask txctl1 before writing it to hardware. This should not make a difference, but be careful to not trash the register. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 07a6169a0b..cac604bc09 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -1690,8 +1690,8 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation); if (radio->version == 0x2050) { bcm43xx_radio_write16(bcm, 0x0052, - (bcm43xx_radio_read16(bcm, 0x0052) & 0xFF8F) - | (txpower << 4)); + (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070) + | ((txpower << 4) & 0x0070)); } if (phy->type == BCM43xx_PHYTYPE_G) bcm43xx_phy_lo_adjust(bcm, 0); -- cgit v1.2.2 From 4a1821e4c7a84569f788b7667affe2743317b63f Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 18 Mar 2006 20:19:12 +0100 Subject: [PATCH] bcm43xx: remove check for mmio length, as it differs among platforms. (especially embedded) Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 30 ++++------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index e26507b11f..6a877df2ec 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3386,23 +3386,17 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) struct net_device *net_dev = bcm->net_dev; int err; int i; - void __iomem *ioaddr; - unsigned long mmio_start, mmio_end, mmio_flags, mmio_len; + unsigned long mmio_start, mmio_flags, mmio_len; u32 coremask; err = pci_enable_device(pci_dev); if (err) { printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err); - err = -ENODEV; goto out; } - mmio_start = pci_resource_start(pci_dev, 0); - mmio_end = pci_resource_end(pci_dev, 0); mmio_flags = pci_resource_flags(pci_dev, 0); mmio_len = pci_resource_len(pci_dev, 0); - - /* make sure PCI base addr is MMIO */ if (!(mmio_flags & IORESOURCE_MEM)) { printk(KERN_ERR PFX "%s, region #0 not an MMIO resource, aborting\n", @@ -3410,39 +3404,23 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm) err = -ENODEV; goto err_pci_disable; } -//FIXME: Why is this check disabled for BCM947XX? What is the IO_SIZE there? -#ifndef CONFIG_BCM947XX - if (mmio_len != BCM43xx_IO_SIZE) { - printk(KERN_ERR PFX - "%s: invalid PCI mem region size(s), aborting\n", - pci_name(pci_dev)); - err = -ENODEV; - goto err_pci_disable; - } -#endif - err = pci_request_regions(pci_dev, KBUILD_MODNAME); if (err) { printk(KERN_ERR PFX "could not access PCI resources (%i)\n", err); goto err_pci_disable; } - /* enable PCI bus-mastering */ pci_set_master(pci_dev); - - /* ioremap MMIO region */ - ioaddr = ioremap(mmio_start, mmio_len); - if (!ioaddr) { + bcm->mmio_addr = ioremap(mmio_start, mmio_len); + if (!bcm->mmio_addr) { printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pci_dev)); err = -EIO; goto err_pci_release; } - - net_dev->base_addr = (unsigned long)ioaddr; - bcm->mmio_addr = ioaddr; bcm->mmio_len = mmio_len; + net_dev->base_addr = (unsigned long)bcm->mmio_addr; bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID, &bcm->board_vendor); -- cgit v1.2.2 From 714eece7c7c300bbc5e8285890e7374958ca37f4 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 18 Mar 2006 21:28:46 +0100 Subject: [PATCH] bcm43xx: fix some gpio register trashing (hopefully :D) Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 16 +++++-- drivers/net/wireless/bcm43xx/bcm43xx_leds.h | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 71 ++++++++++++++--------------- 3 files changed, 46 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 72a243aac6..c8f5ad75d2 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -165,7 +165,7 @@ void bcm43xx_leds_exit(struct bcm43xx_private *bcm) led = &(bcm->leds[i]); bcm43xx_led_blink_stop(led, 1); } - bcm43xx_leds_turn_off(bcm); + bcm43xx_leds_switch_all(bcm, 0); } void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) @@ -268,18 +268,26 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); } -void bcm43xx_leds_turn_off(struct bcm43xx_private *bcm) +void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) { struct bcm43xx_led *led; - u16 ledctl = 0; + u16 ledctl; int i; + int bit_on; + ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); for (i = 0; i < BCM43xx_NR_LEDS; i++) { led = &(bcm->leds[i]); if (led->behaviour == BCM43xx_LED_INACTIVE) continue; - if (led->activelow) + if (on) + bit_on = led->activelow ? 0 : 1; + else + bit_on = led->activelow ? 1 : 0; + if (bit_on) ledctl |= (1 << i); + else + ledctl &= ~(1 << i); } bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); } diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h index 6f18e2f95d..d3716cf3ae 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h @@ -51,6 +51,6 @@ enum { /* LED behaviour values */ int bcm43xx_leds_init(struct bcm43xx_private *bcm); void bcm43xx_leds_exit(struct bcm43xx_private *bcm); void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity); -void bcm43xx_leds_turn_off(struct bcm43xx_private *bcm); +void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on); #endif /* BCM43xx_LEDS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 6a877df2ec..eb8fca8279 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2182,13 +2182,10 @@ static int switch_to_gpio_core(struct bcm43xx_private *bcm) if (unlikely(err == -ENODEV)) { printk(KERN_ERR PFX "gpio error: " "Neither ChipCommon nor PCI core available!\n"); - return -ENODEV; - } else if (unlikely(err != 0)) - return -ENODEV; - } else if (unlikely(err != 0)) - return -ENODEV; + } + } - return 0; + return err; } /* Initialize the GPIOs @@ -2198,45 +2195,48 @@ static int bcm43xx_gpio_init(struct bcm43xx_private *bcm) { struct bcm43xx_coreinfo *old_core; int err; - u32 mask, value; + u32 mask, set; - value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value &= ~0xc000; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) + & 0xFFFF3FFF); - mask = 0x0000001F; - value = 0x0000000F; - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, - bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL) & 0xFFF0); + bcm43xx_leds_switch_all(bcm, 0); bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F); - old_core = bcm->current_core; - - err = switch_to_gpio_core(bcm); - if (err) - return err; - - if (bcm->current_core->rev >= 2){ - mask |= 0x10; - value |= 0x10; - } + mask = 0x0000001F; + set = 0x0000000F; if (bcm->chip_id == 0x4301) { - mask |= 0x60; - value |= 0x60; + mask |= 0x0060; + set |= 0x0060; + } + if (0 /* FIXME: conditional unknown */) { + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, + bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) + | 0x0100); + mask |= 0x0180; + set |= 0x0180; } if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) { - mask |= 0x200; - value |= 0x200; + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, + bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) + | 0x0200); + mask |= 0x0200; + set |= 0x0200; } + if (bcm->current_core->rev >= 2) + mask |= 0x0010; /* FIXME: This is redundant. */ + old_core = bcm->current_core; + err = switch_to_gpio_core(bcm); + if (err) + goto out; bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, - (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | value); - + (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set); err = bcm43xx_switch_core(bcm, old_core); - assert(err == 0); - - return 0; +out: + return err; } /* Turn off all GPIO stuff. Call this on module unload, for example. */ @@ -2384,11 +2384,6 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) goto err_gpio_cleanup; bcm43xx_radio_turn_on(bcm); - if (modparam_noleds) - bcm43xx_leds_turn_off(bcm); - else - bcm43xx_leds_update(bcm, 0); - bcm43xx_write16(bcm, 0x03E6, 0x0000); err = bcm43xx_phy_init(bcm); if (err) -- cgit v1.2.2 From 6ab5b8e670c4bb7ac0035ec3c6d6a161fae12009 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Mar 2006 17:18:48 +0100 Subject: [PATCH] bcm43xx: merge all iwmode code into the set_iwmode function. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 65 +++++++++++++---------------- 1 file changed, 29 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index eb8fca8279..a85176325e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2292,50 +2292,60 @@ void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, int iw_mode) { unsigned long flags; + struct net_device *net_dev = bcm->net_dev; u32 status; + u16 value; spin_lock_irqsave(&bcm->ieee->lock, flags); bcm->ieee->iw_mode = iw_mode; spin_unlock_irqrestore(&bcm->ieee->lock, flags); if (iw_mode == IW_MODE_MONITOR) - bcm->net_dev->type = ARPHRD_IEEE80211; + net_dev->type = ARPHRD_IEEE80211; else - bcm->net_dev->type = ARPHRD_ETHER; + net_dev->type = ARPHRD_ETHER; - if (!bcm->initialized) - return; - - bcm43xx_mac_suspend(bcm); status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Reset status to infrastructured mode */ status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR); - /*FIXME: We actually set promiscuous mode as well, until we don't - * get the HW mac filter working */ - status |= BCM43xx_SBF_MODE_NOTADHOC | BCM43xx_SBF_MODE_PROMISC; + status &= ~BCM43xx_SBF_MODE_PROMISC; + status |= BCM43xx_SBF_MODE_NOTADHOC; + +/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */ +status |= BCM43xx_SBF_MODE_PROMISC; switch (iw_mode) { case IW_MODE_MONITOR: - status |= (BCM43xx_SBF_MODE_PROMISC | - BCM43xx_SBF_MODE_MONITOR); + status |= BCM43xx_SBF_MODE_MONITOR; + status |= BCM43xx_SBF_MODE_PROMISC; break; case IW_MODE_ADHOC: status &= ~BCM43xx_SBF_MODE_NOTADHOC; break; case IW_MODE_MASTER: + status |= BCM43xx_SBF_MODE_AP; + break; case IW_MODE_SECOND: case IW_MODE_REPEAT: - /* TODO: No AP/Repeater mode for now :-/ */ - TODO(); + TODO(); /* TODO */ break; case IW_MODE_INFRA: /* nothing to be done here... */ break; default: - printk(KERN_ERR PFX "Unknown iwmode %d\n", iw_mode); + dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode); } - + if (net_dev->flags & IFF_PROMISC) + status |= BCM43xx_SBF_MODE_PROMISC; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - bcm43xx_mac_enable(bcm); + + value = 0x0002; + if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) { + if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3) + value = 0x0064; + else + value = 0x0032; + } + bcm43xx_write16(bcm, 0x0612, value); } /* This is the opposite of bcm43xx_chip_init() */ @@ -2357,7 +2367,6 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); int err; - int iw_mode = bcm->ieee->iw_mode; int tmp; u32 value32; u16 value16; @@ -2411,20 +2420,9 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); value32 |= BCM43xx_SBF_MODE_NOTADHOC; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - /*FIXME: For now, use promiscuous mode at all times; otherwise we don't - get broadcast or multicast packets */ - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 |= BCM43xx_SBF_MODE_PROMISC; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - if (iw_mode == IW_MODE_MONITOR) { - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 |= BCM43xx_SBF_MODE_PROMISC; - value32 |= BCM43xx_SBF_MODE_MONITOR; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - } value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 |= 0x100000; //FIXME: What's this? Is this correct? + value32 |= 0x100000; bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); if (bcm43xx_using_pio(bcm)) { @@ -2439,13 +2437,8 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm) /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000); - if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) { - if ((bcm->chip_id == 0x4306) && (bcm->chip_rev == 3)) - bcm43xx_write16(bcm, 0x0612, 0x0064); - else - bcm43xx_write16(bcm, 0x0612, 0x0032); - } else - bcm43xx_write16(bcm, 0x0612, 0x0002); + /* Initially set the wireless operation mode. */ + bcm43xx_set_iwmode(bcm, bcm->ieee->iw_mode); if (bcm->current_core->rev < 3) { bcm43xx_write16(bcm, 0x060E, 0x0000); -- cgit v1.2.2 From 0ac59daee5f7fbaab25784a643edede669b5419e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 19 Mar 2006 21:43:40 +0100 Subject: [PATCH] bcm43xx: some IRQ handler cleanups. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 65 +++++++++++++---------------- 1 file changed, 30 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index a85176325e..12c93d274a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1785,10 +1785,6 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS); } - /* We get spurious IRQs, althought they are masked. - * Assume they are void and ignore them. - */ - bcmirq_handled(~(bcm->irq_savedstate)); /* IRQ_PIO_WORKAROUND is handled in the top-half. */ bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND); #ifdef CONFIG_BCM43XX_DEBUG @@ -1809,41 +1805,31 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) bcm43xx_unlock_mmio(bcm, flags); } -static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, - u32 reason, u32 mask) +static void pio_irq_workaround(struct bcm43xx_private *bcm, + u16 base, int queueidx) { - bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) - & 0x0001dc00; - bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) - & 0x0000dc00; - bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) - & 0x0000dc00; - bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) - & 0x0001dc00; + u16 rxctl; + + rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL); + if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE) + bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE; + else + bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE; +} +static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason) +{ if (bcm43xx_using_pio(bcm) && (bcm->current_core->rev < 3) && (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) { /* Apply a PIO specific workaround to the dma_reasons */ - -#define apply_pio_workaround(BASE, QNUM) \ - do { \ - if (bcm43xx_read16(bcm, BASE + BCM43xx_PIO_RXCTL) & BCM43xx_PIO_RXCTL_DATAAVAILABLE) \ - bcm->dma_reason[QNUM] |= 0x00010000; \ - else \ - bcm->dma_reason[QNUM] &= ~0x00010000; \ - } while (0) - - apply_pio_workaround(BCM43xx_MMIO_PIO1_BASE, 0); - apply_pio_workaround(BCM43xx_MMIO_PIO2_BASE, 1); - apply_pio_workaround(BCM43xx_MMIO_PIO3_BASE, 2); - apply_pio_workaround(BCM43xx_MMIO_PIO4_BASE, 3); - -#undef apply_pio_workaround + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0); + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1); + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2); + pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3); } - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, - reason & mask); + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason); bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON, bcm->dma_reason[0]); @@ -1860,7 +1846,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re { irqreturn_t ret = IRQ_HANDLED; struct bcm43xx_private *bcm = dev_id; - u32 reason, mask; + u32 reason; if (!bcm) return IRQ_NONE; @@ -1873,11 +1859,20 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re ret = IRQ_NONE; goto out; } - mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); - if (!(reason & mask)) + reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); + if (!reason) goto out; - bcm43xx_interrupt_ack(bcm, reason, mask); + bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) + & 0x0001dc00; + bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) + & 0x0000dc00; + bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) + & 0x0000dc00; + bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) + & 0x0001dc00; + + bcm43xx_interrupt_ack(bcm, reason); /* Only accept IRQs, if we are initialized properly. * This avoids an RX race while initializing. -- cgit v1.2.2 From 6ecb26904c9db15ca964d60b9483f19dc51bda5b Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 20 Mar 2006 00:01:04 +0100 Subject: [PATCH] bcm43xx: set default attenuation values. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 21 +++-- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 9 +- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 30 +++--- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 131 +++++++++++++++++++++++++-- drivers/net/wireless/bcm43xx/bcm43xx_radio.h | 5 + 5 files changed, 158 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 8820012b4b..1fca1f9c48 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -507,14 +507,23 @@ struct bcm43xx_radioinfo { u16 version; u8 revision; - /* 0: baseband attenuation, - * 1: radio attenuation, - * 2: tx_CTL1 - * 3: tx_CTL2 - */ - u16 txpower[4]; /* Desired TX power in dBm Q5.2 */ u16 txpower_desired; + /* TX Power control values. */ + union { + /* B/G PHY */ + struct { + u16 baseband_atten; + u16 radio_atten; + u16 txctl1; + u16 txctl2; + }; + /* A PHY */ + struct { + u16 txpwr_offset; + }; + }; + /* Current Interference Mitigation mode */ int interfmode; /* Stack of saved values from the Interference Mitigation code */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 12c93d274a..e680d2acc4 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -560,12 +560,9 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) radio->revision = revision; /* Set default attenuation values. */ - radio->txpower[0] = 2; - radio->txpower[1] = 2; - if (revision == 1) - radio->txpower[2] = 3; - else - radio->txpower[2] = 0; + radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm); + radio->radio_atten = bcm43xx_default_radio_attenuation(bcm); + radio->txctl1 = bcm43xx_default_txctl1(bcm); if (phy->type == BCM43xx_PHYTYPE_A) radio->txpower_desired = bcm->sprom.maxpower_aphy; else diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 1ce9a45999..054c64e462 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -220,9 +220,9 @@ static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) | 0x0084); } else { - saved_batt = radio->txpower[0]; - saved_ratt = radio->txpower[1]; - saved_txctl1 = radio->txpower[2]; + saved_batt = radio->baseband_atten; + saved_ratt = radio->radio_atten; + saved_txctl1 = radio->txctl1; if ((radio->revision >= 6) && (radio->revision <= 8) && /*FIXME: incomplete specs for 5 < revision < 9 */ 0) bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0); @@ -1039,7 +1039,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) bcm43xx_radio_write16(bcm, 0x0078, radio->initval); bcm43xx_radio_write16(bcm, 0x0052, (bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0) - | radio->txpower[3]); + | radio->txctl2); } if (phy->connected) { @@ -1259,7 +1259,6 @@ struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm, if (baseband_attenuation > 6) baseband_attenuation = 6; assert(radio_attenuation < 10); - assert(tx == 0 || tx == 3); if (tx == 3) { return bcm43xx_get_lopair(phy, @@ -1275,9 +1274,9 @@ struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm) struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); return bcm43xx_find_lopair(bcm, - radio->txpower[0], - radio->txpower[1], - radio->txpower[2]); + radio->baseband_atten, + radio->radio_atten, + radio->txctl1); } /* Adjust B/G LO */ @@ -1311,7 +1310,7 @@ static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) txctl2 = i; } } - radio->txpower[3] = txctl2; + radio->txctl2 = txctl2; } static @@ -1530,8 +1529,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) r31 = 0; } bcm43xx_radio_write16(bcm, 0x43, i); - bcm43xx_radio_write16(bcm, 0x52, - radio->txpower[3]); + bcm43xx_radio_write16(bcm, 0x52, radio->txctl2); udelay(10); bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); @@ -1573,7 +1571,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) } bcm43xx_radio_write16(bcm, 0x43, i - 9); bcm43xx_radio_write16(bcm, 0x52, - radio->txpower[3] + radio->txctl2 | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? udelay(10); @@ -1780,9 +1778,9 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) } /* Calculate the new attenuation values. */ - baseband_attenuation = radio->txpower[0]; + baseband_attenuation = radio->baseband_atten; baseband_attenuation += baseband_att_delta; - radio_attenuation = radio->txpower[1]; + radio_attenuation = radio->radio_atten; radio_attenuation += radio_att_delta; /* Get baseband and radio attenuation values into their permitted ranges. @@ -1807,7 +1805,7 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) } baseband_attenuation = limit_value(baseband_attenuation, 0, 11); - txpower = radio->txpower[2]; + txpower = radio->txctl1; if ((radio->version == 0x2050) && (radio->revision == 2)) { if (radio_attenuation <= 1) { if (txpower == 0) { @@ -1829,7 +1827,7 @@ void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) } } } - radio->txpower[2] = txpower; + radio->txctl1 = txpower; baseband_attenuation = limit_value(baseband_attenuation, 0, 11); radio_attenuation = limit_value(radio_attenuation, 0, 9); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index cac604bc09..4e8d8c936a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -1652,7 +1652,7 @@ void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) bcm43xx_ilt_write(bcm, 0x3001, dac); - radio->txpower[0] = txpower; + radio->txpwr_offset = txpower; TODO(); //TODO: FuncPlaceholder (Adjust BB loft cancel) @@ -1666,17 +1666,14 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); if (baseband_attenuation == 0xFFFF) - baseband_attenuation = radio->txpower[0]; - else - radio->txpower[0] = baseband_attenuation; + baseband_attenuation = radio->baseband_atten; if (radio_attenuation == 0xFFFF) - radio_attenuation = radio->txpower[1]; - else - radio->txpower[1] = radio_attenuation; + radio_attenuation = radio->radio_atten; if (txpower == 0xFFFF) - txpower = radio->txpower[2]; - else - radio->txpower[2] = txpower; + txpower = radio->txctl1; + radio->baseband_atten = baseband_attenuation; + radio->radio_atten = radio_attenuation; + radio->txctl1 = txpower; assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11); if (radio->revision < 6) @@ -1693,10 +1690,124 @@ void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070) | ((txpower << 4) & 0x0070)); } + //FIXME: The spec is very weird and unclear here. if (phy->type == BCM43xx_PHYTYPE_G) bcm43xx_phy_lo_adjust(bcm, 0); } +u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + + if (radio->version == 0x2050 && radio->revision < 6) + return 0; + return 2; +} + +u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + u16 att = 0xFFFF; + + if (phy->type == BCM43xx_PHYTYPE_A) + return 0x60; + + switch (radio->version) { + case 0x2053: + switch (radio->revision) { + case 1: + att = 6; + break; + } + break; + case 0x2050: + switch (radio->revision) { + case 0: + att = 5; + break; + case 1: + if (phy->type == BCM43xx_PHYTYPE_G) { + if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x421 && + bcm->board_revision >= 30) + att = 3; + else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x416) + att = 3; + else + att = 1; + } else { + if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x421 && + bcm->board_revision >= 30) + att = 7; + else + att = 6; + } + break; + case 2: + if (phy->type == BCM43xx_PHYTYPE_G) { + if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x421 && + bcm->board_revision >= 30) + att = 3; + else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x416) + att = 5; + else if (bcm->chip_id == 0x4320) + att = 4; + else + att = 3; + } else + att = 6; + break; + case 3: + att = 5; + break; + case 4: + case 5: + att = 1; + break; + case 6: + case 7: + att = 5; + break; + case 8: + att = 0x1A; + break; + case 9: + default: + att = 5; + } + } + if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && + bcm->board_type == 0x421) { + if (bcm->board_revision < 0x43) + att = 2; + else if (bcm->board_revision < 0x51) + att = 3; + } + if (att == 0xFFFF) + att = 5; + + return att; +} + +u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm) +{ + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + + if (radio->version != 0x2050) + return 0; + if (radio->revision == 1) + return 3; + if (radio->revision < 6) + return 2; + if (radio->revision == 8) + return 1; + return 0; +} void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm) { diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h index a5d2e10d5d..9ed18039fa 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h @@ -72,6 +72,11 @@ void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower); void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, u16 baseband_attenuation, u16 attenuation, u16 txpower); + +u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm); +u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm); +u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm); + void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val); void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm); -- cgit v1.2.2 From e382c234cbc6fcd76e9ed1168c77fe88d75df73c Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 21 Mar 2006 18:16:28 +0100 Subject: [PATCH] bcm43xx: sync interference mitigation code to the specs. This also includes a rewritten valuesave-stack. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 12 +- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 447 ++++++++++++++++++--------- 2 files changed, 309 insertions(+), 150 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 1fca1f9c48..57fcaafcf7 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -526,8 +526,16 @@ struct bcm43xx_radioinfo { /* Current Interference Mitigation mode */ int interfmode; - /* Stack of saved values from the Interference Mitigation code */ - u16 interfstack[20]; + /* Stack of saved values from the Interference Mitigation code. + * Each value in the stack is layed out as follows: + * bit 0-11: offset + * bit 12-15: register ID + * bit 16-32: value + * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT + */ +#define BCM43xx_INTERFSTACK_SIZE 26 + u32 interfstack[BCM43xx_INTERFSTACK_SIZE]; + /* Saved values from the NRSSI Slope calculation */ s16 nrssi[2]; s32 nrssislope; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 4e8d8c936a..63aae43ba8 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -879,24 +879,76 @@ void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) } } -/* Helper macros to save on and restore values from the radio->interfstack */ -#ifdef stack_save -# undef stack_save -#endif -#ifdef stack_restore -# undef stack_restore -#endif -#define stack_save(value) \ +/* Stack implementation to save/restore values from the + * interference mitigation code. + * It is save to restore values in random order. + */ +static void _stack_save(u32 *_stackptr, size_t *stackidx, + u8 id, u16 offset, u16 value) +{ + u32 *stackptr = &(_stackptr[*stackidx]); + + assert((offset & 0xF000) == 0x0000); + assert((id & 0xF0) == 0x00); + *stackptr = offset; + *stackptr |= ((u32)id) << 12; + *stackptr |= ((u32)value) << 16; + (*stackidx)++; + assert(*stackidx < BCM43xx_INTERFSTACK_SIZE); +} + +static u16 _stack_restore(u32 *stackptr, + u8 id, u16 offset) +{ + size_t i; + + assert((offset & 0xF000) == 0x0000); + assert((id & 0xF0) == 0x00); + for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) { + if ((*stackptr & 0x00000FFF) != offset) + continue; + if (((*stackptr & 0x0000F000) >> 12) != id) + continue; + return ((*stackptr & 0xFFFF0000) >> 16); + } + assert(0); + + return 0; +} + +#define phy_stacksave(offset) \ do { \ - assert(i < ARRAY_SIZE(radio->interfstack)); \ - stack[i++] = (value); \ + _stack_save(stack, &stackidx, 0x1, (offset), \ + bcm43xx_phy_read(bcm, (offset))); \ + } while (0) +#define phy_stackrestore(offset) \ + do { \ + bcm43xx_phy_write(bcm, (offset), \ + _stack_restore(stack, 0x1, \ + (offset))); \ + } while (0) +#define radio_stacksave(offset) \ + do { \ + _stack_save(stack, &stackidx, 0x2, (offset), \ + bcm43xx_radio_read16(bcm, (offset))); \ + } while (0) +#define radio_stackrestore(offset) \ + do { \ + bcm43xx_radio_write16(bcm, (offset), \ + _stack_restore(stack, 0x2, \ + (offset))); \ + } while (0) +#define ilt_stacksave(offset) \ + do { \ + _stack_save(stack, &stackidx, 0x3, (offset), \ + bcm43xx_ilt_read(bcm, (offset))); \ + } while (0) +#define ilt_stackrestore(offset) \ + do { \ + bcm43xx_ilt_write(bcm, (offset), \ + _stack_restore(stack, 0x3, \ + (offset))); \ } while (0) - -#define stack_restore() \ - ({ \ - assert(i < ARRAY_SIZE(radio->interfstack)); \ - stack[i++]; \ - }) static void bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, @@ -904,144 +956,231 @@ bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - int i = 0; - u16 *stack = radio->interfstack; u16 tmp, flipped; + u32 tmp32; + size_t stackidx = 0; + u32 *stack = radio->interfstack; switch (mode) { case BCM43xx_RADIO_INTERFMODE_NONWLAN: if (phy->rev != 1) { bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) & 0x0800); + bcm43xx_phy_read(bcm, 0x042B) | 0x0800); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000); break; } + radio_stacksave(0x0078); tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); flipped = flip_4bit(tmp); - if ((flipped >> 1) >= 4) - tmp = flipped - 3; - tmp = flip_4bit(tmp); - bcm43xx_radio_write16(bcm, 0x0078, tmp << 1); + if (flipped < 10 && flipped >= 8) + flipped = 7; + else if (flipped >= 10) + flipped -= 3; + flipped = flip_4bit(flipped); + flipped = (flipped << 1) | 0x0020; + bcm43xx_radio_write16(bcm, 0x0078, flipped); bcm43xx_calc_nrssi_threshold(bcm); - if (bcm->current_core->rev < 5) { - stack_save(bcm43xx_phy_read(bcm, 0x0406)); - bcm43xx_phy_write(bcm, 0x0406, 0x7E28); - } else { - stack_save(bcm43xx_phy_read(bcm, 0x04C0)); - stack_save(bcm43xx_phy_read(bcm, 0x04C1)); - bcm43xx_phy_write(bcm, 0x04C0, 0x3E04); - bcm43xx_phy_write(bcm, 0x04C1, 0x0640); - } + phy_stacksave(0x0406); + bcm43xx_phy_write(bcm, 0x0406, 0x7E28); bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x0800); bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000); - stack_save(bcm43xx_phy_read(bcm, 0x04A0)); + phy_stacksave(0x04A0); bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008); - stack_save(bcm43xx_phy_read(bcm, 0x04A1)); + phy_stacksave(0x04A1); bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605); - stack_save(bcm43xx_phy_read(bcm, 0x04A2)); + phy_stacksave(0x04A2); bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204); - stack_save(bcm43xx_phy_read(bcm, 0x04A8)); + phy_stacksave(0x04A8); bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0403); - stack_save(bcm43xx_phy_read(bcm, 0x04AB)); + (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803); + phy_stacksave(0x04AB); bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0504); + (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605); - stack_save(bcm43xx_phy_read(bcm, 0x04A7)); + phy_stacksave(0x04A7); bcm43xx_phy_write(bcm, 0x04A7, 0x0002); - stack_save(bcm43xx_phy_read(bcm, 0x04A3)); + phy_stacksave(0x04A3); bcm43xx_phy_write(bcm, 0x04A3, 0x287A); - stack_save(bcm43xx_phy_read(bcm, 0x04A9)); + phy_stacksave(0x04A9); bcm43xx_phy_write(bcm, 0x04A9, 0x2027); - stack_save(bcm43xx_phy_read(bcm, 0x0493)); + phy_stacksave(0x0493); bcm43xx_phy_write(bcm, 0x0493, 0x32F5); - stack_save(bcm43xx_phy_read(bcm, 0x04AA)); + phy_stacksave(0x04AA); bcm43xx_phy_write(bcm, 0x04AA, 0x2027); - stack_save(bcm43xx_phy_read(bcm, 0x04AC)); + phy_stacksave(0x04AC); bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); break; case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - if (bcm43xx_phy_read(bcm, 0x0033) == 0x0800) + if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800) break; radio->aci_enable = 1; - stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)); - stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)); - if (bcm->current_core->rev < 5) { - stack_save(bcm43xx_phy_read(bcm, 0x0406)); + phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD); + phy_stacksave(BCM43xx_PHY_G_CRS); + if (phy->rev < 2) { + phy_stacksave(0x0406); } else { - stack_save(bcm43xx_phy_read(bcm, 0x04C0)); - stack_save(bcm43xx_phy_read(bcm, 0x04C1)); + phy_stacksave(0x04C0); + phy_stacksave(0x04C1); } - stack_save(bcm43xx_phy_read(bcm, 0x0033)); - stack_save(bcm43xx_phy_read(bcm, 0x04A7)); - stack_save(bcm43xx_phy_read(bcm, 0x04A3)); - stack_save(bcm43xx_phy_read(bcm, 0x04A9)); - stack_save(bcm43xx_phy_read(bcm, 0x04AA)); - stack_save(bcm43xx_phy_read(bcm, 0x04AC)); - stack_save(bcm43xx_phy_read(bcm, 0x0493)); - stack_save(bcm43xx_phy_read(bcm, 0x04A1)); - stack_save(bcm43xx_phy_read(bcm, 0x04A0)); - stack_save(bcm43xx_phy_read(bcm, 0x04A2)); - stack_save(bcm43xx_phy_read(bcm, 0x048A)); - stack_save(bcm43xx_phy_read(bcm, 0x04A8)); - stack_save(bcm43xx_phy_read(bcm, 0x04AB)); + phy_stacksave(0x0033); + phy_stacksave(0x04A7); + phy_stacksave(0x04A3); + phy_stacksave(0x04A9); + phy_stacksave(0x04AA); + phy_stacksave(0x04AC); + phy_stacksave(0x0493); + phy_stacksave(0x04A1); + phy_stacksave(0x04A0); + phy_stacksave(0x04A2); + phy_stacksave(0x048A); + phy_stacksave(0x04A8); + phy_stacksave(0x04AB); + if (phy->rev == 2) { + phy_stacksave(0x04AD); + phy_stacksave(0x04AE); + } else if (phy->rev >= 3) { + phy_stacksave(0x04AD); + phy_stacksave(0x0415); + phy_stacksave(0x0416); + phy_stacksave(0x0417); + ilt_stacksave(0x1A00 + 0x2); + ilt_stacksave(0x1A00 + 0x3); + } + phy_stacksave(0x042B); + phy_stacksave(0x048C); bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & 0xEFFF); + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) + & ~0x1000); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xEFFF) | 0x0002); + (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) + & 0xFFFC) | 0x0002); - bcm43xx_phy_write(bcm, 0x04A7, 0x0800); - bcm43xx_phy_write(bcm, 0x04A3, 0x287A); - bcm43xx_phy_write(bcm, 0x04A9, 0x2027); - bcm43xx_phy_write(bcm, 0x0493, 0x32F5); - bcm43xx_phy_write(bcm, 0x04AA, 0x2027); - bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); + bcm43xx_phy_write(bcm, 0x0033, 0x0800); + bcm43xx_phy_write(bcm, 0x04A3, 0x2027); + bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8); + bcm43xx_phy_write(bcm, 0x0493, 0x287A); + bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8); + bcm43xx_phy_write(bcm, 0x04AC, 0x287A); bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFC0) | 0x001A); - if (bcm->current_core->rev < 5) { - bcm43xx_phy_write(bcm, 0x0406, 0x280D); - } else { - bcm43xx_phy_write(bcm, 0x04C0, 0x0640); + (bcm43xx_phy_read(bcm, 0x04A0) + & 0xFFC0) | 0x001A); + bcm43xx_phy_write(bcm, 0x04A7, 0x000D); + + if (phy->rev < 2) { + bcm43xx_phy_write(bcm, 0x0406, 0xFF0D); + } else if (phy->rev == 2) { + bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF); bcm43xx_phy_write(bcm, 0x04C1, 0x00A9); + } else { + bcm43xx_phy_write(bcm, 0x04C0, 0x00C1); + bcm43xx_phy_write(bcm, 0x04C1, 0x0059); } bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0FF) | 0x1800); + (bcm43xx_phy_read(bcm, 0x04A1) + & 0xC0FF) | 0x1800); bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) & 0xFFC0) | 0x0016); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0900); - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0700); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x000D); + (bcm43xx_phy_read(bcm, 0x04A1) + & 0xFFC0) | 0x0015); bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) & 0xCFFF) | 0x1000); + (bcm43xx_phy_read(bcm, 0x04A8) + & 0xCFFF) | 0x1000); bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) & 0xF0FF) | 0x0A00); + (bcm43xx_phy_read(bcm, 0x04A8) + & 0xF0FF) | 0x0A00); bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xCFFF) | 0x1000); + (bcm43xx_phy_read(bcm, 0x04AB) + & 0xCFFF) | 0x1000); bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xF0FF) | 0x0800); + (bcm43xx_phy_read(bcm, 0x04AB) + & 0xF0FF) | 0x0800); bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFCF) | 0x0010); + (bcm43xx_phy_read(bcm, 0x04AB) + & 0xFFCF) | 0x0010); bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFF0) | 0x0006); + (bcm43xx_phy_read(bcm, 0x04AB) + & 0xFFF0) | 0x0005); + bcm43xx_phy_write(bcm, 0x04A8, + (bcm43xx_phy_read(bcm, 0x04A8) + & 0xFFCF) | 0x0010); + bcm43xx_phy_write(bcm, 0x04A8, + (bcm43xx_phy_read(bcm, 0x04A8) + & 0xFFF0) | 0x0006); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) + & 0xF0FF) | 0x0800); + bcm43xx_phy_write(bcm, 0x04A0, + (bcm43xx_phy_read(bcm, 0x04A0) + & 0xF0FF) | 0x0500); + bcm43xx_phy_write(bcm, 0x04A2, + (bcm43xx_phy_read(bcm, 0x04A2) + & 0xFFF0) | 0x000B); + if (phy->rev >= 3) { + bcm43xx_phy_write(bcm, 0x048A, + bcm43xx_phy_read(bcm, 0x048A) + & ~0x8000); + bcm43xx_phy_write(bcm, 0x0415, + (bcm43xx_phy_read(bcm, 0x0415) + & 0x8000) | 0x36D8); + bcm43xx_phy_write(bcm, 0x0416, + (bcm43xx_phy_read(bcm, 0x0416) + & 0x8000) | 0x36D8); + bcm43xx_phy_write(bcm, 0x0417, + (bcm43xx_phy_read(bcm, 0x0417) + & 0xFE00) | 0x016D); + } else { + bcm43xx_phy_write(bcm, 0x048A, + bcm43xx_phy_read(bcm, 0x048A) + | 0x1000); + bcm43xx_phy_write(bcm, 0x048A, + (bcm43xx_phy_read(bcm, 0x048A) + & 0x9FFF) | 0x2000); + tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET); + if (!(tmp32 & 0x800)) { + tmp32 |= 0x800; + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + tmp32); + } + } + if (phy->rev >= 2) { + bcm43xx_phy_write(bcm, 0x042B, + bcm43xx_phy_read(bcm, 0x042B) + | 0x0800); + } + bcm43xx_phy_write(bcm, 0x048C, + (bcm43xx_phy_read(bcm, 0x048C) + & 0xF0FF) | 0x0200); + if (phy->rev == 2) { + bcm43xx_phy_write(bcm, 0x04AE, + (bcm43xx_phy_read(bcm, 0x04AE) + & 0xFF00) | 0x007F); + bcm43xx_phy_write(bcm, 0x04AD, + (bcm43xx_phy_read(bcm, 0x04AD) + & 0x00FF) | 0x1300); + } else if (phy->rev >= 6) { + bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F); + bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F); + bcm43xx_phy_write(bcm, 0x04AD, + bcm43xx_phy_read(bcm, 0x04AD) + & 0x00FF); + } bcm43xx_calc_nrssi_slope(bcm); break; default: @@ -1055,9 +1194,8 @@ bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - int i = 0; - u16 *stack = radio->interfstack; - u16 tmp, flipped; + u32 tmp32; + u32 *stack = radio->interfstack; switch (mode) { case BCM43xx_RADIO_INTERFMODE_NONWLAN: @@ -1065,71 +1203,80 @@ bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000); break; } - tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); - flipped = flip_4bit(tmp); - if ((flipped >> 1) >= 0x000C) - tmp = flipped + 3; - tmp = flip_4bit(tmp); - bcm43xx_radio_write16(bcm, 0x0078, tmp << 1); - + phy_stackrestore(0x0078); bcm43xx_calc_nrssi_threshold(bcm); - - if (bcm->current_core->rev < 5) { - bcm43xx_phy_write(bcm, 0x0406, stack_restore()); - } else { - bcm43xx_phy_write(bcm, 0x04C0, stack_restore()); - bcm43xx_phy_write(bcm, 0x04C1, stack_restore()); - } + phy_stackrestore(0x0406); bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); - - if (!bcm->bad_frames_preempt) + if (!bcm->bad_frames_preempt) { bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & ~(1 << 11)); + bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) + & ~(1 << 11)); + } bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); - bcm43xx_phy_write(bcm, 0x04A0, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A1, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A2, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A8, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AB, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A7, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A3, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A9, stack_restore()); - bcm43xx_phy_write(bcm, 0x0493, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AA, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AC, stack_restore()); + bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000); + phy_stackrestore(0x04A0); + phy_stackrestore(0x04A1); + phy_stackrestore(0x04A2); + phy_stackrestore(0x04A8); + phy_stackrestore(0x04AB); + phy_stackrestore(0x04A7); + phy_stackrestore(0x04A3); + phy_stackrestore(0x04A9); + phy_stackrestore(0x0493); + phy_stackrestore(0x04AA); + phy_stackrestore(0x04AC); break; case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - if (bcm43xx_phy_read(bcm, 0x0033) != 0x0800) + if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800)) break; radio->aci_enable = 0; - bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, stack_restore()); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, stack_restore()); - if (bcm->current_core->rev < 5) { - bcm43xx_phy_write(bcm, 0x0406, stack_restore()); - } else { - bcm43xx_phy_write(bcm, 0x04C0, stack_restore()); - bcm43xx_phy_write(bcm, 0x04C1, stack_restore()); + phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD); + phy_stackrestore(BCM43xx_PHY_G_CRS); + phy_stackrestore(0x0033); + phy_stackrestore(0x04A3); + phy_stackrestore(0x04A9); + phy_stackrestore(0x0493); + phy_stackrestore(0x04AA); + phy_stackrestore(0x04AC); + phy_stackrestore(0x04A0); + phy_stackrestore(0x04A7); + if (phy->rev >= 2) { + phy_stackrestore(0x04C0); + phy_stackrestore(0x04C1); + } else + phy_stackrestore(0x0406); + phy_stackrestore(0x04A1); + phy_stackrestore(0x04AB); + phy_stackrestore(0x04A8); + if (phy->rev == 2) { + phy_stackrestore(0x04AD); + phy_stackrestore(0x04AE); + } else if (phy->rev >= 3) { + phy_stackrestore(0x04AD); + phy_stackrestore(0x0415); + phy_stackrestore(0x0416); + phy_stackrestore(0x0417); + ilt_stackrestore(0x1A00 + 0x2); + ilt_stackrestore(0x1A00 + 0x3); + } + phy_stackrestore(0x04A2); + phy_stackrestore(0x04A8); + phy_stackrestore(0x042B); + phy_stackrestore(0x048C); + tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET); + if (tmp32 & 0x800) { + tmp32 &= ~0x800; + bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, + BCM43xx_UCODEFLAGS_OFFSET, + tmp32); } - bcm43xx_phy_write(bcm, 0x0033, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A7, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A3, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A9, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AA, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AC, stack_restore()); - bcm43xx_phy_write(bcm, 0x0493, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A1, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A0, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A2, stack_restore()); - bcm43xx_phy_write(bcm, 0x04A8, stack_restore()); - bcm43xx_phy_write(bcm, 0x04AB, stack_restore()); - bcm43xx_calc_nrssi_slope(bcm); break; default: @@ -1137,8 +1284,12 @@ bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, } } -#undef stack_save -#undef stack_restore +#undef phy_stacksave +#undef phy_stackrestore +#undef radio_stacksave +#undef radio_stackrestore +#undef ilt_stacksave +#undef ilt_stackrestore int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode) -- cgit v1.2.2 From cf017e1b6f625978288e2cd8ede04f8185b97c08 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 22 Mar 2006 17:58:47 +0100 Subject: [PATCH] bcm43xx: fix nrssi_threshold calculation. patch by doctorzoidberg. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 72 +++++++++++++--------------- 1 file changed, 33 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c index 63aae43ba8..af5c0bff16 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c @@ -782,41 +782,30 @@ void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - s16 threshold; + s32 threshold; s32 a, b; - int tmp; s16 tmp16; u16 tmp_u16; switch (phy->type) { case BCM43xx_PHYTYPE_B: { - int radiotype = 0; - - if (phy->rev < 2) - return; if (radio->version != 0x2050) return; if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) return; - tmp = radio->revision; - if ((radio->manufact == 0x175 && tmp == 5) || - (radio->manufact == 0x17F && (tmp == 3 || tmp == 4))) - radiotype = 1; - - if (radiotype == 1) { + if (radio->revision >= 6) { + threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32; + threshold += 20 * (radio->nrssi[0] + 1); + threshold /= 40; + } else threshold = radio->nrssi[1] - 5; - } else { - threshold = 40 * radio->nrssi[0]; - threshold += 33 * (radio->nrssi[1] - radio->nrssi[0]); - threshold += 20; - threshold /= 10; - } + threshold = limit_value(threshold, 0, 0x3E); bcm43xx_phy_read(bcm, 0x0020); /* dummy read */ bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C); - if (radiotype == 1) { + if (radio->revision >= 6) { bcm43xx_phy_write(bcm, 0x0087, 0x0E0D); bcm43xx_phy_write(bcm, 0x0086, 0x0C0B); bcm43xx_phy_write(bcm, 0x0085, 0x0A09); @@ -844,33 +833,38 @@ void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) & 0xF000) | 0x0AED); } } else { - tmp = radio->interfmode; - if (tmp == BCM43xx_RADIO_INTERFMODE_NONWLAN) { - a = -13; - b = -17; - } else if (tmp == BCM43xx_RADIO_INTERFMODE_NONE && - !radio->aci_enable) { - a = -13; - b = -10; + if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) { + a = 0xE; + b = 0xA; + } else if (!radio->aci_wlan_automatic && radio->aci_enable) { + a = 0x13; + b = 0x12; } else { - a = -8; - b = -9; + a = 0xE; + b = 0x11; } - a += 0x1B; - a *= radio->nrssi[1] - radio->nrssi[0]; - a += radio->nrssi[0] * 0x40; - a /= 64; - b += 0x1B; - b *= radio->nrssi[1] - radio->nrssi[0]; - b += radio->nrssi[0] * 0x40; - b /= 64; + a = a * (radio->nrssi[1] - radio->nrssi[0]); + a += (radio->nrssi[0] << 6); + if (a < 32) + a += 31; + else + a += 32; + a = a >> 6; a = limit_value(a, -31, 31); + + b = b * (radio->nrssi[1] - radio->nrssi[0]); + b += (radio->nrssi[0] << 6); + if (b < 32) + b += 31; + else + b += 32; + b = b >> 6; b = limit_value(b, -31, 31); tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000; - tmp_u16 |= ((u32)a & 0x003F); - tmp_u16 |= (((u32)b & 0x003F) << 6); + tmp_u16 |= ((u32)b & 0x0000003F); + tmp_u16 |= (((u32)a & 0x0000003F) << 6); bcm43xx_phy_write(bcm, 0x048A, tmp_u16); } break; -- cgit v1.2.2 From 72fb851e971a416f47ad0a3ffca7342a424af37a Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 22 Mar 2006 18:10:19 +0100 Subject: [PATCH] bcm43xx: add useless and broken statistics stuff. People seem to want it. well... Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 2 ++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 3 ++ drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 52 ++++++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 57fcaafcf7..ae0fe5cf1d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -621,6 +621,8 @@ struct bcm43xx_noise_calculation { struct bcm43xx_stats { u8 link_quality; + u8 noise; + struct iw_statistics wstats; /* Store the last TX/RX times here for updating the leds. */ unsigned long last_tx; unsigned long last_rx; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index e680d2acc4..15deaa508e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1539,6 +1539,7 @@ static void handle_irq_noise(struct bcm43xx_private *bcm) average *= 125; average += 64; average /= 128; + tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C); tmp = (tmp / 128) & 0x1F; if (tmp >= 8) @@ -1550,6 +1551,8 @@ static void handle_irq_noise(struct bcm43xx_private *bcm) else average -= 48; +/* FIXME: This is wrong, but people want fancy stats. well... */ +bcm->stats.noise = average; if (average > -65) bcm->stats.link_quality = 0; else if (average > -75) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 651ba60549..e929634028 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -244,13 +244,13 @@ static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, range->max_qual.qual = 100; /* TODO: Real max RSSI */ - range->max_qual.level = 0; - range->max_qual.noise = 0; + range->max_qual.level = 3; + range->max_qual.noise = 100; range->max_qual.updated = 7; range->avg_qual.qual = 70; - range->avg_qual.level = 0; - range->avg_qual.noise = 0; + range->avg_qual.level = 2; + range->avg_qual.noise = 40; range->avg_qual.updated = 7; range->min_rts = BCM43xx_MIN_RTS_THRESHOLD; @@ -875,6 +875,49 @@ out: return err; } +/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */ + +static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev) +{ + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); + struct iw_statistics *wstats; + + wstats = &bcm->stats.wstats; + if (!mac->associated) { + wstats->miss.beacon = 0; +// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here? + wstats->discard.retries = 0; +// bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question + wstats->discard.nwid = 0; +// bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto + wstats->discard.code = 0; +// bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here + wstats->discard.fragment = 0; + wstats->discard.misc = 0; + wstats->qual.qual = 0; + wstats->qual.level = 0; + wstats->qual.noise = 0; + wstats->qual.updated = 7; + wstats->qual.updated |= IW_QUAL_NOISE_INVALID | + IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; + return wstats; + } + /* fill in the real statistics when iface associated */ + wstats->qual.qual = 100; // TODO: get the real signal quality + wstats->qual.level = 3 - bcm->stats.link_quality; + wstats->qual.noise = bcm->stats.noise; + wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | + IW_QUAL_NOISE_UPDATED; + wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable; + wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded; + wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa; + wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments; + wstats->discard.misc = 0; // FIXME + wstats->miss.beacon = 0; // FIXME + return wstats; +} + #ifdef WX # undef WX @@ -1010,6 +1053,7 @@ const struct iw_handler_def bcm43xx_wx_handlers_def = { .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args), .private = bcm43xx_priv_wx_handlers, .private_args = bcm43xx_priv_wx_args, + .get_wireless_stats = bcm43xx_get_wireless_stats, }; /* vim: set ts=8 sw=8 sts=8: */ -- cgit v1.2.2 From 04b98f71e2e3facc15e73b7e3ae9516ecb737375 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 25 Mar 2006 15:37:53 +0100 Subject: [PATCH] bcm43xx: get rid of "/* vim: ..." lines at the end of several files. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 2 -- drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 2 -- 8 files changed, 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index f73d36b8e0..d2c3401e9b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c @@ -497,5 +497,3 @@ void bcm43xx_printk_bitdump(const unsigned char *data, } printk("\n"); } - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 9c64438b76..18928acedd 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -968,5 +968,3 @@ void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) & ~BCM43xx_DMA_TXCTRL_SUSPEND); bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1); } - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index c8f5ad75d2..4b2c02c0b3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -291,5 +291,3 @@ void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) } bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); } - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 15deaa508e..281db642bd 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3956,5 +3956,3 @@ static void __exit bcm43xx_exit(void) module_init(bcm43xx_init) module_exit(bcm43xx_exit) - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index 5b6f0a84d0..c59ddd4068 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c @@ -604,5 +604,3 @@ data_ready: } bcm43xx_rx(queue->bcm, skb, rxhdr); } - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index 35c3c9704c..c44d890b94 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c @@ -320,5 +320,3 @@ void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm) device_remove_file(dev, &sysfs->attr_interfmode); device_remove_file(dev, &sysfs->attr_sprom); } - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index e929634028..e72be32bda 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -1055,5 +1055,3 @@ const struct iw_handler_def bcm43xx_wx_handlers_def = { .private_args = bcm43xx_priv_wx_args, .get_wireless_stats = bcm43xx_get_wireless_stats, }; - -/* vim: set ts=8 sw=8 sts=8: */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c index c4809da8e9..9c37478c80 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c @@ -577,5 +577,3 @@ int bcm43xx_rx(struct bcm43xx_private *bcm, return err; } - -/* vim: set ts=8 sw=8 sts=8: */ -- cgit v1.2.2 From d1ca6c4ff6714826acb1a434e5d3862984eb26d5 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 25 Mar 2006 15:43:18 +0100 Subject: [PATCH] bcm43xx: fix "include" issues on some platforms. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 3 +-- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 18928acedd..bad5374b81 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -34,11 +34,10 @@ #include "bcm43xx_power.h" #include "bcm43xx_xmit.h" -#include +#include #include #include #include -#include static inline int free_slots(struct bcm43xx_dmaring *ring) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 281db642bd..29df4f844c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "bcm43xx.h" -- cgit v1.2.2 From b5e868edbeaa5fd832d42563195c0da00edfd3c9 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 25 Mar 2006 16:27:32 +0100 Subject: [PATCH] bcm43xx: remove some compilerwarnings. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 1 - drivers/net/wireless/bcm43xx/bcm43xx_main.c | 10 ++++-- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 55 ----------------------------- drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 7 ++-- 4 files changed, 13 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index bad5374b81..c3681b8f09 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -787,7 +787,6 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, struct bcm43xx_xmitstatus *status) { - struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); struct bcm43xx_dmaring *ring; struct bcm43xx_dmadesc *desc; struct bcm43xx_dmadesc_meta *meta; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 29df4f844c..ac9a8dd1ab 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -404,6 +404,8 @@ static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm) bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i))); } +//FIXME: Well, we should probably call them from somewhere. +#if 0 static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) { /* slot_time is in usec. */ @@ -422,8 +424,12 @@ static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm) { bcm43xx_set_slot_time(bcm, 20); } +#endif -//FIXME: rename this func? +/* FIXME: To get the MAC-filter working, we need to implement the + * following functions (and rename them :) + */ +#if 0 static void bcm43xx_disassociate(struct bcm43xx_private *bcm) { bcm43xx_mac_suspend(bcm); @@ -451,7 +457,6 @@ static void bcm43xx_disassociate(struct bcm43xx_private *bcm) bcm43xx_mac_enable(bcm); } -//FIXME: rename this func? static void bcm43xx_associate(struct bcm43xx_private *bcm, const u8 *mac) { @@ -462,6 +467,7 @@ static void bcm43xx_associate(struct bcm43xx_private *bcm, bcm43xx_write_mac_bssid_templates(bcm); bcm43xx_mac_enable(bcm); } +#endif /* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. * Returns the _previously_ enabled IRQ mask. diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index e72be32bda..3daee828ef 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -106,7 +106,6 @@ static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, char *extra) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct ieee80211softmac_device *softmac = bcm->softmac; unsigned long flags; u8 channel; int freq; @@ -205,24 +204,6 @@ static int bcm43xx_wx_get_mode(struct net_device *net_dev, return 0; } -static int bcm43xx_wx_set_sensitivity(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - -static int bcm43xx_wx_get_sensitivity(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, struct iw_request_info *info, union iwreq_data *data, @@ -517,24 +498,6 @@ out_unlock: return err; } -static int bcm43xx_wx_set_retry(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - -static int bcm43xx_wx_get_retry(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - static int bcm43xx_wx_set_encoding(struct net_device *net_dev, struct iw_request_info *info, union iwreq_data *data, @@ -587,24 +550,6 @@ static int bcm43xx_wx_get_encodingext(struct net_device *net_dev, return err; } -static int bcm43xx_wx_set_power(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - -static int bcm43xx_wx_get_power(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - /*TODO*/ - return 0; -} - static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, struct iw_request_info *info, union iwreq_data *data, diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c index 9c37478c80..d8ece28c07 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c @@ -215,7 +215,7 @@ static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy, u8 fallback_bitrate; int ofdm_modulation; int fallback_ofdm_modulation; - u8 *sa, *da; +// u8 *sa, *da; u16 flen; //FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr); @@ -267,7 +267,7 @@ assert(dur); //printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3)); //printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da)); memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME! - memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN); +// memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN); *flags |= BCM43xx_TXHDRFLAG_RTSCTS; *flags |= BCM43xx_TXHDRFLAG_RTS; @@ -439,6 +439,8 @@ static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, return (s8)tmp; } +//TODO +#if 0 static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, u8 in_rssi) { @@ -453,6 +455,7 @@ static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, return ret; } +#endif int bcm43xx_rx(struct bcm43xx_private *bcm, struct sk_buff *skb, -- cgit v1.2.2 From 8afceb1e6a3b6361c7c2456ef488ee9c6db7b370 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 25 Mar 2006 17:04:41 +0100 Subject: [PATCH] bcm43xx: fix the remaining sparse warnings. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4 ++-- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index ac9a8dd1ab..7c1d72fc62 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2509,7 +2509,7 @@ error: return -ENODEV; } -void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy) +static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy) { /* Initialize a "phyinfo" structure. The structure is already * zeroed out. @@ -2521,7 +2521,7 @@ void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy) spin_lock_init(&phy->lock); } -void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio) +static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio) { /* Initialize a "radioinfo" structure. The structure is already * zeroed out. diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 054c64e462..4ab17a7f7e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -1057,9 +1057,14 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) bcm43xx_phy_write(bcm, 0x002F, 0x0202); } - if ((bcm->sprom.boardflags & BCM43xx_BFL_RSSI) == 0) { - FIXME();//FIXME: 0x7FFFFFFF should be 16-bit ! - bcm43xx_nrssi_hw_update(bcm, (u16)0x7FFFFFFF); + if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) { + /* The specs state to update the NRSSI LT with + * the value 0x7FFFFFFF here. I think that is some weird + * compiler optimization in the original driver. + * Essentially, what we do here is resetting all NRSSI LT + * entries to -32 (see the limit_value() in nrssi_hw_update()) + */ + bcm43xx_nrssi_hw_update(bcm, 0xFFFF); bcm43xx_calc_nrssi_threshold(bcm); } else if (phy->connected) { if (radio->nrssi[0] == -1000) { -- cgit v1.2.2 From adc40e9796d03d56e99bdac62492492a1098124b Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 25 Mar 2006 20:36:57 +0100 Subject: [PATCH] bcm43xx: sync GPHY init with the specs. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 5 + drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4 +- drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 275 +++++++++++++++++++++++++--- 3 files changed, 255 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index ae0fe5cf1d..dcadd295de 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -495,6 +495,10 @@ struct bcm43xx_phyinfo { const s8 *tssi2dbm; /* idle TSSI value */ s8 idle_tssi; + + /* Values from bcm43xx_calc_loopback_gain() */ + u16 loopback_gain[2]; + /* PHY lock for core.rev < 3 * This lock is only used by bcm43xx_phy_{un}lock() */ @@ -674,6 +678,7 @@ struct bcm43xx_private { u16 chip_id; u8 chip_rev; + u8 chip_package; struct bcm43xx_sprominfo sprom; #define BCM43xx_NR_LEDS 4 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 7c1d72fc62..2b7ef9b46c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -570,6 +570,7 @@ static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm); radio->radio_atten = bcm43xx_default_radio_attenuation(bcm); radio->txctl1 = bcm43xx_default_txctl1(bcm); + radio->txctl2 = 0xFFFF; if (phy->type == BCM43xx_PHYTYPE_A) radio->txpower_desired = bcm->sprom.maxpower_aphy; else @@ -2635,7 +2636,8 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) } bcm->chip_id = chip_id_16; - bcm->chip_rev = (chip_id_32 & 0x000f0000) >> 16; + bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16; + bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20; dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n", bcm->chip_id, bcm->chip_rev); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 4ab17a7f7e..0a66f43ca0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c @@ -994,12 +994,205 @@ static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) bcm43xx_write16(bcm, 0x03E6, 0x0); } +static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) +{ + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + u16 backup_phy[15]; + u16 backup_radio[3]; + u16 backup_bband; + u16 i; + u16 loop1_cnt, loop1_done, loop1_omitted; + u16 loop2_done; + + backup_phy[0] = bcm43xx_phy_read(bcm, 0x0429); + backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001); + backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811); + backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812); + backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814); + backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815); + backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A); + backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059); + backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058); + backup_phy[9] = bcm43xx_phy_read(bcm, 0x000A); + backup_phy[10] = bcm43xx_phy_read(bcm, 0x0003); + backup_phy[11] = bcm43xx_phy_read(bcm, 0x080F); + backup_phy[12] = bcm43xx_phy_read(bcm, 0x0810); + backup_phy[13] = bcm43xx_phy_read(bcm, 0x002B); + backup_phy[14] = bcm43xx_phy_read(bcm, 0x0015); + bcm43xx_phy_read(bcm, 0x002D); /* dummy read */ + backup_bband = radio->baseband_atten; + backup_radio[0] = bcm43xx_radio_read16(bcm, 0x0052); + backup_radio[1] = bcm43xx_radio_read16(bcm, 0x0043); + backup_radio[2] = bcm43xx_radio_read16(bcm, 0x007A); + + bcm43xx_phy_write(bcm, 0x0429, + bcm43xx_phy_read(bcm, 0x0429) & 0x3FFF); + bcm43xx_phy_write(bcm, 0x0001, + bcm43xx_phy_read(bcm, 0x0001) & 0x8000); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x0002); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) & 0xFFFD); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x0001); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE); + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0001); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0002); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x000C); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) | 0x000C); + + bcm43xx_phy_write(bcm, 0x0811, + (bcm43xx_phy_read(bcm, 0x0811) + & 0xFFCF) | 0x0030); + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) + & 0xFFCF) | 0x0010); + + bcm43xx_phy_write(bcm, 0x005A, 0x0780); + bcm43xx_phy_write(bcm, 0x0059, 0xC810); + bcm43xx_phy_write(bcm, 0x0058, 0x000D); + if (phy->version == 0) { + bcm43xx_phy_write(bcm, 0x0003, 0x0122); + } else { + bcm43xx_phy_write(bcm, 0x000A, + bcm43xx_phy_read(bcm, 0x000A) + | 0x2000); + } + bcm43xx_phy_write(bcm, 0x0814, + bcm43xx_phy_read(bcm, 0x0814) | 0x0004); + bcm43xx_phy_write(bcm, 0x0815, + bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); + bcm43xx_phy_write(bcm, 0x0003, + (bcm43xx_phy_read(bcm, 0x0003) + & 0xFF9F) | 0x0040); + if (radio->version == 0x2050 && radio->revision == 2) { + bcm43xx_radio_write16(bcm, 0x0052, 0x0000); + bcm43xx_radio_write16(bcm, 0x0043, + (bcm43xx_radio_read16(bcm, 0x0043) + & 0xFFF0) | 0x0009); + loop1_cnt = 9; + } else if (radio->revision == 8) { + bcm43xx_radio_write16(bcm, 0x0043, 0x000F); + loop1_cnt = 15; + } else + loop1_cnt = 0; + + bcm43xx_phy_set_baseband_attenuation(bcm, 11); + + if (phy->rev >= 3) + bcm43xx_phy_write(bcm, 0x080F, 0xC020); + else + bcm43xx_phy_write(bcm, 0x080F, 0x8020); + bcm43xx_phy_write(bcm, 0x0810, 0x0000); + + bcm43xx_phy_write(bcm, 0x002B, + (bcm43xx_phy_read(bcm, 0x002B) + & 0xFFC0) | 0x0001); + bcm43xx_phy_write(bcm, 0x002B, + (bcm43xx_phy_read(bcm, 0x002B) + & 0xC0FF) | 0x0800); + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) | 0x0100); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF); + if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) { + if (phy->rev >= 7) { + bcm43xx_phy_write(bcm, 0x0811, + bcm43xx_phy_read(bcm, 0x0811) + | 0x0800); + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) + | 0x8000); + } + } + bcm43xx_radio_write16(bcm, 0x007A, + bcm43xx_radio_read16(bcm, 0x007A) + & 0x00F7); + + for (i = 0; i < loop1_cnt; i++) { + bcm43xx_radio_write16(bcm, 0x0043, loop1_cnt); + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) + & 0xF0FF) | (i << 8)); + bcm43xx_phy_write(bcm, 0x0015, + (bcm43xx_phy_read(bcm, 0x0015) + & 0x0FFF) | 0xA000); + bcm43xx_phy_write(bcm, 0x0015, + (bcm43xx_phy_read(bcm, 0x0015) + & 0x0FFF) | 0xF000); + udelay(20); + if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC) + break; + } + loop1_done = i; + loop1_omitted = loop1_cnt - loop1_done; + + loop2_done = 0; + if (loop1_done >= 8) { + bcm43xx_phy_write(bcm, 0x0812, + bcm43xx_phy_read(bcm, 0x0812) + | 0x0030); + for (i = loop1_done - 8; i < 16; i++) { + bcm43xx_phy_write(bcm, 0x0812, + (bcm43xx_phy_read(bcm, 0x0812) + & 0xF0FF) | (i << 8)); + bcm43xx_phy_write(bcm, 0x0015, + (bcm43xx_phy_read(bcm, 0x0015) + & 0x0FFF) | 0xA000); + bcm43xx_phy_write(bcm, 0x0015, + (bcm43xx_phy_read(bcm, 0x0015) + & 0x0FFF) | 0xF000); + udelay(20); + if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC) + break; + } + } + + bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]); + bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]); + bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]); + bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]); + bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]); + bcm43xx_phy_write(bcm, 0x000A, backup_phy[9]); + bcm43xx_phy_write(bcm, 0x0003, backup_phy[10]); + bcm43xx_phy_write(bcm, 0x080F, backup_phy[11]); + bcm43xx_phy_write(bcm, 0x0810, backup_phy[12]); + bcm43xx_phy_write(bcm, 0x002B, backup_phy[13]); + bcm43xx_phy_write(bcm, 0x0015, backup_phy[14]); + + bcm43xx_phy_set_baseband_attenuation(bcm, backup_bband); + + bcm43xx_radio_write16(bcm, 0x0052, backup_radio[0]); + bcm43xx_radio_write16(bcm, 0x0043, backup_radio[1]); + bcm43xx_radio_write16(bcm, 0x007A, backup_radio[2]); + + bcm43xx_phy_write(bcm, 0x0811, backup_phy[2] | 0x0003); + udelay(10); + bcm43xx_phy_write(bcm, 0x0811, backup_phy[2]); + bcm43xx_phy_write(bcm, 0x0812, backup_phy[3]); + bcm43xx_phy_write(bcm, 0x0429, backup_phy[0]); + bcm43xx_phy_write(bcm, 0x0001, backup_phy[1]); + + phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11; + phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2; +} + static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) { struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 tmp; - + if (phy->rev == 1) bcm43xx_phy_initb5(bcm); else if (phy->rev >= 2 && phy->rev <= 7) @@ -1015,47 +1208,63 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) else if (phy->rev >= 3) bcm43xx_phy_write(bcm, 0x0811, 0x0400); bcm43xx_phy_write(bcm, 0x0015, 0x00C0); - tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; - if (tmp == 3) { - bcm43xx_phy_write(bcm, 0x04C2, 0x1816); - bcm43xx_phy_write(bcm, 0x04C3, 0x8606); - } else if (tmp == 4 || tmp == 5) { - bcm43xx_phy_write(bcm, 0x04C2, 0x1816); - bcm43xx_phy_write(bcm, 0x04C3, 0x8006); - bcm43xx_phy_write(bcm, 0x04CC, (bcm43xx_phy_read(bcm, 0x04CC) - & 0x00FF) | 0x1F00); + if (phy->connected) { + tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; + if (tmp < 6) { + bcm43xx_phy_write(bcm, 0x04C2, 0x1816); + bcm43xx_phy_write(bcm, 0x04C3, 0x8006); + if (tmp != 3) { + bcm43xx_phy_write(bcm, 0x04CC, + (bcm43xx_phy_read(bcm, 0x04CC) + & 0x00FF) | 0x1F00); + } + } } } - if (radio->revision <= 3 && phy->connected) + if (phy->rev < 3 && phy->connected) bcm43xx_phy_write(bcm, 0x047E, 0x0078); - if (radio->revision >= 6 && radio->revision <= 8) { + if (phy->rev >= 6 && phy->rev <= 8) { bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080); bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004); } - if (radio->initval == 0xFFFF) { - radio->initval = bcm43xx_radio_init2050(bcm); + if (phy->rev >= 2 && phy->connected) + bcm43xx_calc_loopback_gain(bcm); + if (radio->revision != 8) { + if (radio->initval == 0xFFFF) + radio->initval = bcm43xx_radio_init2050(bcm); + else + bcm43xx_radio_write16(bcm, 0x0078, radio->initval); + } + if (radio->txctl2 == 0xFFFF) { bcm43xx_phy_lo_g_measure(bcm); } else { - bcm43xx_radio_write16(bcm, 0x0078, radio->initval); - bcm43xx_radio_write16(bcm, 0x0052, - (bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0) - | radio->txctl2); - } - - if (phy->connected) { - bcm43xx_phy_lo_adjust(bcm, 0); - bcm43xx_phy_write(bcm, 0x080F, 0x8078); - + if (radio->version == 0x2050 && radio->revision == 8) { + //FIXME + } else { + bcm43xx_radio_write16(bcm, 0x0052, + (bcm43xx_radio_read16(bcm, 0x0052) + & 0xFFF0) | radio->txctl1); + } + if (phy->rev >= 6) { + /* + bcm43xx_phy_write(bcm, 0x0036, + (bcm43xx_phy_read(bcm, 0x0036) + & 0xF000) | (FIXME << 12)); + */ + } if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) - bcm43xx_phy_write(bcm, 0x002E, 0x807F); - else bcm43xx_phy_write(bcm, 0x002E, 0x8075); - + else + bcm43xx_phy_write(bcm, 0x003E, 0x807F); if (phy->rev < 2) bcm43xx_phy_write(bcm, 0x002F, 0x0101); else bcm43xx_phy_write(bcm, 0x002F, 0x0202); } + if (phy->connected) { + bcm43xx_phy_lo_adjust(bcm, 0); + bcm43xx_phy_write(bcm, 0x080F, 0x8078); + } if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) { /* The specs state to update the NRSSI LT with @@ -1070,10 +1279,20 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) if (radio->nrssi[0] == -1000) { assert(radio->nrssi[1] == -1000); bcm43xx_calc_nrssi_slope(bcm); - } else + } else { + assert(radio->nrssi[1] != -1000); bcm43xx_calc_nrssi_threshold(bcm); + } } + if (radio->revision == 8) + bcm43xx_phy_write(bcm, 0x0805, 0x3230); bcm43xx_phy_init_pctl(bcm); + if (bcm->chip_id == 0x4306 && bcm->chip_package != 2) { + bcm43xx_phy_write(bcm, 0x0429, + bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF); + bcm43xx_phy_write(bcm, 0x04C3, + bcm43xx_phy_read(bcm, 0x04C3) & 0x7FFF); + } } static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) -- cgit v1.2.2 From ec483781fe98bba92e00f4428f8d69dd5e071246 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 27 Mar 2006 11:49:51 +0200 Subject: [PATCH] bcm43xx: don't set the channel on a device, which is down. Initial patch by David Woodhouse and Michael Marineau. Locking fix by me. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 2b7ef9b46c..c37371fc9e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3530,12 +3530,18 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, u8 channel) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct bcm43xx_radioinfo *radio; unsigned long flags; bcm43xx_lock_mmio(bcm, flags); - bcm43xx_mac_suspend(bcm); - bcm43xx_radio_selectchannel(bcm, channel, 0); - bcm43xx_mac_enable(bcm); + if (bcm->initialized) { + bcm43xx_mac_suspend(bcm); + bcm43xx_radio_selectchannel(bcm, channel, 0); + bcm43xx_mac_enable(bcm); + } else { + radio = bcm43xx_current_radio(bcm); + radio->initial_channel = channel; + } bcm43xx_unlock_mmio(bcm, flags); } -- cgit v1.2.2 From e4a9af98bb0fab13be6e3adbe108d565b790158a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 24 Mar 2006 17:56:19 +0100 Subject: [PATCH] PCMCIA_SPECTRUM must select FW_LOADER PCMCIA_SPECTRUM must select FW_LOADER. Reported by "Alexander E. Patrakov" . Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 9c01fb26c8..f85e301900 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -404,6 +404,7 @@ config PCMCIA_HERMES config PCMCIA_SPECTRUM tristate "Symbol Spectrum24 Trilogy PCMCIA card support" depends on NET_RADIO && PCMCIA && HERMES + select FW_LOADER ---help--- This is a driver for 802.11b cards using RAM-loadable Symbol -- cgit v1.2.2 From 0073602544954002e35699477dc59cdd5e9112e3 Mon Sep 17 00:00:00 2001 From: Jean Tourrilhes Date: Fri, 24 Mar 2006 16:45:24 -0800 Subject: [PATCH] zd1201 wireless stat update The "dev->get_wireless_stats" field is deprecated and slowly be surely going away. Most drivers have been updated months ago. Actually, there is an annoying message for driver still using it, but it seems that user of zd1201 were not annoyed enough ;-) Signed-off-by: Jean Tourrilhes Signed-off-by: John W. Linville --- drivers/usb/net/zd1201.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c index fe9b60cd8d..9b1e4ed1d0 100644 --- a/drivers/usb/net/zd1201.c +++ b/drivers/usb/net/zd1201.c @@ -1736,6 +1736,7 @@ static const struct iw_handler_def zd1201_iw_handlers = { .standard = (iw_handler *)zd1201_iw_handler, .private = (iw_handler *)zd1201_private_handler, .private_args = (struct iw_priv_args *) zd1201_private_args, + .get_wireless_stats = zd1201_get_wireless_stats, }; static int zd1201_probe(struct usb_interface *interface, @@ -1796,7 +1797,6 @@ static int zd1201_probe(struct usb_interface *interface, zd->dev->open = zd1201_net_open; zd->dev->stop = zd1201_net_stop; zd->dev->get_stats = zd1201_get_stats; - zd->dev->get_wireless_stats = zd1201_get_wireless_stats; zd->dev->wireless_handlers = (struct iw_handler_def *)&zd1201_iw_handlers; zd->dev->hard_start_xmit = zd1201_hard_start_xmit; -- cgit v1.2.2 From 79058acaf5b6d4bcc3056382619de3ca9cebc62f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Mar 2006 21:24:54 -0800 Subject: [PATCH] hostap: Make hostap_tx_encrypt() static hostap_tx_encrypt() is used only inside hostap_80211_tx.c and there are no plans to use it elsewhere in the future either, so let's make it static. As a bonus, this should silence Coverity scanner from complaining about bogus FORWARD_NULL case (CID: 274). Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_80211.h | 2 -- drivers/net/wireless/hostap/hostap_80211_tx.c | 7 +++---- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h index 1fc72fe511..cc1ee7f4f5 100644 --- a/drivers/net/wireless/hostap/hostap_80211.h +++ b/drivers/net/wireless/hostap/hostap_80211.h @@ -92,8 +92,6 @@ void hostap_dump_rx_80211(const char *name, struct sk_buff *skb, void hostap_dump_tx_80211(const char *name, struct sk_buff *skb); int hostap_data_start_xmit(struct sk_buff *skb, struct net_device *dev); int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev); -struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, - struct ieee80211_crypt_data *crypt); int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev); #endif /* HOSTAP_80211_H */ diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c index 4a85e63906..a881212e1f 100644 --- a/drivers/net/wireless/hostap/hostap_80211_tx.c +++ b/drivers/net/wireless/hostap/hostap_80211_tx.c @@ -299,8 +299,8 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Called only from software IRQ */ -struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, - struct ieee80211_crypt_data *crypt) +static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, + struct ieee80211_crypt_data *crypt) { struct hostap_interface *iface; local_info_t *local; @@ -317,7 +317,7 @@ struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, } if (local->tkip_countermeasures && - crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) { + strcmp(crypt->ops->name, "TKIP") == 0) { hdr = (struct ieee80211_hdr_4addr *) skb->data; if (net_ratelimit()) { printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " @@ -535,5 +535,4 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev) EXPORT_SYMBOL(hostap_dump_tx_80211); -EXPORT_SYMBOL(hostap_tx_encrypt); EXPORT_SYMBOL(hostap_master_start_xmit); -- cgit v1.2.2 From cfa146e4be274fd04bfdb26b3c96cdfe81a43dc2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Mar 2006 21:24:55 -0800 Subject: [PATCH] hostap: Fix EAPOL frame encryption Fixed encrypted of EAPOL frames from wlan#ap interface (hostapd). This was broken when moving to use new frame control field defines in net/ieee80211.h. hostapd uses Protected flag, not protocol version (which was cleared in this function anyway). This fixes WPA group key handshake and re-authentication. http://hostap.epitest.fi/bugz/show_bug.cgi?id=126 Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_80211_tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c index a881212e1f..06a5214145 100644 --- a/drivers/net/wireless/hostap/hostap_80211_tx.c +++ b/drivers/net/wireless/hostap/hostap_80211_tx.c @@ -469,7 +469,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev) } if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt && - !(fc & IEEE80211_FCTL_VERS)) { + !(fc & IEEE80211_FCTL_PROTECTED)) { no_encrypt = 1; PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing " "unencrypted EAPOL frame\n", dev->name); -- cgit v1.2.2 From 45d607ed92695d7543f5e1fc5b133cd69834e3e4 Mon Sep 17 00:00:00 2001 From: "Ryan S. Arnold" Date: Mon, 27 Mar 2006 21:25:16 +0200 Subject: [PATCH] powerpc: hvc_console updates These are some updates from both Ryan and Arnd for the hvc_console driver: The main point is to enable the inclusion of a console driver for rtas, which is currrently needed for the cell platform. Also shuffle around some data-type declarations and moves some functions out of include/asm-ppc64/hvconsole.h and into a new drivers/char/hvc_console.h file. Signed-off-by: "Ryan S. Arnold" Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- drivers/char/Kconfig | 10 +++++++ drivers/char/Makefile | 3 +- drivers/char/hvc_console.c | 69 +++++++++++++++++++--------------------------- drivers/char/hvc_console.h | 63 ++++++++++++++++++++++++++++++++++++++++++ drivers/char/hvc_vio.c | 11 ++++++++ 5 files changed, 115 insertions(+), 41 deletions(-) create mode 100644 drivers/char/hvc_console.h (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index facc3f1d9e..831419381c 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -561,9 +561,19 @@ config TIPAR If unsure, say N. +config HVC_DRIVER + bool + help + Users of pSeries machines that want to utilize the hvc console front-end + module for their backend console driver should select this option. + It will automatically be selected if one of the back-end console drivers + is selected. + + config HVC_CONSOLE bool "pSeries Hypervisor Virtual Console support" depends on PPC_PSERIES + select HVC_DRIVER help pSeries machines when partitioned support a hypervisor virtual console. This driver allows each pSeries partition to have a console diff --git a/drivers/char/Makefile b/drivers/char/Makefile index b2a11245fa..e6c03335fd 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -41,7 +41,8 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o -obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o +obj-$(CONFIG_HVC_DRIVER) += hvc_console.o +obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MMTIMER) += mmtimer.o diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index a94c5b0cac..2b6a56b2bf 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -39,8 +39,10 @@ #include #include #include + #include -#include + +#include "hvc_console.h" #define HVC_MAJOR 229 #define HVC_MINOR 0 @@ -54,17 +56,14 @@ #define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */ /* - * The Linux TTY code does not support dynamic addition of tty derived devices - * so we need to know how many tty devices we might need when space is allocated - * for the tty device. Since this driver supports hotplug of vty adapters we - * need to make sure we have enough allocated. + * These sizes are most efficient for vio, because they are the + * native transfer size. We could make them selectable in the + * future to better deal with backends that want other buffer sizes. */ -#define HVC_ALLOC_TTY_ADAPTERS 8 - #define N_OUTBUF 16 #define N_INBUF 16 -#define __ALIGNED__ __attribute__((__aligned__(8))) +#define __ALIGNED__ __attribute__((__aligned__(sizeof(long)))) static struct tty_driver *hvc_driver; static struct task_struct *hvc_task; @@ -154,7 +153,7 @@ static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] = void hvc_console_print(struct console *co, const char *b, unsigned count) { - char c[16] __ALIGNED__; + char c[N_OUTBUF] __ALIGNED__; unsigned i = 0, n = 0; int r, donecr = 0, index = co->index; @@ -473,8 +472,10 @@ static void hvc_push(struct hvc_struct *hp) n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf); if (n <= 0) { - if (n == 0) + if (n == 0) { + hp->do_wakeup = 1; return; + } /* throw away output on error; this happens when there is no session connected to the vterm. */ hp->n_outbuf = 0; @@ -486,12 +487,19 @@ static void hvc_push(struct hvc_struct *hp) hp->do_wakeup = 1; } -static inline int __hvc_write_kernel(struct hvc_struct *hp, - const unsigned char *buf, int count) +static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count) { + struct hvc_struct *hp = tty->driver_data; unsigned long flags; int rsize, written = 0; + /* This write was probably executed during a tty close. */ + if (!hp) + return -EPIPE; + + if (hp->count <= 0) + return -EIO; + spin_lock_irqsave(&hp->lock, flags); /* Push pending writes */ @@ -510,26 +518,8 @@ static inline int __hvc_write_kernel(struct hvc_struct *hp, } spin_unlock_irqrestore(&hp->lock, flags); - return written; -} -static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count) -{ - struct hvc_struct *hp = tty->driver_data; - int written; - - /* This write was probably executed during a tty close. */ - if (!hp) - return -EPIPE; - - if (hp->count <= 0) - return -EIO; - - written = __hvc_write_kernel(hp, buf, count); - /* * Racy, but harmless, kick thread if there is still pending data. - * There really is nothing wrong with kicking the thread, even if there - * is no buffered data. */ if (hp->n_outbuf) hvc_kick(); @@ -614,6 +604,13 @@ static int hvc_poll(struct hvc_struct *hp) spin_unlock_irqrestore(&hp->lock, flags); tty_hangup(tty); spin_lock_irqsave(&hp->lock, flags); + } else if ( n == -EAGAIN ) { + /* + * Some back-ends can only ensure a certain min + * num of bytes read, which may be > 'count'. + * Let the tty clear the flip buff to make room. + */ + poll_mask |= HVC_POLL_READ; } break; } @@ -635,16 +632,7 @@ static int hvc_poll(struct hvc_struct *hp) tty_insert_flip_char(tty, buf[i], 0); } - /* - * Account for the total amount read in one loop, and if above - * 64 bytes, we do a quick schedule loop to let the tty grok - * the data and eventually throttle us. - */ read_total += n; - if (read_total >= 64) { - poll_mask |= HVC_POLL_QUICK; - break; - } } throttled: /* Wakeup write queue if necessary */ @@ -767,7 +755,8 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, * see if this vterm id matches one registered for console. */ for (i=0; i < MAX_NR_HVC_CONSOLES; i++) - if (vtermnos[i] == hp->vtermno) + if (vtermnos[i] == hp->vtermno && + cons_ops[i] == hp->ops) break; /* no matching slot, just use a counter */ diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h new file mode 100644 index 0000000000..96b7401319 --- /dev/null +++ b/drivers/char/hvc_console.h @@ -0,0 +1,63 @@ +/* + * hvc_console.h + * Copyright (C) 2005 IBM Corporation + * + * Author(s): + * Ryan S. Arnold + * + * hvc_console header information: + * moved here from include/asm-powerpc/hvconsole.h + * and drivers/char/hvc_console.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef HVC_CONSOLE_H +#define HVC_CONSOLE_H + +/* + * This is the max number of console adapters that can/will be found as + * console devices on first stage console init. Any number beyond this range + * can't be used as a console device but is still a valid tty device. + */ +#define MAX_NR_HVC_CONSOLES 16 + +/* + * The Linux TTY code does not support dynamic addition of tty derived devices + * so we need to know how many tty devices we might need when space is allocated + * for the tty device. Since this driver supports hotplug of vty adapters we + * need to make sure we have enough allocated. + */ +#define HVC_ALLOC_TTY_ADAPTERS 8 + + +/* implemented by a low level driver */ +struct hv_ops { + int (*get_chars)(uint32_t vtermno, char *buf, int count); + int (*put_chars)(uint32_t vtermno, const char *buf, int count); +}; + +struct hvc_struct; + +/* Register a vterm and a slot index for use as a console (console_init) */ +extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); + +/* register a vterm for hvc tty operation (module_init or hotplug add) */ +extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq, + struct hv_ops *ops); +/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ +extern int __devexit hvc_remove(struct hvc_struct *hp); + +#endif // HVC_CONSOLE_H diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index f5212eb2b4..9add81ceb4 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c @@ -31,10 +31,13 @@ #include #include + #include #include #include +#include "hvc_console.h" + char hvc_driver_name[] = "hvc_console"; static struct vio_device_id hvc_driver_table[] __devinitdata = { @@ -48,6 +51,14 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count) unsigned long got; int i; + /* + * Vio firmware will read up to SIZE_VIO_GET_CHARS at its own discretion + * so we play safe and avoid the situation where got > count which could + * overload the flip buffer. + */ + if (count < SIZE_VIO_GET_CHARS) + return -EAGAIN; + got = hvc_get_chars(vtermno, buf, count); /* -- cgit v1.2.2 From f4d1749e9570d3984800c371c6e06eb35b9718b1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 27 Mar 2006 21:26:03 +0200 Subject: [PATCH] powerpc: add hvc backend for rtas Current Cell hardware is using the console through a set of rtas calls. This driver is needed to get console output on those boards. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- drivers/char/Kconfig | 7 +++ drivers/char/Makefile | 1 + drivers/char/hvc_rtas.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 drivers/char/hvc_rtas.c (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 831419381c..7a85b3a26f 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -579,6 +579,13 @@ config HVC_CONSOLE console. This driver allows each pSeries partition to have a console which is accessed via the HMC. +config HVC_RTAS + bool "IBM RTAS Console support" + depends on PPC_RTAS + select HVC_DRIVER + help + IBM Console device driver which makes use of RTAS + config HVCS tristate "IBM Hypervisor Virtual Console Server support" depends on PPC_PSERIES diff --git a/drivers/char/Makefile b/drivers/char/Makefile index e6c03335fd..a73cb49569 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o obj-$(CONFIG_HVC_DRIVER) += hvc_console.o obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o +obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MMTIMER) += mmtimer.o diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c new file mode 100644 index 0000000000..83364ea63c --- /dev/null +++ b/drivers/char/hvc_rtas.c @@ -0,0 +1,138 @@ +/* + * IBM RTAS driver interface to hvc_console.c + * + * (C) Copyright IBM Corporation 2001-2005 + * (C) Copyright Red Hat, Inc. 2005 + * + * Author(s): Maximino Augilar + * : Ryan S. Arnold + * : Utz Bacher + * : David Woodhouse + * + * inspired by drivers/char/hvc_console.c + * written by Anton Blanchard and Paul Mackerras + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "hvc_console.h" + +#define hvc_rtas_cookie 0x67781e15 +struct hvc_struct *hvc_rtas_dev; + +#define RTASCONS_PUT_ATTEMPTS 16 + +static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE; +static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE; +static int rtascons_put_delay = 100; +module_param_named(put_delay, rtascons_put_delay, int, 0644); + +static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, int count) +{ + int done; + + /* if there is more than one character to be displayed, wait a bit */ + for (done = 0; done < count; done++) { + int result; + result = rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[done]); + if (result) + break; + } + /* the calling routine expects to receive the number of bytes sent */ + return done; +} + +static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count) +{ + int i; + + for (i = 0; i < count; i++) { + int c, err; + + err = rtas_call(rtascons_get_char_token, 0, 2, &c); + if (err) + break; + + buf[i] = c; + } + + return i; +} + +static struct hv_ops hvc_rtas_get_put_ops = { + .get_chars = hvc_rtas_read_console, + .put_chars = hvc_rtas_write_console, +}; + +static int hvc_rtas_init(void) +{ + struct hvc_struct *hp; + + if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) + rtascons_put_char_token = rtas_token("put-term-char"); + if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) + return -EIO; + + if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) + rtascons_get_char_token = rtas_token("get-term-char"); + if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) + return -EIO; + + BUG_ON(hvc_rtas_dev); + + /* Allocate an hvc_struct for the console device we instantiated + * earlier. Save off hp so that we can return it on exit */ + hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops); + if (IS_ERR(hp)) + return PTR_ERR(hp); + hvc_rtas_dev = hp; + return 0; +} +module_init(hvc_rtas_init); + +/* This will tear down the tty portion of the driver */ +static void __exit hvc_rtas_exit(void) +{ + /* Really the fun isn't over until the worker thread breaks down and the + * tty cleans up */ + if (hvc_rtas_dev) + hvc_remove(hvc_rtas_dev); +} +module_exit(hvc_rtas_exit); + +/* This will happen prior to module init. There is no tty at this time? */ +static int hvc_rtas_console_init(void) +{ + rtascons_put_char_token = rtas_token("put-term-char"); + if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) + return -EIO; + rtascons_get_char_token = rtas_token("get-term-char"); + if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE) + return -EIO; + + hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops ); + add_preferred_console("hvc", 0, NULL); + return 0; +} +console_initcall(hvc_rtas_console_init); -- cgit v1.2.2 From e8222502ee6157e2713da9e0792c21f4ad458d50 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 28 Mar 2006 23:15:54 +1100 Subject: [PATCH] powerpc: Kill _machine and hard-coded platform numbers This removes statically assigned platform numbers and reworks the powerpc platform probe code to use a better mechanism. With this, board support files can simply declare a new machine type with a macro, and implement a probe() function that uses the flattened device-tree to detect if they apply for a given machine. We now have a machine_is() macro that replaces the comparisons of _machine with the various PLATFORM_* constants. This commit also changes various drivers to use the new macro instead of looking at _machine. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- drivers/char/generic_nvram.c | 5 ++++- drivers/ide/pci/via82cxxx.c | 2 +- drivers/ide/ppc/pmac.c | 2 +- drivers/ieee1394/ohci1394.c | 4 ++-- drivers/macintosh/adb.c | 3 ++- drivers/macintosh/adbhid.c | 4 ++-- drivers/macintosh/mediabay.c | 4 ++-- drivers/media/video/planb.c | 2 +- drivers/net/tulip/de4x5.c | 2 +- drivers/scsi/mesh.c | 2 +- drivers/usb/core/hcd-pci.c | 4 ++-- drivers/video/aty/aty128fb.c | 7 ++++--- drivers/video/aty/atyfb_base.c | 7 ++++--- drivers/video/aty/radeon_pm.c | 4 ++-- drivers/video/cirrusfb.c | 4 ++-- drivers/video/matrox/matroxfb_base.c | 3 ++- drivers/video/nvidia/nvidia.c | 5 +++-- drivers/video/radeonfb.c | 2 +- drivers/video/riva/fbdev.c | 9 +++++---- 19 files changed, 42 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c index 1b5e01e6e1..43ff598165 100644 --- a/drivers/char/generic_nvram.c +++ b/drivers/char/generic_nvram.c @@ -22,6 +22,9 @@ #include #include #include +#ifdef CONFIG_PPC_PMAC +#include +#endif #define NVRAM_SIZE 8192 @@ -92,7 +95,7 @@ static int nvram_ioctl(struct inode *inode, struct file *file, case IOC_NVRAM_GET_OFFSET: { int part, offset; - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return -EINVAL; if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) return -EFAULT; diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index c85b87cb59..3e677c4f8c 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -440,7 +440,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) #if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32) - if(_machine == _MACH_chrp && _chrp_type == _CHRP_Pegasos) { + if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) { hwif->irq = hwif->channel ? 15 : 14; } #endif diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 5013b1285e..78e30f8036 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -1677,7 +1677,7 @@ MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match); void __init pmac_ide_probe(void) { - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return; #ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index b6b96fa04d..314f355400 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3526,7 +3526,7 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) static int ohci1394_pci_resume (struct pci_dev *pdev) { #ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct device_node *of_node; /* Re-enable 1394 */ @@ -3545,7 +3545,7 @@ static int ohci1394_pci_resume (struct pci_dev *pdev) static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) { #ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct device_node *of_node; /* Disable 1394 */ diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index d2ead1776c..781d93b0bb 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -42,6 +42,7 @@ #include #ifdef CONFIG_PPC #include +#include #endif @@ -294,7 +295,7 @@ int __init adb_init(void) int i; #ifdef CONFIG_PPC32 - if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) + if (!machine_is(chrp) && !machine_is(powermac)) return 0; #endif #ifdef CONFIG_MAC diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index c0b46bceb5..0a4c680d4a 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -1206,8 +1206,8 @@ init_ms_a3(int id) static int __init adbhid_init(void) { #ifndef CONFIG_MAC - if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) - return 0; + if (!machine_is(chrp) && !machine_is(powermac)) + return 0; #endif led_request.complete = 1; diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index 8dbf2852ba..53c1c79094 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -839,8 +839,8 @@ static int __init media_bay_init(void) media_bays[i].cd_index = -1; #endif } - if (_machine != _MACH_Pmac) - return -ENODEV; + if (!machine_is(powermac)) + return 0; macio_register_driver(&media_bay_driver); diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index 522e9ddeb0..d9e3cada52 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -2156,7 +2156,7 @@ static int find_planb(void) struct pci_dev *pdev; int rc; - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return 0; planb_devices = find_devices("planb"); diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index ee48bfd673..46d087c546 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -4160,7 +4160,7 @@ get_hw_addr(struct net_device *dev) ** If the address starts with 00 a0, we have to bit-reverse ** each byte of the address. */ - if ( (_machine & _MACH_Pmac) && + if ( machine_is(powermac) && (dev->dev_addr[0] == 0) && (dev->dev_addr[1] == 0xa0) ) { diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index d6d2125f90..f852421002 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1748,7 +1748,7 @@ static int mesh_host_reset(struct scsi_cmnd *cmd) static void set_mesh_power(struct mesh_state *ms, int state) { - if (_machine != _MACH_Pmac) + if (!machine_is(powermac)) return; if (state) { pmac_call_feature(PMAC_FTR_MESH_ENABLE, macio_get_of_node(ms->mdev), 0, 1); diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index e0afb5ad29..0d2193b692 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -296,7 +296,7 @@ done: #ifdef CONFIG_PPC_PMAC /* Disable ASIC clocks for USB */ - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct device_node *of_node; of_node = pci_device_to_OF_node (dev); @@ -331,7 +331,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev) #ifdef CONFIG_PPC_PMAC /* Reenable ASIC clocks for USB */ - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct device_node *of_node; of_node = pci_device_to_OF_node (dev); diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 620c9a934e..f07be22e11 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -67,6 +67,7 @@ #include #ifdef CONFIG_PPC_PMAC +#include #include #include #include @@ -1748,7 +1749,7 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id * var = default_var; #ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { /* Indicate sleep capability */ if (par->chip_gen == rage_M3) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1); @@ -2011,7 +2012,7 @@ static int aty128fb_blank(int blank, struct fb_info *fb) return 0; #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && blank) + if (machine_is(powermac) && blank) set_backlight_enable(0); #endif /* CONFIG_PMAC_BACKLIGHT */ @@ -2029,7 +2030,7 @@ static int aty128fb_blank(int blank, struct fb_info *fb) aty128_set_lcd_enable(par, par->lcd_on && !blank); } #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && !blank) + if (machine_is(powermac) && !blank) set_backlight_enable(1); #endif /* CONFIG_PMAC_BACKLIGHT */ return 0; diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 485be386a8..1b1f24e2bf 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -75,6 +75,7 @@ #include "ati_ids.h" #ifdef __powerpc__ +#include #include #include "../macmodes.h" #endif @@ -2516,7 +2517,7 @@ static int __init aty_init(struct fb_info *info, const char *name) memset(&var, 0, sizeof(var)); #ifdef CONFIG_PPC - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { /* * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it * applies to all Mac video cards @@ -2671,7 +2672,7 @@ static int atyfb_blank(int blank, struct fb_info *info) return 0; #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && blank > FB_BLANK_NORMAL) + if (machine_is(powermac) && blank > FB_BLANK_NORMAL) set_backlight_enable(0); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) if (par->lcd_table && blank > FB_BLANK_NORMAL && @@ -2703,7 +2704,7 @@ static int atyfb_blank(int blank, struct fb_info *info) aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); #ifdef CONFIG_PMAC_BACKLIGHT - if ((_machine == _MACH_Pmac) && blank <= FB_BLANK_NORMAL) + if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) set_backlight_enable(1); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) if (par->lcd_table && blank <= FB_BLANK_NORMAL && diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 5886a2f132..c7091761ce 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -20,7 +20,7 @@ #include #ifdef CONFIG_PPC_PMAC -#include +#include #include #include #endif @@ -2745,7 +2745,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) rinfo->pm_mode |= radeon_pm_off; } #if defined(CONFIG_PPC_PMAC) - if (_machine == _MACH_Pmac && rinfo->of_node) { + if (machine_is(powermac) && rinfo->of_node) { if (rinfo->is_mobility && rinfo->pm_reg && rinfo->family <= CHIP_FAMILY_RV250) rinfo->pm_mode |= radeon_pm_d2; diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 66d6f2f0a2..1103010af5 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -60,8 +60,8 @@ #include #endif #ifdef CONFIG_PPC_PREP -#include -#define isPReP (_machine == _MACH_prep) +#include +#define isPReP (machine_is(prep)) #else #define isPReP 0 #endif diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 951c9974a1..23c1827b2d 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -115,6 +115,7 @@ #include #ifdef CONFIG_PPC_PMAC +#include unsigned char nvram_read_byte(int); static int default_vmode = VMODE_NVRAM; static int default_cmode = CMODE_NVRAM; @@ -1833,7 +1834,7 @@ static int initMatrox2(WPMINFO struct board* b){ /* FIXME: Where to move this?! */ #if defined(CONFIG_PPC_PMAC) #ifndef MODULE - if (_machine == _MACH_Pmac) { + if (machine_is(powermac)) { struct fb_var_screeninfo var; if (default_vmode <= 0 || default_vmode > VMODE_MAX) default_vmode = VMODE_640_480_60; diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index a7c4e5e8ea..7258b32453 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -29,6 +29,7 @@ #include #endif #ifdef CONFIG_PMAC_BACKLIGHT +#include #include #endif @@ -1353,7 +1354,7 @@ static int nvidiafb_blank(int blank, struct fb_info *info) NVWriteCrtc(par, 0x1a, vesa); #ifdef CONFIG_PMAC_BACKLIGHT - if (par->FlatPanel && _machine == _MACH_Pmac) { + if (par->FlatPanel && machine_is(powermac)) { set_backlight_enable(!blank); } #endif @@ -1688,7 +1689,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, info->fix.id, par->FbMapSize / (1024 * 1024), info->fix.smem_start); #ifdef CONFIG_PMAC_BACKLIGHT - if (par->FlatPanel && _machine == _MACH_Pmac) + if (par->FlatPanel && machine_is(powermac)) register_backlight_controller(&nvidia_backlight_controller, par, "mnca"); #endif diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index db9fb9074d..04820fab96 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c @@ -1596,7 +1596,7 @@ static int radeonfb_blank (int blank, struct fb_info *info) return 0; #ifdef CONFIG_PMAC_BACKLIGHT - if (rinfo->dviDisp_type == MT_LCD && _machine == _MACH_Pmac) { + if (rinfo->dviDisp_type == MT_LCD && machine_is(powermac)) { set_backlight_enable(!blank); return 0; } diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 6c19ab6afb..b7bd6bb2c7 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c @@ -49,6 +49,7 @@ #include #endif #ifdef CONFIG_PMAC_BACKLIGHT +#include #include #endif @@ -1247,7 +1248,7 @@ static int rivafb_blank(int blank, struct fb_info *info) CRTCout(par, 0x1a, vesa); #ifdef CONFIG_PMAC_BACKLIGHT - if ( par->FlatPanel && _machine == _MACH_Pmac) { + if ( par->FlatPanel && machine_is(powermac)) { set_backlight_enable(!blank); } #endif @@ -2037,9 +2038,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd, info->fix.smem_len / (1024 * 1024), info->fix.smem_start); #ifdef CONFIG_PMAC_BACKLIGHT - if (default_par->FlatPanel && _machine == _MACH_Pmac) - register_backlight_controller(&riva_backlight_controller, - default_par, "mnca"); + if (default_par->FlatPanel && machine_is(powermac)) + register_backlight_controller(&riva_backlight_controller, + default_par, "mnca"); #endif NVTRACE_LEAVE(); return 0; -- cgit v1.2.2 From d2b58b58838159b2afdc624f74b208e8bd3c029e Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 29 Mar 2006 08:12:52 +1000 Subject: drm: sis fix compile warning Prevent a gcc warning in the SIS DRM driver. offset is a unsigned int and the printk wants a long. Signed-off-by: Jon Mason Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/char/drm/sis_mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c index 6774d2fe34..5e9936bc30 100644 --- a/drivers/char/drm/sis_mm.c +++ b/drivers/char/drm/sis_mm.c @@ -110,7 +110,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS) DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); - DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset); + DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset); return retval; } -- cgit v1.2.2 From 55eb061326765b2d0489387cfb3fc7dbd244f917 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 29 Mar 2006 08:16:12 +1000 Subject: drm: remove drm_{alloc,free}_pages drm_alloc_pages and drm_free_pages can now be removed. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/char/drm/drmP.h | 2 -- drivers/char/drm/drm_memory.c | 59 ------------------------------- drivers/char/drm/drm_memory_debug.h | 70 ------------------------------------- 3 files changed, 131 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index dbe952f899..edc72a6348 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -813,8 +813,6 @@ extern void drm_mem_init(void); extern int drm_mem_info(char *buf, char **start, off_t offset, int request, int *eof, void *data); extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area); -extern unsigned long drm_alloc_pages(int order, int area); -extern void drm_free_pages(unsigned long address, int order, int area); extern void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t * dev); extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size, diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index 8074771e34..dddf8de661 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c @@ -79,65 +79,6 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) return pt; } -/** - * Allocate pages. - * - * \param order size order. - * \param area memory area. (Not used.) - * \return page address on success, or zero on failure. - * - * Allocate and reserve free pages. - */ -unsigned long drm_alloc_pages(int order, int area) -{ - unsigned long address; - unsigned long bytes = PAGE_SIZE << order; - unsigned long addr; - unsigned int sz; - - address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); - if (!address) - return 0; - - /* Zero */ - memset((void *)address, 0, bytes); - - /* Reserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - SetPageReserved(virt_to_page(addr)); - } - - return address; -} - -/** - * Free pages. - * - * \param address address of the pages to free. - * \param order size order. - * \param area memory area. (Not used.) - * - * Unreserve and free pages allocated by alloc_pages(). - */ -void drm_free_pages(unsigned long address, int order, int area) -{ - unsigned long bytes = PAGE_SIZE << order; - unsigned long addr; - unsigned int sz; - - if (!address) - return; - - /* Unreserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - } - - free_pages(address, order); -} - #if __OS_HAS_AGP /** Wrapper around agp_allocate_memory() */ DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type) diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h index e84605fc54..7868341817 100644 --- a/drivers/char/drm/drm_memory_debug.h +++ b/drivers/char/drm/drm_memory_debug.h @@ -206,76 +206,6 @@ void drm_free (void *pt, size_t size, int area) { } } -unsigned long drm_alloc_pages (int order, int area) { - unsigned long address; - unsigned long bytes = PAGE_SIZE << order; - unsigned long addr; - unsigned int sz; - - spin_lock(&drm_mem_lock); - if ((drm_ram_used >> PAGE_SHIFT) - > (DRM_RAM_PERCENT * drm_ram_available) / 100) { - spin_unlock(&drm_mem_lock); - return 0; - } - spin_unlock(&drm_mem_lock); - - address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); - if (!address) { - spin_lock(&drm_mem_lock); - ++drm_mem_stats[area].fail_count; - spin_unlock(&drm_mem_lock); - return 0; - } - spin_lock(&drm_mem_lock); - ++drm_mem_stats[area].succeed_count; - drm_mem_stats[area].bytes_allocated += bytes; - drm_ram_used += bytes; - spin_unlock(&drm_mem_lock); - - /* Zero outside the lock */ - memset((void *)address, 0, bytes); - - /* Reserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - SetPageReserved(virt_to_page(addr)); - } - - return address; -} - -void drm_free_pages (unsigned long address, int order, int area) { - unsigned long bytes = PAGE_SIZE << order; - int alloc_count; - int free_count; - unsigned long addr; - unsigned int sz; - - if (!address) { - DRM_MEM_ERROR(area, "Attempt to free address 0\n"); - } else { - /* Unreserve */ - for (addr = address, sz = bytes; - sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - } - free_pages(address, order); - } - - spin_lock(&drm_mem_lock); - free_count = ++drm_mem_stats[area].free_count; - alloc_count = drm_mem_stats[area].succeed_count; - drm_mem_stats[area].bytes_freed += bytes; - drm_ram_used -= bytes; - spin_unlock(&drm_mem_lock); - if (free_count > alloc_count) { - DRM_MEM_ERROR(area, - "Excess frees: %d frees, %d allocs\n", - free_count, alloc_count); - } -} - void *drm_ioremap (unsigned long offset, unsigned long size, drm_device_t * dev) { void *pt; -- cgit v1.2.2 From 008652b337364ee994a0cd71d88a0fe9f00fc7ca Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:14:53 -0800 Subject: [TG3]: Fix probe failure due to invalid MAC address Some older bootcode in some devices may report 0 MAC address in SRAM when booting up from low power state. This patch fixes the problem by checking for a valid MAC address in SRAM and falling back to NVRAM if necessary. Thanks to walt for reporting the problem and helping to debug it. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b5473325bf..c41dbb0e8f 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10531,6 +10531,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) { struct net_device *dev = tp->dev; u32 hi, lo, mac_offset; + int addr_ok = 0; #ifdef CONFIG_SPARC64 if (!tg3_get_macaddr_sparc(tp)) @@ -10560,29 +10561,34 @@ static int __devinit tg3_get_device_address(struct tg3 *tp) dev->dev_addr[3] = (lo >> 16) & 0xff; dev->dev_addr[4] = (lo >> 8) & 0xff; dev->dev_addr[5] = (lo >> 0) & 0xff; - } - /* Next, try NVRAM. */ - else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) && - !tg3_nvram_read(tp, mac_offset + 0, &hi) && - !tg3_nvram_read(tp, mac_offset + 4, &lo)) { - dev->dev_addr[0] = ((hi >> 16) & 0xff); - dev->dev_addr[1] = ((hi >> 24) & 0xff); - dev->dev_addr[2] = ((lo >> 0) & 0xff); - dev->dev_addr[3] = ((lo >> 8) & 0xff); - dev->dev_addr[4] = ((lo >> 16) & 0xff); - dev->dev_addr[5] = ((lo >> 24) & 0xff); - } - /* Finally just fetch it out of the MAC control regs. */ - else { - hi = tr32(MAC_ADDR_0_HIGH); - lo = tr32(MAC_ADDR_0_LOW); - dev->dev_addr[5] = lo & 0xff; - dev->dev_addr[4] = (lo >> 8) & 0xff; - dev->dev_addr[3] = (lo >> 16) & 0xff; - dev->dev_addr[2] = (lo >> 24) & 0xff; - dev->dev_addr[1] = hi & 0xff; - dev->dev_addr[0] = (hi >> 8) & 0xff; + /* Some old bootcode may report a 0 MAC address in SRAM */ + addr_ok = is_valid_ether_addr(&dev->dev_addr[0]); + } + if (!addr_ok) { + /* Next, try NVRAM. */ + if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) && + !tg3_nvram_read(tp, mac_offset + 0, &hi) && + !tg3_nvram_read(tp, mac_offset + 4, &lo)) { + dev->dev_addr[0] = ((hi >> 16) & 0xff); + dev->dev_addr[1] = ((hi >> 24) & 0xff); + dev->dev_addr[2] = ((lo >> 0) & 0xff); + dev->dev_addr[3] = ((lo >> 8) & 0xff); + dev->dev_addr[4] = ((lo >> 16) & 0xff); + dev->dev_addr[5] = ((lo >> 24) & 0xff); + } + /* Finally just fetch it out of the MAC control regs. */ + else { + hi = tr32(MAC_ADDR_0_HIGH); + lo = tr32(MAC_ADDR_0_LOW); + + dev->dev_addr[5] = lo & 0xff; + dev->dev_addr[4] = (lo >> 8) & 0xff; + dev->dev_addr[3] = (lo >> 16) & 0xff; + dev->dev_addr[2] = (lo >> 24) & 0xff; + dev->dev_addr[1] = hi & 0xff; + dev->dev_addr[0] = (hi >> 8) & 0xff; + } } if (!is_valid_ether_addr(&dev->dev_addr[0])) { -- cgit v1.2.2 From 6728a8e2e180b96ac7940dd4d766c52f8e177717 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:16:49 -0800 Subject: [TG3]: Fix bug in 40-bit DMA workaround code Need to check the TG3_FLAG_40BIT_DMA_BUG flag in the workaround code path instead of device flags. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c41dbb0e8f..0fafc52646 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3600,7 +3600,7 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping, int len) { #if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64) - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG) return (((u64) mapping + len) > DMA_40BIT_MASK); return 0; #else -- cgit v1.2.2 From ff18ff023495a4f1ce7c65e7c376c4720eccf4da Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:17:27 -0800 Subject: [TG3]: Fix PHY loopback on 5700 Fix PHY loopback failure on some 5700 devices. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0fafc52646..3c5c9fafe9 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8399,8 +8399,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) } mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII; - if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) + if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { mac_mode &= ~MAC_MODE_LINK_POLARITY; + tg3_writephy(tp, MII_TG3_EXT_CTRL, + MII_TG3_EXT_CTRL_LNK3_LED_MODE); + } tw32(MAC_MODE, mac_mode); } else -- cgit v1.2.2 From 100c4673307f5806788791b9b886877c806afd96 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:19:00 -0800 Subject: [TG3]: Speed up SRAM access Speed up SRAM read and write functions if possible by using MMIO instead of config. cycles. With this change, the post reset signature done at the end of D3 power change must now be moved before the D3 power change. IBM reported a problem on powerpc blades during ethtool self test that was caused by the memory test taking excessively long. Config. cycles are very slow on powerpc and the memory test can take more than 10 seconds to complete using config. cycles. As a result, NETDEV WATCHDOG can be triggered during self test and the chip can end up in a funny state. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 53 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 3c5c9fafe9..c504ff29d4 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -497,21 +497,20 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + if (tp->write32 != tg3_write_indirect_reg32) { + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); + tw32_f(TG3PCI_MEM_WIN_DATA, val); - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); - spin_unlock_irqrestore(&tp->indirect_lock, flags); -} + /* Always leave this as zero. */ + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); + } else { + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); -static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val) -{ - /* If no workaround is needed, write to mem space directly */ - if (tp->write32 != tg3_write_indirect_reg32) - tw32(NIC_SRAM_WIN_BASE + off, val); - else - tg3_write_mem(tp, off, val); + /* Always leave this as zero. */ + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + } + spin_unlock_irqrestore(&tp->indirect_lock, flags); } static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) @@ -519,11 +518,19 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + if (tp->write32 != tg3_write_indirect_reg32) { + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); + *val = tr32(TG3PCI_MEM_WIN_DATA); - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + /* Always leave this as zero. */ + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); + } else { + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); + pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + + /* Always leave this as zero. */ + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + } spin_unlock_irqrestore(&tp->indirect_lock, flags); } @@ -1367,12 +1374,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) } } + tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); + /* Finally, set the new power state. */ pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); udelay(100); /* Delay after power state change */ - tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); - return 0; } @@ -6537,11 +6544,11 @@ static void tg3_timer(unsigned long __opaque) if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { u32 val; - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX, - FWCMD_NICDRV_ALIVE2); - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, + FWCMD_NICDRV_ALIVE2); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); /* 5 seconds timeout */ - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); val = tr32(GRC_RX_CPU_EVENT); val |= (1 << 14); tw32(GRC_RX_CPU_EVENT, val); -- cgit v1.2.2 From f475f163f128a0d9c92dfa90bcb5953fd8f9766f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:20:14 -0800 Subject: [TG3]: Skip timer code during full lock Skip the main timer code if interrupts are disabled in the full lock state. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c504ff29d4..b6a6051db7 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6468,6 +6468,9 @@ static void tg3_timer(unsigned long __opaque) { struct tg3 *tp = (struct tg3 *) __opaque; + if (tp->irq_sync) + goto restart_timer; + spin_lock(&tp->lock); if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { @@ -6558,6 +6561,7 @@ static void tg3_timer(unsigned long __opaque) spin_unlock(&tp->lock); +restart_timer: tp->timer.expires = jiffies + tp->timer_offset; add_timer(&tp->timer); } -- cgit v1.2.2 From e3a05978f18a38ae13bb3f1184abf3c999e06da9 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 27 Mar 2006 23:21:07 -0800 Subject: [TG3]: Update version and reldate Update version to 3.55. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index b6a6051db7..964c096448 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.54" -#define DRV_MODULE_RELDATE "Mar 23, 2006" +#define DRV_MODULE_VERSION "3.55" +#define DRV_MODULE_RELDATE "Mar 27, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.2 From 730c9b7e6630f786fcec026fb11d2e6f2c90fdcb Mon Sep 17 00:00:00 2001 From: Carlos Aguiar Date: Wed, 29 Mar 2006 09:21:00 +0100 Subject: [MMC] Add OMAP MMC host driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds OMAP MMC driver. Signed-off-by: Juha Yrjölä Signed-off-by: Tony Lindgren Signed-off-by: Carlos Aguiar Signed-off-by: Russell King --- drivers/mmc/Kconfig | 11 + drivers/mmc/Makefile | 1 + drivers/mmc/omap.c | 1231 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/mmc/omap.h | 55 +++ 4 files changed, 1298 insertions(+) create mode 100644 drivers/mmc/omap.c create mode 100644 drivers/mmc/omap.h (limited to 'drivers') diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 3f5d77f633..7cc162e897 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -60,6 +60,17 @@ config MMC_SDHCI If unsure, say N. +config MMC_OMAP + tristate "TI OMAP Multimedia Card Interface support" + depends on ARCH_OMAP && MMC + select TPS65010 if MACH_OMAP_H2 + help + This selects the TI OMAP Multimedia card Interface. + If you have an OMAP board with a Multimedia Card slot, + say Y or M here. + + If unsure, say N. + config MMC_WBSD tristate "Winbond W83L51xD SD/MMC Card Interface support" depends on MMC && ISA_DMA_API diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 769d545284..0b0920ae46 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -20,5 +20,6 @@ obj-$(CONFIG_MMC_PXA) += pxamci.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_WBSD) += wbsd.o obj-$(CONFIG_MMC_AU1X) += au1xmmc.o +obj-$(CONFIG_MMC_OMAP) += omap.o mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c new file mode 100644 index 0000000000..49fb2ea4b7 --- /dev/null +++ b/drivers/mmc/omap.c @@ -0,0 +1,1231 @@ +/* + * linux/drivers/media/mmc/omap.c + * + * Copyright (C) 2004 Nokia Corporation + * Written by Tuukka Tikkanen and Juha Yrjölä + * Misc hacks here and there by Tony Lindgren + * Other hacks (DMA, SD, etc) by David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +#ifdef CONFIG_MMC_DEBUG +#define DEBUG /* for dev_dbg(), pr_debug(), etc */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "omap.h" + +#define DRIVER_NAME "mmci-omap" +#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) + +/* Specifies how often in millisecs to poll for card status changes + * when the cover switch is open */ +#define OMAP_MMC_SWITCH_POLL_DELAY 500 + +static int mmc_omap_enable_poll = 1; + +struct mmc_omap_host { + int initialized; + int suspended; + struct mmc_request * mrq; + struct mmc_command * cmd; + struct mmc_data * data; + struct mmc_host * mmc; + struct device * dev; + unsigned char id; /* 16xx chips have 2 MMC blocks */ + struct clk * iclk; + struct clk * fclk; + void __iomem *base; + int irq; + unsigned char bus_mode; + unsigned char hw_bus_mode; + + unsigned int sg_len; + int sg_idx; + u16 * buffer; + u32 buffer_bytes_left; + u32 total_bytes_left; + + unsigned use_dma:1; + unsigned brs_received:1, dma_done:1; + unsigned dma_is_read:1; + unsigned dma_in_use:1; + int dma_ch; + spinlock_t dma_lock; + struct timer_list dma_timer; + unsigned dma_len; + + short power_pin; + short wp_pin; + + int switch_pin; + struct work_struct switch_work; + struct timer_list switch_timer; + int switch_last_state; +}; + +static inline int +mmc_omap_cover_is_open(struct mmc_omap_host *host) +{ + if (host->switch_pin < 0) + return 0; + return omap_get_gpio_datain(host->switch_pin); +} + +static ssize_t +mmc_omap_show_cover_switch(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mmc_omap_host *host = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", mmc_omap_cover_is_open(host) ? "open" : + "closed"); +} + +static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL); + +static ssize_t +mmc_omap_show_enable_poll(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", mmc_omap_enable_poll); +} + +static ssize_t +mmc_omap_store_enable_poll(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + int enable_poll; + + if (sscanf(buf, "%10d", &enable_poll) != 1) + return -EINVAL; + + if (enable_poll != mmc_omap_enable_poll) { + struct mmc_omap_host *host = dev_get_drvdata(dev); + + mmc_omap_enable_poll = enable_poll; + if (enable_poll && host->switch_pin >= 0) + schedule_work(&host->switch_work); + } + return size; +} + +static DEVICE_ATTR(enable_poll, 0664, + mmc_omap_show_enable_poll, mmc_omap_store_enable_poll); + +static void +mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd) +{ + u32 cmdreg; + u32 resptype; + u32 cmdtype; + + host->cmd = cmd; + + resptype = 0; + cmdtype = 0; + + /* Our hardware needs to know exact type */ + switch (RSP_TYPE(mmc_resp_type(cmd))) { + case RSP_TYPE(MMC_RSP_R1): + /* resp 1, resp 1b */ + resptype = 1; + break; + case RSP_TYPE(MMC_RSP_R2): + resptype = 2; + break; + case RSP_TYPE(MMC_RSP_R3): + resptype = 3; + break; + default: + break; + } + + if (mmc_cmd_type(cmd) == MMC_CMD_ADTC) { + cmdtype = OMAP_MMC_CMDTYPE_ADTC; + } else if (mmc_cmd_type(cmd) == MMC_CMD_BC) { + cmdtype = OMAP_MMC_CMDTYPE_BC; + } else if (mmc_cmd_type(cmd) == MMC_CMD_BCR) { + cmdtype = OMAP_MMC_CMDTYPE_BCR; + } else { + cmdtype = OMAP_MMC_CMDTYPE_AC; + } + + cmdreg = cmd->opcode | (resptype << 8) | (cmdtype << 12); + + if (host->bus_mode == MMC_BUSMODE_OPENDRAIN) + cmdreg |= 1 << 6; + + if (cmd->flags & MMC_RSP_BUSY) + cmdreg |= 1 << 11; + + if (host->data && !(host->data->flags & MMC_DATA_WRITE)) + cmdreg |= 1 << 15; + + clk_enable(host->fclk); + + OMAP_MMC_WRITE(host->base, CTO, 200); + OMAP_MMC_WRITE(host->base, ARGL, cmd->arg & 0xffff); + OMAP_MMC_WRITE(host->base, ARGH, cmd->arg >> 16); + OMAP_MMC_WRITE(host->base, IE, + OMAP_MMC_STAT_A_EMPTY | OMAP_MMC_STAT_A_FULL | + OMAP_MMC_STAT_CMD_CRC | OMAP_MMC_STAT_CMD_TOUT | + OMAP_MMC_STAT_DATA_CRC | OMAP_MMC_STAT_DATA_TOUT | + OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR | + OMAP_MMC_STAT_END_OF_DATA); + OMAP_MMC_WRITE(host->base, CMD, cmdreg); +} + +static void +mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) +{ + if (host->dma_in_use) { + enum dma_data_direction dma_data_dir; + + BUG_ON(host->dma_ch < 0); + if (data->error != MMC_ERR_NONE) + omap_stop_dma(host->dma_ch); + /* Release DMA channel lazily */ + mod_timer(&host->dma_timer, jiffies + HZ); + if (data->flags & MMC_DATA_WRITE) + dma_data_dir = DMA_TO_DEVICE; + else + dma_data_dir = DMA_FROM_DEVICE; + dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len, + dma_data_dir); + } + host->data = NULL; + host->sg_len = 0; + clk_disable(host->fclk); + + /* NOTE: MMC layer will sometimes poll-wait CMD13 next, issuing + * dozens of requests until the card finishes writing data. + * It'd be cheaper to just wait till an EOFB interrupt arrives... + */ + + if (!data->stop) { + host->mrq = NULL; + mmc_request_done(host->mmc, data->mrq); + return; + } + + mmc_omap_start_command(host, data->stop); +} + +static void +mmc_omap_end_of_data(struct mmc_omap_host *host, struct mmc_data *data) +{ + unsigned long flags; + int done; + + if (!host->dma_in_use) { + mmc_omap_xfer_done(host, data); + return; + } + done = 0; + spin_lock_irqsave(&host->dma_lock, flags); + if (host->dma_done) + done = 1; + else + host->brs_received = 1; + spin_unlock_irqrestore(&host->dma_lock, flags); + if (done) + mmc_omap_xfer_done(host, data); +} + +static void +mmc_omap_dma_timer(unsigned long data) +{ + struct mmc_omap_host *host = (struct mmc_omap_host *) data; + + BUG_ON(host->dma_ch < 0); + omap_free_dma(host->dma_ch); + host->dma_ch = -1; +} + +static void +mmc_omap_dma_done(struct mmc_omap_host *host, struct mmc_data *data) +{ + unsigned long flags; + int done; + + done = 0; + spin_lock_irqsave(&host->dma_lock, flags); + if (host->brs_received) + done = 1; + else + host->dma_done = 1; + spin_unlock_irqrestore(&host->dma_lock, flags); + if (done) + mmc_omap_xfer_done(host, data); +} + +static void +mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd) +{ + host->cmd = NULL; + + if (cmd->flags & MMC_RSP_PRESENT) { + if (cmd->flags & MMC_RSP_136) { + /* response type 2 */ + cmd->resp[3] = + OMAP_MMC_READ(host->base, RSP0) | + (OMAP_MMC_READ(host->base, RSP1) << 16); + cmd->resp[2] = + OMAP_MMC_READ(host->base, RSP2) | + (OMAP_MMC_READ(host->base, RSP3) << 16); + cmd->resp[1] = + OMAP_MMC_READ(host->base, RSP4) | + (OMAP_MMC_READ(host->base, RSP5) << 16); + cmd->resp[0] = + OMAP_MMC_READ(host->base, RSP6) | + (OMAP_MMC_READ(host->base, RSP7) << 16); + } else { + /* response types 1, 1b, 3, 4, 5, 6 */ + cmd->resp[0] = + OMAP_MMC_READ(host->base, RSP6) | + (OMAP_MMC_READ(host->base, RSP7) << 16); + } + } + + if (host->data == NULL || cmd->error != MMC_ERR_NONE) { + host->mrq = NULL; + clk_disable(host->fclk); + mmc_request_done(host->mmc, cmd->mrq); + } +} + +/* PIO only */ +static void +mmc_omap_sg_to_buf(struct mmc_omap_host *host) +{ + struct scatterlist *sg; + + sg = host->data->sg + host->sg_idx; + host->buffer_bytes_left = sg->length; + host->buffer = page_address(sg->page) + sg->offset; + if (host->buffer_bytes_left > host->total_bytes_left) + host->buffer_bytes_left = host->total_bytes_left; +} + +/* PIO only */ +static void +mmc_omap_xfer_data(struct mmc_omap_host *host, int write) +{ + int n; + void __iomem *reg; + u16 *p; + + if (host->buffer_bytes_left == 0) { + host->sg_idx++; + BUG_ON(host->sg_idx == host->sg_len); + mmc_omap_sg_to_buf(host); + } + n = 64; + if (n > host->buffer_bytes_left) + n = host->buffer_bytes_left; + host->buffer_bytes_left -= n; + host->total_bytes_left -= n; + host->data->bytes_xfered += n; + + if (write) { + __raw_writesw(host->base + OMAP_MMC_REG_DATA, host->buffer, n); + } else { + __raw_readsw(host->base + OMAP_MMC_REG_DATA, host->buffer, n); + } +} + +static inline void mmc_omap_report_irq(u16 status) +{ + static const char *mmc_omap_status_bits[] = { + "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO", + "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR" + }; + int i, c = 0; + + for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++) + if (status & (1 << i)) { + if (c) + printk(" "); + printk("%s", mmc_omap_status_bits[i]); + c++; + } +} + +static irqreturn_t mmc_omap_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct mmc_omap_host * host = (struct mmc_omap_host *)dev_id; + u16 status; + int end_command; + int end_transfer; + int transfer_error; + + if (host->cmd == NULL && host->data == NULL) { + status = OMAP_MMC_READ(host->base, STAT); + dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status); + if (status != 0) { + OMAP_MMC_WRITE(host->base, STAT, status); + OMAP_MMC_WRITE(host->base, IE, 0); + } + return IRQ_HANDLED; + } + + end_command = 0; + end_transfer = 0; + transfer_error = 0; + + while ((status = OMAP_MMC_READ(host->base, STAT)) != 0) { + OMAP_MMC_WRITE(host->base, STAT, status); +#ifdef CONFIG_MMC_DEBUG + dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ", + status, host->cmd != NULL ? host->cmd->opcode : -1); + mmc_omap_report_irq(status); + printk("\n"); +#endif + if (host->total_bytes_left) { + if ((status & OMAP_MMC_STAT_A_FULL) || + (status & OMAP_MMC_STAT_END_OF_DATA)) + mmc_omap_xfer_data(host, 0); + if (status & OMAP_MMC_STAT_A_EMPTY) + mmc_omap_xfer_data(host, 1); + } + + if (status & OMAP_MMC_STAT_END_OF_DATA) { + end_transfer = 1; + } + + if (status & OMAP_MMC_STAT_DATA_TOUT) { + dev_dbg(mmc_dev(host->mmc), "data timeout\n"); + if (host->data) { + host->data->error |= MMC_ERR_TIMEOUT; + transfer_error = 1; + } + } + + if (status & OMAP_MMC_STAT_DATA_CRC) { + if (host->data) { + host->data->error |= MMC_ERR_BADCRC; + dev_dbg(mmc_dev(host->mmc), + "data CRC error, bytes left %d\n", + host->total_bytes_left); + transfer_error = 1; + } else { + dev_dbg(mmc_dev(host->mmc), "data CRC error\n"); + } + } + + if (status & OMAP_MMC_STAT_CMD_TOUT) { + /* Timeouts are routine with some commands */ + if (host->cmd) { + if (host->cmd->opcode != MMC_ALL_SEND_CID && + host->cmd->opcode != + MMC_SEND_OP_COND && + host->cmd->opcode != + MMC_APP_CMD && + !mmc_omap_cover_is_open(host)) + dev_err(mmc_dev(host->mmc), + "command timeout, CMD %d\n", + host->cmd->opcode); + host->cmd->error = MMC_ERR_TIMEOUT; + end_command = 1; + } + } + + if (status & OMAP_MMC_STAT_CMD_CRC) { + if (host->cmd) { + dev_err(mmc_dev(host->mmc), + "command CRC error (CMD%d, arg 0x%08x)\n", + host->cmd->opcode, host->cmd->arg); + host->cmd->error = MMC_ERR_BADCRC; + end_command = 1; + } else + dev_err(mmc_dev(host->mmc), + "command CRC error without cmd?\n"); + } + + if (status & OMAP_MMC_STAT_CARD_ERR) { + if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) { + u32 response = OMAP_MMC_READ(host->base, RSP6) + | (OMAP_MMC_READ(host->base, RSP7) << 16); + /* STOP sometimes sets must-ignore bits */ + if (!(response & (R1_CC_ERROR + | R1_ILLEGAL_COMMAND + | R1_COM_CRC_ERROR))) { + end_command = 1; + continue; + } + } + + dev_dbg(mmc_dev(host->mmc), "card status error (CMD%d)\n", + host->cmd->opcode); + if (host->cmd) { + host->cmd->error = MMC_ERR_FAILED; + end_command = 1; + } + if (host->data) { + host->data->error = MMC_ERR_FAILED; + transfer_error = 1; + } + } + + /* + * NOTE: On 1610 the END_OF_CMD may come too early when + * starting a write + */ + if ((status & OMAP_MMC_STAT_END_OF_CMD) && + (!(status & OMAP_MMC_STAT_A_EMPTY))) { + end_command = 1; + } + } + + if (end_command) { + mmc_omap_cmd_done(host, host->cmd); + } + if (transfer_error) + mmc_omap_xfer_done(host, host->data); + else if (end_transfer) + mmc_omap_end_of_data(host, host->data); + + return IRQ_HANDLED; +} + +static irqreturn_t mmc_omap_switch_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct mmc_omap_host *host = (struct mmc_omap_host *) dev_id; + + schedule_work(&host->switch_work); + + return IRQ_HANDLED; +} + +static void mmc_omap_switch_timer(unsigned long arg) +{ + struct mmc_omap_host *host = (struct mmc_omap_host *) arg; + + schedule_work(&host->switch_work); +} + +/* FIXME: Handle card insertion and removal properly. Maybe use a mask + * for MMC state? */ +static void mmc_omap_switch_callback(unsigned long data, u8 mmc_mask) +{ +} + +static void mmc_omap_switch_handler(void *data) +{ + struct mmc_omap_host *host = (struct mmc_omap_host *) data; + struct mmc_card *card; + static int complained = 0; + int cards = 0, cover_open; + + if (host->switch_pin == -1) + return; + cover_open = mmc_omap_cover_is_open(host); + if (cover_open != host->switch_last_state) { + kobject_uevent(&host->dev->kobj, KOBJ_CHANGE); + host->switch_last_state = cover_open; + } + mmc_detect_change(host->mmc, 0); + list_for_each_entry(card, &host->mmc->cards, node) { + if (mmc_card_present(card)) + cards++; + } + if (mmc_omap_cover_is_open(host)) { + if (!complained) { + dev_info(mmc_dev(host->mmc), "cover is open"); + complained = 1; + } + if (mmc_omap_enable_poll) + mod_timer(&host->switch_timer, jiffies + + msecs_to_jiffies(OMAP_MMC_SWITCH_POLL_DELAY)); + } else { + complained = 0; + } +} + +/* Prepare to transfer the next segment of a scatterlist */ +static void +mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) +{ + int dma_ch = host->dma_ch; + unsigned long data_addr; + u16 buf, frame; + u32 count; + struct scatterlist *sg = &data->sg[host->sg_idx]; + int src_port = 0; + int dst_port = 0; + int sync_dev = 0; + + data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA; + frame = 1 << data->blksz_bits; + count = sg_dma_len(sg); + + if ((data->blocks == 1) && (count > (1 << data->blksz_bits))) + count = frame; + + host->dma_len = count; + + /* FIFO is 16x2 bytes on 15xx, and 32x2 bytes on 16xx and 24xx. + * Use 16 or 32 word frames when the blocksize is at least that large. + * Blocksize is usually 512 bytes; but not for some SD reads. + */ + if (cpu_is_omap15xx() && frame > 32) + frame = 32; + else if (frame > 64) + frame = 64; + count /= frame; + frame >>= 1; + + if (!(data->flags & MMC_DATA_WRITE)) { + buf = 0x800f | ((frame - 1) << 8); + + if (cpu_class_is_omap1()) { + src_port = OMAP_DMA_PORT_TIPB; + dst_port = OMAP_DMA_PORT_EMIFF; + } + if (cpu_is_omap24xx()) + sync_dev = OMAP24XX_DMA_MMC1_RX; + + omap_set_dma_src_params(dma_ch, src_port, + OMAP_DMA_AMODE_CONSTANT, + data_addr, 0, 0); + omap_set_dma_dest_params(dma_ch, dst_port, + OMAP_DMA_AMODE_POST_INC, + sg_dma_address(sg), 0, 0); + omap_set_dma_dest_data_pack(dma_ch, 1); + omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); + } else { + buf = 0x0f80 | ((frame - 1) << 0); + + if (cpu_class_is_omap1()) { + src_port = OMAP_DMA_PORT_EMIFF; + dst_port = OMAP_DMA_PORT_TIPB; + } + if (cpu_is_omap24xx()) + sync_dev = OMAP24XX_DMA_MMC1_TX; + + omap_set_dma_dest_params(dma_ch, dst_port, + OMAP_DMA_AMODE_CONSTANT, + data_addr, 0, 0); + omap_set_dma_src_params(dma_ch, src_port, + OMAP_DMA_AMODE_POST_INC, + sg_dma_address(sg), 0, 0); + omap_set_dma_src_data_pack(dma_ch, 1); + omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4); + } + + /* Max limit for DMA frame count is 0xffff */ + if (unlikely(count > 0xffff)) + BUG(); + + OMAP_MMC_WRITE(host->base, BUF, buf); + omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16, + frame, count, OMAP_DMA_SYNC_FRAME, + sync_dev, 0); +} + +/* A scatterlist segment completed */ +static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data) +{ + struct mmc_omap_host *host = (struct mmc_omap_host *) data; + struct mmc_data *mmcdat = host->data; + + if (unlikely(host->dma_ch < 0)) { + dev_err(mmc_dev(host->mmc), "DMA callback while DMA not + enabled\n"); + return; + } + /* FIXME: We really should do something to _handle_ the errors */ + if (ch_status & OMAP_DMA_TOUT_IRQ) { + dev_err(mmc_dev(host->mmc),"DMA timeout\n"); + return; + } + if (ch_status & OMAP_DMA_DROP_IRQ) { + dev_err(mmc_dev(host->mmc), "DMA sync error\n"); + return; + } + if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) { + return; + } + mmcdat->bytes_xfered += host->dma_len; + host->sg_idx++; + if (host->sg_idx < host->sg_len) { + mmc_omap_prepare_dma(host, host->data); + omap_start_dma(host->dma_ch); + } else + mmc_omap_dma_done(host, host->data); +} + +static int mmc_omap_get_dma_channel(struct mmc_omap_host *host, struct mmc_data *data) +{ + const char *dev_name; + int sync_dev, dma_ch, is_read, r; + + is_read = !(data->flags & MMC_DATA_WRITE); + del_timer_sync(&host->dma_timer); + if (host->dma_ch >= 0) { + if (is_read == host->dma_is_read) + return 0; + omap_free_dma(host->dma_ch); + host->dma_ch = -1; + } + + if (is_read) { + if (host->id == 1) { + sync_dev = OMAP_DMA_MMC_RX; + dev_name = "MMC1 read"; + } else { + sync_dev = OMAP_DMA_MMC2_RX; + dev_name = "MMC2 read"; + } + } else { + if (host->id == 1) { + sync_dev = OMAP_DMA_MMC_TX; + dev_name = "MMC1 write"; + } else { + sync_dev = OMAP_DMA_MMC2_TX; + dev_name = "MMC2 write"; + } + } + r = omap_request_dma(sync_dev, dev_name, mmc_omap_dma_cb, + host, &dma_ch); + if (r != 0) { + dev_dbg(mmc_dev(host->mmc), "omap_request_dma() failed with %d\n", r); + return r; + } + host->dma_ch = dma_ch; + host->dma_is_read = is_read; + + return 0; +} + +static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_request *req) +{ + u16 reg; + + reg = OMAP_MMC_READ(host->base, SDIO); + reg &= ~(1 << 5); + OMAP_MMC_WRITE(host->base, SDIO, reg); + /* Set maximum timeout */ + OMAP_MMC_WRITE(host->base, CTO, 0xff); +} + +static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req) +{ + int timeout; + u16 reg; + + /* Convert ns to clock cycles by assuming 20MHz frequency + * 1 cycle at 20MHz = 500 ns + */ + timeout = req->data->timeout_clks + req->data->timeout_ns / 500; + + /* Check if we need to use timeout multiplier register */ + reg = OMAP_MMC_READ(host->base, SDIO); + if (timeout > 0xffff) { + reg |= (1 << 5); + timeout /= 1024; + } else + reg &= ~(1 << 5); + OMAP_MMC_WRITE(host->base, SDIO, reg); + OMAP_MMC_WRITE(host->base, DTO, timeout); +} + +static void +mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) +{ + struct mmc_data *data = req->data; + int i, use_dma, block_size; + unsigned sg_len; + + host->data = data; + if (data == NULL) { + OMAP_MMC_WRITE(host->base, BLEN, 0); + OMAP_MMC_WRITE(host->base, NBLK, 0); + OMAP_MMC_WRITE(host->base, BUF, 0); + host->dma_in_use = 0; + set_cmd_timeout(host, req); + return; + } + + + block_size = 1 << data->blksz_bits; + + OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1); + OMAP_MMC_WRITE(host->base, BLEN, block_size - 1); + set_data_timeout(host, req); + + /* cope with calling layer confusion; it issues "single + * block" writes using multi-block scatterlists. + */ + sg_len = (data->blocks == 1) ? 1 : data->sg_len; + + /* Only do DMA for entire blocks */ + use_dma = host->use_dma; + if (use_dma) { + for (i = 0; i < sg_len; i++) { + if ((data->sg[i].length % block_size) != 0) { + use_dma = 0; + break; + } + } + } + + host->sg_idx = 0; + if (use_dma) { + if (mmc_omap_get_dma_channel(host, data) == 0) { + enum dma_data_direction dma_data_dir; + + if (data->flags & MMC_DATA_WRITE) + dma_data_dir = DMA_TO_DEVICE; + else + dma_data_dir = DMA_FROM_DEVICE; + + host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, + sg_len, dma_data_dir); + host->total_bytes_left = 0; + mmc_omap_prepare_dma(host, req->data); + host->brs_received = 0; + host->dma_done = 0; + host->dma_in_use = 1; + } else + use_dma = 0; + } + + /* Revert to PIO? */ + if (!use_dma) { + OMAP_MMC_WRITE(host->base, BUF, 0x1f1f); + host->total_bytes_left = data->blocks * block_size; + host->sg_len = sg_len; + mmc_omap_sg_to_buf(host); + host->dma_in_use = 0; + } +} + +static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req) +{ + struct mmc_omap_host *host = mmc_priv(mmc); + + WARN_ON(host->mrq != NULL); + + host->mrq = req; + + /* only touch fifo AFTER the controller readies it */ + mmc_omap_prepare_data(host, req); + mmc_omap_start_command(host, req->cmd); + if (host->dma_in_use) + omap_start_dma(host->dma_ch); +} + +static void innovator_fpga_socket_power(int on) +{ +#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX) + + if (on) { + fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3), + OMAP1510_FPGA_POWER); + } else { + fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3), + OMAP1510_FPGA_POWER); + } +#endif +} + +/* + * Turn the socket power on/off. Innovator uses FPGA, most boards + * probably use GPIO. + */ +static void mmc_omap_power(struct mmc_omap_host *host, int on) +{ + if (on) { + if (machine_is_omap_innovator()) + innovator_fpga_socket_power(1); + else if (machine_is_omap_h2()) + tps65010_set_gpio_out_value(GPIO3, HIGH); + else if (machine_is_omap_h3()) + /* GPIO 4 of TPS65010 sends SD_EN signal */ + tps65010_set_gpio_out_value(GPIO4, HIGH); + else if (cpu_is_omap24xx()) { + u16 reg = OMAP_MMC_READ(host->base, CON); + OMAP_MMC_WRITE(host->base, CON, reg | (1 << 11)); + } else + if (host->power_pin >= 0) + omap_set_gpio_dataout(host->power_pin, 1); + } else { + if (machine_is_omap_innovator()) + innovator_fpga_socket_power(0); + else if (machine_is_omap_h2()) + tps65010_set_gpio_out_value(GPIO3, LOW); + else if (machine_is_omap_h3()) + tps65010_set_gpio_out_value(GPIO4, LOW); + else if (cpu_is_omap24xx()) { + u16 reg = OMAP_MMC_READ(host->base, CON); + OMAP_MMC_WRITE(host->base, CON, reg & ~(1 << 11)); + } else + if (host->power_pin >= 0) + omap_set_gpio_dataout(host->power_pin, 0); + } +} + +static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct mmc_omap_host *host = mmc_priv(mmc); + int dsor; + int realclock, i; + + realclock = ios->clock; + + if (ios->clock == 0) + dsor = 0; + else { + int func_clk_rate = clk_get_rate(host->fclk); + + dsor = func_clk_rate / realclock; + if (dsor < 1) + dsor = 1; + + if (func_clk_rate / dsor > realclock) + dsor++; + + if (dsor > 250) + dsor = 250; + dsor++; + + if (ios->bus_width == MMC_BUS_WIDTH_4) + dsor |= 1 << 15; + } + + switch (ios->power_mode) { + case MMC_POWER_OFF: + mmc_omap_power(host, 0); + break; + case MMC_POWER_UP: + case MMC_POWER_ON: + mmc_omap_power(host, 1); + dsor |= 1<<11; + break; + } + + host->bus_mode = ios->bus_mode; + host->hw_bus_mode = host->bus_mode; + + clk_enable(host->fclk); + + /* On insanely high arm_per frequencies something sometimes + * goes somehow out of sync, and the POW bit is not being set, + * which results in the while loop below getting stuck. + * Writing to the CON register twice seems to do the trick. */ + for (i = 0; i < 2; i++) + OMAP_MMC_WRITE(host->base, CON, dsor); + if (ios->power_mode == MMC_POWER_UP) { + /* Send clock cycles, poll completion */ + OMAP_MMC_WRITE(host->base, IE, 0); + OMAP_MMC_WRITE(host->base, STAT, 0xffff); + OMAP_MMC_WRITE(host->base, CMD, 1<<7); + while (0 == (OMAP_MMC_READ(host->base, STAT) & 1)); + OMAP_MMC_WRITE(host->base, STAT, 1); + } + clk_disable(host->fclk); +} + +static int mmc_omap_get_ro(struct mmc_host *mmc) +{ + struct mmc_omap_host *host = mmc_priv(mmc); + + return host->wp_pin && omap_get_gpio_datain(host->wp_pin); +} + +static struct mmc_host_ops mmc_omap_ops = { + .request = mmc_omap_request, + .set_ios = mmc_omap_set_ios, + .get_ro = mmc_omap_get_ro, +}; + +static int __init mmc_omap_probe(struct platform_device *pdev) +{ + struct omap_mmc_conf *minfo = pdev->dev.platform_data; + struct mmc_host *mmc; + struct mmc_omap_host *host = NULL; + int ret = 0; + + if (platform_get_resource(pdev, IORESOURCE_MEM, 0) || + platform_get_irq(pdev, IORESOURCE_IRQ, 0)) { + dev_err(&pdev->dev, "mmc_omap_probe: invalid resource type\n"); + return -ENODEV; + } + + if (!request_mem_region(pdev->resource[0].start, + pdev->resource[0].end - pdev->resource[0].start + 1, + pdev->name)) { + dev_dbg(&pdev->dev, "request_mem_region failed\n"); + return -EBUSY; + } + + mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev); + if (!mmc) { + ret = -ENOMEM; + goto out; + } + + host = mmc_priv(mmc); + host->mmc = mmc; + + spin_lock_init(&host->dma_lock); + init_timer(&host->dma_timer); + host->dma_timer.function = mmc_omap_dma_timer; + host->dma_timer.data = (unsigned long) host; + + host->id = pdev->id; + + if (cpu_is_omap24xx()) { + host->iclk = clk_get(&pdev->dev, "mmc_ick"); + if (IS_ERR(host->iclk)) + goto out; + clk_enable(host->iclk); + } + + if (!cpu_is_omap24xx()) + host->fclk = clk_get(&pdev->dev, "mmc_ck"); + else + host->fclk = clk_get(&pdev->dev, "mmc_fck"); + + if (IS_ERR(host->fclk)) { + ret = PTR_ERR(host->fclk); + goto out; + } + + /* REVISIT: + * Also, use minfo->cover to decide how to manage + * the card detect sensing. + */ + host->power_pin = minfo->power_pin; + host->switch_pin = minfo->switch_pin; + host->wp_pin = minfo->wp_pin; + host->use_dma = 1; + host->dma_ch = -1; + + host->irq = pdev->resource[1].start; + host->base = ioremap(pdev->res.start, SZ_4K); + if (!host->base) { + ret = -ENOMEM; + goto out; + } + + if (minfo->wire4) + mmc->caps |= MMC_CAP_4_BIT_DATA; + + mmc->ops = &mmc_omap_ops; + mmc->f_min = 400000; + mmc->f_max = 24000000; + mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; + + /* Use scatterlist DMA to reduce per-transfer costs. + * NOTE max_seg_size assumption that small blocks aren't + * normally used (except e.g. for reading SD registers). + */ + mmc->max_phys_segs = 32; + mmc->max_hw_segs = 32; + mmc->max_sectors = 256; /* NBLK max 11-bits, OMAP also limited by DMA */ + mmc->max_seg_size = mmc->max_sectors * 512; + + if (host->power_pin >= 0) { + if ((ret = omap_request_gpio(host->power_pin)) != 0) { + dev_err(mmc_dev(host->mmc), "Unable to get GPIO + pin for MMC power\n"); + goto out; + } + omap_set_gpio_direction(host->power_pin, 0); + } + + ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host); + if (ret) + goto out; + + host->dev = &pdev->dev; + platform_set_drvdata(pdev, host); + + mmc_add_host(mmc); + + if (host->switch_pin >= 0) { + INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host); + init_timer(&host->switch_timer); + host->switch_timer.function = mmc_omap_switch_timer; + host->switch_timer.data = (unsigned long) host; + if (omap_request_gpio(host->switch_pin) != 0) { + dev_warn(mmc_dev(host->mmc), "Unable to get GPIO pin for MMC cover switch\n"); + host->switch_pin = -1; + goto no_switch; + } + + omap_set_gpio_direction(host->switch_pin, 1); + ret = request_irq(OMAP_GPIO_IRQ(host->switch_pin), + mmc_omap_switch_irq, SA_TRIGGER_RISING, DRIVER_NAME, host); + if (ret) { + dev_warn(mmc_dev(host->mmc), "Unable to get IRQ for MMC cover switch\n"); + omap_free_gpio(host->switch_pin); + host->switch_pin = -1; + goto no_switch; + } + ret = device_create_file(&pdev->dev, &dev_attr_cover_switch); + if (ret == 0) { + ret = device_create_file(&pdev->dev, &dev_attr_enable_poll); + if (ret != 0) + device_remove_file(&pdev->dev, &dev_attr_cover_switch); + } + if (ret) { + dev_wan(mmc_dev(host->mmc), "Unable to create sysfs attributes\n"); + free_irq(OMAP_GPIO_IRQ(host->switch_pin), host); + omap_free_gpio(host->switch_pin); + host->switch_pin = -1; + goto no_switch; + } + if (mmc_omap_enable_poll && mmc_omap_cover_is_open(host)) + schedule_work(&host->switch_work); + } + +no_switch: + return 0; + +out: + /* FIXME: Free other resources too. */ + if (host) { + if (host->iclk && !IS_ERR(host->iclk)) + clk_put(host->iclk); + if (host->fclk && !IS_ERR(host->fclk)) + clk_put(host->fclk); + mmc_free_host(host->mmc); + } + return ret; +} + +static int mmc_omap_remove(struct platform_device *pdev) +{ + struct mmc_omap_host *host = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + if (host) { + mmc_remove_host(host->mmc); + free_irq(host->irq, host); + + if (host->power_pin >= 0) + omap_free_gpio(host->power_pin); + if (host->switch_pin >= 0) { + device_remove_file(&pdev->dev, &dev_attr_enable_poll); + device_remove_file(&pdev->dev, &dev_attr_cover_switch); + free_irq(OMAP_GPIO_IRQ(host->switch_pin), host); + omap_free_gpio(host->switch_pin); + host->switch_pin = -1; + del_timer_sync(&host->switch_timer); + flush_scheduled_work(); + } + if (host->iclk && !IS_ERR(host->iclk)) + clk_put(host->iclk); + if (host->fclk && !IS_ERR(host->fclk)) + clk_put(host->fclk); + mmc_free_host(host->mmc); + } + + release_mem_region(pdev->resource[0].start, + pdev->resource[0].end - pdev->resource[0].start + 1); + + return 0; +} + +#ifdef CONFIG_PM +static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + int ret = 0; + struct mmc_omap_host *host = platform_get_drvdata(pdev); + + if (host && host->suspended) + return 0; + + if (host) { + ret = mmc_suspend_host(host->mmc, mesg); + if (ret == 0) + host->suspended = 1; + } + return ret; +} + +static int mmc_omap_resume(struct platform_device *pdev) +{ + int ret = 0; + struct mmc_omap_host *host = platform_get_drvdata(pdev); + + if (host && !host->suspended) + return 0; + + if (host) { + ret = mmc_resume_host(host->mmc); + if (ret == 0) + host->suspended = 0; + } + + return ret; +} +#else +#define mmc_omap_suspend NULL +#define mmc_omap_resume NULL +#endif + +static struct platform_driver mmc_omap_driver = { + .probe = mmc_omap_probe, + .remove = mmc_omap_remove, + .suspend = mmc_omap_suspend, + .resume = mmc_omap_resume, + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init mmc_omap_init(void) +{ + return platform_driver_register(&mmc_omap_driver); +} + +static void __exit mmc_omap_exit(void) +{ + platform_driver_unregister(&mmc_omap_driver); +} + +module_init(mmc_omap_init); +module_exit(mmc_omap_exit); + +MODULE_DESCRIPTION("OMAP Multimedia Card driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS(DRIVER_NAME); +MODULE_AUTHOR("Juha Yrjölä"); diff --git a/drivers/mmc/omap.h b/drivers/mmc/omap.h new file mode 100644 index 0000000000..c954d355a5 --- /dev/null +++ b/drivers/mmc/omap.h @@ -0,0 +1,55 @@ +#ifndef DRIVERS_MEDIA_MMC_OMAP_H +#define DRIVERS_MEDIA_MMC_OMAP_H + +#define OMAP_MMC_REG_CMD 0x00 +#define OMAP_MMC_REG_ARGL 0x04 +#define OMAP_MMC_REG_ARGH 0x08 +#define OMAP_MMC_REG_CON 0x0c +#define OMAP_MMC_REG_STAT 0x10 +#define OMAP_MMC_REG_IE 0x14 +#define OMAP_MMC_REG_CTO 0x18 +#define OMAP_MMC_REG_DTO 0x1c +#define OMAP_MMC_REG_DATA 0x20 +#define OMAP_MMC_REG_BLEN 0x24 +#define OMAP_MMC_REG_NBLK 0x28 +#define OMAP_MMC_REG_BUF 0x2c +#define OMAP_MMC_REG_SDIO 0x34 +#define OMAP_MMC_REG_REV 0x3c +#define OMAP_MMC_REG_RSP0 0x40 +#define OMAP_MMC_REG_RSP1 0x44 +#define OMAP_MMC_REG_RSP2 0x48 +#define OMAP_MMC_REG_RSP3 0x4c +#define OMAP_MMC_REG_RSP4 0x50 +#define OMAP_MMC_REG_RSP5 0x54 +#define OMAP_MMC_REG_RSP6 0x58 +#define OMAP_MMC_REG_RSP7 0x5c +#define OMAP_MMC_REG_IOSR 0x60 +#define OMAP_MMC_REG_SYSC 0x64 +#define OMAP_MMC_REG_SYSS 0x68 + +#define OMAP_MMC_STAT_CARD_ERR (1 << 14) +#define OMAP_MMC_STAT_CARD_IRQ (1 << 13) +#define OMAP_MMC_STAT_OCR_BUSY (1 << 12) +#define OMAP_MMC_STAT_A_EMPTY (1 << 11) +#define OMAP_MMC_STAT_A_FULL (1 << 10) +#define OMAP_MMC_STAT_CMD_CRC (1 << 8) +#define OMAP_MMC_STAT_CMD_TOUT (1 << 7) +#define OMAP_MMC_STAT_DATA_CRC (1 << 6) +#define OMAP_MMC_STAT_DATA_TOUT (1 << 5) +#define OMAP_MMC_STAT_END_BUSY (1 << 4) +#define OMAP_MMC_STAT_END_OF_DATA (1 << 3) +#define OMAP_MMC_STAT_CARD_BUSY (1 << 2) +#define OMAP_MMC_STAT_END_OF_CMD (1 << 0) + +#define OMAP_MMC_READ(base, reg) __raw_readw((base) + OMAP_MMC_REG_##reg) +#define OMAP_MMC_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MMC_REG_##reg) + +/* + * Command types + */ +#define OMAP_MMC_CMDTYPE_BC 0 +#define OMAP_MMC_CMDTYPE_BCR 1 +#define OMAP_MMC_CMDTYPE_AC 2 +#define OMAP_MMC_CMDTYPE_ADTC 3 + +#endif -- cgit v1.2.2 From c65631781eb0f2e81865017c1484e9aef76e1b61 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 29 Mar 2006 09:30:20 +0100 Subject: [MMC] Pass -DDEBUG on compiler command line if MMC_DEBUG selected Rather than each driver test MMC_DEBUG itself, and define DEBUG, pass it in via the makefile instead. Fix drivers to use pr_debug() where appropriate, and avoid defining a DEBUG() macro. Signed-off-by: Russell King --- drivers/mmc/Makefile | 4 ++++ drivers/mmc/au1xmmc.c | 19 +++++++++---------- drivers/mmc/mmc.c | 19 +++++++------------ drivers/mmc/mmci.c | 4 ---- drivers/mmc/omap.c | 5 ----- drivers/mmc/pxamci.c | 24 +++++++++--------------- drivers/mmc/sdhci.c | 6 +----- drivers/mmc/wbsd.c | 9 ++------- 8 files changed, 32 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 0b0920ae46..c7c34aadfc 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -23,3 +23,7 @@ obj-$(CONFIG_MMC_AU1X) += au1xmmc.o obj-$(CONFIG_MMC_OMAP) += omap.o mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o + +ifeq ($(CONFIG_MMC_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c index 85e89c77bd..c0326bbc5f 100644 --- a/drivers/mmc/au1xmmc.c +++ b/drivers/mmc/au1xmmc.c @@ -56,12 +56,11 @@ #define DRIVER_NAME "au1xxx-mmc" /* Set this to enable special debugging macros */ -/* #define MMC_DEBUG */ -#ifdef MMC_DEBUG -#define DEBUG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args) +#ifdef DEBUG +#define DBG(fmt, idx, args...) printk("au1xx(%d): DEBUG: " fmt, idx, ##args) #else -#define DEBUG(fmt, idx, args...) +#define DBG(fmt, idx, args...) #endif const struct { @@ -424,18 +423,18 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host) break; if (status & SD_STATUS_RC) { - DEBUG("RX CRC Error [%d + %d].\n", host->id, + DBG("RX CRC Error [%d + %d].\n", host->id, host->pio.len, count); break; } if (status & SD_STATUS_RO) { - DEBUG("RX Overrun [%d + %d]\n", host->id, + DBG("RX Overrun [%d + %d]\n", host->id, host->pio.len, count); break; } else if (status & SD_STATUS_RU) { - DEBUG("RX Underrun [%d + %d]\n", host->id, + DBG("RX Underrun [%d + %d]\n", host->id, host->pio.len, count); break; } @@ -721,7 +720,7 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) { struct au1xmmc_host *host = mmc_priv(mmc); - DEBUG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n", + DBG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n", host->id, ios->power_mode, ios->clock, ios->vdd, ios->bus_mode); @@ -810,7 +809,7 @@ static irqreturn_t au1xmmc_irq(int irq, void *dev_id, struct pt_regs *regs) au1xmmc_receive_pio(host); } else if (status & 0x203FBC70) { - DEBUG("Unhandled status %8.8x\n", host->id, status); + DBG("Unhandled status %8.8x\n", host->id, status); handled = 0; } @@ -839,7 +838,7 @@ static void au1xmmc_poll_event(unsigned long arg) if (host->mrq != NULL) { u32 status = au_readl(HOST_STATUS(host)); - DEBUG("PENDING - %8.8x\n", host->id, status); + DBG("PENDING - %8.8x\n", host->id, status); } mod_timer(&host->timer, jiffies + AU1XMMC_DETECT_TIMEOUT); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 1888060c5e..da6ddd910f 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -27,12 +27,6 @@ #include "mmc.h" -#ifdef CONFIG_MMC_DEBUG -#define DBG(x...) printk(KERN_DEBUG x) -#else -#define DBG(x...) do { } while (0) -#endif - #define CMD_RETRIES 3 /* @@ -77,8 +71,9 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) { struct mmc_command *cmd = mrq->cmd; int err = mrq->cmd->error; - DBG("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", cmd->opcode, - err, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); + pr_debug("MMC: req done (%02x): %d: %08x %08x %08x %08x\n", + cmd->opcode, err, cmd->resp[0], cmd->resp[1], + cmd->resp[2], cmd->resp[3]); if (err && cmd->retries) { cmd->retries--; @@ -102,8 +97,8 @@ EXPORT_SYMBOL(mmc_request_done); void mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) { - DBG("MMC: starting cmd %02x arg %08x flags %08x\n", - mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags); + pr_debug("MMC: starting cmd %02x arg %08x flags %08x\n", + mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags); WARN_ON(host->card_busy == NULL); @@ -976,8 +971,8 @@ static unsigned int mmc_calculate_clock(struct mmc_host *host) if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr) max_dtr = card->csd.max_dtr; - DBG("MMC: selected %d.%03dMHz transfer rate\n", - max_dtr / 1000000, (max_dtr / 1000) % 1000); + pr_debug("MMC: selected %d.%03dMHz transfer rate\n", + max_dtr / 1000000, (max_dtr / 1000) % 1000); return max_dtr; } diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 9fef29d978..df7e861e2f 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c @@ -33,12 +33,8 @@ #define DRIVER_NAME "mmci-pl18x" -#ifdef CONFIG_MMC_DEBUG #define DBG(host,fmt,args...) \ pr_debug("%s: %s: " fmt, mmc_hostname(host->mmc), __func__ , args) -#else -#define DBG(host,fmt,args...) do { } while (0) -#endif static unsigned int fmax = 515633; diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 49fb2ea4b7..becb3c68c3 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -12,11 +12,6 @@ */ #include - -#ifdef CONFIG_MMC_DEBUG -#define DEBUG /* for dev_dbg(), pr_debug(), etc */ -#endif - #include #include #include diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index c32fad1ce5..eb9a8826e9 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -37,12 +37,6 @@ #include "pxamci.h" -#ifdef CONFIG_MMC_DEBUG -#define DBG(x...) printk(KERN_DEBUG x) -#else -#define DBG(x...) do { } while (0) -#endif - #define DRIVER_NAME "pxa2xx-mci" #define NR_SG 1 @@ -206,7 +200,7 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq) { - DBG("PXAMCI: request done\n"); + pr_debug("PXAMCI: request done\n"); host->mrq = NULL; host->cmd = NULL; host->data = NULL; @@ -252,7 +246,7 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) if ((cmd->resp[0] & 0x80000000) == 0) cmd->error = MMC_ERR_BADCRC; } else { - DBG("ignoring CRC from command %d - *risky*\n",cmd->opcode); + pr_debug("ignoring CRC from command %d - *risky*\n",cmd->opcode); } #else cmd->error = MMC_ERR_BADCRC; @@ -317,12 +311,12 @@ static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs) ireg = readl(host->base + MMC_I_REG); - DBG("PXAMCI: irq %08x\n", ireg); + pr_debug("PXAMCI: irq %08x\n", ireg); if (ireg) { unsigned stat = readl(host->base + MMC_STAT); - DBG("PXAMCI: stat %08x\n", stat); + pr_debug("PXAMCI: stat %08x\n", stat); if (ireg & END_CMD_RES) handled |= pxamci_cmd_done(host, stat); @@ -376,9 +370,9 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct pxamci_host *host = mmc_priv(mmc); - DBG("pxamci_set_ios: clock %u power %u vdd %u.%02u\n", - ios->clock, ios->power_mode, ios->vdd / 100, - ios->vdd % 100); + pr_debug("pxamci_set_ios: clock %u power %u vdd %u.%02u\n", + ios->clock, ios->power_mode, ios->vdd / 100, + ios->vdd % 100); if (ios->clock) { unsigned int clk = CLOCKRATE / ios->clock; @@ -405,8 +399,8 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->cmdat |= CMDAT_INIT; } - DBG("pxamci_set_ios: clkrt = %x cmdat = %x\n", - host->clkrt, host->cmdat); + pr_debug("pxamci_set_ios: clkrt = %x cmdat = %x\n", + host->clkrt, host->cmdat); } static struct mmc_host_ops pxamci_ops = { diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 8b811d9437..bdbfca0500 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -31,12 +31,8 @@ #define BUGMAIL "" -#ifdef CONFIG_MMC_DEBUG #define DBG(f, x...) \ - printk(KERN_DEBUG DRIVER_NAME " [%s()]: " f, __func__,## x) -#else -#define DBG(f, x...) do { } while (0) -#endif + pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x) static const struct pci_device_id pci_ids[] __devinitdata = { /* handle any SD host controller */ diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 3be397d436..511f7b0b31 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -44,15 +44,10 @@ #define DRIVER_NAME "wbsd" #define DRIVER_VERSION "1.5" -#ifdef CONFIG_MMC_DEBUG #define DBG(x...) \ - printk(KERN_DEBUG DRIVER_NAME ": " x) + pr_debug(DRIVER_NAME ": " x) #define DBGF(f, x...) \ - printk(KERN_DEBUG DRIVER_NAME " [%s()]: " f, __func__ , ##x) -#else -#define DBG(x...) do { } while (0) -#define DBGF(x...) do { } while (0) -#endif + pr_debug(DRIVER_NAME " [%s()]: " f, __func__ , ##x) /* * Device resources -- cgit v1.2.2 From 3f89f834497c0f37f16a3b6c32b1d60782facbca Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Mar 2006 09:36:45 -0800 Subject: IB/srp: Fix unmapping of fake scatterlist The recently merged patch to create a fake scatterlist for non-SG SCSI commands had a bug: the driver ended up doing dma_unmap_sg() on a scatterlist scmnd->request_buffer rather than the fake scatter list it created. Fix this so that the driver unmaps the same thing it maps. Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 61924cc30e..fd8a95a9c5 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -607,10 +607,10 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, */ if (likely(scmnd->use_sg)) { nents = scmnd->use_sg; - scat = (struct scatterlist *) scmnd->request_buffer; + scat = scmnd->request_buffer; } else { nents = 1; - scat = (struct scatterlist *) scmnd->request_buffer; + scat = &req->fake_sg; } dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents, -- cgit v1.2.2 From a07bacca7b4032dd361ad5c87b1c39ae229e6739 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Sun, 26 Mar 2006 17:01:12 +0200 Subject: IB/mthca: Fix check of size in SRQ creation The previous patch for Tavor broke MemFree logic. The driver should perform limit check only for Tavor. For MemFree, the check is incorrect, since ds (WQE stride) is always a power-of-2 (although the max_desc_size may not be). In Tavor, however, WQE stride and desc_size are the same, and are not necessarily power-of-2. The check was really for the WQE stride (and it Tavor, we use max_desc_size for the stride). Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_srq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 0cfd158022..e74751ef91 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -206,7 +206,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, roundup_pow_of_two(sizeof (struct mthca_next_seg) + srq->max_gs * sizeof (struct mthca_data_seg))); - if (ds > dev->limits.max_desc_sz) + if (!mthca_is_memfree(dev) && (ds > dev->limits.max_desc_sz)) return -EINVAL; srq->wqe_shift = long_log2(ds); -- cgit v1.2.2 From ef12d4561900d4af37f46a8f2d97dec3c4d59bf9 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Mar 2006 09:36:46 -0800 Subject: IPoIB: Fix oops with raw sockets ipoib_hard_header() needs to handle the case that daddr is NULL. This can happen when packets are injected via a raw socket, and IPoIB shouldn't oops in this case. Reported by Anton Blanchard Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 53a32f6578..9b0bd7c746 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -723,7 +723,7 @@ static int ipoib_hard_header(struct sk_buff *skb, * destination address onto the front of the skb so we can * figure out where to send the packet later. */ - if (!skb->dst || !skb->dst->neighbour) { + if ((!skb->dst || !skb->dst->neighbour) && daddr) { struct ipoib_pseudoheader *phdr = (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); -- cgit v1.2.2 From e1f7868c80947d40ef8e1fd37323d939a9bf311c Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Mar 2006 09:36:46 -0800 Subject: IB/mthca: Fix section mismatch problems Quite a few cleanup functions in mthca were marked as __devexit. However, they could also be called from error paths during initialization, so they cannot be marked that way. Just delete all of the incorrect annotations. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_av.c | 2 +- drivers/infiniband/hw/mthca/mthca_cq.c | 2 +- drivers/infiniband/hw/mthca/mthca_eq.c | 6 +++--- drivers/infiniband/hw/mthca/mthca_mad.c | 2 +- drivers/infiniband/hw/mthca/mthca_mcg.c | 2 +- drivers/infiniband/hw/mthca/mthca_mr.c | 4 ++-- drivers/infiniband/hw/mthca/mthca_pd.c | 2 +- drivers/infiniband/hw/mthca/mthca_qp.c | 2 +- drivers/infiniband/hw/mthca/mthca_srq.c | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index f023d39365..bc5bdcbe51 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c @@ -265,7 +265,7 @@ int __devinit mthca_init_av_table(struct mthca_dev *dev) return -ENOMEM; } -void __devexit mthca_cleanup_av_table(struct mthca_dev *dev) +void mthca_cleanup_av_table(struct mthca_dev *dev) { if (mthca_is_memfree(dev)) return; diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 76aabc5bf3..312cf90731 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -973,7 +973,7 @@ int __devinit mthca_init_cq_table(struct mthca_dev *dev) return err; } -void __devexit mthca_cleanup_cq_table(struct mthca_dev *dev) +void mthca_cleanup_cq_table(struct mthca_dev *dev) { mthca_array_cleanup(&dev->cq_table.cq, dev->limits.num_cqs); mthca_alloc_cleanup(&dev->cq_table.alloc); diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index cbdc348fb6..99f109c381 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -765,7 +765,7 @@ static int __devinit mthca_map_eq_regs(struct mthca_dev *dev) } -static void __devexit mthca_unmap_eq_regs(struct mthca_dev *dev) +static void mthca_unmap_eq_regs(struct mthca_dev *dev) { if (mthca_is_memfree(dev)) { mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & @@ -821,7 +821,7 @@ int __devinit mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt) return ret; } -void __devexit mthca_unmap_eq_icm(struct mthca_dev *dev) +void mthca_unmap_eq_icm(struct mthca_dev *dev) { u8 status; @@ -954,7 +954,7 @@ err_out_free: return err; } -void __devexit mthca_cleanup_eq_table(struct mthca_dev *dev) +void mthca_cleanup_eq_table(struct mthca_dev *dev) { u8 status; int i; diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 4ace6a392f..dfb482eac9 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c @@ -271,7 +271,7 @@ err: return PTR_ERR(agent); } -void mthca_free_agents(struct mthca_dev *dev) +void __devexit mthca_free_agents(struct mthca_dev *dev) { struct ib_mad_agent *agent; int p, q; diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index 9965bda9af..47ca8a9b72 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c @@ -388,7 +388,7 @@ int __devinit mthca_init_mcg_table(struct mthca_dev *dev) return 0; } -void __devexit mthca_cleanup_mcg_table(struct mthca_dev *dev) +void mthca_cleanup_mcg_table(struct mthca_dev *dev) { mthca_alloc_cleanup(&dev->mcg_table.alloc); } diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 698b621257..25e1c1db9a 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -170,7 +170,7 @@ err_out: return -ENOMEM; } -static void __devexit mthca_buddy_cleanup(struct mthca_buddy *buddy) +static void mthca_buddy_cleanup(struct mthca_buddy *buddy) { int i; @@ -866,7 +866,7 @@ err_mtt_buddy: return err; } -void __devexit mthca_cleanup_mr_table(struct mthca_dev *dev) +void mthca_cleanup_mr_table(struct mthca_dev *dev) { /* XXX check if any MRs are still allocated? */ if (dev->limits.fmr_reserved_mtts) diff --git a/drivers/infiniband/hw/mthca/mthca_pd.c b/drivers/infiniband/hw/mthca/mthca_pd.c index 105fc5faad..59df51614c 100644 --- a/drivers/infiniband/hw/mthca/mthca_pd.c +++ b/drivers/infiniband/hw/mthca/mthca_pd.c @@ -77,7 +77,7 @@ int __devinit mthca_init_pd_table(struct mthca_dev *dev) dev->limits.reserved_pds); } -void __devexit mthca_cleanup_pd_table(struct mthca_dev *dev) +void mthca_cleanup_pd_table(struct mthca_dev *dev) { /* XXX check if any PDs are still allocated? */ mthca_alloc_cleanup(&dev->pd_table.alloc); diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 1bc2678c2f..057c8e6af8 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -2204,7 +2204,7 @@ int __devinit mthca_init_qp_table(struct mthca_dev *dev) return err; } -void __devexit mthca_cleanup_qp_table(struct mthca_dev *dev) +void mthca_cleanup_qp_table(struct mthca_dev *dev) { int i; u8 status; diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index e74751ef91..2dd3aea053 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -684,7 +684,7 @@ int __devinit mthca_init_srq_table(struct mthca_dev *dev) return err; } -void __devexit mthca_cleanup_srq_table(struct mthca_dev *dev) +void mthca_cleanup_srq_table(struct mthca_dev *dev) { if (!(dev->mthca_flags & MTHCA_FLAG_SRQ)) return; -- cgit v1.2.2 From 0cff260a42c051ee64c184ed05d96d18d243f7f6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 29 Mar 2006 22:03:38 +0100 Subject: [SERIAL] Allow 8250 PCI, PNP, GSC and HP300 support to be disabled Allow the 8250 probe modules to be disabled if we're building for with EMBEDDED enabled. This reduces the kernel size by not including unnecessary probe module support. Original idea from Matt Mackall for PCI only, expanded to others by rmk. Signed-off-by: Russell King --- drivers/serial/Kconfig | 27 +++++++++++++++++++++++++++ drivers/serial/Makefile | 12 +++++------- 2 files changed, 32 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index fe0d8b8e91..7d22dc0478 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -63,6 +63,33 @@ config SERIAL_8250_CONSOLE If unsure, say N. +config SERIAL_8250_GSC + tristate + depends on SERIAL_8250 && GSC + default SERIAL_8250 + +config SERIAL_8250_PCI + tristate "8250/16550 PCI device support" if EMBEDDED + depends on SERIAL_8250 && PCI + default SERIAL_8250 + help + This builds standard PCI serial support. You may be able to + disable this feature if you only need legacy serial support. + Saves about 9K. + +config SERIAL_8250_PNP + tristate "8250/16550 PNP device support" if EMBEDDED + depends on SERIAL_8250 && PNP + default SERIAL_8250 + help + This builds standard PNP serial support. You may be able to + disable this feature if you only need legacy serial support. + +config SERIAL_8250_HP300 + tristate + depends on SERIAL_8250 && HP300 + default SERIAL_8250 + config SERIAL_8250_CS tristate "8250/16550 PCMCIA device support" depends on PCMCIA && SERIAL_8250 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index d2b4c21487..0a71bf68a0 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -4,15 +4,13 @@ # $Id: Makefile,v 1.8 2002/07/21 21:32:30 rmk Exp $ # -serial-8250-y := -serial-8250-$(CONFIG_PNP) += 8250_pnp.o -serial-8250-$(CONFIG_GSC) += 8250_gsc.o -serial-8250-$(CONFIG_PCI) += 8250_pci.o -serial-8250-$(CONFIG_HP300) += 8250_hp300.o - obj-$(CONFIG_SERIAL_CORE) += serial_core.o obj-$(CONFIG_SERIAL_21285) += 21285.o -obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y) +obj-$(CONFIG_SERIAL_8250) += 8250.o +obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o +obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o +obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o +obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o -- cgit v1.2.2 From 5c5131297db57b501f371ab53c40343eac6f2af7 Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Wed, 29 Mar 2006 17:12:05 -0500 Subject: b44: fix force mac address before ifconfig up Initializing the b44 MAC & PCI functional blocks in the controller must occur inside init_one(). This will allow access to the MAC registers. The controller was being powered up in b44_open() which would not allow access to the registers before ifconfig was up. Philip Kohlbecher found this bug. Signed-off-by: Gary Zambrano --- drivers/net/b44.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/b44.c b/drivers/net/b44.c index c3267e4e1b..2eab2a88c7 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -2033,6 +2033,11 @@ static int __devinit b44_init_one(struct pci_dev *pdev, pci_save_state(bp->pdev); + /* Chip reset provides power to the b44 MAC & PCI cores, which + * is necessary for MAC register access. + */ + b44_chip_reset(bp); + printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name); for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i], -- cgit v1.2.2 From 05c8e0ac5c37e9739a852b526afeecae97607cbb Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 25 Mar 2006 14:28:57 +0900 Subject: [PATCH] libata: kill trailing whitespace Kill trailing whitespace. Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1cb9813753..86310562da 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2635,7 +2635,7 @@ static int ata_dma_blacklisted(const struct ata_device *dev) * * FIXME: The current implementation limits all transfer modes to * the fastest of the lowested device on the port. This is not - * required on most controllers. + * required on most controllers. * * LOCKING: * None. -- cgit v1.2.2 From b8ab2dc3e1a7c525ca73ba0af3518ec0b7654b3b Mon Sep 17 00:00:00 2001 From: Komuro Date: Sun, 26 Mar 2006 07:31:55 +0900 Subject: [PATCH] axnet_cs.c : add hardware multicast support Signed-off-by: Jeff Garzik --- drivers/net/pcmcia/axnet_cs.c | 61 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index aa55813693..1cc94b2d76 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "../8390.h" #include @@ -1682,17 +1683,67 @@ static struct net_device_stats *get_stats(struct net_device *dev) return &ei_local->stat; } +/* + * Form the 64 bit 8390 multicast table from the linked list of addresses + * associated with this dev structure. + */ + +static inline void make_mc_bits(u8 *bits, struct net_device *dev) +{ + struct dev_mc_list *dmi; + u32 crc; + + for (dmi=dev->mc_list; dmi; dmi=dmi->next) { + + crc = ether_crc(ETH_ALEN, dmi->dmi_addr); + /* + * The 8390 uses the 6 most significant bits of the + * CRC to index the multicast table. + */ + bits[crc>>29] |= (1<<((crc>>26)&7)); + } +} + /** * do_set_multicast_list - set/clear multicast filter * @dev: net device for which multicast filter is adjusted * - * Set or clear the multicast filter for this adaptor. May be called - * from a BH in 2.1.x. Must be called with lock held. + * Set or clear the multicast filter for this adaptor. + * Must be called with lock held. */ static void do_set_multicast_list(struct net_device *dev) { long e8390_base = dev->base_addr; + int i; + struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev); + + if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) { + memset(ei_local->mcfilter, 0, 8); + if (dev->mc_list) + make_mc_bits(ei_local->mcfilter, dev); + } else { + /* set to accept-all */ + memset(ei_local->mcfilter, 0xFF, 8); + } + + /* + * DP8390 manuals don't specify any magic sequence for altering + * the multicast regs on an already running card. To be safe, we + * ensure multicast mode is off prior to loading up the new hash + * table. If this proves to be not enough, we can always resort + * to stopping the NIC, loading the table and then restarting. + */ + + if (netif_running(dev)) + outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); + + outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD); + for(i = 0; i < 8; i++) + { + outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i)); + } + outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD); if(dev->flags&IFF_PROMISC) outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR); @@ -1794,12 +1845,6 @@ static void AX88190_init(struct net_device *dev, int startp) if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i]) printk(KERN_ERR "Hw. address read/write mismap %d\n",i); } - /* - * Initialize the multicast list to accept-all. If we enable multicast - * the higher levels can do the filtering. - */ - for (i = 0; i < 8; i++) - outb_p(0xff, e8390_base + EN1_MULT + i); outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); -- cgit v1.2.2 From 00b428c2ab35c81905b3e39d673689216dbd4742 Mon Sep 17 00:00:00 2001 From: Roger Luethi Date: Tue, 28 Mar 2006 20:53:56 +0200 Subject: [PATCH] via-rhine: link state fix Problems with link state detection have been reported several times in the past months. Denis Vlasenko did all the work tracking it down. Jeff Garzik suggested the proper place for the fix. When using the mii library, the driver needs to check mii->force_media and set dev->state accordingly. Signed-off-by: Roger Luethi Signed-off-by: Jeff Garzik --- drivers/net/via-rhine.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 2418715892..a9b2150909 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1085,6 +1085,25 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media) else iowrite8(ioread8(ioaddr + ChipCmd1) & ~Cmd1FDuplex, ioaddr + ChipCmd1); + if (debug > 1) + printk(KERN_INFO "%s: force_media %d, carrier %d\n", dev->name, + rp->mii_if.force_media, netif_carrier_ok(dev)); +} + +/* Called after status of force_media possibly changed */ +void rhine_set_carrier(struct mii_if_info *mii) +{ + if (mii->force_media) { + /* autoneg is off: Link is always assumed to be up */ + if (!netif_carrier_ok(mii->dev)) + netif_carrier_on(mii->dev); + } + else /* Let MMI library update carrier status */ + rhine_check_media(mii->dev, 0); + if (debug > 1) + printk(KERN_INFO "%s: force_media %d, carrier %d\n", + mii->dev->name, mii->force_media, + netif_carrier_ok(mii->dev)); } static void rhine_check_media_task(struct net_device *dev) @@ -1782,6 +1801,7 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) spin_lock_irq(&rp->lock); rc = mii_ethtool_sset(&rp->mii_if, cmd); spin_unlock_irq(&rp->lock); + rhine_set_carrier(&rp->mii_if); return rc; } @@ -1869,6 +1889,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) spin_lock_irq(&rp->lock); rc = generic_mii_ioctl(&rp->mii_if, if_mii(rq), cmd, NULL); spin_unlock_irq(&rp->lock); + rhine_set_carrier(&rp->mii_if); return rc; } -- cgit v1.2.2 From 4e5077b62b1f67fe0df916e387da4a6dabe577e9 Mon Sep 17 00:00:00 2001 From: Jens Osterkamp Date: Tue, 28 Mar 2006 15:59:55 +0200 Subject: [PATCH] spidernet : reduce console spam This patch reduces the message level of the RX ram full messages from err to debug to prevent spamming the console leaving it in the logfiles though. From: Jens Osterkamp Signed-off-by: Jeff Garzik --- drivers/net/spider_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 1f5975a61e..0000de01ec 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -1442,7 +1442,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) case SPIDER_NET_GRFAFLLINT: /* fallthrough */ case SPIDER_NET_GRMFLLINT: if (netif_msg_intr(card) && net_ratelimit()) - pr_err("Spider RX RAM full, incoming packets " + pr_debug("Spider RX RAM full, incoming packets " "might be discarded!\n"); spider_net_rx_irq_off(card); tasklet_schedule(&card->rxram_full_tl); -- cgit v1.2.2 From 8a89334caf80bb7c86383b73fd5a528cb88c696f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 27 Mar 2006 12:26:12 -0800 Subject: [PATCH] acenic: fix section mismatches Fix section mismatches in acenic driver: WARNING: drivers/net/acenic.o - Section mismatch: reference to .init.data:tigon2FwText from .text between 'acenic_probe_one' (at offset 0x2409) and 'ace_interrupt' WARNING: drivers/net/acenic.o - Section mismatch: reference to .init.data:tigon2FwRodata from .text between 'acenic_probe_one' (at offset 0x2422) and 'ace_interrupt' Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/net/acenic_firmware.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h index 6d625d5956..d7882dd783 100644 --- a/drivers/net/acenic_firmware.h +++ b/drivers/net/acenic_firmware.h @@ -4397,7 +4397,7 @@ static u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = { 0x3c010001, 0x220821, 0xac317e30, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x0 }; -static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { +static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __devinitdata = { 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e, @@ -4571,7 +4571,7 @@ static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x0, 0x14c38, 0x14c38, 0x14b80, 0x14bc4, 0x14c38, 0x14c38, 0x0, 0x0, 0x0 }; -static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = { +static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __devinitdata = { 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242, @@ -4612,7 +4612,7 @@ static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = { #define tigon2FwSbssLen 0xcc #define tigon2FwBssAddr 0x00016f50 #define tigon2FwBssLen 0x20c0 -static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { +static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = { 0x0, 0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000, @@ -9154,7 +9154,7 @@ static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24020001, 0x8f430328, 0x1021, 0x24630001, 0x3e00008, 0xaf430328, 0x3e00008, 0x0, 0x0, 0x0, 0x0, 0x0 }; -static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { +static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __devinitdata = { 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, @@ -9425,7 +9425,7 @@ static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x14ed8, 0x14b8c, 0x14bd8, 0x14c24, 0x14ed8, 0x7365746d, 0x61636163, 0x74000000, 0x0, 0x0 }; -static u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __initdata = { +static u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __devinitdata = { 0x1, 0x1, 0x1, 0xc001fc, 0x3ffc, 0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49, -- cgit v1.2.2 From ff59c4563a8d1b39597aab4917959146c61f09b0 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Mon, 27 Mar 2006 13:27:43 -0800 Subject: [PATCH] bonding: support carrier state for master Add support for the bonding master to specify its carrier state based upon the state of the slaves. For 802.3ad, the bond is up if there is an active, parterned aggregator. For other modes, the bond is up if any slaves are up. Updates driver version to 3.0.3. Based on a patch by jamal . Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_3ad.c | 28 ++++++++++++ drivers/net/bonding/bond_3ad.h | 1 + drivers/net/bonding/bond_main.c | 97 ++++++++++++++++++++++++++++++----------- drivers/net/bonding/bonding.h | 4 +- 4 files changed, 102 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index f3f5825469..6a407070c2 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2294,6 +2294,34 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) port->sm_vars |= AD_PORT_BEGIN; } +/* + * set link state for bonding master: if we have an active partnered + * aggregator, we're up, if not, we're down. Presumes that we cannot + * have an active aggregator if there are no slaves with link up. + * + * Called by bond_set_carrier(). Return zero if carrier state does not + * change, nonzero if it does. + */ +int bond_3ad_set_carrier(struct bonding *bond) +{ + struct aggregator *agg; + + agg = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator)); + if (agg && MAC_ADDRESS_COMPARE(&agg->partner_system, &null_mac_addr)) { + if (!netif_carrier_ok(bond->dev)) { + netif_carrier_on(bond->dev); + return 1; + } + return 0; + } + + if (netif_carrier_ok(bond->dev)) { + netif_carrier_off(bond->dev); + return 1; + } + return 0; +} + /** * bond_3ad_get_active_agg_info - get information of the active aggregator * @bond: bonding struct to work on diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index 5ee2cef5b0..6ad5ad6e65 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h @@ -283,5 +283,6 @@ void bond_3ad_handle_link_change(struct slave *slave, char link); int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info); int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev); int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev); +int bond_3ad_set_carrier(struct bonding *bond); #endif //__BOND_3AD_H__ diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f13a539dc1..55d236726d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -558,6 +558,42 @@ out: /*------------------------------- Link status -------------------------------*/ +/* + * Set the carrier state for the master according to the state of its + * slaves. If any slaves are up, the master is up. In 802.3ad mode, + * do special 802.3ad magic. + * + * Returns zero if carrier state does not change, nonzero if it does. + */ +static int bond_set_carrier(struct bonding *bond) +{ + struct slave *slave; + int i; + + if (bond->slave_cnt == 0) + goto down; + + if (bond->params.mode == BOND_MODE_8023AD) + return bond_3ad_set_carrier(bond); + + bond_for_each_slave(bond, slave, i) { + if (slave->link == BOND_LINK_UP) { + if (!netif_carrier_ok(bond->dev)) { + netif_carrier_on(bond->dev); + return 1; + } + return 0; + } + } + +down: + if (netif_carrier_ok(bond->dev)) { + netif_carrier_off(bond->dev); + return 1; + } + return 0; +} + /* * Get link speed and duplex from the slave's base driver * using ethtool. If for some reason the call fails or the @@ -1074,10 +1110,24 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) void bond_select_active_slave(struct bonding *bond) { struct slave *best_slave; + int rv; best_slave = bond_find_best_slave(bond); if (best_slave != bond->curr_active_slave) { bond_change_active_slave(bond, best_slave); + rv = bond_set_carrier(bond); + if (!rv) + return; + + if (netif_carrier_ok(bond->dev)) { + printk(KERN_INFO DRV_NAME + ": %s: first active interface up!\n", + bond->dev->name); + } else { + printk(KERN_INFO DRV_NAME ": %s: " + "now running without any active interface !\n", + bond->dev->name); + } } } @@ -1458,10 +1508,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (((!bond->curr_active_slave) || (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) && (new_slave->link != BOND_LINK_DOWN)) { - dprintk("This is the first active slave\n"); /* first slave or no active slave yet, and this link is OK, so make this interface the active one */ bond_change_active_slave(bond, new_slave); + printk(KERN_INFO DRV_NAME + ": %s: first active interface up!\n", + bond->dev->name); + netif_carrier_on(bond->dev); + } else { dprintk("This is just a backup slave\n"); bond_set_slave_inactive_flags(new_slave); @@ -1517,6 +1571,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) break; } /* switch(bond_mode) */ + bond_set_carrier(bond); + write_unlock_bh(&bond->lock); res = bond_create_slave_symlinks(bond_dev, slave_dev); @@ -1656,18 +1712,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) bond_alb_deinit_slave(bond, slave); } - if (oldcurrent == slave) { + if (oldcurrent == slave) bond_select_active_slave(bond); - if (!bond->curr_active_slave) { - printk(KERN_INFO DRV_NAME - ": %s: now running without any active " - "interface !\n", - bond_dev->name); - } - } - if (bond->slave_cnt == 0) { + bond_set_carrier(bond); + /* if the last slave was removed, zero the mac address * of the master so it will be set by the application * to the mac address of the first slave @@ -1751,6 +1801,8 @@ static int bond_release_all(struct net_device *bond_dev) write_lock_bh(&bond->lock); + netif_carrier_off(bond_dev); + if (bond->slave_cnt == 0) { goto out; } @@ -2187,15 +2239,9 @@ void bond_mii_monitor(struct net_device *bond_dev) bond_select_active_slave(bond); - if (oldcurrent && !bond->curr_active_slave) { - printk(KERN_INFO DRV_NAME - ": %s: now running without any active " - "interface !\n", - bond_dev->name); - } - write_unlock(&bond->curr_slave_lock); - } + } else + bond_set_carrier(bond); re_arm: if (bond->params.miimon) { @@ -2499,13 +2545,6 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev) bond_select_active_slave(bond); - if (oldcurrent && !bond->curr_active_slave) { - printk(KERN_INFO DRV_NAME - ": %s: now running without any active " - "interface !\n", - bond_dev->name); - } - write_unlock(&bond->curr_slave_lock); } @@ -2579,12 +2618,15 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev) bond->current_arp_slave = NULL; } + bond_set_carrier(bond); + if (slave == bond->curr_active_slave) { printk(KERN_INFO DRV_NAME ": %s: %s is up and now the " "active interface\n", bond_dev->name, slave->dev->name); + netif_carrier_on(bond->dev); } else { printk(KERN_INFO DRV_NAME ": %s: backup interface %s is " @@ -2844,7 +2886,8 @@ static void bond_info_show_master(struct seq_file *seq) (curr) ? curr->dev->name : "None"); } - seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down"); + seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ? + "up" : "down"); seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon); seq_printf(seq, "Up Delay (ms): %d\n", bond->params.updelay * bond->params.miimon); @@ -4531,6 +4574,8 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond if (newbond) *newbond = bond_dev->priv; + netif_carrier_off(bond_dev); + rtnl_unlock(); /* allows sysfs registration of net device */ res = bond_create_sysfs_entry(bond_dev->priv); goto done; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index ce9dc9b4e2..0bdfe2c714 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -22,8 +22,8 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.0.2" -#define DRV_RELDATE "February 21, 2006" +#define DRV_VERSION "3.0.3" +#define DRV_RELDATE "March 23, 2006" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" -- cgit v1.2.2 From 8dfc914a3f2ae4e303e2bff89f28fc14cee8a9a6 Mon Sep 17 00:00:00 2001 From: Jens Osterkamp Date: Mon, 27 Mar 2006 17:16:36 +0200 Subject: [PATCH] spidernet : enable tx checksum offloading by default This enables TX checksum offloading for the spidernet driver by default. Signed-off-by: Jens Osterkamp Signed-off-by: Jeff Garzik --- drivers/net/spider_net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 0000de01ec..43f5e86fc5 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -2086,7 +2086,7 @@ spider_net_setup_netdev(struct spider_net_card *card) spider_net_setup_netdev_ops(netdev); - netdev->features = 0; + netdev->features = NETIF_F_HW_CSUM; /* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | * NETIF_F_HW_VLAN_FILTER */ -- cgit v1.2.2 From a8b4cf42cf57e44e3c4a585e0f0a71e3a7efbf29 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 28 Mar 2006 14:08:55 -0800 Subject: [PATCH] natsemi: Support oversized EEPROMs The natsemi chip can have a larger EEPROM attached than it itself uses for configuration. This patch adds support for user space access to such an EEPROM. Signed-off-by: Mark Brown Cc: Tim Hockin Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/natsemi.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 8d4999837b..7826afbb9d 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c @@ -226,7 +226,7 @@ static int full_duplex[MAX_UNITS]; NATSEMI_PG1_NREGS) #define NATSEMI_REGS_VER 1 /* v1 added RFDR registers */ #define NATSEMI_REGS_SIZE (NATSEMI_NREGS * sizeof(u32)) -#define NATSEMI_EEPROM_SIZE 24 /* 12 16-bit values */ +#define NATSEMI_DEF_EEPROM_SIZE 24 /* 12 16-bit values */ /* Buffer sizes: * The nic writes 32-bit values, even if the upper bytes of @@ -714,6 +714,8 @@ struct netdev_private { unsigned int iosize; spinlock_t lock; u32 msg_enable; + /* EEPROM data */ + int eeprom_size; }; static void move_int_phy(struct net_device *dev, int addr); @@ -890,6 +892,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, np->msg_enable = (debug >= 0) ? (1<hands_off = 0; np->intr_status = 0; + np->eeprom_size = NATSEMI_DEF_EEPROM_SIZE; /* Initial port: * - If the nic was configured to use an external phy and if find_mii @@ -2582,7 +2585,8 @@ static int get_regs_len(struct net_device *dev) static int get_eeprom_len(struct net_device *dev) { - return NATSEMI_EEPROM_SIZE; + struct netdev_private *np = netdev_priv(dev); + return np->eeprom_size; } static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) @@ -2669,15 +2673,20 @@ static u32 get_link(struct net_device *dev) static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data) { struct netdev_private *np = netdev_priv(dev); - u8 eebuf[NATSEMI_EEPROM_SIZE]; + u8 *eebuf; int res; + eebuf = kmalloc(np->eeprom_size, GFP_KERNEL); + if (!eebuf) + return -ENOMEM; + eeprom->magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16); spin_lock_irq(&np->lock); res = netdev_get_eeprom(dev, eebuf); spin_unlock_irq(&np->lock); if (!res) memcpy(data, eebuf+eeprom->offset, eeprom->len); + kfree(eebuf); return res; } @@ -3033,9 +3042,10 @@ static int netdev_get_eeprom(struct net_device *dev, u8 *buf) int i; u16 *ebuf = (u16 *)buf; void __iomem * ioaddr = ns_ioaddr(dev); + struct netdev_private *np = netdev_priv(dev); /* eeprom_read reads 16 bits, and indexes by 16 bits */ - for (i = 0; i < NATSEMI_EEPROM_SIZE/2; i++) { + for (i = 0; i < np->eeprom_size/2; i++) { ebuf[i] = eeprom_read(ioaddr, i); /* The EEPROM itself stores data bit-swapped, but eeprom_read * reads it back "sanely". So we swap it back here in order to -- cgit v1.2.2 From 8a91ed60f58451342a25f3ab4484c7257430aa8e Mon Sep 17 00:00:00 2001 From: Arthur Othieno Date: Tue, 28 Mar 2006 14:09:01 -0800 Subject: [PATCH] net: remove CONFIG_NET_CBUS conditional for NS8390 Don't bother testing for CONFIG_NET_CBUS ("NEC PC-9800 C-bus cards"); it went out with the rest of PC98 subarch. Signed-off-by: Arthur Othieno Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/8390.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/8390.h b/drivers/net/8390.h index 599b68d8c4..51e39dcd06 100644 --- a/drivers/net/8390.h +++ b/drivers/net/8390.h @@ -134,7 +134,7 @@ struct ei_device { #define inb_p(_p) inb(_p) #define outb_p(_v,_p) outb(_v,_p) -#elif defined(CONFIG_NET_CBUS) || defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE) +#elif defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE) #define EI_SHIFT(x) (ei_local->reg_offset[x]) #else #define EI_SHIFT(x) (x) -- cgit v1.2.2 From bc0e1fc970279c539db1e94dd473acbb193ee473 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Tue, 28 Mar 2006 16:36:23 -0600 Subject: [PATCH] Janitor: drivers/net/pcnet32: fix incorrect comments The comments concerning how the pcnet32 ethernet device driver selects the MAC addr to use are incorrect. A recent patch (in the last 3 months) changed how the code worked, but did not change the comments. Side comment: the new behaviour is good; I've got a pcnet32 card which powers up with garbage in the CSR's, and a good MAC addr in the PROM. Signed-off-by: Linas Vepstas Signed-off-by: Jeff Garzik --- drivers/net/pcnet32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 9595f74da9..07c31f19c6 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -1167,8 +1167,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) * station address PROM at the base address and programmed into the * "Physical Address Registers" CSR12-14. * As a precautionary measure, we read the PROM values and complain if - * they disagree with the CSRs. Either way, we use the CSR values, and - * double check that they are valid. + * they disagree with the CSRs. If they miscompare, and the PROM addr + * is valid, then the PROM addr is used. */ for (i = 0; i < 3; i++) { unsigned int val; -- cgit v1.2.2 From 391fc09a143aac08d1a3dc37b60238612b504ad3 Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Tue, 28 Mar 2006 14:57:38 -0800 Subject: [PATCH] b44: ensure valid mac addr Added code to check for invalid MAC address from eeprom or user input. Signed-off-by: Gary Zambrano Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 2eab2a88c7..15032f2c78 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -1339,6 +1339,9 @@ static int b44_set_mac_addr(struct net_device *dev, void *p) if (netif_running(dev)) return -EBUSY; + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); spin_lock_irq(&bp->lock); @@ -1876,6 +1879,12 @@ static int __devinit b44_get_invariants(struct b44 *bp) bp->dev->dev_addr[3] = eeprom[80]; bp->dev->dev_addr[4] = eeprom[83]; bp->dev->dev_addr[5] = eeprom[82]; + + if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){ + printk(KERN_ERR PFX "Invalid MAC address found in EEPROM\n"); + return -EINVAL; + } + memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len); bp->phy_addr = eeprom[90] & 0x1f; -- cgit v1.2.2 From 5d4fe2c1ce83c3e967ccc1ba3d580c1a5603a866 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Wed, 29 Mar 2006 15:12:44 +0200 Subject: [PATCH] ixp2000: fix gcc4 breakage gcc4 doesn't like us declaring a static function inside another function. We can do away with this construct altogether and use BUILD_BUG_ON() instead (idea from Andi Kleen.) Signed-off-by: Lennert Buytenhek Signed-off-by: Jeff Garzik --- drivers/net/ixp2000/ixpdev.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c index 77f104a005..fbc2d21020 100644 --- a/drivers/net/ixp2000/ixpdev.c +++ b/drivers/net/ixp2000/ixpdev.c @@ -299,10 +299,7 @@ int ixpdev_init(int __nds_count, struct net_device **__nds, int i; int err; - if (RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192) { - static void __too_many_rx_or_tx_buffers(void); - __too_many_rx_or_tx_buffers(); - } + BUILD_BUG_ON(RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192); printk(KERN_INFO "IXP2000 MSF ethernet driver %s\n", DRV_MODULE_VERSION); -- cgit v1.2.2 From 4e5ec5dba22ea509b1a004f9815751f0ffc815e5 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Mar 2006 18:42:40 +0100 Subject: [PATCH] libata: BMDMA handling updates This is the minimal patch set to enable the current code to be used with a controller following SFF (ie any PATA and early SATA controllers) safely without crashes if there is no BMDMA area or if BMDMA is not assigned by the BIOS for some reason. Simplex status is recorded but not acted upon in this change, this isn't a problem with the current drivers as none of them are for simplex hardware. A following diff will deal with that. The flags in the probe structure remain ->host_set_flags although Jeff asked me to rename them, simply because the rename would break the usual Linux rules that old code should break when there are changes. not compile and run and then blow up/eat your computer/etc. Renaming this later is a trivial exercise once a better name is chosen. Signed-off-by: Jeff Garzik --- drivers/scsi/libata-bmdma.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c index 95d81d86d8..835dff0baf 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/scsi/libata-bmdma.c @@ -703,6 +703,7 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); int p = 0; + unsigned long bmdma; if (!probe_ent) return NULL; @@ -716,7 +717,12 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int probe_ent->port[p].altstatus_addr = probe_ent->port[p].ctl_addr = pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; - probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4); + bmdma = pci_resource_start(pdev, 4); + if (bmdma) { + if (inb(bmdma + 2) & 0x80) + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + probe_ent->port[p].bmdma_addr = bmdma; + } ata_std_ports(&probe_ent->port[p]); p++; } @@ -726,7 +732,13 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int probe_ent->port[p].altstatus_addr = probe_ent->port[p].ctl_addr = pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; - probe_ent->port[p].bmdma_addr = pci_resource_start(pdev, 4) + 8; + bmdma = pci_resource_start(pdev, 4); + if (bmdma) { + bmdma += 8; + if(inb(bmdma + 2) & 0x80) + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + probe_ent->port[p].bmdma_addr = bmdma; + } ata_std_ports(&probe_ent->port[p]); p++; } @@ -740,6 +752,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info *port, int port_num) { struct ata_probe_ent *probe_ent; + unsigned long bmdma; probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port); if (!probe_ent) @@ -766,8 +779,13 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, break; } - probe_ent->port[0].bmdma_addr = - pci_resource_start(pdev, 4) + 8 * port_num; + bmdma = pci_resource_start(pdev, 4); + if (bmdma != 0) { + bmdma += 8 * port_num; + probe_ent->port[0].bmdma_addr = bmdma; + if (inb(bmdma + 2) & 0x80) + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + } ata_std_ports(&probe_ent->port[0]); return probe_ent; -- cgit v1.2.2 From e35a9e01f2a504871e70576a9e11dbe4d8dee456 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Mar 2006 18:46:37 +0100 Subject: [PATCH] libata: Add ->set_mode hook for odd drivers Some hardware doesn't want the usual mode setup logic running. This allows the hardware driver to replace it for special cases in the least invasive way possible. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 86310562da..10933cb722 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1409,7 +1409,11 @@ static int ata_bus_probe(struct ata_port *ap) if (!found) goto err_out_disable; - ata_set_mode(ap); + if (ap->ops->set_mode) + ap->ops->set_mode(ap); + else + ata_set_mode(ap); + if (ap->flags & ATA_FLAG_PORT_DISABLED) goto err_out_disable; -- cgit v1.2.2 From 692785e798f341c057ff976c35a3d86ad5af8ac6 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Mar 2006 18:49:19 +0100 Subject: [PATCH] libata - ATA is both ATA and CFA I think this is still needed with the new probe code (which btw seems to be missing docs in upstream ?). Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 10933cb722..41659448a2 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1140,7 +1140,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, swap_buf_le16(id, ATA_ID_WORDS); /* sanity check */ - if ((class == ATA_DEV_ATA) != ata_id_is_ata(id)) { + if ((class == ATA_DEV_ATA) != (ata_id_is_ata(id) | ata_id_is_cfa(id))) { rc = -EINVAL; reason = "device reports illegal type"; goto err_out; -- cgit v1.2.2 From 5444a6f405618706eddbe1605ef8533b1b655764 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Mar 2006 18:58:20 +0100 Subject: [PATCH] libata: Simplex and other mode filtering logic Add a field to the host_set called 'flags' (was host_set_flags changed to suit Jeff) Add a simplex_claimed field so we can remember who owns the DMA channel Add a ->mode_filter() hook to allow drivers to filter modes Add docs for mode_filter and set_mode Filter according to simplex state Filter cable in core This provides the needed framework to support all the mode rules found in the PATA world. The simplex filter deals with 'to spec' simplex DMA systems found in older chips. The cable filter avoids duplicating the same rules in each chip driver with PATA. Finally the mode filter is neccessary because drive/chip combinations have errata that forbid certain modes with some drives or types of ATA object. Drive speed setup remains per channel for now and the filters now use the framework Tejun put into place which cleans them up a lot from the older libata-pata patches. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 41659448a2..b1ddf40533 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1818,7 +1818,7 @@ static void ata_host_set_dma(struct ata_port *ap) */ static void ata_set_mode(struct ata_port *ap) { - int i, rc; + int i, rc, used_dma = 0; /* step 1: calculate xfer_mask */ for (i = 0; i < ATA_MAX_DEVICES; i++) { @@ -1836,6 +1836,9 @@ static void ata_set_mode(struct ata_port *ap) dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); dev->pio_mode = ata_xfer_mask2mode(pio_mask); dev->dma_mode = ata_xfer_mask2mode(dma_mask); + + if (dev->dma_mode) + used_dma = 1; } /* step 2: always set host PIO timings */ @@ -1857,6 +1860,17 @@ static void ata_set_mode(struct ata_port *ap) goto err_out; } + /* + * Record simplex status. If we selected DMA then the other + * host channels are not permitted to do so. + */ + + if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX)) + ap->host_set->simplex_claimed = 1; + + /* + * Chip specific finalisation + */ if (ap->ops->post_set_mode) ap->ops->post_set_mode(ap); @@ -2646,13 +2660,14 @@ static int ata_dma_blacklisted(const struct ata_device *dev) */ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) { + struct ata_host_set *hs = ap->host_set; unsigned long xfer_mask; int i; xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, ap->udma_mask); - /* use port-wide xfermask for now */ + /* FIXME: Use port-wide xfermask for now */ for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *d = &ap->device[i]; if (!ata_dev_present(d)) @@ -2662,12 +2677,23 @@ static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev) xfer_mask &= ata_id_xfermask(d->id); if (ata_dma_blacklisted(d)) xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + /* Apply cable rule here. Don't apply it early because when + we handle hot plug the cable type can itself change */ + if (ap->cbl == ATA_CBL_PATA40) + xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); } if (ata_dma_blacklisted(dev)) printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " "disabling DMA\n", ap->id, dev->devno); + if (hs->flags & ATA_HOST_SIMPLEX) { + if (hs->simplex_claimed) + xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + } + if (ap->ops->mode_filter) + xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask); + ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask, &dev->udma_mask); } @@ -4531,6 +4557,7 @@ int ata_device_add(const struct ata_probe_ent *ent) host_set->mmio_base = ent->mmio_base; host_set->private_data = ent->private_data; host_set->ops = ent->port_ops; + host_set->flags = ent->host_set_flags; /* register each port bound to this device */ for (i = 0; i < ent->n_ports; i++) { -- cgit v1.2.2 From 17efc5f7237995295cbe008828788d187fea3c88 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Mar 2006 19:01:32 +0100 Subject: [PATCH] libata: Fix interesting use of "extern" and also some bracketing Signed-off-by: Alan Cox Last of the set, just clean up some oddments. Assuming the whole set is now ok then the remaining differences are the setup of PIO_0 at reset and the ->data_xfer method. Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index b1ddf40533..ac19505f7f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -2160,9 +2160,9 @@ static int sata_phy_resume(struct ata_port *ap) * so makes reset sequence different from the original * ->phy_reset implementation and Jeff nervous. :-P */ -extern void ata_std_probeinit(struct ata_port *ap) +void ata_std_probeinit(struct ata_port *ap) { - if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) { + if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { sata_phy_resume(ap); if (sata_dev_present(ap)) ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); -- cgit v1.2.2 From 00b6f5e9e04b2186a71a5892640bb2d8e09a030e Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Mon, 27 Mar 2006 16:39:18 +0800 Subject: [PATCH] libata: ata_dev_init_params() fixes ata_dev_init_params() fixes: - Get the "heads" and "sectors" parameters from caller instead of implicitly from dev->id[]. - Return AC_ERR_INVALID instead of 0 if an invalid parameter is found Signed-off-by: Albert Lee Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ac19505f7f..21b0ed583b 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -62,7 +62,9 @@ #include "libata.h" static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev); + struct ata_device *dev, + u16 heads, + u16 sectors); static void ata_set_mode(struct ata_port *ap); static unsigned int ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); @@ -1156,7 +1158,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, * Some drives were very specific about that exact sequence. */ if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) { - err_mask = ata_dev_init_params(ap, dev); + err_mask = ata_dev_init_params(ap, dev, id[3], id[6]); if (err_mask) { rc = -EIO; reason = "INIT_DEV_PARAMS failed"; @@ -2748,16 +2750,16 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, */ static unsigned int ata_dev_init_params(struct ata_port *ap, - struct ata_device *dev) + struct ata_device *dev, + u16 heads, + u16 sectors) { struct ata_taskfile tf; unsigned int err_mask; - u16 sectors = dev->id[6]; - u16 heads = dev->id[3]; /* Number of sectors per track 1-255. Number of heads 1-16 */ if (sectors < 1 || sectors > 255 || heads < 1 || heads > 16) - return 0; + return AC_ERR_INVALID; /* set up init dev params taskfile */ DPRINTK("init dev params \n"); -- cgit v1.2.2 From 63af2a5c5990d95f1e7d8795f1425fb976ea2b4b Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 29 Mar 2006 09:50:31 -0500 Subject: [PATCH] sata_mv: three bug fixes (1) A DMA transfer size of 0x10000 was not being written as 0x0000 in the PRDs. Fixed. (1) The DEV_IRQ interrupt cause bit happens spuriously during EDMA operation, and was not being ignored by the driver. This led to various "drive busy" errors being reported, with associated unpredictable behaviour. Fixed. (2) If a SATA or PCI interrupt was received with no outstanding command, the interrupt handler still attempted to invoke ata_qc_complete(), triggering assert()/BUG_ON() behaviour elsewhere in libata. Fixed. The driver still has issues with confusion after error-recovery, but should now be reliable in the absence of drive errors. I will be looking more into the error-handling bugs next. Signed-Off-By: Mark Lord Signed-off-by: Jeff Garzik --- drivers/scsi/sata_mv.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 2770005324..33e3873543 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -915,7 +915,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); - pp->sg_tbl[i].flags_size = cpu_to_le32(len); + pp->sg_tbl[i].flags_size = cpu_to_le32(len & 0xffff); sg_len -= len; addr += len; @@ -1187,7 +1187,6 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, { void __iomem *mmio = host_set->mmio_base; void __iomem *hc_mmio = mv_hc_base(mmio, hc); - struct ata_port *ap; struct ata_queued_cmd *qc; u32 hc_irq_cause; int shift, port, port0, hard_port, handled; @@ -1210,25 +1209,31 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, hc,relevant,hc_irq_cause); for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { - ap = host_set->ports[port]; + struct ata_port *ap = host_set->ports[port]; + struct mv_port_priv *pp = ap->private_data; hard_port = port & MV_PORT_MASK; /* range 0-3 */ handled = 0; /* ensure ata_status is set if handled++ */ - if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { - /* new CRPB on the queue; just one at a time until NCQ - */ - ata_status = mv_get_crpb_status(ap); - handled++; - } else if ((DEV_IRQ << hard_port) & hc_irq_cause) { - /* received ATA IRQ; read the status reg to clear INTRQ - */ - ata_status = readb((void __iomem *) + /* Note that DEV_IRQ might happen spuriously during EDMA, + * and should be ignored in such cases. We could mask it, + * but it's pretty rare and may not be worth the overhead. + */ + if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { + /* EDMA: check for response queue interrupt */ + if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) { + ata_status = mv_get_crpb_status(ap); + handled = 1; + } + } else { + /* PIO: check for device (drive) interrupt */ + if ((DEV_IRQ << hard_port) & hc_irq_cause) { + ata_status = readb((void __iomem *) ap->ioaddr.status_addr); - handled++; + handled = 1; + } } - if (ap && - (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) + if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) continue; err_mask = ac_err_mask(ata_status); @@ -1240,12 +1245,12 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, if ((PORT0_ERR << shift) & relevant) { mv_err_intr(ap); err_mask |= AC_ERR_OTHER; - handled++; + handled = 1; } - if (handled && ap) { + if (handled) { qc = ata_qc_from_tag(ap, ap->active_tag); - if (NULL != qc) { + if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) { VPRINTK("port %u IRQ found for qc, " "ata_status 0x%x\n", port,ata_status); /* mark qc status appropriately */ -- cgit v1.2.2 From fa9656bbd9af5b95adc43eaa0a143992346378cb Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 28 Mar 2006 16:39:07 -0800 Subject: IB/mad: include GID/class when matching receives Received responses are currently matched against sent requests based on TID only. According to the spec, responses should match based on the combination of TID, management class, and requester LID/GID. Without the additional qualification, an agent that is responding to two requests, both of which have the same TID, can match RMPP ACKs with the incorrect transaction. This problem can occur on the SM node when responding to SA queries. Signed-off-by: Jack Morgenstein Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/mad.c | 58 ++++++++++++++++++++++++++++++++++---- drivers/infiniband/core/mad_priv.h | 3 +- drivers/infiniband/core/mad_rmpp.c | 35 +++++++++-------------- 3 files changed, 67 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index f7854b65fd..d4d07012a5 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -1618,14 +1618,59 @@ static int is_data_mad(struct ib_mad_agent_private *mad_agent_priv, (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); } +static inline int rcv_has_same_class(struct ib_mad_send_wr_private *wr, + struct ib_mad_recv_wc *rwc) +{ + return ((struct ib_mad *)(wr->send_buf.mad))->mad_hdr.mgmt_class == + rwc->recv_buf.mad->mad_hdr.mgmt_class; +} + +static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr, + struct ib_mad_recv_wc *rwc ) +{ + struct ib_ah_attr attr; + u8 send_resp, rcv_resp; + + send_resp = ((struct ib_mad *)(wr->send_buf.mad))-> + mad_hdr.method & IB_MGMT_METHOD_RESP; + rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP; + + if (!send_resp && rcv_resp) + /* is request/response. GID/LIDs are both local (same). */ + return 1; + + if (send_resp == rcv_resp) + /* both requests, or both responses. GIDs different */ + return 0; + + if (ib_query_ah(wr->send_buf.ah, &attr)) + /* Assume not equal, to avoid false positives. */ + return 0; + + if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH)) + return attr.dlid == rwc->wc->slid; + else if ((attr.ah_flags & IB_AH_GRH) && + (rwc->wc->wc_flags & IB_WC_GRH)) + return memcmp(attr.grh.dgid.raw, + rwc->recv_buf.grh->sgid.raw, 16) == 0; + else + /* one has GID, other does not. Assume different */ + return 0; +} struct ib_mad_send_wr_private* -ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid) +ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc) { struct ib_mad_send_wr_private *mad_send_wr; + struct ib_mad *mad; + + mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad; list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list, agent_list) { - if (mad_send_wr->tid == tid) + if ((mad_send_wr->tid == mad->mad_hdr.tid) && + rcv_has_same_class(mad_send_wr, mad_recv_wc) && + rcv_has_same_gid(mad_send_wr, mad_recv_wc)) return mad_send_wr; } @@ -1636,7 +1681,10 @@ ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid) list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list, agent_list) { if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) && - mad_send_wr->tid == tid && mad_send_wr->timeout) { + mad_send_wr->tid == mad->mad_hdr.tid && + mad_send_wr->timeout && + rcv_has_same_class(mad_send_wr, mad_recv_wc) && + rcv_has_same_gid(mad_send_wr, mad_recv_wc)) { /* Verify request has not been canceled */ return (mad_send_wr->status == IB_WC_SUCCESS) ? mad_send_wr : NULL; @@ -1661,7 +1709,6 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wc mad_send_wc; unsigned long flags; - __be64 tid; INIT_LIST_HEAD(&mad_recv_wc->rmpp_list); list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); @@ -1677,9 +1724,8 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv, /* Complete corresponding request */ if (response_mad(mad_recv_wc->recv_buf.mad)) { - tid = mad_recv_wc->recv_buf.mad->mad_hdr.tid; spin_lock_irqsave(&mad_agent_priv->lock, flags); - mad_send_wr = ib_find_send_mad(mad_agent_priv, tid); + mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); if (!mad_send_wr) { spin_unlock_irqrestore(&mad_agent_priv->lock, flags); ib_free_recv_mad(mad_recv_wc); diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index a7125d4b5c..6c9c133d71 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h @@ -216,7 +216,8 @@ extern kmem_cache_t *ib_mad_cache; int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr); struct ib_mad_send_wr_private * -ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, __be64 tid); +ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, + struct ib_mad_recv_wc *mad_recv_wc); void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr, struct ib_mad_send_wc *mad_send_wc); diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index bacfdd5bdd..a6405079c2 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -562,15 +562,15 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) return ib_send_mad(mad_send_wr); } -static void abort_send(struct ib_mad_agent_private *agent, __be64 tid, - u8 rmpp_status) +static void abort_send(struct ib_mad_agent_private *agent, + struct ib_mad_recv_wc *mad_recv_wc, u8 rmpp_status) { struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wc wc; unsigned long flags; spin_lock_irqsave(&agent->lock, flags); - mad_send_wr = ib_find_send_mad(agent, tid); + mad_send_wr = ib_find_send_mad(agent, mad_recv_wc); if (!mad_send_wr) goto out; /* Unmatched send */ @@ -612,8 +612,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; if (rmpp_mad->rmpp_hdr.rmpp_status) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BAD_STATUS); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); return; } @@ -621,14 +620,13 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, seg_num = be32_to_cpu(rmpp_mad->rmpp_hdr.seg_num); newwin = be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); if (newwin < seg_num) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_W2S); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_W2S); return; } spin_lock_irqsave(&agent->lock, flags); - mad_send_wr = ib_find_send_mad(agent, rmpp_mad->mad_hdr.tid); + mad_send_wr = ib_find_send_mad(agent, mad_recv_wc); if (!mad_send_wr) goto out; /* Unmatched ACK */ @@ -639,8 +637,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, if (seg_num > mad_send_wr->send_buf.seg_count || seg_num > mad_send_wr->newwin) { spin_unlock_irqrestore(&agent->lock, flags); - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_S2B); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_S2B); return; } @@ -728,12 +725,10 @@ static void process_rmpp_stop(struct ib_mad_agent_private *agent, rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad; if (rmpp_mad->rmpp_hdr.rmpp_status != IB_MGMT_RMPP_STATUS_RESX) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BAD_STATUS); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); } else - abort_send(agent, rmpp_mad->mad_hdr.tid, - rmpp_mad->rmpp_hdr.rmpp_status); + abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status); } static void process_rmpp_abort(struct ib_mad_agent_private *agent, @@ -745,12 +740,10 @@ static void process_rmpp_abort(struct ib_mad_agent_private *agent, if (rmpp_mad->rmpp_hdr.rmpp_status < IB_MGMT_RMPP_STATUS_ABORT_MIN || rmpp_mad->rmpp_hdr.rmpp_status > IB_MGMT_RMPP_STATUS_ABORT_MAX) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BAD_STATUS); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BAD_STATUS); } else - abort_send(agent, rmpp_mad->mad_hdr.tid, - rmpp_mad->rmpp_hdr.rmpp_status); + abort_send(agent, mad_recv_wc, rmpp_mad->rmpp_hdr.rmpp_status); } struct ib_mad_recv_wc * @@ -764,8 +757,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent, return mad_recv_wc; if (rmpp_mad->rmpp_hdr.rmpp_version != IB_MGMT_RMPP_VERSION) { - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_UNV); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_UNV); goto out; } @@ -783,8 +775,7 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent, process_rmpp_abort(agent, mad_recv_wc); break; default: - abort_send(agent, rmpp_mad->mad_hdr.tid, - IB_MGMT_RMPP_STATUS_BADT); + abort_send(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); nack_recv(agent, mad_recv_wc, IB_MGMT_RMPP_STATUS_BADT); break; } -- cgit v1.2.2 From 618a3c03fcfdf1ac4543247c8ddfb0c9d775ff33 Mon Sep 17 00:00:00 2001 From: Hal Rosenstock Date: Tue, 28 Mar 2006 16:40:04 -0800 Subject: IB/mad: RMPP support for additional classes Add RMPP support for additional management classes that support it. Also, validate RMPP is consistent with management class specified. Signed-off-by: Hal Rosenstock Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/mad.c | 54 ++++++++++++++++++++++++++++++++++---- drivers/infiniband/core/mad_rmpp.c | 19 +++----------- drivers/infiniband/core/user_mad.c | 30 +++++---------------- 3 files changed, 59 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index d4d07012a5..ba54c856b0 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -227,6 +227,14 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, if (!is_vendor_oui(mad_reg_req->oui)) goto error1; } + /* Make sure class supplied is consistent with RMPP */ + if (ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) { + if (!rmpp_version) + goto error1; + } else { + if (rmpp_version) + goto error1; + } /* Make sure class supplied is consistent with QP type */ if (qp_type == IB_QPT_SMI) { if ((mad_reg_req->mgmt_class != @@ -890,6 +898,35 @@ struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, } EXPORT_SYMBOL(ib_create_send_mad); +int ib_get_mad_data_offset(u8 mgmt_class) +{ + if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) + return IB_MGMT_SA_HDR; + else if ((mgmt_class == IB_MGMT_CLASS_DEVICE_MGMT) || + (mgmt_class == IB_MGMT_CLASS_DEVICE_ADM) || + (mgmt_class == IB_MGMT_CLASS_BIS)) + return IB_MGMT_DEVICE_HDR; + else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && + (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) + return IB_MGMT_VENDOR_HDR; + else + return IB_MGMT_MAD_HDR; +} +EXPORT_SYMBOL(ib_get_mad_data_offset); + +int ib_is_mad_class_rmpp(u8 mgmt_class) +{ + if ((mgmt_class == IB_MGMT_CLASS_SUBN_ADM) || + (mgmt_class == IB_MGMT_CLASS_DEVICE_MGMT) || + (mgmt_class == IB_MGMT_CLASS_DEVICE_ADM) || + (mgmt_class == IB_MGMT_CLASS_BIS) || + ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && + (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))) + return 1; + return 0; +} +EXPORT_SYMBOL(ib_is_mad_class_rmpp); + void *ib_get_rmpp_segment(struct ib_mad_send_buf *send_buf, int seg_num) { struct ib_mad_send_wr_private *mad_send_wr; @@ -1022,6 +1059,13 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf, goto error; } + if (!ib_is_mad_class_rmpp(((struct ib_mad_hdr *) send_buf->mad)->mgmt_class)) { + if (mad_agent_priv->agent.rmpp_version) { + ret = -EINVAL; + goto error; + } + } + /* * Save pointer to next work request to post in case the * current one completes, and the user modifies the work @@ -2454,11 +2498,11 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, } } sg_list.addr = dma_map_single(qp_info->port_priv-> - device->dma_device, - &mad_priv->grh, - sizeof *mad_priv - - sizeof mad_priv->header, - DMA_FROM_DEVICE); + device->dma_device, + &mad_priv->grh, + sizeof *mad_priv - + sizeof mad_priv->header, + DMA_FROM_DEVICE); pci_unmap_addr_set(&mad_priv->header, mapping, sg_list.addr); recv_wr.wr_id = (unsigned long)&mad_priv->header.mad_list; mad_priv->header.mad_list.mad_queue = recv_queue; diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index a6405079c2..dfd4e588ce 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005 Intel Inc. All rights reserved. - * Copyright (c) 2005 Voltaire, Inc. All rights reserved. + * Copyright (c) 2005-2006 Voltaire, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -100,17 +100,6 @@ void ib_cancel_rmpp_recvs(struct ib_mad_agent_private *agent) } } -static int data_offset(u8 mgmt_class) -{ - if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) - return IB_MGMT_SA_HDR; - else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && - (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) - return IB_MGMT_VENDOR_HDR; - else - return IB_MGMT_RMPP_HDR; -} - static void format_ack(struct ib_mad_send_buf *msg, struct ib_rmpp_mad *data, struct mad_rmpp_recv *rmpp_recv) @@ -137,7 +126,7 @@ static void ack_recv(struct mad_rmpp_recv *rmpp_recv, struct ib_mad_send_buf *msg; int ret, hdr_len; - hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); + hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); msg = ib_create_send_mad(&rmpp_recv->agent->agent, recv_wc->wc->src_qp, recv_wc->wc->pkey_index, 1, hdr_len, 0, GFP_KERNEL); @@ -163,7 +152,7 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent, if (IS_ERR(ah)) return (void *) ah; - hdr_len = data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); + hdr_len = ib_get_mad_data_offset(recv_wc->recv_buf.mad->mad_hdr.mgmt_class); msg = ib_create_send_mad(agent, recv_wc->wc->src_qp, recv_wc->wc->pkey_index, 1, hdr_len, 0, GFP_KERNEL); @@ -408,7 +397,7 @@ static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv) rmpp_mad = (struct ib_rmpp_mad *)rmpp_recv->cur_seg_buf->mad; - hdr_size = data_offset(rmpp_mad->mad_hdr.mgmt_class); + hdr_size = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); data_size = sizeof(struct ib_rmpp_mad) - hdr_size; pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); if (pad > IB_MGMT_RMPP_DATA || pad < 0) diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index fb6cd42601..afe70a549c 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -177,17 +177,6 @@ static int queue_packet(struct ib_umad_file *file, return ret; } -static int data_offset(u8 mgmt_class) -{ - if (mgmt_class == IB_MGMT_CLASS_SUBN_ADM) - return IB_MGMT_SA_HDR; - else if ((mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && - (mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) - return IB_MGMT_VENDOR_HDR; - else - return IB_MGMT_RMPP_HDR; -} - static void send_handler(struct ib_mad_agent *agent, struct ib_mad_send_wc *send_wc) { @@ -283,7 +272,7 @@ static ssize_t copy_recv_mad(char __user *buf, struct ib_umad_packet *packet, */ return -ENOSPC; } - offset = data_offset(recv_buf->mad->mad_hdr.mgmt_class); + offset = ib_get_mad_data_offset(recv_buf->mad->mad_hdr.mgmt_class); max_seg_payload = sizeof (struct ib_mad) - offset; for (left = packet->length - seg_payload, buf += seg_payload; @@ -441,21 +430,14 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, } rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data; - if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { - hdr_len = IB_MGMT_SA_HDR; - copy_offset = IB_MGMT_RMPP_HDR; - rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & - IB_MGMT_RMPP_FLAG_ACTIVE; - } else if (rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START && - rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END) { - hdr_len = IB_MGMT_VENDOR_HDR; + hdr_len = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); + if (!ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)) { + copy_offset = IB_MGMT_MAD_HDR; + rmpp_active = 0; + } else { copy_offset = IB_MGMT_RMPP_HDR; rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE; - } else { - hdr_len = IB_MGMT_MAD_HDR; - copy_offset = IB_MGMT_MAD_HDR; - rmpp_active = 0; } data_len = count - sizeof (struct ib_user_mad) - hdr_len; -- cgit v1.2.2 From a81dd18eb974cc34634c53a6447b2799ec0c3158 Mon Sep 17 00:00:00 2001 From: Thibaut VARENE Date: Fri, 3 Feb 2006 18:06:30 -0700 Subject: [PARISC] Clarify pdc_stable license terms pdc_stable.c is explicitly licensed under GPL version 2. Signed-off-by: Thibaut VARENE Signed-off-by: Kyle McMartin --- drivers/parisc/pdc_stable.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index a28e17898f..4e53be9c03 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -4,9 +4,8 @@ * Copyright (C) 2005-2006 Thibaut VARENE * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of -- cgit v1.2.2 From 5076c15862644edb91d2e3436b2fa3e07b28385d Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Mon, 27 Mar 2006 12:52:15 -0700 Subject: [PARISC] I/O-Space must be ioremap_nocache()'d Addresses in F-space must be accessed uncached on most parisc machines. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- drivers/input/serio/gscps2.c | 4 ++-- drivers/parisc/ccio-dma.c | 2 +- drivers/parisc/dino.c | 5 +++-- drivers/parisc/eisa.c | 2 +- drivers/parisc/iosapic.c | 2 +- drivers/parisc/lba_pci.c | 8 ++++---- drivers/parisc/sba_iommu.c | 6 +++--- drivers/parisc/superio.c | 48 ++++++++++++++++++-------------------------- drivers/scsi/lasi700.c | 2 +- drivers/scsi/zalon.c | 2 +- drivers/serial/8250_gsc.c | 15 +++++++------- drivers/serial/mux.c | 4 ++-- 12 files changed, 47 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index a7b0de0f92..c0b1e4beca 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -1,7 +1,7 @@ /* * drivers/input/serio/gscps2.c * - * Copyright (c) 2004 Helge Deller + * Copyright (c) 2004-2006 Helge Deller * Copyright (c) 2002 Laurent Canet * Copyright (c) 2002 Thibaut Varene * @@ -354,7 +354,7 @@ static int __init gscps2_probe(struct parisc_device *dev) memset(serio, 0, sizeof(struct serio)); ps2port->port = serio; ps2port->padev = dev; - ps2port->addr = ioremap(hpa, GSC_STATUS + 4); + ps2port->addr = ioremap_nocache(hpa, GSC_STATUS + 4); spin_lock_init(&ps2port->lock); gscps2_reset(ps2port); diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 93f8a8fa88..a5d826237b 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -1560,7 +1560,7 @@ static int ccio_probe(struct parisc_device *dev) *ioc_p = ioc; ioc->hw_path = dev->hw_path; - ioc->ioc_regs = ioremap(dev->hpa.start, 4096); + ioc->ioc_regs = ioremap_nocache(dev->hpa.start, 4096); ccio_ioc_init(ioc); ccio_init_resources(ioc); hppa_dma_ops = &ccio_ops; diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 3d1a7f98c6..6e8ed0c81a 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -5,6 +5,7 @@ ** (c) Copyright 1999 SuSE GmbH ** (c) Copyright 1999,2000 Hewlett-Packard Company ** (c) Copyright 2000 Grant Grundler +** (c) Copyright 2006 Helge Deller ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -785,7 +786,7 @@ dino_bridge_init(struct dino_device *dino_dev, const char *name) if((io_addr & (1 << i)) == 0) continue; - start = (unsigned long)(signed int)(0xf0000000 | (i << 23)); + start = F_EXTEND(0xf0000000UL) | (i << 23); end = start + 8 * 1024 * 1024 - 1; DBG("DINO RANGE %d is at 0x%lx-0x%lx\n", count, @@ -996,7 +997,7 @@ static int __init dino_probe(struct parisc_device *dev) } dino_dev->hba.dev = dev; - dino_dev->hba.base_addr = ioremap(hpa, 4096); + dino_dev->hba.base_addr = ioremap_nocache(hpa, 4096); dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */ spin_lock_init(&dino_dev->dinosaur_pen); dino_dev->hba.iommu = ccio_get_iommu(dev); diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index 3d94d86c1c..9d3bd15bf5 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c @@ -366,7 +366,7 @@ static int __devinit eisa_probe(struct parisc_device *dev) eisa_dev.eeprom_addr = MIRAGE_EEPROM_BASE_ADDR; } } - eisa_eeprom_addr = ioremap(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH); + eisa_eeprom_addr = ioremap_nocache(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH); result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space); init_eisa_pic(); diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 8d7a36392e..7a458d5bc7 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -879,7 +879,7 @@ void *iosapic_register(unsigned long hpa) return NULL; } - isi->addr = ioremap(hpa, 4096); + isi->addr = ioremap_nocache(hpa, 4096); isi->isi_hpa = hpa; isi->isi_version = iosapic_rd_version(isi); isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index e8a2a4a852..3fe4a77fa1 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1213,7 +1213,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ** Postable I/O port space is per PCI host adapter. ** base of 64MB PIOP region */ - lba_dev->iop_base = ioremap(p->start, 64 * 1024 * 1024); + lba_dev->iop_base = ioremap_nocache(p->start, 64 * 1024 * 1024); sprintf(lba_dev->hba.io_name, "PCI%02lx Ports", lba_dev->hba.bus_num.start); @@ -1525,7 +1525,7 @@ lba_driver_probe(struct parisc_device *dev) u32 func_class; void *tmp_obj; char *version; - void __iomem *addr = ioremap(dev->hpa.start, 4096); + void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096); /* Read HW Rev First */ func_class = READ_REG32(addr + LBA_FCLASS); @@ -1619,7 +1619,7 @@ lba_driver_probe(struct parisc_device *dev) } else { if (!astro_iop_base) { /* Sprockets PDC uses NPIOP region */ - astro_iop_base = ioremap(LBA_PORT_BASE, 64 * 1024); + astro_iop_base = ioremap_nocache(LBA_PORT_BASE, 64 * 1024); pci_port = &lba_astro_port_ops; } @@ -1700,7 +1700,7 @@ void __init lba_init(void) */ void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask) { - void __iomem * base_addr = ioremap(lba->hpa.start, 4096); + void __iomem * base_addr = ioremap_nocache(lba->hpa.start, 4096); imask <<= 2; /* adjust for hints - 2 more bits */ diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 0821747e44..42b32ff2fc 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1642,9 +1642,9 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** **************************************************************************/ -static void __iomem *ioc_remap(struct sba_device *sba_dev, int offset) +static void __iomem *ioc_remap(struct sba_device *sba_dev, unsigned int offset) { - return ioremap(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE); + return ioremap_nocache(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE); } static void sba_hw_init(struct sba_device *sba_dev) @@ -2040,7 +2040,7 @@ sba_driver_callback(struct parisc_device *dev) u32 func_class; int i; char *version; - void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE); + void __iomem *sba_addr = ioremap_nocache(dev->hpa.start, SBA_FUNC_SIZE); struct proc_dir_entry *info_entry, *bitmap_entry, *root; sba_dump_ranges(sba_addr); diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index ad6d3b28a3..719b863bc2 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -12,6 +12,7 @@ * (C) Copyright 2001 John Marvin * (C) Copyright 2003 Grant Grundler * (C) Copyright 2005 Kyle McMartin + * (C) Copyright 2006 Helge Deller * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -388,43 +389,34 @@ int superio_fixup_irq(struct pci_dev *pcidev) return local_irq; } -static struct uart_port serial[] = { - { - .iotype = UPIO_PORT, - .line = 0, - .type = PORT_16550A, - .uartclk = 115200*16, - .fifosize = 16, - }, - { - .iotype = UPIO_PORT, - .line = 1, - .type = PORT_16550A, - .uartclk = 115200*16, - .fifosize = 16, - } -}; - static void __devinit superio_serial_init(void) { #ifdef CONFIG_SERIAL_8250 int retval; - - serial[0].iobase = sio_dev.sp1_base; - serial[0].irq = SP1_IRQ; - spin_lock_init(&serial[0].lock); - - retval = early_serial_setup(&serial[0]); + struct uart_port serial_port; + + memset(&serial_port, 0, sizeof(serial_port)); + serial_port.iotype = UPIO_PORT; + serial_port.type = PORT_16550A; + serial_port.uartclk = 115200*16; + serial_port.fifosize = 16; + spin_lock_init(&serial_port.lock); + + /* serial port #1 */ + serial_port.iobase = sio_dev.sp1_base; + serial_port.irq = SP1_IRQ; + serial_port.line = 0; + retval = early_serial_setup(&serial_port); if (retval < 0) { printk(KERN_WARNING PFX "Register Serial #0 failed.\n"); return; } - serial[1].iobase = sio_dev.sp2_base; - serial[1].irq = SP2_IRQ; - spin_lock_init(&serial[1].lock); - retval = early_serial_setup(&serial[1]); - + /* serial port #2 */ + serial_port.iobase = sio_dev.sp2_base; + serial_port.irq = SP2_IRQ; + serial_port.line = 1; + retval = early_serial_setup(&serial_port); if (retval < 0) printk(KERN_WARNING PFX "Register Serial #1 failed.\n"); #endif /* CONFIG_SERIAL_8250 */ diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 459a4daebe..eb7bd310cc 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -112,7 +112,7 @@ lasi700_probe(struct parisc_device *dev) hostdata->dev = &dev->dev; dma_set_mask(&dev->dev, DMA_32BIT_MASK); - hostdata->base = ioremap(base, 0x100); + hostdata->base = ioremap_nocache(base, 0x100); hostdata->differential = 0; if (dev->id.sversion == LASI_700_SVERSION) { diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index b131432c67..a6cfbb3b36 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -88,7 +88,7 @@ zalon_probe(struct parisc_device *dev) struct gsc_irq gsc_irq; u32 zalon_vers; int error = -ENODEV; - void __iomem *zalon = ioremap(dev->hpa.start, 4096); + void __iomem *zalon = ioremap_nocache(dev->hpa.start, 4096); void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET; static int unit = 0; struct Scsi_Host *host; diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c index 8b4947933d..913c71cc05 100644 --- a/drivers/serial/8250_gsc.c +++ b/drivers/serial/8250_gsc.c @@ -52,13 +52,14 @@ serial_init_chip(struct parisc_device *dev) address += 0x800; } - memset(&port, 0, sizeof(struct uart_port)); - port.mapbase = address; - port.irq = dev->irq; - port.iotype = UPIO_MEM; - port.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; - port.uartclk = LASI_BASE_BAUD * 16; - port.dev = &dev->dev; + memset(&port, 0, sizeof(port)); + port.iotype = UPIO_MEM; + port.uartclk = LASI_BASE_BAUD * 16; + port.mapbase = address; + port.membase = ioremap_nocache(address, 16); + port.irq = dev->irq; + port.flags = UPF_BOOT_AUTOCONF; + port.dev = &dev->dev; err = serial8250_register_port(&port); if (err < 0) { diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 868eaf4a1a..64c0e89124 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -51,7 +51,7 @@ #define MUX_BREAK(status) ((status & 0xF000) == 0x2000) #define MUX_NR 256 -static unsigned int port_cnt = 0; +static unsigned int port_cnt __read_mostly; static struct uart_port mux_ports[MUX_NR]; static struct uart_driver mux_driver = { @@ -461,7 +461,7 @@ static int __init mux_probe(struct parisc_device *dev) port->iobase = 0; port->mapbase = dev->hpa.start + MUX_OFFSET + (i * MUX_LINE_OFFSET); - port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); + port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET); port->iotype = UPIO_MEM; port->type = PORT_MUX; port->irq = NO_IRQ; -- cgit v1.2.2 From 857600c77161fd36e30cd6bcca9a0a8676036323 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 22 Mar 2006 15:19:46 -0700 Subject: [PARISC] Fix stifb with IOREMAP and a 64-bit kernel Kill various warnings when built using ioremap. Remove stifb_{read,write} functions, which are now obsolete (and stack abusers!) Disable stifb mmap() functionality on a 64-bit kernel, it will crash the machine. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- drivers/video/console/sticore.c | 18 +------- drivers/video/sticore.h | 37 +++++------------ drivers/video/stifb.c | 91 +++-------------------------------------- 3 files changed, 19 insertions(+), 127 deletions(-) (limited to 'drivers') diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index 0339f5640a..d6041e781a 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -373,7 +373,7 @@ sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request) glob_cfg->save_addr)); /* dump extended cfg */ - cfg = PTR_STI(glob_cfg->ext_ptr); + cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr); DPRINTK(( KERN_INFO "monitor %d\n" "in friendly mode: %d\n" @@ -453,25 +453,11 @@ sti_init_glob_cfg(struct sti_struct *sti, sti->regions_phys[i] = REGION_OFFSET_TO_PHYS(sti->regions[i], newhpa); - /* remap virtually */ - /* FIXME: add BTLB support if btlb==1 */ len = sti->regions[i].region_desc.length * 4096; - -/* XXX: Enabling IOREMAP debugging causes a crash, so we must be passing - * a virtual address to something expecting a physical address that doesn't - * go through a readX macro */ -#if 0 - if (len) - glob_cfg->region_ptrs[i] = (unsigned long) ( - sti->regions[i].region_desc.cache ? - ioremap(sti->regions_phys[i], len) : - ioremap_nocache(sti->regions_phys[i], len) ); -#else if (len) glob_cfg->region_ptrs[i] = sti->regions_phys[i]; -#endif - DPRINTK(("region #%d: phys %08lx, virt %08x, len=%lukB, " + DPRINTK(("region #%d: phys %08lx, region_ptr %08x, len=%lukB, " "btlb=%d, sysonly=%d, cache=%d, last=%d\n", i, sti->regions_phys[i], glob_cfg->region_ptrs[i], len/1024, diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h index dc93336af5..1a9a60c74b 100644 --- a/drivers/video/sticore.h +++ b/drivers/video/sticore.h @@ -34,36 +34,20 @@ * for them to fix it and steal their solution. prumpf */ -#define STI_WAIT 1 - -#include /* for USE_HPPA_IOREMAP */ - -#if USE_HPPA_IOREMAP +#include -#define STI_PTR(p) (p) -#define PTR_STI(p) (p) -static inline int STI_CALL( unsigned long func, - void *flags, void *inptr, void *outptr, void *glob_cfg ) -{ - int (*f)(void *,void *,void *,void *); - f = (void*)func; - return f(flags, inptr, outptr, glob_cfg); -} - -#else /* !USE_HPPA_IOREMAP */ +#define STI_WAIT 1 #define STI_PTR(p) ( virt_to_phys(p) ) -#define PTR_STI(p) ( phys_to_virt((long)p) ) -#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \ - ({ \ - pdc_sti_call( func, (unsigned long)STI_PTR(flags), \ - (unsigned long)STI_PTR(inptr), \ - (unsigned long)STI_PTR(outptr), \ - (unsigned long)STI_PTR(glob_cfg)); \ +#define PTR_STI(p) ( phys_to_virt((unsigned long)p) ) +#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \ + ({ \ + pdc_sti_call( func, STI_PTR(flags), \ + STI_PTR(inptr), \ + STI_PTR(outptr), \ + STI_PTR(glob_cfg)); \ }) -#endif /* USE_HPPA_IOREMAP */ - #define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x) #define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y) @@ -352,8 +336,9 @@ struct sti_struct { struct sti_conf_outptr outptr; /* configuration */ struct sti_conf_outptr_ext outptr_ext; - /* PCI data structures (pg. 17ff from sti.pdf) */ struct pci_dev *pd; + + /* PCI data structures (pg. 17ff from sti.pdf) */ u8 rm_entry[16]; /* pci region mapper array == pci config space offset */ /* pointer to the fb_info where this STI device is used */ diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 56d71d6e9a..8d5f35676f 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -3,7 +3,7 @@ * Low level Frame buffer driver for HP workstations with * STI (standard text interface) video firmware. * - * Copyright (C) 2001-2005 Helge Deller + * Copyright (C) 2001-2006 Helge Deller * Portions Copyright (C) 2001 Thomas Bogendoerfer * * Based on: @@ -514,7 +514,7 @@ rattlerSetupPlanes(struct stifb_info *fb) SETUP_HW(fb); WRITE_BYTE(1, fb, REG_16b1); - fb_memset(fb->info.fix.smem_start, 0xff, + fb_memset((void*)fb->info.fix.smem_start, 0xff, fb->info.var.yres*fb->info.fix.line_length); CRX24_SET_OVLY_MASK(fb); @@ -908,83 +908,6 @@ SETUP_HCRX(struct stifb_info *fb) /* ------------------- driver specific functions --------------------------- */ -#define TMPBUFLEN 2048 - -static ssize_t -stifb_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - unsigned long p = *ppos; - struct inode *inode = file->f_dentry->d_inode; - int fbidx = iminor(inode); - struct fb_info *info = registered_fb[fbidx]; - char tmpbuf[TMPBUFLEN]; - - if (!info || ! info->screen_base) - return -ENODEV; - - if (p >= info->fix.smem_len) - return 0; - if (count >= info->fix.smem_len) - count = info->fix.smem_len; - if (count + p > info->fix.smem_len) - count = info->fix.smem_len - p; - if (count > sizeof(tmpbuf)) - count = sizeof(tmpbuf); - if (count) { - char *base_addr; - - base_addr = info->screen_base; - memcpy_fromio(&tmpbuf, base_addr+p, count); - count -= copy_to_user(buf, &tmpbuf, count); - if (!count) - return -EFAULT; - *ppos += count; - } - return count; -} - -static ssize_t -stifb_write(struct file *file, const char *buf, size_t count, loff_t *ppos) -{ - struct inode *inode = file->f_dentry->d_inode; - int fbidx = iminor(inode); - struct fb_info *info = registered_fb[fbidx]; - unsigned long p = *ppos; - size_t c; - int err; - char tmpbuf[TMPBUFLEN]; - - if (!info || !info->screen_base) - return -ENODEV; - - if (p > info->fix.smem_len) - return -ENOSPC; - if (count >= info->fix.smem_len) - count = info->fix.smem_len; - err = 0; - if (count + p > info->fix.smem_len) { - count = info->fix.smem_len - p; - err = -ENOSPC; - } - - p += (unsigned long)info->screen_base; - c = count; - while (c) { - int len = c > sizeof(tmpbuf) ? sizeof(tmpbuf) : c; - err = -EFAULT; - if (copy_from_user(&tmpbuf, buf, len)) - break; - memcpy_toio(p, &tmpbuf, len); - c -= len; - p += len; - buf += len; - *ppos += len; - } - if (count-c) - return (count-c); - return err; -} - static int stifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) @@ -1137,8 +1060,6 @@ stifb_init_display(struct stifb_info *fb) static struct fb_ops stifb_ops = { .owner = THIS_MODULE, - .fb_read = stifb_read, - .fb_write = stifb_write, .fb_setcolreg = stifb_setcolreg, .fb_blank = stifb_blank, .fb_fillrect = cfb_fillrect, @@ -1162,7 +1083,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref) char *dev_name; int bpp, xres, yres; - fb = kmalloc(sizeof(*fb), GFP_ATOMIC); + fb = kzalloc(sizeof(*fb), GFP_ATOMIC); if (!fb) { printk(KERN_ERR "stifb: Could not allocate stifb structure\n"); return -ENODEV; @@ -1171,7 +1092,6 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref) info = &fb->info; /* set struct to a known state */ - memset(fb, 0, sizeof(*fb)); fix = &info->fix; var = &info->var; @@ -1234,7 +1154,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref) case S9000_ID_TOMCAT: /* Dual CRX, behaves else like a CRX */ /* FIXME: TomCat supports two heads: * fb.iobase = REGION_BASE(fb_info,3); - * fb.screen_base = (void*) REGION_BASE(fb_info,2); + * fb.screen_base = ioremap_nocache(REGION_BASE(fb_info,2),xxx); * for now we only support the left one ! */ xres = fb->ngle_rom.x_size_visible; yres = fb->ngle_rom.y_size_visible; @@ -1327,7 +1247,8 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref) strcpy(fix->id, "stifb"); info->fbops = &stifb_ops; - info->screen_base = (void*) REGION_BASE(fb,1); + info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len); + info->screen_size = fix->smem_len; info->flags = FBINFO_DEFAULT; info->pseudo_palette = &fb->pseudo_palette; -- cgit v1.2.2 From 102c8c76f787add0790406d5c47e03cb6f8765c2 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 26 Mar 2006 07:41:55 -0700 Subject: [PARISC] Convert HIL drivers to use input_allocate_device Convert HIL drivers to use input_allocate_device() - avoids crashes. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- drivers/input/keyboard/hil_kbd.c | 57 +++++++++++++------------ drivers/input/keyboard/hilkbd.c | 54 +++++++++++++----------- drivers/input/mouse/hil_ptr.c | 91 +++++++++++++++++++++------------------- 3 files changed, 109 insertions(+), 93 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 0a90962c38..99f8c5b4cd 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -66,7 +66,7 @@ static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] = static char hil_language[][16] = { HIL_LOCALE_MAP }; struct hil_kbd { - struct input_dev dev; + struct input_dev *dev; struct serio *serio; /* Input buffer and index for packets from HIL bus. */ @@ -86,7 +86,7 @@ struct hil_kbd { /* Process a complete packet after transfer from the HIL */ static void hil_kbd_process_record(struct hil_kbd *kbd) { - struct input_dev *dev = &kbd->dev; + struct input_dev *dev = kbd->dev; hil_packet *data = kbd->data; hil_packet p; int idx, i, cnt; @@ -240,8 +240,9 @@ static void hil_kbd_disconnect(struct serio *serio) return; } - input_unregister_device(&kbd->dev); + input_unregister_device(kbd->dev); serio_close(serio); + input_free_device(kbd->dev); kfree(kbd); } @@ -251,16 +252,18 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) uint8_t did, *idd; int i; - kbd = kmalloc(sizeof(*kbd), GFP_KERNEL); + kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); if (!kbd) return -ENOMEM; - memset(kbd, 0, sizeof(struct hil_kbd)); + + kbd->dev = input_allocate_device(); + if (!kbd->dev) goto bail1; + kbd->dev->private = kbd; if (serio_open(serio, drv)) goto bail0; serio_set_drvdata(serio, kbd); kbd->serio = serio; - kbd->dev.private = kbd; init_MUTEX_LOCKED(&(kbd->sem)); @@ -302,38 +305,38 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); break; default: - goto bail1; + goto bail2; } if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n"); - goto bail1; + goto bail2; } - kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); - kbd->dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE; - kbd->dev.keycodesize = sizeof(hil_kbd_set1[0]); - kbd->dev.keycode = hil_kbd_set1; - kbd->dev.name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME; - kbd->dev.phys = "hpkbd/input0"; /* XXX */ + kbd->dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + kbd->dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); + kbd->dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; + kbd->dev->keycodesize = sizeof(hil_kbd_set1[0]); + kbd->dev->keycode = hil_kbd_set1; + kbd->dev->name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME; + kbd->dev->phys = "hpkbd/input0"; /* XXX */ - kbd->dev.id.bustype = BUS_HIL; - kbd->dev.id.vendor = PCI_VENDOR_ID_HP; - kbd->dev.id.product = 0x0001; /* TODO: get from kbd->rsc */ - kbd->dev.id.version = 0x0100; /* TODO: get from kbd->rsc */ - kbd->dev.dev = &serio->dev; + kbd->dev->id.bustype = BUS_HIL; + kbd->dev->id.vendor = PCI_VENDOR_ID_HP; + kbd->dev->id.product = 0x0001; /* TODO: get from kbd->rsc */ + kbd->dev->id.version = 0x0100; /* TODO: get from kbd->rsc */ + kbd->dev->dev = &serio->dev; for (i = 0; i < 128; i++) { - set_bit(hil_kbd_set1[i], kbd->dev.keybit); - set_bit(hil_kbd_set3[i], kbd->dev.keybit); + set_bit(hil_kbd_set1[i], kbd->dev->keybit); + set_bit(hil_kbd_set3[i], kbd->dev->keybit); } - clear_bit(0, kbd->dev.keybit); + clear_bit(0, kbd->dev->keybit); - input_register_device(&kbd->dev); + input_register_device(kbd->dev); printk(KERN_INFO "input: %s, ID: %d\n", - kbd->dev.name, did); + kbd->dev->name, did); serio->write(serio, 0); serio->write(serio, 0); @@ -343,8 +346,10 @@ static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) up(&(kbd->sem)); return 0; - bail1: + bail2: serio_close(serio); + bail1: + input_free_device(kbd->dev); bail0: kfree(kbd); serio_set_drvdata(serio, NULL); diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index e95bc052e3..452c5f3e61 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c @@ -3,7 +3,7 @@ * * Copyright (C) 1998 Philip Blundell * Copyright (C) 1999 Matthew Wilcox - * Copyright (C) 1999-2003 Helge Deller + * Copyright (C) 1999-2006 Helge Deller * * Very basic HP Human Interface Loop (HIL) driver. * This driver handles the keyboard on HP300 (m68k) and on some @@ -90,7 +90,7 @@ static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = /* HIL structure */ static struct { - struct input_dev dev; + struct input_dev *dev; unsigned int curdev; @@ -117,7 +117,7 @@ static void poll_finished(void) down = (hil_dev.data[1] & 1) == 0; scode = hil_dev.data[1] >> 1; key = hphilkeyb_keycode[scode]; - input_report_key(&hil_dev.dev, key, down); + input_report_key(hil_dev.dev, key, down); break; } hil_dev.curdev = 0; @@ -207,9 +207,14 @@ hil_keyb_init(void) unsigned int i, kbid; wait_queue_head_t hil_wait; - if (hil_dev.dev.id.bustype) { + if (hil_dev.dev) { return -ENODEV; /* already initialized */ } + + hil_dev.dev = input_allocate_device(); + if (!hil_dev.dev) + return -ENOMEM; + hil_dev.dev->private = &hil_dev; #if defined(CONFIG_HP300) if (!hwreg_present((void *)(HILBASE + HIL_DATA))) @@ -247,28 +252,26 @@ hil_keyb_init(void) c = 0; hil_do(HIL_WRITEKBDSADR, &c, 1); - init_input_dev(&hil_dev.dev); - for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) if (hphilkeyb_keycode[i] != KEY_RESERVED) - set_bit(hphilkeyb_keycode[i], hil_dev.dev.keybit); - - hil_dev.dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - hil_dev.dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); - hil_dev.dev.keycodemax = HIL_KEYCODES_SET1_TBLSIZE; - hil_dev.dev.keycodesize = sizeof(hphilkeyb_keycode[0]); - hil_dev.dev.keycode = hphilkeyb_keycode; - hil_dev.dev.name = "HIL keyboard"; - hil_dev.dev.phys = "hpkbd/input0"; - - hil_dev.dev.id.bustype = BUS_HIL; - hil_dev.dev.id.vendor = PCI_VENDOR_ID_HP; - hil_dev.dev.id.product = 0x0001; - hil_dev.dev.id.version = 0x0010; - - input_register_device(&hil_dev.dev); + set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); + + hil_dev.dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + hil_dev.dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL); + hil_dev.dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; + hil_dev.dev->keycodesize = sizeof(hphilkeyb_keycode[0]); + hil_dev.dev->keycode = hphilkeyb_keycode; + hil_dev.dev->name = "HIL keyboard"; + hil_dev.dev->phys = "hpkbd/input0"; + + hil_dev.dev->id.bustype = BUS_HIL; + hil_dev.dev->id.vendor = PCI_VENDOR_ID_HP; + hil_dev.dev->id.product = 0x0001; + hil_dev.dev->id.version = 0x0010; + + input_register_device(hil_dev.dev); printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", - hil_dev.dev.name, kbid, HILBASE, HIL_IRQ); + hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); return 0; } @@ -329,7 +332,10 @@ static void __exit hil_exit(void) /* Turn off interrupts */ hil_do(HIL_INTOFF, NULL, 0); - input_unregister_device(&hil_dev.dev); + input_unregister_device(hil_dev.dev); + + input_free_device(hil_dev.dev); + hil_dev.dev = NULL; #if defined(CONFIG_PARISC) unregister_parisc_driver(&hil_driver); diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c index c2bf2ed07d..a648f9fe3d 100644 --- a/drivers/input/mouse/hil_ptr.c +++ b/drivers/input/mouse/hil_ptr.c @@ -55,7 +55,7 @@ MODULE_LICENSE("Dual BSD/GPL"); #define HIL_PTR_MAX_LENGTH 16 struct hil_ptr { - struct input_dev dev; + struct input_dev *dev; struct serio *serio; /* Input buffer and index for packets from HIL bus. */ @@ -79,7 +79,7 @@ struct hil_ptr { /* Process a complete packet after transfer from the HIL */ static void hil_ptr_process_record(struct hil_ptr *ptr) { - struct input_dev *dev = &ptr->dev; + struct input_dev *dev = ptr->dev; hil_packet *data = ptr->data; hil_packet p; int idx, i, cnt, laxis; @@ -148,12 +148,12 @@ static void hil_ptr_process_record(struct hil_ptr *ptr) if (absdev) { val = lo + (hi<<8); #ifdef TABLET_AUTOADJUST - if (val < ptr->dev.absmin[ABS_X + i]) - ptr->dev.absmin[ABS_X + i] = val; - if (val > ptr->dev.absmax[ABS_X + i]) - ptr->dev.absmax[ABS_X + i] = val; + if (val < dev->absmin[ABS_X + i]) + dev->absmin[ABS_X + i] = val; + if (val > dev->absmax[ABS_X + i]) + dev->absmax[ABS_X + i] = val; #endif - if (i%3) val = ptr->dev.absmax[ABS_X + i] - val; + if (i%3) val = dev->absmax[ABS_X + i] - val; input_report_abs(dev, ABS_X + i, val); } else { val = (int) (((int8_t)lo) | ((int8_t)hi<<8)); @@ -233,26 +233,30 @@ static void hil_ptr_disconnect(struct serio *serio) return; } - input_unregister_device(&ptr->dev); + input_unregister_device(ptr->dev); serio_close(serio); + input_free_device(ptr->dev); kfree(ptr); } static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) { - struct hil_ptr *ptr; - char *txt; - unsigned int i, naxsets, btntype; - uint8_t did, *idd; + struct hil_ptr *ptr; + char *txt; + unsigned int i, naxsets, btntype; + uint8_t did, *idd; - if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return -ENOMEM; - memset(ptr, 0, sizeof(struct hil_ptr)); + if (!(ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL))) + return -ENOMEM; - if (serio_open(serio, driver)) goto bail0; + ptr->dev = input_allocate_device(); + if (!ptr->dev) goto bail0; + ptr->dev->private = ptr; + + if (serio_open(serio, driver)) goto bail1; serio_set_drvdata(serio, ptr); ptr->serio = serio; - ptr->dev.private = ptr; init_MUTEX_LOCKED(&(ptr->sem)); @@ -283,25 +287,24 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) up(&(ptr->sem)); - init_input_dev(&ptr->dev); did = ptr->idd[0]; idd = ptr->idd + 1; txt = "unknown"; if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { - ptr->dev.evbit[0] = BIT(EV_REL); + ptr->dev->evbit[0] = BIT(EV_REL); txt = "relative"; } if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) { - ptr->dev.evbit[0] = BIT(EV_ABS); + ptr->dev->evbit[0] = BIT(EV_ABS); txt = "absolute"; } - if (!ptr->dev.evbit[0]) { - goto bail1; + if (!ptr->dev->evbit[0]) { + goto bail2; } ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); - if (ptr->nbtn) ptr->dev.evbit[0] |= BIT(EV_KEY); + if (ptr->nbtn) ptr->dev->evbit[0] |= BIT(EV_KEY); naxsets = HIL_IDD_NUM_AXSETS(*idd); ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); @@ -325,7 +328,7 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) btntype = BTN_MOUSE; for (i = 0; i < ptr->nbtn; i++) { - set_bit(btntype | i, ptr->dev.keybit); + set_bit(btntype | i, ptr->dev->keybit); ptr->btnmap[i] = btntype | i; } @@ -337,50 +340,52 @@ static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { for (i = 0; i < ptr->naxes; i++) { - set_bit(REL_X + i, ptr->dev.relbit); + set_bit(REL_X + i, ptr->dev->relbit); } for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { - set_bit(REL_X + i, ptr->dev.relbit); + set_bit(REL_X + i, ptr->dev->relbit); } } else { for (i = 0; i < ptr->naxes; i++) { - set_bit(ABS_X + i, ptr->dev.absbit); - ptr->dev.absmin[ABS_X + i] = 0; - ptr->dev.absmax[ABS_X + i] = + set_bit(ABS_X + i, ptr->dev->absbit); + ptr->dev->absmin[ABS_X + i] = 0; + ptr->dev->absmax[ABS_X + i] = HIL_IDD_AXIS_MAX((ptr->idd + 1), i); } for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { - set_bit(ABS_X + i, ptr->dev.absbit); - ptr->dev.absmin[ABS_X + i] = 0; - ptr->dev.absmax[ABS_X + i] = + set_bit(ABS_X + i, ptr->dev->absbit); + ptr->dev->absmin[ABS_X + i] = 0; + ptr->dev->absmax[ABS_X + i] = HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3)); } #ifdef TABLET_AUTOADJUST for (i = 0; i < ABS_MAX; i++) { - int diff = ptr->dev.absmax[ABS_X + i] / 10; - ptr->dev.absmin[ABS_X + i] += diff; - ptr->dev.absmax[ABS_X + i] -= diff; + int diff = ptr->dev->absmax[ABS_X + i] / 10; + ptr->dev->absmin[ABS_X + i] += diff; + ptr->dev->absmax[ABS_X + i] -= diff; } #endif } - ptr->dev.name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME; + ptr->dev->name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME; - ptr->dev.id.bustype = BUS_HIL; - ptr->dev.id.vendor = PCI_VENDOR_ID_HP; - ptr->dev.id.product = 0x0001; /* TODO: get from ptr->rsc */ - ptr->dev.id.version = 0x0100; /* TODO: get from ptr->rsc */ - ptr->dev.dev = &serio->dev; + ptr->dev->id.bustype = BUS_HIL; + ptr->dev->id.vendor = PCI_VENDOR_ID_HP; + ptr->dev->id.product = 0x0001; /* TODO: get from ptr->rsc */ + ptr->dev->id.version = 0x0100; /* TODO: get from ptr->rsc */ + ptr->dev->dev = &serio->dev; - input_register_device(&ptr->dev); + input_register_device(ptr->dev); printk(KERN_INFO "input: %s (%s), ID: %d\n", - ptr->dev.name, + ptr->dev->name, (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad", did); return 0; - bail1: + bail2: serio_close(serio); + bail1: + input_free_device(ptr->dev); bail0: kfree(ptr); serio_set_drvdata(serio, NULL); -- cgit v1.2.2 From cd7a9202a5a6e7712df2b80ed5ebd7b078130fc3 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Thu, 30 Mar 2006 11:47:32 -0500 Subject: [PARISC] Fix double free when removing HIL drivers On Thu, Mar 30, 2006 at 08:31:02AM -0500, Dmitry Torokhov wrote: > Don't do that, its double free. input_unregister_device() normally > causes release() to be called and free the device. input_free_device > is only to be called when input_register_device has not been called or > failed. > > Plus you might want to unregister device after closing serio port, > otherwise your interrupt routine might be referencing already freed > memory. Signed-off-by: Kyle McMartin --- drivers/input/keyboard/hil_kbd.c | 3 +-- drivers/input/keyboard/hilkbd.c | 1 - drivers/input/mouse/hil_ptr.c | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 99f8c5b4cd..63f387e4b7 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -240,9 +240,8 @@ static void hil_kbd_disconnect(struct serio *serio) return; } - input_unregister_device(kbd->dev); serio_close(serio); - input_free_device(kbd->dev); + input_unregister_device(kbd->dev); kfree(kbd); } diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index 452c5f3e61..33edd030aa 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c @@ -334,7 +334,6 @@ static void __exit hil_exit(void) input_unregister_device(hil_dev.dev); - input_free_device(hil_dev.dev); hil_dev.dev = NULL; #if defined(CONFIG_PARISC) diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c index a648f9fe3d..bfb564fd8f 100644 --- a/drivers/input/mouse/hil_ptr.c +++ b/drivers/input/mouse/hil_ptr.c @@ -233,9 +233,8 @@ static void hil_ptr_disconnect(struct serio *serio) return; } - input_unregister_device(ptr->dev); serio_close(serio); - input_free_device(ptr->dev); + input_unregister_device(ptr->dev); kfree(ptr); } -- cgit v1.2.2 From 8b316a3973f05e572b4edeeda9072987f6bbaa44 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 30 Mar 2006 17:07:32 -0500 Subject: [libata] ahci: add ATI SB600 PCI IDs From: Anatoli Antonovitch Signed-off-by: Felix Kuehling Signed-off-by: Jeff Garzik --- drivers/scsi/ahci.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index ffba65656a..1bd82c4e52 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -293,6 +293,10 @@ static const struct pci_device_id ahci_pci_tbl[] = { board_ahci }, /* JMicron JMB360 */ { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB363 */ + { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* ATI SB600 non-raid */ + { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* ATI SB600 raid */ { } /* terminate list */ }; -- cgit v1.2.2 From 6e3d4f25a561d15863ff4868a03780f59ba5ae8c Mon Sep 17 00:00:00 2001 From: Janos Farkas Date: Fri, 31 Mar 2006 01:04:57 +0200 Subject: [PATCH] pcmcia: permit single-character identifiers For some time, the core pcmcia drivers seem not to think single character prod_ids are valid, thus preventing the "cleverly" named "D" "Link DWL-650 11Mbps WLAN Card" Before (as in 2.6.16): PRODID_1="" PRODID_2="Link DWL-650 11Mbps WLAN Card" PRODID_3="Version 01.02" PRODID_4="" MANFID=0156,0002 FUNCID=6 After (with the patch) PRODID_1="D" PRODID_2="Link DWL-650 11Mbps WLAN Card" PRODID_3="Version 01.02" PRODID_4="" MANFID=0156,0002 FUNCID=6 Signed-off-by: Janos Farkas Signed-off-by: Dominik Brodowski --- drivers/pcmcia/ds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index bb96ce1db0..a4333a8266 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -546,7 +546,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) tmp = vers1->str + vers1->ofs[i]; length = strlen(tmp) + 1; - if ((length < 3) || (length > 255)) + if ((length < 2) || (length > 255)) continue; p_dev->prod_id[i] = kmalloc(sizeof(char) * length, -- cgit v1.2.2 From 1ae9c7d8198ae973da3b927e28d63f294ffa11e3 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 10 Jan 2006 20:40:40 +0100 Subject: [PATCH] pcmcia: remove unused field Present from config_t config_t.Present is set to the same value as CardValues, which isn't modified anywhere. Therefore, we can use only one of these two objects. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cs_internal.h | 1 - drivers/pcmcia/pcmcia_resource.c | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 7b37eba35b..2b267def96 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -45,7 +45,6 @@ typedef struct config_t { u_int IntType; u_int ConfigBase; u_char Status, Pin, Copy, Option, ExtStatus; - u_int Present; u_int CardValues; io_req_t io; struct { diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 89022ad5b5..f58814519e 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -338,7 +338,7 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function, if ((c != NULL) && (c->state & CONFIG_LOCKED) && (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { u_char reg; - if (c->Present & PRESENT_PIN_REPLACE) { + if (c->CardValues & PRESENT_PIN_REPLACE) { pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); status->CardState |= (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; @@ -352,7 +352,7 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function, /* No PRR? Then assume we're always ready */ status->CardState |= CS_EVENT_READY_CHANGE; } - if (c->Present & PRESENT_EXT_STATUS) { + if (c->CardValues & PRESENT_EXT_STATUS) { pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); status->CardState |= (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; @@ -643,7 +643,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, /* Set up CIS configuration registers */ base = c->ConfigBase = req->ConfigBase; - c->Present = c->CardValues = req->Present; + c->CardValues = req->Present; if (req->Present & PRESENT_COPY) { c->Copy = req->Copy; pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); -- cgit v1.2.2 From dbb22f0d65ccc2e9dfeb4c420942f2757a80f8d2 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 10 Jan 2006 20:41:27 +0100 Subject: [PATCH] pcmcia: access config_t using pointer instead of array Access the PCMCIA config_t struct (one per device function) using a pointer in struct pcmcia_device, instead of looking them up in an array. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cs_internal.h | 6 ------ drivers/pcmcia/ds.c | 1 + drivers/pcmcia/pcmcia_resource.c | 19 +++++++++---------- 3 files changed, 10 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 2b267def96..f889a44280 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -94,12 +94,6 @@ static inline void cs_socket_put(struct pcmcia_socket *skt) } } -#define CHECK_SOCKET(s) \ - (((s) >= sockets) || (socket_table[s]->ops == NULL)) - -#define SOCKET(h) (h->socket) -#define CONFIG(h) (&SOCKET(h)->config[(h)->func]) - /* In cardbus.c */ int cb_alloc(struct pcmcia_socket *s); void cb_free(struct pcmcia_socket *s); diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index a4333a8266..5166f00cfe 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -399,6 +399,7 @@ static int pcmcia_device_probe(struct device * dev) goto put_module; } } + p_dev->function_config = &s->config[p_dev->func]; ret = p_drv->probe(p_dev); if (ret) diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index f58814519e..11a94d9a15 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -372,9 +372,7 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function, int pcmcia_get_status(client_handle_t handle, cs_status_t *status) { - struct pcmcia_socket *s; - s = SOCKET(handle); - return pccard_get_status(s, handle->func, status); + return pccard_get_status(handle->socket, handle->func, status); } EXPORT_SYMBOL(pcmcia_get_status); @@ -422,7 +420,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, config_t *c; s = p_dev->socket; - c = CONFIG(p_dev); + c = p_dev->function_config; + if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (!(c->state & CONFIG_LOCKED)) @@ -470,7 +469,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) p_dev->state &= ~CLIENT_CONFIG_LOCKED; if (!(p_dev->state & CLIENT_STALE)) { - config_t *c = CONFIG(p_dev); + config_t *c = p_dev->function_config; if (--(s->lock_count) == 0) { s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ s->socket.Vpp = 0; @@ -512,7 +511,7 @@ int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) p_dev->state &= ~CLIENT_IO_REQ; if (!(p_dev->state & CLIENT_STALE)) { - config_t *c = CONFIG(p_dev); + config_t *c = p_dev->function_config; if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if ((c->io.BasePort1 != req->BasePort1) || @@ -540,7 +539,7 @@ int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) p_dev->state &= ~CLIENT_IRQ_REQ; if (!(p_dev->state & CLIENT_STALE)) { - config_t *c = CONFIG(p_dev); + config_t *c= p_dev->function_config; if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if (c->irq.Attributes != req->Attributes) @@ -610,7 +609,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, if (req->IntType & INT_CARDBUS) return CS_UNSUPPORTED_MODE; - c = CONFIG(p_dev); + c = p_dev->function_config; if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; @@ -730,7 +729,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) if (!req) return CS_UNSUPPORTED_MODE; - c = CONFIG(p_dev); + c = p_dev->function_config; if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if (c->state & CONFIG_IO_REQ) @@ -786,7 +785,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; - c = CONFIG(p_dev); + c = p_dev->function_config; if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if (c->state & CONFIG_IRQ_REQ) -- cgit v1.2.2 From 855cdf134dfcf2ecb92ac4ad675cf655d8ceb678 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 10 Jan 2006 20:48:59 +0100 Subject: [PATCH] pcmcia: always use device pointer to config_t Update the remaining users using the static lookup table of the PCMCIA function configuration to use the struct pcmcia_device-contained pointer. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cs_internal.h | 5 ++-- drivers/pcmcia/pcmcia_ioctl.c | 57 +++++++++++++++++++++++++++++----------- drivers/pcmcia/pcmcia_resource.c | 39 +++++++++++---------------- 3 files changed, 58 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index f889a44280..88c96aee0f 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -126,10 +126,9 @@ extern struct class_interface pccard_sysfs_interface; extern struct rw_semaphore pcmcia_socket_list_rwsem; extern struct list_head pcmcia_socket_list; int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req); -int pccard_get_configuration_info(struct pcmcia_socket *s, unsigned int function, config_info_t *config); +int pccard_get_configuration_info(struct pcmcia_socket *s, struct pcmcia_device *p_dev, config_info_t *config); int pccard_reset_card(struct pcmcia_socket *skt); -int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status); -int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int function, conf_reg_t *reg); +int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_status_t *status); struct pcmcia_callback{ diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 80969f7e7a..56b625d171 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -70,10 +70,26 @@ extern int ds_pc_debug; #define ds_dbg(lvl, fmt, arg...) do { } while (0) #endif +static struct pcmcia_device *get_pcmcia_device(struct pcmcia_socket *s, + unsigned int function) +{ + struct pcmcia_device *p_dev = NULL; + unsigned long flags; + + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { + if (p_dev->func == function) { + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + return pcmcia_get_dev(p_dev); + } + } + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + return NULL; +} /* backwards-compatible accessing of driver --- by name! */ -static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info) +static struct pcmcia_driver *get_pcmcia_driver(dev_info_t *dev_info) { struct device_driver *drv; struct pcmcia_driver *p_drv; @@ -583,9 +599,11 @@ static int ds_ioctl(struct inode * inode, struct file * file, if (buf->config.Function && (buf->config.Function >= s->functions)) ret = CS_BAD_ARGS; - else - ret = pccard_get_configuration_info(s, - buf->config.Function, &buf->config); + else { + struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function); + ret = pccard_get_configuration_info(s, p_dev, &buf->config); + pcmcia_put_dev(p_dev); + } break; case DS_GET_FIRST_TUPLE: down(&s->skt_sem); @@ -609,12 +627,15 @@ static int ds_ioctl(struct inode * inode, struct file * file, ret = pccard_reset_card(s); break; case DS_GET_STATUS: - if (buf->status.Function && - (buf->status.Function >= s->functions)) - ret = CS_BAD_ARGS; - else - ret = pccard_get_status(s, buf->status.Function, &buf->status); - break; + if (buf->status.Function && + (buf->status.Function >= s->functions)) + ret = CS_BAD_ARGS; + else { + struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function); + ret = pccard_get_status(s, p_dev, &buf->status); + pcmcia_put_dev(p_dev); + } + break; case DS_VALIDATE_CIS: down(&s->skt_sem); pcmcia_validate_mem(s); @@ -638,12 +659,16 @@ static int ds_ioctl(struct inode * inode, struct file * file, err = -EPERM; goto free_out; } - if (buf->conf_reg.Function && - (buf->conf_reg.Function >= s->functions)) - ret = CS_BAD_ARGS; - else - ret = pccard_access_configuration_register(s, - buf->conf_reg.Function, &buf->conf_reg); + + ret = CS_BAD_ARGS; + + if (!(buf->conf_reg.Function && + (buf->conf_reg.Function >= s->functions))) { + struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->conf_reg.Function); + if (p_dev) + ret = pcmcia_access_configuration_register(p_dev, &buf->conf_reg); + pcmcia_put_dev(p_dev); + } break; case DS_GET_FIRST_REGION: case DS_GET_NEXT_REGION: diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 11a94d9a15..aabde8be64 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -165,21 +165,19 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base, * this and the tuple reading services. */ -int pccard_access_configuration_register(struct pcmcia_socket *s, - unsigned int function, +int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, conf_reg_t *reg) { + struct pcmcia_socket *s; config_t *c; int addr; u_char val; - if (!s || !s->config) + if (!p_dev || !p_dev->function_config) return CS_NO_CARD; - c = &s->config[function]; - - if (c == NULL) - return CS_NO_CARD; + s = p_dev->socket; + c = p_dev->function_config; if (!(c->state & CONFIG_LOCKED)) return CS_CONFIGURATION_LOCKED; @@ -200,20 +198,12 @@ int pccard_access_configuration_register(struct pcmcia_socket *s, break; } return CS_SUCCESS; -} /* pccard_access_configuration_register */ - -int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, - conf_reg_t *reg) -{ - return pccard_access_configuration_register(p_dev->socket, - p_dev->func, reg); -} +} /* pcmcia_access_configuration_register */ EXPORT_SYMBOL(pcmcia_access_configuration_register); - int pccard_get_configuration_info(struct pcmcia_socket *s, - unsigned int function, + struct pcmcia_device *p_dev, config_info_t *config) { config_t *c; @@ -221,7 +211,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; - config->Function = function; + config->Function = p_dev->func; #ifdef CONFIG_CARDBUS if (s->state & SOCKET_CARDBUS) { @@ -242,7 +232,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, } #endif - c = (s->config != NULL) ? &s->config[function] : NULL; + c = (p_dev) ? p_dev->function_config : NULL; if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { config->Attributes = 0; @@ -271,7 +261,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, config_info_t *config) { - return pccard_get_configuration_info(p_dev->socket, p_dev->func, + return pccard_get_configuration_info(p_dev->socket, p_dev, config); } EXPORT_SYMBOL(pcmcia_get_configuration_info); @@ -317,7 +307,7 @@ EXPORT_SYMBOL(pcmcia_get_window); * SocketState yet: I haven't seen any point for it. */ -int pccard_get_status(struct pcmcia_socket *s, unsigned int function, +int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_status_t *status) { config_t *c; @@ -334,7 +324,8 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function, if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; - c = (s->config != NULL) ? &s->config[function] : NULL; + c = (p_dev) ? p_dev->function_config : NULL; + if ((c != NULL) && (c->state & CONFIG_LOCKED) && (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { u_char reg; @@ -370,9 +361,9 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function, return CS_SUCCESS; } /* pccard_get_status */ -int pcmcia_get_status(client_handle_t handle, cs_status_t *status) +int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status) { - return pccard_get_status(handle->socket, handle->func, status); + return pccard_get_status(p_dev->socket, p_dev, status); } EXPORT_SYMBOL(pcmcia_get_status); -- cgit v1.2.2 From 360b65b95bae96f854a2413093ee9b79c31203ae Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 10 Jan 2006 20:50:39 +0100 Subject: [PATCH] pcmcia: make config_t independent, add reference counting Handle config_t structs independent of struct pcmcia_socket, and add reference counting for them. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cs.c | 2 -- drivers/pcmcia/cs_internal.h | 2 ++ drivers/pcmcia/ds.c | 70 +++++++++++++++++++++++++++----------------- 3 files changed, 45 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 613f2f1fbf..45cffbf285 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -406,8 +406,6 @@ static void socket_shutdown(struct pcmcia_socket *s) cb_free(s); #endif s->functions = 0; - kfree(s->config); - s->config = NULL; s->ops->get_status(s, &status); if (status & SS_POWERON) { diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 88c96aee0f..01c32af559 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -16,6 +16,7 @@ #define _LINUX_CS_INTERNAL_H #include +#include /* Flags in client state */ #define CLIENT_CONFIG_LOCKED 0x0001 @@ -40,6 +41,7 @@ typedef struct region_t { /* Each card function gets one of these guys */ typedef struct config_t { + struct kref ref; u_int state; u_int Attributes; u_int IntType; diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 5166f00cfe..37ba1246c2 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -23,6 +23,7 @@ #include #include #include +#include #define IN_CARD_SERVICES #include @@ -343,12 +344,19 @@ void pcmcia_put_dev(struct pcmcia_device *p_dev) put_device(&p_dev->dev); } +static void pcmcia_release_function(struct kref *ref) +{ + struct config_t *c = container_of(ref, struct config_t, ref); + kfree(c); +} + static void pcmcia_release_dev(struct device *dev) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); ds_dbg(1, "releasing dev %p\n", p_dev); pcmcia_put_socket(p_dev->socket); kfree(p_dev->devname); + kref_put(&p_dev->function_config->ref, pcmcia_release_function); kfree(p_dev); } @@ -377,30 +385,14 @@ static int pcmcia_device_probe(struct device * dev) p_drv = to_pcmcia_drv(dev->driver); s = p_dev->socket; - if ((!p_drv->probe) || (!try_module_get(p_drv->owner))) { + if ((!p_drv->probe) || (!p_dev->function_config) || + (!try_module_get(p_drv->owner))) { ret = -EINVAL; goto put_dev; } p_dev->state &= ~CLIENT_UNBOUND; - /* set up the device configuration, if it hasn't been done before */ - if (!s->functions) { - cistpl_longlink_mfc_t mfc; - if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC, - &mfc) == CS_SUCCESS) - s->functions = mfc.nfn; - else - s->functions = 1; - s->config = kzalloc(sizeof(config_t) * s->functions, - GFP_KERNEL); - if (!s->config) { - ret = -ENOMEM; - goto put_module; - } - } - p_dev->function_config = &s->config[p_dev->func]; - ret = p_drv->probe(p_dev); if (ret) goto put_module; @@ -576,7 +568,7 @@ static DECLARE_MUTEX(device_add_lock); struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) { - struct pcmcia_device *p_dev; + struct pcmcia_device *p_dev, *tmp_dev; unsigned long flags; int bus_id_len; @@ -597,6 +589,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f p_dev->socket = s; p_dev->device_no = (s->device_count++); p_dev->func = function; + if (s->functions < function) + s->functions = function; p_dev->dev.bus = &pcmcia_bus_type; p_dev->dev.parent = s->dev.dev; @@ -611,28 +605,50 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f /* compat */ p_dev->state = CLIENT_UNBOUND; - /* Add to the list in pcmcia_bus_socket */ + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + + /* + * p_dev->function_config must be the same for all card functions. + * Note that this is serialized by the device_add_lock, so that + * only one such struct will be created. + */ + list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) + if (p_dev->func == tmp_dev->func) { + p_dev->function_config = tmp_dev->function_config; + kref_get(&p_dev->function_config->ref); + } + + /* Add to the list in pcmcia_bus_socket */ list_add_tail(&p_dev->socket_device_list, &s->devices_list); + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + if (!p_dev->function_config) { + p_dev->function_config = kzalloc(sizeof(struct config_t), + GFP_KERNEL); + if (!p_dev->function_config) + goto err_unreg; + kref_init(&p_dev->function_config->ref); + } + printk(KERN_NOTICE "pcmcia: registering new device %s\n", p_dev->devname); pcmcia_device_query(p_dev); - if (device_register(&p_dev->dev)) { - spin_lock_irqsave(&pcmcia_dev_list_lock, flags); - list_del(&p_dev->socket_device_list); - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - - goto err_free; - } + if (device_register(&p_dev->dev)) + goto err_unreg; up(&device_add_lock); return p_dev; + err_unreg: + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + list_del(&p_dev->socket_device_list); + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + err_free: kfree(p_dev->devname); kfree(p_dev); -- cgit v1.2.2 From 7fe908dd11e0c947bb72baa5b001d7abe5a420d5 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 10 Jan 2006 21:20:36 +0100 Subject: [PATCH] pcmcia: use mutexes instead of semaphores Use mutexes in the PCMICA core, as they suffice for what needs to be done. Includes a bugfix from and Signed-off-by Andrew Morton. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cs.c | 40 ++++++++++++++++++++-------------------- drivers/pcmcia/ds.c | 14 +++++++------- drivers/pcmcia/pcmcia_ioctl.c | 12 ++++++------ drivers/pcmcia/rsrc_nonstatic.c | 40 ++++++++++++++++++++-------------------- drivers/pcmcia/socket_sysfs.c | 9 +++++---- 5 files changed, 58 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 45cffbf285..907a6768e9 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -111,9 +111,9 @@ int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state) list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { if (socket->dev.dev != dev) continue; - down(&socket->skt_sem); + mutex_lock(&socket->skt_mutex); socket_suspend(socket); - up(&socket->skt_sem); + mutex_unlock(&socket->skt_mutex); } up_read(&pcmcia_socket_list_rwsem); @@ -129,9 +129,9 @@ int pcmcia_socket_dev_resume(struct device *dev) list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { if (socket->dev.dev != dev) continue; - down(&socket->skt_sem); + mutex_lock(&socket->skt_mutex); socket_resume(socket); - up(&socket->skt_sem); + mutex_unlock(&socket->skt_mutex); } up_read(&pcmcia_socket_list_rwsem); @@ -237,7 +237,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) init_completion(&socket->socket_released); init_completion(&socket->thread_done); init_waitqueue_head(&socket->thread_wait); - init_MUTEX(&socket->skt_sem); + mutex_init(&socket->skt_mutex); spin_lock_init(&socket->thread_lock); ret = kernel_thread(pccardd, socket, CLONE_KERNEL); @@ -662,7 +662,7 @@ static int pccardd(void *__skt) spin_unlock_irqrestore(&skt->thread_lock, flags); if (events) { - down(&skt->skt_sem); + mutex_lock(&skt->skt_mutex); if (events & SS_DETECT) socket_detect_change(skt); if (events & SS_BATDEAD) @@ -671,7 +671,7 @@ static int pccardd(void *__skt) send_event(skt, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW); if (events & SS_READY) send_event(skt, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW); - up(&skt->skt_sem); + mutex_unlock(&skt->skt_mutex); continue; } @@ -715,8 +715,8 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) { int ret = 0; - /* s->skt_sem also protects s->callback */ - down(&s->skt_sem); + /* s->skt_mutex also protects s->callback */ + mutex_lock(&s->skt_mutex); if (c) { /* registration */ @@ -732,7 +732,7 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) } else s->callback = NULL; err: - up(&s->skt_sem); + mutex_unlock(&s->skt_mutex); return ret; } @@ -750,7 +750,7 @@ int pccard_reset_card(struct pcmcia_socket *skt) cs_dbg(skt, 1, "resetting socket\n"); - down(&skt->skt_sem); + mutex_lock(&skt->skt_mutex); do { if (!(skt->state & SOCKET_PRESENT)) { ret = CS_NO_CARD; @@ -779,7 +779,7 @@ int pccard_reset_card(struct pcmcia_socket *skt) ret = CS_SUCCESS; } while (0); - up(&skt->skt_sem); + mutex_unlock(&skt->skt_mutex); return ret; } /* reset_card */ @@ -795,7 +795,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt) cs_dbg(skt, 1, "suspending socket\n"); - down(&skt->skt_sem); + mutex_lock(&skt->skt_mutex); do { if (!(skt->state & SOCKET_PRESENT)) { ret = CS_NO_CARD; @@ -812,7 +812,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt) } ret = socket_suspend(skt); } while (0); - up(&skt->skt_sem); + mutex_unlock(&skt->skt_mutex); return ret; } /* suspend_card */ @@ -825,7 +825,7 @@ int pcmcia_resume_card(struct pcmcia_socket *skt) cs_dbg(skt, 1, "waking up socket\n"); - down(&skt->skt_sem); + mutex_lock(&skt->skt_mutex); do { if (!(skt->state & SOCKET_PRESENT)) { ret = CS_NO_CARD; @@ -839,7 +839,7 @@ int pcmcia_resume_card(struct pcmcia_socket *skt) if (!ret && skt->callback) skt->callback->resume(skt); } while (0); - up(&skt->skt_sem); + mutex_unlock(&skt->skt_mutex); return ret; } /* resume_card */ @@ -853,7 +853,7 @@ int pcmcia_eject_card(struct pcmcia_socket *skt) cs_dbg(skt, 1, "user eject request\n"); - down(&skt->skt_sem); + mutex_lock(&skt->skt_mutex); do { if (!(skt->state & SOCKET_PRESENT)) { ret = -ENODEV; @@ -869,7 +869,7 @@ int pcmcia_eject_card(struct pcmcia_socket *skt) socket_remove(skt); ret = 0; } while (0); - up(&skt->skt_sem); + mutex_unlock(&skt->skt_mutex); return ret; } /* eject_card */ @@ -882,7 +882,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) cs_dbg(skt, 1, "user insert request\n"); - down(&skt->skt_sem); + mutex_lock(&skt->skt_mutex); do { if (skt->state & SOCKET_PRESENT) { ret = -EBUSY; @@ -894,7 +894,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) } ret = 0; } while (0); - up(&skt->skt_sem); + mutex_unlock(&skt->skt_mutex); return ret; } /* insert_card */ diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 37ba1246c2..3b7e1ba13c 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -564,7 +564,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) * won't work, this doesn't matter much at the moment: the driver core doesn't * support it either. */ -static DECLARE_MUTEX(device_add_lock); +static DEFINE_MUTEX(device_add_lock); struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) { @@ -576,7 +576,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f if (!s) return NULL; - down(&device_add_lock); + mutex_lock(&device_add_lock); /* max of 2 devices per card */ if (s->device_count == 2) @@ -640,7 +640,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f if (device_register(&p_dev->dev)) goto err_unreg; - up(&device_add_lock); + mutex_unlock(&device_add_lock); return p_dev; @@ -654,7 +654,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f kfree(p_dev); s->device_count--; err_put: - up(&device_add_lock); + mutex_unlock(&device_add_lock); pcmcia_put_socket(s); return NULL; @@ -713,7 +713,7 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt) int no_devices=0; unsigned long flags; - /* must be called with skt_sem held */ + /* must be called with skt_mutex held */ spin_lock_irqsave(&pcmcia_dev_list_lock, flags); if (list_empty(&skt->devices_list)) no_devices=1; @@ -999,9 +999,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, if (!count) return -EINVAL; - down(&p_dev->socket->skt_sem); + mutex_lock(&p_dev->socket->skt_mutex); p_dev->allow_func_id_match = 1; - up(&p_dev->socket->skt_sem); + mutex_unlock(&p_dev->socket->skt_mutex); bus_rescan_devices(&pcmcia_bus_type); diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 56b625d171..8eceba7391 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -269,9 +269,9 @@ rescan: /* * Prevent this racing with a card insertion. */ - down(&s->skt_sem); + mutex_lock(&s->skt_mutex); bus_rescan_devices(&pcmcia_bus_type); - up(&s->skt_sem); + mutex_unlock(&s->skt_mutex); /* check whether the driver indeed matched. I don't care if this * is racy or not, because it can only happen on cardmgr access @@ -606,9 +606,9 @@ static int ds_ioctl(struct inode * inode, struct file * file, } break; case DS_GET_FIRST_TUPLE: - down(&s->skt_sem); + mutex_lock(&s->skt_mutex); pcmcia_validate_mem(s); - up(&s->skt_sem); + mutex_unlock(&s->skt_mutex); ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple); break; case DS_GET_NEXT_TUPLE: @@ -637,9 +637,9 @@ static int ds_ioctl(struct inode * inode, struct file * file, } break; case DS_VALIDATE_CIS: - down(&s->skt_sem); + mutex_lock(&s->skt_mutex); pcmcia_validate_mem(s); - up(&s->skt_sem); + mutex_unlock(&s->skt_mutex); ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo); break; case DS_SUSPEND_CARD: diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 5301ac6035..6da4a03d68 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -61,7 +61,7 @@ struct socket_data { unsigned int rsrc_mem_probe; }; -static DECLARE_MUTEX(rsrc_sem); +static DEFINE_MUTEX(rsrc_mutex); #define MEM_PROBE_LOW (1 << 0) #define MEM_PROBE_HIGH (1 << 1) @@ -484,7 +484,7 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) /* - * Locking note: Must be called with skt_sem held! + * Locking note: Must be called with skt_mutex held! */ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) { @@ -495,7 +495,7 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) if (!probe_mem) return 0; - down(&rsrc_sem); + mutex_lock(&rsrc_mutex); if (s->features & SS_CAP_PAGE_REGS) probe_mask = MEM_PROBE_HIGH; @@ -507,7 +507,7 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) s_data->rsrc_mem_probe |= probe_mask; } - up(&rsrc_sem); + mutex_unlock(&rsrc_mutex); return ret; } @@ -585,7 +585,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star struct socket_data *s_data = s->resource_data; int ret = -ENOMEM; - down(&rsrc_sem); + mutex_lock(&rsrc_mutex); for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) { unsigned long start = m->base; unsigned long end = m->base + m->num - 1; @@ -596,7 +596,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star ret = adjust_resource(res, r_start, r_end - r_start + 1); break; } - up(&rsrc_sem); + mutex_unlock(&rsrc_mutex); return ret; } @@ -630,7 +630,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, data.offset = base & data.mask; data.map = &s_data->io_db; - down(&rsrc_sem); + mutex_lock(&rsrc_mutex); #ifdef CONFIG_PCI if (s->cb_dev) { ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1, @@ -639,7 +639,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, #endif ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, 1, pcmcia_align, &data); - up(&rsrc_sem); + mutex_unlock(&rsrc_mutex); if (ret != 0) { kfree(res); @@ -672,7 +672,7 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num, min = 0x100000UL + base; } - down(&rsrc_sem); + mutex_lock(&rsrc_mutex); #ifdef CONFIG_PCI if (s->cb_dev) { ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, @@ -682,7 +682,7 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num, #endif ret = allocate_resource(&iomem_resource, res, num, min, max, 1, pcmcia_align, &data); - up(&rsrc_sem); + mutex_unlock(&rsrc_mutex); if (ret == 0 || low) break; low = 1; @@ -705,7 +705,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned if (end < start) return -EINVAL; - down(&rsrc_sem); + mutex_lock(&rsrc_mutex); switch (action) { case ADD_MANAGED_RESOURCE: ret = add_interval(&data->mem_db, start, size); @@ -723,7 +723,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned default: ret = -EINVAL; } - up(&rsrc_sem); + mutex_unlock(&rsrc_mutex); return ret; } @@ -741,7 +741,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long if (end > IO_SPACE_LIMIT) return -EINVAL; - down(&rsrc_sem); + mutex_lock(&rsrc_mutex); switch (action) { case ADD_MANAGED_RESOURCE: if (add_interval(&data->io_db, start, size) != 0) { @@ -760,7 +760,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long ret = -EINVAL; break; } - up(&rsrc_sem); + mutex_unlock(&rsrc_mutex); return ret; } @@ -867,7 +867,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s) struct socket_data *data = s->resource_data; struct resource_map *p, *q; - down(&rsrc_sem); + mutex_lock(&rsrc_mutex); for (p = data->mem_db.next; p != &data->mem_db; p = q) { q = p->next; kfree(p); @@ -876,7 +876,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s) q = p->next; kfree(p); } - up(&rsrc_sem); + mutex_unlock(&rsrc_mutex); } @@ -901,7 +901,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf) struct resource_map *p; ssize_t ret = 0; - down(&rsrc_sem); + mutex_lock(&rsrc_mutex); data = s->resource_data; for (p = data->io_db.next; p != &data->io_db; p = p->next) { @@ -913,7 +913,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf) ((unsigned long) p->base + p->num - 1)); } - up(&rsrc_sem); + mutex_unlock(&rsrc_mutex); return (ret); } @@ -953,7 +953,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf) struct resource_map *p; ssize_t ret = 0; - down(&rsrc_sem); + mutex_lock(&rsrc_mutex); data = s->resource_data; for (p = data->mem_db.next; p != &data->mem_db; p = p->next) { @@ -965,7 +965,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf) ((unsigned long) p->base + p->num - 1)); } - up(&rsrc_sem); + mutex_unlock(&rsrc_mutex); return (ret); } diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 5ab1cdef7c..83c6b31133 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -183,7 +184,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, s->resource_setup_done = 1; spin_unlock_irqrestore(&s->lock, flags); - down(&s->skt_sem); + mutex_lock(&s->skt_mutex); if ((s->callback) && (s->state & SOCKET_PRESENT) && !(s->state & SOCKET_CARDBUS)) { @@ -192,7 +193,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, module_put(s->callback->owner); } } - up(&s->skt_sem); + mutex_unlock(&s->skt_mutex); return count; } @@ -322,7 +323,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz kfree(cis); if (!ret) { - down(&s->skt_sem); + mutex_lock(&s->skt_mutex); if ((s->callback) && (s->state & SOCKET_PRESENT) && !(s->state & SOCKET_CARDBUS)) { if (try_module_get(s->callback->owner)) { @@ -330,7 +331,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz module_put(s->callback->owner); } } - up(&s->skt_sem); + mutex_unlock(&s->skt_mutex); } -- cgit v1.2.2 From e904663b4d511884145df54bead401840389853a Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 10 Jan 2006 21:35:49 +0100 Subject: [PATCH] pcmcia: remove include of config.h Remove the inclusion of include/config.h as it isn't needed any longer. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cistpl.c | 1 - drivers/pcmcia/cs.c | 1 - drivers/pcmcia/cs_internal.h | 1 - drivers/pcmcia/ds.c | 1 - drivers/pcmcia/i82092.c | 1 - drivers/pcmcia/i82365.c | 1 - drivers/pcmcia/pcmcia_compat.c | 1 - drivers/pcmcia/pcmcia_ioctl.c | 1 - drivers/pcmcia/pcmcia_resource.c | 1 - drivers/pcmcia/pd6729.c | 1 - drivers/pcmcia/rsrc_mgr.c | 1 - drivers/pcmcia/rsrc_nonstatic.c | 1 - drivers/pcmcia/sa1100_cerf.c | 1 - drivers/pcmcia/socket_sysfs.c | 1 - drivers/pcmcia/ti113x.h | 1 - 15 files changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 120fa8da63..912c03e5eb 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -12,7 +12,6 @@ * (C) 1999 David A. Hinds */ -#include #include #include #include diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 907a6768e9..3162998579 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 01c32af559..ad04ad4386 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -15,7 +15,6 @@ #ifndef _LINUX_CS_INTERNAL_H #define _LINUX_CS_INTERNAL_H -#include #include /* Flags in client state */ diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 3b7e1ba13c..4d11b35d4c 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -13,7 +13,6 @@ * (C) 2003 - 2005 Dominik Brodowski */ -#include #include #include #include diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index 7979c85df3..d5f03a338c 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -10,7 +10,6 @@ */ #include -#include #include #include #include diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 35a92d1e49..bd0308e898 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c index ebb161c4f8..734f28085a 100644 --- a/drivers/pcmcia/pcmcia_compat.c +++ b/drivers/pcmcia/pcmcia_compat.c @@ -13,7 +13,6 @@ * */ -#include #include #include diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 8eceba7391..be08bc9e99 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -18,7 +18,6 @@ */ -#include #include #include #include diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index aabde8be64..08377232d8 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -14,7 +14,6 @@ * */ -#include #include #include #include diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index f2789afb22..16d1ea7b0a 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -8,7 +8,6 @@ */ #include -#include #include #include #include diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 5146093698..e5a33121de 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -12,7 +12,6 @@ * (C) 1999 David A. Hinds */ -#include #include #include diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 6da4a03d68..0f8b157c97 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -12,7 +12,6 @@ * (C) 1999 David A. Hinds */ -#include #include #include #include diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c index 2b3c2895b4..eb89928f23 100644 --- a/drivers/pcmcia/sa1100_cerf.c +++ b/drivers/pcmcia/sa1100_cerf.c @@ -5,7 +5,6 @@ * Based off the Assabet. * */ -#include #include #include #include diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 83c6b31133..c5d7476da4 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index d5b4ff7446..7a3d1b8e16 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -30,7 +30,6 @@ #ifndef _LINUX_TI113X_H #define _LINUX_TI113X_H -#include /* Register definitions for TI 113X PCI-to-CardBus bridges */ -- cgit v1.2.2 From 1540eec5e5549b2e41704ce77f3f4ba880d2434c Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 15 Jan 2006 00:51:53 +0100 Subject: [PATCH] pcmcia: remove pcmcia_compat.c Remove the compatibility wrappers, as they can (now) also be implemented using macros. Please continue using these wrappers instead of new functions until a new API has stabilized. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/Makefile | 2 +- drivers/pcmcia/pcmcia_compat.c | 64 ------------------------------------------ 2 files changed, 1 insertion(+), 65 deletions(-) delete mode 100644 drivers/pcmcia/pcmcia_compat.c (limited to 'drivers') diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index bcecf5133b..22e17fdfa7 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -10,7 +10,7 @@ pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o obj-$(CONFIG_PCCARD) += pcmcia_core.o -pcmcia-y += ds.o pcmcia_compat.o pcmcia_resource.o +pcmcia-y += ds.o pcmcia_resource.o pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o obj-$(CONFIG_PCMCIA) += pcmcia.o diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c deleted file mode 100644 index 734f28085a..0000000000 --- a/drivers/pcmcia/pcmcia_compat.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * PCMCIA 16-bit compatibility functions - * - * The initial developer of the original code is David A. Hinds - * . Portions created by David A. Hinds - * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - * - * Copyright (C) 2004 Dominik Brodowski - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include - -#define IN_CARD_SERVICES -#include -#include -#include -#include -#include -#include - -#include "cs_internal.h" - -int pcmcia_get_first_tuple(struct pcmcia_device *p_dev, tuple_t *tuple) -{ - return pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple); -} -EXPORT_SYMBOL(pcmcia_get_first_tuple); - -int pcmcia_get_next_tuple(struct pcmcia_device *p_dev, tuple_t *tuple) -{ - return pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple); -} -EXPORT_SYMBOL(pcmcia_get_next_tuple); - -int pcmcia_get_tuple_data(struct pcmcia_device *p_dev, tuple_t *tuple) -{ - return pccard_get_tuple_data(p_dev->socket, tuple); -} -EXPORT_SYMBOL(pcmcia_get_tuple_data); - -int pcmcia_parse_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, cisparse_t *parse) -{ - return pccard_parse_tuple(tuple, parse); -} -EXPORT_SYMBOL(pcmcia_parse_tuple); - -int pcmcia_validate_cis(struct pcmcia_device *p_dev, cisinfo_t *info) -{ - return pccard_validate_cis(p_dev->socket, p_dev->func, info); -} -EXPORT_SYMBOL(pcmcia_validate_cis); - - -int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req) -{ - return pccard_reset_card(p_dev->socket); -} -EXPORT_SYMBOL(pcmcia_reset_card); -- cgit v1.2.2 From 0e0fad8f71a8a23fad223b7d72b4ba06d57f764f Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 15 Jan 2006 01:14:31 +0100 Subject: [PATCH] pcmcia: size reduction if ioctl isn't compiled If the kernel is configured to not include the deprecated PCMCIA ioctl, some code doesn't need to be built. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/ds.c | 2 ++ drivers/pcmcia/ds_internal.h | 2 +- drivers/pcmcia/rsrc_mgr.c | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 4d11b35d4c..211aa84353 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -835,9 +835,11 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); struct pcmcia_device_id *did = p_drv->id_table; +#ifdef CONFIG_PCMCIA_IOCTL /* matching by cardmgr */ if (p_dev->cardmgr == p_drv) return 1; +#endif while (did && did->match_flags) { if (pcmcia_devmatch(p_dev, did)) diff --git a/drivers/pcmcia/ds_internal.h b/drivers/pcmcia/ds_internal.h index d359bd25a5..783d8617a0 100644 --- a/drivers/pcmcia/ds_internal.h +++ b/drivers/pcmcia/ds_internal.h @@ -15,7 +15,7 @@ extern void handle_event(struct pcmcia_socket *s, event_t event); extern int handle_request(struct pcmcia_socket *s, event_t event); #else static inline void __init pcmcia_setup_ioctl(void) { return; } -static inline void __init pcmcia_cleanup_ioctl(void) { return; } +static inline void __exit pcmcia_cleanup_ioctl(void) { return; } static inline void handle_event(struct pcmcia_socket *s, event_t event) { return; } static inline int handle_request(struct pcmcia_socket *s, event_t event) { return CS_SUCCESS; } #endif diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index e5a33121de..81dfc2cac2 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -21,6 +21,8 @@ #include "cs_internal.h" +#ifdef CONFIG_PCMCIA_IOCTL + #ifdef CONFIG_PCMCIA_PROBE static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) @@ -97,6 +99,8 @@ int pcmcia_adjust_resource_info(adjust_t *adj) } EXPORT_SYMBOL(pcmcia_adjust_resource_info); +#endif + int pcmcia_validate_mem(struct pcmcia_socket *s) { if (s->resource_ops->validate_mem) -- cgit v1.2.2 From c7d006935dfda9174187aa557e94a137ced10c30 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 15 Jan 2006 08:04:43 +0100 Subject: [PATCH] pcmcia: remove duplicate fields in io_window_t BasePort, NumPorts and Attributes are or can be embedded in struct resource, so remove them. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 45 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 08377232d8..dbd5571064 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -88,7 +88,7 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base, } if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) { *base = s->io_offset | (*base & 0x0fff); - s->io[0].Attributes = attr; + s->io[0].res->flags = (s->io[0].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS); return 0; } /* Check for an already-allocated window that must conflict with @@ -96,38 +96,36 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base, * potential conflicts, just the most obvious ones. */ for (i = 0; i < MAX_IO_WIN; i++) - if ((s->io[i].NumPorts != 0) && - ((s->io[i].BasePort & (align-1)) == *base)) + if ((s->io[i].res) && + ((s->io[i].res->start & (align-1)) == *base)) return 1; for (i = 0; i < MAX_IO_WIN; i++) { - if (s->io[i].NumPorts == 0) { + if (!s->io[i].res) { s->io[i].res = pcmcia_find_io_region(*base, num, align, s); if (s->io[i].res) { - s->io[i].Attributes = attr; - s->io[i].BasePort = *base = s->io[i].res->start; - s->io[i].NumPorts = s->io[i].InUse = num; + *base = s->io[i].res->start; + s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS); + s->io[i].InUse = num; break; } else return 1; - } else if (s->io[i].Attributes != attr) + } else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS)) continue; /* Try to extend top of window */ - try = s->io[i].BasePort + s->io[i].NumPorts; + try = s->io[i].res->end + 1; if ((*base == 0) || (*base == try)) if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start, s->io[i].res->end + num, s) == 0) { *base = try; - s->io[i].NumPorts += num; s->io[i].InUse += num; break; } /* Try to extend bottom of window */ - try = s->io[i].BasePort - num; + try = s->io[i].res->start - num; if ((*base == 0) || (*base == try)) if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num, s->io[i].res->end, s) == 0) { - s->io[i].BasePort = *base = try; - s->io[i].NumPorts += num; + *base = try; s->io[i].InUse += num; break; } @@ -142,12 +140,13 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base, int i; for (i = 0; i < MAX_IO_WIN; i++) { - if ((s->io[i].BasePort <= base) && - (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) { + if (!s->io[i].res) + continue; + if ((s->io[i].res->start <= base) && + (s->io[i].res->end >= base+num-1)) { s->io[i].InUse -= num; /* Free the window if no one else is using it */ if (s->io[i].InUse == 0) { - s->io[i].NumPorts = 0; release_resource(s->io[i].res); kfree(s->io[i].res); s->io[i].res = NULL; @@ -224,8 +223,8 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, config->AssignedIRQ = s->irq.AssignedIRQ; if (config->AssignedIRQ) config->Attributes |= CONF_ENABLE_IRQ; - config->BasePort1 = s->io[0].BasePort; - config->NumPorts1 = s->io[0].NumPorts; + config->BasePort1 = s->io[0].res->start; + config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1; } return CS_SUCCESS; } @@ -468,7 +467,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) } if (c->state & CONFIG_IO_REQ) for (i = 0; i < MAX_IO_WIN; i++) { - if (s->io[i].NumPorts == 0) + if (!s->io[i].res) continue; s->io[i].Config--; if (s->io[i].Config != 0) @@ -679,10 +678,10 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, if (c->state & CONFIG_IO_REQ) { iomap.speed = io_speed; for (i = 0; i < MAX_IO_WIN; i++) - if (s->io[i].NumPorts != 0) { + if (s->io[i].res) { iomap.map = i; iomap.flags = MAP_ACTIVE; - switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) { + switch (s->io[i].res->flags & IO_DATA_PATH_WIDTH) { case IO_DATA_PATH_WIDTH_16: iomap.flags |= MAP_16BIT; break; case IO_DATA_PATH_WIDTH_AUTO: @@ -690,8 +689,8 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, default: break; } - iomap.start = s->io[i].BasePort; - iomap.stop = iomap.start + s->io[i].NumPorts - 1; + iomap.start = s->io[i].res->start; + iomap.stop = s->io[i].res->end; s->ops->set_io_map(s, &iomap); s->io[i].Config++; } -- cgit v1.2.2 From 8961b828667e715a96d9d8517f7c8b6552ead3bb Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 15 Jan 2006 08:30:40 +0100 Subject: [PATCH] parport_cs: don't play games with resources pcmcia_request_io() doesn't mark the resource as busy in 2.6., therefore there's no need to work around the registration of the resources into the resource tree. Signed-off-by: Dominik Brodowski --- drivers/parport/parport_cs.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 158d925632..d0fc8be569 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -226,9 +226,6 @@ void parport_config(dev_link_t *link) CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); - release_region(link->io.BasePort1, link->io.NumPorts1); - if (link->io.NumPorts2) - release_region(link->io.BasePort2, link->io.NumPorts2); p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2, link->irq.AssignedIRQ, PARPORT_DMA_NONE, NULL); @@ -277,11 +274,6 @@ void parport_cs_release(dev_link_t *link) if (info->ndev) { struct parport *p = info->port; parport_pc_unregister_port(p); - request_region(link->io.BasePort1, link->io.NumPorts1, - info->node.dev_name); - if (link->io.NumPorts2) - request_region(link->io.BasePort2, link->io.NumPorts2, - info->node.dev_name); } info->ndev = 0; link->dev = NULL; -- cgit v1.2.2 From 552dc85dfed6b6a74a3a01c4ba277ee09797dd0a Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 1 Mar 2006 14:04:52 +0100 Subject: [PATCH] pcmcia: socket.functions starts with 1 socket.functions is the number of functions, and so must be one larger than the maximum function number. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/ds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 211aa84353..16159e9d1b 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -588,8 +588,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f p_dev->socket = s; p_dev->device_no = (s->device_count++); p_dev->func = function; - if (s->functions < function) - s->functions = function; + if (s->functions <= function) + s->functions = function + 1; p_dev->dev.bus = &pcmcia_bus_type; p_dev->dev.parent = s->dev.dev; -- cgit v1.2.2 From 2c1f3b7a30286c16ba151fadb0abf0b20e2a1e45 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 21 Feb 2006 12:56:52 +0200 Subject: [PATCH] pcmcia: AT91RM9200 Compact Flash driver This patch adds support for the Compact Flash controller integrated in the Atmel AT91RM9200 processor. Signed-off-by: Andrew Victor --- drivers/pcmcia/Kconfig | 7 + drivers/pcmcia/Makefile | 1 + drivers/pcmcia/at91_cf.c | 365 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 373 insertions(+) create mode 100644 drivers/pcmcia/at91_cf.c (limited to 'drivers') diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 1f4ad0e783..cba6c9eef2 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -263,6 +263,13 @@ config OMAP_CF Say Y here to support the CompactFlash controller on OMAP. Note that this doesn't support "True IDE" mode. +config AT91_CF + tristate "AT91 CompactFlash Controller" + depends on PCMCIA && ARCH_AT91RM9200 + help + Say Y here to support the CompactFlash controller on AT91 chips. + Or choose M to compile the driver as a module named "at91_cf". + config PCCARD_NONSTATIC tristate diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 22e17fdfa7..4276965517 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o obj-$(CONFIG_OMAP_CF) += omap_cf.o +obj-$(CONFIG_AT91_CF) += at91_cf.o sa11xx_core-y += soc_common.o sa11xx_base.o pxa2xx_core-y += soc_common.o pxa2xx_base.o diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c new file mode 100644 index 0000000000..67cc5f7d0c --- /dev/null +++ b/drivers/pcmcia/at91_cf.c @@ -0,0 +1,365 @@ +/* + * at91_cf.c -- AT91 CompactFlash controller driver + * + * Copyright (C) 2005 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + + +#define CF_SIZE 0x30000000 /* CS5+CS6: unavailable */ + +/* + * A0..A10 work in each range; A23 indicates I/O space; A25 is CFRNW; + * some other bit in {A24,A22..A11} is nREG to flag memory access + * (vs attributes). So more than 2KB/region would just be waste. + */ +#define CF_ATTR_PHYS (AT91_CF_BASE) +#define CF_IO_PHYS (AT91_CF_BASE + (1 << 23)) +#define CF_MEM_PHYS (AT91_CF_BASE + 0x017ff800) + +/*--------------------------------------------------------------------------*/ + +static const char driver_name[] = "at91_cf"; + +struct at91_cf_socket { + struct pcmcia_socket socket; + + unsigned present:1; + + struct platform_device *pdev; + struct at91_cf_data *board; +}; + +#define SZ_2K (2 * SZ_1K) + +static inline int at91_cf_present(struct at91_cf_socket *cf) +{ + return !at91_get_gpio_value(cf->board->det_pin); +} + +/*--------------------------------------------------------------------------*/ + +static int at91_cf_ss_init(struct pcmcia_socket *s) +{ + return 0; +} + +static irqreturn_t at91_cf_irq(int irq, void *_cf, struct pt_regs *r) +{ + struct at91_cf_socket *cf = (struct at91_cf_socket *) _cf; + + if (irq == cf->board->det_pin) { + unsigned present = at91_cf_present(cf); + + /* kick pccard as needed */ + if (present != cf->present) { + cf->present = present; + pr_debug("%s: card %s\n", driver_name, present ? "present" : "gone"); + pcmcia_parse_events(&cf->socket, SS_DETECT); + } + } + + return IRQ_HANDLED; +} + +static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp) +{ + struct at91_cf_socket *cf; + + if (!sp) + return -EINVAL; + + cf = container_of(s, struct at91_cf_socket, socket); + + /* NOTE: we assume 3VCARD, not XVCARD... */ + if (at91_cf_present(cf)) { + int rdy = cf->board->irq_pin; /* RDY/nIRQ */ + int vcc = cf->board->vcc_pin; + + *sp = SS_DETECT | SS_3VCARD; + if (!rdy || at91_get_gpio_value(rdy)) + *sp |= SS_READY; + if (!vcc || at91_get_gpio_value(vcc)) + *sp |= SS_POWERON; + } else + *sp = 0; + + return 0; +} + +static int at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s) +{ + struct at91_cf_socket *cf; + + cf = container_of(sock, struct at91_cf_socket, socket); + + /* switch Vcc if needed and possible */ + if (cf->board->vcc_pin) { + switch (s->Vcc) { + case 0: + at91_set_gpio_value(cf->board->vcc_pin, 0); + break; + case 33: + at91_set_gpio_value(cf->board->vcc_pin, 1); + break; + default: + return -EINVAL; + } + } + + /* toggle reset if needed */ + at91_set_gpio_value(cf->board->rst_pin, s->flags & SS_RESET); + + pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n", + driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask); + + return 0; +} + +static int at91_cf_ss_suspend(struct pcmcia_socket *s) +{ + return at91_cf_set_socket(s, &dead_socket); +} + +/* we already mapped the I/O region */ +static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) +{ + struct at91_cf_socket *cf; + u32 csr; + + cf = container_of(s, struct at91_cf_socket, socket); + io->flags &= (MAP_ACTIVE | MAP_16BIT | MAP_AUTOSZ); + + /* + * Use 16 bit accesses unless/until we need 8-bit i/o space. + * Always set CSR4 ... PCMCIA won't always unmap things. + */ + csr = at91_sys_read(AT91_SMC_CSR(4)) & ~AT91_SMC_DBW; + + /* + * NOTE: this CF controller ignores IOIS16, so we can't really do + * MAP_AUTOSZ. The 16bit mode allows single byte access on either + * D0-D7 (even addr) or D8-D15 (odd), so it's close enough for many + * purposes (and handles ide-cs). + * + * The 8bit mode is needed for odd byte access on D0-D7. It seems + * some cards only like that way to get at the odd byte, despite + * CF 3.0 spec table 35 also giving the D8-D15 option. + */ + if (!(io->flags & (MAP_16BIT|MAP_AUTOSZ))) { + csr |= AT91_SMC_DBW_8; + pr_debug("%s: 8bit i/o bus\n", driver_name); + } else { + csr |= AT91_SMC_DBW_16; + pr_debug("%s: 16bit i/o bus\n", driver_name); + } + at91_sys_write(AT91_SMC_CSR(4), csr); + + io->start = cf->socket.io_offset; + io->stop = io->start + SZ_2K - 1; + + return 0; +} + +/* pcmcia layer maps/unmaps mem regions */ +static int at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map) +{ + struct at91_cf_socket *cf; + + if (map->card_start) + return -EINVAL; + + cf = container_of(s, struct at91_cf_socket, socket); + + map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT; + if (map->flags & MAP_ATTRIB) + map->static_start = CF_ATTR_PHYS; + else + map->static_start = CF_MEM_PHYS; + + return 0; +} + +static struct pccard_operations at91_cf_ops = { + .init = at91_cf_ss_init, + .suspend = at91_cf_ss_suspend, + .get_status = at91_cf_get_status, + .set_socket = at91_cf_set_socket, + .set_io_map = at91_cf_set_io_map, + .set_mem_map = at91_cf_set_mem_map, +}; + +/*--------------------------------------------------------------------------*/ + +static int __init at91_cf_probe(struct device *dev) +{ + struct at91_cf_socket *cf; + struct at91_cf_data *board = dev->platform_data; + struct platform_device *pdev = to_platform_device(dev); + unsigned int csa; + int status; + + if (!board || !board->det_pin || !board->rst_pin) + return -ENODEV; + + cf = kcalloc(1, sizeof *cf, GFP_KERNEL); + if (!cf) + return -ENOMEM; + + cf->board = board; + cf->pdev = pdev; + dev_set_drvdata(dev, cf); + + /* CF takes over CS4, CS5, CS6 */ + csa = at91_sys_read(AT91_EBI_CSA); + at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH); + + /* force poweron defaults for these pins ... */ + (void) at91_set_A_periph(AT91_PIN_PC9, 0); /* A25/CFRNW */ + (void) at91_set_A_periph(AT91_PIN_PC10, 0); /* NCS4/CFCS */ + (void) at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */ + (void) at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ + + /* nWAIT is _not_ a default setting */ + (void) at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */ + + /* + * Static memory controller timing adjustments. + * REVISIT: these timings are in terms of MCK cycles, so + * when MCK changes (cpufreq etc) so must these values... + */ + at91_sys_write(AT91_SMC_CSR(4), AT91_SMC_ACSS_STD | AT91_SMC_DBW_16 | AT91_SMC_BAT | AT91_SMC_WSEN + | AT91_SMC_NWS_(32) /* wait states */ + | AT91_SMC_RWSETUP_(6) /* setup time */ + | AT91_SMC_RWHOLD_(4) /* hold time */ + ); + + /* must be a GPIO; ergo must trigger on both edges */ + status = request_irq(board->det_pin, at91_cf_irq, + SA_SAMPLE_RANDOM, driver_name, cf); + if (status < 0) + goto fail0; + + /* + * The card driver will request this irq later as needed. + * but it causes lots of "irqNN: nobody cared" messages + * unless we report that we handle everything (sigh). + * (Note: DK board doesn't wire the IRQ pin...) + */ + if (board->irq_pin) { + status = request_irq(board->irq_pin, at91_cf_irq, + SA_SHIRQ, driver_name, cf); + if (status < 0) + goto fail0a; + cf->socket.pci_irq = board->irq_pin; + } + else + cf->socket.pci_irq = NR_IRQS + 1; + + /* pcmcia layer only remaps "real" memory not iospace */ + cf->socket.io_offset = (unsigned long) ioremap(CF_IO_PHYS, SZ_2K); + if (!cf->socket.io_offset) + goto fail1; + + /* reserve CS4, CS5, and CS6 regions; but use just CS4 */ + if (!request_mem_region(AT91_CF_BASE, CF_SIZE, driver_name)) + goto fail1; + + pr_info("%s: irqs det #%d, io #%d\n", driver_name, + board->det_pin, board->irq_pin); + + cf->socket.owner = THIS_MODULE; + cf->socket.dev.dev = dev; + cf->socket.ops = &at91_cf_ops; + cf->socket.resource_ops = &pccard_static_ops; + cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP + | SS_CAP_MEM_ALIGN; + cf->socket.map_size = SZ_2K; + cf->socket.io[0].NumPorts = SZ_2K; + + status = pcmcia_register_socket(&cf->socket); + if (status < 0) + goto fail2; + + return 0; + +fail2: + iounmap((void __iomem *) cf->socket.io_offset); + release_mem_region(AT91_CF_BASE, CF_SIZE); +fail1: + if (board->irq_pin) + free_irq(board->irq_pin, cf); +fail0a: + free_irq(board->det_pin, cf); +fail0: + at91_sys_write(AT91_EBI_CSA, csa); + kfree(cf); + return status; +} + +static int __exit at91_cf_remove(struct device *dev) +{ + struct at91_cf_socket *cf = dev_get_drvdata(dev); + unsigned int csa; + + pcmcia_unregister_socket(&cf->socket); + free_irq(cf->board->irq_pin, cf); + free_irq(cf->board->det_pin, cf); + iounmap((void __iomem *) cf->socket.io_offset); + release_mem_region(AT91_CF_BASE, CF_SIZE); + + csa = at91_sys_read(AT91_EBI_CSA); + at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A); + + kfree(cf); + return 0; +} + +static struct device_driver at91_cf_driver = { + .name = (char *) driver_name, + .bus = &platform_bus_type, + .probe = at91_cf_probe, + .remove = __exit_p(at91_cf_remove), + .suspend = pcmcia_socket_dev_suspend, + .resume = pcmcia_socket_dev_resume, +}; + +/*--------------------------------------------------------------------------*/ + +static int __init at91_cf_init(void) +{ + return driver_register(&at91_cf_driver); +} +module_init(at91_cf_init); + +static void __exit at91_cf_exit(void) +{ + driver_unregister(&at91_cf_driver); +} +module_exit(at91_cf_exit); + +MODULE_DESCRIPTION("AT91 Compact Flash Driver"); +MODULE_AUTHOR("David Brownell"); +MODULE_LICENSE("GPL"); -- cgit v1.2.2 From 1de9cedfbdff1d8adb662cd3afc5bda66e393351 Mon Sep 17 00:00:00 2001 From: Domen Puncer Date: Mon, 6 Mar 2006 10:25:53 +0100 Subject: [PATCH] serial_cs: add Merlin U630 IDs Add Merlin U630 IDs. Signed-off-by: Domen Puncer Signed-off-by: Dominik Brodowski --- drivers/serial/serial_cs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index c30333694f..2307d9407a 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -739,6 +739,7 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_MFC_DEVICE_PROD_ID1(1, "Motorola MARQUIS", 0xf03e4e77), PCMCIA_MFC_DEVICE_PROD_ID2(1, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302), PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0301), + PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x0276), PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0039), PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0006), PCMCIA_DEVICE_MANF_CARD(0x0105, 0x410a), @@ -757,6 +758,7 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_PROD_ID14("MEGAHERTZ", "PCMCIA MODEM", 0xf510db04, 0xbd6c43ef), PCMCIA_DEVICE_PROD_ID124("TOSHIBA", "T144PF", "PCMCIA MODEM", 0xb4585a1a, 0x7271409c, 0xbd6c43ef), PCMCIA_DEVICE_PROD_ID123("FUJITSU", "FC14F ", "MBH10213", 0x6ee5a3d8, 0x30ead12b, 0xb00f05a0), + PCMCIA_DEVICE_PROD_ID123("Novatel Wireless", "Merlin UMTS Modem", "U630", 0x32607776, 0xd9e73b13, 0xe87332e), PCMCIA_DEVICE_PROD_ID13("MEGAHERTZ", "V.34 PCMCIA MODEM", 0xf510db04, 0xbb2cce4a), PCMCIA_DEVICE_PROD_ID12("Brain Boxes", "Bluetooth PC Card", 0xee138382, 0xd4ce9b02), PCMCIA_DEVICE_PROD_ID12("CIRRUS LOGIC", "FAX MODEM", 0xe625f451, 0xcecd6dfa), -- cgit v1.2.2 From 79ea24e72e59b5f0951483cc4f357afe9bf7ff89 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 31 Mar 2006 20:01:50 +0900 Subject: [PATCH] ata_piix: fix ich6/m_map_db MAP tables of ich6 and ich6m are wrong. Depending on port usage, ata_piix may fail to initialize attached devices. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/ata_piix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 2d5be84d8b..24e71b5551 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -301,7 +301,7 @@ static struct piix_map_db ich6_map_db = { .mask = 0x3, .map = { /* PM PS SM SS MAP */ - { P0, P1, P2, P3 }, /* 00b */ + { P0, P2, P1, P3 }, /* 00b */ { IDE, IDE, P1, P3 }, /* 01b */ { P0, P2, IDE, IDE }, /* 10b */ { RV, RV, RV, RV }, @@ -312,7 +312,7 @@ static struct piix_map_db ich6m_map_db = { .mask = 0x3, .map = { /* PM PS SM SS MAP */ - { P0, P1, P2, P3 }, /* 00b */ + { P0, P2, RV, RV }, /* 00b */ { RV, RV, RV, RV }, { P0, P2, IDE, IDE }, /* 10b */ { RV, RV, RV, RV }, -- cgit v1.2.2 From e4a70e76add280db6068426716a9b2a74099144f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 31 Mar 2006 20:36:47 +0900 Subject: [PATCH] libata: fix ata_qc_issue failure path On sg_err failure path, ata_qc_issue() doesn't mark the qc active before returning. This triggers WARN_ON() in __ata_qc_complete() when the qc gets completed. This patch moves ap->active_tag and QCFLAG_ACTIVE setting to the top of the function. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 21b0ed583b..eb4df01d9f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4006,6 +4006,9 @@ unsigned int ata_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; + qc->ap->active_tag = qc->tag; + qc->flags |= ATA_QCFLAG_ACTIVE; + if (ata_should_dma_map(qc)) { if (qc->flags & ATA_QCFLAG_SG) { if (ata_sg_setup(qc)) @@ -4020,9 +4023,6 @@ unsigned int ata_qc_issue(struct ata_queued_cmd *qc) ap->ops->qc_prep(qc); - qc->ap->active_tag = qc->tag; - qc->flags |= ATA_QCFLAG_ACTIVE; - return ap->ops->qc_issue(qc); sg_err: -- cgit v1.2.2 From 8e0e694a3a48212bfe29a9ad3cd592bf68dfec81 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 31 Mar 2006 20:41:11 +0900 Subject: [PATCH] libata: make ata_qc_issue complete failed qcs There is no reason for the issuer to diddle with a failed qc as the issuer has complete control over when a qc gets freed (usually in ->complete_fn). Make ata_qc_issue() responsible for completing qcs which failed to issue. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 20 +++++++++----------- drivers/scsi/libata-scsi.c | 8 ++------ drivers/scsi/libata.h | 2 +- 3 files changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index eb4df01d9f..63ae23b5c0 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -989,9 +989,7 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev, qc->private_data = &wait; qc->complete_fn = ata_qc_complete_internal; - qc->err_mask = ata_qc_issue(qc); - if (qc->err_mask) - ata_qc_complete(qc); + ata_qc_issue(qc); spin_unlock_irqrestore(&ap->host_set->lock, flags); @@ -3997,12 +3995,8 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc) * * LOCKING: * spin_lock_irqsave(host_set lock) - * - * RETURNS: - * Zero on success, AC_ERR_* mask on failure */ - -unsigned int ata_qc_issue(struct ata_queued_cmd *qc) +void ata_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; @@ -4023,14 +4017,18 @@ unsigned int ata_qc_issue(struct ata_queued_cmd *qc) ap->ops->qc_prep(qc); - return ap->ops->qc_issue(qc); + qc->err_mask |= ap->ops->qc_issue(qc); + if (unlikely(qc->err_mask)) + goto err; + return; sg_err: qc->flags &= ~ATA_QCFLAG_DMAMAP; - return AC_ERR_SYSTEM; + qc->err_mask |= AC_ERR_SYSTEM; +err: + ata_qc_complete(qc); } - /** * ata_qc_issue_prot - issue taskfile to device in proto-dependent manner * @qc: command to issue to device diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 628191bfd9..53f5b0d916 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -1431,9 +1431,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, goto early_finish; /* select device, send command to hardware */ - qc->err_mask = ata_qc_issue(qc); - if (qc->err_mask) - ata_qc_complete(qc); + ata_qc_issue(qc); VPRINTK("EXIT\n"); return; @@ -2199,9 +2197,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) qc->complete_fn = atapi_sense_complete; - qc->err_mask = ata_qc_issue(qc); - if (qc->err_mask) - ata_qc_complete(qc); + ata_qc_issue(qc); DPRINTK("EXIT\n"); } diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 65f52beea8..1c755b1452 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -47,7 +47,7 @@ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); extern void ata_port_flush_task(struct ata_port *ap); extern void ata_qc_free(struct ata_queued_cmd *qc); -extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc); +extern void ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); -- cgit v1.2.2 From be9a50c8524b53003e5fa32f072945772ffd13a5 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 31 Mar 2006 22:48:52 +0900 Subject: [PATCH] libata: fix ata_xfer_tbl termination ata_xfer_tbl is terminated by entry with -1 as ->shift. However, ->shift was unsigned int making the termination condition bogus. This patch converts ->shift and ->bits to int. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 63ae23b5c0..e63c1ff1e1 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -278,7 +278,7 @@ static void ata_unpack_xfermask(unsigned int xfer_mask, } static const struct ata_xfer_ent { - unsigned int shift, bits; + int shift, bits; u8 base; } ata_xfer_tbl[] = { { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 }, -- cgit v1.2.2 From 5f2a71fcb7995633b335a1e380ac63a968e61320 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 15 Jan 2006 09:32:39 +0100 Subject: [PATCH] pcmcia: add pcmcia_disable_device pcmcia_disable_device(struct pcmcia_device *p_dev) performs the necessary cleanups upon device or driver removal: it calls the appropriate pcmcia_release_* functions, and can replace (most) of the current drivers' _release() functions. Signed-off-by: Dominik Brodowski --- drivers/bluetooth/bluecard_cs.c | 8 +--- drivers/bluetooth/bt3c_cs.c | 8 +--- drivers/bluetooth/btuart_cs.c | 8 +--- drivers/bluetooth/dtl1_cs.c | 8 +--- drivers/char/pcmcia/cm4000_cs.c | 3 +- drivers/char/pcmcia/cm4040_cs.c | 3 +- drivers/char/pcmcia/synclink_cs.c | 10 +---- drivers/ide/legacy/ide-cs.c | 8 +--- drivers/isdn/hardware/avm/avm_cs.c | 12 +----- drivers/isdn/hisax/avma1_cs.c | 17 +++----- drivers/isdn/hisax/elsa_cs.c | 12 +----- drivers/isdn/hisax/sedlbauer_cs.c | 17 +------- drivers/isdn/hisax/teles_cs.c | 12 +----- drivers/net/pcmcia/3c574_cs.c | 8 +--- drivers/net/pcmcia/3c589_cs.c | 8 +--- drivers/net/pcmcia/axnet_cs.c | 8 +--- drivers/net/pcmcia/com20020_cs.c | 12 +----- drivers/net/pcmcia/fmvj18x_cs.c | 12 +----- drivers/net/pcmcia/ibmtr_cs.c | 23 +++++------ drivers/net/pcmcia/nmclan_cs.c | 10 +---- drivers/net/pcmcia/pcnet_cs.c | 15 +++---- drivers/net/pcmcia/smc91c92_cs.c | 21 ++++------ drivers/net/pcmcia/xirc2ps_cs.c | 22 ++++------ drivers/net/wireless/airo_cs.c | 19 +-------- drivers/net/wireless/atmel_cs.c | 21 +++------- drivers/net/wireless/hostap/hostap_cs.c | 11 +---- drivers/net/wireless/netwave_cs.c | 19 +++------ drivers/net/wireless/orinoco_cs.c | 8 +--- drivers/net/wireless/spectrum_cs.c | 8 +--- drivers/net/wireless/wavelan_cs.c | 18 +++------ drivers/net/wireless/wl3501_cs.c | 10 +---- drivers/parport/parport_cs.c | 24 +++++------ drivers/pcmcia/pcmcia_resource.c | 71 +++++++++++++++++++-------------- drivers/scsi/pcmcia/aha152x_stub.c | 8 +--- drivers/scsi/pcmcia/fdomain_stub.c | 17 +++----- drivers/scsi/pcmcia/nsp_cs.c | 11 +---- drivers/scsi/pcmcia/qlogic_stub.c | 9 +---- drivers/scsi/pcmcia/sym53c500_cs.c | 8 +--- drivers/serial/serial_cs.c | 7 +--- 39 files changed, 145 insertions(+), 389 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 9888bc1517..128e41609a 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -1002,13 +1002,7 @@ static void bluecard_release(dev_link_t *link) del_timer(&(info->timer)); - link->dev = NULL; - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } static int bluecard_suspend(struct pcmcia_device *dev) diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 7e21b1ff27..ac1410c0a4 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -839,13 +839,7 @@ static void bt3c_release(dev_link_t *link) if (link->state & DEV_PRESENT) bt3c_close(info); - link->dev = NULL; - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } static int bt3c_suspend(struct pcmcia_device *dev) diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 7b4bff4cfa..8cd54bb199 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -768,13 +768,7 @@ static void btuart_release(dev_link_t *link) if (link->state & DEV_PRESENT) btuart_close(info); - link->dev = NULL; - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } static int btuart_suspend(struct pcmcia_device *dev) diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 0449bc45ae..efbc8a543a 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -720,13 +720,7 @@ static void dtl1_release(dev_link_t *link) if (link->state & DEV_PRESENT) dtl1_close(info); - link->dev = NULL; - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } static int dtl1_suspend(struct pcmcia_device *dev) diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 5fdf185154..3ddd3da9e7 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -1899,8 +1899,7 @@ static int cm4000_resume(struct pcmcia_device *p_dev) static void cm4000_release(dev_link_t *link) { cmm_cm4000_release(link->priv); /* delay release until device closed */ - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); + pcmcia_disable_device(link->handle); } static int cm4000_attach(struct pcmcia_device *p_dev) diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 466e33bab0..1c355bd2be 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -654,8 +654,7 @@ static int reader_resume(struct pcmcia_device *p_dev) static void reader_release(dev_link_t *link) { cm4040_reader_release(link->priv); - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); + pcmcia_disable_device(link->handle); } static int reader_attach(struct pcmcia_device *p_dev) diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index e6b714b639..371d10b780 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -710,15 +710,7 @@ static void mgslpc_release(u_long arg) if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_release(0x%p)\n", link); - /* Unlink the device chain */ - link->dev = NULL; - link->state &= ~DEV_CONFIG; - - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); + pcmcia_disable_device(link->handle); } static void mgslpc_detach(struct pcmcia_device *p_dev) diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 6213bd3cae..024aad6164 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -369,14 +369,8 @@ void ide_release(dev_link_t *link) ide_unregister(info->hd); } info->ndev = 0; - link->dev = NULL; - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } /* ide_release */ static int ide_suspend(struct pcmcia_device *dev) diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 2a2b03ff09..f3889bdc8e 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -367,16 +367,8 @@ found_port: static void avmcs_release(dev_link_t *link) { - b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ); - - /* Unlink the device chain */ - link->dev = NULL; - - /* Don't bother checking to see if these succeed or not */ - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ); + pcmcia_disable_device(link->handle); } /* avmcs_release */ static int avmcs_suspend(struct pcmcia_device *dev) diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 969da40c42..729c2de0bc 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -373,21 +373,14 @@ found_port: static void avma1cs_release(dev_link_t *link) { - local_info_t *local = link->priv; + local_info_t *local = link->priv; - DEBUG(0, "avma1cs_release(0x%p)\n", link); + DEBUG(0, "avma1cs_release(0x%p)\n", link); - /* no unregister function with hisax */ - HiSax_closecard(local->node.minor); + /* now unregister function with hisax */ + HiSax_closecard(local->node.minor); - /* Unlink the device chain */ - link->dev = NULL; - - /* Don't bother checking to see if these succeed or not */ - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } /* avma1cs_release */ static int avma1cs_suspend(struct pcmcia_device *dev) diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 062fb8f073..60c75c7c01 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -380,16 +380,8 @@ static void elsa_cs_release(dev_link_t *link) HiSax_closecard(local->cardnr); } } - /* Unlink the device chain */ - link->dev = NULL; - - /* Don't bother checking to see if these succeed or not */ - if (link->win) - pcmcia_release_window(link->win); - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + + pcmcia_disable_device(link->handle); } /* elsa_cs_release */ static int elsa_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 6f5213a18a..e59539157d 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -467,23 +467,8 @@ static void sedlbauer_release(dev_link_t *link) HiSax_closecard(local->cardnr); } } - /* Unlink the device chain */ - link->dev = NULL; - /* - In a normal driver, additional code may be needed to release - other kernel data structures associated with this device. - */ - - /* Don't bother checking to see if these succeed or not */ - if (link->win) - pcmcia_release_window(link->win); - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } /* sedlbauer_release */ static int sedlbauer_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 4e5c14c724..7945fd6462 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -371,16 +371,8 @@ static void teles_cs_release(dev_link_t *link) HiSax_closecard(local->cardnr); } } - /* Unlink the device chain */ - link->dev = NULL; - - /* Don't bother checking to see if these succeed or not */ - if (link->win) - pcmcia_release_window(link->win); - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + + pcmcia_disable_device(link->handle); } /* teles_cs_release */ static int teles_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index ce90becb8b..1799660bdc 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -511,13 +511,7 @@ failed: static void tc574_release(dev_link_t *link) { - DEBUG(0, "3c574_release(0x%p)\n", link); - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } static int tc574_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 3dba50849d..e361538517 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -386,13 +386,7 @@ failed: static void tc589_release(dev_link_t *link) { - DEBUG(0, "3c589_release(0x%p)\n", link); - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } static int tc589_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 1cc94b2d76..9b9c0f19b2 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -456,13 +456,7 @@ failed: static void axnet_release(dev_link_t *link) { - DEBUG(0, "axnet_release(0x%p)\n", link); - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } static int axnet_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 2827a48ea3..a0ec5e7aac 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -377,16 +377,8 @@ failed: static void com20020_release(dev_link_t *link) { - - DEBUG(1,"release...\n"); - - DEBUG(0, "com20020_release(0x%p)\n", link); - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); + DEBUG(0, "com20020_release(0x%p)\n", link); + pcmcia_disable_device(link->handle); } static int com20020_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index b7ac14ba88..6b435e9406 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -674,16 +674,8 @@ static int fmvj18x_setup_mfc(dev_link_t *link) static void fmvj18x_release(dev_link_t *link) { - - DEBUG(0, "fmvj18x_release(0x%p)\n", link); - - /* Don't bother checking to see if these succeed or not */ - pcmcia_release_window(link->win); - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + DEBUG(0, "fmvj18x_release(0x%p)\n", link); + pcmcia_disable_device(link->handle); } static int fmvj18x_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index b9c7e39576..1948a0bc19 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -348,22 +348,17 @@ failed: static void ibmtr_release(dev_link_t *link) { - ibmtr_dev_t *info = link->priv; - struct net_device *dev = info->dev; - - DEBUG(0, "ibmtr_release(0x%p)\n", link); + ibmtr_dev_t *info = link->priv; + struct net_device *dev = info->dev; - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - if (link->win) { - struct tok_info *ti = netdev_priv(dev); - iounmap(ti->mmio); - pcmcia_release_window(link->win); - pcmcia_release_window(info->sram_win_handle); - } + DEBUG(0, "ibmtr_release(0x%p)\n", link); - link->state &= ~DEV_CONFIG; + if (link->win) { + struct tok_info *ti = netdev_priv(dev); + iounmap(ti->mmio); + pcmcia_release_window(info->sram_win_handle); + } + pcmcia_disable_device(link->handle); } static int ibmtr_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 787176c57f..76ef453d17 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -765,14 +765,8 @@ nmclan_release ---------------------------------------------------------------------------- */ static void nmclan_release(dev_link_t *link) { - - DEBUG(0, "nmclan_release(0x%p)\n", link); - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + DEBUG(0, "nmclan_release(0x%p)\n", link); + pcmcia_disable_device(link->handle); } static int nmclan_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index b46e5f703e..52f44bdff1 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -732,19 +732,14 @@ failed: static void pcnet_release(dev_link_t *link) { - pcnet_dev_t *info = PRIV(link->priv); + pcnet_dev_t *info = PRIV(link->priv); - DEBUG(0, "pcnet_release(0x%p)\n", link); + DEBUG(0, "pcnet_release(0x%p)\n", link); - if (info->flags & USE_SHMEM) { - iounmap(info->base); - pcmcia_release_window(link->win); - } - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); + if (info->flags & USE_SHMEM) + iounmap(info->base); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } /*====================================================================== diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 8839c4faaf..56700b154d 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1181,20 +1181,13 @@ config_failed: /* CS_EXIT_TEST() calls jump to here... */ static void smc91c92_release(dev_link_t *link) { - - DEBUG(0, "smc91c92_release(0x%p)\n", link); - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - if (link->win) { - struct net_device *dev = link->priv; - struct smc_private *smc = netdev_priv(dev); - iounmap(smc->base); - pcmcia_release_window(link->win); - } - - link->state &= ~DEV_CONFIG; + DEBUG(0, "smc91c92_release(0x%p)\n", link); + if (link->win) { + struct net_device *dev = link->priv; + struct smc_private *smc = netdev_priv(dev); + iounmap(smc->base); + } + pcmcia_disable_device(link->handle); } /*====================================================================== diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index eed496803f..2b57a87371 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1090,21 +1090,15 @@ xirc2ps_config(dev_link_t * link) static void xirc2ps_release(dev_link_t *link) { + DEBUG(0, "release(0x%p)\n", link); - DEBUG(0, "release(0x%p)\n", link); - - if (link->win) { - struct net_device *dev = link->priv; - local_info_t *local = netdev_priv(dev); - if (local->dingo) - iounmap(local->dingo_ccr - 0x0800); - pcmcia_release_window(link->win); - } - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; - + if (link->win) { + struct net_device *dev = link->priv; + local_info_t *local = netdev_priv(dev); + if (local->dingo) + iounmap(local->dingo_ccr - 0x0800); + } + pcmcia_disable_device(link->handle); } /* xirc2ps_release */ /*====================================================================*/ diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index a496460ce2..489ef7f3d9 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -429,24 +429,7 @@ static void airo_config(dev_link_t *link) static void airo_release(dev_link_t *link) { DEBUG(0, "airo_release(0x%p)\n", link); - - /* Unlink the device chain */ - link->dev = NULL; - - /* - In a normal driver, additional code may be needed to release - other kernel data structures associated with this device. - */ - - /* Don't bother checking to see if these succeed or not */ - if (link->win) - pcmcia_release_window(link->win); - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } static int airo_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index d6f4a5a3e5..1da8e6197f 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -418,23 +418,14 @@ static void atmel_config(dev_link_t *link) static void atmel_release(dev_link_t *link) { struct net_device *dev = ((local_info_t*)link->priv)->eth_dev; - + DEBUG(0, "atmel_release(0x%p)\n", link); - - /* Unlink the device chain */ - link->dev = NULL; - - if (dev) + + if (dev) stop_atmel_card(dev); - ((local_info_t*)link->priv)->eth_dev = NULL; - - /* Don't bother checking to see if these succeed or not */ - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + ((local_info_t*)link->priv)->eth_dev = NULL; + + pcmcia_disable_device(link->handle); } static int atmel_suspend(struct pcmcia_device *dev) diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index d335b25092..7a1023f387 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -804,16 +804,7 @@ static void prism2_release(u_long arg) iface->local->shutdown = 1; } - if (link->win) - pcmcia_release_window(link->win); - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; - + pcmcia_disable_device(link->handle); PDEBUG(DEBUG_FLOW, "release - done\n"); } diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 75ce6ddb0c..dfb47ac9da 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -869,21 +869,14 @@ failed: */ static void netwave_release(dev_link_t *link) { - struct net_device *dev = link->priv; - netwave_private *priv = netdev_priv(dev); - - DEBUG(0, "netwave_release(0x%p)\n", link); + struct net_device *dev = link->priv; + netwave_private *priv = netdev_priv(dev); - /* Don't bother checking to see if these succeed or not */ - if (link->win) { - iounmap(priv->ramBase); - pcmcia_release_window(link->win); - } - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); + DEBUG(0, "netwave_release(0x%p)\n", link); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); + if (link->win) + iounmap(priv->ramBase); } static int netwave_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index ec6f2a4889..7fdc4ff551 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -416,13 +416,7 @@ orinoco_cs_release(dev_link_t *link) priv->hw_unavailable++; spin_unlock_irqrestore(&priv->lock, flags); - /* Don't bother checking to see if these succeed or not */ - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); if (priv->hw.iobase) ioport_unmap(priv->hw.iobase); } /* orinoco_cs_release */ diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 5fa6fbe35b..78320c1a1c 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -894,13 +894,7 @@ spectrum_cs_release(dev_link_t *link) priv->hw_unavailable++; spin_unlock_irqrestore(&priv->lock, flags); - /* Don't bother checking to see if these succeed or not */ - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); if (priv->hw.iobase) ioport_unmap(priv->hw.iobase); } /* spectrum_cs_release */ diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 98122f3a4b..696aeb9d8f 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4098,24 +4098,18 @@ wv_pcmcia_config(dev_link_t * link) static void wv_pcmcia_release(dev_link_t *link) { - struct net_device * dev = (struct net_device *) link->priv; - net_local * lp = netdev_priv(dev); + struct net_device * dev = (struct net_device *) link->priv; + net_local * lp = netdev_priv(dev); #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link); + printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link); #endif - /* Don't bother checking to see if these succeed or not */ - iounmap(lp->mem); - pcmcia_release_window(link->win); - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + iounmap(lp->mem); + pcmcia_disable_device(link->handle); #ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); + printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); #endif } diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 48e10b0c7e..0c81b3e7d7 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -2149,16 +2149,10 @@ static void wl3501_release(dev_link_t *link) struct net_device *dev = link->priv; /* Unlink the device chain */ - if (link->dev) { + if (link->dev) unregister_netdev(dev); - link->dev = NULL; - } - /* Don't bother checking to see if these succeed or not */ - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } static int wl3501_suspend(struct pcmcia_device *p_dev) diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index d0fc8be569..7edd7ef6c3 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -267,23 +267,17 @@ failed: void parport_cs_release(dev_link_t *link) { - parport_info_t *info = link->priv; - - DEBUG(0, "parport_release(0x%p)\n", link); + parport_info_t *info = link->priv; - if (info->ndev) { - struct parport *p = info->port; - parport_pc_unregister_port(p); - } - info->ndev = 0; - link->dev = NULL; - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + DEBUG(0, "parport_release(0x%p)\n", link); + + if (info->ndev) { + struct parport *p = info->port; + parport_pc_unregister_port(p); + } + info->ndev = 0; + pcmcia_disable_device(link->handle); } /* parport_cs_release */ static int parport_suspend(struct pcmcia_device *dev) diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index dbd5571064..555c8698eb 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -451,20 +451,20 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) { pccard_io_map io = { 0, 0, 0, 0, 1 }; struct pcmcia_socket *s = p_dev->socket; + config_t *c = p_dev->function_config; int i; - if (!(p_dev->state & CLIENT_CONFIG_LOCKED)) - return CS_BAD_HANDLE; - p_dev->state &= ~CLIENT_CONFIG_LOCKED; - - if (!(p_dev->state & CLIENT_STALE)) { - config_t *c = p_dev->function_config; + if (p_dev->state & CLIENT_CONFIG_LOCKED) { + p_dev->state &= ~CLIENT_CONFIG_LOCKED; if (--(s->lock_count) == 0) { s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ s->socket.Vpp = 0; s->socket.io_irq = 0; s->ops->set_socket(s, &s->socket); } + } + if (c->state & CONFIG_LOCKED) { + c->state &= ~CONFIG_LOCKED; if (c->state & CONFIG_IO_REQ) for (i = 0; i < MAX_IO_WIN; i++) { if (!s->io[i].res) @@ -475,7 +475,6 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) io.map = i; s->ops->set_io_map(s, &io); } - c->state &= ~CONFIG_LOCKED; } return CS_SUCCESS; @@ -494,22 +493,20 @@ EXPORT_SYMBOL(pcmcia_release_configuration); int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) { struct pcmcia_socket *s = p_dev->socket; + config_t *c = p_dev->function_config; if (!(p_dev->state & CLIENT_IO_REQ)) return CS_BAD_HANDLE; + p_dev->state &= ~CLIENT_IO_REQ; - if (!(p_dev->state & CLIENT_STALE)) { - config_t *c = p_dev->function_config; - if (c->state & CONFIG_LOCKED) - return CS_CONFIGURATION_LOCKED; - if ((c->io.BasePort1 != req->BasePort1) || - (c->io.NumPorts1 != req->NumPorts1) || - (c->io.BasePort2 != req->BasePort2) || - (c->io.NumPorts2 != req->NumPorts2)) - return CS_BAD_ARGS; - c->state &= ~CONFIG_IO_REQ; - } + if ((c->io.BasePort1 != req->BasePort1) || + (c->io.NumPorts1 != req->NumPorts1) || + (c->io.BasePort2 != req->BasePort2) || + (c->io.NumPorts2 != req->NumPorts2)) + return CS_BAD_ARGS; + + c->state &= ~CONFIG_IO_REQ; release_io_space(s, req->BasePort1, req->NumPorts1); if (req->NumPorts2) @@ -523,22 +520,21 @@ EXPORT_SYMBOL(pcmcia_release_io); int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) { struct pcmcia_socket *s = p_dev->socket; + config_t *c= p_dev->function_config; + if (!(p_dev->state & CLIENT_IRQ_REQ)) return CS_BAD_HANDLE; p_dev->state &= ~CLIENT_IRQ_REQ; - if (!(p_dev->state & CLIENT_STALE)) { - config_t *c= p_dev->function_config; - if (c->state & CONFIG_LOCKED) - return CS_CONFIGURATION_LOCKED; - if (c->irq.Attributes != req->Attributes) - return CS_BAD_ATTRIBUTE; - if (s->irq.AssignedIRQ != req->AssignedIRQ) - return CS_BAD_IRQ; - if (--s->irq.Config == 0) { - c->state &= ~CONFIG_IRQ_REQ; - s->irq.AssignedIRQ = 0; - } + if (c->state & CONFIG_LOCKED) + return CS_CONFIGURATION_LOCKED; + if (c->irq.Attributes != req->Attributes) + return CS_BAD_ATTRIBUTE; + if (s->irq.AssignedIRQ != req->AssignedIRQ) + return CS_BAD_IRQ; + if (--s->irq.Config == 0) { + c->state &= ~CONFIG_IRQ_REQ; + s->irq.AssignedIRQ = 0; } if (req->Attributes & IRQ_HANDLE_PRESENT) { @@ -929,3 +925,18 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h return CS_SUCCESS; } /* pcmcia_request_window */ EXPORT_SYMBOL(pcmcia_request_window); + +void pcmcia_disable_device(struct pcmcia_device *p_dev) { + if (!p_dev->instance) + return; + + pcmcia_release_configuration(p_dev); + pcmcia_release_io(p_dev, &p_dev->instance->io); + pcmcia_release_irq(p_dev, &p_dev->instance->irq); + if (&p_dev->instance->win) + pcmcia_release_window(p_dev->instance->win); + + p_dev->instance->dev = NULL; + p_dev->instance->state &= ~DEV_CONFIG; +} +EXPORT_SYMBOL(pcmcia_disable_device); diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 5609847e25..e7f9d26a0d 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -248,13 +248,7 @@ static void aha152x_release_cs(dev_link_t *link) scsi_info_t *info = link->priv; aha152x_release(info->host); - link->dev = NULL; - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } static int aha152x_suspend(struct pcmcia_device *dev) diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 788c58d805..fb7221cf51 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -209,20 +209,13 @@ cs_failed: static void fdomain_release(dev_link_t *link) { - scsi_info_t *info = link->priv; - - DEBUG(0, "fdomain_release(0x%p)\n", link); - - scsi_remove_host(info->host); - link->dev = NULL; - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); + scsi_info_t *info = link->priv; - scsi_unregister(info->host); + DEBUG(0, "fdomain_release(0x%p)\n", link); - link->state &= ~DEV_CONFIG; + scsi_remove_host(info->host); + pcmcia_disable_device(link->handle); + scsi_unregister(info->host); } /*====================================================================*/ diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 9e3ab3fd53..dd383c538d 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1974,16 +1974,9 @@ static void nsp_cs_release(dev_link_t *link) if (data != NULL) { iounmap((void *)(data->MmioAddress)); } - pcmcia_release_window(link->win); } - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) { - pcmcia_release_io(link->handle, &link->io); - } - if (link->irq.AssignedIRQ) { - pcmcia_release_irq(link->handle, &link->irq); - } - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2)) if (info->host != NULL) { scsi_host_put(info->host); diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index dce7e687fd..70269fc10f 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -289,6 +289,7 @@ out: cs_failed: cs_error(link->handle, last_fn, last_ret); link->dev = NULL; + pcmcia_release_configuration(link->handle); pcmcia_release_io(link->handle, &link->io); pcmcia_release_irq(link->handle, &link->irq); @@ -306,17 +307,11 @@ static void qlogic_release(dev_link_t *link) DEBUG(0, "qlogic_release(0x%p)\n", link); scsi_remove_host(info->host); - link->dev = NULL; free_irq(link->irq.AssignedIRQ, info->host); - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); + pcmcia_disable_device(link->handle); scsi_host_put(info->host); - - link->state &= ~DEV_CONFIG; } /*====================================================================*/ diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 3a4dd6f5b8..42d002b6d1 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -550,13 +550,7 @@ SYM53C500_release(dev_link_t *link) if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); - link->dev = NULL; - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); scsi_host_put(shost); } /* SYM53C500_release */ diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 2307d9407a..ff38820a03 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -141,11 +141,8 @@ static void serial_remove(dev_link_t *link) info->link.dev = NULL; - if (!info->slave) { - pcmcia_release_configuration(info->link.handle); - pcmcia_release_io(info->link.handle, &info->link.io); - pcmcia_release_irq(info->link.handle, &info->link.irq); - } + if (!info->slave) + pcmcia_disable_device(link->handle); info->link.state &= ~DEV_CONFIG; } -- cgit v1.2.2 From 50db3fdbbc98260fb538c1cc3f8cc597ba7bffe7 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 15 Jan 2006 10:05:19 +0100 Subject: [PATCH] pcmcia: convert remaining users of pcmcia_release_io and _irq Convert the remaining drivers which use pcmcia_release_io or pcmcia_release_irq, and remove the EXPORT of these symbols. Signed-off-by: Dominik Brodowski --- drivers/isdn/hardware/avm/avm_cs.c | 10 +++++----- drivers/isdn/hisax/avma1_cs.c | 8 ++++---- drivers/isdn/hisax/sedlbauer_cs.c | 8 ++------ drivers/net/pcmcia/smc91c92_cs.c | 10 ++++++++-- drivers/net/wireless/orinoco_cs.c | 3 +-- drivers/net/wireless/ray_cs.c | 8 +------- drivers/net/wireless/spectrum_cs.c | 3 +-- drivers/pcmcia/pcmcia_resource.c | 3 --- drivers/scsi/pcmcia/nsp_cs.c | 5 +---- drivers/scsi/pcmcia/qlogic_stub.c | 7 +------ drivers/telephony/ixj_pcmcia.c | 5 +---- drivers/usb/host/sl811_cs.c | 14 ++------------ 12 files changed, 27 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index f3889bdc8e..5f70661994 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -284,25 +284,25 @@ found_port: cs_error(link->handle, RequestIO, i); break; } - + /* * allocate an interrupt line */ i = pcmcia_request_irq(link->handle, &link->irq); if (i != CS_SUCCESS) { cs_error(link->handle, RequestIRQ, i); - pcmcia_release_io(link->handle, &link->io); + /* undo */ + pcmcia_disable_device(link->handle); break; } - + /* * configure the PCMCIA socket */ i = pcmcia_request_configuration(link->handle, &link->conf); if (i != CS_SUCCESS) { cs_error(link->handle, RequestConfiguration, i); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); + pcmcia_disable_device(link->handle); break; } diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 729c2de0bc..845fa14e1b 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -313,18 +313,18 @@ found_port: i = pcmcia_request_irq(link->handle, &link->irq); if (i != CS_SUCCESS) { cs_error(link->handle, RequestIRQ, i); - pcmcia_release_io(link->handle, &link->io); + /* undo */ + pcmcia_disable_device(link->handle); break; } - + /* * configure the PCMCIA socket */ i = pcmcia_request_configuration(link->handle, &link->conf); if (i != CS_SUCCESS) { cs_error(link->handle, RequestConfiguration, i); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); + pcmcia_disable_device(link->handle); break; } diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index e59539157d..fd0f127e40 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -374,15 +374,11 @@ static void sedlbauer_config(dev_link_t *link) } /* If we got this far, we're cool! */ break; - + next_entry: -/* new in dummy.cs 2001/01/28 MN - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); -*/ CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } - + /* Allocate an interrupt line. Note that this does not assign a handler to the interrupt, unless the 'Handler' member of the diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 56700b154d..03b1d8fbe7 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -965,10 +966,15 @@ static int check_sig(dev_link_t *link) if (width) { printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); + /* call pcmcia_release_configuration() in _suspend */ smc91c92_suspend(link->handle); - pcmcia_release_io(link->handle, &link->io); + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - pcmcia_request_io(link->handle, &link->io); + link->handle->socket->io[0].res->flags &= ~IO_DATA_PATH_WIDTH; + link->handle->socket->io[0].res->flags |= IO_DATA_PATH_WIDTH_8; + + /* call pcmcia_request_configuration() in _resume, it handles the + * flag update */ smc91c92_resume(link->handle); return check_sig(link); } diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 7fdc4ff551..0ce4165efc 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -317,8 +317,7 @@ orinoco_cs_config(dev_link_t *link) break; next_entry: - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); + pcmcia_disable_device(handle); last_ret = pcmcia_get_next_tuple(handle, &tuple); if (last_ret == CS_NO_MORE_ITEMS) { printk(KERN_ERR PFX "GetNextTuple(): No matching " diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 7880d8c31a..fc81ac6700 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -849,22 +849,16 @@ static void ray_release(dev_link_t *link) DEBUG(1, "ray_release(0x%p)\n", link); del_timer(&local->timer); - link->state &= ~DEV_CONFIG; iounmap(local->sram); iounmap(local->rmem); iounmap(local->amem); /* Do bother checking to see if these succeed or not */ - i = pcmcia_release_window(link->win); - if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(link->win) ret = %x\n",i); i = pcmcia_release_window(local->amem_handle); if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i); i = pcmcia_release_window(local->rmem_handle); if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i); - i = pcmcia_release_configuration(link->handle); - if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseConfiguration ret = %x\n",i); - i = pcmcia_release_irq(link->handle, &link->irq); - if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i); + pcmcia_disable_device(link->handle); DEBUG(2,"ray_release ending\n"); } diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 78320c1a1c..b7ed99f8d3 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -790,8 +790,7 @@ spectrum_cs_config(dev_link_t *link) break; next_entry: - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); + pcmcia_disable_device(handle); last_ret = pcmcia_get_next_tuple(handle, &tuple); if (last_ret == CS_NO_MORE_ITEMS) { printk(KERN_ERR PFX "GetNextTuple(): No matching " diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 555c8698eb..f4dcea6ac4 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -514,7 +514,6 @@ int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) return CS_SUCCESS; } /* pcmcia_release_io */ -EXPORT_SYMBOL(pcmcia_release_io); int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) @@ -547,7 +546,6 @@ int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) return CS_SUCCESS; } /* pcmcia_release_irq */ -EXPORT_SYMBOL(pcmcia_release_irq); int pcmcia_release_window(window_handle_t win) @@ -937,6 +935,5 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) { pcmcia_release_window(p_dev->instance->win); p_dev->instance->dev = NULL; - p_dev->instance->state &= ~DEV_CONFIG; } EXPORT_SYMBOL(pcmcia_disable_device); diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index dd383c538d..d469e0d162 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1802,10 +1802,7 @@ static void nsp_cs_config(dev_link_t *link) next_entry: nsp_dbg(NSP_DEBUG_INIT, "next"); - - if (link->io.NumPorts1) { - pcmcia_release_io(link->handle, &link->io); - } + pcmcia_disable_device(handle); CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); } diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 70269fc10f..1e27059cd4 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -288,12 +288,7 @@ out: cs_failed: cs_error(link->handle, last_fn, last_ret); - link->dev = NULL; - - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); return; } /* qlogic_config */ diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index d3a7b0c3d3..fe3cde0da8 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -229,10 +229,7 @@ static void ixj_cs_release(dev_link_t *link) ixj_info_t *info = link->priv; DEBUG(0, "ixj_cs_release(0x%p)\n", link); info->ndev = 0; - link->dev = NULL; - pcmcia_release_configuration(link->handle); - pcmcia_release_io(link->handle, &link->io); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } static int ixj_suspend(struct pcmcia_device *dev) diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 134d200012..ee811673d9 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -154,19 +154,10 @@ static void sl811_cs_detach(struct pcmcia_device *p_dev) static void sl811_cs_release(dev_link_t * link) { - DBG(0, "sl811_cs_release(0x%p)\n", link); - /* Unlink the device chain */ - link->dev = NULL; - + pcmcia_disable_device(link->handle); platform_device_unregister(&platform_dev); - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; } static void sl811_cs_config(dev_link_t *link) @@ -260,8 +251,7 @@ static void sl811_cs_config(dev_link_t *link) break; next_entry: - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); + pcmcia_disable_device(handle); last_ret = pcmcia_get_next_tuple(handle, &tuple); } -- cgit v1.2.2 From 8661bb5b4af1849c1f5a4e80c4e275fd13c155d6 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Thu, 2 Mar 2006 00:02:33 +0100 Subject: [PATCH] pcmcia: default suspend and resume handling In all but one case, the suspend and resume functions of PCMCIA drivers contain mostly of calls to pcmcia_release_configuration() and pcmcia_request_configuration(). Therefore, move this code out of the drivers and into the core. Signed-off-by: Dominik Brodowski --- drivers/bluetooth/bluecard_cs.c | 24 --------------------- drivers/bluetooth/bt3c_cs.c | 24 --------------------- drivers/bluetooth/btuart_cs.c | 25 ---------------------- drivers/bluetooth/dtl1_cs.c | 24 --------------------- drivers/char/pcmcia/cm4000_cs.c | 9 -------- drivers/char/pcmcia/cm4040_cs.c | 24 --------------------- drivers/char/pcmcia/synclink_cs.c | 6 ------ drivers/ide/legacy/ide-cs.c | 23 -------------------- drivers/isdn/hardware/avm/avm_cs.c | 38 --------------------------------- drivers/isdn/hisax/avma1_cs.c | 26 +--------------------- drivers/isdn/hisax/elsa_cs.c | 6 ------ drivers/isdn/hisax/sedlbauer_cs.c | 6 ------ drivers/isdn/hisax/teles_cs.c | 6 ------ drivers/net/pcmcia/3c574_cs.c | 18 +++++----------- drivers/net/pcmcia/3c589_cs.c | 18 +++++----------- drivers/net/pcmcia/axnet_cs.c | 18 +++++----------- drivers/net/pcmcia/com20020_cs.c | 23 ++++++-------------- drivers/net/pcmcia/fmvj18x_cs.c | 19 +++++------------ drivers/net/pcmcia/ibmtr_cs.c | 20 ++++++----------- drivers/net/pcmcia/nmclan_cs.c | 19 +++++------------ drivers/net/pcmcia/pcnet_cs.c | 20 ++++++----------- drivers/net/pcmcia/smc91c92_cs.c | 2 -- drivers/net/pcmcia/xirc2ps_cs.c | 16 ++++---------- drivers/net/wireless/airo_cs.c | 9 ++------ drivers/net/wireless/atmel_cs.c | 7 +----- drivers/net/wireless/hostap/hostap_cs.c | 6 ------ drivers/net/wireless/netwave_cs.c | 18 +++++----------- drivers/net/wireless/orinoco_cs.c | 8 ------- drivers/net/wireless/ray_cs.c | 22 ++++++------------- drivers/net/wireless/spectrum_cs.c | 7 ------ drivers/net/wireless/wavelan_cs.c | 24 ++++++--------------- drivers/net/wireless/wl3501_cs.c | 18 +++++----------- drivers/parport/parport_cs.c | 23 -------------------- drivers/pcmcia/ds.c | 30 ++++++++++++++++++++++---- drivers/scsi/pcmcia/aha152x_stub.c | 18 +--------------- drivers/scsi/pcmcia/fdomain_stub.c | 17 +-------------- drivers/scsi/pcmcia/nsp_cs.c | 10 --------- drivers/scsi/pcmcia/qlogic_stub.c | 13 ----------- drivers/scsi/pcmcia/sym53c500_cs.c | 15 ------------- drivers/serial/serial_cs.c | 9 ++------ drivers/telephony/ixj_pcmcia.c | 24 --------------------- drivers/usb/host/sl811_cs.c | 24 --------------------- 42 files changed, 104 insertions(+), 612 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 128e41609a..bb833b251b 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -1005,28 +1005,6 @@ static void bluecard_release(dev_link_t *link) pcmcia_disable_device(link->handle); } -static int bluecard_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int bluecard_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (DEV_OK(link)) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} - static struct pcmcia_device_id bluecard_ids[] = { PCMCIA_DEVICE_PROD_ID12("BlueCard", "LSE041", 0xbaf16fbf, 0x657cc15e), PCMCIA_DEVICE_PROD_ID12("BTCFCARD", "LSE139", 0xe3987764, 0x2524b59c), @@ -1043,8 +1021,6 @@ static struct pcmcia_driver bluecard_driver = { .probe = bluecard_attach, .remove = bluecard_detach, .id_table = bluecard_ids, - .suspend = bluecard_suspend, - .resume = bluecard_resume, }; static int __init init_bluecard_cs(void) diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index ac1410c0a4..7b0f4f0bea 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -842,28 +842,6 @@ static void bt3c_release(dev_link_t *link) pcmcia_disable_device(link->handle); } -static int bt3c_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int bt3c_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (DEV_OK(link)) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} - static struct pcmcia_device_id bt3c_ids[] = { PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02), @@ -879,8 +857,6 @@ static struct pcmcia_driver bt3c_driver = { .probe = bt3c_attach, .remove = bt3c_detach, .id_table = bt3c_ids, - .suspend = bt3c_suspend, - .resume = bt3c_resume, }; static int __init init_bt3c_cs(void) diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 8cd54bb199..9a507bdb8b 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -771,29 +771,6 @@ static void btuart_release(dev_link_t *link) pcmcia_disable_device(link->handle); } -static int btuart_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int btuart_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (DEV_OK(link)) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} - - static struct pcmcia_device_id btuart_ids[] = { /* don't use this driver. Use serial_cs + hci_uart instead */ PCMCIA_DEVICE_NULL @@ -808,8 +785,6 @@ static struct pcmcia_driver btuart_driver = { .probe = btuart_attach, .remove = btuart_detach, .id_table = btuart_ids, - .suspend = btuart_suspend, - .resume = btuart_resume, }; static int __init init_btuart_cs(void) diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index efbc8a543a..39dbe7300d 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -723,28 +723,6 @@ static void dtl1_release(dev_link_t *link) pcmcia_disable_device(link->handle); } -static int dtl1_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int dtl1_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (DEV_OK(link)) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} - static struct pcmcia_device_id dtl1_ids[] = { PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d), @@ -762,8 +740,6 @@ static struct pcmcia_driver dtl1_driver = { .probe = dtl1_attach, .remove = dtl1_detach, .id_table = dtl1_ids, - .suspend = dtl1_suspend, - .resume = dtl1_resume, }; static int __init init_dtl1_cs(void) diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 3ddd3da9e7..870decbdf7 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -1870,10 +1870,6 @@ static int cm4000_suspend(struct pcmcia_device *p_dev) struct cm4000_dev *dev; dev = link->priv; - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); stop_monitor(dev); return 0; @@ -1885,11 +1881,6 @@ static int cm4000_resume(struct pcmcia_device *p_dev) struct cm4000_dev *dev; dev = link->priv; - - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) start_monitor(dev); diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 1c355bd2be..47f10c8b88 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -629,28 +629,6 @@ cs_release: link->state &= ~DEV_CONFIG_PENDING; } -static int reader_suspend(struct pcmcia_device *p_dev) -{ - dev_link_t *link = dev_to_instance(p_dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int reader_resume(struct pcmcia_device *p_dev) -{ - dev_link_t *link = dev_to_instance(p_dev); - - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} - static void reader_release(dev_link_t *link) { cm4040_reader_release(link->priv); @@ -754,8 +732,6 @@ static struct pcmcia_driver reader_driver = { }, .probe = reader_attach, .remove = reader_detach, - .suspend = reader_suspend, - .resume = reader_resume, .id_table = cm4040_ids, }; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 371d10b780..d3ea53a5a5 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -733,10 +733,7 @@ static int mgslpc_suspend(struct pcmcia_device *dev) dev_link_t *link = dev_to_instance(dev); MGSLPC_INFO *info = link->priv; - link->state |= DEV_SUSPEND; info->stop = 1; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); return 0; } @@ -746,9 +743,6 @@ static int mgslpc_resume(struct pcmcia_device *dev) dev_link_t *link = dev_to_instance(dev); MGSLPC_INFO *info = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); info->stop = 0; return 0; diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 024aad6164..7ad8a95969 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -373,27 +373,6 @@ void ide_release(dev_link_t *link) pcmcia_disable_device(link->handle); } /* ide_release */ -static int ide_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int ide_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (DEV_OK(link)) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} /*====================================================================== @@ -456,8 +435,6 @@ static struct pcmcia_driver ide_cs_driver = { .probe = ide_attach, .remove = ide_detach, .id_table = ide_ids, - .suspend = ide_suspend, - .resume = ide_resume, }; static int __init init_ide_cs(void) diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 5f70661994..ae70247d51 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -371,42 +371,6 @@ static void avmcs_release(dev_link_t *link) pcmcia_disable_device(link->handle); } /* avmcs_release */ -static int avmcs_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int avmcs_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} - -/*====================================================================== - - The card status event handler. Mostly, this schedules other - stuff to run after an event is received. A CARD_REMOVAL event - also sets some flags to discourage the net drivers from trying - to talk to the card any more. - - When a CARD_REMOVAL event is received, we immediately set a flag - to block future accesses to this device. All the functions that - actually access the device should check this flag to make sure - the card is still present. - -======================================================================*/ - static struct pcmcia_device_id avmcs_ids[] = { PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335), @@ -424,8 +388,6 @@ static struct pcmcia_driver avmcs_driver = { .probe = avmcs_attach, .remove = avmcs_detach, .id_table = avmcs_ids, - .suspend= avmcs_suspend, - .resume = avmcs_resume, }; static int __init avmcs_init(void) diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 845fa14e1b..5e847cfb96 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -383,28 +383,6 @@ static void avma1cs_release(dev_link_t *link) pcmcia_disable_device(link->handle); } /* avma1cs_release */ -static int avma1cs_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int avma1cs_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} - static struct pcmcia_device_id avma1cs_ids[] = { PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb), @@ -421,10 +399,8 @@ static struct pcmcia_driver avma1cs_driver = { .probe = avma1cs_attach, .remove = avma1cs_detach, .id_table = avma1cs_ids, - .suspend = avma1cs_suspend, - .resume = avma1cs_resume, }; - + /*====================================================================*/ static int __init init_avma1_cs(void) diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 60c75c7c01..b76b303ebf 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -389,10 +389,7 @@ static int elsa_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state |= DEV_SUSPEND; dev->busy = 1; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); return 0; } @@ -402,9 +399,6 @@ static int elsa_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); dev->busy = 0; return 0; diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index fd0f127e40..5745eb1afe 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -472,10 +472,7 @@ static int sedlbauer_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state |= DEV_SUSPEND; dev->stop = 1; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); return 0; } @@ -485,9 +482,6 @@ static int sedlbauer_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); dev->stop = 0; return 0; diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 7945fd6462..929507eb63 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -380,10 +380,7 @@ static int teles_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state |= DEV_SUSPEND; dev->busy = 1; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); return 0; } @@ -393,9 +390,6 @@ static int teles_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); dev->busy = 0; return 0; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 1799660bdc..8dfa30b3c7 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -519,12 +519,8 @@ static int tc574_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - if (link->open) - netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); return 0; } @@ -534,13 +530,9 @@ static int tc574_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - tc574_reset(dev); - netif_device_attach(dev); - } + if ((link->state & DEV_CONFIG) && (link->open)) { + tc574_reset(dev); + netif_device_attach(dev); } return 0; diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index e361538517..b15066be26 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -394,12 +394,8 @@ static int tc589_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - if (link->open) - netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); return 0; } @@ -409,13 +405,9 @@ static int tc589_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - tc589_reset(dev); - netif_device_attach(dev); - } + if ((link->state & DEV_CONFIG) && (link->open)) { + tc589_reset(dev); + netif_device_attach(dev); } return 0; diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 9b9c0f19b2..c34547c792 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -464,12 +464,8 @@ static int axnet_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - if (link->open) + if ((link->state & DEV_CONFIG) && (link->open)) netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } return 0; } @@ -479,14 +475,10 @@ static int axnet_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - axnet_reset_8390(dev); - AX88190_init(dev, 1); - netif_device_attach(dev); - } + if ((link->state & DEV_CONFIG) && (link->open)) { + axnet_reset_8390(dev); + AX88190_init(dev, 1); + netif_device_attach(dev); } return 0; diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index a0ec5e7aac..0748c3d495 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -387,13 +387,8 @@ static int com20020_suspend(struct pcmcia_device *p_dev) com20020_dev_t *info = link->priv; struct net_device *dev = info->dev; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - if (link->open) { - netif_device_detach(dev); - } - pcmcia_release_configuration(link->handle); - } + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); return 0; } @@ -404,15 +399,11 @@ static int com20020_resume(struct pcmcia_device *p_dev) com20020_dev_t *info = link->priv; struct net_device *dev = info->dev; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - int ioaddr = dev->base_addr; - struct arcnet_local *lp = dev->priv; - ARCRESET; - } - } + if ((link->state & DEV_CONFIG) && (link->open)) { + int ioaddr = dev->base_addr; + struct arcnet_local *lp = dev->priv; + ARCRESET; + } return 0; } diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 6b435e9406..62efbc7c2d 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -683,13 +683,8 @@ static int fmvj18x_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - if (link->open) - netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } - + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); return 0; } @@ -699,13 +694,9 @@ static int fmvj18x_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - fjn_reset(dev); - netif_device_attach(dev); - } + if ((link->state & DEV_CONFIG) && (link->open)) { + fjn_reset(dev); + netif_device_attach(dev); } return 0; diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 1948a0bc19..6d7f8f52e1 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -367,12 +367,8 @@ static int ibmtr_suspend(struct pcmcia_device *p_dev) ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - if (link->open) - netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); return 0; } @@ -383,14 +379,10 @@ static int ibmtr_resume(struct pcmcia_device *p_dev) ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - ibmtr_probe(dev); /* really? */ - netif_device_attach(dev); - } - } + if ((link->state & DEV_CONFIG) && (link->open)) { + ibmtr_probe(dev); /* really? */ + netif_device_attach(dev); + } return 0; } diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 76ef453d17..cf2a50c015 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -774,13 +774,8 @@ static int nmclan_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - if (link->open) - netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } - + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); return 0; } @@ -790,13 +785,9 @@ static int nmclan_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - nmclan_reset(dev); - netif_device_attach(dev); - } + if ((link->state & DEV_CONFIG) && (link->open)) { + nmclan_reset(dev); + netif_device_attach(dev); } return 0; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 52f44bdff1..3a2b731eeb 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -756,12 +756,8 @@ static int pcnet_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - if (link->open) - netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); return 0; } @@ -771,14 +767,10 @@ static int pcnet_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - pcnet_reset_8390(dev); - NS8390_init(dev, 1); - netif_device_attach(dev); - } + if ((link->state & DEV_CONFIG) && (link->open)) { + pcnet_reset_8390(dev); + NS8390_init(dev, 1); + netif_device_attach(dev); } return 0; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 03b1d8fbe7..84e18bbed9 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -874,7 +874,6 @@ static int smc91c92_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state |= DEV_SUSPEND; if (link->state & DEV_CONFIG) { if (link->open) netif_device_detach(dev); @@ -891,7 +890,6 @@ static int smc91c92_resume(struct pcmcia_device *p_dev) struct smc_private *smc = netdev_priv(dev); int i; - link->state &= ~DEV_SUSPEND; if (link->state & DEV_CONFIG) { if ((smc->manfid == MANFID_MEGAHERTZ) && (smc->cardid == PRODID_MEGAHERTZ_EM3288)) diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 2b57a87371..19347bcb2f 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1109,13 +1109,9 @@ static int xirc2ps_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - if (link->open) { + if ((link->state & DEV_CONFIG) && (link->open)) { netif_device_detach(dev); do_powerdown(dev); - } - pcmcia_release_configuration(link->handle); } return 0; @@ -1126,13 +1122,9 @@ static int xirc2ps_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - do_reset(dev,1); - netif_device_attach(dev); - } + if ((link->state & DEV_CONFIG) && (link->open)) { + do_reset(dev,1); + netif_device_attach(dev); } return 0; diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 489ef7f3d9..adb90b679d 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -437,11 +437,8 @@ static int airo_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); local_info_t *local = link->priv; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) netif_device_detach(local->eth_dev); - pcmcia_release_configuration(link->handle); - } return 0; } @@ -451,9 +448,7 @@ static int airo_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); local_info_t *local = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); + if ((link->state & DEV_CONFIG) && (link->open)) { reset_airo_card(local->eth_dev); netif_device_attach(local->eth_dev); } diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 1da8e6197f..89dbc783ff 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -433,11 +433,8 @@ static int atmel_suspend(struct pcmcia_device *dev) dev_link_t *link = dev_to_instance(dev); local_info_t *local = link->priv; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) netif_device_detach(local->eth_dev); - pcmcia_release_configuration(link->handle); - } return 0; } @@ -447,9 +444,7 @@ static int atmel_resume(struct pcmcia_device *dev) dev_link_t *link = dev_to_instance(dev); local_info_t *local = link->priv; - link->state &= ~DEV_SUSPEND; if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); atmel_open(local->eth_dev); netif_device_attach(local->eth_dev); } diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 7a1023f387..0fb6251854 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -816,8 +816,6 @@ static int hostap_cs_suspend(struct pcmcia_device *p_dev) PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info); - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { struct hostap_interface *iface = netdev_priv(dev); if (iface && iface->local) @@ -827,7 +825,6 @@ static int hostap_cs_suspend(struct pcmcia_device *p_dev) netif_device_detach(dev); } prism2_suspend(dev); - pcmcia_release_configuration(link->handle); } return 0; @@ -841,14 +838,11 @@ static int hostap_cs_resume(struct pcmcia_device *p_dev) PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info); - link->state &= ~DEV_SUSPEND; if (link->state & DEV_CONFIG) { struct hostap_interface *iface = netdev_priv(dev); if (iface && iface->local) dev_open = iface->local->num_dev_open > 0; - pcmcia_request_configuration(link->handle, &link->conf); - prism2_hw_shutdown(dev, 1); prism2_hw_config(dev, dev_open ? 0 : 1); if (dev_open) { diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index dfb47ac9da..545717b5e1 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -884,12 +884,8 @@ static int netwave_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - if (link->open) - netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); return 0; } @@ -899,13 +895,9 @@ static int netwave_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - netwave_reset(dev); - netif_device_attach(dev); - } + if ((link->state & DEV_CONFIG) && (link->open)) { + netwave_reset(dev); + netif_device_attach(dev); } return 0; diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 0ce4165efc..89e16cd1be 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -429,7 +429,6 @@ static int orinoco_cs_suspend(struct pcmcia_device *p_dev) int err = 0; unsigned long flags; - link->state |= DEV_SUSPEND; if (link->state & DEV_CONFIG) { /* This is probably racy, but I can't think of a better way, short of rewriting the PCMCIA @@ -447,8 +446,6 @@ static int orinoco_cs_suspend(struct pcmcia_device *p_dev) spin_unlock_irqrestore(&priv->lock, flags); } - - pcmcia_release_configuration(link->handle); } return 0; @@ -463,12 +460,7 @@ static int orinoco_cs_resume(struct pcmcia_device *p_dev) int err = 0; unsigned long flags; - link->state &= ~DEV_SUSPEND; if (link->state & DEV_CONFIG) { - /* FIXME: should we double check that this is - * the same card as we had before */ - pcmcia_request_configuration(link->handle, &link->conf); - if (! test_bit(0, &card->hard_reset_in_progress)) { err = orinoco_reinit_firmware(dev); if (err) { diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index fc81ac6700..ed4bf5013f 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -868,14 +868,8 @@ static int ray_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - if (link->open) - netif_device_detach(dev); - - pcmcia_release_configuration(link->handle); - } - + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); return 0; } @@ -885,14 +879,10 @@ static int ray_resume(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - ray_reset(dev); - netif_device_attach(dev); - } - } + if ((link->state & DEV_CONFIG) && (link->open)) { + ray_reset(dev); + netif_device_attach(dev); + } return 0; } diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index b7ed99f8d3..0429f1dc7f 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -908,7 +908,6 @@ spectrum_cs_suspend(struct pcmcia_device *p_dev) unsigned long flags; int err = 0; - link->state |= DEV_SUSPEND; /* Mark the device as stopped, to block IO until later */ if (link->state & DEV_CONFIG) { spin_lock_irqsave(&priv->lock, flags); @@ -922,8 +921,6 @@ spectrum_cs_suspend(struct pcmcia_device *p_dev) priv->hw_unavailable++; spin_unlock_irqrestore(&priv->lock, flags); - - pcmcia_release_configuration(link->handle); } return 0; @@ -936,11 +933,7 @@ spectrum_cs_resume(struct pcmcia_device *p_dev) struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); - link->state &= ~DEV_SUSPEND; if (link->state & DEV_CONFIG) { - /* FIXME: should we double check that this is - * the same card as we had before */ - pcmcia_request_configuration(link->handle, &link->conf); netif_device_attach(dev); priv->hw_unavailable--; schedule_work(&priv->reset_work); diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 696aeb9d8f..8cabcfe3a6 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4742,19 +4742,12 @@ static int wavelan_suspend(struct pcmcia_device *p_dev) /* Stop receiving new messages and wait end of transmission */ wv_ru_stop(dev); + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); + /* Power down the module */ hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT)); - /* The card is now suspended */ - link->state |= DEV_SUSPEND; - - if(link->state & DEV_CONFIG) - { - if(link->open) - netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } - return 0; } @@ -4764,14 +4757,9 @@ static int wavelan_resume(struct pcmcia_device *p_dev) struct net_device * dev = (struct net_device *) link->priv; link->state &= ~DEV_SUSPEND; - if(link->state & DEV_CONFIG) - { - pcmcia_request_configuration(link->handle, &link->conf); - if(link->open) /* If RESET -> True, If RESUME -> False ? */ - { - wv_hw_reset(dev); - netif_device_attach(dev); - } + if ((link->state & DEV_CONFIG) && (link->open)) { + wv_hw_reset(dev); + netif_device_attach(dev); } return 0; diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 0c81b3e7d7..3a93a8bb2e 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -2160,14 +2160,9 @@ static int wl3501_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - link->state |= DEV_SUSPEND; - wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND); - if (link->state & DEV_CONFIG) { - if (link->open) - netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); return 0; } @@ -2178,12 +2173,9 @@ static int wl3501_resume(struct pcmcia_device *p_dev) struct net_device *dev = link->priv; wl3501_pwr_mgmt(dev->priv, WL3501_RESUME); - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - if (link->open) { - wl3501_reset(dev); - netif_device_attach(dev); - } + if ((link->state & DEV_CONFIG) && (link->open)) { + wl3501_reset(dev); + netif_device_attach(dev); } return 0; diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 7edd7ef6c3..5e12ed2f1b 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -280,27 +280,6 @@ void parport_cs_release(dev_link_t *link) pcmcia_disable_device(link->handle); } /* parport_cs_release */ -static int parport_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int parport_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (DEV_OK(link)) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} static struct pcmcia_device_id parport_ids[] = { PCMCIA_DEVICE_FUNC_ID(3), @@ -317,8 +296,6 @@ static struct pcmcia_driver parport_cs_driver = { .probe = parport_attach, .remove = parport_detach, .id_table = parport_ids, - .suspend = parport_suspend, - .resume = parport_resume, }; static int __init init_parport_cs(void) diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 16159e9d1b..ec2d4166a2 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -10,7 +10,7 @@ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. * * (C) 1999 David A. Hinds - * (C) 2003 - 2005 Dominik Brodowski + * (C) 2003 - 2006 Dominik Brodowski */ #include @@ -1030,12 +1030,22 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct pcmcia_driver *p_drv = NULL; + int ret; if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); - if (p_drv && p_drv->suspend) - return p_drv->suspend(p_dev); + if (p_drv && p_drv->suspend) { + ret = p_drv->suspend(p_dev); + if (ret) + return ret; + if (p_dev->instance) { + p_dev->instance->state |= DEV_SUSPEND; + if ((p_dev->instance->state & DEV_CONFIG) && + !(p_dev->instance->state & DEV_SUSPEND_NORELEASE)) + pcmcia_release_configuration(p_dev); + } + } return 0; } @@ -1045,12 +1055,24 @@ static int pcmcia_dev_resume(struct device * dev) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct pcmcia_driver *p_drv = NULL; + int ret; if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); - if (p_drv && p_drv->resume) + if (p_drv && p_drv->resume) { + if (p_dev->instance) { + p_dev->instance->state &= ~DEV_SUSPEND; + if ((p_dev->instance->state & DEV_CONFIG) && + !(p_dev->instance->state & DEV_SUSPEND_NORELEASE)){ + ret = pcmcia_request_configuration(p_dev, + &p_dev->instance->conf); + if (ret) + return ret; + } + } return p_drv->resume(p_dev); + } return 0; } diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index e7f9d26a0d..7fbef1e516 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -251,27 +251,12 @@ static void aha152x_release_cs(dev_link_t *link) pcmcia_disable_device(link->handle); } -static int aha152x_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - static int aha152x_resume(struct pcmcia_device *dev) { dev_link_t *link = dev_to_instance(dev); scsi_info_t *info = link->priv; - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - aha152x_host_reset_host(info->host); - } + aha152x_host_reset_host(info->host); return 0; } @@ -294,7 +279,6 @@ static struct pcmcia_driver aha152x_cs_driver = { .probe = aha152x_attach, .remove = aha152x_detach, .id_table = aha152x_ids, - .suspend = aha152x_suspend, .resume = aha152x_resume, }; diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index fb7221cf51..20b9b27c60 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -220,26 +220,12 @@ static void fdomain_release(dev_link_t *link) /*====================================================================*/ -static int fdomain_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - static int fdomain_resume(struct pcmcia_device *dev) { dev_link_t *link = dev_to_instance(dev); - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); + if (link->state & DEV_CONFIG) fdomain_16x0_bus_reset(NULL); - } return 0; } @@ -260,7 +246,6 @@ static struct pcmcia_driver fdomain_cs_driver = { .probe = fdomain_attach, .remove = fdomain_detach, .id_table = fdomain_ids, - .suspend = fdomain_suspend, .resume = fdomain_resume, }; diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index d469e0d162..e313b40b70 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1987,8 +1987,6 @@ static int nsp_cs_suspend(struct pcmcia_device *dev) scsi_info_t *info = link->priv; nsp_hw_data *data; - link->state |= DEV_SUSPEND; - nsp_dbg(NSP_DEBUG_INIT, "event: suspend"); if (info->host != NULL) { @@ -2001,9 +1999,6 @@ static int nsp_cs_suspend(struct pcmcia_device *dev) info->stop = 1; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - return 0; } @@ -2015,11 +2010,6 @@ static int nsp_cs_resume(struct pcmcia_device *dev) nsp_dbg(NSP_DEBUG_INIT, "event: resume"); - link->state &= ~DEV_SUSPEND; - - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); - info->stop = 0; if (info->host != NULL) { diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 1e27059cd4..5a8da5143b 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -311,22 +311,10 @@ static void qlogic_release(dev_link_t *link) /*====================================================================*/ -static int qlogic_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - static int qlogic_resume(struct pcmcia_device *dev) { dev_link_t *link = dev_to_instance(dev); - link->state &= ~DEV_SUSPEND; if (link->state & DEV_CONFIG) { scsi_info_t *info = link->priv; @@ -375,7 +363,6 @@ static struct pcmcia_driver qlogic_cs_driver = { .probe = qlogic_attach, .remove = qlogic_detach, .id_table = qlogic_ids, - .suspend = qlogic_suspend, .resume = qlogic_resume, }; diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 42d002b6d1..4a6988567d 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -857,26 +857,12 @@ cs_failed: return; } /* SYM53C500_config */ -static int sym53c500_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - static int sym53c500_resume(struct pcmcia_device *dev) { dev_link_t *link = dev_to_instance(dev); struct scsi_info_t *info = link->priv; - link->state &= ~DEV_SUSPEND; if (link->state & DEV_CONFIG) { - pcmcia_request_configuration(link->handle, &link->conf); - /* See earlier comment about manufacturer IDs. */ if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || @@ -963,7 +949,6 @@ static struct pcmcia_driver sym53c500_cs_driver = { .probe = SYM53C500_attach, .remove = SYM53C500_detach, .id_table = sym53c500_ids, - .suspend = sym53c500_suspend, .resume = sym53c500_resume, }; diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index ff38820a03..b6b460fa69 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -151,7 +151,6 @@ static void serial_remove(dev_link_t *link) static int serial_suspend(struct pcmcia_device *dev) { dev_link_t *link = dev_to_instance(dev); - link->state |= DEV_SUSPEND; if (link->state & DEV_CONFIG) { struct serial_info *info = link->priv; @@ -160,8 +159,8 @@ static int serial_suspend(struct pcmcia_device *dev) for (i = 0; i < info->ndev; i++) serial8250_suspend_port(info->line[i]); - if (!info->slave) - pcmcia_release_configuration(link->handle); + if (info->slave) + link->state &= DEV_SUSPEND_NORELEASE; } return 0; @@ -170,15 +169,11 @@ static int serial_suspend(struct pcmcia_device *dev) static int serial_resume(struct pcmcia_device *dev) { dev_link_t *link = dev_to_instance(dev); - link->state &= ~DEV_SUSPEND; if (DEV_OK(link)) { struct serial_info *info = link->priv; int i; - if (!info->slave) - pcmcia_request_configuration(link->handle, &link->conf); - for (i = 0; i < info->ndev; i++) serial8250_resume_port(info->line[i]); } diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index fe3cde0da8..509465586d 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -232,28 +232,6 @@ static void ixj_cs_release(dev_link_t *link) pcmcia_disable_device(link->handle); } -static int ixj_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int ixj_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (DEV_OK(link)) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} - static struct pcmcia_device_id ixj_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0257, 0x0600), PCMCIA_DEVICE_NULL @@ -268,8 +246,6 @@ static struct pcmcia_driver ixj_driver = { .probe = ixj_attach, .remove = ixj_detach, .id_table = ixj_ids, - .suspend = ixj_suspend, - .resume = ixj_resume, }; static int __init ixj_pcmcia_init(void) diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index ee811673d9..ca3fc336d3 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -293,28 +293,6 @@ cs_failed: } } -static int sl811_suspend(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state |= DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - - return 0; -} - -static int sl811_resume(struct pcmcia_device *dev) -{ - dev_link_t *link = dev_to_instance(dev); - - link->state &= ~DEV_SUSPEND; - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); - - return 0; -} - static int sl811_cs_attach(struct pcmcia_device *p_dev) { local_info_t *local; @@ -359,8 +337,6 @@ static struct pcmcia_driver sl811_cs_driver = { .probe = sl811_cs_attach, .remove = sl811_cs_detach, .id_table = sl811_ids, - .suspend = sl811_suspend, - .resume = sl811_resume, }; /*====================================================================*/ -- cgit v1.2.2 From 4bbed5231468014b500b048d7370a1c6c349231a Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 15 Jan 2006 11:18:12 +0100 Subject: [PATCH] pcmcia: remove export of pcmcia_release_configuration Handle the _modifying_ operation sm91c92_cs requires in pcmcia_modify_configuration, so that the only remaining users of pcmcia_release_configuration() are within the pcmcia core module. Signed-off-by: Dominik Brodowski --- drivers/mtd/maps/pcmciamtd.c | 3 +-- drivers/net/pcmcia/smc91c92_cs.c | 29 +++++++++++------------------ drivers/pcmcia/ds_internal.h | 2 ++ drivers/pcmcia/pcmcia_resource.c | 23 ++++++++++++++++++++++- 4 files changed, 36 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index f988c817e1..f45ff2581d 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -353,8 +353,7 @@ static void pcmciamtd_release(dev_link_t *link) } pcmcia_release_window(link->win); } - pcmcia_release_configuration(link->handle); - link->state &= ~DEV_CONFIG; + pcmcia_disable_device(link->handle); } diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 84e18bbed9..86942c09d8 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -874,11 +874,8 @@ static int smc91c92_suspend(struct pcmcia_device *p_dev) dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; - if (link->state & DEV_CONFIG) { - if (link->open) - netif_device_detach(dev); - pcmcia_release_configuration(link->handle); - } + if ((link->state & DEV_CONFIG) && (link->open)) + netif_device_detach(dev); return 0; } @@ -894,7 +891,6 @@ static int smc91c92_resume(struct pcmcia_device *p_dev) if ((smc->manfid == MANFID_MEGAHERTZ) && (smc->cardid == PRODID_MEGAHERTZ_EM3288)) mhz_3288_power(link); - pcmcia_request_configuration(link->handle, &link->conf); if (smc->manfid == MANFID_MOTOROLA) mot_config(link); if ((smc->manfid == MANFID_OSITECH) && @@ -963,18 +959,15 @@ static int check_sig(dev_link_t *link) } if (width) { - printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); - /* call pcmcia_release_configuration() in _suspend */ - smc91c92_suspend(link->handle); - - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->handle->socket->io[0].res->flags &= ~IO_DATA_PATH_WIDTH; - link->handle->socket->io[0].res->flags |= IO_DATA_PATH_WIDTH_8; - - /* call pcmcia_request_configuration() in _resume, it handles the - * flag update */ - smc91c92_resume(link->handle); - return check_sig(link); + modconf_t mod = { + .Attributes = CONF_IO_CHANGE_WIDTH, + }; + printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); + + smc91c92_suspend(link->handle); + pcmcia_modify_configuration(link->handle, &mod); + smc91c92_resume(link->handle); + return check_sig(link); } return -ENODEV; } diff --git a/drivers/pcmcia/ds_internal.h b/drivers/pcmcia/ds_internal.h index 783d8617a0..3a2b25e6ed 100644 --- a/drivers/pcmcia/ds_internal.h +++ b/drivers/pcmcia/ds_internal.h @@ -8,6 +8,8 @@ extern void pcmcia_put_dev(struct pcmcia_device *p_dev); struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function); +extern int pcmcia_release_configuration(struct pcmcia_device *p_dev); + #ifdef CONFIG_PCMCIA_IOCTL extern void __init pcmcia_setup_ioctl(void); extern void __exit pcmcia_cleanup_ioctl(void); diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index f4dcea6ac4..16504f852a 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -442,6 +442,28 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, (mod->Attributes & CONF_VPP2_CHANGE_VALID)) return CS_BAD_VPP; + if (mod->Attributes & CONF_IO_CHANGE_WIDTH) { + pccard_io_map io_off = { 0, 0, 0, 0, 1 }; + pccard_io_map io_on; + int i; + + io_on.speed = io_speed; + for (i = 0; i < MAX_IO_WIN; i++) { + if (!s->io[i].res) + continue; + io_off.map = i; + io_on.map = i; + + io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8; + io_on.start = s->io[i].res->start; + io_on.stop = s->io[i].res->end; + + s->ops->set_io_map(s, &io_off); + mdelay(40); + s->ops->set_io_map(s, &io_on); + } + } + return CS_SUCCESS; } /* modify_configuration */ EXPORT_SYMBOL(pcmcia_modify_configuration); @@ -479,7 +501,6 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) return CS_SUCCESS; } /* pcmcia_release_configuration */ -EXPORT_SYMBOL(pcmcia_release_configuration); /** pcmcia_release_io -- cgit v1.2.2 From 70294b468302fd7a0a99dad935c7ba5322989345 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 15 Jan 2006 12:43:16 +0100 Subject: [PATCH] pcmcia: remove unneeded Vcc pseudo setting As we do not allow setting Vcc in the pcmcia core, and Vpp1 and Vpp2 can only be set to the same value, a lot of code can be streamlined. Signed-off-by: Dominik Brodowski --- drivers/bluetooth/bluecard_cs.c | 4 ---- drivers/bluetooth/bt3c_cs.c | 6 +----- drivers/bluetooth/btuart_cs.c | 6 +----- drivers/bluetooth/dtl1_cs.c | 4 ---- drivers/char/pcmcia/cm4000_cs.c | 7 ------- drivers/char/pcmcia/cm4040_cs.c | 7 ------- drivers/char/pcmcia/synclink_cs.c | 7 ------- drivers/ide/legacy/ide-cs.c | 11 ++++------- drivers/isdn/hardware/avm/avm_cs.c | 1 - drivers/isdn/hisax/avma1_cs.c | 1 - drivers/isdn/hisax/elsa_cs.c | 8 ++------ drivers/isdn/hisax/sedlbauer_cs.c | 16 ++++++---------- drivers/isdn/hisax/teles_cs.c | 8 ++------ drivers/mtd/maps/pcmciamtd.c | 7 ++----- drivers/net/pcmcia/3c574_cs.c | 1 - drivers/net/pcmcia/3c589_cs.c | 1 - drivers/net/pcmcia/axnet_cs.c | 5 ----- drivers/net/pcmcia/com20020_cs.c | 1 - drivers/net/pcmcia/fmvj18x_cs.c | 8 +------- drivers/net/pcmcia/ibmtr_cs.c | 1 - drivers/net/pcmcia/nmclan_cs.c | 1 - drivers/net/pcmcia/pcnet_cs.c | 5 ----- drivers/net/pcmcia/smc91c92_cs.c | 1 - drivers/net/pcmcia/xirc2ps_cs.c | 1 - drivers/net/wireless/airo_cs.c | 19 ++++++------------- drivers/net/wireless/atmel_cs.c | 10 ++-------- drivers/net/wireless/hostap/hostap_cs.c | 19 +++++++------------ drivers/net/wireless/netwave_cs.c | 1 - drivers/net/wireless/orinoco_cs.c | 18 ++++++++---------- drivers/net/wireless/ray_cs.c | 1 - drivers/net/wireless/spectrum_cs.c | 16 +++++++--------- drivers/net/wireless/wavelan_cs.c | 1 - drivers/net/wireless/wl3501_cs.c | 1 - drivers/parport/parport_cs.c | 5 ----- drivers/pcmcia/pcmcia_resource.c | 6 +----- drivers/scsi/pcmcia/aha152x_stub.c | 1 - drivers/scsi/pcmcia/fdomain_stub.c | 1 - drivers/scsi/pcmcia/nsp_cs.c | 15 ++++++--------- drivers/scsi/pcmcia/qlogic_stub.c | 1 - drivers/scsi/pcmcia/sym53c500_cs.c | 1 - drivers/serial/serial_cs.c | 12 +----------- drivers/telephony/ixj_pcmcia.c | 3 --- drivers/usb/host/sl811_cs.c | 15 ++++++--------- 43 files changed, 63 insertions(+), 201 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index bb833b251b..8e23f9ad3e 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -878,7 +878,6 @@ static int bluecard_attach(struct pcmcia_device *p_dev) link->irq.Instance = info; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; @@ -925,7 +924,6 @@ static void bluecard_config(dev_link_t *link) tuple_t tuple; u_short buf[256]; cisparse_t parse; - config_info_t config; int i, n, last_ret, last_fn; tuple.TupleData = (cisdata_t *)buf; @@ -945,8 +943,6 @@ static void bluecard_config(dev_link_t *link) /* Configure card */ link->state |= DEV_CONFIG; - i = pcmcia_get_configuration_info(handle, &config); - link->conf.Vcc = config.Vcc; link->conf.ConfigIndex = 0x20; link->io.NumPorts1 = 64; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 7b0f4f0bea..0b848050b0 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -670,7 +670,6 @@ static int bt3c_attach(struct pcmcia_device *p_dev) link->irq.Instance = info; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; @@ -728,7 +727,6 @@ static void bt3c_config(dev_link_t *link) u_short buf[256]; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; - config_info_t config; int i, j, try, last_ret, last_fn; tuple.TupleData = (cisdata_t *)buf; @@ -748,8 +746,6 @@ static void bt3c_config(dev_link_t *link) /* Configure card */ link->state |= DEV_CONFIG; - i = pcmcia_get_configuration_info(handle, &config); - link->conf.Vcc = config.Vcc; /* First pass: look for a config entry that looks normal. */ tuple.TupleData = (cisdata_t *)buf; @@ -764,7 +760,7 @@ static void bt3c_config(dev_link_t *link) if (i != CS_SUCCESS) goto next_entry; if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; + link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 9a507bdb8b..ec19a577b4 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -598,7 +598,6 @@ static int btuart_attach(struct pcmcia_device *p_dev) link->irq.Instance = info; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; @@ -656,7 +655,6 @@ static void btuart_config(dev_link_t *link) u_short buf[256]; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; - config_info_t config; int i, j, try, last_ret, last_fn; tuple.TupleData = (cisdata_t *)buf; @@ -676,8 +674,6 @@ static void btuart_config(dev_link_t *link) /* Configure card */ link->state |= DEV_CONFIG; - i = pcmcia_get_configuration_info(handle, &config); - link->conf.Vcc = config.Vcc; /* First pass: look for a config entry that looks normal. */ tuple.TupleData = (cisdata_t *) buf; @@ -692,7 +688,7 @@ static void btuart_config(dev_link_t *link) if (i != CS_SUCCESS) goto next_entry; if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; + link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) { link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 39dbe7300d..86617ee80e 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -577,7 +577,6 @@ static int dtl1_attach(struct pcmcia_device *p_dev) link->irq.Instance = info; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; @@ -634,7 +633,6 @@ static void dtl1_config(dev_link_t *link) u_short buf[256]; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; - config_info_t config; int i, last_ret, last_fn; tuple.TupleData = (cisdata_t *)buf; @@ -654,8 +652,6 @@ static void dtl1_config(dev_link_t *link) /* Configure card */ link->state |= DEV_CONFIG; - i = pcmcia_get_configuration_info(handle, &config); - link->conf.Vcc = config.Vcc; tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 870decbdf7..c996ae1375 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -1765,7 +1765,6 @@ static void cm4000_config(dev_link_t * link, int devno) struct cm4000_dev *dev; tuple_t tuple; cisparse_t parse; - config_info_t conf; u_char buf[64]; int fail_fn, fail_rc; int rc; @@ -1790,16 +1789,10 @@ static void cm4000_config(dev_link_t * link, int devno) fail_fn = ParseTuple; goto cs_failed; } - if ((fail_rc = - pcmcia_get_configuration_info(handle, &conf)) != CS_SUCCESS) { - fail_fn = GetConfigurationInfo; - goto cs_failed; - } link->state |= DEV_CONFIG; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - link->conf.Vcc = conf.Vcc; link->io.BasePort2 = 0; link->io.NumPorts2 = 0; diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 47f10c8b88..94ecd0342b 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -520,7 +520,6 @@ static void reader_config(dev_link_t *link, int devno) struct reader_dev *dev; tuple_t tuple; cisparse_t parse; - config_info_t conf; u_char buf[64]; int fail_fn, fail_rc; int rc; @@ -546,16 +545,10 @@ static void reader_config(dev_link_t *link, int devno) fail_fn = ParseTuple; goto cs_failed; } - if ((fail_rc = pcmcia_get_configuration_info(handle, &conf)) - != CS_SUCCESS) { - fail_fn = GetConfigurationInfo; - goto cs_failed; - } link->state |= DEV_CONFIG; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - link->conf.Vcc = conf.Vcc; link->io.BasePort2 = 0; link->io.NumPorts2 = 0; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index d3ea53a5a5..a6cbd32399 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -576,7 +576,6 @@ static int mgslpc_attach(struct pcmcia_device *p_dev) link->irq.Handler = NULL; link->conf.Attributes = 0; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; @@ -604,7 +603,6 @@ static void mgslpc_config(dev_link_t *link) cisparse_t parse; int last_fn, last_ret; u_char buf[64]; - config_info_t conf; cistpl_cftable_entry_t dflt = { 0 }; cistpl_cftable_entry_t *cfg; @@ -626,10 +624,6 @@ static void mgslpc_config(dev_link_t *link) /* Configure card */ link->state |= DEV_CONFIG; - /* Look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; - /* get CIS configuration entry */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; @@ -662,7 +656,6 @@ static void mgslpc_config(dev_link_t *link) } link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 8; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 7ad8a95969..3b5b55f85e 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -122,7 +122,6 @@ static int ide_attach(struct pcmcia_device *p_dev) link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; @@ -222,7 +221,6 @@ static void ide_config(dev_link_t *link) /* Not sure if this is right... look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf)); - link->conf.Vcc = stk->conf.Vcc; pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; @@ -244,10 +242,10 @@ static void ide_config(dev_link_t *link) } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) { @@ -329,9 +327,8 @@ static void ide_config(dev_link_t *link) info->node.minor = 0; info->hd = hd; link->dev = &info->node; - printk(KERN_INFO "ide-cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", - info->node.dev_name, link->conf.Vcc / 10, link->conf.Vcc % 10, - link->conf.Vpp1 / 10, link->conf.Vpp1 % 10); + printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n", + info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10); link->state &= ~DEV_CONFIG_PENDING; kfree(stk); diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index ae70247d51..0c504dc49a 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -123,7 +123,6 @@ static int avmcs_attach(struct pcmcia_device *p_dev) /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 5e847cfb96..8d23e5ab8d 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -153,7 +153,6 @@ static int avma1cs_attach(struct pcmcia_device *p_dev) /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index b76b303ebf..00835d537c 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -170,7 +170,6 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev) link->io.IOAddrLines = 3; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; @@ -324,11 +323,8 @@ static void elsa_cs_config(dev_link_t *link) link->dev = &dev->node; /* Finally, report what we've done */ - printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", - dev->node.dev_name, link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + printk(KERN_INFO "%s: index 0x%02x: ", + dev->node.dev_name, link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq.AssignedIRQ); if (link->io.NumPorts1) diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 5745eb1afe..a3cd1c5563 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -184,7 +184,6 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev) link->conf.Attributes = 0; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; @@ -263,9 +262,7 @@ static void sedlbauer_config(dev_link_t *link) /* Configure card */ link->state |= DEV_CONFIG; - /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; /* In this loop, we scan the CIS for configuration table entries, @@ -309,10 +306,10 @@ static void sedlbauer_config(dev_link_t *link) } if (cfg->vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; else if (dflt.vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; /* Do we need to allocate an interrupt? */ @@ -403,11 +400,10 @@ static void sedlbauer_config(dev_link_t *link) link->dev = &dev->node; /* Finally, report what we've done */ - printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", - dev->node.dev_name, link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + printk(KERN_INFO "%s: index 0x%02x:", + dev->node.dev_name, link->conf.ConfigIndex); + if (link->conf.Vpp) + printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq.AssignedIRQ); if (link->io.NumPorts1) diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 929507eb63..040f098d4b 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -161,7 +161,6 @@ static int teles_attach(struct pcmcia_device *p_dev) link->io.IOAddrLines = 5; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; @@ -315,11 +314,8 @@ static void teles_cs_config(dev_link_t *link) link->dev = &dev->node; /* Finally, report what we've done */ - printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", - dev->node.dev_name, link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + printk(KERN_INFO "%s: index 0x%02x:", + dev->node.dev_name, link->conf.ConfigIndex); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq.AssignedIRQ); if (link->io.NumPorts1) diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index f45ff2581d..0026460be1 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -587,13 +587,10 @@ static void pcmciamtd_config(dev_link_t *link) DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2); dev->vpp = (vpp) ? vpp : t.Vpp1; link->conf.Attributes = 0; - link->conf.Vcc = t.Vcc; if(setvpp == 2) { - link->conf.Vpp1 = dev->vpp; - link->conf.Vpp2 = dev->vpp; + link->conf.Vpp = dev->vpp; } else { - link->conf.Vpp1 = 0; - link->conf.Vpp2 = 0; + link->conf.Vpp = 0; } link->conf.IntType = INT_MEMORY; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 8dfa30b3c7..179c9b7ad0 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -280,7 +280,6 @@ static int tc574_attach(struct pcmcia_device *p_dev) link->irq.Handler = &el3_interrupt; link->irq.Instance = dev; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index b15066be26..7e8036f2e1 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -194,7 +194,6 @@ static int tc589_attach(struct pcmcia_device *p_dev) link->irq.Handler = &el3_interrupt; link->irq.Instance = dev; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index c34547c792..5ca0d57185 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -302,7 +302,6 @@ static void axnet_config(dev_link_t *link) cisparse_t parse; int i, j, last_ret, last_fn; u_short buf[64]; - config_info_t conf; DEBUG(0, "axnet_config(0x%p)\n", link); @@ -321,10 +320,6 @@ static void axnet_config(dev_link_t *link) /* Configure card */ link->state |= DEV_CONFIG; - /* Look up current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 0748c3d495..e14d3d18b9 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -178,7 +178,6 @@ static int com20020_attach(struct pcmcia_device *p_dev) link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 62efbc7c2d..34bf963b12 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -257,7 +257,6 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev) /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; /* The FMVJ18x specific entries in the device structure. */ @@ -396,12 +395,7 @@ static void fmvj18x_config(dev_link_t *link) switch (le16_to_cpu(buf[0])) { case MANFID_TDK: cardtype = TDK; - if (le16_to_cpu(buf[1]) == PRODID_TDK_CF010) { - cs_status_t status; - pcmcia_get_status(handle, &status); - if (status.CardState & CS_EVENT_3VCARD) - link->conf.Vcc = 33; /* inserted in 3.3V slot */ - } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410 + if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410 || le16_to_cpu(buf[1]) == PRODID_TDK_NP9610 || le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) { /* MultiFunction Card */ diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 6d7f8f52e1..904c5cb04e 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -167,7 +167,6 @@ static int ibmtr_attach(struct pcmcia_device *p_dev) link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = &tok_interrupt; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index cf2a50c015..c25d9451d5 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -469,7 +469,6 @@ static int nmclan_attach(struct pcmcia_device *p_dev) link->irq.Handler = &mace_interrupt; link->irq.Instance = dev; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 3a2b731eeb..5a7e58af0b 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -531,7 +531,6 @@ static void pcnet_config(dev_link_t *link) int i, last_ret, last_fn, start_pg, stop_pg, cm_offset; int manfid = 0, prodid = 0, has_shmem = 0; u_short buf[64]; - config_info_t conf; hw_info_t *hw_info; DEBUG(0, "pcnet_config(0x%p)\n", link); @@ -550,10 +549,6 @@ static void pcnet_config(dev_link_t *link) /* Configure card */ link->state |= DEV_CONFIG; - /* Look up current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; - tuple.DesiredTuple = CISTPL_MANFID; tuple.Attributes = TUPLE_RETURN_COMMON; if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 86942c09d8..b46b7e1483 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -334,7 +334,6 @@ static int smc91c92_attach(struct pcmcia_device *p_dev) link->irq.Handler = &smc_interrupt; link->irq.Instance = dev; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; /* The SMC91c92-specific entries in the device structure. */ diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 19347bcb2f..f5fa86d046 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -571,7 +571,6 @@ xirc2ps_attach(struct pcmcia_device *p_dev) /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index adb90b679d..2216c04a02 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -168,7 +168,6 @@ static int airo_attach(struct pcmcia_device *p_dev) device, and can be hard-wired here. */ link->conf.Attributes = 0; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; /* Allocate space for private device-specific data */ @@ -294,16 +293,11 @@ static void airo_config(dev_link_t *link) /* Use power settings for Vcc and Vpp if present */ /* Note that the CIS values need to be rescaled */ - if (cfg->vcc.present & (1<conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vcc.present & (1<conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000; - if (cfg->vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; else if (dflt.vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; /* Do we need to allocate an interrupt? */ @@ -391,11 +385,10 @@ static void airo_config(dev_link_t *link) link->dev = &dev->node; /* Finally, report what we've done */ - printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", - dev->node.dev_name, link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + printk(KERN_INFO "%s: index 0x%02x: ", + dev->node.dev_name, link->conf.ConfigIndex); + if (link->conf.Vpp) + printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq.AssignedIRQ); if (link->io.NumPorts1) diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 89dbc783ff..53fdaa2222 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -179,7 +179,6 @@ static int atmel_attach(struct pcmcia_device *p_dev) device, and can be hard-wired here. */ link->conf.Attributes = 0; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; /* Allocate space for private device-specific data */ @@ -314,16 +313,11 @@ static void atmel_config(dev_link_t *link) /* Use power settings for Vcc and Vpp if present */ /* Note that the CIS values need to be rescaled */ - if (cfg->vcc.present & (1<conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vcc.present & (1<conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000; - if (cfg->vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; else if (dflt.vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; /* Do we need to allocate an interrupt? */ diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 0fb6251854..69024bfb5b 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -512,7 +512,6 @@ static int prism2_attach(struct pcmcia_device *p_dev) memset(link, 0, sizeof(dev_link_t)); PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); - link->conf.Vcc = 33; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; @@ -603,9 +602,6 @@ static int prism2_config(dev_link_t *link) CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link->handle, &conf)); - PDEBUG(DEBUG_HW, "%s: %s Vcc=%d (from config)\n", dev_info, - ignore_cis_vcc ? "ignoring" : "setting", conf.Vcc); - link->conf.Vcc = conf.Vcc; /* Look for an appropriate configuration table entry in the CIS */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; @@ -650,10 +646,10 @@ static int prism2_config(dev_link_t *link) } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; /* Do we need to allocate an interrupt? */ @@ -745,12 +741,11 @@ static int prism2_config(dev_link_t *link) dev->base_addr = link->io.BasePort1; /* Finally, report what we've done */ - printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", - dev_info, link->conf.ConfigIndex, - link->conf.Vcc / 10, link->conf.Vcc % 10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1 / 10, - link->conf.Vpp1 % 10); + printk(KERN_INFO "%s: index 0x%02x: ", + dev_info, link->conf.ConfigIndex); + if (link->conf.Vpp) + printk(", Vpp %d.%d", link->conf.Vpp / 10, + link->conf.Vpp % 10); if (link->conf.Attributes & CONF_ENABLE_IRQ) printk(", irq %d", link->irq.AssignedIRQ); if (link->io.NumPorts1) diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 545717b5e1..23d6b3376e 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -406,7 +406,6 @@ static int netwave_attach(struct pcmcia_device *p_dev) /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 89e16cd1be..75981d88a1 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -218,8 +218,7 @@ orinoco_cs_config(dev_link_t *link) /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, - pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; + pcmcia_get_configuration_info(link->handle, &conf)); /* * In this loop, we scan the CIS for configuration table @@ -274,10 +273,10 @@ orinoco_cs_config(dev_link_t *link) } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; /* Do we need to allocate an interrupt? */ @@ -373,12 +372,11 @@ orinoco_cs_config(dev_link_t *link) link->state &= ~DEV_CONFIG_PENDING; /* Finally, report what we've done */ - printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d", - dev->name, link->conf.ConfigIndex, - link->conf.Vcc / 10, link->conf.Vcc % 10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1 / 10, - link->conf.Vpp1 % 10); + printk(KERN_DEBUG "%s: index 0x%02x: ", + dev->name, link->conf.ConfigIndex); + if (link->conf.Vpp) + printk(", Vpp %d.%d", link->conf.Vpp / 10, + link->conf.Vpp % 10); printk(", irq %d", link->irq.AssignedIRQ); if (link->io.NumPorts1) printk(", io 0x%04x-0x%04x", link->io.BasePort1, diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index ed4bf5013f..7d95587d09 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -342,7 +342,6 @@ static int ray_attach(struct pcmcia_device *p_dev) /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 0429f1dc7f..7a4a80b01f 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -692,7 +692,6 @@ spectrum_cs_config(dev_link_t *link) /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; /* * In this loop, we scan the CIS for configuration table @@ -747,10 +746,10 @@ spectrum_cs_config(dev_link_t *link) } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; /* Do we need to allocate an interrupt? */ @@ -851,12 +850,11 @@ spectrum_cs_config(dev_link_t *link) link->state &= ~DEV_CONFIG_PENDING; /* Finally, report what we've done */ - printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d", - dev->name, link->conf.ConfigIndex, - link->conf.Vcc / 10, link->conf.Vcc % 10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1 / 10, - link->conf.Vpp1 % 10); + printk(KERN_DEBUG "%s: index 0x%02x: ", + dev->name, link->conf.ConfigIndex); + if (link->conf.Vpp) + printk(", Vpp %d.%d", link->conf.Vpp / 10, + link->conf.Vpp % 10); printk(", irq %d", link->irq.AssignedIRQ); if (link->io.NumPorts1) printk(", io 0x%04x-0x%04x", link->io.BasePort1, diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 8cabcfe3a6..daa17dc343 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4607,7 +4607,6 @@ wavelan_attach(struct pcmcia_device *p_dev) /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; /* Chain drivers */ diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 3a93a8bb2e..393b5cb7a5 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1976,7 +1976,6 @@ static int wl3501_attach(struct pcmcia_device *p_dev) /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 5e12ed2f1b..8d60146c72 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -117,7 +117,6 @@ static int parport_attach(struct pcmcia_device *p_dev) link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; @@ -168,7 +167,6 @@ void parport_config(dev_link_t *link) tuple_t tuple; u_short buf[128]; cisparse_t parse; - config_info_t conf; cistpl_cftable_entry_t *cfg = &parse.cftable_entry; cistpl_cftable_entry_t dflt = { 0 }; struct parport *p; @@ -189,9 +187,6 @@ void parport_config(dev_link_t *link) /* Configure card */ link->state |= DEV_CONFIG; - /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 16504f852a..17e2fbf26e 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -618,11 +618,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, return CS_CONFIGURATION_LOCKED; /* Do power control. We don't allow changes in Vcc. */ - if (s->socket.Vcc != req->Vcc) - return CS_BAD_VCC; - if (req->Vpp1 != req->Vpp2) - return CS_BAD_VPP; - s->socket.Vpp = req->Vpp1; + s->socket.Vpp = req->Vpp; if (s->ops->set_socket(s, &s->socket)) return CS_BAD_VPP; diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 7fbef1e516..12ec94d6ef 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -119,7 +119,6 @@ static int aha152x_attach(struct pcmcia_device *p_dev) link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 20b9b27c60..b3cd206ad6 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -101,7 +101,6 @@ static int fdomain_attach(struct pcmcia_device *p_dev) link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index e313b40b70..e41e1febe8 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1627,7 +1627,6 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev) /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; @@ -1709,7 +1708,6 @@ static void nsp_cs_config(dev_link_t *link) /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); @@ -1743,10 +1741,10 @@ static void nsp_cs_config(dev_link_t *link) } if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) { - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) { - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; } @@ -1905,11 +1903,10 @@ static void nsp_cs_config(dev_link_t *link) #endif /* Finally, report what we've done */ - printk(KERN_INFO "nsp_cs: index 0x%02x: Vcc %d.%d", - link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) { - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + printk(KERN_INFO "nsp_cs: index 0x%02x: ", + link->conf.ConfigIndex); + if (link->conf.Vpp) { + printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); } if (link->conf.Attributes & CONF_ENABLE_IRQ) { printk(", irq %d", link->irq.AssignedIRQ); diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 5a8da5143b..4f28589bbf 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -176,7 +176,6 @@ static int qlogic_attach(struct pcmcia_device *p_dev) link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 4a6988567d..2bce7b070a 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -916,7 +916,6 @@ SYM53C500_attach(struct pcmcia_device *p_dev) link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index b6b460fa69..1e6889f52b 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -358,7 +358,6 @@ static int simple_config(dev_link_t *link) return setup_serial(handle, info, port, config.AssignedIRQ); } } - link->conf.Vcc = config.Vcc; /* First pass: look for a config entry that looks normal. */ tuple->TupleData = (cisdata_t *) buf; @@ -374,7 +373,7 @@ static int simple_config(dev_link_t *link) if (i != CS_SUCCESS) goto next_entry; if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) && (cf->io.win[0].base != 0)) { @@ -445,7 +444,6 @@ static int multi_config(dev_link_t * link) u_char *buf; cisparse_t *parse; cistpl_cftable_entry_t *cf; - config_info_t config; int i, rc, base2 = 0; cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); @@ -456,14 +454,6 @@ static int multi_config(dev_link_t * link) cf = &parse->cftable_entry; buf = cfg_mem->buf; - i = pcmcia_get_configuration_info(handle, &config); - if (i != CS_SUCCESS) { - cs_error(handle, GetConfigurationInfo, i); - rc = -1; - goto free_cfg_mem; - } - link->conf.Vcc = config.Vcc; - tuple->TupleData = (cisdata_t *) buf; tuple->TupleOffset = 0; tuple->TupleDataMax = 255; diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index 509465586d..de794b21d7 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -51,7 +51,6 @@ static int ixj_attach(struct pcmcia_device *p_dev) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; link->io.IOAddrLines = 3; - link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL); if (!link->priv) { @@ -157,7 +156,6 @@ static void ixj_config(dev_link_t * link) tuple_t tuple; u_short buf[128]; cisparse_t parse; - config_info_t conf; cistpl_cftable_entry_t *cfg = &parse.cftable_entry; cistpl_cftable_entry_t dflt = { @@ -178,7 +176,6 @@ static void ixj_config(dev_link_t * link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; link->state |= DEV_CONFIG; - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index ca3fc336d3..c6f1baf541 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -191,7 +191,6 @@ static void sl811_cs_config(dev_link_t *link) /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); @@ -225,10 +224,10 @@ static void sl811_cs_config(dev_link_t *link) } if (cfg->vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; else if (dflt.vpp1.present & (1<conf.Vpp1 = link->conf.Vpp2 = + link->conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; /* we need an interrupt */ @@ -271,11 +270,10 @@ next_entry: dev->node.major = dev->node.minor = 0; link->dev = &dev->node; - printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", - dev->node.dev_name, link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + printk(KERN_INFO "%s: index 0x%02x: ", + dev->node.dev_name, link->conf.ConfigIndex); + if (link->conf.Vpp) + printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); printk(", irq %d", link->irq.AssignedIRQ); printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1); @@ -311,7 +309,6 @@ static int sl811_cs_attach(struct pcmcia_device *p_dev) link->irq.Handler = NULL; link->conf.Attributes = 0; - link->conf.Vcc = 33; link->conf.IntType = INT_MEMORY_AND_IO; link->handle = p_dev; -- cgit v1.2.2 From a78f4dd331a4f6a396eb5849656a4a72a70a56d7 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 15 Jan 2006 16:26:00 +0100 Subject: [PATCH] pcmcia: rename pcmcia_device.state Rename pcmcia_device.state (which is used in very few places) to p_state in order to avoid a namespace collision when moving the deprecated dev_link_t into struct pcmcia_device Signed-off-by: Dominik Brodowski --- drivers/pcmcia/ds.c | 12 ++++++------ drivers/pcmcia/pcmcia_resource.c | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index ec2d4166a2..488448a12b 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -390,7 +390,7 @@ static int pcmcia_device_probe(struct device * dev) goto put_dev; } - p_dev->state &= ~CLIENT_UNBOUND; + p_dev->p_state &= ~CLIENT_UNBOUND; ret = p_drv->probe(p_dev); if (ret) @@ -433,17 +433,17 @@ static int pcmcia_device_remove(struct device * dev) p_drv->remove(p_dev); /* check for proper unloading */ - if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED)) + if (p_dev->p_state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED)) printk(KERN_INFO "pcmcia: driver %s did not release config properly\n", p_drv->drv.name); for (i = 0; i < MAX_WIN; i++) - if (p_dev->state & CLIENT_WIN_REQ(i)) + if (p_dev->p_state & CLIENT_WIN_REQ(i)) printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n", p_drv->drv.name); /* references from pcmcia_probe_device */ - p_dev->state = CLIENT_UNBOUND; + p_dev->p_state = CLIENT_UNBOUND; pcmcia_put_dev(p_dev); module_put(p_drv->owner); @@ -472,7 +472,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s) } p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list); list_del(&p_dev->socket_device_list); - p_dev->state |= CLIENT_STALE; + p_dev->p_state |= CLIENT_STALE; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); device_unregister(&p_dev->dev); @@ -602,7 +602,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id); /* compat */ - p_dev->state = CLIENT_UNBOUND; + p_dev->p_state = CLIENT_UNBOUND; spin_lock_irqsave(&pcmcia_dev_list_lock, flags); diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 17e2fbf26e..ab0bbb6207 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -476,8 +476,8 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) config_t *c = p_dev->function_config; int i; - if (p_dev->state & CLIENT_CONFIG_LOCKED) { - p_dev->state &= ~CLIENT_CONFIG_LOCKED; + if (p_dev->p_state & CLIENT_CONFIG_LOCKED) { + p_dev->p_state &= ~CLIENT_CONFIG_LOCKED; if (--(s->lock_count) == 0) { s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ s->socket.Vpp = 0; @@ -516,10 +516,10 @@ int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) struct pcmcia_socket *s = p_dev->socket; config_t *c = p_dev->function_config; - if (!(p_dev->state & CLIENT_IO_REQ)) + if (!(p_dev->p_state & CLIENT_IO_REQ)) return CS_BAD_HANDLE; - p_dev->state &= ~CLIENT_IO_REQ; + p_dev->p_state &= ~CLIENT_IO_REQ; if ((c->io.BasePort1 != req->BasePort1) || (c->io.NumPorts1 != req->NumPorts1) || @@ -542,9 +542,9 @@ int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) struct pcmcia_socket *s = p_dev->socket; config_t *c= p_dev->function_config; - if (!(p_dev->state & CLIENT_IRQ_REQ)) + if (!(p_dev->p_state & CLIENT_IRQ_REQ)) return CS_BAD_HANDLE; - p_dev->state &= ~CLIENT_IRQ_REQ; + p_dev->p_state &= ~CLIENT_IRQ_REQ; if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; @@ -576,7 +576,7 @@ int pcmcia_release_window(window_handle_t win) if ((win == NULL) || (win->magic != WINDOW_MAGIC)) return CS_BAD_HANDLE; s = win->sock; - if (!(win->handle->state & CLIENT_WIN_REQ(win->index))) + if (!(win->handle->p_state & CLIENT_WIN_REQ(win->index))) return CS_BAD_HANDLE; /* Shut down memory window */ @@ -590,7 +590,7 @@ int pcmcia_release_window(window_handle_t win) kfree(win->ctl.res); win->ctl.res = NULL; } - win->handle->state &= ~CLIENT_WIN_REQ(win->index); + win->handle->p_state &= ~CLIENT_WIN_REQ(win->index); win->magic = 0; @@ -708,7 +708,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, } c->state |= CONFIG_LOCKED; - p_dev->state |= CLIENT_CONFIG_LOCKED; + p_dev->p_state |= CLIENT_CONFIG_LOCKED; return CS_SUCCESS; } /* pcmcia_request_configuration */ EXPORT_SYMBOL(pcmcia_request_configuration); @@ -754,7 +754,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) c->io = *req; c->state |= CONFIG_IO_REQ; - p_dev->state |= CLIENT_IO_REQ; + p_dev->p_state |= CLIENT_IO_REQ; return CS_SUCCESS; } /* pcmcia_request_io */ EXPORT_SYMBOL(pcmcia_request_io); @@ -850,7 +850,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) s->irq.Config++; c->state |= CONFIG_IRQ_REQ; - p_dev->state |= CLIENT_IRQ_REQ; + p_dev->p_state |= CLIENT_IRQ_REQ; #ifdef CONFIG_PCMCIA_PROBE pcmcia_used_irq[irq]++; @@ -910,7 +910,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h if (!win->ctl.res) return CS_IN_USE; } - (*p_dev)->state |= CLIENT_WIN_REQ(w); + (*p_dev)->p_state |= CLIENT_WIN_REQ(w); /* Configure the socket controller */ win->ctl.map = w+1; -- cgit v1.2.2 From fd238232cd0ff4840ae6946bb338502154096d88 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 5 Mar 2006 10:45:09 +0100 Subject: [PATCH] pcmcia: embed dev_link_t into struct pcmcia_device Embed dev_link_t into struct pcmcia_device(), as they basically address the same entity. The actual contents of dev_link_t will be cleaned up step by step. This patch includes a bugfix from and signed-off-by Andrew Morton. Signed-off-by: Dominik Brodowski --- drivers/bluetooth/bluecard_cs.c | 31 +++++------ drivers/bluetooth/bt3c_cs.c | 26 ++++----- drivers/bluetooth/btuart_cs.c | 25 ++++----- drivers/bluetooth/dtl1_cs.c | 25 ++++----- drivers/char/pcmcia/cm4000_cs.c | 29 +++++----- drivers/char/pcmcia/cm4040_cs.c | 29 +++++----- drivers/char/pcmcia/synclink_cs.c | 21 +++---- drivers/ide/legacy/ide-cs.c | 13 ++--- drivers/isdn/hardware/avm/avm_cs.c | 45 ++++++--------- drivers/isdn/hisax/avma1_cs.c | 48 ++++++---------- drivers/isdn/hisax/elsa_cs.c | 14 ++--- drivers/isdn/hisax/sedlbauer_cs.c | 16 +++--- drivers/isdn/hisax/teles_cs.c | 13 ++--- drivers/mtd/maps/pcmciamtd.c | 22 +++----- drivers/net/pcmcia/3c574_cs.c | 19 +++---- drivers/net/pcmcia/3c589_cs.c | 23 ++++---- drivers/net/pcmcia/axnet_cs.c | 19 +++---- drivers/net/pcmcia/com20020_cs.c | 39 +++++-------- drivers/net/pcmcia/fmvj18x_cs.c | 19 +++---- drivers/net/pcmcia/ibmtr_cs.c | 17 +++--- drivers/net/pcmcia/nmclan_cs.c | 21 +++---- drivers/net/pcmcia/pcnet_cs.c | 21 +++---- drivers/net/pcmcia/smc91c92_cs.c | 19 +++---- drivers/net/pcmcia/xirc2ps_cs.c | 19 +++---- drivers/net/wireless/airo_cs.c | 33 ++++------- drivers/net/wireless/atmel_cs.c | 33 ++++------- drivers/net/wireless/hostap/hostap_cs.c | 20 ++----- drivers/net/wireless/netwave_cs.c | 19 +++---- drivers/net/wireless/orinoco_cs.c | 22 +++----- drivers/net/wireless/ray_cs.c | 98 +++++++++++---------------------- drivers/net/wireless/spectrum_cs.c | 21 +++---- drivers/net/wireless/wavelan_cs.c | 46 ++++++---------- drivers/net/wireless/wl3501.h | 1 + drivers/net/wireless/wl3501_cs.c | 61 +++----------------- drivers/parport/parport_cs.c | 12 ++-- drivers/pcmcia/ds.c | 19 +++---- drivers/pcmcia/pcmcia_ioctl.c | 9 ++- drivers/pcmcia/pcmcia_resource.c | 13 ++--- drivers/scsi/pcmcia/aha152x_stub.c | 21 ++----- drivers/scsi/pcmcia/fdomain_stub.c | 12 ++-- drivers/scsi/pcmcia/nsp_cs.c | 13 ++--- drivers/scsi/pcmcia/nsp_cs.h | 2 +- drivers/scsi/pcmcia/qlogic_stub.c | 11 ++-- drivers/scsi/pcmcia/sym53c500_cs.c | 11 ++-- drivers/serial/serial_cs.c | 16 +++--- drivers/telephony/ixj_pcmcia.c | 31 ++++------- drivers/usb/host/sl811_cs.c | 11 ++-- 47 files changed, 415 insertions(+), 693 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 8e23f9ad3e..b461411eab 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -65,7 +65,7 @@ MODULE_LICENSE("GPL"); typedef struct bluecard_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct hci_dev *hdev; @@ -162,7 +162,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev); static void bluecard_activity_led_timeout(u_long arg) { bluecard_info_t *info = (bluecard_info_t *)arg; - unsigned int iobase = info->link.io.BasePort1; + unsigned int iobase = info->p_dev->io.BasePort1; if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) return; @@ -179,7 +179,7 @@ static void bluecard_activity_led_timeout(u_long arg) static void bluecard_enable_activity_led(bluecard_info_t *info) { - unsigned int iobase = info->link.io.BasePort1; + unsigned int iobase = info->p_dev->io.BasePort1; if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) return; @@ -235,7 +235,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info) } do { - register unsigned int iobase = info->link.io.BasePort1; + register unsigned int iobase = info->p_dev->io.BasePort1; register unsigned int offset; register unsigned char command; register unsigned long ready_bit; @@ -244,7 +244,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info) clear_bit(XMIT_WAKEUP, &(info->tx_state)); - if (!(info->link.state & DEV_PRESENT)) + if (!(info->p_dev->state & DEV_PRESENT)) return; if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) { @@ -382,7 +382,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset) return; } - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; if (test_bit(XMIT_SENDING_READY, &(info->tx_state))) bluecard_enable_activity_led(info); @@ -512,7 +512,7 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst, struct pt_regs *r if (!test_bit(CARD_READY, &(info->hw_state))) return IRQ_HANDLED; - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; spin_lock(&(info->lock)); @@ -626,7 +626,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev) static int bluecard_hci_open(struct hci_dev *hdev) { bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); - unsigned int iobase = info->link.io.BasePort1; + unsigned int iobase = info->p_dev->io.BasePort1; if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE); @@ -646,7 +646,7 @@ static int bluecard_hci_open(struct hci_dev *hdev) static int bluecard_hci_close(struct hci_dev *hdev) { bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data); - unsigned int iobase = info->link.io.BasePort1; + unsigned int iobase = info->p_dev->io.BasePort1; if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags))) return 0; @@ -713,7 +713,7 @@ static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned l static int bluecard_open(bluecard_info_t *info) { - unsigned int iobase = info->link.io.BasePort1; + unsigned int iobase = info->p_dev->io.BasePort1; struct hci_dev *hdev; unsigned char id; @@ -831,7 +831,7 @@ static int bluecard_open(bluecard_info_t *info) static int bluecard_close(bluecard_info_t *info) { - unsigned int iobase = info->link.io.BasePort1; + unsigned int iobase = info->p_dev->io.BasePort1; struct hci_dev *hdev = info->hdev; if (!hdev) @@ -859,14 +859,14 @@ static int bluecard_close(bluecard_info_t *info) static int bluecard_attach(struct pcmcia_device *p_dev) { bluecard_info_t *info; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); /* Create new info device */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - link = &info->link; + info->p_dev = p_dev; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -880,9 +880,6 @@ static int bluecard_attach(struct pcmcia_device *p_dev) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; bluecard_config(link); @@ -976,7 +973,7 @@ static void bluecard_config(dev_link_t *link) goto failed; strcpy(info->node.dev_name, info->hdev->name); - link->dev = &info->node; + link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; return; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 0b848050b0..9192a754eb 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -72,7 +72,7 @@ MODULE_LICENSE("GPL"); typedef struct bt3c_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct hci_dev *hdev; @@ -191,11 +191,11 @@ static void bt3c_write_wakeup(bt3c_info_t *info) return; do { - register unsigned int iobase = info->link.io.BasePort1; + register unsigned int iobase = info->p_dev->io.BasePort1; register struct sk_buff *skb; register int len; - if (!(info->link.state & DEV_PRESENT)) + if (!(info->p_dev->state & DEV_PRESENT)) break; @@ -229,7 +229,7 @@ static void bt3c_receive(bt3c_info_t *info) return; } - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; avail = bt3c_read(iobase, 0x7006); //printk("bt3c_cs: receiving %d bytes\n", avail); @@ -350,7 +350,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs) return IRQ_NONE; } - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; spin_lock(&(info->lock)); @@ -481,7 +481,7 @@ static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int co unsigned int iobase, size, addr, fcs, tmp; int i, err = 0; - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; /* Reset */ bt3c_io_write(iobase, 0x8040, 0x0404); @@ -562,7 +562,6 @@ static int bt3c_open(bt3c_info_t *info) { const struct firmware *firmware; struct hci_dev *hdev; - client_handle_t handle; int err; spin_lock_init(&(info->lock)); @@ -594,10 +593,8 @@ static int bt3c_open(bt3c_info_t *info) hdev->owner = THIS_MODULE; - handle = info->link.handle; - /* Load firmware */ - err = request_firmware(&firmware, "BT3CPCC.bin", &handle_to_dev(handle)); + err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev); if (err < 0) { BT_ERR("Firmware request failed"); goto error; @@ -651,14 +648,14 @@ static int bt3c_close(bt3c_info_t *info) static int bt3c_attach(struct pcmcia_device *p_dev) { bt3c_info_t *info; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); /* Create new info device */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - link = &info->link; + info->p_dev = p_dev; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -672,9 +669,6 @@ static int bt3c_attach(struct pcmcia_device *p_dev) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; bt3c_config(link); @@ -815,7 +809,7 @@ found_port: goto failed; strcpy(info->node.dev_name, info->hdev->name); - link->dev = &info->node; + link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; return; diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index ec19a577b4..cfe1d74a91 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -68,7 +68,7 @@ MODULE_LICENSE("GPL"); typedef struct btuart_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct hci_dev *hdev; @@ -146,13 +146,13 @@ static void btuart_write_wakeup(btuart_info_t *info) } do { - register unsigned int iobase = info->link.io.BasePort1; + register unsigned int iobase = info->p_dev->io.BasePort1; register struct sk_buff *skb; register int len; clear_bit(XMIT_WAKEUP, &(info->tx_state)); - if (!(info->link.state & DEV_PRESENT)) + if (!(info->p_dev->state & DEV_PRESENT)) return; if (!(skb = skb_dequeue(&(info->txq)))) @@ -187,7 +187,7 @@ static void btuart_receive(btuart_info_t *info) return; } - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; do { info->hdev->stat.byte_rx++; @@ -301,7 +301,7 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst, struct pt_regs *reg return IRQ_NONE; } - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; spin_lock(&(info->lock)); @@ -357,7 +357,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed) return; } - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; spin_lock_irqsave(&(info->lock), flags); @@ -481,7 +481,7 @@ static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned lon static int btuart_open(btuart_info_t *info) { unsigned long flags; - unsigned int iobase = info->link.io.BasePort1; + unsigned int iobase = info->p_dev->io.BasePort1; struct hci_dev *hdev; spin_lock_init(&(info->lock)); @@ -550,7 +550,7 @@ static int btuart_open(btuart_info_t *info) static int btuart_close(btuart_info_t *info) { unsigned long flags; - unsigned int iobase = info->link.io.BasePort1; + unsigned int iobase = info->p_dev->io.BasePort1; struct hci_dev *hdev = info->hdev; if (!hdev) @@ -579,14 +579,14 @@ static int btuart_close(btuart_info_t *info) static int btuart_attach(struct pcmcia_device *p_dev) { btuart_info_t *info; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); /* Create new info device */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - link = &info->link; + info->p_dev = p_dev; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -600,9 +600,6 @@ static int btuart_attach(struct pcmcia_device *p_dev) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; btuart_config(link); @@ -744,7 +741,7 @@ found_port: goto failed; strcpy(info->node.dev_name, info->hdev->name); - link->dev = &info->node; + link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; return; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 86617ee80e..389a68256f 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -68,7 +68,7 @@ MODULE_LICENSE("GPL"); typedef struct dtl1_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct hci_dev *hdev; @@ -153,13 +153,13 @@ static void dtl1_write_wakeup(dtl1_info_t *info) } do { - register unsigned int iobase = info->link.io.BasePort1; + register unsigned int iobase = info->p_dev->io.BasePort1; register struct sk_buff *skb; register int len; clear_bit(XMIT_WAKEUP, &(info->tx_state)); - if (!(info->link.state & DEV_PRESENT)) + if (!(info->p_dev->state & DEV_PRESENT)) return; if (!(skb = skb_dequeue(&(info->txq)))) @@ -218,7 +218,7 @@ static void dtl1_receive(dtl1_info_t *info) return; } - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; do { info->hdev->stat.byte_rx++; @@ -305,7 +305,7 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs) return IRQ_NONE; } - iobase = info->link.io.BasePort1; + iobase = info->p_dev->io.BasePort1; spin_lock(&(info->lock)); @@ -458,7 +458,7 @@ static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long static int dtl1_open(dtl1_info_t *info) { unsigned long flags; - unsigned int iobase = info->link.io.BasePort1; + unsigned int iobase = info->p_dev->io.BasePort1; struct hci_dev *hdev; spin_lock_init(&(info->lock)); @@ -504,7 +504,7 @@ static int dtl1_open(dtl1_info_t *info) outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */ outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR); - info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI; + info->ri_latch = inb(info->p_dev->io.BasePort1 + UART_MSR) & UART_MSR_RI; /* Turn on interrupts */ outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); @@ -529,7 +529,7 @@ static int dtl1_open(dtl1_info_t *info) static int dtl1_close(dtl1_info_t *info) { unsigned long flags; - unsigned int iobase = info->link.io.BasePort1; + unsigned int iobase = info->p_dev->io.BasePort1; struct hci_dev *hdev = info->hdev; if (!hdev) @@ -558,14 +558,14 @@ static int dtl1_close(dtl1_info_t *info) static int dtl1_attach(struct pcmcia_device *p_dev) { dtl1_info_t *info; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); /* Create new info device */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - link = &info->link; + info->p_dev = p_dev; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -579,9 +579,6 @@ static int dtl1_attach(struct pcmcia_device *p_dev) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; dtl1_config(link); @@ -696,7 +693,7 @@ static void dtl1_config(dev_link_t *link) goto failed; strcpy(info->node.dev_name, info->hdev->name); - link->dev = &info->node; + link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; return; diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index c996ae1375..3e6d6e0bb6 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -46,7 +46,7 @@ /* #define ATR_CSUM */ #ifdef PCMCIA_DEBUG -#define reader_to_dev(x) (&handle_to_dev(x->link.handle)) +#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle)) static int pc_debug = PCMCIA_DEBUG; module_param(pc_debug, int, 0600); #define DEBUGP(n, rdr, x, args...) do { \ @@ -106,7 +106,7 @@ static int major; /* major number we get from the kernel */ #define REG_STOPBITS(x) (x + 7) struct cm4000_dev { - dev_link_t link; /* pcmcia link */ + struct pcmcia_device *p_dev; dev_node_t node; /* OS node (major,minor) */ unsigned char atr[MAX_ATR]; @@ -454,7 +454,7 @@ static struct card_fixup card_fixups[] = { static void set_cardparameter(struct cm4000_dev *dev) { int i; - ioaddr_t iobase = dev->link.io.BasePort1; + ioaddr_t iobase = dev->p_dev->io.BasePort1; u_int8_t stopbits = 0x02; /* ISO default */ DEBUGP(3, dev, "-> set_cardparameter\n"); @@ -487,7 +487,7 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) unsigned short num_bytes_read; unsigned char pts_reply[4]; ssize_t rc; - ioaddr_t iobase = dev->link.io.BasePort1; + ioaddr_t iobase = dev->p_dev->io.BasePort1; rc = 0; @@ -699,7 +699,7 @@ static void terminate_monitor(struct cm4000_dev *dev) static void monitor_card(unsigned long p) { struct cm4000_dev *dev = (struct cm4000_dev *) p; - ioaddr_t iobase = dev->link.io.BasePort1; + ioaddr_t iobase = dev->p_dev->io.BasePort1; unsigned short s; struct ptsreq ptsreq; int i, atrc; @@ -962,7 +962,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, loff_t *ppos) { struct cm4000_dev *dev = filp->private_data; - ioaddr_t iobase = dev->link.io.BasePort1; + ioaddr_t iobase = dev->p_dev->io.BasePort1; ssize_t rc; int i, j, k; @@ -971,7 +971,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, if (count == 0) /* according to manpage */ return 0; - if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */ + if ((dev->p_dev->state & DEV_PRESENT) == 0 || /* socket removed */ test_bit(IS_CMM_ABSENT, &dev->flags)) return -ENODEV; @@ -1083,7 +1083,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data; - ioaddr_t iobase = dev->link.io.BasePort1; + ioaddr_t iobase = dev->p_dev->io.BasePort1; unsigned short s; unsigned char tmp; unsigned char infolen; @@ -1108,7 +1108,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0; - if ((dev->link.state & DEV_PRESENT) == 0 || /* socket removed */ + if ((dev->p_dev->state & DEV_PRESENT) == 0 || /* socket removed */ test_bit(IS_CMM_ABSENT, &dev->flags)) return -ENODEV; @@ -1440,7 +1440,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { struct cm4000_dev *dev = filp->private_data; - ioaddr_t iobase = dev->link.io.BasePort1; + ioaddr_t iobase = dev->p_dev->io.BasePort1; dev_link_t *link; int size; int rc; @@ -1844,7 +1844,7 @@ static void cm4000_config(dev_link_t * link, int devno) dev->node.major = major; dev->node.minor = devno; dev->node.next = NULL; - link->dev = &dev->node; + link->dev_node = &dev->node; link->state &= ~DEV_CONFIG_PENDING; return; @@ -1889,8 +1889,8 @@ static void cm4000_release(dev_link_t *link) static int cm4000_attach(struct pcmcia_device *p_dev) { struct cm4000_dev *dev; - dev_link_t *link; int i; + dev_link_t *link = dev_to_instance(p_dev); for (i = 0; i < CM4000_MAX_DEV; i++) if (dev_table[i] == NULL) @@ -1906,7 +1906,7 @@ static int cm4000_attach(struct pcmcia_device *p_dev) if (dev == NULL) return -ENOMEM; - link = &dev->link; + dev->p_dev = p_dev; link->priv = dev; link->conf.IntType = INT_MEMORY_AND_IO; dev_table[i] = link; @@ -1916,9 +1916,6 @@ static int cm4000_attach(struct pcmcia_device *p_dev) init_waitqueue_head(&dev->atrq); init_waitqueue_head(&dev->readq); - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; cm4000_config(link, i); diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 94ecd0342b..97e32e7f84 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -41,7 +41,7 @@ #ifdef PCMCIA_DEBUG -#define reader_to_dev(x) (&handle_to_dev(x->link.handle)) +#define reader_to_dev(x) (&handle_to_dev(x->p_dev->handle)) static int pc_debug = PCMCIA_DEBUG; module_param(pc_debug, int, 0600); #define DEBUGP(n, rdr, x, args...) do { \ @@ -74,7 +74,7 @@ static struct class *cmx_class; #define BS_WRITABLE 0x02 struct reader_dev { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; wait_queue_head_t devq; wait_queue_head_t poll_wait; @@ -116,7 +116,7 @@ static inline unsigned char xinb(unsigned short port) static void cm4040_do_poll(unsigned long dummy) { struct reader_dev *dev = (struct reader_dev *) dummy; - unsigned int obs = xinb(dev->link.io.BasePort1 + unsigned int obs = xinb(dev->p_dev->io.BasePort1 + REG_OFFSET_BUFFER_STATUS); if ((obs & BSR_BULK_IN_FULL)) { @@ -147,7 +147,7 @@ static void cm4040_stop_poll(struct reader_dev *dev) static int wait_for_bulk_out_ready(struct reader_dev *dev) { int i, rc; - int iobase = dev->link.io.BasePort1; + int iobase = dev->p_dev->io.BasePort1; for (i = 0; i < POLL_LOOP_COUNT; i++) { if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) @@ -177,7 +177,7 @@ static int wait_for_bulk_out_ready(struct reader_dev *dev) /* Write to Sync Control Register */ static int write_sync_reg(unsigned char val, struct reader_dev *dev) { - int iobase = dev->link.io.BasePort1; + int iobase = dev->p_dev->io.BasePort1; int rc; rc = wait_for_bulk_out_ready(dev); @@ -195,7 +195,7 @@ static int write_sync_reg(unsigned char val, struct reader_dev *dev) static int wait_for_bulk_in_ready(struct reader_dev *dev) { int i, rc; - int iobase = dev->link.io.BasePort1; + int iobase = dev->p_dev->io.BasePort1; for (i = 0; i < POLL_LOOP_COUNT; i++) { if ((xinb(iobase + REG_OFFSET_BUFFER_STATUS) @@ -225,7 +225,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { struct reader_dev *dev = filp->private_data; - int iobase = dev->link.io.BasePort1; + int iobase = dev->p_dev->io.BasePort1; size_t bytes_to_read; unsigned long i; size_t min_bytes_to_read; @@ -246,7 +246,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf, return -EAGAIN; } - if ((dev->link.state & DEV_PRESENT)==0) + if ((dev->p_dev->state & DEV_PRESENT)==0) return -ENODEV; for (i = 0; i < 5; i++) { @@ -328,7 +328,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { struct reader_dev *dev = filp->private_data; - int iobase = dev->link.io.BasePort1; + int iobase = dev->p_dev->io.BasePort1; ssize_t rc; int i; unsigned int bytes_to_write; @@ -351,7 +351,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, return -EAGAIN; } - if ((dev->link.state & DEV_PRESENT) == 0) + if ((dev->p_dev->state & DEV_PRESENT) == 0) return -ENODEV; bytes_to_write = count; @@ -606,7 +606,7 @@ static void reader_config(dev_link_t *link, int devno) dev->node.major = major; dev->node.minor = devno; dev->node.next = NULL; - link->dev = &dev->node; + link->dev_node = &dev->node; link->state &= ~DEV_CONFIG_PENDING; DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno, @@ -631,8 +631,8 @@ static void reader_release(dev_link_t *link) static int reader_attach(struct pcmcia_device *p_dev) { struct reader_dev *dev; - dev_link_t *link; int i; + dev_link_t *link = dev_to_instance(p_dev); for (i = 0; i < CM_MAX_DEV; i++) { if (dev_table[i] == NULL) @@ -649,8 +649,8 @@ static int reader_attach(struct pcmcia_device *p_dev) dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; dev->buffer_status = 0; - link = &dev->link; link->priv = dev; + dev->p_dev = p_dev; link->conf.IntType = INT_MEMORY_AND_IO; dev_table[i] = link; @@ -662,9 +662,6 @@ static int reader_attach(struct pcmcia_device *p_dev) init_timer(&dev->poll_timer); dev->poll_timer.function = &cm4040_do_poll; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; reader_config(link, i); diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index a6cbd32399..7b1e055184 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -228,7 +228,7 @@ typedef struct _mgslpc_info { struct _input_signal_events input_signal_events; /* PCMCIA support */ - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; int stop; @@ -536,11 +536,11 @@ static void ldisc_receive_buf(struct tty_struct *tty, static int mgslpc_attach(struct pcmcia_device *p_dev) { MGSLPC_INFO *info; - dev_link_t *link; - + dev_link_t *link = dev_to_instance(p_dev); + if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_attach\n"); - + info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); if (!info) { printk("Error can't allocate device instance data\n"); @@ -565,22 +565,19 @@ static int mgslpc_attach(struct pcmcia_device *p_dev) info->imrb_value = 0xffff; info->pim_value = 0xff; - link = &info->link; + info->p_dev = p_dev; link->priv = info; - + /* Initialize the dev_link_t structure */ /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = NULL; - + link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; mgslpc_config(link); @@ -673,7 +670,7 @@ static void mgslpc_config(dev_link_t *link) /* add to linked list of devices */ sprintf(info->node.dev_name, "mgslpc0"); info->node.major = info->node.minor = 0; - link->dev = &info->node; + link->dev_node = &info->node; printk(KERN_INFO "%s: index 0x%02x:", info->node.dev_name, link->conf.ConfigIndex); @@ -1259,7 +1256,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs) if (!info) return IRQ_NONE; - if (!(info->link.state & DEV_CONFIG)) + if (!(info->p_dev->state & DEV_CONFIG)) return IRQ_HANDLED; spin_lock(&info->lock); diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 3b5b55f85e..70bb1b8bab 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -81,7 +81,7 @@ static const char ide_major[] = { }; typedef struct ide_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; int ndev; dev_node_t node; int hd; @@ -106,7 +106,7 @@ static void ide_detach(struct pcmcia_device *p_dev); static int ide_attach(struct pcmcia_device *p_dev) { ide_info_t *info; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "ide_attach()\n"); @@ -114,7 +114,9 @@ static int ide_attach(struct pcmcia_device *p_dev) info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - link = &info->link; link->priv = info; + + info->p_dev = p_dev; + link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; @@ -124,9 +126,6 @@ static int ide_attach(struct pcmcia_device *p_dev) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; ide_config(link); @@ -326,7 +325,7 @@ static void ide_config(dev_link_t *link) info->node.major = ide_major[hd]; info->node.minor = 0; info->hd = hd; - link->dev = &info->node; + link->dev_node = &info->node; printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n", info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10); diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 0c504dc49a..3b7461ece5 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -101,49 +101,37 @@ typedef struct local_info_t { static int avmcs_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; local_info_t *local; - /* Initialize the dev_link_t structure */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); - if (!link) - goto err; - memset(link, 0, sizeof(struct dev_link_t)); - /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts2 = 0; + p_dev->io.NumPorts1 = 16; + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.NumPorts2 = 0; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + + p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - /* General socket configuration */ - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.ConfigIndex = 1; - link->conf.Present = PRESENT_OPTION; + p_dev->conf.Attributes = CONF_ENABLE_IRQ; + p_dev->conf.IntType = INT_MEMORY_AND_IO; + p_dev->conf.ConfigIndex = 1; + p_dev->conf.Present = PRESENT_OPTION; /* Allocate space for private device-specific data */ local = kmalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) - goto err_kfree; + goto err; memset(local, 0, sizeof(local_info_t)); - link->priv = local; - - link->handle = p_dev; - p_dev->instance = link; + p_dev->priv = local; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - avmcs_config(link); + p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + avmcs_config(p_dev); return 0; - err_kfree: - kfree(link); err: return -EINVAL; } /* avmcs_attach */ @@ -165,7 +153,6 @@ static void avmcs_detach(struct pcmcia_device *p_dev) avmcs_release(link); kfree(link->priv); - kfree(link); } /* avmcs_detach */ /*====================================================================== @@ -330,7 +317,7 @@ found_port: dev->node.major = 64; dev->node.minor = 0; - link->dev = &dev->node; + link->dev_node = &dev->node; link->state &= ~DEV_CONFIG_PENDING; /* If any step failed, release any partially configured state */ diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 8d23e5ab8d..f7143fe1a2 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -118,50 +118,39 @@ typedef struct local_info_t { static int avma1cs_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; local_info_t *local; DEBUG(0, "avma1cs_attach()\n"); - /* Initialize the dev_link_t structure */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); - if (!link) - return -ENOMEM; - memset(link, 0, sizeof(struct dev_link_t)); - /* Allocate space for private device-specific data */ local = kmalloc(sizeof(local_info_t), GFP_KERNEL); - if (!local) { - kfree(link); + if (!local) return -ENOMEM; - } + memset(local, 0, sizeof(local_info_t)); - link->priv = local; + p_dev->priv = local; /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts2 = 16; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_16; - link->io.IOAddrLines = 5; + p_dev->io.NumPorts1 = 16; + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.NumPorts2 = 16; + p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_16; + p_dev->io.IOAddrLines = 5; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; + p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; /* General socket configuration */ - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.ConfigIndex = 1; - link->conf.Present = PRESENT_OPTION; - - link->handle = p_dev; - p_dev->instance = link; + p_dev->conf.Attributes = CONF_ENABLE_IRQ; + p_dev->conf.IntType = INT_MEMORY_AND_IO; + p_dev->conf.ConfigIndex = 1; + p_dev->conf.Present = PRESENT_OPTION; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - avma1cs_config(link); + p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + avma1cs_config(p_dev); return 0; } /* avma1cs_attach */ @@ -185,7 +174,6 @@ static void avma1cs_detach(struct pcmcia_device *p_dev) avma1cs_release(link); kfree(link->priv); - kfree(link); } /* avma1cs_detach */ /*====================================================================== @@ -335,7 +323,7 @@ found_port: strcpy(dev->node.dev_name, "A1"); dev->node.major = 45; dev->node.minor = 0; - link->dev = &dev->node; + link->dev_node = &dev->node; link->state &= ~DEV_CONFIG_PENDING; /* If any step failed, release any partially configured state */ diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 00835d537c..bcda675e91 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -121,7 +121,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev); */ typedef struct local_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; int busy; int cardnr; @@ -141,8 +141,8 @@ typedef struct local_info_t { static int elsa_cs_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; local_info_t *local; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "elsa_cs_attach()\n"); @@ -150,8 +150,11 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev) local = kmalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; memset(local, 0, sizeof(local_info_t)); + + local->p_dev = p_dev; + link->priv = local; + local->cardnr = -1; - link = &local->link; link->priv = local; /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; @@ -172,9 +175,6 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; elsa_cs_config(link); @@ -320,7 +320,7 @@ static void elsa_cs_config(dev_link_t *link) sprintf(dev->node.dev_name, "elsa"); dev->node.major = dev->node.minor = 0x0; - link->dev = &dev->node; + link->dev_node = &dev->node; /* Finally, report what we've done */ printk(KERN_INFO "%s: index 0x%02x: ", diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index a3cd1c5563..6025722001 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -130,7 +130,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev); */ typedef struct local_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; int stop; int cardnr; @@ -151,7 +151,7 @@ typedef struct local_info_t { static int sedlbauer_attach(struct pcmcia_device *p_dev) { local_info_t *local; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "sedlbauer_attach()\n"); @@ -160,8 +160,10 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev) if (!local) return -ENOMEM; memset(local, 0, sizeof(local_info_t)); local->cardnr = -1; - link = &local->link; link->priv = local; - + + local->p_dev = p_dev; + link->priv = local; + /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; @@ -182,13 +184,9 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.IOAddrLines = 3; - link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; sedlbauer_config(link); @@ -397,7 +395,7 @@ static void sedlbauer_config(dev_link_t *link) */ sprintf(dev->node.dev_name, "sedlbauer"); dev->node.major = dev->node.minor = 0; - link->dev = &dev->node; + link->dev_node = &dev->node; /* Finally, report what we've done */ printk(KERN_INFO "%s: index 0x%02x:", diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 040f098d4b..ea16ebfc02 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -112,7 +112,7 @@ static void teles_detach(struct pcmcia_device *p_dev); */ typedef struct local_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; int busy; int cardnr; @@ -132,8 +132,8 @@ typedef struct local_info_t { static int teles_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; local_info_t *local; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "teles_attach()\n"); @@ -142,7 +142,9 @@ static int teles_attach(struct pcmcia_device *p_dev) if (!local) return -ENOMEM; memset(local, 0, sizeof(local_info_t)); local->cardnr = -1; - link = &local->link; link->priv = local; + + local->p_dev = p_dev; + link->priv = local; /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; @@ -163,9 +165,6 @@ static int teles_attach(struct pcmcia_device *p_dev) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; teles_cs_config(link); @@ -311,7 +310,7 @@ static void teles_cs_config(dev_link_t *link) sprintf(dev->node.dev_name, "teles"); dev->node.major = dev->node.minor = 0x0; - link->dev = &dev->node; + link->dev_node = &dev->node; /* Finally, report what we've done */ printk(KERN_INFO "%s: index 0x%02x:", diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 0026460be1..8259dca97e 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -54,7 +54,7 @@ static const int debug = 0; #define MAX_PCMCIA_ADDR 0x4000000 struct pcmciamtd_dev { - dev_link_t link; /* PCMCIA link */ + struct pcmcia_device *p_dev; dev_node_t node; /* device node */ caddr_t win_base; /* ioremapped address of PCMCIA window */ unsigned int win_size; /* size of window */ @@ -111,8 +111,8 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) memreq_t mrq; int ret; - if(!(dev->link.state & DEV_PRESENT)) { - DEBUG(1, "device removed state = 0x%4.4X", dev->link.state); + if(!(dev->p_dev->state & DEV_PRESENT)) { + DEBUG(1, "device removed state = 0x%4.4X", dev->p_dev->state); return 0; } @@ -122,7 +122,7 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) dev->offset, mrq.CardOffset); mrq.Page = 0; if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) { - cs_error(dev->link.handle, MapMemPage, ret); + cs_error(dev->p_dev->handle, MapMemPage, ret); return NULL; } dev->offset = mrq.CardOffset; @@ -319,7 +319,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f static void pcmciamtd_set_vpp(struct map_info *map, int on) { struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; - dev_link_t *link = &dev->link; + dev_link_t *link = dev->p_dev; modconf_t mod; int ret; @@ -650,7 +650,7 @@ static void pcmciamtd_config(dev_link_t *link) use the faster non-remapping read/write functions */ if(mtd->size <= dev->win_size) { DEBUG(1, "Using non remapping memory functions"); - dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state); + dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->p_dev->state); dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base; if (dev->pcmcia_map.bankwidth == 1) { dev->pcmcia_map.read = pcmcia_read8; @@ -673,7 +673,7 @@ static void pcmciamtd_config(dev_link_t *link) snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index); info("mtd%d: %s", mtd->index, mtd->name); link->state &= ~DEV_CONFIG_PENDING; - link->dev = &dev->node; + link->dev_node = &dev->node; return; cs_failed: @@ -735,7 +735,7 @@ static void pcmciamtd_detach(struct pcmcia_device *p_dev) static int pcmciamtd_attach(struct pcmcia_device *p_dev) { struct pcmciamtd_dev *dev; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); /* Create new memory card device */ dev = kmalloc(sizeof(*dev), GFP_KERNEL); @@ -743,16 +743,12 @@ static int pcmciamtd_attach(struct pcmcia_device *p_dev) DEBUG(1, "dev=0x%p", dev); memset(dev, 0, sizeof(*dev)); - link = &dev->link; + dev->p_dev = p_dev; link->priv = dev; link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY; - link->next = NULL; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; pcmciamtd_config(link); diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 179c9b7ad0..b65758d3c6 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -204,7 +204,7 @@ enum Window4 { /* Window 4: Xcvr/media bits. */ #define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */ struct el3_private { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats stats; u16 advertising, partner; /* NWay media advertisement */ @@ -259,8 +259,8 @@ static void tc574_detach(struct pcmcia_device *p_dev); static int tc574_attach(struct pcmcia_device *p_dev) { struct el3_private *lp; - dev_link_t *link; struct net_device *dev; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "3c574_attach()\n"); @@ -269,8 +269,8 @@ static int tc574_attach(struct pcmcia_device *p_dev) if (!dev) return -ENOMEM; lp = netdev_priv(dev); - link = &lp->link; link->priv = dev; + lp->p_dev = p_dev; spin_lock_init(&lp->window_lock); link->io.NumPorts1 = 32; @@ -297,9 +297,6 @@ static int tc574_attach(struct pcmcia_device *p_dev) dev->watchdog_timeo = TX_TIMEOUT; #endif - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; tc574_config(link); @@ -322,7 +319,7 @@ static void tc574_detach(struct pcmcia_device *p_dev) DEBUG(0, "3c574_detach(0x%p)\n", link); - if (link->dev) + if (link->dev_node) unregister_netdev(dev); if (link->state & DEV_CONFIG) @@ -473,12 +470,12 @@ static void tc574_config(dev_link_t *link) } link->state &= ~DEV_CONFIG_PENDING; - link->dev = &lp->node; + link->dev_node = &lp->node; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto failed; } @@ -742,7 +739,7 @@ static void tc574_reset(struct net_device *dev) static int el3_open(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; if (!DEV_OK(link)) return -ENODEV; @@ -1188,7 +1185,7 @@ static int el3_close(struct net_device *dev) { kio_addr_t ioaddr = dev->base_addr; struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; DEBUG(2, "%s: shutting down ethercard.\n", dev->name); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 7e8036f2e1..4faf1fa082 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -105,7 +105,7 @@ enum RxFilter { #define TX_TIMEOUT ((400*HZ)/1000) struct el3_private { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats stats; /* For transceiver monitoring */ @@ -173,8 +173,8 @@ static void tc589_detach(struct pcmcia_device *p_dev); static int tc589_attach(struct pcmcia_device *p_dev) { struct el3_private *lp; - dev_link_t *link; struct net_device *dev; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "3c589_attach()\n"); @@ -183,8 +183,8 @@ static int tc589_attach(struct pcmcia_device *p_dev) if (!dev) return -ENOMEM; lp = netdev_priv(dev); - link = &lp->link; link->priv = dev; + lp->p_dev = p_dev; spin_lock_init(&lp->lock); link->io.NumPorts1 = 16; @@ -212,9 +212,6 @@ static int tc589_attach(struct pcmcia_device *p_dev) #endif SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; tc589_config(link); @@ -237,7 +234,7 @@ static void tc589_detach(struct pcmcia_device *p_dev) DEBUG(0, "3c589_detach(0x%p)\n", link); - if (link->dev) + if (link->dev_node) unregister_netdev(dev); if (link->state & DEV_CONFIG) @@ -345,13 +342,13 @@ static void tc589_config(dev_link_t *link) else printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); - link->dev = &lp->node; + link->dev_node = &lp->node; link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if (register_netdev(dev) != 0) { printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto failed; } @@ -572,7 +569,7 @@ static int el3_config(struct net_device *dev, struct ifmap *map) static int el3_open(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; if (!DEV_OK(link)) return -ENODEV; @@ -833,7 +830,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); unsigned long flags; - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; if (DEV_OK(link)) { spin_lock_irqsave(&lp->lock, flags); @@ -935,7 +932,7 @@ static int el3_rx(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; kio_addr_t ioaddr = dev->base_addr; u16 opts = SetRxFilter | RxStation | RxBroadcast; @@ -950,7 +947,7 @@ static void set_multicast_list(struct net_device *dev) static int el3_close(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; kio_addr_t ioaddr = dev->base_addr; DEBUG(1, "%s: shutting down ethercard.\n", dev->name); diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 5ca0d57185..58dc7c3835 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -117,7 +117,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs *regs); /*====================================================================*/ typedef struct axnet_dev_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; caddr_t base; struct timer_list watchdog; @@ -145,8 +145,8 @@ static inline axnet_dev_t *PRIV(struct net_device *dev) static int axnet_attach(struct pcmcia_device *p_dev) { axnet_dev_t *info; - dev_link_t *link; struct net_device *dev; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "axnet_attach()\n"); @@ -157,7 +157,7 @@ static int axnet_attach(struct pcmcia_device *p_dev) return -ENOMEM; info = PRIV(dev); - link = &info->link; + info->p_dev = p_dev; link->priv = dev; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; @@ -169,9 +169,6 @@ static int axnet_attach(struct pcmcia_device *p_dev) dev->do_ioctl = &axnet_ioctl; SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; axnet_config(link); @@ -194,7 +191,7 @@ static void axnet_detach(struct pcmcia_device *p_dev) DEBUG(0, "axnet_detach(0x%p)\n", link); - if (link->dev) + if (link->dev_node) unregister_netdev(dev); if (link->state & DEV_CONFIG) @@ -409,13 +406,13 @@ static void axnet_config(dev_link_t *link) } info->phy_id = (i < 32) ? i : -1; - link->dev = &info->node; + link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto failed; } @@ -543,7 +540,7 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value) static int axnet_open(struct net_device *dev) { axnet_dev_t *info = PRIV(dev); - dev_link_t *link = &info->link; + dev_link_t *link = info->p_dev; DEBUG(2, "axnet_open('%s')\n", dev->name); @@ -569,7 +566,7 @@ static int axnet_open(struct net_device *dev) static int axnet_close(struct net_device *dev) { axnet_dev_t *info = PRIV(dev); - dev_link_t *link = &info->link; + dev_link_t *link = info->p_dev; DEBUG(2, "axnet_close('%s')\n", dev->name); diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index e14d3d18b9..44da01cdd2 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -140,7 +140,6 @@ typedef struct com20020_dev_t { static int com20020_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; com20020_dev_t *info; struct net_device *dev; struct arcnet_local *lp; @@ -148,10 +147,6 @@ static int com20020_attach(struct pcmcia_device *p_dev) DEBUG(0, "com20020_attach()\n"); /* Create new network device */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); - if (!link) - return -ENOMEM; - info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); if (!info) goto fail_alloc_info; @@ -161,7 +156,6 @@ static int com20020_attach(struct pcmcia_device *p_dev) goto fail_alloc_dev; memset(info, 0, sizeof(struct com20020_dev_t)); - memset(link, 0, sizeof(struct dev_link_t)); lp = dev->priv; lp->timeout = timeout; lp->backplane = backplane; @@ -172,27 +166,26 @@ static int com20020_attach(struct pcmcia_device *p_dev) /* fill in our module parameters as defaults */ dev->dev_addr[0] = node; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 16; - link->io.IOAddrLines = 16; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.Present = PRESENT_OPTION; + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.NumPorts1 = 16; + p_dev->io.IOAddrLines = 16; + p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; + p_dev->conf.Attributes = CONF_ENABLE_IRQ; + p_dev->conf.IntType = INT_MEMORY_AND_IO; + p_dev->conf.Present = PRESENT_OPTION; - link->irq.Instance = info->dev = dev; - link->priv = info; + p_dev->irq.Instance = info->dev = dev; + p_dev->priv = info; - link->state |= DEV_PRESENT; - com20020_config(link); + p_dev->state |= DEV_PRESENT; + com20020_config(p_dev); return 0; fail_alloc_dev: kfree(info); fail_alloc_info: - kfree(link); return -ENOMEM; } /* com20020_attach */ @@ -215,7 +208,7 @@ static void com20020_detach(struct pcmcia_device *p_dev) DEBUG(0, "com20020_detach(0x%p)\n", link); - if (link->dev) { + if (link->dev_node) { DEBUG(1,"unregister...\n"); unregister_netdev(dev); @@ -244,8 +237,6 @@ static void com20020_detach(struct pcmcia_device *p_dev) DEBUG(1,"kfree2...\n"); kfree(info); } - DEBUG(1,"kfree3...\n"); - kfree(link); } /* com20020_detach */ @@ -341,7 +332,7 @@ static void com20020_config(dev_link_t *link) lp->card_name = "PCMCIA COM20020"; lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ - link->dev = &info->node; + link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); @@ -349,7 +340,7 @@ static void com20020_config(dev_link_t *link) if (i != 0) { DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto failed; } diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 34bf963b12..3f0ace4ed7 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -116,7 +116,7 @@ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, driver specific data structure */ typedef struct local_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats stats; long open_time; @@ -231,8 +231,8 @@ typedef struct local_info_t { static int fmvj18x_attach(struct pcmcia_device *p_dev) { local_info_t *lp; - dev_link_t *link; struct net_device *dev; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "fmvj18x_attach()\n"); @@ -241,8 +241,8 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev) if (!dev) return -ENOMEM; lp = netdev_priv(dev); - link = &lp->link; link->priv = dev; + lp->p_dev = p_dev; /* The io structure describes IO port mapping */ link->io.NumPorts1 = 32; @@ -273,9 +273,6 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev) #endif SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; fmvj18x_config(link); @@ -291,7 +288,7 @@ static void fmvj18x_detach(struct pcmcia_device *p_dev) DEBUG(0, "fmvj18x_detach(0x%p)\n", link); - if (link->dev) + if (link->dev_node) unregister_netdev(dev); if (link->state & DEV_CONFIG) @@ -539,13 +536,13 @@ static void fmvj18x_config(dev_link_t *link) } lp->cardtype = cardtype; - link->dev = &lp->node; + link->dev_node = &lp->node; link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto failed; } @@ -1125,7 +1122,7 @@ static int fjn_config(struct net_device *dev, struct ifmap *map){ static int fjn_open(struct net_device *dev) { struct local_info_t *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; DEBUG(4, "fjn_open('%s').\n", dev->name); @@ -1150,7 +1147,7 @@ static int fjn_open(struct net_device *dev) static int fjn_close(struct net_device *dev) { struct local_info_t *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; kio_addr_t ioaddr = dev->base_addr; DEBUG(4, "fjn_close('%s').\n", dev->name); diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 904c5cb04e..f4c3dd870a 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -113,7 +113,7 @@ static void ibmtr_detach(struct pcmcia_device *p_dev); /*====================================================================*/ typedef struct ibmtr_dev_t { - dev_link_t link; + struct pcmcia_device *p_dev; struct net_device *dev; dev_node_t node; window_handle_t sram_win_handle; @@ -141,8 +141,8 @@ static struct ethtool_ops netdev_ethtool_ops = { static int ibmtr_attach(struct pcmcia_device *p_dev) { ibmtr_dev_t *info; - dev_link_t *link; struct net_device *dev; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "ibmtr_attach()\n"); @@ -156,7 +156,7 @@ static int ibmtr_attach(struct pcmcia_device *p_dev) return -ENOMEM; } - link = &info->link; + info->p_dev = p_dev; link->priv = info; info->ti = netdev_priv(dev); @@ -171,11 +171,8 @@ static int ibmtr_attach(struct pcmcia_device *p_dev) link->conf.Present = PRESENT_OPTION; link->irq.Instance = info->dev = dev; - - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - link->handle = p_dev; - p_dev->instance = link; + SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); link->state |= DEV_PRESENT; ibmtr_config(link); @@ -200,7 +197,7 @@ static void ibmtr_detach(struct pcmcia_device *p_dev) DEBUG(0, "ibmtr_detach(0x%p)\n", link); - if (link->dev) + if (link->dev_node) unregister_netdev(dev); { @@ -308,14 +305,14 @@ static void ibmtr_config(dev_link_t *link) Adapters Technical Reference" SC30-3585 for this info. */ ibmtr_hw_setup(dev, mmiobase); - link->dev = &info->node; + link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); i = ibmtr_probe_card(dev); if (i != 0) { printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto failed; } diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index c25d9451d5..0ccca12d9d 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -362,7 +362,7 @@ typedef struct _mace_statistics { } mace_statistics; typedef struct _mace_private { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats linux_stats; /* Linux statistics counters */ mace_statistics mace_stats; /* MACE chip statistics counters */ @@ -446,8 +446,8 @@ nmclan_attach static int nmclan_attach(struct pcmcia_device *p_dev) { mace_private *lp; - dev_link_t *link; struct net_device *dev; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "nmclan_attach()\n"); DEBUG(1, "%s\n", rcsid); @@ -457,7 +457,7 @@ static int nmclan_attach(struct pcmcia_device *p_dev) if (!dev) return -ENOMEM; lp = netdev_priv(dev); - link = &lp->link; + lp->p_dev = p_dev; link->priv = dev; spin_lock_init(&lp->bank_lock); @@ -488,9 +488,6 @@ static int nmclan_attach(struct pcmcia_device *p_dev) dev->watchdog_timeo = TX_TIMEOUT; #endif - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; nmclan_config(link); @@ -512,7 +509,7 @@ static void nmclan_detach(struct pcmcia_device *p_dev) DEBUG(0, "nmclan_detach(0x%p)\n", link); - if (link->dev) + if (link->dev_node) unregister_netdev(dev); if (link->state & DEV_CONFIG) @@ -729,14 +726,14 @@ static void nmclan_config(dev_link_t *link) else printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n"); - link->dev = &lp->node; + link->dev_node = &lp->node; link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); i = register_netdev(dev); if (i != 0) { printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto failed; } @@ -869,7 +866,7 @@ static int mace_open(struct net_device *dev) { kio_addr_t ioaddr = dev->base_addr; mace_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; if (!DEV_OK(link)) return -ENODEV; @@ -892,7 +889,7 @@ static int mace_close(struct net_device *dev) { kio_addr_t ioaddr = dev->base_addr; mace_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; DEBUG(2, "%s: shutting down ethercard.\n", dev->name); @@ -947,7 +944,7 @@ mace_start_xmit static void mace_tx_timeout(struct net_device *dev) { mace_private *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name); #if RESET_ON_TIMEOUT diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 5a7e58af0b..8ed6a410ea 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -214,7 +214,7 @@ static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII }; static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII }; typedef struct pcnet_dev_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; u_int flags; void __iomem *base; @@ -243,8 +243,8 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev) static int pcnet_probe(struct pcmcia_device *p_dev) { pcnet_dev_t *info; - dev_link_t *link; struct net_device *dev; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "pcnet_attach()\n"); @@ -252,7 +252,7 @@ static int pcnet_probe(struct pcmcia_device *p_dev) dev = __alloc_ei_netdev(sizeof(pcnet_dev_t)); if (!dev) return -ENOMEM; info = PRIV(dev); - link = &info->link; + info->p_dev = p_dev; link->priv = dev; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; @@ -265,9 +265,6 @@ static int pcnet_probe(struct pcmcia_device *p_dev) dev->stop = &pcnet_close; dev->set_config = &set_config; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; pcnet_config(link); @@ -290,7 +287,7 @@ static void pcnet_detach(struct pcmcia_device *p_dev) DEBUG(0, "pcnet_detach(0x%p)\n", link); - if (link->dev) + if (link->dev_node) unregister_netdev(dev); if (link->state & DEV_CONFIG) @@ -674,7 +671,7 @@ static void pcnet_config(dev_link_t *link) info->eth_phy = 0; } - link->dev = &info->node; + link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); @@ -684,7 +681,7 @@ static void pcnet_config(dev_link_t *link) if (register_netdev(dev) != 0) { printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto failed; } @@ -1005,8 +1002,8 @@ static void mii_phy_probe(struct net_device *dev) static int pcnet_open(struct net_device *dev) { pcnet_dev_t *info = PRIV(dev); - dev_link_t *link = &info->link; - + dev_link_t *link = info->p_dev; + DEBUG(2, "pcnet_open('%s')\n", dev->name); if (!DEV_OK(link)) @@ -1033,7 +1030,7 @@ static int pcnet_open(struct net_device *dev) static int pcnet_close(struct net_device *dev) { pcnet_dev_t *info = PRIV(dev); - dev_link_t *link = &info->link; + dev_link_t *link = info->p_dev; DEBUG(2, "pcnet_close('%s')\n", dev->name); diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index b46b7e1483..a18b02a9a6 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -104,7 +104,7 @@ static const char *version = #define MEMORY_WAIT_TIME 8 struct smc_private { - dev_link_t link; + struct pcmcia_device *p_dev; spinlock_t lock; u_short manfid; u_short cardid; @@ -312,8 +312,8 @@ static struct ethtool_ops ethtool_ops; static int smc91c92_attach(struct pcmcia_device *p_dev) { struct smc_private *smc; - dev_link_t *link; struct net_device *dev; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "smc91c92_attach()\n"); @@ -322,7 +322,7 @@ static int smc91c92_attach(struct pcmcia_device *p_dev) if (!dev) return -ENOMEM; smc = netdev_priv(dev); - link = &smc->link; + smc->p_dev = p_dev; link->priv = dev; spin_lock_init(&smc->lock); @@ -357,9 +357,6 @@ static int smc91c92_attach(struct pcmcia_device *p_dev) smc->mii_if.phy_id_mask = 0x1f; smc->mii_if.reg_num_mask = 0x1f; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; smc91c92_config(link); @@ -382,7 +379,7 @@ static void smc91c92_detach(struct pcmcia_device *p_dev) DEBUG(0, "smc91c92_detach(0x%p)\n", link); - if (link->dev) + if (link->dev_node) unregister_netdev(dev); if (link->state & DEV_CONFIG) @@ -1120,13 +1117,13 @@ static void smc91c92_config(dev_link_t *link) SMC_SELECT_BANK(0); } - link->dev = &smc->node; + link->dev_node = &smc->node; link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if (register_netdev(dev) != 0) { printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto config_undo; } @@ -1272,7 +1269,7 @@ static void smc_dump(struct net_device *dev) static int smc_open(struct net_device *dev) { struct smc_private *smc = netdev_priv(dev); - dev_link_t *link = &smc->link; + dev_link_t *link = smc->p_dev; #ifdef PCMCIA_DEBUG DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n", @@ -1309,7 +1306,7 @@ static int smc_open(struct net_device *dev) static int smc_close(struct net_device *dev) { struct smc_private *smc = netdev_priv(dev); - dev_link_t *link = &smc->link; + dev_link_t *link = smc->p_dev; kio_addr_t ioaddr = dev->base_addr; DEBUG(0, "%s: smc_close(), status %4.4x.\n", diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index f5fa86d046..94a1e644ab 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -332,7 +332,7 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs */ typedef struct local_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats stats; int card_type; @@ -555,9 +555,9 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len) static int xirc2ps_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; struct net_device *dev; local_info_t *local; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "attach()\n"); @@ -566,7 +566,7 @@ xirc2ps_attach(struct pcmcia_device *p_dev) if (!dev) return -ENOMEM; local = netdev_priv(dev); - link = &local->link; + local->p_dev = p_dev; link->priv = dev; /* General socket configuration */ @@ -592,9 +592,6 @@ xirc2ps_attach(struct pcmcia_device *p_dev) dev->watchdog_timeo = TX_TIMEOUT; #endif - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; xirc2ps_config(link); @@ -616,7 +613,7 @@ xirc2ps_detach(struct pcmcia_device *p_dev) DEBUG(0, "detach(0x%p)\n", link); - if (link->dev) + if (link->dev_node) unregister_netdev(dev); if (link->state & DEV_CONFIG) @@ -1049,13 +1046,13 @@ xirc2ps_config(dev_link_t * link) if (local->dingo) do_reset(dev, 1); /* a kludge to make the cem56 work */ - link->dev = &local->node; + link->dev_node = &local->node; link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(handle)); if ((err=register_netdev(dev))) { printk(KNOT_XIRC "register_netdev() failed\n"); - link->dev = NULL; + link->dev_node = NULL; goto config_error; } @@ -1537,7 +1534,7 @@ static int do_open(struct net_device *dev) { local_info_t *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; DEBUG(0, "do_open(%p)\n", dev); @@ -1867,7 +1864,7 @@ do_stop(struct net_device *dev) { kio_addr_t ioaddr = dev->base_addr; local_info_t *lp = netdev_priv(dev); - dev_link_t *link = &lp->link; + dev_link_t *link = lp->p_dev; DEBUG(0, "do_stop(%p)\n", dev); diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 2216c04a02..836c71ff77 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -143,22 +143,14 @@ typedef struct local_info_t { static int airo_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; local_info_t *local; DEBUG(0, "airo_attach()\n"); - /* Initialize the dev_link_t structure */ - link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); - if (!link) { - printk(KERN_ERR "airo_cs: no memory for new device\n"); - return -ENOMEM; - } - /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.Handler = NULL; + p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; + p_dev->irq.Handler = NULL; /* General socket configuration defaults can go here. In this @@ -167,23 +159,19 @@ static int airo_attach(struct pcmcia_device *p_dev) and attributes of IO windows) are fixed by the nature of the device, and can be hard-wired here. */ - link->conf.Attributes = 0; - link->conf.IntType = INT_MEMORY_AND_IO; + p_dev->conf.Attributes = 0; + p_dev->conf.IntType = INT_MEMORY_AND_IO; /* Allocate space for private device-specific data */ local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) { printk(KERN_ERR "airo_cs: no memory for new device\n"); - kfree (link); return -ENOMEM; } - link->priv = local; - - link->handle = p_dev; - p_dev->instance = link; + p_dev->priv = local; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - airo_config(link); + p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + airo_config(p_dev); return 0; } /* airo_attach */ @@ -212,7 +200,6 @@ static void airo_detach(struct pcmcia_device *p_dev) ((local_info_t*)link->priv)->eth_dev = NULL; kfree(link->priv); - kfree(link); } /* airo_detach */ /*====================================================================== @@ -378,11 +365,11 @@ static void airo_config(dev_link_t *link) /* At this point, the dev_node_t structure(s) need to be - initialized and arranged in a linked list at link->dev. + initialized and arranged in a linked list at link->dev_node. */ strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); dev->node.major = dev->node.minor = 0; - link->dev = &dev->node; + link->dev_node = &dev->node; /* Finally, report what we've done */ printk(KERN_INFO "%s: index 0x%02x: ", diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 53fdaa2222..522bbed47a 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -154,22 +154,14 @@ typedef struct local_info_t { static int atmel_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; local_info_t *local; DEBUG(0, "atmel_attach()\n"); - /* Initialize the dev_link_t structure */ - link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); - if (!link) { - printk(KERN_ERR "atmel_cs: no memory for new device\n"); - return -ENOMEM; - } - /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.Handler = NULL; + p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; + p_dev->irq.Handler = NULL; /* General socket configuration defaults can go here. In this @@ -178,23 +170,19 @@ static int atmel_attach(struct pcmcia_device *p_dev) and attributes of IO windows) are fixed by the nature of the device, and can be hard-wired here. */ - link->conf.Attributes = 0; - link->conf.IntType = INT_MEMORY_AND_IO; + p_dev->conf.Attributes = 0; + p_dev->conf.IntType = INT_MEMORY_AND_IO; /* Allocate space for private device-specific data */ local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) { printk(KERN_ERR "atmel_cs: no memory for new device\n"); - kfree (link); return -ENOMEM; } - link->priv = local; - - link->handle = p_dev; - p_dev->instance = link; + p_dev->priv = local; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - atmel_config(link); + p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + atmel_config(p_dev); return 0; } /* atmel_attach */ @@ -218,7 +206,6 @@ static void atmel_detach(struct pcmcia_device *p_dev) atmel_release(link); kfree(link->priv); - kfree(link); } /*====================================================================== @@ -387,11 +374,11 @@ static void atmel_config(dev_link_t *link) /* At this point, the dev_node_t structure(s) need to be - initialized and arranged in a linked list at link->dev. + initialized and arranged in a linked list at link->dev_node. */ strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); dev->node.major = dev->node.minor = 0; - link->dev = &dev->node; + link->dev_node = &dev->node; link->state &= ~DEV_CONFIG_PENDING; return; diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 69024bfb5b..e3095a8874 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -503,22 +503,11 @@ static struct prism2_helper_functions prism2_pccard_funcs = * initialize dev_link structure, but do not configure the card yet */ static int prism2_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; - - link = kmalloc(sizeof(dev_link_t), GFP_KERNEL); - if (link == NULL) - return -ENOMEM; - - memset(link, 0, sizeof(dev_link_t)); - PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); - link->conf.IntType = INT_MEMORY_AND_IO; - - link->handle = p_dev; - p_dev->instance = link; + p_dev->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - if (prism2_config(link)) + p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + if (prism2_config(p_dev)) PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n"); return 0; @@ -546,7 +535,6 @@ static void prism2_detach(struct pcmcia_device *p_dev) prism2_free_local_data(dev); kfree(hw_priv); } - kfree(link); } @@ -713,7 +701,7 @@ static int prism2_config(dev_link_t *link) local->hw_priv = hw_priv; hw_priv->link = link; strcpy(hw_priv->node.dev_name, dev->name); - link->dev = &hw_priv->node; + link->dev_node = &hw_priv->node; /* * Allocate an interrupt line. Note that this does not assign a diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 23d6b3376e..68dfe68ffe 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -268,7 +268,7 @@ struct site_survey { }; typedef struct netwave_private { - dev_link_t link; + struct pcmcia_device *p_dev; spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ dev_node_t node; u_char __iomem *ramBase; @@ -378,9 +378,9 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev) */ static int netwave_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; struct net_device *dev; netwave_private *priv; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "netwave_attach()\n"); @@ -389,7 +389,7 @@ static int netwave_attach(struct pcmcia_device *p_dev) if (!dev) return -ENOMEM; priv = netdev_priv(dev); - link = &priv->link; + priv->p_dev = p_dev; link->priv = dev; /* The io structure describes IO port mapping */ @@ -429,9 +429,6 @@ static int netwave_attach(struct pcmcia_device *p_dev) dev->stop = &netwave_close; link->irq.Instance = dev; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; netwave_pcmcia_config( link); @@ -456,7 +453,7 @@ static void netwave_detach(struct pcmcia_device *p_dev) if (link->state & DEV_CONFIG) netwave_release(link); - if (link->dev) + if (link->dev_node) unregister_netdev(dev); free_netdev(dev); @@ -830,7 +827,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { } strcpy(priv->node.dev_name, dev->name); - link->dev = &priv->node; + link->dev_node = &priv->node; link->state &= ~DEV_CONFIG_PENDING; /* Reset card before reading physical address */ @@ -1103,7 +1100,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs u_char __iomem *ramBase; struct net_device *dev = (struct net_device *)dev_id; struct netwave_private *priv = netdev_priv(dev); - dev_link_t *link = &priv->link; + dev_link_t *link = priv->p_dev; int i; if (!netif_device_present(dev)) @@ -1357,7 +1354,7 @@ static int netwave_rx(struct net_device *dev) static int netwave_open(struct net_device *dev) { netwave_private *priv = netdev_priv(dev); - dev_link_t *link = &priv->link; + dev_link_t *link = priv->p_dev; DEBUG(1, "netwave_open: starting.\n"); @@ -1374,7 +1371,7 @@ static int netwave_open(struct net_device *dev) { static int netwave_close(struct net_device *dev) { netwave_private *priv = netdev_priv(dev); - dev_link_t *link = &priv->link; + dev_link_t *link = priv->p_dev; DEBUG(1, "netwave_close: finishing.\n"); diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 75981d88a1..f10d97bc45 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -49,7 +49,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket /* PCMCIA specific device information (goes in the card field of * struct orinoco_private */ struct orinoco_pccard { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; /* Used to handle hard reset */ @@ -75,7 +75,7 @@ static int orinoco_cs_hard_reset(struct orinoco_private *priv) { struct orinoco_pccard *card = priv->card; - dev_link_t *link = &card->link; + dev_link_t *link = card->p_dev; int err; /* We need atomic ops here, because we're not holding the lock */ @@ -109,7 +109,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev) struct net_device *dev; struct orinoco_private *priv; struct orinoco_pccard *card; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); if (! dev) @@ -118,7 +118,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev) card = priv->card; /* Link both structures together */ - link = &card->link; + card->p_dev = p_dev; link->priv = dev; /* Interrupt setup */ @@ -135,12 +135,6 @@ orinoco_cs_attach(struct pcmcia_device *p_dev) link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; - /* Register with Card Services */ - link->next = NULL; - - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; orinoco_cs_config(link); @@ -161,8 +155,8 @@ static void orinoco_cs_detach(struct pcmcia_device *p_dev) if (link->state & DEV_CONFIG) orinoco_cs_release(link); - DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); - if (link->dev) { + DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); + if (link->dev_node) { DEBUG(0, PFX "About to unregister net device %p\n", dev); unregister_netdev(dev); @@ -364,9 +358,9 @@ orinoco_cs_config(dev_link_t *link) } /* At this point, the dev_node_t structure(s) needs to be - * initialized and arranged in a linked list at link->dev. */ + * initialized and arranged in a linked list at link->dev_node. */ strcpy(card->node.dev_name, dev->name); - link->dev = &card->node; /* link->dev being non-NULL is also + link->dev_node = &card->node; /* link->dev_node being non-NULL is also used to indicate that the net_device has been registered */ link->state &= ~DEV_CONFIG_PENDING; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 7d95587d09..60297460de 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -190,12 +190,6 @@ static int bc; static char *phy_addr = NULL; -/* A linked list of "instances" of the ray device. Each actual - PCMCIA card corresponds to one device instance, and is described - by one dev_link_t structure (defined in ds.h). -*/ -static dev_link_t *dev_list = NULL; - /* A dev_link_t structure has fields for most things that are needed to keep track of a socket, but there will usually be some device specific information that also needs to be kept track of. The @@ -204,6 +198,9 @@ static dev_link_t *dev_list = NULL; */ static unsigned int ray_mem_speed = 500; +/* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */ +static struct pcmcia_device *this_device = NULL; + MODULE_AUTHOR("Corey Thomas "); MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver"); MODULE_LICENSE("GPL"); @@ -308,53 +305,44 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey priv; - - memset(link, 0, sizeof(struct dev_link_t)); + local->finder = p_dev; /* The io structure describes IO port mapping. None used here */ - link->io.NumPorts1 = 0; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = 5; + p_dev->io.NumPorts1 = 0; + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.IOAddrLines = 5; /* Interrupt setup. For PCMCIA, driver takes what's given */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.Handler = &ray_interrupt; + p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; + p_dev->irq.Handler = &ray_interrupt; /* General socket configuration */ - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.ConfigIndex = 1; - link->conf.Present = PRESENT_OPTION; + p_dev->conf.Attributes = CONF_ENABLE_IRQ; + p_dev->conf.IntType = INT_MEMORY_AND_IO; + p_dev->conf.ConfigIndex = 1; + p_dev->conf.Present = PRESENT_OPTION; - link->priv = dev; - link->irq.Instance = dev; + p_dev->priv = dev; + p_dev->irq.Instance = dev; - local->finder = link; + local->finder = p_dev; local->card_status = CARD_INSERTED; local->authentication_state = UNAUTHENTICATED; local->num_multi = 0; - DEBUG(2,"ray_attach link = %p, dev = %p, local = %p, intr = %p\n", - link,dev,local,&ray_interrupt); + DEBUG(2,"ray_attach p_dev = %p, dev = %p, local = %p, intr = %p\n", + p_dev,dev,local,&ray_interrupt); /* Raylink entries in the device structure */ dev->hard_start_xmit = &ray_dev_start_xmit; @@ -378,16 +366,13 @@ static int ray_attach(struct pcmcia_device *p_dev) init_timer(&local->timer); - link->handle = p_dev; - p_dev->instance = link; - - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - ray_config(link); + p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + this_device = p_dev; + ray_config(p_dev); return 0; fail_alloc_dev: - kfree(link); return -ENOMEM; } /* ray_attach */ /*============================================================================= @@ -399,18 +384,12 @@ fail_alloc_dev: static void ray_detach(struct pcmcia_device *p_dev) { dev_link_t *link = dev_to_instance(p_dev); - dev_link_t **linkp; struct net_device *dev; ray_dev_t *local; DEBUG(1, "ray_detach(0x%p)\n", link); - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) break; - if (*linkp == NULL) - return; + this_device = NULL; dev = link->priv; if (link->state & DEV_CONFIG) { @@ -420,13 +399,10 @@ static void ray_detach(struct pcmcia_device *p_dev) del_timer(&local->timer); } - /* Unlink device structure, free pieces */ - *linkp = link->next; if (link->priv) { - if (link->dev) unregister_netdev(dev); + if (link->dev_node) unregister_netdev(dev); free_netdev(dev); } - kfree(link); DEBUG(2,"ray_cs ray_detach ending\n"); } /* ray_detach */ /*============================================================================= @@ -537,7 +513,7 @@ static void ray_config(dev_link_t *link) } strcpy(local->node.dev_name, dev->name); - link->dev = &local->node; + link->dev_node = &local->node; link->state &= ~DEV_CONFIG_PENDING; printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ", @@ -1640,18 +1616,14 @@ static const struct iw_handler_def ray_handler_def = /*===========================================================================*/ static int ray_open(struct net_device *dev) { - dev_link_t *link; ray_dev_t *local = (ray_dev_t *)dev->priv; + dev_link_t *link; + link = local->finder; DEBUG(1, "ray_open('%s')\n", dev->name); - for (link = dev_list; link; link = link->next) - if (link->priv == dev) break; - if (!DEV_OK(link)) { - return -ENODEV; - } - - if (link->open == 0) local->num_multi = 0; + if (link->open == 0) + local->num_multi = 0; link->open++; /* If the card is not started, time to start it ! - Jean II */ @@ -1678,15 +1650,12 @@ static int ray_open(struct net_device *dev) /*===========================================================================*/ static int ray_dev_close(struct net_device *dev) { + ray_dev_t *local = (ray_dev_t *)dev->priv; dev_link_t *link; + link = local->finder; DEBUG(1, "ray_dev_close('%s')\n", dev->name); - for (link = dev_list; link; link = link->next) - if (link->priv == dev) break; - if (link == NULL) - return -ENODEV; - link->open--; netif_stop_queue(dev); @@ -2679,7 +2648,7 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len) struct freq_hop_element *pfh; UCHAR c[33]; - link = dev_list; + link = this_device; if (!link) return 0; dev = (struct net_device *)link->priv; @@ -2923,7 +2892,6 @@ static void __exit exit_ray_cs(void) #endif pcmcia_unregister_driver(&ray_driver); - BUG_ON(dev_list != NULL); } /* exit_ray_cs */ module_init(init_ray_cs); diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 7a4a80b01f..be36679c8c 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -63,7 +63,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket /* PCMCIA specific device information (goes in the card field of * struct orinoco_private */ struct orinoco_pccard { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; }; @@ -554,12 +554,12 @@ static int spectrum_cs_hard_reset(struct orinoco_private *priv) { struct orinoco_pccard *card = priv->card; - dev_link_t *link = &card->link; + dev_link_t *link = card->p_dev; int err; if (!hermes_present(&priv->hw)) { /* The firmware needs to be reloaded */ - if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) { + if (spectrum_dl_firmware(&priv->hw, link) != 0) { printk(KERN_ERR PFX "Firmware download failed\n"); err = -ENODEV; } @@ -589,7 +589,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev) struct net_device *dev; struct orinoco_private *priv; struct orinoco_pccard *card; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); if (! dev) @@ -598,7 +598,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev) card = priv->card; /* Link both structures together */ - link = &card->link; + card->p_dev = p_dev; link->priv = dev; /* Interrupt setup */ @@ -615,9 +615,6 @@ spectrum_cs_attach(struct pcmcia_device *p_dev) link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; spectrum_cs_config(link); @@ -638,8 +635,8 @@ static void spectrum_cs_detach(struct pcmcia_device *p_dev) if (link->state & DEV_CONFIG) spectrum_cs_release(link); - DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); - if (link->dev) { + DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); + if (link->dev_node) { DEBUG(0, PFX "About to unregister net device %p\n", dev); unregister_netdev(dev); @@ -842,9 +839,9 @@ spectrum_cs_config(dev_link_t *link) } /* At this point, the dev_node_t structure(s) needs to be - * initialized and arranged in a linked list at link->dev. */ + * initialized and arranged in a linked list at link->dev_node. */ strcpy(card->node.dev_name, dev->name); - link->dev = &card->node; /* link->dev being non-NULL is also + link->dev_node = &card->node; /* link->dev_node being non-NULL is also used to indicate that the net_device has been registered */ link->state &= ~DEV_CONFIG_PENDING; diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index daa17dc343..baa1011e70 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4081,7 +4081,7 @@ wv_pcmcia_config(dev_link_t * link) } strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name); - link->dev = &((net_local *) netdev_priv(dev))->node; + link->dev_node = &((net_local *) netdev_priv(dev))->node; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "<-wv_pcmcia_config()\n"); @@ -4583,7 +4583,6 @@ wavelan_close(struct net_device * dev) static int wavelan_attach(struct pcmcia_device *p_dev) { - dev_link_t * link; /* Info for cardmgr */ struct net_device * dev; /* Interface generic data */ net_local * lp; /* Interface specific data */ @@ -4591,34 +4590,26 @@ wavelan_attach(struct pcmcia_device *p_dev) printk(KERN_DEBUG "-> wavelan_attach()\n"); #endif - /* Initialize the dev_link_t structure */ - link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); - if (!link) return -ENOMEM; - /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 8; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = 3; + p_dev->io.NumPorts1 = 8; + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.IOAddrLines = 3; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.Handler = wavelan_interrupt; + p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; + p_dev->irq.Handler = wavelan_interrupt; /* General socket configuration */ - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - - /* Chain drivers */ - link->next = NULL; + p_dev->conf.Attributes = CONF_ENABLE_IRQ; + p_dev->conf.IntType = INT_MEMORY_AND_IO; /* Allocate the generic data structure */ dev = alloc_etherdev(sizeof(net_local)); - if (!dev) { - kfree(link); + if (!dev) return -ENOMEM; - } - link->priv = link->irq.Instance = dev; + + p_dev->priv = p_dev->irq.Instance = dev; lp = netdev_priv(dev); @@ -4635,7 +4626,6 @@ wavelan_attach(struct pcmcia_device *p_dev) spin_lock_init(&lp->spinlock); /* back links */ - lp->link = link; lp->dev = dev; /* wavelan NET3 callbacks */ @@ -4661,11 +4651,8 @@ wavelan_attach(struct pcmcia_device *p_dev) /* Other specific data */ dev->mtu = WAVELAN_MTU; - link->handle = p_dev; - p_dev->instance = link; - - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - if(wv_pcmcia_config(link) && + p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + if(wv_pcmcia_config(p_dev) && wv_hw_config(dev)) wv_init_info(dev); else @@ -4713,14 +4700,13 @@ wavelan_detach(struct pcmcia_device *p_dev) /* Remove ourselves from the kernel list of ethernet devices */ /* Warning : can't be called from interrupt, timer or wavelan_close() */ - if (link->dev) + if (link->dev_node) unregister_netdev(dev); - link->dev = NULL; + link->dev_node = NULL; ((net_local *)netdev_priv(dev))->link = NULL; ((net_local *)netdev_priv(dev))->dev = NULL; free_netdev(dev); } - kfree(link); #ifdef DEBUG_CALLBACK_TRACE printk(KERN_DEBUG "<- wavelan_detach()\n"); diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h index 4303c50c2a..65ceb088f7 100644 --- a/drivers/net/wireless/wl3501.h +++ b/drivers/net/wireless/wl3501.h @@ -611,5 +611,6 @@ struct wl3501_card { struct iw_spy_data spy_data; struct iw_public_data wireless_data; struct dev_node_t node; + struct pcmcia_device *p_dev; }; #endif diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 393b5cb7a5..4b054f54e9 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -226,17 +226,6 @@ static void iw_copy_mgmt_info_element(struct iw_mgmt_info_element *to, iw_set_mgmt_info_element(from->id, to, from->data, from->len); } -/* - * A linked list of "instances" of the wl24 device. Each actual PCMCIA card - * corresponds to one device instance, and is described by one dev_link_t - * structure (defined in ds.h). - * - * You may not want to use a linked list for this -- for example, the memory - * card driver uses an array of dev_link_t pointers, where minor device numbers - * are used to derive the corresponding array index. - */ -static dev_link_t *wl3501_dev_list; - static inline void wl3501_switch_page(struct wl3501_card *this, u8 page) { wl3501_outb(page, this->base_addr + WL3501_NIC_BSS); @@ -1282,14 +1271,9 @@ static int wl3501_close(struct net_device *dev) int rc = -ENODEV; unsigned long flags; dev_link_t *link; + link = this->p_dev; spin_lock_irqsave(&this->lock, flags); - /* Check if the device is in wl3501_dev_list */ - for (link = wl3501_dev_list; link; link = link->next) - if (link->priv == dev) - break; - if (!link) - goto out; link->open--; /* Stop wl3501_hard_start_xmit() from now on */ @@ -1301,7 +1285,6 @@ static int wl3501_close(struct net_device *dev) rc = 0; printk(KERN_INFO "%s: WL3501 closed\n", dev->name); -out: spin_unlock_irqrestore(&this->lock, flags); return rc; } @@ -1401,12 +1384,9 @@ static int wl3501_open(struct net_device *dev) struct wl3501_card *this = dev->priv; unsigned long flags; dev_link_t *link; + link = this->p_dev; spin_lock_irqsave(&this->lock, flags); - /* Check if the device is in wl3501_dev_list */ - for (link = wl3501_dev_list; link; link = link->next) - if (link->priv == dev) - break; if (!DEV_OK(link)) goto out; netif_device_attach(dev); @@ -1500,16 +1480,8 @@ static struct ethtool_ops ops = { static void wl3501_detach(struct pcmcia_device *p_dev) { dev_link_t *link = dev_to_instance(p_dev); - dev_link_t **linkp; struct net_device *dev = link->priv; - /* Locate device structure */ - for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) - break; - if (!*linkp) - goto out; - /* If the device is currently configured and active, we won't actually * delete it yet. Instead, it is marked so that when the release() * function is called, that will trigger a proper detach(). */ @@ -1522,13 +1494,9 @@ static void wl3501_detach(struct pcmcia_device *p_dev) wl3501_release(link); } - /* Unlink device structure, free pieces */ - *linkp = link->next; - if (link->priv) free_netdev(link->priv); - kfree(link); -out: + return; } @@ -1955,14 +1923,9 @@ static const struct iw_handler_def wl3501_handler_def = { */ static int wl3501_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; struct net_device *dev; struct wl3501_card *this; - - /* Initialize the dev_link_t structure */ - link = kzalloc(sizeof(*link), GFP_KERNEL); - if (!link) - return -ENOMEM; + dev_link_t *link = dev_to_instance(p_dev); /* The io structure describes IO port mapping */ link->io.NumPorts1 = 16; @@ -1991,22 +1954,18 @@ static int wl3501_attach(struct pcmcia_device *p_dev) dev->get_stats = wl3501_get_stats; this = dev->priv; this->wireless_data.spy_data = &this->spy_data; + this->p_dev = p_dev; dev->wireless_data = &this->wireless_data; dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def; SET_ETHTOOL_OPS(dev, &ops); netif_stop_queue(dev); link->priv = link->irq.Instance = dev; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - wl3501_config(link); + wl3501_config(p_dev); return 0; out_link: - kfree(link); - link = NULL; return -ENOMEM; } @@ -2087,9 +2046,9 @@ static void wl3501_config(dev_link_t *link) this = dev->priv; /* * At this point, the dev_node_t structure(s) should be initialized and - * arranged in a linked list at link->dev. + * arranged in a linked list at link->dev_node. */ - link->dev = &this->node; + link->dev_node = &this->node; link->state &= ~DEV_CONFIG_PENDING; this->base_addr = dev->base_addr; @@ -2148,7 +2107,7 @@ static void wl3501_release(dev_link_t *link) struct net_device *dev = link->priv; /* Unlink the device chain */ - if (link->dev) + if (link->dev_node) unregister_netdev(dev); pcmcia_disable_device(link->handle); @@ -2206,9 +2165,7 @@ static int __init wl3501_init_module(void) static void __exit wl3501_exit_module(void) { - dprintk(0, ": unloading"); pcmcia_unregister_driver(&wl3501_driver); - BUG_ON(wl3501_dev_list != NULL); } module_init(wl3501_init_module); diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 8d60146c72..ad2738ae22 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -81,7 +81,7 @@ static char *version = #define FORCE_EPP_MODE 0x08 typedef struct parport_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; int ndev; dev_node_t node; struct parport *port; @@ -102,7 +102,7 @@ static void parport_cs_release(dev_link_t *); static int parport_attach(struct pcmcia_device *p_dev) { parport_info_t *info; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "parport_attach()\n"); @@ -110,7 +110,8 @@ static int parport_attach(struct pcmcia_device *p_dev) info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; memset(info, 0, sizeof(*info)); - link = &info->link; link->priv = info; + link->priv = info; + info->p_dev = p_dev; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; @@ -119,9 +120,6 @@ static int parport_attach(struct pcmcia_device *p_dev) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; parport_config(link); @@ -239,7 +237,7 @@ void parport_config(dev_link_t *link) info->node.minor = p->number; info->port = p; strcpy(info->node.dev_name, p->name); - link->dev = &info->node; + link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; return; diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 488448a12b..4ab956843d 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -391,6 +391,7 @@ static int pcmcia_device_probe(struct device * dev) } p_dev->p_state &= ~CLIENT_UNBOUND; + p_dev->handle = p_dev; ret = p_drv->probe(p_dev); if (ret) @@ -1039,12 +1040,10 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) ret = p_drv->suspend(p_dev); if (ret) return ret; - if (p_dev->instance) { - p_dev->instance->state |= DEV_SUSPEND; - if ((p_dev->instance->state & DEV_CONFIG) && - !(p_dev->instance->state & DEV_SUSPEND_NORELEASE)) + p_dev->state |= DEV_SUSPEND; + if ((p_dev->state & DEV_CONFIG) && + !(p_dev->state & DEV_SUSPEND_NORELEASE)) pcmcia_release_configuration(p_dev); - } } return 0; @@ -1061,16 +1060,14 @@ static int pcmcia_dev_resume(struct device * dev) p_drv = to_pcmcia_drv(dev->driver); if (p_drv && p_drv->resume) { - if (p_dev->instance) { - p_dev->instance->state &= ~DEV_SUSPEND; - if ((p_dev->instance->state & DEV_CONFIG) && - !(p_dev->instance->state & DEV_SUSPEND_NORELEASE)){ + p_dev->state &= ~DEV_SUSPEND; + if ((p_dev->state & DEV_CONFIG) && + !(p_dev->state & DEV_SUSPEND_NORELEASE)){ ret = pcmcia_request_configuration(p_dev, - &p_dev->instance->conf); + &p_dev->conf); if (ret) return ret; } - } return p_drv->resume(p_dev); } diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index be08bc9e99..2b11a33217 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -229,7 +229,7 @@ static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info) * by userspace before, we need to * return the "instance". */ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - bind_info->instance = p_dev->instance; + bind_info->instance = p_dev; ret = -EBUSY; goto err_put_module; } else { @@ -358,16 +358,15 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int found: spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - if ((!p_dev->instance) || - (p_dev->instance->state & DEV_CONFIG_PENDING)) { + if (p_dev->state & DEV_CONFIG_PENDING) { ret = -EAGAIN; goto err_put; } if (first) - node = p_dev->instance->dev; + node = p_dev->dev_node; else - for (node = p_dev->instance->dev; node; node = node->next) + for (node = p_dev->dev_node; node; node = node->next) if (node == bind_info->next) break; if (!node) { diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index ab0bbb6207..93ab9402d3 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -942,15 +942,12 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h EXPORT_SYMBOL(pcmcia_request_window); void pcmcia_disable_device(struct pcmcia_device *p_dev) { - if (!p_dev->instance) - return; - pcmcia_release_configuration(p_dev); - pcmcia_release_io(p_dev, &p_dev->instance->io); - pcmcia_release_irq(p_dev, &p_dev->instance->irq); - if (&p_dev->instance->win) - pcmcia_release_window(p_dev->instance->win); + pcmcia_release_io(p_dev, &p_dev->io); + pcmcia_release_irq(p_dev, &p_dev->irq); + if (&p_dev->win) + pcmcia_release_window(p_dev->win); - p_dev->instance->dev = NULL; + p_dev->dev_node = NULL; } EXPORT_SYMBOL(pcmcia_disable_device); diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 12ec94d6ef..0c196fbb31 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -89,7 +89,7 @@ MODULE_LICENSE("Dual MPL/GPL"); /*====================================================================*/ typedef struct scsi_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct Scsi_Host *host; } scsi_info_t; @@ -103,7 +103,7 @@ static dev_link_t *dev_list; static int aha152x_attach(struct pcmcia_device *p_dev) { scsi_info_t *info; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "aha152x_attach()\n"); @@ -111,7 +111,8 @@ static int aha152x_attach(struct pcmcia_device *p_dev) info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; memset(info, 0, sizeof(*info)); - link = &info->link; link->priv = info; + info->p_dev = p_dev; + link->priv = info; link->io.NumPorts1 = 0x20; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; @@ -122,9 +123,6 @@ static int aha152x_attach(struct pcmcia_device *p_dev) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; aha152x_config_cs(link); @@ -136,23 +134,14 @@ static int aha152x_attach(struct pcmcia_device *p_dev) static void aha152x_detach(struct pcmcia_device *p_dev) { dev_link_t *link = dev_to_instance(p_dev); - dev_link_t **linkp; DEBUG(0, "aha152x_detach(0x%p)\n", link); - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) break; - if (*linkp == NULL) - return; if (link->state & DEV_CONFIG) aha152x_release_cs(link); /* Unlink device structure, free bits */ - *linkp = link->next; kfree(link->priv); - } /* aha152x_detach */ /*====================================================================*/ @@ -230,7 +219,7 @@ static void aha152x_config_cs(dev_link_t *link) } sprintf(info->node.dev_name, "scsi%d", host->host_no); - link->dev = &info->node; + link->dev_node = &info->node; info->host = host; link->state &= ~DEV_CONFIG_PENDING; diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index b3cd206ad6..94dcee9f28 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -73,7 +73,7 @@ static char *version = /*====================================================================*/ typedef struct scsi_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct Scsi_Host *host; } scsi_info_t; @@ -86,7 +86,7 @@ static void fdomain_config(dev_link_t *link); static int fdomain_attach(struct pcmcia_device *p_dev) { scsi_info_t *info; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "fdomain_attach()\n"); @@ -94,7 +94,8 @@ static int fdomain_attach(struct pcmcia_device *p_dev) info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; memset(info, 0, sizeof(*info)); - link = &info->link; link->priv = info; + info->p_dev = p_dev; + link->priv = info; link->io.NumPorts1 = 0x10; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.IOAddrLines = 10; @@ -104,9 +105,6 @@ static int fdomain_attach(struct pcmcia_device *p_dev) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; fdomain_config(link); @@ -191,7 +189,7 @@ static void fdomain_config(dev_link_t *link) scsi_scan_host(host); sprintf(info->node.dev_name, "scsi%d", host->host_no); - link->dev = &info->node; + link->dev_node = &info->node; info->host = host; link->state &= ~DEV_CONFIG_PENDING; diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index e41e1febe8..23548fbf48 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1596,8 +1596,8 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt) static int nsp_cs_attach(struct pcmcia_device *p_dev) { scsi_info_t *info; - dev_link_t *link; nsp_hw_data *data = &nsp_data_base; + dev_link_t *link = dev_to_instance(p_dev); nsp_dbg(NSP_DEBUG_INIT, "in"); @@ -1605,7 +1605,7 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev) info = kmalloc(sizeof(*info), GFP_KERNEL); if (info == NULL) { return -ENOMEM; } memset(info, 0, sizeof(*info)); - link = &info->link; + info->p_dev = p_dev; link->priv = info; data->ScsiInfo = info; @@ -1630,9 +1630,6 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; nsp_cs_config(link); @@ -1853,12 +1850,12 @@ static void nsp_cs_config(dev_link_t *link) scsi_scan_host(host); snprintf(info->node.dev_name, sizeof(info->node.dev_name), "scsi%d", host->host_no); - link->dev = &info->node; + link->dev_node = &info->node; info->host = host; #else nsp_dbg(NSP_DEBUG_INIT, "GET_SCSI_INFO"); - tail = &link->dev; + tail = &link->dev_node; info->ndev = 0; nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host); @@ -1962,7 +1959,7 @@ static void nsp_cs_release(dev_link_t *link) #else scsi_unregister_host(&nsp_driver_template); #endif - link->dev = NULL; + link->dev_node = NULL; if (link->win) { if (data != NULL) { diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index b66b140a74..2e1fde467c 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -225,7 +225,7 @@ /*====================================================================*/ typedef struct scsi_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; struct Scsi_Host *host; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74)) dev_node_t node; diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 4f28589bbf..c6b3e9587f 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -91,7 +91,7 @@ static struct scsi_host_template qlogicfas_driver_template = { /*====================================================================*/ typedef struct scsi_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct Scsi_Host *host; unsigned short manf_id; @@ -159,7 +159,7 @@ err: static int qlogic_attach(struct pcmcia_device *p_dev) { scsi_info_t *info; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "qlogic_attach()\n"); @@ -168,7 +168,7 @@ static int qlogic_attach(struct pcmcia_device *p_dev) if (!info) return -ENOMEM; memset(info, 0, sizeof(*info)); - link = &info->link; + info->p_dev = p_dev; link->priv = info; link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; @@ -179,9 +179,6 @@ static int qlogic_attach(struct pcmcia_device *p_dev) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; qlogic_config(link); @@ -278,7 +275,7 @@ static void qlogic_config(dev_link_t * link) } sprintf(info->node.dev_name, "scsi%d", host->host_no); - link->dev = &info->node; + link->dev_node = &info->node; info->host = host; out: diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 2bce7b070a..1ef3109418 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -202,7 +202,7 @@ static char *version = /* ================================================================== */ struct scsi_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; struct Scsi_Host *host; unsigned short manf_id; @@ -829,7 +829,7 @@ next_entry: data->fast_pio = USE_FAST_PIO; sprintf(info->node.dev_name, "scsi%d", host->host_no); - link->dev = &info->node; + link->dev_node = &info->node; info->host = host; if (scsi_add_host(host, NULL)) @@ -899,7 +899,7 @@ static int SYM53C500_attach(struct pcmcia_device *p_dev) { struct scsi_info_t *info; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "SYM53C500_attach()\n"); @@ -908,7 +908,7 @@ SYM53C500_attach(struct pcmcia_device *p_dev) if (!info) return -ENOMEM; memset(info, 0, sizeof(*info)); - link = &info->link; + info->p_dev = p_dev; link->priv = info; link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; @@ -919,9 +919,6 @@ SYM53C500_attach(struct pcmcia_device *p_dev) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; SYM53C500_config(link); diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 1e6889f52b..6bcde2c7b1 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -97,7 +97,7 @@ static const struct multi_id multi_id[] = { #define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id)) struct serial_info { - dev_link_t link; + struct pcmcia_device *p_dev; int ndev; int multi; int slave; @@ -135,16 +135,16 @@ static void serial_remove(dev_link_t *link) /* * Recheck to see if the device is still configured. */ - if (info->link.state & DEV_CONFIG) { + if (info->p_dev->state & DEV_CONFIG) { for (i = 0; i < info->ndev; i++) serial8250_unregister_port(info->line[i]); - info->link.dev = NULL; + info->p_dev->dev_node = NULL; if (!info->slave) pcmcia_disable_device(link->handle); - info->link.state &= ~DEV_CONFIG; + info->p_dev->state &= ~DEV_CONFIG; } } @@ -192,7 +192,7 @@ static int serial_resume(struct pcmcia_device *dev) static int serial_probe(struct pcmcia_device *p_dev) { struct serial_info *info; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "serial_attach()\n"); @@ -201,7 +201,7 @@ static int serial_probe(struct pcmcia_device *p_dev) if (!info) return -ENOMEM; memset(info, 0, sizeof (*info)); - link = &info->link; + info->p_dev = p_dev; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -215,8 +215,6 @@ static int serial_probe(struct pcmcia_device *p_dev) } link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; serial_config(link); @@ -660,7 +658,7 @@ void serial_config(dev_link_t * link) } } - link->dev = &info->node[0]; + link->dev_node = &info->node[0]; link->state &= ~DEV_CONFIG_PENDING; kfree(cfg_mem); return; diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index de794b21d7..0afd6c04f2 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -40,30 +40,20 @@ static void ixj_cs_release(dev_link_t * link); static int ixj_attach(struct pcmcia_device *p_dev) { - dev_link_t *link; - DEBUG(0, "ixj_attach()\n"); /* Create new ixj device */ - link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); - if (!link) - return -ENOMEM; - memset(link, 0, sizeof(struct dev_link_t)); - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = 3; - link->conf.IntType = INT_MEMORY_AND_IO; - link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL); - if (!link->priv) { - kfree(link); + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_8; + p_dev->io.IOAddrLines = 3; + p_dev->conf.IntType = INT_MEMORY_AND_IO; + p_dev->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL); + if (!p_dev->priv) { return -ENOMEM; } - memset(link->priv, 0, sizeof(struct ixj_info_t)); - - link->handle = p_dev; - p_dev->instance = link; + memset(p_dev->priv, 0, sizeof(struct ixj_info_t)); - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - ixj_config(link); + p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + ixj_config(p_dev); return 0; } @@ -79,7 +69,6 @@ static void ixj_detach(struct pcmcia_device *p_dev) ixj_cs_release(link); kfree(link->priv); - kfree(link); } #define CS_CHECK(fn, ret) \ @@ -212,7 +201,7 @@ static void ixj_config(dev_link_t * link) info->ndev = 1; info->node.major = PHONE_MAJOR; - link->dev = &info->node; + link->dev_node = &info->node; ixj_get_serial(link, j); link->state &= ~DEV_CONFIG_PENDING; return; diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index c6f1baf541..8e61faa120 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -67,7 +67,7 @@ module_param(pc_debug, int, 0644); static const char driver_name[DEV_NAME_LEN] = "sl811_cs"; typedef struct local_info_t { - dev_link_t link; + struct pcmcia_device *p_dev; dev_node_t node; } local_info_t; @@ -268,7 +268,7 @@ next_entry: sprintf(dev->node.dev_name, driver_name); dev->node.major = dev->node.minor = 0; - link->dev = &dev->node; + link->dev_node = &dev->node; printk(KERN_INFO "%s: index 0x%02x: ", dev->node.dev_name, link->conf.ConfigIndex); @@ -294,13 +294,13 @@ cs_failed: static int sl811_cs_attach(struct pcmcia_device *p_dev) { local_info_t *local; - dev_link_t *link; + dev_link_t *link = dev_to_instance(p_dev); local = kmalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; memset(local, 0, sizeof(local_info_t)); - link = &local->link; + local->p_dev = p_dev; link->priv = local; /* Initialize */ @@ -311,9 +311,6 @@ static int sl811_cs_attach(struct pcmcia_device *p_dev) link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; - link->handle = p_dev; - p_dev->instance = link; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; sl811_cs_config(link); -- cgit v1.2.2 From fba395eee7d3f342ca739c20f5b3ee635d0420a0 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Fri, 31 Mar 2006 17:21:06 +0200 Subject: [PATCH] pcmcia: remove dev_link_t and client_handle_t indirection dev_link_t * and client_handle_t both mean struct pcmcai_device * by now. Therefore, remove all such indirections. Signed-off-by: Dominik Brodowski --- drivers/bluetooth/bluecard_cs.c | 37 +++++------ drivers/bluetooth/bt3c_cs.c | 51 +++++++------- drivers/bluetooth/btuart_cs.c | 51 +++++++------- drivers/bluetooth/dtl1_cs.c | 45 ++++++------- drivers/char/pcmcia/cm4000_cs.c | 55 +++++++-------- drivers/char/pcmcia/cm4040_cs.c | 53 +++++++-------- drivers/char/pcmcia/synclink_cs.c | 46 ++++++------- drivers/ide/legacy/ide-cs.c | 60 ++++++++--------- drivers/isdn/hardware/avm/avm_cs.c | 60 ++++++++--------- drivers/isdn/hisax/avma1_cs.c | 60 ++++++++--------- drivers/isdn/hisax/elsa_cs.c | 50 ++++++-------- drivers/isdn/hisax/sedlbauer_cs.c | 58 ++++++++-------- drivers/isdn/hisax/teles_cs.c | 54 +++++++-------- drivers/mtd/maps/pcmciamtd.c | 55 ++++++++------- drivers/net/pcmcia/3c574_cs.c | 57 ++++++++-------- drivers/net/pcmcia/3c589_cs.c | 59 ++++++++--------- drivers/net/pcmcia/axnet_cs.c | 63 ++++++++---------- drivers/net/pcmcia/com20020_cs.c | 39 +++++------ drivers/net/pcmcia/fmvj18x_cs.c | 97 +++++++++++++-------------- drivers/net/pcmcia/ibmtr_cs.c | 49 ++++++-------- drivers/net/pcmcia/nmclan_cs.c | 61 ++++++++--------- drivers/net/pcmcia/pcnet_cs.c | 91 ++++++++++++------------- drivers/net/pcmcia/smc91c92_cs.c | 114 +++++++++++++++----------------- drivers/net/pcmcia/xirc2ps_cs.c | 108 ++++++++++++++---------------- drivers/net/wireless/airo_cs.c | 58 ++++++++-------- drivers/net/wireless/atmel_cs.c | 56 +++++++--------- drivers/net/wireless/hostap/hostap_cs.c | 82 +++++++++++------------ drivers/net/wireless/netwave_cs.c | 61 ++++++++--------- drivers/net/wireless/orinoco_cs.c | 59 ++++++++--------- drivers/net/wireless/ray_cs.c | 92 ++++++++++++-------------- drivers/net/wireless/ray_cs.h | 2 +- drivers/net/wireless/spectrum_cs.c | 80 +++++++++++----------- drivers/net/wireless/wavelan_cs.c | 67 +++++++++---------- drivers/net/wireless/wavelan_cs.p.h | 6 +- drivers/net/wireless/wl3501_cs.c | 67 +++++++++---------- drivers/parport/parport_cs.c | 42 ++++++------ drivers/pcmcia/cs_internal.h | 2 +- drivers/pcmcia/ds.c | 1 - drivers/scsi/pcmcia/aha152x_stub.c | 49 ++++++-------- drivers/scsi/pcmcia/fdomain_stub.c | 46 ++++++------- drivers/scsi/pcmcia/nsp_cs.c | 50 ++++++-------- drivers/scsi/pcmcia/nsp_cs.h | 6 +- drivers/scsi/pcmcia/qlogic_stub.c | 54 +++++++-------- drivers/scsi/pcmcia/sym53c500_cs.c | 45 ++++++------- drivers/serial/serial_cs.c | 111 ++++++++++++++----------------- drivers/telephony/ixj_pcmcia.c | 44 ++++++------ drivers/usb/host/sl811_cs.c | 46 ++++++------- 47 files changed, 1193 insertions(+), 1406 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index b461411eab..e557f2359c 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -85,8 +85,8 @@ typedef struct bluecard_info_t { } bluecard_info_t; -static void bluecard_config(dev_link_t *link); -static void bluecard_release(dev_link_t *link); +static void bluecard_config(struct pcmcia_device *link); +static void bluecard_release(struct pcmcia_device *link); static void bluecard_detach(struct pcmcia_device *p_dev); @@ -856,17 +856,16 @@ static int bluecard_close(bluecard_info_t *info) return 0; } -static int bluecard_attach(struct pcmcia_device *p_dev) +static int bluecard_attach(struct pcmcia_device *link) { bluecard_info_t *info; - dev_link_t *link = dev_to_instance(p_dev); /* Create new info device */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -887,9 +886,8 @@ static int bluecard_attach(struct pcmcia_device *p_dev) } -static void bluecard_detach(struct pcmcia_device *p_dev) +static void bluecard_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); bluecard_info_t *info = link->priv; if (link->state & DEV_CONFIG) @@ -899,7 +897,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev) } -static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i; @@ -914,9 +912,8 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse return pcmcia_parse_tuple(handle, tuple, parse); } -static void bluecard_config(dev_link_t *link) +static void bluecard_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; bluecard_info_t *info = link->priv; tuple_t tuple; u_short buf[256]; @@ -930,7 +927,7 @@ static void bluecard_config(dev_link_t *link) /* Get configuration register information */ tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(handle, &tuple, &parse); + last_ret = first_tuple(link, &tuple, &parse); if (last_ret != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; @@ -947,25 +944,25 @@ static void bluecard_config(dev_link_t *link) for (n = 0; n < 0x400; n += 0x40) { link->io.BasePort1 = n ^ 0x300; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); goto failed; } - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); + cs_error(link, RequestIRQ, i); link->irq.AssignedIRQ = 0; } - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); + cs_error(link, RequestConfiguration, i); goto failed; } @@ -979,14 +976,14 @@ static void bluecard_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: bluecard_release(link); } -static void bluecard_release(dev_link_t *link) +static void bluecard_release(struct pcmcia_device *link) { bluecard_info_t *info = link->priv; @@ -995,7 +992,7 @@ static void bluecard_release(dev_link_t *link) del_timer(&(info->timer)); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } static struct pcmcia_device_id bluecard_ids[] = { diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 9192a754eb..7ea8fa350d 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -88,8 +88,8 @@ typedef struct bt3c_info_t { } bt3c_info_t; -static void bt3c_config(dev_link_t *link); -static void bt3c_release(dev_link_t *link); +static void bt3c_config(struct pcmcia_device *link); +static void bt3c_release(struct pcmcia_device *link); static void bt3c_detach(struct pcmcia_device *p_dev); @@ -645,17 +645,16 @@ static int bt3c_close(bt3c_info_t *info) return 0; } -static int bt3c_attach(struct pcmcia_device *p_dev) +static int bt3c_attach(struct pcmcia_device *link) { bt3c_info_t *info; - dev_link_t *link = dev_to_instance(p_dev); /* Create new info device */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -676,9 +675,8 @@ static int bt3c_attach(struct pcmcia_device *p_dev) } -static void bt3c_detach(struct pcmcia_device *p_dev) +static void bt3c_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); bt3c_info_t *info = link->priv; if (link->state & DEV_CONFIG) @@ -687,7 +685,7 @@ static void bt3c_detach(struct pcmcia_device *p_dev) kfree(info); } -static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i; @@ -698,24 +696,23 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) return CS_NO_MORE_ITEMS; return get_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) return CS_NO_MORE_ITEMS; return get_tuple(handle, tuple, parse); } -static void bt3c_config(dev_link_t *link) +static void bt3c_config(struct pcmcia_device *link) { static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; - client_handle_t handle = link->handle; bt3c_info_t *info = link->priv; tuple_t tuple; u_short buf[256]; @@ -730,7 +727,7 @@ static void bt3c_config(dev_link_t *link) /* Get configuration register information */ tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(handle, &tuple, &parse); + last_ret = first_tuple(link, &tuple, &parse); if (last_ret != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; @@ -749,7 +746,7 @@ static void bt3c_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; /* Two tries: without IO aliases, then with aliases */ for (try = 0; try < 2; try++) { - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i != CS_NO_MORE_ITEMS) { if (i != CS_SUCCESS) goto next_entry; @@ -759,49 +756,49 @@ static void bt3c_config(dev_link_t *link) link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } next_entry: - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } } /* Second pass: try to find an entry that isn't picky about its base address, then try to grab any standard serial port address, and finally try to get any free port. */ - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i != CS_NO_MORE_ITEMS) { if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { link->conf.ConfigIndex = cf->index; for (j = 0; j < 5; j++) { link->io.BasePort1 = base[j]; link->io.IOAddrLines = base[j] ? 16 : 3; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } found_port: if (i != CS_SUCCESS) { BT_ERR("No usable port range found"); - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); goto failed; } - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); + cs_error(link, RequestIRQ, i); link->irq.AssignedIRQ = 0; } - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); + cs_error(link, RequestConfiguration, i); goto failed; } @@ -815,21 +812,21 @@ found_port: return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: bt3c_release(link); } -static void bt3c_release(dev_link_t *link) +static void bt3c_release(struct pcmcia_device *link) { bt3c_info_t *info = link->priv; if (link->state & DEV_PRESENT) bt3c_close(info); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index cfe1d74a91..5948390613 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -84,8 +84,8 @@ typedef struct btuart_info_t { } btuart_info_t; -static void btuart_config(dev_link_t *link); -static void btuart_release(dev_link_t *link); +static void btuart_config(struct pcmcia_device *link); +static void btuart_release(struct pcmcia_device *link); static void btuart_detach(struct pcmcia_device *p_dev); @@ -576,17 +576,16 @@ static int btuart_close(btuart_info_t *info) return 0; } -static int btuart_attach(struct pcmcia_device *p_dev) +static int btuart_attach(struct pcmcia_device *link) { btuart_info_t *info; - dev_link_t *link = dev_to_instance(p_dev); /* Create new info device */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -607,9 +606,8 @@ static int btuart_attach(struct pcmcia_device *p_dev) } -static void btuart_detach(struct pcmcia_device *p_dev) +static void btuart_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); btuart_info_t *info = link->priv; if (link->state & DEV_CONFIG) @@ -618,7 +616,7 @@ static void btuart_detach(struct pcmcia_device *p_dev) kfree(info); } -static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i; @@ -629,24 +627,23 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) return CS_NO_MORE_ITEMS; return get_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) return CS_NO_MORE_ITEMS; return get_tuple(handle, tuple, parse); } -static void btuart_config(dev_link_t *link) +static void btuart_config(struct pcmcia_device *link) { static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; - client_handle_t handle = link->handle; btuart_info_t *info = link->priv; tuple_t tuple; u_short buf[256]; @@ -661,7 +658,7 @@ static void btuart_config(dev_link_t *link) /* Get configuration register information */ tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(handle, &tuple, &parse); + last_ret = first_tuple(link, &tuple, &parse); if (last_ret != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; @@ -680,7 +677,7 @@ static void btuart_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; /* Two tries: without IO aliases, then with aliases */ for (try = 0; try < 2; try++) { - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i != CS_NO_MORE_ITEMS) { if (i != CS_SUCCESS) goto next_entry; @@ -690,19 +687,19 @@ static void btuart_config(dev_link_t *link) link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } next_entry: - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } } /* Second pass: try to find an entry that isn't picky about its base address, then try to grab any standard serial port address, and finally try to get any free port. */ - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i != CS_NO_MORE_ITEMS) { if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { @@ -710,30 +707,30 @@ next_entry: for (j = 0; j < 5; j++) { link->io.BasePort1 = base[j]; link->io.IOAddrLines = base[j] ? 16 : 3; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } found_port: if (i != CS_SUCCESS) { BT_ERR("No usable port range found"); - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); goto failed; } - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); + cs_error(link, RequestIRQ, i); link->irq.AssignedIRQ = 0; } - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); + cs_error(link, RequestConfiguration, i); goto failed; } @@ -747,21 +744,21 @@ found_port: return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: btuart_release(link); } -static void btuart_release(dev_link_t *link) +static void btuart_release(struct pcmcia_device *link) { btuart_info_t *info = link->priv; if (link->state & DEV_PRESENT) btuart_close(info); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } static struct pcmcia_device_id btuart_ids[] = { diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 389a68256f..416433b4a3 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -87,8 +87,8 @@ typedef struct dtl1_info_t { } dtl1_info_t; -static void dtl1_config(dev_link_t *link); -static void dtl1_release(dev_link_t *link); +static void dtl1_config(struct pcmcia_device *link); +static void dtl1_release(struct pcmcia_device *link); static void dtl1_detach(struct pcmcia_device *p_dev); @@ -555,17 +555,16 @@ static int dtl1_close(dtl1_info_t *info) return 0; } -static int dtl1_attach(struct pcmcia_device *p_dev) +static int dtl1_attach(struct pcmcia_device *link) { dtl1_info_t *info; - dev_link_t *link = dev_to_instance(p_dev); /* Create new info device */ info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -586,9 +585,8 @@ static int dtl1_attach(struct pcmcia_device *p_dev) } -static void dtl1_detach(struct pcmcia_device *p_dev) +static void dtl1_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); dtl1_info_t *info = link->priv; if (link->state & DEV_CONFIG) @@ -597,7 +595,7 @@ static void dtl1_detach(struct pcmcia_device *p_dev) kfree(info); } -static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i; @@ -608,23 +606,22 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) return CS_NO_MORE_ITEMS; return get_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS) return CS_NO_MORE_ITEMS; return get_tuple(handle, tuple, parse); } -static void dtl1_config(dev_link_t *link) +static void dtl1_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; dtl1_info_t *info = link->priv; tuple_t tuple; u_short buf[256]; @@ -639,7 +636,7 @@ static void dtl1_config(dev_link_t *link) /* Get configuration register information */ tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(handle, &tuple, &parse); + last_ret = first_tuple(link, &tuple, &parse); if (last_ret != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; @@ -658,34 +655,34 @@ static void dtl1_config(dev_link_t *link) /* Look for a generic full-sized window */ link->io.NumPorts1 = 8; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i != CS_NO_MORE_ITEMS) { if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) { link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; link->io.NumPorts1 = cf->io.win[0].len; /*yo */ link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); goto failed; } - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); + cs_error(link, RequestIRQ, i); link->irq.AssignedIRQ = 0; } - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); + cs_error(link, RequestConfiguration, i); goto failed; } @@ -699,21 +696,21 @@ static void dtl1_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: dtl1_release(link); } -static void dtl1_release(dev_link_t *link) +static void dtl1_release(struct pcmcia_device *link) { dtl1_info_t *info = link->priv; if (link->state & DEV_PRESENT) dtl1_close(info); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 3e6d6e0bb6..79b8ad0e32 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -67,7 +67,7 @@ static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte"; #define T_100MSEC msecs_to_jiffies(100) #define T_500MSEC msecs_to_jiffies(500) -static void cm4000_release(dev_link_t *link); +static void cm4000_release(struct pcmcia_device *link); static int major; /* major number we get from the kernel */ @@ -149,14 +149,14 @@ struct cm4000_dev { #define ZERO_DEV(dev) \ memset(&dev->atr_csum,0, \ sizeof(struct cm4000_dev) - \ - /*link*/ sizeof(dev_link_t) - \ + /*link*/ sizeof(struct pcmcia_device) - \ /*node*/ sizeof(dev_node_t) - \ /*atr*/ MAX_ATR*sizeof(char) - \ /*rbuf*/ 512*sizeof(char) - \ /*sbuf*/ 512*sizeof(char) - \ /*queue*/ 4*sizeof(wait_queue_head_t)) -static dev_link_t *dev_table[CM4000_MAX_DEV]; +static struct pcmcia_device *dev_table[CM4000_MAX_DEV]; static struct class *cmm_class; /* This table doesn't use spaces after the comma between fields and thus @@ -1441,7 +1441,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, { struct cm4000_dev *dev = filp->private_data; ioaddr_t iobase = dev->p_dev->io.BasePort1; - dev_link_t *link; + struct pcmcia_device *link; int size; int rc; void __user *argp = (void __user *)arg; @@ -1660,7 +1660,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, static int cmm_open(struct inode *inode, struct file *filp) { struct cm4000_dev *dev; - dev_link_t *link; + struct pcmcia_device *link; int rc, minor = iminor(inode); if (minor >= CM4000_MAX_DEV) @@ -1709,7 +1709,7 @@ static int cmm_open(struct inode *inode, struct file *filp) static int cmm_close(struct inode *inode, struct file *filp) { struct cm4000_dev *dev; - dev_link_t *link; + struct pcmcia_device *link; int minor = iminor(inode); if (minor >= CM4000_MAX_DEV) @@ -1735,7 +1735,7 @@ static int cmm_close(struct inode *inode, struct file *filp) return 0; } -static void cmm_cm4000_release(dev_link_t * link) +static void cmm_cm4000_release(struct pcmcia_device * link) { struct cm4000_dev *dev = link->priv; @@ -1759,9 +1759,8 @@ static void cmm_cm4000_release(dev_link_t * link) /*==== Interface to PCMCIA Layer =======================================*/ -static void cm4000_config(dev_link_t * link, int devno) +static void cm4000_config(struct pcmcia_device * link, int devno) { - client_handle_t handle = link->handle; struct cm4000_dev *dev; tuple_t tuple; cisparse_t parse; @@ -1776,16 +1775,16 @@ static void cm4000_config(dev_link_t * link, int devno) tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) { + if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) { fail_fn = GetFirstTuple; goto cs_failed; } - if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) { + if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) { fail_fn = GetTupleData; goto cs_failed; } if ((fail_rc = - pcmcia_parse_tuple(handle, &tuple, &parse)) != CS_SUCCESS) { + pcmcia_parse_tuple(link, &tuple, &parse)) != CS_SUCCESS) { fail_fn = ParseTuple; goto cs_failed; } @@ -1798,13 +1797,13 @@ static void cm4000_config(dev_link_t * link, int devno) link->io.NumPorts2 = 0; link->io.Attributes2 = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - for (rc = pcmcia_get_first_tuple(handle, &tuple); - rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(handle, &tuple)) { + for (rc = pcmcia_get_first_tuple(link, &tuple); + rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) { - rc = pcmcia_get_tuple_data(handle, &tuple); + rc = pcmcia_get_tuple_data(link, &tuple); if (rc != CS_SUCCESS) continue; - rc = pcmcia_parse_tuple(handle, &tuple, &parse); + rc = pcmcia_parse_tuple(link, &tuple, &parse); if (rc != CS_SUCCESS) continue; @@ -1824,7 +1823,7 @@ static void cm4000_config(dev_link_t * link, int devno) link->io.IOAddrLines = parse.cftable_entry.io.flags & CISTPL_IO_LINES_MASK; - rc = pcmcia_request_io(handle, &link->io); + rc = pcmcia_request_io(link, &link->io); if (rc == CS_SUCCESS) break; /* we are done */ } @@ -1834,7 +1833,7 @@ static void cm4000_config(dev_link_t * link, int devno) link->conf.IntType = 00000002; if ((fail_rc = - pcmcia_request_configuration(handle, &link->conf)) != CS_SUCCESS) { + pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) { fail_fn = RequestConfiguration; goto cs_release; } @@ -1850,16 +1849,15 @@ static void cm4000_config(dev_link_t * link, int devno) return; cs_failed: - cs_error(handle, fail_fn, fail_rc); + cs_error(link, fail_fn, fail_rc); cs_release: cm4000_release(link); link->state &= ~DEV_CONFIG_PENDING; } -static int cm4000_suspend(struct pcmcia_device *p_dev) +static int cm4000_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct cm4000_dev *dev; dev = link->priv; @@ -1868,9 +1866,8 @@ static int cm4000_suspend(struct pcmcia_device *p_dev) return 0; } -static int cm4000_resume(struct pcmcia_device *p_dev) +static int cm4000_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct cm4000_dev *dev; dev = link->priv; @@ -1880,17 +1877,16 @@ static int cm4000_resume(struct pcmcia_device *p_dev) return 0; } -static void cm4000_release(dev_link_t *link) +static void cm4000_release(struct pcmcia_device *link) { cmm_cm4000_release(link->priv); /* delay release until device closed */ - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int cm4000_attach(struct pcmcia_device *p_dev) +static int cm4000_attach(struct pcmcia_device *link) { struct cm4000_dev *dev; int i; - dev_link_t *link = dev_to_instance(p_dev); for (i = 0; i < CM4000_MAX_DEV; i++) if (dev_table[i] == NULL) @@ -1906,7 +1902,7 @@ static int cm4000_attach(struct pcmcia_device *p_dev) if (dev == NULL) return -ENOMEM; - dev->p_dev = p_dev; + dev->p_dev = link; link->priv = dev; link->conf.IntType = INT_MEMORY_AND_IO; dev_table[i] = link; @@ -1925,9 +1921,8 @@ static int cm4000_attach(struct pcmcia_device *p_dev) return 0; } -static void cm4000_detach(struct pcmcia_device *p_dev) +static void cm4000_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct cm4000_dev *dev = link->priv; int devno; diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 97e32e7f84..8334226e10 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -65,7 +65,7 @@ static char *version = /* how often to poll for fifo status change */ #define POLL_PERIOD msecs_to_jiffies(10) -static void reader_release(dev_link_t *link); +static void reader_release(struct pcmcia_device *link); static int major; static struct class *cmx_class; @@ -87,7 +87,7 @@ struct reader_dev { struct timer_list poll_timer; }; -static dev_link_t *dev_table[CM_MAX_DEV]; +static struct pcmcia_device *dev_table[CM_MAX_DEV]; #ifndef PCMCIA_DEBUG #define xoutb outb @@ -445,7 +445,7 @@ static unsigned int cm4040_poll(struct file *filp, poll_table *wait) static int cm4040_open(struct inode *inode, struct file *filp) { struct reader_dev *dev; - dev_link_t *link; + struct pcmcia_device *link; int minor = iminor(inode); if (minor >= CM_MAX_DEV) @@ -478,7 +478,7 @@ static int cm4040_open(struct inode *inode, struct file *filp) static int cm4040_close(struct inode *inode, struct file *filp) { struct reader_dev *dev = filp->private_data; - dev_link_t *link; + struct pcmcia_device *link; int minor = iminor(inode); DEBUGP(2, dev, "-> cm4040_close(maj/min=%d.%d)\n", imajor(inode), @@ -500,7 +500,7 @@ static int cm4040_close(struct inode *inode, struct file *filp) return 0; } -static void cm4040_reader_release(dev_link_t *link) +static void cm4040_reader_release(struct pcmcia_device *link) { struct reader_dev *dev = link->priv; @@ -514,9 +514,8 @@ static void cm4040_reader_release(dev_link_t *link) return; } -static void reader_config(dev_link_t *link, int devno) +static void reader_config(struct pcmcia_device *link, int devno) { - client_handle_t handle; struct reader_dev *dev; tuple_t tuple; cisparse_t parse; @@ -524,23 +523,21 @@ static void reader_config(dev_link_t *link, int devno) int fail_fn, fail_rc; int rc; - handle = link->handle; - tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - if ((fail_rc = pcmcia_get_first_tuple(handle, &tuple)) != CS_SUCCESS) { + if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) { fail_fn = GetFirstTuple; goto cs_failed; } - if ((fail_rc = pcmcia_get_tuple_data(handle, &tuple)) != CS_SUCCESS) { + if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) { fail_fn = GetTupleData; goto cs_failed; } - if ((fail_rc = pcmcia_parse_tuple(handle, &tuple, &parse)) + if ((fail_rc = pcmcia_parse_tuple(link, &tuple, &parse)) != CS_SUCCESS) { fail_fn = ParseTuple; goto cs_failed; @@ -554,13 +551,13 @@ static void reader_config(dev_link_t *link, int devno) link->io.NumPorts2 = 0; link->io.Attributes2 = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - for (rc = pcmcia_get_first_tuple(handle, &tuple); + for (rc = pcmcia_get_first_tuple(link, &tuple); rc == CS_SUCCESS; - rc = pcmcia_get_next_tuple(handle, &tuple)) { - rc = pcmcia_get_tuple_data(handle, &tuple); + rc = pcmcia_get_next_tuple(link, &tuple)) { + rc = pcmcia_get_tuple_data(link, &tuple); if (rc != CS_SUCCESS) continue; - rc = pcmcia_parse_tuple(handle, &tuple, &parse); + rc = pcmcia_parse_tuple(link, &tuple, &parse); if (rc != CS_SUCCESS) continue; @@ -578,13 +575,13 @@ static void reader_config(dev_link_t *link, int devno) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.IOAddrLines = parse.cftable_entry.io.flags & CISTPL_IO_LINES_MASK; - rc = pcmcia_request_io(handle, &link->io); + rc = pcmcia_request_io(link, &link->io); - dev_printk(KERN_INFO, &handle_to_dev(handle), "foo"); + dev_printk(KERN_INFO, &handle_to_dev(link), "foo"); if (rc == CS_SUCCESS) break; else - dev_printk(KERN_INFO, &handle_to_dev(handle), + dev_printk(KERN_INFO, &handle_to_dev(link), "pcmcia_request_io failed 0x%x\n", rc); } if (rc != CS_SUCCESS) @@ -592,10 +589,10 @@ static void reader_config(dev_link_t *link, int devno) link->conf.IntType = 00000002; - if ((fail_rc = pcmcia_request_configuration(handle,&link->conf)) + if ((fail_rc = pcmcia_request_configuration(link,&link->conf)) !=CS_SUCCESS) { fail_fn = RequestConfiguration; - dev_printk(KERN_INFO, &handle_to_dev(handle), + dev_printk(KERN_INFO, &handle_to_dev(link), "pcmcia_request_configuration failed 0x%x\n", fail_rc); goto cs_release; @@ -616,23 +613,22 @@ static void reader_config(dev_link_t *link, int devno) return; cs_failed: - cs_error(handle, fail_fn, fail_rc); + cs_error(link, fail_fn, fail_rc); cs_release: reader_release(link); link->state &= ~DEV_CONFIG_PENDING; } -static void reader_release(dev_link_t *link) +static void reader_release(struct pcmcia_device *link) { cm4040_reader_release(link->priv); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int reader_attach(struct pcmcia_device *p_dev) +static int reader_attach(struct pcmcia_device *link) { struct reader_dev *dev; int i; - dev_link_t *link = dev_to_instance(p_dev); for (i = 0; i < CM_MAX_DEV; i++) { if (dev_table[i] == NULL) @@ -650,7 +646,7 @@ static int reader_attach(struct pcmcia_device *p_dev) dev->buffer_status = 0; link->priv = dev; - dev->p_dev = p_dev; + dev->p_dev = link; link->conf.IntType = INT_MEMORY_AND_IO; dev_table[i] = link; @@ -671,9 +667,8 @@ static int reader_attach(struct pcmcia_device *p_dev) return 0; } -static void reader_detach(struct pcmcia_device *p_dev) +static void reader_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct reader_dev *dev = link->priv; int devno; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 7b1e055184..9bfd90e5d6 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -484,7 +484,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout); /* PCMCIA prototypes */ -static void mgslpc_config(dev_link_t *link); +static void mgslpc_config(struct pcmcia_device *link); static void mgslpc_release(u_long arg); static void mgslpc_detach(struct pcmcia_device *p_dev); @@ -533,10 +533,9 @@ static void ldisc_receive_buf(struct tty_struct *tty, } } -static int mgslpc_attach(struct pcmcia_device *p_dev) +static int mgslpc_attach(struct pcmcia_device *link) { MGSLPC_INFO *info; - dev_link_t *link = dev_to_instance(p_dev); if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_attach\n"); @@ -565,10 +564,10 @@ static int mgslpc_attach(struct pcmcia_device *p_dev) info->imrb_value = 0xffff; info->pim_value = 0xff; - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; - /* Initialize the dev_link_t structure */ + /* Initialize the struct pcmcia_device structure */ /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; @@ -592,9 +591,8 @@ static int mgslpc_attach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void mgslpc_config(dev_link_t *link) +static void mgslpc_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; MGSLPC_INFO *info = link->priv; tuple_t tuple; cisparse_t parse; @@ -612,9 +610,9 @@ static void mgslpc_config(dev_link_t *link) tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -624,11 +622,11 @@ static void mgslpc_config(dev_link_t *link) /* get CIS configuration entry */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); cfg = &(parse.cftable_entry); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; if (cfg->index == 0) @@ -649,7 +647,7 @@ static void mgslpc_config(dev_link_t *link) link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; link->io.BasePort1 = io->win[0].base; link->io.NumPorts1 = io->win[0].len; - CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); + CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); } link->conf.Attributes = CONF_ENABLE_IRQ; @@ -660,9 +658,9 @@ static void mgslpc_config(dev_link_t *link) link->irq.Attributes |= IRQ_HANDLE_PRESENT; link->irq.Handler = mgslpc_isr; link->irq.Instance = info; - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); info->io_base = link->io.BasePort1; info->irq_level = link->irq.AssignedIRQ; @@ -685,7 +683,7 @@ static void mgslpc_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); mgslpc_release((u_long)link); } @@ -695,18 +693,16 @@ cs_failed: */ static void mgslpc_release(u_long arg) { - dev_link_t *link = (dev_link_t *)arg; + struct pcmcia_device *link = (struct pcmcia_device *)arg; if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_release(0x%p)\n", link); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static void mgslpc_detach(struct pcmcia_device *p_dev) +static void mgslpc_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_detach(0x%p)\n", link); @@ -718,9 +714,8 @@ static void mgslpc_detach(struct pcmcia_device *p_dev) mgslpc_remove_device((MGSLPC_INFO *)link->priv); } -static int mgslpc_suspend(struct pcmcia_device *dev) +static int mgslpc_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); MGSLPC_INFO *info = link->priv; info->stop = 1; @@ -728,9 +723,8 @@ static int mgslpc_suspend(struct pcmcia_device *dev) return 0; } -static int mgslpc_resume(struct pcmcia_device *dev) +static int mgslpc_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); MGSLPC_INFO *info = link->priv; info->stop = 0; diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 70bb1b8bab..58690c1ff6 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -87,8 +87,8 @@ typedef struct ide_info_t { int hd; } ide_info_t; -static void ide_release(dev_link_t *); -static void ide_config(dev_link_t *); +static void ide_release(struct pcmcia_device *); +static void ide_config(struct pcmcia_device *); static void ide_detach(struct pcmcia_device *p_dev); @@ -103,10 +103,9 @@ static void ide_detach(struct pcmcia_device *p_dev); ======================================================================*/ -static int ide_attach(struct pcmcia_device *p_dev) +static int ide_attach(struct pcmcia_device *link) { ide_info_t *info; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "ide_attach()\n"); @@ -115,7 +114,7 @@ static int ide_attach(struct pcmcia_device *p_dev) if (!info) return -ENOMEM; - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; @@ -141,10 +140,8 @@ static int ide_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void ide_detach(struct pcmcia_device *p_dev) +static void ide_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "ide_detach(0x%p)\n", link); if (link->state & DEV_CONFIG) @@ -175,9 +172,8 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void ide_config(dev_link_t *link) +static void ide_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; ide_info_t *info = link->priv; tuple_t tuple; struct { @@ -201,16 +197,16 @@ static void ide_config(dev_link_t *link) tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &stk->parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &stk->parse)); link->conf.ConfigBase = stk->parse.config.base; link->conf.Present = stk->parse.config.rmask[0]; tuple.DesiredTuple = CISTPL_MANFID; - if (!pcmcia_get_first_tuple(handle, &tuple) && - !pcmcia_get_tuple_data(handle, &tuple) && - !pcmcia_parse_tuple(handle, &tuple, &stk->parse)) + if (!pcmcia_get_first_tuple(link, &tuple) && + !pcmcia_get_tuple_data(link, &tuple) && + !pcmcia_parse_tuple(link, &tuple, &stk->parse)) is_kme = ((stk->parse.manfid.manf == MANFID_KME) && ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); @@ -219,15 +215,15 @@ static void ide_config(dev_link_t *link) link->state |= DEV_CONFIG; /* Not sure if this is right... look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &stk->conf)); + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf)); pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { - if (pcmcia_get_tuple_data(handle, &tuple) != 0) goto next_entry; - if (pcmcia_parse_tuple(handle, &tuple, &stk->parse) != 0) goto next_entry; + if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry; + if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry; /* Check for matching Vcc, unless we're desperate */ if (!pass) { @@ -258,14 +254,14 @@ static void ide_config(dev_link_t *link) link->io.NumPorts1 = 8; link->io.BasePort2 = io->win[1].base; link->io.NumPorts2 = (is_kme) ? 2 : 1; - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; ctl_base = link->io.BasePort2; } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { link->io.NumPorts1 = io->win[0].len; link->io.NumPorts2 = 0; - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; io_base = link->io.BasePort1; ctl_base = link->io.BasePort1 + 0x0e; @@ -278,16 +274,16 @@ static void ide_config(dev_link_t *link) if (cfg->flags & CISTPL_CFTABLE_DEFAULT) memcpy(&stk->dflt, cfg, sizeof(stk->dflt)); if (pass) { - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); - } else if (pcmcia_get_next_tuple(handle, &tuple) != 0) { - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); + } else if (pcmcia_get_next_tuple(link, &tuple) != 0) { + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); memset(&stk->dflt, 0, sizeof(stk->dflt)); pass++; } } - CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); /* disable drive interrupts during IDE probe */ outb(0x02, ctl_base); @@ -298,12 +294,12 @@ static void ide_config(dev_link_t *link) /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { - hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, handle); + hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { outb(0x02, ctl_base + 0x10); hd = idecs_register(io_base + 0x10, ctl_base + 0x10, - link->irq.AssignedIRQ, handle); + link->irq.AssignedIRQ, link); if (hd >= 0) { io_base += 0x10; ctl_base += 0x10; @@ -338,7 +334,7 @@ err_mem: goto failed; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: kfree(stk); ide_release(link); @@ -353,7 +349,7 @@ failed: ======================================================================*/ -void ide_release(dev_link_t *link) +void ide_release(struct pcmcia_device *link) { ide_info_t *info = link->priv; @@ -366,7 +362,7 @@ void ide_release(dev_link_t *link) } info->ndev = 0; - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } /* ide_release */ diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 3b7461ece5..c9c794e292 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -51,8 +51,8 @@ MODULE_LICENSE("GPL"); handler. */ -static void avmcs_config(dev_link_t *link); -static void avmcs_release(dev_link_t *link); +static void avmcs_config(struct pcmcia_device *link); +static void avmcs_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -65,10 +65,10 @@ static void avmcs_detach(struct pcmcia_device *p_dev); /* A linked list of "instances" of the skeleton device. Each actual PCMCIA card corresponds to one device instance, and is described - by one dev_link_t structure (defined in ds.h). + by one struct pcmcia_device structure (defined in ds.h). You may not want to use a linked list for this -- for example, the - memory card driver uses an array of dev_link_t pointers, where minor + memory card driver uses an array of struct pcmcia_device pointers, where minor device numbers are used to derive the corresponding array index. */ @@ -78,7 +78,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally can't be allocated dynamically. */ @@ -145,10 +145,8 @@ static int avmcs_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void avmcs_detach(struct pcmcia_device *p_dev) +static void avmcs_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - if (link->state & DEV_CONFIG) avmcs_release(link); @@ -163,7 +161,7 @@ static void avmcs_detach(struct pcmcia_device *p_dev) ======================================================================*/ -static int get_tuple(client_handle_t handle, tuple_t *tuple, +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_tuple_data(handle, tuple); @@ -171,7 +169,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_first_tuple(handle, tuple); @@ -179,7 +177,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_next_tuple(handle, tuple); @@ -187,9 +185,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void avmcs_config(dev_link_t *link) +static void avmcs_config(struct pcmcia_device *link) { - client_handle_t handle; tuple_t tuple; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; @@ -199,8 +196,7 @@ static void avmcs_config(dev_link_t *link) char devname[128]; int cardtype; int (*addcard)(unsigned int port, unsigned irq); - - handle = link->handle; + dev = link->priv; /* @@ -209,19 +205,19 @@ static void avmcs_config(dev_link_t *link) */ do { tuple.DesiredTuple = CISTPL_CONFIG; - i = pcmcia_get_first_tuple(handle, &tuple); + i = pcmcia_get_first_tuple(link, &tuple); if (i != CS_SUCCESS) break; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - i = pcmcia_get_tuple_data(handle, &tuple); + i = pcmcia_get_tuple_data(link, &tuple); if (i != CS_SUCCESS) break; - i = pcmcia_parse_tuple(handle, &tuple, &parse); + i = pcmcia_parse_tuple(link, &tuple, &parse); if (i != CS_SUCCESS) break; link->conf.ConfigBase = parse.config.base; } while (0); if (i != CS_SUCCESS) { - cs_error(link->handle, ParseTuple, i); + cs_error(link, ParseTuple, i); link->state &= ~DEV_CONFIG_PENDING; return; } @@ -238,7 +234,7 @@ static void avmcs_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_VERS_1; devname[0] = 0; - if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) { + if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) { strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], sizeof(devname)); } @@ -249,7 +245,7 @@ static void avmcs_config(dev_link_t *link) tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i == CS_SUCCESS) { if (cf->io.nwin > 0) { link->conf.ConfigIndex = cf->index; @@ -259,36 +255,36 @@ static void avmcs_config(dev_link_t *link) printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1); - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } found_port: if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); break; } /* * allocate an interrupt line */ - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); + cs_error(link, RequestIRQ, i); /* undo */ - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); break; } /* * configure the PCMCIA socket */ - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); - pcmcia_disable_device(link->handle); + cs_error(link, RequestConfiguration, i); + pcmcia_disable_device(link); break; } @@ -351,10 +347,10 @@ found_port: ======================================================================*/ -static void avmcs_release(dev_link_t *link) +static void avmcs_release(struct pcmcia_device *link) { b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } /* avmcs_release */ diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index f7143fe1a2..ff6b0e185b 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -67,8 +67,8 @@ module_param(isdnprot, int, 0); handler. */ -static void avma1cs_config(dev_link_t *link); -static void avma1cs_release(dev_link_t *link); +static void avma1cs_config(struct pcmcia_device *link); +static void avma1cs_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -82,10 +82,10 @@ static void avma1cs_detach(struct pcmcia_device *p_dev); /* A linked list of "instances" of the skeleton device. Each actual PCMCIA card corresponds to one device instance, and is described - by one dev_link_t structure (defined in ds.h). + by one struct pcmcia_device structure (defined in ds.h). You may not want to use a linked list for this -- for example, the - memory card driver uses an array of dev_link_t pointers, where minor + memory card driver uses an array of struct pcmcia_device pointers, where minor device numbers are used to derive the corresponding array index. */ @@ -95,7 +95,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally can't be allocated dynamically. */ @@ -164,10 +164,8 @@ static int avma1cs_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void avma1cs_detach(struct pcmcia_device *p_dev) +static void avma1cs_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "avma1cs_detach(0x%p)\n", link); if (link->state & DEV_CONFIG) @@ -184,7 +182,7 @@ static void avma1cs_detach(struct pcmcia_device *p_dev) ======================================================================*/ -static int get_tuple(client_handle_t handle, tuple_t *tuple, +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_tuple_data(handle, tuple); @@ -192,7 +190,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_first_tuple(handle, tuple); @@ -200,7 +198,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_next_tuple(handle, tuple); @@ -208,9 +206,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void avma1cs_config(dev_link_t *link) +static void avma1cs_config(struct pcmcia_device *link) { - client_handle_t handle; tuple_t tuple; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; @@ -220,8 +217,7 @@ static void avma1cs_config(dev_link_t *link) char devname[128]; IsdnCard_t icard; int busy = 0; - - handle = link->handle; + dev = link->priv; DEBUG(0, "avma1cs_config(0x%p)\n", link); @@ -232,19 +228,19 @@ static void avma1cs_config(dev_link_t *link) */ do { tuple.DesiredTuple = CISTPL_CONFIG; - i = pcmcia_get_first_tuple(handle, &tuple); + i = pcmcia_get_first_tuple(link, &tuple); if (i != CS_SUCCESS) break; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - i = pcmcia_get_tuple_data(handle, &tuple); + i = pcmcia_get_tuple_data(link, &tuple); if (i != CS_SUCCESS) break; - i = pcmcia_parse_tuple(handle, &tuple, &parse); + i = pcmcia_parse_tuple(link, &tuple, &parse); if (i != CS_SUCCESS) break; link->conf.ConfigBase = parse.config.base; } while (0); if (i != CS_SUCCESS) { - cs_error(link->handle, ParseTuple, i); + cs_error(link, ParseTuple, i); link->state &= ~DEV_CONFIG_PENDING; return; } @@ -261,7 +257,7 @@ static void avma1cs_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_VERS_1; devname[0] = 0; - if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) { + if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) { strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], sizeof(devname)); } @@ -272,7 +268,7 @@ static void avma1cs_config(dev_link_t *link) tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i == CS_SUCCESS) { if (cf->io.nwin > 0) { link->conf.ConfigIndex = cf->index; @@ -282,36 +278,36 @@ static void avma1cs_config(dev_link_t *link) printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1 - 1); - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } found_port: if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); break; } /* * allocate an interrupt line */ - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); + cs_error(link, RequestIRQ, i); /* undo */ - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); break; } /* * configure the PCMCIA socket */ - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); - pcmcia_disable_device(link->handle); + cs_error(link, RequestConfiguration, i); + pcmcia_disable_device(link); break; } @@ -358,7 +354,7 @@ found_port: ======================================================================*/ -static void avma1cs_release(dev_link_t *link) +static void avma1cs_release(struct pcmcia_device *link) { local_info_t *local = link->priv; @@ -367,7 +363,7 @@ static void avma1cs_release(dev_link_t *link) /* now unregister function with hisax */ HiSax_closecard(local->node.minor); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } /* avma1cs_release */ diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index bcda675e91..7a42bd4316 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -94,8 +94,8 @@ module_param(protocol, int, 0); handler. */ -static void elsa_cs_config(dev_link_t *link); -static void elsa_cs_release(dev_link_t *link); +static void elsa_cs_config(struct pcmcia_device *link); +static void elsa_cs_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -111,7 +111,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally shouldn't be allocated dynamically. In this case, we also provide a flag to indicate if a device is @@ -139,10 +139,9 @@ typedef struct local_info_t { ======================================================================*/ -static int elsa_cs_attach(struct pcmcia_device *p_dev) +static int elsa_cs_attach(struct pcmcia_device *link) { local_info_t *local; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "elsa_cs_attach()\n"); @@ -151,7 +150,7 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev) if (!local) return -ENOMEM; memset(local, 0, sizeof(local_info_t)); - local->p_dev = p_dev; + local->p_dev = link; link->priv = local; local->cardnr = -1; @@ -190,9 +189,8 @@ static int elsa_cs_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void elsa_cs_detach(struct pcmcia_device *p_dev) +static void elsa_cs_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *info = link->priv; DEBUG(0, "elsa_cs_detach(0x%p)\n", link); @@ -213,7 +211,7 @@ static void elsa_cs_detach(struct pcmcia_device *p_dev) device available to the system. ======================================================================*/ -static int get_tuple(client_handle_t handle, tuple_t *tuple, +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_tuple_data(handle, tuple); @@ -221,7 +219,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_first_tuple(handle, tuple); @@ -229,7 +227,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_next_tuple(handle, tuple); @@ -237,9 +235,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void elsa_cs_config(dev_link_t *link) +static void elsa_cs_config(struct pcmcia_device *link) { - client_handle_t handle; tuple_t tuple; cisparse_t parse; local_info_t *dev; @@ -249,7 +246,6 @@ static void elsa_cs_config(dev_link_t *link) IsdnCard_t icard; DEBUG(0, "elsa_config(0x%p)\n", link); - handle = link->handle; dev = link->priv; /* @@ -261,7 +257,7 @@ static void elsa_cs_config(dev_link_t *link) tuple.TupleDataMax = 255; tuple.TupleOffset = 0; tuple.Attributes = 0; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); if (i != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; @@ -276,25 +272,25 @@ static void elsa_cs_config(dev_link_t *link) tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i == CS_SUCCESS) { if ( (cf->io.nwin > 0) && cf->io.win[0].base) { printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n"); link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } else { printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n"); link->conf.ConfigIndex = cf->index; for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) { link->io.BasePort1 = j; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } break; } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } if (i != CS_SUCCESS) { @@ -302,14 +298,14 @@ static void elsa_cs_config(dev_link_t *link) goto cs_failed; } - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { link->irq.AssignedIRQ = 0; last_fn = RequestIRQ; goto cs_failed; } - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { last_fn = RequestConfiguration; goto cs_failed; @@ -352,7 +348,7 @@ static void elsa_cs_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, i); + cs_error(link, last_fn, i); elsa_cs_release(link); } /* elsa_cs_config */ @@ -364,7 +360,7 @@ cs_failed: ======================================================================*/ -static void elsa_cs_release(dev_link_t *link) +static void elsa_cs_release(struct pcmcia_device *link) { local_info_t *local = link->priv; @@ -377,12 +373,11 @@ static void elsa_cs_release(dev_link_t *link) } } - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } /* elsa_cs_release */ -static int elsa_suspend(struct pcmcia_device *p_dev) +static int elsa_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; dev->busy = 1; @@ -390,9 +385,8 @@ static int elsa_suspend(struct pcmcia_device *p_dev) return 0; } -static int elsa_resume(struct pcmcia_device *p_dev) +static int elsa_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; dev->busy = 0; diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 6025722001..2af48a6846 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -95,8 +95,8 @@ module_param(protocol, int, 0); event handler. */ -static void sedlbauer_config(dev_link_t *link); -static void sedlbauer_release(dev_link_t *link); +static void sedlbauer_config(struct pcmcia_device *link); +static void sedlbauer_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -119,7 +119,7 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally shouldn't be allocated dynamically. @@ -148,11 +148,10 @@ typedef struct local_info_t { ======================================================================*/ -static int sedlbauer_attach(struct pcmcia_device *p_dev) +static int sedlbauer_attach(struct pcmcia_device *link) { local_info_t *local; - dev_link_t *link = dev_to_instance(p_dev); - + DEBUG(0, "sedlbauer_attach()\n"); /* Allocate space for private device-specific data */ @@ -161,7 +160,7 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev) memset(local, 0, sizeof(local_info_t)); local->cardnr = -1; - local->p_dev = p_dev; + local->p_dev = link; link->priv = local; /* Interrupt setup */ @@ -202,10 +201,8 @@ static int sedlbauer_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void sedlbauer_detach(struct pcmcia_device *p_dev) +static void sedlbauer_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "sedlbauer_detach(0x%p)\n", link); if (link->state & DEV_CONFIG) { @@ -227,9 +224,8 @@ static void sedlbauer_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void sedlbauer_config(dev_link_t *link) +static void sedlbauer_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; local_info_t *dev = link->priv; tuple_t tuple; cisparse_t parse; @@ -251,16 +247,16 @@ static void sedlbauer_config(dev_link_t *link) tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* Configure card */ link->state |= DEV_CONFIG; - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); /* In this loop, we scan the CIS for configuration table entries, @@ -275,12 +271,12 @@ static void sedlbauer_config(dev_link_t *link) will only use the CIS to fill in implementation-defined details. */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { cistpl_cftable_entry_t dflt = { 0 }; cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; @@ -334,13 +330,13 @@ static void sedlbauer_config(dev_link_t *link) link->io.NumPorts2 = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; } /* Now set up a common memory window, if needed. There is room - in the dev_link_t structure for one memory window handle, + in the struct pcmcia_device structure for one memory window handle, but if the base addresses need to be saved, or if multiple windows are needed, the info should go in the private data structure for this device. @@ -361,7 +357,7 @@ static void sedlbauer_config(dev_link_t *link) req.Size = 0x1000; */ req.AccessSpeed = 0; - if (pcmcia_request_window(&link->handle, &req, &link->win) != 0) + if (pcmcia_request_window(&link, &req, &link->win) != 0) goto next_entry; map.Page = 0; map.CardOffset = mem->win[0].card_addr; if (pcmcia_map_mem_page(link->win, &map) != 0) @@ -371,7 +367,7 @@ static void sedlbauer_config(dev_link_t *link) break; next_entry: - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } /* @@ -380,14 +376,14 @@ static void sedlbauer_config(dev_link_t *link) irq structure is initialized. */ if (link->conf.Attributes & CONF_ENABLE_IRQ) - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping, and putting the card and host interface into "Memory and IO" mode. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); /* At this point, the dev_node_t structure(s) need to be @@ -433,7 +429,7 @@ static void sedlbauer_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); sedlbauer_release(link); } /* sedlbauer_config */ @@ -446,7 +442,7 @@ cs_failed: ======================================================================*/ -static void sedlbauer_release(dev_link_t *link) +static void sedlbauer_release(struct pcmcia_device *link) { local_info_t *local = link->priv; DEBUG(0, "sedlbauer_release(0x%p)\n", link); @@ -458,12 +454,11 @@ static void sedlbauer_release(dev_link_t *link) } } - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } /* sedlbauer_release */ -static int sedlbauer_suspend(struct pcmcia_device *p_dev) +static int sedlbauer_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; dev->stop = 1; @@ -471,9 +466,8 @@ static int sedlbauer_suspend(struct pcmcia_device *p_dev) return 0; } -static int sedlbauer_resume(struct pcmcia_device *p_dev) +static int sedlbauer_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; dev->stop = 0; diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index ea16ebfc02..698e9ec95f 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -75,8 +75,8 @@ module_param(protocol, int, 0); handler. */ -static void teles_cs_config(dev_link_t *link); -static void teles_cs_release(dev_link_t *link); +static void teles_cs_config(struct pcmcia_device *link); +static void teles_cs_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -89,10 +89,10 @@ static void teles_detach(struct pcmcia_device *p_dev); /* A linked list of "instances" of the teles_cs device. Each actual PCMCIA card corresponds to one device instance, and is described - by one dev_link_t structure (defined in ds.h). + by one struct pcmcia_device structure (defined in ds.h). You may not want to use a linked list for this -- for example, the - memory card driver uses an array of dev_link_t pointers, where minor + memory card driver uses an array of struct pcmcia_device pointers, where minor device numbers are used to derive the corresponding array index. */ @@ -102,7 +102,7 @@ static void teles_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally shouldn't be allocated dynamically. In this case, we also provide a flag to indicate if a device is @@ -130,10 +130,9 @@ typedef struct local_info_t { ======================================================================*/ -static int teles_attach(struct pcmcia_device *p_dev) +static int teles_attach(struct pcmcia_device *link) { local_info_t *local; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "teles_attach()\n"); @@ -143,7 +142,7 @@ static int teles_attach(struct pcmcia_device *p_dev) memset(local, 0, sizeof(local_info_t)); local->cardnr = -1; - local->p_dev = p_dev; + local->p_dev = link; link->priv = local; /* Interrupt setup */ @@ -180,9 +179,8 @@ static int teles_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void teles_detach(struct pcmcia_device *p_dev) +static void teles_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *info = link->priv; DEBUG(0, "teles_detach(0x%p)\n", link); @@ -203,7 +201,7 @@ static void teles_detach(struct pcmcia_device *p_dev) device available to the system. ======================================================================*/ -static int get_tuple(client_handle_t handle, tuple_t *tuple, +static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_tuple_data(handle, tuple); @@ -211,7 +209,7 @@ static int get_tuple(client_handle_t handle, tuple_t *tuple, return pcmcia_parse_tuple(handle, tuple, parse); } -static int first_tuple(client_handle_t handle, tuple_t *tuple, +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_first_tuple(handle, tuple); @@ -219,7 +217,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i = pcmcia_get_next_tuple(handle, tuple); @@ -227,9 +225,8 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void teles_cs_config(dev_link_t *link) +static void teles_cs_config(struct pcmcia_device *link) { - client_handle_t handle; tuple_t tuple; cisparse_t parse; local_info_t *dev; @@ -239,7 +236,6 @@ static void teles_cs_config(dev_link_t *link) IsdnCard_t icard; DEBUG(0, "teles_config(0x%p)\n", link); - handle = link->handle; dev = link->priv; /* @@ -251,7 +247,7 @@ static void teles_cs_config(dev_link_t *link) tuple.TupleDataMax = 255; tuple.TupleOffset = 0; tuple.Attributes = 0; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); if (i != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; @@ -266,25 +262,25 @@ static void teles_cs_config(dev_link_t *link) tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(handle, &tuple, &parse); + i = first_tuple(link, &tuple, &parse); while (i == CS_SUCCESS) { if ( (cf->io.nwin > 0) && cf->io.win[0].base) { printk(KERN_INFO "(teles_cs: looks like the 96 model)\n"); link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } else { printk(KERN_INFO "(teles_cs: looks like the 97 model)\n"); link->conf.ConfigIndex = cf->index; for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) { link->io.BasePort1 = j; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } break; } - i = next_tuple(handle, &tuple, &parse); + i = next_tuple(link, &tuple, &parse); } if (i != CS_SUCCESS) { @@ -292,14 +288,14 @@ static void teles_cs_config(dev_link_t *link) goto cs_failed; } - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { link->irq.AssignedIRQ = 0; last_fn = RequestIRQ; goto cs_failed; } - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { last_fn = RequestConfiguration; goto cs_failed; @@ -342,7 +338,7 @@ static void teles_cs_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, i); + cs_error(link, last_fn, i); teles_cs_release(link); } /* teles_cs_config */ @@ -354,7 +350,7 @@ cs_failed: ======================================================================*/ -static void teles_cs_release(dev_link_t *link) +static void teles_cs_release(struct pcmcia_device *link) { local_info_t *local = link->priv; @@ -367,12 +363,11 @@ static void teles_cs_release(dev_link_t *link) } } - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } /* teles_cs_release */ -static int teles_suspend(struct pcmcia_device *p_dev) +static int teles_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; dev->busy = 1; @@ -380,9 +375,8 @@ static int teles_suspend(struct pcmcia_device *p_dev) return 0; } -static int teles_resume(struct pcmcia_device *p_dev) +static int teles_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *dev = link->priv; dev->busy = 0; diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 8259dca97e..e9086f0cb2 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -122,7 +122,7 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) dev->offset, mrq.CardOffset); mrq.Page = 0; if( (ret = pcmcia_map_mem_page(win, &mrq)) != CS_SUCCESS) { - cs_error(dev->p_dev->handle, MapMemPage, ret); + cs_error(dev->p_dev, MapMemPage, ret); return NULL; } dev->offset = mrq.CardOffset; @@ -319,7 +319,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f static void pcmciamtd_set_vpp(struct map_info *map, int on) { struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; - dev_link_t *link = dev->p_dev; + struct pcmcia_device *link = dev->p_dev; modconf_t mod; int ret; @@ -328,9 +328,9 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0; DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); - ret = pcmcia_modify_configuration(link->handle, &mod); + ret = pcmcia_modify_configuration(link, &mod); if(ret != CS_SUCCESS) { - cs_error(link->handle, ModifyConfiguration, ret); + cs_error(link, ModifyConfiguration, ret); } } @@ -340,7 +340,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) * still open, this will be postponed until it is closed. */ -static void pcmciamtd_release(dev_link_t *link) +static void pcmciamtd_release(struct pcmcia_device *link) { struct pcmciamtd_dev *dev = link->priv; @@ -353,11 +353,11 @@ static void pcmciamtd_release(dev_link_t *link) } pcmcia_release_window(link->win); } - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_name) +static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name) { int rc; tuple_t tuple; @@ -370,16 +370,16 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ tuple.TupleOffset = 0; tuple.DesiredTuple = RETURN_FIRST_TUPLE; - rc = pcmcia_get_first_tuple(link->handle, &tuple); + rc = pcmcia_get_first_tuple(link, &tuple); while(rc == CS_SUCCESS) { - rc = pcmcia_get_tuple_data(link->handle, &tuple); + rc = pcmcia_get_tuple_data(link, &tuple); if(rc != CS_SUCCESS) { - cs_error(link->handle, GetTupleData, rc); + cs_error(link, GetTupleData, rc); break; } - rc = pcmcia_parse_tuple(link->handle, &tuple, &parse); + rc = pcmcia_parse_tuple(link, &tuple, &parse); if(rc != CS_SUCCESS) { - cs_error(link->handle, ParseTuple, rc); + cs_error(link, ParseTuple, rc); break; } @@ -450,7 +450,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ DEBUG(2, "Unknown tuple code %d", tuple.TupleCode); } - rc = pcmcia_get_next_tuple(link->handle, &tuple); + rc = pcmcia_get_next_tuple(link, &tuple); } if(!dev->pcmcia_map.size) dev->pcmcia_map.size = MAX_PCMCIA_ADDR; @@ -487,7 +487,7 @@ static void card_settings(struct pcmciamtd_dev *dev, dev_link_t *link, int *new_ #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void pcmciamtd_config(dev_link_t *link) +static void pcmciamtd_config(struct pcmcia_device *link) { struct pcmciamtd_dev *dev = link->priv; struct mtd_info *mtd = NULL; @@ -507,9 +507,9 @@ static void pcmciamtd_config(dev_link_t *link) link->state |= DEV_CONFIG; DEBUG(2, "Validating CIS"); - ret = pcmcia_validate_cis(link->handle, &cisinfo); + ret = pcmcia_validate_cis(link, &cisinfo); if(ret != CS_SUCCESS) { - cs_error(link->handle, GetTupleData, ret); + cs_error(link, GetTupleData, ret); } else { DEBUG(2, "ValidateCIS found %d chains", cisinfo.Chains); } @@ -537,7 +537,7 @@ static void pcmciamtd_config(dev_link_t *link) req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; req.Base = 0; req.AccessSpeed = mem_speed; - link->win = (window_handle_t)link->handle; + link->win = (window_handle_t)link; req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR; dev->win_size = 0; @@ -545,7 +545,7 @@ static void pcmciamtd_config(dev_link_t *link) int ret; DEBUG(2, "requesting window with size = %dKiB memspeed = %d", req.Size >> 10, req.AccessSpeed); - ret = pcmcia_request_window(&link->handle, &req, &link->win); + ret = pcmcia_request_window(&link, &req, &link->win); DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); if(ret) { req.Size >>= 1; @@ -566,7 +566,7 @@ static void pcmciamtd_config(dev_link_t *link) DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); /* Get write protect status */ - CS_CHECK(GetStatus, pcmcia_get_status(link->handle, &status)); + CS_CHECK(GetStatus, pcmcia_get_status(link, &status)); DEBUG(2, "status value: 0x%x window handle = 0x%8.8lx", status.CardState, (unsigned long)link->win); dev->win_base = ioremap(req.Base, req.Size); @@ -583,7 +583,7 @@ static void pcmciamtd_config(dev_link_t *link) dev->pcmcia_map.map_priv_2 = (unsigned long)link->win; DEBUG(2, "Getting configuration"); - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link->handle, &t)); + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &t)); DEBUG(2, "Vcc = %d Vpp1 = %d Vpp2 = %d", t.Vcc, t.Vpp1, t.Vpp2); dev->vpp = (vpp) ? vpp : t.Vpp1; link->conf.Attributes = 0; @@ -602,9 +602,9 @@ static void pcmciamtd_config(dev_link_t *link) link->conf.ConfigIndex = 0; link->conf.Present = t.Present; DEBUG(2, "Setting Configuration"); - ret = pcmcia_request_configuration(link->handle, &link->conf); + ret = pcmcia_request_configuration(link, &link->conf); if(ret != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, ret); + cs_error(link, RequestConfiguration, ret); } if(mem_type == 1) { @@ -677,7 +677,7 @@ static void pcmciamtd_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); err("CS Error, exiting"); pcmciamtd_release(link); return; @@ -709,10 +709,8 @@ static int pcmciamtd_resume(struct pcmcia_device *dev) * when the device is released. */ -static void pcmciamtd_detach(struct pcmcia_device *p_dev) +static void pcmciamtd_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(3, "link=0x%p", link); if(link->state & DEV_CONFIG) { @@ -732,10 +730,9 @@ static void pcmciamtd_detach(struct pcmcia_device *p_dev) * with Card Services. */ -static int pcmciamtd_attach(struct pcmcia_device *p_dev) +static int pcmciamtd_attach(struct pcmcia_device *link) { struct pcmciamtd_dev *dev; - dev_link_t *link = dev_to_instance(p_dev); /* Create new memory card device */ dev = kmalloc(sizeof(*dev), GFP_KERNEL); @@ -743,7 +740,7 @@ static int pcmciamtd_attach(struct pcmcia_device *p_dev) DEBUG(1, "dev=0x%p", dev); memset(dev, 0, sizeof(*dev)); - dev->p_dev = p_dev; + dev->p_dev = link; link->priv = dev; link->conf.Attributes = 0; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index b65758d3c6..f4e293bd04 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -225,8 +225,8 @@ static char mii_preamble_required = 0; /* Index of functions. */ -static void tc574_config(dev_link_t *link); -static void tc574_release(dev_link_t *link); +static void tc574_config(struct pcmcia_device *link); +static void tc574_release(struct pcmcia_device *link); static void mdio_sync(kio_addr_t ioaddr, int bits); static int mdio_read(kio_addr_t ioaddr, int phy_id, int location); @@ -256,11 +256,10 @@ static void tc574_detach(struct pcmcia_device *p_dev); with Card Services. */ -static int tc574_attach(struct pcmcia_device *p_dev) +static int tc574_attach(struct pcmcia_device *link) { struct el3_private *lp; struct net_device *dev; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "3c574_attach()\n"); @@ -270,7 +269,7 @@ static int tc574_attach(struct pcmcia_device *p_dev) return -ENOMEM; lp = netdev_priv(dev); link->priv = dev; - lp->p_dev = p_dev; + lp->p_dev = link; spin_lock_init(&lp->window_lock); link->io.NumPorts1 = 32; @@ -312,9 +311,8 @@ static int tc574_attach(struct pcmcia_device *p_dev) */ -static void tc574_detach(struct pcmcia_device *p_dev) +static void tc574_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; DEBUG(0, "3c574_detach(0x%p)\n", link); @@ -339,9 +337,8 @@ static void tc574_detach(struct pcmcia_device *p_dev) static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; -static void tc574_config(dev_link_t *link) +static void tc574_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); tuple_t tuple; @@ -359,12 +356,12 @@ static void tc574_config(dev_link_t *link) tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -374,15 +371,15 @@ static void tc574_config(dev_link_t *link) link->io.IOAddrLines = 16; for (i = j = 0; j < 0x400; j += 0x20) { link->io.BasePort1 = j ^ 0x300; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); goto failed; } - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; @@ -393,8 +390,8 @@ static void tc574_config(dev_link_t *link) the hardware address. The future products may include a modem chip and put the address in the CIS. */ tuple.DesiredTuple = 0x88; - if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { - pcmcia_get_tuple_data(handle, &tuple); + if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { + pcmcia_get_tuple_data(link, &tuple); for (i = 0; i < 3; i++) phys_addr[i] = htons(buf[i]); } else { @@ -408,9 +405,9 @@ static void tc574_config(dev_link_t *link) } } tuple.DesiredTuple = CISTPL_VERS_1; - if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS && - pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS && - pcmcia_parse_tuple(handle, &tuple, &parse) == CS_SUCCESS) { + if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS && + pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS && + pcmcia_parse_tuple(link, &tuple, &parse) == CS_SUCCESS) { cardname = parse.version_1.str + parse.version_1.ofs[1]; } else cardname = "3Com 3c574"; @@ -471,7 +468,7 @@ static void tc574_config(dev_link_t *link) link->state &= ~DEV_CONFIG_PENDING; link->dev_node = &lp->node; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n"); @@ -492,7 +489,7 @@ static void tc574_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: tc574_release(link); return; @@ -505,14 +502,13 @@ failed: still open, this will be postponed until it is closed. */ -static void tc574_release(dev_link_t *link) +static void tc574_release(struct pcmcia_device *link) { - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int tc574_suspend(struct pcmcia_device *p_dev) +static int tc574_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) @@ -521,9 +517,8 @@ static int tc574_suspend(struct pcmcia_device *p_dev) return 0; } -static int tc574_resume(struct pcmcia_device *p_dev) +static int tc574_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) { @@ -739,7 +734,7 @@ static void tc574_reset(struct net_device *dev) static int el3_open(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; if (!DEV_OK(link)) return -ENODEV; @@ -1185,7 +1180,7 @@ static int el3_close(struct net_device *dev) { kio_addr_t ioaddr = dev->base_addr; struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; DEBUG(2, "%s: shutting down ethercard.\n", dev->name); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 4faf1fa082..565063d493 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -142,8 +142,8 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; /*====================================================================*/ -static void tc589_config(dev_link_t *link); -static void tc589_release(dev_link_t *link); +static void tc589_config(struct pcmcia_device *link); +static void tc589_release(struct pcmcia_device *link); static u16 read_eeprom(kio_addr_t ioaddr, int index); static void tc589_reset(struct net_device *dev); @@ -170,11 +170,10 @@ static void tc589_detach(struct pcmcia_device *p_dev); ======================================================================*/ -static int tc589_attach(struct pcmcia_device *p_dev) +static int tc589_attach(struct pcmcia_device *link) { struct el3_private *lp; struct net_device *dev; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "3c589_attach()\n"); @@ -184,7 +183,7 @@ static int tc589_attach(struct pcmcia_device *p_dev) return -ENOMEM; lp = netdev_priv(dev); link->priv = dev; - lp->p_dev = p_dev; + lp->p_dev = link; spin_lock_init(&lp->lock); link->io.NumPorts1 = 16; @@ -227,9 +226,8 @@ static int tc589_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void tc589_detach(struct pcmcia_device *p_dev) +static void tc589_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; DEBUG(0, "3c589_detach(0x%p)\n", link); @@ -254,9 +252,8 @@ static void tc589_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void tc589_config(dev_link_t *link) +static void tc589_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); tuple_t tuple; @@ -271,20 +268,20 @@ static void tc589_config(dev_link_t *link) phys_addr = (u16 *)dev->dev_addr; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* Is this a 3c562? */ tuple.DesiredTuple = CISTPL_MANFID; tuple.Attributes = TUPLE_RETURN_COMMON; - if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && - (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) { + if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && + (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) { if (le16_to_cpu(buf[0]) != MANFID_3COM) printk(KERN_INFO "3c589_cs: hmmm, is this really a " "3Com card??\n"); @@ -299,15 +296,15 @@ static void tc589_config(dev_link_t *link) for (i = j = 0; j < 0x400; j += 0x10) { if (multi && (j & 0x80)) continue; link->io.BasePort1 = j ^ 0x300; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); goto failed; } - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; @@ -317,8 +314,8 @@ static void tc589_config(dev_link_t *link) /* The 3c589 has an extra EEPROM for configuration info, including the hardware address. The 3c562 puts the address in the CIS. */ tuple.DesiredTuple = 0x88; - if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { - pcmcia_get_tuple_data(handle, &tuple); + if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { + pcmcia_get_tuple_data(link, &tuple); for (i = 0; i < 3; i++) phys_addr[i] = htons(buf[i]); } else { @@ -344,7 +341,7 @@ static void tc589_config(dev_link_t *link) link->dev_node = &lp->node; link->state &= ~DEV_CONFIG_PENDING; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); @@ -365,7 +362,7 @@ static void tc589_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: tc589_release(link); return; @@ -380,14 +377,13 @@ failed: ======================================================================*/ -static void tc589_release(dev_link_t *link) +static void tc589_release(struct pcmcia_device *link) { - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int tc589_suspend(struct pcmcia_device *p_dev) +static int tc589_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) @@ -396,9 +392,8 @@ static int tc589_suspend(struct pcmcia_device *p_dev) return 0; } -static int tc589_resume(struct pcmcia_device *p_dev) +static int tc589_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) { @@ -569,7 +564,7 @@ static int el3_config(struct net_device *dev, struct ifmap *map) static int el3_open(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; if (!DEV_OK(link)) return -ENODEV; @@ -830,7 +825,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); unsigned long flags; - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; if (DEV_OK(link)) { spin_lock_irqsave(&lp->lock, flags); @@ -932,7 +927,7 @@ static int el3_rx(struct net_device *dev) static void set_multicast_list(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; kio_addr_t ioaddr = dev->base_addr; u16 opts = SetRxFilter | RxStation | RxBroadcast; @@ -947,7 +942,7 @@ static void set_multicast_list(struct net_device *dev) static int el3_close(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; kio_addr_t ioaddr = dev->base_addr; DEBUG(1, "%s: shutting down ethercard.\n", dev->name); diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 58dc7c3835..88f180e98e 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -86,8 +86,8 @@ static char *version = /*====================================================================*/ -static void axnet_config(dev_link_t *link); -static void axnet_release(dev_link_t *link); +static void axnet_config(struct pcmcia_device *link); +static void axnet_release(struct pcmcia_device *link); static int axnet_open(struct net_device *dev); static int axnet_close(struct net_device *dev); static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); @@ -142,11 +142,10 @@ static inline axnet_dev_t *PRIV(struct net_device *dev) ======================================================================*/ -static int axnet_attach(struct pcmcia_device *p_dev) +static int axnet_attach(struct pcmcia_device *link) { axnet_dev_t *info; struct net_device *dev; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "axnet_attach()\n"); @@ -157,7 +156,7 @@ static int axnet_attach(struct pcmcia_device *p_dev) return -ENOMEM; info = PRIV(dev); - info->p_dev = p_dev; + info->p_dev = link; link->priv = dev; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.IRQInfo1 = IRQ_LEVEL_ID; @@ -184,9 +183,8 @@ static int axnet_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void axnet_detach(struct pcmcia_device *p_dev) +static void axnet_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; DEBUG(0, "axnet_detach(0x%p)\n", link); @@ -206,7 +204,7 @@ static void axnet_detach(struct pcmcia_device *p_dev) ======================================================================*/ -static int get_prom(dev_link_t *link) +static int get_prom(struct pcmcia_device *link) { struct net_device *dev = link->priv; kio_addr_t ioaddr = dev->base_addr; @@ -260,7 +258,7 @@ static int get_prom(dev_link_t *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int try_io_port(dev_link_t *link) +static int try_io_port(struct pcmcia_device *link) { int j, ret; if (link->io.NumPorts1 == 32) { @@ -281,18 +279,17 @@ static int try_io_port(dev_link_t *link) for (j = 0; j < 0x400; j += 0x20) { link->io.BasePort1 = j ^ 0x300; link->io.BasePort2 = (j ^ 0x300) + 0x10; - ret = pcmcia_request_io(link->handle, &link->io); + ret = pcmcia_request_io(link, &link->io); if (ret == CS_SUCCESS) return ret; } return ret; } else { - return pcmcia_request_io(link->handle, &link->io); + return pcmcia_request_io(link, &link->io); } } -static void axnet_config(dev_link_t *link) +static void axnet_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; axnet_dev_t *info = PRIV(dev); tuple_t tuple; @@ -307,9 +304,9 @@ static void axnet_config(dev_link_t *link) tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; /* don't trust the CIS on this; Linksys got it wrong */ link->conf.Present = 0x63; @@ -319,13 +316,13 @@ static void axnet_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (last_ret == CS_SUCCESS) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); cistpl_io_t *io = &(parse.cftable_entry.io); - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0 || + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0 || cfg->index == 0 || cfg->io.nwin == 0) goto next_entry; @@ -347,21 +344,21 @@ static void axnet_config(dev_link_t *link) if (last_ret == CS_SUCCESS) break; } next_entry: - last_ret = pcmcia_get_next_tuple(handle, &tuple); + last_ret = pcmcia_get_next_tuple(link, &tuple); } if (last_ret != CS_SUCCESS) { - cs_error(handle, RequestIO, last_ret); + cs_error(link, RequestIO, last_ret); goto failed; } - CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); if (link->io.NumPorts2 == 8) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; } - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; @@ -398,7 +395,7 @@ static void axnet_config(dev_link_t *link) Bit 2 of CCSR is active low. */ if (i == 32) { conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 }; - pcmcia_access_configuration_register(link->handle, ®); + pcmcia_access_configuration_register(link, ®); for (i = 0; i < 32; i++) { j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); if ((j != 0) && (j != 0xffff)) break; @@ -408,7 +405,7 @@ static void axnet_config(dev_link_t *link) info->phy_id = (i < 32) ? i : -1; link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n"); @@ -431,7 +428,7 @@ static void axnet_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: axnet_release(link); link->state &= ~DEV_CONFIG_PENDING; @@ -446,14 +443,13 @@ failed: ======================================================================*/ -static void axnet_release(dev_link_t *link) +static void axnet_release(struct pcmcia_device *link) { - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int axnet_suspend(struct pcmcia_device *p_dev) +static int axnet_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) @@ -462,9 +458,8 @@ static int axnet_suspend(struct pcmcia_device *p_dev) return 0; } -static int axnet_resume(struct pcmcia_device *p_dev) +static int axnet_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) { @@ -540,7 +535,7 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value) static int axnet_open(struct net_device *dev) { axnet_dev_t *info = PRIV(dev); - dev_link_t *link = info->p_dev; + struct pcmcia_device *link = info->p_dev; DEBUG(2, "axnet_open('%s')\n", dev->name); @@ -566,7 +561,7 @@ static int axnet_open(struct net_device *dev) static int axnet_close(struct net_device *dev) { axnet_dev_t *info = PRIV(dev); - dev_link_t *link = info->p_dev; + struct pcmcia_device *link = info->p_dev; DEBUG(2, "axnet_close('%s')\n", dev->name); diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 44da01cdd2..a9bcfb4ba1 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -118,8 +118,8 @@ MODULE_LICENSE("GPL"); /*====================================================================*/ -static void com20020_config(dev_link_t *link); -static void com20020_release(dev_link_t *link); +static void com20020_config(struct pcmcia_device *link); +static void com20020_release(struct pcmcia_device *link); static void com20020_detach(struct pcmcia_device *p_dev); @@ -198,9 +198,8 @@ fail_alloc_info: ======================================================================*/ -static void com20020_detach(struct pcmcia_device *p_dev) +static void com20020_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct com20020_dev_t *info = link->priv; struct net_device *dev = info->dev; @@ -251,10 +250,9 @@ static void com20020_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void com20020_config(dev_link_t *link) +static void com20020_config(struct pcmcia_device *link) { struct arcnet_local *lp; - client_handle_t handle; tuple_t tuple; cisparse_t parse; com20020_dev_t *info; @@ -263,7 +261,6 @@ static void com20020_config(dev_link_t *link) u_char buf[64]; int ioaddr; - handle = link->handle; info = link->priv; dev = info->dev; @@ -276,9 +273,9 @@ static void com20020_config(dev_link_t *link) tuple.TupleDataMax = 64; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; /* Configure card */ @@ -291,13 +288,13 @@ static void com20020_config(dev_link_t *link) for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) { link->io.BasePort1 = ioaddr; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } } else - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i != CS_SUCCESS) { @@ -311,7 +308,7 @@ static void com20020_config(dev_link_t *link) DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n", link->irq.AssignedIRQ, link->irq.IRQInfo1, link->irq.IRQInfo2); - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { DEBUG(1,"arcnet: requestIRQ failed totally!\n"); @@ -320,7 +317,7 @@ static void com20020_config(dev_link_t *link) dev->irq = link->irq.AssignedIRQ; - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); if (com20020_check(dev)) { @@ -334,7 +331,7 @@ static void com20020_config(dev_link_t *link) link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); i = com20020_found(dev, 0); /* calls register_netdev */ @@ -351,7 +348,7 @@ static void com20020_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: DEBUG(1,"com20020_config failed...\n"); com20020_release(link); @@ -365,15 +362,14 @@ failed: ======================================================================*/ -static void com20020_release(dev_link_t *link) +static void com20020_release(struct pcmcia_device *link) { DEBUG(0, "com20020_release(0x%p)\n", link); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int com20020_suspend(struct pcmcia_device *p_dev) +static int com20020_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); com20020_dev_t *info = link->priv; struct net_device *dev = info->dev; @@ -383,9 +379,8 @@ static int com20020_suspend(struct pcmcia_device *p_dev) return 0; } -static int com20020_resume(struct pcmcia_device *p_dev) +static int com20020_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); com20020_dev_t *info = link->priv; struct net_device *dev = info->dev; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 3f0ace4ed7..ad3e490bb0 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -84,10 +84,10 @@ static char *version = DRV_NAME ".c " DRV_VERSION " 2002/03/23"; /* PCMCIA event handlers */ -static void fmvj18x_config(dev_link_t *link); -static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id); -static int fmvj18x_setup_mfc(dev_link_t *link); -static void fmvj18x_release(dev_link_t *link); +static void fmvj18x_config(struct pcmcia_device *link); +static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id); +static int fmvj18x_setup_mfc(struct pcmcia_device *link); +static void fmvj18x_release(struct pcmcia_device *link); static void fmvj18x_detach(struct pcmcia_device *p_dev); /* @@ -228,11 +228,10 @@ typedef struct local_info_t { #define BANK_1U 0x24 /* bank 1 (CONFIG_1) */ #define BANK_2U 0x28 /* bank 2 (CONFIG_1) */ -static int fmvj18x_attach(struct pcmcia_device *p_dev) +static int fmvj18x_attach(struct pcmcia_device *link) { local_info_t *lp; struct net_device *dev; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "fmvj18x_attach()\n"); @@ -242,7 +241,7 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev) return -ENOMEM; lp = netdev_priv(dev); link->priv = dev; - lp->p_dev = p_dev; + lp->p_dev = link; /* The io structure describes IO port mapping */ link->io.NumPorts1 = 32; @@ -281,9 +280,8 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev) /*====================================================================*/ -static void fmvj18x_detach(struct pcmcia_device *p_dev) +static void fmvj18x_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; DEBUG(0, "fmvj18x_detach(0x%p)\n", link); @@ -302,7 +300,7 @@ static void fmvj18x_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int mfc_try_io_port(dev_link_t *link) +static int mfc_try_io_port(struct pcmcia_device *link) { int i, ret; static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; @@ -314,13 +312,13 @@ static int mfc_try_io_port(dev_link_t *link) link->io.NumPorts2 = 0; printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n"); } - ret = pcmcia_request_io(link->handle, &link->io); + ret = pcmcia_request_io(link, &link->io); if (ret == CS_SUCCESS) return ret; } return ret; } -static int ungermann_try_io_port(dev_link_t *link) +static int ungermann_try_io_port(struct pcmcia_device *link) { int ret; kio_addr_t ioaddr; @@ -330,7 +328,7 @@ static int ungermann_try_io_port(dev_link_t *link) */ for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) { link->io.BasePort1 = ioaddr; - ret = pcmcia_request_io(link->handle, &link->io); + ret = pcmcia_request_io(link, &link->io); if (ret == CS_SUCCESS) { /* calculate ConfigIndex value */ link->conf.ConfigIndex = @@ -341,9 +339,8 @@ static int ungermann_try_io_port(dev_link_t *link) return ret; /* RequestIO failed */ } -static void fmvj18x_config(dev_link_t *link) +static void fmvj18x_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; local_info_t *lp = netdev_priv(dev); tuple_t tuple; @@ -362,12 +359,12 @@ static void fmvj18x_config(dev_link_t *link) registers. */ tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); tuple.TupleData = (u_char *)buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); /* Configure card */ link->state |= DEV_CONFIG; @@ -377,16 +374,16 @@ static void fmvj18x_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_FUNCE; tuple.TupleOffset = 0; - if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { + if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigIndex = parse.cftable_entry.index; tuple.DesiredTuple = CISTPL_MANFID; - if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); else buf[0] = 0xffff; switch (le16_to_cpu(buf[0])) { @@ -420,8 +417,8 @@ static void fmvj18x_config(dev_link_t *link) } else { /* old type card */ tuple.DesiredTuple = CISTPL_MANFID; - if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); else buf[0] = 0xffff; switch (le16_to_cpu(buf[0])) { @@ -452,10 +449,10 @@ static void fmvj18x_config(dev_link_t *link) ret = ungermann_try_io_port(link); if (ret != CS_SUCCESS) goto cs_failed; } else { - CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); + CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); } - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; @@ -484,17 +481,17 @@ static void fmvj18x_config(dev_link_t *link) case CONTEC: tuple.DesiredTuple = CISTPL_FUNCE; tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); if (cardtype == MBH10304) { /* MBH10304's CIS_FUNCE is corrupted */ node_id = &(tuple.TupleData[5]); card_name = "FMV-J182"; } else { while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) { - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); } node_id = &(tuple.TupleData[2]); if( cardtype == TDK ) { @@ -538,7 +535,7 @@ static void fmvj18x_config(dev_link_t *link) lp->cardtype = cardtype; link->dev_node = &lp->node; link->state &= ~DEV_CONFIG_PENDING; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n"); @@ -559,7 +556,7 @@ static void fmvj18x_config(dev_link_t *link) cs_failed: /* All Card Services errors end up here */ - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: fmvj18x_release(link); link->state &= ~DEV_CONFIG_PENDING; @@ -567,7 +564,7 @@ failed: } /* fmvj18x_config */ /*====================================================================*/ -static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id) +static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id) { win_req_t req; memreq_t mem; @@ -578,9 +575,9 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id) req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Base = 0; req.Size = 0; req.AccessSpeed = 0; - i = pcmcia_request_window(&link->handle, &req, &link->win); + i = pcmcia_request_window(&link, &req, &link->win); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestWindow, i); + cs_error(link, RequestWindow, i); return -1; } @@ -614,13 +611,13 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id) iounmap(base); j = pcmcia_release_window(link->win); if (j != CS_SUCCESS) - cs_error(link->handle, ReleaseWindow, j); + cs_error(link, ReleaseWindow, j); return (i != 0x200) ? 0 : -1; } /* fmvj18x_get_hwinfo */ /*====================================================================*/ -static int fmvj18x_setup_mfc(dev_link_t *link) +static int fmvj18x_setup_mfc(struct pcmcia_device *link) { win_req_t req; memreq_t mem; @@ -633,9 +630,9 @@ static int fmvj18x_setup_mfc(dev_link_t *link) req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Base = 0; req.Size = 0; req.AccessSpeed = 0; - i = pcmcia_request_window(&link->handle, &req, &link->win); + i = pcmcia_request_window(&link, &req, &link->win); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestWindow, i); + cs_error(link, RequestWindow, i); return -1; } @@ -657,21 +654,20 @@ static int fmvj18x_setup_mfc(dev_link_t *link) iounmap(base); j = pcmcia_release_window(link->win); if (j != CS_SUCCESS) - cs_error(link->handle, ReleaseWindow, j); + cs_error(link, ReleaseWindow, j); return 0; } /*====================================================================*/ -static void fmvj18x_release(dev_link_t *link) +static void fmvj18x_release(struct pcmcia_device *link) { DEBUG(0, "fmvj18x_release(0x%p)\n", link); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int fmvj18x_suspend(struct pcmcia_device *p_dev) +static int fmvj18x_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) @@ -680,9 +676,8 @@ static int fmvj18x_suspend(struct pcmcia_device *p_dev) return 0; } -static int fmvj18x_resume(struct pcmcia_device *p_dev) +static int fmvj18x_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) { @@ -1122,7 +1117,7 @@ static int fjn_config(struct net_device *dev, struct ifmap *map){ static int fjn_open(struct net_device *dev) { struct local_info_t *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; DEBUG(4, "fjn_open('%s').\n", dev->name); @@ -1147,7 +1142,7 @@ static int fjn_open(struct net_device *dev) static int fjn_close(struct net_device *dev) { struct local_info_t *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; kio_addr_t ioaddr = dev->base_addr; DEBUG(4, "fjn_close('%s').\n", dev->name); diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index f4c3dd870a..1b8b44dc4c 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -105,9 +105,9 @@ MODULE_LICENSE("GPL"); /*====================================================================*/ -static void ibmtr_config(dev_link_t *link); +static void ibmtr_config(struct pcmcia_device *link); static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase); -static void ibmtr_release(dev_link_t *link); +static void ibmtr_release(struct pcmcia_device *link); static void ibmtr_detach(struct pcmcia_device *p_dev); /*====================================================================*/ @@ -138,12 +138,11 @@ static struct ethtool_ops netdev_ethtool_ops = { ======================================================================*/ -static int ibmtr_attach(struct pcmcia_device *p_dev) +static int ibmtr_attach(struct pcmcia_device *link) { ibmtr_dev_t *info; struct net_device *dev; - dev_link_t *link = dev_to_instance(p_dev); - + DEBUG(0, "ibmtr_attach()\n"); /* Create new token-ring device */ @@ -156,7 +155,7 @@ static int ibmtr_attach(struct pcmcia_device *p_dev) return -ENOMEM; } - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; info->ti = netdev_priv(dev); @@ -189,9 +188,8 @@ static int ibmtr_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void ibmtr_detach(struct pcmcia_device *p_dev) +static void ibmtr_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; @@ -222,9 +220,8 @@ static void ibmtr_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void ibmtr_config(dev_link_t *link) +static void ibmtr_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; struct tok_info *ti = netdev_priv(dev); @@ -242,9 +239,9 @@ static void ibmtr_config(dev_link_t *link) tuple.TupleDataMax = 64; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; /* Configure card */ @@ -256,15 +253,15 @@ static void ibmtr_config(dev_link_t *link) /* Try PRIMARY card at 0xA20-0xA23 */ link->io.BasePort1 = 0xA20; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i != CS_SUCCESS) { /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */ link->io.BasePort1 = 0xA24; - CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); + CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); } dev->base_addr = link->io.BasePort1; - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); dev->irq = link->irq.AssignedIRQ; ti->irq = link->irq.AssignedIRQ; ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); @@ -275,7 +272,7 @@ static void ibmtr_config(dev_link_t *link) req.Base = 0; req.Size = 0x2000; req.AccessSpeed = 250; - CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); + CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); mem.CardOffset = mmiobase; mem.Page = 0; @@ -288,7 +285,7 @@ static void ibmtr_config(dev_link_t *link) req.Base = 0; req.Size = sramsize * 1024; req.AccessSpeed = 250; - CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &info->sram_win_handle)); + CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &info->sram_win_handle)); mem.CardOffset = srambase; mem.Page = 0; @@ -298,7 +295,7 @@ static void ibmtr_config(dev_link_t *link) ti->sram_virt = ioremap(req.Base, req.Size); ti->sram_phys = req.Base; - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); /* Set up the Token-Ring Controller Configuration Register and turn on the card. Check the "Local Area Network Credit Card @@ -307,7 +304,7 @@ static void ibmtr_config(dev_link_t *link) link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); i = ibmtr_probe_card(dev); if (i != 0) { @@ -329,7 +326,7 @@ static void ibmtr_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: ibmtr_release(link); } /* ibmtr_config */ @@ -342,7 +339,7 @@ failed: ======================================================================*/ -static void ibmtr_release(dev_link_t *link) +static void ibmtr_release(struct pcmcia_device *link) { ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; @@ -354,12 +351,11 @@ static void ibmtr_release(dev_link_t *link) iounmap(ti->mmio); pcmcia_release_window(info->sram_win_handle); } - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int ibmtr_suspend(struct pcmcia_device *p_dev) +static int ibmtr_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; @@ -369,9 +365,8 @@ static int ibmtr_suspend(struct pcmcia_device *p_dev) return 0; } -static int ibmtr_resume(struct pcmcia_device *p_dev) +static int ibmtr_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 0ccca12d9d..8b8e716231 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -417,8 +417,8 @@ INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); Function Prototypes ---------------------------------------------------------------------------- */ -static void nmclan_config(dev_link_t *link); -static void nmclan_release(dev_link_t *link); +static void nmclan_config(struct pcmcia_device *link); +static void nmclan_release(struct pcmcia_device *link); static void nmclan_reset(struct net_device *dev); static int mace_config(struct net_device *dev, struct ifmap *map); @@ -443,11 +443,10 @@ nmclan_attach Services. ---------------------------------------------------------------------------- */ -static int nmclan_attach(struct pcmcia_device *p_dev) +static int nmclan_attach(struct pcmcia_device *link) { mace_private *lp; struct net_device *dev; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "nmclan_attach()\n"); DEBUG(1, "%s\n", rcsid); @@ -457,7 +456,7 @@ static int nmclan_attach(struct pcmcia_device *p_dev) if (!dev) return -ENOMEM; lp = netdev_priv(dev); - lp->p_dev = p_dev; + lp->p_dev = link; link->priv = dev; spin_lock_init(&lp->bank_lock); @@ -502,9 +501,8 @@ nmclan_detach when the device is released. ---------------------------------------------------------------------------- */ -static void nmclan_detach(struct pcmcia_device *p_dev) +static void nmclan_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; DEBUG(0, "nmclan_detach(0x%p)\n", link); @@ -657,9 +655,8 @@ nmclan_config #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void nmclan_config(dev_link_t *link) +static void nmclan_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; mace_private *lp = netdev_priv(dev); tuple_t tuple; @@ -675,17 +672,17 @@ static void nmclan_config(dev_link_t *link) tuple.TupleDataMax = 64; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; /* Configure card */ link->state |= DEV_CONFIG; - CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io)); - CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; @@ -696,8 +693,8 @@ static void nmclan_config(dev_link_t *link) tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN); /* Verify configuration by reading the MACE ID. */ @@ -728,7 +725,7 @@ static void nmclan_config(dev_link_t *link) link->dev_node = &lp->node; link->state &= ~DEV_CONFIG_PENDING; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); i = register_netdev(dev); if (i != 0) { @@ -746,7 +743,7 @@ static void nmclan_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: nmclan_release(link); return; @@ -759,15 +756,14 @@ nmclan_release net device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed. ---------------------------------------------------------------------------- */ -static void nmclan_release(dev_link_t *link) +static void nmclan_release(struct pcmcia_device *link) { DEBUG(0, "nmclan_release(0x%p)\n", link); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int nmclan_suspend(struct pcmcia_device *p_dev) +static int nmclan_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) @@ -776,9 +772,8 @@ static int nmclan_suspend(struct pcmcia_device *p_dev) return 0; } -static int nmclan_resume(struct pcmcia_device *p_dev) +static int nmclan_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) { @@ -799,7 +794,7 @@ static void nmclan_reset(struct net_device *dev) mace_private *lp = netdev_priv(dev); #if RESET_XILINX - dev_link_t *link = &lp->link; + struct pcmcia_device *link = &lp->link; conf_reg_t reg; u_long OrigCorValue; @@ -808,7 +803,7 @@ static void nmclan_reset(struct net_device *dev) reg.Action = CS_READ; reg.Offset = CISREG_COR; reg.Value = 0; - pcmcia_access_configuration_register(link->handle, ®); + pcmcia_access_configuration_register(link, ®); OrigCorValue = reg.Value; /* Reset Xilinx */ @@ -817,12 +812,12 @@ static void nmclan_reset(struct net_device *dev) DEBUG(1, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n", OrigCorValue); reg.Value = COR_SOFT_RESET; - pcmcia_access_configuration_register(link->handle, ®); + pcmcia_access_configuration_register(link, ®); /* Need to wait for 20 ms for PCMCIA to finish reset. */ /* Restore original COR configuration index */ reg.Value = COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK); - pcmcia_access_configuration_register(link->handle, ®); + pcmcia_access_configuration_register(link, ®); /* Xilinx is now completely reset along with the MACE chip. */ lp->tx_free_frames=AM2150_MAX_TX_FRAMES; @@ -866,7 +861,7 @@ static int mace_open(struct net_device *dev) { kio_addr_t ioaddr = dev->base_addr; mace_private *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; if (!DEV_OK(link)) return -ENODEV; @@ -889,7 +884,7 @@ static int mace_close(struct net_device *dev) { kio_addr_t ioaddr = dev->base_addr; mace_private *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; DEBUG(2, "%s: shutting down ethercard.\n", dev->name); @@ -944,12 +939,12 @@ mace_start_xmit static void mace_tx_timeout(struct net_device *dev) { mace_private *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name); #if RESET_ON_TIMEOUT printk("resetting card\n"); - pcmcia_reset_card(link->handle, NULL); + pcmcia_reset_card(link, NULL); #else /* #if RESET_ON_TIMEOUT */ printk("NOT resetting card\n"); #endif /* #if RESET_ON_TIMEOUT */ diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 8ed6a410ea..9f41355e6b 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -103,8 +103,8 @@ module_param_array(hw_addr, int, NULL, 0); /*====================================================================*/ static void mii_phy_probe(struct net_device *dev); -static void pcnet_config(dev_link_t *link); -static void pcnet_release(dev_link_t *link); +static void pcnet_config(struct pcmcia_device *link); +static void pcnet_release(struct pcmcia_device *link); static int pcnet_open(struct net_device *dev); static int pcnet_close(struct net_device *dev); static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); @@ -113,9 +113,9 @@ static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs); static void ei_watchdog(u_long arg); static void pcnet_reset_8390(struct net_device *dev); static int set_config(struct net_device *dev, struct ifmap *map); -static int setup_shmem_window(dev_link_t *link, int start_pg, +static int setup_shmem_window(struct pcmcia_device *link, int start_pg, int stop_pg, int cm_offset); -static int setup_dma_config(dev_link_t *link, int start_pg, +static int setup_dma_config(struct pcmcia_device *link, int start_pg, int stop_pg); static void pcnet_detach(struct pcmcia_device *p_dev); @@ -240,11 +240,10 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev) ======================================================================*/ -static int pcnet_probe(struct pcmcia_device *p_dev) +static int pcnet_probe(struct pcmcia_device *link) { pcnet_dev_t *info; struct net_device *dev; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "pcnet_attach()\n"); @@ -252,7 +251,7 @@ static int pcnet_probe(struct pcmcia_device *p_dev) dev = __alloc_ei_netdev(sizeof(pcnet_dev_t)); if (!dev) return -ENOMEM; info = PRIV(dev); - info->p_dev = p_dev; + info->p_dev = link; link->priv = dev; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; @@ -280,9 +279,8 @@ static int pcnet_probe(struct pcmcia_device *p_dev) ======================================================================*/ -static void pcnet_detach(struct pcmcia_device *p_dev) +static void pcnet_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; DEBUG(0, "pcnet_detach(0x%p)\n", link); @@ -303,7 +301,7 @@ static void pcnet_detach(struct pcmcia_device *p_dev) ======================================================================*/ -static hw_info_t *get_hwinfo(dev_link_t *link) +static hw_info_t *get_hwinfo(struct pcmcia_device *link) { struct net_device *dev = link->priv; win_req_t req; @@ -315,9 +313,9 @@ static hw_info_t *get_hwinfo(dev_link_t *link) req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Base = 0; req.Size = 0; req.AccessSpeed = 0; - i = pcmcia_request_window(&link->handle, &req, &link->win); + i = pcmcia_request_window(&link, &req, &link->win); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestWindow, i); + cs_error(link, RequestWindow, i); return NULL; } @@ -340,7 +338,7 @@ static hw_info_t *get_hwinfo(dev_link_t *link) iounmap(virt); j = pcmcia_release_window(link->win); if (j != CS_SUCCESS) - cs_error(link->handle, ReleaseWindow, j); + cs_error(link, ReleaseWindow, j); return (i < NR_INFO) ? hw_info+i : NULL; } /* get_hwinfo */ @@ -352,7 +350,7 @@ static hw_info_t *get_hwinfo(dev_link_t *link) ======================================================================*/ -static hw_info_t *get_prom(dev_link_t *link) +static hw_info_t *get_prom(struct pcmcia_device *link) { struct net_device *dev = link->priv; kio_addr_t ioaddr = dev->base_addr; @@ -406,7 +404,7 @@ static hw_info_t *get_prom(dev_link_t *link) ======================================================================*/ -static hw_info_t *get_dl10019(dev_link_t *link) +static hw_info_t *get_dl10019(struct pcmcia_device *link) { struct net_device *dev = link->priv; int i; @@ -428,7 +426,7 @@ static hw_info_t *get_dl10019(dev_link_t *link) ======================================================================*/ -static hw_info_t *get_ax88190(dev_link_t *link) +static hw_info_t *get_ax88190(struct pcmcia_device *link) { struct net_device *dev = link->priv; kio_addr_t ioaddr = dev->base_addr; @@ -461,7 +459,7 @@ static hw_info_t *get_ax88190(dev_link_t *link) ======================================================================*/ -static hw_info_t *get_hwired(dev_link_t *link) +static hw_info_t *get_hwired(struct pcmcia_device *link) { struct net_device *dev = link->priv; int i; @@ -488,7 +486,7 @@ static hw_info_t *get_hwired(dev_link_t *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static int try_io_port(dev_link_t *link) +static int try_io_port(struct pcmcia_device *link) { int j, ret; if (link->io.NumPorts1 == 32) { @@ -509,18 +507,17 @@ static int try_io_port(dev_link_t *link) for (j = 0; j < 0x400; j += 0x20) { link->io.BasePort1 = j ^ 0x300; link->io.BasePort2 = (j ^ 0x300) + 0x10; - ret = pcmcia_request_io(link->handle, &link->io); + ret = pcmcia_request_io(link, &link->io); if (ret == CS_SUCCESS) return ret; } return ret; } else { - return pcmcia_request_io(link->handle, &link->io); + return pcmcia_request_io(link, &link->io); } } -static void pcnet_config(dev_link_t *link) +static void pcnet_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; pcnet_dev_t *info = PRIV(dev); tuple_t tuple; @@ -537,9 +534,9 @@ static void pcnet_config(dev_link_t *link) tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -548,21 +545,21 @@ static void pcnet_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_MANFID; tuple.Attributes = TUPLE_RETURN_COMMON; - if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && - (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) { + if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && + (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) { manfid = le16_to_cpu(buf[0]); prodid = le16_to_cpu(buf[1]); } tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (last_ret == CS_SUCCESS) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); cistpl_io_t *io = &(parse.cftable_entry.io); - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0 || + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0 || cfg->index == 0 || cfg->io.nwin == 0) goto next_entry; @@ -586,14 +583,14 @@ static void pcnet_config(dev_link_t *link) if (last_ret == CS_SUCCESS) break; } next_entry: - last_ret = pcmcia_get_next_tuple(handle, &tuple); + last_ret = pcmcia_get_next_tuple(link, &tuple); } if (last_ret != CS_SUCCESS) { - cs_error(handle, RequestIO, last_ret); + cs_error(link, RequestIO, last_ret); goto failed; } - CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); if (link->io.NumPorts2 == 8) { link->conf.Attributes |= CONF_ENABLE_SPKR; @@ -603,7 +600,7 @@ static void pcnet_config(dev_link_t *link) (prodid == PRODID_IBM_HOME_AND_AWAY)) link->conf.ConfigIndex |= 0x10; - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; if (info->flags & HAS_MISC_REG) { @@ -673,7 +670,7 @@ static void pcnet_config(dev_link_t *link) link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = ei_poll; @@ -707,7 +704,7 @@ static void pcnet_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: pcnet_release(link); link->state &= ~DEV_CONFIG_PENDING; @@ -722,7 +719,7 @@ failed: ======================================================================*/ -static void pcnet_release(dev_link_t *link) +static void pcnet_release(struct pcmcia_device *link) { pcnet_dev_t *info = PRIV(link->priv); @@ -731,7 +728,7 @@ static void pcnet_release(dev_link_t *link) if (info->flags & USE_SHMEM) iounmap(info->base); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } /*====================================================================== @@ -743,9 +740,8 @@ static void pcnet_release(dev_link_t *link) ======================================================================*/ -static int pcnet_suspend(struct pcmcia_device *p_dev) +static int pcnet_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) @@ -754,9 +750,8 @@ static int pcnet_suspend(struct pcmcia_device *p_dev) return 0; } -static int pcnet_resume(struct pcmcia_device *p_dev) +static int pcnet_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) { @@ -1002,7 +997,7 @@ static void mii_phy_probe(struct net_device *dev) static int pcnet_open(struct net_device *dev) { pcnet_dev_t *info = PRIV(dev); - dev_link_t *link = info->p_dev; + struct pcmcia_device *link = info->p_dev; DEBUG(2, "pcnet_open('%s')\n", dev->name); @@ -1030,7 +1025,7 @@ static int pcnet_open(struct net_device *dev) static int pcnet_close(struct net_device *dev) { pcnet_dev_t *info = PRIV(dev); - dev_link_t *link = info->p_dev; + struct pcmcia_device *link = info->p_dev; DEBUG(2, "pcnet_close('%s')\n", dev->name); @@ -1408,7 +1403,7 @@ static void dma_block_output(struct net_device *dev, int count, /*====================================================================*/ -static int setup_dma_config(dev_link_t *link, int start_pg, +static int setup_dma_config(struct pcmcia_device *link, int start_pg, int stop_pg) { struct net_device *dev = link->priv; @@ -1511,7 +1506,7 @@ static void shmem_block_output(struct net_device *dev, int count, /*====================================================================*/ -static int setup_shmem_window(dev_link_t *link, int start_pg, +static int setup_shmem_window(struct pcmcia_device *link, int start_pg, int stop_pg, int cm_offset) { struct net_device *dev = link->priv; @@ -1533,7 +1528,7 @@ static int setup_shmem_window(dev_link_t *link, int start_pg, req.Attributes |= WIN_USE_WAIT; req.Base = 0; req.Size = window_size; req.AccessSpeed = mem_speed; - CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); + CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); mem.CardOffset = (start_pg << 8) + cm_offset; offset = mem.CardOffset % window_size; @@ -1574,7 +1569,7 @@ static int setup_shmem_window(dev_link_t *link, int start_pg, return 0; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: return 1; } diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index a18b02a9a6..a4ee3057b8 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -279,8 +279,8 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002, /*====================================================================*/ static void smc91c92_detach(struct pcmcia_device *p_dev); -static void smc91c92_config(dev_link_t *link); -static void smc91c92_release(dev_link_t *link); +static void smc91c92_config(struct pcmcia_device *link); +static void smc91c92_release(struct pcmcia_device *link); static int smc_open(struct net_device *dev); static int smc_close(struct net_device *dev); @@ -309,11 +309,10 @@ static struct ethtool_ops ethtool_ops; ======================================================================*/ -static int smc91c92_attach(struct pcmcia_device *p_dev) +static int smc91c92_attach(struct pcmcia_device *link) { struct smc_private *smc; struct net_device *dev; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "smc91c92_attach()\n"); @@ -322,7 +321,7 @@ static int smc91c92_attach(struct pcmcia_device *p_dev) if (!dev) return -ENOMEM; smc = netdev_priv(dev); - smc->p_dev = p_dev; + smc->p_dev = link; link->priv = dev; spin_lock_init(&smc->lock); @@ -372,9 +371,8 @@ static int smc91c92_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void smc91c92_detach(struct pcmcia_device *p_dev) +static void smc91c92_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; DEBUG(0, "smc91c92_detach(0x%p)\n", link); @@ -411,7 +409,7 @@ static int cvt_ascii_address(struct net_device *dev, char *s) /*====================================================================*/ -static int first_tuple(client_handle_t handle, tuple_t *tuple, +static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i; @@ -422,7 +420,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, return pcmcia_parse_tuple(handle, tuple, parse); } -static int next_tuple(client_handle_t handle, tuple_t *tuple, +static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int i; @@ -444,7 +442,7 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, ======================================================================*/ -static int mhz_3288_power(dev_link_t *link) +static int mhz_3288_power(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct smc_private *smc = netdev_priv(dev); @@ -466,7 +464,7 @@ static int mhz_3288_power(dev_link_t *link) return 0; } -static int mhz_mfc_config(dev_link_t *link) +static int mhz_mfc_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct smc_private *smc = netdev_priv(dev); @@ -501,7 +499,7 @@ static int mhz_mfc_config(dev_link_t *link) tuple->TupleDataMax = 255; tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; - i = first_tuple(link->handle, tuple, parse); + i = first_tuple(link, tuple, parse); /* The Megahertz combo cards have modem-like CIS entries, so we have to explicitly try a bunch of port combinations. */ while (i == CS_SUCCESS) { @@ -510,11 +508,11 @@ static int mhz_mfc_config(dev_link_t *link) for (k = 0; k < 0x400; k += 0x10) { if (k & 0x80) continue; link->io.BasePort1 = k ^ 0x300; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } if (i == CS_SUCCESS) break; - i = next_tuple(link->handle, tuple, parse); + i = next_tuple(link, tuple, parse); } if (i != CS_SUCCESS) goto free_cfg_mem; @@ -524,7 +522,7 @@ static int mhz_mfc_config(dev_link_t *link) req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Base = req.Size = 0; req.AccessSpeed = 0; - i = pcmcia_request_window(&link->handle, &req, &link->win); + i = pcmcia_request_window(&link, &req, &link->win); if (i != CS_SUCCESS) goto free_cfg_mem; smc->base = ioremap(req.Base, req.Size); @@ -543,9 +541,8 @@ free_cfg_mem: return i; } -static int mhz_setup(dev_link_t *link) +static int mhz_setup(struct pcmcia_device *link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; struct smc_cfg_mem *cfg_mem; tuple_t *tuple; @@ -568,13 +565,13 @@ static int mhz_setup(dev_link_t *link) /* Read the station address from the CIS. It is stored as the last (fourth) string in the Version 1 Version/ID tuple. */ tuple->DesiredTuple = CISTPL_VERS_1; - if (first_tuple(handle, tuple, parse) != CS_SUCCESS) { + if (first_tuple(link, tuple, parse) != CS_SUCCESS) { rc = -1; goto free_cfg_mem; } /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ - if (next_tuple(handle, tuple, parse) != CS_SUCCESS) - first_tuple(handle, tuple, parse); + if (next_tuple(link, tuple, parse) != CS_SUCCESS) + first_tuple(link, tuple, parse); if (parse->version_1.ns > 3) { station_addr = parse->version_1.str + parse->version_1.ofs[3]; if (cvt_ascii_address(dev, station_addr) == 0) { @@ -585,11 +582,11 @@ static int mhz_setup(dev_link_t *link) /* Another possibility: for the EM3288, in a special tuple */ tuple->DesiredTuple = 0x81; - if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) { + if (pcmcia_get_first_tuple(link, tuple) != CS_SUCCESS) { rc = -1; goto free_cfg_mem; } - if (pcmcia_get_tuple_data(handle, tuple) != CS_SUCCESS) { + if (pcmcia_get_tuple_data(link, tuple) != CS_SUCCESS) { rc = -1; goto free_cfg_mem; } @@ -613,7 +610,7 @@ free_cfg_mem: ======================================================================*/ -static void mot_config(dev_link_t *link) +static void mot_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct smc_private *smc = netdev_priv(dev); @@ -634,7 +631,7 @@ static void mot_config(dev_link_t *link) mdelay(100); } -static int mot_setup(dev_link_t *link) +static int mot_setup(struct pcmcia_device *link) { struct net_device *dev = link->priv; kio_addr_t ioaddr = dev->base_addr; @@ -668,7 +665,7 @@ static int mot_setup(dev_link_t *link) /*====================================================================*/ -static int smc_config(dev_link_t *link) +static int smc_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct smc_cfg_mem *cfg_mem; @@ -693,16 +690,16 @@ static int smc_config(dev_link_t *link) tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; link->io.NumPorts1 = 16; - i = first_tuple(link->handle, tuple, parse); + i = first_tuple(link, tuple, parse); while (i != CS_NO_MORE_ITEMS) { if (i == CS_SUCCESS) { link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } - i = next_tuple(link->handle, tuple, parse); + i = next_tuple(link, tuple, parse); } if (i == CS_SUCCESS) dev->base_addr = link->io.BasePort1; @@ -711,9 +708,8 @@ static int smc_config(dev_link_t *link) return i; } -static int smc_setup(dev_link_t *link) +static int smc_setup(struct pcmcia_device *link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; struct smc_cfg_mem *cfg_mem; tuple_t *tuple; @@ -736,11 +732,11 @@ static int smc_setup(dev_link_t *link) /* Check for a LAN function extension tuple */ tuple->DesiredTuple = CISTPL_FUNCE; - i = first_tuple(handle, tuple, parse); + i = first_tuple(link, tuple, parse); while (i == CS_SUCCESS) { if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID) break; - i = next_tuple(handle, tuple, parse); + i = next_tuple(link, tuple, parse); } if (i == CS_SUCCESS) { node_id = (cistpl_lan_node_id_t *)parse->funce.data; @@ -753,7 +749,7 @@ static int smc_setup(dev_link_t *link) } /* Try the third string in the Version 1 Version/ID tuple. */ tuple->DesiredTuple = CISTPL_VERS_1; - if (first_tuple(handle, tuple, parse) != CS_SUCCESS) { + if (first_tuple(link, tuple, parse) != CS_SUCCESS) { rc = -1; goto free_cfg_mem; } @@ -771,7 +767,7 @@ free_cfg_mem: /*====================================================================*/ -static int osi_config(dev_link_t *link) +static int osi_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; static const kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; @@ -791,22 +787,21 @@ static int osi_config(dev_link_t *link) for (i = j = 0; j < 4; j++) { link->io.BasePort2 = com[j]; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } if (i != CS_SUCCESS) { /* Fallback: turn off hard decode */ link->conf.ConfigIndex = 0x03; link->io.NumPorts2 = 0; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); } dev->base_addr = link->io.BasePort1 + 0x10; return i; } -static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) +static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; struct smc_cfg_mem *cfg_mem; tuple_t *tuple; @@ -827,12 +822,12 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) /* Read the station address from tuple 0x90, subtuple 0x04 */ tuple->DesiredTuple = 0x90; - i = pcmcia_get_first_tuple(handle, tuple); + i = pcmcia_get_first_tuple(link, tuple); while (i == CS_SUCCESS) { - i = pcmcia_get_tuple_data(handle, tuple); + i = pcmcia_get_tuple_data(link, tuple); if ((i != CS_SUCCESS) || (buf[0] == 0x04)) break; - i = pcmcia_get_next_tuple(handle, tuple); + i = pcmcia_get_next_tuple(link, tuple); } if (i != CS_SUCCESS) { rc = -1; @@ -865,9 +860,8 @@ free_cfg_mem: return rc; } -static int smc91c92_suspend(struct pcmcia_device *p_dev) +static int smc91c92_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) @@ -876,9 +870,8 @@ static int smc91c92_suspend(struct pcmcia_device *p_dev) return 0; } -static int smc91c92_resume(struct pcmcia_device *p_dev) +static int smc91c92_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; struct smc_private *smc = netdev_priv(dev); int i; @@ -922,7 +915,7 @@ static int smc91c92_resume(struct pcmcia_device *p_dev) ======================================================================*/ -static int check_sig(dev_link_t *link) +static int check_sig(struct pcmcia_device *link) { struct net_device *dev = link->priv; kio_addr_t ioaddr = dev->base_addr; @@ -960,9 +953,9 @@ static int check_sig(dev_link_t *link) }; printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); - smc91c92_suspend(link->handle); - pcmcia_modify_configuration(link->handle, &mod); - smc91c92_resume(link->handle); + smc91c92_suspend(link); + pcmcia_modify_configuration(link, &mod); + smc91c92_resume(link); return check_sig(link); } return -ENODEV; @@ -977,11 +970,10 @@ static int check_sig(dev_link_t *link) ======================================================================*/ #define CS_EXIT_TEST(ret, svc, label) \ -if (ret != CS_SUCCESS) { cs_error(link->handle, svc, ret); goto label; } +if (ret != CS_SUCCESS) { cs_error(link, svc, ret); goto label; } -static void smc91c92_config(dev_link_t *link) +static void smc91c92_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; struct smc_private *smc = netdev_priv(dev); struct smc_cfg_mem *cfg_mem; @@ -1008,14 +1000,14 @@ static void smc91c92_config(dev_link_t *link) tuple->TupleDataMax = 64; tuple->DesiredTuple = CISTPL_CONFIG; - i = first_tuple(handle, tuple, parse); + i = first_tuple(link, tuple, parse); CS_EXIT_TEST(i, ParseTuple, config_failed); link->conf.ConfigBase = parse->config.base; link->conf.Present = parse->config.rmask[0]; tuple->DesiredTuple = CISTPL_MANFID; tuple->Attributes = TUPLE_RETURN_COMMON; - if (first_tuple(handle, tuple, parse) == CS_SUCCESS) { + if (first_tuple(link, tuple, parse) == CS_SUCCESS) { smc->manfid = parse->manfid.manf; smc->cardid = parse->manfid.card; } @@ -1036,9 +1028,9 @@ static void smc91c92_config(dev_link_t *link) } CS_EXIT_TEST(i, RequestIO, config_failed); - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); CS_EXIT_TEST(i, RequestIRQ, config_failed); - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); CS_EXIT_TEST(i, RequestConfiguration, config_failed); if (smc->manfid == MANFID_MOTOROLA) @@ -1119,7 +1111,7 @@ static void smc91c92_config(dev_link_t *link) link->dev_node = &smc->node; link->state &= ~DEV_CONFIG_PENDING; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n"); @@ -1172,7 +1164,7 @@ config_failed: /* CS_EXIT_TEST() calls jump to here... */ ======================================================================*/ -static void smc91c92_release(dev_link_t *link) +static void smc91c92_release(struct pcmcia_device *link) { DEBUG(0, "smc91c92_release(0x%p)\n", link); if (link->win) { @@ -1180,7 +1172,7 @@ static void smc91c92_release(dev_link_t *link) struct smc_private *smc = netdev_priv(dev); iounmap(smc->base); } - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } /*====================================================================== @@ -1269,7 +1261,7 @@ static void smc_dump(struct net_device *dev) static int smc_open(struct net_device *dev) { struct smc_private *smc = netdev_priv(dev); - dev_link_t *link = smc->p_dev; + struct pcmcia_device *link = smc->p_dev; #ifdef PCMCIA_DEBUG DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n", @@ -1306,7 +1298,7 @@ static int smc_open(struct net_device *dev) static int smc_close(struct net_device *dev) { struct smc_private *smc = netdev_priv(dev); - dev_link_t *link = smc->p_dev; + struct pcmcia_device *link = smc->p_dev; kio_addr_t ioaddr = dev->base_addr; DEBUG(0, "%s: smc_close(), status %4.4x.\n", diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 94a1e644ab..84328da075 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -289,9 +289,9 @@ static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, * and ejection events. They are invoked from the event handler. */ -static int has_ce2_string(dev_link_t * link); -static void xirc2ps_config(dev_link_t * link); -static void xirc2ps_release(dev_link_t * link); +static int has_ce2_string(struct pcmcia_device * link); +static void xirc2ps_config(struct pcmcia_device * link); +static void xirc2ps_release(struct pcmcia_device * link); /**************** * The attach() and detach() entry points are used to create and destroy @@ -313,10 +313,10 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs /**************** * A linked list of "instances" of the device. Each actual * PCMCIA card corresponds to one device instance, and is described - * by one dev_link_t structure (defined in ds.h). + * by one struct pcmcia_device structure (defined in ds.h). * * You may not want to use a linked list for this -- for example, the - * memory card driver uses an array of dev_link_t pointers, where minor + * memory card driver uses an array of struct pcmcia_device pointers, where minor * device numbers are used to derive the corresponding array index. */ @@ -326,7 +326,7 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs * example, ethernet cards, modems). In other cases, there may be * many actual or logical devices (SCSI adapters, memory cards with * multiple partitions). The dev_node_t structures need to be kept - * in a linked list starting at the 'dev' field of a dev_link_t + * in a linked list starting at the 'dev' field of a struct pcmcia_device * structure. We allocate them in the card's private data structure, * because they generally can't be allocated dynamically. */ @@ -355,7 +355,7 @@ static void do_tx_timeout(struct net_device *dev); static struct net_device_stats *do_get_stats(struct net_device *dev); static void set_addresses(struct net_device *dev); static void set_multicast_list(struct net_device *dev); -static int set_card_type(dev_link_t *link, const void *s); +static int set_card_type(struct pcmcia_device *link, const void *s); static int do_config(struct net_device *dev, struct ifmap *map); static int do_open(struct net_device *dev); static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); @@ -368,7 +368,7 @@ static int do_stop(struct net_device *dev); /*=============== Helper functions =========================*/ static int -first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int err; @@ -379,7 +379,7 @@ first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) } static int -next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) +next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) { int err; @@ -553,11 +553,10 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len) */ static int -xirc2ps_attach(struct pcmcia_device *p_dev) +xirc2ps_attach(struct pcmcia_device *link) { struct net_device *dev; local_info_t *local; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "attach()\n"); @@ -566,7 +565,7 @@ xirc2ps_attach(struct pcmcia_device *p_dev) if (!dev) return -ENOMEM; local = netdev_priv(dev); - local->p_dev = p_dev; + local->p_dev = link; link->priv = dev; /* General socket configuration */ @@ -606,9 +605,8 @@ xirc2ps_attach(struct pcmcia_device *p_dev) */ static void -xirc2ps_detach(struct pcmcia_device *p_dev) +xirc2ps_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; DEBUG(0, "detach(0x%p)\n", link); @@ -641,7 +639,7 @@ xirc2ps_detach(struct pcmcia_device *p_dev) * */ static int -set_card_type(dev_link_t *link, const void *s) +set_card_type(struct pcmcia_device *link, const void *s) { struct net_device *dev = link->priv; local_info_t *local = netdev_priv(dev); @@ -710,9 +708,8 @@ set_card_type(dev_link_t *link, const void *s) * Returns: true if this is a CE2 */ static int -has_ce2_string(dev_link_t * link) +has_ce2_string(struct pcmcia_device * link) { - client_handle_t handle = link->handle; tuple_t tuple; cisparse_t parse; u_char buf[256]; @@ -722,7 +719,7 @@ has_ce2_string(dev_link_t * link) tuple.TupleDataMax = 254; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_VERS_1; - if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) { + if (!first_tuple(link, &tuple, &parse) && parse.version_1.ns > 2) { if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2")) return 1; } @@ -735,9 +732,8 @@ has_ce2_string(dev_link_t * link) * ethernet device available to the system. */ static void -xirc2ps_config(dev_link_t * link) +xirc2ps_config(struct pcmcia_device * link) { - client_handle_t handle = link->handle; struct net_device *dev = link->priv; local_info_t *local = netdev_priv(dev); tuple_t tuple; @@ -763,7 +759,7 @@ xirc2ps_config(dev_link_t * link) /* Is this a valid card */ tuple.DesiredTuple = CISTPL_MANFID; - if ((err=first_tuple(handle, &tuple, &parse))) { + if ((err=first_tuple(link, &tuple, &parse))) { printk(KNOT_XIRC "manfid not found in CIS\n"); goto failure; } @@ -799,15 +795,15 @@ xirc2ps_config(dev_link_t * link) /* get configuration stuff */ tuple.DesiredTuple = CISTPL_CONFIG; - if ((err=first_tuple(handle, &tuple, &parse))) + if ((err=first_tuple(link, &tuple, &parse))) goto cis_error; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* get the ethernet address from the CIS */ tuple.DesiredTuple = CISTPL_FUNCE; - for (err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse)) { + for (err = first_tuple(link, &tuple, &parse); !err; + err = next_tuple(link, &tuple, &parse)) { /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries: * the first one with a length of zero the second correct - * so I skip all entries with length 0 */ @@ -817,8 +813,8 @@ xirc2ps_config(dev_link_t * link) } if (err) { /* not found: try to get the node-id from tuple 0x89 */ tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */ - if ((err = pcmcia_get_first_tuple(handle, &tuple)) == 0 && - (err = pcmcia_get_tuple_data(handle, &tuple)) == 0) { + if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 && + (err = pcmcia_get_tuple_data(link, &tuple)) == 0) { if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID) memcpy(&parse, buf, 8); else @@ -827,8 +823,8 @@ xirc2ps_config(dev_link_t * link) } if (err) { /* another try (James Lehmer's CE2 version 4.1)*/ tuple.DesiredTuple = CISTPL_FUNCE; - for (err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse)) { + for (err = first_tuple(link, &tuple, &parse); !err; + err = next_tuple(link, &tuple, &parse)) { if (parse.funce.type == 0x02 && parse.funce.data[0] == 1 && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) { buf[1] = 4; @@ -871,14 +867,14 @@ xirc2ps_config(dev_link_t * link) * Ethernet port */ link->io.NumPorts1 = 16; /* no Mako stuff anymore */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - for (err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse)) { + for (err = first_tuple(link, &tuple, &parse); !err; + err = next_tuple(link, &tuple, &parse)) { if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = ioaddr; - if (!(err=pcmcia_request_io(link->handle, &link->io))) + if (!(err=pcmcia_request_io(link, &link->io))) goto port_found; } } @@ -892,15 +888,15 @@ xirc2ps_config(dev_link_t * link) */ for (pass=0; pass < 2; pass++) { tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - for (err = first_tuple(handle, &tuple, &parse); !err; - err = next_tuple(handle, &tuple, &parse)){ + for (err = first_tuple(link, &tuple, &parse); !err; + err = next_tuple(link, &tuple, &parse)){ if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){ link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = link->io.BasePort2 + (pass ? (cf->index & 0x20 ? -24:8) : (cf->index & 0x20 ? 8:-24)); - if (!(err=pcmcia_request_io(link->handle, &link->io))) + if (!(err=pcmcia_request_io(link, &link->io))) goto port_found; } } @@ -915,12 +911,12 @@ xirc2ps_config(dev_link_t * link) link->io.NumPorts1 = 16; for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->io.BasePort1 = ioaddr; - if (!(err=pcmcia_request_io(link->handle, &link->io))) + if (!(err=pcmcia_request_io(link, &link->io))) goto port_found; } link->io.BasePort1 = 0; /* let CS decide */ - if ((err=pcmcia_request_io(link->handle, &link->io))) { - cs_error(link->handle, RequestIO, err); + if ((err=pcmcia_request_io(link, &link->io))) { + cs_error(link, RequestIO, err); goto config_error; } } @@ -932,8 +928,8 @@ xirc2ps_config(dev_link_t * link) * Now allocate an interrupt line. Note that this does not * actually assign a handler to the interrupt. */ - if ((err=pcmcia_request_irq(link->handle, &link->irq))) { - cs_error(link->handle, RequestIRQ, err); + if ((err=pcmcia_request_irq(link, &link->irq))) { + cs_error(link, RequestIRQ, err); goto config_error; } @@ -941,8 +937,8 @@ xirc2ps_config(dev_link_t * link) * This actually configures the PCMCIA socket -- setting up * the I/O windows and the interrupt mapping. */ - if ((err=pcmcia_request_configuration(link->handle, &link->conf))) { - cs_error(link->handle, RequestConfiguration, err); + if ((err=pcmcia_request_configuration(link, &link->conf))) { + cs_error(link, RequestConfiguration, err); goto config_error; } @@ -959,15 +955,15 @@ xirc2ps_config(dev_link_t * link) reg.Action = CS_WRITE; reg.Offset = CISREG_IOBASE_0; reg.Value = link->io.BasePort2 & 0xff; - if ((err = pcmcia_access_configuration_register(link->handle, ®))) { - cs_error(link->handle, AccessConfigurationRegister, err); + if ((err = pcmcia_access_configuration_register(link, ®))) { + cs_error(link, AccessConfigurationRegister, err); goto config_error; } reg.Action = CS_WRITE; reg.Offset = CISREG_IOBASE_1; reg.Value = (link->io.BasePort2 >> 8) & 0xff; - if ((err = pcmcia_access_configuration_register(link->handle, ®))) { - cs_error(link->handle, AccessConfigurationRegister, err); + if ((err = pcmcia_access_configuration_register(link, ®))) { + cs_error(link, AccessConfigurationRegister, err); goto config_error; } @@ -978,15 +974,15 @@ xirc2ps_config(dev_link_t * link) req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Base = req.Size = 0; req.AccessSpeed = 0; - if ((err = pcmcia_request_window(&link->handle, &req, &link->win))) { - cs_error(link->handle, RequestWindow, err); + if ((err = pcmcia_request_window(&link, &req, &link->win))) { + cs_error(link, RequestWindow, err); goto config_error; } local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800; mem.CardOffset = 0x0; mem.Page = 0; if ((err = pcmcia_map_mem_page(link->win, &mem))) { - cs_error(link->handle, MapMemPage, err); + cs_error(link, MapMemPage, err); goto config_error; } @@ -1048,7 +1044,7 @@ xirc2ps_config(dev_link_t * link) link->dev_node = &local->node; link->state &= ~DEV_CONFIG_PENDING; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); if ((err=register_netdev(dev))) { printk(KNOT_XIRC "register_netdev() failed\n"); @@ -1084,7 +1080,7 @@ xirc2ps_config(dev_link_t * link) * still open, this will be postponed until it is closed. */ static void -xirc2ps_release(dev_link_t *link) +xirc2ps_release(struct pcmcia_device *link) { DEBUG(0, "release(0x%p)\n", link); @@ -1094,15 +1090,14 @@ xirc2ps_release(dev_link_t *link) if (local->dingo) iounmap(local->dingo_ccr - 0x0800); } - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } /* xirc2ps_release */ /*====================================================================*/ -static int xirc2ps_suspend(struct pcmcia_device *p_dev) +static int xirc2ps_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) { @@ -1113,9 +1108,8 @@ static int xirc2ps_suspend(struct pcmcia_device *p_dev) return 0; } -static int xirc2ps_resume(struct pcmcia_device *p_dev) +static int xirc2ps_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) { @@ -1534,7 +1528,7 @@ static int do_open(struct net_device *dev) { local_info_t *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; DEBUG(0, "do_open(%p)\n", dev); @@ -1864,7 +1858,7 @@ do_stop(struct net_device *dev) { kio_addr_t ioaddr = dev->base_addr; local_info_t *lp = netdev_priv(dev); - dev_link_t *link = lp->p_dev; + struct pcmcia_device *link = lp->p_dev; DEBUG(0, "do_stop(%p)\n", dev); diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 836c71ff77..76970197f9 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -80,8 +80,8 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); event handler. */ -static void airo_config(dev_link_t *link); -static void airo_release(dev_link_t *link); +static void airo_config(struct pcmcia_device *link); +static void airo_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -101,10 +101,10 @@ static void airo_detach(struct pcmcia_device *p_dev); /* A linked list of "instances" of the aironet device. Each actual PCMCIA card corresponds to one device instance, and is described - by one dev_link_t structure (defined in ds.h). + by one struct pcmcia_device structure (defined in ds.h). You may not want to use a linked list for this -- for example, the - memory card driver uses an array of dev_link_t pointers, where minor + memory card driver uses an array of struct pcmcia_device pointers, where minor device numbers are used to derive the corresponding array index. */ @@ -114,7 +114,7 @@ static void airo_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally shouldn't be allocated dynamically. @@ -185,10 +185,8 @@ static int airo_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void airo_detach(struct pcmcia_device *p_dev) +static void airo_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "airo_detach(0x%p)\n", link); if (link->state & DEV_CONFIG) @@ -213,9 +211,8 @@ static void airo_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void airo_config(dev_link_t *link) +static void airo_config(struct pcmcia_device *link) { - client_handle_t handle; tuple_t tuple; cisparse_t parse; local_info_t *dev; @@ -223,8 +220,7 @@ static void airo_config(dev_link_t *link) u_char buf[64]; win_req_t req; memreq_t map; - - handle = link->handle; + dev = link->priv; DEBUG(0, "airo_config(0x%p)\n", link); @@ -238,9 +234,9 @@ static void airo_config(dev_link_t *link) tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -260,12 +256,12 @@ static void airo_config(dev_link_t *link) will only use the CIS to fill in implementation-defined details. */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { cistpl_cftable_entry_t dflt = { 0 }; cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; @@ -310,12 +306,12 @@ static void airo_config(dev_link_t *link) } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; /* Now set up a common memory window, if needed. There is room - in the dev_link_t structure for one memory window handle, + in the struct pcmcia_device structure for one memory window handle, but if the base addresses need to be saved, or if multiple windows are needed, the info should go in the private data structure for this device. @@ -331,7 +327,7 @@ static void airo_config(dev_link_t *link) req.Base = mem->win[0].host_addr; req.Size = mem->win[0].len; req.AccessSpeed = 0; - if (pcmcia_request_window(&link->handle, &req, &link->win) != 0) + if (pcmcia_request_window(&link, &req, &link->win) != 0) goto next_entry; map.Page = 0; map.CardOffset = mem->win[0].card_addr; if (pcmcia_map_mem_page(link->win, &map) != 0) @@ -341,7 +337,7 @@ static void airo_config(dev_link_t *link) break; next_entry: - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } /* @@ -350,17 +346,17 @@ static void airo_config(dev_link_t *link) irq structure is initialized. */ if (link->conf.Attributes & CONF_ENABLE_IRQ) - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping, and putting the card and host interface into "Memory and IO" mode. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); ((local_info_t*)link->priv)->eth_dev = init_airo_card( link->irq.AssignedIRQ, - link->io.BasePort1, 1, &handle_to_dev(handle) ); + link->io.BasePort1, 1, &handle_to_dev(link) ); if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed; /* @@ -393,7 +389,7 @@ static void airo_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); airo_release(link); } /* airo_config */ @@ -406,15 +402,14 @@ static void airo_config(dev_link_t *link) ======================================================================*/ -static void airo_release(dev_link_t *link) +static void airo_release(struct pcmcia_device *link) { DEBUG(0, "airo_release(0x%p)\n", link); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int airo_suspend(struct pcmcia_device *p_dev) +static int airo_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *local = link->priv; if (link->state & DEV_CONFIG) @@ -423,9 +418,8 @@ static int airo_suspend(struct pcmcia_device *p_dev) return 0; } -static int airo_resume(struct pcmcia_device *p_dev) +static int airo_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); local_info_t *local = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) { diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 522bbed47a..843dd1a036 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -91,8 +91,8 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards"); event handler. */ -static void atmel_config(dev_link_t *link); -static void atmel_release(dev_link_t *link); +static void atmel_config(struct pcmcia_device *link); +static void atmel_release(struct pcmcia_device *link); /* The attach() and detach() entry points are used to create and destroy @@ -112,10 +112,10 @@ static void atmel_detach(struct pcmcia_device *p_dev); /* A linked list of "instances" of the atmelnet device. Each actual PCMCIA card corresponds to one device instance, and is described - by one dev_link_t structure (defined in ds.h). + by one struct pcmcia_device structure (defined in ds.h). You may not want to use a linked list for this -- for example, the - memory card driver uses an array of dev_link_t pointers, where minor + memory card driver uses an array of struct pcmcia_device pointers, where minor device numbers are used to derive the corresponding array index. */ @@ -125,7 +125,7 @@ static void atmel_detach(struct pcmcia_device *p_dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally shouldn't be allocated dynamically. @@ -196,10 +196,8 @@ static int atmel_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void atmel_detach(struct pcmcia_device *p_dev) +static void atmel_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "atmel_detach(0x%p)\n", link); if (link->state & DEV_CONFIG) @@ -223,7 +221,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) about the current existance of the card */ static int card_present(void *arg) { - dev_link_t *link = (dev_link_t *)arg; + struct pcmcia_device *link = (struct pcmcia_device *)arg; if (link->state & DEV_SUSPEND) return 0; else if (link->state & DEV_PRESENT) @@ -232,9 +230,8 @@ static int card_present(void *arg) return 0; } -static void atmel_config(dev_link_t *link) +static void atmel_config(struct pcmcia_device *link) { - client_handle_t handle; tuple_t tuple; cisparse_t parse; local_info_t *dev; @@ -242,9 +239,8 @@ static void atmel_config(dev_link_t *link) u_char buf[64]; struct pcmcia_device_id *did; - handle = link->handle; dev = link->priv; - did = handle_to_dev(handle).driver_data; + did = handle_to_dev(link).driver_data; DEBUG(0, "atmel_config(0x%p)\n", link); @@ -258,9 +254,9 @@ static void atmel_config(dev_link_t *link) registers. */ tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -280,12 +276,12 @@ static void atmel_config(dev_link_t *link) will only use the CIS to fill in implementation-defined details. */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { cistpl_cftable_entry_t dflt = { 0 }; cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; @@ -330,14 +326,14 @@ static void atmel_config(dev_link_t *link) } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; /* If we got this far, we're cool! */ break; next_entry: - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } /* @@ -346,14 +342,14 @@ static void atmel_config(dev_link_t *link) irq structure is initialized. */ if (link->conf.Attributes & CONF_ENABLE_IRQ) - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping, and putting the card and host interface into "Memory and IO" mode. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); if (link->irq.AssignedIRQ == 0) { printk(KERN_ALERT @@ -365,7 +361,7 @@ static void atmel_config(dev_link_t *link) init_atmel_card(link->irq.AssignedIRQ, link->io.BasePort1, did ? did->driver_info : ATMEL_FW_TYPE_NONE, - &handle_to_dev(handle), + &handle_to_dev(link), card_present, link); if (!((local_info_t*)link->priv)->eth_dev) @@ -384,7 +380,7 @@ static void atmel_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); atmel_release(link); } @@ -396,7 +392,7 @@ static void atmel_config(dev_link_t *link) ======================================================================*/ -static void atmel_release(dev_link_t *link) +static void atmel_release(struct pcmcia_device *link) { struct net_device *dev = ((local_info_t*)link->priv)->eth_dev; @@ -406,12 +402,11 @@ static void atmel_release(dev_link_t *link) stop_atmel_card(dev); ((local_info_t*)link->priv)->eth_dev = NULL; - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int atmel_suspend(struct pcmcia_device *dev) +static int atmel_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); local_info_t *local = link->priv; if (link->state & DEV_CONFIG) @@ -420,9 +415,8 @@ static int atmel_suspend(struct pcmcia_device *dev) return 0; } -static int atmel_resume(struct pcmcia_device *dev) +static int atmel_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); local_info_t *local = link->priv; if (link->state & DEV_CONFIG) { diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index e3095a8874..89b178106e 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -42,7 +42,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry"); /* struct local_info::hw_priv */ struct hostap_cs_priv { dev_node_t node; - dev_link_t *link; + struct pcmcia_device *link; int sandisk_connectplus; }; @@ -204,7 +204,7 @@ static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len) static void prism2_detach(struct pcmcia_device *p_dev); static void prism2_release(u_long arg); -static int prism2_config(dev_link_t *link); +static int prism2_config(struct pcmcia_device *link); static int prism2_pccard_card_present(local_info_t *local) @@ -237,7 +237,7 @@ static void sandisk_set_iobase(local_info_t *local) reg.Action = CS_WRITE; reg.Offset = 0x10; /* 0x3f0 IO base 1 */ reg.Value = hw_priv->link->io.BasePort1 & 0x00ff; - res = pcmcia_access_configuration_register(hw_priv->link->handle, + res = pcmcia_access_configuration_register(hw_priv->link, ®); if (res != CS_SUCCESS) { printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -" @@ -249,7 +249,7 @@ static void sandisk_set_iobase(local_info_t *local) reg.Action = CS_WRITE; reg.Offset = 0x12; /* 0x3f2 IO base 2 */ reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8; - res = pcmcia_access_configuration_register(hw_priv->link->handle, + res = pcmcia_access_configuration_register(hw_priv->link, ®); if (res != CS_SUCCESS) { printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -" @@ -301,9 +301,9 @@ static int sandisk_enable_wireless(struct net_device *dev) tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) || - pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) || - pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) || + if (pcmcia_get_first_tuple(hw_priv->link, &tuple) || + pcmcia_get_tuple_data(hw_priv->link, &tuple) || + pcmcia_parse_tuple(hw_priv->link, &tuple, parse) || parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) { /* No SanDisk manfid found */ ret = -ENODEV; @@ -311,9 +311,9 @@ static int sandisk_enable_wireless(struct net_device *dev) } tuple.DesiredTuple = CISTPL_LONGLINK_MFC; - if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) || - pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) || - pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) || + if (pcmcia_get_first_tuple(hw_priv->link, &tuple) || + pcmcia_get_tuple_data(hw_priv->link, &tuple) || + pcmcia_parse_tuple(hw_priv->link, &tuple, parse) || parse->longlink_mfc.nfn < 2) { /* No multi-function links found */ ret = -ENODEV; @@ -328,7 +328,7 @@ static int sandisk_enable_wireless(struct net_device *dev) reg.Action = CS_WRITE; reg.Offset = CISREG_COR; reg.Value = COR_SOFT_RESET; - res = pcmcia_access_configuration_register(hw_priv->link->handle, + res = pcmcia_access_configuration_register(hw_priv->link, ®); if (res != CS_SUCCESS) { printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", @@ -345,7 +345,7 @@ static int sandisk_enable_wireless(struct net_device *dev) * will be enabled during the first cor_sreset call. */ reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA; - res = pcmcia_access_configuration_register(hw_priv->link->handle, + res = pcmcia_access_configuration_register(hw_priv->link, ®); if (res != CS_SUCCESS) { printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", @@ -380,7 +380,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local) reg.Action = CS_READ; reg.Offset = CISREG_COR; reg.Value = 0; - res = pcmcia_access_configuration_register(hw_priv->link->handle, + res = pcmcia_access_configuration_register(hw_priv->link, ®); if (res != CS_SUCCESS) { printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n", @@ -392,7 +392,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local) reg.Action = CS_WRITE; reg.Value |= COR_SOFT_RESET; - res = pcmcia_access_configuration_register(hw_priv->link->handle, + res = pcmcia_access_configuration_register(hw_priv->link, ®); if (res != CS_SUCCESS) { printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n", @@ -405,7 +405,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local) reg.Value &= ~COR_SOFT_RESET; if (hw_priv->sandisk_connectplus) reg.Value |= COR_IREQ_ENA; - res = pcmcia_access_configuration_register(hw_priv->link->handle, + res = pcmcia_access_configuration_register(hw_priv->link, ®); if (res != CS_SUCCESS) { printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n", @@ -439,7 +439,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) reg.Action = CS_READ; reg.Offset = CISREG_COR; reg.Value = 0; - res = pcmcia_access_configuration_register(hw_priv->link->handle, + res = pcmcia_access_configuration_register(hw_priv->link, ®); if (res != CS_SUCCESS) { printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 " @@ -452,7 +452,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) reg.Action = CS_WRITE; reg.Value |= COR_SOFT_RESET; - res = pcmcia_access_configuration_register(hw_priv->link->handle, + res = pcmcia_access_configuration_register(hw_priv->link, ®); if (res != CS_SUCCESS) { printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 " @@ -466,7 +466,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) reg.Action = CS_WRITE; reg.Value = hcr; reg.Offset = CISREG_CCSR; - res = pcmcia_access_configuration_register(hw_priv->link->handle, + res = pcmcia_access_configuration_register(hw_priv->link, ®); if (res != CS_SUCCESS) { printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 " @@ -478,7 +478,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) reg.Action = CS_WRITE; reg.Offset = CISREG_COR; reg.Value = old_cor & ~COR_SOFT_RESET; - res = pcmcia_access_configuration_register(hw_priv->link->handle, + res = pcmcia_access_configuration_register(hw_priv->link, ®); if (res != CS_SUCCESS) { printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 " @@ -514,10 +514,8 @@ static int prism2_attach(struct pcmcia_device *p_dev) } -static void prism2_detach(struct pcmcia_device *p_dev) +static void prism2_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - PDEBUG(DEBUG_FLOW, "prism2_detach\n"); if (link->state & DEV_CONFIG) { @@ -545,7 +543,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) do { int ret = (retf); \ if (ret != 0) { \ PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \ - cs_error(link->handle, fn, ret); \ + cs_error(link, fn, ret); \ goto next_entry; \ } \ } while (0) @@ -553,7 +551,7 @@ if (ret != 0) { \ /* run after a CARD_INSERTION event is received to configure the PCMCIA * socket and make the device available to the system */ -static int prism2_config(dev_link_t *link) +static int prism2_config(struct pcmcia_device *link) { struct net_device *dev; struct hostap_interface *iface; @@ -582,24 +580,24 @@ static int prism2_config(dev_link_t *link) tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link->handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link->handle, &tuple, parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse)); link->conf.ConfigBase = parse->config.base; link->conf.Present = parse->config.rmask[0]; CS_CHECK(GetConfigurationInfo, - pcmcia_get_configuration_info(link->handle, &conf)); + pcmcia_get_configuration_info(link, &conf)); /* Look for an appropriate configuration table entry in the CIS */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); for (;;) { cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); CFG_CHECK2(GetTupleData, - pcmcia_get_tuple_data(link->handle, &tuple)); + pcmcia_get_tuple_data(link, &tuple)); CFG_CHECK2(ParseTuple, - pcmcia_parse_tuple(link->handle, &tuple, parse)); + pcmcia_parse_tuple(link, &tuple, parse)); if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; @@ -679,19 +677,19 @@ static int prism2_config(dev_link_t *link) /* This reserves IO space but doesn't actually enable it */ CFG_CHECK2(RequestIO, - pcmcia_request_io(link->handle, &link->io)); + pcmcia_request_io(link, &link->io)); /* This configuration table entry is OK */ break; next_entry: CS_CHECK(GetNextTuple, - pcmcia_get_next_tuple(link->handle, &tuple)); + pcmcia_get_next_tuple(link, &tuple)); } /* Need to allocate net_device before requesting IRQ handler */ dev = prism2_init_local_data(&prism2_pccard_funcs, 0, - &handle_to_dev(link->handle)); + &handle_to_dev(link)); if (dev == NULL) goto failed; link->priv = dev; @@ -714,7 +712,7 @@ static int prism2_config(dev_link_t *link) link->irq.Handler = prism2_interrupt; link->irq.Instance = dev; CS_CHECK(RequestIRQ, - pcmcia_request_irq(link->handle, &link->irq)); + pcmcia_request_irq(link, &link->irq)); } /* @@ -723,7 +721,7 @@ static int prism2_config(dev_link_t *link) * card and host interface into "Memory and IO" mode. */ CS_CHECK(RequestConfiguration, - pcmcia_request_configuration(link->handle, &link->conf)); + pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; @@ -761,7 +759,7 @@ static int prism2_config(dev_link_t *link) return ret; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: kfree(parse); @@ -773,7 +771,7 @@ static int prism2_config(dev_link_t *link) static void prism2_release(u_long arg) { - dev_link_t *link = (dev_link_t *)arg; + struct pcmcia_device *link = (struct pcmcia_device *)arg; PDEBUG(DEBUG_FLOW, "prism2_release\n"); @@ -787,13 +785,12 @@ static void prism2_release(u_long arg) iface->local->shutdown = 1; } - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); PDEBUG(DEBUG_FLOW, "release - done\n"); } -static int hostap_cs_suspend(struct pcmcia_device *p_dev) +static int hostap_cs_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = (struct net_device *) link->priv; int dev_open = 0; @@ -813,9 +810,8 @@ static int hostap_cs_suspend(struct pcmcia_device *p_dev) return 0; } -static int hostap_cs_resume(struct pcmcia_device *p_dev) +static int hostap_cs_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = (struct net_device *) link->priv; int dev_open = 0; diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 68dfe68ffe..2a688865f7 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -190,8 +190,8 @@ module_param(mem_speed, int, 0); /*====================================================================*/ /* PCMCIA (Card Services) related functions */ -static void netwave_release(dev_link_t *link); /* Card removal */ -static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card +static void netwave_release(struct pcmcia_device *link); /* Card removal */ +static void netwave_pcmcia_config(struct pcmcia_device *arg); /* Runs after card insertion */ static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */ @@ -221,10 +221,10 @@ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); /* - A dev_link_t structure has fields for most things that are needed + A struct pcmcia_device structure has fields for most things that are needed to keep track of a socket, but there will usually be some device specific information that also needs to be kept track of. The - 'priv' pointer in a dev_link_t structure can be used to point to + 'priv' pointer in a struct pcmcia_device structure can be used to point to a device-specific private data structure, like this. A driver needs to provide a dev_node_t structure for each device @@ -232,7 +232,7 @@ static void set_multicast_list(struct net_device *dev); example, ethernet cards, modems). In other cases, there may be many actual or logical devices (SCSI adapters, memory cards with multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a dev_link_t + in a linked list starting at the 'dev' field of a struct pcmcia_device structure. We allocate them in the card's private data structure, because they generally can't be allocated dynamically. */ @@ -376,20 +376,19 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev) * configure the card at this point -- we wait until we receive a * card insertion event. */ -static int netwave_attach(struct pcmcia_device *p_dev) +static int netwave_attach(struct pcmcia_device *link) { struct net_device *dev; netwave_private *priv; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "netwave_attach()\n"); - /* Initialize the dev_link_t structure */ + /* Initialize the struct pcmcia_device structure */ dev = alloc_etherdev(sizeof(netwave_private)); if (!dev) return -ENOMEM; priv = netdev_priv(dev); - priv->p_dev = p_dev; + priv->p_dev = link; link->priv = dev; /* The io structure describes IO port mapping */ @@ -443,9 +442,8 @@ static int netwave_attach(struct pcmcia_device *p_dev) * structures are freed. Otherwise, the structures will be freed * when the device is released. */ -static void netwave_detach(struct pcmcia_device *p_dev) +static void netwave_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; DEBUG(0, "netwave_detach(0x%p)\n", link); @@ -739,8 +737,7 @@ static const struct iw_handler_def netwave_handler_def = #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void netwave_pcmcia_config(dev_link_t *link) { - client_handle_t handle = link->handle; +static void netwave_pcmcia_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; netwave_private *priv = netdev_priv(dev); tuple_t tuple; @@ -762,9 +759,9 @@ static void netwave_pcmcia_config(dev_link_t *link) { tuple.TupleDataMax = 64; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -778,11 +775,11 @@ static void netwave_pcmcia_config(dev_link_t *link) { */ for (i = j = 0x0; j < 0x400; j += 0x20) { link->io.BasePort1 = j ^ 0x300; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); goto failed; } @@ -790,16 +787,16 @@ static void netwave_pcmcia_config(dev_link_t *link) { * Now allocate an interrupt line. Note that this does not * actually assign a handler to the interrupt. */ - CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); /* * This actually configures the PCMCIA socket -- setting up * the I/O windows and the interrupt mapping. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); /* - * Allocate a 32K memory window. Note that the dev_link_t + * Allocate a 32K memory window. Note that the struct pcmcia_device * structure provides space for one window handle -- if your * device needs several windows, you'll need to keep track of * the handles in your private data structure, dev->priv. @@ -809,7 +806,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE; req.Base = 0; req.Size = 0x8000; req.AccessSpeed = mem_speed; - CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); + CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); mem.CardOffset = 0x20000; mem.Page = 0; CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); @@ -819,7 +816,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n"); @@ -851,7 +848,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: netwave_release(link); } /* netwave_pcmcia_config */ @@ -863,21 +860,20 @@ failed: * device, and release the PCMCIA configuration. If the device is * still open, this will be postponed until it is closed. */ -static void netwave_release(dev_link_t *link) +static void netwave_release(struct pcmcia_device *link) { struct net_device *dev = link->priv; netwave_private *priv = netdev_priv(dev); DEBUG(0, "netwave_release(0x%p)\n", link); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); if (link->win) iounmap(priv->ramBase); } -static int netwave_suspend(struct pcmcia_device *p_dev) +static int netwave_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) @@ -886,9 +882,8 @@ static int netwave_suspend(struct pcmcia_device *p_dev) return 0; } -static int netwave_resume(struct pcmcia_device *p_dev) +static int netwave_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) { @@ -1100,7 +1095,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs u_char __iomem *ramBase; struct net_device *dev = (struct net_device *)dev_id; struct netwave_private *priv = netdev_priv(dev); - dev_link_t *link = priv->p_dev; + struct pcmcia_device *link = priv->p_dev; int i; if (!netif_device_present(dev)) @@ -1354,7 +1349,7 @@ static int netwave_rx(struct net_device *dev) static int netwave_open(struct net_device *dev) { netwave_private *priv = netdev_priv(dev); - dev_link_t *link = priv->p_dev; + struct pcmcia_device *link = priv->p_dev; DEBUG(1, "netwave_open: starting.\n"); @@ -1371,7 +1366,7 @@ static int netwave_open(struct net_device *dev) { static int netwave_close(struct net_device *dev) { netwave_private *priv = netdev_priv(dev); - dev_link_t *link = priv->p_dev; + struct pcmcia_device *link = priv->p_dev; DEBUG(1, "netwave_close: finishing.\n"); diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index f10d97bc45..405b7baa8b 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -63,8 +63,8 @@ struct orinoco_pccard { /* Function prototypes */ /********************************************************************/ -static void orinoco_cs_config(dev_link_t *link); -static void orinoco_cs_release(dev_link_t *link); +static void orinoco_cs_config(struct pcmcia_device *link); +static void orinoco_cs_release(struct pcmcia_device *link); static void orinoco_cs_detach(struct pcmcia_device *p_dev); /********************************************************************/ @@ -75,13 +75,13 @@ static int orinoco_cs_hard_reset(struct orinoco_private *priv) { struct orinoco_pccard *card = priv->card; - dev_link_t *link = card->p_dev; + struct pcmcia_device *link = card->p_dev; int err; /* We need atomic ops here, because we're not holding the lock */ set_bit(0, &card->hard_reset_in_progress); - err = pcmcia_reset_card(link->handle, NULL); + err = pcmcia_reset_card(link, NULL); if (err) return err; @@ -104,12 +104,11 @@ orinoco_cs_hard_reset(struct orinoco_private *priv) * configure the card at this point -- we wait until we receive a card * insertion event. */ static int -orinoco_cs_attach(struct pcmcia_device *p_dev) +orinoco_cs_attach(struct pcmcia_device *link) { struct net_device *dev; struct orinoco_private *priv; struct orinoco_pccard *card; - dev_link_t *link = dev_to_instance(p_dev); dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); if (! dev) @@ -118,7 +117,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev) card = priv->card; /* Link both structures together */ - card->p_dev = p_dev; + card->p_dev = link; link->priv = dev; /* Interrupt setup */ @@ -147,9 +146,8 @@ orinoco_cs_attach(struct pcmcia_device *p_dev) * are freed. Otherwise, the structures will be freed when the device * is released. */ -static void orinoco_cs_detach(struct pcmcia_device *p_dev) +static void orinoco_cs_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if (link->state & DEV_CONFIG) @@ -175,10 +173,9 @@ static void orinoco_cs_detach(struct pcmcia_device *p_dev) } while (0) static void -orinoco_cs_config(dev_link_t *link) +orinoco_cs_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; - client_handle_t handle = link->handle; struct orinoco_private *priv = netdev_priv(dev); struct orinoco_pccard *card = priv->card; hermes_t *hw = &priv->hw; @@ -190,7 +187,7 @@ orinoco_cs_config(dev_link_t *link) cisparse_t parse; void __iomem *mem; - CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info)); + CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info)); /* * This reads the card's CONFIG tuple to find its @@ -201,9 +198,9 @@ orinoco_cs_config(dev_link_t *link) tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -212,7 +209,7 @@ orinoco_cs_config(dev_link_t *link) /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, - pcmcia_get_configuration_info(link->handle, &conf)); + pcmcia_get_configuration_info(link, &conf)); /* * In this loop, we scan the CIS for configuration table @@ -229,13 +226,13 @@ orinoco_cs_config(dev_link_t *link) * implementation-defined details. */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); cistpl_cftable_entry_t dflt = { .index = 0 }; - if ( (pcmcia_get_tuple_data(handle, &tuple) != 0) - || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0)) + if ( (pcmcia_get_tuple_data(link, &tuple) != 0) + || (pcmcia_parse_tuple(link, &tuple, &parse) != 0)) goto next_entry; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) @@ -300,7 +297,7 @@ orinoco_cs_config(dev_link_t *link) } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; } @@ -310,8 +307,8 @@ orinoco_cs_config(dev_link_t *link) break; next_entry: - pcmcia_disable_device(handle); - last_ret = pcmcia_get_next_tuple(handle, &tuple); + pcmcia_disable_device(link); + last_ret = pcmcia_get_next_tuple(link, &tuple); if (last_ret == CS_NO_MORE_ITEMS) { printk(KERN_ERR PFX "GetNextTuple(): No matching " "CIS configuration. Maybe you need the " @@ -325,7 +322,7 @@ orinoco_cs_config(dev_link_t *link) * a handler to the interrupt, unless the 'Handler' member of * the irq structure is initialized. */ - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); /* We initialize the hermes structure before completing PCMCIA * configuration just in case the interrupt handler gets @@ -342,7 +339,7 @@ orinoco_cs_config(dev_link_t *link) * card and host interface into "Memory and IO" mode. */ CS_CHECK(RequestConfiguration, - pcmcia_request_configuration(link->handle, &link->conf)); + pcmcia_request_configuration(link, &link->conf)); /* Ok, we have the configuration, prepare to register the netdev */ dev->base_addr = link->io.BasePort1; @@ -350,7 +347,7 @@ orinoco_cs_config(dev_link_t *link) SET_MODULE_OWNER(dev); card->node.major = card->node.minor = 0; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); /* Tell the stack we exist */ if (register_netdev(dev) != 0) { printk(KERN_ERR PFX "register_netdev() failed\n"); @@ -383,7 +380,7 @@ orinoco_cs_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: orinoco_cs_release(link); @@ -395,7 +392,7 @@ orinoco_cs_config(dev_link_t *link) * still open, this will be postponed until it is closed. */ static void -orinoco_cs_release(dev_link_t *link) +orinoco_cs_release(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); @@ -407,14 +404,13 @@ orinoco_cs_release(dev_link_t *link) priv->hw_unavailable++; spin_unlock_irqrestore(&priv->lock, flags); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); if (priv->hw.iobase) ioport_unmap(priv->hw.iobase); } /* orinoco_cs_release */ -static int orinoco_cs_suspend(struct pcmcia_device *p_dev) +static int orinoco_cs_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); struct orinoco_pccard *card = priv->card; @@ -443,9 +439,8 @@ static int orinoco_cs_suspend(struct pcmcia_device *p_dev) return 0; } -static int orinoco_cs_resume(struct pcmcia_device *p_dev) +static int orinoco_cs_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); struct orinoco_pccard *card = priv->card; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 60297460de..415ae8be1e 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -90,8 +90,8 @@ module_param(pc_debug, int, 0); #define DEBUG(n, args...) #endif /** Prototypes based on PCMCIA skeleton driver *******************************/ -static void ray_config(dev_link_t *link); -static void ray_release(dev_link_t *link); +static void ray_config(struct pcmcia_device *link); +static void ray_release(struct pcmcia_device *link); static void ray_detach(struct pcmcia_device *p_dev); /***** Prototypes indicated by device structure ******************************/ @@ -190,10 +190,10 @@ static int bc; static char *phy_addr = NULL; -/* A dev_link_t structure has fields for most things that are needed +/* A struct pcmcia_device structure has fields for most things that are needed to keep track of a socket, but there will usually be some device specific information that also needs to be kept track of. The - 'priv' pointer in a dev_link_t structure can be used to point to + 'priv' pointer in a struct pcmcia_device structure can be used to point to a device-specific private data structure, like this. */ static unsigned int ray_mem_speed = 500; @@ -381,9 +381,8 @@ fail_alloc_dev: structures are freed. Otherwise, the structures will be freed when the device is released. =============================================================================*/ -static void ray_detach(struct pcmcia_device *p_dev) +static void ray_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev; ray_dev_t *local; @@ -413,9 +412,8 @@ static void ray_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) #define MAX_TUPLE_SIZE 128 -static void ray_config(dev_link_t *link) +static void ray_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; tuple_t tuple; cisparse_t parse; int last_fn = 0, last_ret = 0; @@ -430,23 +428,23 @@ static void ray_config(dev_link_t *link) /* This reads the card's CONFIG tuple to find its configuration regs */ tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); tuple.TupleData = buf; tuple.TupleDataMax = MAX_TUPLE_SIZE; tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* Determine card type and firmware version */ buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0; tuple.DesiredTuple = CISTPL_VERS_1; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); tuple.TupleData = buf; tuple.TupleDataMax = MAX_TUPLE_SIZE; tuple.TupleOffset = 2; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); for (i=0; ihandle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); dev->irq = link->irq.AssignedIRQ; /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); /*** Set up 32k window for shared memory (transmit and control) ************/ req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; req.Base = 0; req.Size = 0x8000; req.AccessSpeed = ray_mem_speed; - CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); + CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); mem.CardOffset = 0x0000; mem.Page = 0; CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); local->sram = ioremap(req.Base,req.Size); @@ -481,7 +479,7 @@ static void ray_config(dev_link_t *link) req.Base = 0; req.Size = 0x4000; req.AccessSpeed = ray_mem_speed; - CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle)); + CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->rmem_handle)); mem.CardOffset = 0x8000; mem.Page = 0; CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem)); local->rmem = ioremap(req.Base,req.Size); @@ -491,7 +489,7 @@ static void ray_config(dev_link_t *link) req.Base = 0; req.Size = 0x1000; req.AccessSpeed = ray_mem_speed; - CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle)); + CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->amem_handle)); mem.CardOffset = 0x0000; mem.Page = 0; CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem)); local->amem = ioremap(req.Base,req.Size); @@ -504,7 +502,7 @@ static void ray_config(dev_link_t *link) return; } - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); i = register_netdev(dev); if (i != 0) { printk("ray_config register_netdev() failed\n"); @@ -524,7 +522,7 @@ static void ray_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); ray_release(link); } /* ray_config */ @@ -553,7 +551,7 @@ static int ray_init(struct net_device *dev) UCHAR *p; struct ccs __iomem *pccs; ray_dev_t *local = (ray_dev_t *)dev->priv; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; DEBUG(1, "ray_init(0x%p)\n", dev); if (!(link->state & DEV_PRESENT)) { DEBUG(0,"ray_init - device not present\n"); @@ -615,7 +613,7 @@ static int dl_startup_params(struct net_device *dev) int ccsindex; ray_dev_t *local = (ray_dev_t *)dev->priv; struct ccs __iomem *pccs; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; DEBUG(1,"dl_startup_params entered\n"); if (!(link->state & DEV_PRESENT)) { @@ -722,7 +720,7 @@ static void verify_dl_startup(u_long data) ray_dev_t *local = (ray_dev_t *)data; struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs; UCHAR status; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs verify_dl_startup - device not present\n"); @@ -762,7 +760,7 @@ static void start_net(u_long data) ray_dev_t *local = (ray_dev_t *)data; struct ccs __iomem *pccs; int ccsindex; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs start_net - device not present\n"); return; @@ -789,7 +787,7 @@ static void join_net(u_long data) struct ccs __iomem *pccs; int ccsindex; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs join_net - device not present\n"); @@ -815,7 +813,7 @@ static void join_net(u_long data) device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed. =============================================================================*/ -static void ray_release(dev_link_t *link) +static void ray_release(struct pcmcia_device *link) { struct net_device *dev = link->priv; ray_dev_t *local = dev->priv; @@ -833,14 +831,13 @@ static void ray_release(dev_link_t *link) if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i); i = pcmcia_release_window(local->rmem_handle); if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); DEBUG(2,"ray_release ending\n"); } -static int ray_suspend(struct pcmcia_device *p_dev) +static int ray_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) @@ -849,9 +846,8 @@ static int ray_suspend(struct pcmcia_device *p_dev) return 0; } -static int ray_resume(struct pcmcia_device *p_dev) +static int ray_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if ((link->state & DEV_CONFIG) && (link->open)) { @@ -869,7 +865,7 @@ int ray_dev_init(struct net_device *dev) int i; #endif /* RAY_IMMEDIATE_INIT */ ray_dev_t *local = dev->priv; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; DEBUG(1,"ray_dev_init(dev=%p)\n",dev); if (!(link->state & DEV_PRESENT)) { @@ -903,7 +899,7 @@ int ray_dev_init(struct net_device *dev) static int ray_dev_config(struct net_device *dev, struct ifmap *map) { ray_dev_t *local = dev->priv; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; /* Dummy routine to satisfy device structure */ DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map); if (!(link->state & DEV_PRESENT)) { @@ -917,7 +913,7 @@ static int ray_dev_config(struct net_device *dev, struct ifmap *map) static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) { ray_dev_t *local = dev->priv; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; short length = skb->len; if (!(link->state & DEV_PRESENT)) { @@ -1529,7 +1525,7 @@ static int ray_commit(struct net_device *dev, static iw_stats * ray_get_wireless_stats(struct net_device * dev) { ray_dev_t * local = (ray_dev_t *) dev->priv; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; struct status __iomem *p = local->sram + STATUS_BASE; if(local == (ray_dev_t *) NULL) @@ -1617,7 +1613,7 @@ static const struct iw_handler_def ray_handler_def = static int ray_open(struct net_device *dev) { ray_dev_t *local = (ray_dev_t *)dev->priv; - dev_link_t *link; + struct pcmcia_device *link; link = local->finder; DEBUG(1, "ray_open('%s')\n", dev->name); @@ -1651,7 +1647,7 @@ static int ray_open(struct net_device *dev) static int ray_dev_close(struct net_device *dev) { ray_dev_t *local = (ray_dev_t *)dev->priv; - dev_link_t *link; + struct pcmcia_device *link; link = local->finder; DEBUG(1, "ray_dev_close('%s')\n", dev->name); @@ -1677,7 +1673,7 @@ static void ray_reset(struct net_device *dev) { static int interrupt_ecf(ray_dev_t *local, int ccs) { int i = 50; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs interrupt_ecf - device not present\n"); @@ -1704,7 +1700,7 @@ static int get_free_tx_ccs(ray_dev_t *local) { int i; struct ccs __iomem *pccs = ccs_base(local); - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n"); @@ -1735,7 +1731,7 @@ static int get_free_ccs(ray_dev_t *local) { int i; struct ccs __iomem *pccs = ccs_base(local); - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs get_free_ccs - device not present\n"); @@ -1810,7 +1806,7 @@ static int parse_addr(char *in_str, UCHAR *out) static struct net_device_stats *ray_get_stats(struct net_device *dev) { ray_dev_t *local = (ray_dev_t *)dev->priv; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; struct status __iomem *p = local->sram + STATUS_BASE; if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs net_device_stats - device not present\n"); @@ -1840,7 +1836,7 @@ static struct net_device_stats *ray_get_stats(struct net_device *dev) static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len) { ray_dev_t *local = (ray_dev_t *)dev->priv; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; int ccsindex; int i; struct ccs __iomem *pccs; @@ -1877,7 +1873,7 @@ static void ray_update_multi_list(struct net_device *dev, int all) struct ccs __iomem *pccs; int i = 0; ray_dev_t *local = (ray_dev_t *)dev->priv; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; void __iomem *p = local->sram + HOST_TO_ECF_BASE; if (!(link->state & DEV_PRESENT)) { @@ -1957,7 +1953,7 @@ static void set_multicast_list(struct net_device *dev) static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct net_device *dev = (struct net_device *)dev_id; - dev_link_t *link; + struct pcmcia_device *link; ray_dev_t *local; struct ccs __iomem *pccs; struct rcs __iomem *prcs; @@ -1972,7 +1968,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev); local = (ray_dev_t *)dev->priv; - link = (dev_link_t *)local->finder; + link = (struct pcmcia_device *)local->finder; if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) { DEBUG(2,"ray_cs interrupt from device not present or suspended.\n"); return IRQ_NONE; @@ -2492,7 +2488,7 @@ static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs) /*===========================================================================*/ static void authenticate(ray_dev_t *local) { - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; DEBUG(0,"ray_cs Starting authentication.\n"); if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_cs authenticate - device not present\n"); @@ -2558,7 +2554,7 @@ static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, static void associate(ray_dev_t *local) { struct ccs __iomem *pccs; - dev_link_t *link = local->finder; + struct pcmcia_device *link = local->finder; struct net_device *dev = link->priv; int ccsindex; if (!(link->state & DEV_PRESENT)) { @@ -2641,7 +2637,7 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len) * eg ifconfig */ int i; - dev_link_t *link; + struct pcmcia_device *link; struct net_device *dev; ray_dev_t *local; UCHAR *p; diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h index 42660fe64b..bd73ebf033 100644 --- a/drivers/net/wireless/ray_cs.h +++ b/drivers/net/wireless/ray_cs.h @@ -31,7 +31,7 @@ typedef struct ray_dev_t { void __iomem *sram; /* pointer to beginning of shared RAM */ void __iomem *amem; /* pointer to attribute mem window */ void __iomem *rmem; /* pointer to receive buffer window */ - dev_link_t *finder; /* pointer back to dev_link_t for card */ + struct pcmcia_device *finder; /* pointer back to struct pcmcia_device for card */ struct timer_list timer; long tx_ccs_lock; long ccs_lock; diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index be36679c8c..a75ea7e593 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -71,8 +71,8 @@ struct orinoco_pccard { /* Function prototypes */ /********************************************************************/ -static void spectrum_cs_config(dev_link_t *link); -static void spectrum_cs_release(dev_link_t *link); +static void spectrum_cs_config(struct pcmcia_device *link); +static void spectrum_cs_release(struct pcmcia_device *link); /********************************************************************/ /* Firmware downloader */ @@ -238,7 +238,7 @@ spectrum_aux_open(hermes_t *hw) * If IDLE is 1, stop the firmware, so that it can be safely rewritten. */ static int -spectrum_reset(dev_link_t *link, int idle) +spectrum_reset(struct pcmcia_device *link, int idle) { int last_ret, last_fn; conf_reg_t reg; @@ -253,7 +253,7 @@ spectrum_reset(dev_link_t *link, int idle) reg.Action = CS_READ; reg.Offset = CISREG_COR; CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link->handle, ®)); + pcmcia_access_configuration_register(link, ®)); save_cor = reg.Value; /* Soft-Reset card */ @@ -261,14 +261,14 @@ spectrum_reset(dev_link_t *link, int idle) reg.Offset = CISREG_COR; reg.Value = (save_cor | COR_SOFT_RESET); CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link->handle, ®)); + pcmcia_access_configuration_register(link, ®)); udelay(1000); /* Read CCSR */ reg.Action = CS_READ; reg.Offset = CISREG_CCSR; CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link->handle, ®)); + pcmcia_access_configuration_register(link, ®)); /* * Start or stop the firmware. Memory width bit should be @@ -278,7 +278,7 @@ spectrum_reset(dev_link_t *link, int idle) reg.Offset = CISREG_CCSR; reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16); CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link->handle, ®)); + pcmcia_access_configuration_register(link, ®)); udelay(1000); /* Restore original COR configuration index */ @@ -286,12 +286,12 @@ spectrum_reset(dev_link_t *link, int idle) reg.Offset = CISREG_COR; reg.Value = (save_cor & ~COR_SOFT_RESET); CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link->handle, ®)); + pcmcia_access_configuration_register(link, ®)); udelay(1000); return 0; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); return -ENODEV; } @@ -441,7 +441,7 @@ spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block) * care of the PDA - read it and then write it on top of the firmware. */ static int -spectrum_dl_image(hermes_t *hw, dev_link_t *link, +spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, const unsigned char *image) { int ret; @@ -505,14 +505,13 @@ spectrum_dl_image(hermes_t *hw, dev_link_t *link, * reset on the card, to make sure it's in a sane state. */ static int -spectrum_dl_firmware(hermes_t *hw, dev_link_t *link) +spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link) { int ret; - client_handle_t handle = link->handle; const struct firmware *fw_entry; if (request_firmware(&fw_entry, primary_fw_name, - &handle_to_dev(handle)) == 0) { + &handle_to_dev(link)) == 0) { primsym = fw_entry->data; } else { printk(KERN_ERR PFX "Cannot find firmware: %s\n", @@ -521,7 +520,7 @@ spectrum_dl_firmware(hermes_t *hw, dev_link_t *link) } if (request_firmware(&fw_entry, secondary_fw_name, - &handle_to_dev(handle)) == 0) { + &handle_to_dev(link)) == 0) { secsym = fw_entry->data; } else { printk(KERN_ERR PFX "Cannot find firmware: %s\n", @@ -554,7 +553,7 @@ static int spectrum_cs_hard_reset(struct orinoco_private *priv) { struct orinoco_pccard *card = priv->card; - dev_link_t *link = card->p_dev; + struct pcmcia_device *link = card->p_dev; int err; if (!hermes_present(&priv->hw)) { @@ -584,12 +583,11 @@ spectrum_cs_hard_reset(struct orinoco_private *priv) * configure the card at this point -- we wait until we receive a card * insertion event. */ static int -spectrum_cs_attach(struct pcmcia_device *p_dev) +spectrum_cs_attach(struct pcmcia_device *link) { struct net_device *dev; struct orinoco_private *priv; struct orinoco_pccard *card; - dev_link_t *link = dev_to_instance(p_dev); dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); if (! dev) @@ -598,7 +596,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev) card = priv->card; /* Link both structures together */ - card->p_dev = p_dev; + card->p_dev = link; link->priv = dev; /* Interrupt setup */ @@ -627,9 +625,8 @@ spectrum_cs_attach(struct pcmcia_device *p_dev) * are freed. Otherwise, the structures will be freed when the device * is released. */ -static void spectrum_cs_detach(struct pcmcia_device *p_dev) +static void spectrum_cs_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; if (link->state & DEV_CONFIG) @@ -651,10 +648,9 @@ static void spectrum_cs_detach(struct pcmcia_device *p_dev) */ static void -spectrum_cs_config(dev_link_t *link) +spectrum_cs_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; - client_handle_t handle = link->handle; struct orinoco_private *priv = netdev_priv(dev); struct orinoco_pccard *card = priv->card; hermes_t *hw = &priv->hw; @@ -666,7 +662,7 @@ spectrum_cs_config(dev_link_t *link) cisparse_t parse; void __iomem *mem; - CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info)); + CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info)); /* * This reads the card's CONFIG tuple to find its @@ -677,9 +673,9 @@ spectrum_cs_config(dev_link_t *link) tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -688,7 +684,7 @@ spectrum_cs_config(dev_link_t *link) /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, - pcmcia_get_configuration_info(handle, &conf)); + pcmcia_get_configuration_info(link, &conf)); /* * In this loop, we scan the CIS for configuration table @@ -705,13 +701,13 @@ spectrum_cs_config(dev_link_t *link) * implementation-defined details. */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); cistpl_cftable_entry_t dflt = { .index = 0 }; - if ( (pcmcia_get_tuple_data(handle, &tuple) != 0) - || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0)) + if ( (pcmcia_get_tuple_data(link, &tuple) != 0) + || (pcmcia_parse_tuple(link, &tuple, &parse) != 0)) goto next_entry; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) @@ -776,7 +772,7 @@ spectrum_cs_config(dev_link_t *link) } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; } @@ -786,8 +782,8 @@ spectrum_cs_config(dev_link_t *link) break; next_entry: - pcmcia_disable_device(handle); - last_ret = pcmcia_get_next_tuple(handle, &tuple); + pcmcia_disable_device(link); + last_ret = pcmcia_get_next_tuple(link, &tuple); if (last_ret == CS_NO_MORE_ITEMS) { printk(KERN_ERR PFX "GetNextTuple(): No matching " "CIS configuration. Maybe you need the " @@ -801,7 +797,7 @@ spectrum_cs_config(dev_link_t *link) * a handler to the interrupt, unless the 'Handler' member of * the irq structure is initialized. */ - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); /* We initialize the hermes structure before completing PCMCIA * configuration just in case the interrupt handler gets @@ -818,7 +814,7 @@ spectrum_cs_config(dev_link_t *link) * card and host interface into "Memory and IO" mode. */ CS_CHECK(RequestConfiguration, - pcmcia_request_configuration(link->handle, &link->conf)); + pcmcia_request_configuration(link, &link->conf)); /* Ok, we have the configuration, prepare to register the netdev */ dev->base_addr = link->io.BasePort1; @@ -831,7 +827,7 @@ spectrum_cs_config(dev_link_t *link) goto failed; } - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); /* Tell the stack we exist */ if (register_netdev(dev) != 0) { printk(KERN_ERR PFX "register_netdev() failed\n"); @@ -864,7 +860,7 @@ spectrum_cs_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: spectrum_cs_release(link); @@ -876,7 +872,7 @@ spectrum_cs_config(dev_link_t *link) * still open, this will be postponed until it is closed. */ static void -spectrum_cs_release(dev_link_t *link) +spectrum_cs_release(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); @@ -888,16 +884,15 @@ spectrum_cs_release(dev_link_t *link) priv->hw_unavailable++; spin_unlock_irqrestore(&priv->lock, flags); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); if (priv->hw.iobase) ioport_unmap(priv->hw.iobase); } /* spectrum_cs_release */ static int -spectrum_cs_suspend(struct pcmcia_device *p_dev) +spectrum_cs_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); unsigned long flags; @@ -922,9 +917,8 @@ spectrum_cs_suspend(struct pcmcia_device *p_dev) } static int -spectrum_cs_resume(struct pcmcia_device *p_dev) +spectrum_cs_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index baa1011e70..352d4a50b7 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -1005,7 +1005,7 @@ static inline void wv_82593_reconfig(struct net_device * dev) { net_local * lp = netdev_priv(dev); - dev_link_t * link = lp->link; + struct pcmcia_device * link = lp->link; unsigned long flags; /* Arm the flag, will be cleard in wv_82593_config() */ @@ -3744,16 +3744,16 @@ wv_pcmcia_reset(struct net_device * dev) { int i; conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 }; - dev_link_t * link = ((net_local *)netdev_priv(dev))->link; + struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name); #endif - i = pcmcia_access_configuration_register(link->handle, ®); + i = pcmcia_access_configuration_register(link, ®); if(i != CS_SUCCESS) { - cs_error(link->handle, AccessConfigurationRegister, i); + cs_error(link, AccessConfigurationRegister, i); return FALSE; } @@ -3764,19 +3764,19 @@ wv_pcmcia_reset(struct net_device * dev) reg.Action = CS_WRITE; reg.Value = reg.Value | COR_SW_RESET; - i = pcmcia_access_configuration_register(link->handle, ®); + i = pcmcia_access_configuration_register(link, ®); if(i != CS_SUCCESS) { - cs_error(link->handle, AccessConfigurationRegister, i); + cs_error(link, AccessConfigurationRegister, i); return FALSE; } reg.Action = CS_WRITE; reg.Value = COR_LEVEL_IRQ | COR_CONFIG; - i = pcmcia_access_configuration_register(link->handle, ®); + i = pcmcia_access_configuration_register(link, ®); if(i != CS_SUCCESS) { - cs_error(link->handle, AccessConfigurationRegister, i); + cs_error(link, AccessConfigurationRegister, i); return FALSE; } @@ -3940,9 +3940,8 @@ wv_hw_reset(struct net_device * dev) * (called by wavelan_event()) */ static inline int -wv_pcmcia_config(dev_link_t * link) +wv_pcmcia_config(struct pcmcia_device * link) { - client_handle_t handle = link->handle; tuple_t tuple; cisparse_t parse; struct net_device * dev = (struct net_device *) link->priv; @@ -3965,16 +3964,16 @@ wv_pcmcia_config(dev_link_t * link) { tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; - i = pcmcia_get_first_tuple(handle, &tuple); + i = pcmcia_get_first_tuple(link, &tuple); if(i != CS_SUCCESS) break; tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - i = pcmcia_get_tuple_data(handle, &tuple); + i = pcmcia_get_tuple_data(link, &tuple); if(i != CS_SUCCESS) break; - i = pcmcia_parse_tuple(handle, &tuple, &parse); + i = pcmcia_parse_tuple(link, &tuple, &parse); if(i != CS_SUCCESS) break; link->conf.ConfigBase = parse.config.base; @@ -3983,7 +3982,7 @@ wv_pcmcia_config(dev_link_t * link) while(0); if(i != CS_SUCCESS) { - cs_error(link->handle, ParseTuple, i); + cs_error(link, ParseTuple, i); link->state &= ~DEV_CONFIG_PENDING; return FALSE; } @@ -3992,10 +3991,10 @@ wv_pcmcia_config(dev_link_t * link) link->state |= DEV_CONFIG; do { - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if(i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); break; } @@ -4003,10 +4002,10 @@ wv_pcmcia_config(dev_link_t * link) * Now allocate an interrupt line. Note that this does not * actually assign a handler to the interrupt. */ - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if(i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); + cs_error(link, RequestIRQ, i); break; } @@ -4015,15 +4014,15 @@ wv_pcmcia_config(dev_link_t * link) * the I/O windows and the interrupt mapping. */ link->conf.ConfigIndex = 1; - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if(i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); + cs_error(link, RequestConfiguration, i); break; } /* - * Allocate a small memory window. Note that the dev_link_t + * Allocate a small memory window. Note that the struct pcmcia_device * structure provides space for one window handle -- if your * device needs several windows, you'll need to keep track of * the handles in your private data structure, link->priv. @@ -4031,10 +4030,10 @@ wv_pcmcia_config(dev_link_t * link) req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; req.Base = req.Size = 0; req.AccessSpeed = mem_speed; - i = pcmcia_request_window(&link->handle, &req, &link->win); + i = pcmcia_request_window(&link, &req, &link->win); if(i != CS_SUCCESS) { - cs_error(link->handle, RequestWindow, i); + cs_error(link, RequestWindow, i); break; } @@ -4046,7 +4045,7 @@ wv_pcmcia_config(dev_link_t * link) i = pcmcia_map_mem_page(link->win, &mem); if(i != CS_SUCCESS) { - cs_error(link->handle, MapMemPage, i); + cs_error(link, MapMemPage, i); break; } @@ -4060,7 +4059,7 @@ wv_pcmcia_config(dev_link_t * link) lp->mem, dev->irq, (u_int) dev->base_addr); #endif - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); i = register_netdev(dev); if(i != 0) { @@ -4096,7 +4095,7 @@ wv_pcmcia_config(dev_link_t * link) * still open, this will be postponed until it is closed. */ static void -wv_pcmcia_release(dev_link_t *link) +wv_pcmcia_release(struct pcmcia_device *link) { struct net_device * dev = (struct net_device *) link->priv; net_local * lp = netdev_priv(dev); @@ -4106,7 +4105,7 @@ wv_pcmcia_release(dev_link_t *link) #endif iounmap(lp->mem); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); @@ -4473,7 +4472,7 @@ static int wavelan_open(struct net_device * dev) { net_local * lp = netdev_priv(dev); - dev_link_t * link = lp->link; + struct pcmcia_device * link = lp->link; kio_addr_t base = dev->base_addr; #ifdef DEBUG_CALLBACK_TRACE @@ -4527,7 +4526,7 @@ wavelan_open(struct net_device * dev) static int wavelan_close(struct net_device * dev) { - dev_link_t * link = ((net_local *)netdev_priv(dev))->link; + struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link; kio_addr_t base = dev->base_addr; #ifdef DEBUG_CALLBACK_TRACE @@ -4673,10 +4672,8 @@ wavelan_attach(struct pcmcia_device *p_dev) * is released. */ static void -wavelan_detach(struct pcmcia_device *p_dev) +wavelan_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - #ifdef DEBUG_CALLBACK_TRACE printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); #endif @@ -4713,9 +4710,8 @@ wavelan_detach(struct pcmcia_device *p_dev) #endif } -static int wavelan_suspend(struct pcmcia_device *p_dev) +static int wavelan_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device * dev = (struct net_device *) link->priv; /* NB: wavelan_close will be called, but too late, so we are @@ -4736,9 +4732,8 @@ static int wavelan_suspend(struct pcmcia_device *p_dev) return 0; } -static int wavelan_resume(struct pcmcia_device *p_dev) +static int wavelan_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device * dev = (struct net_device *) link->priv; link->state &= ~DEV_SUSPEND; diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h index 451f6271dc..c65fe7a391 100644 --- a/drivers/net/wireless/wavelan_cs.p.h +++ b/drivers/net/wireless/wavelan_cs.p.h @@ -602,7 +602,7 @@ struct net_local dev_node_t node; /* ???? What is this stuff ???? */ struct net_device * dev; /* Reverse link... */ spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ - dev_link_t * link; /* pcmcia structure */ + struct pcmcia_device * link; /* pcmcia structure */ en_stats stats; /* Ethernet interface statistics */ int nresets; /* Number of hw resets */ u_char configured; /* If it is configured */ @@ -733,9 +733,9 @@ static int static inline void wv_hw_reset(struct net_device *); /* Same, + start receiver unit */ static inline int - wv_pcmcia_config(dev_link_t *); /* Configure the pcmcia interface */ + wv_pcmcia_config(struct pcmcia_device *); /* Configure the pcmcia interface */ static void - wv_pcmcia_release(dev_link_t *);/* Remove a device */ + wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */ /* ---------------------- INTERRUPT HANDLING ---------------------- */ static irqreturn_t wavelan_interrupt(int, /* Interrupt handler */ diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 4b054f54e9..752d222600 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -103,8 +103,8 @@ module_param(pc_debug, int, 0); * release a socket, in response to card insertion and ejection events. They * are invoked from the wl24 event handler. */ -static void wl3501_config(dev_link_t *link); -static void wl3501_release(dev_link_t *link); +static void wl3501_config(struct pcmcia_device *link); +static void wl3501_release(struct pcmcia_device *link); /* * The dev_info variable is the "key" that is used to match up this @@ -1270,7 +1270,7 @@ static int wl3501_close(struct net_device *dev) struct wl3501_card *this = dev->priv; int rc = -ENODEV; unsigned long flags; - dev_link_t *link; + struct pcmcia_device *link; link = this->p_dev; spin_lock_irqsave(&this->lock, flags); @@ -1383,7 +1383,7 @@ static int wl3501_open(struct net_device *dev) int rc = -ENODEV; struct wl3501_card *this = dev->priv; unsigned long flags; - dev_link_t *link; + struct pcmcia_device *link; link = this->p_dev; spin_lock_irqsave(&this->lock, flags); @@ -1477,9 +1477,8 @@ static struct ethtool_ops ops = { * Services. If it has been released, all local data structures are freed. * Otherwise, the structures will be freed when the device is released. */ -static void wl3501_detach(struct pcmcia_device *p_dev) +static void wl3501_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; /* If the device is currently configured and active, we won't actually @@ -1925,23 +1924,22 @@ static int wl3501_attach(struct pcmcia_device *p_dev) { struct net_device *dev; struct wl3501_card *this; - dev_link_t *link = dev_to_instance(p_dev); /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = 5; + p_dev->io.NumPorts1 = 16; + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.IOAddrLines = 5; /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.Handler = wl3501_interrupt; + p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; + p_dev->irq.Handler = wl3501_interrupt; /* General socket configuration */ - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.ConfigIndex = 1; - link->conf.Present = PRESENT_OPTION; + p_dev->conf.Attributes = CONF_ENABLE_IRQ; + p_dev->conf.IntType = INT_MEMORY_AND_IO; + p_dev->conf.ConfigIndex = 1; + p_dev->conf.Present = PRESENT_OPTION; dev = alloc_etherdev(sizeof(struct wl3501_card)); if (!dev) @@ -1959,9 +1957,9 @@ static int wl3501_attach(struct pcmcia_device *p_dev) dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def; SET_ETHTOOL_OPS(dev, &ops); netif_stop_queue(dev); - link->priv = link->irq.Instance = dev; + p_dev->priv = p_dev->irq.Instance = dev; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; wl3501_config(p_dev); return 0; @@ -1980,11 +1978,10 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) * received, to configure the PCMCIA socket, and to make the ethernet device * available to the system. */ -static void wl3501_config(dev_link_t *link) +static void wl3501_config(struct pcmcia_device *link) { tuple_t tuple; cisparse_t parse; - client_handle_t handle = link->handle; struct net_device *dev = link->priv; int i = 0, j, last_fn, last_ret; unsigned char bf[64]; @@ -1993,12 +1990,12 @@ static void wl3501_config(dev_link_t *link) /* This reads the card's CONFIG tuple to find its config registers. */ tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); tuple.TupleData = bf; tuple.TupleDataMax = sizeof(bf); tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -2014,28 +2011,28 @@ static void wl3501_config(dev_link_t *link) * 0x200-0x2ff, and so on, because this seems safer */ link->io.BasePort1 = j; link->io.BasePort2 = link->io.BasePort1 + 0x10; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); goto failed; } /* Now allocate an interrupt line. Note that this does not actually * assign a handler to the interrupt. */ - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); /* This actually configures the PCMCIA socket -- setting up the I/O * windows and the interrupt mapping. */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); dev->irq = link->irq.AssignedIRQ; dev->base_addr = link->io.BasePort1; - SET_NETDEV_DEV(dev, &handle_to_dev(handle)); + SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev)) { printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n"); goto failed; @@ -2087,7 +2084,7 @@ static void wl3501_config(dev_link_t *link) netif_start_queue(dev); goto out; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: wl3501_release(link); out: @@ -2102,7 +2099,7 @@ out: * and release the PCMCIA configuration. If the device is still open, this * will be postponed until it is closed. */ -static void wl3501_release(dev_link_t *link) +static void wl3501_release(struct pcmcia_device *link) { struct net_device *dev = link->priv; @@ -2110,12 +2107,11 @@ static void wl3501_release(dev_link_t *link) if (link->dev_node) unregister_netdev(dev); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int wl3501_suspend(struct pcmcia_device *p_dev) +static int wl3501_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND); @@ -2125,9 +2121,8 @@ static int wl3501_suspend(struct pcmcia_device *p_dev) return 0; } -static int wl3501_resume(struct pcmcia_device *p_dev) +static int wl3501_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct net_device *dev = link->priv; wl3501_pwr_mgmt(dev->priv, WL3501_RESUME); diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index ad2738ae22..6dcaf44c12 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -88,8 +88,8 @@ typedef struct parport_info_t { } parport_info_t; static void parport_detach(struct pcmcia_device *p_dev); -static void parport_config(dev_link_t *link); -static void parport_cs_release(dev_link_t *); +static void parport_config(struct pcmcia_device *link); +static void parport_cs_release(struct pcmcia_device *); /*====================================================================== @@ -99,10 +99,9 @@ static void parport_cs_release(dev_link_t *); ======================================================================*/ -static int parport_attach(struct pcmcia_device *p_dev) +static int parport_attach(struct pcmcia_device *link) { parport_info_t *info; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "parport_attach()\n"); @@ -111,7 +110,7 @@ static int parport_attach(struct pcmcia_device *p_dev) if (!info) return -ENOMEM; memset(info, 0, sizeof(*info)); link->priv = info; - info->p_dev = p_dev; + info->p_dev = link; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; @@ -135,10 +134,8 @@ static int parport_attach(struct pcmcia_device *p_dev) ======================================================================*/ -static void parport_detach(struct pcmcia_device *p_dev) +static void parport_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "parport_detach(0x%p)\n", link); if (link->state & DEV_CONFIG) @@ -158,9 +155,8 @@ static void parport_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -void parport_config(dev_link_t *link) +void parport_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; parport_info_t *info = link->priv; tuple_t tuple; u_short buf[128]; @@ -176,9 +172,9 @@ void parport_config(dev_link_t *link) tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -187,10 +183,10 @@ void parport_config(dev_link_t *link) tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { @@ -205,7 +201,7 @@ void parport_config(dev_link_t *link) link->io.BasePort2 = io->win[1].base; link->io.NumPorts2 = io->win[1].len; } - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; /* If we've got this far, we're done */ break; @@ -213,11 +209,11 @@ void parport_config(dev_link_t *link) next_entry: if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } - CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2, link->irq.AssignedIRQ, PARPORT_DMA_NONE, @@ -243,7 +239,7 @@ void parport_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: parport_cs_release(link); link->state &= ~DEV_CONFIG_PENDING; @@ -258,7 +254,7 @@ failed: ======================================================================*/ -void parport_cs_release(dev_link_t *link) +void parport_cs_release(struct pcmcia_device *link) { parport_info_t *info = link->priv; @@ -270,7 +266,7 @@ void parport_cs_release(dev_link_t *link) } info->ndev = 0; - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } /* parport_cs_release */ diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index ad04ad4386..ecc579bbae 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -31,7 +31,7 @@ typedef struct region_t { u_short region_magic; u_short state; dev_info_t dev_info; - client_handle_t mtd; + struct pcmcia_device *mtd; u_int MediaID; region_info_t info; } region_t; diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 4ab956843d..e8fe544f2e 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -391,7 +391,6 @@ static int pcmcia_device_probe(struct device * dev) } p_dev->p_state &= ~CLIENT_UNBOUND; - p_dev->handle = p_dev; ret = p_drv->probe(p_dev); if (ret) diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 0c196fbb31..21c6b10145 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -94,24 +94,23 @@ typedef struct scsi_info_t { struct Scsi_Host *host; } scsi_info_t; -static void aha152x_release_cs(dev_link_t *link); +static void aha152x_release_cs(struct pcmcia_device *link); static void aha152x_detach(struct pcmcia_device *p_dev); -static void aha152x_config_cs(dev_link_t *link); +static void aha152x_config_cs(struct pcmcia_device *link); -static dev_link_t *dev_list; +static struct pcmcia_device *dev_list; -static int aha152x_attach(struct pcmcia_device *p_dev) +static int aha152x_attach(struct pcmcia_device *link) { scsi_info_t *info; - dev_link_t *link = dev_to_instance(p_dev); - + DEBUG(0, "aha152x_attach()\n"); /* Create new SCSI device */ info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; memset(info, 0, sizeof(*info)); - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; link->io.NumPorts1 = 0x20; @@ -131,10 +130,8 @@ static int aha152x_attach(struct pcmcia_device *p_dev) /*====================================================================*/ -static void aha152x_detach(struct pcmcia_device *p_dev) +static void aha152x_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "aha152x_detach(0x%p)\n", link); if (link->state & DEV_CONFIG) @@ -149,9 +146,8 @@ static void aha152x_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void aha152x_config_cs(dev_link_t *link) +static void aha152x_config_cs(struct pcmcia_device *link) { - client_handle_t handle = link->handle; scsi_info_t *info = link->priv; struct aha152x_setup s; tuple_t tuple; @@ -166,19 +162,19 @@ static void aha152x_config_cs(dev_link_t *link) tuple.TupleData = tuple_data; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; /* Configure card */ link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; /* For New Media T&J, look for a SCSI window */ if (parse.cftable_entry.io.win[0].len >= 0x20) @@ -189,15 +185,15 @@ static void aha152x_config_cs(dev_link_t *link) if ((parse.cftable_entry.io.nwin > 0) && (link->io.BasePort1 < 0xffff)) { link->conf.ConfigIndex = parse.cftable_entry.index; - i = pcmcia_request_io(handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } next_entry: - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } - CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); /* Set configuration options for the aha152x driver */ memset(&s, 0, sizeof(s)); @@ -226,22 +222,21 @@ static void aha152x_config_cs(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); aha152x_release_cs(link); return; } -static void aha152x_release_cs(dev_link_t *link) +static void aha152x_release_cs(struct pcmcia_device *link) { scsi_info_t *info = link->priv; aha152x_release(info->host); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } -static int aha152x_resume(struct pcmcia_device *dev) +static int aha152x_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); scsi_info_t *info = link->priv; aha152x_host_reset_host(info->host); diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 94dcee9f28..4e6927112c 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -79,14 +79,13 @@ typedef struct scsi_info_t { } scsi_info_t; -static void fdomain_release(dev_link_t *link); +static void fdomain_release(struct pcmcia_device *link); static void fdomain_detach(struct pcmcia_device *p_dev); -static void fdomain_config(dev_link_t *link); +static void fdomain_config(struct pcmcia_device *link); -static int fdomain_attach(struct pcmcia_device *p_dev) +static int fdomain_attach(struct pcmcia_device *link) { scsi_info_t *info; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "fdomain_attach()\n"); @@ -94,7 +93,7 @@ static int fdomain_attach(struct pcmcia_device *p_dev) info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; memset(info, 0, sizeof(*info)); - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; link->io.NumPorts1 = 0x10; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; @@ -113,10 +112,8 @@ static int fdomain_attach(struct pcmcia_device *p_dev) /*====================================================================*/ -static void fdomain_detach(struct pcmcia_device *p_dev) +static void fdomain_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "fdomain_detach(0x%p)\n", link); if (link->state & DEV_CONFIG) @@ -130,9 +127,8 @@ static void fdomain_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void fdomain_config(dev_link_t *link) +static void fdomain_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; scsi_info_t *info = link->priv; tuple_t tuple; cisparse_t parse; @@ -147,30 +143,30 @@ static void fdomain_config(dev_link_t *link) tuple.TupleData = tuple_data; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; /* Configure card */ link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; link->conf.ConfigIndex = parse.cftable_entry.index; link->io.BasePort1 = parse.cftable_entry.io.win[0].base; - i = pcmcia_request_io(handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; next_entry: - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } - CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); /* A bad hack... */ release_region(link->io.BasePort1, link->io.NumPorts1); @@ -196,7 +192,7 @@ static void fdomain_config(dev_link_t *link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); fdomain_release(link); return; @@ -204,23 +200,21 @@ cs_failed: /*====================================================================*/ -static void fdomain_release(dev_link_t *link) +static void fdomain_release(struct pcmcia_device *link) { scsi_info_t *info = link->priv; DEBUG(0, "fdomain_release(0x%p)\n", link); scsi_remove_host(info->host); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); scsi_unregister(info->host); } /*====================================================================*/ -static int fdomain_resume(struct pcmcia_device *dev) +static int fdomain_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); - if (link->state & DEV_CONFIG) fdomain_16x0_bus_reset(NULL); diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 23548fbf48..ce4d7d868d 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1593,11 +1593,10 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt) configure the card at this point -- we wait until we receive a card insertion event. ======================================================================*/ -static int nsp_cs_attach(struct pcmcia_device *p_dev) +static int nsp_cs_attach(struct pcmcia_device *link) { scsi_info_t *info; nsp_hw_data *data = &nsp_data_base; - dev_link_t *link = dev_to_instance(p_dev); nsp_dbg(NSP_DEBUG_INIT, "in"); @@ -1605,7 +1604,7 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev) info = kmalloc(sizeof(*info), GFP_KERNEL); if (info == NULL) { return -ENOMEM; } memset(info, 0, sizeof(*info)); - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; data->ScsiInfo = info; @@ -1644,10 +1643,8 @@ static int nsp_cs_attach(struct pcmcia_device *p_dev) structures are freed. Otherwise, the structures will be freed when the device is released. ======================================================================*/ -static void nsp_cs_detach(struct pcmcia_device *p_dev) +static void nsp_cs_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link); if (link->state & DEV_CONFIG) { @@ -1668,9 +1665,8 @@ static void nsp_cs_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) /*====================================================================*/ -static void nsp_cs_config(dev_link_t *link) +static void nsp_cs_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; scsi_info_t *info = link->priv; tuple_t tuple; cisparse_t parse; @@ -1694,9 +1690,9 @@ static void nsp_cs_config(dev_link_t *link) tuple.TupleData = tuple_data; tuple.TupleDataMax = sizeof(tuple_data); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -1704,15 +1700,15 @@ static void nsp_cs_config(dev_link_t *link) link->state |= DEV_CONFIG; /* Look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); + CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; } @@ -1768,7 +1764,7 @@ static void nsp_cs_config(dev_link_t *link) link->io.NumPorts2 = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; } @@ -1783,7 +1779,7 @@ static void nsp_cs_config(dev_link_t *link) req.Size = 0x1000; } req.AccessSpeed = 0; - if (pcmcia_request_window(&link->handle, &req, &link->win) != 0) + if (pcmcia_request_window(&link, &req, &link->win) != 0) goto next_entry; map.Page = 0; map.CardOffset = mem->win[0].card_addr; if (pcmcia_map_mem_page(link->win, &map) != 0) @@ -1797,14 +1793,14 @@ static void nsp_cs_config(dev_link_t *link) next_entry: nsp_dbg(NSP_DEBUG_INIT, "next"); - pcmcia_disable_device(handle); - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + pcmcia_disable_device(link); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } if (link->conf.Attributes & CONF_ENABLE_IRQ) { - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); } - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); if (free_ports) { if (link->io.BasePort1) { @@ -1925,7 +1921,7 @@ static void nsp_cs_config(dev_link_t *link) cs_failed: nsp_dbg(NSP_DEBUG_INIT, "config fail"); - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); nsp_cs_release(link); return; @@ -1938,7 +1934,7 @@ static void nsp_cs_config(dev_link_t *link) device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed. ======================================================================*/ -static void nsp_cs_release(dev_link_t *link) +static void nsp_cs_release(struct pcmcia_device *link) { scsi_info_t *info = link->priv; nsp_hw_data *data = NULL; @@ -1966,7 +1962,7 @@ static void nsp_cs_release(dev_link_t *link) iounmap((void *)(data->MmioAddress)); } } - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2)) if (info->host != NULL) { @@ -1975,9 +1971,8 @@ static void nsp_cs_release(dev_link_t *link) #endif } /* nsp_cs_release */ -static int nsp_cs_suspend(struct pcmcia_device *dev) +static int nsp_cs_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); scsi_info_t *info = link->priv; nsp_hw_data *data; @@ -1996,9 +1991,8 @@ static int nsp_cs_suspend(struct pcmcia_device *dev) return 0; } -static int nsp_cs_resume(struct pcmcia_device *dev) +static int nsp_cs_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); scsi_info_t *info = link->priv; nsp_hw_data *data; diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index 2e1fde467c..ce348b379f 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -297,8 +297,8 @@ typedef struct _nsp_hw_data { /* Card service functions */ static void nsp_cs_detach (struct pcmcia_device *p_dev); -static void nsp_cs_release(dev_link_t *link); -static void nsp_cs_config (dev_link_t *link); +static void nsp_cs_release(struct pcmcia_device *link); +static void nsp_cs_config (struct pcmcia_device *link); /* Linux SCSI subsystem specific functions */ static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht); @@ -450,7 +450,7 @@ static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno) return host; } -static void cs_error(client_handle_t handle, int func, int ret) +static void cs_error(struct pcmcia_device *handle, int func, int ret) { error_info_t err = { func, ret }; pcmcia_report_error(handle, &err); diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index c6b3e9587f..a2a1c4b318 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -97,12 +97,12 @@ typedef struct scsi_info_t { unsigned short manf_id; } scsi_info_t; -static void qlogic_release(dev_link_t *link); +static void qlogic_release(struct pcmcia_device *link); static void qlogic_detach(struct pcmcia_device *p_dev); -static void qlogic_config(dev_link_t * link); +static void qlogic_config(struct pcmcia_device * link); static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host, - dev_link_t *link, int qbase, int qlirq) + struct pcmcia_device *link, int qbase, int qlirq) { int qltyp; /* type of chip */ int qinitid; @@ -156,10 +156,9 @@ free_scsi_host: err: return NULL; } -static int qlogic_attach(struct pcmcia_device *p_dev) +static int qlogic_attach(struct pcmcia_device *link) { scsi_info_t *info; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "qlogic_attach()\n"); @@ -168,7 +167,7 @@ static int qlogic_attach(struct pcmcia_device *p_dev) if (!info) return -ENOMEM; memset(info, 0, sizeof(*info)); - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; @@ -187,10 +186,8 @@ static int qlogic_attach(struct pcmcia_device *p_dev) /*====================================================================*/ -static void qlogic_detach(struct pcmcia_device *p_dev) +static void qlogic_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "qlogic_detach(0x%p)\n", link); if (link->state & DEV_CONFIG) @@ -205,9 +202,8 @@ static void qlogic_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void qlogic_config(dev_link_t * link) +static void qlogic_config(struct pcmcia_device * link) { - client_handle_t handle = link->handle; scsi_info_t *info = link->priv; tuple_t tuple; cisparse_t parse; @@ -221,38 +217,38 @@ static void qlogic_config(dev_link_t * link) tuple.TupleDataMax = 64; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; tuple.DesiredTuple = CISTPL_MANFID; - if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) + if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) info->manf_id = le16_to_cpu(tuple.TupleData[0]); /* Configure card */ link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; link->conf.ConfigIndex = parse.cftable_entry.index; link->io.BasePort1 = parse.cftable_entry.io.win[0].base; link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; if (link->io.BasePort1 != 0) { - i = pcmcia_request_io(handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } next_entry: - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } - CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { /* set ATAcmd */ @@ -283,15 +279,15 @@ out: return; cs_failed: - cs_error(link->handle, last_fn, last_ret); - pcmcia_disable_device(link->handle); + cs_error(link, last_fn, last_ret); + pcmcia_disable_device(link); return; } /* qlogic_config */ /*====================================================================*/ -static void qlogic_release(dev_link_t *link) +static void qlogic_release(struct pcmcia_device *link) { scsi_info_t *info = link->priv; @@ -300,21 +296,19 @@ static void qlogic_release(dev_link_t *link) scsi_remove_host(info->host); free_irq(link->irq.AssignedIRQ, info->host); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); scsi_host_put(info->host); } /*====================================================================*/ -static int qlogic_resume(struct pcmcia_device *dev) +static int qlogic_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); - if (link->state & DEV_CONFIG) { scsi_info_t *info = link->priv; - pcmcia_request_configuration(link->handle, &link->conf); + pcmcia_request_configuration(link, &link->conf); if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 1ef3109418..49a37de687 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -527,7 +527,7 @@ idle_out: } static void -SYM53C500_release(dev_link_t *link) +SYM53C500_release(struct pcmcia_device *link) { struct scsi_info_t *info = link->priv; struct Scsi_Host *shost = info->host; @@ -550,7 +550,7 @@ SYM53C500_release(dev_link_t *link) if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); scsi_host_put(shost); } /* SYM53C500_release */ @@ -708,9 +708,8 @@ static struct scsi_host_template sym53c500_driver_template = { do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) static void -SYM53C500_config(dev_link_t *link) +SYM53C500_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; struct scsi_info_t *info = link->priv; tuple_t tuple; cisparse_t parse; @@ -727,40 +726,40 @@ SYM53C500_config(dev_link_t *link) tuple.TupleDataMax = 64; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; tuple.DesiredTuple = CISTPL_MANFID; - if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && - (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) + if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && + (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) info->manf_id = le16_to_cpu(tuple.TupleData[0]); /* Configure card */ link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; link->conf.ConfigIndex = parse.cftable_entry.index; link->io.BasePort1 = parse.cftable_entry.io.win[0].base; link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; if (link->io.BasePort1 != 0) { - i = pcmcia_request_io(handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) break; } next_entry: - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } - CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); /* * That's the trouble with copying liberally from another driver. @@ -852,14 +851,13 @@ out: return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); SYM53C500_release(link); return; } /* SYM53C500_config */ -static int sym53c500_resume(struct pcmcia_device *dev) +static int sym53c500_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); struct scsi_info_t *info = link->priv; if (link->state & DEV_CONFIG) { @@ -882,10 +880,8 @@ static int sym53c500_resume(struct pcmcia_device *dev) } static void -SYM53C500_detach(struct pcmcia_device *p_dev) +SYM53C500_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "SYM53C500_detach(0x%p)\n", link); if (link->state & DEV_CONFIG) @@ -896,10 +892,9 @@ SYM53C500_detach(struct pcmcia_device *p_dev) } /* SYM53C500_detach */ static int -SYM53C500_attach(struct pcmcia_device *p_dev) +SYM53C500_attach(struct pcmcia_device *link) { struct scsi_info_t *info; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "SYM53C500_attach()\n"); @@ -908,7 +903,7 @@ SYM53C500_attach(struct pcmcia_device *p_dev) if (!info) return -ENOMEM; memset(info, 0, sizeof(*info)); - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 6bcde2c7b1..1fe8cafebe 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -113,7 +113,7 @@ struct serial_cfg_mem { }; -static void serial_config(dev_link_t * link); +static void serial_config(struct pcmcia_device * link); /*====================================================================== @@ -123,7 +123,7 @@ static void serial_config(dev_link_t * link); ======================================================================*/ -static void serial_remove(dev_link_t *link) +static void serial_remove(struct pcmcia_device *link) { struct serial_info *info = link->priv; int i; @@ -142,16 +142,14 @@ static void serial_remove(dev_link_t *link) info->p_dev->dev_node = NULL; if (!info->slave) - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); info->p_dev->state &= ~DEV_CONFIG; } } -static int serial_suspend(struct pcmcia_device *dev) +static int serial_suspend(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); - if (link->state & DEV_CONFIG) { struct serial_info *info = link->priv; int i; @@ -166,10 +164,8 @@ static int serial_suspend(struct pcmcia_device *dev) return 0; } -static int serial_resume(struct pcmcia_device *dev) +static int serial_resume(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(dev); - if (DEV_OK(link)) { struct serial_info *info = link->priv; int i; @@ -189,10 +185,9 @@ static int serial_resume(struct pcmcia_device *dev) ======================================================================*/ -static int serial_probe(struct pcmcia_device *p_dev) +static int serial_probe(struct pcmcia_device *link) { struct serial_info *info; - dev_link_t *link = dev_to_instance(p_dev); DEBUG(0, "serial_attach()\n"); @@ -201,7 +196,7 @@ static int serial_probe(struct pcmcia_device *p_dev) if (!info) return -ENOMEM; memset(info, 0, sizeof (*info)); - info->p_dev = p_dev; + info->p_dev = link; link->priv = info; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -230,9 +225,8 @@ static int serial_probe(struct pcmcia_device *p_dev) ======================================================================*/ -static void serial_detach(struct pcmcia_device *p_dev) +static void serial_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); struct serial_info *info = link->priv; DEBUG(0, "serial_detach(0x%p)\n", link); @@ -253,7 +247,7 @@ static void serial_detach(struct pcmcia_device *p_dev) /*====================================================================*/ -static int setup_serial(client_handle_t handle, struct serial_info * info, +static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, kio_addr_t iobase, int irq) { struct uart_port port; @@ -288,7 +282,7 @@ static int setup_serial(client_handle_t handle, struct serial_info * info, /*====================================================================*/ static int -first_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse) +first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse) { int i; i = pcmcia_get_first_tuple(handle, tuple); @@ -301,7 +295,7 @@ first_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse) } static int -next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse) +next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse) { int i; i = pcmcia_get_next_tuple(handle, tuple); @@ -315,11 +309,10 @@ next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse) /*====================================================================*/ -static int simple_config(dev_link_t *link) +static int simple_config(struct pcmcia_device *link) { static const kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; static const int size_table[2] = { 8, 16 }; - client_handle_t handle = link->handle; struct serial_info *info = link->priv; struct serial_cfg_mem *cfg_mem; tuple_t *tuple; @@ -340,7 +333,7 @@ static int simple_config(dev_link_t *link) buf = cfg_mem->buf; /* If the card is already configured, look up the port and irq */ - i = pcmcia_get_configuration_info(handle, &config); + i = pcmcia_get_configuration_info(link, &config); if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) { kio_addr_t port = 0; if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) { @@ -353,7 +346,7 @@ static int simple_config(dev_link_t *link) } if (info->slave) { kfree(cfg_mem); - return setup_serial(handle, info, port, config.AssignedIRQ); + return setup_serial(link, info, port, config.AssignedIRQ); } } @@ -366,7 +359,7 @@ static int simple_config(dev_link_t *link) /* Two tries: without IO aliases, then with aliases */ for (s = 0; s < 2; s++) { for (try = 0; try < 2; try++) { - i = first_tuple(handle, tuple, parse); + i = first_tuple(link, tuple, parse); while (i != CS_NO_MORE_ITEMS) { if (i != CS_SUCCESS) goto next_entry; @@ -379,19 +372,19 @@ static int simple_config(dev_link_t *link) link->io.BasePort1 = cf->io.win[0].base; link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } next_entry: - i = next_tuple(handle, tuple, parse); + i = next_tuple(link, tuple, parse); } } } /* Second pass: try to find an entry that isn't picky about its base address, then try to grab any standard serial port address, and finally try to get any free port. */ - i = first_tuple(handle, tuple, parse); + i = first_tuple(link, tuple, parse); while (i != CS_NO_MORE_ITEMS) { if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { @@ -399,43 +392,42 @@ next_entry: for (j = 0; j < 5; j++) { link->io.BasePort1 = base[j]; link->io.IOAddrLines = base[j] ? 16 : 3; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); if (i == CS_SUCCESS) goto found_port; } } - i = next_tuple(handle, tuple, parse); + i = next_tuple(link, tuple, parse); } found_port: if (i != CS_SUCCESS) { printk(KERN_NOTICE "serial_cs: no usable port range found, giving up\n"); - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); kfree(cfg_mem); return -1; } - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); + cs_error(link, RequestIRQ, i); link->irq.AssignedIRQ = 0; } if (info->multi && (info->manfid == MANFID_3COM)) link->conf.ConfigIndex &= ~(0x08); - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); + cs_error(link, RequestConfiguration, i); kfree(cfg_mem); return -1; } kfree(cfg_mem); - return setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ); + return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); } -static int multi_config(dev_link_t * link) +static int multi_config(struct pcmcia_device * link) { - client_handle_t handle = link->handle; struct serial_info *info = link->priv; struct serial_cfg_mem *cfg_mem; tuple_t *tuple; @@ -460,7 +452,7 @@ static int multi_config(dev_link_t * link) /* First, look for a generic full-sized window */ link->io.NumPorts1 = info->multi * 8; - i = first_tuple(handle, tuple, parse); + i = first_tuple(link, tuple, parse); while (i != CS_NO_MORE_ITEMS) { /* The quad port cards have bad CIS's, so just look for a window larger than 8 ports and assume it will be right */ @@ -470,19 +462,19 @@ static int multi_config(dev_link_t * link) link->io.BasePort1 = cf->io.win[0].base; link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); base2 = link->io.BasePort1 + 8; if (i == CS_SUCCESS) break; } - i = next_tuple(handle, tuple, parse); + i = next_tuple(link, tuple, parse); } /* If that didn't work, look for two windows */ if (i != CS_SUCCESS) { link->io.NumPorts1 = link->io.NumPorts2 = 8; info->multi = 2; - i = first_tuple(handle, tuple, parse); + i = first_tuple(link, tuple, parse); while (i != CS_NO_MORE_ITEMS) { if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { link->conf.ConfigIndex = cf->index; @@ -490,26 +482,26 @@ static int multi_config(dev_link_t * link) link->io.BasePort2 = cf->io.win[1].base; link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; - i = pcmcia_request_io(link->handle, &link->io); + i = pcmcia_request_io(link, &link->io); base2 = link->io.BasePort2; if (i == CS_SUCCESS) break; } - i = next_tuple(handle, tuple, parse); + i = next_tuple(link, tuple, parse); } } if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); + cs_error(link, RequestIO, i); rc = -1; goto free_cfg_mem; } - i = pcmcia_request_irq(link->handle, &link->irq); + i = pcmcia_request_irq(link, &link->irq); if (i != CS_SUCCESS) { printk(KERN_NOTICE "serial_cs: no usable port range found, giving up\n"); - cs_error(link->handle, RequestIRQ, i); + cs_error(link, RequestIRQ, i); link->irq.AssignedIRQ = 0; } /* Socket Dual IO: this enables irq's for second port */ @@ -517,9 +509,9 @@ static int multi_config(dev_link_t * link) link->conf.Present |= PRESENT_EXT_STATUS; link->conf.ExtStatus = ESR_REQ_ATTN_ENA; } - i = pcmcia_request_configuration(link->handle, &link->conf); + i = pcmcia_request_configuration(link, &link->conf); if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); + cs_error(link, RequestConfiguration, i); rc = -1; goto free_cfg_mem; } @@ -528,24 +520,24 @@ static int multi_config(dev_link_t * link) 8 registers are for the UART, the others are extra registers */ if (info->manfid == MANFID_OXSEMI) { if (cf->index == 1 || cf->index == 3) { - setup_serial(handle, info, base2, link->irq.AssignedIRQ); + setup_serial(link, info, base2, link->irq.AssignedIRQ); outb(12, link->io.BasePort1 + 1); } else { - setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ); + setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); outb(12, base2 + 1); } rc = 0; goto free_cfg_mem; } - setup_serial(handle, info, link->io.BasePort1, link->irq.AssignedIRQ); + setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); /* The Nokia cards are not really multiport cards */ if (info->manfid == MANFID_NOKIA) { rc = 0; goto free_cfg_mem; } for (i = 0; i < info->multi - 1; i++) - setup_serial(handle, info, base2 + (8 * i), + setup_serial(link, info, base2 + (8 * i), link->irq.AssignedIRQ); rc = 0; free_cfg_mem: @@ -561,9 +553,8 @@ free_cfg_mem: ======================================================================*/ -void serial_config(dev_link_t * link) +void serial_config(struct pcmcia_device * link) { - client_handle_t handle = link->handle; struct serial_info *info = link->priv; struct serial_cfg_mem *cfg_mem; tuple_t *tuple; @@ -589,7 +580,7 @@ void serial_config(dev_link_t * link) tuple->Attributes = 0; /* Get configuration register information */ tuple->DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(handle, tuple, parse); + last_ret = first_tuple(link, tuple, parse); if (last_ret != CS_SUCCESS) { last_fn = ParseTuple; goto cs_failed; @@ -603,11 +594,11 @@ void serial_config(dev_link_t * link) /* Is this a compliant multifunction card? */ tuple->DesiredTuple = CISTPL_LONGLINK_MFC; tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; - info->multi = (first_tuple(handle, tuple, parse) == CS_SUCCESS); + info->multi = (first_tuple(link, tuple, parse) == CS_SUCCESS); /* Is this a multiport card? */ tuple->DesiredTuple = CISTPL_MANFID; - if (first_tuple(handle, tuple, parse) == CS_SUCCESS) { + if (first_tuple(link, tuple, parse) == CS_SUCCESS) { info->manfid = parse->manfid.manf; for (i = 0; i < MULTI_COUNT; i++) if ((info->manfid == multi_id[i].manfid) && @@ -621,11 +612,11 @@ void serial_config(dev_link_t * link) multifunction cards that ask for appropriate IO port ranges */ tuple->DesiredTuple = CISTPL_FUNCID; if ((info->multi == 0) && - ((first_tuple(handle, tuple, parse) != CS_SUCCESS) || + ((first_tuple(link, tuple, parse) != CS_SUCCESS) || (parse->funcid.func == CISTPL_FUNCID_MULTI) || (parse->funcid.func == CISTPL_FUNCID_SERIAL))) { tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; - if (first_tuple(handle, tuple, parse) == CS_SUCCESS) { + if (first_tuple(link, tuple, parse) == CS_SUCCESS) { if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) info->multi = cf->io.win[0].len >> 3; if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && @@ -644,14 +635,14 @@ void serial_config(dev_link_t * link) if (info->manfid == MANFID_IBM) { conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; - last_ret = pcmcia_access_configuration_register(link->handle, ®); + last_ret = pcmcia_access_configuration_register(link, ®); if (last_ret) { last_fn = AccessConfigurationRegister; goto cs_failed; } reg.Action = CS_WRITE; reg.Value = reg.Value | 1; - last_ret = pcmcia_access_configuration_register(link->handle, ®); + last_ret = pcmcia_access_configuration_register(link, ®); if (last_ret) { last_fn = AccessConfigurationRegister; goto cs_failed; @@ -664,7 +655,7 @@ void serial_config(dev_link_t * link) return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: serial_remove(link); link->state &= ~DEV_CONFIG_PENDING; diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index 0afd6c04f2..bad68187f2 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -35,8 +35,8 @@ typedef struct ixj_info_t { } ixj_info_t; static void ixj_detach(struct pcmcia_device *p_dev); -static void ixj_config(dev_link_t * link); -static void ixj_cs_release(dev_link_t * link); +static void ixj_config(struct pcmcia_device * link); +static void ixj_cs_release(struct pcmcia_device * link); static int ixj_attach(struct pcmcia_device *p_dev) { @@ -58,10 +58,8 @@ static int ixj_attach(struct pcmcia_device *p_dev) return 0; } -static void ixj_detach(struct pcmcia_device *p_dev) +static void ixj_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DEBUG(0, "ixj_detach(0x%p)\n", link); link->state &= ~DEV_RELEASE_PENDING; @@ -74,22 +72,20 @@ static void ixj_detach(struct pcmcia_device *p_dev) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void ixj_get_serial(dev_link_t * link, IXJ * j) +static void ixj_get_serial(struct pcmcia_device * link, IXJ * j) { - client_handle_t handle; tuple_t tuple; u_short buf[128]; char *str; int last_ret, last_fn, i, place; - handle = link->handle; DEBUG(0, "ixj_get_serial(0x%p)\n", link); tuple.TupleData = (cisdata_t *) buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 80; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_VERS_1; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); str = (char *) buf; printk("PCMCIA Version %d.%d\n", str[0], str[1]); str += 2; @@ -137,10 +133,9 @@ static void ixj_get_serial(dev_link_t * link, IXJ * j) return; } -static void ixj_config(dev_link_t * link) +static void ixj_config(struct pcmcia_device * link) { IXJ *j; - client_handle_t handle; ixj_info_t *info; tuple_t tuple; u_short buf[128]; @@ -151,7 +146,6 @@ static void ixj_config(dev_link_t * link) 0 }; int last_ret, last_fn; - handle = link->handle; info = link->priv; DEBUG(0, "ixj_config(0x%p)\n", link); tuple.TupleData = (cisdata_t *) buf; @@ -159,18 +153,18 @@ static void ixj_config(dev_link_t * link) tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) + if (pcmcia_get_tuple_data(link, &tuple) != 0 || + pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; @@ -181,7 +175,7 @@ static void ixj_config(dev_link_t * link) link->io.BasePort2 = io->win[1].base; link->io.NumPorts2 = io->win[1].len; } - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; /* If we've got this far, we're done */ break; @@ -189,10 +183,10 @@ static void ixj_config(dev_link_t * link) next_entry: if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); + CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); + CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); /* * Register the card with the core. @@ -206,16 +200,16 @@ static void ixj_config(dev_link_t * link) link->state &= ~DEV_CONFIG_PENDING; return; cs_failed: - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); ixj_cs_release(link); } -static void ixj_cs_release(dev_link_t *link) +static void ixj_cs_release(struct pcmcia_device *link) { ixj_info_t *info = link->priv; DEBUG(0, "ixj_cs_release(0x%p)\n", link); info->ndev = 0; - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); } static struct pcmcia_device_id ixj_ids[] = { diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 8e61faa120..bfa8b213e1 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -71,7 +71,7 @@ typedef struct local_info_t { dev_node_t node; } local_info_t; -static void sl811_cs_release(dev_link_t * link); +static void sl811_cs_release(struct pcmcia_device * link); /*====================================================================*/ @@ -138,10 +138,8 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq) /*====================================================================*/ -static void sl811_cs_detach(struct pcmcia_device *p_dev) +static void sl811_cs_detach(struct pcmcia_device *link) { - dev_link_t *link = dev_to_instance(p_dev); - DBG(0, "sl811_cs_detach(0x%p)\n", link); link->state &= ~DEV_PRESENT; @@ -152,18 +150,17 @@ static void sl811_cs_detach(struct pcmcia_device *p_dev) kfree(link->priv); } -static void sl811_cs_release(dev_link_t * link) +static void sl811_cs_release(struct pcmcia_device * link) { DBG(0, "sl811_cs_release(0x%p)\n", link); - pcmcia_disable_device(link->handle); + pcmcia_disable_device(link); platform_device_unregister(&platform_dev); } -static void sl811_cs_config(dev_link_t *link) +static void sl811_cs_config(struct pcmcia_device *link) { - client_handle_t handle = link->handle; - struct device *parent = &handle_to_dev(handle); + struct device *parent = &handle_to_dev(link); local_info_t *dev = link->priv; tuple_t tuple; cisparse_t parse; @@ -179,9 +176,9 @@ static void sl811_cs_config(dev_link_t *link) tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); + CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -190,15 +187,15 @@ static void sl811_cs_config(dev_link_t *link) /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, - pcmcia_get_configuration_info(handle, &conf)); + pcmcia_get_configuration_info(link, &conf)); tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); + CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - if (pcmcia_get_tuple_data(handle, &tuple) != 0 - || pcmcia_parse_tuple(handle, &tuple, &parse) + if (pcmcia_get_tuple_data(link, &tuple) != 0 + || pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; @@ -244,14 +241,14 @@ static void sl811_cs_config(dev_link_t *link) link->io.BasePort1 = io->win[0].base; link->io.NumPorts1 = io->win[0].len; - if (pcmcia_request_io(link->handle, &link->io) != 0) + if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; } break; next_entry: - pcmcia_disable_device(handle); - last_ret = pcmcia_get_next_tuple(handle, &tuple); + pcmcia_disable_device(link); + last_ret = pcmcia_get_next_tuple(link, &tuple); } /* require an IRQ and two registers */ @@ -259,12 +256,12 @@ next_entry: goto cs_failed; if (link->conf.Attributes & CONF_ENABLE_IRQ) CS_CHECK(RequestIRQ, - pcmcia_request_irq(link->handle, &link->irq)); + pcmcia_request_irq(link, &link->irq)); else goto cs_failed; CS_CHECK(RequestConfiguration, - pcmcia_request_configuration(link->handle, &link->conf)); + pcmcia_request_configuration(link, &link->conf)); sprintf(dev->node.dev_name, driver_name); dev->node.major = dev->node.minor = 0; @@ -285,22 +282,21 @@ next_entry: < 0) { cs_failed: printk("sl811_cs_config failed\n"); - cs_error(link->handle, last_fn, last_ret); + cs_error(link, last_fn, last_ret); sl811_cs_release(link); link->state &= ~DEV_CONFIG_PENDING; } } -static int sl811_cs_attach(struct pcmcia_device *p_dev) +static int sl811_cs_attach(struct pcmcia_device *link) { local_info_t *local; - dev_link_t *link = dev_to_instance(p_dev); local = kmalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; memset(local, 0, sizeof(local_info_t)); - local->p_dev = p_dev; + local->p_dev = link; link->priv = local; /* Initialize */ -- cgit v1.2.2 From 15b99ac1729503db9e6dc642a50b9b6cb3bf51f9 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Fri, 31 Mar 2006 17:26:06 +0200 Subject: [PATCH] pcmcia: add return value to _config() functions Most of the driver initialization isn't done in the .probe function, but in the internal _config() functions. Make them return a value, so that .probe can properly report whether the probing of the device succeeded or not. Signed-off-by: Dominik Brodowski --- drivers/bluetooth/bluecard_cs.c | 15 ++++--- drivers/bluetooth/bt3c_cs.c | 15 ++++--- drivers/bluetooth/btuart_cs.c | 15 ++++--- drivers/bluetooth/dtl1_cs.c | 15 ++++--- drivers/char/pcmcia/cm4000_cs.c | 15 ++++--- drivers/char/pcmcia/cm4040_cs.c | 15 ++++--- drivers/char/pcmcia/synclink_cs.c | 16 +++++--- drivers/ide/legacy/ide-cs.c | 15 ++++--- drivers/isdn/hardware/avm/avm_cs.c | 21 +++++----- drivers/isdn/hisax/avma1_cs.c | 19 ++++----- drivers/isdn/hisax/elsa_cs.c | 15 ++++--- drivers/isdn/hisax/sedlbauer_cs.c | 16 ++++---- drivers/isdn/hisax/teles_cs.c | 21 +++++----- drivers/mtd/maps/pcmciamtd.c | 23 +++++------ drivers/net/pcmcia/3c574_cs.c | 16 ++++---- drivers/net/pcmcia/3c589_cs.c | 17 ++++---- drivers/net/pcmcia/axnet_cs.c | 16 ++++---- drivers/net/pcmcia/com20020_cs.c | 15 ++++--- drivers/net/pcmcia/fmvj18x_cs.c | 16 ++++---- drivers/net/pcmcia/ibmtr_cs.c | 11 +++-- drivers/net/pcmcia/nmclan_cs.c | 23 +++++------ drivers/net/pcmcia/pcnet_cs.c | 12 +++--- drivers/net/pcmcia/smc91c92_cs.c | 16 ++++---- drivers/net/pcmcia/xirc2ps_cs.c | 17 ++++---- drivers/net/wireless/airo_cs.c | 18 ++++---- drivers/net/wireless/atmel_cs.c | 15 ++++--- drivers/net/wireless/hostap/hostap_cs.c | 12 ++++-- drivers/net/wireless/netwave_cs.c | 15 ++++--- drivers/net/wireless/orinoco_cs.c | 15 ++++--- drivers/net/wireless/ray_cs.c | 19 ++++----- drivers/net/wireless/spectrum_cs.c | 15 ++++--- drivers/net/wireless/wavelan_cs.c | 20 ++++++--- drivers/net/wireless/wl3501_cs.c | 18 ++++---- drivers/parport/parport_cs.c | 18 ++++---- drivers/scsi/pcmcia/aha152x_stub.c | 19 ++++----- drivers/scsi/pcmcia/fdomain_stub.c | 73 ++++++++++++++++----------------- drivers/scsi/pcmcia/nsp_cs.c | 21 ++++++---- drivers/scsi/pcmcia/nsp_cs.h | 2 +- drivers/scsi/pcmcia/qlogic_stub.c | 19 ++++----- drivers/scsi/pcmcia/sym53c500_cs.c | 19 ++++----- drivers/serial/serial_cs.c | 11 +++-- drivers/telephony/ixj_pcmcia.c | 15 ++++--- drivers/usb/host/sl811_cs.c | 12 +++--- 43 files changed, 364 insertions(+), 387 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index e557f2359c..50174fb107 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -85,7 +85,7 @@ typedef struct bluecard_info_t { } bluecard_info_t; -static void bluecard_config(struct pcmcia_device *link); +static int bluecard_config(struct pcmcia_device *link); static void bluecard_release(struct pcmcia_device *link); static void bluecard_detach(struct pcmcia_device *p_dev); @@ -856,7 +856,7 @@ static int bluecard_close(bluecard_info_t *info) return 0; } -static int bluecard_attach(struct pcmcia_device *link) +static int bluecard_probe(struct pcmcia_device *link) { bluecard_info_t *info; @@ -880,9 +880,7 @@ static int bluecard_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - bluecard_config(link); - - return 0; + return bluecard_config(link); } @@ -912,7 +910,7 @@ static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t return pcmcia_parse_tuple(handle, tuple, parse); } -static void bluecard_config(struct pcmcia_device *link) +static int bluecard_config(struct pcmcia_device *link) { bluecard_info_t *info = link->priv; tuple_t tuple; @@ -973,13 +971,14 @@ static void bluecard_config(struct pcmcia_device *link) link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: bluecard_release(link); + return -ENODEV; } @@ -1008,7 +1007,7 @@ static struct pcmcia_driver bluecard_driver = { .drv = { .name = "bluecard_cs", }, - .probe = bluecard_attach, + .probe = bluecard_probe, .remove = bluecard_detach, .id_table = bluecard_ids, }; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 7ea8fa350d..80861f4f35 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -88,7 +88,7 @@ typedef struct bt3c_info_t { } bt3c_info_t; -static void bt3c_config(struct pcmcia_device *link); +static int bt3c_config(struct pcmcia_device *link); static void bt3c_release(struct pcmcia_device *link); static void bt3c_detach(struct pcmcia_device *p_dev); @@ -645,7 +645,7 @@ static int bt3c_close(bt3c_info_t *info) return 0; } -static int bt3c_attach(struct pcmcia_device *link) +static int bt3c_probe(struct pcmcia_device *link) { bt3c_info_t *info; @@ -669,9 +669,7 @@ static int bt3c_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - bt3c_config(link); - - return 0; + return bt3c_config(link); } @@ -710,7 +708,7 @@ static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t * return get_tuple(handle, tuple, parse); } -static void bt3c_config(struct pcmcia_device *link) +static int bt3c_config(struct pcmcia_device *link) { static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; bt3c_info_t *info = link->priv; @@ -809,13 +807,14 @@ found_port: link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: bt3c_release(link); + return -ENODEV; } @@ -841,7 +840,7 @@ static struct pcmcia_driver bt3c_driver = { .drv = { .name = "bt3c_cs", }, - .probe = bt3c_attach, + .probe = bt3c_probe, .remove = bt3c_detach, .id_table = bt3c_ids, }; diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 5948390613..658a137369 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -84,7 +84,7 @@ typedef struct btuart_info_t { } btuart_info_t; -static void btuart_config(struct pcmcia_device *link); +static int btuart_config(struct pcmcia_device *link); static void btuart_release(struct pcmcia_device *link); static void btuart_detach(struct pcmcia_device *p_dev); @@ -576,7 +576,7 @@ static int btuart_close(btuart_info_t *info) return 0; } -static int btuart_attach(struct pcmcia_device *link) +static int btuart_probe(struct pcmcia_device *link) { btuart_info_t *info; @@ -600,9 +600,7 @@ static int btuart_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - btuart_config(link); - - return 0; + return btuart_config(link); } @@ -641,7 +639,7 @@ static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t * return get_tuple(handle, tuple, parse); } -static void btuart_config(struct pcmcia_device *link) +static int btuart_config(struct pcmcia_device *link) { static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; btuart_info_t *info = link->priv; @@ -741,13 +739,14 @@ found_port: link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: btuart_release(link); + return -ENODEV; } @@ -772,7 +771,7 @@ static struct pcmcia_driver btuart_driver = { .drv = { .name = "btuart_cs", }, - .probe = btuart_attach, + .probe = btuart_probe, .remove = btuart_detach, .id_table = btuart_ids, }; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 416433b4a3..0ec7fd4c92 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -87,7 +87,7 @@ typedef struct dtl1_info_t { } dtl1_info_t; -static void dtl1_config(struct pcmcia_device *link); +static int dtl1_config(struct pcmcia_device *link); static void dtl1_release(struct pcmcia_device *link); static void dtl1_detach(struct pcmcia_device *p_dev); @@ -555,7 +555,7 @@ static int dtl1_close(dtl1_info_t *info) return 0; } -static int dtl1_attach(struct pcmcia_device *link) +static int dtl1_probe(struct pcmcia_device *link) { dtl1_info_t *info; @@ -579,9 +579,7 @@ static int dtl1_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - dtl1_config(link); - - return 0; + return dtl1_config(link); } @@ -620,7 +618,7 @@ static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t * return get_tuple(handle, tuple, parse); } -static void dtl1_config(struct pcmcia_device *link) +static int dtl1_config(struct pcmcia_device *link) { dtl1_info_t *info = link->priv; tuple_t tuple; @@ -693,13 +691,14 @@ static void dtl1_config(struct pcmcia_device *link) link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: dtl1_release(link); + return -ENODEV; } @@ -727,7 +726,7 @@ static struct pcmcia_driver dtl1_driver = { .drv = { .name = "dtl1_cs", }, - .probe = dtl1_attach, + .probe = dtl1_probe, .remove = dtl1_detach, .id_table = dtl1_ids, }; diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 79b8ad0e32..22dce9d47b 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -1759,7 +1759,7 @@ static void cmm_cm4000_release(struct pcmcia_device * link) /*==== Interface to PCMCIA Layer =======================================*/ -static void cm4000_config(struct pcmcia_device * link, int devno) +static int cm4000_config(struct pcmcia_device * link, int devno) { struct cm4000_dev *dev; tuple_t tuple; @@ -1846,7 +1846,7 @@ static void cm4000_config(struct pcmcia_device * link, int devno) link->dev_node = &dev->node; link->state &= ~DEV_CONFIG_PENDING; - return; + return 0; cs_failed: cs_error(link, fail_fn, fail_rc); @@ -1854,6 +1854,7 @@ cs_release: cm4000_release(link); link->state &= ~DEV_CONFIG_PENDING; + return -ENODEV; } static int cm4000_suspend(struct pcmcia_device *link) @@ -1883,10 +1884,10 @@ static void cm4000_release(struct pcmcia_device *link) pcmcia_disable_device(link); } -static int cm4000_attach(struct pcmcia_device *link) +static int cm4000_probe(struct pcmcia_device *link) { struct cm4000_dev *dev; - int i; + int i, ret; for (i = 0; i < CM4000_MAX_DEV; i++) if (dev_table[i] == NULL) @@ -1913,7 +1914,9 @@ static int cm4000_attach(struct pcmcia_device *link) init_waitqueue_head(&dev->readq); link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - cm4000_config(link, i); + ret = cm4000_config(link, i); + if (ret) + return ret; class_device_create(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i); @@ -1968,7 +1971,7 @@ static struct pcmcia_driver cm4000_driver = { .drv = { .name = "cm4000_cs", }, - .probe = cm4000_attach, + .probe = cm4000_probe, .remove = cm4000_detach, .suspend = cm4000_suspend, .resume = cm4000_resume, diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 8334226e10..6ccca8cbab 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -514,7 +514,7 @@ static void cm4040_reader_release(struct pcmcia_device *link) return; } -static void reader_config(struct pcmcia_device *link, int devno) +static int reader_config(struct pcmcia_device *link, int devno) { struct reader_dev *dev; tuple_t tuple; @@ -610,13 +610,14 @@ static void reader_config(struct pcmcia_device *link, int devno) link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1); DEBUGP(2, dev, "<- reader_config (succ)\n"); - return; + return 0; cs_failed: cs_error(link, fail_fn, fail_rc); cs_release: reader_release(link); link->state &= ~DEV_CONFIG_PENDING; + return -ENODEV; } static void reader_release(struct pcmcia_device *link) @@ -625,10 +626,10 @@ static void reader_release(struct pcmcia_device *link) pcmcia_disable_device(link); } -static int reader_attach(struct pcmcia_device *link) +static int reader_probe(struct pcmcia_device *link) { struct reader_dev *dev; - int i; + int i, ret; for (i = 0; i < CM_MAX_DEV; i++) { if (dev_table[i] == NULL) @@ -659,7 +660,9 @@ static int reader_attach(struct pcmcia_device *link) dev->poll_timer.function = &cm4040_do_poll; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - reader_config(link, i); + ret = reader_config(link, i); + if (ret) + return ret; class_device_create(cmx_class, NULL, MKDEV(major, i), NULL, "cmx%d", i); @@ -715,7 +718,7 @@ static struct pcmcia_driver reader_driver = { .drv = { .name = "cm4040_cs", }, - .probe = reader_attach, + .probe = reader_probe, .remove = reader_detach, .id_table = cm4040_ids, }; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 9bfd90e5d6..ef7a81314f 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -484,7 +484,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout); /* PCMCIA prototypes */ -static void mgslpc_config(struct pcmcia_device *link); +static int mgslpc_config(struct pcmcia_device *link); static void mgslpc_release(u_long arg); static void mgslpc_detach(struct pcmcia_device *p_dev); @@ -533,9 +533,10 @@ static void ldisc_receive_buf(struct tty_struct *tty, } } -static int mgslpc_attach(struct pcmcia_device *link) +static int mgslpc_probe(struct pcmcia_device *link) { MGSLPC_INFO *info; + int ret; if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_attach\n"); @@ -578,7 +579,9 @@ static int mgslpc_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - mgslpc_config(link); + ret = mgslpc_config(link); + if (ret) + return ret; mgslpc_add_device(info); @@ -591,7 +594,7 @@ static int mgslpc_attach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void mgslpc_config(struct pcmcia_device *link) +static int mgslpc_config(struct pcmcia_device *link) { MGSLPC_INFO *info = link->priv; tuple_t tuple; @@ -680,11 +683,12 @@ static void mgslpc_config(struct pcmcia_device *link) printk("\n"); link->state &= ~DEV_CONFIG_PENDING; - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); mgslpc_release((u_long)link); + return -ENODEV; } /* Card has been removed. @@ -3003,7 +3007,7 @@ static struct pcmcia_driver mgslpc_driver = { .drv = { .name = "synclink_cs", }, - .probe = mgslpc_attach, + .probe = mgslpc_probe, .remove = mgslpc_detach, .id_table = mgslpc_ids, .suspend = mgslpc_suspend, diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 58690c1ff6..56c8e828c6 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -88,7 +88,7 @@ typedef struct ide_info_t { } ide_info_t; static void ide_release(struct pcmcia_device *); -static void ide_config(struct pcmcia_device *); +static int ide_config(struct pcmcia_device *); static void ide_detach(struct pcmcia_device *p_dev); @@ -103,7 +103,7 @@ static void ide_detach(struct pcmcia_device *p_dev); ======================================================================*/ -static int ide_attach(struct pcmcia_device *link) +static int ide_probe(struct pcmcia_device *link) { ide_info_t *info; @@ -126,9 +126,7 @@ static int ide_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - ide_config(link); - - return 0; + return ide_config(link); } /* ide_attach */ /*====================================================================== @@ -172,7 +170,7 @@ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void ide_config(struct pcmcia_device *link) +static int ide_config(struct pcmcia_device *link) { ide_info_t *info = link->priv; tuple_t tuple; @@ -327,7 +325,7 @@ static void ide_config(struct pcmcia_device *link) link->state &= ~DEV_CONFIG_PENDING; kfree(stk); - return; + return 0; err_mem: printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n"); @@ -339,6 +337,7 @@ failed: kfree(stk); ide_release(link); link->state &= ~DEV_CONFIG_PENDING; + return -ENODEV; } /* ide_config */ /*====================================================================== @@ -424,7 +423,7 @@ static struct pcmcia_driver ide_cs_driver = { .drv = { .name = "ide-cs", }, - .probe = ide_attach, + .probe = ide_probe, .remove = ide_detach, .id_table = ide_ids, }; diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index c9c794e292..28f9211726 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -51,7 +51,7 @@ MODULE_LICENSE("GPL"); handler. */ -static void avmcs_config(struct pcmcia_device *link); +static int avmcs_config(struct pcmcia_device *link); static void avmcs_release(struct pcmcia_device *link); /* @@ -99,7 +99,7 @@ typedef struct local_info_t { ======================================================================*/ -static int avmcs_attach(struct pcmcia_device *p_dev) +static int avmcs_probe(struct pcmcia_device *p_dev) { local_info_t *local; @@ -128,12 +128,10 @@ static int avmcs_attach(struct pcmcia_device *p_dev) p_dev->priv = local; p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - avmcs_config(p_dev); - - return 0; + return avmcs_config(p_dev); err: - return -EINVAL; + return -ENOMEM; } /* avmcs_attach */ /*====================================================================== @@ -185,7 +183,7 @@ static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void avmcs_config(struct pcmcia_device *link) +static int avmcs_config(struct pcmcia_device *link) { tuple_t tuple; cisparse_t parse; @@ -219,7 +217,7 @@ static void avmcs_config(struct pcmcia_device *link) if (i != CS_SUCCESS) { cs_error(link, ParseTuple, i); link->state &= ~DEV_CONFIG_PENDING; - return; + return -ENODEV; } /* Configure card */ @@ -319,7 +317,7 @@ found_port: /* If any step failed, release any partially configured state */ if (i != 0) { avmcs_release(link); - return; + return -ENODEV; } @@ -333,9 +331,10 @@ found_port: printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n", dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ); avmcs_release(link); - return; + return -ENODEV; } dev->node.minor = i; + return 0; } /* avmcs_config */ @@ -367,7 +366,7 @@ static struct pcmcia_driver avmcs_driver = { .drv = { .name = "avm_cs", }, - .probe = avmcs_attach, + .probe = avmcs_probe, .remove = avmcs_detach, .id_table = avmcs_ids, }; diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index ff6b0e185b..11c7c4f09e 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -67,7 +67,7 @@ module_param(isdnprot, int, 0); handler. */ -static void avma1cs_config(struct pcmcia_device *link); +static int avma1cs_config(struct pcmcia_device *link); static void avma1cs_release(struct pcmcia_device *link); /* @@ -116,7 +116,7 @@ typedef struct local_info_t { ======================================================================*/ -static int avma1cs_attach(struct pcmcia_device *p_dev) +static int avma1cs_probe(struct pcmcia_device *p_dev) { local_info_t *local; @@ -150,9 +150,7 @@ static int avma1cs_attach(struct pcmcia_device *p_dev) p_dev->conf.Present = PRESENT_OPTION; p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - avma1cs_config(p_dev); - - return 0; + return avma1cs_config(p_dev); } /* avma1cs_attach */ /*====================================================================== @@ -206,7 +204,7 @@ static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void avma1cs_config(struct pcmcia_device *link) +static int avma1cs_config(struct pcmcia_device *link) { tuple_t tuple; cisparse_t parse; @@ -242,7 +240,7 @@ static void avma1cs_config(struct pcmcia_device *link) if (i != CS_SUCCESS) { cs_error(link, ParseTuple, i); link->state &= ~DEV_CONFIG_PENDING; - return; + return -ENODEV; } /* Configure card */ @@ -325,7 +323,7 @@ found_port: /* If any step failed, release any partially configured state */ if (i != 0) { avma1cs_release(link); - return; + return -ENODEV; } printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n", @@ -340,10 +338,11 @@ found_port: if (i < 0) { printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); avma1cs_release(link); - return; + return -ENODEV; } dev->node.minor = i; + return 0; } /* avma1cs_config */ /*====================================================================== @@ -379,7 +378,7 @@ static struct pcmcia_driver avma1cs_driver = { .drv = { .name = "avma1_cs", }, - .probe = avma1cs_attach, + .probe = avma1cs_probe, .remove = avma1cs_detach, .id_table = avma1cs_ids, }; diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 7a42bd4316..4856680ce7 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -94,7 +94,7 @@ module_param(protocol, int, 0); handler. */ -static void elsa_cs_config(struct pcmcia_device *link); +static int elsa_cs_config(struct pcmcia_device *link); static void elsa_cs_release(struct pcmcia_device *link); /* @@ -139,7 +139,7 @@ typedef struct local_info_t { ======================================================================*/ -static int elsa_cs_attach(struct pcmcia_device *link) +static int elsa_cs_probe(struct pcmcia_device *link) { local_info_t *local; @@ -175,9 +175,7 @@ static int elsa_cs_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - elsa_cs_config(link); - - return 0; + return elsa_cs_config(link); } /* elsa_cs_attach */ /*====================================================================== @@ -235,7 +233,7 @@ static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void elsa_cs_config(struct pcmcia_device *link) +static int elsa_cs_config(struct pcmcia_device *link) { tuple_t tuple; cisparse_t parse; @@ -346,10 +344,11 @@ static void elsa_cs_config(struct pcmcia_device *link) } else ((local_info_t*)link->priv)->cardnr = i; - return; + return 0; cs_failed: cs_error(link, last_fn, i); elsa_cs_release(link); + return -ENODEV; } /* elsa_cs_config */ /*====================================================================== @@ -406,7 +405,7 @@ static struct pcmcia_driver elsa_cs_driver = { .drv = { .name = "elsa_cs", }, - .probe = elsa_cs_attach, + .probe = elsa_cs_probe, .remove = elsa_cs_detach, .id_table = elsa_ids, .suspend = elsa_suspend, diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 2af48a6846..a35a29586a 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -95,7 +95,7 @@ module_param(protocol, int, 0); event handler. */ -static void sedlbauer_config(struct pcmcia_device *link); +static int sedlbauer_config(struct pcmcia_device *link); static void sedlbauer_release(struct pcmcia_device *link); /* @@ -148,7 +148,7 @@ typedef struct local_info_t { ======================================================================*/ -static int sedlbauer_attach(struct pcmcia_device *link) +static int sedlbauer_probe(struct pcmcia_device *link) { local_info_t *local; @@ -187,9 +187,7 @@ static int sedlbauer_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - sedlbauer_config(link); - - return 0; + return sedlbauer_config(link); } /* sedlbauer_attach */ /*====================================================================== @@ -224,7 +222,7 @@ static void sedlbauer_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void sedlbauer_config(struct pcmcia_device *link) +static int sedlbauer_config(struct pcmcia_device *link) { local_info_t *dev = link->priv; tuple_t tuple; @@ -423,14 +421,16 @@ static void sedlbauer_config(struct pcmcia_device *link) printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", last_ret, link->io.BasePort1); sedlbauer_release(link); + return -ENODEV; } else ((local_info_t*)link->priv)->cardnr = last_ret; - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); sedlbauer_release(link); + return -ENODEV; } /* sedlbauer_config */ @@ -493,7 +493,7 @@ static struct pcmcia_driver sedlbauer_driver = { .drv = { .name = "sedlbauer_cs", }, - .probe = sedlbauer_attach, + .probe = sedlbauer_probe, .remove = sedlbauer_detach, .id_table = sedlbauer_ids, .suspend = sedlbauer_suspend, diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 698e9ec95f..7b66038096 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -75,7 +75,7 @@ module_param(protocol, int, 0); handler. */ -static void teles_cs_config(struct pcmcia_device *link); +static int teles_cs_config(struct pcmcia_device *link); static void teles_cs_release(struct pcmcia_device *link); /* @@ -130,7 +130,7 @@ typedef struct local_info_t { ======================================================================*/ -static int teles_attach(struct pcmcia_device *link) +static int teles_probe(struct pcmcia_device *link) { local_info_t *local; @@ -165,9 +165,7 @@ static int teles_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - teles_cs_config(link); - - return 0; + return teles_cs_config(link); } /* teles_attach */ /*====================================================================== @@ -225,7 +223,7 @@ static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, return get_tuple(handle, tuple, parse); } -static void teles_cs_config(struct pcmcia_device *link) +static int teles_cs_config(struct pcmcia_device *link) { tuple_t tuple; cisparse_t parse; @@ -333,13 +331,16 @@ static void teles_cs_config(struct pcmcia_device *link) printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); teles_cs_release(link); - } else - ((local_info_t*)link->priv)->cardnr = i; + return -ENODEV; + } + + ((local_info_t*)link->priv)->cardnr = i; + return 0; - return; cs_failed: cs_error(link, last_fn, i); teles_cs_release(link); + return -ENODEV; } /* teles_cs_config */ /*====================================================================== @@ -396,7 +397,7 @@ static struct pcmcia_driver teles_cs_driver = { .drv = { .name = "teles_cs", }, - .probe = teles_attach, + .probe = teles_probe, .remove = teles_detach, .id_table = teles_ids, .suspend = teles_suspend, diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index e9086f0cb2..466f558aa7 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -487,7 +487,7 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void pcmciamtd_config(struct pcmcia_device *link) +static int pcmciamtd_config(struct pcmcia_device *link) { struct pcmciamtd_dev *dev = link->priv; struct mtd_info *mtd = NULL; @@ -561,7 +561,7 @@ static void pcmciamtd_config(struct pcmcia_device *link) if(!dev->win_size) { err("Cant allocate memory window"); pcmciamtd_release(link); - return; + return -ENODEV; } DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10); @@ -573,7 +573,7 @@ static void pcmciamtd_config(struct pcmcia_device *link) if(!dev->win_base) { err("ioremap(%lu, %u) failed", req.Base, req.Size); pcmciamtd_release(link); - return; + return -ENODEV; } DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x", dev, req.Base, dev->win_base, req.Size); @@ -605,6 +605,7 @@ static void pcmciamtd_config(struct pcmcia_device *link) ret = pcmcia_request_configuration(link, &link->conf); if(ret != CS_SUCCESS) { cs_error(link, RequestConfiguration, ret); + return -ENODEV; } if(mem_type == 1) { @@ -625,7 +626,7 @@ static void pcmciamtd_config(struct pcmcia_device *link) if(!mtd) { DEBUG(1, "Cant find an MTD"); pcmciamtd_release(link); - return; + return -ENODEV; } dev->mtd_info = mtd; @@ -668,19 +669,19 @@ static void pcmciamtd_config(struct pcmcia_device *link) dev->mtd_info = NULL; err("Couldnt register MTD device"); pcmciamtd_release(link); - return; + return -ENODEV; } snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index); info("mtd%d: %s", mtd->index, mtd->name); link->state &= ~DEV_CONFIG_PENDING; link->dev_node = &dev->node; - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); err("CS Error, exiting"); pcmciamtd_release(link); - return; + return -ENODEV; } @@ -730,7 +731,7 @@ static void pcmciamtd_detach(struct pcmcia_device *link) * with Card Services. */ -static int pcmciamtd_attach(struct pcmcia_device *link) +static int pcmciamtd_probe(struct pcmcia_device *link) { struct pcmciamtd_dev *dev; @@ -747,9 +748,7 @@ static int pcmciamtd_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - pcmciamtd_config(link); - - return 0; + return pcmciamtd_config(link); } static struct pcmcia_device_id pcmciamtd_ids[] = { @@ -783,7 +782,7 @@ static struct pcmcia_driver pcmciamtd_driver = { .drv = { .name = "pcmciamtd" }, - .probe = pcmciamtd_attach, + .probe = pcmciamtd_probe, .remove = pcmciamtd_detach, .owner = THIS_MODULE, .id_table = pcmciamtd_ids, diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index f4e293bd04..4611469fdf 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -225,7 +225,7 @@ static char mii_preamble_required = 0; /* Index of functions. */ -static void tc574_config(struct pcmcia_device *link); +static int tc574_config(struct pcmcia_device *link); static void tc574_release(struct pcmcia_device *link); static void mdio_sync(kio_addr_t ioaddr, int bits); @@ -256,7 +256,7 @@ static void tc574_detach(struct pcmcia_device *p_dev); with Card Services. */ -static int tc574_attach(struct pcmcia_device *link) +static int tc574_probe(struct pcmcia_device *link) { struct el3_private *lp; struct net_device *dev; @@ -297,9 +297,7 @@ static int tc574_attach(struct pcmcia_device *link) #endif link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - tc574_config(link); - - return 0; + return tc574_config(link); } /* tc574_attach */ /* @@ -337,7 +335,7 @@ static void tc574_detach(struct pcmcia_device *link) static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; -static void tc574_config(struct pcmcia_device *link) +static int tc574_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); @@ -486,13 +484,13 @@ static void tc574_config(struct pcmcia_device *link) 8 << config.u.ram_size, ram_split[config.u.ram_split], config.u.autoselect ? "autoselect " : ""); - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: tc574_release(link); - return; + return -ENODEV; } /* tc574_config */ @@ -1223,7 +1221,7 @@ static struct pcmcia_driver tc574_driver = { .drv = { .name = "3c574_cs", }, - .probe = tc574_attach, + .probe = tc574_probe, .remove = tc574_detach, .id_table = tc574_ids, .suspend = tc574_suspend, diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 565063d493..160d48a8ed 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -142,7 +142,7 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; /*====================================================================*/ -static void tc589_config(struct pcmcia_device *link); +static int tc589_config(struct pcmcia_device *link); static void tc589_release(struct pcmcia_device *link); static u16 read_eeprom(kio_addr_t ioaddr, int index); @@ -170,7 +170,7 @@ static void tc589_detach(struct pcmcia_device *p_dev); ======================================================================*/ -static int tc589_attach(struct pcmcia_device *link) +static int tc589_probe(struct pcmcia_device *link) { struct el3_private *lp; struct net_device *dev; @@ -212,9 +212,7 @@ static int tc589_attach(struct pcmcia_device *link) SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - tc589_config(link); - - return 0; + return tc589_config(link); } /* tc589_attach */ /*====================================================================== @@ -252,7 +250,7 @@ static void tc589_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void tc589_config(struct pcmcia_device *link) +static int tc589_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); @@ -359,14 +357,13 @@ static void tc589_config(struct pcmcia_device *link) printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n", (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], if_names[dev->if_port]); - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: tc589_release(link); - return; - + return -ENODEV; } /* tc589_config */ /*====================================================================== @@ -997,7 +994,7 @@ static struct pcmcia_driver tc589_driver = { .drv = { .name = "3c589_cs", }, - .probe = tc589_attach, + .probe = tc589_probe, .remove = tc589_detach, .id_table = tc589_ids, .suspend = tc589_suspend, diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 88f180e98e..f6ca85d77c 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -86,7 +86,7 @@ static char *version = /*====================================================================*/ -static void axnet_config(struct pcmcia_device *link); +static int axnet_config(struct pcmcia_device *link); static void axnet_release(struct pcmcia_device *link); static int axnet_open(struct net_device *dev); static int axnet_close(struct net_device *dev); @@ -142,7 +142,7 @@ static inline axnet_dev_t *PRIV(struct net_device *dev) ======================================================================*/ -static int axnet_attach(struct pcmcia_device *link) +static int axnet_probe(struct pcmcia_device *link) { axnet_dev_t *info; struct net_device *dev; @@ -169,9 +169,7 @@ static int axnet_attach(struct pcmcia_device *link) SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - axnet_config(link); - - return 0; + return axnet_config(link); } /* axnet_attach */ /*====================================================================== @@ -288,7 +286,7 @@ static int try_io_port(struct pcmcia_device *link) } } -static void axnet_config(struct pcmcia_device *link) +static int axnet_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; axnet_dev_t *info = PRIV(dev); @@ -425,14 +423,14 @@ static void axnet_config(struct pcmcia_device *link) } else { printk(KERN_NOTICE " No MII transceivers found!\n"); } - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: axnet_release(link); link->state &= ~DEV_CONFIG_PENDING; - return; + return -ENODEV; } /* axnet_config */ /*====================================================================== @@ -806,7 +804,7 @@ static struct pcmcia_driver axnet_cs_driver = { .drv = { .name = "axnet_cs", }, - .probe = axnet_attach, + .probe = axnet_probe, .remove = axnet_detach, .id_table = axnet_ids, .suspend = axnet_suspend, diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index a9bcfb4ba1..a7d675bc60 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -118,7 +118,7 @@ MODULE_LICENSE("GPL"); /*====================================================================*/ -static void com20020_config(struct pcmcia_device *link); +static int com20020_config(struct pcmcia_device *link); static void com20020_release(struct pcmcia_device *link); static void com20020_detach(struct pcmcia_device *p_dev); @@ -138,7 +138,7 @@ typedef struct com20020_dev_t { ======================================================================*/ -static int com20020_attach(struct pcmcia_device *p_dev) +static int com20020_probe(struct pcmcia_device *p_dev) { com20020_dev_t *info; struct net_device *dev; @@ -179,9 +179,7 @@ static int com20020_attach(struct pcmcia_device *p_dev) p_dev->priv = info; p_dev->state |= DEV_PRESENT; - com20020_config(p_dev); - - return 0; + return com20020_config(p_dev); fail_alloc_dev: kfree(info); @@ -250,7 +248,7 @@ static void com20020_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void com20020_config(struct pcmcia_device *link) +static int com20020_config(struct pcmcia_device *link) { struct arcnet_local *lp; tuple_t tuple; @@ -345,13 +343,14 @@ static void com20020_config(struct pcmcia_device *link) DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n", dev->name, dev->base_addr, dev->irq); - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: DEBUG(1,"com20020_config failed...\n"); com20020_release(link); + return -ENODEV; } /* com20020_config */ /*====================================================================== @@ -404,7 +403,7 @@ static struct pcmcia_driver com20020_cs_driver = { .drv = { .name = "com20020_cs", }, - .probe = com20020_attach, + .probe = com20020_probe, .remove = com20020_detach, .id_table = com20020_ids, .suspend = com20020_suspend, diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index ad3e490bb0..d9c83b2900 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -84,7 +84,7 @@ static char *version = DRV_NAME ".c " DRV_VERSION " 2002/03/23"; /* PCMCIA event handlers */ -static void fmvj18x_config(struct pcmcia_device *link); +static int fmvj18x_config(struct pcmcia_device *link); static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id); static int fmvj18x_setup_mfc(struct pcmcia_device *link); static void fmvj18x_release(struct pcmcia_device *link); @@ -228,7 +228,7 @@ typedef struct local_info_t { #define BANK_1U 0x24 /* bank 1 (CONFIG_1) */ #define BANK_2U 0x28 /* bank 2 (CONFIG_1) */ -static int fmvj18x_attach(struct pcmcia_device *link) +static int fmvj18x_probe(struct pcmcia_device *link) { local_info_t *lp; struct net_device *dev; @@ -273,9 +273,7 @@ static int fmvj18x_attach(struct pcmcia_device *link) SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - fmvj18x_config(link); - - return 0; + return fmvj18x_config(link); } /* fmvj18x_attach */ /*====================================================================*/ @@ -339,7 +337,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link) return ret; /* RequestIO failed */ } -static void fmvj18x_config(struct pcmcia_device *link) +static int fmvj18x_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; local_info_t *lp = netdev_priv(dev); @@ -552,7 +550,7 @@ static void fmvj18x_config(struct pcmcia_device *link) for (i = 0; i < 6; i++) printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); - return; + return 0; cs_failed: /* All Card Services errors end up here */ @@ -560,7 +558,7 @@ cs_failed: failed: fmvj18x_release(link); link->state &= ~DEV_CONFIG_PENDING; - + return -ENODEV; } /* fmvj18x_config */ /*====================================================================*/ @@ -720,7 +718,7 @@ static struct pcmcia_driver fmvj18x_cs_driver = { .drv = { .name = "fmvj18x_cs", }, - .probe = fmvj18x_attach, + .probe = fmvj18x_probe, .remove = fmvj18x_detach, .id_table = fmvj18x_ids, .suspend = fmvj18x_suspend, diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 1b8b44dc4c..e038d9278a 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -105,7 +105,7 @@ MODULE_LICENSE("GPL"); /*====================================================================*/ -static void ibmtr_config(struct pcmcia_device *link); +static int ibmtr_config(struct pcmcia_device *link); static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase); static void ibmtr_release(struct pcmcia_device *link); static void ibmtr_detach(struct pcmcia_device *p_dev); @@ -174,9 +174,7 @@ static int ibmtr_attach(struct pcmcia_device *link) SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); link->state |= DEV_PRESENT; - ibmtr_config(link); - - return 0; + return ibmtr_config(link); } /* ibmtr_attach */ /*====================================================================== @@ -220,7 +218,7 @@ static void ibmtr_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void ibmtr_config(struct pcmcia_device *link) +static int ibmtr_config(struct pcmcia_device *link) { ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; @@ -323,12 +321,13 @@ static void ibmtr_config(struct pcmcia_device *link) for (i = 0; i < TR_ALEN; i++) printk("%02X", dev->dev_addr[i]); printk("\n"); - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: ibmtr_release(link); + return -ENODEV; } /* ibmtr_config */ /*====================================================================== diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 8b8e716231..ea8a62e629 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -417,7 +417,7 @@ INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); Function Prototypes ---------------------------------------------------------------------------- */ -static void nmclan_config(struct pcmcia_device *link); +static int nmclan_config(struct pcmcia_device *link); static void nmclan_release(struct pcmcia_device *link); static void nmclan_reset(struct net_device *dev); @@ -443,7 +443,7 @@ nmclan_attach Services. ---------------------------------------------------------------------------- */ -static int nmclan_attach(struct pcmcia_device *link) +static int nmclan_probe(struct pcmcia_device *link) { mace_private *lp; struct net_device *dev; @@ -488,9 +488,7 @@ static int nmclan_attach(struct pcmcia_device *link) #endif link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - nmclan_config(link); - - return 0; + return nmclan_config(link); } /* nmclan_attach */ /* ---------------------------------------------------------------------------- @@ -655,7 +653,7 @@ nmclan_config #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void nmclan_config(struct pcmcia_device *link) +static int nmclan_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; mace_private *lp = netdev_priv(dev); @@ -710,7 +708,7 @@ static void nmclan_config(struct pcmcia_device *link) printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should" " be 0x40 0x?9\n", sig[0], sig[1]); link->state &= ~DEV_CONFIG_PENDING; - return; + return -ENODEV; } } @@ -740,14 +738,13 @@ static void nmclan_config(struct pcmcia_device *link) dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]); for (i = 0; i < 6; i++) printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); - return; + return 0; cs_failed: - cs_error(link, last_fn, last_ret); + cs_error(link, last_fn, last_ret); failed: - nmclan_release(link); - return; - + nmclan_release(link); + return -ENODEV; } /* nmclan_config */ /* ---------------------------------------------------------------------------- @@ -1611,7 +1608,7 @@ static struct pcmcia_driver nmclan_cs_driver = { .drv = { .name = "nmclan_cs", }, - .probe = nmclan_attach, + .probe = nmclan_probe, .remove = nmclan_detach, .id_table = nmclan_ids, .suspend = nmclan_suspend, diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 9f41355e6b..d840c0f03e 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -103,7 +103,7 @@ module_param_array(hw_addr, int, NULL, 0); /*====================================================================*/ static void mii_phy_probe(struct net_device *dev); -static void pcnet_config(struct pcmcia_device *link); +static int pcnet_config(struct pcmcia_device *link); static void pcnet_release(struct pcmcia_device *link); static int pcnet_open(struct net_device *dev); static int pcnet_close(struct net_device *dev); @@ -265,9 +265,7 @@ static int pcnet_probe(struct pcmcia_device *link) dev->set_config = &set_config; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - pcnet_config(link); - - return 0; + return pcnet_config(link); } /* pcnet_attach */ /*====================================================================== @@ -516,7 +514,7 @@ static int try_io_port(struct pcmcia_device *link) } } -static void pcnet_config(struct pcmcia_device *link) +static int pcnet_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; pcnet_dev_t *info = PRIV(dev); @@ -701,14 +699,14 @@ static void pcnet_config(struct pcmcia_device *link) printk(" hw_addr "); for (i = 0; i < 6; i++) printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: pcnet_release(link); link->state &= ~DEV_CONFIG_PENDING; - return; + return -ENODEV; } /* pcnet_config */ /*====================================================================== diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index a4ee3057b8..3252c1dc9e 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -279,7 +279,7 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002, /*====================================================================*/ static void smc91c92_detach(struct pcmcia_device *p_dev); -static void smc91c92_config(struct pcmcia_device *link); +static int smc91c92_config(struct pcmcia_device *link); static void smc91c92_release(struct pcmcia_device *link); static int smc_open(struct net_device *dev); @@ -309,7 +309,7 @@ static struct ethtool_ops ethtool_ops; ======================================================================*/ -static int smc91c92_attach(struct pcmcia_device *link) +static int smc91c92_probe(struct pcmcia_device *link) { struct smc_private *smc; struct net_device *dev; @@ -357,9 +357,7 @@ static int smc91c92_attach(struct pcmcia_device *link) smc->mii_if.reg_num_mask = 0x1f; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - smc91c92_config(link); - - return 0; + return smc91c92_config(link); } /* smc91c92_attach */ /*====================================================================== @@ -972,7 +970,7 @@ static int check_sig(struct pcmcia_device *link) #define CS_EXIT_TEST(ret, svc, label) \ if (ret != CS_SUCCESS) { cs_error(link, svc, ret); goto label; } -static void smc91c92_config(struct pcmcia_device *link) +static int smc91c92_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct smc_private *smc = netdev_priv(dev); @@ -1145,7 +1143,7 @@ static void smc91c92_config(struct pcmcia_device *link) } } kfree(cfg_mem); - return; + return 0; config_undo: unregister_netdev(dev); @@ -1153,7 +1151,7 @@ config_failed: /* CS_EXIT_TEST() calls jump to here... */ smc91c92_release(link); link->state &= ~DEV_CONFIG_PENDING; kfree(cfg_mem); - + return -ENODEV; } /* smc91c92_config */ /*====================================================================== @@ -2289,7 +2287,7 @@ static struct pcmcia_driver smc91c92_cs_driver = { .drv = { .name = "smc91c92_cs", }, - .probe = smc91c92_attach, + .probe = smc91c92_probe, .remove = smc91c92_detach, .id_table = smc91c92_ids, .suspend = smc91c92_suspend, diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 84328da075..77bf4e3a61 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -290,7 +290,7 @@ static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, */ static int has_ce2_string(struct pcmcia_device * link); -static void xirc2ps_config(struct pcmcia_device * link); +static int xirc2ps_config(struct pcmcia_device * link); static void xirc2ps_release(struct pcmcia_device * link); /**************** @@ -553,7 +553,7 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len) */ static int -xirc2ps_attach(struct pcmcia_device *link) +xirc2ps_probe(struct pcmcia_device *link) { struct net_device *dev; local_info_t *local; @@ -592,9 +592,7 @@ xirc2ps_attach(struct pcmcia_device *link) #endif link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - xirc2ps_config(link); - - return 0; + return xirc2ps_config(link); } /* xirc2ps_attach */ /**************** @@ -731,7 +729,7 @@ has_ce2_string(struct pcmcia_device * link) * is received, to configure the PCMCIA socket, and to make the * ethernet device available to the system. */ -static void +static int xirc2ps_config(struct pcmcia_device * link) { struct net_device *dev = link->priv; @@ -1061,17 +1059,18 @@ xirc2ps_config(struct pcmcia_device * link) printk("%c%02X", i?':':' ', dev->dev_addr[i]); printk("\n"); - return; + return 0; config_error: link->state &= ~DEV_CONFIG_PENDING; xirc2ps_release(link); - return; + return -ENODEV; cis_error: printk(KNOT_XIRC "unable to parse CIS\n"); failure: link->state &= ~DEV_CONFIG_PENDING; + return -ENODEV; } /* xirc2ps_config */ /**************** @@ -1911,7 +1910,7 @@ static struct pcmcia_driver xirc2ps_cs_driver = { .drv = { .name = "xirc2ps_cs", }, - .probe = xirc2ps_attach, + .probe = xirc2ps_probe, .remove = xirc2ps_detach, .id_table = xirc2ps_ids, .suspend = xirc2ps_suspend, diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 76970197f9..97f41565fc 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -80,7 +80,7 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); event handler. */ -static void airo_config(struct pcmcia_device *link); +static int airo_config(struct pcmcia_device *link); static void airo_release(struct pcmcia_device *link); /* @@ -141,7 +141,7 @@ typedef struct local_info_t { ======================================================================*/ -static int airo_attach(struct pcmcia_device *p_dev) +static int airo_probe(struct pcmcia_device *p_dev) { local_info_t *local; @@ -171,9 +171,7 @@ static int airo_attach(struct pcmcia_device *p_dev) p_dev->priv = local; p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - airo_config(p_dev); - - return 0; + return airo_config(p_dev); } /* airo_attach */ /*====================================================================== @@ -211,7 +209,7 @@ static void airo_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void airo_config(struct pcmcia_device *link) +static int airo_config(struct pcmcia_device *link) { tuple_t tuple; cisparse_t parse; @@ -386,12 +384,12 @@ static void airo_config(struct pcmcia_device *link) printk("\n"); link->state &= ~DEV_CONFIG_PENDING; - return; - + return 0; + cs_failed: cs_error(link, last_fn, last_ret); airo_release(link); - + return -ENODEV; } /* airo_config */ /*====================================================================== @@ -444,7 +442,7 @@ static struct pcmcia_driver airo_driver = { .drv = { .name = "airo_cs", }, - .probe = airo_attach, + .probe = airo_probe, .remove = airo_detach, .id_table = airo_ids, .suspend = airo_suspend, diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 843dd1a036..962272c134 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -91,7 +91,7 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards"); event handler. */ -static void atmel_config(struct pcmcia_device *link); +static int atmel_config(struct pcmcia_device *link); static void atmel_release(struct pcmcia_device *link); /* @@ -152,7 +152,7 @@ typedef struct local_info_t { ======================================================================*/ -static int atmel_attach(struct pcmcia_device *p_dev) +static int atmel_probe(struct pcmcia_device *p_dev) { local_info_t *local; @@ -182,9 +182,7 @@ static int atmel_attach(struct pcmcia_device *p_dev) p_dev->priv = local; p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - atmel_config(p_dev); - - return 0; + return atmel_config(p_dev); } /* atmel_attach */ /*====================================================================== @@ -230,7 +228,7 @@ static int card_present(void *arg) return 0; } -static void atmel_config(struct pcmcia_device *link) +static int atmel_config(struct pcmcia_device *link) { tuple_t tuple; cisparse_t parse; @@ -377,11 +375,12 @@ static void atmel_config(struct pcmcia_device *link) link->dev_node = &dev->node; link->state &= ~DEV_CONFIG_PENDING; - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); atmel_release(link); + return -ENODEV; } /*====================================================================== @@ -476,7 +475,7 @@ static struct pcmcia_driver atmel_driver = { .drv = { .name = "atmel_cs", }, - .probe = atmel_attach, + .probe = atmel_probe, .remove = atmel_detach, .id_table = atmel_ids, .suspend = atmel_suspend, diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 89b178106e..88dc383a3d 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -501,16 +501,20 @@ static struct prism2_helper_functions prism2_pccard_funcs = /* allocate local data and register with CardServices * initialize dev_link structure, but do not configure the card yet */ -static int prism2_attach(struct pcmcia_device *p_dev) +static int hostap_cs_probe(struct pcmcia_device *p_dev) { + int ret; + PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); p_dev->conf.IntType = INT_MEMORY_AND_IO; p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - if (prism2_config(p_dev)) + ret = prism2_config(p_dev); + if (ret) { PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n"); + } - return 0; + return ret; } @@ -894,7 +898,7 @@ static struct pcmcia_driver hostap_driver = { .drv = { .name = "hostap_cs", }, - .probe = prism2_attach, + .probe = hostap_cs_probe, .remove = prism2_detach, .owner = THIS_MODULE, .id_table = hostap_cs_ids, diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 2a688865f7..2689f3bbc8 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -191,7 +191,7 @@ module_param(mem_speed, int, 0); /* PCMCIA (Card Services) related functions */ static void netwave_release(struct pcmcia_device *link); /* Card removal */ -static void netwave_pcmcia_config(struct pcmcia_device *arg); /* Runs after card +static int netwave_pcmcia_config(struct pcmcia_device *arg); /* Runs after card insertion */ static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */ @@ -376,7 +376,7 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev) * configure the card at this point -- we wait until we receive a * card insertion event. */ -static int netwave_attach(struct pcmcia_device *link) +static int netwave_probe(struct pcmcia_device *link) { struct net_device *dev; netwave_private *priv; @@ -429,9 +429,7 @@ static int netwave_attach(struct pcmcia_device *link) link->irq.Instance = dev; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - netwave_pcmcia_config( link); - - return 0; + return netwave_pcmcia_config( link); } /* netwave_attach */ /* @@ -737,7 +735,7 @@ static const struct iw_handler_def netwave_handler_def = #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void netwave_pcmcia_config(struct pcmcia_device *link) { +static int netwave_pcmcia_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; netwave_private *priv = netdev_priv(dev); tuple_t tuple; @@ -845,12 +843,13 @@ static void netwave_pcmcia_config(struct pcmcia_device *link) { printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n", get_uint16(ramBase + NETWAVE_EREG_ARW), get_uint16(ramBase + NETWAVE_EREG_ARW+2)); - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: netwave_release(link); + return -ENODEV; } /* netwave_pcmcia_config */ /* @@ -1387,7 +1386,7 @@ static struct pcmcia_driver netwave_driver = { .drv = { .name = "netwave_cs", }, - .probe = netwave_attach, + .probe = netwave_probe, .remove = netwave_detach, .id_table = netwave_ids, .suspend = netwave_suspend, diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 405b7baa8b..0e92bee16c 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -63,7 +63,7 @@ struct orinoco_pccard { /* Function prototypes */ /********************************************************************/ -static void orinoco_cs_config(struct pcmcia_device *link); +static int orinoco_cs_config(struct pcmcia_device *link); static void orinoco_cs_release(struct pcmcia_device *link); static void orinoco_cs_detach(struct pcmcia_device *p_dev); @@ -104,7 +104,7 @@ orinoco_cs_hard_reset(struct orinoco_private *priv) * configure the card at this point -- we wait until we receive a card * insertion event. */ static int -orinoco_cs_attach(struct pcmcia_device *link) +orinoco_cs_probe(struct pcmcia_device *link) { struct net_device *dev; struct orinoco_private *priv; @@ -135,9 +135,7 @@ orinoco_cs_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - orinoco_cs_config(link); - - return 0; + return orinoco_cs_config(link); } /* orinoco_cs_attach */ /* @@ -172,7 +170,7 @@ static void orinoco_cs_detach(struct pcmcia_device *link) last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ } while (0) -static void +static int orinoco_cs_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; @@ -377,13 +375,14 @@ orinoco_cs_config(struct pcmcia_device *link) link->io.BasePort2 + link->io.NumPorts2 - 1); printk("\n"); - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: orinoco_cs_release(link); + return -ENODEV; } /* orinoco_cs_config */ /* @@ -576,7 +575,7 @@ static struct pcmcia_driver orinoco_driver = { .drv = { .name = DRIVER_NAME, }, - .probe = orinoco_cs_attach, + .probe = orinoco_cs_probe, .remove = orinoco_cs_detach, .id_table = orinoco_cs_ids, .suspend = orinoco_cs_suspend, diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 415ae8be1e..8cfe9332a3 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -90,7 +90,7 @@ module_param(pc_debug, int, 0); #define DEBUG(n, args...) #endif /** Prototypes based on PCMCIA skeleton driver *******************************/ -static void ray_config(struct pcmcia_device *link); +static int ray_config(struct pcmcia_device *link); static void ray_release(struct pcmcia_device *link); static void ray_detach(struct pcmcia_device *p_dev); @@ -303,7 +303,7 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey state |= DEV_PRESENT | DEV_CONFIG_PENDING; this_device = p_dev; - ray_config(p_dev); - - return 0; + return ray_config(p_dev); fail_alloc_dev: return -ENOMEM; @@ -412,7 +410,7 @@ static void ray_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) #define MAX_TUPLE_SIZE 128 -static void ray_config(struct pcmcia_device *link) +static int ray_config(struct pcmcia_device *link) { tuple_t tuple; cisparse_t parse; @@ -499,7 +497,7 @@ static void ray_config(struct pcmcia_device *link) DEBUG(3,"ray_config amem=%p\n",local->amem); if (ray_init(dev) < 0) { ray_release(link); - return; + return -ENODEV; } SET_NETDEV_DEV(dev, &handle_to_dev(link)); @@ -507,7 +505,7 @@ static void ray_config(struct pcmcia_device *link) if (i != 0) { printk("ray_config register_netdev() failed\n"); ray_release(link); - return; + return i; } strcpy(local->node.dev_name, dev->name); @@ -519,12 +517,13 @@ static void ray_config(struct pcmcia_device *link) for (i = 0; i < 6; i++) printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); ray_release(link); + return -ENODEV; } /* ray_config */ static inline struct ccs __iomem *ccs_base(ray_dev_t *dev) @@ -2846,7 +2845,7 @@ static struct pcmcia_driver ray_driver = { .drv = { .name = "ray_cs", }, - .probe = ray_attach, + .probe = ray_probe, .remove = ray_detach, .id_table = ray_ids, .suspend = ray_suspend, diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index a75ea7e593..118b2c6e5a 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -71,7 +71,7 @@ struct orinoco_pccard { /* Function prototypes */ /********************************************************************/ -static void spectrum_cs_config(struct pcmcia_device *link); +static int spectrum_cs_config(struct pcmcia_device *link); static void spectrum_cs_release(struct pcmcia_device *link); /********************************************************************/ @@ -583,7 +583,7 @@ spectrum_cs_hard_reset(struct orinoco_private *priv) * configure the card at this point -- we wait until we receive a card * insertion event. */ static int -spectrum_cs_attach(struct pcmcia_device *link) +spectrum_cs_probe(struct pcmcia_device *link) { struct net_device *dev; struct orinoco_private *priv; @@ -614,9 +614,7 @@ spectrum_cs_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - spectrum_cs_config(link); - - return 0; + return spectrum_cs_config(link); } /* spectrum_cs_attach */ /* @@ -647,7 +645,7 @@ static void spectrum_cs_detach(struct pcmcia_device *link) * device available to the system. */ -static void +static int spectrum_cs_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; @@ -857,13 +855,14 @@ spectrum_cs_config(struct pcmcia_device *link) link->io.BasePort2 + link->io.NumPorts2 - 1); printk("\n"); - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: spectrum_cs_release(link); + return -ENODEV; } /* spectrum_cs_config */ /* @@ -954,7 +953,7 @@ static struct pcmcia_driver orinoco_driver = { .drv = { .name = DRIVER_NAME, }, - .probe = spectrum_cs_attach, + .probe = spectrum_cs_probe, .remove = spectrum_cs_detach, .suspend = spectrum_cs_suspend, .resume = spectrum_cs_resume, diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 352d4a50b7..7373caf6e8 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4580,10 +4580,11 @@ wavelan_close(struct net_device * dev) * card insertion event. */ static int -wavelan_attach(struct pcmcia_device *p_dev) +wavelan_probe(struct pcmcia_device *p_dev) { struct net_device * dev; /* Interface generic data */ net_local * lp; /* Interface specific data */ + int ret; #ifdef DEBUG_CALLBACK_TRACE printk(KERN_DEBUG "-> wavelan_attach()\n"); @@ -4651,11 +4652,18 @@ wavelan_attach(struct pcmcia_device *p_dev) dev->mtu = WAVELAN_MTU; p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - if(wv_pcmcia_config(p_dev) && - wv_hw_config(dev)) - wv_init_info(dev); - else + ret = wv_pcmcia_config(p_dev); + if (ret) + return ret; + + ret = wv_hw_config(dev); + if (ret) { dev->irq = 0; + pcmcia_disable_device(p_dev); + return ret; + } + + wv_init_info(dev); #ifdef DEBUG_CALLBACK_TRACE printk(KERN_DEBUG "<- wavelan_attach()\n"); @@ -4760,7 +4768,7 @@ static struct pcmcia_driver wavelan_driver = { .drv = { .name = "wavelan_cs", }, - .probe = wavelan_attach, + .probe = wavelan_probe, .remove = wavelan_detach, .id_table = wavelan_ids, .suspend = wavelan_suspend, diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 752d222600..6b3a605897 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -103,7 +103,7 @@ module_param(pc_debug, int, 0); * release a socket, in response to card insertion and ejection events. They * are invoked from the wl24 event handler. */ -static void wl3501_config(struct pcmcia_device *link); +static int wl3501_config(struct pcmcia_device *link); static void wl3501_release(struct pcmcia_device *link); /* @@ -1920,7 +1920,7 @@ static const struct iw_handler_def wl3501_handler_def = { * The dev_link structure is initialized, but we don't actually configure the * card at this point -- we wait until we receive a card insertion event. */ -static int wl3501_attach(struct pcmcia_device *p_dev) +static int wl3501_probe(struct pcmcia_device *p_dev) { struct net_device *dev; struct wl3501_card *this; @@ -1960,9 +1960,7 @@ static int wl3501_attach(struct pcmcia_device *p_dev) p_dev->priv = p_dev->irq.Instance = dev; p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - wl3501_config(p_dev); - - return 0; + return wl3501_config(p_dev); out_link: return -ENOMEM; } @@ -1978,7 +1976,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) * received, to configure the PCMCIA socket, and to make the ethernet device * available to the system. */ -static void wl3501_config(struct pcmcia_device *link) +static int wl3501_config(struct pcmcia_device *link) { tuple_t tuple; cisparse_t parse; @@ -2082,13 +2080,13 @@ static void wl3501_config(struct pcmcia_device *link) spin_lock_init(&this->lock); init_waitqueue_head(&this->wait); netif_start_queue(dev); - goto out; + return 0; + cs_failed: cs_error(link, last_fn, last_ret); failed: wl3501_release(link); -out: - return; + return -ENODEV; } /** @@ -2146,7 +2144,7 @@ static struct pcmcia_driver wl3501_driver = { .drv = { .name = "wl3501_cs", }, - .probe = wl3501_attach, + .probe = wl3501_probe, .remove = wl3501_detach, .id_table = wl3501_ids, .suspend = wl3501_suspend, diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 6dcaf44c12..e4be826c48 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -88,7 +88,7 @@ typedef struct parport_info_t { } parport_info_t; static void parport_detach(struct pcmcia_device *p_dev); -static void parport_config(struct pcmcia_device *link); +static int parport_config(struct pcmcia_device *link); static void parport_cs_release(struct pcmcia_device *); /*====================================================================== @@ -99,7 +99,7 @@ static void parport_cs_release(struct pcmcia_device *); ======================================================================*/ -static int parport_attach(struct pcmcia_device *link) +static int parport_probe(struct pcmcia_device *link) { parport_info_t *info; @@ -120,9 +120,7 @@ static int parport_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - parport_config(link); - - return 0; + return parport_config(link); } /* parport_attach */ /*====================================================================== @@ -155,7 +153,7 @@ static void parport_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -void parport_config(struct pcmcia_device *link) +static int parport_config(struct pcmcia_device *link) { parport_info_t *info = link->priv; tuple_t tuple; @@ -236,14 +234,14 @@ void parport_config(struct pcmcia_device *link) link->dev_node = &info->node; link->state &= ~DEV_CONFIG_PENDING; - return; - + return 0; + cs_failed: cs_error(link, last_fn, last_ret); failed: parport_cs_release(link); link->state &= ~DEV_CONFIG_PENDING; - + return -ENODEV; } /* parport_config */ /*====================================================================== @@ -282,7 +280,7 @@ static struct pcmcia_driver parport_cs_driver = { .drv = { .name = "parport_cs", }, - .probe = parport_attach, + .probe = parport_probe, .remove = parport_detach, .id_table = parport_ids, }; diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 21c6b10145..7caa700cf1 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -96,11 +96,11 @@ typedef struct scsi_info_t { static void aha152x_release_cs(struct pcmcia_device *link); static void aha152x_detach(struct pcmcia_device *p_dev); -static void aha152x_config_cs(struct pcmcia_device *link); +static int aha152x_config_cs(struct pcmcia_device *link); static struct pcmcia_device *dev_list; -static int aha152x_attach(struct pcmcia_device *link) +static int aha152x_probe(struct pcmcia_device *link) { scsi_info_t *info; @@ -123,9 +123,7 @@ static int aha152x_attach(struct pcmcia_device *link) link->conf.Present = PRESENT_OPTION; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - aha152x_config_cs(link); - - return 0; + return aha152x_config_cs(link); } /* aha152x_attach */ /*====================================================================*/ @@ -146,7 +144,7 @@ static void aha152x_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void aha152x_config_cs(struct pcmcia_device *link) +static int aha152x_config_cs(struct pcmcia_device *link) { scsi_info_t *info = link->priv; struct aha152x_setup s; @@ -219,12 +217,12 @@ static void aha152x_config_cs(struct pcmcia_device *link) info->host = host; link->state &= ~DEV_CONFIG_PENDING; - return; - + return 0; + cs_failed: cs_error(link, last_fn, last_ret); aha152x_release_cs(link); - return; + return -ENODEV; } static void aha152x_release_cs(struct pcmcia_device *link) @@ -259,7 +257,7 @@ static struct pcmcia_driver aha152x_cs_driver = { .drv = { .name = "aha152x_cs", }, - .probe = aha152x_attach, + .probe = aha152x_probe, .remove = aha152x_detach, .id_table = aha152x_ids, .resume = aha152x_resume, @@ -278,4 +276,3 @@ static void __exit exit_aha152x_cs(void) module_init(init_aha152x_cs); module_exit(exit_aha152x_cs); - diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 4e6927112c..80afd3e879 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -81,33 +81,32 @@ typedef struct scsi_info_t { static void fdomain_release(struct pcmcia_device *link); static void fdomain_detach(struct pcmcia_device *p_dev); -static void fdomain_config(struct pcmcia_device *link); +static int fdomain_config(struct pcmcia_device *link); -static int fdomain_attach(struct pcmcia_device *link) +static int fdomain_probe(struct pcmcia_device *link) { - scsi_info_t *info; - - DEBUG(0, "fdomain_attach()\n"); - - /* Create new SCSI device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) return -ENOMEM; - memset(info, 0, sizeof(*info)); - info->p_dev = link; - link->priv = info; - link->io.NumPorts1 = 0x10; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.Present = PRESENT_OPTION; - - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - fdomain_config(link); - - return 0; + scsi_info_t *info; + + DEBUG(0, "fdomain_attach()\n"); + + /* Create new SCSI device */ + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->p_dev = link; + link->priv = info; + link->io.NumPorts1 = 0x10; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + link->io.IOAddrLines = 10; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_LEVEL_ID; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.IntType = INT_MEMORY_AND_IO; + link->conf.Present = PRESENT_OPTION; + + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + return fdomain_config(link); } /* fdomain_attach */ /*====================================================================*/ @@ -127,7 +126,7 @@ static void fdomain_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void fdomain_config(struct pcmcia_device *link) +static int fdomain_config(struct pcmcia_device *link) { scsi_info_t *info = link->priv; tuple_t tuple; @@ -150,7 +149,7 @@ static void fdomain_config(struct pcmcia_device *link) /* Configure card */ link->state |= DEV_CONFIG; - + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { @@ -167,35 +166,35 @@ static void fdomain_config(struct pcmcia_device *link) CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); - + /* A bad hack... */ release_region(link->io.BasePort1, link->io.NumPorts1); /* Set configuration options for the fdomain driver */ sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ); fdomain_setup(str); - + host = __fdomain_16x0_detect(&fdomain_driver_template); if (!host) { printk(KERN_INFO "fdomain_cs: no SCSI devices found\n"); goto cs_failed; } - - scsi_add_host(host, NULL); /* XXX handle failure */ + + if (scsi_add_host(host, NULL)) + goto cs_failed; scsi_scan_host(host); sprintf(info->node.dev_name, "scsi%d", host->host_no); link->dev_node = &info->node; info->host = host; - + link->state &= ~DEV_CONFIG_PENDING; - return; - + return 0; + cs_failed: cs_error(link, last_fn, last_ret); fdomain_release(link); - return; - + return -ENODEV; } /* fdomain_config */ /*====================================================================*/ @@ -234,7 +233,7 @@ static struct pcmcia_driver fdomain_cs_driver = { .drv = { .name = "fdomain_cs", }, - .probe = fdomain_attach, + .probe = fdomain_probe, .remove = fdomain_detach, .id_table = fdomain_ids, .resume = fdomain_resume, diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index ce4d7d868d..deec1c3a26 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1593,10 +1593,11 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt) configure the card at this point -- we wait until we receive a card insertion event. ======================================================================*/ -static int nsp_cs_attach(struct pcmcia_device *link) +static int nsp_cs_probe(struct pcmcia_device *link) { scsi_info_t *info; nsp_hw_data *data = &nsp_data_base; + int ret; nsp_dbg(NSP_DEBUG_INIT, "in"); @@ -1630,10 +1631,10 @@ static int nsp_cs_attach(struct pcmcia_device *link) link->conf.Present = PRESENT_OPTION; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - nsp_cs_config(link); + ret = nsp_cs_config(link); nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); - return 0; + return ret; } /* nsp_cs_attach */ @@ -1665,8 +1666,9 @@ static void nsp_cs_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) /*====================================================================*/ -static void nsp_cs_config(struct pcmcia_device *link) +static int nsp_cs_config(struct pcmcia_device *link) { + int ret; scsi_info_t *info = link->priv; tuple_t tuple; cisparse_t parse; @@ -1842,7 +1844,10 @@ static void nsp_cs_config(struct pcmcia_device *link) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74)) - scsi_add_host (host, NULL); + ret = scsi_add_host (host, NULL); + if (ret) + goto cs_failed; + scsi_scan_host(host); snprintf(info->node.dev_name, sizeof(info->node.dev_name), "scsi%d", host->host_no); @@ -1917,14 +1922,14 @@ static void nsp_cs_config(struct pcmcia_device *link) printk("\n"); link->state &= ~DEV_CONFIG_PENDING; - return; + return 0; cs_failed: nsp_dbg(NSP_DEBUG_INIT, "config fail"); cs_error(link, last_fn, last_ret); nsp_cs_release(link); - return; + return -ENODEV; } /* nsp_cs_config */ #undef CS_CHECK @@ -2033,7 +2038,7 @@ static struct pcmcia_driver nsp_driver = { .drv = { .name = "nsp_cs", }, - .probe = nsp_cs_attach, + .probe = nsp_cs_probe, .remove = nsp_cs_detach, .id_table = nsp_cs_ids, .suspend = nsp_cs_suspend, diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index ce348b379f..8908b8e5b7 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -298,7 +298,7 @@ typedef struct _nsp_hw_data { /* Card service functions */ static void nsp_cs_detach (struct pcmcia_device *p_dev); static void nsp_cs_release(struct pcmcia_device *link); -static void nsp_cs_config (struct pcmcia_device *link); +static int nsp_cs_config (struct pcmcia_device *link); /* Linux SCSI subsystem specific functions */ static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht); diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index a2a1c4b318..61c2eb03a9 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -99,7 +99,7 @@ typedef struct scsi_info_t { static void qlogic_release(struct pcmcia_device *link); static void qlogic_detach(struct pcmcia_device *p_dev); -static void qlogic_config(struct pcmcia_device * link); +static int qlogic_config(struct pcmcia_device * link); static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host, struct pcmcia_device *link, int qbase, int qlirq) @@ -156,7 +156,7 @@ free_scsi_host: err: return NULL; } -static int qlogic_attach(struct pcmcia_device *link) +static int qlogic_probe(struct pcmcia_device *link) { scsi_info_t *info; @@ -179,9 +179,7 @@ static int qlogic_attach(struct pcmcia_device *link) link->conf.Present = PRESENT_OPTION; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - qlogic_config(link); - - return 0; + return qlogic_config(link); } /* qlogic_attach */ /*====================================================================*/ @@ -202,7 +200,7 @@ static void qlogic_detach(struct pcmcia_device *link) #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void qlogic_config(struct pcmcia_device * link) +static int qlogic_config(struct pcmcia_device * link) { scsi_info_t *info = link->priv; tuple_t tuple; @@ -267,21 +265,20 @@ static void qlogic_config(struct pcmcia_device * link) if (!host) { printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name); - goto out; + goto cs_failed; } sprintf(info->node.dev_name, "scsi%d", host->host_no); link->dev_node = &info->node; info->host = host; -out: link->state &= ~DEV_CONFIG_PENDING; - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); pcmcia_disable_device(link); - return; + return -ENODEV; } /* qlogic_config */ @@ -350,7 +347,7 @@ static struct pcmcia_driver qlogic_cs_driver = { .drv = { .name = "qlogic_cs", }, - .probe = qlogic_attach, + .probe = qlogic_probe, .remove = qlogic_detach, .id_table = qlogic_ids, .resume = qlogic_resume, diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 49a37de687..b4432206a8 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -707,7 +707,7 @@ static struct scsi_host_template sym53c500_driver_template = { #define CS_CHECK(fn, ret) \ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -static void +static int SYM53C500_config(struct pcmcia_device *link) { struct scsi_info_t *info = link->priv; @@ -836,7 +836,8 @@ next_entry: scsi_scan_host(host); - goto out; /* SUCCESS */ + link->state &= ~DEV_CONFIG_PENDING; + return 0; err_free_irq: free_irq(irq_level, host); @@ -845,15 +846,13 @@ err_free_scsi: err_release: release_region(port_base, 0x10); printk(KERN_INFO "sym53c500_cs: no SCSI devices found\n"); - -out: link->state &= ~DEV_CONFIG_PENDING; - return; + return -ENODEV; cs_failed: cs_error(link, last_fn, last_ret); SYM53C500_release(link); - return; + return -ENODEV; } /* SYM53C500_config */ static int sym53c500_resume(struct pcmcia_device *link) @@ -892,7 +891,7 @@ SYM53C500_detach(struct pcmcia_device *link) } /* SYM53C500_detach */ static int -SYM53C500_attach(struct pcmcia_device *link) +SYM53C500_probe(struct pcmcia_device *link) { struct scsi_info_t *info; @@ -915,9 +914,7 @@ SYM53C500_attach(struct pcmcia_device *link) link->conf.Present = PRESENT_OPTION; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - SYM53C500_config(link); - - return 0; + return SYM53C500_config(link); } /* SYM53C500_attach */ MODULE_AUTHOR("Bob Tracy "); @@ -937,7 +934,7 @@ static struct pcmcia_driver sym53c500_cs_driver = { .drv = { .name = "sym53c500_cs", }, - .probe = SYM53C500_attach, + .probe = SYM53C500_probe, .remove = SYM53C500_detach, .id_table = sym53c500_ids, .resume = sym53c500_resume, diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 1fe8cafebe..e7875090dc 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -113,7 +113,7 @@ struct serial_cfg_mem { }; -static void serial_config(struct pcmcia_device * link); +static int serial_config(struct pcmcia_device * link); /*====================================================================== @@ -211,9 +211,7 @@ static int serial_probe(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - serial_config(link); - - return 0; + return serial_config(link); } /*====================================================================== @@ -553,7 +551,7 @@ free_cfg_mem: ======================================================================*/ -void serial_config(struct pcmcia_device * link) +static int serial_config(struct pcmcia_device * link) { struct serial_info *info = link->priv; struct serial_cfg_mem *cfg_mem; @@ -652,7 +650,7 @@ void serial_config(struct pcmcia_device * link) link->dev_node = &info->node[0]; link->state &= ~DEV_CONFIG_PENDING; kfree(cfg_mem); - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); @@ -660,6 +658,7 @@ void serial_config(struct pcmcia_device * link) serial_remove(link); link->state &= ~DEV_CONFIG_PENDING; kfree(cfg_mem); + return -ENODEV; } static struct pcmcia_device_id serial_ids[] = { diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index bad68187f2..a27df6101d 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -35,10 +35,10 @@ typedef struct ixj_info_t { } ixj_info_t; static void ixj_detach(struct pcmcia_device *p_dev); -static void ixj_config(struct pcmcia_device * link); +static int ixj_config(struct pcmcia_device * link); static void ixj_cs_release(struct pcmcia_device * link); -static int ixj_attach(struct pcmcia_device *p_dev) +static int ixj_probe(struct pcmcia_device *p_dev) { DEBUG(0, "ixj_attach()\n"); /* Create new ixj device */ @@ -53,9 +53,7 @@ static int ixj_attach(struct pcmcia_device *p_dev) memset(p_dev->priv, 0, sizeof(struct ixj_info_t)); p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - ixj_config(p_dev); - - return 0; + return ixj_config(p_dev); } static void ixj_detach(struct pcmcia_device *link) @@ -133,7 +131,7 @@ static void ixj_get_serial(struct pcmcia_device * link, IXJ * j) return; } -static void ixj_config(struct pcmcia_device * link) +static int ixj_config(struct pcmcia_device * link) { IXJ *j; ixj_info_t *info; @@ -198,10 +196,11 @@ static void ixj_config(struct pcmcia_device * link) link->dev_node = &info->node; ixj_get_serial(link, j); link->state &= ~DEV_CONFIG_PENDING; - return; + return 0; cs_failed: cs_error(link, last_fn, last_ret); ixj_cs_release(link); + return -ENODEV; } static void ixj_cs_release(struct pcmcia_device *link) @@ -223,7 +222,7 @@ static struct pcmcia_driver ixj_driver = { .drv = { .name = "ixj_cs", }, - .probe = ixj_attach, + .probe = ixj_probe, .remove = ixj_detach, .id_table = ixj_ids, }; diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index bfa8b213e1..e8b8e9a930 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -158,7 +158,7 @@ static void sl811_cs_release(struct pcmcia_device * link) platform_device_unregister(&platform_dev); } -static void sl811_cs_config(struct pcmcia_device *link) +static int sl811_cs_config(struct pcmcia_device *link) { struct device *parent = &handle_to_dev(link); local_info_t *dev = link->priv; @@ -285,10 +285,12 @@ cs_failed: cs_error(link, last_fn, last_ret); sl811_cs_release(link); link->state &= ~DEV_CONFIG_PENDING; + return -ENODEV; } + return 0; } -static int sl811_cs_attach(struct pcmcia_device *link) +static int sl811_cs_probe(struct pcmcia_device *link) { local_info_t *local; @@ -308,9 +310,7 @@ static int sl811_cs_attach(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - sl811_cs_config(link); - - return 0; + return sl811_cs_config(link); } static struct pcmcia_device_id sl811_ids[] = { @@ -324,7 +324,7 @@ static struct pcmcia_driver sl811_cs_driver = { .drv = { .name = (char *)driver_name, }, - .probe = sl811_cs_attach, + .probe = sl811_cs_probe, .remove = sl811_cs_detach, .id_table = sl811_ids, }; -- cgit v1.2.2 From b4c884000a7d3664dd8ad7227241456bd7824d86 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 18 Jan 2006 23:53:13 -0800 Subject: [PATCH] pcmcia: make pcmcia_release_{io,irq} static We can now make pcmcia_release_{io,irq} static. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 93ab9402d3..dbf167c979 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -511,7 +511,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) * don't bother checking the port ranges against the current socket * values. */ -int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) +static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) { struct pcmcia_socket *s = p_dev->socket; config_t *c = p_dev->function_config; @@ -537,7 +537,7 @@ int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) } /* pcmcia_release_io */ -int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) +static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) { struct pcmcia_socket *s = p_dev->socket; config_t *c= p_dev->function_config; -- cgit v1.2.2 From f6fbe01ac976f3ec618cd5fb71ad9ce2cfa7ab2b Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Fri, 20 Jan 2006 15:10:23 +0100 Subject: [PATCH] pcmcia: remove unused p_dev->state flags Remove the unused DEV_RELEASE_PENDING flag, and move the DEV_SUSPEND flag into the p_dev structure, and make use of it at the core level. Signed-off-by: Dominik Brodowski --- drivers/net/wireless/atmel_cs.c | 2 +- drivers/net/wireless/ray_cs.c | 2 +- drivers/net/wireless/wavelan_cs.c | 1 - drivers/pcmcia/ds.c | 48 ++++++++++++++++++++------------------- drivers/telephony/ixj_pcmcia.c | 1 - 5 files changed, 27 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 962272c134..d09b1472e6 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -220,7 +220,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) static int card_present(void *arg) { struct pcmcia_device *link = (struct pcmcia_device *)arg; - if (link->state & DEV_SUSPEND) + if (link->suspended) return 0; else if (link->state & DEV_PRESENT) return 1; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 8cfe9332a3..e3924339fa 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1968,7 +1968,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) local = (ray_dev_t *)dev->priv; link = (struct pcmcia_device *)local->finder; - if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) { + if ( ! (link->state & DEV_PRESENT) || link->suspended ) { DEBUG(2,"ray_cs interrupt from device not present or suspended.\n"); return IRQ_NONE; } diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 7373caf6e8..6b67696547 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -4744,7 +4744,6 @@ static int wavelan_resume(struct pcmcia_device *link) { struct net_device * dev = (struct net_device *) link->priv; - link->state &= ~DEV_SUSPEND; if ((link->state & DEV_CONFIG) && (link->open)) { wv_hw_reset(dev); netif_device_attach(dev); diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index e8fe544f2e..34e634aa48 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -945,7 +945,7 @@ static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); - if (p_dev->dev.power.power_state.event != PM_EVENT_ON) + if (p_dev->suspended) return sprintf(buf, "off\n"); else return sprintf(buf, "on\n"); @@ -960,11 +960,9 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute if (!count) return -EINVAL; - if ((p_dev->dev.power.power_state.event == PM_EVENT_ON) && - (!strncmp(buf, "off", 3))) + if ((!p_dev->suspended) && !strncmp(buf, "off", 3)) ret = dpm_runtime_suspend(dev, PMSG_SUSPEND); - else if ((p_dev->dev.power.power_state.event != PM_EVENT_ON) && - (!strncmp(buf, "on", 2))) + else if (p_dev->suspended && !strncmp(buf, "on", 2)) dpm_runtime_resume(dev); return ret ? ret : count; @@ -1030,7 +1028,7 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct pcmcia_driver *p_drv = NULL; - int ret; + int ret = 0; if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); @@ -1038,14 +1036,16 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) if (p_drv && p_drv->suspend) { ret = p_drv->suspend(p_dev); if (ret) - return ret; - p_dev->state |= DEV_SUSPEND; - if ((p_dev->state & DEV_CONFIG) && - !(p_dev->state & DEV_SUSPEND_NORELEASE)) - pcmcia_release_configuration(p_dev); + goto out; + if ((p_dev->state & DEV_CONFIG) && + !(p_dev->state & DEV_SUSPEND_NORELEASE)) + pcmcia_release_configuration(p_dev); } - return 0; + out: + if (!ret) + p_dev->suspended = 1; + return ret; } @@ -1053,24 +1053,26 @@ static int pcmcia_dev_resume(struct device * dev) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct pcmcia_driver *p_drv = NULL; - int ret; + int ret = 0; if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); if (p_drv && p_drv->resume) { - p_dev->state &= ~DEV_SUSPEND; - if ((p_dev->state & DEV_CONFIG) && - !(p_dev->state & DEV_SUSPEND_NORELEASE)){ - ret = pcmcia_request_configuration(p_dev, - &p_dev->conf); - if (ret) - return ret; - } - return p_drv->resume(p_dev); + if ((p_dev->state & DEV_CONFIG) && + !(p_dev->state & DEV_SUSPEND_NORELEASE)){ + ret = pcmcia_request_configuration(p_dev, + &p_dev->conf); + if (ret) + goto out; + } + ret = p_drv->resume(p_dev); } - return 0; + out: + if (!ret) + p_dev->suspended = 0; + return ret; } diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index a27df6101d..5c7611c2ac 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -60,7 +60,6 @@ static void ixj_detach(struct pcmcia_device *link) { DEBUG(0, "ixj_detach(0x%p)\n", link); - link->state &= ~DEV_RELEASE_PENDING; if (link->state & DEV_CONFIG) ixj_cs_release(link); -- cgit v1.2.2 From e2d4096365e06b9a3799afbadc28b4519c0b3526 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Thu, 2 Mar 2006 00:09:29 +0100 Subject: [PATCH] pcmcia: use bitfield instead of p_state and state Instead of the two status values struct pcmcia_device->p_state and state, use descriptive bitfields. Most value-checking in drivers was invalid, as the core now only calls the ->remove() (a.k.a. detach) function in case the attachement _and_ configuration was successful. Signed-off-by: Dominik Brodowski --- drivers/bluetooth/bluecard_cs.c | 14 ++----- drivers/bluetooth/bt3c_cs.c | 14 ++----- drivers/bluetooth/btuart_cs.c | 14 ++----- drivers/bluetooth/dtl1_cs.c | 13 ++---- drivers/char/pcmcia/cm4000_cs.c | 13 ++---- drivers/char/pcmcia/cm4040_cs.c | 16 ++------ drivers/char/pcmcia/synclink_cs.c | 28 +++++-------- drivers/ide/legacy/ide-cs.c | 9 +---- drivers/isdn/hardware/avm/avm_cs.c | 12 +----- drivers/isdn/hisax/avma1_cs.c | 17 ++------ drivers/isdn/hisax/elsa_cs.c | 19 +++------ drivers/isdn/hisax/sedlbauer_cs.c | 18 +++------ drivers/isdn/hisax/teles_cs.c | 19 +++------ drivers/mtd/maps/pcmciamtd.c | 27 +++++-------- drivers/net/pcmcia/3c574_cs.c | 12 ++---- drivers/net/pcmcia/3c589_cs.c | 12 ++---- drivers/net/pcmcia/axnet_cs.c | 15 ++----- drivers/net/pcmcia/com20020_cs.c | 12 ++---- drivers/net/pcmcia/fmvj18x_cs.c | 13 ++---- drivers/net/pcmcia/ibmtr_cs.c | 14 ++----- drivers/net/pcmcia/nmclan_cs.c | 13 ++---- drivers/net/pcmcia/pcnet_cs.c | 13 ++---- drivers/net/pcmcia/smc91c92_cs.c | 59 ++++++++++++--------------- drivers/net/pcmcia/xirc2ps_cs.c | 18 +++------ drivers/net/wireless/airo_cs.c | 16 ++------ drivers/net/wireless/atmel_cs.c | 25 ++++-------- drivers/net/wireless/hostap/hostap_cs.c | 56 +++++++++++--------------- drivers/net/wireless/netwave_cs.c | 12 ++---- drivers/net/wireless/orinoco_cs.c | 70 ++++++++++++++------------------- drivers/net/wireless/ray_cs.c | 53 +++++++++++-------------- drivers/net/wireless/spectrum_cs.c | 37 +++++++---------- drivers/net/wireless/wavelan_cs.c | 24 +++-------- drivers/net/wireless/wl3501_cs.c | 19 +++------ drivers/parport/parport_cs.c | 9 +---- drivers/pcmcia/cs_internal.h | 2 +- drivers/pcmcia/ds.c | 41 +++++++++---------- drivers/pcmcia/pcmcia_ioctl.c | 4 +- drivers/pcmcia/pcmcia_resource.c | 24 +++++------ drivers/scsi/pcmcia/aha152x_stub.c | 8 +--- drivers/scsi/pcmcia/fdomain_stub.c | 11 +----- drivers/scsi/pcmcia/nsp_cs.c | 23 +---------- drivers/scsi/pcmcia/qlogic_stub.c | 33 ++++++---------- drivers/scsi/pcmcia/sym53c500_cs.c | 35 ++++++----------- drivers/serial/serial_cs.c | 35 +++++------------ drivers/telephony/ixj_pcmcia.c | 6 +-- drivers/usb/host/sl811_cs.c | 11 +----- 46 files changed, 311 insertions(+), 657 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 50174fb107..473a13b22b 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -244,7 +244,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info) clear_bit(XMIT_WAKEUP, &(info->tx_state)); - if (!(info->p_dev->state & DEV_PRESENT)) + if (!pcmcia_dev_present(info->p_dev)) return; if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) { @@ -879,7 +879,6 @@ static int bluecard_probe(struct pcmcia_device *link) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return bluecard_config(link); } @@ -888,9 +887,7 @@ static void bluecard_detach(struct pcmcia_device *link) { bluecard_info_t *info = link->priv; - if (link->state & DEV_CONFIG) - bluecard_release(link); - + bluecard_release(link); kfree(info); } @@ -933,9 +930,6 @@ static int bluecard_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - link->conf.ConfigIndex = 0x20; link->io.NumPorts1 = 64; link->io.IOAddrLines = 6; @@ -969,7 +963,6 @@ static int bluecard_config(struct pcmcia_device *link) strcpy(info->node.dev_name, info->hdev->name); link->dev_node = &info->node; - link->state &= ~DEV_CONFIG_PENDING; return 0; @@ -986,8 +979,7 @@ static void bluecard_release(struct pcmcia_device *link) { bluecard_info_t *info = link->priv; - if (link->state & DEV_PRESENT) - bluecard_close(info); + bluecard_close(info); del_timer(&(info->timer)); diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 80861f4f35..b94ac2f9f7 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -195,7 +195,7 @@ static void bt3c_write_wakeup(bt3c_info_t *info) register struct sk_buff *skb; register int len; - if (!(info->p_dev->state & DEV_PRESENT)) + if (!pcmcia_dev_present(info->p_dev)) break; @@ -668,7 +668,6 @@ static int bt3c_probe(struct pcmcia_device *link) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return bt3c_config(link); } @@ -677,9 +676,7 @@ static void bt3c_detach(struct pcmcia_device *link) { bt3c_info_t *info = link->priv; - if (link->state & DEV_CONFIG) - bt3c_release(link); - + bt3c_release(link); kfree(info); } @@ -733,9 +730,6 @@ static int bt3c_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - /* First pass: look for a config entry that looks normal. */ tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; @@ -805,7 +799,6 @@ found_port: strcpy(info->node.dev_name, info->hdev->name); link->dev_node = &info->node; - link->state &= ~DEV_CONFIG_PENDING; return 0; @@ -822,8 +815,7 @@ static void bt3c_release(struct pcmcia_device *link) { bt3c_info_t *info = link->priv; - if (link->state & DEV_PRESENT) - bt3c_close(info); + bt3c_close(info); pcmcia_disable_device(link); } diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 658a137369..9ce4c93467 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -152,7 +152,7 @@ static void btuart_write_wakeup(btuart_info_t *info) clear_bit(XMIT_WAKEUP, &(info->tx_state)); - if (!(info->p_dev->state & DEV_PRESENT)) + if (!pcmcia_dev_present(info->p_dev)) return; if (!(skb = skb_dequeue(&(info->txq)))) @@ -599,7 +599,6 @@ static int btuart_probe(struct pcmcia_device *link) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return btuart_config(link); } @@ -608,9 +607,7 @@ static void btuart_detach(struct pcmcia_device *link) { btuart_info_t *info = link->priv; - if (link->state & DEV_CONFIG) - btuart_release(link); - + btuart_release(link); kfree(info); } @@ -664,9 +661,6 @@ static int btuart_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - /* First pass: look for a config entry that looks normal. */ tuple.TupleData = (cisdata_t *) buf; tuple.TupleOffset = 0; @@ -737,7 +731,6 @@ found_port: strcpy(info->node.dev_name, info->hdev->name); link->dev_node = &info->node; - link->state &= ~DEV_CONFIG_PENDING; return 0; @@ -754,8 +747,7 @@ static void btuart_release(struct pcmcia_device *link) { btuart_info_t *info = link->priv; - if (link->state & DEV_PRESENT) - btuart_close(info); + btuart_close(info); pcmcia_disable_device(link); } diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 0ec7fd4c92..a71a240611 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -159,7 +159,7 @@ static void dtl1_write_wakeup(dtl1_info_t *info) clear_bit(XMIT_WAKEUP, &(info->tx_state)); - if (!(info->p_dev->state & DEV_PRESENT)) + if (!pcmcia_dev_present(info->p_dev)) return; if (!(skb = skb_dequeue(&(info->txq)))) @@ -578,7 +578,6 @@ static int dtl1_probe(struct pcmcia_device *link) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return dtl1_config(link); } @@ -587,8 +586,7 @@ static void dtl1_detach(struct pcmcia_device *link) { dtl1_info_t *info = link->priv; - if (link->state & DEV_CONFIG) - dtl1_release(link); + dtl1_release(link); kfree(info); } @@ -642,9 +640,6 @@ static int dtl1_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; @@ -689,7 +684,6 @@ static int dtl1_config(struct pcmcia_device *link) strcpy(info->node.dev_name, info->hdev->name); link->dev_node = &info->node; - link->state &= ~DEV_CONFIG_PENDING; return 0; @@ -706,8 +700,7 @@ static void dtl1_release(struct pcmcia_device *link) { dtl1_info_t *info = link->priv; - if (link->state & DEV_PRESENT) - dtl1_close(info); + dtl1_close(info); pcmcia_disable_device(link); } diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 22dce9d47b..16e105d8d7 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -971,7 +971,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count, if (count == 0) /* according to manpage */ return 0; - if ((dev->p_dev->state & DEV_PRESENT) == 0 || /* socket removed */ + if (!pcmcia_dev_present(dev->p_dev) || /* device removed */ test_bit(IS_CMM_ABSENT, &dev->flags)) return -ENODEV; @@ -1108,7 +1108,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, sendT0 = dev->proto ? 0 : nr > 5 ? 0x08 : 0; - if ((dev->p_dev->state & DEV_PRESENT) == 0 || /* socket removed */ + if (!pcmcia_dev_present(dev->p_dev) || /* device removed */ test_bit(IS_CMM_ABSENT, &dev->flags)) return -ENODEV; @@ -1789,7 +1789,6 @@ static int cm4000_config(struct pcmcia_device * link, int devno) goto cs_failed; } - link->state |= DEV_CONFIG; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -1844,7 +1843,6 @@ static int cm4000_config(struct pcmcia_device * link, int devno) dev->node.minor = devno; dev->node.next = NULL; link->dev_node = &dev->node; - link->state &= ~DEV_CONFIG_PENDING; return 0; @@ -1852,8 +1850,6 @@ cs_failed: cs_error(link, fail_fn, fail_rc); cs_release: cm4000_release(link); - - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } @@ -1913,7 +1909,6 @@ static int cm4000_probe(struct pcmcia_device *link) init_waitqueue_head(&dev->atrq); init_waitqueue_head(&dev->readq); - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; ret = cm4000_config(link, i); if (ret) return ret; @@ -1936,11 +1931,9 @@ static void cm4000_detach(struct pcmcia_device *link) if (devno == CM4000_MAX_DEV) return; - link->state &= ~DEV_PRESENT; stop_monitor(dev); - if (link->state & DEV_CONFIG) - cm4000_release(link); + cm4000_release(link); dev_table[devno] = NULL; kfree(dev); diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 6ccca8cbab..74609c3b2b 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -246,7 +246,7 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf, return -EAGAIN; } - if ((dev->p_dev->state & DEV_PRESENT)==0) + if (!pcmcia_dev_present(dev->p_dev)) return -ENODEV; for (i = 0; i < 5; i++) { @@ -351,7 +351,7 @@ static ssize_t cm4040_write(struct file *filp, const char __user *buf, return -EAGAIN; } - if ((dev->p_dev->state & DEV_PRESENT) == 0) + if (!pcmcia_dev_present(dev->p_dev)) return -ENODEV; bytes_to_write = count; @@ -543,7 +543,6 @@ static int reader_config(struct pcmcia_device *link, int devno) goto cs_failed; } - link->state |= DEV_CONFIG; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -602,9 +601,7 @@ static int reader_config(struct pcmcia_device *link, int devno) sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); dev->node.major = major; dev->node.minor = devno; - dev->node.next = NULL; - link->dev_node = &dev->node; - link->state &= ~DEV_CONFIG_PENDING; + dev->node.next = &dev->node; DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno, link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1); @@ -616,7 +613,6 @@ cs_failed: cs_error(link, fail_fn, fail_rc); cs_release: reader_release(link); - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } @@ -659,7 +655,6 @@ static int reader_probe(struct pcmcia_device *link) init_timer(&dev->poll_timer); dev->poll_timer.function = &cm4040_do_poll; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; ret = reader_config(link, i); if (ret) return ret; @@ -683,10 +678,7 @@ static void reader_detach(struct pcmcia_device *link) if (devno == CM_MAX_DEV) return; - link->state &= ~DEV_PRESENT; - - if (link->state & DEV_CONFIG) - reader_release(link); + reader_release(link); dev_table[devno] = NULL; kfree(dev); diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index ef7a81314f..07213454c4 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -578,7 +578,6 @@ static int mgslpc_probe(struct pcmcia_device *link) link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; ret = mgslpc_config(link); if (ret) return ret; @@ -618,9 +617,6 @@ static int mgslpc_config(struct pcmcia_device *link) CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; /* get CIS configuration entry */ @@ -681,8 +677,6 @@ static int mgslpc_config(struct pcmcia_device *link) printk(", io 0x%04x-0x%04x", link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1-1); printk("\n"); - - link->state &= ~DEV_CONFIG_PENDING; return 0; cs_failed: @@ -697,25 +691,23 @@ cs_failed: */ static void mgslpc_release(u_long arg) { - struct pcmcia_device *link = (struct pcmcia_device *)arg; + struct pcmcia_device *link = (struct pcmcia_device *)arg; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_release(0x%p)\n", link); + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_release(0x%p)\n", link); - pcmcia_disable_device(link); + pcmcia_disable_device(link); } static void mgslpc_detach(struct pcmcia_device *link) { - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_detach(0x%p)\n", link); + if (debug_level >= DEBUG_LEVEL_INFO) + printk("mgslpc_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) { - ((MGSLPC_INFO *)link->priv)->stop = 1; - mgslpc_release((u_long)link); - } + ((MGSLPC_INFO *)link->priv)->stop = 1; + mgslpc_release((u_long)link); - mgslpc_remove_device((MGSLPC_INFO *)link->priv); + mgslpc_remove_device((MGSLPC_INFO *)link->priv); } static int mgslpc_suspend(struct pcmcia_device *link) @@ -1254,7 +1246,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs) if (!info) return IRQ_NONE; - if (!(info->p_dev->state & DEV_CONFIG)) + if (!(info->p_dev->_locked)) return IRQ_HANDLED; spin_lock(&info->lock); diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 56c8e828c6..4961f1e764 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -125,7 +125,6 @@ static int ide_probe(struct pcmcia_device *link) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return ide_config(link); } /* ide_attach */ @@ -142,8 +141,7 @@ static void ide_detach(struct pcmcia_device *link) { DEBUG(0, "ide_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) - ide_release(link); + ide_release(link); kfree(link->priv); } /* ide_detach */ @@ -209,9 +207,6 @@ static int ide_config(struct pcmcia_device *link) ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); - /* Configure card */ - link->state |= DEV_CONFIG; - /* Not sure if this is right... look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf)); @@ -323,7 +318,6 @@ static int ide_config(struct pcmcia_device *link) printk(KERN_INFO "ide-cs: %s: Vpp = %d.%d\n", info->node.dev_name, link->conf.Vpp / 10, link->conf.Vpp % 10); - link->state &= ~DEV_CONFIG_PENDING; kfree(stk); return 0; @@ -336,7 +330,6 @@ cs_failed: failed: kfree(stk); ide_release(link); - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } /* ide_config */ diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 28f9211726..7bbfd85ab7 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -127,7 +127,6 @@ static int avmcs_probe(struct pcmcia_device *p_dev) memset(local, 0, sizeof(local_info_t)); p_dev->priv = local; - p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return avmcs_config(p_dev); err: @@ -145,10 +144,8 @@ static int avmcs_probe(struct pcmcia_device *p_dev) static void avmcs_detach(struct pcmcia_device *link) { - if (link->state & DEV_CONFIG) avmcs_release(link); - - kfree(link->priv); + kfree(link->priv); } /* avmcs_detach */ /*====================================================================== @@ -216,12 +213,8 @@ static int avmcs_config(struct pcmcia_device *link) } while (0); if (i != CS_SUCCESS) { cs_error(link, ParseTuple, i); - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } - - /* Configure card */ - link->state |= DEV_CONFIG; do { @@ -312,8 +305,7 @@ found_port: dev->node.major = 64; dev->node.minor = 0; link->dev_node = &dev->node; - - link->state &= ~DEV_CONFIG_PENDING; + /* If any step failed, release any partially configured state */ if (i != 0) { avmcs_release(link); diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 11c7c4f09e..ac28e3278a 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -149,7 +149,6 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) p_dev->conf.ConfigIndex = 1; p_dev->conf.Present = PRESENT_OPTION; - p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return avma1cs_config(p_dev); } /* avma1cs_attach */ @@ -164,12 +163,9 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) static void avma1cs_detach(struct pcmcia_device *link) { - DEBUG(0, "avma1cs_detach(0x%p)\n", link); - - if (link->state & DEV_CONFIG) - avma1cs_release(link); - - kfree(link->priv); + DEBUG(0, "avma1cs_detach(0x%p)\n", link); + avma1cs_release(link); + kfree(link->priv); } /* avma1cs_detach */ /*====================================================================== @@ -239,12 +235,8 @@ static int avma1cs_config(struct pcmcia_device *link) } while (0); if (i != CS_SUCCESS) { cs_error(link, ParseTuple, i); - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } - - /* Configure card */ - link->state |= DEV_CONFIG; do { @@ -318,8 +310,7 @@ found_port: dev->node.major = 45; dev->node.minor = 0; link->dev_node = &dev->node; - - link->state &= ~DEV_CONFIG_PENDING; + /* If any step failed, release any partially configured state */ if (i != 0) { avma1cs_release(link); diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index 4856680ce7..e18e75be8e 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -174,7 +174,6 @@ static int elsa_cs_probe(struct pcmcia_device *link) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return elsa_cs_config(link); } /* elsa_cs_attach */ @@ -189,17 +188,14 @@ static int elsa_cs_probe(struct pcmcia_device *link) static void elsa_cs_detach(struct pcmcia_device *link) { - local_info_t *info = link->priv; + local_info_t *info = link->priv; - DEBUG(0, "elsa_cs_detach(0x%p)\n", link); + DEBUG(0, "elsa_cs_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) { - info->busy = 1; - elsa_cs_release(link); - } - - kfree(info); + info->busy = 1; + elsa_cs_release(link); + kfree(info); } /* elsa_cs_detach */ /*====================================================================== @@ -263,9 +259,6 @@ static int elsa_cs_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; @@ -329,8 +322,6 @@ static int elsa_cs_config(struct pcmcia_device *link) link->io.BasePort2+link->io.NumPorts2-1); printk("\n"); - link->state &= ~DEV_CONFIG_PENDING; - icard.para[0] = link->irq.AssignedIRQ; icard.para[1] = link->io.BasePort1; icard.protocol = protocol; diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index a35a29586a..9bb18f3f78 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -186,7 +186,6 @@ static int sedlbauer_probe(struct pcmcia_device *link) link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return sedlbauer_config(link); } /* sedlbauer_attach */ @@ -201,15 +200,13 @@ static int sedlbauer_probe(struct pcmcia_device *link) static void sedlbauer_detach(struct pcmcia_device *link) { - DEBUG(0, "sedlbauer_detach(0x%p)\n", link); + DEBUG(0, "sedlbauer_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) { - ((local_info_t *)link->priv)->stop = 1; - sedlbauer_release(link); - } + ((local_info_t *)link->priv)->stop = 1; + sedlbauer_release(link); - /* This points to the parent local_info_t struct */ - kfree(link->priv); + /* This points to the parent local_info_t struct */ + kfree(link->priv); } /* sedlbauer_detach */ /*====================================================================== @@ -250,9 +247,6 @@ static int sedlbauer_config(struct pcmcia_device *link) CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); @@ -408,8 +402,6 @@ static int sedlbauer_config(struct pcmcia_device *link) printk(", mem 0x%06lx-0x%06lx", req.Base, req.Base+req.Size-1); printk("\n"); - - link->state &= ~DEV_CONFIG_PENDING; icard.para[0] = link->irq.AssignedIRQ; icard.para[1] = link->io.BasePort1; diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 7b66038096..afcc2aeadb 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -164,7 +164,6 @@ static int teles_probe(struct pcmcia_device *link) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return teles_cs_config(link); } /* teles_attach */ @@ -179,17 +178,14 @@ static int teles_probe(struct pcmcia_device *link) static void teles_detach(struct pcmcia_device *link) { - local_info_t *info = link->priv; + local_info_t *info = link->priv; - DEBUG(0, "teles_detach(0x%p)\n", link); + DEBUG(0, "teles_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) { - info->busy = 1; - teles_cs_release(link); - } - - kfree(info); + info->busy = 1; + teles_cs_release(link); + kfree(info); } /* teles_detach */ /*====================================================================== @@ -253,9 +249,6 @@ static int teles_cs_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; @@ -319,8 +312,6 @@ static int teles_cs_config(struct pcmcia_device *link) link->io.BasePort2+link->io.NumPorts2-1); printk("\n"); - link->state &= ~DEV_CONFIG_PENDING; - icard.para[0] = link->irq.AssignedIRQ; icard.para[1] = link->io.BasePort1; icard.protocol = protocol; diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 466f558aa7..a01e04bf48 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -111,8 +111,8 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) memreq_t mrq; int ret; - if(!(dev->p_dev->state & DEV_PRESENT)) { - DEBUG(1, "device removed state = 0x%4.4X", dev->p_dev->state); + if (!pcmcia_dev_present(dev->p_dev)) { + DEBUG(1, "device removed"); return 0; } @@ -238,7 +238,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v /* read/write{8,16} copy_{from,to} routines with direct access */ -#define DEV_REMOVED(x) (!(*(u_int *)x->map_priv_1 & DEV_PRESENT)) +#define DEV_REMOVED(x) (!(pcmcia_dev_present(((struct pcmciamtd_dev *)map->map_priv_1)->p_dev))) static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) { @@ -503,9 +503,6 @@ static int pcmciamtd_config(struct pcmcia_device *link) DEBUG(3, "link=0x%p", link); - /* Configure card */ - link->state |= DEV_CONFIG; - DEBUG(2, "Validating CIS"); ret = pcmcia_validate_cis(link, &cisinfo); if(ret != CS_SUCCESS) { @@ -651,7 +648,6 @@ static int pcmciamtd_config(struct pcmcia_device *link) use the faster non-remapping read/write functions */ if(mtd->size <= dev->win_size) { DEBUG(1, "Using non remapping memory functions"); - dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->p_dev->state); dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base; if (dev->pcmcia_map.bankwidth == 1) { dev->pcmcia_map.read = pcmcia_read8; @@ -673,7 +669,6 @@ static int pcmciamtd_config(struct pcmcia_device *link) } snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index); info("mtd%d: %s", mtd->index, mtd->name); - link->state &= ~DEV_CONFIG_PENDING; link->dev_node = &dev->node; return 0; @@ -712,17 +707,16 @@ static int pcmciamtd_resume(struct pcmcia_device *dev) static void pcmciamtd_detach(struct pcmcia_device *link) { - DEBUG(3, "link=0x%p", link); + struct pcmciamtd_dev *dev = link->priv; - if(link->state & DEV_CONFIG) { - struct pcmciamtd_dev *dev = link->priv; - if(dev->mtd_info) { - del_mtd_device(dev->mtd_info); - info("mtd%d: Removed", dev->mtd_info->index); - } + DEBUG(3, "link=0x%p", link); - pcmciamtd_release(link); + if(dev->mtd_info) { + del_mtd_device(dev->mtd_info); + info("mtd%d: Removed", dev->mtd_info->index); } + + pcmciamtd_release(link); } @@ -747,7 +741,6 @@ static int pcmciamtd_probe(struct pcmcia_device *link) link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return pcmciamtd_config(link); } diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 4611469fdf..70e3cca097 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -296,7 +296,6 @@ static int tc574_probe(struct pcmcia_device *link) dev->watchdog_timeo = TX_TIMEOUT; #endif - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return tc574_config(link); } /* tc574_attach */ @@ -318,8 +317,7 @@ static void tc574_detach(struct pcmcia_device *link) if (link->dev_node) unregister_netdev(dev); - if (link->state & DEV_CONFIG) - tc574_release(link); + tc574_release(link); free_netdev(dev); } /* tc574_detach */ @@ -363,9 +361,6 @@ static int tc574_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - link->io.IOAddrLines = 16; for (i = j = 0; j < 0x400; j += 0x20) { link->io.BasePort1 = j ^ 0x300; @@ -464,7 +459,6 @@ static int tc574_config(struct pcmcia_device *link) } } - link->state &= ~DEV_CONFIG_PENDING; link->dev_node = &lp->node; SET_NETDEV_DEV(dev, &handle_to_dev(link)); @@ -509,7 +503,7 @@ static int tc574_suspend(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); return 0; @@ -519,7 +513,7 @@ static int tc574_resume(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { tc574_reset(dev); netif_device_attach(dev); } diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 160d48a8ed..3d05f66e9c 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -211,7 +211,6 @@ static int tc589_probe(struct pcmcia_device *link) #endif SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return tc589_config(link); } /* tc589_attach */ @@ -233,8 +232,7 @@ static void tc589_detach(struct pcmcia_device *link) if (link->dev_node) unregister_netdev(dev); - if (link->state & DEV_CONFIG) - tc589_release(link); + tc589_release(link); free_netdev(dev); } /* tc589_detach */ @@ -285,9 +283,6 @@ static int tc589_config(struct pcmcia_device *link) "3Com card??\n"); multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562); } - - /* Configure card */ - link->state |= DEV_CONFIG; /* For the 3c562, the base address must be xx00-xx7f */ link->io.IOAddrLines = 16; @@ -338,7 +333,6 @@ static int tc589_config(struct pcmcia_device *link) printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); link->dev_node = &lp->node; - link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { @@ -383,7 +377,7 @@ static int tc589_suspend(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); return 0; @@ -393,7 +387,7 @@ static int tc589_resume(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { tc589_reset(dev); netif_device_attach(dev); } diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index f6ca85d77c..0f1219c118 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -168,7 +168,6 @@ static int axnet_probe(struct pcmcia_device *link) dev->do_ioctl = &axnet_ioctl; SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return axnet_config(link); } /* axnet_attach */ @@ -190,8 +189,7 @@ static void axnet_detach(struct pcmcia_device *link) if (link->dev_node) unregister_netdev(dev); - if (link->state & DEV_CONFIG) - axnet_release(link); + axnet_release(link); free_netdev(dev); } /* axnet_detach */ @@ -309,9 +307,6 @@ static int axnet_config(struct pcmcia_device *link) /* don't trust the CIS on this; Linksys got it wrong */ link->conf.Present = 0x63; - /* Configure card */ - link->state |= DEV_CONFIG; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); @@ -402,7 +397,6 @@ static int axnet_config(struct pcmcia_device *link) info->phy_id = (i < 32) ? i : -1; link->dev_node = &info->node; - link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { @@ -429,7 +423,6 @@ cs_failed: cs_error(link, last_fn, last_ret); failed: axnet_release(link); - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } /* axnet_config */ @@ -450,8 +443,8 @@ static int axnet_suspend(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) - netif_device_detach(dev); + if (link->open) + netif_device_detach(dev); return 0; } @@ -460,7 +453,7 @@ static int axnet_resume(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { axnet_reset_8390(dev); AX88190_init(dev, 1); netif_device_attach(dev); diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index a7d675bc60..441de824ab 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -178,7 +178,6 @@ static int com20020_probe(struct pcmcia_device *p_dev) p_dev->irq.Instance = info->dev = dev; p_dev->priv = info; - p_dev->state |= DEV_PRESENT; return com20020_config(p_dev); fail_alloc_dev: @@ -218,8 +217,7 @@ static void com20020_detach(struct pcmcia_device *link) free_irq(dev->irq, dev); } - if (link->state & DEV_CONFIG) - com20020_release(link); + com20020_release(link); /* Unlink device structure, free bits */ DEBUG(1,"unlinking...\n"); @@ -276,9 +274,6 @@ static int com20020_config(struct pcmcia_device *link) CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; - /* Configure card */ - link->state |= DEV_CONFIG; - DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1); i = !CS_SUCCESS; if (!link->io.BasePort1) @@ -328,7 +323,6 @@ static int com20020_config(struct pcmcia_device *link) lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ link->dev_node = &info->node; - link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(link)); i = com20020_found(dev, 0); /* calls register_netdev */ @@ -372,7 +366,7 @@ static int com20020_suspend(struct pcmcia_device *link) com20020_dev_t *info = link->priv; struct net_device *dev = info->dev; - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); return 0; @@ -383,7 +377,7 @@ static int com20020_resume(struct pcmcia_device *link) com20020_dev_t *info = link->priv; struct net_device *dev = info->dev; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { int ioaddr = dev->base_addr; struct arcnet_local *lp = dev->priv; ARCRESET; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index d9c83b2900..7cb20b6b93 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -272,7 +272,6 @@ static int fmvj18x_probe(struct pcmcia_device *link) #endif SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return fmvj18x_config(link); } /* fmvj18x_attach */ @@ -287,8 +286,7 @@ static void fmvj18x_detach(struct pcmcia_device *link) if (link->dev_node) unregister_netdev(dev); - if (link->state & DEV_CONFIG) - fmvj18x_release(link); + fmvj18x_release(link); free_netdev(dev); } /* fmvj18x_detach */ @@ -363,9 +361,6 @@ static int fmvj18x_config(struct pcmcia_device *link) tuple.TupleOffset = 0; CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - - /* Configure card */ - link->state |= DEV_CONFIG; link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; @@ -532,7 +527,6 @@ static int fmvj18x_config(struct pcmcia_device *link) lp->cardtype = cardtype; link->dev_node = &lp->node; - link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { @@ -557,7 +551,6 @@ cs_failed: cs_error(link, last_fn, last_ret); failed: fmvj18x_release(link); - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } /* fmvj18x_config */ /*====================================================================*/ @@ -668,7 +661,7 @@ static int fmvj18x_suspend(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); return 0; @@ -678,7 +671,7 @@ static int fmvj18x_resume(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { fjn_reset(dev); netif_device_attach(dev); } diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index e038d9278a..b8fe70b856 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -173,7 +173,6 @@ static int ibmtr_attach(struct pcmcia_device *link) SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - link->state |= DEV_PRESENT; return ibmtr_config(link); } /* ibmtr_attach */ @@ -200,8 +199,8 @@ static void ibmtr_detach(struct pcmcia_device *link) struct tok_info *ti = netdev_priv(dev); del_timer_sync(&(ti->tr_timer)); } - if (link->state & DEV_CONFIG) - ibmtr_release(link); + + ibmtr_release(link); free_netdev(dev); kfree(info); @@ -241,10 +240,6 @@ static int ibmtr_config(struct pcmcia_device *link) CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; - - /* Configure card */ - link->state |= DEV_CONFIG; - link->conf.ConfigIndex = 0x61; /* Determine if this is PRIMARY or ALTERNATE. */ @@ -301,7 +296,6 @@ static int ibmtr_config(struct pcmcia_device *link) ibmtr_hw_setup(dev, mmiobase); link->dev_node = &info->node; - link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(link)); i = ibmtr_probe_card(dev); @@ -358,7 +352,7 @@ static int ibmtr_suspend(struct pcmcia_device *link) ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); return 0; @@ -369,7 +363,7 @@ static int ibmtr_resume(struct pcmcia_device *link) ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { ibmtr_probe(dev); /* really? */ netif_device_attach(dev); } diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index ea8a62e629..fd191143cb 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -487,7 +487,6 @@ static int nmclan_probe(struct pcmcia_device *link) dev->watchdog_timeo = TX_TIMEOUT; #endif - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return nmclan_config(link); } /* nmclan_attach */ @@ -508,8 +507,7 @@ static void nmclan_detach(struct pcmcia_device *link) if (link->dev_node) unregister_netdev(dev); - if (link->state & DEV_CONFIG) - nmclan_release(link); + nmclan_release(link); free_netdev(dev); } /* nmclan_detach */ @@ -675,9 +673,6 @@ static int nmclan_config(struct pcmcia_device *link) CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; - /* Configure card */ - link->state |= DEV_CONFIG; - CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); @@ -707,7 +702,6 @@ static int nmclan_config(struct pcmcia_device *link) } else { printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should" " be 0x40 0x?9\n", sig[0], sig[1]); - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } } @@ -722,7 +716,6 @@ static int nmclan_config(struct pcmcia_device *link) printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n"); link->dev_node = &lp->node; - link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(link)); i = register_netdev(dev); @@ -763,7 +756,7 @@ static int nmclan_suspend(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); return 0; @@ -773,7 +766,7 @@ static int nmclan_resume(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { nmclan_reset(dev); netif_device_attach(dev); } diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index d840c0f03e..d9661410f2 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -264,7 +264,6 @@ static int pcnet_probe(struct pcmcia_device *link) dev->stop = &pcnet_close; dev->set_config = &set_config; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return pcnet_config(link); } /* pcnet_attach */ @@ -286,8 +285,7 @@ static void pcnet_detach(struct pcmcia_device *link) if (link->dev_node) unregister_netdev(dev); - if (link->state & DEV_CONFIG) - pcnet_release(link); + pcnet_release(link); free_netdev(dev); } /* pcnet_detach */ @@ -538,9 +536,6 @@ static int pcnet_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - tuple.DesiredTuple = CISTPL_MANFID; tuple.Attributes = TUPLE_RETURN_COMMON; if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && @@ -667,7 +662,6 @@ static int pcnet_config(struct pcmcia_device *link) } link->dev_node = &info->node; - link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(link)); #ifdef CONFIG_NET_POLL_CONTROLLER @@ -705,7 +699,6 @@ cs_failed: cs_error(link, last_fn, last_ret); failed: pcnet_release(link); - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } /* pcnet_config */ @@ -742,7 +735,7 @@ static int pcnet_suspend(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); return 0; @@ -752,7 +745,7 @@ static int pcnet_resume(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { pcnet_reset_8390(dev); NS8390_init(dev, 1); netif_device_attach(dev); diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 3252c1dc9e..7d565f26a3 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -356,7 +356,6 @@ static int smc91c92_probe(struct pcmcia_device *link) smc->mii_if.phy_id_mask = 0x1f; smc->mii_if.reg_num_mask = 0x1f; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return smc91c92_config(link); } /* smc91c92_attach */ @@ -378,8 +377,7 @@ static void smc91c92_detach(struct pcmcia_device *link) if (link->dev_node) unregister_netdev(dev); - if (link->state & DEV_CONFIG) - smc91c92_release(link); + smc91c92_release(link); free_netdev(dev); } /* smc91c92_detach */ @@ -862,7 +860,7 @@ static int smc91c92_suspend(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); return 0; @@ -874,33 +872,31 @@ static int smc91c92_resume(struct pcmcia_device *link) struct smc_private *smc = netdev_priv(dev); int i; - if (link->state & DEV_CONFIG) { - if ((smc->manfid == MANFID_MEGAHERTZ) && - (smc->cardid == PRODID_MEGAHERTZ_EM3288)) - mhz_3288_power(link); - if (smc->manfid == MANFID_MOTOROLA) - mot_config(link); - if ((smc->manfid == MANFID_OSITECH) && - (smc->cardid != PRODID_OSITECH_SEVEN)) { - /* Power up the card and enable interrupts */ - set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); - set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); - } - if (((smc->manfid == MANFID_OSITECH) && - (smc->cardid == PRODID_OSITECH_SEVEN)) || - ((smc->manfid == MANFID_PSION) && - (smc->cardid == PRODID_PSION_NET100))) { - /* Download the Seven of Diamonds firmware */ - for (i = 0; i < sizeof(__Xilinx7OD); i++) { - outb(__Xilinx7OD[i], link->io.BasePort1+2); - udelay(50); - } - } - if (link->open) { - smc_reset(dev); - netif_device_attach(dev); + if ((smc->manfid == MANFID_MEGAHERTZ) && + (smc->cardid == PRODID_MEGAHERTZ_EM3288)) + mhz_3288_power(link); + if (smc->manfid == MANFID_MOTOROLA) + mot_config(link); + if ((smc->manfid == MANFID_OSITECH) && + (smc->cardid != PRODID_OSITECH_SEVEN)) { + /* Power up the card and enable interrupts */ + set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); + set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); + } + if (((smc->manfid == MANFID_OSITECH) && + (smc->cardid == PRODID_OSITECH_SEVEN)) || + ((smc->manfid == MANFID_PSION) && + (smc->cardid == PRODID_PSION_NET100))) { + /* Download the Seven of Diamonds firmware */ + for (i = 0; i < sizeof(__Xilinx7OD); i++) { + outb(__Xilinx7OD[i], link->io.BasePort1+2); + udelay(50); } } + if (link->open) { + smc_reset(dev); + netif_device_attach(dev); + } return 0; } @@ -1010,9 +1006,6 @@ static int smc91c92_config(struct pcmcia_device *link) smc->cardid = parse->manfid.card; } - /* Configure card */ - link->state |= DEV_CONFIG; - if ((smc->manfid == MANFID_OSITECH) && (smc->cardid != PRODID_OSITECH_SEVEN)) { i = osi_config(link); @@ -1108,7 +1101,6 @@ static int smc91c92_config(struct pcmcia_device *link) } link->dev_node = &smc->node; - link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(link)); if (register_netdev(dev) != 0) { @@ -1149,7 +1141,6 @@ config_undo: unregister_netdev(dev); config_failed: /* CS_EXIT_TEST() calls jump to here... */ smc91c92_release(link); - link->state &= ~DEV_CONFIG_PENDING; kfree(cfg_mem); return -ENODEV; } /* smc91c92_config */ diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 77bf4e3a61..0141c5037f 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -591,7 +591,6 @@ xirc2ps_probe(struct pcmcia_device *link) dev->watchdog_timeo = TX_TIMEOUT; #endif - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return xirc2ps_config(link); } /* xirc2ps_attach */ @@ -612,8 +611,7 @@ xirc2ps_detach(struct pcmcia_device *link) if (link->dev_node) unregister_netdev(dev); - if (link->state & DEV_CONFIG) - xirc2ps_release(link); + xirc2ps_release(link); free_netdev(dev); } /* xirc2ps_detach */ @@ -843,9 +841,6 @@ xirc2ps_config(struct pcmcia_device * link) for (i=0; i < 6; i++) dev->dev_addr[i] = node_id->id[i]; - /* Configure card */ - link->state |= DEV_CONFIG; - link->io.IOAddrLines =10; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; link->irq.Attributes = IRQ_HANDLE_PRESENT; @@ -1041,7 +1036,6 @@ xirc2ps_config(struct pcmcia_device * link) do_reset(dev, 1); /* a kludge to make the cem56 work */ link->dev_node = &local->node; - link->state &= ~DEV_CONFIG_PENDING; SET_NETDEV_DEV(dev, &handle_to_dev(link)); if ((err=register_netdev(dev))) { @@ -1062,14 +1056,12 @@ xirc2ps_config(struct pcmcia_device * link) return 0; config_error: - link->state &= ~DEV_CONFIG_PENDING; xirc2ps_release(link); return -ENODEV; cis_error: printk(KNOT_XIRC "unable to parse CIS\n"); failure: - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } /* xirc2ps_config */ @@ -1099,9 +1091,9 @@ static int xirc2ps_suspend(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { - netif_device_detach(dev); - do_powerdown(dev); + if (link->open) { + netif_device_detach(dev); + do_powerdown(dev); } return 0; @@ -1111,7 +1103,7 @@ static int xirc2ps_resume(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { do_reset(dev,1); netif_device_attach(dev); } diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index 97f41565fc..af0cbb6c5c 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -170,7 +170,6 @@ static int airo_probe(struct pcmcia_device *p_dev) } p_dev->priv = local; - p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return airo_config(p_dev); } /* airo_attach */ @@ -187,8 +186,7 @@ static void airo_detach(struct pcmcia_device *link) { DEBUG(0, "airo_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) - airo_release(link); + airo_release(link); if ( ((local_info_t*)link->priv)->eth_dev ) { stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); @@ -237,10 +235,7 @@ static int airo_config(struct pcmcia_device *link) CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; - + /* In this loop, we scan the CIS for configuration table entries, each of which describes a valid card configuration, including @@ -382,8 +377,6 @@ static int airo_config(struct pcmcia_device *link) printk(", mem 0x%06lx-0x%06lx", req.Base, req.Base+req.Size-1); printk("\n"); - - link->state &= ~DEV_CONFIG_PENDING; return 0; cs_failed: @@ -410,8 +403,7 @@ static int airo_suspend(struct pcmcia_device *link) { local_info_t *local = link->priv; - if (link->state & DEV_CONFIG) - netif_device_detach(local->eth_dev); + netif_device_detach(local->eth_dev); return 0; } @@ -420,7 +412,7 @@ static int airo_resume(struct pcmcia_device *link) { local_info_t *local = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { reset_airo_card(local->eth_dev); netif_device_attach(local->eth_dev); } diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index d09b1472e6..25fb919b37 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -181,7 +181,6 @@ static int atmel_probe(struct pcmcia_device *p_dev) } p_dev->priv = local; - p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return atmel_config(p_dev); } /* atmel_attach */ @@ -198,8 +197,7 @@ static void atmel_detach(struct pcmcia_device *link) { DEBUG(0, "atmel_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) - atmel_release(link); + atmel_release(link); kfree(link->priv); } @@ -222,7 +220,7 @@ static int card_present(void *arg) struct pcmcia_device *link = (struct pcmcia_device *)arg; if (link->suspended) return 0; - else if (link->state & DEV_PRESENT) + else if (pcmcia_dev_present(link)) return 1; return 0; @@ -257,10 +255,7 @@ static int atmel_config(struct pcmcia_device *link) CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; - + /* In this loop, we scan the CIS for configuration table entries, each of which describes a valid card configuration, including @@ -373,10 +368,9 @@ static int atmel_config(struct pcmcia_device *link) strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); dev->node.major = dev->node.minor = 0; link->dev_node = &dev->node; - - link->state &= ~DEV_CONFIG_PENDING; + return 0; - + cs_failed: cs_error(link, last_fn, last_ret); atmel_release(link); @@ -408,8 +402,7 @@ static int atmel_suspend(struct pcmcia_device *link) { local_info_t *local = link->priv; - if (link->state & DEV_CONFIG) - netif_device_detach(local->eth_dev); + netif_device_detach(local->eth_dev); return 0; } @@ -418,10 +411,8 @@ static int atmel_resume(struct pcmcia_device *link) { local_info_t *local = link->priv; - if (link->state & DEV_CONFIG) { - atmel_open(local->eth_dev); - netif_device_attach(local->eth_dev); - } + atmel_open(local->eth_dev); + netif_device_attach(local->eth_dev); return 0; } diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 88dc383a3d..a2cb9b0fa3 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -210,9 +210,7 @@ static int prism2_config(struct pcmcia_device *link); static int prism2_pccard_card_present(local_info_t *local) { struct hostap_cs_priv *hw_priv = local->hw_priv; - if (hw_priv != NULL && hw_priv->link != NULL && - ((hw_priv->link->state & (DEV_PRESENT | DEV_CONFIG)) == - (DEV_PRESENT | DEV_CONFIG))) + if (hw_priv != NULL && hw_priv->link != NULL && DEV_OK(hw_priv->link)) return 1; return 0; } @@ -508,7 +506,6 @@ static int hostap_cs_probe(struct pcmcia_device *p_dev) PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); p_dev->conf.IntType = INT_MEMORY_AND_IO; - p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; ret = prism2_config(p_dev); if (ret) { PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n"); @@ -522,9 +519,7 @@ static void prism2_detach(struct pcmcia_device *link) { PDEBUG(DEBUG_FLOW, "prism2_detach\n"); - if (link->state & DEV_CONFIG) { - prism2_release((u_long)link); - } + prism2_release((u_long)link); /* release net devices */ if (link->priv) { @@ -746,9 +741,6 @@ static int prism2_config(struct pcmcia_device *link) link->io.BasePort2+link->io.NumPorts2-1); printk("\n"); - link->state |= DEV_CONFIG; - link->state &= ~DEV_CONFIG_PENDING; - local->shutdown = 0; sandisk_enable_wireless(dev); @@ -784,8 +776,7 @@ static void prism2_release(u_long arg) struct hostap_interface *iface; iface = netdev_priv(dev); - if (link->state & DEV_CONFIG) - prism2_hw_shutdown(dev, 0); + prism2_hw_shutdown(dev, 0); iface->local->shutdown = 1; } @@ -797,19 +788,19 @@ static int hostap_cs_suspend(struct pcmcia_device *link) { struct net_device *dev = (struct net_device *) link->priv; int dev_open = 0; + struct hostap_interface *iface = NULL; - PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info); + if (dev) + iface = netdev_priv(dev); - if (link->state & DEV_CONFIG) { - struct hostap_interface *iface = netdev_priv(dev); - if (iface && iface->local) - dev_open = iface->local->num_dev_open > 0; - if (dev_open) { - netif_stop_queue(dev); - netif_device_detach(dev); - } - prism2_suspend(dev); + PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info); + if (iface && iface->local) + dev_open = iface->local->num_dev_open > 0; + if (dev_open) { + netif_stop_queue(dev); + netif_device_detach(dev); } + prism2_suspend(dev); return 0; } @@ -818,20 +809,21 @@ static int hostap_cs_resume(struct pcmcia_device *link) { struct net_device *dev = (struct net_device *) link->priv; int dev_open = 0; + struct hostap_interface *iface = NULL; + + if (dev) + iface = netdev_priv(dev); PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info); - if (link->state & DEV_CONFIG) { - struct hostap_interface *iface = netdev_priv(dev); - if (iface && iface->local) - dev_open = iface->local->num_dev_open > 0; + if (iface && iface->local) + dev_open = iface->local->num_dev_open > 0; - prism2_hw_shutdown(dev, 1); - prism2_hw_config(dev, dev_open ? 0 : 1); - if (dev_open) { - netif_device_attach(dev); - netif_start_queue(dev); - } + prism2_hw_shutdown(dev, 1); + prism2_hw_config(dev, dev_open ? 0 : 1); + if (dev_open) { + netif_device_attach(dev); + netif_start_queue(dev); } return 0; diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 2689f3bbc8..fbc8595cde 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -428,7 +428,6 @@ static int netwave_probe(struct pcmcia_device *link) dev->stop = &netwave_close; link->irq.Instance = dev; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return netwave_pcmcia_config( link); } /* netwave_attach */ @@ -446,8 +445,7 @@ static void netwave_detach(struct pcmcia_device *link) DEBUG(0, "netwave_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) - netwave_release(link); + netwave_release(link); if (link->dev_node) unregister_netdev(dev); @@ -763,9 +761,6 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) { link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - /* * Try allocating IO ports. This tries a few fixed addresses. * If you want, you can also read the card's config table to @@ -823,7 +818,6 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) { strcpy(priv->node.dev_name, dev->name); link->dev_node = &priv->node; - link->state &= ~DEV_CONFIG_PENDING; /* Reset card before reading physical address */ netwave_doreset(dev->base_addr, ramBase); @@ -875,7 +869,7 @@ static int netwave_suspend(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); return 0; @@ -885,7 +879,7 @@ static int netwave_resume(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { netwave_reset(dev); netif_device_attach(dev); } diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 0e92bee16c..434f7d7ad8 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -134,7 +134,6 @@ orinoco_cs_probe(struct pcmcia_device *link) link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return orinoco_cs_config(link); } /* orinoco_cs_attach */ @@ -148,8 +147,7 @@ static void orinoco_cs_detach(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if (link->state & DEV_CONFIG) - orinoco_cs_release(link); + orinoco_cs_release(link); DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); if (link->dev_node) { @@ -202,9 +200,6 @@ orinoco_cs_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); @@ -358,7 +353,6 @@ orinoco_cs_config(struct pcmcia_device *link) link->dev_node = &card->node; /* link->dev_node being non-NULL is also used to indicate that the net_device has been registered */ - link->state &= ~DEV_CONFIG_PENDING; /* Finally, report what we've done */ printk(KERN_DEBUG "%s: index 0x%02x: ", @@ -416,23 +410,21 @@ static int orinoco_cs_suspend(struct pcmcia_device *link) int err = 0; unsigned long flags; - if (link->state & DEV_CONFIG) { - /* This is probably racy, but I can't think of - a better way, short of rewriting the PCMCIA - layer to not suck :-( */ - if (! test_bit(0, &card->hard_reset_in_progress)) { - spin_lock_irqsave(&priv->lock, flags); + /* This is probably racy, but I can't think of + a better way, short of rewriting the PCMCIA + layer to not suck :-( */ + if (! test_bit(0, &card->hard_reset_in_progress)) { + spin_lock_irqsave(&priv->lock, flags); - err = __orinoco_down(dev); - if (err) - printk(KERN_WARNING "%s: Error %d downing interface\n", - dev->name, err); + err = __orinoco_down(dev); + if (err) + printk(KERN_WARNING "%s: Error %d downing interface\n", + dev->name, err); - netif_device_detach(dev); - priv->hw_unavailable++; + netif_device_detach(dev); + priv->hw_unavailable++; - spin_unlock_irqrestore(&priv->lock, flags); - } + spin_unlock_irqrestore(&priv->lock, flags); } return 0; @@ -446,29 +438,27 @@ static int orinoco_cs_resume(struct pcmcia_device *link) int err = 0; unsigned long flags; - if (link->state & DEV_CONFIG) { - if (! test_bit(0, &card->hard_reset_in_progress)) { - err = orinoco_reinit_firmware(dev); - if (err) { - printk(KERN_ERR "%s: Error %d re-initializing firmware\n", - dev->name, err); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); + if (! test_bit(0, &card->hard_reset_in_progress)) { + err = orinoco_reinit_firmware(dev); + if (err) { + printk(KERN_ERR "%s: Error %d re-initializing firmware\n", + dev->name, err); + return -EIO; + } - netif_device_attach(dev); - priv->hw_unavailable--; + spin_lock_irqsave(&priv->lock, flags); - if (priv->open && ! priv->hw_unavailable) { - err = __orinoco_up(dev); - if (err) - printk(KERN_ERR "%s: Error %d restarting card\n", - dev->name, err); - } + netif_device_attach(dev); + priv->hw_unavailable--; - spin_unlock_irqrestore(&priv->lock, flags); + if (priv->open && ! priv->hw_unavailable) { + err = __orinoco_up(dev); + if (err) + printk(KERN_ERR "%s: Error %d restarting card\n", + dev->name, err); } + + spin_unlock_irqrestore(&priv->lock, flags); } return 0; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index e3924339fa..85712ffb84 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -366,7 +366,6 @@ static int ray_probe(struct pcmcia_device *p_dev) init_timer(&local->timer); - p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; this_device = p_dev; return ray_config(p_dev); @@ -389,12 +388,10 @@ static void ray_detach(struct pcmcia_device *link) this_device = NULL; dev = link->priv; - if (link->state & DEV_CONFIG) { - ray_release(link); + ray_release(link); - local = (ray_dev_t *)dev->priv; - del_timer(&local->timer); - } + local = (ray_dev_t *)dev->priv; + del_timer(&local->timer); if (link->priv) { if (link->dev_node) unregister_netdev(dev); @@ -448,9 +445,6 @@ static int ray_config(struct pcmcia_device *link) if (buf[i] == 0) buf[i] = ' '; printk(KERN_INFO "ray_cs Detected: %s\n",buf); - /* Configure card */ - link->state |= DEV_CONFIG; - /* Now allocate an interrupt line. Note that this does not actually assign a handler to the interrupt. */ @@ -511,7 +505,6 @@ static int ray_config(struct pcmcia_device *link) strcpy(local->node.dev_name, dev->name); link->dev_node = &local->node; - link->state &= ~DEV_CONFIG_PENDING; printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ", dev->name, dev->irq); for (i = 0; i < 6; i++) @@ -552,7 +545,7 @@ static int ray_init(struct net_device *dev) ray_dev_t *local = (ray_dev_t *)dev->priv; struct pcmcia_device *link = local->finder; DEBUG(1, "ray_init(0x%p)\n", dev); - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(0,"ray_init - device not present\n"); return -1; } @@ -615,7 +608,7 @@ static int dl_startup_params(struct net_device *dev) struct pcmcia_device *link = local->finder; DEBUG(1,"dl_startup_params entered\n"); - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_cs dl_startup_params - device not present\n"); return -1; } @@ -721,7 +714,7 @@ static void verify_dl_startup(u_long data) UCHAR status; struct pcmcia_device *link = local->finder; - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_cs verify_dl_startup - device not present\n"); return; } @@ -760,7 +753,7 @@ static void start_net(u_long data) struct ccs __iomem *pccs; int ccsindex; struct pcmcia_device *link = local->finder; - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_cs start_net - device not present\n"); return; } @@ -788,7 +781,7 @@ static void join_net(u_long data) int ccsindex; struct pcmcia_device *link = local->finder; - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_cs join_net - device not present\n"); return; } @@ -839,7 +832,7 @@ static int ray_suspend(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); return 0; @@ -849,7 +842,7 @@ static int ray_resume(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { ray_reset(dev); netif_device_attach(dev); } @@ -867,7 +860,7 @@ int ray_dev_init(struct net_device *dev) struct pcmcia_device *link = local->finder; DEBUG(1,"ray_dev_init(dev=%p)\n",dev); - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_dev_init - device not present\n"); return -1; } @@ -901,7 +894,7 @@ static int ray_dev_config(struct net_device *dev, struct ifmap *map) struct pcmcia_device *link = local->finder; /* Dummy routine to satisfy device structure */ DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map); - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_dev_config - device not present\n"); return -1; } @@ -915,7 +908,7 @@ static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) struct pcmcia_device *link = local->finder; short length = skb->len; - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_dev_start_xmit - device not present\n"); return -1; } @@ -1542,7 +1535,7 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev) } #endif /* WIRELESS_SPY */ - if((link->state & DEV_PRESENT)) { + if(pcmcia_dev_present(link)) { local->wstats.qual.noise = readb(&p->rxnoise); local->wstats.qual.updated |= 4; } @@ -1674,7 +1667,7 @@ static int interrupt_ecf(ray_dev_t *local, int ccs) int i = 50; struct pcmcia_device *link = local->finder; - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_cs interrupt_ecf - device not present\n"); return -1; } @@ -1701,7 +1694,7 @@ static int get_free_tx_ccs(ray_dev_t *local) struct ccs __iomem *pccs = ccs_base(local); struct pcmcia_device *link = local->finder; - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n"); return ECARDGONE; } @@ -1732,7 +1725,7 @@ static int get_free_ccs(ray_dev_t *local) struct ccs __iomem *pccs = ccs_base(local); struct pcmcia_device *link = local->finder; - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_cs get_free_ccs - device not present\n"); return ECARDGONE; } @@ -1807,7 +1800,7 @@ static struct net_device_stats *ray_get_stats(struct net_device *dev) ray_dev_t *local = (ray_dev_t *)dev->priv; struct pcmcia_device *link = local->finder; struct status __iomem *p = local->sram + STATUS_BASE; - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_cs net_device_stats - device not present\n"); return &local->stats; } @@ -1840,7 +1833,7 @@ static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, i int i; struct ccs __iomem *pccs; - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_update_parm - device not present\n"); return; } @@ -1875,7 +1868,7 @@ static void ray_update_multi_list(struct net_device *dev, int all) struct pcmcia_device *link = local->finder; void __iomem *p = local->sram + HOST_TO_ECF_BASE; - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_update_multi_list - device not present\n"); return; } @@ -1968,7 +1961,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) local = (ray_dev_t *)dev->priv; link = (struct pcmcia_device *)local->finder; - if ( ! (link->state & DEV_PRESENT) || link->suspended ) { + if (!(pcmcia_dev_present(link)) || link->suspended ) { DEBUG(2,"ray_cs interrupt from device not present or suspended.\n"); return IRQ_NONE; } @@ -2489,7 +2482,7 @@ static void authenticate(ray_dev_t *local) { struct pcmcia_device *link = local->finder; DEBUG(0,"ray_cs Starting authentication.\n"); - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_cs authenticate - device not present\n"); return; } @@ -2556,7 +2549,7 @@ static void associate(ray_dev_t *local) struct pcmcia_device *link = local->finder; struct net_device *dev = link->priv; int ccsindex; - if (!(link->state & DEV_PRESENT)) { + if (!(pcmcia_dev_present(link))) { DEBUG(2,"ray_cs associate - device not present\n"); return; } diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 118b2c6e5a..f7b77ce54d 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c @@ -245,7 +245,7 @@ spectrum_reset(struct pcmcia_device *link, int idle) u_int save_cor; /* Doing it if hardware is gone is guaranteed crash */ - if (!(link->state & DEV_CONFIG)) + if (pcmcia_dev_present(link)) return -ENODEV; /* Save original COR value */ @@ -613,7 +613,6 @@ spectrum_cs_probe(struct pcmcia_device *link) link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return spectrum_cs_config(link); } /* spectrum_cs_attach */ @@ -627,8 +626,7 @@ static void spectrum_cs_detach(struct pcmcia_device *link) { struct net_device *dev = link->priv; - if (link->state & DEV_CONFIG) - spectrum_cs_release(link); + spectrum_cs_release(link); DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); if (link->dev_node) { @@ -677,9 +675,6 @@ spectrum_cs_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); @@ -838,7 +833,6 @@ spectrum_cs_config(struct pcmcia_device *link) link->dev_node = &card->node; /* link->dev_node being non-NULL is also used to indicate that the net_device has been registered */ - link->state &= ~DEV_CONFIG_PENDING; /* Finally, report what we've done */ printk(KERN_DEBUG "%s: index 0x%02x: ", @@ -898,19 +892,17 @@ spectrum_cs_suspend(struct pcmcia_device *link) int err = 0; /* Mark the device as stopped, to block IO until later */ - if (link->state & DEV_CONFIG) { - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->lock, flags); - err = __orinoco_down(dev); - if (err) - printk(KERN_WARNING "%s: Error %d downing interface\n", - dev->name, err); + err = __orinoco_down(dev); + if (err) + printk(KERN_WARNING "%s: Error %d downing interface\n", + dev->name, err); - netif_device_detach(dev); - priv->hw_unavailable++; + netif_device_detach(dev); + priv->hw_unavailable++; - spin_unlock_irqrestore(&priv->lock, flags); - } + spin_unlock_irqrestore(&priv->lock, flags); return 0; } @@ -921,11 +913,10 @@ spectrum_cs_resume(struct pcmcia_device *link) struct net_device *dev = link->priv; struct orinoco_private *priv = netdev_priv(dev); - if (link->state & DEV_CONFIG) { - netif_device_attach(dev); - priv->hw_unavailable--; - schedule_work(&priv->reset_work); - } + netif_device_attach(dev); + priv->hw_unavailable--; + schedule_work(&priv->reset_work); + return 0; } diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 6b67696547..f7724eb2fa 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -3983,12 +3983,9 @@ wv_pcmcia_config(struct pcmcia_device * link) if(i != CS_SUCCESS) { cs_error(link, ParseTuple, i); - link->state &= ~DEV_CONFIG_PENDING; return FALSE; } - - /* Configure card */ - link->state |= DEV_CONFIG; + do { i = pcmcia_request_io(link, &link->io); @@ -4071,7 +4068,6 @@ wv_pcmcia_config(struct pcmcia_device * link) } while(0); /* Humm... Disguised goto !!! */ - link->state &= ~DEV_CONFIG_PENDING; /* If any step failed, release any partially configured state */ if(i != 0) { @@ -4651,7 +4647,6 @@ wavelan_probe(struct pcmcia_device *p_dev) /* Other specific data */ dev->mtu = WAVELAN_MTU; - p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; ret = wv_pcmcia_config(p_dev); if (ret) return ret; @@ -4686,17 +4681,8 @@ wavelan_detach(struct pcmcia_device *link) printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); #endif - /* - * If the device is currently configured and active, we won't - * actually delete it yet. Instead, it is marked so that when the - * release() function is called, that will trigger a proper - * detach(). - */ - if(link->state & DEV_CONFIG) - { - /* Some others haven't done their job : give them another chance */ - wv_pcmcia_release(link); - } + /* Some others haven't done their job : give them another chance */ + wv_pcmcia_release(link); /* Free pieces */ if(link->priv) @@ -4731,7 +4717,7 @@ static int wavelan_suspend(struct pcmcia_device *link) /* Stop receiving new messages and wait end of transmission */ wv_ru_stop(dev); - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); /* Power down the module */ @@ -4744,7 +4730,7 @@ static int wavelan_resume(struct pcmcia_device *link) { struct net_device * dev = (struct net_device *) link->priv; - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { wv_hw_reset(dev); netif_device_attach(dev); } diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 6b3a605897..b6578059de 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1485,13 +1485,11 @@ static void wl3501_detach(struct pcmcia_device *link) * delete it yet. Instead, it is marked so that when the release() * function is called, that will trigger a proper detach(). */ - if (link->state & DEV_CONFIG) { - while (link->open > 0) - wl3501_close(dev); + while (link->open > 0) + wl3501_close(dev); - netif_device_detach(dev); - wl3501_release(link); - } + netif_device_detach(dev); + wl3501_release(link); if (link->priv) free_netdev(link->priv); @@ -1959,7 +1957,6 @@ static int wl3501_probe(struct pcmcia_device *p_dev) netif_stop_queue(dev); p_dev->priv = p_dev->irq.Instance = dev; - p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return wl3501_config(p_dev); out_link: return -ENOMEM; @@ -1997,9 +1994,6 @@ static int wl3501_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - /* Try allocating IO ports. This tries a few fixed addresses. If you * want, you can also read the card's config table to pick addresses -- * see the serial driver for an example. */ @@ -2044,7 +2038,6 @@ static int wl3501_config(struct pcmcia_device *link) * arranged in a linked list at link->dev_node. */ link->dev_node = &this->node; - link->state &= ~DEV_CONFIG_PENDING; this->base_addr = dev->base_addr; @@ -2113,7 +2106,7 @@ static int wl3501_suspend(struct pcmcia_device *link) struct net_device *dev = link->priv; wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND); - if ((link->state & DEV_CONFIG) && (link->open)) + if (link->open) netif_device_detach(dev); return 0; @@ -2124,7 +2117,7 @@ static int wl3501_resume(struct pcmcia_device *link) struct net_device *dev = link->priv; wl3501_pwr_mgmt(dev->priv, WL3501_RESUME); - if ((link->state & DEV_CONFIG) && (link->open)) { + if (link->open) { wl3501_reset(dev); netif_device_attach(dev); } diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index e4be826c48..b953d5907c 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -119,7 +119,6 @@ static int parport_probe(struct pcmcia_device *link) link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return parport_config(link); } /* parport_attach */ @@ -136,8 +135,7 @@ static void parport_detach(struct pcmcia_device *link) { DEBUG(0, "parport_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) - parport_cs_release(link); + parport_cs_release(link); kfree(link->priv); } /* parport_detach */ @@ -175,9 +173,6 @@ static int parport_config(struct pcmcia_device *link) CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; @@ -233,14 +228,12 @@ static int parport_config(struct pcmcia_device *link) strcpy(info->node.dev_name, p->name); link->dev_node = &info->node; - link->state &= ~DEV_CONFIG_PENDING; return 0; cs_failed: cs_error(link, last_fn, last_ret); failed: parport_cs_release(link); - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } /* parport_config */ diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index ecc579bbae..d6164cd583 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -23,7 +23,7 @@ #define CLIENT_IO_REQ 0x0004 #define CLIENT_UNBOUND 0x0008 #define CLIENT_STALE 0x0010 -#define CLIENT_WIN_REQ(i) (0x20<<(i)) +#define CLIENT_WIN_REQ(i) (0x1<<(i)) #define CLIENT_CARDBUS 0x8000 #define REGION_MAGIC 0xE3C9 diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 34e634aa48..8c87343707 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -390,8 +390,6 @@ static int pcmcia_device_probe(struct device * dev) goto put_dev; } - p_dev->p_state &= ~CLIENT_UNBOUND; - ret = p_drv->probe(p_dev); if (ret) goto put_module; @@ -433,17 +431,16 @@ static int pcmcia_device_remove(struct device * dev) p_drv->remove(p_dev); /* check for proper unloading */ - if (p_dev->p_state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED)) + if (p_dev->_irq || p_dev->_io || p_dev->_locked) printk(KERN_INFO "pcmcia: driver %s did not release config properly\n", p_drv->drv.name); for (i = 0; i < MAX_WIN; i++) - if (p_dev->p_state & CLIENT_WIN_REQ(i)) + if (p_dev->_win & CLIENT_WIN_REQ(i)) printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n", p_drv->drv.name); /* references from pcmcia_probe_device */ - p_dev->p_state = CLIENT_UNBOUND; pcmcia_put_dev(p_dev); module_put(p_drv->owner); @@ -472,7 +469,6 @@ static void pcmcia_card_remove(struct pcmcia_socket *s) } p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list); list_del(&p_dev->socket_device_list); - p_dev->p_state |= CLIENT_STALE; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); device_unregister(&p_dev->dev); @@ -602,9 +598,6 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id); /* compat */ - p_dev->p_state = CLIENT_UNBOUND; - - spin_lock_irqsave(&pcmcia_dev_list_lock, flags); /* @@ -1033,15 +1026,18 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); - if (p_drv && p_drv->suspend) { + if (!p_drv) + goto out; + + if (p_drv->suspend) { ret = p_drv->suspend(p_dev); if (ret) goto out; - if ((p_dev->state & DEV_CONFIG) && - !(p_dev->state & DEV_SUSPEND_NORELEASE)) - pcmcia_release_configuration(p_dev); } + if (p_dev->device_no == p_dev->func) + pcmcia_release_configuration(p_dev); + out: if (!ret) p_dev->suspended = 1; @@ -1058,17 +1054,18 @@ static int pcmcia_dev_resume(struct device * dev) if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); - if (p_drv && p_drv->resume) { - if ((p_dev->state & DEV_CONFIG) && - !(p_dev->state & DEV_SUSPEND_NORELEASE)){ - ret = pcmcia_request_configuration(p_dev, - &p_dev->conf); - if (ret) - goto out; - } - ret = p_drv->resume(p_dev); + if (!p_drv) + goto out; + + if (p_dev->device_no == p_dev->func) { + ret = pcmcia_request_configuration(p_dev, &p_dev->conf); + if (ret) + goto out; } + if (p_drv->resume) + ret = p_drv->resume(p_dev); + out: if (!ret) p_dev->suspended = 0; diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 2b11a33217..c53db7ceda 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -304,6 +304,7 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int { dev_node_t *node; struct pcmcia_device *p_dev; + struct pcmcia_driver *p_drv; unsigned long flags; int ret = 0; @@ -358,7 +359,8 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int found: spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - if (p_dev->state & DEV_CONFIG_PENDING) { + p_drv = to_pcmcia_drv(p_dev->dev.driver); + if (p_drv && !p_dev->_locked) { ret = -EAGAIN; goto err_put; } diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index dbf167c979..45063b4e5b 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -476,8 +476,8 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) config_t *c = p_dev->function_config; int i; - if (p_dev->p_state & CLIENT_CONFIG_LOCKED) { - p_dev->p_state &= ~CLIENT_CONFIG_LOCKED; + if (p_dev->_locked) { + p_dev->_locked = 0; if (--(s->lock_count) == 0) { s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ s->socket.Vpp = 0; @@ -516,10 +516,10 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) struct pcmcia_socket *s = p_dev->socket; config_t *c = p_dev->function_config; - if (!(p_dev->p_state & CLIENT_IO_REQ)) + if (!p_dev->_io ) return CS_BAD_HANDLE; - p_dev->p_state &= ~CLIENT_IO_REQ; + p_dev->_io = 0; if ((c->io.BasePort1 != req->BasePort1) || (c->io.NumPorts1 != req->NumPorts1) || @@ -542,9 +542,9 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) struct pcmcia_socket *s = p_dev->socket; config_t *c= p_dev->function_config; - if (!(p_dev->p_state & CLIENT_IRQ_REQ)) + if (!p_dev->_irq) return CS_BAD_HANDLE; - p_dev->p_state &= ~CLIENT_IRQ_REQ; + p_dev->_irq = 0; if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; @@ -576,7 +576,7 @@ int pcmcia_release_window(window_handle_t win) if ((win == NULL) || (win->magic != WINDOW_MAGIC)) return CS_BAD_HANDLE; s = win->sock; - if (!(win->handle->p_state & CLIENT_WIN_REQ(win->index))) + if (!(win->handle->_win & CLIENT_WIN_REQ(win->index))) return CS_BAD_HANDLE; /* Shut down memory window */ @@ -590,7 +590,7 @@ int pcmcia_release_window(window_handle_t win) kfree(win->ctl.res); win->ctl.res = NULL; } - win->handle->p_state &= ~CLIENT_WIN_REQ(win->index); + win->handle->_win &= ~CLIENT_WIN_REQ(win->index); win->magic = 0; @@ -708,7 +708,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, } c->state |= CONFIG_LOCKED; - p_dev->p_state |= CLIENT_CONFIG_LOCKED; + p_dev->_locked = 1; return CS_SUCCESS; } /* pcmcia_request_configuration */ EXPORT_SYMBOL(pcmcia_request_configuration); @@ -754,7 +754,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) c->io = *req; c->state |= CONFIG_IO_REQ; - p_dev->p_state |= CLIENT_IO_REQ; + p_dev->_io = 1; return CS_SUCCESS; } /* pcmcia_request_io */ EXPORT_SYMBOL(pcmcia_request_io); @@ -850,7 +850,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) s->irq.Config++; c->state |= CONFIG_IRQ_REQ; - p_dev->p_state |= CLIENT_IRQ_REQ; + p_dev->_irq = 1; #ifdef CONFIG_PCMCIA_PROBE pcmcia_used_irq[irq]++; @@ -910,7 +910,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h if (!win->ctl.res) return CS_IN_USE; } - (*p_dev)->p_state |= CLIENT_WIN_REQ(w); + (*p_dev)->_win |= CLIENT_WIN_REQ(w); /* Configure the socket controller */ win->ctl.map = w+1; diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 7caa700cf1..ee449b29fc 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -122,7 +122,6 @@ static int aha152x_probe(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return aha152x_config_cs(link); } /* aha152x_attach */ @@ -132,8 +131,7 @@ static void aha152x_detach(struct pcmcia_device *link) { DEBUG(0, "aha152x_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) - aha152x_release_cs(link); + aha152x_release_cs(link); /* Unlink device structure, free bits */ kfree(link->priv); @@ -165,9 +163,6 @@ static int aha152x_config_cs(struct pcmcia_device *link) CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; - /* Configure card */ - link->state |= DEV_CONFIG; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { @@ -216,7 +211,6 @@ static int aha152x_config_cs(struct pcmcia_device *link) link->dev_node = &info->node; info->host = host; - link->state &= ~DEV_CONFIG_PENDING; return 0; cs_failed: diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 80afd3e879..85f7ffac19 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -105,7 +105,6 @@ static int fdomain_probe(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return fdomain_config(link); } /* fdomain_attach */ @@ -115,8 +114,7 @@ static void fdomain_detach(struct pcmcia_device *link) { DEBUG(0, "fdomain_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) - fdomain_release(link); + fdomain_release(link); kfree(link->priv); } /* fdomain_detach */ @@ -147,9 +145,6 @@ static int fdomain_config(struct pcmcia_device *link) CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; - /* Configure card */ - link->state |= DEV_CONFIG; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { @@ -188,7 +183,6 @@ static int fdomain_config(struct pcmcia_device *link) link->dev_node = &info->node; info->host = host; - link->state &= ~DEV_CONFIG_PENDING; return 0; cs_failed: @@ -214,8 +208,7 @@ static void fdomain_release(struct pcmcia_device *link) static int fdomain_resume(struct pcmcia_device *link) { - if (link->state & DEV_CONFIG) - fdomain_16x0_bus_reset(NULL); + fdomain_16x0_bus_reset(NULL); return 0; } diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index deec1c3a26..231f9c311c 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1630,7 +1630,6 @@ static int nsp_cs_probe(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; ret = nsp_cs_config(link); nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); @@ -1648,10 +1647,8 @@ static void nsp_cs_detach(struct pcmcia_device *link) { nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link); - if (link->state & DEV_CONFIG) { - ((scsi_info_t *)link->priv)->stop = 1; - nsp_cs_release(link); - } + ((scsi_info_t *)link->priv)->stop = 1; + nsp_cs_release(link); kfree(link->priv); link->priv = NULL; @@ -1698,9 +1695,6 @@ static int nsp_cs_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); @@ -1921,7 +1915,6 @@ static int nsp_cs_config(struct pcmcia_device *link) req.Base+req.Size-1); printk("\n"); - link->state &= ~DEV_CONFIG_PENDING; return 0; cs_failed: @@ -2071,19 +2064,7 @@ static int __init nsp_cs_init(void) static void __exit nsp_cs_exit(void) { nsp_msg(KERN_INFO, "unloading..."); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) pcmcia_unregister_driver(&nsp_driver); -#else - unregister_pcmcia_driver(&dev_info); - /* XXX: this really needs to move into generic code.. */ - while (dev_list != NULL) { - if (dev_list->state & DEV_CONFIG) { - nsp_cs_release(dev_list); - } - nsp_cs_detach(dev_list); - } -#endif } diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 61c2eb03a9..86c2ac6ae6 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -178,7 +178,6 @@ static int qlogic_probe(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return qlogic_config(link); } /* qlogic_attach */ @@ -188,9 +187,7 @@ static void qlogic_detach(struct pcmcia_device *link) { DEBUG(0, "qlogic_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) - qlogic_release(link); - + qlogic_release(link); kfree(link->priv); } /* qlogic_detach */ @@ -224,9 +221,6 @@ static int qlogic_config(struct pcmcia_device * link) if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) info->manf_id = le16_to_cpu(tuple.TupleData[0]); - /* Configure card */ - link->state |= DEV_CONFIG; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { @@ -272,7 +266,6 @@ static int qlogic_config(struct pcmcia_device * link) link->dev_node = &info->node; info->host = host; - link->state &= ~DEV_CONFIG_PENDING; return 0; cs_failed: @@ -302,20 +295,18 @@ static void qlogic_release(struct pcmcia_device *link) static int qlogic_resume(struct pcmcia_device *link) { - if (link->state & DEV_CONFIG) { - scsi_info_t *info = link->priv; - - pcmcia_request_configuration(link, &link->conf); - if ((info->manf_id == MANFID_MACNICA) || - (info->manf_id == MANFID_PIONEER) || - (info->manf_id == 0x0098)) { - outb(0x80, link->io.BasePort1 + 0xd); - outb(0x24, link->io.BasePort1 + 0x9); - outb(0x04, link->io.BasePort1 + 0xd); - } - /* Ugggglllyyyy!!! */ - qlogicfas408_bus_reset(NULL); + scsi_info_t *info = link->priv; + + pcmcia_request_configuration(link, &link->conf); + if ((info->manf_id == MANFID_MACNICA) || + (info->manf_id == MANFID_PIONEER) || + (info->manf_id == 0x0098)) { + outb(0x80, link->io.BasePort1 + 0xd); + outb(0x24, link->io.BasePort1 + 0x9); + outb(0x04, link->io.BasePort1 + 0xd); } + /* Ugggglllyyyy!!! */ + qlogicfas408_bus_reset(NULL); return 0; } diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index b4432206a8..9f59827707 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -736,9 +736,6 @@ SYM53C500_config(struct pcmcia_device *link) (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) info->manf_id = le16_to_cpu(tuple.TupleData[0]); - /* Configure card */ - link->state |= DEV_CONFIG; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { @@ -836,7 +833,6 @@ next_entry: scsi_scan_host(host); - link->state &= ~DEV_CONFIG_PENDING; return 0; err_free_irq: @@ -846,7 +842,6 @@ err_free_scsi: err_release: release_region(port_base, 0x10); printk(KERN_INFO "sym53c500_cs: no SCSI devices found\n"); - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; cs_failed: @@ -859,21 +854,19 @@ static int sym53c500_resume(struct pcmcia_device *link) { struct scsi_info_t *info = link->priv; - if (link->state & DEV_CONFIG) { - /* See earlier comment about manufacturer IDs. */ - if ((info->manf_id == MANFID_MACNICA) || - (info->manf_id == MANFID_PIONEER) || - (info->manf_id == 0x0098)) { - outb(0x80, link->io.BasePort1 + 0xd); - outb(0x24, link->io.BasePort1 + 0x9); - outb(0x04, link->io.BasePort1 + 0xd); - } - /* - * If things don't work after a "resume", - * this is a good place to start looking. - */ - SYM53C500_int_host_reset(link->io.BasePort1); + /* See earlier comment about manufacturer IDs. */ + if ((info->manf_id == MANFID_MACNICA) || + (info->manf_id == MANFID_PIONEER) || + (info->manf_id == 0x0098)) { + outb(0x80, link->io.BasePort1 + 0xd); + outb(0x24, link->io.BasePort1 + 0x9); + outb(0x04, link->io.BasePort1 + 0xd); } + /* + * If things don't work after a "resume", + * this is a good place to start looking. + */ + SYM53C500_int_host_reset(link->io.BasePort1); return 0; } @@ -883,8 +876,7 @@ SYM53C500_detach(struct pcmcia_device *link) { DEBUG(0, "SYM53C500_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) - SYM53C500_release(link); + SYM53C500_release(link); kfree(link->priv); link->priv = NULL; @@ -913,7 +905,6 @@ SYM53C500_probe(struct pcmcia_device *link) link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return SYM53C500_config(link); } /* SYM53C500_attach */ diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index e7875090dc..eec05a0a86 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -128,38 +128,27 @@ static void serial_remove(struct pcmcia_device *link) struct serial_info *info = link->priv; int i; - link->state &= ~DEV_PRESENT; - DEBUG(0, "serial_release(0x%p)\n", link); /* * Recheck to see if the device is still configured. */ - if (info->p_dev->state & DEV_CONFIG) { - for (i = 0; i < info->ndev; i++) - serial8250_unregister_port(info->line[i]); - - info->p_dev->dev_node = NULL; + for (i = 0; i < info->ndev; i++) + serial8250_unregister_port(info->line[i]); - if (!info->slave) - pcmcia_disable_device(link); + info->p_dev->dev_node = NULL; - info->p_dev->state &= ~DEV_CONFIG; - } + if (!info->slave) + pcmcia_disable_device(link); } static int serial_suspend(struct pcmcia_device *link) { - if (link->state & DEV_CONFIG) { - struct serial_info *info = link->priv; - int i; - - for (i = 0; i < info->ndev; i++) - serial8250_suspend_port(info->line[i]); + struct serial_info *info = link->priv; + int i; - if (info->slave) - link->state &= DEV_SUSPEND_NORELEASE; - } + for (i = 0; i < info->ndev; i++) + serial8250_suspend_port(info->line[i]); return 0; } @@ -210,7 +199,6 @@ static int serial_probe(struct pcmcia_device *link) } link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return serial_config(link); } @@ -586,9 +574,6 @@ static int serial_config(struct pcmcia_device * link) link->conf.ConfigBase = parse->config.base; link->conf.Present = parse->config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - /* Is this a compliant multifunction card? */ tuple->DesiredTuple = CISTPL_LONGLINK_MFC; tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; @@ -648,7 +633,6 @@ static int serial_config(struct pcmcia_device * link) } link->dev_node = &info->node[0]; - link->state &= ~DEV_CONFIG_PENDING; kfree(cfg_mem); return 0; @@ -656,7 +640,6 @@ static int serial_config(struct pcmcia_device * link) cs_error(link, last_fn, last_ret); failed: serial_remove(link); - link->state &= ~DEV_CONFIG_PENDING; kfree(cfg_mem); return -ENODEV; } diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index 5c7611c2ac..dda0ca45d9 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -52,7 +52,6 @@ static int ixj_probe(struct pcmcia_device *p_dev) } memset(p_dev->priv, 0, sizeof(struct ixj_info_t)); - p_dev->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return ixj_config(p_dev); } @@ -60,8 +59,7 @@ static void ixj_detach(struct pcmcia_device *link) { DEBUG(0, "ixj_detach(0x%p)\n", link); - if (link->state & DEV_CONFIG) - ixj_cs_release(link); + ixj_cs_release(link); kfree(link->priv); } @@ -155,7 +153,6 @@ static int ixj_config(struct pcmcia_device * link) CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); @@ -194,7 +191,6 @@ static int ixj_config(struct pcmcia_device * link) info->node.major = PHONE_MAJOR; link->dev_node = &info->node; ixj_get_serial(link, j); - link->state &= ~DEV_CONFIG_PENDING; return 0; cs_failed: cs_error(link, last_fn, last_ret); diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index e8b8e9a930..302aa1ec31 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -142,9 +142,7 @@ static void sl811_cs_detach(struct pcmcia_device *link) { DBG(0, "sl811_cs_detach(0x%p)\n", link); - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) - sl811_cs_release(link); + sl811_cs_release(link); /* This points to the parent local_info_t struct */ kfree(link->priv); @@ -182,9 +180,6 @@ static int sl811_cs_config(struct pcmcia_device *link) link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; - /* Configure card */ - link->state |= DEV_CONFIG; - /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); @@ -276,15 +271,12 @@ next_entry: link->io.BasePort1+link->io.NumPorts1-1); printk("\n"); - link->state &= ~DEV_CONFIG_PENDING; - if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ) < 0) { cs_failed: printk("sl811_cs_config failed\n"); cs_error(link, last_fn, last_ret); sl811_cs_release(link); - link->state &= ~DEV_CONFIG_PENDING; return -ENODEV; } return 0; @@ -309,7 +301,6 @@ static int sl811_cs_probe(struct pcmcia_device *link) link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY_AND_IO; - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; return sl811_cs_config(link); } -- cgit v1.2.2 From 9940ec3617fec1db13e589bbc3f37e37878c7683 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 5 Mar 2006 11:04:33 +0100 Subject: [PATCH] pcmcia: convert DEV_OK to pcmcia_dev_present Instead of the DEV_OK macro, drivers should use pcmcia_dev_present(). Signed-off-by: Dominik Brodowski --- drivers/char/pcmcia/cm4000_cs.c | 4 ++-- drivers/char/pcmcia/cm4040_cs.c | 2 +- drivers/net/pcmcia/3c574_cs.c | 4 ++-- drivers/net/pcmcia/3c589_cs.c | 8 ++++---- drivers/net/pcmcia/axnet_cs.c | 2 +- drivers/net/pcmcia/fmvj18x_cs.c | 2 +- drivers/net/pcmcia/nmclan_cs.c | 2 +- drivers/net/pcmcia/pcnet_cs.c | 2 +- drivers/net/pcmcia/smc91c92_cs.c | 2 +- drivers/net/pcmcia/xirc2ps_cs.c | 2 +- drivers/net/wireless/atmel_cs.c | 9 ++++----- drivers/net/wireless/hostap/hostap_cs.c | 2 +- drivers/net/wireless/netwave_cs.c | 4 ++-- drivers/net/wireless/ray_cs.c | 2 +- drivers/net/wireless/wl3501_cs.c | 2 +- drivers/pcmcia/ds.c | 27 +++++++++++++++++++++++++++ drivers/serial/serial_cs.c | 2 +- 17 files changed, 52 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 16e105d8d7..02114a0bd0 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -1458,7 +1458,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, iminor(inode), ioctl_names[_IOC_NR(cmd)]); link = dev_table[iminor(inode)]; - if (!(DEV_OK(link))) { + if (!pcmcia_dev_present(link)) { DEBUGP(4, dev, "DEV_OK false\n"); return -ENODEV; } @@ -1667,7 +1667,7 @@ static int cmm_open(struct inode *inode, struct file *filp) return -ENODEV; link = dev_table[minor]; - if (link == NULL || !(DEV_OK(link))) + if (link == NULL || !pcmcia_dev_present(link)) return -ENODEV; if (link->open) diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 74609c3b2b..29efa64580 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -452,7 +452,7 @@ static int cm4040_open(struct inode *inode, struct file *filp) return -ENODEV; link = dev_table[minor]; - if (link == NULL || !(DEV_OK(link))) + if (link == NULL || !pcmcia_dev_present(link)) return -ENODEV; if (link->open) diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 70e3cca097..fab93360f0 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -728,7 +728,7 @@ static int el3_open(struct net_device *dev) struct el3_private *lp = netdev_priv(dev); struct pcmcia_device *link = lp->p_dev; - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; link->open++; @@ -1176,7 +1176,7 @@ static int el3_close(struct net_device *dev) DEBUG(2, "%s: shutting down ethercard.\n", dev->name); - if (DEV_OK(link)) { + if (pcmcia_dev_present(link)) { unsigned long flags; /* Turn off statistics ASAP. We update lp->stats below. */ diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 3d05f66e9c..875a0fe251 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -557,7 +557,7 @@ static int el3_open(struct net_device *dev) struct el3_private *lp = netdev_priv(dev); struct pcmcia_device *link = lp->p_dev; - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; link->open++; @@ -818,7 +818,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev) unsigned long flags; struct pcmcia_device *link = lp->p_dev; - if (DEV_OK(link)) { + if (pcmcia_dev_present(link)) { spin_lock_irqsave(&lp->lock, flags); update_stats(dev); spin_unlock_irqrestore(&lp->lock, flags); @@ -922,7 +922,7 @@ static void set_multicast_list(struct net_device *dev) kio_addr_t ioaddr = dev->base_addr; u16 opts = SetRxFilter | RxStation | RxBroadcast; - if (!(DEV_OK(link))) return; + if (!pcmcia_dev_present(link)) return; if (dev->flags & IFF_PROMISC) opts |= RxMulticast | RxProm; else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) @@ -938,7 +938,7 @@ static int el3_close(struct net_device *dev) DEBUG(1, "%s: shutting down ethercard.\n", dev->name); - if (DEV_OK(link)) { + if (pcmcia_dev_present(link)) { /* Turn off statistics ASAP. We update lp->stats below. */ outw(StatsDisable, ioaddr + EL3_CMD); diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 0f1219c118..56233afcb2 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -530,7 +530,7 @@ static int axnet_open(struct net_device *dev) DEBUG(2, "axnet_open('%s')\n", dev->name); - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; link->open++; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 7cb20b6b93..09b11761cd 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -1112,7 +1112,7 @@ static int fjn_open(struct net_device *dev) DEBUG(4, "fjn_open('%s').\n", dev->name); - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; link->open++; diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index fd191143cb..4260c2128f 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -853,7 +853,7 @@ static int mace_open(struct net_device *dev) mace_private *lp = netdev_priv(dev); struct pcmcia_device *link = lp->p_dev; - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; link->open++; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index d9661410f2..506e777c5f 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -992,7 +992,7 @@ static int pcnet_open(struct net_device *dev) DEBUG(2, "pcnet_open('%s')\n", dev->name); - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; link->open++; diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 7d565f26a3..e74bf5014e 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -1259,7 +1259,7 @@ static int smc_open(struct net_device *dev) #endif /* Check that the PCMCIA card is still here. */ - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; /* Physical device present signature. */ if (check_sig(link) < 0) { diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 0141c5037f..a92a3134c8 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1525,7 +1525,7 @@ do_open(struct net_device *dev) /* Check that the PCMCIA card is still here. */ /* Physical device present signature. */ - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; /* okay */ diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 25fb919b37..26bf112752 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -216,13 +216,12 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) /* Call-back function to interrogate PCMCIA-specific information about the current existance of the card */ static int card_present(void *arg) -{ +{ struct pcmcia_device *link = (struct pcmcia_device *)arg; - if (link->suspended) - return 0; - else if (pcmcia_dev_present(link)) + + if (pcmcia_dev_present(link)) return 1; - + return 0; } diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index a2cb9b0fa3..55bed923fb 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -210,7 +210,7 @@ static int prism2_config(struct pcmcia_device *link); static int prism2_pccard_card_present(local_info_t *local) { struct hostap_cs_priv *hw_priv = local->hw_priv; - if (hw_priv != NULL && hw_priv->link != NULL && DEV_OK(hw_priv->link)) + if (hw_priv != NULL && hw_priv->link != NULL && pcmcia_dev_present(hw_priv->link)) return 1; return 0; } diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index fbc8595cde..9343d97053 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c @@ -1107,7 +1107,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs status = inb(iobase + NETWAVE_REG_ASR); - if (!DEV_OK(link)) { + if (!pcmcia_dev_present(link)) { DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x " "from removed or suspended card!\n", status); break; @@ -1346,7 +1346,7 @@ static int netwave_open(struct net_device *dev) { DEBUG(1, "netwave_open: starting.\n"); - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) return -ENODEV; link->open++; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 85712ffb84..879eb42760 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1961,7 +1961,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) local = (ray_dev_t *)dev->priv; link = (struct pcmcia_device *)local->finder; - if (!(pcmcia_dev_present(link)) || link->suspended ) { + if (!pcmcia_dev_present(link)) { DEBUG(2,"ray_cs interrupt from device not present or suspended.\n"); return IRQ_NONE; } diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index b6578059de..e52a650f67 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -1387,7 +1387,7 @@ static int wl3501_open(struct net_device *dev) link = this->p_dev; spin_lock_irqsave(&this->lock, flags); - if (!DEV_OK(link)) + if (!pcmcia_dev_present(link)) goto out; netif_device_attach(dev); link->open++; diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 8c87343707..677105e357 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -469,6 +469,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s) } p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list); list_del(&p_dev->socket_device_list); + p_dev->_removed=1; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); device_unregister(&p_dev->dev); @@ -1163,6 +1164,32 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) } /* ds_event */ +struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *_p_dev) +{ + struct pcmcia_device *p_dev; + struct pcmcia_device *ret = NULL; + + p_dev = pcmcia_get_dev(_p_dev); + if (!p_dev) + return NULL; + + if (!p_dev->socket->pcmcia_state.present) + goto out; + + if (p_dev->_removed) + goto out; + + if (p_dev->suspended) + goto out; + + ret = p_dev; + out: + pcmcia_put_dev(p_dev); + return ret; +} +EXPORT_SYMBOL(pcmcia_dev_present); + + static struct pcmcia_callback pcmcia_bus_callback = { .owner = THIS_MODULE, .event = ds_event, diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index eec05a0a86..389d847cd1 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -155,7 +155,7 @@ static int serial_suspend(struct pcmcia_device *link) static int serial_resume(struct pcmcia_device *link) { - if (DEV_OK(link)) { + if (pcmcia_dev_present(link)) { struct serial_info *info = link->priv; int i; -- cgit v1.2.2 From d6ff5a8532b553e4d85ea65c99eaa0794edf5311 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 5 Feb 2006 09:51:34 +0100 Subject: [PATCH] pcmcia: pseudo device handling update If the driver for the primary pseudo device is removed from the device, the secondary driver must be removed as well -- it cannot exist on its own. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/ds.c | 81 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 677105e357..8966dd0913 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -415,15 +415,61 @@ static int pcmcia_device_probe(struct device * dev) } +/* + * Removes a PCMCIA card from the device tree and socket list. + */ +static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *leftover) +{ + struct pcmcia_device *p_dev; + struct pcmcia_device *tmp; + unsigned long flags; + + ds_dbg(2, "unbind_request(%d)\n", s->sock); + + + if (!leftover) + s->device_count = 0; + else + s->device_count = 1; + + /* unregister all pcmcia_devices registered with this socket, except leftover */ + list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) { + if (p_dev == leftover) + continue; + + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); + list_del(&p_dev->socket_device_list); + p_dev->_removed=1; + spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + + device_unregister(&p_dev->dev); + } + + return; +} + + static int pcmcia_device_remove(struct device * dev) { struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; + struct pcmcia_device_id *did; int i; - /* detach the "instance" */ p_dev = to_pcmcia_dev(dev); p_drv = to_pcmcia_drv(dev->driver); + + /* If we're removing the primary module driving a + * pseudo multi-function card, we need to unbind + * all devices + */ + did = (struct pcmcia_device_id *) p_dev->dev.driver_data; + if ((did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && + (p_dev->socket->device_count != 0) && + (p_dev->device_no == 0)) + pcmcia_card_remove(p_dev->socket, p_dev); + + /* detach the "instance" */ if (!p_drv) return 0; @@ -448,37 +494,6 @@ static int pcmcia_device_remove(struct device * dev) } -/* - * Removes a PCMCIA card from the device tree and socket list. - */ -static void pcmcia_card_remove(struct pcmcia_socket *s) -{ - struct pcmcia_device *p_dev; - unsigned long flags; - - ds_dbg(2, "unbind_request(%d)\n", s->sock); - - s->device_count = 0; - - for (;;) { - /* unregister all pcmcia_devices registered with this socket*/ - spin_lock_irqsave(&pcmcia_dev_list_lock, flags); - if (list_empty(&s->devices_list)) { - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - return; - } - p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list); - list_del(&p_dev->socket_device_list); - p_dev->_removed=1; - spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); - - device_unregister(&p_dev->dev); - } - - return; -} /* unbind_request */ - - /* * pcmcia_device_query -- determine information about a pcmcia device */ @@ -1136,7 +1151,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) switch (event) { case CS_EVENT_CARD_REMOVAL: s->pcmcia_state.present = 0; - pcmcia_card_remove(skt); + pcmcia_card_remove(skt, NULL); handle_event(skt, event); break; -- cgit v1.2.2 From 30bac7aa0e3678c79ff00fc9372f34712eeb34fc Mon Sep 17 00:00:00 2001 From: Petr Vandrovec Date: Fri, 10 Feb 2006 02:04:00 -0800 Subject: [PATCH] pcmcia: Add support for Possio GCC AKA PCMCIA Siemens MC45 This ugly hack add support for Siemens MC45 PCMCIA GPRS card (which is identical to Possio GCC, and which is offered by one of our local GPRS providers). Card has unfortunate feature that after poweron oxcf950 chip is fully powered and works, but attached MC45 modem is powered down :-( There is a special sequence (which takes 1 sec :-( ) to poweron MC45 (and after MC45 powers on, it takes more than 2 secs until firmware fully boots...) which needs to be executed after all powerons. I'm really not familiar with PCMCIA subsystem, so I have no idea whether I should issue request_region() on rest of oxcf950 address range (0-7 is UART, 8-F are special configuration registers), or how this should be better integrated with PM system and so on - I just put it in same place where another hack already lived... Card uses 18.432MHz XTAL, so to get it to work you must add lines below to the /etc/pcmcia/serial.opts. case "$MANFID-$FUNCID-$PRODID_1-$PRODID_2-$PRODID_3-$PRODID_4" in '030c,0003-2-GPRS-CARD--') SERIAL_OPTS="baud_base 1152000" ;; esac Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski --- drivers/serial/serial_cs.c | 52 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 389d847cd1..2c70773543 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -102,6 +103,8 @@ struct serial_info { int multi; int slave; int manfid; + int prodid; + int c950ctrl; dev_node_t node[4]; int line[4]; }; @@ -116,6 +119,33 @@ struct serial_cfg_mem { static int serial_config(struct pcmcia_device * link); +static void wakeup_card(struct serial_info *info) +{ + int ctrl = info->c950ctrl; + + if (info->manfid == MANFID_OXSEMI) { + outb(12, ctrl + 1); + } else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) { + /* request_region? oxsemi branch does no request_region too... */ + /* This sequence is needed to properly initialize MC45 attached to OXCF950. + * I tried decreasing these msleep()s, but it worked properly (survived + * 1000 stop/start operations) with these timeouts (or bigger). */ + outb(0xA, ctrl + 1); + msleep(100); + outb(0xE, ctrl + 1); + msleep(300); + outb(0xC, ctrl + 1); + msleep(100); + outb(0xE, ctrl + 1); + msleep(200); + outb(0xF, ctrl + 1); + msleep(100); + outb(0xE, ctrl + 1); + msleep(100); + outb(0xC, ctrl + 1); + } +} + /*====================================================================== After a card is removed, serial_remove() will unregister @@ -161,6 +191,7 @@ static int serial_resume(struct pcmcia_device *link) for (i = 0; i < info->ndev; i++) serial8250_resume_port(info->line[i]); + wakeup_card(info); } return 0; @@ -503,15 +534,23 @@ static int multi_config(struct pcmcia_device * link) } /* The Oxford Semiconductor OXCF950 cards are in fact single-port: - 8 registers are for the UART, the others are extra registers */ - if (info->manfid == MANFID_OXSEMI) { + * 8 registers are for the UART, the others are extra registers. + * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too. + */ + if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO && + info->prodid == PRODID_POSSIO_GCC)) { + int err; + if (cf->index == 1 || cf->index == 3) { - setup_serial(link, info, base2, link->irq.AssignedIRQ); - outb(12, link->io.BasePort1 + 1); + err = setup_serial(link, info, base2, + link->irq.AssignedIRQ); + base2 = link->io.BasePort1; } else { - setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ); - outb(12, base2 + 1); + err = setup_serial(link, info, link->io.BasePort1, + link->irq.AssignedIRQ); } + info->c950ctrl = base2; + wakeup_card(info); rc = 0; goto free_cfg_mem; } @@ -583,6 +622,7 @@ static int serial_config(struct pcmcia_device * link) tuple->DesiredTuple = CISTPL_MANFID; if (first_tuple(link, tuple, parse) == CS_SUCCESS) { info->manfid = parse->manfid.manf; + info->prodid = le16_to_cpu(buf[1]); for (i = 0; i < MULTI_COUNT; i++) if ((info->manfid == multi_id[i].manfid) && (parse->manfid.card == multi_id[i].prodid)) -- cgit v1.2.2 From b2f51a1cb4e1d72061d7a3f7905affdb7d074fec Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 10 Mar 2006 21:15:19 +0000 Subject: [PATCH] pcmcia: fix pcmcia_device_remove oops Fix pcmcia_device_remove NULL pointer dereference at shutdown. Signed-off-by: Hugh Dickins Signed-off-by: Dominik Brodowski --- drivers/pcmcia/ds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 8966dd0913..ae10d1eed6 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -464,7 +464,7 @@ static int pcmcia_device_remove(struct device * dev) * all devices */ did = (struct pcmcia_device_id *) p_dev->dev.driver_data; - if ((did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && + if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && (p_dev->socket->device_count != 0) && (p_dev->device_no == 0)) pcmcia_card_remove(p_dev->socket, p_dev); -- cgit v1.2.2 From 37466ea85a7f7c9eef071a334e074265df4d1305 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 31 Mar 2006 02:29:39 -0800 Subject: [PATCH] m25p80: printk warning fix drivers/mtd/devices/m25p80.c: In function `m25p80_erase': drivers/mtd/devices/m25p80.c:189: warning: signed size_t format, different type arg (arg 6) Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/devices/m25p80.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index d5f24089be..04e65d5dae 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -186,7 +186,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) struct m25p *flash = mtd_to_m25p(mtd); u32 addr,len; - DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", + DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n", flash->spi->dev.bus_id, __FUNCTION__, "at", (u32)instr->addr, instr->len); -- cgit v1.2.2 From 040d79f906654d55c810313f29c6605593bf21c5 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 31 Mar 2006 02:29:40 -0800 Subject: [PATCH] sem2mutex: mtd/doc2000.c Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/devices/doc2000.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index e4345cf744..0f2c956a90 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -975,13 +976,13 @@ static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, u_char *eccbuf, struct nand_oobinfo *oobsel) { static char static_buf[512]; - static DECLARE_MUTEX(writev_buf_sem); + static DEFINE_MUTEX(writev_buf_mutex); size_t totretlen = 0; size_t thisvecofs = 0; int ret= 0; - down(&writev_buf_sem); + mutex_lock(&writev_buf_mutex); while(count) { size_t thislen, thisretlen; @@ -1024,7 +1025,7 @@ static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, to += thislen; } - up(&writev_buf_sem); + mutex_unlock(&writev_buf_mutex); *retlen = totretlen; return ret; } -- cgit v1.2.2 From 48b192686dd20cb1576ae1d8ccd17a07971ef24a Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 31 Mar 2006 02:29:41 -0800 Subject: [PATCH] sem2mutex: drivers/mtd/ Semaphore to mutex conversion. The conversion was generated via scripts, and the result was validated automatically via a script as well. Signed-off-by: Ingo Molnar Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/devices/blkmtd.c | 10 +++++----- drivers/mtd/devices/block2mtd.c | 13 +++++++------ drivers/mtd/devices/doc2000.c | 30 +++++++++++++++--------------- drivers/mtd/mtd_blkdevs.c | 32 ++++++++++++++++---------------- drivers/mtd/mtdblock.c | 14 ++++++++------ drivers/mtd/mtdcore.c | 32 ++++++++++++++++---------------- 6 files changed, 67 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c index 04f864d238..d732532635 100644 --- a/drivers/mtd/devices/blkmtd.c +++ b/drivers/mtd/devices/blkmtd.c @@ -29,7 +29,7 @@ #include #include #include - +#include #define err(format, arg...) printk(KERN_ERR "blkmtd: " format "\n" , ## arg) #define info(format, arg...) printk(KERN_INFO "blkmtd: " format "\n" , ## arg) @@ -46,7 +46,7 @@ struct blkmtd_dev { struct list_head list; struct block_device *blkdev; struct mtd_info mtd_info; - struct semaphore wrbuf_mutex; + struct mutex wrbuf_mutex; }; @@ -268,7 +268,7 @@ static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to, if(end_len) pagecnt++; - down(&dev->wrbuf_mutex); + mutex_lock(&dev->wrbuf_mutex); DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n", start_len, len, end_len, pagecnt); @@ -376,7 +376,7 @@ static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to, blkmtd_write_out(bio); DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err); - up(&dev->wrbuf_mutex); + mutex_unlock(&dev->wrbuf_mutex); if(retlen) *retlen = thislen; @@ -659,7 +659,7 @@ static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size memset(dev, 0, sizeof(struct blkmtd_dev)); dev->blkdev = bdev; if(!readonly) { - init_MUTEX(&dev->wrbuf_mutex); + mutex_init(&dev->wrbuf_mutex); } dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 7ff403b2a0..4160b8334c 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -18,6 +18,7 @@ #include #include #include +#include #define VERSION "$Revision: 1.30 $" @@ -31,7 +32,7 @@ struct block2mtd_dev { struct list_head list; struct block_device *blkdev; struct mtd_info mtd; - struct semaphore write_mutex; + struct mutex write_mutex; }; @@ -134,9 +135,9 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr) int err; instr->state = MTD_ERASING; - down(&dev->write_mutex); + mutex_lock(&dev->write_mutex); err = _block2mtd_erase(dev, from, len); - up(&dev->write_mutex); + mutex_unlock(&dev->write_mutex); if (err) { ERROR("erase failed err = %d", err); instr->state = MTD_ERASE_FAILED; @@ -249,9 +250,9 @@ static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, if (to + len > mtd->size) len = mtd->size - to; - down(&dev->write_mutex); + mutex_lock(&dev->write_mutex); err = _block2mtd_write(dev, buf, to, len, retlen); - up(&dev->write_mutex); + mutex_unlock(&dev->write_mutex); if (err > 0) err = 0; return err; @@ -310,7 +311,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) goto devinit_err; } - init_MUTEX(&dev->write_mutex); + mutex_init(&dev->write_mutex); /* Setup the MTD structure */ /* make the name contain the block device in */ diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index 0f2c956a90..23e7a5c7d2 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c @@ -606,7 +606,7 @@ static void DoC2k_init(struct mtd_info *mtd) this->curfloor = -1; this->curchip = -1; - init_MUTEX(&this->lock); + mutex_init(&this->lock); /* Ident all the chips present. */ DoC_ScanChips(this, maxchips); @@ -646,7 +646,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, if (from >= this->totlen) return -EINVAL; - down(&this->lock); + mutex_lock(&this->lock); *retlen = 0; while (left) { @@ -775,7 +775,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, buf += len; } - up(&this->lock); + mutex_unlock(&this->lock); return ret; } @@ -804,7 +804,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, if (to >= this->totlen) return -EINVAL; - down(&this->lock); + mutex_lock(&this->lock); *retlen = 0; while (left) { @@ -874,7 +874,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, printk(KERN_ERR "Error programming flash\n"); /* Error in programming */ *retlen = 0; - up(&this->lock); + mutex_unlock(&this->lock); return -EIO; } @@ -936,7 +936,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, printk(KERN_ERR "Error programming flash\n"); /* Error in programming */ *retlen = 0; - up(&this->lock); + mutex_unlock(&this->lock); return -EIO; } @@ -957,7 +957,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, ret = doc_write_oob_nolock(mtd, to, 8, &dummy, x); if (ret) { - up(&this->lock); + mutex_unlock(&this->lock); return ret; } } @@ -967,7 +967,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, buf += len; } - up(&this->lock); + mutex_unlock(&this->lock); return 0; } @@ -1038,7 +1038,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, int len256 = 0, ret; struct Nand *mychip; - down(&this->lock); + mutex_lock(&this->lock); mychip = &this->chips[ofs >> this->chipshift]; @@ -1084,7 +1084,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, ret = DoC_WaitReady(this); - up(&this->lock); + mutex_unlock(&this->lock); return ret; } @@ -1198,10 +1198,10 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, struct DiskOnChip *this = mtd->priv; int ret; - down(&this->lock); + mutex_lock(&this->lock); ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf); - up(&this->lock); + mutex_unlock(&this->lock); return ret; } @@ -1215,10 +1215,10 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) struct Nand *mychip; int status; - down(&this->lock); + mutex_lock(&this->lock); if (ofs & (mtd->erasesize-1) || len & (mtd->erasesize-1)) { - up(&this->lock); + mutex_unlock(&this->lock); return -EINVAL; } @@ -1266,7 +1266,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) callback: mtd_erase_callback(instr); - up(&this->lock); + mutex_unlock(&this->lock); return 0; } diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 840dd66ce2..458d3c8ae1 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -19,12 +19,12 @@ #include #include #include -#include +#include #include static LIST_HEAD(blktrans_majors); -extern struct semaphore mtd_table_mutex; +extern struct mutex mtd_table_mutex; extern struct mtd_info *mtd_table[]; struct mtd_blkcore_priv { @@ -122,9 +122,9 @@ static int mtd_blktrans_thread(void *arg) spin_unlock_irq(rq->queue_lock); - down(&dev->sem); + mutex_lock(&dev->lock); res = do_blktrans_request(tr, dev, req); - up(&dev->sem); + mutex_unlock(&dev->lock); spin_lock_irq(rq->queue_lock); @@ -235,8 +235,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) int last_devnum = -1; struct gendisk *gd; - if (!down_trylock(&mtd_table_mutex)) { - up(&mtd_table_mutex); + if (!!mutex_trylock(&mtd_table_mutex)) { + mutex_unlock(&mtd_table_mutex); BUG(); } @@ -267,7 +267,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) return -EBUSY; } - init_MUTEX(&new->sem); + mutex_init(&new->lock); list_add_tail(&new->list, &tr->devs); added: if (!tr->writesect) @@ -313,8 +313,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) { - if (!down_trylock(&mtd_table_mutex)) { - up(&mtd_table_mutex); + if (!!mutex_trylock(&mtd_table_mutex)) { + mutex_unlock(&mtd_table_mutex); BUG(); } @@ -378,14 +378,14 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) memset(tr->blkcore_priv, 0, sizeof(*tr->blkcore_priv)); - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); ret = register_blkdev(tr->major, tr->name); if (ret) { printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n", tr->name, tr->major, ret); kfree(tr->blkcore_priv); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return ret; } spin_lock_init(&tr->blkcore_priv->queue_lock); @@ -396,7 +396,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) if (!tr->blkcore_priv->rq) { unregister_blkdev(tr->major, tr->name); kfree(tr->blkcore_priv); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return -ENOMEM; } @@ -407,7 +407,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) blk_cleanup_queue(tr->blkcore_priv->rq); unregister_blkdev(tr->major, tr->name); kfree(tr->blkcore_priv); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return ret; } @@ -419,7 +419,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) tr->add_mtd(tr, mtd_table[i]); } - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return 0; } @@ -428,7 +428,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) { struct list_head *this, *next; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); /* Clean up the kernel thread */ tr->blkcore_priv->exiting = 1; @@ -446,7 +446,7 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) blk_cleanup_queue(tr->blkcore_priv->rq); unregister_blkdev(tr->major, tr->name); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); kfree(tr->blkcore_priv); diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index e84756644f..2cef280e38 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -19,11 +19,13 @@ #include #include +#include + static struct mtdblk_dev { struct mtd_info *mtd; int count; - struct semaphore cache_sem; + struct mutex cache_mutex; unsigned char *cache_data; unsigned long cache_offset; unsigned int cache_size; @@ -284,7 +286,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd) mtdblk->count = 1; mtdblk->mtd = mtd; - init_MUTEX (&mtdblk->cache_sem); + mutex_init(&mtdblk->cache_mutex); mtdblk->cache_state = STATE_EMPTY; if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM && mtdblk->mtd->erasesize) { @@ -306,9 +308,9 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd) DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); - down(&mtdblk->cache_sem); + mutex_lock(&mtdblk->cache_mutex); write_cached_data(mtdblk); - up(&mtdblk->cache_sem); + mutex_unlock(&mtdblk->cache_mutex); if (!--mtdblk->count) { /* It was the last usage. Free the device */ @@ -327,9 +329,9 @@ static int mtdblock_flush(struct mtd_blktrans_dev *dev) { struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; - down(&mtdblk->cache_sem); + mutex_lock(&mtdblk->cache_mutex); write_cached_data(mtdblk); - up(&mtdblk->cache_sem); + mutex_unlock(&mtdblk->cache_mutex); if (mtdblk->mtd->sync) mtdblk->mtd->sync(mtdblk->mtd); diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index dade02ab06..9c3813486a 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -27,7 +27,7 @@ /* These are exported solely for the purpose of mtd_blkdevs.c. You should not use them for _anything_ else */ -DECLARE_MUTEX(mtd_table_mutex); +DEFINE_MUTEX(mtd_table_mutex); struct mtd_info *mtd_table[MAX_MTD_DEVICES]; EXPORT_SYMBOL_GPL(mtd_table_mutex); @@ -49,7 +49,7 @@ int add_mtd_device(struct mtd_info *mtd) { int i; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); for (i=0; i < MAX_MTD_DEVICES; i++) if (!mtd_table[i]) { @@ -67,7 +67,7 @@ int add_mtd_device(struct mtd_info *mtd) not->add(mtd); } - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); /* We _know_ we aren't being removed, because our caller is still holding us here. So none of this try_ nonsense, and no bitching about it @@ -76,7 +76,7 @@ int add_mtd_device(struct mtd_info *mtd) return 0; } - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return 1; } @@ -94,7 +94,7 @@ int del_mtd_device (struct mtd_info *mtd) { int ret; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); if (mtd_table[mtd->index] != mtd) { ret = -ENODEV; @@ -118,7 +118,7 @@ int del_mtd_device (struct mtd_info *mtd) ret = 0; } - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return ret; } @@ -135,7 +135,7 @@ void register_mtd_user (struct mtd_notifier *new) { int i; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); list_add(&new->list, &mtd_notifiers); @@ -145,7 +145,7 @@ void register_mtd_user (struct mtd_notifier *new) if (mtd_table[i]) new->add(mtd_table[i]); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); } /** @@ -162,7 +162,7 @@ int unregister_mtd_user (struct mtd_notifier *old) { int i; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); module_put(THIS_MODULE); @@ -171,7 +171,7 @@ int unregister_mtd_user (struct mtd_notifier *old) old->remove(mtd_table[i]); list_del(&old->list); - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return 0; } @@ -193,7 +193,7 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) struct mtd_info *ret = NULL; int i; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); if (num == -1) { for (i=0; i< MAX_MTD_DEVICES; i++) @@ -211,7 +211,7 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) if (ret) ret->usecount++; - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); return ret; } @@ -219,9 +219,9 @@ void put_mtd_device(struct mtd_info *mtd) { int c; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); c = --mtd->usecount; - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); BUG_ON(c < 0); module_put(mtd->owner); @@ -319,7 +319,7 @@ static int mtd_read_proc (char *page, char **start, off_t off, int count, int len, l, i; off_t begin = 0; - down(&mtd_table_mutex); + mutex_lock(&mtd_table_mutex); len = sprintf(page, "dev: size erasesize name\n"); for (i=0; i< MAX_MTD_DEVICES; i++) { @@ -337,7 +337,7 @@ static int mtd_read_proc (char *page, char **start, off_t off, int count, *eof = 1; done: - up(&mtd_table_mutex); + mutex_unlock(&mtd_table_mutex); if (off >= len+begin) return 0; *start = page + (off-begin); -- cgit v1.2.2 From 0500abf52109d09bf60d740dec2e41d6cf265688 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 31 Mar 2006 02:29:42 -0800 Subject: [PATCH] drivers/mtd/: small cleanups - chips/sharp.c: make two needlessly global functions static - move some declarations to a header file where they belong to Signed-off-by: Adrian Bunk Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/chips/sharp.c | 7 +++---- drivers/mtd/inftlcore.c | 5 ----- 2 files changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c index 36f61a6a76..3cc0b23c58 100644 --- a/drivers/mtd/chips/sharp.c +++ b/drivers/mtd/chips/sharp.c @@ -64,7 +64,7 @@ #undef AUTOUNLOCK /* automatically unlocks blocks before erasing */ -struct mtd_info *sharp_probe(struct map_info *); +static struct mtd_info *sharp_probe(struct map_info *); static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd); @@ -96,7 +96,6 @@ struct sharp_info{ struct flchip chips[1]; }; -struct mtd_info *sharp_probe(struct map_info *map); static void sharp_destroy(struct mtd_info *mtd); static struct mtd_chip_driver sharp_chipdrv = { @@ -107,7 +106,7 @@ static struct mtd_chip_driver sharp_chipdrv = { }; -struct mtd_info *sharp_probe(struct map_info *map) +static struct mtd_info *sharp_probe(struct map_info *map) { struct mtd_info *mtd = NULL; struct sharp_info *sharp = NULL; @@ -581,7 +580,7 @@ static void sharp_destroy(struct mtd_info *mtd) } -int __init sharp_probe_init(void) +static int __init sharp_probe_init(void) { printk("MTD Sharp chip driver \n"); diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 8a54489017..abb76aa632 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -47,9 +47,6 @@ */ #define MAX_LOOPS 10000 -extern void INFTL_dumptables(struct INFTLrecord *inftl); -extern void INFTL_dumpVUchains(struct INFTLrecord *inftl); - static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) { struct INFTLrecord *inftl; @@ -885,8 +882,6 @@ static struct mtd_blktrans_ops inftl_tr = { .owner = THIS_MODULE, }; -extern char inftlmountrev[]; - static int __init init_inftl(void) { printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.19 $, " -- cgit v1.2.2 From 54af6b46485bb706b7cdffd2e419253fd00cae6a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 31 Mar 2006 02:29:43 -0800 Subject: [PATCH] MTD_NAND_SHARPSL and MTD_NAND_NANDSIM should be tristate's MTD_NAND=m and MTD_NAND_SHARPSL=y or MTD_NAND_NANDSIM=y are illegal combinations that mustn't be allowed. This patch fixes this bug by making MTD_NAND_SHARPSL and MTD_NAND_NANDSIM tristate's. Additionally, it fixes some whitespace damage at these options. Signed-off-by: Adrian Bunk Acked-by: Richard Purdie Acked-by: "Artem B. Bityutskiy" Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/nand/Kconfig | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 1fc4c134d9..cfe288a6e8 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -178,17 +178,16 @@ config MTD_NAND_DISKONCHIP_BBTWRITE Even if you leave this disabled, you can enable BBT writes at module load time (assuming you build diskonchip as a module) with the module parameter "inftl_bbt_write=1". - - config MTD_NAND_SHARPSL - bool "Support for NAND Flash on Sharp SL Series (C7xx + others)" - depends on MTD_NAND && ARCH_PXA - - config MTD_NAND_NANDSIM - bool "Support for NAND Flash Simulator" - depends on MTD_NAND && MTD_PARTITIONS +config MTD_NAND_SHARPSL + tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)" + depends on MTD_NAND && ARCH_PXA + +config MTD_NAND_NANDSIM + tristate "Support for NAND Flash Simulator" + depends on MTD_NAND && MTD_PARTITIONS help The simulator may simulate verious NAND flash chips for the MTD nand layer. - + endmenu -- cgit v1.2.2 From 87d10f3c7954d143e509a2af2bca2a27aeb3114d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 31 Mar 2006 02:29:45 -0800 Subject: [PATCH] drivers/mtd: Use ARRAY_SIZE macro Use ARRAY_SIZE macro instead of sizeof(x)/sizeof(x[0]) and remove duplicates of the macro. Signed-off-by: Tobias Klauser Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/chips/amd_flash.c | 4 ++-- drivers/mtd/chips/jedec_probe.c | 2 +- drivers/mtd/devices/lart.c | 10 ++++------ drivers/mtd/devices/ms02-nv.c | 2 +- drivers/mtd/maps/alchemy-flash.c | 4 +--- drivers/mtd/maps/cfi_flagadm.c | 2 +- drivers/mtd/maps/dbox2-flash.c | 2 +- drivers/mtd/maps/dilnetpc.c | 4 ++-- drivers/mtd/maps/dmv182.c | 2 +- drivers/mtd/maps/h720x-flash.c | 2 +- drivers/mtd/maps/netsc520.c | 4 ++-- drivers/mtd/maps/nettel.c | 3 +-- drivers/mtd/maps/ocotea.c | 6 ++---- drivers/mtd/maps/pcmciamtd.c | 2 +- drivers/mtd/maps/redwood.c | 3 +-- drivers/mtd/maps/sbc8240.c | 8 +++----- drivers/mtd/maps/sc520cdp.c | 2 +- drivers/mtd/maps/scx200_docflash.c | 2 +- drivers/mtd/maps/sharpsl-flash.c | 4 +--- drivers/mtd/maps/ts5500_flash.c | 2 +- drivers/mtd/maps/uclinux.c | 2 +- drivers/mtd/nand/au1550nd.c | 4 +--- 22 files changed, 31 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c index fdb91b6f1d..57115618c4 100644 --- a/drivers/mtd/chips/amd_flash.c +++ b/drivers/mtd/chips/amd_flash.c @@ -664,7 +664,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map) printk("%s: Probing for AMD compatible flash...\n", map->name); if ((table_pos[0] = probe_new_chip(mtd, 0, NULL, &temp, table, - sizeof(table)/sizeof(table[0]))) + ARRAY_SIZE(table))) == -1) { printk(KERN_WARNING "%s: Found no AMD compatible device at location zero\n", @@ -696,7 +696,7 @@ static struct mtd_info *amd_flash_probe(struct map_info *map) base += (1 << temp.chipshift)) { int numchips = temp.numchips; table_pos[numchips] = probe_new_chip(mtd, base, chips, - &temp, table, sizeof(table)/sizeof(table[0])); + &temp, table, ARRAY_SIZE(table)); } mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info) * diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index edb306c03c..8e24be0fae 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -2035,7 +2035,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, DEBUG(MTD_DEBUG_LEVEL3, "Search for id:(%02x %02x) interleave(%d) type(%d)\n", cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type); - for (i=0; iowner = THIS_MODULE; add_mtd_partitions(flash, ocotea_small_partitions, - NB_OF(ocotea_small_partitions)); + ARRAY_SIZE(ocotea_small_partitions)); } else { printk("map probe failed for flash\n"); return -ENXIO; @@ -118,7 +116,7 @@ int __init init_ocotea(void) if (flash) { flash->owner = THIS_MODULE; add_mtd_partitions(flash, ocotea_large_partitions, - NB_OF(ocotea_large_partitions)); + ARRAY_SIZE(ocotea_large_partitions)); } else { printk("map probe failed for flash\n"); return -ENXIO; diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index f988c817e1..8bbc751a60 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -616,7 +616,7 @@ static void pcmciamtd_config(dev_link_t *link) } else if(mem_type == 2) { mtd = do_map_probe("map_rom", &dev->pcmcia_map); } else { - for(i = 0; i < sizeof(probes) / sizeof(char *); i++) { + for(i = 0; i < ARRAY_SIZE(probes); i++) { DEBUG(1, "Trying %s", probes[i]); mtd = do_map_probe(probes[i], &dev->pcmcia_map); if(mtd) diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c index 5b76ed8861..50b1403361 100644 --- a/drivers/mtd/maps/redwood.c +++ b/drivers/mtd/maps/redwood.c @@ -121,8 +121,7 @@ struct map_info redwood_flash_map = { }; -#define NUM_REDWOOD_FLASH_PARTITIONS \ - (sizeof(redwood_flash_partitions)/sizeof(redwood_flash_partitions[0])) +#define NUM_REDWOOD_FLASH_PARTITIONS ARRAY_SIZE(redwood_flash_partitions) static struct mtd_info *redwood_mtd; diff --git a/drivers/mtd/maps/sbc8240.c b/drivers/mtd/maps/sbc8240.c index 225cdd9ba5..350286dc1d 100644 --- a/drivers/mtd/maps/sbc8240.c +++ b/drivers/mtd/maps/sbc8240.c @@ -66,7 +66,7 @@ static struct map_info sbc8240_map[2] = { } }; -#define NUM_FLASH_BANKS (sizeof(sbc8240_map) / sizeof(struct map_info)) +#define NUM_FLASH_BANKS ARRAY_SIZE(sbc8240_map) /* * The following defines the partition layout of SBC8240 boards. @@ -125,8 +125,6 @@ static struct mtd_partition sbc8240_fs_partitions [] = { } }; -#define NB_OF(x) (sizeof (x) / sizeof (x[0])) - /* trivial struct to describe partition information */ struct mtd_part_def { @@ -190,10 +188,10 @@ int __init init_sbc8240_mtd (void) #ifdef CONFIG_MTD_PARTITIONS sbc8240_part_banks[0].mtd_part = sbc8240_uboot_partitions; sbc8240_part_banks[0].type = "static image"; - sbc8240_part_banks[0].nums = NB_OF(sbc8240_uboot_partitions); + sbc8240_part_banks[0].nums = ARRAY_SIZE(sbc8240_uboot_partitions); sbc8240_part_banks[1].mtd_part = sbc8240_fs_partitions; sbc8240_part_banks[1].type = "static file system"; - sbc8240_part_banks[1].nums = NB_OF(sbc8240_fs_partitions); + sbc8240_part_banks[1].nums = ARRAY_SIZE(sbc8240_fs_partitions); for (i = 0; i < NUM_FLASH_BANKS; i++) { diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c index ed92afadd8..e8c130e1ef 100644 --- a/drivers/mtd/maps/sc520cdp.c +++ b/drivers/mtd/maps/sc520cdp.c @@ -107,7 +107,7 @@ static struct map_info sc520cdp_map[] = { }, }; -#define NUM_FLASH_BANKS (sizeof(sc520cdp_map)/sizeof(struct map_info)) +#define NUM_FLASH_BANKS ARRAY_SIZE(sc520cdp_map) static struct mtd_info *mymtd[NUM_FLASH_BANKS]; static struct mtd_info *merged_mtd; diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c index 2c91dff8bb..28b8a571a9 100644 --- a/drivers/mtd/maps/scx200_docflash.c +++ b/drivers/mtd/maps/scx200_docflash.c @@ -70,7 +70,7 @@ static struct mtd_partition partition_info[] = { .size = 0x80000 }, }; -#define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) +#define NUM_PARTITIONS ARRAY_SIZE(partition_info) #endif diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c index 999f4bb3d8..12fe53c0d2 100644 --- a/drivers/mtd/maps/sharpsl-flash.c +++ b/drivers/mtd/maps/sharpsl-flash.c @@ -49,8 +49,6 @@ static struct mtd_partition sharpsl_partitions[1] = { } }; -#define NB_OF(x) (sizeof(x)/sizeof(x[0])) - int __init init_sharpsl(void) { struct mtd_partition *parts; @@ -92,7 +90,7 @@ int __init init_sharpsl(void) } parts = sharpsl_partitions; - nb_parts = NB_OF(sharpsl_partitions); + nb_parts = ARRAY_SIZE(sharpsl_partitions); printk(KERN_NOTICE "Using %s partision definition\n", part_type); add_mtd_partitions(mymtd, parts, nb_parts); diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c index 4b372bcb17..a7422c2005 100644 --- a/drivers/mtd/maps/ts5500_flash.c +++ b/drivers/mtd/maps/ts5500_flash.c @@ -64,7 +64,7 @@ static struct mtd_partition ts5500_partitions[] = { } }; -#define NUM_PARTITIONS (sizeof(ts5500_partitions)/sizeof(struct mtd_partition)) +#define NUM_PARTITIONS ARRAY_SIZE(ts5500_partitions) static struct mtd_info *mymtd; diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index 79d92808b7..f7264dc2ac 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c @@ -37,7 +37,7 @@ struct mtd_partition uclinux_romfs[] = { { .name = "ROMfs" } }; -#define NUM_PARTITIONS (sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0])) +#define NUM_PARTITIONS ARRAY_SIZE(uclinux_romfs) /****************************************************************************/ diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 201e1362da..bde3550910 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -55,8 +55,6 @@ static const struct mtd_partition partition_info[] = { .size = MTDPART_SIZ_FULL } }; -#define NB_OF(x) (sizeof(x)/sizeof(x[0])) - /** * au_read_byte - read one byte from the chip @@ -462,7 +460,7 @@ int __init au1xxx_nand_init (void) } /* Register the partitions */ - add_mtd_partitions(au1550_mtd, partition_info, NB_OF(partition_info)); + add_mtd_partitions(au1550_mtd, partition_info, ARRAY_SIZE(partition_info)); return 0; -- cgit v1.2.2 From b175d03dd207283609b7f8bfdaa5dc93ac9b16dd Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Fri, 31 Mar 2006 02:29:46 -0800 Subject: [PATCH] mtd cmdlinepart: allow zero offset value Current cmdlinepart.c uses offset value 0 to specify a continuous partition. This prevents creating a second partition starting at 0. For example, I can split 4MB device using "mtdparts=id:2M,2M", but I can not do "mtdparts=id:2M@2M,2M@0" to swap mtd0 and mtd1. This patch introduces special OFFSET_CONTINUOUS value for a continuous partition and allows 0 for offset value. Also this patch replaces 0xffffffff with UINT_MAX for SIZE_REMAINING. Signed-off-by: Atsushi Nemoto Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/cmdlinepart.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index 6b8bb2e4dc..a7a7bfe338 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c @@ -42,7 +42,8 @@ /* special size referring to all the remaining space in a partition */ -#define SIZE_REMAINING 0xffffffff +#define SIZE_REMAINING UINT_MAX +#define OFFSET_CONTINUOUS UINT_MAX struct cmdline_mtd_partition { struct cmdline_mtd_partition *next; @@ -75,7 +76,7 @@ static struct mtd_partition * newpart(char *s, { struct mtd_partition *parts; unsigned long size; - unsigned long offset = 0; + unsigned long offset = OFFSET_CONTINUOUS; char *name; int name_len; unsigned char *extra_mem; @@ -314,7 +315,7 @@ static int parse_cmdline_partitions(struct mtd_info *master, { for(i = 0, offset = 0; i < part->num_parts; i++) { - if (!part->parts[i].offset) + if (part->parts[i].offset == OFFSET_CONTINUOUS) part->parts[i].offset = offset; else offset = part->parts[i].offset; -- cgit v1.2.2 From 8b68a1263305d4e8a07d8a43c996969ea9e44292 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn / snakebyte Date: Fri, 31 Mar 2006 02:29:47 -0800 Subject: [PATCH] Fix debug statement in inftlcore.c Fix a copy/paste bug found by cpminer inside the inftlcore.c file Signed-off-by: Eric Sesterhenn Acked-by: Greg Ungerer Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/inftlcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index abb76aa632..a3b9247971 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -129,7 +129,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) return; } #ifdef PSYCHO_DEBUG - printk(KERN_INFO "INFTL: Found new nftl%c\n", nftl->mbd.devnum + 'a'); + printk(KERN_INFO "INFTL: Found new inftl%c\n", inftl->mbd.devnum + 'a'); #endif return; } -- cgit v1.2.2 From 2d2dce0eb650831046316a9cd091ea5257aa7d4b Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 31 Mar 2006 02:29:49 -0800 Subject: [PATCH] Kill ifdefs in mtdcore.c Kill unneccessary ifdefs in mtdcore.c. Signed-off-by: Pavel Machek Cc: Thomas Gleixner Signed-off-by: Adrian Bunk Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/mtdcore.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 9c3813486a..9905870f56 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -19,9 +19,7 @@ #include #include #include -#ifdef CONFIG_PROC_FS #include -#endif #include @@ -296,10 +294,11 @@ EXPORT_SYMBOL(unregister_mtd_user); EXPORT_SYMBOL(default_mtd_writev); EXPORT_SYMBOL(default_mtd_readv); +#ifdef CONFIG_PROC_FS + /*====================================================================*/ /* Support for /proc/mtd */ -#ifdef CONFIG_PROC_FS static struct proc_dir_entry *proc_mtd; static inline int mtd_proc_info (char *buf, int i) @@ -344,31 +343,27 @@ done: return ((count < begin+len-off) ? count : begin+len-off); } -#endif /* CONFIG_PROC_FS */ - /*====================================================================*/ /* Init code */ static int __init init_mtd(void) { -#ifdef CONFIG_PROC_FS if ((proc_mtd = create_proc_entry( "mtd", 0, NULL ))) proc_mtd->read_proc = mtd_read_proc; -#endif return 0; } static void __exit cleanup_mtd(void) { -#ifdef CONFIG_PROC_FS if (proc_mtd) remove_proc_entry( "mtd", NULL); -#endif } module_init(init_mtd); module_exit(cleanup_mtd); +#endif /* CONFIG_PROC_FS */ + MODULE_LICENSE("GPL"); MODULE_AUTHOR("David Woodhouse "); -- cgit v1.2.2 From edcbce2150fec1f6e6670e14eb65098eebfacae8 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 31 Mar 2006 02:29:50 -0800 Subject: [PATCH] Dead code in mtd/maps/pci.c This fixes coverity bug #12. The first two gotos in the function still have the initial value for mtd set. And the third goto just triggers for !mtd Signed-off-by: Eric Sesterhenn Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/maps/pci.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 21822c2edb..d2ab1bae9c 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c @@ -334,9 +334,6 @@ mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) return 0; release: - if (mtd) - map_destroy(mtd); - if (map) { map->exit(dev, map); kfree(map); -- cgit v1.2.2 From a63ec1b7b7c38f9a61ed11eefd670a49879e9dd3 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 31 Mar 2006 02:29:51 -0800 Subject: [PATCH] Add chip used in collie to jedec_probe This adds flash chip used in Sharp Zaurus sl5500 (collie) to jedec_probe. Values work for read-only access, but I have not figured out how to do read-write. Signed-off-by: Pavel Machek Cc: Richard Purdie Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/chips/jedec_probe.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index 8e24be0fae..517ea33e72 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -34,6 +34,7 @@ #define MANUFACTURER_MACRONIX 0x00C2 #define MANUFACTURER_NEC 0x0010 #define MANUFACTURER_PMC 0x009D +#define MANUFACTURER_SHARP 0x00b0 #define MANUFACTURER_SST 0x00BF #define MANUFACTURER_ST 0x0020 #define MANUFACTURER_TOSHIBA 0x0098 @@ -124,6 +125,9 @@ #define PM49FL004 0x006E #define PM49FL008 0x006A +/* Sharp */ +#define LH28F640BF 0x00b0 + /* ST - www.st.com */ #define M29W800DT 0x00D7 #define M29W800DB 0x005B @@ -1267,6 +1271,19 @@ static const struct amd_flash_info jedec_table[] = { .regions = { ERASEINFO( 0x01000, 256 ) } + }, { + .mfr_id = MANUFACTURER_SHARP, + .dev_id = LH28F640BF, + .name = "LH28F640BF", + .uaddr = { + [0] = MTD_UADDR_UNNECESSARY, /* x8 */ + }, + .DevSize = SIZE_4MiB, + .CmdSet = P_ID_INTEL_STD, + .NumEraseRegions= 1, + .regions = { + ERASEINFO(0x40000,16), + } }, { .mfr_id = MANUFACTURER_SST, .dev_id = SST39LF512, -- cgit v1.2.2 From 84e699e6ec5b431289474f78f8df9dfcc2737085 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Fri, 31 Mar 2006 02:29:52 -0800 Subject: [PATCH] mtd/redboot: Handle holes in fis table Redboot simply sets the first character of a fis entry to 0xff on "fis delete". The kernel redboot parser stops parsing on such an entry, and without this patch any entries after a deleted image would not be detected. Signed-off-by: Peter Korsgaard Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/redboot.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index 8815c8dbef..c077d2ec9c 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c @@ -85,10 +85,6 @@ static int parse_redboot_partitions(struct mtd_info *master, numslots = (master->erasesize / sizeof(struct fis_image_desc)); for (i = 0; i < numslots; i++) { - if (buf[i].name[0] == 0xff) { - i = numslots; - break; - } if (!memcmp(buf[i].name, "FIS directory", 14)) { /* This is apparently the FIS directory entry for the * FIS directory itself. The FIS directory size is @@ -128,7 +124,7 @@ static int parse_redboot_partitions(struct mtd_info *master, struct fis_list *new_fl, **prev; if (buf[i].name[0] == 0xff) - break; + continue; if (!redboot_checksum(&buf[i])) break; -- cgit v1.2.2 From 4d551465986c9a0040f47700a8c736c90519418f Mon Sep 17 00:00:00 2001 From: Herbert Poetzl Date: Fri, 31 Mar 2006 02:29:53 -0800 Subject: [PATCH] mtd: fix broken name_to_dev_t() declaration drivers/mtd/devices/blkmtd.c uses a local declaration of name_to_dev_t() which is inconsistant with the real one. the following patch fixes this by removing the local declaration and including mount.h instead this patch was originally done by Micah Anderson. Signed-off-by: Herbert Poetzl Acked-by: Micah Anderson Acked-by: Daniel Hokka Zakrisson Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/devices/blkmtd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c index d732532635..79f2e1f23e 100644 --- a/drivers/mtd/devices/blkmtd.c +++ b/drivers/mtd/devices/blkmtd.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -614,8 +615,6 @@ static struct mtd_erase_region_info *calc_erase_regions( } -extern dev_t __init name_to_dev_t(const char *line); - static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size) { struct block_device *bdev; -- cgit v1.2.2 From b5ac5d7edb64b3ca1a489b30d95d62492a1f0b80 Mon Sep 17 00:00:00 2001 From: "Petri T. Koistinen" Date: Fri, 31 Mar 2006 02:29:54 -0800 Subject: [PATCH] drivers/mtd/maps/vmax301.c: fix off by one vmax_mtd Fix an obvious off-by-one error (vmax_mtd[] contains two elements). Signed-off-by: Adrian Bunk Cc: Thomas Gleixner Acked-by: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/maps/vmax301.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c index e0063941c0..b3e4873954 100644 --- a/drivers/mtd/maps/vmax301.c +++ b/drivers/mtd/maps/vmax301.c @@ -182,7 +182,7 @@ int __init init_vmax301(void) } } - if (!vmax_mtd[1] && !vmax_mtd[2]) { + if (!vmax_mtd[0] && !vmax_mtd[1]) { iounmap((void *)iomapadr); return -ENXIO; } -- cgit v1.2.2 From 694a464e19b9e3278dbaf6a09fa7c1efec3f8eb5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 31 Mar 2006 02:30:14 -0800 Subject: [PATCH] uml: kconfigs kconfig sanitized around drivers/net Signed-off-by: Al Viro Signed-off-by: Jeff Dike Cc: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/Kconfig | 2 -- drivers/net/tokenring/Kconfig | 2 +- drivers/net/wireless/Kconfig | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e20b849a22..bdaaad8f21 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2313,13 +2313,11 @@ config S2IO_NAPI endmenu -if !UML source "drivers/net/tokenring/Kconfig" source "drivers/net/wireless/Kconfig" source "drivers/net/pcmcia/Kconfig" -endif source "drivers/net/wan/Kconfig" diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig index e4cfc80b28..99c4c1922f 100644 --- a/drivers/net/tokenring/Kconfig +++ b/drivers/net/tokenring/Kconfig @@ -3,7 +3,7 @@ # menu "Token Ring devices" - depends on NETDEVICES + depends on NETDEVICES && !UML # So far, we only have PCI, ISA, and MCA token ring devices config TR diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index f85e301900..bad09ebdb5 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -356,7 +356,7 @@ config PCI_HERMES config ATMEL tristate "Atmel at76c50x chipset 802.11b support" - depends on NET_RADIO + depends on NET_RADIO && (PCI || PCMCIA) select FW_LOADER select CRC32 ---help--- -- cgit v1.2.2 From 9b41046cd0ee0a57f849d6e1363f7933e363cca9 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Fri, 31 Mar 2006 02:30:33 -0800 Subject: [PATCH] Don't pass boot parameters to argv_init[] The boot cmdline is parsed in parse_early_param() and parse_args(,unknown_bootoption). And __setup() is used in obsolete_checksetup(). start_kernel() -> parse_args() -> unknown_bootoption() -> obsolete_checksetup() If __setup()'s callback (->setup_func()) returns 1 in obsolete_checksetup(), obsolete_checksetup() thinks a parameter was handled. If ->setup_func() returns 0, obsolete_checksetup() tries other ->setup_func(). If all ->setup_func() that matched a parameter returns 0, a parameter is seted to argv_init[]. Then, when runing /sbin/init or init=app, argv_init[] is passed to the app. If the app doesn't ignore those arguments, it will warning and exit. This patch fixes a wrong usage of it, however fixes obvious one only. Signed-off-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/ec.c | 4 ++-- drivers/block/amiflop.c | 1 + drivers/media/video/cpia_pp.c | 2 +- drivers/net/netconsole.c | 2 +- drivers/net/pcmcia/xirc2ps_cs.c | 2 +- drivers/pcmcia/vrc4171_card.c | 12 ++++++------ drivers/pcmcia/vrc4173_cardu.c | 8 ++++---- drivers/scsi/ibmmca.c | 2 +- drivers/video/console/fbcon.c | 10 +++++----- drivers/video/console/sticore.c | 4 ++-- drivers/video/fbmem.c | 2 +- drivers/video/stifb.c | 4 ++-- 12 files changed, 27 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 79b09d76c1..eee0864ba3 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1572,7 +1572,7 @@ static void __exit acpi_ec_exit(void) static int __init acpi_fake_ecdt_setup(char *str) { acpi_fake_ecdt_enabled = 1; - return 0; + return 1; } __setup("acpi_fake_ecdt", acpi_fake_ecdt_setup); @@ -1591,7 +1591,7 @@ static int __init acpi_ec_set_intr_mode(char *str) acpi_ec_driver.ops.add = acpi_ec_poll_add; } printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling"); - return 0; + return 1; } __setup("ec_intr=", acpi_ec_set_intr_mode); diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index b6e2909562..2a8af68592 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1850,6 +1850,7 @@ static int __init amiga_floppy_setup (char *str) return 0; printk (KERN_INFO "amiflop: Setting default df0 to %x\n", n); fd_def_df0 = n; + return 1; } __setup("floppy=", amiga_floppy_setup); diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c index 3021f21aae..0b00e6027d 100644 --- a/drivers/media/video/cpia_pp.c +++ b/drivers/media/video/cpia_pp.c @@ -873,7 +873,7 @@ static int __init cpia_pp_setup(char *str) parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE; } - return 0; + return 1; } __setup("cpia_pp=", cpia_pp_setup); diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index edd1b5306b..75b35ad760 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -94,7 +94,7 @@ static struct console netconsole = { static int option_setup(char *opt) { configured = !netpoll_parse_options(&np, opt); - return 0; + return 1; } __setup("netconsole=", option_setup); diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index eed496803f..e8f849e129 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1973,7 +1973,7 @@ static int __init setup_xirc2ps_cs(char *str) MAYBE_SET(lockup_hack, 6); #undef MAYBE_SET - return 0; + return 1; } __setup("xirc2ps_cs=", setup_xirc2ps_cs); diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index 0574efd782..459e6e1946 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c @@ -634,7 +634,7 @@ static void vrc4171_remove_sockets(void) static int __devinit vrc4171_card_setup(char *options) { if (options == NULL || *options == '\0') - return 0; + return 1; if (strncmp(options, "irq:", 4) == 0) { int irq; @@ -644,7 +644,7 @@ static int __devinit vrc4171_card_setup(char *options) vrc4171_irq = irq; if (*options != ',') - return 0; + return 1; options++; } @@ -663,10 +663,10 @@ static int __devinit vrc4171_card_setup(char *options) } if (*options != ',') - return 0; + return 1; options++; } else - return 0; + return 1; } @@ -688,7 +688,7 @@ static int __devinit vrc4171_card_setup(char *options) } if (*options != ',') - return 0; + return 1; options++; if (strncmp(options, "memnoprobe", 10) == 0) @@ -700,7 +700,7 @@ static int __devinit vrc4171_card_setup(char *options) } } - return 0; + return 1; } __setup("vrc4171_card=", vrc4171_card_setup); diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c index 57f38dba0a..6004196f7c 100644 --- a/drivers/pcmcia/vrc4173_cardu.c +++ b/drivers/pcmcia/vrc4173_cardu.c @@ -516,7 +516,7 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev, static int __devinit vrc4173_cardu_setup(char *options) { if (options == NULL || *options == '\0') - return 0; + return 1; if (strncmp(options, "cardu1:", 7) == 0) { options += 7; @@ -527,9 +527,9 @@ static int __devinit vrc4173_cardu_setup(char *options) } if (*options != ',') - return 0; + return 1; } else - return 0; + return 1; } if (strncmp(options, "cardu2:", 7) == 0) { @@ -538,7 +538,7 @@ static int __devinit vrc4173_cardu_setup(char *options) cardu_sockets[CARDU2].noprobe = 1; } - return 0; + return 1; } __setup("vrc4173_cardu=", vrc4173_cardu_setup); diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 3a8462e8d0..24eb59e143 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -2488,7 +2488,7 @@ static int option_setup(char *str) } ints[0] = i - 1; internal_ibmmca_scsi_setup(cur, ints); - return 0; + return 1; } __setup("ibmmcascsi=", option_setup); diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 041d069878..d7351560f5 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -466,7 +466,7 @@ static int __init fb_console_setup(char *this_opt) int i, j; if (!this_opt || !*this_opt) - return 0; + return 1; while ((options = strsep(&this_opt, ",")) != NULL) { if (!strncmp(options, "font:", 5)) @@ -481,10 +481,10 @@ static int __init fb_console_setup(char *this_opt) options++; } if (*options != ',') - return 0; + return 1; options++; } else - return 0; + return 1; } if (!strncmp(options, "map:", 4)) { @@ -496,7 +496,7 @@ static int __init fb_console_setup(char *this_opt) con2fb_map_boot[i] = (options[j++]-'0') % FB_MAX; } - return 0; + return 1; } if (!strncmp(options, "vc:", 3)) { @@ -518,7 +518,7 @@ static int __init fb_console_setup(char *this_opt) rotate = 0; } } - return 0; + return 1; } __setup("fbcon=", fb_console_setup); diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index d6041e781a..74ac2acaf7 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -275,7 +275,7 @@ static int __init sti_setup(char *str) if (str) strlcpy (default_sti_path, str, sizeof (default_sti_path)); - return 0; + return 1; } /* Assuming the machine has multiple STI consoles (=graphic cards) which @@ -321,7 +321,7 @@ static int __init sti_font_setup(char *str) i++; } - return 0; + return 1; } /* The optional linux kernel parameter "sti_font" defines which font diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index b1a8dca764..944855b3e4 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1588,7 +1588,7 @@ static int __init video_setup(char *options) } } - return 0; + return 1; } __setup("video=", video_setup); #endif diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 8d5f35676f..4a292aae6e 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1378,7 +1378,7 @@ stifb_setup(char *options) int i; if (!options || !*options) - return 0; + return 1; if (strncmp(options, "off", 3) == 0) { stifb_disabled = 1; @@ -1393,7 +1393,7 @@ stifb_setup(char *options) stifb_bpp_pref[i] = simple_strtoul(options, &options, 10); } } - return 0; + return 1; } __setup("stifb=", stifb_setup); -- cgit v1.2.2 From da960a6ad1864dd1636cb9b0330d7bb7408aed45 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 31 Mar 2006 02:30:34 -0800 Subject: [PATCH] edac_752x needs CONFIG_HOTPLUG EDAC_752X uses pci_scan_single_device(), which is only available if CONFIG_HOTPLUG is enabled, so limit this driver with HOTPLUG. Signed-off-by: Randy Dunlap Cc: Dave Peterson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index b582d0cdc2..4f0898400c 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -71,7 +71,7 @@ config EDAC_E7XXX config EDAC_E752X tristate "Intel e752x (e7520, e7525, e7320)" - depends on EDAC_MM_EDAC && PCI && X86 + depends on EDAC_MM_EDAC && PCI && X86 && HOTPLUG help Support for error detection and correction on the Intel E7520, E7525, E7320 server chipsets. -- cgit v1.2.2 From ee37df7877eeaa16d7761cce64854110a7c17ad9 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 31 Mar 2006 02:30:35 -0800 Subject: [PATCH] make tty_insert_flip_string a non-GPL export Alan sayeth "Based on Linus original comments about _GPL we should export tty_insert_flip_char as EXPORT_SYMBOL because it used to be EXPORT_SYMBOL equivalent (trivial inline). The other features are new extensions are were not available to drivers before so need not be provided except as _GPL functionality as far as I can see." Addresses http://bugzilla.kernel.org/show_bug.cgi?id=6294 Cc: Alan Cox Cc: Russell King Cc: Paul Fulghum Cc: Philippe Vouters Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 0bfd1b6366..98b126c2de 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -376,7 +376,7 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, s return copied; } -EXPORT_SYMBOL_GPL(tty_insert_flip_string); +EXPORT_SYMBOL(tty_insert_flip_string); int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size) { -- cgit v1.2.2 From 453823ba08ba762b3d58934b6dce75edce37169e Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 31 Mar 2006 02:30:39 -0800 Subject: [PATCH] IPMI: fix startup race condition Matt Domsch noticed a startup race with the IPMI kernel thread, it was possible (though extraordinarly unlikely) that a message could come in before the upper layer was ready to handle it. This patch splits the startup processing of an IPMI interface into two parts, one to get ready and one to actually start the processes to receive messages from the interface. [akpm@osdl.org: cleanups] Signed-off-by: Corey Minyard Cc: Matt Domsch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 9 +++--- drivers/char/ipmi/ipmi_si_intf.c | 59 +++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 40eb005b9d..a0b6f797d9 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -2305,8 +2305,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, void *send_info, struct ipmi_device_id *device_id, struct device *si_dev, - unsigned char slave_addr, - ipmi_smi_t *new_intf) + unsigned char slave_addr) { int i, j; int rv; @@ -2388,9 +2387,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, if (rv) goto out; - /* FIXME - this is an ugly kludge, this sets the intf for the - caller before sending any messages with it. */ - *new_intf = intf; + rv = handlers->start_processing(send_info, intf); + if (rv) + goto out; get_guid(intf); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 35fbd4d8ed..d48d86bd2c 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -972,10 +972,37 @@ static irqreturn_t si_bt_irq_handler(int irq, void *data, struct pt_regs *regs) return si_irq_handler(irq, data, regs); } +static int smi_start_processing(void *send_info, + ipmi_smi_t intf) +{ + struct smi_info *new_smi = send_info; + + new_smi->intf = intf; + + /* Set up the timer that drives the interface. */ + setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi); + new_smi->last_timeout_jiffies = jiffies; + mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES); + + if (new_smi->si_type != SI_BT) { + new_smi->thread = kthread_run(ipmi_thread, new_smi, + "kipmi%d", new_smi->intf_num); + if (IS_ERR(new_smi->thread)) { + printk(KERN_NOTICE "ipmi_si_intf: Could not start" + " kernel thread due to error %ld, only using" + " timers to drive the interface\n", + PTR_ERR(new_smi->thread)); + new_smi->thread = NULL; + } + } + + return 0; +} static struct ipmi_smi_handlers handlers = { .owner = THIS_MODULE, + .start_processing = smi_start_processing, .sender = sender, .request_events = request_events, .set_run_to_completion = set_run_to_completion, @@ -2162,9 +2189,13 @@ static void setup_xaction_handlers(struct smi_info *smi_info) static inline void wait_for_timer_and_thread(struct smi_info *smi_info) { - if (smi_info->thread != NULL && smi_info->thread != ERR_PTR(-ENOMEM)) - kthread_stop(smi_info->thread); - del_timer_sync(&smi_info->si_timer); + if (smi_info->intf) { + /* The timer and thread are only running if the + interface has been started up and registered. */ + if (smi_info->thread != NULL) + kthread_stop(smi_info->thread); + del_timer_sync(&smi_info->si_timer); + } } static struct ipmi_default_vals @@ -2341,21 +2372,6 @@ static int try_smi_init(struct smi_info *new_smi) if (new_smi->irq) new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ; - /* The ipmi_register_smi() code does some operations to - determine the channel information, so we must be ready to - handle operations before it is called. This means we have - to stop the timer if we get an error after this point. */ - init_timer(&(new_smi->si_timer)); - new_smi->si_timer.data = (long) new_smi; - new_smi->si_timer.function = smi_timeout; - new_smi->last_timeout_jiffies = jiffies; - new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; - - add_timer(&(new_smi->si_timer)); - if (new_smi->si_type != SI_BT) - new_smi->thread = kthread_run(ipmi_thread, new_smi, - "kipmi%d", new_smi->intf_num); - if (!new_smi->dev) { /* If we don't already have a device from something * else (like PCI), then register a new one. */ @@ -2365,7 +2381,7 @@ static int try_smi_init(struct smi_info *new_smi) printk(KERN_ERR "ipmi_si_intf:" " Unable to allocate platform device\n"); - goto out_err_stop_timer; + goto out_err; } new_smi->dev = &new_smi->pdev->dev; new_smi->dev->driver = &ipmi_driver; @@ -2377,7 +2393,7 @@ static int try_smi_init(struct smi_info *new_smi) " Unable to register system interface device:" " %d\n", rv); - goto out_err_stop_timer; + goto out_err; } new_smi->dev_registered = 1; } @@ -2386,8 +2402,7 @@ static int try_smi_init(struct smi_info *new_smi) new_smi, &new_smi->device_id, new_smi->dev, - new_smi->slave_addr, - &(new_smi->intf)); + new_smi->slave_addr); if (rv) { printk(KERN_ERR "ipmi_si: Unable to register device: error %d\n", -- cgit v1.2.2 From 8a3628d53fe5eb1d1401dd1ce16655182c1c5ffc Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 31 Mar 2006 02:30:40 -0800 Subject: [PATCH] IPMI: tidy up various things Tidy up various coding standard things, mostly removing the space after !, but also break some long lines and fix a few other spacing inconsistencies. Also fixes some bad error reporting when deleting an IPMI user. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_kcs_sm.c | 8 +++---- drivers/char/ipmi/ipmi_msghandler.c | 48 +++++++++++++++++++------------------ drivers/char/ipmi/ipmi_poweroff.c | 2 +- drivers/char/ipmi/ipmi_si_intf.c | 2 +- drivers/char/ipmi/ipmi_watchdog.c | 8 +++---- 5 files changed, 35 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index da1554194d..2062675f9e 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c @@ -227,7 +227,7 @@ static inline int check_ibf(struct si_sm_data *kcs, unsigned char status, static inline int check_obf(struct si_sm_data *kcs, unsigned char status, long time) { - if (! GET_STATUS_OBF(status)) { + if (!GET_STATUS_OBF(status)) { kcs->obf_timeout -= time; if (kcs->obf_timeout < 0) { start_error_recovery(kcs, "OBF not ready in time"); @@ -407,7 +407,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) } if (state == KCS_READ_STATE) { - if (! check_obf(kcs, status, time)) + if (!check_obf(kcs, status, time)) return SI_SM_CALL_WITH_DELAY; read_next_byte(kcs); } else { @@ -447,7 +447,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) "Not in read state for error2"); break; } - if (! check_obf(kcs, status, time)) + if (!check_obf(kcs, status, time)) return SI_SM_CALL_WITH_DELAY; clear_obf(kcs, status); @@ -462,7 +462,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) break; } - if (! check_obf(kcs, status, time)) + if (!check_obf(kcs, status, time)) return SI_SM_CALL_WITH_DELAY; clear_obf(kcs, status); diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index a0b6f797d9..c0c862cce1 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -557,7 +557,7 @@ unsigned int ipmi_addr_length(int addr_type) static void deliver_response(struct ipmi_recv_msg *msg) { - if (! msg->user) { + if (!msg->user) { ipmi_smi_t intf = msg->user_msg_data; unsigned long flags; @@ -598,11 +598,11 @@ static int intf_next_seq(ipmi_smi_t intf, (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq; i = (i+1)%IPMI_IPMB_NUM_SEQ) { - if (! intf->seq_table[i].inuse) + if (!intf->seq_table[i].inuse) break; } - if (! intf->seq_table[i].inuse) { + if (!intf->seq_table[i].inuse) { intf->seq_table[i].recv_msg = recv_msg; /* Start with the maximum timeout, when the send response @@ -763,7 +763,7 @@ int ipmi_create_user(unsigned int if_num, } new_user = kmalloc(sizeof(*new_user), GFP_KERNEL); - if (! new_user) + if (!new_user) return -ENOMEM; spin_lock_irqsave(&interfaces_lock, flags); @@ -819,14 +819,13 @@ static void free_user(struct kref *ref) int ipmi_destroy_user(ipmi_user_t user) { - int rv = -ENODEV; ipmi_smi_t intf = user->intf; int i; unsigned long flags; struct cmd_rcvr *rcvr; struct cmd_rcvr *rcvrs = NULL; - user->valid = 1; + user->valid = 0; /* Remove the user from the interface's sequence table. */ spin_lock_irqsave(&intf->seq_lock, flags); @@ -871,7 +870,7 @@ int ipmi_destroy_user(ipmi_user_t user) kref_put(&user->refcount, free_user); - return rv; + return 0; } void ipmi_get_version(ipmi_user_t user, @@ -936,7 +935,8 @@ int ipmi_set_gets_events(ipmi_user_t user, int val) if (val) { /* Deliver any queued events. */ - list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) { + list_for_each_entry_safe(msg, msg2, &intf->waiting_events, + link) { list_del(&msg->link); list_add_tail(&msg->link, &msgs); } @@ -978,7 +978,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL); - if (! rcvr) + if (!rcvr) return -ENOMEM; rcvr->cmd = cmd; rcvr->netfn = netfn; @@ -1514,7 +1514,7 @@ int ipmi_request_settime(ipmi_user_t user, unsigned char saddr, lun; int rv; - if (! user) + if (!user) return -EINVAL; rv = check_addr(user->intf, addr, &saddr, &lun); if (rv) @@ -1545,7 +1545,7 @@ int ipmi_request_supply_msgs(ipmi_user_t user, unsigned char saddr, lun; int rv; - if (! user) + if (!user) return -EINVAL; rv = check_addr(user->intf, addr, &saddr, &lun); if (rv) @@ -1570,7 +1570,7 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off, char *out = (char *) page; ipmi_smi_t intf = data; int i; - int rv= 0; + int rv = 0; for (i = 0; i < IPMI_MAX_CHANNELS; i++) rv += sprintf(out+rv, "%x ", intf->channels[i].address); @@ -1989,7 +1989,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf) } else { bmc->dev = platform_device_alloc("ipmi_bmc", bmc->id.device_id); - if (! bmc->dev) { + if (!bmc->dev) { printk(KERN_ERR "ipmi_msghandler:" " Unable to allocate platform device\n"); @@ -2621,7 +2621,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, spin_unlock_irqrestore(&intf->counter_lock, flags); recv_msg = ipmi_alloc_recv_msg(); - if (! recv_msg) { + if (!recv_msg) { /* We couldn't allocate memory for the message, so requeue it for handling later. */ @@ -2776,7 +2776,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, spin_unlock_irqrestore(&intf->counter_lock, flags); recv_msg = ipmi_alloc_recv_msg(); - if (! recv_msg) { + if (!recv_msg) { /* We couldn't allocate memory for the message, so requeue it for handling later. */ @@ -2868,13 +2868,14 @@ static int handle_read_event_rsp(ipmi_smi_t intf, events. */ rcu_read_lock(); list_for_each_entry_rcu(user, &intf->users, link) { - if (! user->gets_events) + if (!user->gets_events) continue; recv_msg = ipmi_alloc_recv_msg(); - if (! recv_msg) { + if (!recv_msg) { rcu_read_unlock(); - list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) { + list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, + link) { list_del(&recv_msg->link); ipmi_free_recv_msg(recv_msg); } @@ -2904,7 +2905,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf, /* No one to receive the message, put it in queue if there's not already too many things in the queue. */ recv_msg = ipmi_alloc_recv_msg(); - if (! recv_msg) { + if (!recv_msg) { /* We couldn't allocate memory for the message, so requeue it for handling later. */ @@ -3189,7 +3190,7 @@ void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) rcu_read_lock(); list_for_each_entry_rcu(user, &intf->users, link) { - if (! user->handler->ipmi_watchdog_pretimeout) + if (!user->handler->ipmi_watchdog_pretimeout) continue; user->handler->ipmi_watchdog_pretimeout(user->handler_data); @@ -3277,7 +3278,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, ent->seqid); - if (! smi_msg) + if (!smi_msg) return; spin_unlock_irqrestore(&intf->seq_lock, *flags); @@ -3313,8 +3314,9 @@ static void ipmi_timeout_handler(long timeout_period) /* See if any waiting messages need to be processed. */ spin_lock_irqsave(&intf->waiting_msgs_lock, flags); - list_for_each_entry_safe(smi_msg, smi_msg2, &intf->waiting_msgs, link) { - if (! handle_new_recv_msg(intf, smi_msg)) { + list_for_each_entry_safe(smi_msg, smi_msg2, + &intf->waiting_msgs, link) { + if (!handle_new_recv_msg(intf, smi_msg)) { list_del(&smi_msg->link); ipmi_free_smi_msg(smi_msg); } else { diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 786a2802ca..d0b5c08e7b 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -346,7 +346,7 @@ static int ipmi_dell_chassis_detect (ipmi_user_t user) { const char ipmi_version_major = ipmi_version & 0xF; const char ipmi_version_minor = (ipmi_version >> 4) & 0xF; - const char mfr[3]=DELL_IANA_MFR_ID; + const char mfr[3] = DELL_IANA_MFR_ID; if (!memcmp(mfr, &mfg_id, sizeof(mfr)) && ipmi_version_major <= 1 && ipmi_version_minor < 5) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index d48d86bd2c..2da5845a38 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -803,7 +803,7 @@ static int ipmi_thread(void *data) set_user_nice(current, 19); while (!kthread_should_stop()) { spin_lock_irqsave(&(smi_info->si_lock), flags); - smi_result=smi_event_handler(smi_info, 0); + smi_result = smi_event_handler(smi_info, 0); spin_unlock_irqrestore(&(smi_info->si_lock), flags); if (smi_result == SI_SM_CALL_WITHOUT_DELAY) { /* do nothing */ diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 7ece9f3c8f..2872c95755 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -589,7 +589,7 @@ static void panic_halt_ipmi_heartbeat(void) 1); } -static struct watchdog_info ident= +static struct watchdog_info ident = { .options = 0, /* WDIOF_SETTIMEOUT, */ .firmware_version = 1, @@ -790,13 +790,13 @@ static int ipmi_fasync(int fd, struct file *file, int on) static int ipmi_close(struct inode *ino, struct file *filep) { - if (iminor(ino)==WATCHDOG_MINOR) - { + if (iminor(ino) == WATCHDOG_MINOR) { if (expect_close == 42) { ipmi_watchdog_state = WDOG_TIMEOUT_NONE; ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); } else { - printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + printk(KERN_CRIT PFX + "Unexpected close, not stopping watchdog!\n"); ipmi_heartbeat(); } clear_bit(0, &ipmi_wdog_open); -- cgit v1.2.2 From d6dfd1310d3562698fd7c3c086f6c239f96394ac Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 31 Mar 2006 02:30:41 -0800 Subject: [PATCH] IPMI: convert from semaphores to mutexes Convert the remaining semaphores to mutexes in the IPMI driver. The watchdog was using a semaphore as a real semaphore (for IPC), so the conversion there required adding a completion. Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_devintf.c | 18 ++++++------- drivers/char/ipmi/ipmi_msghandler.c | 23 ++++++++-------- drivers/char/ipmi/ipmi_si_intf.c | 24 ++++++++--------- drivers/char/ipmi/ipmi_watchdog.c | 53 +++++++++++++++++++++---------------- 4 files changed, 63 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 932feedda2..e1c9537498 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include @@ -55,7 +55,7 @@ struct ipmi_file_private struct file *file; struct fasync_struct *fasync_queue; wait_queue_head_t wait; - struct semaphore recv_sem; + struct mutex recv_mutex; int default_retries; unsigned int default_retry_time_ms; }; @@ -141,7 +141,7 @@ static int ipmi_open(struct inode *inode, struct file *file) INIT_LIST_HEAD(&(priv->recv_msgs)); init_waitqueue_head(&priv->wait); priv->fasync_queue = NULL; - sema_init(&(priv->recv_sem), 1); + mutex_init(&priv->recv_mutex); /* Use the low-level defaults. */ priv->default_retries = -1; @@ -285,15 +285,15 @@ static int ipmi_ioctl(struct inode *inode, break; } - /* We claim a semaphore because we don't want two + /* We claim a mutex because we don't want two users getting something from the queue at a time. Since we have to release the spinlock before we can copy the data to the user, it's possible another user will grab something from the queue, too. Then the messages might get out of order if something fails and the message gets put back onto the - queue. This semaphore prevents that problem. */ - down(&(priv->recv_sem)); + queue. This mutex prevents that problem. */ + mutex_lock(&priv->recv_mutex); /* Grab the message off the list. */ spin_lock_irqsave(&(priv->recv_msg_lock), flags); @@ -352,7 +352,7 @@ static int ipmi_ioctl(struct inode *inode, goto recv_putback_on_err; } - up(&(priv->recv_sem)); + mutex_unlock(&priv->recv_mutex); ipmi_free_recv_msg(msg); break; @@ -362,11 +362,11 @@ static int ipmi_ioctl(struct inode *inode, spin_lock_irqsave(&(priv->recv_msg_lock), flags); list_add(entry, &(priv->recv_msgs)); spin_unlock_irqrestore(&(priv->recv_msg_lock), flags); - up(&(priv->recv_sem)); + mutex_unlock(&priv->recv_mutex); break; recv_err: - up(&(priv->recv_sem)); + mutex_unlock(&priv->recv_mutex); break; } diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index c0c862cce1..0ded046d5a 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -234,7 +235,7 @@ struct ipmi_smi /* The list of command receivers that are registered for commands on this interface. */ - struct semaphore cmd_rcvrs_lock; + struct mutex cmd_rcvrs_mutex; struct list_head cmd_rcvrs; /* Events that were queues because no one was there to receive @@ -387,10 +388,10 @@ static void clean_up_interface_data(ipmi_smi_t intf) /* Wholesale remove all the entries from the list in the * interface and wait for RCU to know that none are in use. */ - down(&intf->cmd_rcvrs_lock); + mutex_lock(&intf->cmd_rcvrs_mutex); list_add_rcu(&list, &intf->cmd_rcvrs); list_del_rcu(&intf->cmd_rcvrs); - up(&intf->cmd_rcvrs_lock); + mutex_unlock(&intf->cmd_rcvrs_mutex); synchronize_rcu(); list_for_each_entry_safe(rcvr, rcvr2, &list, link) @@ -846,7 +847,7 @@ int ipmi_destroy_user(ipmi_user_t user) * since other things may be using it till we do * synchronize_rcu()) then free everything in that list. */ - down(&intf->cmd_rcvrs_lock); + mutex_lock(&intf->cmd_rcvrs_mutex); list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { if (rcvr->user == user) { list_del_rcu(&rcvr->link); @@ -854,7 +855,7 @@ int ipmi_destroy_user(ipmi_user_t user) rcvrs = rcvr; } } - up(&intf->cmd_rcvrs_lock); + mutex_unlock(&intf->cmd_rcvrs_mutex); synchronize_rcu(); while (rcvrs) { rcvr = rcvrs; @@ -984,7 +985,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, rcvr->netfn = netfn; rcvr->user = user; - down(&intf->cmd_rcvrs_lock); + mutex_lock(&intf->cmd_rcvrs_mutex); /* Make sure the command/netfn is not already registered. */ entry = find_cmd_rcvr(intf, netfn, cmd); if (entry) { @@ -995,7 +996,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); out_unlock: - up(&intf->cmd_rcvrs_lock); + mutex_unlock(&intf->cmd_rcvrs_mutex); if (rv) kfree(rcvr); @@ -1009,17 +1010,17 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, ipmi_smi_t intf = user->intf; struct cmd_rcvr *rcvr; - down(&intf->cmd_rcvrs_lock); + mutex_lock(&intf->cmd_rcvrs_mutex); /* Make sure the command/netfn is not already registered. */ rcvr = find_cmd_rcvr(intf, netfn, cmd); if ((rcvr) && (rcvr->user == user)) { list_del_rcu(&rcvr->link); - up(&intf->cmd_rcvrs_lock); + mutex_unlock(&intf->cmd_rcvrs_mutex); synchronize_rcu(); kfree(rcvr); return 0; } else { - up(&intf->cmd_rcvrs_lock); + mutex_unlock(&intf->cmd_rcvrs_mutex); return -ENOENT; } } @@ -2365,7 +2366,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, spin_lock_init(&intf->events_lock); INIT_LIST_HEAD(&intf->waiting_events); intf->waiting_events_count = 0; - init_MUTEX(&intf->cmd_rcvrs_lock); + mutex_init(&intf->cmd_rcvrs_mutex); INIT_LIST_HEAD(&intf->cmd_rcvrs); init_waitqueue_head(&intf->waitq); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 2da5845a38..a86c0f2995 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1014,7 +1014,7 @@ static struct ipmi_smi_handlers handlers = #define SI_MAX_PARMS 4 static LIST_HEAD(smi_infos); -static DECLARE_MUTEX(smi_infos_lock); +static DEFINE_MUTEX(smi_infos_lock); static int smi_num; /* Used to sequence the SMIs */ #define DEFAULT_REGSPACING 1 @@ -2276,7 +2276,7 @@ static int try_smi_init(struct smi_info *new_smi) new_smi->slave_addr, new_smi->irq); } - down(&smi_infos_lock); + mutex_lock(&smi_infos_lock); if (!is_new_interface(new_smi)) { printk(KERN_WARNING "ipmi_si: duplicate interface\n"); rv = -EBUSY; @@ -2432,7 +2432,7 @@ static int try_smi_init(struct smi_info *new_smi) list_add_tail(&new_smi->link, &smi_infos); - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]); @@ -2469,7 +2469,7 @@ static int try_smi_init(struct smi_info *new_smi) kfree(new_smi); - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); return rv; } @@ -2527,26 +2527,26 @@ static __devinit int init_ipmi_si(void) #endif if (si_trydefaults) { - down(&smi_infos_lock); + mutex_lock(&smi_infos_lock); if (list_empty(&smi_infos)) { /* No BMC was found, try defaults. */ - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); default_find_bmc(); } else { - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); } } - down(&smi_infos_lock); + mutex_lock(&smi_infos_lock); if (list_empty(&smi_infos)) { - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); #ifdef CONFIG_PCI pci_unregister_driver(&ipmi_pci_driver); #endif printk("ipmi_si: Unable to find any System Interface(s)\n"); return -ENODEV; } else { - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); return 0; } } @@ -2622,10 +2622,10 @@ static __exit void cleanup_ipmi_si(void) pci_unregister_driver(&ipmi_pci_driver); #endif - down(&smi_infos_lock); + mutex_lock(&smi_infos_lock); list_for_each_entry_safe(e, tmp_e, &smi_infos, link) cleanup_one_si(e); - up(&smi_infos_lock); + mutex_unlock(&smi_infos_lock); driver_unregister(&ipmi_driver); } diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 2872c95755..2d11ddd99e 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -303,21 +304,22 @@ static int ipmi_heartbeat(void); static void panic_halt_ipmi_heartbeat(void); -/* We use a semaphore to make sure that only one thing can send a set +/* We use a mutex to make sure that only one thing can send a set timeout at one time, because we only have one copy of the data. - The semaphore is claimed when the set_timeout is sent and freed + The mutex is claimed when the set_timeout is sent and freed when both messages are free. */ static atomic_t set_timeout_tofree = ATOMIC_INIT(0); -static DECLARE_MUTEX(set_timeout_lock); +static DEFINE_MUTEX(set_timeout_lock); +static DECLARE_COMPLETION(set_timeout_wait); static void set_timeout_free_smi(struct ipmi_smi_msg *msg) { if (atomic_dec_and_test(&set_timeout_tofree)) - up(&set_timeout_lock); + complete(&set_timeout_wait); } static void set_timeout_free_recv(struct ipmi_recv_msg *msg) { if (atomic_dec_and_test(&set_timeout_tofree)) - up(&set_timeout_lock); + complete(&set_timeout_wait); } static struct ipmi_smi_msg set_timeout_smi_msg = { @@ -399,7 +401,7 @@ static int ipmi_set_timeout(int do_heartbeat) /* We can only send one of these at a time. */ - down(&set_timeout_lock); + mutex_lock(&set_timeout_lock); atomic_set(&set_timeout_tofree, 2); @@ -407,16 +409,21 @@ static int ipmi_set_timeout(int do_heartbeat) &set_timeout_recv_msg, &send_heartbeat_now); if (rv) { - up(&set_timeout_lock); - } else { - if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) - || ((send_heartbeat_now) - && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) - { - rv = ipmi_heartbeat(); - } + mutex_unlock(&set_timeout_lock); + goto out; + } + + wait_for_completion(&set_timeout_wait); + + if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) + || ((send_heartbeat_now) + && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) + { + rv = ipmi_heartbeat(); } + mutex_unlock(&set_timeout_lock); +out: return rv; } @@ -458,17 +465,17 @@ static void panic_halt_ipmi_set_timeout(void) The semaphore is claimed when the set_timeout is sent and freed when both messages are free. */ static atomic_t heartbeat_tofree = ATOMIC_INIT(0); -static DECLARE_MUTEX(heartbeat_lock); -static DECLARE_MUTEX_LOCKED(heartbeat_wait_lock); +static DEFINE_MUTEX(heartbeat_lock); +static DECLARE_COMPLETION(heartbeat_wait); static void heartbeat_free_smi(struct ipmi_smi_msg *msg) { if (atomic_dec_and_test(&heartbeat_tofree)) - up(&heartbeat_wait_lock); + complete(&heartbeat_wait); } static void heartbeat_free_recv(struct ipmi_recv_msg *msg) { if (atomic_dec_and_test(&heartbeat_tofree)) - up(&heartbeat_wait_lock); + complete(&heartbeat_wait); } static struct ipmi_smi_msg heartbeat_smi_msg = { @@ -511,14 +518,14 @@ static int ipmi_heartbeat(void) return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); } - down(&heartbeat_lock); + mutex_lock(&heartbeat_lock); atomic_set(&heartbeat_tofree, 2); /* Don't reset the timer if we have the timer turned off, that re-enables the watchdog. */ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) { - up(&heartbeat_lock); + mutex_unlock(&heartbeat_lock); return 0; } @@ -539,14 +546,14 @@ static int ipmi_heartbeat(void) &heartbeat_recv_msg, 1); if (rv) { - up(&heartbeat_lock); + mutex_unlock(&heartbeat_lock); printk(KERN_WARNING PFX "heartbeat failure: %d\n", rv); return rv; } /* Wait for the heartbeat to be sent. */ - down(&heartbeat_wait_lock); + wait_for_completion(&heartbeat_wait); if (heartbeat_recv_msg.msg.data[0] != 0) { /* Got an error in the heartbeat response. It was already @@ -555,7 +562,7 @@ static int ipmi_heartbeat(void) rv = -EINVAL; } - up(&heartbeat_lock); + mutex_unlock(&heartbeat_lock); return rv; } -- cgit v1.2.2 From 0000754c27f07d5656eff17367c05dc4cfb7d965 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 31 Mar 2006 02:30:47 -0800 Subject: [PATCH] "3c59x collision statistics fix" fix The pre-2.6.16 patch "3c59x collision statistics fix" accidentally caused vortex_error() to not run iowrite16(TxEnable, ioaddr + EL3_CMD) if we got a maxCollisions interrupt but MAX_COLLISION_RESET is not set. Thanks to Pete Clements for reporting and testing. Acked-by: Steffen Klassert Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 70f63891b1..5112907985 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -2083,16 +2083,14 @@ vortex_error(struct net_device *dev, int status) } if (tx_status & 0x14) vp->stats.tx_fifo_errors++; if (tx_status & 0x38) vp->stats.tx_aborted_errors++; + if (tx_status & 0x08) vp->xstats.tx_max_collisions++; iowrite8(0, ioaddr + TxStatus); if (tx_status & 0x30) { /* txJabber or txUnderrun */ do_tx_reset = 1; - } else if (tx_status & 0x08) { /* maxCollisions */ - vp->xstats.tx_max_collisions++; - if (vp->drv_flags & MAX_COLLISION_RESET) { - do_tx_reset = 1; - reset_mask = 0x0108; /* Reset interface logic, but not download logic */ - } - } else { /* Merely re-enable the transmitter. */ + } else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) { /* maxCollisions */ + do_tx_reset = 1; + reset_mask = 0x0108; /* Reset interface logic, but not download logic */ + } else { /* Merely re-enable the transmitter. */ iowrite16(TxEnable, ioaddr + EL3_CMD); } } -- cgit v1.2.2 From 09ce3512dcad0ad1d07eee0dc5ebb6d037c39c16 Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Fri, 31 Mar 2006 02:30:48 -0800 Subject: [PATCH] 3c59x: fix networking for 10base2 NICs The "3c59x: use mii_check_media" patch introduced a netif_carrier_off in vortex_up. 10base2 stoped working because of this. This is removed. Tx/Rx reset is back in vortex_up because the 3c900B-Combo stops working after changing from half duplex to full duplex when Tx/Rx reset is done with vortex_timer. Also brought back some mii stuff to be sure that it does not break something else. Thanks to Pete Clements for reporting and testing. Signed-off-by: Steffen Klassert Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/3c59x.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 5112907985..274b0138d4 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -788,7 +788,7 @@ struct vortex_private { int options; /* User-settable misc. driver options. */ unsigned int media_override:4, /* Passed-in media type. */ default_media:4, /* Read from the EEPROM/Wn3_Config. */ - full_duplex:1, force_fd:1, autoselect:1, + full_duplex:1, autoselect:1, bus_master:1, /* Vortex can only do a fragment bus-m. */ full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */ flow_ctrl:1, /* Use 802.3x flow control (PAUSE only) */ @@ -1633,12 +1633,6 @@ vortex_set_duplex(struct net_device *dev) ((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0), ioaddr + Wn3_MAC_Ctrl); - - issue_and_wait(dev, TxReset); - /* - * Don't reset the PHY - that upsets autonegotiation during DHCP operations. - */ - issue_and_wait(dev, RxReset|0x04); } static void vortex_check_media(struct net_device *dev, unsigned int init) @@ -1663,7 +1657,7 @@ vortex_up(struct net_device *dev) struct vortex_private *vp = netdev_priv(dev); void __iomem *ioaddr = vp->ioaddr; unsigned int config; - int i; + int i, mii_reg1, mii_reg5; if (VORTEX_PCI(vp)) { pci_set_power_state(VORTEX_PCI(vp), PCI_D0); /* Go active */ @@ -1723,14 +1717,23 @@ vortex_up(struct net_device *dev) printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config); iowrite32(config, ioaddr + Wn3_Config); - netif_carrier_off(dev); if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { EL3WINDOW(4); + mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR); + mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA); + vp->partner_flow_ctrl = ((mii_reg5 & 0x0400) != 0); + vortex_check_media(dev, 1); } else vortex_set_duplex(dev); + issue_and_wait(dev, TxReset); + /* + * Don't reset the PHY - that upsets autonegotiation during DHCP operations. + */ + issue_and_wait(dev, RxReset|0x04); + iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD); -- cgit v1.2.2 From b0b4ed728cdd0c7204392b0c18857e4a99917aa5 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 31 Mar 2006 02:30:56 -0800 Subject: [PATCH] drivers/char/[i]stallion: Clean up kmalloc usage Delete two useless kmalloc wrappers and use kmalloc/kzalloc. Some weird NULL checks are also simplified. Signed-off-by: Tobias Klauser Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/istallion.c | 32 +++++++++----------------------- drivers/char/stallion.c | 46 +++++++++++++++------------------------------- 2 files changed, 24 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index e5247f85a4..ef20c1fc9c 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -706,7 +706,6 @@ static int stli_portcmdstats(stliport_t *portp); static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp); static int stli_getportstruct(stliport_t __user *arg); static int stli_getbrdstruct(stlibrd_t __user *arg); -static void *stli_memalloc(int len); static stlibrd_t *stli_allocbrd(void); static void stli_ecpinit(stlibrd_t *brdp); @@ -997,17 +996,6 @@ static int stli_parsebrd(stlconf_t *confp, char **argp) /*****************************************************************************/ -/* - * Local driver kernel malloc routine. - */ - -static void *stli_memalloc(int len) -{ - return((void *) kmalloc(len, GFP_KERNEL)); -} - -/*****************************************************************************/ - static int stli_open(struct tty_struct *tty, struct file *filp) { stlibrd_t *brdp; @@ -3227,13 +3215,12 @@ static int stli_initports(stlibrd_t *brdp) #endif for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { - portp = (stliport_t *) stli_memalloc(sizeof(stliport_t)); - if (portp == (stliport_t *) NULL) { + portp = kzalloc(sizeof(stliport_t), GFP_KERNEL); + if (!portp) { printk("STALLION: failed to allocate port structure\n"); continue; } - memset(portp, 0, sizeof(stliport_t)); portp->magic = STLI_PORTMAGIC; portp->portnr = i; portp->brdnr = brdp->brdnr; @@ -4610,14 +4597,13 @@ static stlibrd_t *stli_allocbrd(void) { stlibrd_t *brdp; - brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t)); - if (brdp == (stlibrd_t *) NULL) { + brdp = kzalloc(sizeof(stlibrd_t), GFP_KERNEL); + if (!brdp) { printk(KERN_ERR "STALLION: failed to allocate memory " "(size=%d)\n", sizeof(stlibrd_t)); - return((stlibrd_t *) NULL); + return NULL; } - memset(brdp, 0, sizeof(stlibrd_t)); brdp->magic = STLI_BOARDMAGIC; return(brdp); } @@ -5210,12 +5196,12 @@ int __init stli_init(void) /* * Allocate a temporary write buffer. */ - stli_tmpwritebuf = (char *) stli_memalloc(STLI_TXBUFSIZE); - if (stli_tmpwritebuf == (char *) NULL) + stli_tmpwritebuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); + if (!stli_tmpwritebuf) printk(KERN_ERR "STALLION: failed to allocate memory " "(size=%d)\n", STLI_TXBUFSIZE); - stli_txcookbuf = stli_memalloc(STLI_TXBUFSIZE); - if (stli_txcookbuf == (char *) NULL) + stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); + if (!stli_txcookbuf) printk(KERN_ERR "STALLION: failed to allocate memory " "(size=%d)\n", STLI_TXBUFSIZE); diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 3f5d6077f3..a9c5a7230f 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -504,7 +504,6 @@ static int stl_echmcaintr(stlbrd_t *brdp); static int stl_echpciintr(stlbrd_t *brdp); static int stl_echpci64intr(stlbrd_t *brdp); static void stl_offintr(void *private); -static void *stl_memalloc(int len); static stlbrd_t *stl_allocbrd(void); static stlport_t *stl_getport(int brdnr, int panelnr, int portnr); @@ -939,17 +938,6 @@ static int stl_parsebrd(stlconf_t *confp, char **argp) /*****************************************************************************/ -/* - * Local driver kernel memory allocation routine. - */ - -static void *stl_memalloc(int len) -{ - return (void *) kmalloc(len, GFP_KERNEL); -} - -/*****************************************************************************/ - /* * Allocate a new board structure. Fill out the basic info in it. */ @@ -958,14 +946,13 @@ static stlbrd_t *stl_allocbrd(void) { stlbrd_t *brdp; - brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t)); - if (brdp == (stlbrd_t *) NULL) { + brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL); + if (!brdp) { printk("STALLION: failed to allocate memory (size=%d)\n", sizeof(stlbrd_t)); - return (stlbrd_t *) NULL; + return NULL; } - memset(brdp, 0, sizeof(stlbrd_t)); brdp->magic = STL_BOARDMAGIC; return brdp; } @@ -1017,9 +1004,9 @@ static int stl_open(struct tty_struct *tty, struct file *filp) portp->refcount++; if ((portp->flags & ASYNC_INITIALIZED) == 0) { - if (portp->tx.buf == (char *) NULL) { - portp->tx.buf = (char *) stl_memalloc(STL_TXBUFSIZE); - if (portp->tx.buf == (char *) NULL) + if (!portp->tx.buf) { + portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); + if (!portp->tx.buf) return -ENOMEM; portp->tx.head = portp->tx.buf; portp->tx.tail = portp->tx.buf; @@ -2178,13 +2165,12 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) * each ports data structures. */ for (i = 0; (i < panelp->nrports); i++) { - portp = (stlport_t *) stl_memalloc(sizeof(stlport_t)); - if (portp == (stlport_t *) NULL) { + portp = kzalloc(sizeof(stlport_t), GFP_KERNEL); + if (!portp) { printk("STALLION: failed to allocate memory " "(size=%d)\n", sizeof(stlport_t)); break; } - memset(portp, 0, sizeof(stlport_t)); portp->magic = STL_PORTMAGIC; portp->portnr = i; @@ -2315,13 +2301,12 @@ static inline int stl_initeio(stlbrd_t *brdp) * can complete the setup. */ - panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t)); - if (panelp == (stlpanel_t *) NULL) { + panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); + if (!panelp) { printk(KERN_WARNING "STALLION: failed to allocate memory " "(size=%d)\n", sizeof(stlpanel_t)); - return(-ENOMEM); + return -ENOMEM; } - memset(panelp, 0, sizeof(stlpanel_t)); panelp->magic = STL_PANELMAGIC; panelp->brdnr = brdp->brdnr; @@ -2490,13 +2475,12 @@ static inline int stl_initech(stlbrd_t *brdp) status = inb(ioaddr + ECH_PNLSTATUS); if ((status & ECH_PNLIDMASK) != nxtid) break; - panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t)); - if (panelp == (stlpanel_t *) NULL) { + panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); + if (!panelp) { printk("STALLION: failed to allocate memory " "(size=%d)\n", sizeof(stlpanel_t)); break; } - memset(panelp, 0, sizeof(stlpanel_t)); panelp->magic = STL_PANELMAGIC; panelp->brdnr = brdp->brdnr; panelp->panelnr = panelnr; @@ -3074,8 +3058,8 @@ static int __init stl_init(void) /* * Allocate a temporary write buffer. */ - stl_tmpwritebuf = (char *) stl_memalloc(STL_TXBUFSIZE); - if (stl_tmpwritebuf == (char *) NULL) + stl_tmpwritebuf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); + if (!stl_tmpwritebuf) printk("STALLION: failed to allocate memory (size=%d)\n", STL_TXBUFSIZE); -- cgit v1.2.2 From d32af0fe11b1618572389723e93cf33a4cc11c81 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Fri, 31 Mar 2006 02:30:57 -0800 Subject: [PATCH] ISDN: fix a few memory leaks in sc_ioctl() Fix a few memory leaks in drivers/isdn/sc/ioctl.c::sc_ioctl() Signed-off-by: Jesper Juhl Acked-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/sc/ioctl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c index 94c9afb701..f4f71226a0 100644 --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c @@ -46,7 +46,8 @@ int sc_ioctl(int card, scs_ioctl *data) pr_debug("%s: SCIOCRESET: ioctl received\n", sc_adapter[card]->devicename); sc_adapter[card]->StartOnReset = 0; - return (reset(card)); + kfree(rcvmsg); + return reset(card); } case SCIOCLOAD: @@ -183,7 +184,7 @@ int sc_ioctl(int card, scs_ioctl *data) sc_adapter[card]->devicename); spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL); - if(!spid) { + if (!spid) { kfree(rcvmsg); return -ENOMEM; } @@ -195,10 +196,10 @@ int sc_ioctl(int card, scs_ioctl *data) if (!status) { pr_debug("%s: SCIOCGETSPID: command successful\n", sc_adapter[card]->devicename); - } - else { + } else { pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n", sc_adapter[card]->devicename, status); + kfree(spid); kfree(rcvmsg); return status; } -- cgit v1.2.2 From 0ca07731e495584bd84dca15a0f065470d594ec4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 31 Mar 2006 02:30:58 -0800 Subject: [PATCH] vt: add TIOCL_GETKMSGREDIRECT Add TIOCL_GETKMSGREDIRECT needed by the userland suspend tool to get the current value of kmsg_redirect from the kernel so that it can save it and restore it after resume. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Cc: Michael Kerrisk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/vt.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/char/vt.c b/drivers/char/vt.c index ca4844c527..acc5d47844 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2328,6 +2328,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) case TIOCL_SETVESABLANK: set_vesa_blanking(p); break; + case TIOCL_GETKMSGREDIRECT: + data = kmsg_redirect; + ret = __put_user(data, p); + break; case TIOCL_SETKMSGREDIRECT: if (!capable(CAP_SYS_ADMIN)) { ret = -EPERM; -- cgit v1.2.2 From c72a1d608dd0eb3d553a08bfdf1c0041bebaa8a0 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:04 -0800 Subject: [PATCH] LED: add LED class Add the foundations of a new LEDs subsystem. This patch adds a class which presents LED devices within sysfs and allows their brightness to be controlled. Signed-off-by: Richard Purdie Cc: Russell King Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/leds/Kconfig | 18 ++++++ drivers/leds/Makefile | 4 ++ drivers/leds/led-class.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/leds/led-core.c | 25 ++++++++ drivers/leds/leds.h | 31 ++++++++++ 7 files changed, 228 insertions(+) create mode 100644 drivers/leds/Kconfig create mode 100644 drivers/leds/Makefile create mode 100644 drivers/leds/led-class.c create mode 100644 drivers/leds/led-core.c create mode 100644 drivers/leds/leds.h (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index 9f5c0da57c..5c91d6afb1 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -64,6 +64,8 @@ source "drivers/usb/Kconfig" source "drivers/mmc/Kconfig" +source "drivers/leds/Kconfig" + source "drivers/infiniband/Kconfig" source "drivers/sn/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 424955274e..d6e8ffbd81 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_MCA) += mca/ obj-$(CONFIG_EISA) += eisa/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_MMC) += mmc/ +obj-$(CONFIG_NEW_LEDS) += leds/ obj-$(CONFIG_INFINIBAND) += infiniband/ obj-$(CONFIG_SGI_SN) += sn/ obj-y += firmware/ diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig new file mode 100644 index 0000000000..106f9aeca0 --- /dev/null +++ b/drivers/leds/Kconfig @@ -0,0 +1,18 @@ + +menu "LED devices" + +config NEW_LEDS + bool "LED Support" + help + Say Y to enable Linux LED support. This is not related to standard + keyboard LEDs which are controlled via the input system. + +config LEDS_CLASS + tristate "LED Class Support" + depends NEW_LEDS + help + This option enables the led sysfs class in /sys/class/leds. You'll + need this to do anything useful with LEDs. If unsure, say N. + +endmenu + diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile new file mode 100644 index 0000000000..8a62871437 --- /dev/null +++ b/drivers/leds/Makefile @@ -0,0 +1,4 @@ + +# LED Core +obj-$(CONFIG_NEW_LEDS) += led-core.o +obj-$(CONFIG_LEDS_CLASS) += led-class.o diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c new file mode 100644 index 0000000000..0292df4101 --- /dev/null +++ b/drivers/leds/led-class.c @@ -0,0 +1,147 @@ +/* + * LED Class Core + * + * Copyright (C) 2005 John Lenz + * Copyright (C) 2005-2006 Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "leds.h" + +static struct class *leds_class; + +static ssize_t led_brightness_show(struct class_device *dev, char *buf) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + ssize_t ret = 0; + + /* no lock needed for this */ + sprintf(buf, "%u\n", led_cdev->brightness); + ret = strlen(buf) + 1; + + return ret; +} + +static ssize_t led_brightness_store(struct class_device *dev, + const char *buf, size_t size) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + ssize_t ret = -EINVAL; + char *after; + unsigned long state = simple_strtoul(buf, &after, 10); + + if (after - buf > 0) { + ret = after - buf; + led_set_brightness(led_cdev, state); + } + + return ret; +} + +static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show, + led_brightness_store); + +/** + * led_classdev_suspend - suspend an led_classdev. + * @led_cdev: the led_classdev to suspend. + */ +void led_classdev_suspend(struct led_classdev *led_cdev) +{ + led_cdev->flags |= LED_SUSPENDED; + led_cdev->brightness_set(led_cdev, 0); +} +EXPORT_SYMBOL_GPL(led_classdev_suspend); + +/** + * led_classdev_resume - resume an led_classdev. + * @led_cdev: the led_classdev to resume. + */ +void led_classdev_resume(struct led_classdev *led_cdev) +{ + led_cdev->brightness_set(led_cdev, led_cdev->brightness); + led_cdev->flags &= ~LED_SUSPENDED; +} +EXPORT_SYMBOL_GPL(led_classdev_resume); + +/** + * led_classdev_register - register a new object of led_classdev class. + * @dev: The device to register. + * @led_cdev: the led_classdev structure for this device. + */ +int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) +{ + led_cdev->class_dev = class_device_create(leds_class, NULL, 0, + parent, "%s", led_cdev->name); + if (unlikely(IS_ERR(led_cdev->class_dev))) + return PTR_ERR(led_cdev->class_dev); + + class_set_devdata(led_cdev->class_dev, led_cdev); + + /* register the attributes */ + class_device_create_file(led_cdev->class_dev, + &class_device_attr_brightness); + + /* add to the list of leds */ + write_lock(&leds_list_lock); + list_add_tail(&led_cdev->node, &leds_list); + write_unlock(&leds_list_lock); + + printk(KERN_INFO "Registered led device: %s\n", + led_cdev->class_dev->class_id); + + return 0; +} +EXPORT_SYMBOL_GPL(led_classdev_register); + +/** + * led_classdev_unregister - unregisters a object of led_properties class. + * @led_cdev: the led device to unreigister + * + * Unregisters a previously registered via led_classdev_register object. + */ +void led_classdev_unregister(struct led_classdev *led_cdev) +{ + class_device_remove_file(led_cdev->class_dev, + &class_device_attr_brightness); + + class_device_unregister(led_cdev->class_dev); + + write_lock(&leds_list_lock); + list_del(&led_cdev->node); + write_unlock(&leds_list_lock); +} +EXPORT_SYMBOL_GPL(led_classdev_unregister); + +static int __init leds_init(void) +{ + leds_class = class_create(THIS_MODULE, "leds"); + if (IS_ERR(leds_class)) + return PTR_ERR(leds_class); + return 0; +} + +static void __exit leds_exit(void) +{ + class_destroy(leds_class); +} + +subsys_initcall(leds_init); +module_exit(leds_exit); + +MODULE_AUTHOR("John Lenz, Richard Purdie"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LED Class Interface"); diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c new file mode 100644 index 0000000000..fe6541326c --- /dev/null +++ b/drivers/leds/led-core.c @@ -0,0 +1,25 @@ +/* + * LED Class Core + * + * Copyright 2005-2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include "leds.h" + +rwlock_t leds_list_lock = RW_LOCK_UNLOCKED; +LIST_HEAD(leds_list); + +EXPORT_SYMBOL_GPL(leds_list); +EXPORT_SYMBOL_GPL(leds_list_lock); diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h new file mode 100644 index 0000000000..d26ca2f7e7 --- /dev/null +++ b/drivers/leds/leds.h @@ -0,0 +1,31 @@ +/* + * LED Core + * + * Copyright 2005 Openedhand Ltd. + * + * Author: Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#ifndef __LEDS_H_INCLUDED +#define __LEDS_H_INCLUDED + +#include + +static inline void led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness value) +{ + if (value > LED_FULL) + value = LED_FULL; + led_cdev->brightness = value; + if (!(led_cdev->flags & LED_SUSPENDED)) + led_cdev->brightness_set(led_cdev, value); +} + +extern rwlock_t leds_list_lock; +extern struct list_head leds_list; + +#endif /* __LEDS_H_INCLUDED */ -- cgit v1.2.2 From c3bc9956ec52fb2c70f29aa894d8eec766116584 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:05 -0800 Subject: [PATCH] LED: add LED trigger tupport Add support for LED triggers to the LED subsystem. "Triggers" are events which change the state of an LED. Two kinds of trigger are available, simple ones which can be added to exising code with minimum disruption and complex ones for implementing new or more complex functionality. Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 8 ++ drivers/leds/Makefile | 1 + drivers/leds/led-class.c | 20 ++++ drivers/leds/led-triggers.c | 239 ++++++++++++++++++++++++++++++++++++++++++++ drivers/leds/leds.h | 13 +++ 5 files changed, 281 insertions(+) create mode 100644 drivers/leds/led-triggers.c (limited to 'drivers') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 106f9aeca0..a4d12ecaf6 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -14,5 +14,13 @@ config LEDS_CLASS This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. +config LEDS_TRIGGERS + bool "LED Trigger support" + depends NEW_LEDS + help + This option enables trigger support for the leds class. + These triggers allow kernel events to drive the LEDs and can + be configured via sysfs. If unsure, say Y. + endmenu diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 8a62871437..a9d8becd61 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -2,3 +2,4 @@ # LED Core obj-$(CONFIG_NEW_LEDS) += led-core.o obj-$(CONFIG_LEDS_CLASS) += led-class.o +obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 0292df4101..b0b5d05fad 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -54,6 +54,9 @@ static ssize_t led_brightness_store(struct class_device *dev, static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show, led_brightness_store); +#ifdef CONFIG_LEDS_TRIGGERS +static CLASS_DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store); +#endif /** * led_classdev_suspend - suspend an led_classdev. @@ -100,6 +103,15 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) list_add_tail(&led_cdev->node, &leds_list); write_unlock(&leds_list_lock); +#ifdef CONFIG_LEDS_TRIGGERS + rwlock_init(&led_cdev->trigger_lock); + + led_trigger_set_default(led_cdev); + + class_device_create_file(led_cdev->class_dev, + &class_device_attr_trigger); +#endif + printk(KERN_INFO "Registered led device: %s\n", led_cdev->class_dev->class_id); @@ -117,6 +129,14 @@ void led_classdev_unregister(struct led_classdev *led_cdev) { class_device_remove_file(led_cdev->class_dev, &class_device_attr_brightness); +#ifdef CONFIG_LEDS_TRIGGERS + class_device_remove_file(led_cdev->class_dev, + &class_device_attr_trigger); + write_lock(&led_cdev->trigger_lock); + if (led_cdev->trigger) + led_trigger_set(led_cdev, NULL); + write_unlock(&led_cdev->trigger_lock); +#endif class_device_unregister(led_cdev->class_dev); diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c new file mode 100644 index 0000000000..5e2cd8be11 --- /dev/null +++ b/drivers/leds/led-triggers.c @@ -0,0 +1,239 @@ +/* + * LED Triggers Core + * + * Copyright 2005-2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "leds.h" + +/* + * Nests outside led_cdev->trigger_lock + */ +static rwlock_t triggers_list_lock = RW_LOCK_UNLOCKED; +static LIST_HEAD(trigger_list); + +ssize_t led_trigger_store(struct class_device *dev, const char *buf, + size_t count) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + char trigger_name[TRIG_NAME_MAX]; + struct led_trigger *trig; + size_t len; + + trigger_name[sizeof(trigger_name) - 1] = '\0'; + strncpy(trigger_name, buf, sizeof(trigger_name) - 1); + len = strlen(trigger_name); + + if (len && trigger_name[len - 1] == '\n') + trigger_name[len - 1] = '\0'; + + if (!strcmp(trigger_name, "none")) { + write_lock(&led_cdev->trigger_lock); + led_trigger_set(led_cdev, NULL); + write_unlock(&led_cdev->trigger_lock); + return count; + } + + read_lock(&triggers_list_lock); + list_for_each_entry(trig, &trigger_list, next_trig) { + if (!strcmp(trigger_name, trig->name)) { + write_lock(&led_cdev->trigger_lock); + led_trigger_set(led_cdev, trig); + write_unlock(&led_cdev->trigger_lock); + + read_unlock(&triggers_list_lock); + return count; + } + } + read_unlock(&triggers_list_lock); + + return -EINVAL; +} + + +ssize_t led_trigger_show(struct class_device *dev, char *buf) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + struct led_trigger *trig; + int len = 0; + + read_lock(&triggers_list_lock); + read_lock(&led_cdev->trigger_lock); + + if (!led_cdev->trigger) + len += sprintf(buf+len, "[none] "); + else + len += sprintf(buf+len, "none "); + + list_for_each_entry(trig, &trigger_list, next_trig) { + if (led_cdev->trigger && !strcmp(led_cdev->trigger->name, + trig->name)) + len += sprintf(buf+len, "[%s] ", trig->name); + else + len += sprintf(buf+len, "%s ", trig->name); + } + read_unlock(&led_cdev->trigger_lock); + read_unlock(&triggers_list_lock); + + len += sprintf(len+buf, "\n"); + return len; +} + +void led_trigger_event(struct led_trigger *trigger, + enum led_brightness brightness) +{ + struct list_head *entry; + + if (!trigger) + return; + + read_lock(&trigger->leddev_list_lock); + list_for_each(entry, &trigger->led_cdevs) { + struct led_classdev *led_cdev; + + led_cdev = list_entry(entry, struct led_classdev, trig_list); + led_set_brightness(led_cdev, brightness); + } + read_unlock(&trigger->leddev_list_lock); +} + +/* Caller must ensure led_cdev->trigger_lock held */ +void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger) +{ + unsigned long flags; + + /* Remove any existing trigger */ + if (led_cdev->trigger) { + write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags); + list_del(&led_cdev->trig_list); + write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags); + if (led_cdev->trigger->deactivate) + led_cdev->trigger->deactivate(led_cdev); + } + if (trigger) { + write_lock_irqsave(&trigger->leddev_list_lock, flags); + list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs); + write_unlock_irqrestore(&trigger->leddev_list_lock, flags); + if (trigger->activate) + trigger->activate(led_cdev); + } + led_cdev->trigger = trigger; +} + +void led_trigger_set_default(struct led_classdev *led_cdev) +{ + struct led_trigger *trig; + + if (!led_cdev->default_trigger) + return; + + read_lock(&triggers_list_lock); + write_lock(&led_cdev->trigger_lock); + list_for_each_entry(trig, &trigger_list, next_trig) { + if (!strcmp(led_cdev->default_trigger, trig->name)) + led_trigger_set(led_cdev, trig); + } + write_unlock(&led_cdev->trigger_lock); + read_unlock(&triggers_list_lock); +} + +int led_trigger_register(struct led_trigger *trigger) +{ + struct led_classdev *led_cdev; + + rwlock_init(&trigger->leddev_list_lock); + INIT_LIST_HEAD(&trigger->led_cdevs); + + /* Add to the list of led triggers */ + write_lock(&triggers_list_lock); + list_add_tail(&trigger->next_trig, &trigger_list); + write_unlock(&triggers_list_lock); + + /* Register with any LEDs that have this as a default trigger */ + read_lock(&leds_list_lock); + list_for_each_entry(led_cdev, &leds_list, node) { + write_lock(&led_cdev->trigger_lock); + if (!led_cdev->trigger && led_cdev->default_trigger && + !strcmp(led_cdev->default_trigger, trigger->name)) + led_trigger_set(led_cdev, trigger); + write_unlock(&led_cdev->trigger_lock); + } + read_unlock(&leds_list_lock); + + return 0; +} + +void led_trigger_register_simple(const char *name, struct led_trigger **tp) +{ + struct led_trigger *trigger; + + trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); + + if (trigger) { + trigger->name = name; + led_trigger_register(trigger); + } + *tp = trigger; +} + +void led_trigger_unregister(struct led_trigger *trigger) +{ + struct led_classdev *led_cdev; + + /* Remove from the list of led triggers */ + write_lock(&triggers_list_lock); + list_del(&trigger->next_trig); + write_unlock(&triggers_list_lock); + + /* Remove anyone actively using this trigger */ + read_lock(&leds_list_lock); + list_for_each_entry(led_cdev, &leds_list, node) { + write_lock(&led_cdev->trigger_lock); + if (led_cdev->trigger == trigger) + led_trigger_set(led_cdev, NULL); + write_unlock(&led_cdev->trigger_lock); + } + read_unlock(&leds_list_lock); +} + +void led_trigger_unregister_simple(struct led_trigger *trigger) +{ + led_trigger_unregister(trigger); + kfree(trigger); +} + +/* Used by LED Class */ +EXPORT_SYMBOL_GPL(led_trigger_set); +EXPORT_SYMBOL_GPL(led_trigger_set_default); +EXPORT_SYMBOL_GPL(led_trigger_show); +EXPORT_SYMBOL_GPL(led_trigger_store); + +/* LED Trigger Interface */ +EXPORT_SYMBOL_GPL(led_trigger_register); +EXPORT_SYMBOL_GPL(led_trigger_unregister); + +/* Simple LED Tigger Interface */ +EXPORT_SYMBOL_GPL(led_trigger_register_simple); +EXPORT_SYMBOL_GPL(led_trigger_unregister_simple); +EXPORT_SYMBOL_GPL(led_trigger_event); + +MODULE_AUTHOR("Richard Purdie"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LED Triggers Core"); diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index d26ca2f7e7..a715c4ed93 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -28,4 +28,17 @@ static inline void led_set_brightness(struct led_classdev *led_cdev, extern rwlock_t leds_list_lock; extern struct list_head leds_list; +#ifdef CONFIG_LEDS_TRIGGERS +void led_trigger_set_default(struct led_classdev *led_cdev); +void led_trigger_set(struct led_classdev *led_cdev, + struct led_trigger *trigger); +#else +#define led_trigger_set_default(x) do {} while(0) +#define led_trigger_set(x, y) do {} while(0) +#endif + +ssize_t led_trigger_store(struct class_device *dev, const char *buf, + size_t count); +ssize_t led_trigger_show(struct class_device *dev, char *buf); + #endif /* __LEDS_H_INCLUDED */ -- cgit v1.2.2 From 6655c6fe575b720eb8cb6c143ae10995a7aa1916 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:07 -0800 Subject: [PATCH] LED: add LED timer trigger Add an example of a complex LED trigger in the form of a generic timer which triggers the LED its attached to at a user specified frequency and duty cycle. Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 7 ++ drivers/leds/Makefile | 3 + drivers/leds/ledtrig-timer.c | 170 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 drivers/leds/ledtrig-timer.c (limited to 'drivers') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index a4d12ecaf6..fda44df592 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -22,5 +22,12 @@ config LEDS_TRIGGERS These triggers allow kernel events to drive the LEDs and can be configured via sysfs. If unsure, say Y. +config LEDS_TRIGGER_TIMER + tristate "LED Timer Trigger" + depends LEDS_TRIGGERS + help + This allows LEDs to be controlled by a programmable timer + via sysfs. If unsure, say Y. + endmenu diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index a9d8becd61..81e4abb9dc 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -3,3 +3,6 @@ obj-$(CONFIG_NEW_LEDS) += led-core.o obj-$(CONFIG_LEDS_CLASS) += led-class.o obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o + +# LED Triggers +obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c new file mode 100644 index 0000000000..f484b5d6db --- /dev/null +++ b/drivers/leds/ledtrig-timer.c @@ -0,0 +1,170 @@ +/* + * LED Kernel Timer Trigger + * + * Copyright 2005-2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "leds.h" + +struct timer_trig_data { + unsigned long delay_on; /* milliseconds on */ + unsigned long delay_off; /* milliseconds off */ + struct timer_list timer; +}; + +static void led_timer_function(unsigned long data) +{ + struct led_classdev *led_cdev = (struct led_classdev *) data; + struct timer_trig_data *timer_data = led_cdev->trigger_data; + unsigned long brightness = LED_OFF; + unsigned long delay = timer_data->delay_off; + + if (!timer_data->delay_on || !timer_data->delay_off) { + led_set_brightness(led_cdev, LED_OFF); + return; + } + + if (!led_cdev->brightness) { + brightness = LED_FULL; + delay = timer_data->delay_on; + } + + led_set_brightness(led_cdev, brightness); + + mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); +} + +static ssize_t led_delay_on_show(struct class_device *dev, char *buf) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; + + sprintf(buf, "%lu\n", timer_data->delay_on); + + return strlen(buf) + 1; +} + +static ssize_t led_delay_on_store(struct class_device *dev, const char *buf, + size_t size) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; + int ret = -EINVAL; + char *after; + unsigned long state = simple_strtoul(buf, &after, 10); + + if (after - buf > 0) { + timer_data->delay_on = state; + mod_timer(&timer_data->timer, jiffies + 1); + ret = after - buf; + } + + return ret; +} + +static ssize_t led_delay_off_show(struct class_device *dev, char *buf) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; + + sprintf(buf, "%lu\n", timer_data->delay_off); + + return strlen(buf) + 1; +} + +static ssize_t led_delay_off_store(struct class_device *dev, const char *buf, + size_t size) +{ + struct led_classdev *led_cdev = class_get_devdata(dev); + struct timer_trig_data *timer_data = led_cdev->trigger_data; + int ret = -EINVAL; + char *after; + unsigned long state = simple_strtoul(buf, &after, 10); + + if (after - buf > 0) { + timer_data->delay_off = state; + mod_timer(&timer_data->timer, jiffies + 1); + ret = after - buf; + } + + return ret; +} + +static CLASS_DEVICE_ATTR(delay_on, 0644, led_delay_on_show, + led_delay_on_store); +static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show, + led_delay_off_store); + +static void timer_trig_activate(struct led_classdev *led_cdev) +{ + struct timer_trig_data *timer_data; + + timer_data = kzalloc(sizeof(struct timer_trig_data), GFP_KERNEL); + if (!timer_data) + return; + + led_cdev->trigger_data = timer_data; + + init_timer(&timer_data->timer); + timer_data->timer.function = led_timer_function; + timer_data->timer.data = (unsigned long) led_cdev; + + class_device_create_file(led_cdev->class_dev, + &class_device_attr_delay_on); + class_device_create_file(led_cdev->class_dev, + &class_device_attr_delay_off); +} + +static void timer_trig_deactivate(struct led_classdev *led_cdev) +{ + struct timer_trig_data *timer_data = led_cdev->trigger_data; + + if (timer_data) { + class_device_remove_file(led_cdev->class_dev, + &class_device_attr_delay_on); + class_device_remove_file(led_cdev->class_dev, + &class_device_attr_delay_off); + del_timer_sync(&timer_data->timer); + kfree(timer_data); + } +} + +static struct led_trigger timer_led_trigger = { + .name = "timer", + .activate = timer_trig_activate, + .deactivate = timer_trig_deactivate, +}; + +static int __init timer_trig_init(void) +{ + return led_trigger_register(&timer_led_trigger); +} + +static void __exit timer_trig_exit(void) +{ + led_trigger_unregister(&timer_led_trigger); +} + +module_init(timer_trig_init); +module_exit(timer_trig_exit); + +MODULE_AUTHOR("Richard Purdie "); +MODULE_DESCRIPTION("Timer LED trigger"); +MODULE_LICENSE("GPL"); -- cgit v1.2.2 From 3179108daaaccbf28b17d6d8b0e06abf0eee6d9f Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:09 -0800 Subject: [PATCH] LED: add LED device support for the zaurus corgi and spitz models Adds LED drivers for LEDs found on the Sharp Zaurus c7x0 (corgi, shepherd, husky) and cxx00 (akita, spitz, borzoi) models. Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 14 ++++++ drivers/leds/Makefile | 4 ++ drivers/leds/leds-corgi.c | 121 ++++++++++++++++++++++++++++++++++++++++++++ drivers/leds/leds-spitz.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 drivers/leds/leds-corgi.c create mode 100644 drivers/leds/leds-spitz.c (limited to 'drivers') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index fda44df592..f7846b40c8 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -22,6 +22,20 @@ config LEDS_TRIGGERS These triggers allow kernel events to drive the LEDs and can be configured via sysfs. If unsure, say Y. +config LEDS_CORGI + tristate "LED Support for the Sharp SL-C7x0 series" + depends LEDS_CLASS && PXA_SHARP_C7xx + help + This option enables support for the LEDs on Sharp Zaurus + SL-C7x0 series (C700, C750, C760, C860). + +config LEDS_SPITZ + tristate "LED Support for the Sharp SL-Cxx00 series" + depends LEDS_CLASS && PXA_SHARP_Cxx00 + help + This option enables support for the LEDs on Sharp Zaurus + SL-Cxx00 series (C1000, C3000, C3100). + config LEDS_TRIGGER_TIMER tristate "LED Timer Trigger" depends LEDS_TRIGGERS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 81e4abb9dc..cb5d0ada6a 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -4,5 +4,9 @@ obj-$(CONFIG_NEW_LEDS) += led-core.o obj-$(CONFIG_LEDS_CLASS) += led-class.o obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o +# LED Platform Drivers +obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o +obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o + # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c new file mode 100644 index 0000000000..bb7d84df01 --- /dev/null +++ b/drivers/leds/leds-corgi.c @@ -0,0 +1,121 @@ +/* + * LED Triggers Core + * + * Copyright 2005-2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightness value) +{ + if (value) + GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); + else + GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); +} + +static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightness value) +{ + if (value) + set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); + else + reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); +} + +static struct led_classdev corgi_amber_led = { + .name = "corgi:amber", + .default_trigger = "sharpsl-charge", + .brightness_set = corgiled_amber_set, +}; + +static struct led_classdev corgi_green_led = { + .name = "corgi:green", + .default_trigger = "nand-disk", + .brightness_set = corgiled_green_set, +}; + +#ifdef CONFIG_PM +static int corgiled_suspend(struct platform_device *dev, pm_message_t state) +{ +#ifdef CONFIG_LEDS_TRIGGERS + if (corgi_amber_led.trigger && strcmp(corgi_amber_led.trigger->name, "sharpsl-charge")) +#endif + led_classdev_suspend(&corgi_amber_led); + led_classdev_suspend(&corgi_green_led); + return 0; +} + +static int corgiled_resume(struct platform_device *dev) +{ + led_classdev_resume(&corgi_amber_led); + led_classdev_resume(&corgi_green_led); + return 0; +} +#endif + +static int corgiled_probe(struct platform_device *pdev) +{ + int ret; + + ret = led_classdev_register(&pdev->dev, &corgi_amber_led); + if (ret < 0) + return ret; + + ret = led_classdev_register(&pdev->dev, &corgi_green_led); + if (ret < 0) + led_classdev_unregister(&corgi_amber_led); + + return ret; +} + +static int corgiled_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&corgi_amber_led); + led_classdev_unregister(&corgi_green_led); + return 0; +} + +static struct platform_driver corgiled_driver = { + .probe = corgiled_probe, + .remove = corgiled_remove, +#ifdef CONFIG_PM + .suspend = corgiled_suspend, + .resume = corgiled_resume, +#endif + .driver = { + .name = "corgi-led", + }, +}; + +static int __init corgiled_init(void) +{ + return platform_driver_register(&corgiled_driver); +} + +static void __exit corgiled_exit(void) +{ + platform_driver_unregister(&corgiled_driver); +} + +module_init(corgiled_init); +module_exit(corgiled_exit); + +MODULE_AUTHOR("Richard Purdie "); +MODULE_DESCRIPTION("Corgi LED driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c new file mode 100644 index 0000000000..65bbef4a5e --- /dev/null +++ b/drivers/leds/leds-spitz.c @@ -0,0 +1,125 @@ +/* + * LED Triggers Core + * + * Copyright 2005-2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightness value) +{ + if (value) + set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); + else + reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); +} + +static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightness value) +{ + if (value) + set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); + else + reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); +} + +static struct led_classdev spitz_amber_led = { + .name = "spitz:amber", + .default_trigger = "sharpsl-charge", + .brightness_set = spitzled_amber_set, +}; + +static struct led_classdev spitz_green_led = { + .name = "spitz:green", + .default_trigger = "ide-disk", + .brightness_set = spitzled_green_set, +}; + +#ifdef CONFIG_PM +static int spitzled_suspend(struct platform_device *dev, pm_message_t state) +{ +#ifdef CONFIG_LEDS_TRIGGERS + if (spitz_amber_led.trigger && strcmp(spitz_amber_led.trigger->name, "sharpsl-charge")) +#endif + led_classdev_suspend(&spitz_amber_led); + led_classdev_suspend(&spitz_green_led); + return 0; +} + +static int spitzled_resume(struct platform_device *dev) +{ + led_classdev_resume(&spitz_amber_led); + led_classdev_resume(&spitz_green_led); + return 0; +} +#endif + +static int spitzled_probe(struct platform_device *pdev) +{ + int ret; + + if (machine_is_akita()) + spitz_green_led.default_trigger = "nand-disk"; + + ret = led_classdev_register(&pdev->dev, &spitz_amber_led); + if (ret < 0) + return ret; + + ret = led_classdev_register(&pdev->dev, &spitz_green_led); + if (ret < 0) + led_classdev_unregister(&spitz_amber_led); + + return ret; +} + +static int spitzled_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&spitz_amber_led); + led_classdev_unregister(&spitz_green_led); + + return 0; +} + +static struct platform_driver spitzled_driver = { + .probe = spitzled_probe, + .remove = spitzled_remove, +#ifdef CONFIG_PM + .suspend = spitzled_suspend, + .resume = spitzled_resume, +#endif + .driver = { + .name = "spitz-led", + }, +}; + +static int __init spitzled_init(void) +{ + return platform_driver_register(&spitzled_driver); +} + +static void __exit spitzled_exit(void) +{ + platform_driver_unregister(&spitzled_driver); +} + +module_init(spitzled_init); +module_exit(spitzled_exit); + +MODULE_AUTHOR("Richard Purdie "); +MODULE_DESCRIPTION("Spitz LED driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.2 From 4d3cb35476903768541f79e61f171e79e6065098 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:10 -0800 Subject: [PATCH] LED: add LED device support for locomo devices Adds an LED driver for LEDs exported by the Sharp LOCOMO chip as found on some models of Sharp Zaurus. Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 7 ++++ drivers/leds/Makefile | 1 + drivers/leds/leds-locomo.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 drivers/leds/leds-locomo.c (limited to 'drivers') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index f7846b40c8..6099e32985 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -29,6 +29,13 @@ config LEDS_CORGI This option enables support for the LEDs on Sharp Zaurus SL-C7x0 series (C700, C750, C760, C860). +config LEDS_LOCOMO + tristate "LED Support for Locomo device" + depends LEDS_CLASS && SHARP_LOCOMO + help + This option enables support for the LEDs on Sharp Locomo. + Zaurus models SL-5500 and SL-5600. + config LEDS_SPITZ tristate "LED Support for the Sharp SL-Cxx00 series" depends LEDS_CLASS && PXA_SHARP_Cxx00 diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index cb5d0ada6a..d60e12b8af 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o # LED Platform Drivers obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o +obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o # LED Triggers diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c new file mode 100644 index 0000000000..749a86c2ad --- /dev/null +++ b/drivers/leds/leds-locomo.c @@ -0,0 +1,95 @@ +/* + * linux/drivers/leds/locomo.c + * + * Copyright (C) 2005 John Lenz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include + +#include +#include + +static void locomoled_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value, int offset) +{ + struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->class_dev->dev); + unsigned long flags; + + local_irq_save(flags); + if (value) + locomo_writel(LOCOMO_LPT_TOFH, locomo_dev->mapbase + offset); + else + locomo_writel(LOCOMO_LPT_TOFL, locomo_dev->mapbase + offset); + local_irq_restore(flags); +} + +static void locomoled_brightness_set0(struct led_classdev *led_cdev, + enum led_brightness value) +{ + locomoled_brightness_set(led_cdev, value, LOCOMO_LPT0); +} + +static void locomoled_brightness_set1(struct led_classdev *led_cdev, + enum led_brightness value) +{ + locomoled_brightness_set(led_cdev, value, LOCOMO_LPT1); +} + +static struct led_classdev locomo_led0 = { + .name = "locomo:amber", + .brightness_set = locomoled_brightness_set0, +}; + +static struct led_classdev locomo_led1 = { + .name = "locomo:green", + .brightness_set = locomoled_brightness_set1, +}; + +static int locomoled_probe(struct locomo_dev *ldev) +{ + int ret; + + ret = led_classdev_register(&ldev->dev, &locomo_led0); + if (ret < 0) + return ret; + + ret = led_classdev_register(&ldev->dev, &locomo_led1); + if (ret < 0) + led_classdev_unregister(&locomo_led0); + + return ret; +} + +static int locomoled_remove(struct locomo_dev *dev) +{ + led_classdev_unregister(&locomo_led0); + led_classdev_unregister(&locomo_led1); + return 0; +} + +static struct locomo_driver locomoled_driver = { + .drv = { + .name = "locomoled" + }, + .devid = LOCOMO_DEVID_LED, + .probe = locomoled_probe, + .remove = locomoled_remove, +}; + +static int __init locomoled_init(void) +{ + return locomo_driver_register(&locomoled_driver); +} +module_init(locomoled_init); + +MODULE_AUTHOR("John Lenz "); +MODULE_DESCRIPTION("Locomo LED driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.2 From 6a0c51bfce5ae4058366017d861aea6564d25aee Mon Sep 17 00:00:00 2001 From: John Bowler Date: Fri, 31 Mar 2006 02:31:11 -0800 Subject: [PATCH] LED: add LED device support for ixp4xx devices NEW_LEDS support for ixp4xx boards where LEDs are connected to the GPIO lines. This includes a new generic ixp4xx driver (leds-ixp4xx-gpio.c name "IXP4XX-GPIO-LED") Signed-off-by: John Bowler Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 9 ++ drivers/leds/Makefile | 1 + drivers/leds/leds-ixp4xx-gpio.c | 215 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100644 drivers/leds/leds-ixp4xx-gpio.c (limited to 'drivers') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 6099e32985..d9e2f9853b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -43,6 +43,15 @@ config LEDS_SPITZ This option enables support for the LEDs on Sharp Zaurus SL-Cxx00 series (C1000, C3000, C3100). +config LEDS_IXP4XX + tristate "LED Support for GPIO connected LEDs on IXP4XX processors" + depends LEDS_CLASS && ARCH_IXP4XX + help + This option enables support for the LEDs connected to GPIO + outputs of the Intel IXP4XX processors. To be useful the + particular board must have LEDs and they must be connected + to the GPIO lines. If unsure, say Y. + config LEDS_TRIGGER_TIMER tristate "LED Timer Trigger" depends LEDS_TRIGGERS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index d60e12b8af..b1187c0b36 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o +obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/drivers/leds/leds-ixp4xx-gpio.c b/drivers/leds/leds-ixp4xx-gpio.c new file mode 100644 index 0000000000..30ced150e4 --- /dev/null +++ b/drivers/leds/leds-ixp4xx-gpio.c @@ -0,0 +1,215 @@ +/* + * IXP4XX GPIO driver LED driver + * + * Author: John Bowler + * + * Copyright (c) 2006 John Bowler + * + * Permission is hereby granted, free of charge, to any + * person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the + * Software without restriction, including without + * limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the + * following conditions: + * + * The above copyright notice and this permission notice + * shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF + * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT + * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +extern spinlock_t gpio_lock; + +/* Up to 16 gpio lines are possible. */ +#define GPIO_MAX 16 +static struct ixp4xxgpioled_device { + struct led_classdev ancestor; + int flags; +} ixp4xxgpioled_devices[GPIO_MAX]; + +void ixp4xxgpioled_brightness_set(struct led_classdev *pled, + enum led_brightness value) +{ + const struct ixp4xxgpioled_device *const ixp4xx_dev = + container_of(pled, struct ixp4xxgpioled_device, ancestor); + const u32 gpio_pin = ixp4xx_dev - ixp4xxgpioled_devices; + + if (gpio_pin < GPIO_MAX && ixp4xx_dev->ancestor.name != 0) { + /* Set or clear the 'gpio_pin' bit according to the style + * and the required setting (value > 0 == on) + */ + const int gpio_value = + (value > 0) == (ixp4xx_dev->flags != IXP4XX_GPIO_LOW) ? + IXP4XX_GPIO_HIGH : IXP4XX_GPIO_LOW; + + { + unsigned long flags; + spin_lock_irqsave(&gpio_lock, flags); + gpio_line_set(gpio_pin, gpio_value); + spin_unlock_irqrestore(&gpio_lock, flags); + } + } +} + +/* LEDs are described in resources, the following iterates over the valid + * LED resources. + */ +#define for_all_leds(i, pdev) \ + for (i=0; inum_resources; ++i) \ + if (pdev->resource[i].start < GPIO_MAX && \ + pdev->resource[i].name != 0) + +/* The following applies 'operation' to each LED from the given platform, + * the function always returns 0 to allow tail call elimination. + */ +static int apply_to_all_leds(struct platform_device *pdev, + void (*operation)(struct led_classdev *pled)) +{ + int i; + + for_all_leds(i, pdev) + operation(&ixp4xxgpioled_devices[pdev->resource[i].start].ancestor); + return 0; +} + +#ifdef CONFIG_PM +static int ixp4xxgpioled_suspend(struct platform_device *pdev, + pm_message_t state) +{ + return apply_to_all_leds(pdev, led_classdev_suspend); +} + +static int ixp4xxgpioled_resume(struct platform_device *pdev) +{ + return apply_to_all_leds(pdev, led_classdev_resume); +} +#endif + +static void ixp4xxgpioled_remove_one_led(struct led_classdev *pled) +{ + led_classdev_unregister(pled); + pled->name = 0; +} + +static int ixp4xxgpioled_remove(struct platform_device *pdev) +{ + return apply_to_all_leds(pdev, ixp4xxgpioled_remove_one_led); +} + +static int ixp4xxgpioled_probe(struct platform_device *pdev) +{ + /* The board level has to tell the driver where the + * LEDs are connected - there is no way to find out + * electrically. It must also say whether the GPIO + * lines are active high or active low. + * + * To do this read the num_resources (the number of + * LEDs) and the struct resource (the data for each + * LED). The name comes from the resource, and it + * isn't copied. + */ + int i; + + for_all_leds(i, pdev) { + const u8 gpio_pin = pdev->resource[i].start; + int rc; + + if (ixp4xxgpioled_devices[gpio_pin].ancestor.name == 0) { + unsigned long flags; + + spin_lock_irqsave(&gpio_lock, flags); + gpio_line_config(gpio_pin, IXP4XX_GPIO_OUT); + /* The config can, apparently, reset the state, + * I suspect the gpio line may be an input and + * the config may cause the line to be latched, + * so the setting depends on how the LED is + * connected to the line (which affects how it + * floats if not driven). + */ + gpio_line_set(gpio_pin, IXP4XX_GPIO_HIGH); + spin_unlock_irqrestore(&gpio_lock, flags); + + ixp4xxgpioled_devices[gpio_pin].flags = + pdev->resource[i].flags & IORESOURCE_BITS; + + ixp4xxgpioled_devices[gpio_pin].ancestor.name = + pdev->resource[i].name; + + /* This is how a board manufacturer makes the LED + * come on on reset - the GPIO line will be high, so + * make the LED light when the line is low... + */ + if (ixp4xxgpioled_devices[gpio_pin].flags != IXP4XX_GPIO_LOW) + ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 100; + else + ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 0; + + ixp4xxgpioled_devices[gpio_pin].ancestor.flags = 0; + + ixp4xxgpioled_devices[gpio_pin].ancestor.brightness_set = + ixp4xxgpioled_brightness_set; + + ixp4xxgpioled_devices[gpio_pin].ancestor.default_trigger = 0; + } + + rc = led_classdev_register(&pdev->dev, + &ixp4xxgpioled_devices[gpio_pin].ancestor); + if (rc < 0) { + ixp4xxgpioled_devices[gpio_pin].ancestor.name = 0; + ixp4xxgpioled_remove(pdev); + return rc; + } + } + + return 0; +} + +static struct platform_driver ixp4xxgpioled_driver = { + .probe = ixp4xxgpioled_probe, + .remove = ixp4xxgpioled_remove, +#ifdef CONFIG_PM + .suspend = ixp4xxgpioled_suspend, + .resume = ixp4xxgpioled_resume, +#endif + .driver = { + .name = "IXP4XX-GPIO-LED", + }, +}; + +static int __init ixp4xxgpioled_init(void) +{ + return platform_driver_register(&ixp4xxgpioled_driver); +} + +static void __exit ixp4xxgpioled_exit(void) +{ + platform_driver_unregister(&ixp4xxgpioled_driver); +} + +module_init(ixp4xxgpioled_init); +module_exit(ixp4xxgpioled_exit); + +MODULE_AUTHOR("John Bowler "); +MODULE_DESCRIPTION("IXP4XX GPIO LED driver"); +MODULE_LICENSE("Dual MIT/GPL"); -- cgit v1.2.2 From 6d0cf3e0480f6be9232854387794443d1a904d6d Mon Sep 17 00:00:00 2001 From: Dirk Opfer Date: Fri, 31 Mar 2006 02:31:12 -0800 Subject: [PATCH] LED: add device support for tosa Adds LED drivers for LEDs found on the Sharp Zaurus c6000 model (tosa). Signed-off-by: Dirk Opfer Signed-off-by: Richard Purdie Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 7 +++ drivers/leds/Makefile | 1 + drivers/leds/leds-tosa.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 drivers/leds/leds-tosa.c (limited to 'drivers') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index d9e2f9853b..64dcdd3185 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -52,6 +52,13 @@ config LEDS_IXP4XX particular board must have LEDs and they must be connected to the GPIO lines. If unsure, say Y. +config LEDS_TOSA + tristate "LED Support for the Sharp SL-6000 series" + depends LEDS_CLASS && PXA_SHARPSL + help + This option enables support for the LEDs on Sharp Zaurus + SL-6000 series. + config LEDS_TRIGGER_TIMER tristate "LED Timer Trigger" depends LEDS_TRIGGERS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index b1187c0b36..9d2930f89d 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o +obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/drivers/leds/leds-tosa.c b/drivers/leds/leds-tosa.c new file mode 100644 index 0000000000..c9e8cc1ec4 --- /dev/null +++ b/drivers/leds/leds-tosa.c @@ -0,0 +1,131 @@ +/* + * LED Triggers Core + * + * Copyright 2005 Dirk Opfer + * + * Author: Dirk Opfer + * based on spitz.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void tosaled_amber_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + if (value) + set_scoop_gpio(&tosascoop_jc_device.dev, + TOSA_SCOOP_JC_CHRG_ERR_LED); + else + reset_scoop_gpio(&tosascoop_jc_device.dev, + TOSA_SCOOP_JC_CHRG_ERR_LED); +} + +static void tosaled_green_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + if (value) + set_scoop_gpio(&tosascoop_jc_device.dev, + TOSA_SCOOP_JC_NOTE_LED); + else + reset_scoop_gpio(&tosascoop_jc_device.dev, + TOSA_SCOOP_JC_NOTE_LED); +} + +static struct led_classdev tosa_amber_led = { + .name = "tosa:amber", + .default_trigger = "sharpsl-charge", + .brightness_set = tosaled_amber_set, +}; + +static struct led_classdev tosa_green_led = { + .name = "tosa:green", + .default_trigger = "nand-disk", + .brightness_set = tosaled_green_set, +}; + +#ifdef CONFIG_PM +static int tosaled_suspend(struct platform_device *dev, pm_message_t state) +{ +#ifdef CONFIG_LEDS_TRIGGERS + if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name, + "sharpsl-charge")) +#endif + led_classdev_suspend(&tosa_amber_led); + led_classdev_suspend(&tosa_green_led); + return 0; +} + +static int tosaled_resume(struct platform_device *dev) +{ + led_classdev_resume(&tosa_amber_led); + led_classdev_resume(&tosa_green_led); + return 0; +} +#else +#define tosaled_suspend NULL +#define tosaled_resume NULL +#endif + +static int tosaled_probe(struct platform_device *pdev) +{ + int ret; + + ret = led_classdev_register(&pdev->dev, &tosa_amber_led); + if (ret < 0) + return ret; + + ret = led_classdev_register(&pdev->dev, &tosa_green_led); + if (ret < 0) + led_classdev_unregister(&tosa_amber_led); + + return ret; +} + +static int tosaled_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&tosa_amber_led); + led_classdev_unregister(&tosa_green_led); + + return 0; +} + +static struct platform_driver tosaled_driver = { + .probe = tosaled_probe, + .remove = tosaled_remove, + .suspend = tosaled_suspend, + .resume = tosaled_resume, + .driver = { + .name = "tosa-led", + }, +}; + +static int __init tosaled_init(void) +{ + return platform_driver_register(&tosaled_driver); +} + +static void __exit tosaled_exit(void) +{ + platform_driver_unregister(&tosaled_driver); +} + +module_init(tosaled_init); +module_exit(tosaled_exit); + +MODULE_AUTHOR("Dirk Opfer "); +MODULE_DESCRIPTION("Tosa LED driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.2 From 8fe833c1b010489b71b082e553b1dfa80ef81061 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:14 -0800 Subject: [PATCH] LED: add NAND MTD activity LED trigger Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/nand/nand_base.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5d222460b4..95e96fa1fc 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -80,6 +80,7 @@ #include #include #include +#include #include #ifdef CONFIG_MTD_PARTITIONS @@ -515,6 +516,8 @@ static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, i return nand_isbad_bbt (mtd, ofs, allowbbt); } +DEFINE_LED_TRIGGER(nand_led_trigger); + /* * Wait for the ready pin, after a command * The timeout is catched later. @@ -524,12 +527,14 @@ static void nand_wait_ready(struct mtd_info *mtd) struct nand_chip *this = mtd->priv; unsigned long timeo = jiffies + 2; + led_trigger_event(nand_led_trigger, LED_FULL); /* wait until command is processed or timeout occures */ do { if (this->dev_ready(mtd)) - return; + break; touch_softlockup_watchdog(); } while (time_before(jiffies, timeo)); + led_trigger_event(nand_led_trigger, LED_OFF); } /** @@ -817,6 +822,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) else timeo += (HZ * 20) / 1000; + led_trigger_event(nand_led_trigger, LED_FULL); + /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ ndelay (100); @@ -840,6 +847,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state) } cond_resched(); } + led_trigger_event(nand_led_trigger, LED_OFF); + status = (int) this->read_byte(mtd); return status; } @@ -2724,6 +2733,21 @@ void nand_release (struct mtd_info *mtd) EXPORT_SYMBOL_GPL (nand_scan); EXPORT_SYMBOL_GPL (nand_release); + +static int __init nand_base_init(void) +{ + led_trigger_register_simple("nand-disk", &nand_led_trigger); + return 0; +} + +static void __exit nand_base_exit(void) +{ + led_trigger_unregister_simple(nand_led_trigger); +} + +module_init(nand_base_init); +module_exit(nand_base_exit); + MODULE_LICENSE ("GPL"); MODULE_AUTHOR ("Steven J. Hill , Thomas Gleixner "); MODULE_DESCRIPTION ("Generic NAND flash driver code"); -- cgit v1.2.2 From 03731fbdd09f8db4af86dbf437e3169fb1920d5e Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:15 -0800 Subject: [PATCH] Ensure ide-taskfile calls any driver specific end_request function Ensure ide-taskfile.c calls any driver specific end_request function if present. Signed-off-by: Richard Purdie Cc: Alan Cox Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-taskfile.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 0606bd2f60..9233b8109a 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -375,7 +375,13 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) } } - ide_end_request(drive, 1, rq->hard_nr_sectors); + if (rq->rq_disk) { + ide_driver_t *drv; + + drv = *(ide_driver_t **)rq->rq_disk->private_data;; + drv->end_request(drive, 1, rq->hard_nr_sectors); + } else + ide_end_request(drive, 1, rq->hard_nr_sectors); } /* -- cgit v1.2.2 From 2bfb646cdf348cb77c572f06d5b9d17ea205c7e2 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:16 -0800 Subject: [PATCH] LED: Add IDE disk activity LED trigger Add an LED trigger for IDE disk activity to the ide-disk driver. Signed-off-by: Richard Purdie Acked-by: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-disk.c | 3 ++ drivers/leds/Kconfig | 7 +++++ drivers/leds/Makefile | 1 + drivers/leds/ledtrig-ide-disk.c | 62 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 drivers/leds/ledtrig-ide-disk.c (limited to 'drivers') diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index ccf528d733..a5017de72d 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -61,6 +61,7 @@ #include #include #include +#include #define _IDE_DISK @@ -317,6 +318,8 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s return ide_stopped; } + ledtrig_ide_activity(); + pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n", drive->name, rq_data_dir(rq) == READ ? "read" : "writ", (unsigned long long)block, rq->nr_sectors, diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 64dcdd3185..2c4f20b7f0 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -66,5 +66,12 @@ config LEDS_TRIGGER_TIMER This allows LEDs to be controlled by a programmable timer via sysfs. If unsure, say Y. +config LEDS_TRIGGER_IDE_DISK + bool "LED Timer Trigger" + depends LEDS_TRIGGERS && BLK_DEV_IDEDISK + help + This allows LEDs to be controlled by IDE disk activity. + If unsure, say Y. + endmenu diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 9d2930f89d..40699d3cab 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o +obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c new file mode 100644 index 0000000000..fa651886ab --- /dev/null +++ b/drivers/leds/ledtrig-ide-disk.c @@ -0,0 +1,62 @@ +/* + * LED IDE-Disk Activity Trigger + * + * Copyright 2006 Openedhand Ltd. + * + * Author: Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +static void ledtrig_ide_timerfunc(unsigned long data); + +DEFINE_LED_TRIGGER(ledtrig_ide); +static DEFINE_TIMER(ledtrig_ide_timer, ledtrig_ide_timerfunc, 0, 0); +static int ide_activity; +static int ide_lastactivity; + +void ledtrig_ide_activity(void) +{ + ide_activity++; + if (!timer_pending(&ledtrig_ide_timer)) + mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10)); +} +EXPORT_SYMBOL(ledtrig_ide_activity); + +static void ledtrig_ide_timerfunc(unsigned long data) +{ + if (ide_lastactivity != ide_activity) { + ide_lastactivity = ide_activity; + led_trigger_event(ledtrig_ide, LED_FULL); + mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10)); + } else { + led_trigger_event(ledtrig_ide, LED_OFF); + } +} + +static int __init ledtrig_ide_init(void) +{ + led_trigger_register_simple("ide-disk", &ledtrig_ide); + return 0; +} + +static void __exit ledtrig_ide_exit(void) +{ + led_trigger_unregister_simple(ledtrig_ide); +} + +module_init(ledtrig_ide_init); +module_exit(ledtrig_ide_exit); + +MODULE_AUTHOR("Richard Purdie "); +MODULE_DESCRIPTION("LED IDE Disk Activity Trigger"); +MODULE_LICENSE("GPL"); -- cgit v1.2.2 From 1a37d5f51020b9967d4b4094f6d627d0873a6469 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Fri, 31 Mar 2006 02:31:45 -0800 Subject: [PATCH] fbcon: Save current display during initialization The current display was not saved during initialization. This leads to hard to track console corruption, such as a misplaced cursor, which is correctible by switching consoles. Fix this minor bug. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index d7351560f5..ca020719d2 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -1142,6 +1142,7 @@ static void fbcon_init(struct vc_data *vc, int init) set_blitting_type(vc, info); } + ops->p = &fb_display[fg_console]; } static void fbcon_deinit(struct vc_data *vc) -- cgit v1.2.2 From 9b0e1c5dd2941aec566047e10a5cc929ca7f7d4f Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Fri, 31 Mar 2006 02:31:46 -0800 Subject: [PATCH] w100fb: Add acceleration support to ATI Imageon Add acceleration support in w100fb.c (i.e. ATI Imageons) for the copyarea and fillrect operations. Signed-off-by: Alberto Mardegan Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/w100fb.c | 162 ++++++++++- drivers/video/w100fb.h | 748 ++++++++++++++++++++++++++++++------------------- 2 files changed, 611 insertions(+), 299 deletions(-) (limited to 'drivers') diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index f6e24ee85f..5fc86ea206 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -4,8 +4,9 @@ * Frame Buffer Device for ATI Imageon w100 (Wallaby) * * Copyright (C) 2002, ATI Corp. - * Copyright (C) 2004-2005 Richard Purdie + * Copyright (C) 2004-2006 Richard Purdie * Copyright (c) 2005 Ian Molton + * Copyright (c) 2006 Alberto Mardegan * * Rewritten for 2.6 by Richard Purdie * @@ -14,6 +15,9 @@ * * w32xx support by Ian Molton * + * Hardware acceleration support by Alberto Mardegan + * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -47,6 +51,7 @@ static void w100_set_dispregs(struct w100fb_par*); static void w100_update_enable(void); static void w100_update_disable(void); static void calc_hsync(struct w100fb_par *par); +static void w100_init_graphic_engine(struct w100fb_par *par); struct w100_pll_info *w100_get_xtal_table(unsigned int freq); /* Pseudo palette size */ @@ -248,6 +253,152 @@ static int w100fb_blank(int blank_mode, struct fb_info *info) } +static void w100_fifo_wait(int entries) +{ + union rbbm_status_u status; + int i; + + for (i = 0; i < 2000000; i++) { + status.val = readl(remapped_regs + mmRBBM_STATUS); + if (status.f.cmdfifo_avail >= entries) + return; + udelay(1); + } + printk(KERN_ERR "w100fb: FIFO Timeout!\n"); +} + + +static int w100fb_sync(struct fb_info *info) +{ + union rbbm_status_u status; + int i; + + for (i = 0; i < 2000000; i++) { + status.val = readl(remapped_regs + mmRBBM_STATUS); + if (!status.f.gui_active) + return 0; + udelay(1); + } + printk(KERN_ERR "w100fb: Graphic engine timeout!\n"); + return -EBUSY; +} + + +static void w100_init_graphic_engine(struct w100fb_par *par) +{ + union dp_gui_master_cntl_u gmc; + union dp_mix_u dp_mix; + union dp_datatype_u dp_datatype; + union dp_cntl_u dp_cntl; + + w100_fifo_wait(4); + writel(W100_FB_BASE, remapped_regs + mmDST_OFFSET); + writel(par->xres, remapped_regs + mmDST_PITCH); + writel(W100_FB_BASE, remapped_regs + mmSRC_OFFSET); + writel(par->xres, remapped_regs + mmSRC_PITCH); + + w100_fifo_wait(3); + writel(0, remapped_regs + mmSC_TOP_LEFT); + writel((par->yres << 16) | par->xres, remapped_regs + mmSC_BOTTOM_RIGHT); + writel(0x1fff1fff, remapped_regs + mmSRC_SC_BOTTOM_RIGHT); + + w100_fifo_wait(4); + dp_cntl.val = 0; + dp_cntl.f.dst_x_dir = 1; + dp_cntl.f.dst_y_dir = 1; + dp_cntl.f.src_x_dir = 1; + dp_cntl.f.src_y_dir = 1; + dp_cntl.f.dst_major_x = 1; + dp_cntl.f.src_major_x = 1; + writel(dp_cntl.val, remapped_regs + mmDP_CNTL); + + gmc.val = 0; + gmc.f.gmc_src_pitch_offset_cntl = 1; + gmc.f.gmc_dst_pitch_offset_cntl = 1; + gmc.f.gmc_src_clipping = 1; + gmc.f.gmc_dst_clipping = 1; + gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE; + gmc.f.gmc_dst_datatype = 3; /* from DstType_16Bpp_444 */ + gmc.f.gmc_src_datatype = SRC_DATATYPE_EQU_DST; + gmc.f.gmc_byte_pix_order = 1; + gmc.f.gmc_default_sel = 0; + gmc.f.gmc_rop3 = ROP3_SRCCOPY; + gmc.f.gmc_dp_src_source = DP_SRC_MEM_RECTANGULAR; + gmc.f.gmc_clr_cmp_fcn_dis = 1; + gmc.f.gmc_wr_msk_dis = 1; + gmc.f.gmc_dp_op = DP_OP_ROP; + writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL); + + dp_datatype.val = dp_mix.val = 0; + dp_datatype.f.dp_dst_datatype = gmc.f.gmc_dst_datatype; + dp_datatype.f.dp_brush_datatype = gmc.f.gmc_brush_datatype; + dp_datatype.f.dp_src2_type = 0; + dp_datatype.f.dp_src2_datatype = gmc.f.gmc_src_datatype; + dp_datatype.f.dp_src_datatype = gmc.f.gmc_src_datatype; + dp_datatype.f.dp_byte_pix_order = gmc.f.gmc_byte_pix_order; + writel(dp_datatype.val, remapped_regs + mmDP_DATATYPE); + + dp_mix.f.dp_src_source = gmc.f.gmc_dp_src_source; + dp_mix.f.dp_src2_source = 1; + dp_mix.f.dp_rop3 = gmc.f.gmc_rop3; + dp_mix.f.dp_op = gmc.f.gmc_dp_op; + writel(dp_mix.val, remapped_regs + mmDP_MIX); +} + + +static void w100fb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) +{ + union dp_gui_master_cntl_u gmc; + + if (info->state != FBINFO_STATE_RUNNING) + return; + if (info->flags & FBINFO_HWACCEL_DISABLED) { + cfb_fillrect(info, rect); + return; + } + + gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL); + gmc.f.gmc_rop3 = ROP3_PATCOPY; + gmc.f.gmc_brush_datatype = GMC_BRUSH_SOLID_COLOR; + w100_fifo_wait(2); + writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL); + writel(rect->color, remapped_regs + mmDP_BRUSH_FRGD_CLR); + + w100_fifo_wait(2); + writel((rect->dy << 16) | (rect->dx & 0xffff), remapped_regs + mmDST_Y_X); + writel((rect->width << 16) | (rect->height & 0xffff), + remapped_regs + mmDST_WIDTH_HEIGHT); +} + + +static void w100fb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) +{ + u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; + u32 h = area->height, w = area->width; + union dp_gui_master_cntl_u gmc; + + if (info->state != FBINFO_STATE_RUNNING) + return; + if (info->flags & FBINFO_HWACCEL_DISABLED) { + cfb_copyarea(info, area); + return; + } + + gmc.val = readl(remapped_regs + mmDP_GUI_MASTER_CNTL); + gmc.f.gmc_rop3 = ROP3_SRCCOPY; + gmc.f.gmc_brush_datatype = GMC_BRUSH_NONE; + w100_fifo_wait(1); + writel(gmc.val, remapped_regs + mmDP_GUI_MASTER_CNTL); + + w100_fifo_wait(3); + writel((sy << 16) | (sx & 0xffff), remapped_regs + mmSRC_Y_X); + writel((dy << 16) | (dx & 0xffff), remapped_regs + mmDST_Y_X); + writel((w << 16) | (h & 0xffff), remapped_regs + mmDST_WIDTH_HEIGHT); +} + + /* * Change the resolution by calling the appropriate hardware functions */ @@ -265,6 +416,7 @@ static void w100fb_activate_var(struct w100fb_par *par) w100_init_lcd(par); w100_set_dispregs(par); w100_update_enable(); + w100_init_graphic_engine(par); calc_hsync(par); @@ -394,9 +546,10 @@ static struct fb_ops w100fb_ops = { .fb_set_par = w100fb_set_par, .fb_setcolreg = w100fb_setcolreg, .fb_blank = w100fb_blank, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, + .fb_fillrect = w100fb_fillrect, + .fb_copyarea = w100fb_copyarea, .fb_imageblit = cfb_imageblit, + .fb_sync = w100fb_sync, }; #ifdef CONFIG_PM @@ -543,7 +696,8 @@ int __init w100fb_probe(struct platform_device *pdev) } info->fbops = &w100fb_ops; - info->flags = FBINFO_DEFAULT; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | + FBINFO_HWACCEL_FILLRECT; info->node = -1; info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE); info->screen_size = REMAPPED_FB_LEN; diff --git a/drivers/video/w100fb.h b/drivers/video/w100fb.h index 7a58a1e3e4..fffae7b4f6 100644 --- a/drivers/video/w100fb.h +++ b/drivers/video/w100fb.h @@ -122,15 +122,32 @@ /* Block DISPLAY End: */ /* Block GFX Start: */ +#define mmDST_OFFSET 0x1004 +#define mmDST_PITCH 0x1008 +#define mmDST_Y_X 0x1038 +#define mmDST_WIDTH_HEIGHT 0x1198 +#define mmDP_GUI_MASTER_CNTL 0x106C #define mmBRUSH_OFFSET 0x108C #define mmBRUSH_Y_X 0x1074 +#define mmDP_BRUSH_FRGD_CLR 0x107C +#define mmSRC_OFFSET 0x11AC +#define mmSRC_PITCH 0x11B0 +#define mmSRC_Y_X 0x1034 #define mmDEFAULT_PITCH_OFFSET 0x10A0 #define mmDEFAULT_SC_BOTTOM_RIGHT 0x10A8 #define mmDEFAULT2_SC_BOTTOM_RIGHT 0x10AC +#define mmSC_TOP_LEFT 0x11BC +#define mmSC_BOTTOM_RIGHT 0x11C0 +#define mmSRC_SC_BOTTOM_RIGHT 0x11C4 #define mmGLOBAL_ALPHA 0x1210 #define mmFILTER_COEF 0x1214 #define mmMVC_CNTL_START 0x11E0 #define mmE2_ARITHMETIC_CNTL 0x1220 +#define mmDP_CNTL 0x11C8 +#define mmDP_CNTL_DST_DIR 0x11CC +#define mmDP_DATATYPE 0x12C4 +#define mmDP_MIX 0x12C8 +#define mmDP_WRITE_MSK 0x12CC #define mmENG_CNTL 0x13E8 #define mmENG_PERF_CNT 0x13F0 /* Block GFX End: */ @@ -179,6 +196,7 @@ /* Block RBBM Start: */ #define mmWAIT_UNTIL 0x1400 #define mmISYNC_CNTL 0x1404 +#define mmRBBM_STATUS 0x0140 #define mmRBBM_CNTL 0x0144 #define mmNQWAIT_UNTIL 0x0150 /* Block RBBM End: */ @@ -225,147 +243,147 @@ /* Register structure definitions */ struct wrap_top_dir_t { - unsigned long top_addr : 23; - unsigned long : 9; + u32 top_addr : 23; + u32 : 9; } __attribute__((packed)); union wrap_top_dir_u { - unsigned long val : 32; + u32 val : 32; struct wrap_top_dir_t f; } __attribute__((packed)); struct wrap_start_dir_t { - unsigned long start_addr : 23; - unsigned long : 9; + u32 start_addr : 23; + u32 : 9; } __attribute__((packed)); union wrap_start_dir_u { - unsigned long val : 32; + u32 val : 32; struct wrap_start_dir_t f; } __attribute__((packed)); struct cif_cntl_t { - unsigned long swap_reg : 2; - unsigned long swap_fbuf_1 : 2; - unsigned long swap_fbuf_2 : 2; - unsigned long swap_fbuf_3 : 2; - unsigned long pmi_int_disable : 1; - unsigned long pmi_schmen_disable : 1; - unsigned long intb_oe : 1; - unsigned long en_wait_to_compensate_dq_prop_dly : 1; - unsigned long compensate_wait_rd_size : 2; - unsigned long wait_asserted_timeout_val : 2; - unsigned long wait_masked_val : 2; - unsigned long en_wait_timeout : 1; - unsigned long en_one_clk_setup_before_wait : 1; - unsigned long interrupt_active_high : 1; - unsigned long en_overwrite_straps : 1; - unsigned long strap_wait_active_hi : 1; - unsigned long lat_busy_count : 2; - unsigned long lat_rd_pm4_sclk_busy : 1; - unsigned long dis_system_bits : 1; - unsigned long dis_mr : 1; - unsigned long cif_spare_1 : 4; + u32 swap_reg : 2; + u32 swap_fbuf_1 : 2; + u32 swap_fbuf_2 : 2; + u32 swap_fbuf_3 : 2; + u32 pmi_int_disable : 1; + u32 pmi_schmen_disable : 1; + u32 intb_oe : 1; + u32 en_wait_to_compensate_dq_prop_dly : 1; + u32 compensate_wait_rd_size : 2; + u32 wait_asserted_timeout_val : 2; + u32 wait_masked_val : 2; + u32 en_wait_timeout : 1; + u32 en_one_clk_setup_before_wait : 1; + u32 interrupt_active_high : 1; + u32 en_overwrite_straps : 1; + u32 strap_wait_active_hi : 1; + u32 lat_busy_count : 2; + u32 lat_rd_pm4_sclk_busy : 1; + u32 dis_system_bits : 1; + u32 dis_mr : 1; + u32 cif_spare_1 : 4; } __attribute__((packed)); union cif_cntl_u { - unsigned long val : 32; + u32 val : 32; struct cif_cntl_t f; } __attribute__((packed)); struct cfgreg_base_t { - unsigned long cfgreg_base : 24; - unsigned long : 8; + u32 cfgreg_base : 24; + u32 : 8; } __attribute__((packed)); union cfgreg_base_u { - unsigned long val : 32; + u32 val : 32; struct cfgreg_base_t f; } __attribute__((packed)); struct cif_io_t { - unsigned long dq_srp : 1; - unsigned long dq_srn : 1; - unsigned long dq_sp : 4; - unsigned long dq_sn : 4; - unsigned long waitb_srp : 1; - unsigned long waitb_srn : 1; - unsigned long waitb_sp : 4; - unsigned long waitb_sn : 4; - unsigned long intb_srp : 1; - unsigned long intb_srn : 1; - unsigned long intb_sp : 4; - unsigned long intb_sn : 4; - unsigned long : 2; + u32 dq_srp : 1; + u32 dq_srn : 1; + u32 dq_sp : 4; + u32 dq_sn : 4; + u32 waitb_srp : 1; + u32 waitb_srn : 1; + u32 waitb_sp : 4; + u32 waitb_sn : 4; + u32 intb_srp : 1; + u32 intb_srn : 1; + u32 intb_sp : 4; + u32 intb_sn : 4; + u32 : 2; } __attribute__((packed)); union cif_io_u { - unsigned long val : 32; + u32 val : 32; struct cif_io_t f; } __attribute__((packed)); struct cif_read_dbg_t { - unsigned long unpacker_pre_fetch_trig_gen : 2; - unsigned long dly_second_rd_fetch_trig : 1; - unsigned long rst_rd_burst_id : 1; - unsigned long dis_rd_burst_id : 1; - unsigned long en_block_rd_when_packer_is_not_emp : 1; - unsigned long dis_pre_fetch_cntl_sm : 1; - unsigned long rbbm_chrncy_dis : 1; - unsigned long rbbm_rd_after_wr_lat : 2; - unsigned long dis_be_during_rd : 1; - unsigned long one_clk_invalidate_pulse : 1; - unsigned long dis_chnl_priority : 1; - unsigned long rst_read_path_a_pls : 1; - unsigned long rst_read_path_b_pls : 1; - unsigned long dis_reg_rd_fetch_trig : 1; - unsigned long dis_rd_fetch_trig_from_ind_addr : 1; - unsigned long dis_rd_same_byte_to_trig_fetch : 1; - unsigned long dis_dir_wrap : 1; - unsigned long dis_ring_buf_to_force_dec : 1; - unsigned long dis_addr_comp_in_16bit : 1; - unsigned long clr_w : 1; - unsigned long err_rd_tag_is_3 : 1; - unsigned long err_load_when_ful_a : 1; - unsigned long err_load_when_ful_b : 1; - unsigned long : 7; + u32 unpacker_pre_fetch_trig_gen : 2; + u32 dly_second_rd_fetch_trig : 1; + u32 rst_rd_burst_id : 1; + u32 dis_rd_burst_id : 1; + u32 en_block_rd_when_packer_is_not_emp : 1; + u32 dis_pre_fetch_cntl_sm : 1; + u32 rbbm_chrncy_dis : 1; + u32 rbbm_rd_after_wr_lat : 2; + u32 dis_be_during_rd : 1; + u32 one_clk_invalidate_pulse : 1; + u32 dis_chnl_priority : 1; + u32 rst_read_path_a_pls : 1; + u32 rst_read_path_b_pls : 1; + u32 dis_reg_rd_fetch_trig : 1; + u32 dis_rd_fetch_trig_from_ind_addr : 1; + u32 dis_rd_same_byte_to_trig_fetch : 1; + u32 dis_dir_wrap : 1; + u32 dis_ring_buf_to_force_dec : 1; + u32 dis_addr_comp_in_16bit : 1; + u32 clr_w : 1; + u32 err_rd_tag_is_3 : 1; + u32 err_load_when_ful_a : 1; + u32 err_load_when_ful_b : 1; + u32 : 7; } __attribute__((packed)); union cif_read_dbg_u { - unsigned long val : 32; + u32 val : 32; struct cif_read_dbg_t f; } __attribute__((packed)); struct cif_write_dbg_t { - unsigned long packer_timeout_count : 2; - unsigned long en_upper_load_cond : 1; - unsigned long en_chnl_change_cond : 1; - unsigned long dis_addr_comp_cond : 1; - unsigned long dis_load_same_byte_addr_cond : 1; - unsigned long dis_timeout_cond : 1; - unsigned long dis_timeout_during_rbbm : 1; - unsigned long dis_packer_ful_during_rbbm_timeout : 1; - unsigned long en_dword_split_to_rbbm : 1; - unsigned long en_dummy_val : 1; - unsigned long dummy_val_sel : 1; - unsigned long mask_pm4_wrptr_dec : 1; - unsigned long dis_mc_clean_cond : 1; - unsigned long err_two_reqi_during_ful : 1; - unsigned long err_reqi_during_idle_clk : 1; - unsigned long err_global : 1; - unsigned long en_wr_buf_dbg_load : 1; - unsigned long en_wr_buf_dbg_path : 1; - unsigned long sel_wr_buf_byte : 3; - unsigned long dis_rd_flush_wr : 1; - unsigned long dis_packer_ful_cond : 1; - unsigned long dis_invalidate_by_ops_chnl : 1; - unsigned long en_halt_when_reqi_err : 1; - unsigned long cif_spare_2 : 5; - unsigned long : 1; + u32 packer_timeout_count : 2; + u32 en_upper_load_cond : 1; + u32 en_chnl_change_cond : 1; + u32 dis_addr_comp_cond : 1; + u32 dis_load_same_byte_addr_cond : 1; + u32 dis_timeout_cond : 1; + u32 dis_timeout_during_rbbm : 1; + u32 dis_packer_ful_during_rbbm_timeout : 1; + u32 en_dword_split_to_rbbm : 1; + u32 en_dummy_val : 1; + u32 dummy_val_sel : 1; + u32 mask_pm4_wrptr_dec : 1; + u32 dis_mc_clean_cond : 1; + u32 err_two_reqi_during_ful : 1; + u32 err_reqi_during_idle_clk : 1; + u32 err_global : 1; + u32 en_wr_buf_dbg_load : 1; + u32 en_wr_buf_dbg_path : 1; + u32 sel_wr_buf_byte : 3; + u32 dis_rd_flush_wr : 1; + u32 dis_packer_ful_cond : 1; + u32 dis_invalidate_by_ops_chnl : 1; + u32 en_halt_when_reqi_err : 1; + u32 cif_spare_2 : 5; + u32 : 1; } __attribute__((packed)); union cif_write_dbg_u { - unsigned long val : 32; + u32 val : 32; struct cif_write_dbg_t f; } __attribute__((packed)); @@ -403,327 +421,327 @@ union cpu_defaults_u { } __attribute__((packed)); struct crtc_total_t { - unsigned long crtc_h_total : 10; - unsigned long : 6; - unsigned long crtc_v_total : 10; - unsigned long : 6; + u32 crtc_h_total : 10; + u32 : 6; + u32 crtc_v_total : 10; + u32 : 6; } __attribute__((packed)); union crtc_total_u { - unsigned long val : 32; + u32 val : 32; struct crtc_total_t f; } __attribute__((packed)); struct crtc_ss_t { - unsigned long ss_start : 10; - unsigned long : 6; - unsigned long ss_end : 10; - unsigned long : 2; - unsigned long ss_align : 1; - unsigned long ss_pol : 1; - unsigned long ss_run_mode : 1; - unsigned long ss_en : 1; + u32 ss_start : 10; + u32 : 6; + u32 ss_end : 10; + u32 : 2; + u32 ss_align : 1; + u32 ss_pol : 1; + u32 ss_run_mode : 1; + u32 ss_en : 1; } __attribute__((packed)); union crtc_ss_u { - unsigned long val : 32; + u32 val : 32; struct crtc_ss_t f; } __attribute__((packed)); struct active_h_disp_t { - unsigned long active_h_start : 10; - unsigned long : 6; - unsigned long active_h_end : 10; - unsigned long : 6; + u32 active_h_start : 10; + u32 : 6; + u32 active_h_end : 10; + u32 : 6; } __attribute__((packed)); union active_h_disp_u { - unsigned long val : 32; + u32 val : 32; struct active_h_disp_t f; } __attribute__((packed)); struct active_v_disp_t { - unsigned long active_v_start : 10; - unsigned long : 6; - unsigned long active_v_end : 10; - unsigned long : 6; + u32 active_v_start : 10; + u32 : 6; + u32 active_v_end : 10; + u32 : 6; } __attribute__((packed)); union active_v_disp_u { - unsigned long val : 32; + u32 val : 32; struct active_v_disp_t f; } __attribute__((packed)); struct graphic_h_disp_t { - unsigned long graphic_h_start : 10; - unsigned long : 6; - unsigned long graphic_h_end : 10; - unsigned long : 6; + u32 graphic_h_start : 10; + u32 : 6; + u32 graphic_h_end : 10; + u32 : 6; } __attribute__((packed)); union graphic_h_disp_u { - unsigned long val : 32; + u32 val : 32; struct graphic_h_disp_t f; } __attribute__((packed)); struct graphic_v_disp_t { - unsigned long graphic_v_start : 10; - unsigned long : 6; - unsigned long graphic_v_end : 10; - unsigned long : 6; + u32 graphic_v_start : 10; + u32 : 6; + u32 graphic_v_end : 10; + u32 : 6; } __attribute__((packed)); union graphic_v_disp_u{ - unsigned long val : 32; + u32 val : 32; struct graphic_v_disp_t f; } __attribute__((packed)); struct graphic_ctrl_t_w100 { - unsigned long color_depth : 3; - unsigned long portrait_mode : 2; - unsigned long low_power_on : 1; - unsigned long req_freq : 4; - unsigned long en_crtc : 1; - unsigned long en_graphic_req : 1; - unsigned long en_graphic_crtc : 1; - unsigned long total_req_graphic : 9; - unsigned long lcd_pclk_on : 1; - unsigned long lcd_sclk_on : 1; - unsigned long pclk_running : 1; - unsigned long sclk_running : 1; - unsigned long : 6; + u32 color_depth : 3; + u32 portrait_mode : 2; + u32 low_power_on : 1; + u32 req_freq : 4; + u32 en_crtc : 1; + u32 en_graphic_req : 1; + u32 en_graphic_crtc : 1; + u32 total_req_graphic : 9; + u32 lcd_pclk_on : 1; + u32 lcd_sclk_on : 1; + u32 pclk_running : 1; + u32 sclk_running : 1; + u32 : 6; } __attribute__((packed)); struct graphic_ctrl_t_w32xx { - unsigned long color_depth : 3; - unsigned long portrait_mode : 2; - unsigned long low_power_on : 1; - unsigned long req_freq : 4; - unsigned long en_crtc : 1; - unsigned long en_graphic_req : 1; - unsigned long en_graphic_crtc : 1; - unsigned long total_req_graphic : 10; - unsigned long lcd_pclk_on : 1; - unsigned long lcd_sclk_on : 1; - unsigned long pclk_running : 1; - unsigned long sclk_running : 1; - unsigned long : 5; + u32 color_depth : 3; + u32 portrait_mode : 2; + u32 low_power_on : 1; + u32 req_freq : 4; + u32 en_crtc : 1; + u32 en_graphic_req : 1; + u32 en_graphic_crtc : 1; + u32 total_req_graphic : 10; + u32 lcd_pclk_on : 1; + u32 lcd_sclk_on : 1; + u32 pclk_running : 1; + u32 sclk_running : 1; + u32 : 5; } __attribute__((packed)); union graphic_ctrl_u { - unsigned long val : 32; + u32 val : 32; struct graphic_ctrl_t_w100 f_w100; struct graphic_ctrl_t_w32xx f_w32xx; } __attribute__((packed)); struct video_ctrl_t { - unsigned long video_mode : 1; - unsigned long keyer_en : 1; - unsigned long en_video_req : 1; - unsigned long en_graphic_req_video : 1; - unsigned long en_video_crtc : 1; - unsigned long video_hor_exp : 2; - unsigned long video_ver_exp : 2; - unsigned long uv_combine : 1; - unsigned long total_req_video : 9; - unsigned long video_ch_sel : 1; - unsigned long video_portrait : 2; - unsigned long yuv2rgb_en : 1; - unsigned long yuv2rgb_option : 1; - unsigned long video_inv_hor : 1; - unsigned long video_inv_ver : 1; - unsigned long gamma_sel : 2; - unsigned long dis_limit : 1; - unsigned long en_uv_hblend : 1; - unsigned long rgb_gamma_sel : 2; + u32 video_mode : 1; + u32 keyer_en : 1; + u32 en_video_req : 1; + u32 en_graphic_req_video : 1; + u32 en_video_crtc : 1; + u32 video_hor_exp : 2; + u32 video_ver_exp : 2; + u32 uv_combine : 1; + u32 total_req_video : 9; + u32 video_ch_sel : 1; + u32 video_portrait : 2; + u32 yuv2rgb_en : 1; + u32 yuv2rgb_option : 1; + u32 video_inv_hor : 1; + u32 video_inv_ver : 1; + u32 gamma_sel : 2; + u32 dis_limit : 1; + u32 en_uv_hblend : 1; + u32 rgb_gamma_sel : 2; } __attribute__((packed)); union video_ctrl_u { - unsigned long val : 32; + u32 val : 32; struct video_ctrl_t f; } __attribute__((packed)); struct disp_db_buf_cntl_rd_t { - unsigned long en_db_buf : 1; - unsigned long update_db_buf_done : 1; - unsigned long db_buf_cntl : 6; - unsigned long : 24; + u32 en_db_buf : 1; + u32 update_db_buf_done : 1; + u32 db_buf_cntl : 6; + u32 : 24; } __attribute__((packed)); union disp_db_buf_cntl_rd_u { - unsigned long val : 32; + u32 val : 32; struct disp_db_buf_cntl_rd_t f; } __attribute__((packed)); struct disp_db_buf_cntl_wr_t { - unsigned long en_db_buf : 1; - unsigned long update_db_buf : 1; - unsigned long db_buf_cntl : 6; - unsigned long : 24; + u32 en_db_buf : 1; + u32 update_db_buf : 1; + u32 db_buf_cntl : 6; + u32 : 24; } __attribute__((packed)); union disp_db_buf_cntl_wr_u { - unsigned long val : 32; + u32 val : 32; struct disp_db_buf_cntl_wr_t f; } __attribute__((packed)); struct gamma_value1_t { - unsigned long gamma1 : 8; - unsigned long gamma2 : 8; - unsigned long gamma3 : 8; - unsigned long gamma4 : 8; + u32 gamma1 : 8; + u32 gamma2 : 8; + u32 gamma3 : 8; + u32 gamma4 : 8; } __attribute__((packed)); union gamma_value1_u { - unsigned long val : 32; + u32 val : 32; struct gamma_value1_t f; } __attribute__((packed)); struct gamma_value2_t { - unsigned long gamma5 : 8; - unsigned long gamma6 : 8; - unsigned long gamma7 : 8; - unsigned long gamma8 : 8; + u32 gamma5 : 8; + u32 gamma6 : 8; + u32 gamma7 : 8; + u32 gamma8 : 8; } __attribute__((packed)); union gamma_value2_u { - unsigned long val : 32; + u32 val : 32; struct gamma_value2_t f; } __attribute__((packed)); struct gamma_slope_t { - unsigned long slope1 : 3; - unsigned long slope2 : 3; - unsigned long slope3 : 3; - unsigned long slope4 : 3; - unsigned long slope5 : 3; - unsigned long slope6 : 3; - unsigned long slope7 : 3; - unsigned long slope8 : 3; - unsigned long : 8; + u32 slope1 : 3; + u32 slope2 : 3; + u32 slope3 : 3; + u32 slope4 : 3; + u32 slope5 : 3; + u32 slope6 : 3; + u32 slope7 : 3; + u32 slope8 : 3; + u32 : 8; } __attribute__((packed)); union gamma_slope_u { - unsigned long val : 32; + u32 val : 32; struct gamma_slope_t f; } __attribute__((packed)); struct mc_ext_mem_location_t { - unsigned long mc_ext_mem_start : 16; - unsigned long mc_ext_mem_top : 16; + u32 mc_ext_mem_start : 16; + u32 mc_ext_mem_top : 16; } __attribute__((packed)); union mc_ext_mem_location_u { - unsigned long val : 32; + u32 val : 32; struct mc_ext_mem_location_t f; } __attribute__((packed)); struct mc_fb_location_t { - unsigned long mc_fb_start : 16; - unsigned long mc_fb_top : 16; + u32 mc_fb_start : 16; + u32 mc_fb_top : 16; } __attribute__((packed)); union mc_fb_location_u { - unsigned long val : 32; + u32 val : 32; struct mc_fb_location_t f; } __attribute__((packed)); struct clk_pin_cntl_t { - unsigned long osc_en : 1; - unsigned long osc_gain : 5; - unsigned long dont_use_xtalin : 1; - unsigned long xtalin_pm_en : 1; - unsigned long xtalin_dbl_en : 1; - unsigned long : 7; - unsigned long cg_debug : 16; + u32 osc_en : 1; + u32 osc_gain : 5; + u32 dont_use_xtalin : 1; + u32 xtalin_pm_en : 1; + u32 xtalin_dbl_en : 1; + u32 : 7; + u32 cg_debug : 16; } __attribute__((packed)); union clk_pin_cntl_u { - unsigned long val : 32; + u32 val : 32; struct clk_pin_cntl_t f; } __attribute__((packed)); struct pll_ref_fb_div_t { - unsigned long pll_ref_div : 4; - unsigned long : 4; - unsigned long pll_fb_div_int : 6; - unsigned long : 2; - unsigned long pll_fb_div_frac : 3; - unsigned long : 1; - unsigned long pll_reset_time : 4; - unsigned long pll_lock_time : 8; + u32 pll_ref_div : 4; + u32 : 4; + u32 pll_fb_div_int : 6; + u32 : 2; + u32 pll_fb_div_frac : 3; + u32 : 1; + u32 pll_reset_time : 4; + u32 pll_lock_time : 8; } __attribute__((packed)); union pll_ref_fb_div_u { - unsigned long val : 32; + u32 val : 32; struct pll_ref_fb_div_t f; } __attribute__((packed)); struct pll_cntl_t { - unsigned long pll_pwdn : 1; - unsigned long pll_reset : 1; - unsigned long pll_pm_en : 1; - unsigned long pll_mode : 1; - unsigned long pll_refclk_sel : 1; - unsigned long pll_fbclk_sel : 1; - unsigned long pll_tcpoff : 1; - unsigned long pll_pcp : 3; - unsigned long pll_pvg : 3; - unsigned long pll_vcofr : 1; - unsigned long pll_ioffset : 2; - unsigned long pll_pecc_mode : 2; - unsigned long pll_pecc_scon : 2; - unsigned long pll_dactal : 4; - unsigned long pll_cp_clip : 2; - unsigned long pll_conf : 3; - unsigned long pll_mbctrl : 2; - unsigned long pll_ring_off : 1; + u32 pll_pwdn : 1; + u32 pll_reset : 1; + u32 pll_pm_en : 1; + u32 pll_mode : 1; + u32 pll_refclk_sel : 1; + u32 pll_fbclk_sel : 1; + u32 pll_tcpoff : 1; + u32 pll_pcp : 3; + u32 pll_pvg : 3; + u32 pll_vcofr : 1; + u32 pll_ioffset : 2; + u32 pll_pecc_mode : 2; + u32 pll_pecc_scon : 2; + u32 pll_dactal : 4; + u32 pll_cp_clip : 2; + u32 pll_conf : 3; + u32 pll_mbctrl : 2; + u32 pll_ring_off : 1; } __attribute__((packed)); union pll_cntl_u { - unsigned long val : 32; + u32 val : 32; struct pll_cntl_t f; } __attribute__((packed)); struct sclk_cntl_t { - unsigned long sclk_src_sel : 2; - unsigned long : 2; - unsigned long sclk_post_div_fast : 4; - unsigned long sclk_clkon_hys : 3; - unsigned long sclk_post_div_slow : 4; - unsigned long disp_cg_ok2switch_en : 1; - unsigned long sclk_force_reg : 1; - unsigned long sclk_force_disp : 1; - unsigned long sclk_force_mc : 1; - unsigned long sclk_force_extmc : 1; - unsigned long sclk_force_cp : 1; - unsigned long sclk_force_e2 : 1; - unsigned long sclk_force_e3 : 1; - unsigned long sclk_force_idct : 1; - unsigned long sclk_force_bist : 1; - unsigned long busy_extend_cp : 1; - unsigned long busy_extend_e2 : 1; - unsigned long busy_extend_e3 : 1; - unsigned long busy_extend_idct : 1; - unsigned long : 3; + u32 sclk_src_sel : 2; + u32 : 2; + u32 sclk_post_div_fast : 4; + u32 sclk_clkon_hys : 3; + u32 sclk_post_div_slow : 4; + u32 disp_cg_ok2switch_en : 1; + u32 sclk_force_reg : 1; + u32 sclk_force_disp : 1; + u32 sclk_force_mc : 1; + u32 sclk_force_extmc : 1; + u32 sclk_force_cp : 1; + u32 sclk_force_e2 : 1; + u32 sclk_force_e3 : 1; + u32 sclk_force_idct : 1; + u32 sclk_force_bist : 1; + u32 busy_extend_cp : 1; + u32 busy_extend_e2 : 1; + u32 busy_extend_e3 : 1; + u32 busy_extend_idct : 1; + u32 : 3; } __attribute__((packed)); union sclk_cntl_u { - unsigned long val : 32; + u32 val : 32; struct sclk_cntl_t f; } __attribute__((packed)); struct pclk_cntl_t { - unsigned long pclk_src_sel : 2; - unsigned long : 2; - unsigned long pclk_post_div : 4; - unsigned long : 8; - unsigned long pclk_force_disp : 1; - unsigned long : 15; + u32 pclk_src_sel : 2; + u32 : 2; + u32 pclk_post_div : 4; + u32 : 8; + u32 pclk_force_disp : 1; + u32 : 15; } __attribute__((packed)); union pclk_cntl_u { - unsigned long val : 32; + u32 val : 32; struct pclk_cntl_t f; } __attribute__((packed)); @@ -735,36 +753,176 @@ union pclk_cntl_u { #define TESTCLK_SRC_XTAL 0x06 struct clk_test_cntl_t { - unsigned long testclk_sel : 4; - unsigned long : 3; - unsigned long start_check_freq : 1; - unsigned long tstcount_rst : 1; - unsigned long : 15; - unsigned long test_count : 8; + u32 testclk_sel : 4; + u32 : 3; + u32 start_check_freq : 1; + u32 tstcount_rst : 1; + u32 : 15; + u32 test_count : 8; } __attribute__((packed)); union clk_test_cntl_u { - unsigned long val : 32; + u32 val : 32; struct clk_test_cntl_t f; } __attribute__((packed)); struct pwrmgt_cntl_t { - unsigned long pwm_enable : 1; - unsigned long : 1; - unsigned long pwm_mode_req : 2; - unsigned long pwm_wakeup_cond : 2; - unsigned long pwm_fast_noml_hw_en : 1; - unsigned long pwm_noml_fast_hw_en : 1; - unsigned long pwm_fast_noml_cond : 4; - unsigned long pwm_noml_fast_cond : 4; - unsigned long pwm_idle_timer : 8; - unsigned long pwm_busy_timer : 8; + u32 pwm_enable : 1; + u32 : 1; + u32 pwm_mode_req : 2; + u32 pwm_wakeup_cond : 2; + u32 pwm_fast_noml_hw_en : 1; + u32 pwm_noml_fast_hw_en : 1; + u32 pwm_fast_noml_cond : 4; + u32 pwm_noml_fast_cond : 4; + u32 pwm_idle_timer : 8; + u32 pwm_busy_timer : 8; } __attribute__((packed)); union pwrmgt_cntl_u { - unsigned long val : 32; + u32 val : 32; struct pwrmgt_cntl_t f; } __attribute__((packed)); +#define SRC_DATATYPE_EQU_DST 3 + +#define ROP3_SRCCOPY 0xcc +#define ROP3_PATCOPY 0xf0 + +#define GMC_BRUSH_SOLID_COLOR 13 +#define GMC_BRUSH_NONE 15 + +#define DP_SRC_MEM_RECTANGULAR 2 + +#define DP_OP_ROP 0 + +struct dp_gui_master_cntl_t { + u32 gmc_src_pitch_offset_cntl : 1; + u32 gmc_dst_pitch_offset_cntl : 1; + u32 gmc_src_clipping : 1; + u32 gmc_dst_clipping : 1; + u32 gmc_brush_datatype : 4; + u32 gmc_dst_datatype : 4; + u32 gmc_src_datatype : 3; + u32 gmc_byte_pix_order : 1; + u32 gmc_default_sel : 1; + u32 gmc_rop3 : 8; + u32 gmc_dp_src_source : 3; + u32 gmc_clr_cmp_fcn_dis : 1; + u32 : 1; + u32 gmc_wr_msk_dis : 1; + u32 gmc_dp_op : 1; +} __attribute__((packed)); + +union dp_gui_master_cntl_u { + u32 val : 32; + struct dp_gui_master_cntl_t f; +} __attribute__((packed)); + +struct rbbm_status_t { + u32 cmdfifo_avail : 7; + u32 : 1; + u32 hirq_on_rbb : 1; + u32 cprq_on_rbb : 1; + u32 cfrq_on_rbb : 1; + u32 hirq_in_rtbuf : 1; + u32 cprq_in_rtbuf : 1; + u32 cfrq_in_rtbuf : 1; + u32 cf_pipe_busy : 1; + u32 eng_ev_busy : 1; + u32 cp_cmdstrm_busy : 1; + u32 e2_busy : 1; + u32 rb2d_busy : 1; + u32 rb3d_busy : 1; + u32 se_busy : 1; + u32 re_busy : 1; + u32 tam_busy : 1; + u32 tdm_busy : 1; + u32 pb_busy : 1; + u32 : 6; + u32 gui_active : 1; +} __attribute__((packed)); + +union rbbm_status_u { + u32 val : 32; + struct rbbm_status_t f; +} __attribute__((packed)); + +struct dp_datatype_t { + u32 dp_dst_datatype : 4; + u32 : 4; + u32 dp_brush_datatype : 4; + u32 dp_src2_type : 1; + u32 dp_src2_datatype : 3; + u32 dp_src_datatype : 3; + u32 : 11; + u32 dp_byte_pix_order : 1; + u32 : 1; +} __attribute__((packed)); + +union dp_datatype_u { + u32 val : 32; + struct dp_datatype_t f; +} __attribute__((packed)); + +struct dp_mix_t { + u32 : 8; + u32 dp_src_source : 3; + u32 dp_src2_source : 3; + u32 : 2; + u32 dp_rop3 : 8; + u32 dp_op : 1; + u32 : 7; +} __attribute__((packed)); + +union dp_mix_u { + u32 val : 32; + struct dp_mix_t f; +} __attribute__((packed)); + +struct eng_cntl_t { + u32 erc_reg_rd_ws : 1; + u32 erc_reg_wr_ws : 1; + u32 erc_idle_reg_wr : 1; + u32 dis_engine_triggers : 1; + u32 dis_rop_src_uses_dst_w_h : 1; + u32 dis_src_uses_dst_dirmaj : 1; + u32 : 6; + u32 force_3dclk_when_2dclk : 1; + u32 : 19; +} __attribute__((packed)); + +union eng_cntl_u { + u32 val : 32; + struct eng_cntl_t f; +} __attribute__((packed)); + +struct dp_cntl_t { + u32 dst_x_dir : 1; + u32 dst_y_dir : 1; + u32 src_x_dir : 1; + u32 src_y_dir : 1; + u32 dst_major_x : 1; + u32 src_major_x : 1; + u32 : 26; +} __attribute__((packed)); + +union dp_cntl_u { + u32 val : 32; + struct dp_cntl_t f; +} __attribute__((packed)); + +struct dp_cntl_dst_dir_t { + u32 : 15; + u32 dst_y_dir : 1; + u32 : 15; + u32 dst_x_dir : 1; +} __attribute__((packed)); + +union dp_cntl_dst_dir_u { + u32 val : 32; + struct dp_cntl_dst_dir_t f; +} __attribute__((packed)); + #endif -- cgit v1.2.2 From 6ca017658b1f902c9bba2cc1017e301581f7728d Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:49 -0800 Subject: [PATCH] backlight: Backlight Class Improvements Backlight class attributes are currently easy to implement incorrectly. Moving certain handling into the backlight core prevents this whilst at the same time makes the drivers simpler and consistent. The following changes are included: The brightness attribute only sets and reads the brightness variable in the backlight_properties structure. The power attribute only sets and reads the power variable in the backlight_properties structure. Any framebuffer blanking events change a variable fb_blank in the backlight_properties structure. The backlight driver has only two functions to implement. One function is called when any of the above properties change (to update the backlight brightness), the second is called to return the current backlight brightness value. A new attribute "actual_brightness" is added to return this brightness as determined by the driver having combined all the above factors (and any driver/device specific factors). Additionally, the backlight core takes care of checking the maximum brightness is not exceeded and of turning off the backlight before device removal. The corgi backlight driver is updated to reflect these changes. Signed-off-by: Richard Purdie Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/backlight.c | 84 ++++++++++++++++++++----------- drivers/video/backlight/corgi_bl.c | 99 ++++++++++++++----------------------- 2 files changed, 92 insertions(+), 91 deletions(-) (limited to 'drivers') diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 151fda8dde..334b1db1bd 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -16,14 +16,12 @@ static ssize_t backlight_show_power(struct class_device *cdev, char *buf) { - int rc; + int rc = -ENXIO; struct backlight_device *bd = to_backlight_device(cdev); down(&bd->sem); - if (likely(bd->props && bd->props->get_power)) - rc = sprintf(buf, "%d\n", bd->props->get_power(bd)); - else - rc = -ENXIO; + if (likely(bd->props)) + rc = sprintf(buf, "%d\n", bd->props->power); up(&bd->sem); return rc; @@ -31,7 +29,7 @@ static ssize_t backlight_show_power(struct class_device *cdev, char *buf) static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, size_t count) { - int rc, power; + int rc = -ENXIO, power; char *endp; struct backlight_device *bd = to_backlight_device(cdev); @@ -40,12 +38,13 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, return -EINVAL; down(&bd->sem); - if (likely(bd->props && bd->props->set_power)) { + if (likely(bd->props)) { pr_debug("backlight: set power to %d\n", power); - bd->props->set_power(bd, power); + bd->props->power = power; + if (likely(bd->props->update_status)) + bd->props->update_status(bd); rc = count; - } else - rc = -ENXIO; + } up(&bd->sem); return rc; @@ -53,14 +52,12 @@ static ssize_t backlight_store_power(struct class_device *cdev, const char *buf, static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf) { - int rc; + int rc = -ENXIO; struct backlight_device *bd = to_backlight_device(cdev); down(&bd->sem); - if (likely(bd->props && bd->props->get_brightness)) - rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd)); - else - rc = -ENXIO; + if (likely(bd->props)) + rc = sprintf(buf, "%d\n", bd->props->brightness); up(&bd->sem); return rc; @@ -68,7 +65,7 @@ static ssize_t backlight_show_brightness(struct class_device *cdev, char *buf) static ssize_t backlight_store_brightness(struct class_device *cdev, const char *buf, size_t count) { - int rc, brightness; + int rc = -ENXIO, brightness; char *endp; struct backlight_device *bd = to_backlight_device(cdev); @@ -77,12 +74,18 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char return -EINVAL; down(&bd->sem); - if (likely(bd->props && bd->props->set_brightness)) { - pr_debug("backlight: set brightness to %d\n", brightness); - bd->props->set_brightness(bd, brightness); - rc = count; - } else - rc = -ENXIO; + if (likely(bd->props)) { + if (brightness > bd->props->max_brightness) + rc = -EINVAL; + else { + pr_debug("backlight: set brightness to %d\n", + brightness); + bd->props->brightness = brightness; + if (likely(bd->props->update_status)) + bd->props->update_status(bd); + rc = count; + } + } up(&bd->sem); return rc; @@ -90,14 +93,26 @@ static ssize_t backlight_store_brightness(struct class_device *cdev, const char static ssize_t backlight_show_max_brightness(struct class_device *cdev, char *buf) { - int rc; + int rc = -ENXIO; struct backlight_device *bd = to_backlight_device(cdev); down(&bd->sem); if (likely(bd->props)) rc = sprintf(buf, "%d\n", bd->props->max_brightness); - else - rc = -ENXIO; + up(&bd->sem); + + return rc; +} + +static ssize_t backlight_show_actual_brightness(struct class_device *cdev, + char *buf) +{ + int rc = -ENXIO; + struct backlight_device *bd = to_backlight_device(cdev); + + down(&bd->sem); + if (likely(bd->props && bd->props->get_brightness)) + rc = sprintf(buf, "%d\n", bd->props->get_brightness(bd)); up(&bd->sem); return rc; @@ -123,7 +138,10 @@ static struct class backlight_class = { static struct class_device_attribute bl_class_device_attributes[] = { DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power), - DECLARE_ATTR(brightness, 0644, backlight_show_brightness, backlight_store_brightness), + DECLARE_ATTR(brightness, 0644, backlight_show_brightness, + backlight_store_brightness), + DECLARE_ATTR(actual_brightness, 0444, backlight_show_actual_brightness, + NULL), DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), }; @@ -144,8 +162,12 @@ static int fb_notifier_callback(struct notifier_block *self, bd = container_of(self, struct backlight_device, fb_notif); down(&bd->sem); if (bd->props) - if (!bd->props->check_fb || bd->props->check_fb(evdata->info)) - bd->props->set_power(bd, *(int *)evdata->data); + if (!bd->props->check_fb || + bd->props->check_fb(evdata->info)) { + bd->props->fb_blank = *(int *)evdata->data; + if (likely(bd->props && bd->props->update_status)) + bd->props->update_status(bd); + } up(&bd->sem); return 0; } @@ -231,6 +253,12 @@ void backlight_device_unregister(struct backlight_device *bd) &bl_class_device_attributes[i]); down(&bd->sem); + if (likely(bd->props && bd->props->update_status)) { + bd->props->brightness = 0; + bd->props->power = 0; + bd->props->update_status(bd); + } + bd->props = NULL; up(&bd->sem); diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index d0aaf450e8..f86213b4a8 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -25,24 +25,30 @@ #define CORGI_DEFAULT_INTENSITY 0x1f #define CORGI_LIMIT_MASK 0x0b -static int corgibl_powermode = FB_BLANK_UNBLANK; -static int current_intensity = 0; -static int corgibl_limit = 0; +static int corgibl_intensity; static void (*corgibl_mach_set_intensity)(int intensity); static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; static struct backlight_properties corgibl_data; +static struct backlight_device *corgi_backlight_device; + +static unsigned long corgibl_flags; +#define CORGIBL_SUSPENDED 0x01 +#define CORGIBL_BATTLOW 0x02 -static void corgibl_send_intensity(int intensity) +static int corgibl_send_intensity(struct backlight_device *bd) { unsigned long flags; void (*corgi_kick_batt)(void); + int intensity = bd->props->brightness; - if (corgibl_powermode != FB_BLANK_UNBLANK) { + if (bd->props->power != FB_BLANK_UNBLANK) + intensity = 0; + if (bd->props->fb_blank != FB_BLANK_UNBLANK) intensity = 0; - } else { - if (corgibl_limit) - intensity &= CORGI_LIMIT_MASK; - } + if (corgibl_flags & CORGIBL_SUSPENDED) + intensity = 0; + if (corgibl_flags & CORGIBL_BATTLOW) + intensity &= CORGI_LIMIT_MASK; spin_lock_irqsave(&bl_lock, flags); @@ -50,45 +56,29 @@ static void corgibl_send_intensity(int intensity) spin_unlock_irqrestore(&bl_lock, flags); + corgibl_intensity = intensity; + corgi_kick_batt = symbol_get(sharpsl_battery_kick); if (corgi_kick_batt) { corgi_kick_batt(); symbol_put(sharpsl_battery_kick); } -} -static void corgibl_blank(int blank) -{ - switch(blank) { - - case FB_BLANK_NORMAL: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - if (corgibl_powermode == FB_BLANK_UNBLANK) { - corgibl_send_intensity(0); - corgibl_powermode = blank; - } - break; - case FB_BLANK_UNBLANK: - if (corgibl_powermode != FB_BLANK_UNBLANK) { - corgibl_powermode = blank; - corgibl_send_intensity(current_intensity); - } - break; - } + return 0; } #ifdef CONFIG_PM static int corgibl_suspend(struct platform_device *dev, pm_message_t state) { - corgibl_blank(FB_BLANK_POWERDOWN); + corgibl_flags |= CORGIBL_SUSPENDED; + corgibl_send_intensity(corgi_backlight_device); return 0; } static int corgibl_resume(struct platform_device *dev) { - corgibl_blank(FB_BLANK_UNBLANK); + corgibl_flags &= ~CORGIBL_SUSPENDED; + corgibl_send_intensity(corgi_backlight_device); return 0; } #else @@ -96,54 +86,38 @@ static int corgibl_resume(struct platform_device *dev) #define corgibl_resume NULL #endif - -static int corgibl_set_power(struct backlight_device *bd, int state) -{ - corgibl_blank(state); - return 0; -} - -static int corgibl_get_power(struct backlight_device *bd) +static int corgibl_get_intensity(struct backlight_device *bd) { - return corgibl_powermode; + return corgibl_intensity; } -static int corgibl_set_intensity(struct backlight_device *bd, int intensity) +static int corgibl_set_intensity(struct backlight_device *bd) { - if (intensity > corgibl_data.max_brightness) - intensity = corgibl_data.max_brightness; - corgibl_send_intensity(intensity); - current_intensity=intensity; + corgibl_send_intensity(corgi_backlight_device); return 0; } -static int corgibl_get_intensity(struct backlight_device *bd) -{ - return current_intensity; -} - /* * Called when the battery is low to limit the backlight intensity. * If limit==0 clear any limit, otherwise limit the intensity */ void corgibl_limit_intensity(int limit) { - corgibl_limit = (limit ? 1 : 0); - corgibl_send_intensity(current_intensity); + if (limit) + corgibl_flags |= CORGIBL_BATTLOW; + else + corgibl_flags &= ~CORGIBL_BATTLOW; + corgibl_send_intensity(corgi_backlight_device); } EXPORT_SYMBOL(corgibl_limit_intensity); static struct backlight_properties corgibl_data = { - .owner = THIS_MODULE, - .get_power = corgibl_get_power, - .set_power = corgibl_set_power, + .owner = THIS_MODULE, .get_brightness = corgibl_get_intensity, - .set_brightness = corgibl_set_intensity, + .update_status = corgibl_set_intensity, }; -static struct backlight_device *corgi_backlight_device; - static int __init corgibl_probe(struct platform_device *pdev) { struct corgibl_machinfo *machinfo = pdev->dev.platform_data; @@ -156,8 +130,9 @@ static int __init corgibl_probe(struct platform_device *pdev) if (IS_ERR (corgi_backlight_device)) return PTR_ERR (corgi_backlight_device); - corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY); - corgibl_limit_intensity(0); + corgibl_data.power = FB_BLANK_UNBLANK; + corgibl_data.brightness = CORGI_DEFAULT_INTENSITY; + corgibl_send_intensity(corgi_backlight_device); printk("Corgi Backlight Driver Initialized.\n"); return 0; @@ -167,8 +142,6 @@ static int corgibl_remove(struct platform_device *dev) { backlight_device_unregister(corgi_backlight_device); - corgibl_set_intensity(NULL, 0); - printk("Corgi Backlight Driver Unloaded\n"); return 0; } -- cgit v1.2.2 From 5f27a27bd77fcfd4b90ed33668940bc3cf72768b Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:50 -0800 Subject: [PATCH] backlight: HP Jornada 680 Backlight driver updates/fixes Updates to the HP Jornada 680 Backlight driver: - Correct the suspend/resume functions so the driver compiles (SUSPEND_POWER_DOWN/RESUME_POWER_ON no longer exist). - Convert the driver to match the recent platform device changes. - Replace the unsafe static struct platform_device with dynamic allocation. - Convert the driver to the new backlight code. This has not been tested on a device due to lack of hardware but wouldn't compile beforehand. Signed-off-by: Richard Purdie Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/hp680_bl.c | 139 ++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 80 deletions(-) (limited to 'drivers') diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index 95da4c9ed1..a71e984c93 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -25,66 +25,58 @@ #define HP680_MAX_INTENSITY 255 #define HP680_DEFAULT_INTENSITY 10 -static int hp680bl_powermode = FB_BLANK_UNBLANK; +static int hp680bl_suspended; static int current_intensity = 0; static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; +static struct backlight_device *hp680_backlight_device; -static void hp680bl_send_intensity(int intensity) +static void hp680bl_send_intensity(struct backlight_device *bd) { unsigned long flags; + u16 v; + int intensity = bd->props->brightness; - if (hp680bl_powermode != FB_BLANK_UNBLANK) + if (bd->props->power != FB_BLANK_UNBLANK) + intensity = 0; + if (bd->props->fb_blank != FB_BLANK_UNBLANK) + intensity = 0; + if (hp680bl_suspended) intensity = 0; spin_lock_irqsave(&bl_lock, flags); - sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + if (intensity && current_intensity == 0) { + sh_dac_enable(DAC_LCD_BRIGHTNESS); + v = inw(HD64461_GPBDR); + v &= ~HD64461_GPBDR_LCDOFF; + outw(v, HD64461_GPBDR); + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + } else if (intensity == 0 && current_intensity != 0) { + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + sh_dac_disable(DAC_LCD_BRIGHTNESS); + v = inw(HD64461_GPBDR); + v |= HD64461_GPBDR_LCDOFF; + outw(v, HD64461_GPBDR); + } else if (intensity) { + sh_dac_output(255-(u8)intensity, DAC_LCD_BRIGHTNESS); + } spin_unlock_irqrestore(&bl_lock, flags); -} -static void hp680bl_blank(int blank) -{ - u16 v; - - switch(blank) { - - case FB_BLANK_NORMAL: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - if (hp680bl_powermode == FB_BLANK_UNBLANK) { - hp680bl_send_intensity(0); - hp680bl_powermode = blank; - sh_dac_disable(DAC_LCD_BRIGHTNESS); - v = inw(HD64461_GPBDR); - v |= HD64461_GPBDR_LCDOFF; - outw(v, HD64461_GPBDR); - } - break; - case FB_BLANK_UNBLANK: - if (hp680bl_powermode != FB_BLANK_UNBLANK) { - sh_dac_enable(DAC_LCD_BRIGHTNESS); - v = inw(HD64461_GPBDR); - v &= ~HD64461_GPBDR_LCDOFF; - outw(v, HD64461_GPBDR); - hp680bl_powermode = blank; - hp680bl_send_intensity(current_intensity); - } - break; - } + current_intensity = intensity; } + #ifdef CONFIG_PM -static int hp680bl_suspend(struct device *dev, pm_message_t state, u32 level) +static int hp680bl_suspend(struct platform_device *dev, pm_message_t state) { - if (level == SUSPEND_POWER_DOWN) - hp680bl_blank(FB_BLANK_POWERDOWN); + hp680bl_suspended = 1; + hp680bl_send_intensity(hp680_backlight_device); return 0; } -static int hp680bl_resume(struct device *dev, u32 level) +static int hp680bl_resume(struct platform_device *dev) { - if (level == RESUME_POWER_ON) - hp680bl_blank(FB_BLANK_UNBLANK); + hp680bl_suspended = 0; + hp680bl_send_intensity(hp680_backlight_device); return 0; } #else @@ -92,24 +84,9 @@ static int hp680bl_resume(struct device *dev, u32 level) #define hp680bl_resume NULL #endif - -static int hp680bl_set_power(struct backlight_device *bd, int state) +static int hp680bl_set_intensity(struct backlight_device *bd) { - hp680bl_blank(state); - return 0; -} - -static int hp680bl_get_power(struct backlight_device *bd) -{ - return hp680bl_powermode; -} - -static int hp680bl_set_intensity(struct backlight_device *bd, int intensity) -{ - if (intensity > HP680_MAX_INTENSITY) - intensity = HP680_MAX_INTENSITY; - hp680bl_send_intensity(intensity); - current_intensity = intensity; + hp680bl_send_intensity(bd); return 0; } @@ -120,65 +97,67 @@ static int hp680bl_get_intensity(struct backlight_device *bd) static struct backlight_properties hp680bl_data = { .owner = THIS_MODULE, - .get_power = hp680bl_get_power, - .set_power = hp680bl_set_power, .max_brightness = HP680_MAX_INTENSITY, .get_brightness = hp680bl_get_intensity, - .set_brightness = hp680bl_set_intensity, + .update_status = hp680bl_set_intensity, }; -static struct backlight_device *hp680_backlight_device; - -static int __init hp680bl_probe(struct device *dev) +static int __init hp680bl_probe(struct platform_device *dev) { hp680_backlight_device = backlight_device_register ("hp680-bl", NULL, &hp680bl_data); if (IS_ERR (hp680_backlight_device)) return PTR_ERR (hp680_backlight_device); - hp680bl_set_intensity(NULL, HP680_DEFAULT_INTENSITY); + hp680_backlight_device->props->brightness = HP680_DEFAULT_INTENSITY; + hp680bl_send_intensity(hp680_backlight_device); return 0; } -static int hp680bl_remove(struct device *dev) +static int hp680bl_remove(struct platform_device *dev) { backlight_device_unregister(hp680_backlight_device); return 0; } -static struct device_driver hp680bl_driver = { - .name = "hp680-bl", - .bus = &platform_bus_type, +static struct platform_driver hp680bl_driver = { .probe = hp680bl_probe, .remove = hp680bl_remove, .suspend = hp680bl_suspend, .resume = hp680bl_resume, + .driver = { + .name = "hp680-bl", + }, }; -static struct platform_device hp680bl_device = { - .name = "hp680-bl", - .id = -1, -}; +static struct platform_device *hp680bl_device; static int __init hp680bl_init(void) { int ret; - ret=driver_register(&hp680bl_driver); + ret = platform_driver_register(&hp680bl_driver); if (!ret) { - ret = platform_device_register(&hp680bl_device); - if (ret) - driver_unregister(&hp680bl_driver); + hp680bl_device = platform_device_alloc("hp680-bl", -1); + if (!hp680bl_device) + return -ENOMEM; + + ret = platform_device_add(hp680bl_device); + + if (ret) { + platform_device_put(hp680bl_device); + platform_driver_unregister(&hp680bl_driver); + } } return ret; } static void __exit hp680bl_exit(void) { - platform_device_unregister(&hp680bl_device); - driver_unregister(&hp680bl_driver); + platform_device_unregister(hp680bl_device); + platform_driver_unregister(&hp680bl_driver); } module_init(hp680bl_init); -- cgit v1.2.2 From 2c0f5fb08e8ad59f396b1bda41ccd93cbb00a09f Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:51 -0800 Subject: [PATCH] backlight: corgi_bl: Generalise to support other Sharp SL hardware Generalise the Corgi backlight driver by moving the default intensity and limit mask settings into the platform specific data structure. This enables the driver to support other Zaurus hardware, specifically the SL-6000x (Tosa) model. Also change the spinlock to a mutex (the spinlock is overkill). Signed-off-by: Richard Purdie Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/Kconfig | 4 ++-- drivers/video/backlight/corgi_bl.c | 31 +++++++++++++------------------ 2 files changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 9d996f2c10..b895eaaa73 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -43,11 +43,11 @@ config LCD_DEVICE default y config BACKLIGHT_CORGI - tristate "Sharp Corgi Backlight Driver (SL-C7xx Series)" + tristate "Sharp Corgi Backlight Driver (SL Series)" depends on BACKLIGHT_DEVICE && PXA_SHARPSL default y help - If you have a Sharp Zaurus SL-C7xx, say y to enable the + If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the backlight driver. config BACKLIGHT_HP680 diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index f86213b4a8..2ebbfd9514 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -1,7 +1,7 @@ /* - * Backlight Driver for Sharp Corgi + * Backlight Driver for Sharp Zaurus Handhelds (various models) * - * Copyright (c) 2004-2005 Richard Purdie + * Copyright (c) 2004-2006 Richard Purdie * * Based on Sharp's 2.4 Backlight Driver * @@ -15,21 +15,17 @@ #include #include #include -#include +#include #include #include - #include #include -#define CORGI_DEFAULT_INTENSITY 0x1f -#define CORGI_LIMIT_MASK 0x0b - static int corgibl_intensity; -static void (*corgibl_mach_set_intensity)(int intensity); -static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_MUTEX(bl_mutex); static struct backlight_properties corgibl_data; static struct backlight_device *corgi_backlight_device; +static struct corgibl_machinfo *bl_machinfo; static unsigned long corgibl_flags; #define CORGIBL_SUSPENDED 0x01 @@ -37,7 +33,6 @@ static unsigned long corgibl_flags; static int corgibl_send_intensity(struct backlight_device *bd) { - unsigned long flags; void (*corgi_kick_batt)(void); int intensity = bd->props->brightness; @@ -48,13 +43,11 @@ static int corgibl_send_intensity(struct backlight_device *bd) if (corgibl_flags & CORGIBL_SUSPENDED) intensity = 0; if (corgibl_flags & CORGIBL_BATTLOW) - intensity &= CORGI_LIMIT_MASK; - - spin_lock_irqsave(&bl_lock, flags); - - corgibl_mach_set_intensity(intensity); + intensity &= bl_machinfo->limit_mask; - spin_unlock_irqrestore(&bl_lock, flags); + mutex_lock(&bl_mutex); + bl_machinfo->set_bl_intensity(intensity); + mutex_unlock(&bl_mutex); corgibl_intensity = intensity; @@ -122,8 +115,10 @@ static int __init corgibl_probe(struct platform_device *pdev) { struct corgibl_machinfo *machinfo = pdev->dev.platform_data; + bl_machinfo = machinfo; corgibl_data.max_brightness = machinfo->max_intensity; - corgibl_mach_set_intensity = machinfo->set_bl_intensity; + if (!machinfo->limit_mask) + machinfo->limit_mask = -1; corgi_backlight_device = backlight_device_register ("corgi-bl", NULL, &corgibl_data); @@ -131,7 +126,7 @@ static int __init corgibl_probe(struct platform_device *pdev) return PTR_ERR (corgi_backlight_device); corgibl_data.power = FB_BLANK_UNBLANK; - corgibl_data.brightness = CORGI_DEFAULT_INTENSITY; + corgibl_data.brightness = machinfo->default_intensity; corgibl_send_intensity(corgi_backlight_device); printk("Corgi Backlight Driver Initialized.\n"); -- cgit v1.2.2 From 2cbbb3b59c3ccdc55ad0c924fb49e09a962bb517 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Fri, 31 Mar 2006 02:31:53 -0800 Subject: [PATCH] pxafb: Minor driver fixes Fixes for the pxafb driver: * Return -EINVAL for resolutions that are too large as per framebuffer driver policy. * Increase the error timeout for disabling the LCD controller. The current timeout is sometimes too short on the Sharp Zaurus Cxx00 hardware and an extra delay in an error path shouldn't pose any problems. * Fix a dev reference which causes a compile error when DEBUG is defined. Signed-off-by: Richard Purdie Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/pxafb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 53ad61f103..809fc5eefc 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -232,9 +232,9 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) if (var->yres < MIN_YRES) var->yres = MIN_YRES; if (var->xres > fbi->max_xres) - var->xres = fbi->max_xres; + return -EINVAL; if (var->yres > fbi->max_yres) - var->yres = fbi->max_yres; + return -EINVAL; var->xres_virtual = max(var->xres_virtual, var->xres); var->yres_virtual = @@ -781,7 +781,7 @@ static void pxafb_disable_controller(struct pxafb_info *fbi) LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */ LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */ - schedule_timeout(20 * HZ / 1000); + schedule_timeout(200 * HZ / 1000); remove_wait_queue(&fbi->ctrlr_wait, &wait); /* disable LCD controller clock */ @@ -1274,7 +1274,7 @@ int __init pxafb_probe(struct platform_device *dev) struct pxafb_mach_info *inf; int ret; - dev_dbg(dev, "pxafb_probe\n"); + dev_dbg(&dev->dev, "pxafb_probe\n"); inf = dev->dev.platform_data; ret = -ENOMEM; -- cgit v1.2.2 From a536093a2f07007aa572e922752b7491b9ea8ff2 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Fri, 31 Mar 2006 02:31:54 -0800 Subject: [PATCH] fbcon: Fix big-endian bogosity in slow_imageblit() The monochrome->color expansion routine that handles bitmaps which have (widths % 8) != 0 (slow_imageblit) produces corrupt characters in big-endian. This is caused by a bogus bit test in slow_imageblit(). Fix. This patch may deserve to go to the stable tree. The code has already been well tested in little-endian machines. It's only in big-endian where there is uncertainty and Herbert confirmed that this is the correct way to go. It should not introduce regressions. Signed-off-by: Antonino Daplas Acked-by: Herbert Poetzl Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/cfbimgblt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c index 910e2338a2..8ba6152db2 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -169,7 +169,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info * while (j--) { l--; - color = (*s & 1 << (FB_BIT_NR(l))) ? fgcolor : bgcolor; + color = (*s & (1 << l)) ? fgcolor : bgcolor; val |= FB_SHIFT_HIGH(color, shift); /* Did the bitshift spill bits to the next long? */ -- cgit v1.2.2 From 39451a73a2d190763ba8a98f486cf23d63d22582 Mon Sep 17 00:00:00 2001 From: Michael Hanselmann Date: Fri, 31 Mar 2006 02:31:55 -0800 Subject: [PATCH] fbdev: Remove old radeon driver This patch removes the old radeon driver which has been replaced by a newer one. Signed-off-by: Michael Hanselmann Acked-by: Benjamin Herrenschmidt Signed-off-by: Adrian Bunk Acked-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/Kconfig | 12 - drivers/video/Makefile | 1 - drivers/video/radeonfb.c | 3167 ---------------------------------------------- 3 files changed, 3180 deletions(-) delete mode 100644 drivers/video/radeonfb.c (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 22e9d696fd..f87c0171f4 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -904,18 +904,6 @@ config FB_MATROX_MULTIHEAD There is no need for enabling 'Matrox multihead support' if you have only one Matrox card in the box. -config FB_RADEON_OLD - tristate "ATI Radeon display support (Old driver)" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MACMODES if PPC - help - Choose this option if you want to use an ATI Radeon graphics card as - a framebuffer device. There are both PCI and AGP versions. You - don't need to choose this to run the Radeon in plain VGA mode. - config FB_RADEON tristate "ATI Radeon display support" depends on FB && PCI diff --git a/drivers/video/Makefile b/drivers/video/Makefile index cb90218515..23de3b2c78 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -39,7 +39,6 @@ obj-$(CONFIG_FB_KYRO) += kyro/ obj-$(CONFIG_FB_SAVAGE) += savage/ obj-$(CONFIG_FB_GEODE) += geode/ obj-$(CONFIG_FB_I810) += vgastate.o -obj-$(CONFIG_FB_RADEON_OLD) += radeonfb.o obj-$(CONFIG_FB_NEOMAGIC) += neofb.o vgastate.o obj-$(CONFIG_FB_VIRGE) += virgefb.o obj-$(CONFIG_FB_3DFX) += tdfxfb.o diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c deleted file mode 100644 index afb6c2ead5..0000000000 --- a/drivers/video/radeonfb.c +++ /dev/null @@ -1,3167 +0,0 @@ -/* - * drivers/video/radeonfb.c - * framebuffer driver for ATI Radeon chipset video boards - * - * Copyright 2000 Ani Joshi - * - * - * ChangeLog: - * 2000-08-03 initial version 0.0.1 - * 2000-09-10 more bug fixes, public release 0.0.5 - * 2001-02-19 mode bug fixes, 0.0.7 - * 2001-07-05 fixed scrolling issues, engine initialization, - * and minor mode tweaking, 0.0.9 - * 2001-09-07 Radeon VE support, Nick Kurshev - * blanking, pan_display, and cmap fixes, 0.1.0 - * 2001-10-10 Radeon 7500 and 8500 support, and experimental - * flat panel support, 0.1.1 - * 2001-11-17 Radeon M6 (ppc) support, Daniel Berlin, 0.1.2 - * 2001-11-18 DFP fixes, Kevin Hendricks, 0.1.3 - * 2001-11-29 more cmap, backlight fixes, Benjamin Herrenschmidt - * 2002-01-18 DFP panel detection via BIOS, Michael Clark, 0.1.4 - * 2002-06-02 console switching, mode set fixes, accel fixes - * 2002-06-03 MTRR support, Peter Horton, 0.1.5 - * 2002-09-21 rv250, r300, m9 initial support, - * added mirror option, 0.1.6 - * - * Special thanks to ATI DevRel team for their hardware donations. - * - */ - - -#define RADEON_VERSION "0.1.6" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#if defined(__powerpc__) -#include -#include -#include "macmodes.h" - -#ifdef CONFIG_NVRAM -#include -#endif - -#ifdef CONFIG_PMAC_BACKLIGHT -#include -#endif - -#ifdef CONFIG_BOOTX_TEXT -#include -#endif - -#ifdef CONFIG_ADB_PMU -#include -#include -#endif - -#endif /* __powerpc__ */ - -#ifdef CONFIG_MTRR -#include -#endif - -#include