diff options
Diffstat (limited to 'drivers')
153 files changed, 1320 insertions, 569 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index db6dfcfa3e2..ab58556d347 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3625,6 +3625,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) shost->max_lun = 1; shost->max_channel = 1; shost->max_cmd_len = 16; + shost->no_write_same = 1; /* Schedule policy is determined by ->qc_defer() * callback and it needs to see every deferred qc. diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 432db1b59b0..c4a4c900628 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -489,7 +489,7 @@ static int blkif_queue_request(struct request *req) if ((ring_req->operation == BLKIF_OP_INDIRECT) && (i % SEGS_PER_INDIRECT_FRAME == 0)) { - unsigned long pfn; + unsigned long uninitialized_var(pfn); if (segments) kunmap_atomic(segments); @@ -2011,6 +2011,10 @@ static void blkif_release(struct gendisk *disk, fmode_t mode) bdev = bdget_disk(disk, 0); + if (!bdev) { + WARN(1, "Block device %s yanked out from us!\n", disk->disk_name); + goto out_mutex; + } if (bdev->bd_openers) goto out; @@ -2041,6 +2045,7 @@ static void blkif_release(struct gendisk *disk, fmode_t mode) out: bdput(bdev); +out_mutex: mutex_unlock(&blkfront_mutex); } diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 40cc0cf2ded..e6939e13e33 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -664,6 +664,13 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"), }, }, + { + .ident = "Dell XPS421", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"), + }, + }, { } }; diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c index 856ad80418a..7c03dd84f66 100644 --- a/drivers/cpufreq/at32ap-cpufreq.c +++ b/drivers/cpufreq/at32ap-cpufreq.c @@ -58,7 +58,7 @@ static int at32_set_target(struct cpufreq_policy *policy, unsigned int index) return 0; } -static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) +static int at32_cpufreq_driver_init(struct cpufreq_policy *policy) { unsigned int frequency, rate, min_freq; int retval, steps, i; diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 2a991e468f7..a55e68f2cfc 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -400,7 +400,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device); */ void cpuidle_unregister_device(struct cpuidle_device *dev) { - if (dev->registered == 0) + if (!dev || dev->registered == 0) return; cpuidle_pause_and_lock(); diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 3c55ec856e3..a287cece059 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -1082,7 +1082,7 @@ static void arizona_micd_set_level(struct arizona *arizona, int index, static int arizona_extcon_probe(struct platform_device *pdev) { struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); - struct arizona_pdata *pdata; + struct arizona_pdata *pdata = &arizona->pdata; struct arizona_extcon_info *info; unsigned int val; int jack_irq_fall, jack_irq_rise; @@ -1091,8 +1091,6 @@ static int arizona_extcon_probe(struct platform_device *pdev) if (!arizona->dapm || !arizona->dapm->card) return -EPROBE_DEFER; - pdata = dev_get_platdata(arizona->dev); - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) { dev_err(&pdev->dev, "Failed to allocate memory\n"); diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 15443d3b6be..76322330cbd 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -792,6 +792,8 @@ void extcon_dev_unregister(struct extcon_dev *edev) return; } + device_unregister(&edev->dev); + if (edev->mutually_exclusive && edev->max_supported) { for (index = 0; edev->mutually_exclusive[index]; index++) @@ -812,7 +814,6 @@ void extcon_dev_unregister(struct extcon_dev *edev) if (switch_class) class_compat_remove_link(switch_class, &edev->dev, NULL); #endif - device_unregister(&edev->dev); put_device(&edev->dev); } EXPORT_SYMBOL_GPL(extcon_dev_unregister); diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 281029daf98..b0bb056458a 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -1623,6 +1623,7 @@ static struct scsi_host_template scsi_driver_template = { .cmd_per_lun = 1, .can_queue = 1, .sdev_attrs = sbp2_scsi_sysfs_attrs, + .no_write_same = 1, }; MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index 5002d50e378..743fd426f21 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c @@ -18,14 +18,12 @@ module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644); static int efi_pstore_open(struct pstore_info *psi) { - efivar_entry_iter_begin(); psi->data = NULL; return 0; } static int efi_pstore_close(struct pstore_info *psi) { - efivar_entry_iter_end(); psi->data = NULL; return 0; } @@ -39,6 +37,12 @@ struct pstore_read_data { char **buf; }; +static inline u64 generic_id(unsigned long timestamp, + unsigned int part, int count) +{ + return (timestamp * 100 + part) * 1000 + count; +} + static int efi_pstore_read_func(struct efivar_entry *entry, void *data) { efi_guid_t vendor = LINUX_EFI_CRASH_GUID; @@ -57,7 +61,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) if (sscanf(name, "dump-type%u-%u-%d-%lu-%c", cb_data->type, &part, &cnt, &time, &data_type) == 5) { - *cb_data->id = part; + *cb_data->id = generic_id(time, part, cnt); *cb_data->count = cnt; cb_data->timespec->tv_sec = time; cb_data->timespec->tv_nsec = 0; @@ -67,7 +71,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) *cb_data->compressed = false; } else if (sscanf(name, "dump-type%u-%u-%d-%lu", cb_data->type, &part, &cnt, &time) == 4) { - *cb_data->id = part; + *cb_data->id = generic_id(time, part, cnt); *cb_data->count = cnt; cb_data->timespec->tv_sec = time; cb_data->timespec->tv_nsec = 0; @@ -79,7 +83,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) * which doesn't support holding * multiple logs, remains. */ - *cb_data->id = part; + *cb_data->id = generic_id(time, part, 0); *cb_data->count = 0; cb_data->timespec->tv_sec = time; cb_data->timespec->tv_nsec = 0; @@ -91,19 +95,125 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) __efivar_entry_get(entry, &entry->var.Attributes, &entry->var.DataSize, entry->var.Data); size = entry->var.DataSize; + memcpy(*cb_data->buf, entry->var.Data, + (size_t)min_t(unsigned long, EFIVARS_DATA_SIZE_MAX, size)); - *cb_data->buf = kmemdup(entry->var.Data, size, GFP_KERNEL); - if (*cb_data->buf == NULL) - return -ENOMEM; return size; } +/** + * efi_pstore_scan_sysfs_enter + * @entry: scanning entry + * @next: next entry + * @head: list head + */ +static void efi_pstore_scan_sysfs_enter(struct efivar_entry *pos, + struct efivar_entry *next, + struct list_head *head) +{ + pos->scanning = true; + if (&next->list != head) + next->scanning = true; +} + +/** + * __efi_pstore_scan_sysfs_exit + * @entry: deleting entry + * @turn_off_scanning: Check if a scanning flag should be turned off + */ +static inline void __efi_pstore_scan_sysfs_exit(struct efivar_entry *entry, + bool turn_off_scanning) +{ + if (entry->deleting) { + list_del(&entry->list); + efivar_entry_iter_end(); + efivar_unregister(entry); + efivar_entry_iter_begin(); + } else if (turn_off_scanning) + entry->scanning = false; +} + +/** + * efi_pstore_scan_sysfs_exit + * @pos: scanning entry + * @next: next entry + * @head: list head + * @stop: a flag checking if scanning will stop + */ +static void efi_pstore_scan_sysfs_exit(struct efivar_entry *pos, + struct efivar_entry *next, + struct list_head *head, bool stop) +{ + __efi_pstore_scan_sysfs_exit(pos, true); + if (stop) + __efi_pstore_scan_sysfs_exit(next, &next->list != head); +} + +/** + * efi_pstore_sysfs_entry_iter + * + * @data: function-specific data to pass to callback + * @pos: entry to begin iterating from + * + * You MUST call efivar_enter_iter_begin() before this function, and + * efivar_entry_iter_end() afterwards. + * + * It is possible to begin iteration from an arbitrary entry within + * the list by passing @pos. @pos is updated on return to point to + * the next entry of the last one passed to efi_pstore_read_func(). + * To begin iterating from the beginning of the list @pos must be %NULL. + */ +static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos) +{ + struct efivar_entry *entry, *n; + struct list_head *head = &efivar_sysfs_list; + int size = 0; + + if (!*pos) { + list_for_each_entry_safe(entry, n, head, list) { + efi_pstore_scan_sysfs_enter(entry, n, head); + + size = efi_pstore_read_func(entry, data); + efi_pstore_scan_sysfs_exit(entry, n, head, size < 0); + if (size) + break; + } + *pos = n; + return size; + } + + list_for_each_entry_safe_from((*pos), n, head, list) { + efi_pstore_scan_sysfs_enter((*pos), n, head); + + size = efi_pstore_read_func((*pos), data); + efi_pstore_scan_sysfs_exit((*pos), n, head, size < 0); + if (size) + break; + } + *pos = n; + return size; +} + +/** + * efi_pstore_read + * + * This function returns a size of NVRAM entry logged via efi_pstore_write(). + * The meaning and behavior of efi_pstore/pstore are as below. + * + * size > 0: Got data of an entry logged via efi_pstore_write() successfully, + * and pstore filesystem will continue reading subsequent entries. + * size == 0: Entry was not logged via efi_pstore_write(), + * and efi_pstore driver will continue reading subsequent entries. + * size < 0: Failed to get data of entry logging via efi_pstore_write(), + * and pstore will stop reading entry. + */ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, int *count, struct timespec *timespec, char **buf, bool *compressed, struct pstore_info *psi) { struct pstore_read_data data; + ssize_t size; data.id = id; data.type = type; @@ -112,8 +222,17 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, data.compressed = compressed; data.buf = buf; - return __efivar_entry_iter(efi_pstore_read_func, &efivar_sysfs_list, &data, - (struct efivar_entry **)&psi->data); + *data.buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL); + if (!*data.buf) + return -ENOMEM; + + efivar_entry_iter_begin(); + size = efi_pstore_sysfs_entry_iter(&data, + (struct efivar_entry **)&psi->data); + efivar_entry_iter_end(); + if (size <= 0) + kfree(*data.buf); + return size; } static int efi_pstore_write(enum pstore_type_id type, @@ -184,9 +303,17 @@ static int efi_pstore_erase_func(struct efivar_entry *entry, void *data) return 0; } + if (entry->scanning) { + /* + * Skip deletion because this entry will be deleted + * after scanning is completed. + */ + entry->deleting = true; + } else + list_del(&entry->list); + /* found */ __efivar_entry_delete(entry); - list_del(&entry->list); return 1; } @@ -199,14 +326,16 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, char name[DUMP_NAME_LEN]; efi_char16_t efi_name[DUMP_NAME_LEN]; int found, i; + unsigned int part; - sprintf(name, "dump-type%u-%u-%d-%lu", type, (unsigned int)id, count, - time.tv_sec); + do_div(id, 1000); + part = do_div(id, 100); + sprintf(name, "dump-type%u-%u-%d-%lu", type, part, count, time.tv_sec); for (i = 0; i < DUMP_NAME_LEN; i++) efi_name[i] = name[i]; - edata.id = id; + edata.id = part; edata.type = type; edata.count = count; edata.time = time; @@ -214,10 +343,12 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, efivar_entry_iter_begin(); found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, &edata, &entry); - efivar_entry_iter_end(); - if (found) + if (found && !entry->scanning) { + efivar_entry_iter_end(); efivar_unregister(entry); + } else + efivar_entry_iter_end(); return 0; } diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 933eb027d52..3dc24823919 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c @@ -383,12 +383,16 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, else if (__efivar_entry_delete(entry)) err = -EIO; - efivar_entry_iter_end(); - - if (err) + if (err) { + efivar_entry_iter_end(); return err; + } - efivar_unregister(entry); + if (!entry->scanning) { + efivar_entry_iter_end(); + efivar_unregister(entry); + } else + efivar_entry_iter_end(); /* It's dead Jim.... */ return count; diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c index 391c67b182d..b22659cccca 100644 --- a/drivers/firmware/efi/vars.c +++ b/drivers/firmware/efi/vars.c @@ -683,8 +683,16 @@ struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid, if (!found) return NULL; - if (remove) - list_del(&entry->list); + if (remove) { + if (entry->scanning) { + /* + * The entry will be deleted + * after scanning is completed. + */ + entry->deleting = true; + } else + list_del(&entry->list); + } return entry; } diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h index eef09ec9a5f..a72cae03b99 100644 --- a/drivers/gpu/drm/armada/armada_drm.h +++ b/drivers/gpu/drm/armada/armada_drm.h @@ -103,6 +103,7 @@ void armada_drm_queue_unref_work(struct drm_device *, extern const struct drm_mode_config_funcs armada_drm_mode_config_funcs; int armada_fbdev_init(struct drm_device *); +void armada_fbdev_lastclose(struct drm_device *); void armada_fbdev_fini(struct drm_device *); int armada_overlay_plane_create(struct drm_device *, unsigned long); diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 4f2b2835491..62d0ff3efdd 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -321,6 +321,11 @@ static struct drm_ioctl_desc armada_ioctls[] = { DRM_UNLOCKED), }; +static void armada_drm_lastclose(struct drm_device *dev) +{ + armada_fbdev_lastclose(dev); +} + static const struct file_operations armada_drm_fops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -337,7 +342,7 @@ static struct drm_driver armada_drm_driver = { .open = NULL, .preclose = NULL, .postclose = NULL, - .lastclose = NULL, + .lastclose = armada_drm_lastclose, .unload = armada_drm_unload, .get_vblank_counter = drm_vblank_count, .enable_vblank = armada_drm_enable_vblank, diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index dd5ea77dac9..948cb14c561 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -105,9 +105,9 @@ static int armada_fb_create(struct drm_fb_helper *fbh, drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth); drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height); - DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08x\n", - dfb->fb.width, dfb->fb.height, - dfb->fb.bits_per_pixel, obj->phys_addr); + DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08llx\n", + dfb->fb.width, dfb->fb.height, dfb->fb.bits_per_pixel, + (unsigned long long)obj->phys_addr); return 0; @@ -177,6 +177,16 @@ int armada_fbdev_init(struct drm_device *dev) return ret; } +void armada_fbdev_lastclose(struct drm_device *dev) +{ + struct armada_private *priv = dev->dev_private; + + drm_modeset_lock_all(dev); + if (priv->fbdev) + drm_fb_helper_restore_fbdev_mode(priv->fbdev); + drm_modeset_unlock_all(dev); +} + void armada_fbdev_fini(struct drm_device *dev) { struct armada_private *priv = dev->dev_private; @@ -192,11 +202,11 @@ void armada_fbdev_fini(struct drm_device *dev) framebuffer_release(info); } + drm_fb_helper_fini(fbh); + if (fbh->fb) fbh->fb->funcs->destroy(fbh->fb); - drm_fb_helper_fini(fbh); - priv->fbdev = NULL; } } diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 9f2356bae7f..887816f4347 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -172,8 +172,9 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj) obj->dev_addr = obj->linear->start; } - DRM_DEBUG_DRIVER("obj %p phys %#x dev %#x\n", - obj, obj->phys_addr, obj->dev_addr); + DRM_DEBUG_DRIVER("obj %p phys %#llx dev %#llx\n", obj, + (unsigned long long)obj->phys_addr, + (unsigned long long)obj->dev_addr); return 0; } @@ -557,7 +558,6 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf) * refcount on the gem object itself. */ drm_gem_object_reference(obj); - dma_buf_put(buf); return obj; } } @@ -573,6 +573,7 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf) } dobj->obj.import_attach = attach; + get_dma_buf(buf); /* * Don't call dma_buf_map_attachment() here - it maps the diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index f53d5246979..66dd3a001cf 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -566,11 +566,11 @@ err_unload: if (dev->driver->unload) dev->driver->unload(dev); err_primary_node: - drm_put_minor(dev->primary); + drm_unplug_minor(dev->primary); err_render_node: - drm_put_minor(dev->render); + drm_unplug_minor(dev->render); err_control_node: - drm_put_minor(dev->control); + drm_unplug_minor(dev->control); err_agp: if (dev->driver->bus->agp_destroy) dev->driver->bus->agp_destroy(dev); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0cab2d04513..5c648425c1e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -83,6 +83,14 @@ void i915_update_dri1_breadcrumb(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv; + /* + * The dri breadcrumb update races against the drm master disappearing. + * Instead of trying to fix this (this is by far not the only ums issue) + * just don't do the update in kms mode. + */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + if (dev->primary->master) { master_priv = dev->primary->master->driver_priv; if (master_priv->sarea_priv) @@ -1490,16 +1498,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->uncore.lock); spin_lock_init(&dev_priv->mm.object_stat_lock); mutex_init(&dev_priv->dpio_lock); - mutex_init(&dev_priv->rps.hw_lock); mutex_init(&dev_priv->modeset_restore_lock); - mutex_init(&dev_priv->pc8.lock); - dev_priv->pc8.requirements_met = false; - dev_priv->pc8.gpu_idle = false; - dev_priv->pc8.irqs_disabled = false; - dev_priv->pc8.enabled = false; - dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */ - INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work); + intel_pm_setup(dev); intel_display_crc_init(dev); @@ -1603,7 +1604,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) } intel_irq_init(dev); - intel_pm_init(dev); intel_uncore_sanitize(dev); /* Try to make sure MCHBAR is enabled before poking at it */ @@ -1848,8 +1848,10 @@ void i915_driver_lastclose(struct drm_device * dev) void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { + mutex_lock(&dev->struct_mutex); i915_gem_context_close(dev, file_priv); i915_gem_release(dev, file_priv); + mutex_unlock(&dev->struct_mutex); } void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2e367a1c6a6..5b7b7e06cb3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -651,6 +651,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) intel_modeset_init_hw(dev); drm_modeset_lock_all(dev); + drm_mode_config_reset(dev); intel_modeset_setup_hw_state(dev, true); drm_modeset_unlock_all(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ccdbecca070..90fcccba17b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1755,8 +1755,13 @@ struct drm_i915_file_private { #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0xFF00) == 0x0C00) -#define IS_ULT(dev) (IS_HASWELL(dev) && \ +#define IS_BDW_ULT(dev) (IS_BROADWELL(dev) && \ + (((dev)->pdev->device & 0xf) == 0x2 || \ + ((dev)->pdev->device & 0xf) == 0x6 || \ + ((dev)->pdev->device & 0xf) == 0xe)) +#define IS_HSW_ULT(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0xFF00) == 0x0A00) +#define IS_ULT(dev) (IS_HSW_ULT(dev) || IS_BDW_ULT(dev)) #define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0x00F0) == 0x0020) #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) @@ -1901,9 +1906,7 @@ void i915_queue_hangcheck(struct drm_device *dev); void i915_handle_error(struct drm_device *dev, bool wedged); extern void intel_irq_init(struct drm_device *dev); -extern void intel_pm_init(struct drm_device *dev); extern void intel_hpd_init(struct drm_device *dev); -extern void intel_pm_init(struct drm_device *dev); extern void intel_uncore_sanitize(struct drm_device *dev); extern void intel_uncore_early_sanitize(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 72a3df32292..b0f42b9ca03 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -347,10 +347,8 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - mutex_lock(&dev->struct_mutex); idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); idr_destroy(&file_priv->context_idr); - mutex_unlock(&dev->struct_mutex); } static struct i915_hw_context * @@ -423,11 +421,21 @@ static int do_switch(struct i915_hw_context *to) if (ret) return ret; - /* Clear this page out of any CPU caches for coherent swap-in/out. Note + /* + * Pin can switch back to the default context if we end up calling into + * evict_everything - as a last ditch gtt defrag effort that also + * switches to the default context. Hence we need to reload from here. + */ + from = ring->last_context; + + /* + * Clear this page out of any CPU caches for coherent swap-in/out. Note * that thanks to write = false in this call and us not setting any gpu * write domains when putting a context object onto the active list * (when switching away from it), this won't block. - * XXX: We need a real interface to do this instead of trickery. */ + * + * XXX: We need a real interface to do this instead of trickery. + */ ret = i915_gem_object_set_to_gtt_domain(to->obj, false); if (ret) { i915_gem_object_unpin(to->obj); diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index b7376533633..8f3adc7d0dc 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -88,6 +88,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, } else drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level); +search_again: /* First see if there is a large enough contiguous idle region... */ list_for_each_entry(vma, &vm->inactive_list, mm_list) { if (mark_free(vma, &unwind_list)) @@ -115,10 +116,17 @@ none: list_del_init(&vma->exec_list); } - /* We expect the caller to unpin, evict all and try again, or give up. - * So calling i915_gem_evict_vm() is unnecessary. + /* Can we unpin some objects such as idle hw contents, + * or pending flips? */ - return -ENOSPC; + ret = nonblocking ? -ENOSPC : i915_gpu_idle(dev); + if (ret) + return ret; + + /* Only idle the GPU and repeat the search once */ + i915_gem_retire_requests(dev); + nonblocking = true; + goto search_again; found: /* drm_mm doesn't allow any other other operations while diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 38cb8d44a01..c79dd2b1f70 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -337,8 +337,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) kfree(ppgtt->gen8_pt_dma_addr[i]); } - __free_pages(ppgtt->gen8_pt_pages, ppgtt->num_pt_pages << PAGE_SHIFT); - __free_pages(ppgtt->pd_pages, ppgtt->num_pd_pages << PAGE_SHIFT); + __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT)); + __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT)); } /** @@ -1241,6 +1241,11 @@ static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl) bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK; if (bdw_gmch_ctl) bdw_gmch_ctl = 1 << bdw_gmch_ctl; + if (bdw_gmch_ctl > 4) { + WARN_ON(!i915_preliminary_hw_support); + return 4<<20; + } + return bdw_gmch_ctl << 20; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 080f6fd4e83..8b8bde7dce5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9135,7 +9135,7 @@ intel_pipe_config_compare(struct drm_device *dev, if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) PIPE_CONF_CHECK_I(pipe_bpp); - if (!IS_HASWELL(dev)) { + if (!HAS_DDI(dev)) { PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock); PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); } @@ -11036,8 +11036,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, } intel_modeset_check_state(dev); - - drm_mode_config_reset(dev); } void intel_modeset_gem_init(struct drm_device *dev) @@ -11046,7 +11044,10 @@ void intel_modeset_gem_init(struct drm_device *dev) intel_setup_overlay(dev); + drm_modeset_lock_all(dev); + drm_mode_config_reset(dev); intel_modeset_setup_hw_state(dev, false); + drm_modeset_unlock_all(dev); } void intel_modeset_cleanup(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a18e88b3e42..79f91f26e28 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -821,6 +821,7 @@ void intel_update_sprite_watermarks(struct drm_plane *plane, uint32_t sprite_width, int pixel_size, bool enabled, bool scaled); void intel_init_pm(struct drm_device *dev); +void intel_pm_setup(struct drm_device *dev); bool intel_fbc_enabled(struct drm_device *dev); void intel_update_fbc(struct drm_device *dev); void intel_gpu_ips_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index f161ac02c4f..e6f782d1c66 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -451,7 +451,9 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, spin_lock_irqsave(&dev_priv->backlight.lock, flags); - if (HAS_PCH_SPLIT(dev)) { + if (IS_BROADWELL(dev)) { + val = I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; + } else if (HAS_PCH_SPLIT(dev)) { val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } else { if (IS_VALLEYVIEW(dev)) @@ -479,6 +481,13 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, return val; } +static void intel_bdw_panel_set_backlight(struct drm_device *dev, u32 level) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(BLC_PWM_PCH_CTL2, val | level); +} + static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -496,7 +505,9 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); level = intel_panel_compute_brightness(dev, pipe, level); - if (HAS_PCH_SPLIT(dev)) + if (IS_BROADWELL(dev)) + return intel_bdw_panel_set_backlight(dev, level); + else if (HAS_PCH_SPLIT(dev)) return intel_pch_panel_set_backlight(dev, level); if (is_backlight_combination_mode(dev)) { @@ -666,7 +677,16 @@ void intel_panel_enable_backlight(struct intel_connector *connector) POSTING_READ(reg); I915_WRITE(reg, tmp | BLM_PWM_ENABLE); - if (HAS_PCH_SPLIT(dev) && + if (IS_BROADWELL(dev)) { + /* + * Broadwell requires PCH override to drive the PCH + * backlight pin. The above will configure the CPU + * backlight pin, which we don't plan to use. + */ + tmp = I915_READ(BLC_PWM_PCH_CTL1); + tmp |= BLM_PCH_OVERRIDE_ENABLE | BLM_PCH_PWM_ENABLE; + I915_WRITE(BLC_PWM_PCH_CTL1, tmp); + } else if (HAS_PCH_SPLIT(dev) && !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { tmp = I915_READ(BLC_PWM_PCH_CTL1); tmp |= BLM_PCH_PWM_ENABLE; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6e0d5e075b1..3657ab43c8f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5685,6 +5685,7 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; bool is_enabled, enable_requested; + unsigned long irqflags; uint32_t tmp; tmp = I915_READ(HSW_PWR_WELL_DRIVER); @@ -5702,9 +5703,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) HSW_PWR_WELL_STATE_ENABLED), 20)) DRM_ERROR("Timeout enabling power well\n"); } + + if (IS_BROADWELL(dev)) { + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B), + dev_priv->de_irq_mask[PIPE_B]); + I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B), + ~dev_priv->de_irq_mask[PIPE_B] | + GEN8_PIPE_VBLANK); + I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C), + dev_priv->de_irq_mask[PIPE_C]); + I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C), + ~dev_priv->de_irq_mask[PIPE_C] | + GEN8_PIPE_VBLANK); + POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C)); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + } } else { if (enable_requested) { - unsigned long irqflags; enum pipe p; I915_WRITE(HSW_PWR_WELL_DRIVER, 0); @@ -6130,10 +6146,19 @@ int vlv_freq_opcode(int ddr_freq, int val) return val; } -void intel_pm_init(struct drm_device *dev) +void intel_pm_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + mutex_init(&dev_priv->rps.hw_lock); + + mutex_init(&dev_priv->pc8.lock); + dev_priv->pc8.requirements_met = false; + dev_priv->pc8.gpu_idle = false; + dev_priv->pc8.irqs_disabled = false; + dev_priv->pc8.enabled = false; + dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */ + INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work); INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, intel_gen6_powersave_work); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b620337e6d6..c2f09d45630 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -965,6 +965,7 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring) } else if (IS_GEN6(ring->dev)) { mmio = RING_HWS_PGA_GEN6(ring->mmio_base); } else { + /* XXX: gen8 returns to sanity */ mmio = RING_HWS_PGA(ring->mmio_base); } diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 0b02078a0b8..25cbe073c38 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -784,6 +784,7 @@ static int gen6_do_reset(struct drm_device *dev) int intel_gpu_reset(struct drm_device *dev) { switch (INTEL_INFO(dev)->gen) { + case 8: case 7: case 6: return gen6_do_reset(dev); case 5: return ironlake_do_reset(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 7a3759f1c41..98a22e6e27a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -858,6 +858,12 @@ static int nouveau_pmops_runtime_suspend(struct device *dev) if (nouveau_runtime_pm == 0) return -EINVAL; + /* are we optimus enabled? */ + if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) { + DRM_DEBUG_DRIVER("failing to power off - not optimus\n"); + return -EINVAL; + } + nv_debug_level(SILENT); drm_kms_helper_poll_disable(drm_dev); vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF); diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 80a20120e62..b1970596a78 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1196,7 +1196,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, } else if ((rdev->family == CHIP_TAHITI) || (rdev->family == CHIP_PITCAIRN)) fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16); - else if (rdev->family == CHIP_VERDE) + else if ((rdev->family == CHIP_VERDE) || + (rdev->family == CHIP_OLAND) || + (rdev->family == CHIP_HAINAN)) /* for completeness. HAINAN has no display hw */ fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16); switch (radeon_crtc->crtc_id) { diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index 0300727a4f7..d08b83c6267 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -458,7 +458,7 @@ int cik_copy_dma(struct radeon_device *rdev, radeon_ring_write(ring, 0); /* src/dst endian swap */ radeon_ring_write(ring, src_offset & 0xffffffff); radeon_ring_write(ring, upper_32_bits(src_offset) & 0xffffffff); - radeon_ring_write(ring, dst_offset & 0xfffffffc); + radeon_ring_write(ring, dst_offset & 0xffffffff); radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xffffffff); src_offset += cur_size_in_bytes; dst_offset += cur_size_in_bytes; diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index e354ce94cdd..c0425bb6223 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2021,7 +2021,7 @@ static struct radeon_asic ci_asic = { .hdmi_setmode = &evergreen_hdmi_setmode, }, .copy = { - .blit = NULL, + .blit = &cik_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &cik_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, @@ -2122,7 +2122,7 @@ static struct radeon_asic kv_asic = { .hdmi_setmode = &evergreen_hdmi_setmode, }, .copy = { - .blit = NULL, + .blit = &cik_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &cik_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 9f5ff28864f..1958b36ad0e 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -508,15 +508,6 @@ static const struct file_operations radeon_driver_kms_fops = { #endif }; - -static void -radeon_pci_shutdown(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - - radeon_driver_unload_kms(dev); -} - static struct drm_driver kms_driver = { .driver_features = DRIVER_USE_AGP | @@ -586,7 +577,6 @@ static struct pci_driver radeon_kms_pci_driver = { .probe = radeon_pci_probe, .remove = radeon_pci_remove, .driver.pm = &radeon_pm_ops, - .shutdown = radeon_pci_shutdown, }; static int __init radeon_init(void) diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index dc75bb603ea..984097b907e 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -552,8 +552,7 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev, struct device_attribute *attr, char *buf) { - struct drm_device *ddev = dev_get_drvdata(dev); - struct radeon_device *rdev = ddev->dev_private; + struct radeon_device *rdev = dev_get_drvdata(dev); int hyst = to_sensor_dev_attr(attr)->index; int temp; @@ -580,8 +579,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct attribute *attr, int index) { struct device *dev = container_of(kobj, struct device, kobj); - struct drm_device *ddev = dev_get_drvdata(dev); - struct radeon_device *rdev = ddev->dev_private; + struct radeon_device *rdev = dev_get_drvdata(dev); /* Skip limit attributes if DPM is not enabled */ if (rdev->pm.pm_method != PM_METHOD_DPM && diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 1c560629575..e7dab069ccc 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -162,6 +162,16 @@ static void rs690_mc_init(struct radeon_device *rdev) base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); base = G_000100_MC_FB_START(base) << 16; rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); + /* Some boards seem to be configured for 128MB of sideport memory, + * but really only have 64MB. Just skip the sideport and use + * UMA memory. + */ + if (rdev->mc.igp_sideport_enabled && + (rdev->mc.real_vram_size == (384 * 1024 * 1024))) { + base += 128 * 1024 * 1024; + rdev->mc.real_vram_size -= 128 * 1024 * 1024; + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; + } /* Use K8 direct mapping for fast fb access. */ rdev->fastfb_working = false; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index a51f48e3e91..45d5b5ab6ca 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -68,6 +68,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, SVGA_FIFO_3D_HWVERSION)); break; } + case DRM_VMW_PARAM_MAX_SURF_MEMORY: + param->value = dev_priv->memory_size; + break; default: DRM_ERROR("Illegal vmwgfx get param request: %d\n", param->param); diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index a184e1921c1..d87f7cb4bee 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -112,13 +112,15 @@ static int sensor_hub_get_physical_device_count( static void sensor_hub_fill_attr_info( struct hid_sensor_hub_attribute_info *info, - s32 index, s32 report_id, s32 units, s32 unit_expo, s32 size) + s32 index, s32 report_id, struct hid_field *field) { info->index = index; info->report_id = report_id; - info->units = units; - info->unit_expo = unit_expo; - info->size = size/8; + info->units = field->unit; + info->unit_expo = field->unit_exponent; + info->size = (field->report_size * field->report_count)/8; + info->logical_minimum = field->logical_minimum; + info->logical_maximum = field->logical_maximum; } static struct hid_sensor_hub_callbacks *sensor_hub_get_callback( @@ -325,9 +327,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, if (field->physical == usage_id && field->logical == attr_usage_id) { sensor_hub_fill_attr_info(info, i, report->id, - field->unit, field->unit_exponent, - field->report_size * - field->report_count); + field); ret = 0; } else { for (j = 0; j < field->maxusage; ++j) { @@ -336,11 +336,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev, field->usage[j].collection_index == collection_index) { sensor_hub_fill_attr_info(info, - i, report->id, - field->unit, - field->unit_exponent, - field->report_size * - field->report_count); + i, report->id, field); ret = 0; break; } diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index cbd4e9abc47..92d1206482a 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -329,7 +329,7 @@ static struct cpuidle_state atom_cstates[] __initdata = { { .enter = NULL } }; -static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = { +static struct cpuidle_state avn_cstates[] __initdata = { { .name = "C1-AVN", .desc = "MWAIT 0x00", @@ -340,7 +340,7 @@ static struct cpuidle_state avn_cstates[CPUIDLE_STATE_MAX] = { { .name = "C6-AVN", .desc = "MWAIT 0x51", - .flags = MWAIT2flg(0x58) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 15, .target_residency = 45, .enter = &intel_idle }, diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig index 1178121b55b..39188b72cd3 100644 --- a/drivers/iio/common/hid-sensors/Kconfig +++ b/drivers/iio/common/hid-sensors/Kconfig @@ -25,13 +25,4 @@ config HID_SENSOR_IIO_TRIGGER If this driver is compiled as a module, it will be named hid-sensor-trigger. -config HID_SENSOR_ENUM_BASE_QUIRKS - bool "ENUM base quirks for HID Sensor IIO drivers" - depends on HID_SENSOR_IIO_COMMON - help - Say yes here to build support for sensor hub FW using - enumeration, which is using 1 as base instead of 0. - Since logical minimum is still set 0 instead of 1, - there is no easy way to differentiate. - endmenu diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index bbd6426c972..7dcf83998e6 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -33,24 +33,34 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, { struct hid_sensor_common *st = iio_trigger_get_drvdata(trig); int state_val; + int report_val; if (state) { if (sensor_hub_device_open(st->hsdev)) return -EIO; - } else + state_val = + HID_USAGE_SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM; + report_val = + HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM; + + } else { sensor_hub_device_close(st->hsdev); + state_val = + HID_USAGE_SENSOR_PROP_POWER_STATE_D4_POWER_OFF_ENUM; + report_val = + HID_USAGE_SENSOR_PROP_REPORTING_STATE_NO_EVENTS_ENUM; + } - state_val = state ? 1 : 0; - if (IS_ENABLED(CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS)) - ++state_val; st->data_ready = state; + state_val += st->power_state.logical_minimum; + report_val += st->report_state.logical_minimum; sensor_hub_set_feature(st->hsdev, st->power_state.report_id, st->power_state.index, (s32)state_val); sensor_hub_set_feature(st->hsdev, st->report_state.report_id, st->report_state.index, - (s32)state_val); + (s32)report_val); return 0; } diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index b0d65df3ede..a022f27c669 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -43,6 +43,7 @@ config GP2AP020A00F depends on I2C select IIO_BUFFER select IIO_TRIGGERED_BUFFER + select IRQ_WORK help Say Y here if you have a Sharp GP2AP020A00F proximity/ALS combo-chip hooked to an I2C bus. diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index dbd2047f164..3ed23513d88 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -536,7 +536,8 @@ static int adp5588_probe(struct i2c_client *client, __set_bit(EV_REP, input->evbit); for (i = 0; i < input->keycodemax; i++) - __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit); + if (kpad->keycode[i] <= KEY_MAX) + __set_bit(kpad->keycode[i], input->keybit); __clear_bit(KEY_RESERVED, input->keybit); if (kpad->gpimapsize) diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 67d12b3427c..60dafd4fa69 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -992,7 +992,8 @@ static int adp5589_probe(struct i2c_client *client, __set_bit(EV_REP, input->evbit); for (i = 0; i < input->keycodemax; i++) - __set_bit(kpad->keycode[i] & KEY_MAX, input->keybit); + if (kpad->keycode[i] <= KEY_MAX) + __set_bit(kpad->keycode[i], input->keybit); __clear_bit(KEY_RESERVED, input->keybit); if (kpad->gpimapsize) diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index fc88fb48d70..09b91d09308 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -289,7 +289,8 @@ static int bfin_kpad_probe(struct platform_device *pdev) __set_bit(EV_REP, input->evbit); for (i = 0; i < input->keycodemax; i++) - __set_bit(bf54x_kpad->keycode[i] & KEY_MAX, input->keybit); + if (bf54x_kpad->keycode[i] <= KEY_MAX) + __set_bit(bf54x_kpad->keycode[i], input->keybit); __clear_bit(KEY_RESERVED, input->keybit); error = input_register_device(input); diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index e37392976fd..0deca5a3c87 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c @@ -113,9 +113,12 @@ static int pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_i idev->keycodemax = ARRAY_SIZE(lp->btncode); for (i = 0; i < ARRAY_SIZE(pcf8574_kp_btncode); i++) { - lp->btncode[i] = pcf8574_kp_btncode[i]; - __set_bit(lp->btncode[i] & KEY_MAX, idev->keybit); + if (lp->btncode[i] <= KEY_MAX) { + lp->btncode[i] = pcf8574_kp_btncode[i]; + __set_bit(lp->btncode[i], idev->keybit); + } } + __clear_bit(KEY_RESERVED, idev->keybit); sprintf(lp->name, DRV_NAME); sprintf(lp->phys, "kp_data/input0"); diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index ca7a26f1dce..5cf62e31521 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -70,6 +70,25 @@ static const struct alps_nibble_commands alps_v4_nibble_commands[] = { { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ }; +static const struct alps_nibble_commands alps_v6_nibble_commands[] = { + { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */ + { PSMOUSE_CMD_SETRATE, 0x0a }, /* 1 */ + { PSMOUSE_CMD_SETRATE, 0x14 }, /* 2 */ + { PSMOUSE_CMD_SETRATE, 0x28 }, /* 3 */ + { PSMOUSE_CMD_SETRATE, 0x3c }, /* 4 */ + { PSMOUSE_CMD_SETRATE, 0x50 }, /* 5 */ + { PSMOUSE_CMD_SETRATE, 0x64 }, /* 6 */ + { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 7 */ + { PSMOUSE_CMD_GETID, 0x00 }, /* 8 */ + { PSMOUSE_CMD_GETINFO, 0x00 }, /* 9 */ + { PSMOUSE_CMD_SETRES, 0x00 }, /* a */ + { PSMOUSE_CMD_SETRES, 0x01 }, /* b */ + { PSMOUSE_CMD_SETRES, 0x02 }, /* c */ + { PSMOUSE_CMD_SETRES, 0x03 }, /* d */ + { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* e */ + { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */ +}; + #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ #define ALPS_PASS 0x04 /* device has a pass-through port */ @@ -103,6 +122,7 @@ static const struct alps_model_info alps_model_data[] = { /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ { { 0x62, 0x02, 0x14 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, + { { 0x73, 0x00, 0x14 }, 0x00, ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT }, /* Dell XT2 */ { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ @@ -645,6 +665,76 @@ static void alps_process_packet_v3(struct psmouse *psmouse) alps_process_touchpad_packet_v3(psmouse); } +static void alps_process_packet_v6(struct psmouse *psmouse) +{ + struct alps_data *priv = psmouse->private; + unsigned char *packet = psmouse->packet; + struct input_dev *dev = psmouse->dev; + struct input_dev *dev2 = priv->dev2; + int x, y, z, left, right, middle; + + /* + * We can use Byte5 to distinguish if the packet is from Touchpad + * or Trackpoint. + * Touchpad: 0 - 0x7E + * Trackpoint: 0x7F + */ + if (packet[5] == 0x7F) { + /* It should be a DualPoint when received Trackpoint packet */ + if (!(priv->flags & ALPS_DUALPOINT)) + return; + + /* Trackpoint packet */ + x = packet[1] | ((packet[3] & 0x20) << 2); + y = packet[2] | ((packet[3] & 0x40) << 1); + z = packet[4]; + left = packet[3] & 0x01; + right = packet[3] & 0x02; + middle = packet[3] & 0x04; + + /* To prevent the cursor jump when finger lifted */ + if (x == 0x7F && y == 0x7F && z == 0x7F) + x = y = z = 0; + + /* Divide 4 since trackpoint's speed is too fast */ + input_report_rel(dev2, REL_X, (char)x / 4); + input_report_rel(dev2, REL_Y, -((char)y / 4)); + + input_report_key(dev2, BTN_LEFT, left); + input_report_key(dev2, BTN_RIGHT, right); + input_report_key(dev2, BTN_MIDDLE, middle); + + input_sync(dev2); + return; + } + + /* Touchpad packet */ + x = packet[1] | ((packet[3] & 0x78) << 4); + y = packet[2] | ((packet[4] & 0x78) << 4); + z = packet[5]; + left = packet[3] & 0x01; + right = packet[3] & 0x02; + + if (z > 30) + input_report_key(dev, BTN_TOUCH, 1); + if (z < 25) + input_report_key(dev, BTN_TOUCH, 0); + + if (z > 0) { + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); + } + + input_report_abs(dev, ABS_PRESSURE, z); + input_report_key(dev, BTN_TOOL_FINGER, z > 0); + + /* v6 touchpad does not have middle button */ + input_report_key(dev, BTN_LEFT, left); + input_report_key(dev, BTN_RIGHT, right); + + input_sync(dev); +} + static void alps_process_packet_v4(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; @@ -897,7 +987,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) } /* Bytes 2 - pktsize should have 0 in the highest bit */ - if (priv->proto_version != ALPS_PROTO_V5 && + if ((priv->proto_version < ALPS_PROTO_V5) && psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", @@ -1085,6 +1175,80 @@ static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL); } +static int alps_monitor_mode_send_word(struct psmouse *psmouse, u16 word) +{ + int i, nibble; + + /* + * b0-b11 are valid bits, send sequence is inverse. + * e.g. when word = 0x0123, nibble send sequence is 3, 2, 1 + */ + for (i = 0; i <= 8; i += 4) { + nibble = (word >> i) & 0xf; + if (alps_command_mode_send_nibble(psmouse, nibble)) + return -1; + } + + return 0; +} + +static int alps_monitor_mode_write_reg(struct psmouse *psmouse, + u16 addr, u16 value) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + + /* 0x0A0 is the command to write the word */ + if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE) || + alps_monitor_mode_send_word(psmouse, 0x0A0) || + alps_monitor_mode_send_word(psmouse, addr) || + alps_monitor_mode_send_word(psmouse, value) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE)) + return -1; + + return 0; +} + +static int alps_monitor_mode(struct psmouse *psmouse, bool enable) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + + if (enable) { + /* EC E9 F5 F5 E7 E6 E7 E9 to enter monitor mode */ + if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO)) + return -1; + } else { + /* EC to exit monitor mode */ + if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP)) + return -1; + } + + return 0; +} + +static int alps_absolute_mode_v6(struct psmouse *psmouse) +{ + u16 reg_val = 0x181; + int ret = -1; + + /* enter monitor mode, to write the register */ + if (alps_monitor_mode(psmouse, true)) + return -1; + + ret = alps_monitor_mode_write_reg(psmouse, 0x000, reg_val); + + if (alps_monitor_mode(psmouse, false)) + ret = -1; + + return ret; +} + static int alps_get_status(struct psmouse *psmouse, char *param) { /* Get status: 0xF5 0xF5 0xF5 0xE9 */ @@ -1189,6 +1353,32 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) return 0; } +static int alps_hw_init_v6(struct psmouse *psmouse) +{ + unsigned char param[2] = {0xC8, 0x14}; + + /* Enter passthrough mode to let trackpoint enter 6byte raw mode */ + if (alps_passthrough_mode_v2(psmouse, true)) + return -1; + + if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || + ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || + ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || + ps2_command(&psmouse->ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || + ps2_command(&psmouse->ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) + return -1; + + if (alps_passthrough_mode_v2(psmouse, false)) + return -1; + + if (alps_absolute_mode_v6(psmouse)) { + psmouse_err(psmouse, "Failed to enable absolute mode\n"); + return -1; + } + + return 0; +} + /* * Enable or disable passthrough mode to the trackstick. */ @@ -1553,6 +1743,8 @@ static void alps_set_defaults(struct alps_data *priv) priv->hw_init = alps_hw_init_v1_v2; priv->process_packet = alps_process_packet_v1_v2; priv->set_abs_params = alps_set_abs_params_st; + priv->x_max = 1023; + priv->y_max = 767; break; case ALPS_PROTO_V3: priv->hw_init = alps_hw_init_v3; @@ -1584,6 +1776,14 @@ static void alps_set_defaults(struct alps_data *priv) priv->x_bits = 23; priv->y_bits = 12; break; + case ALPS_PROTO_V6: + priv->hw_init = alps_hw_init_v6; + priv->process_packet = alps_process_packet_v6; + priv->set_abs_params = alps_set_abs_params_st; + priv->nibble_commands = alps_v6_nibble_commands; + priv->x_max = 2047; + priv->y_max = 1535; + break; } } @@ -1705,8 +1905,8 @@ static void alps_disconnect(struct psmouse *psmouse) static void alps_set_abs_params_st(struct alps_data *priv, struct input_dev *dev1) { - input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); - input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); + input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); + input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); } static void alps_set_abs_params_mt(struct alps_data *priv, diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index eee59853b9c..704f0f92430 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h @@ -17,6 +17,7 @@ #define ALPS_PROTO_V3 3 #define ALPS_PROTO_V4 4 #define ALPS_PROTO_V5 5 +#define ALPS_PROTO_V6 6 /** * struct alps_model_info - touchpad ID table diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 8551dcaf24d..597e9b8fc18 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1313,6 +1313,7 @@ static int elantech_set_properties(struct elantech_data *etd) break; case 6: case 7: + case 8: etd->hw_version = 4; break; default: diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index cfd1b7e8c00..f1cb05148b4 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -251,7 +251,7 @@ static void sur40_poll(struct input_polled_dev *polldev) struct sur40_state *sur40 = polldev->private; struct input_dev *input = polldev->input; int result, bulk_read, need_blobs, packet_blobs, i; - u32 packet_id; + u32 uninitialized_var(packet_id); struct sur40_header *header = &sur40->bulk_in_buffer->header; struct sur40_blob *inblob = &sur40->bulk_in_buffer->blobs[0]; @@ -286,7 +286,7 @@ static void sur40_poll(struct input_polled_dev *polldev) if (need_blobs == -1) { need_blobs = le16_to_cpu(header->count); dev_dbg(sur40->dev, "need %d blobs\n", need_blobs); - packet_id = header->packet_id; + packet_id = le32_to_cpu(header->packet_id); } /* diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index ae4b6b90362..5f87bed0546 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -106,6 +106,7 @@ struct usbtouch_device_info { struct usbtouch_usb { unsigned char *data; dma_addr_t data_dma; + int data_size; unsigned char *buffer; int buf_len; struct urb *irq; @@ -1521,7 +1522,7 @@ static int usbtouch_reset_resume(struct usb_interface *intf) static void usbtouch_free_buffers(struct usb_device *udev, struct usbtouch_usb *usbtouch) { - usb_free_coherent(udev, usbtouch->type->rept_size, + usb_free_coherent(udev, usbtouch->data_size, usbtouch->data, usbtouch->data_dma); kfree(usbtouch->buffer); } @@ -1566,7 +1567,20 @@ static int usbtouch_probe(struct usb_interface *intf, if (!type->process_pkt) type->process_pkt = usbtouch_process_pkt; - usbtouch->data = usb_alloc_coherent(udev, type->rept_size, + usbtouch->data_size = type->rept_size; + if (type->get_pkt_len) { + /* + * When dealing with variable-length packets we should + * not request more than wMaxPacketSize bytes at once + * as we do not know if there is more data coming or + * we filled exactly wMaxPacketSize bytes and there is + * nothing else. + */ + usbtouch->data_size = min(usbtouch->data_size, + usb_endpoint_maxp(endpoint)); + } + + usbtouch->data = usb_alloc_coherent(udev, usbtouch->data_size, GFP_KERNEL, &usbtouch->data_dma); if (!usbtouch->data) goto out_free; @@ -1626,12 +1640,12 @@ static int usbtouch_probe(struct usb_interface *intf, if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) usb_fill_int_urb(usbtouch->irq, udev, usb_rcvintpipe(udev, endpoint->bEndpointAddress), - usbtouch->data, type->rept_size, + usbtouch->data, usbtouch->data_size, usbtouch_irq, usbtouch, endpoint->bInterval); else usb_fill_bulk_urb(usbtouch->irq, udev, usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), - usbtouch->data, type->rept_size, + usbtouch->data, usbtouch->data_size, usbtouch_irq, usbtouch); usbtouch->irq->dev = udev; diff --git a/drivers/md/md.c b/drivers/md/md.c index e60cebf3f51..21f4d7ff0da 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -776,16 +776,10 @@ void md_super_wait(struct mddev *mddev) finish_wait(&mddev->sb_wait, &wq); } -static void bi_complete(struct bio *bio, int error) -{ - complete((struct completion*)bio->bi_private); -} - int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, struct page *page, int rw, bool metadata_op) { struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev); - struct completion event; int ret; rw |= REQ_SYNC; @@ -801,11 +795,7 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, else bio->bi_sector = sector + rdev->data_offset; bio_add_page(bio, page, size, 0); - init_completion(&event); - bio->bi_private = &event; - bio->bi_end_io = bi_complete; - submit_bio(rw, bio); - wait_for_completion(&event); + submit_bio_wait(rw, bio); ret = test_bit(BIO_UPTODATE, &bio->bi_flags); bio_put(bio); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 62a60caa5d1..dd671582c9a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -32,7 +32,7 @@ config MFD_AS3722 select MFD_CORE select REGMAP_I2C select REGMAP_IRQ - depends on I2C && OF + depends on I2C=y && OF help The ams AS3722 is a compact system PMU suitable for mobile phones, tablets etc. It has 4 DC/DC step-down regulators, 3 DC/DC step-down diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index da1c6566d93..37edf9e989b 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -506,7 +506,7 @@ static struct lpc_ich_info lpc_chipset_info[] = { .iTCO_version = 2, }, [LPC_WPT_LP] = { - .name = "Lynx Point_LP", + .name = "Wildcat Point_LP", .iTCO_version = 2, }, }; diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c index 71e3e0c5bf7..a5424579679 100644 --- a/drivers/mfd/ti-ssp.c +++ b/drivers/mfd/ti-ssp.c @@ -32,6 +32,7 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/sched.h> #include <linux/mfd/core.h> #include <linux/mfd/ti_ssp.h> @@ -409,7 +410,6 @@ static int ti_ssp_probe(struct platform_device *pdev) cells[id].id = id; cells[id].name = data->dev_name; cells[id].platform_data = data->pdata; - cells[id].data_size = data->pdata_size; } error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL); diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index 0e8df41aaf1..2cf2bbc0b92 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c @@ -198,6 +198,13 @@ static void enclosure_remove_links(struct enclosure_component *cdev) { char name[ENCLOSURE_NAME_SIZE]; + /* + * In odd circumstances, like multipath devices, something else may + * already have removed the links, so check for this condition first. + */ + if (!cdev->dev->kobj.sd) + return; + enclosure_link_name(cdev, name); sysfs_remove_link(&cdev->dev->kobj, name); sysfs_remove_link(&cdev->cdev.kobj, "device"); diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index 6c0fde55270..66f411a6e8e 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -109,9 +109,12 @@ #define MEI_DEV_ID_PPT_2 0x1CBA /* Panther Point */ #define MEI_DEV_ID_PPT_3 0x1DBA /* Panther Point */ -#define MEI_DEV_ID_LPT 0x8C3A /* Lynx Point */ +#define MEI_DEV_ID_LPT_H 0x8C3A /* Lynx Point H */ #define MEI_DEV_ID_LPT_W 0x8D3A /* Lynx Point - Wellsburg */ #define MEI_DEV_ID_LPT_LP 0x9C3A /* Lynx Point LP */ +#define MEI_DEV_ID_LPT_HR 0x8CBA /* Lynx Point H Refresh */ + +#define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */ /* * MEI HW Section */ diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index b96205aece0..2cab3c0a680 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -76,9 +76,11 @@ static DEFINE_PCI_DEVICE_TABLE(mei_me_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_H)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_W)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_LP)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_LPT_HR)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_WPT_LP)}, /* required last entry */ {0, } diff --git a/drivers/misc/mic/card/mic_virtio.c b/drivers/misc/mic/card/mic_virtio.c index 8aa42e738ac..653799b96bf 100644 --- a/drivers/misc/mic/card/mic_virtio.c +++ b/drivers/misc/mic/card/mic_virtio.c @@ -154,14 +154,14 @@ static void mic_reset_inform_host(struct virtio_device *vdev) { struct mic_vdev *mvdev = to_micvdev(vdev); struct mic_device_ctrl __iomem *dc = mvdev->dc; - int retry = 100, i; + int retry; iowrite8(0, &dc->host_ack); iowrite8(1, &dc->vdev_reset); mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db); /* Wait till host completes all card accesses and acks the reset */ - for (i = retry; i--;) { + for (retry = 100; retry--;) { if (ioread8(&dc->host_ack)) break; msleep(100); @@ -187,11 +187,12 @@ static void mic_reset(struct virtio_device *vdev) /* * The virtio_ring code calls this API when it wants to notify the Host. */ -static void mic_notify(struct virtqueue *vq) +static bool mic_notify(struct virtqueue *vq) { struct mic_vdev *mvdev = vq->priv; mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db); + return true; } static void mic_del_vq(struct virtqueue *vq, int n) @@ -247,17 +248,17 @@ static struct virtqueue *mic_find_vq(struct virtio_device *vdev, /* First assign the vring's allocated in host memory */ vqconfig = mic_vq_config(mvdev->desc) + index; memcpy_fromio(&config, vqconfig, sizeof(config)); - _vr_size = vring_size(config.num, MIC_VIRTIO_RING_ALIGN); + _vr_size = vring_size(le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN); vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info)); - va = mic_card_map(mvdev->mdev, config.address, vr_size); + va = mic_card_map(mvdev->mdev, le64_to_cpu(config.address), vr_size); if (!va) return ERR_PTR(-ENOMEM); mvdev->vr[index] = va; memset_io(va, 0x0, _vr_size); - vq = vring_new_virtqueue(index, - config.num, MIC_VIRTIO_RING_ALIGN, vdev, - false, - va, mic_notify, callback, name); + vq = vring_new_virtqueue(index, le16_to_cpu(config.num), + MIC_VIRTIO_RING_ALIGN, vdev, false, + (void __force *)va, mic_notify, callback, + name); if (!vq) { err = -ENOMEM; goto unmap; @@ -272,7 +273,8 @@ static struct virtqueue *mic_find_vq(struct virtio_device *vdev, /* Allocate and reassign used ring now */ mvdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 + - sizeof(struct vring_used_elem) * config.num); + sizeof(struct vring_used_elem) * + le16_to_cpu(config.num)); used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(mvdev->used_size[index])); if (!used) { @@ -309,7 +311,7 @@ static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs, { struct mic_vdev *mvdev = to_micvdev(vdev); struct mic_device_ctrl __iomem *dc = mvdev->dc; - int i, err, retry = 100; + int i, err, retry; /* We must have this many virtqueues. */ if (nvqs > ioread8(&mvdev->desc->num_vq)) @@ -331,7 +333,7 @@ static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs, * rings have been re-assigned. */ mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db); - for (i = retry; i--;) { + for (retry = 100; retry--;) { if (!ioread8(&dc->used_address_updated)) break; msleep(100); @@ -519,8 +521,8 @@ static void mic_scan_devices(struct mic_driver *mdrv, bool remove) struct device *dev; int ret; - for (i = mic_aligned_size(struct mic_bootparam); - i < MIC_DP_SIZE; i += mic_total_desc_size(d)) { + for (i = sizeof(struct mic_bootparam); i < MIC_DP_SIZE; + i += mic_total_desc_size(d)) { d = mdrv->dp + i; dc = (void __iomem *)d + mic_aligned_desc_size(d); /* @@ -539,7 +541,8 @@ static void mic_scan_devices(struct mic_driver *mdrv, bool remove) continue; /* device already exists */ - dev = device_find_child(mdrv->dev, d, mic_match_desc); + dev = device_find_child(mdrv->dev, (void __force *)d, + mic_match_desc); if (dev) { if (remove) iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE, diff --git a/drivers/misc/mic/card/mic_virtio.h b/drivers/misc/mic/card/mic_virtio.h index 2c5c22c93ba..d0407ba53bb 100644 --- a/drivers/misc/mic/card/mic_virtio.h +++ b/drivers/misc/mic/card/mic_virtio.h @@ -42,8 +42,8 @@ static inline unsigned mic_desc_size(struct mic_device_desc __iomem *desc) { - return mic_aligned_size(*desc) - + ioread8(&desc->num_vq) * mic_aligned_size(struct mic_vqconfig) + return sizeof(*desc) + + ioread8(&desc->num_vq) * sizeof(struct mic_vqconfig) + ioread8(&desc->feature_len) * 2 + ioread8(&desc->config_len); } @@ -67,8 +67,7 @@ mic_vq_configspace(struct mic_device_desc __iomem *desc) } static inline unsigned mic_total_desc_size(struct mic_device_desc __iomem *desc) { - return mic_aligned_desc_size(desc) + - mic_aligned_size(struct mic_device_ctrl); + return mic_aligned_desc_size(desc) + sizeof(struct mic_device_ctrl); } int mic_devices_init(struct mic_driver *mdrv); diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c index 7558d918643..b75c6b5cc20 100644 --- a/drivers/misc/mic/host/mic_boot.c +++ b/drivers/misc/mic/host/mic_boot.c @@ -62,7 +62,7 @@ void mic_bootparam_init(struct mic_device *mdev) { struct mic_bootparam *bootparam = mdev->dp; - bootparam->magic = MIC_MAGIC; + bootparam->magic = cpu_to_le32(MIC_MAGIC); bootparam->c2h_shutdown_db = mdev->shutdown_db; bootparam->h2c_shutdown_db = -1; bootparam->h2c_config_db = -1; diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c index 5b8494bd1e0..e04bb4fe682 100644 --- a/drivers/misc/mic/host/mic_virtio.c +++ b/drivers/misc/mic/host/mic_virtio.c @@ -41,7 +41,7 @@ static int mic_virtio_copy_to_user(struct mic_vdev *mvdev, * We are copying from IO below an should ideally use something * like copy_to_user_fromio(..) if it existed. */ - if (copy_to_user(ubuf, dbuf, len)) { + if (copy_to_user(ubuf, (void __force *)dbuf, len)) { err = -EFAULT; dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err); @@ -66,7 +66,7 @@ static int mic_virtio_copy_from_user(struct mic_vdev *mvdev, * We are copying to IO below and should ideally use something * like copy_from_user_toio(..) if it existed. */ - if (copy_from_user(dbuf, ubuf, len)) { + if (copy_from_user((void __force *)dbuf, ubuf, len)) { err = -EFAULT; dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err); @@ -293,7 +293,7 @@ static void mic_virtio_init_post(struct mic_vdev *mvdev) continue; } mvdev->mvr[i].vrh.vring.used = - mvdev->mdev->aper.va + + (void __force *)mvdev->mdev->aper.va + le64_to_cpu(vqconfig[i].used_address); } @@ -378,7 +378,7 @@ int mic_virtio_config_change(struct mic_vdev *mvdev, void __user *argp) { DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); - int ret = 0, retry = 100, i; + int ret = 0, retry, i; struct mic_bootparam *bootparam = mvdev->mdev->dp; s8 db = bootparam->h2c_config_db; @@ -401,7 +401,7 @@ int mic_virtio_config_change(struct mic_vdev *mvdev, mvdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED; mvdev->mdev->ops->send_intr(mvdev->mdev, db); - for (i = retry; i--;) { + for (retry = 100; retry--;) { ret = wait_event_timeout(wake, mvdev->dc->guest_ack, msecs_to_jiffies(100)); if (ret) @@ -467,7 +467,7 @@ static int mic_copy_dp_entry(struct mic_vdev *mvdev, } /* Find the first free device page entry */ - for (i = mic_aligned_size(struct mic_bootparam); + for (i = sizeof(struct mic_bootparam); i < MIC_DP_SIZE - mic_total_desc_size(dd_config); i += mic_total_desc_size(devp)) { devp = mdev->dp + i; @@ -525,6 +525,7 @@ int mic_virtio_add_device(struct mic_vdev *mvdev, char irqname[10]; struct mic_bootparam *bootparam = mdev->dp; u16 num; + dma_addr_t vr_addr; mutex_lock(&mdev->mic_mutex); @@ -559,17 +560,16 @@ int mic_virtio_add_device(struct mic_vdev *mvdev, } vr->len = vr_size; vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN); - vr->info->magic = MIC_MAGIC + mvdev->virtio_id + i; - vqconfig[i].address = mic_map_single(mdev, - vr->va, vr_size); - if (mic_map_error(vqconfig[i].address)) { + vr->info->magic = cpu_to_le32(MIC_MAGIC + mvdev->virtio_id + i); + vr_addr = mic_map_single(mdev, vr->va, vr_size); + if (mic_map_error(vr_addr)) { free_pages((unsigned long)vr->va, get_order(vr_size)); ret = -ENOMEM; dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, ret); goto err; } - vqconfig[i].address = cpu_to_le64(vqconfig[i].address); + vqconfig[i].address = cpu_to_le64(vr_addr); vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN); ret = vringh_init_kern(&mvr->vrh, @@ -639,7 +639,7 @@ void mic_virtio_del_device(struct mic_vdev *mvdev) struct mic_vdev *tmp_mvdev; struct mic_device *mdev = mvdev->mdev; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); - int i, ret, retry = 100; + int i, ret, retry; struct mic_vqconfig *vqconfig; struct mic_bootparam *bootparam = mdev->dp; s8 db; @@ -652,16 +652,16 @@ void mic_virtio_del_device(struct mic_vdev *mvdev) "Requesting hot remove id %d\n", mvdev->virtio_id); mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE; mdev->ops->send_intr(mdev, db); - for (i = retry; i--;) { + for (retry = 100; retry--;) { ret = wait_event_timeout(wake, mvdev->dc->guest_ack, msecs_to_jiffies(100)); if (ret) break; } dev_dbg(mdev->sdev->parent, - "Device id %d config_change %d guest_ack %d\n", + "Device id %d config_change %d guest_ack %d retry %d\n", mvdev->virtio_id, mvdev->dc->config_change, - mvdev->dc->guest_ack); + mvdev->dc->guest_ack, retry); mvdev->dc->config_change = 0; mvdev->dc->guest_ack = 0; skip_hot_remove: diff --git a/drivers/misc/mic/host/mic_x100.c b/drivers/misc/mic/host/mic_x100.c index 81e9541b784..0dfa8a81436 100644 --- a/drivers/misc/mic/host/mic_x100.c +++ b/drivers/misc/mic/host/mic_x100.c @@ -397,8 +397,8 @@ mic_x100_load_ramdisk(struct mic_device *mdev) * so copy over the ramdisk @ 128M. */ memcpy_toio(mdev->aper.va + (mdev->bootaddr << 1), fw->data, fw->size); - iowrite32(cpu_to_le32(mdev->bootaddr << 1), &bp->hdr.ramdisk_image); - iowrite32(cpu_to_le32(fw->size), &bp->hdr.ramdisk_size); + iowrite32(mdev->bootaddr << 1, &bp->hdr.ramdisk_image); + iowrite32(fw->size, &bp->hdr.ramdisk_size); release_firmware(fw); error: return rc; diff --git a/drivers/pinctrl/pinctrl-abx500.c b/drivers/pinctrl/pinctrl-abx500.c index 4780959e11d..5183e7bb8de 100644 --- a/drivers/pinctrl/pinctrl-abx500.c +++ b/drivers/pinctrl/pinctrl-abx500.c @@ -418,7 +418,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG, af.alt_bit1, - !!(af.alta_val && BIT(0))); + !!(af.alta_val & BIT(0))); if (ret < 0) goto out; @@ -439,7 +439,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, goto out; ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG, - af.alt_bit1, !!(af.altb_val && BIT(0))); + af.alt_bit1, !!(af.altb_val & BIT(0))); if (ret < 0) goto out; @@ -462,7 +462,7 @@ static int abx500_set_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, goto out; ret = abx500_gpio_set_bits(chip, AB8500_GPIO_ALTFUN_REG, - af.alt_bit2, !!(af.altc_val && BIT(1))); + af.alt_bit2, !!(af.altc_val & BIT(1))); break; default: diff --git a/drivers/pinctrl/pinctrl-abx500.h b/drivers/pinctrl/pinctrl-abx500.h index eeca8f97399..82293806e84 100644 --- a/drivers/pinctrl/pinctrl-abx500.h +++ b/drivers/pinctrl/pinctrl-abx500.h @@ -1,4 +1,4 @@ -#ifndef PINCTRL_PINCTRL_ABx5O0_H +#ifndef PINCTRL_PINCTRL_ABx500_H #define PINCTRL_PINCTRL_ABx500_H /* Package definitions */ diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index e939c28cbf1..46dddc15928 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -504,6 +504,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, data |= (3 << bit); break; default: + spin_unlock_irqrestore(&bank->slock, flags); dev_err(info->dev, "unsupported pull setting %d\n", pull); return -EINVAL; @@ -1453,8 +1454,8 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) if (ctrl->type == RK3188) { res = platform_get_resource(pdev, IORESOURCE_MEM, 1); info->reg_pull = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(info->reg_base)) - return PTR_ERR(info->reg_base); + if (IS_ERR(info->reg_pull)) + return PTR_ERR(info->reg_pull); } ret = rockchip_gpiolib_register(pdev, info); diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c index 009174d0776..bc5eb453a45 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c @@ -3720,7 +3720,7 @@ static void __iomem *r8a7740_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin) const struct r8a7740_portcr_group *group = &r8a7740_portcr_offsets[i]; - if (i <= group->end_pin) + if (pin <= group->end_pin) return pfc->window->virt + group->offset + pin; } diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7372.c b/drivers/pinctrl/sh-pfc/pfc-sh7372.c index 70b522d3482..cc097b69382 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh7372.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh7372.c @@ -2584,7 +2584,7 @@ static void __iomem *sh7372_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin) const struct sh7372_portcr_group *group = &sh7372_portcr_offsets[i]; - if (i <= group->end_pin) + if (pin <= group->end_pin) return pfc->window->virt + group->offset + pin; } diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 6936e0acedc..f748cc8cbb0 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -197,6 +197,11 @@ static int pnp_bus_freeze(struct device *dev) return __pnp_bus_suspend(dev, PMSG_FREEZE); } +static int pnp_bus_poweroff(struct device *dev) +{ + return __pnp_bus_suspend(dev, PMSG_HIBERNATE); +} + static int pnp_bus_resume(struct device *dev) { struct pnp_dev *pnp_dev = to_pnp_dev(dev); @@ -234,9 +239,14 @@ static int pnp_bus_resume(struct device *dev) } static const struct dev_pm_ops pnp_bus_dev_pm_ops = { + /* Suspend callbacks */ .suspend = pnp_bus_suspend, - .freeze = pnp_bus_freeze, .resume = pnp_bus_resume, + /* Hibernate callbacks */ + .freeze = pnp_bus_freeze, + .thaw = pnp_bus_resume, + .poweroff = pnp_bus_poweroff, + .restore = pnp_bus_resume, }; struct bus_type pnp_bus_type = { diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c index 8d0fe431dbd..84419af16f7 100644 --- a/drivers/powercap/powercap_sys.c +++ b/drivers/powercap/powercap_sys.c @@ -377,9 +377,14 @@ static void create_power_zone_common_attributes( if (power_zone->ops->get_max_energy_range_uj) power_zone->zone_dev_attrs[count++] = &dev_attr_max_energy_range_uj.attr; - if (power_zone->ops->get_energy_uj) + if (power_zone->ops->get_energy_uj) { + if (power_zone->ops->reset_energy_uj) + dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUGO; + else + dev_attr_energy_uj.attr.mode = S_IRUGO; power_zone->zone_dev_attrs[count++] = &dev_attr_energy_uj.attr; + } if (power_zone->ops->get_power_uw) power_zone->zone_dev_attrs[count++] = &dev_attr_power_uw.attr; diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index f64921756ad..f224d59c4b6 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -87,7 +87,6 @@ void dasd_gendisk_free(struct dasd_block *block) { if (block->gdp) { del_gendisk(block->gdp); - block->gdp->queue = NULL; block->gdp->private_data = NULL; put_disk(block->gdp); block->gdp = NULL; diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index f7aa080e9b2..1465e956310 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -35,7 +35,6 @@ struct read_info_sccb { u8 _reserved5[4096 - 112]; /* 112-4095 */ } __packed __aligned(PAGE_SIZE); -static __initdata struct init_sccb early_event_mask_sccb __aligned(PAGE_SIZE); static __initdata struct read_info_sccb early_read_info_sccb; static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE); static unsigned long sclp_hsa_size; @@ -113,7 +112,7 @@ static void __init sclp_facilities_detect(void) bool __init sclp_has_linemode(void) { - struct init_sccb *sccb = &early_event_mask_sccb; + struct init_sccb *sccb = (void *) &sccb_early; if (sccb->header.response_code != 0x20) return 0; @@ -126,7 +125,7 @@ bool __init sclp_has_linemode(void) bool __init sclp_has_vt220(void) { - struct init_sccb *sccb = &early_event_mask_sccb; + struct init_sccb *sccb = (void *) &sccb_early; if (sccb->header.response_code != 0x20) return 0; diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 5e1e12c0cf4..0a7325361d2 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -2025,7 +2025,8 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = TW_MAX_CMDS_PER_LUN, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = twa_host_attrs, - .emulated = 1 + .emulated = 1, + .no_write_same = 1, }; /* This function will probe and initialize a card */ diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index c845bdbeb6c..4de346017e9 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c @@ -1600,7 +1600,8 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = TW_MAX_CMDS_PER_LUN, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = twl_host_attrs, - .emulated = 1 + .emulated = 1, + .no_write_same = 1, }; /* This function will probe and initialize a card */ diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index b9276d10b25..752624e6bc0 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -2279,7 +2279,8 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = TW_MAX_CMDS_PER_LUN, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = tw_host_attrs, - .emulated = 1 + .emulated = 1, + .no_write_same = 1, }; /* This function will probe and initialize a card */ diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index f0d432c139d..4921ed19a02 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1081,6 +1081,7 @@ static struct scsi_host_template aac_driver_template = { #endif .use_clustering = ENABLE_CLUSTERING, .emulated = 1, + .no_write_same = 1, }; static void __aac_shutdown(struct aac_dev * aac) diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 97fd450aff0..4f6a30b8e5f 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -137,6 +137,7 @@ static struct scsi_host_template arcmsr_scsi_host_template = { .cmd_per_lun = ARCMSR_MAX_CMD_PERLUN, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = arcmsr_host_attrs, + .no_write_same = 1, }; static struct pci_device_id arcmsr_device_id_table[] = { {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, diff --git a/drivers/scsi/bfa/bfa_fcs.h b/drivers/scsi/bfa/bfa_fcs.h index 94d5d0102f7..42bcb970445 100644 --- a/drivers/scsi/bfa/bfa_fcs.h +++ b/drivers/scsi/bfa/bfa_fcs.h @@ -296,6 +296,7 @@ wwn_t bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, struct bfa_fcs_lport_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn); +void bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port, char *symname); void bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port, struct bfa_lport_info_s *port_info); void bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s *port, diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 2f61a5af365..f5e4e61a0fd 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -1097,6 +1097,17 @@ bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport, bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE); } +void +bfa_fcs_lport_set_symname(struct bfa_fcs_lport_s *port, + char *symname) +{ + strcpy(port->port_cfg.sym_name.symname, symname); + + if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online)) + bfa_fcs_lport_ns_util_send_rspn_id( + BFA_FCS_GET_NS_FROM_PORT(port), NULL); +} + /* * fcs_lport_api */ @@ -5140,9 +5151,6 @@ bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced) u8 *psymbl = &symbl[0]; int len; - if (!bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online)) - return; - /* Avoid sending RSPN in the following states. */ if (bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_offline) || bfa_sm_cmp_state(ns, bfa_fcs_lport_ns_sm_plogi_sending) || diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index e9a681d3122..40be670a1cb 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -593,11 +593,8 @@ bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport) return; spin_lock_irqsave(&bfad->bfad_lock, flags); - if (strlen(sym_name) > 0) { - strcpy(fcs_vport->lport.port_cfg.sym_name.symname, sym_name); - bfa_fcs_lport_ns_util_send_rspn_id( - BFA_FCS_GET_NS_FROM_PORT((&fcs_vport->lport)), NULL); - } + if (strlen(sym_name) > 0) + bfa_fcs_lport_set_symname(&fcs_vport->lport, sym_name); spin_unlock_irqrestore(&bfad->bfad_lock, flags); } diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index ee4fa40a50b..ce5ef0190ba 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4684,6 +4684,7 @@ static struct scsi_host_template gdth_template = { .cmd_per_lun = GDTH_MAXC_P_L, .unchecked_isa_dma = 1, .use_clustering = ENABLE_CLUSTERING, + .no_write_same = 1, }; #ifdef CONFIG_ISA diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index f334859024c..f2c5005f312 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -395,6 +395,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->use_clustering = sht->use_clustering; shost->ordered_tag = sht->ordered_tag; shost->eh_deadline = shost_eh_deadline * HZ; + shost->no_write_same = sht->no_write_same; if (sht->supported_mode == MODE_UNKNOWN) /* means we didn't set it ... default to INITIATOR */ diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 22f6432eb47..20a5e6ecf94 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -561,6 +561,7 @@ static struct scsi_host_template hpsa_driver_template = { .sdev_attrs = hpsa_sdev_attrs, .shost_attrs = hpsa_shost_attrs, .max_sectors = 8192, + .no_write_same = 1, }; @@ -1288,7 +1289,7 @@ static void complete_scsi_command(struct CommandList *cp) "has check condition: aborted command: " "ASC: 0x%x, ASCQ: 0x%x\n", cp, asc, ascq); - cmd->result = DID_SOFT_ERROR << 16; + cmd->result |= DID_SOFT_ERROR << 16; break; } /* Must be some other type of check condition */ @@ -4925,7 +4926,7 @@ reinit_after_soft_reset: hpsa_hba_inquiry(h); hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */ start_controller_lockup_detector(h); - return 1; + return 0; clean4: hpsa_free_sg_chain_blocks(h); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 36ac1c34ce9..573f4128b6b 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -6305,7 +6305,8 @@ static struct scsi_host_template driver_template = { .use_clustering = ENABLE_CLUSTERING, .shost_attrs = ipr_ioa_attrs, .sdev_attrs = ipr_dev_attrs, - .proc_name = IPR_NAME + .proc_name = IPR_NAME, + .no_write_same = 1, }; /** diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 8d5ea8a1e5a..52a216f21ae 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -374,6 +374,7 @@ static struct scsi_host_template ips_driver_template = { .sg_tablesize = IPS_MAX_SG, .cmd_per_lun = 3, .use_clustering = ENABLE_CLUSTERING, + .no_write_same = 1, }; diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 161c98efade..d2895836f9f 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -211,7 +211,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) qc->tf.nsect = 0; } - ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis); + ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *)&task->ata_task.fis); task->uldd_task = qc; if (ata_is_atapi(qc->tf.protocol)) { memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 90c95a3385d..816db12ef5d 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -4244,6 +4244,7 @@ static struct scsi_host_template megaraid_template = { .eh_device_reset_handler = megaraid_reset, .eh_bus_reset_handler = megaraid_reset, .eh_host_reset_handler = megaraid_reset, + .no_write_same = 1, }; static int diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index d1a4b82836e..e2237a97cb9 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -367,6 +367,7 @@ static struct scsi_host_template megaraid_template_g = { .eh_host_reset_handler = megaraid_reset_handler, .change_queue_depth = megaraid_change_queue_depth, .use_clustering = ENABLE_CLUSTERING, + .no_write_same = 1, .sdev_attrs = megaraid_sdev_attrs, .shost_attrs = megaraid_shost_attrs, }; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 0a743a5d164..c99812bf2a7 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -2148,6 +2148,7 @@ static struct scsi_host_template megasas_template = { .bios_param = megasas_bios_param, .use_clustering = ENABLE_CLUSTERING, .change_queue_depth = megasas_change_queue_depth, + .no_write_same = 1, }; /** diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index f16ece91b94..0a1296a87d6 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -3403,6 +3403,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) unsigned long flags; u8 deviceType = pPayload->sas_identify.dev_type; port->port_state = portstate; + phy->phy_state = PHY_STATE_LINK_UP_SPC; PM8001_MSG_DBG(pm8001_ha, pm8001_printk("HW_EVENT_SAS_PHY_UP port id = %d, phy id = %d\n", port_id, phy_id)); @@ -3483,6 +3484,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("HW_EVENT_SATA_PHY_UP port id = %d," " phy id = %d\n", port_id, phy_id)); port->port_state = portstate; + phy->phy_state = PHY_STATE_LINK_UP_SPC; port->port_attached = 1; pm8001_get_lrate_mode(phy, link_rate); phy->phy_type |= PORT_TYPE_SATA; diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h index 6d91e244654..e4867e690c8 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.h +++ b/drivers/scsi/pm8001/pm8001_hwi.h @@ -131,6 +131,10 @@ #define LINKRATE_30 (0x02 << 8) #define LINKRATE_60 (0x04 << 8) +/* for phy state */ + +#define PHY_STATE_LINK_UP_SPC 0x1 + /* for new SPC controllers MEMBASE III is shared between BIOS and DATA */ #define GSM_SM_BASE 0x4F0000 struct mpi_msg_hdr{ diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 34f5f5ffef0..73a120d81b4 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -175,20 +175,16 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha) static void pm8001_tasklet(unsigned long opaque) { struct pm8001_hba_info *pm8001_ha; - u32 vec; - pm8001_ha = (struct pm8001_hba_info *)opaque; + struct isr_param *irq_vector; + + irq_vector = (struct isr_param *)opaque; + pm8001_ha = irq_vector->drv_inst; if (unlikely(!pm8001_ha)) BUG_ON(1); - vec = pm8001_ha->int_vector; - PM8001_CHIP_DISP->isr(pm8001_ha, vec); + PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id); } #endif -static struct pm8001_hba_info *outq_to_hba(u8 *outq) -{ - return container_of((outq - *outq), struct pm8001_hba_info, outq[0]); -} - /** * pm8001_interrupt_handler_msix - main MSIX interrupt handler. * It obtains the vector number and calls the equivalent bottom @@ -198,18 +194,20 @@ static struct pm8001_hba_info *outq_to_hba(u8 *outq) */ static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque) { - struct pm8001_hba_info *pm8001_ha = outq_to_hba(opaque); - u8 outq = *(u8 *)opaque; + struct isr_param *irq_vector; + struct pm8001_hba_info *pm8001_ha; irqreturn_t ret = IRQ_HANDLED; + irq_vector = (struct isr_param *)opaque; + pm8001_ha = irq_vector->drv_inst; + if (unlikely(!pm8001_ha)) return IRQ_NONE; if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha)) return IRQ_NONE; - pm8001_ha->int_vector = outq; #ifdef PM8001_USE_TASKLET - tasklet_schedule(&pm8001_ha->tasklet); + tasklet_schedule(&pm8001_ha->tasklet[irq_vector->irq_id]); #else - ret = PM8001_CHIP_DISP->isr(pm8001_ha, outq); + ret = PM8001_CHIP_DISP->isr(pm8001_ha, irq_vector->irq_id); #endif return ret; } @@ -230,9 +228,8 @@ static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id) if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha)) return IRQ_NONE; - pm8001_ha->int_vector = 0; #ifdef PM8001_USE_TASKLET - tasklet_schedule(&pm8001_ha->tasklet); + tasklet_schedule(&pm8001_ha->tasklet[0]); #else ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0); #endif @@ -457,7 +454,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, { struct pm8001_hba_info *pm8001_ha; struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); - + int j; pm8001_ha = sha->lldd_ha; if (!pm8001_ha) @@ -480,12 +477,14 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, pm8001_ha->iomb_size = IOMB_SIZE_SPC; #ifdef PM8001_USE_TASKLET - /** - * default tasklet for non msi-x interrupt handler/first msi-x - * interrupt handler - **/ - tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet, - (unsigned long)pm8001_ha); + /* Tasklet for non msi-x interrupt handler */ + if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) + tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet, + (unsigned long)&(pm8001_ha->irq_vector[0])); + else + for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) + tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet, + (unsigned long)&(pm8001_ha->irq_vector[j])); #endif pm8001_ioremap(pm8001_ha); if (!pm8001_alloc(pm8001_ha, ent)) @@ -733,19 +732,20 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) "pci_enable_msix request ret:%d no of intr %d\n", rc, pm8001_ha->number_of_intr)); - for (i = 0; i < number_of_intr; i++) - pm8001_ha->outq[i] = i; for (i = 0; i < number_of_intr; i++) { snprintf(intr_drvname[i], sizeof(intr_drvname[0]), DRV_NAME"%d", i); + pm8001_ha->irq_vector[i].irq_id = i; + pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; + if (request_irq(pm8001_ha->msix_entries[i].vector, pm8001_interrupt_handler_msix, flag, - intr_drvname[i], &pm8001_ha->outq[i])) { + intr_drvname[i], &(pm8001_ha->irq_vector[i]))) { for (j = 0; j < i; j++) free_irq( pm8001_ha->msix_entries[j].vector, - &pm8001_ha->outq[j]); + &(pm8001_ha->irq_vector[i])); pci_disable_msix(pm8001_ha->pdev); break; } @@ -907,7 +907,7 @@ static void pm8001_pci_remove(struct pci_dev *pdev) { struct sas_ha_struct *sha = pci_get_drvdata(pdev); struct pm8001_hba_info *pm8001_ha; - int i; + int i, j; pm8001_ha = sha->lldd_ha; sas_unregister_ha(sha); sas_remove_host(pm8001_ha->shost); @@ -921,13 +921,18 @@ static void pm8001_pci_remove(struct pci_dev *pdev) synchronize_irq(pm8001_ha->msix_entries[i].vector); for (i = 0; i < pm8001_ha->number_of_intr; i++) free_irq(pm8001_ha->msix_entries[i].vector, - &pm8001_ha->outq[i]); + &(pm8001_ha->irq_vector[i])); pci_disable_msix(pdev); #else free_irq(pm8001_ha->irq, sha); #endif #ifdef PM8001_USE_TASKLET - tasklet_kill(&pm8001_ha->tasklet); + /* For non-msix and msix interrupts */ + if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) + tasklet_kill(&pm8001_ha->tasklet[0]); + else + for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) + tasklet_kill(&pm8001_ha->tasklet[j]); #endif pm8001_free(pm8001_ha); kfree(sha->sas_phy); @@ -948,7 +953,7 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct sas_ha_struct *sha = pci_get_drvdata(pdev); struct pm8001_hba_info *pm8001_ha; - int i; + int i, j; u32 device_state; pm8001_ha = sha->lldd_ha; flush_workqueue(pm8001_wq); @@ -964,13 +969,18 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) synchronize_irq(pm8001_ha->msix_entries[i].vector); for (i = 0; i < pm8001_ha->number_of_intr; i++) free_irq(pm8001_ha->msix_entries[i].vector, - &pm8001_ha->outq[i]); + &(pm8001_ha->irq_vector[i])); pci_disable_msix(pdev); #else free_irq(pm8001_ha->irq, sha); #endif #ifdef PM8001_USE_TASKLET - tasklet_kill(&pm8001_ha->tasklet); + /* For non-msix and msix interrupts */ + if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) + tasklet_kill(&pm8001_ha->tasklet[0]); + else + for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) + tasklet_kill(&pm8001_ha->tasklet[j]); #endif device_state = pci_choose_state(pdev, state); pm8001_printk("pdev=0x%p, slot=%s, entering " @@ -993,7 +1003,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev) struct sas_ha_struct *sha = pci_get_drvdata(pdev); struct pm8001_hba_info *pm8001_ha; int rc; - u8 i = 0; + u8 i = 0, j; u32 device_state; pm8001_ha = sha->lldd_ha; device_state = pdev->current_state; @@ -1033,10 +1043,14 @@ static int pm8001_pci_resume(struct pci_dev *pdev) if (rc) goto err_out_disable; #ifdef PM8001_USE_TASKLET - /* default tasklet for non msi-x interrupt handler/first msi-x - * interrupt handler */ - tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet, - (unsigned long)pm8001_ha); + /* Tasklet for non msi-x interrupt handler */ + if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) + tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet, + (unsigned long)&(pm8001_ha->irq_vector[0])); + else + for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) + tasklet_init(&pm8001_ha->tasklet[j], pm8001_tasklet, + (unsigned long)&(pm8001_ha->irq_vector[j])); #endif PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0); if (pm8001_ha->chip_id != chip_8001) { @@ -1169,6 +1183,7 @@ module_exit(pm8001_exit); MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>"); MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>"); MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>"); +MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>"); MODULE_DESCRIPTION( "PMC-Sierra PM8001/8081/8088/8089/8074/8076/8077 " "SAS/SATA controller driver"); diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index f4eb18e5163..f50ac44b950 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1098,15 +1098,17 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun) struct pm8001_tmf_task tmf_task; struct pm8001_device *pm8001_dev = dev->lldd_dev; struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); + DECLARE_COMPLETION_ONSTACK(completion_setstate); if (dev_is_sata(dev)) { struct sas_phy *phy = sas_get_local_phy(dev); rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , dev, 1, 0); rc = sas_phy_reset(phy, 1); sas_put_local_phy(phy); + pm8001_dev->setds_completion = &completion_setstate; rc = PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha, pm8001_dev, 0x01); - msleep(2000); + wait_for_completion(&completion_setstate); } else { tmf_task.tmf = TMF_LU_RESET; rc = pm8001_issue_ssp_tmf(dev, lun, &tmf_task); diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 6037d477a18..6c5fd5ee22d 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -466,6 +466,10 @@ struct pm8001_hba_memspace { u64 membase; u32 memsize; }; +struct isr_param { + struct pm8001_hba_info *drv_inst; + u32 irq_id; +}; struct pm8001_hba_info { char name[PM8001_NAME_LENGTH]; struct list_head list; @@ -519,14 +523,13 @@ struct pm8001_hba_info { int number_of_intr;/*will be used in remove()*/ #endif #ifdef PM8001_USE_TASKLET - struct tasklet_struct tasklet; + struct tasklet_struct tasklet[PM8001_MAX_MSIX_VEC]; #endif u32 logging_level; u32 fw_status; u32 smp_exp_mode; - u32 int_vector; const struct firmware *fw_image; - u8 outq[PM8001_MAX_MSIX_VEC]; + struct isr_param irq_vector[PM8001_MAX_MSIX_VEC]; }; struct pm8001_work { diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 8987b170621..c950dc5c994 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -2894,6 +2894,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) unsigned long flags; u8 deviceType = pPayload->sas_identify.dev_type; port->port_state = portstate; + phy->phy_state = PHY_STATE_LINK_UP_SPCV; PM8001_MSG_DBG(pm8001_ha, pm8001_printk( "portid:%d; phyid:%d; linkrate:%d; " "portstate:%x; devicetype:%x\n", @@ -2978,6 +2979,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) port_id, phy_id, link_rate, portstate)); port->port_state = portstate; + phy->phy_state = PHY_STATE_LINK_UP_SPCV; port->port_attached = 1; pm8001_get_lrate_mode(phy, link_rate); phy->phy_type |= PORT_TYPE_SATA; diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h index c86816bea42..9970a385795 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.h +++ b/drivers/scsi/pm8001/pm80xx_hwi.h @@ -215,6 +215,8 @@ #define SAS_DOPNRJT_RTRY_TMO 128 #define SAS_COPNRJT_RTRY_TMO 128 +/* for phy state */ +#define PHY_STATE_LINK_UP_SPCV 0x2 /* Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second. Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128 diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 892ea616137..be8ce54f99b 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -4325,6 +4325,7 @@ static struct scsi_host_template pmcraid_host_template = { .this_id = -1, .sg_tablesize = PMCRAID_MAX_IOADLS, .max_sectors = PMCRAID_IOA_MAX_SECTORS, + .no_write_same = 1, .cmd_per_lun = PMCRAID_MAX_CMD_PER_LUN, .use_clustering = ENABLE_CLUSTERING, .shost_attrs = pmcraid_host_attrs, diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e6c4bff0433..69725f7c32c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2659,6 +2659,12 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) { struct scsi_device *sdev = sdkp->device; + if (sdev->host->no_write_same) { + sdev->no_write_same = 1; + + return; + } + if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) { /* too large values might cause issues with arcmsr */ int vpd_buf_len = 64; diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 1a28f563279..17d74042724 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1697,6 +1697,7 @@ static struct scsi_host_template scsi_driver = { .use_clustering = DISABLE_CLUSTERING, /* Make sure we dont get a sg segment crosses a page boundary */ .dma_boundary = PAGE_SIZE-1, + .no_write_same = 1, }; enum { diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 1aa4a3fd0f1..56e355b3e7f 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -258,7 +258,8 @@ err: /* This function maps kernel space memory to user space memory. */ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) { - u32 status; + struct omap_dsp_platform_data *pdata = + omap_dspbridge_dev->dev.platform_data; /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); @@ -268,13 +269,9 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_start, vma->vm_end, vma->vm_page_prot, vma->vm_flags); - status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); - if (status != 0) - status = -EAGAIN; - - return status; + return vm_iomap_memory(vma, + pdata->phys_mempool_base, + pdata->phys_mempool_size); } static const struct file_operations bridge_fops = { diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0f74945af62..268b62768f2 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -810,7 +810,8 @@ static void process_echoes(struct tty_struct *tty) struct n_tty_data *ldata = tty->disc_data; size_t echoed; - if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_tail) + if ((!L_ECHO(tty) && !L_ECHONL(tty)) || + ldata->echo_commit == ldata->echo_tail) return; mutex_lock(&ldata->output_lock); @@ -825,7 +826,8 @@ static void flush_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_head) + if ((!L_ECHO(tty) && !L_ECHONL(tty)) || + ldata->echo_commit == ldata->echo_head) return; mutex_lock(&ldata->output_lock); diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 3e7560f004f..e8404319ca6 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1515,6 +1515,8 @@ static int acm_reset_resume(struct usb_interface *intf) static const struct usb_device_id acm_ids[] = { /* quirky and broken devices */ + { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */ + .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */ { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a7c04e24ca4..bd9dc3504b5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4832,8 +4832,9 @@ static void hub_events(void) hub->ports[i - 1]->child; dev_dbg(hub_dev, "warm reset port %d\n", i); - if (!udev || !(portstatus & - USB_PORT_STAT_CONNECTION)) { + if (!udev || + !(portstatus & USB_PORT_STAT_CONNECTION) || + udev->state == USB_STATE_NOTATTACHED) { status = hub_port_reset(hub, i, NULL, HUB_BH_RESET_TIME, true); diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 95f7649c71a..21a352079bc 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -459,6 +459,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, dep = dwc3_wIndex_to_dep(dwc, wIndex); if (!dep) return -EINVAL; + if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) + break; ret = __dwc3_gadget_ep_set_halt(dep, set); if (ret) return -EINVAL; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5452c0fce36..02e44fcaf20 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1200,9 +1200,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) else dep->flags |= DWC3_EP_STALL; } else { - if (dep->flags & DWC3_EP_WEDGE) - return 0; - ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, DWC3_DEPCMD_CLEARSTALL, ¶ms); if (ret) @@ -1210,7 +1207,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) value ? "set" : "clear", dep->name); else - dep->flags &= ~DWC3_EP_STALL; + dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE); } return ret; diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index a91e6422f93..f66d96ad1f5 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -682,6 +682,7 @@ config USB_CONFIGFS_PHONET config USB_CONFIGFS_MASS_STORAGE boolean "Mass storage" depends on USB_CONFIGFS + depends on BLOCK select USB_F_MASS_STORAGE help The Mass Storage Gadget acts as a USB Mass Storage disk drive. diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 3e7ae707f69..2018ba1a217 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -593,6 +593,7 @@ static void reset_config(struct usb_composite_dev *cdev) bitmap_zero(f->endpoints, 32); } cdev->config = NULL; + cdev->delayed_status = 0; } static int set_config(struct usb_composite_dev *cdev, diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 774e8b89cdb..241fc873ffa 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1304,7 +1304,7 @@ static struct ffs_data *ffs_data_new(void) { struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL); if (unlikely(!ffs)) - return 0; + return NULL; ENTER(); diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index a03ba2c8358..b9639390886 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -523,7 +523,7 @@ static int fsg_setup(struct usb_function *f, */ DBG(fsg, "bulk reset request\n"); raise_exception(fsg->common, FSG_STATE_RESET); - return DELAYED_STATUS; + return USB_GADGET_DELAYED_STATUS; case US_BULK_GET_MAX_LUN: if (ctrl->bRequestType != @@ -602,13 +602,14 @@ static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh) return true; } -static int sleep_thread(struct fsg_common *common) +static int sleep_thread(struct fsg_common *common, bool can_freeze) { int rc = 0; /* Wait until a signal arrives or we are woken up */ for (;;) { - try_to_freeze(); + if (can_freeze) + try_to_freeze(); set_current_state(TASK_INTERRUPTIBLE); if (signal_pending(current)) { rc = -EINTR; @@ -682,7 +683,7 @@ static int do_read(struct fsg_common *common) /* Wait for the next buffer to become available */ bh = common->next_buffhd_to_fill; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); + rc = sleep_thread(common, false); if (rc) return rc; } @@ -937,7 +938,7 @@ static int do_write(struct fsg_common *common) } /* Wait for something to happen */ - rc = sleep_thread(common); + rc = sleep_thread(common, false); if (rc) return rc; } @@ -1504,7 +1505,7 @@ static int throw_away_data(struct fsg_common *common) } /* Otherwise wait for something to happen */ - rc = sleep_thread(common); + rc = sleep_thread(common, true); if (rc) return rc; } @@ -1625,7 +1626,7 @@ static int send_status(struct fsg_common *common) /* Wait for the next buffer to become available */ bh = common->next_buffhd_to_fill; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); + rc = sleep_thread(common, true); if (rc) return rc; } @@ -1828,7 +1829,7 @@ static int do_scsi_command(struct fsg_common *common) bh = common->next_buffhd_to_fill; common->next_buffhd_to_drain = bh; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); + rc = sleep_thread(common, true); if (rc) return rc; } @@ -2174,7 +2175,7 @@ static int get_next_command(struct fsg_common *common) /* Wait for the next buffer to become available */ bh = common->next_buffhd_to_fill; while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(common); + rc = sleep_thread(common, true); if (rc) return rc; } @@ -2193,7 +2194,7 @@ static int get_next_command(struct fsg_common *common) /* Wait for the CBW to arrive */ while (bh->state != BUF_STATE_FULL) { - rc = sleep_thread(common); + rc = sleep_thread(common, true); if (rc) return rc; } @@ -2379,7 +2380,7 @@ static void handle_exception(struct fsg_common *common) } if (num_active == 0) break; - if (sleep_thread(common)) + if (sleep_thread(common, true)) return; } @@ -2516,7 +2517,7 @@ static int fsg_main_thread(void *common_) } if (!common->running) { - sleep_thread(common); + sleep_thread(common, true); continue; } @@ -3111,7 +3112,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) fsg->common->can_stall); if (ret) return ret; - fsg_common_set_inquiry_string(fsg->common, 0, 0); + fsg_common_set_inquiry_string(fsg->common, NULL, NULL); ret = fsg_common_run_thread(fsg->common); if (ret) return ret; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 0ac6064aa3b..409a3c45a36 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -54,6 +54,7 @@ */ #ifdef CONFIG_ARCH_PXA #include <mach/pxa25x-udc.h> +#include <mach/hardware.h> #endif #ifdef CONFIG_ARCH_LUBBOCK diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 9875d9c0823..e20bc109fdd 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -1180,6 +1180,7 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, } static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg); +static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg); /** * s3c_hsotg_process_control - process a control request @@ -1221,6 +1222,7 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { switch (ctrl->bRequest) { case USB_REQ_SET_ADDRESS: + s3c_hsotg_disconnect(hsotg); dcfg = readl(hsotg->regs + DCFG); dcfg &= ~DCFG_DevAddr_MASK; dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT; @@ -1245,7 +1247,9 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, /* as a fallback, try delivering it to the driver to deal with */ if (ret == 0 && hsotg->driver) { + spin_unlock(&hsotg->lock); ret = hsotg->driver->setup(&hsotg->gadget, ctrl); + spin_lock(&hsotg->lock); if (ret < 0) dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret); } @@ -1308,10 +1312,12 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep, return; } + spin_lock(&hsotg->lock); if (req->actual == 0) s3c_hsotg_enqueue_setup(hsotg); else s3c_hsotg_process_control(hsotg, req->buf); + spin_unlock(&hsotg->lock); } /** @@ -2533,7 +2539,6 @@ irq_retry: writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS); call_gadget(hsotg, suspend); - s3c_hsotg_disconnect(hsotg); } if (gintsts & GINTSTS_WkUpInt) { diff --git a/drivers/usb/gadget/storage_common.h b/drivers/usb/gadget/storage_common.h index c74c2fdbd56..70c891469f5 100644 --- a/drivers/usb/gadget/storage_common.h +++ b/drivers/usb/gadget/storage_common.h @@ -119,10 +119,6 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun) return curlun->filp != NULL; } -/* Big enough to hold our biggest descriptor */ -#define EP0_BUFSIZE 256 -#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ - /* Default size of buffer length. */ #define FSG_BUFLEN ((u32)16384) diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 6c3d7950d2a..0f8aad78b54 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -370,7 +370,7 @@ err: return -ENOMEM; } -void bot_cleanup_old_alt(struct f_uas *fu) +static void bot_cleanup_old_alt(struct f_uas *fu) { if (!(fu->flags & USBG_ENABLED)) return; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 0dd07ae1555..f49b0b61ecc 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -91,17 +91,17 @@ static struct usb_zero_options gzero_options = { * functional coverage for the "USBCV" test harness from USB-IF. * It's always set if OTG mode is enabled. */ -unsigned autoresume = DEFAULT_AUTORESUME; +static unsigned autoresume = DEFAULT_AUTORESUME; module_param(autoresume, uint, S_IRUGO); MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); /* Maximum Autoresume time */ -unsigned max_autoresume; +static unsigned max_autoresume; module_param(max_autoresume, uint, S_IRUGO); MODULE_PARM_DESC(max_autoresume, "maximum seconds before remote wakeup"); /* Interval between two remote wakeups */ -unsigned autoresume_interval_ms; +static unsigned autoresume_interval_ms; module_param(autoresume_interval_ms, uint, S_IRUGO); MODULE_PARM_DESC(autoresume_interval_ms, "milliseconds to increase successive wakeup delays"); diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index e89ac4d4b87..9b7435f0dcd 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -21,6 +21,7 @@ #include <linux/clk.h> #include <linux/device.h> +#include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 1e2f3f49584..53c2e296467 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2973,8 +2973,58 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, } while (1) { - if (room_on_ring(xhci, ep_ring, num_trbs)) - break; + if (room_on_ring(xhci, ep_ring, num_trbs)) { + union xhci_trb *trb = ep_ring->enqueue; + unsigned int usable = ep_ring->enq_seg->trbs + + TRBS_PER_SEGMENT - 1 - trb; + u32 nop_cmd; + + /* + * Section 4.11.7.1 TD Fragments states that a link + * TRB must only occur at the boundary between + * data bursts (eg 512 bytes for 480M). + * While it is possible to split a large fragment + * we don't know the size yet. + * Simplest solution is to fill the trb before the + * LINK with nop commands. + */ + if (num_trbs == 1 || num_trbs <= usable || usable == 0) + break; + + if (ep_ring->type != TYPE_BULK) + /* + * While isoc transfers might have a buffer that + * crosses a 64k boundary it is unlikely. + * Since we can't add NOPs without generating + * gaps in the traffic just hope it never + * happens at the end of the ring. + * This could be fixed by writing a LINK TRB + * instead of the first NOP - however the + * TRB_TYPE_LINK_LE32() calls would all need + * changing to check the ring length. + */ + break; + + if (num_trbs >= TRBS_PER_SEGMENT) { + xhci_err(xhci, "Too many fragments %d, max %d\n", + num_trbs, TRBS_PER_SEGMENT - 1); + return -ENOMEM; + } + + nop_cmd = cpu_to_le32(TRB_TYPE(TRB_TR_NOOP) | + ep_ring->cycle_state); + ep_ring->num_trbs_free -= usable; + do { + trb->generic.field[0] = 0; + trb->generic.field[1] = 0; + trb->generic.field[2] = 0; + trb->generic.field[3] = nop_cmd; + trb++; + } while (--usable); + ep_ring->enqueue = trb; + if (room_on_ring(xhci, ep_ring, num_trbs)) + break; + } if (ep_ring == xhci->cmd_ring) { xhci_err(xhci, "Do not support expand command ring\n"); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 0a43329569d..4d4499b8044 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1809,7 +1809,6 @@ static void musb_free(struct musb *musb) disable_irq_wake(musb->nIrq); free_irq(musb->nIrq, musb); } - cancel_work_sync(&musb->irq_work); musb_host_free(musb); } @@ -1896,6 +1895,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb_platform_disable(musb); musb_generic_disable(musb); + /* Init IRQ workqueue before request_irq */ + INIT_WORK(&musb->irq_work, musb_irq_work); + /* setup musb parts of the core (especially endpoints) */ status = musb_core_init(plat->config->multipoint ? MUSB_CONTROLLER_MHDRC @@ -1905,9 +1907,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb); - /* Init IRQ workqueue before request_irq */ - INIT_WORK(&musb->irq_work, musb_irq_work); - /* attach to the IRQ */ if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) { dev_err(dev, "request_irq %d failed!\n", nIrq); @@ -1981,6 +1980,7 @@ fail4: musb_host_cleanup(musb); fail3: + cancel_work_sync(&musb->irq_work); if (musb->dma_controller) dma_controller_destroy(musb->dma_controller); fail2_5: @@ -2043,6 +2043,7 @@ static int musb_remove(struct platform_device *pdev) if (musb->dma_controller) dma_controller_destroy(musb->dma_controller); + cancel_work_sync(&musb->irq_work); musb_free(musb); device_init_wakeup(dev, 0); return 0; diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c index ff9d6de2b74..a12bd30401e 100644 --- a/drivers/usb/musb/musb_cppi41.c +++ b/drivers/usb/musb/musb_cppi41.c @@ -38,6 +38,7 @@ struct cppi41_dma_channel { u32 prog_len; u32 transferred; u32 packet_sz; + struct list_head tx_check; }; #define MUSB_DMA_NUM_CHANNELS 15 @@ -47,6 +48,8 @@ struct cppi41_dma_controller { struct cppi41_dma_channel rx_channel[MUSB_DMA_NUM_CHANNELS]; struct cppi41_dma_channel tx_channel[MUSB_DMA_NUM_CHANNELS]; struct musb *musb; + struct hrtimer early_tx; + struct list_head early_tx_list; u32 rx_mode; u32 tx_mode; u32 auto_req; @@ -96,31 +99,27 @@ static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel) cppi41_channel->usb_toggle = toggle; } -static void cppi41_dma_callback(void *private_data) +static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep) { - struct dma_channel *channel = private_data; - struct cppi41_dma_channel *cppi41_channel = channel->private_data; - struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep; - struct musb *musb = hw_ep->musb; - unsigned long flags; - struct dma_tx_state txstate; - u32 transferred; + u8 epnum = hw_ep->epnum; + struct musb *musb = hw_ep->musb; + void __iomem *epio = musb->endpoints[epnum].regs; + u16 csr; - spin_lock_irqsave(&musb->lock, flags); + csr = musb_readw(epio, MUSB_TXCSR); + if (csr & MUSB_TXCSR_TXPKTRDY) + return false; + return true; +} - dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie, - &txstate); - transferred = cppi41_channel->prog_len - txstate.residue; - cppi41_channel->transferred += transferred; +static void cppi41_dma_callback(void *private_data); - dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n", - hw_ep->epnum, cppi41_channel->transferred, - cppi41_channel->total_len); +static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel) +{ + struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep; + struct musb *musb = hw_ep->musb; - update_rx_toggle(cppi41_channel); - - if (cppi41_channel->transferred == cppi41_channel->total_len || - transferred < cppi41_channel->packet_sz) { + if (!cppi41_channel->prog_len) { /* done, complete */ cppi41_channel->channel.actual_len = @@ -150,13 +149,11 @@ static void cppi41_dma_callback(void *private_data) remain_bytes, direction, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (WARN_ON(!dma_desc)) { - spin_unlock_irqrestore(&musb->lock, flags); + if (WARN_ON(!dma_desc)) return; - } dma_desc->callback = cppi41_dma_callback; - dma_desc->callback_param = channel; + dma_desc->callback_param = &cppi41_channel->channel; cppi41_channel->cookie = dma_desc->tx_submit(dma_desc); dma_async_issue_pending(dc); @@ -166,6 +163,117 @@ static void cppi41_dma_callback(void *private_data) musb_writew(epio, MUSB_RXCSR, csr); } } +} + +static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer) +{ + struct cppi41_dma_controller *controller; + struct cppi41_dma_channel *cppi41_channel, *n; + struct musb *musb; + unsigned long flags; + enum hrtimer_restart ret = HRTIMER_NORESTART; + + controller = container_of(timer, struct cppi41_dma_controller, + early_tx); + musb = controller->musb; + + spin_lock_irqsave(&musb->lock, flags); + list_for_each_entry_safe(cppi41_channel, n, &controller->early_tx_list, + tx_check) { + bool empty; + struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep; + + empty = musb_is_tx_fifo_empty(hw_ep); + if (empty) { + list_del_init(&cppi41_channel->tx_check); + cppi41_trans_done(cppi41_channel); + } + } + + if (!list_empty(&controller->early_tx_list)) { + ret = HRTIMER_RESTART; + hrtimer_forward_now(&controller->early_tx, + ktime_set(0, 150 * NSEC_PER_USEC)); + } + + spin_unlock_irqrestore(&musb->lock, flags); + return ret; +} + +static void cppi41_dma_callback(void *private_data) +{ + struct dma_channel *channel = private_data; + struct cppi41_dma_channel *cppi41_channel = channel->private_data; + struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep; + struct musb *musb = hw_ep->musb; + unsigned long flags; + struct dma_tx_state txstate; + u32 transferred; + bool empty; + + spin_lock_irqsave(&musb->lock, flags); + + dmaengine_tx_status(cppi41_channel->dc, cppi41_channel->cookie, + &txstate); + transferred = cppi41_channel->prog_len - txstate.residue; + cppi41_channel->transferred += transferred; + + dev_dbg(musb->controller, "DMA transfer done on hw_ep=%d bytes=%d/%d\n", + hw_ep->epnum, cppi41_channel->transferred, + cppi41_channel->total_len); + + update_rx_toggle(cppi41_channel); + + if (cppi41_channel->transferred == cppi41_channel->total_len || + transferred < cppi41_channel->packet_sz) + cppi41_channel->prog_len = 0; + + empty = musb_is_tx_fifo_empty(hw_ep); + if (empty) { + cppi41_trans_done(cppi41_channel); + } else { + struct cppi41_dma_controller *controller; + /* + * On AM335x it has been observed that the TX interrupt fires + * too early that means the TXFIFO is not yet empty but the DMA + * engine says that it is done with the transfer. We don't + * receive a FIFO empty interrupt so the only thing we can do is + * to poll for the bit. On HS it usually takes 2us, on FS around + * 110us - 150us depending on the transfer size. + * We spin on HS (no longer than than 25us and setup a timer on + * FS to check for the bit and complete the transfer. + */ + controller = cppi41_channel->controller; + + if (musb->g.speed == USB_SPEED_HIGH) { + unsigned wait = 25; + + do { + empty = musb_is_tx_fifo_empty(hw_ep); + if (empty) + break; + wait--; + if (!wait) + break; + udelay(1); + } while (1); + + empty = musb_is_tx_fifo_empty(hw_ep); + if (empty) { + cppi41_trans_done(cppi41_channel); + goto out; + } + } + list_add_tail(&cppi41_channel->tx_check, + &controller->early_tx_list); + if (!hrtimer_active(&controller->early_tx)) { + hrtimer_start_range_ns(&controller->early_tx, + ktime_set(0, 140 * NSEC_PER_USEC), + 40 * NSEC_PER_USEC, + HRTIMER_MODE_REL); + } + } +out: spin_unlock_irqrestore(&musb->lock, flags); } @@ -364,6 +472,8 @@ static int cppi41_is_compatible(struct dma_channel *channel, u16 maxpacket, WARN_ON(1); return 1; } + if (cppi41_channel->hw_ep->ep_in.type != USB_ENDPOINT_XFER_BULK) + return 0; if (cppi41_channel->is_tx) return 1; /* AM335x Advisory 1.0.13. No workaround for device RX mode */ @@ -388,6 +498,7 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel) if (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE) return 0; + list_del_init(&cppi41_channel->tx_check); if (is_tx) { csr = musb_readw(epio, MUSB_TXCSR); csr &= ~MUSB_TXCSR_DMAENAB; @@ -495,6 +606,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller) cppi41_channel->controller = controller; cppi41_channel->port_num = port; cppi41_channel->is_tx = is_tx; + INIT_LIST_HEAD(&cppi41_channel->tx_check); musb_dma = &cppi41_channel->channel; musb_dma->private_data = cppi41_channel; @@ -520,6 +632,7 @@ void dma_controller_destroy(struct dma_controller *c) struct cppi41_dma_controller *controller = container_of(c, struct cppi41_dma_controller, controller); + hrtimer_cancel(&controller->early_tx); cppi41_dma_controller_stop(controller); kfree(controller); } @@ -539,6 +652,9 @@ struct dma_controller *dma_controller_create(struct musb *musb, if (!controller) goto kzalloc_fail; + hrtimer_init(&controller->early_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + controller->early_tx.function = cppi41_recheck_tx_req; + INIT_LIST_HEAD(&controller->early_tx_list); controller->musb = musb; controller->controller.channel_alloc = cppi41_dma_channel_allocate; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d2d3a173b31..32fb057c03f 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1796,7 +1796,11 @@ int musb_gadget_setup(struct musb *musb) /* this "gadget" abstracts/virtualizes the controller */ musb->g.name = musb_driver_name; +#if IS_ENABLED(CONFIG_USB_MUSB_DUAL_ROLE) musb->g.is_otg = 1; +#elif IS_ENABLED(CONFIG_USB_MUSB_GADGET) + musb->g.is_otg = 0; +#endif musb_g_init_endpoints(musb); diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index 6370e50649d..0e3c60cb669 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c @@ -52,8 +52,7 @@ static int am335x_phy_probe(struct platform_device *pdev) return am_phy->id; } - ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, - USB_PHY_TYPE_USB2, 0, false); + ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, NULL); if (ret) return ret; @@ -66,8 +65,6 @@ static int am335x_phy_probe(struct platform_device *pdev) platform_set_drvdata(pdev, am_phy); return 0; - - return ret; } static int am335x_phy_remove(struct platform_device *pdev) diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c index fce3a9e9bb5..aa6d37b3378 100644 --- a/drivers/usb/phy/phy-generic.c +++ b/drivers/usb/phy/phy-generic.c @@ -48,8 +48,9 @@ void usb_nop_xceiv_register(void) if (pd) return; pd = platform_device_register_simple("usb_phy_gen_xceiv", -1, NULL, 0); - if (!pd) { + if (IS_ERR(pd)) { pr_err("Unable to register generic usb transceiver\n"); + pd = NULL; return; } } @@ -150,10 +151,40 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host) } int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, - enum usb_phy_type type, u32 clk_rate, bool needs_vcc) + struct usb_phy_gen_xceiv_platform_data *pdata) { + enum usb_phy_type type = USB_PHY_TYPE_USB2; int err; + u32 clk_rate = 0; + bool needs_vcc = false; + + nop->reset_active_low = true; /* default behaviour */ + + if (dev->of_node) { + struct device_node *node = dev->of_node; + enum of_gpio_flags flags = 0; + + if (of_property_read_u32(node, "clock-frequency", &clk_rate)) + clk_rate = 0; + + needs_vcc = of_property_read_bool(node, "vcc-supply"); + nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios", + 0, &flags); + if (nop->gpio_reset == -EPROBE_DEFER) + return -EPROBE_DEFER; + + nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; + + } else if (pdata) { + type = pdata->type; + clk_rate = pdata->clk_rate; + needs_vcc = pdata->needs_vcc; + nop->gpio_reset = pdata->gpio_reset; + } else { + nop->gpio_reset = -1; + } + nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg), GFP_KERNEL); if (!nop->phy.otg) @@ -218,43 +249,14 @@ EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy); static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct usb_phy_gen_xceiv_platform_data *pdata = - dev_get_platdata(&pdev->dev); struct usb_phy_gen_xceiv *nop; - enum usb_phy_type type = USB_PHY_TYPE_USB2; int err; - u32 clk_rate = 0; - bool needs_vcc = false; nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL); if (!nop) return -ENOMEM; - nop->reset_active_low = true; /* default behaviour */ - - if (dev->of_node) { - struct device_node *node = dev->of_node; - enum of_gpio_flags flags; - - if (of_property_read_u32(node, "clock-frequency", &clk_rate)) - clk_rate = 0; - - needs_vcc = of_property_read_bool(node, "vcc-supply"); - nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios", - 0, &flags); - if (nop->gpio_reset == -EPROBE_DEFER) - return -EPROBE_DEFER; - - nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; - - } else if (pdata) { - type = pdata->type; - clk_rate = pdata->clk_rate; - needs_vcc = pdata->needs_vcc; - nop->gpio_reset = pdata->gpio_reset; - } - - err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc); + err = usb_phy_gen_create_phy(dev, nop, dev_get_platdata(&pdev->dev)); if (err) return err; @@ -271,8 +273,6 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nop); return 0; - - return err; } static int usb_phy_gen_xceiv_remove(struct platform_device *pdev) diff --git a/drivers/usb/phy/phy-generic.h b/drivers/usb/phy/phy-generic.h index d2a220d8173..38a81f307b8 100644 --- a/drivers/usb/phy/phy-generic.h +++ b/drivers/usb/phy/phy-generic.h @@ -1,6 +1,8 @@ #ifndef _PHY_GENERIC_H_ #define _PHY_GENERIC_H_ +#include <linux/usb/usb_phy_gen_xceiv.h> + struct usb_phy_gen_xceiv { struct usb_phy phy; struct device *dev; @@ -14,6 +16,6 @@ int usb_gen_phy_init(struct usb_phy *phy); void usb_gen_phy_shutdown(struct usb_phy *phy); int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, - enum usb_phy_type type, u32 clk_rate, bool needs_vcc); + struct usb_phy_gen_xceiv_platform_data *pdata); #endif diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index fdd33b44dbd..545844b7e79 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -164,7 +164,7 @@ static int mxs_phy_probe(struct platform_device *pdev) mxs_phy->clk = clk; - platform_set_drvdata(pdev, &mxs_phy->phy); + platform_set_drvdata(pdev, mxs_phy); ret = usb_add_phy_dev(&mxs_phy->phy); if (ret) diff --git a/drivers/usb/phy/phy-rcar-gen2-usb.c b/drivers/usb/phy/phy-rcar-gen2-usb.c index a99a6953f11..db3ab34cddb 100644 --- a/drivers/usb/phy/phy-rcar-gen2-usb.c +++ b/drivers/usb/phy/phy-rcar-gen2-usb.c @@ -107,10 +107,10 @@ static void __rcar_gen2_usb_phy_init(struct rcar_gen2_usb_phy_priv *priv) clk_prepare_enable(priv->clk); /* Set USB channels in the USBHS UGCTRL2 register */ - val = ioread32(priv->base); + val = ioread32(priv->base + USBHS_UGCTRL2_REG); val &= ~(USBHS_UGCTRL2_USB0_HS | USBHS_UGCTRL2_USB2_SS); val |= priv->ugctrl2; - iowrite32(val, priv->base); + iowrite32(val, priv->base + USBHS_UGCTRL2_REG); } /* Shutdown USB channels */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 9ced8937a8f..fb0d537435e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2123,6 +2123,20 @@ static void ftdi_set_termios(struct tty_struct *tty, termios->c_cflag |= CRTSCTS; } + /* + * All FTDI UART chips are limited to CS7/8. We won't pretend to + * support CS5/6 and revert the CSIZE setting instead. + */ + if ((C_CSIZE(tty) != CS8) && (C_CSIZE(tty) != CS7)) { + dev_warn(ddev, "requested CSIZE setting not supported\n"); + + termios->c_cflag &= ~CSIZE; + if (old_termios) + termios->c_cflag |= old_termios->c_cflag & CSIZE; + else + termios->c_cflag |= CS8; + } + cflag = termios->c_cflag; if (!old_termios) @@ -2159,19 +2173,16 @@ no_skip: } else { urb_value |= FTDI_SIO_SET_DATA_PARITY_NONE; } - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS7: - urb_value |= 7; - dev_dbg(ddev, "Setting CS7\n"); - break; - case CS8: - urb_value |= 8; - dev_dbg(ddev, "Setting CS8\n"); - break; - default: - dev_err(ddev, "CSIZE was set but not CS7-CS8\n"); - } + switch (cflag & CSIZE) { + case CS7: + urb_value |= 7; + dev_dbg(ddev, "Setting CS7\n"); + break; + default: + case CS8: + urb_value |= 8; + dev_dbg(ddev, "Setting CS8\n"); + break; } /* This is needed by the break command since it uses the same command diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 2b01ec8651c..b63ce023f96 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -173,16 +173,8 @@ retry: clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); return result; } - /* - * Try sending off another urb, unless called from completion handler - * (in which case there will be no free urb or no data). - */ - if (mem_flags != GFP_ATOMIC) - goto retry; - clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); - - return 0; + goto retry; /* try sending off another urb */ } EXPORT_SYMBOL_GPL(usb_serial_generic_write_start); @@ -208,7 +200,7 @@ int usb_serial_generic_write(struct tty_struct *tty, return 0; count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock); - result = usb_serial_generic_write_start(port, GFP_KERNEL); + result = usb_serial_generic_write_start(port, GFP_ATOMIC); if (result) return result; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index e5bdd987b9e..a69da83604c 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1813,25 +1813,25 @@ static void mos7840_change_port_settings(struct tty_struct *tty, iflag = tty->termios.c_iflag; /* Change the number of bits */ - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: - lData = LCR_BITS_5; - break; + switch (cflag & CSIZE) { + case CS5: + lData = LCR_BITS_5; + break; - case CS6: - lData = LCR_BITS_6; - break; + case CS6: + lData = LCR_BITS_6; + break; - case CS7: - lData = LCR_BITS_7; - break; - default: - case CS8: - lData = LCR_BITS_8; - break; - } + case CS7: + lData = LCR_BITS_7; + break; + + default: + case CS8: + lData = LCR_BITS_8; + break; } + /* Change the Parity bit */ if (cflag & PARENB) { if (cflag & PARODD) { diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index c3d94853b4a..496b7e39d5b 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -85,6 +85,7 @@ static void option_instat_callback(struct urb *urb); #define HUAWEI_PRODUCT_K4505 0x1464 #define HUAWEI_PRODUCT_K3765 0x1465 #define HUAWEI_PRODUCT_K4605 0x14C6 +#define HUAWEI_PRODUCT_E173S6 0x1C07 #define QUANTA_VENDOR_ID 0x0408 #define QUANTA_PRODUCT_Q101 0xEA02 @@ -572,6 +573,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S6, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1750, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) }, @@ -634,6 +637,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) }, @@ -688,6 +695,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, @@ -742,6 +753,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7A) }, @@ -796,6 +811,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7A) }, @@ -850,6 +869,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7A) }, @@ -904,6 +927,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7A) }, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 1e6de4cd079..1e3318dfa1c 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -361,23 +361,21 @@ static void pl2303_set_termios(struct tty_struct *tty, 0, 0, buf, 7, 100); dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); - if (C_CSIZE(tty)) { - switch (C_CSIZE(tty)) { - case CS5: - buf[6] = 5; - break; - case CS6: - buf[6] = 6; - break; - case CS7: - buf[6] = 7; - break; - default: - case CS8: - buf[6] = 8; - } - dev_dbg(&port->dev, "data bits = %d\n", buf[6]); + switch (C_CSIZE(tty)) { + case CS5: + buf[6] = 5; + break; + case CS6: + buf[6] = 6; + break; + case CS7: + buf[6] = 7; + break; + default: + case CS8: + buf[6] = 8; } + dev_dbg(&port->dev, "data bits = %d\n", buf[6]); /* For reference buf[0]:buf[3] baud rate value */ pl2303_encode_baudrate(tty, port, &buf[0]); diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 4abac28b599..5b793c35226 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -348,22 +348,20 @@ static void spcp8x5_set_termios(struct tty_struct *tty, } /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */ - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: - buf[1] |= SET_UART_FORMAT_SIZE_5; - break; - case CS6: - buf[1] |= SET_UART_FORMAT_SIZE_6; - break; - case CS7: - buf[1] |= SET_UART_FORMAT_SIZE_7; - break; - default: - case CS8: - buf[1] |= SET_UART_FORMAT_SIZE_8; - break; - } + switch (cflag & CSIZE) { + case CS5: + buf[1] |= SET_UART_FORMAT_SIZE_5; + break; + case CS6: + buf[1] |= SET_UART_FORMAT_SIZE_6; + break; + case CS7: + buf[1] |= SET_UART_FORMAT_SIZE_7; + break; + default: + case CS8: + buf[1] |= SET_UART_FORMAT_SIZE_8; + break; } /* Set Stop bit2 : 0:1bit 1:2bit */ diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index e538b72c4e3..f14e7929ba2 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -97,18 +97,12 @@ static void wusbhc_devconnect_acked_work(struct work_struct *work); static void wusb_dev_free(struct wusb_dev *wusb_dev) { - if (wusb_dev) { - kfree(wusb_dev->set_gtk_req); - usb_free_urb(wusb_dev->set_gtk_urb); - kfree(wusb_dev); - } + kfree(wusb_dev); } static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc) { struct wusb_dev *wusb_dev; - struct urb *urb; - struct usb_ctrlrequest *req; wusb_dev = kzalloc(sizeof(*wusb_dev), GFP_KERNEL); if (wusb_dev == NULL) @@ -118,22 +112,6 @@ static struct wusb_dev *wusb_dev_alloc(struct wusbhc *wusbhc) INIT_WORK(&wusb_dev->devconnect_acked_work, wusbhc_devconnect_acked_work); - urb = usb_alloc_urb(0, GFP_KERNEL); - if (urb == NULL) - goto err; - wusb_dev->set_gtk_urb = urb; - - req = kmalloc(sizeof(*req), GFP_KERNEL); - if (req == NULL) - goto err; - wusb_dev->set_gtk_req = req; - - req->bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; - req->bRequest = USB_REQ_SET_DESCRIPTOR; - req->wValue = cpu_to_le16(USB_DT_KEY << 8 | wusbhc->gtk_index); - req->wIndex = 0; - req->wLength = cpu_to_le16(wusbhc->gtk.descr.bLength); - return wusb_dev; err: wusb_dev_free(wusb_dev); @@ -411,9 +389,6 @@ static void __wusbhc_dev_disconnect(struct wusbhc *wusbhc, /* * Refresh the list of keep alives to emit in the MMC * - * Some devices don't respond to keep alives unless they've been - * authenticated, so skip unauthenticated devices. - * * We only publish the first four devices that have a coming timeout * condition. Then when we are done processing those, we go for the * next ones. We ignore the ones that have timed out already (they'll @@ -448,7 +423,7 @@ static void __wusbhc_keep_alive(struct wusbhc *wusbhc) if (wusb_dev == NULL) continue; - if (wusb_dev->usb_dev == NULL || !wusb_dev->usb_dev->authenticated) + if (wusb_dev->usb_dev == NULL) continue; if (time_after(jiffies, wusb_dev->entry_ts + tt)) { @@ -524,11 +499,19 @@ static struct wusb_dev *wusbhc_find_dev_by_addr(struct wusbhc *wusbhc, u8 addr) * * @wusbhc shall be referenced and unlocked */ -static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) +static void wusbhc_handle_dn_alive(struct wusbhc *wusbhc, u8 srcaddr) { + struct wusb_dev *wusb_dev; + mutex_lock(&wusbhc->mutex); - wusb_dev->entry_ts = jiffies; - __wusbhc_keep_alive(wusbhc); + wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr); + if (wusb_dev == NULL) { + dev_dbg(wusbhc->dev, "ignoring DN_Alive from unconnected device %02x\n", + srcaddr); + } else { + wusb_dev->entry_ts = jiffies; + __wusbhc_keep_alive(wusbhc); + } mutex_unlock(&wusbhc->mutex); } @@ -582,14 +565,22 @@ static void wusbhc_handle_dn_connect(struct wusbhc *wusbhc, * * @wusbhc shall be referenced and unlocked */ -static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) +static void wusbhc_handle_dn_disconnect(struct wusbhc *wusbhc, u8 srcaddr) { struct device *dev = wusbhc->dev; - - dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n", wusb_dev->addr); + struct wusb_dev *wusb_dev; mutex_lock(&wusbhc->mutex); - __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, wusb_dev->port_idx)); + wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr); + if (wusb_dev == NULL) { + dev_dbg(dev, "ignoring DN DISCONNECT from unconnected device %02x\n", + srcaddr); + } else { + dev_info(dev, "DN DISCONNECT: device 0x%02x going down\n", + wusb_dev->addr); + __wusbhc_dev_disconnect(wusbhc, wusb_port_by_idx(wusbhc, + wusb_dev->port_idx)); + } mutex_unlock(&wusbhc->mutex); } @@ -611,30 +602,21 @@ void wusbhc_handle_dn(struct wusbhc *wusbhc, u8 srcaddr, struct wusb_dn_hdr *dn_hdr, size_t size) { struct device *dev = wusbhc->dev; - struct wusb_dev *wusb_dev; if (size < sizeof(struct wusb_dn_hdr)) { dev_err(dev, "DN data shorter than DN header (%d < %d)\n", (int)size, (int)sizeof(struct wusb_dn_hdr)); return; } - - wusb_dev = wusbhc_find_dev_by_addr(wusbhc, srcaddr); - if (wusb_dev == NULL && dn_hdr->bType != WUSB_DN_CONNECT) { - dev_dbg(dev, "ignoring DN %d from unconnected device %02x\n", - dn_hdr->bType, srcaddr); - return; - } - switch (dn_hdr->bType) { case WUSB_DN_CONNECT: wusbhc_handle_dn_connect(wusbhc, dn_hdr, size); break; case WUSB_DN_ALIVE: - wusbhc_handle_dn_alive(wusbhc, wusb_dev); + wusbhc_handle_dn_alive(wusbhc, srcaddr); break; case WUSB_DN_DISCONNECT: - wusbhc_handle_dn_disconnect(wusbhc, wusb_dev); + wusbhc_handle_dn_disconnect(wusbhc, srcaddr); break; case WUSB_DN_MASAVAILCHANGED: case WUSB_DN_RWAKE: diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index dd88441c8f7..4c40d0dbf53 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c @@ -29,19 +29,16 @@ #include <linux/export.h> #include "wusbhc.h" -static void wusbhc_set_gtk_callback(struct urb *urb); -static void wusbhc_gtk_rekey_done_work(struct work_struct *work); +static void wusbhc_gtk_rekey_work(struct work_struct *work); int wusbhc_sec_create(struct wusbhc *wusbhc) { wusbhc->gtk.descr.bLength = sizeof(wusbhc->gtk.descr) + sizeof(wusbhc->gtk.data); wusbhc->gtk.descr.bDescriptorType = USB_DT_KEY; wusbhc->gtk.descr.bReserved = 0; + wusbhc->gtk_index = 0; - wusbhc->gtk_index = wusb_key_index(0, WUSB_KEY_INDEX_TYPE_GTK, - WUSB_KEY_INDEX_ORIGINATOR_HOST); - - INIT_WORK(&wusbhc->gtk_rekey_done_work, wusbhc_gtk_rekey_done_work); + INIT_WORK(&wusbhc->gtk_rekey_work, wusbhc_gtk_rekey_work); return 0; } @@ -113,7 +110,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc) wusbhc_generate_gtk(wusbhc); result = wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, - &wusbhc->gtk.descr.bKeyData, key_size); + &wusbhc->gtk.descr.bKeyData, key_size); if (result < 0) dev_err(wusbhc->dev, "cannot set GTK for the host: %d\n", result); @@ -129,7 +126,7 @@ int wusbhc_sec_start(struct wusbhc *wusbhc) */ void wusbhc_sec_stop(struct wusbhc *wusbhc) { - cancel_work_sync(&wusbhc->gtk_rekey_done_work); + cancel_work_sync(&wusbhc->gtk_rekey_work); } @@ -185,12 +182,14 @@ static int wusb_dev_set_encryption(struct usb_device *usb_dev, int value) static int wusb_dev_set_gtk(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) { struct usb_device *usb_dev = wusb_dev->usb_dev; + u8 key_index = wusb_key_index(wusbhc->gtk_index, + WUSB_KEY_INDEX_TYPE_GTK, WUSB_KEY_INDEX_ORIGINATOR_HOST); return usb_control_msg( usb_dev, usb_sndctrlpipe(usb_dev, 0), USB_REQ_SET_DESCRIPTOR, USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - USB_DT_KEY << 8 | wusbhc->gtk_index, 0, + USB_DT_KEY << 8 | key_index, 0, &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength, 1000); } @@ -520,24 +519,55 @@ error_kzalloc: * Once all connected and authenticated devices have received the new * GTK, switch the host to using it. */ -static void wusbhc_gtk_rekey_done_work(struct work_struct *work) +static void wusbhc_gtk_rekey_work(struct work_struct *work) { - struct wusbhc *wusbhc = container_of(work, struct wusbhc, gtk_rekey_done_work); + struct wusbhc *wusbhc = container_of(work, + struct wusbhc, gtk_rekey_work); size_t key_size = sizeof(wusbhc->gtk.data); + int port_idx; + struct wusb_dev *wusb_dev, *wusb_dev_next; + LIST_HEAD(rekey_list); mutex_lock(&wusbhc->mutex); + /* generate the new key */ + wusbhc_generate_gtk(wusbhc); + /* roll the gtk index. */ + wusbhc->gtk_index = (wusbhc->gtk_index + 1) % (WUSB_KEY_INDEX_MAX + 1); + /* + * Save all connected devices on a list while holding wusbhc->mutex and + * take a reference to each one. Then submit the set key request to + * them after releasing the lock in order to avoid a deadlock. + */ + for (port_idx = 0; port_idx < wusbhc->ports_max; port_idx++) { + wusb_dev = wusbhc->port[port_idx].wusb_dev; + if (!wusb_dev || !wusb_dev->usb_dev + || !wusb_dev->usb_dev->authenticated) + continue; - if (--wusbhc->pending_set_gtks == 0) - wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size); - + wusb_dev_get(wusb_dev); + list_add_tail(&wusb_dev->rekey_node, &rekey_list); + } mutex_unlock(&wusbhc->mutex); -} -static void wusbhc_set_gtk_callback(struct urb *urb) -{ - struct wusbhc *wusbhc = urb->context; + /* Submit the rekey requests without holding wusbhc->mutex. */ + list_for_each_entry_safe(wusb_dev, wusb_dev_next, &rekey_list, + rekey_node) { + list_del_init(&wusb_dev->rekey_node); + dev_dbg(&wusb_dev->usb_dev->dev, "%s: rekey device at port %d\n", + __func__, wusb_dev->port_idx); + + if (wusb_dev_set_gtk(wusbhc, wusb_dev) < 0) { + dev_err(&wusb_dev->usb_dev->dev, "%s: rekey device at port %d failed\n", + __func__, wusb_dev->port_idx); + } + wusb_dev_put(wusb_dev); + } - queue_work(wusbd, &wusbhc->gtk_rekey_done_work); + /* Switch the host controller to use the new GTK. */ + mutex_lock(&wusbhc->mutex); + wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, + &wusbhc->gtk.descr.bKeyData, key_size); + mutex_unlock(&wusbhc->mutex); } /** @@ -553,26 +583,12 @@ static void wusbhc_set_gtk_callback(struct urb *urb) */ void wusbhc_gtk_rekey(struct wusbhc *wusbhc) { - static const size_t key_size = sizeof(wusbhc->gtk.data); - int p; - - wusbhc_generate_gtk(wusbhc); - - for (p = 0; p < wusbhc->ports_max; p++) { - struct wusb_dev *wusb_dev; - - wusb_dev = wusbhc->port[p].wusb_dev; - if (!wusb_dev || !wusb_dev->usb_dev || !wusb_dev->usb_dev->authenticated) - continue; - - usb_fill_control_urb(wusb_dev->set_gtk_urb, wusb_dev->usb_dev, - usb_sndctrlpipe(wusb_dev->usb_dev, 0), - (void *)wusb_dev->set_gtk_req, - &wusbhc->gtk.descr, wusbhc->gtk.descr.bLength, - wusbhc_set_gtk_callback, wusbhc); - if (usb_submit_urb(wusb_dev->set_gtk_urb, GFP_KERNEL) == 0) - wusbhc->pending_set_gtks++; - } - if (wusbhc->pending_set_gtks == 0) - wusbhc->set_gtk(wusbhc, wusbhc->gtk_tkid, &wusbhc->gtk.descr.bKeyData, key_size); + /* + * We need to submit a URB to the downstream WUSB devices in order to + * change the group key. This can't be done while holding the + * wusbhc->mutex since that is also taken in the urb_enqueue routine + * and will cause a deadlock. Instead, queue a work item to do + * it when the lock is not held + */ + queue_work(wusbd, &wusbhc->gtk_rekey_work); } diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index 711b1952b11..6bd3b819a6b 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h @@ -97,6 +97,7 @@ struct wusb_dev { struct kref refcnt; struct wusbhc *wusbhc; struct list_head cack_node; /* Connect-Ack list */ + struct list_head rekey_node; /* GTK rekey list */ u8 port_idx; u8 addr; u8 beacon_type:4; @@ -107,8 +108,6 @@ struct wusb_dev { struct usb_wireless_cap_descriptor *wusb_cap_descr; struct uwb_mas_bm availability; struct work_struct devconnect_acked_work; - struct urb *set_gtk_urb; - struct usb_ctrlrequest *set_gtk_req; struct usb_device *usb_dev; }; @@ -296,8 +295,7 @@ struct wusbhc { } __attribute__((packed)) gtk; u8 gtk_index; u32 gtk_tkid; - struct work_struct gtk_rekey_done_work; - int pending_set_gtks; + struct work_struct gtk_rekey_work; struct usb_encryption_descriptor *ccm1_etd; }; diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 8521051cf94..cd961622f9c 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -131,6 +131,7 @@ static const struct platform_device_id atmel_lcdfb_devtypes[] = { /* terminator */ } }; +MODULE_DEVICE_TABLE(platform, atmel_lcdfb_devtypes); static struct atmel_lcdfb_config * atmel_lcdfb_get_config(struct platform_device *pdev) diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c index 50c857477e4..65041e15fd5 100644 --- a/drivers/video/kyro/fbdev.c +++ b/drivers/video/kyro/fbdev.c @@ -624,15 +624,15 @@ static int kyrofb_ioctl(struct fb_info *info, return -EINVAL; } case KYRO_IOCTL_UVSTRIDE: - if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride))) return -EFAULT; break; case KYRO_IOCTL_STRIDE: - if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride))) return -EFAULT; break; case KYRO_IOCTL_OVERLAY_OFFSET: - if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset))) return -EFAULT; break; } diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 9dbea222340..7d44d669d5b 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -91,6 +91,15 @@ extern boot_infos_t *boot_infos; #define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN 0x6cd4 #define AVIVO_DC_LUTB_WHITE_OFFSET_RED 0x6cd8 +#define FB_RIGHT_POS(p, bpp) (fb_be_math(p) ? 0 : (32 - (bpp))) + +static inline u32 offb_cmap_byteswap(struct fb_info *info, u32 value) +{ + u32 bpp = info->var.bits_per_pixel; + + return cpu_to_be32(value) >> FB_RIGHT_POS(info, bpp); +} + /* * Set a single color register. The values supplied are already * rounded down to the hardware's capabilities (according to the @@ -120,7 +129,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, mask <<= info->var.transp.offset; value |= mask; } - pal[regno] = value; + pal[regno] = offb_cmap_byteswap(info, value); return 0; } @@ -301,7 +310,7 @@ static struct fb_ops offb_ops = { static void __iomem *offb_map_reg(struct device_node *np, int index, unsigned long offset, unsigned long size) { - const u32 *addrp; + const __be32 *addrp; u64 asize, taddr; unsigned int flags; @@ -369,7 +378,11 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp } of_node_put(pciparent); } else if (dp && of_device_is_compatible(dp, "qemu,std-vga")) { - const u32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 }; +#ifdef __BIG_ENDIAN + const __be32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 }; +#else + const __be32 io_of_addr[3] = { 0x00000001, 0x0, 0x0 }; +#endif u64 io_addr = of_translate_address(dp, io_of_addr); if (io_addr != OF_BAD_ADDR) { par->cmap_adr = ioremap(io_addr + 0x3c8, 2); @@ -535,7 +548,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) unsigned int flags, rsize, addr_prop = 0; unsigned long max_size = 0; u64 rstart, address = OF_BAD_ADDR; - const u32 *pp, *addrp, *up; + const __be32 *pp, *addrp, *up; u64 asize; int foreign_endian = 0; @@ -551,25 +564,25 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) if (pp == NULL) pp = of_get_property(dp, "depth", &len); if (pp && len == sizeof(u32)) - depth = *pp; + depth = be32_to_cpup(pp); pp = of_get_property(dp, "linux,bootx-width", &len); if (pp == NULL) pp = of_get_property(dp, "width", &len); if (pp && len == sizeof(u32)) - width = *pp; + width = be32_to_cpup(pp); pp = of_get_property(dp, "linux,bootx-height", &len); if (pp == NULL) pp = of_get_property(dp, "height", &len); if (pp && len == sizeof(u32)) - height = *pp; + height = be32_to_cpup(pp); pp = of_get_property(dp, "linux,bootx-linebytes", &len); if (pp == NULL) pp = of_get_property(dp, "linebytes", &len); if (pp && len == sizeof(u32) && (*pp != 0xffffffffu)) - pitch = *pp; + pitch = be32_to_cpup(pp); else pitch = width * ((depth + 7) / 8); diff --git a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c index e6d56f714ae..d94f35dbd53 100644 --- a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c +++ b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c @@ -526,6 +526,8 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev) struct omap_dss_device *in = ddata->in; int r; + mutex_lock(&ddata->mutex); + dev_dbg(&ddata->spi->dev, "%s\n", __func__); in->ops.sdi->set_timings(in, &ddata->videomode); @@ -614,10 +616,7 @@ static int acx565akm_enable(struct omap_dss_device *dssdev) if (omapdss_device_is_enabled(dssdev)) return 0; - mutex_lock(&ddata->mutex); r = acx565akm_panel_power_on(dssdev); - mutex_unlock(&ddata->mutex); - if (r) return r; diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c index e0f098562a7..a297de5cc85 100644 --- a/drivers/video/sh_mobile_meram.c +++ b/drivers/video/sh_mobile_meram.c @@ -569,6 +569,7 @@ EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_update); * Power management */ +#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_RUNTIME) static int sh_mobile_meram_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -611,6 +612,7 @@ static int sh_mobile_meram_resume(struct device *dev) meram_write_reg(priv->base, common_regs[i], priv->regs[i]); return 0; } +#endif /* CONFIG_PM_SLEEP || CONFIG_PM_RUNTIME */ static UNIVERSAL_DEV_PM_OPS(sh_mobile_meram_dev_pm_ops, sh_mobile_meram_suspend, diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c index b30e5a439d1..a8f2b280f79 100644 --- a/drivers/video/vt8500lcdfb.c +++ b/drivers/video/vt8500lcdfb.c @@ -293,8 +293,7 @@ static int vt8500lcd_probe(struct platform_device *pdev) + sizeof(u32) * 16, GFP_KERNEL); if (!fbi) { dev_err(&pdev->dev, "Failed to initialize framebuffer device\n"); - ret = -ENOMEM; - goto failed; + return -ENOMEM; } strcpy(fbi->fb.fix.id, "VT8500 LCD"); @@ -327,15 +326,13 @@ static int vt8500lcd_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, "no I/O memory resource defined\n"); - ret = -ENODEV; - goto failed_fbi; + return -ENODEV; } res = request_mem_region(res->start, resource_size(res), "vt8500lcd"); if (res == NULL) { dev_err(&pdev->dev, "failed to request I/O memory\n"); - ret = -EBUSY; - goto failed_fbi; + return -EBUSY; } fbi->regbase = ioremap(res->start, resource_size(res)); @@ -346,17 +343,19 @@ static int vt8500lcd_probe(struct platform_device *pdev) } disp_timing = of_get_display_timings(pdev->dev.of_node); - if (!disp_timing) - return -EINVAL; + if (!disp_timing) { + ret = -EINVAL; + goto failed_free_io; + } ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode, OF_USE_NATIVE_MODE); if (ret) - return ret; + goto failed_free_io; ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp); if (ret) - return ret; + goto failed_free_io; /* try allocating the framebuffer */ fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8); @@ -364,7 +363,8 @@ static int vt8500lcd_probe(struct platform_device *pdev) GFP_KERNEL); if (!fb_mem_virt) { pr_err("%s: Failed to allocate framebuffer\n", __func__); - return -ENOMEM; + ret = -ENOMEM; + goto failed_free_io; } fbi->fb.fix.smem_start = fb_mem_phys; @@ -447,9 +447,6 @@ failed_free_io: iounmap(fbi->regbase); failed_free_res: release_mem_region(res->start, resource_size(res)); -failed_fbi: - kfree(fbi); -failed: return ret; } diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c index a6a2cebb258..cafa973c43b 100644 --- a/drivers/watchdog/bcm2835_wdt.c +++ b/drivers/watchdog/bcm2835_wdt.c @@ -19,7 +19,6 @@ #include <linux/watchdog.h> #include <linux/platform_device.h> #include <linux/of_address.h> -#include <linux/miscdevice.h> #define PM_RSTC 0x1c #define PM_WDOG 0x24 diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index 833e8131184..d1d07f2f69d 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c @@ -28,7 +28,6 @@ #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/timer.h> #include <linux/io.h> diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c index 70a240297c6..07f88f54e5c 100644 --- a/drivers/watchdog/ie6xx_wdt.c +++ b/drivers/watchdog/ie6xx_wdt.c @@ -28,7 +28,6 @@ #include <linux/kernel.h> #include <linux/types.h> #include <linux/watchdog.h> -#include <linux/miscdevice.h> #include <linux/seq_file.h> #include <linux/debugfs.h> #include <linux/uaccess.h> diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index 2de486a7eea..3aa50cfa335 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -17,7 +17,6 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/init.h> #include <linux/platform_device.h> diff --git a/drivers/watchdog/kempld_wdt.c b/drivers/watchdog/kempld_wdt.c index a1a3638c579..20dc7384473 100644 --- a/drivers/watchdog/kempld_wdt.c +++ b/drivers/watchdog/kempld_wdt.c @@ -26,7 +26,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/miscdevice.h> #include <linux/uaccess.h> #include <linux/watchdog.h> #include <linux/platform_device.h> diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c index 6d4f3998e1f..bdb3f4a5b27 100644 --- a/drivers/watchdog/max63xx_wdt.c +++ b/drivers/watchdog/max63xx_wdt.c @@ -19,7 +19,6 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/init.h> #include <linux/bitops.h> diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 44edca66d56..f7722a42467 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -16,7 +16,6 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/miscdevice.h> #include <linux/platform_device.h> #include <linux/watchdog.h> #include <linux/init.h> diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 1bdcc313e1d..5bec20f5dc2 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -23,7 +23,6 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/kernel.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/init.h> #include <linux/platform_device.h> diff --git a/drivers/watchdog/rt2880_wdt.c b/drivers/watchdog/rt2880_wdt.c index 53d37fea183..d92c2d5859c 100644 --- a/drivers/watchdog/rt2880_wdt.c +++ b/drivers/watchdog/rt2880_wdt.c @@ -16,7 +16,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/watchdog.h> -#include <linux/miscdevice.h> #include <linux/moduleparam.h> #include <linux/platform_device.h> diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 3b9fff9dcf6..131193a7acd 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c @@ -409,8 +409,9 @@ static int __init sc1200wdt_init(void) #if defined CONFIG_PNP /* now that the user has specified an IO port and we haven't detected * any devices, disable pnp support */ + if (isapnp) + pnp_unregister_driver(&scl200wdt_pnp_driver); isapnp = 0; - pnp_unregister_driver(&scl200wdt_pnp_driver); #endif if (!request_region(io, io_len, SC1200_MODULE_NAME)) { diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index f9b8e06f355..af3528f84d6 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c @@ -26,7 +26,6 @@ #include <linux/init.h> #include <linux/types.h> #include <linux/spinlock.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/pm_runtime.h> #include <linux/fs.h> diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index ef2638fee4a..c04a1aa158e 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c @@ -42,7 +42,6 @@ #include <linux/moduleparam.h> #include <linux/types.h> #include <linux/timer.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/notifier.h> #include <linux/reboot.h> diff --git a/drivers/watchdog/stmp3xxx_rtc_wdt.c b/drivers/watchdog/stmp3xxx_rtc_wdt.c index d667f6b51d3..bb64ae3f47d 100644 --- a/drivers/watchdog/stmp3xxx_rtc_wdt.c +++ b/drivers/watchdog/stmp3xxx_rtc_wdt.c @@ -12,7 +12,6 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/platform_device.h> #include <linux/stmp3xxx_rtc_wdt.h> diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c index 0fd0e8ae62a..6a447e321dd 100644 --- a/drivers/watchdog/txx9wdt.c +++ b/drivers/watchdog/txx9wdt.c @@ -13,7 +13,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/types.h> -#include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/init.h> #include <linux/platform_device.h> diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c index e029b5768f2..5aed9d7ad47 100644 --- a/drivers/watchdog/ux500_wdt.c +++ b/drivers/watchdog/ux500_wdt.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/moduleparam.h> -#include <linux/miscdevice.h> #include <linux/err.h> #include <linux/uaccess.h> #include <linux/watchdog.h> |