diff options
Diffstat (limited to 'drivers/infiniband/hw/cxgb4/t4.h')
-rw-r--r-- | drivers/infiniband/hw/cxgb4/t4.h | 72 |
1 files changed, 67 insertions, 5 deletions
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index eeca8b1e6376..2178f3198410 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h | |||
@@ -84,7 +84,14 @@ struct t4_status_page { | |||
84 | sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge)) | 84 | sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge)) |
85 | #define T4_MAX_FR_IMMD ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_fr_nsmr_wr) - \ | 85 | #define T4_MAX_FR_IMMD ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_fr_nsmr_wr) - \ |
86 | sizeof(struct fw_ri_immd)) & ~31UL) | 86 | sizeof(struct fw_ri_immd)) & ~31UL) |
87 | #define T4_MAX_FR_DEPTH (1024 / sizeof(u64)) | 87 | #define T4_MAX_FR_IMMD_DEPTH (T4_MAX_FR_IMMD / sizeof(u64)) |
88 | #define T4_MAX_FR_DSGL 1024 | ||
89 | #define T4_MAX_FR_DSGL_DEPTH (T4_MAX_FR_DSGL / sizeof(u64)) | ||
90 | |||
91 | static inline int t4_max_fr_depth(int use_dsgl) | ||
92 | { | ||
93 | return use_dsgl ? T4_MAX_FR_DSGL_DEPTH : T4_MAX_FR_IMMD_DEPTH; | ||
94 | } | ||
88 | 95 | ||
89 | #define T4_RQ_NUM_SLOTS 2 | 96 | #define T4_RQ_NUM_SLOTS 2 |
90 | #define T4_RQ_NUM_BYTES (T4_EQ_ENTRY_SIZE * T4_RQ_NUM_SLOTS) | 97 | #define T4_RQ_NUM_BYTES (T4_EQ_ENTRY_SIZE * T4_RQ_NUM_SLOTS) |
@@ -292,7 +299,7 @@ struct t4_sq { | |||
292 | unsigned long phys_addr; | 299 | unsigned long phys_addr; |
293 | struct t4_swsqe *sw_sq; | 300 | struct t4_swsqe *sw_sq; |
294 | struct t4_swsqe *oldest_read; | 301 | struct t4_swsqe *oldest_read; |
295 | u64 udb; | 302 | u64 __iomem *udb; |
296 | size_t memsize; | 303 | size_t memsize; |
297 | u32 qid; | 304 | u32 qid; |
298 | u16 in_use; | 305 | u16 in_use; |
@@ -314,7 +321,7 @@ struct t4_rq { | |||
314 | dma_addr_t dma_addr; | 321 | dma_addr_t dma_addr; |
315 | DEFINE_DMA_UNMAP_ADDR(mapping); | 322 | DEFINE_DMA_UNMAP_ADDR(mapping); |
316 | struct t4_swrqe *sw_rq; | 323 | struct t4_swrqe *sw_rq; |
317 | u64 udb; | 324 | u64 __iomem *udb; |
318 | size_t memsize; | 325 | size_t memsize; |
319 | u32 qid; | 326 | u32 qid; |
320 | u32 msn; | 327 | u32 msn; |
@@ -435,15 +442,67 @@ static inline u16 t4_sq_wq_size(struct t4_wq *wq) | |||
435 | return wq->sq.size * T4_SQ_NUM_SLOTS; | 442 | return wq->sq.size * T4_SQ_NUM_SLOTS; |
436 | } | 443 | } |
437 | 444 | ||
438 | static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc) | 445 | /* This function copies 64 byte coalesced work request to memory |
446 | * mapped BAR2 space. For coalesced WRs, the SGE fetches data | ||
447 | * from the FIFO instead of from Host. | ||
448 | */ | ||
449 | static inline void pio_copy(u64 __iomem *dst, u64 *src) | ||
450 | { | ||
451 | int count = 8; | ||
452 | |||
453 | while (count) { | ||
454 | writeq(*src, dst); | ||
455 | src++; | ||
456 | dst++; | ||
457 | count--; | ||
458 | } | ||
459 | } | ||
460 | |||
461 | static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, u8 t5, | ||
462 | union t4_wr *wqe) | ||
439 | { | 463 | { |
464 | |||
465 | /* Flush host queue memory writes. */ | ||
440 | wmb(); | 466 | wmb(); |
467 | if (t5) { | ||
468 | if (inc == 1 && wqe) { | ||
469 | PDBG("%s: WC wq->sq.pidx = %d\n", | ||
470 | __func__, wq->sq.pidx); | ||
471 | pio_copy(wq->sq.udb + 7, (void *)wqe); | ||
472 | } else { | ||
473 | PDBG("%s: DB wq->sq.pidx = %d\n", | ||
474 | __func__, wq->sq.pidx); | ||
475 | writel(PIDX_T5(inc), wq->sq.udb); | ||
476 | } | ||
477 | |||
478 | /* Flush user doorbell area writes. */ | ||
479 | wmb(); | ||
480 | return; | ||
481 | } | ||
441 | writel(QID(wq->sq.qid) | PIDX(inc), wq->db); | 482 | writel(QID(wq->sq.qid) | PIDX(inc), wq->db); |
442 | } | 483 | } |
443 | 484 | ||
444 | static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc) | 485 | static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc, u8 t5, |
486 | union t4_recv_wr *wqe) | ||
445 | { | 487 | { |
488 | |||
489 | /* Flush host queue memory writes. */ | ||
446 | wmb(); | 490 | wmb(); |
491 | if (t5) { | ||
492 | if (inc == 1 && wqe) { | ||
493 | PDBG("%s: WC wq->rq.pidx = %d\n", | ||
494 | __func__, wq->rq.pidx); | ||
495 | pio_copy(wq->rq.udb + 7, (void *)wqe); | ||
496 | } else { | ||
497 | PDBG("%s: DB wq->rq.pidx = %d\n", | ||
498 | __func__, wq->rq.pidx); | ||
499 | writel(PIDX_T5(inc), wq->rq.udb); | ||
500 | } | ||
501 | |||
502 | /* Flush user doorbell area writes. */ | ||
503 | wmb(); | ||
504 | return; | ||
505 | } | ||
447 | writel(QID(wq->rq.qid) | PIDX(inc), wq->db); | 506 | writel(QID(wq->rq.qid) | PIDX(inc), wq->db); |
448 | } | 507 | } |
449 | 508 | ||
@@ -568,6 +627,9 @@ static inline int t4_next_hw_cqe(struct t4_cq *cq, struct t4_cqe **cqe) | |||
568 | printk(KERN_ERR MOD "cq overflow cqid %u\n", cq->cqid); | 627 | printk(KERN_ERR MOD "cq overflow cqid %u\n", cq->cqid); |
569 | BUG_ON(1); | 628 | BUG_ON(1); |
570 | } else if (t4_valid_cqe(cq, &cq->queue[cq->cidx])) { | 629 | } else if (t4_valid_cqe(cq, &cq->queue[cq->cidx])) { |
630 | |||
631 | /* Ensure CQE is flushed to memory */ | ||
632 | rmb(); | ||
571 | *cqe = &cq->queue[cq->cidx]; | 633 | *cqe = &cq->queue[cq->cidx]; |
572 | ret = 0; | 634 | ret = 0; |
573 | } else | 635 | } else |