@@ -272,6 +272,12 @@ struct qm_doorbell {
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 ,
@@ -2174,6 +2180,125 @@ void hisi_qm_dev_err_uninit(struct hisi_qm *qm)
2174
2180
}
2175
2181
EXPORT_SYMBOL_GPL (hisi_qm_dev_err_uninit );
2176
2182
2183
+ /**
2184
+ * hisi_qm_free_qps() - free multiple queue pairs.
2185
+ * @qps: The queue pairs need to be freed.
2186
+ * @qp_num: The num of queue pairs.
2187
+ */
2188
+ void hisi_qm_free_qps (struct hisi_qp * * qps , int qp_num )
2189
+ {
2190
+ int i ;
2191
+
2192
+ if (!qps || qp_num <= 0 )
2193
+ return ;
2194
+
2195
+ for (i = qp_num - 1 ; i >= 0 ; i -- )
2196
+ hisi_qm_release_qp (qps [i ]);
2197
+ }
2198
+ EXPORT_SYMBOL_GPL (hisi_qm_free_qps );
2199
+
2200
+ static void free_list (struct list_head * head )
2201
+ {
2202
+ struct hisi_qm_resource * res , * tmp ;
2203
+
2204
+ list_for_each_entry_safe (res , tmp , head , list ) {
2205
+ list_del (& res -> list );
2206
+ kfree (res );
2207
+ }
2208
+ }
2209
+
2210
+ static int hisi_qm_sort_devices (int node , struct list_head * head ,
2211
+ struct hisi_qm_list * qm_list )
2212
+ {
2213
+ struct hisi_qm_resource * res , * tmp ;
2214
+ struct hisi_qm * qm ;
2215
+ struct list_head * n ;
2216
+ struct device * dev ;
2217
+ int dev_node = 0 ;
2218
+
2219
+ list_for_each_entry (qm , & qm_list -> list , list ) {
2220
+ dev = & qm -> pdev -> dev ;
2221
+
2222
+ if (IS_ENABLED (CONFIG_NUMA )) {
2223
+ dev_node = dev_to_node (dev );
2224
+ if (dev_node < 0 )
2225
+ dev_node = 0 ;
2226
+ }
2227
+
2228
+ res = kzalloc (sizeof (* res ), GFP_KERNEL );
2229
+ if (!res )
2230
+ return - ENOMEM ;
2231
+
2232
+ res -> qm = qm ;
2233
+ res -> distance = node_distance (dev_node , node );
2234
+ n = head ;
2235
+ list_for_each_entry (tmp , head , list ) {
2236
+ if (res -> distance < tmp -> distance ) {
2237
+ n = & tmp -> list ;
2238
+ break ;
2239
+ }
2240
+ }
2241
+ list_add_tail (& res -> list , n );
2242
+ }
2243
+
2244
+ return 0 ;
2245
+ }
2246
+
2247
+ /**
2248
+ * hisi_qm_alloc_qps_node() - Create multiple queue pairs.
2249
+ * @qm_list: The list of all available devices.
2250
+ * @qp_num: The number of queue pairs need created.
2251
+ * @alg_type: The algorithm type.
2252
+ * @node: The numa node.
2253
+ * @qps: The queue pairs need created.
2254
+ *
2255
+ * This function will sort all available device according to numa distance.
2256
+ * Then try to create all queue pairs from one device, if all devices do
2257
+ * not meet the requirements will return error.
2258
+ */
2259
+ int hisi_qm_alloc_qps_node (struct hisi_qm_list * qm_list , int qp_num ,
2260
+ u8 alg_type , int node , struct hisi_qp * * qps )
2261
+ {
2262
+ struct hisi_qm_resource * tmp ;
2263
+ int ret = - ENODEV ;
2264
+ LIST_HEAD (head );
2265
+ int i ;
2266
+
2267
+ if (!qps || !qm_list || qp_num <= 0 )
2268
+ return - EINVAL ;
2269
+
2270
+ mutex_lock (& qm_list -> lock );
2271
+ if (hisi_qm_sort_devices (node , & head , qm_list )) {
2272
+ mutex_unlock (& qm_list -> lock );
2273
+ goto err ;
2274
+ }
2275
+
2276
+ list_for_each_entry (tmp , & head , list ) {
2277
+ for (i = 0 ; i < qp_num ; i ++ ) {
2278
+ qps [i ] = hisi_qm_create_qp (tmp -> qm , alg_type );
2279
+ if (IS_ERR (qps [i ])) {
2280
+ hisi_qm_free_qps (qps , i );
2281
+ break ;
2282
+ }
2283
+ }
2284
+
2285
+ if (i == qp_num ) {
2286
+ ret = 0 ;
2287
+ break ;
2288
+ }
2289
+ }
2290
+
2291
+ mutex_unlock (& qm_list -> lock );
2292
+ if (ret )
2293
+ pr_info ("Failed to create qps, node[%d], alg[%d], qp[%d]!\n" ,
2294
+ node , alg_type , qp_num );
2295
+
2296
+ err :
2297
+ free_list (& head );
2298
+ return ret ;
2299
+ }
2300
+ EXPORT_SYMBOL_GPL (hisi_qm_alloc_qps_node );
2301
+
2177
2302
static pci_ers_result_t qm_dev_err_handle (struct hisi_qm * qm )
2178
2303
{
2179
2304
u32 err_sts ;
0 commit comments