linux/drivers/net/ethernet/pensando/ionic/ionic_dev.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
   3
   4#include <linux/kernel.h>
   5#include <linux/types.h>
   6#include <linux/errno.h>
   7#include <linux/io.h>
   8#include <linux/slab.h>
   9#include <linux/etherdevice.h>
  10#include "ionic.h"
  11#include "ionic_dev.h"
  12#include "ionic_lif.h"
  13
  14static void ionic_watchdog_cb(struct timer_list *t)
  15{
  16        struct ionic *ionic = from_timer(ionic, t, watchdog_timer);
  17        int hb;
  18
  19        mod_timer(&ionic->watchdog_timer,
  20                  round_jiffies(jiffies + ionic->watchdog_period));
  21
  22        hb = ionic_heartbeat_check(ionic);
  23
  24        if (hb >= 0 && ionic->master_lif)
  25                ionic_link_status_check_request(ionic->master_lif);
  26}
  27
  28void ionic_init_devinfo(struct ionic *ionic)
  29{
  30        struct ionic_dev *idev = &ionic->idev;
  31
  32        idev->dev_info.asic_type = ioread8(&idev->dev_info_regs->asic_type);
  33        idev->dev_info.asic_rev = ioread8(&idev->dev_info_regs->asic_rev);
  34
  35        memcpy_fromio(idev->dev_info.fw_version,
  36                      idev->dev_info_regs->fw_version,
  37                      IONIC_DEVINFO_FWVERS_BUFLEN);
  38
  39        memcpy_fromio(idev->dev_info.serial_num,
  40                      idev->dev_info_regs->serial_num,
  41                      IONIC_DEVINFO_SERIAL_BUFLEN);
  42
  43        idev->dev_info.fw_version[IONIC_DEVINFO_FWVERS_BUFLEN] = 0;
  44        idev->dev_info.serial_num[IONIC_DEVINFO_SERIAL_BUFLEN] = 0;
  45
  46        dev_dbg(ionic->dev, "fw_version %s\n", idev->dev_info.fw_version);
  47}
  48
  49int ionic_dev_setup(struct ionic *ionic)
  50{
  51        struct ionic_dev_bar *bar = ionic->bars;
  52        unsigned int num_bars = ionic->num_bars;
  53        struct ionic_dev *idev = &ionic->idev;
  54        struct device *dev = ionic->dev;
  55        u32 sig;
  56
  57        /* BAR0: dev_cmd and interrupts */
  58        if (num_bars < 1) {
  59                dev_err(dev, "No bars found, aborting\n");
  60                return -EFAULT;
  61        }
  62
  63        if (bar->len < IONIC_BAR0_SIZE) {
  64                dev_err(dev, "Resource bar size %lu too small, aborting\n",
  65                        bar->len);
  66                return -EFAULT;
  67        }
  68
  69        idev->dev_info_regs = bar->vaddr + IONIC_BAR0_DEV_INFO_REGS_OFFSET;
  70        idev->dev_cmd_regs = bar->vaddr + IONIC_BAR0_DEV_CMD_REGS_OFFSET;
  71        idev->intr_status = bar->vaddr + IONIC_BAR0_INTR_STATUS_OFFSET;
  72        idev->intr_ctrl = bar->vaddr + IONIC_BAR0_INTR_CTRL_OFFSET;
  73
  74        sig = ioread32(&idev->dev_info_regs->signature);
  75        if (sig != IONIC_DEV_INFO_SIGNATURE) {
  76                dev_err(dev, "Incompatible firmware signature %x", sig);
  77                return -EFAULT;
  78        }
  79
  80        ionic_init_devinfo(ionic);
  81
  82        /* BAR1: doorbells */
  83        bar++;
  84        if (num_bars < 2) {
  85                dev_err(dev, "Doorbell bar missing, aborting\n");
  86                return -EFAULT;
  87        }
  88
  89        idev->last_fw_status = 0xff;
  90        timer_setup(&ionic->watchdog_timer, ionic_watchdog_cb, 0);
  91        ionic->watchdog_period = IONIC_WATCHDOG_SECS * HZ;
  92        mod_timer(&ionic->watchdog_timer,
  93                  round_jiffies(jiffies + ionic->watchdog_period));
  94
  95        idev->db_pages = bar->vaddr;
  96        idev->phy_db_pages = bar->bus_addr;
  97
  98        return 0;
  99}
 100
 101void ionic_dev_teardown(struct ionic *ionic)
 102{
 103        del_timer_sync(&ionic->watchdog_timer);
 104}
 105
 106/* Devcmd Interface */
 107int ionic_heartbeat_check(struct ionic *ionic)
 108{
 109        struct ionic_dev *idev = &ionic->idev;
 110        unsigned long hb_time;
 111        u8 fw_status;
 112        u32 hb;
 113
 114        /* wait a little more than one second before testing again */
 115        hb_time = jiffies;
 116        if (time_before(hb_time, (idev->last_hb_time + ionic->watchdog_period)))
 117                return 0;
 118
 119        /* firmware is useful only if the running bit is set and
 120         * fw_status != 0xff (bad PCI read)
 121         */
 122        fw_status = ioread8(&idev->dev_info_regs->fw_status);
 123        if (fw_status != 0xff)
 124                fw_status &= IONIC_FW_STS_F_RUNNING;  /* use only the run bit */
 125
 126        /* is this a transition? */
 127        if (fw_status != idev->last_fw_status &&
 128            idev->last_fw_status != 0xff) {
 129                struct ionic_lif *lif = ionic->master_lif;
 130                bool trigger = false;
 131
 132                if (!fw_status || fw_status == 0xff) {
 133                        dev_info(ionic->dev, "FW stopped %u\n", fw_status);
 134                        if (lif && !test_bit(IONIC_LIF_F_FW_RESET, lif->state))
 135                                trigger = true;
 136                } else {
 137                        dev_info(ionic->dev, "FW running %u\n", fw_status);
 138                        if (lif && test_bit(IONIC_LIF_F_FW_RESET, lif->state))
 139                                trigger = true;
 140                }
 141
 142                if (trigger) {
 143                        struct ionic_deferred_work *work;
 144
 145                        work = kzalloc(sizeof(*work), GFP_ATOMIC);
 146                        if (!work) {
 147                                dev_err(ionic->dev, "%s OOM\n", __func__);
 148                        } else {
 149                                work->type = IONIC_DW_TYPE_LIF_RESET;
 150                                if (fw_status & IONIC_FW_STS_F_RUNNING &&
 151                                    fw_status != 0xff)
 152                                        work->fw_status = 1;
 153                                ionic_lif_deferred_enqueue(&lif->deferred, work);
 154                        }
 155                }
 156        }
 157        idev->last_fw_status = fw_status;
 158
 159        if (!fw_status || fw_status == 0xff)
 160                return -ENXIO;
 161
 162        /* early FW has no heartbeat, else FW will return non-zero */
 163        hb = ioread32(&idev->dev_info_regs->fw_heartbeat);
 164        if (!hb)
 165                return 0;
 166
 167        /* are we stalled? */
 168        if (hb == idev->last_hb) {
 169                /* only complain once for each stall seen */
 170                if (idev->last_hb_time != 1) {
 171                        dev_info(ionic->dev, "FW heartbeat stalled at %d\n",
 172                                 idev->last_hb);
 173                        idev->last_hb_time = 1;
 174                }
 175
 176                return -ENXIO;
 177        }
 178
 179        if (idev->last_hb_time == 1)
 180                dev_info(ionic->dev, "FW heartbeat restored at %d\n", hb);
 181
 182        idev->last_hb = hb;
 183        idev->last_hb_time = hb_time;
 184
 185        return 0;
 186}
 187
 188u8 ionic_dev_cmd_status(struct ionic_dev *idev)
 189{
 190        return ioread8(&idev->dev_cmd_regs->comp.comp.status);
 191}
 192
 193bool ionic_dev_cmd_done(struct ionic_dev *idev)
 194{
 195        return ioread32(&idev->dev_cmd_regs->done) & IONIC_DEV_CMD_DONE;
 196}
 197
 198void ionic_dev_cmd_comp(struct ionic_dev *idev, union ionic_dev_cmd_comp *comp)
 199{
 200        memcpy_fromio(comp, &idev->dev_cmd_regs->comp, sizeof(*comp));
 201}
 202
 203void ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd)
 204{
 205        memcpy_toio(&idev->dev_cmd_regs->cmd, cmd, sizeof(*cmd));
 206        iowrite32(0, &idev->dev_cmd_regs->done);
 207        iowrite32(1, &idev->dev_cmd_regs->doorbell);
 208}
 209
 210/* Device commands */
 211void ionic_dev_cmd_identify(struct ionic_dev *idev, u8 ver)
 212{
 213        union ionic_dev_cmd cmd = {
 214                .identify.opcode = IONIC_CMD_IDENTIFY,
 215                .identify.ver = ver,
 216        };
 217
 218        ionic_dev_cmd_go(idev, &cmd);
 219}
 220
 221void ionic_dev_cmd_init(struct ionic_dev *idev)
 222{
 223        union ionic_dev_cmd cmd = {
 224                .init.opcode = IONIC_CMD_INIT,
 225                .init.type = 0,
 226        };
 227
 228        ionic_dev_cmd_go(idev, &cmd);
 229}
 230
 231void ionic_dev_cmd_reset(struct ionic_dev *idev)
 232{
 233        union ionic_dev_cmd cmd = {
 234                .reset.opcode = IONIC_CMD_RESET,
 235        };
 236
 237        ionic_dev_cmd_go(idev, &cmd);
 238}
 239
 240/* Port commands */
 241void ionic_dev_cmd_port_identify(struct ionic_dev *idev)
 242{
 243        union ionic_dev_cmd cmd = {
 244                .port_init.opcode = IONIC_CMD_PORT_IDENTIFY,
 245                .port_init.index = 0,
 246        };
 247
 248        ionic_dev_cmd_go(idev, &cmd);
 249}
 250
 251void ionic_dev_cmd_port_init(struct ionic_dev *idev)
 252{
 253        union ionic_dev_cmd cmd = {
 254                .port_init.opcode = IONIC_CMD_PORT_INIT,
 255                .port_init.index = 0,
 256                .port_init.info_pa = cpu_to_le64(idev->port_info_pa),
 257        };
 258
 259        ionic_dev_cmd_go(idev, &cmd);
 260}
 261
 262void ionic_dev_cmd_port_reset(struct ionic_dev *idev)
 263{
 264        union ionic_dev_cmd cmd = {
 265                .port_reset.opcode = IONIC_CMD_PORT_RESET,
 266                .port_reset.index = 0,
 267        };
 268
 269        ionic_dev_cmd_go(idev, &cmd);
 270}
 271
 272void ionic_dev_cmd_port_state(struct ionic_dev *idev, u8 state)
 273{
 274        union ionic_dev_cmd cmd = {
 275                .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
 276                .port_setattr.index = 0,
 277                .port_setattr.attr = IONIC_PORT_ATTR_STATE,
 278                .port_setattr.state = state,
 279        };
 280
 281        ionic_dev_cmd_go(idev, &cmd);
 282}
 283
 284void ionic_dev_cmd_port_speed(struct ionic_dev *idev, u32 speed)
 285{
 286        union ionic_dev_cmd cmd = {
 287                .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
 288                .port_setattr.index = 0,
 289                .port_setattr.attr = IONIC_PORT_ATTR_SPEED,
 290                .port_setattr.speed = cpu_to_le32(speed),
 291        };
 292
 293        ionic_dev_cmd_go(idev, &cmd);
 294}
 295
 296void ionic_dev_cmd_port_autoneg(struct ionic_dev *idev, u8 an_enable)
 297{
 298        union ionic_dev_cmd cmd = {
 299                .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
 300                .port_setattr.index = 0,
 301                .port_setattr.attr = IONIC_PORT_ATTR_AUTONEG,
 302                .port_setattr.an_enable = an_enable,
 303        };
 304
 305        ionic_dev_cmd_go(idev, &cmd);
 306}
 307
 308void ionic_dev_cmd_port_fec(struct ionic_dev *idev, u8 fec_type)
 309{
 310        union ionic_dev_cmd cmd = {
 311                .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
 312                .port_setattr.index = 0,
 313                .port_setattr.attr = IONIC_PORT_ATTR_FEC,
 314                .port_setattr.fec_type = fec_type,
 315        };
 316
 317        ionic_dev_cmd_go(idev, &cmd);
 318}
 319
 320void ionic_dev_cmd_port_pause(struct ionic_dev *idev, u8 pause_type)
 321{
 322        union ionic_dev_cmd cmd = {
 323                .port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
 324                .port_setattr.index = 0,
 325                .port_setattr.attr = IONIC_PORT_ATTR_PAUSE,
 326                .port_setattr.pause_type = pause_type,
 327        };
 328
 329        ionic_dev_cmd_go(idev, &cmd);
 330}
 331
 332/* VF commands */
 333int ionic_set_vf_config(struct ionic *ionic, int vf, u8 attr, u8 *data)
 334{
 335        union ionic_dev_cmd cmd = {
 336                .vf_setattr.opcode = IONIC_CMD_VF_SETATTR,
 337                .vf_setattr.attr = attr,
 338                .vf_setattr.vf_index = vf,
 339        };
 340        int err;
 341
 342        switch (attr) {
 343        case IONIC_VF_ATTR_SPOOFCHK:
 344                cmd.vf_setattr.spoofchk = *data;
 345                dev_dbg(ionic->dev, "%s: vf %d spoof %d\n",
 346                        __func__, vf, *data);
 347                break;
 348        case IONIC_VF_ATTR_TRUST:
 349                cmd.vf_setattr.trust = *data;
 350                dev_dbg(ionic->dev, "%s: vf %d trust %d\n",
 351                        __func__, vf, *data);
 352                break;
 353        case IONIC_VF_ATTR_LINKSTATE:
 354                cmd.vf_setattr.linkstate = *data;
 355                dev_dbg(ionic->dev, "%s: vf %d linkstate %d\n",
 356                        __func__, vf, *data);
 357                break;
 358        case IONIC_VF_ATTR_MAC:
 359                ether_addr_copy(cmd.vf_setattr.macaddr, data);
 360                dev_dbg(ionic->dev, "%s: vf %d macaddr %pM\n",
 361                        __func__, vf, data);
 362                break;
 363        case IONIC_VF_ATTR_VLAN:
 364                cmd.vf_setattr.vlanid = cpu_to_le16(*(u16 *)data);
 365                dev_dbg(ionic->dev, "%s: vf %d vlan %d\n",
 366                        __func__, vf, *(u16 *)data);
 367                break;
 368        case IONIC_VF_ATTR_RATE:
 369                cmd.vf_setattr.maxrate = cpu_to_le32(*(u32 *)data);
 370                dev_dbg(ionic->dev, "%s: vf %d maxrate %d\n",
 371                        __func__, vf, *(u32 *)data);
 372                break;
 373        case IONIC_VF_ATTR_STATSADDR:
 374                cmd.vf_setattr.stats_pa = cpu_to_le64(*(u64 *)data);
 375                dev_dbg(ionic->dev, "%s: vf %d stats_pa 0x%08llx\n",
 376                        __func__, vf, *(u64 *)data);
 377                break;
 378        default:
 379                return -EINVAL;
 380        }
 381
 382        mutex_lock(&ionic->dev_cmd_lock);
 383        ionic_dev_cmd_go(&ionic->idev, &cmd);
 384        err = ionic_dev_cmd_wait(ionic, DEVCMD_TIMEOUT);
 385        mutex_unlock(&ionic->dev_cmd_lock);
 386
 387        return err;
 388}
 389
 390/* LIF commands */
 391void ionic_dev_cmd_lif_identify(struct ionic_dev *idev, u8 type, u8 ver)
 392{
 393        union ionic_dev_cmd cmd = {
 394                .lif_identify.opcode = IONIC_CMD_LIF_IDENTIFY,
 395                .lif_identify.type = type,
 396                .lif_identify.ver = ver,
 397        };
 398
 399        ionic_dev_cmd_go(idev, &cmd);
 400}
 401
 402void ionic_dev_cmd_lif_init(struct ionic_dev *idev, u16 lif_index,
 403                            dma_addr_t info_pa)
 404{
 405        union ionic_dev_cmd cmd = {
 406                .lif_init.opcode = IONIC_CMD_LIF_INIT,
 407                .lif_init.index = cpu_to_le16(lif_index),
 408                .lif_init.info_pa = cpu_to_le64(info_pa),
 409        };
 410
 411        ionic_dev_cmd_go(idev, &cmd);
 412}
 413
 414void ionic_dev_cmd_lif_reset(struct ionic_dev *idev, u16 lif_index)
 415{
 416        union ionic_dev_cmd cmd = {
 417                .lif_init.opcode = IONIC_CMD_LIF_RESET,
 418                .lif_init.index = cpu_to_le16(lif_index),
 419        };
 420
 421        ionic_dev_cmd_go(idev, &cmd);
 422}
 423
 424void ionic_dev_cmd_adminq_init(struct ionic_dev *idev, struct ionic_qcq *qcq,
 425                               u16 lif_index, u16 intr_index)
 426{
 427        struct ionic_queue *q = &qcq->q;
 428        struct ionic_cq *cq = &qcq->cq;
 429
 430        union ionic_dev_cmd cmd = {
 431                .q_init.opcode = IONIC_CMD_Q_INIT,
 432                .q_init.lif_index = cpu_to_le16(lif_index),
 433                .q_init.type = q->type,
 434                .q_init.index = cpu_to_le32(q->index),
 435                .q_init.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
 436                                            IONIC_QINIT_F_ENA),
 437                .q_init.pid = cpu_to_le16(q->pid),
 438                .q_init.intr_index = cpu_to_le16(intr_index),
 439                .q_init.ring_size = ilog2(q->num_descs),
 440                .q_init.ring_base = cpu_to_le64(q->base_pa),
 441                .q_init.cq_ring_base = cpu_to_le64(cq->base_pa),
 442        };
 443
 444        ionic_dev_cmd_go(idev, &cmd);
 445}
 446
 447int ionic_db_page_num(struct ionic_lif *lif, int pid)
 448{
 449        return (lif->hw_index * lif->dbid_count) + pid;
 450}
 451
 452int ionic_cq_init(struct ionic_lif *lif, struct ionic_cq *cq,
 453                  struct ionic_intr_info *intr,
 454                  unsigned int num_descs, size_t desc_size)
 455{
 456        struct ionic_cq_info *cur;
 457        unsigned int ring_size;
 458        unsigned int i;
 459
 460        if (desc_size == 0 || !is_power_of_2(num_descs))
 461                return -EINVAL;
 462
 463        ring_size = ilog2(num_descs);
 464        if (ring_size < 2 || ring_size > 16)
 465                return -EINVAL;
 466
 467        cq->lif = lif;
 468        cq->bound_intr = intr;
 469        cq->num_descs = num_descs;
 470        cq->desc_size = desc_size;
 471        cq->tail = cq->info;
 472        cq->done_color = 1;
 473
 474        cur = cq->info;
 475
 476        for (i = 0; i < num_descs; i++) {
 477                if (i + 1 == num_descs) {
 478                        cur->next = cq->info;
 479                        cur->last = true;
 480                } else {
 481                        cur->next = cur + 1;
 482                }
 483                cur->index = i;
 484                cur++;
 485        }
 486
 487        return 0;
 488}
 489
 490void ionic_cq_map(struct ionic_cq *cq, void *base, dma_addr_t base_pa)
 491{
 492        struct ionic_cq_info *cur;
 493        unsigned int i;
 494
 495        cq->base = base;
 496        cq->base_pa = base_pa;
 497
 498        for (i = 0, cur = cq->info; i < cq->num_descs; i++, cur++)
 499                cur->cq_desc = base + (i * cq->desc_size);
 500}
 501
 502void ionic_cq_bind(struct ionic_cq *cq, struct ionic_queue *q)
 503{
 504        cq->bound_q = q;
 505}
 506
 507unsigned int ionic_cq_service(struct ionic_cq *cq, unsigned int work_to_do,
 508                              ionic_cq_cb cb, ionic_cq_done_cb done_cb,
 509                              void *done_arg)
 510{
 511        unsigned int work_done = 0;
 512
 513        if (work_to_do == 0)
 514                return 0;
 515
 516        while (cb(cq, cq->tail)) {
 517                if (cq->tail->last)
 518                        cq->done_color = !cq->done_color;
 519                cq->tail = cq->tail->next;
 520                DEBUG_STATS_CQE_CNT(cq);
 521
 522                if (++work_done >= work_to_do)
 523                        break;
 524        }
 525
 526        if (work_done && done_cb)
 527                done_cb(done_arg);
 528
 529        return work_done;
 530}
 531
 532int ionic_q_init(struct ionic_lif *lif, struct ionic_dev *idev,
 533                 struct ionic_queue *q, unsigned int index, const char *name,
 534                 unsigned int num_descs, size_t desc_size,
 535                 size_t sg_desc_size, unsigned int pid)
 536{
 537        struct ionic_desc_info *cur;
 538        unsigned int ring_size;
 539        unsigned int i;
 540
 541        if (desc_size == 0 || !is_power_of_2(num_descs))
 542                return -EINVAL;
 543
 544        ring_size = ilog2(num_descs);
 545        if (ring_size < 2 || ring_size > 16)
 546                return -EINVAL;
 547
 548        q->lif = lif;
 549        q->idev = idev;
 550        q->index = index;
 551        q->num_descs = num_descs;
 552        q->desc_size = desc_size;
 553        q->sg_desc_size = sg_desc_size;
 554        q->tail = q->info;
 555        q->head = q->tail;
 556        q->pid = pid;
 557
 558        snprintf(q->name, sizeof(q->name), "L%d-%s%u", lif->index, name, index);
 559
 560        cur = q->info;
 561
 562        for (i = 0; i < num_descs; i++) {
 563                if (i + 1 == num_descs)
 564                        cur->next = q->info;
 565                else
 566                        cur->next = cur + 1;
 567                cur->index = i;
 568                cur->left = num_descs - i;
 569                cur++;
 570        }
 571
 572        return 0;
 573}
 574
 575void ionic_q_map(struct ionic_queue *q, void *base, dma_addr_t base_pa)
 576{
 577        struct ionic_desc_info *cur;
 578        unsigned int i;
 579
 580        q->base = base;
 581        q->base_pa = base_pa;
 582
 583        for (i = 0, cur = q->info; i < q->num_descs; i++, cur++)
 584                cur->desc = base + (i * q->desc_size);
 585}
 586
 587void ionic_q_sg_map(struct ionic_queue *q, void *base, dma_addr_t base_pa)
 588{
 589        struct ionic_desc_info *cur;
 590        unsigned int i;
 591
 592        q->sg_base = base;
 593        q->sg_base_pa = base_pa;
 594
 595        for (i = 0, cur = q->info; i < q->num_descs; i++, cur++)
 596                cur->sg_desc = base + (i * q->sg_desc_size);
 597}
 598
 599void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, ionic_desc_cb cb,
 600                  void *cb_arg)
 601{
 602        struct device *dev = q->lif->ionic->dev;
 603        struct ionic_lif *lif = q->lif;
 604
 605        q->head->cb = cb;
 606        q->head->cb_arg = cb_arg;
 607        q->head = q->head->next;
 608
 609        dev_dbg(dev, "lif=%d qname=%s qid=%d qtype=%d p_index=%d ringdb=%d\n",
 610                q->lif->index, q->name, q->hw_type, q->hw_index,
 611                q->head->index, ring_doorbell);
 612
 613        if (ring_doorbell)
 614                ionic_dbell_ring(lif->kern_dbpage, q->hw_type,
 615                                 q->dbval | q->head->index);
 616}
 617
 618static bool ionic_q_is_posted(struct ionic_queue *q, unsigned int pos)
 619{
 620        unsigned int mask, tail, head;
 621
 622        mask = q->num_descs - 1;
 623        tail = q->tail->index;
 624        head = q->head->index;
 625
 626        return ((pos - tail) & mask) < ((head - tail) & mask);
 627}
 628
 629void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info,
 630                     unsigned int stop_index)
 631{
 632        struct ionic_desc_info *desc_info;
 633        ionic_desc_cb cb;
 634        void *cb_arg;
 635
 636        /* check for empty queue */
 637        if (q->tail->index == q->head->index)
 638                return;
 639
 640        /* stop index must be for a descriptor that is not yet completed */
 641        if (unlikely(!ionic_q_is_posted(q, stop_index)))
 642                dev_err(q->lif->ionic->dev,
 643                        "ionic stop is not posted %s stop %u tail %u head %u\n",
 644                        q->name, stop_index, q->tail->index, q->head->index);
 645
 646        do {
 647                desc_info = q->tail;
 648                q->tail = desc_info->next;
 649
 650                cb = desc_info->cb;
 651                cb_arg = desc_info->cb_arg;
 652
 653                desc_info->cb = NULL;
 654                desc_info->cb_arg = NULL;
 655
 656                if (cb)
 657                        cb(q, desc_info, cq_info, cb_arg);
 658        } while (desc_info->index != stop_index);
 659}
 660