RDMA/bnxt_re: Disable doorbell moderation if hardware register read fails
authorSelvin Xavier <selvin.xavier@broadcom.com>
Thu, 27 Jun 2024 02:41:05 +0000 (19:41 -0700)
committerLeon Romanovsky <leon@kernel.org>
Mon, 1 Jul 2024 11:36:50 +0000 (14:36 +0300)
If the HW register read fails, the FIFO will be always shown as
full. DB moderation doesn't work in that case and the traffic fails.
So disable this feature and log a message.

Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
Link: https://lore.kernel.org/r/1719456065-27394-4-git-send-email-selvin.xavier@broadcom.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/hw/bnxt_re/main.c

index 2c5282fdc9f740aec2f5ce80bb975a7e847e23a8..9714b9ab75240bc3019e05bbc1235b2a97678277 100644 (file)
@@ -488,19 +488,40 @@ static void bnxt_re_set_default_pacing_data(struct bnxt_re_dev *rdev)
                pacing_data->pacing_th * BNXT_RE_PACING_ALARM_TH_MULTIPLE;
 }
 
-static void __wait_for_fifo_occupancy_below_th(struct bnxt_re_dev *rdev)
+static u32 __get_fifo_occupancy(struct bnxt_re_dev *rdev)
 {
        struct bnxt_qplib_db_pacing_data *pacing_data = rdev->qplib_res.pacing_data;
        u32 read_val, fifo_occup;
 
+       read_val = readl(rdev->en_dev->bar0 + rdev->pacing.dbr_db_fifo_reg_off);
+       fifo_occup = pacing_data->fifo_max_depth -
+                    ((read_val & pacing_data->fifo_room_mask) >>
+                     pacing_data->fifo_room_shift);
+       return fifo_occup;
+}
+
+static bool is_dbr_fifo_full(struct bnxt_re_dev *rdev)
+{
+       u32 max_occup, fifo_occup;
+
+       fifo_occup = __get_fifo_occupancy(rdev);
+       max_occup = BNXT_RE_MAX_FIFO_DEPTH(rdev->chip_ctx) - 1;
+       if (fifo_occup == max_occup)
+               return true;
+
+       return false;
+}
+
+static void __wait_for_fifo_occupancy_below_th(struct bnxt_re_dev *rdev)
+{
+       struct bnxt_qplib_db_pacing_data *pacing_data = rdev->qplib_res.pacing_data;
+       u32 fifo_occup;
+
        /* loop shouldn't run infintely as the occupancy usually goes
         * below pacing algo threshold as soon as pacing kicks in.
         */
        while (1) {
-               read_val = readl(rdev->en_dev->bar0 + rdev->pacing.dbr_db_fifo_reg_off);
-               fifo_occup = pacing_data->fifo_max_depth -
-                            ((read_val & pacing_data->fifo_room_mask) >>
-                             pacing_data->fifo_room_shift);
+               fifo_occup = __get_fifo_occupancy(rdev);
                /* Fifo occupancy cannot be greater the MAX FIFO depth */
                if (fifo_occup > pacing_data->fifo_max_depth)
                        break;
@@ -556,16 +577,13 @@ static void bnxt_re_pacing_timer_exp(struct work_struct *work)
        struct bnxt_re_dev *rdev = container_of(work, struct bnxt_re_dev,
                        dbq_pacing_work.work);
        struct bnxt_qplib_db_pacing_data *pacing_data;
-       u32 read_val, fifo_occup;
+       u32 fifo_occup;
 
        if (!mutex_trylock(&rdev->pacing.dbq_lock))
                return;
 
        pacing_data = rdev->qplib_res.pacing_data;
-       read_val = readl(rdev->en_dev->bar0 + rdev->pacing.dbr_db_fifo_reg_off);
-       fifo_occup = pacing_data->fifo_max_depth -
-                    ((read_val & pacing_data->fifo_room_mask) >>
-                     pacing_data->fifo_room_shift);
+       fifo_occup = __get_fifo_occupancy(rdev);
 
        if (fifo_occup > pacing_data->pacing_th)
                goto restart_timer;
@@ -613,7 +631,6 @@ void bnxt_re_pacing_alert(struct bnxt_re_dev *rdev)
 
 static int bnxt_re_initialize_dbr_pacing(struct bnxt_re_dev *rdev)
 {
-
        /* Allocate a page for app use */
        rdev->pacing.dbr_page = (void *)__get_free_page(GFP_KERNEL);
        if (!rdev->pacing.dbr_page)
@@ -637,6 +654,12 @@ static int bnxt_re_initialize_dbr_pacing(struct bnxt_re_dev *rdev)
        rdev->pacing.dbr_bar_addr =
                pci_resource_start(rdev->qplib_res.pdev, 0) + rdev->pacing.dbr_db_fifo_reg_off;
 
+       if (is_dbr_fifo_full(rdev)) {
+               free_page((u64)rdev->pacing.dbr_page);
+               rdev->pacing.dbr_page = NULL;
+               return -EIO;
+       }
+
        rdev->pacing.pacing_algo_th = BNXT_RE_PACING_ALGO_THRESHOLD;
        rdev->pacing.dbq_pacing_time = BNXT_RE_DBR_PACING_TIME;
        rdev->pacing.dbr_def_do_pacing = BNXT_RE_DBR_DO_PACING_NO_CONGESTION;