.. | .. |
---|
26 | 26 | #include "fuc/os.h" |
---|
27 | 27 | |
---|
28 | 28 | #include <core/client.h> |
---|
29 | | -#include <core/option.h> |
---|
30 | 29 | #include <core/firmware.h> |
---|
31 | | -#include <subdev/secboot.h> |
---|
| 30 | +#include <core/option.h> |
---|
| 31 | +#include <subdev/acr.h> |
---|
32 | 32 | #include <subdev/fb.h> |
---|
33 | 33 | #include <subdev/mc.h> |
---|
34 | 34 | #include <subdev/pmu.h> |
---|
.. | .. |
---|
714 | 714 | /******************************************************************************* |
---|
715 | 715 | * PGRAPH engine/subdev functions |
---|
716 | 716 | ******************************************************************************/ |
---|
| 717 | + |
---|
| 718 | +static u32 |
---|
| 719 | +gf100_gr_ctxsw_inst(struct nvkm_gr *gr) |
---|
| 720 | +{ |
---|
| 721 | + return nvkm_rd32(gr->engine.subdev.device, 0x409b00); |
---|
| 722 | +} |
---|
| 723 | + |
---|
| 724 | +static int |
---|
| 725 | +gf100_gr_fecs_ctrl_ctxsw(struct gf100_gr *gr, u32 mthd) |
---|
| 726 | +{ |
---|
| 727 | + struct nvkm_device *device = gr->base.engine.subdev.device; |
---|
| 728 | + |
---|
| 729 | + nvkm_wr32(device, 0x409804, 0xffffffff); |
---|
| 730 | + nvkm_wr32(device, 0x409840, 0xffffffff); |
---|
| 731 | + nvkm_wr32(device, 0x409500, 0xffffffff); |
---|
| 732 | + nvkm_wr32(device, 0x409504, mthd); |
---|
| 733 | + nvkm_msec(device, 2000, |
---|
| 734 | + u32 stat = nvkm_rd32(device, 0x409804); |
---|
| 735 | + if (stat == 0x00000002) |
---|
| 736 | + return -EIO; |
---|
| 737 | + if (stat == 0x00000001) |
---|
| 738 | + return 0; |
---|
| 739 | + ); |
---|
| 740 | + |
---|
| 741 | + return -ETIMEDOUT; |
---|
| 742 | +} |
---|
| 743 | + |
---|
| 744 | +static int |
---|
| 745 | +gf100_gr_fecs_start_ctxsw(struct nvkm_gr *base) |
---|
| 746 | +{ |
---|
| 747 | + struct gf100_gr *gr = gf100_gr(base); |
---|
| 748 | + int ret = 0; |
---|
| 749 | + |
---|
| 750 | + mutex_lock(&gr->fecs.mutex); |
---|
| 751 | + if (!--gr->fecs.disable) { |
---|
| 752 | + if (WARN_ON(ret = gf100_gr_fecs_ctrl_ctxsw(gr, 0x39))) |
---|
| 753 | + gr->fecs.disable++; |
---|
| 754 | + } |
---|
| 755 | + mutex_unlock(&gr->fecs.mutex); |
---|
| 756 | + return ret; |
---|
| 757 | +} |
---|
| 758 | + |
---|
| 759 | +static int |
---|
| 760 | +gf100_gr_fecs_stop_ctxsw(struct nvkm_gr *base) |
---|
| 761 | +{ |
---|
| 762 | + struct gf100_gr *gr = gf100_gr(base); |
---|
| 763 | + int ret = 0; |
---|
| 764 | + |
---|
| 765 | + mutex_lock(&gr->fecs.mutex); |
---|
| 766 | + if (!gr->fecs.disable++) { |
---|
| 767 | + if (WARN_ON(ret = gf100_gr_fecs_ctrl_ctxsw(gr, 0x38))) |
---|
| 768 | + gr->fecs.disable--; |
---|
| 769 | + } |
---|
| 770 | + mutex_unlock(&gr->fecs.mutex); |
---|
| 771 | + return ret; |
---|
| 772 | +} |
---|
| 773 | + |
---|
| 774 | +int |
---|
| 775 | +gf100_gr_fecs_bind_pointer(struct gf100_gr *gr, u32 inst) |
---|
| 776 | +{ |
---|
| 777 | + struct nvkm_device *device = gr->base.engine.subdev.device; |
---|
| 778 | + |
---|
| 779 | + nvkm_wr32(device, 0x409840, 0x00000030); |
---|
| 780 | + nvkm_wr32(device, 0x409500, inst); |
---|
| 781 | + nvkm_wr32(device, 0x409504, 0x00000003); |
---|
| 782 | + nvkm_msec(device, 2000, |
---|
| 783 | + u32 stat = nvkm_rd32(device, 0x409800); |
---|
| 784 | + if (stat & 0x00000020) |
---|
| 785 | + return -EIO; |
---|
| 786 | + if (stat & 0x00000010) |
---|
| 787 | + return 0; |
---|
| 788 | + ); |
---|
| 789 | + |
---|
| 790 | + return -ETIMEDOUT; |
---|
| 791 | +} |
---|
| 792 | + |
---|
| 793 | +static int |
---|
| 794 | +gf100_gr_fecs_set_reglist_virtual_address(struct gf100_gr *gr, u64 addr) |
---|
| 795 | +{ |
---|
| 796 | + struct nvkm_device *device = gr->base.engine.subdev.device; |
---|
| 797 | + |
---|
| 798 | + nvkm_wr32(device, 0x409810, addr >> 8); |
---|
| 799 | + nvkm_wr32(device, 0x409800, 0x00000000); |
---|
| 800 | + nvkm_wr32(device, 0x409500, 0x00000001); |
---|
| 801 | + nvkm_wr32(device, 0x409504, 0x00000032); |
---|
| 802 | + nvkm_msec(device, 2000, |
---|
| 803 | + if (nvkm_rd32(device, 0x409800) == 0x00000001) |
---|
| 804 | + return 0; |
---|
| 805 | + ); |
---|
| 806 | + |
---|
| 807 | + return -ETIMEDOUT; |
---|
| 808 | +} |
---|
| 809 | + |
---|
| 810 | +static int |
---|
| 811 | +gf100_gr_fecs_set_reglist_bind_instance(struct gf100_gr *gr, u32 inst) |
---|
| 812 | +{ |
---|
| 813 | + struct nvkm_device *device = gr->base.engine.subdev.device; |
---|
| 814 | + |
---|
| 815 | + nvkm_wr32(device, 0x409810, inst); |
---|
| 816 | + nvkm_wr32(device, 0x409800, 0x00000000); |
---|
| 817 | + nvkm_wr32(device, 0x409500, 0x00000001); |
---|
| 818 | + nvkm_wr32(device, 0x409504, 0x00000031); |
---|
| 819 | + nvkm_msec(device, 2000, |
---|
| 820 | + if (nvkm_rd32(device, 0x409800) == 0x00000001) |
---|
| 821 | + return 0; |
---|
| 822 | + ); |
---|
| 823 | + |
---|
| 824 | + return -ETIMEDOUT; |
---|
| 825 | +} |
---|
| 826 | + |
---|
| 827 | +static int |
---|
| 828 | +gf100_gr_fecs_discover_reglist_image_size(struct gf100_gr *gr, u32 *psize) |
---|
| 829 | +{ |
---|
| 830 | + struct nvkm_device *device = gr->base.engine.subdev.device; |
---|
| 831 | + |
---|
| 832 | + nvkm_wr32(device, 0x409800, 0x00000000); |
---|
| 833 | + nvkm_wr32(device, 0x409500, 0x00000001); |
---|
| 834 | + nvkm_wr32(device, 0x409504, 0x00000030); |
---|
| 835 | + nvkm_msec(device, 2000, |
---|
| 836 | + if ((*psize = nvkm_rd32(device, 0x409800))) |
---|
| 837 | + return 0; |
---|
| 838 | + ); |
---|
| 839 | + |
---|
| 840 | + return -ETIMEDOUT; |
---|
| 841 | +} |
---|
| 842 | + |
---|
| 843 | +static int |
---|
| 844 | +gf100_gr_fecs_elpg_bind(struct gf100_gr *gr) |
---|
| 845 | +{ |
---|
| 846 | + u32 size; |
---|
| 847 | + int ret; |
---|
| 848 | + |
---|
| 849 | + ret = gf100_gr_fecs_discover_reglist_image_size(gr, &size); |
---|
| 850 | + if (ret) |
---|
| 851 | + return ret; |
---|
| 852 | + |
---|
| 853 | + /*XXX: We need to allocate + map the above into PMU's inst block, |
---|
| 854 | + * which which means we probably need a proper PMU before we |
---|
| 855 | + * even bother. |
---|
| 856 | + */ |
---|
| 857 | + |
---|
| 858 | + ret = gf100_gr_fecs_set_reglist_bind_instance(gr, 0); |
---|
| 859 | + if (ret) |
---|
| 860 | + return ret; |
---|
| 861 | + |
---|
| 862 | + return gf100_gr_fecs_set_reglist_virtual_address(gr, 0); |
---|
| 863 | +} |
---|
| 864 | + |
---|
| 865 | +static int |
---|
| 866 | +gf100_gr_fecs_discover_pm_image_size(struct gf100_gr *gr, u32 *psize) |
---|
| 867 | +{ |
---|
| 868 | + struct nvkm_device *device = gr->base.engine.subdev.device; |
---|
| 869 | + |
---|
| 870 | + nvkm_wr32(device, 0x409840, 0xffffffff); |
---|
| 871 | + nvkm_wr32(device, 0x409500, 0x00000000); |
---|
| 872 | + nvkm_wr32(device, 0x409504, 0x00000025); |
---|
| 873 | + nvkm_msec(device, 2000, |
---|
| 874 | + if ((*psize = nvkm_rd32(device, 0x409800))) |
---|
| 875 | + return 0; |
---|
| 876 | + ); |
---|
| 877 | + |
---|
| 878 | + return -ETIMEDOUT; |
---|
| 879 | +} |
---|
| 880 | + |
---|
| 881 | +static int |
---|
| 882 | +gf100_gr_fecs_discover_zcull_image_size(struct gf100_gr *gr, u32 *psize) |
---|
| 883 | +{ |
---|
| 884 | + struct nvkm_device *device = gr->base.engine.subdev.device; |
---|
| 885 | + |
---|
| 886 | + nvkm_wr32(device, 0x409840, 0xffffffff); |
---|
| 887 | + nvkm_wr32(device, 0x409500, 0x00000000); |
---|
| 888 | + nvkm_wr32(device, 0x409504, 0x00000016); |
---|
| 889 | + nvkm_msec(device, 2000, |
---|
| 890 | + if ((*psize = nvkm_rd32(device, 0x409800))) |
---|
| 891 | + return 0; |
---|
| 892 | + ); |
---|
| 893 | + |
---|
| 894 | + return -ETIMEDOUT; |
---|
| 895 | +} |
---|
| 896 | + |
---|
| 897 | +static int |
---|
| 898 | +gf100_gr_fecs_discover_image_size(struct gf100_gr *gr, u32 *psize) |
---|
| 899 | +{ |
---|
| 900 | + struct nvkm_device *device = gr->base.engine.subdev.device; |
---|
| 901 | + |
---|
| 902 | + nvkm_wr32(device, 0x409840, 0xffffffff); |
---|
| 903 | + nvkm_wr32(device, 0x409500, 0x00000000); |
---|
| 904 | + nvkm_wr32(device, 0x409504, 0x00000010); |
---|
| 905 | + nvkm_msec(device, 2000, |
---|
| 906 | + if ((*psize = nvkm_rd32(device, 0x409800))) |
---|
| 907 | + return 0; |
---|
| 908 | + ); |
---|
| 909 | + |
---|
| 910 | + return -ETIMEDOUT; |
---|
| 911 | +} |
---|
| 912 | + |
---|
| 913 | +static void |
---|
| 914 | +gf100_gr_fecs_set_watchdog_timeout(struct gf100_gr *gr, u32 timeout) |
---|
| 915 | +{ |
---|
| 916 | + struct nvkm_device *device = gr->base.engine.subdev.device; |
---|
| 917 | + |
---|
| 918 | + nvkm_wr32(device, 0x409840, 0xffffffff); |
---|
| 919 | + nvkm_wr32(device, 0x409500, timeout); |
---|
| 920 | + nvkm_wr32(device, 0x409504, 0x00000021); |
---|
| 921 | +} |
---|
717 | 922 | |
---|
718 | 923 | static bool |
---|
719 | 924 | gf100_gr_chsw_load(struct nvkm_gr *base) |
---|
.. | .. |
---|
1431 | 1636 | |
---|
1432 | 1637 | static void |
---|
1433 | 1638 | gf100_gr_init_fw(struct nvkm_falcon *falcon, |
---|
1434 | | - struct gf100_gr_fuc *code, struct gf100_gr_fuc *data) |
---|
| 1639 | + struct nvkm_blob *code, struct nvkm_blob *data) |
---|
1435 | 1640 | { |
---|
1436 | 1641 | nvkm_falcon_load_dmem(falcon, data->data, 0x0, data->size, 0); |
---|
1437 | 1642 | nvkm_falcon_load_imem(falcon, code->data, 0x0, code->size, 0, 0, false); |
---|
.. | .. |
---|
1485 | 1690 | { |
---|
1486 | 1691 | struct nvkm_subdev *subdev = &gr->base.engine.subdev; |
---|
1487 | 1692 | struct nvkm_device *device = subdev->device; |
---|
1488 | | - struct nvkm_secboot *sb = device->secboot; |
---|
1489 | | - u32 secboot_mask = 0; |
---|
| 1693 | + u32 lsf_mask = 0; |
---|
| 1694 | + int ret; |
---|
1490 | 1695 | |
---|
1491 | 1696 | /* load fuc microcode */ |
---|
1492 | 1697 | nvkm_mc_unk260(device, 0); |
---|
1493 | 1698 | |
---|
1494 | 1699 | /* securely-managed falcons must be reset using secure boot */ |
---|
1495 | | - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) |
---|
1496 | | - secboot_mask |= BIT(NVKM_SECBOOT_FALCON_FECS); |
---|
1497 | | - else |
---|
1498 | | - gf100_gr_init_fw(gr->fecs, &gr->fuc409c, &gr->fuc409d); |
---|
1499 | 1700 | |
---|
1500 | | - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) |
---|
1501 | | - secboot_mask |= BIT(NVKM_SECBOOT_FALCON_GPCCS); |
---|
1502 | | - else |
---|
1503 | | - gf100_gr_init_fw(gr->gpccs, &gr->fuc41ac, &gr->fuc41ad); |
---|
| 1701 | + if (!nvkm_acr_managed_falcon(device, NVKM_ACR_LSF_FECS)) { |
---|
| 1702 | + gf100_gr_init_fw(&gr->fecs.falcon, &gr->fecs.inst, |
---|
| 1703 | + &gr->fecs.data); |
---|
| 1704 | + } else { |
---|
| 1705 | + lsf_mask |= BIT(NVKM_ACR_LSF_FECS); |
---|
| 1706 | + } |
---|
1504 | 1707 | |
---|
1505 | | - if (secboot_mask != 0) { |
---|
1506 | | - int ret = nvkm_secboot_reset(sb, secboot_mask); |
---|
| 1708 | + if (!nvkm_acr_managed_falcon(device, NVKM_ACR_LSF_GPCCS)) { |
---|
| 1709 | + gf100_gr_init_fw(&gr->gpccs.falcon, &gr->gpccs.inst, |
---|
| 1710 | + &gr->gpccs.data); |
---|
| 1711 | + } else { |
---|
| 1712 | + lsf_mask |= BIT(NVKM_ACR_LSF_GPCCS); |
---|
| 1713 | + } |
---|
| 1714 | + |
---|
| 1715 | + if (lsf_mask) { |
---|
| 1716 | + ret = nvkm_acr_bootstrap_falcons(device, lsf_mask); |
---|
1507 | 1717 | if (ret) |
---|
1508 | 1718 | return ret; |
---|
1509 | 1719 | } |
---|
.. | .. |
---|
1515 | 1725 | nvkm_wr32(device, 0x41a10c, 0x00000000); |
---|
1516 | 1726 | nvkm_wr32(device, 0x40910c, 0x00000000); |
---|
1517 | 1727 | |
---|
1518 | | - nvkm_falcon_start(gr->gpccs); |
---|
1519 | | - nvkm_falcon_start(gr->fecs); |
---|
| 1728 | + nvkm_falcon_start(&gr->gpccs.falcon); |
---|
| 1729 | + nvkm_falcon_start(&gr->fecs.falcon); |
---|
1520 | 1730 | |
---|
1521 | 1731 | if (nvkm_msec(device, 2000, |
---|
1522 | 1732 | if (nvkm_rd32(device, 0x409800) & 0x00000001) |
---|
.. | .. |
---|
1524 | 1734 | ) < 0) |
---|
1525 | 1735 | return -EBUSY; |
---|
1526 | 1736 | |
---|
1527 | | - nvkm_wr32(device, 0x409840, 0xffffffff); |
---|
1528 | | - nvkm_wr32(device, 0x409500, 0x7fffffff); |
---|
1529 | | - nvkm_wr32(device, 0x409504, 0x00000021); |
---|
| 1737 | + gf100_gr_fecs_set_watchdog_timeout(gr, 0x7fffffff); |
---|
1530 | 1738 | |
---|
1531 | | - nvkm_wr32(device, 0x409840, 0xffffffff); |
---|
1532 | | - nvkm_wr32(device, 0x409500, 0x00000000); |
---|
1533 | | - nvkm_wr32(device, 0x409504, 0x00000010); |
---|
1534 | | - if (nvkm_msec(device, 2000, |
---|
1535 | | - if ((gr->size = nvkm_rd32(device, 0x409800))) |
---|
1536 | | - break; |
---|
1537 | | - ) < 0) |
---|
1538 | | - return -EBUSY; |
---|
| 1739 | + /* Determine how much memory is required to store main context image. */ |
---|
| 1740 | + ret = gf100_gr_fecs_discover_image_size(gr, &gr->size); |
---|
| 1741 | + if (ret) |
---|
| 1742 | + return ret; |
---|
1539 | 1743 | |
---|
1540 | | - nvkm_wr32(device, 0x409840, 0xffffffff); |
---|
1541 | | - nvkm_wr32(device, 0x409500, 0x00000000); |
---|
1542 | | - nvkm_wr32(device, 0x409504, 0x00000016); |
---|
1543 | | - if (nvkm_msec(device, 2000, |
---|
1544 | | - if (nvkm_rd32(device, 0x409800)) |
---|
1545 | | - break; |
---|
1546 | | - ) < 0) |
---|
1547 | | - return -EBUSY; |
---|
| 1744 | + /* Determine how much memory is required to store ZCULL image. */ |
---|
| 1745 | + ret = gf100_gr_fecs_discover_zcull_image_size(gr, &gr->size_zcull); |
---|
| 1746 | + if (ret) |
---|
| 1747 | + return ret; |
---|
1548 | 1748 | |
---|
1549 | | - nvkm_wr32(device, 0x409840, 0xffffffff); |
---|
1550 | | - nvkm_wr32(device, 0x409500, 0x00000000); |
---|
1551 | | - nvkm_wr32(device, 0x409504, 0x00000025); |
---|
1552 | | - if (nvkm_msec(device, 2000, |
---|
1553 | | - if (nvkm_rd32(device, 0x409800)) |
---|
1554 | | - break; |
---|
1555 | | - ) < 0) |
---|
1556 | | - return -EBUSY; |
---|
| 1749 | + /* Determine how much memory is required to store PerfMon image. */ |
---|
| 1750 | + ret = gf100_gr_fecs_discover_pm_image_size(gr, &gr->size_pm); |
---|
| 1751 | + if (ret) |
---|
| 1752 | + return ret; |
---|
1557 | 1753 | |
---|
1558 | | - if (device->chipset >= 0xe0) { |
---|
1559 | | - nvkm_wr32(device, 0x409800, 0x00000000); |
---|
1560 | | - nvkm_wr32(device, 0x409500, 0x00000001); |
---|
1561 | | - nvkm_wr32(device, 0x409504, 0x00000030); |
---|
1562 | | - if (nvkm_msec(device, 2000, |
---|
1563 | | - if (nvkm_rd32(device, 0x409800)) |
---|
1564 | | - break; |
---|
1565 | | - ) < 0) |
---|
1566 | | - return -EBUSY; |
---|
1567 | | - |
---|
1568 | | - nvkm_wr32(device, 0x409810, 0xb00095c8); |
---|
1569 | | - nvkm_wr32(device, 0x409800, 0x00000000); |
---|
1570 | | - nvkm_wr32(device, 0x409500, 0x00000001); |
---|
1571 | | - nvkm_wr32(device, 0x409504, 0x00000031); |
---|
1572 | | - if (nvkm_msec(device, 2000, |
---|
1573 | | - if (nvkm_rd32(device, 0x409800)) |
---|
1574 | | - break; |
---|
1575 | | - ) < 0) |
---|
1576 | | - return -EBUSY; |
---|
1577 | | - |
---|
1578 | | - nvkm_wr32(device, 0x409810, 0x00080420); |
---|
1579 | | - nvkm_wr32(device, 0x409800, 0x00000000); |
---|
1580 | | - nvkm_wr32(device, 0x409500, 0x00000001); |
---|
1581 | | - nvkm_wr32(device, 0x409504, 0x00000032); |
---|
1582 | | - if (nvkm_msec(device, 2000, |
---|
1583 | | - if (nvkm_rd32(device, 0x409800)) |
---|
1584 | | - break; |
---|
1585 | | - ) < 0) |
---|
1586 | | - return -EBUSY; |
---|
1587 | | - |
---|
1588 | | - nvkm_wr32(device, 0x409614, 0x00000070); |
---|
1589 | | - nvkm_wr32(device, 0x409614, 0x00000770); |
---|
1590 | | - nvkm_wr32(device, 0x40802c, 0x00000001); |
---|
| 1754 | + /*XXX: We (likely) require PMU support to even bother with this. |
---|
| 1755 | + * |
---|
| 1756 | + * Also, it seems like not all GPUs support ELPG. Traces I |
---|
| 1757 | + * have here show RM enabling it on Kepler/Turing, but none |
---|
| 1758 | + * of the GPUs between those. NVGPU decides this by PCIID. |
---|
| 1759 | + */ |
---|
| 1760 | + if (0) { |
---|
| 1761 | + ret = gf100_gr_fecs_elpg_bind(gr); |
---|
| 1762 | + if (ret) |
---|
| 1763 | + return ret; |
---|
1591 | 1764 | } |
---|
1592 | 1765 | |
---|
| 1766 | + /* Generate golden context image. */ |
---|
1593 | 1767 | if (gr->data == NULL) { |
---|
1594 | 1768 | int ret = gf100_grctx_generate(gr); |
---|
1595 | 1769 | if (ret) { |
---|
.. | .. |
---|
1614 | 1788 | |
---|
1615 | 1789 | /* load HUB microcode */ |
---|
1616 | 1790 | nvkm_mc_unk260(device, 0); |
---|
1617 | | - nvkm_falcon_load_dmem(gr->fecs, gr->func->fecs.ucode->data.data, 0x0, |
---|
| 1791 | + nvkm_falcon_load_dmem(&gr->fecs.falcon, |
---|
| 1792 | + gr->func->fecs.ucode->data.data, 0x0, |
---|
1618 | 1793 | gr->func->fecs.ucode->data.size, 0); |
---|
1619 | | - nvkm_falcon_load_imem(gr->fecs, gr->func->fecs.ucode->code.data, 0x0, |
---|
| 1794 | + nvkm_falcon_load_imem(&gr->fecs.falcon, |
---|
| 1795 | + gr->func->fecs.ucode->code.data, 0x0, |
---|
1620 | 1796 | gr->func->fecs.ucode->code.size, 0, 0, false); |
---|
1621 | 1797 | |
---|
1622 | 1798 | /* load GPC microcode */ |
---|
1623 | | - nvkm_falcon_load_dmem(gr->gpccs, gr->func->gpccs.ucode->data.data, 0x0, |
---|
| 1799 | + nvkm_falcon_load_dmem(&gr->gpccs.falcon, |
---|
| 1800 | + gr->func->gpccs.ucode->data.data, 0x0, |
---|
1624 | 1801 | gr->func->gpccs.ucode->data.size, 0); |
---|
1625 | | - nvkm_falcon_load_imem(gr->gpccs, gr->func->gpccs.ucode->code.data, 0x0, |
---|
| 1802 | + nvkm_falcon_load_imem(&gr->gpccs.falcon, |
---|
| 1803 | + gr->func->gpccs.ucode->code.data, 0x0, |
---|
1626 | 1804 | gr->func->gpccs.ucode->code.size, 0, 0, false); |
---|
1627 | 1805 | nvkm_mc_unk260(device, 1); |
---|
1628 | 1806 | |
---|
.. | .. |
---|
1767 | 1945 | struct nvkm_subdev *subdev = &gr->base.engine.subdev; |
---|
1768 | 1946 | struct nvkm_device *device = subdev->device; |
---|
1769 | 1947 | int i, j; |
---|
1770 | | - int ret; |
---|
1771 | | - |
---|
1772 | | - ret = nvkm_falcon_v1_new(subdev, "FECS", 0x409000, &gr->fecs); |
---|
1773 | | - if (ret) |
---|
1774 | | - return ret; |
---|
1775 | | - |
---|
1776 | | - ret = nvkm_falcon_v1_new(subdev, "GPCCS", 0x41a000, &gr->gpccs); |
---|
1777 | | - if (ret) |
---|
1778 | | - return ret; |
---|
1779 | 1948 | |
---|
1780 | 1949 | nvkm_pmu_pgob(device->pmu, false); |
---|
1781 | 1950 | |
---|
.. | .. |
---|
1812 | 1981 | { |
---|
1813 | 1982 | struct gf100_gr *gr = gf100_gr(base); |
---|
1814 | 1983 | struct nvkm_subdev *subdev = &base->engine.subdev; |
---|
| 1984 | + struct nvkm_device *device = subdev->device; |
---|
| 1985 | + bool reset = device->chipset == 0x137 || device->chipset == 0x138; |
---|
1815 | 1986 | u32 ret; |
---|
| 1987 | + |
---|
| 1988 | + /* On certain GP107/GP108 boards, we trigger a weird issue where |
---|
| 1989 | + * GR will stop responding to PRI accesses after we've asked the |
---|
| 1990 | + * SEC2 RTOS to boot the GR falcons. This happens with far more |
---|
| 1991 | + * frequency when cold-booting a board (ie. returning from D3). |
---|
| 1992 | + * |
---|
| 1993 | + * The root cause for this is not known and has proven difficult |
---|
| 1994 | + * to isolate, with many avenues being dead-ends. |
---|
| 1995 | + * |
---|
| 1996 | + * A workaround was discovered by Karol, whereby putting GR into |
---|
| 1997 | + * reset for an extended period right before initialisation |
---|
| 1998 | + * prevents the problem from occuring. |
---|
| 1999 | + * |
---|
| 2000 | + * XXX: As RM does not require any such workaround, this is more |
---|
| 2001 | + * of a hack than a true fix. |
---|
| 2002 | + */ |
---|
| 2003 | + reset = nvkm_boolopt(device->cfgopt, "NvGrResetWar", reset); |
---|
| 2004 | + if (reset) { |
---|
| 2005 | + nvkm_mask(device, 0x000200, 0x00001000, 0x00000000); |
---|
| 2006 | + nvkm_rd32(device, 0x000200); |
---|
| 2007 | + msleep(50); |
---|
| 2008 | + nvkm_mask(device, 0x000200, 0x00001000, 0x00001000); |
---|
| 2009 | + nvkm_rd32(device, 0x000200); |
---|
| 2010 | + } |
---|
1816 | 2011 | |
---|
1817 | 2012 | nvkm_pmu_pgob(gr->base.engine.subdev.device->pmu, false); |
---|
1818 | 2013 | |
---|
1819 | | - ret = nvkm_falcon_get(gr->fecs, subdev); |
---|
| 2014 | + ret = nvkm_falcon_get(&gr->fecs.falcon, subdev); |
---|
1820 | 2015 | if (ret) |
---|
1821 | 2016 | return ret; |
---|
1822 | 2017 | |
---|
1823 | | - ret = nvkm_falcon_get(gr->gpccs, subdev); |
---|
| 2018 | + ret = nvkm_falcon_get(&gr->gpccs.falcon, subdev); |
---|
1824 | 2019 | if (ret) |
---|
1825 | 2020 | return ret; |
---|
1826 | 2021 | |
---|
.. | .. |
---|
1828 | 2023 | } |
---|
1829 | 2024 | |
---|
1830 | 2025 | static int |
---|
1831 | | -gf100_gr_fini_(struct nvkm_gr *base, bool suspend) |
---|
| 2026 | +gf100_gr_fini(struct nvkm_gr *base, bool suspend) |
---|
1832 | 2027 | { |
---|
1833 | 2028 | struct gf100_gr *gr = gf100_gr(base); |
---|
1834 | 2029 | struct nvkm_subdev *subdev = &gr->base.engine.subdev; |
---|
1835 | | - nvkm_falcon_put(gr->gpccs, subdev); |
---|
1836 | | - nvkm_falcon_put(gr->fecs, subdev); |
---|
| 2030 | + nvkm_falcon_put(&gr->gpccs.falcon, subdev); |
---|
| 2031 | + nvkm_falcon_put(&gr->fecs.falcon, subdev); |
---|
1837 | 2032 | return 0; |
---|
1838 | 2033 | } |
---|
1839 | 2034 | |
---|
1840 | | -void |
---|
1841 | | -gf100_gr_dtor_fw(struct gf100_gr_fuc *fuc) |
---|
1842 | | -{ |
---|
1843 | | - kfree(fuc->data); |
---|
1844 | | - fuc->data = NULL; |
---|
1845 | | -} |
---|
1846 | | - |
---|
1847 | | -static void |
---|
1848 | | -gf100_gr_dtor_init(struct gf100_gr_pack *pack) |
---|
1849 | | -{ |
---|
1850 | | - vfree(pack); |
---|
1851 | | -} |
---|
1852 | | - |
---|
1853 | | -void * |
---|
| 2035 | +static void * |
---|
1854 | 2036 | gf100_gr_dtor(struct nvkm_gr *base) |
---|
1855 | 2037 | { |
---|
1856 | 2038 | struct gf100_gr *gr = gf100_gr(base); |
---|
1857 | 2039 | |
---|
1858 | | - if (gr->func->dtor) |
---|
1859 | | - gr->func->dtor(gr); |
---|
1860 | 2040 | kfree(gr->data); |
---|
1861 | 2041 | |
---|
1862 | | - nvkm_falcon_del(&gr->gpccs); |
---|
1863 | | - nvkm_falcon_del(&gr->fecs); |
---|
| 2042 | + nvkm_falcon_dtor(&gr->gpccs.falcon); |
---|
| 2043 | + nvkm_falcon_dtor(&gr->fecs.falcon); |
---|
1864 | 2044 | |
---|
1865 | | - gf100_gr_dtor_fw(&gr->fuc409c); |
---|
1866 | | - gf100_gr_dtor_fw(&gr->fuc409d); |
---|
1867 | | - gf100_gr_dtor_fw(&gr->fuc41ac); |
---|
1868 | | - gf100_gr_dtor_fw(&gr->fuc41ad); |
---|
| 2045 | + nvkm_blob_dtor(&gr->fecs.inst); |
---|
| 2046 | + nvkm_blob_dtor(&gr->fecs.data); |
---|
| 2047 | + nvkm_blob_dtor(&gr->gpccs.inst); |
---|
| 2048 | + nvkm_blob_dtor(&gr->gpccs.data); |
---|
1869 | 2049 | |
---|
1870 | | - gf100_gr_dtor_init(gr->fuc_bundle); |
---|
1871 | | - gf100_gr_dtor_init(gr->fuc_method); |
---|
1872 | | - gf100_gr_dtor_init(gr->fuc_sw_ctx); |
---|
1873 | | - gf100_gr_dtor_init(gr->fuc_sw_nonctx); |
---|
| 2050 | + vfree(gr->bundle); |
---|
| 2051 | + vfree(gr->method); |
---|
| 2052 | + vfree(gr->sw_ctx); |
---|
| 2053 | + vfree(gr->sw_nonctx); |
---|
1874 | 2054 | |
---|
1875 | 2055 | return gr; |
---|
1876 | 2056 | } |
---|
.. | .. |
---|
1880 | 2060 | .dtor = gf100_gr_dtor, |
---|
1881 | 2061 | .oneinit = gf100_gr_oneinit, |
---|
1882 | 2062 | .init = gf100_gr_init_, |
---|
1883 | | - .fini = gf100_gr_fini_, |
---|
| 2063 | + .fini = gf100_gr_fini, |
---|
1884 | 2064 | .intr = gf100_gr_intr, |
---|
1885 | 2065 | .units = gf100_gr_units, |
---|
1886 | 2066 | .chan_new = gf100_gr_chan_new, |
---|
1887 | 2067 | .object_get = gf100_gr_object_get, |
---|
1888 | 2068 | .chsw_load = gf100_gr_chsw_load, |
---|
| 2069 | + .ctxsw.pause = gf100_gr_fecs_stop_ctxsw, |
---|
| 2070 | + .ctxsw.resume = gf100_gr_fecs_start_ctxsw, |
---|
| 2071 | + .ctxsw.inst = gf100_gr_ctxsw_inst, |
---|
| 2072 | +}; |
---|
| 2073 | + |
---|
| 2074 | +static const struct nvkm_falcon_func |
---|
| 2075 | +gf100_gr_flcn = { |
---|
| 2076 | + .fbif = 0x600, |
---|
| 2077 | + .load_imem = nvkm_falcon_v1_load_imem, |
---|
| 2078 | + .load_dmem = nvkm_falcon_v1_load_dmem, |
---|
| 2079 | + .read_dmem = nvkm_falcon_v1_read_dmem, |
---|
| 2080 | + .bind_context = nvkm_falcon_v1_bind_context, |
---|
| 2081 | + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, |
---|
| 2082 | + .clear_interrupt = nvkm_falcon_v1_clear_interrupt, |
---|
| 2083 | + .set_start_addr = nvkm_falcon_v1_set_start_addr, |
---|
| 2084 | + .start = nvkm_falcon_v1_start, |
---|
| 2085 | + .enable = nvkm_falcon_v1_enable, |
---|
| 2086 | + .disable = nvkm_falcon_v1_disable, |
---|
1889 | 2087 | }; |
---|
1890 | 2088 | |
---|
1891 | 2089 | int |
---|
1892 | | -gf100_gr_ctor_fw_legacy(struct gf100_gr *gr, const char *fwname, |
---|
1893 | | - struct gf100_gr_fuc *fuc, int ret) |
---|
1894 | | -{ |
---|
1895 | | - struct nvkm_subdev *subdev = &gr->base.engine.subdev; |
---|
1896 | | - struct nvkm_device *device = subdev->device; |
---|
1897 | | - const struct firmware *fw; |
---|
1898 | | - char f[32]; |
---|
1899 | | - |
---|
1900 | | - /* see if this firmware has a legacy path */ |
---|
1901 | | - if (!strcmp(fwname, "fecs_inst")) |
---|
1902 | | - fwname = "fuc409c"; |
---|
1903 | | - else if (!strcmp(fwname, "fecs_data")) |
---|
1904 | | - fwname = "fuc409d"; |
---|
1905 | | - else if (!strcmp(fwname, "gpccs_inst")) |
---|
1906 | | - fwname = "fuc41ac"; |
---|
1907 | | - else if (!strcmp(fwname, "gpccs_data")) |
---|
1908 | | - fwname = "fuc41ad"; |
---|
1909 | | - else { |
---|
1910 | | - /* nope, let's just return the error we got */ |
---|
1911 | | - nvkm_error(subdev, "failed to load %s\n", fwname); |
---|
1912 | | - return ret; |
---|
1913 | | - } |
---|
1914 | | - |
---|
1915 | | - /* yes, try to load from the legacy path */ |
---|
1916 | | - nvkm_debug(subdev, "%s: falling back to legacy path\n", fwname); |
---|
1917 | | - |
---|
1918 | | - snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname); |
---|
1919 | | - ret = request_firmware(&fw, f, device->dev); |
---|
1920 | | - if (ret) { |
---|
1921 | | - snprintf(f, sizeof(f), "nouveau/%s", fwname); |
---|
1922 | | - ret = request_firmware(&fw, f, device->dev); |
---|
1923 | | - if (ret) { |
---|
1924 | | - nvkm_error(subdev, "failed to load %s\n", fwname); |
---|
1925 | | - return ret; |
---|
1926 | | - } |
---|
1927 | | - } |
---|
1928 | | - |
---|
1929 | | - fuc->size = fw->size; |
---|
1930 | | - fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); |
---|
1931 | | - release_firmware(fw); |
---|
1932 | | - return (fuc->data != NULL) ? 0 : -ENOMEM; |
---|
1933 | | -} |
---|
1934 | | - |
---|
1935 | | -int |
---|
1936 | | -gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname, |
---|
1937 | | - struct gf100_gr_fuc *fuc) |
---|
1938 | | -{ |
---|
1939 | | - struct nvkm_subdev *subdev = &gr->base.engine.subdev; |
---|
1940 | | - struct nvkm_device *device = subdev->device; |
---|
1941 | | - const struct firmware *fw; |
---|
1942 | | - int ret; |
---|
1943 | | - |
---|
1944 | | - ret = nvkm_firmware_get(device, fwname, &fw); |
---|
1945 | | - if (ret) { |
---|
1946 | | - ret = gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret); |
---|
1947 | | - if (ret) |
---|
1948 | | - return -ENODEV; |
---|
1949 | | - return 0; |
---|
1950 | | - } |
---|
1951 | | - |
---|
1952 | | - fuc->size = fw->size; |
---|
1953 | | - fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); |
---|
1954 | | - nvkm_firmware_put(fw); |
---|
1955 | | - return (fuc->data != NULL) ? 0 : -ENOMEM; |
---|
1956 | | -} |
---|
1957 | | - |
---|
1958 | | -int |
---|
1959 | | -gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device, |
---|
1960 | | - int index, struct gf100_gr *gr) |
---|
1961 | | -{ |
---|
1962 | | - gr->func = func; |
---|
1963 | | - gr->firmware = nvkm_boolopt(device->cfgopt, "NvGrUseFW", |
---|
1964 | | - func->fecs.ucode == NULL); |
---|
1965 | | - |
---|
1966 | | - return nvkm_gr_ctor(&gf100_gr_, device, index, |
---|
1967 | | - gr->firmware || func->fecs.ucode != NULL, |
---|
1968 | | - &gr->base); |
---|
1969 | | -} |
---|
1970 | | - |
---|
1971 | | -int |
---|
1972 | | -gf100_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, |
---|
1973 | | - int index, struct nvkm_gr **pgr) |
---|
| 2090 | +gf100_gr_new_(const struct gf100_gr_fwif *fwif, |
---|
| 2091 | + struct nvkm_device *device, int index, struct nvkm_gr **pgr) |
---|
1974 | 2092 | { |
---|
1975 | 2093 | struct gf100_gr *gr; |
---|
1976 | 2094 | int ret; |
---|
.. | .. |
---|
1979 | 2097 | return -ENOMEM; |
---|
1980 | 2098 | *pgr = &gr->base; |
---|
1981 | 2099 | |
---|
1982 | | - ret = gf100_gr_ctor(func, device, index, gr); |
---|
| 2100 | + ret = nvkm_gr_ctor(&gf100_gr_, device, index, true, &gr->base); |
---|
1983 | 2101 | if (ret) |
---|
1984 | 2102 | return ret; |
---|
1985 | 2103 | |
---|
1986 | | - if (gr->firmware) { |
---|
1987 | | - if (gf100_gr_ctor_fw(gr, "fecs_inst", &gr->fuc409c) || |
---|
1988 | | - gf100_gr_ctor_fw(gr, "fecs_data", &gr->fuc409d) || |
---|
1989 | | - gf100_gr_ctor_fw(gr, "gpccs_inst", &gr->fuc41ac) || |
---|
1990 | | - gf100_gr_ctor_fw(gr, "gpccs_data", &gr->fuc41ad)) |
---|
1991 | | - return -ENODEV; |
---|
1992 | | - } |
---|
| 2104 | + fwif = nvkm_firmware_load(&gr->base.engine.subdev, fwif, "Gr", gr); |
---|
| 2105 | + if (IS_ERR(fwif)) |
---|
| 2106 | + return PTR_ERR(fwif); |
---|
| 2107 | + |
---|
| 2108 | + gr->func = fwif->func; |
---|
| 2109 | + |
---|
| 2110 | + ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev, |
---|
| 2111 | + "fecs", 0x409000, &gr->fecs.falcon); |
---|
| 2112 | + if (ret) |
---|
| 2113 | + return ret; |
---|
| 2114 | + |
---|
| 2115 | + mutex_init(&gr->fecs.mutex); |
---|
| 2116 | + |
---|
| 2117 | + ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev, |
---|
| 2118 | + "gpccs", 0x41a000, &gr->gpccs.falcon); |
---|
| 2119 | + if (ret) |
---|
| 2120 | + return ret; |
---|
1993 | 2121 | |
---|
1994 | 2122 | return 0; |
---|
| 2123 | +} |
---|
| 2124 | + |
---|
| 2125 | +void |
---|
| 2126 | +gf100_gr_init_num_tpc_per_gpc(struct gf100_gr *gr, bool pd, bool ds) |
---|
| 2127 | +{ |
---|
| 2128 | + struct nvkm_device *device = gr->base.engine.subdev.device; |
---|
| 2129 | + int gpc, i, j; |
---|
| 2130 | + u32 data; |
---|
| 2131 | + |
---|
| 2132 | + for (gpc = 0, i = 0; i < 4; i++) { |
---|
| 2133 | + for (data = 0, j = 0; j < 8 && gpc < gr->gpc_nr; j++, gpc++) |
---|
| 2134 | + data |= gr->tpc_nr[gpc] << (j * 4); |
---|
| 2135 | + if (pd) |
---|
| 2136 | + nvkm_wr32(device, 0x406028 + (i * 4), data); |
---|
| 2137 | + if (ds) |
---|
| 2138 | + nvkm_wr32(device, 0x405870 + (i * 4), data); |
---|
| 2139 | + } |
---|
1995 | 2140 | } |
---|
1996 | 2141 | |
---|
1997 | 2142 | void |
---|
.. | .. |
---|
2118 | 2263 | |
---|
2119 | 2264 | gr->func->init_gpc_mmu(gr); |
---|
2120 | 2265 | |
---|
2121 | | - if (gr->fuc_sw_nonctx) |
---|
2122 | | - gf100_gr_mmio(gr, gr->fuc_sw_nonctx); |
---|
| 2266 | + if (gr->sw_nonctx) |
---|
| 2267 | + gf100_gr_mmio(gr, gr->sw_nonctx); |
---|
2123 | 2268 | else |
---|
2124 | 2269 | gf100_gr_mmio(gr, gr->func->mmio); |
---|
2125 | 2270 | |
---|
.. | .. |
---|
2143 | 2288 | gr->func->init_bios_2(gr); |
---|
2144 | 2289 | if (gr->func->init_swdx_pes_mask) |
---|
2145 | 2290 | gr->func->init_swdx_pes_mask(gr); |
---|
| 2291 | + if (gr->func->init_fs) |
---|
| 2292 | + gr->func->init_fs(gr); |
---|
2146 | 2293 | |
---|
2147 | 2294 | nvkm_wr32(device, 0x400500, 0x00010001); |
---|
2148 | 2295 | |
---|
.. | .. |
---|
2161 | 2308 | if (gr->func->init_40601c) |
---|
2162 | 2309 | gr->func->init_40601c(gr); |
---|
2163 | 2310 | |
---|
2164 | | - nvkm_wr32(device, 0x404490, 0xc0000000); |
---|
2165 | 2311 | nvkm_wr32(device, 0x406018, 0xc0000000); |
---|
| 2312 | + nvkm_wr32(device, 0x404490, 0xc0000000); |
---|
2166 | 2313 | |
---|
2167 | 2314 | if (gr->func->init_sked_hww_esr) |
---|
2168 | 2315 | gr->func->init_sked_hww_esr(gr); |
---|
.. | .. |
---|
2277 | 2424 | }; |
---|
2278 | 2425 | |
---|
2279 | 2426 | int |
---|
| 2427 | +gf100_gr_nofw(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) |
---|
| 2428 | +{ |
---|
| 2429 | + gr->firmware = false; |
---|
| 2430 | + return 0; |
---|
| 2431 | +} |
---|
| 2432 | + |
---|
| 2433 | +static int |
---|
| 2434 | +gf100_gr_load_fw(struct gf100_gr *gr, const char *name, |
---|
| 2435 | + struct nvkm_blob *blob) |
---|
| 2436 | +{ |
---|
| 2437 | + struct nvkm_subdev *subdev = &gr->base.engine.subdev; |
---|
| 2438 | + struct nvkm_device *device = subdev->device; |
---|
| 2439 | + const struct firmware *fw; |
---|
| 2440 | + char f[32]; |
---|
| 2441 | + int ret; |
---|
| 2442 | + |
---|
| 2443 | + snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, name); |
---|
| 2444 | + ret = request_firmware(&fw, f, device->dev); |
---|
| 2445 | + if (ret) { |
---|
| 2446 | + snprintf(f, sizeof(f), "nouveau/%s", name); |
---|
| 2447 | + ret = request_firmware(&fw, f, device->dev); |
---|
| 2448 | + if (ret) { |
---|
| 2449 | + nvkm_error(subdev, "failed to load %s\n", name); |
---|
| 2450 | + return ret; |
---|
| 2451 | + } |
---|
| 2452 | + } |
---|
| 2453 | + |
---|
| 2454 | + blob->size = fw->size; |
---|
| 2455 | + blob->data = kmemdup(fw->data, blob->size, GFP_KERNEL); |
---|
| 2456 | + release_firmware(fw); |
---|
| 2457 | + return (blob->data != NULL) ? 0 : -ENOMEM; |
---|
| 2458 | +} |
---|
| 2459 | + |
---|
| 2460 | +int |
---|
| 2461 | +gf100_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) |
---|
| 2462 | +{ |
---|
| 2463 | + struct nvkm_device *device = gr->base.engine.subdev.device; |
---|
| 2464 | + |
---|
| 2465 | + if (!nvkm_boolopt(device->cfgopt, "NvGrUseFW", false)) |
---|
| 2466 | + return -EINVAL; |
---|
| 2467 | + |
---|
| 2468 | + if (gf100_gr_load_fw(gr, "fuc409c", &gr->fecs.inst) || |
---|
| 2469 | + gf100_gr_load_fw(gr, "fuc409d", &gr->fecs.data) || |
---|
| 2470 | + gf100_gr_load_fw(gr, "fuc41ac", &gr->gpccs.inst) || |
---|
| 2471 | + gf100_gr_load_fw(gr, "fuc41ad", &gr->gpccs.data)) |
---|
| 2472 | + return -ENOENT; |
---|
| 2473 | + |
---|
| 2474 | + gr->firmware = true; |
---|
| 2475 | + return 0; |
---|
| 2476 | +} |
---|
| 2477 | + |
---|
| 2478 | +static const struct gf100_gr_fwif |
---|
| 2479 | +gf100_gr_fwif[] = { |
---|
| 2480 | + { -1, gf100_gr_load, &gf100_gr }, |
---|
| 2481 | + { -1, gf100_gr_nofw, &gf100_gr }, |
---|
| 2482 | + {} |
---|
| 2483 | +}; |
---|
| 2484 | + |
---|
| 2485 | +int |
---|
2280 | 2486 | gf100_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr) |
---|
2281 | 2487 | { |
---|
2282 | | - return gf100_gr_new_(&gf100_gr, device, index, pgr); |
---|
| 2488 | + return gf100_gr_new_(gf100_gr_fwif, device, index, pgr); |
---|
2283 | 2489 | } |
---|