Re: [Nouveau] [PATCH v2 16/22] volt: don't require perfect fit
On 21/03/16 18:16, Karol Herbst wrote: if we calculate the voltage in the table right, we get all kinds of values, which never fit the hardware steps, so we use the closest higher value the hardware can do This is indeed the goal. Signed-off-by: Karol Herbst--- drm/nouveau/nvkm/subdev/volt/base.c | 25 ++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drm/nouveau/nvkm/subdev/volt/base.c b/drm/nouveau/nvkm/subdev/volt/base.c index e741383..58738e3 100644 --- a/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drm/nouveau/nvkm/subdev/volt/base.c @@ -51,18 +51,37 @@ static int nvkm_volt_set(struct nvkm_volt *volt, u32 uv) { struct nvkm_subdev *subdev = >subdev; - int i, ret = -EINVAL; + int i, ret = -EINVAL, err, best = -1; if (volt->func->volt_set) return volt->func->volt_set(volt, uv); for (i = 0; i < volt->vid_nr; i++) { - if (volt->vid[i].uv == uv) { - ret = volt->func->vid_set(volt, volt->vid[i].vid); + if (i == 0) { + best = 0; + err = volt->vid[i].uv - uv; + } else { + int new_err = volt->vid[i].uv - uv; + if (abs(new_err) < abs(err) + || (err < 0 && new_err >= 0)) { + best = i; + err = new_err; + } + } + + if (err == 0) { + ret = volt->func->vid_set(volt, volt->vid[best].vid); nvkm_debug(subdev, "set %duv: %d\n", uv, ret); break; } } + + if (best != -1) { + ret = volt->func->vid_set(volt, volt->vid[best].vid); + nvkm_debug(subdev, "set req %duv to %duv: %d\n", uv, + volt->vid[best].uv, ret); + } + return ret; } The code is really weird though :o How about the following? It would make it much more readable and actually do what your commit message says. int best = -1; u32 best_abs_err = -1; for (i = 0; i < volt->vid_nr; i++) { int abs_err = abs(volt->vid[i].uv - uv); if (volt->vid[i].uv >= uv && abs_err < best_abs_err) { best = i; best_abs_err = abs_err; if (abs_err == 0) break; } } if (best >= 0) { ret = volt->func->vid_set(volt, volt->vid[best].vid); nvkm_debug(subdev, "set %duv: %d\n", uv, ret); } else { /* return an error to tell that we cannot use the wanted clock since we cannot select the needed voltage! */ } ___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
Re: [Nouveau] [PATCH v2 18/22] volt: add coefficients I found on my gpu
On 21/03/16 18:16, Karol Herbst wrote: I am sure that those are a bit different on other GPUs, but while testing the error range compared to nvidia was around 100%+-3%. Without this change we are most of the time around 10% below nvidias voltage, so this change causes no harm and improves the situation a lot already. The remaining task for this is to figure out which of these constants are chip specific and from where to get the chip specific factors Signed-off-by: Karol HerbstInstead of landing these coefficients like that, I would really like if you could dump pfuse and check if you find these coefficients there. What could be done also is to re-do the work you did to find out those coefficients on a GPU where your coefficients are not really good and find out what values would have needed and then compare pfuse with the original card. If this is to be considered a long task, then I am OK landing those coefficients, but I would really appreciate if you could at least have a quick look at pfuse :) ___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
Re: [Nouveau] [PATCH v2 06/22] volt: parse the both max voltage entries
On 28/03/16 23:49, Martin Peres wrote: On 21/03/16 18:16, Karol Herbst wrote: these entries specify a maximum voltage nvidia never exceeds, we shouldn't do that, too. Signed-off-by: Karol Herbst--- drm/nouveau/include/nvkm/subdev/bios/vmap.h | 2 ++ drm/nouveau/include/nvkm/subdev/volt.h | 2 ++ drm/nouveau/nvkm/subdev/bios/vmap.c | 5 + drm/nouveau/nvkm/subdev/volt/base.c | 11 +++ 4 files changed, 20 insertions(+) diff --git a/drm/nouveau/include/nvkm/subdev/bios/vmap.h b/drm/nouveau/include/nvkm/subdev/bios/vmap.h index 6633c6d..48fe71d 100644 --- a/drm/nouveau/include/nvkm/subdev/bios/vmap.h +++ b/drm/nouveau/include/nvkm/subdev/bios/vmap.h @@ -1,6 +1,8 @@ #ifndef __NVBIOS_VMAP_H__ #define __NVBIOS_VMAP_H__ struct nvbios_vmap { + u8 max0; + u8 max1; }; u16 nvbios_vmap_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); diff --git a/drm/nouveau/include/nvkm/subdev/volt.h b/drm/nouveau/include/nvkm/subdev/volt.h index fc68825..3e0f8da 100644 --- a/drm/nouveau/include/nvkm/subdev/volt.h +++ b/drm/nouveau/include/nvkm/subdev/volt.h @@ -15,6 +15,8 @@ struct nvkm_volt { u32 max_uv; u32 min_uv; + u8 max0_vid; + u8 max1_vid; }; int nvkm_volt_map_min(struct nvkm_volt *volt, u8 id); diff --git a/drm/nouveau/nvkm/subdev/bios/vmap.c b/drm/nouveau/nvkm/subdev/bios/vmap.c index 2f13db7..f5463b1 100644 --- a/drm/nouveau/nvkm/subdev/bios/vmap.c +++ b/drm/nouveau/nvkm/subdev/bios/vmap.c @@ -61,7 +61,12 @@ nvbios_vmap_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, memset(info, 0x00, sizeof(*info)); switch (!!vmap * *ver) { case 0x10: + info->max0 = 0xff; + info->max1 = 0xff; + break; case 0x20: + info->max0 = nvbios_rd08(bios, vmap + 0x7); + info->max1 = nvbios_rd08(bios, vmap + 0x8); break; } return vmap; diff --git a/drm/nouveau/nvkm/subdev/volt/base.c b/drm/nouveau/nvkm/subdev/volt/base.c index 71094a9..205dfcf 100644 --- a/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drm/nouveau/nvkm/subdev/volt/base.c @@ -217,9 +217,20 @@ nvkm_volt_ctor(const struct nvkm_volt_func *func, struct nvkm_device *device, /* Assuming the non-bios device should build the voltage table later */ if (bios) { + u8 ver, hdr, cnt, len; + struct nvbios_vmap vmap; + nvkm_volt_parse_bios(bios, volt); nvkm_debug(>subdev, "min: %iuv max: %iuv\n", volt->min_uv, volt->max_uv); + + if (nvbios_vmap_parse(bios, , , , , )) { + volt->max0_vid = vmap.max0; + volt->max1_vid = vmap.max1; + } else { + volt->max0_vid = 0xff; + volt->max1_vid = 0xff; + } } if (volt->vid_nr) { This is really peculiar that NVIDIA would have 2 max_vid in the same entry :s How did you reverse that? Did you really see no differences? Maybe the two max_vid are for different temperatures? Ok, after discussions on IRC, I understand better. Max0/1 is actually not a vid but an entry in the voltage mapping table, which has different coefficient for the temperature. This allows OEMs to clamp the maximum voltage with not one but two different functions. I can see why it is OK. Can you explain this a little more? Maybe as a comment in the code? ___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
Re: [Nouveau] [PATCH v2 22/22] debugfs: add boost interface to change the boost_mode
On 21/03/16 18:16, Karol Herbst wrote: Signed-off-by: Karol Herbst21-22 are: Reviewed-by: Martin Peres ___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
Re: [Nouveau] [PATCH v2 07/22] volt: add min_id parameter to nvkm_volt_set_id
On 28/03/16 23:52, Martin Peres wrote: On 21/03/16 18:16, Karol Herbst wrote: min_id indicates a volt map entry which acts as a floor value, this will be used to set the lower voltage limit through pstates Please state that this comes that this min_id is different for each pstate, hence why volt should not know about this and needs to take it as an input! Signed-off-by: Karol HerbstDo we really want to push reclocking logic to the volt subsystem? To me, volt should just allow you to read back and set a voltage. All the rest of the logic should be in clk. Since this is my first NAK, here are my R-b for 3, 4 and 5: Reviewed-by: Martin Peres With this fixed, this patch is Reviewed-by: Martin Peres ___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
Re: [Nouveau] [PATCH v2 07/22] volt: add min_id parameter to nvkm_volt_set_id
On 21/03/16 18:16, Karol Herbst wrote: min_id indicates a volt map entry which acts as a floor value, this will be used to set the lower voltage limit through pstates Signed-off-by: Karol HerbstDo we really want to push reclocking logic to the volt subsystem? To me, volt should just allow you to read back and set a voltage. All the rest of the logic should be in clk. Since this is my first NAK, here are my R-b for 3, 4 and 5: Reviewed-by: Martin Peres ___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
Re: [Nouveau] [PATCH v2 06/22] volt: parse the both max voltage entries
On 21/03/16 18:16, Karol Herbst wrote: these entries specify a maximum voltage nvidia never exceeds, we shouldn't do that, too. Signed-off-by: Karol Herbst--- drm/nouveau/include/nvkm/subdev/bios/vmap.h | 2 ++ drm/nouveau/include/nvkm/subdev/volt.h | 2 ++ drm/nouveau/nvkm/subdev/bios/vmap.c | 5 + drm/nouveau/nvkm/subdev/volt/base.c | 11 +++ 4 files changed, 20 insertions(+) diff --git a/drm/nouveau/include/nvkm/subdev/bios/vmap.h b/drm/nouveau/include/nvkm/subdev/bios/vmap.h index 6633c6d..48fe71d 100644 --- a/drm/nouveau/include/nvkm/subdev/bios/vmap.h +++ b/drm/nouveau/include/nvkm/subdev/bios/vmap.h @@ -1,6 +1,8 @@ #ifndef __NVBIOS_VMAP_H__ #define __NVBIOS_VMAP_H__ struct nvbios_vmap { + u8 max0; + u8 max1; }; u16 nvbios_vmap_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); diff --git a/drm/nouveau/include/nvkm/subdev/volt.h b/drm/nouveau/include/nvkm/subdev/volt.h index fc68825..3e0f8da 100644 --- a/drm/nouveau/include/nvkm/subdev/volt.h +++ b/drm/nouveau/include/nvkm/subdev/volt.h @@ -15,6 +15,8 @@ struct nvkm_volt { u32 max_uv; u32 min_uv; + u8 max0_vid; + u8 max1_vid; }; int nvkm_volt_map_min(struct nvkm_volt *volt, u8 id); diff --git a/drm/nouveau/nvkm/subdev/bios/vmap.c b/drm/nouveau/nvkm/subdev/bios/vmap.c index 2f13db7..f5463b1 100644 --- a/drm/nouveau/nvkm/subdev/bios/vmap.c +++ b/drm/nouveau/nvkm/subdev/bios/vmap.c @@ -61,7 +61,12 @@ nvbios_vmap_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, memset(info, 0x00, sizeof(*info)); switch (!!vmap * *ver) { case 0x10: + info->max0 = 0xff; + info->max1 = 0xff; + break; case 0x20: + info->max0 = nvbios_rd08(bios, vmap + 0x7); + info->max1 = nvbios_rd08(bios, vmap + 0x8); break; } return vmap; diff --git a/drm/nouveau/nvkm/subdev/volt/base.c b/drm/nouveau/nvkm/subdev/volt/base.c index 71094a9..205dfcf 100644 --- a/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drm/nouveau/nvkm/subdev/volt/base.c @@ -217,9 +217,20 @@ nvkm_volt_ctor(const struct nvkm_volt_func *func, struct nvkm_device *device, /* Assuming the non-bios device should build the voltage table later */ if (bios) { + u8 ver, hdr, cnt, len; + struct nvbios_vmap vmap; + nvkm_volt_parse_bios(bios, volt); nvkm_debug(>subdev, "min: %iuv max: %iuv\n", volt->min_uv, volt->max_uv); + + if (nvbios_vmap_parse(bios, , , , , )) { + volt->max0_vid = vmap.max0; + volt->max1_vid = vmap.max1; + } else { + volt->max0_vid = 0xff; + volt->max1_vid = 0xff; + } } if (volt->vid_nr) { This is really peculiar that NVIDIA would have 2 max_vid in the same entry :s How did you reverse that? Did you really see no differences? Maybe the two max_vid are for different temperatures? ___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 94728] Nouveau doesn't work with Nvidia GTX 960
https://bugs.freedesktop.org/show_bug.cgi?id=94728 --- Comment #4 from neilmed...@gmail.com --- Makes sense. Thanks for the quick replies - and the good work in maintaining nouveau :) -- You are receiving this mail because: You are the assignee for the bug.___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 91526] World of Warcraft (on Wine) has UI corruption with nouveau
https://bugs.freedesktop.org/show_bug.cgi?id=91526 Ilia Mirkinchanged: What|Removed |Added Status|REOPENED|RESOLVED Resolution|--- |FIXED --- Comment #15 from Ilia Mirkin --- Pushed to master: commit 41100b6b44e747b9003937f123fce571fd3dec46 Author: Ilia Mirkin Date: Sat Mar 26 22:32:43 2016 -0400 nvc0: disable primitive restart and index bias during blits -- You are receiving this mail because: You are the assignee for the bug. You are the QA Contact for the bug.___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 94728] Nouveau doesn't work with Nvidia GTX 960
https://bugs.freedesktop.org/show_bug.cgi?id=94728 --- Comment #3 from Ilia Mirkin--- As you can see, it's falling back to modesetting, as expected. The xf86-video-nouveau DDX does not support any maxwell GPUs at the moment. Separately, modesetting isn't able to start up glamor because of the reasons that Martin pointed out. This means that you'll get swrast when running applications inside X as well. -- You are receiving this mail because: You are the assignee for the bug.___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 91526] World of Warcraft (on Wine) has UI corruption with nouveau
https://bugs.freedesktop.org/show_bug.cgi?id=91526 --- Comment #14 from Karol Herbst--- (In reply to Ilia Mirkin from comment #13) > As I had originally suspected, this has nothing to actually do with BGRA4 > format. It was just an odd place in the command stream. > > The following patch should fix it: > https://patchwork.freedesktop.org/patch/78448/ > > Please test. I think this has been broken since mesa 10.2 or so =/ works great, thanks :) Tested-by: Karol Herbst -- You are receiving this mail because: You are the QA Contact for the bug. You are the assignee for the bug.___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH v2 2/4] iccsense: convert to linked list
v2: add list_del calls Signed-off-by: Karol HerbstReviewed-by: Martin Peres --- drm/nouveau/include/nvkm/subdev/iccsense.h | 4 +--- drm/nouveau/nouveau_hwmon.c| 2 +- drm/nouveau/nvkm/subdev/iccsense/base.c| 34 ++ drm/nouveau/nvkm/subdev/iccsense/priv.h| 1 + 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/iccsense.h b/drm/nouveau/include/nvkm/subdev/iccsense.h index c3defcd..a4c0da0 100644 --- a/drm/nouveau/include/nvkm/subdev/iccsense.h +++ b/drm/nouveau/include/nvkm/subdev/iccsense.h @@ -3,12 +3,10 @@ #include -struct nkvm_iccsense_rail; struct nvkm_iccsense { struct nvkm_subdev subdev; - u8 rail_count; bool data_valid; - struct nvkm_iccsense_rail *rails; + struct list_head rails; }; int gf100_iccsense_new(struct nvkm_device *, int index, struct nvkm_iccsense **); diff --git a/drm/nouveau/nouveau_hwmon.c b/drm/nouveau/nouveau_hwmon.c index 67edd2f..74f237b 100644 --- a/drm/nouveau/nouveau_hwmon.c +++ b/drm/nouveau/nouveau_hwmon.c @@ -689,7 +689,7 @@ nouveau_hwmon_init(struct drm_device *dev) goto error; } - if (iccsense && iccsense->data_valid && iccsense->rail_count) { + if (iccsense && iccsense->data_valid && !list_empty(>rails)) { ret = sysfs_create_group(_dev->kobj, _power_attrgroup); if (ret) diff --git a/drm/nouveau/nvkm/subdev/iccsense/base.c b/drm/nouveau/nvkm/subdev/iccsense/base.c index bf1b94e..f2a210a 100644 --- a/drm/nouveau/nvkm/subdev/iccsense/base.c +++ b/drm/nouveau/nvkm/subdev/iccsense/base.c @@ -98,25 +98,21 @@ nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense, int nvkm_iccsense_read_all(struct nvkm_iccsense *iccsense) { - int result = 0, i; + int result = 0; + struct nvkm_iccsense_rail *rail; if (!iccsense) return -EINVAL; - if (iccsense->rail_count == 0) - return -ENODEV; - - for (i = 0; i < iccsense->rail_count; ++i) { + list_for_each_entry(rail, >rails, head) { int res; - struct nvkm_iccsense_rail *rail = >rails[i]; if (!rail->read) return -ENODEV; res = rail->read(iccsense, rail); - if (res >= 0) - result += res; - else + if (res < 0) return res; + result += res; } return result; } @@ -125,9 +121,12 @@ static void * nvkm_iccsense_dtor(struct nvkm_subdev *subdev) { struct nvkm_iccsense *iccsense = nvkm_iccsense(subdev); + struct nvkm_iccsense_rail *rail, *tmp; - if (iccsense->rails) - kfree(iccsense->rails); + list_for_each_entry_safe(rail, tmp, >rails, head) { + list_del(>head); + kfree(rail); + } return iccsense; } @@ -145,11 +144,6 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev) || !stbl.nr_entry) return 0; - iccsense->rails = kmalloc(sizeof(*iccsense->rails) * stbl.nr_entry, - GFP_KERNEL); - if (!iccsense->rails) - return -ENOMEM; - iccsense->data_valid = true; for (i = 0; i < stbl.nr_entry; ++i) { struct pwr_rail_t *r = [i]; @@ -184,7 +178,10 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev) continue; } - rail = >rails[iccsense->rail_count]; + rail = kmalloc(sizeof(*rail), GFP_KERNEL); + if (!rail) + return -ENOMEM; + switch (extdev.type) { case NVBIOS_EXTDEV_INA209: rail->read = nvkm_iccsense_ina209_read; @@ -201,7 +198,7 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev) rail->rail = r->rail; rail->mohm = r->resistor_mohm; rail->i2c = _bus->i2c; - ++iccsense->rail_count; + list_add_tail(>head, >rails); } return 0; } @@ -224,6 +221,7 @@ nvkm_iccsense_new_(struct nvkm_device *device, int index, { if (!(*iccsense = kzalloc(sizeof(**iccsense), GFP_KERNEL))) return -ENOMEM; + INIT_LIST_HEAD(&(*iccsense)->rails); nvkm_iccsense_ctor(device, index, *iccsense); return 0; } diff --git a/drm/nouveau/nvkm/subdev/iccsense/priv.h b/drm/nouveau/nvkm/subdev/iccsense/priv.h index ed398b8..e479128 100644 --- a/drm/nouveau/nvkm/subdev/iccsense/priv.h +++ b/drm/nouveau/nvkm/subdev/iccsense/priv.h @@ -4,6 +4,7 @@ #include struct nvkm_iccsense_rail { + struct list_head head; int (*read)(struct nvkm_iccsense *, struct nvkm_iccsense_rail *); struct
[Nouveau] [PATCH v2 4/4] iccsense: configure sensors like nvidia does
v2: rename ina209/ina219 read function Signed-off-by: Karol HerbstReviewed-by: Martin Peres --- drm/nouveau/nvkm/subdev/iccsense/base.c | 68 + 1 file changed, 68 insertions(+) diff --git a/drm/nouveau/nvkm/subdev/iccsense/base.c b/drm/nouveau/nvkm/subdev/iccsense/base.c index 03eef9d..55f36f5 100644 --- a/drm/nouveau/nvkm/subdev/iccsense/base.c +++ b/drm/nouveau/nvkm/subdev/iccsense/base.c @@ -95,6 +95,63 @@ nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense, 40 * 8); } +static void +nvkm_iccsense_ina209_config(struct nvkm_iccsense *iccsense, + struct nvkm_iccsense_sensor *sensor) +{ + struct nvkm_subdev *subdev = >subdev; + /* configuration: +* 0x0007: 0x0007 shunt and bus continous +* 0x0078: 0x0078 128 samples shunt +* 0x0780: 0x0780 128 samples bus +* 0x1800: 0x +-40 mV shunt range +* 0x2000: 0x 16V FSR + */ + u16 value = 0x07ff; + nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value); + nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value); +} + +static void +nvkm_iccsense_ina3221_config(struct nvkm_iccsense *iccsense, +struct nvkm_iccsense_sensor *sensor) +{ + struct nvkm_subdev *subdev = >subdev; + /* configuration: +* 0x0007: 0x0007 shunt and bus continous +* 0x0031: 0x 140 us conversion time shunt +* 0x01c0: 0x 140 us conversion time bus +* 0x0f00: 0x0f00 1024 samples +* 0x7000: 0x?000 channels + */ + u16 value = 0x0e07; + if (sensor->rail_mask & 0x1) + value |= 0x1 << 14; + if (sensor->rail_mask & 0x2) + value |= 0x1 << 13; + if (sensor->rail_mask & 0x4) + value |= 0x1 << 12; + nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value); + nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value); +} + +static void +nvkm_iccsense_sensor_config(struct nvkm_iccsense *iccsense, + struct nvkm_iccsense_sensor *sensor) +{ + switch (sensor->type) { + case NVBIOS_EXTDEV_INA209: + case NVBIOS_EXTDEV_INA219: + nvkm_iccsense_ina209_config(iccsense, sensor); + break; + case NVBIOS_EXTDEV_INA3221: + nvkm_iccsense_ina3221_config(iccsense, sensor); + break; + default: + break; + } +} + int nvkm_iccsense_read_all(struct nvkm_iccsense *iccsense) { @@ -260,8 +317,19 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev) return 0; } +static int +nvkm_iccsense_init(struct nvkm_subdev *subdev) +{ + struct nvkm_iccsense *iccsense = nvkm_iccsense(subdev); + struct nvkm_iccsense_sensor *sensor; + list_for_each_entry(sensor, >sensors, head) + nvkm_iccsense_sensor_config(iccsense, sensor); + return 0; +} + struct nvkm_subdev_func iccsense_func = { .oneinit = nvkm_iccsense_oneinit, + .init = nvkm_iccsense_init, .dtor = nvkm_iccsense_dtor, }; -- 2.7.4 ___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH v2 0/4] Configure Power Sensors
The power sensors can be configured to sample the readout values over time. Nvidia does this too, so nouveau should probably do that too. v2: use list_del and rework an error message Karol Herbst (4): iccsense: remove read function iccsense: convert to linked list iccsense: split sensor into own struct iccsense: configure sensors like nvidia does drm/nouveau/include/nvkm/subdev/iccsense.h | 6 +- drm/nouveau/nouveau_hwmon.c| 2 +- drm/nouveau/nvkm/subdev/iccsense/base.c| 249 + drm/nouveau/nvkm/subdev/iccsense/priv.h| 16 +- 4 files changed, 201 insertions(+), 72 deletions(-) -- 2.7.4 ___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH v2 1/4] iccsense: remove read function
Signed-off-by: Karol HerbstReviewed-by: Martin Peres --- drm/nouveau/include/nvkm/subdev/iccsense.h | 1 - drm/nouveau/nvkm/subdev/iccsense/base.c| 23 ++- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/iccsense.h b/drm/nouveau/include/nvkm/subdev/iccsense.h index 530c621..c3defcd 100644 --- a/drm/nouveau/include/nvkm/subdev/iccsense.h +++ b/drm/nouveau/include/nvkm/subdev/iccsense.h @@ -12,6 +12,5 @@ struct nvkm_iccsense { }; int gf100_iccsense_new(struct nvkm_device *, int index, struct nvkm_iccsense **); -int nvkm_iccsense_read(struct nvkm_iccsense *iccsense, u8 idx); int nvkm_iccsense_read_all(struct nvkm_iccsense *iccsense); #endif diff --git a/drm/nouveau/nvkm/subdev/iccsense/base.c b/drm/nouveau/nvkm/subdev/iccsense/base.c index c44a852..bf1b94e 100644 --- a/drm/nouveau/nvkm/subdev/iccsense/base.c +++ b/drm/nouveau/nvkm/subdev/iccsense/base.c @@ -96,26 +96,23 @@ nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense, } int -nvkm_iccsense_read(struct nvkm_iccsense *iccsense, u8 idx) +nvkm_iccsense_read_all(struct nvkm_iccsense *iccsense) { - struct nvkm_iccsense_rail *rail; + int result = 0, i; - if (!iccsense || idx >= iccsense->rail_count) + if (!iccsense) return -EINVAL; - rail = >rails[idx]; - if (!rail->read) + if (iccsense->rail_count == 0) return -ENODEV; - return rail->read(iccsense, rail); -} - -int -nvkm_iccsense_read_all(struct nvkm_iccsense *iccsense) -{ - int result = 0, i; for (i = 0; i < iccsense->rail_count; ++i) { - int res = nvkm_iccsense_read(iccsense, i); + int res; + struct nvkm_iccsense_rail *rail = >rails[i]; + if (!rail->read) + return -ENODEV; + + res = rail->read(iccsense, rail); if (res >= 0) result += res; else -- 2.7.4 ___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH v2 3/4] iccsense: split sensor into own struct
v2: add list_del call, reword error message Signed-off-by: Karol HerbstReviewed-by: Martin Peres --- drm/nouveau/include/nvkm/subdev/iccsense.h | 1 + drm/nouveau/nvkm/subdev/iccsense/base.c| 142 - drm/nouveau/nvkm/subdev/iccsense/priv.h| 15 ++- 3 files changed, 113 insertions(+), 45 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/iccsense.h b/drm/nouveau/include/nvkm/subdev/iccsense.h index a4c0da0..3c2ddd9 100644 --- a/drm/nouveau/include/nvkm/subdev/iccsense.h +++ b/drm/nouveau/include/nvkm/subdev/iccsense.h @@ -6,6 +6,7 @@ struct nvkm_iccsense { struct nvkm_subdev subdev; bool data_valid; + struct list_head sensors; struct list_head rails; }; diff --git a/drm/nouveau/nvkm/subdev/iccsense/base.c b/drm/nouveau/nvkm/subdev/iccsense/base.c index f2a210a..03eef9d 100644 --- a/drm/nouveau/nvkm/subdev/iccsense/base.c +++ b/drm/nouveau/nvkm/subdev/iccsense/base.c @@ -30,15 +30,14 @@ static bool nvkm_iccsense_validate_device(struct i2c_adapter *i2c, u8 addr, - enum nvbios_extdev_type type, u8 rail) + enum nvbios_extdev_type type) { switch (type) { case NVBIOS_EXTDEV_INA209: case NVBIOS_EXTDEV_INA219: - return rail == 0 && nv_rd16i2cr(i2c, addr, 0x0) >= 0; + return nv_rd16i2cr(i2c, addr, 0x0) >= 0; case NVBIOS_EXTDEV_INA3221: - return rail <= 3 && - nv_rd16i2cr(i2c, addr, 0xff) == 0x3220 && + return nv_rd16i2cr(i2c, addr, 0xff) == 0x3220 && nv_rd16i2cr(i2c, addr, 0xfe) == 0x5449; default: return false; @@ -67,8 +66,9 @@ nvkm_iccsense_ina2x9_read(struct nvkm_iccsense *iccsense, struct nvkm_iccsense_rail *rail, u8 shunt_reg, u8 bus_reg) { - return nvkm_iccsense_poll_lane(rail->i2c, rail->addr, shunt_reg, 0, - bus_reg, 3, rail->mohm, 10 * 4); + return nvkm_iccsense_poll_lane(rail->sensor->i2c, rail->sensor->addr, + shunt_reg, 0, bus_reg, 3, rail->mohm, + 10 * 4); } static int @@ -89,9 +89,9 @@ static int nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense, struct nvkm_iccsense_rail *rail) { - return nvkm_iccsense_poll_lane(rail->i2c, rail->addr, - 1 + (rail->rail * 2), 3, - 2 + (rail->rail * 2), 3, rail->mohm, + return nvkm_iccsense_poll_lane(rail->sensor->i2c, rail->sensor->addr, + 1 + (rail->idx * 2), 3, + 2 + (rail->idx * 2), 3, rail->mohm, 40 * 8); } @@ -121,9 +121,14 @@ static void * nvkm_iccsense_dtor(struct nvkm_subdev *subdev) { struct nvkm_iccsense *iccsense = nvkm_iccsense(subdev); - struct nvkm_iccsense_rail *rail, *tmp; + struct nvkm_iccsense_sensor *sensor, *tmps; + struct nvkm_iccsense_rail *rail, *tmpr; - list_for_each_entry_safe(rail, tmp, >rails, head) { + list_for_each_entry_safe(sensor, tmps, >sensors, head) { + list_del(>head); + kfree(sensor); + } + list_for_each_entry_safe(rail, tmpr, >rails, head) { list_del(>head); kfree(rail); } @@ -131,73 +136,125 @@ nvkm_iccsense_dtor(struct nvkm_subdev *subdev) return iccsense; } +static struct nvkm_iccsense_sensor* +nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id) +{ + + struct nvkm_subdev *subdev = >subdev; + struct nvkm_bios *bios = subdev->device->bios; + struct nvkm_i2c *i2c = subdev->device->i2c; + struct nvbios_extdev_func extdev; + struct nvkm_i2c_bus *i2c_bus; + struct nvkm_iccsense_sensor *sensor; + u8 addr; + + if (!i2c || !bios || nvbios_extdev_parse(bios, id, )) + return NULL; + + if (extdev.type == 0xff) + return NULL; + + if (extdev.type != NVBIOS_EXTDEV_INA209 && + extdev.type != NVBIOS_EXTDEV_INA219 && + extdev.type != NVBIOS_EXTDEV_INA3221) { + iccsense->data_valid = false; + nvkm_error(subdev, "Unknown sensor type %x, power reading " + "disabled\n", extdev.type); + return NULL; + } + + if (extdev.bus) + i2c_bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_SEC); + else + i2c_bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_PRI); + if (!i2c_bus) + return NULL; + + addr = extdev.addr >> 1; + if (!nvkm_iccsense_validate_device(_bus->i2c, addr, +
Re: [Nouveau] [PATCH 4/4] iccsense: configure sensors like nvidia does
On 25/03/16 13:19, Karol Herbst wrote: Signed-off-by: Karol Herbst--- drm/nouveau/nvkm/subdev/iccsense/base.c | 68 + 1 file changed, 68 insertions(+) diff --git a/drm/nouveau/nvkm/subdev/iccsense/base.c b/drm/nouveau/nvkm/subdev/iccsense/base.c index b6f6222..6f3709e 100644 --- a/drm/nouveau/nvkm/subdev/iccsense/base.c +++ b/drm/nouveau/nvkm/subdev/iccsense/base.c @@ -95,6 +95,63 @@ nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense, 40 * 8); } +static void +nvkm_iccsense_ina2x9_config(struct nvkm_iccsense *iccsense, + struct nvkm_iccsense_sensor *sensor) Maybe calling the sensor ina209 and using it also for 219 would be less confusing, especially if a 229 is later released by TI. +{ + struct nvkm_subdev *subdev = >subdev; + /* configuration: +* 0x0007: 0x0007 shunt and bus continous +* 0x0078: 0x0078 128 samples shunt +* 0x0780: 0x0780 128 samples bus +* 0x1800: 0x +-40 mV shunt range +* 0x2000: 0x 16V FSR + */ + u16 value = 0x07ff; + nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value); + nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value); +} + +static void +nvkm_iccsense_ina3221_config(struct nvkm_iccsense *iccsense, +struct nvkm_iccsense_sensor *sensor) +{ + struct nvkm_subdev *subdev = >subdev; + /* configuration: +* 0x0007: 0x0007 shunt and bus continous +* 0x0031: 0x 140 us conversion time shunt +* 0x01c0: 0x 140 us conversion time bus +* 0x0f00: 0x0f00 1024 samples +* 0x7000: 0x?000 channels + */ + u16 value = 0x0e07; + if (sensor->rail_mask & 0x1) + value |= 0x1 << 14; + if (sensor->rail_mask & 0x2) + value |= 0x1 << 13; + if (sensor->rail_mask & 0x4) + value |= 0x1 << 12; + nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value); + nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value); +} + +static void +nvkm_iccsense_sensor_config(struct nvkm_iccsense *iccsense, + struct nvkm_iccsense_sensor *sensor) +{ + switch (sensor->type) { + case NVBIOS_EXTDEV_INA209: + case NVBIOS_EXTDEV_INA219: + nvkm_iccsense_ina2x9_config(iccsense, sensor); + break; + case NVBIOS_EXTDEV_INA3221: + nvkm_iccsense_ina3221_config(iccsense, sensor); + break; + default: + break; + } +} + int nvkm_iccsense_read_all(struct nvkm_iccsense *iccsense) { @@ -257,8 +314,19 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev) return 0; } +static int +nvkm_iccsense_init(struct nvkm_subdev *subdev) +{ + struct nvkm_iccsense *iccsense = nvkm_iccsense(subdev); + struct nvkm_iccsense_sensor *sensor; + list_for_each_entry(sensor, >sensors, head) + nvkm_iccsense_sensor_config(iccsense, sensor); + return 0; +} + struct nvkm_subdev_func iccsense_func = { .oneinit = nvkm_iccsense_oneinit, + .init = nvkm_iccsense_init, .dtor = nvkm_iccsense_dtor, }; Looks like a good cleanup and improvement to me! With the free-ing the lists fixed and maybe the change in name for the ina2x9, this is: Martin Peres ___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
Re: [Nouveau] [PATCH 3/4] iccsense: split sensor into own struct
On 25/03/16 13:19, Karol Herbst wrote: Signed-off-by: Karol Herbst--- drm/nouveau/include/nvkm/subdev/iccsense.h | 1 + drm/nouveau/nvkm/subdev/iccsense/base.c| 141 - drm/nouveau/nvkm/subdev/iccsense/priv.h| 15 ++- 3 files changed, 112 insertions(+), 45 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/iccsense.h b/drm/nouveau/include/nvkm/subdev/iccsense.h index a4c0da0..3c2ddd9 100644 --- a/drm/nouveau/include/nvkm/subdev/iccsense.h +++ b/drm/nouveau/include/nvkm/subdev/iccsense.h @@ -6,6 +6,7 @@ struct nvkm_iccsense { struct nvkm_subdev subdev; bool data_valid; + struct list_head sensors; struct list_head rails; }; diff --git a/drm/nouveau/nvkm/subdev/iccsense/base.c b/drm/nouveau/nvkm/subdev/iccsense/base.c index 6fde68d..b6f6222 100644 --- a/drm/nouveau/nvkm/subdev/iccsense/base.c +++ b/drm/nouveau/nvkm/subdev/iccsense/base.c @@ -30,15 +30,14 @@ static bool nvkm_iccsense_validate_device(struct i2c_adapter *i2c, u8 addr, - enum nvbios_extdev_type type, u8 rail) + enum nvbios_extdev_type type) { switch (type) { case NVBIOS_EXTDEV_INA209: case NVBIOS_EXTDEV_INA219: - return rail == 0 && nv_rd16i2cr(i2c, addr, 0x0) >= 0; + return nv_rd16i2cr(i2c, addr, 0x0) >= 0; case NVBIOS_EXTDEV_INA3221: - return rail <= 3 && - nv_rd16i2cr(i2c, addr, 0xff) == 0x3220 && + return nv_rd16i2cr(i2c, addr, 0xff) == 0x3220 && nv_rd16i2cr(i2c, addr, 0xfe) == 0x5449; default: return false; @@ -67,8 +66,9 @@ nvkm_iccsense_ina2x9_read(struct nvkm_iccsense *iccsense, struct nvkm_iccsense_rail *rail, u8 shunt_reg, u8 bus_reg) { - return nvkm_iccsense_poll_lane(rail->i2c, rail->addr, shunt_reg, 0, - bus_reg, 3, rail->mohm, 10 * 4); + return nvkm_iccsense_poll_lane(rail->sensor->i2c, rail->sensor->addr, + shunt_reg, 0, bus_reg, 3, rail->mohm, + 10 * 4); } static int @@ -89,9 +89,9 @@ static int nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense, struct nvkm_iccsense_rail *rail) { - return nvkm_iccsense_poll_lane(rail->i2c, rail->addr, - 1 + (rail->rail * 2), 3, - 2 + (rail->rail * 2), 3, rail->mohm, + return nvkm_iccsense_poll_lane(rail->sensor->i2c, rail->sensor->addr, + 1 + (rail->idx * 2), 3, + 2 + (rail->idx * 2), 3, rail->mohm, 40 * 8); } @@ -121,81 +121,137 @@ static void * nvkm_iccsense_dtor(struct nvkm_subdev *subdev) { struct nvkm_iccsense *iccsense = nvkm_iccsense(subdev); - struct nvkm_iccsense_rail *rail, *tmp; + struct nvkm_iccsense_sensor *sensor, *tmps; + struct nvkm_iccsense_rail *rail, *tmpr; - list_for_each_entry_safe(rail, tmp, >rails, head) + list_for_each_entry_safe(sensor, tmps, >sensors, head) + kfree(sensor); + list_for_each_entry_safe(rail, tmpr, >rails, head) kfree(rail); Same problem as the last patch. return iccsense; } +static struct nvkm_iccsense_sensor* +nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id) +{ + + struct nvkm_subdev *subdev = >subdev; + struct nvkm_bios *bios = subdev->device->bios; + struct nvkm_i2c *i2c = subdev->device->i2c; + struct nvbios_extdev_func extdev; + struct nvkm_i2c_bus *i2c_bus; + struct nvkm_iccsense_sensor *sensor; + u8 addr; + + if (!i2c || !bios || nvbios_extdev_parse(bios, id, )) + return NULL; + + if (extdev.type == 0xff) + return NULL; + + if (extdev.type != NVBIOS_EXTDEV_INA209 && + extdev.type != NVBIOS_EXTDEV_INA219 && + extdev.type != NVBIOS_EXTDEV_INA3221) { + iccsense->data_valid = false; + nvkm_error(subdev, "found unknown sensor type %x, " + "power reading might be invalid\n", + extdev.type); You do not create the sensor if it is unknown, so why do you say the report might be invalid? Please change it to "Unknown sensor type %x". + return NULL; + } + + if (extdev.bus) + i2c_bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_SEC); + else + i2c_bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_PRI); + if (!i2c_bus) + return NULL; + + addr = extdev.addr >> 1; + if (!nvkm_iccsense_validate_device(_bus->i2c, addr, +
Re: [Nouveau] [PATCH 2/4] iccsense: convert to linked list
On 25/03/16 13:19, Karol Herbst wrote: Signed-off-by: Karol Herbst--- drm/nouveau/include/nvkm/subdev/iccsense.h | 4 +--- drm/nouveau/nouveau_hwmon.c| 2 +- drm/nouveau/nvkm/subdev/iccsense/base.c| 32 +- drm/nouveau/nvkm/subdev/iccsense/priv.h| 1 + 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/iccsense.h b/drm/nouveau/include/nvkm/subdev/iccsense.h index c3defcd..a4c0da0 100644 --- a/drm/nouveau/include/nvkm/subdev/iccsense.h +++ b/drm/nouveau/include/nvkm/subdev/iccsense.h @@ -3,12 +3,10 @@ #include -struct nkvm_iccsense_rail; struct nvkm_iccsense { struct nvkm_subdev subdev; - u8 rail_count; bool data_valid; - struct nvkm_iccsense_rail *rails; + struct list_head rails; }; int gf100_iccsense_new(struct nvkm_device *, int index, struct nvkm_iccsense **); diff --git a/drm/nouveau/nouveau_hwmon.c b/drm/nouveau/nouveau_hwmon.c index 67edd2f..74f237b 100644 --- a/drm/nouveau/nouveau_hwmon.c +++ b/drm/nouveau/nouveau_hwmon.c @@ -689,7 +689,7 @@ nouveau_hwmon_init(struct drm_device *dev) goto error; } - if (iccsense && iccsense->data_valid && iccsense->rail_count) { + if (iccsense && iccsense->data_valid && !list_empty(>rails)) { ret = sysfs_create_group(_dev->kobj, _power_attrgroup); if (ret) diff --git a/drm/nouveau/nvkm/subdev/iccsense/base.c b/drm/nouveau/nvkm/subdev/iccsense/base.c index bf1b94e..6fde68d 100644 --- a/drm/nouveau/nvkm/subdev/iccsense/base.c +++ b/drm/nouveau/nvkm/subdev/iccsense/base.c @@ -98,25 +98,21 @@ nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense, int nvkm_iccsense_read_all(struct nvkm_iccsense *iccsense) { - int result = 0, i; + int result = 0; + struct nvkm_iccsense_rail *rail; if (!iccsense) return -EINVAL; - if (iccsense->rail_count == 0) - return -ENODEV; - - for (i = 0; i < iccsense->rail_count; ++i) { + list_for_each_entry(rail, >rails, head) { int res; - struct nvkm_iccsense_rail *rail = >rails[i]; if (!rail->read) return -ENODEV; res = rail->read(iccsense, rail); - if (res >= 0) - result += res; - else + if (res < 0) return res; + result += res; } return result; } @@ -125,9 +121,10 @@ static void * nvkm_iccsense_dtor(struct nvkm_subdev *subdev) { struct nvkm_iccsense *iccsense = nvkm_iccsense(subdev); + struct nvkm_iccsense_rail *rail, *tmp; - if (iccsense->rails) - kfree(iccsense->rails); + list_for_each_entry_safe(rail, tmp, >rails, head) + kfree(rail); The rails list is filled with invalid pointers at this point. Please add list_del(rail); before kfree(rail); It has the added benefit of adding poisonous pointers that will show any access after freeing. return iccsense; } @@ -145,11 +142,6 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev) || !stbl.nr_entry) return 0; - iccsense->rails = kmalloc(sizeof(*iccsense->rails) * stbl.nr_entry, - GFP_KERNEL); - if (!iccsense->rails) - return -ENOMEM; - iccsense->data_valid = true; for (i = 0; i < stbl.nr_entry; ++i) { struct pwr_rail_t *r = [i]; @@ -184,7 +176,10 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev) continue; } - rail = >rails[iccsense->rail_count]; + rail = kmalloc(sizeof(*rail), GFP_KERNEL); + if (!rail) + return -ENOMEM; + switch (extdev.type) { case NVBIOS_EXTDEV_INA209: rail->read = nvkm_iccsense_ina209_read; @@ -201,7 +196,7 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev) rail->rail = r->rail; rail->mohm = r->resistor_mohm; rail->i2c = _bus->i2c; - ++iccsense->rail_count; + list_add_tail(>head, >rails); } return 0; } @@ -224,6 +219,7 @@ nvkm_iccsense_new_(struct nvkm_device *device, int index, { if (!(*iccsense = kzalloc(sizeof(**iccsense), GFP_KERNEL))) return -ENOMEM; + INIT_LIST_HEAD(&(*iccsense)->rails); nvkm_iccsense_ctor(device, index, *iccsense); return 0; } diff --git a/drm/nouveau/nvkm/subdev/iccsense/priv.h b/drm/nouveau/nvkm/subdev/iccsense/priv.h index ed398b8..e479128 100644 --- a/drm/nouveau/nvkm/subdev/iccsense/priv.h +++ b/drm/nouveau/nvkm/subdev/iccsense/priv.h @@ -4,6 +4,7 @@ #include struct nvkm_iccsense_rail { +
[Nouveau] [Bug 94728] Nouveau doesn't work with Nvidia GTX 960
https://bugs.freedesktop.org/show_bug.cgi?id=94728 Martin Pereschanged: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |NOTABUG --- Comment #2 from Martin Peres --- Yes, you need a more up-to-date kernel and mesa version. That is to say Linux 4.6 and mesa 11.2 which are not released yet. You will also need to update linux-firmware. Maybe rawhide would work for you? -- You are receiving this mail because: You are the assignee for the bug.___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 94728] New: Nouveau doesn't work with Nvidia GTX 960
https://bugs.freedesktop.org/show_bug.cgi?id=94728 Bug ID: 94728 Summary: Nouveau doesn't work with Nvidia GTX 960 Product: xorg Version: unspecified Hardware: x86-64 (AMD64) OS: Linux (All) Status: NEW Severity: normal Priority: medium Component: Driver/nouveau Assignee: nouveau@lists.freedesktop.org Reporter: neilmed...@gmail.com QA Contact: xorg-t...@lists.x.org The nouveau driver doesn't seem to work with my GTX 960 card - I'm getting "Unknown chipset: NV126" message in the logs. Looks like it's then falling back to mesa (gnome-control-center shows graphics as Gallium 0.4 on llvmpipe (LLVM 3.7, 256 bits)). I'm on the latest version Fedora 23, although I haven't seen this work since I got the card. Output of journalctl -b _COMM=gdm-x-session attached. Let me know if you need anymore info - many thanks. (II) [drm] nouveau interface version: 1.3.1 (EE) Unknown chipset: NV126 (II) [drm] nouveau interface version: 1.3.1 (EE) Unknown chipset: NV126 (II) [drm] nouveau interface version: 1.3.1 (EE) Unknown chipset: NV126 (EE) [drm] Failed to open DRM device for pci::01:00.0: -13 (EE) [drm] Failed to open DRM device for pci::01:00.0: -13 -- You are receiving this mail because: You are the assignee for the bug.___ Nouveau mailing list Nouveau@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/nouveau