Skip to content

Commit

Permalink
build with 6.6 vanilla kernel
Browse files Browse the repository at this point in the history
  • Loading branch information
bbaa-bbaa committed Oct 6, 2024
1 parent 3b9db78 commit 0e25f11
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 12 deletions.
9 changes: 2 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
# Linux i915 driver (dkms module) with SR-IOV support for linux 6.1 ~ linux 6.11
# Linux i915 driver (dkms module) with SR-IOV support for linux (6.6)6.8 ~ linux 6.11

Originally from [linux-intel-lts](https://github.com/intel/linux-intel-lts/tree/lts-v5.15.49-adl-linux-220826T092047Z/drivers/gpu/drm/i915)
Update to [6.1.12](https://github.com/intel/linux-intel-lts/tree/lts-v6.1.12-linux-230415T124447Z/drivers/gpu/drm/i915)

## Update Notice

The i915 module parameter to enable SR-IOV functionality has changed since [commit #092d1cf](https://github.com/strongtz/i915-sriov-dkms/commit/092d1cf126f31eca3c1de4673e537c3c5f1e6ab4). If you are updating from previous version, please modify `i915.enable_guc=7` to **`i915.enable_guc=3 i915.max_vfs=7`** in your kernel command line or in the corresponding modprobe config file.
Originally from [linux-intel-lts#lts-v6.6.50-linux-240925T091328Z](https://github.com/intel/linux-intel-lts/tree/lts-v6.6.50-linux-240925T091328Z/drivers/gpu/drm/i915)

## Warning

Expand Down
234 changes: 234 additions & 0 deletions backport/drivers/gpu/drm/display/drm_dp_mst_topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,238 @@ drm_dp_mst_port_downstream_of_parent(struct drm_dp_mst_topology_mgr *mgr,
mutex_unlock(&mgr->lock);
return ret;
}
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0)
// https://github.com/gregkh/linux/commit/1cd0a5ea427931016c3e95b20dc20f17604937cc

static bool drm_dp_mst_is_end_device(u8 pdt, bool mcs)
{
switch (pdt) {
case DP_PEER_DEVICE_DP_LEGACY_CONV:
case DP_PEER_DEVICE_SST_SINK:
return true;
case DP_PEER_DEVICE_MST_BRANCHING:
/* For sst branch device */
if (!mcs)
return true;

return false;
}
return true;
}


static int
drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
struct drm_dp_mst_topology_state *state,
struct drm_dp_mst_port **failing_port);

static int
drm_dp_mst_atomic_check_mstb_bw_limit(struct drm_dp_mst_branch *mstb,
struct drm_dp_mst_topology_state *state,
struct drm_dp_mst_port **failing_port)
{
struct drm_dp_mst_atomic_payload *payload;
struct drm_dp_mst_port *port;
int pbn_used = 0, ret;
bool found = false;

/* Check that we have at least one port in our state that's downstream
* of this branch, otherwise we can skip this branch
*/
list_for_each_entry(payload, &state->payloads, next) {
if (!payload->pbn ||
!drm_dp_mst_port_downstream_of_branch(payload->port, mstb))
continue;

found = true;
break;
}
if (!found)
return 0;

if (mstb->port_parent)
drm_dbg_atomic(mstb->mgr->dev,
"[MSTB:%p] [MST PORT:%p] Checking bandwidth limits on [MSTB:%p]\n",
mstb->port_parent->parent, mstb->port_parent, mstb);
else
drm_dbg_atomic(mstb->mgr->dev, "[MSTB:%p] Checking bandwidth limits\n", mstb);

list_for_each_entry(port, &mstb->ports, next) {
ret = drm_dp_mst_atomic_check_port_bw_limit(port, state, failing_port);
if (ret < 0)
return ret;

pbn_used += ret;
}

return pbn_used;
}


static int
drm_dp_mst_atomic_check_port_bw_limit(struct drm_dp_mst_port *port,
struct drm_dp_mst_topology_state *state,
struct drm_dp_mst_port **failing_port)
{
struct drm_dp_mst_atomic_payload *payload;
int pbn_used = 0;

if (port->pdt == DP_PEER_DEVICE_NONE)
return 0;

if (drm_dp_mst_is_end_device(port->pdt, port->mcs)) {
payload = drm_atomic_get_mst_payload_state(state, port);
if (!payload)
return 0;

/*
* This could happen if the sink deasserted its HPD line, but
* the branch device still reports it as attached (PDT != NONE).
*/
if (!port->full_pbn) {
drm_dbg_atomic(port->mgr->dev,
"[MSTB:%p] [MST PORT:%p] no BW available for the port\n",
port->parent, port);
*failing_port = port;
return -EINVAL;
}

pbn_used = payload->pbn;
} else {
pbn_used = drm_dp_mst_atomic_check_mstb_bw_limit(port->mstb,
state,
failing_port);
if (pbn_used <= 0)
return pbn_used;
}

if (pbn_used > port->full_pbn) {
drm_dbg_atomic(port->mgr->dev,
"[MSTB:%p] [MST PORT:%p] required PBN of %d exceeds port limit of %d\n",
port->parent, port, pbn_used, port->full_pbn);
*failing_port = port;
return -ENOSPC;
}

drm_dbg_atomic(port->mgr->dev, "[MSTB:%p] [MST PORT:%p] uses %d out of %d PBN\n",
port->parent, port, pbn_used, port->full_pbn);

return pbn_used;
}


static inline int
drm_dp_mst_atomic_check_payload_alloc_limits(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_topology_state *mst_state)
{
struct drm_dp_mst_atomic_payload *payload;
int avail_slots = mst_state->total_avail_slots, payload_count = 0;

list_for_each_entry(payload, &mst_state->payloads, next) {
/* Releasing payloads is always OK-even if the port is gone */
if (payload->delete) {
drm_dbg_atomic(mgr->dev, "[MST PORT:%p] releases all time slots\n",
payload->port);
continue;
}

drm_dbg_atomic(mgr->dev, "[MST PORT:%p] requires %d time slots\n",
payload->port, payload->time_slots);

avail_slots -= payload->time_slots;
if (avail_slots < 0) {
drm_dbg_atomic(mgr->dev,
"[MST PORT:%p] not enough time slots in mst state %p (avail=%d)\n",
payload->port, mst_state, avail_slots + payload->time_slots);
return -ENOSPC;
}

if (++payload_count > mgr->max_payloads) {
drm_dbg_atomic(mgr->dev,
"[MST MGR:%p] state %p has too many payloads (max=%d)\n",
mgr, mst_state, mgr->max_payloads);
return -EINVAL;
}

/* Assign a VCPI */
if (!payload->vcpi) {
payload->vcpi = ffz(mst_state->payload_mask) + 1;
drm_dbg_atomic(mgr->dev, "[MST PORT:%p] assigned VCPI #%d\n",
payload->port, payload->vcpi);
mst_state->payload_mask |= BIT(payload->vcpi - 1);
}
}

if (!payload_count)
mst_state->pbn_div = 0;

drm_dbg_atomic(mgr->dev, "[MST MGR:%p] mst state %p TU pbn_div=%d avail=%d used=%d\n",
mgr, mst_state, mst_state->pbn_div, avail_slots,
mst_state->total_avail_slots - avail_slots);

return 0;
}

/**
* drm_dp_mst_atomic_check_mgr - Check the atomic state of an MST topology manager
* @state: The global atomic state
* @mgr: Manager to check
* @mst_state: The MST atomic state for @mgr
* @failing_port: Returns the port with a BW limitation
*
* Checks the given MST manager's topology state for an atomic update to ensure
* that it's valid. This includes checking whether there's enough bandwidth to
* support the new timeslot allocations in the atomic update.
*
* Any atomic drivers supporting DP MST must make sure to call this or
* the drm_dp_mst_atomic_check() function after checking the rest of their state
* in their &drm_mode_config_funcs.atomic_check() callback.
*
* See also:
* drm_dp_mst_atomic_check()
* drm_dp_atomic_find_time_slots()
* drm_dp_atomic_release_time_slots()
*
* Returns:
* - 0 if the new state is valid
* - %-ENOSPC, if the new state is invalid, because of BW limitation
* @failing_port is set to:
*
* - The non-root port where a BW limit check failed
* with all the ports downstream of @failing_port passing
* the BW limit check.
* The returned port pointer is valid until at least
* one payload downstream of it exists.
* - %NULL if the BW limit check failed at the root port
* with all the ports downstream of the root port passing
* the BW limit check.
*
* - %-EINVAL, if the new state is invalid, because the root port has
* too many payloads.
*/
int drm_dp_mst_atomic_check_mgr(struct drm_atomic_state *state,
struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_topology_state *mst_state,
struct drm_dp_mst_port **failing_port)
{
int ret;

*failing_port = NULL;

if (!mgr->mst_state)
return 0;

mutex_lock(&mgr->lock);
ret = drm_dp_mst_atomic_check_mstb_bw_limit(mgr->mst_primary,
mst_state,
failing_port);
mutex_unlock(&mgr->lock);

if (ret < 0)
return ret;

return drm_dp_mst_atomic_check_payload_alloc_limits(mgr, mst_state);
}
#endif
10 changes: 8 additions & 2 deletions drivers/gpu/drm/i915/display/intel_dp_mst.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ static void intel_dp_mst_compute_m_n(const struct intel_crtc_state *crtc_state,

m_n->tu = DIV_ROUND_UP_ULL(mul_u32_u32(m_n->data_m, 64), m_n->data_n);
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0)
static int intel_dp_mst_calc_pbn(int pixel_clock, int bpp_x16, int bw_overhead)
{
int effective_data_rate =
Expand All @@ -136,6 +136,7 @@ static int intel_dp_mst_calc_pbn(int pixel_clock, int bpp_x16, int bw_overhead)
*/
return DIV_ROUND_UP(effective_data_rate * 64, 54 * 1000);
}
#endif

static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
Expand Down Expand Up @@ -1505,7 +1506,7 @@ intel_dp_mst_read_decompression_port_dsc_caps(struct intel_dp *intel_dp,

intel_dp_get_dsc_sink_cap(dpcd_caps[DP_DPCD_REV], connector);
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0)
static bool detect_dsc_hblank_expansion_quirk(const struct intel_connector *connector)
{
struct drm_i915_private *i915 = to_i915(connector->base.dev);
Expand Down Expand Up @@ -1535,6 +1536,7 @@ static bool detect_dsc_hblank_expansion_quirk(const struct intel_connector *conn

return true;
}
#endif

static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *port,
Expand All @@ -1560,8 +1562,12 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo

intel_connector->dp.dsc_decompression_aux = drm_dp_mst_dsc_aux_for_port(port);
intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, intel_connector);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 8, 0)
intel_connector->dp.dsc_hblank_expansion_quirk =
detect_dsc_hblank_expansion_quirk(intel_connector);
#else
intel_connector->dp.dsc_hblank_expansion_quirk = false;
#endif

connector = &intel_connector->base;
ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs,
Expand Down
9 changes: 7 additions & 2 deletions drivers/gpu/drm/i915/display/intel_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
#include <linux/version.h>

#include <drm/display/drm_hdcp_helper.h>
#include <drm/display/drm_hdmi_helper.h>
Expand Down Expand Up @@ -2492,10 +2493,14 @@ intel_hdmi_set_edid(struct drm_connector *connector)
}

intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);

#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0)
/* FIXME: Get rid of drm_edid_raw() */
cec_notifier_set_phys_addr_from_edid(intel_hdmi->cec_notifier,
drm_edid_raw(drm_edid));
#else
cec_notifier_set_phys_addr(intel_hdmi->cec_notifier,
connector->display_info.source_physical_address);

#endif
return connected;
}

Expand Down
10 changes: 9 additions & 1 deletion include/drm/display/drm_dp_mst_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,12 @@ bool drm_dp_mst_port_downstream_of_parent(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_port *parent);
#endif

#endif /* __DRM_DRM_DP_MST_HELPER_H__ */
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 8, 0)
// https://github.com/gregkh/linux/commit/9dcf67deeab6fbc4984175278b1b2c59881dca52
int __must_check drm_dp_mst_atomic_check_mgr(struct drm_atomic_state *state,
struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_topology_state *mst_state,
struct drm_dp_mst_port **failing_port);
#endif

#endif /* __BACKPORT_DRM_DP_MST_HELPER_H__ */

0 comments on commit 0e25f11

Please sign in to comment.