diff options
Diffstat (limited to 'drivers')
119 files changed, 2849 insertions, 1228 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 7bcc1d8bc967..34f80fa6fed1 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -406,6 +406,7 @@ static int nbd_do_it(struct nbd_device *lo) ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr); if (ret) { printk(KERN_ERR "nbd: sysfs_create_file failed!"); + lo->pid = 0; return ret; } @@ -413,6 +414,7 @@ static int nbd_do_it(struct nbd_device *lo) nbd_end_request(req); sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr); + lo->pid = 0; return 0; } @@ -648,6 +650,8 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode, set_capacity(lo->disk, lo->bytesize >> 9); return 0; case NBD_DO_IT: + if (lo->pid) + return -EBUSY; if (!lo->file) return -EINVAL; thread = kthread_create(nbd_thread, lo, lo->disk->disk_name); diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 29e1dfafb7c6..381d686fc1a3 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -1206,6 +1206,7 @@ static struct of_device_id ace_of_match[] __devinitdata = { { .compatible = "xlnx,opb-sysace-1.00.b", }, { .compatible = "xlnx,opb-sysace-1.00.c", }, { .compatible = "xlnx,xps-sysace-1.00.a", }, + { .compatible = "xlnx,sysace", }, {}, }; MODULE_DEVICE_TABLE(of, ace_of_match); diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 977dfb1096a0..f6094ae0ef33 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c @@ -103,7 +103,7 @@ static ssize_t bsr_len_show(struct device *dev, struct device_attribute *attr, char *buf) { struct bsr_dev *bsr_dev = dev_get_drvdata(dev); - return sprintf(buf, "%lu\n", bsr_dev->bsr_len); + return sprintf(buf, "%llu\n", bsr_dev->bsr_len); } static struct device_attribute bsr_dev_attrs[] = { diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 5a8a4c28c867..09676b4e5d89 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -318,7 +318,8 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) } /* else count == 0 */ tty->driver_data = hp; - tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ + if (!hp->irq_requested) + tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ hp->tty = tty; @@ -764,13 +765,11 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, return ERR_PTR(err); } - hp = kmalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size, + hp = kzalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size, GFP_KERNEL); if (!hp) return ERR_PTR(-ENOMEM); - memset(hp, 0x00, sizeof(*hp)); - hp->vtermno = vtermno; hp->data = data; hp->ops = ops; @@ -876,8 +875,11 @@ static int hvc_init(void) goto stop_thread; } - /* FIXME: This mb() seems completely random. Remove it. */ - mb(); + /* + * Make sure tty is fully registered before allowing it to be + * found by hvc_console_device. + */ + smp_mb(); hvc_driver = drv; return 0; diff --git a/drivers/char/hvc_irq.c b/drivers/char/hvc_irq.c index d09e5688d449..2623e177e8d6 100644 --- a/drivers/char/hvc_irq.c +++ b/drivers/char/hvc_irq.c @@ -37,7 +37,7 @@ int notifier_add_irq(struct hvc_struct *hp, int irq) void notifier_del_irq(struct hvc_struct *hp, int irq) { - if (!irq) + if (!hp->irq_requested) return; free_irq(irq, hp); hp->irq_requested = 0; diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 53544e21f191..f329f459817c 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -1,6 +1,4 @@ /* - * $Id: synclink_gt.c,v 4.50 2007/07/25 19:29:25 paulkf Exp $ - * * Device driver for Microgate SyncLink GT serial adapters. * * written by Paul Fulghum for Microgate Corporation @@ -91,7 +89,6 @@ * module identification */ static char *driver_name = "SyncLink GT"; -static char *driver_version = "$Revision: 4.50 $"; static char *tty_driver_name = "synclink_gt"; static char *tty_dev_prefix = "ttySLG"; MODULE_LICENSE("GPL"); @@ -1309,7 +1306,7 @@ static int read_proc(char *page, char **start, off_t off, int count, off_t begin = 0; struct slgt_info *info; - len += sprintf(page, "synclink_gt driver:%s\n", driver_version); + len += sprintf(page, "synclink_gt driver\n"); info = slgt_device_list; while( info ) { @@ -2441,7 +2438,7 @@ static void program_hw(struct slgt_info *info) info->ri_chkcount = 0; info->dsr_chkcount = 0; - slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR); + slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR | IRQ_RI); get_signals(info); if (info->netcount || @@ -3576,7 +3573,7 @@ static void slgt_cleanup(void) struct slgt_info *info; struct slgt_info *tmp; - printk("unload %s %s\n", driver_name, driver_version); + printk(KERN_INFO "unload %s\n", driver_name); if (serial_driver) { for (info=slgt_device_list ; info != NULL ; info=info->next_device) @@ -3619,7 +3616,7 @@ static int __init slgt_init(void) { int rc; - printk("%s %s\n", driver_name, driver_version); + printk(KERN_INFO "%s\n", driver_name); serial_driver = alloc_tty_driver(MAX_DEVICES); if (!serial_driver) { @@ -3650,9 +3647,8 @@ static int __init slgt_init(void) goto error; } - printk("%s %s, tty major#%d\n", - driver_name, driver_version, - serial_driver->major); + printk(KERN_INFO "%s, tty major#%d\n", + driver_name, serial_driver->major); slgt_device_count = 0; if ((rc = pci_register_driver(&pci_driver)) < 0) { diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index d41b9f6f7903..33a9351c896d 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -473,6 +473,12 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) unsigned long flags; spin_lock_irqsave(&sysrq_key_table_lock, flags); + /* + * Raise the apparent loglevel to maximum so that the sysrq header + * is shown to provide the user with positive feedback. We do not + * simply emit this at KERN_EMERG as that would change message + * routing in the consumers of /proc/kmsg. + */ orig_log_level = console_loglevel; console_loglevel = 7; printk(KERN_INFO "SysRq : "); diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index a408c8e487ec..6f4c7d0a53bf 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -1057,7 +1057,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg) if (retval) return retval; - ld = tty_ldisc_ref(tty); + ld = tty_ldisc_ref_wait(tty); switch (arg) { case TCIFLUSH: if (ld && ld->ops->flush_buffer) diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c index 8b24d784db93..3e7f4e06386e 100644 --- a/drivers/gpio/max7301.c +++ b/drivers/gpio/max7301.c @@ -217,8 +217,10 @@ static int __devinit max7301_probe(struct spi_device *spi) int i, ret; pdata = spi->dev.platform_data; - if (!pdata || !pdata->base) - return -ENODEV; + if (!pdata || !pdata->base) { + dev_dbg(&spi->dev, "incorrect or missing platform data\n"); + return -EINVAL; + } /* * bits_per_word cannot be configured in platform data diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c index 55ae9a41897a..f7868243af89 100644 --- a/drivers/gpio/max732x.c +++ b/drivers/gpio/max732x.c @@ -267,8 +267,10 @@ static int __devinit max732x_probe(struct i2c_client *client, int ret, nr_port; pdata = client->dev.platform_data; - if (pdata == NULL) - return -ENODEV; + if (pdata == NULL) { + dev_dbg(&client->dev, "no platform data\n"); + return -EINVAL; + } chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL); if (chip == NULL) diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c index 89c1d222e9d1..f6fae0e50e65 100644 --- a/drivers/gpio/mcp23s08.c +++ b/drivers/gpio/mcp23s08.c @@ -310,8 +310,10 @@ static int mcp23s08_probe(struct spi_device *spi) unsigned base; pdata = spi->dev.platform_data; - if (!pdata || !gpio_is_valid(pdata->base)) - return -ENODEV; + if (!pdata || !gpio_is_valid(pdata->base)) { + dev_dbg(&spi->dev, "invalid or missing platform data\n"); + return -EINVAL; + } for (addr = 0; addr < 4; addr++) { if (!pdata->chip[addr].is_present) diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 37f35388a2ae..8dc0164bd51e 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c @@ -202,8 +202,10 @@ static int __devinit pca953x_probe(struct i2c_client *client, int ret; pdata = client->dev.platform_data; - if (pdata == NULL) - return -ENODEV; + if (pdata == NULL) { + dev_dbg(&client->dev, "no platform data\n"); + return -EINVAL; + } chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); if (chip == NULL) diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c index 4bc2070dd4a1..9525724be731 100644 --- a/drivers/gpio/pcf857x.c +++ b/drivers/gpio/pcf857x.c @@ -188,8 +188,10 @@ static int pcf857x_probe(struct i2c_client *client, int status; pdata = client->dev.platform_data; - if (!pdata) - return -ENODEV; + if (!pdata) { + dev_dbg(&client->dev, "no platform data\n"); + return -EINVAL; + } /* Allocate, initialize, and register this gpio_chip. */ gpio = kzalloc(sizeof *gpio, GFP_KERNEL); @@ -248,8 +250,10 @@ static int pcf857x_probe(struct i2c_client *client, else status = i2c_read_le16(client); - } else - status = -ENODEV; + } else { + dev_dbg(&client->dev, "unsupported number of gpios\n"); + status = -EINVAL; + } if (status < 0) goto fail; diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index d8a982b71296..964c5eb1fada 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -36,7 +36,7 @@ /* * Detailed mode info for 800x600@60Hz */ -static struct drm_display_mode std_mode[] = { +static struct drm_display_mode std_modes[] = { { DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, @@ -60,15 +60,18 @@ static struct drm_display_mode std_mode[] = { * changes have occurred. * * FIXME: take into account monitor limits + * + * RETURNS: + * Number of modes found on @connector. */ -void drm_helper_probe_single_connector_modes(struct drm_connector *connector, - uint32_t maxX, uint32_t maxY) +int drm_helper_probe_single_connector_modes(struct drm_connector *connector, + uint32_t maxX, uint32_t maxY) { struct drm_device *dev = connector->dev; struct drm_display_mode *mode, *t; struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; - int ret; + int count = 0; DRM_DEBUG("%s\n", drm_get_connector_name(connector)); /* set all modes to the unverified state */ @@ -81,14 +84,14 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector, DRM_DEBUG("%s is disconnected\n", drm_get_connector_name(connector)); /* TODO set EDID to NULL */ - return; + return 0; } - ret = (*connector_funcs->get_modes)(connector); + count = (*connector_funcs->get_modes)(connector); + if (!count) + return 0; - if (ret) { - drm_mode_connector_list_update(connector); - } + drm_mode_connector_list_update(connector); if (maxX && maxY) drm_mode_validate_size(dev, &connector->modes, maxX, @@ -102,25 +105,8 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector, drm_mode_prune_invalid(dev, &connector->modes, true); - if (list_empty(&connector->modes)) { - struct drm_display_mode *stdmode; - - DRM_DEBUG("No valid modes on %s\n", - drm_get_connector_name(connector)); - - /* Should we do this here ??? - * When no valid EDID modes are available we end up - * here and bailed in the past, now we add a standard - * 640x480@60Hz mode and carry on. - */ - stdmode = drm_mode_duplicate(dev, &std_mode[0]); - drm_mode_probed_add(connector, stdmode); - drm_mode_list_concat(&connector->probed_modes, - &connector->modes); - - DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n", - drm_get_connector_name(connector)); - } + if (list_empty(&connector->modes)) + return 0; drm_mode_sort(&connector->modes); @@ -131,20 +117,58 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector, drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); drm_mode_debug_printmodeline(mode); } + + return count; } EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); -void drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, +int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, uint32_t maxY) { struct drm_connector *connector; + int count = 0; list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - drm_helper_probe_single_connector_modes(connector, maxX, maxY); + count += drm_helper_probe_single_connector_modes(connector, + maxX, maxY); } + + return count; } EXPORT_SYMBOL(drm_helper_probe_connector_modes); +static void drm_helper_add_std_modes(struct drm_device *dev, + struct drm_connector *connector) +{ + struct drm_display_mode *mode, *t; + int i; + + for (i = 0; i < ARRAY_SIZE(std_modes); i++) { + struct drm_display_mode *stdmode; + + /* + * When no valid EDID modes are available we end up + * here and bailed in the past, now we add some standard + * modes and move on. + */ + stdmode = drm_mode_duplicate(dev, &std_modes[i]); + drm_mode_probed_add(connector, stdmode); + drm_mode_list_concat(&connector->probed_modes, + &connector->modes); + + DRM_DEBUG("Adding mode %s to %s\n", stdmode->name, + drm_get_connector_name(connector)); + } + drm_mode_sort(&connector->modes); + + DRM_DEBUG("Added std modes on %s\n", drm_get_connector_name(connector)); + list_for_each_entry_safe(mode, t, &connector->modes, head) { + mode->vrefresh = drm_mode_vrefresh(mode); + + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); + drm_mode_debug_printmodeline(mode); + } +} /** * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config @@ -237,6 +261,8 @@ static void drm_enable_connectors(struct drm_device *dev, bool *enabled) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { enabled[i] = drm_connector_enabled(connector, true); + DRM_DEBUG("connector %d enabled? %s\n", connector->base.id, + enabled[i] ? "yes" : "no"); any_enabled |= enabled[i]; i++; } @@ -265,11 +291,17 @@ static bool drm_target_preferred(struct drm_device *dev, continue; } + DRM_DEBUG("looking for preferred mode on connector %d\n", + connector->base.id); + modes[i] = drm_has_preferred_mode(connector, width, height); - if (!modes[i]) { + /* No preferred modes, pick one off the list */ + if (!modes[i] && !list_empty(&connector->modes)) { list_for_each_entry(modes[i], &connector->modes, head) break; } + DRM_DEBUG("found mode %s\n", modes[i] ? modes[i]->name : + "none"); i++; } return true; @@ -369,6 +401,8 @@ static void drm_setup_crtcs(struct drm_device *dev) int width, height; int i, ret; + DRM_DEBUG("\n"); + width = dev->mode_config.max_width; height = dev->mode_config.max_height; @@ -390,6 +424,8 @@ static void drm_setup_crtcs(struct drm_device *dev) if (!ret) DRM_ERROR("Unable to find initial modes\n"); + DRM_DEBUG("picking CRTCs for %dx%d config\n", width, height); + drm_pick_crtcs(dev, crtcs, modes, 0, width, height); i = 0; @@ -403,6 +439,8 @@ static void drm_setup_crtcs(struct drm_device *dev) } if (mode && crtc) { + DRM_DEBUG("desired mode %s set on crtc %d\n", + mode->name, crtc->base.id); crtc->desired_mode = mode; connector->encoder->crtc = crtc; } else @@ -442,6 +480,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, int saved_x, saved_y; struct drm_encoder *encoder; bool ret = true; + bool depth_changed, bpp_changed; adjusted_mode = drm_mode_duplicate(dev, mode); @@ -450,6 +489,15 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (!crtc->enabled) return true; + if (old_fb && crtc->fb) { + depth_changed = (old_fb->depth != crtc->fb->depth); + bpp_changed = (old_fb->bits_per_pixel != + crtc->fb->bits_per_pixel); + } else { + depth_changed = true; + bpp_changed = true; + } + saved_mode = crtc->mode; saved_x = crtc->x; saved_y = crtc->y; @@ -462,7 +510,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, crtc->y = y; if (drm_mode_equal(&saved_mode, &crtc->mode)) { - if (saved_x != crtc->x || saved_y != crtc->y) { + if (saved_x != crtc->x || saved_y != crtc->y || + depth_changed || bpp_changed) { crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, old_fb); goto done; @@ -568,8 +617,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) struct drm_encoder **save_encoders, *new_encoder; struct drm_framebuffer *old_fb; bool save_enabled; - bool changed = false; - bool flip_or_move = false; + bool mode_changed = false; + bool fb_changed = false; struct drm_connector *connector; int count = 0, ro, fail = 0; struct drm_crtc_helper_funcs *crtc_funcs; @@ -597,7 +646,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) /* save previous config */ save_enabled = set->crtc->enabled; - /* this is meant to be num_connector not num_crtc */ + /* + * We do mode_config.num_connectors here since we'll look at the + * CRTC and encoder associated with each connector later. + */ save_crtcs = kzalloc(dev->mode_config.num_connector * sizeof(struct drm_crtc *), GFP_KERNEL); if (!save_crtcs) @@ -613,21 +665,25 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) /* We should be able to check here if the fb has the same properties * and then just flip_or_move it */ if (set->crtc->fb != set->fb) { - /* if we have no fb then its a change not a flip */ + /* If we have no fb then treat it as a full mode set */ if (set->crtc->fb == NULL) - changed = true; + mode_changed = true; + else if ((set->fb->bits_per_pixel != + set->crtc->fb->bits_per_pixel) || + set->fb->depth != set->crtc->fb->depth) + fb_changed = true; else - flip_or_move = true; + fb_changed = true; } if (set->x != set->crtc->x || set->y != set->crtc->y) - flip_or_move = true; + fb_changed = true; if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { DRM_DEBUG("modes are different\n"); drm_mode_debug_printmodeline(&set->crtc->mode); drm_mode_debug_printmodeline(set->mode); - changed = true; + mode_changed = true; } /* a) traverse passed in connector list and get encoders for them */ @@ -650,7 +706,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) } if (new_encoder != connector->encoder) { - changed = true; + mode_changed = true; connector->encoder = new_encoder; } } @@ -677,16 +733,16 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) new_crtc = set->crtc; } if (new_crtc != connector->encoder->crtc) { - changed = true; + mode_changed = true; connector->encoder->crtc = new_crtc; } } /* mode_set_base is not a required function */ - if (flip_or_move && !crtc_funcs->mode_set_base) - changed = true; + if (fb_changed && !crtc_funcs->mode_set_base) + mode_changed = true; - if (changed) { + if (mode_changed) { old_fb = set->crtc->fb; set->crtc->fb = set->fb; set->crtc->enabled = (set->mode != NULL); @@ -705,7 +761,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) set->crtc->desired_mode = set->mode; } drm_helper_disable_unused_functions(dev); - } else if (flip_or_move) { + } else if (fb_changed) { old_fb = set->crtc->fb; if (set->crtc->fb != set->fb) set->crtc->fb = set->fb; @@ -764,10 +820,31 @@ bool drm_helper_plugged_event(struct drm_device *dev) */ bool drm_helper_initial_config(struct drm_device *dev, bool can_grow) { - int ret = false; + struct drm_connector *connector; + int count = 0; - drm_helper_plugged_event(dev); - return ret; + count = drm_helper_probe_connector_modes(dev, + dev->mode_config.max_width, + dev->mode_config.max_height); + + /* + * None of the available connectors had any modes, so add some + * and try to light them up anyway + */ + if (!count) { + DRM_ERROR("connectors have no modes, using standard modes\n"); + list_for_each_entry(connector, + &dev->mode_config.connector_list, + head) + drm_helper_add_std_modes(dev, connector); + } + + drm_setup_crtcs(dev); + + /* alert the driver fb layer */ + dev->mode_config.funcs->fb_changed(dev); + + return 0; } EXPORT_SYMBOL(drm_helper_initial_config); diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 724e505873cf..477caa1b1e4b 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -267,7 +267,8 @@ EXPORT_SYMBOL(drm_irq_install); */ int drm_irq_uninstall(struct drm_device * dev) { - int irq_enabled; + unsigned long irqflags; + int irq_enabled, i; if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; @@ -277,6 +278,16 @@ int drm_irq_uninstall(struct drm_device * dev) dev->irq_enabled = 0; mutex_unlock(&dev->struct_mutex); + /* + * Wake up any waiters so they don't hang. + */ + spin_lock_irqsave(&dev->vbl_lock, irqflags); + for (i = 0; i < dev->num_crtcs; i++) { + DRM_WAKEUP(&dev->vbl_queue[i]); + dev->vblank_enabled[i] = 0; + } + spin_unlock_irqrestore(&dev->vbl_lock, irqflags); + if (!irq_enabled) return -EINVAL; @@ -652,8 +663,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data, vblwait->request.sequence, crtc); dev->last_vblank_wait[crtc] = vblwait->request.sequence; DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, - ((drm_vblank_count(dev, crtc) - - vblwait->request.sequence) <= (1 << 23))); + (((drm_vblank_count(dev, crtc) - + vblwait->request.sequence) <= (1 << 23)) || + !dev->irq_enabled)); if (ret != -EINTR) { struct timeval now; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 62a4bf7b49df..bbadf1c04142 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -177,6 +177,14 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; + master_priv->sarea = drm_getsarea(dev); + if (master_priv->sarea) { + master_priv->sarea_priv = (drm_i915_sarea_t *) + ((u8 *)master_priv->sarea->handle + init->sarea_priv_offset); + } else { + DRM_DEBUG("sarea not found assuming DRI2 userspace\n"); + } + if (init->ring_size != 0) { if (dev_priv->ring.ring_obj != NULL) { i915_dma_cleanup(dev); @@ -1152,6 +1160,8 @@ int i915_driver_unload(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) { intel_modeset_cleanup(dev); + i915_gem_free_all_phys_object(dev); + mutex_lock(&dev->struct_mutex); i915_gem_cleanup_ringbuffer(dev); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 563de18063fd..e13518252007 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -72,6 +72,18 @@ enum pipe { #define WATCH_INACTIVE 0 #define WATCH_PWRITE 0 +#define I915_GEM_PHYS_CURSOR_0 1 +#define I915_GEM_PHYS_CURSOR_1 2 +#define I915_GEM_PHYS_OVERLAY_REGS 3 +#define I915_MAX_PHYS_OBJECT (I915_GEM_PHYS_OVERLAY_REGS) + +struct drm_i915_gem_phys_object { + int id; + struct page **page_list; + drm_dma_handle_t *handle; + struct drm_gem_object *cur_obj; +}; + typedef struct _drm_i915_ring_buffer { int tail_mask; unsigned long Size; @@ -358,6 +370,9 @@ typedef struct drm_i915_private { uint32_t bit_6_swizzle_x; /** Bit 6 swizzling required for Y tiling */ uint32_t bit_6_swizzle_y; + + /* storage for physical objects */ + struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; } mm; } drm_i915_private_t; @@ -436,6 +451,9 @@ struct drm_i915_gem_object { /** User space pin count and filp owning the pin */ uint32_t user_pin_count; struct drm_file *pin_filp; + + /** for phy allocated objects */ + struct drm_i915_gem_phys_object *phys_obj; }; /** @@ -598,6 +616,11 @@ int i915_gem_do_init(struct drm_device *dev, unsigned long start, int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write); +int i915_gem_attach_phys_object(struct drm_device *dev, + struct drm_gem_object *obj, int id); +void i915_gem_detach_phys_object(struct drm_device *dev, + struct drm_gem_object *obj); +void i915_gem_free_all_phys_object(struct drm_device *dev); /* i915_gem_tiling.c */ void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1384d6686555..96316fd47233 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -55,6 +55,9 @@ static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, static void i915_gem_object_get_fence_reg(struct drm_gem_object *obj); static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); static int i915_gem_evict_something(struct drm_device *dev); +static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, + struct drm_i915_gem_pwrite *args, + struct drm_file *file_priv); int i915_gem_do_init(struct drm_device *dev, unsigned long start, unsigned long end) @@ -386,8 +389,10 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, * pread/pwrite currently are reading and writing from the CPU * perspective, requiring manual detiling by the client. */ - if (obj_priv->tiling_mode == I915_TILING_NONE && - dev->gtt_total != 0) + if (obj_priv->phys_obj) + ret = i915_gem_phys_pwrite(dev, obj, args, file_priv); + else if (obj_priv->tiling_mode == I915_TILING_NONE && + dev->gtt_total != 0) ret = i915_gem_gtt_pwrite(dev, obj, args, file_priv); else ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv); @@ -2858,6 +2863,9 @@ void i915_gem_free_object(struct drm_gem_object *obj) while (obj_priv->pin_count > 0) i915_gem_object_unpin(obj); + if (obj_priv->phys_obj) + i915_gem_detach_phys_object(dev, obj); + i915_gem_object_unbind(obj); list = &obj->map_list; @@ -3293,3 +3301,180 @@ i915_gem_load(struct drm_device *dev) i915_gem_detect_bit_6_swizzle(dev); } + +/* + * Create a physically contiguous memory object for this object + * e.g. for cursor + overlay regs + */ +int i915_gem_init_phys_object(struct drm_device *dev, + int id, int size) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_phys_object *phys_obj; + int ret; + + if (dev_priv->mm.phys_objs[id - 1] || !size) + return 0; + + phys_obj = drm_calloc(1, sizeof(struct drm_i915_gem_phys_object), DRM_MEM_DRIVER); + if (!phys_obj) + return -ENOMEM; + + phys_obj->id = id; + + phys_obj->handle = drm_pci_alloc(dev, size, 0, 0xffffffff); + if (!phys_obj->handle) { + ret = -ENOMEM; + goto kfree_obj; + } +#ifdef CONFIG_X86 + set_memory_wc((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE); +#endif + + dev_priv->mm.phys_objs[id - 1] = phys_obj; + + return 0; +kfree_obj: + drm_free(phys_obj, sizeof(struct drm_i915_gem_phys_object), DRM_MEM_DRIVER); + return ret; +} + +void i915_gem_free_phys_object(struct drm_device *dev, int id) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_phys_object *phys_obj; + + if (!dev_priv->mm.phys_objs[id - 1]) + return; + + phys_obj = dev_priv->mm.phys_objs[id - 1]; + if (phys_obj->cur_obj) { + i915_gem_detach_phys_object(dev, phys_obj->cur_obj); + } + +#ifdef CONFIG_X86 + set_memory_wb((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE); +#endif + drm_pci_free(dev, phys_obj->handle); + kfree(phys_obj); + dev_priv->mm.phys_objs[id - 1] = NULL; +} + +void i915_gem_free_all_phys_object(struct drm_device *dev) +{ + int i; + + for (i = 0; i < I915_MAX_PHYS_OBJECT; i++) + i915_gem_free_phys_object(dev, i); +} + +void i915_gem_detach_phys_object(struct drm_device *dev, + struct drm_gem_object *obj) +{ + struct drm_i915_gem_object *obj_priv; + int i; + int ret; + int page_count; + + obj_priv = obj->driver_private; + if (!obj_priv->phys_obj) + return; + + ret = i915_gem_object_get_page_list(obj); + if (ret) + goto out; + + page_count = obj->size / PAGE_SIZE; + + for (i = 0; i < page_count; i++) { + char *dst = kmap_atomic(obj_priv->page_list[i], KM_USER0); + char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); + + memcpy(dst, src, PAGE_SIZE); + kunmap_atomic(dst, KM_USER0); + } + drm_clflush_pages(obj_priv->page_list, page_count); + drm_agp_chipset_flush(dev); +out: + obj_priv->phys_obj->cur_obj = NULL; + obj_priv->phys_obj = NULL; +} + +int +i915_gem_attach_phys_object(struct drm_device *dev, + struct drm_gem_object *obj, int id) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv; + int ret = 0; + int page_count; + int i; + + if (id > I915_MAX_PHYS_OBJECT) + return -EINVAL; + + obj_priv = obj->driver_private; + + if (obj_priv->phys_obj) { + if (obj_priv->phys_obj->id == id) + return 0; + i915_gem_detach_phys_object(dev, obj); + } + + + /* create a new object */ + if (!dev_priv->mm.phys_objs[id - 1]) { + ret = i915_gem_init_phys_object(dev, id, + obj->size); + if (ret) { + DRM_ERROR("failed to init phys object %d size: %d\n", id, obj->size); + goto out; + } + } + + /* bind to the object */ + obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1]; + obj_priv->phys_obj->cur_obj = obj; + + ret = i915_gem_object_get_page_list(obj); + if (ret) { + DRM_ERROR("failed to get page list\n"); + goto out; + } + + page_count = obj->size / PAGE_SIZE; + + for (i = 0; i < page_count; i++) { + char *src = kmap_atomic(obj_priv->page_list[i], KM_USER0); + char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); + + memcpy(dst, src, PAGE_SIZE); + kunmap_atomic(src, KM_USER0); + } + + return 0; +out: + return ret; +} + +static int +i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, + struct drm_i915_gem_pwrite *args, + struct drm_file *file_priv) +{ + struct drm_i915_gem_object *obj_priv = obj->driver_private; + void *obj_addr; + int ret; + char __user *user_data; + + user_data = (char __user *) (uintptr_t) args->data_ptr; + obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; + + DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size); + ret = copy_from_user(obj_addr, user_data, args->size); + if (ret) + return -EFAULT; + + drm_agp_chipset_flush(dev); + return 0; +} diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0cadafbef411..6290219de6c8 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -411,6 +411,12 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; + int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; + u32 pipeconf; + + pipeconf = I915_READ(pipeconf_reg); + if (!(pipeconf & PIPEACONF_ENABLE)) + return -EINVAL; spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); if (IS_I965G(dev)) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8ccb9c3ab868..31c3732b7a69 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -401,6 +401,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, I915_WRITE(dspstride, crtc->fb->pitch); dspcntr = I915_READ(dspcntr_reg); + /* Mask out pixel format bits in case we change it */ + dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; switch (crtc->fb->bits_per_pixel) { case 8: dspcntr |= DISPPLANE_8BPP; @@ -1014,21 +1016,25 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, if (bo->size < width * height * 4) { DRM_ERROR("buffer is to small\n"); - drm_gem_object_unreference(bo); - return -ENOMEM; + ret = -ENOMEM; + goto fail; } - if (dev_priv->cursor_needs_physical) { - addr = dev->agp->base + obj_priv->gtt_offset; - } else { + /* we only need to pin inside GTT if cursor is non-phy */ + if (!dev_priv->cursor_needs_physical) { + ret = i915_gem_object_pin(bo, PAGE_SIZE); + if (ret) { + DRM_ERROR("failed to pin cursor bo\n"); + goto fail; + } addr = obj_priv->gtt_offset; - } - - ret = i915_gem_object_pin(bo, PAGE_SIZE); - if (ret) { - DRM_ERROR("failed to pin cursor bo\n"); - drm_gem_object_unreference(bo); - return ret; + } else { + ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1); + if (ret) { + DRM_ERROR("failed to attach phys object\n"); + goto fail; + } + addr = obj_priv->phys_obj->handle->busaddr; } temp = 0; @@ -1041,14 +1047,25 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, I915_WRITE(base, addr); if (intel_crtc->cursor_bo) { - i915_gem_object_unpin(intel_crtc->cursor_bo); + if (dev_priv->cursor_needs_physical) { + if (intel_crtc->cursor_bo != bo) + i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); + } else + i915_gem_object_unpin(intel_crtc->cursor_bo); + mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(intel_crtc->cursor_bo); + mutex_unlock(&dev->struct_mutex); } intel_crtc->cursor_addr = addr; intel_crtc->cursor_bo = bo; return 0; +fail: + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(bo); + mutex_unlock(&dev->struct_mutex); + return ret; } static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index ccecfaf6307b..2fafdcc108fe 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -456,6 +456,13 @@ void intel_lvds_init(struct drm_device *dev) dev_priv->panel_fixed_mode = drm_mode_duplicate(dev, dev_priv->vbt_mode); mutex_unlock(&dev->mode_config.mutex); + if (dev_priv->panel_fixed_mode) { + dev_priv->panel_fixed_mode->type |= + DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, + dev_priv->panel_fixed_mode); + goto out; + } } /* diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 4b33bc82cc24..b84bf066879b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -189,6 +189,16 @@ config SENSORS_ADT7473 This driver can also be built as a module. If so, the module will be called adt7473. +config SENSORS_ADT7475 + tristate "Analog Devices ADT7475" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for the Analog Devices + ADT7475 hardware monitoring chips. + + This driver can also be build as a module. If so, the module + will be called adt7475. + config SENSORS_K8TEMP tristate "AMD Athlon64/FX or Opteron temperature sensor" depends on X86 && PCI && EXPERIMENTAL @@ -861,6 +871,8 @@ config SENSORS_HDAPS config SENSORS_LIS3LV02D tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer" depends on ACPI && INPUT + select NEW_LEDS + select LEDS_CLASS default n help This driver provides support for the LIS3LV02Dx accelerometer. In @@ -872,10 +884,16 @@ config SENSORS_LIS3LV02D /sys/devices/platform/lis3lv02d. This driver also provides an absolute input class device, allowing - the laptop to act as a pinball machine-esque joystick. + the laptop to act as a pinball machine-esque joystick. On HP laptops, + if the led infrastructure is activated, support for a led indicating + disk protection will be provided as hp:red:hddprotection. - This driver can also be built as a module. If so, the module - will be called lis3lv02d. + This driver can also be built as modules. If so, the core module + will be called lis3lv02d and a specific module for HP laptops will be + called hp_accel. + + Say Y here if you have an applicable laptop and want to experience + the awesome power of lis3lv02d. config SENSORS_APPLESMC tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)" diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 19cb1ace3eb4..2e80f37f39eb 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -28,6 +28,8 @@ obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o +obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o + obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o obj-$(CONFIG_SENSORS_AMS) += ams/ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index 70bb854086df..e52b38806d03 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -279,7 +279,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "OTES1 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0011, "AT8 32X(ATI RD580-ULI M1575)", { + { 0x0011, "AT8 32X", { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR", 1, 0, 20, 1, 0 }, { "DDR VTT", 2, 0, 10, 1, 0 }, @@ -402,7 +402,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0016, "AW9D-MAX (Intel i975-ICH7)", { + { 0x0016, "AW9D-MAX", { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR2", 1, 0, 20, 1, 0 }, { "DDR2 VTT", 2, 0, 10, 1, 0 }, @@ -482,7 +482,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 Fan", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x0019, NULL /* Unknown, need DMI string */, { + { 0x0019, "IN9 32X MAX", { { "CPU Core", 7, 0, 10, 1, 0 }, { "DDR2", 13, 0, 20, 1, 0 }, { "DDR2 VTT", 14, 0, 10, 1, 0 }, @@ -509,7 +509,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { { "AUX3 FAN", 36, 2, 60, 1, 0 }, { NULL, 0, 0, 0, 0, 0 } } }, - { 0x001A, "IP35 Pro(Intel P35-ICH9R)", { + { 0x001A, "IP35 Pro", { { "CPU Core", 0, 0, 10, 1, 0 }, { "DDR2", 1, 0, 20, 1, 0 }, { "DDR2 VTT", 2, 0, 10, 1, 0 }, @@ -1128,6 +1128,7 @@ static int __init abituguru3_dmi_detect(void) { const char *board_vendor, *board_name; int i, err = (force) ? 1 : -ENODEV; + size_t sublen; board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); if (!board_vendor || strcmp(board_vendor, "http://www.abit.com.tw/")) @@ -1137,9 +1138,20 @@ static int __init abituguru3_dmi_detect(void) if (!board_name) return err; + /* At the moment, we don't care about the part of the vendor + * DMI string contained in brackets. Truncate the string at + * the first occurrence of a bracket. Trim any trailing space + * from the substring. + */ + sublen = strcspn(board_name, "("); + while (sublen > 0 && board_name[sublen - 1] == ' ') + sublen--; + for (i = 0; abituguru3_motherboards[i].id; i++) { const char *dmi_name = abituguru3_motherboards[i].dmi_name; - if (dmi_name && !strcmp(dmi_name, board_name)) + if (!dmi_name || strlen(dmi_name) != sublen) + continue; + if (!strncasecmp(board_name, dmi_name, sublen)) break; } @@ -1153,7 +1165,7 @@ static int __init abituguru3_dmi_detect(void) static inline int abituguru3_dmi_detect(void) { - return -ENODEV; + return 1; } #endif /* CONFIG_DMI */ diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c new file mode 100644 index 000000000000..d39877a7da63 --- /dev/null +++ b/drivers/hwmon/adt7475.c @@ -0,0 +1,1221 @@ +/* + * adt7475 - Thermal sensor driver for the ADT7475 chip and derivatives + * Copyright (C) 2007-2008, Advanced Micro Devices, Inc. + * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net> + * Copyright (C) 2008 Hans de Goede <hdegoede@redhat.com> + + * Derived from the lm83 driver by Jean Delvare + * + * 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 <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> + +/* Indexes for the sysfs hooks */ + +#define INPUT 0 +#define MIN 1 +#define MAX 2 +#define CONTROL 3 +#define OFFSET 3 +#define AUTOMIN 4 +#define THERM 5 +#define HYSTERSIS 6 + +/* These are unique identifiers for the sysfs functions - unlike the + numbers above, these are not also indexes into an array +*/ + +#define ALARM 9 +#define FAULT 10 + +/* 7475 Common Registers */ + +#define REG_VOLTAGE_BASE 0x21 +#define REG_TEMP_BASE 0x25 +#define REG_TACH_BASE 0x28 +#define REG_PWM_BASE 0x30 +#define REG_PWM_MAX_BASE 0x38 + +#define REG_DEVID 0x3D +#define REG_VENDID 0x3E + +#define REG_STATUS1 0x41 +#define REG_STATUS2 0x42 + +#define REG_VOLTAGE_MIN_BASE 0x46 +#define REG_VOLTAGE_MAX_BASE 0x47 + +#define REG_TEMP_MIN_BASE 0x4E +#define REG_TEMP_MAX_BASE 0x4F + +#define REG_TACH_MIN_BASE 0x54 + +#define REG_PWM_CONFIG_BASE 0x5C + +#define REG_TEMP_TRANGE_BASE 0x5F + +#define REG_PWM_MIN_BASE 0x64 + +#define REG_TEMP_TMIN_BASE 0x67 +#define REG_TEMP_THERM_BASE 0x6A + +#define REG_REMOTE1_HYSTERSIS 0x6D +#define REG_REMOTE2_HYSTERSIS 0x6E + +#define REG_TEMP_OFFSET_BASE 0x70 + +#define REG_EXTEND1 0x76 +#define REG_EXTEND2 0x77 +#define REG_CONFIG5 0x7C + +#define CONFIG5_TWOSCOMP 0x01 +#define CONFIG5_TEMPOFFSET 0x02 + +/* ADT7475 Settings */ + +#define ADT7475_VOLTAGE_COUNT 2 +#define ADT7475_TEMP_COUNT 3 +#define ADT7475_TACH_COUNT 4 +#define ADT7475_PWM_COUNT 3 + +/* Macro to read the registers */ + +#define adt7475_read(reg) i2c_smbus_read_byte_data(client, (reg)) + +/* Macros to easily index the registers */ + +#define TACH_REG(idx) (REG_TACH_BASE + ((idx) * 2)) +#define TACH_MIN_REG(idx) (REG_TACH_MIN_BASE + ((idx) * 2)) + +#define PWM_REG(idx) (REG_PWM_BASE + (idx)) +#define PWM_MAX_REG(idx) (REG_PWM_MAX_BASE + (idx)) +#define PWM_MIN_REG(idx) (REG_PWM_MIN_BASE + (idx)) +#define PWM_CONFIG_REG(idx) (REG_PWM_CONFIG_BASE + (idx)) + +#define VOLTAGE_REG(idx) (REG_VOLTAGE_BASE + (idx)) +#define VOLTAGE_MIN_REG(idx) (REG_VOLTAGE_MIN_BASE + ((idx) * 2)) +#define VOLTAGE_MAX_REG(idx) (REG_VOLTAGE_MAX_BASE + ((idx) * 2)) + +#define TEMP_REG(idx) (REG_TEMP_BASE + (idx)) +#define TEMP_MIN_REG(idx) (REG_TEMP_MIN_BASE + ((idx) * 2)) +#define TEMP_MAX_REG(idx) (REG_TEMP_MAX_BASE + ((idx) * 2)) +#define TEMP_TMIN_REG(idx) (REG_TEMP_TMIN_BASE + (idx)) +#define TEMP_THERM_REG(idx) (REG_TEMP_THERM_BASE + (idx)) +#define TEMP_OFFSET_REG(idx) (REG_TEMP_OFFSET_BASE + (idx)) +#define TEMP_TRANGE_REG(idx) (REG_TEMP_TRANGE_BASE + (idx)) + +static unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD_1(adt7475); + +static const struct i2c_device_id adt7475_id[] = { + { "adt7475", adt7475 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adt7475_id); + +struct adt7475_data { + struct device *hwmon_dev; + struct mutex lock; + + unsigned long measure_updated; + unsigned long limits_updated; + char valid; + + u8 config5; + u16 alarms; + u16 voltage[3][3]; + u16 temp[7][3]; + u16 tach[2][4]; + u8 pwm[4][3]; + u8 range[3]; + u8 pwmctl[3]; + u8 pwmchan[3]; +}; + +static struct i2c_driver adt7475_driver; +static struct adt7475_data *adt7475_update_device(struct device *dev); +static void adt7475_read_hystersis(struct i2c_client *client); +static void adt7475_read_pwm(struct i2c_client *client, int index); + +/* Given a temp value, convert it to register value */ + +static inline u16 temp2reg(struct adt7475_data *data, long val) +{ + u16 ret; + + if (!(data->config5 & CONFIG5_TWOSCOMP)) { + val = SENSORS_LIMIT(val, -64000, 191000); + ret = (val + 64500) / 1000; + } else { + val = SENSORS_LIMIT(val, -128000, 127000); + if (val < -500) + ret = (256500 + val) / 1000; + else + ret = (val + 500) / 1000; + } + + return ret << 2; +} + +/* Given a register value, convert it to a real temp value */ + +static inline int reg2temp(struct adt7475_data *data, u16 reg) +{ + if (data->config5 & CONFIG5_TWOSCOMP) { + if (reg >= 512) + return (reg - 1024) * 250; + else + return reg * 250; + } else + return (reg - 256) * 250; +} + +static inline int tach2rpm(u16 tach) +{ + if (tach == 0 || tach == 0xFFFF) + return 0; + + return (90000 * 60) / tach; +} + +static inline u16 rpm2tach(unsigned long rpm) +{ + if (rpm == 0) + return 0; + + return SENSORS_LIMIT((90000 * 60) / rpm, 1, 0xFFFF); +} + +static inline int reg2vcc(u16 reg) +{ + return (4296 * reg) / 1000; +} + +static inline int reg2vccp(u16 reg) +{ + return (2929 * reg) / 1000; +} + +static inline u16 vcc2reg(long vcc) +{ + vcc = SENSORS_LIMIT(vcc, 0, 4396); + return (vcc * 1000) / 4296; +} + +static inline u16 vccp2reg(long vcc) +{ + vcc = SENSORS_LIMIT(vcc, 0, 2998); + return (vcc * 1000) / 2929; +} + +static u16 adt7475_read_word(struct i2c_client *client, int reg) +{ + u16 val; + + val = i2c_smbus_read_byte_data(client, reg); + val |= (i2c_smbus_read_byte_data(client, reg + 1) << 8); + + return val; +} + +static void adt7475_write_word(struct i2c_client *client, int reg, u16 val) +{ + i2c_smbus_write_byte_data(client, reg + 1, val >> 8); + i2c_smbus_write_byte_data(client, reg, val & 0xFF); +} + +/* Find the nearest value in a table - used for pwm frequency and + auto temp range */ +static int find_nearest(long val, const int *array, int size) +{ + int i; + + if (val < array[0]) + return 0; + + if (val > array[size - 1]) + return size - 1; + + for (i = 0; i < size - 1; i++) { + int a, b; + + if (val > array[i + 1]) + continue; + + a = val - array[i]; + b = array[i + 1] - val; + + return (a <= b) ? i : i + 1; + } + + return 0; +} + +static ssize_t show_voltage(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adt7475_data *data = adt7475_update_device(dev); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + unsigned short val; + + switch (sattr->nr) { + case ALARM: + return sprintf(buf, "%d\n", + (data->alarms >> (sattr->index + 1)) & 1); + default: + val = data->voltage[sattr->nr][sattr->index]; + return sprintf(buf, "%d\n", + sattr->index == + 0 ? reg2vccp(val) : reg2vcc(val)); + } +} + +static ssize_t set_voltage(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + unsigned char reg; + long val; + + if (strict_strtol(buf, 10, &val)) + return -EINVAL; + + mutex_lock(&data->lock); + + data->voltage[sattr->nr][sattr->index] = + sattr->index ? vcc2reg(val) : vccp2reg(val); + + if (sattr->nr == MIN) + reg = VOLTAGE_MIN_REG(sattr->index); + else + reg = VOLTAGE_MAX_REG(sattr->index); + + i2c_smbus_write_byte_data(client, reg, + data->voltage[sattr->nr][sattr->index] >> 2); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adt7475_data *data = adt7475_update_device(dev); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + int out; + + switch (sattr->nr) { + case HYSTERSIS: + mutex_lock(&data->lock); + out = data->temp[sattr->nr][sattr->index]; + if (sattr->index != 1) + out = (out >> 4) & 0xF; + else + out = (out & 0xF); + /* Show the value as an absolute number tied to + * THERM */ + out = reg2temp(data, data->temp[THERM][sattr->index]) - + out * 1000; + mutex_unlock(&data->lock); + break; + + case OFFSET: + /* Offset is always 2's complement, regardless of the + * setting in CONFIG5 */ + mutex_lock(&data->lock); + out = (s8)data->temp[sattr->nr][sattr->index]; + if (data->config5 & CONFIG5_TEMPOFFSET) + out *= 1000; + else + out *= 500; + mutex_unlock(&data->lock); + break; + + case ALARM: + out = (data->alarms >> (sattr->index + 4)) & 1; + break; + + case FAULT: + /* Note - only for remote1 and remote2 */ + out = data->alarms & (sattr->index ? 0x8000 : 0x4000); + out = out ? 0 : 1; + break; + + default: + /* All other temp values are in the configured format */ + out = reg2temp(data, data->temp[sattr->nr][sattr->index]); + } + + return sprintf(buf, "%d\n", out); +} + +static ssize_t set_temp(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + unsigned char reg = 0; + u8 out; + int temp; + long val; + + if (strict_strtol(buf, 10, &val)) + return -EINVAL; + + mutex_lock(&data->lock); + + /* We need the config register in all cases for temp <-> reg conv. */ + data->config5 = adt7475_read(REG_CONFIG5); + + switch (sattr->nr) { + case OFFSET: + if (data->config5 & CONFIG5_TEMPOFFSET) { + val = SENSORS_LIMIT(val, -63000, 127000); + out = data->temp[OFFSET][sattr->index] = val / 1000; + } else { + val = SENSORS_LIMIT(val, -63000, 64000); + out = data->temp[OFFSET][sattr->index] = val / 500; + } + break; + + case HYSTERSIS: + /* The value will be given as an absolute value, turn it + into an offset based on THERM */ + + /* Read fresh THERM and HYSTERSIS values from the chip */ + data->temp[THERM][sattr->index] = + adt7475_read(TEMP_THERM_REG(sattr->index)) << 2; + adt7475_read_hystersis(client); + + temp = reg2temp(data, data->temp[THERM][sattr->index]); + val = SENSORS_LIMIT(val, temp - 15000, temp); + val = (temp - val) / 1000; + + if (sattr->index != 1) { + data->temp[HYSTERSIS][sattr->index] &= 0xF0; + data->temp[HYSTERSIS][sattr->index] |= (val & 0xF) << 4; + } else { + data->temp[HYSTERSIS][sattr->index] &= 0x0F; + data->temp[HYSTERSIS][sattr->index] |= (val & 0xF); + } + + out = data->temp[HYSTERSIS][sattr->index]; + break; + + default: + data->temp[sattr->nr][sattr->index] = temp2reg(data, val); + + /* We maintain an extra 2 digits of precision for simplicity + * - shift those back off before writing the value */ + out = (u8) (data->temp[sattr->nr][sattr->index] >> 2); + } + + switch (sattr->nr) { + case MIN: + reg = TEMP_MIN_REG(sattr->index); + break; + case MAX: + reg = TEMP_MAX_REG(sattr->index); + break; + case OFFSET: + reg = TEMP_OFFSET_REG(sattr->index); + break; + case AUTOMIN: + reg = TEMP_TMIN_REG(sattr->index); + break; + case THERM: + reg = TEMP_THERM_REG(sattr->index); + break; + case HYSTERSIS: + if (sattr->index != 2) + reg = REG_REMOTE1_HYSTERSIS; + else + reg = REG_REMOTE2_HYSTERSIS; + + break; + } + + i2c_smbus_write_byte_data(client, reg, out); + + mutex_unlock(&data->lock); + return count; +} + +/* Table of autorange values - the user will write the value in millidegrees, + and we'll convert it */ +static const int autorange_table[] = { + 2000, 2500, 3330, 4000, 5000, 6670, 8000, + 10000, 13330, 16000, 20000, 26670, 32000, 40000, + 53330, 80000 +}; + +static ssize_t show_point2(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adt7475_data *data = adt7475_update_device(dev); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + int out, val; + + mutex_lock(&data->lock); + out = (data->range[sattr->index] >> 4) & 0x0F; + val = reg2temp(data, data->temp[AUTOMIN][sattr->index]); + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", val + autorange_table[out]); +} + +static ssize_t set_point2(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + int temp; + long val; + + if (strict_strtol(buf, 10, &val)) + return -EINVAL; + + mutex_lock(&data->lock); + + /* Get a fresh copy of the needed registers */ + data->config5 = adt7475_read(REG_CONFIG5); + data->temp[AUTOMIN][sattr->index] = + adt7475_read(TEMP_TMIN_REG(sattr->index)) << 2; + data->range[sattr->index] = + adt7475_read(TEMP_TRANGE_REG(sattr->index)); + + /* The user will write an absolute value, so subtract the start point + to figure the range */ + temp = reg2temp(data, data->temp[AUTOMIN][sattr->index]); + val = SENSORS_LIMIT(val, temp + autorange_table[0], + temp + autorange_table[ARRAY_SIZE(autorange_table) - 1]); + val -= temp; + + /* Find the nearest table entry to what the user wrote */ + val = find_nearest(val, autorange_table, ARRAY_SIZE(autorange_table)); + + data->range[sattr->index] &= ~0xF0; + data->range[sattr->index] |= val << 4; + + i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index), + data->range[sattr->index]); + + mutex_unlock(&data->lock); + return count; +} + +static ssize_t show_tach(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adt7475_data *data = adt7475_update_device(dev); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + int out; + + if (sattr->nr == ALARM) + out = (data->alarms >> (sattr->index + 10)) & 1; + else + out = tach2rpm(data->tach[sattr->nr][sattr->index]); + + return sprintf(buf, "%d\n", out); +} + +static ssize_t set_tach(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + unsigned long val; + + if (strict_strtoul(buf, 10, &val)) + return -EINVAL; + + mutex_lock(&data->lock); + + data->tach[MIN][sattr->index] = rpm2tach(val); + + adt7475_write_word(client, TACH_MIN_REG(sattr->index), + data->tach[MIN][sattr->index]); + + mutex_unlock(&data->lock); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adt7475_data *data = adt7475_update_device(dev); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + + return sprintf(buf, "%d\n", data->pwm[sattr->nr][sattr->index]); +} + +static ssize_t show_pwmchan(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adt7475_data *data = adt7475_update_device(dev); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + + return sprintf(buf, "%d\n", data->pwmchan[sattr->index]); +} + +static ssize_t show_pwmctrl(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adt7475_data *data = adt7475_update_device(dev); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + + return sprintf(buf, "%d\n", data->pwmctl[sattr->index]); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + unsigned char reg = 0; + long val; + + if (strict_strtol(buf, 10, &val)) + return -EINVAL; + + mutex_lock(&data->lock); + + switch (sattr->nr) { + case INPUT: + /* Get a fresh value for CONTROL */ + data->pwm[CONTROL][sattr->index] = + adt7475_read(PWM_CONFIG_REG(sattr->index)); + + /* If we are not in manual mode, then we shouldn't allow + * the user to set the pwm speed */ + if (((data->pwm[CONTROL][sattr->index] >> 5) & 7) != 7) { + mutex_unlock(&data->lock); + return count; + } + + reg = PWM_REG(sattr->index); + break; + + case MIN: + reg = PWM_MIN_REG(sattr->index); + break; + + case MAX: + reg = PWM_MAX_REG(sattr->index); + break; + } + + data->pwm[sattr->nr][sattr->index] = SENSORS_LIMIT(val, 0, 0xFF); + i2c_smbus_write_byte_data(client, reg, + data->pwm[sattr->nr][sattr->index]); + + mutex_unlock(&data->lock); + + return count; +} + +/* Called by set_pwmctrl and set_pwmchan */ + +static int hw_set_pwm(struct i2c_client *client, int index, + unsigned int pwmctl, unsigned int pwmchan) +{ + struct adt7475_data *data = i2c_get_clientdata(client); + long val = 0; + + switch (pwmctl) { + case 0: + val = 0x03; /* Run at full speed */ + break; + case 1: + val = 0x07; /* Manual mode */ + break; + case 2: + switch (pwmchan) { + case 1: + /* Remote1 controls PWM */ + val = 0x00; + break; + case 2: + /* local controls PWM */ + val = 0x01; + break; + case 4: + /* remote2 controls PWM */ + val = 0x02; + break; + case 6: + /* local/remote2 control PWM */ + val = 0x05; + break; + case 7: + /* All three control PWM */ + val = 0x06; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + data->pwmctl[index] = pwmctl; + data->pwmchan[index] = pwmchan; + + data->pwm[CONTROL][index] &= ~0xE0; + data->pwm[CONTROL][index] |= (val & 7) << 5; + + i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index), + data->pwm[CONTROL][index]); + + return 0; +} + +static ssize_t set_pwmchan(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + int r; + long val; + + if (strict_strtol(buf, 10, &val)) + return -EINVAL; + + mutex_lock(&data->lock); + /* Read Modify Write PWM values */ + adt7475_read_pwm(client, sattr->index); + r = hw_set_pwm(client, sattr->index, data->pwmctl[sattr->index], val); + if (r) + count = r; + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t set_pwmctrl(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + int r; + long val; + + if (strict_strtol(buf, 10, &val)) + return -EINVAL; + + mutex_lock(&data->lock); + /* Read Modify Write PWM values */ + adt7475_read_pwm(client, sattr->index); + r = hw_set_pwm(client, sattr->index, val, data->pwmchan[sattr->index]); + if (r) + count = r; + mutex_unlock(&data->lock); + + return count; +} + +/* List of frequencies for the PWM */ +static const int pwmfreq_table[] = { + 11, 14, 22, 29, 35, 44, 58, 88 +}; + +static ssize_t show_pwmfreq(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct adt7475_data *data = adt7475_update_device(dev); + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + + return sprintf(buf, "%d\n", + pwmfreq_table[data->range[sattr->index] & 7]); +} + +static ssize_t set_pwmfreq(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + int out; + long val; + + if (strict_strtol(buf, 10, &val)) + return -EINVAL; + + out = find_nearest(val, pwmfreq_table, ARRAY_SIZE(pwmfreq_table)); + + mutex_lock(&data->lock); + + data->range[sattr->index] = + adt7475_read(TEMP_TRANGE_REG(sattr->index)); + data->range[sattr->index] &= ~7; + data->range[sattr->index] |= out; + + i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index), + data->range[sattr->index]); + + mutex_unlock(&data->lock); + return count; +} + +static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_voltage, NULL, INPUT, 0); +static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_voltage, + set_voltage, MAX, 0); +static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_voltage, + set_voltage, MIN, 0); +static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, show_voltage, NULL, ALARM, 0); +static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_voltage, NULL, INPUT, 1); +static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_voltage, + set_voltage, MAX, 1); +static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_voltage, + set_voltage, MIN, 1); +static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, show_voltage, NULL, ALARM, 1); +static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, INPUT, 0); +static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, show_temp, NULL, ALARM, 0); +static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, show_temp, NULL, FAULT, 0); +static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, + MAX, 0); +static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp, + MIN, 0); +static SENSOR_DEVICE_ATTR_2(temp1_offset, S_IRUGO | S_IWUSR, show_temp, + set_temp, OFFSET, 0); +static SENSOR_DEVICE_ATTR_2(temp1_auto_point1_temp, S_IRUGO | S_IWUSR, + show_temp, set_temp, AUTOMIN, 0); +static SENSOR_DEVICE_ATTR_2(temp1_auto_point2_temp, S_IRUGO | S_IWUSR, + show_point2, set_point2, 0, 0); +static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, + THERM, 0); +static SENSOR_DEVICE_ATTR_2(temp1_crit_hyst, S_IRUGO | S_IWUSR, show_temp, + set_temp, HYSTERSIS, 0); +static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, INPUT, 1); +static SENSOR_DEVICE_ATTR_2(temp2_alarm, S_IRUGO, show_temp, NULL, ALARM, 1); +static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, + MAX, 1); +static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp, + MIN, 1); +static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IRUGO | S_IWUSR, show_temp, + set_temp, OFFSET, 1); +static SENSOR_DEVICE_ATTR_2(temp2_auto_point1_temp, S_IRUGO | S_IWUSR, + show_temp, set_temp, AUTOMIN, 1); +static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IRUGO | S_IWUSR, + show_point2, set_point2, 0, 1); +static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, + THERM, 1); +static SENSOR_DEVICE_ATTR_2(temp2_crit_hyst, S_IRUGO | S_IWUSR, show_temp, + set_temp, HYSTERSIS, 1); +static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, INPUT, 2); +static SENSOR_DEVICE_ATTR_2(temp3_alarm, S_IRUGO, show_temp, NULL, ALARM, 2); +static SENSOR_DEVICE_ATTR_2(temp3_fault, S_IRUGO, show_temp, NULL, FAULT, 2); +static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, + MAX, 2); +static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp, + MIN, 2); +static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp, + set_temp, OFFSET, 2); +static SENSOR_DEVICE_ATTR_2(temp3_auto_point1_temp, S_IRUGO | S_IWUSR, + show_temp, set_temp, AUTOMIN, 2); +static SENSOR_DEVICE_ATTR_2(temp3_auto_point2_temp, S_IRUGO | S_IWUSR, + show_point2, set_point2, 0, 2); +static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, + THERM, 2); +static SENSOR_DEVICE_ATTR_2(temp3_crit_hyst, S_IRUGO | S_IWUSR, show_temp, + set_temp, HYSTERSIS, 2); +static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_tach, NULL, INPUT, 0); +static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_tach, set_tach, + MIN, 0); +static SENSOR_DEVICE_ATTR_2(fan1_alarm, S_IRUGO, show_tach, NULL, ALARM, 0); +static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_tach, NULL, INPUT, 1); +static SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_tach, set_tach, + MIN, 1); +static SENSOR_DEVICE_ATTR_2(fan2_alarm, S_IRUGO, show_tach, NULL, ALARM, 1); +static SENSOR_DEVICE_ATTR_2(fan3_input, S_IRUGO, show_tach, NULL, INPUT, 2); +static SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_tach, set_tach, + MIN, 2); +static SENSOR_DEVICE_ATTR_2(fan3_alarm, S_IRUGO, show_tach, NULL, ALARM, 2); +static SENSOR_DEVICE_ATTR_2(fan4_input, S_IRUGO, show_tach, NULL, INPUT, 3); +static SENSOR_DEVICE_ATTR_2(fan4_min, S_IRUGO | S_IWUSR, show_tach, set_tach, + MIN, 3); +static SENSOR_DEVICE_ATTR_2(fan4_alarm, S_IRUGO, show_tach, NULL, ALARM, 3); +static SENSOR_DEVICE_ATTR_2(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, + 0); +static SENSOR_DEVICE_ATTR_2(pwm1_freq, S_IRUGO | S_IWUSR, show_pwmfreq, + set_pwmfreq, INPUT, 0); +static SENSOR_DEVICE_ATTR_2(pwm1_enable, S_IRUGO | S_IWUSR, show_pwmctrl, + set_pwmctrl, INPUT, 0); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_channel_temp, S_IRUGO | S_IWUSR, + show_pwmchan, set_pwmchan, INPUT, 0); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, + set_pwm, MIN, 0); +static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, + set_pwm, MAX, 0); +static SENSOR_DEVICE_ATTR_2(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, + 1); +static SENSOR_DEVICE_ATTR_2(pwm2_freq, S_IRUGO | S_IWUSR, show_pwmfreq, + set_pwmfreq, INPUT, 1); +static SENSOR_DEVICE_ATTR_2(pwm2_enable, S_IRUGO | S_IWUSR, show_pwmctrl, + set_pwmctrl, INPUT, 1); +static SENSOR_DEVICE_ATTR_2(pwm2_auto_channel_temp, S_IRUGO | S_IWUSR, + show_pwmchan, set_pwmchan, INPUT, 1); +static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, + set_pwm, MIN, 1); +static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, + set_pwm, MAX, 1); +static SENSOR_DEVICE_ATTR_2(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, + 2); +static SENSOR_DEVICE_ATTR_2(pwm3_freq, S_IRUGO | S_IWUSR, show_pwmfreq, + set_pwmfreq, INPUT, 2); +static SENSOR_DEVICE_ATTR_2(pwm3_enable, S_IRUGO | S_IWUSR, show_pwmctrl, + set_pwmctrl, INPUT, 2); +static SENSOR_DEVICE_ATTR_2(pwm3_auto_channel_temp, S_IRUGO | S_IWUSR, + show_pwmchan, set_pwmchan, INPUT, 2); +static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, + set_pwm, MIN, 2); +static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, + set_pwm, MAX, 2); + +static struct attribute *adt7475_attrs[] = { + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_fault.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_offset.dev_attr.attr, + &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp2_offset.dev_attr.attr, + &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_temp2_crit.dev_attr.attr, + &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_fault.dev_attr.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp3_offset.dev_attr.attr, + &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_temp3_crit.dev_attr.attr, + &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan3_min.dev_attr.attr, + &sensor_dev_attr_fan3_alarm.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan4_min.dev_attr.attr, + &sensor_dev_attr_fan4_alarm.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm1_freq.dev_attr.attr, + &sensor_dev_attr_pwm1_enable.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_channel_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm2_freq.dev_attr.attr, + &sensor_dev_attr_pwm2_enable.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_channel_temp.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm3_freq.dev_attr.attr, + &sensor_dev_attr_pwm3_enable.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_channel_temp.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, + NULL, +}; + +struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs }; + +static int adt7475_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + if (kind <= 0) { + if (adt7475_read(REG_VENDID) != 0x41 || + adt7475_read(REG_DEVID) != 0x75) { + dev_err(&adapter->dev, + "Couldn't detect a adt7475 part at 0x%02x\n", + (unsigned int)client->addr); + return -ENODEV; + } + } + + strlcpy(info->type, adt7475_id[0].name, I2C_NAME_SIZE); + + return 0; +} + +static int adt7475_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adt7475_data *data; + int i, ret = 0; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + mutex_init(&data->lock); + i2c_set_clientdata(client, data); + + /* Call adt7475_read_pwm for all pwm's as this will reprogram any + pwm's which are disabled to manual mode with 0% duty cycle */ + for (i = 0; i < ADT7475_PWM_COUNT; i++) + adt7475_read_pwm(client, i); + + ret = sysfs_create_group(&client->dev.kobj, &adt7475_attr_group); + if (ret) + goto efree; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + ret = PTR_ERR(data->hwmon_dev); + goto eremove; + } + + return 0; + +eremove: + sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group); +efree: + kfree(data); + return ret; +} + +static int adt7475_remove(struct i2c_client *client) +{ + struct adt7475_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group); + kfree(data); + + return 0; +} + +static struct i2c_driver adt7475_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adt7475", + }, + .probe = adt7475_probe, + .remove = adt7475_remove, + .id_table = adt7475_id, + .detect = adt7475_detect, + .address_data = &addr_data, +}; + +static void adt7475_read_hystersis(struct i2c_client *client) +{ + struct adt7475_data *data = i2c_get_clientdata(client); + + data->temp[HYSTERSIS][0] = (u16) adt7475_read(REG_REMOTE1_HYSTERSIS); + data->temp[HYSTERSIS][1] = data->temp[HYSTERSIS][0]; + data->temp[HYSTERSIS][2] = (u16) adt7475_read(REG_REMOTE2_HYSTERSIS); +} + +static void adt7475_read_pwm(struct i2c_client *client, int index) +{ + struct adt7475_data *data = i2c_get_clientdata(client); + unsigned int v; + + data->pwm[CONTROL][index] = adt7475_read(PWM_CONFIG_REG(index)); + + /* Figure out the internal value for pwmctrl and pwmchan + based on the current settings */ + v = (data->pwm[CONTROL][index] >> 5) & 7; + + if (v == 3) + data->pwmctl[index] = 0; + else if (v == 7) + data->pwmctl[index] = 1; + else if (v == 4) { + /* The fan is disabled - we don't want to + support that, so change to manual mode and + set the duty cycle to 0 instead + */ + data->pwm[INPUT][index] = 0; + data->pwm[CONTROL][index] &= ~0xE0; + data->pwm[CONTROL][index] |= (7 << 5); + + i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index), + data->pwm[INPUT][index]); + + i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index), + data->pwm[CONTROL][index]); + + data->pwmctl[index] = 1; + } else { + data->pwmctl[index] = 2; + + switch (v) { + case 0: + data->pwmchan[index] = 1; + break; + case 1: + data->pwmchan[index] = 2; + break; + case 2: + data->pwmchan[index] = 4; + break; + case 5: + data->pwmchan[index] = 6; + break; + case 6: + data->pwmchan[index] = 7; + break; + } + } +} + +static struct adt7475_data *adt7475_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adt7475_data *data = i2c_get_clientdata(client); + u8 ext; + int i; + + mutex_lock(&data->lock); + + /* Measurement values update every 2 seconds */ + if (time_after(jiffies, data->measure_updated + HZ * 2) || + !data->valid) { + data->alarms = adt7475_read(REG_STATUS2) << 8; + data->alarms |= adt7475_read(REG_STATUS1); + + ext = adt7475_read(REG_EXTEND1); + for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) + data->voltage[INPUT][i] = + (adt7475_read(VOLTAGE_REG(i)) << 2) | + ((ext >> ((i + 1) * 2)) & 3); + + ext = adt7475_read(REG_EXTEND2); + for (i = 0; i < ADT7475_TEMP_COUNT; i++) + data->temp[INPUT][i] = + (adt7475_read(TEMP_REG(i)) << 2) | + ((ext >> ((i + 1) * 2)) & 3); + + for (i = 0; i < ADT7475_TACH_COUNT; i++) + data->tach[INPUT][i] = + adt7475_read_word(client, TACH_REG(i)); + + /* Updated by hw when in auto mode */ + for (i = 0; i < ADT7475_PWM_COUNT; i++) + data->pwm[INPUT][i] = adt7475_read(PWM_REG(i)); + + data->measure_updated = jiffies; + } + + /* Limits and settings, should never change update every 60 seconds */ + if (time_after(jiffies, data->limits_updated + HZ * 2) || + !data->valid) { + data->config5 = adt7475_read(REG_CONFIG5); + + for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) { + /* Adjust values so they match the input precision */ + data->voltage[MIN][i] = + adt7475_read(VOLTAGE_MIN_REG(i)) << 2; + data->voltage[MAX][i] = + adt7475_read(VOLTAGE_MAX_REG(i)) << 2; + } + + for (i = 0; i < ADT7475_TEMP_COUNT; i++) { + /* Adjust values so they match the input precision */ + data->temp[MIN][i] = + adt7475_read(TEMP_MIN_REG(i)) << 2; + data->temp[MAX][i] = + adt7475_read(TEMP_MAX_REG(i)) << 2; + data->temp[AUTOMIN][i] = + adt7475_read(TEMP_TMIN_REG(i)) << 2; + data->temp[THERM][i] = + adt7475_read(TEMP_THERM_REG(i)) << 2; + data->temp[OFFSET][i] = + adt7475_read(TEMP_OFFSET_REG(i)); + } + adt7475_read_hystersis(client); + + for (i = 0; i < ADT7475_TACH_COUNT; i++) + data->tach[MIN][i] = + adt7475_read_word(client, TACH_MIN_REG(i)); + + for (i = 0; i < ADT7475_PWM_COUNT; i++) { + data->pwm[MAX][i] = adt7475_read(PWM_MAX_REG(i)); + data->pwm[MIN][i] = adt7475_read(PWM_MIN_REG(i)); + /* Set the channel and control information */ + adt7475_read_pwm(client, i); + } + + data->range[0] = adt7475_read(TEMP_TRANGE_REG(0)); + data->range[1] = adt7475_read(TEMP_TRANGE_REG(1)); + data->range[2] = adt7475_read(TEMP_TRANGE_REG(2)); + + data->limits_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->lock); + + return data; +} + +static int __init sensors_adt7475_init(void) +{ + return i2c_add_driver(&adt7475_driver); +} + +static void __exit sensors_adt7475_exit(void) +{ + i2c_del_driver(&adt7475_driver); +} + +MODULE_AUTHOR("Advanced Micro Devices, Inc"); +MODULE_DESCRIPTION("adt7475 driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_adt7475_init); +module_exit(sensors_adt7475_exit); diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index dca47a591baf..e30186236588 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -590,6 +590,11 @@ static ssize_t applesmc_light_show(struct device *dev, } ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length); + /* newer macbooks report a single 10-bit bigendian value */ + if (data_length == 10) { + left = be16_to_cpu(*(__be16 *)(buffer + 6)) >> 2; + goto out; + } left = buffer[2]; if (ret) goto out; diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index bf8d40580577..03705240000f 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c @@ -3,7 +3,7 @@ * * Copyright (C) 2007-2008 Yan Burman * Copyright (C) 2008 Eric Piel - * Copyright (C) 2008 Pavel Machek + * Copyright (C) 2008-2009 Pavel Machek * * 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 @@ -36,6 +36,7 @@ #include <linux/freezer.h> #include <linux/version.h> #include <linux/uaccess.h> +#include <linux/leds.h> #include <acpi/acpi_drivers.h> #include <asm/atomic.h> #include "lis3lv02d.h" @@ -43,6 +44,36 @@ #define DRIVER_NAME "lis3lv02d" #define ACPI_MDPS_CLASS "accelerometer" +/* Delayed LEDs infrastructure ------------------------------------ */ + +/* Special LED class that can defer work */ +struct delayed_led_classdev { + struct led_classdev led_classdev; + struct work_struct work; + enum led_brightness new_brightness; + + unsigned int led; /* For driver */ + void (*set_brightness)(struct delayed_led_classdev *data, enum led_brightness value); +}; + +static inline void delayed_set_status_worker(struct work_struct *work) +{ + struct delayed_led_classdev *data = + container_of(work, struct delayed_led_classdev, work); + + data->set_brightness(data, data->new_brightness); +} + +static inline void delayed_sysfs_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct delayed_led_classdev *data = container_of(led_cdev, + struct delayed_led_classdev, led_classdev); + data->new_brightness = brightness; + schedule_work(&data->work); +} + +/* HP-specific accelerometer driver ------------------------------------ */ /* For automatic insertion of the module */ static struct acpi_device_id lis3lv02d_device_ids[] = { @@ -154,10 +185,33 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { */ }; +static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value) +{ + acpi_handle handle = adev.device->handle; + unsigned long long ret; /* Not used when writing */ + union acpi_object in_obj[1]; + struct acpi_object_list args = { 1, in_obj }; + + in_obj[0].type = ACPI_TYPE_INTEGER; + in_obj[0].integer.value = !!value; + + acpi_evaluate_integer(handle, "ALED", &args, &ret); +} + +static struct delayed_led_classdev hpled_led = { + .led_classdev = { + .name = "hp::hddprotect", + .default_trigger = "none", + .brightness_set = delayed_sysfs_set, + .flags = LED_CORE_SUSPENDRESUME, + }, + .set_brightness = hpled_set, +}; static int lis3lv02d_add(struct acpi_device *device) { u8 val; + int ret; if (!device) return -EINVAL; @@ -183,7 +237,19 @@ static int lis3lv02d_add(struct acpi_device *device) adev.ac = lis3lv02d_axis_normal; } - return lis3lv02d_init_device(&adev); + INIT_WORK(&hpled_led.work, delayed_set_status_worker); + ret = led_classdev_register(NULL, &hpled_led.led_classdev); + if (ret) + return ret; + + ret = lis3lv02d_init_device(&adev); + if (ret) { + flush_work(&hpled_led.work); + led_classdev_unregister(&hpled_led.led_classdev); + return ret; + } + + return ret; } static int lis3lv02d_remove(struct acpi_device *device, int type) @@ -194,6 +260,9 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) lis3lv02d_joystick_disable(); lis3lv02d_poweroff(device->handle); + flush_work(&hpled_led.work); + led_classdev_unregister(&hpled_led.led_classdev); + return lis3lv02d_remove_fs(); } @@ -256,7 +325,7 @@ static void __exit lis3lv02d_exit_module(void) acpi_bus_unregister_driver(&lis3lv02d_driver); } -MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS"); +MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED."); MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index bd2bde0ef95e..1fe995111841 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c @@ -31,6 +31,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> +#include <asm/processor.h> #define TEMP_FROM_REG(val) (((((val) >> 16) & 0xff) - 49) * 1000) #define REG_TEMP 0xe4 @@ -47,6 +48,8 @@ struct k8temp_data { /* registers values */ u8 sensorsp; /* sensor presence bits - SEL_CORE & SEL_PLACE */ u32 temp[2][2]; /* core, place */ + u8 swap_core_select; /* meaning of SEL_CORE is inverted */ + u32 temp_offset; }; static struct k8temp_data *k8temp_update_device(struct device *dev) @@ -114,10 +117,15 @@ static ssize_t show_temp(struct device *dev, to_sensor_dev_attr_2(devattr); int core = attr->nr; int place = attr->index; + int temp; struct k8temp_data *data = k8temp_update_device(dev); - return sprintf(buf, "%d\n", - TEMP_FROM_REG(data->temp[core][place])); + if (data->swap_core_select) + core = core ? 0 : 1; + + temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset; + + return sprintf(buf, "%d\n", temp); } /* core, place */ @@ -141,20 +149,49 @@ static int __devinit k8temp_probe(struct pci_dev *pdev, int err; u8 scfg; u32 temp; + u8 model, stepping; struct k8temp_data *data; - u32 cpuid = cpuid_eax(1); - - /* this feature should be available since SH-C0 core */ - if ((cpuid == 0xf40) || (cpuid == 0xf50) || (cpuid == 0xf51)) { - err = -ENODEV; - goto exit; - } if (!(data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } + model = boot_cpu_data.x86_model; + stepping = boot_cpu_data.x86_mask; + + switch (boot_cpu_data.x86) { + case 0xf: + /* feature available since SH-C0, exclude older revisions */ + if (((model == 4) && (stepping == 0)) || + ((model == 5) && (stepping <= 1))) { + err = -ENODEV; + goto exit_free; + } + + /* + * AMD NPT family 0fh, i.e. RevF and RevG: + * meaning of SEL_CORE bit is inverted + */ + if (model >= 0x40) { + data->swap_core_select = 1; + dev_warn(&pdev->dev, "Temperature readouts might be " + "wrong - check erratum #141\n"); + } + + if ((model >= 0x69) && + !(model == 0xc1 || model == 0x6c || model == 0x7c)) { + /* + * RevG desktop CPUs (i.e. no socket S1G1 parts) + * need additional offset, otherwise reported + * temperature is below ambient temperature + */ + data->temp_offset = 21000; + } + + break; + } + pci_read_config_byte(pdev, REG_TEMP, &scfg); scfg &= ~(SEL_PLACE | SEL_CORE); /* Select sensor 0, core0 */ pci_write_config_byte(pdev, REG_TEMP, scfg); diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 59c3d23f5bdc..b9bef04b7be4 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig @@ -139,15 +139,4 @@ config SENSORS_TSL2550 This driver can also be built as a module. If so, the module will be called tsl2550. -config MCU_MPC8349EMITX - tristate "MPC8349E-mITX MCU driver" - depends on I2C && PPC_83xx - select GENERIC_GPIO - select ARCH_REQUIRE_GPIOLIB - help - Say Y here to enable soft power-off functionality on the Freescale - boards with the MPC8349E-mITX-compatible MCU chips. This driver will - also register MCU GPIOs with the generic GPIO API, so you'll able - to use MCU pins as GPIOs. - endmenu diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index 83accaaf8164..00fcb5193ac2 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_PCF8575) += pcf8575.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o -obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/i2c/chips/mcu_mpc8349emitx.c b/drivers/i2c/chips/mcu_mpc8349emitx.c deleted file mode 100644 index 82a9bcb858b6..000000000000 --- a/drivers/i2c/chips/mcu_mpc8349emitx.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Power Management and GPIO expander driver for MPC8349E-mITX-compatible MCU - * - * Copyright (c) 2008 MontaVista Software, Inc. - * - * Author: Anton Vorontsov <avorontsov@ru.mvista.com> - * - * 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 <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/mutex.h> -#include <linux/i2c.h> -#include <linux/gpio.h> -#include <linux/of.h> -#include <linux/of_gpio.h> -#include <asm/prom.h> -#include <asm/machdep.h> - -/* - * I don't have specifications for the MCU firmware, I found this register - * and bits positions by the trial&error method. - */ -#define MCU_REG_CTRL 0x20 -#define MCU_CTRL_POFF 0x40 - -#define MCU_NUM_GPIO 2 - -struct mcu { - struct mutex lock; - struct device_node *np; - struct i2c_client *client; - struct of_gpio_chip of_gc; - u8 reg_ctrl; -}; - -static struct mcu *glob_mcu; - -static void mcu_power_off(void) -{ - struct mcu *mcu = glob_mcu; - - pr_info("Sending power-off request to the MCU...\n"); - mutex_lock(&mcu->lock); - i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL, - mcu->reg_ctrl | MCU_CTRL_POFF); - mutex_unlock(&mcu->lock); -} - -static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -{ - struct of_gpio_chip *of_gc = to_of_gpio_chip(gc); - struct mcu *mcu = container_of(of_gc, struct mcu, of_gc); - u8 bit = 1 << (4 + gpio); - - mutex_lock(&mcu->lock); - if (val) - mcu->reg_ctrl &= ~bit; - else - mcu->reg_ctrl |= bit; - - i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL, mcu->reg_ctrl); - mutex_unlock(&mcu->lock); -} - -static int mcu_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) -{ - mcu_gpio_set(gc, gpio, val); - return 0; -} - -static int mcu_gpiochip_add(struct mcu *mcu) -{ - struct device_node *np; - struct of_gpio_chip *of_gc = &mcu->of_gc; - struct gpio_chip *gc = &of_gc->gc; - int ret; - - np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx"); - if (!np) - return -ENODEV; - - gc->owner = THIS_MODULE; - gc->label = np->full_name; - gc->can_sleep = 1; - gc->ngpio = MCU_NUM_GPIO; - gc->base = -1; - gc->set = mcu_gpio_set; - gc->direction_output = mcu_gpio_dir_out; - of_gc->gpio_cells = 2; - of_gc->xlate = of_gpio_simple_xlate; - - np->data = of_gc; - mcu->np = np; - - /* - * We don't want to lose the node, its ->data and ->full_name... - * So, if succeeded, we don't put the node here. - */ - ret = gpiochip_add(gc); - if (ret) - of_node_put(np); - return ret; -} - -static int mcu_gpiochip_remove(struct mcu *mcu) -{ - int ret; - - ret = gpiochip_remove(&mcu->of_gc.gc); - if (ret) - return ret; - of_node_put(mcu->np); - - return 0; -} - -static int __devinit mcu_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct mcu *mcu; - int ret; - - mcu = kzalloc(sizeof(*mcu), GFP_KERNEL); - if (!mcu) - return -ENOMEM; - - mutex_init(&mcu->lock); - mcu->client = client; - i2c_set_clientdata(client, mcu); - - ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL); - if (ret < 0) - goto err; - mcu->reg_ctrl = ret; - - ret = mcu_gpiochip_add(mcu); - if (ret) - goto err; - - /* XXX: this is potentially racy, but there is no lock for ppc_md */ - if (!ppc_md.power_off) { - glob_mcu = mcu; - ppc_md.power_off = mcu_power_off; - dev_info(&client->dev, "will provide power-off service\n"); - } - - return 0; -err: - kfree(mcu); - return ret; -} - -static int __devexit mcu_remove(struct i2c_client *client) -{ - struct mcu *mcu = i2c_get_clientdata(client); - int ret; - - if (glob_mcu == mcu) { - ppc_md.power_off = NULL; - glob_mcu = NULL; - } - - ret = mcu_gpiochip_remove(mcu); - if (ret) - return ret; - i2c_set_clientdata(client, NULL); - kfree(mcu); - return 0; -} - -static const struct i2c_device_id mcu_ids[] = { - { "mcu-mpc8349emitx", }, - {}, -}; -MODULE_DEVICE_TABLE(i2c, mcu_ids); - -static struct i2c_driver mcu_driver = { - .driver = { - .name = "mcu-mpc8349emitx", - .owner = THIS_MODULE, - }, - .probe = mcu_probe, - .remove = __devexit_p(mcu_remove), - .id_table = mcu_ids, -}; - -static int __init mcu_init(void) -{ - return i2c_add_driver(&mcu_driver); -} -module_init(mcu_init); - -static void __exit mcu_exit(void) -{ - i2c_del_driver(&mcu_driver); -} -module_exit(mcu_exit); - -MODULE_DESCRIPTION("Power Management and GPIO expander driver for " - "MPC8349E-mITX-compatible MCU"); -MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 3f9503867e6b..b1c6f68d98ce 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -701,11 +701,6 @@ config BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX endchoice -config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ - int "Maximum transfer size (KB) per request (up to 128)" - default "128" - depends on BLK_DEV_IDE_AU1XXX - config BLK_DEV_IDE_TX4938 tristate "TX4938 internal IDE support" depends on SOC_TX4938 diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 4088a622873e..806760d24cef 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -633,7 +633,7 @@ static void ide_disk_setup(ide_drive_t *drive) printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, q->max_sectors / 2); - if (ata_id_is_ssd(id) || ata_id_is_cfa(id)) + if (ata_id_is_ssd(id)) queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); /* calculate drive capacity, and select LBA if possible */ diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index e728cfe7273f..753b92ebe0ae 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -493,7 +493,7 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti stat = tp_ops->read_status(hwif); if (stat & ATA_BUSY) { - local_irq_save(flags); + local_save_flags(flags); local_irq_enable_in_hardirq(); timeout += jiffies; while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) { diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index 4b3bf6a06b70..60538d9c84ee 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c @@ -186,12 +186,10 @@ void ide_complete_pm_request(ide_drive_t *drive, struct request *rq) blk_pm_suspend_request(rq) ? "suspend" : "resume"); #endif spin_lock_irqsave(q->queue_lock, flags); - if (blk_pm_suspend_request(rq)) { + if (blk_pm_suspend_request(rq)) blk_stop_queue(q); - } else { + else drive->dev_flags &= ~IDE_DFLAG_BLOCKED; - blk_start_queue(q); - } spin_unlock_irqrestore(q->queue_lock, flags); drive->hwif->rq = NULL; @@ -219,6 +217,8 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq) * point. */ ide_hwif_t *hwif = drive->hwif; + struct request_queue *q = drive->queue; + unsigned long flags; int rc; #ifdef DEBUG_PM printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); @@ -231,5 +231,9 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq) rc = ide_wait_not_busy(hwif, 100000); if (rc) printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); + + spin_lock_irqsave(q->queue_lock, flags); + blk_start_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); } } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 0ccbb4459fb9..312127ea443a 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -796,7 +796,7 @@ static int ide_probe_port(ide_hwif_t *hwif) if (irqd) disable_irq(hwif->irq); - local_irq_save(flags); + local_save_flags(flags); local_irq_enable_in_hardirq(); if (ide_port_wait_ready(hwif) == -EBUSY) diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c index 0be27ac1f077..e1c4f5437396 100644 --- a/drivers/ide/it821x.c +++ b/drivers/ide/it821x.c @@ -68,6 +68,8 @@ #define DRV_NAME "it821x" +#define QUIRK_VORTEX86 1 + struct it821x_dev { unsigned int smart:1, /* Are we in smart raid mode */ @@ -79,6 +81,7 @@ struct it821x_dev u16 pio[2]; /* Cached PIO values */ u16 mwdma[2]; /* Cached MWDMA values */ u16 udma[2]; /* Cached UDMA values (per drive) */ + u16 quirks; }; #define ATA_66 0 @@ -557,8 +560,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif) * this is necessary. */ - pci_read_config_byte(dev, 0x08, &conf); - if (conf == 0x10) { + if (dev->revision == 0x10) { idev->timing10 = 1; hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA; if (idev->smart == 0) @@ -577,6 +579,12 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif) hwif->ultra_mask = ATA_UDMA6; hwif->mwdma_mask = ATA_MWDMA2; + + /* Vortex86SX quirk: prevent Ultra-DMA mode to fix BadCRC issue */ + if (idev->quirks & QUIRK_VORTEX86) { + if (dev->revision == 0x11) + hwif->ultra_mask = 0; + } } static void it8212_disable_raid(struct pci_dev *dev) @@ -649,6 +657,8 @@ static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_devic return -ENOMEM; } + itdevs->quirks = id->driver_data; + rc = ide_pci_init_one(dev, &it821x_chipset, itdevs); if (rc) kfree(itdevs); @@ -668,6 +678,7 @@ static void __devexit it821x_remove(struct pci_dev *dev) static const struct pci_device_id it821x_pci_tbl[] = { { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), 0 }, { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), 0 }, + { PCI_VDEVICE(RDC, PCI_DEVICE_ID_RDC_D1010), QUIRK_VORTEX86 }, { 0, }, }; diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c index 48cc748c5043..6297956507c0 100644 --- a/drivers/ide/sl82c105.c +++ b/drivers/ide/sl82c105.c @@ -310,10 +310,6 @@ static const struct ide_port_info sl82c105_chipset __devinitdata = { .dma_ops = &sl82c105_dma_ops, .host_flags = IDE_HFLAG_IO_32BIT | IDE_HFLAG_UNMASK_IRQS | -/* FIXME: check for Compatibility mode in generic IDE PCI code */ -#if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT) - IDE_HFLAG_FORCE_LEGACY_IRQS | -#endif IDE_HFLAG_SERIALIZE_DMA | IDE_HFLAG_NO_AUTODMA, .pio_mask = ATA_PIO5, diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index b4ef218072cd..d9095345f7ca 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c @@ -202,7 +202,6 @@ static const struct ide_tp_ops tx4938ide_tp_ops = { .exec_command = ide_exec_command, .read_status = ide_read_status, .read_altstatus = ide_read_altstatus, - .read_sff_dma_status = ide_read_sff_dma_status, .set_irq = ide_set_irq, diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index fecc0e03c3fc..703c3eeb20a8 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -432,8 +432,6 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i if (via_clock < 20000 || via_clock > 50000) { printk(KERN_WARNING DRV_NAME ": User given PCI clock speed " "impossible (%d), using 33 MHz instead.\n", via_clock); - printk(KERN_WARNING DRV_NAME ": Use ide0=ata66 if you want " - "to assume 80-wire cable.\n"); via_clock = 33333; } diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 7c5f97033b9f..cb8943da4f12 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -292,7 +292,9 @@ isdn_net_unbind_channel(isdn_net_local * lp) lp->dialstate = 0; dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL; dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL; - isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET); + if (lp->isdn_device != -1 && lp->isdn_channel != -1) + isdn_free_channel(lp->isdn_device, lp->isdn_channel, + ISDN_USAGE_NET); lp->flags &= ~ISDN_NET_CONNECTED; lp->isdn_device = -1; lp->isdn_channel = -1; @@ -2513,7 +2515,6 @@ static const struct net_device_ops isdn_netdev_ops = { .ndo_stop = isdn_net_close, .ndo_do_ioctl = isdn_net_ioctl, - .ndo_validate_addr = NULL, .ndo_start_xmit = isdn_net_start_xmit, .ndo_get_stats = isdn_net_get_stats, .ndo_tx_timeout = isdn_net_tx_timeout, @@ -2528,12 +2529,8 @@ static void _isdn_setup(struct net_device *dev) ether_setup(dev); - dev->flags = IFF_NOARP | IFF_POINTOPOINT; /* Setup the generic properties */ - dev->mtu = 1500; dev->flags = IFF_NOARP|IFF_POINTOPOINT; - dev->type = ARPHRD_ETHER; - dev->addr_len = ETH_ALEN; dev->header_ops = NULL; dev->netdev_ops = &isdn_netdev_ops; diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index a4a1ae214630..742713611bc5 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -119,13 +119,6 @@ config LEDS_GPIO outputs. To be useful the particular board must have LEDs and they must be connected to the GPIO lines. -config LEDS_HP_DISK - tristate "LED Support for disk protection LED on HP notebooks" - depends on LEDS_CLASS && ACPI - help - This option enable support for disk protection LED, found on - newer HP notebooks. - config LEDS_CLEVO_MAIL tristate "Mail LED on Clevo notebook (EXPERIMENTAL)" depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index bc247cb02e82..9d76f0f160a4 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -23,7 +23,6 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o obj-$(CONFIG_LEDS_FSG) += leds-fsg.o obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o -obj-$(CONFIG_LEDS_HP_DISK) += leds-hp-disk.o obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o # LED Triggers diff --git a/drivers/leds/leds-hp-disk.c b/drivers/leds/leds-hp-disk.c deleted file mode 100644 index d786adc8c5e3..000000000000 --- a/drivers/leds/leds-hp-disk.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * leds-hp-disk.c - driver for HP "hard disk protection" LED - * - * Copyright (C) 2008 Pavel Machek - * - * 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 <linux/kernel.h> -#include <linux/init.h> -#include <linux/dmi.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/input.h> -#include <linux/kthread.h> -#include <linux/leds.h> -#include <acpi/acpi_drivers.h> - -#define DRIVER_NAME "leds-hp-disk" -#define ACPI_MDPS_CLASS "led" - -/* For automatic insertion of the module */ -static struct acpi_device_id hpled_device_ids[] = { - {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, hpled_device_ids); - -struct acpi_hpled { - struct acpi_device *device; /* The ACPI device */ -}; - -static struct acpi_hpled adev; - -static acpi_status hpled_acpi_write(acpi_handle handle, int reg) -{ - unsigned long long ret; /* Not used when writing */ - union acpi_object in_obj[1]; - struct acpi_object_list args = { 1, in_obj }; - - in_obj[0].type = ACPI_TYPE_INTEGER; - in_obj[0].integer.value = reg; - - return acpi_evaluate_integer(handle, "ALED", &args, &ret); -} - -static void hpled_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - hpled_acpi_write(adev.device->handle, !!value); -} - -static struct led_classdev hpled_led = { - .name = "hp:red:hddprotection", - .default_trigger = "heartbeat", - .brightness_set = hpled_set, - .flags = LED_CORE_SUSPENDRESUME, -}; - -static int hpled_add(struct acpi_device *device) -{ - int ret; - - if (!device) - return -EINVAL; - - adev.device = device; - strcpy(acpi_device_name(device), DRIVER_NAME); - strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); - device->driver_data = &adev; - - ret = led_classdev_register(NULL, &hpled_led); - return ret; -} - -static int hpled_remove(struct acpi_device *device, int type) -{ - if (!device) - return -EINVAL; - - led_classdev_unregister(&hpled_led); - return 0; -} - - - -static struct acpi_driver leds_hp_driver = { - .name = DRIVER_NAME, - .class = ACPI_MDPS_CLASS, - .ids = hpled_device_ids, - .ops = { - .add = hpled_add, - .remove = hpled_remove, - } -}; - -static int __init hpled_init_module(void) -{ - int ret; - - if (acpi_disabled) - return -ENODEV; - - ret = acpi_bus_register_driver(&leds_hp_driver); - if (ret < 0) - return ret; - - printk(KERN_INFO DRIVER_NAME " driver loaded.\n"); - - return 0; -} - -static void __exit hpled_exit_module(void) -{ - acpi_bus_unregister_driver(&leds_hp_driver); -} - -MODULE_DESCRIPTION("Driver for HP disk protection LED"); -MODULE_AUTHOR("Pavel Machek <pavel@suse.cz>"); -MODULE_LICENSE("GPL"); - -module_init(hpled_init_module); -module_exit(hpled_exit_module); diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c index 074b11ffbf41..e7ab0035d305 100644 --- a/drivers/mfd/twl4030-core.c +++ b/drivers/mfd/twl4030-core.c @@ -649,7 +649,7 @@ static inline int __init unprotect_pm_master(void) return e; } -static void __init clocks_init(void) +static void __init clocks_init(struct device *dev) { int e = 0; struct clk *osc; @@ -658,9 +658,9 @@ static void __init clocks_init(void) #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) if (cpu_is_omap2430()) - osc = clk_get(NULL, "osc_ck"); + osc = clk_get(dev, "osc_ck"); else - osc = clk_get(NULL, "osc_sys_ck"); + osc = clk_get(dev, "osc_sys_ck"); if (IS_ERR(osc)) { printk(KERN_WARNING "Skipping twl4030 internal clock init and " @@ -776,7 +776,7 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) inuse = true; /* setup clock framework */ - clocks_init(); + clocks_init(&client->dev); /* Maybe init the T2 Interrupt subsystem */ if (client->irq diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c index 73b7fb8de47a..82fb9958f22f 100644 --- a/drivers/misc/sgi-xp/xpc_sn2.c +++ b/drivers/misc/sgi-xp/xpc_sn2.c @@ -899,7 +899,7 @@ xpc_update_partition_info_sn2(struct xpc_partition *part, u8 remote_rp_version, dev_dbg(xpc_part, " remote_vars_pa = 0x%016lx\n", part_sn2->remote_vars_pa); - part->last_heartbeat = remote_vars->heartbeat; + part->last_heartbeat = remote_vars->heartbeat - 1; dev_dbg(xpc_part, " last_heartbeat = 0x%016lx\n", part->last_heartbeat); diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 745ac188babe..d15d8b79d8e5 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -646,7 +646,7 @@ static const struct net_device_ops etherh_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_addr = eth_set_mac_addr, + .ndo_set_mac_address = eth_set_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c index 337488ec707c..a4eb6c40678c 100644 --- a/drivers/net/ax88796.c +++ b/drivers/net/ax88796.c @@ -37,7 +37,10 @@ static int phy_debug = 0; #define __ei_open ax_ei_open #define __ei_close ax_ei_close #define __ei_poll ax_ei_poll +#define __ei_start_xmit ax_ei_start_xmit #define __ei_tx_timeout ax_ei_tx_timeout +#define __ei_get_stats ax_ei_get_stats +#define __ei_set_multicast_list ax_ei_set_multicast_list #define __ei_interrupt ax_ei_interrupt #define ____alloc_ei_netdev ax__alloc_ei_netdev #define __NS8390_init ax_NS8390_init @@ -623,6 +626,23 @@ static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom) } #endif +static const struct net_device_ops ax_netdev_ops = { + .ndo_open = ax_open, + .ndo_stop = ax_close, + .ndo_do_ioctl = ax_ioctl, + + .ndo_start_xmit = ax_ei_start_xmit, + .ndo_tx_timeout = ax_ei_tx_timeout, + .ndo_get_stats = ax_ei_get_stats, + .ndo_set_multicast_list = ax_ei_set_multicast_list, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, + .ndo_change_mtu = eth_change_mtu, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ax_ei_poll, +#endif +}; + /* setup code */ static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local) @@ -738,9 +758,7 @@ static int ax_init_dev(struct net_device *dev, int first_init) ei_status.get_8390_hdr = &ax_get_8390_hdr; ei_status.priv = 0; - dev->open = ax_open; - dev->stop = ax_close; - dev->do_ioctl = ax_ioctl; + dev->netdev_ops = &ax_netdev_ops; dev->ethtool_ops = &ax_ethtool_ops; ax->msg_enable = NETIF_MSG_LINK; @@ -753,9 +771,6 @@ static int ax_init_dev(struct net_device *dev, int first_init) ax->mii.mdio_write = ax_phy_write; ax->mii.dev = dev; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ax_ei_poll; -#endif ax_NS8390_init(dev, 0); if (first_init) diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 5ae131c147f9..c38512ebcea6 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -679,6 +679,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) dev_kfree_skb_any(skb); return -ENOMEM; } + bp->force_copybreak = 1; } rh = (struct rx_header *) skb->data; @@ -800,7 +801,7 @@ static int b44_rx(struct b44 *bp, int budget) /* Omit CRC. */ len -= 4; - if (len > RX_COPY_THRESHOLD) { + if (!bp->force_copybreak && len > RX_COPY_THRESHOLD) { int skb_size; skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod); if (skb_size < 0) @@ -2152,6 +2153,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev, bp = netdev_priv(dev); bp->sdev = sdev; bp->dev = dev; + bp->force_copybreak = 0; bp->msg_enable = netif_msg_init(b44_debug, B44_DEF_MSG_ENABLE); diff --git a/drivers/net/b44.h b/drivers/net/b44.h index 7db0c84a7950..e678498de6db 100644 --- a/drivers/net/b44.h +++ b/drivers/net/b44.h @@ -395,7 +395,7 @@ struct b44 { u32 rx_pending; u32 tx_pending; u8 phy_addr; - + u8 force_copybreak; struct mii_if_info mii_if; }; diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index fd705d1295a7..6fcccef4cf3d 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -20,6 +20,11 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#define BCM_VLAN 1 +#endif + + /* error/debug prints */ #define DRV_MODULE_NAME "bnx2x" @@ -78,11 +83,6 @@ #endif -#ifdef NETIF_F_HW_VLAN_TX -#define BCM_VLAN 1 -#endif - - #define U64_LO(x) (u32)(((u64)(x)) & 0xffffffff) #define U64_HI(x) (u32)(((u64)(x)) >> 32) #define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo)) @@ -150,6 +150,9 @@ struct sw_rx_page { #define PAGES_PER_SGE_SHIFT 0 #define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT) +#define SGE_PAGE_SIZE PAGE_SIZE +#define SGE_PAGE_SHIFT PAGE_SHIFT +#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN(addr) #define BCM_RX_ETH_PAYLOAD_ALIGN 64 @@ -736,7 +739,7 @@ struct bnx2x { struct bnx2x_fastpath fp[MAX_CONTEXT]; void __iomem *regview; void __iomem *doorbells; -#define BNX2X_DB_SIZE (16*2048) +#define BNX2X_DB_SIZE (16*BCM_PAGE_SIZE) struct net_device *dev; struct pci_dev *pdev; @@ -801,6 +804,8 @@ struct bnx2x { #define TPA_ENABLE_FLAG 0x80 #define NO_MCP_FLAG 0x100 #define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG) +#define HW_VLAN_TX_FLAG 0x400 +#define HW_VLAN_RX_FLAG 0x800 int func; #define BP_PORT(bp) (bp->func % PORT_MAX) @@ -811,7 +816,7 @@ struct bnx2x { int pm_cap; int pcie_cap; - struct work_struct sp_task; + struct delayed_work sp_task; struct work_struct reset_task; struct timer_list timer; diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 4be05847f86f..7c533797c064 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -38,9 +38,7 @@ #include <linux/time.h> #include <linux/ethtool.h> #include <linux/mii.h> -#ifdef NETIF_F_HW_VLAN_TX - #include <linux/if_vlan.h> -#endif +#include <linux/if_vlan.h> #include <net/ip.h> #include <net/tcp.h> #include <net/checksum.h> @@ -95,6 +93,7 @@ MODULE_PARM_DESC(debug, "default debug msglevel"); module_param(use_multi, int, 0); MODULE_PARM_DESC(use_multi, "use per-CPU queues"); #endif +static struct workqueue_struct *bnx2x_wq; enum bnx2x_board_type { BCM57710 = 0, @@ -671,7 +670,8 @@ static void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw) synchronize_irq(bp->pdev->irq); /* make sure sp_task is not running */ - cancel_work_sync(&bp->sp_task); + cancel_delayed_work(&bp->sp_task); + flush_workqueue(bnx2x_wq); } /* fast path */ @@ -972,7 +972,7 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp, return; pci_unmap_page(bp->pdev, pci_unmap_addr(sw_buf, mapping), - BCM_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); + SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); __free_pages(page, PAGES_PER_SGE_SHIFT); sw_buf->page = NULL; @@ -1000,7 +1000,7 @@ static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp, if (unlikely(page == NULL)) return -ENOMEM; - mapping = pci_map_page(bp->pdev, page, 0, BCM_PAGE_SIZE*PAGES_PER_SGE, + mapping = pci_map_page(bp->pdev, page, 0, SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) { __free_pages(page, PAGES_PER_SGE_SHIFT); @@ -1096,9 +1096,9 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp, struct eth_fast_path_rx_cqe *fp_cqe) { struct bnx2x *bp = fp->bp; - u16 sge_len = BCM_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) - + u16 sge_len = SGE_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) - le16_to_cpu(fp_cqe->len_on_bd)) >> - BCM_PAGE_SHIFT; + SGE_PAGE_SHIFT; u16 last_max, last_elem, first_elem; u16 delta = 0; u16 i; @@ -1203,22 +1203,22 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, u16 cqe_idx) { struct sw_rx_page *rx_pg, old_rx_pg; - struct page *sge; u16 len_on_bd = le16_to_cpu(fp_cqe->len_on_bd); u32 i, frag_len, frag_size, pages; int err; int j; frag_size = le16_to_cpu(fp_cqe->pkt_len) - len_on_bd; - pages = BCM_PAGE_ALIGN(frag_size) >> BCM_PAGE_SHIFT; + pages = SGE_PAGE_ALIGN(frag_size) >> SGE_PAGE_SHIFT; /* This is needed in order to enable forwarding support */ if (frag_size) - skb_shinfo(skb)->gso_size = min((u32)BCM_PAGE_SIZE, + skb_shinfo(skb)->gso_size = min((u32)SGE_PAGE_SIZE, max(frag_size, (u32)len_on_bd)); #ifdef BNX2X_STOP_ON_ERROR - if (pages > 8*PAGES_PER_SGE) { + if (pages > + min((u32)8, (u32)MAX_SKB_FRAGS) * SGE_PAGE_SIZE * PAGES_PER_SGE) { BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n", pages, cqe_idx); BNX2X_ERR("fp_cqe->pkt_len = %d fp_cqe->len_on_bd = %d\n", @@ -1234,9 +1234,8 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, /* FW gives the indices of the SGE as if the ring is an array (meaning that "next" element will consume 2 indices) */ - frag_len = min(frag_size, (u32)(BCM_PAGE_SIZE*PAGES_PER_SGE)); + frag_len = min(frag_size, (u32)(SGE_PAGE_SIZE*PAGES_PER_SGE)); rx_pg = &fp->rx_page_ring[sge_idx]; - sge = rx_pg->page; old_rx_pg = *rx_pg; /* If we fail to allocate a substitute page, we simply stop @@ -1249,7 +1248,7 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, /* Unmap the page as we r going to pass it to the stack */ pci_unmap_page(bp->pdev, pci_unmap_addr(&old_rx_pg, mapping), - BCM_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); + SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE); /* Add one frag and update the appropriate fields in the skb */ skb_fill_page_desc(skb, j, old_rx_pg.page, 0, frag_len); @@ -1282,6 +1281,13 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, if (likely(new_skb)) { /* fix ip xsum and give it to the stack */ /* (no need to map the new skb) */ +#ifdef BCM_VLAN + int is_vlan_cqe = + (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & + PARSING_FLAGS_VLAN); + int is_not_hwaccel_vlan_cqe = + (is_vlan_cqe && (!(bp->flags & HW_VLAN_RX_FLAG))); +#endif prefetch(skb); prefetch(((char *)(skb)) + 128); @@ -1306,6 +1312,12 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, struct iphdr *iph; iph = (struct iphdr *)skb->data; +#ifdef BCM_VLAN + /* If there is no Rx VLAN offloading - + take VLAN tag into an account */ + if (unlikely(is_not_hwaccel_vlan_cqe)) + iph = (struct iphdr *)((u8 *)iph + VLAN_HLEN); +#endif iph->check = 0; iph->check = ip_fast_csum((u8 *)iph, iph->ihl); } @@ -1313,9 +1325,8 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, if (!bnx2x_fill_frag_skb(bp, fp, skb, &cqe->fast_path_cqe, cqe_idx)) { #ifdef BCM_VLAN - if ((bp->vlgrp != NULL) && - (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & - PARSING_FLAGS_VLAN)) + if ((bp->vlgrp != NULL) && is_vlan_cqe && + (!is_not_hwaccel_vlan_cqe)) vlan_hwaccel_receive_skb(skb, bp->vlgrp, le16_to_cpu(cqe->fast_path_cqe. vlan_tag)); @@ -1355,11 +1366,23 @@ static inline void bnx2x_update_rx_prod(struct bnx2x *bp, rx_prods.cqe_prod = rx_comp_prod; rx_prods.sge_prod = rx_sge_prod; + /* + * Make sure that the BD and SGE data is updated before updating the + * producers since FW might read the BD/SGE right after the producer + * is updated. + * This is only applicable for weak-ordered memory model archs such + * as IA-64. The following barrier is also mandatory since FW will + * assumes BDs must have buffers. + */ + wmb(); + for (i = 0; i < sizeof(struct tstorm_eth_rx_producers)/4; i++) REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_RX_PRODS_OFFSET(BP_PORT(bp), FP_CL_ID(fp)) + i*4, ((u32 *)&rx_prods)[i]); + mmiowb(); /* keep prod updates ordered */ + DP(NETIF_MSG_RX_STATUS, "Wrote: bd_prod %u cqe_prod %u sge_prod %u\n", bd_prod, rx_comp_prod, rx_sge_prod); @@ -1415,7 +1438,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) DP(NETIF_MSG_RX_STATUS, "CQE type %x err %x status %x" " queue %x vlan %x len %u\n", CQE_TYPE(cqe_fp_flags), cqe_fp_flags, cqe->fast_path_cqe.status_flags, - cqe->fast_path_cqe.rss_hash_result, + le32_to_cpu(cqe->fast_path_cqe.rss_hash_result), le16_to_cpu(cqe->fast_path_cqe.vlan_tag), le16_to_cpu(cqe->fast_path_cqe.pkt_len)); @@ -1547,7 +1570,7 @@ reuse_rx: } #ifdef BCM_VLAN - if ((bp->vlgrp != NULL) && + if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) && (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & PARSING_FLAGS_VLAN)) vlan_hwaccel_receive_skb(skb, bp->vlgrp, @@ -1580,7 +1603,6 @@ next_cqe: /* Update producers */ bnx2x_update_rx_prod(bp, fp, bd_prod_fw, sw_comp_prod, fp->rx_sge_prod); - mmiowb(); /* keep prod updates ordered */ fp->rx_pkt += rx_pkt; fp->rx_calls++; @@ -1660,7 +1682,7 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance) if (unlikely(status & 0x1)) { - schedule_work(&bp->sp_task); + queue_delayed_work(bnx2x_wq, &bp->sp_task, 0); status &= ~0x1; if (!status) @@ -1887,7 +1909,8 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode) static void bnx2x_calc_fc_adv(struct bnx2x *bp) { - switch (bp->link_vars.ieee_fc) { + switch (bp->link_vars.ieee_fc & + MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) { case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE: bp->port.advertising &= ~(ADVERTISED_Asym_Pause | ADVERTISED_Pause); @@ -1957,10 +1980,11 @@ static u8 bnx2x_initial_phy_init(struct bnx2x *bp) rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars); bnx2x_release_phy_lock(bp); + bnx2x_calc_fc_adv(bp); + if (bp->link_vars.link_up) bnx2x_link_report(bp); - bnx2x_calc_fc_adv(bp); return rc; } @@ -2220,9 +2244,7 @@ static void bnx2x_link_attn(struct bnx2x *bp) /* Make sure that we are synced with the current statistics */ bnx2x_stats_handle(bp, STATS_EVENT_STOP); - bnx2x_acquire_phy_lock(bp); bnx2x_link_update(&bp->link_params, &bp->link_vars); - bnx2x_release_phy_lock(bp); if (bp->link_vars.link_up) { @@ -2471,6 +2493,8 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted) if (asserted & ATTN_HARD_WIRED_MASK) { if (asserted & ATTN_NIG_FOR_FUNC) { + bnx2x_acquire_phy_lock(bp); + /* save nig interrupt mask */ bp->nig_mask = REG_RD(bp, nig_int_mask_addr); REG_WR(bp, nig_int_mask_addr, 0); @@ -2526,8 +2550,10 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted) REG_WR(bp, hc_addr, asserted); /* now set back the mask */ - if (asserted & ATTN_NIG_FOR_FUNC) + if (asserted & ATTN_NIG_FOR_FUNC) { REG_WR(bp, nig_int_mask_addr, bp->nig_mask); + bnx2x_release_phy_lock(bp); + } } static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn) @@ -2795,8 +2821,10 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted) static void bnx2x_attn_int(struct bnx2x *bp) { /* read local copy of bits */ - u32 attn_bits = bp->def_status_blk->atten_status_block.attn_bits; - u32 attn_ack = bp->def_status_blk->atten_status_block.attn_bits_ack; + u32 attn_bits = le32_to_cpu(bp->def_status_blk->atten_status_block. + attn_bits); + u32 attn_ack = le32_to_cpu(bp->def_status_blk->atten_status_block. + attn_bits_ack); u32 attn_state = bp->attn_state; /* look for changed bits */ @@ -2820,7 +2848,7 @@ static void bnx2x_attn_int(struct bnx2x *bp) static void bnx2x_sp_task(struct work_struct *work) { - struct bnx2x *bp = container_of(work, struct bnx2x, sp_task); + struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work); u16 status; @@ -2844,7 +2872,7 @@ static void bnx2x_sp_task(struct work_struct *work) if (status & 0x2) bp->stats_pending = 0; - bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, bp->def_att_idx, + bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, le16_to_cpu(bp->def_att_idx), IGU_INT_NOP, 1); bnx2x_ack_sb(bp, DEF_SB_ID, USTORM_ID, le16_to_cpu(bp->def_u_idx), IGU_INT_NOP, 1); @@ -2875,7 +2903,7 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) return IRQ_HANDLED; #endif - schedule_work(&bp->sp_task); + queue_delayed_work(bnx2x_wq, &bp->sp_task, 0); return IRQ_HANDLED; } @@ -2892,7 +2920,7 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance) #define ADD_64(s_hi, a_hi, s_lo, a_lo) \ do { \ s_lo += a_lo; \ - s_hi += a_hi + (s_lo < a_lo) ? 1 : 0; \ + s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \ } while (0) /* difference = minuend - subtrahend */ @@ -4496,7 +4524,7 @@ static void bnx2x_init_context(struct bnx2x *bp) static void bnx2x_init_ind_table(struct bnx2x *bp) { - int port = BP_PORT(bp); + int func = BP_FUNC(bp); int i; if (!is_multi(bp)) @@ -4505,10 +4533,8 @@ static void bnx2x_init_ind_table(struct bnx2x *bp) DP(NETIF_MSG_IFUP, "Initializing indirection table\n"); for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++) REG_WR8(bp, BAR_TSTRORM_INTMEM + - TSTORM_INDIRECTION_TABLE_OFFSET(port) + i, - i % bp->num_queues); - - REG_WR(bp, PRS_REG_A_PRSU_20, 0xf); + TSTORM_INDIRECTION_TABLE_OFFSET(func) + i, + BP_CL_ID(bp) + (i % bp->num_queues)); } static void bnx2x_set_client_config(struct bnx2x *bp) @@ -4517,12 +4543,12 @@ static void bnx2x_set_client_config(struct bnx2x *bp) int port = BP_PORT(bp); int i; - tstorm_client.mtu = bp->dev->mtu + ETH_OVREHEAD; + tstorm_client.mtu = bp->dev->mtu; tstorm_client.statistics_counter_id = BP_CL_ID(bp); tstorm_client.config_flags = TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE; #ifdef BCM_VLAN - if (bp->rx_mode && bp->vlgrp) { + if (bp->rx_mode && bp->vlgrp && (bp->flags & HW_VLAN_RX_FLAG)) { tstorm_client.config_flags |= TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE; DP(NETIF_MSG_IFUP, "vlan removal enabled\n"); @@ -4531,7 +4557,7 @@ static void bnx2x_set_client_config(struct bnx2x *bp) if (bp->flags & TPA_ENABLE_FLAG) { tstorm_client.max_sges_for_packet = - BCM_PAGE_ALIGN(tstorm_client.mtu) >> BCM_PAGE_SHIFT; + SGE_PAGE_ALIGN(tstorm_client.mtu) >> SGE_PAGE_SHIFT; tstorm_client.max_sges_for_packet = ((tstorm_client.max_sges_for_packet + PAGES_PER_SGE - 1) & (~(PAGES_PER_SGE - 1))) >> @@ -4714,10 +4740,11 @@ static void bnx2x_init_internal_func(struct bnx2x *bp) bp->e1hov); } - /* Init CQ ring mapping and aggregation size */ - max_agg_size = min((u32)(bp->rx_buf_size + - 8*BCM_PAGE_SIZE*PAGES_PER_SGE), - (u32)0xffff); + /* Init CQ ring mapping and aggregation size, the FW limit is 8 frags */ + max_agg_size = + min((u32)(min((u32)8, (u32)MAX_SKB_FRAGS) * + SGE_PAGE_SIZE * PAGES_PER_SGE), + (u32)0xffff); for_each_queue(bp, i) { struct bnx2x_fastpath *fp = &bp->fp[i]; @@ -4785,6 +4812,15 @@ static void bnx2x_nic_init(struct bnx2x *bp, u32 load_code) bnx2x_init_context(bp); bnx2x_init_internal(bp, load_code); bnx2x_init_ind_table(bp); + bnx2x_stats_init(bp); + + /* At this point, we are ready for interrupts */ + atomic_set(&bp->intr_sem, 0); + + /* flush all before enabling interrupts */ + mb(); + mmiowb(); + bnx2x_int_enable(bp); } @@ -5134,7 +5170,6 @@ static int bnx2x_init_common(struct bnx2x *bp) REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1); REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1); REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1); - REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 1); /* REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */ REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1); @@ -5212,6 +5247,7 @@ static int bnx2x_init_common(struct bnx2x *bp) } bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END); + REG_WR(bp, PRS_REG_A_PRSU_20, 0xf); /* set NIC mode */ REG_WR(bp, PRS_REG_NIC_MODE, 1); if (CHIP_IS_E1H(bp)) @@ -6393,17 +6429,8 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) } } - bnx2x_stats_init(bp); - bp->state = BNX2X_STATE_OPENING_WAIT4_PORT; - /* Enable Rx interrupt handling before sending the ramrod - as it's completed on Rx FP queue */ - bnx2x_napi_enable(bp); - - /* Enable interrupt handling */ - atomic_set(&bp->intr_sem, 0); - rc = bnx2x_setup_leading(bp); if (rc) { BNX2X_ERR("Setup leading failed!\n"); @@ -7501,7 +7528,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp) mutex_init(&bp->port.phy_mutex); - INIT_WORK(&bp->sp_task, bnx2x_sp_task); + INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task); INIT_WORK(&bp->reset_task, bnx2x_reset_task); rc = bnx2x_get_hwinfo(bp); @@ -8727,6 +8754,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) tx_bd->general_data = ((UNICAST_ADDRESS << ETH_TX_BD_ETH_ADDR_TYPE_SHIFT) | 1); + wmb(); + fp->hw_tx_prods->bds_prod = cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + 1); mb(); /* FW restriction: must not reorder writing nbd and packets */ @@ -8778,7 +8807,6 @@ test_loopback_rx_exit: /* Update producers */ bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod, fp->rx_sge_prod); - mmiowb(); /* keep prod updates ordered */ test_loopback_exit: bp->link_params.loopback_mode = LOOPBACK_NONE; @@ -9549,11 +9577,14 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) "sending pkt %u @%p next_idx %u bd %u @%p\n", pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_bd); - if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb)) { +#ifdef BCM_VLAN + if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) && + (bp->flags & HW_VLAN_TX_FLAG)) { tx_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb)); tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG; vlan_off += 4; } else +#endif tx_bd->vlan = cpu_to_le16(pkt_prod); if (xmit_type) { @@ -9705,6 +9736,15 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod); + /* + * Make sure that the BD data is updated before updating the producer + * since FW might read the BD right after the producer is updated. + * This is only applicable for weak-ordered memory model archs such + * as IA-64. The following barrier is also mandatory since FW will + * assumes packets must have BDs. + */ + wmb(); + fp->hw_tx_prods->bds_prod = cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + nbd); mb(); /* FW restriction: must not reorder writing nbd and packets */ @@ -9718,6 +9758,9 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) { + /* We want bnx2x_tx_int to "see" the updated tx_bd_prod + if we put Tx into XOFF state. */ + smp_mb(); netif_stop_queue(dev); bp->eth_stats.driver_xoff++; if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3) @@ -9987,6 +10030,16 @@ static void bnx2x_vlan_rx_register(struct net_device *dev, struct bnx2x *bp = netdev_priv(dev); bp->vlgrp = vlgrp; + + /* Set flags according to the required capabilities */ + bp->flags &= ~(HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG); + + if (dev->features & NETIF_F_HW_VLAN_TX) + bp->flags |= HW_VLAN_TX_FLAG; + + if (dev->features & NETIF_F_HW_VLAN_RX) + bp->flags |= HW_VLAN_RX_FLAG; + if (netif_running(dev)) bnx2x_set_client_config(bp); } @@ -10143,6 +10196,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev, dev->features |= NETIF_F_HIGHDMA; #ifdef BCM_VLAN dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); + bp->flags |= (HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG); #endif dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); dev->features |= NETIF_F_TSO6; @@ -10519,12 +10573,20 @@ static struct pci_driver bnx2x_pci_driver = { static int __init bnx2x_init(void) { + bnx2x_wq = create_singlethread_workqueue("bnx2x"); + if (bnx2x_wq == NULL) { + printk(KERN_ERR PFX "Cannot create workqueue\n"); + return -ENOMEM; + } + return pci_register_driver(&bnx2x_pci_driver); } static void __exit bnx2x_cleanup(void) { pci_unregister_driver(&bnx2x_pci_driver); + + destroy_workqueue(bnx2x_wq); } module_init(bnx2x_init); diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index e3131ea629cd..dfe92264e825 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -132,7 +132,7 @@ void ehea_dump(void *adr, int len, char *msg) int x; unsigned char *deb = adr; for (x = 0; x < len; x += 16) { - printk(DRV_NAME " %s adr=%p ofs=%04x %016lx %016lx\n", msg, + printk(DRV_NAME " %s adr=%p ofs=%04x %016llx %016llx\n", msg, deb, x, *((u64 *)&deb[0]), *((u64 *)&deb[8])); deb += 16; } @@ -883,7 +883,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param) while (eqe) { qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry); - ehea_error("QP aff_err: entry=0x%lx, token=0x%x", + ehea_error("QP aff_err: entry=0x%llx, token=0x%x", eqe->entry, qp_token); qp = port->port_res[qp_token].qp; @@ -1159,7 +1159,7 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe) netif_stop_queue(port->netdev); break; default: - ehea_error("unknown event code %x, eqe=0x%lX", ec, eqe); + ehea_error("unknown event code %x, eqe=0x%llX", ec, eqe); break; } } @@ -1971,7 +1971,7 @@ static void ehea_set_multicast_list(struct net_device *dev) } if (dev->mc_count > port->adapter->max_mc_mac) { - ehea_info("Mcast registration limit reached (0x%lx). " + ehea_info("Mcast registration limit reached (0x%llx). " "Use ALLMULTI!", port->adapter->max_mc_mac); goto out; diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 225c692b5d99..49d766ebbcf4 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c @@ -168,7 +168,7 @@ struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter, cq->fw_handle, rpage, 1); if (hret < H_SUCCESS) { ehea_error("register_rpage_cq failed ehea_cq=%p " - "hret=%lx counter=%i act_pages=%i", + "hret=%llx counter=%i act_pages=%i", cq, hret, counter, cq->attr.nr_pages); goto out_kill_hwq; } @@ -178,13 +178,13 @@ struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter, if ((hret != H_SUCCESS) || (vpage)) { ehea_error("registration of pages not " - "complete hret=%lx\n", hret); + "complete hret=%llx\n", hret); goto out_kill_hwq; } } else { if (hret != H_PAGE_REGISTERED) { ehea_error("CQ: registration of page failed " - "hret=%lx\n", hret); + "hret=%llx\n", hret); goto out_kill_hwq; } } @@ -986,15 +986,15 @@ void print_error_data(u64 *data) length = EHEA_PAGESIZE; if (type == 0x8) /* Queue Pair */ - ehea_error("QP (resource=%lX) state: AER=0x%lX, AERR=0x%lX, " - "port=%lX", resource, data[6], data[12], data[22]); + ehea_error("QP (resource=%llX) state: AER=0x%llX, AERR=0x%llX, " + "port=%llX", resource, data[6], data[12], data[22]); if (type == 0x4) /* Completion Queue */ - ehea_error("CQ (resource=%lX) state: AER=0x%lX", resource, + ehea_error("CQ (resource=%llX) state: AER=0x%llX", resource, data[6]); if (type == 0x3) /* Event Queue */ - ehea_error("EQ (resource=%lX) state: AER=0x%lX", resource, + ehea_error("EQ (resource=%llX) state: AER=0x%llX", resource, data[6]); ehea_dump(data, length, "error data"); @@ -1016,11 +1016,11 @@ void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle) rblock); if (ret == H_R_STATE) - ehea_error("No error data is available: %lX.", res_handle); + ehea_error("No error data is available: %llX.", res_handle); else if (ret == H_SUCCESS) print_error_data(rblock); else - ehea_error("Error data could not be fetched: %lX", res_handle); + ehea_error("Error data could not be fetched: %llX", res_handle); kfree(rblock); } diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 4e6a9195fe5f..ce900e54d8d1 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -795,6 +795,7 @@ static int fs_enet_open(struct net_device *dev) err = fs_init_phy(dev); if (err) { + free_irq(fep->interrupt, dev); if (fep->fpi->use_napi) napi_disable(&fep->napi); return err; diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index efcbeb6c8673..ea530673236e 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1622,10 +1622,18 @@ static int gfar_clean_tx_ring(struct net_device *dev) static void gfar_schedule_cleanup(struct net_device *dev) { struct gfar_private *priv = netdev_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&priv->txlock, flags); + spin_lock(&priv->rxlock); + if (netif_rx_schedule_prep(&priv->napi)) { gfar_write(&priv->regs->imask, IMASK_RTX_DISABLED); __netif_rx_schedule(&priv->napi); } + + spin_unlock(&priv->rxlock); + spin_unlock_irqrestore(&priv->txlock, flags); } /* Interrupt Handler for Transmit complete */ diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c index ecf9798987fa..2a2fc17b2878 100644 --- a/drivers/net/ibm_newemac/mal.c +++ b/drivers/net/ibm_newemac/mal.c @@ -613,7 +613,9 @@ static int __devinit mal_probe(struct of_device *ofdev, INIT_LIST_HEAD(&mal->list); spin_lock_init(&mal->lock); - netif_napi_add(NULL, &mal->napi, mal_poll, + init_dummy_netdev(&mal->dummy_dev); + + netif_napi_add(&mal->dummy_dev, &mal->napi, mal_poll, CONFIG_IBM_NEW_EMAC_POLL_WEIGHT); /* Load power-on reset defaults */ diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h index 2f0a87360844..9ededfbf0726 100644 --- a/drivers/net/ibm_newemac/mal.h +++ b/drivers/net/ibm_newemac/mal.h @@ -214,6 +214,8 @@ struct mal_instance { int index; spinlock_t lock; + struct net_device dummy_dev; + unsigned int features; }; diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index ca3bb9f7321b..dfa6348ac1dc 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -602,7 +602,7 @@ static int ibmveth_open(struct net_device *netdev) if(lpar_rc != H_SUCCESS) { ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc); - ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n", + ibmveth_error_printk("buffer TCE:0x%llx filter TCE:0x%llx rxq desc:0x%llx MAC:0x%llx\n", adapter->buffer_list_dma, adapter->filter_list_dma, rxq_desc.desc, @@ -1378,13 +1378,13 @@ static int ibmveth_show(struct seq_file *seq, void *v) seq_printf(seq, "Firmware MAC: %pM\n", firmware_mac); seq_printf(seq, "\nAdapter Statistics:\n"); - seq_printf(seq, " TX: vio_map_single failres: %ld\n", adapter->tx_map_failed); - seq_printf(seq, " send failures: %ld\n", adapter->tx_send_failed); - seq_printf(seq, " RX: replenish task cycles: %ld\n", adapter->replenish_task_cycles); - seq_printf(seq, " alloc_skb_failures: %ld\n", adapter->replenish_no_mem); - seq_printf(seq, " add buffer failures: %ld\n", adapter->replenish_add_buff_failure); - seq_printf(seq, " invalid buffers: %ld\n", adapter->rx_invalid_buffer); - seq_printf(seq, " no buffers: %ld\n", adapter->rx_no_buffer); + seq_printf(seq, " TX: vio_map_single failres: %lld\n", adapter->tx_map_failed); + seq_printf(seq, " send failures: %lld\n", adapter->tx_send_failed); + seq_printf(seq, " RX: replenish task cycles: %lld\n", adapter->replenish_task_cycles); + seq_printf(seq, " alloc_skb_failures: %lld\n", adapter->replenish_no_mem); + seq_printf(seq, " add buffer failures: %lld\n", adapter->replenish_add_buff_failure); + seq_printf(seq, " invalid buffers: %lld\n", adapter->rx_invalid_buffer); + seq_printf(seq, " no buffers: %lld\n", adapter->rx_no_buffer); return 0; } diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 29118f58a141..3a22dc41b656 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1073,7 +1073,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self) { unsigned int i; int ret; - char stir421x_fw_name[11]; + char stir421x_fw_name[12]; const struct firmware *fw; const unsigned char *fw_version_ptr; /* pointer to version string */ unsigned long fw_version = 0; diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index c7457f97259d..cb793c2bade2 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -429,7 +429,7 @@ SIMPLE_PORT_ATTR(promiscuous); SIMPLE_PORT_ATTR(num_mcast); CUSTOM_PORT_ATTR(lpar_map, "0x%X\n", port->lpar_map); CUSTOM_PORT_ATTR(stopped_map, "0x%X\n", port->stopped_map); -CUSTOM_PORT_ATTR(mac_addr, "0x%lX\n", port->mac_addr); +CUSTOM_PORT_ATTR(mac_addr, "0x%llX\n", port->mac_addr); #define GET_PORT_ATTR(_name) (&veth_port_attr_##_name.attr) static struct attribute *veth_port_default_attrs[] = { diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 4a5580c1126a..1d6e48e13366 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c @@ -84,7 +84,10 @@ #define KORINA_NUM_RDS 64 /* number of receive descriptors */ #define KORINA_NUM_TDS 64 /* number of transmit descriptors */ -#define KORINA_RBSIZE 536 /* size of one resource buffer = Ether MTU */ +/* KORINA_RBSIZE is the hardware's default maximum receive + * frame size in bytes. Having this hardcoded means that there + * is no support for MTU sizes greater than 1500. */ +#define KORINA_RBSIZE 1536 /* size of one resource buffer = Ether MTU */ #define KORINA_RDS_MASK (KORINA_NUM_RDS - 1) #define KORINA_TDS_MASK (KORINA_NUM_TDS - 1) #define RD_RING_SIZE (KORINA_NUM_RDS * sizeof(struct dma_desc)) @@ -196,7 +199,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) struct korina_private *lp = netdev_priv(dev); unsigned long flags; u32 length; - u32 chain_index; + u32 chain_prev, chain_next; struct dma_desc *td; spin_lock_irqsave(&lp->lock, flags); @@ -228,8 +231,8 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) /* Setup the transmit descriptor. */ dma_cache_inv((u32) td, sizeof(*td)); td->ca = CPHYSADDR(skb->data); - chain_index = (lp->tx_chain_tail - 1) & - KORINA_TDS_MASK; + chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; + chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) { if (lp->tx_chain_status == desc_empty) { @@ -237,7 +240,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) td->control = DMA_COUNT(length) | DMA_DESC_COF | DMA_DESC_IOF; /* Move tail */ - lp->tx_chain_tail = chain_index; + lp->tx_chain_tail = chain_next; /* Write to NDPTR */ writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), &lp->tx_dma_regs->dmandptr); @@ -248,12 +251,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) td->control = DMA_COUNT(length) | DMA_DESC_COF | DMA_DESC_IOF; /* Link to prev */ - lp->td_ring[chain_index].control &= + lp->td_ring[chain_prev].control &= ~DMA_DESC_COF; /* Link to prev */ - lp->td_ring[chain_index].link = CPHYSADDR(td); + lp->td_ring[chain_prev].link = CPHYSADDR(td); /* Move tail */ - lp->tx_chain_tail = chain_index; + lp->tx_chain_tail = chain_next; /* Write to NDPTR */ writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), &(lp->tx_dma_regs->dmandptr)); @@ -267,17 +270,16 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) td->control = DMA_COUNT(length) | DMA_DESC_COF | DMA_DESC_IOF; /* Move tail */ - lp->tx_chain_tail = chain_index; + lp->tx_chain_tail = chain_next; lp->tx_chain_status = desc_filled; - netif_stop_queue(dev); } else { /* Update tail */ td->control = DMA_COUNT(length) | DMA_DESC_COF | DMA_DESC_IOF; - lp->td_ring[chain_index].control &= + lp->td_ring[chain_prev].control &= ~DMA_DESC_COF; - lp->td_ring[chain_index].link = CPHYSADDR(td); - lp->tx_chain_tail = chain_index; + lp->td_ring[chain_prev].link = CPHYSADDR(td); + lp->tx_chain_tail = chain_next; } } dma_cache_wback((u32) td, sizeof(*td)); @@ -327,13 +329,13 @@ static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id) dmas = readl(&lp->rx_dma_regs->dmas); if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) { - netif_rx_schedule_prep(&lp->napi); - dmasm = readl(&lp->rx_dma_regs->dmasm); writel(dmasm | (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR), &lp->rx_dma_regs->dmasm); + netif_rx_schedule(&lp->napi); + if (dmas & DMA_STAT_ERR) printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name); @@ -350,15 +352,20 @@ static int korina_rx(struct net_device *dev, int limit) struct dma_desc *rd = &lp->rd_ring[lp->rx_next_done]; struct sk_buff *skb, *skb_new; u8 *pkt_buf; - u32 devcs, pkt_len, dmas, rx_free_desc; + u32 devcs, pkt_len, dmas; int count; dma_cache_inv((u32)rd, sizeof(*rd)); for (count = 0; count < limit; count++) { + skb = lp->rx_skb[lp->rx_next_done]; + skb_new = NULL; devcs = rd->devcs; + if ((KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) == 0) + break; + /* Update statistics counters */ if (devcs & ETH_RX_CRC) dev->stats.rx_crc_errors++; @@ -381,63 +388,55 @@ static int korina_rx(struct net_device *dev, int limit) * in Rc32434 (errata ref #077) */ dev->stats.rx_errors++; dev->stats.rx_dropped++; - } - - while ((rx_free_desc = KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) { - /* init the var. used for the later - * operations within the while loop */ - skb_new = NULL; + } else if ((devcs & ETH_RX_ROK)) { pkt_len = RCVPKT_LENGTH(devcs); - skb = lp->rx_skb[lp->rx_next_done]; - - if ((devcs & ETH_RX_ROK)) { - /* must be the (first and) last - * descriptor then */ - pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data; - - /* invalidate the cache */ - dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4); - - /* Malloc up new buffer. */ - skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2); - - if (!skb_new) - break; - /* Do not count the CRC */ - skb_put(skb, pkt_len - 4); - skb->protocol = eth_type_trans(skb, dev); - - /* Pass the packet to upper layers */ - netif_receive_skb(skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += pkt_len; - - /* Update the mcast stats */ - if (devcs & ETH_RX_MP) - dev->stats.multicast++; - - lp->rx_skb[lp->rx_next_done] = skb_new; - } - - rd->devcs = 0; - - /* Restore descriptor's curr_addr */ - if (skb_new) - rd->ca = CPHYSADDR(skb_new->data); - else - rd->ca = CPHYSADDR(skb->data); - - rd->control = DMA_COUNT(KORINA_RBSIZE) | - DMA_DESC_COD | DMA_DESC_IOD; - lp->rd_ring[(lp->rx_next_done - 1) & - KORINA_RDS_MASK].control &= - ~DMA_DESC_COD; - - lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; - dma_cache_wback((u32)rd, sizeof(*rd)); - rd = &lp->rd_ring[lp->rx_next_done]; - writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas); + + /* must be the (first and) last + * descriptor then */ + pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data; + + /* invalidate the cache */ + dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4); + + /* Malloc up new buffer. */ + skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2); + + if (!skb_new) + break; + /* Do not count the CRC */ + skb_put(skb, pkt_len - 4); + skb->protocol = eth_type_trans(skb, dev); + + /* Pass the packet to upper layers */ + netif_receive_skb(skb); + dev->stats.rx_packets++; + dev->stats.rx_bytes += pkt_len; + + /* Update the mcast stats */ + if (devcs & ETH_RX_MP) + dev->stats.multicast++; + + lp->rx_skb[lp->rx_next_done] = skb_new; } + + rd->devcs = 0; + + /* Restore descriptor's curr_addr */ + if (skb_new) + rd->ca = CPHYSADDR(skb_new->data); + else + rd->ca = CPHYSADDR(skb->data); + + rd->control = DMA_COUNT(KORINA_RBSIZE) | + DMA_DESC_COD | DMA_DESC_IOD; + lp->rd_ring[(lp->rx_next_done - 1) & + KORINA_RDS_MASK].control &= + ~DMA_DESC_COD; + + lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; + dma_cache_wback((u32)rd, sizeof(*rd)); + rd = &lp->rd_ring[lp->rx_next_done]; + writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas); } dmas = readl(&lp->rx_dma_regs->dmas); @@ -623,12 +622,12 @@ korina_tx_dma_interrupt(int irq, void *dev_id) dmas = readl(&lp->tx_dma_regs->dmas); if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) { - korina_tx(dev); - dmasm = readl(&lp->tx_dma_regs->dmasm); writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR), &lp->tx_dma_regs->dmasm); + korina_tx(dev); + if (lp->tx_chain_status == desc_filled && (readl(&(lp->tx_dma_regs->dmandptr)) == 0)) { writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]), @@ -901,6 +900,8 @@ static int korina_restart(struct net_device *dev) korina_free_ring(dev); + napi_disable(&lp->napi); + ret = korina_init(dev); if (ret < 0) { printk(KERN_ERR DRV_NAME "%s: cannot restart device\n", @@ -999,14 +1000,14 @@ static int korina_open(struct net_device *dev) * that handles the Done Finished * Ovr and Und Events */ ret = request_irq(lp->rx_irq, &korina_rx_dma_interrupt, - IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Rx", dev); + IRQF_DISABLED, "Korina ethernet Rx", dev); if (ret < 0) { printk(KERN_ERR DRV_NAME "%s: unable to get Rx DMA IRQ %d\n", dev->name, lp->rx_irq); goto err_release; } ret = request_irq(lp->tx_irq, &korina_tx_dma_interrupt, - IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Tx", dev); + IRQF_DISABLED, "Korina ethernet Tx", dev); if (ret < 0) { printk(KERN_ERR DRV_NAME "%s: unable to get Tx DMA IRQ %d\n", dev->name, lp->tx_irq); @@ -1015,7 +1016,7 @@ static int korina_open(struct net_device *dev) /* Install handler for overrun error. */ ret = request_irq(lp->ovr_irq, &korina_ovr_interrupt, - IRQF_SHARED | IRQF_DISABLED, "Ethernet Overflow", dev); + IRQF_DISABLED, "Ethernet Overflow", dev); if (ret < 0) { printk(KERN_ERR DRV_NAME"%s: unable to get OVR IRQ %d\n", dev->name, lp->ovr_irq); @@ -1024,7 +1025,7 @@ static int korina_open(struct net_device *dev) /* Install handler for underflow error. */ ret = request_irq(lp->und_irq, &korina_und_interrupt, - IRQF_SHARED | IRQF_DISABLED, "Ethernet Underflow", dev); + IRQF_DISABLED, "Ethernet Underflow", dev); if (ret < 0) { printk(KERN_ERR DRV_NAME "%s: unable to get UND IRQ %d\n", dev->name, lp->und_irq); @@ -1067,6 +1068,8 @@ static int korina_close(struct net_device *dev) korina_free_ring(dev); + napi_disable(&lp->napi); + free_irq(lp->rx_irq, dev); free_irq(lp->tx_irq, dev); free_irq(lp->ovr_irq, dev); @@ -1089,7 +1092,6 @@ static int korina_probe(struct platform_device *pdev) return -ENOMEM; } SET_NETDEV_DEV(dev, &pdev->dev); - platform_set_drvdata(pdev, dev); lp = netdev_priv(dev); bif->dev = dev; diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f8e601c51da7..c11c568fd7db 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -308,27 +308,16 @@ struct netxen_ring_ctx { #define netxen_set_cmd_desc_ctxid(cmd_desc, var) \ ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0)) -#define netxen_set_cmd_desc_flags(cmd_desc, val) \ - (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \ - ~cpu_to_le16(0x7f)) | cpu_to_le16((val) & 0x7f) -#define netxen_set_cmd_desc_opcode(cmd_desc, val) \ - (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \ - ~cpu_to_le16((u16)0x3f << 7)) | cpu_to_le16(((val) & 0x3f) << 7) - -#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \ - (cmd_desc)->num_of_buffers_total_length = \ - ((cmd_desc)->num_of_buffers_total_length & \ - ~cpu_to_le32(0xff)) | cpu_to_le32((val) & 0xff) -#define netxen_set_cmd_desc_totallength(cmd_desc, val) \ - (cmd_desc)->num_of_buffers_total_length = \ - ((cmd_desc)->num_of_buffers_total_length & \ - ~cpu_to_le32((u32)0xffffff << 8)) | \ - cpu_to_le32(((val) & 0xffffff) << 8) - -#define netxen_get_cmd_desc_opcode(cmd_desc) \ - ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003f) -#define netxen_get_cmd_desc_totallength(cmd_desc) \ - ((le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8) & 0xffffff) +#define netxen_set_tx_port(_desc, _port) \ + (_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0) + +#define netxen_set_tx_flags_opcode(_desc, _flags, _opcode) \ + (_desc)->flags_opcode = \ + cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)) + +#define netxen_set_tx_frags_len(_desc, _frags, _len) \ + (_desc)->num_of_buffers_total_length = \ + cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)) struct cmd_desc_type0 { u8 tcp_hdr_offset; /* For LSO only */ @@ -510,7 +499,8 @@ typedef enum { NETXEN_BRDTYPE_P3_10G_SFP_CT = 0x002a, NETXEN_BRDTYPE_P3_10G_SFP_QT = 0x002b, NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031, - NETXEN_BRDTYPE_P3_10G_XFP = 0x0032 + NETXEN_BRDTYPE_P3_10G_XFP = 0x0032, + NETXEN_BRDTYPE_P3_10G_TP = 0x0080 } netxen_brdtype_t; @@ -757,7 +747,7 @@ extern char netxen_nic_driver_name[]; */ struct netxen_skb_frag { u64 dma; - u32 length; + ulong length; }; #define _netxen_set_bits(config_word, start, bits, val) {\ @@ -783,13 +773,7 @@ struct netxen_skb_frag { struct netxen_cmd_buffer { struct sk_buff *skb; struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1]; - u32 total_length; - u32 mss; - u16 port; - u8 cmd; - u8 frag_count; - unsigned long time_stamp; - u32 state; + u32 frag_count; }; /* In rx_buffer, we do not need multiple fragments as is a single buffer */ @@ -876,7 +860,6 @@ struct nx_host_rds_ring { u32 skb_size; struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */ struct list_head free_list; - int begin_alloc; }; /* @@ -995,31 +978,31 @@ struct netxen_recv_context { */ typedef struct { - u64 host_phys_addr; /* Ring base addr */ - u32 ring_size; /* Ring entries */ - u16 msi_index; - u16 rsvd; /* Padding */ + __le64 host_phys_addr; /* Ring base addr */ + __le32 ring_size; /* Ring entries */ + __le16 msi_index; + __le16 rsvd; /* Padding */ } nx_hostrq_sds_ring_t; typedef struct { - u64 host_phys_addr; /* Ring base addr */ - u64 buff_size; /* Packet buffer size */ - u32 ring_size; /* Ring entries */ - u32 ring_kind; /* Class of ring */ + __le64 host_phys_addr; /* Ring base addr */ + __le64 buff_size; /* Packet buffer size */ + __le32 ring_size; /* Ring entries */ + __le32 ring_kind; /* Class of ring */ } nx_hostrq_rds_ring_t; typedef struct { - u64 host_rsp_dma_addr; /* Response dma'd here */ - u32 capabilities[4]; /* Flag bit vector */ - u32 host_int_crb_mode; /* Interrupt crb usage */ - u32 host_rds_crb_mode; /* RDS crb usage */ + __le64 host_rsp_dma_addr; /* Response dma'd here */ + __le32 capabilities[4]; /* Flag bit vector */ + __le32 host_int_crb_mode; /* Interrupt crb usage */ + __le32 host_rds_crb_mode; /* RDS crb usage */ /* These ring offsets are relative to data[0] below */ - u32 rds_ring_offset; /* Offset to RDS config */ - u32 sds_ring_offset; /* Offset to SDS config */ - u16 num_rds_rings; /* Count of RDS rings */ - u16 num_sds_rings; /* Count of SDS rings */ - u16 rsvd1; /* Padding */ - u16 rsvd2; /* Padding */ + __le32 rds_ring_offset; /* Offset to RDS config */ + __le32 sds_ring_offset; /* Offset to SDS config */ + __le16 num_rds_rings; /* Count of RDS rings */ + __le16 num_sds_rings; /* Count of SDS rings */ + __le16 rsvd1; /* Padding */ + __le16 rsvd2; /* Padding */ u8 reserved[128]; /* reserve space for future expansion*/ /* MUST BE 64-bit aligned. The following is packed: @@ -1029,24 +1012,24 @@ typedef struct { } nx_hostrq_rx_ctx_t; typedef struct { - u32 host_producer_crb; /* Crb to use */ - u32 rsvd1; /* Padding */ + __le32 host_producer_crb; /* Crb to use */ + __le32 rsvd1; /* Padding */ } nx_cardrsp_rds_ring_t; typedef struct { - u32 host_consumer_crb; /* Crb to use */ - u32 interrupt_crb; /* Crb to use */ + __le32 host_consumer_crb; /* Crb to use */ + __le32 interrupt_crb; /* Crb to use */ } nx_cardrsp_sds_ring_t; typedef struct { /* These ring offsets are relative to data[0] below */ - u32 rds_ring_offset; /* Offset to RDS config */ - u32 sds_ring_offset; /* Offset to SDS config */ - u32 host_ctx_state; /* Starting State */ - u32 num_fn_per_port; /* How many PCI fn share the port */ - u16 num_rds_rings; /* Count of RDS rings */ - u16 num_sds_rings; /* Count of SDS rings */ - u16 context_id; /* Handle for context */ + __le32 rds_ring_offset; /* Offset to RDS config */ + __le32 sds_ring_offset; /* Offset to SDS config */ + __le32 host_ctx_state; /* Starting State */ + __le32 num_fn_per_port; /* How many PCI fn share the port */ + __le16 num_rds_rings; /* Count of RDS rings */ + __le16 num_sds_rings; /* Count of SDS rings */ + __le16 context_id; /* Handle for context */ u8 phys_port; /* Physical id of port */ u8 virt_port; /* Virtual/Logical id of port */ u8 reserved[128]; /* save space for future expansion */ @@ -1072,34 +1055,34 @@ typedef struct { */ typedef struct { - u64 host_phys_addr; /* Ring base addr */ - u32 ring_size; /* Ring entries */ - u32 rsvd; /* Padding */ + __le64 host_phys_addr; /* Ring base addr */ + __le32 ring_size; /* Ring entries */ + __le32 rsvd; /* Padding */ } nx_hostrq_cds_ring_t; typedef struct { - u64 host_rsp_dma_addr; /* Response dma'd here */ - u64 cmd_cons_dma_addr; /* */ - u64 dummy_dma_addr; /* */ - u32 capabilities[4]; /* Flag bit vector */ - u32 host_int_crb_mode; /* Interrupt crb usage */ - u32 rsvd1; /* Padding */ - u16 rsvd2; /* Padding */ - u16 interrupt_ctl; - u16 msi_index; - u16 rsvd3; /* Padding */ + __le64 host_rsp_dma_addr; /* Response dma'd here */ + __le64 cmd_cons_dma_addr; /* */ + __le64 dummy_dma_addr; /* */ + __le32 capabilities[4]; /* Flag bit vector */ + __le32 host_int_crb_mode; /* Interrupt crb usage */ + __le32 rsvd1; /* Padding */ + __le16 rsvd2; /* Padding */ + __le16 interrupt_ctl; + __le16 msi_index; + __le16 rsvd3; /* Padding */ nx_hostrq_cds_ring_t cds_ring; /* Desc of cds ring */ u8 reserved[128]; /* future expansion */ } nx_hostrq_tx_ctx_t; typedef struct { - u32 host_producer_crb; /* Crb to use */ - u32 interrupt_crb; /* Crb to use */ + __le32 host_producer_crb; /* Crb to use */ + __le32 interrupt_crb; /* Crb to use */ } nx_cardrsp_cds_ring_t; typedef struct { - u32 host_ctx_state; /* Starting state */ - u16 context_id; /* Handle for context */ + __le32 host_ctx_state; /* Starting state */ + __le16 context_id; /* Handle for context */ u8 phys_port; /* Physical id of port */ u8 virt_port; /* Virtual/Logical id of port */ nx_cardrsp_cds_ring_t cds_ring; /* Card cds settings */ @@ -1202,9 +1185,9 @@ enum { #define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */ typedef struct { - u64 qhdr; - u64 req_hdr; - u64 words[6]; + __le64 qhdr; + __le64 req_hdr; + __le64 words[6]; } nx_nic_req_t; typedef struct { @@ -1486,8 +1469,6 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter); void netxen_initialize_adapter_ops(struct netxen_adapter *adapter); int netxen_init_firmware(struct netxen_adapter *adapter); -void netxen_tso_check(struct netxen_adapter *adapter, - struct cmd_desc_type0 *desc, struct sk_buff *skb); void netxen_nic_clear_stats(struct netxen_adapter *adapter); void netxen_watchdog_task(struct work_struct *work); void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, @@ -1496,6 +1477,7 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter); u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); void netxen_p2_nic_set_multi(struct net_device *netdev); void netxen_p3_nic_set_multi(struct net_device *netdev); +void netxen_p3_free_mac_list(struct netxen_adapter *adapter); int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32); int netxen_config_intr_coalesce(struct netxen_adapter *adapter); diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 64b51643c626..746bdb470418 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -76,7 +76,7 @@ netxen_api_unlock(struct netxen_adapter *adapter) static u32 netxen_poll_rsp(struct netxen_adapter *adapter) { - u32 raw_rsp, rsp = NX_CDRP_RSP_OK; + u32 rsp = NX_CDRP_RSP_OK; int timeout = 0; do { @@ -86,10 +86,7 @@ netxen_poll_rsp(struct netxen_adapter *adapter) if (++timeout > NX_OS_CRB_RETRY_COUNT) return NX_CDRP_RSP_TIMEOUT; - netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET, - &raw_rsp); - - rsp = le32_to_cpu(raw_rsp); + netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET, &rsp); } while (!NX_CDRP_IS_RSP(rsp)); return rsp; @@ -109,20 +106,16 @@ netxen_issue_cmd(struct netxen_adapter *adapter, if (netxen_api_lock(adapter)) return NX_RCODE_TIMEOUT; - netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET, - cpu_to_le32(signature)); + netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET, signature); - netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET, - cpu_to_le32(arg1)); + netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET, arg1); - netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET, - cpu_to_le32(arg2)); + netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET, arg2); - netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET, - cpu_to_le32(arg3)); + netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET, arg3); netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET, - cpu_to_le32(NX_CDRP_FORM_CMD(cmd))); + NX_CDRP_FORM_CMD(cmd)); rsp = netxen_poll_rsp(adapter); @@ -133,7 +126,6 @@ netxen_issue_cmd(struct netxen_adapter *adapter, rcode = NX_RCODE_TIMEOUT; } else if (rsp == NX_CDRP_RSP_FAIL) { netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode); - rcode = le32_to_cpu(rcode); printk(KERN_ERR "%s: failed card response code:0x%x\n", netxen_nic_driver_name, rcode); @@ -183,7 +175,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) int i, nrds_rings, nsds_rings; size_t rq_size, rsp_size; - u32 cap, reg; + u32 cap, reg, val; int err; @@ -225,11 +217,14 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) prq->num_rds_rings = cpu_to_le16(nrds_rings); prq->num_sds_rings = cpu_to_le16(nsds_rings); - prq->rds_ring_offset = 0; - prq->sds_ring_offset = prq->rds_ring_offset + + prq->rds_ring_offset = cpu_to_le32(0); + + val = le32_to_cpu(prq->rds_ring_offset) + (sizeof(nx_hostrq_rds_ring_t) * nrds_rings); + prq->sds_ring_offset = cpu_to_le32(val); - prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + prq->rds_ring_offset); + prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + + le32_to_cpu(prq->rds_ring_offset)); for (i = 0; i < nrds_rings; i++) { @@ -241,17 +236,14 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size); } - prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + prq->sds_ring_offset); + prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + + le32_to_cpu(prq->sds_ring_offset)); prq_sds[0].host_phys_addr = cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr); prq_sds[0].ring_size = cpu_to_le32(adapter->max_rx_desc_count); /* only one msix vector for now */ - prq_sds[0].msi_index = cpu_to_le32(0); - - /* now byteswap offsets */ - prq->rds_ring_offset = cpu_to_le32(prq->rds_ring_offset); - prq->sds_ring_offset = cpu_to_le32(prq->sds_ring_offset); + prq_sds[0].msi_index = cpu_to_le16(0); phys_addr = hostrq_phys_addr; err = netxen_issue_cmd(adapter, @@ -269,9 +261,9 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) prsp_rds = ((nx_cardrsp_rds_ring_t *) - &prsp->data[prsp->rds_ring_offset]); + &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]); - for (i = 0; i < le32_to_cpu(prsp->num_rds_rings); i++) { + for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) { rds_ring = &recv_ctx->rds_rings[i]; reg = le32_to_cpu(prsp_rds[i].host_producer_crb); @@ -279,7 +271,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) } prsp_sds = ((nx_cardrsp_sds_ring_t *) - &prsp->data[prsp->sds_ring_offset]); + &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]); reg = le32_to_cpu(prsp_sds[0].host_consumer_crb); recv_ctx->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200); @@ -288,7 +280,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); recv_ctx->context_id = le16_to_cpu(prsp->context_id); - recv_ctx->virt_port = le16_to_cpu(prsp->virt_port); + recv_ctx->virt_port = prsp->virt_port; out_free_rsp: pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr); diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index e45ce2951729..c0bd40fcf708 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -136,11 +136,9 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->port = PORT_TP; - if (netif_running(dev)) { - ecmd->speed = adapter->link_speed; - ecmd->duplex = adapter->link_duplex; - ecmd->autoneg = adapter->link_autoneg; - } + ecmd->speed = adapter->link_speed; + ecmd->duplex = adapter->link_duplex; + ecmd->autoneg = adapter->link_autoneg; } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { u32 val; @@ -171,7 +169,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) } else return -EIO; - ecmd->phy_address = adapter->portnum; + ecmd->phy_address = adapter->physical_port; ecmd->transceiver = XCVR_EXTERNAL; switch ((netxen_brdtype_t) boardinfo->board_type) { @@ -180,13 +178,13 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) case NETXEN_BRDTYPE_P3_REF_QG: case NETXEN_BRDTYPE_P3_4_GB: case NETXEN_BRDTYPE_P3_4_GB_MM: - case NETXEN_BRDTYPE_P3_10000_BASE_T: ecmd->supported |= SUPPORTED_Autoneg; ecmd->advertising |= ADVERTISED_Autoneg; case NETXEN_BRDTYPE_P2_SB31_10G_CX4: case NETXEN_BRDTYPE_P3_10G_CX4: case NETXEN_BRDTYPE_P3_10G_CX4_LP: + case NETXEN_BRDTYPE_P3_10000_BASE_T: ecmd->supported |= SUPPORTED_TP; ecmd->advertising |= ADVERTISED_TP; ecmd->port = PORT_TP; @@ -204,16 +202,33 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->port = PORT_FIBRE; ecmd->autoneg = AUTONEG_DISABLE; break; - case NETXEN_BRDTYPE_P2_SB31_10G: case NETXEN_BRDTYPE_P3_10G_SFP_PLUS: case NETXEN_BRDTYPE_P3_10G_SFP_CT: case NETXEN_BRDTYPE_P3_10G_SFP_QT: + ecmd->advertising |= ADVERTISED_TP; + ecmd->supported |= SUPPORTED_TP; + case NETXEN_BRDTYPE_P2_SB31_10G: case NETXEN_BRDTYPE_P3_10G_XFP: ecmd->supported |= SUPPORTED_FIBRE; ecmd->advertising |= ADVERTISED_FIBRE; ecmd->port = PORT_FIBRE; ecmd->autoneg = AUTONEG_DISABLE; break; + case NETXEN_BRDTYPE_P3_10G_TP: + if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP); + ecmd->advertising |= + (ADVERTISED_FIBRE | ADVERTISED_TP); + ecmd->port = PORT_FIBRE; + } else { + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg); + ecmd->advertising |= + (ADVERTISED_TP | ADVERTISED_Autoneg); + ecmd->port = PORT_TP; + } + break; default: printk(KERN_ERR "netxen-nic: Unsupported board model %d\n", (netxen_brdtype_t) boardinfo->board_type); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index aa6e603bfcbf..821cff68b3f3 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -503,17 +503,15 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, i = 0; + netif_tx_lock_bh(adapter->netdev); + producer = adapter->cmd_producer; do { cmd_desc = &cmd_desc_arr[i]; pbuf = &adapter->cmd_buf_arr[producer]; - pbuf->mss = 0; - pbuf->total_length = 0; pbuf->skb = NULL; - pbuf->cmd = 0; pbuf->frag_count = 0; - pbuf->port = 0; /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */ memcpy(&adapter->ahw.cmd_desc_head[producer], @@ -531,6 +529,8 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer); + netif_tx_unlock_bh(adapter->netdev); + return 0; } @@ -539,16 +539,19 @@ static int nx_p3_sre_macaddr_change(struct net_device *dev, { struct netxen_adapter *adapter = netdev_priv(dev); nx_nic_req_t req; - nx_mac_req_t mac_req; + nx_mac_req_t *mac_req; + u64 word; int rv; memset(&req, 0, sizeof(nx_nic_req_t)); - req.qhdr |= (NX_NIC_REQUEST << 23); - req.req_hdr |= NX_MAC_EVENT; - req.req_hdr |= ((u64)adapter->portnum << 16); - mac_req.op = op; - memcpy(&mac_req.mac_addr, addr, 6); - req.words[0] = cpu_to_le64(*(u64 *)&mac_req); + req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23); + + word = NX_MAC_EVENT | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + mac_req = (nx_mac_req_t *)&req.words[0]; + mac_req->op = op; + memcpy(mac_req->mac_addr, addr, 6); rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); if (rv != 0) { @@ -612,18 +615,35 @@ send_fw_cmd: int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode) { nx_nic_req_t req; + u64 word; memset(&req, 0, sizeof(nx_nic_req_t)); - req.qhdr |= (NX_HOST_REQUEST << 23); - req.req_hdr |= NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE; - req.req_hdr |= ((u64)adapter->portnum << 16); + req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); + + word = NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE | + ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + req.words[0] = cpu_to_le64(mode); return netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); } +void netxen_p3_free_mac_list(struct netxen_adapter *adapter) +{ + nx_mac_list_t *cur, *next; + + cur = adapter->mac_list; + + while (cur) { + next = cur->next; + kfree(cur); + cur = next; + } +} + #define NETXEN_CONFIG_INTR_COALESCE 3 /* @@ -632,13 +652,15 @@ int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode) int netxen_config_intr_coalesce(struct netxen_adapter *adapter) { nx_nic_req_t req; + u64 word; int rv; memset(&req, 0, sizeof(nx_nic_req_t)); - req.qhdr |= (NX_NIC_REQUEST << 23); - req.req_hdr |= NETXEN_CONFIG_INTR_COALESCE; - req.req_hdr |= ((u64)adapter->portnum << 16); + req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23); + + word = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal)); @@ -772,13 +794,10 @@ int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4); adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4); - mac_hi = cpu_to_le32(mac_hi); - mac_lo = cpu_to_le32(mac_lo); - if (pci_func & 1) - *mac = ((mac_lo >> 16) | ((u64)mac_hi << 16)); + *mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16)); else - *mac = ((mac_lo) | ((u64)mac_hi << 32)); + *mac = le64_to_cpu((u64)mac_lo | ((u64)mac_hi << 32)); return 0; } @@ -937,7 +956,7 @@ int netxen_load_firmware(struct netxen_adapter *adapter) { int i; u32 data, size = 0; - u32 flashaddr = NETXEN_BOOTLD_START, memaddr = NETXEN_BOOTLD_START; + u32 flashaddr = NETXEN_BOOTLD_START; size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4; @@ -949,10 +968,8 @@ int netxen_load_firmware(struct netxen_adapter *adapter) if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) return -EIO; - adapter->pci_mem_write(adapter, memaddr, &data, 4); + adapter->pci_mem_write(adapter, flashaddr, &data, 4); flashaddr += 4; - memaddr += 4; - cond_resched(); } msleep(1); @@ -2034,7 +2051,13 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) rv = -1; } - DPRINTK(INFO, "Discovered board type:0x%x ", boardinfo->board_type); + if (boardinfo->board_type == NETXEN_BRDTYPE_P3_4_GB_MM) { + u32 gpio = netxen_nic_reg_read(adapter, + NETXEN_ROMUSB_GLB_PAD_GPIO_I); + if ((gpio & 0x8000) == 0) + boardinfo->board_type = NETXEN_BRDTYPE_P3_10G_TP; + } + switch ((netxen_brdtype_t) boardinfo->board_type) { case NETXEN_BRDTYPE_P2_SB35_4G: adapter->ahw.board_type = NETXEN_NIC_GBE; @@ -2053,7 +2076,6 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_10G_SFP_QT: case NETXEN_BRDTYPE_P3_10G_XFP: case NETXEN_BRDTYPE_P3_10000_BASE_T: - adapter->ahw.board_type = NETXEN_NIC_XGBE; break; case NETXEN_BRDTYPE_P1_BD: @@ -2063,9 +2085,12 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_REF_QG: case NETXEN_BRDTYPE_P3_4_GB: case NETXEN_BRDTYPE_P3_4_GB_MM: - adapter->ahw.board_type = NETXEN_NIC_GBE; break; + case NETXEN_BRDTYPE_P3_10G_TP: + adapter->ahw.board_type = (adapter->portnum < 2) ? + NETXEN_NIC_XGBE : NETXEN_NIC_GBE; + break; default: printk("%s: Unknown(%x)\n", netxen_nic_driver_name, boardinfo->board_type); @@ -2110,12 +2135,16 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) { __u32 status; __u32 autoneg; - __u32 mode; __u32 port_mode; - netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode); - if (netxen_get_niu_enable_ge(mode)) { /* Gb 10/100/1000 Mbps mode */ + if (!netif_carrier_ok(adapter->netdev)) { + adapter->link_speed = 0; + adapter->link_duplex = -1; + adapter->link_autoneg = AUTONEG_ENABLE; + return; + } + if (adapter->ahw.board_type == NETXEN_NIC_GBE) { adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR, &port_mode, 4); if (port_mode == NETXEN_PORT_MODE_802_3_AP) { @@ -2141,7 +2170,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) adapter->link_speed = SPEED_1000; break; default: - adapter->link_speed = -1; + adapter->link_speed = 0; break; } switch (netxen_get_phy_duplex(status)) { @@ -2164,7 +2193,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) goto link_down; } else { link_down: - adapter->link_speed = -1; + adapter->link_speed = 0; adapter->link_duplex = -1; } } diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index d924468e506e..ca7c8d8050c9 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -308,7 +308,6 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) } memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE); INIT_LIST_HEAD(&rds_ring->free_list); - rds_ring->begin_alloc = 0; /* * Now go through all of them, set reference handles * and put them in the queues. @@ -439,6 +438,8 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter) long timeout = 0; long done = 0; + cond_resched(); + while (done == 0) { done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS); done &= 2; @@ -533,12 +534,9 @@ static int do_rom_fast_write(struct netxen_adapter *adapter, int addr, static int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { - cond_resched(); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); - udelay(100); /* prevent bursting on CRB */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); if (netxen_wait_rom_done(adapter)) { printk("Error waiting for rom done\n"); @@ -546,7 +544,7 @@ static int do_rom_fast_read(struct netxen_adapter *adapter, } /* reset abyte_cnt and dummy_byte_cnt */ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); - udelay(100); /* prevent bursting on CRB */ + udelay(10); netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA); @@ -884,14 +882,16 @@ int netxen_flash_unlock(struct netxen_adapter *adapter) int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) { int addr, val; - int i, init_delay = 0; + int i, n, init_delay = 0; struct crb_addr_pair *buf; - unsigned offset, n; + unsigned offset; u32 off; /* resetall */ + rom_lock(adapter); netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff); + netxen_rom_unlock(adapter); if (verbose) { if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0) @@ -910,7 +910,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { if (netxen_rom_fast_read(adapter, 0, &n) != 0 || - (n != 0xcafecafeUL) || + (n != 0xcafecafe) || netxen_rom_fast_read(adapter, 4, &n) != 0) { printk(KERN_ERR "%s: ERROR Reading crb_init area: " "n: %08x\n", netxen_nic_driver_name, n); @@ -975,6 +975,14 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) /* do not reset PCI */ if (off == (ROMUSB_GLB + 0xbc)) continue; + if (off == (ROMUSB_GLB + 0xa8)) + continue; + if (off == (ROMUSB_GLB + 0xc8)) /* core clock */ + continue; + if (off == (ROMUSB_GLB + 0x24)) /* MN clock */ + continue; + if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */ + continue; if (off == (NETXEN_CRB_PEG_NET_1 + 0x18)) buf[i].data = 0x1020; /* skip the function enable register */ @@ -992,23 +1000,21 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) continue; } + init_delay = 1; /* After writing this register, HW needs time for CRB */ /* to quiet down (else crb_window returns 0xffffffff) */ if (off == NETXEN_ROMUSB_GLB_SW_RESET) { - init_delay = 1; + init_delay = 1000; if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { /* hold xdma in reset also */ buf[i].data = NETXEN_NIC_XDMA_RESET; + buf[i].data = 0x8000ff; } } adapter->hw_write_wx(adapter, off, &buf[i].data, 4); - if (init_delay == 1) { - msleep(1000); - init_delay = 0; - } - msleep(1); + msleep(init_delay); } kfree(buf); @@ -1277,7 +1283,7 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, dev_kfree_skb_any(skb); for (i = 0; i < nr_frags; i++) { - index = frag_desc->frag_handles[i]; + index = le16_to_cpu(frag_desc->frag_handles[i]); skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum); if (skb) @@ -1428,7 +1434,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) struct rcv_desc *pdesc; struct netxen_rx_buffer *buffer; int count = 0; - int index = 0; netxen_ctx_msg msg = 0; dma_addr_t dma; struct list_head *head; @@ -1436,7 +1441,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) rds_ring = &recv_ctx->rds_rings[ringid]; producer = rds_ring->producer; - index = rds_ring->begin_alloc; head = &rds_ring->free_list; /* We can start writing rx descriptors into the phantom memory. */ @@ -1444,39 +1448,37 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) skb = dev_alloc_skb(rds_ring->skb_size); if (unlikely(!skb)) { - rds_ring->begin_alloc = index; break; } + if (!adapter->ahw.cut_through) + skb_reserve(skb, 2); + + dma = pci_map_single(pdev, skb->data, + rds_ring->dma_size, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, dma)) { + dev_kfree_skb_any(skb); + break; + } + + count++; buffer = list_entry(head->next, struct netxen_rx_buffer, list); list_del(&buffer->list); - count++; /* now there should be no failure */ - pdesc = &rds_ring->desc_head[producer]; - - if (!adapter->ahw.cut_through) - skb_reserve(skb, 2); - /* This will be setup when we receive the - * buffer after it has been filled FSL TBD TBD - * skb->dev = netdev; - */ - dma = pci_map_single(pdev, skb->data, rds_ring->dma_size, - PCI_DMA_FROMDEVICE); - pdesc->addr_buffer = cpu_to_le64(dma); buffer->skb = skb; buffer->state = NETXEN_BUFFER_BUSY; buffer->dma = dma; + /* make a rcv descriptor */ + pdesc = &rds_ring->desc_head[producer]; + pdesc->addr_buffer = cpu_to_le64(dma); pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); - DPRINTK(INFO, "done writing descripter\n"); - producer = - get_next_index(producer, rds_ring->max_rx_desc_count); - index = get_next_index(index, rds_ring->max_rx_desc_count); + + producer = get_next_index(producer, rds_ring->max_rx_desc_count); } /* if we did allocate buffers, then write the count to Phantom */ if (count) { - rds_ring->begin_alloc = index; rds_ring->producer = producer; /* Window = 1 */ adapter->pci_write_normalize(adapter, @@ -1515,49 +1517,50 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, struct rcv_desc *pdesc; struct netxen_rx_buffer *buffer; int count = 0; - int index = 0; struct list_head *head; + dma_addr_t dma; rds_ring = &recv_ctx->rds_rings[ringid]; producer = rds_ring->producer; - index = rds_ring->begin_alloc; head = &rds_ring->free_list; /* We can start writing rx descriptors into the phantom memory. */ while (!list_empty(head)) { skb = dev_alloc_skb(rds_ring->skb_size); if (unlikely(!skb)) { - rds_ring->begin_alloc = index; break; } + if (!adapter->ahw.cut_through) + skb_reserve(skb, 2); + + dma = pci_map_single(pdev, skb->data, + rds_ring->dma_size, PCI_DMA_FROMDEVICE); + if (pci_dma_mapping_error(pdev, dma)) { + dev_kfree_skb_any(skb); + break; + } + + count++; buffer = list_entry(head->next, struct netxen_rx_buffer, list); list_del(&buffer->list); - count++; /* now there should be no failure */ - pdesc = &rds_ring->desc_head[producer]; - if (!adapter->ahw.cut_through) - skb_reserve(skb, 2); buffer->skb = skb; buffer->state = NETXEN_BUFFER_BUSY; - buffer->dma = pci_map_single(pdev, skb->data, - rds_ring->dma_size, - PCI_DMA_FROMDEVICE); + buffer->dma = dma; /* make a rcv descriptor */ + pdesc = &rds_ring->desc_head[producer]; pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); pdesc->addr_buffer = cpu_to_le64(buffer->dma); - producer = - get_next_index(producer, rds_ring->max_rx_desc_count); - index = get_next_index(index, rds_ring->max_rx_desc_count); - buffer = &rds_ring->rx_buf_arr[index]; + + producer = get_next_index(producer, rds_ring->max_rx_desc_count); } /* if we did allocate buffers, then write the count to Phantom */ if (count) { - rds_ring->begin_alloc = index; rds_ring->producer = producer; /* Window = 1 */ adapter->pci_write_normalize(adapter, diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index ba01524b5531..86867405a367 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -39,6 +39,7 @@ #include "netxen_nic_phan_reg.h" #include <linux/dma-mapping.h> +#include <linux/if_vlan.h> #include <net/ip.h> MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); @@ -242,7 +243,7 @@ static void netxen_check_options(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_4_GB: case NETXEN_BRDTYPE_P3_4_GB_MM: adapter->msix_supported = !!use_msi_x; - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; + adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; break; case NETXEN_BRDTYPE_P2_SB35_4G: @@ -251,6 +252,14 @@ static void netxen_check_options(struct netxen_adapter *adapter) adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; break; + case NETXEN_BRDTYPE_P3_10G_TP: + adapter->msix_supported = !!use_msi_x; + if (adapter->ahw.board_type == NETXEN_NIC_XGBE) + adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; + else + adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; + break; + default: adapter->msix_supported = 0; adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; @@ -271,10 +280,15 @@ static void netxen_check_options(struct netxen_adapter *adapter) static int netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot) { - int ret = 0; + u32 val, timeout; if (first_boot == 0x55555555) { /* This is the first boot after power up */ + adapter->pci_write_normalize(adapter, + NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); + + if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 0; /* PCI bus master workaround */ adapter->hw_read_wx(adapter, @@ -294,18 +308,26 @@ netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot) /* clear the register for future unloads/loads */ adapter->pci_write_normalize(adapter, NETXEN_CAM_RAM(0x1fc), 0); - ret = -1; + return -EIO; } - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - /* Start P2 boot loader */ - adapter->pci_write_normalize(adapter, - NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); - adapter->pci_write_normalize(adapter, - NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1); - } + /* Start P2 boot loader */ + val = adapter->pci_read_normalize(adapter, + NETXEN_ROMUSB_GLB_PEGTUNE_DONE); + adapter->pci_write_normalize(adapter, + NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1); + timeout = 0; + do { + msleep(1); + val = adapter->pci_read_normalize(adapter, + NETXEN_CAM_RAM(0x1fc)); + + if (++timeout > 5000) + return -EIO; + + } while (val == NETXEN_BDINFO_MAGIC); } - return ret; + return 0; } static void netxen_set_port_mode(struct netxen_adapter *adapter) @@ -784,8 +806,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) CRB_CMDPEG_STATE, 0); netxen_pinit_from_rom(adapter, 0); msleep(1); - netxen_load_firmware(adapter); } + netxen_load_firmware(adapter); if (NX_IS_REVISION_P3(revision_id)) netxen_pcie_strap_init(adapter); @@ -801,13 +823,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } - if ((first_boot == 0x55555555) && - (NX_IS_REVISION_P2(revision_id))) { - /* Unlock the HW, prompting the boot sequence */ - adapter->pci_write_normalize(adapter, - NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1); - } - err = netxen_initialize_adapter_offload(adapter); if (err) goto err_out_iounmap; @@ -821,7 +836,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i); /* Handshake with the card before we register the devices. */ - netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); + err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); + if (err) + goto err_out_free_offload; } /* first_driver */ @@ -925,6 +942,7 @@ err_out_disable_msi: if (adapter->flags & NETXEN_NIC_MSI_ENABLED) pci_disable_msi(pdev); +err_out_free_offload: if (first_driver) netxen_free_adapter_offload(adapter); @@ -968,6 +986,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_free_hw_resources(adapter); netxen_release_rx_buffers(adapter); netxen_free_sw_resources(adapter); + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netxen_p3_free_mac_list(adapter); } if (adapter->portnum == 0) @@ -1137,29 +1158,64 @@ static int netxen_nic_close(struct net_device *netdev) return 0; } -void netxen_tso_check(struct netxen_adapter *adapter, +static bool netxen_tso_check(struct net_device *netdev, struct cmd_desc_type0 *desc, struct sk_buff *skb) { - if (desc->mss) { - desc->total_hdr_length = (sizeof(struct ethhdr) + - ip_hdrlen(skb) + tcp_hdrlen(skb)); + bool tso = false; + u8 opcode = TX_ETHER_PKT; - if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) && - (skb->protocol == htons(ETH_P_IPV6))) - netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6); - else - netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO); + if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && + skb_shinfo(skb)->gso_size > 0) { + + desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); + desc->total_hdr_length = + skb_transport_offset(skb) + tcp_hdrlen(skb); + + opcode = (skb->protocol == htons(ETH_P_IPV6)) ? + TX_TCP_LSO6 : TX_TCP_LSO; + tso = true; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - if (ip_hdr(skb)->protocol == IPPROTO_TCP) - netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT); - else if (ip_hdr(skb)->protocol == IPPROTO_UDP) - netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT); - else - return; + u8 l4proto; + + if (skb->protocol == htons(ETH_P_IP)) { + l4proto = ip_hdr(skb)->protocol; + + if (l4proto == IPPROTO_TCP) + opcode = TX_TCP_PKT; + else if(l4proto == IPPROTO_UDP) + opcode = TX_UDP_PKT; + } else if (skb->protocol == htons(ETH_P_IPV6)) { + l4proto = ipv6_hdr(skb)->nexthdr; + + if (l4proto == IPPROTO_TCP) + opcode = TX_TCPV6_PKT; + else if(l4proto == IPPROTO_UDP) + opcode = TX_UDPV6_PKT; + } } desc->tcp_hdr_offset = skb_transport_offset(skb); desc->ip_hdr_offset = skb_network_offset(skb); + netxen_set_tx_flags_opcode(desc, 0, opcode); + return tso; +} + +static void +netxen_clean_tx_dma_mapping(struct pci_dev *pdev, + struct netxen_cmd_buffer *pbuf, int last) +{ + int k; + struct netxen_skb_frag *buffrag; + + buffrag = &pbuf->frag_array[0]; + pci_unmap_single(pdev, buffrag->dma, + buffrag->length, PCI_DMA_TODEVICE); + + for (k = 1; k < last; k++) { + buffrag = &pbuf->frag_array[k]; + pci_unmap_page(pdev, buffrag->dma, + buffrag->length, PCI_DMA_TODEVICE); + } } static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) @@ -1167,33 +1223,22 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct netxen_adapter *adapter = netdev_priv(netdev); struct netxen_hardware_context *hw = &adapter->ahw; unsigned int first_seg_len = skb->len - skb->data_len; + struct netxen_cmd_buffer *pbuf; struct netxen_skb_frag *buffrag; - unsigned int i; + struct cmd_desc_type0 *hwdesc; + struct pci_dev *pdev = adapter->pdev; + dma_addr_t temp_dma; + int i, k; u32 producer, consumer; - u32 saved_producer = 0; - struct cmd_desc_type0 *hwdesc; - int k; - struct netxen_cmd_buffer *pbuf = NULL; - int frag_count; - int no_of_desc; + int frag_count, no_of_desc; u32 num_txd = adapter->max_tx_desc_count; + bool is_tso = false; frag_count = skb_shinfo(skb)->nr_frags + 1; /* There 4 fragments per descriptor */ no_of_desc = (frag_count + 3) >> 2; - if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { - if (skb_shinfo(skb)->gso_size > 0) { - - no_of_desc++; - if ((ip_hdrlen(skb) + tcp_hdrlen(skb) + - sizeof(struct ethhdr)) > - (sizeof(struct cmd_desc_type0) - 2)) { - no_of_desc++; - } - } - } producer = adapter->cmd_producer; smp_mb(); @@ -1205,34 +1250,26 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } /* Copy the descriptors into the hardware */ - saved_producer = producer; hwdesc = &hw->cmd_desc_head[producer]; memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); /* Take skb->data itself */ pbuf = &adapter->cmd_buf_arr[producer]; - if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && - skb_shinfo(skb)->gso_size > 0) { - pbuf->mss = skb_shinfo(skb)->gso_size; - hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); - } else { - pbuf->mss = 0; - hwdesc->mss = 0; - } - pbuf->total_length = skb->len; + + is_tso = netxen_tso_check(netdev, hwdesc, skb); + pbuf->skb = skb; - pbuf->cmd = TX_ETHER_PKT; pbuf->frag_count = frag_count; - pbuf->port = adapter->portnum; buffrag = &pbuf->frag_array[0]; - buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len, + temp_dma = pci_map_single(pdev, skb->data, first_seg_len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, temp_dma)) + goto drop_packet; + + buffrag->dma = temp_dma; buffrag->length = first_seg_len; - netxen_set_cmd_desc_totallength(hwdesc, skb->len); - netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count); - netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT); + netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); + netxen_set_tx_port(hwdesc, adapter->portnum); - netxen_set_cmd_desc_port(hwdesc, adapter->portnum); - netxen_set_cmd_desc_ctxid(hwdesc, adapter->portnum); hwdesc->buffer1_length = cpu_to_le16(first_seg_len); hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); @@ -1240,7 +1277,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct skb_frag_struct *frag; int len, temp_len; unsigned long offset; - dma_addr_t temp_dma; /* move to next desc. if there is a need */ if ((i & 0x3) == 0) { @@ -1256,8 +1292,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) offset = frag->page_offset; temp_len = len; - temp_dma = pci_map_page(adapter->pdev, frag->page, offset, + temp_dma = pci_map_page(pdev, frag->page, offset, len, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, temp_dma)) { + netxen_clean_tx_dma_mapping(pdev, pbuf, i); + goto drop_packet; + } buffrag++; buffrag->dma = temp_dma; @@ -1285,16 +1325,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } producer = get_next_index(producer, num_txd); - /* might change opcode to TX_TCP_LSO */ - netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb); - /* For LSO, we need to copy the MAC/IP/TCP headers into * the descriptor ring */ - if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer]) - == TX_TCP_LSO) { + if (is_tso) { int hdr_len, first_hdr_len, more_hdr; - hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length; + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) { first_hdr_len = sizeof(struct cmd_desc_type0) - 2; more_hdr = 1; @@ -1336,6 +1372,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) netdev->trans_start = jiffies; return NETDEV_TX_OK; + +drop_packet: + adapter->stats.txdropped++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } static int netxen_nic_check_temp(struct netxen_adapter *adapter) @@ -1407,6 +1448,8 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netif_carrier_off(netdev); netif_stop_queue(netdev); } + + netxen_nic_set_link_parameters(adapter); } else if (!adapter->ahw.linkup && linkup) { printk(KERN_INFO "%s: %s NIC Link is up\n", netxen_nic_driver_name, netdev->name); @@ -1415,6 +1458,8 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netif_carrier_on(netdev); netif_wake_queue(netdev); } + + netxen_nic_set_link_parameters(adapter); } } diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index 5b7a574ce571..d0349e7d73ea 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c @@ -712,7 +712,7 @@ static inline void pasemi_mac_rx_error(const struct pasemi_mac *mac, rcmdsta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if)); ccmdsta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno)); - printk(KERN_ERR "pasemi_mac: rx error. macrx %016lx, rx status %lx\n", + printk(KERN_ERR "pasemi_mac: rx error. macrx %016llx, rx status %llx\n", macrx, *chan->status); printk(KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n", @@ -730,8 +730,8 @@ static inline void pasemi_mac_tx_error(const struct pasemi_mac *mac, cmdsta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno)); - printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016lx, "\ - "tx status 0x%016lx\n", mactx, *chan->status); + printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016llx, "\ + "tx status 0x%016llx\n", mactx, *chan->status); printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta); } diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index e35460165bf7..0a06e4fd37d9 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -231,15 +231,6 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr) if ((phy_id & 0x1fffffff) == 0x1fffffff) return NULL; - /* - * Broken hardware is sometimes missing the pull-up resistor on the - * MDIO line, which results in reads to non-existent devices returning - * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent - * device as well. - */ - if (phy_id == 0) - return NULL; - dev = phy_device_create(bus, addr, phy_id); return dev; diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 06b448285eb5..7b2728b8f1b7 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -250,6 +250,7 @@ static int ppp_connect_channel(struct channel *pch, int unit); static int ppp_disconnect_channel(struct channel *pch); static void ppp_destroy_channel(struct channel *pch); static int unit_get(struct idr *p, void *ptr); +static int unit_set(struct idr *p, void *ptr, int n); static void unit_put(struct idr *p, int n); static void *unit_find(struct idr *p, int n); @@ -2432,11 +2433,18 @@ ppp_create_interface(int unit, int *retp) } else { if (unit_find(&ppp_units_idr, unit)) goto out2; /* unit already exists */ - else { - /* darn, someone is cheating us? */ - *retp = -EINVAL; + /* + * if caller need a specified unit number + * lets try to satisfy him, otherwise -- + * he should better ask us for new unit number + * + * NOTE: yes I know that returning EEXIST it's not + * fair but at least pppd will ask us to allocate + * new unit in this case so user is happy :) + */ + unit = unit_set(&ppp_units_idr, ppp, unit); + if (unit < 0) goto out2; - } } /* Initialize the new ppp unit */ @@ -2677,14 +2685,37 @@ static void __exit ppp_cleanup(void) * by holding all_ppp_mutex */ +/* associate pointer with specified number */ +static int unit_set(struct idr *p, void *ptr, int n) +{ + int unit, err; + +again: + if (!idr_pre_get(p, GFP_KERNEL)) { + printk(KERN_ERR "PPP: No free memory for idr\n"); + return -ENOMEM; + } + + err = idr_get_new_above(p, ptr, n, &unit); + if (err == -EAGAIN) + goto again; + + if (unit != n) { + idr_remove(p, unit); + return -EINVAL; + } + + return unit; +} + /* get new free unit number and associate pointer with it */ static int unit_get(struct idr *p, void *ptr) { int unit, err; again: - if (idr_pre_get(p, GFP_KERNEL) == 0) { - printk(KERN_ERR "Out of memory expanding drawable idr\n"); + if (!idr_pre_get(p, GFP_KERNEL)) { + printk(KERN_ERR "PPP: No free memory for idr\n"); return -ENOMEM; } diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 6cbefcae9ac2..be4465bc0a69 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -509,10 +509,10 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev, else ret = sis900_get_mac_addr(pci_dev, net_dev); - if (ret == 0) { - printk(KERN_WARNING "%s: Cannot read MAC address.\n", dev_name); - ret = -ENODEV; - goto err_unmap_rx; + if (!ret || !is_valid_ether_addr(net_dev->dev_addr)) { + random_ether_addr(net_dev->dev_addr); + printk(KERN_WARNING "%s: Unreadable or invalid MAC address," + "using random generated one\n", dev_name); } /* 630ET : set the mii access mode as software-mode */ diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index c4918b86ed19..0d0fa91c0251 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1297,6 +1297,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) /* setup */ spin_lock_irq(&serial->serial_lock); tty->driver_data = serial; + tty_kref_put(serial->tty); serial->tty = tty_kref_get(tty); spin_unlock_irq(&serial->serial_lock); @@ -1792,8 +1793,8 @@ static int mux_device_request(struct hso_serial *serial, u8 type, u16 port, /* initialize */ ctrl_req->wValue = 0; - ctrl_req->wIndex = hso_port_to_mux(port); - ctrl_req->wLength = size; + ctrl_req->wIndex = cpu_to_le16(hso_port_to_mux(port)); + ctrl_req->wLength = cpu_to_le16(size); if (type == USB_CDC_GET_ENCAPSULATED_RESPONSE) { /* Reading command */ @@ -2043,9 +2044,8 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) return -2; } - spin_lock(&serial->serial_lock); + /* All callers to put_rxbuf_data hold serial_lock */ tty = tty_kref_get(serial->tty); - spin_unlock(&serial->serial_lock); /* Push data to tty */ if (tty) { @@ -2053,8 +2053,10 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) serial->curr_rx_urb_offset; D1("data to push to tty"); while (write_length_remaining) { - if (test_bit(TTY_THROTTLED, &tty->flags)) + if (test_bit(TTY_THROTTLED, &tty->flags)) { + tty_kref_put(tty); return -1; + } curr_write_len = tty_insert_flip_string (tty, urb->transfer_buffer + serial->curr_rx_urb_offset, diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 2dc241689d37..0dbd85b0162d 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -622,7 +622,7 @@ static void hss_hdlc_rx_irq(void *pdev) printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name); #endif qmgr_disable_irq(queue_ids[port->id].rx); - netif_rx_schedule(dev, &port->napi); + netif_rx_schedule(&port->napi); } static int hss_hdlc_poll(struct napi_struct *napi, int budget) @@ -651,7 +651,7 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget) printk(KERN_DEBUG "%s: hss_hdlc_poll" " netif_rx_complete\n", dev->name); #endif - netif_rx_complete(dev, napi); + netif_rx_complete(napi); qmgr_enable_irq(rxq); if (!qmgr_stat_empty(rxq) && netif_rx_reschedule(napi)) { @@ -1069,7 +1069,7 @@ static int hss_hdlc_open(struct net_device *dev) hss_start_hdlc(port); /* we may already have RX data, enables IRQ */ - netif_rx_schedule(dev, &port->napi); + netif_rx_schedule(&port->napi); return 0; err_unlock: diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index ea543fcf2687..e4f9f747de88 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -111,7 +111,7 @@ config WLAN_80211 lets you choose drivers. config PCMCIA_RAYCS - tristate "Aviator/Raytheon 2.4MHz wireless support" + tristate "Aviator/Raytheon 2.4GHz wireless support" depends on PCMCIA && WLAN_80211 select WIRELESS_EXT ---help--- diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 4af2607deec0..8ef87356e083 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2644,7 +2644,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (skb_headroom(skb) < padsize) { ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" " headroom to pad %d\n", hdrlen, padsize); - return -1; + return NETDEV_TX_BUSY; } skb_push(skb, padsize); memmove(skb->data, skb->data+padsize, hdrlen); @@ -2655,7 +2655,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); spin_unlock_irqrestore(&sc->txbuflock, flags); ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); - return -1; + return NETDEV_TX_BUSY; } bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); list_del(&bf->list); @@ -2673,10 +2673,10 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) sc->txbuf_len++; spin_unlock_irqrestore(&sc->txbuflock, flags); dev_kfree_skb_any(skb); - return 0; + return NETDEV_TX_OK; } - return 0; + return NETDEV_TX_OK; } static int diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c index 0cac05c6a9ce..75eb9f43c741 100644 --- a/drivers/net/wireless/ath5k/pcu.c +++ b/drivers/net/wireless/ath5k/pcu.c @@ -65,7 +65,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) if (ah->ah_version == AR5K_AR5210) pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; else - AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC); + AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); break; case NL80211_IFTYPE_AP: @@ -75,7 +75,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) if (ah->ah_version == AR5K_AR5210) pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; else - AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC); + AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); break; case NL80211_IFTYPE_STATION: diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index 91aaeaf88199..9189ab13286c 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h @@ -73,7 +73,7 @@ #define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */ #define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */ #define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */ -#define AR5K_CFG_ADHOC 0x00000020 /* AP/Adhoc indication [5211+] */ +#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */ #define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */ #define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */ #define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */ diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath9k/Kconfig index c43bd321f97f..90a8dd873786 100644 --- a/drivers/net/wireless/ath9k/Kconfig +++ b/drivers/net/wireless/ath9k/Kconfig @@ -1,6 +1,7 @@ config ATH9K tristate "Atheros 802.11n wireless cards support" depends on PCI && MAC80211 && WLAN_80211 + depends on RFKILL || RFKILL=n select MAC80211_LEDS select LEDS_CLASS select NEW_LEDS diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 191eec50dc75..727f067aca4f 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -2164,13 +2164,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) conf->ht.channel_type); } + ath_update_chainmask(sc, conf->ht.enabled); + if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) { DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); mutex_unlock(&sc->mutex); return -EINVAL; } - - ath_update_chainmask(sc, conf->ht.enabled); } if (changed & IEEE80211_CONF_CHANGE_POWER) diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 3bfc3b90f256..c92f0c6e4adc 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -126,15 +126,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, tx_info->flags |= IEEE80211_TX_STAT_ACK; } - tx_info->status.rates[0].count = tx_status->retries; - if (tx_info->status.rates[0].flags & IEEE80211_TX_RC_MCS) { - /* Change idx from internal table index to MCS index */ - int idx = tx_info->status.rates[0].idx; - struct ath_rate_table *rate_table = sc->cur_rate_table; - if (idx >= 0 && idx < rate_table->rate_cnt) - tx_info->status.rates[0].idx = - rate_table->info[idx].ratecode & 0x7f; - } + tx_info->status.rates[0].count = tx_status->retries + 1; hdrlen = ieee80211_get_hdrlen_from_skb(skb); padsize = hdrlen & 3; @@ -264,25 +256,22 @@ static void assign_aggr_tid_seqno(struct sk_buff *skb, } /* Get seqno */ - - if (ieee80211_is_data(fc) && !is_pae(skb)) { - /* For HT capable stations, we save tidno for later use. - * We also override seqno set by upper layer with the one - * in tx aggregation state. - * - * If fragmentation is on, the sequence number is - * not overridden, since it has been - * incremented by the fragmentation routine. - * - * FIXME: check if the fragmentation threshold exceeds - * IEEE80211 max. - */ - tid = ATH_AN_2_TID(an, bf->bf_tidno); - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << - IEEE80211_SEQ_SEQ_SHIFT); - bf->bf_seqno = tid->seq_next; - INCR(tid->seq_next, IEEE80211_SEQ_MAX); - } + /* For HT capable stations, we save tidno for later use. + * We also override seqno set by upper layer with the one + * in tx aggregation state. + * + * If fragmentation is on, the sequence number is + * not overridden, since it has been + * incremented by the fragmentation routine. + * + * FIXME: check if the fragmentation threshold exceeds + * IEEE80211 max. + */ + tid = ATH_AN_2_TID(an, bf->bf_tidno); + hdr->seq_ctrl = cpu_to_le16(tid->seq_next << + IEEE80211_SEQ_SEQ_SHIFT); + bf->bf_seqno = tid->seq_next; + INCR(tid->seq_next, IEEE80211_SEQ_MAX); } static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, @@ -1718,11 +1707,10 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, /* Assign seqno, tidno */ - if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR)) + if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR)) assign_aggr_tid_seqno(skb, bf); /* DMA setup */ - bf->bf_mpdu = skb; bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data, diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 7b31a327b24a..c788bad10661 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3261,7 +3261,7 @@ static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan) struct b43_wldev *down_dev; struct b43_wldev *d; int err; - bool gmode; + bool uninitialized_var(gmode); int prev_status; /* Find a device and PHY which supports the band. */ diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index c1324e31d2f6..fb996c27a19b 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2465,7 +2465,7 @@ static void b43legacy_put_phy_into_reset(struct b43legacy_wldev *dev) static int b43legacy_switch_phymode(struct b43legacy_wl *wl, unsigned int new_mode) { - struct b43legacy_wldev *up_dev; + struct b43legacy_wldev *uninitialized_var(up_dev); struct b43legacy_wldev *down_dev; int err; bool gmode = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8fdb34222c0a..45cfa1cf194a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2219,7 +2219,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv) /* set tx power value for all OFDM rates */ for (rate_index = 0; rate_index < IWL_OFDM_RATES; rate_index++) { - s32 power_idx; + s32 uninitialized_var(power_idx); int rc; /* use channel group's clip-power table, diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 52966ffbef6e..ba997204c8d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -255,7 +255,7 @@ struct iwl_cmd_header { * 0x3) 54 Mbps * * Legacy CCK rate format for bits 7:0 (bit 8 must be "0", bit 9 "1"): - * 3-0: 10) 1 Mbps + * 6-0: 10) 1 Mbps * 20) 2 Mbps * 55) 5.5 Mbps * 110) 11 Mbps diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 01a2169cecec..8c71ad4f88c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -51,6 +51,7 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(REPLY_REMOVE_STA); IWL_CMD(REPLY_REMOVE_ALL_STA); IWL_CMD(REPLY_WEPKEY); + IWL_CMD(REPLY_3945_RX); IWL_CMD(REPLY_TX); IWL_CMD(REPLY_RATE_SCALE); IWL_CMD(REPLY_LEDS_CMD); diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index d1fc305de5fe..e7289e2e7f16 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -206,7 +206,7 @@ static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * there are no buffered multicast frames to send */ ieee80211_stop_queues(priv->hw); - return 0; + return NETDEV_TX_OK; } static void lbtf_tx_work(struct work_struct *work) diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index bc84e2792f8a..c3bb85e0251e 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -1610,6 +1610,16 @@ static void orinoco_rx_isr_tasklet(unsigned long data) struct orinoco_rx_data *rx_data, *temp; struct hermes_rx_descriptor *desc; struct sk_buff *skb; + unsigned long flags; + + /* orinoco_rx requires the driver lock, and we also need to + * protect priv->rx_list, so just hold the lock over the + * lot. + * + * If orinoco_lock fails, we've unplugged the card. In this + * case just abort. */ + if (orinoco_lock(priv, &flags) != 0) + return; /* extract desc and skb from queue */ list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) { @@ -1622,6 +1632,8 @@ static void orinoco_rx_isr_tasklet(unsigned long data) kfree(desc); } + + orinoco_unlock(priv, &flags); } /********************************************************************/ @@ -3645,12 +3657,22 @@ struct net_device void free_orinocodev(struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); + struct orinoco_rx_data *rx_data, *temp; - /* No need to empty priv->rx_list: if the tasklet is scheduled - * when we call tasklet_kill it will run one final time, - * emptying the list */ + /* If the tasklet is scheduled when we call tasklet_kill it + * will run one final time. However the tasklet will only + * drain priv->rx_list if the hw is still available. */ tasklet_kill(&priv->rx_tasklet); + /* Explicitly drain priv->rx_list */ + list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) { + list_del(&rx_data->list); + + dev_kfree_skb(rx_data->skb); + kfree(rx_data->desc); + kfree(rx_data); + } + unregister_pm_notifier(&priv->pm_notifier); orinoco_uncache_fw(priv); diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index f127602670ec..0b32215d3f5d 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -435,6 +435,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */ PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */ PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */ + PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */ PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */ PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */ diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 82354b974a04..c6a370fa9bcb 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -138,6 +138,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) u8 *fw_version = NULL; size_t len; int i; + int maxlen; if (priv->rx_start) return 0; @@ -195,6 +196,16 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) else priv->rx_mtu = (size_t) 0x620 - priv->tx_hdr_len; + maxlen = priv->tx_hdr_len + /* USB devices */ + sizeof(struct p54_rx_data) + + 4 + /* rx alignment */ + IEEE80211_MAX_FRAG_THRESHOLD; + if (priv->rx_mtu > maxlen && PAGE_SIZE == 4096) { + printk(KERN_INFO "p54: rx_mtu reduced from %d " + "to %d\n", priv->rx_mtu, + maxlen); + priv->rx_mtu = maxlen; + } break; } case BR_CODE_EXPOSED_IF: @@ -575,6 +586,7 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) u16 freq = le16_to_cpu(hdr->freq); size_t header_len = sizeof(*hdr); u32 tsf32; + u8 rate = hdr->rate & 0xf; /* * If the device is in a unspecified state we have to @@ -603,8 +615,11 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) rx_status.qual = (100 * hdr->rssi) / 127; if (hdr->rate & 0x10) rx_status.flag |= RX_FLAG_SHORTPRE; - rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ? - hdr->rate : (hdr->rate - 4)) & 0xf; + if (dev->conf.channel->band == IEEE80211_BAND_5GHZ) + rx_status.rate_idx = (rate < 4) ? 0 : rate - 4; + else + rx_status.rate_idx = rate; + rx_status.freq = freq; rx_status.band = dev->conf.channel->band; rx_status.antenna = hdr->antenna; @@ -798,6 +813,16 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) info->flags |= IEEE80211_TX_STAT_TX_FILTERED; info->status.ack_signal = p54_rssi_to_dbm(dev, (int)payload->ack_rssi); + + if (entry_data->key_type == P54_CRYPTO_TKIPMICHAEL) { + u8 *iv = (u8 *)(entry_data->align + pad + + entry_data->crypt_offset); + + /* Restore the original TKIP IV. */ + iv[2] = iv[0]; + iv[0] = iv[1]; + iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */ + } skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); ieee80211_tx_status_irqsafe(dev, entry); goto out; @@ -1383,7 +1408,6 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) hdr->tries = ridx; txhdr->rts_rate_idx = 0; if (info->control.hw_key) { - crypt_offset += info->control.hw_key->iv_len; txhdr->key_type = p54_convert_algo(info->control.hw_key->alg); txhdr->key_len = min((u8)16, info->control.hw_key->keylen); memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len); @@ -1397,6 +1421,8 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) } /* reserve some space for ICV */ len += info->control.hw_key->icv_len; + memset(skb_put(skb, info->control.hw_key->icv_len), 0, + info->control.hw_key->icv_len); } else { txhdr->key_type = 0; txhdr->key_len = 0; @@ -1824,7 +1850,7 @@ static void p54_remove_interface(struct ieee80211_hw *dev, static int p54_config(struct ieee80211_hw *dev, u32 changed) { - int ret; + int ret = 0; struct p54_common *priv = dev->priv; struct ieee80211_conf *conf = &dev->conf; diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index c44a200059d2..6a6a72f6f82c 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -56,6 +56,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */ {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */ {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */ + {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ @@ -284,6 +285,7 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb) usb_fill_bulk_urb(data_urb, priv->udev, usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), skb->data, skb->len, p54u_tx_cb, skb); + data_urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(data_urb, &priv->submitted); if (usb_submit_urb(data_urb, GFP_ATOMIC)) { diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 30028e2422fc..af6b5847be5c 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -38,7 +38,7 @@ /* * Allow hardware encryption to be disabled. */ -static int modparam_nohwcrypt = 1; +static int modparam_nohwcrypt = 0; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -376,11 +376,11 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, /* * The driver does not support the IV/EIV generation - * in hardware. However it doesn't support the IV/EIV - * inside the ieee80211 frame either, but requires it - * to be provided seperately for the descriptor. - * rt2x00lib will cut the IV/EIV data out of all frames - * given to us by mac80211, but we must tell mac80211 + * in hardware. However it demands the data to be provided + * both seperately as well as inside the frame. + * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib + * to ensure rt2x00lib will not strip the data from the + * frame after the copy, now we must tell mac80211 * to generate the IV/EIV data. */ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; @@ -1181,7 +1181,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); - rt2x00_set_field32(&word, TXD_W0_CIPHER, txdesc->cipher); + rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher); rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx); rt2x00_desc_write(txd, 0, word); } @@ -1334,14 +1334,7 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, /* ICV is located at the end of frame */ - /* - * Hardware has stripped IV/EIV data from 802.11 frame during - * decryption. It has provided the data seperately but rt2x00lib - * should decide if it should be reinserted. - */ - rxdesc->flags |= RX_FLAG_IV_STRIPPED; - if (rxdesc->cipher != CIPHER_TKIP) - rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; + rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) rxdesc->flags |= RX_FLAG_DECRYPTED; else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 6d92542fcf0d..87c0f2c83077 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -807,13 +807,11 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry, { entry->flags = 0; entry->bitrate = rate->bitrate; - entry->hw_value = rt2x00_create_rate_hw_value(index, 0); - entry->hw_value_short = entry->hw_value; + entry->hw_value =index; + entry->hw_value_short = index; - if (rate->flags & DEV_RATE_SHORT_PREAMBLE) { + if (rate->flags & DEV_RATE_SHORT_PREAMBLE) entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE; - entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1); - } } static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index 68f4e0fc35b9..a0cd35b6beb5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -97,7 +97,7 @@ void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled) void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled) { - if (rt2x00dev->led_radio.type == LED_TYPE_ASSOC) + if (rt2x00dev->led_radio.type == LED_TYPE_RADIO) rt2x00led_led_simple(&rt2x00dev->led_radio, enabled); } diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 03024327767b..86cd26fbf769 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -52,22 +52,11 @@ struct rt2x00_rate { extern const struct rt2x00_rate rt2x00_supported_rates[12]; -static inline u16 rt2x00_create_rate_hw_value(const u16 index, - const u16 short_preamble) -{ - return (short_preamble << 8) | (index & 0xff); -} - static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) { return &rt2x00_supported_rates[hw_value & 0xff]; } -static inline int rt2x00_get_rate_preamble(const u16 hw_value) -{ - return (hw_value & 0xff00); -} - /* * Radio control handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index eaec6bd93ed5..746a8f36b931 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -313,7 +313,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * When preamble is enabled we should set the * preamble bit for the signal. */ - if (rt2x00_get_rate_preamble(rate->hw_value)) + if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) txdesc->signal |= 0x08; } } diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 83df312ac56f..0b29d767a258 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -434,11 +434,11 @@ static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev) if (usb_endpoint_is_bulk_in(ep_desc)) { rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc); - } else if (usb_endpoint_is_bulk_out(ep_desc)) { + } else if (usb_endpoint_is_bulk_out(ep_desc) && + (queue != queue_end(rt2x00dev))) { rt2x00usb_assign_endpoint(queue, ep_desc); + queue = queue_next(queue); - if (queue != queue_end(rt2x00dev)) - queue = queue_next(queue); tx_ep_desc = ep_desc; } } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index d638a8a59370..96a8d69f8790 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2321,6 +2321,7 @@ static struct usb_device_id rt73usb_device_table[] = { /* Linksys */ { USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) }, /* MSI */ { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) }, diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 5f887fb137a9..387c133ec0f2 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -897,6 +897,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_UNSPEC; + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); dev->queues = 1; dev->max_signal = 65; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 00ce3ef39abe..6ad6bac37706 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -213,7 +213,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { kfree_skb(skb); - return -ENOMEM; + return NETDEV_TX_OK; } flags = skb->len; @@ -281,7 +281,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) } usb_free_urb(urb); - return rc; + return NETDEV_TX_OK; } static void rtl8187_rx_cb(struct urb *urb) @@ -1471,6 +1471,7 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf) ieee80211_unregister_hw(dev); priv = dev->priv; + usb_reset_device(priv->udev); usb_put_dev(interface_to_usbdev(intf)); ieee80211_free_hw(dev); } diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c index e1b0ad6e918f..fa65a2b2ae2e 100644 --- a/drivers/of/of_i2c.c +++ b/drivers/of/of_i2c.c @@ -66,4 +66,23 @@ void of_register_i2c_devices(struct i2c_adapter *adap, } EXPORT_SYMBOL(of_register_i2c_devices); +static int of_dev_node_match(struct device *dev, void *data) +{ + return dev_archdata_get_node(&dev->archdata) == data; +} + +/* must call put_device() when done with returned i2c_client device */ +struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) +{ + struct device *dev; + + dev = bus_find_device(&i2c_bus_type, NULL, node, + of_dev_node_match); + if (!dev) + return NULL; + + return to_i2c_client(dev); +} +EXPORT_SYMBOL(of_find_i2c_device_by_node); + MODULE_LICENSE("GPL"); diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 1e93c837514f..4fa3bb2ddfe4 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -405,7 +405,6 @@ static void __init superio_serial_init(void) 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; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index c12f6c790698..e491fdedf705 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1260,15 +1260,14 @@ void pci_pm_init(struct pci_dev *dev) /* find PCI PM capability in list */ pm = pci_find_capability(dev, PCI_CAP_ID_PM); if (!pm) - goto Exit; - + return; /* Check device's ability to generate PME# */ pci_read_config_word(dev, pm + PCI_PM_PMC, &pmc); if ((pmc & PCI_PM_CAP_VER_MASK) > 3) { dev_err(&dev->dev, "unsupported PM cap regs version (%u)\n", pmc & PCI_PM_CAP_VER_MASK); - goto Exit; + return; } dev->pm_cap = pm; @@ -1307,9 +1306,6 @@ void pci_pm_init(struct pci_dev *dev) } else { dev->pme_support = 0; } - - Exit: - pci_update_current_state(dev, PCI_D0); } /** diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c index 645d7a60e412..ec22284eed30 100644 --- a/drivers/pci/syscall.c +++ b/drivers/pci/syscall.c @@ -14,10 +14,8 @@ #include <asm/uaccess.h> #include "pci.h" -asmlinkage long -sys_pciconfig_read(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - void __user *buf) +SYSCALL_DEFINE5(pciconfig_read, unsigned long, bus, unsigned long, dfn, + unsigned long, off, unsigned long, len, void __user *, buf) { struct pci_dev *dev; u8 byte; @@ -86,10 +84,8 @@ error: return err; } -asmlinkage long -sys_pciconfig_write(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - void __user *buf) +SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, + unsigned long, off, unsigned long, len, void __user *, buf) { struct pci_dev *dev; u8 byte; diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c index a34284b1482a..d187ba4c5e0e 100644 --- a/drivers/pcmcia/electra_cf.c +++ b/drivers/pcmcia/electra_cf.c @@ -297,7 +297,7 @@ static int __devinit electra_cf_probe(struct of_device *ofdev, goto fail3; } - dev_info(device, "at mem 0x%lx io 0x%lx irq %d\n", + dev_info(device, "at mem 0x%lx io 0x%llx irq %d\n", cf->mem_phys, io.start, cf->irq); cf->active = 1; diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index cc7eb8767b82..bd56a033bfd0 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c @@ -27,6 +27,8 @@ #include <linux/interrupt.h> #include <linux/io.h> +#include <mach/hardware.h> + #define TIMER_FREQ CLOCK_TICK_RATE #define RTC_DEF_DIVIDER (32768 - 1) #define RTC_DEF_TRIM 0 diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c index 8ce5f74ee45b..ad35f76c46b7 100644 --- a/drivers/rtc/rtc-twl4030.c +++ b/drivers/rtc/rtc-twl4030.c @@ -120,7 +120,7 @@ static int twl4030_rtc_write_u8(u8 data, u8 reg) static unsigned char rtc_irq_bits; /* - * Enable timer and/or alarm interrupts. + * Enable 1/second update and/or alarm interrupts. */ static int set_rtc_irq_bit(unsigned char bit) { @@ -128,6 +128,7 @@ static int set_rtc_irq_bit(unsigned char bit) int ret; val = rtc_irq_bits | bit; + val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M; ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG); if (ret == 0) rtc_irq_bits = val; @@ -136,7 +137,7 @@ static int set_rtc_irq_bit(unsigned char bit) } /* - * Disable timer and/or alarm interrupts. + * Disable update and/or alarm interrupts. */ static int mask_rtc_irq_bit(unsigned char bit) { @@ -151,7 +152,7 @@ static int mask_rtc_irq_bit(unsigned char bit) return ret; } -static inline int twl4030_rtc_alarm_irq_set_state(int enabled) +static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) { int ret; @@ -163,7 +164,7 @@ static inline int twl4030_rtc_alarm_irq_set_state(int enabled) return ret; } -static inline int twl4030_rtc_irq_set_state(int enabled) +static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled) { int ret; @@ -292,7 +293,7 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) unsigned char alarm_data[ALL_TIME_REGS + 1]; int ret; - ret = twl4030_rtc_alarm_irq_set_state(0); + ret = twl4030_rtc_alarm_irq_enable(dev, 0); if (ret) goto out; @@ -312,35 +313,11 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) } if (alm->enabled) - ret = twl4030_rtc_alarm_irq_set_state(1); + ret = twl4030_rtc_alarm_irq_enable(dev, 1); out: return ret; } -#ifdef CONFIG_RTC_INTF_DEV - -static int twl4030_rtc_ioctl(struct device *dev, unsigned int cmd, - unsigned long arg) -{ - switch (cmd) { - case RTC_AIE_OFF: - return twl4030_rtc_alarm_irq_set_state(0); - case RTC_AIE_ON: - return twl4030_rtc_alarm_irq_set_state(1); - case RTC_UIE_OFF: - return twl4030_rtc_irq_set_state(0); - case RTC_UIE_ON: - return twl4030_rtc_irq_set_state(1); - - default: - return -ENOIOCTLCMD; - } -} - -#else -#define twl4030_rtc_ioctl NULL -#endif - static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) { unsigned long events = 0; @@ -400,11 +377,12 @@ out: } static struct rtc_class_ops twl4030_rtc_ops = { - .ioctl = twl4030_rtc_ioctl, .read_time = twl4030_rtc_read_time, .set_time = twl4030_rtc_set_time, .read_alarm = twl4030_rtc_read_alarm, .set_alarm = twl4030_rtc_set_alarm, + .alarm_irq_enable = twl4030_rtc_alarm_irq_enable, + .update_irq_enable = twl4030_rtc_update_irq_enable, }; /*----------------------------------------------------------------------*/ @@ -422,7 +400,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) rtc = rtc_device_register(pdev->name, &pdev->dev, &twl4030_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { - ret = -EINVAL; + ret = PTR_ERR(rtc); dev_err(&pdev->dev, "can't register RTC device, err %ld\n", PTR_ERR(rtc)); goto out0; @@ -432,7 +410,6 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); - if (ret < 0) goto out1; @@ -475,7 +452,6 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) return ret; - out2: free_irq(irq, rtc); out1: @@ -506,8 +482,9 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev) static void twl4030_rtc_shutdown(struct platform_device *pdev) { - mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M | - BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); + /* mask timer interrupts, but leave alarm interrupts on to enable + power-on when alarm is triggered */ + mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); } #ifdef CONFIG_PM diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 5c541f7850f9..74d07d137dae 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1061,7 +1061,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) } sdev_printk(KERN_INFO, cmd->device, - "aborting command. lun 0x%lx, tag 0x%lx\n", + "aborting command. lun 0x%llx, tag 0x%llx\n", (((u64) lun) << 48), (u64) found_evt); wait_for_completion(&evt->comp); @@ -1082,7 +1082,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) if (rsp_rc) { if (printk_ratelimit()) sdev_printk(KERN_WARNING, cmd->device, - "abort code %d for task tag 0x%lx\n", + "abort code %d for task tag 0x%llx\n", rsp_rc, tsk_mgmt->task_tag); return FAILED; } @@ -1102,12 +1102,12 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd) if (found_evt == NULL) { spin_unlock_irqrestore(hostdata->host->host_lock, flags); - sdev_printk(KERN_INFO, cmd->device, "aborted task tag 0x%lx completed\n", + sdev_printk(KERN_INFO, cmd->device, "aborted task tag 0x%llx completed\n", tsk_mgmt->task_tag); return SUCCESS; } - sdev_printk(KERN_INFO, cmd->device, "successfully aborted task tag 0x%lx\n", + sdev_printk(KERN_INFO, cmd->device, "successfully aborted task tag 0x%llx\n", tsk_mgmt->task_tag); cmd->result = (DID_ABORT << 16); @@ -1182,7 +1182,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) return FAILED; } - sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%lx\n", + sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%llx\n", (((u64) lun) << 48)); wait_for_completion(&evt->comp); @@ -1203,7 +1203,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd) if (rsp_rc) { if (printk_ratelimit()) sdev_printk(KERN_WARNING, cmd->device, - "reset code %d for task tag 0x%lx\n", + "reset code %d for task tag 0x%llx\n", rsp_rc, tsk_mgmt->task_tag); return FAILED; } diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 1889a63ebc22..0d934bfbdd9b 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -2839,6 +2839,8 @@ int __init early_serial_setup(struct uart_port *port) p->flags = port->flags; p->mapbase = port->mapbase; p->private_data = port->private_data; + p->type = port->type; + p->line = port->line; set_io_from_upio(p); if (port->serial_in) diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index c088146b7513..2a3671233b15 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -602,6 +602,10 @@ static int pci_netmos_init(struct pci_dev *dev) /* subdevice 0x00PS means <P> parallel, <S> serial */ unsigned int num_serial = dev->subsystem_device & 0xf; + if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && + dev->subsystem_device == 0x0299) + return 0; + if (num_serial == 0) return -ENODEV; return num_serial; @@ -3096,6 +3100,10 @@ static struct pci_device_id serial_pci_tbl[] = { 0, pbn_b0_8_115200 }, + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835, + PCI_VENDOR_ID_IBM, 0x0299, + 0, 0, pbn_b0_bt_2_115200 }, + /* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index fde7f9ccf57e..bbcfc26a3b6d 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -270,6 +270,8 @@ static const struct pnp_device_id pnp_dev_table[] = { { "RSS0250", 0 }, /* SupraExpress 28.8 Data/Fax PnP modem */ { "SUP1310", 0 }, + /* SupraExpress 336i PnP Voice Modem */ + { "SUP1381", 0 }, /* SupraExpress 33.6 Data/Fax PnP modem */ { "SUP1421", 0 }, /* SupraExpress 33.6 Data/Fax PnP modem */ diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index d5efd6c77904..89362d733d62 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -579,7 +579,7 @@ static void atmel_tx_dma(struct uart_port *port) /* disable PDC transmit */ UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); - if (!uart_circ_empty(xmit)) { + if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) { dma_sync_single_for_device(port->dev, pdc->dma_addr, pdc->dma_size, diff --git a/drivers/serial/pnx8xxx_uart.c b/drivers/serial/pnx8xxx_uart.c index 22e30d21225e..1bb8f1b45767 100644 --- a/drivers/serial/pnx8xxx_uart.c +++ b/drivers/serial/pnx8xxx_uart.c @@ -187,7 +187,7 @@ static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport) status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) | ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT)); while (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFIFO)) { - ch = serial_in(sport, PNX8XXX_FIFO); + ch = serial_in(sport, PNX8XXX_FIFO) & 0xff; sport->port.icount.rx++; @@ -198,9 +198,16 @@ static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport) * out of the main execution path */ if (status & (FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE | - PNX8XXX_UART_FIFO_RXPAR) | + PNX8XXX_UART_FIFO_RXPAR | + PNX8XXX_UART_FIFO_RXBRK) | ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))) { - if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR)) + if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXBRK)) { + status &= ~(FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) | + FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR)); + sport->port.icount.brk++; + if (uart_handle_break(&sport->port)) + goto ignore_char; + } else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR)) sport->port.icount.parity++; else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE)) sport->port.icount.frame++; @@ -284,14 +291,8 @@ static irqreturn_t pnx8xxx_int(int irq, void *dev_id) /* Get the interrupts */ status = serial_in(sport, PNX8XXX_ISTAT) & serial_in(sport, PNX8XXX_IEN); - /* Break signal received */ - if (status & PNX8XXX_UART_INT_BREAK) { - sport->port.icount.brk++; - uart_handle_break(&sport->port); - } - - /* Byte received */ - if (status & PNX8XXX_UART_INT_RX) + /* Byte or break signal received */ + if (status & (PNX8XXX_UART_INT_RX | PNX8XXX_UART_INT_BREAK)) pnx8xxx_rx_chars(sport); /* TX holding register empty - transmit a byte */ diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 5e39bac9c51b..56ff3e6864ea 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -670,8 +670,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) dev_dbg(controller, "new message %p submitted for %s\n", msg, spi->dev.bus_id); - if (unlikely(list_empty(&msg->transfers) - || !spi->max_speed_hz)) + if (unlikely(list_empty(&msg->transfers))) return -EINVAL; if (as->stopping) diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index 68d6f4988fb5..fe7e5f35e5d0 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -15,12 +15,15 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/platform_device.h> + +#include <linux/of_platform.h> +#include <linux/of_device.h> +#include <linux/of_spi.h> + #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> #include <linux/io.h> -#include <syslib/virtex_devices.h> - #define XILINX_SPI_NAME "xilinx_spi" /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e) @@ -144,23 +147,14 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { u8 bits_per_word; - u32 hz; - struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word; - hz = (t) ? t->speed_hz : spi->max_speed_hz; if (bits_per_word != 8) { dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", __func__, bits_per_word); return -EINVAL; } - if (hz && xspi->speed_hz > hz) { - dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n", - __func__, hz); - return -EINVAL; - } - return 0; } @@ -304,32 +298,38 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static int __init xilinx_spi_probe(struct platform_device *dev) +static int __init xilinx_spi_of_probe(struct of_device *ofdev, + const struct of_device_id *match) { - int ret = 0; struct spi_master *master; struct xilinx_spi *xspi; - struct xspi_platform_data *pdata; - struct resource *r; + struct resource r_irq_struct; + struct resource r_mem_struct; + + struct resource *r_irq = &r_irq_struct; + struct resource *r_mem = &r_mem_struct; + int rc = 0; + const u32 *prop; + int len; /* Get resources(memory, IRQ) associated with the device */ - master = spi_alloc_master(&dev->dev, sizeof(struct xilinx_spi)); + master = spi_alloc_master(&ofdev->dev, sizeof(struct xilinx_spi)); if (master == NULL) { return -ENOMEM; } - platform_set_drvdata(dev, master); - pdata = dev->dev.platform_data; + dev_set_drvdata(&ofdev->dev, master); - if (pdata == NULL) { - ret = -ENODEV; + rc = of_address_to_resource(ofdev->node, 0, r_mem); + if (rc) { + dev_warn(&ofdev->dev, "invalid address\n"); goto put_master; } - r = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (r == NULL) { - ret = -ENODEV; + rc = of_irq_to_resource(ofdev->node, 0, r_irq); + if (rc == NO_IRQ) { + dev_warn(&ofdev->dev, "no IRQ found\n"); goto put_master; } @@ -341,47 +341,57 @@ static int __init xilinx_spi_probe(struct platform_device *dev) xspi->bitbang.master->setup = xilinx_spi_setup; init_completion(&xspi->done); - if (!request_mem_region(r->start, - r->end - r->start + 1, XILINX_SPI_NAME)) { - ret = -ENXIO; + xspi->irq = r_irq->start; + + if (!request_mem_region(r_mem->start, + r_mem->end - r_mem->start + 1, XILINX_SPI_NAME)) { + rc = -ENXIO; + dev_warn(&ofdev->dev, "memory request failure\n"); goto put_master; } - xspi->regs = ioremap(r->start, r->end - r->start + 1); + xspi->regs = ioremap(r_mem->start, r_mem->end - r_mem->start + 1); if (xspi->regs == NULL) { - ret = -ENOMEM; + rc = -ENOMEM; + dev_warn(&ofdev->dev, "ioremap failure\n"); goto put_master; } + xspi->irq = r_irq->start; - ret = platform_get_irq(dev, 0); - if (ret < 0) { - ret = -ENXIO; - goto unmap_io; - } - xspi->irq = ret; + /* dynamic bus assignment */ + master->bus_num = -1; - master->bus_num = pdata->bus_num; - master->num_chipselect = pdata->num_chipselect; - xspi->speed_hz = pdata->speed_hz; + /* number of slave select bits is required */ + prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len); + if (!prop || len < sizeof(*prop)) { + dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n"); + goto put_master; + } + master->num_chipselect = *prop; /* SPI controller initializations */ xspi_init_hw(xspi->regs); /* Register for SPI Interrupt */ - ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); - if (ret != 0) + rc = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); + if (rc != 0) { + dev_warn(&ofdev->dev, "irq request failure: %d\n", xspi->irq); goto unmap_io; + } - ret = spi_bitbang_start(&xspi->bitbang); - if (ret != 0) { - dev_err(&dev->dev, "spi_bitbang_start FAILED\n"); + rc = spi_bitbang_start(&xspi->bitbang); + if (rc != 0) { + dev_err(&ofdev->dev, "spi_bitbang_start FAILED\n"); goto free_irq; } - dev_info(&dev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n", - r->start, (u32)xspi->regs, xspi->irq); + dev_info(&ofdev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n", + (unsigned int)r_mem->start, (u32)xspi->regs, xspi->irq); - return ret; + /* Add any subnodes on the SPI bus */ + of_register_spi_devices(master, ofdev->node); + + return rc; free_irq: free_irq(xspi->irq, xspi); @@ -389,21 +399,21 @@ unmap_io: iounmap(xspi->regs); put_master: spi_master_put(master); - return ret; + return rc; } -static int __devexit xilinx_spi_remove(struct platform_device *dev) +static int __devexit xilinx_spi_remove(struct of_device *ofdev) { struct xilinx_spi *xspi; struct spi_master *master; - master = platform_get_drvdata(dev); + master = platform_get_drvdata(ofdev); xspi = spi_master_get_devdata(master); spi_bitbang_stop(&xspi->bitbang); free_irq(xspi->irq, xspi); iounmap(xspi->regs); - platform_set_drvdata(dev, 0); + dev_set_drvdata(&ofdev->dev, 0); spi_master_put(xspi->bitbang.master); return 0; @@ -412,27 +422,42 @@ static int __devexit xilinx_spi_remove(struct platform_device *dev) /* work with hotplug and coldplug */ MODULE_ALIAS("platform:" XILINX_SPI_NAME); -static struct platform_driver xilinx_spi_driver = { - .probe = xilinx_spi_probe, - .remove = __devexit_p(xilinx_spi_remove), +static int __exit xilinx_spi_of_remove(struct of_device *op) +{ + return xilinx_spi_remove(op); +} + +static struct of_device_id xilinx_spi_of_match[] = { + { .compatible = "xlnx,xps-spi-2.00.a", }, + { .compatible = "xlnx,xps-spi-2.00.b", }, + {} +}; + +MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); + +static struct of_platform_driver xilinx_spi_of_driver = { + .owner = THIS_MODULE, + .name = "xilinx-xps-spi", + .match_table = xilinx_spi_of_match, + .probe = xilinx_spi_of_probe, + .remove = __exit_p(xilinx_spi_of_remove), .driver = { - .name = XILINX_SPI_NAME, + .name = "xilinx-xps-spi", .owner = THIS_MODULE, }, }; static int __init xilinx_spi_init(void) { - return platform_driver_register(&xilinx_spi_driver); + return of_register_platform_driver(&xilinx_spi_of_driver); } module_init(xilinx_spi_init); static void __exit xilinx_spi_exit(void) { - platform_driver_unregister(&xilinx_spi_driver); + of_unregister_platform_driver(&xilinx_spi_of_driver); } module_exit(xilinx_spi_exit); - MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); MODULE_DESCRIPTION("Xilinx SPI driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d5d0e40b1e2d..94d5ee263c20 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1554,7 +1554,7 @@ static int usb_configure_device_otg(struct usb_device *udev) * (Includes HNP test device.) */ if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { - err = usb_port_suspend(udev); + err = usb_port_suspend(udev, PMSG_SUSPEND); if (err < 0) dev_dbg(&udev->dev, "HNP fail, %d\n", err); } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ef6cfa5a447f..c70a8f667d85 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2030,7 +2030,7 @@ static void ftdi_process_read(struct work_struct *work) spin_unlock_irqrestore(&priv->rx_lock, flags); dbg("%s - deferring remainder until unthrottled", __func__); - return; + goto out; } spin_unlock_irqrestore(&priv->rx_lock, flags); /* if the port is closed stop trying to read */ diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 7644ed249564..37e60b1d2ed9 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -335,7 +335,20 @@ static int bfin_bf54x_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - if (var->bits_per_pixel != LCD_BPP) { + switch (var->bits_per_pixel) { + case 24:/* TRUECOLOUR, 16m */ + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + var->transp.msb_right = 0; + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + break; + default: pr_debug("%s: depth not supported: %u BPP\n", __func__, var->bits_per_pixel); return -EINVAL; diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index a9b3ada05d99..2a423d3a2a8e 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -254,7 +254,20 @@ static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - if (var->bits_per_pixel != LCD_BPP) { + switch (var->bits_per_pixel) { + case 24:/* TRUECOLOUR, 16m */ + var->red.offset = 0; + var->green.offset = 8; + var->blue.offset = 16; + var->red.length = var->green.length = var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + var->transp.msb_right = 0; + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + break; + default: pr_debug("%s: depth not supported: %u BPP\n", __func__, var->bits_per_pixel); return -EINVAL; |