These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / drivers / net / intelvf.c
1 /*
2  * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <ipxe/io.h>
30 #include <ipxe/netdevice.h>
31 #include <ipxe/ethernet.h>
32 #include "intelvf.h"
33
34 /** @file
35  *
36  * Intel 10/100/1000 virtual function network card driver
37  *
38  */
39
40 /******************************************************************************
41  *
42  * Mailbox messages
43  *
44  ******************************************************************************
45  */
46
47 /**
48  * Write message to mailbox
49  *
50  * @v intel             Intel device
51  * @v msg               Message
52  */
53 static void intelvf_mbox_write ( struct intel_nic *intel,
54                                  const union intelvf_msg *msg ) {
55         unsigned int i;
56
57         /* Write message */
58         DBGC2 ( intel, "INTEL %p sending message", intel );
59         for ( i = 0 ; i < ( sizeof ( *msg ) / sizeof ( msg->dword[0] ) ) ; i++){
60                 DBGC2 ( intel, "%c%08x", ( i ? ':' : ' ' ), msg->dword[i] );
61                 writel ( msg->dword[i], ( intel->regs + intel->mbox.mem +
62                                           ( i * sizeof ( msg->dword[0] ) ) ) );
63         }
64         DBGC2 ( intel, "\n" );
65 }
66
67 /**
68  * Read message from mailbox
69  *
70  * @v intel             Intel device
71  * @v msg               Message
72  */
73 static void intelvf_mbox_read ( struct intel_nic *intel,
74                                 union intelvf_msg *msg ) {
75         unsigned int i;
76
77         /* Read message */
78         DBGC2 ( intel, "INTEL %p received message", intel );
79         for ( i = 0 ; i < ( sizeof ( *msg ) / sizeof ( msg->dword[0] ) ) ; i++){
80                 msg->dword[i] = readl ( intel->regs + intel->mbox.mem +
81                                         ( i * sizeof ( msg->dword[0] ) ) );
82                 DBGC2 ( intel, "%c%08x", ( i ? ':' : ' ' ), msg->dword[i] );
83         }
84         DBGC2 ( intel, "\n" );
85 }
86
87 /**
88  * Poll mailbox
89  *
90  * @v intel             Intel device
91  * @ret rc              Return status code
92  *
93  * Note that polling the mailbox may fail if the underlying PF is
94  * reset.
95  */
96 int intelvf_mbox_poll ( struct intel_nic *intel ) {
97         struct intel_mailbox *mbox = &intel->mbox;
98         union intelvf_msg msg;
99         uint32_t ctrl;
100
101         /* Get mailbox status */
102         ctrl = readl ( intel->regs + mbox->ctrl );
103
104         /* Fail if a reset is in progress */
105         if ( ctrl & INTELVF_MBCTRL_RSTI )
106                 return -EPIPE;
107
108         /* Acknowledge (and ignore) any received messages */
109         if ( ctrl & INTELVF_MBCTRL_PFSTS ) {
110                 intelvf_mbox_read ( intel, &msg );
111                 writel ( INTELVF_MBCTRL_ACK, intel->regs + mbox->ctrl );
112         }
113
114         return 0;
115 }
116
117 /**
118  * Wait for PF reset to complete
119  *
120  * @v intel             Intel device
121  * @ret rc              Return status code
122  */
123 int intelvf_mbox_wait ( struct intel_nic *intel ) {
124         unsigned int i;
125         int rc;
126
127         /* Wait until a poll completes successfully */
128         for ( i = 0 ; i < INTELVF_MBOX_MAX_WAIT_MS ; i++ ) {
129
130                 /* Check for successful poll */
131                 if ( ( rc = intelvf_mbox_poll ( intel ) ) == 0 )
132                         return 0;
133
134                 /* Delay */
135                 mdelay ( 1 );
136         }
137
138         DBGC ( intel, "INTEL %p timed out waiting for reset\n", intel );
139         return -ETIMEDOUT;
140 }
141
142 /**
143  * Send/receive mailbox message
144  *
145  * @v intel             Intel device
146  * @v msg               Message buffer
147  * @ret rc              Return status code
148  */
149 int intelvf_mbox_msg ( struct intel_nic *intel, union intelvf_msg *msg ) {
150         struct intel_mailbox *mbox = &intel->mbox;
151         uint32_t ctrl;
152         uint32_t seen = 0;
153         unsigned int i;
154
155         /* Sanity check */
156         assert ( ! ( msg->hdr & INTELVF_MSG_RESPONSE ) );
157
158         /* Handle mailbox */
159         for ( i = 0 ; i < INTELVF_MBOX_MAX_WAIT_MS ; i++ ) {
160
161                 /* Attempt to claim mailbox, if we have not yet sent
162                  * our message.
163                  */
164                 if ( ! ( seen & INTELVF_MBCTRL_VFU ) )
165                         writel ( INTELVF_MBCTRL_VFU, intel->regs + mbox->ctrl );
166
167                 /* Get mailbox status and record observed flags */
168                 ctrl = readl ( intel->regs + mbox->ctrl );
169                 seen |= ctrl;
170
171                 /* If a reset is in progress, clear VFU and abort */
172                 if ( ctrl & INTELVF_MBCTRL_RSTI ) {
173                         writel ( 0, intel->regs + mbox->ctrl );
174                         return -EPIPE;
175                 }
176
177                 /* Write message to mailbox, if applicable.  This
178                  * potentially overwrites a message sent by the PF (if
179                  * the PF has simultaneously released PFU (thus
180                  * allowing our VFU) and asserted PFSTS), but that
181                  * doesn't really matter since there are no
182                  * unsolicited PF->VF messages that require the actual
183                  * message content to be observed.
184                  */
185                 if ( ctrl & INTELVF_MBCTRL_VFU )
186                         intelvf_mbox_write ( intel, msg );
187
188                 /* Read message from mailbox, if applicable. */
189                 if ( ( seen & INTELVF_MBCTRL_VFU ) &&
190                      ( seen & INTELVF_MBCTRL_PFACK ) &&
191                      ( ctrl & INTELVF_MBCTRL_PFSTS ) )
192                         intelvf_mbox_read ( intel, msg );
193
194                 /* Acknowledge received message (if applicable),
195                  * release VFU lock, and send message (if applicable).
196                  */
197                 ctrl = ( ( ( ctrl & INTELVF_MBCTRL_PFSTS ) ?
198                            INTELVF_MBCTRL_ACK : 0 ) |
199                          ( ( ctrl & INTELVF_MBCTRL_VFU ) ?
200                            INTELVF_MBCTRL_REQ : 0 ) );
201                 writel ( ctrl, intel->regs + mbox->ctrl );
202
203                 /* Exit successfully if we have received a response */
204                 if ( msg->hdr & INTELVF_MSG_RESPONSE ) {
205
206                         /* Sanity check */
207                         assert ( seen & INTELVF_MBCTRL_VFU );
208                         assert ( seen & INTELVF_MBCTRL_PFACK );
209                         assert ( seen & INTELVF_MBCTRL_PFSTS );
210
211                         return 0;
212                 }
213
214                 /* Delay */
215                 mdelay ( 1 );
216         }
217
218         DBGC ( intel, "INTEL %p timed out waiting for mailbox (seen %08x)\n",
219                intel, seen );
220         return -ETIMEDOUT;
221 }
222
223 /**
224  * Send reset message and get initial MAC address
225  *
226  * @v intel             Intel device
227  * @v hw_addr           Hardware address to fill in, or NULL
228  * @ret rc              Return status code
229  */
230 int intelvf_mbox_reset ( struct intel_nic *intel, uint8_t *hw_addr ) {
231         union intelvf_msg msg;
232         int rc;
233
234         /* Send reset message */
235         memset ( &msg, 0, sizeof ( msg ) );
236         msg.hdr = INTELVF_MSG_TYPE_RESET;
237         if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
238                 DBGC ( intel, "INTEL %p reset failed: %s\n",
239                        intel, strerror ( rc ) );
240                 return rc;
241         }
242
243         /* Check response */
244         if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) != INTELVF_MSG_TYPE_RESET ) {
245                 DBGC ( intel, "INTEL %p reset unexpected response:\n", intel );
246                 DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
247                 return -EPROTO;
248         }
249
250         /* Fill in MAC address, if applicable */
251         if ( hw_addr ) {
252                 if ( msg.hdr & INTELVF_MSG_ACK ) {
253                         memcpy ( hw_addr, msg.mac.mac, sizeof ( msg.mac.mac ) );
254                         DBGC ( intel, "INTEL %p reset assigned MAC address "
255                                "%s\n", intel, eth_ntoa ( hw_addr ) );
256                 } else {
257                         eth_random_addr ( hw_addr );
258                         DBGC ( intel, "INTEL %p reset generated MAC address "
259                                "%s\n", intel, eth_ntoa ( hw_addr ) );
260                 }
261         }
262
263         return 0;
264 }
265
266 /**
267  * Send set MAC address message
268  *
269  * @v intel             Intel device
270  * @v ll_addr           Link-layer address
271  * @ret rc              Return status code
272  */
273 int intelvf_mbox_set_mac ( struct intel_nic *intel, const uint8_t *ll_addr ) {
274         union intelvf_msg msg;
275         int rc;
276
277         /* Send set MAC address message */
278         memset ( &msg, 0, sizeof ( msg ) );
279         msg.hdr = INTELVF_MSG_TYPE_SET_MAC;
280         memcpy ( msg.mac.mac, ll_addr, sizeof ( msg.mac.mac ) );
281         if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
282                 DBGC ( intel, "INTEL %p set MAC address failed: %s\n",
283                        intel, strerror ( rc ) );
284                 return rc;
285         }
286
287         /* Check response */
288         if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) != INTELVF_MSG_TYPE_SET_MAC ) {
289                 DBGC ( intel, "INTEL %p set MAC address unexpected response:\n",
290                        intel );
291                 DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
292                 return -EPROTO;
293         }
294
295         /* Check that we were allowed to set the MAC address */
296         if ( ! ( msg.hdr & INTELVF_MSG_ACK ) ) {
297                 DBGC ( intel, "INTEL %p set MAC address refused\n", intel );
298                 return -EPERM;
299         }
300
301         return 0;
302 }
303
304 /**
305  * Send set MTU message
306  *
307  * @v intel             Intel device
308  * @v mtu               Maximum packet size
309  * @ret rc              Return status code
310  */
311 int intelvf_mbox_set_mtu ( struct intel_nic *intel, size_t mtu ) {
312         union intelvf_msg msg;
313         int rc;
314
315         /* Send set MTU message */
316         memset ( &msg, 0, sizeof ( msg ) );
317         msg.hdr = INTELVF_MSG_TYPE_SET_MTU;
318         msg.mtu.mtu = mtu;
319         if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
320                 DBGC ( intel, "INTEL %p set MTU failed: %s\n",
321                        intel, strerror ( rc ) );
322                 return rc;
323         }
324
325         /* Check response */
326         if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) != INTELVF_MSG_TYPE_SET_MTU ) {
327                 DBGC ( intel, "INTEL %p set MTU unexpected response:\n",
328                        intel );
329                 DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
330                 return -EPROTO;
331         }
332
333         /* Check that we were allowed to set the MTU */
334         if ( ! ( msg.hdr & INTELVF_MSG_ACK ) ) {
335                 DBGC ( intel, "INTEL %p set MTU refused\n", intel );
336                 return -EPERM;
337         }
338
339         return 0;
340 }