* Callback to DMA map external memory to a device. * * @param rte_dev * Pointer to the generic device. * @param addr * Starting virtual address of memory to be mapped. * @param iova * Starting IOVA address of memory to be mapped. * @param len * Length of memory segment being mapped. * * @return * 0 on success, negative value on error. */
| 1084 | * 0 on success, negative value on error. |
| 1085 | */ |
| 1086 | int |
| 1087 | mlx5_common_dev_dma_map(struct rte_device *rte_dev, void *addr, |
| 1088 | uint64_t iova __rte_unused, size_t len) |
| 1089 | { |
| 1090 | struct mlx5_common_device *dev; |
| 1091 | struct mlx5_mr_btree *bt; |
| 1092 | struct mlx5_mr *mr; |
| 1093 | |
| 1094 | dev = to_mlx5_device(rte_dev); |
| 1095 | if (!dev) { |
| 1096 | DRV_LOG(WARNING, |
| 1097 | "Unable to find matching mlx5 device to device %s", |
| 1098 | rte_dev->name); |
| 1099 | rte_errno = ENODEV; |
| 1100 | return -1; |
| 1101 | } |
| 1102 | mr = mlx5_create_mr_ext(dev->pd, (uintptr_t)addr, len, |
| 1103 | SOCKET_ID_ANY, dev->mr_scache.reg_mr_cb); |
| 1104 | if (!mr) { |
| 1105 | DRV_LOG(WARNING, "Device %s unable to DMA map", rte_dev->name); |
| 1106 | rte_errno = EINVAL; |
| 1107 | return -1; |
| 1108 | } |
| 1109 | try_insert: |
| 1110 | rte_rwlock_write_lock(&dev->mr_scache.rwlock); |
| 1111 | bt = &dev->mr_scache.cache; |
| 1112 | if (bt->len == bt->size) { |
| 1113 | uint32_t size; |
| 1114 | int ret; |
| 1115 | |
| 1116 | size = bt->size + 1; |
| 1117 | MLX5_ASSERT(size > bt->size); |
| 1118 | /* |
| 1119 | * Avoid deadlock (numbers show the sequence of events): |
| 1120 | * mlx5_mr_create_primary(): |
| 1121 | * 1) take EAL memory lock |
| 1122 | * 3) take MR lock |
| 1123 | * this function: |
| 1124 | * 2) take MR lock |
| 1125 | * 4) take EAL memory lock while allocating the new cache |
| 1126 | * Releasing the MR lock before step 4 |
| 1127 | * allows another thread to execute step 3. |
| 1128 | */ |
| 1129 | rte_rwlock_write_unlock(&dev->mr_scache.rwlock); |
| 1130 | ret = mlx5_mr_expand_cache(&dev->mr_scache, size, |
| 1131 | rte_dev->numa_node); |
| 1132 | if (ret < 0) { |
| 1133 | mlx5_mr_free(mr, dev->mr_scache.dereg_mr_cb); |
| 1134 | rte_errno = ret; |
| 1135 | return -1; |
| 1136 | } |
| 1137 | goto try_insert; |
| 1138 | } |
| 1139 | LIST_INSERT_HEAD(&dev->mr_scache.mr_list, mr, mr); |
| 1140 | /* Insert to the global cache table. */ |
| 1141 | mlx5_mr_insert_cache(&dev->mr_scache, mr); |
| 1142 | rte_rwlock_write_unlock(&dev->mr_scache.rwlock); |
| 1143 | return 0; |
no test coverage detected