2005-06-28 16:48:56 +04:00
/*
* Copyright 1998 - 2003 VIA Technologies , Inc . All Rights Reserved .
* Copyright 2001 - 2003 S3 Graphics , Inc . All Rights Reserved .
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sub license ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the
* next paragraph ) shall be included in all copies or substantial portions
* of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NON - INFRINGEMENT . IN NO EVENT SHALL
* VIA , S3 GRAPHICS , AND / OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM , DAMAGES OR
* OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE ,
* ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
*/
2012-10-02 21:01:07 +04:00
# include <drm/drmP.h>
# include <drm/via_drm.h>
2005-06-28 16:48:56 +04:00
# include "via_drv.h"
2010-07-11 17:32:42 +04:00
static int via_do_init_map ( struct drm_device * dev , drm_via_init_t * init )
2005-06-28 16:48:56 +04:00
{
2005-11-12 13:52:46 +03:00
drm_via_private_t * dev_priv = dev - > dev_private ;
2005-06-28 16:48:56 +04:00
2008-01-24 08:58:57 +03:00
DRM_DEBUG ( " \n " ) ;
2005-06-28 16:48:56 +04:00
2014-08-29 14:12:28 +04:00
dev_priv - > sarea = drm_legacy_getsarea ( dev ) ;
2005-06-28 16:48:56 +04:00
if ( ! dev_priv - > sarea ) {
DRM_ERROR ( " could not find sarea! \n " ) ;
dev - > dev_private = ( void * ) dev_priv ;
via_do_cleanup_map ( dev ) ;
return - EINVAL ;
}
2014-09-10 14:43:56 +04:00
dev_priv - > fb = drm_legacy_findmap ( dev , init - > fb_offset ) ;
2005-06-28 16:48:56 +04:00
if ( ! dev_priv - > fb ) {
DRM_ERROR ( " could not find framebuffer! \n " ) ;
dev - > dev_private = ( void * ) dev_priv ;
via_do_cleanup_map ( dev ) ;
return - EINVAL ;
}
2014-09-10 14:43:56 +04:00
dev_priv - > mmio = drm_legacy_findmap ( dev , init - > mmio_offset ) ;
2005-06-28 16:48:56 +04:00
if ( ! dev_priv - > mmio ) {
DRM_ERROR ( " could not find mmio region! \n " ) ;
dev - > dev_private = ( void * ) dev_priv ;
via_do_cleanup_map ( dev ) ;
return - EINVAL ;
}
dev_priv - > sarea_priv =
( drm_via_sarea_t * ) ( ( u8 * ) dev_priv - > sarea - > handle +
init - > sarea_priv_offset ) ;
dev_priv - > agpAddr = init - > agpAddr ;
2005-09-25 08:28:13 +04:00
via_init_futex ( dev_priv ) ;
2005-11-12 13:52:46 +03:00
via_init_dmablit ( dev ) ;
2005-06-28 16:48:56 +04:00
dev - > dev_private = ( void * ) dev_priv ;
return 0 ;
}
2010-07-11 17:32:42 +04:00
int via_do_cleanup_map ( struct drm_device * dev )
2005-06-28 16:48:56 +04:00
{
2005-11-12 13:52:46 +03:00
via_dma_cleanup ( dev ) ;
2005-06-28 16:48:56 +04:00
return 0 ;
}
2007-09-03 06:06:45 +04:00
int via_map_init ( struct drm_device * dev , void * data , struct drm_file * file_priv )
2005-06-28 16:48:56 +04:00
{
2007-09-03 06:06:45 +04:00
drm_via_init_t * init = data ;
2005-06-28 16:48:56 +04:00
2008-01-24 08:58:57 +03:00
DRM_DEBUG ( " \n " ) ;
2005-06-28 16:48:56 +04:00
2007-09-03 06:06:45 +04:00
switch ( init - > func ) {
2005-06-28 16:48:56 +04:00
case VIA_INIT_MAP :
2007-09-03 06:06:45 +04:00
return via_do_init_map ( dev , init ) ;
2005-06-28 16:48:56 +04:00
case VIA_CLEANUP_MAP :
return via_do_cleanup_map ( dev ) ;
}
return - EINVAL ;
}
2005-11-12 13:52:46 +03:00
2007-07-11 09:53:27 +04:00
int via_driver_load ( struct drm_device * dev , unsigned long chipset )
2005-11-12 13:52:46 +03:00
{
drm_via_private_t * dev_priv ;
2006-08-07 16:03:22 +04:00
int ret = 0 ;
2005-11-12 13:52:46 +03:00
2009-03-24 22:23:04 +03:00
dev_priv = kzalloc ( sizeof ( drm_via_private_t ) , GFP_KERNEL ) ;
2005-11-12 13:52:46 +03:00
if ( dev_priv = = NULL )
2007-08-25 13:22:43 +04:00
return - ENOMEM ;
2005-11-12 13:52:46 +03:00
drm via: initialize object_idr
The field obejct_idr of struct drm_via_private was introduced with the
commit http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=77ee8f3825054f23b17e9c8f728f061defd86cdc .
In that patch idr_init(&dev->object_name_idr) was called instead of
idr_init(&dev_priv->object_idr) by mistake, leaving the dev_priv->object_idr
uninitialized. To be more exact, the object_idr buffer is filled with zeros
because of kzalloc(), but the dev_priv->object_idr.lock spinlock can cause
system freeze at lib/idr.c:move_to_free_list() when spin_lock_irqsave()
is called on this spinlock.
The patch was tested on Clevo D4J, model D410J laptop, on the following
hardware, without AGP kernel module loaded:
# lspci -s 01:00.0 -n
01:00.0 0300: 1106:3108 (rev 01)
# lspci -s 01:00.0 -v
01:00.0 VGA compatible controller: VIA Technologies, Inc. K8M800/K8N800/K8N800A [S3 UniChrome Pro] (rev 01) (prog-if 00 [VGA controller])
Subsystem: CLEVO/KAPOK Computer Device 4702
Flags: bus master, 66MHz, medium devsel, latency 64, IRQ 16
Memory at f0000000 (32-bit, prefetchable) [size=64M]
Memory at d1000000 (32-bit, non-prefetchable) [size=16M]
Expansion ROM at <unassigned> [disabled]
Capabilities: [60] Power Management version 2
Capabilities: [70] AGP version 3.0
Signed-off-by: Márton Németh <nm127@freemail.hu>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: stable@vger.kernel.org
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-06-11 01:39:55 +04:00
idr_init ( & dev_priv - > object_idr ) ;
2005-11-12 13:52:46 +03:00
dev - > dev_private = ( void * ) dev_priv ;
2007-01-08 13:19:57 +03:00
dev_priv - > chipset = chipset ;
2005-11-12 13:52:46 +03:00
2011-12-19 15:15:29 +04:00
pci_set_master ( dev - > pdev ) ;
2008-11-18 20:30:25 +03:00
ret = drm_vblank_init ( dev , 1 ) ;
if ( ret ) {
2009-03-24 22:23:04 +03:00
kfree ( dev_priv ) ;
2008-11-18 20:30:25 +03:00
return ret ;
}
return 0 ;
2005-11-12 13:52:46 +03:00
}
2007-07-11 09:53:27 +04:00
int via_driver_unload ( struct drm_device * dev )
2005-11-12 13:52:46 +03:00
{
drm_via_private_t * dev_priv = dev - > dev_private ;
2011-10-25 20:00:41 +04:00
idr_destroy ( & dev_priv - > object_idr ) ;
2006-08-07 16:03:22 +04:00
2009-03-24 22:23:04 +03:00
kfree ( dev_priv ) ;
2005-11-12 13:52:46 +03:00
return 0 ;
}