@@ -153,6 +153,17 @@ static inline long long h_hfi_open_window(int token,
return rc;
}
+static inline long long h_hfi_close_window(int token,
+ u64 HFI_chip_ID,
+ u64 win_num,
+ u64 flag)
+{
+ return plpar_hcall_norets(token,
+ HFI_chip_ID,
+ win_num,
+ flag);
+}
+
long long hfi_start_nmmu(u64 chip_id, void *nmmu_info)
{
return h_nmmu_start(H_NMMU_START, chip_id, nmmu_info);
@@ -249,6 +260,17 @@ long long hfi_modify_mr(u64 chip_id, u64 request, u64 mr_handle,
return hvrc;
}
+long long hfi_close_window(u64 unit_id, u64 win_id, u64 flag)
+{
+ long long hvrc;
+
+ hvrc = h_hfi_close_window(H_HFI_CLOSE_WINDOW,
+ unit_id,
+ win_id,
+ flag);
+ return hvrc;
+}
+
long long hfi_free_mr(u64 chip_id, u64 res, u64 mr_handle, u64 sub_region_id)
{
long long hvrc;
@@ -94,6 +94,7 @@ long long hfi_modify_mr(u64 chip_id, u64 request, u64 mr_handle,
u64 e_addr,
u64 l_addr,
u64 num_pg_sz);
+long long hfi_close_window(u64 unit_id, u64 win_id, u64 flag);
long long hfi_free_mr(u64 chip_id, u64 res, u64 mr_handle,
u64 sub_region_id);
long long hfi_hquery_interface(u64 unit_id, u64 subtype, u64 query_p,
@@ -459,6 +459,43 @@ static int hfi_hcall_to_open_window(struct hfidd_acs *p_acs,
return 0;
}
+/* Call to CLOSE WINDOW hcall */
+static int hfi_hcall_to_close_window(struct hfidd_acs *p_acs,
+ struct hfidd_window *win_p)
+{
+ int rc = 0;
+ long long hvrc = 0;
+ u64 start_time = get_jiffies_64();
+
+ hvrc = hfi_close_window(p_acs->dds.hfi_id,
+ win_p->index,
+ H_CLOSE);
+
+ /*
+ * Need to call CLOSE WINDOW with flag H_CHECK_CLOSED
+ * to check when the window is completely closed
+ */
+ while (hvrc == H_BUSY) {
+ hvrc = hfi_close_window(p_acs->dds.hfi_id,
+ win_p->index,
+ H_CHECK_CLOSED);
+ if (hvrc != H_BUSY)
+ break;
+ if (hfidd_age_hcall(start_time))
+ break;
+ }
+
+ if (hvrc != H_SUCCESS) {
+ win_p->state = WIN_FAIL_CLOSE;
+ rc = -EIO;
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_hcall_to_close_window: CLOSE WINDOW failed, "
+ "hvrc=0x%llx\n", hvrc);
+ }
+
+ return rc;
+}
+
/*
* Map the Effective Address pages for Memory Regions.
* If more than one page, need to setup a page containing
@@ -1005,7 +1042,7 @@ int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
dev_printk(KERN_ERR, p_acs->hfidd_dev,
"hfidd_open_window_func: hfi_map_mmio_regs "
"failed, rc = 0x%x\n", rc);
- goto hfidd_open_window_func_err4;
+ goto hfidd_open_window_func_err5;
}
/* tell user the local ISR id */
@@ -1019,7 +1056,7 @@ int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
dev_printk(KERN_ERR, p_acs->hfidd_dev,
"hfidd_open_window_func: hfi_copy_to_user "
"failed, rc = 0x%x\n", rc);
- goto hfidd_open_window_func_err5;
+ goto hfidd_open_window_func_err6;
}
spin_lock(&(win_p->win_lock));
@@ -1031,9 +1068,11 @@ int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
kfree(local_p);
return rc;
-hfidd_open_window_func_err5:
+hfidd_open_window_func_err6:
if (is_userspace)
hfidd_unmap(local_p->mmio_regs.use.kptr, PAGE_SIZE_64K);
+hfidd_open_window_func_err5:
+ hfi_hcall_to_close_window(p_acs, win_p);
hfidd_open_window_func_err4:
hfi_destroy_window_parm(p_acs, is_userspace, win_p, local_p);
hfidd_open_window_func_err3:
@@ -1103,6 +1142,14 @@ int hfidd_close_window_internal(struct hfidd_acs *p_acs,
goto hfidd_close_window_internal_err0;
}
+ rc = hfi_hcall_to_close_window(p_acs, win_p);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_close_window_internal: hfi_hcall_to_close_window "
+ "failed, rc = 0x%x\n", rc);
+ goto hfidd_close_window_internal_err0;
+ }
+
hfi_destroy_window_info(p_acs, win_p);
/* Call hcall to unregister MR in the MMU */