xref: /freebsd/sys/dev/qat/qat_common/adf_freebsd_uio_cleanup.c (revision 866dc4bd81398b478daefe4b7447b92422b4a06c)
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