IB/mthca: map MPT/MTT context in mem-free mode
Subsystems (2)
PATCH 1/27 IB/mthca: map MPT/MTT context in mem-free mode
In mem-free mode, when allocating memory regions, make sure that the HCA has context memory mapped to cover the virtual space used for the MPT and MTTs being used.
drivers/infiniband/hw/mthca/mthca_main.c +1 -1
@@ -390,7 +390,7 @@ } mdev->mr_table.mtt_table =mthca_alloc_icm_table (mdev, init_hca->mtt_base, - init_hca->mtt_seg_sz, + dev_lim->mtt_seg_sz, mdev->limits.num_mtt_segs, mdev->limits.reserved_mtts,1 );if (!mdev->mr_table.mtt_table) {
drivers/infiniband/hw/mthca/mthca_memfree.c +32 -0
@@ -192,6 +192,38 @@up (&table->mutex); } +int mthca_table_get_range (struct mthca_dev *dev,struct mthca_icm_table *table, +int start,int end) +{ +int inc =MTHCA_TABLE_CHUNK_SIZE / table->obj_size; +int i, err; + +for (i = start; i <= end; i += inc) { + err =mthca_table_get (dev, table, i); +if (err) + goto fail; + } + +return 0 ; + +fail: +while (i > start) { + i -= inc; +mthca_table_put (dev, table, i); + } + +return err; +} + +void mthca_table_put_range (struct mthca_dev *dev,struct mthca_icm_table *table, +int start,int end) +{ +int i; + +for (i = start; i <= end; i +=MTHCA_TABLE_CHUNK_SIZE / table->obj_size) +mthca_table_put (dev, table, i); +} + struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev, u64 virt, int obj_size, int nobj, int reserved,
drivers/infiniband/hw/mthca/mthca_memfree.h +4 -0
@@ -85,6 +85,10 @@void mthca_free_icm_table (struct mthca_dev *dev,struct mthca_icm_table *table);int mthca_table_get (struct mthca_dev *dev,struct mthca_icm_table *table,int obj);void mthca_table_put (struct mthca_dev *dev,struct mthca_icm_table *table,int obj); +int mthca_table_get_range (struct mthca_dev *dev,struct mthca_icm_table *table, +int start,int end); +void mthca_table_put_range (struct mthca_dev *dev,struct mthca_icm_table *table, +int start,int end);static inline void mthca_icm_first (struct mthca_icm *icm,struct mthca_icm_iter *iter)
drivers/infiniband/hw/mthca/mthca_mr.c +68 -11
160 lines not on this page · raw message
PATCH 2/27 IB/mthca: fill in more device query fields
Implement more of the device_query method in mthca.
drivers/infiniband/hw/mthca/mthca_cmd.c +2 -0
@@ -987,6 +987,8 @@if (dev->hca_type ==ARBEL_NATIVE ) {MTHCA_GET (field, outbox,QUERY_DEV_LIM_RSZ_SRQ_OFFSET ); dev_lim->hca.arbel.resize_srq = field &1 ; +MTHCA_GET (field, outbox,QUERY_DEV_LIM_MAX_SG_RQ_OFFSET ); + dev_lim->max_sg =min_t (int, field, dev_lim->max_sg);MTHCA_GET (size, outbox,QUERY_DEV_LIM_MTT_ENTRY_SZ_OFFSET ); dev_lim->mtt_seg_sz = size;MTHCA_GET (size, outbox,QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET );
drivers/infiniband/hw/mthca/mthca_provider.c +18 -4
@@ -52,6 +52,8 @@if (!in_mad || !out_mad) goto out; +memset (props,0 ,sizeof props); + props->fw_ver = mdev->fw_ver;memset (in_mad,0 ,sizeof *in_mad);
@@ -71,14 +73,26 @@ goto out; } - props->device_cap_flags = mdev->device_cap_flags; - props->vendor_id =be32_to_cpup ((u32 *) (out_mad->data +36 )) & + props->device_cap_flags = mdev->device_cap_flags; + props->vendor_id =be32_to_cpup ((u32 *) (out_mad->data +36 )) &0xffffff ; - props->vendor_part_id =be16_to_cpup ((u16 *) (out_mad->data +30 )); - props->hw_ver =be16_to_cpup ((u16 *) (out_mad->data +32 )); + props->vendor_part_id =be16_to_cpup ((u16 *) (out_mad->data +30 )); + props->hw_ver =be16_to_cpup ((u16 *) (out_mad->data +32 ));memcpy (&props->sys_image_guid, out_mad->data +4 ,8 );memcpy (&props->node_guid, out_mad->data +12 ,8 ); + props->max_mr_size = ~0ull ; + props->max_qp = mdev->limits.num_qps - mdev->limits.reserved_qps; + props->max_qp_wr =0xffff ; + props->max_sge = mdev->limits.max_sg; + props->max_cq = mdev->limits.num_cqs - mdev->limits.reserved_cqs; + props->max_cqe =0xffff ; + props->max_mr = mdev->limits.num_mpts - mdev->limits.reserved_mrws; + props->max_pd = mdev->limits.num_pds - mdev->limits.reserved_pds; + props->max_qp_rd_atom =1 << mdev->qp_table.rdb_shift; + props->max_qp_init_rd_atom =1 << mdev->qp_table.rdb_shift; + props->local_ca_ack_delay = mdev->limits.local_ca_ack_delay; + err =0 ; out:kfree (in_mad);
PATCH 3/27 IB/mthca: fix calculation of RDB shift
Fix calculation of rdb_shift by using original number of QPs, not their slot in profile[] (which will be rearranged when we sort it).
drivers/infiniband/hw/mthca/mthca_profile.c +1 -2
@@ -208,8 +208,7 @@break ;case MTHCA_RES_RDB :for (dev->qp_table.rdb_shift =0 ; - profile[MTHCA_RES_QP ].num << dev->qp_table.rdb_shift < - profile[i].num; + request->num_qp << dev->qp_table.rdb_shift < profile[i].num; ++dev->qp_table.rdb_shift) ;/* nothing */ dev->qp_table.rdb_base = (u32 ) profile[i].start;
PATCH 4/27 IB/mthca: fix posting sends with immediate data
When posting a work request with immediate data, put the immediate data in the immediate data field of the hardware's work request (rather than overwriting the flags field).
drivers/infiniband/hw/mthca/mthca_qp.c +2 -2
@@ -1465,7 +1465,7 @@cpu_to_be32 (1 );if (wr->opcode ==IB_WR_SEND_WITH_IMM || wr->opcode ==IB_WR_RDMA_WRITE_WITH_IMM ) - ((struct mthca_next_seg *) wqe)->flags = wr->imm_data; + ((struct mthca_next_seg *) wqe)->imm = wr->imm_data; wqe +=sizeof (struct mthca_next_seg ); size =sizeof (struct mthca_next_seg ) /16 ;
@@ -1769,7 +1769,7 @@cpu_to_be32 (1 );if (wr->opcode ==IB_WR_SEND_WITH_IMM || wr->opcode ==IB_WR_RDMA_WRITE_WITH_IMM ) - ((struct mthca_next_seg *) wqe)->flags = wr->imm_data; + ((struct mthca_next_seg *) wqe)->imm = wr->imm_data; wqe +=sizeof (struct mthca_next_seg ); size =sizeof (struct mthca_next_seg ) /16 ;
PATCH 5/27 IB/mthca: allow unaligned memory regions
From: Michael S. Tsirkin <[email protected]>
The first buffer of a memory region is not required to be page-aligned, so don't return an error if it's not.
drivers/infiniband/hw/mthca/mthca_provider.c +1 -1
@@ -494,7 +494,7 @@ mask =0 ; total_size =0 ;for (i =0 ; i < num_phys_buf; ++i) { -if (buffer_list[i].addr & ~PAGE_MASK ) +if (i !=0 && buffer_list[i].addr & ~PAGE_MASK )return ERR_PTR (-EINVAL );if (i !=0 && i != num_phys_buf -1 && (buffer_list[i].size & ~PAGE_MASK ))
PATCH 6/27 IB/mthca: allocate correct number of doorbell pages
Doorbell record pages are allocated in HCA page size chunks (always 4096 bytes), so we need to divide by 4096 and not PAGE_SIZE when figuring out how many pages we'll need space for.
drivers/infiniband/hw/mthca/mthca_memfree.c +1 -1
@@ -446,7 +446,7 @@init_MUTEX (&dev->db_tab->mutex); - dev->db_tab->npages = dev->uar_table.uarc_size /PAGE_SIZE ; + dev->db_tab->npages = dev->uar_table.uarc_size /4096 ; dev->db_tab->max_group1 =0 ; dev->db_tab->min_group2 = dev->db_tab->npages -1 ;
PATCH 7/27 IB/mthca: clean up mthca_dereg_mr()
It's cleaner to kfree mthca_mr, and not rely on the fact that ib_mr is the first field in mthca_mr.
drivers/infiniband/hw/mthca/mthca_provider.c +3 -2
@@ -568,8 +568,9 @@static int mthca_dereg_mr (struct ib_mr *mr) { -mthca_free_mr (to_mdev (mr->device),to_mmr (mr)); -kfree (mr); +struct mthca_mr *mmr =to_mmr (mr); +mthca_free_mr (to_mdev (mr->device), mmr); +kfree (mmr);return 0 ; }
PATCH 8/27 IB/mthca: fix MR allocation error path
From: Michael S. Tsirkin <[email protected]>
Fix error handling in MR allocation for mem-free mode:mthca_free must get an MR index, not a key.
drivers/infiniband/hw/mthca/mthca_mr.c +2 -2
@@ -231,7 +231,7 @@mthca_table_put (dev, dev->mr_table.mpt_table, key); err_out_mpt_free: -mthca_free (&dev->mr_table.mpt_alloc, mr->ibmr.lkey); +mthca_free (&dev->mr_table.mpt_alloc, key);kfree (mailbox);return err; }
@@ -368,7 +368,7 @@mthca_table_put (dev, dev->mr_table.mpt_table, key); err_out_mpt_free: -mthca_free (&dev->mr_table.mpt_alloc, mr->ibmr.lkey); +mthca_free (&dev->mr_table.mpt_alloc, key);return err; }
PATCH 9/27 IB/mthca: release mutex on doorbell alloc error path
Release mutex on error return path from mthca_alloc_db().
drivers/infiniband/hw/mthca/mthca_memfree.c +2 -1
@@ -337,7 +337,8 @@break ;default : -return -1 ; + ret = -EINVAL ; + goto out; }for (i = start; i != end; i += dir)
PATCH 10/27 IB/mthca: print assigned IRQ when interrupt test fails
Print IRQ number when NOP command interrupt test fails to help debugging.
drivers/infiniband/hw/mthca/mthca_main.c +4 -1
@@ -672,7 +672,10 @@ err =mthca_NOP (dev, &status);if (err || status) { -mthca_err (dev,"NOP command failed to generate interrupt, aborting.\n" ); +mthca_err (dev,"NOP command failed to generate interrupt (IRQ %d), aborting.\n" , + dev->mthca_flags &MTHCA_FLAG_MSI_X ? + dev->eq_table.eq[MTHCA_EQ_CMD ].msi_x_vector : + dev->pdev->irq);if (dev->mthca_flags & (MTHCA_FLAG_MSI |MTHCA_FLAG_MSI_X ))mthca_err (dev,"Try again with MSI/MSI-X disabled.\n" );else
PATCH 11/27 IB/mthca: only free doorbell records in mem-free mode
On error path, only free doorbell records if we're in mem-free mode.
drivers/infiniband/hw/mthca/mthca_cq.c +4 -2
@@ -817,10 +817,12 @@ err_out_mailbox:kfree (mailbox); -mthca_free_db (dev,MTHCA_DB_TYPE_CQ_ARM , cq->arm_db_index); +if (dev->hca_type ==ARBEL_NATIVE ) +mthca_free_db (dev,MTHCA_DB_TYPE_CQ_ARM , cq->arm_db_index); err_out_ci: -mthca_free_db (dev,MTHCA_DB_TYPE_CQ_SET_CI , cq->set_ci_db_index); +if (dev->hca_type ==ARBEL_NATIVE ) +mthca_free_db (dev,MTHCA_DB_TYPE_CQ_SET_CI , cq->set_ci_db_index); err_out_icm:mthca_table_put (dev, dev->cq_table.table, cq->cqn);
PATCH 12/27 IB/mthca: fix format of CQ number for CQ events
CQ numbers are only 24 bits, so only print 6 hex digits and mask off reserved part when reporting a CQ event.
drivers/infiniband/hw/mthca/mthca_eq.c +2 -2
@@ -344,10 +344,10 @@break ;case MTHCA_EVENT_TYPE_CQ_ERROR : -mthca_warn (dev,"CQ %s on CQN %08x\n" , +mthca_warn (dev,"CQ %s on CQN %06x\n" , eqe->event.cq_err.syndrome ==1 ?"overrun" :"access violation" , -be32_to_cpu (eqe->event.cq_err.cqn)); +be32_to_cpu (eqe->event.cq_err.cqn) &0xffffff );break ;case MTHCA_EVENT_TYPE_EQ_OVERFLOW :
PATCH 13/27 IB/mthca: implement RDMA/atomic operations for mem-free mode
Add code to support RDMA and atomic send work requests in mem-free mode.
drivers/infiniband/hw/mthca/mthca_qp.c +47 -0
@@ -1775,6 +1775,53 @@ size =sizeof (struct mthca_next_seg ) /16 ;switch (qp->transport) { +case RC : +switch (wr->opcode) { +case IB_WR_ATOMIC_CMP_AND_SWP : +case IB_WR_ATOMIC_FETCH_AND_ADD : + ((struct mthca_raddr_seg *) wqe)->raddr = +cpu_to_be64 (wr->wr.atomic.remote_addr); + ((struct mthca_raddr_seg *) wqe)->rkey = +cpu_to_be32 (wr->wr.atomic.rkey); + ((struct mthca_raddr_seg *) wqe)->reserved =0 ; + + wqe +=sizeof (struct mthca_raddr_seg ); + +if (wr->opcode ==IB_WR_ATOMIC_CMP_AND_SWP ) { + ((struct mthca_atomic_seg *) wqe)->swap_add = +cpu_to_be64 (wr->wr.atomic.swap); + ((struct mthca_atomic_seg *) wqe)->compare = +cpu_to_be64 (wr->wr.atomic.compare_add); + }else { + ((struct mthca_atomic_seg *) wqe)->swap_add = +cpu_to_be64 (wr->wr.atomic.compare_add); + ((struct mthca_atomic_seg *) wqe)->compare =0 ; + } + + wqe +=sizeof (struct mthca_atomic_seg ); + size +=sizeof (struct mthca_raddr_seg ) /16 + +sizeof (struct mthca_atomic_seg ); +break ; + +case IB_WR_RDMA_WRITE : +case IB_WR_RDMA_WRITE_WITH_IMM : +case IB_WR_RDMA_READ : + ((struct mthca_raddr_seg *) wqe)->raddr = +cpu_to_be64 (wr->wr.rdma.remote_addr); + ((struct mthca_raddr_seg *) wqe)->rkey = +cpu_to_be32 (wr->wr.rdma.rkey); + ((struct mthca_raddr_seg *) wqe)->reserved =0 ; + wqe +=sizeof (struct mthca_raddr_seg ); + size +=sizeof (struct mthca_raddr_seg ) /16 ; +break ; + +default : +/* No extra segments required for sends */ +break ; + } + +break ; +case UD :memcpy (((struct mthca_arbel_ud_seg *) wqe)->av,to_mah (wr->wr.ud.ah)->av,MTHCA_AV_SIZE );
PATCH 14/27 IB/mthca: fix MTT allocation in mem-free mode
Fix bug in MTT allocation in mem-free mode.
I misunderstood the MTT size value returned by the firmware -- it is really the size of a single MTT entry, since mem-free mode does not segment the MTT as the original firmware did. This meant that our MTT addresses ended up being off by a factor of 8. This meant that our MTT allocations might overlap, and so we could overwrite and corrupt earlier memory regions when writing new MTT entries.
We fix this by always using our 64-byte MTT segment size. This allows some simplification of the code as well, since there's no reason to put the MTT segment size in a variable -- we can always use our enum value directly.
drivers/infiniband/hw/mthca/mthca_cmd.c +0 -2
@@ -990,7 +990,6 @@MTHCA_GET (field, outbox,QUERY_DEV_LIM_MAX_SG_RQ_OFFSET ); dev_lim->max_sg =min_t (int, field, dev_lim->max_sg);MTHCA_GET (size, outbox,QUERY_DEV_LIM_MTT_ENTRY_SZ_OFFSET ); - dev_lim->mtt_seg_sz = size;MTHCA_GET (size, outbox,QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET ); dev_lim->mpt_entry_sz = size;MTHCA_GET (field, outbox,QUERY_DEV_LIM_PBL_SZ_OFFSET );
@@ -1018,7 +1017,6 @@ }else {MTHCA_GET (field, outbox,QUERY_DEV_LIM_MAX_AV_OFFSET ); dev_lim->hca.tavor.max_avs =1 << (field &0x3f ); - dev_lim->mtt_seg_sz =MTHCA_MTT_SEG_SIZE ; dev_lim->mpt_entry_sz =MTHCA_MPT_ENTRY_SIZE ; }
drivers/infiniband/hw/mthca/mthca_cmd.h +0 -1
@@ -162,7 +162,6 @@int cqc_entry_sz;int srq_entry_sz;int uar_scratch_entry_sz; -int mtt_seg_sz;int mpt_entry_sz; union { struct {
drivers/infiniband/hw/mthca/mthca_dev.h +0 -1
@@ -121,7 +121,6 @@int reserved_eqs;int num_mpts;int num_mtt_segs; -int mtt_seg_size;int reserved_mtts;int reserved_mrws;int reserved_uars;
drivers/infiniband/hw/mthca/mthca_main.c +1 -1
@@ -390,7 +390,7 @@ } mdev->mr_table.mtt_table =mthca_alloc_icm_table (mdev, init_hca->mtt_base, - dev_lim->mtt_seg_sz, +MTHCA_MTT_SEG_SIZE , mdev->limits.num_mtt_segs, mdev->limits.reserved_mtts,1 );if (!mdev->mr_table.mtt_table) {
drivers/infiniband/hw/mthca/mthca_mr.c +3 -3
@@ -263,7 +263,7 @@ goto err_out_mpt_free; } -for (i = dev->limits.mtt_seg_size /8 , mr->order =0 ; +for (i =MTHCA_MTT_SEG_SIZE /8 , mr->order =0 ; i < list_len; i <<=1 , ++mr->order) ;/* nothing */
@@ -286,7 +286,7 @@ mtt_entry =MAILBOX_ALIGN (mailbox); mtt_entry[0 ] =cpu_to_be64 (dev->mr_table.mtt_base + - mr->first_seg * dev->limits.mtt_seg_size); + mr->first_seg *MTHCA_MTT_SEG_SIZE ); mtt_entry[1 ] =0 ;for (i =0 ; i < list_len; ++i) mtt_entry[i + 2] = cpu_to_be64(buffer_list[i] |
@@ -330,7 +330,7 @@memset (&mpt_entry->lkey,0 ,sizeof *mpt_entry - offsetof(struct mthca_mpt_entry , lkey)); mpt_entry->mtt_seg =cpu_to_be64 (dev->mr_table.mtt_base + - mr->first_seg * dev->limits.mtt_seg_size); + mr->first_seg *MTHCA_MTT_SEG_SIZE );if (0 ) {mthca_dbg (dev,"Dumping MPT entry %08x:\n" , mr->ibmr.lkey);
drivers/infiniband/hw/mthca/mthca_profile.c +2 -3
@@ -95,7 +95,7 @@ profile[MTHCA_RES_RDB ].size =MTHCA_RDB_ENTRY_SIZE ; profile[MTHCA_RES_MCG ].size =MTHCA_MGM_ENTRY_SIZE ; profile[MTHCA_RES_MPT ].size = dev_lim->mpt_entry_sz; - profile[MTHCA_RES_MTT ].size = dev_lim->mtt_seg_sz; + profile[MTHCA_RES_MTT ].size =MTHCA_MTT_SEG_SIZE ; profile[MTHCA_RES_UAR ].size = dev_lim->uar_scratch_entry_sz; profile[MTHCA_RES_UDAV ].size =MTHCA_AV_SIZE ; profile[MTHCA_RES_UARC ].size = request->uarc_size;
@@ -229,10 +229,9 @@break ;case MTHCA_RES_MTT : dev->limits.num_mtt_segs = profile[i].num; - dev->limits.mtt_seg_size = dev_lim->mtt_seg_sz; dev->mr_table.mtt_base = profile[i].start; init_hca->mtt_base = profile[i].start; - init_hca->mtt_seg_sz =ffs (dev_lim->mtt_seg_sz) -7 ; + init_hca->mtt_seg_sz =ffs (MTHCA_MTT_SEG_SIZE ) -7 ;break ;case MTHCA_RES_UAR : dev->limits.num_uars = profile[i].num;
PATCH 15/27 IB/mthca: fill in opcode field for send completions
From: Michael S. Tsirkin <[email protected]>
Fill in missing fields in send completions.
drivers/infiniband/hw/mthca/mthca_cq.c +35 -1
@@ -473,7 +473,41 @@ }if (is_send) { - entry->opcode =IB_WC_SEND ;/* XXX */ + entry->wc_flags =0 ; +switch (cqe->opcode) { +case MTHCA_OPCODE_RDMA_WRITE : + entry->opcode =IB_WC_RDMA_WRITE ; +break ; +case MTHCA_OPCODE_RDMA_WRITE_IMM : + entry->opcode =IB_WC_RDMA_WRITE ; + entry->wc_flags |=IB_WC_WITH_IMM ; +break ; +case MTHCA_OPCODE_SEND : + entry->opcode =IB_WC_SEND ; +break ; +case MTHCA_OPCODE_SEND_IMM : + entry->opcode =IB_WC_SEND ; + entry->wc_flags |=IB_WC_WITH_IMM ; +break ; +case MTHCA_OPCODE_RDMA_READ : + entry->opcode =IB_WC_RDMA_READ ; + entry->byte_len =be32_to_cpu (cqe->byte_cnt); +break ; +case MTHCA_OPCODE_ATOMIC_CS : + entry->opcode =IB_WC_COMP_SWAP ; + entry->byte_len =be32_to_cpu (cqe->byte_cnt); +break ; +case MTHCA_OPCODE_ATOMIC_FA : + entry->opcode =IB_WC_FETCH_ADD ; + entry->byte_len =be32_to_cpu (cqe->byte_cnt); +break ; +case MTHCA_OPCODE_BIND_MW : + entry->opcode =IB_WC_BIND_MW ; +break ; +default : + entry->opcode =MTHCA_OPCODE_INVALID ; +break ; + } }else { entry->byte_len =be32_to_cpu (cqe->byte_cnt);switch (cqe->opcode &0x1f ) {
drivers/infiniband/hw/mthca/mthca_dev.h +13 -0
@@ -88,6 +88,19 @@MTHCA_NUM_EQ }; +enum { +MTHCA_OPCODE_NOP =0x00 , +MTHCA_OPCODE_RDMA_WRITE =0x08 , +MTHCA_OPCODE_RDMA_WRITE_IMM =0x09 , +MTHCA_OPCODE_SEND =0x0a , +MTHCA_OPCODE_SEND_IMM =0x0b , +MTHCA_OPCODE_RDMA_READ =0x10 , +MTHCA_OPCODE_ATOMIC_CS =0x11 , +MTHCA_OPCODE_ATOMIC_FA =0x12 , +MTHCA_OPCODE_BIND_MW =0x18 , +MTHCA_OPCODE_INVALID =0xff +}; +struct mthca_cmd {int use_events;struct semaphore hcr_sem;
drivers/infiniband/hw/mthca/mthca_qp.c +0 -13
@@ -171,19 +171,6 @@ };enum { -MTHCA_OPCODE_NOP =0x00 , -MTHCA_OPCODE_RDMA_WRITE =0x08 , -MTHCA_OPCODE_RDMA_WRITE_IMM =0x09 , -MTHCA_OPCODE_SEND =0x0a , -MTHCA_OPCODE_SEND_IMM =0x0b , -MTHCA_OPCODE_RDMA_READ =0x10 , -MTHCA_OPCODE_ATOMIC_CS =0x11 , -MTHCA_OPCODE_ATOMIC_FA =0x12 , -MTHCA_OPCODE_BIND_MW =0x18 , -MTHCA_OPCODE_INVALID =0xff -}; - -enum {MTHCA_NEXT_DBD =1 <<7 ,MTHCA_NEXT_FENCE =1 <<6 ,MTHCA_NEXT_CQ_UPDATE =1 <<3 ,
PATCH 16/27 IB/mthca: allow address handle creation in interrupt context
Make address handle verbs usable from interrupt context.
drivers/infiniband/hw/mthca/mthca_av.c +3 -3
@@ -63,7 +63,7 @@ ah->type =MTHCA_AH_PCI_POOL ;if (dev->hca_type ==ARBEL_NATIVE ) { - ah->av =kmalloc (sizeof *ah->av,GFP_KERNEL ); + ah->av =kmalloc (sizeof *ah->av,GFP_ATOMIC );if (!ah->av)return -ENOMEM ;
@@ -77,7 +77,7 @@if (index ==-1 ) goto on_hca_fail; - av =kmalloc (sizeof *av,GFP_KERNEL ); + av =kmalloc (sizeof *av,GFP_ATOMIC );if (!av) goto on_hca_fail;
@@ -89,7 +89,7 @@ on_hca_fail:if (ah->type ==MTHCA_AH_PCI_POOL ) { ah->av =pci_pool_alloc (dev->av_table.pool, -SLAB_KERNEL , &ah->avdma); +SLAB_ATOMIC , &ah->avdma);if (!ah->av)return -ENOMEM ;
drivers/infiniband/hw/mthca/mthca_provider.c +1 -1
@@ -315,7 +315,7 @@int err;struct mthca_ah *ah; - ah =kmalloc (sizeof *ah,GFP_KERNEL ); + ah =kmalloc (sizeof *ah,GFP_ATOMIC );if (!ah)return ERR_PTR (-ENOMEM );
PATCH 17/27 IB/mthca: encapsulate MTT buddy allocator
From: Michael S. Tsirkin <[email protected]>
Encapsulate the buddy allocator used for MTT segments. This cleans up the code and also gets us ready to add FMR support.
drivers/infiniband/hw/mthca/mthca_dev.h +7 -2
@@ -170,10 +170,15 @@struct mthca_alloc alloc; }; +struct mthca_buddy { +unsigned long **bits; +int max_order; +spinlock_t lock; +}; +struct mthca_mr_table {struct mthca_alloc mpt_alloc; -int max_mtt_order; -unsigned long **mtt_buddy; +struct mthca_buddy mtt_buddy;u64 mtt_base;struct mthca_icm_table *mtt_table;struct mthca_icm_table *mpt_table;
drivers/infiniband/hw/mthca/mthca_mr.c +87 -71
255 lines not on this page · raw message
PATCH 18/27 IB/mthca: add SYNC_TPT firmware command
From: Michael S. Tsirkin <[email protected]>
Add code for SYNC_TPT firmware command, which will be used by FMR implementation.
drivers/infiniband/hw/mthca/mthca_cmd.c +5 -0
@@ -1404,6 +1404,11 @@return err; } +int mthca_SYNC_TPT (struct mthca_dev *dev,u8 *status) +{ +return mthca_cmd (dev,0 ,0 ,0 ,CMD_SYNC_TPT ,CMD_TIME_CLASS_B , status); +} +int mthca_MAP_EQ (struct mthca_dev *dev,u64 event_mask,int unmap,int eq_num,u8 *status) {
drivers/infiniband/hw/mthca/mthca_cmd.h +1 -0
@@ -276,6 +276,7 @@ int mpt_index, u8 *status);int mthca_WRITE_MTT (struct mthca_dev *dev,u64 *mtt_entry,int num_mtt,u8 *status); +int mthca_SYNC_TPT (struct mthca_dev *dev,u8 *status);int mthca_MAP_EQ (struct mthca_dev *dev,u64 event_mask,int unmap,int eq_num,u8 *status); int mthca_SW2HW_EQ(struct mthca_dev *dev, void *eq_context,
PATCH 19/27 IB/mthca: add mthca_write64_raw() for writing to MTT table directly
From: Michael S. Tsirkin <[email protected]>
Add mthca_write64_raw() function, which will be used to write FMR entries that are in ioremapped PCI memory.
drivers/infiniband/hw/mthca/mthca_doorbell.h +11 -0
@@ -51,6 +51,11 @@#define MTHCA_INIT_DOORBELL_LOCK (ptr) do { } while (0)#define MTHCA_GET_DOORBELL_LOCK (ptr) (NULL) +static inline void mthca_write64_raw (__be64 val,void __iomem *dest) +{ +__raw_writeq ((__force u64 ) val, dest); +} +static inline void mthca_write64 (u32 val[2 ],void __iomem *dest,spinlock_t *doorbell_lock) {
@@ -74,6 +79,12 @@#define MTHCA_INIT_DOORBELL_LOCK (ptr) spin_lock_init(ptr)#define MTHCA_GET_DOORBELL_LOCK (ptr) (ptr) +static inline void mthca_write64_raw (__be64 val,void __iomem *dest) +{ +__raw_writel (((__force u32 *) &val)[0 ], dest); +__raw_writel (((__force u32 *) &val)[1 ], dest +4 ); +} +static inline void mthca_write64 (u32 val[2 ],void __iomem *dest,spinlock_t *doorbell_lock) {
PATCH 20/27 IB/mthca: add mthca_table_find() function
From: Michael S. Tsirkin <[email protected]>
Add mthca_table_find() function, which returns the lowmem address of an entry in a mem-free HCA's context tables. This will be used by the FMR implementation.
drivers/infiniband/hw/mthca/mthca_memfree.c +34 -0
@@ -192,6 +192,40 @@up (&table->mutex); } +void *mthca_table_find (struct mthca_icm_table *table,int obj) +{ +int idx, offset, i; +struct mthca_icm_chunk *chunk; +struct mthca_icm *icm; +struct page *page =NULL ; + +if (!table->lowmem) +return NULL ; + +down (&table->mutex); + + idx = (obj & (table->num_obj -1 )) * table->obj_size; + icm = table->icm[idx /MTHCA_TABLE_CHUNK_SIZE ]; + offset = idx %MTHCA_TABLE_CHUNK_SIZE ; + +if (!icm) + goto out; + +list_for_each_entry (chunk, &icm->chunk_list, list) { +for (i =0 ; i < chunk->npages; ++i) { +if (chunk->mem[i].length >= offset) { + page = chunk->mem[i].page; +break ; + } + offset -= chunk->mem[i].length; + } + } + +out: +up (&table->mutex); +return page ?lowmem_page_address (page) + offset :NULL ; +} +int mthca_table_get_range (struct mthca_dev *dev,struct mthca_icm_table *table,int start,int end) {
drivers/infiniband/hw/mthca/mthca_memfree.h +1 -0
@@ -85,6 +85,7 @@void mthca_free_icm_table (struct mthca_dev *dev,struct mthca_icm_table *table);int mthca_table_get (struct mthca_dev *dev,struct mthca_icm_table *table,int obj);void mthca_table_put (struct mthca_dev *dev,struct mthca_icm_table *table,int obj); +void *mthca_table_find (struct mthca_icm_table *table,int obj);int mthca_table_get_range (struct mthca_dev *dev,struct mthca_icm_table *table,int start,int end); void mthca_table_put_range(struct mthca_dev *dev, struct mthca_icm_table *table,
PATCH 21/27 IB/mthca: split MR key munging routines
From: Michael S. Tsirkin <[email protected]>
Split Tavor and Arbel/mem-free index<->hw key munging routines, so that FMR implementation can call correct implementation without testing HCA type (which it already knows).
drivers/infiniband/hw/mthca/mthca_mr.c +24 -4
@@ -198,20 +198,40 @@ seg + (1 << order) - 1); } +static inline u32 tavor_hw_index_to_key (u32 ind) +{ +return ind; +} + +static inline u32 tavor_key_to_hw_index (u32 key) +{ +return key; +} + +static inline u32 arbel_hw_index_to_key (u32 ind) +{ +return (ind >>24 ) | (ind <<8 ); +} + +static inline u32 arbel_key_to_hw_index (u32 key) +{ +return (key <<24 ) | (key >>8 ); +} +static inline u32 hw_index_to_key (struct mthca_dev *dev,u32 ind) {if (dev->hca_type ==ARBEL_NATIVE ) -return (ind >>24 ) | (ind <<8 ); +return arbel_hw_index_to_key (ind);else -return ind; +return tavor_hw_index_to_key (ind); }static inline u32 key_to_hw_index (struct mthca_dev *dev,u32 key) {if (dev->hca_type ==ARBEL_NATIVE ) -return (key <<24 ) | (key >>8 ); +return arbel_key_to_hw_index (key);else -return key; +return tavor_key_to_hw_index (key); } int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
PATCH 22/27 IB/mthca: add fast memory region implementation
From: Michael S. Tsirkin <[email protected]>
Implement fast memory regions (FMRs), where the driver writes directly into the HCA's translation tables rather than requiring a firmware command. For Tavor, MTTs for FMR are separate from regular MTTs, and are reserved at driver initialization. This is done to limit the amount of virtual memory needed to map the MTTs. For Arbel, there's no such limitation, and all MTTs and MPTs may be used for FMR or for regular MR.
drivers/infiniband/hw/mthca/mthca_dev.h +22 -3
@@ -61,7 +61,8 @@MTHCA_FLAG_SRQ =1 <<2 ,MTHCA_FLAG_MSI =1 <<3 ,MTHCA_FLAG_MSI_X =1 <<4 , -MTHCA_FLAG_NO_LAM =1 <<5 +MTHCA_FLAG_NO_LAM =1 <<5 , +MTHCA_FLAG_FMR =1 <<6 }; enum {
@@ -134,6 +135,7 @@int reserved_eqs;int num_mpts;int num_mtt_segs; +int fmr_reserved_mtts;int reserved_mtts;int reserved_mrws;int reserved_uars;
@@ -178,10 +180,17 @@struct mthca_mr_table {struct mthca_alloc mpt_alloc; -struct mthca_buddy mtt_buddy; +struct mthca_buddy mtt_buddy; +struct mthca_buddy *fmr_mtt_buddy;u64 mtt_base; +u64 mpt_base;struct mthca_icm_table *mtt_table;struct mthca_icm_table *mpt_table; +struct { +void __iomem *mpt_base; +void __iomem *mtt_base; +struct mthca_buddy mtt_buddy; + } tavor_fmr; };struct mthca_eq_table {
@@ -380,7 +389,17 @@ u64 *buffer_list, int buffer_size_shift, int list_len, u64 iova, u64 total_size, u32 access, struct mthca_mr *mr); -void mthca_free_mr (struct mthca_dev *dev,struct mthca_mr *mr); +void mthca_free_mr (struct mthca_dev *dev,struct mthca_mr *mr); + +int mthca_fmr_alloc (struct mthca_dev *dev,u32 pd, +u32 access,struct mthca_fmr *fmr); +int mthca_tavor_map_phys_fmr (struct ib_fmr *ibfmr,u64 *page_list, +int list_len,u64 iova); +void mthca_tavor_fmr_unmap (struct mthca_dev *dev,struct mthca_fmr *fmr); +int mthca_arbel_map_phys_fmr (struct ib_fmr *ibfmr,u64 *page_list, +int list_len,u64 iova); +void mthca_arbel_fmr_unmap (struct mthca_dev *dev,struct mthca_fmr *fmr); +int mthca_free_fmr (struct mthca_dev *dev,struct mthca_fmr *fmr);int mthca_map_eq_icm (struct mthca_dev *dev,u64 icm_virt);void mthca_unmap_eq_icm (struct mthca_dev *dev);
drivers/infiniband/hw/mthca/mthca_main.c +9 -8
@@ -73,14 +73,15 @@DRV_VERSION " (" DRV_RELDATE ")\n" ;static struct mthca_profile default_profile = { - .num_qp =1 <<16 , - .rdb_per_qp =4 , - .num_cq =1 <<16 , - .num_mcg =1 <<13 , - .num_mpt =1 <<17 , - .num_mtt =1 <<20 , - .num_udav =1 <<15 ,/* Tavor only */ - .uarc_size =1 <<18 ,/* Arbel only */ + .num_qp =1 <<16 , + .rdb_per_qp =4 , + .num_cq =1 <<16 , + .num_mcg =1 <<13 , + .num_mpt =1 <<17 , + .num_mtt =1 <<20 , + .num_udav =1 <<15 ,/* Tavor only */ + .fmr_reserved_mtts =1 <<18 ,/* Tavor only */ + .uarc_size =1 <<18 ,/* Arbel only */ };static int __devinit mthca_tune_pci (struct mthca_dev *mdev)
drivers/infiniband/hw/mthca/mthca_mr.c +376 -10
435 lines not on this page · raw message
drivers/infiniband/hw/mthca/mthca_profile.c +16 -3
@@ -223,9 +223,10 @@ init_hca->mc_hash_sz =1 << (profile[i].log_num -1 );break ;case MTHCA_RES_MPT : - dev->limits.num_mpts = profile[i].num; - init_hca->mpt_base = profile[i].start; - init_hca->log_mpt_sz = profile[i].log_num; + dev->limits.num_mpts = profile[i].num; + dev->mr_table.mpt_base = profile[i].start; + init_hca->mpt_base = profile[i].start; + init_hca->log_mpt_sz = profile[i].log_num;break ;case MTHCA_RES_MTT : dev->limits.num_mtt_segs = profile[i].num;
@@ -259,6 +260,18 @@*/ dev->limits.num_pds =MTHCA_NUM_PDS ; +/* +* For Tavor, FMRs use ioremapped PCI memory. For 32 bit +* systems it may use too much vmalloc space to map all MTT +* memory, so we reserve some MTTs for FMR access, taking them +* out of the MR pool. They don't use additional memory, but +* we assign them as part of the HCA profile anyway. +*/ +if (dev->hca_type ==ARBEL_NATIVE ) + dev->limits.fmr_reserved_mtts =0 ; +else + dev->limits.fmr_reserved_mtts = request->fmr_reserved_mtts; +kfree (profile);return total_size; }
drivers/infiniband/hw/mthca/mthca_profile.h +1 -0
@@ -48,6 +48,7 @@int num_udav;int num_uar;int uarc_size; +int fmr_reserved_mtts; }; u64 mthca_make_profile(struct mthca_dev *mdev,
drivers/infiniband/hw/mthca/mthca_provider.c +79 -0
91 lines not on this page · raw message
drivers/infiniband/hw/mthca/mthca_provider.h +23 -0
@@ -60,6 +60,24 @@u32 first_seg; }; +struct mthca_fmr { +struct ib_fmr ibmr; +struct ib_fmr_attr attr; +int order; +u32 first_seg; +int maps; +union { +struct { +struct mthca_mpt_entry __iomem *mpt; +u64 __iomem *mtts; + } tavor; +struct { +struct mthca_mpt_entry *mpt; +__be64 *mtts; + } arbel; + } mem; +}; +struct mthca_pd {struct ib_pd ibpd;u32 pd_num;
@@ -218,6 +236,11 @@dma_addr_t header_dma; }; +static inline struct mthca_fmr *to_mfmr (struct ib_fmr *ibmr) +{ + return container_of(ibmr, struct mthca_fmr, ibmr); +} +static inline struct mthca_mr *to_mmr (struct ib_mr *ibmr) { return container_of(ibmr, struct mthca_mr, ibmr);
PATCH 23/27 IB/mthca: tweaks to mthca_cmd.c
Minor tweaks to firmware command handling: kill off an unused get of a value, and add a little more info to debug output.
drivers/infiniband/hw/mthca/mthca_cmd.c +2 -3
@@ -989,7 +989,6 @@ dev_lim->hca.arbel.resize_srq = field &1 ;MTHCA_GET (field, outbox,QUERY_DEV_LIM_MAX_SG_RQ_OFFSET ); dev_lim->max_sg =min_t (int, field, dev_lim->max_sg); -MTHCA_GET (size, outbox,QUERY_DEV_LIM_MTT_ENTRY_SZ_OFFSET );MTHCA_GET (size, outbox,QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET ); dev_lim->mpt_entry_sz = size;MTHCA_GET (field, outbox,QUERY_DEV_LIM_PBL_SZ_OFFSET );
@@ -1297,8 +1296,8 @@pci_free_consistent (dev->pdev,16 , inbox, indma);if (!err) -mthca_dbg (dev,"Mapped page at %llx for ICM.\n" , - (unsigned long long ) virt); +mthca_dbg (dev,"Mapped page at %llx to %llx for ICM.\n" , + (unsigned long long ) dma_addr, (unsigned long long ) virt);return err; }
PATCH 24/27 IB/mthca: encapsulate mem-free check into mthca_is_memfree()
Clean up mem-free mode support by introducing mthca_is_memfree() function, which encapsulates the logic of deciding if a device is mem-free.
drivers/infiniband/hw/mthca/mthca_av.c +3 -3
@@ -62,7 +62,7 @@ ah->type =MTHCA_AH_PCI_POOL ; -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { ah->av =kmalloc (sizeof *ah->av,GFP_ATOMIC );if (!ah->av)return -ENOMEM ;
@@ -192,7 +192,7 @@ {int err; -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))return 0 ; err = mthca_alloc_init(&dev->av_table.alloc,
@@ -231,7 +231,7 @@ void __devexit mthca_cleanup_av_table(struct mthca_dev *dev) { -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))return ;if (dev->av_table.av_map)
drivers/infiniband/hw/mthca/mthca_cmd.c +4 -4
@@ -651,7 +651,7 @@mthca_dbg (dev,"FW version %012llx, max commands %d\n" , (unsigned long long ) dev->fw_ver, dev->cmd.max_cmds); -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) {MTHCA_GET (dev->fw.arbel.fw_pages, outbox,QUERY_FW_SIZE_OFFSET );MTHCA_GET (dev->fw.arbel.clr_int_base, outbox,QUERY_FW_CLR_INT_BASE_OFFSET );MTHCA_GET (dev->fw.arbel.eq_arm_base, outbox,QUERY_FW_EQ_ARM_BASE_OFFSET );
@@ -984,7 +984,7 @@mthca_dbg (dev,"Flags: %08x\n" , dev_lim->flags); -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) {MTHCA_GET (field, outbox,QUERY_DEV_LIM_RSZ_SRQ_OFFSET ); dev_lim->hca.arbel.resize_srq = field &1 ;MTHCA_GET (field, outbox,QUERY_DEV_LIM_MAX_SG_RQ_OFFSET );
@@ -1148,7 +1148,7 @@/* TPT attributes */ MTHCA_PUT (inbox, param->mpt_base,INIT_HCA_MPT_BASE_OFFSET ); -if (dev->hca_type !=ARBEL_NATIVE ) +if (!mthca_is_memfree (dev))MTHCA_PUT (inbox, param->mtt_seg_sz,INIT_HCA_MTT_SEG_SZ_OFFSET );MTHCA_PUT (inbox, param->log_mpt_sz,INIT_HCA_LOG_MPT_SZ_OFFSET );MTHCA_PUT (inbox, param->mtt_base,INIT_HCA_MTT_BASE_OFFSET );
@@ -1161,7 +1161,7 @@MTHCA_PUT (inbox, param->uar_scratch_base,INIT_HCA_UAR_SCATCH_BASE_OFFSET ); -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) {MTHCA_PUT (inbox, param->log_uarc_sz,INIT_HCA_UARC_SZ_OFFSET );MTHCA_PUT (inbox, param->log_uar_sz,INIT_HCA_LOG_UAR_SZ_OFFSET );MTHCA_PUT (inbox, param->uarc_base,INIT_HCA_UAR_CTX_BASE_OFFSET );
drivers/infiniband/hw/mthca/mthca_cq.c +6 -6
@@ -180,7 +180,7 @@ {u32 doorbell[2 ]; -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { *cq->set_ci_db =cpu_to_be32 (cq->cons_index);wmb (); }else {
@@ -760,7 +760,7 @@if (cq->cqn ==-1 )return -ENOMEM ; -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { cq->arm_sn =1 ; err =mthca_table_get (dev, dev->cq_table.table, cq->cqn);
@@ -811,7 +811,7 @@ cq_context->lkey =cpu_to_be32 (cq->mr.ibmr.lkey); cq_context->cqn =cpu_to_be32 (cq->cqn); -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { cq_context->ci_db =cpu_to_be32 (cq->set_ci_db_index); cq_context->state_db =cpu_to_be32 (cq->arm_db_index); }
@@ -851,11 +851,11 @@ err_out_mailbox:kfree (mailbox); -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))mthca_free_db (dev,MTHCA_DB_TYPE_CQ_ARM , cq->arm_db_index); err_out_ci: -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))mthca_free_db (dev,MTHCA_DB_TYPE_CQ_SET_CI , cq->set_ci_db_index); err_out_icm:
@@ -916,7 +916,7 @@mthca_free_mr (dev, &cq->mr);mthca_free_cq_buf (dev, cq); -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) {mthca_free_db (dev,MTHCA_DB_TYPE_CQ_ARM , cq->arm_db_index);mthca_free_db (dev,MTHCA_DB_TYPE_CQ_SET_CI , cq->set_ci_db_index);mthca_table_put (dev, dev->cq_table.table, cq->cqn);
drivers/infiniband/hw/mthca/mthca_dev.h +5 -0
@@ -470,4 +470,9 @@ return container_of(ibdev, struct mthca_dev, ib_dev); } +static inline int mthca_is_memfree (struct mthca_dev *dev) +{ +return dev->hca_type ==ARBEL_NATIVE ; +} +#endif /* MTHCA_DEV_H */
drivers/infiniband/hw/mthca/mthca_eq.c +9 -9
@@ -198,7 +198,7 @@static inline void set_eq_ci (struct mthca_dev *dev,struct mthca_eq *eq,u32 ci) { -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))arbel_set_eq_ci (dev, eq, ci);else tavor_set_eq_ci (dev, eq, ci);
@@ -223,7 +223,7 @@static inline void disarm_cq (struct mthca_dev *dev,int eqn,int cqn) { -if (dev->hca_type !=ARBEL_NATIVE ) { +if (!mthca_is_memfree (dev)) {u32 doorbell[2 ]; doorbell[0 ] =cpu_to_be32 (MTHCA_EQ_DB_DISARM_CQ | eqn);
@@ -535,11 +535,11 @@MTHCA_EQ_OWNER_HW |MTHCA_EQ_STATE_ARMED | MTHCA_EQ_FLAG_TR); -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev)) eq_context->flags |=cpu_to_be32 (MTHCA_EQ_STATE_ARBEL ); eq_context->logsize_usrpage =cpu_to_be32 ((ffs (nent) -1 ) <<24 ); -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { eq_context->arbel_pd =cpu_to_be32 (dev->driver_pd.pd_num); }else { eq_context->logsize_usrpage |=cpu_to_be32 (dev->driver_uar.index);
@@ -686,7 +686,7 @@ mthca_base =pci_resource_start (dev->pdev,0 ); -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) {/* * We assume that the EQ arm and EQ set CI registers * fall within the first BAR. We can't trust the
@@ -756,7 +756,7 @@ static void __devexit mthca_unmap_eq_regs(struct mthca_dev *dev) { -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) & dev->fw.arbel.eq_set_ci_base, MTHCA_EQ_SET_CI_SIZE,
@@ -880,7 +880,7 @@for (i =0 ; i <MTHCA_NUM_EQ ; ++i) { err =request_irq (dev->eq_table.eq[i].msi_x_vector, - dev->hca_type ==ARBEL_NATIVE ? +mthca_is_memfree (dev) ? mthca_arbel_msi_x_interrupt : mthca_tavor_msi_x_interrupt,0 , eq_name[i], dev->eq_table.eq + i);
@@ -890,7 +890,7 @@ } }else { err =request_irq (dev->pdev->irq, - dev->hca_type ==ARBEL_NATIVE ? +mthca_is_memfree (dev) ? mthca_arbel_interrupt : mthca_tavor_interrupt,SA_SHIRQ ,DRV_NAME , dev);
@@ -918,7 +918,7 @@ dev->eq_table.eq[MTHCA_EQ_CMD].eqn, status);for (i =0 ; i <MTHCA_EQ_CMD ; ++i) -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))arbel_eq_req_not (dev, dev->eq_table.eq[i].eqn_mask);else tavor_eq_req_not (dev, dev->eq_table.eq[i].eqn);
drivers/infiniband/hw/mthca/mthca_main.c +3 -3
@@ -601,7 +601,7 @@static int __devinit mthca_init_hca (struct mthca_dev *mdev) { -if (mdev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (mdev))return mthca_init_arbel (mdev);else return mthca_init_tavor (mdev);
@@ -835,7 +835,7 @@mthca_CLOSE_HCA (mdev,0 , &status); -if (mdev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (mdev)) {mthca_free_icm_table (mdev, mdev->cq_table.table);mthca_free_icm_table (mdev, mdev->qp_table.eqp_table);mthca_free_icm_table (mdev, mdev->qp_table.qp_table);
@@ -939,7 +939,7 @@ mdev->pdev = pdev; mdev->hca_type = id->driver_data; -if (mdev->hca_type ==ARBEL_NATIVE && !mthca_memfree_warned++) +if (mthca_is_memfree (mdev) && !mthca_memfree_warned++)mthca_warn (mdev,"Warning: native MT25208 mode support is incomplete. " "Your HCA may not work properly.\n" );
drivers/infiniband/hw/mthca/mthca_memfree.c +2 -2
@@ -472,7 +472,7 @@ {int i; -if (dev->hca_type !=ARBEL_NATIVE ) +if (!mthca_is_memfree (dev))return 0 ; dev->db_tab =kmalloc (sizeof *dev->db_tab,GFP_KERNEL );
@@ -504,7 +504,7 @@int i;u8 status; -if (dev->hca_type !=ARBEL_NATIVE ) +if (!mthca_is_memfree (dev))return ;/*
drivers/infiniband/hw/mthca/mthca_mr.c +14 -14
@@ -181,7 +181,7 @@if (seg ==-1 )return -1 ; -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))if (mthca_table_get_range (dev, dev->mr_table.mtt_table, seg, seg + (1 << order) -1 )) {mthca_buddy_free (buddy, seg, order);
@@ -196,7 +196,7 @@ {mthca_buddy_free (buddy, seg, order); -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))mthca_table_put_range (dev, dev->mr_table.mtt_table, seg, seg + (1 << order) -1 ); }
@@ -223,7 +223,7 @@static inline u32 hw_index_to_key (struct mthca_dev *dev,u32 ind) { -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))return arbel_hw_index_to_key (ind);else return tavor_hw_index_to_key (ind);
@@ -231,7 +231,7 @@static inline u32 key_to_hw_index (struct mthca_dev *dev,u32 key) { -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))return arbel_key_to_hw_index (key);else return tavor_key_to_hw_index (key);
@@ -254,7 +254,7 @@return -ENOMEM ; mr->ibmr.rkey = mr->ibmr.lkey =hw_index_to_key (dev, key); -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { err =mthca_table_get (dev, dev->mr_table.mpt_table, key);if (err) goto err_out_mpt_free;
@@ -299,7 +299,7 @@return err; err_out_table: -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))mthca_table_put (dev, dev->mr_table.mpt_table, key); err_out_mpt_free:
@@ -329,7 +329,7 @@return -ENOMEM ; mr->ibmr.rkey = mr->ibmr.lkey =hw_index_to_key (dev, key); -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { err =mthca_table_get (dev, dev->mr_table.mpt_table, key);if (err) goto err_out_mpt_free;
@@ -437,7 +437,7 @@mthca_free_mtt (dev, mr->first_seg, mr->order, &dev->mr_table.mtt_buddy); err_out_table: -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))mthca_table_put (dev, dev->mr_table.mpt_table, key); err_out_mpt_free:
@@ -452,7 +452,7 @@if (order >=0 )mthca_free_mtt (dev, first_seg, order, buddy); -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))mthca_table_put (dev, dev->mr_table.mpt_table,arbel_key_to_hw_index (lkey));
@@ -498,7 +498,7 @@return -EINVAL ;/* For Arbel, all MTTs must fit in the same page. */ -if (dev->hca_type ==ARBEL_NATIVE && +if (mthca_is_memfree (dev) && mr->attr.max_pages *sizeof *mr->mem.arbel.mtts >PAGE_SIZE )return -EINVAL ;
@@ -511,7 +511,7 @@ idx = key & (dev->limits.num_mpts -1 ); mr->ibmr.rkey = mr->ibmr.lkey =hw_index_to_key (dev, key); -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { err =mthca_table_get (dev, dev->mr_table.mpt_table, key);if (err) goto err_out_mpt_free;
@@ -534,7 +534,7 @@ mtt_seg = mr->first_seg *MTHCA_MTT_SEG_SIZE ; -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { mr->mem.arbel.mtts =mthca_table_find (dev->mr_table.mtt_table, mr->first_seg);BUG_ON (!mr->mem.arbel.mtts);
@@ -596,7 +596,7 @@ dev->mr_table.fmr_mtt_buddy); err_out_table: -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))mthca_table_put (dev, dev->mr_table.mpt_table, key); err_out_mpt_free:
@@ -765,7 +765,7 @@if (err)return err; -if (dev->hca_type !=ARBEL_NATIVE && +if (!mthca_is_memfree (dev) && (dev->mthca_flags &MTHCA_FLAG_DDR_HIDDEN )) dev->limits.fmr_reserved_mtts =0 ;else
drivers/infiniband/hw/mthca/mthca_profile.c +4 -4
@@ -116,11 +116,11 @@ profile[i].type = i; profile[i].log_num =max (ffs (profile[i].num) -1 ,0 ); profile[i].size *= profile[i].num; -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev)) profile[i].size =max (profile[i].size, (u64 )PAGE_SIZE ); } -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { mem_base =0 ; mem_avail = dev_lim->hca.arbel.max_icm_sz; }else {
@@ -165,7 +165,7 @@ (unsigned long long) profile[i].size); } -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev))mthca_dbg (dev,"HCA context memory: reserving %d KB\n" , (int ) (total_size >>10 ));else
@@ -267,7 +267,7 @@* out of the MR pool. They don't use additional memory, but * we assign them as part of the HCA profile anyway. */ -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev)) dev->limits.fmr_reserved_mtts =0 ;else dev->limits.fmr_reserved_mtts = request->fmr_reserved_mtts;
drivers/infiniband/hw/mthca/mthca_provider.c +3 -3
@@ -625,7 +625,7 @@if (!mdev)return 0 ; -if (mdev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (mdev)) {list_for_each_entry (fmr, fmr_list, list)mthca_arbel_fmr_unmap (mdev,to_mfmr (fmr));
@@ -710,7 +710,7 @@ dev->ib_dev.alloc_fmr = mthca_alloc_fmr; dev->ib_dev.unmap_fmr = mthca_unmap_fmr; dev->ib_dev.dealloc_fmr = mthca_dealloc_fmr; -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev)) dev->ib_dev.map_phys_fmr = mthca_arbel_map_phys_fmr;else dev->ib_dev.map_phys_fmr = mthca_tavor_map_phys_fmr;
@@ -720,7 +720,7 @@ dev->ib_dev.detach_mcast = mthca_multicast_detach; dev->ib_dev.process_mad = mthca_process_mad; -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { dev->ib_dev.req_notify_cq = mthca_arbel_arm_cq; dev->ib_dev.post_send = mthca_arbel_post_send; dev->ib_dev.post_recv = mthca_arbel_post_receive;
drivers/infiniband/hw/mthca/mthca_qp.c +9 -9
@@ -639,7 +639,7 @@else if (attr_mask &IB_QP_PATH_MTU ) qp_context->mtu_msgmax = (attr->path_mtu <<5 ) |31 ; -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { qp_context->rq_size_stride = ((ffs (qp->rq.max) -1 ) <<3 ) | (qp->rq.wqe_shift -4 ); qp_context->sq_size_stride =
@@ -731,7 +731,7 @@ qp_context->next_send_psn =cpu_to_be32 (attr->sq_psn); qp_context->cqn_snd =cpu_to_be32 (to_mcq (ibqp->send_cq)->cqn); -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { qp_context->snd_wqe_base_l =cpu_to_be32 (qp->send_wqe_offset); qp_context->snd_db_index =cpu_to_be32 (qp->sq.db_index); }
@@ -822,7 +822,7 @@ qp_context->cqn_rcv =cpu_to_be32 (to_mcq (ibqp->recv_cq)->cqn); -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev)) qp_context->rcv_db_index =cpu_to_be32 (qp->rq.db_index);if (attr_mask &IB_QP_QKEY ) {
@@ -897,7 +897,7 @@ size +=2 *sizeof (struct mthca_data_seg );break ;case UD : -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev)) size +=sizeof (struct mthca_arbel_ud_seg );else size +=sizeof (struct mthca_tavor_ud_seg );
@@ -1016,7 +1016,7 @@ {int ret =0 ; -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) { ret =mthca_table_get (dev, dev->qp_table.qp_table, qp->qpn);if (ret)return ret;
@@ -1057,7 +1057,7 @@static void mthca_free_memfree (struct mthca_dev *dev,struct mthca_qp *qp) { -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) {mthca_free_db (dev,MTHCA_DB_TYPE_SQ , qp->sq.db_index);mthca_free_db (dev,MTHCA_DB_TYPE_RQ , qp->rq.db_index);mthca_table_put (dev, dev->qp_table.eqp_table, qp->qpn);
@@ -1104,7 +1104,7 @@return ret; } -if (dev->hca_type ==ARBEL_NATIVE ) { +if (mthca_is_memfree (dev)) {for (i =0 ; i < qp->rq.max; ++i) { wqe =get_recv_wqe (qp, i); wqe->nda_op = cpu_to_be32(((i + 1) & (qp->rq.max - 1)) <<
@@ -1127,7 +1127,7 @@ {int i; -if (dev->hca_type !=ARBEL_NATIVE ) +if (!mthca_is_memfree (dev))return ;for (i =0 ;1 << i < qp->rq.max; ++i)
@@ -2011,7 +2011,7 @@else next =get_recv_wqe (qp, index); -if (dev->hca_type ==ARBEL_NATIVE ) +if (mthca_is_memfree (dev)) *dbd =1 ;else *dbd = !!(next->ee_nds &cpu_to_be32 (MTHCA_NEXT_DBD ));
PATCH 25/27 IB/mthca: map context for RDMA responder in mem-free mode
Fix RDMA in mem-free mode: we need to make sure that the RDMA context memory is mapped for the HCA.
drivers/infiniband/hw/mthca/mthca_dev.h +1 -0
@@ -222,6 +222,7 @@struct mthca_array qp;struct mthca_icm_table *qp_table;struct mthca_icm_table *eqp_table; +struct mthca_icm_table *rdb_table; };struct mthca_av_table {
drivers/infiniband/hw/mthca/mthca_main.c +16 -2
@@ -430,14 +430,25 @@ goto err_unmap_qp; } - mdev->cq_table.table =mthca_alloc_icm_table (mdev, init_hca->cqc_base, + mdev->qp_table.rdb_table =mthca_alloc_icm_table (mdev, init_hca->rdb_base, +MTHCA_RDB_ENTRY_SIZE , + mdev->limits.num_qps << + mdev->qp_table.rdb_shift, +0 ,0 ); +if (!mdev->qp_table.rdb_table) { +mthca_err (mdev,"Failed to map RDB context memory, aborting\n" ); + err = -ENOMEM ; + goto err_unmap_eqp; + } + + mdev->cq_table.table =mthca_alloc_icm_table (mdev, init_hca->cqc_base, dev_lim->cqc_entry_sz, mdev->limits.num_cqs, mdev->limits.reserved_cqs,0 );if (!mdev->cq_table.table) {mthca_err (mdev,"Failed to map CQ context memory, aborting.\n" ); err = -ENOMEM ; - goto err_unmap_eqp; + goto err_unmap_rdb; }/*
@@ -463,6 +474,9 @@ err_unmap_cq:mthca_free_icm_table (mdev, mdev->cq_table.table); +err_unmap_rdb: +mthca_free_icm_table (mdev, mdev->qp_table.rdb_table); + err_unmap_eqp:mthca_free_icm_table (mdev, mdev->qp_table.eqp_table);
drivers/infiniband/hw/mthca/mthca_qp.c +12 -1
@@ -1025,11 +1025,16 @@if (ret) goto err_qpc; + ret =mthca_table_get (dev, dev->qp_table.rdb_table, + qp->qpn << dev->qp_table.rdb_shift); +if (ret) + goto err_eqpc; + qp->rq.db_index =mthca_alloc_db (dev,MTHCA_DB_TYPE_RQ , qp->qpn, &qp->rq.db);if (qp->rq.db_index <0 ) { ret = -ENOMEM ; - goto err_eqpc; + goto err_rdb; } qp->sq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SQ,
@@ -1045,6 +1050,10 @@ err_rq_db:mthca_free_db (dev,MTHCA_DB_TYPE_RQ , qp->rq.db_index); +err_rdb: +mthca_table_put (dev, dev->qp_table.rdb_table, + qp->qpn << dev->qp_table.rdb_shift); + err_eqpc:mthca_table_put (dev, dev->qp_table.eqp_table, qp->qpn);
@@ -1060,6 +1069,8 @@if (mthca_is_memfree (dev)) {mthca_free_db (dev,MTHCA_DB_TYPE_SQ , qp->sq.db_index);mthca_free_db (dev,MTHCA_DB_TYPE_RQ , qp->rq.db_index); +mthca_table_put (dev, dev->qp_table.rdb_table, + qp->qpn << dev->qp_table.rdb_shift);mthca_table_put (dev, dev->qp_table.eqp_table, qp->qpn);mthca_table_put (dev, dev->qp_table.qp_table, qp->qpn); }
PATCH 26/27 IB/mthca: update receive queue initialization for new HCAs
Update initialization of receive queue to match new documentation. This change is required to support new MT25204 HCA.
drivers/infiniband/hw/mthca/mthca_qp.c +23 -10
@@ -181,6 +181,10 @@MTHCA_MLX_SLR =1 <<16 }; +enum { +MTHCA_INVAL_LKEY =0x100 +}; +struct mthca_next_seg {u32 nda_op;/* [31:6] next WQE [4:0] next opcode */ u32 ee_nds;/* [31:8] next EE [7] DBD [6] F [5:0] next WQE size */
@@ -1093,7 +1097,6 @@enum ib_sig_type send_policy, struct mthca_qp *qp) { - struct mthca_next_seg *wqe; int ret;int i;
@@ -1116,18 +1119,28 @@ }if (mthca_is_memfree (dev)) { +struct mthca_next_seg *next; +struct mthca_data_seg *scatter; +int size = (sizeof (struct mthca_next_seg ) + + qp->rq.max_gs *sizeof (struct mthca_data_seg )) /16 ; +for (i =0 ; i < qp->rq.max; ++i) { - wqe =get_recv_wqe (qp, i); - wqe->nda_op =cpu_to_be32 (((i +1 ) & (qp->rq.max -1 )) << - qp->rq.wqe_shift); - wqe->ee_nds =cpu_to_be32 (1 << (qp->rq.wqe_shift -4 )); + next =get_recv_wqe (qp, i); + next->nda_op =cpu_to_be32 (((i +1 ) & (qp->rq.max -1 )) << + qp->rq.wqe_shift); + next->ee_nds =cpu_to_be32 (size); + +for (scatter = (void *) (next +1 ); + (void *) scatter < (void *) next + (1 << qp->rq.wqe_shift); + ++scatter) + scatter->lkey =cpu_to_be32 (MTHCA_INVAL_LKEY ); }for (i =0 ; i < qp->sq.max; ++i) { - wqe =get_send_wqe (qp, i); - wqe->nda_op =cpu_to_be32 ((((i +1 ) & (qp->sq.max -1 )) << - qp->sq.wqe_shift) + - qp->send_wqe_offset); + next =get_send_wqe (qp, i); + next->nda_op =cpu_to_be32 ((((i +1 ) & (qp->sq.max -1 )) << + qp->sq.wqe_shift) + + qp->send_wqe_offset); } }
@@ -1986,7 +1999,7 @@if (i < qp->rq.max_gs) { ((struct mthca_data_seg *) wqe)->byte_count =0 ; - ((struct mthca_data_seg *) wqe)->lkey =cpu_to_be32 (0x100 ); + ((struct mthca_data_seg *) wqe)->lkey =cpu_to_be32 (MTHCA_INVAL_LKEY ); ((struct mthca_data_seg *) wqe)->addr =0 ; }
PATCH 27/27 IB/mthca: add support for new MT25204 HCA
Decouple table of HCA features from exact HCA device type. Add a current FW version field so we can warn when someone is using old FW. Add support for new MT25204 HCA.
Remove the warning about mem-free support, since it should be pretty solid at this point.
drivers/infiniband/hw/mthca/mthca_dev.h +4 -9
@@ -49,20 +49,15 @@#define DRV_VERSION "0.06-pre"#define DRV_RELDATE "November 8, 2004" -/* Types of supported HCA */ -enum { -TAVOR ,/* MT23108 */ -ARBEL_COMPAT ,/* MT25208 in Tavor compat mode */ -ARBEL_NATIVE /* MT25208 with extended features */ -}; -enum {MTHCA_FLAG_DDR_HIDDEN =1 <<1 ,MTHCA_FLAG_SRQ =1 <<2 ,MTHCA_FLAG_MSI =1 <<3 ,MTHCA_FLAG_MSI_X =1 <<4 ,MTHCA_FLAG_NO_LAM =1 <<5 , -MTHCA_FLAG_FMR =1 <<6 +MTHCA_FLAG_FMR =1 <<6 , +MTHCA_FLAG_MEMFREE =1 <<7 , +MTHCA_FLAG_PCIE =1 <<8 };enum {
@@ -473,7 +468,7 @@static inline int mthca_is_memfree (struct mthca_dev *dev) { -return dev->hca_type ==ARBEL_NATIVE ; +return dev->mthca_flags &MTHCA_FLAG_MEMFREE ; }#endif /* MTHCA_DEV_H */
drivers/infiniband/hw/mthca/mthca_main.c +56 -11
134 lines not on this page · raw message
drivers/infiniband/hw/mthca/mthca_provider.c +12 -5
@@ -659,11 +659,18 @@static ssize_t show_hca (struct class_device *cdev,char *buf) { struct mthca_dev *dev = container_of(cdev, struct mthca_dev, ib_dev.class_dev); -switch (dev->hca_type) { -case TAVOR :return sprintf (buf,"MT23108\n" ); -case ARBEL_COMPAT :return sprintf (buf,"MT25208 (MT23108 compat mode)\n" ); -case ARBEL_NATIVE :return sprintf (buf,"MT25208\n" ); -default :return sprintf (buf,"unknown\n" ); +switch (dev->pdev->device) { +case PCI_DEVICE_ID_MELLANOX_TAVOR : +return sprintf (buf,"MT23108\n" ); +case PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT : +return sprintf (buf,"MT25208 (MT23108 compat mode)\n" ); +case PCI_DEVICE_ID_MELLANOX_ARBEL : +return sprintf (buf,"MT25208\n" ); +case PCI_DEVICE_ID_MELLANOX_SINAI : +case PCI_DEVICE_ID_MELLANOX_SINAI_OLD : +return sprintf (buf,"MT25204\n" ); +default : +return sprintf (buf,"unknown\n" ); } }
drivers/infiniband/hw/mthca/mthca_reset.c +1 -1
@@ -63,7 +63,7 @@* header as well. */ - if (mdev->hca_type == TAVOR) { + if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE)) { /* Look for the bridge -- its device ID will be 2 more than HCA's device ID. */ while ((bridge = pci_get_device(mdev->pdev->vendor,
PATCH 1/1 [26.5/27] Add MT25204 PCI IDs
Ugh, this patch is required to build support for the new Mellanox HCAs. Greg K-H applied it to his tree a while ago but it hasn't made it to Linus yet.
Sorry,
Roland
Add PCI device IDs for new Mellanox MT25204 "Sinai" InfiniHost III Lx HCA.
include/linux/pci_ids.h +2 -0
@@ -2122,6 +2122,8 @@#define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44#define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278#define PCI_DEVICE_ID_MELLANOX_ARBEL 0x6282 +#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c +#define PCI_DEVICE_ID_MELLANOX_SINAI 0x6274#define PCI_VENDOR_ID_PDC 0x15e9#define PCI_DEVICE_ID_PDC_1841 0x1841
Re: [PATCH][26.5/27] Add MT25204 PCI IDs
Quoted 10 lines · Roland Dreier
Ugh, this patch is required to build support for the new Mellanox HCAs. Greg K-H applied it to his tree a while ago but it hasn't made it to Linus yet.
Sorry,
RolandAdd PCI device IDs for new Mellanox MT25204 "Sinai" InfiniHost III Lx HCA.
Signed-off-by Roland Dreier <[email protected]>
Already in 2.6.12-rc2.
thanks,
greg k-h