You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

intelvf.c 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <string.h>
  25. #include <unistd.h>
  26. #include <errno.h>
  27. #include <ipxe/io.h>
  28. #include <ipxe/netdevice.h>
  29. #include <ipxe/ethernet.h>
  30. #include "intelvf.h"
  31. /** @file
  32. *
  33. * Intel 10/100/1000 virtual function network card driver
  34. *
  35. */
  36. /******************************************************************************
  37. *
  38. * Mailbox messages
  39. *
  40. ******************************************************************************
  41. */
  42. /**
  43. * Write message to mailbox
  44. *
  45. * @v intel Intel device
  46. * @v msg Message
  47. */
  48. static void intelvf_mbox_write ( struct intel_nic *intel,
  49. const union intelvf_msg *msg ) {
  50. unsigned int i;
  51. /* Write message */
  52. DBGC2 ( intel, "INTEL %p sending message", intel );
  53. for ( i = 0 ; i < ( sizeof ( *msg ) / sizeof ( msg->dword[0] ) ) ; i++){
  54. DBGC2 ( intel, "%c%08x", ( i ? ':' : ' ' ), msg->dword[i] );
  55. writel ( msg->dword[i], ( intel->regs + intel->mbox.mem +
  56. ( i * sizeof ( msg->dword[0] ) ) ) );
  57. }
  58. DBGC2 ( intel, "\n" );
  59. }
  60. /**
  61. * Read message from mailbox
  62. *
  63. * @v intel Intel device
  64. * @v msg Message
  65. */
  66. static void intelvf_mbox_read ( struct intel_nic *intel,
  67. union intelvf_msg *msg ) {
  68. unsigned int i;
  69. /* Read message */
  70. DBGC2 ( intel, "INTEL %p received message", intel );
  71. for ( i = 0 ; i < ( sizeof ( *msg ) / sizeof ( msg->dword[0] ) ) ; i++){
  72. msg->dword[i] = readl ( intel->regs + intel->mbox.mem +
  73. ( i * sizeof ( msg->dword[0] ) ) );
  74. DBGC2 ( intel, "%c%08x", ( i ? ':' : ' ' ), msg->dword[i] );
  75. }
  76. DBGC2 ( intel, "\n" );
  77. }
  78. /**
  79. * Poll mailbox
  80. *
  81. * @v intel Intel device
  82. * @ret rc Return status code
  83. *
  84. * Note that polling the mailbox may fail if the underlying PF is
  85. * reset.
  86. */
  87. int intelvf_mbox_poll ( struct intel_nic *intel ) {
  88. struct intel_mailbox *mbox = &intel->mbox;
  89. union intelvf_msg msg;
  90. uint32_t ctrl;
  91. /* Get mailbox status */
  92. ctrl = readl ( intel->regs + mbox->ctrl );
  93. /* Fail if a reset is in progress */
  94. if ( ctrl & INTELVF_MBCTRL_RSTI )
  95. return -EPIPE;
  96. /* Acknowledge (and ignore) any received messages */
  97. if ( ctrl & INTELVF_MBCTRL_PFSTS ) {
  98. intelvf_mbox_read ( intel, &msg );
  99. writel ( INTELVF_MBCTRL_ACK, intel->regs + mbox->ctrl );
  100. }
  101. return 0;
  102. }
  103. /**
  104. * Wait for PF reset to complete
  105. *
  106. * @v intel Intel device
  107. * @ret rc Return status code
  108. */
  109. int intelvf_mbox_wait ( struct intel_nic *intel ) {
  110. unsigned int i;
  111. int rc;
  112. /* Wait until a poll completes successfully */
  113. for ( i = 0 ; i < INTELVF_MBOX_MAX_WAIT_MS ; i++ ) {
  114. /* Check for successful poll */
  115. if ( ( rc = intelvf_mbox_poll ( intel ) ) == 0 )
  116. return 0;
  117. /* Delay */
  118. mdelay ( 1 );
  119. }
  120. DBGC ( intel, "INTEL %p timed out waiting for reset\n", intel );
  121. return -ETIMEDOUT;
  122. }
  123. /**
  124. * Send/receive mailbox message
  125. *
  126. * @v intel Intel device
  127. * @v msg Message buffer
  128. * @ret rc Return status code
  129. */
  130. int intelvf_mbox_msg ( struct intel_nic *intel, union intelvf_msg *msg ) {
  131. struct intel_mailbox *mbox = &intel->mbox;
  132. uint32_t ctrl;
  133. uint32_t seen = 0;
  134. unsigned int i;
  135. /* Sanity check */
  136. assert ( ! ( msg->hdr & INTELVF_MSG_RESPONSE ) );
  137. /* Handle mailbox */
  138. for ( i = 0 ; i < INTELVF_MBOX_MAX_WAIT_MS ; i++ ) {
  139. /* Attempt to claim mailbox, if we have not yet sent
  140. * our message.
  141. */
  142. if ( ! ( seen & INTELVF_MBCTRL_VFU ) )
  143. writel ( INTELVF_MBCTRL_VFU, intel->regs + mbox->ctrl );
  144. /* Get mailbox status and record observed flags */
  145. ctrl = readl ( intel->regs + mbox->ctrl );
  146. seen |= ctrl;
  147. /* If a reset is in progress, clear VFU and abort */
  148. if ( ctrl & INTELVF_MBCTRL_RSTI ) {
  149. writel ( 0, intel->regs + mbox->ctrl );
  150. return -EPIPE;
  151. }
  152. /* Write message to mailbox, if applicable. This
  153. * potentially overwrites a message sent by the PF (if
  154. * the PF has simultaneously released PFU (thus
  155. * allowing our VFU) and asserted PFSTS), but that
  156. * doesn't really matter since there are no
  157. * unsolicited PF->VF messages that require the actual
  158. * message content to be observed.
  159. */
  160. if ( ctrl & INTELVF_MBCTRL_VFU )
  161. intelvf_mbox_write ( intel, msg );
  162. /* Read message from mailbox, if applicable. */
  163. if ( ( seen & INTELVF_MBCTRL_VFU ) &&
  164. ( seen & INTELVF_MBCTRL_PFACK ) &&
  165. ( ctrl & INTELVF_MBCTRL_PFSTS ) )
  166. intelvf_mbox_read ( intel, msg );
  167. /* Acknowledge received message (if applicable),
  168. * release VFU lock, and send message (if applicable).
  169. */
  170. ctrl = ( ( ( ctrl & INTELVF_MBCTRL_PFSTS ) ?
  171. INTELVF_MBCTRL_ACK : 0 ) |
  172. ( ( ctrl & INTELVF_MBCTRL_VFU ) ?
  173. INTELVF_MBCTRL_REQ : 0 ) );
  174. writel ( ctrl, intel->regs + mbox->ctrl );
  175. /* Exit successfully if we have received a response */
  176. if ( msg->hdr & INTELVF_MSG_RESPONSE ) {
  177. /* Sanity check */
  178. assert ( seen & INTELVF_MBCTRL_VFU );
  179. assert ( seen & INTELVF_MBCTRL_PFACK );
  180. assert ( seen & INTELVF_MBCTRL_PFSTS );
  181. return 0;
  182. }
  183. /* Delay */
  184. mdelay ( 1 );
  185. }
  186. DBGC ( intel, "INTEL %p timed out waiting for mailbox (seen %08x)\n",
  187. intel, seen );
  188. return -ETIMEDOUT;
  189. }
  190. /**
  191. * Send reset message and get initial MAC address
  192. *
  193. * @v intel Intel device
  194. * @v hw_addr Hardware address to fill in, or NULL
  195. * @ret rc Return status code
  196. */
  197. int intelvf_mbox_reset ( struct intel_nic *intel, uint8_t *hw_addr ) {
  198. union intelvf_msg msg;
  199. int rc;
  200. /* Send reset message */
  201. memset ( &msg, 0, sizeof ( msg ) );
  202. msg.hdr = INTELVF_MSG_TYPE_RESET;
  203. if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
  204. DBGC ( intel, "INTEL %p reset failed: %s\n",
  205. intel, strerror ( rc ) );
  206. return rc;
  207. }
  208. /* Check response */
  209. if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) != INTELVF_MSG_TYPE_RESET ) {
  210. DBGC ( intel, "INTEL %p reset unexpected response:\n", intel );
  211. DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
  212. return -EPROTO;
  213. }
  214. /* Fill in MAC address, if applicable */
  215. if ( hw_addr ) {
  216. if ( msg.hdr & INTELVF_MSG_ACK ) {
  217. memcpy ( hw_addr, msg.mac.mac, sizeof ( msg.mac.mac ) );
  218. DBGC ( intel, "INTEL %p reset assigned MAC address "
  219. "%s\n", intel, eth_ntoa ( hw_addr ) );
  220. } else {
  221. eth_random_addr ( hw_addr );
  222. DBGC ( intel, "INTEL %p reset generated MAC address "
  223. "%s\n", intel, eth_ntoa ( hw_addr ) );
  224. }
  225. }
  226. return 0;
  227. }
  228. /**
  229. * Send set MAC address message
  230. *
  231. * @v intel Intel device
  232. * @v ll_addr Link-layer address
  233. * @ret rc Return status code
  234. */
  235. int intelvf_mbox_set_mac ( struct intel_nic *intel, const uint8_t *ll_addr ) {
  236. union intelvf_msg msg;
  237. int rc;
  238. /* Send set MAC address message */
  239. memset ( &msg, 0, sizeof ( msg ) );
  240. msg.hdr = INTELVF_MSG_TYPE_SET_MAC;
  241. memcpy ( msg.mac.mac, ll_addr, sizeof ( msg.mac.mac ) );
  242. if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
  243. DBGC ( intel, "INTEL %p set MAC address failed: %s\n",
  244. intel, strerror ( rc ) );
  245. return rc;
  246. }
  247. /* Check response */
  248. if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) != INTELVF_MSG_TYPE_SET_MAC ) {
  249. DBGC ( intel, "INTEL %p set MAC address unexpected response:\n",
  250. intel );
  251. DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
  252. return -EPROTO;
  253. }
  254. /* Check that we were allowed to set the MAC address */
  255. if ( ! ( msg.hdr & INTELVF_MSG_ACK ) ) {
  256. DBGC ( intel, "INTEL %p set MAC address refused\n", intel );
  257. return -EPERM;
  258. }
  259. return 0;
  260. }
  261. /**
  262. * Send set MTU message
  263. *
  264. * @v intel Intel device
  265. * @v mtu Maximum packet size
  266. * @ret rc Return status code
  267. */
  268. int intelvf_mbox_set_mtu ( struct intel_nic *intel, size_t mtu ) {
  269. union intelvf_msg msg;
  270. int rc;
  271. /* Send set MTU message */
  272. memset ( &msg, 0, sizeof ( msg ) );
  273. msg.hdr = INTELVF_MSG_TYPE_SET_MTU;
  274. msg.mtu.mtu = mtu;
  275. if ( ( rc = intelvf_mbox_msg ( intel, &msg ) ) != 0 ) {
  276. DBGC ( intel, "INTEL %p set MTU failed: %s\n",
  277. intel, strerror ( rc ) );
  278. return rc;
  279. }
  280. /* Check response */
  281. if ( ( msg.hdr & INTELVF_MSG_TYPE_MASK ) != INTELVF_MSG_TYPE_SET_MTU ) {
  282. DBGC ( intel, "INTEL %p set MTU unexpected response:\n",
  283. intel );
  284. DBGC_HDA ( intel, 0, &msg, sizeof ( msg ) );
  285. return -EPROTO;
  286. }
  287. /* Check that we were allowed to set the MTU */
  288. if ( ! ( msg.hdr & INTELVF_MSG_ACK ) ) {
  289. DBGC ( intel, "INTEL %p set MTU refused\n", intel );
  290. return -EPERM;
  291. }
  292. return 0;
  293. }