Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
[linux-2.6-microblaze.git] / drivers / infiniband / hw / hfi1 / chip.c
index addefae..310105d 100644 (file)
@@ -4104,6 +4104,9 @@ def_access_ibp_counter(seq_naks);
 
 static struct cntr_entry dev_cntrs[DEV_CNTR_LAST] = {
 [C_RCV_OVF] = RXE32_DEV_CNTR_ELEM(RcvOverflow, RCV_BUF_OVFL_CNT, CNTR_SYNTH),
+[C_RX_LEN_ERR] = RXE32_DEV_CNTR_ELEM(RxLenErr, RCV_LENGTH_ERR_CNT, CNTR_SYNTH),
+[C_RX_ICRC_ERR] = RXE32_DEV_CNTR_ELEM(RxICrcErr, RCV_ICRC_ERR_CNT, CNTR_SYNTH),
+[C_RX_EBP] = RXE32_DEV_CNTR_ELEM(RxEbpCnt, RCV_EBP_CNT, CNTR_SYNTH),
 [C_RX_TID_FULL] = RXE32_DEV_CNTR_ELEM(RxTIDFullEr, RCV_TID_FULL_ERR_CNT,
                        CNTR_NORMAL),
 [C_RX_TID_INVALID] = RXE32_DEV_CNTR_ELEM(RxTIDInvalid, RCV_TID_VALID_ERR_CNT,
@@ -13294,15 +13297,18 @@ static int set_up_context_variables(struct hfi1_devdata *dd)
        /*
         * The RMT entries are currently allocated as shown below:
         * 1. QOS (0 to 128 entries);
-        * 2. FECN for PSM (num_user_contexts + num_vnic_contexts);
+        * 2. FECN (num_kernel_context - 1 + num_user_contexts +
+        *    num_vnic_contexts);
         * 3. VNIC (num_vnic_contexts).
-        * It should be noted that PSM FECN oversubscribe num_vnic_contexts
+        * It should be noted that FECN oversubscribe num_vnic_contexts
         * entries of RMT because both VNIC and PSM could allocate any receive
         * context between dd->first_dyn_alloc_text and dd->num_rcv_contexts,
         * and PSM FECN must reserve an RMT entry for each possible PSM receive
         * context.
         */
        rmt_count = qos_rmt_entries(dd, NULL, NULL) + (num_vnic_contexts * 2);
+       if (HFI1_CAP_IS_KSET(TID_RDMA))
+               rmt_count += num_kernel_contexts - 1;
        if (rmt_count + n_usr_ctxts > NUM_MAP_ENTRIES) {
                user_rmt_reduced = NUM_MAP_ENTRIES - rmt_count;
                dd_dev_err(dd,
@@ -14285,37 +14291,43 @@ bail:
        init_qpmap_table(dd, FIRST_KERNEL_KCTXT, dd->n_krcv_queues - 1);
 }
 
-static void init_user_fecn_handling(struct hfi1_devdata *dd,
-                                   struct rsm_map_table *rmt)
+static void init_fecn_handling(struct hfi1_devdata *dd,
+                              struct rsm_map_table *rmt)
 {
        struct rsm_rule_data rrd;
        u64 reg;
-       int i, idx, regoff, regidx;
+       int i, idx, regoff, regidx, start;
        u8 offset;
        u32 total_cnt;
 
+       if (HFI1_CAP_IS_KSET(TID_RDMA))
+               /* Exclude context 0 */
+               start = 1;
+       else
+               start = dd->first_dyn_alloc_ctxt;
+
+       total_cnt = dd->num_rcv_contexts - start;
+
        /* there needs to be enough room in the map table */
-       total_cnt = dd->num_rcv_contexts - dd->first_dyn_alloc_ctxt;
        if (rmt->used + total_cnt >= NUM_MAP_ENTRIES) {
-               dd_dev_err(dd, "User FECN handling disabled - too many user contexts allocated\n");
+               dd_dev_err(dd, "FECN handling disabled - too many contexts allocated\n");
                return;
        }
 
        /*
         * RSM will extract the destination context as an index into the
         * map table.  The destination contexts are a sequential block
-        * in the range first_dyn_alloc_ctxt...num_rcv_contexts-1 (inclusive).
+        * in the range start...num_rcv_contexts-1 (inclusive).
         * Map entries are accessed as offset + extracted value.  Adjust
         * the added offset so this sequence can be placed anywhere in
         * the table - as long as the entries themselves do not wrap.
         * There are only enough bits in offset for the table size, so
         * start with that to allow for a "negative" offset.
         */
-       offset = (u8)(NUM_MAP_ENTRIES + (int)rmt->used -
-                                               (int)dd->first_dyn_alloc_ctxt);
+       offset = (u8)(NUM_MAP_ENTRIES + rmt->used - start);
 
-       for (i = dd->first_dyn_alloc_ctxt, idx = rmt->used;
-                               i < dd->num_rcv_contexts; i++, idx++) {
+       for (i = start, idx = rmt->used; i < dd->num_rcv_contexts;
+            i++, idx++) {
                /* replace with identity mapping */
                regoff = (idx % 8) * 8;
                regidx = idx / 8;
@@ -14437,7 +14449,7 @@ static void init_rxe(struct hfi1_devdata *dd)
        rmt = alloc_rsm_map_table(dd);
        /* set up QOS, including the QPN map table */
        init_qos(dd, rmt);
-       init_user_fecn_handling(dd, rmt);
+       init_fecn_handling(dd, rmt);
        complete_rsm_map_table(dd, rmt);
        /* record number of used rsm map entries for vnic */
        dd->vnic.rmt_start = rmt->used;
@@ -14663,8 +14675,8 @@ void hfi1_start_cleanup(struct hfi1_devdata *dd)
  */
 static int init_asic_data(struct hfi1_devdata *dd)
 {
-       unsigned long flags;
-       struct hfi1_devdata *tmp, *peer = NULL;
+       unsigned long index;
+       struct hfi1_devdata *peer;
        struct hfi1_asic_data *asic_data;
        int ret = 0;
 
@@ -14673,14 +14685,12 @@ static int init_asic_data(struct hfi1_devdata *dd)
        if (!asic_data)
                return -ENOMEM;
 
-       spin_lock_irqsave(&hfi1_devs_lock, flags);
+       xa_lock_irq(&hfi1_dev_table);
        /* Find our peer device */
-       list_for_each_entry(tmp, &hfi1_dev_list, list) {
-               if ((HFI_BASE_GUID(dd) == HFI_BASE_GUID(tmp)) &&
-                   dd->unit != tmp->unit) {
-                       peer = tmp;
+       xa_for_each(&hfi1_dev_table, index, peer) {
+               if ((HFI_BASE_GUID(dd) == HFI_BASE_GUID(peer)) &&
+                   dd->unit != peer->unit)
                        break;
-               }
        }
 
        if (peer) {
@@ -14692,7 +14702,7 @@ static int init_asic_data(struct hfi1_devdata *dd)
                mutex_init(&dd->asic_data->asic_resource_mutex);
        }
        dd->asic_data->dds[dd->hfi1_id] = dd; /* self back-pointer */
-       spin_unlock_irqrestore(&hfi1_devs_lock, flags);
+       xa_unlock_irq(&hfi1_dev_table);
 
        /* first one through - set up i2c devices */
        if (!peer)