|
|
|
|
@ -59,6 +59,7 @@ static void reset_bw_alloc_struct(struct dc_link *link)
|
|
|
|
|
link->dpia_bw_alloc_config.estimated_bw = 0;
|
|
|
|
|
link->dpia_bw_alloc_config.bw_granularity = 0;
|
|
|
|
|
link->dpia_bw_alloc_config.response_ready = false;
|
|
|
|
|
link->dpia_bw_alloc_config.sink_allocated_bw = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define BW_GRANULARITY_0 4 // 0.25 Gbps
|
|
|
|
|
@ -104,6 +105,32 @@ static int get_estimated_bw(struct dc_link *link)
|
|
|
|
|
return bw_estimated_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int get_non_reduced_max_link_rate(struct dc_link *link)
|
|
|
|
|
{
|
|
|
|
|
uint8_t nrd_max_link_rate = 0;
|
|
|
|
|
|
|
|
|
|
core_link_read_dpcd(
|
|
|
|
|
link,
|
|
|
|
|
DP_TUNNELING_MAX_LINK_RATE,
|
|
|
|
|
&nrd_max_link_rate,
|
|
|
|
|
sizeof(uint8_t));
|
|
|
|
|
|
|
|
|
|
return nrd_max_link_rate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int get_non_reduced_max_lane_count(struct dc_link *link)
|
|
|
|
|
{
|
|
|
|
|
uint8_t nrd_max_lane_count = 0;
|
|
|
|
|
|
|
|
|
|
core_link_read_dpcd(
|
|
|
|
|
link,
|
|
|
|
|
DP_TUNNELING_MAX_LANE_COUNT,
|
|
|
|
|
&nrd_max_lane_count,
|
|
|
|
|
sizeof(uint8_t));
|
|
|
|
|
|
|
|
|
|
return nrd_max_lane_count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Read all New BW alloc configuration ex: estimated_bw, allocated_bw,
|
|
|
|
|
* granuality, Driver_ID, CM_Group, & populate the BW allocation structs
|
|
|
|
|
@ -111,13 +138,20 @@ static int get_estimated_bw(struct dc_link *link)
|
|
|
|
|
*/
|
|
|
|
|
static void init_usb4_bw_struct(struct dc_link *link)
|
|
|
|
|
{
|
|
|
|
|
// Init the known values
|
|
|
|
|
reset_bw_alloc_struct(link);
|
|
|
|
|
|
|
|
|
|
/* init the known values */
|
|
|
|
|
link->dpia_bw_alloc_config.bw_granularity = get_bw_granularity(link);
|
|
|
|
|
link->dpia_bw_alloc_config.estimated_bw = get_estimated_bw(link);
|
|
|
|
|
link->dpia_bw_alloc_config.nrd_max_link_rate = get_non_reduced_max_link_rate(link);
|
|
|
|
|
link->dpia_bw_alloc_config.nrd_max_lane_count = get_non_reduced_max_lane_count(link);
|
|
|
|
|
|
|
|
|
|
DC_LOG_DEBUG("%s: bw_granularity(%d), estimated_bw(%d)\n",
|
|
|
|
|
__func__, link->dpia_bw_alloc_config.bw_granularity,
|
|
|
|
|
link->dpia_bw_alloc_config.estimated_bw);
|
|
|
|
|
DC_LOG_DEBUG("%s: nrd_max_link_rate(%d), nrd_max_lane_count(%d)\n",
|
|
|
|
|
__func__, link->dpia_bw_alloc_config.nrd_max_link_rate,
|
|
|
|
|
link->dpia_bw_alloc_config.nrd_max_lane_count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint8_t get_lowest_dpia_index(struct dc_link *link)
|
|
|
|
|
@ -142,39 +176,50 @@ static uint8_t get_lowest_dpia_index(struct dc_link *link)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get the Max Available BW or Max Estimated BW for each Host Router
|
|
|
|
|
* Get the maximum dp tunnel banwidth of host router
|
|
|
|
|
*
|
|
|
|
|
* @link: pointer to the dc_link struct instance
|
|
|
|
|
* @type: ESTIMATD BW or MAX AVAILABLE BW
|
|
|
|
|
* @dc: pointer to the dc struct instance
|
|
|
|
|
* @hr_index: host router index
|
|
|
|
|
*
|
|
|
|
|
* return: response_ready flag from dc_link struct
|
|
|
|
|
* return: host router maximum dp tunnel bandwidth
|
|
|
|
|
*/
|
|
|
|
|
static int get_host_router_total_bw(struct dc_link *link, uint8_t type)
|
|
|
|
|
static int get_host_router_total_dp_tunnel_bw(const struct dc *dc, uint8_t hr_index)
|
|
|
|
|
{
|
|
|
|
|
const struct dc *dc_struct = link->dc;
|
|
|
|
|
uint8_t lowest_dpia_index = get_lowest_dpia_index(link);
|
|
|
|
|
uint8_t idx = (link->link_index - lowest_dpia_index) / 2, idx_temp = 0;
|
|
|
|
|
struct dc_link *link_temp;
|
|
|
|
|
uint8_t lowest_dpia_index = get_lowest_dpia_index(dc->links[0]);
|
|
|
|
|
uint8_t hr_index_temp = 0;
|
|
|
|
|
struct dc_link *link_dpia_primary, *link_dpia_secondary;
|
|
|
|
|
int total_bw = 0;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_PIPES * 2; ++i) {
|
|
|
|
|
for (uint8_t i = 0; i < MAX_PIPES * 2; ++i) {
|
|
|
|
|
|
|
|
|
|
if (!dc_struct->links[i] || dc_struct->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
|
|
|
|
|
if (!dc->links[i] || dc->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
link_temp = dc_struct->links[i];
|
|
|
|
|
if (!link_temp || !link_temp->hpd_status)
|
|
|
|
|
continue;
|
|
|
|
|
hr_index_temp = (dc->links[i]->link_index - lowest_dpia_index) / 2;
|
|
|
|
|
|
|
|
|
|
idx_temp = (link_temp->link_index - lowest_dpia_index) / 2;
|
|
|
|
|
if (hr_index_temp == hr_index) {
|
|
|
|
|
link_dpia_primary = dc->links[i];
|
|
|
|
|
link_dpia_secondary = dc->links[i + 1];
|
|
|
|
|
|
|
|
|
|
if (idx_temp == idx) {
|
|
|
|
|
|
|
|
|
|
if (type == HOST_ROUTER_BW_ESTIMATED)
|
|
|
|
|
total_bw += link_temp->dpia_bw_alloc_config.estimated_bw;
|
|
|
|
|
else if (type == HOST_ROUTER_BW_ALLOCATED)
|
|
|
|
|
total_bw += link_temp->dpia_bw_alloc_config.sink_allocated_bw;
|
|
|
|
|
/**
|
|
|
|
|
* If BW allocation enabled on both DPIAs, then
|
|
|
|
|
* HR BW = Estimated(dpia_primary) + Allocated(dpia_secondary)
|
|
|
|
|
* otherwise HR BW = Estimated(bw alloc enabled dpia)
|
|
|
|
|
*/
|
|
|
|
|
if ((link_dpia_primary->hpd_status &&
|
|
|
|
|
link_dpia_primary->dpia_bw_alloc_config.bw_alloc_enabled) &&
|
|
|
|
|
(link_dpia_secondary->hpd_status &&
|
|
|
|
|
link_dpia_secondary->dpia_bw_alloc_config.bw_alloc_enabled)) {
|
|
|
|
|
total_bw += link_dpia_primary->dpia_bw_alloc_config.estimated_bw +
|
|
|
|
|
link_dpia_secondary->dpia_bw_alloc_config.sink_allocated_bw;
|
|
|
|
|
} else if (link_dpia_primary->hpd_status &&
|
|
|
|
|
link_dpia_primary->dpia_bw_alloc_config.bw_alloc_enabled) {
|
|
|
|
|
total_bw = link_dpia_primary->dpia_bw_alloc_config.estimated_bw;
|
|
|
|
|
} else if (link_dpia_secondary->hpd_status &&
|
|
|
|
|
link_dpia_secondary->dpia_bw_alloc_config.bw_alloc_enabled) {
|
|
|
|
|
total_bw += link_dpia_secondary->dpia_bw_alloc_config.estimated_bw;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -194,7 +239,6 @@ static void dpia_bw_alloc_unplug(struct dc_link *link)
|
|
|
|
|
if (link) {
|
|
|
|
|
DC_LOG_DEBUG("%s: resetting bw alloc config for link(%d)\n",
|
|
|
|
|
__func__, link->link_index);
|
|
|
|
|
link->dpia_bw_alloc_config.sink_allocated_bw = 0;
|
|
|
|
|
reset_bw_alloc_struct(link);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -397,7 +441,7 @@ int dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int pea
|
|
|
|
|
if (!timeout)
|
|
|
|
|
ret = 0;// ERROR TIMEOUT waiting for response for allocating bw
|
|
|
|
|
else if (link->dpia_bw_alloc_config.sink_allocated_bw > 0)
|
|
|
|
|
ret = get_host_router_total_bw(link, HOST_ROUTER_BW_ALLOCATED);
|
|
|
|
|
ret = link->dpia_bw_alloc_config.sink_allocated_bw;
|
|
|
|
|
}
|
|
|
|
|
//2. Cold Unplug
|
|
|
|
|
else if (!link->hpd_status)
|
|
|
|
|
@ -439,31 +483,43 @@ out:
|
|
|
|
|
bool dpia_validate_usb4_bw(struct dc_link **link, int *bw_needed_per_dpia, const unsigned int num_dpias)
|
|
|
|
|
{
|
|
|
|
|
bool ret = true;
|
|
|
|
|
int bw_needed_per_hr[MAX_HR_NUM] = { 0, 0 };
|
|
|
|
|
uint8_t lowest_dpia_index = 0, dpia_index = 0;
|
|
|
|
|
uint8_t i;
|
|
|
|
|
int bw_needed_per_hr[MAX_HR_NUM] = { 0, 0 }, host_router_total_dp_bw = 0;
|
|
|
|
|
uint8_t lowest_dpia_index, i, hr_index;
|
|
|
|
|
|
|
|
|
|
if (!num_dpias || num_dpias > MAX_DPIA_NUM)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
//Get total Host Router BW & Validate against each Host Router max BW
|
|
|
|
|
lowest_dpia_index = get_lowest_dpia_index(link[0]);
|
|
|
|
|
|
|
|
|
|
/* get total Host Router BW with granularity for the given modes */
|
|
|
|
|
for (i = 0; i < num_dpias; ++i) {
|
|
|
|
|
int granularity_Gbps = 0;
|
|
|
|
|
int bw_granularity = 0;
|
|
|
|
|
|
|
|
|
|
if (!link[i]->dpia_bw_alloc_config.bw_alloc_enabled)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
lowest_dpia_index = get_lowest_dpia_index(link[i]);
|
|
|
|
|
if (link[i]->link_index < lowest_dpia_index)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
dpia_index = (link[i]->link_index - lowest_dpia_index) / 2;
|
|
|
|
|
bw_needed_per_hr[dpia_index] += bw_needed_per_dpia[i];
|
|
|
|
|
if (bw_needed_per_hr[dpia_index] > get_host_router_total_bw(link[i], HOST_ROUTER_BW_ALLOCATED)) {
|
|
|
|
|
granularity_Gbps = (Kbps_TO_Gbps / link[i]->dpia_bw_alloc_config.bw_granularity);
|
|
|
|
|
bw_granularity = (bw_needed_per_dpia[i] / granularity_Gbps) * granularity_Gbps +
|
|
|
|
|
((bw_needed_per_dpia[i] % granularity_Gbps) ? granularity_Gbps : 0);
|
|
|
|
|
|
|
|
|
|
hr_index = (link[i]->link_index - lowest_dpia_index) / 2;
|
|
|
|
|
bw_needed_per_hr[hr_index] += bw_granularity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* validate against each Host Router max BW */
|
|
|
|
|
for (hr_index = 0; hr_index < MAX_HR_NUM; ++hr_index) {
|
|
|
|
|
if (bw_needed_per_hr[hr_index]) {
|
|
|
|
|
host_router_total_dp_bw = get_host_router_total_dp_tunnel_bw(link[0]->dc, hr_index);
|
|
|
|
|
if (bw_needed_per_hr[hr_index] > host_router_total_dp_bw) {
|
|
|
|
|
ret = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|