From 1d002fa720738bcd0bddb9178e9ea0773288e1dd Mon Sep 17 00:00:00 2001 From: Simon Farnsworth Date: Tue, 10 Feb 2015 18:38:08 +0000 Subject: drm/dp: Use large transactions for I2C over AUX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Older DisplayPort to DVI-D Dual Link adapters designed by Bizlink have bugs in their I2C over AUX implementation (fixed in newer revisions). They work fine with Windows, but fail with Linux. It turns out that they cannot keep an I2C transaction open unless the previous read was 16 bytes; shorter reads can only be followed by a zero byte transfer ending the I2C transaction. Copy Windows's behaviour, and read 16 bytes at a time. If we get a short reply, assume that there's a hardware bottleneck, and shrink our read size to match. For this purpose, use the algorithm in the DisplayPort 1.2 spec, in the hopes that it'll be closest to what Windows does. Also provide an unsafe module parameter for testing smaller transfer sizes, in case there are sinks out there that cannot work with Windows. Note also that despite the previous comment in drm_dp_i2c_xfer, this speeds up native DP EDID reads; Ville Syrjälä found the following changes in his testing: Device under test: old -> with this patch DP->DVI (OUI 001cf8): 40ms -> 35ms DP->VGA (OUI 0022b9): 45ms -> 38ms Zotac DP->2xHDMI: 25ms -> 4ms Asus PB278 monitor: 22ms -> 3ms A back of the envelope calculation shows that peak theoretical transfer rate for 1 byte reads is around 60 kbit/s; with 16 byte reads, this increases to around 500 kbit/s, which explains the increase in speed. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55228 Tested-by: Aidan Marks (v3) Signed-off-by: Simon Farnsworth Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- include/drm/drm_dp_helper.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index c5fdc2d3ca97..523f04c90dea 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -42,6 +42,8 @@ * 1.2 formally includes both eDP and DPI definitions. */ +#define DP_AUX_MAX_PAYLOAD_BYTES 16 + #define DP_AUX_I2C_WRITE 0x0 #define DP_AUX_I2C_READ 0x1 #define DP_AUX_I2C_STATUS 0x2 @@ -680,6 +682,9 @@ struct drm_dp_aux_msg { * transactions. The drm_dp_aux_register_i2c_bus() function registers an * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter. + * The I2C adapter uses long transfers by default; if a partial response is + * received, the adapter will drop down to the size given by the partial + * response for this transaction only. * * Note that the aux helper code assumes that the .transfer() function * only modifies the reply field of the drm_dp_aux_msg structure. The -- cgit v1.2.3 From b7b5ee593118f9dc884fc21237f51b9f599cc432 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 11 Mar 2015 10:23:08 -0400 Subject: drm/fb: document drm_fb_helper_surface_size There has been some confusion about this struct. Lack of documentation probably didn't help. Signed-off-by: Rob Clark Reviewed-by: Alex Deucher Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter --- include/drm/drm_fb_helper.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'include') diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 21b944c456f6..0dfd94def593 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -44,6 +44,25 @@ struct drm_fb_helper_crtc { int x, y; }; +/** + * struct drm_fb_helper_surface_size - describes fbdev size and scanout surface size + * @fb_width: fbdev width + * @fb_height: fbdev height + * @surface_width: scanout buffer width + * @surface_height: scanout buffer height + * @surface_bpp: scanout buffer bpp + * @surface_depth: scanout buffer depth + * + * Note that the scanout surface width/height may be larger than the fbdev + * width/height. In case of multiple displays, the scanout surface is sized + * according to the largest width/height (so it is large enough for all CRTCs + * to scanout). But the fbdev width/height is sized to the minimum width/ + * height of all the displays. This ensures that fbcon fits on the smallest + * of the attached displays. + * + * So what is passed to drm_fb_helper_fill_var() should be fb_width/fb_height, + * rather than the surface size. + */ struct drm_fb_helper_surface_size { u32 fb_width; u32 fb_height; -- cgit v1.2.3 From 08855fae10f088d83527bdf108199d3e35be503b Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 11 Mar 2015 10:23:09 -0400 Subject: drm/atomic: minor kerneldoc typo fix Signed-off-by: Rob Clark Reviewed-by: Alex Deucher Acked-by: Laurent Pinchart Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index adc9ea5acf02..7b5c661b37d8 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -915,7 +915,7 @@ struct drm_bridge { }; /** - * struct struct drm_atomic_state - the global state object for atomic updates + * struct drm_atomic_state - the global state object for atomic updates * @dev: parent DRM device * @allow_modeset: allow full modeset * @legacy_cursor_update: hint to enforce legacy cursor ioctl semantics -- cgit v1.2.3 From a2f4870697a5bcf4a87073ec6b32dd2928c1211d Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 17 Mar 2015 12:23:19 -0400 Subject: fs: make sure the timestamps for lazytime inodes eventually get written Jan Kara pointed out that if there is an inode which is constantly getting dirtied with I_DIRTY_PAGES, an inode with an updated timestamp will never be written since inode->dirtied_when is constantly getting updated. We fix this by adding an extra field to the inode, dirtied_time_when, so inodes with a stale dirtytime can get detected and handled. In addition, if we have a dirtytime inode caused by an atime update, and there is no write activity on the file system, we need to have a secondary system to make sure these inodes get written out. We do this by setting up a second delayed work structure which wakes up the CPU much more rarely compared to writeback_expire_centisecs. Signed-off-by: Theodore Ts'o Reviewed-by: Jan Kara --- fs/fs-writeback.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++------- include/linux/fs.h | 1 + 2 files changed, 73 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index e907052eeadb..2cfcd74faf87 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -53,6 +53,18 @@ struct wb_writeback_work { struct completion *done; /* set if the caller waits */ }; +/* + * If an inode is constantly having its pages dirtied, but then the + * updates stop dirtytime_expire_interval seconds in the past, it's + * possible for the worst case time between when an inode has its + * timestamps updated and when they finally get written out to be two + * dirtytime_expire_intervals. We set the default to 12 hours (in + * seconds), which means most of the time inodes will have their + * timestamps written to disk after 12 hours, but in the worst case a + * few inodes might not their timestamps updated for 24 hours. + */ +unsigned int dirtytime_expire_interval = 12 * 60 * 60; + /** * writeback_in_progress - determine whether there is writeback in progress * @bdi: the device's backing_dev_info structure. @@ -275,8 +287,8 @@ static int move_expired_inodes(struct list_head *delaying_queue, if ((flags & EXPIRE_DIRTY_ATIME) == 0) older_than_this = work->older_than_this; - else if ((work->reason == WB_REASON_SYNC) == 0) { - expire_time = jiffies - (HZ * 86400); + else if (!work->for_sync) { + expire_time = jiffies - (dirtytime_expire_interval * HZ); older_than_this = &expire_time; } while (!list_empty(delaying_queue)) { @@ -458,6 +470,7 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb, */ redirty_tail(inode, wb); } else if (inode->i_state & I_DIRTY_TIME) { + inode->dirtied_when = jiffies; list_move(&inode->i_wb_list, &wb->b_dirty_time); } else { /* The inode is clean. Remove from writeback lists. */ @@ -505,12 +518,17 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) spin_lock(&inode->i_lock); dirty = inode->i_state & I_DIRTY; - if (((dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) && - (inode->i_state & I_DIRTY_TIME)) || - (inode->i_state & I_DIRTY_TIME_EXPIRED)) { - dirty |= I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED; - trace_writeback_lazytime(inode); - } + if (inode->i_state & I_DIRTY_TIME) { + if ((dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) || + unlikely(inode->i_state & I_DIRTY_TIME_EXPIRED) || + unlikely(time_after(jiffies, + (inode->dirtied_time_when + + dirtytime_expire_interval * HZ)))) { + dirty |= I_DIRTY_TIME | I_DIRTY_TIME_EXPIRED; + trace_writeback_lazytime(inode); + } + } else + inode->i_state &= ~I_DIRTY_TIME_EXPIRED; inode->i_state &= ~dirty; /* @@ -1131,6 +1149,45 @@ void wakeup_flusher_threads(long nr_pages, enum wb_reason reason) rcu_read_unlock(); } +/* + * Wake up bdi's periodically to make sure dirtytime inodes gets + * written back periodically. We deliberately do *not* check the + * b_dirtytime list in wb_has_dirty_io(), since this would cause the + * kernel to be constantly waking up once there are any dirtytime + * inodes on the system. So instead we define a separate delayed work + * function which gets called much more rarely. (By default, only + * once every 12 hours.) + * + * If there is any other write activity going on in the file system, + * this function won't be necessary. But if the only thing that has + * happened on the file system is a dirtytime inode caused by an atime + * update, we need this infrastructure below to make sure that inode + * eventually gets pushed out to disk. + */ +static void wakeup_dirtytime_writeback(struct work_struct *w); +static DECLARE_DELAYED_WORK(dirtytime_work, wakeup_dirtytime_writeback); + +static void wakeup_dirtytime_writeback(struct work_struct *w) +{ + struct backing_dev_info *bdi; + + rcu_read_lock(); + list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) { + if (list_empty(&bdi->wb.b_dirty_time)) + continue; + bdi_wakeup_thread(bdi); + } + rcu_read_unlock(); + schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ); +} + +static int __init start_dirtytime_writeback(void) +{ + schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ); + return 0; +} +__initcall(start_dirtytime_writeback); + static noinline void block_dump___mark_inode_dirty(struct inode *inode) { if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) { @@ -1269,8 +1326,13 @@ void __mark_inode_dirty(struct inode *inode, int flags) } inode->dirtied_when = jiffies; - list_move(&inode->i_wb_list, dirtytime ? - &bdi->wb.b_dirty_time : &bdi->wb.b_dirty); + if (dirtytime) + inode->dirtied_time_when = jiffies; + if (inode->i_state & (I_DIRTY_INODE | I_DIRTY_PAGES)) + list_move(&inode->i_wb_list, &bdi->wb.b_dirty); + else + list_move(&inode->i_wb_list, + &bdi->wb.b_dirty_time); spin_unlock(&bdi->wb.list_lock); trace_writeback_dirty_inode_enqueue(inode); diff --git a/include/linux/fs.h b/include/linux/fs.h index b4d71b5e1ff2..f4131e8ead74 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -604,6 +604,7 @@ struct inode { struct mutex i_mutex; unsigned long dirtied_when; /* jiffies of first dirtying */ + unsigned long dirtied_time_when; struct hlist_node i_hash; struct list_head i_wb_list; /* backing dev IO list */ -- cgit v1.2.3 From 1efff914afac8a965ad63817ecf8861a927c2ace Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 17 Mar 2015 12:23:32 -0400 Subject: fs: add dirtytime_expire_seconds sysctl Add a tuning knob so we can adjust the dirtytime expiration timeout, which is very useful for testing lazytime. Signed-off-by: Theodore Ts'o Reviewed-by: Jan Kara --- fs/fs-writeback.c | 11 +++++++++++ include/linux/writeback.h | 3 +++ kernel/sysctl.c | 8 ++++++++ 3 files changed, 22 insertions(+) (limited to 'include') diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 2cfcd74faf87..32a8bbd7a9ad 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1188,6 +1188,17 @@ static int __init start_dirtytime_writeback(void) } __initcall(start_dirtytime_writeback); +int dirtytime_interval_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int ret; + + ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); + if (ret == 0 && write) + mod_delayed_work(system_wq, &dirtytime_work, 0); + return ret; +} + static noinline void block_dump___mark_inode_dirty(struct inode *inode) { if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) { diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 00048339c23e..b2dd371ec0ca 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -130,6 +130,7 @@ extern int vm_dirty_ratio; extern unsigned long vm_dirty_bytes; extern unsigned int dirty_writeback_interval; extern unsigned int dirty_expire_interval; +extern unsigned int dirtytime_expire_interval; extern int vm_highmem_is_dirtyable; extern int block_dump; extern int laptop_mode; @@ -146,6 +147,8 @@ extern int dirty_ratio_handler(struct ctl_table *table, int write, extern int dirty_bytes_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); +int dirtytime_interval_handler(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos); struct ctl_table; int dirty_writeback_centisecs_handler(struct ctl_table *, int, diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 88ea2d6e0031..ce410bb9f2e1 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1227,6 +1227,14 @@ static struct ctl_table vm_table[] = { .proc_handler = proc_dointvec_minmax, .extra1 = &zero, }, + { + .procname = "dirtytime_expire_seconds", + .data = &dirtytime_expire_interval, + .maxlen = sizeof(dirty_expire_interval), + .mode = 0644, + .proc_handler = dirtytime_interval_handler, + .extra1 = &zero, + }, { .procname = "nr_pdflush_threads", .mode = 0444 /* read-only */, -- cgit v1.2.3 From d6d2a1882a79c1a5425d6f82b2fc7b934916f893 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 30 Sep 2014 10:04:40 -0400 Subject: drm/radeon: add INFO query for GPU temperature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Useful for profiling. Tested-by: Marek Olšák Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_kms.c | 7 +++++++ include/uapi/drm/radeon_drm.h | 1 + 2 files changed, 8 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 686411e4e4f6..7904887c6cc7 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -547,6 +547,13 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file else *value = 1; break; + case RADEON_INFO_CURRENT_GPU_TEMP: + /* get temperature in millidegrees C */ + if (rdev->asic->pm.get_temperature) + *value = radeon_get_temperature(rdev); + else + *value = 0; + break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->request); return -EINVAL; diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h index 50d0fb41a3bf..66b1131bb296 100644 --- a/include/uapi/drm/radeon_drm.h +++ b/include/uapi/drm/radeon_drm.h @@ -1034,6 +1034,7 @@ struct drm_radeon_cs { #define RADEON_INFO_VRAM_USAGE 0x1e #define RADEON_INFO_GTT_USAGE 0x1f #define RADEON_INFO_ACTIVE_CU_COUNT 0x20 +#define RADEON_INFO_CURRENT_GPU_TEMP 0x21 struct drm_radeon_info { uint32_t request; -- cgit v1.2.3 From 5c363a860398e2a09e5cff7f4654cf82ed8485e1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 30 Sep 2014 11:33:30 -0400 Subject: drm/radeon: add INFO query for current sclk/mclk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow the UMDs to query the current sclk/mclk for profiling, etc. Tested-by: Marek Olšák Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_kms.c | 14 ++++++++++++++ include/uapi/drm/radeon_drm.h | 2 ++ 2 files changed, 16 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 7904887c6cc7..cf7e54e9b0d1 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -554,6 +554,20 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file else *value = 0; break; + case RADEON_INFO_CURRENT_GPU_SCLK: + /* get sclk in Mhz */ + if (rdev->pm.dpm_enabled) + *value = radeon_dpm_get_current_sclk(rdev) / 100; + else + *value = rdev->pm.current_sclk / 100; + break; + case RADEON_INFO_CURRENT_GPU_MCLK: + /* get mclk in Mhz */ + if (rdev->pm.dpm_enabled) + *value = radeon_dpm_get_current_mclk(rdev) / 100; + else + *value = rdev->pm.current_mclk / 100; + break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->request); return -EINVAL; diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h index 66b1131bb296..de7ee21efea2 100644 --- a/include/uapi/drm/radeon_drm.h +++ b/include/uapi/drm/radeon_drm.h @@ -1035,6 +1035,8 @@ struct drm_radeon_cs { #define RADEON_INFO_GTT_USAGE 0x1f #define RADEON_INFO_ACTIVE_CU_COUNT 0x20 #define RADEON_INFO_CURRENT_GPU_TEMP 0x21 +#define RADEON_INFO_CURRENT_GPU_SCLK 0x22 +#define RADEON_INFO_CURRENT_GPU_MCLK 0x23 struct drm_radeon_info { uint32_t request; -- cgit v1.2.3 From 4535cb9cefbc736b47bc1e7f8628065aba5ca0d7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 1 Oct 2014 11:26:50 -0400 Subject: drm/radeon: add support for read reg query from radeon info ioctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to query certain registers from userspace for profiling and harvest configuration. E.g., it can be used by the GALLIUM_HUD for profiling the status of various gfx blocks. Tested-by: Marek Olšák Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_kms.c | 8 ++++++++ include/uapi/drm/radeon_drm.h | 1 + 2 files changed, 9 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index cf7e54e9b0d1..7b2a7335cc5d 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -568,6 +568,14 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file else *value = rdev->pm.current_mclk / 100; break; + case RADEON_INFO_READ_REG: + if (copy_from_user(value, value_ptr, sizeof(uint32_t))) { + DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); + return -EFAULT; + } + if (radeon_get_allowed_info_register(rdev, *value, value)) + return -EINVAL; + break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->request); return -EINVAL; diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h index de7ee21efea2..871e73f99a4d 100644 --- a/include/uapi/drm/radeon_drm.h +++ b/include/uapi/drm/radeon_drm.h @@ -1037,6 +1037,7 @@ struct drm_radeon_cs { #define RADEON_INFO_CURRENT_GPU_TEMP 0x21 #define RADEON_INFO_CURRENT_GPU_SCLK 0x22 #define RADEON_INFO_CURRENT_GPU_MCLK 0x23 +#define RADEON_INFO_READ_REG 0x24 struct drm_radeon_info { uint32_t request; -- cgit v1.2.3 From 87f5942d1f7bc320a0ec70ac4a8a3396024c7091 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 24 Feb 2015 09:23:55 +1000 Subject: drm/dp_mst: add a function to retrieve vcpi slots radeon requires this to get the slots for later filling out a table on every transition. Signed-off-by: Dave Airlie Signed-off-by: Alex Deucher --- drivers/gpu/drm/drm_dp_mst_topology.c | 13 +++++++++++++ include/drm/drm_dp_mst_helper.h | 2 ++ 2 files changed, 15 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 9a5b68717ec8..0d15e6e30732 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2319,6 +2319,19 @@ out: } EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi); +int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) +{ + int slots = 0; + port = drm_dp_get_validated_port_ref(mgr, port); + if (!port) + return slots; + + slots = port->vcpi.num_slots; + drm_dp_put_port(port); + return slots; +} +EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots); + /** * drm_dp_mst_reset_vcpi_slots() - Reset number of slots to 0 for VCPI * @mgr: manager for this port diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 00c1da927245..a2507817be41 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -486,6 +486,8 @@ int drm_dp_calc_pbn_mode(int clock, int bpp); bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int *slots); +int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); + void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); -- cgit v1.2.3 From a736775db683174269c65c7c5cc8e5ee534e7681 Mon Sep 17 00:00:00 2001 From: Charlie Mooney Date: Fri, 20 Mar 2015 09:40:17 -0700 Subject: Input: add MT_TOOL_PALM Currently there are only two "tools" that can be specified by a multi-touch driver: MT_TOOL_FINGER and MT_TOOL_PEN. In working with Elan (The touch vendor) and discussing their next-gen devices it seems that it will be useful to have more tools so that their devices can give the upper layers of the stack hints as to what is touching the sensor. In particular they have new experimental firmware that can better differentiate between palms vs fingertips and would like to plumb a patch so that we can use their hints in higher-level gesture soft- ware. The firmware on the device can reasonably do a better job of palm detection because it has access to all of the raw sensor readings as opposed to just the width/pressure/etc that are exposed by the driver. As such, the firmware can characterize what a palm looks like in much finer-grained detail and this change would allow such a device to share its findings with the kernel. Signed-off-by: Charlie Mooney Acked-by: Peter Hutterer Signed-off-by: Dmitry Torokhov --- Documentation/input/multi-touch-protocol.txt | 9 ++++++--- include/uapi/linux/input.h | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/Documentation/input/multi-touch-protocol.txt b/Documentation/input/multi-touch-protocol.txt index 7b4f59c09ee2..b85d000faeb4 100644 --- a/Documentation/input/multi-touch-protocol.txt +++ b/Documentation/input/multi-touch-protocol.txt @@ -312,9 +312,12 @@ ABS_MT_TOOL_TYPE The type of approaching tool. A lot of kernel drivers cannot distinguish between different tool types, such as a finger or a pen. In such cases, the -event should be omitted. The protocol currently supports MT_TOOL_FINGER and -MT_TOOL_PEN [2]. For type B devices, this event is handled by input core; -drivers should instead use input_mt_report_slot_state(). +event should be omitted. The protocol currently supports MT_TOOL_FINGER, +MT_TOOL_PEN, and MT_TOOL_PALM [2]. For type B devices, this event is handled +by input core; drivers should instead use input_mt_report_slot_state(). +A contact's ABS_MT_TOOL_TYPE may change over time while still touching the +device, because the firmware may not be able to determine which tool is being +used when it first appears. ABS_MT_BLOB_ID diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h index a1d7e931ab72..2320b0ce7579 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -972,7 +972,8 @@ struct input_keymap_entry { */ #define MT_TOOL_FINGER 0 #define MT_TOOL_PEN 1 -#define MT_TOOL_MAX 1 +#define MT_TOOL_PALM 2 +#define MT_TOOL_MAX 2 /* * Values describing the status of a force-feedback effect -- cgit v1.2.3 From 6321fd6b6f0942e986b297e8192febfc860b83b3 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 30 Jan 2015 12:36:12 +0100 Subject: drm: Remove unused DRM_MODE_OBJECT_BRIDGE With bridges now moving to a separate registry they are no longer DRM objects, hence this define is no longer needed. Signed-off-by: Thierry Reding --- include/drm/drm_crtc.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 920e21a8f3fd..f924b81d48ff 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -53,7 +53,6 @@ struct fence; #define DRM_MODE_OBJECT_FB 0xfbfbfbfb #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb #define DRM_MODE_OBJECT_PLANE 0xeeeeeeee -#define DRM_MODE_OBJECT_BRIDGE 0xbdbdbdbd #define DRM_MODE_OBJECT_ANY 0 struct drm_mode_object { -- cgit v1.2.3 From 9c7d3d3e289c9870ae688780a0f9807bb5ae9faf Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 27 Mar 2015 15:51:55 +0200 Subject: drm: Fix DRM_IOCTL_DEF_DRV() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently DRM_IOCTL_DEF_DRV does '[DRM_IOCTL_NR(DRM_##ioctl)]' which doesn't make much sense since DRM_##ioctl is already a the raw ioctl number. So change it to 'DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE' which means the DRM_IOCTL_NR() now makes sense, and also this also means if there's a mistake in the DRM_IOCTL_##ioctl macros we might get a warning about it (eg. we would have gotten a sparse warning about the i915 colorkey get/set ioctl being defined to be the same thing). Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- include/drm/drmP.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 63c0b0131f61..6195ee9b4c2a 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -263,7 +263,7 @@ struct drm_ioctl_desc { */ #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \ - [DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl, .name = #ioctl} + [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl, .name = #ioctl} /* Event queued up for userspace to read */ struct drm_pending_event { -- cgit v1.2.3 From 7e7392a6e854a29016377b87bebe5ae263f65e5c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 27 Mar 2015 15:51:56 +0200 Subject: drm: Drop ioctl->cmd_drv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ioctl->cmd_drv is pointless and we can just as well stick the full ioctl definition into ioctl->cmd. Cc: Jakob Bornecrantz Cc: Thomas Hellstrom Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_ioctl.c | 6 +++--- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 4 ++-- include/drm/drmP.h | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index a6d773a61c2d..fc0cf4a84011 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -525,7 +525,7 @@ static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv) } #define DRM_IOCTL_DEF(ioctl, _func, _flags) \ - [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl} + [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .name = #ioctl} /** Ioctl table */ static const struct drm_ioctl_desc drm_ioctls[] = { @@ -677,11 +677,11 @@ long drm_ioctl(struct file *filp, (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) { u32 drv_size; ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; - drv_size = _IOC_SIZE(ioctl->cmd_drv); + drv_size = _IOC_SIZE(ioctl->cmd); usize = asize = _IOC_SIZE(cmd); if (drv_size > asize) asize = drv_size; - cmd = ioctl->cmd_drv; + cmd = ioctl->cmd; } else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) { u32 drv_size; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 6c6b655defcf..761b2a767ce0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -134,7 +134,7 @@ */ #define VMW_IOCTL_DEF(ioctl, func, flags) \ - [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {DRM_##ioctl, flags, func, DRM_IOCTL_##ioctl} + [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {DRM_IOCTL_##ioctl, flags, func} /** * Ioctl definitions. @@ -1041,7 +1041,7 @@ static long vmw_generic_ioctl(struct file *filp, unsigned int cmd, const struct drm_ioctl_desc *ioctl = &vmw_ioctls[nr - DRM_COMMAND_BASE]; - if (unlikely(ioctl->cmd_drv != cmd)) { + if (unlikely(ioctl->cmd != cmd)) { DRM_ERROR("Invalid command format, ioctl %d\n", nr - DRM_COMMAND_BASE); return -EINVAL; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 6195ee9b4c2a..0d501ed20775 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -253,7 +253,6 @@ struct drm_ioctl_desc { unsigned int cmd; int flags; drm_ioctl_t *func; - unsigned int cmd_drv; const char *name; }; @@ -263,7 +262,7 @@ struct drm_ioctl_desc { */ #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \ - [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl, .name = #ioctl} + [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {.cmd = DRM_IOCTL_##ioctl, .func = _func, .flags = _flags, .name = #ioctl} /* Event queued up for userspace to read */ struct drm_pending_event { -- cgit v1.2.3 From 1e9e39f4a29857a396ac7b669d109f697f66695e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 26 Feb 2015 19:34:37 +0000 Subject: usbnet: Fix tx_packets stat for FLAG_MULTI_FRAME drivers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the usbnet core does not update the tx_packets statistic for drivers with FLAG_MULTI_PACKET and there is no hook in the TX completion path where they could do this. cdc_ncm and dependent drivers are bumping tx_packets stat on the transmit path while asix and sr9800 aren't updating it at all. Add a packet count in struct skb_data so these drivers can fill it in, initialise it to 1 for other drivers, and add the packet count to the tx_packets statistic on completion. Signed-off-by: Ben Hutchings Tested-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/asix_common.c | 2 ++ drivers/net/usb/cdc_ncm.c | 3 ++- drivers/net/usb/sr9800.c | 1 + drivers/net/usb/usbnet.c | 5 +++-- include/linux/usb/usbnet.h | 12 ++++++++++++ 5 files changed, 20 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 5c55f11572ba..724a9b50df7a 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -188,6 +188,8 @@ struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); skb_put(skb, sizeof(padbytes)); } + + usbnet_set_skb_tx_stats(skb, 1); return skb; } diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 80a844e0ae03..70cbea551139 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1172,7 +1172,6 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) /* return skb */ ctx->tx_curr_skb = NULL; - dev->net->stats.tx_packets += ctx->tx_curr_frame_num; /* keep private stats: framing overhead and number of NTBs */ ctx->tx_overhead += skb_out->len - ctx->tx_curr_frame_payload; @@ -1184,6 +1183,8 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) */ dev->net->stats.tx_bytes -= skb_out->len - ctx->tx_curr_frame_payload; + usbnet_set_skb_tx_stats(skb_out, n); + return skb_out; exit_no_skb: diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c index b94a0fbb8b3b..7650cdc8fe6b 100644 --- a/drivers/net/usb/sr9800.c +++ b/drivers/net/usb/sr9800.c @@ -144,6 +144,7 @@ static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb, skb_put(skb, sizeof(padbytes)); } + usbnet_set_skb_tx_stats(skb, 1); return skb; } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 449835f4331e..0f3ff285f6a1 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1188,8 +1188,7 @@ static void tx_complete (struct urb *urb) struct usbnet *dev = entry->dev; if (urb->status == 0) { - if (!(dev->driver_info->flags & FLAG_MULTI_PACKET)) - dev->net->stats.tx_packets++; + dev->net->stats.tx_packets += entry->packets; dev->net->stats.tx_bytes += entry->length; } else { dev->net->stats.tx_errors++; @@ -1348,6 +1347,8 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, urb->transfer_flags |= URB_ZERO_PACKET; } entry->length = urb->transfer_buffer_length = length; + if (!(info->flags & FLAG_MULTI_PACKET)) + usbnet_set_skb_tx_stats(skb, 1); spin_lock_irqsave(&dev->txq.lock, flags); retval = usb_autopm_get_interface_async(dev->intf); diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index d9a4905e01d0..ff3fb2bd0e90 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -228,8 +228,20 @@ struct skb_data { /* skb->cb is one of these */ struct usbnet *dev; enum skb_state state; size_t length; + unsigned long packets; }; +/* Drivers that set FLAG_MULTI_PACKET must call this in their + * tx_fixup method before returning an skb. + */ +static inline void +usbnet_set_skb_tx_stats(struct sk_buff *skb, unsigned long packets) +{ + struct skb_data *entry = (struct skb_data *) skb->cb; + + entry->packets = packets; +} + extern int usbnet_open(struct net_device *net); extern int usbnet_stop(struct net_device *net); extern netdev_tx_t usbnet_start_xmit(struct sk_buff *skb, -- cgit v1.2.3 From 7a1e890e2168e33fb62d84528e996b8b4b478fea Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 25 Mar 2015 21:41:33 +0100 Subject: usbnet: Fix tx_bytes statistic running backward in cdc_ncm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cdc_ncm disagrees with usbnet about how much framing overhead should be counted in the tx_bytes statistics, and tries 'fix' this by decrementing tx_bytes on the transmit path. But statistics must never be decremented except due to roll-over; this will thoroughly confuse user-space. Also, tx_bytes is only incremented by usbnet in the completion path. Fix this by requiring drivers that set FLAG_MULTI_FRAME to set a tx_bytes delta along with the tx_packets count. Fixes: beeecd42c3b4 ("net: cdc_ncm/cdc_mbim: adding NCM protocol statistics") Signed-off-by: Ben Hutchings Signed-off-by: Bjørn Mork --- drivers/net/usb/asix_common.c | 2 +- drivers/net/usb/cdc_ncm.c | 7 +++---- drivers/net/usb/sr9800.c | 2 +- drivers/net/usb/usbnet.c | 16 +++++++++++++--- include/linux/usb/usbnet.h | 6 ++++-- 5 files changed, 22 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 724a9b50df7a..75d6f26729a3 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -189,7 +189,7 @@ struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, skb_put(skb, sizeof(padbytes)); } - usbnet_set_skb_tx_stats(skb, 1); + usbnet_set_skb_tx_stats(skb, 1, 0); return skb; } diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 70cbea551139..c3e4da9e79ca 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1177,13 +1177,12 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) ctx->tx_overhead += skb_out->len - ctx->tx_curr_frame_payload; ctx->tx_ntbs++; - /* usbnet has already counted all the framing overhead. + /* usbnet will count all the framing overhead by default. * Adjust the stats so that the tx_bytes counter show real * payload data instead. */ - dev->net->stats.tx_bytes -= skb_out->len - ctx->tx_curr_frame_payload; - - usbnet_set_skb_tx_stats(skb_out, n); + usbnet_set_skb_tx_stats(skb_out, n, + ctx->tx_curr_frame_payload - skb_out->len); return skb_out; diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c index 7650cdc8fe6b..953de13267df 100644 --- a/drivers/net/usb/sr9800.c +++ b/drivers/net/usb/sr9800.c @@ -144,7 +144,7 @@ static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb, skb_put(skb, sizeof(padbytes)); } - usbnet_set_skb_tx_stats(skb, 1); + usbnet_set_skb_tx_stats(skb, 1, 0); return skb; } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 0f3ff285f6a1..777757ae1973 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1346,9 +1346,19 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, } else urb->transfer_flags |= URB_ZERO_PACKET; } - entry->length = urb->transfer_buffer_length = length; - if (!(info->flags & FLAG_MULTI_PACKET)) - usbnet_set_skb_tx_stats(skb, 1); + urb->transfer_buffer_length = length; + + if (info->flags & FLAG_MULTI_PACKET) { + /* Driver has set number of packets and a length delta. + * Calculate the complete length and ensure that it's + * positive. + */ + entry->length += length; + if (WARN_ON_ONCE(entry->length <= 0)) + entry->length = length; + } else { + usbnet_set_skb_tx_stats(skb, 1, length); + } spin_lock_irqsave(&dev->txq.lock, flags); retval = usb_autopm_get_interface_async(dev->intf); diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index ff3fb2bd0e90..6e0ce8c7b8cb 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -227,7 +227,7 @@ struct skb_data { /* skb->cb is one of these */ struct urb *urb; struct usbnet *dev; enum skb_state state; - size_t length; + long length; unsigned long packets; }; @@ -235,11 +235,13 @@ struct skb_data { /* skb->cb is one of these */ * tx_fixup method before returning an skb. */ static inline void -usbnet_set_skb_tx_stats(struct sk_buff *skb, unsigned long packets) +usbnet_set_skb_tx_stats(struct sk_buff *skb, + unsigned long packets, long bytes_delta) { struct skb_data *entry = (struct skb_data *) skb->cb; entry->packets = packets; + entry->length = bytes_delta; } extern int usbnet_open(struct net_device *net); -- cgit v1.2.3 From 4ad3e3634a6cbe916722c7113c5b488d52c7a3dc Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 27 Mar 2015 14:15:04 +0000 Subject: irqchip: gicv3-its: Fix PROP/PEND and BASE/CBASE confusion The ITS driver sometime mixes up the use of GICR_PROPBASE bitfields for the GICR_PENDBASE register, and GITS_BASER for GICR_CBASE. This does not lead to any observable bug because similar bits are at the same location, but this just make the code even harder to understand... This patch provides the required #defines and fixes the mixup. Signed-off-by: Marc Zyngier Link: https://lkml.kernel.org/r/1427465705-17126-4-git-send-email-marc.zyngier@arm.com Signed-off-by: Jason Cooper --- drivers/irqchip/irq-gic-v3-its.c | 6 +++--- include/linux/irqchip/arm-gic-v3.h | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index fa0c43660c8b..56353f6b5952 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -986,8 +986,8 @@ static void its_cpu_init_lpis(void) /* set PENDBASE */ val = (page_to_phys(pend_page) | - GICR_PROPBASER_InnerShareable | - GICR_PROPBASER_WaWb); + GICR_PENDBASER_InnerShareable | + GICR_PENDBASER_WaWb); writeq_relaxed(val, rbase + GICR_PENDBASER); @@ -1425,7 +1425,7 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) writeq_relaxed(0, its->base + GITS_CWRITER); writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR); - if ((tmp ^ baser) & GITS_BASER_SHAREABILITY_MASK) { + if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) { pr_info("ITS: using cache flushing for cmd queue\n"); its->flags |= ITS_FLAGS_CMDQ_NEEDS_FLUSHING; } diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 781974afff9f..826a4bd63d4a 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -128,6 +128,19 @@ #define GICR_PROPBASER_RaWaWb (7U << 7) #define GICR_PROPBASER_IDBITS_MASK (0x1f) +#define GICR_PENDBASER_NonShareable (0U << 10) +#define GICR_PENDBASER_InnerShareable (1U << 10) +#define GICR_PENDBASER_OuterShareable (2U << 10) +#define GICR_PENDBASER_SHAREABILITY_MASK (3UL << 10) +#define GICR_PENDBASER_nCnB (0U << 7) +#define GICR_PENDBASER_nC (1U << 7) +#define GICR_PENDBASER_RaWt (2U << 7) +#define GICR_PENDBASER_RaWb (3U << 7) +#define GICR_PENDBASER_WaWt (4U << 7) +#define GICR_PENDBASER_WaWb (5U << 7) +#define GICR_PENDBASER_RaWaWt (6U << 7) +#define GICR_PENDBASER_RaWaWb (7U << 7) + /* * Re-Distributor registers, offsets from SGI_base */ -- cgit v1.2.3 From 241a386c7dbb8b0db400a1f92f2ebe3b10eb661d Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 27 Mar 2015 14:15:05 +0000 Subject: irqchip: gicv3-its: Use non-cacheable accesses when no shareability If the ITS or the redistributors report their shareability as zero, then it is important to make sure they will no generate any cacheable traffic, as this is unlikely to produce the expected result. Signed-off-by: Marc Zyngier Link: https://lkml.kernel.org/r/1427465705-17126-5-git-send-email-marc.zyngier@arm.com Signed-off-by: Jason Cooper --- drivers/irqchip/irq-gic-v3-its.c | 47 ++++++++++++++++++++++++++++++++++---- include/linux/irqchip/arm-gic-v3.h | 4 ++++ 2 files changed, 47 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 56353f6b5952..9687f8afebff 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -802,6 +802,7 @@ static int its_alloc_tables(struct its_node *its) int i; int psz = SZ_64K; u64 shr = GITS_BASER_InnerShareable; + u64 cache = GITS_BASER_WaWb; for (i = 0; i < GITS_BASER_NR_REGS; i++) { u64 val = readq_relaxed(its->base + GITS_BASER + i * 8); @@ -848,7 +849,7 @@ retry_baser: val = (virt_to_phys(base) | (type << GITS_BASER_TYPE_SHIFT) | ((entry_size - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) | - GITS_BASER_WaWb | + cache | shr | GITS_BASER_VALID); @@ -874,9 +875,12 @@ retry_baser: * Shareability didn't stick. Just use * whatever the read reported, which is likely * to be the only thing this redistributor - * supports. + * supports. If that's zero, make it + * non-cacheable as well. */ shr = tmp & GITS_BASER_SHAREABILITY_MASK; + if (!shr) + cache = GITS_BASER_nC; goto retry_baser; } @@ -980,6 +984,17 @@ static void its_cpu_init_lpis(void) tmp = readq_relaxed(rbase + GICR_PROPBASER); if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) { + if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) { + /* + * The HW reports non-shareable, we must + * remove the cacheability attributes as + * well. + */ + val &= ~(GICR_PROPBASER_SHAREABILITY_MASK | + GICR_PROPBASER_CACHEABILITY_MASK); + val |= GICR_PROPBASER_nC; + writeq_relaxed(val, rbase + GICR_PROPBASER); + } pr_info_once("GIC: using cache flushing for LPI property table\n"); gic_rdists->flags |= RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING; } @@ -990,6 +1005,18 @@ static void its_cpu_init_lpis(void) GICR_PENDBASER_WaWb); writeq_relaxed(val, rbase + GICR_PENDBASER); + tmp = readq_relaxed(rbase + GICR_PENDBASER); + + if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) { + /* + * The HW reports non-shareable, we must remove the + * cacheability attributes as well. + */ + val &= ~(GICR_PENDBASER_SHAREABILITY_MASK | + GICR_PENDBASER_CACHEABILITY_MASK); + val |= GICR_PENDBASER_nC; + writeq_relaxed(val, rbase + GICR_PENDBASER); + } /* Enable LPIs */ val = readl_relaxed(rbase + GICR_CTLR); @@ -1422,14 +1449,26 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) writeq_relaxed(baser, its->base + GITS_CBASER); tmp = readq_relaxed(its->base + GITS_CBASER); - writeq_relaxed(0, its->base + GITS_CWRITER); - writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR); if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) { + if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) { + /* + * The HW reports non-shareable, we must + * remove the cacheability attributes as + * well. + */ + baser &= ~(GITS_CBASER_SHAREABILITY_MASK | + GITS_CBASER_CACHEABILITY_MASK); + baser |= GITS_CBASER_nC; + writeq_relaxed(baser, its->base + GITS_CBASER); + } pr_info("ITS: using cache flushing for cmd queue\n"); its->flags |= ITS_FLAGS_CMDQ_NEEDS_FLUSHING; } + writeq_relaxed(0, its->base + GITS_CWRITER); + writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR); + if (of_property_read_bool(its->msi_chip.of_node, "msi-controller")) { its->domain = irq_domain_add_tree(NULL, &its_domain_ops, its); if (!its->domain) { diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 826a4bd63d4a..ffbc034c8810 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -126,6 +126,7 @@ #define GICR_PROPBASER_WaWb (5U << 7) #define GICR_PROPBASER_RaWaWt (6U << 7) #define GICR_PROPBASER_RaWaWb (7U << 7) +#define GICR_PROPBASER_CACHEABILITY_MASK (7U << 7) #define GICR_PROPBASER_IDBITS_MASK (0x1f) #define GICR_PENDBASER_NonShareable (0U << 10) @@ -140,6 +141,7 @@ #define GICR_PENDBASER_WaWb (5U << 7) #define GICR_PENDBASER_RaWaWt (6U << 7) #define GICR_PENDBASER_RaWaWb (7U << 7) +#define GICR_PENDBASER_CACHEABILITY_MASK (7U << 7) /* * Re-Distributor registers, offsets from SGI_base @@ -195,6 +197,7 @@ #define GITS_CBASER_WaWb (5UL << 59) #define GITS_CBASER_RaWaWt (6UL << 59) #define GITS_CBASER_RaWaWb (7UL << 59) +#define GITS_CBASER_CACHEABILITY_MASK (7UL << 59) #define GITS_CBASER_NonShareable (0UL << 10) #define GITS_CBASER_InnerShareable (1UL << 10) #define GITS_CBASER_OuterShareable (2UL << 10) @@ -211,6 +214,7 @@ #define GITS_BASER_WaWb (5UL << 59) #define GITS_BASER_RaWaWt (6UL << 59) #define GITS_BASER_RaWaWb (7UL << 59) +#define GITS_BASER_CACHEABILITY_MASK (7UL << 59) #define GITS_BASER_TYPE_SHIFT (56) #define GITS_BASER_TYPE(r) (((r) >> GITS_BASER_TYPE_SHIFT) & 7) #define GITS_BASER_ENTRY_SIZE_SHIFT (48) -- cgit v1.2.3 From f3f03330dee0526d82f2a0fd1a79d207ed1ac439 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 30 Mar 2015 18:46:29 +0200 Subject: nfsd: require an explicit option to enable pNFS Turns out sending out layouts to any client is a bad idea if they can't get at the storage device, so require explicit admin action to enable pNFS. Signed-off-by: Christoph Hellwig Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4layouts.c | 2 +- include/uapi/linux/nfsd/export.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c index 80e236bf79fc..6904213a4363 100644 --- a/fs/nfsd/nfs4layouts.c +++ b/fs/nfsd/nfs4layouts.c @@ -118,7 +118,7 @@ void nfsd4_setup_layout_type(struct svc_export *exp) { struct super_block *sb = exp->ex_path.mnt->mnt_sb; - if (exp->ex_flags & NFSEXP_NOPNFS) + if (!(exp->ex_flags & NFSEXP_PNFS)) return; if (sb->s_export_op->get_uuid && diff --git a/include/uapi/linux/nfsd/export.h b/include/uapi/linux/nfsd/export.h index 4742f2cb42f2..d3bd6ffec041 100644 --- a/include/uapi/linux/nfsd/export.h +++ b/include/uapi/linux/nfsd/export.h @@ -47,7 +47,7 @@ * exported filesystem. */ #define NFSEXP_V4ROOT 0x10000 -#define NFSEXP_NOPNFS 0x20000 +#define NFSEXP_PNFS 0x20000 /* All flags that we claim to support. (Note we don't support NOACL.) */ #define NFSEXP_ALLFLAGS 0x3FE7F -- cgit v1.2.3 From 066626d5d5548d7ff63772a840b8d40a0d278825 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Mon, 30 Mar 2015 17:10:36 +0000 Subject: drm: line wrap DRM_IOCTL_DEF* macros Improve the readability and keeps the lines shorter than 80 columns. Signed-off-by: Emil Velikov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_ioctl.c | 9 +++++++-- include/drm/drmP.h | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 1f257aecd2b2..266dcd6cdf3b 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -524,8 +524,13 @@ static int drm_ioctl_permit(u32 flags, struct drm_file *file_priv) return 0; } -#define DRM_IOCTL_DEF(ioctl, _func, _flags) \ - [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .name = #ioctl} +#define DRM_IOCTL_DEF(ioctl, _func, _flags) \ + [DRM_IOCTL_NR(ioctl)] = { \ + .cmd = ioctl, \ + .func = _func, \ + .flags = _flags, \ + .name = #ioctl \ + } /** Ioctl table */ static const struct drm_ioctl_desc drm_ioctls[] = { diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 0d501ed20775..62c40777c009 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -261,8 +261,13 @@ struct drm_ioctl_desc { * ioctl, for use by drm_ioctl(). */ -#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \ - [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {.cmd = DRM_IOCTL_##ioctl, .func = _func, .flags = _flags, .name = #ioctl} +#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \ + [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = { \ + .cmd = DRM_IOCTL_##ioctl, \ + .func = _func, \ + .flags = _flags, \ + .name = #ioctl \ + } /* Event queued up for userspace to read */ struct drm_pending_event { -- cgit v1.2.3 From e9637415a92cf25ad800b7fdeddcd30cce7b44ab Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Mon, 30 Mar 2015 13:39:09 -0400 Subject: block: fix blk_stack_limits() regression due to lcm() change Linux 3.19 commit 69c953c ("lib/lcm.c: lcm(n,0)=lcm(0,n) is 0, not n") caused blk_stack_limits() to not properly stack queue_limits for stacked devices (e.g. DM). Fix this regression by establishing lcm_not_zero() and switching blk_stack_limits() over to using it. DM uses blk_set_stacking_limits() to establish the initial top-level queue_limits that are then built up based on underlying devices' limits using blk_stack_limits(). In the case of optimal_io_size (io_opt) blk_set_stacking_limits() establishes a default value of 0. With commit 69c953c, lcm(0, n) is no longer n, which compromises proper stacking of the underlying devices' io_opt. Test: $ modprobe scsi_debug dev_size_mb=10 num_tgts=1 opt_blks=1536 $ cat /sys/block/sde/queue/optimal_io_size 786432 $ dmsetup create node --table "0 100 linear /dev/sde 0" Before this fix: $ cat /sys/block/dm-5/queue/optimal_io_size 0 After this fix: $ cat /sys/block/dm-5/queue/optimal_io_size 786432 Signed-off-by: Mike Snitzer Cc: stable@vger.kernel.org # 3.19+ Acked-by: Martin K. Petersen Signed-off-by: Jens Axboe --- block/blk-settings.c | 6 +++--- include/linux/lcm.h | 1 + lib/lcm.c | 11 +++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/block/blk-settings.c b/block/blk-settings.c index 6ed2cbe5e8c9..12600bfffca9 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -585,7 +585,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, b->physical_block_size); t->io_min = max(t->io_min, b->io_min); - t->io_opt = lcm(t->io_opt, b->io_opt); + t->io_opt = lcm_not_zero(t->io_opt, b->io_opt); t->cluster &= b->cluster; t->discard_zeroes_data &= b->discard_zeroes_data; @@ -616,7 +616,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, b->raid_partial_stripes_expensive); /* Find lowest common alignment_offset */ - t->alignment_offset = lcm(t->alignment_offset, alignment) + t->alignment_offset = lcm_not_zero(t->alignment_offset, alignment) % max(t->physical_block_size, t->io_min); /* Verify that new alignment_offset is on a logical block boundary */ @@ -643,7 +643,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, b->max_discard_sectors); t->discard_granularity = max(t->discard_granularity, b->discard_granularity); - t->discard_alignment = lcm(t->discard_alignment, alignment) % + t->discard_alignment = lcm_not_zero(t->discard_alignment, alignment) % t->discard_granularity; } diff --git a/include/linux/lcm.h b/include/linux/lcm.h index 7bf01d779b45..1ce79a7f1daa 100644 --- a/include/linux/lcm.h +++ b/include/linux/lcm.h @@ -4,5 +4,6 @@ #include unsigned long lcm(unsigned long a, unsigned long b) __attribute_const__; +unsigned long lcm_not_zero(unsigned long a, unsigned long b) __attribute_const__; #endif /* _LCM_H */ diff --git a/lib/lcm.c b/lib/lcm.c index e97dbd51e756..03d7fcb420b5 100644 --- a/lib/lcm.c +++ b/lib/lcm.c @@ -12,3 +12,14 @@ unsigned long lcm(unsigned long a, unsigned long b) return 0; } EXPORT_SYMBOL_GPL(lcm); + +unsigned long lcm_not_zero(unsigned long a, unsigned long b) +{ + unsigned long l = lcm(a, b); + + if (l) + return l; + + return (b ? : a); +} +EXPORT_SYMBOL_GPL(lcm_not_zero); -- cgit v1.2.3 From f9c72d10d6fbf949558cd088389a42213ed7b12d Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 31 Mar 2015 12:03:28 -0400 Subject: sunrpc: make debugfs file creation failure non-fatal We currently have a problem that SELinux policy is being enforced when creating debugfs files. If a debugfs file is created as a side effect of doing some syscall, then that creation can fail if the SELinux policy for that process prevents it. This seems wrong. We don't do that for files under /proc, for instance, so Bruce has proposed a patch to fix that. While discussing that patch however, Greg K.H. stated: "No kernel code should care / fail if a debugfs function fails, so please fix up the sunrpc code first." This patch converts all of the sunrpc debugfs setup code to be void return functins, and the callers to not look for errors from those functions. This should allow rpc_clnt and rpc_xprt creation to work, even if the kernel fails to create debugfs files for some reason. Symptoms were failing krb5 mounts on systems using gss-proxy and selinux. Fixes: 388f0c776781 "sunrpc: add a debugfs rpc_xprt directory..." Cc: stable@vger.kernel.org Signed-off-by: Jeff Layton Acked-by: Greg Kroah-Hartman Signed-off-by: J. Bruce Fields --- include/linux/sunrpc/debug.h | 18 +++++++-------- net/sunrpc/clnt.c | 4 +--- net/sunrpc/debugfs.c | 52 ++++++++++++++++++++++++-------------------- net/sunrpc/sunrpc_syms.c | 7 +----- net/sunrpc/xprt.c | 7 +----- 5 files changed, 41 insertions(+), 47 deletions(-) (limited to 'include') diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h index c57d8ea0716c..59a7889e15db 100644 --- a/include/linux/sunrpc/debug.h +++ b/include/linux/sunrpc/debug.h @@ -60,17 +60,17 @@ struct rpc_xprt; #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) void rpc_register_sysctl(void); void rpc_unregister_sysctl(void); -int sunrpc_debugfs_init(void); +void sunrpc_debugfs_init(void); void sunrpc_debugfs_exit(void); -int rpc_clnt_debugfs_register(struct rpc_clnt *); +void rpc_clnt_debugfs_register(struct rpc_clnt *); void rpc_clnt_debugfs_unregister(struct rpc_clnt *); -int rpc_xprt_debugfs_register(struct rpc_xprt *); +void rpc_xprt_debugfs_register(struct rpc_xprt *); void rpc_xprt_debugfs_unregister(struct rpc_xprt *); #else -static inline int +static inline void sunrpc_debugfs_init(void) { - return 0; + return; } static inline void @@ -79,10 +79,10 @@ sunrpc_debugfs_exit(void) return; } -static inline int +static inline void rpc_clnt_debugfs_register(struct rpc_clnt *clnt) { - return 0; + return; } static inline void @@ -91,10 +91,10 @@ rpc_clnt_debugfs_unregister(struct rpc_clnt *clnt) return; } -static inline int +static inline void rpc_xprt_debugfs_register(struct rpc_xprt *xprt) { - return 0; + return; } static inline void diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 612aa73bbc60..e6ce1517367f 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -303,9 +303,7 @@ static int rpc_client_register(struct rpc_clnt *clnt, struct super_block *pipefs_sb; int err; - err = rpc_clnt_debugfs_register(clnt); - if (err) - return err; + rpc_clnt_debugfs_register(clnt); pipefs_sb = rpc_get_sb_net(net); if (pipefs_sb) { diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c index e811f390f9f6..82962f7e6e88 100644 --- a/net/sunrpc/debugfs.c +++ b/net/sunrpc/debugfs.c @@ -129,48 +129,52 @@ static const struct file_operations tasks_fops = { .release = tasks_release, }; -int +void rpc_clnt_debugfs_register(struct rpc_clnt *clnt) { - int len, err; + int len; char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */ + struct rpc_xprt *xprt; /* Already registered? */ - if (clnt->cl_debugfs) - return 0; + if (clnt->cl_debugfs || !rpc_clnt_dir) + return; len = snprintf(name, sizeof(name), "%x", clnt->cl_clid); if (len >= sizeof(name)) - return -EINVAL; + return; /* make the per-client dir */ clnt->cl_debugfs = debugfs_create_dir(name, rpc_clnt_dir); if (!clnt->cl_debugfs) - return -ENOMEM; + return; /* make tasks file */ - err = -ENOMEM; if (!debugfs_create_file("tasks", S_IFREG | S_IRUSR, clnt->cl_debugfs, clnt, &tasks_fops)) goto out_err; - err = -EINVAL; rcu_read_lock(); + xprt = rcu_dereference(clnt->cl_xprt); + /* no "debugfs" dentry? Don't bother with the symlink. */ + if (!xprt->debugfs) { + rcu_read_unlock(); + return; + } len = snprintf(name, sizeof(name), "../../rpc_xprt/%s", - rcu_dereference(clnt->cl_xprt)->debugfs->d_name.name); + xprt->debugfs->d_name.name); rcu_read_unlock(); + if (len >= sizeof(name)) goto out_err; - err = -ENOMEM; if (!debugfs_create_symlink("xprt", clnt->cl_debugfs, name)) goto out_err; - return 0; + return; out_err: debugfs_remove_recursive(clnt->cl_debugfs); clnt->cl_debugfs = NULL; - return err; } void @@ -226,33 +230,33 @@ static const struct file_operations xprt_info_fops = { .release = xprt_info_release, }; -int +void rpc_xprt_debugfs_register(struct rpc_xprt *xprt) { int len, id; static atomic_t cur_id; char name[9]; /* 8 hex digits + NULL term */ + if (!rpc_xprt_dir) + return; + id = (unsigned int)atomic_inc_return(&cur_id); len = snprintf(name, sizeof(name), "%x", id); if (len >= sizeof(name)) - return -EINVAL; + return; /* make the per-client dir */ xprt->debugfs = debugfs_create_dir(name, rpc_xprt_dir); if (!xprt->debugfs) - return -ENOMEM; + return; /* make tasks file */ if (!debugfs_create_file("info", S_IFREG | S_IRUSR, xprt->debugfs, xprt, &xprt_info_fops)) { debugfs_remove_recursive(xprt->debugfs); xprt->debugfs = NULL; - return -ENOMEM; } - - return 0; } void @@ -266,14 +270,17 @@ void __exit sunrpc_debugfs_exit(void) { debugfs_remove_recursive(topdir); + topdir = NULL; + rpc_clnt_dir = NULL; + rpc_xprt_dir = NULL; } -int __init +void __init sunrpc_debugfs_init(void) { topdir = debugfs_create_dir("sunrpc", NULL); if (!topdir) - goto out; + return; rpc_clnt_dir = debugfs_create_dir("rpc_clnt", topdir); if (!rpc_clnt_dir) @@ -283,10 +290,9 @@ sunrpc_debugfs_init(void) if (!rpc_xprt_dir) goto out_remove; - return 0; + return; out_remove: debugfs_remove_recursive(topdir); topdir = NULL; -out: - return -ENOMEM; + rpc_clnt_dir = NULL; } diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index e37fbed87956..ee5d3d253102 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -98,10 +98,7 @@ init_sunrpc(void) if (err) goto out4; - err = sunrpc_debugfs_init(); - if (err) - goto out5; - + sunrpc_debugfs_init(); #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) rpc_register_sysctl(); #endif @@ -109,8 +106,6 @@ init_sunrpc(void) init_socket_xprt(); /* clnt sock transport */ return 0; -out5: - unregister_rpc_pipefs(); out4: unregister_pernet_subsys(&sunrpc_net_ops); out3: diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index e3015aede0d9..9949722d99ce 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -1331,7 +1331,6 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net) */ struct rpc_xprt *xprt_create_transport(struct xprt_create *args) { - int err; struct rpc_xprt *xprt; struct xprt_class *t; @@ -1372,11 +1371,7 @@ found: return ERR_PTR(-ENOMEM); } - err = rpc_xprt_debugfs_register(xprt); - if (err) { - xprt_destroy(xprt); - return ERR_PTR(err); - } + rpc_xprt_debugfs_register(xprt); dprintk("RPC: created transport %p with %u slots\n", xprt, xprt->max_reqs); -- cgit v1.2.3 From b4a20144e0c0a45431695fa5968ce2ed8c9ce6ca Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 28 Jan 2015 14:29:02 +0100 Subject: gpu: host1x: Export host1x_syncpt_read() This function is used to read the current value of the syncpt and is useful in situations where drivers don't schedule work and wait for the syncpoint to increment. One particular use-case is using the syncpoint as a VBLANK counter. Signed-off-by: Thierry Reding --- drivers/gpu/host1x/syncpt.c | 6 ++++++ include/linux/host1x.h | 1 + 2 files changed, 7 insertions(+) (limited to 'include') diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index b10550ee1d89..6b7fdc1e2ed0 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c @@ -425,6 +425,12 @@ u32 host1x_syncpt_read_min(struct host1x_syncpt *sp) } EXPORT_SYMBOL(host1x_syncpt_read_min); +u32 host1x_syncpt_read(struct host1x_syncpt *sp) +{ + return host1x_syncpt_load(sp); +} +EXPORT_SYMBOL(host1x_syncpt_read); + int host1x_syncpt_nb_pts(struct host1x *host) { return host->info->nb_pts; diff --git a/include/linux/host1x.h b/include/linux/host1x.h index 464f33814a94..d2ba7d334039 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -135,6 +135,7 @@ struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id); u32 host1x_syncpt_id(struct host1x_syncpt *sp); u32 host1x_syncpt_read_min(struct host1x_syncpt *sp); u32 host1x_syncpt_read_max(struct host1x_syncpt *sp); +u32 host1x_syncpt_read(struct host1x_syncpt *sp); int host1x_syncpt_incr(struct host1x_syncpt *sp); u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs); int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, -- cgit v1.2.3 From f5e7840b0c4368f8cdbb055188c2a0eef50c3052 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 28 Jan 2015 14:54:32 +0100 Subject: drm/atomic: Add helpers for state-subclassing drivers Drivers that subclass CRTC, plane or connector state need to carefully duplicate the code that the atomic helpers have. This is bound to cause breakage eventually because it requires auditing all drivers and update them when code is added to the helpers. In order to avoid that, implement new helpers that perform the required steps when copying and destroying state. These new helpers are exported so that state-subclassing drivers can use them. The default helpers are implemented using them as well, providing a single location that needs to be changed when adding to base atomic states. Reviewed-by: Daniel Vetter Reviewed-by: Eric Anholt Signed-off-by: Thierry Reding --- drivers/gpu/drm/drm_atomic_helper.c | 144 ++++++++++++++++++++++++++++++++---- include/drm/drm_atomic_helper.h | 14 ++++ 2 files changed, 142 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 7e3a52b97c7d..60d28a18f0a3 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2049,6 +2049,26 @@ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) } EXPORT_SYMBOL(drm_atomic_helper_crtc_reset); +/** + * __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state + * @crtc: CRTC object + * @state: atomic CRTC state + * + * Copies atomic state from a CRTC's current state and resets inferred values. + * This is useful for drivers that subclass the CRTC state. + */ +void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + memcpy(state, crtc->state, sizeof(*state)); + + state->mode_changed = false; + state->active_changed = false; + state->planes_changed = false; + state->event = NULL; +} +EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state); + /** * drm_atomic_helper_crtc_duplicate_state - default state duplicate hook * @crtc: drm CRTC @@ -2064,19 +2084,34 @@ drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc) if (WARN_ON(!crtc->state)) return NULL; - state = kmemdup(crtc->state, sizeof(*crtc->state), GFP_KERNEL); - - if (state) { - state->mode_changed = false; - state->active_changed = false; - state->planes_changed = false; - state->event = NULL; - } + state = kmalloc(sizeof(*state), GFP_KERNEL); + if (state) + __drm_atomic_helper_crtc_duplicate_state(crtc, state); return state; } EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); +/** + * __drm_atomic_helper_crtc_destroy_state - release CRTC state + * @crtc: CRTC object + * @state: CRTC state object to release + * + * Releases all resources stored in the CRTC state without actually freeing + * the memory of the CRTC state. This is useful for drivers that subclass the + * CRTC state. + */ +void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + /* + * This is currently a placeholder so that drivers that subclass the + * state will automatically do the right thing if code is ever added + * to this function. + */ +} +EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state); + /** * drm_atomic_helper_crtc_destroy_state - default state destroy hook * @crtc: drm CRTC @@ -2088,6 +2123,7 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) { + __drm_atomic_helper_crtc_destroy_state(crtc, state); kfree(state); } EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); @@ -2112,6 +2148,24 @@ void drm_atomic_helper_plane_reset(struct drm_plane *plane) } EXPORT_SYMBOL(drm_atomic_helper_plane_reset); +/** + * __drm_atomic_helper_plane_duplicate_state - copy atomic plane state + * @plane: plane object + * @state: atomic plane state + * + * Copies atomic state from a plane's current state. This is useful for + * drivers that subclass the plane state. + */ +void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, + struct drm_plane_state *state) +{ + memcpy(state, plane->state, sizeof(*state)); + + if (state->fb) + drm_framebuffer_reference(state->fb); +} +EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state); + /** * drm_atomic_helper_plane_duplicate_state - default state duplicate hook * @plane: drm plane @@ -2127,15 +2181,31 @@ drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane) if (WARN_ON(!plane->state)) return NULL; - state = kmemdup(plane->state, sizeof(*plane->state), GFP_KERNEL); - - if (state && state->fb) - drm_framebuffer_reference(state->fb); + state = kmalloc(sizeof(*state), GFP_KERNEL); + if (state) + __drm_atomic_helper_plane_duplicate_state(plane, state); return state; } EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); +/** + * __drm_atomic_helper_plane_destroy_state - release plane state + * @plane: plane object + * @state: plane state object to release + * + * Releases all resources stored in the plane state without actually freeing + * the memory of the plane state. This is useful for drivers that subclass the + * plane state. + */ +void __drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) +{ + if (state->fb) + drm_framebuffer_unreference(state->fb); +} +EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state); + /** * drm_atomic_helper_plane_destroy_state - default state destroy hook * @plane: drm plane @@ -2147,9 +2217,7 @@ EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state); void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state) { - if (state->fb) - drm_framebuffer_unreference(state->fb); - + __drm_atomic_helper_plane_destroy_state(plane, state); kfree(state); } EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); @@ -2172,6 +2240,22 @@ void drm_atomic_helper_connector_reset(struct drm_connector *connector) } EXPORT_SYMBOL(drm_atomic_helper_connector_reset); +/** + * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state + * @connector: connector object + * @state: atomic connector state + * + * Copies atomic state from a connector's current state. This is useful for + * drivers that subclass the connector state. + */ +void +__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, + struct drm_connector_state *state) +{ + memcpy(state, connector->state, sizeof(*state)); +} +EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state); + /** * drm_atomic_helper_connector_duplicate_state - default state duplicate hook * @connector: drm connector @@ -2182,13 +2266,40 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_reset); struct drm_connector_state * drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector) { + struct drm_connector_state *state; + if (WARN_ON(!connector->state)) return NULL; - return kmemdup(connector->state, sizeof(*connector->state), GFP_KERNEL); + state = kmalloc(sizeof(*state), GFP_KERNEL); + if (state) + __drm_atomic_helper_connector_duplicate_state(connector, state); + + return state; } EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); +/** + * __drm_atomic_helper_connector_destroy_state - release connector state + * @connector: connector object + * @state: connector state object to release + * + * Releases all resources stored in the connector state without actually + * freeing the memory of the connector state. This is useful for drivers that + * subclass the connector state. + */ +void +__drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, + struct drm_connector_state *state) +{ + /* + * This is currently a placeholder so that drivers that subclass the + * state will automatically do the right thing if code is ever added + * to this function. + */ +} +EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state); + /** * drm_atomic_helper_connector_destroy_state - default state destroy hook * @connector: drm connector @@ -2200,6 +2311,7 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state) { + __drm_atomic_helper_connector_destroy_state(connector, state); kfree(state); } EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state); diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 8039d54a7441..e2086372ef61 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -87,20 +87,34 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector, /* default implementations for state handling */ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc); +void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, + struct drm_crtc_state *state); struct drm_crtc_state * drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc); +void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state); void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state); void drm_atomic_helper_plane_reset(struct drm_plane *plane); +void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, + struct drm_plane_state *state); struct drm_plane_state * drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane); +void __drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state); void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state); void drm_atomic_helper_connector_reset(struct drm_connector *connector); +void +__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, + struct drm_connector_state *state); struct drm_connector_state * drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector); +void +__drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, + struct drm_connector_state *state); void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, struct drm_connector_state *state); -- cgit v1.2.3 From bdf765071a8b573f7b1ba14c02881fa3e623825e Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Fri, 30 Jan 2015 13:57:01 -0500 Subject: drm/tegra: gem: Return 64-bit offset for mmap(2) On 64-bit targets, tegra_gem_mmap() only returns a partial offset to userspace. As such, subsequent calls to mmap(2) may fail. Change the arguments to use a 64-bit offset to fix this. Signed-off-by: Sean Paul Acked-by: Erik Faye-Lund [treding@nvidia.com: tweak commit message] Signed-off-by: Thierry Reding --- include/uapi/drm/tegra_drm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index c15d781ecc0f..5391780c2b05 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h @@ -36,7 +36,8 @@ struct drm_tegra_gem_create { struct drm_tegra_gem_mmap { __u32 handle; - __u32 offset; + __u32 pad; + __u64 offset; }; struct drm_tegra_syncpt_read { -- cgit v1.2.3 From 2938931f3732a4ec70c299e221ec8dea01dfd796 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 11 Dec 2014 18:32:44 +0100 Subject: drm/panel: Add display timing support Many panel data sheets, additionally to typical values, list allowed ranges for timings such as hsync/vsync lengths, porches, and the pixel clock rate. These can be stored in a struct display_timing, to be used by an encoder mode_fixup callback to clamp user provided timing values or to validate workarounds for clock source limitations. This patch adds a new drm_panel_funcs callback that returns the panel's available display_timing entries. Signed-off-by: Philipp Zabel Signed-off-by: Thierry Reding --- include/drm/drm_panel.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 1fbcc96063a7..13ff44b28893 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -29,6 +29,7 @@ struct drm_connector; struct drm_device; struct drm_panel; +struct display_timing; /** * struct drm_panel_funcs - perform operations on a given panel @@ -38,6 +39,8 @@ struct drm_panel; * @enable: enable panel (turn on back light, etc.) * @get_modes: add modes to the connector that the panel is attached to and * return the number of modes added + * @get_timings: copy display timings into the provided array and return + * the number of display timings available * * The .prepare() function is typically called before the display controller * starts to transmit video data. Panel drivers can use this to turn the panel @@ -68,6 +71,8 @@ struct drm_panel_funcs { int (*prepare)(struct drm_panel *panel); int (*enable)(struct drm_panel *panel); int (*get_modes)(struct drm_panel *panel); + int (*get_timings)(struct drm_panel *panel, unsigned int num_timings, + struct display_timing *timings); }; struct drm_panel { -- cgit v1.2.3 From f60e5990d9c1424af9dbca60a23ba2a1c7c1ce90 Mon Sep 17 00:00:00 2001 From: "hannes@stressinduktion.org" Date: Wed, 1 Apr 2015 17:07:44 +0200 Subject: ipv6: protect skb->sk accesses from recursive dereference inside the stack We should not consult skb->sk for output decisions in xmit recursion levels > 0 in the stack. Otherwise local socket settings could influence the result of e.g. tunnel encapsulation process. ipv6 does not conform with this in three places: 1) ip6_fragment: we do consult ipv6_npinfo for frag_size 2) sk_mc_loop in ipv6 uses skb->sk and checks if we should loop the packet back to the local socket 3) ip6_skb_dst_mtu could query the settings from the user socket and force a wrong MTU Furthermore: In sk_mc_loop we could potentially land in WARN_ON(1) if we use a PF_PACKET socket ontop of an IPv6-backed vxlan device. Reuse xmit_recursion as we are currently only interested in protecting tunnel devices. Cc: Jiri Pirko Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- include/linux/netdevice.h | 6 ++++++ include/net/ip.h | 16 ---------------- include/net/ip6_route.h | 3 ++- include/net/sock.h | 2 ++ net/core/dev.c | 4 +++- net/core/sock.c | 19 +++++++++++++++++++ net/ipv6/ip6_output.c | 3 ++- 7 files changed, 34 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index dcf6ec27739b..278738873703 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2185,6 +2185,12 @@ void netdev_freemem(struct net_device *dev); void synchronize_net(void); int init_dummy_netdev(struct net_device *dev); +DECLARE_PER_CPU(int, xmit_recursion); +static inline int dev_recursion_level(void) +{ + return this_cpu_read(xmit_recursion); +} + struct net_device *dev_get_by_index(struct net *net, int ifindex); struct net_device *__dev_get_by_index(struct net *net, int ifindex); struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex); diff --git a/include/net/ip.h b/include/net/ip.h index 025c61c0dffb..6cc1eafb153a 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -453,22 +453,6 @@ static __inline__ void inet_reset_saddr(struct sock *sk) #endif -static inline int sk_mc_loop(struct sock *sk) -{ - if (!sk) - return 1; - switch (sk->sk_family) { - case AF_INET: - return inet_sk(sk)->mc_loop; -#if IS_ENABLED(CONFIG_IPV6) - case AF_INET6: - return inet6_sk(sk)->mc_loop; -#endif - } - WARN_ON(1); - return 1; -} - bool ip_call_ra_chain(struct sk_buff *skb); /* diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 1d09b46c1e48..eda131d179d9 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -174,7 +174,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)); static inline int ip6_skb_dst_mtu(struct sk_buff *skb) { - struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; + struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? + inet6_sk(skb->sk) : NULL; return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ? skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); diff --git a/include/net/sock.h b/include/net/sock.h index ab186b1d31ff..e4079c28e6b8 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1762,6 +1762,8 @@ struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie); struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie); +bool sk_mc_loop(struct sock *sk); + static inline bool sk_can_gso(const struct sock *sk) { return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type); diff --git a/net/core/dev.c b/net/core/dev.c index 962ee9d71964..45109b70664e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2848,7 +2848,9 @@ static void skb_update_prio(struct sk_buff *skb) #define skb_update_prio(skb) #endif -static DEFINE_PER_CPU(int, xmit_recursion); +DEFINE_PER_CPU(int, xmit_recursion); +EXPORT_SYMBOL(xmit_recursion); + #define RECURSION_LIMIT 10 /** diff --git a/net/core/sock.c b/net/core/sock.c index 78e89eb7eb70..71e3e5f1eaa0 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -653,6 +653,25 @@ static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool) sock_reset_flag(sk, bit); } +bool sk_mc_loop(struct sock *sk) +{ + if (dev_recursion_level()) + return false; + if (!sk) + return true; + switch (sk->sk_family) { + case AF_INET: + return inet_sk(sk)->mc_loop; +#if IS_ENABLED(CONFIG_IPV6) + case AF_INET6: + return inet6_sk(sk)->mc_loop; +#endif + } + WARN_ON(1); + return true; +} +EXPORT_SYMBOL(sk_mc_loop); + /* * This is meant for all protocols to use and covers goings on * at the socket level. Everything here is generic. diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 7e80b61b51ff..36cf0ab685a0 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -542,7 +542,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) { struct sk_buff *frag; struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); - struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL; + struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? + inet6_sk(skb->sk) : NULL; struct ipv6hdr *tmp_hdr; struct frag_hdr *fh; unsigned int mtu, hlen, left, len; -- cgit v1.2.3 From 1347f5b46a270db1991625f9f57af91e23a4b512 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Tue, 17 Mar 2015 11:39:27 +0200 Subject: drm/i915/bxt: Add BXT PCI ids MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: Switch to info->ring_mask and add VEBOX support. v3: Fold in update from Damien. v4: Add GEN_DEFAULT_PIPEOFFSETS and IVB_CURSOR_OFFSETS v5: set no-LLC (imre) Signed-off-by: Damien Lespiau (v1,v4) Signed-off-by: Daniel Vetter (v4) Signed-off-by: Imre Deak Reviewed-by: Antti Koskipää Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 14 +++++++++++++- include/drm/i915_pciids.h | 6 ++++++ 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 82f8be4b6745..4d5078550e0b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -381,6 +381,17 @@ static const struct intel_device_info intel_skylake_gt3_info = { IVB_CURSOR_OFFSETS, }; +static const struct intel_device_info intel_broxton_info = { + .is_preliminary = 1, + .gen = 9, + .need_gfx_hws = 1, .has_hotplug = 1, + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, + .num_pipes = 3, + .has_ddi = 1, + GEN_DEFAULT_PIPEOFFSETS, + IVB_CURSOR_OFFSETS, +}; + /* * Make sure any device matches here are from most specific to most * general. For example, since the Quanta match is based on the subsystem @@ -420,7 +431,8 @@ static const struct intel_device_info intel_skylake_gt3_info = { INTEL_CHV_IDS(&intel_cherryview_info), \ INTEL_SKL_GT1_IDS(&intel_skylake_info), \ INTEL_SKL_GT2_IDS(&intel_skylake_info), \ - INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info) \ + INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info), \ + INTEL_BXT_IDS(&intel_broxton_info) static const struct pci_device_id pciidlist[] = { /* aka */ INTEL_PCI_IDS, diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 613372375ada..bd0d644d2a03 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -287,4 +287,10 @@ INTEL_SKL_GT3_IDS(info) +#define INTEL_BXT_IDS(info) \ + INTEL_VGA_DEVICE(0x0A84, info), \ + INTEL_VGA_DEVICE(0x0A85, info), \ + INTEL_VGA_DEVICE(0x0A86, info), \ + INTEL_VGA_DEVICE(0x0A87, info) + #endif /* _I915_PCIIDS_H */ -- cgit v1.2.3