From a4196febbe75e2cc8fcb7af6460d2c3ef208d66c Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Sat, 24 Mar 2012 21:58:45 +0530 Subject: video: s3c-fb: move video interface timing out of window setup data The video interface timing is independent of the window setup data. The resolution of the window can be smaller than that of the lcd panel to which the video data is output. So move the video timing data from the per-window setup data to the platform specific section in the platform data. This also removes the restriction that atleast one window should have the same resolution as that of the panel attached. Cc: Ben Dooks Signed-off-by: Thomas Abraham Acked-by: Jingoo Han Signed-off-by: Florian Tobias Schandinat diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h index 0fedf47..39d6bd7a 100644 --- a/arch/arm/plat-samsung/include/plat/fb.h +++ b/arch/arm/plat-samsung/include/plat/fb.h @@ -24,15 +24,16 @@ /** * struct s3c_fb_pd_win - per window setup data - * @win_mode: The display parameters to initialise (not for window 0) + * @xres : The window X size. + * @yres : The window Y size. * @virtual_x: The virtual X size. * @virtual_y: The virtual Y size. */ struct s3c_fb_pd_win { - struct fb_videomode win_mode; - unsigned short default_bpp; unsigned short max_bpp; + unsigned short xres; + unsigned short yres; unsigned short virtual_x; unsigned short virtual_y; }; @@ -45,6 +46,7 @@ struct s3c_fb_pd_win { * @default_win: default window layer number to be used for UI layer. * @vidcon0: The base vidcon0 values to control the panel data format. * @vidcon1: The base vidcon1 values to control the panel data output. + * @vtiming: Video timing when connected to a RGB type panel. * @win: The setup data for each hardware window, or NULL for unused. * @display_mode: The LCD output display mode. * @@ -58,6 +60,7 @@ struct s3c_fb_platdata { void (*setup_gpio)(void); struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; + struct fb_videomode *vtiming; u32 default_win; diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index f310516..c94f40d 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -495,7 +495,6 @@ static int s3c_fb_set_par(struct fb_info *info) u32 alpha = 0; u32 data; u32 pagewidth; - int clkdiv; dev_dbg(sfb->dev, "setting framebuffer parameters\n"); @@ -532,48 +531,9 @@ static int s3c_fb_set_par(struct fb_info *info) /* disable the window whilst we update it */ writel(0, regs + WINCON(win_no)); - /* use platform specified window as the basis for the lcd timings */ - - if (win_no == sfb->pdata->default_win) { - clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); - - data = sfb->pdata->vidcon0; - data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); - - if (clkdiv > 1) - data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR; - else - data &= ~VIDCON0_CLKDIR; /* 1:1 clock */ - - /* write the timing data to the panel */ - - if (sfb->variant.is_2443) - data |= (1 << 5); - - writel(data, regs + VIDCON0); - + if (win_no == sfb->pdata->default_win) s3c_fb_enable(sfb, 1); - data = VIDTCON0_VBPD(var->upper_margin - 1) | - VIDTCON0_VFPD(var->lower_margin - 1) | - VIDTCON0_VSPW(var->vsync_len - 1); - - writel(data, regs + sfb->variant.vidtcon); - - data = VIDTCON1_HBPD(var->left_margin - 1) | - VIDTCON1_HFPD(var->right_margin - 1) | - VIDTCON1_HSPW(var->hsync_len - 1); - - /* VIDTCON1 */ - writel(data, regs + sfb->variant.vidtcon + 4); - - data = VIDTCON2_LINEVAL(var->yres - 1) | - VIDTCON2_HOZVAL(var->xres - 1) | - VIDTCON2_LINEVAL_E(var->yres - 1) | - VIDTCON2_HOZVAL_E(var->xres - 1); - writel(data, regs + sfb->variant.vidtcon + 8); - } - /* write the buffer address */ /* start and end registers stride is 8 */ @@ -1144,11 +1104,11 @@ static int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb, dev_dbg(sfb->dev, "allocating memory for display\n"); - real_size = windata->win_mode.xres * windata->win_mode.yres; + real_size = windata->xres * windata->yres; virt_size = windata->virtual_x * windata->virtual_y; dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n", - real_size, windata->win_mode.xres, windata->win_mode.yres, + real_size, windata->xres, windata->yres, virt_size, windata->virtual_x, windata->virtual_y); size = (real_size > virt_size) ? real_size : virt_size; @@ -1230,7 +1190,7 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, struct s3c_fb_win **res) { struct fb_var_screeninfo *var; - struct fb_videomode *initmode; + struct fb_videomode initmode; struct s3c_fb_pd_win *windata; struct s3c_fb_win *win; struct fb_info *fbinfo; @@ -1251,11 +1211,11 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, } windata = sfb->pdata->win[win_no]; - initmode = &windata->win_mode; + initmode = *sfb->pdata->vtiming; WARN_ON(windata->max_bpp == 0); - WARN_ON(windata->win_mode.xres == 0); - WARN_ON(windata->win_mode.yres == 0); + WARN_ON(windata->xres == 0); + WARN_ON(windata->yres == 0); win = fbinfo->par; *res = win; @@ -1294,7 +1254,9 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, } /* setup the initial video mode from the window */ - fb_videomode_to_var(&fbinfo->var, initmode); + initmode.xres = windata->xres; + initmode.yres = windata->yres; + fb_videomode_to_var(&fbinfo->var, &initmode); fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; fbinfo->fix.accel = FB_ACCEL_NONE; @@ -1339,6 +1301,53 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, } /** + * s3c_fb_set_rgb_timing() - set video timing for rgb interface. + * @sfb: The base resources for the hardware. + * + * Set horizontal and vertical lcd rgb interface timing. + */ +static void s3c_fb_set_rgb_timing(struct s3c_fb *sfb) +{ + struct fb_videomode *vmode = sfb->pdata->vtiming; + void __iomem *regs = sfb->regs; + int clkdiv; + u32 data; + + if (!vmode->pixclock) + s3c_fb_missing_pixclock(vmode); + + clkdiv = s3c_fb_calc_pixclk(sfb, vmode->pixclock); + + data = sfb->pdata->vidcon0; + data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); + + if (clkdiv > 1) + data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR; + else + data &= ~VIDCON0_CLKDIR; /* 1:1 clock */ + + if (sfb->variant.is_2443) + data |= (1 << 5); + writel(data, regs + VIDCON0); + + data = VIDTCON0_VBPD(vmode->upper_margin - 1) | + VIDTCON0_VFPD(vmode->lower_margin - 1) | + VIDTCON0_VSPW(vmode->vsync_len - 1); + writel(data, regs + sfb->variant.vidtcon); + + data = VIDTCON1_HBPD(vmode->left_margin - 1) | + VIDTCON1_HFPD(vmode->right_margin - 1) | + VIDTCON1_HSPW(vmode->hsync_len - 1); + writel(data, regs + sfb->variant.vidtcon + 4); + + data = VIDTCON2_LINEVAL(vmode->yres - 1) | + VIDTCON2_HOZVAL(vmode->xres - 1) | + VIDTCON2_LINEVAL_E(vmode->yres - 1) | + VIDTCON2_HOZVAL_E(vmode->xres - 1); + writel(data, regs + sfb->variant.vidtcon + 8); +} + +/** * s3c_fb_clear_win() - clear hardware window registers. * @sfb: The base resources for the hardware. * @win: The window to process. @@ -1481,15 +1490,14 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) writel(0xffffff, regs + WKEYCON1); } + s3c_fb_set_rgb_timing(sfb); + /* we have the register setup, start allocating framebuffers */ for (win = 0; win < fbdrv->variant.nr_windows; win++) { if (!pd->win[win]) continue; - if (!pd->win[win]->win_mode.pixclock) - s3c_fb_missing_pixclock(&pd->win[win]->win_mode); - ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win], &sfb->windows[win]); if (ret < 0) { @@ -1623,6 +1631,8 @@ static int s3c_fb_resume(struct device *dev) shadow_protect_win(win, 0); } + s3c_fb_set_rgb_timing(sfb); + /* restore framebuffers */ for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { win = sfb->windows[win_no]; -- cgit v0.10.2 From 3c582647a9f84affd5c86e89d548157c62f8d9ca Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Sat, 24 Mar 2012 21:58:46 +0530 Subject: video: s3c-fb: remove 'default_win' element from platform data The decision to enable or disable the data output to the lcd panel from the controller need not be based on the value of 'default_win' element in the platform data. Instead, the data output to the panel is enabled if any of the windows are active, else data output is disabled. Cc: Ben Dooks Signed-off-by: Jingoo Han Signed-off-by: Thomas Abraham Signed-off-by: Florian Tobias Schandinat diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h index 39d6bd7a..536002f 100644 --- a/arch/arm/plat-samsung/include/plat/fb.h +++ b/arch/arm/plat-samsung/include/plat/fb.h @@ -62,8 +62,6 @@ struct s3c_fb_platdata { struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN]; struct fb_videomode *vtiming; - u32 default_win; - u32 vidcon0; u32 vidcon1; }; diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index c94f40d..18c84b8 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -531,7 +531,7 @@ static int s3c_fb_set_par(struct fb_info *info) /* disable the window whilst we update it */ writel(0, regs + WINCON(win_no)); - if (win_no == sfb->pdata->default_win) + if (!sfb->output_on) s3c_fb_enable(sfb, 1); /* write the buffer address */ @@ -799,6 +799,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) struct s3c_fb *sfb = win->parent; unsigned int index = win->index; u32 wincon; + u32 output_on = sfb->output_on; dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); @@ -837,34 +838,18 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) shadow_protect_win(win, 1); writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4)); - shadow_protect_win(win, 0); /* Check the enabled state to see if we need to be running the * main LCD interface, as if there are no active windows then * it is highly likely that we also do not need to output * anything. */ - - /* We could do something like the following code, but the current - * system of using framebuffer events means that we cannot make - * the distinction between just window 0 being inactive and all - * the windows being down. - * - * s3c_fb_enable(sfb, sfb->enabled ? 1 : 0); - */ - - /* we're stuck with this until we can do something about overriding - * the power control using the blanking event for a single fb. - */ - if (index == sfb->pdata->default_win) { - shadow_protect_win(win, 1); - s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); - shadow_protect_win(win, 0); - } + s3c_fb_enable(sfb, sfb->enabled ? 1 : 0); + shadow_protect_win(win, 0); pm_runtime_put_sync(sfb->dev); - return 0; + return output_on == sfb->output_on; } /** -- cgit v0.10.2 From 884924be2a3368a3ac96587f347f9973c80140f6 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Sat, 24 Mar 2012 21:58:47 +0530 Subject: ARM: s3c64xx: Decouple lcd type from display controller window data The display controller window data should contain window configuration data for only one type of lcd panel. So, for real6410 and mini6410 boards, split the existing display controller window data, which contains window configuration data for two different types of lcd panels, into two seperate instances and register one of them depending on the type of the lcd panel detected at runtime. This is a prerequisite change for a subsequent commit that reorders the platform data of display controller by moving video interface timing out of window setup data. Cc: Darius Augulis Acked-by: Jingoo Han Signed-off-by: Thomas Abraham Signed-off-by: Florian Tobias Schandinat diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c index c34c2ab..34f5195 100644 --- a/arch/arm/mach-s3c64xx/mach-mini6410.c +++ b/arch/arm/mach-s3c64xx/mach-mini6410.c @@ -151,41 +151,49 @@ static struct s3c2410_platform_nand mini6410_nand_info = { .sets = mini6410_nand_sets, }; -static struct s3c_fb_pd_win mini6410_fb_win[] = { - { - .win_mode = { /* 4.3" 480x272 */ - .left_margin = 3, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 1, - .hsync_len = 40, - .vsync_len = 1, - .xres = 480, - .yres = 272, - }, - .max_bpp = 32, - .default_bpp = 16, - }, { - .win_mode = { /* 7.0" 800x480 */ - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, - .max_bpp = 32, - .default_bpp = 16, +static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = { + .win_mode = { /* 4.3" 480x272 */ + .left_margin = 3, + .right_margin = 2, + .upper_margin = 1, + .lower_margin = 1, + .hsync_len = 40, + .vsync_len = 1, + .xres = 480, + .yres = 272, }, + .max_bpp = 32, + .default_bpp = 16, }; -static struct s3c_fb_platdata mini6410_lcd_pdata __initdata = { - .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .win[0] = &mini6410_fb_win[0], - .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, - .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, +static struct s3c_fb_pd_win mini6410_lcd_type1_fb_win = { + .win_mode = { /* 7.0" 800x480 */ + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 16, +}; + +static struct s3c_fb_platdata mini6410_lcd_pdata[] __initdata = { + { + .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .win[0] = &mini6410_lcd_type0_fb_win, + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + }, { + .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .win[0] = &mini6410_lcd_type1_fb_win, + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + }, + { }, }; static void mini6410_lcd_power_set(struct plat_lcd_data *pd, @@ -283,7 +291,7 @@ static void mini6410_parse_features( "screen type already set\n", f); } else { int li = f - '0'; - if (li >= ARRAY_SIZE(mini6410_fb_win)) + if (li >= ARRAY_SIZE(mini6410_lcd_pdata)) printk(KERN_INFO "MINI6410: '%c' out " "of range LCD mode\n", f); else { @@ -307,14 +315,12 @@ static void __init mini6410_machine_init(void) /* Parse the feature string */ mini6410_parse_features(&features, mini6410_features_str); - mini6410_lcd_pdata.win[0] = &mini6410_fb_win[features.lcd_index]; - printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n", - mini6410_lcd_pdata.win[0]->win_mode.xres, - mini6410_lcd_pdata.win[0]->win_mode.yres); + mini6410_lcd_pdata[features.lcd_index].win[0]->win_mode.xres, + mini6410_lcd_pdata[features.lcd_index].win[0]->win_mode.yres); s3c_nand_set_platdata(&mini6410_nand_info); - s3c_fb_set_platdata(&mini6410_lcd_pdata); + s3c_fb_set_platdata(&mini6410_lcd_pdata[features.lcd_index]); s3c24xx_ts_set_platdata(NULL); /* configure nCS1 width to 16 bits */ diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c index be2a9a2..21f91e5 100644 --- a/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/arch/arm/mach-s3c64xx/mach-real6410.c @@ -117,41 +117,49 @@ static struct platform_device real6410_device_eth = { }, }; -static struct s3c_fb_pd_win real6410_fb_win[] = { - { - .win_mode = { /* 4.3" 480x272 */ - .left_margin = 3, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 1, - .hsync_len = 40, - .vsync_len = 1, - .xres = 480, - .yres = 272, - }, - .max_bpp = 32, - .default_bpp = 16, - }, { - .win_mode = { /* 7.0" 800x480 */ - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, - .max_bpp = 32, - .default_bpp = 16, +static struct s3c_fb_pd_win real6410_lcd_type0_fb_win = { + .win_mode = { /* 4.3" 480x272 */ + .left_margin = 3, + .right_margin = 2, + .upper_margin = 1, + .lower_margin = 1, + .hsync_len = 40, + .vsync_len = 1, + .xres = 480, + .yres = 272, }, + .max_bpp = 32, + .default_bpp = 16, }; -static struct s3c_fb_platdata real6410_lcd_pdata __initdata = { - .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, - .win[0] = &real6410_fb_win[0], - .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, - .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, +static struct s3c_fb_pd_win real6410_lcd_type1_fb_win = { + .win_mode = { /* 7.0" 800x480 */ + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 16, +}; + +static struct s3c_fb_platdata real6410_lcd_pdata[] __initdata = { + { + .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .win[0] = &real6410_lcd_type0_fb_win, + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + }, { + .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .win[0] = &real6410_lcd_type1_fb_win, + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, + }, + { }, }; static struct mtd_partition real6410_nand_part[] = { @@ -264,7 +272,7 @@ static void real6410_parse_features( "screen type already set\n", f); } else { int li = f - '0'; - if (li >= ARRAY_SIZE(real6410_fb_win)) + if (li >= ARRAY_SIZE(real6410_lcd_pdata)) printk(KERN_INFO "REAL6410: '%c' out " "of range LCD mode\n", f); else { @@ -288,13 +296,11 @@ static void __init real6410_machine_init(void) /* Parse the feature string */ real6410_parse_features(&features, real6410_features_str); - real6410_lcd_pdata.win[0] = &real6410_fb_win[features.lcd_index]; - printk(KERN_INFO "REAL6410: selected LCD display is %dx%d\n", - real6410_lcd_pdata.win[0]->win_mode.xres, - real6410_lcd_pdata.win[0]->win_mode.yres); + real6410_lcd_pdata[features.lcd_index].win[0]->win_mode.xres, + real6410_lcd_pdata[features.lcd_index].win[0]->win_mode.yres); - s3c_fb_set_platdata(&real6410_lcd_pdata); + s3c_fb_set_platdata(&real6410_lcd_pdata[features.lcd_index]); s3c_nand_set_platdata(&real6410_nand_info); s3c24xx_ts_set_platdata(NULL); -- cgit v0.10.2 From 79d3c41ae444fb064cc8aab7cb249f577d6e0aae Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Sat, 24 Mar 2012 21:58:48 +0530 Subject: ARM: Samsung: Rework platform data of s3c-fb driver For all the Samsung SoC based boards which have the platform data for s3c-fb driver, the 'default_win' element in the platform data is removed and the lcd panel video timing values are moved out of individual window configuration data. Acked-by: Jingoo Han Cc: Kyungmin Park Cc: JeongHyeon Kim Cc: Kukjin Kim Cc: Heiko Stuebner Cc: Ben Dooks Cc: Kwangwoo Lee Cc: Mark Brown Cc: Peter Korsgaard Cc: Darius Augulis Cc: Maurus Cuelenaere Signed-off-by: Thomas Abraham Signed-off-by: Florian Tobias Schandinat diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index b3982c8..e1e640e 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -214,25 +214,29 @@ static struct platform_device nuri_gpio_keys = { /* Frame Buffer */ static struct s3c_fb_pd_win nuri_fb_win0 = { - .win_mode = { - .left_margin = 64, - .right_margin = 16, - .upper_margin = 64, - .lower_margin = 1, - .hsync_len = 48, - .vsync_len = 3, - .xres = 1024, - .yres = 600, - .refresh = 60, - }, .max_bpp = 24, .default_bpp = 16, + .xres = 1024, + .yres = 600, .virtual_x = 1024, .virtual_y = 2 * 600, }; +static struct fb_videomode nuri_lcd_timing = { + .left_margin = 64, + .right_margin = 16, + .upper_margin = 64, + .lower_margin = 1, + .hsync_len = 48, + .vsync_len = 3, + .xres = 1024, + .yres = 600, + .refresh = 60, +}; + static struct s3c_fb_platdata nuri_fb_pdata __initdata = { .win[0] = &nuri_fb_win0, + .vtiming = &nuri_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | VIDCON0_CLKSEL_LCD, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 878d4c9..0968eba 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -584,22 +584,26 @@ static struct platform_device origen_lcd_hv070wsa = { }; static struct s3c_fb_pd_win origen_fb_win0 = { - .win_mode = { - .left_margin = 64, - .right_margin = 16, - .upper_margin = 64, - .lower_margin = 16, - .hsync_len = 48, - .vsync_len = 3, - .xres = 1024, - .yres = 600, - }, + .xres = 1024, + .yres = 600, .max_bpp = 32, .default_bpp = 24, }; +static struct fb_videomode origen_lcd_timing = { + .left_margin = 64, + .right_margin = 16, + .upper_margin = 64, + .lower_margin = 16, + .hsync_len = 48, + .vsync_len = 3, + .xres = 1024, + .yres = 600, +}; + static struct s3c_fb_platdata origen_lcd_pdata __initdata = { .win[0] = &origen_fb_win0, + .vtiming = &origen_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | VIDCON1_INV_VCLK, diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c index 83b91fa..3e482b8 100644 --- a/arch/arm/mach-exynos/mach-smdkv310.c +++ b/arch/arm/mach-exynos/mach-smdkv310.c @@ -161,22 +161,26 @@ static struct platform_device smdkv310_lcd_lte480wv = { }; static struct s3c_fb_pd_win smdkv310_fb_win0 = { - .win_mode = { - .left_margin = 13, - .right_margin = 8, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, - .max_bpp = 32, - .default_bpp = 24, + .max_bpp = 32, + .default_bpp = 24, + .xres = 800, + .yres = 480, +}; + +static struct fb_videomode smdkv310_lcd_timing = { + .left_margin = 13, + .right_margin = 8, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, }; static struct s3c_fb_platdata smdkv310_lcd0_pdata __initdata = { .win[0] = &smdkv310_fb_win0, + .vtiming = &smdkv310_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = exynos4_fimd0_gpio_setup_24bpp, diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c index 6bb9dbd..879c539 100644 --- a/arch/arm/mach-exynos/mach-universal_c210.c +++ b/arch/arm/mach-exynos/mach-universal_c210.c @@ -812,25 +812,29 @@ static struct i2c_board_info i2c1_devs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win universal_fb_win0 = { - .win_mode = { - .left_margin = 16, - .right_margin = 16, - .upper_margin = 2, - .lower_margin = 28, - .hsync_len = 2, - .vsync_len = 1, - .xres = 480, - .yres = 800, - .refresh = 55, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 480, + .yres = 800, .virtual_x = 480, .virtual_y = 2 * 800, }; +static struct fb_videomode universal_lcd_timing = { + .left_margin = 16, + .right_margin = 16, + .upper_margin = 2, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 1, + .xres = 480, + .yres = 800, + .refresh = 55, +}; + static struct s3c_fb_platdata universal_lcd_pdata __initdata = { .win[0] = &universal_fb_win0, + .vtiming = &universal_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | VIDCON0_CLKSEL_LCD, .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c index 30a44f8..c3100a0 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2416.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c @@ -148,23 +148,25 @@ static struct s3c24xx_hsudc_platdata smdk2416_hsudc_platdata = { static struct s3c_fb_pd_win smdk2416_fb_win[] = { [0] = { - /* think this is the same as the smdk6410 */ - .win_mode = { - .pixclock = 41094, - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, .default_bpp = 16, .max_bpp = 32, + .xres = 800, + .yres = 480, }, }; +static struct fb_videomode smdk2416_lcd_timing = { + .pixclock = 41094, + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, +}; + static void s3c2416_fb_gpio_setup_24bpp(void) { unsigned int gpio; @@ -187,6 +189,7 @@ static void s3c2416_fb_gpio_setup_24bpp(void) static struct s3c_fb_platdata smdk2416_fb_platdata = { .win[0] = &smdk2416_fb_win[0], + .vtiming = &smdk2416_lcd_timing, .setup_gpio = s3c2416_fb_gpio_setup_24bpp, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c index b86f277..58fd0e3 100644 --- a/arch/arm/mach-s3c64xx/mach-anw6410.c +++ b/arch/arm/mach-s3c64xx/mach-anw6410.c @@ -134,24 +134,27 @@ static struct platform_device anw6410_lcd_powerdev = { }; static struct s3c_fb_pd_win anw6410_fb_win0 = { - /* this is to ensure we use win0 */ - .win_mode = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 800, + .yres = 480, +}; + +static struct fb_videomode anw6410_lcd_timing = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, }; /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .vtiming = &anw6410_lcd_timing, .win[0] = &anw6410_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index e20bf58..c1ef57e 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -151,26 +151,29 @@ static struct platform_device crag6410_lcd_powerdev = { /* 640x480 URT */ static struct s3c_fb_pd_win crag6410_fb_win0 = { - /* this is to ensure we use win0 */ - .win_mode = { - .left_margin = 150, - .right_margin = 80, - .upper_margin = 40, - .lower_margin = 5, - .hsync_len = 40, - .vsync_len = 5, - .xres = 640, - .yres = 480, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 640, + .yres = 480, .virtual_y = 480 * 2, .virtual_x = 640, }; +static struct fb_videomode crag6410_lcd_timing = { + .left_margin = 150, + .right_margin = 80, + .upper_margin = 40, + .lower_margin = 5, + .hsync_len = 40, + .vsync_len = 5, + .xres = 640, + .yres = 480, +}; + /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .vtiming = &crag6410_lcd_timing, .win[0] = &crag6410_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c index 521e07b..4e9b1ac 100644 --- a/arch/arm/mach-s3c64xx/mach-hmt.c +++ b/arch/arm/mach-s3c64xx/mach-hmt.c @@ -129,23 +129,27 @@ static struct platform_device hmt_backlight_device = { }; static struct s3c_fb_pd_win hmt_fb_win0 = { - .win_mode = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 800, + .yres = 480, +}; + +static struct fb_videomode hmt_lcd_timing = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, }; /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata hmt_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .vtiming = &hmt_lcd_timing, .win[0] = &hmt_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c index 34f5195..2f425d5 100644 --- a/arch/arm/mach-s3c64xx/mach-mini6410.c +++ b/arch/arm/mach-s3c64xx/mach-mini6410.c @@ -152,43 +152,53 @@ static struct s3c2410_platform_nand mini6410_nand_info = { }; static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = { - .win_mode = { /* 4.3" 480x272 */ - .left_margin = 3, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 1, - .hsync_len = 40, - .vsync_len = 1, - .xres = 480, - .yres = 272, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 480, + .yres = 272, +}; + +static struct fb_videomode mini6410_lcd_type0_timing = { + /* 4.3" 480x272 */ + .left_margin = 3, + .right_margin = 2, + .upper_margin = 1, + .lower_margin = 1, + .hsync_len = 40, + .vsync_len = 1, + .xres = 480, + .yres = 272, }; static struct s3c_fb_pd_win mini6410_lcd_type1_fb_win = { - .win_mode = { /* 7.0" 800x480 */ - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 800, + .yres = 480, +}; + +static struct fb_videomode mini6410_lcd_type1_timing = { + /* 7.0" 800x480 */ + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, }; static struct s3c_fb_platdata mini6410_lcd_pdata[] __initdata = { { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .vtiming = &mini6410_lcd_type0_timing, .win[0] = &mini6410_lcd_type0_fb_win, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, }, { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .vtiming = &mini6410_lcd_type1_timing, .win[0] = &mini6410_lcd_type1_fb_win, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, @@ -316,8 +326,8 @@ static void __init mini6410_machine_init(void) mini6410_parse_features(&features, mini6410_features_str); printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n", - mini6410_lcd_pdata[features.lcd_index].win[0]->win_mode.xres, - mini6410_lcd_pdata[features.lcd_index].win[0]->win_mode.yres); + mini6410_lcd_pdata[features.lcd_index].win[0]->xres, + mini6410_lcd_pdata[features.lcd_index].win[0]->yres); s3c_nand_set_platdata(&mini6410_nand_info); s3c_fb_set_platdata(&mini6410_lcd_pdata[features.lcd_index]); diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c index 21f91e5..0fbd32c 100644 --- a/arch/arm/mach-s3c64xx/mach-real6410.c +++ b/arch/arm/mach-s3c64xx/mach-real6410.c @@ -118,43 +118,51 @@ static struct platform_device real6410_device_eth = { }; static struct s3c_fb_pd_win real6410_lcd_type0_fb_win = { - .win_mode = { /* 4.3" 480x272 */ - .left_margin = 3, - .right_margin = 2, - .upper_margin = 1, - .lower_margin = 1, - .hsync_len = 40, - .vsync_len = 1, - .xres = 480, - .yres = 272, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 480, + .yres = 272, +}; + +static struct fb_videomode real6410_lcd_type0_timing = { + /* 4.3" 480x272 */ + .left_margin = 3, + .right_margin = 2, + .upper_margin = 1, + .lower_margin = 1, + .hsync_len = 40, + .vsync_len = 1, }; static struct s3c_fb_pd_win real6410_lcd_type1_fb_win = { - .win_mode = { /* 7.0" 800x480 */ - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 800, + .yres = 480, +}; + +static struct fb_videomode real6410_lcd_type1_timing = { + /* 7.0" 800x480 */ + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, }; static struct s3c_fb_platdata real6410_lcd_pdata[] __initdata = { { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .vtiming = &real6410_lcd_type0_timing, .win[0] = &real6410_lcd_type0_fb_win, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, }, { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .vtiming = &real6410_lcd_type1_timing, .win[0] = &real6410_lcd_type1_fb_win, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, @@ -297,8 +305,8 @@ static void __init real6410_machine_init(void) real6410_parse_features(&features, real6410_features_str); printk(KERN_INFO "REAL6410: selected LCD display is %dx%d\n", - real6410_lcd_pdata[features.lcd_index].win[0]->win_mode.xres, - real6410_lcd_pdata[features.lcd_index].win[0]->win_mode.yres); + real6410_lcd_pdata[features.lcd_index].win[0]->xres, + real6410_lcd_pdata[features.lcd_index].win[0]->yres); s3c_fb_set_platdata(&real6410_lcd_pdata[features.lcd_index]); s3c_nand_set_platdata(&real6410_nand_info); diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c index 3f42431..03a2f88 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq5.c +++ b/arch/arm/mach-s3c64xx/mach-smartq5.c @@ -108,23 +108,27 @@ static struct platform_device smartq5_buttons_device = { }; static struct s3c_fb_pd_win smartq5_fb_win0 = { - .win_mode = { - .left_margin = 216, - .right_margin = 40, - .upper_margin = 35, - .lower_margin = 10, - .hsync_len = 1, - .vsync_len = 1, - .xres = 800, - .yres = 480, - .refresh = 80, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 800, + .yres = 480, +}; + +static struct fb_videomode smartq5_lcd_timing = { + .left_margin = 216, + .right_margin = 40, + .upper_margin = 35, + .lower_margin = 10, + .hsync_len = 1, + .vsync_len = 1, + .xres = 800, + .yres = 480, + .refresh = 80, }; static struct s3c_fb_platdata smartq5_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .vtiming = &smartq5_lcd_timing, .win[0] = &smartq5_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c index e5c09b6..4e3b038 100644 --- a/arch/arm/mach-s3c64xx/mach-smartq7.c +++ b/arch/arm/mach-s3c64xx/mach-smartq7.c @@ -124,23 +124,27 @@ static struct platform_device smartq7_buttons_device = { }; static struct s3c_fb_pd_win smartq7_fb_win0 = { - .win_mode = { - .left_margin = 3, - .right_margin = 5, - .upper_margin = 1, - .lower_margin = 20, - .hsync_len = 10, - .vsync_len = 3, - .xres = 800, - .yres = 480, - .refresh = 80, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 800, + .yres = 480, +}; + +static struct fb_videomode smartq7_lcd_timing = { + .left_margin = 3, + .right_margin = 5, + .upper_margin = 1, + .lower_margin = 20, + .hsync_len = 10, + .vsync_len = 3, + .xres = 800, + .yres = 480, + .refresh = 80, }; static struct s3c_fb_platdata smartq7_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .vtiming = &smartq7_lcd_timing, .win[0] = &smartq7_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index d55bc96..3cfc90f 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -146,26 +146,29 @@ static struct platform_device smdk6410_lcd_powerdev = { }; static struct s3c_fb_pd_win smdk6410_fb_win0 = { - /* this is to ensure we use win0 */ - .win_mode = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 800, + .yres = 480, .virtual_y = 480 * 2, .virtual_x = 800, }; +static struct fb_videomode smdk6410_lcd_timing = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, +}; + /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = { .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .vtiming = &smdk6410_lcd_timing, .win[0] = &smdk6410_fb_win0, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c index a40e325..92fefad 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6440.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c @@ -103,22 +103,26 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win smdk6440_fb_win0 = { - .win_mode = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, .max_bpp = 32, .default_bpp = 24, + .xres = 800, + .yres = 480, +}; + +static struct fb_videomode smdk6440_lcd_timing = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, }; static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = { .win[0] = &smdk6440_fb_win0, + .vtiming = &smdk6440_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c index efb69e2..e2335ec 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6450.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c @@ -121,22 +121,26 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win smdk6450_fb_win0 = { - .win_mode = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, .max_bpp = 32, .default_bpp = 24, + .xres = 800, + .yres = 480, +}; + +static struct fb_videomode smdk6450_lcd_timing = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, }; static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = { .win[0] = &smdk6450_fb_win0, + .vtiming = &smdk6450_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5p64x0_fb_gpio_setup_24bpp, diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c index 674d229..0c3ae38 100644 --- a/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -136,24 +136,27 @@ static struct platform_device smdkc100_lcd_powerdev = { /* Frame Buffer */ static struct s3c_fb_pd_win smdkc100_fb_win0 = { - /* this is to ensure we use win0 */ - .win_mode = { - .left_margin = 8, - .right_margin = 13, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - .refresh = 80, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 800, + .yres = 480, +}; + +static struct fb_videomode smdkc100_lcd_timing = { + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + .refresh = 80, }; static struct s3c_fb_platdata smdkc100_lcd_pdata __initdata = { .win[0] = &smdkc100_fb_win0, + .vtiming = &smdkc100_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5pc100_fb_gpio_setup_24bpp, diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index a9ea64e..7b91bbf 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -96,38 +96,34 @@ static struct s3c2410_uartcfg aquila_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win aquila_fb_win0 = { - .win_mode = { - .left_margin = 16, - .right_margin = 16, - .upper_margin = 3, - .lower_margin = 28, - .hsync_len = 2, - .vsync_len = 2, - .xres = 480, - .yres = 800, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 480, + .yres = 800, }; static struct s3c_fb_pd_win aquila_fb_win1 = { - .win_mode = { - .left_margin = 16, - .right_margin = 16, - .upper_margin = 3, - .lower_margin = 28, - .hsync_len = 2, - .vsync_len = 2, - .xres = 480, - .yres = 800, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 480, + .yres = 800, +}; + +static struct fb_videomode aquila_lcd_timing = { + .left_margin = 16, + .right_margin = 16, + .upper_margin = 3, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 2, + .xres = 480, + .yres = 800, }; static struct s3c_fb_platdata aquila_lcd_pdata __initdata = { .win[0] = &aquila_fb_win0, .win[1] = &aquila_fb_win1, + .vtiming = &aquila_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC | VIDCON1_INV_VCLK | VIDCON1_INV_VDEN, diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index 2cf5ed7..07a840d 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -105,25 +105,29 @@ static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = { /* Frame Buffer */ static struct s3c_fb_pd_win goni_fb_win0 = { - .win_mode = { - .left_margin = 16, - .right_margin = 16, - .upper_margin = 2, - .lower_margin = 28, - .hsync_len = 2, - .vsync_len = 1, - .xres = 480, - .yres = 800, - .refresh = 55, - }, .max_bpp = 32, .default_bpp = 16, + .xres = 480, + .yres = 800, .virtual_x = 480, .virtual_y = 2 * 800, }; +static struct fb_videomode goni_lcd_timing = { + .left_margin = 16, + .right_margin = 16, + .upper_margin = 2, + .lower_margin = 28, + .hsync_len = 2, + .vsync_len = 1, + .xres = 480, + .yres = 800, + .refresh = 55, +}; + static struct s3c_fb_platdata goni_lcd_pdata __initdata = { .win[0] = &goni_fb_win0, + .vtiming = &goni_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB | VIDCON0_CLKSEL_LCD, .vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index 91d4ad8..5e0c955 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -189,22 +189,26 @@ static struct platform_device smdkv210_lcd_lte480wv = { }; static struct s3c_fb_pd_win smdkv210_fb_win0 = { - .win_mode = { - .left_margin = 13, - .right_margin = 8, - .upper_margin = 7, - .lower_margin = 5, - .hsync_len = 3, - .vsync_len = 1, - .xres = 800, - .yres = 480, - }, .max_bpp = 32, .default_bpp = 24, + .xres = 800, + .yres = 480, +}; + +static struct fb_videomode smdkv210_lcd_timing = { + .left_margin = 13, + .right_margin = 8, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, }; static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = { .win[0] = &smdkv210_fb_win0, + .vtiming = &smdkv210_lcd_timing, .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, .setup_gpio = s5pv210_fb_gpio_setup_24bpp, -- cgit v0.10.2 From 688ec344a62e85f221d7a310a1209cf9b1209fd3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 27 Mar 2012 11:15:56 +0800 Subject: video: pxa3xx-gcu: Simplify the logic to exit while loop in pxa3xx_gcu_wait_idle If wait_event_interruptible_timeout returns a positive value, it means the condition evaluated is true. Which means priv->shared->hw_running is false. And then we will exit the loop. This patch simplifies the logic to exit the while loop. Signed-off-by: Axel Lin Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c index 1d71c08..0b4ae0c 100644 --- a/drivers/video/pxa3xx-gcu.c +++ b/drivers/video/pxa3xx-gcu.c @@ -316,12 +316,9 @@ pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv) ret = wait_event_interruptible_timeout(priv->wait_idle, !priv->shared->hw_running, HZ*4); - if (ret < 0) + if (ret != 0) break; - if (ret > 0) - continue; - if (gc_readl(priv, REG_GCRBEXHR) == rbexhr && priv->shared->num_interrupts == num) { QERROR("TIMEOUT"); -- cgit v0.10.2 From 03af42c59e5fc073fa93b7fe44e80161acb22772 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 30 Mar 2012 09:46:21 -0400 Subject: nfsd: trivial: remove unused variable from nfsd4_lock ..."fp" is set but never used. Signed-off-by: Jeff Layton Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1841f8b..a822e31 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4055,7 +4055,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfs4_openowner *open_sop = NULL; struct nfs4_lockowner *lock_sop = NULL; struct nfs4_ol_stateid *lock_stp; - struct nfs4_file *fp; struct file *filp = NULL; struct file_lock file_lock; struct file_lock conflock; @@ -4123,7 +4122,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out; } lock_sop = lockowner(lock_stp->st_stateowner); - fp = lock_stp->st_file; lkflg = setlkflg(lock->lk_type); status = nfs4_check_openmode(lock_stp, lkflg); -- cgit v0.10.2 From a9aa53df6e6c768fc0f25a7c80ba586b0290720a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 29 Mar 2012 19:18:19 -0400 Subject: svcauth: remove unused define Signed-off-by: Simo Sorce diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h index 548790e..2e2af10 100644 --- a/include/linux/sunrpc/svcauth.h +++ b/include/linux/sunrpc/svcauth.h @@ -16,7 +16,6 @@ #include #include -#define SVC_CRED_NGROUPS 32 struct svc_cred { uid_t cr_uid; gid_t cr_gid; -- cgit v0.10.2 From 33dcc481eddc3f532732a9582095373fa5354369 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 10 Apr 2012 11:08:48 -0400 Subject: nfsd: don't use locks_in_grace to determine whether to call nfs4_grace_end It's possible that lockd or another lock manager might still be on the list after we call nfsd4_end_grace. If the laundromat thread runs again at that point, then we could end up calling nfsd4_end_grace more than once. That's not only inefficient, but calling nfsd4_recdir_purge_old more than once could be problematic. Fix this by adding a new global "grace_ended" flag and use that to determine whether we've already called nfsd4_grace_end. Signed-off-by: Jeff Layton Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index a822e31..277c989 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3155,10 +3155,17 @@ out: static struct lock_manager nfsd4_manager = { }; +static bool grace_ended; + static void nfsd4_end_grace(void) { + /* do nothing if grace period already ended */ + if (grace_ended) + return; + dprintk("NFSD: end of grace period\n"); + grace_ended = true; nfsd4_record_grace_done(&init_net, boot_time); locks_end_grace(&nfsd4_manager); /* @@ -3183,8 +3190,7 @@ nfs4_laundromat(void) nfs4_lock_state(); dprintk("NFSD: laundromat service - starting\n"); - if (locks_in_grace()) - nfsd4_end_grace(); + nfsd4_end_grace(); INIT_LIST_HEAD(&reaplist); spin_lock(&client_lock); list_for_each_safe(pos, next, &client_lru) { @@ -4718,6 +4724,7 @@ nfs4_state_start(void) nfsd4_client_tracking_init(&init_net); boot_time = get_seconds(); locks_start_grace(&nfsd4_manager); + grace_ended = false; printk(KERN_INFO "NFSD: starting %ld-second grace period\n", nfsd4_grace); ret = set_callback_cred(); -- cgit v0.10.2 From d4bb527e9e6c00e6e24f3475fe65db7775ff6c63 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 28 Mar 2012 19:09:01 +0400 Subject: nfsd: use passed cache_detail pointer expkey_parse() Using of hard-coded svc_expkey_cache pointer in expkey_parse() looks redundant. Moreover, global cache will be replaced with per-net instance soon. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 8e9689a..71c5ce3 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -163,7 +163,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) cache_flush(); out: if (ek) - cache_put(&ek->h, &svc_expkey_cache); + cache_put(&ek->h, cd); if (dom) auth_domain_put(dom); kfree(buf); -- cgit v0.10.2 From db3a35326362624dd4d8473e676d63afa52bedcc Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 28 Mar 2012 19:09:08 +0400 Subject: nfsd: add link to owner cache detail to svc_export structure Without info about owner cache datail it won't be able to find out, which per-net cache detail have to be. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 71c5ce3..99ea4c0 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -525,6 +525,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) goto out1; exp.ex_client = dom; + exp.cd = cd; /* expiry */ err = -EINVAL; @@ -672,6 +673,7 @@ static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) new->ex_fslocs.locations = NULL; new->ex_fslocs.locations_count = 0; new->ex_fslocs.migrated = 0; + new->cd = item->cd; } static void export_update(struct cache_head *cnew, struct cache_head *citem) @@ -739,8 +741,7 @@ svc_export_lookup(struct svc_export *exp) struct cache_head *ch; int hash = svc_export_hash(exp); - ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h, - hash); + ch = sunrpc_cache_lookup(exp->cd, &exp->h, hash); if (ch) return container_of(ch, struct svc_export, h); else @@ -753,9 +754,7 @@ svc_export_update(struct svc_export *new, struct svc_export *old) struct cache_head *ch; int hash = svc_export_hash(old); - ch = sunrpc_cache_update(&svc_export_cache, &new->h, - &old->h, - hash); + ch = sunrpc_cache_update(old->cd, &new->h, &old->h, hash); if (ch) return container_of(ch, struct svc_export, h); else @@ -797,6 +796,7 @@ static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, key.ex_client = clp; key.ex_path = *path; + key.cd = &svc_export_cache; exp = svc_export_lookup(&key); if (exp == NULL) diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index f85308e..6445529 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -103,6 +103,7 @@ struct svc_export { struct nfsd4_fs_locations ex_fslocs; int ex_nflavors; struct exp_flavor_info ex_flavors[MAX_SECINFO_LIST]; + struct cache_detail *cd; }; /* an "export key" (expkey) maps a filehandlefragement to an -- cgit v0.10.2 From 71234978e81ee515c8025d087a197561b311c183 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 28 Mar 2012 19:09:15 +0400 Subject: nfsd: use cache detail pointer from svc_export structure on cache put Hard-coded pointer is redundant now and can be replaced. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 6445529..485c2af 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -147,7 +147,7 @@ extern struct cache_detail svc_export_cache; static inline void exp_put(struct svc_export *exp) { - cache_put(&exp->h, &svc_export_cache); + cache_put(&exp->h, exp->cd); } static inline void exp_get(struct svc_export *exp) -- cgit v0.10.2 From a09581f29434ae67f8fc6ae487e4f30a7f0d019f Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 28 Mar 2012 19:09:22 +0400 Subject: nfsd: use exp_put() for svc_export_cache put This patch replaces cache_put() call for svc_export_cache by exp_put() call. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 99ea4c0..c20a405 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -1205,7 +1205,7 @@ static int e_show(struct seq_file *m, void *p) cache_get(&exp->h); if (cache_check(&svc_export_cache, &exp->h, NULL)) return 0; - cache_put(&exp->h, &svc_export_cache); + exp_put(exp); return svc_export_show(m, &svc_export_cache, cp); } diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 68454e7..cc79300 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -636,7 +636,7 @@ fh_put(struct svc_fh *fhp) #endif } if (exp) { - cache_put(&exp->h, &svc_export_cache); + exp_put(exp); fhp->fh_export = NULL; } return; -- cgit v0.10.2 From f2c7ea10f901b7648eb61f1da7243588351f1dac Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 28 Mar 2012 19:09:29 +0400 Subject: nfsd: pass svc_export_cache pointer as private data to "exports" seq file ops Global svc_export_cache cache is going to be replaced with per-net instance. So prepare the ground for it. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index c20a405..1495320 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -1029,13 +1029,14 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp) /* Iterator */ static void *e_start(struct seq_file *m, loff_t *pos) - __acquires(svc_export_cache.hash_lock) + __acquires(((struct cache_detail *)m->private)->hash_lock) { loff_t n = *pos; unsigned hash, export; struct cache_head *ch; - - read_lock(&svc_export_cache.hash_lock); + struct cache_detail *cd = m->private; + + read_lock(&cd->hash_lock); if (!n--) return SEQ_START_TOKEN; hash = n >> 32; @@ -1082,9 +1083,11 @@ static void *e_next(struct seq_file *m, void *p, loff_t *pos) } static void e_stop(struct seq_file *m, void *p) - __releases(svc_export_cache.hash_lock) + __releases(((struct cache_detail *)m->private)->hash_lock) { - read_unlock(&svc_export_cache.hash_lock); + struct cache_detail *cd = m->private; + + read_unlock(&cd->hash_lock); } static struct flags { @@ -1195,6 +1198,7 @@ static int e_show(struct seq_file *m, void *p) { struct cache_head *cp = p; struct svc_export *exp = container_of(cp, struct svc_export, h); + struct cache_detail *cd = m->private; if (p == SEQ_START_TOKEN) { seq_puts(m, "# Version 1.1\n"); @@ -1203,10 +1207,10 @@ static int e_show(struct seq_file *m, void *p) } cache_get(&exp->h); - if (cache_check(&svc_export_cache, &exp->h, NULL)) + if (cache_check(cd, &exp->h, NULL)) return 0; exp_put(exp); - return svc_export_show(m, &svc_export_cache, cp); + return svc_export_show(m, cd, cp); } const struct seq_operations nfs_exports_op = { diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 2c53be6..ae19293 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -127,7 +127,16 @@ static const struct file_operations transaction_ops = { static int exports_open(struct inode *inode, struct file *file) { - return seq_open(file, &nfs_exports_op); + int err; + struct seq_file *seq; + + err = seq_open(file, &nfs_exports_op); + if (err) + return err; + + seq = file->private_data; + seq->private = &svc_export_cache; + return 0; } static const struct file_operations exports_operations = { -- cgit v0.10.2 From 83e0ed700d4d2cad2f555ae536fafd531f55b6d0 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 28 Mar 2012 19:09:35 +0400 Subject: nfsd: use hash table from cache detail in nfsd export seq ops Hard-code is redundant and will prevent from making caches per net ns. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 1495320..9fe7156 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -1035,6 +1035,7 @@ static void *e_start(struct seq_file *m, loff_t *pos) unsigned hash, export; struct cache_head *ch; struct cache_detail *cd = m->private; + struct cache_head **export_table = cd->hash_table; read_lock(&cd->hash_lock); if (!n--) @@ -1061,6 +1062,8 @@ static void *e_next(struct seq_file *m, void *p, loff_t *pos) { struct cache_head *ch = p; int hash = (*pos >> 32); + struct cache_detail *cd = m->private; + struct cache_head **export_table = cd->hash_table; if (p == SEQ_START_TOKEN) hash = 0; -- cgit v0.10.2 From c89172e36e3d3972f9f3fa107c1f3e666f1e05cf Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 28 Mar 2012 19:09:50 +0400 Subject: nfsd: pass pointer to expkey cache down to stack wherever possible. This cache will be per-net soon. And it's easier to get the pointer to desired per-net instance only once and then pass it down instead of discovering it in every place were required. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 9fe7156..84723bc 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -71,9 +71,9 @@ static int expkey_upcall(struct cache_detail *cd, struct cache_head *h) return sunrpc_cache_pipe_upcall(cd, h, expkey_request); } -static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old); -static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *); -static struct cache_detail svc_expkey_cache; +static struct svc_expkey *svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new, + struct svc_expkey *old); +static struct svc_expkey *svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *); static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) { @@ -131,7 +131,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) key.ek_fsidtype = fsidtype; memcpy(key.ek_fsid, buf, len); - ek = svc_expkey_lookup(&key); + ek = svc_expkey_lookup(cd, &key); err = -ENOMEM; if (!ek) goto out; @@ -145,7 +145,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) err = 0; if (len == 0) { set_bit(CACHE_NEGATIVE, &key.h.flags); - ek = svc_expkey_update(&key, ek); + ek = svc_expkey_update(cd, &key, ek); if (!ek) err = -ENOMEM; } else { @@ -155,7 +155,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) dprintk("Found the path %s\n", buf); - ek = svc_expkey_update(&key, ek); + ek = svc_expkey_update(cd, &key, ek); if (!ek) err = -ENOMEM; path_put(&key.ek_path); @@ -268,13 +268,12 @@ svc_expkey_hash(struct svc_expkey *item) } static struct svc_expkey * -svc_expkey_lookup(struct svc_expkey *item) +svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *item) { struct cache_head *ch; int hash = svc_expkey_hash(item); - ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h, - hash); + ch = sunrpc_cache_lookup(cd, &item->h, hash); if (ch) return container_of(ch, struct svc_expkey, h); else @@ -282,13 +281,13 @@ svc_expkey_lookup(struct svc_expkey *item) } static struct svc_expkey * -svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) +svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new, + struct svc_expkey *old) { struct cache_head *ch; int hash = svc_expkey_hash(new); - ch = sunrpc_cache_update(&svc_expkey_cache, &new->h, - &old->h, hash); + ch = sunrpc_cache_update(cd, &new->h, &old->h, hash); if (ch) return container_of(ch, struct svc_expkey, h); else @@ -763,7 +762,8 @@ svc_export_update(struct svc_export *new, struct svc_export *old) static struct svc_expkey * -exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) +exp_find_key(struct cache_detail *cd, svc_client *clp, int fsid_type, + u32 *fsidv, struct cache_req *reqp) { struct svc_expkey key, *ek; int err; @@ -775,10 +775,10 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) key.ek_fsidtype = fsid_type; memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); - ek = svc_expkey_lookup(&key); + ek = svc_expkey_lookup(cd, &key); if (ek == NULL) return ERR_PTR(-ENOMEM); - err = cache_check(&svc_expkey_cache, &ek->h, reqp); + err = cache_check(cd, &ek->h, reqp); if (err) return ERR_PTR(err); return ek; @@ -879,7 +879,7 @@ static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) { struct svc_export *exp; - struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); + struct svc_expkey *ek = exp_find_key(&svc_expkey_cache, clp, fsid_type, fsidv, reqp); if (IS_ERR(ek)) return ERR_CAST(ek); -- cgit v0.10.2 From f890edbbeff6928b7db0c6179a9036cbd4f0efbf Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Thu, 29 Mar 2012 19:34:16 +0400 Subject: NFSd: remove hard-coded dereferences to name-to-id and id-to-name caches These dereferences to global static caches are redundant. They also prevents converting these caches into per-net ones. So this patch is cleanup + precursor of patch set,a which will make them per-net. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 322d11c..2ff4470 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -183,8 +183,9 @@ warn_no_idmapd(struct cache_detail *detail, int has_died) static int idtoname_parse(struct cache_detail *, char *, int); -static struct ent *idtoname_lookup(struct ent *); -static struct ent *idtoname_update(struct ent *, struct ent *); +static struct ent *idtoname_lookup(struct cache_detail *, struct ent *); +static struct ent *idtoname_update(struct cache_detail *, struct ent *, + struct ent *); static struct cache_detail idtoname_cache = { .owner = THIS_MODULE, @@ -244,7 +245,7 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) goto out; error = -ENOMEM; - res = idtoname_lookup(&ent); + res = idtoname_lookup(cd, &ent); if (!res) goto out; @@ -260,11 +261,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) else memcpy(ent.name, buf1, sizeof(ent.name)); error = -ENOMEM; - res = idtoname_update(&ent, res); + res = idtoname_update(cd, &ent, res); if (res == NULL) goto out; - cache_put(&res->h, &idtoname_cache); + cache_put(&res->h, cd); error = 0; out: @@ -275,10 +276,9 @@ out: static struct ent * -idtoname_lookup(struct ent *item) +idtoname_lookup(struct cache_detail *cd, struct ent *item) { - struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache, - &item->h, + struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h, idtoname_hash(item)); if (ch) return container_of(ch, struct ent, h); @@ -287,10 +287,9 @@ idtoname_lookup(struct ent *item) } static struct ent * -idtoname_update(struct ent *new, struct ent *old) +idtoname_update(struct cache_detail *cd, struct ent *new, struct ent *old) { - struct cache_head *ch = sunrpc_cache_update(&idtoname_cache, - &new->h, &old->h, + struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h, idtoname_hash(new)); if (ch) return container_of(ch, struct ent, h); @@ -359,8 +358,9 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h) return 0; } -static struct ent *nametoid_lookup(struct ent *); -static struct ent *nametoid_update(struct ent *, struct ent *); +static struct ent *nametoid_lookup(struct cache_detail *, struct ent *); +static struct ent *nametoid_update(struct cache_detail *, struct ent *, + struct ent *); static int nametoid_parse(struct cache_detail *, char *, int); static struct cache_detail nametoid_cache = { @@ -426,14 +426,14 @@ nametoid_parse(struct cache_detail *cd, char *buf, int buflen) set_bit(CACHE_NEGATIVE, &ent.h.flags); error = -ENOMEM; - res = nametoid_lookup(&ent); + res = nametoid_lookup(cd, &ent); if (res == NULL) goto out; - res = nametoid_update(&ent, res); + res = nametoid_update(cd, &ent, res); if (res == NULL) goto out; - cache_put(&res->h, &nametoid_cache); + cache_put(&res->h, cd); error = 0; out: kfree(buf1); @@ -443,10 +443,9 @@ out: static struct ent * -nametoid_lookup(struct ent *item) +nametoid_lookup(struct cache_detail *cd, struct ent *item) { - struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache, - &item->h, + struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h, nametoid_hash(item)); if (ch) return container_of(ch, struct ent, h); @@ -455,10 +454,9 @@ nametoid_lookup(struct ent *item) } static struct ent * -nametoid_update(struct ent *new, struct ent *old) +nametoid_update(struct cache_detail *cd, struct ent *new, struct ent *old) { - struct cache_head *ch = sunrpc_cache_update(&nametoid_cache, - &new->h, &old->h, + struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h, nametoid_hash(new)); if (ch) return container_of(ch, struct ent, h); @@ -493,12 +491,12 @@ nfsd_idmap_shutdown(void) static int idmap_lookup(struct svc_rqst *rqstp, - struct ent *(*lookup_fn)(struct ent *), struct ent *key, - struct cache_detail *detail, struct ent **item) + struct ent *(*lookup_fn)(struct cache_detail *, struct ent *), + struct ent *key, struct cache_detail *detail, struct ent **item) { int ret; - *item = lookup_fn(key); + *item = lookup_fn(detail, key); if (!*item) return -ENOMEM; retry: @@ -506,7 +504,7 @@ idmap_lookup(struct svc_rqst *rqstp, if (ret == -ETIMEDOUT) { struct ent *prev_item = *item; - *item = lookup_fn(key); + *item = lookup_fn(detail, key); if (*item != prev_item) goto retry; cache_put(&(*item)->h, detail); -- cgit v0.10.2 From e3f70eadb7dddfb5a2bb9afff7abfc6ee17a29d0 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Thu, 29 Mar 2012 18:54:33 +0400 Subject: Lockd: pass network namespace to creation and destruction routines v2: dereference of most probably already released nlm_host removed in nlmclnt_done() and reclaimer(). These routines are called from locks reclaimer() kernel thread. This thread works in "init_net" network context and currently relays on persence on lockd thread and it's per-net resources. Thus lockd_up() and lockd_down() can't relay on current network context. So let's pass corrent one into them. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index ba1dc2e..ca0a080 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -56,7 +56,7 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init) u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; int status; - status = lockd_up(); + status = lockd_up(nlm_init->net); if (status < 0) return ERR_PTR(status); @@ -65,7 +65,7 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init) nlm_init->hostname, nlm_init->noresvport, nlm_init->net); if (host == NULL) { - lockd_down(); + lockd_down(nlm_init->net); return ERR_PTR(-ENOLCK); } @@ -80,8 +80,10 @@ EXPORT_SYMBOL_GPL(nlmclnt_init); */ void nlmclnt_done(struct nlm_host *host) { + struct net *net = host->net; + nlmclnt_release_host(host); - lockd_down(); + lockd_down(net); } EXPORT_SYMBOL_GPL(nlmclnt_done); @@ -220,11 +222,12 @@ reclaimer(void *ptr) struct nlm_wait *block; struct file_lock *fl, *next; u32 nsmstate; + struct net *net = host->net; allow_signal(SIGKILL); down_write(&host->h_rwsem); - lockd_up(); /* note: this cannot fail as lockd is already running */ + lockd_up(net); /* note: this cannot fail as lockd is already running */ dprintk("lockd: reclaiming locks for host %s\n", host->h_name); @@ -275,6 +278,6 @@ restart: /* Release host handle after use */ nlmclnt_release_host(host); - lockd_down(); + lockd_down(net); return 0; } diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index f49b9af..1ead075 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -295,11 +295,10 @@ static void lockd_down_net(struct net *net) /* * Bring up the lockd process if it's not already up. */ -int lockd_up(void) +int lockd_up(struct net *net) { struct svc_serv *serv; int error = 0; - struct net *net = current->nsproxy->net_ns; mutex_lock(&nlmsvc_mutex); /* @@ -378,12 +377,12 @@ EXPORT_SYMBOL_GPL(lockd_up); * Decrement the user count and bring down lockd if we're the last. */ void -lockd_down(void) +lockd_down(struct net *net) { mutex_lock(&nlmsvc_mutex); if (nlmsvc_users) { if (--nlmsvc_users) { - lockd_down_net(current->nsproxy->net_ns); + lockd_down_net(net); goto out; } } else { diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 28dfad3..78e5213 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -220,7 +220,7 @@ static int nfsd_startup(unsigned short port, int nrservs) ret = nfsd_init_socks(port); if (ret) goto out_racache; - ret = lockd_up(); + ret = lockd_up(&init_net); if (ret) goto out_racache; ret = nfs4_state_start(); @@ -229,7 +229,7 @@ static int nfsd_startup(unsigned short port, int nrservs) nfsd_up = true; return 0; out_lockd: - lockd_down(); + lockd_down(&init_net); out_racache: nfsd_racache_shutdown(); return ret; @@ -246,7 +246,7 @@ static void nfsd_shutdown(void) if (!nfsd_up) return; nfs4_state_shutdown(); - lockd_down(); + lockd_down(&init_net); nfsd_racache_shutdown(); nfsd_up = false; } diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h index 11a966e..4d24d64 100644 --- a/include/linux/lockd/bind.h +++ b/include/linux/lockd/bind.h @@ -54,7 +54,7 @@ extern void nlmclnt_done(struct nlm_host *host); extern int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl); -extern int lockd_up(void); -extern void lockd_down(void); +extern int lockd_up(struct net *net); +extern void lockd_down(struct net *net); #endif /* LINUX_LOCKD_BIND_H */ -- cgit v0.10.2 From b89109bef4a6a4a8ab5788778ee0addca0787870 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 11 Apr 2012 15:13:14 +0400 Subject: nfsd: pass network context to export caches init/shutdown routines These functions will be called from per-net operations. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 84723bc..6453669 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -1228,17 +1228,17 @@ const struct seq_operations nfs_exports_op = { * Initialize the exports module. */ int -nfsd_export_init(void) +nfsd_export_init(struct net *net) { int rv; - dprintk("nfsd: initializing export module.\n"); + dprintk("nfsd: initializing export module (net: %p).\n", net); - rv = cache_register_net(&svc_export_cache, &init_net); + rv = cache_register_net(&svc_export_cache, net); if (rv) return rv; - rv = cache_register_net(&svc_expkey_cache, &init_net); + rv = cache_register_net(&svc_expkey_cache, net); if (rv) - cache_unregister_net(&svc_export_cache, &init_net); + cache_unregister_net(&svc_export_cache, net); return rv; } @@ -1257,14 +1257,14 @@ nfsd_export_flush(void) * Shutdown the exports module. */ void -nfsd_export_shutdown(void) +nfsd_export_shutdown(struct net *net) { - dprintk("nfsd: shutting down export module.\n"); + dprintk("nfsd: shutting down export module (net: %p).\n", net); - cache_unregister_net(&svc_expkey_cache, &init_net); - cache_unregister_net(&svc_export_cache, &init_net); + cache_unregister_net(&svc_expkey_cache, net); + cache_unregister_net(&svc_export_cache, net); svcauth_unix_purge(); - dprintk("nfsd: export shutdown complete.\n"); + dprintk("nfsd: export shutdown complete (net: %p).\n", net); } diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index ae19293..bc76f8e 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1163,7 +1163,7 @@ static int __init init_nfsd(void) retval = nfsd_reply_cache_init(); if (retval) goto out_free_stat; - retval = nfsd_export_init(); + retval = nfsd_export_init(&init_net); if (retval) goto out_free_cache; nfsd_lockd_init(); /* lockd->nfsd callbacks */ @@ -1184,7 +1184,7 @@ out_free_idmap: nfsd_idmap_shutdown(); out_free_lockd: nfsd_lockd_shutdown(); - nfsd_export_shutdown(); + nfsd_export_shutdown(&init_net); out_free_cache: nfsd_reply_cache_shutdown(); out_free_stat: @@ -1201,7 +1201,7 @@ out_unregister_notifier: static void __exit exit_nfsd(void) { - nfsd_export_shutdown(); + nfsd_export_shutdown(&init_net); nfsd_reply_cache_shutdown(); remove_proc_entry("fs/nfs/exports", NULL); remove_proc_entry("fs/nfs", NULL); diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 485c2af..375096c 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -130,8 +130,8 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp); /* * Function declarations */ -int nfsd_export_init(void); -void nfsd_export_shutdown(void); +int nfsd_export_init(struct net *); +void nfsd_export_shutdown(struct net *); void nfsd_export_flush(void); struct svc_export * rqst_exp_get_by_name(struct svc_rqst *, struct path *); -- cgit v0.10.2 From 2a75cfa64e63502e54e40f99ba07411544bd3190 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 28 Mar 2012 19:09:42 +0400 Subject: nfsd: pass pointer to export cache down to stack wherever possible. This cache will be per-net soon. And it's easier to get the pointer to desired per-net instance only once and then pass it down instead of discovering it in every place were required. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 6453669..688264b 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -785,8 +785,8 @@ exp_find_key(struct cache_detail *cd, svc_client *clp, int fsid_type, } -static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, - struct cache_req *reqp) +static svc_export *exp_get_by_name(struct cache_detail *cd, svc_client *clp, + const struct path *path, struct cache_req *reqp) { struct svc_export *exp, key; int err; @@ -796,12 +796,12 @@ static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, key.ex_client = clp; key.ex_path = *path; - key.cd = &svc_export_cache; + key.cd = cd; exp = svc_export_lookup(&key); if (exp == NULL) return ERR_PTR(-ENOMEM); - err = cache_check(&svc_export_cache, &exp->h, reqp); + err = cache_check(cd, &exp->h, reqp); if (err) return ERR_PTR(err); return exp; @@ -810,16 +810,17 @@ static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, /* * Find the export entry for a given dentry. */ -static struct svc_export *exp_parent(svc_client *clp, struct path *path) +static struct svc_export *exp_parent(struct cache_detail *cd, svc_client *clp, + struct path *path) { struct dentry *saved = dget(path->dentry); - svc_export *exp = exp_get_by_name(clp, path, NULL); + svc_export *exp = exp_get_by_name(cd, clp, path, NULL); while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) { struct dentry *parent = dget_parent(path->dentry); dput(path->dentry); path->dentry = parent; - exp = exp_get_by_name(clp, path, NULL); + exp = exp_get_by_name(cd, clp, path, NULL); } dput(path->dentry); path->dentry = saved; @@ -834,13 +835,15 @@ static struct svc_export *exp_parent(svc_client *clp, struct path *path) * since its harder to fool a kernel module than a user space program. */ int -exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize) +exp_rootfh(svc_client *clp, char *name, + struct knfsd_fh *f, int maxsize) { struct svc_export *exp; struct path path; struct inode *inode; struct svc_fh fh; int err; + struct cache_detail *cd = &svc_export_cache; err = -EPERM; /* NB: we probably ought to check that it's NUL-terminated */ @@ -853,7 +856,7 @@ exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize) dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", name, path.dentry, clp->name, inode->i_sb->s_id, inode->i_ino); - exp = exp_parent(clp, &path); + exp = exp_parent(cd, clp, &path); if (IS_ERR(exp)) { err = PTR_ERR(exp); goto out; @@ -875,7 +878,8 @@ out: return err; } -static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type, +static struct svc_export *exp_find(struct cache_detail *cd, + struct auth_domain *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) { struct svc_export *exp; @@ -883,7 +887,7 @@ static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type, if (IS_ERR(ek)) return ERR_CAST(ek); - exp = exp_get_by_name(clp, &ek->ek_path, reqp); + exp = exp_get_by_name(cd, clp, &ek->ek_path, reqp); cache_put(&ek->h, &svc_expkey_cache); if (IS_ERR(exp)) @@ -926,12 +930,13 @@ struct svc_export * rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) { struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); + struct cache_detail *cd = &svc_export_cache; if (rqstp->rq_client == NULL) goto gss; /* First try the auth_unix client: */ - exp = exp_get_by_name(rqstp->rq_client, path, &rqstp->rq_chandle); + exp = exp_get_by_name(cd, rqstp->rq_client, path, &rqstp->rq_chandle); if (PTR_ERR(exp) == -ENOENT) goto gss; if (IS_ERR(exp)) @@ -943,7 +948,7 @@ gss: /* Otherwise, try falling back on gss client */ if (rqstp->rq_gssclient == NULL) return exp; - gssexp = exp_get_by_name(rqstp->rq_gssclient, path, &rqstp->rq_chandle); + gssexp = exp_get_by_name(cd, rqstp->rq_gssclient, path, &rqstp->rq_chandle); if (PTR_ERR(gssexp) == -ENOENT) return exp; if (!IS_ERR(exp)) @@ -955,12 +960,14 @@ struct svc_export * rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) { struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); + struct cache_detail *cd = &svc_export_cache; if (rqstp->rq_client == NULL) goto gss; /* First try the auth_unix client: */ - exp = exp_find(rqstp->rq_client, fsid_type, fsidv, &rqstp->rq_chandle); + exp = exp_find(cd, rqstp->rq_client, fsid_type, + fsidv, &rqstp->rq_chandle); if (PTR_ERR(exp) == -ENOENT) goto gss; if (IS_ERR(exp)) @@ -972,7 +979,7 @@ gss: /* Otherwise, try falling back on gss client */ if (rqstp->rq_gssclient == NULL) return exp; - gssexp = exp_find(rqstp->rq_gssclient, fsid_type, fsidv, + gssexp = exp_find(cd, rqstp->rq_gssclient, fsid_type, fsidv, &rqstp->rq_chandle); if (PTR_ERR(gssexp) == -ENOENT) return exp; -- cgit v0.10.2 From b3853e0ea1f2ef58f7e7c03e47819e2ae3766dea Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 11 Apr 2012 15:13:21 +0400 Subject: nfsd: make export cache allocated per network namespace context This patch also changes prototypes of nfsd_export_flush() and exp_rootfh(): network namespace parameter added. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 688264b..84d020f 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -15,11 +15,13 @@ #include #include #include +#include #include #include "nfsd.h" #include "nfsfh.h" +#include "netns.h" #define NFSDDBG_FACILITY NFSDDBG_EXPORT @@ -298,8 +300,6 @@ svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new, #define EXPORT_HASHBITS 8 #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) -static struct cache_head *export_table[EXPORT_HASHMAX]; - static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc) { int i; @@ -708,10 +708,9 @@ static struct cache_head *svc_export_alloc(void) return NULL; } -struct cache_detail svc_export_cache = { +struct cache_detail svc_export_cache_template = { .owner = THIS_MODULE, .hash_size = EXPORT_HASHMAX, - .hash_table = export_table, .name = "nfsd.export", .cache_put = svc_export_put, .cache_upcall = svc_export_upcall, @@ -835,7 +834,7 @@ static struct svc_export *exp_parent(struct cache_detail *cd, svc_client *clp, * since its harder to fool a kernel module than a user space program. */ int -exp_rootfh(svc_client *clp, char *name, +exp_rootfh(struct net *net, svc_client *clp, char *name, struct knfsd_fh *f, int maxsize) { struct svc_export *exp; @@ -843,7 +842,8 @@ exp_rootfh(svc_client *clp, char *name, struct inode *inode; struct svc_fh fh; int err; - struct cache_detail *cd = &svc_export_cache; + struct nfsd_net *nn = net_generic(net, nfsd_net_id); + struct cache_detail *cd = nn->svc_export_cache; err = -EPERM; /* NB: we probably ought to check that it's NUL-terminated */ @@ -930,7 +930,8 @@ struct svc_export * rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) { struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); - struct cache_detail *cd = &svc_export_cache; + struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); + struct cache_detail *cd = nn->svc_export_cache; if (rqstp->rq_client == NULL) goto gss; @@ -960,7 +961,8 @@ struct svc_export * rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) { struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); - struct cache_detail *cd = &svc_export_cache; + struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); + struct cache_detail *cd = nn->svc_export_cache; if (rqstp->rq_client == NULL) goto gss; @@ -1238,26 +1240,39 @@ int nfsd_export_init(struct net *net) { int rv; + struct nfsd_net *nn = net_generic(net, nfsd_net_id); + dprintk("nfsd: initializing export module (net: %p).\n", net); - rv = cache_register_net(&svc_export_cache, net); + nn->svc_export_cache = cache_create_net(&svc_export_cache_template, net); + if (IS_ERR(nn->svc_export_cache)) + return PTR_ERR(nn->svc_export_cache); + rv = cache_register_net(nn->svc_export_cache, net); if (rv) - return rv; + goto destroy_export_cache; + rv = cache_register_net(&svc_expkey_cache, net); if (rv) - cache_unregister_net(&svc_export_cache, net); - return rv; + goto unregister_export_cache; + return 0; +unregister_export_cache: + cache_unregister_net(nn->svc_export_cache, net); +destroy_export_cache: + cache_destroy_net(nn->svc_export_cache, net); + return rv; } /* * Flush exports table - called when last nfsd thread is killed */ void -nfsd_export_flush(void) +nfsd_export_flush(struct net *net) { + struct nfsd_net *nn = net_generic(net, nfsd_net_id); + cache_purge(&svc_expkey_cache); - cache_purge(&svc_export_cache); + cache_purge(nn->svc_export_cache); } /* @@ -1266,11 +1281,13 @@ nfsd_export_flush(void) void nfsd_export_shutdown(struct net *net) { + struct nfsd_net *nn = net_generic(net, nfsd_net_id); dprintk("nfsd: shutting down export module (net: %p).\n", net); cache_unregister_net(&svc_expkey_cache, net); - cache_unregister_net(&svc_export_cache, net); + cache_unregister_net(nn->svc_export_cache, net); + cache_destroy_net(nn->svc_export_cache, net); svcauth_unix_purge(); dprintk("nfsd: export shutdown complete (net: %p).\n", net); diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 12e0cff..c1c6242 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -28,6 +28,8 @@ struct cld_net; struct nfsd_net { struct cld_net *cld_net; + + struct cache_detail *svc_export_cache; }; extern int nfsd_net_id; diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index bc76f8e..ddb9f87 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -354,7 +354,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size) if (!dom) return -ENOMEM; - len = exp_rootfh(dom, path, &fh, maxsize); + len = exp_rootfh(&init_net, dom, path, &fh, maxsize); auth_domain_put(dom); if (len) return len; diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 78e5213..cb4d51d 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -261,7 +261,7 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net) printk(KERN_WARNING "nfsd: last server has exited, flushing export " "cache\n"); - nfsd_export_flush(); + nfsd_export_flush(net); } void nfsd_reset_versions(void) diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 375096c..565c212 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -132,13 +132,13 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp); */ int nfsd_export_init(struct net *); void nfsd_export_shutdown(struct net *); -void nfsd_export_flush(void); +void nfsd_export_flush(struct net *); struct svc_export * rqst_exp_get_by_name(struct svc_rqst *, struct path *); struct svc_export * rqst_exp_parent(struct svc_rqst *, struct path *); struct svc_export * rqst_find_fsidzero_export(struct svc_rqst *); -int exp_rootfh(struct auth_domain *, +int exp_rootfh(struct net *, struct auth_domain *, char *path, struct knfsd_fh *, int maxsize); __be32 exp_pseudoroot(struct svc_rqst *, struct svc_fh *); __be32 nfserrno(int errno); -- cgit v0.10.2 From e5f06f720eff24e32f1cc08ec03bcc8c4b2d2934 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 11 Apr 2012 15:13:28 +0400 Subject: nfsd: make expkey cache allocated per network namespace context This patch also changes svcauth_unix_purge() function: added network namespace as a parameter and thus loop over all networks was replaced by only one call for ip map cache purge. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 84d020f..dcb52b8 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -40,7 +40,6 @@ typedef struct svc_export svc_export; #define EXPKEY_HASHBITS 8 #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) -static struct cache_head *expkey_table[EXPKEY_HASHMAX]; static void expkey_put(struct kref *ref) { @@ -241,10 +240,9 @@ static struct cache_head *expkey_alloc(void) return NULL; } -static struct cache_detail svc_expkey_cache = { +static struct cache_detail svc_expkey_cache_template = { .owner = THIS_MODULE, .hash_size = EXPKEY_HASHMAX, - .hash_table = expkey_table, .name = "nfsd.fh", .cache_put = expkey_put, .cache_upcall = expkey_upcall, @@ -883,12 +881,13 @@ static struct svc_export *exp_find(struct cache_detail *cd, u32 *fsidv, struct cache_req *reqp) { struct svc_export *exp; - struct svc_expkey *ek = exp_find_key(&svc_expkey_cache, clp, fsid_type, fsidv, reqp); + struct nfsd_net *nn = net_generic(cd->net, nfsd_net_id); + struct svc_expkey *ek = exp_find_key(nn->svc_expkey_cache, clp, fsid_type, fsidv, reqp); if (IS_ERR(ek)) return ERR_CAST(ek); exp = exp_get_by_name(cd, clp, &ek->ek_path, reqp); - cache_put(&ek->h, &svc_expkey_cache); + cache_put(&ek->h, nn->svc_expkey_cache); if (IS_ERR(exp)) return ERR_CAST(exp); @@ -1232,7 +1231,6 @@ const struct seq_operations nfs_exports_op = { .show = e_show, }; - /* * Initialize the exports module. */ @@ -1251,11 +1249,18 @@ nfsd_export_init(struct net *net) if (rv) goto destroy_export_cache; - rv = cache_register_net(&svc_expkey_cache, net); - if (rv) + nn->svc_expkey_cache = cache_create_net(&svc_expkey_cache_template, net); + if (IS_ERR(nn->svc_expkey_cache)) { + rv = PTR_ERR(nn->svc_expkey_cache); goto unregister_export_cache; + } + rv = cache_register_net(nn->svc_expkey_cache, net); + if (rv) + goto destroy_expkey_cache; return 0; +destroy_expkey_cache: + cache_destroy_net(nn->svc_expkey_cache, net); unregister_export_cache: cache_unregister_net(nn->svc_export_cache, net); destroy_export_cache: @@ -1271,7 +1276,7 @@ nfsd_export_flush(struct net *net) { struct nfsd_net *nn = net_generic(net, nfsd_net_id); - cache_purge(&svc_expkey_cache); + cache_purge(nn->svc_expkey_cache); cache_purge(nn->svc_export_cache); } @@ -1285,10 +1290,11 @@ nfsd_export_shutdown(struct net *net) dprintk("nfsd: shutting down export module (net: %p).\n", net); - cache_unregister_net(&svc_expkey_cache, net); + cache_unregister_net(nn->svc_expkey_cache, net); cache_unregister_net(nn->svc_export_cache, net); + cache_destroy_net(nn->svc_expkey_cache, net); cache_destroy_net(nn->svc_export_cache, net); - svcauth_unix_purge(); + svcauth_unix_purge(net); dprintk("nfsd: export shutdown complete (net: %p).\n", net); } diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index c1c6242..9794c6c 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -29,6 +29,7 @@ struct cld_net; struct nfsd_net { struct cld_net *cld_net; + struct cache_detail *svc_expkey_cache; struct cache_detail *svc_export_cache; }; diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index ddb9f87..b144177 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -129,13 +129,14 @@ static int exports_open(struct inode *inode, struct file *file) { int err; struct seq_file *seq; + struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); err = seq_open(file, &nfs_exports_op); if (err) return err; seq = file->private_data; - seq->private = &svc_export_cache; + seq->private = nn->svc_export_cache; return 0; } diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 565c212..e33f747 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -143,8 +143,6 @@ int exp_rootfh(struct net *, struct auth_domain *, __be32 exp_pseudoroot(struct svc_rqst *, struct svc_fh *); __be32 nfserrno(int errno); -extern struct cache_detail svc_export_cache; - static inline void exp_put(struct svc_export *exp) { cache_put(&exp->h, exp->cd); diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h index 2e2af10..2c54683 100644 --- a/include/linux/sunrpc/svcauth.h +++ b/include/linux/sunrpc/svcauth.h @@ -130,7 +130,7 @@ extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *ne extern struct auth_domain *auth_domain_find(char *name); extern struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr); extern int auth_unix_forget_old(struct auth_domain *dom); -extern void svcauth_unix_purge(void); +extern void svcauth_unix_purge(struct net *net); extern void svcauth_unix_info_release(struct svc_xprt *xpt); extern int svcauth_unix_set_client(struct svc_rqst *rqstp); diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 521d8f7..9c3b9f0 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -346,17 +346,12 @@ static inline int ip_map_update(struct net *net, struct ip_map *ipm, return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); } - -void svcauth_unix_purge(void) +void svcauth_unix_purge(struct net *net) { - struct net *net; - - for_each_net(net) { - struct sunrpc_net *sn; + struct sunrpc_net *sn; - sn = net_generic(net, sunrpc_net_id); - cache_purge(sn->ip_map_cache); - } + sn = net_generic(net, sunrpc_net_id); + cache_purge(sn->ip_map_cache); } EXPORT_SYMBOL_GPL(svcauth_unix_purge); -- cgit v0.10.2 From 5717e0128422b96be6aa414fa752ec90c1cd31e9 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 11 Apr 2012 15:13:35 +0400 Subject: nfsd: allocate export and expkey caches in per-net operations. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index b144177..08cd87a 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1137,7 +1137,28 @@ static int create_proc_exports_entry(void) #endif int nfsd_net_id; + +static __net_init int nfsd_init_net(struct net *net) +{ + int retval; + + retval = nfsd_export_init(net); + if (retval) + goto out_export_error; + return 0; + +out_export_error: + return retval; +} + +static __net_exit void nfsd_exit_net(struct net *net) +{ + nfsd_export_shutdown(net); +} + static struct pernet_operations nfsd_net_ops = { + .init = nfsd_init_net, + .exit = nfsd_exit_net, .id = &nfsd_net_id, .size = sizeof(struct nfsd_net), }; @@ -1164,9 +1185,6 @@ static int __init init_nfsd(void) retval = nfsd_reply_cache_init(); if (retval) goto out_free_stat; - retval = nfsd_export_init(&init_net); - if (retval) - goto out_free_cache; nfsd_lockd_init(); /* lockd->nfsd callbacks */ retval = nfsd_idmap_init(); if (retval) @@ -1185,8 +1203,6 @@ out_free_idmap: nfsd_idmap_shutdown(); out_free_lockd: nfsd_lockd_shutdown(); - nfsd_export_shutdown(&init_net); -out_free_cache: nfsd_reply_cache_shutdown(); out_free_stat: nfsd_stat_shutdown(); @@ -1202,7 +1218,6 @@ out_unregister_notifier: static void __exit exit_nfsd(void) { - nfsd_export_shutdown(&init_net); nfsd_reply_cache_shutdown(); remove_proc_entry("fs/nfs/exports", NULL); remove_proc_entry("fs/nfs", NULL); -- cgit v0.10.2 From 43ec1a20bfbe1fbf6df6bf5a7b9c88ea090dbfcd Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 11 Apr 2012 17:32:44 +0400 Subject: nfsd: pass network context to idmap init/exit functions These functions will be called from per-net operations. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/idmap.h b/fs/nfsd/idmap.h index 2f3be13..9d513ef 100644 --- a/fs/nfsd/idmap.h +++ b/fs/nfsd/idmap.h @@ -42,14 +42,14 @@ #define IDMAP_NAMESZ 128 #ifdef CONFIG_NFSD_V4 -int nfsd_idmap_init(void); -void nfsd_idmap_shutdown(void); +int nfsd_idmap_init(struct net *); +void nfsd_idmap_shutdown(struct net *); #else -static inline int nfsd_idmap_init(void) +static inline int nfsd_idmap_init(struct net *net) { return 0; } -static inline void nfsd_idmap_shutdown(void) +static inline void nfsd_idmap_shutdown(struct net *net) { } #endif diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 2ff4470..d37405f 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -469,24 +469,24 @@ nametoid_update(struct cache_detail *cd, struct ent *new, struct ent *old) */ int -nfsd_idmap_init(void) +nfsd_idmap_init(struct net *net) { int rv; - rv = cache_register_net(&idtoname_cache, &init_net); + rv = cache_register_net(&idtoname_cache, net); if (rv) return rv; - rv = cache_register_net(&nametoid_cache, &init_net); + rv = cache_register_net(&nametoid_cache, net); if (rv) - cache_unregister_net(&idtoname_cache, &init_net); + cache_unregister_net(&idtoname_cache, net); return rv; } void -nfsd_idmap_shutdown(void) +nfsd_idmap_shutdown(struct net *net) { - cache_unregister_net(&idtoname_cache, &init_net); - cache_unregister_net(&nametoid_cache, &init_net); + cache_unregister_net(&idtoname_cache, net); + cache_unregister_net(&nametoid_cache, net); } static int diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 08cd87a..d6e8b85 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1186,7 +1186,7 @@ static int __init init_nfsd(void) if (retval) goto out_free_stat; nfsd_lockd_init(); /* lockd->nfsd callbacks */ - retval = nfsd_idmap_init(); + retval = nfsd_idmap_init(&init_net); if (retval) goto out_free_lockd; retval = create_proc_exports_entry(); @@ -1200,7 +1200,7 @@ out_free_all: remove_proc_entry("fs/nfs/exports", NULL); remove_proc_entry("fs/nfs", NULL); out_free_idmap: - nfsd_idmap_shutdown(); + nfsd_idmap_shutdown(&init_net); out_free_lockd: nfsd_lockd_shutdown(); nfsd_reply_cache_shutdown(); @@ -1223,7 +1223,7 @@ static void __exit exit_nfsd(void) remove_proc_entry("fs/nfs", NULL); nfsd_stat_shutdown(); nfsd_lockd_shutdown(); - nfsd_idmap_shutdown(); + nfsd_idmap_shutdown(&init_net); nfsd4_free_slabs(); nfsd_fault_inject_cleanup(); unregister_filesystem(&nfsd_fs_type); -- cgit v0.10.2 From c2e76ef5e0716bc82364e6049e8023ffd5bbe395 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 11 Apr 2012 17:32:51 +0400 Subject: nfsd: make id-to-name cache allocated per network namespace context Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 9794c6c..948a718 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -31,6 +31,9 @@ struct nfsd_net { struct cache_detail *svc_expkey_cache; struct cache_detail *svc_export_cache; + + struct cache_detail *idtoname_cache; + }; extern int nfsd_net_id; diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index d37405f..b285a69 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -36,9 +36,11 @@ #include #include #include +#include #include #include "idmap.h" #include "nfsd.h" +#include "netns.h" /* * Turn off idmapping when using AUTH_SYS. @@ -107,8 +109,6 @@ ent_alloc(void) * ID -> Name cache */ -static struct cache_head *idtoname_table[ENT_HASHMAX]; - static uint32_t idtoname_hash(struct ent *ent) { @@ -187,10 +187,9 @@ static struct ent *idtoname_lookup(struct cache_detail *, struct ent *); static struct ent *idtoname_update(struct cache_detail *, struct ent *, struct ent *); -static struct cache_detail idtoname_cache = { +static struct cache_detail idtoname_cache_template = { .owner = THIS_MODULE, .hash_size = ENT_HASHMAX, - .hash_table = idtoname_table, .name = "nfs4.idtoname", .cache_put = ent_put, .cache_upcall = idtoname_upcall, @@ -472,21 +471,34 @@ int nfsd_idmap_init(struct net *net) { int rv; + struct nfsd_net *nn = net_generic(net, nfsd_net_id); - rv = cache_register_net(&idtoname_cache, net); + nn->idtoname_cache = cache_create_net(&idtoname_cache_template, net); + if (IS_ERR(nn->idtoname_cache)) + return PTR_ERR(nn->idtoname_cache); + rv = cache_register_net(nn->idtoname_cache, net); if (rv) - return rv; + goto destroy_idtoname_cache; rv = cache_register_net(&nametoid_cache, net); if (rv) - cache_unregister_net(&idtoname_cache, net); + goto unregister_idtoname_cache; + return 0; + +unregister_idtoname_cache: + cache_unregister_net(nn->idtoname_cache, net); +destroy_idtoname_cache: + cache_destroy_net(nn->idtoname_cache, net); return rv; } void nfsd_idmap_shutdown(struct net *net) { - cache_unregister_net(&idtoname_cache, net); + struct nfsd_net *nn = net_generic(net, nfsd_net_id); + + cache_unregister_net(nn->idtoname_cache, net); cache_unregister_net(&nametoid_cache, net); + cache_destroy_net(nn->idtoname_cache, net); } static int @@ -553,9 +565,10 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) .type = type, }; int ret; + struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); - ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item); + ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); if (ret == -ENOENT) return sprintf(name, "%u", id); if (ret) @@ -563,7 +576,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) ret = strlen(item->name); BUG_ON(ret > IDMAP_NAMESZ); memcpy(name, item->name, ret); - cache_put(&item->h, &idtoname_cache); + cache_put(&item->h, nn->idtoname_cache); return ret; } -- cgit v0.10.2 From 9e75a4dee08e8fe21f349e11c43955c34523bced Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 11 Apr 2012 17:32:58 +0400 Subject: nfsd: make name-to-id cache allocated per network namespace context Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 948a718..3936563 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -33,7 +33,7 @@ struct nfsd_net { struct cache_detail *svc_export_cache; struct cache_detail *idtoname_cache; - + struct cache_detail *nametoid_cache; }; extern int nfsd_net_id; diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index b285a69..286a7f8 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -301,8 +301,6 @@ idtoname_update(struct cache_detail *cd, struct ent *new, struct ent *old) * Name -> ID cache */ -static struct cache_head *nametoid_table[ENT_HASHMAX]; - static inline int nametoid_hash(struct ent *ent) { @@ -362,10 +360,9 @@ static struct ent *nametoid_update(struct cache_detail *, struct ent *, struct ent *); static int nametoid_parse(struct cache_detail *, char *, int); -static struct cache_detail nametoid_cache = { +static struct cache_detail nametoid_cache_template = { .owner = THIS_MODULE, .hash_size = ENT_HASHMAX, - .hash_table = nametoid_table, .name = "nfs4.nametoid", .cache_put = ent_put, .cache_upcall = nametoid_upcall, @@ -479,11 +476,18 @@ nfsd_idmap_init(struct net *net) rv = cache_register_net(nn->idtoname_cache, net); if (rv) goto destroy_idtoname_cache; - rv = cache_register_net(&nametoid_cache, net); - if (rv) + nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net); + if (IS_ERR(nn->nametoid_cache)) { + rv = PTR_ERR(nn->idtoname_cache); goto unregister_idtoname_cache; + } + rv = cache_register_net(nn->nametoid_cache, net); + if (rv) + goto destroy_nametoid_cache; return 0; +destroy_nametoid_cache: + cache_destroy_net(nn->nametoid_cache, net); unregister_idtoname_cache: cache_unregister_net(nn->idtoname_cache, net); destroy_idtoname_cache: @@ -497,8 +501,9 @@ nfsd_idmap_shutdown(struct net *net) struct nfsd_net *nn = net_generic(net, nfsd_net_id); cache_unregister_net(nn->idtoname_cache, net); - cache_unregister_net(&nametoid_cache, net); + cache_unregister_net(nn->nametoid_cache, net); cache_destroy_net(nn->idtoname_cache, net); + cache_destroy_net(nn->nametoid_cache, net); } static int @@ -541,19 +546,20 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen .type = type, }; int ret; + struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); if (namelen + 1 > sizeof(key.name)) return nfserr_badowner; memcpy(key.name, name, namelen); key.name[namelen] = '\0'; strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); - ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item); + ret = idmap_lookup(rqstp, nametoid_lookup, &key, nn->nametoid_cache, &item); if (ret == -ENOENT) return nfserr_badowner; if (ret) return nfserrno(ret); *id = item->id; - cache_put(&item->h, &nametoid_cache); + cache_put(&item->h, nn->nametoid_cache); return 0; } -- cgit v0.10.2 From f69adb2fe2553f0536ad3603828c835239d5ec3e Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 11 Apr 2012 17:33:05 +0400 Subject: nfsd: allocate id-to-name and name-to-id caches in per-net operations. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index d6e8b85..7269988 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1145,14 +1145,20 @@ static __net_init int nfsd_init_net(struct net *net) retval = nfsd_export_init(net); if (retval) goto out_export_error; + retval = nfsd_idmap_init(net); + if (retval) + goto out_idmap_error; return 0; +out_idmap_error: + nfsd_export_shutdown(net); out_export_error: return retval; } static __net_exit void nfsd_exit_net(struct net *net) { + nfsd_idmap_shutdown(net); nfsd_export_shutdown(net); } @@ -1186,12 +1192,9 @@ static int __init init_nfsd(void) if (retval) goto out_free_stat; nfsd_lockd_init(); /* lockd->nfsd callbacks */ - retval = nfsd_idmap_init(&init_net); - if (retval) - goto out_free_lockd; retval = create_proc_exports_entry(); if (retval) - goto out_free_idmap; + goto out_free_lockd; retval = register_filesystem(&nfsd_fs_type); if (retval) goto out_free_all; @@ -1199,8 +1202,6 @@ static int __init init_nfsd(void) out_free_all: remove_proc_entry("fs/nfs/exports", NULL); remove_proc_entry("fs/nfs", NULL); -out_free_idmap: - nfsd_idmap_shutdown(&init_net); out_free_lockd: nfsd_lockd_shutdown(); nfsd_reply_cache_shutdown(); @@ -1223,7 +1224,6 @@ static void __exit exit_nfsd(void) remove_proc_entry("fs/nfs", NULL); nfsd_stat_shutdown(); nfsd_lockd_shutdown(); - nfsd_idmap_shutdown(&init_net); nfsd4_free_slabs(); nfsd_fault_inject_cleanup(); unregister_filesystem(&nfsd_fs_type); -- cgit v0.10.2 From 366ee7c2289cc307259166fe8c2f093920c1e575 Mon Sep 17 00:00:00 2001 From: Alexander Guy Date: Thu, 12 Apr 2012 12:26:49 -0700 Subject: skeletonfb: fixed module exit function typo. Signed-off-by: Alexander Guy Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 30f7a81..5b6abc6 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -1036,6 +1036,6 @@ static void __exit xxxfb_exit(void) */ module_init(xxxfb_init); -module_exit(xxxfb_remove); +module_exit(xxxfb_exit); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 4e0dd49d2c4bc10d56bc536113c16f165c0edeb3 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Apr 2012 15:57:44 +0900 Subject: video: s3c-fb: add runtime_get/put to suspend/resume This patch adds runtime_get/put to suspend/resume, which should be necessary to prevent the problem to access the fimd register without block power on. Signed-off-by: Jingoo Han Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 18c84b8..ecb82bb 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -1557,6 +1557,8 @@ static int s3c_fb_suspend(struct device *dev) struct s3c_fb_win *win; int win_no; + pm_runtime_get_sync(sfb->dev); + for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) { win = sfb->windows[win_no]; if (!win) @@ -1570,6 +1572,9 @@ static int s3c_fb_suspend(struct device *dev) clk_disable(sfb->lcd_clk); clk_disable(sfb->bus_clk); + + pm_runtime_put_sync(sfb->dev); + return 0; } @@ -1582,6 +1587,8 @@ static int s3c_fb_resume(struct device *dev) int win_no; u32 reg; + pm_runtime_get_sync(sfb->dev); + clk_enable(sfb->bus_clk); if (!sfb->variant.has_clksel) @@ -1628,6 +1635,8 @@ static int s3c_fb_resume(struct device *dev) s3c_fb_set_par(win->fbinfo); } + pm_runtime_put_sync(sfb->dev); + return 0; } #endif -- cgit v0.10.2 From b5cfeed6cf90a4bb619b7ac640ba1a6dd002364d Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Apr 2012 15:59:24 +0900 Subject: video: exynos_dp: check DP PLL Lock status DP PLL Lock status should be checked in order to prevent unlocked PLL. Signed-off-by: Jingoo Han Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c index 6548afa..169d181 100644 --- a/drivers/video/exynos/exynos_dp_reg.c +++ b/drivers/video/exynos/exynos_dp_reg.c @@ -271,6 +271,7 @@ void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp, void exynos_dp_init_analog_func(struct exynos_dp_device *dp) { u32 reg; + int timeout_loop = 0; exynos_dp_set_analog_power_down(dp, POWER_ALL, 0); @@ -282,9 +283,19 @@ void exynos_dp_init_analog_func(struct exynos_dp_device *dp) writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL); /* Power up PLL */ - if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) + if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { exynos_dp_set_pll_power_down(dp, 0); + while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + timeout_loop++; + if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { + dev_err(dp->dev, "failed to get pll lock status\n"); + return; + } + usleep_range(10, 20); + } + } + /* Enable Serdes FIFO function and Link symbol clock domain module */ reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2); reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N -- cgit v0.10.2 From 8f802da33a842bc9e511d2a9c8259fbee8a6d17e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 4 Apr 2012 16:00:00 +0900 Subject: video: exynos_dp: replace char pointer with char array for adjust_request variable The char pointer for adjust_request variable is replaced with char array to fix possible null pointer dereference when clock recovery is failed. Signed-off-by: Jingoo Han Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index 2a4481c..6e9f3ce 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c @@ -478,7 +478,7 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) int lane_count; u8 buf[5]; - u8 *adjust_request; + u8 adjust_request[2]; u8 voltage_swing; u8 pre_emphasis; u8 training_lane; @@ -493,8 +493,8 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) /* set training pattern 2 for EQ */ exynos_dp_set_training_pattern(dp, TRAINING_PTN2); - adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1 - - DPCD_ADDR_LANE0_1_STATUS); + adjust_request[0] = link_status[4]; + adjust_request[1] = link_status[5]; exynos_dp_get_adjust_train(dp, adjust_request); @@ -566,7 +566,7 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) u8 buf[5]; u32 reg; - u8 *adjust_request; + u8 adjust_request[2]; udelay(400); @@ -575,8 +575,8 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) lane_count = dp->link_train.lane_count; if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { - adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1 - - DPCD_ADDR_LANE0_1_STATUS); + adjust_request[0] = link_status[4]; + adjust_request[1] = link_status[5]; if (exynos_dp_channel_eq_ok(link_status, lane_count) == 0) { /* traing pattern Set to Normal */ -- cgit v0.10.2 From 8affaf5c7698c627b133bfcafd9869ef17faff31 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 16 Apr 2012 09:33:12 +0900 Subject: video: exynos_dp: add analog and pll control setting This patch adds analog and pll control setting. This control setting is used for DP TX PHY block to set the values as below. It is beneficial to improve analog characteristics. - TX terminal registor is 50 Ohm. - Reference clock of PHY is 24 MHz. - Power source for TX digital logic is 1.0625 V. - Power source for internal clock driver is 1.0625 V. - PLL VCO range setting is 600 uA. - Power down ring osc is turned off. - AUX terminal resistor is 50 Ohm. - AUX channel current is 8 mA and multiplied by 2. - TX channel output amplitude is 400 mV. Signed-off-by: Jingoo Han Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h index 90ceaca..519c3a6 100644 --- a/drivers/video/exynos/exynos_dp_core.h +++ b/drivers/video/exynos/exynos_dp_core.h @@ -39,6 +39,7 @@ struct exynos_dp_device { void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable); void exynos_dp_stop_video(struct exynos_dp_device *dp); void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable); +void exynos_dp_init_analog_param(struct exynos_dp_device *dp); void exynos_dp_init_interrupt(struct exynos_dp_device *dp); void exynos_dp_reset(struct exynos_dp_device *dp); void exynos_dp_config_interrupt(struct exynos_dp_device *dp); diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c index 169d181..3863726 100644 --- a/drivers/video/exynos/exynos_dp_reg.c +++ b/drivers/video/exynos/exynos_dp_reg.c @@ -65,6 +65,28 @@ void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable) writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP); } +void exynos_dp_init_analog_param(struct exynos_dp_device *dp) +{ + u32 reg; + + reg = TX_TERMINAL_CTRL_50_OHM; + writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1); + + reg = SEL_24M | TX_DVDD_BIT_1_0625V; + writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2); + + reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO; + writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3); + + reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM | + TX_CUR1_2X | TX_CUR_8_MA; + writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1); + + reg = CH3_AMP_400_MV | CH2_AMP_400_MV | + CH1_AMP_400_MV | CH0_AMP_400_MV; + writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL); +} + void exynos_dp_init_interrupt(struct exynos_dp_device *dp) { /* Set interrupt pin assertion polarity as high */ @@ -131,6 +153,7 @@ void exynos_dp_reset(struct exynos_dp_device *dp) writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); + exynos_dp_init_analog_param(dp); exynos_dp_init_interrupt(dp); } diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h index 42f608e..125b27c 100644 --- a/drivers/video/exynos/exynos_dp_reg.h +++ b/drivers/video/exynos/exynos_dp_reg.h @@ -24,6 +24,12 @@ #define EXYNOS_DP_LANE_MAP 0x35C +#define EXYNOS_DP_ANALOG_CTL_1 0x370 +#define EXYNOS_DP_ANALOG_CTL_2 0x374 +#define EXYNOS_DP_ANALOG_CTL_3 0x378 +#define EXYNOS_DP_PLL_FILTER_CTL_1 0x37C +#define EXYNOS_DP_TX_AMP_TUNING_CTL 0x380 + #define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390 #define EXYNOS_DP_COMMON_INT_STA_1 0x3C4 @@ -166,6 +172,29 @@ #define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0) #define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0) +/* EXYNOS_DP_ANALOG_CTL_1 */ +#define TX_TERMINAL_CTRL_50_OHM (0x1 << 4) + +/* EXYNOS_DP_ANALOG_CTL_2 */ +#define SEL_24M (0x1 << 3) +#define TX_DVDD_BIT_1_0625V (0x4 << 0) + +/* EXYNOS_DP_ANALOG_CTL_3 */ +#define DRIVE_DVDD_BIT_1_0625V (0x4 << 5) +#define VCO_BIT_600_MICRO (0x5 << 0) + +/* EXYNOS_DP_PLL_FILTER_CTL_1 */ +#define PD_RING_OSC (0x1 << 6) +#define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4) +#define TX_CUR1_2X (0x1 << 2) +#define TX_CUR_8_MA (0x2 << 0) + +/* EXYNOS_DP_TX_AMP_TUNING_CTL */ +#define CH3_AMP_400_MV (0x0 << 24) +#define CH2_AMP_400_MV (0x0 << 16) +#define CH1_AMP_400_MV (0x0 << 8) +#define CH0_AMP_400_MV (0x0 << 0) + /* EXYNOS_DP_AUX_HW_RETRY_CTL */ #define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8) #define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3) -- cgit v0.10.2 From 49a8ee8ac3f20e4d8fe284012c082a793982d48f Mon Sep 17 00:00:00 2001 From: David Brown Date: Thu, 12 Apr 2012 11:45:33 -0700 Subject: video: msm: Fix section mismatches in mddi.c The change commit 461cbe77d0a4f887c33a3a95ea68a7daf23b4302 Author: Gregory Bean Date: Wed Jul 28 10:22:13 2010 -0700 video: msm: Fix section mismatch in mddi.c. fixes a section mismatch between the board file and the driver's probe function, however, it misses the additional mismatches between the probe function and some routines it calls. Fix these up as well. Signed-off-by: David Brown Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c index 4527cbf..b061d70 100644 --- a/drivers/video/msm/mddi.c +++ b/drivers/video/msm/mddi.c @@ -420,7 +420,7 @@ static void mddi_resume(struct msm_mddi_client_data *cdata) mddi_set_auto_hibernate(&mddi->client_data, 1); } -static int __init mddi_get_client_caps(struct mddi_info *mddi) +static int __devinit mddi_get_client_caps(struct mddi_info *mddi) { int i, j; @@ -622,9 +622,9 @@ uint32_t mddi_remote_read(struct msm_mddi_client_data *cdata, uint32_t reg) static struct mddi_info mddi_info[2]; -static int __init mddi_clk_setup(struct platform_device *pdev, - struct mddi_info *mddi, - unsigned long clk_rate) +static int __devinit mddi_clk_setup(struct platform_device *pdev, + struct mddi_info *mddi, + unsigned long clk_rate) { int ret; -- cgit v0.10.2 From 045dfdb5c5e8fe49afe1de82fb94eaae8121e059 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 18 Apr 2012 21:37:08 +0200 Subject: drivers/video/ep93xx-fb.c: clean up error-handling code There were two problems in this code: failure of the setup function should free locally allocated resources like other nearby failures, and the test if (&info->cmap) can never be false. To generally clean things up, this patch reorders the error handling code at the failed label and adds labels so that the conditionals are not necessary. Signed-off-by: Julia Lawall Acked-by: H Hartley Sweeten Reviewed-by: Ryan Mallon Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c index f8babbe..345d962 100644 --- a/drivers/video/ep93xx-fb.c +++ b/drivers/video/ep93xx-fb.c @@ -507,16 +507,16 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev) err = fb_alloc_cmap(&info->cmap, 256, 0); if (err) - goto failed; + goto failed_cmap; err = ep93xxfb_alloc_videomem(info); if (err) - goto failed; + goto failed_videomem; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { err = -ENXIO; - goto failed; + goto failed_resource; } /* @@ -532,7 +532,7 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev) fbi->mmio_base = ioremap(res->start, resource_size(res)); if (!fbi->mmio_base) { err = -ENXIO; - goto failed; + goto failed_resource; } strcpy(info->fix.id, pdev->name); @@ -553,24 +553,24 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev) if (err == 0) { dev_err(info->dev, "No suitable video mode found\n"); err = -EINVAL; - goto failed; + goto failed_mode; } if (mach_info->setup) { err = mach_info->setup(pdev); if (err) - return err; + goto failed_mode; } err = ep93xxfb_check_var(&info->var, info); if (err) - goto failed; + goto failed_check; fbi->clk = clk_get(info->dev, NULL); if (IS_ERR(fbi->clk)) { err = PTR_ERR(fbi->clk); fbi->clk = NULL; - goto failed; + goto failed_check; } ep93xxfb_set_par(info); @@ -585,15 +585,17 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev) return 0; failed: - if (fbi->clk) - clk_put(fbi->clk); - if (fbi->mmio_base) - iounmap(fbi->mmio_base); - ep93xxfb_dealloc_videomem(info); - if (&info->cmap) - fb_dealloc_cmap(&info->cmap); + clk_put(fbi->clk); +failed_check: if (fbi->mach_info->teardown) fbi->mach_info->teardown(pdev); +failed_mode: + iounmap(fbi->mmio_base); +failed_resource: + ep93xxfb_dealloc_videomem(info); +failed_videomem: + fb_dealloc_cmap(&info->cmap); +failed_cmap: kfree(info); platform_set_drvdata(pdev, NULL); -- cgit v0.10.2 From 2de06df49f71fee795e997dee1eeda74a2b8598b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 18 Apr 2012 22:07:11 +0200 Subject: drivers/video/mbx/mbxfb.c: correct ioremap_nocache test The test tested not the most recently allocated value but a previously allocated one. Signed-off-by: Julia Lawall Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c index 55bf619..ab0a8e5 100644 --- a/drivers/video/mbx/mbxfb.c +++ b/drivers/video/mbx/mbxfb.c @@ -950,7 +950,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev) mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr, res_size(mfbi->fb_req)); - if (!mfbi->reg_virt_addr) { + if (!mfbi->fb_virt_addr) { dev_err(&dev->dev, "failed to ioremap frame buffer\n"); ret = -EINVAL; goto err4; -- cgit v0.10.2 From d313a86d2efb2c5568832389663322e93e291c59 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 19 Apr 2012 20:31:02 +0200 Subject: i.MX28: Shut down the LCD controller to avoid BootROM sampling bug If there's some traffic on the LCD controller pads, the BootROM has trouble with sampling the bootmode from these pads. The BootROM usually ends in a loop. Signed-off-by: Marek Vasut Cc: Chen Peter-B29397 Cc: Detlev Zundel Cc: Fabio Estevam Cc: Li Frank-B20596 Cc: Lin Tony-B19295 Cc: Linux FBDEV Cc: Sascha Hauer Cc: Shawn Guo Cc: Stefano Babic Cc: Subodh Nijsure Cc: Tony Lin Acked-by: Shawn Guo Acked-by: Wolfgang Denk Acked-by: Wolfram Sang Tested-by: Wolfgang Denk Signed-off-by: Florian Tobias Schandinat diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 4a89f88..dcf29bf 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -880,6 +880,18 @@ static int __devexit mxsfb_remove(struct platform_device *pdev) return 0; } +static void mxsfb_shutdown(struct platform_device *pdev) +{ + struct fb_info *fb_info = platform_get_drvdata(pdev); + struct mxsfb_info *host = to_imxfb_host(fb_info); + + /* + * Force stop the LCD controller as keeping it running during reboot + * might interfere with the BootROM's boot mode pads sampling. + */ + writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR); +} + static struct platform_device_id mxsfb_devtype[] = { { .name = "imx23-fb", @@ -896,6 +908,7 @@ MODULE_DEVICE_TABLE(platform, mxsfb_devtype); static struct platform_driver mxsfb_driver = { .probe = mxsfb_probe, .remove = __devexit_p(mxsfb_remove), + .shutdown = mxsfb_shutdown, .id_table = mxsfb_devtype, .driver = { .name = DRIVER_NAME, -- cgit v0.10.2 From 62c1dcfc7451a8e42104776705a317e06a8e24a3 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 8 Mar 2012 12:37:58 +0200 Subject: OMAPDSS: add set_min_bus_tput pointer to omapdss's platform data omapdss driver needs to use the omap_pm_set_min_bus_tput(), so add a new entry for that in omapdss's platform data, and set it. Signed-off-by: Tomi Valkeinen Cc: Paul Walmsley Acked-by: Kevin Hilman diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index db5a88a..60cded4 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -180,6 +180,11 @@ static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask) omap4_dsi_mux_pads(dsi_id, 0); } +static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput) +{ + return omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, tput); +} + int __init omap_display_init(struct omap_dss_board_info *board_data) { int r = 0; @@ -210,6 +215,7 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) pdata.board_data = board_data; pdata.board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count; + pdata.board_data->set_min_bus_tput = omap_dss_set_min_bus_tput; for (i = 0; i < oh_count; i++) { oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 483f67c..7aecadb 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -309,6 +309,7 @@ struct omap_dss_board_info { struct omap_dss_device *default_device; int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask); void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask); + int (*set_min_bus_tput)(struct device *dev, unsigned long r); }; /* Init with the board info */ -- cgit v0.10.2 From a8081d317978416197295df22fc2ea71e4812f50 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 8 Mar 2012 12:52:38 +0200 Subject: OMAPDSS: Ensure OPP100 when DSS is operational Most of the DSS clocks have restrictions on their frequency based on the OPP in use. For example, maximum frequency for a clock may be 180MHz in OPP100, but 90MHz in OPP50. This means that when a high enough pixel clock or function clock is required, we need to use OPP100. However, there's currently no way in the PM framework to make that kind of request. The closest we get is to ask for very high bus throughput from the PM framework, which should effectively force OPP100. This patch is a simple version for handling the problem. Instead of asking for OPP100 only when needed, this patch asks for OPP100 whenever DSS is active. This obviously is not an optimal solution for cases with small displays where OPP50 would work just fine. However, a proper solution is a complex one, and this patch is a short term solution for the problem. Signed-off-by: Tomi Valkeinen Cc: Paul Walmsley Acked-by: Kevin Hilman diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index e8a1207..5ad8cc7 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -87,6 +87,16 @@ struct regulator *dss_get_vdds_sdi(void) return reg; } +int dss_set_min_bus_tput(struct device *dev, unsigned long tput) +{ + struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; + + if (pdata->set_min_bus_tput) + return pdata->set_min_bus_tput(dev, tput); + else + return 0; +} + #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) static int dss_debug_show(struct seq_file *s, void *unused) { diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index bd2d5e1..e731aa4 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -829,11 +829,24 @@ static int omap_dsshw_remove(struct platform_device *pdev) static int dss_runtime_suspend(struct device *dev) { dss_save_context(); + dss_set_min_bus_tput(dev, 0); return 0; } static int dss_runtime_resume(struct device *dev) { + int r; + /* + * Set an arbitrarily high tput request to ensure OPP100. + * What we should really do is to make a request to stay in OPP100, + * without any tput requirements, but that is not currently possible + * via the PM layer. + */ + + r = dss_set_min_bus_tput(dev, 1000000000); + if (r) + return r; + dss_restore_context(); return 0; } diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index d4b3dff..42f8f62 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -162,6 +162,7 @@ struct platform_device; struct bus_type *dss_get_bus(void); struct regulator *dss_get_vdds_dsi(void); struct regulator *dss_get_vdds_sdi(void); +int dss_set_min_bus_tput(struct device *dev, unsigned long tput); /* apply */ void dss_apply_init(void); -- cgit v0.10.2 From b6e695abe710ee1ae248463d325169efac487e17 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 15 Mar 2012 15:22:58 +0200 Subject: OMAPDSS: DSI: remove option to use pck for DSI PLL clkin For some OMAP versions the TRM says that the pixel clock from DISPC can be used as an input clock for DSI PLL, instead of the default, which is sysclk. For some OMAP versions the bits affecting this are marked as reserved. This feature has never been tested, so it's unknown if the HW even works, and has never been used. To clean things up, this patch removes the functionality. This should not affect any board. Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 662d14f..0d2c53f 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1279,10 +1279,9 @@ static int dsi_pll_power(struct platform_device *dsidev, } /* calculate clock rates using dividers in cinfo */ -static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, +static int dsi_calc_clock_rates(struct platform_device *dsidev, struct dsi_clock_info *cinfo) { - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max) @@ -1297,21 +1296,8 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, if (cinfo->regm_dsi > dsi->regm_dsi_max) return -EINVAL; - if (cinfo->use_sys_clk) { - cinfo->clkin = clk_get_rate(dsi->sys_clk); - /* XXX it is unclear if highfreq should be used - * with DSS_SYS_CLK source also */ - cinfo->highfreq = 0; - } else { - cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id); - - if (cinfo->clkin < 32000000) - cinfo->highfreq = 0; - else - cinfo->highfreq = 1; - } - - cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); + cinfo->clkin = clk_get_rate(dsi->sys_clk); + cinfo->fint = cinfo->clkin / cinfo->regn; if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min) return -EINVAL; @@ -1378,27 +1364,21 @@ retry: memset(&cur, 0, sizeof(cur)); cur.clkin = dss_sys_clk; - cur.use_sys_clk = 1; - cur.highfreq = 0; - /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ - /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ + /* 0.75MHz < Fint = clkin / regn < 2.1MHz */ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { - if (cur.highfreq == 0) - cur.fint = cur.clkin / cur.regn; - else - cur.fint = cur.clkin / (2 * cur.regn); + cur.fint = cur.clkin / cur.regn; if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) continue; - /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ + /* DSIPHY(MHz) = (2 * regm / regn) * clkin */ for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { unsigned long a, b; a = 2 * cur.regm * (cur.clkin/1000); - b = cur.regn * (cur.highfreq + 1); + b = cur.regn; cur.clkin4ddr = a / b * 1000; if (cur.clkin4ddr > 1800 * 1000 * 1000) @@ -1486,9 +1466,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, DSSDBGF(); - dsi->current_cinfo.use_sys_clk = cinfo->use_sys_clk; - dsi->current_cinfo.highfreq = cinfo->highfreq; - + dsi->current_cinfo.clkin = cinfo->clkin; dsi->current_cinfo.fint = cinfo->fint; dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr; dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk = @@ -1503,17 +1481,13 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, DSSDBG("DSI Fint %ld\n", cinfo->fint); - DSSDBG("clkin (%s) rate %ld, highfreq %d\n", - cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree", - cinfo->clkin, - cinfo->highfreq); + DSSDBG("clkin rate %ld\n", cinfo->clkin); /* DSIPHY == CLKIN4DDR */ - DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n", + DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n", cinfo->regm, cinfo->regn, cinfo->clkin, - cinfo->highfreq + 1, cinfo->clkin4ddr); DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", @@ -1568,10 +1542,6 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev, if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ - l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, - 11, 11); /* DSI_PLL_CLKSEL */ - l = FLD_MOD(l, cinfo->highfreq, - 12, 12); /* DSI_PLL_HIGHFREQ */ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ @@ -1726,8 +1696,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); - seq_printf(s, "dsi pll source = %s\n", - cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree"); + seq_printf(s, "dsi pll clkin\t%lu\n", cinfo->clkin); seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); @@ -4285,13 +4254,11 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) struct dsi_clock_info cinfo; int r; - /* we always use DSS_CLK_SYSCK as input clock */ - cinfo.use_sys_clk = true; cinfo.regn = dssdev->clocks.dsi.regn; cinfo.regm = dssdev->clocks.dsi.regm; cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; - r = dsi_calc_clock_rates(dssdev, &cinfo); + r = dsi_calc_clock_rates(dsidev, &cinfo); if (r) { DSSERR("Failed to calc dsi clocks\n"); return r; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 42f8f62..7080f5f 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -150,9 +150,6 @@ struct dsi_clock_info { u16 regm_dsi; /* OMAP3: REGM4 * OMAP4: REGM5 */ u16 lp_clk_div; - - u8 highfreq; - bool use_sys_clk; }; struct seq_file; -- cgit v0.10.2 From 9c3d5eb71b1fdcdef434a46444d931ada6938446 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 19 Mar 2012 14:50:46 +0000 Subject: OMAP: DSS2: Remove suspicous and unused TAAL regulator API usage The TAAL driver contains some regulator support which is currently unused (the code is there but the one panel supported by the driver doesn't have any regulators provided). This code mostly looks like an open coded version of the regulator core bulk API. The only additional feature is that a voltage range can be set once when the device is opened, though this is never varied at runtime. The general expectation is that if the device is not actively managing the voltage of the device (eg, doing DVFS) then any configuration will be done using the constraints rather than by drivers, saving them code and ensuring that they work well with systems where the voltage is not configurable. If systems are added needing regulator support this can be added back in, though it should be based on core features rather than open coding things. Signed-off-by: Mark Brown Signed-off-by: Tomi Valkeinen diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 0f21fa5..72d6307 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include