drm/nv50-/disp: audit and version DAC_LOAD method
The full object interfaces are about to be exposed to userspace, so we need to check for any security-related issues and version the structs to make it easier to handle any changes we may need in the future. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
bf0eb89859
commit
c4abd3178e
10 changed files with 48 additions and 51 deletions
|
@ -63,9 +63,24 @@ nv50_dac_power(NV50_DISP_MTHD_V1)
|
|||
}
|
||||
|
||||
int
|
||||
nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval)
|
||||
nv50_dac_sense(NV50_DISP_MTHD_V1)
|
||||
{
|
||||
const u32 doff = (or * 0x800);
|
||||
union {
|
||||
struct nv50_disp_dac_load_v0 v0;
|
||||
} *args = data;
|
||||
const u32 doff = outp->or * 0x800;
|
||||
u32 loadval;
|
||||
int ret;
|
||||
|
||||
nv_ioctl(object, "disp dac load size %d\n", size);
|
||||
if (nvif_unpack(args->v0, 0, 0, false)) {
|
||||
nv_ioctl(object, "disp dac load vers %d data %08x\n",
|
||||
args->v0.version, args->v0.data);
|
||||
if (args->v0.data & 0xfff00000)
|
||||
return -EINVAL;
|
||||
loadval = args->v0.data;
|
||||
} else
|
||||
return ret;
|
||||
|
||||
nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000);
|
||||
nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
|
||||
|
@ -78,35 +93,10 @@ nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval)
|
|||
nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000);
|
||||
nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000);
|
||||
|
||||
nv_debug(priv, "DAC%d sense: 0x%08x\n", or, loadval);
|
||||
nv_debug(priv, "DAC%d sense: 0x%08x\n", outp->or, loadval);
|
||||
if (!(loadval & 0x80000000))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return (loadval & 0x38000000) >> 27;
|
||||
}
|
||||
|
||||
int
|
||||
nv50_dac_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
|
||||
{
|
||||
struct nv50_disp_priv *priv = (void *)object->engine;
|
||||
const u8 or = (mthd & NV50_DISP_DAC_MTHD_OR);
|
||||
u32 *data = args;
|
||||
int ret;
|
||||
|
||||
if (size < sizeof(u32))
|
||||
return -EINVAL;
|
||||
|
||||
switch (mthd & ~0x3f) {
|
||||
case NV50_DISP_DAC_LOAD:
|
||||
ret = priv->dac.sense(priv, or, data[0]);
|
||||
if (ret >= 0) {
|
||||
data[0] = ret;
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG_ON(1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
args->v0.load = (loadval & 0x38000000) >> 27;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -901,6 +901,8 @@ nv50_disp_base_mthd(struct nouveau_object *object, u32 mthd,
|
|||
switch (mthd * !!outp) {
|
||||
case NV50_DISP_MTHD_V1_DAC_PWR:
|
||||
return priv->dac.power(object, priv, data, size, head, outp);
|
||||
case NV50_DISP_MTHD_V1_DAC_LOAD:
|
||||
return priv->dac.sense(object, priv, data, size, head, outp);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1031,7 +1033,6 @@ nv50_disp_base_omthds[] = {
|
|||
{ HEAD_MTHD(NV50_DISP_SCANOUTPOS) , nv50_disp_base_scanoutpos },
|
||||
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
||||
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
||||
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
|
||||
|
|
|
@ -42,7 +42,7 @@ struct nv50_disp_priv {
|
|||
struct {
|
||||
int nr;
|
||||
int (*power)(NV50_DISP_MTHD_V1);
|
||||
int (*sense)(struct nv50_disp_priv *, int dac, u32 load);
|
||||
int (*sense)(NV50_DISP_MTHD_V1);
|
||||
} dac;
|
||||
struct {
|
||||
int nr;
|
||||
|
@ -65,9 +65,8 @@ int nv50_disp_base_mthd(struct nouveau_object *, u32, void *, u32);
|
|||
|
||||
#define DAC_MTHD(n) (n), (n) + 0x03
|
||||
|
||||
int nv50_dac_mthd(struct nouveau_object *, u32, void *, u32);
|
||||
int nv50_dac_power(NV50_DISP_MTHD_V1);
|
||||
int nv50_dac_sense(struct nv50_disp_priv *, int, u32);
|
||||
int nv50_dac_sense(NV50_DISP_MTHD_V1);
|
||||
|
||||
#define SOR_MTHD(n) (n), (n) + 0x3f
|
||||
|
||||
|
|
|
@ -218,7 +218,6 @@ nv84_disp_base_omthds[] = {
|
|||
{ SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd },
|
||||
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
|
||||
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
||||
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
|
||||
|
|
|
@ -78,7 +78,6 @@ nv94_disp_base_omthds[] = {
|
|||
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
|
||||
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
||||
{ SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
|
||||
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
|
||||
|
|
|
@ -51,7 +51,6 @@ nva3_disp_base_omthds[] = {
|
|||
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
|
||||
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
||||
{ SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
|
||||
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
|
||||
|
|
|
@ -717,7 +717,6 @@ nvd0_disp_base_omthds[] = {
|
|||
{ SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd },
|
||||
{ SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd },
|
||||
{ SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd },
|
||||
{ DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd },
|
||||
{ PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd },
|
||||
|
|
|
@ -77,13 +77,6 @@ struct nv04_display_scanoutpos {
|
|||
#define NV94_DISP_SOR_DP_PWR_STATE_OFF 0x00000000
|
||||
#define NV94_DISP_SOR_DP_PWR_STATE_ON 0x00000001
|
||||
|
||||
#define NV50_DISP_DAC_MTHD 0x00020000
|
||||
#define NV50_DISP_DAC_MTHD_TYPE 0x0000f000
|
||||
#define NV50_DISP_DAC_MTHD_OR 0x00000003
|
||||
|
||||
#define NV50_DISP_DAC_LOAD 0x00020100
|
||||
#define NV50_DISP_DAC_LOAD_VALUE 0x00000007
|
||||
|
||||
#define NV50_DISP_PIOR_MTHD 0x00030000
|
||||
#define NV50_DISP_PIOR_MTHD_TYPE 0x0000f000
|
||||
#define NV50_DISP_PIOR_MTHD_OR 0x00000003
|
||||
|
|
|
@ -1590,14 +1590,25 @@ nv50_dac_disconnect(struct drm_encoder *encoder)
|
|||
static enum drm_connector_status
|
||||
nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
|
||||
{
|
||||
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
||||
struct nv50_disp *disp = nv50_disp(encoder->dev);
|
||||
int ret, or = nouveau_encoder(encoder)->or;
|
||||
u32 load = nouveau_drm(encoder->dev)->vbios.dactestval;
|
||||
if (load == 0)
|
||||
load = 340;
|
||||
struct {
|
||||
struct nv50_disp_mthd_v1 base;
|
||||
struct nv50_disp_dac_load_v0 load;
|
||||
} args = {
|
||||
.base.version = 1,
|
||||
.base.method = NV50_DISP_MTHD_V1_DAC_LOAD,
|
||||
.base.hasht = nv_encoder->dcb->hasht,
|
||||
.base.hashm = nv_encoder->dcb->hashm,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = nvif_exec(disp->disp, NV50_DISP_DAC_LOAD + or, &load, sizeof(load));
|
||||
if (ret || !load)
|
||||
args.load.data = nouveau_drm(encoder->dev)->vbios.dactestval;
|
||||
if (args.load.data == 0)
|
||||
args.load.data = 340;
|
||||
|
||||
ret = nvif_mthd(disp->disp, 0, &args, sizeof(args));
|
||||
if (ret || !args.load.load)
|
||||
return connector_status_disconnected;
|
||||
|
||||
return connector_status_connected;
|
||||
|
|
|
@ -333,4 +333,11 @@ struct nv50_disp_dac_pwr_v0 {
|
|||
__u8 pad05[3];
|
||||
};
|
||||
|
||||
struct nv50_disp_dac_load_v0 {
|
||||
__u8 version;
|
||||
__u8 load;
|
||||
__u16 data;
|
||||
__u8 pad04[4];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue