New upstream version 18.02
[deb_dpdk.git] / drivers / bus / fslmc / mc / mc_sys.c
1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2  *
3  * Copyright 2013-2015 Freescale Semiconductor Inc.
4  * Copyright 2017 NXP
5  *
6  */
7 #include <fsl_mc_sys.h>
8 #include <fsl_mc_cmd.h>
9
10 #include <rte_spinlock.h>
11
12 /** User space framework uses MC Portal in shared mode. Following change
13  * introduces lock in MC FLIB
14  */
15
16 /**
17  * A static spinlock initializer.
18  */
19 static rte_spinlock_t mc_portal_lock = RTE_SPINLOCK_INITIALIZER;
20
21 static int mc_status_to_error(enum mc_cmd_status status)
22 {
23         switch (status) {
24         case MC_CMD_STATUS_OK:
25                 return 0;
26         case MC_CMD_STATUS_AUTH_ERR:
27                 return -EACCES; /* Token error */
28         case MC_CMD_STATUS_NO_PRIVILEGE:
29                 return -EPERM; /* Permission denied */
30         case MC_CMD_STATUS_DMA_ERR:
31                 return -EIO; /* Input/Output error */
32         case MC_CMD_STATUS_CONFIG_ERR:
33                 return -EINVAL; /* Device not configured */
34         case MC_CMD_STATUS_TIMEOUT:
35                 return -ETIMEDOUT; /* Operation timed out */
36         case MC_CMD_STATUS_NO_RESOURCE:
37                 return -ENAVAIL; /* Resource temporarily unavailable */
38         case MC_CMD_STATUS_NO_MEMORY:
39                 return -ENOMEM; /* Cannot allocate memory */
40         case MC_CMD_STATUS_BUSY:
41                 return -EBUSY; /* Device busy */
42         case MC_CMD_STATUS_UNSUPPORTED_OP:
43                 return -ENOTSUP; /* Operation not supported by device */
44         case MC_CMD_STATUS_INVALID_STATE:
45                 return -ENODEV; /* Invalid device state */
46         default:
47                 break;
48         }
49
50         /* Not expected to reach here */
51         return -EINVAL;
52 }
53
54 int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd)
55 {
56         enum mc_cmd_status status;
57         uint64_t response;
58
59         if (!mc_io || !mc_io->regs)
60                 return -EACCES;
61
62         /* --- Call lock function here in case portal is shared --- */
63         rte_spinlock_lock(&mc_portal_lock);
64
65         mc_write_command(mc_io->regs, cmd);
66
67         /* Spin until status changes */
68         do {
69                 response = ioread64(mc_io->regs);
70                 status = mc_cmd_read_status((struct mc_command *)&response);
71
72                 /* --- Call wait function here to prevent blocking ---
73                  * Change the loop condition accordingly to exit on timeout.
74                  */
75         } while (status == MC_CMD_STATUS_READY);
76
77         /* Read the response back into the command buffer */
78         mc_read_response(mc_io->regs, cmd);
79
80         /* --- Call unlock function here in case portal is shared --- */
81         rte_spinlock_unlock(&mc_portal_lock);
82
83         return mc_status_to_error(status);
84 }