Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: hisilicon/qm - Put device finding logic into QM

Use struct hisi_qm to maintain device list. Meanwhile, add two external
interface into qm, merge find proper device and create qp into QP alloc
logic, merge release qps into QP free logic.

Signed-off-by: Weili Qian <qianweili@huawei.com>
Signed-off-by: Shukun Tan <tanshukun1@huawei.com>
Reviewed-by: Zhou Wang <wangzhou1@hisilicon.com>
Reviewed-by: Zaibo Xu <xuzaibo@huawei.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Weili Qian and committed by
Herbert Xu
3f1ec97a 0eae14a0

+156
+125
drivers/crypto/hisilicon/qm.c
··· 272 272 __le16 priority; 273 273 }; 274 274 275 + struct hisi_qm_resource { 276 + struct hisi_qm *qm; 277 + int distance; 278 + struct list_head list; 279 + }; 280 + 275 281 struct hisi_qm_hw_ops { 276 282 int (*get_vft)(struct hisi_qm *qm, u32 *base, u32 *number); 277 283 void (*qm_db)(struct hisi_qm *qm, u16 qn, ··· 2179 2173 qm->err_ini->hw_err_disable(qm); 2180 2174 } 2181 2175 EXPORT_SYMBOL_GPL(hisi_qm_dev_err_uninit); 2176 + 2177 + /** 2178 + * hisi_qm_free_qps() - free multiple queue pairs. 2179 + * @qps: The queue pairs need to be freed. 2180 + * @qp_num: The num of queue pairs. 2181 + */ 2182 + void hisi_qm_free_qps(struct hisi_qp **qps, int qp_num) 2183 + { 2184 + int i; 2185 + 2186 + if (!qps || qp_num <= 0) 2187 + return; 2188 + 2189 + for (i = qp_num - 1; i >= 0; i--) 2190 + hisi_qm_release_qp(qps[i]); 2191 + } 2192 + EXPORT_SYMBOL_GPL(hisi_qm_free_qps); 2193 + 2194 + static void free_list(struct list_head *head) 2195 + { 2196 + struct hisi_qm_resource *res, *tmp; 2197 + 2198 + list_for_each_entry_safe(res, tmp, head, list) { 2199 + list_del(&res->list); 2200 + kfree(res); 2201 + } 2202 + } 2203 + 2204 + static int hisi_qm_sort_devices(int node, struct list_head *head, 2205 + struct hisi_qm_list *qm_list) 2206 + { 2207 + struct hisi_qm_resource *res, *tmp; 2208 + struct hisi_qm *qm; 2209 + struct list_head *n; 2210 + struct device *dev; 2211 + int dev_node = 0; 2212 + 2213 + list_for_each_entry(qm, &qm_list->list, list) { 2214 + dev = &qm->pdev->dev; 2215 + 2216 + if (IS_ENABLED(CONFIG_NUMA)) { 2217 + dev_node = dev_to_node(dev); 2218 + if (dev_node < 0) 2219 + dev_node = 0; 2220 + } 2221 + 2222 + res = kzalloc(sizeof(*res), GFP_KERNEL); 2223 + if (!res) 2224 + return -ENOMEM; 2225 + 2226 + res->qm = qm; 2227 + res->distance = node_distance(dev_node, node); 2228 + n = head; 2229 + list_for_each_entry(tmp, head, list) { 2230 + if (res->distance < tmp->distance) { 2231 + n = &tmp->list; 2232 + break; 2233 + } 2234 + } 2235 + list_add_tail(&res->list, n); 2236 + } 2237 + 2238 + return 0; 2239 + } 2240 + 2241 + /** 2242 + * hisi_qm_alloc_qps_node() - Create multiple queue pairs. 2243 + * @qm_list: The list of all available devices. 2244 + * @qp_num: The number of queue pairs need created. 2245 + * @alg_type: The algorithm type. 2246 + * @node: The numa node. 2247 + * @qps: The queue pairs need created. 2248 + * 2249 + * This function will sort all available device according to numa distance. 2250 + * Then try to create all queue pairs from one device, if all devices do 2251 + * not meet the requirements will return error. 2252 + */ 2253 + int hisi_qm_alloc_qps_node(struct hisi_qm_list *qm_list, int qp_num, 2254 + u8 alg_type, int node, struct hisi_qp **qps) 2255 + { 2256 + struct hisi_qm_resource *tmp; 2257 + int ret = -ENODEV; 2258 + LIST_HEAD(head); 2259 + int i; 2260 + 2261 + if (!qps || !qm_list || qp_num <= 0) 2262 + return -EINVAL; 2263 + 2264 + mutex_lock(&qm_list->lock); 2265 + if (hisi_qm_sort_devices(node, &head, qm_list)) { 2266 + mutex_unlock(&qm_list->lock); 2267 + goto err; 2268 + } 2269 + 2270 + list_for_each_entry(tmp, &head, list) { 2271 + for (i = 0; i < qp_num; i++) { 2272 + qps[i] = hisi_qm_create_qp(tmp->qm, alg_type); 2273 + if (IS_ERR(qps[i])) { 2274 + hisi_qm_free_qps(qps, i); 2275 + break; 2276 + } 2277 + } 2278 + 2279 + if (i == qp_num) { 2280 + ret = 0; 2281 + break; 2282 + } 2283 + } 2284 + 2285 + mutex_unlock(&qm_list->lock); 2286 + if (ret) 2287 + pr_info("Failed to create qps, node[%d], alg[%d], qp[%d]!\n", 2288 + node, alg_type, qp_num); 2289 + 2290 + err: 2291 + free_list(&head); 2292 + return ret; 2293 + } 2294 + EXPORT_SYMBOL_GPL(hisi_qm_alloc_qps_node); 2182 2295 2183 2296 static pci_ers_result_t qm_dev_err_handle(struct hisi_qm *qm) 2184 2297 {
+31
drivers/crypto/hisilicon/qm.h
··· 145 145 struct hisi_qm_err_info err_info; 146 146 }; 147 147 148 + struct hisi_qm_list { 149 + struct mutex lock; 150 + struct list_head list; 151 + }; 152 + 148 153 struct hisi_qm { 149 154 enum qm_hw_ver ver; 150 155 enum qm_fun_type fun_type; ··· 161 156 u32 qp_num; 162 157 u32 qp_in_used; 163 158 u32 ctrl_qp_num; 159 + struct list_head list; 164 160 165 161 struct qm_dma qdma; 166 162 struct qm_sqc *sqc; ··· 234 228 struct uacce_queue *uacce_q; 235 229 }; 236 230 231 + static inline void hisi_qm_init_list(struct hisi_qm_list *qm_list) 232 + { 233 + INIT_LIST_HEAD(&qm_list->list); 234 + mutex_init(&qm_list->lock); 235 + } 236 + 237 + static inline void hisi_qm_add_to_list(struct hisi_qm *qm, 238 + struct hisi_qm_list *qm_list) 239 + { 240 + mutex_lock(&qm_list->lock); 241 + list_add_tail(&qm->list, &qm_list->list); 242 + mutex_unlock(&qm_list->lock); 243 + } 244 + 245 + static inline void hisi_qm_del_from_list(struct hisi_qm *qm, 246 + struct hisi_qm_list *qm_list) 247 + { 248 + mutex_lock(&qm_list->lock); 249 + list_del(&qm->list); 250 + mutex_unlock(&qm_list->lock); 251 + } 252 + 237 253 int hisi_qm_init(struct hisi_qm *qm); 238 254 void hisi_qm_uninit(struct hisi_qm *qm); 239 255 int hisi_qm_start(struct hisi_qm *qm); ··· 286 258 u32 count, u32 sge_nr); 287 259 void hisi_acc_free_sgl_pool(struct device *dev, 288 260 struct hisi_acc_sgl_pool *pool); 261 + int hisi_qm_alloc_qps_node(struct hisi_qm_list *qm_list, int qp_num, 262 + u8 alg_type, int node, struct hisi_qp **qps); 263 + void hisi_qm_free_qps(struct hisi_qp **qps, int qp_num); 289 264 #endif