diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-09-24 00:24:10 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-09-24 00:24:10 +0400 |
commit | dc4fea795bf7e3f80dbfa3a40b8ab89427e9aed5 (patch) | |
tree | 1926c96f145965c393a2c8ab523c327dd1a241cf /drivers | |
parent | c8f2efc8f636506e0f0c2ba4035382076875f0c1 (diff) | |
parent | 9d23108df359e572a0dca0b631bfee9f5e0fa9ea (diff) | |
download | linux-dc4fea795bf7e3f80dbfa3a40b8ab89427e9aed5.tar.xz |
Merge branch 'master' into usb-next
We have USB fixes now in Linus's tree that we need to properly sort out
with reverts and the like in the usb-next branch, so merge them together
and do it by hand.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
262 files changed, 2244 insertions, 1218 deletions
diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 449f6298dc89..8557adcd34ee 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -2865,15 +2865,4 @@ static struct pci_driver he_driver = { .id_table = he_pci_tbl, }; -static int __init he_init(void) -{ - return pci_register_driver(&he_driver); -} - -static void __exit he_cleanup(void) -{ - pci_unregister_driver(&he_driver); -} - -module_init(he_init); -module_exit(he_cleanup); +module_pci_driver(he_driver); diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 409502a78e7e..5aca5f4c5458 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -778,7 +778,7 @@ static int ns_init_card(int i, struct pci_dev *pcidev) return error; } - if (mac[i] == NULL || mac_pton(mac[i], card->atmdev->esi)) { + if (mac[i] == NULL || !mac_pton(mac[i], card->atmdev->esi)) { nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET, card->atmdev->esi, 6); if (memcmp(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00", 6) == diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index cd6b20fce680..37768401d113 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -269,6 +269,8 @@ static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 core return NULL; } +#define IS_ERR_VALUE_U32(x) ((x) >= (u32)-MAX_ERRNO) + static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, struct bcma_device_id *match, int core_num, struct bcma_device *core) @@ -351,11 +353,11 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, * the main register space for the core */ tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0); - if (tmp == 0 || IS_ERR_VALUE(tmp)) { + if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) { /* Try again to see if it is a bridge */ tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_BRIDGE, 0); - if (tmp == 0 || IS_ERR_VALUE(tmp)) { + if (tmp == 0 || IS_ERR_VALUE_U32(tmp)) { return -EILSEQ; } else { bcma_info(bus, "Bridge found\n"); @@ -369,7 +371,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, for (j = 0; ; j++) { tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, i); - if (IS_ERR_VALUE(tmp)) { + if (IS_ERR_VALUE_U32(tmp)) { /* no more entries for port _i_ */ /* pr_debug("erom: slave port %d " * "has %d descriptors\n", i, j); */ @@ -386,7 +388,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, for (j = 0; ; j++) { tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_MWRAP, i); - if (IS_ERR_VALUE(tmp)) { + if (IS_ERR_VALUE_U32(tmp)) { /* no more entries for port _i_ */ /* pr_debug("erom: master wrapper %d " * "has %d descriptors\n", i, j); */ @@ -404,7 +406,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, for (j = 0; ; j++) { tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SWRAP, i + hack); - if (IS_ERR_VALUE(tmp)) { + if (IS_ERR_VALUE_U32(tmp)) { /* no more entries for port _i_ */ /* pr_debug("erom: master wrapper %d " * has %d descriptors\n", i, j); */ diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index b22a7d0fe5b7..cb1db2979d3d 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -931,12 +931,14 @@ static const char *rbd_dev_v1_snap_name(struct rbd_device *rbd_dev, u64 snap_id) { u32 which; + const char *snap_name; which = rbd_dev_snap_index(rbd_dev, snap_id); if (which == BAD_SNAP_INDEX) - return NULL; + return ERR_PTR(-ENOENT); - return _rbd_dev_v1_snap_name(rbd_dev, which); + snap_name = _rbd_dev_v1_snap_name(rbd_dev, which); + return snap_name ? snap_name : ERR_PTR(-ENOMEM); } static const char *rbd_snap_name(struct rbd_device *rbd_dev, u64 snap_id) @@ -2812,7 +2814,7 @@ out_err: obj_request_done_set(obj_request); } -static int rbd_obj_notify_ack(struct rbd_device *rbd_dev, u64 notify_id) +static int rbd_obj_notify_ack_sync(struct rbd_device *rbd_dev, u64 notify_id) { struct rbd_obj_request *obj_request; struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; @@ -2827,16 +2829,17 @@ static int rbd_obj_notify_ack(struct rbd_device *rbd_dev, u64 notify_id) obj_request->osd_req = rbd_osd_req_create(rbd_dev, false, obj_request); if (!obj_request->osd_req) goto out; - obj_request->callback = rbd_obj_request_put; osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_NOTIFY_ACK, notify_id, 0, 0); rbd_osd_req_format_read(obj_request); ret = rbd_obj_request_submit(osdc, obj_request); -out: if (ret) - rbd_obj_request_put(obj_request); + goto out; + ret = rbd_obj_request_wait(obj_request); +out: + rbd_obj_request_put(obj_request); return ret; } @@ -2856,7 +2859,7 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) if (ret) rbd_warn(rbd_dev, "header refresh error (%d)\n", ret); - rbd_obj_notify_ack(rbd_dev, notify_id); + rbd_obj_notify_ack_sync(rbd_dev, notify_id); } /* @@ -3328,6 +3331,31 @@ static void rbd_exists_validate(struct rbd_device *rbd_dev) clear_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags); } +static void rbd_dev_update_size(struct rbd_device *rbd_dev) +{ + sector_t size; + bool removing; + + /* + * Don't hold the lock while doing disk operations, + * or lock ordering will conflict with the bdev mutex via: + * rbd_add() -> blkdev_get() -> rbd_open() + */ + spin_lock_irq(&rbd_dev->lock); + removing = test_bit(RBD_DEV_FLAG_REMOVING, &rbd_dev->flags); + spin_unlock_irq(&rbd_dev->lock); + /* + * If the device is being removed, rbd_dev->disk has + * been destroyed, so don't try to update its size + */ + if (!removing) { + size = (sector_t)rbd_dev->mapping.size / SECTOR_SIZE; + dout("setting size to %llu sectors", (unsigned long long)size); + set_capacity(rbd_dev->disk, size); + revalidate_disk(rbd_dev->disk); + } +} + static int rbd_dev_refresh(struct rbd_device *rbd_dev) { u64 mapping_size; @@ -3347,12 +3375,7 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev) up_write(&rbd_dev->header_rwsem); if (mapping_size != rbd_dev->mapping.size) { - sector_t size; - - size = (sector_t)rbd_dev->mapping.size / SECTOR_SIZE; - dout("setting size to %llu sectors", (unsigned long long)size); - set_capacity(rbd_dev->disk, size); - revalidate_disk(rbd_dev->disk); + rbd_dev_update_size(rbd_dev); } return ret; @@ -4061,8 +4084,13 @@ static u64 rbd_v2_snap_id_by_name(struct rbd_device *rbd_dev, const char *name) snap_id = snapc->snaps[which]; snap_name = rbd_dev_v2_snap_name(rbd_dev, snap_id); - if (IS_ERR(snap_name)) - break; + if (IS_ERR(snap_name)) { + /* ignore no-longer existing snapshots */ + if (PTR_ERR(snap_name) == -ENOENT) + continue; + else + break; + } found = !strcmp(name, snap_name); kfree(snap_name); } @@ -4141,8 +4169,8 @@ static int rbd_dev_spec_update(struct rbd_device *rbd_dev) /* Look up the snapshot name, and make a copy */ snap_name = rbd_snap_name(rbd_dev, spec->snap_id); - if (!snap_name) { - ret = -ENOMEM; + if (IS_ERR(snap_name)) { + ret = PTR_ERR(snap_name); goto out_err; } @@ -5163,10 +5191,23 @@ static ssize_t rbd_remove(struct bus_type *bus, if (ret < 0 || already) return ret; - rbd_bus_del_dev(rbd_dev); ret = rbd_dev_header_watch_sync(rbd_dev, false); if (ret) rbd_warn(rbd_dev, "failed to cancel watch event (%d)\n", ret); + + /* + * flush remaining watch callbacks - these must be complete + * before the osd_client is shutdown + */ + dout("%s: flushing notifies", __func__); + ceph_osdc_flush_notifies(&rbd_dev->rbd_client->client->osdc); + /* + * Don't free anything from rbd_dev->disk until after all + * notifies are completely processed. Otherwise + * rbd_bus_del_dev() will race with rbd_watch_cb(), resulting + * in a potential use after free of rbd_dev->disk or rbd_dev. + */ + rbd_bus_del_dev(rbd_dev); rbd_dev_image_release(rbd_dev); module_put(THIS_MODULE); diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index cbfffa91ebdd..78c49d8e0f4a 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -12,6 +12,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/clk.h> +#include <linux/cpu.h> #include <linux/cpufreq.h> #include <linux/err.h> #include <linux/module.h> @@ -177,7 +178,11 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) struct device_node *np; int ret; - cpu_dev = &pdev->dev; + cpu_dev = get_cpu_device(0); + if (!cpu_dev) { + pr_err("failed to get cpu0 device\n"); + return -ENODEV; + } np = of_node_get(cpu_dev->of_node); if (!np) { diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 43c24aa756f6..89b3c52cd5c3 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -952,9 +952,20 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) if (cpu == policy->cpu) return; + /* + * Take direct locks as lock_policy_rwsem_write wouldn't work here. + * Also lock for last cpu is enough here as contention will happen only + * after policy->cpu is changed and after it is changed, other threads + * will try to acquire lock for new cpu. And policy is already updated + * by then. + */ + down_write(&per_cpu(cpu_policy_rwsem, policy->cpu)); + policy->last_cpu = policy->cpu; policy->cpu = cpu; + up_write(&per_cpu(cpu_policy_rwsem, policy->last_cpu)); + #ifdef CONFIG_CPU_FREQ_TABLE cpufreq_frequency_table_update_policy_cpu(policy); #endif @@ -1125,7 +1136,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, int ret; /* first sibling now owns the new sysfs dir */ - cpu_dev = get_cpu_device(cpumask_first(policy->cpus)); + cpu_dev = get_cpu_device(cpumask_any_but(policy->cpus, old_cpu)); /* Don't touch sysfs files during light-weight tear-down */ if (frozen) @@ -1189,12 +1200,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, policy->governor->name, CPUFREQ_NAME_LEN); #endif - WARN_ON(lock_policy_rwsem_write(cpu)); + lock_policy_rwsem_read(cpu); cpus = cpumask_weight(policy->cpus); - - if (cpus > 1) - cpumask_clear_cpu(cpu, policy->cpus); - unlock_policy_rwsem_write(cpu); + unlock_policy_rwsem_read(cpu); if (cpu != policy->cpu) { if (!frozen) @@ -1203,9 +1211,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev, new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen); if (new_cpu >= 0) { - WARN_ON(lock_policy_rwsem_write(cpu)); update_policy_cpu(policy, new_cpu); - unlock_policy_rwsem_write(cpu); if (!frozen) { pr_debug("%s: policy Kobject moved to cpu: %d " @@ -1237,9 +1243,12 @@ static int __cpufreq_remove_dev_finish(struct device *dev, return -EINVAL; } - lock_policy_rwsem_read(cpu); + WARN_ON(lock_policy_rwsem_write(cpu)); cpus = cpumask_weight(policy->cpus); - unlock_policy_rwsem_read(cpu); + + if (cpus > 1) + cpumask_clear_cpu(cpu, policy->cpus); + unlock_policy_rwsem_write(cpu); /* If cpu is last user of policy, free policy */ if (cpus == 1) { @@ -2095,7 +2104,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) write_lock_irqsave(&cpufreq_driver_lock, flags); if (cpufreq_driver) { write_unlock_irqrestore(&cpufreq_driver_lock, flags); - return -EBUSY; + return -EEXIST; } cpufreq_driver = driver_data; write_unlock_irqrestore(&cpufreq_driver_lock, flags); diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 3e396543aea4..c3fd2a101ca0 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -7,6 +7,7 @@ */ #include <linux/clk.h> +#include <linux/cpu.h> #include <linux/cpufreq.h> #include <linux/delay.h> #include <linux/err.h> @@ -202,7 +203,11 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) unsigned long min_volt, max_volt; int num, ret; - cpu_dev = &pdev->dev; + cpu_dev = get_cpu_device(0); + if (!cpu_dev) { + pr_err("failed to get cpu0 device\n"); + return -ENODEV; + } np = of_node_get(cpu_dev->of_node); if (!np) { diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 796dbb212a41..8492b68e873c 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -177,7 +177,7 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast, static inline void ast_open_key(struct ast_private *ast) { - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xA1, 0xFF, 0x04); + ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x80, 0xA8); } #define AST_VIDMEM_SIZE_8M 0x00800000 diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c index b4fb86d89850..224ff965bcf7 100644 --- a/drivers/gpu/drm/drm_context.c +++ b/drivers/gpu/drm/drm_context.c @@ -42,6 +42,10 @@ #include <drm/drmP.h> +/******************************************************************/ +/** \name Context bitmap support */ +/*@{*/ + /** * Free a handle from the context bitmap. * @@ -52,48 +56,13 @@ * in drm_device::ctx_idr, while holding the drm_device::struct_mutex * lock. */ -static void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle) +void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle) { - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return; - mutex_lock(&dev->struct_mutex); idr_remove(&dev->ctx_idr, ctx_handle); mutex_unlock(&dev->struct_mutex); } -/******************************************************************/ -/** \name Context bitmap support */ -/*@{*/ - -void drm_legacy_ctxbitmap_release(struct drm_device *dev, - struct drm_file *file_priv) -{ - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return; - - mutex_lock(&dev->ctxlist_mutex); - if (!list_empty(&dev->ctxlist)) { - struct drm_ctx_list *pos, *n; - - list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { - if (pos->tag == file_priv && - pos->handle != DRM_KERNEL_CONTEXT) { - if (dev->driver->context_dtor) - dev->driver->context_dtor(dev, - pos->handle); - - drm_ctxbitmap_free(dev, pos->handle); - - list_del(&pos->head); - kfree(pos); - --dev->ctx_count; - } - } - } - mutex_unlock(&dev->ctxlist_mutex); -} - /** * Context bitmap allocation. * @@ -121,12 +90,10 @@ static int drm_ctxbitmap_next(struct drm_device * dev) * * Initialise the drm_device::ctx_idr */ -void drm_legacy_ctxbitmap_init(struct drm_device * dev) +int drm_ctxbitmap_init(struct drm_device * dev) { - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return; - idr_init(&dev->ctx_idr); + return 0; } /** @@ -137,7 +104,7 @@ void drm_legacy_ctxbitmap_init(struct drm_device * dev) * Free all idr members using drm_ctx_sarea_free helper function * while holding the drm_device::struct_mutex lock. */ -void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev) +void drm_ctxbitmap_cleanup(struct drm_device * dev) { mutex_lock(&dev->struct_mutex); idr_destroy(&dev->ctx_idr); @@ -169,9 +136,6 @@ int drm_getsareactx(struct drm_device *dev, void *data, struct drm_local_map *map; struct drm_map_list *_entry; - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; - mutex_lock(&dev->struct_mutex); map = idr_find(&dev->ctx_idr, request->ctx_id); @@ -216,9 +180,6 @@ int drm_setsareactx(struct drm_device *dev, void *data, struct drm_local_map *map = NULL; struct drm_map_list *r_list = NULL; - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; - mutex_lock(&dev->struct_mutex); list_for_each_entry(r_list, &dev->maplist, head) { if (r_list->map @@ -319,9 +280,6 @@ int drm_resctx(struct drm_device *dev, void *data, struct drm_ctx ctx; int i; - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; - if (res->count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { @@ -352,9 +310,6 @@ int drm_addctx(struct drm_device *dev, void *data, struct drm_ctx_list *ctx_entry; struct drm_ctx *ctx = data; - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; - ctx->handle = drm_ctxbitmap_next(dev); if (ctx->handle == DRM_KERNEL_CONTEXT) { /* Skip kernel's context and get a new one. */ @@ -398,9 +353,6 @@ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_ctx *ctx = data; - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; - /* This is 0, because we don't handle any context flags */ ctx->flags = 0; @@ -423,9 +375,6 @@ int drm_switchctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; - DRM_DEBUG("%d\n", ctx->handle); return drm_context_switch(dev, dev->last_context, ctx->handle); } @@ -446,9 +395,6 @@ int drm_newctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; - DRM_DEBUG("%d\n", ctx->handle); drm_context_switch_complete(dev, file_priv, ctx->handle); @@ -471,9 +417,6 @@ int drm_rmctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; - if (drm_core_check_feature(dev, DRIVER_MODESET)) - return -EINVAL; - DRM_DEBUG("%d\n", ctx->handle); if (ctx->handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_dtor) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 3d13ca6e257f..f6f6cc7fc133 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -416,6 +416,14 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) return; /* + * fbdev->blank can be called from irq context in case of a panic. + * Since we already have our own special panic handler which will + * restore the fbdev console mode completely, just bail out early. + */ + if (oops_in_progress) + return; + + /* * For each CRTC in this fb, turn the connectors on/off. */ drm_modeset_lock_all(dev); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 4be8e09a32ef..3f84277d7036 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -439,7 +439,26 @@ int drm_release(struct inode *inode, struct file *filp) if (dev->driver->driver_features & DRIVER_GEM) drm_gem_release(dev, file_priv); - drm_legacy_ctxbitmap_release(dev, file_priv); + mutex_lock(&dev->ctxlist_mutex); + if (!list_empty(&dev->ctxlist)) { + struct drm_ctx_list *pos, *n; + + list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { + if (pos->tag == file_priv && + pos->handle != DRM_KERNEL_CONTEXT) { + if (dev->driver->context_dtor) + dev->driver->context_dtor(dev, + pos->handle); + + drm_ctxbitmap_free(dev, pos->handle); + + list_del(&pos->head); + kfree(pos); + --dev->ctx_count; + } + } + } + mutex_unlock(&dev->ctxlist_mutex); mutex_lock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index e7eb0276f7f1..39d864576be4 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -292,7 +292,13 @@ int drm_fill_in_dev(struct drm_device *dev, goto error_out_unreg; } - drm_legacy_ctxbitmap_init(dev); + + + retcode = drm_ctxbitmap_init(dev); + if (retcode) { + DRM_ERROR("Cannot allocate memory for context bitmap.\n"); + goto error_out_unreg; + } if (driver->driver_features & DRIVER_GEM) { retcode = drm_gem_init(dev); @@ -446,7 +452,7 @@ void drm_put_dev(struct drm_device *dev) drm_rmmap(dev, r_list->map); drm_ht_remove(&dev->map_hash); - drm_legacy_ctxbitmap_cleanup(dev); + drm_ctxbitmap_cleanup(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_put_minor(&dev->control); diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 4752f223e5b2..45b6ef595965 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -56,7 +56,7 @@ config DRM_EXYNOS_IPP config DRM_EXYNOS_FIMC bool "Exynos DRM FIMC" - depends on DRM_EXYNOS_IPP && MFD_SYSCON && OF + depends on DRM_EXYNOS_IPP && MFD_SYSCON help Choose this option if you want to use Exynos FIMC for DRM. diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c index 3445a0f3a6b2..9c8088462c26 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c @@ -63,7 +63,8 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, return -ENOMEM; } - buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size, + buf->kvaddr = (void __iomem *)dma_alloc_attrs(dev->dev, + buf->size, &buf->dma_addr, GFP_KERNEL, &buf->dma_attrs); if (!buf->kvaddr) { @@ -90,9 +91,9 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, } buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages); - if (!buf->sgt) { + if (IS_ERR(buf->sgt)) { DRM_ERROR("failed to get sg table.\n"); - ret = -ENOMEM; + ret = PTR_ERR(buf->sgt); goto err_free_attrs; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 78e868bcf1ec..e7c2f2d07f19 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -99,12 +99,13 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, if (is_drm_iommu_supported(dev)) { unsigned int nr_pages = buffer->size >> PAGE_SHIFT; - buffer->kvaddr = vmap(buffer->pages, nr_pages, VM_MAP, + buffer->kvaddr = (void __iomem *) vmap(buffer->pages, + nr_pages, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); } else { phys_addr_t dma_addr = buffer->dma_addr; if (dma_addr) - buffer->kvaddr = phys_to_virt(dma_addr); + buffer->kvaddr = (void __iomem *)phys_to_virt(dma_addr); else buffer->kvaddr = (void __iomem *)NULL; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8507c6d1e642..df9253d890ee 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1392,14 +1392,11 @@ out: if (i915_terminally_wedged(&dev_priv->gpu_error)) return VM_FAULT_SIGBUS; case -EAGAIN: - /* Give the error handler a chance to run and move the - * objects off the GPU active list. Next time we service the - * fault, we should be able to transition the page into the - * GTT without touching the GPU (and so avoid further - * EIO/EGAIN). If the GPU is wedged, then there is no issue - * with coherency, just lost writes. + /* + * EAGAIN means the gpu is hung and we'll wait for the error + * handler to reset everything when re-faulting in + * i915_mutex_lock_interruptible. */ - set_need_resched(); case 0: case -ERESTARTSYS: case -EINTR: diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 83cce0cdb769..4b91228fd9bd 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1469,6 +1469,34 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) return ret; } +static void i915_error_wake_up(struct drm_i915_private *dev_priv, + bool reset_completed) +{ + struct intel_ring_buffer *ring; + int i; + + /* + * Notify all waiters for GPU completion events that reset state has + * been changed, and that they need to restart their wait after + * checking for potential errors (and bail out to drop locks if there is + * a gpu reset pending so that i915_error_work_func can acquire them). + */ + + /* Wake up __wait_seqno, potentially holding dev->struct_mutex. */ + for_each_ring(ring, dev_priv, i) + wake_up_all(&ring->irq_queue); + + /* Wake up intel_crtc_wait_for_pending_flips, holding crtc->mutex. */ + wake_up_all(&dev_priv->pending_flip_queue); + + /* + * Signal tasks blocked in i915_gem_wait_for_error that the pending + * reset state is cleared. + */ + if (reset_completed) + wake_up_all(&dev_priv->gpu_error.reset_queue); +} + /** * i915_error_work_func - do process context error handling work * @work: work struct @@ -1483,11 +1511,10 @@ static void i915_error_work_func(struct work_struct *work) drm_i915_private_t *dev_priv = container_of(error, drm_i915_private_t, gpu_error); struct drm_device *dev = dev_priv->dev; - struct intel_ring_buffer *ring; char *error_event[] = { I915_ERROR_UEVENT "=1", NULL }; char *reset_event[] = { I915_RESET_UEVENT "=1", NULL }; char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL }; - int i, ret; + int ret; kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, error_event); @@ -1506,8 +1533,16 @@ static void i915_error_work_func(struct work_struct *work) kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, reset_event); + /* + * All state reset _must_ be completed before we update the + * reset counter, for otherwise waiters might miss the reset + * pending state and not properly drop locks, resulting in + * deadlocks with the reset work. + */ ret = i915_reset(dev); + intel_display_handle_reset(dev); + if (ret == 0) { /* * After all the gem state is reset, increment the reset @@ -1528,12 +1563,11 @@ static void i915_error_work_func(struct work_struct *work) atomic_set(&error->reset_counter, I915_WEDGED); } - for_each_ring(ring, dev_priv, i) - wake_up_all(&ring->irq_queue); - - intel_display_handle_reset(dev); - - wake_up_all(&dev_priv->gpu_error.reset_queue); + /* + * Note: The wake_up also serves as a memory barrier so that + * waiters see the update value of the reset counter atomic_t. + */ + i915_error_wake_up(dev_priv, true); } } @@ -1642,8 +1676,6 @@ static void i915_report_and_clear_eir(struct drm_device *dev) void i915_handle_error(struct drm_device *dev, bool wedged) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring; - int i; i915_capture_error_state(dev); i915_report_and_clear_eir(dev); @@ -1653,11 +1685,19 @@ void i915_handle_error(struct drm_device *dev, bool wedged) &dev_priv->gpu_error.reset_counter); /* - * Wakeup waiting processes so that the reset work item - * doesn't deadlock trying to grab various locks. + * Wakeup waiting processes so that the reset work function + * i915_error_work_func doesn't deadlock trying to grab various + * locks. By bumping the reset counter first, the woken + * processes will see a reset in progress and back off, + * releasing their locks and then wait for the reset completion. + * We must do this for _all_ gpu waiters that might hold locks + * that the reset work needs to acquire. + * + * Note: The wake_up serves as the required memory barrier to + * ensure that the waiters see the updated value of the reset + * counter atomic_t. */ - for_each_ring(ring, dev_priv, i) - wake_up_all(&ring->irq_queue); + i915_error_wake_up(dev_priv, false); } /* diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 63aca49d11a8..63de2701b974 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -778,7 +778,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) /* Can only use the always-on power well for eDP when * not using the panel fitter, and when not using motion * blur mitigation (which we don't support). */ - if (intel_crtc->config.pch_pfit.size) + if (intel_crtc->config.pch_pfit.enabled) temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; else temp |= TRANS_DDI_EDP_INPUT_A_ON; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2489d0b4c7d2..d8a1d98693e7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2249,7 +2249,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, I915_WRITE(PIPESRC(intel_crtc->pipe), ((crtc->mode.hdisplay - 1) << 16) | (crtc->mode.vdisplay - 1)); - if (!intel_crtc->config.pch_pfit.size && + if (!intel_crtc->config.pch_pfit.enabled && (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) { I915_WRITE(PF_CTL(intel_crtc->pipe), 0); @@ -3203,7 +3203,7 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; int pipe = crtc->pipe; - if (crtc->config.pch_pfit.size) { + if (crtc->config.pch_pfit.enabled) { /* Force use of hard-coded filter coefficients * as some pre-programmed values are broken, * e.g. x201. @@ -3428,7 +3428,7 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc) /* To avoid upsetting the power well on haswell only disable the pfit if * it's in use. The hw state code will make sure we get this right. */ - if (crtc->config.pch_pfit.size) { + if (crtc->config.pch_pfit.enabled) { I915_WRITE(PF_CTL(pipe), 0); I915_WRITE(PF_WIN_POS(pipe), 0); I915_WRITE(PF_WIN_SZ(pipe), 0); @@ -4877,9 +4877,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, return -EINVAL; } - /* Ensure that the cursor is valid for the new mode before changing... */ - intel_crtc_update_cursor(crtc, true); - if (is_lvds && dev_priv->lvds_downclock_avail) { /* * Ensure we match the reduced clock's P to the target clock. @@ -5768,9 +5765,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, intel_crtc->config.dpll.p2 = clock.p2; } - /* Ensure that the cursor is valid for the new mode before changing... */ - intel_crtc_update_cursor(crtc, true); - /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */ if (intel_crtc->config.has_pch_encoder) { fp = i9xx_dpll_compute_fp(&intel_crtc->config.dpll); @@ -5859,6 +5853,7 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc, tmp = I915_READ(PF_CTL(crtc->pipe)); if (tmp & PF_ENABLE) { + pipe_config->pch_pfit.enabled = true; pipe_config->pch_pfit.pos = I915_READ(PF_WIN_POS(crtc->pipe)); pipe_config->pch_pfit.size = I915_READ(PF_WIN_SZ(crtc->pipe)); @@ -6236,7 +6231,7 @@ static void haswell_modeset_global_resources(struct drm_device *dev) if (!crtc->base.enabled) continue; - if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.size || + if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.enabled || crtc->config.cpu_transcoder != TRANSCODER_EDP) enable = true; } @@ -6259,9 +6254,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc, if (!intel_ddi_pll_mode_set(crtc)) return -EINVAL; - /* Ensure that the cursor is valid for the new mode before changing... */ - intel_crtc_update_cursor(crtc, true); - if (intel_crtc->config.has_dp_encoder) intel_dp_set_m_n(intel_crtc); @@ -6494,15 +6486,15 @@ static void haswell_write_eld(struct drm_connector *connector, /* Set ELD valid state */ tmp = I915_READ(aud_cntrl_st2); - DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%8x\n", tmp); + DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%08x\n", tmp); tmp |= (AUDIO_ELD_VALID_A << (pipe * 4)); I915_WRITE(aud_cntrl_st2, tmp); tmp = I915_READ(aud_cntrl_st2); - DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%8x\n", tmp); + DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%08x\n", tmp); /* Enable HDMI mode */ tmp = I915_READ(aud_config); - DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%8x\n", tmp); + DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%08x\n", tmp); /* clear N_programing_enable and N_value_index */ tmp &= ~(AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_N_PROG_ENABLE); I915_WRITE(aud_config, tmp); @@ -6937,7 +6929,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, intel_crtc->cursor_width = width; intel_crtc->cursor_height = height; - intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); + if (intel_crtc->active) + intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); return 0; fail_unpin: @@ -6956,7 +6949,8 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) intel_crtc->cursor_x = x; intel_crtc->cursor_y = y; - intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); + if (intel_crtc->active) + intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); return 0; } @@ -8205,9 +8199,10 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->gmch_pfit.control, pipe_config->gmch_pfit.pgm_ratios, pipe_config->gmch_pfit.lvds_border_bits); - DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x\n", + DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x, %s\n", pipe_config->pch_pfit.pos, - pipe_config->pch_pfit.size); + pipe_config->pch_pfit.size, + pipe_config->pch_pfit.enabled ? "enabled" : "disabled"); DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled); } @@ -8603,8 +8598,11 @@ intel_pipe_config_compare(struct drm_device *dev, if (INTEL_INFO(dev)->gen < 4) PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios); PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits); - PIPE_CONF_CHECK_I(pch_pfit.pos); - PIPE_CONF_CHECK_I(pch_pfit.size); + PIPE_CONF_CHECK_I(pch_pfit.enabled); + if (current_config->pch_pfit.enabled) { + PIPE_CONF_CHECK_I(pch_pfit.pos); + PIPE_CONF_CHECK_I(pch_pfit.size); + } PIPE_CONF_CHECK_I(ips_enabled); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a47799e832c6..28cae80495e2 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -280,6 +280,7 @@ struct intel_crtc_config { struct { u32 pos; u32 size; + bool enabled; } pch_pfit; /* FDI configuration, only valid if has_pch_encoder is set. */ diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 406303b509c1..7fa7df546c1e 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -263,6 +263,8 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder, C(vtotal); C(clock); #undef C + + drm_mode_set_crtcinfo(adjusted_mode, 0); } if (intel_dvo->dev.dev_ops->mode_fixup) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 42114ecbae0e..293564a2896a 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -112,6 +112,7 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc, done: pipe_config->pch_pfit.pos = (x << 16) | y; pipe_config->pch_pfit.size = (width << 16) | height; + pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0; } static void diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0c115cc4899f..dd176b7296c1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2096,16 +2096,16 @@ static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev, struct drm_crtc *crtc) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - uint32_t pixel_rate, pfit_size; + uint32_t pixel_rate; pixel_rate = intel_crtc->config.adjusted_mode.clock; /* We only use IF-ID interlacing. If we ever use PF-ID we'll need to * adjust the pixel_rate here. */ - pfit_size = intel_crtc->config.pch_pfit.size; - if (pfit_size) { + if (intel_crtc->config.pch_pfit.enabled) { uint64_t pipe_w, pipe_h, pfit_w, pfit_h; + uint32_t pfit_size = intel_crtc->config.pch_pfit.size; pipe_w = intel_crtc->config.requested_mode.hdisplay; pipe_h = intel_crtc->config.requested_mode.vdisplay; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 85037b9d4934..49482fd5b76c 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -788,6 +788,8 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd, uint16_t h_sync_offset, v_sync_offset; int mode_clock; + memset(dtd, 0, sizeof(*dtd)); + width = mode->hdisplay; height = mode->vdisplay; @@ -830,44 +832,51 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd, if (mode->flags & DRM_MODE_FLAG_PVSYNC) dtd->part2.dtd_flags |= DTD_FLAG_VSYNC_POSITIVE; - dtd->part2.sdvo_flags = 0; dtd->part2.v_sync_off_high = v_sync_offset & 0xc0; - dtd->part2.reserved = 0; } -static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode, +static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode *pmode, const struct intel_sdvo_dtd *dtd) { - mode->hdisplay = dtd->part1.h_active; - mode->hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8; - mode->hsync_start = mode->hdisplay + dtd->part2.h_sync_off; - mode->hsync_start += (dtd->part2.sync_off_width_high & 0xc0) << 2; - mode->hsync_end = mode->hsync_start + dtd->part2.h_sync_width; - mode->hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4; - mode->htotal = mode->hdisplay + dtd->part1.h_blank; - mode->htotal += (dtd->part1.h_high & 0xf) << 8; - - mode->vdisplay = dtd->part1.v_active; - mode->vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8; - mode->vsync_start = mode->vdisplay; - mode->vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf; - mode->vsync_start += (dtd->part2.sync_off_width_high & 0x0c) << 2; - mode->vsync_start += dtd->part2.v_sync_off_high & 0xc0; - mode->vsync_end = mode->vsync_start + + struct drm_display_mode mode = {}; + + mode.hdisplay = dtd->part1.h_active; + mode.hdisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8; + mode.hsync_start = mode.hdisplay + dtd->part2.h_sync_off; + mode.hsync_start += (dtd->part2.sync_off_width_high & 0xc0) << 2; + mode.hsync_end = mode.hsync_start + dtd->part2.h_sync_width; + mode.hsync_end += (dtd->part2.sync_off_width_high & 0x30) << 4; + mode.htotal = mode.hdisplay + dtd->part1.h_blank; + mode.htotal += (dtd->part1.h_high & 0xf) << 8; + + mode.vdisplay = dtd->part1.v_active; + mode.vdisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8; + mode.vsync_start = mode.vdisplay; + mode.vsync_start += (dtd->part2.v_sync_off_width >> 4) & 0xf; + mode.vsync_start += (dtd->part2.sync_off_width_high & 0x0c) << 2; + mode.vsync_start += dtd->part2.v_sync_off_high & 0xc0; + mode.vsync_end = mode.vsync_start + (dtd->part2.v_sync_off_width & 0xf); - mode->vsync_end += (dtd->part2.sync_off_width_high & 0x3) << 4; - mode->vtotal = mode->vdisplay + dtd->part1.v_blank; - mode->vtotal += (dtd->part1.v_high & 0xf) << 8; + mode.vsync_end += (dtd->part2.sync_off_width_high & 0x3) << 4; + mode.vtotal = mode.vdisplay + dtd->part1.v_blank; + mode.vtotal += (dtd->part1.v_high & 0xf) << 8; - mode->clock = dtd->part1.clock * 10; + mode.clock = dtd->part1.clock * 10; - mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); if (dtd->part2.dtd_flags & DTD_FLAG_INTERLACE) - mode->flags |= DRM_MODE_FLAG_INTERLACE; + mode.flags |= DRM_MODE_FLAG_INTERLACE; if (dtd->part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE) - mode->flags |= DRM_MODE_FLAG_PHSYNC; + mode.flags |= DRM_MODE_FLAG_PHSYNC; + else + mode.flags |= DRM_MODE_FLAG_NHSYNC; if (dtd->part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE) - mode->flags |= DRM_MODE_FLAG_PVSYNC; + mode.flags |= DRM_MODE_FLAG_PVSYNC; + else + mode.flags |= DRM_MODE_FLAG_NVSYNC; + + drm_mode_set_crtcinfo(&mode, 0); + + drm_mode_copy(pmode, &mode); } static bool intel_sdvo_check_supp_encode(struct intel_sdvo *intel_sdvo) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index a60584763b61..a0b9d8a95b16 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -124,6 +124,8 @@ void adreno_recover(struct msm_gpu *gpu) /* reset completed fence seqno, just discard anything pending: */ adreno_gpu->memptrs->fence = gpu->submitted_fence; + adreno_gpu->memptrs->rptr = 0; + adreno_gpu->memptrs->wptr = 0; gpu->funcs->pm_resume(gpu); ret = gpu->funcs->hw_init(gpu); @@ -229,7 +231,7 @@ void adreno_idle(struct msm_gpu *gpu) return; } while(time_before(jiffies, t)); - DRM_ERROR("timeout waiting for %s to drain ringbuffer!\n", gpu->name); + DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name); /* TODO maybe we need to reset GPU here to recover from hang? */ } @@ -256,11 +258,17 @@ void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); uint32_t freedwords; + unsigned long t = jiffies + ADRENO_IDLE_TIMEOUT; do { uint32_t size = gpu->rb->size / 4; uint32_t wptr = get_wptr(gpu->rb); uint32_t rptr = adreno_gpu->memptrs->rptr; freedwords = (rptr + (size - 1) - wptr) % size; + + if (time_after(jiffies, t)) { + DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name); + break; + } } while(freedwords < ndwords); } diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 864c9773636b..008d772384c7 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -499,25 +499,41 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, struct timespec *timeout) { struct msm_drm_private *priv = dev->dev_private; - unsigned long timeout_jiffies = timespec_to_jiffies(timeout); - unsigned long start_jiffies = jiffies; - unsigned long remaining_jiffies; int ret; - if (time_after(start_jiffies, timeout_jiffies)) - remaining_jiffies = 0; - else - remaining_jiffies = timeout_jiffies - start_jiffies; - - ret = wait_event_interruptible_timeout(priv->fence_event, - priv->completed_fence >= fence, - remaining_jiffies); - if (ret == 0) { - DBG("timeout waiting for fence: %u (completed: %u)", - fence, priv->completed_fence); - ret = -ETIMEDOUT; - } else if (ret != -ERESTARTSYS) { - ret = 0; + if (!priv->gpu) + return 0; + + if (fence > priv->gpu->submitted_fence) { + DRM_ERROR("waiting on invalid fence: %u (of %u)\n", + fence, priv->gpu->submitted_fence); + return -EINVAL; + } + + if (!timeout) { + /* no-wait: */ + ret = fence_completed(dev, fence) ? 0 : -EBUSY; + } else { + unsigned long timeout_jiffies = timespec_to_jiffies(timeout); + unsigned long start_jiffies = jiffies; + unsigned long remaining_jiffies; + + if (time_after(start_jiffies, timeout_jiffies)) + remaining_jiffies = 0; + else + remaining_jiffies = timeout_jiffies - start_jiffies; + + ret = wait_event_interruptible_timeout(priv->fence_event, + fence_completed(dev, fence), + remaining_jiffies); + + if (ret == 0) { + DBG("timeout waiting for fence: %u (completed: %u)", + fence, priv->completed_fence); + ret = -ETIMEDOUT; + } else if (ret != -ERESTARTSYS) { + ret = 0; + } } return ret; diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 80d75094bf0a..df8f1d084bc1 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -153,7 +153,7 @@ void *msm_gem_vaddr(struct drm_gem_object *obj); int msm_gem_queue_inactive_work(struct drm_gem_object *obj, struct work_struct *work); void msm_gem_move_to_active(struct drm_gem_object *obj, - struct msm_gpu *gpu, uint32_t fence); + struct msm_gpu *gpu, bool write, uint32_t fence); void msm_gem_move_to_inactive(struct drm_gem_object *obj); int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, struct timespec *timeout); @@ -191,6 +191,12 @@ u32 msm_readl(const void __iomem *addr); #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) +static inline bool fence_completed(struct drm_device *dev, uint32_t fence) +{ + struct msm_drm_private *priv = dev->dev_private; + return priv->completed_fence >= fence; +} + static inline int align_pitch(int width, int bpp) { int bytespp = (bpp + 7) / 8; diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 6b5a6c8c7658..29eacfa29cfb 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -40,9 +40,9 @@ static struct page **get_pages(struct drm_gem_object *obj) } msm_obj->sgt = drm_prime_pages_to_sg(p, npages); - if (!msm_obj->sgt) { + if (IS_ERR(msm_obj->sgt)) { dev_err(dev->dev, "failed to allocate sgt\n"); - return ERR_PTR(-ENOMEM); + return ERR_CAST(msm_obj->sgt); } msm_obj->pages = p; @@ -159,7 +159,6 @@ out_unlock: out: switch (ret) { case -EAGAIN: - set_need_resched(); case 0: case -ERESTARTSYS: case -EINTR: @@ -393,11 +392,14 @@ int msm_gem_queue_inactive_work(struct drm_gem_object *obj, } void msm_gem_move_to_active(struct drm_gem_object *obj, - struct msm_gpu *gpu, uint32_t fence) + struct msm_gpu *gpu, bool write, uint32_t fence) { struct msm_gem_object *msm_obj = to_msm_bo(obj); msm_obj->gpu = gpu; - msm_obj->fence = fence; + if (write) + msm_obj->write_fence = fence; + else + msm_obj->read_fence = fence; list_del_init(&msm_obj->mm_list); list_add_tail(&msm_obj->mm_list, &gpu->active_list); } @@ -411,7 +413,8 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj) WARN_ON(!mutex_is_locked(&dev->struct_mutex)); msm_obj->gpu = NULL; - msm_obj->fence = 0; + msm_obj->read_fence = 0; + msm_obj->write_fence = 0; list_del_init(&msm_obj->mm_list); list_add_tail(&msm_obj->mm_list, &priv->inactive_list); @@ -433,8 +436,18 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, struct msm_gem_object *msm_obj = to_msm_bo(obj); int ret = 0; - if (is_active(msm_obj) && !(op & MSM_PREP_NOSYNC)) - ret = msm_wait_fence_interruptable(dev, msm_obj->fence, timeout); + if (is_active(msm_obj)) { + uint32_t fence = 0; + + if (op & MSM_PREP_READ) + fence = msm_obj->write_fence; + if (op & MSM_PREP_WRITE) + fence = max(fence, msm_obj->read_fence); + if (op & MSM_PREP_NOSYNC) + timeout = NULL; + + ret = msm_wait_fence_interruptable(dev, fence, timeout); + } /* TODO cache maintenance */ @@ -455,9 +468,10 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m) uint64_t off = drm_vma_node_start(&obj->vma_node); WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - seq_printf(m, "%08x: %c(%d) %2d (%2d) %08llx %p %d\n", + seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %d\n", msm_obj->flags, is_active(msm_obj) ? 'A' : 'I', - msm_obj->fence, obj->name, obj->refcount.refcount.counter, + msm_obj->read_fence, msm_obj->write_fence, + obj->name, obj->refcount.refcount.counter, off, msm_obj->vaddr, obj->size); } diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index d746f13d283c..0676f32e2c6a 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -36,7 +36,7 @@ struct msm_gem_object { */ struct list_head mm_list; struct msm_gpu *gpu; /* non-null if active */ - uint32_t fence; + uint32_t read_fence, write_fence; /* Transiently in the process of submit ioctl, objects associated * with the submit are on submit->bo_list.. this only lasts for diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 3e1ef3a00f60..5281d4bc37f7 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -78,7 +78,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, } if (submit_bo.flags & BO_INVALID_FLAGS) { - DBG("invalid flags: %x", submit_bo.flags); + DRM_ERROR("invalid flags: %x\n", submit_bo.flags); ret = -EINVAL; goto out_unlock; } @@ -92,7 +92,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, */ obj = idr_find(&file->object_idr, submit_bo.handle); if (!obj) { - DBG("invalid handle %u at index %u", submit_bo.handle, i); + DRM_ERROR("invalid handle %u at index %u\n", submit_bo.handle, i); ret = -EINVAL; goto out_unlock; } @@ -100,7 +100,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit, msm_obj = to_msm_bo(obj); if (!list_empty(&msm_obj->submit_entry)) { - DBG("handle %u at index %u already on submit list", + DRM_ERROR("handle %u at index %u already on submit list\n", submit_bo.handle, i); ret = -EINVAL; goto out_unlock; @@ -216,8 +216,9 @@ static int submit_bo(struct msm_gem_submit *submit, uint32_t idx, struct msm_gem_object **obj, uint32_t *iova, bool *valid) { if (idx >= submit->nr_bos) { - DBG("invalid buffer index: %u (out of %u)", idx, submit->nr_bos); - return EINVAL; + DRM_ERROR("invalid buffer index: %u (out of %u)\n", + idx, submit->nr_bos); + return -EINVAL; } if (obj) @@ -239,7 +240,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob int ret; if (offset % 4) { - DBG("non-aligned cmdstream buffer: %u", offset); + DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset); return -EINVAL; } @@ -266,7 +267,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob return -EFAULT; if (submit_reloc.submit_offset % 4) { - DBG("non-aligned reloc offset: %u", + DRM_ERROR("non-aligned reloc offset: %u\n", submit_reloc.submit_offset); return -EINVAL; } @@ -276,7 +277,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob if ((off >= (obj->base.size / 4)) || (off < last_offset)) { - DBG("invalid offset %u at reloc %u", off, i); + DRM_ERROR("invalid offset %u at reloc %u\n", off, i); return -EINVAL; } @@ -374,14 +375,15 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, goto out; if (submit_cmd.size % 4) { - DBG("non-aligned cmdstream buffer size: %u", + DRM_ERROR("non-aligned cmdstream buffer size: %u\n", submit_cmd.size); ret = -EINVAL; goto out; } - if (submit_cmd.size >= msm_obj->base.size) { - DBG("invalid cmdstream size: %u", submit_cmd.size); + if ((submit_cmd.size + submit_cmd.submit_offset) >= + msm_obj->base.size) { + DRM_ERROR("invalid cmdstream size: %u\n", submit_cmd.size); ret = -EINVAL; goto out; } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index e1e1ec9321ff..3bab937965d1 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -29,13 +29,14 @@ static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev) { struct drm_device *dev = gpu->dev; - struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; + struct kgsl_device_platform_data *pdata; if (!pdev) { dev_err(dev->dev, "could not find dtv pdata\n"); return; } + pdata = pdev->dev.platform_data; if (pdata->bus_scale_table) { gpu->bsc = msm_bus_scale_register_client(pdata->bus_scale_table); DBG("bus scale client: %08x", gpu->bsc); @@ -230,6 +231,8 @@ static void hangcheck_timer_reset(struct msm_gpu *gpu) static void hangcheck_handler(unsigned long data) { struct msm_gpu *gpu = (struct msm_gpu *)data; + struct drm_device *dev = gpu->dev; + struct msm_drm_private *priv = dev->dev_private; uint32_t fence = gpu->funcs->last_fence(gpu); if (fence != gpu->hangcheck_fence) { @@ -237,14 +240,22 @@ static void hangcheck_handler(unsigned long data) gpu->hangcheck_fence = fence; } else if (fence < gpu->submitted_fence) { /* no progress and not done.. hung! */ - struct msm_drm_private *priv = gpu->dev->dev_private; gpu->hangcheck_fence = fence; + dev_err(dev->dev, "%s: hangcheck detected gpu lockup!\n", + gpu->name); + dev_err(dev->dev, "%s: completed fence: %u\n", + gpu->name, fence); + dev_err(dev->dev, "%s: submitted fence: %u\n", + gpu->name, gpu->submitted_fence); queue_work(priv->wq, &gpu->recover_work); } /* if still more pending work, reset the hangcheck timer: */ if (gpu->submitted_fence > gpu->hangcheck_fence) hangcheck_timer_reset(gpu); + + /* workaround for missing irq: */ + queue_work(priv->wq, &gpu->retire_work); } /* @@ -265,7 +276,8 @@ static void retire_worker(struct work_struct *work) obj = list_first_entry(&gpu->active_list, struct msm_gem_object, mm_list); - if (obj->fence <= fence) { + if ((obj->read_fence <= fence) && + (obj->write_fence <= fence)) { /* move to inactive: */ msm_gem_move_to_inactive(&obj->base); msm_gem_put_iova(&obj->base, gpu->id); @@ -321,7 +333,11 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, submit->gpu->id, &iova); } - msm_gem_move_to_active(&msm_obj->base, gpu, submit->fence); + if (submit->bos[i].flags & MSM_SUBMIT_BO_READ) + msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence); + + if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE) + msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence); } hangcheck_timer_reset(gpu); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index 2e11ea02cf87..57cda2a1437b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c @@ -579,8 +579,22 @@ static void init_reserved(struct nvbios_init *init) { u8 opcode = nv_ro08(init->bios, init->offset); - trace("RESERVED\t0x%02x\n", opcode); - init->offset += 1; + u8 length, i; + + switch (opcode) { + case 0xaa: + length = 4; + break; + default: + length = 1; + break; + } + + trace("RESERVED 0x%02x\t", opcode); + for (i = 1; i < length; i++) + cont(" 0x%02x", nv_ro08(init->bios, init->offset + i)); + cont("\n"); + init->offset += length; } /** @@ -1437,7 +1451,7 @@ init_configure_mem(struct nvbios_init *init) data = init_rdvgai(init, 0x03c4, 0x01); init_wrvgai(init, 0x03c4, 0x01, data | 0x20); - while ((addr = nv_ro32(bios, sdata)) != 0xffffffff) { + for (; (addr = nv_ro32(bios, sdata)) != 0xffffffff; sdata += 4) { switch (addr) { case 0x10021c: /* CKE_NORMAL */ case 0x1002d0: /* CMD_REFRESH */ @@ -2135,6 +2149,7 @@ static struct nvbios_init_opcode { [0x99] = { init_zm_auxch }, [0x9a] = { init_i2c_long_if }, [0xa9] = { init_gpio_ne }, + [0xaa] = { init_reserved }, }; #define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index d2712e6e5d31..7848590f5568 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -278,7 +278,6 @@ nouveau_display_create(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_display *disp; - u32 pclass = dev->pdev->class >> 8; int ret, gen; disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); @@ -340,29 +339,25 @@ nouveau_display_create(struct drm_device *dev) drm_kms_helper_poll_init(dev); drm_kms_helper_poll_disable(dev); - if (nouveau_modeset == 1 || - (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) { - if (drm->vbios.dcb.entries) { - if (nv_device(drm->device)->card_type < NV_50) - ret = nv04_display_create(dev); - else - ret = nv50_display_create(dev); - } else { - ret = 0; - } - - if (ret) - goto disp_create_err; + if (drm->vbios.dcb.entries) { + if (nv_device(drm->device)->card_type < NV_50) + ret = nv04_display_create(dev); + else + ret = nv50_display_create(dev); + } else { + ret = 0; + } - if (dev->mode_config.num_crtc) { - ret = drm_vblank_init(dev, dev->mode_config.num_crtc); - if (ret) - goto vblank_err; - } + if (ret) + goto disp_create_err; - nouveau_backlight_init(dev); + if (dev->mode_config.num_crtc) { + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); + if (ret) + goto vblank_err; } + nouveau_backlight_init(dev); return 0; vblank_err: diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 8f6d63d7edd3..a86ecf65c164 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -454,7 +454,8 @@ nouveau_fbcon_init(struct drm_device *dev) int preferred_bpp; int ret; - if (!dev->mode_config.num_crtc) + if (!dev->mode_config.num_crtc || + (dev->pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) return 0; fbcon = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL); diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index ca5492ac2da5..0843ebc910d4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -104,9 +104,7 @@ nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev, else nvbe->ttm.ttm.func = &nv50_sgdma_backend; - if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page)) { - kfree(nvbe); + if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page)) return NULL; - } return &nvbe->ttm.ttm; } diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index dfac7965ea28..32923d2f6002 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -707,8 +707,9 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ - if (drm_detect_hdmi_monitor(radeon_connector->edid) && - radeon_audio) + if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) || + (drm_detect_hdmi_monitor(radeon_connector->edid) && + (radeon_connector->audio == RADEON_AUDIO_AUTO))) return ATOM_ENCODER_MODE_HDMI; else if (radeon_connector->use_digital) return ATOM_ENCODER_MODE_DVI; @@ -718,8 +719,9 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_HDMIA: default: - if (drm_detect_hdmi_monitor(radeon_connector->edid) && - radeon_audio) + if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) || + (drm_detect_hdmi_monitor(radeon_connector->edid) && + (radeon_connector->audio == RADEON_AUDIO_AUTO))) return ATOM_ENCODER_MODE_HDMI; else return ATOM_ENCODER_MODE_DVI; @@ -732,8 +734,9 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) return ATOM_ENCODER_MODE_DP; - else if (drm_detect_hdmi_monitor(radeon_connector->edid) && - radeon_audio) + else if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) || + (drm_detect_hdmi_monitor(radeon_connector->edid) && + (radeon_connector->audio == RADEON_AUDIO_AUTO))) return ATOM_ENCODER_MODE_HDMI; else return ATOM_ENCODER_MODE_DVI; @@ -1647,8 +1650,12 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) + /* some dce3.x boards have a bug in their transmitter control table. + * ACTION_ENABLE_OUTPUT can probably be dropped since ACTION_ENABLE + * does the same thing and more. + */ + if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) && + (rdev->family != CHIP_RS880)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c index 084e69414fd1..05ff315e8e9e 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.c +++ b/drivers/gpu/drm/radeon/btc_dpm.c @@ -2340,12 +2340,6 @@ int btc_dpm_set_power_state(struct radeon_device *rdev) return ret; } - ret = rv770_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO); - if (ret) { - DRM_ERROR("rv770_dpm_force_performance_level failed\n"); - return ret; - } - return 0; } diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 3cce533397c6..899627443030 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -4748,12 +4748,6 @@ int ci_dpm_set_power_state(struct radeon_device *rdev) if (pi->pcie_performance_request) ci_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps); - ret = ci_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO); - if (ret) { - DRM_ERROR("ci_dpm_force_performance_level failed\n"); - return ret; - } - cik_update_cg(rdev, (RADEON_CG_BLOCK_GFX | RADEON_CG_BLOCK_MC | RADEON_CG_BLOCK_SDMA | diff --git a/drivers/gpu/drm/radeon/ci_smc.c b/drivers/gpu/drm/radeon/ci_smc.c index 53b43dd3cf1e..252e10a41cf5 100644 --- a/drivers/gpu/drm/radeon/ci_smc.c +++ b/drivers/gpu/drm/radeon/ci_smc.c @@ -47,10 +47,11 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev, u32 smc_start_address, const u8 *src, u32 byte_count, u32 limit) { + unsigned long flags; u32 data, original_data; u32 addr; u32 extra_shift; - int ret; + int ret = 0; if (smc_start_address & 3) return -EINVAL; @@ -59,13 +60,14 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev, addr = smc_start_address; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); while (byte_count >= 4) { /* SMC address space is BE */ data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; ret = ci_set_smc_sram_address(rdev, addr, limit); if (ret) - return ret; + goto done; WREG32(SMC_IND_DATA_0, data); @@ -80,7 +82,7 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev, ret = ci_set_smc_sram_address(rdev, addr, limit); if (ret) - return ret; + goto done; original_data = RREG32(SMC_IND_DATA_0); @@ -97,11 +99,15 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev, ret = ci_set_smc_sram_address(rdev, addr, limit); if (ret) - return ret; + goto done; WREG32(SMC_IND_DATA_0, data); } - return 0; + +done: + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); + + return ret; } void ci_start_smc(struct radeon_device *rdev) @@ -197,6 +203,7 @@ PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev) int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit) { + unsigned long flags; u32 ucode_start_address; u32 ucode_size; const u8 *src; @@ -219,6 +226,7 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit) return -EINVAL; src = (const u8 *)rdev->smc_fw->data; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); WREG32(SMC_IND_INDEX_0, ucode_start_address); WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0); while (ucode_size >= 4) { @@ -231,6 +239,7 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit) ucode_size -= 4; } WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); return 0; } @@ -238,25 +247,29 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit) int ci_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 *value, u32 limit) { + unsigned long flags; int ret; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); ret = ci_set_smc_sram_address(rdev, smc_address, limit); - if (ret) - return ret; + if (ret == 0) + *value = RREG32(SMC_IND_DATA_0); + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); - *value = RREG32(SMC_IND_DATA_0); - return 0; + return ret; } int ci_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 value, u32 limit) { + unsigned long flags; int ret; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); ret = ci_set_smc_sram_address(rdev, smc_address, limit); - if (ret) - return ret; + if (ret == 0) + WREG32(SMC_IND_DATA_0, value); + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); - WREG32(SMC_IND_DATA_0, value); - return 0; + return ret; } diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index a3bba0587276..adbdb6503b05 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -77,6 +77,8 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev); static void cik_program_aspm(struct radeon_device *rdev); static void cik_init_pg(struct radeon_device *rdev); static void cik_init_cg(struct radeon_device *rdev); +static void cik_enable_gui_idle_interrupt(struct radeon_device *rdev, + bool enable); /* get temperature in millidegrees */ int ci_get_temp(struct radeon_device *rdev) @@ -120,20 +122,27 @@ int kv_get_temp(struct radeon_device *rdev) */ u32 cik_pciep_rreg(struct radeon_device *rdev, u32 reg) { + unsigned long flags; u32 r; + spin_lock_irqsave(&rdev->pciep_idx_lock, flags); WREG32(PCIE_INDEX, reg); (void)RREG32(PCIE_INDEX); r = RREG32(PCIE_DATA); + spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags); return r; } void cik_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->pciep_idx_lock, flags); WREG32(PCIE_INDEX, reg); (void)RREG32(PCIE_INDEX); WREG32(PCIE_DATA, v); (void)RREG32(PCIE_DATA); + spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags); } static const u32 spectre_rlc_save_restore_register_list[] = @@ -2722,7 +2731,8 @@ static void cik_gpu_init(struct radeon_device *rdev) } else if ((rdev->pdev->device == 0x1309) || (rdev->pdev->device == 0x130A) || (rdev->pdev->device == 0x130D) || - (rdev->pdev->device == 0x1313)) { + (rdev->pdev->device == 0x1313) || + (rdev->pdev->device == 0x131D)) { rdev->config.cik.max_cu_per_sh = 6; rdev->config.cik.max_backends_per_se = 2; } else if ((rdev->pdev->device == 0x1306) || @@ -4013,6 +4023,8 @@ static int cik_cp_resume(struct radeon_device *rdev) { int r; + cik_enable_gui_idle_interrupt(rdev, false); + r = cik_cp_load_microcode(rdev); if (r) return r; @@ -4024,6 +4036,8 @@ static int cik_cp_resume(struct radeon_device *rdev) if (r) return r; + cik_enable_gui_idle_interrupt(rdev, true); + return 0; } @@ -5376,7 +5390,9 @@ static void cik_enable_hdp_ls(struct radeon_device *rdev, void cik_update_cg(struct radeon_device *rdev, u32 block, bool enable) { + if (block & RADEON_CG_BLOCK_GFX) { + cik_enable_gui_idle_interrupt(rdev, false); /* order matters! */ if (enable) { cik_enable_mgcg(rdev, true); @@ -5385,6 +5401,7 @@ void cik_update_cg(struct radeon_device *rdev, cik_enable_cgcg(rdev, false); cik_enable_mgcg(rdev, false); } + cik_enable_gui_idle_interrupt(rdev, true); } if (block & RADEON_CG_BLOCK_MC) { @@ -5541,7 +5558,7 @@ static void cik_enable_gfx_cgpg(struct radeon_device *rdev, { u32 data, orig; - if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG)) { + if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG)) { orig = data = RREG32(RLC_PG_CNTL); data |= GFX_PG_ENABLE; if (orig != data) @@ -5805,7 +5822,7 @@ static void cik_init_pg(struct radeon_device *rdev) if (rdev->pg_flags) { cik_enable_sck_slowdown_on_pu(rdev, true); cik_enable_sck_slowdown_on_pd(rdev, true); - if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) { + if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) { cik_init_gfx_cgpg(rdev); cik_enable_cp_pg(rdev, true); cik_enable_gds_pg(rdev, true); @@ -5819,7 +5836,7 @@ static void cik_fini_pg(struct radeon_device *rdev) { if (rdev->pg_flags) { cik_update_gfx_pg(rdev, false); - if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) { + if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) { cik_enable_cp_pg(rdev, false); cik_enable_gds_pg(rdev, false); } @@ -5895,7 +5912,9 @@ static void cik_disable_interrupt_state(struct radeon_device *rdev) u32 tmp; /* gfx ring */ - WREG32(CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + tmp = RREG32(CP_INT_CNTL_RING0) & + (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + WREG32(CP_INT_CNTL_RING0, tmp); /* sdma */ tmp = RREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET) & ~TRAP_ENABLE; WREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET, tmp); @@ -6036,8 +6055,7 @@ static int cik_irq_init(struct radeon_device *rdev) */ int cik_irq_set(struct radeon_device *rdev) { - u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE | - PRIV_INSTR_INT_ENABLE | PRIV_REG_INT_ENABLE; + u32 cp_int_cntl; u32 cp_m1p0, cp_m1p1, cp_m1p2, cp_m1p3; u32 cp_m2p0, cp_m2p1, cp_m2p2, cp_m2p3; u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; @@ -6058,6 +6076,10 @@ int cik_irq_set(struct radeon_device *rdev) return 0; } + cp_int_cntl = RREG32(CP_INT_CNTL_RING0) & + (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + cp_int_cntl |= PRIV_INSTR_INT_ENABLE | PRIV_REG_INT_ENABLE; + hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; diff --git a/drivers/gpu/drm/radeon/cypress_dpm.c b/drivers/gpu/drm/radeon/cypress_dpm.c index 95a66db08d9b..91bb470de0a3 100644 --- a/drivers/gpu/drm/radeon/cypress_dpm.c +++ b/drivers/gpu/drm/radeon/cypress_dpm.c @@ -2014,12 +2014,6 @@ int cypress_dpm_set_power_state(struct radeon_device *rdev) if (eg_pi->pcie_performance_request) cypress_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps); - ret = rv770_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO); - if (ret) { - DRM_ERROR("rv770_dpm_force_performance_level failed\n"); - return ret; - } - return 0; } diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 8953255e894b..85a69d2ea3d2 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -28,22 +28,30 @@ static u32 dce6_endpoint_rreg(struct radeon_device *rdev, u32 block_offset, u32 reg) { + unsigned long flags; u32 r; + spin_lock_irqsave(&rdev->end_idx_lock, flags); WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); r = RREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset); + spin_unlock_irqrestore(&rdev->end_idx_lock, flags); + return r; } static void dce6_endpoint_wreg(struct radeon_device *rdev, u32 block_offset, u32 reg, u32 v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->end_idx_lock, flags); if (ASIC_IS_DCE8(rdev)) WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg); else WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, AZ_ENDPOINT_REG_WRITE_EN | AZ_ENDPOINT_REG_INDEX(reg)); WREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset, v); + spin_unlock_irqrestore(&rdev->end_idx_lock, flags); } #define RREG32_ENDPOINT(block, reg) dce6_endpoint_rreg(rdev, (block), (reg)) @@ -86,12 +94,12 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder) struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; u32 offset = dig->afmt->offset; - u32 id = dig->afmt->pin->id; if (!dig->afmt->pin) return; - WREG32(AFMT_AUDIO_SRC_CONTROL + offset, AFMT_AUDIO_SRC_SELECT(id)); + WREG32(AFMT_AUDIO_SRC_CONTROL + offset, + AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id)); } void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index ecd60809db4e..71399065db04 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -40,6 +40,7 @@ static int kv_calculate_dpm_settings(struct radeon_device *rdev); static void kv_enable_new_levels(struct radeon_device *rdev); static void kv_program_nbps_index_settings(struct radeon_device *rdev, struct radeon_ps *new_rps); +static int kv_set_enabled_level(struct radeon_device *rdev, u32 level); static int kv_set_enabled_levels(struct radeon_device *rdev); static int kv_force_dpm_highest(struct radeon_device *rdev); static int kv_force_dpm_lowest(struct radeon_device *rdev); @@ -519,7 +520,7 @@ static int kv_set_dpm_boot_state(struct radeon_device *rdev) static void kv_program_vc(struct radeon_device *rdev) { - WREG32_SMC(CG_FTV_0, 0x3FFFC000); + WREG32_SMC(CG_FTV_0, 0x3FFFC100); } static void kv_clear_vc(struct radeon_device *rdev) @@ -638,7 +639,10 @@ static int kv_force_lowest_valid(struct radeon_device *rdev) static int kv_unforce_levels(struct radeon_device *rdev) { - return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel); + if (rdev->family == CHIP_KABINI) + return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel); + else + return kv_set_enabled_levels(rdev); } static int kv_update_sclk_t(struct radeon_device *rdev) @@ -667,9 +671,8 @@ static int kv_program_bootup_state(struct radeon_device *rdev) &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; if (table && table->count) { - for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) { - if ((table->entries[i].clk == pi->boot_pl.sclk) || - (i == 0)) + for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { + if (table->entries[i].clk == pi->boot_pl.sclk) break; } @@ -682,9 +685,8 @@ static int kv_program_bootup_state(struct radeon_device *rdev) if (table->num_max_dpm_entries == 0) return -EINVAL; - for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) { - if ((table->entries[i].sclk_frequency == pi->boot_pl.sclk) || - (i == 0)) + for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { + if (table->entries[i].sclk_frequency == pi->boot_pl.sclk) break; } @@ -1078,6 +1080,13 @@ static int kv_enable_ulv(struct radeon_device *rdev, bool enable) PPSMC_MSG_EnableULV : PPSMC_MSG_DisableULV); } +static void kv_reset_acp_boot_level(struct radeon_device *rdev) +{ + struct kv_power_info *pi = kv_get_pi(rdev); + + pi->acp_boot_level = 0xff; +} + static void kv_update_current_ps(struct radeon_device *rdev, struct radeon_ps *rps) { @@ -1100,6 +1109,18 @@ static void kv_update_requested_ps(struct radeon_device *rdev, pi->requested_rps.ps_priv = &pi->requested_ps; } +void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable) +{ + struct kv_power_info *pi = kv_get_pi(rdev); + int ret; + + if (pi->bapm_enable) { + ret = kv_smc_bapm_enable(rdev, enable); + if (ret) + DRM_ERROR("kv_smc_bapm_enable failed\n"); + } +} + int kv_dpm_enable(struct radeon_device *rdev) { struct kv_power_info *pi = kv_get_pi(rdev); @@ -1192,6 +1213,8 @@ int kv_dpm_enable(struct radeon_device *rdev) return ret; } + kv_reset_acp_boot_level(rdev); + if (rdev->irq.installed && r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { ret = kv_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); @@ -1203,6 +1226,12 @@ int kv_dpm_enable(struct radeon_device *rdev) radeon_irq_set(rdev); } + ret = kv_smc_bapm_enable(rdev, false); + if (ret) { + DRM_ERROR("kv_smc_bapm_enable failed\n"); + return ret; + } + /* powerdown unused blocks for now */ kv_dpm_powergate_acp(rdev, true); kv_dpm_powergate_samu(rdev, true); @@ -1226,6 +1255,8 @@ void kv_dpm_disable(struct radeon_device *rdev) RADEON_CG_BLOCK_BIF | RADEON_CG_BLOCK_HDP), false); + kv_smc_bapm_enable(rdev, false); + /* powerup blocks */ kv_dpm_powergate_acp(rdev, false); kv_dpm_powergate_samu(rdev, false); @@ -1450,6 +1481,39 @@ static int kv_update_samu_dpm(struct radeon_device *rdev, bool gate) return kv_enable_samu_dpm(rdev, !gate); } +static u8 kv_get_acp_boot_level(struct radeon_device *rdev) +{ + u8 i; + struct radeon_clock_voltage_dependency_table *table = + &rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; + + for (i = 0; i < table->count; i++) { + if (table->entries[i].clk >= 0) /* XXX */ + break; + } + + if (i >= table->count) + i = table->count - 1; + + return i; +} + +static void kv_update_acp_boot_level(struct radeon_device *rdev) +{ + struct kv_power_info *pi = kv_get_pi(rdev); + u8 acp_boot_level; + + if (!pi->caps_stable_p_state) { + acp_boot_level = kv_get_acp_boot_level(rdev); + if (acp_boot_level != pi->acp_boot_level) { + pi->acp_boot_level = acp_boot_level; + kv_send_msg_to_smc_with_parameter(rdev, + PPSMC_MSG_ACPDPM_SetEnabledMask, + (1 << pi->acp_boot_level)); + } + } +} + static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate) { struct kv_power_info *pi = kv_get_pi(rdev); @@ -1461,7 +1525,7 @@ static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate) if (pi->caps_stable_p_state) pi->acp_boot_level = table->count - 1; else - pi->acp_boot_level = 0; + pi->acp_boot_level = kv_get_acp_boot_level(rdev); ret = kv_copy_bytes_to_smc(rdev, pi->dpm_table_start + @@ -1588,13 +1652,11 @@ static void kv_set_valid_clock_range(struct radeon_device *rdev, } } - for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) { - if ((table->entries[i].clk <= new_ps->levels[new_ps->num_levels -1].sclk) || - (i == 0)) { - pi->highest_valid = i; + for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { + if (table->entries[i].clk <= new_ps->levels[new_ps->num_levels - 1].sclk) break; - } } + pi->highest_valid = i; if (pi->lowest_valid > pi->highest_valid) { if ((new_ps->levels[0].sclk - table->entries[pi->highest_valid].clk) > @@ -1615,14 +1677,12 @@ static void kv_set_valid_clock_range(struct radeon_device *rdev, } } - for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) { + for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { if (table->entries[i].sclk_frequency <= - new_ps->levels[new_ps->num_levels - 1].sclk || - i == 0) { - pi->highest_valid = i; + new_ps->levels[new_ps->num_levels - 1].sclk) break; - } } + pi->highest_valid = i; if (pi->lowest_valid > pi->highest_valid) { if ((new_ps->levels[0].sclk - @@ -1724,6 +1784,14 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) RADEON_CG_BLOCK_BIF | RADEON_CG_BLOCK_HDP), false); + if (pi->bapm_enable) { + ret = kv_smc_bapm_enable(rdev, rdev->pm.dpm.ac_power); + if (ret) { + DRM_ERROR("kv_smc_bapm_enable failed\n"); + return ret; + } + } + if (rdev->family == CHIP_KABINI) { if (pi->enable_dpm) { kv_set_valid_clock_range(rdev, new_ps); @@ -1775,6 +1843,7 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) return ret; } #endif + kv_update_acp_boot_level(rdev); kv_update_sclk_t(rdev); kv_enable_nb_dpm(rdev); } @@ -1785,7 +1854,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) RADEON_CG_BLOCK_BIF | RADEON_CG_BLOCK_HDP), true); - rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO; return 0; } @@ -1806,12 +1874,23 @@ void kv_dpm_setup_asic(struct radeon_device *rdev) void kv_dpm_reset_asic(struct radeon_device *rdev) { - kv_force_lowest_valid(rdev); - kv_init_graphics_levels(rdev); - kv_program_bootup_state(rdev); - kv_upload_dpm_settings(rdev); - kv_force_lowest_valid(rdev); - kv_unforce_levels(rdev); + struct kv_power_info *pi = kv_get_pi(rdev); + + if (rdev->family == CHIP_KABINI) { + kv_force_lowest_valid(rdev); + kv_init_graphics_levels(rdev); + kv_program_bootup_state(rdev); + kv_upload_dpm_settings(rdev); + kv_force_lowest_valid(rdev); + kv_unforce_levels(rdev); + } else { + kv_init_graphics_levels(rdev); + kv_program_bootup_state(rdev); + kv_freeze_sclk_dpm(rdev, true); + kv_upload_dpm_settings(rdev); + kv_freeze_sclk_dpm(rdev, false); + kv_set_enabled_level(rdev, pi->graphics_boot_level); + } } //XXX use sumo_dpm_display_configuration_changed @@ -1871,12 +1950,15 @@ static int kv_force_dpm_highest(struct radeon_device *rdev) if (ret) return ret; - for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i >= 0; i--) { + for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i > 0; i--) { if (enable_mask & (1 << i)) break; } - return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); + if (rdev->family == CHIP_KABINI) + return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); + else + return kv_set_enabled_level(rdev, i); } static int kv_force_dpm_lowest(struct radeon_device *rdev) @@ -1893,7 +1975,10 @@ static int kv_force_dpm_lowest(struct radeon_device *rdev) break; } - return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); + if (rdev->family == CHIP_KABINI) + return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); + else + return kv_set_enabled_level(rdev, i); } static u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev, @@ -1911,9 +1996,9 @@ static u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev, if (!pi->caps_sclk_ds) return 0; - for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i <= 0; i--) { + for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i > 0; i--) { temp = sclk / sumo_get_sleep_divider_from_id(i); - if ((temp >= min) || (i == 0)) + if (temp >= min) break; } @@ -2039,12 +2124,12 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev, ps->dpmx_nb_ps_lo = 0x1; ps->dpmx_nb_ps_hi = 0x0; } else { - ps->dpm0_pg_nb_ps_lo = 0x1; + ps->dpm0_pg_nb_ps_lo = 0x3; ps->dpm0_pg_nb_ps_hi = 0x0; - ps->dpmx_nb_ps_lo = 0x2; - ps->dpmx_nb_ps_hi = 0x1; + ps->dpmx_nb_ps_lo = 0x3; + ps->dpmx_nb_ps_hi = 0x0; - if (pi->sys_info.nb_dpm_enable && pi->battery_state) { + if (pi->sys_info.nb_dpm_enable) { force_high = (mclk >= pi->sys_info.nbp_memory_clock[3]) || pi->video_start || (rdev->pm.dpm.new_active_crtc_count >= 3) || pi->disable_nb_ps3_in_battery; @@ -2210,6 +2295,15 @@ static void kv_enable_new_levels(struct radeon_device *rdev) } } +static int kv_set_enabled_level(struct radeon_device *rdev, u32 level) +{ + u32 new_mask = (1 << level); + + return kv_send_msg_to_smc_with_parameter(rdev, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + new_mask); +} + static int kv_set_enabled_levels(struct radeon_device *rdev) { struct kv_power_info *pi = kv_get_pi(rdev); diff --git a/drivers/gpu/drm/radeon/kv_dpm.h b/drivers/gpu/drm/radeon/kv_dpm.h index 32bb079572d7..8cef7525d7a8 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.h +++ b/drivers/gpu/drm/radeon/kv_dpm.h @@ -192,6 +192,7 @@ int kv_send_msg_to_smc_with_parameter(struct radeon_device *rdev, int kv_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 *value, u32 limit); int kv_smc_dpm_enable(struct radeon_device *rdev, bool enable); +int kv_smc_bapm_enable(struct radeon_device *rdev, bool enable); int kv_copy_bytes_to_smc(struct radeon_device *rdev, u32 smc_start_address, const u8 *src, u32 byte_count, u32 limit); diff --git a/drivers/gpu/drm/radeon/kv_smc.c b/drivers/gpu/drm/radeon/kv_smc.c index 34a226d7e34a..0000b59a6d05 100644 --- a/drivers/gpu/drm/radeon/kv_smc.c +++ b/drivers/gpu/drm/radeon/kv_smc.c @@ -107,6 +107,14 @@ int kv_smc_dpm_enable(struct radeon_device *rdev, bool enable) return kv_notify_message_to_smu(rdev, PPSMC_MSG_DPM_Disable); } +int kv_smc_bapm_enable(struct radeon_device *rdev, bool enable) +{ + if (enable) + return kv_notify_message_to_smu(rdev, PPSMC_MSG_EnableBAPM); + else + return kv_notify_message_to_smu(rdev, PPSMC_MSG_DisableBAPM); +} + int kv_copy_bytes_to_smc(struct radeon_device *rdev, u32 smc_start_address, const u8 *src, u32 byte_count, u32 limit) diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c index f7b625c9e0e9..6c398a456d78 100644 --- a/drivers/gpu/drm/radeon/ni_dpm.c +++ b/drivers/gpu/drm/radeon/ni_dpm.c @@ -3865,12 +3865,6 @@ int ni_dpm_set_power_state(struct radeon_device *rdev) return ret; } - ret = ni_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO); - if (ret) { - DRM_ERROR("ni_dpm_force_performance_level failed\n"); - return ret; - } - return 0; } diff --git a/drivers/gpu/drm/radeon/ppsmc.h b/drivers/gpu/drm/radeon/ppsmc.h index 682842804bce..5670b8291285 100644 --- a/drivers/gpu/drm/radeon/ppsmc.h +++ b/drivers/gpu/drm/radeon/ppsmc.h @@ -163,6 +163,8 @@ typedef uint8_t PPSMC_Result; #define PPSMC_MSG_VCEPowerON ((uint32_t) 0x10f) #define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint32_t) 0x11d) #define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint32_t) 0x11e) +#define PPSMC_MSG_EnableBAPM ((uint32_t) 0x120) +#define PPSMC_MSG_DisableBAPM ((uint32_t) 0x121) #define PPSMC_MSG_UVD_DPM_Config ((uint32_t) 0x124) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 9fc61dd68bc0..24175717307b 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -2853,21 +2853,28 @@ static void r100_pll_errata_after_data(struct radeon_device *rdev) uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg) { + unsigned long flags; uint32_t data; + spin_lock_irqsave(&rdev->pll_idx_lock, flags); WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f); r100_pll_errata_after_index(rdev); data = RREG32(RADEON_CLOCK_CNTL_DATA); r100_pll_errata_after_data(rdev); + spin_unlock_irqrestore(&rdev->pll_idx_lock, flags); return data; } void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->pll_idx_lock, flags); WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN)); r100_pll_errata_after_index(rdev); WREG32(RADEON_CLOCK_CNTL_DATA, v); r100_pll_errata_after_data(rdev); + spin_unlock_irqrestore(&rdev->pll_idx_lock, flags); } static void r100_set_safe_registers(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 4e796ecf9ea4..6edf2b3a52b4 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -160,18 +160,25 @@ void r420_pipes_init(struct radeon_device *rdev) u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg) { + unsigned long flags; u32 r; + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg)); r = RREG32(R_0001FC_MC_IND_DATA); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); return r; } void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) | S_0001F8_MC_IND_WR_EN(1)); WREG32(R_0001FC_MC_IND_DATA, v); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); } static void r420_debugfs(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index ea4d3734e6d9..2a1b1876b431 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -119,6 +119,11 @@ u32 r600_get_xclk(struct radeon_device *rdev) return rdev->clock.spll.reference_freq; } +int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) +{ + return 0; +} + /* get temperature in millidegrees */ int rv6xx_get_temp(struct radeon_device *rdev) { @@ -1045,20 +1050,27 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev) uint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg) { + unsigned long flags; uint32_t r; + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg)); r = RREG32(R_0028FC_MC_DATA); WREG32(R_0028F8_MC_INDEX, ~C_0028F8_MC_IND_ADDR); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); return r; } void rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg) | S_0028F8_MC_IND_WR_EN(1)); WREG32(R_0028FC_MC_DATA, v); WREG32(R_0028F8_MC_INDEX, 0x7F); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); } static void r600_mc_program(struct radeon_device *rdev) @@ -2092,20 +2104,27 @@ static void r600_gpu_init(struct radeon_device *rdev) */ u32 r600_pciep_rreg(struct radeon_device *rdev, u32 reg) { + unsigned long flags; u32 r; + spin_lock_irqsave(&rdev->pciep_idx_lock, flags); WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); (void)RREG32(PCIE_PORT_INDEX); r = RREG32(PCIE_PORT_DATA); + spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags); return r; } void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->pciep_idx_lock, flags); WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); (void)RREG32(PCIE_PORT_INDEX); WREG32(PCIE_PORT_DATA, (v)); (void)RREG32(PCIE_PORT_DATA); + spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags); } /* diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index fa0de46fcc0d..e65f211a7be0 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -1219,30 +1219,20 @@ int r600_parse_extended_power_table(struct radeon_device *rdev) void r600_free_extended_power_table(struct radeon_device *rdev) { - if (rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries) - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries); - if (rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries) - kfree(rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk.entries); - if (rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries) - kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk.entries); - if (rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries) - kfree(rdev->pm.dpm.dyn_state.mvdd_dependency_on_mclk.entries); - if (rdev->pm.dpm.dyn_state.cac_leakage_table.entries) - kfree(rdev->pm.dpm.dyn_state.cac_leakage_table.entries); - if (rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) - kfree(rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries); - if (rdev->pm.dpm.dyn_state.ppm_table) - kfree(rdev->pm.dpm.dyn_state.ppm_table); - if (rdev->pm.dpm.dyn_state.cac_tdp_table) - kfree(rdev->pm.dpm.dyn_state.cac_tdp_table); - if (rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) - kfree(rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries); - if (rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) - kfree(rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries); - if (rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) - kfree(rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries); - if (rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) - kfree(rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries); + struct radeon_dpm_dynamic_state *dyn_state = &rdev->pm.dpm.dyn_state; + + kfree(dyn_state->vddc_dependency_on_sclk.entries); + kfree(dyn_state->vddci_dependency_on_mclk.entries); + kfree(dyn_state->vddc_dependency_on_mclk.entries); + kfree(dyn_state->mvdd_dependency_on_mclk.entries); + kfree(dyn_state->cac_leakage_table.entries); + kfree(dyn_state->phase_shedding_limits_table.entries); + kfree(dyn_state->ppm_table); + kfree(dyn_state->cac_tdp_table); + kfree(dyn_state->vce_clock_voltage_dependency_table.entries); + kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); + kfree(dyn_state->samu_clock_voltage_dependency_table.entries); + kfree(dyn_state->acp_clock_voltage_dependency_table.entries); } enum radeon_pcie_gen r600_get_pcie_gen_support(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 454f90a849e4..e673fe26ea84 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -1040,7 +1040,7 @@ # define HDMI0_AVI_INFO_CONT (1 << 1) # define HDMI0_AUDIO_INFO_SEND (1 << 4) # define HDMI0_AUDIO_INFO_CONT (1 << 5) -# define HDMI0_AUDIO_INFO_SOURCE (1 << 6) /* 0 - sound block; 1 - hmdi regs */ +# define HDMI0_AUDIO_INFO_SOURCE (1 << 6) /* 0 - sound block; 1 - hdmi regs */ # define HDMI0_AUDIO_INFO_UPDATE (1 << 7) # define HDMI0_MPEG_INFO_SEND (1 << 8) # define HDMI0_MPEG_INFO_CONT (1 << 9) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ff8b564ce2b2..a400ac1c4147 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -181,7 +181,7 @@ extern int radeon_aspm; #define RADEON_CG_SUPPORT_HDP_MGCG (1 << 16) /* PG flags */ -#define RADEON_PG_SUPPORT_GFX_CG (1 << 0) +#define RADEON_PG_SUPPORT_GFX_PG (1 << 0) #define RADEON_PG_SUPPORT_GFX_SMG (1 << 1) #define RADEON_PG_SUPPORT_GFX_DMG (1 << 2) #define RADEON_PG_SUPPORT_UVD (1 << 3) @@ -1778,6 +1778,7 @@ struct radeon_asic { int (*force_performance_level)(struct radeon_device *rdev, enum radeon_dpm_forced_level level); bool (*vblank_too_short)(struct radeon_device *rdev); void (*powergate_uvd)(struct radeon_device *rdev, bool gate); + void (*enable_bapm)(struct radeon_device *rdev, bool enable); } dpm; /* pageflipping */ struct { @@ -2110,6 +2111,28 @@ struct radeon_device { resource_size_t rmmio_size; /* protects concurrent MM_INDEX/DATA based register access */ spinlock_t mmio_idx_lock; + /* protects concurrent SMC based register access */ + spinlock_t smc_idx_lock; + /* protects concurrent PLL register access */ + spinlock_t pll_idx_lock; + /* protects concurrent MC register access */ + spinlock_t mc_idx_lock; + /* protects concurrent PCIE register access */ + spinlock_t pcie_idx_lock; + /* protects concurrent PCIE_PORT register access */ + spinlock_t pciep_idx_lock; + /* protects concurrent PIF register access */ + spinlock_t pif_idx_lock; + /* protects concurrent CG register access */ + spinlock_t cg_idx_lock; + /* protects concurrent UVD register access */ + spinlock_t uvd_idx_lock; + /* protects concurrent RCU register access */ + spinlock_t rcu_idx_lock; + /* protects concurrent DIDT register access */ + spinlock_t didt_idx_lock; + /* protects concurrent ENDPOINT (audio) register access */ + spinlock_t end_idx_lock; void __iomem *rmmio; radeon_rreg_t mc_rreg; radeon_wreg_t mc_wreg; @@ -2277,123 +2300,179 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v); */ static inline uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg) { + unsigned long flags; uint32_t r; + spin_lock_irqsave(&rdev->pcie_idx_lock, flags); WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); r = RREG32(RADEON_PCIE_DATA); + spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags); return r; } static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->pcie_idx_lock, flags); WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask)); WREG32(RADEON_PCIE_DATA, (v)); + spin_unlock_irqrestore(&rdev->pcie_idx_lock, flags); } static inline u32 tn_smc_rreg(struct radeon_device *rdev, u32 reg) { + unsigned long flags; u32 r; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); WREG32(TN_SMC_IND_INDEX_0, (reg)); r = RREG32(TN_SMC_IND_DATA_0); + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); return r; } static inline void tn_smc_wreg(struct radeon_device *rdev, u32 reg, u32 v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->smc_idx_lock, flags); WREG32(TN_SMC_IND_INDEX_0, (reg)); WREG32(TN_SMC_IND_DATA_0, (v)); + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); } static inline u32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg) { + unsigned long flags; u32 r; + spin_lock_irqsave(&rdev->rcu_idx_lock, flags); WREG32(R600_RCU_INDEX, ((reg) & 0x1fff)); r = RREG32(R600_RCU_DATA); + spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags); return r; } static inline void r600_rcu_wreg(struct radeon_device *rdev, u32 reg, u32 v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->rcu_idx_lock, flags); WREG32(R600_RCU_INDEX, ((reg) & 0x1fff)); WREG32(R600_RCU_DATA, (v)); + spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags); } static inline u32 eg_cg_rreg(struct radeon_device *rdev, u32 reg) { + unsigned long flags; u32 r; + spin_lock_irqsave(&rdev->cg_idx_lock, flags); WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff)); r = RREG32(EVERGREEN_CG_IND_DATA); + spin_unlock_irqrestore(&rdev->cg_idx_lock, flags); return r; } static inline void eg_cg_wreg(struct radeon_device *rdev, u32 reg, u32 v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->cg_idx_lock, flags); WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff)); WREG32(EVERGREEN_CG_IND_DATA, (v)); + spin_unlock_irqrestore(&rdev->cg_idx_lock, flags); } static inline u32 eg_pif_phy0_rreg(struct radeon_device *rdev, u32 reg) { + unsigned long flags; u32 r; + spin_lock_irqsave(&rdev->pif_idx_lock, flags); WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff)); r = RREG32(EVERGREEN_PIF_PHY0_DATA); + spin_unlock_irqrestore(&rdev->pif_idx_lock, flags); return r; } static inline void eg_pif_phy0_wreg(struct radeon_device *rdev, u32 reg, u32 v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->pif_idx_lock, flags); WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff)); WREG32(EVERGREEN_PIF_PHY0_DATA, (v)); + spin_unlock_irqrestore(&rdev->pif_idx_lock, flags); } static inline u32 eg_pif_phy1_rreg(struct radeon_device *rdev, u32 reg) { + unsigned long flags; u32 r; + spin_lock_irqsave(&rdev->pif_idx_lock, flags); WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff)); r = RREG32(EVERGREEN_PIF_PHY1_DATA); + spin_unlock_irqrestore(&rdev->pif_idx_lock, flags); return r; } static inline void eg_pif_phy1_wreg(struct radeon_device *rdev, u32 reg, u32 v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->pif_idx_lock, flags); WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff)); WREG32(EVERGREEN_PIF_PHY1_DATA, (v)); + spin_unlock_irqrestore(&rdev->pif_idx_lock, flags); } static inline u32 r600_uvd_ctx_rreg(struct radeon_device *rdev, u32 reg) { + unsigned long flags; u32 r; + spin_lock_irqsave(&rdev->uvd_idx_lock, flags); WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff)); r = RREG32(R600_UVD_CTX_DATA); + spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags); return r; } static inline void r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->uvd_idx_lock, flags); WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff)); WREG32(R600_UVD_CTX_DATA, (v)); + spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags); } static inline u32 cik_didt_rreg(struct radeon_device *rdev, u32 reg) { + unsigned long flags; u32 r; + spin_lock_irqsave(&rdev->didt_idx_lock, flags); WREG32(CIK_DIDT_IND_INDEX, (reg)); r = RREG32(CIK_DIDT_IND_DATA); + spin_unlock_irqrestore(&rdev->didt_idx_lock, flags); return r; } static inline void cik_didt_wreg(struct radeon_device *rdev, u32 reg, u32 v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->didt_idx_lock, flags); WREG32(CIK_DIDT_IND_INDEX, (reg)); WREG32(CIK_DIDT_IND_DATA, (v)); + spin_unlock_irqrestore(&rdev->didt_idx_lock, flags); } void r100_pll_errata_after_index(struct radeon_device *rdev); @@ -2569,6 +2648,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_dpm_force_performance_level(rdev, l) rdev->asic->dpm.force_performance_level((rdev), (l)) #define radeon_dpm_vblank_too_short(rdev) rdev->asic->dpm.vblank_too_short((rdev)) #define radeon_dpm_powergate_uvd(rdev, g) rdev->asic->dpm.powergate_uvd((rdev), (g)) +#define radeon_dpm_enable_bapm(rdev, e) rdev->asic->dpm.enable_bapm((rdev), (e)) /* Common functions */ /* AGP */ diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 630853b96841..5003385a7512 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -1037,6 +1037,7 @@ static struct radeon_asic rv6xx_asic = { .set_pcie_lanes = &r600_set_pcie_lanes, .set_clock_gating = NULL, .get_temperature = &rv6xx_get_temp, + .set_uvd_clocks = &r600_set_uvd_clocks, }, .dpm = { .init = &rv6xx_dpm_init, @@ -1126,6 +1127,7 @@ static struct radeon_asic rs780_asic = { .set_pcie_lanes = NULL, .set_clock_gating = NULL, .get_temperature = &rv6xx_get_temp, + .set_uvd_clocks = &r600_set_uvd_clocks, }, .dpm = { .init = &rs780_dpm_init, @@ -1141,6 +1143,7 @@ static struct radeon_asic rs780_asic = { .get_mclk = &rs780_dpm_get_mclk, .print_power_state = &rs780_dpm_print_power_state, .debugfs_print_current_performance_level = &rs780_dpm_debugfs_print_current_performance_level, + .force_performance_level = &rs780_dpm_force_performance_level, }, .pflip = { .pre_page_flip = &rs600_pre_page_flip, @@ -1791,6 +1794,7 @@ static struct radeon_asic trinity_asic = { .print_power_state = &trinity_dpm_print_power_state, .debugfs_print_current_performance_level = &trinity_dpm_debugfs_print_current_performance_level, .force_performance_level = &trinity_dpm_force_performance_level, + .enable_bapm = &trinity_dpm_enable_bapm, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip, @@ -2166,6 +2170,7 @@ static struct radeon_asic kv_asic = { .debugfs_print_current_performance_level = &kv_dpm_debugfs_print_current_performance_level, .force_performance_level = &kv_dpm_force_performance_level, .powergate_uvd = &kv_dpm_powergate_uvd, + .enable_bapm = &kv_dpm_enable_bapm, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip, @@ -2390,7 +2395,7 @@ int radeon_asic_init(struct radeon_device *rdev) RADEON_CG_SUPPORT_HDP_LS | RADEON_CG_SUPPORT_HDP_MGCG; rdev->pg_flags = 0 | - /*RADEON_PG_SUPPORT_GFX_CG | */ + /*RADEON_PG_SUPPORT_GFX_PG | */ RADEON_PG_SUPPORT_SDMA; break; case CHIP_OLAND: @@ -2479,7 +2484,7 @@ int radeon_asic_init(struct radeon_device *rdev) RADEON_CG_SUPPORT_HDP_LS | RADEON_CG_SUPPORT_HDP_MGCG; rdev->pg_flags = 0; - /*RADEON_PG_SUPPORT_GFX_CG | + /*RADEON_PG_SUPPORT_GFX_PG | RADEON_PG_SUPPORT_GFX_SMG | RADEON_PG_SUPPORT_GFX_DMG | RADEON_PG_SUPPORT_UVD | @@ -2507,7 +2512,7 @@ int radeon_asic_init(struct radeon_device *rdev) RADEON_CG_SUPPORT_HDP_LS | RADEON_CG_SUPPORT_HDP_MGCG; rdev->pg_flags = 0; - /*RADEON_PG_SUPPORT_GFX_CG | + /*RADEON_PG_SUPPORT_GFX_PG | RADEON_PG_SUPPORT_GFX_SMG | RADEON_PG_SUPPORT_UVD | RADEON_PG_SUPPORT_VCE | diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 818bbe6b884b..70c29d5e080d 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -389,6 +389,7 @@ int r600_mc_wait_for_idle(struct radeon_device *rdev); u32 r600_get_xclk(struct radeon_device *rdev); uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev); int rv6xx_get_temp(struct radeon_device *rdev); +int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); int r600_dpm_pre_set_power_state(struct radeon_device *rdev); void r600_dpm_post_set_power_state(struct radeon_device *rdev); /* r600 dma */ @@ -428,6 +429,8 @@ void rs780_dpm_print_power_state(struct radeon_device *rdev, struct radeon_ps *ps); void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, struct seq_file *m); +int rs780_dpm_force_performance_level(struct radeon_device *rdev, + enum radeon_dpm_forced_level level); /* * rv770,rv730,rv710,rv740 @@ -625,6 +628,7 @@ void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *r struct seq_file *m); int trinity_dpm_force_performance_level(struct radeon_device *rdev, enum radeon_dpm_forced_level level); +void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable); /* DCE6 - SI */ void dce6_bandwidth_update(struct radeon_device *rdev); @@ -781,6 +785,7 @@ void kv_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, int kv_dpm_force_performance_level(struct radeon_device *rdev, enum radeon_dpm_forced_level level); void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); +void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable); /* uvd v1.0 */ uint32_t uvd_v1_0_get_rptr(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 2399f25ec037..79159b5da05b 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -396,6 +396,21 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct } } + if (property == rdev->mode_info.audio_property) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + /* need to find digital encoder on connector */ + encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); + if (!encoder) + return 0; + + radeon_encoder = to_radeon_encoder(encoder); + + if (radeon_connector->audio != val) { + radeon_connector->audio = val; + radeon_property_change_mode(&radeon_encoder->base); + } + } + if (property == rdev->mode_info.underscan_property) { /* need to find digital encoder on connector */ encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS); @@ -1420,7 +1435,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force) if (radeon_dp_getdpcd(radeon_connector)) ret = connector_status_connected; } else { - /* try non-aux ddc (DP to DVI/HMDI/etc. adapter) */ + /* try non-aux ddc (DP to DVI/HDMI/etc. adapter) */ if (radeon_ddc_probe(radeon_connector, false)) ret = connector_status_connected; } @@ -1489,6 +1504,24 @@ static const struct drm_connector_funcs radeon_dp_connector_funcs = { .force = radeon_dvi_force, }; +static const struct drm_connector_funcs radeon_edp_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = radeon_dp_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .set_property = radeon_lvds_set_property, + .destroy = radeon_dp_connector_destroy, + .force = radeon_dvi_force, +}; + +static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = radeon_dp_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .set_property = radeon_lvds_set_property, + .destroy = radeon_dp_connector_destroy, + .force = radeon_dvi_force, +}; + void radeon_add_atom_connector(struct drm_device *dev, uint32_t connector_id, @@ -1580,8 +1613,6 @@ radeon_add_atom_connector(struct drm_device *dev, goto failed; radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; - drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (i2c_bus->valid) { /* add DP i2c bus */ if (connector_type == DRM_MODE_CONNECTOR_eDP) @@ -1598,6 +1629,10 @@ radeon_add_atom_connector(struct drm_device *dev, case DRM_MODE_CONNECTOR_VGA: case DRM_MODE_CONNECTOR_DVIA: default: + drm_connector_init(dev, &radeon_connector->base, + &radeon_dp_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, + &radeon_dp_connector_helper_funcs); connector->interlace_allowed = true; connector->doublescan_allowed = true; radeon_connector->dac_load_detect = true; @@ -1610,6 +1645,10 @@ radeon_add_atom_connector(struct drm_device *dev, case DRM_MODE_CONNECTOR_HDMIA: case DRM_MODE_CONNECTOR_HDMIB: case DRM_MODE_CONNECTOR_DisplayPort: + drm_connector_init(dev, &radeon_connector->base, + &radeon_dp_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, + &radeon_dp_connector_helper_funcs); drm_object_attach_property(&radeon_connector->base.base, rdev->mode_info.underscan_property, UNDERSCAN_OFF); @@ -1619,6 +1658,9 @@ radeon_add_atom_connector(struct drm_device *dev, drm_object_attach_property(&radeon_connector->base.base, rdev->mode_info.underscan_vborder_property, 0); + drm_object_attach_property(&radeon_connector->base.base, + rdev->mode_info.audio_property, + RADEON_AUDIO_DISABLE); subpixel_order = SubPixelHorizontalRGB; connector->interlace_allowed = true; if (connector_type == DRM_MODE_CONNECTOR_HDMIB) @@ -1634,6 +1676,10 @@ radeon_add_atom_connector(struct drm_device *dev, break; case DRM_MODE_CONNECTOR_LVDS: case DRM_MODE_CONNECTOR_eDP: + drm_connector_init(dev, &radeon_connector->base, + &radeon_lvds_bridge_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, + &radeon_dp_connector_helper_funcs); drm_object_attach_property(&radeon_connector->base.base, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); @@ -1708,6 +1754,11 @@ radeon_add_atom_connector(struct drm_device *dev, rdev->mode_info.underscan_vborder_property, 0); } + if (ASIC_IS_DCE2(rdev)) { + drm_object_attach_property(&radeon_connector->base.base, + rdev->mode_info.audio_property, + RADEON_AUDIO_DISABLE); + } if (connector_type == DRM_MODE_CONNECTOR_DVII) { radeon_connector->dac_load_detect = true; drm_object_attach_property(&radeon_connector->base.base, @@ -1748,6 +1799,11 @@ radeon_add_atom_connector(struct drm_device *dev, rdev->mode_info.underscan_vborder_property, 0); } + if (ASIC_IS_DCE2(rdev)) { + drm_object_attach_property(&radeon_connector->base.base, + rdev->mode_info.audio_property, + RADEON_AUDIO_DISABLE); + } subpixel_order = SubPixelHorizontalRGB; connector->interlace_allowed = true; if (connector_type == DRM_MODE_CONNECTOR_HDMIB) @@ -1787,6 +1843,11 @@ radeon_add_atom_connector(struct drm_device *dev, rdev->mode_info.underscan_vborder_property, 0); } + if (ASIC_IS_DCE2(rdev)) { + drm_object_attach_property(&radeon_connector->base.base, + rdev->mode_info.audio_property, + RADEON_AUDIO_DISABLE); + } connector->interlace_allowed = true; /* in theory with a DP to VGA converter... */ connector->doublescan_allowed = false; @@ -1797,7 +1858,7 @@ radeon_add_atom_connector(struct drm_device *dev, goto failed; radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; - drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); + drm_connector_init(dev, &radeon_connector->base, &radeon_edp_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (i2c_bus->valid) { /* add DP i2c bus */ diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index a56084410372..ac6ece61a476 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -28,6 +28,7 @@ #include <drm/radeon_drm.h> #include "radeon_reg.h" #include "radeon.h" +#include "radeon_trace.h" static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) { @@ -80,9 +81,11 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) p->relocs[i].lobj.bo = p->relocs[i].robj; p->relocs[i].lobj.written = !!r->write_domain; - /* the first reloc of an UVD job is the - msg and that must be in VRAM */ - if (p->ring == R600_RING_TYPE_UVD_INDEX && i == 0) { + /* the first reloc of an UVD job is the msg and that must be in + VRAM, also but everything into VRAM on AGP cards to avoid + image corruptions */ + if (p->ring == R600_RING_TYPE_UVD_INDEX && + (i == 0 || p->rdev->flags & RADEON_IS_AGP)) { /* TODO: is this still needed for NI+ ? */ p->relocs[i].lobj.domain = RADEON_GEM_DOMAIN_VRAM; @@ -559,6 +562,8 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) return r; } + trace_radeon_cs(&parser); + r = radeon_cs_ib_chunk(rdev, &parser); if (r) { goto out; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 16cb8792b1e6..e29faa73b574 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1249,6 +1249,17 @@ int radeon_device_init(struct radeon_device *rdev, /* Registers mapping */ /* TODO: block userspace mapping of io register */ spin_lock_init(&rdev->mmio_idx_lock); + spin_lock_init(&rdev->smc_idx_lock); + spin_lock_init(&rdev->pll_idx_lock); + spin_lock_init(&rdev->mc_idx_lock); + spin_lock_init(&rdev->pcie_idx_lock); + spin_lock_init(&rdev->pciep_idx_lock); + spin_lock_init(&rdev->pif_idx_lock); + spin_lock_init(&rdev->cg_idx_lock); + spin_lock_init(&rdev->uvd_idx_lock); + spin_lock_init(&rdev->rcu_idx_lock); + spin_lock_init(&rdev->didt_idx_lock); + spin_lock_init(&rdev->end_idx_lock); if (rdev->family >= CHIP_BONAIRE) { rdev->rmmio_base = pci_resource_start(rdev->pdev, 5); rdev->rmmio_size = pci_resource_len(rdev->pdev, 5); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index b055bddaa94c..0d1aa050d41d 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1172,6 +1172,12 @@ static struct drm_prop_enum_list radeon_underscan_enum_list[] = { UNDERSCAN_AUTO, "auto" }, }; +static struct drm_prop_enum_list radeon_audio_enum_list[] = +{ { RADEON_AUDIO_DISABLE, "off" }, + { RADEON_AUDIO_ENABLE, "on" }, + { RADEON_AUDIO_AUTO, "auto" }, +}; + static int radeon_modeset_create_props(struct radeon_device *rdev) { int sz; @@ -1222,6 +1228,12 @@ static int radeon_modeset_create_props(struct radeon_device *rdev) if (!rdev->mode_info.underscan_vborder_property) return -ENOMEM; + sz = ARRAY_SIZE(radeon_audio_enum_list); + rdev->mode_info.audio_property = + drm_property_create_enum(rdev->ddev, 0, + "audio", + radeon_audio_enum_list, sz); + return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index cb4445f55a96..cdd12dcd988b 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -153,7 +153,7 @@ int radeon_benchmarking = 0; int radeon_testing = 0; int radeon_connector_table = 0; int radeon_tv = 1; -int radeon_audio = 0; +int radeon_audio = 1; int radeon_disp_priority = 0; int radeon_hw_i2c = 0; int radeon_pcie_gen2 = -1; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index d908d8d68f6b..ef63d3f00b2f 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -247,6 +247,8 @@ struct radeon_mode_info { struct drm_property *underscan_property; struct drm_property *underscan_hborder_property; struct drm_property *underscan_vborder_property; + /* audio */ + struct drm_property *audio_property; /* hardcoded DFP edid from BIOS */ struct edid *bios_hardcoded_edid; int bios_hardcoded_edid_size; @@ -471,6 +473,12 @@ struct radeon_router { u8 cd_mux_state; }; +enum radeon_connector_audio { + RADEON_AUDIO_DISABLE = 0, + RADEON_AUDIO_ENABLE = 1, + RADEON_AUDIO_AUTO = 2 +}; + struct radeon_connector { struct drm_connector base; uint32_t connector_id; @@ -489,6 +497,7 @@ struct radeon_connector { struct radeon_hpd hpd; struct radeon_router router; struct radeon_i2c_chan *router_bus; + enum radeon_connector_audio audio; }; struct radeon_framebuffer { diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index d7555369a3e5..87e1d69e8fdb 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -67,7 +67,16 @@ int radeon_pm_get_type_index(struct radeon_device *rdev, void radeon_pm_acpi_event_handler(struct radeon_device *rdev) { - if (rdev->pm.pm_method == PM_METHOD_PROFILE) { + if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) { + mutex_lock(&rdev->pm.mutex); + if (power_supply_is_system_supplied() > 0) + rdev->pm.dpm.ac_power = true; + else + rdev->pm.dpm.ac_power = false; + if (rdev->asic->dpm.enable_bapm) + radeon_dpm_enable_bapm(rdev, rdev->pm.dpm.ac_power); + mutex_unlock(&rdev->pm.mutex); + } else if (rdev->pm.pm_method == PM_METHOD_PROFILE) { if (rdev->pm.profile == PM_PROFILE_AUTO) { mutex_lock(&rdev->pm.mutex); radeon_pm_update_profile(rdev); @@ -333,7 +342,7 @@ static ssize_t radeon_get_pm_profile(struct device *dev, struct device_attribute *attr, char *buf) { - struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; int cp = rdev->pm.profile; @@ -349,7 +358,7 @@ static ssize_t radeon_set_pm_profile(struct device *dev, const char *buf, size_t count) { - struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; mutex_lock(&rdev->pm.mutex); @@ -383,7 +392,7 @@ static ssize_t radeon_get_pm_method(struct device *dev, struct device_attribute *attr, char *buf) { - struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; int pm = rdev->pm.pm_method; @@ -397,7 +406,7 @@ static ssize_t radeon_set_pm_method(struct device *dev, const char *buf, size_t count) { - struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; /* we don't support the legacy modes with dpm */ @@ -433,7 +442,7 @@ static ssize_t radeon_get_dpm_state(struct device *dev, struct device_attribute *attr, char *buf) { - struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; enum radeon_pm_state_type pm = rdev->pm.dpm.user_state; @@ -447,7 +456,7 @@ static ssize_t radeon_set_dpm_state(struct device *dev, const char *buf, size_t count) { - struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; mutex_lock(&rdev->pm.mutex); @@ -472,7 +481,7 @@ static ssize_t radeon_get_dpm_forced_performance_level(struct device *dev, struct device_attribute *attr, char *buf) { - struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level; @@ -486,7 +495,7 @@ static ssize_t radeon_set_dpm_forced_performance_level(struct device *dev, const char *buf, size_t count) { - struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; enum radeon_dpm_forced_level level; int ret = 0; @@ -524,7 +533,7 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev, struct device_attribute *attr, char *buf) { - struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); + struct drm_device *ddev = dev_get_drvdata(dev); struct radeon_device *rdev = ddev->dev_private; int temp; @@ -536,6 +545,23 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", temp); } +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; + int hyst = to_sensor_dev_attr(attr)->index; + int temp; + + if (hyst) + temp = rdev->pm.dpm.thermal.min_temp; + else + temp = rdev->pm.dpm.thermal.max_temp; + + return snprintf(buf, PAGE_SIZE, "%d\n", temp); +} + static ssize_t radeon_hwmon_show_name(struct device *dev, struct device_attribute *attr, char *buf) @@ -544,16 +570,37 @@ static ssize_t radeon_hwmon_show_name(struct device *dev, } static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 1); static SENSOR_DEVICE_ATTR(name, S_IRUGO, radeon_hwmon_show_name, NULL, 0); static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, &sensor_dev_attr_name.dev_attr.attr, NULL }; +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; + + /* Skip limit attributes if DPM is not enabled */ + if (rdev->pm.pm_method != PM_METHOD_DPM && + (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || + attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr)) + return 0; + + return attr->mode; +} + static const struct attribute_group hwmon_attrgroup = { .attrs = hwmon_attributes, + .is_visible = hwmon_attributes_visible, }; static int radeon_hwmon_init(struct radeon_device *rdev) @@ -870,10 +917,13 @@ static void radeon_dpm_change_power_state_locked(struct radeon_device *rdev) radeon_dpm_post_set_power_state(rdev); - /* force low perf level for thermal */ - if (rdev->pm.dpm.thermal_active && - rdev->asic->dpm.force_performance_level) { - radeon_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_LOW); + if (rdev->asic->dpm.force_performance_level) { + if (rdev->pm.dpm.thermal_active) + /* force low perf level for thermal */ + radeon_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_LOW); + else + /* otherwise, enable auto */ + radeon_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO); } done: @@ -1102,9 +1152,10 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev) { int ret; - /* default to performance state */ + /* default to balanced state */ rdev->pm.dpm.state = POWER_STATE_TYPE_BALANCED; rdev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED; + rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO; rdev->pm.default_sclk = rdev->clock.default_sclk; rdev->pm.default_mclk = rdev->clock.default_mclk; rdev->pm.current_sclk = rdev->clock.default_sclk; diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h index eafd8160a155..f7e367815964 100644 --- a/drivers/gpu/drm/radeon/radeon_trace.h +++ b/drivers/gpu/drm/radeon/radeon_trace.h @@ -27,6 +27,26 @@ TRACE_EVENT(radeon_bo_create, TP_printk("bo=%p, pages=%u", __entry->bo, __entry->pages) ); +TRACE_EVENT(radeon_cs, + TP_PROTO(struct radeon_cs_parser *p), + TP_ARGS(p), + TP_STRUCT__entry( + __field(u32, ring) + __field(u32, dw) + __field(u32, fences) + ), + + TP_fast_assign( + __entry->ring = p->ring; + __entry->dw = p->chunks[p->chunk_ib_idx].length_dw; + __entry->fences = radeon_fence_count_emitted( + p->rdev, p->ring); + ), + TP_printk("ring=%u, dw=%u, fences=%u", + __entry->ring, __entry->dw, + __entry->fences) +); + DECLARE_EVENT_CLASS(radeon_fence_request, TP_PROTO(struct drm_device *dev, u32 seqno), @@ -53,13 +73,6 @@ DEFINE_EVENT(radeon_fence_request, radeon_fence_emit, TP_ARGS(dev, seqno) ); -DEFINE_EVENT(radeon_fence_request, radeon_fence_retire, - - TP_PROTO(struct drm_device *dev, u32 seqno), - - TP_ARGS(dev, seqno) -); - DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_begin, TP_PROTO(struct drm_device *dev, u32 seqno), diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index b8074a8ec75a..9566b5940a5a 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -274,19 +274,26 @@ static void rs400_mc_init(struct radeon_device *rdev) uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg) { + unsigned long flags; uint32_t r; + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(RS480_NB_MC_INDEX, reg & 0xff); r = RREG32(RS480_NB_MC_DATA); WREG32(RS480_NB_MC_INDEX, 0xff); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); return r; } void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(RS480_NB_MC_INDEX, ((reg) & 0xff) | RS480_NB_MC_IND_WR_EN); WREG32(RS480_NB_MC_DATA, (v)); WREG32(RS480_NB_MC_INDEX, 0xff); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); } #if defined(CONFIG_DEBUG_FS) diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 670b555d2ca2..6acba8017b9a 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -847,16 +847,26 @@ void rs600_bandwidth_update(struct radeon_device *rdev) uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg) { + unsigned long flags; + u32 r; + + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) | S_000070_MC_IND_CITF_ARB0(1)); - return RREG32(R_000074_MC_IND_DATA); + r = RREG32(R_000074_MC_IND_DATA); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); + return r; } void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(R_000070_MC_IND_INDEX, S_000070_MC_IND_ADDR(reg) | S_000070_MC_IND_CITF_ARB0(1) | S_000070_MC_IND_WR_EN(1)); WREG32(R_000074_MC_IND_DATA, v); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); } static void rs600_debugfs(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index d8ddfb34545d..1447d794c22a 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -631,20 +631,27 @@ void rs690_bandwidth_update(struct radeon_device *rdev) uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg) { + unsigned long flags; uint32_t r; + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg)); r = RREG32(R_00007C_MC_DATA); WREG32(R_000078_MC_INDEX, ~C_000078_MC_IND_ADDR); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); return r; } void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(R_000078_MC_INDEX, S_000078_MC_IND_ADDR(reg) | S_000078_MC_IND_WR_EN(1)); WREG32(R_00007C_MC_DATA, v); WREG32(R_000078_MC_INDEX, 0x7F); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); } static void rs690_mc_program(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c index d1a1ce73bd45..6af8505cf4d2 100644 --- a/drivers/gpu/drm/radeon/rs780_dpm.c +++ b/drivers/gpu/drm/radeon/rs780_dpm.c @@ -62,9 +62,7 @@ static void rs780_get_pm_mode_parameters(struct radeon_device *rdev) radeon_crtc = to_radeon_crtc(crtc); pi->crtc_id = radeon_crtc->crtc_id; if (crtc->mode.htotal && crtc->mode.vtotal) - pi->refresh_rate = - (crtc->mode.clock * 1000) / - (crtc->mode.htotal * crtc->mode.vtotal); + pi->refresh_rate = drm_mode_vrefresh(&crtc->mode); break; } } @@ -376,9 +374,8 @@ static void rs780_disable_vbios_powersaving(struct radeon_device *rdev) WREG32_P(CG_INTGFX_MISC, 0, ~0xFFF00000); } -static void rs780_force_voltage_to_high(struct radeon_device *rdev) +static void rs780_force_voltage(struct radeon_device *rdev, u16 voltage) { - struct igp_power_info *pi = rs780_get_pi(rdev); struct igp_ps *current_state = rs780_get_ps(rdev->pm.dpm.current_ps); if ((current_state->max_voltage == RS780_VDDC_LEVEL_HIGH) && @@ -390,7 +387,7 @@ static void rs780_force_voltage_to_high(struct radeon_device *rdev) udelay(1); WREG32_P(FVTHROT_PWM_CTRL_REG0, - STARTING_PWM_HIGHTIME(pi->max_voltage), + STARTING_PWM_HIGHTIME(voltage), ~STARTING_PWM_HIGHTIME_MASK); WREG32_P(FVTHROT_PWM_CTRL_REG0, @@ -404,6 +401,26 @@ static void rs780_force_voltage_to_high(struct radeon_device *rdev) WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL); } +static void rs780_force_fbdiv(struct radeon_device *rdev, u32 fb_div) +{ + struct igp_ps *current_state = rs780_get_ps(rdev->pm.dpm.current_ps); + + if (current_state->sclk_low == current_state->sclk_high) + return; + + WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, ~SPLL_BYPASS_CNTL); + + WREG32_P(FVTHROT_FBDIV_REG2, FORCED_FEEDBACK_DIV(fb_div), + ~FORCED_FEEDBACK_DIV_MASK); + WREG32_P(FVTHROT_FBDIV_REG1, STARTING_FEEDBACK_DIV(fb_div), + ~STARTING_FEEDBACK_DIV_MASK); + WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV, ~FORCE_FEEDBACK_DIV); + + udelay(100); + + WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL); +} + static int rs780_set_engine_clock_scaling(struct radeon_device *rdev, struct radeon_ps *new_ps, struct radeon_ps *old_ps) @@ -432,17 +449,13 @@ static int rs780_set_engine_clock_scaling(struct radeon_device *rdev, if (ret) return ret; - WREG32_P(GFX_MACRO_BYPASS_CNTL, SPLL_BYPASS_CNTL, ~SPLL_BYPASS_CNTL); - - WREG32_P(FVTHROT_FBDIV_REG2, FORCED_FEEDBACK_DIV(max_dividers.fb_div), - ~FORCED_FEEDBACK_DIV_MASK); - WREG32_P(FVTHROT_FBDIV_REG1, STARTING_FEEDBACK_DIV(max_dividers.fb_div), - ~STARTING_FEEDBACK_DIV_MASK); - WREG32_P(FVTHROT_FBDIV_REG1, FORCE_FEEDBACK_DIV, ~FORCE_FEEDBACK_DIV); - - udelay(100); + if ((min_dividers.ref_div != max_dividers.ref_div) || + (min_dividers.post_div != max_dividers.post_div) || + (max_dividers.ref_div != current_max_dividers.ref_div) || + (max_dividers.post_div != current_max_dividers.post_div)) + return -EINVAL; - WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~SPLL_BYPASS_CNTL); + rs780_force_fbdiv(rdev, max_dividers.fb_div); if (max_dividers.fb_div > min_dividers.fb_div) { WREG32_P(FVTHROT_FBDIV_REG0, @@ -486,6 +499,9 @@ static void rs780_activate_engine_clk_scaling(struct radeon_device *rdev, (new_state->sclk_low == old_state->sclk_low)) return; + if (new_state->sclk_high == new_state->sclk_low) + return; + rs780_clk_scaling_enable(rdev, true); } @@ -649,7 +665,7 @@ int rs780_dpm_set_power_state(struct radeon_device *rdev) rs780_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps); if (pi->voltage_control) { - rs780_force_voltage_to_high(rdev); + rs780_force_voltage(rdev, pi->max_voltage); mdelay(5); } @@ -717,14 +733,18 @@ static void rs780_parse_pplib_non_clock_info(struct radeon_device *rdev, if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); - } else if (r600_is_uvd_state(rps->class, rps->class2)) { - rps->vclk = RS780_DEFAULT_VCLK_FREQ; - rps->dclk = RS780_DEFAULT_DCLK_FREQ; } else { rps->vclk = 0; rps->dclk = 0; } + if (r600_is_uvd_state(rps->class, rps->class2)) { + if ((rps->vclk == 0) || (rps->dclk == 0)) { + rps->vclk = RS780_DEFAULT_VCLK_FREQ; + rps->dclk = RS780_DEFAULT_DCLK_FREQ; + } + } + if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) rdev->pm.dpm.boot_ps = rps; if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) @@ -986,3 +1006,55 @@ void rs780_dpm_debugfs_print_current_performance_level(struct radeon_device *rde seq_printf(m, "power level 1 sclk: %u vddc_index: %d\n", ps->sclk_high, ps->max_voltage); } + +int rs780_dpm_force_performance_level(struct radeon_device *rdev, + enum radeon_dpm_forced_level level) +{ + struct igp_power_info *pi = rs780_get_pi(rdev); + struct radeon_ps *rps = rdev->pm.dpm.current_ps; + struct igp_ps *ps = rs780_get_ps(rps); + struct atom_clock_dividers dividers; + int ret; + + rs780_clk_scaling_enable(rdev, false); + rs780_voltage_scaling_enable(rdev, false); + + if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { + if (pi->voltage_control) + rs780_force_voltage(rdev, pi->max_voltage); + + ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, + ps->sclk_high, false, ÷rs); + if (ret) + return ret; + + rs780_force_fbdiv(rdev, dividers.fb_div); + } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { + ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, + ps->sclk_low, false, ÷rs); + if (ret) + return ret; + + rs780_force_fbdiv(rdev, dividers.fb_div); + + if (pi->voltage_control) + rs780_force_voltage(rdev, pi->min_voltage); + } else { + if (pi->voltage_control) + rs780_force_voltage(rdev, pi->max_voltage); + + if (ps->sclk_high != ps->sclk_low) { + WREG32_P(FVTHROT_FBDIV_REG1, 0, ~FORCE_FEEDBACK_DIV); + rs780_clk_scaling_enable(rdev, true); + } + + if (pi->voltage_control) { + rs780_voltage_scaling_enable(rdev, true); + rs780_enable_voltage_scaling(rdev, rps); + } + } + + rdev->pm.dpm.forced_level = level; + + return 0; +} diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 8ea1573ae820..873eb4b193b4 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -209,19 +209,27 @@ static void rv515_mc_init(struct radeon_device *rdev) uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg) { + unsigned long flags; uint32_t r; + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(MC_IND_INDEX, 0x7f0000 | (reg & 0xffff)); r = RREG32(MC_IND_DATA); WREG32(MC_IND_INDEX, 0); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); + return r; } void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) { + unsigned long flags; + + spin_lock_irqsave(&rdev->mc_idx_lock, flags); WREG32(MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff)); WREG32(MC_IND_DATA, (v)); WREG32(MC_IND_INDEX, 0); + spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); } #if defined(CONFIG_DEBUG_FS) diff --git a/drivers/gpu/drm/radeon/rv6xx_dpm.c b/drivers/gpu/drm/radeon/rv6xx_dpm.c index ab1f2016f21e..5811d277a36a 100644 --- a/drivers/gpu/drm/radeon/rv6xx_dpm.c +++ b/drivers/gpu/drm/radeon/rv6xx_dpm.c @@ -1758,8 +1758,6 @@ int rv6xx_dpm_set_power_state(struct radeon_device *rdev) rv6xx_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); - rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO; - return 0; } diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c index 8cbb85dae5aa..913b025ae9b3 100644 --- a/drivers/gpu/drm/radeon/rv770_dpm.c +++ b/drivers/gpu/drm/radeon/rv770_dpm.c @@ -2064,12 +2064,6 @@ int rv770_dpm_set_power_state(struct radeon_device *rdev) rv770_program_dcodt_after_state_switch(rdev, new_ps, old_ps); rv770_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); - ret = rv770_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO); - if (ret) { - DRM_ERROR("rv770_dpm_force_performance_level failed\n"); - return ret; - } - return 0; } @@ -2147,14 +2141,18 @@ static void rv7xx_parse_pplib_non_clock_info(struct radeon_device *rdev, if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); - } else if (r600_is_uvd_state(rps->class, rps->class2)) { - rps->vclk = RV770_DEFAULT_VCLK_FREQ; - rps->dclk = RV770_DEFAULT_DCLK_FREQ; } else { rps->vclk = 0; rps->dclk = 0; } + if (r600_is_uvd_state(rps->class, rps->class2)) { + if ((rps->vclk == 0) || (rps->dclk == 0)) { + rps->vclk = RV770_DEFAULT_VCLK_FREQ; + rps->dclk = RV770_DEFAULT_DCLK_FREQ; + } + } + if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) rdev->pm.dpm.boot_ps = rps; if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) diff --git a/drivers/gpu/drm/radeon/rv770_smc.c b/drivers/gpu/drm/radeon/rv770_smc.c index ab95da570215..b2a224407365 100644 --- a/drivers/gpu/drm/radeon/rv770_smc.c +++ b/drivers/gpu/drm/radeon/rv770_smc.c @@ -274,8 +274,8 @@ static const u8 cayman_smc_int_vectors[] = 0x08, 0x72, 0x08, 0x72 }; -int rv770_set_smc_sram_address(struct radeon_device *rdev, - u16 smc_address, u16 limit) +static int rv770_set_smc_sram_address(struct radeon_device *rdev, + u16 smc_address, u16 limit) { u32 addr; @@ -296,9 +296,10 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev, u16 smc_start_address, const u8 *src, u16 byte_count, u16 limit) { + unsigned long flags; u32 data, original_data, extra_shift; u16 addr; - int ret; + int ret = 0; if (smc_start_address & 3) return -EINVAL; @@ -307,13 +308,14 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev, addr = smc_start_address; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); while (byte_count >= 4) { /* SMC address space is BE */ data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; ret = rv770_set_smc_sram_address(rdev, addr, limit); if (ret) - return ret; + goto done; WREG32(SMC_SRAM_DATA, data); @@ -328,7 +330,7 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev, ret = rv770_set_smc_sram_address(rdev, addr, limit); if (ret) - return ret; + goto done; original_data = RREG32(SMC_SRAM_DATA); @@ -346,12 +348,15 @@ int rv770_copy_bytes_to_smc(struct radeon_device *rdev, ret = rv770_set_smc_sram_address(rdev, addr, limit); if (ret) - return ret; + goto done; WREG32(SMC_SRAM_DATA, data); } - return 0; +done: + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); + + return ret; } static int rv770_program_interrupt_vectors(struct radeon_device *rdev, @@ -461,12 +466,15 @@ PPSMC_Result rv770_wait_for_smc_inactive(struct radeon_device *rdev) static void rv770_clear_smc_sram(struct radeon_device *rdev, u16 limit) { + unsigned long flags; u16 i; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); for (i = 0; i < limit; i += 4) { rv770_set_smc_sram_address(rdev, i, limit); WREG32(SMC_SRAM_DATA, 0); } + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); } int rv770_load_smc_ucode(struct radeon_device *rdev, @@ -595,27 +603,29 @@ int rv770_load_smc_ucode(struct radeon_device *rdev, int rv770_read_smc_sram_dword(struct radeon_device *rdev, u16 smc_address, u32 *value, u16 limit) { + unsigned long flags; int ret; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); ret = rv770_set_smc_sram_address(rdev, smc_address, limit); - if (ret) - return ret; - - *value = RREG32(SMC_SRAM_DATA); + if (ret == 0) + *value = RREG32(SMC_SRAM_DATA); + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); - return 0; + return ret; } int rv770_write_smc_sram_dword(struct radeon_device *rdev, u16 smc_address, u32 value, u16 limit) { + unsigned long flags; int ret; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); ret = rv770_set_smc_sram_address(rdev, smc_address, limit); - if (ret) - return ret; + if (ret == 0) + WREG32(SMC_SRAM_DATA, value); + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); - WREG32(SMC_SRAM_DATA, value); - - return 0; + return ret; } diff --git a/drivers/gpu/drm/radeon/rv770_smc.h b/drivers/gpu/drm/radeon/rv770_smc.h index f78d92a4b325..3b2c963c4880 100644 --- a/drivers/gpu/drm/radeon/rv770_smc.h +++ b/drivers/gpu/drm/radeon/rv770_smc.h @@ -187,8 +187,6 @@ typedef struct RV770_SMC_STATETABLE RV770_SMC_STATETABLE; #define RV770_SMC_SOFT_REGISTER_uvd_enabled 0x9C #define RV770_SMC_SOFT_REGISTER_is_asic_lombok 0xA0 -int rv770_set_smc_sram_address(struct radeon_device *rdev, - u16 smc_address, u16 limit); int rv770_copy_bytes_to_smc(struct radeon_device *rdev, u16 smc_start_address, const u8 *src, u16 byte_count, u16 limit); diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h index 9fe60e542922..1ae277152cc7 100644 --- a/drivers/gpu/drm/radeon/rv770d.h +++ b/drivers/gpu/drm/radeon/rv770d.h @@ -852,7 +852,7 @@ #define AFMT_VBI_PACKET_CONTROL 0x7608 # define AFMT_GENERIC0_UPDATE (1 << 2) #define AFMT_INFOFRAME_CONTROL0 0x760c -# define AFMT_AUDIO_INFO_SOURCE (1 << 6) /* 0 - sound block; 1 - hmdi regs */ +# define AFMT_AUDIO_INFO_SOURCE (1 << 6) /* 0 - sound block; 1 - hdmi regs */ # define AFMT_AUDIO_INFO_UPDATE (1 << 7) # define AFMT_MPEG_INFO_UPDATE (1 << 10) #define AFMT_GENERIC0_7 0x7610 diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 3e23b757dcfa..c354c1094967 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -83,6 +83,8 @@ extern void si_dma_vm_set_page(struct radeon_device *rdev, uint64_t pe, uint64_t addr, unsigned count, uint32_t incr, uint32_t flags); +static void si_enable_gui_idle_interrupt(struct radeon_device *rdev, + bool enable); static const u32 verde_rlc_save_restore_register_list[] = { @@ -3386,6 +3388,8 @@ static int si_cp_resume(struct radeon_device *rdev) u32 rb_bufsz; int r; + si_enable_gui_idle_interrupt(rdev, false); + WREG32(CP_SEM_WAIT_TIMER, 0x0); WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0); @@ -3501,6 +3505,8 @@ static int si_cp_resume(struct radeon_device *rdev) rdev->ring[CAYMAN_RING_TYPE_CP2_INDEX].ready = false; } + si_enable_gui_idle_interrupt(rdev, true); + return 0; } @@ -4888,7 +4894,7 @@ static void si_enable_gfx_cgpg(struct radeon_device *rdev, { u32 tmp; - if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG)) { + if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG)) { tmp = RLC_PUD(0x10) | RLC_PDD(0x10) | RLC_TTPD(0x10) | RLC_MSD(0x10); WREG32(RLC_TTOP_D, tmp); @@ -5250,6 +5256,7 @@ void si_update_cg(struct radeon_device *rdev, u32 block, bool enable) { if (block & RADEON_CG_BLOCK_GFX) { + si_enable_gui_idle_interrupt(rdev, false); /* order matters! */ if (enable) { si_enable_mgcg(rdev, true); @@ -5258,6 +5265,7 @@ void si_update_cg(struct radeon_device *rdev, si_enable_cgcg(rdev, false); si_enable_mgcg(rdev, false); } + si_enable_gui_idle_interrupt(rdev, true); } if (block & RADEON_CG_BLOCK_MC) { @@ -5408,7 +5416,7 @@ static void si_init_pg(struct radeon_device *rdev) si_init_dma_pg(rdev); } si_init_ao_cu_mask(rdev); - if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) { + if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) { si_init_gfx_cgpg(rdev); } si_enable_dma_pg(rdev, true); @@ -5560,7 +5568,9 @@ static void si_disable_interrupt_state(struct radeon_device *rdev) { u32 tmp; - WREG32(CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + tmp = RREG32(CP_INT_CNTL_RING0) & + (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + WREG32(CP_INT_CNTL_RING0, tmp); WREG32(CP_INT_CNTL_RING1, 0); WREG32(CP_INT_CNTL_RING2, 0); tmp = RREG32(DMA_CNTL + DMA0_REGISTER_OFFSET) & ~TRAP_ENABLE; @@ -5685,7 +5695,7 @@ static int si_irq_init(struct radeon_device *rdev) int si_irq_set(struct radeon_device *rdev) { - u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; + u32 cp_int_cntl; u32 cp_int_cntl1 = 0, cp_int_cntl2 = 0; u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; u32 hpd1 = 0, hpd2 = 0, hpd3 = 0, hpd4 = 0, hpd5 = 0, hpd6 = 0; @@ -5706,6 +5716,9 @@ int si_irq_set(struct radeon_device *rdev) return 0; } + cp_int_cntl = RREG32(CP_INT_CNTL_RING0) & + (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); + if (!ASIC_IS_NODCE(rdev)) { hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 5be9b4e72350..cfe5d4d28915 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -6075,12 +6075,6 @@ int si_dpm_set_power_state(struct radeon_device *rdev) return ret; } - ret = si_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO); - if (ret) { - DRM_ERROR("si_dpm_force_performance_level failed\n"); - return ret; - } - si_update_cg(rdev, (RADEON_CG_BLOCK_GFX | RADEON_CG_BLOCK_MC | RADEON_CG_BLOCK_SDMA | diff --git a/drivers/gpu/drm/radeon/si_smc.c b/drivers/gpu/drm/radeon/si_smc.c index 5f524c0a541e..d422a1cbf727 100644 --- a/drivers/gpu/drm/radeon/si_smc.c +++ b/drivers/gpu/drm/radeon/si_smc.c @@ -29,8 +29,8 @@ #include "ppsmc.h" #include "radeon_ucode.h" -int si_set_smc_sram_address(struct radeon_device *rdev, - u32 smc_address, u32 limit) +static int si_set_smc_sram_address(struct radeon_device *rdev, + u32 smc_address, u32 limit) { if (smc_address & 3) return -EINVAL; @@ -47,7 +47,8 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev, u32 smc_start_address, const u8 *src, u32 byte_count, u32 limit) { - int ret; + unsigned long flags; + int ret = 0; u32 data, original_data, addr, extra_shift; if (smc_start_address & 3) @@ -57,13 +58,14 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev, addr = smc_start_address; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); while (byte_count >= 4) { /* SMC address space is BE */ data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; ret = si_set_smc_sram_address(rdev, addr, limit); if (ret) - return ret; + goto done; WREG32(SMC_IND_DATA_0, data); @@ -78,7 +80,7 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev, ret = si_set_smc_sram_address(rdev, addr, limit); if (ret) - return ret; + goto done; original_data = RREG32(SMC_IND_DATA_0); @@ -96,11 +98,15 @@ int si_copy_bytes_to_smc(struct radeon_device *rdev, ret = si_set_smc_sram_address(rdev, addr, limit); if (ret) - return ret; + goto done; WREG32(SMC_IND_DATA_0, data); } - return 0; + +done: + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); + + return ret; } void si_start_smc(struct radeon_device *rdev) @@ -203,6 +209,7 @@ PPSMC_Result si_wait_for_smc_inactive(struct radeon_device *rdev) int si_load_smc_ucode(struct radeon_device *rdev, u32 limit) { + unsigned long flags; u32 ucode_start_address; u32 ucode_size; const u8 *src; @@ -241,6 +248,7 @@ int si_load_smc_ucode(struct radeon_device *rdev, u32 limit) return -EINVAL; src = (const u8 *)rdev->smc_fw->data; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); WREG32(SMC_IND_INDEX_0, ucode_start_address); WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0); while (ucode_size >= 4) { @@ -253,6 +261,7 @@ int si_load_smc_ucode(struct radeon_device *rdev, u32 limit) ucode_size -= 4; } WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); return 0; } @@ -260,25 +269,29 @@ int si_load_smc_ucode(struct radeon_device *rdev, u32 limit) int si_read_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 *value, u32 limit) { + unsigned long flags; int ret; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); ret = si_set_smc_sram_address(rdev, smc_address, limit); - if (ret) - return ret; + if (ret == 0) + *value = RREG32(SMC_IND_DATA_0); + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); - *value = RREG32(SMC_IND_DATA_0); - return 0; + return ret; } int si_write_smc_sram_dword(struct radeon_device *rdev, u32 smc_address, u32 value, u32 limit) { + unsigned long flags; int ret; + spin_lock_irqsave(&rdev->smc_idx_lock, flags); ret = si_set_smc_sram_address(rdev, smc_address, limit); - if (ret) - return ret; + if (ret == 0) + WREG32(SMC_IND_DATA_0, value); + spin_unlock_irqrestore(&rdev->smc_idx_lock, flags); - WREG32(SMC_IND_DATA_0, value); - return 0; + return ret; } diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c index 864761c0120e..96ea6db8bf57 100644 --- a/drivers/gpu/drm/radeon/sumo_dpm.c +++ b/drivers/gpu/drm/radeon/sumo_dpm.c @@ -1319,8 +1319,6 @@ int sumo_dpm_set_power_state(struct radeon_device *rdev) if (pi->enable_dpm) sumo_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); - rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO; - return 0; } diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c index b07b7b8f1aff..7f998bf1cc9d 100644 --- a/drivers/gpu/drm/radeon/trinity_dpm.c +++ b/drivers/gpu/drm/radeon/trinity_dpm.c @@ -1068,6 +1068,17 @@ static void trinity_update_requested_ps(struct radeon_device *rdev, pi->requested_rps.ps_priv = &pi->requested_ps; } +void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable) +{ + struct trinity_power_info *pi = trinity_get_pi(rdev); + + if (pi->enable_bapm) { + trinity_acquire_mutex(rdev); + trinity_dpm_bapm_enable(rdev, enable); + trinity_release_mutex(rdev); + } +} + int trinity_dpm_enable(struct radeon_device *rdev) { struct trinity_power_info *pi = trinity_get_pi(rdev); @@ -1091,6 +1102,7 @@ int trinity_dpm_enable(struct radeon_device *rdev) trinity_program_sclk_dpm(rdev); trinity_start_dpm(rdev); trinity_wait_for_dpm_enabled(rdev); + trinity_dpm_bapm_enable(rdev, false); trinity_release_mutex(rdev); if (rdev->irq.installed && @@ -1116,6 +1128,7 @@ void trinity_dpm_disable(struct radeon_device *rdev) trinity_release_mutex(rdev); return; } + trinity_dpm_bapm_enable(rdev, false); trinity_disable_clock_power_gating(rdev); sumo_clear_vc(rdev); trinity_wait_for_level_0(rdev); @@ -1212,6 +1225,8 @@ int trinity_dpm_set_power_state(struct radeon_device *rdev) trinity_acquire_mutex(rdev); if (pi->enable_dpm) { + if (pi->enable_bapm) + trinity_dpm_bapm_enable(rdev, rdev->pm.dpm.ac_power); trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps); trinity_enable_power_level_0(rdev); trinity_force_level_0(rdev); @@ -1221,7 +1236,6 @@ int trinity_dpm_set_power_state(struct radeon_device *rdev) trinity_force_level_0(rdev); trinity_unforce_levels(rdev); trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); - rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO; } trinity_release_mutex(rdev); @@ -1854,6 +1868,7 @@ int trinity_dpm_init(struct radeon_device *rdev) for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) pi->at[i] = TRINITY_AT_DFLT; + pi->enable_bapm = true; pi->enable_nbps_policy = true; pi->enable_sclk_ds = true; pi->enable_gfx_power_gating = true; diff --git a/drivers/gpu/drm/radeon/trinity_dpm.h b/drivers/gpu/drm/radeon/trinity_dpm.h index e82df071f8b3..c261657750ca 100644 --- a/drivers/gpu/drm/radeon/trinity_dpm.h +++ b/drivers/gpu/drm/radeon/trinity_dpm.h @@ -108,6 +108,7 @@ struct trinity_power_info { bool enable_auto_thermal_throttling; bool enable_dpm; bool enable_sclk_ds; + bool enable_bapm; bool uvd_dpm; struct radeon_ps current_rps; struct trinity_ps current_ps; @@ -118,6 +119,7 @@ struct trinity_power_info { #define TRINITY_AT_DFLT 30 /* trinity_smc.c */ +int trinity_dpm_bapm_enable(struct radeon_device *rdev, bool enable); int trinity_dpm_config(struct radeon_device *rdev, bool enable); int trinity_uvd_dpm_config(struct radeon_device *rdev); int trinity_dpm_force_state(struct radeon_device *rdev, u32 n); diff --git a/drivers/gpu/drm/radeon/trinity_smc.c b/drivers/gpu/drm/radeon/trinity_smc.c index a42d89f1830c..9672bcbc7312 100644 --- a/drivers/gpu/drm/radeon/trinity_smc.c +++ b/drivers/gpu/drm/radeon/trinity_smc.c @@ -56,6 +56,14 @@ static int trinity_notify_message_to_smu(struct radeon_device *rdev, u32 id) return 0; } +int trinity_dpm_bapm_enable(struct radeon_device *rdev, bool enable) +{ + if (enable) + return trinity_notify_message_to_smu(rdev, PPSMC_MSG_EnableBAPM); + else + return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DisableBAPM); +} + int trinity_dpm_config(struct radeon_device *rdev, bool enable) { if (enable) diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c index 58a5f3261c0b..a868176c258a 100644 --- a/drivers/gpu/drm/ttm/ttm_object.c +++ b/drivers/gpu/drm/ttm/ttm_object.c @@ -218,7 +218,7 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile, uint32_t key) { struct ttm_object_device *tdev = tfile->tdev; - struct ttm_base_object *base; + struct ttm_base_object *uninitialized_var(base); struct drm_hash_item *hash; int ret; diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 5e93a52d4f2c..210d50365162 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -170,7 +170,7 @@ void ttm_tt_destroy(struct ttm_tt *ttm) ttm_tt_unbind(ttm); } - if (likely(ttm->pages != NULL)) { + if (ttm->state == tt_unbound) { ttm->bdev->driver->ttm_tt_unpopulate(ttm); } diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index 8dbe9d0ae9a7..8bf646183bac 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -97,7 +97,6 @@ int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page); switch (ret) { case -EAGAIN: - set_need_resched(); case 0: case -ERESTARTSYS: return VM_FAULT_NOPAGE; diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ae88a97f976e..b8470b1a10fe 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -94,7 +94,6 @@ EXPORT_SYMBOL_GPL(hid_register_report); static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) { struct hid_field *field; - int i; if (report->maxfield == HID_MAX_FIELDS) { hid_err(report->device, "too many fields in report\n"); @@ -113,9 +112,6 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned field->value = (s32 *)(field->usage + usages); field->report = report; - for (i = 0; i < usages; i++) - field->usage[i].usage_index = i; - return field; } @@ -226,9 +222,9 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign { struct hid_report *report; struct hid_field *field; - int usages; + unsigned usages; unsigned offset; - int i; + unsigned i; report = hid_register_report(parser->device, report_type, parser->global.report_id); if (!report) { @@ -255,7 +251,8 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign if (!parser->local.usage_index) /* Ignore padding fields */ return 0; - usages = max_t(int, parser->local.usage_index, parser->global.report_count); + usages = max_t(unsigned, parser->local.usage_index, + parser->global.report_count); field = hid_register_field(report, usages, parser->global.report_count); if (!field) @@ -266,13 +263,14 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); for (i = 0; i < usages; i++) { - int j = i; + unsigned j = i; /* Duplicate the last usage we parsed if we have excess values */ if (i >= parser->local.usage_index) j = parser->local.usage_index - 1; field->usage[i].hid = parser->local.usage[j]; field->usage[i].collection_index = parser->local.collection_index[j]; + field->usage[i].usage_index = i; } field->maxusage = usages; @@ -801,6 +799,64 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) } EXPORT_SYMBOL_GPL(hid_parse_report); +static const char * const hid_report_names[] = { + "HID_INPUT_REPORT", + "HID_OUTPUT_REPORT", + "HID_FEATURE_REPORT", +}; +/** + * hid_validate_values - validate existing device report's value indexes + * + * @device: hid device + * @type: which report type to examine + * @id: which report ID to examine (0 for first) + * @field_index: which report field to examine + * @report_counts: expected number of values + * + * Validate the number of values in a given field of a given report, after + * parsing. + */ +struct hid_report *hid_validate_values(struct hid_device *hid, + unsigned int type, unsigned int id, + unsigned int field_index, + unsigned int report_counts) +{ + struct hid_report *report; + + if (type > HID_FEATURE_REPORT) { + hid_err(hid, "invalid HID report type %u\n", type); + return NULL; + } + + if (id >= HID_MAX_IDS) { + hid_err(hid, "invalid HID report id %u\n", id); + return NULL; + } + + /* + * Explicitly not using hid_get_report() here since it depends on + * ->numbered being checked, which may not always be the case when + * drivers go to access report values. + */ + report = hid->report_enum[type].report_id_hash[id]; + if (!report) { + hid_err(hid, "missing %s %u\n", hid_report_names[type], id); + return NULL; + } + if (report->maxfield <= field_index) { + hid_err(hid, "not enough fields in %s %u\n", + hid_report_names[type], id); + return NULL; + } + if (report->field[field_index]->report_count < report_counts) { + hid_err(hid, "not enough values in %s %u field %u\n", + hid_report_names[type], id, field_index); + return NULL; + } + return report; +} +EXPORT_SYMBOL_GPL(hid_validate_values); + /** * hid_open_report - open a driver-specific device report * @@ -1296,7 +1352,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, goto out; } - if (hid->claimed != HID_CLAIMED_HIDRAW) { + if (hid->claimed != HID_CLAIMED_HIDRAW && report->maxfield) { for (a = 0; a < report->maxfield; a++) hid_input_field(hid, report->field[a], cdata, interrupt); hdrv = hid->driver; diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index b420f4a0fd28..8741d953dcc8 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -485,6 +485,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel if (field->flags & HID_MAIN_ITEM_CONSTANT) goto ignore; + /* Ignore if report count is out of bounds. */ + if (field->report_count < 1) + goto ignore; + /* only LED usages are supported in output fields */ if (field->report_type == HID_OUTPUT_REPORT && (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) { @@ -1236,7 +1240,11 @@ static void report_features(struct hid_device *hid) rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; list_for_each_entry(rep, &rep_enum->report_list, list) - for (i = 0; i < rep->maxfield; i++) + for (i = 0; i < rep->maxfield; i++) { + /* Ignore if report count is out of bounds. */ + if (rep->field[i]->report_count < 1) + continue; + for (j = 0; j < rep->field[i]->maxusage; j++) { /* Verify if Battery Strength feature is available */ hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]); @@ -1245,6 +1253,7 @@ static void report_features(struct hid_device *hid) drv->feature_mapping(hid, rep->field[i], rep->field[i]->usage + j); } + } } static struct hid_input *hidinput_allocate(struct hid_device *hid) diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c index 07837f5a4eb8..31cf29a6ba17 100644 --- a/drivers/hid/hid-lenovo-tpkbd.c +++ b/drivers/hid/hid-lenovo-tpkbd.c @@ -339,7 +339,15 @@ static int tpkbd_probe_tp(struct hid_device *hdev) struct tpkbd_data_pointer *data_pointer; size_t name_sz = strlen(dev_name(dev)) + 16; char *name_mute, *name_micmute; - int ret; + int i, ret; + + /* Validate required reports. */ + for (i = 0; i < 4; i++) { + if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1)) + return -ENODEV; + } + if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2)) + return -ENODEV; if (sysfs_create_group(&hdev->dev.kobj, &tpkbd_attr_group_pointer)) { @@ -406,22 +414,27 @@ static int tpkbd_probe(struct hid_device *hdev, ret = hid_parse(hdev); if (ret) { hid_err(hdev, "hid_parse failed\n"); - goto err_free; + goto err; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { hid_err(hdev, "hid_hw_start failed\n"); - goto err_free; + goto err; } uhdev = (struct usbhid_device *) hdev->driver_data; - if (uhdev->ifnum == 1) - return tpkbd_probe_tp(hdev); + if (uhdev->ifnum == 1) { + ret = tpkbd_probe_tp(hdev); + if (ret) + goto err_hid; + } return 0; -err_free: +err_hid: + hid_hw_stop(hdev); +err: return ret; } diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c index b3cd1507dda2..1a42eaa6ca02 100644 --- a/drivers/hid/hid-lg2ff.c +++ b/drivers/hid/hid-lg2ff.c @@ -64,26 +64,13 @@ int lg2ff_init(struct hid_device *hid) struct hid_report *report; struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; int error; - if (list_empty(report_list)) { - hid_err(hid, "no output report found\n"); + /* Check that the report looks ok */ + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7); + if (!report) return -ENODEV; - } - - report = list_entry(report_list->next, struct hid_report, list); - - if (report->maxfield < 1) { - hid_err(hid, "output report is empty\n"); - return -ENODEV; - } - if (report->field[0]->report_count < 7) { - hid_err(hid, "not enough values in the field\n"); - return -ENODEV; - } lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL); if (!lg2ff) diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c index e52f181f6aa1..8c2da183d3bc 100644 --- a/drivers/hid/hid-lg3ff.c +++ b/drivers/hid/hid-lg3ff.c @@ -66,10 +66,11 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data, int x, y; /* - * Maxusage should always be 63 (maximum fields) - * likely a better way to ensure this data is clean + * Available values in the field should always be 63, but we only use up to + * 35. Instead, clear the entire area, however big it is. */ - memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage); + memset(report->field[0]->value, 0, + sizeof(__s32) * report->field[0]->report_count); switch (effect->type) { case FF_CONSTANT: @@ -129,32 +130,14 @@ static const signed short ff3_joystick_ac[] = { int lg3ff_init(struct hid_device *hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; const signed short *ff_bits = ff3_joystick_ac; int error; int i; - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - if (!report) { - hid_err(hid, "NULL output report\n"); - return -1; - } - - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35)) + return -ENODEV; /* Assume single fixed device G940 */ for (i = 0; ff_bits[i] >= 0; i++) diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 0ddae2a00d59..8782fe1aaa07 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -484,34 +484,16 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde int lg4ff_init(struct hid_device *hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; struct lg4ff_device_entry *entry; struct lg_drv_data *drv_data; struct usb_device_descriptor *udesc; int error, i, j; __u16 bcdDevice, rev_maj, rev_min; - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - if (!report) { - hid_err(hid, "NULL output report\n"); + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) return -1; - } - - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } /* Check what wheel has been connected */ for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index d7ea8c845b40..e1394af0ae7b 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c @@ -128,27 +128,14 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) int lgff_init(struct hid_device* hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; const signed short *ff_bits = ff_joystick; int error; int i; - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) + return -ENODEV; for (i = 0; i < ARRAY_SIZE(devices); i++) { if (dev->id.vendor == devices[i].idVendor && diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 7800b1410562..2e5302462efb 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -461,7 +461,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, struct hid_report *report; struct hid_report_enum *output_report_enum; u8 *data = (u8 *)(&dj_report->device_index); - int i; + unsigned int i; output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; @@ -471,7 +471,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, return -ENODEV; } - for (i = 0; i < report->field[0]->report_count; i++) + for (i = 0; i < DJREPORT_SHORT_LENGTH - 1; i++) report->field[0]->value[i] = data[i]; hid_hw_request(hdev, report, HID_REQ_SET_REPORT); @@ -791,6 +791,12 @@ static int logi_dj_probe(struct hid_device *hdev, goto hid_parse_fail; } + if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT, + 0, DJREPORT_SHORT_LENGTH - 1)) { + retval = -ENODEV; + goto hid_parse_fail; + } + /* Starts the usb device and connects to upper interfaces hiddev and * hidraw */ retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index ac28f08c3866..5e5fe1b8eebb 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -101,9 +101,9 @@ struct mt_device { unsigned last_slot_field; /* the last field of a slot */ unsigned mt_report_id; /* the report ID of the multitouch device */ unsigned pen_report_id; /* the report ID of the pen device */ - __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ - __s8 inputmode_index; /* InputMode HID feature index in the report */ - __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, + __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ + __s16 inputmode_index; /* InputMode HID feature index in the report */ + __s16 maxcontact_report_id; /* Maximum Contact Number HID feature, -1 if non-existent */ __u8 num_received; /* how many contacts we received */ __u8 num_expected; /* expected last contact index */ @@ -312,20 +312,18 @@ static void mt_feature_mapping(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage) { struct mt_device *td = hid_get_drvdata(hdev); - int i; switch (usage->hid) { case HID_DG_INPUTMODE: - td->inputmode = field->report->id; - td->inputmode_index = 0; /* has to be updated below */ - - for (i=0; i < field->maxusage; i++) { - if (field->usage[i].hid == usage->hid) { - td->inputmode_index = i; - break; - } + /* Ignore if value index is out of bounds. */ + if (usage->usage_index >= field->report_count) { + dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n"); + break; } + td->inputmode = field->report->id; + td->inputmode_index = usage->usage_index; + break; case HID_DG_CONTACTMAX: td->maxcontact_report_id = field->report->id; @@ -511,6 +509,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, mt_store_field(usage, td, hi); return 1; case HID_DG_CONTACTCOUNT: + /* Ignore if indexes are out of bounds. */ + if (field->index >= field->report->maxfield || + usage->usage_index >= field->report_count) + return 1; td->cc_index = field->index; td->cc_value_index = usage->usage_index; return 1; diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 30dbb6b40bbf..b18320db5f7d 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -537,6 +537,10 @@ static int buzz_init(struct hid_device *hdev) drv_data = hid_get_drvdata(hdev); BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); + /* Validate expected report characteristics. */ + if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) + return -ENODEV; + buzz = kzalloc(sizeof(*buzz), GFP_KERNEL); if (!buzz) { hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c index d16491192112..29f328f411fb 100644 --- a/drivers/hid/hid-steelseries.c +++ b/drivers/hid/hid-steelseries.c @@ -249,6 +249,11 @@ static int steelseries_srws1_probe(struct hid_device *hdev, goto err_free; } + if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 16)) { + ret = -ENODEV; + goto err_free; + } + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) { hid_err(hdev, "hw start failed\n"); diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index 6ec28a37c146..a29756c6ca02 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c @@ -68,21 +68,13 @@ static int zpff_init(struct hid_device *hid) struct hid_report *report; struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - int error; + int i, error; - if (list_empty(report_list)) { - hid_err(hid, "no output report found\n"); - return -ENODEV; - } - - report = list_entry(report_list->next, struct hid_report, list); - - if (report->maxfield < 4) { - hid_err(hid, "not enough fields in report\n"); - return -ENODEV; + for (i = 0; i < 4; i++) { + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1); + if (!report) + return -ENODEV; } zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 12e32e6b4103..81e3dc260993 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -620,7 +620,7 @@ static int bma180_remove(struct i2c_client *client) #ifdef CONFIG_PM_SLEEP static int bma180_suspend(struct device *dev) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct bma180_data *data = iio_priv(indio_dev); int ret; @@ -633,7 +633,7 @@ static int bma180_suspend(struct device *dev) static int bma180_resume(struct device *dev) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct bma180_data *data = iio_priv(indio_dev); int ret; diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 84be63bdf038..0f16b553e063 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -556,7 +556,7 @@ static const struct iio_info at91_adc_info = { static int at91_adc_probe(struct platform_device *pdev) { - unsigned int prsc, mstrclk, ticks, adc_clk, shtim; + unsigned int prsc, mstrclk, ticks, adc_clk, adc_clk_khz, shtim; int ret; struct iio_dev *idev; struct at91_adc_state *st; @@ -649,6 +649,7 @@ static int at91_adc_probe(struct platform_device *pdev) */ mstrclk = clk_get_rate(st->clk); adc_clk = clk_get_rate(st->adc_clk); + adc_clk_khz = adc_clk / 1000; prsc = (mstrclk / (2 * adc_clk)) - 1; if (!st->startup_time) { @@ -662,15 +663,15 @@ static int at91_adc_probe(struct platform_device *pdev) * defined in the electrical characteristics of the board, divided by 8. * The formula thus is : Startup Time = (ticks + 1) * 8 / ADC Clock */ - ticks = round_up((st->startup_time * adc_clk / - 1000000) - 1, 8) / 8; + ticks = round_up((st->startup_time * adc_clk_khz / + 1000) - 1, 8) / 8; /* * a minimal Sample and Hold Time is necessary for the ADC to guarantee * the best converted final value between two channels selection * The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock */ - shtim = round_up((st->sample_hold_time * adc_clk / - 1000000) - 1, 1); + shtim = round_up((st->sample_hold_time * adc_clk_khz / + 1000) - 1, 1); reg = AT91_ADC_PRESCAL_(prsc) & st->registers->mr_prescal_mask; reg |= AT91_ADC_STARTUP_(ticks) & st->registers->mr_startup_mask; diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer_cb.c index 9d19ba74f22b..415f3c6efd72 100644 --- a/drivers/iio/buffer_cb.c +++ b/drivers/iio/buffer_cb.c @@ -41,6 +41,8 @@ struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev, goto error_ret; } + iio_buffer_init(&cb_buff->buffer); + cb_buff->private = private; cb_buff->cb = cb; cb_buff->buffer.access = &iio_cb_access; diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 1f4a48e6a82c..1397b6e0e414 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -37,21 +37,21 @@ struct mcp4725_data { static int mcp4725_suspend(struct device *dev) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct mcp4725_data *data = iio_priv(indio_dev); + struct mcp4725_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); u8 outbuf[2]; outbuf[0] = (data->powerdown_mode + 1) << 4; outbuf[1] = 0; data->powerdown = true; - return i2c_master_send(to_i2c_client(dev), outbuf, 2); + return i2c_master_send(data->client, outbuf, 2); } static int mcp4725_resume(struct device *dev) { - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct mcp4725_data *data = iio_priv(indio_dev); + struct mcp4725_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); u8 outbuf[2]; /* restore previous DAC value */ @@ -59,7 +59,7 @@ static int mcp4725_resume(struct device *dev) outbuf[1] = data->dac_value & 0xff; data->powerdown = false; - return i2c_master_send(to_i2c_client(dev), outbuf, 2); + return i2c_master_send(data->client, outbuf, 2); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h index 05c1b74502a3..9b32253b824b 100644 --- a/drivers/iio/iio_core.h +++ b/drivers/iio/iio_core.h @@ -49,11 +49,15 @@ ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, #define iio_buffer_poll_addr (&iio_buffer_poll) #define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer) +void iio_disable_all_buffers(struct iio_dev *indio_dev); + #else #define iio_buffer_poll_addr NULL #define iio_buffer_read_first_n_outer_addr NULL +static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {} + #endif int iio_device_register_eventset(struct iio_dev *indio_dev); diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index e73033f3839a..2710f7245c3b 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -460,6 +460,25 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask, return bytes; } +void iio_disable_all_buffers(struct iio_dev *indio_dev) +{ + struct iio_buffer *buffer, *_buffer; + + if (list_empty(&indio_dev->buffer_list)) + return; + + if (indio_dev->setup_ops->predisable) + indio_dev->setup_ops->predisable(indio_dev); + + list_for_each_entry_safe(buffer, _buffer, + &indio_dev->buffer_list, buffer_list) + list_del_init(&buffer->buffer_list); + + indio_dev->currentmode = INDIO_DIRECT_MODE; + if (indio_dev->setup_ops->postdisable) + indio_dev->setup_ops->postdisable(indio_dev); +} + int iio_update_buffers(struct iio_dev *indio_dev, struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer) @@ -528,8 +547,15 @@ int iio_update_buffers(struct iio_dev *indio_dev, * Note can only occur when adding a buffer. */ list_del(&insert_buffer->buffer_list); - indio_dev->active_scan_mask = old_mask; - success = -EINVAL; + if (old_mask) { + indio_dev->active_scan_mask = old_mask; + success = -EINVAL; + } + else { + kfree(compound_mask); + ret = -EINVAL; + goto error_ret; + } } } else { indio_dev->active_scan_mask = compound_mask; diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 97f0297b120f..8e84cd522e49 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -848,8 +848,6 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) static void iio_dev_release(struct device *device) { struct iio_dev *indio_dev = dev_to_iio_dev(device); - if (indio_dev->chrdev.dev) - cdev_del(&indio_dev->chrdev); if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) iio_device_unregister_trigger_consumer(indio_dev); iio_device_unregister_eventset(indio_dev); @@ -970,6 +968,8 @@ static int iio_chrdev_open(struct inode *inode, struct file *filp) if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags)) return -EBUSY; + iio_device_get(indio_dev); + filp->private_data = indio_dev; return 0; @@ -983,6 +983,8 @@ static int iio_chrdev_release(struct inode *inode, struct file *filp) struct iio_dev *indio_dev = container_of(inode->i_cdev, struct iio_dev, chrdev); clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); + iio_device_put(indio_dev); + return 0; } @@ -1052,18 +1054,20 @@ int iio_device_register(struct iio_dev *indio_dev) indio_dev->setup_ops == NULL) indio_dev->setup_ops = &noop_ring_setup_ops; - ret = device_add(&indio_dev->dev); - if (ret < 0) - goto error_unreg_eventset; cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); indio_dev->chrdev.owner = indio_dev->info->driver_module; + indio_dev->chrdev.kobj.parent = &indio_dev->dev.kobj; ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); if (ret < 0) - goto error_del_device; - return 0; + goto error_unreg_eventset; -error_del_device: - device_del(&indio_dev->dev); + ret = device_add(&indio_dev->dev); + if (ret < 0) + goto error_cdev_del; + + return 0; +error_cdev_del: + cdev_del(&indio_dev->chrdev); error_unreg_eventset: iio_device_unregister_eventset(indio_dev); error_free_sysfs: @@ -1078,9 +1082,16 @@ EXPORT_SYMBOL(iio_device_register); void iio_device_unregister(struct iio_dev *indio_dev) { mutex_lock(&indio_dev->info_exist_lock); + + device_del(&indio_dev->dev); + + if (indio_dev->chrdev.dev) + cdev_del(&indio_dev->chrdev); + + iio_disable_all_buffers(indio_dev); + indio_dev->info = NULL; mutex_unlock(&indio_dev->info_exist_lock); - device_del(&indio_dev->dev); } EXPORT_SYMBOL(iio_device_unregister); subsys_initcall(iio_init); diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 10aa9ef86cec..6be65ef5faa9 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -72,7 +72,8 @@ EXPORT_SYMBOL(iio_push_event); static unsigned int iio_event_poll(struct file *filep, struct poll_table_struct *wait) { - struct iio_event_interface *ev_int = filep->private_data; + struct iio_dev *indio_dev = filep->private_data; + struct iio_event_interface *ev_int = indio_dev->event_interface; unsigned int events = 0; poll_wait(filep, &ev_int->wait, wait); @@ -90,7 +91,8 @@ static ssize_t iio_event_chrdev_read(struct file *filep, size_t count, loff_t *f_ps) { - struct iio_event_interface *ev_int = filep->private_data; + struct iio_dev *indio_dev = filep->private_data; + struct iio_event_interface *ev_int = indio_dev->event_interface; unsigned int copied; int ret; @@ -121,7 +123,8 @@ error_unlock: static int iio_event_chrdev_release(struct inode *inode, struct file *filep) { - struct iio_event_interface *ev_int = filep->private_data; + struct iio_dev *indio_dev = filep->private_data; + struct iio_event_interface *ev_int = indio_dev->event_interface; spin_lock_irq(&ev_int->wait.lock); __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); @@ -133,6 +136,8 @@ static int iio_event_chrdev_release(struct inode *inode, struct file *filep) kfifo_reset_out(&ev_int->det_events); spin_unlock_irq(&ev_int->wait.lock); + iio_device_put(indio_dev); + return 0; } @@ -158,12 +163,15 @@ int iio_event_getfd(struct iio_dev *indio_dev) return -EBUSY; } spin_unlock_irq(&ev_int->wait.lock); - fd = anon_inode_getfd("iio:event", - &iio_event_chrdev_fileops, ev_int, O_RDONLY); + iio_device_get(indio_dev); + + fd = anon_inode_getfd("iio:event", &iio_event_chrdev_fileops, + indio_dev, O_RDONLY); if (fd < 0) { spin_lock_irq(&ev_int->wait.lock); __clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags); spin_unlock_irq(&ev_int->wait.lock); + iio_device_put(indio_dev); } return fd; } @@ -276,7 +284,7 @@ static int iio_device_add_event_sysfs(struct iio_dev *indio_dev, goto error_ret; } if (chan->modified) - mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, + mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel2, i/IIO_EV_DIR_MAX, i%IIO_EV_DIR_MAX); else if (chan->differential) diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c index 64ccde3f1f7a..6d63883da1ab 100644 --- a/drivers/iio/temperature/tmp006.c +++ b/drivers/iio/temperature/tmp006.c @@ -255,12 +255,14 @@ static int tmp006_remove(struct i2c_client *client) #ifdef CONFIG_PM_SLEEP static int tmp006_suspend(struct device *dev) { - return tmp006_powerdown(iio_priv(dev_to_iio_dev(dev))); + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + return tmp006_powerdown(iio_priv(indio_dev)); } static int tmp006_resume(struct device *dev) { - struct tmp006_data *data = iio_priv(dev_to_iio_dev(dev)); + struct tmp006_data *data = iio_priv(i2c_get_clientdata( + to_i2c_client(dev))); return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG, data->config | TMP006_CONFIG_MOD_MASK); } diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 7f910c76ca0a..3c92780bda09 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -2295,8 +2295,8 @@ _hfcpci_softirq(struct device *dev, void *arg) static void hfcpci_softirq(void *arg) { - (void) driver_for_each_device(&hfc_driver.driver, NULL, arg, - _hfcpci_softirq); + WARN_ON_ONCE(driver_for_each_device(&hfc_driver.driver, NULL, arg, + _hfcpci_softirq) != 0); /* if next event would be in the past ... */ if ((s32)(hfc_jiffies + tics - jiffies) <= 0) diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c index 1063babe1d3a..36817e0a0b94 100644 --- a/drivers/isdn/hisax/amd7930_fn.c +++ b/drivers/isdn/hisax/amd7930_fn.c @@ -314,7 +314,7 @@ Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag) t += sprintf(t, "Amd7930: empty_Dfifo cnt: %d |", cs->rcvidx); QuickHex(t, cs->rcvbuf, cs->rcvidx); - debugl1(cs, cs->dlog); + debugl1(cs, "%s", cs->dlog); } /* moves received data in sk-buffer */ memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx); @@ -406,7 +406,7 @@ Amd7930_fill_Dfifo(struct IsdnCardState *cs) t += sprintf(t, "Amd7930: fill_Dfifo cnt: %d |", count); QuickHex(t, deb_ptr, count); - debugl1(cs, cs->dlog); + debugl1(cs, "%s", cs->dlog); } /* AMD interrupts on */ AmdIrqOn(cs); diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index ee9b9a03cffa..d1427bd6452d 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c @@ -285,7 +285,7 @@ hdlc_empty_fifo(struct BCState *bcs, int count) t += sprintf(t, "hdlc_empty_fifo %c cnt %d", bcs->channel ? 'B' : 'A', count); QuickHex(t, p, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } @@ -345,7 +345,7 @@ hdlc_fill_fifo(struct BCState *bcs) t += sprintf(t, "hdlc_fill_fifo %c cnt %d", bcs->channel ? 'B' : 'A', count); QuickHex(t, p, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index bf04d2a3cf4a..b33f53b3ca93 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -1896,7 +1896,7 @@ static void EChannel_proc_rcv(struct hisax_d_if *d_if) ptr--; *ptr++ = '\n'; *ptr = 0; - HiSax_putstatus(cs, NULL, cs->dlog); + HiSax_putstatus(cs, NULL, "%s", cs->dlog); } else HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 8d0cf6e4dc00..4fc90de68d18 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -427,7 +427,7 @@ Memhscx_empty_fifo(struct BCState *bcs, int count) t += sprintf(t, "hscx_empty_fifo %c cnt %d", bcs->hw.hscx.hscx ? 'B' : 'A', count); QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } @@ -469,7 +469,7 @@ Memhscx_fill_fifo(struct BCState *bcs) t += sprintf(t, "hscx_fill_fifo %c cnt %d", bcs->hw.hscx.hscx ? 'B' : 'A', count); QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index 1df6f9a56ca2..2be1c8a3bb5f 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -535,7 +535,7 @@ check_arcofi(struct IsdnCardState *cs) t = tmp; t += sprintf(tmp, "Arcofi data"); QuickHex(t, p, cs->dc.isac.mon_rxp); - debugl1(cs, tmp); + debugl1(cs, "%s", tmp); if ((cs->dc.isac.mon_rxp == 2) && (cs->dc.isac.mon_rx[0] == 0xa0)) { switch (cs->dc.isac.mon_rx[1]) { case 0x80: diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c index d4c98d330bfe..3f84dd8f1757 100644 --- a/drivers/isdn/hisax/elsa_ser.c +++ b/drivers/isdn/hisax/elsa_ser.c @@ -344,7 +344,7 @@ static inline void receive_chars(struct IsdnCardState *cs, t += sprintf(t, "modem read cnt %d", cs->hw.elsa.rcvcnt); QuickHex(t, cs->hw.elsa.rcvbuf, cs->hw.elsa.rcvcnt); - debugl1(cs, tmp); + debugl1(cs, "%s", tmp); } cs->hw.elsa.rcvcnt = 0; } diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 3ccd724ff8c2..497bd026c237 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -901,7 +901,7 @@ Begin: ptr--; *ptr++ = '\n'; *ptr = 0; - HiSax_putstatus(cs, NULL, cs->dlog); + HiSax_putstatus(cs, NULL, "%s", cs->dlog); } else HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3); } diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c index dc4574f735ef..fa1fefd711cd 100644 --- a/drivers/isdn/hisax/hfc_sx.c +++ b/drivers/isdn/hisax/hfc_sx.c @@ -674,7 +674,7 @@ receive_emsg(struct IsdnCardState *cs) ptr--; *ptr++ = '\n'; *ptr = 0; - HiSax_putstatus(cs, NULL, cs->dlog); + HiSax_putstatus(cs, NULL, "%s", cs->dlog); } else HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", skb->len); } diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c index f398d4838937..a8d6188402c6 100644 --- a/drivers/isdn/hisax/hscx_irq.c +++ b/drivers/isdn/hisax/hscx_irq.c @@ -75,7 +75,7 @@ hscx_empty_fifo(struct BCState *bcs, int count) t += sprintf(t, "hscx_empty_fifo %c cnt %d", bcs->hw.hscx.hscx ? 'B' : 'A', count); QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } @@ -115,7 +115,7 @@ hscx_fill_fifo(struct BCState *bcs) t += sprintf(t, "hscx_fill_fifo %c cnt %d", bcs->hw.hscx.hscx ? 'B' : 'A', count); QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c index db5321f6379b..51dae9167238 100644 --- a/drivers/isdn/hisax/icc.c +++ b/drivers/isdn/hisax/icc.c @@ -134,7 +134,7 @@ icc_empty_fifo(struct IsdnCardState *cs, int count) t += sprintf(t, "icc_empty_fifo cnt %d", count); QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); + debugl1(cs, "%s", cs->dlog); } } @@ -176,7 +176,7 @@ icc_fill_fifo(struct IsdnCardState *cs) t += sprintf(t, "icc_fill_fifo cnt %d", count); QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); + debugl1(cs, "%s", cs->dlog); } } diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c index 74feb5c83067..5faa5de24305 100644 --- a/drivers/isdn/hisax/ipacx.c +++ b/drivers/isdn/hisax/ipacx.c @@ -260,7 +260,7 @@ dch_empty_fifo(struct IsdnCardState *cs, int count) t += sprintf(t, "dch_empty_fifo() cnt %d", count); QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); + debugl1(cs, "%s", cs->dlog); } } @@ -307,7 +307,7 @@ dch_fill_fifo(struct IsdnCardState *cs) t += sprintf(t, "dch_fill_fifo() cnt %d", count); QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); + debugl1(cs, "%s", cs->dlog); } } @@ -539,7 +539,7 @@ bch_empty_fifo(struct BCState *bcs, int count) t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count); QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } @@ -582,7 +582,7 @@ bch_fill_fifo(struct BCState *bcs) t += sprintf(t, "chb_fill_fifo() B-%d cnt %d", hscx, count); QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c index a365ccc1c99c..7fdf78f46433 100644 --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c @@ -137,7 +137,7 @@ isac_empty_fifo(struct IsdnCardState *cs, int count) t += sprintf(t, "isac_empty_fifo cnt %d", count); QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); + debugl1(cs, "%s", cs->dlog); } } @@ -179,7 +179,7 @@ isac_fill_fifo(struct IsdnCardState *cs) t += sprintf(t, "isac_fill_fifo cnt %d", count); QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); + debugl1(cs, "%s", cs->dlog); } } diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index 7fdf34704fe5..f4956c73aa11 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -74,7 +74,7 @@ sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len, t = tmp; t += sprintf(t, "sendmbox cnt %d", len); QuickHex(t, &msg[len-i], (i > 64) ? 64 : i); - debugl1(cs, tmp); + debugl1(cs, "%s", tmp); i -= 64; } } @@ -105,7 +105,7 @@ rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg) t = tmp; t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb); QuickHex(t, &msg[ireg->clsb - i], (i > 64) ? 64 : i); - debugl1(cs, tmp); + debugl1(cs, "%s", tmp); i -= 64; } } @@ -1248,7 +1248,7 @@ isar_int_main(struct IsdnCardState *cs) tp += sprintf(debbuf, "msg iis(%x) msb(%x)", ireg->iis, ireg->cmsb); QuickHex(tp, (u_char *)ireg->par, ireg->clsb); - debugl1(cs, debbuf); + debugl1(cs, "%s", debbuf); } break; case ISAR_IIS_INVMSG: diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c index f946c58d8ab1..e2ae7871a209 100644 --- a/drivers/isdn/hisax/jade.c +++ b/drivers/isdn/hisax/jade.c @@ -81,10 +81,7 @@ modejade(struct BCState *bcs, int mode, int bc) int jade = bcs->hw.hscx.hscx; if (cs->debug & L1_DEB_HSCX) { - char tmp[40]; - sprintf(tmp, "jade %c mode %d ichan %d", - 'A' + jade, mode, bc); - debugl1(cs, tmp); + debugl1(cs, "jade %c mode %d ichan %d", 'A' + jade, mode, bc); } bcs->mode = mode; bcs->channel = bc; @@ -257,23 +254,18 @@ void clear_pending_jade_ints(struct IsdnCardState *cs) { int val; - char tmp[64]; cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00); cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00); val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR); - sprintf(tmp, "jade B ISTA %x", val); - debugl1(cs, tmp); + debugl1(cs, "jade B ISTA %x", val); val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR); - sprintf(tmp, "jade A ISTA %x", val); - debugl1(cs, tmp); + debugl1(cs, "jade A ISTA %x", val); val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR); - sprintf(tmp, "jade B STAR %x", val); - debugl1(cs, tmp); + debugl1(cs, "jade B STAR %x", val); val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR); - sprintf(tmp, "jade A STAR %x", val); - debugl1(cs, tmp); + debugl1(cs, "jade A STAR %x", val); /* Unmask ints */ cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8); cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8); diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c index f521fc83dc76..b930da9b5aa6 100644 --- a/drivers/isdn/hisax/jade_irq.c +++ b/drivers/isdn/hisax/jade_irq.c @@ -65,7 +65,7 @@ jade_empty_fifo(struct BCState *bcs, int count) t += sprintf(t, "jade_empty_fifo %c cnt %d", bcs->hw.hscx.hscx ? 'B' : 'A', count); QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } @@ -105,7 +105,7 @@ jade_fill_fifo(struct BCState *bcs) t += sprintf(t, "jade_fill_fifo %c cnt %d", bcs->hw.hscx.hscx ? 'B' : 'A', count); QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c index 4c1bca5caa1d..875402e76d0a 100644 --- a/drivers/isdn/hisax/l3_1tr6.c +++ b/drivers/isdn/hisax/l3_1tr6.c @@ -63,7 +63,7 @@ l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb) { dev_kfree_skb(skb); if (pc->st->l3.debug & L3_DEB_WARN) - l3_debug(pc->st, msg); + l3_debug(pc->st, "%s", msg); l3_1tr6_release_req(pc, 0, NULL); } @@ -161,7 +161,6 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg) { u_char *p; int bcfound = 0; - char tmp[80]; struct sk_buff *skb = arg; /* Channel Identification */ @@ -214,10 +213,9 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg) /* Signal all services, linklevel takes care of Service-Indicator */ if (bcfound) { if ((pc->para.setup.si1 != 7) && (pc->st->l3.debug & L3_DEB_WARN)) { - sprintf(tmp, "non-digital call: %s -> %s", + l3_debug(pc->st, "non-digital call: %s -> %s", pc->para.setup.phone, pc->para.setup.eazmsn); - l3_debug(pc->st, tmp); } newl3state(pc, 6); pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); @@ -301,7 +299,7 @@ l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg) { u_char *p; int i, tmpcharge = 0; - char a_charge[8], tmp[32]; + char a_charge[8]; struct sk_buff *skb = arg; p = skb->data; @@ -316,8 +314,8 @@ l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg) pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc); } if (pc->st->l3.debug & L3_DEB_CHARGE) { - sprintf(tmp, "charging info %d", pc->para.chargeinfo); - l3_debug(pc->st, tmp); + l3_debug(pc->st, "charging info %d", + pc->para.chargeinfo); } } else if (pc->st->l3.debug & L3_DEB_CHARGE) l3_debug(pc->st, "charging info not found"); @@ -399,7 +397,7 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg) struct sk_buff *skb = arg; u_char *p; int i, tmpcharge = 0; - char a_charge[8], tmp[32]; + char a_charge[8]; StopAllL3Timer(pc); p = skb->data; @@ -414,8 +412,8 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg) pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc); } if (pc->st->l3.debug & L3_DEB_CHARGE) { - sprintf(tmp, "charging info %d", pc->para.chargeinfo); - l3_debug(pc->st, tmp); + l3_debug(pc->st, "charging info %d", + pc->para.chargeinfo); } } else if (pc->st->l3.debug & L3_DEB_CHARGE) l3_debug(pc->st, "charging info not found"); @@ -746,7 +744,6 @@ up1tr6(struct PStack *st, int pr, void *arg) int i, mt, cr; struct l3_process *proc; struct sk_buff *skb = arg; - char tmp[80]; switch (pr) { case (DL_DATA | INDICATION): @@ -762,26 +759,23 @@ up1tr6(struct PStack *st, int pr, void *arg) } if (skb->len < 4) { if (st->l3.debug & L3_DEB_PROTERR) { - sprintf(tmp, "up1tr6 len only %d", skb->len); - l3_debug(st, tmp); + l3_debug(st, "up1tr6 len only %d", skb->len); } dev_kfree_skb(skb); return; } if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) { if (st->l3.debug & L3_DEB_PROTERR) { - sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %d", + l3_debug(st, "up1tr6%sunexpected discriminator %x message len %d", (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", skb->data[0], skb->len); - l3_debug(st, tmp); } dev_kfree_skb(skb); return; } if (skb->data[1] != 1) { if (st->l3.debug & L3_DEB_PROTERR) { - sprintf(tmp, "up1tr6 CR len not 1"); - l3_debug(st, tmp); + l3_debug(st, "up1tr6 CR len not 1"); } dev_kfree_skb(skb); return; @@ -791,9 +785,8 @@ up1tr6(struct PStack *st, int pr, void *arg) if (skb->data[0] == PROTO_DIS_N0) { dev_kfree_skb(skb); if (st->l3.debug & L3_DEB_STATE) { - sprintf(tmp, "up1tr6%s N0 mt %x unhandled", + l3_debug(st, "up1tr6%s N0 mt %x unhandled", (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt); - l3_debug(st, tmp); } } else if (skb->data[0] == PROTO_DIS_N1) { if (!(proc = getl3proc(st, cr))) { @@ -801,8 +794,7 @@ up1tr6(struct PStack *st, int pr, void *arg) if (cr < 128) { if (!(proc = new_l3_process(st, cr))) { if (st->l3.debug & L3_DEB_PROTERR) { - sprintf(tmp, "up1tr6 no roc mem"); - l3_debug(st, tmp); + l3_debug(st, "up1tr6 no roc mem"); } dev_kfree_skb(skb); return; @@ -821,8 +813,7 @@ up1tr6(struct PStack *st, int pr, void *arg) } else { if (!(proc = new_l3_process(st, cr))) { if (st->l3.debug & L3_DEB_PROTERR) { - sprintf(tmp, "up1tr6 no roc mem"); - l3_debug(st, tmp); + l3_debug(st, "up1tr6 no roc mem"); } dev_kfree_skb(skb); return; @@ -837,18 +828,16 @@ up1tr6(struct PStack *st, int pr, void *arg) if (i == ARRAY_SIZE(datastln1)) { dev_kfree_skb(skb); if (st->l3.debug & L3_DEB_STATE) { - sprintf(tmp, "up1tr6%sstate %d mt %x unhandled", + l3_debug(st, "up1tr6%sstate %d mt %x unhandled", (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", proc->state, mt); - l3_debug(st, tmp); } return; } else { if (st->l3.debug & L3_DEB_STATE) { - sprintf(tmp, "up1tr6%sstate %d mt %x", + l3_debug(st, "up1tr6%sstate %d mt %x", (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", proc->state, mt); - l3_debug(st, tmp); } datastln1[i].rout(proc, pr, skb); } @@ -861,7 +850,6 @@ down1tr6(struct PStack *st, int pr, void *arg) int i, cr; struct l3_process *proc; struct Channel *chan; - char tmp[80]; if ((DL_ESTABLISH | REQUEST) == pr) { l3_msg(st, pr, NULL); @@ -888,15 +876,13 @@ down1tr6(struct PStack *st, int pr, void *arg) break; if (i == ARRAY_SIZE(downstl)) { if (st->l3.debug & L3_DEB_STATE) { - sprintf(tmp, "down1tr6 state %d prim %d unhandled", + l3_debug(st, "down1tr6 state %d prim %d unhandled", proc->state, pr); - l3_debug(st, tmp); } } else { if (st->l3.debug & L3_DEB_STATE) { - sprintf(tmp, "down1tr6 state %d prim %d", + l3_debug(st, "down1tr6 state %d prim %d", proc->state, pr); - l3_debug(st, tmp); } downstl[i].rout(proc, pr, arg); } diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index b646eed379df..233e432e06f6 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -176,7 +176,7 @@ static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s else j = i; QuickHex(t, p, j); - debugl1(cs, tmp); + debugl1(cs, "%s", tmp); p += j; i -= j; t = tmp; diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c index 041bf52d9d0a..af1b020a81f1 100644 --- a/drivers/isdn/hisax/q931.c +++ b/drivers/isdn/hisax/q931.c @@ -1179,7 +1179,7 @@ LogFrame(struct IsdnCardState *cs, u_char *buf, int size) dp--; *dp++ = '\n'; *dp = 0; - HiSax_putstatus(cs, NULL, cs->dlog); + HiSax_putstatus(cs, NULL, "%s", cs->dlog); } else HiSax_putstatus(cs, "LogFrame: ", "warning Frame too big (%d)", size); } @@ -1246,7 +1246,7 @@ dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir) } if (finish) { *dp = 0; - HiSax_putstatus(cs, NULL, cs->dlog); + HiSax_putstatus(cs, NULL, "%s", cs->dlog); return; } if ((0xfe & buf[0]) == PROTO_DIS_N0) { /* 1TR6 */ @@ -1509,5 +1509,5 @@ dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir) dp += sprintf(dp, "Unknown protocol %x!", buf[0]); } *dp = 0; - HiSax_putstatus(cs, NULL, cs->dlog); + HiSax_putstatus(cs, NULL, "%s", cs->dlog); } diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c index d8cac6935818..a85895585d90 100644 --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c @@ -154,7 +154,7 @@ W6692_empty_fifo(struct IsdnCardState *cs, int count) t += sprintf(t, "W6692_empty_fifo cnt %d", count); QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); + debugl1(cs, "%s", cs->dlog); } } @@ -196,7 +196,7 @@ W6692_fill_fifo(struct IsdnCardState *cs) t += sprintf(t, "W6692_fill_fifo cnt %d", count); QuickHex(t, ptr, count); - debugl1(cs, cs->dlog); + debugl1(cs, "%s", cs->dlog); } } @@ -226,7 +226,7 @@ W6692B_empty_fifo(struct BCState *bcs, int count) t += sprintf(t, "W6692B_empty_fifo %c cnt %d", bcs->channel + '1', count); QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } @@ -264,7 +264,7 @@ W6692B_fill_fifo(struct BCState *bcs) t += sprintf(t, "W6692B_fill_fifo %c cnt %d", bcs->channel + '1', count); QuickHex(t, ptr, count); - debugl1(cs, bcs->blog); + debugl1(cs, "%s", bcs->blog); } } diff --git a/drivers/mailbox/mailbox-omap2.c b/drivers/mailbox/mailbox-omap2.c index eba380d7b17f..42d2b893ea67 100644 --- a/drivers/mailbox/mailbox-omap2.c +++ b/drivers/mailbox/mailbox-omap2.c @@ -325,7 +325,6 @@ static int omap2_mbox_remove(struct platform_device *pdev) kfree(privblk); kfree(mboxblk); kfree(list); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 5db900d917f9..dd03dfdfb0d6 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1236,7 +1236,6 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF static struct of_device_id pxa3xx_nand_dt_ids[] = { { .compatible = "marvell,pxa3xx-nand", @@ -1284,12 +1283,6 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev) return 0; } -#else -static inline int pxa3xx_nand_probe_dt(struct platform_device *pdev) -{ - return 0; -} -#endif static int pxa3xx_nand_probe(struct platform_device *pdev) { diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 91f179d5135c..f428ef574372 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -1472,7 +1472,7 @@ void bond_alb_monitor(struct work_struct *work) bond_info->lp_counter++; /* send learning packets */ - if (bond_info->lp_counter >= BOND_ALB_LP_TICKS) { + if (bond_info->lp_counter >= BOND_ALB_LP_TICKS(bond)) { /* change of curr_active_slave involves swapping of mac addresses. * in order to avoid this swapping from happening while * sending the learning packets, the curr_slave_lock must be held for diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h index 28d8e4c7dc06..c5eff5dafdfe 100644 --- a/drivers/net/bonding/bond_alb.h +++ b/drivers/net/bonding/bond_alb.h @@ -36,14 +36,15 @@ struct slave; * Used for division - never set * to zero !!! */ -#define BOND_ALB_LP_INTERVAL 1 /* In seconds, periodic send of - * learning packets to the switch - */ +#define BOND_ALB_DEFAULT_LP_INTERVAL 1 +#define BOND_ALB_LP_INTERVAL(bond) (bond->params.lp_interval) /* In seconds, periodic send of + * learning packets to the switch + */ #define BOND_TLB_REBALANCE_TICKS (BOND_TLB_REBALANCE_INTERVAL \ * ALB_TIMER_TICKS_PER_SEC) -#define BOND_ALB_LP_TICKS (BOND_ALB_LP_INTERVAL \ +#define BOND_ALB_LP_TICKS(bond) (BOND_ALB_LP_INTERVAL(bond) \ * ALB_TIMER_TICKS_PER_SEC) #define TLB_HASH_TABLE_SIZE 256 /* The size of the clients hash table. diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 72df399c4ab3..55bbb8b8200c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4416,6 +4416,7 @@ static int bond_check_params(struct bond_params *params) params->all_slaves_active = all_slaves_active; params->resend_igmp = resend_igmp; params->min_links = min_links; + params->lp_interval = BOND_ALB_DEFAULT_LP_INTERVAL; if (primary) { strncpy(params->primary, primary, IFNAMSIZ); diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index eeab40b01b7a..c29b836749b6 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1699,6 +1699,44 @@ out: static DEVICE_ATTR(resend_igmp, S_IRUGO | S_IWUSR, bonding_show_resend_igmp, bonding_store_resend_igmp); + +static ssize_t bonding_show_lp_interval(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct bonding *bond = to_bond(d); + return sprintf(buf, "%d\n", bond->params.lp_interval); +} + +static ssize_t bonding_store_lp_interval(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct bonding *bond = to_bond(d); + int new_value, ret = count; + + if (sscanf(buf, "%d", &new_value) != 1) { + pr_err("%s: no lp interval value specified.\n", + bond->dev->name); + ret = -EINVAL; + goto out; + } + + if (new_value <= 0) { + pr_err ("%s: lp_interval must be between 1 and %d\n", + bond->dev->name, INT_MAX); + ret = -EINVAL; + goto out; + } + + bond->params.lp_interval = new_value; +out: + return ret; +} + +static DEVICE_ATTR(lp_interval, S_IRUGO | S_IWUSR, + bonding_show_lp_interval, bonding_store_lp_interval); + static struct attribute *per_bond_attrs[] = { &dev_attr_slaves.attr, &dev_attr_mode.attr, @@ -1729,6 +1767,7 @@ static struct attribute *per_bond_attrs[] = { &dev_attr_all_slaves_active.attr, &dev_attr_resend_igmp.attr, &dev_attr_min_links.attr, + &dev_attr_lp_interval.attr, NULL, }; diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 7ad8bd5cc947..03cf3fd14490 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -176,6 +176,7 @@ struct bond_params { int tx_queues; int all_slaves_active; int resend_igmp; + int lp_interval; }; struct bond_parm_tbl { diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c index e66684a438f5..75fb1d20d6fd 100644 --- a/drivers/net/ethernet/adi/bfin_mac.c +++ b/drivers/net/ethernet/adi/bfin_mac.c @@ -530,7 +530,7 @@ static int bfin_mac_ethtool_setwol(struct net_device *dev, if (lp->wol && !lp->irq_wake_requested) { /* register wake irq handler */ rc = request_irq(IRQ_MAC_WAKEDET, bfin_mac_wake_interrupt, - IRQF_DISABLED, "EMAC_WAKE", dev); + 0, "EMAC_WAKE", dev); if (rc) return rc; lp->irq_wake_requested = true; @@ -1686,7 +1686,7 @@ static int bfin_mac_probe(struct platform_device *pdev) /* now, enable interrupts */ /* register irq handler */ rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt, - IRQF_DISABLED, "EMAC_RX", ndev); + 0, "EMAC_RX", ndev); if (rc) { dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n"); rc = -EBUSY; diff --git a/drivers/net/ethernet/amd/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c index d6b20296b8e4..3d8c6b2cdea4 100644 --- a/drivers/net/ethernet/amd/sun3lance.c +++ b/drivers/net/ethernet/amd/sun3lance.c @@ -358,7 +358,7 @@ static int __init lance_probe( struct net_device *dev) REGA(CSR0) = CSR0_STOP; - if (request_irq(LANCE_IRQ, lance_interrupt, IRQF_DISABLED, "SUN3 Lance", dev) < 0) { + if (request_irq(LANCE_IRQ, lance_interrupt, 0, "SUN3 Lance", dev) < 0) { #ifdef CONFIG_SUN3 iounmap((void __iomem *)ioaddr); #endif diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index 027398ebbba6..fc95b235e210 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -1188,7 +1188,7 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct alx_priv *alx; struct alx_hw *hw; bool phy_configured; - int bars, pm_cap, err; + int bars, err; err = pci_enable_device_mem(pdev); if (err) @@ -1225,18 +1225,13 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_enable_pcie_error_reporting(pdev); pci_set_master(pdev); - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap == 0) { + if (!pdev->pm_cap) { dev_err(&pdev->dev, "Can't find power management capability, aborting\n"); err = -EIO; goto out_pci_release; } - err = pci_set_power_state(pdev, PCI_D0); - if (err) - goto out_pci_release; - netdev = alloc_etherdev(sizeof(*alx)); if (!netdev) { err = -ENOMEM; diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index eec0af45b859..249468f95365 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -157,6 +157,7 @@ static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac, if (++ring->end >= BGMAC_TX_RING_SLOTS) ring->end = 0; bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX, + ring->index_base + ring->end * sizeof(struct bgmac_dma_desc)); /* Always keep one slot free to allow detecting bugged calls. */ @@ -181,6 +182,8 @@ static void bgmac_dma_tx_free(struct bgmac *bgmac, struct bgmac_dma_ring *ring) /* The last slot that hardware didn't consume yet */ empty_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS); empty_slot &= BGMAC_DMA_TX_STATDPTR; + empty_slot -= ring->index_base; + empty_slot &= BGMAC_DMA_TX_STATDPTR; empty_slot /= sizeof(struct bgmac_dma_desc); while (ring->start != empty_slot) { @@ -274,6 +277,8 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, end_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_STATUS); end_slot &= BGMAC_DMA_RX_STATDPTR; + end_slot -= ring->index_base; + end_slot &= BGMAC_DMA_RX_STATDPTR; end_slot /= sizeof(struct bgmac_dma_desc); ring->end = end_slot; @@ -418,9 +423,6 @@ static int bgmac_dma_alloc(struct bgmac *bgmac) ring = &bgmac->tx_ring[i]; ring->num_slots = BGMAC_TX_RING_SLOTS; ring->mmio_base = ring_base[i]; - if (bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_TX)) - bgmac_warn(bgmac, "TX on ring 0x%X supports unaligned addressing but this feature is not implemented\n", - ring->mmio_base); /* Alloc ring of descriptors */ size = ring->num_slots * sizeof(struct bgmac_dma_desc); @@ -435,6 +437,13 @@ static int bgmac_dma_alloc(struct bgmac *bgmac) if (ring->dma_base & 0xC0000000) bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n"); + ring->unaligned = bgmac_dma_unaligned(bgmac, ring, + BGMAC_DMA_RING_TX); + if (ring->unaligned) + ring->index_base = lower_32_bits(ring->dma_base); + else + ring->index_base = 0; + /* No need to alloc TX slots yet */ } @@ -444,9 +453,6 @@ static int bgmac_dma_alloc(struct bgmac *bgmac) ring = &bgmac->rx_ring[i]; ring->num_slots = BGMAC_RX_RING_SLOTS; ring->mmio_base = ring_base[i]; - if (bgmac_dma_unaligned(bgmac, ring, BGMAC_DMA_RING_RX)) - bgmac_warn(bgmac, "RX on ring 0x%X supports unaligned addressing but this feature is not implemented\n", - ring->mmio_base); /* Alloc ring of descriptors */ size = ring->num_slots * sizeof(struct bgmac_dma_desc); @@ -462,6 +468,13 @@ static int bgmac_dma_alloc(struct bgmac *bgmac) if (ring->dma_base & 0xC0000000) bgmac_warn(bgmac, "DMA address using 0xC0000000 bit(s), it may need translation trick\n"); + ring->unaligned = bgmac_dma_unaligned(bgmac, ring, + BGMAC_DMA_RING_RX); + if (ring->unaligned) + ring->index_base = lower_32_bits(ring->dma_base); + else + ring->index_base = 0; + /* Alloc RX slots */ for (j = 0; j < ring->num_slots; j++) { err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]); @@ -489,12 +502,14 @@ static void bgmac_dma_init(struct bgmac *bgmac) for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) { ring = &bgmac->tx_ring[i]; - /* We don't implement unaligned addressing, so enable first */ - bgmac_dma_tx_enable(bgmac, ring); + if (!ring->unaligned) + bgmac_dma_tx_enable(bgmac, ring); bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO, lower_32_bits(ring->dma_base)); bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGHI, upper_32_bits(ring->dma_base)); + if (ring->unaligned) + bgmac_dma_tx_enable(bgmac, ring); ring->start = 0; ring->end = 0; /* Points the slot that should *not* be read */ @@ -505,12 +520,14 @@ static void bgmac_dma_init(struct bgmac *bgmac) ring = &bgmac->rx_ring[i]; - /* We don't implement unaligned addressing, so enable first */ - bgmac_dma_rx_enable(bgmac, ring); + if (!ring->unaligned) + bgmac_dma_rx_enable(bgmac, ring); bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO, lower_32_bits(ring->dma_base)); bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGHI, upper_32_bits(ring->dma_base)); + if (ring->unaligned) + bgmac_dma_rx_enable(bgmac, ring); for (j = 0, dma_desc = ring->cpu_base; j < ring->num_slots; j++, dma_desc++) { @@ -531,6 +548,7 @@ static void bgmac_dma_init(struct bgmac *bgmac) } bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX, + ring->index_base + ring->num_slots * sizeof(struct bgmac_dma_desc)); ring->start = 0; @@ -908,10 +926,10 @@ static void bgmac_chip_reset(struct bgmac *bgmac) struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc; u8 et_swtype = 0; u8 sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHY | - BGMAC_CHIPCTL_1_IF_TYPE_RMII; - char buf[2]; + BGMAC_CHIPCTL_1_IF_TYPE_MII; + char buf[4]; - if (bcm47xx_nvram_getenv("et_swtype", buf, 1) > 0) { + if (bcm47xx_nvram_getenv("et_swtype", buf, sizeof(buf)) > 0) { if (kstrtou8(buf, 0, &et_swtype)) bgmac_err(bgmac, "Failed to parse et_swtype (%s)\n", buf); diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h index 98d4b5fcc070..66c8afbdc8c7 100644 --- a/drivers/net/ethernet/broadcom/bgmac.h +++ b/drivers/net/ethernet/broadcom/bgmac.h @@ -333,7 +333,7 @@ #define BGMAC_CHIPCTL_1_IF_TYPE_MASK 0x00000030 #define BGMAC_CHIPCTL_1_IF_TYPE_RMII 0x00000000 -#define BGMAC_CHIPCTL_1_IF_TYPE_MI 0x00000010 +#define BGMAC_CHIPCTL_1_IF_TYPE_MII 0x00000010 #define BGMAC_CHIPCTL_1_IF_TYPE_RGMII 0x00000020 #define BGMAC_CHIPCTL_1_SW_TYPE_MASK 0x000000C0 #define BGMAC_CHIPCTL_1_SW_TYPE_EPHY 0x00000000 @@ -384,6 +384,8 @@ struct bgmac_dma_ring { u16 mmio_base; struct bgmac_dma_desc *cpu_base; dma_addr_t dma_base; + u32 index_base; /* Used for unaligned rings only, otherwise 0 */ + bool unaligned; struct bgmac_slot_info slots[BGMAC_RX_RING_SLOTS]; }; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 0c338026ce01..97b3d32a98bd 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -246,8 +246,37 @@ enum { BNX2X_MAX_CNIC_ETH_CL_ID_IDX, }; -#define BNX2X_CNIC_START_ETH_CID(bp) (BNX2X_NUM_NON_CNIC_QUEUES(bp) *\ +/* use a value high enough to be above all the PFs, which has least significant + * nibble as 8, so when cnic needs to come up with a CID for UIO to use to + * calculate doorbell address according to old doorbell configuration scheme + * (db_msg_sz 1 << 7 * cid + 0x40 DPM offset) it can come up with a valid number + * We must avoid coming up with cid 8 for iscsi since according to this method + * the designated UIO cid will come out 0 and it has a special handling for that + * case which doesn't suit us. Therefore will will cieling to closes cid which + * has least signigifcant nibble 8 and if it is 8 we will move forward to 0x18. + */ + +#define BNX2X_1st_NON_L2_ETH_CID(bp) (BNX2X_NUM_NON_CNIC_QUEUES(bp) * \ (bp)->max_cos) +/* amount of cids traversed by UIO's DPM addition to doorbell */ +#define UIO_DPM 8 +/* roundup to DPM offset */ +#define UIO_ROUNDUP(bp) (roundup(BNX2X_1st_NON_L2_ETH_CID(bp), \ + UIO_DPM)) +/* offset to nearest value which has lsb nibble matching DPM */ +#define UIO_CID_OFFSET(bp) ((UIO_ROUNDUP(bp) + UIO_DPM) % \ + (UIO_DPM * 2)) +/* add offset to rounded-up cid to get a value which could be used with UIO */ +#define UIO_DPM_ALIGN(bp) (UIO_ROUNDUP(bp) + UIO_CID_OFFSET(bp)) +/* but wait - avoid UIO special case for cid 0 */ +#define UIO_DPM_CID0_OFFSET(bp) ((UIO_DPM * 2) * \ + (UIO_DPM_ALIGN(bp) == UIO_DPM)) +/* Properly DPM aligned CID dajusted to cid 0 secal case */ +#define BNX2X_CNIC_START_ETH_CID(bp) (UIO_DPM_ALIGN(bp) + \ + (UIO_DPM_CID0_OFFSET(bp))) +/* how many cids were wasted - need this value for cid allocation */ +#define UIO_CID_PAD(bp) (BNX2X_CNIC_START_ETH_CID(bp) - \ + BNX2X_1st_NON_L2_ETH_CID(bp)) /* iSCSI L2 */ #define BNX2X_ISCSI_ETH_CID(bp) (BNX2X_CNIC_START_ETH_CID(bp)) /* FCoE L2 */ @@ -1542,7 +1571,6 @@ struct bnx2x { */ bool fcoe_init; - int pm_cap; int mrrs; struct delayed_work sp_task; @@ -1681,10 +1709,11 @@ struct bnx2x { * Maximum CID count that might be required by the bnx2x: * Max RSS * Max_Tx_Multi_Cos + FCoE + iSCSI */ + #define BNX2X_L2_CID_COUNT(bp) (BNX2X_NUM_ETH_QUEUES(bp) * BNX2X_MULTI_TX_COS \ - + 2 * CNIC_SUPPORT(bp)) + + CNIC_SUPPORT(bp) * (2 + UIO_CID_PAD(bp))) #define BNX2X_L2_MAX_CID(bp) (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS \ - + 2 * CNIC_SUPPORT(bp)) + + CNIC_SUPPORT(bp) * (2 + UIO_CID_PAD(bp))) #define L2_ILT_LINES(bp) (DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\ ILT_PAGE_CIDS)) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 90045c920d09..61726af1de6e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -3008,16 +3008,16 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) u16 pmcsr; /* If there is no power capability, silently succeed */ - if (!bp->pm_cap) { + if (!bp->pdev->pm_cap) { BNX2X_DEV_INFO("No power capability. Breaking.\n"); return 0; } - pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr); + pci_read_config_word(bp->pdev, bp->pdev->pm_cap + PCI_PM_CTRL, &pmcsr); switch (state) { case PCI_D0: - pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, + pci_write_config_word(bp->pdev, bp->pdev->pm_cap + PCI_PM_CTRL, ((pmcsr & ~PCI_PM_CTRL_STATE_MASK) | PCI_PM_CTRL_PME_STATUS)); @@ -3041,7 +3041,7 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) if (bp->wol) pmcsr |= PCI_PM_CTRL_PME_ENABLE; - pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, + pci_write_config_word(bp->pdev, bp->pdev->pm_cap + PCI_PM_CTRL, pmcsr); /* No more memory access after this point until diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 2612e3c715d4..324de5f05332 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1387,9 +1387,9 @@ static bool bnx2x_is_nvm_accessible(struct bnx2x *bp) u16 pm = 0; struct net_device *dev = pci_get_drvdata(bp->pdev); - if (bp->pm_cap) + if (bp->pdev->pm_cap) rc = pci_read_config_word(bp->pdev, - bp->pm_cap + PCI_PM_CTRL, &pm); + bp->pdev->pm_cap + PCI_PM_CTRL, &pm); if ((rc && !netif_running(dev)) || (!rc && ((pm & PCI_PM_CTRL_STATE_MASK) != (__force u16)PCI_D0))) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 2f8dbbbd7a86..a6704b555042 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -8652,6 +8652,7 @@ u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode) else if (bp->wol) { u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; u8 *mac_addr = bp->dev->dev_addr; + struct pci_dev *pdev = bp->pdev; u32 val; u16 pmc; @@ -8668,9 +8669,9 @@ u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode) EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val); /* Enable the PME and clear the status */ - pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmc); + pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmc); pmc |= PCI_PM_CTRL_PME_ENABLE | PCI_PM_CTRL_PME_STATUS; - pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, pmc); + pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, pmc); reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN; @@ -10399,7 +10400,7 @@ static void bnx2x_get_common_hwinfo(struct bnx2x *bp) break; } - pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc); + pci_read_config_word(bp->pdev, bp->pdev->pm_cap + PCI_PM_PMC, &pmc); bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG; BNX2X_DEV_INFO("%sWoL capable\n", @@ -12141,8 +12142,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, } if (IS_PF(bp)) { - bp->pm_cap = pdev->pm_cap; - if (bp->pm_cap == 0) { + if (!pdev->pm_cap) { dev_err(&bp->pdev->dev, "Cannot find power management capability, aborting\n"); rc = -EIO; @@ -13632,6 +13632,10 @@ void bnx2x_setup_cnic_info(struct bnx2x *bp) cp->fcoe_init_cid = BNX2X_FCOE_ETH_CID(bp); cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID(bp); + DP(NETIF_MSG_IFUP, "BNX2X_1st_NON_L2_ETH_CID(bp) %x, cp->starting_cid %x, cp->fcoe_init_cid %x, cp->iscsi_l2_cid %x\n", + BNX2X_1st_NON_L2_ETH_CID(bp), cp->starting_cid, cp->fcoe_init_cid, + cp->iscsi_l2_cid); + if (NO_ISCSI_OOO(bp)) cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI_OOO; } diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index 8142480d9770..99394bd49a13 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c @@ -3135,6 +3135,7 @@ static void cnic_service_bnx2x_bh(unsigned long data) { struct cnic_dev *dev = (struct cnic_dev *) data; struct cnic_local *cp = dev->cnic_priv; + struct bnx2x *bp = netdev_priv(dev->netdev); u32 status_idx, new_status_idx; if (unlikely(!test_bit(CNIC_F_CNIC_UP, &dev->flags))) @@ -3146,7 +3147,7 @@ static void cnic_service_bnx2x_bh(unsigned long data) CNIC_WR16(dev, cp->kcq1.io_addr, cp->kcq1.sw_prod_idx + MAX_KCQ_IDX); - if (cp->ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE) { + if (!CNIC_SUPPORTS_FCOE(bp)) { cp->arm_int(dev, status_idx); break; } @@ -5217,7 +5218,8 @@ static void cnic_init_rings(struct cnic_dev *dev) "iSCSI CLIENT_SETUP did not complete\n"); cnic_spq_completion(dev, DRV_CTL_RET_L2_SPQ_CREDIT_CMD, 1); cnic_ring_ctl(dev, cid, cli, 1); - *cid_ptr = cid; + *cid_ptr = cid >> 4; + *(cid_ptr + 1) = cid * bp->db_size; } } diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 5701f3d1a169..12d961c4ebca 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -3034,6 +3034,7 @@ static bool tg3_phy_led_bug(struct tg3 *tp) { switch (tg3_asic_rev(tp)) { case ASIC_REV_5719: + case ASIC_REV_5720: if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) && !tp->pci_fn) return true; @@ -16192,12 +16193,12 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent) * So explicitly force the chip into D0 here. */ pci_read_config_dword(tp->pdev, - tp->pm_cap + PCI_PM_CTRL, + tp->pdev->pm_cap + PCI_PM_CTRL, &pm_reg); pm_reg &= ~PCI_PM_CTRL_STATE_MASK; pm_reg |= PCI_PM_CTRL_PME_ENABLE | 0 /* D0 */; pci_write_config_dword(tp->pdev, - tp->pm_cap + PCI_PM_CTRL, + tp->pdev->pm_cap + PCI_PM_CTRL, pm_reg); /* Also, force SERR#/PERR# in PCI command. */ @@ -17346,7 +17347,6 @@ static int tg3_init_one(struct pci_dev *pdev, tp = netdev_priv(dev); tp->pdev = pdev; tp->dev = dev; - tp->pm_cap = pdev->pm_cap; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; tp->irq_sync = 1; diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h index ddb8be1298ea..70257808aa37 100644 --- a/drivers/net/ethernet/broadcom/tg3.h +++ b/drivers/net/ethernet/broadcom/tg3.h @@ -3234,7 +3234,6 @@ struct tg3 { u8 pci_lat_timer; int pci_fn; - int pm_cap; int msi_cap; int pcix_cap; int pcie_readrq; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 0d0665ca6f19..c73cabdbd4c0 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -6149,8 +6149,10 @@ static int __init cxgb4_init_module(void) pr_warn("could not create debugfs entry, continuing\n"); ret = pci_register_driver(&cxgb4_driver); - if (ret < 0) + if (ret < 0) { debugfs_remove(cxgb4_debugfs_root); + destroy_workqueue(workq); + } register_inet6addr_notifier(&cxgb4_inet6addr_notifier); diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c index 2db6c573cec7..263b92c00cbf 100644 --- a/drivers/net/ethernet/dec/tulip/de4x5.c +++ b/drivers/net/ethernet/dec/tulip/de4x5.c @@ -1321,7 +1321,7 @@ de4x5_open(struct net_device *dev) if (request_irq(dev->irq, de4x5_interrupt, IRQF_SHARED, lp->adapter_name, dev)) { printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq); - if (request_irq(dev->irq, de4x5_interrupt, IRQF_DISABLED | IRQF_SHARED, + if (request_irq(dev->irq, de4x5_interrupt, IRQF_SHARED, lp->adapter_name, dev)) { printk("\n Cannot get IRQ- reconfigure your hardware.\n"); disable_ast(dev); diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 3224d28cdad4..100b528b9bd0 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -2802,7 +2802,7 @@ static int be_vfs_if_create(struct be_adapter *adapter) struct be_resources res = {0}; struct be_vf_cfg *vf_cfg; u32 cap_flags, en_flags, vf; - int status; + int status = 0; cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_MULTICAST; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index f9aacf5d8523..b2793b91cc55 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2199,7 +2199,7 @@ fec_probe(struct platform_device *pdev) goto failed_irq; } ret = devm_request_irq(&pdev->dev, irq, fec_enet_interrupt, - IRQF_DISABLED, pdev->name, ndev); + 0, pdev->name, ndev); if (ret) goto failed_irq; } diff --git a/drivers/net/ethernet/hp/hp100.c b/drivers/net/ethernet/hp/hp100.c index e3c7c697fc45..91227d03274e 100644 --- a/drivers/net/ethernet/hp/hp100.c +++ b/drivers/net/ethernet/hp/hp100.c @@ -1097,7 +1097,7 @@ static int hp100_open(struct net_device *dev) /* New: if bus is PCI or EISA, interrupts might be shared interrupts */ if (request_irq(dev->irq, hp100_interrupt, lp->bus == HP100_BUS_PCI || lp->bus == - HP100_BUS_EISA ? IRQF_SHARED : IRQF_DISABLED, + HP100_BUS_EISA ? IRQF_SHARED : 0, "hp100", dev)) { printk("hp100: %s: unable to get IRQ %d\n", dev->name, dev->irq); return -EAGAIN; diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 35853b43d66e..2d1c6bdd3618 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -102,6 +102,19 @@ static int ehea_probe_adapter(struct platform_device *dev); static int ehea_remove(struct platform_device *dev); +static struct of_device_id ehea_module_device_table[] = { + { + .name = "lhea", + .compatible = "IBM,lhea", + }, + { + .type = "network", + .compatible = "IBM,lhea-ethernet", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, ehea_module_device_table); + static struct of_device_id ehea_device_table[] = { { .name = "lhea", @@ -109,7 +122,6 @@ static struct of_device_id ehea_device_table[] = { }, {}, }; -MODULE_DEVICE_TABLE(of, ehea_device_table); static struct platform_driver ehea_driver = { .driver = { @@ -1285,7 +1297,7 @@ static int ehea_reg_interrupts(struct net_device *dev) ret = ibmebus_request_irq(port->qp_eq->attr.ist1, ehea_qp_aff_irq_handler, - IRQF_DISABLED, port->int_aff_name, port); + 0, port->int_aff_name, port); if (ret) { netdev_err(dev, "failed registering irq for qp_aff_irq_handler:ist=%X\n", port->qp_eq->attr.ist1); @@ -1303,8 +1315,7 @@ static int ehea_reg_interrupts(struct net_device *dev) "%s-queue%d", dev->name, i); ret = ibmebus_request_irq(pr->eq->attr.ist1, ehea_recv_irq_handler, - IRQF_DISABLED, pr->int_send_name, - pr); + 0, pr->int_send_name, pr); if (ret) { netdev_err(dev, "failed registering irq for ehea_queue port_res_nr:%d, ist=%X\n", i, pr->eq->attr.ist1); @@ -3320,7 +3331,7 @@ static int ehea_probe_adapter(struct platform_device *dev) } ret = ibmebus_request_irq(adapter->neq->attr.ist1, - ehea_interrupt_neq, IRQF_DISABLED, + ehea_interrupt_neq, 0, "ehea_neq", adapter); if (ret) { dev_err(&dev->dev, "requesting NEQ IRQ failed\n"); diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index a8633b8f0ac5..d14c8f53384c 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -922,6 +922,14 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) else mask &= ~(1 << 30); } + if (mac->type == e1000_pch2lan) { + /* SHRAH[0,1,2] different than previous */ + if (i == 7) + mask &= 0xFFF4FFFF; + /* SHRAH[3] different than SHRAH[0,1,2] */ + if (i == 10) + mask |= (1 << 30); + } REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), mask, 0xFFFFFFFF); diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index af08188d7e62..42f0f6717511 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1371,7 +1371,10 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) return; } - if (index < hw->mac.rar_entry_count) { + /* RAR[1-6] are owned by manageability. Skip those and program the + * next address into the SHRA register array. + */ + if (index < (u32)(hw->mac.rar_entry_count - 6)) { s32 ret_val; ret_val = e1000_acquire_swflag_ich8lan(hw); @@ -1962,8 +1965,8 @@ void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw) if (ret_val) goto release; - /* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */ - for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { + /* Copy both RAL/H (rar_entry_count) and SHRAL/H to PHY */ + for (i = 0; i < (hw->mac.rar_entry_count); i++) { mac_reg = er32(RAL(i)); hw->phy.ops.write_reg_page(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF)); @@ -2007,10 +2010,10 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) return ret_val; if (enable) { - /* Write Rx addresses (rar_entry_count for RAL/H, +4 for + /* Write Rx addresses (rar_entry_count for RAL/H, and * SHRAL/H) and initial CRC values to the MAC */ - for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { + for (i = 0; i < hw->mac.rar_entry_count; i++) { u8 mac_addr[ETH_ALEN] = { 0 }; u32 addr_high, addr_low; diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h index 59865695b282..217090df33e7 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.h +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h @@ -98,7 +98,7 @@ #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL #define E1000_ICH_RAR_ENTRIES 7 -#define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */ +#define E1000_PCH2_RAR_ENTRIES 11 /* RAR[0-6], SHRA[0-3] */ #define E1000_PCH_LPT_RAR_ENTRIES 12 /* RAR[0], SHRA[0-10] */ #define PHY_PAGE_SHIFT 5 diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index e87e9b01f404..4ef786775acb 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -4868,7 +4868,7 @@ static void e1000_watchdog_task(struct work_struct *work) */ if ((hw->phy.type == e1000_phy_igp_3 || hw->phy.type == e1000_phy_bm) && - (hw->mac.autoneg == true) && + hw->mac.autoneg && (adapter->link_speed == SPEED_10 || adapter->link_speed == SPEED_100) && (adapter->link_duplex == HALF_DUPLEX)) { diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index 79b58353d849..47c2d10df826 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -719,6 +719,10 @@ static s32 igb_get_phy_id_82575(struct e1000_hw *hw) u32 ctrl_ext; u32 mdic; + /* Extra read required for some PHY's on i354 */ + if (hw->mac.type == e1000_i354) + igb_get_phy_id(hw); + /* For SGMII PHYs, we try the list of possible addresses until * we find one that works. For non-SGMII PHYs * (e.g. integrated copper PHYs), an address of 1 should diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c index f0dfd41dd4bd..298f0ed50670 100644 --- a/drivers/net/ethernet/intel/igb/e1000_mac.c +++ b/drivers/net/ethernet/intel/igb/e1000_mac.c @@ -712,6 +712,7 @@ static s32 igb_set_fc_watermarks(struct e1000_hw *hw) static s32 igb_set_default_fc(struct e1000_hw *hw) { s32 ret_val = 0; + u16 lan_offset; u16 nvm_data; /* Read and store word 0x0F of the EEPROM. This word contains bits @@ -722,7 +723,14 @@ static s32 igb_set_default_fc(struct e1000_hw *hw) * control setting, then the variable hw->fc will * be initialized based on a value in the EEPROM. */ - ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); + if (hw->mac.type == e1000_i350) { + lan_offset = NVM_82580_LAN_FUNC_OFFSET(hw->bus.func); + ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG + + lan_offset, 1, &nvm_data); + } else { + ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, + 1, &nvm_data); + } if (ret_val) { hw_dbg("NVM Read Error\n"); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 0e1b973659b0..e8649abf97c0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -160,6 +160,13 @@ static int ixgbe_get_settings(struct net_device *netdev, bool autoneg = false; bool link_up; + /* SFP type is needed for get_link_capabilities */ + if (hw->phy.media_type & (ixgbe_media_type_fiber | + ixgbe_media_type_fiber_qsfp)) { + if (hw->phy.sfp_type == ixgbe_sfp_type_not_present) + hw->phy.ops.identify_sfp(hw); + } + hw->mac.ops.get_link_capabilities(hw, &supported_link, &autoneg); /* set the supported link speeds */ @@ -186,6 +193,11 @@ static int ixgbe_get_settings(struct net_device *netdev, ecmd->advertising |= ADVERTISED_1000baseT_Full; if (supported_link & IXGBE_LINK_SPEED_100_FULL) ecmd->advertising |= ADVERTISED_100baseT_Full; + + if (hw->phy.multispeed_fiber && !autoneg) { + if (supported_link & IXGBE_LINK_SPEED_10GB_FULL) + ecmd->advertising = ADVERTISED_10000baseT_Full; + } } if (autoneg) { @@ -314,6 +326,14 @@ static int ixgbe_set_settings(struct net_device *netdev, if (ecmd->advertising & ~ecmd->supported) return -EINVAL; + /* only allow one speed at a time if no autoneg */ + if (!ecmd->autoneg && hw->phy.multispeed_fiber) { + if (ecmd->advertising == + (ADVERTISED_10000baseT_Full | + ADVERTISED_1000baseT_Full)) + return -EINVAL; + } + old = hw->phy.autoneg_advertised; advertised = 0; if (ecmd->advertising & ADVERTISED_10000baseT_Full) @@ -1805,6 +1825,10 @@ static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter) unsigned int size = 1024; netdev_tx_t tx_ret_val; struct sk_buff *skb; + u32 flags_orig = adapter->flags; + + /* DCB can modify the frames on Tx */ + adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED; /* allocate test skb */ skb = alloc_skb(size, GFP_KERNEL); @@ -1857,6 +1881,7 @@ static int ixgbe_run_loopback_test(struct ixgbe_adapter *adapter) /* free the original skb */ kfree_skb(skb); + adapter->flags = flags_orig; return ret_val; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 7aba452833e5..0ade0cd5ef53 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3571,7 +3571,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; int i; - u32 rxctrl; + u32 rxctrl, rfctl; /* disable receives while setting up the descriptors */ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); @@ -3580,6 +3580,13 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) ixgbe_setup_psrtype(adapter); ixgbe_setup_rdrxctl(adapter); + /* RSC Setup */ + rfctl = IXGBE_READ_REG(hw, IXGBE_RFCTL); + rfctl &= ~IXGBE_RFCTL_RSC_DIS; + if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)) + rfctl |= IXGBE_RFCTL_RSC_DIS; + IXGBE_WRITE_REG(hw, IXGBE_RFCTL, rfctl); + /* Program registers for the distribution of queues */ ixgbe_setup_mrqc(adapter); @@ -5993,8 +6000,16 @@ static void ixgbe_sfp_link_config_subtask(struct ixgbe_adapter *adapter) adapter->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG; speed = hw->phy.autoneg_advertised; - if ((!speed) && (hw->mac.ops.get_link_capabilities)) + if ((!speed) && (hw->mac.ops.get_link_capabilities)) { hw->mac.ops.get_link_capabilities(hw, &speed, &autoneg); + + /* setup the highest link when no autoneg */ + if (!autoneg) { + if (speed & IXGBE_LINK_SPEED_10GB_FULL) + speed = IXGBE_LINK_SPEED_10GB_FULL; + } + } + if (hw->mac.ops.setup_link) hw->mac.ops.setup_link(hw, speed, true); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 6442cf8f9dce..10775cb9b6d8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -1861,6 +1861,7 @@ enum { #define IXGBE_RFCTL_ISCSI_DIS 0x00000001 #define IXGBE_RFCTL_ISCSI_DWC_MASK 0x0000003E #define IXGBE_RFCTL_ISCSI_DWC_SHIFT 1 +#define IXGBE_RFCTL_RSC_DIS 0x00000020 #define IXGBE_RFCTL_NFSW_DIS 0x00000040 #define IXGBE_RFCTL_NFSR_DIS 0x00000080 #define IXGBE_RFCTL_NFS_VER_MASK 0x00000300 diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index bfdb06860397..6a6c1f76d8e0 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -282,8 +282,7 @@ ltq_etop_hw_init(struct net_device *dev) if (IS_TX(i)) { ltq_dma_alloc_tx(&ch->dma); - request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED, - "etop_tx", priv); + request_irq(irq, ltq_etop_dma_irq, 0, "etop_tx", priv); } else if (IS_RX(i)) { ltq_dma_alloc_rx(&ch->dma); for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM; @@ -291,8 +290,7 @@ ltq_etop_hw_init(struct net_device *dev) if (ltq_etop_alloc_skb(ch)) return -ENOMEM; ch->dma.desc = 0; - request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED, - "etop_rx", priv); + request_irq(irq, ltq_etop_dma_irq, 0, "etop_rx", priv); } ch->dma.irq = irq; } diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 4ae0c7426010..fff62460185c 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -1123,8 +1123,7 @@ static int pxa168_eth_open(struct net_device *dev) struct pxa168_eth_private *pep = netdev_priv(dev); int err; - err = request_irq(dev->irq, pxa168_eth_int_handler, - IRQF_DISABLED, dev->name, dev); + err = request_irq(dev->irq, pxa168_eth_int_handler, 0, dev->name, dev); if (err) { dev_err(&dev->dev, "can't assign irq\n"); return -EAGAIN; diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index ef94a591f9e5..1a9c4f6269ea 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -3092,6 +3092,9 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, if (!nskb) goto resubmit; + skb = e->skb; + prefetch(skb->data); + if (skge_rx_setup(skge, e, nskb, skge->rx_buf_size) < 0) { dev_kfree_skb(nskb); goto resubmit; @@ -3101,8 +3104,6 @@ static struct sk_buff *skge_rx_get(struct net_device *dev, dma_unmap_addr(e, mapaddr), dma_unmap_len(e, maplen), PCI_DMA_FROMDEVICE); - skb = e->skb; - prefetch(skb->data); } skb_put(skb, len); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index a28cd801a236..0c750985f47e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -53,9 +53,11 @@ static int mlx4_en_moderation_update(struct mlx4_en_priv *priv) for (i = 0; i < priv->tx_ring_num; i++) { priv->tx_cq[i].moder_cnt = priv->tx_frames; priv->tx_cq[i].moder_time = priv->tx_usecs; - err = mlx4_en_set_cq_moder(priv, &priv->tx_cq[i]); - if (err) - return err; + if (priv->port_up) { + err = mlx4_en_set_cq_moder(priv, &priv->tx_cq[i]); + if (err) + return err; + } } if (priv->adaptive_rx_coal) @@ -65,9 +67,11 @@ static int mlx4_en_moderation_update(struct mlx4_en_priv *priv) priv->rx_cq[i].moder_cnt = priv->rx_frames; priv->rx_cq[i].moder_time = priv->rx_usecs; priv->last_moder_time[i] = MLX4_EN_AUTO_CONF; - err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]); - if (err) - return err; + if (priv->port_up) { + err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]); + if (err) + return err; + } } return err; diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index 0fba1532d326..075f4e21d33d 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c @@ -915,7 +915,7 @@ static int ks_net_open(struct net_device *netdev) struct ks_net *ks = netdev_priv(netdev); int err; -#define KS_INT_FLAGS (IRQF_DISABLED|IRQF_TRIGGER_LOW) +#define KS_INT_FLAGS IRQF_TRIGGER_LOW /* lock the card, even if we may not actually do anything * else at the moment. */ diff --git a/drivers/net/ethernet/natsemi/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c index c20766c2f65b..79257f71c5d9 100644 --- a/drivers/net/ethernet/natsemi/jazzsonic.c +++ b/drivers/net/ethernet/natsemi/jazzsonic.c @@ -83,8 +83,7 @@ static int jazzsonic_open(struct net_device* dev) { int retval; - retval = request_irq(dev->irq, sonic_interrupt, IRQF_DISABLED, - "sonic", dev); + retval = request_irq(dev->irq, sonic_interrupt, 0, "sonic", dev); if (retval) { printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c index c2e0256fe3df..4da172ac5599 100644 --- a/drivers/net/ethernet/natsemi/xtsonic.c +++ b/drivers/net/ethernet/natsemi/xtsonic.c @@ -95,8 +95,7 @@ static int xtsonic_open(struct net_device *dev) { int retval; - retval = request_irq(dev->irq, sonic_interrupt, IRQF_DISABLED, - "sonic", dev); + retval = request_irq(dev->irq, sonic_interrupt, 0, "sonic", dev); if (retval) { printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index c498181a9aa8..5b65356e7568 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -1219,7 +1219,7 @@ static int pasemi_mac_open(struct net_device *dev) snprintf(mac->tx_irq_name, sizeof(mac->tx_irq_name), "%s tx", dev->name); - ret = request_irq(mac->tx->chan.irq, pasemi_mac_tx_intr, IRQF_DISABLED, + ret = request_irq(mac->tx->chan.irq, pasemi_mac_tx_intr, 0, mac->tx_irq_name, mac->tx); if (ret) { dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n", @@ -1230,7 +1230,7 @@ static int pasemi_mac_open(struct net_device *dev) snprintf(mac->rx_irq_name, sizeof(mac->rx_irq_name), "%s rx", dev->name); - ret = request_irq(mac->rx->chan.irq, pasemi_mac_rx_intr, IRQF_DISABLED, + ret = request_irq(mac->rx->chan.irq, pasemi_mac_rx_intr, 0, mac->rx_irq_name, mac->rx); if (ret) { dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n", diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 652cc13c5023..392b9bd12b4f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c @@ -1561,6 +1561,7 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter) { int err; + adapter->need_fw_reset = 0; qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox); qlcnic_83xx_enable_mbx_interrupt(adapter); diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 6f87f2cde647..3397cee89777 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -4231,6 +4231,7 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_23: case RTL_GIGA_MAC_VER_24: case RTL_GIGA_MAC_VER_34: + case RTL_GIGA_MAC_VER_35: RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST); break; case RTL_GIGA_MAC_VER_40: diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig index 8b7152565c5e..088921294448 100644 --- a/drivers/net/ethernet/sfc/Kconfig +++ b/drivers/net/ethernet/sfc/Kconfig @@ -7,7 +7,7 @@ config SFC select I2C_ALGOBIT select PTP_1588_CLOCK ---help--- - This driver supports 10-gigabit Ethernet cards based on + This driver supports 10/40-gigabit Ethernet cards based on the Solarflare SFC4000, SFC9000-family and SFC9100-family controllers. diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 5f42313b4965..9f18ae984f9e 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -94,7 +94,7 @@ static unsigned int efx_ef10_mem_map_size(struct efx_nic *efx) return resource_size(&efx->pci_dev->resource[EFX_MEM_BAR]); } -static int efx_ef10_init_capabilities(struct efx_nic *efx) +static int efx_ef10_init_datapath_caps(struct efx_nic *efx) { MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_OUT_LEN); struct efx_ef10_nic_data *nic_data = efx->nic_data; @@ -107,16 +107,27 @@ static int efx_ef10_init_capabilities(struct efx_nic *efx) outbuf, sizeof(outbuf), &outlen); if (rc) return rc; + if (outlen < sizeof(outbuf)) { + netif_err(efx, drv, efx->net_dev, + "unable to read datapath firmware capabilities\n"); + return -EIO; + } - if (outlen >= sizeof(outbuf)) { - nic_data->datapath_caps = - MCDI_DWORD(outbuf, GET_CAPABILITIES_OUT_FLAGS1); - if (!(nic_data->datapath_caps & - (1 << MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN))) { - netif_err(efx, drv, efx->net_dev, - "Capabilities don't indicate TSO support.\n"); - return -ENODEV; - } + nic_data->datapath_caps = + MCDI_DWORD(outbuf, GET_CAPABILITIES_OUT_FLAGS1); + + if (!(nic_data->datapath_caps & + (1 << MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN))) { + netif_err(efx, drv, efx->net_dev, + "current firmware does not support TSO\n"); + return -ENODEV; + } + + if (!(nic_data->datapath_caps & + (1 << MC_CMD_GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14_LBN))) { + netif_err(efx, probe, efx->net_dev, + "current firmware does not support an RX prefix\n"); + return -ENODEV; } return 0; @@ -217,21 +228,13 @@ static int efx_ef10_probe(struct efx_nic *efx) if (rc) goto fail3; - rc = efx_ef10_init_capabilities(efx); + rc = efx_ef10_init_datapath_caps(efx); if (rc < 0) goto fail3; efx->rx_packet_len_offset = ES_DZ_RX_PREFIX_PKTLEN_OFST - ES_DZ_RX_PREFIX_SIZE; - if (!(nic_data->datapath_caps & - (1 << MC_CMD_GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14_LBN))) { - netif_err(efx, probe, efx->net_dev, - "current firmware does not support an RX prefix\n"); - rc = -ENODEV; - goto fail3; - } - rc = efx_mcdi_port_get_number(efx); if (rc < 0) goto fail3; @@ -260,8 +263,6 @@ static int efx_ef10_probe(struct efx_nic *efx) if (rc) goto fail3; - efx_ptp_probe(efx); - return 0; fail3: @@ -342,6 +343,13 @@ static int efx_ef10_init_nic(struct efx_nic *efx) struct efx_ef10_nic_data *nic_data = efx->nic_data; int rc; + if (nic_data->must_check_datapath_caps) { + rc = efx_ef10_init_datapath_caps(efx); + if (rc) + return rc; + nic_data->must_check_datapath_caps = false; + } + if (nic_data->must_realloc_vis) { /* We cannot let the number of VIs change now */ rc = efx_ef10_alloc_vis(efx, nic_data->n_allocated_vis, @@ -710,6 +718,14 @@ static int efx_ef10_mcdi_poll_reboot(struct efx_nic *efx) nic_data->must_restore_filters = true; nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID; + /* The datapath firmware might have been changed */ + nic_data->must_check_datapath_caps = true; + + /* MAC statistics have been cleared on the NIC; clear the local + * statistic that we update with efx_update_diff_stat(). + */ + nic_data->stats[EF10_STAT_rx_bad_bytes] = 0; + return -EIO; } diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c index 8d33da6697fb..7b6be61d549f 100644 --- a/drivers/net/ethernet/sfc/mcdi_port.c +++ b/drivers/net/ethernet/sfc/mcdi_port.c @@ -556,6 +556,7 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec case 100: caps = 1 << MC_CMD_PHY_CAP_100FDX_LBN; break; case 1000: caps = 1 << MC_CMD_PHY_CAP_1000FDX_LBN; break; case 10000: caps = 1 << MC_CMD_PHY_CAP_10000FDX_LBN; break; + case 40000: caps = 1 << MC_CMD_PHY_CAP_40000FDX_LBN; break; default: return -EINVAL; } } else { @@ -841,6 +842,7 @@ static unsigned int efx_mcdi_event_link_speed[] = { [MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100, [MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000, [MCDI_EVENT_LINKCHANGE_SPEED_10G] = 10000, + [MCDI_EVENT_LINKCHANGE_SPEED_40G] = 40000, }; void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev) diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index 4b1e188f7a2f..fda29d39032f 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -400,6 +400,8 @@ enum { * @rx_rss_context: Firmware handle for our RSS context * @stats: Hardware statistics * @workaround_35388: Flag: firmware supports workaround for bug 35388 + * @must_check_datapath_caps: Flag: @datapath_caps needs to be revalidated + * after MC reboot * @datapath_caps: Capabilities of datapath firmware (FLAGS1 field of * %MC_CMD_GET_CAPABILITIES response) */ @@ -413,6 +415,7 @@ struct efx_ef10_nic_data { u32 rx_rss_context; u64 stats[EF10_STAT_COUNT]; bool workaround_35388; + bool must_check_datapath_caps; u32 datapath_caps; }; diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index 370e13dde115..5730fe2445a6 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -271,7 +271,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l) #define SMC_insw(a, r, p, l) mcf_insw(a + r, p, l) #define SMC_outsw(a, r, p, l) mcf_outsw(a + r, p, l) -#define SMC_IRQ_FLAGS (IRQF_DISABLED) +#define SMC_IRQ_FLAGS 0 #else diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c index ffa5c4ad1210..5f9e79f7f2df 100644 --- a/drivers/net/ethernet/smsc/smsc9420.c +++ b/drivers/net/ethernet/smsc/smsc9420.c @@ -1356,8 +1356,7 @@ static int smsc9420_open(struct net_device *dev) smsc9420_reg_write(pd, INT_STAT, 0xFFFFFFFF); smsc9420_pci_flush_write(pd); - result = request_irq(irq, smsc9420_isr, IRQF_SHARED | IRQF_DISABLED, - DRV_NAME, pd); + result = request_irq(irq, smsc9420_isr, IRQF_SHARED, DRV_NAME, pd); if (result) { smsc_warn(IFUP, "Unable to use IRQ = %d", irq); result = -ENODEV; diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c index 9c805e0c0cae..f7f2ef49c0c1 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c @@ -1726,7 +1726,7 @@ static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) goto fail_alloc_irq; } result = request_irq(card->irq, gelic_card_interrupt, - IRQF_DISABLED, netdev->name, card); + 0, netdev->name, card); if (result) { dev_info(ctodev(card), "%s:request_irq failed (%d)\n", diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c index f07c340990da..3f138ca88670 100644 --- a/drivers/net/irda/mcs7780.c +++ b/drivers/net/irda/mcs7780.c @@ -191,8 +191,8 @@ static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs) goto error; ret = 0; - error: - return ret; +error: + return ret; } /* Setup a communication between mcs7780 and agilent chip. */ @@ -501,8 +501,11 @@ static inline int mcs_setup_urbs(struct mcs_cb *mcs) return 0; mcs->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!mcs->rx_urb) + if (!mcs->rx_urb) { + usb_free_urb(mcs->tx_urb); + mcs->tx_urb = NULL; return 0; + } return 1; } @@ -643,9 +646,9 @@ static int mcs_speed_change(struct mcs_cb *mcs) ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); mcs->speed = mcs->new_speed; - error: - mcs->new_speed = 0; - return ret; +error: + mcs->new_speed = 0; + return ret; } /* Ioctl calls not supported at this time. Can be an area of future work. */ @@ -738,17 +741,20 @@ static int mcs_net_open(struct net_device *netdev) ret = mcs_receive_start(mcs); if (ret) - goto error3; + goto error4; netif_start_queue(netdev); return 0; - error3: - irlap_close(mcs->irlap); - error2: - kfree_skb(mcs->rx_buff.skb); - error1: - return ret; +error4: + usb_free_urb(mcs->rx_urb); + usb_free_urb(mcs->tx_urb); +error3: + irlap_close(mcs->irlap); +error2: + kfree_skb(mcs->rx_buff.skb); +error1: + return ret; } /* Receive callback function. */ @@ -946,11 +952,11 @@ static int mcs_probe(struct usb_interface *intf, usb_set_intfdata(intf, mcs); return 0; - error2: - free_netdev(ndev); +error2: + free_netdev(ndev); - error1: - return ret; +error1: + return ret; } /* The current device is removed, the USB layer tells us to shut down. */ diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index fcbf680c3e62..a17d85a331f1 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -146,6 +146,7 @@ static int loopback_dev_init(struct net_device *dev) static void loopback_dev_free(struct net_device *dev) { + dev_net(dev)->loopback_dev = NULL; free_percpu(dev->lstats); free_netdev(dev); } diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index dcb21347c670..adeee615dd19 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -684,15 +684,12 @@ restart: case NETDEV_RELEASE: case NETDEV_JOIN: case NETDEV_UNREGISTER: - /* - * rtnl_lock already held + /* rtnl_lock already held * we might sleep in __netpoll_cleanup() */ spin_unlock_irqrestore(&target_list_lock, flags); - mutex_lock(&nt->mutex); __netpoll_cleanup(&nt->np); - mutex_unlock(&nt->mutex); spin_lock_irqsave(&target_list_lock, flags); dev_put(nt->np.dev); diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c index db472ffb6e89..313a0377f68f 100644 --- a/drivers/net/phy/cicada.c +++ b/drivers/net/phy/cicada.c @@ -30,9 +30,9 @@ #include <linux/ethtool.h> #include <linux/phy.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/irq.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> /* Cicada Extended Control Register 1 */ #define MII_CIS8201_EXT_CON1 0x17 diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 6fa5ae00039f..01805319e1e0 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -281,7 +281,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) nf_reset(skb); skb->ip_summed = CHECKSUM_NONE; - ip_select_ident(iph, &rt->dst, NULL); + ip_select_ident(skb, &rt->dst, NULL); ip_send_check(iph); ip_local_out(skb); diff --git a/drivers/net/tun.c b/drivers/net/tun.c index a639de8401f8..807815fc9968 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1641,11 +1641,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) INIT_LIST_HEAD(&tun->disabled); err = tun_attach(tun, file, false); if (err < 0) - goto err_free_dev; + goto err_free_flow; err = register_netdevice(tun->dev); if (err < 0) - goto err_free_dev; + goto err_detach; if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) || device_create_file(&tun->dev->dev, &dev_attr_owner) || @@ -1689,7 +1689,12 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) strcpy(ifr->ifr_name, tun->dev->name); return 0; - err_free_dev: +err_detach: + tun_detach_all(dev); +err_free_flow: + tun_flow_uninit(tun); + security_tun_dev_free_security(tun->security); +err_free_dev: free_netdev(dev); return err; } diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 03ad4dc293aa..2023f3ea891e 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -33,7 +33,7 @@ #include <linux/usb/usbnet.h> -#if defined(CONFIG_USB_NET_RNDIS_HOST) || defined(CONFIG_USB_NET_RNDIS_HOST_MODULE) +#if IS_ENABLED(CONFIG_USB_NET_RNDIS_HOST) static int is_rndis(struct usb_interface_descriptor *desc) { @@ -69,8 +69,7 @@ static const u8 mbm_guid[16] = { 0xa6, 0x07, 0xc0, 0xff, 0xcb, 0x7e, 0x39, 0x2a, }; -/* - * probes control interface, claims data interface, collects the bulk +/* probes control interface, claims data interface, collects the bulk * endpoints, activates data interface (if needed), maybe sets MTU. * all pure cdc, except for certain firmware workarounds, and knowing * that rndis uses one different rule. @@ -88,7 +87,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) struct usb_cdc_mdlm_desc *desc = NULL; struct usb_cdc_mdlm_detail_desc *detail = NULL; - if (sizeof dev->data < sizeof *info) + if (sizeof(dev->data) < sizeof(*info)) return -EDOM; /* expect strict spec conformance for the descriptors, but @@ -126,10 +125,10 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) is_activesync(&intf->cur_altsetting->desc) || is_wireless_rndis(&intf->cur_altsetting->desc)); - memset(info, 0, sizeof *info); + memset(info, 0, sizeof(*info)); info->control = intf; while (len > 3) { - if (buf [1] != USB_DT_CS_INTERFACE) + if (buf[1] != USB_DT_CS_INTERFACE) goto next_desc; /* use bDescriptorSubType to identify the CDC descriptors. @@ -139,14 +138,14 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) * in favor of a complicated OID-based RPC scheme doing what * CDC Ethernet achieves with a simple descriptor. */ - switch (buf [2]) { + switch (buf[2]) { case USB_CDC_HEADER_TYPE: if (info->header) { dev_dbg(&intf->dev, "extra CDC header\n"); goto bad_desc; } info->header = (void *) buf; - if (info->header->bLength != sizeof *info->header) { + if (info->header->bLength != sizeof(*info->header)) { dev_dbg(&intf->dev, "CDC header len %u\n", info->header->bLength); goto bad_desc; @@ -175,7 +174,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) goto bad_desc; } info->u = (void *) buf; - if (info->u->bLength != sizeof *info->u) { + if (info->u->bLength != sizeof(*info->u)) { dev_dbg(&intf->dev, "CDC union len %u\n", info->u->bLength); goto bad_desc; @@ -233,7 +232,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) goto bad_desc; } info->ether = (void *) buf; - if (info->ether->bLength != sizeof *info->ether) { + if (info->ether->bLength != sizeof(*info->ether)) { dev_dbg(&intf->dev, "CDC ether len %u\n", info->ether->bLength); goto bad_desc; @@ -274,8 +273,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) break; } next_desc: - len -= buf [0]; /* bLength */ - buf += buf [0]; + len -= buf[0]; /* bLength */ + buf += buf[0]; } /* Microsoft ActiveSync based and some regular RNDIS devices lack the @@ -379,9 +378,7 @@ void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf) } EXPORT_SYMBOL_GPL(usbnet_cdc_unbind); -/*------------------------------------------------------------------------- - * - * Communications Device Class, Ethernet Control model +/* Communications Device Class, Ethernet Control model * * Takes two interfaces. The DATA interface is inactive till an altsetting * is selected. Configuration data includes class descriptors. There's @@ -389,8 +386,7 @@ EXPORT_SYMBOL_GPL(usbnet_cdc_unbind); * * This should interop with whatever the 2.4 "CDCEther.c" driver * (by Brad Hards) talked with, with more functionality. - * - *-------------------------------------------------------------------------*/ + */ static void dumpspeed(struct usbnet *dev, __le32 *speeds) { @@ -404,7 +400,7 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb) { struct usb_cdc_notification *event; - if (urb->actual_length < sizeof *event) + if (urb->actual_length < sizeof(*event)) return; /* SPEED_CHANGE can get split into two 8-byte packets */ @@ -423,7 +419,7 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb) case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */ netif_dbg(dev, timer, dev->net, "CDC: speed change (len %d)\n", urb->actual_length); - if (urb->actual_length != (sizeof *event + 8)) + if (urb->actual_length != (sizeof(*event) + 8)) set_bit(EVENT_STS_SPLIT, &dev->flags); else dumpspeed(dev, (__le32 *) &event[1]); @@ -469,7 +465,6 @@ EXPORT_SYMBOL_GPL(usbnet_cdc_bind); static const struct driver_info cdc_info = { .description = "CDC Ethernet Device", .flags = FLAG_ETHER | FLAG_POINTTOPOINT, - // .check_connect = cdc_check_connect, .bind = usbnet_cdc_bind, .unbind = usbnet_cdc_unbind, .status = usbnet_cdc_status, @@ -493,9 +488,8 @@ static const struct driver_info wwan_info = { #define DELL_VENDOR_ID 0x413C #define REALTEK_VENDOR_ID 0x0bda -static const struct usb_device_id products [] = { -/* - * BLACKLIST !! +static const struct usb_device_id products[] = { +/* BLACKLIST !! * * First blacklist any products that are egregiously nonconformant * with the CDC Ethernet specs. Minor braindamage we cope with; when @@ -542,7 +536,7 @@ static const struct usb_device_id products [] = { .driver_info = 0, }, { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, + | USB_DEVICE_ID_MATCH_DEVICE, .idVendor = 0x04DD, .idProduct = 0x8007, /* C-700 */ ZAURUS_MASTER_INTERFACE, @@ -659,8 +653,7 @@ static const struct usb_device_id products [] = { .driver_info = 0, }, -/* - * WHITELIST!!! +/* WHITELIST!!! * * CDC Ether uses two interfaces, not necessarily consecutive. * We match the main interface, ignoring the optional device @@ -672,60 +665,40 @@ static const struct usb_device_id products [] = { */ { /* ZTE (Vodafone) K3805-Z */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_PRODUCT - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = ZTE_VENDOR_ID, - .idProduct = 0x1003, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, + USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1003, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&wwan_info, }, { /* ZTE (Vodafone) K3806-Z */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_PRODUCT - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = ZTE_VENDOR_ID, - .idProduct = 0x1015, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, + USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1015, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&wwan_info, }, { /* ZTE (Vodafone) K4510-Z */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_PRODUCT - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = ZTE_VENDOR_ID, - .idProduct = 0x1173, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, + USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1173, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&wwan_info, }, { /* ZTE (Vodafone) K3770-Z */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_PRODUCT - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = ZTE_VENDOR_ID, - .idProduct = 0x1177, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, + USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1177, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&wwan_info, }, { /* ZTE (Vodafone) K3772-Z */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_PRODUCT - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = ZTE_VENDOR_ID, - .idProduct = 0x1181, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, + USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1181, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&wwan_info, }, { + /* Telit modules */ + USB_VENDOR_AND_INTERFACE_INFO(0x1bc7, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = (kernel_ulong_t) &wwan_info, +}, { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &cdc_info, @@ -736,15 +709,11 @@ static const struct usb_device_id products [] = { }, { /* Various Huawei modems with a network port like the UMG1831 */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = HUAWEI_VENDOR_ID, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = 255, + USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, 255), .driver_info = (unsigned long)&wwan_info, }, - { }, // END + { }, /* END */ }; MODULE_DEVICE_TABLE(usb, products); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index bf64b4191dcc..d1292fe746bc 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -564,7 +564,7 @@ static void vxlan_notify_add_rx_port(struct sock *sk) struct net_device *dev; struct net *net = sock_net(sk); sa_family_t sa_family = sk->sk_family; - u16 port = htons(inet_sk(sk)->inet_sport); + __be16 port = inet_sk(sk)->inet_sport; rcu_read_lock(); for_each_netdev_rcu(net, dev) { @@ -581,7 +581,7 @@ static void vxlan_notify_del_rx_port(struct sock *sk) struct net_device *dev; struct net *net = sock_net(sk); sa_family_t sa_family = sk->sk_family; - u16 port = htons(inet_sk(sk)->inet_sport); + __be16 port = inet_sk(sk)->inet_sport; rcu_read_lock(); for_each_netdev_rcu(net, dev) { @@ -2021,7 +2021,8 @@ static struct device_type vxlan_type = { }; /* Calls the ndo_add_vxlan_port of the caller in order to - * supply the listening VXLAN udp ports. + * supply the listening VXLAN udp ports. Callers are expected + * to implement the ndo_add_vxlan_port. */ void vxlan_get_rx_port(struct net_device *dev) { @@ -2029,16 +2030,13 @@ void vxlan_get_rx_port(struct net_device *dev) struct net *net = dev_net(dev); struct vxlan_net *vn = net_generic(net, vxlan_net_id); sa_family_t sa_family; - u16 port; - int i; - - if (!dev || !dev->netdev_ops || !dev->netdev_ops->ndo_add_vxlan_port) - return; + __be16 port; + unsigned int i; spin_lock(&vn->sock_lock); for (i = 0; i < PORT_HASH_SIZE; ++i) { - hlist_for_each_entry_rcu(vs, vs_head(net, i), hlist) { - port = htons(inet_sk(vs->sock->sk)->inet_sport); + hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist) { + port = inet_sk(vs->sock->sk)->inet_sport; sa_family = vs->sock->sk->sk_family; dev->netdev_ops->ndo_add_vxlan_port(dev, sa_family, port); @@ -2492,15 +2490,19 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, SET_ETHTOOL_OPS(dev, &vxlan_ethtool_ops); - /* create an fdb entry for default destination */ - err = vxlan_fdb_create(vxlan, all_zeros_mac, - &vxlan->default_dst.remote_ip, - NUD_REACHABLE|NUD_PERMANENT, - NLM_F_EXCL|NLM_F_CREATE, - vxlan->dst_port, vxlan->default_dst.remote_vni, - vxlan->default_dst.remote_ifindex, NTF_SELF); - if (err) - return err; + /* create an fdb entry for a valid default destination */ + if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) { + err = vxlan_fdb_create(vxlan, all_zeros_mac, + &vxlan->default_dst.remote_ip, + NUD_REACHABLE|NUD_PERMANENT, + NLM_F_EXCL|NLM_F_CREATE, + vxlan->dst_port, + vxlan->default_dst.remote_vni, + vxlan->default_dst.remote_ifindex, + NTF_SELF); + if (err) + return err; + } err = register_netdevice(dev); if (err) { diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index fc8a0fa6d3b2..b00a7e92225f 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig @@ -28,7 +28,7 @@ config BRCMFMAC config BRCMFMAC_SDIO bool "SDIO bus interface support for FullMAC driver" - depends on MMC + depends on (MMC = y || MMC = BRCMFMAC) depends on BRCMFMAC select FW_LOADER default y @@ -39,7 +39,7 @@ config BRCMFMAC_SDIO config BRCMFMAC_USB bool "USB bus interface support for FullMAC driver" - depends on USB + depends on (USB = y || USB = BRCMFMAC) depends on BRCMFMAC select FW_LOADER ---help--- diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index d06376014bcd..f5e6b489ed32 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -40,7 +40,9 @@ struct hwbus_priv { struct cw1200_common *core; const struct cw1200_platform_data_spi *pdata; spinlock_t lock; /* Serialize all bus operations */ + wait_queue_head_t wq; int claimed; + int irq_disabled; }; #define SDIO_TO_SPI_ADDR(addr) ((addr & 0x1f)>>2) @@ -197,8 +199,11 @@ static void cw1200_spi_lock(struct hwbus_priv *self) { unsigned long flags; + DECLARE_WAITQUEUE(wait, current); + might_sleep(); + add_wait_queue(&self->wq, &wait); spin_lock_irqsave(&self->lock, flags); while (1) { set_current_state(TASK_UNINTERRUPTIBLE); @@ -211,6 +216,7 @@ static void cw1200_spi_lock(struct hwbus_priv *self) set_current_state(TASK_RUNNING); self->claimed = 1; spin_unlock_irqrestore(&self->lock, flags); + remove_wait_queue(&self->wq, &wait); return; } @@ -222,6 +228,8 @@ static void cw1200_spi_unlock(struct hwbus_priv *self) spin_lock_irqsave(&self->lock, flags); self->claimed = 0; spin_unlock_irqrestore(&self->lock, flags); + wake_up(&self->wq); + return; } @@ -230,6 +238,8 @@ static irqreturn_t cw1200_spi_irq_handler(int irq, void *dev_id) struct hwbus_priv *self = dev_id; if (self->core) { + disable_irq_nosync(self->func->irq); + self->irq_disabled = 1; cw1200_irq_handler(self->core); return IRQ_HANDLED; } else { @@ -263,13 +273,22 @@ exit: static int cw1200_spi_irq_unsubscribe(struct hwbus_priv *self) { - int ret = 0; - pr_debug("SW IRQ unsubscribe\n"); disable_irq_wake(self->func->irq); free_irq(self->func->irq, self); - return ret; + return 0; +} + +static int cw1200_spi_irq_enable(struct hwbus_priv *self, int enable) +{ + /* Disables are handled by the interrupt handler */ + if (enable && self->irq_disabled) { + enable_irq(self->func->irq); + self->irq_disabled = 0; + } + + return 0; } static int cw1200_spi_off(const struct cw1200_platform_data_spi *pdata) @@ -349,6 +368,7 @@ static struct hwbus_ops cw1200_spi_hwbus_ops = { .unlock = cw1200_spi_unlock, .align_size = cw1200_spi_align_size, .power_mgmt = cw1200_spi_pm, + .irq_enable = cw1200_spi_irq_enable, }; /* Probe Function to be called by SPI stack when device is discovered */ @@ -400,6 +420,8 @@ static int cw1200_spi_probe(struct spi_device *func) spi_set_drvdata(func, self); + init_waitqueue_head(&self->wq); + status = cw1200_spi_irq_subscribe(self); status = cw1200_core_probe(&cw1200_spi_hwbus_ops, diff --git a/drivers/net/wireless/cw1200/fwio.c b/drivers/net/wireless/cw1200/fwio.c index acdff0f7f952..0b2061bbc68b 100644 --- a/drivers/net/wireless/cw1200/fwio.c +++ b/drivers/net/wireless/cw1200/fwio.c @@ -485,7 +485,7 @@ int cw1200_load_firmware(struct cw1200_common *priv) /* Enable interrupt signalling */ priv->hwbus_ops->lock(priv->hwbus_priv); - ret = __cw1200_irq_enable(priv, 1); + ret = __cw1200_irq_enable(priv, 2); priv->hwbus_ops->unlock(priv->hwbus_priv); if (ret < 0) goto unsubscribe; diff --git a/drivers/net/wireless/cw1200/hwbus.h b/drivers/net/wireless/cw1200/hwbus.h index 8b2fc831c3de..51dfb3a90735 100644 --- a/drivers/net/wireless/cw1200/hwbus.h +++ b/drivers/net/wireless/cw1200/hwbus.h @@ -28,6 +28,7 @@ struct hwbus_ops { void (*unlock)(struct hwbus_priv *self); size_t (*align_size)(struct hwbus_priv *self, size_t size); int (*power_mgmt)(struct hwbus_priv *self, bool suspend); + int (*irq_enable)(struct hwbus_priv *self, int enable); }; #endif /* CW1200_HWBUS_H */ diff --git a/drivers/net/wireless/cw1200/hwio.c b/drivers/net/wireless/cw1200/hwio.c index ff230b7aeedd..41bd7615ccaa 100644 --- a/drivers/net/wireless/cw1200/hwio.c +++ b/drivers/net/wireless/cw1200/hwio.c @@ -273,6 +273,21 @@ int __cw1200_irq_enable(struct cw1200_common *priv, int enable) u16 val16; int ret; + /* We need to do this hack because the SPI layer can sleep on I/O + and the general path involves I/O to the device in interrupt + context. + + However, the initial enable call needs to go to the hardware. + + We don't worry about shutdown because we do a full reset which + clears the interrupt enabled bits. + */ + if (priv->hwbus_ops->irq_enable) { + ret = priv->hwbus_ops->irq_enable(priv->hwbus_priv, enable); + if (ret || enable < 2) + return ret; + } + if (HIF_8601_SILICON == priv->hw_type) { ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32); if (ret < 0) { diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 95e6e61c3de0..88ce656f96cd 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -6659,19 +6659,20 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) rt2800_init_registers(rt2x00dev))) return -EIO; + if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev))) + return -EIO; + /* * Send signal to firmware during boot time. */ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); - if (rt2x00_is_usb(rt2x00dev)) { + if (rt2x00_is_usb(rt2x00dev)) rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); - rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); - } + rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); msleep(1); - if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) || - rt2800_wait_bbp_ready(rt2x00dev))) + if (unlikely(rt2800_wait_bbp_ready(rt2x00dev))) return -EIO; rt2800_init_bbp(rt2x00dev); diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 841fb9dfc9da..9a6edb0c014e 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -438,17 +438,16 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) skb_queue_tail(&priv->rx_queue, skb); usb_anchor_urb(entry, &priv->anchored); ret = usb_submit_urb(entry, GFP_KERNEL); + usb_put_urb(entry); if (ret) { skb_unlink(skb, &priv->rx_queue); usb_unanchor_urb(entry); goto err; } - usb_free_urb(entry); } return ret; err: - usb_free_urb(entry); kfree_skb(skb); usb_kill_anchored_urbs(&priv->anchored); return ret; @@ -956,8 +955,12 @@ static int rtl8187_start(struct ieee80211_hw *dev) (RETRY_COUNT << 8 /* short retry limit */) | (RETRY_COUNT << 0 /* long retry limit */) | (7 << 21 /* MAX TX DMA */)); - rtl8187_init_urbs(dev); - rtl8187b_init_status_urb(dev); + ret = rtl8187_init_urbs(dev); + if (ret) + goto rtl8187_start_exit; + ret = rtl8187b_init_status_urb(dev); + if (ret) + usb_kill_anchored_urbs(&priv->anchored); goto rtl8187_start_exit; } @@ -966,7 +969,9 @@ static int rtl8187_start(struct ieee80211_hw *dev) rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); - rtl8187_init_urbs(dev); + ret = rtl8187_init_urbs(dev); + if (ret) + goto rtl8187_start_exit; reg = RTL818X_RX_CONF_ONLYERLPKT | RTL818X_RX_CONF_RX_AUTORESETPHY | diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index a1977430ddfb..5715318d6bab 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -184,6 +184,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, unsigned long rx_ring_ref, unsigned int tx_evtchn, unsigned int rx_evtchn); void xenvif_disconnect(struct xenvif *vif); +void xenvif_free(struct xenvif *vif); int xenvif_xenbus_init(void); void xenvif_xenbus_fini(void); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 625c6f49cfba..01bb854c7f62 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -353,6 +353,9 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, } netdev_dbg(dev, "Successfully created xenvif\n"); + + __module_get(THIS_MODULE); + return vif; } @@ -366,8 +369,6 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, if (vif->tx_irq) return 0; - __module_get(THIS_MODULE); - err = xenvif_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref); if (err < 0) goto err; @@ -406,7 +407,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, init_waitqueue_head(&vif->wq); vif->task = kthread_create(xenvif_kthread, - (void *)vif, vif->dev->name); + (void *)vif, "%s", vif->dev->name); if (IS_ERR(vif->task)) { pr_warn("Could not allocate kthread for %s\n", vif->dev->name); err = PTR_ERR(vif->task); @@ -452,12 +453,6 @@ void xenvif_carrier_off(struct xenvif *vif) void xenvif_disconnect(struct xenvif *vif) { - /* Disconnect funtion might get called by generic framework - * even before vif connects, so we need to check if we really - * need to do a module_put. - */ - int need_module_put = 0; - if (netif_carrier_ok(vif->dev)) xenvif_carrier_off(vif); @@ -468,23 +463,22 @@ void xenvif_disconnect(struct xenvif *vif) unbind_from_irqhandler(vif->tx_irq, vif); unbind_from_irqhandler(vif->rx_irq, vif); } - /* vif->irq is valid, we had a module_get in - * xenvif_connect. - */ - need_module_put = 1; + vif->tx_irq = 0; } if (vif->task) kthread_stop(vif->task); + xenvif_unmap_frontend_rings(vif); +} + +void xenvif_free(struct xenvif *vif) +{ netif_napi_del(&vif->napi); unregister_netdev(vif->dev); - xenvif_unmap_frontend_rings(vif); - free_netdev(vif->dev); - if (need_module_put) - module_put(THIS_MODULE); + module_put(THIS_MODULE); } diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 956130c70036..f3e591c611de 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -212,6 +212,49 @@ static bool start_new_rx_buffer(int offset, unsigned long size, int head) return false; } +struct xenvif_count_slot_state { + unsigned long copy_off; + bool head; +}; + +unsigned int xenvif_count_frag_slots(struct xenvif *vif, + unsigned long offset, unsigned long size, + struct xenvif_count_slot_state *state) +{ + unsigned count = 0; + + offset &= ~PAGE_MASK; + + while (size > 0) { + unsigned long bytes; + + bytes = PAGE_SIZE - offset; + + if (bytes > size) + bytes = size; + + if (start_new_rx_buffer(state->copy_off, bytes, state->head)) { + count++; + state->copy_off = 0; + } + + if (state->copy_off + bytes > MAX_BUFFER_OFFSET) + bytes = MAX_BUFFER_OFFSET - state->copy_off; + + state->copy_off += bytes; + + offset += bytes; + size -= bytes; + + if (offset == PAGE_SIZE) + offset = 0; + + state->head = false; + } + + return count; +} + /* * Figure out how many ring slots we're going to need to send @skb to * the guest. This function is essentially a dry run of @@ -219,48 +262,39 @@ static bool start_new_rx_buffer(int offset, unsigned long size, int head) */ unsigned int xenvif_count_skb_slots(struct xenvif *vif, struct sk_buff *skb) { + struct xenvif_count_slot_state state; unsigned int count; - int i, copy_off; + unsigned char *data; + unsigned i; - count = DIV_ROUND_UP(skb_headlen(skb), PAGE_SIZE); + state.head = true; + state.copy_off = 0; - copy_off = skb_headlen(skb) % PAGE_SIZE; + /* Slot for the first (partial) page of data. */ + count = 1; + /* Need a slot for the GSO prefix for GSO extra data? */ if (skb_shinfo(skb)->gso_size) count++; - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]); - unsigned long offset = skb_shinfo(skb)->frags[i].page_offset; - unsigned long bytes; - - offset &= ~PAGE_MASK; - - while (size > 0) { - BUG_ON(offset >= PAGE_SIZE); - BUG_ON(copy_off > MAX_BUFFER_OFFSET); - - bytes = PAGE_SIZE - offset; - - if (bytes > size) - bytes = size; + data = skb->data; + while (data < skb_tail_pointer(skb)) { + unsigned long offset = offset_in_page(data); + unsigned long size = PAGE_SIZE - offset; - if (start_new_rx_buffer(copy_off, bytes, 0)) { - count++; - copy_off = 0; - } + if (data + size > skb_tail_pointer(skb)) + size = skb_tail_pointer(skb) - data; - if (copy_off + bytes > MAX_BUFFER_OFFSET) - bytes = MAX_BUFFER_OFFSET - copy_off; + count += xenvif_count_frag_slots(vif, offset, size, &state); - copy_off += bytes; + data += size; + } - offset += bytes; - size -= bytes; + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]); + unsigned long offset = skb_shinfo(skb)->frags[i].page_offset; - if (offset == PAGE_SIZE) - offset = 0; - } + count += xenvif_count_frag_slots(vif, offset, size, &state); } return count; } diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 1fe48fe364ed..a53782ef1540 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -42,7 +42,7 @@ static int netback_remove(struct xenbus_device *dev) if (be->vif) { kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); - xenvif_disconnect(be->vif); + xenvif_free(be->vif); be->vif = NULL; } kfree(be); @@ -213,9 +213,18 @@ static void disconnect_backend(struct xenbus_device *dev) { struct backend_info *be = dev_get_drvdata(&dev->dev); + if (be->vif) + xenvif_disconnect(be->vif); +} + +static void destroy_backend(struct xenbus_device *dev) +{ + struct backend_info *be = dev_get_drvdata(&dev->dev); + if (be->vif) { + kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); - xenvif_disconnect(be->vif); + xenvif_free(be->vif); be->vif = NULL; } } @@ -246,14 +255,11 @@ static void frontend_changed(struct xenbus_device *dev, case XenbusStateConnected: if (dev->state == XenbusStateConnected) break; - backend_create_xenvif(be); if (be->vif) connect(be); break; case XenbusStateClosing: - if (be->vif) - kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); disconnect_backend(dev); xenbus_switch_state(dev, XenbusStateClosing); break; @@ -262,6 +268,7 @@ static void frontend_changed(struct xenbus_device *dev, xenbus_switch_state(dev, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; + destroy_backend(dev); /* fall through if not online */ case XenbusStateUnknown: device_unregister(&dev->dev); diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 7c29ee4ed0ae..b0299e6d9a3f 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -47,6 +47,9 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev) return; + if (pci_dev->pme_poll) + pci_dev->pme_poll = false; + if (pci_dev->current_state == PCI_D3cold) { pci_wakeup_event(pci_dev); pm_runtime_resume(&pci_dev->dev); @@ -57,9 +60,6 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) if (pci_dev->pme_support) pci_check_pme_status(pci_dev); - if (pci_dev->pme_poll) - pci_dev->pme_poll = false; - pci_wakeup_event(pci_dev); pm_runtime_resume(&pci_dev->dev); diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 08b22a901c25..d7ca9305ff45 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -105,7 +105,7 @@ #define BNX2FC_RQ_WQE_SIZE (BNX2FC_RQ_BUF_SZ) #define BNX2FC_XFERQ_WQE_SIZE (sizeof(struct fcoe_xfrqe)) #define BNX2FC_CONFQ_WQE_SIZE (sizeof(struct fcoe_confqe)) -#define BNX2FC_5771X_DB_PAGE_SIZE 128 +#define BNX2X_DB_SHIFT 3 #define BNX2FC_TASK_SIZE 128 #define BNX2FC_TASKS_PER_PAGE (PAGE_SIZE/BNX2FC_TASK_SIZE) diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index c0d035a8f8f9..46a37657307f 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c @@ -1421,8 +1421,7 @@ int bnx2fc_map_doorbell(struct bnx2fc_rport *tgt) reg_base = pci_resource_start(hba->pcidev, BNX2X_DOORBELL_PCI_BAR); - reg_off = BNX2FC_5771X_DB_PAGE_SIZE * - (context_id & 0x1FFFF) + DPM_TRIGER_TYPE; + reg_off = (1 << BNX2X_DB_SHIFT) * (context_id & 0x1FFFF); tgt->ctx_base = ioremap_nocache(reg_base + reg_off, 4); if (!tgt->ctx_base) return -ENOMEM; diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index 6940f0930a84..c73bbcb63c02 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h @@ -64,7 +64,7 @@ #define MAX_PAGES_PER_CTRL_STRUCT_POOL 8 #define BNX2I_RESERVED_SLOW_PATH_CMD_SLOTS 4 -#define BNX2I_5771X_DBELL_PAGE_SIZE 128 +#define BNX2X_DB_SHIFT 3 /* 5706/08 hardware has limit on maximum buffer size per BD it can handle */ #define MAX_BD_LENGTH 65535 diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index af3e675d4d48..5be718c241c4 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -2738,8 +2738,7 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep) if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) { reg_base = pci_resource_start(ep->hba->pcidev, BNX2X_DOORBELL_PCI_BAR); - reg_off = BNX2I_5771X_DBELL_PAGE_SIZE * (cid_num & 0x1FFFF) + - DPM_TRIGER_TYPE; + reg_off = (1 << BNX2X_DB_SHIFT) * (cid_num & 0x1FFFF); ep->qp.ctx_base = ioremap_nocache(reg_base + reg_off, 4); goto arm_cq; } diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index a84aab47a113..f73287eab373 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -96,6 +96,15 @@ config COMEDI_SKEL To compile this driver as a module, choose M here: the module will be called skel. +config COMEDI_SSV_DNP + tristate "SSV Embedded Systems DIL/Net-PC support" + depends on X86_32 || COMPILE_TEST + ---help--- + Enable support for SSV Embedded Systems DIL/Net-PC + + To compile this driver as a module, choose M here: the module will be + called ssv_dnp. + endif # COMEDI_MISC_DRIVERS menuconfig COMEDI_ISA_DRIVERS @@ -386,6 +395,14 @@ config COMEDI_DMM32AT To compile this driver as a module, choose M here: the module will be called dmm32at. +config COMEDI_UNIOXX5 + tristate "Fastwel UNIOxx-5 analog and digital io board support" + ---help--- + Enable support for Fastwel UNIOxx-5 (analog and digital i/o) boards + + To compile this driver as a module, choose M here: the module will be + called unioxx5. + config COMEDI_FL512 tristate "FL512 ISA card support" ---help--- @@ -855,14 +872,6 @@ config COMEDI_DYNA_PCI10XX To compile this driver as a module, choose M here: the module will be called dyna_pci10xx. -config COMEDI_UNIOXX5 - tristate "Fastwel UNIOxx-5 analog and digital io board support" - ---help--- - Enable support for Fastwel UNIOxx-5 (analog and digital i/o) boards - - To compile this driver as a module, choose M here: the module will be - called unioxx5. - config COMEDI_GSC_HPDI tristate "General Standards PCI-HPDI32 / PMC-HPDI32 support" select COMEDI_FC @@ -1085,14 +1094,6 @@ config COMEDI_S626 To compile this driver as a module, choose M here: the module will be called s626. -config COMEDI_SSV_DNP - tristate "SSV Embedded Systems DIL/Net-PC support" - ---help--- - Enable support for SSV Embedded Systems DIL/Net-PC - - To compile this driver as a module, choose M here: the module will be - called ssv_dnp. - config COMEDI_MITE depends on HAS_DMA tristate diff --git a/drivers/staging/dgap/dgap_driver.c b/drivers/staging/dgap/dgap_driver.c index 724a685753dd..40ef785a0428 100644 --- a/drivers/staging/dgap/dgap_driver.c +++ b/drivers/staging/dgap/dgap_driver.c @@ -474,7 +474,7 @@ static void dgap_cleanup_board(struct board_t *brd) DGAP_LOCK(dgap_global_lock, flags); brd->msgbuf = NULL; - printk(brd->msgbuf_head); + printk("%s", brd->msgbuf_head); kfree(brd->msgbuf_head); brd->msgbuf_head = NULL; DGAP_UNLOCK(dgap_global_lock, flags); @@ -628,7 +628,7 @@ static int dgap_found_board(struct pci_dev *pdev, int id) DPR_INIT(("dgap_scan(%d) - printing out the msgbuf\n", i)); DGAP_LOCK(dgap_global_lock, flags); brd->msgbuf = NULL; - printk(brd->msgbuf_head); + printk("%s", brd->msgbuf_head); kfree(brd->msgbuf_head); brd->msgbuf_head = NULL; DGAP_UNLOCK(dgap_global_lock, flags); @@ -955,25 +955,28 @@ static void dgap_mbuf(struct board_t *brd, const char *fmt, ...) { char buf[1024]; int i; unsigned long flags; + size_t length; DGAP_LOCK(dgap_global_lock, flags); /* Format buf using fmt and arguments contained in ap. */ va_start(ap, fmt); - i = vsprintf(buf, fmt, ap); + i = vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); DPR((buf)); if (!brd || !brd->msgbuf) { - printk(buf); + printk("%s", buf); DGAP_UNLOCK(dgap_global_lock, flags); return; } - memcpy(brd->msgbuf, buf, strlen(buf)); - brd->msgbuf += strlen(buf); - *brd->msgbuf = 0; + length = strlen(buf) + 1; + if (brd->msgbuf - brd->msgbuf_head < length) + length = brd->msgbuf - brd->msgbuf_head; + memcpy(brd->msgbuf, buf, length); + brd->msgbuf += length; DGAP_UNLOCK(dgap_global_lock, flags); } diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index f8c1e22585d6..71d2b83cc3a1 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -454,7 +454,7 @@ static void dgnc_cleanup_board(struct board_t *brd) DGNC_LOCK(dgnc_global_lock, flags); brd->msgbuf = NULL; - printk(brd->msgbuf_head); + printk("%s", brd->msgbuf_head); kfree(brd->msgbuf_head); brd->msgbuf_head = NULL; DGNC_UNLOCK(dgnc_global_lock, flags); @@ -710,7 +710,7 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) DPR_INIT(("dgnc_scan(%d) - printing out the msgbuf\n", i)); DGNC_LOCK(dgnc_global_lock, flags); brd->msgbuf = NULL; - printk(brd->msgbuf_head); + printk("%s", brd->msgbuf_head); kfree(brd->msgbuf_head); brd->msgbuf_head = NULL; DGNC_UNLOCK(dgnc_global_lock, flags); diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index db4d6dc03243..b36feb080cba 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -37,7 +37,7 @@ config IIO_SIMPLE_DUMMY_EVENTS config IIO_SIMPLE_DUMMY_BUFFER boolean "Buffered capture support" - depends on IIO_KFIFO_BUF + select IIO_KFIFO_BUF help Add buffered data capture to the simple dummy driver. diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index 351936c3efd6..e4998e4d4434 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -563,6 +563,7 @@ static int isl29018_probe(struct i2c_client *client, mutex_init(&chip->lock); chip->lux_scale = 1; + chip->lux_uscale = 0; chip->range = 1000; chip->adc_bit = 16; chip->suspended = false; diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c index d2748c329eae..c3f3f539e787 100644 --- a/drivers/staging/iio/magnetometer/hmc5843.c +++ b/drivers/staging/iio/magnetometer/hmc5843.c @@ -229,7 +229,7 @@ static int hmc5843_read_measurement(struct iio_dev *indio_dev, if (result < 0) return -EINVAL; - *val = result; + *val = sign_extend32(result, 15); return IIO_VAL_INT; } diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c index a802cf2491d6..4c6d2041260b 100644 --- a/drivers/staging/iio/meter/ade7854-spi.c +++ b/drivers/staging/iio/meter/ade7854-spi.c @@ -299,7 +299,7 @@ static int ade7854_spi_probe(struct spi_device *spi) if (ret) iio_device_free(indio_dev); - return 0; + return ret; } static int ade7854_spi_remove(struct spi_device *spi) diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c index 2f44d56700af..776d3632dc7d 100644 --- a/drivers/staging/line6/toneport.c +++ b/drivers/staging/line6/toneport.c @@ -244,13 +244,17 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol, struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)line6pcm->line6; + unsigned int source; - if (ucontrol->value.enumerated.item[0] == toneport->source) + source = ucontrol->value.enumerated.item[0]; + if (source >= ARRAY_SIZE(toneport_source_info)) + return -EINVAL; + if (source == toneport->source) return 0; - toneport->source = ucontrol->value.enumerated.item[0]; + toneport->source = source; toneport_send_cmd(toneport->line6.usbdev, - toneport_source_info[toneport->source].code, 0x0000); + toneport_source_info[source].code, 0x0000); return 1; } diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 086ca3d7241b..26b49a24b3df 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -1802,7 +1802,7 @@ kiblnd_recv (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, int kiblnd_thread_start(int (*fn)(void *arg), void *arg, char *name) { - struct task_struct *task = kthread_run(fn, arg, name); + struct task_struct *task = kthread_run(fn, arg, "%s", name); if (IS_ERR(task)) return PTR_ERR(task); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 2c581b7fa8ad..68a4f52ec998 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -1005,7 +1005,7 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) int ksocknal_thread_start(int (*fn)(void *arg), void *arg, char *name) { - struct task_struct *task = kthread_run(fn, arg, name); + struct task_struct *task = kthread_run(fn, arg, "%s", name); if (IS_ERR(task)) return PTR_ERR(task); diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig index 4e898e491860..2156a44d0740 100644 --- a/drivers/staging/lustre/lustre/Kconfig +++ b/drivers/staging/lustre/lustre/Kconfig @@ -1,6 +1,6 @@ config LUSTRE_FS tristate "Lustre file system client support" - depends on INET && m + depends on INET && m && !MIPS && !XTENSA && !SUPERH select LNET select CRYPTO select CRYPTO_CRC32 @@ -52,7 +52,7 @@ config LUSTRE_DEBUG_EXPENSIVE_CHECK config LUSTRE_TRANSLATE_ERRNOS bool depends on LUSTRE_FS && !X86 - default true + default y config LUSTRE_LLITE_LLOOP bool "Lustre virtual block device" diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index 3916bda3004c..a100a0b96381 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -800,9 +800,9 @@ static int ldlm_bl_thread_start(struct ldlm_bl_pool *blp) init_completion(&bltd.bltd_comp); bltd.bltd_num = atomic_read(&blp->blp_num_threads); - snprintf(bltd.bltd_name, sizeof(bltd.bltd_name) - 1, + snprintf(bltd.bltd_name, sizeof(bltd.bltd_name), "ldlm_bl_%02d", bltd.bltd_num); - task = kthread_run(ldlm_bl_thread_main, &bltd, bltd.bltd_name); + task = kthread_run(ldlm_bl_thread_main, &bltd, "%s", bltd.bltd_name); if (IS_ERR(task)) { CERROR("cannot start LDLM thread ldlm_bl_%02d: rc %ld\n", atomic_read(&blp->blp_num_threads), PTR_ERR(task)); diff --git a/drivers/staging/lustre/lustre/libcfs/workitem.c b/drivers/staging/lustre/lustre/libcfs/workitem.c index 462172d1a756..1a55c81892e0 100644 --- a/drivers/staging/lustre/lustre/libcfs/workitem.c +++ b/drivers/staging/lustre/lustre/libcfs/workitem.c @@ -397,7 +397,7 @@ cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab, sched->ws_name, sched->ws_nthreads); } - task = kthread_run(cfs_wi_scheduler, sched, name); + task = kthread_run(cfs_wi_scheduler, sched, "%s", name); if (!IS_ERR(task)) { nthrs--; continue; diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index 227a0ae9593b..5dec771d70ee 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -383,8 +383,8 @@ int ptlrpc_start_pinger(void) /* CLONE_VM and CLONE_FILES just avoid a needless copy, because we * just drop the VM and FILES in cfs_daemonize_ctxt() right away. */ - rc = PTR_ERR(kthread_run(ptlrpc_pinger_main, - &pinger_thread, pinger_thread.t_name)); + rc = PTR_ERR(kthread_run(ptlrpc_pinger_main, &pinger_thread, + "%s", pinger_thread.t_name)); if (IS_ERR_VALUE(rc)) { CERROR("cannot start thread: %d\n", rc); return rc; diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index fbdeff65d059..89c9be96f454 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -615,7 +615,7 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc) init_completion(&pc->pc_starting); init_completion(&pc->pc_finishing); spin_lock_init(&pc->pc_lock); - strncpy(pc->pc_name, name, sizeof(pc->pc_name) - 1); + strlcpy(pc->pc_name, name, sizeof(pc->pc_name)); pc->pc_set = ptlrpc_prep_set(); if (pc->pc_set == NULL) GOTO(out, rc = -ENOMEM); @@ -638,7 +638,7 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc) GOTO(out, rc); } - task = kthread_run(ptlrpcd, pc, pc->pc_name); + task = kthread_run(ptlrpcd, pc, "%s", pc->pc_name); if (IS_ERR(task)) GOTO(out, rc = PTR_ERR(task)); @@ -745,7 +745,7 @@ static int ptlrpcd_init(void) if (ptlrpcds == NULL) GOTO(out, rc = -ENOMEM); - snprintf(name, 15, "ptlrpcd_rcv"); + snprintf(name, sizeof(name), "ptlrpcd_rcv"); set_bit(LIOD_RECOVERY, &ptlrpcds->pd_thread_rcv.pc_flags); rc = ptlrpcd_start(-1, nthreads, name, &ptlrpcds->pd_thread_rcv); if (rc < 0) @@ -764,7 +764,7 @@ static int ptlrpcd_init(void) * unnecessary dependency. But how to distribute async RPCs load * among all the ptlrpc daemons becomes another trouble. */ for (i = 0; i < nthreads; i++) { - snprintf(name, 15, "ptlrpcd_%d", i); + snprintf(name, sizeof(name), "ptlrpcd_%d", i); rc = ptlrpcd_start(i, nthreads, name, &ptlrpcds->pd_threads[i]); if (rc < 0) GOTO(out, rc); diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index e90c8fb7da6a..6547f46a7729 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -59,8 +59,8 @@ ****************************************/ -#define PTRS_PER_PAGE (PAGE_CACHE_SIZE / sizeof(void *)) -#define PAGES_PER_POOL (PTRS_PER_PAGE) +#define POINTERS_PER_PAGE (PAGE_CACHE_SIZE / sizeof(void *)) +#define PAGES_PER_POOL (POINTERS_PER_PAGE) #define IDLE_IDX_MAX (100) #define IDLE_IDX_WEIGHT (3) diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index ac8b5fd2300b..acf75f3873d1 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -2718,15 +2718,15 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait) spin_unlock(&svcpt->scp_lock); if (svcpt->scp_cpt >= 0) { - snprintf(thread->t_name, PTLRPC_THR_NAME_LEN, "%s%02d_%03d", + snprintf(thread->t_name, sizeof(thread->t_name), "%s%02d_%03d", svc->srv_thread_name, svcpt->scp_cpt, thread->t_id); } else { - snprintf(thread->t_name, PTLRPC_THR_NAME_LEN, "%s_%04d", + snprintf(thread->t_name, sizeof(thread->t_name), "%s_%04d", svc->srv_thread_name, thread->t_id); } CDEBUG(D_RPCTRACE, "starting thread '%s'\n", thread->t_name); - rc = PTR_ERR(kthread_run(ptlrpc_main, thread, thread->t_name)); + rc = PTR_ERR(kthread_run(ptlrpc_main, thread, "%s", thread->t_name)); if (IS_ERR_VALUE(rc)) { CERROR("cannot start thread '%s': rc %d\n", thread->t_name, rc); diff --git a/drivers/staging/octeon/ethernet-mem.c b/drivers/staging/octeon/ethernet-mem.c index 78b6cb743769..199059d64c9b 100644 --- a/drivers/staging/octeon/ethernet-mem.c +++ b/drivers/staging/octeon/ethernet-mem.c @@ -48,13 +48,8 @@ static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements) while (freed) { struct sk_buff *skb = dev_alloc_skb(size + 256); - if (unlikely(skb == NULL)) { - pr_warning - ("Failed to allocate skb for hardware pool %d\n", - pool); + if (unlikely(skb == NULL)) break; - } - skb_reserve(skb, 256 - (((unsigned long)skb->data) & 0x7f)); *(struct sk_buff **)(skb->data - sizeof(void *)) = skb; cvmx_fpa_free(skb->data, pool, DONT_WRITEBACK(size / 128)); diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index d8f5f694ec35..ea53af30dfa7 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -373,9 +373,7 @@ int cvm_oct_rgmii_init(struct net_device *dev) * Enable interrupts on inband status changes * for this port. */ - gmx_rx_int_en.u64 = - cvmx_read_csr(CVMX_GMXX_RXX_INT_EN - (index, interface)); + gmx_rx_int_en.u64 = 0; gmx_rx_int_en.s.phy_dupx = 1; gmx_rx_int_en.s.phy_link = 1; gmx_rx_int_en.s.phy_spd = 1; diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 34afc16bc493..e14a1bb04361 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -303,6 +303,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) if (backlog > budget * cores_in_use && napi != NULL) cvm_oct_enable_one_cpu(); } + rx_count++; skb_in_hw = USE_SKBUFFS_IN_HW && work->word2.s.bufs == 1; if (likely(skb_in_hw)) { @@ -336,9 +337,6 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) */ skb = dev_alloc_skb(work->len); if (!skb) { - printk_ratelimited("Port %d failed to allocate " - "skbuff, packet dropped\n", - work->ipprt); cvm_oct_free_work(work); continue; } @@ -429,7 +427,6 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) #endif } netif_receive_skb(skb); - rx_count++; } else { /* Drop any packet received for a device that isn't up */ /* diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 3605c5da822d..6fc77428e83a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -157,8 +157,8 @@ _func_enter_; *frlen = *frlen + (len + 2); - return pbuf + len + 2; _func_exit_; + return pbuf + len + 2; } inline u8 *rtw_set_ie_ch_switch (u8 *buf, u32 *buf_len, u8 ch_switch_mode, diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 8b2ba26ba38d..4b2eb8e9b562 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -1827,13 +1827,13 @@ unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_fra #ifdef CONFIG_88EU_P2P -static int get_reg_classes_full_count(struct p2p_channels channel_list) +static int get_reg_classes_full_count(struct p2p_channels *channel_list) { int cnt = 0; int i; - for (i = 0; i < channel_list.reg_classes; i++) { - cnt += channel_list.reg_class[i].channels; + for (i = 0; i < channel_list->reg_classes; i++) { + cnt += channel_list->reg_class[i].channels; } return cnt; @@ -2065,7 +2065,7 @@ void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr) /* + number of channels in all classes */ len_channellist_attr = 3 + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes) - + get_reg_classes_full_count(pmlmeext->channel_list); + + get_reg_classes_full_count(&pmlmeext->channel_list); *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); p2pielen += 2; @@ -2437,7 +2437,7 @@ static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame /* + number of channels in all classes */ len_channellist_attr = 3 + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes - + get_reg_classes_full_count(pmlmeext->channel_list); + + get_reg_classes_full_count(&pmlmeext->channel_list); *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); @@ -2859,7 +2859,7 @@ void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr) /* + number of channels in all classes */ len_channellist_attr = 3 + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes - + get_reg_classes_full_count(pmlmeext->channel_list); + + get_reg_classes_full_count(&pmlmeext->channel_list); *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); @@ -3120,7 +3120,7 @@ void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr, u8 dialo /* + number of channels in all classes */ len_channellist_attr = 3 + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes - + get_reg_classes_full_count(pmlmeext->channel_list); + + get_reg_classes_full_count(&pmlmeext->channel_list); *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); p2pielen += 2; diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 013ea487e7ac..8018edd3d42e 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -631,7 +631,7 @@ void WMMOnAssocRsp(struct adapter *padapter) inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3; if (pregpriv->wifi_spec == 1) { - u32 j, tmp, change_inx; + u32 j, tmp, change_inx = false; /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */ for (i = 0; i < 4; i++) { diff --git a/drivers/staging/rtl8188eu/include/odm.h b/drivers/staging/rtl8188eu/include/odm.h index 2bfe72841921..4787bacdcad8 100644 --- a/drivers/staging/rtl8188eu/include/odm.h +++ b/drivers/staging/rtl8188eu/include/odm.h @@ -1010,7 +1010,7 @@ enum dm_dig_op { #define DM_false_ALARM_THRESH_LOW 400 #define DM_false_ALARM_THRESH_HIGH 1000 -#define DM_DIG_MAX_NIC 0x3e +#define DM_DIG_MAX_NIC 0x4e #define DM_DIG_MIN_NIC 0x1e /* 0x22/0x1c */ #define DM_DIG_MAX_AP 0x32 diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 52b280165a92..555c801d2ded 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -188,7 +188,7 @@ enum ChannelPlan { struct txpowerinfo24g { u8 IndexCCK_Base[MAX_RF_PATH][MAX_CHNL_GROUP_24G]; - u8 IndexBW40_Base[MAX_RF_PATH][MAX_CHNL_GROUP_24G-1]; + u8 IndexBW40_Base[MAX_RF_PATH][MAX_CHNL_GROUP_24G]; /* If only one tx, only BW20 and OFDM are used. */ s8 CCK_Diff[MAX_RF_PATH][MAX_TX_COUNT]; s8 OFDM_Diff[MAX_RF_PATH][MAX_TX_COUNT]; diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index a96b018e5e6a..853ab80a2b86 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -870,6 +870,7 @@ static struct fwevent wlanevents[] = { {0, NULL}, {0, NULL}, {0, &rtw_cpwm_event_callback}, + {0, NULL}, }; #endif/* _RTL_MLME_EXT_C_ */ diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index dbf11ecb794e..19d3cf451b88 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -172,8 +172,8 @@ static u16 swGetOFDMControlRate(struct vnt_private *pDevice, u16 wRateIdx) if (!CARDbIsOFDMinBasicRate(pDevice)) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "swGetOFDMControlRate:(NO OFDM) %d\n", wRateIdx); - if (wRateIdx > RATE_24M) - wRateIdx = RATE_24M; + if (wRateIdx > RATE_24M) + wRateIdx = RATE_24M; return wRateIdx; } diff --git a/drivers/staging/xillybus/xillybus_core.c b/drivers/staging/xillybus/xillybus_core.c index efc56987a60b..7db6f03a0054 100644 --- a/drivers/staging/xillybus/xillybus_core.c +++ b/drivers/staging/xillybus/xillybus_core.c @@ -2054,7 +2054,7 @@ static int xillybus_init_chrdev(struct xilly_endpoint *endpoint, NULL, MKDEV(major, i), NULL, - devname); + "%s", devname); if (IS_ERR(device)) { pr_warn("xillybus: Failed to create %s " diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 91d94b564433..2c4ed52ca849 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -981,4 +981,3 @@ MODULE_PARM_DESC(num_devices, "Number of zram devices"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>"); MODULE_DESCRIPTION("Compressed RAM Block Device"); -MODULE_ALIAS("devname:zram"); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index a9355ce1c6d5..3a1a01af9a80 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -854,7 +854,8 @@ void disassociate_ctty(int on_exit) struct pid *tty_pgrp = tty_get_pgrp(tty); if (tty_pgrp) { kill_pgrp(tty_pgrp, SIGHUP, on_exit); - kill_pgrp(tty_pgrp, SIGCONT, on_exit); + if (!on_exit) + kill_pgrp(tty_pgrp, SIGCONT, on_exit); put_pid(tty_pgrp); } } diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index b870872e020f..70fc43027a5c 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -1,7 +1,6 @@ config USB_DWC3 tristate "DesignWare USB3 DRD Core Support" depends on (USB || USB_GADGET) && HAS_DMA - depends on EXTCON select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD help Say Y or M here if your system has a Dual Role SuperSpeed diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 9b138129e856..997ebe420bc9 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -28,6 +28,7 @@ /* FIXME define these in <linux/pci_ids.h> */ #define PCI_VENDOR_ID_SYNOPSYS 0x16c3 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd +#define PCI_DEVICE_ID_INTEL_BYT 0x0f37 struct dwc3_pci { struct device *dev; @@ -187,6 +188,7 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = { PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), }, { } /* Terminating Entry */ }; MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index f168eaebdef8..5452c0fce360 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2611,15 +2611,13 @@ int dwc3_gadget_init(struct dwc3 *dwc) ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); if (ret) { dev_err(dwc->dev, "failed to register udc\n"); - goto err5; + goto err4; } return 0; -err5: - dwc3_gadget_free_endpoints(dwc); - err4: + dwc3_gadget_free_endpoints(dwc); dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE, dwc->ep0_bounce, dwc->ep0_bounce_addr); diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 5a5acf22c694..e126b6b248e6 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -113,12 +113,6 @@ static int __init cdc_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - fi_ecm = usb_get_function_instance("ecm"); - if (IS_ERR(fi_ecm)) { - status = PTR_ERR(fi_ecm); - goto err_func_ecm; - } - f_ecm = usb_get_function(fi_ecm); if (IS_ERR(f_ecm)) { status = PTR_ERR(f_ecm); @@ -129,35 +123,24 @@ static int __init cdc_do_config(struct usb_configuration *c) if (status) goto err_add_ecm; - fi_serial = usb_get_function_instance("acm"); - if (IS_ERR(fi_serial)) { - status = PTR_ERR(fi_serial); - goto err_get_acm; - } - f_acm = usb_get_function(fi_serial); if (IS_ERR(f_acm)) { status = PTR_ERR(f_acm); - goto err_func_acm; + goto err_get_acm; } status = usb_add_function(c, f_acm); if (status) goto err_add_acm; - return 0; err_add_acm: usb_put_function(f_acm); -err_func_acm: - usb_put_function_instance(fi_serial); err_get_acm: usb_remove_function(c, f_ecm); err_add_ecm: usb_put_function(f_ecm); err_get_ecm: - usb_put_function_instance(fi_ecm); -err_func_ecm: return status; } diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 06ecd08fd57a..b8a2376971a4 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -923,8 +923,9 @@ static int dummy_udc_stop(struct usb_gadget *g, struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g); struct dummy *dum = dum_hcd->dum; - dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n", - driver->driver.name); + if (driver) + dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n", + driver->driver.name); dum->driver = NULL; @@ -1000,8 +1001,8 @@ static int dummy_udc_remove(struct platform_device *pdev) { struct dummy *dum = platform_get_drvdata(pdev); - usb_del_gadget_udc(&dum->gadget); device_remove_file(&dum->gadget.dev, &dev_attr_function); + usb_del_gadget_udc(&dum->gadget); return 0; } diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index edab45da3741..8d9e6f7e8f1a 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -995,7 +995,7 @@ static void ecm_unbind(struct usb_configuration *c, struct usb_function *f) usb_ep_free_request(ecm->notify, ecm->notify_req); } -struct usb_function *ecm_alloc(struct usb_function_instance *fi) +static struct usb_function *ecm_alloc(struct usb_function_instance *fi) { struct f_ecm *ecm; struct f_ecm_opts *opts; diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index d00392d879db..d61c11d765d0 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c @@ -624,7 +624,7 @@ static void eem_unbind(struct usb_configuration *c, struct usb_function *f) usb_free_all_descriptors(f); } -struct usb_function *eem_alloc(struct usb_function_instance *fi) +static struct usb_function *eem_alloc(struct usb_function_instance *fi) { struct f_eem *eem; struct f_eem_opts *opts; diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 313b835eedfd..a01d7d38c016 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2260,10 +2260,12 @@ reset: /* Disable the endpoints */ if (fsg->bulk_in_enabled) { usb_ep_disable(fsg->bulk_in); + fsg->bulk_in->driver_data = NULL; fsg->bulk_in_enabled = 0; } if (fsg->bulk_out_enabled) { usb_ep_disable(fsg->bulk_out); + fsg->bulk_out->driver_data = NULL; fsg->bulk_out_enabled = 0; } diff --git a/drivers/usb/gadget/fotg210-udc.c b/drivers/usb/gadget/fotg210-udc.c index 32db2eee2d87..bbbfd1948778 100644 --- a/drivers/usb/gadget/fotg210-udc.c +++ b/drivers/usb/gadget/fotg210-udc.c @@ -1214,6 +1214,6 @@ static struct platform_driver fotg210_driver = { module_platform_driver(fotg210_driver); -MODULE_AUTHOR("Yuan-Hsin Chen <yhchen@faraday-tech.com>"); +MODULE_AUTHOR("Yuan-Hsin Chen, Feng-Hsin Chiang <john453@faraday-tech.com>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index f1dd6daabe21..b278abe52453 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -22,7 +22,7 @@ MODULE_DESCRIPTION("FUSB300 USB gadget driver"); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Yuan Hsin Chen <yhchen@faraday-tech.com>"); +MODULE_AUTHOR("Yuan-Hsin Chen, Feng-Hsin Chiang <john453@faraday-tech.com>"); MODULE_ALIAS("platform:fusb300_udc"); #define DRIVER_VERSION "20 October 2010" diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 2a1ebefd8f9e..23393254a8a3 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -179,7 +179,7 @@ err_conf: return ret; } -static int rndis_config_register(struct usb_composite_dev *cdev) +static __ref int rndis_config_register(struct usb_composite_dev *cdev) { static struct usb_configuration config = { .bConfigurationValue = MULTI_RNDIS_CONFIG_NUM, @@ -194,7 +194,7 @@ static int rndis_config_register(struct usb_composite_dev *cdev) #else -static int rndis_config_register(struct usb_composite_dev *cdev) +static __ref int rndis_config_register(struct usb_composite_dev *cdev) { return 0; } @@ -241,7 +241,7 @@ err_conf: return ret; } -static int cdc_config_register(struct usb_composite_dev *cdev) +static __ref int cdc_config_register(struct usb_composite_dev *cdev) { static struct usb_configuration config = { .bConfigurationValue = MULTI_CDC_CONFIG_NUM, @@ -256,7 +256,7 @@ static int cdc_config_register(struct usb_composite_dev *cdev) #else -static int cdc_config_register(struct usb_composite_dev *cdev) +static __ref int cdc_config_register(struct usb_composite_dev *cdev) { return 0; } diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index bbb6e98c4384..561b30efb8ee 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -645,6 +645,7 @@ static int mv_u3d_ep_disable(struct usb_ep *_ep) struct mv_u3d_ep *ep; struct mv_u3d_ep_context *ep_context; u32 epxcr, direction; + unsigned long flags; if (!_ep) return -EINVAL; @@ -661,7 +662,9 @@ static int mv_u3d_ep_disable(struct usb_ep *_ep) direction = mv_u3d_ep_dir(ep); /* nuke all pending requests (does flush) */ + spin_lock_irqsave(&u3d->lock, flags); mv_u3d_nuke(ep, -ESHUTDOWN); + spin_unlock_irqrestore(&u3d->lock, flags); /* Disable the endpoint for Rx or Tx and reset the endpoint type */ if (direction == MV_U3D_EP_DIR_OUT) { diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index d69b36a99dbc..6bddf1aa2347 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2475,8 +2475,6 @@ irq_retry: if (gintsts & GINTSTS_ErlySusp) { dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n"); writel(GINTSTS_ErlySusp, hsotg->regs + GINTSTS); - - s3c_hsotg_disconnect(hsotg); } /* @@ -2962,9 +2960,6 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, if (!hsotg) return -ENODEV; - if (!driver || driver != hsotg->driver || !driver->unbind) - return -EINVAL; - /* all endpoints should be shutdown */ for (ep = 0; ep < hsotg->num_of_eps; ep++) s3c_hsotg_ep_disable(&hsotg->eps[ep].ep); @@ -2972,15 +2967,15 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, spin_lock_irqsave(&hsotg->lock, flags); s3c_hsotg_phy_disable(hsotg); - regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); - hsotg->driver = NULL; + if (!driver) + hsotg->driver = NULL; + hsotg->gadget.speed = USB_SPEED_UNKNOWN; spin_unlock_irqrestore(&hsotg->lock, flags); - dev_info(hsotg->dev, "unregistered gadget driver '%s'\n", - driver->driver.name); + regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); return 0; } diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index e41cfdc9bf93..848fc46ad80c 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -669,7 +669,7 @@ static const struct hc_driver ehci_fsl_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_USB2 | HCD_MEMORY | HCD_BH, + .flags = HCD_USB2 | HCD_MEMORY, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c index b52a66ce92e8..83ab51af250f 100644 --- a/drivers/usb/host/ehci-grlib.c +++ b/drivers/usb/host/ehci-grlib.c @@ -43,7 +43,7 @@ static const struct hc_driver ehci_grlib_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_USB2, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 5d6022f30ebe..86ab9fd9fe9e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1158,7 +1158,7 @@ static const struct hc_driver ehci_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_USB2, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 417c10da9450..35cdbd88bbbe 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -96,7 +96,7 @@ static const struct hc_driver mv_ehci_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_USB2, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c index ab0397e4d8f3..45cc00158412 100644 --- a/drivers/usb/host/ehci-octeon.c +++ b/drivers/usb/host/ehci-octeon.c @@ -51,7 +51,7 @@ static const struct hc_driver ehci_octeon_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_USB2, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c index 893b707f0000..601e208bd782 100644 --- a/drivers/usb/host/ehci-pmcmsp.c +++ b/drivers/usb/host/ehci-pmcmsp.c @@ -286,7 +286,7 @@ static const struct hc_driver ehci_msp_hc_driver = { #else .irq = ehci_irq, #endif - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_USB2, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 6cc5567bf9c8..932293fa32de 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -28,7 +28,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_USB2, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 8188542ba17e..fd983771b025 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -71,7 +71,7 @@ static const struct hc_driver ps3_ehci_hc_driver = { .product_desc = "PS3 EHCI Host Controller", .hcd_priv_size = sizeof(struct ehci_hcd), .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_USB2, .reset = ps3_ehci_hc_reset, .start = ehci_run, .stop = ehci_stop, diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index e321804c3475..a7f776a13eb1 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -247,6 +247,8 @@ static int qtd_copy_status ( static void ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status) +__releases(ehci->lock) +__acquires(ehci->lock) { if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { /* ... update hc-wide periodic stats */ @@ -272,8 +274,11 @@ ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status) urb->actual_length, urb->transfer_buffer_length); #endif + /* complete() can reenter this HCD */ usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); + spin_unlock (&ehci->lock); usb_hcd_giveback_urb(ehci_to_hcd(ehci), urb, status); + spin_lock (&ehci->lock); } static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c index 8a734498079b..b2de52d39614 100644 --- a/drivers/usb/host/ehci-sead3.c +++ b/drivers/usb/host/ehci-sead3.c @@ -55,7 +55,7 @@ const struct hc_driver ehci_sead3_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_USB2, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index dc899eb2b861..93e59a13bc1f 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -36,7 +36,7 @@ static const struct hc_driver ehci_sh_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_USB2 | HCD_MEMORY | HCD_BH, + .flags = HCD_USB2 | HCD_MEMORY, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-tilegx.c b/drivers/usb/host/ehci-tilegx.c index 67026ffbf9a8..cca4be90a864 100644 --- a/drivers/usb/host/ehci-tilegx.c +++ b/drivers/usb/host/ehci-tilegx.c @@ -61,7 +61,7 @@ static const struct hc_driver ehci_tilegx_hc_driver = { * Generic hardware linkage. */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_USB2, /* * Basic lifecycle operations. diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c index 1c370dfbee0d..59e0e24c753f 100644 --- a/drivers/usb/host/ehci-w90x900.c +++ b/drivers/usb/host/ehci-w90x900.c @@ -108,7 +108,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_USB2|HCD_MEMORY|HCD_BH, + .flags = HCD_USB2|HCD_MEMORY, /* * basic lifecycle operations diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 95979f9f4381..eba962e6ebfb 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -79,7 +79,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { * generic hardware linkage */ .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, + .flags = HCD_MEMORY | HCD_USB2, /* * basic lifecycle operations diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 9e0020d9e4c8..abd5050a4899 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -24,7 +24,7 @@ struct fsl_usb2_dev_data { enum fsl_usb2_operating_modes op_mode; /* operating mode */ }; -struct fsl_usb2_dev_data dr_mode_data[] = { +static struct fsl_usb2_dev_data dr_mode_data[] = { { .dr_mode = "host", .drivers = { "fsl-ehci", NULL, NULL, }, @@ -42,7 +42,7 @@ struct fsl_usb2_dev_data dr_mode_data[] = { }, }; -struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np) +static struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np) { const unsigned char *prop; int i; @@ -75,7 +75,7 @@ static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type) return FSL_USB2_PHY_NONE; } -struct platform_device *fsl_usb2_device_register( +static struct platform_device *fsl_usb2_device_register( struct platform_device *ofdev, struct fsl_usb2_platform_data *pdata, const char *name, int id) diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c index fc15694d3031..4e8a0405f956 100644 --- a/drivers/usb/phy/phy-omap-usb3.c +++ b/drivers/usb/phy/phy-omap-usb3.c @@ -79,7 +79,7 @@ static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate) return &dpll_map[i].params; } - return 0; + return NULL; } static int omap_usb3_suspend(struct usb_phy *x, int suspend) diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index c454bfa22a10..ddb9c51f2c99 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -60,7 +60,7 @@ config USB_SERIAL_SIMPLE - Suunto ANT+ USB device. - Fundamental Software dongle. - HP4x calculators - - a number of Motoroloa phones + - a number of Motorola phones - Siemens USB/MPI adapter. - ViVOtech ViVOpay USB device. - Infineon Modem Flashloader USB interface diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index e7a84f0f5179..bedf8e47713b 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -139,6 +139,7 @@ enum pl2303_type { HX_TA, /* HX(A) / X(A) / TA version */ /* TODO: improve */ HXD_EA_RA_SA, /* HXD / EA / RA / SA version */ /* TODO: improve */ TB, /* TB version */ + HX_CLONE, /* Cheap and less functional clone of the HX chip */ }; /* * NOTE: don't know the difference between type 0 and type 1, @@ -206,8 +207,23 @@ static int pl2303_startup(struct usb_serial *serial) * the device descriptors of the X/HX, HXD, EA, RA, SA, TA, TB */ if (le16_to_cpu(serial->dev->descriptor.bcdDevice) == 0x300) { - type = HX_TA; - type_str = "X/HX/TA"; + /* Check if the device is a clone */ + pl2303_vendor_read(0x9494, 0, serial, buf); + /* + * NOTE: Not sure if this read is really needed. + * The HX returns 0x00, the clone 0x02, but the Windows + * driver seems to ignore the value and continues. + */ + pl2303_vendor_write(0x0606, 0xaa, serial); + pl2303_vendor_read(0x8686, 0, serial, buf); + if (buf[0] != 0xaa) { + type = HX_CLONE; + type_str = "X/HX clone (limited functionality)"; + } else { + type = HX_TA; + type_str = "X/HX/TA"; + } + pl2303_vendor_write(0x0606, 0x00, serial); } else if (le16_to_cpu(serial->dev->descriptor.bcdDevice) == 0x400) { type = HXD_EA_RA_SA; @@ -305,8 +321,9 @@ static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type, { /* * NOTE: Only the values defined in baud_sup are supported ! - * => if unsupported values are set, the PL2303 seems to - * use 9600 baud (at least my PL2303X always does) + * => if unsupported values are set, the PL2303 uses 9600 baud instead + * => HX clones just don't work at unsupported baud rates < 115200 baud, + * for baud rates > 115200 they run at 115200 baud */ const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400, 19200, 28800, 38400, @@ -316,14 +333,14 @@ static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type, * NOTE: With the exception of type_0/1 devices, the following * additional baud rates are supported (tested with HX rev. 3A only): * 110*, 56000*, 128000, 134400, 161280, 201600, 256000*, 268800, - * 403200, 806400. (*: not HX) + * 403200, 806400. (*: not HX and HX clones) * * Maximum values: HXD, TB: 12000000; HX, TA: 6000000; - * type_0+1: 1228800; RA: 921600; SA: 115200 + * type_0+1: 1228800; RA: 921600; HX clones, SA: 115200 * * As long as we are not using this encoding method for anything else - * than the type_0+1 and HX chips, there is no point in complicating - * the code to support them. + * than the type_0+1, HX and HX clone chips, there is no point in + * complicating the code to support them. */ int i; @@ -347,6 +364,8 @@ static int pl2303_baudrate_encode_direct(int baud, enum pl2303_type type, baud = min_t(int, baud, 6000000); else if (type == type_0 || type == type_1) baud = min_t(int, baud, 1228800); + else if (type == HX_CLONE) + baud = min_t(int, baud, 115200); /* Direct (standard) baud rate encoding method */ put_unaligned_le32(baud, buf); @@ -359,7 +378,8 @@ static int pl2303_baudrate_encode_divisor(int baud, enum pl2303_type type, /* * Divisor based baud rate encoding method * - * NOTE: it's not clear if the type_0/1 chips support this method + * NOTE: HX clones do NOT support this method. + * It's not clear if the type_0/1 chips support it. * * divisor = 12MHz * 32 / baudrate = 2^A * B * @@ -452,7 +472,7 @@ static void pl2303_encode_baudrate(struct tty_struct *tty, * 1) Direct method: encodes the baud rate value directly * => supported by all chip types * 2) Divisor based method: encodes a divisor to a base value (12MHz*32) - * => supported by HX chips (and likely not by type_0/1 chips) + * => not supported by HX clones (and likely type_0/1 chips) * * NOTE: Although the divisor based baud rate encoding method is much * more flexible, some of the standard baud rate values can not be @@ -460,7 +480,7 @@ static void pl2303_encode_baudrate(struct tty_struct *tty, * the device likely uses the same baud rate generator for both methods * so that there is likley no difference. */ - if (type == type_0 || type == type_1) + if (type == type_0 || type == type_1 || type == HX_CLONE) baud = pl2303_baudrate_encode_direct(baud, type, buf); else baud = pl2303_baudrate_encode_divisor(baud, type, buf); @@ -813,6 +833,7 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state) result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 0, NULL, 0, 100); + /* NOTE: HX clones don't support sending breaks, -EPIPE is returned */ if (result) dev_err(&port->dev, "error sending break = %d\n", result); } diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 4b79a1f2f901..592b31698fc8 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -461,7 +461,7 @@ static void tcm_vhost_release_cmd(struct se_cmd *se_cmd) u32 i; for (i = 0; i < tv_cmd->tvc_sgl_count; i++) put_page(sg_page(&tv_cmd->tvc_sgl[i])); - } + } tcm_vhost_put_inflight(tv_cmd->inflight); percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag); @@ -1373,21 +1373,30 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) return 0; } +static void vhost_scsi_free(struct vhost_scsi *vs) +{ + if (is_vmalloc_addr(vs)) + vfree(vs); + else + kfree(vs); +} + static int vhost_scsi_open(struct inode *inode, struct file *f) { struct vhost_scsi *vs; struct vhost_virtqueue **vqs; - int r, i; + int r = -ENOMEM, i; - vs = kzalloc(sizeof(*vs), GFP_KERNEL); - if (!vs) - return -ENOMEM; + vs = kzalloc(sizeof(*vs), GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT); + if (!vs) { + vs = vzalloc(sizeof(*vs)); + if (!vs) + goto err_vs; + } vqs = kmalloc(VHOST_SCSI_MAX_VQ * sizeof(*vqs), GFP_KERNEL); - if (!vqs) { - kfree(vs); - return -ENOMEM; - } + if (!vqs) + goto err_vqs; vhost_work_init(&vs->vs_completion_work, vhost_scsi_complete_cmd_work); vhost_work_init(&vs->vs_event_work, tcm_vhost_evt_work); @@ -1407,14 +1416,18 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) tcm_vhost_init_inflight(vs, NULL); - if (r < 0) { - kfree(vqs); - kfree(vs); - return r; - } + if (r < 0) + goto err_init; f->private_data = vs; return 0; + +err_init: + kfree(vqs); +err_vqs: + vhost_scsi_free(vs); +err_vs: + return r; } static int vhost_scsi_release(struct inode *inode, struct file *f) @@ -1431,7 +1444,7 @@ static int vhost_scsi_release(struct inode *inode, struct file *f) /* Jobs can re-queue themselves in evt kick handler. Do extra flush. */ vhost_scsi_flush(vs); kfree(vs->dev.vqs); - kfree(vs); + vhost_scsi_free(vs); return 0; } diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 9a9502a4aa50..69068e0d8f31 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -161,9 +161,11 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work) if (list_empty(&work->node)) { list_add_tail(&work->node, &dev->work_list); work->queue_seq++; + spin_unlock_irqrestore(&dev->work_lock, flags); wake_up_process(dev->worker); + } else { + spin_unlock_irqrestore(&dev->work_lock, flags); } - spin_unlock_irqrestore(&dev->work_lock, flags); } EXPORT_SYMBOL_GPL(vhost_work_queue); |