diff options
author | YoungJun Cho <yj44.cho@samsung.com> | 2014-05-26 04:17:20 -0400 |
---|---|---|
committer | Inki Dae <daeinki@gmail.com> | 2014-06-01 13:07:14 -0400 |
commit | 220db6fe00136faff129f7a4b610d960dc27b7e7 (patch) | |
tree | f1fe2d46213ba28794d303d0f0a6b6413a3c9c91 /drivers/gpu | |
parent | 075436b08b8c9b30d56af7b7b3306b0a3439d12e (diff) |
drm/exynos: ipp: rearrange c_node->mem_lock using routines
The c_node->mem_list[] should be protected with
c_node->mem_lock.
Signed-off-by: YoungJun Cho <yj44.cho@samsung.com>
Acked-by: Seong-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Tested-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_ipp.c | 86 |
1 files changed, 48 insertions, 38 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index f1c51b4dd56c..4b5afd37eaf9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c | |||
@@ -584,8 +584,6 @@ static int ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node) | |||
584 | struct list_head *head; | 584 | struct list_head *head; |
585 | int ret, i, count[EXYNOS_DRM_OPS_MAX] = { 0, }; | 585 | int ret, i, count[EXYNOS_DRM_OPS_MAX] = { 0, }; |
586 | 586 | ||
587 | mutex_lock(&c_node->mem_lock); | ||
588 | |||
589 | for_each_ipp_ops(i) { | 587 | for_each_ipp_ops(i) { |
590 | /* source/destination memory list */ | 588 | /* source/destination memory list */ |
591 | head = &c_node->mem_list[i]; | 589 | head = &c_node->mem_list[i]; |
@@ -614,8 +612,6 @@ static int ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node) | |||
614 | ret = max(count[EXYNOS_DRM_OPS_SRC], | 612 | ret = max(count[EXYNOS_DRM_OPS_SRC], |
615 | count[EXYNOS_DRM_OPS_DST]); | 613 | count[EXYNOS_DRM_OPS_DST]); |
616 | 614 | ||
617 | mutex_unlock(&c_node->mem_lock); | ||
618 | |||
619 | return ret; | 615 | return ret; |
620 | } | 616 | } |
621 | 617 | ||
@@ -658,16 +654,13 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv, | |||
658 | return -EFAULT; | 654 | return -EFAULT; |
659 | } | 655 | } |
660 | 656 | ||
661 | mutex_lock(&c_node->mem_lock); | ||
662 | |||
663 | DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id); | 657 | DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id); |
664 | 658 | ||
665 | /* get operations callback */ | 659 | /* get operations callback */ |
666 | ops = ippdrv->ops[m_node->ops_id]; | 660 | ops = ippdrv->ops[m_node->ops_id]; |
667 | if (!ops) { | 661 | if (!ops) { |
668 | DRM_ERROR("not support ops.\n"); | 662 | DRM_ERROR("not support ops.\n"); |
669 | ret = -EFAULT; | 663 | return -EFAULT; |
670 | goto err_unlock; | ||
671 | } | 664 | } |
672 | 665 | ||
673 | /* set address and enable irq */ | 666 | /* set address and enable irq */ |
@@ -676,12 +669,10 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv, | |||
676 | m_node->buf_id, IPP_BUF_ENQUEUE); | 669 | m_node->buf_id, IPP_BUF_ENQUEUE); |
677 | if (ret) { | 670 | if (ret) { |
678 | DRM_ERROR("failed to set addr.\n"); | 671 | DRM_ERROR("failed to set addr.\n"); |
679 | goto err_unlock; | 672 | return ret; |
680 | } | 673 | } |
681 | } | 674 | } |
682 | 675 | ||
683 | err_unlock: | ||
684 | mutex_unlock(&c_node->mem_lock); | ||
685 | return ret; | 676 | return ret; |
686 | } | 677 | } |
687 | 678 | ||
@@ -696,11 +687,9 @@ static struct drm_exynos_ipp_mem_node | |||
696 | void *addr; | 687 | void *addr; |
697 | int i; | 688 | int i; |
698 | 689 | ||
699 | mutex_lock(&c_node->mem_lock); | ||
700 | |||
701 | m_node = kzalloc(sizeof(*m_node), GFP_KERNEL); | 690 | m_node = kzalloc(sizeof(*m_node), GFP_KERNEL); |
702 | if (!m_node) | 691 | if (!m_node) |
703 | goto err_unlock; | 692 | return ERR_PTR(-ENOMEM); |
704 | 693 | ||
705 | /* clear base address for error handling */ | 694 | /* clear base address for error handling */ |
706 | memset(&buf_info, 0x0, sizeof(buf_info)); | 695 | memset(&buf_info, 0x0, sizeof(buf_info)); |
@@ -734,15 +723,14 @@ static struct drm_exynos_ipp_mem_node | |||
734 | 723 | ||
735 | m_node->filp = file; | 724 | m_node->filp = file; |
736 | m_node->buf_info = buf_info; | 725 | m_node->buf_info = buf_info; |
726 | mutex_lock(&c_node->mem_lock); | ||
737 | list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]); | 727 | list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]); |
738 | |||
739 | mutex_unlock(&c_node->mem_lock); | 728 | mutex_unlock(&c_node->mem_lock); |
729 | |||
740 | return m_node; | 730 | return m_node; |
741 | 731 | ||
742 | err_clear: | 732 | err_clear: |
743 | kfree(m_node); | 733 | kfree(m_node); |
744 | err_unlock: | ||
745 | mutex_unlock(&c_node->mem_lock); | ||
746 | return ERR_PTR(-EFAULT); | 734 | return ERR_PTR(-EFAULT); |
747 | } | 735 | } |
748 | 736 | ||
@@ -759,13 +747,6 @@ static int ipp_put_mem_node(struct drm_device *drm_dev, | |||
759 | return -EFAULT; | 747 | return -EFAULT; |
760 | } | 748 | } |
761 | 749 | ||
762 | if (list_empty(&m_node->list)) { | ||
763 | DRM_ERROR("empty memory node.\n"); | ||
764 | return -ENOMEM; | ||
765 | } | ||
766 | |||
767 | mutex_lock(&c_node->mem_lock); | ||
768 | |||
769 | DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id); | 750 | DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id); |
770 | 751 | ||
771 | /* put gem buffer */ | 752 | /* put gem buffer */ |
@@ -780,8 +761,6 @@ static int ipp_put_mem_node(struct drm_device *drm_dev, | |||
780 | list_del(&m_node->list); | 761 | list_del(&m_node->list); |
781 | kfree(m_node); | 762 | kfree(m_node); |
782 | 763 | ||
783 | mutex_unlock(&c_node->mem_lock); | ||
784 | |||
785 | return 0; | 764 | return 0; |
786 | } | 765 | } |
787 | 766 | ||
@@ -894,7 +873,9 @@ static int ipp_queue_buf_with_run(struct device *dev, | |||
894 | return 0; | 873 | return 0; |
895 | } | 874 | } |
896 | 875 | ||
876 | mutex_lock(&c_node->mem_lock); | ||
897 | if (!ipp_check_mem_list(c_node)) { | 877 | if (!ipp_check_mem_list(c_node)) { |
878 | mutex_unlock(&c_node->mem_lock); | ||
898 | DRM_DEBUG_KMS("empty memory.\n"); | 879 | DRM_DEBUG_KMS("empty memory.\n"); |
899 | return 0; | 880 | return 0; |
900 | } | 881 | } |
@@ -911,10 +892,12 @@ static int ipp_queue_buf_with_run(struct device *dev, | |||
911 | } else { | 892 | } else { |
912 | ret = ipp_set_mem_node(ippdrv, c_node, m_node); | 893 | ret = ipp_set_mem_node(ippdrv, c_node, m_node); |
913 | if (ret) { | 894 | if (ret) { |
895 | mutex_unlock(&c_node->mem_lock); | ||
914 | DRM_ERROR("failed to set m node.\n"); | 896 | DRM_ERROR("failed to set m node.\n"); |
915 | return ret; | 897 | return ret; |
916 | } | 898 | } |
917 | } | 899 | } |
900 | mutex_unlock(&c_node->mem_lock); | ||
918 | 901 | ||
919 | return 0; | 902 | return 0; |
920 | } | 903 | } |
@@ -926,12 +909,14 @@ static void ipp_clean_queue_buf(struct drm_device *drm_dev, | |||
926 | struct drm_exynos_ipp_mem_node *m_node, *tm_node; | 909 | struct drm_exynos_ipp_mem_node *m_node, *tm_node; |
927 | 910 | ||
928 | /* delete list */ | 911 | /* delete list */ |
912 | mutex_lock(&c_node->mem_lock); | ||
929 | list_for_each_entry_safe(m_node, tm_node, | 913 | list_for_each_entry_safe(m_node, tm_node, |
930 | &c_node->mem_list[qbuf->ops_id], list) { | 914 | &c_node->mem_list[qbuf->ops_id], list) { |
931 | if (m_node->buf_id == qbuf->buf_id && | 915 | if (m_node->buf_id == qbuf->buf_id && |
932 | m_node->ops_id == qbuf->ops_id) | 916 | m_node->ops_id == qbuf->ops_id) |
933 | ipp_put_mem_node(drm_dev, c_node, m_node); | 917 | ipp_put_mem_node(drm_dev, c_node, m_node); |
934 | } | 918 | } |
919 | mutex_unlock(&c_node->mem_lock); | ||
935 | } | 920 | } |
936 | 921 | ||
937 | int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data, | 922 | int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data, |
@@ -1267,9 +1252,11 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv, | |||
1267 | /* store command info in ippdrv */ | 1252 | /* store command info in ippdrv */ |
1268 | ippdrv->c_node = c_node; | 1253 | ippdrv->c_node = c_node; |
1269 | 1254 | ||
1255 | mutex_lock(&c_node->mem_lock); | ||
1270 | if (!ipp_check_mem_list(c_node)) { | 1256 | if (!ipp_check_mem_list(c_node)) { |
1271 | DRM_DEBUG_KMS("empty memory.\n"); | 1257 | DRM_DEBUG_KMS("empty memory.\n"); |
1272 | return -ENOMEM; | 1258 | ret = -ENOMEM; |
1259 | goto err_unlock; | ||
1273 | } | 1260 | } |
1274 | 1261 | ||
1275 | /* set current property in ippdrv */ | 1262 | /* set current property in ippdrv */ |
@@ -1277,7 +1264,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv, | |||
1277 | if (ret) { | 1264 | if (ret) { |
1278 | DRM_ERROR("failed to set property.\n"); | 1265 | DRM_ERROR("failed to set property.\n"); |
1279 | ippdrv->c_node = NULL; | 1266 | ippdrv->c_node = NULL; |
1280 | return ret; | 1267 | goto err_unlock; |
1281 | } | 1268 | } |
1282 | 1269 | ||
1283 | /* check command */ | 1270 | /* check command */ |
@@ -1292,7 +1279,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv, | |||
1292 | if (!m_node) { | 1279 | if (!m_node) { |
1293 | DRM_ERROR("failed to get node.\n"); | 1280 | DRM_ERROR("failed to get node.\n"); |
1294 | ret = -EFAULT; | 1281 | ret = -EFAULT; |
1295 | return ret; | 1282 | goto err_unlock; |
1296 | } | 1283 | } |
1297 | 1284 | ||
1298 | DRM_DEBUG_KMS("m_node[0x%x]\n", (int)m_node); | 1285 | DRM_DEBUG_KMS("m_node[0x%x]\n", (int)m_node); |
@@ -1300,7 +1287,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv, | |||
1300 | ret = ipp_set_mem_node(ippdrv, c_node, m_node); | 1287 | ret = ipp_set_mem_node(ippdrv, c_node, m_node); |
1301 | if (ret) { | 1288 | if (ret) { |
1302 | DRM_ERROR("failed to set m node.\n"); | 1289 | DRM_ERROR("failed to set m node.\n"); |
1303 | return ret; | 1290 | goto err_unlock; |
1304 | } | 1291 | } |
1305 | } | 1292 | } |
1306 | break; | 1293 | break; |
@@ -1312,7 +1299,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv, | |||
1312 | ret = ipp_set_mem_node(ippdrv, c_node, m_node); | 1299 | ret = ipp_set_mem_node(ippdrv, c_node, m_node); |
1313 | if (ret) { | 1300 | if (ret) { |
1314 | DRM_ERROR("failed to set m node.\n"); | 1301 | DRM_ERROR("failed to set m node.\n"); |
1315 | return ret; | 1302 | goto err_unlock; |
1316 | } | 1303 | } |
1317 | } | 1304 | } |
1318 | break; | 1305 | break; |
@@ -1324,14 +1311,16 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv, | |||
1324 | ret = ipp_set_mem_node(ippdrv, c_node, m_node); | 1311 | ret = ipp_set_mem_node(ippdrv, c_node, m_node); |
1325 | if (ret) { | 1312 | if (ret) { |
1326 | DRM_ERROR("failed to set m node.\n"); | 1313 | DRM_ERROR("failed to set m node.\n"); |
1327 | return ret; | 1314 | goto err_unlock; |
1328 | } | 1315 | } |
1329 | } | 1316 | } |
1330 | break; | 1317 | break; |
1331 | default: | 1318 | default: |
1332 | DRM_ERROR("invalid operations.\n"); | 1319 | DRM_ERROR("invalid operations.\n"); |
1333 | return -EINVAL; | 1320 | ret = -EINVAL; |
1321 | goto err_unlock; | ||
1334 | } | 1322 | } |
1323 | mutex_unlock(&c_node->mem_lock); | ||
1335 | 1324 | ||
1336 | DRM_DEBUG_KMS("cmd[%d]\n", property->cmd); | 1325 | DRM_DEBUG_KMS("cmd[%d]\n", property->cmd); |
1337 | 1326 | ||
@@ -1340,11 +1329,17 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv, | |||
1340 | ret = ippdrv->start(ippdrv->dev, property->cmd); | 1329 | ret = ippdrv->start(ippdrv->dev, property->cmd); |
1341 | if (ret) { | 1330 | if (ret) { |
1342 | DRM_ERROR("failed to start ops.\n"); | 1331 | DRM_ERROR("failed to start ops.\n"); |
1332 | ippdrv->c_node = NULL; | ||
1343 | return ret; | 1333 | return ret; |
1344 | } | 1334 | } |
1345 | } | 1335 | } |
1346 | 1336 | ||
1347 | return 0; | 1337 | return 0; |
1338 | |||
1339 | err_unlock: | ||
1340 | mutex_unlock(&c_node->mem_lock); | ||
1341 | ippdrv->c_node = NULL; | ||
1342 | return ret; | ||
1348 | } | 1343 | } |
1349 | 1344 | ||
1350 | static int ipp_stop_property(struct drm_device *drm_dev, | 1345 | static int ipp_stop_property(struct drm_device *drm_dev, |
@@ -1361,6 +1356,8 @@ static int ipp_stop_property(struct drm_device *drm_dev, | |||
1361 | /* put event */ | 1356 | /* put event */ |
1362 | ipp_put_event(c_node, NULL); | 1357 | ipp_put_event(c_node, NULL); |
1363 | 1358 | ||
1359 | mutex_lock(&c_node->mem_lock); | ||
1360 | |||
1364 | /* check command */ | 1361 | /* check command */ |
1365 | switch (property->cmd) { | 1362 | switch (property->cmd) { |
1366 | case IPP_CMD_M2M: | 1363 | case IPP_CMD_M2M: |
@@ -1410,6 +1407,8 @@ static int ipp_stop_property(struct drm_device *drm_dev, | |||
1410 | } | 1407 | } |
1411 | 1408 | ||
1412 | err_clear: | 1409 | err_clear: |
1410 | mutex_unlock(&c_node->mem_lock); | ||
1411 | |||
1413 | /* stop operations */ | 1412 | /* stop operations */ |
1414 | if (ippdrv->stop) | 1413 | if (ippdrv->stop) |
1415 | ippdrv->stop(ippdrv->dev, property->cmd); | 1414 | ippdrv->stop(ippdrv->dev, property->cmd); |
@@ -1521,9 +1520,11 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv, | |||
1521 | return 0; | 1520 | return 0; |
1522 | } | 1521 | } |
1523 | 1522 | ||
1523 | mutex_lock(&c_node->mem_lock); | ||
1524 | if (!ipp_check_mem_list(c_node)) { | 1524 | if (!ipp_check_mem_list(c_node)) { |
1525 | DRM_DEBUG_KMS("empty memory.\n"); | 1525 | DRM_DEBUG_KMS("empty memory.\n"); |
1526 | return 0; | 1526 | ret = 0; |
1527 | goto err_mem_unlock; | ||
1527 | } | 1528 | } |
1528 | 1529 | ||
1529 | /* check command */ | 1530 | /* check command */ |
@@ -1537,7 +1538,8 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv, | |||
1537 | struct drm_exynos_ipp_mem_node, list); | 1538 | struct drm_exynos_ipp_mem_node, list); |
1538 | if (!m_node) { | 1539 | if (!m_node) { |
1539 | DRM_ERROR("empty memory node.\n"); | 1540 | DRM_ERROR("empty memory node.\n"); |
1540 | return -ENOMEM; | 1541 | ret = -ENOMEM; |
1542 | goto err_mem_unlock; | ||
1541 | } | 1543 | } |
1542 | 1544 | ||
1543 | tbuf_id[i] = m_node->buf_id; | 1545 | tbuf_id[i] = m_node->buf_id; |
@@ -1559,7 +1561,8 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv, | |||
1559 | m_node = ipp_find_mem_node(c_node, &qbuf); | 1561 | m_node = ipp_find_mem_node(c_node, &qbuf); |
1560 | if (!m_node) { | 1562 | if (!m_node) { |
1561 | DRM_ERROR("empty memory node.\n"); | 1563 | DRM_ERROR("empty memory node.\n"); |
1562 | return -ENOMEM; | 1564 | ret = -ENOMEM; |
1565 | goto err_mem_unlock; | ||
1563 | } | 1566 | } |
1564 | 1567 | ||
1565 | tbuf_id[EXYNOS_DRM_OPS_DST] = m_node->buf_id; | 1568 | tbuf_id[EXYNOS_DRM_OPS_DST] = m_node->buf_id; |
@@ -1576,7 +1579,8 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv, | |||
1576 | struct drm_exynos_ipp_mem_node, list); | 1579 | struct drm_exynos_ipp_mem_node, list); |
1577 | if (!m_node) { | 1580 | if (!m_node) { |
1578 | DRM_ERROR("empty memory node.\n"); | 1581 | DRM_ERROR("empty memory node.\n"); |
1579 | return -ENOMEM; | 1582 | ret = -ENOMEM; |
1583 | goto err_mem_unlock; | ||
1580 | } | 1584 | } |
1581 | 1585 | ||
1582 | tbuf_id[EXYNOS_DRM_OPS_SRC] = m_node->buf_id; | 1586 | tbuf_id[EXYNOS_DRM_OPS_SRC] = m_node->buf_id; |
@@ -1587,8 +1591,10 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv, | |||
1587 | break; | 1591 | break; |
1588 | default: | 1592 | default: |
1589 | DRM_ERROR("invalid operations.\n"); | 1593 | DRM_ERROR("invalid operations.\n"); |
1590 | return -EINVAL; | 1594 | ret = -EINVAL; |
1595 | goto err_mem_unlock; | ||
1591 | } | 1596 | } |
1597 | mutex_unlock(&c_node->mem_lock); | ||
1592 | 1598 | ||
1593 | if (tbuf_id[EXYNOS_DRM_OPS_DST] != buf_id[EXYNOS_DRM_OPS_DST]) | 1599 | if (tbuf_id[EXYNOS_DRM_OPS_DST] != buf_id[EXYNOS_DRM_OPS_DST]) |
1594 | DRM_ERROR("failed to match buf_id[%d %d]prop_id[%d]\n", | 1600 | DRM_ERROR("failed to match buf_id[%d %d]prop_id[%d]\n", |
@@ -1627,6 +1633,10 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv, | |||
1627 | property->cmd, property->prop_id, tbuf_id[EXYNOS_DRM_OPS_DST]); | 1633 | property->cmd, property->prop_id, tbuf_id[EXYNOS_DRM_OPS_DST]); |
1628 | 1634 | ||
1629 | return 0; | 1635 | return 0; |
1636 | |||
1637 | err_mem_unlock: | ||
1638 | mutex_unlock(&c_node->mem_lock); | ||
1639 | return ret; | ||
1630 | } | 1640 | } |
1631 | 1641 | ||
1632 | void ipp_sched_event(struct work_struct *work) | 1642 | void ipp_sched_event(struct work_struct *work) |