.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright 2016-17 IBM Corp. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or |
---|
5 | | - * modify it under the terms of the GNU General Public License |
---|
6 | | - * as published by the Free Software Foundation; either version |
---|
7 | | - * 2 of the License, or (at your option) any later version. |
---|
8 | 4 | */ |
---|
9 | 5 | |
---|
10 | 6 | #define pr_fmt(fmt) "vas: " fmt |
---|
.. | .. |
---|
16 | 12 | #include <linux/log2.h> |
---|
17 | 13 | #include <linux/rcupdate.h> |
---|
18 | 14 | #include <linux/cred.h> |
---|
| 15 | +#include <linux/sched/mm.h> |
---|
| 16 | +#include <linux/mmu_context.h> |
---|
19 | 17 | #include <asm/switch_to.h> |
---|
20 | 18 | #include <asm/ppc-opcode.h> |
---|
21 | 19 | #include "vas.h" |
---|
.. | .. |
---|
28 | 26 | * Compute the paste address region for the window @window using the |
---|
29 | 27 | * ->paste_base_addr and ->paste_win_id_shift we got from device tree. |
---|
30 | 28 | */ |
---|
31 | | -static void compute_paste_address(struct vas_window *window, u64 *addr, int *len) |
---|
| 29 | +void vas_win_paste_addr(struct vas_window *window, u64 *addr, int *len) |
---|
32 | 30 | { |
---|
33 | 31 | int winid; |
---|
34 | 32 | u64 base, shift; |
---|
.. | .. |
---|
43 | 41 | |
---|
44 | 42 | pr_debug("Txwin #%d: Paste addr 0x%llx\n", winid, *addr); |
---|
45 | 43 | } |
---|
46 | | - |
---|
47 | | -u64 vas_win_paste_addr(struct vas_window *win) |
---|
48 | | -{ |
---|
49 | | - u64 addr; |
---|
50 | | - |
---|
51 | | - compute_paste_address(win, &addr, NULL); |
---|
52 | | - |
---|
53 | | - return addr; |
---|
54 | | -} |
---|
55 | | -EXPORT_SYMBOL(vas_win_paste_addr); |
---|
56 | 44 | |
---|
57 | 45 | static inline void get_hvwc_mmio_bar(struct vas_window *window, |
---|
58 | 46 | u64 *start, int *len) |
---|
.. | .. |
---|
92 | 80 | goto free_name; |
---|
93 | 81 | |
---|
94 | 82 | txwin->paste_addr_name = name; |
---|
95 | | - compute_paste_address(txwin, &start, &len); |
---|
| 83 | + vas_win_paste_addr(txwin, &start, &len); |
---|
96 | 84 | |
---|
97 | 85 | if (!request_mem_region(start, len, name)) { |
---|
98 | 86 | pr_devel("%s(): request_mem_region(0x%llx, %d) failed\n", |
---|
.. | .. |
---|
150 | 138 | u64 busaddr_start; |
---|
151 | 139 | |
---|
152 | 140 | if (window->paste_kaddr) { |
---|
153 | | - compute_paste_address(window, &busaddr_start, &len); |
---|
| 141 | + vas_win_paste_addr(window, &busaddr_start, &len); |
---|
154 | 142 | unmap_region(window->paste_kaddr, busaddr_start, len); |
---|
155 | 143 | window->paste_kaddr = NULL; |
---|
156 | 144 | kfree(window->paste_addr_name); |
---|
.. | .. |
---|
198 | 186 | * OS/User Window Context (UWC) MMIO Base Address Region for the given window. |
---|
199 | 187 | * Map these bus addresses and save the mapped kernel addresses in @window. |
---|
200 | 188 | */ |
---|
201 | | -int map_winctx_mmio_bars(struct vas_window *window) |
---|
| 189 | +static int map_winctx_mmio_bars(struct vas_window *window) |
---|
202 | 190 | { |
---|
203 | 191 | int len; |
---|
204 | 192 | u64 start; |
---|
.. | .. |
---|
226 | 214 | * registers are not sequential. And, we can only write to offsets |
---|
227 | 215 | * with valid registers. |
---|
228 | 216 | */ |
---|
229 | | -void reset_window_regs(struct vas_window *window) |
---|
| 217 | +static void reset_window_regs(struct vas_window *window) |
---|
230 | 218 | { |
---|
231 | 219 | write_hvwc_reg(window, VREG(LPID), 0ULL); |
---|
232 | 220 | write_hvwc_reg(window, VREG(PID), 0ULL); |
---|
.. | .. |
---|
369 | 357 | * as a one-time task? That could work for NX but what about other |
---|
370 | 358 | * receivers? Let the receivers tell us the rx-fifo buffers for now. |
---|
371 | 359 | */ |
---|
372 | | -int init_winctx_regs(struct vas_window *window, struct vas_winctx *winctx) |
---|
| 360 | +static void init_winctx_regs(struct vas_window *window, |
---|
| 361 | + struct vas_winctx *winctx) |
---|
373 | 362 | { |
---|
374 | 363 | u64 val; |
---|
375 | 364 | int fifo_size; |
---|
.. | .. |
---|
387 | 376 | init_xlate_regs(window, winctx->user_win); |
---|
388 | 377 | |
---|
389 | 378 | val = 0ULL; |
---|
390 | | - val = SET_FIELD(VAS_FAULT_TX_WIN, val, 0); |
---|
| 379 | + val = SET_FIELD(VAS_FAULT_TX_WIN, val, winctx->fault_win_id); |
---|
391 | 380 | write_hvwc_reg(window, VREG(FAULT_TX_WIN), val); |
---|
392 | 381 | |
---|
393 | 382 | /* In PowerNV, interrupts go to HV. */ |
---|
.. | .. |
---|
414 | 403 | * |
---|
415 | 404 | * See also: Design note in function header. |
---|
416 | 405 | */ |
---|
417 | | - val = __pa(winctx->rx_fifo); |
---|
| 406 | + val = winctx->rx_fifo; |
---|
418 | 407 | val = SET_FIELD(VAS_PAGE_MIGRATION_SELECT, val, 0); |
---|
419 | 408 | write_hvwc_reg(window, VREG(LFIFO_BAR), val); |
---|
420 | 409 | |
---|
.. | .. |
---|
511 | 500 | val = SET_FIELD(VAS_WINCTL_NX_WIN, val, winctx->nx_win); |
---|
512 | 501 | val = SET_FIELD(VAS_WINCTL_OPEN, val, 1); |
---|
513 | 502 | write_hvwc_reg(window, VREG(WINCTL), val); |
---|
514 | | - |
---|
515 | | - return 0; |
---|
516 | 503 | } |
---|
517 | 504 | |
---|
518 | 505 | static void vas_release_window_id(struct ida *ida, int winid) |
---|
.. | .. |
---|
750 | 737 | */ |
---|
751 | 738 | winctx->fifo_disable = true; |
---|
752 | 739 | winctx->intr_disable = true; |
---|
753 | | - winctx->rx_fifo = NULL; |
---|
| 740 | + winctx->rx_fifo = 0; |
---|
754 | 741 | } |
---|
755 | 742 | |
---|
756 | 743 | winctx->lnotify_lpid = rxattr->lnotify_lpid; |
---|
.. | .. |
---|
762 | 749 | |
---|
763 | 750 | winctx->min_scope = VAS_SCOPE_LOCAL; |
---|
764 | 751 | winctx->max_scope = VAS_SCOPE_VECTORED_GROUP; |
---|
| 752 | + if (rxwin->vinst->virq) |
---|
| 753 | + winctx->irq_port = rxwin->vinst->irq_port; |
---|
765 | 754 | } |
---|
766 | 755 | |
---|
767 | 756 | static bool rx_win_args_valid(enum vas_cop_type cop, |
---|
.. | .. |
---|
782 | 771 | if (attr->rx_fifo_size > VAS_RX_FIFO_SIZE_MAX) |
---|
783 | 772 | return false; |
---|
784 | 773 | |
---|
785 | | - if (attr->wcreds_max > VAS_RX_WCREDS_MAX) |
---|
| 774 | + if (!attr->wcreds_max) |
---|
786 | 775 | return false; |
---|
787 | 776 | |
---|
788 | 777 | if (attr->nx_win) { |
---|
.. | .. |
---|
827 | 816 | { |
---|
828 | 817 | memset(rxattr, 0, sizeof(*rxattr)); |
---|
829 | 818 | |
---|
830 | | - if (cop == VAS_COP_TYPE_842 || cop == VAS_COP_TYPE_842_HIPRI) { |
---|
| 819 | + if (cop == VAS_COP_TYPE_842 || cop == VAS_COP_TYPE_842_HIPRI || |
---|
| 820 | + cop == VAS_COP_TYPE_GZIP || cop == VAS_COP_TYPE_GZIP_HIPRI) { |
---|
831 | 821 | rxattr->pin_win = true; |
---|
832 | 822 | rxattr->nx_win = true; |
---|
833 | 823 | rxattr->fault_win = false; |
---|
.. | .. |
---|
841 | 831 | rxattr->fault_win = true; |
---|
842 | 832 | rxattr->notify_disable = true; |
---|
843 | 833 | rxattr->rx_wcred_mode = true; |
---|
844 | | - rxattr->tx_wcred_mode = true; |
---|
845 | 834 | rxattr->rx_win_ord_mode = true; |
---|
846 | | - rxattr->tx_win_ord_mode = true; |
---|
| 835 | + rxattr->rej_no_credit = true; |
---|
| 836 | + rxattr->tc_mode = VAS_THRESH_DISABLED; |
---|
847 | 837 | } else if (cop == VAS_COP_TYPE_FTW) { |
---|
848 | 838 | rxattr->user_win = true; |
---|
849 | 839 | rxattr->intr_disable = true; |
---|
.. | .. |
---|
887 | 877 | rxwin->nx_win = rxattr->nx_win; |
---|
888 | 878 | rxwin->user_win = rxattr->user_win; |
---|
889 | 879 | rxwin->cop = cop; |
---|
890 | | - rxwin->wcreds_max = rxattr->wcreds_max ?: VAS_WCREDS_DEFAULT; |
---|
891 | | - if (rxattr->user_win) |
---|
892 | | - rxwin->pid = task_pid_vnr(current); |
---|
| 880 | + rxwin->wcreds_max = rxattr->wcreds_max; |
---|
893 | 881 | |
---|
894 | 882 | init_winctx_for_rxwin(rxwin, rxattr, &winctx); |
---|
895 | 883 | init_winctx_regs(rxwin, &winctx); |
---|
.. | .. |
---|
904 | 892 | { |
---|
905 | 893 | memset(txattr, 0, sizeof(*txattr)); |
---|
906 | 894 | |
---|
907 | | - if (cop == VAS_COP_TYPE_842 || cop == VAS_COP_TYPE_842_HIPRI) { |
---|
| 895 | + if (cop == VAS_COP_TYPE_842 || cop == VAS_COP_TYPE_842_HIPRI || |
---|
| 896 | + cop == VAS_COP_TYPE_GZIP || cop == VAS_COP_TYPE_GZIP_HIPRI) { |
---|
908 | 897 | txattr->rej_no_credit = false; |
---|
909 | 898 | txattr->rx_wcred_mode = true; |
---|
910 | 899 | txattr->tx_wcred_mode = true; |
---|
.. | .. |
---|
958 | 947 | winctx->lpid = txattr->lpid; |
---|
959 | 948 | winctx->pidr = txattr->pidr; |
---|
960 | 949 | winctx->rx_win_id = txwin->rxwin->winid; |
---|
| 950 | + /* |
---|
| 951 | + * IRQ and fault window setup is successful. Set fault window |
---|
| 952 | + * for the send window so that ready to handle faults. |
---|
| 953 | + */ |
---|
| 954 | + if (txwin->vinst->virq) |
---|
| 955 | + winctx->fault_win_id = txwin->vinst->fault_win->winid; |
---|
961 | 956 | |
---|
962 | 957 | winctx->dma_type = VAS_DMA_TYPE_INJECT; |
---|
963 | 958 | winctx->tc_mode = txattr->tc_mode; |
---|
964 | 959 | winctx->min_scope = VAS_SCOPE_LOCAL; |
---|
965 | 960 | winctx->max_scope = VAS_SCOPE_VECTORED_GROUP; |
---|
| 961 | + if (txwin->vinst->virq) |
---|
| 962 | + winctx->irq_port = txwin->vinst->irq_port; |
---|
966 | 963 | |
---|
967 | | - winctx->pswid = 0; |
---|
| 964 | + winctx->pswid = txattr->pswid ? txattr->pswid : |
---|
| 965 | + encode_pswid(txwin->vinst->vas_id, txwin->winid); |
---|
968 | 966 | } |
---|
969 | 967 | |
---|
970 | 968 | static bool tx_win_args_valid(enum vas_cop_type cop, |
---|
.. | .. |
---|
979 | 977 | if (attr->wcreds_max > VAS_TX_WCREDS_MAX) |
---|
980 | 978 | return false; |
---|
981 | 979 | |
---|
982 | | - if (attr->user_win && |
---|
983 | | - (cop != VAS_COP_TYPE_FTW || attr->rsvd_txbuf_count)) |
---|
984 | | - return false; |
---|
| 980 | + if (attr->user_win) { |
---|
| 981 | + if (attr->rsvd_txbuf_count) |
---|
| 982 | + return false; |
---|
| 983 | + |
---|
| 984 | + if (cop != VAS_COP_TYPE_FTW && cop != VAS_COP_TYPE_GZIP && |
---|
| 985 | + cop != VAS_COP_TYPE_GZIP_HIPRI) |
---|
| 986 | + return false; |
---|
| 987 | + } |
---|
985 | 988 | |
---|
986 | 989 | return true; |
---|
987 | 990 | } |
---|
.. | .. |
---|
1030 | 1033 | txwin->tx_win = 1; |
---|
1031 | 1034 | txwin->rxwin = rxwin; |
---|
1032 | 1035 | txwin->nx_win = txwin->rxwin->nx_win; |
---|
1033 | | - txwin->pid = attr->pid; |
---|
1034 | 1036 | txwin->user_win = attr->user_win; |
---|
1035 | 1037 | txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT; |
---|
1036 | 1038 | |
---|
.. | .. |
---|
1054 | 1056 | } |
---|
1055 | 1057 | } else { |
---|
1056 | 1058 | /* |
---|
1057 | | - * A user mapping must ensure that context switch issues |
---|
1058 | | - * CP_ABORT for this thread. |
---|
| 1059 | + * Interrupt hanlder or fault window setup failed. Means |
---|
| 1060 | + * NX can not generate fault for page fault. So not |
---|
| 1061 | + * opening for user space tx window. |
---|
1059 | 1062 | */ |
---|
1060 | | - rc = set_thread_uses_vas(); |
---|
1061 | | - if (rc) |
---|
| 1063 | + if (!vinst->virq) { |
---|
| 1064 | + rc = -ENODEV; |
---|
1062 | 1065 | goto free_window; |
---|
| 1066 | + } |
---|
| 1067 | + |
---|
| 1068 | + /* |
---|
| 1069 | + * Window opened by a child thread may not be closed when |
---|
| 1070 | + * it exits. So take reference to its pid and release it |
---|
| 1071 | + * when the window is free by parent thread. |
---|
| 1072 | + * Acquire a reference to the task's pid to make sure |
---|
| 1073 | + * pid will not be re-used - needed only for multithread |
---|
| 1074 | + * applications. |
---|
| 1075 | + */ |
---|
| 1076 | + txwin->pid = get_task_pid(current, PIDTYPE_PID); |
---|
| 1077 | + /* |
---|
| 1078 | + * Acquire a reference to the task's mm. |
---|
| 1079 | + */ |
---|
| 1080 | + txwin->mm = get_task_mm(current); |
---|
| 1081 | + |
---|
| 1082 | + if (!txwin->mm) { |
---|
| 1083 | + put_pid(txwin->pid); |
---|
| 1084 | + pr_err("VAS: pid(%d): mm_struct is not found\n", |
---|
| 1085 | + current->pid); |
---|
| 1086 | + rc = -EPERM; |
---|
| 1087 | + goto free_window; |
---|
| 1088 | + } |
---|
| 1089 | + |
---|
| 1090 | + mmgrab(txwin->mm); |
---|
| 1091 | + mmput(txwin->mm); |
---|
| 1092 | + mm_context_add_vas_window(txwin->mm); |
---|
| 1093 | + /* |
---|
| 1094 | + * Process closes window during exit. In the case of |
---|
| 1095 | + * multithread application, the child thread can open |
---|
| 1096 | + * window and can exit without closing it. so takes tgid |
---|
| 1097 | + * reference until window closed to make sure tgid is not |
---|
| 1098 | + * reused. |
---|
| 1099 | + */ |
---|
| 1100 | + txwin->tgid = find_get_pid(task_tgid_vnr(current)); |
---|
| 1101 | + /* |
---|
| 1102 | + * Even a process that has no foreign real address mapping can |
---|
| 1103 | + * use an unpaired COPY instruction (to no real effect). Issue |
---|
| 1104 | + * CP_ABORT to clear any pending COPY and prevent a covert |
---|
| 1105 | + * channel. |
---|
| 1106 | + * |
---|
| 1107 | + * __switch_to() will issue CP_ABORT on future context switches |
---|
| 1108 | + * if process / thread has any open VAS window (Use |
---|
| 1109 | + * current->mm->context.vas_windows). |
---|
| 1110 | + */ |
---|
| 1111 | + asm volatile(PPC_CP_ABORT); |
---|
1063 | 1112 | } |
---|
1064 | 1113 | |
---|
1065 | 1114 | set_vinst_win(vinst, txwin); |
---|
.. | .. |
---|
1142 | 1191 | { |
---|
1143 | 1192 | u64 val; |
---|
1144 | 1193 | int creds, mode; |
---|
| 1194 | + int count = 0; |
---|
1145 | 1195 | |
---|
1146 | 1196 | val = read_hvwc_reg(window, VREG(WINCTL)); |
---|
1147 | 1197 | if (window->tx_win) |
---|
.. | .. |
---|
1160 | 1210 | creds = GET_FIELD(VAS_LRX_WCRED, val); |
---|
1161 | 1211 | } |
---|
1162 | 1212 | |
---|
| 1213 | + /* |
---|
| 1214 | + * Takes around few milliseconds to complete all pending requests |
---|
| 1215 | + * and return credits. |
---|
| 1216 | + * TODO: Scan fault FIFO and invalidate CRBs points to this window |
---|
| 1217 | + * and issue CRB Kill to stop all pending requests. Need only |
---|
| 1218 | + * if there is a bug in NX or fault handling in kernel. |
---|
| 1219 | + */ |
---|
1163 | 1220 | if (creds < window->wcreds_max) { |
---|
1164 | 1221 | val = 0; |
---|
1165 | 1222 | set_current_state(TASK_UNINTERRUPTIBLE); |
---|
1166 | 1223 | schedule_timeout(msecs_to_jiffies(10)); |
---|
| 1224 | + count++; |
---|
| 1225 | + /* |
---|
| 1226 | + * Process can not close send window until all credits are |
---|
| 1227 | + * returned. |
---|
| 1228 | + */ |
---|
| 1229 | + if (!(count % 1000)) |
---|
| 1230 | + pr_warn_ratelimited("VAS: pid %d stuck. Waiting for credits returned for Window(%d). creds %d, Retries %d\n", |
---|
| 1231 | + vas_window_pid(window), window->winid, |
---|
| 1232 | + creds, count); |
---|
| 1233 | + |
---|
1167 | 1234 | goto retry; |
---|
1168 | 1235 | } |
---|
1169 | 1236 | } |
---|
.. | .. |
---|
1177 | 1244 | { |
---|
1178 | 1245 | int busy; |
---|
1179 | 1246 | u64 val; |
---|
| 1247 | + int count = 0; |
---|
1180 | 1248 | |
---|
1181 | 1249 | retry: |
---|
1182 | 1250 | val = read_hvwc_reg(window, VREG(WIN_STATUS)); |
---|
.. | .. |
---|
1184 | 1252 | if (busy) { |
---|
1185 | 1253 | val = 0; |
---|
1186 | 1254 | set_current_state(TASK_UNINTERRUPTIBLE); |
---|
1187 | | - schedule_timeout(msecs_to_jiffies(5)); |
---|
| 1255 | + schedule_timeout(msecs_to_jiffies(10)); |
---|
| 1256 | + count++; |
---|
| 1257 | + /* |
---|
| 1258 | + * Takes around few milliseconds to process all pending |
---|
| 1259 | + * requests. |
---|
| 1260 | + */ |
---|
| 1261 | + if (!(count % 1000)) |
---|
| 1262 | + pr_warn_ratelimited("VAS: pid %d stuck. Window (ID=%d) is in busy state. Retries %d\n", |
---|
| 1263 | + vas_window_pid(window), window->winid, count); |
---|
| 1264 | + |
---|
1188 | 1265 | goto retry; |
---|
1189 | 1266 | } |
---|
1190 | 1267 | } |
---|
.. | .. |
---|
1249 | 1326 | |
---|
1250 | 1327 | unmap_paste_region(window); |
---|
1251 | 1328 | |
---|
1252 | | - clear_vinst_win(window); |
---|
1253 | | - |
---|
1254 | 1329 | poll_window_busy_state(window); |
---|
1255 | 1330 | |
---|
1256 | 1331 | unpin_close_window(window); |
---|
1257 | 1332 | |
---|
1258 | 1333 | poll_window_credits(window); |
---|
1259 | 1334 | |
---|
| 1335 | + clear_vinst_win(window); |
---|
| 1336 | + |
---|
1260 | 1337 | poll_window_castout(window); |
---|
1261 | 1338 | |
---|
1262 | 1339 | /* if send window, drop reference to matching receive window */ |
---|
1263 | | - if (window->tx_win) |
---|
| 1340 | + if (window->tx_win) { |
---|
| 1341 | + if (window->user_win) { |
---|
| 1342 | + /* Drop references to pid. tgid and mm */ |
---|
| 1343 | + put_pid(window->pid); |
---|
| 1344 | + put_pid(window->tgid); |
---|
| 1345 | + if (window->mm) { |
---|
| 1346 | + mm_context_remove_vas_window(window->mm); |
---|
| 1347 | + mmdrop(window->mm); |
---|
| 1348 | + } |
---|
| 1349 | + } |
---|
1264 | 1350 | put_rx_win(window->rxwin); |
---|
| 1351 | + } |
---|
1265 | 1352 | |
---|
1266 | 1353 | vas_window_free(window); |
---|
1267 | 1354 | |
---|
.. | .. |
---|
1270 | 1357 | EXPORT_SYMBOL_GPL(vas_win_close); |
---|
1271 | 1358 | |
---|
1272 | 1359 | /* |
---|
1273 | | - * Return a system-wide unique window id for the window @win. |
---|
| 1360 | + * Return credit for the given window. |
---|
| 1361 | + * Send windows and fault window uses credit mechanism as follows: |
---|
| 1362 | + * |
---|
| 1363 | + * Send windows: |
---|
| 1364 | + * - The default number of credits available for each send window is |
---|
| 1365 | + * 1024. It means 1024 requests can be issued asynchronously at the |
---|
| 1366 | + * same time. If the credit is not available, that request will be |
---|
| 1367 | + * returned with RMA_Busy. |
---|
| 1368 | + * - One credit is taken when NX request is issued. |
---|
| 1369 | + * - This credit is returned after NX processed that request. |
---|
| 1370 | + * - If NX encounters translation error, kernel will return the |
---|
| 1371 | + * credit on the specific send window after processing the fault CRB. |
---|
| 1372 | + * |
---|
| 1373 | + * Fault window: |
---|
| 1374 | + * - The total number credits available is FIFO_SIZE/CRB_SIZE. |
---|
| 1375 | + * Means 4MB/128 in the current implementation. If credit is not |
---|
| 1376 | + * available, RMA_Reject is returned. |
---|
| 1377 | + * - A credit is taken when NX pastes CRB in fault FIFO. |
---|
| 1378 | + * - The kernel with return credit on fault window after reading entry |
---|
| 1379 | + * from fault FIFO. |
---|
1274 | 1380 | */ |
---|
1275 | | -u32 vas_win_id(struct vas_window *win) |
---|
| 1381 | +void vas_return_credit(struct vas_window *window, bool tx) |
---|
1276 | 1382 | { |
---|
1277 | | - return encode_pswid(win->vinst->vas_id, win->winid); |
---|
| 1383 | + uint64_t val; |
---|
| 1384 | + |
---|
| 1385 | + val = 0ULL; |
---|
| 1386 | + if (tx) { /* send window */ |
---|
| 1387 | + val = SET_FIELD(VAS_TX_WCRED, val, 1); |
---|
| 1388 | + write_hvwc_reg(window, VREG(TX_WCRED_ADDER), val); |
---|
| 1389 | + } else { |
---|
| 1390 | + val = SET_FIELD(VAS_LRX_WCRED, val, 1); |
---|
| 1391 | + write_hvwc_reg(window, VREG(LRX_WCRED_ADDER), val); |
---|
| 1392 | + } |
---|
1278 | 1393 | } |
---|
1279 | | -EXPORT_SYMBOL_GPL(vas_win_id); |
---|
| 1394 | + |
---|
| 1395 | +struct vas_window *vas_pswid_to_window(struct vas_instance *vinst, |
---|
| 1396 | + uint32_t pswid) |
---|
| 1397 | +{ |
---|
| 1398 | + struct vas_window *window; |
---|
| 1399 | + int winid; |
---|
| 1400 | + |
---|
| 1401 | + if (!pswid) { |
---|
| 1402 | + pr_devel("%s: called for pswid 0!\n", __func__); |
---|
| 1403 | + return ERR_PTR(-ESRCH); |
---|
| 1404 | + } |
---|
| 1405 | + |
---|
| 1406 | + decode_pswid(pswid, NULL, &winid); |
---|
| 1407 | + |
---|
| 1408 | + if (winid >= VAS_WINDOWS_PER_CHIP) |
---|
| 1409 | + return ERR_PTR(-ESRCH); |
---|
| 1410 | + |
---|
| 1411 | + /* |
---|
| 1412 | + * If application closes the window before the hardware |
---|
| 1413 | + * returns the fault CRB, we should wait in vas_win_close() |
---|
| 1414 | + * for the pending requests. so the window must be active |
---|
| 1415 | + * and the process alive. |
---|
| 1416 | + * |
---|
| 1417 | + * If its a kernel process, we should not get any faults and |
---|
| 1418 | + * should not get here. |
---|
| 1419 | + */ |
---|
| 1420 | + window = vinst->windows[winid]; |
---|
| 1421 | + |
---|
| 1422 | + if (!window) { |
---|
| 1423 | + pr_err("PSWID decode: Could not find window for winid %d pswid %d vinst 0x%p\n", |
---|
| 1424 | + winid, pswid, vinst); |
---|
| 1425 | + return NULL; |
---|
| 1426 | + } |
---|
| 1427 | + |
---|
| 1428 | + /* |
---|
| 1429 | + * Do some sanity checks on the decoded window. Window should be |
---|
| 1430 | + * NX GZIP user send window. FTW windows should not incur faults |
---|
| 1431 | + * since their CRBs are ignored (not queued on FIFO or processed |
---|
| 1432 | + * by NX). |
---|
| 1433 | + */ |
---|
| 1434 | + if (!window->tx_win || !window->user_win || !window->nx_win || |
---|
| 1435 | + window->cop == VAS_COP_TYPE_FAULT || |
---|
| 1436 | + window->cop == VAS_COP_TYPE_FTW) { |
---|
| 1437 | + pr_err("PSWID decode: id %d, tx %d, user %d, nx %d, cop %d\n", |
---|
| 1438 | + winid, window->tx_win, window->user_win, |
---|
| 1439 | + window->nx_win, window->cop); |
---|
| 1440 | + WARN_ON(1); |
---|
| 1441 | + } |
---|
| 1442 | + |
---|
| 1443 | + return window; |
---|
| 1444 | +} |
---|