bman.c (20343B)
1/* Copyright 2008 - 2016 Freescale Semiconductor, Inc. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are met: 5 * * Redistributions of source code must retain the above copyright 6 * notice, this list of conditions and the following disclaimer. 7 * * Redistributions in binary form must reproduce the above copyright 8 * notice, this list of conditions and the following disclaimer in the 9 * documentation and/or other materials provided with the distribution. 10 * * Neither the name of Freescale Semiconductor nor the 11 * names of its contributors may be used to endorse or promote products 12 * derived from this software without specific prior written permission. 13 * 14 * ALTERNATIVELY, this software may be distributed under the terms of the 15 * GNU General Public License ("GPL") as published by the Free Software 16 * Foundation, either version 2 of that License or (at your option) any 17 * later version. 18 * 19 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "bman_priv.h" 32 33#define IRQNAME "BMan portal %d" 34#define MAX_IRQNAME 16 /* big enough for "BMan portal %d" */ 35 36/* Portal register assists */ 37 38#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) 39/* Cache-inhibited register offsets */ 40#define BM_REG_RCR_PI_CINH 0x3000 41#define BM_REG_RCR_CI_CINH 0x3100 42#define BM_REG_RCR_ITR 0x3200 43#define BM_REG_CFG 0x3300 44#define BM_REG_SCN(n) (0x3400 + ((n) << 6)) 45#define BM_REG_ISR 0x3e00 46#define BM_REG_IER 0x3e40 47#define BM_REG_ISDR 0x3e80 48#define BM_REG_IIR 0x3ec0 49 50/* Cache-enabled register offsets */ 51#define BM_CL_CR 0x0000 52#define BM_CL_RR0 0x0100 53#define BM_CL_RR1 0x0140 54#define BM_CL_RCR 0x1000 55#define BM_CL_RCR_PI_CENA 0x3000 56#define BM_CL_RCR_CI_CENA 0x3100 57 58#else 59/* Cache-inhibited register offsets */ 60#define BM_REG_RCR_PI_CINH 0x0000 61#define BM_REG_RCR_CI_CINH 0x0004 62#define BM_REG_RCR_ITR 0x0008 63#define BM_REG_CFG 0x0100 64#define BM_REG_SCN(n) (0x0200 + ((n) << 2)) 65#define BM_REG_ISR 0x0e00 66#define BM_REG_IER 0x0e04 67#define BM_REG_ISDR 0x0e08 68#define BM_REG_IIR 0x0e0c 69 70/* Cache-enabled register offsets */ 71#define BM_CL_CR 0x0000 72#define BM_CL_RR0 0x0100 73#define BM_CL_RR1 0x0140 74#define BM_CL_RCR 0x1000 75#define BM_CL_RCR_PI_CENA 0x3000 76#define BM_CL_RCR_CI_CENA 0x3100 77#endif 78 79/* 80 * Portal modes. 81 * Enum types; 82 * pmode == production mode 83 * cmode == consumption mode, 84 * Enum values use 3 letter codes. First letter matches the portal mode, 85 * remaining two letters indicate; 86 * ci == cache-inhibited portal register 87 * ce == cache-enabled portal register 88 * vb == in-band valid-bit (cache-enabled) 89 */ 90enum bm_rcr_pmode { /* matches BCSP_CFG::RPM */ 91 bm_rcr_pci = 0, /* PI index, cache-inhibited */ 92 bm_rcr_pce = 1, /* PI index, cache-enabled */ 93 bm_rcr_pvb = 2 /* valid-bit */ 94}; 95enum bm_rcr_cmode { /* s/w-only */ 96 bm_rcr_cci, /* CI index, cache-inhibited */ 97 bm_rcr_cce /* CI index, cache-enabled */ 98}; 99 100 101/* --- Portal structures --- */ 102 103#define BM_RCR_SIZE 8 104 105/* Release Command */ 106struct bm_rcr_entry { 107 union { 108 struct { 109 u8 _ncw_verb; /* writes to this are non-coherent */ 110 u8 bpid; /* used with BM_RCR_VERB_CMD_BPID_SINGLE */ 111 u8 __reserved1[62]; 112 }; 113 struct bm_buffer bufs[8]; 114 }; 115}; 116#define BM_RCR_VERB_VBIT 0x80 117#define BM_RCR_VERB_CMD_MASK 0x70 /* one of two values; */ 118#define BM_RCR_VERB_CMD_BPID_SINGLE 0x20 119#define BM_RCR_VERB_CMD_BPID_MULTI 0x30 120#define BM_RCR_VERB_BUFCOUNT_MASK 0x0f /* values 1..8 */ 121 122struct bm_rcr { 123 struct bm_rcr_entry *ring, *cursor; 124 u8 ci, available, ithresh, vbit; 125#ifdef CONFIG_FSL_DPAA_CHECKING 126 u32 busy; 127 enum bm_rcr_pmode pmode; 128 enum bm_rcr_cmode cmode; 129#endif 130}; 131 132/* MC (Management Command) command */ 133struct bm_mc_command { 134 u8 _ncw_verb; /* writes to this are non-coherent */ 135 u8 bpid; /* used by acquire command */ 136 u8 __reserved[62]; 137}; 138#define BM_MCC_VERB_VBIT 0x80 139#define BM_MCC_VERB_CMD_MASK 0x70 /* where the verb contains; */ 140#define BM_MCC_VERB_CMD_ACQUIRE 0x10 141#define BM_MCC_VERB_CMD_QUERY 0x40 142#define BM_MCC_VERB_ACQUIRE_BUFCOUNT 0x0f /* values 1..8 go here */ 143 144/* MC result, Acquire and Query Response */ 145union bm_mc_result { 146 struct { 147 u8 verb; 148 u8 bpid; 149 u8 __reserved[62]; 150 }; 151 struct bm_buffer bufs[8]; 152}; 153#define BM_MCR_VERB_VBIT 0x80 154#define BM_MCR_VERB_CMD_MASK BM_MCC_VERB_CMD_MASK 155#define BM_MCR_VERB_CMD_ACQUIRE BM_MCC_VERB_CMD_ACQUIRE 156#define BM_MCR_VERB_CMD_QUERY BM_MCC_VERB_CMD_QUERY 157#define BM_MCR_VERB_CMD_ERR_INVALID 0x60 158#define BM_MCR_VERB_CMD_ERR_ECC 0x70 159#define BM_MCR_VERB_ACQUIRE_BUFCOUNT BM_MCC_VERB_ACQUIRE_BUFCOUNT /* 0..8 */ 160#define BM_MCR_TIMEOUT 10000 /* us */ 161 162struct bm_mc { 163 struct bm_mc_command *cr; 164 union bm_mc_result *rr; 165 u8 rridx, vbit; 166#ifdef CONFIG_FSL_DPAA_CHECKING 167 enum { 168 /* Can only be _mc_start()ed */ 169 mc_idle, 170 /* Can only be _mc_commit()ed or _mc_abort()ed */ 171 mc_user, 172 /* Can only be _mc_retry()ed */ 173 mc_hw 174 } state; 175#endif 176}; 177 178struct bm_addr { 179 void *ce; /* cache-enabled */ 180 __be32 *ce_be; /* Same as above but for direct access */ 181 void __iomem *ci; /* cache-inhibited */ 182}; 183 184struct bm_portal { 185 struct bm_addr addr; 186 struct bm_rcr rcr; 187 struct bm_mc mc; 188} ____cacheline_aligned; 189 190/* Cache-inhibited register access. */ 191static inline u32 bm_in(struct bm_portal *p, u32 offset) 192{ 193 return ioread32be(p->addr.ci + offset); 194} 195 196static inline void bm_out(struct bm_portal *p, u32 offset, u32 val) 197{ 198 iowrite32be(val, p->addr.ci + offset); 199} 200 201/* Cache Enabled Portal Access */ 202static inline void bm_cl_invalidate(struct bm_portal *p, u32 offset) 203{ 204 dpaa_invalidate(p->addr.ce + offset); 205} 206 207static inline void bm_cl_touch_ro(struct bm_portal *p, u32 offset) 208{ 209 dpaa_touch_ro(p->addr.ce + offset); 210} 211 212static inline u32 bm_ce_in(struct bm_portal *p, u32 offset) 213{ 214 return be32_to_cpu(*(p->addr.ce_be + (offset/4))); 215} 216 217struct bman_portal { 218 struct bm_portal p; 219 /* interrupt sources processed by portal_isr(), configurable */ 220 unsigned long irq_sources; 221 /* probing time config params for cpu-affine portals */ 222 const struct bm_portal_config *config; 223 char irqname[MAX_IRQNAME]; 224}; 225 226static cpumask_t affine_mask; 227static DEFINE_SPINLOCK(affine_mask_lock); 228static DEFINE_PER_CPU(struct bman_portal, bman_affine_portal); 229 230static inline struct bman_portal *get_affine_portal(void) 231{ 232 return &get_cpu_var(bman_affine_portal); 233} 234 235static inline void put_affine_portal(void) 236{ 237 put_cpu_var(bman_affine_portal); 238} 239 240/* 241 * This object type refers to a pool, it isn't *the* pool. There may be 242 * more than one such object per BMan buffer pool, eg. if different users of the 243 * pool are operating via different portals. 244 */ 245struct bman_pool { 246 /* index of the buffer pool to encapsulate (0-63) */ 247 u32 bpid; 248 /* Used for hash-table admin when using depletion notifications. */ 249 struct bman_portal *portal; 250 struct bman_pool *next; 251}; 252 253static u32 poll_portal_slow(struct bman_portal *p, u32 is); 254 255static irqreturn_t portal_isr(int irq, void *ptr) 256{ 257 struct bman_portal *p = ptr; 258 struct bm_portal *portal = &p->p; 259 u32 clear = p->irq_sources; 260 u32 is = bm_in(portal, BM_REG_ISR) & p->irq_sources; 261 262 if (unlikely(!is)) 263 return IRQ_NONE; 264 265 clear |= poll_portal_slow(p, is); 266 bm_out(portal, BM_REG_ISR, clear); 267 return IRQ_HANDLED; 268} 269 270/* --- RCR API --- */ 271 272#define RCR_SHIFT ilog2(sizeof(struct bm_rcr_entry)) 273#define RCR_CARRY (uintptr_t)(BM_RCR_SIZE << RCR_SHIFT) 274 275/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */ 276static struct bm_rcr_entry *rcr_carryclear(struct bm_rcr_entry *p) 277{ 278 uintptr_t addr = (uintptr_t)p; 279 280 addr &= ~RCR_CARRY; 281 282 return (struct bm_rcr_entry *)addr; 283} 284 285#ifdef CONFIG_FSL_DPAA_CHECKING 286/* Bit-wise logic to convert a ring pointer to a ring index */ 287static int rcr_ptr2idx(struct bm_rcr_entry *e) 288{ 289 return ((uintptr_t)e >> RCR_SHIFT) & (BM_RCR_SIZE - 1); 290} 291#endif 292 293/* Increment the 'cursor' ring pointer, taking 'vbit' into account */ 294static inline void rcr_inc(struct bm_rcr *rcr) 295{ 296 /* increment to the next RCR pointer and handle overflow and 'vbit' */ 297 struct bm_rcr_entry *partial = rcr->cursor + 1; 298 299 rcr->cursor = rcr_carryclear(partial); 300 if (partial != rcr->cursor) 301 rcr->vbit ^= BM_RCR_VERB_VBIT; 302} 303 304static int bm_rcr_get_avail(struct bm_portal *portal) 305{ 306 struct bm_rcr *rcr = &portal->rcr; 307 308 return rcr->available; 309} 310 311static int bm_rcr_get_fill(struct bm_portal *portal) 312{ 313 struct bm_rcr *rcr = &portal->rcr; 314 315 return BM_RCR_SIZE - 1 - rcr->available; 316} 317 318static void bm_rcr_set_ithresh(struct bm_portal *portal, u8 ithresh) 319{ 320 struct bm_rcr *rcr = &portal->rcr; 321 322 rcr->ithresh = ithresh; 323 bm_out(portal, BM_REG_RCR_ITR, ithresh); 324} 325 326static void bm_rcr_cce_prefetch(struct bm_portal *portal) 327{ 328 __maybe_unused struct bm_rcr *rcr = &portal->rcr; 329 330 DPAA_ASSERT(rcr->cmode == bm_rcr_cce); 331 bm_cl_touch_ro(portal, BM_CL_RCR_CI_CENA); 332} 333 334static u8 bm_rcr_cce_update(struct bm_portal *portal) 335{ 336 struct bm_rcr *rcr = &portal->rcr; 337 u8 diff, old_ci = rcr->ci; 338 339 DPAA_ASSERT(rcr->cmode == bm_rcr_cce); 340 rcr->ci = bm_ce_in(portal, BM_CL_RCR_CI_CENA) & (BM_RCR_SIZE - 1); 341 bm_cl_invalidate(portal, BM_CL_RCR_CI_CENA); 342 diff = dpaa_cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci); 343 rcr->available += diff; 344 return diff; 345} 346 347static inline struct bm_rcr_entry *bm_rcr_start(struct bm_portal *portal) 348{ 349 struct bm_rcr *rcr = &portal->rcr; 350 351 DPAA_ASSERT(!rcr->busy); 352 if (!rcr->available) 353 return NULL; 354#ifdef CONFIG_FSL_DPAA_CHECKING 355 rcr->busy = 1; 356#endif 357 dpaa_zero(rcr->cursor); 358 return rcr->cursor; 359} 360 361static inline void bm_rcr_pvb_commit(struct bm_portal *portal, u8 myverb) 362{ 363 struct bm_rcr *rcr = &portal->rcr; 364 struct bm_rcr_entry *rcursor; 365 366 DPAA_ASSERT(rcr->busy); 367 DPAA_ASSERT(rcr->pmode == bm_rcr_pvb); 368 DPAA_ASSERT(rcr->available >= 1); 369 dma_wmb(); 370 rcursor = rcr->cursor; 371 rcursor->_ncw_verb = myverb | rcr->vbit; 372 dpaa_flush(rcursor); 373 rcr_inc(rcr); 374 rcr->available--; 375#ifdef CONFIG_FSL_DPAA_CHECKING 376 rcr->busy = 0; 377#endif 378} 379 380static int bm_rcr_init(struct bm_portal *portal, enum bm_rcr_pmode pmode, 381 enum bm_rcr_cmode cmode) 382{ 383 struct bm_rcr *rcr = &portal->rcr; 384 u32 cfg; 385 u8 pi; 386 387 rcr->ring = portal->addr.ce + BM_CL_RCR; 388 rcr->ci = bm_in(portal, BM_REG_RCR_CI_CINH) & (BM_RCR_SIZE - 1); 389 pi = bm_in(portal, BM_REG_RCR_PI_CINH) & (BM_RCR_SIZE - 1); 390 rcr->cursor = rcr->ring + pi; 391 rcr->vbit = (bm_in(portal, BM_REG_RCR_PI_CINH) & BM_RCR_SIZE) ? 392 BM_RCR_VERB_VBIT : 0; 393 rcr->available = BM_RCR_SIZE - 1 394 - dpaa_cyc_diff(BM_RCR_SIZE, rcr->ci, pi); 395 rcr->ithresh = bm_in(portal, BM_REG_RCR_ITR); 396#ifdef CONFIG_FSL_DPAA_CHECKING 397 rcr->busy = 0; 398 rcr->pmode = pmode; 399 rcr->cmode = cmode; 400#endif 401 cfg = (bm_in(portal, BM_REG_CFG) & 0xffffffe0) 402 | (pmode & 0x3); /* BCSP_CFG::RPM */ 403 bm_out(portal, BM_REG_CFG, cfg); 404 return 0; 405} 406 407static void bm_rcr_finish(struct bm_portal *portal) 408{ 409#ifdef CONFIG_FSL_DPAA_CHECKING 410 struct bm_rcr *rcr = &portal->rcr; 411 int i; 412 413 DPAA_ASSERT(!rcr->busy); 414 415 i = bm_in(portal, BM_REG_RCR_PI_CINH) & (BM_RCR_SIZE - 1); 416 if (i != rcr_ptr2idx(rcr->cursor)) 417 pr_crit("losing uncommitted RCR entries\n"); 418 419 i = bm_in(portal, BM_REG_RCR_CI_CINH) & (BM_RCR_SIZE - 1); 420 if (i != rcr->ci) 421 pr_crit("missing existing RCR completions\n"); 422 if (rcr->ci != rcr_ptr2idx(rcr->cursor)) 423 pr_crit("RCR destroyed unquiesced\n"); 424#endif 425} 426 427/* --- Management command API --- */ 428static int bm_mc_init(struct bm_portal *portal) 429{ 430 struct bm_mc *mc = &portal->mc; 431 432 mc->cr = portal->addr.ce + BM_CL_CR; 433 mc->rr = portal->addr.ce + BM_CL_RR0; 434 mc->rridx = (mc->cr->_ncw_verb & BM_MCC_VERB_VBIT) ? 435 0 : 1; 436 mc->vbit = mc->rridx ? BM_MCC_VERB_VBIT : 0; 437#ifdef CONFIG_FSL_DPAA_CHECKING 438 mc->state = mc_idle; 439#endif 440 return 0; 441} 442 443static void bm_mc_finish(struct bm_portal *portal) 444{ 445#ifdef CONFIG_FSL_DPAA_CHECKING 446 struct bm_mc *mc = &portal->mc; 447 448 DPAA_ASSERT(mc->state == mc_idle); 449 if (mc->state != mc_idle) 450 pr_crit("Losing incomplete MC command\n"); 451#endif 452} 453 454static inline struct bm_mc_command *bm_mc_start(struct bm_portal *portal) 455{ 456 struct bm_mc *mc = &portal->mc; 457 458 DPAA_ASSERT(mc->state == mc_idle); 459#ifdef CONFIG_FSL_DPAA_CHECKING 460 mc->state = mc_user; 461#endif 462 dpaa_zero(mc->cr); 463 return mc->cr; 464} 465 466static inline void bm_mc_commit(struct bm_portal *portal, u8 myverb) 467{ 468 struct bm_mc *mc = &portal->mc; 469 union bm_mc_result *rr = mc->rr + mc->rridx; 470 471 DPAA_ASSERT(mc->state == mc_user); 472 dma_wmb(); 473 mc->cr->_ncw_verb = myverb | mc->vbit; 474 dpaa_flush(mc->cr); 475 dpaa_invalidate_touch_ro(rr); 476#ifdef CONFIG_FSL_DPAA_CHECKING 477 mc->state = mc_hw; 478#endif 479} 480 481static inline union bm_mc_result *bm_mc_result(struct bm_portal *portal) 482{ 483 struct bm_mc *mc = &portal->mc; 484 union bm_mc_result *rr = mc->rr + mc->rridx; 485 486 DPAA_ASSERT(mc->state == mc_hw); 487 /* 488 * The inactive response register's verb byte always returns zero until 489 * its command is submitted and completed. This includes the valid-bit, 490 * in case you were wondering... 491 */ 492 if (!rr->verb) { 493 dpaa_invalidate_touch_ro(rr); 494 return NULL; 495 } 496 mc->rridx ^= 1; 497 mc->vbit ^= BM_MCC_VERB_VBIT; 498#ifdef CONFIG_FSL_DPAA_CHECKING 499 mc->state = mc_idle; 500#endif 501 return rr; 502} 503 504static inline int bm_mc_result_timeout(struct bm_portal *portal, 505 union bm_mc_result **mcr) 506{ 507 int timeout = BM_MCR_TIMEOUT; 508 509 do { 510 *mcr = bm_mc_result(portal); 511 if (*mcr) 512 break; 513 udelay(1); 514 } while (--timeout); 515 516 return timeout; 517} 518 519/* Disable all BSCN interrupts for the portal */ 520static void bm_isr_bscn_disable(struct bm_portal *portal) 521{ 522 bm_out(portal, BM_REG_SCN(0), 0); 523 bm_out(portal, BM_REG_SCN(1), 0); 524} 525 526static int bman_create_portal(struct bman_portal *portal, 527 const struct bm_portal_config *c) 528{ 529 struct bm_portal *p; 530 int ret; 531 532 p = &portal->p; 533 /* 534 * prep the low-level portal struct with the mapped addresses from the 535 * config, everything that follows depends on it and "config" is more 536 * for (de)reference... 537 */ 538 p->addr.ce = c->addr_virt_ce; 539 p->addr.ce_be = c->addr_virt_ce; 540 p->addr.ci = c->addr_virt_ci; 541 if (bm_rcr_init(p, bm_rcr_pvb, bm_rcr_cce)) { 542 dev_err(c->dev, "RCR initialisation failed\n"); 543 goto fail_rcr; 544 } 545 if (bm_mc_init(p)) { 546 dev_err(c->dev, "MC initialisation failed\n"); 547 goto fail_mc; 548 } 549 /* 550 * Default to all BPIDs disabled, we enable as required at 551 * run-time. 552 */ 553 bm_isr_bscn_disable(p); 554 555 /* Write-to-clear any stale interrupt status bits */ 556 bm_out(p, BM_REG_ISDR, 0xffffffff); 557 portal->irq_sources = 0; 558 bm_out(p, BM_REG_IER, 0); 559 bm_out(p, BM_REG_ISR, 0xffffffff); 560 snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, c->cpu); 561 if (request_irq(c->irq, portal_isr, 0, portal->irqname, portal)) { 562 dev_err(c->dev, "request_irq() failed\n"); 563 goto fail_irq; 564 } 565 566 if (dpaa_set_portal_irq_affinity(c->dev, c->irq, c->cpu)) 567 goto fail_affinity; 568 569 /* Need RCR to be empty before continuing */ 570 ret = bm_rcr_get_fill(p); 571 if (ret) { 572 dev_err(c->dev, "RCR unclean\n"); 573 goto fail_rcr_empty; 574 } 575 /* Success */ 576 portal->config = c; 577 578 bm_out(p, BM_REG_ISDR, 0); 579 bm_out(p, BM_REG_IIR, 0); 580 581 return 0; 582 583fail_rcr_empty: 584fail_affinity: 585 free_irq(c->irq, portal); 586fail_irq: 587 bm_mc_finish(p); 588fail_mc: 589 bm_rcr_finish(p); 590fail_rcr: 591 return -EIO; 592} 593 594struct bman_portal *bman_create_affine_portal(const struct bm_portal_config *c) 595{ 596 struct bman_portal *portal; 597 int err; 598 599 portal = &per_cpu(bman_affine_portal, c->cpu); 600 err = bman_create_portal(portal, c); 601 if (err) 602 return NULL; 603 604 spin_lock(&affine_mask_lock); 605 cpumask_set_cpu(c->cpu, &affine_mask); 606 spin_unlock(&affine_mask_lock); 607 608 return portal; 609} 610 611static u32 poll_portal_slow(struct bman_portal *p, u32 is) 612{ 613 u32 ret = is; 614 615 if (is & BM_PIRQ_RCRI) { 616 bm_rcr_cce_update(&p->p); 617 bm_rcr_set_ithresh(&p->p, 0); 618 bm_out(&p->p, BM_REG_ISR, BM_PIRQ_RCRI); 619 is &= ~BM_PIRQ_RCRI; 620 } 621 622 /* There should be no status register bits left undefined */ 623 DPAA_ASSERT(!is); 624 return ret; 625} 626 627int bman_p_irqsource_add(struct bman_portal *p, u32 bits) 628{ 629 unsigned long irqflags; 630 631 local_irq_save(irqflags); 632 p->irq_sources |= bits & BM_PIRQ_VISIBLE; 633 bm_out(&p->p, BM_REG_IER, p->irq_sources); 634 local_irq_restore(irqflags); 635 return 0; 636} 637 638int bm_shutdown_pool(u32 bpid) 639{ 640 int err = 0; 641 struct bm_mc_command *bm_cmd; 642 union bm_mc_result *bm_res; 643 644 645 struct bman_portal *p = get_affine_portal(); 646 while (1) { 647 /* Acquire buffers until empty */ 648 bm_cmd = bm_mc_start(&p->p); 649 bm_cmd->bpid = bpid; 650 bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE | 1); 651 if (!bm_mc_result_timeout(&p->p, &bm_res)) { 652 pr_crit("BMan Acquire Command timedout\n"); 653 err = -ETIMEDOUT; 654 goto done; 655 } 656 if (!(bm_res->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT)) { 657 /* Pool is empty */ 658 goto done; 659 } 660 } 661done: 662 put_affine_portal(); 663 return err; 664} 665 666struct gen_pool *bm_bpalloc; 667 668static int bm_alloc_bpid_range(u32 *result, u32 count) 669{ 670 unsigned long addr; 671 672 addr = gen_pool_alloc(bm_bpalloc, count); 673 if (!addr) 674 return -ENOMEM; 675 676 *result = addr & ~DPAA_GENALLOC_OFF; 677 678 return 0; 679} 680 681static int bm_release_bpid(u32 bpid) 682{ 683 int ret; 684 685 ret = bm_shutdown_pool(bpid); 686 if (ret) { 687 pr_debug("BPID %d leaked\n", bpid); 688 return ret; 689 } 690 691 gen_pool_free(bm_bpalloc, bpid | DPAA_GENALLOC_OFF, 1); 692 return 0; 693} 694 695struct bman_pool *bman_new_pool(void) 696{ 697 struct bman_pool *pool = NULL; 698 u32 bpid; 699 700 if (bm_alloc_bpid_range(&bpid, 1)) 701 return NULL; 702 703 pool = kmalloc(sizeof(*pool), GFP_KERNEL); 704 if (!pool) 705 goto err; 706 707 pool->bpid = bpid; 708 709 return pool; 710err: 711 bm_release_bpid(bpid); 712 return NULL; 713} 714EXPORT_SYMBOL(bman_new_pool); 715 716void bman_free_pool(struct bman_pool *pool) 717{ 718 bm_release_bpid(pool->bpid); 719 720 kfree(pool); 721} 722EXPORT_SYMBOL(bman_free_pool); 723 724int bman_get_bpid(const struct bman_pool *pool) 725{ 726 return pool->bpid; 727} 728EXPORT_SYMBOL(bman_get_bpid); 729 730static void update_rcr_ci(struct bman_portal *p, int avail) 731{ 732 if (avail) 733 bm_rcr_cce_prefetch(&p->p); 734 else 735 bm_rcr_cce_update(&p->p); 736} 737 738int bman_release(struct bman_pool *pool, const struct bm_buffer *bufs, u8 num) 739{ 740 struct bman_portal *p; 741 struct bm_rcr_entry *r; 742 unsigned long irqflags; 743 int avail, timeout = 1000; /* 1ms */ 744 int i = num - 1; 745 746 DPAA_ASSERT(num > 0 && num <= 8); 747 748 do { 749 p = get_affine_portal(); 750 local_irq_save(irqflags); 751 avail = bm_rcr_get_avail(&p->p); 752 if (avail < 2) 753 update_rcr_ci(p, avail); 754 r = bm_rcr_start(&p->p); 755 local_irq_restore(irqflags); 756 put_affine_portal(); 757 if (likely(r)) 758 break; 759 760 udelay(1); 761 } while (--timeout); 762 763 if (unlikely(!timeout)) 764 return -ETIMEDOUT; 765 766 p = get_affine_portal(); 767 local_irq_save(irqflags); 768 /* 769 * we can copy all but the first entry, as this can trigger badness 770 * with the valid-bit 771 */ 772 bm_buffer_set64(r->bufs, bm_buffer_get64(bufs)); 773 bm_buffer_set_bpid(r->bufs, pool->bpid); 774 if (i) 775 memcpy(&r->bufs[1], &bufs[1], i * sizeof(bufs[0])); 776 777 bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE | 778 (num & BM_RCR_VERB_BUFCOUNT_MASK)); 779 780 local_irq_restore(irqflags); 781 put_affine_portal(); 782 return 0; 783} 784EXPORT_SYMBOL(bman_release); 785 786int bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num) 787{ 788 struct bman_portal *p = get_affine_portal(); 789 struct bm_mc_command *mcc; 790 union bm_mc_result *mcr; 791 int ret; 792 793 DPAA_ASSERT(num > 0 && num <= 8); 794 795 mcc = bm_mc_start(&p->p); 796 mcc->bpid = pool->bpid; 797 bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE | 798 (num & BM_MCC_VERB_ACQUIRE_BUFCOUNT)); 799 if (!bm_mc_result_timeout(&p->p, &mcr)) { 800 put_affine_portal(); 801 pr_crit("BMan Acquire Timeout\n"); 802 return -ETIMEDOUT; 803 } 804 ret = mcr->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT; 805 if (bufs) 806 memcpy(&bufs[0], &mcr->bufs[0], num * sizeof(bufs[0])); 807 808 put_affine_portal(); 809 if (ret != num) 810 ret = -ENOMEM; 811 return ret; 812} 813EXPORT_SYMBOL(bman_acquire); 814 815const struct bm_portal_config * 816bman_get_bm_portal_config(const struct bman_portal *portal) 817{ 818 return portal->config; 819}