New upstream version 18.02
[deb_dpdk.git] / drivers / net / sfc / base / ef10_mcdi.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright (c) 2012-2018 Solarflare Communications Inc.
4  * All rights reserved.
5  */
6
7 #include "efx.h"
8 #include "efx_impl.h"
9
10
11 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
12
13 #if EFSYS_OPT_MCDI
14
15 #ifndef WITH_MCDI_V2
16 #error "WITH_MCDI_V2 required for EF10 MCDIv2 commands."
17 #endif
18
19
20         __checkReturn   efx_rc_t
21 ef10_mcdi_init(
22         __in            efx_nic_t *enp,
23         __in            const efx_mcdi_transport_t *emtp)
24 {
25         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
26         efsys_mem_t *esmp = emtp->emt_dma_mem;
27         efx_dword_t dword;
28         efx_rc_t rc;
29
30         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
31                     enp->en_family == EFX_FAMILY_MEDFORD);
32         EFSYS_ASSERT(enp->en_features & EFX_FEATURE_MCDI_DMA);
33
34         /*
35          * All EF10 firmware supports MCDIv2 and MCDIv1.
36          * Medford BootROM supports MCDIv2 and MCDIv1.
37          * Huntington BootROM supports MCDIv1 only.
38          */
39         emip->emi_max_version = 2;
40
41         /* A host DMA buffer is required for EF10 MCDI */
42         if (esmp == NULL) {
43                 rc = EINVAL;
44                 goto fail1;
45         }
46
47         /*
48          * Ensure that the MC doorbell is in a known state before issuing MCDI
49          * commands. The recovery algorithm requires that the MC command buffer
50          * must be 256 byte aligned. See bug24769.
51          */
52         if ((EFSYS_MEM_ADDR(esmp) & 0xFF) != 0) {
53                 rc = EINVAL;
54                 goto fail2;
55         }
56         EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0, 1);
57         EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE);
58
59         /* Save initial MC reboot status */
60         (void) ef10_mcdi_poll_reboot(enp);
61
62         /* Start a new epoch (allow fresh MCDI requests to succeed) */
63         efx_mcdi_new_epoch(enp);
64
65         return (0);
66
67 fail2:
68         EFSYS_PROBE(fail2);
69 fail1:
70         EFSYS_PROBE1(fail1, efx_rc_t, rc);
71
72         return (rc);
73 }
74
75                         void
76 ef10_mcdi_fini(
77         __in            efx_nic_t *enp)
78 {
79         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
80
81         emip->emi_new_epoch = B_FALSE;
82 }
83
84 /*
85  * In older firmware all commands are processed in a single thread, so a long
86  * running command for one PCIe function can block processing for another
87  * function (see bug 61269).
88  *
89  * In newer firmware that supports multithreaded MCDI processing, we can extend
90  * the timeout for long-running requests which we know firmware may choose to
91  * process in a background thread.
92  */
93 #define EF10_MCDI_CMD_TIMEOUT_US        (10 * 1000 * 1000)
94 #define EF10_MCDI_CMD_LONG_TIMEOUT_US   (60 * 1000 * 1000)
95
96                         void
97 ef10_mcdi_get_timeout(
98         __in            efx_nic_t *enp,
99         __in            efx_mcdi_req_t *emrp,
100         __out           uint32_t *timeoutp)
101 {
102         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
103
104         switch (emrp->emr_cmd) {
105         case MC_CMD_POLL_BIST:
106         case MC_CMD_NVRAM_ERASE:
107         case MC_CMD_LICENSING_V3:
108         case MC_CMD_NVRAM_UPDATE_FINISH:
109                 if (encp->enc_nvram_update_verify_result_supported != B_FALSE) {
110                         /*
111                          * Potentially longer running commands, which firmware
112                          * may choose to process in a background thread.
113                          */
114                         *timeoutp = EF10_MCDI_CMD_LONG_TIMEOUT_US;
115                         break;
116                 }
117                 /* FALLTHRU */
118         default:
119                 *timeoutp = EF10_MCDI_CMD_TIMEOUT_US;
120                 break;
121         }
122 }
123
124                         void
125 ef10_mcdi_send_request(
126         __in                    efx_nic_t *enp,
127         __in_bcount(hdr_len)    void *hdrp,
128         __in                    size_t hdr_len,
129         __in_bcount(sdu_len)    void *sdup,
130         __in                    size_t sdu_len)
131 {
132         const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
133         efsys_mem_t *esmp = emtp->emt_dma_mem;
134         efx_dword_t dword;
135         unsigned int pos;
136
137         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
138                     enp->en_family == EFX_FAMILY_MEDFORD);
139
140         /* Write the header */
141         for (pos = 0; pos < hdr_len; pos += sizeof (efx_dword_t)) {
142                 dword = *(efx_dword_t *)((uint8_t *)hdrp + pos);
143                 EFSYS_MEM_WRITED(esmp, pos, &dword);
144         }
145
146         /* Write the payload */
147         for (pos = 0; pos < sdu_len; pos += sizeof (efx_dword_t)) {
148                 dword = *(efx_dword_t *)((uint8_t *)sdup + pos);
149                 EFSYS_MEM_WRITED(esmp, hdr_len + pos, &dword);
150         }
151
152         /* Guarantee ordering of memory (MCDI request) and PIO (MC doorbell) */
153         EFSYS_DMA_SYNC_FOR_DEVICE(esmp, 0, hdr_len + sdu_len);
154         EFSYS_PIO_WRITE_BARRIER();
155
156         /* Ring the doorbell to post the command DMA address to the MC */
157         EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0,
158             EFSYS_MEM_ADDR(esmp) >> 32);
159         EFX_BAR_WRITED(enp, ER_DZ_MC_DB_LWRD_REG, &dword, B_FALSE);
160
161         EFX_POPULATE_DWORD_1(dword, EFX_DWORD_0,
162             EFSYS_MEM_ADDR(esmp) & 0xffffffff);
163         EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE);
164 }
165
166         __checkReturn   boolean_t
167 ef10_mcdi_poll_response(
168         __in            efx_nic_t *enp)
169 {
170         const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
171         efsys_mem_t *esmp = emtp->emt_dma_mem;
172         efx_dword_t hdr;
173
174         EFSYS_MEM_READD(esmp, 0, &hdr);
175         EFSYS_MEM_READ_BARRIER();
176
177         return (EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE) ? B_TRUE : B_FALSE);
178 }
179
180                         void
181 ef10_mcdi_read_response(
182         __in                    efx_nic_t *enp,
183         __out_bcount(length)    void *bufferp,
184         __in                    size_t offset,
185         __in                    size_t length)
186 {
187         const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
188         efsys_mem_t *esmp = emtp->emt_dma_mem;
189         unsigned int pos;
190         efx_dword_t data;
191
192         for (pos = 0; pos < length; pos += sizeof (efx_dword_t)) {
193                 EFSYS_MEM_READD(esmp, offset + pos, &data);
194                 memcpy((uint8_t *)bufferp + pos, &data,
195                     MIN(sizeof (data), length - pos));
196         }
197 }
198
199                         efx_rc_t
200 ef10_mcdi_poll_reboot(
201         __in            efx_nic_t *enp)
202 {
203         efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
204         efx_dword_t dword;
205         uint32_t old_status;
206         uint32_t new_status;
207         efx_rc_t rc;
208
209         old_status = emip->emi_mc_reboot_status;
210
211         /* Update MC reboot status word */
212         EFX_BAR_TBL_READD(enp, ER_DZ_BIU_MC_SFT_STATUS_REG, 0, &dword, B_FALSE);
213         new_status = dword.ed_u32[0];
214
215         /* MC has rebooted if the value has changed */
216         if (new_status != old_status) {
217                 emip->emi_mc_reboot_status = new_status;
218
219                 /*
220                  * FIXME: Ignore detected MC REBOOT for now.
221                  *
222                  * The Siena support for checking for MC reboot from status
223                  * flags is broken - see comments in siena_mcdi_poll_reboot().
224                  * As the generic MCDI code is shared the EF10 reboot
225                  * detection suffers similar problems.
226                  *
227                  * Do not report an error when the boot status changes until
228                  * this can be handled by common code drivers (and reworked to
229                  * support Siena too).
230                  */
231                 _NOTE(CONSTANTCONDITION)
232                 if (B_FALSE) {
233                         rc = EIO;
234                         goto fail1;
235                 }
236         }
237
238         return (0);
239
240 fail1:
241         EFSYS_PROBE1(fail1, efx_rc_t, rc);
242
243         return (rc);
244 }
245
246         __checkReturn   efx_rc_t
247 ef10_mcdi_feature_supported(
248         __in            efx_nic_t *enp,
249         __in            efx_mcdi_feature_id_t id,
250         __out           boolean_t *supportedp)
251 {
252         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
253         uint32_t privilege_mask = encp->enc_privilege_mask;
254         efx_rc_t rc;
255
256         EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
257                     enp->en_family == EFX_FAMILY_MEDFORD);
258
259         /*
260          * Use privilege mask state at MCDI attach.
261          */
262
263         switch (id) {
264         case EFX_MCDI_FEATURE_FW_UPDATE:
265                 /*
266                  * Admin privilege must be used prior to introduction of
267                  * specific flag.
268                  */
269                 *supportedp =
270                     EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN);
271                 break;
272         case EFX_MCDI_FEATURE_LINK_CONTROL:
273                 /*
274                  * Admin privilege used prior to introduction of
275                  * specific flag.
276                  */
277                 *supportedp =
278                     EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, LINK) ||
279                     EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN);
280                 break;
281         case EFX_MCDI_FEATURE_MACADDR_CHANGE:
282                 /*
283                  * Admin privilege must be used prior to introduction of
284                  * mac spoofing privilege (at v4.6), which is used up to
285                  * introduction of change mac spoofing privilege (at v4.7)
286                  */
287                 *supportedp =
288                     EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, CHANGE_MAC) ||
289                     EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, MAC_SPOOFING) ||
290                     EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN);
291                 break;
292         case EFX_MCDI_FEATURE_MAC_SPOOFING:
293                 /*
294                  * Admin privilege must be used prior to introduction of
295                  * mac spoofing privilege (at v4.6), which is used up to
296                  * introduction of mac spoofing TX privilege (at v4.7)
297                  */
298                 *supportedp =
299                     EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, MAC_SPOOFING_TX) ||
300                     EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, MAC_SPOOFING) ||
301                     EFX_MCDI_HAVE_PRIVILEGE(privilege_mask, ADMIN);
302                 break;
303         default:
304                 rc = ENOTSUP;
305                 goto fail1;
306         }
307
308         return (0);
309
310 fail1:
311         EFSYS_PROBE1(fail1, efx_rc_t, rc);
312
313         return (rc);
314 }
315
316 #endif  /* EFSYS_OPT_MCDI */
317
318 #endif  /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */