GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / infiniband / hw / i40iw / i40iw_hmc.c
1 /*******************************************************************************
2 *
3 * Copyright (c) 2015-2016 Intel Corporation.  All rights reserved.
4 *
5 * This software is available to you under a choice of one of two
6 * licenses.  You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenFabrics.org BSD license below:
10 *
11 *   Redistribution and use in source and binary forms, with or
12 *   without modification, are permitted provided that the following
13 *   conditions are met:
14 *
15 *    - Redistributions of source code must retain the above
16 *       copyright notice, this list of conditions and the following
17 *       disclaimer.
18 *
19 *    - Redistributions in binary form must reproduce the above
20 *       copyright notice, this list of conditions and the following
21 *       disclaimer in the documentation and/or other materials
22 *       provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 *
33 *******************************************************************************/
34
35 #include "i40iw_osdep.h"
36 #include "i40iw_register.h"
37 #include "i40iw_status.h"
38 #include "i40iw_hmc.h"
39 #include "i40iw_d.h"
40 #include "i40iw_type.h"
41 #include "i40iw_p.h"
42 #include "i40iw_vf.h"
43 #include "i40iw_virtchnl.h"
44
45 /**
46  * i40iw_find_sd_index_limit - finds segment descriptor index limit
47  * @hmc_info: pointer to the HMC configuration information structure
48  * @type: type of HMC resources we're searching
49  * @index: starting index for the object
50  * @cnt: number of objects we're trying to create
51  * @sd_idx: pointer to return index of the segment descriptor in question
52  * @sd_limit: pointer to return the maximum number of segment descriptors
53  *
54  * This function calculates the segment descriptor index and index limit
55  * for the resource defined by i40iw_hmc_rsrc_type.
56  */
57
58 static inline void i40iw_find_sd_index_limit(struct i40iw_hmc_info *hmc_info,
59                                              u32 type,
60                                              u32 idx,
61                                              u32 cnt,
62                                              u32 *sd_idx,
63                                              u32 *sd_limit)
64 {
65         u64 fpm_addr, fpm_limit;
66
67         fpm_addr = hmc_info->hmc_obj[(type)].base +
68                         hmc_info->hmc_obj[type].size * idx;
69         fpm_limit = fpm_addr + hmc_info->hmc_obj[type].size * cnt;
70         *sd_idx = (u32)(fpm_addr / I40IW_HMC_DIRECT_BP_SIZE);
71         *sd_limit = (u32)((fpm_limit - 1) / I40IW_HMC_DIRECT_BP_SIZE);
72         *sd_limit += 1;
73 }
74
75 /**
76  * i40iw_find_pd_index_limit - finds page descriptor index limit
77  * @hmc_info: pointer to the HMC configuration information struct
78  * @type: HMC resource type we're examining
79  * @idx: starting index for the object
80  * @cnt: number of objects we're trying to create
81  * @pd_index: pointer to return page descriptor index
82  * @pd_limit: pointer to return page descriptor index limit
83  *
84  * Calculates the page descriptor index and index limit for the resource
85  * defined by i40iw_hmc_rsrc_type.
86  */
87
88 static inline void i40iw_find_pd_index_limit(struct i40iw_hmc_info *hmc_info,
89                                              u32 type,
90                                              u32 idx,
91                                              u32 cnt,
92                                              u32 *pd_idx,
93                                              u32 *pd_limit)
94 {
95         u64 fpm_adr, fpm_limit;
96
97         fpm_adr = hmc_info->hmc_obj[type].base +
98                         hmc_info->hmc_obj[type].size * idx;
99         fpm_limit = fpm_adr + (hmc_info)->hmc_obj[(type)].size * (cnt);
100         *(pd_idx) = (u32)(fpm_adr / I40IW_HMC_PAGED_BP_SIZE);
101         *(pd_limit) = (u32)((fpm_limit - 1) / I40IW_HMC_PAGED_BP_SIZE);
102         *(pd_limit) += 1;
103 }
104
105 /**
106  * i40iw_set_sd_entry - setup entry for sd programming
107  * @pa: physical addr
108  * @idx: sd index
109  * @type: paged or direct sd
110  * @entry: sd entry ptr
111  */
112 static inline void i40iw_set_sd_entry(u64 pa,
113                                       u32 idx,
114                                       enum i40iw_sd_entry_type type,
115                                       struct update_sd_entry *entry)
116 {
117         entry->data = pa | (I40IW_HMC_MAX_BP_COUNT << I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) |
118                         (((type == I40IW_SD_TYPE_PAGED) ? 0 : 1) <<
119                                 I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) |
120                         (1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT);
121         entry->cmd = (idx | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT) | (1 << 15));
122 }
123
124 /**
125  * i40iw_clr_sd_entry - setup entry for sd clear
126  * @idx: sd index
127  * @type: paged or direct sd
128  * @entry: sd entry ptr
129  */
130 static inline void i40iw_clr_sd_entry(u32 idx, enum i40iw_sd_entry_type type,
131                                       struct update_sd_entry *entry)
132 {
133         entry->data = (I40IW_HMC_MAX_BP_COUNT <<
134                         I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) |
135                         (((type == I40IW_SD_TYPE_PAGED) ? 0 : 1) <<
136                                 I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT);
137         entry->cmd = (idx | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT) | (1 << 15));
138 }
139
140 /**
141  * i40iw_hmc_sd_one - setup 1 sd entry for cqp
142  * @dev: pointer to the device structure
143  * @hmc_fn_id: hmc's function id
144  * @pa: physical addr
145  * @sd_idx: sd index
146  * @type: paged or direct sd
147  * @setsd: flag to set or clear sd
148  */
149 enum i40iw_status_code i40iw_hmc_sd_one(struct i40iw_sc_dev *dev,
150                                         u8 hmc_fn_id,
151                                         u64 pa, u32 sd_idx,
152                                         enum i40iw_sd_entry_type type,
153                                         bool setsd)
154 {
155         struct i40iw_update_sds_info sdinfo;
156
157         sdinfo.cnt = 1;
158         sdinfo.hmc_fn_id = hmc_fn_id;
159         if (setsd)
160                 i40iw_set_sd_entry(pa, sd_idx, type, sdinfo.entry);
161         else
162                 i40iw_clr_sd_entry(sd_idx, type, sdinfo.entry);
163
164         return dev->cqp->process_cqp_sds(dev, &sdinfo);
165 }
166
167 /**
168  * i40iw_hmc_sd_grp - setup group od sd entries for cqp
169  * @dev: pointer to the device structure
170  * @hmc_info: pointer to the HMC configuration information struct
171  * @sd_index: sd index
172  * @sd_cnt: number of sd entries
173  * @setsd: flag to set or clear sd
174  */
175 static enum i40iw_status_code i40iw_hmc_sd_grp(struct i40iw_sc_dev *dev,
176                                                struct i40iw_hmc_info *hmc_info,
177                                                u32 sd_index,
178                                                u32 sd_cnt,
179                                                bool setsd)
180 {
181         struct i40iw_hmc_sd_entry *sd_entry;
182         struct i40iw_update_sds_info sdinfo;
183         u64 pa;
184         u32 i;
185         enum i40iw_status_code ret_code = 0;
186
187         memset(&sdinfo, 0, sizeof(sdinfo));
188         sdinfo.hmc_fn_id = hmc_info->hmc_fn_id;
189         for (i = sd_index; i < sd_index + sd_cnt; i++) {
190                 sd_entry = &hmc_info->sd_table.sd_entry[i];
191                 if (!sd_entry ||
192                     (!sd_entry->valid && setsd) ||
193                     (sd_entry->valid && !setsd))
194                         continue;
195                 if (setsd) {
196                         pa = (sd_entry->entry_type == I40IW_SD_TYPE_PAGED) ?
197                             sd_entry->u.pd_table.pd_page_addr.pa :
198                             sd_entry->u.bp.addr.pa;
199                         i40iw_set_sd_entry(pa, i, sd_entry->entry_type,
200                                            &sdinfo.entry[sdinfo.cnt]);
201                 } else {
202                         i40iw_clr_sd_entry(i, sd_entry->entry_type,
203                                            &sdinfo.entry[sdinfo.cnt]);
204                 }
205                 sdinfo.cnt++;
206                 if (sdinfo.cnt == I40IW_MAX_SD_ENTRIES) {
207                         ret_code = dev->cqp->process_cqp_sds(dev, &sdinfo);
208                         if (ret_code) {
209                                 i40iw_debug(dev, I40IW_DEBUG_HMC,
210                                             "i40iw_hmc_sd_grp: sd_programming failed err=%d\n",
211                                             ret_code);
212                                 return ret_code;
213                         }
214                         sdinfo.cnt = 0;
215                 }
216         }
217         if (sdinfo.cnt)
218                 ret_code = dev->cqp->process_cqp_sds(dev, &sdinfo);
219
220         return ret_code;
221 }
222
223 /**
224  * i40iw_vfdev_from_fpm - return vf dev ptr for hmc function id
225  * @dev: pointer to the device structure
226  * @hmc_fn_id: hmc's function id
227  */
228 struct i40iw_vfdev *i40iw_vfdev_from_fpm(struct i40iw_sc_dev *dev, u8 hmc_fn_id)
229 {
230         struct i40iw_vfdev *vf_dev = NULL;
231         u16 idx;
232
233         for (idx = 0; idx < I40IW_MAX_PE_ENABLED_VF_COUNT; idx++) {
234                 if (dev->vf_dev[idx] &&
235                     ((u8)dev->vf_dev[idx]->pmf_index == hmc_fn_id)) {
236                         vf_dev = dev->vf_dev[idx];
237                         break;
238                 }
239         }
240         return vf_dev;
241 }
242
243 /**
244  * i40iw_vf_hmcinfo_from_fpm - get ptr to hmc for func_id
245  * @dev: pointer to the device structure
246  * @hmc_fn_id: hmc's function id
247  */
248 struct i40iw_hmc_info *i40iw_vf_hmcinfo_from_fpm(struct i40iw_sc_dev *dev,
249                                                  u8 hmc_fn_id)
250 {
251         struct i40iw_hmc_info *hmc_info = NULL;
252         u16 idx;
253
254         for (idx = 0; idx < I40IW_MAX_PE_ENABLED_VF_COUNT; idx++) {
255                 if (dev->vf_dev[idx] &&
256                     ((u8)dev->vf_dev[idx]->pmf_index == hmc_fn_id)) {
257                         hmc_info = &dev->vf_dev[idx]->hmc_info;
258                         break;
259                 }
260         }
261         return hmc_info;
262 }
263
264 /**
265  * i40iw_hmc_finish_add_sd_reg - program sd entries for objects
266  * @dev: pointer to the device structure
267  * @info: create obj info
268  */
269 static enum i40iw_status_code i40iw_hmc_finish_add_sd_reg(struct i40iw_sc_dev *dev,
270                                                           struct i40iw_hmc_create_obj_info *info)
271 {
272         if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt)
273                 return I40IW_ERR_INVALID_HMC_OBJ_INDEX;
274
275         if ((info->start_idx + info->count) >
276                         info->hmc_info->hmc_obj[info->rsrc_type].cnt)
277                 return I40IW_ERR_INVALID_HMC_OBJ_COUNT;
278
279         if (!info->add_sd_cnt)
280                 return 0;
281
282         return i40iw_hmc_sd_grp(dev, info->hmc_info,
283                                 info->hmc_info->sd_indexes[0],
284                                 info->add_sd_cnt, true);
285 }
286
287 /**
288  * i40iw_create_iw_hmc_obj - allocate backing store for hmc objects
289  * @dev: pointer to the device structure
290  * @info: pointer to i40iw_hmc_iw_create_obj_info struct
291  *
292  * This will allocate memory for PDs and backing pages and populate
293  * the sd and pd entries.
294  */
295 enum i40iw_status_code i40iw_sc_create_hmc_obj(struct i40iw_sc_dev *dev,
296                                                struct i40iw_hmc_create_obj_info *info)
297 {
298         struct i40iw_hmc_sd_entry *sd_entry;
299         u32 sd_idx, sd_lmt;
300         u32 pd_idx = 0, pd_lmt = 0;
301         u32 pd_idx1 = 0, pd_lmt1 = 0;
302         u32 i, j;
303         bool pd_error = false;
304         enum i40iw_status_code ret_code = 0;
305
306         if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt)
307                 return I40IW_ERR_INVALID_HMC_OBJ_INDEX;
308
309         if ((info->start_idx + info->count) >
310             info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
311                 i40iw_debug(dev, I40IW_DEBUG_HMC,
312                             "%s: error type %u, start = %u, req cnt %u, cnt = %u\n",
313                             __func__, info->rsrc_type, info->start_idx, info->count,
314                             info->hmc_info->hmc_obj[info->rsrc_type].cnt);
315                 return I40IW_ERR_INVALID_HMC_OBJ_COUNT;
316         }
317
318         if (!dev->is_pf)
319                 return i40iw_vchnl_vf_add_hmc_objs(dev, info->rsrc_type, 0, info->count);
320
321         i40iw_find_sd_index_limit(info->hmc_info, info->rsrc_type,
322                                   info->start_idx, info->count,
323                                   &sd_idx, &sd_lmt);
324         if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
325             sd_lmt > info->hmc_info->sd_table.sd_cnt) {
326                 return I40IW_ERR_INVALID_SD_INDEX;
327         }
328         i40iw_find_pd_index_limit(info->hmc_info, info->rsrc_type,
329                                   info->start_idx, info->count, &pd_idx, &pd_lmt);
330
331         for (j = sd_idx; j < sd_lmt; j++) {
332                 ret_code = i40iw_add_sd_table_entry(dev->hw, info->hmc_info,
333                                                     j,
334                                                     info->entry_type,
335                                                     I40IW_HMC_DIRECT_BP_SIZE);
336                 if (ret_code)
337                         goto exit_sd_error;
338                 sd_entry = &info->hmc_info->sd_table.sd_entry[j];
339
340                 if ((sd_entry->entry_type == I40IW_SD_TYPE_PAGED) &&
341                     ((dev->hmc_info == info->hmc_info) &&
342                      (info->rsrc_type != I40IW_HMC_IW_PBLE))) {
343                         pd_idx1 = max(pd_idx, (j * I40IW_HMC_MAX_BP_COUNT));
344                         pd_lmt1 = min(pd_lmt,
345                                       (j + 1) * I40IW_HMC_MAX_BP_COUNT);
346                         for (i = pd_idx1; i < pd_lmt1; i++) {
347                                 /* update the pd table entry */
348                                 ret_code = i40iw_add_pd_table_entry(dev->hw, info->hmc_info,
349                                                                     i, NULL);
350                                 if (ret_code) {
351                                         pd_error = true;
352                                         break;
353                                 }
354                         }
355                         if (pd_error) {
356                                 while (i && (i > pd_idx1)) {
357                                         i40iw_remove_pd_bp(dev->hw, info->hmc_info, (i - 1),
358                                                            info->is_pf);
359                                         i--;
360                                 }
361                         }
362                 }
363                 if (sd_entry->valid)
364                         continue;
365
366                 info->hmc_info->sd_indexes[info->add_sd_cnt] = (u16)j;
367                 info->add_sd_cnt++;
368                 sd_entry->valid = true;
369         }
370         return i40iw_hmc_finish_add_sd_reg(dev, info);
371
372 exit_sd_error:
373         while (j && (j > sd_idx)) {
374                 sd_entry = &info->hmc_info->sd_table.sd_entry[j - 1];
375                 switch (sd_entry->entry_type) {
376                 case I40IW_SD_TYPE_PAGED:
377                         pd_idx1 = max(pd_idx,
378                                       (j - 1) * I40IW_HMC_MAX_BP_COUNT);
379                         pd_lmt1 = min(pd_lmt, (j * I40IW_HMC_MAX_BP_COUNT));
380                         for (i = pd_idx1; i < pd_lmt1; i++)
381                                 i40iw_prep_remove_pd_page(info->hmc_info, i);
382                         break;
383                 case I40IW_SD_TYPE_DIRECT:
384                         i40iw_prep_remove_pd_page(info->hmc_info, (j - 1));
385                         break;
386                 default:
387                         ret_code = I40IW_ERR_INVALID_SD_TYPE;
388                         break;
389                 }
390                 j--;
391         }
392
393         return ret_code;
394 }
395
396 /**
397  * i40iw_finish_del_sd_reg - delete sd entries for objects
398  * @dev: pointer to the device structure
399  * @info: dele obj info
400  * @reset: true if called before reset
401  */
402 static enum i40iw_status_code i40iw_finish_del_sd_reg(struct i40iw_sc_dev *dev,
403                                                       struct i40iw_hmc_del_obj_info *info,
404                                                       bool reset)
405 {
406         struct i40iw_hmc_sd_entry *sd_entry;
407         enum i40iw_status_code ret_code = 0;
408         u32 i, sd_idx;
409         struct i40iw_dma_mem *mem;
410
411         if (dev->is_pf && !reset)
412                 ret_code = i40iw_hmc_sd_grp(dev, info->hmc_info,
413                                             info->hmc_info->sd_indexes[0],
414                                             info->del_sd_cnt, false);
415
416         if (ret_code)
417                 i40iw_debug(dev, I40IW_DEBUG_HMC, "%s: error cqp sd sd_grp\n", __func__);
418
419         for (i = 0; i < info->del_sd_cnt; i++) {
420                 sd_idx = info->hmc_info->sd_indexes[i];
421                 sd_entry = &info->hmc_info->sd_table.sd_entry[sd_idx];
422                 if (!sd_entry)
423                         continue;
424                 mem = (sd_entry->entry_type == I40IW_SD_TYPE_PAGED) ?
425                         &sd_entry->u.pd_table.pd_page_addr :
426                         &sd_entry->u.bp.addr;
427
428                 if (!mem || !mem->va)
429                         i40iw_debug(dev, I40IW_DEBUG_HMC, "%s: error cqp sd mem\n", __func__);
430                 else
431                         i40iw_free_dma_mem(dev->hw, mem);
432         }
433         return ret_code;
434 }
435
436 /**
437  * i40iw_del_iw_hmc_obj - remove pe hmc objects
438  * @dev: pointer to the device structure
439  * @info: pointer to i40iw_hmc_del_obj_info struct
440  * @reset: true if called before reset
441  *
442  * This will de-populate the SDs and PDs.  It frees
443  * the memory for PDS and backing storage.  After this function is returned,
444  * caller should deallocate memory allocated previously for
445  * book-keeping information about PDs and backing storage.
446  */
447 enum i40iw_status_code i40iw_sc_del_hmc_obj(struct i40iw_sc_dev *dev,
448                                             struct i40iw_hmc_del_obj_info *info,
449                                             bool reset)
450 {
451         struct i40iw_hmc_pd_table *pd_table;
452         u32 sd_idx, sd_lmt;
453         u32 pd_idx, pd_lmt, rel_pd_idx;
454         u32 i, j;
455         enum i40iw_status_code ret_code = 0;
456
457         if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
458                 i40iw_debug(dev, I40IW_DEBUG_HMC,
459                             "%s: error start_idx[%04d]  >= [type %04d].cnt[%04d]\n",
460                             __func__, info->start_idx, info->rsrc_type,
461                             info->hmc_info->hmc_obj[info->rsrc_type].cnt);
462                 return I40IW_ERR_INVALID_HMC_OBJ_INDEX;
463         }
464
465         if ((info->start_idx + info->count) >
466             info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
467                 i40iw_debug(dev, I40IW_DEBUG_HMC,
468                             "%s: error start_idx[%04d] + count %04d  >= [type %04d].cnt[%04d]\n",
469                             __func__, info->start_idx, info->count,
470                             info->rsrc_type,
471                             info->hmc_info->hmc_obj[info->rsrc_type].cnt);
472                 return I40IW_ERR_INVALID_HMC_OBJ_COUNT;
473         }
474         if (!dev->is_pf) {
475                 ret_code = i40iw_vchnl_vf_del_hmc_obj(dev, info->rsrc_type, 0,
476                                                       info->count);
477                 if (info->rsrc_type != I40IW_HMC_IW_PBLE)
478                         return ret_code;
479         }
480
481         i40iw_find_pd_index_limit(info->hmc_info, info->rsrc_type,
482                                   info->start_idx, info->count, &pd_idx, &pd_lmt);
483
484         for (j = pd_idx; j < pd_lmt; j++) {
485                 sd_idx = j / I40IW_HMC_PD_CNT_IN_SD;
486
487                 if (info->hmc_info->sd_table.sd_entry[sd_idx].entry_type !=
488                     I40IW_SD_TYPE_PAGED)
489                         continue;
490
491                 rel_pd_idx = j % I40IW_HMC_PD_CNT_IN_SD;
492                 pd_table = &info->hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
493                 if (pd_table->pd_entry[rel_pd_idx].valid) {
494                         ret_code = i40iw_remove_pd_bp(dev->hw, info->hmc_info, j,
495                                                       info->is_pf);
496                         if (ret_code) {
497                                 i40iw_debug(dev, I40IW_DEBUG_HMC, "%s: error\n", __func__);
498                                 return ret_code;
499                         }
500                 }
501         }
502
503         i40iw_find_sd_index_limit(info->hmc_info, info->rsrc_type,
504                                   info->start_idx, info->count, &sd_idx, &sd_lmt);
505         if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
506             sd_lmt > info->hmc_info->sd_table.sd_cnt) {
507                 i40iw_debug(dev, I40IW_DEBUG_HMC, "%s: error invalid sd_idx\n", __func__);
508                 return I40IW_ERR_INVALID_SD_INDEX;
509         }
510
511         for (i = sd_idx; i < sd_lmt; i++) {
512                 if (!info->hmc_info->sd_table.sd_entry[i].valid)
513                         continue;
514                 switch (info->hmc_info->sd_table.sd_entry[i].entry_type) {
515                 case I40IW_SD_TYPE_DIRECT:
516                         ret_code = i40iw_prep_remove_sd_bp(info->hmc_info, i);
517                         if (!ret_code) {
518                                 info->hmc_info->sd_indexes[info->del_sd_cnt] = (u16)i;
519                                 info->del_sd_cnt++;
520                         }
521                         break;
522                 case I40IW_SD_TYPE_PAGED:
523                         ret_code = i40iw_prep_remove_pd_page(info->hmc_info, i);
524                         if (!ret_code) {
525                                 info->hmc_info->sd_indexes[info->del_sd_cnt] = (u16)i;
526                                 info->del_sd_cnt++;
527                         }
528                         break;
529                 default:
530                         break;
531                 }
532         }
533         return i40iw_finish_del_sd_reg(dev, info, reset);
534 }
535
536 /**
537  * i40iw_add_sd_table_entry - Adds a segment descriptor to the table
538  * @hw: pointer to our hw struct
539  * @hmc_info: pointer to the HMC configuration information struct
540  * @sd_index: segment descriptor index to manipulate
541  * @type: what type of segment descriptor we're manipulating
542  * @direct_mode_sz: size to alloc in direct mode
543  */
544 enum i40iw_status_code i40iw_add_sd_table_entry(struct i40iw_hw *hw,
545                                                 struct i40iw_hmc_info *hmc_info,
546                                                 u32 sd_index,
547                                                 enum i40iw_sd_entry_type type,
548                                                 u64 direct_mode_sz)
549 {
550         enum i40iw_status_code ret_code = 0;
551         struct i40iw_hmc_sd_entry *sd_entry;
552         bool dma_mem_alloc_done = false;
553         struct i40iw_dma_mem mem;
554         u64 alloc_len;
555
556         sd_entry = &hmc_info->sd_table.sd_entry[sd_index];
557         if (!sd_entry->valid) {
558                 if (type == I40IW_SD_TYPE_PAGED)
559                         alloc_len = I40IW_HMC_PAGED_BP_SIZE;
560                 else
561                         alloc_len = direct_mode_sz;
562
563                 /* allocate a 4K pd page or 2M backing page */
564                 ret_code = i40iw_allocate_dma_mem(hw, &mem, alloc_len,
565                                                   I40IW_HMC_PD_BP_BUF_ALIGNMENT);
566                 if (ret_code)
567                         goto exit;
568                 dma_mem_alloc_done = true;
569                 if (type == I40IW_SD_TYPE_PAGED) {
570                         ret_code = i40iw_allocate_virt_mem(hw,
571                                                            &sd_entry->u.pd_table.pd_entry_virt_mem,
572                                                            sizeof(struct i40iw_hmc_pd_entry) * 512);
573                         if (ret_code)
574                                 goto exit;
575                         sd_entry->u.pd_table.pd_entry = (struct i40iw_hmc_pd_entry *)
576                                                          sd_entry->u.pd_table.pd_entry_virt_mem.va;
577
578                         memcpy(&sd_entry->u.pd_table.pd_page_addr, &mem, sizeof(struct i40iw_dma_mem));
579                 } else {
580                         memcpy(&sd_entry->u.bp.addr, &mem, sizeof(struct i40iw_dma_mem));
581                         sd_entry->u.bp.sd_pd_index = sd_index;
582                 }
583
584                 hmc_info->sd_table.sd_entry[sd_index].entry_type = type;
585
586                 I40IW_INC_SD_REFCNT(&hmc_info->sd_table);
587         }
588         if (sd_entry->entry_type == I40IW_SD_TYPE_DIRECT)
589                 I40IW_INC_BP_REFCNT(&sd_entry->u.bp);
590 exit:
591         if (ret_code)
592                 if (dma_mem_alloc_done)
593                         i40iw_free_dma_mem(hw, &mem);
594
595         return ret_code;
596 }
597
598 /**
599  * i40iw_add_pd_table_entry - Adds page descriptor to the specified table
600  * @hw: pointer to our HW structure
601  * @hmc_info: pointer to the HMC configuration information structure
602  * @pd_index: which page descriptor index to manipulate
603  * @rsrc_pg: if not NULL, use preallocated page instead of allocating new one.
604  *
605  * This function:
606  *      1. Initializes the pd entry
607  *      2. Adds pd_entry in the pd_table
608  *      3. Mark the entry valid in i40iw_hmc_pd_entry structure
609  *      4. Initializes the pd_entry's ref count to 1
610  * assumptions:
611  *      1. The memory for pd should be pinned down, physically contiguous and
612  *         aligned on 4K boundary and zeroed memory.
613  *      2. It should be 4K in size.
614  */
615 enum i40iw_status_code i40iw_add_pd_table_entry(struct i40iw_hw *hw,
616                                                 struct i40iw_hmc_info *hmc_info,
617                                                 u32 pd_index,
618                                                 struct i40iw_dma_mem *rsrc_pg)
619 {
620         enum i40iw_status_code ret_code = 0;
621         struct i40iw_hmc_pd_table *pd_table;
622         struct i40iw_hmc_pd_entry *pd_entry;
623         struct i40iw_dma_mem mem;
624         struct i40iw_dma_mem *page = &mem;
625         u32 sd_idx, rel_pd_idx;
626         u64 *pd_addr;
627         u64 page_desc;
628
629         if (pd_index / I40IW_HMC_PD_CNT_IN_SD >= hmc_info->sd_table.sd_cnt)
630                 return I40IW_ERR_INVALID_PAGE_DESC_INDEX;
631
632         sd_idx = (pd_index / I40IW_HMC_PD_CNT_IN_SD);
633         if (hmc_info->sd_table.sd_entry[sd_idx].entry_type != I40IW_SD_TYPE_PAGED)
634                 return 0;
635
636         rel_pd_idx = (pd_index % I40IW_HMC_PD_CNT_IN_SD);
637         pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
638         pd_entry = &pd_table->pd_entry[rel_pd_idx];
639         if (!pd_entry->valid) {
640                 if (rsrc_pg) {
641                         pd_entry->rsrc_pg = true;
642                         page = rsrc_pg;
643                 } else {
644                         ret_code = i40iw_allocate_dma_mem(hw, page,
645                                                           I40IW_HMC_PAGED_BP_SIZE,
646                                                           I40IW_HMC_PD_BP_BUF_ALIGNMENT);
647                         if (ret_code)
648                                 return ret_code;
649                         pd_entry->rsrc_pg = false;
650                 }
651
652                 memcpy(&pd_entry->bp.addr, page, sizeof(struct i40iw_dma_mem));
653                 pd_entry->bp.sd_pd_index = pd_index;
654                 pd_entry->bp.entry_type = I40IW_SD_TYPE_PAGED;
655                 page_desc = page->pa | 0x1;
656
657                 pd_addr = (u64 *)pd_table->pd_page_addr.va;
658                 pd_addr += rel_pd_idx;
659
660                 memcpy(pd_addr, &page_desc, sizeof(*pd_addr));
661
662                 pd_entry->sd_index = sd_idx;
663                 pd_entry->valid = true;
664                 I40IW_INC_PD_REFCNT(pd_table);
665                 if (hmc_info->hmc_fn_id < I40IW_FIRST_VF_FPM_ID)
666                         I40IW_INVALIDATE_PF_HMC_PD(hw, sd_idx, rel_pd_idx);
667                 else if (hw->hmc.hmc_fn_id != hmc_info->hmc_fn_id)
668                         I40IW_INVALIDATE_VF_HMC_PD(hw, sd_idx, rel_pd_idx,
669                                                    hmc_info->hmc_fn_id);
670         }
671         I40IW_INC_BP_REFCNT(&pd_entry->bp);
672
673         return 0;
674 }
675
676 /**
677  * i40iw_remove_pd_bp - remove a backing page from a page descriptor
678  * @hw: pointer to our HW structure
679  * @hmc_info: pointer to the HMC configuration information structure
680  * @idx: the page index
681  * @is_pf: distinguishes a VF from a PF
682  *
683  * This function:
684  *      1. Marks the entry in pd table (for paged address mode) or in sd table
685  *         (for direct address mode) invalid.
686  *      2. Write to register PMPDINV to invalidate the backing page in FV cache
687  *      3. Decrement the ref count for the pd _entry
688  * assumptions:
689  *      1. Caller can deallocate the memory used by backing storage after this
690  *         function returns.
691  */
692 enum i40iw_status_code i40iw_remove_pd_bp(struct i40iw_hw *hw,
693                                           struct i40iw_hmc_info *hmc_info,
694                                           u32 idx,
695                                           bool is_pf)
696 {
697         struct i40iw_hmc_pd_entry *pd_entry;
698         struct i40iw_hmc_pd_table *pd_table;
699         struct i40iw_hmc_sd_entry *sd_entry;
700         u32 sd_idx, rel_pd_idx;
701         struct i40iw_dma_mem *mem;
702         u64 *pd_addr;
703
704         sd_idx = idx / I40IW_HMC_PD_CNT_IN_SD;
705         rel_pd_idx = idx % I40IW_HMC_PD_CNT_IN_SD;
706         if (sd_idx >= hmc_info->sd_table.sd_cnt)
707                 return I40IW_ERR_INVALID_PAGE_DESC_INDEX;
708
709         sd_entry = &hmc_info->sd_table.sd_entry[sd_idx];
710         if (sd_entry->entry_type != I40IW_SD_TYPE_PAGED)
711                 return I40IW_ERR_INVALID_SD_TYPE;
712
713         pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
714         pd_entry = &pd_table->pd_entry[rel_pd_idx];
715         I40IW_DEC_BP_REFCNT(&pd_entry->bp);
716         if (pd_entry->bp.ref_cnt)
717                 return 0;
718
719         pd_entry->valid = false;
720         I40IW_DEC_PD_REFCNT(pd_table);
721         pd_addr = (u64 *)pd_table->pd_page_addr.va;
722         pd_addr += rel_pd_idx;
723         memset(pd_addr, 0, sizeof(u64));
724         if (is_pf)
725                 I40IW_INVALIDATE_PF_HMC_PD(hw, sd_idx, idx);
726         else
727                 I40IW_INVALIDATE_VF_HMC_PD(hw, sd_idx, idx,
728                                            hmc_info->hmc_fn_id);
729
730         if (!pd_entry->rsrc_pg) {
731                 mem = &pd_entry->bp.addr;
732                 if (!mem || !mem->va)
733                         return I40IW_ERR_PARAM;
734                 i40iw_free_dma_mem(hw, mem);
735         }
736         if (!pd_table->ref_cnt)
737                 i40iw_free_virt_mem(hw, &pd_table->pd_entry_virt_mem);
738
739         return 0;
740 }
741
742 /**
743  * i40iw_prep_remove_sd_bp - Prepares to remove a backing page from a sd entry
744  * @hmc_info: pointer to the HMC configuration information structure
745  * @idx: the page index
746  */
747 enum i40iw_status_code i40iw_prep_remove_sd_bp(struct i40iw_hmc_info *hmc_info, u32 idx)
748 {
749         struct i40iw_hmc_sd_entry *sd_entry;
750
751         sd_entry = &hmc_info->sd_table.sd_entry[idx];
752         I40IW_DEC_BP_REFCNT(&sd_entry->u.bp);
753         if (sd_entry->u.bp.ref_cnt)
754                 return I40IW_ERR_NOT_READY;
755
756         I40IW_DEC_SD_REFCNT(&hmc_info->sd_table);
757         sd_entry->valid = false;
758
759         return 0;
760 }
761
762 /**
763  * i40iw_prep_remove_pd_page - Prepares to remove a PD page from sd entry.
764  * @hmc_info: pointer to the HMC configuration information structure
765  * @idx: segment descriptor index to find the relevant page descriptor
766  */
767 enum i40iw_status_code i40iw_prep_remove_pd_page(struct i40iw_hmc_info *hmc_info,
768                                                  u32 idx)
769 {
770         struct i40iw_hmc_sd_entry *sd_entry;
771
772         sd_entry = &hmc_info->sd_table.sd_entry[idx];
773
774         if (sd_entry->u.pd_table.ref_cnt)
775                 return I40IW_ERR_NOT_READY;
776
777         sd_entry->valid = false;
778         I40IW_DEC_SD_REFCNT(&hmc_info->sd_table);
779
780         return 0;
781 }
782
783 /**
784  * i40iw_pf_init_vfhmc -
785  * @vf_cnt_array: array of cnt values of iwarp hmc objects
786  * @vf_hmc_fn_id: hmc function id ofr vf driver
787  * @dev: pointer to i40iw_dev struct
788  *
789  * Called by pf driver to initialize hmc_info for vf driver instance.
790  */
791 enum i40iw_status_code i40iw_pf_init_vfhmc(struct i40iw_sc_dev *dev,
792                                            u8 vf_hmc_fn_id,
793                                            u32 *vf_cnt_array)
794 {
795         struct i40iw_hmc_info *hmc_info;
796         enum i40iw_status_code ret_code = 0;
797         u32 i;
798
799         if ((vf_hmc_fn_id < I40IW_FIRST_VF_FPM_ID) ||
800             (vf_hmc_fn_id >= I40IW_FIRST_VF_FPM_ID +
801              I40IW_MAX_PE_ENABLED_VF_COUNT)) {
802                 i40iw_debug(dev, I40IW_DEBUG_HMC, "%s: invalid vf_hmc_fn_id  0x%x\n",
803                             __func__, vf_hmc_fn_id);
804                 return I40IW_ERR_INVALID_HMCFN_ID;
805         }
806
807         ret_code = i40iw_sc_init_iw_hmc(dev, vf_hmc_fn_id);
808         if (ret_code)
809                 return ret_code;
810
811         hmc_info = i40iw_vf_hmcinfo_from_fpm(dev, vf_hmc_fn_id);
812
813         for (i = I40IW_HMC_IW_QP; i < I40IW_HMC_IW_MAX; i++)
814                 if (vf_cnt_array)
815                         hmc_info->hmc_obj[i].cnt =
816                             vf_cnt_array[i - I40IW_HMC_IW_QP];
817                 else
818                         hmc_info->hmc_obj[i].cnt = hmc_info->hmc_obj[i].max_cnt;
819
820         return 0;
821 }