diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 60 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 48 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.c | 52 |
4 files changed, 146 insertions, 30 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index f5a5f18efa5b..4d79dad9d44f 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -830,6 +830,8 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, | |||
830 | * vblank events since the system was booted, including lost events due to | 830 | * vblank events since the system was booted, including lost events due to |
831 | * modesetting activity. | 831 | * modesetting activity. |
832 | * | 832 | * |
833 | * This is the legacy version of drm_crtc_vblank_count(). | ||
834 | * | ||
833 | * Returns: | 835 | * Returns: |
834 | * The software vblank counter. | 836 | * The software vblank counter. |
835 | */ | 837 | */ |
@@ -844,6 +846,25 @@ u32 drm_vblank_count(struct drm_device *dev, int crtc) | |||
844 | EXPORT_SYMBOL(drm_vblank_count); | 846 | EXPORT_SYMBOL(drm_vblank_count); |
845 | 847 | ||
846 | /** | 848 | /** |
849 | * drm_crtc_vblank_count - retrieve "cooked" vblank counter value | ||
850 | * @crtc: which counter to retrieve | ||
851 | * | ||
852 | * Fetches the "cooked" vblank count value that represents the number of | ||
853 | * vblank events since the system was booted, including lost events due to | ||
854 | * modesetting activity. | ||
855 | * | ||
856 | * This is the native KMS version of drm_vblank_count(). | ||
857 | * | ||
858 | * Returns: | ||
859 | * The software vblank counter. | ||
860 | */ | ||
861 | u32 drm_crtc_vblank_count(struct drm_crtc *crtc) | ||
862 | { | ||
863 | return drm_vblank_count(crtc->dev, drm_crtc_index(crtc)); | ||
864 | } | ||
865 | EXPORT_SYMBOL(drm_crtc_vblank_count); | ||
866 | |||
867 | /** | ||
847 | * drm_vblank_count_and_time - retrieve "cooked" vblank counter value | 868 | * drm_vblank_count_and_time - retrieve "cooked" vblank counter value |
848 | * and the system timestamp corresponding to that vblank counter value. | 869 | * and the system timestamp corresponding to that vblank counter value. |
849 | * | 870 | * |
@@ -904,6 +925,8 @@ static void send_vblank_event(struct drm_device *dev, | |||
904 | * | 925 | * |
905 | * Updates sequence # and timestamp on event, and sends it to userspace. | 926 | * Updates sequence # and timestamp on event, and sends it to userspace. |
906 | * Caller must hold event lock. | 927 | * Caller must hold event lock. |
928 | * | ||
929 | * This is the legacy version of drm_crtc_send_vblank_event(). | ||
907 | */ | 930 | */ |
908 | void drm_send_vblank_event(struct drm_device *dev, int crtc, | 931 | void drm_send_vblank_event(struct drm_device *dev, int crtc, |
909 | struct drm_pending_vblank_event *e) | 932 | struct drm_pending_vblank_event *e) |
@@ -923,6 +946,23 @@ void drm_send_vblank_event(struct drm_device *dev, int crtc, | |||
923 | EXPORT_SYMBOL(drm_send_vblank_event); | 946 | EXPORT_SYMBOL(drm_send_vblank_event); |
924 | 947 | ||
925 | /** | 948 | /** |
949 | * drm_crtc_send_vblank_event - helper to send vblank event after pageflip | ||
950 | * @crtc: the source CRTC of the vblank event | ||
951 | * @e: the event to send | ||
952 | * | ||
953 | * Updates sequence # and timestamp on event, and sends it to userspace. | ||
954 | * Caller must hold event lock. | ||
955 | * | ||
956 | * This is the native KMS version of drm_send_vblank_event(). | ||
957 | */ | ||
958 | void drm_crtc_send_vblank_event(struct drm_crtc *crtc, | ||
959 | struct drm_pending_vblank_event *e) | ||
960 | { | ||
961 | drm_send_vblank_event(crtc->dev, drm_crtc_index(crtc), e); | ||
962 | } | ||
963 | EXPORT_SYMBOL(drm_crtc_send_vblank_event); | ||
964 | |||
965 | /** | ||
926 | * drm_vblank_enable - enable the vblank interrupt on a CRTC | 966 | * drm_vblank_enable - enable the vblank interrupt on a CRTC |
927 | * @dev: DRM device | 967 | * @dev: DRM device |
928 | * @crtc: CRTC in question | 968 | * @crtc: CRTC in question |
@@ -1594,6 +1634,8 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc) | |||
1594 | * | 1634 | * |
1595 | * Drivers should call this routine in their vblank interrupt handlers to | 1635 | * Drivers should call this routine in their vblank interrupt handlers to |
1596 | * update the vblank counter and send any signals that may be pending. | 1636 | * update the vblank counter and send any signals that may be pending. |
1637 | * | ||
1638 | * This is the legacy version of drm_crtc_handle_vblank(). | ||
1597 | */ | 1639 | */ |
1598 | bool drm_handle_vblank(struct drm_device *dev, int crtc) | 1640 | bool drm_handle_vblank(struct drm_device *dev, int crtc) |
1599 | { | 1641 | { |
@@ -1670,3 +1712,21 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) | |||
1670 | return true; | 1712 | return true; |
1671 | } | 1713 | } |
1672 | EXPORT_SYMBOL(drm_handle_vblank); | 1714 | EXPORT_SYMBOL(drm_handle_vblank); |
1715 | |||
1716 | /** | ||
1717 | * drm_crtc_handle_vblank - handle a vblank event | ||
1718 | * @crtc: where this event occurred | ||
1719 | * | ||
1720 | * Drivers should call this routine in their vblank interrupt handlers to | ||
1721 | * update the vblank counter and send any signals that may be pending. | ||
1722 | * | ||
1723 | * This is the native KMS version of drm_handle_vblank(). | ||
1724 | * | ||
1725 | * Returns: | ||
1726 | * True if the event was successfully handled, false on failure. | ||
1727 | */ | ||
1728 | bool drm_crtc_handle_vblank(struct drm_crtc *crtc) | ||
1729 | { | ||
1730 | return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc)); | ||
1731 | } | ||
1732 | EXPORT_SYMBOL(drm_crtc_handle_vblank); | ||
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 3367960286a6..978993fa3a36 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -168,7 +168,7 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
168 | const struct tegra_dc_window *window) | 168 | const struct tegra_dc_window *window) |
169 | { | 169 | { |
170 | unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp; | 170 | unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp; |
171 | unsigned long value; | 171 | unsigned long value, flags; |
172 | bool yuv, planar; | 172 | bool yuv, planar; |
173 | 173 | ||
174 | /* | 174 | /* |
@@ -181,6 +181,8 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
181 | else | 181 | else |
182 | bpp = planar ? 1 : 2; | 182 | bpp = planar ? 1 : 2; |
183 | 183 | ||
184 | spin_lock_irqsave(&dc->lock, flags); | ||
185 | |||
184 | value = WINDOW_A_SELECT << index; | 186 | value = WINDOW_A_SELECT << index; |
185 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); | 187 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); |
186 | 188 | ||
@@ -273,6 +275,7 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
273 | 275 | ||
274 | case TEGRA_BO_TILING_MODE_BLOCK: | 276 | case TEGRA_BO_TILING_MODE_BLOCK: |
275 | DRM_ERROR("hardware doesn't support block linear mode\n"); | 277 | DRM_ERROR("hardware doesn't support block linear mode\n"); |
278 | spin_unlock_irqrestore(&dc->lock, flags); | ||
276 | return -EINVAL; | 279 | return -EINVAL; |
277 | } | 280 | } |
278 | 281 | ||
@@ -331,6 +334,8 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
331 | 334 | ||
332 | tegra_dc_window_commit(dc, index); | 335 | tegra_dc_window_commit(dc, index); |
333 | 336 | ||
337 | spin_unlock_irqrestore(&dc->lock, flags); | ||
338 | |||
334 | return 0; | 339 | return 0; |
335 | } | 340 | } |
336 | 341 | ||
@@ -338,11 +343,14 @@ static int tegra_window_plane_disable(struct drm_plane *plane) | |||
338 | { | 343 | { |
339 | struct tegra_dc *dc = to_tegra_dc(plane->crtc); | 344 | struct tegra_dc *dc = to_tegra_dc(plane->crtc); |
340 | struct tegra_plane *p = to_tegra_plane(plane); | 345 | struct tegra_plane *p = to_tegra_plane(plane); |
346 | unsigned long flags; | ||
341 | u32 value; | 347 | u32 value; |
342 | 348 | ||
343 | if (!plane->crtc) | 349 | if (!plane->crtc) |
344 | return 0; | 350 | return 0; |
345 | 351 | ||
352 | spin_lock_irqsave(&dc->lock, flags); | ||
353 | |||
346 | value = WINDOW_A_SELECT << p->index; | 354 | value = WINDOW_A_SELECT << p->index; |
347 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); | 355 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); |
348 | 356 | ||
@@ -352,6 +360,8 @@ static int tegra_window_plane_disable(struct drm_plane *plane) | |||
352 | 360 | ||
353 | tegra_dc_window_commit(dc, p->index); | 361 | tegra_dc_window_commit(dc, p->index); |
354 | 362 | ||
363 | spin_unlock_irqrestore(&dc->lock, flags); | ||
364 | |||
355 | return 0; | 365 | return 0; |
356 | } | 366 | } |
357 | 367 | ||
@@ -699,14 +709,16 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
699 | struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); | 709 | struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); |
700 | unsigned int h_offset = 0, v_offset = 0; | 710 | unsigned int h_offset = 0, v_offset = 0; |
701 | struct tegra_bo_tiling tiling; | 711 | struct tegra_bo_tiling tiling; |
712 | unsigned long value, flags; | ||
702 | unsigned int format, swap; | 713 | unsigned int format, swap; |
703 | unsigned long value; | ||
704 | int err; | 714 | int err; |
705 | 715 | ||
706 | err = tegra_fb_get_tiling(fb, &tiling); | 716 | err = tegra_fb_get_tiling(fb, &tiling); |
707 | if (err < 0) | 717 | if (err < 0) |
708 | return err; | 718 | return err; |
709 | 719 | ||
720 | spin_lock_irqsave(&dc->lock, flags); | ||
721 | |||
710 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); | 722 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); |
711 | 723 | ||
712 | value = fb->offsets[0] + y * fb->pitches[0] + | 724 | value = fb->offsets[0] + y * fb->pitches[0] + |
@@ -752,6 +764,7 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
752 | 764 | ||
753 | case TEGRA_BO_TILING_MODE_BLOCK: | 765 | case TEGRA_BO_TILING_MODE_BLOCK: |
754 | DRM_ERROR("hardware doesn't support block linear mode\n"); | 766 | DRM_ERROR("hardware doesn't support block linear mode\n"); |
767 | spin_unlock_irqrestore(&dc->lock, flags); | ||
755 | return -EINVAL; | 768 | return -EINVAL; |
756 | } | 769 | } |
757 | 770 | ||
@@ -778,6 +791,8 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
778 | tegra_dc_writel(dc, value << 8, DC_CMD_STATE_CONTROL); | 791 | tegra_dc_writel(dc, value << 8, DC_CMD_STATE_CONTROL); |
779 | tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); | 792 | tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); |
780 | 793 | ||
794 | spin_unlock_irqrestore(&dc->lock, flags); | ||
795 | |||
781 | return 0; | 796 | return 0; |
782 | } | 797 | } |
783 | 798 | ||
@@ -814,23 +829,32 @@ static void tegra_dc_finish_page_flip(struct tegra_dc *dc) | |||
814 | unsigned long flags, base; | 829 | unsigned long flags, base; |
815 | struct tegra_bo *bo; | 830 | struct tegra_bo *bo; |
816 | 831 | ||
817 | if (!dc->event) | 832 | spin_lock_irqsave(&drm->event_lock, flags); |
833 | |||
834 | if (!dc->event) { | ||
835 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
818 | return; | 836 | return; |
837 | } | ||
819 | 838 | ||
820 | bo = tegra_fb_get_plane(crtc->primary->fb, 0); | 839 | bo = tegra_fb_get_plane(crtc->primary->fb, 0); |
821 | 840 | ||
841 | spin_lock_irqsave(&dc->lock, flags); | ||
842 | |||
822 | /* check if new start address has been latched */ | 843 | /* check if new start address has been latched */ |
844 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); | ||
823 | tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); | 845 | tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); |
824 | base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR); | 846 | base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR); |
825 | tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); | 847 | tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); |
826 | 848 | ||
849 | spin_unlock_irqrestore(&dc->lock, flags); | ||
850 | |||
827 | if (base == bo->paddr + crtc->primary->fb->offsets[0]) { | 851 | if (base == bo->paddr + crtc->primary->fb->offsets[0]) { |
828 | spin_lock_irqsave(&drm->event_lock, flags); | 852 | drm_crtc_send_vblank_event(crtc, dc->event); |
829 | drm_send_vblank_event(drm, dc->pipe, dc->event); | 853 | drm_crtc_vblank_put(crtc); |
830 | drm_vblank_put(drm, dc->pipe); | ||
831 | dc->event = NULL; | 854 | dc->event = NULL; |
832 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
833 | } | 855 | } |
856 | |||
857 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
834 | } | 858 | } |
835 | 859 | ||
836 | void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) | 860 | void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) |
@@ -843,7 +867,7 @@ void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) | |||
843 | 867 | ||
844 | if (dc->event && dc->event->base.file_priv == file) { | 868 | if (dc->event && dc->event->base.file_priv == file) { |
845 | dc->event->base.destroy(&dc->event->base); | 869 | dc->event->base.destroy(&dc->event->base); |
846 | drm_vblank_put(drm, dc->pipe); | 870 | drm_crtc_vblank_put(crtc); |
847 | dc->event = NULL; | 871 | dc->event = NULL; |
848 | } | 872 | } |
849 | 873 | ||
@@ -853,16 +877,16 @@ void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) | |||
853 | static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 877 | static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
854 | struct drm_pending_vblank_event *event, uint32_t page_flip_flags) | 878 | struct drm_pending_vblank_event *event, uint32_t page_flip_flags) |
855 | { | 879 | { |
880 | unsigned int pipe = drm_crtc_index(crtc); | ||
856 | struct tegra_dc *dc = to_tegra_dc(crtc); | 881 | struct tegra_dc *dc = to_tegra_dc(crtc); |
857 | struct drm_device *drm = crtc->dev; | ||
858 | 882 | ||
859 | if (dc->event) | 883 | if (dc->event) |
860 | return -EBUSY; | 884 | return -EBUSY; |
861 | 885 | ||
862 | if (event) { | 886 | if (event) { |
863 | event->pipe = dc->pipe; | 887 | event->pipe = pipe; |
864 | dc->event = event; | 888 | dc->event = event; |
865 | drm_vblank_get(drm, dc->pipe); | 889 | drm_crtc_vblank_get(crtc); |
866 | } | 890 | } |
867 | 891 | ||
868 | tegra_dc_set_base(dc, 0, 0, fb); | 892 | tegra_dc_set_base(dc, 0, 0, fb); |
@@ -1127,7 +1151,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data) | |||
1127 | /* | 1151 | /* |
1128 | dev_dbg(dc->dev, "%s(): vertical blank\n", __func__); | 1152 | dev_dbg(dc->dev, "%s(): vertical blank\n", __func__); |
1129 | */ | 1153 | */ |
1130 | drm_handle_vblank(dc->base.dev, dc->pipe); | 1154 | drm_crtc_handle_vblank(&dc->base); |
1131 | tegra_dc_finish_page_flip(dc); | 1155 | tegra_dc_finish_page_flip(dc); |
1132 | } | 1156 | } |
1133 | 1157 | ||
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index e549afeece1f..d4f827593dfa 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
@@ -694,24 +694,28 @@ static const struct file_operations tegra_drm_fops = { | |||
694 | .llseek = noop_llseek, | 694 | .llseek = noop_llseek, |
695 | }; | 695 | }; |
696 | 696 | ||
697 | static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe) | 697 | static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, |
698 | unsigned int pipe) | ||
698 | { | 699 | { |
699 | struct drm_crtc *crtc; | 700 | struct drm_crtc *crtc; |
700 | 701 | ||
701 | list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) { | 702 | list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) { |
702 | struct tegra_dc *dc = to_tegra_dc(crtc); | 703 | if (pipe == drm_crtc_index(crtc)) |
703 | |||
704 | if (dc->pipe == pipe) | ||
705 | return crtc; | 704 | return crtc; |
706 | } | 705 | } |
707 | 706 | ||
708 | return NULL; | 707 | return NULL; |
709 | } | 708 | } |
710 | 709 | ||
711 | static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc) | 710 | static u32 tegra_drm_get_vblank_counter(struct drm_device *drm, int pipe) |
712 | { | 711 | { |
712 | struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); | ||
713 | |||
714 | if (!crtc) | ||
715 | return 0; | ||
716 | |||
713 | /* TODO: implement real hardware counter using syncpoints */ | 717 | /* TODO: implement real hardware counter using syncpoints */ |
714 | return drm_vblank_count(dev, crtc); | 718 | return drm_crtc_vblank_count(crtc); |
715 | } | 719 | } |
716 | 720 | ||
717 | static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) | 721 | static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) |
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index da32086cbeaf..8777b7f75791 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c | |||
@@ -216,32 +216,58 @@ static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo) | |||
216 | } | 216 | } |
217 | } | 217 | } |
218 | 218 | ||
219 | static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo, | 219 | static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo) |
220 | size_t size) | ||
221 | { | 220 | { |
221 | struct scatterlist *s; | ||
222 | struct sg_table *sgt; | ||
223 | unsigned int i; | ||
224 | |||
222 | bo->pages = drm_gem_get_pages(&bo->gem); | 225 | bo->pages = drm_gem_get_pages(&bo->gem); |
223 | if (IS_ERR(bo->pages)) | 226 | if (IS_ERR(bo->pages)) |
224 | return PTR_ERR(bo->pages); | 227 | return PTR_ERR(bo->pages); |
225 | 228 | ||
226 | bo->num_pages = size >> PAGE_SHIFT; | 229 | bo->num_pages = bo->gem.size >> PAGE_SHIFT; |
227 | 230 | ||
228 | bo->sgt = drm_prime_pages_to_sg(bo->pages, bo->num_pages); | 231 | sgt = drm_prime_pages_to_sg(bo->pages, bo->num_pages); |
229 | if (IS_ERR(bo->sgt)) { | 232 | if (IS_ERR(sgt)) |
230 | drm_gem_put_pages(&bo->gem, bo->pages, false, false); | 233 | goto put_pages; |
231 | return PTR_ERR(bo->sgt); | 234 | |
235 | /* | ||
236 | * Fake up the SG table so that dma_map_sg() can be used to flush the | ||
237 | * pages associated with it. Note that this relies on the fact that | ||
238 | * the DMA API doesn't hook into IOMMU on Tegra, therefore mapping is | ||
239 | * only cache maintenance. | ||
240 | * | ||
241 | * TODO: Replace this by drm_clflash_sg() once it can be implemented | ||
242 | * without relying on symbols that are not exported. | ||
243 | */ | ||
244 | for_each_sg(sgt->sgl, s, sgt->nents, i) | ||
245 | sg_dma_address(s) = sg_phys(s); | ||
246 | |||
247 | if (dma_map_sg(drm->dev, sgt->sgl, sgt->nents, DMA_TO_DEVICE) == 0) { | ||
248 | sgt = ERR_PTR(-ENOMEM); | ||
249 | goto release_sgt; | ||
232 | } | 250 | } |
233 | 251 | ||
252 | bo->sgt = sgt; | ||
253 | |||
234 | return 0; | 254 | return 0; |
255 | |||
256 | release_sgt: | ||
257 | sg_free_table(sgt); | ||
258 | kfree(sgt); | ||
259 | put_pages: | ||
260 | drm_gem_put_pages(&bo->gem, bo->pages, false, false); | ||
261 | return PTR_ERR(sgt); | ||
235 | } | 262 | } |
236 | 263 | ||
237 | static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo, | 264 | static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo) |
238 | size_t size) | ||
239 | { | 265 | { |
240 | struct tegra_drm *tegra = drm->dev_private; | 266 | struct tegra_drm *tegra = drm->dev_private; |
241 | int err; | 267 | int err; |
242 | 268 | ||
243 | if (tegra->domain) { | 269 | if (tegra->domain) { |
244 | err = tegra_bo_get_pages(drm, bo, size); | 270 | err = tegra_bo_get_pages(drm, bo); |
245 | if (err < 0) | 271 | if (err < 0) |
246 | return err; | 272 | return err; |
247 | 273 | ||
@@ -251,6 +277,8 @@ static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo, | |||
251 | return err; | 277 | return err; |
252 | } | 278 | } |
253 | } else { | 279 | } else { |
280 | size_t size = bo->gem.size; | ||
281 | |||
254 | bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr, | 282 | bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr, |
255 | GFP_KERNEL | __GFP_NOWARN); | 283 | GFP_KERNEL | __GFP_NOWARN); |
256 | if (!bo->vaddr) { | 284 | if (!bo->vaddr) { |
@@ -274,7 +302,7 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, size_t size, | |||
274 | if (IS_ERR(bo)) | 302 | if (IS_ERR(bo)) |
275 | return bo; | 303 | return bo; |
276 | 304 | ||
277 | err = tegra_bo_alloc(drm, bo, size); | 305 | err = tegra_bo_alloc(drm, bo); |
278 | if (err < 0) | 306 | if (err < 0) |
279 | goto release; | 307 | goto release; |
280 | 308 | ||