1 /*******************************************************************************
3 * Copyright (c) 2015-2016 Intel Corporation. All rights reserved.
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:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
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.
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
33 *******************************************************************************/
35 #include "i40iw_osdep.h"
36 #include "i40iw_register.h"
37 #include "i40iw_status.h"
38 #include "i40iw_hmc.h"
40 #include "i40iw_type.h"
43 #include "i40iw_virtchnl.h"
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
54 * This function calculates the segment descriptor index and index limit
55 * for the resource defined by i40iw_hmc_rsrc_type.
58 static inline void i40iw_find_sd_index_limit(struct i40iw_hmc_info
*hmc_info
,
65 u64 fpm_addr
, fpm_limit
;
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
);
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
84 * Calculates the page descriptor index and index limit for the resource
85 * defined by i40iw_hmc_rsrc_type.
88 static inline void i40iw_find_pd_index_limit(struct i40iw_hmc_info
*hmc_info
,
95 u64 fpm_adr
, fpm_limit
;
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
);
106 * i40iw_set_sd_entry - setup entry for sd programming
109 * @type: paged or direct sd
110 * @entry: sd entry ptr
112 static inline void i40iw_set_sd_entry(u64 pa
,
114 enum i40iw_sd_entry_type type
,
115 struct update_sd_entry
*entry
)
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));
125 * i40iw_clr_sd_entry - setup entry for sd clear
127 * @type: paged or direct sd
128 * @entry: sd entry ptr
130 static inline void i40iw_clr_sd_entry(u32 idx
, enum i40iw_sd_entry_type type
,
131 struct update_sd_entry
*entry
)
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));
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
146 * @type: paged or direct sd
147 * @setsd: flag to set or clear sd
149 enum i40iw_status_code
i40iw_hmc_sd_one(struct i40iw_sc_dev
*dev
,
152 enum i40iw_sd_entry_type type
,
155 struct i40iw_update_sds_info sdinfo
;
158 sdinfo
.hmc_fn_id
= hmc_fn_id
;
160 i40iw_set_sd_entry(pa
, sd_idx
, type
, sdinfo
.entry
);
162 i40iw_clr_sd_entry(sd_idx
, type
, sdinfo
.entry
);
164 return dev
->cqp
->process_cqp_sds(dev
, &sdinfo
);
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
175 static enum i40iw_status_code
i40iw_hmc_sd_grp(struct i40iw_sc_dev
*dev
,
176 struct i40iw_hmc_info
*hmc_info
,
181 struct i40iw_hmc_sd_entry
*sd_entry
;
182 struct i40iw_update_sds_info sdinfo
;
185 enum i40iw_status_code ret_code
= 0;
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
];
192 (!sd_entry
->valid
&& setsd
) ||
193 (sd_entry
->valid
&& !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
]);
202 i40iw_clr_sd_entry(i
, sd_entry
->entry_type
,
203 &sdinfo
.entry
[sdinfo
.cnt
]);
206 if (sdinfo
.cnt
== I40IW_MAX_SD_ENTRIES
) {
207 ret_code
= dev
->cqp
->process_cqp_sds(dev
, &sdinfo
);
209 i40iw_debug(dev
, I40IW_DEBUG_HMC
,
210 "i40iw_hmc_sd_grp: sd_programming failed err=%d\n",
218 ret_code
= dev
->cqp
->process_cqp_sds(dev
, &sdinfo
);
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
228 struct i40iw_vfdev
*i40iw_vfdev_from_fpm(struct i40iw_sc_dev
*dev
, u8 hmc_fn_id
)
230 struct i40iw_vfdev
*vf_dev
= NULL
;
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
];
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
248 struct i40iw_hmc_info
*i40iw_vf_hmcinfo_from_fpm(struct i40iw_sc_dev
*dev
,
251 struct i40iw_hmc_info
*hmc_info
= NULL
;
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
;
265 * i40iw_hmc_finish_add_sd_reg - program sd entries for objects
266 * @dev: pointer to the device structure
267 * @info: create obj info
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
)
272 if (info
->start_idx
>= info
->hmc_info
->hmc_obj
[info
->rsrc_type
].cnt
)
273 return I40IW_ERR_INVALID_HMC_OBJ_INDEX
;
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
;
279 if (!info
->add_sd_cnt
)
282 return i40iw_hmc_sd_grp(dev
, info
->hmc_info
,
283 info
->hmc_info
->sd_indexes
[0],
284 info
->add_sd_cnt
, true);
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
292 * This will allocate memory for PDs and backing pages and populate
293 * the sd and pd entries.
295 enum i40iw_status_code
i40iw_sc_create_hmc_obj(struct i40iw_sc_dev
*dev
,
296 struct i40iw_hmc_create_obj_info
*info
)
298 struct i40iw_hmc_sd_entry
*sd_entry
;
300 u32 pd_idx
= 0, pd_lmt
= 0;
301 u32 pd_idx1
= 0, pd_lmt1
= 0;
303 bool pd_error
= false;
304 enum i40iw_status_code ret_code
= 0;
306 if (info
->start_idx
>= info
->hmc_info
->hmc_obj
[info
->rsrc_type
].cnt
)
307 return I40IW_ERR_INVALID_HMC_OBJ_INDEX
;
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
;
319 return i40iw_vchnl_vf_add_hmc_objs(dev
, info
->rsrc_type
, 0, info
->count
);
321 i40iw_find_sd_index_limit(info
->hmc_info
, info
->rsrc_type
,
322 info
->start_idx
, info
->count
,
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
;
328 i40iw_find_pd_index_limit(info
->hmc_info
, info
->rsrc_type
,
329 info
->start_idx
, info
->count
, &pd_idx
, &pd_lmt
);
331 for (j
= sd_idx
; j
< sd_lmt
; j
++) {
332 ret_code
= i40iw_add_sd_table_entry(dev
->hw
, info
->hmc_info
,
335 I40IW_HMC_DIRECT_BP_SIZE
);
338 sd_entry
= &info
->hmc_info
->sd_table
.sd_entry
[j
];
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
,
356 while (i
&& (i
> pd_idx1
)) {
357 i40iw_remove_pd_bp(dev
->hw
, info
->hmc_info
, (i
- 1),
366 info
->hmc_info
->sd_indexes
[info
->add_sd_cnt
] = (u16
)j
;
368 sd_entry
->valid
= true;
370 return i40iw_hmc_finish_add_sd_reg(dev
, info
);
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
);
383 case I40IW_SD_TYPE_DIRECT
:
384 i40iw_prep_remove_pd_page(info
->hmc_info
, (j
- 1));
387 ret_code
= I40IW_ERR_INVALID_SD_TYPE
;
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
402 static enum i40iw_status_code
i40iw_finish_del_sd_reg(struct i40iw_sc_dev
*dev
,
403 struct i40iw_hmc_del_obj_info
*info
,
406 struct i40iw_hmc_sd_entry
*sd_entry
;
407 enum i40iw_status_code ret_code
= 0;
409 struct i40iw_dma_mem
*mem
;
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);
417 i40iw_debug(dev
, I40IW_DEBUG_HMC
, "%s: error cqp sd sd_grp\n", __func__
);
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
];
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
;
428 if (!mem
|| !mem
->va
)
429 i40iw_debug(dev
, I40IW_DEBUG_HMC
, "%s: error cqp sd mem\n", __func__
);
431 i40iw_free_dma_mem(dev
->hw
, mem
);
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
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.
447 enum i40iw_status_code
i40iw_sc_del_hmc_obj(struct i40iw_sc_dev
*dev
,
448 struct i40iw_hmc_del_obj_info
*info
,
451 struct i40iw_hmc_pd_table
*pd_table
;
453 u32 pd_idx
, pd_lmt
, rel_pd_idx
;
455 enum i40iw_status_code ret_code
= 0;
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
;
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
,
471 info
->hmc_info
->hmc_obj
[info
->rsrc_type
].cnt
);
472 return I40IW_ERR_INVALID_HMC_OBJ_COUNT
;
475 ret_code
= i40iw_vchnl_vf_del_hmc_obj(dev
, info
->rsrc_type
, 0,
477 if (info
->rsrc_type
!= I40IW_HMC_IW_PBLE
)
481 i40iw_find_pd_index_limit(info
->hmc_info
, info
->rsrc_type
,
482 info
->start_idx
, info
->count
, &pd_idx
, &pd_lmt
);
484 for (j
= pd_idx
; j
< pd_lmt
; j
++) {
485 sd_idx
= j
/ I40IW_HMC_PD_CNT_IN_SD
;
487 if (info
->hmc_info
->sd_table
.sd_entry
[sd_idx
].entry_type
!=
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
,
497 i40iw_debug(dev
, I40IW_DEBUG_HMC
, "%s: error\n", __func__
);
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
;
511 for (i
= sd_idx
; i
< sd_lmt
; i
++) {
512 if (!info
->hmc_info
->sd_table
.sd_entry
[i
].valid
)
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
);
518 info
->hmc_info
->sd_indexes
[info
->del_sd_cnt
] = (u16
)i
;
522 case I40IW_SD_TYPE_PAGED
:
523 ret_code
= i40iw_prep_remove_pd_page(info
->hmc_info
, i
);
525 info
->hmc_info
->sd_indexes
[info
->del_sd_cnt
] = (u16
)i
;
533 return i40iw_finish_del_sd_reg(dev
, info
, reset
);
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
544 enum i40iw_status_code
i40iw_add_sd_table_entry(struct i40iw_hw
*hw
,
545 struct i40iw_hmc_info
*hmc_info
,
547 enum i40iw_sd_entry_type type
,
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
;
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
;
561 alloc_len
= direct_mode_sz
;
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
);
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);
575 sd_entry
->u
.pd_table
.pd_entry
= (struct i40iw_hmc_pd_entry
*)
576 sd_entry
->u
.pd_table
.pd_entry_virt_mem
.va
;
578 memcpy(&sd_entry
->u
.pd_table
.pd_page_addr
, &mem
, sizeof(struct i40iw_dma_mem
));
580 memcpy(&sd_entry
->u
.bp
.addr
, &mem
, sizeof(struct i40iw_dma_mem
));
581 sd_entry
->u
.bp
.sd_pd_index
= sd_index
;
584 hmc_info
->sd_table
.sd_entry
[sd_index
].entry_type
= type
;
586 I40IW_INC_SD_REFCNT(&hmc_info
->sd_table
);
588 if (sd_entry
->entry_type
== I40IW_SD_TYPE_DIRECT
)
589 I40IW_INC_BP_REFCNT(&sd_entry
->u
.bp
);
592 if (dma_mem_alloc_done
)
593 i40iw_free_dma_mem(hw
, &mem
);
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.
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
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.
615 enum i40iw_status_code
i40iw_add_pd_table_entry(struct i40iw_hw
*hw
,
616 struct i40iw_hmc_info
*hmc_info
,
618 struct i40iw_dma_mem
*rsrc_pg
)
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
;
629 if (pd_index
/ I40IW_HMC_PD_CNT_IN_SD
>= hmc_info
->sd_table
.sd_cnt
)
630 return I40IW_ERR_INVALID_PAGE_DESC_INDEX
;
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
)
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
) {
641 pd_entry
->rsrc_pg
= true;
644 ret_code
= i40iw_allocate_dma_mem(hw
, page
,
645 I40IW_HMC_PAGED_BP_SIZE
,
646 I40IW_HMC_PD_BP_BUF_ALIGNMENT
);
649 pd_entry
->rsrc_pg
= false;
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;
657 pd_addr
= (u64
*)pd_table
->pd_page_addr
.va
;
658 pd_addr
+= rel_pd_idx
;
660 memcpy(pd_addr
, &page_desc
, sizeof(*pd_addr
));
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
);
671 I40IW_INC_BP_REFCNT(&pd_entry
->bp
);
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
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
689 * 1. Caller can deallocate the memory used by backing storage after this
692 enum i40iw_status_code
i40iw_remove_pd_bp(struct i40iw_hw
*hw
,
693 struct i40iw_hmc_info
*hmc_info
,
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
;
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
;
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
;
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
)
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
));
725 I40IW_INVALIDATE_PF_HMC_PD(hw
, sd_idx
, idx
);
727 I40IW_INVALIDATE_VF_HMC_PD(hw
, sd_idx
, idx
,
728 hmc_info
->hmc_fn_id
);
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
);
736 if (!pd_table
->ref_cnt
)
737 i40iw_free_virt_mem(hw
, &pd_table
->pd_entry_virt_mem
);
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
747 enum i40iw_status_code
i40iw_prep_remove_sd_bp(struct i40iw_hmc_info
*hmc_info
, u32 idx
)
749 struct i40iw_hmc_sd_entry
*sd_entry
;
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
;
756 I40IW_DEC_SD_REFCNT(&hmc_info
->sd_table
);
757 sd_entry
->valid
= false;
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
767 enum i40iw_status_code
i40iw_prep_remove_pd_page(struct i40iw_hmc_info
*hmc_info
,
770 struct i40iw_hmc_sd_entry
*sd_entry
;
772 sd_entry
= &hmc_info
->sd_table
.sd_entry
[idx
];
774 if (sd_entry
->u
.pd_table
.ref_cnt
)
775 return I40IW_ERR_NOT_READY
;
777 sd_entry
->valid
= false;
778 I40IW_DEC_SD_REFCNT(&hmc_info
->sd_table
);
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
789 * Called by pf driver to initialize hmc_info for vf driver instance.
791 enum i40iw_status_code
i40iw_pf_init_vfhmc(struct i40iw_sc_dev
*dev
,
795 struct i40iw_hmc_info
*hmc_info
;
796 enum i40iw_status_code ret_code
= 0;
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
;
807 ret_code
= i40iw_sc_init_iw_hmc(dev
, vf_hmc_fn_id
);
811 hmc_info
= i40iw_vf_hmcinfo_from_fpm(dev
, vf_hmc_fn_id
);
813 for (i
= I40IW_HMC_IW_QP
; i
< I40IW_HMC_IW_MAX
; i
++)
815 hmc_info
->hmc_obj
[i
].cnt
=
816 vf_cnt_array
[i
- I40IW_HMC_IW_QP
];
818 hmc_info
->hmc_obj
[i
].cnt
= hmc_info
->hmc_obj
[i
].max_cnt
;