RDMA/cxgb4: Support on-chip SQs.
Subsystems (2)
PATCH v2 9/11 RDMA/cxgb4: Support on-chip SQs.
T4 support on-chip SQs to reduce latency. This patch adds support for this in iw_cxgb4.
Changes:
Manage ocqp memory like other adapter mem resources.
Allocate user mode SQs from ocqp mem if available.
Map ocqp mem to user process using write combining.
Map PCIE_MA_SYNC reg to user process.
Bump uverbs ABI.
---
drivers/infiniband/hw/cxgb4/device.c | 19 ++++++ drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 7 ++ drivers/infiniband/hw/cxgb4/provider.c | 28 ++++++--- drivers/infiniband/hw/cxgb4/qp.c | 98 +++++++++++++++++++++++++++----- drivers/infiniband/hw/cxgb4/resource.c | 56 ++++++++++++++++++ drivers/infiniband/hw/cxgb4/t4.h | 40 +++++++++++-- drivers/infiniband/hw/cxgb4/user.h | 7 ++ 7 files changed, 226 insertions(+), 29 deletions(-)
drivers/infiniband/hw/cxgb4/device.c +19 -0
@@ -364,7 +364,14 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev) printk(KERN_ERR MOD "error %d initializing rqt pool\n", err); goto err3; } + err =c4iw_ocqp_pool_create (rdev); +if (err) { + printk(KERN_ERR MOD "error %d initializing ocqp pool\n", err); + goto err4; + }return 0 ; +err4: +c4iw_rqtpool_destroy (rdev); err3:c4iw_pblpool_destroy (rdev); err2:
@@ -391,6 +398,7 @@ static void c4iw_remove(struct c4iw_dev *dev)idr_destroy (&dev->cqidr);idr_destroy (&dev->qpidr);idr_destroy (&dev->mmidr); +iounmap (dev->rdev.oc_mw_kva);ib_dealloc_device (&dev->ibdev); }
@@ -406,6 +414,17 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop) } devp->rdev.lldi = *infop; + devp->rdev.oc_mw_pa =pci_resource_start (devp->rdev.lldi.pdev,2 ) + + (pci_resource_len (devp->rdev.lldi.pdev,2 ) - +roundup_pow_of_two (devp->rdev.lldi.vr->ocq.size)); + devp->rdev.oc_mw_kva =ioremap_wc (devp->rdev.oc_mw_pa, + devp->rdev.lldi.vr->ocq.size); + + printk(KERN_INFO MOD "ocq memory: " +"hw_start 0x%x size %u mw_pa 0x%lx mw_kva %p\n" , + devp->rdev.lldi.vr->ocq.start, devp->rdev.lldi.vr->ocq.size, + devp->rdev.oc_mw_pa, devp->rdev.oc_mw_kva); +mutex_lock (&dev_mutex); ret =c4iw_rdev_open (&devp->rdev);
drivers/infiniband/hw/cxgb4/iw_cxgb4.h +7 -0
@@ -112,8 +112,11 @@ struct c4iw_rdev {struct c4iw_dev_ucontext uctx;struct gen_pool *pbl_pool;struct gen_pool *rqt_pool; +struct gen_pool *ocqp_pool;u32 flags;struct cxgb4_lld_info lldi; +unsigned long oc_mw_pa; +void __iomem *oc_mw_kva; };static inline int c4iw_fatal_error (struct c4iw_rdev *rdev)
@@ -675,8 +678,10 @@ int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid);int c4iw_init_ctrl_qp (struct c4iw_rdev *rdev);int c4iw_pblpool_create (struct c4iw_rdev *rdev);int c4iw_rqtpool_create (struct c4iw_rdev *rdev); +int c4iw_ocqp_pool_create (struct c4iw_rdev *rdev);void c4iw_pblpool_destroy (struct c4iw_rdev *rdev);void c4iw_rqtpool_destroy (struct c4iw_rdev *rdev); +void c4iw_ocqp_pool_destroy (struct c4iw_rdev *rdev);void c4iw_destroy_resource (struct c4iw_resource *rscp);int c4iw_destroy_ctrl_qp (struct c4iw_rdev *rdev);int c4iw_register_device (struct c4iw_dev *dev);
@@ -742,6 +747,8 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size);void c4iw_rqtpool_free (struct c4iw_rdev *rdev,u32 addr,int size);u32 c4iw_pblpool_alloc (struct c4iw_rdev *rdev,int size);void c4iw_pblpool_free (struct c4iw_rdev *rdev,u32 addr,int size); +u32 c4iw_ocqp_pool_alloc (struct c4iw_rdev *rdev,int size); +void c4iw_ocqp_pool_free (struct c4iw_rdev *rdev,u32 addr,int size);int c4iw_ofld_send (struct c4iw_rdev *rdev,struct sk_buff *skb);void c4iw_flush_hw_cq (struct t4_cq *cq);void c4iw_count_rcqes (struct t4_cq *cq,struct t4_wq *wq,int *count);
drivers/infiniband/hw/cxgb4/provider.c +19 -9
@@ -149,19 +149,28 @@ static int c4iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) addr = mm->addr;kfree (mm); -if ((addr >=pci_resource_start (rdev->lldi.pdev,2 )) && - (addr < (pci_resource_start (rdev->lldi.pdev,2 ) + -pci_resource_len (rdev->lldi.pdev,2 )))) { +if ((addr >=pci_resource_start (rdev->lldi.pdev,0 )) && + (addr < (pci_resource_start (rdev->lldi.pdev,0 ) + +pci_resource_len (rdev->lldi.pdev,0 )))) {/* -* Map T4 DB register. +* MA_SYNC register... */ -if (vma->vm_flags &VM_READ ) -return -EPERM ; - vma->vm_page_prot =pgprot_noncached (vma->vm_page_prot); - vma->vm_flags |=VM_DONTCOPY |VM_DONTEXPAND ; - vma->vm_flags &= ~VM_MAYREAD ; + ret =io_remap_pfn_range (vma, vma->vm_start, + addr >>PAGE_SHIFT , + len, vma->vm_page_prot); + }else if ((addr >=pci_resource_start (rdev->lldi.pdev,2 )) && + (addr < (pci_resource_start (rdev->lldi.pdev,2 ) + +pci_resource_len (rdev->lldi.pdev,2 )))) { + +/* +* Map user DB or OCQP memory... +*/ +if (addr >= rdev->oc_mw_pa) + vma->vm_page_prot =t4_pgprot_wc (vma->vm_page_prot); +else + vma->vm_page_prot =pgprot_noncached (vma->vm_page_prot); ret =io_remap_pfn_range (vma, vma->vm_start, addr >>PAGE_SHIFT , len, vma->vm_page_prot);
@@ -472,6 +481,7 @@ int c4iw_register_device(struct c4iw_dev *dev) dev->ibdev.post_send = c4iw_post_send; dev->ibdev.post_recv = c4iw_post_receive; dev->ibdev.get_protocol_stats = c4iw_get_mib; + dev->ibdev.uverbs_abi_ver =C4IW_UVERBS_ABI_VERSION ; dev->ibdev.iwcm =kmalloc (sizeof (struct iw_cm_verbs ),GFP_KERNEL );if (!dev->ibdev.iwcm)
drivers/infiniband/hw/cxgb4/qp.c +83 -15
165 lines not on this page · raw message
drivers/infiniband/hw/cxgb4/resource.c +56 -0
59 lines not on this page · raw message
drivers/infiniband/hw/cxgb4/t4.h +35 -5
@@ -52,6 +52,7 @@#define T4_STAG_UNSET 0xffffffff#define T4_FW_MAJ 0#define T4_EQ_STATUS_ENTRIES (L1_CACHE_BYTES > 64 ? 2 : 1) +#define A_PCIE_MA_SYNC 0x30b4struct t4_status_page {__be32 rsvd1;/* flit 0 - hw owns */
@@ -266,10 +267,36 @@ struct t4_swsqe {u16 idx; }; +static inline pgprot_t t4_pgprot_wc (pgprot_t prot) +{ +#if defined(__i386__) || defined(__x86_64__) +return pgprot_writecombine (prot); +#elif defined(CONFIG_PPC64 ) +return __pgprot ((pgprot_val (prot) | _PAGE_NO_CACHE) & + ~(pgprot_t )_PAGE_GUARDED); +#else +return pgprot_noncached (prot); +#endif +} + +static inline int t4_ocqp_supported (void ) +{ +#if defined(__i386__) || defined(__x86_64__) || defined(CONFIG_PPC64 ) +return 1 ; +#else +return 0 ; +#endif +} + +enum { +T4_SQ_ONCHIP = (1 <<0 ), +}; +struct t4_sq {union t4_wr *queue;dma_addr_t dma_addr;DEFINE_DMA_UNMAP_ADDR (mapping); +unsigned long phys_addr;struct t4_swsqe *sw_sq;struct t4_swsqe *oldest_read;u64 udb;
@@ -280,6 +307,7 @@ struct t4_sq {u16 cidx;u16 pidx;u16 wq_pidx; +u16 flags; };struct t4_swrqe {
@@ -350,6 +378,11 @@ static inline void t4_rq_consume(struct t4_wq *wq) wq->rq.cidx =0 ; } +static inline int t4_sq_onchip (struct t4_sq *sq) +{ +return sq->flags &T4_SQ_ONCHIP ; +} +static inline int t4_sq_empty (struct t4_wq *wq) {return wq->sq.in_use ==0 ;
@@ -396,30 +429,27 @@ static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc)static inline int t4_wq_in_error (struct t4_wq *wq) { -return wq->sq.queue[wq->sq.size].status.qp_err; +return wq->rq.queue[wq->rq.size].status.qp_err; }static inline void t4_set_wq_in_error (struct t4_wq *wq) { - wq->sq.queue[wq->sq.size].status.qp_err =1 ; wq->rq.queue[wq->rq.size].status.qp_err =1 ; }static inline void t4_disable_wq_db (struct t4_wq *wq) { - wq->sq.queue[wq->sq.size].status.db_off =1 ; wq->rq.queue[wq->rq.size].status.db_off =1 ; }static inline void t4_enable_wq_db (struct t4_wq *wq) { - wq->sq.queue[wq->sq.size].status.db_off =0 ; wq->rq.queue[wq->rq.size].status.db_off =0 ; }static inline int t4_wq_db_enabled (struct t4_wq *wq) { -return !wq->sq.queue[wq->sq.size].status.db_off; +return !wq->rq.queue[wq->rq.size].status.db_off; }struct t4_cq {
drivers/infiniband/hw/cxgb4/user.h +7 -0
@@ -50,7 +50,13 @@ struct c4iw_create_cq_resp {__u32 qid_mask; }; + +enum { +C4IW_QPF_ONCHIP = (1 <<0 ) +}; +struct c4iw_create_qp_resp { +__u64 ma_sync_key;__u64 sq_key;__u64 rq_key;__u64 sq_db_gts_key;
@@ -62,5 +68,6 @@ struct c4iw_create_qp_resp {__u32 sq_size;__u32 rq_size;__u32 qid_mask; + __u32 flags; };#endif
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 20100913162357.20948.28267.stgit-T4OLL4TyM9aNDNWfRnPdfg@public.gmane.org
As I said, I applied this, but I wonder:
Quoted 10 lines
drivers/infiniband/hw/cxgb4/t4.h +10
-0+static inline pgprot_t t4_pgprot_wc (pgprot_t prot) +{ +#if defined(__i386__) || defined(__x86_64__) +return pgprot_writecombine (prot); +#elif defined(CONFIG_PPC64 ) +return __pgprot ((pgprot_val (prot) | _PAGE_NO_CACHE) & + ~(pgprot_t )_PAGE_GUARDED); +#else +return pgprot_noncached (prot); +#endif
drivers/infiniband/hw/cxgb4/t4.h struct t4_swsqe { · line 289
Quoted 10 lines
drivers/infiniband/hw/cxgb4/t4.h +10
-0+} + +static inline int t4_ocqp_supported (void ) +{ +#if defined(__i386__) || defined(__x86_64__) || defined(CONFIG_PPC64 ) +return 1 ; +#else +return 0 ; +#endif +}
Is there any way to avoid this ifdef-ery? It seems at least the powerpc case should be wrapped up in an arch/powerpc version of pgprot_writecombine. Also doing this by hand as here leaves out for example ia64, which seems to have a definition of pgrprot_writecombine.
However I don't know what (if anything) we should do for the ocqp_supported test ...
- R.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 23 lines · Roland Dreier
As I said, I applied this, but I wonder:
Quoted 12 lines
+static inline
pgprot_tt4_pgprot_wc(pgprot_t prot)+{
+#ifdefined(__i386__)||defined(__x86_64__)
+ returnpgprot_writecombine(prot);
+#elifdefined(CONFIG_PPC64)
+ return __pgprot((pgprot_val(prot) | _PAGE_NO_CACHE)&
+ ~(pgprot_t)_PAGE_GUARDED);
+#else
+ returnpgprot_noncached(prot);
+#endif
+}
+Quoted 8 lines
+static inline int
t4_ocqp_supported(void)
+{
+#ifdefined(__i386__)||defined(__x86_64__)||defined(CONFIG_PPC64)
+ return 1;
+#else
+ return 0;
+#endif
+}
Quoted 6 lines
Is there any way to avoid this ifdef-ery? It seems at least the powerpc case should be wrapped up in an
arch/powerpcversion ofpgprot_writecombine. Also doing this by hand as here leaves out for example ia64, which seems to have a definition ofpgrprot_writecombine.
We would remove it I guess. I see that mlx4 assumes pgprot_writecombine() exists and works correctly across all platforms. See mlx4_ib_mmap().
Quoted 3 lines
However I don't know what (if anything) we should do for the
ocqp_supportedtest ...
If all platforms support pgprot_writecombine() correctly, then we don't need ocqp_supported().
Steve.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 3 lines
We would remove it I guess. I see that mlx4 assumes
pgprot_writecombine()exists and works correctly across all platforms. Seemlx4_ib_mmap().
It might be more accurate to say that mlx4 assumes pgprot_writecombine() is defined on all platforms. Any platform that hasn't defined it (or where the concept of write combining doesn't make sense) just falls back to defining it as pgprot_noncached().
Quoted 1 line
From a quick grep it seems that /arch/powerpc has no definition of
pgprot_writecombine() but your code seems to say that one could be given.
Quoted 2 lines
If all platforms support
pgprot_writecombine()correctly, then we don't needocqp_supported().
As I said, it's a bit tricky. All platforms get some definition of pgprot_writecombine(), but some platforms might define it as just giving a non-cached mapping, which might lead to dire performance (perhaps worse than just putting the SQ in host memory). I'm not sure what the best way to handle it is -- I suppose if you wanted to get fancy you could do a quick benchmark on startup (if such a thing is possible).
- R.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 4 lines · Roland Dreier
Quoted 3 lines
We would remove it I guess. I see that mlx4 assumes
pgprot_writecombine()exists and works correctly across all platforms. Seemlx4_ib_mmap().
Quoted 10 lines
It might be more accurate to say that mlx4 assumes
pgprot_writecombine()is defined on all platforms. Any platform that hasn't defined it (or where the concept of write combining doesn't make sense) just falls back to defining it aspgprot_noncached().Quoted 1 line
From a quick grep it seems that /arch/powerpc has no definition of
pgprot_writecombine()but your code seems to say that one could be given.
This came from the ofed version of mlx4. I assume it works. :)
Quoted 11 lines
Quoted 2 lines
If all platforms support
pgprot_writecombine()correctly, then we don't needocqp_supported().As I said, it's a bit tricky. All platforms get some definition of
pgprot_writecombine(), but some platforms might define it as just giving a non-cached mapping, which might lead to dire performance (perhaps worse than just putting the SQ in host memory). I'm not sure what the best way to handle it is -- I suppose if you wanted to get fancy you could do a quick benchmark on startup (if such a thing is possible).
oof. I don't want to get that fancy. :)
Seems like what I need is an arch-specific function that indicates if write combining is supported or not. Or leave the code as-is.
Steve.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html