diff options
Diffstat (limited to 'drivers/video/console/fbcon.c')
| -rw-r--r-- | drivers/video/console/fbcon.c | 33 | 
1 files changed, 30 insertions, 3 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index cd8a8027f8a..57b1d44acbf 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -748,6 +748,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,  		fbcon_del_cursor_timer(oldinfo);  		kfree(ops->cursor_state.mask);  		kfree(ops->cursor_data); +		kfree(ops->cursor_src);  		kfree(ops->fontbuffer);  		kfree(oldinfo->fbcon_par);  		oldinfo->fbcon_par = NULL; @@ -759,7 +760,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,  		  newinfo in an undefined state. Thus, a call to  		  fb_set_par() may be needed for the newinfo.  		*/ -		if (newinfo->fbops->fb_set_par) { +		if (newinfo && newinfo->fbops->fb_set_par) {  			ret = newinfo->fbops->fb_set_par(newinfo);  			if (ret) @@ -3028,8 +3029,31 @@ static int fbcon_fb_unbind(int idx)  			if (con2fb_map[i] == idx)  				set_con2fb_map(i, new_idx, 0);  		} -	} else +	} else { +		struct fb_info *info = registered_fb[idx]; + +		/* This is sort of like set_con2fb_map, except it maps +		 * the consoles to no device and then releases the +		 * oldinfo to free memory and cancel the cursor blink +		 * timer. I can imagine this just becoming part of +		 * set_con2fb_map where new_idx is -1 +		 */ +		for (i = first_fb_vc; i <= last_fb_vc; i++) { +			if (con2fb_map[i] == idx) { +				con2fb_map[i] = -1; +				if (!search_fb_in_map(idx)) { +					ret = con2fb_release_oldinfo(vc_cons[i].d, +								     info, NULL, i, +								     idx, 0); +					if (ret) { +						con2fb_map[i] = idx; +						return ret; +					} +				} +			} +		}  		ret = fbcon_unbind(); +	}  	return ret;  } @@ -3547,8 +3571,10 @@ static void fbcon_exit(void)  			"no"));  		for (j = first_fb_vc; j <= last_fb_vc; j++) { -			if (con2fb_map[j] == i) +			if (con2fb_map[j] == i) {  				mapped = 1; +				break; +			}  		}  		if (mapped) { @@ -3561,6 +3587,7 @@ static void fbcon_exit(void)  				fbcon_del_cursor_timer(info);  				kfree(ops->cursor_src); +				kfree(ops->cursor_state.mask);  				kfree(info->fbcon_par);  				info->fbcon_par = NULL;  			}  | 
