1266b0663SKrzysztof Zdziarski /* SPDX-License-Identifier: BSD-3-Clause */
2266b0663SKrzysztof Zdziarski /* Copyright(c) 2007-2022 Intel Corporation */
3266b0663SKrzysztof Zdziarski #include "qat_freebsd.h"
4266b0663SKrzysztof Zdziarski #include "adf_cfg.h"
5266b0663SKrzysztof Zdziarski #include "adf_common_drv.h"
6266b0663SKrzysztof Zdziarski #include "adf_accel_devices.h"
7266b0663SKrzysztof Zdziarski #include "icp_qat_uclo.h"
8266b0663SKrzysztof Zdziarski #include "icp_qat_fw.h"
9266b0663SKrzysztof Zdziarski #include "icp_qat_fw_init_admin.h"
10266b0663SKrzysztof Zdziarski #include "adf_cfg_strings.h"
11266b0663SKrzysztof Zdziarski #include "adf_uio_control.h"
12266b0663SKrzysztof Zdziarski #include "adf_uio_cleanup.h"
13266b0663SKrzysztof Zdziarski #include "adf_uio.h"
14266b0663SKrzysztof Zdziarski #include "adf_transport_access_macros.h"
15266b0663SKrzysztof Zdziarski #include "adf_transport_internal.h"
16266b0663SKrzysztof Zdziarski #include <sys/param.h>
17266b0663SKrzysztof Zdziarski #include <sys/lock.h>
18266b0663SKrzysztof Zdziarski #include <sys/rwlock.h>
19266b0663SKrzysztof Zdziarski #include <sys/sglist.h>
20266b0663SKrzysztof Zdziarski #include <sys/systm.h>
21266b0663SKrzysztof Zdziarski #include <sys/proc.h>
22266b0663SKrzysztof Zdziarski #include <vm/vm.h>
23266b0663SKrzysztof Zdziarski #include <vm/pmap.h>
24266b0663SKrzysztof Zdziarski #include <vm/vm_kern.h>
25266b0663SKrzysztof Zdziarski #include <vm/vm_map.h>
26266b0663SKrzysztof Zdziarski #include <vm/vm_object.h>
27266b0663SKrzysztof Zdziarski #include <vm/vm_page.h>
28266b0663SKrzysztof Zdziarski #include <vm/vm_pager.h>
29266b0663SKrzysztof Zdziarski #include <vm/vm_param.h>
30266b0663SKrzysztof Zdziarski
31266b0663SKrzysztof Zdziarski #define TX_RINGS_DISABLE 0
32266b0663SKrzysztof Zdziarski #define TX_RINGS_ENABLE 1
33266b0663SKrzysztof Zdziarski #define PKE_REQ_SIZE 64
34266b0663SKrzysztof Zdziarski #define BASE_ADDR_SHIFT 6
35266b0663SKrzysztof Zdziarski #define PKE_RX_RING_0 0
36266b0663SKrzysztof Zdziarski #define PKE_RX_RING_1 1
37266b0663SKrzysztof Zdziarski
38266b0663SKrzysztof Zdziarski #define ADF_RING_EMPTY_RETRY_DELAY 2
39266b0663SKrzysztof Zdziarski #define ADF_RING_EMPTY_MAX_RETRY 15
40266b0663SKrzysztof Zdziarski
41266b0663SKrzysztof Zdziarski struct bundle_orphan_ring {
42266b0663SKrzysztof Zdziarski unsigned long tx_mask;
43266b0663SKrzysztof Zdziarski unsigned long rx_mask;
44266b0663SKrzysztof Zdziarski unsigned long asym_mask;
45266b0663SKrzysztof Zdziarski int bank;
46266b0663SKrzysztof Zdziarski struct resource *csr_base;
47266b0663SKrzysztof Zdziarski struct adf_uio_control_bundle *bundle;
48266b0663SKrzysztof Zdziarski };
49266b0663SKrzysztof Zdziarski
50266b0663SKrzysztof Zdziarski /*
51266b0663SKrzysztof Zdziarski * if orphan->tx_mask does not match with orphan->rx_mask
52266b0663SKrzysztof Zdziarski */
53266b0663SKrzysztof Zdziarski static void
check_orphan_ring(struct adf_accel_dev * accel_dev,struct bundle_orphan_ring * orphan,struct adf_hw_device_data * hw_data)54266b0663SKrzysztof Zdziarski check_orphan_ring(struct adf_accel_dev *accel_dev,
55266b0663SKrzysztof Zdziarski struct bundle_orphan_ring *orphan,
56266b0663SKrzysztof Zdziarski struct adf_hw_device_data *hw_data)
57266b0663SKrzysztof Zdziarski {
58266b0663SKrzysztof Zdziarski struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(accel_dev);
59266b0663SKrzysztof Zdziarski int i;
60266b0663SKrzysztof Zdziarski int tx_rx_gap = hw_data->tx_rx_gap;
61266b0663SKrzysztof Zdziarski u8 num_rings_per_bank = hw_data->num_rings_per_bank;
62266b0663SKrzysztof Zdziarski struct resource *csr_base = orphan->csr_base;
63266b0663SKrzysztof Zdziarski int bank = orphan->bank;
64266b0663SKrzysztof Zdziarski
65266b0663SKrzysztof Zdziarski for (i = 0; i < num_rings_per_bank; i++) {
66266b0663SKrzysztof Zdziarski if (test_bit(i, &orphan->tx_mask)) {
67266b0663SKrzysztof Zdziarski int rx_ring = i + tx_rx_gap;
68266b0663SKrzysztof Zdziarski
69266b0663SKrzysztof Zdziarski if (!test_bit(rx_ring, &orphan->rx_mask)) {
70266b0663SKrzysztof Zdziarski __clear_bit(i, &orphan->tx_mask);
71266b0663SKrzysztof Zdziarski
72266b0663SKrzysztof Zdziarski /* clean up this tx ring */
73266b0663SKrzysztof Zdziarski csr_ops->write_csr_ring_config(csr_base,
74266b0663SKrzysztof Zdziarski bank,
75266b0663SKrzysztof Zdziarski i,
76266b0663SKrzysztof Zdziarski 0);
77266b0663SKrzysztof Zdziarski csr_ops->write_csr_ring_base(csr_base,
78266b0663SKrzysztof Zdziarski bank,
79266b0663SKrzysztof Zdziarski i,
80266b0663SKrzysztof Zdziarski 0);
81266b0663SKrzysztof Zdziarski }
82266b0663SKrzysztof Zdziarski
83266b0663SKrzysztof Zdziarski } else if (test_bit(i, &orphan->rx_mask)) {
84266b0663SKrzysztof Zdziarski int tx_ring = i - tx_rx_gap;
85266b0663SKrzysztof Zdziarski
86266b0663SKrzysztof Zdziarski if (!test_bit(tx_ring, &orphan->tx_mask)) {
87266b0663SKrzysztof Zdziarski __clear_bit(i, &orphan->rx_mask);
88266b0663SKrzysztof Zdziarski
89266b0663SKrzysztof Zdziarski /* clean up this rx ring */
90266b0663SKrzysztof Zdziarski csr_ops->write_csr_ring_config(csr_base,
91266b0663SKrzysztof Zdziarski bank,
92266b0663SKrzysztof Zdziarski i,
93266b0663SKrzysztof Zdziarski 0);
94266b0663SKrzysztof Zdziarski csr_ops->write_csr_ring_base(csr_base,
95266b0663SKrzysztof Zdziarski bank,
96266b0663SKrzysztof Zdziarski i,
97266b0663SKrzysztof Zdziarski 0);
98266b0663SKrzysztof Zdziarski }
99266b0663SKrzysztof Zdziarski }
100266b0663SKrzysztof Zdziarski }
101266b0663SKrzysztof Zdziarski }
102266b0663SKrzysztof Zdziarski
103266b0663SKrzysztof Zdziarski static int
get_orphan_bundle(int bank,struct adf_uio_control_accel * accel,struct bundle_orphan_ring ** orphan_bundle_out)104266b0663SKrzysztof Zdziarski get_orphan_bundle(int bank,
105266b0663SKrzysztof Zdziarski struct adf_uio_control_accel *accel,
106266b0663SKrzysztof Zdziarski struct bundle_orphan_ring **orphan_bundle_out)
107266b0663SKrzysztof Zdziarski {
108266b0663SKrzysztof Zdziarski int i;
109266b0663SKrzysztof Zdziarski int ret = 0;
110266b0663SKrzysztof Zdziarski struct resource *csr_base;
111266b0663SKrzysztof Zdziarski unsigned long tx_mask;
112266b0663SKrzysztof Zdziarski unsigned long asym_mask;
113266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev = accel->accel_dev;
114266b0663SKrzysztof Zdziarski struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(accel_dev);
115266b0663SKrzysztof Zdziarski struct adf_hw_device_data *hw_data = accel_dev->hw_device;
116266b0663SKrzysztof Zdziarski u8 num_rings_per_bank = hw_data->num_rings_per_bank;
117266b0663SKrzysztof Zdziarski struct bundle_orphan_ring *orphan_bundle = NULL;
118266b0663SKrzysztof Zdziarski uint64_t base;
119266b0663SKrzysztof Zdziarski struct list_head *entry;
120266b0663SKrzysztof Zdziarski struct adf_uio_instance_rings *instance_rings;
121266b0663SKrzysztof Zdziarski struct adf_uio_control_bundle *bundle;
122266b0663SKrzysztof Zdziarski u16 ring_mask = 0;
123266b0663SKrzysztof Zdziarski
124266b0663SKrzysztof Zdziarski orphan_bundle =
125266b0663SKrzysztof Zdziarski malloc(sizeof(*orphan_bundle), M_QAT, M_WAITOK | M_ZERO);
126266b0663SKrzysztof Zdziarski csr_base = accel->bar->virt_addr;
127266b0663SKrzysztof Zdziarski orphan_bundle->csr_base = csr_base;
128266b0663SKrzysztof Zdziarski orphan_bundle->bank = bank;
129266b0663SKrzysztof Zdziarski
130266b0663SKrzysztof Zdziarski orphan_bundle->tx_mask = 0;
131266b0663SKrzysztof Zdziarski orphan_bundle->rx_mask = 0;
132266b0663SKrzysztof Zdziarski tx_mask = accel_dev->hw_device->tx_rings_mask;
133266b0663SKrzysztof Zdziarski asym_mask = accel_dev->hw_device->asym_rings_mask;
134266b0663SKrzysztof Zdziarski
135266b0663SKrzysztof Zdziarski /* Get ring mask for this process. */
136266b0663SKrzysztof Zdziarski bundle = &accel->bundle[bank];
137266b0663SKrzysztof Zdziarski orphan_bundle->bundle = bundle;
138266b0663SKrzysztof Zdziarski mutex_lock(&bundle->list_lock);
139266b0663SKrzysztof Zdziarski list_for_each(entry, &bundle->list)
140266b0663SKrzysztof Zdziarski {
141266b0663SKrzysztof Zdziarski instance_rings =
142266b0663SKrzysztof Zdziarski list_entry(entry, struct adf_uio_instance_rings, list);
143266b0663SKrzysztof Zdziarski if (instance_rings->user_pid == curproc->p_pid) {
144266b0663SKrzysztof Zdziarski ring_mask = instance_rings->ring_mask;
145266b0663SKrzysztof Zdziarski break;
146266b0663SKrzysztof Zdziarski }
147266b0663SKrzysztof Zdziarski }
148266b0663SKrzysztof Zdziarski mutex_unlock(&bundle->list_lock);
149266b0663SKrzysztof Zdziarski
150266b0663SKrzysztof Zdziarski for (i = 0; i < num_rings_per_bank; i++) {
151266b0663SKrzysztof Zdziarski base = csr_ops->read_csr_ring_base(csr_base, bank, i);
152266b0663SKrzysztof Zdziarski
153266b0663SKrzysztof Zdziarski if (!base)
154266b0663SKrzysztof Zdziarski continue;
155266b0663SKrzysztof Zdziarski if (!(ring_mask & 1 << i))
156266b0663SKrzysztof Zdziarski continue; /* Not reserved for this process. */
157266b0663SKrzysztof Zdziarski
158266b0663SKrzysztof Zdziarski if (test_bit(i, &tx_mask))
159266b0663SKrzysztof Zdziarski __set_bit(i, &orphan_bundle->tx_mask);
160266b0663SKrzysztof Zdziarski else
161266b0663SKrzysztof Zdziarski __set_bit(i, &orphan_bundle->rx_mask);
162266b0663SKrzysztof Zdziarski
163266b0663SKrzysztof Zdziarski if (test_bit(i, &asym_mask))
164266b0663SKrzysztof Zdziarski __set_bit(i, &orphan_bundle->asym_mask);
165266b0663SKrzysztof Zdziarski }
166266b0663SKrzysztof Zdziarski
167266b0663SKrzysztof Zdziarski if (orphan_bundle->tx_mask || orphan_bundle->rx_mask)
168266b0663SKrzysztof Zdziarski check_orphan_ring(accel_dev, orphan_bundle, hw_data);
169266b0663SKrzysztof Zdziarski
170266b0663SKrzysztof Zdziarski *orphan_bundle_out = orphan_bundle;
171266b0663SKrzysztof Zdziarski return ret;
172266b0663SKrzysztof Zdziarski }
173266b0663SKrzysztof Zdziarski
174266b0663SKrzysztof Zdziarski static void
put_orphan_bundle(struct bundle_orphan_ring * bundle)175266b0663SKrzysztof Zdziarski put_orphan_bundle(struct bundle_orphan_ring *bundle)
176266b0663SKrzysztof Zdziarski {
177266b0663SKrzysztof Zdziarski if (!bundle)
178266b0663SKrzysztof Zdziarski return;
179266b0663SKrzysztof Zdziarski
180266b0663SKrzysztof Zdziarski free(bundle, M_QAT);
181266b0663SKrzysztof Zdziarski }
182266b0663SKrzysztof Zdziarski
183266b0663SKrzysztof Zdziarski /* cleanup all ring */
184266b0663SKrzysztof Zdziarski static void
cleanup_all_ring(struct adf_uio_control_accel * accel,struct bundle_orphan_ring * orphan)185266b0663SKrzysztof Zdziarski cleanup_all_ring(struct adf_uio_control_accel *accel,
186266b0663SKrzysztof Zdziarski struct bundle_orphan_ring *orphan)
187266b0663SKrzysztof Zdziarski {
188266b0663SKrzysztof Zdziarski int i;
189266b0663SKrzysztof Zdziarski struct resource *csr_base = orphan->csr_base;
190266b0663SKrzysztof Zdziarski unsigned long mask = orphan->rx_mask | orphan->tx_mask;
191266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev = accel->accel_dev;
192266b0663SKrzysztof Zdziarski struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(accel_dev);
193266b0663SKrzysztof Zdziarski struct adf_hw_device_data *hw_data = accel_dev->hw_device;
194266b0663SKrzysztof Zdziarski u8 num_rings_per_bank = hw_data->num_rings_per_bank;
195266b0663SKrzysztof Zdziarski int bank = orphan->bank;
196266b0663SKrzysztof Zdziarski
197266b0663SKrzysztof Zdziarski mutex_lock(&orphan->bundle->lock);
198266b0663SKrzysztof Zdziarski orphan->bundle->rings_enabled &= ~mask;
199266b0663SKrzysztof Zdziarski adf_update_uio_ring_arb(orphan->bundle);
200266b0663SKrzysztof Zdziarski mutex_unlock(&orphan->bundle->lock);
201266b0663SKrzysztof Zdziarski
202266b0663SKrzysztof Zdziarski for (i = 0; i < num_rings_per_bank; i++) {
203266b0663SKrzysztof Zdziarski if (!test_bit(i, &mask))
204266b0663SKrzysztof Zdziarski continue;
205266b0663SKrzysztof Zdziarski
206266b0663SKrzysztof Zdziarski csr_ops->write_csr_ring_config(csr_base, bank, i, 0);
207266b0663SKrzysztof Zdziarski csr_ops->write_csr_ring_base(csr_base, bank, i, 0);
208266b0663SKrzysztof Zdziarski }
209266b0663SKrzysztof Zdziarski }
210266b0663SKrzysztof Zdziarski
211266b0663SKrzysztof Zdziarski /*
212266b0663SKrzysztof Zdziarski * Return true, if number of messages in tx ring is equal to number
213266b0663SKrzysztof Zdziarski * of messages in corresponding rx ring, else false.
214266b0663SKrzysztof Zdziarski */
215266b0663SKrzysztof Zdziarski static bool
is_all_resp_recvd(struct adf_hw_csr_ops * csr_ops,struct bundle_orphan_ring * bundle,const u8 num_rings_per_bank)216266b0663SKrzysztof Zdziarski is_all_resp_recvd(struct adf_hw_csr_ops *csr_ops,
217266b0663SKrzysztof Zdziarski struct bundle_orphan_ring *bundle,
218266b0663SKrzysztof Zdziarski const u8 num_rings_per_bank)
219266b0663SKrzysztof Zdziarski {
220266b0663SKrzysztof Zdziarski u32 rx_tail = 0, tx_head = 0, rx_ring_msg_offset = 0,
221266b0663SKrzysztof Zdziarski tx_ring_msg_offset = 0, tx_rx_offset = num_rings_per_bank / 2,
222266b0663SKrzysztof Zdziarski idx = 0, retry = 0, delay = ADF_RING_EMPTY_RETRY_DELAY;
223266b0663SKrzysztof Zdziarski
224266b0663SKrzysztof Zdziarski do {
225266b0663SKrzysztof Zdziarski for_each_set_bit(idx, &bundle->tx_mask, tx_rx_offset)
226266b0663SKrzysztof Zdziarski {
227266b0663SKrzysztof Zdziarski rx_tail =
228266b0663SKrzysztof Zdziarski csr_ops->read_csr_ring_tail(bundle->csr_base,
229266b0663SKrzysztof Zdziarski 0,
230266b0663SKrzysztof Zdziarski (idx + tx_rx_offset));
231266b0663SKrzysztof Zdziarski tx_head = csr_ops->read_csr_ring_head(bundle->csr_base,
232266b0663SKrzysztof Zdziarski 0,
233266b0663SKrzysztof Zdziarski idx);
234266b0663SKrzysztof Zdziarski
235266b0663SKrzysztof Zdziarski /*
236266b0663SKrzysztof Zdziarski * Normalize messages in tx rings to match rx ring
237266b0663SKrzysztof Zdziarski * message size, i.e., size of response message(32).
238266b0663SKrzysztof Zdziarski * Asym messages are 64 bytes each, so right shift
239266b0663SKrzysztof Zdziarski * by 1 to normalize to 32. Sym and compression
240266b0663SKrzysztof Zdziarski * messages are 128 bytes each, so right shift by 2
241266b0663SKrzysztof Zdziarski * to normalize to 32.
242266b0663SKrzysztof Zdziarski */
243266b0663SKrzysztof Zdziarski if (bundle->asym_mask & (1 << idx))
244266b0663SKrzysztof Zdziarski tx_ring_msg_offset = (tx_head >> 1);
245266b0663SKrzysztof Zdziarski else
246266b0663SKrzysztof Zdziarski tx_ring_msg_offset = (tx_head >> 2);
247266b0663SKrzysztof Zdziarski
248266b0663SKrzysztof Zdziarski rx_ring_msg_offset = rx_tail;
249266b0663SKrzysztof Zdziarski
250266b0663SKrzysztof Zdziarski if (tx_ring_msg_offset != rx_ring_msg_offset)
251266b0663SKrzysztof Zdziarski break;
252266b0663SKrzysztof Zdziarski }
253266b0663SKrzysztof Zdziarski if (idx == tx_rx_offset)
254266b0663SKrzysztof Zdziarski /* All Tx and Rx ring message counts match */
255266b0663SKrzysztof Zdziarski return true;
256266b0663SKrzysztof Zdziarski
257266b0663SKrzysztof Zdziarski DELAY(delay);
258266b0663SKrzysztof Zdziarski delay *= 2;
259266b0663SKrzysztof Zdziarski } while (++retry < ADF_RING_EMPTY_MAX_RETRY);
260266b0663SKrzysztof Zdziarski
261266b0663SKrzysztof Zdziarski return false;
262266b0663SKrzysztof Zdziarski }
263266b0663SKrzysztof Zdziarski
264266b0663SKrzysztof Zdziarski static int
bundle_need_cleanup(int bank,struct adf_uio_control_accel * accel)265266b0663SKrzysztof Zdziarski bundle_need_cleanup(int bank, struct adf_uio_control_accel *accel)
266266b0663SKrzysztof Zdziarski {
267266b0663SKrzysztof Zdziarski struct resource *csr_base = accel->bar->virt_addr;
268266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev = accel->accel_dev;
269266b0663SKrzysztof Zdziarski struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(accel_dev);
270266b0663SKrzysztof Zdziarski struct adf_hw_device_data *hw_data = accel_dev->hw_device;
271266b0663SKrzysztof Zdziarski u8 num_rings_per_bank = hw_data->num_rings_per_bank;
272266b0663SKrzysztof Zdziarski int i;
273266b0663SKrzysztof Zdziarski
274266b0663SKrzysztof Zdziarski if (!csr_base)
275266b0663SKrzysztof Zdziarski return 0;
276266b0663SKrzysztof Zdziarski
277266b0663SKrzysztof Zdziarski for (i = 0; i < num_rings_per_bank; i++) {
278266b0663SKrzysztof Zdziarski if (csr_ops->read_csr_ring_base(csr_base, bank, i))
279266b0663SKrzysztof Zdziarski return 1;
280266b0663SKrzysztof Zdziarski }
281266b0663SKrzysztof Zdziarski
282266b0663SKrzysztof Zdziarski return 0;
283266b0663SKrzysztof Zdziarski }
284266b0663SKrzysztof Zdziarski
285266b0663SKrzysztof Zdziarski static void
cleanup_orphan_ring(struct bundle_orphan_ring * orphan,struct adf_uio_control_accel * accel)286266b0663SKrzysztof Zdziarski cleanup_orphan_ring(struct bundle_orphan_ring *orphan,
287266b0663SKrzysztof Zdziarski struct adf_uio_control_accel *accel)
288266b0663SKrzysztof Zdziarski {
289266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev = accel->accel_dev;
290266b0663SKrzysztof Zdziarski struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(accel_dev);
291266b0663SKrzysztof Zdziarski struct adf_hw_device_data *hw_data = accel_dev->hw_device;
292266b0663SKrzysztof Zdziarski u8 number_rings_per_bank = hw_data->num_rings_per_bank;
293266b0663SKrzysztof Zdziarski
294266b0663SKrzysztof Zdziarski /* disable the interrupt */
295266b0663SKrzysztof Zdziarski csr_ops->write_csr_int_col_en(orphan->csr_base, orphan->bank, 0);
296266b0663SKrzysztof Zdziarski
297266b0663SKrzysztof Zdziarski /*
298266b0663SKrzysztof Zdziarski * wait firmware finish the in-process ring
299266b0663SKrzysztof Zdziarski * 1. disable all tx rings
300266b0663SKrzysztof Zdziarski * 2. check if all responses are received
301266b0663SKrzysztof Zdziarski * 3. reset all rings
302266b0663SKrzysztof Zdziarski */
303266b0663SKrzysztof Zdziarski adf_disable_ring_arb(accel_dev, orphan->csr_base, 0, orphan->tx_mask);
304266b0663SKrzysztof Zdziarski
305266b0663SKrzysztof Zdziarski if (!is_all_resp_recvd(csr_ops, orphan, number_rings_per_bank)) {
306266b0663SKrzysztof Zdziarski device_printf(GET_DEV(accel_dev),
307266b0663SKrzysztof Zdziarski "Failed to clean up orphan rings");
308266b0663SKrzysztof Zdziarski return;
309266b0663SKrzysztof Zdziarski }
310266b0663SKrzysztof Zdziarski
311266b0663SKrzysztof Zdziarski /*
312266b0663SKrzysztof Zdziarski * When the execution reaches here, it is assumed that
313266b0663SKrzysztof Zdziarski * there is no inflight request in the rings and that
314266b0663SKrzysztof Zdziarski * there is no in-process ring.
315266b0663SKrzysztof Zdziarski */
316266b0663SKrzysztof Zdziarski
317266b0663SKrzysztof Zdziarski cleanup_all_ring(accel, orphan);
318266b0663SKrzysztof Zdziarski }
319266b0663SKrzysztof Zdziarski
320266b0663SKrzysztof Zdziarski void
adf_uio_do_cleanup_orphan(int bank,struct adf_uio_control_accel * accel)321266b0663SKrzysztof Zdziarski adf_uio_do_cleanup_orphan(int bank, struct adf_uio_control_accel *accel)
322266b0663SKrzysztof Zdziarski {
323*22cf89c9SPiotr Kasierski int ret;
324266b0663SKrzysztof Zdziarski struct adf_uio_instance_rings *instance_rings, *tmp;
325266b0663SKrzysztof Zdziarski struct adf_uio_control_bundle *bundle;
326266b0663SKrzysztof Zdziarski /* orphan is local pointer allocated and deallocated in this function */
327266b0663SKrzysztof Zdziarski struct bundle_orphan_ring *orphan = NULL;
328266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev = accel->accel_dev;
329266b0663SKrzysztof Zdziarski struct adf_hw_device_data *hw_data = accel_dev->hw_device;
330266b0663SKrzysztof Zdziarski
331266b0663SKrzysztof Zdziarski if (!bundle_need_cleanup(bank, accel))
332266b0663SKrzysztof Zdziarski goto release;
333266b0663SKrzysztof Zdziarski
334266b0663SKrzysztof Zdziarski ret = get_orphan_bundle(bank, accel, &orphan);
335266b0663SKrzysztof Zdziarski if (ret != 0)
336266b0663SKrzysztof Zdziarski return;
337266b0663SKrzysztof Zdziarski
338266b0663SKrzysztof Zdziarski /*
339266b0663SKrzysztof Zdziarski * If driver supports ring pair reset, no matter process
340266b0663SKrzysztof Zdziarski * exits normally or abnormally, just do ring pair reset.
341266b0663SKrzysztof Zdziarski * ring pair reset will reset all ring pair registers to
342266b0663SKrzysztof Zdziarski * default value. Driver only needs to reset ring mask
343266b0663SKrzysztof Zdziarski */
344266b0663SKrzysztof Zdziarski if (hw_data->ring_pair_reset) {
345266b0663SKrzysztof Zdziarski hw_data->ring_pair_reset(
346266b0663SKrzysztof Zdziarski accel_dev, orphan->bundle->hardware_bundle_number);
347266b0663SKrzysztof Zdziarski /*
348266b0663SKrzysztof Zdziarski * If processes exit normally, rx_mask, tx_mask
349266b0663SKrzysztof Zdziarski * and rings_enabled are all 0, below expression
350266b0663SKrzysztof Zdziarski * have no impact on rings_enabled.
351266b0663SKrzysztof Zdziarski * If processes exit abnormally, rings_enabled
352266b0663SKrzysztof Zdziarski * will be set as 0 by below expression.
353266b0663SKrzysztof Zdziarski */
354266b0663SKrzysztof Zdziarski orphan->bundle->rings_enabled &=
355266b0663SKrzysztof Zdziarski ~(orphan->rx_mask | orphan->tx_mask);
356266b0663SKrzysztof Zdziarski goto out;
357266b0663SKrzysztof Zdziarski }
358266b0663SKrzysztof Zdziarski
359266b0663SKrzysztof Zdziarski if (!orphan->tx_mask && !orphan->rx_mask)
360266b0663SKrzysztof Zdziarski goto out;
361266b0663SKrzysztof Zdziarski
362266b0663SKrzysztof Zdziarski device_printf(GET_DEV(accel_dev),
363266b0663SKrzysztof Zdziarski "Process %d %s exit with orphan rings %lx:%lx\n",
364266b0663SKrzysztof Zdziarski curproc->p_pid,
365266b0663SKrzysztof Zdziarski curproc->p_comm,
366266b0663SKrzysztof Zdziarski orphan->tx_mask,
367266b0663SKrzysztof Zdziarski orphan->rx_mask);
368266b0663SKrzysztof Zdziarski
369266b0663SKrzysztof Zdziarski if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) {
370266b0663SKrzysztof Zdziarski cleanup_orphan_ring(orphan, accel);
371266b0663SKrzysztof Zdziarski }
372266b0663SKrzysztof Zdziarski out:
373266b0663SKrzysztof Zdziarski put_orphan_bundle(orphan);
374266b0663SKrzysztof Zdziarski
375266b0663SKrzysztof Zdziarski release:
376266b0663SKrzysztof Zdziarski
377266b0663SKrzysztof Zdziarski bundle = &accel->bundle[bank];
378266b0663SKrzysztof Zdziarski /*
379266b0663SKrzysztof Zdziarski * If the user process died without releasing the rings
380266b0663SKrzysztof Zdziarski * then force a release here.
381266b0663SKrzysztof Zdziarski */
382266b0663SKrzysztof Zdziarski mutex_lock(&bundle->list_lock);
383266b0663SKrzysztof Zdziarski list_for_each_entry_safe(instance_rings, tmp, &bundle->list, list)
384266b0663SKrzysztof Zdziarski {
385266b0663SKrzysztof Zdziarski if (instance_rings->user_pid == curproc->p_pid) {
386*22cf89c9SPiotr Kasierski bundle->rings_used &= ~instance_rings->ring_mask;
387266b0663SKrzysztof Zdziarski break;
388266b0663SKrzysztof Zdziarski }
389266b0663SKrzysztof Zdziarski }
390266b0663SKrzysztof Zdziarski mutex_unlock(&bundle->list_lock);
391266b0663SKrzysztof Zdziarski }
392