xref: /dpdk/drivers/crypto/caam_jr/caam_jr_uio.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
1e7a45f3cSGagandeep Singh /* SPDX-License-Identifier: BSD-3-Clause
2e7a45f3cSGagandeep Singh  * Copyright 2017-2018 NXP
3e7a45f3cSGagandeep Singh  */
4e7a45f3cSGagandeep Singh 
5e7a45f3cSGagandeep Singh #include <stdbool.h>
6e7a45f3cSGagandeep Singh #include <stdint.h>
7e7a45f3cSGagandeep Singh #include <stdio.h>
8e7a45f3cSGagandeep Singh #include <unistd.h>
9e7a45f3cSGagandeep Singh #include <stdlib.h>
10e7a45f3cSGagandeep Singh #include <dirent.h>
11e7a45f3cSGagandeep Singh #include <string.h>
12e7a45f3cSGagandeep Singh #include <sys/mman.h>
13e7a45f3cSGagandeep Singh #include <errno.h>
14e7a45f3cSGagandeep Singh #include <fcntl.h>
15e7a45f3cSGagandeep Singh 
16e7a45f3cSGagandeep Singh #include <rte_common.h>
17e7a45f3cSGagandeep Singh #include <rte_malloc.h>
18e7a45f3cSGagandeep Singh #include <rte_crypto.h>
19e7a45f3cSGagandeep Singh #include <rte_security.h>
20e7a45f3cSGagandeep Singh 
21e7a45f3cSGagandeep Singh #include <caam_jr_config.h>
22e7a45f3cSGagandeep Singh #include <caam_jr_hw_specific.h>
23e7a45f3cSGagandeep Singh #include <caam_jr_pvt.h>
24e7a45f3cSGagandeep Singh #include <caam_jr_log.h>
25e7a45f3cSGagandeep Singh 
26e7a45f3cSGagandeep Singh /* Prefix path to sysfs directory where UIO device attributes are exported.
27e7a45f3cSGagandeep Singh  * Path for UIO device X is /sys/class/uio/uioX
28e7a45f3cSGagandeep Singh  */
29e7a45f3cSGagandeep Singh #define SEC_UIO_DEVICE_SYS_ATTR_PATH    "/sys/class/uio"
30e7a45f3cSGagandeep Singh 
31e7a45f3cSGagandeep Singh /* Subfolder in sysfs where mapping attributes are exported
32e7a45f3cSGagandeep Singh  * for each UIO device. Path for mapping Y for device X is:
33e7a45f3cSGagandeep Singh  *      /sys/class/uio/uioX/maps/mapY
34e7a45f3cSGagandeep Singh  */
35e7a45f3cSGagandeep Singh #define SEC_UIO_DEVICE_SYS_MAP_ATTR     "maps/map"
36e7a45f3cSGagandeep Singh 
37e7a45f3cSGagandeep Singh /* Name of UIO device file prefix. Each UIO device will have a device file
38e7a45f3cSGagandeep Singh  * /dev/uioX, where X is the minor device number.
39e7a45f3cSGagandeep Singh  */
40e7a45f3cSGagandeep Singh #define SEC_UIO_DEVICE_FILE_NAME    "/dev/uio"
41e7a45f3cSGagandeep Singh 
42e7a45f3cSGagandeep Singh /*
43e7a45f3cSGagandeep Singh  * Name of UIO device. Each user space SEC job ring will have a corresponding
44e7a45f3cSGagandeep Singh  * UIO device with the name sec-channelX, where X is the job ring id.
45e7a45f3cSGagandeep Singh  * Maximum length is #SEC_UIO_MAX_DEVICE_NAME_LENGTH.
46e7a45f3cSGagandeep Singh  *
47e7a45f3cSGagandeep Singh  * @note  Must be kept in synch with SEC kernel driver
48e7a45f3cSGagandeep Singh  * define #SEC_UIO_DEVICE_NAME !
49e7a45f3cSGagandeep Singh  */
50e7a45f3cSGagandeep Singh #define SEC_UIO_DEVICE_NAME     "fsl-jr"
51e7a45f3cSGagandeep Singh 
52e7a45f3cSGagandeep Singh /* Maximum length for the name of an UIO device file.
53e7a45f3cSGagandeep Singh  * Device file name format is: /dev/uioX.
54e7a45f3cSGagandeep Singh  */
55e7a45f3cSGagandeep Singh #define SEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH 30
56e7a45f3cSGagandeep Singh 
57e7a45f3cSGagandeep Singh /* Maximum length for the name of an attribute file for an UIO device.
58e7a45f3cSGagandeep Singh  * Attribute files are exported in sysfs and have the name formatted as:
59e7a45f3cSGagandeep Singh  *      /sys/class/uio/uioX/<attribute_file_name>
60e7a45f3cSGagandeep Singh  */
61e7a45f3cSGagandeep Singh #define SEC_UIO_MAX_ATTR_FILE_NAME  100
62e7a45f3cSGagandeep Singh 
63e7a45f3cSGagandeep Singh /* Command that is used by SEC user space driver and SEC kernel driver
64e7a45f3cSGagandeep Singh  *  to signal a request from the former to the later to disable job DONE
65e7a45f3cSGagandeep Singh  *  and error IRQs on a certain job ring.
66e7a45f3cSGagandeep Singh  *  The configuration is done at SEC Controller's level.
67e7a45f3cSGagandeep Singh  *  @note   Need to be kept in synch with #SEC_UIO_DISABLE_IRQ_CMD from
68e7a45f3cSGagandeep Singh  *          linux/drivers/crypto/talitos.c !
69e7a45f3cSGagandeep Singh  */
70e7a45f3cSGagandeep Singh #define SEC_UIO_DISABLE_IRQ_CMD     0
71e7a45f3cSGagandeep Singh 
72e7a45f3cSGagandeep Singh /* Command that is used by SEC user space driver and SEC kernel driver
73e7a45f3cSGagandeep Singh  *  to signal a request from the former to the later to enable job DONE
74e7a45f3cSGagandeep Singh  *  and error IRQs on a certain job ring.
75e7a45f3cSGagandeep Singh  *  The configuration is done at SEC Controller's level.
76e7a45f3cSGagandeep Singh  *  @note   Need to be kept in synch with #SEC_UIO_ENABLE_IRQ_CMD from
77e7a45f3cSGagandeep Singh  *          linux/drivers/crypto/talitos.c !
78e7a45f3cSGagandeep Singh  */
79e7a45f3cSGagandeep Singh #define SEC_UIO_ENABLE_IRQ_CMD      1
80e7a45f3cSGagandeep Singh 
81e7a45f3cSGagandeep Singh /** Command that is used by SEC user space driver and SEC kernel driver
82e7a45f3cSGagandeep Singh  *  to signal a request from the former to the later to do a SEC engine reset.
83e7a45f3cSGagandeep Singh  *  @note   Need to be kept in synch with #SEC_UIO_RESET_SEC_ENGINE_CMD from
84e7a45f3cSGagandeep Singh  *          linux/drivers/crypto/talitos.c !
85e7a45f3cSGagandeep Singh  */
86e7a45f3cSGagandeep Singh #define SEC_UIO_RESET_SEC_ENGINE_CMD    3
87e7a45f3cSGagandeep Singh 
88e7a45f3cSGagandeep Singh /* The id for the mapping used to export SEC's registers to
89e7a45f3cSGagandeep Singh  * user space through UIO devices.
90e7a45f3cSGagandeep Singh  */
91e7a45f3cSGagandeep Singh #define SEC_UIO_MAP_ID              0
92e7a45f3cSGagandeep Singh 
93e7a45f3cSGagandeep Singh static struct uio_job_ring g_uio_job_ring[MAX_SEC_JOB_RINGS];
94e7a45f3cSGagandeep Singh static int g_uio_jr_num;
95e7a45f3cSGagandeep Singh 
96e7a45f3cSGagandeep Singh /** @brief Checks if a file name contains a certain substring.
97e7a45f3cSGagandeep Singh  * If so, it extracts the number following the substring.
98e7a45f3cSGagandeep Singh  * This function assumes a filename format of: [text][number].
99e7a45f3cSGagandeep Singh  * @param [in]  filename    File name
100e7a45f3cSGagandeep Singh  * @param [in]  match       String to match in file name
101e7a45f3cSGagandeep Singh  * @param [out] number      The number extracted from filename
102e7a45f3cSGagandeep Singh  *
103e7a45f3cSGagandeep Singh  * @retval true if file name matches the criteria
104e7a45f3cSGagandeep Singh  * @retval false if file name does not match the criteria
105e7a45f3cSGagandeep Singh  */
106e7a45f3cSGagandeep Singh static bool
107e7a45f3cSGagandeep Singh file_name_match_extract(const char filename[], const char match[], int *number)
108e7a45f3cSGagandeep Singh {
109e7a45f3cSGagandeep Singh 	char *substr = NULL;
110e7a45f3cSGagandeep Singh 
111e7a45f3cSGagandeep Singh 	substr = strstr(filename, match);
112e7a45f3cSGagandeep Singh 	if (substr == NULL)
113e7a45f3cSGagandeep Singh 		return false;
114e7a45f3cSGagandeep Singh 
115e7a45f3cSGagandeep Singh 	/* substring <match> was found in <filename>
116e7a45f3cSGagandeep Singh 	 * read number following <match> substring in <filename>
117e7a45f3cSGagandeep Singh 	 */
118e7a45f3cSGagandeep Singh 	if (sscanf(filename + strlen(match), "%d", number) <= 0)
119e7a45f3cSGagandeep Singh 		return false;
120e7a45f3cSGagandeep Singh 
121e7a45f3cSGagandeep Singh 	return true;
122e7a45f3cSGagandeep Singh }
123e7a45f3cSGagandeep Singh 
124e7a45f3cSGagandeep Singh /** @brief Reads first line from a file.
125e7a45f3cSGagandeep Singh  * Composes file name as: root/subdir/filename
126e7a45f3cSGagandeep Singh  *
127e7a45f3cSGagandeep Singh  * @param [in]  root     Root path
128e7a45f3cSGagandeep Singh  * @param [in]  subdir   Subdirectory name
129e7a45f3cSGagandeep Singh  * @param [in]  filename File name
130e7a45f3cSGagandeep Singh  * @param [out] line     The first line read from file.
131e7a45f3cSGagandeep Singh  *
132e7a45f3cSGagandeep Singh  * @retval 0 for succes
133e7a45f3cSGagandeep Singh  * @retval other value for error
134e7a45f3cSGagandeep Singh  */
135e7a45f3cSGagandeep Singh static int
136e7a45f3cSGagandeep Singh file_read_first_line(const char root[], const char subdir[],
137e7a45f3cSGagandeep Singh 		     const char filename[], char *line)
138e7a45f3cSGagandeep Singh {
139e7a45f3cSGagandeep Singh 	char absolute_file_name[SEC_UIO_MAX_ATTR_FILE_NAME];
140e7a45f3cSGagandeep Singh 	int fd = 0, ret = 0;
141e7a45f3cSGagandeep Singh 
142e7a45f3cSGagandeep Singh 	/*compose the file name: root/subdir/filename */
143e7a45f3cSGagandeep Singh 	memset(absolute_file_name, 0, sizeof(absolute_file_name));
144e7a45f3cSGagandeep Singh 	snprintf(absolute_file_name, SEC_UIO_MAX_ATTR_FILE_NAME,
145e7a45f3cSGagandeep Singh 		 "%s/%s/%s", root, subdir, filename);
146e7a45f3cSGagandeep Singh 
147e7a45f3cSGagandeep Singh 	fd = open(absolute_file_name, O_RDONLY);
14861552661SYunjian Wang 	SEC_ASSERT(fd >= 0, fd, "Error opening file %s",
149e7a45f3cSGagandeep Singh 			absolute_file_name);
150e7a45f3cSGagandeep Singh 
151e7a45f3cSGagandeep Singh 	/* read UIO device name from first line in file */
152e7a45f3cSGagandeep Singh 	ret = read(fd, line, SEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH);
153e7a45f3cSGagandeep Singh 	close(fd);
154e7a45f3cSGagandeep Singh 
155e7a45f3cSGagandeep Singh 	/* NULL-ify string */
156e7a45f3cSGagandeep Singh 	line[SEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH - 1] = '\0';
157e7a45f3cSGagandeep Singh 
158e7a45f3cSGagandeep Singh 	if (ret <= 0) {
159e7a45f3cSGagandeep Singh 		CAAM_JR_ERR("Error reading from file %s", absolute_file_name);
160e7a45f3cSGagandeep Singh 		return ret;
161e7a45f3cSGagandeep Singh 	}
162e7a45f3cSGagandeep Singh 
163e7a45f3cSGagandeep Singh 	return 0;
164e7a45f3cSGagandeep Singh }
165e7a45f3cSGagandeep Singh 
166e7a45f3cSGagandeep Singh /** @brief Uses UIO control to send commands to SEC kernel driver.
167e7a45f3cSGagandeep Singh  * The mechanism is to write a command word into the file descriptor
168e7a45f3cSGagandeep Singh  * that the user-space driver obtained for each user-space SEC job ring.
169e7a45f3cSGagandeep Singh  * Both user-space driver and kernel driver must have the same understanding
170e7a45f3cSGagandeep Singh  * about the command codes.
171e7a45f3cSGagandeep Singh  *
172e7a45f3cSGagandeep Singh  * @param [in]  UIO FD		    The UIO file descriptor
173e7a45f3cSGagandeep Singh  * @param [in]  uio_command         Command word
174e7a45f3cSGagandeep Singh  *
175e7a45f3cSGagandeep Singh  * @retval Result of write operation on the job ring's UIO file descriptor.
176e7a45f3cSGagandeep Singh  *         Should be sizeof(int) for success operations.
177e7a45f3cSGagandeep Singh  *         Other values can be returned and used, if desired to add special
178e7a45f3cSGagandeep Singh  *         meaning to return values, but this has to be programmed in SEC
179e7a45f3cSGagandeep Singh  *         kernel driver as well. No special return values are used.
180e7a45f3cSGagandeep Singh  */
181e7a45f3cSGagandeep Singh static int
18261552661SYunjian Wang sec_uio_send_command(int uio_fd, int32_t uio_command)
183e7a45f3cSGagandeep Singh {
184e7a45f3cSGagandeep Singh 	int ret;
185e7a45f3cSGagandeep Singh 
186e7a45f3cSGagandeep Singh 	/* Use UIO file descriptor we have for this job ring.
187e7a45f3cSGagandeep Singh 	 * Writing a command code to this file descriptor will make the
188e7a45f3cSGagandeep Singh 	 * SEC kernel driver execute the desired command.
189e7a45f3cSGagandeep Singh 	 */
190e7a45f3cSGagandeep Singh 	ret = write(uio_fd, &uio_command, sizeof(int));
191e7a45f3cSGagandeep Singh 	return ret;
192e7a45f3cSGagandeep Singh }
193e7a45f3cSGagandeep Singh 
194e7a45f3cSGagandeep Singh /** @brief Request to SEC kernel driver to enable interrupts for
195e7a45f3cSGagandeep Singh  *         descriptor finished processing
196e7a45f3cSGagandeep Singh  *  Use UIO to communicate with SEC kernel driver: write command
197e7a45f3cSGagandeep Singh  *  value that indicates an IRQ enable action into UIO file descriptor
198e7a45f3cSGagandeep Singh  *  of this job ring.
199e7a45f3cSGagandeep Singh  *
200e7a45f3cSGagandeep Singh  * @param [in]  uio_fd     Job Ring UIO File descriptor
201e7a45f3cSGagandeep Singh  * @retval 0 for success
202e7a45f3cSGagandeep Singh  * @retval -1 value for error
203e7a45f3cSGagandeep Singh  */
204c40b4fcdSYunjian Wang int
20561552661SYunjian Wang caam_jr_enable_irqs(int uio_fd)
206e7a45f3cSGagandeep Singh {
207e7a45f3cSGagandeep Singh 	int ret;
208e7a45f3cSGagandeep Singh 
209e7a45f3cSGagandeep Singh 	/* Use UIO file descriptor we have for this job ring.
210e7a45f3cSGagandeep Singh 	 * Writing a command code to this file descriptor will make the
211e7a45f3cSGagandeep Singh 	 * SEC kernel driver enable DONE and Error IRQs for this job ring,
212e7a45f3cSGagandeep Singh 	 * at Controller level.
213e7a45f3cSGagandeep Singh 	 */
214e7a45f3cSGagandeep Singh 	ret = sec_uio_send_command(uio_fd, SEC_UIO_ENABLE_IRQ_CMD);
215e7a45f3cSGagandeep Singh 	SEC_ASSERT(ret == sizeof(int), -1,
216e7a45f3cSGagandeep Singh 		"Failed to request SEC engine to enable job done and "
217e7a45f3cSGagandeep Singh 		"error IRQs through UIO control. UIO FD %d. Reset SEC driver!",
218e7a45f3cSGagandeep Singh 		uio_fd);
219e7a45f3cSGagandeep Singh 	CAAM_JR_DEBUG("Enabled IRQs on jr with uio_fd %d", uio_fd);
220e7a45f3cSGagandeep Singh 	return 0;
221e7a45f3cSGagandeep Singh }
222e7a45f3cSGagandeep Singh 
223e7a45f3cSGagandeep Singh 
224e7a45f3cSGagandeep Singh /** @brief Request to SEC kernel driver to disable interrupts for descriptor
225e7a45f3cSGagandeep Singh  *  finished processing
226e7a45f3cSGagandeep Singh  *  Use UIO to communicate with SEC kernel driver: write command
227e7a45f3cSGagandeep Singh  *  value that indicates an IRQ disable action into UIO file descriptor
228e7a45f3cSGagandeep Singh  *  of this job ring.
229e7a45f3cSGagandeep Singh  *
2307be78d02SJosh Soref  * @param [in]  uio_fd    UIO File descriptor
231e7a45f3cSGagandeep Singh  * @retval 0 for success
232e7a45f3cSGagandeep Singh  * @retval -1 value for error
233e7a45f3cSGagandeep Singh  *
234e7a45f3cSGagandeep Singh  */
235c40b4fcdSYunjian Wang int
23661552661SYunjian Wang caam_jr_disable_irqs(int uio_fd)
237e7a45f3cSGagandeep Singh {
238e7a45f3cSGagandeep Singh 	int ret;
239e7a45f3cSGagandeep Singh 
240e7a45f3cSGagandeep Singh 	/* Use UIO file descriptor we have for this job ring.
241e7a45f3cSGagandeep Singh 	 * Writing a command code to this file descriptor will make the
242e7a45f3cSGagandeep Singh 	 * SEC kernel driver disable IRQs for this job ring,
243e7a45f3cSGagandeep Singh 	 * at Controller level.
244e7a45f3cSGagandeep Singh 	 */
245e7a45f3cSGagandeep Singh 
246e7a45f3cSGagandeep Singh 	ret = sec_uio_send_command(uio_fd, SEC_UIO_DISABLE_IRQ_CMD);
247e7a45f3cSGagandeep Singh 	SEC_ASSERT(ret == sizeof(int), -1,
248e7a45f3cSGagandeep Singh 		"Failed to request SEC engine to disable job done and "
249e7a45f3cSGagandeep Singh 		"IRQs through UIO control. UIO_FD %d Reset SEC driver!",
250e7a45f3cSGagandeep Singh 		uio_fd);
251e7a45f3cSGagandeep Singh 	CAAM_JR_DEBUG("Disabled IRQs on jr with uio_fd %d", uio_fd);
252e7a45f3cSGagandeep Singh 	return 0;
253e7a45f3cSGagandeep Singh }
254e7a45f3cSGagandeep Singh 
255e7a45f3cSGagandeep Singh /** @brief Maps register range assigned for a job ring.
256e7a45f3cSGagandeep Singh  *
257e7a45f3cSGagandeep Singh  * @param [in] uio_device_fd    UIO device file descriptor
258e7a45f3cSGagandeep Singh  * @param [in] uio_device_id    UIO device id
259e7a45f3cSGagandeep Singh  * @param [in] uio_map_id       UIO allows maximum 5 different mapping for
260e7a45f3cSGagandeep Singh 				each device. Maps start with id 0.
261e7a45f3cSGagandeep Singh  * @param [out] map_size        Map size.
262e7a45f3cSGagandeep Singh  * @retval  NULL if failed to map registers
263e7a45f3cSGagandeep Singh  * @retval  Virtual address for mapped register address range
264e7a45f3cSGagandeep Singh  */
265e7a45f3cSGagandeep Singh static void *
266e7a45f3cSGagandeep Singh uio_map_registers(int uio_device_fd, int uio_device_id,
267e7a45f3cSGagandeep Singh 		  int uio_map_id, int *map_size)
268e7a45f3cSGagandeep Singh {
269e7a45f3cSGagandeep Singh 	void *mapped_address = NULL;
270e7a45f3cSGagandeep Singh 	unsigned int uio_map_size = 0;
271e7a45f3cSGagandeep Singh 	char uio_sys_root[SEC_UIO_MAX_ATTR_FILE_NAME];
272e7a45f3cSGagandeep Singh 	char uio_sys_map_subdir[SEC_UIO_MAX_ATTR_FILE_NAME];
273e7a45f3cSGagandeep Singh 	char uio_map_size_str[32];
274e7a45f3cSGagandeep Singh 	int ret = 0;
275e7a45f3cSGagandeep Singh 
276e7a45f3cSGagandeep Singh 	/* compose the file name: root/subdir/filename */
277e7a45f3cSGagandeep Singh 	memset(uio_sys_root, 0, sizeof(uio_sys_root));
278e7a45f3cSGagandeep Singh 	memset(uio_sys_map_subdir, 0, sizeof(uio_sys_map_subdir));
279e7a45f3cSGagandeep Singh 	memset(uio_map_size_str, 0, sizeof(uio_map_size_str));
280e7a45f3cSGagandeep Singh 
281e7a45f3cSGagandeep Singh 	/* Compose string: /sys/class/uio/uioX */
282a1e8241aSPallantla Poornima 	snprintf(uio_sys_root, sizeof(uio_sys_root), "%s/%s%d",
283a1e8241aSPallantla Poornima 			SEC_UIO_DEVICE_SYS_ATTR_PATH, "uio", uio_device_id);
284e7a45f3cSGagandeep Singh 	/* Compose string: maps/mapY */
285a1e8241aSPallantla Poornima 	snprintf(uio_sys_map_subdir, sizeof(uio_sys_map_subdir), "%s%d",
286a1e8241aSPallantla Poornima 			SEC_UIO_DEVICE_SYS_MAP_ATTR, uio_map_id);
287e7a45f3cSGagandeep Singh 
288e7a45f3cSGagandeep Singh 	/* Read first (and only) line from file
289e7a45f3cSGagandeep Singh 	 * /sys/class/uio/uioX/maps/mapY/size
290e7a45f3cSGagandeep Singh 	 */
291e7a45f3cSGagandeep Singh 	ret = file_read_first_line(uio_sys_root, uio_sys_map_subdir,
292e7a45f3cSGagandeep Singh 				 "size", uio_map_size_str);
293e7a45f3cSGagandeep Singh 	SEC_ASSERT(ret == 0, NULL, "file_read_first_line() failed");
294e7a45f3cSGagandeep Singh 
295e7a45f3cSGagandeep Singh 	/* Read mapping size, expressed in hexa(base 16) */
296e7a45f3cSGagandeep Singh 	uio_map_size = strtol(uio_map_size_str, NULL, 16);
297e7a45f3cSGagandeep Singh 
298e7a45f3cSGagandeep Singh 	/* Map the region in user space */
299e7a45f3cSGagandeep Singh 	mapped_address = mmap(0, /*dynamically choose virtual address */
300e7a45f3cSGagandeep Singh 		uio_map_size, PROT_READ | PROT_WRITE,
301e7a45f3cSGagandeep Singh 		MAP_SHARED, uio_device_fd, 0);
302e7a45f3cSGagandeep Singh 	/* offset = 0 because UIO device has only one mapping
303e7a45f3cSGagandeep Singh 	 * for the entire SEC register memory
304e7a45f3cSGagandeep Singh 	 */
305e7a45f3cSGagandeep Singh 	if (mapped_address == MAP_FAILED) {
306e7a45f3cSGagandeep Singh 		CAAM_JR_ERR(
307e7a45f3cSGagandeep Singh 			"Failed to map registers! errno = %d job ring fd  = %d,"
308e7a45f3cSGagandeep Singh 			"uio device id = %d, uio map id = %d", errno,
309e7a45f3cSGagandeep Singh 			uio_device_fd, uio_device_id, uio_map_id);
310e7a45f3cSGagandeep Singh 		return NULL;
311e7a45f3cSGagandeep Singh 	}
312e7a45f3cSGagandeep Singh 
313e7a45f3cSGagandeep Singh 	/*
314e7a45f3cSGagandeep Singh 	 * Save the map size to use it later on for munmap-ing.
315e7a45f3cSGagandeep Singh 	 */
316e7a45f3cSGagandeep Singh 	*map_size = uio_map_size;
317e7a45f3cSGagandeep Singh 
318e7a45f3cSGagandeep Singh 	CAAM_JR_INFO("UIO dev[%d] mapped region [id =%d] size 0x%x at %p",
319e7a45f3cSGagandeep Singh 		uio_device_id, uio_map_id, uio_map_size, mapped_address);
320e7a45f3cSGagandeep Singh 
321e7a45f3cSGagandeep Singh 	return mapped_address;
322e7a45f3cSGagandeep Singh }
323e7a45f3cSGagandeep Singh 
324e7a45f3cSGagandeep Singh void
32561552661SYunjian Wang free_job_ring(int uio_fd)
326e7a45f3cSGagandeep Singh {
327e7a45f3cSGagandeep Singh 	struct uio_job_ring *job_ring = NULL;
328e7a45f3cSGagandeep Singh 	int i;
329e7a45f3cSGagandeep Singh 
33061552661SYunjian Wang 	if (uio_fd == -1)
331e7a45f3cSGagandeep Singh 		return;
332e7a45f3cSGagandeep Singh 
333e7a45f3cSGagandeep Singh 	for (i = 0; i < MAX_SEC_JOB_RINGS; i++) {
334e7a45f3cSGagandeep Singh 		if (g_uio_job_ring[i].uio_fd == uio_fd) {
335e7a45f3cSGagandeep Singh 			job_ring = &g_uio_job_ring[i];
336e7a45f3cSGagandeep Singh 			break;
337e7a45f3cSGagandeep Singh 		}
338e7a45f3cSGagandeep Singh 	}
339e7a45f3cSGagandeep Singh 
340e7a45f3cSGagandeep Singh 	if (job_ring == NULL) {
341*f665790aSDavid Marchand 		CAAM_JR_ERR("JR not available for fd = %x", uio_fd);
342e7a45f3cSGagandeep Singh 		return;
343e7a45f3cSGagandeep Singh 	}
344e7a45f3cSGagandeep Singh 
345e7a45f3cSGagandeep Singh 	/* Open device file */
346e7a45f3cSGagandeep Singh 	CAAM_JR_INFO("Closed device file for job ring %d , fd = %d",
347e7a45f3cSGagandeep Singh 			job_ring->jr_id, job_ring->uio_fd);
348e7a45f3cSGagandeep Singh 	close(job_ring->uio_fd);
349e7a45f3cSGagandeep Singh 	g_uio_jr_num--;
35061552661SYunjian Wang 	job_ring->uio_fd = -1;
351e7a45f3cSGagandeep Singh 	if (job_ring->register_base_addr == NULL)
352e7a45f3cSGagandeep Singh 		return;
353e7a45f3cSGagandeep Singh 
354e7a45f3cSGagandeep Singh 	/* Unmap the PCI memory resource of device */
355e7a45f3cSGagandeep Singh 	if (munmap(job_ring->register_base_addr, job_ring->map_size)) {
356e7a45f3cSGagandeep Singh 		CAAM_JR_INFO("cannot munmap(%p, 0x%lx): %s",
357e7a45f3cSGagandeep Singh 			job_ring->register_base_addr,
358e7a45f3cSGagandeep Singh 			(unsigned long)job_ring->map_size, strerror(errno));
359e7a45f3cSGagandeep Singh 	} else
360c761bffeSGagandeep Singh 		CAAM_JR_DEBUG("JR UIO memory is unmapped");
361c761bffeSGagandeep Singh 
362e7a45f3cSGagandeep Singh 	job_ring->register_base_addr = NULL;
363e7a45f3cSGagandeep Singh }
364e7a45f3cSGagandeep Singh 
365e7a45f3cSGagandeep Singh struct
366e7a45f3cSGagandeep Singh uio_job_ring *config_job_ring(void)
367e7a45f3cSGagandeep Singh {
368e7a45f3cSGagandeep Singh 	char uio_device_file_name[32];
369e7a45f3cSGagandeep Singh 	struct uio_job_ring *job_ring = NULL;
370e7a45f3cSGagandeep Singh 	int i;
371e7a45f3cSGagandeep Singh 
372e7a45f3cSGagandeep Singh 	for (i = 0; i < MAX_SEC_JOB_RINGS; i++) {
37361552661SYunjian Wang 		if (g_uio_job_ring[i].uio_fd == -1) {
374e7a45f3cSGagandeep Singh 			job_ring = &g_uio_job_ring[i];
375e7a45f3cSGagandeep Singh 			g_uio_jr_num++;
376e7a45f3cSGagandeep Singh 			break;
377e7a45f3cSGagandeep Singh 		}
378e7a45f3cSGagandeep Singh 	}
379e7a45f3cSGagandeep Singh 
380e7a45f3cSGagandeep Singh 	if (job_ring == NULL) {
381*f665790aSDavid Marchand 		CAAM_JR_ERR("No free job ring");
382e7a45f3cSGagandeep Singh 		return NULL;
383e7a45f3cSGagandeep Singh 	}
384e7a45f3cSGagandeep Singh 
385e7a45f3cSGagandeep Singh 	/* Find UIO device created by SEC kernel driver for this job ring. */
386e7a45f3cSGagandeep Singh 	memset(uio_device_file_name, 0, sizeof(uio_device_file_name));
387a1e8241aSPallantla Poornima 	snprintf(uio_device_file_name, sizeof(uio_device_file_name), "%s%d",
388a1e8241aSPallantla Poornima 			SEC_UIO_DEVICE_FILE_NAME, job_ring->uio_minor_number);
389e7a45f3cSGagandeep Singh 
390e7a45f3cSGagandeep Singh 	/* Open device file */
391e7a45f3cSGagandeep Singh 	job_ring->uio_fd = open(uio_device_file_name, O_RDWR);
39261552661SYunjian Wang 	SEC_ASSERT(job_ring->uio_fd >= 0, NULL,
393e7a45f3cSGagandeep Singh 		"Failed to open UIO device file for job ring %d",
394e7a45f3cSGagandeep Singh 		job_ring->jr_id);
395e7a45f3cSGagandeep Singh 
396e7a45f3cSGagandeep Singh 	CAAM_JR_INFO("Open device(%s) file for job ring=%d , uio_fd = %d",
397e7a45f3cSGagandeep Singh 		uio_device_file_name, job_ring->jr_id, job_ring->uio_fd);
398e7a45f3cSGagandeep Singh 
399e7a45f3cSGagandeep Singh 	ASSERT(job_ring->register_base_addr == NULL);
400e7a45f3cSGagandeep Singh 	job_ring->register_base_addr = uio_map_registers(
401e7a45f3cSGagandeep Singh 			job_ring->uio_fd, job_ring->uio_minor_number,
402e7a45f3cSGagandeep Singh 			SEC_UIO_MAP_ID, &job_ring->map_size);
403e7a45f3cSGagandeep Singh 
404e7a45f3cSGagandeep Singh 	SEC_ASSERT(job_ring->register_base_addr != NULL, NULL,
405e7a45f3cSGagandeep Singh 		"Failed to map SEC registers");
406e7a45f3cSGagandeep Singh 	return job_ring;
407e7a45f3cSGagandeep Singh }
408e7a45f3cSGagandeep Singh 
409e7a45f3cSGagandeep Singh int
410e7a45f3cSGagandeep Singh sec_configure(void)
411e7a45f3cSGagandeep Singh {
412e7a45f3cSGagandeep Singh 	char uio_name[32];
413e7a45f3cSGagandeep Singh 	int config_jr_no = 0, jr_id = -1;
414e7a45f3cSGagandeep Singh 	int uio_minor_number = -1;
415e7a45f3cSGagandeep Singh 	int ret;
416e7a45f3cSGagandeep Singh 	DIR *d = NULL;
417e7a45f3cSGagandeep Singh 	struct dirent *dir;
418e7a45f3cSGagandeep Singh 
419e7a45f3cSGagandeep Singh 	d = opendir(SEC_UIO_DEVICE_SYS_ATTR_PATH);
420e7a45f3cSGagandeep Singh 	if (d == NULL) {
4210fcdbde0SHemant Agrawal 		CAAM_JR_ERR("Error opening directory '%s': %s",
422e7a45f3cSGagandeep Singh 			SEC_UIO_DEVICE_SYS_ATTR_PATH, strerror(errno));
423e7a45f3cSGagandeep Singh 		return -1;
424e7a45f3cSGagandeep Singh 	}
425e7a45f3cSGagandeep Singh 
426e7a45f3cSGagandeep Singh 	/* Iterate through all subdirs */
427e7a45f3cSGagandeep Singh 	while ((dir = readdir(d)) != NULL) {
428e7a45f3cSGagandeep Singh 		if (!strncmp(dir->d_name, ".", 1) ||
429e7a45f3cSGagandeep Singh 				!strncmp(dir->d_name, "..", 2))
430e7a45f3cSGagandeep Singh 			continue;
431e7a45f3cSGagandeep Singh 
432e7a45f3cSGagandeep Singh 		if (file_name_match_extract
433e7a45f3cSGagandeep Singh 			(dir->d_name, "uio", &uio_minor_number)) {
434e7a45f3cSGagandeep Singh 		/*
435e7a45f3cSGagandeep Singh 		 * Open file uioX/name and read first line which contains
436e7a45f3cSGagandeep Singh 		 * the name for the device. Based on the name check if this
437e7a45f3cSGagandeep Singh 		 * UIO device is UIO device for job ring with id jr_id.
438e7a45f3cSGagandeep Singh 		 */
439e7a45f3cSGagandeep Singh 			memset(uio_name, 0, sizeof(uio_name));
440e7a45f3cSGagandeep Singh 			ret = file_read_first_line(SEC_UIO_DEVICE_SYS_ATTR_PATH,
441e7a45f3cSGagandeep Singh 					dir->d_name, "name", uio_name);
442e7a45f3cSGagandeep Singh 			CAAM_JR_INFO("sec device uio name: %s", uio_name);
443c761bffeSGagandeep Singh 			if (ret != 0) {
444*f665790aSDavid Marchand 				CAAM_JR_ERR("file_read_first_line failed");
445c761bffeSGagandeep Singh 				closedir(d);
446c761bffeSGagandeep Singh 				return -1;
447c761bffeSGagandeep Singh 			}
448e7a45f3cSGagandeep Singh 
449e7a45f3cSGagandeep Singh 			if (file_name_match_extract(uio_name,
450e7a45f3cSGagandeep Singh 						SEC_UIO_DEVICE_NAME,
451e7a45f3cSGagandeep Singh 						&jr_id)) {
452e7a45f3cSGagandeep Singh 				g_uio_job_ring[config_jr_no].jr_id = jr_id;
453e7a45f3cSGagandeep Singh 				g_uio_job_ring[config_jr_no].uio_minor_number =
454e7a45f3cSGagandeep Singh 							uio_minor_number;
455e7a45f3cSGagandeep Singh 				CAAM_JR_INFO("Detected logical JRID:%d", jr_id);
456e7a45f3cSGagandeep Singh 				config_jr_no++;
457e7a45f3cSGagandeep Singh 
458e7a45f3cSGagandeep Singh 				/* todo  find the actual ring id
459e7a45f3cSGagandeep Singh 				 * OF_FULLNAME=/soc/crypto@1700000/jr@20000
460e7a45f3cSGagandeep Singh 				 */
461e7a45f3cSGagandeep Singh 			}
462e7a45f3cSGagandeep Singh 		}
463e7a45f3cSGagandeep Singh 	}
464e7a45f3cSGagandeep Singh 	closedir(d);
465e7a45f3cSGagandeep Singh 
466e7a45f3cSGagandeep Singh 	if (config_jr_no == 0) {
467e7a45f3cSGagandeep Singh 		CAAM_JR_ERR("! No SEC Job Rings assigned for userspace usage!");
468e7a45f3cSGagandeep Singh 		return 0;
469e7a45f3cSGagandeep Singh 	}
470e7a45f3cSGagandeep Singh 	CAAM_JR_INFO("Total JR detected =%d", config_jr_no);
471e7a45f3cSGagandeep Singh 	return config_jr_no;
472e7a45f3cSGagandeep Singh }
473e7a45f3cSGagandeep Singh 
474e7a45f3cSGagandeep Singh int
475e7a45f3cSGagandeep Singh sec_cleanup(void)
476e7a45f3cSGagandeep Singh {
477e7a45f3cSGagandeep Singh 	int i;
478e7a45f3cSGagandeep Singh 	struct uio_job_ring *job_ring;
479e7a45f3cSGagandeep Singh 
480e7a45f3cSGagandeep Singh 	for (i = 0; i < g_uio_jr_num; i++) {
481e7a45f3cSGagandeep Singh 		job_ring = &g_uio_job_ring[i];
482e7a45f3cSGagandeep Singh 		/* munmap SEC's register memory */
483e7a45f3cSGagandeep Singh 		if (job_ring->register_base_addr) {
484e7a45f3cSGagandeep Singh 			munmap(job_ring->register_base_addr,
485e7a45f3cSGagandeep Singh 				job_ring->map_size);
486e7a45f3cSGagandeep Singh 			job_ring->register_base_addr = NULL;
487e7a45f3cSGagandeep Singh 		}
488e7a45f3cSGagandeep Singh 		/* I need to close the fd after shutdown UIO commands need to be
489e7a45f3cSGagandeep Singh 		 * sent using the fd
490e7a45f3cSGagandeep Singh 		 */
49161552661SYunjian Wang 		if (job_ring->uio_fd != -1) {
492e7a45f3cSGagandeep Singh 			CAAM_JR_INFO(
493e7a45f3cSGagandeep Singh 			"Closed device file for job ring %d , fd = %d",
494e7a45f3cSGagandeep Singh 			job_ring->jr_id, job_ring->uio_fd);
495e7a45f3cSGagandeep Singh 			close(job_ring->uio_fd);
49661552661SYunjian Wang 			job_ring->uio_fd = -1;
497e7a45f3cSGagandeep Singh 		}
498e7a45f3cSGagandeep Singh 	}
499e7a45f3cSGagandeep Singh 	return 0;
500e7a45f3cSGagandeep Singh }
50161552661SYunjian Wang 
50261552661SYunjian Wang void
50361552661SYunjian Wang sec_uio_job_rings_init(void)
50461552661SYunjian Wang {
50561552661SYunjian Wang 	int i;
50661552661SYunjian Wang 
50761552661SYunjian Wang 	for (i = 0; i < MAX_SEC_JOB_RINGS; i++)
50861552661SYunjian Wang 		g_uio_job_ring[i].uio_fd = -1;
50961552661SYunjian Wang }
510