Skip to content

Commit

Permalink
Set subslice mask according to the per-context option.
Browse files Browse the repository at this point in the history
Fixes #267.
  • Loading branch information
zxye committed Oct 10, 2018
1 parent 94e0dd5 commit bc1c760
Show file tree
Hide file tree
Showing 8 changed files with 364 additions and 41 deletions.
125 changes: 113 additions & 12 deletions media_driver/linux/common/os/libdrm/include/i915_drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,83 @@ typedef struct drm_i915_irq_wait {
#define I915_PARAM_HAS_GPU_RESET 35
#define I915_PARAM_HAS_RESOURCE_STREAMER 36
#define I915_PARAM_HAS_EXEC_SOFTPIN 37
#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51
#define I915_PARAM_HAS_POOLED_EU 38
#define I915_PARAM_MIN_EU_IN_POOL 39
#define I915_PARAM_MMAP_GTT_VERSION 40

/*
* Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution
* priorities and the driver will attempt to execute batches in priority order.
* The param returns a capability bitmask, nonzero implies that the scheduler
* is enabled, with different features present according to the mask.
*
* The initial priority for each batch is supplied by the context and is
* controlled via I915_CONTEXT_PARAM_PRIORITY.
*/
#define I915_PARAM_HAS_SCHEDULER 41
#define I915_SCHEDULER_CAP_ENABLED (1ul << 0)
#define I915_SCHEDULER_CAP_PRIORITY (1ul << 1)
#define I915_SCHEDULER_CAP_PREEMPTION (1ul << 2)

#define I915_PARAM_HUC_STATUS 42

/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to opt-out of
* synchronisation with implicit fencing on individual objects.
* See EXEC_OBJECT_ASYNC.
*/
#define I915_PARAM_HAS_EXEC_ASYNC 43

/* Query whether DRM_I915_GEM_EXECBUFFER2 supports explicit fence support -
* both being able to pass in a sync_file fd to wait upon before executing,
* and being able to return a new sync_file fd that is signaled when the
* current request is complete. See I915_EXEC_FENCE_IN and I915_EXEC_FENCE_OUT.
*/
#define I915_PARAM_HAS_EXEC_FENCE 44

/* Query whether DRM_I915_GEM_EXECBUFFER2 supports the ability to capture
* user specified bufffers for post-mortem debugging of GPU hangs. See
* EXEC_OBJECT_CAPTURE.
*/
#define I915_PARAM_HAS_EXEC_CAPTURE 45

#define I915_PARAM_SLICE_MASK 46

/* Assuming it's uniform for each slice, this queries the mask of subslices
* per-slice for this system.
*/
#define I915_PARAM_SUBSLICE_MASK 47

/*
* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying the batch buffer
* as the first execobject as opposed to the last. See I915_EXEC_BATCH_FIRST.
*/
#define I915_PARAM_HAS_EXEC_BATCH_FIRST 48

/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of
* drm_i915_gem_exec_fence structures. See I915_EXEC_FENCE_ARRAY.
*/
#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49

/*
* Query whether every context (both per-file default and user created) is
* isolated (insofar as HW supports). If this parameter is not true, then
* freshly created contexts may inherit values from an existing context,
* rather than default HW values. If true, it also ensures (insofar as HW
* supports) that all state set by this context will not leak to any other
* context.
*
* As not every engine across every gen support contexts, the returned
* value reports the support of context isolation for individual engines by
* returning a bitmask of each engine class set to true if that class supports
* isolation.
*/
#define I915_PARAM_HAS_CONTEXT_ISOLATION 50

/* Frequency of the command streamer timestamps given by the *_TIMESTAMP
* registers. This used to be fixed per platform but from CNL onwards, this
* might vary depending on the parts.
*/
#define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51

typedef struct drm_i915_getparam {
__s32 param;
Expand Down Expand Up @@ -1343,21 +1419,46 @@ struct drm_i915_gem_context_param {
#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
#define I915_CONTEXT_PARAM_NO_ZEROMAP 0x2
#define I915_CONTEXT_PARAM_GTT_SIZE 0x3
#define I915_CONTEXT_PARAM_SSEU 0x6
#define I915_CONTEXT_PARAM_SSEU 0x8
__u64 value;
};

struct drm_i915_gem_context_param_sseu {
__u64 flags;
union {
struct {
__u8 slice_mask;
__u8 subslice_mask;
__u8 min_eu_per_subslice;
__u8 max_eu_per_subslice;
} packed;
__u64 value;
};
/*
* Engine class & instance to be configured or queried.
*/
__u16 engine_class;
__u16 instance;

/*
* Unused for now. Must be cleared to zero.
*/
__u32 rsvd1;

/*
* Mask of slices to enable for the context. Valid values are a subset
* of the bitmask value returned for I915_PARAM_SLICE_MASK.
*/
__u64 slice_mask;

/*
* Mask of subslices to enable for the context. Valid values are a
* subset of the bitmask value return by I915_PARAM_SUBSLICE_MASK.
*/
__u64 subslice_mask;

/*
* Minimum/Maximum number of EUs to enable per subslice for the
* context. min_eus_per_subslice must be inferior or equal to
* max_eus_per_subslice.
*/
__u16 min_eus_per_subslice;
__u16 max_eus_per_subslice;

/*
* Unused for now. Must be cleared to zero.
*/
__u32 rsvd2;
};

typedef struct drm_i915_ring_load_info
Expand Down
7 changes: 5 additions & 2 deletions media_driver/linux/common/os/libdrm/include/mos_bufmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,6 @@ int mos_get_context_param_sseu(struct mos_linux_context *ctx,
int mos_set_context_param_sseu(struct mos_linux_context *ctx,
struct drm_i915_gem_context_param_sseu sseu);

int mos_get_slice_mask(uint32_t slice_count);

int mos_get_context_param(struct mos_linux_context *ctx,
uint32_t size,
uint64_t param,
Expand All @@ -384,6 +382,11 @@ int mos_set_context_param(struct mos_linux_context *ctx,

int mos_get_subslice_total(int fd, unsigned int *subslice_total);
int mos_get_eu_total(int fd, unsigned int *eu_total);
int mos_get_subslice_mask(int fd, unsigned int *subslice_mask);
int mos_get_slice_mask(int fd, unsigned int *slice_mask);
uint8_t mos_switch_off_n_bits(uint8_t in_mask, int n);
unsigned int mos_hweight8(uint8_t w);

#if defined(__cplusplus)
extern "C" {
#endif
Expand Down
72 changes: 63 additions & 9 deletions media_driver/linux/common/os/libdrm/mos_bufmgr.c
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -4695,20 +4695,40 @@ mos_get_reset_stats(struct mos_linux_context *ctx,
return ret;
}

int mos_get_slice_mask(uint32_t slice_count)
unsigned mos_hweight8(uint8_t w)
{
uint32_t bitflag = 1;
uint32_t bitmask = 0;
int count = 0;
uint32_t i, weight = 0;

while (count < slice_count)
for (i=0; i<8; i++)
{
bitmask = bitflag;
bitflag = bitmask | (bitflag << 1);
count++;
weight += !!((w) & (1UL << i));
}
return weight;
}

uint8_t mos_switch_off_n_bits(uint8_t in_mask, int n)
{
int i,count;
uint8_t bi,out_mask;

return bitmask;
assert (n>0 && n<=8);

out_mask = in_mask;
count = n;
for(i=0; i<8; i++)
{
bi = 1UL<<i;
if (bi & in_mask)
{
out_mask &= ~bi;
count--;
}
if (count==0)
{
break;
}
}
return out_mask;
}

int
Expand All @@ -4727,6 +4747,7 @@ mos_get_context_param_sseu(struct mos_linux_context *ctx,
context_param.ctx_id = ctx->ctx_id;
context_param.param = I915_CONTEXT_PARAM_SSEU;
context_param.value = (uint64_t) sseu;
context_param.size = sizeof(struct drm_i915_gem_context_param_sseu);

ret = drmIoctl(bufmgr_gem->fd,
DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM,
Expand All @@ -4751,6 +4772,7 @@ mos_set_context_param_sseu(struct mos_linux_context *ctx,
context_param.ctx_id = ctx->ctx_id;
context_param.param = I915_CONTEXT_PARAM_SSEU;
context_param.value = (uint64_t) &sseu;
context_param.size = sizeof(struct drm_i915_gem_context_param_sseu);

ret = drmIoctl(bufmgr_gem->fd,
DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM,
Expand Down Expand Up @@ -4846,6 +4868,38 @@ mos_get_subslice_total(int fd, unsigned int *subslice_total)
return 0;
}

int
mos_get_subslice_mask(int fd, unsigned int *subslice_mask)
{
drm_i915_getparam_t gp;
int ret;

memclear(gp);
gp.value = (int*)subslice_mask;
gp.param = I915_PARAM_SUBSLICE_MASK;
ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
if (ret)
return -errno;

return 0;
}

int
mos_get_slice_mask(int fd, unsigned int *slice_mask)
{
drm_i915_getparam_t gp;
int ret;

memclear(gp);
gp.value = (int*)slice_mask;
gp.param = I915_PARAM_SLICE_MASK;
ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
if (ret)
return -errno;

return 0;
}

int
mos_get_eu_total(int fd, unsigned int *eu_total)
{
Expand Down
39 changes: 33 additions & 6 deletions media_driver/linux/common/os/mos_context_specific.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,24 +453,42 @@ void OsContextSpecific::SetSliceCount(uint32_t *pSliceCount)
}
}

struct drm_i915_gem_context_param_sseu sseu = { .flags = I915_EXEC_RENDER };
sseu.value = m_sseu;
sliceMask = mos_get_slice_mask(sliceCount);
struct drm_i915_gem_context_param_sseu sseu;
MOS_ZeroMemory(&sseu, sizeof(sseu));
sseu.engine_class = 0;
sseu.instance = 0;

if (sliceMask != sseu.packed.slice_mask)
if (sliceCount != mos_hweight8(m_sseu.slice_mask))
{
if (mos_get_context_param_sseu(m_intelContext, &sseu))
{
MOS_OS_ASSERTMESSAGE("Failed to get context parameter.");
return ;
};
sseu.packed.slice_mask = sliceMask;

unsigned int device_slice_mask;
if (mos_get_slice_mask(m_fd, &device_slice_mask))
{
MOS_OS_ASSERTMESSAGE("Failed to get device slice mask.");
return ;
}

if (mos_hweight8(device_slice_mask) > sliceCount)
{
sseu.slice_mask = mos_switch_off_n_bits((uint8_t)device_slice_mask,
mos_hweight8(device_slice_mask) - sliceCount);
}
else
{
sseu.slice_mask = device_slice_mask;
}

if (mos_set_context_param_sseu(m_intelContext, sseu))
{
MOS_OS_ASSERTMESSAGE("Failed to set context parameter.");
return ;
}
m_sseu = sseu.value;
m_sseu = sseu;
}

*pSliceCount = sliceCount;
Expand Down Expand Up @@ -559,6 +577,15 @@ MOS_STATUS OsContextSpecific::Init(PMOS_CONTEXT pOsDriverContext)
MOS_OS_ASSERTMESSAGE("Failed to create drm intel context");
return MOS_STATUS_UNKNOWN;
}

MOS_ZeroMemory(&m_sseu, sizeof(m_sseu));
m_sseu.engine_class = 0;
m_sseu.instance = 0;
if (mos_get_context_param_sseu(m_intelContext, &m_sseu))
{
MOS_OS_ASSERTMESSAGE("Failed to get context parameter sseu.");
return MOS_STATUS_UNKNOWN;
};
#else
m_intelContext = nullptr;
#endif
Expand Down
2 changes: 1 addition & 1 deletion media_driver/linux/common/os/mos_context_specific.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ class OsContextSpecific : public OsContext
//!
//! \brief sseu for current context
//!
uint64_t m_sseu = 0;
struct drm_i915_gem_context_param_sseu m_sseu;
//!
//! \brief Semophore ID for ruling SSEU configration
//!
Expand Down
34 changes: 34 additions & 0 deletions media_driver/linux/common/os/mos_os_specific.c
Original file line number Diff line number Diff line change
Expand Up @@ -3790,6 +3790,40 @@ MOS_STATUS Mos_Specific_CreateGpuContext(
pOsContextSpecific->SetGpuContextHandle(mosGpuCxt, gpuContextSpecific->GetGpuContextHandle());
}

MOS_OS_CHK_NULL_RETURN(createOption);
if (createOption->SSEUValue)
{
unsigned int subslice_mask;
struct drm_i915_gem_context_param_sseu sseu;
MOS_ZeroMemory(&sseu, sizeof(sseu));
sseu.engine_class = 0;
sseu.instance = 0;

if (mos_get_context_param_sseu(pOsInterface->pOsContext->intel_context, &sseu))
{
MOS_OS_ASSERTMESSAGE("Failed to get sseu configuration.");
return MOS_STATUS_UNKNOWN;
};

if (mos_get_subslice_mask(pOsInterface->pOsContext->fd, &subslice_mask))
{
MOS_OS_ASSERTMESSAGE("Failed to get subslice mask.");
return MOS_STATUS_UNKNOWN;
}

if (mos_hweight8(sseu.subslice_mask) > createOption->packed.SubSliceCount)
{
sseu.subslice_mask = mos_switch_off_n_bits(subslice_mask,
mos_hweight8((uint8_t)subslice_mask)-createOption->packed.SubSliceCount);
}

if (mos_set_context_param_sseu(pOsInterface->pOsContext->intel_context, sseu))
{
MOS_OS_ASSERTMESSAGE("Failed to set sseu configuration.");
return MOS_STATUS_UNKNOWN;
};
}

return MOS_STATUS_SUCCESS;
}

Expand Down
Loading

0 comments on commit bc1c760

Please sign in to comment.