diff options
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 102 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 12 | ||||
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 4 |
5 files changed, 115 insertions, 13 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 292aeba385e0..23e29f3a0c33 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
| @@ -149,12 +149,16 @@ static struct pci_device_id vmw_pci_id_list[] = { | |||
| 149 | }; | 149 | }; |
| 150 | 150 | ||
| 151 | static char *vmw_devname = "vmwgfx"; | 151 | static char *vmw_devname = "vmwgfx"; |
| 152 | static int enable_fbdev; | ||
| 152 | 153 | ||
| 153 | static int vmw_probe(struct pci_dev *, const struct pci_device_id *); | 154 | static int vmw_probe(struct pci_dev *, const struct pci_device_id *); |
| 154 | static void vmw_master_init(struct vmw_master *); | 155 | static void vmw_master_init(struct vmw_master *); |
| 155 | static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, | 156 | static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, |
| 156 | void *ptr); | 157 | void *ptr); |
| 157 | 158 | ||
| 159 | MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev"); | ||
| 160 | module_param_named(enable_fbdev, enable_fbdev, int, 0600); | ||
| 161 | |||
| 158 | static void vmw_print_capabilities(uint32_t capabilities) | 162 | static void vmw_print_capabilities(uint32_t capabilities) |
| 159 | { | 163 | { |
| 160 | DRM_INFO("Capabilities:\n"); | 164 | DRM_INFO("Capabilities:\n"); |
| @@ -192,8 +196,6 @@ static int vmw_request_device(struct vmw_private *dev_priv) | |||
| 192 | { | 196 | { |
| 193 | int ret; | 197 | int ret; |
| 194 | 198 | ||
| 195 | vmw_kms_save_vga(dev_priv); | ||
| 196 | |||
| 197 | ret = vmw_fifo_init(dev_priv, &dev_priv->fifo); | 199 | ret = vmw_fifo_init(dev_priv, &dev_priv->fifo); |
| 198 | if (unlikely(ret != 0)) { | 200 | if (unlikely(ret != 0)) { |
| 199 | DRM_ERROR("Unable to initialize FIFO.\n"); | 201 | DRM_ERROR("Unable to initialize FIFO.\n"); |
| @@ -206,10 +208,36 @@ static int vmw_request_device(struct vmw_private *dev_priv) | |||
| 206 | static void vmw_release_device(struct vmw_private *dev_priv) | 208 | static void vmw_release_device(struct vmw_private *dev_priv) |
| 207 | { | 209 | { |
| 208 | vmw_fifo_release(dev_priv, &dev_priv->fifo); | 210 | vmw_fifo_release(dev_priv, &dev_priv->fifo); |
| 209 | vmw_kms_restore_vga(dev_priv); | 211 | } |
| 212 | |||
| 213 | int vmw_3d_resource_inc(struct vmw_private *dev_priv) | ||
| 214 | { | ||
| 215 | int ret = 0; | ||
| 216 | |||
| 217 | mutex_lock(&dev_priv->release_mutex); | ||
| 218 | if (unlikely(dev_priv->num_3d_resources++ == 0)) { | ||
| 219 | ret = vmw_request_device(dev_priv); | ||
| 220 | if (unlikely(ret != 0)) | ||
| 221 | --dev_priv->num_3d_resources; | ||
| 222 | } | ||
| 223 | mutex_unlock(&dev_priv->release_mutex); | ||
| 224 | return ret; | ||
| 210 | } | 225 | } |
| 211 | 226 | ||
| 212 | 227 | ||
| 228 | void vmw_3d_resource_dec(struct vmw_private *dev_priv) | ||
| 229 | { | ||
| 230 | int32_t n3d; | ||
| 231 | |||
| 232 | mutex_lock(&dev_priv->release_mutex); | ||
| 233 | if (unlikely(--dev_priv->num_3d_resources == 0)) | ||
| 234 | vmw_release_device(dev_priv); | ||
| 235 | n3d = (int32_t) dev_priv->num_3d_resources; | ||
| 236 | mutex_unlock(&dev_priv->release_mutex); | ||
| 237 | |||
| 238 | BUG_ON(n3d < 0); | ||
| 239 | } | ||
| 240 | |||
| 213 | static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | 241 | static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) |
| 214 | { | 242 | { |
| 215 | struct vmw_private *dev_priv; | 243 | struct vmw_private *dev_priv; |
| @@ -228,6 +256,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 228 | dev_priv->last_read_sequence = (uint32_t) -100; | 256 | dev_priv->last_read_sequence = (uint32_t) -100; |
| 229 | mutex_init(&dev_priv->hw_mutex); | 257 | mutex_init(&dev_priv->hw_mutex); |
| 230 | mutex_init(&dev_priv->cmdbuf_mutex); | 258 | mutex_init(&dev_priv->cmdbuf_mutex); |
| 259 | mutex_init(&dev_priv->release_mutex); | ||
| 231 | rwlock_init(&dev_priv->resource_lock); | 260 | rwlock_init(&dev_priv->resource_lock); |
| 232 | idr_init(&dev_priv->context_idr); | 261 | idr_init(&dev_priv->context_idr); |
| 233 | idr_init(&dev_priv->surface_idr); | 262 | idr_init(&dev_priv->surface_idr); |
| @@ -244,6 +273,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 244 | dev_priv->vram_start = pci_resource_start(dev->pdev, 1); | 273 | dev_priv->vram_start = pci_resource_start(dev->pdev, 1); |
| 245 | dev_priv->mmio_start = pci_resource_start(dev->pdev, 2); | 274 | dev_priv->mmio_start = pci_resource_start(dev->pdev, 2); |
| 246 | 275 | ||
| 276 | dev_priv->enable_fb = enable_fbdev; | ||
| 277 | |||
| 247 | mutex_lock(&dev_priv->hw_mutex); | 278 | mutex_lock(&dev_priv->hw_mutex); |
| 248 | 279 | ||
| 249 | vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); | 280 | vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); |
| @@ -369,20 +400,34 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 369 | goto out_no_device; | 400 | goto out_no_device; |
| 370 | } | 401 | } |
| 371 | } | 402 | } |
| 372 | ret = vmw_request_device(dev_priv); | ||
| 373 | if (unlikely(ret != 0)) | ||
| 374 | goto out_no_device; | ||
| 375 | vmw_kms_init(dev_priv); | 403 | vmw_kms_init(dev_priv); |
| 376 | vmw_overlay_init(dev_priv); | 404 | vmw_overlay_init(dev_priv); |
| 377 | vmw_fb_init(dev_priv); | 405 | if (dev_priv->enable_fb) { |
| 406 | ret = vmw_3d_resource_inc(dev_priv); | ||
| 407 | if (unlikely(ret != 0)) | ||
| 408 | goto out_no_fifo; | ||
| 409 | vmw_kms_save_vga(dev_priv); | ||
| 410 | vmw_fb_init(dev_priv); | ||
| 411 | DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? | ||
| 412 | "Detected device 3D availability.\n" : | ||
| 413 | "Detected no device 3D availability.\n"); | ||
| 414 | } else { | ||
| 415 | DRM_INFO("Delayed 3D detection since we're not " | ||
| 416 | "running the device in SVGA mode yet.\n"); | ||
| 417 | } | ||
| 378 | 418 | ||
| 379 | dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier; | 419 | dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier; |
| 380 | register_pm_notifier(&dev_priv->pm_nb); | 420 | register_pm_notifier(&dev_priv->pm_nb); |
| 381 | 421 | ||
| 382 | DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n"); | ||
| 383 | |||
| 384 | return 0; | 422 | return 0; |
| 385 | 423 | ||
| 424 | out_no_fifo: | ||
| 425 | vmw_overlay_close(dev_priv); | ||
| 426 | vmw_kms_close(dev_priv); | ||
| 427 | if (dev_priv->stealth) | ||
| 428 | pci_release_region(dev->pdev, 2); | ||
| 429 | else | ||
| 430 | pci_release_regions(dev->pdev); | ||
| 386 | out_no_device: | 431 | out_no_device: |
| 387 | if (dev_priv->capabilities & SVGA_CAP_IRQMASK) | 432 | if (dev_priv->capabilities & SVGA_CAP_IRQMASK) |
| 388 | drm_irq_uninstall(dev_priv->dev); | 433 | drm_irq_uninstall(dev_priv->dev); |
| @@ -415,10 +460,13 @@ static int vmw_driver_unload(struct drm_device *dev) | |||
| 415 | 460 | ||
| 416 | unregister_pm_notifier(&dev_priv->pm_nb); | 461 | unregister_pm_notifier(&dev_priv->pm_nb); |
| 417 | 462 | ||
| 418 | vmw_fb_close(dev_priv); | 463 | if (dev_priv->enable_fb) { |
| 464 | vmw_fb_close(dev_priv); | ||
| 465 | vmw_kms_restore_vga(dev_priv); | ||
| 466 | vmw_3d_resource_dec(dev_priv); | ||
| 467 | } | ||
| 419 | vmw_kms_close(dev_priv); | 468 | vmw_kms_close(dev_priv); |
| 420 | vmw_overlay_close(dev_priv); | 469 | vmw_overlay_close(dev_priv); |
| 421 | vmw_release_device(dev_priv); | ||
| 422 | if (dev_priv->stealth) | 470 | if (dev_priv->stealth) |
| 423 | pci_release_region(dev->pdev, 2); | 471 | pci_release_region(dev->pdev, 2); |
| 424 | else | 472 | else |
| @@ -589,6 +637,16 @@ static int vmw_master_set(struct drm_device *dev, | |||
| 589 | struct vmw_master *vmaster = vmw_master(file_priv->master); | 637 | struct vmw_master *vmaster = vmw_master(file_priv->master); |
| 590 | int ret = 0; | 638 | int ret = 0; |
| 591 | 639 | ||
| 640 | if (!dev_priv->enable_fb) { | ||
| 641 | ret = vmw_3d_resource_inc(dev_priv); | ||
| 642 | if (unlikely(ret != 0)) | ||
| 643 | return ret; | ||
| 644 | vmw_kms_save_vga(dev_priv); | ||
| 645 | mutex_lock(&dev_priv->hw_mutex); | ||
| 646 | vmw_write(dev_priv, SVGA_REG_TRACES, 0); | ||
| 647 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 648 | } | ||
| 649 | |||
| 592 | if (active) { | 650 | if (active) { |
| 593 | BUG_ON(active != &dev_priv->fbdev_master); | 651 | BUG_ON(active != &dev_priv->fbdev_master); |
| 594 | ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile); | 652 | ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile); |
| @@ -617,7 +675,13 @@ static int vmw_master_set(struct drm_device *dev, | |||
| 617 | return 0; | 675 | return 0; |
| 618 | 676 | ||
| 619 | out_no_active_lock: | 677 | out_no_active_lock: |
| 620 | vmw_release_device(dev_priv); | 678 | if (!dev_priv->enable_fb) { |
| 679 | mutex_lock(&dev_priv->hw_mutex); | ||
| 680 | vmw_write(dev_priv, SVGA_REG_TRACES, 1); | ||
| 681 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 682 | vmw_kms_restore_vga(dev_priv); | ||
| 683 | vmw_3d_resource_dec(dev_priv); | ||
| 684 | } | ||
| 621 | return ret; | 685 | return ret; |
| 622 | } | 686 | } |
| 623 | 687 | ||
| @@ -645,11 +709,23 @@ static void vmw_master_drop(struct drm_device *dev, | |||
| 645 | 709 | ||
| 646 | ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); | 710 | ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); |
| 647 | 711 | ||
| 712 | if (!dev_priv->enable_fb) { | ||
| 713 | ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM); | ||
| 714 | if (unlikely(ret != 0)) | ||
| 715 | DRM_ERROR("Unable to clean VRAM on master drop.\n"); | ||
| 716 | mutex_lock(&dev_priv->hw_mutex); | ||
| 717 | vmw_write(dev_priv, SVGA_REG_TRACES, 1); | ||
| 718 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 719 | vmw_kms_restore_vga(dev_priv); | ||
| 720 | vmw_3d_resource_dec(dev_priv); | ||
| 721 | } | ||
| 722 | |||
| 648 | dev_priv->active_master = &dev_priv->fbdev_master; | 723 | dev_priv->active_master = &dev_priv->fbdev_master; |
| 649 | ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM); | 724 | ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM); |
| 650 | ttm_vt_unlock(&dev_priv->fbdev_master.lock); | 725 | ttm_vt_unlock(&dev_priv->fbdev_master.lock); |
| 651 | 726 | ||
| 652 | vmw_fb_on(dev_priv); | 727 | if (dev_priv->enable_fb) |
| 728 | vmw_fb_on(dev_priv); | ||
| 653 | } | 729 | } |
| 654 | 730 | ||
| 655 | 731 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 429f917b60bf..9142454cc91e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
| @@ -277,6 +277,7 @@ struct vmw_private { | |||
| 277 | 277 | ||
| 278 | bool stealth; | 278 | bool stealth; |
| 279 | bool is_opened; | 279 | bool is_opened; |
| 280 | bool enable_fb; | ||
| 280 | 281 | ||
| 281 | /** | 282 | /** |
| 282 | * Master management. | 283 | * Master management. |
| @@ -285,6 +286,9 @@ struct vmw_private { | |||
| 285 | struct vmw_master *active_master; | 286 | struct vmw_master *active_master; |
| 286 | struct vmw_master fbdev_master; | 287 | struct vmw_master fbdev_master; |
| 287 | struct notifier_block pm_nb; | 288 | struct notifier_block pm_nb; |
| 289 | |||
| 290 | struct mutex release_mutex; | ||
| 291 | uint32_t num_3d_resources; | ||
| 288 | }; | 292 | }; |
| 289 | 293 | ||
| 290 | static inline struct vmw_private *vmw_priv(struct drm_device *dev) | 294 | static inline struct vmw_private *vmw_priv(struct drm_device *dev) |
| @@ -319,6 +323,9 @@ static inline uint32_t vmw_read(struct vmw_private *dev_priv, | |||
| 319 | return val; | 323 | return val; |
| 320 | } | 324 | } |
| 321 | 325 | ||
| 326 | int vmw_3d_resource_inc(struct vmw_private *dev_priv); | ||
| 327 | void vmw_3d_resource_dec(struct vmw_private *dev_priv); | ||
| 328 | |||
| 322 | /** | 329 | /** |
| 323 | * GMR utilities - vmwgfx_gmr.c | 330 | * GMR utilities - vmwgfx_gmr.c |
| 324 | */ | 331 | */ |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index e6a1eb7ea954..0fe31766e4cf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | |||
| @@ -106,6 +106,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 106 | mutex_lock(&dev_priv->hw_mutex); | 106 | mutex_lock(&dev_priv->hw_mutex); |
| 107 | dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE); | 107 | dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE); |
| 108 | dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE); | 108 | dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE); |
| 109 | dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES); | ||
| 109 | vmw_write(dev_priv, SVGA_REG_ENABLE, 1); | 110 | vmw_write(dev_priv, SVGA_REG_ENABLE, 1); |
| 110 | 111 | ||
| 111 | min = 4; | 112 | min = 4; |
| @@ -175,6 +176,8 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 175 | dev_priv->config_done_state); | 176 | dev_priv->config_done_state); |
| 176 | vmw_write(dev_priv, SVGA_REG_ENABLE, | 177 | vmw_write(dev_priv, SVGA_REG_ENABLE, |
| 177 | dev_priv->enable_state); | 178 | dev_priv->enable_state); |
| 179 | vmw_write(dev_priv, SVGA_REG_TRACES, | ||
| 180 | dev_priv->traces_state); | ||
| 178 | 181 | ||
| 179 | mutex_unlock(&dev_priv->hw_mutex); | 182 | mutex_unlock(&dev_priv->hw_mutex); |
| 180 | vmw_fence_queue_takedown(&fifo->fence_queue); | 183 | vmw_fence_queue_takedown(&fifo->fence_queue); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 64d7f47df868..1636e9ba81a1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
| @@ -898,7 +898,19 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv) | |||
| 898 | save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH); | 898 | save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH); |
| 899 | save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT); | 899 | save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT); |
| 900 | vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); | 900 | vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); |
| 901 | if (i == 0 && vmw_priv->num_displays == 1 && | ||
| 902 | save->width == 0 && save->height == 0) { | ||
| 903 | |||
| 904 | /* | ||
| 905 | * It should be fairly safe to assume that these | ||
| 906 | * values are uninitialized. | ||
| 907 | */ | ||
| 908 | |||
| 909 | save->width = vmw_priv->vga_width - save->pos_x; | ||
| 910 | save->height = vmw_priv->vga_height - save->pos_y; | ||
| 911 | } | ||
| 901 | } | 912 | } |
| 913 | |||
| 902 | return 0; | 914 | return 0; |
| 903 | } | 915 | } |
| 904 | 916 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 5f2d5df01e5c..c8c40e9979db 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | |||
| @@ -211,6 +211,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res) | |||
| 211 | cmd->body.cid = cpu_to_le32(res->id); | 211 | cmd->body.cid = cpu_to_le32(res->id); |
| 212 | 212 | ||
| 213 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); | 213 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
| 214 | vmw_3d_resource_dec(dev_priv); | ||
| 214 | } | 215 | } |
| 215 | 216 | ||
| 216 | static int vmw_context_init(struct vmw_private *dev_priv, | 217 | static int vmw_context_init(struct vmw_private *dev_priv, |
| @@ -247,6 +248,7 @@ static int vmw_context_init(struct vmw_private *dev_priv, | |||
| 247 | cmd->body.cid = cpu_to_le32(res->id); | 248 | cmd->body.cid = cpu_to_le32(res->id); |
| 248 | 249 | ||
| 249 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); | 250 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
| 251 | (void) vmw_3d_resource_inc(dev_priv); | ||
| 250 | vmw_resource_activate(res, vmw_hw_context_destroy); | 252 | vmw_resource_activate(res, vmw_hw_context_destroy); |
| 251 | return 0; | 253 | return 0; |
| 252 | } | 254 | } |
| @@ -406,6 +408,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res) | |||
| 406 | cmd->body.sid = cpu_to_le32(res->id); | 408 | cmd->body.sid = cpu_to_le32(res->id); |
| 407 | 409 | ||
| 408 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); | 410 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
| 411 | vmw_3d_resource_dec(dev_priv); | ||
| 409 | } | 412 | } |
| 410 | 413 | ||
| 411 | void vmw_surface_res_free(struct vmw_resource *res) | 414 | void vmw_surface_res_free(struct vmw_resource *res) |
| @@ -473,6 +476,7 @@ int vmw_surface_init(struct vmw_private *dev_priv, | |||
| 473 | } | 476 | } |
| 474 | 477 | ||
| 475 | vmw_fifo_commit(dev_priv, submit_size); | 478 | vmw_fifo_commit(dev_priv, submit_size); |
| 479 | (void) vmw_3d_resource_inc(dev_priv); | ||
| 476 | vmw_resource_activate(res, vmw_hw_surface_destroy); | 480 | vmw_resource_activate(res, vmw_hw_surface_destroy); |
| 477 | return 0; | 481 | return 0; |
| 478 | } | 482 | } |
