| .. | .. |
|---|
| 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 | } |
|---|