drm/amd/display: Fix minor issues in BW Allocation Phase2
authorMeenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com>
Mon, 4 Dec 2023 15:57:45 +0000 (10:57 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 Feb 2024 20:14:30 +0000 (20:14 +0000)
[ Upstream commit aa5dc05340eb97486a631ce6bccb8d020bf6b56b ]

[Why]
Fix minor issues in BW Allocation Phase2.

[How]
- In set_usb4_req_bw_req(), link->dpia_bw_alloc_config.response_ready
  flag should be reset before writing DPCD REQUEST_BW.
- Fix the granularity for value of 2 in get_bw_granularity().
- Removed bandwidth allocation support display fw boot option as
  the fw would read feature enable status from bios.
- Clean up DPIA_EST_BW_CHANGED and DPIA_BW_REQ_SUCCESS cases in
  dpia_handle_bw_alloc_response().
- Removed allocate_usb4_bw and deallocate_usb4_bw.
- Optimized loop in get_lowest_dpia_index().
- Updated link_dp_dpia_allocate_usb4_bandwidth_for_stream() and
  set_usb4_req_bw_req() to always issue request bw.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: PeiChen Huang <peichen.huang@amd.com>
Acked-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
Signed-off-by: Meenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.h

index 7581023..d6e1f96 100644 (file)
@@ -50,6 +50,7 @@ static bool get_bw_alloc_proceed_flag(struct dc_link *tmp)
                        && tmp->hpd_status
                        && tmp->dpia_bw_alloc_config.bw_alloc_enabled);
 }
+
 static void reset_bw_alloc_struct(struct dc_link *link)
 {
        link->dpia_bw_alloc_config.bw_alloc_enabled = false;
@@ -59,6 +60,11 @@ static void reset_bw_alloc_struct(struct dc_link *link)
        link->dpia_bw_alloc_config.bw_granularity = 0;
        link->dpia_bw_alloc_config.response_ready = false;
 }
+
+#define BW_GRANULARITY_0 4 // 0.25 Gbps
+#define BW_GRANULARITY_1 2 // 0.5 Gbps
+#define BW_GRANULARITY_2 1 // 1 Gbps
+
 static uint8_t get_bw_granularity(struct dc_link *link)
 {
        uint8_t bw_granularity = 0;
@@ -71,16 +77,20 @@ static uint8_t get_bw_granularity(struct dc_link *link)
 
        switch (bw_granularity & 0x3) {
        case 0:
-               bw_granularity = 4;
+               bw_granularity = BW_GRANULARITY_0;
                break;
        case 1:
+               bw_granularity = BW_GRANULARITY_1;
+               break;
+       case 2:
        default:
-               bw_granularity = 2;
+               bw_granularity = BW_GRANULARITY_2;
                break;
        }
 
        return bw_granularity;
 }
+
 static int get_estimated_bw(struct dc_link *link)
 {
        uint8_t bw_estimated_bw = 0;
@@ -93,31 +103,7 @@ static int get_estimated_bw(struct dc_link *link)
 
        return bw_estimated_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
 }
-static bool allocate_usb4_bw(int *stream_allocated_bw, int bw_needed, struct dc_link *link)
-{
-       if (bw_needed > 0)
-               *stream_allocated_bw += bw_needed;
-
-       return true;
-}
-static bool deallocate_usb4_bw(int *stream_allocated_bw, int bw_to_dealloc, struct dc_link *link)
-{
-       bool ret = false;
-
-       if (*stream_allocated_bw > 0) {
-               *stream_allocated_bw -= bw_to_dealloc;
-               ret = true;
-       } else {
-               //Do nothing for now
-               ret = true;
-       }
 
-       // Unplug so reset values
-       if (!link->hpd_status)
-               reset_bw_alloc_struct(link);
-
-       return ret;
-}
 /*
  * Read all New BW alloc configuration ex: estimated_bw, allocated_bw,
  * granuality, Driver_ID, CM_Group, & populate the BW allocation structs
@@ -128,7 +114,12 @@ static void init_usb4_bw_struct(struct dc_link *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);
+
+       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);
 }
+
 static uint8_t get_lowest_dpia_index(struct dc_link *link)
 {
        const struct dc *dc_struct = link->dc;
@@ -141,12 +132,15 @@ static uint8_t get_lowest_dpia_index(struct dc_link *link)
                                dc_struct->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
                        continue;
 
-               if (idx > dc_struct->links[i]->link_index)
+               if (idx > dc_struct->links[i]->link_index) {
                        idx = dc_struct->links[i]->link_index;
+                       break;
+               }
        }
 
        return idx;
 }
+
 /*
  * Get the Max Available BW or Max Estimated BW for each Host Router
  *
@@ -186,6 +180,7 @@ static int get_host_router_total_bw(struct dc_link *link, uint8_t type)
 
        return total_bw;
 }
+
 /*
  * Cleanup function for when the dpia is unplugged to reset struct
  * and perform any required clean up
@@ -194,42 +189,50 @@ static int get_host_router_total_bw(struct dc_link *link, uint8_t type)
  *
  * return: none
  */
-static bool dpia_bw_alloc_unplug(struct dc_link *link)
+static void dpia_bw_alloc_unplug(struct dc_link *link)
 {
-       if (!link)
-               return true;
-
-       return deallocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw,
-                       link->dpia_bw_alloc_config.sink_allocated_bw, 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);
+       }
 }
+
 static void set_usb4_req_bw_req(struct dc_link *link, int req_bw)
 {
        uint8_t requested_bw;
        uint32_t temp;
 
-       // 1. Add check for this corner case #1
-       if (req_bw > link->dpia_bw_alloc_config.estimated_bw)
+       /* Error check whether request bw greater than allocated */
+       if (req_bw > link->dpia_bw_alloc_config.estimated_bw) {
+               DC_LOG_ERROR("%s: Request bw greater than estimated bw for link(%d)\n",
+                       __func__, link->link_index);
                req_bw = link->dpia_bw_alloc_config.estimated_bw;
+       }
 
        temp = req_bw * link->dpia_bw_alloc_config.bw_granularity;
        requested_bw = temp / Kbps_TO_Gbps;
 
-       // Always make sure to add more to account for floating points
+       /* Always make sure to add more to account for floating points */
        if (temp % Kbps_TO_Gbps)
                ++requested_bw;
 
-       // 2. Add check for this corner case #2
+       /* Error check whether requested and allocated are equal */
        req_bw = requested_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
-       if (req_bw == link->dpia_bw_alloc_config.sink_allocated_bw)
-               return;
+       if (req_bw == link->dpia_bw_alloc_config.sink_allocated_bw) {
+               DC_LOG_ERROR("%s: Request bw equals to allocated bw for link(%d)\n",
+                       __func__, link->link_index);
+       }
 
-       if (core_link_write_dpcd(
+       link->dpia_bw_alloc_config.response_ready = false; // Reset flag
+       core_link_write_dpcd(
                link,
                REQUESTED_BW,
                &requested_bw,
-               sizeof(uint8_t)) == DC_OK)
-               link->dpia_bw_alloc_config.response_ready = false; // Reset flag
+               sizeof(uint8_t));
 }
+
 /*
  * Return the response_ready flag from dc_link struct
  *
@@ -241,6 +244,7 @@ static bool get_cm_response_ready_flag(struct dc_link *link)
 {
        return link->dpia_bw_alloc_config.response_ready;
 }
+
 // ------------------------------------------------------------------
 //                                     PUBLIC FUNCTIONS
 // ------------------------------------------------------------------
@@ -277,27 +281,27 @@ bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link)
                                DPTX_BW_ALLOCATION_MODE_CONTROL,
                                &response,
                                sizeof(uint8_t)) != DC_OK) {
-                       DC_LOG_DEBUG("%s: **** FAILURE Enabling DPtx BW Allocation Mode Support ***\n",
-                                       __func__);
+                       DC_LOG_DEBUG("%s: FAILURE Enabling DPtx BW Allocation Mode Support for link(%d)\n",
+                               __func__, link->link_index);
                } else {
                        // SUCCESS Enabled DPtx BW Allocation Mode Support
-                       link->dpia_bw_alloc_config.bw_alloc_enabled = true;
-                       DC_LOG_DEBUG("%s: **** SUCCESS Enabling DPtx BW Allocation Mode Support ***\n",
-                                       __func__);
+                       DC_LOG_DEBUG("%s: SUCCESS Enabling DPtx BW Allocation Mode Support for link(%d)\n",
+                               __func__, link->link_index);
 
                        ret = true;
                        init_usb4_bw_struct(link);
+                       link->dpia_bw_alloc_config.bw_alloc_enabled = true;
                }
        }
 
 out:
        return ret;
 }
+
 void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t result)
 {
        int bw_needed = 0;
        int estimated = 0;
-       int host_router_total_estimated_bw = 0;
 
        if (!get_bw_alloc_proceed_flag((link)))
                return;
@@ -306,14 +310,22 @@ void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t res
 
        case DPIA_BW_REQ_FAILED:
 
-               DC_LOG_DEBUG("%s: *** *** BW REQ FAILURE for DP-TX Request *** ***\n", __func__);
+               /*
+                * Ideally, we shouldn't run into this case as we always validate available
+                * bandwidth and request within that limit
+                */
+               estimated = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
 
-               // Update the new Estimated BW value updated by CM
-               link->dpia_bw_alloc_config.estimated_bw =
-                               bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
+               DC_LOG_ERROR("%s: BW REQ FAILURE for DP-TX Request for link(%d)\n",
+                       __func__, link->link_index);
+               DC_LOG_ERROR("%s: current estimated_bw(%d), new estimated_bw(%d)\n",
+                       __func__, link->dpia_bw_alloc_config.estimated_bw, estimated);
 
+               /* Update the new Estimated BW value updated by CM */
+               link->dpia_bw_alloc_config.estimated_bw = estimated;
+
+               /* Allocate the previously requested bandwidth */
                set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.estimated_bw);
-               link->dpia_bw_alloc_config.response_ready = false;
 
                /*
                 * If FAIL then it is either:
@@ -326,68 +338,34 @@ void dpia_handle_bw_alloc_response(struct dc_link *link, uint8_t bw, uint8_t res
 
        case DPIA_BW_REQ_SUCCESS:
 
-               DC_LOG_DEBUG("%s: *** BW REQ SUCCESS for DP-TX Request ***\n", __func__);
-
-               // 1. SUCCESS 1st time before any Pruning is done
-               // 2. SUCCESS after prev. FAIL before any Pruning is done
-               // 3. SUCCESS after Pruning is done but before enabling link
-
                bw_needed = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
 
-               // 1.
-               if (!link->dpia_bw_alloc_config.sink_allocated_bw) {
-
-                       allocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw, bw_needed, link);
-                       link->dpia_bw_alloc_config.sink_verified_bw =
-                                       link->dpia_bw_alloc_config.sink_allocated_bw;
+               DC_LOG_DEBUG("%s: BW REQ SUCCESS for DP-TX Request for link(%d)\n",
+                       __func__, link->link_index);
+               DC_LOG_DEBUG("%s: current allocated_bw(%d), new allocated_bw(%d)\n",
+                       __func__, link->dpia_bw_alloc_config.sink_allocated_bw, bw_needed);
 
-                       // SUCCESS from first attempt
-                       if (link->dpia_bw_alloc_config.sink_allocated_bw >
-                       link->dpia_bw_alloc_config.sink_max_bw)
-                               link->dpia_bw_alloc_config.sink_verified_bw =
-                                               link->dpia_bw_alloc_config.sink_max_bw;
-               }
-               // 3.
-               else if (link->dpia_bw_alloc_config.sink_allocated_bw) {
-
-                       // Find out how much do we need to de-alloc
-                       if (link->dpia_bw_alloc_config.sink_allocated_bw > bw_needed)
-                               deallocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw,
-                                               link->dpia_bw_alloc_config.sink_allocated_bw - bw_needed, link);
-                       else
-                               allocate_usb4_bw(&link->dpia_bw_alloc_config.sink_allocated_bw,
-                                               bw_needed - link->dpia_bw_alloc_config.sink_allocated_bw, link);
-               }
-
-               // 4. If this is the 2nd sink then any unused bw will be reallocated to master DPIA
-               // => check if estimated_bw changed
+               link->dpia_bw_alloc_config.sink_allocated_bw = bw_needed;
 
                link->dpia_bw_alloc_config.response_ready = true;
                break;
 
        case DPIA_EST_BW_CHANGED:
 
-               DC_LOG_DEBUG("%s: *** ESTIMATED BW CHANGED for DP-TX Request ***\n", __func__);
-
                estimated = bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
-               host_router_total_estimated_bw = get_host_router_total_bw(link, HOST_ROUTER_BW_ESTIMATED);
 
-               // 1. If due to unplug of other sink
-               if (estimated == host_router_total_estimated_bw) {
-                       // First update the estimated & max_bw fields
-                       if (link->dpia_bw_alloc_config.estimated_bw < estimated)
-                               link->dpia_bw_alloc_config.estimated_bw = estimated;
-               }
-               // 2. If due to realloc bw btw 2 dpia due to plug OR realloc unused Bw
-               else {
-                       // We lost estimated bw usually due to plug event of other dpia
-                       link->dpia_bw_alloc_config.estimated_bw = estimated;
-               }
+               DC_LOG_DEBUG("%s: ESTIMATED BW CHANGED for link(%d)\n",
+                       __func__, link->link_index);
+               DC_LOG_DEBUG("%s: current estimated_bw(%d), new estimated_bw(%d)\n",
+                       __func__, link->dpia_bw_alloc_config.estimated_bw, estimated);
+
+               link->dpia_bw_alloc_config.estimated_bw = estimated;
                break;
 
        case DPIA_BW_ALLOC_CAPS_CHANGED:
 
-               DC_LOG_DEBUG("%s: *** BW ALLOC CAPABILITY CHANGED for DP-TX Request ***\n", __func__);
+               DC_LOG_ERROR("%s: BW ALLOC CAPABILITY CHANGED to Disabled for link(%d)\n",
+                       __func__, link->link_index);
                link->dpia_bw_alloc_config.bw_alloc_enabled = false;
                break;
        }
@@ -409,11 +387,11 @@ int dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int pea
                set_usb4_req_bw_req(link, link->dpia_bw_alloc_config.sink_max_bw);
 
                do {
-                       if (!(timeout > 0))
+                       if (timeout > 0)
                                timeout--;
                        else
                                break;
-                       fsleep(10 * 1000);
+                       msleep(10);
                } while (!get_cm_response_ready_flag(link));
 
                if (!timeout)
@@ -428,37 +406,36 @@ int dpia_handle_usb4_bandwidth_allocation_for_link(struct dc_link *link, int pea
 out:
        return ret;
 }
-int link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw)
+
+bool link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw)
 {
-       int ret = 0;
+       bool ret = false;
        uint8_t timeout = 10;
 
+       DC_LOG_DEBUG("%s: ENTER: link(%d), hpd_status(%d), current allocated_bw(%d), req_bw(%d)\n",
+               __func__, link->link_index, link->hpd_status,
+               link->dpia_bw_alloc_config.sink_allocated_bw, req_bw);
+
        if (!get_bw_alloc_proceed_flag(link))
                goto out;
 
-       /*
-        * Sometimes stream uses same timing parameters as the already
-        * allocated max sink bw so no need to re-alloc
-        */
-       if (req_bw != link->dpia_bw_alloc_config.sink_allocated_bw) {
-               set_usb4_req_bw_req(link, req_bw);
-               do {
-                       if (!(timeout > 0))
-                               timeout--;
-                       else
-                               break;
-                       udelay(10 * 1000);
-               } while (!get_cm_response_ready_flag(link));
+       set_usb4_req_bw_req(link, req_bw);
+       do {
+               if (timeout > 0)
+                       timeout--;
+               else
+                       break;
+               msleep(10);
+       } while (!get_cm_response_ready_flag(link));
 
-               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);
-       }
+       if (timeout)
+               ret = true;
 
 out:
+       DC_LOG_DEBUG("%s: EXIT: timeout(%d), ret(%d)\n", __func__, timeout, ret);
        return ret;
 }
+
 bool dpia_validate_usb4_bw(struct dc_link **link, int *bw_needed_per_dpia, const unsigned int num_dpias)
 {
        bool ret = true;
index 7292690..981bc4e 100644 (file)
@@ -59,9 +59,9 @@ bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link);
  * @link: pointer to the dc_link struct instance
  * @req_bw: Bw requested by the stream
  *
- * return: allocated bw else return 0
+ * return: true if allocated successfully
  */
-int link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw);
+bool link_dp_dpia_allocate_usb4_bandwidth_for_stream(struct dc_link *link, int req_bw);
 
 /*
  * Handle the USB4 BW Allocation related functionality here: