1 
2 /*
3  * Copyright 2022 Advanced Micro Devices, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: AMD
24  *
25  */
26 /*********************************************************************/
27 //				USB4 DPIA BANDWIDTH ALLOCATION LOGIC
28 /*********************************************************************/
29 #include "link_dp_dpia_bw.h"
30 #include "link_dpcd.h"
31 #include "dc_dmub_srv.h"
32 
33 #define DC_LOGGER \
34 	link->ctx->logger
35 
36 #define Kbps_TO_Gbps (1000 * 1000)
37 
38 // ------------------------------------------------------------------
39 //					PRIVATE FUNCTIONS
40 // ------------------------------------------------------------------
41 /*
42  * Always Check the following:
43  *  - Is it USB4 link?
44  *  - Is HPD HIGH?
45  *  - Is BW Allocation Support Mode enabled on DP-Tx?
46  */
get_bw_alloc_proceed_flag(struct dc_link * tmp)47 static bool get_bw_alloc_proceed_flag(struct dc_link *tmp)
48 {
49 	return (tmp && DISPLAY_ENDPOINT_USB4_DPIA == tmp->ep_type
50 			&& tmp->hpd_status
51 			&& tmp->dpia_bw_alloc_config.bw_alloc_enabled);
52 }
53 
reset_bw_alloc_struct(struct dc_link * link)54 static void reset_bw_alloc_struct(struct dc_link *link)
55 {
56 	link->dpia_bw_alloc_config.bw_alloc_enabled = false;
57 	link->dpia_bw_alloc_config.link_verified_bw = 0;
58 	link->dpia_bw_alloc_config.link_max_bw = 0;
59 	link->dpia_bw_alloc_config.allocated_bw = 0;
60 	link->dpia_bw_alloc_config.estimated_bw = 0;
61 	link->dpia_bw_alloc_config.bw_granularity = 0;
62 	link->dpia_bw_alloc_config.dp_overhead = 0;
63 	link->dpia_bw_alloc_config.response_ready = false;
64 	link->dpia_bw_alloc_config.nrd_max_lane_count = 0;
65 	link->dpia_bw_alloc_config.nrd_max_link_rate = 0;
66 	for (int i = 0; i < MAX_SINKS_PER_LINK; i++)
67 		link->dpia_bw_alloc_config.remote_sink_req_bw[i] = 0;
68 	DC_LOG_DEBUG("reset usb4 bw alloc of link(%d)\n", link->link_index);
69 }
70 
71 #define BW_GRANULARITY_0 4 // 0.25 Gbps
72 #define BW_GRANULARITY_1 2 // 0.5 Gbps
73 #define BW_GRANULARITY_2 1 // 1 Gbps
74 
get_bw_granularity(struct dc_link * link)75 static uint8_t get_bw_granularity(struct dc_link *link)
76 {
77 	uint8_t bw_granularity = 0;
78 
79 	core_link_read_dpcd(
80 			link,
81 			DP_BW_GRANULALITY,
82 			&bw_granularity,
83 			sizeof(uint8_t));
84 
85 	switch (bw_granularity & 0x3) {
86 	case 0:
87 		bw_granularity = BW_GRANULARITY_0;
88 		break;
89 	case 1:
90 		bw_granularity = BW_GRANULARITY_1;
91 		break;
92 	case 2:
93 	default:
94 		bw_granularity = BW_GRANULARITY_2;
95 		break;
96 	}
97 
98 	return bw_granularity;
99 }
100 
get_estimated_bw(struct dc_link * link)101 static int get_estimated_bw(struct dc_link *link)
102 {
103 	uint8_t bw_estimated_bw = 0;
104 
105 	core_link_read_dpcd(
106 			link,
107 			ESTIMATED_BW,
108 			&bw_estimated_bw,
109 			sizeof(uint8_t));
110 
111 	return bw_estimated_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
112 }
113 
get_non_reduced_max_link_rate(struct dc_link * link)114 static int get_non_reduced_max_link_rate(struct dc_link *link)
115 {
116 	uint8_t nrd_max_link_rate = 0;
117 
118 	core_link_read_dpcd(
119 			link,
120 			DP_TUNNELING_MAX_LINK_RATE,
121 			&nrd_max_link_rate,
122 			sizeof(uint8_t));
123 
124 	return nrd_max_link_rate;
125 }
126 
get_non_reduced_max_lane_count(struct dc_link * link)127 static int get_non_reduced_max_lane_count(struct dc_link *link)
128 {
129 	uint8_t nrd_max_lane_count = 0;
130 
131 	core_link_read_dpcd(
132 			link,
133 			DP_TUNNELING_MAX_LANE_COUNT,
134 			&nrd_max_lane_count,
135 			sizeof(uint8_t));
136 
137 	return nrd_max_lane_count;
138 }
139 
140 /*
141  * Read all New BW alloc configuration ex: estimated_bw, allocated_bw,
142  * granuality, Driver_ID, CM_Group, & populate the BW allocation structs
143  * for host router and dpia
144  */
init_usb4_bw_struct(struct dc_link * link)145 static void init_usb4_bw_struct(struct dc_link *link)
146 {
147 	reset_bw_alloc_struct(link);
148 
149 	/* init the known values */
150 	link->dpia_bw_alloc_config.bw_granularity = get_bw_granularity(link);
151 	link->dpia_bw_alloc_config.estimated_bw = get_estimated_bw(link);
152 	link->dpia_bw_alloc_config.nrd_max_link_rate = get_non_reduced_max_link_rate(link);
153 	link->dpia_bw_alloc_config.nrd_max_lane_count = get_non_reduced_max_lane_count(link);
154 
155 	DC_LOG_DEBUG("%s: bw_granularity(%d), estimated_bw(%d)\n",
156 		__func__, link->dpia_bw_alloc_config.bw_granularity,
157 		link->dpia_bw_alloc_config.estimated_bw);
158 	DC_LOG_DEBUG("%s: nrd_max_link_rate(%d), nrd_max_lane_count(%d)\n",
159 		__func__, link->dpia_bw_alloc_config.nrd_max_link_rate,
160 		link->dpia_bw_alloc_config.nrd_max_lane_count);
161 }
162 
get_lowest_dpia_index(struct dc_link * link)163 static uint8_t get_lowest_dpia_index(struct dc_link *link)
164 {
165 	const struct dc *dc_struct = link->dc;
166 	uint8_t idx = 0xFF;
167 	int i;
168 
169 	for (i = 0; i < MAX_PIPES * 2; ++i) {
170 
171 		if (!dc_struct->links[i] ||
172 				dc_struct->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
173 			continue;
174 
175 		if (idx > dc_struct->links[i]->link_index) {
176 			idx = dc_struct->links[i]->link_index;
177 			break;
178 		}
179 	}
180 
181 	return idx;
182 }
183 
184 /*
185  * Get the maximum dp tunnel banwidth of host router
186  *
187  * @dc: pointer to the dc struct instance
188  * @hr_index: host router index
189  *
190  * return: host router maximum dp tunnel bandwidth
191  */
get_host_router_total_dp_tunnel_bw(const struct dc * dc,uint8_t hr_index)192 static int get_host_router_total_dp_tunnel_bw(const struct dc *dc, uint8_t hr_index)
193 {
194 	uint8_t lowest_dpia_index = get_lowest_dpia_index(dc->links[0]);
195 	uint8_t hr_index_temp = 0;
196 	struct dc_link *link_dpia_primary, *link_dpia_secondary;
197 	int total_bw = 0;
198 
199 	for (uint8_t i = 0; i < (MAX_PIPES * 2) - 1; ++i) {
200 
201 		if (!dc->links[i] || dc->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
202 			continue;
203 
204 		hr_index_temp = (dc->links[i]->link_index - lowest_dpia_index) / 2;
205 
206 		if (hr_index_temp == hr_index) {
207 			link_dpia_primary = dc->links[i];
208 			link_dpia_secondary = dc->links[i + 1];
209 
210 			/**
211 			 * If BW allocation enabled on both DPIAs, then
212 			 * HR BW = Estimated(dpia_primary) + Allocated(dpia_secondary)
213 			 * otherwise HR BW = Estimated(bw alloc enabled dpia)
214 			 */
215 			if ((link_dpia_primary->hpd_status &&
216 				link_dpia_primary->dpia_bw_alloc_config.bw_alloc_enabled) &&
217 				(link_dpia_secondary->hpd_status &&
218 				link_dpia_secondary->dpia_bw_alloc_config.bw_alloc_enabled)) {
219 					total_bw += link_dpia_primary->dpia_bw_alloc_config.estimated_bw +
220 						link_dpia_secondary->dpia_bw_alloc_config.allocated_bw;
221 			} else if (link_dpia_primary->hpd_status &&
222 					link_dpia_primary->dpia_bw_alloc_config.bw_alloc_enabled) {
223 				total_bw = link_dpia_primary->dpia_bw_alloc_config.estimated_bw;
224 			} else if (link_dpia_secondary->hpd_status &&
225 				link_dpia_secondary->dpia_bw_alloc_config.bw_alloc_enabled) {
226 				total_bw += link_dpia_secondary->dpia_bw_alloc_config.estimated_bw;
227 			}
228 			break;
229 		}
230 	}
231 
232 	return total_bw;
233 }
234 
235 /*
236  * Cleanup function for when the dpia is unplugged to reset struct
237  * and perform any required clean up
238  *
239  * @link: pointer to the dc_link struct instance
240  *
241  * return: none
242  */
dpia_bw_alloc_unplug(struct dc_link * link)243 static void dpia_bw_alloc_unplug(struct dc_link *link)
244 {
245 	if (link) {
246 		DC_LOG_DEBUG("%s: resetting bw alloc config for link(%d)\n",
247 			__func__, link->link_index);
248 		reset_bw_alloc_struct(link);
249 	}
250 }
251 
set_usb4_req_bw_req(struct dc_link * link,int req_bw)252 static void set_usb4_req_bw_req(struct dc_link *link, int req_bw)
253 {
254 	uint8_t requested_bw;
255 	uint32_t temp;
256 
257 	/* Error check whether request bw greater than allocated */
258 	if (req_bw > link->dpia_bw_alloc_config.estimated_bw) {
259 		DC_LOG_ERROR("%s: Request bw greater than estimated bw for link(%d)\n",
260 			__func__, link->link_index);
261 		req_bw = link->dpia_bw_alloc_config.estimated_bw;
262 	}
263 
264 	temp = req_bw * link->dpia_bw_alloc_config.bw_granularity;
265 	requested_bw = temp / Kbps_TO_Gbps;
266 
267 	/* Always make sure to add more to account for floating points */
268 	if (temp % Kbps_TO_Gbps)
269 		++requested_bw;
270 
271 	/* Error check whether requested and allocated are equal */
272 	req_bw = requested_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
273 	if (req_bw && (req_bw == link->dpia_bw_alloc_config.allocated_bw)) {
274 		DC_LOG_ERROR("%s: Request bw equals to allocated bw for link(%d)\n",
275 			__func__, link->link_index);
276 	}
277 
278 	link->dpia_bw_alloc_config.response_ready = false; // Reset flag
279 	core_link_write_dpcd(
280 		link,
281 		REQUESTED_BW,
282 		&requested_bw,
283 		sizeof(uint8_t));
284 }
285 
286 /*
287  * Return the response_ready flag from dc_link struct
288  *
289  * @link: pointer to the dc_link struct instance
290  *
291  * return: response_ready flag from dc_link struct
292  */
get_cm_response_ready_flag(struct dc_link * link)293 static bool get_cm_response_ready_flag(struct dc_link *link)
294 {
295 	return link->dpia_bw_alloc_config.response_ready;
296 }
297 
298 // ------------------------------------------------------------------
299 //					PUBLIC FUNCTIONS
300 // ------------------------------------------------------------------
link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link * link)301 bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link)
302 {
303 	bool ret = false;
304 	uint8_t response = 0,
305 			bw_support_dpia = 0,
306 			bw_support_cm = 0;
307 
308 	if (!(link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && link->hpd_status))
309 		goto out;
310 
311 	if (core_link_read_dpcd(
312 			link,
313 			DP_TUNNELING_CAPABILITIES,
314 			&response,
315 			sizeof(uint8_t)) == DC_OK)
316 		bw_support_dpia = (response >> 7) & 1;
317 
318 	if (core_link_read_dpcd(
319 		link,
320 		USB4_DRIVER_BW_CAPABILITY,
321 		&response,
322 		sizeof(uint8_t)) == DC_OK)
323 		bw_support_cm = (response >> 7) & 1;
324 
325 	/* Send request acknowledgment to Turn ON DPTX support */
326 	if (bw_support_cm && bw_support_dpia) {
327 
328 		response = 0x80;
329 		if (core_link_write_dpcd(
330 				link,
331 				DPTX_BW_ALLOCATION_MODE_CONTROL,
332 				&response,
333 				sizeof(uint8_t)) != DC_OK) {
334 			DC_LOG_DEBUG("%s: FAILURE Enabling DPtx BW Allocation Mode Support for link(%d)\n",
335 				__func__, link->link_index);
336 		} else {
337 			// SUCCESS Enabled DPtx BW Allocation Mode Support
338 			DC_LOG_DEBUG("%s: SUCCESS Enabling DPtx BW Allocation Mode Support for link(%d)\n",
339 				__func__, link->link_index);
340 
341 			ret = true;
342 			init_usb4_bw_struct(link);
343 			link->dpia_bw_alloc_config.bw_alloc_enabled = true;
344 
345 			/*
346 			 * During DP tunnel creation, CM preallocates BW and reduces estimated BW of other
347 			 * DPIA. CM release preallocation only when allocation is complete. Do zero alloc
348 			 * to make the CM to release preallocation and update estimated BW correctly for
349 			 * all DPIAs per host router
350 			 */
351 			link_dp_dpia_allocate_usb4_bandwidth_for_stream(link, 0);
352 		}
353 	}
354 
355 out:
356 	return ret;
357 }
358 
dpia_handle_bw_alloc_response(struct dc_link * link,uint8_t bw,uint8_t result)359 void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t result)
360 {
361 	int bw_needed = 0;
362 	int estimated = 0;
363 
364 	if (!get_bw_alloc_proceed_flag((link)))
365 		return;
366 
367 	switch (result) {
368 
369 	case DPIA_BW_REQ_FAILED:
370 
371 		/*
372 		 * Ideally, we shouldn't run into this case as we always validate available
373 		 * bandwidth and request within that limit
374 		 */
375 		estimated = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
376 
377 		DC_LOG_ERROR("%s: BW REQ FAILURE for DP-TX Request for link(%d)\n",
378 			__func__, link->link_index);
379 		DC_LOG_ERROR("%s: current estimated_bw(%d), new estimated_bw(%d)\n",
380 			__func__, link->dpia_bw_alloc_config.estimated_bw, estimated);
381 
382 		/* Update the new Estimated BW value updated by CM */
383 		link->dpia_bw_alloc_config.estimated_bw = estimated;
384 
385 		/* Allocate the previously requested bandwidth */
386 		set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.estimated_bw);
387 
388 		/*
389 		 * If FAIL then it is either:
390 		 * 1. Due to DP-Tx trying to allocate more than available i.e. it failed locally
391 		 *    => get estimated and allocate that
392 		 * 2. Due to the fact that DP-Tx tried to allocated ESTIMATED BW and failed then
393 		 *    CM will have to update 0xE0023 with new ESTIMATED BW value.
394 		 */
395 		break;
396 
397 	case DPIA_BW_REQ_SUCCESS:
398 
399 		bw_needed = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
400 
401 		DC_LOG_DEBUG("%s: BW REQ SUCCESS for DP-TX Request for link(%d)\n",
402 			__func__, link->link_index);
403 		DC_LOG_DEBUG("%s: current allocated_bw(%d), new allocated_bw(%d)\n",
404 			__func__, link->dpia_bw_alloc_config.allocated_bw, bw_needed);
405 
406 		link->dpia_bw_alloc_config.allocated_bw = bw_needed;
407 
408 		link->dpia_bw_alloc_config.response_ready = true;
409 		break;
410 
411 	case DPIA_EST_BW_CHANGED:
412 
413 		estimated = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
414 
415 		DC_LOG_DEBUG("%s: ESTIMATED BW CHANGED for link(%d)\n",
416 			__func__, link->link_index);
417 		DC_LOG_DEBUG("%s: current estimated_bw(%d), new estimated_bw(%d)\n",
418 			__func__, link->dpia_bw_alloc_config.estimated_bw, estimated);
419 
420 		link->dpia_bw_alloc_config.estimated_bw = estimated;
421 		break;
422 
423 	case DPIA_BW_ALLOC_CAPS_CHANGED:
424 
425 		DC_LOG_ERROR("%s: BW ALLOC CAPABILITY CHANGED to Disabled for link(%d)\n",
426 			__func__, link->link_index);
427 		link->dpia_bw_alloc_config.bw_alloc_enabled = false;
428 		break;
429 	}
430 }
dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link * link,int peak_bw)431 int dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int peak_bw)
432 {
433 	int ret = 0;
434 	uint8_t timeout = 10;
435 
436 	if (!(link && DISPLAY_ENDPOINT_USB4_DPIA == link->ep_type
437 			&& link->dpia_bw_alloc_config.bw_alloc_enabled))
438 		goto out;
439 
440 	//1. Hot Plug
441 	if (link->hpd_status && peak_bw > 0) {
442 
443 		// If DP over USB4 then we need to check BW allocation
444 		link->dpia_bw_alloc_config.link_max_bw = peak_bw;
445 		set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.link_max_bw);
446 
447 		do {
448 			if (timeout > 0)
449 				timeout--;
450 			else
451 				break;
452 			msleep(10);
453 		} while (!get_cm_response_ready_flag(link));
454 
455 		if (!timeout)
456 			ret = 0;// ERROR TIMEOUT waiting for response for allocating bw
457 		else if (link->dpia_bw_alloc_config.allocated_bw > 0)
458 			ret = link->dpia_bw_alloc_config.allocated_bw;
459 	}
460 	//2. Cold Unplug
461 	else if (!link->hpd_status)
462 		dpia_bw_alloc_unplug(link);
463 
464 out:
465 	return ret;
466 }
link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link * link,int req_bw)467 bool link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw)
468 {
469 	bool ret = false;
470 	uint8_t timeout = 10;
471 
472 	DC_LOG_DEBUG("%s: ENTER: link(%d), hpd_status(%d), current allocated_bw(%d), req_bw(%d)\n",
473 		__func__, link->link_index, link->hpd_status,
474 		link->dpia_bw_alloc_config.allocated_bw, req_bw);
475 
476 	if (!get_bw_alloc_proceed_flag(link))
477 		goto out;
478 
479 	set_usb4_req_bw_req(link, req_bw);
480 	do {
481 		if (timeout > 0)
482 			timeout--;
483 		else
484 			break;
485 		msleep(10);
486 	} while (!get_cm_response_ready_flag(link));
487 
488 	if (timeout)
489 		ret = true;
490 
491 out:
492 	DC_LOG_DEBUG("%s: EXIT: timeout(%d), ret(%d)\n", __func__, timeout, ret);
493 	return ret;
494 }
495 
dpia_validate_usb4_bw(struct dc_link ** link,int * bw_needed_per_dpia,const unsigned int num_dpias)496 bool dpia_validate_usb4_bw(struct dc_link **link, int *bw_needed_per_dpia, const unsigned int num_dpias)
497 {
498 	bool ret = true;
499 	int bw_needed_per_hr[MAX_HR_NUM] = { 0, 0 }, host_router_total_dp_bw = 0;
500 	uint8_t lowest_dpia_index, i, hr_index;
501 
502 	if (!num_dpias || num_dpias > MAX_DPIA_NUM)
503 		return ret;
504 
505 	lowest_dpia_index = get_lowest_dpia_index(link[0]);
506 
507 	/* get total Host Router BW with granularity for the given modes */
508 	for (i = 0; i < num_dpias; ++i) {
509 		int granularity_Gbps = 0;
510 		int bw_granularity = 0;
511 
512 		if (!link[i]->dpia_bw_alloc_config.bw_alloc_enabled)
513 			continue;
514 
515 		if (link[i]->link_index < lowest_dpia_index)
516 			continue;
517 
518 		granularity_Gbps = (Kbps_TO_Gbps / link[i]->dpia_bw_alloc_config.bw_granularity);
519 		bw_granularity = (bw_needed_per_dpia[i] / granularity_Gbps) * granularity_Gbps +
520 				((bw_needed_per_dpia[i] % granularity_Gbps) ? granularity_Gbps : 0);
521 
522 		hr_index = (link[i]->link_index - lowest_dpia_index) / 2;
523 		bw_needed_per_hr[hr_index] += bw_granularity;
524 	}
525 
526 	/* validate against each Host Router max BW */
527 	for (hr_index = 0; hr_index < MAX_HR_NUM; ++hr_index) {
528 		if (bw_needed_per_hr[hr_index]) {
529 			host_router_total_dp_bw = get_host_router_total_dp_tunnel_bw(link[0]->dc, hr_index);
530 			if (bw_needed_per_hr[hr_index] > host_router_total_dp_bw) {
531 				ret = false;
532 				break;
533 			}
534 		}
535 	}
536 
537 	return ret;
538 }
539 
link_dp_dpia_get_dp_overhead_in_dp_tunneling(struct dc_link * link)540 int link_dp_dpia_get_dp_overhead_in_dp_tunneling(struct dc_link *link)
541 {
542 	int dp_overhead = 0, link_mst_overhead = 0;
543 
544 	if (!get_bw_alloc_proceed_flag((link)))
545 		return dp_overhead;
546 
547 	/* if its mst link, add MTPH overhead */
548 	if ((link->type == dc_connection_mst_branch) &&
549 		!link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
550 		/* For 8b/10b encoding: MTP is 64 time slots long, slot 0 is used for MTPH
551 		 * MST overhead is 1/64 of link bandwidth (excluding any overhead)
552 		 */
553 		const struct dc_link_settings *link_cap =
554 			dc_link_get_link_cap(link);
555 		uint32_t link_bw_in_kbps = (uint32_t)link_cap->link_rate *
556 					   (uint32_t)link_cap->lane_count *
557 					   LINK_RATE_REF_FREQ_IN_KHZ * 8;
558 		link_mst_overhead = (link_bw_in_kbps / 64) + ((link_bw_in_kbps % 64) ? 1 : 0);
559 	}
560 
561 	/* add all the overheads */
562 	dp_overhead = link_mst_overhead;
563 
564 	return dp_overhead;
565 }
566