Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'linux-4.10' of git://github.com/skeggsb/linux into drm-next

- Regression fix from atomic conversion (rotation on the original G80).
- Concurrency fix when clearing compression tags.
- Fixes DP link training issues on GP102/4/6.
- Fixes backlight handling in the presence of Apple GMUX.
- Improvements to GPU error recovery in a number of scenarios.
- GP106 support.

* 'linux-4.10' of git://github.com/skeggsb/linux:
drm/nouveau/kms/nv50: fix atomic regression on original G80
drm/nouveau/bl: Do not register interface if Apple GMUX detected
drm/nouveau/bl: Assign different names to interfaces
drm/nouveau/bios/dp: fix handling of LevelEntryTableIndex on DP table 4.2
drm/nouveau/ltc: protect clearing of comptags with mutex
drm/nouveau/gr/gf100-: handle GPC/TPC/MPC trap
drm/nouveau/core: recognise GP106 chipset
drm/nouveau/ttm: wait for bo fence to signal before unmapping vmas
drm/nouveau/gr/gf100-: FECS intr handling is not relevant on proprietary ucode
drm/nouveau/gr/gf100-: properly ack all FECS error interrupts
drm/nouveau/fifo/gf100-: recover from host mmu faults

+172 -39
+77 -5
drivers/gpu/drm/nouveau/nouveau_backlight.c
··· 30 30 * Register locations derived from NVClock by Roderick Colenbrander 31 31 */ 32 32 33 + #include <linux/apple-gmux.h> 33 34 #include <linux/backlight.h> 35 + #include <linux/idr.h> 34 36 35 37 #include "nouveau_drv.h" 36 38 #include "nouveau_reg.h" 37 39 #include "nouveau_encoder.h" 40 + 41 + static struct ida bl_ida; 42 + #define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0' 43 + 44 + struct backlight_connector { 45 + struct list_head head; 46 + int id; 47 + }; 48 + 49 + static bool 50 + nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_connector 51 + *connector) 52 + { 53 + const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL); 54 + if (nb < 0 || nb >= 100) 55 + return false; 56 + if (nb > 0) 57 + snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb); 58 + else 59 + snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight"); 60 + connector->id = nb; 61 + return true; 62 + } 38 63 39 64 static int 40 65 nv40_get_intensity(struct backlight_device *bd) ··· 99 74 struct nvif_object *device = &drm->device.object; 100 75 struct backlight_properties props; 101 76 struct backlight_device *bd; 77 + struct backlight_connector bl_connector; 78 + char backlight_name[BL_NAME_SIZE]; 102 79 103 80 if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK)) 104 81 return 0; ··· 108 81 memset(&props, 0, sizeof(struct backlight_properties)); 109 82 props.type = BACKLIGHT_RAW; 110 83 props.max_brightness = 31; 111 - bd = backlight_device_register("nv_backlight", connector->kdev, drm, 84 + if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) { 85 + NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n"); 86 + return 0; 87 + } 88 + bd = backlight_device_register(backlight_name , connector->kdev, drm, 112 89 &nv40_bl_ops, &props); 113 - if (IS_ERR(bd)) 90 + 91 + if (IS_ERR(bd)) { 92 + if (bl_connector.id > 0) 93 + ida_simple_remove(&bl_ida, bl_connector.id); 114 94 return PTR_ERR(bd); 95 + } 96 + list_add(&bl_connector.head, &drm->bl_connectors); 115 97 drm->backlight = bd; 116 98 bd->props.brightness = nv40_get_intensity(bd); 117 99 backlight_update_status(bd); ··· 218 182 struct backlight_properties props; 219 183 struct backlight_device *bd; 220 184 const struct backlight_ops *ops; 185 + struct backlight_connector bl_connector; 186 + char backlight_name[BL_NAME_SIZE]; 221 187 222 188 nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS); 223 189 if (!nv_encoder) { ··· 241 203 memset(&props, 0, sizeof(struct backlight_properties)); 242 204 props.type = BACKLIGHT_RAW; 243 205 props.max_brightness = 100; 244 - bd = backlight_device_register("nv_backlight", connector->kdev, 206 + if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) { 207 + NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n"); 208 + return 0; 209 + } 210 + bd = backlight_device_register(backlight_name , connector->kdev, 245 211 nv_encoder, ops, &props); 246 - if (IS_ERR(bd)) 247 - return PTR_ERR(bd); 248 212 213 + if (IS_ERR(bd)) { 214 + if (bl_connector.id > 0) 215 + ida_simple_remove(&bl_ida, bl_connector.id); 216 + return PTR_ERR(bd); 217 + } 218 + 219 + list_add(&bl_connector.head, &drm->bl_connectors); 249 220 drm->backlight = bd; 250 221 bd->props.brightness = bd->ops->get_brightness(bd); 251 222 backlight_update_status(bd); ··· 267 220 struct nouveau_drm *drm = nouveau_drm(dev); 268 221 struct nvif_device *device = &drm->device; 269 222 struct drm_connector *connector; 223 + 224 + if (apple_gmux_present()) { 225 + NV_INFO(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n"); 226 + return 0; 227 + } 228 + 229 + INIT_LIST_HEAD(&drm->bl_connectors); 270 230 271 231 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 272 232 if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && ··· 301 247 nouveau_backlight_exit(struct drm_device *dev) 302 248 { 303 249 struct nouveau_drm *drm = nouveau_drm(dev); 250 + struct backlight_connector *connector; 251 + 252 + list_for_each_entry(connector, &drm->bl_connectors, head) { 253 + if (connector->id >= 0) 254 + ida_simple_remove(&bl_ida, connector->id); 255 + } 304 256 305 257 if (drm->backlight) { 306 258 backlight_device_unregister(drm->backlight); 307 259 drm->backlight = NULL; 308 260 } 261 + } 262 + 263 + void 264 + nouveau_backlight_ctor(void) 265 + { 266 + ida_init(&bl_ida); 267 + } 268 + 269 + void 270 + nouveau_backlight_dtor(void) 271 + { 272 + ida_destroy(&bl_ida); 309 273 }
+1
drivers/gpu/drm/nouveau/nouveau_bo.c
··· 1209 1209 nvbo->page_shift != vma->vm->mmu->lpg_shift)) { 1210 1210 nvkm_vm_map(vma, new_mem->mm_node); 1211 1211 } else { 1212 + WARN_ON(ttm_bo_wait(bo, false, false)); 1212 1213 nvkm_vm_unmap(vma); 1213 1214 } 1214 1215 }
+10
drivers/gpu/drm/nouveau/nouveau_display.h
··· 91 91 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT 92 92 extern int nouveau_backlight_init(struct drm_device *); 93 93 extern void nouveau_backlight_exit(struct drm_device *); 94 + extern void nouveau_backlight_ctor(void); 95 + extern void nouveau_backlight_dtor(void); 94 96 #else 95 97 static inline int 96 98 nouveau_backlight_init(struct drm_device *dev) ··· 102 100 103 101 static inline void 104 102 nouveau_backlight_exit(struct drm_device *dev) { 103 + } 104 + 105 + static inline void 106 + nouveau_backlight_ctor(void) { 107 + } 108 + 109 + static inline void 110 + nouveau_backlight_dtor(void) { 105 111 } 106 112 #endif 107 113
+2
drivers/gpu/drm/nouveau/nouveau_drm.c
··· 1122 1122 #endif 1123 1123 1124 1124 nouveau_register_dsm_handler(); 1125 + nouveau_backlight_ctor(); 1125 1126 return drm_pci_init(&driver_pci, &nouveau_drm_pci_driver); 1126 1127 } 1127 1128 ··· 1133 1132 return; 1134 1133 1135 1134 drm_pci_exit(&driver_pci, &nouveau_drm_pci_driver); 1135 + nouveau_backlight_dtor(); 1136 1136 nouveau_unregister_dsm_handler(); 1137 1137 1138 1138 #ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER
+1
drivers/gpu/drm/nouveau/nouveau_drv.h
··· 163 163 struct nvbios vbios; 164 164 struct nouveau_display *display; 165 165 struct backlight_device *backlight; 166 + struct list_head bl_connectors; 166 167 struct work_struct hpd_work; 167 168 #ifdef CONFIG_ACPI 168 169 struct notifier_block acpi_nb;
+5
drivers/gpu/drm/nouveau/nv50_display.c
··· 1726 1726 evo_data(push, asyh->core.handle); 1727 1727 evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1); 1728 1728 evo_data(push, (asyh->core.y << 16) | asyh->core.x); 1729 + /* EVO will complain with INVALID_STATE if we have an 1730 + * active cursor and (re)specify HeadSetContextDmaIso 1731 + * without also updating HeadSetOffsetCursor. 1732 + */ 1733 + asyh->set.curs = asyh->curs.visible; 1729 1734 } else 1730 1735 if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { 1731 1736 evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
+30
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
··· 2241 2241 .fifo = gp100_fifo_new, 2242 2242 }; 2243 2243 2244 + static const struct nvkm_device_chip 2245 + nv136_chipset = { 2246 + .name = "GP106", 2247 + .bar = gf100_bar_new, 2248 + .bios = nvkm_bios_new, 2249 + .bus = gf100_bus_new, 2250 + .devinit = gm200_devinit_new, 2251 + .fb = gp102_fb_new, 2252 + .fuse = gm107_fuse_new, 2253 + .gpio = gk104_gpio_new, 2254 + .i2c = gm200_i2c_new, 2255 + .ibus = gm200_ibus_new, 2256 + .imem = nv50_instmem_new, 2257 + .ltc = gp100_ltc_new, 2258 + .mc = gp100_mc_new, 2259 + .mmu = gf100_mmu_new, 2260 + .pci = gp100_pci_new, 2261 + .pmu = gp102_pmu_new, 2262 + .timer = gk20a_timer_new, 2263 + .top = gk104_top_new, 2264 + .ce[0] = gp102_ce_new, 2265 + .ce[1] = gp102_ce_new, 2266 + .ce[2] = gp102_ce_new, 2267 + .ce[3] = gp102_ce_new, 2268 + .disp = gp102_disp_new, 2269 + .dma = gf119_dma_new, 2270 + .fifo = gp100_fifo_new, 2271 + }; 2272 + 2244 2273 static int 2245 2274 nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size, 2246 2275 struct nvkm_notify *notify) ··· 2706 2677 case 0x130: device->chip = &nv130_chipset; break; 2707 2678 case 0x132: device->chip = &nv132_chipset; break; 2708 2679 case 0x134: device->chip = &nv134_chipset; break; 2680 + case 0x136: device->chip = &nv136_chipset; break; 2709 2681 default: 2710 2682 nvdev_error(device, "unknown chipset (%08x)\n", boot0); 2711 2683 goto done;
+2 -1
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
··· 180 180 list_del_init(&chan->head); 181 181 chan->killed = true; 182 182 183 - fifo->recover.mask |= 1ULL << engine->subdev.index; 183 + if (engine != &fifo->base.engine) 184 + fifo->recover.mask |= 1ULL << engine->subdev.index; 184 185 schedule_work(&fifo->recover.work); 185 186 } 186 187
+8 -8
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
··· 743 743 { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, 744 744 { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, 745 745 { 0x06, "SCHED" }, 746 - { 0x07, "HOST0" }, 747 - { 0x08, "HOST1" }, 748 - { 0x09, "HOST2" }, 749 - { 0x0a, "HOST3" }, 750 - { 0x0b, "HOST4" }, 751 - { 0x0c, "HOST5" }, 752 - { 0x0d, "HOST6" }, 753 - { 0x0e, "HOST7" }, 746 + { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO }, 747 + { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO }, 748 + { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO }, 749 + { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO }, 750 + { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO }, 751 + { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO }, 752 + { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO }, 753 + { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO }, 754 754 { 0x0f, "HOSTSR" }, 755 755 { 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD }, 756 756 { 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP },
+8 -8
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
··· 32 32 { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, 33 33 { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, 34 34 { 0x06, "SCHED" }, 35 - { 0x07, "HOST0" }, 36 - { 0x08, "HOST1" }, 37 - { 0x09, "HOST2" }, 38 - { 0x0a, "HOST3" }, 39 - { 0x0b, "HOST4" }, 40 - { 0x0c, "HOST5" }, 41 - { 0x0d, "HOST6" }, 42 - { 0x0e, "HOST7" }, 35 + { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO }, 36 + { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO }, 37 + { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO }, 38 + { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO }, 39 + { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO }, 40 + { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO }, 41 + { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO }, 42 + { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO }, 43 43 { 0x0f, "HOSTSR" }, 44 44 { 0x13, "PERF" }, 45 45 { 0x17, "PMU" },
+11 -11
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
··· 30 30 { 0x03, "IFB", NULL, NVKM_ENGINE_IFB }, 31 31 { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, 32 32 { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM }, 33 - { 0x06, "HOST0" }, 34 - { 0x07, "HOST1" }, 35 - { 0x08, "HOST2" }, 36 - { 0x09, "HOST3" }, 37 - { 0x0a, "HOST4" }, 38 - { 0x0b, "HOST5" }, 39 - { 0x0c, "HOST6" }, 40 - { 0x0d, "HOST7" }, 41 - { 0x0e, "HOST8" }, 42 - { 0x0f, "HOST9" }, 43 - { 0x10, "HOST10" }, 33 + { 0x06, "HOST0", NULL, NVKM_ENGINE_FIFO }, 34 + { 0x07, "HOST1", NULL, NVKM_ENGINE_FIFO }, 35 + { 0x08, "HOST2", NULL, NVKM_ENGINE_FIFO }, 36 + { 0x09, "HOST3", NULL, NVKM_ENGINE_FIFO }, 37 + { 0x0a, "HOST4", NULL, NVKM_ENGINE_FIFO }, 38 + { 0x0b, "HOST5", NULL, NVKM_ENGINE_FIFO }, 39 + { 0x0c, "HOST6", NULL, NVKM_ENGINE_FIFO }, 40 + { 0x0d, "HOST7", NULL, NVKM_ENGINE_FIFO }, 41 + { 0x0e, "HOST8", NULL, NVKM_ENGINE_FIFO }, 42 + { 0x0f, "HOST9", NULL, NVKM_ENGINE_FIFO }, 43 + { 0x10, "HOST10", NULL, NVKM_ENGINE_FIFO }, 44 44 { 0x13, "PERF" }, 45 45 { 0x17, "PMU" }, 46 46 { 0x18, "PTP" },
+11 -5
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
··· 1041 1041 stat &= ~0x00000008; 1042 1042 } 1043 1043 1044 + if (stat & 0x00000010) { 1045 + u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0430)); 1046 + nvkm_error(subdev, "GPC%d/TPC%d/MPC: %08x\n", gpc, tpc, trap); 1047 + nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x0430), 0xc0000000); 1048 + stat &= ~0x00000010; 1049 + } 1050 + 1044 1051 if (stat) { 1045 1052 nvkm_error(subdev, "GPC%d/TPC%d/%08x: unknown\n", gpc, tpc, stat); 1046 1053 } ··· 1265 1258 struct nvkm_device *device = subdev->device; 1266 1259 u32 stat = nvkm_rd32(device, 0x409c18); 1267 1260 1268 - if (stat & 0x00000001) { 1261 + if (!gr->firmware && (stat & 0x00000001)) { 1269 1262 u32 code = nvkm_rd32(device, 0x409814); 1270 1263 if (code == E_BAD_FWMTHD) { 1271 1264 u32 class = nvkm_rd32(device, 0x409808); ··· 1277 1270 nvkm_error(subdev, "FECS MTHD subc %d class %04x " 1278 1271 "mthd %04x data %08x\n", 1279 1272 subc, class, mthd, data); 1280 - 1281 - nvkm_wr32(device, 0x409c20, 0x00000001); 1282 - stat &= ~0x00000001; 1283 1273 } else { 1284 1274 nvkm_error(subdev, "FECS ucode error %d\n", code); 1285 1275 } 1276 + nvkm_wr32(device, 0x409c20, 0x00000001); 1277 + stat &= ~0x00000001; 1286 1278 } 1287 1279 1288 - if (stat & 0x00080000) { 1280 + if (!gr->firmware && (stat & 0x00080000)) { 1289 1281 nvkm_error(subdev, "FECS watchdog timeout\n"); 1290 1282 gf100_gr_ctxctl_debug(gr); 1291 1283 nvkm_wr32(device, 0x409c20, 0x00080000);
+4 -1
drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c
··· 207 207 if (*ver >= 0x30) { 208 208 const u8 vsoff[] = { 0, 4, 7, 9 }; 209 209 idx = (pc * 10) + vsoff[vs] + pe; 210 - if (*ver >= 0x40 && *hdr >= 0x12) 210 + if (*ver >= 0x40 && *ver <= 0x41 && *hdr >= 0x12) 211 211 idx += nvbios_rd08(bios, outp + 0x11) * 40; 212 + else 213 + if (*ver >= 0x42) 214 + idx += nvbios_rd08(bios, outp + 0x11) * 10; 212 215 } else { 213 216 while ((data = nvbios_dpcfg_entry(bios, outp, ++idx, 214 217 ver, hdr, cnt, len))) {
+2
drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
··· 47 47 48 48 BUG_ON((first > limit) || (limit >= ltc->num_tags)); 49 49 50 + mutex_lock(&ltc->subdev.mutex); 50 51 ltc->func->cbc_clear(ltc, first, limit); 51 52 ltc->func->cbc_wait(ltc); 53 + mutex_unlock(&ltc->subdev.mutex); 52 54 } 53 55 54 56 int