Commit 309b8c89 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau: downgrade severity of most init table parser errors

As long as we know the length of the opcode, we're probably better off
trying to parse the remainder of an init table rather than aborting in
the middle of it.
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 8f1a6086
...@@ -935,7 +935,7 @@ init_io_restrict_prog(struct nvbios *bios, uint16_t offset, ...@@ -935,7 +935,7 @@ init_io_restrict_prog(struct nvbios *bios, uint16_t offset,
NV_ERROR(bios->dev, NV_ERROR(bios->dev,
"0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
offset, config, count); offset, config, count);
return -EINVAL; return len;
} }
configval = ROM32(bios->data[offset + 11 + config * 4]); configval = ROM32(bios->data[offset + 11 + config * 4]);
...@@ -1037,7 +1037,7 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset, ...@@ -1037,7 +1037,7 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset,
NV_ERROR(bios->dev, NV_ERROR(bios->dev,
"0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
offset, config, count); offset, config, count);
return -EINVAL; return len;
} }
freq = ROM16(bios->data[offset + 12 + config * 2]); freq = ROM16(bios->data[offset + 12 + config * 2]);
...@@ -1209,7 +1209,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1209,7 +1209,7 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
dpe = nouveau_bios_dp_table(dev, dcb, &dummy); dpe = nouveau_bios_dp_table(dev, dcb, &dummy);
if (!dpe) { if (!dpe) {
NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset); NV_ERROR(dev, "0x%04X: INIT_3A: no encoder table!!\n", offset);
return -EINVAL; return 3;
} }
switch (cond) { switch (cond) {
...@@ -1233,12 +1233,16 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1233,12 +1233,16 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
int ret; int ret;
auxch = nouveau_i2c_find(dev, bios->display.output->i2c_index); auxch = nouveau_i2c_find(dev, bios->display.output->i2c_index);
if (!auxch) if (!auxch) {
return -ENODEV; NV_ERROR(dev, "0x%04X: couldn't get auxch\n", offset);
return 3;
}
ret = nouveau_dp_auxch(auxch, 9, 0xd, &cond, 1); ret = nouveau_dp_auxch(auxch, 9, 0xd, &cond, 1);
if (ret) if (ret) {
return ret; NV_ERROR(dev, "0x%04X: auxch rd fail: %d\n", offset, ret);
return 3;
}
if (cond & 1) if (cond & 1)
iexec->execute = false; iexec->execute = false;
...@@ -1407,7 +1411,7 @@ init_io_restrict_pll2(struct nvbios *bios, uint16_t offset, ...@@ -1407,7 +1411,7 @@ init_io_restrict_pll2(struct nvbios *bios, uint16_t offset,
NV_ERROR(bios->dev, NV_ERROR(bios->dev,
"0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
offset, config, count); offset, config, count);
return -EINVAL; return len;
} }
freq = ROM32(bios->data[offset + 11 + config * 4]); freq = ROM32(bios->data[offset + 11 + config * 4]);
...@@ -1467,6 +1471,7 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1467,6 +1471,7 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
* "mask n" and OR it with "data n" before writing it back to the device * "mask n" and OR it with "data n" before writing it back to the device
*/ */
struct drm_device *dev = bios->dev;
uint8_t i2c_index = bios->data[offset + 1]; uint8_t i2c_index = bios->data[offset + 1];
uint8_t i2c_address = bios->data[offset + 2] >> 1; uint8_t i2c_address = bios->data[offset + 2] >> 1;
uint8_t count = bios->data[offset + 3]; uint8_t count = bios->data[offset + 3];
...@@ -1481,9 +1486,11 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1481,9 +1486,11 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
"Count: 0x%02X\n", "Count: 0x%02X\n",
offset, i2c_index, i2c_address, count); offset, i2c_index, i2c_address, count);
chan = init_i2c_device_find(bios->dev, i2c_index); chan = init_i2c_device_find(dev, i2c_index);
if (!chan) if (!chan) {
return -ENODEV; NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset);
return len;
}
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
uint8_t reg = bios->data[offset + 4 + i * 3]; uint8_t reg = bios->data[offset + 4 + i * 3];
...@@ -1494,8 +1501,10 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1494,8 +1501,10 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0,
I2C_SMBUS_READ, reg, I2C_SMBUS_READ, reg,
I2C_SMBUS_BYTE_DATA, &val); I2C_SMBUS_BYTE_DATA, &val);
if (ret < 0) if (ret < 0) {
return ret; NV_ERROR(dev, "0x%04X: i2c rd fail: %d\n", offset, ret);
return len;
}
BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, " BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, "
"Mask: 0x%02X, Data: 0x%02X\n", "Mask: 0x%02X, Data: 0x%02X\n",
...@@ -1509,8 +1518,10 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1509,8 +1518,10 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0,
I2C_SMBUS_WRITE, reg, I2C_SMBUS_WRITE, reg,
I2C_SMBUS_BYTE_DATA, &val); I2C_SMBUS_BYTE_DATA, &val);
if (ret < 0) if (ret < 0) {
return ret; NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret);
return len;
}
} }
return len; return len;
...@@ -1535,6 +1546,7 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1535,6 +1546,7 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
* "DCB I2C table entry index", set the register to "data n" * "DCB I2C table entry index", set the register to "data n"
*/ */
struct drm_device *dev = bios->dev;
uint8_t i2c_index = bios->data[offset + 1]; uint8_t i2c_index = bios->data[offset + 1];
uint8_t i2c_address = bios->data[offset + 2] >> 1; uint8_t i2c_address = bios->data[offset + 2] >> 1;
uint8_t count = bios->data[offset + 3]; uint8_t count = bios->data[offset + 3];
...@@ -1549,9 +1561,11 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1549,9 +1561,11 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
"Count: 0x%02X\n", "Count: 0x%02X\n",
offset, i2c_index, i2c_address, count); offset, i2c_index, i2c_address, count);
chan = init_i2c_device_find(bios->dev, i2c_index); chan = init_i2c_device_find(dev, i2c_index);
if (!chan) if (!chan) {
return -ENODEV; NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset);
return len;
}
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
uint8_t reg = bios->data[offset + 4 + i * 2]; uint8_t reg = bios->data[offset + 4 + i * 2];
...@@ -1568,8 +1582,10 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1568,8 +1582,10 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0,
I2C_SMBUS_WRITE, reg, I2C_SMBUS_WRITE, reg,
I2C_SMBUS_BYTE_DATA, &val); I2C_SMBUS_BYTE_DATA, &val);
if (ret < 0) if (ret < 0) {
return ret; NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret);
return len;
}
} }
return len; return len;
...@@ -1592,6 +1608,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1592,6 +1608,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
* address" on the I2C bus given by "DCB I2C table entry index" * address" on the I2C bus given by "DCB I2C table entry index"
*/ */
struct drm_device *dev = bios->dev;
uint8_t i2c_index = bios->data[offset + 1]; uint8_t i2c_index = bios->data[offset + 1];
uint8_t i2c_address = bios->data[offset + 2] >> 1; uint8_t i2c_address = bios->data[offset + 2] >> 1;
uint8_t count = bios->data[offset + 3]; uint8_t count = bios->data[offset + 3];
...@@ -1599,7 +1616,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1599,7 +1616,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
struct nouveau_i2c_chan *chan; struct nouveau_i2c_chan *chan;
struct i2c_msg msg; struct i2c_msg msg;
uint8_t data[256]; uint8_t data[256];
int i; int ret, i;
if (!iexec->execute) if (!iexec->execute)
return len; return len;
...@@ -1608,9 +1625,11 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1608,9 +1625,11 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
"Count: 0x%02X\n", "Count: 0x%02X\n",
offset, i2c_index, i2c_address, count); offset, i2c_index, i2c_address, count);
chan = init_i2c_device_find(bios->dev, i2c_index); chan = init_i2c_device_find(dev, i2c_index);
if (!chan) if (!chan) {
return -ENODEV; NV_ERROR(dev, "0x%04X: i2c bus not found\n", offset);
return len;
}
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
data[i] = bios->data[offset + 4 + i]; data[i] = bios->data[offset + 4 + i];
...@@ -1623,8 +1642,11 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1623,8 +1642,11 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
msg.flags = 0; msg.flags = 0;
msg.len = count; msg.len = count;
msg.buf = data; msg.buf = data;
if (i2c_transfer(&chan->adapter, &msg, 1) != 1) ret = i2c_transfer(&chan->adapter, &msg, 1);
return -EIO; if (ret != 1) {
NV_ERROR(dev, "0x%04X: i2c wr fail: %d\n", offset, ret);
return len;
}
} }
return len; return len;
...@@ -1648,6 +1670,7 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1648,6 +1670,7 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
* used -- see get_tmds_index_reg() * used -- see get_tmds_index_reg()
*/ */
struct drm_device *dev = bios->dev;
uint8_t mlv = bios->data[offset + 1]; uint8_t mlv = bios->data[offset + 1];
uint32_t tmdsaddr = bios->data[offset + 2]; uint32_t tmdsaddr = bios->data[offset + 2];
uint8_t mask = bios->data[offset + 3]; uint8_t mask = bios->data[offset + 3];
...@@ -1662,8 +1685,10 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1662,8 +1685,10 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
offset, mlv, tmdsaddr, mask, data); offset, mlv, tmdsaddr, mask, data);
reg = get_tmds_index_reg(bios->dev, mlv); reg = get_tmds_index_reg(bios->dev, mlv);
if (!reg) if (!reg) {
return -EINVAL; NV_ERROR(dev, "0x%04X: no tmds_index_reg\n", offset);
return 5;
}
bios_wr32(bios, reg, bios_wr32(bios, reg,
tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE); tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
...@@ -1693,6 +1718,7 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset, ...@@ -1693,6 +1718,7 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset,
* register is used -- see get_tmds_index_reg() * register is used -- see get_tmds_index_reg()
*/ */
struct drm_device *dev = bios->dev;
uint8_t mlv = bios->data[offset + 1]; uint8_t mlv = bios->data[offset + 1];
uint8_t count = bios->data[offset + 2]; uint8_t count = bios->data[offset + 2];
int len = 3 + count * 2; int len = 3 + count * 2;
...@@ -1706,8 +1732,10 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset, ...@@ -1706,8 +1732,10 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset,
offset, mlv, count); offset, mlv, count);
reg = get_tmds_index_reg(bios->dev, mlv); reg = get_tmds_index_reg(bios->dev, mlv);
if (!reg) if (!reg) {
return -EINVAL; NV_ERROR(dev, "0x%04X: no tmds_index_reg\n", offset);
return len;
}
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
uint8_t tmdsaddr = bios->data[offset + 3 + i * 2]; uint8_t tmdsaddr = bios->data[offset + 3 + i * 2];
...@@ -2816,7 +2844,7 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -2816,7 +2844,7 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
if (dev_priv->card_type != NV_50) { if (dev_priv->card_type != NV_50) {
NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n");
return -ENODEV; return 1;
} }
if (!iexec->execute) if (!iexec->execute)
...@@ -2888,10 +2916,7 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset, ...@@ -2888,10 +2916,7 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset,
uint8_t index; uint8_t index;
int i; int i;
/* critical! to know the length of the opcode */;
if (!iexec->execute)
return len;
if (!blocklen) { if (!blocklen) {
NV_ERROR(bios->dev, NV_ERROR(bios->dev,
"0x%04X: Zero block length - has the M table " "0x%04X: Zero block length - has the M table "
...@@ -2899,6 +2924,9 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset, ...@@ -2899,6 +2924,9 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset,
return -EINVAL; return -EINVAL;
} }
if (!iexec->execute)
return len;
strap_ramcfg = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 2) & 0xf; strap_ramcfg = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 2) & 0xf;
index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg]; index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg];
...@@ -3080,14 +3108,14 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -3080,14 +3108,14 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
if (!bios->display.output) { if (!bios->display.output) {
NV_ERROR(dev, "INIT_AUXCH: no active output\n"); NV_ERROR(dev, "INIT_AUXCH: no active output\n");
return -EINVAL; return len;
} }
auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); auxch = init_i2c_device_find(dev, bios->display.output->i2c_index);
if (!auxch) { if (!auxch) {
NV_ERROR(dev, "INIT_AUXCH: couldn't get auxch %d\n", NV_ERROR(dev, "INIT_AUXCH: couldn't get auxch %d\n",
bios->display.output->i2c_index); bios->display.output->i2c_index);
return -ENODEV; return len;
} }
if (!iexec->execute) if (!iexec->execute)
...@@ -3100,7 +3128,7 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -3100,7 +3128,7 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
ret = nouveau_dp_auxch(auxch, 9, addr, &data, 1); ret = nouveau_dp_auxch(auxch, 9, addr, &data, 1);
if (ret) { if (ret) {
NV_ERROR(dev, "INIT_AUXCH: rd auxch fail %d\n", ret); NV_ERROR(dev, "INIT_AUXCH: rd auxch fail %d\n", ret);
return ret; return len;
} }
data &= bios->data[offset + 0]; data &= bios->data[offset + 0];
...@@ -3109,7 +3137,7 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -3109,7 +3137,7 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
ret = nouveau_dp_auxch(auxch, 8, addr, &data, 1); ret = nouveau_dp_auxch(auxch, 8, addr, &data, 1);
if (ret) { if (ret) {
NV_ERROR(dev, "INIT_AUXCH: wr auxch fail %d\n", ret); NV_ERROR(dev, "INIT_AUXCH: wr auxch fail %d\n", ret);
return ret; return len;
} }
} }
...@@ -3139,14 +3167,14 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -3139,14 +3167,14 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
if (!bios->display.output) { if (!bios->display.output) {
NV_ERROR(dev, "INIT_ZM_AUXCH: no active output\n"); NV_ERROR(dev, "INIT_ZM_AUXCH: no active output\n");
return -EINVAL; return len;
} }
auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); auxch = init_i2c_device_find(dev, bios->display.output->i2c_index);
if (!auxch) { if (!auxch) {
NV_ERROR(dev, "INIT_ZM_AUXCH: couldn't get auxch %d\n", NV_ERROR(dev, "INIT_ZM_AUXCH: couldn't get auxch %d\n",
bios->display.output->i2c_index); bios->display.output->i2c_index);
return -ENODEV; return len;
} }
if (!iexec->execute) if (!iexec->execute)
...@@ -3157,7 +3185,7 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -3157,7 +3185,7 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
ret = nouveau_dp_auxch(auxch, 8, addr, &bios->data[offset], 1); ret = nouveau_dp_auxch(auxch, 8, addr, &bios->data[offset], 1);
if (ret) { if (ret) {
NV_ERROR(dev, "INIT_ZM_AUXCH: wr auxch fail %d\n", ret); NV_ERROR(dev, "INIT_ZM_AUXCH: wr auxch fail %d\n", ret);
return ret; return len;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment