Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.8-rc7 658 lines 18 kB view raw
1/* QLogic qed NIC Driver 2 * Copyright (c) 2015 QLogic Corporation 3 * 4 * This software is available under the terms of the GNU General Public License 5 * (GPL) Version 2, available from the file COPYING in the main directory of 6 * this source tree. 7 */ 8 9#ifndef _QED_CHAIN_H 10#define _QED_CHAIN_H 11 12#include <linux/types.h> 13#include <asm/byteorder.h> 14#include <linux/kernel.h> 15#include <linux/list.h> 16#include <linux/slab.h> 17#include <linux/qed/common_hsi.h> 18 19/* dma_addr_t manip */ 20#define DMA_LO_LE(x) cpu_to_le32(lower_32_bits(x)) 21#define DMA_HI_LE(x) cpu_to_le32(upper_32_bits(x)) 22#define DMA_REGPAIR_LE(x, val) do { \ 23 (x).hi = DMA_HI_LE((val)); \ 24 (x).lo = DMA_LO_LE((val)); \ 25 } while (0) 26 27#define HILO_GEN(hi, lo, type) ((((type)(hi)) << 32) + (lo)) 28#define HILO_64(hi, lo) HILO_GEN((le32_to_cpu(hi)), (le32_to_cpu(lo)), u64) 29#define HILO_64_REGPAIR(regpair) (HILO_64(regpair.hi, regpair.lo)) 30#define HILO_DMA_REGPAIR(regpair) ((dma_addr_t)HILO_64_REGPAIR(regpair)) 31 32enum qed_chain_mode { 33 /* Each Page contains a next pointer at its end */ 34 QED_CHAIN_MODE_NEXT_PTR, 35 36 /* Chain is a single page (next ptr) is unrequired */ 37 QED_CHAIN_MODE_SINGLE, 38 39 /* Page pointers are located in a side list */ 40 QED_CHAIN_MODE_PBL, 41}; 42 43enum qed_chain_use_mode { 44 QED_CHAIN_USE_TO_PRODUCE, /* Chain starts empty */ 45 QED_CHAIN_USE_TO_CONSUME, /* Chain starts full */ 46 QED_CHAIN_USE_TO_CONSUME_PRODUCE, /* Chain starts empty */ 47}; 48 49enum qed_chain_cnt_type { 50 /* The chain's size/prod/cons are kept in 16-bit variables */ 51 QED_CHAIN_CNT_TYPE_U16, 52 53 /* The chain's size/prod/cons are kept in 32-bit variables */ 54 QED_CHAIN_CNT_TYPE_U32, 55}; 56 57struct qed_chain_next { 58 struct regpair next_phys; 59 void *next_virt; 60}; 61 62struct qed_chain_pbl_u16 { 63 u16 prod_page_idx; 64 u16 cons_page_idx; 65}; 66 67struct qed_chain_pbl_u32 { 68 u32 prod_page_idx; 69 u32 cons_page_idx; 70}; 71 72struct qed_chain_pbl { 73 /* Base address of a pre-allocated buffer for pbl */ 74 dma_addr_t p_phys_table; 75 void *p_virt_table; 76 77 /* Table for keeping the virtual addresses of the chain pages, 78 * respectively to the physical addresses in the pbl table. 79 */ 80 void **pp_virt_addr_tbl; 81 82 /* Index to current used page by producer/consumer */ 83 union { 84 struct qed_chain_pbl_u16 pbl16; 85 struct qed_chain_pbl_u32 pbl32; 86 } u; 87}; 88 89struct qed_chain_u16 { 90 /* Cyclic index of next element to produce/consme */ 91 u16 prod_idx; 92 u16 cons_idx; 93}; 94 95struct qed_chain_u32 { 96 /* Cyclic index of next element to produce/consme */ 97 u32 prod_idx; 98 u32 cons_idx; 99}; 100 101struct qed_chain { 102 void *p_virt_addr; 103 dma_addr_t p_phys_addr; 104 void *p_prod_elem; 105 void *p_cons_elem; 106 107 enum qed_chain_mode mode; 108 enum qed_chain_use_mode intended_use; /* used to produce/consume */ 109 enum qed_chain_cnt_type cnt_type; 110 111 union { 112 struct qed_chain_u16 chain16; 113 struct qed_chain_u32 chain32; 114 } u; 115 116 u32 page_cnt; 117 118 /* Number of elements - capacity is for usable elements only, 119 * while size will contain total number of elements [for entire chain]. 120 */ 121 u32 capacity; 122 u32 size; 123 124 /* Elements information for fast calculations */ 125 u16 elem_per_page; 126 u16 elem_per_page_mask; 127 u16 elem_unusable; 128 u16 usable_per_page; 129 u16 elem_size; 130 u16 next_page_mask; 131 struct qed_chain_pbl pbl; 132}; 133 134#define QED_CHAIN_PBL_ENTRY_SIZE (8) 135#define QED_CHAIN_PAGE_SIZE (0x1000) 136#define ELEMS_PER_PAGE(elem_size) (QED_CHAIN_PAGE_SIZE / (elem_size)) 137 138#define UNUSABLE_ELEMS_PER_PAGE(elem_size, mode) \ 139 ((mode == QED_CHAIN_MODE_NEXT_PTR) ? \ 140 (1 + ((sizeof(struct qed_chain_next) - 1) / \ 141 (elem_size))) : 0) 142 143#define USABLE_ELEMS_PER_PAGE(elem_size, mode) \ 144 ((u32)(ELEMS_PER_PAGE(elem_size) - \ 145 UNUSABLE_ELEMS_PER_PAGE(elem_size, mode))) 146 147#define QED_CHAIN_PAGE_CNT(elem_cnt, elem_size, mode) \ 148 DIV_ROUND_UP(elem_cnt, USABLE_ELEMS_PER_PAGE(elem_size, mode)) 149 150#define is_chain_u16(p) ((p)->cnt_type == QED_CHAIN_CNT_TYPE_U16) 151#define is_chain_u32(p) ((p)->cnt_type == QED_CHAIN_CNT_TYPE_U32) 152 153/* Accessors */ 154static inline u16 qed_chain_get_prod_idx(struct qed_chain *p_chain) 155{ 156 return p_chain->u.chain16.prod_idx; 157} 158 159static inline u16 qed_chain_get_cons_idx(struct qed_chain *p_chain) 160{ 161 return p_chain->u.chain16.cons_idx; 162} 163 164static inline u32 qed_chain_get_cons_idx_u32(struct qed_chain *p_chain) 165{ 166 return p_chain->u.chain32.cons_idx; 167} 168 169static inline u16 qed_chain_get_elem_left(struct qed_chain *p_chain) 170{ 171 u16 used; 172 173 used = (u16) (((u32)0x10000 + 174 (u32)p_chain->u.chain16.prod_idx) - 175 (u32)p_chain->u.chain16.cons_idx); 176 if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR) 177 used -= p_chain->u.chain16.prod_idx / p_chain->elem_per_page - 178 p_chain->u.chain16.cons_idx / p_chain->elem_per_page; 179 180 return (u16)(p_chain->capacity - used); 181} 182 183static inline u32 qed_chain_get_elem_left_u32(struct qed_chain *p_chain) 184{ 185 u32 used; 186 187 used = (u32) (((u64)0x100000000ULL + 188 (u64)p_chain->u.chain32.prod_idx) - 189 (u64)p_chain->u.chain32.cons_idx); 190 if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR) 191 used -= p_chain->u.chain32.prod_idx / p_chain->elem_per_page - 192 p_chain->u.chain32.cons_idx / p_chain->elem_per_page; 193 194 return p_chain->capacity - used; 195} 196 197static inline u16 qed_chain_get_usable_per_page(struct qed_chain *p_chain) 198{ 199 return p_chain->usable_per_page; 200} 201 202static inline u16 qed_chain_get_unusable_per_page(struct qed_chain *p_chain) 203{ 204 return p_chain->elem_unusable; 205} 206 207static inline u32 qed_chain_get_page_cnt(struct qed_chain *p_chain) 208{ 209 return p_chain->page_cnt; 210} 211 212static inline dma_addr_t qed_chain_get_pbl_phys(struct qed_chain *p_chain) 213{ 214 return p_chain->pbl.p_phys_table; 215} 216 217/** 218 * @brief qed_chain_advance_page - 219 * 220 * Advance the next element accros pages for a linked chain 221 * 222 * @param p_chain 223 * @param p_next_elem 224 * @param idx_to_inc 225 * @param page_to_inc 226 */ 227static inline void 228qed_chain_advance_page(struct qed_chain *p_chain, 229 void **p_next_elem, void *idx_to_inc, void *page_to_inc) 230 231{ 232 struct qed_chain_next *p_next = NULL; 233 u32 page_index = 0; 234 switch (p_chain->mode) { 235 case QED_CHAIN_MODE_NEXT_PTR: 236 p_next = *p_next_elem; 237 *p_next_elem = p_next->next_virt; 238 if (is_chain_u16(p_chain)) 239 *(u16 *)idx_to_inc += p_chain->elem_unusable; 240 else 241 *(u32 *)idx_to_inc += p_chain->elem_unusable; 242 break; 243 case QED_CHAIN_MODE_SINGLE: 244 *p_next_elem = p_chain->p_virt_addr; 245 break; 246 247 case QED_CHAIN_MODE_PBL: 248 if (is_chain_u16(p_chain)) { 249 if (++(*(u16 *)page_to_inc) == p_chain->page_cnt) 250 *(u16 *)page_to_inc = 0; 251 page_index = *(u16 *)page_to_inc; 252 } else { 253 if (++(*(u32 *)page_to_inc) == p_chain->page_cnt) 254 *(u32 *)page_to_inc = 0; 255 page_index = *(u32 *)page_to_inc; 256 } 257 *p_next_elem = p_chain->pbl.pp_virt_addr_tbl[page_index]; 258 } 259} 260 261#define is_unusable_idx(p, idx) \ 262 (((p)->u.chain16.idx & (p)->elem_per_page_mask) == (p)->usable_per_page) 263 264#define is_unusable_idx_u32(p, idx) \ 265 (((p)->u.chain32.idx & (p)->elem_per_page_mask) == (p)->usable_per_page) 266#define is_unusable_next_idx(p, idx) \ 267 ((((p)->u.chain16.idx + 1) & (p)->elem_per_page_mask) == \ 268 (p)->usable_per_page) 269 270#define is_unusable_next_idx_u32(p, idx) \ 271 ((((p)->u.chain32.idx + 1) & (p)->elem_per_page_mask) == \ 272 (p)->usable_per_page) 273 274#define test_and_skip(p, idx) \ 275 do { \ 276 if (is_chain_u16(p)) { \ 277 if (is_unusable_idx(p, idx)) \ 278 (p)->u.chain16.idx += (p)->elem_unusable; \ 279 } else { \ 280 if (is_unusable_idx_u32(p, idx)) \ 281 (p)->u.chain32.idx += (p)->elem_unusable; \ 282 } \ 283 } while (0) 284 285/** 286 * @brief qed_chain_return_produced - 287 * 288 * A chain in which the driver "Produces" elements should use this API 289 * to indicate previous produced elements are now consumed. 290 * 291 * @param p_chain 292 */ 293static inline void qed_chain_return_produced(struct qed_chain *p_chain) 294{ 295 if (is_chain_u16(p_chain)) 296 p_chain->u.chain16.cons_idx++; 297 else 298 p_chain->u.chain32.cons_idx++; 299 test_and_skip(p_chain, cons_idx); 300} 301 302/** 303 * @brief qed_chain_produce - 304 * 305 * A chain in which the driver "Produces" elements should use this to get 306 * a pointer to the next element which can be "Produced". It's driver 307 * responsibility to validate that the chain has room for new element. 308 * 309 * @param p_chain 310 * 311 * @return void*, a pointer to next element 312 */ 313static inline void *qed_chain_produce(struct qed_chain *p_chain) 314{ 315 void *p_ret = NULL, *p_prod_idx, *p_prod_page_idx; 316 317 if (is_chain_u16(p_chain)) { 318 if ((p_chain->u.chain16.prod_idx & 319 p_chain->elem_per_page_mask) == p_chain->next_page_mask) { 320 p_prod_idx = &p_chain->u.chain16.prod_idx; 321 p_prod_page_idx = &p_chain->pbl.u.pbl16.prod_page_idx; 322 qed_chain_advance_page(p_chain, &p_chain->p_prod_elem, 323 p_prod_idx, p_prod_page_idx); 324 } 325 p_chain->u.chain16.prod_idx++; 326 } else { 327 if ((p_chain->u.chain32.prod_idx & 328 p_chain->elem_per_page_mask) == p_chain->next_page_mask) { 329 p_prod_idx = &p_chain->u.chain32.prod_idx; 330 p_prod_page_idx = &p_chain->pbl.u.pbl32.prod_page_idx; 331 qed_chain_advance_page(p_chain, &p_chain->p_prod_elem, 332 p_prod_idx, p_prod_page_idx); 333 } 334 p_chain->u.chain32.prod_idx++; 335 } 336 337 p_ret = p_chain->p_prod_elem; 338 p_chain->p_prod_elem = (void *)(((u8 *)p_chain->p_prod_elem) + 339 p_chain->elem_size); 340 341 return p_ret; 342} 343 344/** 345 * @brief qed_chain_get_capacity - 346 * 347 * Get the maximum number of BDs in chain 348 * 349 * @param p_chain 350 * @param num 351 * 352 * @return number of unusable BDs 353 */ 354static inline u32 qed_chain_get_capacity(struct qed_chain *p_chain) 355{ 356 return p_chain->capacity; 357} 358 359/** 360 * @brief qed_chain_recycle_consumed - 361 * 362 * Returns an element which was previously consumed; 363 * Increments producers so they could be written to FW. 364 * 365 * @param p_chain 366 */ 367static inline void qed_chain_recycle_consumed(struct qed_chain *p_chain) 368{ 369 test_and_skip(p_chain, prod_idx); 370 if (is_chain_u16(p_chain)) 371 p_chain->u.chain16.prod_idx++; 372 else 373 p_chain->u.chain32.prod_idx++; 374} 375 376/** 377 * @brief qed_chain_consume - 378 * 379 * A Chain in which the driver utilizes data written by a different source 380 * (i.e., FW) should use this to access passed buffers. 381 * 382 * @param p_chain 383 * 384 * @return void*, a pointer to the next buffer written 385 */ 386static inline void *qed_chain_consume(struct qed_chain *p_chain) 387{ 388 void *p_ret = NULL, *p_cons_idx, *p_cons_page_idx; 389 390 if (is_chain_u16(p_chain)) { 391 if ((p_chain->u.chain16.cons_idx & 392 p_chain->elem_per_page_mask) == p_chain->next_page_mask) { 393 p_cons_idx = &p_chain->u.chain16.cons_idx; 394 p_cons_page_idx = &p_chain->pbl.u.pbl16.cons_page_idx; 395 qed_chain_advance_page(p_chain, &p_chain->p_cons_elem, 396 p_cons_idx, p_cons_page_idx); 397 } 398 p_chain->u.chain16.cons_idx++; 399 } else { 400 if ((p_chain->u.chain32.cons_idx & 401 p_chain->elem_per_page_mask) == p_chain->next_page_mask) { 402 p_cons_idx = &p_chain->u.chain32.cons_idx; 403 p_cons_page_idx = &p_chain->pbl.u.pbl32.cons_page_idx; 404 qed_chain_advance_page(p_chain, &p_chain->p_cons_elem, 405 p_cons_idx, p_cons_page_idx); 406 } 407 p_chain->u.chain32.cons_idx++; 408 } 409 410 p_ret = p_chain->p_cons_elem; 411 p_chain->p_cons_elem = (void *)(((u8 *)p_chain->p_cons_elem) + 412 p_chain->elem_size); 413 414 return p_ret; 415} 416 417/** 418 * @brief qed_chain_reset - Resets the chain to its start state 419 * 420 * @param p_chain pointer to a previously allocted chain 421 */ 422static inline void qed_chain_reset(struct qed_chain *p_chain) 423{ 424 u32 i; 425 426 if (is_chain_u16(p_chain)) { 427 p_chain->u.chain16.prod_idx = 0; 428 p_chain->u.chain16.cons_idx = 0; 429 } else { 430 p_chain->u.chain32.prod_idx = 0; 431 p_chain->u.chain32.cons_idx = 0; 432 } 433 p_chain->p_cons_elem = p_chain->p_virt_addr; 434 p_chain->p_prod_elem = p_chain->p_virt_addr; 435 436 if (p_chain->mode == QED_CHAIN_MODE_PBL) { 437 /* Use (page_cnt - 1) as a reset value for the prod/cons page's 438 * indices, to avoid unnecessary page advancing on the first 439 * call to qed_chain_produce/consume. Instead, the indices 440 * will be advanced to page_cnt and then will be wrapped to 0. 441 */ 442 u32 reset_val = p_chain->page_cnt - 1; 443 444 if (is_chain_u16(p_chain)) { 445 p_chain->pbl.u.pbl16.prod_page_idx = (u16)reset_val; 446 p_chain->pbl.u.pbl16.cons_page_idx = (u16)reset_val; 447 } else { 448 p_chain->pbl.u.pbl32.prod_page_idx = reset_val; 449 p_chain->pbl.u.pbl32.cons_page_idx = reset_val; 450 } 451 } 452 453 switch (p_chain->intended_use) { 454 case QED_CHAIN_USE_TO_CONSUME_PRODUCE: 455 case QED_CHAIN_USE_TO_PRODUCE: 456 /* Do nothing */ 457 break; 458 459 case QED_CHAIN_USE_TO_CONSUME: 460 /* produce empty elements */ 461 for (i = 0; i < p_chain->capacity; i++) 462 qed_chain_recycle_consumed(p_chain); 463 break; 464 } 465} 466 467/** 468 * @brief qed_chain_init - Initalizes a basic chain struct 469 * 470 * @param p_chain 471 * @param p_virt_addr 472 * @param p_phys_addr physical address of allocated buffer's beginning 473 * @param page_cnt number of pages in the allocated buffer 474 * @param elem_size size of each element in the chain 475 * @param intended_use 476 * @param mode 477 */ 478static inline void qed_chain_init_params(struct qed_chain *p_chain, 479 u32 page_cnt, 480 u8 elem_size, 481 enum qed_chain_use_mode intended_use, 482 enum qed_chain_mode mode, 483 enum qed_chain_cnt_type cnt_type) 484{ 485 /* chain fixed parameters */ 486 p_chain->p_virt_addr = NULL; 487 p_chain->p_phys_addr = 0; 488 p_chain->elem_size = elem_size; 489 p_chain->intended_use = intended_use; 490 p_chain->mode = mode; 491 p_chain->cnt_type = cnt_type; 492 493 p_chain->elem_per_page = ELEMS_PER_PAGE(elem_size); 494 p_chain->usable_per_page = USABLE_ELEMS_PER_PAGE(elem_size, mode); 495 p_chain->elem_per_page_mask = p_chain->elem_per_page - 1; 496 p_chain->elem_unusable = UNUSABLE_ELEMS_PER_PAGE(elem_size, mode); 497 p_chain->next_page_mask = (p_chain->usable_per_page & 498 p_chain->elem_per_page_mask); 499 500 p_chain->page_cnt = page_cnt; 501 p_chain->capacity = p_chain->usable_per_page * page_cnt; 502 p_chain->size = p_chain->elem_per_page * page_cnt; 503 504 p_chain->pbl.p_phys_table = 0; 505 p_chain->pbl.p_virt_table = NULL; 506 p_chain->pbl.pp_virt_addr_tbl = NULL; 507} 508 509/** 510 * @brief qed_chain_init_mem - 511 * 512 * Initalizes a basic chain struct with its chain buffers 513 * 514 * @param p_chain 515 * @param p_virt_addr virtual address of allocated buffer's beginning 516 * @param p_phys_addr physical address of allocated buffer's beginning 517 * 518 */ 519static inline void qed_chain_init_mem(struct qed_chain *p_chain, 520 void *p_virt_addr, dma_addr_t p_phys_addr) 521{ 522 p_chain->p_virt_addr = p_virt_addr; 523 p_chain->p_phys_addr = p_phys_addr; 524} 525 526/** 527 * @brief qed_chain_init_pbl_mem - 528 * 529 * Initalizes a basic chain struct with its pbl buffers 530 * 531 * @param p_chain 532 * @param p_virt_pbl pointer to a pre allocated side table which will hold 533 * virtual page addresses. 534 * @param p_phys_pbl pointer to a pre-allocated side table which will hold 535 * physical page addresses. 536 * @param pp_virt_addr_tbl 537 * pointer to a pre-allocated side table which will hold 538 * the virtual addresses of the chain pages. 539 * 540 */ 541static inline void qed_chain_init_pbl_mem(struct qed_chain *p_chain, 542 void *p_virt_pbl, 543 dma_addr_t p_phys_pbl, 544 void **pp_virt_addr_tbl) 545{ 546 p_chain->pbl.p_phys_table = p_phys_pbl; 547 p_chain->pbl.p_virt_table = p_virt_pbl; 548 p_chain->pbl.pp_virt_addr_tbl = pp_virt_addr_tbl; 549} 550 551/** 552 * @brief qed_chain_init_next_ptr_elem - 553 * 554 * Initalizes a next pointer element 555 * 556 * @param p_chain 557 * @param p_virt_curr virtual address of a chain page of which the next 558 * pointer element is initialized 559 * @param p_virt_next virtual address of the next chain page 560 * @param p_phys_next physical address of the next chain page 561 * 562 */ 563static inline void 564qed_chain_init_next_ptr_elem(struct qed_chain *p_chain, 565 void *p_virt_curr, 566 void *p_virt_next, dma_addr_t p_phys_next) 567{ 568 struct qed_chain_next *p_next; 569 u32 size; 570 571 size = p_chain->elem_size * p_chain->usable_per_page; 572 p_next = (struct qed_chain_next *)((u8 *)p_virt_curr + size); 573 574 DMA_REGPAIR_LE(p_next->next_phys, p_phys_next); 575 576 p_next->next_virt = p_virt_next; 577} 578 579/** 580 * @brief qed_chain_get_last_elem - 581 * 582 * Returns a pointer to the last element of the chain 583 * 584 * @param p_chain 585 * 586 * @return void* 587 */ 588static inline void *qed_chain_get_last_elem(struct qed_chain *p_chain) 589{ 590 struct qed_chain_next *p_next = NULL; 591 void *p_virt_addr = NULL; 592 u32 size, last_page_idx; 593 594 if (!p_chain->p_virt_addr) 595 goto out; 596 597 switch (p_chain->mode) { 598 case QED_CHAIN_MODE_NEXT_PTR: 599 size = p_chain->elem_size * p_chain->usable_per_page; 600 p_virt_addr = p_chain->p_virt_addr; 601 p_next = (struct qed_chain_next *)((u8 *)p_virt_addr + size); 602 while (p_next->next_virt != p_chain->p_virt_addr) { 603 p_virt_addr = p_next->next_virt; 604 p_next = (struct qed_chain_next *)((u8 *)p_virt_addr + 605 size); 606 } 607 break; 608 case QED_CHAIN_MODE_SINGLE: 609 p_virt_addr = p_chain->p_virt_addr; 610 break; 611 case QED_CHAIN_MODE_PBL: 612 last_page_idx = p_chain->page_cnt - 1; 613 p_virt_addr = p_chain->pbl.pp_virt_addr_tbl[last_page_idx]; 614 break; 615 } 616 /* p_virt_addr points at this stage to the last page of the chain */ 617 size = p_chain->elem_size * (p_chain->usable_per_page - 1); 618 p_virt_addr = (u8 *)p_virt_addr + size; 619out: 620 return p_virt_addr; 621} 622 623/** 624 * @brief qed_chain_set_prod - sets the prod to the given value 625 * 626 * @param prod_idx 627 * @param p_prod_elem 628 */ 629static inline void qed_chain_set_prod(struct qed_chain *p_chain, 630 u32 prod_idx, void *p_prod_elem) 631{ 632 if (is_chain_u16(p_chain)) 633 p_chain->u.chain16.prod_idx = (u16) prod_idx; 634 else 635 p_chain->u.chain32.prod_idx = prod_idx; 636 p_chain->p_prod_elem = p_prod_elem; 637} 638 639/** 640 * @brief qed_chain_pbl_zero_mem - set chain memory to 0 641 * 642 * @param p_chain 643 */ 644static inline void qed_chain_pbl_zero_mem(struct qed_chain *p_chain) 645{ 646 u32 i, page_cnt; 647 648 if (p_chain->mode != QED_CHAIN_MODE_PBL) 649 return; 650 651 page_cnt = qed_chain_get_page_cnt(p_chain); 652 653 for (i = 0; i < page_cnt; i++) 654 memset(p_chain->pbl.pp_virt_addr_tbl[i], 0, 655 QED_CHAIN_PAGE_SIZE); 656} 657 658#endif