Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: omapdrm: dss: Support passing private data to debugfs show handlers

To simplify implementation of debugfs seq_file show handlers, the driver
passes the pointer to the show function through the debugfs_create_file
data pointer. This prevents using the pointer to pass driver private
data to the show handler, and requires all handlers to use global
variables to access private data.

To prepare for the removal of global private data in the driver, rework
the debugfs infrastructure to allow passing a private data pointer to
show handlers.

The price to pay is explicit removal of debugfs files to free the
internally allocated memory. This is desirable anyway as debugfs entries
should be removed when a component driver is unbound, otherwise crashes
will occur due to access to freed memory when the components will be
dynamically allocated instead of stored in global variables.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>

authored by

Laurent Pinchart and committed by
Tomi Valkeinen
f33656e1 360c2153

+141 -63
+10 -3
drivers/gpu/drm/omapdrm/dss/dispc.c
··· 167 167 void __iomem *base; 168 168 struct dss_device *dss; 169 169 170 + struct dss_debugfs_entry *debugfs; 171 + 170 172 int irq; 171 173 irq_handler_t user_handler; 172 174 void *user_data; ··· 3270 3268 dispc_runtime_put(); 3271 3269 } 3272 3270 3273 - static void dispc_dump_regs(struct seq_file *s) 3271 + static int dispc_dump_regs(struct seq_file *s, void *p) 3274 3272 { 3275 3273 int i, j; 3276 3274 const char *mgr_names[] = { ··· 3291 3289 #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) 3292 3290 3293 3291 if (dispc_runtime_get()) 3294 - return; 3292 + return 0; 3295 3293 3296 3294 /* DISPC common registers */ 3297 3295 DUMPREG(DISPC_REVISION); ··· 3463 3461 3464 3462 #undef DISPC_REG 3465 3463 #undef DUMPREG 3464 + 3465 + return 0; 3466 3466 } 3467 3467 3468 3468 /* calculate clock rates using dividers in cinfo */ ··· 4624 4620 4625 4621 dispc_set_ops(&dispc_ops); 4626 4622 4627 - dss_debugfs_create_file("dispc", dispc_dump_regs); 4623 + dispc.debugfs = dss_debugfs_create_file("dispc", dispc_dump_regs, 4624 + &dispc); 4628 4625 4629 4626 return 0; 4630 4627 ··· 4637 4632 static void dispc_unbind(struct device *dev, struct device *master, 4638 4633 void *data) 4639 4634 { 4635 + dss_debugfs_remove_file(dispc.debugfs); 4636 + 4640 4637 dispc_set_ops(NULL); 4641 4638 4642 4639 pm_runtime_disable(dev);
+29 -11
drivers/gpu/drm/omapdrm/dss/dsi.c
··· 401 401 #endif 402 402 int debug_read; 403 403 int debug_write; 404 + struct { 405 + struct dss_debugfs_entry *irqs; 406 + struct dss_debugfs_entry *regs; 407 + } debugfs; 404 408 405 409 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 406 410 spinlock_t irq_stats_lock; ··· 1664 1660 #undef PIS 1665 1661 } 1666 1662 1667 - static void dsi1_dump_irqs(struct seq_file *s) 1663 + static int dsi1_dump_irqs(struct seq_file *s, void *p) 1668 1664 { 1669 1665 struct platform_device *dsidev = dsi_get_dsidev_from_id(0); 1670 1666 1671 1667 dsi_dump_dsidev_irqs(dsidev, s); 1668 + return 0; 1672 1669 } 1673 1670 1674 - static void dsi2_dump_irqs(struct seq_file *s) 1671 + static int dsi2_dump_irqs(struct seq_file *s, void *p) 1675 1672 { 1676 1673 struct platform_device *dsidev = dsi_get_dsidev_from_id(1); 1677 1674 1678 1675 dsi_dump_dsidev_irqs(dsidev, s); 1676 + return 0; 1679 1677 } 1680 1678 #endif 1681 1679 ··· 1765 1759 #undef DUMPREG 1766 1760 } 1767 1761 1768 - static void dsi1_dump_regs(struct seq_file *s) 1762 + static int dsi1_dump_regs(struct seq_file *s, void *p) 1769 1763 { 1770 1764 struct platform_device *dsidev = dsi_get_dsidev_from_id(0); 1771 1765 1772 1766 dsi_dump_dsidev_regs(dsidev, s); 1767 + return 0; 1773 1768 } 1774 1769 1775 - static void dsi2_dump_regs(struct seq_file *s) 1770 + static int dsi2_dump_regs(struct seq_file *s, void *p) 1776 1771 { 1777 1772 struct platform_device *dsidev = dsi_get_dsidev_from_id(1); 1778 1773 1779 1774 dsi_dump_dsidev_regs(dsidev, s); 1775 + return 0; 1780 1776 } 1781 1777 1782 1778 enum dsi_cio_power_state { ··· 5577 5569 dsi_runtime_put(dsidev); 5578 5570 5579 5571 if (dsi->module_id == 0) 5580 - dss_debugfs_create_file("dsi1_regs", dsi1_dump_regs); 5581 - else if (dsi->module_id == 1) 5582 - dss_debugfs_create_file("dsi2_regs", dsi2_dump_regs); 5583 - 5572 + dsi->debugfs.regs = dss_debugfs_create_file("dsi1_regs", 5573 + dsi1_dump_regs, 5574 + &dsi); 5575 + else 5576 + dsi->debugfs.regs = dss_debugfs_create_file("dsi2_regs", 5577 + dsi2_dump_regs, 5578 + &dsi); 5584 5579 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 5585 5580 if (dsi->module_id == 0) 5586 - dss_debugfs_create_file("dsi1_irqs", dsi1_dump_irqs); 5587 - else if (dsi->module_id == 1) 5588 - dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs); 5581 + dsi->debugfs.irqs = dss_debugfs_create_file("dsi1_irqs", 5582 + dsi1_dump_irqs, 5583 + &dsi); 5584 + else 5585 + dsi->debugfs.irqs = dss_debugfs_create_file("dsi2_irqs", 5586 + dsi2_dump_irqs, 5587 + &dsi); 5589 5588 #endif 5590 5589 5591 5590 return 0; ··· 5610 5595 { 5611 5596 struct platform_device *dsidev = to_platform_device(dev); 5612 5597 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5598 + 5599 + dss_debugfs_remove_file(dsi->debugfs.irqs); 5600 + dss_debugfs_remove_file(dsi->debugfs.regs); 5613 5601 5614 5602 of_platform_depopulate(&dsidev->dev); 5615 5603
+59 -30
drivers/gpu/drm/omapdrm/dss/dss.c
··· 365 365 } 366 366 #endif 367 367 368 - static void dss_dump_regs(struct seq_file *s) 368 + static int dss_dump_regs(struct seq_file *s, void *p) 369 369 { 370 370 struct dss_device *dss = s->private; 371 371 372 372 #define DUMPREG(dss, r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(dss, r)) 373 373 374 374 if (dss_runtime_get(dss)) 375 - return; 375 + return 0; 376 376 377 377 DUMPREG(dss, DSS_REVISION); 378 378 DUMPREG(dss, DSS_SYSCONFIG); ··· 387 387 388 388 dss_runtime_put(dss); 389 389 #undef DUMPREG 390 + return 0; 390 391 } 391 392 392 393 static int dss_get_channel_index(enum omap_channel channel) ··· 889 888 890 889 /* DEBUGFS */ 891 890 #if defined(CONFIG_OMAP2_DSS_DEBUGFS) 892 - static void dss_debug_dump_clocks(struct seq_file *s) 891 + static int dss_debug_dump_clocks(struct seq_file *s, void *p) 893 892 { 894 893 struct dss_device *dss = s->private; 895 894 ··· 898 897 #ifdef CONFIG_OMAP2_DSS_DSI 899 898 dsi_dump_clocks(s); 900 899 #endif 901 - } 902 - 903 - static int dss_debug_show(struct seq_file *s, void *unused) 904 - { 905 - void (*func)(struct seq_file *) = s->private; 906 - 907 - func(s); 908 900 return 0; 909 901 } 910 - 911 - static int dss_debug_open(struct inode *inode, struct file *file) 912 - { 913 - return single_open(file, dss_debug_show, inode->i_private); 914 - } 915 - 916 - static const struct file_operations dss_debug_fops = { 917 - .open = dss_debug_open, 918 - .read = seq_read, 919 - .llseek = seq_lseek, 920 - .release = single_release, 921 - }; 922 902 923 903 static struct dentry *dss_debugfs_dir; 924 904 ··· 913 931 return err; 914 932 } 915 933 916 - debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, 917 - &dss_debug_dump_clocks, &dss_debug_fops); 918 - 919 934 return 0; 920 935 } 921 936 ··· 922 943 debugfs_remove_recursive(dss_debugfs_dir); 923 944 } 924 945 925 - int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) 946 + struct dss_debugfs_entry { 947 + struct dentry *dentry; 948 + int (*show_fn)(struct seq_file *s, void *data); 949 + void *data; 950 + }; 951 + 952 + static int dss_debug_open(struct inode *inode, struct file *file) 926 953 { 954 + struct dss_debugfs_entry *entry = inode->i_private; 955 + 956 + return single_open(file, entry->show_fn, entry->data); 957 + } 958 + 959 + static const struct file_operations dss_debug_fops = { 960 + .open = dss_debug_open, 961 + .read = seq_read, 962 + .llseek = seq_lseek, 963 + .release = single_release, 964 + }; 965 + 966 + struct dss_debugfs_entry *dss_debugfs_create_file(const char *name, 967 + int (*show_fn)(struct seq_file *s, void *data), void *data) 968 + { 969 + struct dss_debugfs_entry *entry; 927 970 struct dentry *d; 928 971 929 - d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, 930 - write, &dss_debug_fops); 972 + entry = kzalloc(sizeof(*entry), GFP_KERNEL); 973 + if (!entry) 974 + return ERR_PTR(-ENOMEM); 931 975 932 - return PTR_ERR_OR_ZERO(d); 976 + entry->show_fn = show_fn; 977 + entry->data = data; 978 + 979 + d = debugfs_create_file(name, 0444, dss_debugfs_dir, entry, 980 + &dss_debug_fops); 981 + if (IS_ERR(d)) { 982 + kfree(entry); 983 + return ERR_PTR(PTR_ERR(d)); 984 + } 985 + 986 + entry->dentry = d; 987 + return entry; 933 988 } 989 + 990 + void dss_debugfs_remove_file(struct dss_debugfs_entry *entry) 991 + { 992 + if (IS_ERR_OR_NULL(entry)) 993 + return; 994 + 995 + debugfs_remove(entry->dentry); 996 + kfree(entry); 997 + } 998 + 934 999 #else /* CONFIG_OMAP2_DSS_DEBUGFS */ 935 1000 static inline int dss_initialize_debugfs(struct dss_device *dss) 936 1001 { ··· 1472 1449 if (r) 1473 1450 goto err_pm_runtime_disable; 1474 1451 1475 - dss_debugfs_create_file("dss", dss_dump_regs); 1452 + dss->debugfs.clk = dss_debugfs_create_file("clk", dss_debug_dump_clocks, 1453 + dss); 1454 + dss->debugfs.dss = dss_debugfs_create_file("dss", dss_dump_regs, dss); 1476 1455 1477 1456 /* Add all the child devices as components. */ 1478 1457 device_for_each_child(&pdev->dev, &match, dss_add_child_component); ··· 1486 1461 return 0; 1487 1462 1488 1463 err_uninit_debugfs: 1464 + dss_debugfs_remove_file(dss->debugfs.clk); 1465 + dss_debugfs_remove_file(dss->debugfs.dss); 1489 1466 dss_uninitialize_debugfs(); 1490 1467 1491 1468 err_pm_runtime_disable: ··· 1515 1488 1516 1489 component_master_del(&pdev->dev, &dss_component_ops); 1517 1490 1491 + dss_debugfs_remove_file(dss->debugfs.clk); 1492 + dss_debugfs_remove_file(dss->debugfs.dss); 1518 1493 dss_uninitialize_debugfs(); 1519 1494 1520 1495 pm_runtime_disable(&pdev->dev);
+21 -10
drivers/gpu/drm/omapdrm/dss/dss.h
··· 25 25 26 26 #include "omapdss.h" 27 27 28 + struct dss_debugfs_entry; 29 + struct platform_device; 30 + struct seq_file; 31 + 28 32 #define MAX_DSS_LCD_MANAGERS 3 29 33 #define MAX_NUM_DSI 2 30 34 ··· 237 233 int lcden_sig_polarity; 238 234 }; 239 235 240 - struct seq_file; 241 - struct platform_device; 242 - 243 236 #define DSS_SZ_REGS SZ_512 244 237 245 238 struct dss_device { ··· 262 261 263 262 const struct dss_features *feat; 264 263 264 + struct { 265 + struct dss_debugfs_entry *clk; 266 + struct dss_debugfs_entry *dss; 267 + } debugfs; 268 + 265 269 struct dss_pll *video1_pll; 266 270 struct dss_pll *video2_pll; 267 271 }; ··· 289 283 290 284 /* DSS */ 291 285 #if defined(CONFIG_OMAP2_DSS_DEBUGFS) 292 - int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); 286 + struct dss_debugfs_entry *dss_debugfs_create_file(const char *name, 287 + int (*show_fn)(struct seq_file *s, void *data), void *data); 288 + void dss_debugfs_remove_file(struct dss_debugfs_entry *entry); 293 289 #else 294 - static inline int dss_debugfs_create_file(const char *name, 295 - void (*write)(struct seq_file *)) 290 + static inline struct dss_debugfs_entry * 291 + dss_debugfs_create_file(const char *name, 292 + int (*show_fn)(struct seq_file *s, void *data), 293 + void *data) 296 294 { 297 - return 0; 295 + return NULL; 296 + } 297 + 298 + static inline void dss_debugfs_remove_file(struct dss_debugfs_entry *entry) 299 + { 298 300 } 299 301 #endif /* CONFIG_OMAP2_DSS_DEBUGFS */ 300 302 ··· 373 359 /* DSI */ 374 360 375 361 #ifdef CONFIG_OMAP2_DSS_DSI 376 - 377 - struct dentry; 378 - struct file_operations; 379 362 380 363 void dsi_dump_clocks(struct seq_file *s); 381 364
+2
drivers/gpu/drm/omapdrm/dss/hdmi.h
··· 361 361 struct platform_device *pdev; 362 362 struct dss_device *dss; 363 363 364 + struct dss_debugfs_entry *debugfs; 365 + 364 366 struct hdmi_wp_data wp; 365 367 struct hdmi_pll_data pll; 366 368 struct hdmi_phy_data phy;
+6 -3
drivers/gpu/drm/omapdrm/dss/hdmi4.c
··· 303 303 *vm = hdmi.cfg.vm; 304 304 } 305 305 306 - static void hdmi_dump_regs(struct seq_file *s) 306 + static int hdmi_dump_regs(struct seq_file *s, void *p) 307 307 { 308 308 mutex_lock(&hdmi.lock); 309 309 310 310 if (hdmi_runtime_get()) { 311 311 mutex_unlock(&hdmi.lock); 312 - return; 312 + return 0; 313 313 } 314 314 315 315 hdmi_wp_dump(&hdmi.wp, s); ··· 319 319 320 320 hdmi_runtime_put(); 321 321 mutex_unlock(&hdmi.lock); 322 + return 0; 322 323 } 323 324 324 325 static int read_edid(u8 *buf, int len) ··· 780 779 return r; 781 780 } 782 781 783 - dss_debugfs_create_file("hdmi", hdmi_dump_regs); 782 + hdmi.debugfs = dss_debugfs_create_file("hdmi", hdmi_dump_regs, &hdmi); 784 783 785 784 return 0; 786 785 err: ··· 791 790 static void hdmi4_unbind(struct device *dev, struct device *master, void *data) 792 791 { 793 792 struct platform_device *pdev = to_platform_device(dev); 793 + 794 + dss_debugfs_remove_file(hdmi.debugfs); 794 795 795 796 if (hdmi.audio_pdev) 796 797 platform_device_unregister(hdmi.audio_pdev);
+6 -3
drivers/gpu/drm/omapdrm/dss/hdmi5.c
··· 299 299 *vm = hdmi.cfg.vm; 300 300 } 301 301 302 - static void hdmi_dump_regs(struct seq_file *s) 302 + static int hdmi_dump_regs(struct seq_file *s, void *p) 303 303 { 304 304 mutex_lock(&hdmi.lock); 305 305 306 306 if (hdmi_runtime_get()) { 307 307 mutex_unlock(&hdmi.lock); 308 - return; 308 + return 0; 309 309 } 310 310 311 311 hdmi_wp_dump(&hdmi.wp, s); ··· 315 315 316 316 hdmi_runtime_put(); 317 317 mutex_unlock(&hdmi.lock); 318 + return 0; 318 319 } 319 320 320 321 static int read_edid(u8 *buf, int len) ··· 777 776 return r; 778 777 } 779 778 780 - dss_debugfs_create_file("hdmi", hdmi_dump_regs); 779 + hdmi.debugfs = dss_debugfs_create_file("hdmi", hdmi_dump_regs, &hdmi); 781 780 782 781 return 0; 783 782 err: ··· 788 787 static void hdmi5_unbind(struct device *dev, struct device *master, void *data) 789 788 { 790 789 struct platform_device *pdev = to_platform_device(dev); 790 + 791 + dss_debugfs_remove_file(hdmi.debugfs); 791 792 792 793 if (hdmi.audio_pdev) 793 794 platform_device_unregister(hdmi.audio_pdev);
+8 -3
drivers/gpu/drm/omapdrm/dss/venc.c
··· 327 327 struct regulator *vdda_dac_reg; 328 328 struct dss_device *dss; 329 329 330 + struct dss_debugfs_entry *debugfs; 331 + 330 332 struct clk *tv_dac_clk; 331 333 332 334 struct videomode vm; ··· 672 670 return 0; 673 671 } 674 672 675 - static void venc_dump_regs(struct seq_file *s) 673 + static int venc_dump_regs(struct seq_file *s, void *p) 676 674 { 677 675 #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) 678 676 679 677 if (venc_runtime_get()) 680 - return; 678 + return 0; 681 679 682 680 DUMPREG(VENC_F_CONTROL); 683 681 DUMPREG(VENC_VIDOUT_CTRL); ··· 724 722 venc_runtime_put(); 725 723 726 724 #undef DUMPREG 725 + return 0; 727 726 } 728 727 729 728 static int venc_get_clocks(struct platform_device *pdev) ··· 917 914 goto err_probe_of; 918 915 } 919 916 920 - dss_debugfs_create_file("venc", venc_dump_regs); 917 + venc.debugfs = dss_debugfs_create_file("venc", venc_dump_regs, &venc); 921 918 922 919 venc_init_output(pdev); 923 920 ··· 932 929 static void venc_unbind(struct device *dev, struct device *master, void *data) 933 930 { 934 931 struct platform_device *pdev = to_platform_device(dev); 932 + 933 + dss_debugfs_remove_file(venc.debugfs); 935 934 936 935 venc_uninit_output(pdev); 937 936