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.

sfc_hunt.c 33KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  1. /**************************************************************************
  2. *
  3. * Device driver for Solarflare Communications EF10 devices
  4. *
  5. * Written by Shradha Shah <sshah@solarflare.com>
  6. *
  7. * Copyright 2012-2017 Solarflare Communications Inc.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of the
  12. * License, or any later version.
  13. *
  14. * You can also choose to distribute this program under the terms of
  15. * the Unmodified Binary Distribution Licence (as given in the file
  16. * COPYING.UBDL), provided that you have satisfied its requirements.
  17. *
  18. ***************************************************************************/
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <unistd.h>
  22. #include <errno.h>
  23. #include <byteswap.h>
  24. #include <ipxe/io.h>
  25. #include <ipxe/pci.h>
  26. #include <ipxe/malloc.h>
  27. #include <ipxe/ethernet.h>
  28. #include <ipxe/iobuf.h>
  29. #include <ipxe/netdevice.h>
  30. #include "efx_hunt.h"
  31. #include "efx_bitfield.h"
  32. #include "ef10_regs.h"
  33. #include "mc_driver_pcol.h"
  34. #include <ipxe/if_ether.h>
  35. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  36. #define HUNTINGTON_NVRAM_CHUNK 0x80
  37. #define HUNTINGTON_NVS_MAX_LENGTH 0x1000
  38. #define EMCDI_IO(code) EUNIQ(EINFO_EIO, (code))
  39. #ifndef MIN
  40. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  41. #endif
  42. #ifndef MAX
  43. #define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
  44. #endif
  45. struct hunt_nic *primary_nics = NULL;
  46. struct hunt_nic {
  47. struct efx_nic efx;
  48. /* PHY information */
  49. unsigned int phy_cap_mask;
  50. unsigned int phy_cap;
  51. unsigned long link_poll_timer;
  52. /* resource housekeeping */
  53. uint64_t uc_filter_id;
  54. uint64_t mc_filter_id;
  55. u8 mac[ETH_ALEN];
  56. struct {
  57. /* Common payload for all MCDI requests */
  58. unsigned int seqno;
  59. size_t resp_hdr_len;
  60. size_t resp_data_len;
  61. struct io_buffer *iob;
  62. uint64_t dma_addr;
  63. } mcdi;
  64. struct hunt_nic *primary;
  65. struct hunt_nic *next_primary;
  66. u32 flags;
  67. };
  68. static int hunt_nic_is_primary(struct hunt_nic *hunt)
  69. {
  70. return (hunt->flags & (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY));
  71. }
  72. /*******************************************************************************
  73. *
  74. *
  75. * MCDI transport
  76. *
  77. * This has been based on the implementation of MCDI in the common code driver.
  78. *
  79. *
  80. ******************************************************************************/
  81. static int hunt_mcdi_init(struct hunt_nic *hunt)
  82. {
  83. size_t max_msg_size;
  84. int rc;
  85. /* The MCDI message has two 32-bit headers (the MCDI header and the
  86. * MCDI v2 extended command) and then up to MCDI_CTL_SDU_LEN_MAX_V2
  87. * bytes of payload
  88. */
  89. max_msg_size = 2 * sizeof(efx_dword_t) + MCDI_CTL_SDU_LEN_MAX_V2;
  90. hunt->mcdi.iob = alloc_iob(max_msg_size);
  91. if (!hunt->mcdi.iob) {
  92. rc = -ENOMEM;
  93. return rc;
  94. }
  95. return 0;
  96. }
  97. static void hunt_mcdi_copyin(struct hunt_nic *hunt,
  98. unsigned int cmd,
  99. uint8_t *inbuf,
  100. size_t inlen)
  101. {
  102. efx_dword_t hdr[2];
  103. uint32_t seqno;
  104. unsigned int xflags;
  105. size_t hdr_len;
  106. u8 *pdu = hunt->mcdi.iob->data;
  107. seqno = hunt->mcdi.seqno & MCDI_SEQ_MASK;
  108. xflags = 0;
  109. EFX_POPULATE_DWORD_7(hdr[0],
  110. MCDI_HEADER_CODE, MC_CMD_V2_EXTN,
  111. MCDI_HEADER_RESYNC, 1,
  112. MCDI_HEADER_DATALEN, 0,
  113. MCDI_HEADER_SEQ, seqno,
  114. MCDI_HEADER_ERROR, 0,
  115. MCDI_HEADER_RESPONSE, 0,
  116. MCDI_HEADER_XFLAGS, xflags);
  117. EFX_POPULATE_DWORD_2(hdr[1],
  118. MC_CMD_V2_EXTN_IN_EXTENDED_CMD, cmd,
  119. MC_CMD_V2_EXTN_IN_ACTUAL_LEN, inlen);
  120. hdr_len = sizeof(hdr);
  121. memcpy(pdu, &hdr, hdr_len);
  122. assert(inlen <= MCDI_CTL_SDU_LEN_MAX_V2);
  123. memcpy(pdu + hdr_len, inbuf, inlen);
  124. wmb(); /* Sync the data before ringing the doorbell */
  125. /* Ring the doorbell to post the command DMA address to the MC */
  126. hunt->mcdi.dma_addr = virt_to_bus(hunt->mcdi.iob->data);
  127. assert((hunt->mcdi.dma_addr & 0xFF) == 0);
  128. _efx_writel(&hunt->efx,
  129. cpu_to_le32((u64)hunt->mcdi.dma_addr >> 32),
  130. ER_DZ_MC_DB_LWRD);
  131. _efx_writel(&hunt->efx,
  132. cpu_to_le32((u32)hunt->mcdi.dma_addr),
  133. ER_DZ_MC_DB_HWRD);
  134. }
  135. static void hunt_mcdi_copyout(struct hunt_nic *hunt,
  136. uint8_t *outbuf, size_t outlen)
  137. {
  138. size_t offset;
  139. const u8 *pdu = hunt->mcdi.iob->data;
  140. offset = hunt->mcdi.resp_hdr_len;
  141. if (outlen > 0)
  142. memcpy(outbuf, pdu+offset, outlen);
  143. }
  144. static int hunt_mcdi_request_poll(struct hunt_nic *hunt, bool quiet)
  145. {
  146. unsigned int resplen, respseq, error;
  147. unsigned long finish;
  148. efx_dword_t errdword;
  149. efx_qword_t qword;
  150. const efx_dword_t *pdu = hunt->mcdi.iob->data;
  151. const u8 *pdu1 = hunt->mcdi.iob->data;
  152. int delay, rc;
  153. /* Spin for up to 5s, polling at intervals of 10us, 20us, ... ~100ms */
  154. finish = currticks() + (5 * TICKS_PER_SEC);
  155. delay = 10;
  156. while (1) {
  157. udelay(delay);
  158. /* Check for an MCDI response */
  159. if (EFX_DWORD_FIELD(*pdu, MCDI_HEADER_RESPONSE))
  160. break;
  161. if (currticks() >= finish)
  162. return -ETIMEDOUT;
  163. if (delay < 100000)
  164. delay *= 2;
  165. }
  166. memcpy(&qword, pdu1, 8);
  167. /* qword.dword[0] is the MCDI header; qword.dword[1] is the MCDI v2
  168. * extended command
  169. */
  170. respseq = EFX_DWORD_FIELD(qword.dword[0], MCDI_HEADER_SEQ);
  171. error = EFX_DWORD_FIELD(qword.dword[0], MCDI_HEADER_ERROR);
  172. resplen = EFX_DWORD_FIELD(qword.dword[1], MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
  173. if (error && resplen == 0) {
  174. if (!quiet)
  175. DBGC(hunt, "MC rebooted\n");
  176. return -EIO;
  177. } else if ((respseq ^ hunt->mcdi.seqno) & MCDI_SEQ_MASK) {
  178. if (!quiet)
  179. DBGC(hunt, "MC response mismatch rxseq 0x%x txseq "
  180. "0x%x\n", respseq, hunt->mcdi.seqno);
  181. return -EIO;
  182. } else if (error) {
  183. memcpy(&errdword, pdu1 + 8, 4);
  184. rc = EFX_DWORD_FIELD(errdword, EFX_DWORD_0);
  185. switch (rc) {
  186. case MC_CMD_ERR_ENOENT:
  187. return -ENOENT;
  188. case MC_CMD_ERR_EINTR:
  189. return -EINTR;
  190. case MC_CMD_ERR_EACCES:
  191. return -EACCES;
  192. case MC_CMD_ERR_EBUSY:
  193. return -EBUSY;
  194. case MC_CMD_ERR_EINVAL:
  195. return -EINVAL;
  196. case MC_CMD_ERR_EDEADLK:
  197. return -EDEADLK;
  198. case MC_CMD_ERR_ENOSYS:
  199. return -ENOSYS;
  200. case MC_CMD_ERR_ETIME:
  201. return -ETIME;
  202. case MC_CMD_ERR_EPERM:
  203. return -EPERM;
  204. default:
  205. /* Return the MC error in an I/O error. */
  206. return EMCDI_IO(rc & 0xff);
  207. }
  208. }
  209. hunt->mcdi.resp_hdr_len = 8;
  210. hunt->mcdi.resp_data_len = resplen;
  211. return 0;
  212. }
  213. static void hunt_mcdi_fini(struct hunt_nic *hunt)
  214. {
  215. free_iob(hunt->mcdi.iob);
  216. }
  217. int _hunt_mcdi(struct efx_nic *efx, unsigned int cmd,
  218. const efx_dword_t *inbuf, size_t inlen,
  219. efx_dword_t *outbuf, size_t outlen,
  220. size_t *outlen_actual, bool quiet)
  221. {
  222. int rc;
  223. struct hunt_nic *hunt = (struct hunt_nic *) efx;
  224. size_t local_outlen_actual;
  225. if (outlen_actual == NULL)
  226. outlen_actual = &local_outlen_actual;
  227. ++hunt->mcdi.seqno;
  228. hunt_mcdi_copyin(hunt, cmd, (uint8_t *) inbuf, inlen);
  229. rc = hunt_mcdi_request_poll(hunt, quiet);
  230. if (rc != 0) {
  231. if (!quiet)
  232. DBGC(hunt, "MC response to cmd 0x%x: %s\n",
  233. cmd, strerror(rc));
  234. return rc;
  235. }
  236. *outlen_actual = hunt->mcdi.resp_data_len;
  237. hunt_mcdi_copyout(hunt, (uint8_t *) outbuf, outlen);
  238. return 0;
  239. }
  240. static int hunt_mcdi(struct hunt_nic *hunt, struct efx_mcdi_req_s *req)
  241. {
  242. return _hunt_mcdi(&hunt->efx, req->emr_cmd,
  243. (const efx_dword_t *) req->emr_in_buf,
  244. req->emr_in_length,
  245. (efx_dword_t *) req->emr_out_buf, req->emr_out_length,
  246. &req->emr_out_length_used, false);
  247. }
  248. static int hunt_mcdi_quiet(struct hunt_nic *hunt, struct efx_mcdi_req_s *req)
  249. {
  250. return _hunt_mcdi(&hunt->efx, req->emr_cmd,
  251. (const efx_dword_t *) req->emr_in_buf,
  252. req->emr_in_length,
  253. (efx_dword_t *) req->emr_out_buf, req->emr_out_length,
  254. &req->emr_out_length_used, true);
  255. }
  256. /*******************************************************************************
  257. *
  258. *
  259. * Hardware initialization
  260. *
  261. *
  262. ******************************************************************************/
  263. static int hunt_get_workarounds(struct hunt_nic *hunt, uint32_t *implemented,
  264. uint32_t *enabled)
  265. {
  266. struct efx_mcdi_req_s req;
  267. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_WORKAROUNDS_OUT_LEN);
  268. int rc;
  269. *implemented = *enabled = 0;
  270. req.emr_cmd = MC_CMD_GET_WORKAROUNDS;
  271. req.emr_in_buf = NULL;
  272. req.emr_in_length = 0;
  273. req.emr_out_buf = outbuf;
  274. req.emr_out_length = sizeof(outbuf);
  275. rc = hunt_mcdi(hunt, &req);
  276. if (rc)
  277. return rc;
  278. if (req.emr_out_length_used < MC_CMD_GET_WORKAROUNDS_OUT_LEN)
  279. return -EMSGSIZE;
  280. *implemented = MCDI_DWORD(outbuf, GET_WORKAROUNDS_OUT_IMPLEMENTED);
  281. *enabled = MCDI_DWORD(outbuf, GET_WORKAROUNDS_OUT_ENABLED);
  282. return 0;
  283. }
  284. static int hunt_enable_workaround_35388(struct hunt_nic *hunt)
  285. {
  286. struct efx_mcdi_req_s req;
  287. MCDI_DECLARE_BUF(payload, MC_CMD_WORKAROUND_IN_LEN);
  288. req.emr_cmd = MC_CMD_WORKAROUND;
  289. req.emr_in_buf = payload;
  290. req.emr_in_length = MC_CMD_WORKAROUND_IN_LEN;
  291. req.emr_out_buf = NULL;
  292. req.emr_out_length = 0;
  293. MCDI_SET_DWORD(req.emr_in_buf, WORKAROUND_IN_TYPE,
  294. MC_CMD_WORKAROUND_BUG35388);
  295. MCDI_SET_DWORD(req.emr_in_buf, WORKAROUND_IN_ENABLED, 1);
  296. /* If the firmware doesn't support this workaround, hunt_mcdi() will
  297. * return -EINVAL from hunt_mcdi_request_poll().
  298. */
  299. return hunt_mcdi(hunt, &req);
  300. }
  301. static int hunt_workaround_35388(struct hunt_nic *hunt)
  302. {
  303. uint32_t implemented, enabled;
  304. int rc = hunt_get_workarounds(hunt, &implemented, &enabled);
  305. if (rc < 0)
  306. return 0;
  307. if (!(implemented & MC_CMD_GET_WORKAROUNDS_OUT_BUG35388))
  308. return 0;
  309. if (enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG35388)
  310. return 1;
  311. rc = hunt_enable_workaround_35388(hunt);
  312. if (rc == 0)
  313. return 1; /* Workaround is enabled */
  314. else
  315. return 0;
  316. }
  317. static int hunt_get_port_assignment(struct hunt_nic *hunt)
  318. {
  319. struct efx_mcdi_req_s req;
  320. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PORT_ASSIGNMENT_OUT_LEN);
  321. int rc;
  322. req.emr_cmd = MC_CMD_GET_PORT_ASSIGNMENT;
  323. req.emr_in_buf = NULL;
  324. req.emr_in_length = 0;
  325. req.emr_out_buf = outbuf;
  326. req.emr_out_length = sizeof(outbuf);
  327. rc = hunt_mcdi(hunt, &req);
  328. if (rc != 0)
  329. return rc;
  330. hunt->efx.port = MCDI_DWORD(req.emr_out_buf,
  331. GET_PORT_ASSIGNMENT_OUT_PORT);
  332. return 0;
  333. }
  334. static int hunt_mac_addr(struct hunt_nic *hunt, uint8_t *ll_addr)
  335. {
  336. struct efx_mcdi_req_s req;
  337. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
  338. int rc;
  339. req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES;
  340. req.emr_in_buf = NULL;
  341. req.emr_in_length = 0;
  342. req.emr_out_buf = outbuf;
  343. req.emr_out_length = MC_CMD_GET_MAC_ADDRESSES_OUT_LEN;
  344. rc = hunt_mcdi(hunt, &req);
  345. if (rc != 0)
  346. return rc;
  347. if (req.emr_out_length_used < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)
  348. return -EMSGSIZE;
  349. memcpy(ll_addr,
  350. MCDI_PTR(req.emr_out_buf, GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE),
  351. ETH_ALEN);
  352. return 0;
  353. }
  354. static int hunt_get_phy_cfg(struct hunt_nic *hunt)
  355. {
  356. struct efx_mcdi_req_s req;
  357. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_PHY_CFG_OUT_LEN);
  358. int rc;
  359. req.emr_cmd = MC_CMD_GET_PHY_CFG;
  360. req.emr_in_buf = NULL;
  361. req.emr_in_length = 0;
  362. req.emr_out_buf = outbuf;
  363. req.emr_out_length = sizeof(outbuf);
  364. rc = hunt_mcdi(hunt, &req);
  365. if (rc != 0)
  366. return rc;
  367. if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN)
  368. return -EMSGSIZE;
  369. hunt->phy_cap_mask = hunt->phy_cap =
  370. MCDI_DWORD(req.emr_out_buf, GET_PHY_CFG_OUT_SUPPORTED_CAP);
  371. DBGC2(hunt, "GET_PHY_CFG: flags=%x, caps=%x\n", rc, hunt->phy_cap);
  372. return 0;
  373. }
  374. static int hunt_driver_attach(struct hunt_nic *hunt, int attach)
  375. {
  376. struct efx_mcdi_req_s req;
  377. MCDI_DECLARE_BUF(inbuf, MC_CMD_DRV_ATTACH_IN_LEN);
  378. MCDI_DECLARE_BUF(outbuf, MC_CMD_DRV_ATTACH_EXT_OUT_LEN);
  379. int rc;
  380. req.emr_cmd = MC_CMD_DRV_ATTACH;
  381. req.emr_in_buf = inbuf;
  382. req.emr_in_length = sizeof(inbuf);
  383. req.emr_out_buf = outbuf;
  384. req.emr_out_length = sizeof(outbuf);
  385. /* Set the PREBOOT flag to indicate later instances of attach should
  386. * force an ENTITY RESET
  387. */
  388. if (attach)
  389. attach |= 1 << MC_CMD_DRV_PREBOOT_LBN;
  390. MCDI_SET_DWORD(req.emr_in_buf, DRV_ATTACH_IN_NEW_STATE, attach);
  391. MCDI_SET_DWORD(req.emr_in_buf, DRV_ATTACH_IN_UPDATE, 1);
  392. MCDI_SET_DWORD(req.emr_in_buf, DRV_ATTACH_IN_FIRMWARE_ID,
  393. MC_CMD_FW_DONT_CARE);
  394. rc = hunt_mcdi(hunt, &req);
  395. if (rc != 0)
  396. return rc;
  397. if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN)
  398. return -EMSGSIZE;
  399. hunt->flags = MCDI_DWORD(outbuf, DRV_ATTACH_EXT_OUT_FUNC_FLAGS);
  400. return 0;
  401. }
  402. static int hunt_reset(struct hunt_nic *hunt)
  403. {
  404. struct efx_mcdi_req_s req;
  405. MCDI_DECLARE_BUF(inbuf, MC_CMD_ENTITY_RESET_IN_LEN);
  406. req.emr_cmd = MC_CMD_ENTITY_RESET;
  407. req.emr_in_buf = inbuf;
  408. req.emr_in_length = sizeof(inbuf);
  409. req.emr_out_buf = NULL;
  410. req.emr_out_length = 0;
  411. MCDI_POPULATE_DWORD_1(req.emr_in_buf, ENTITY_RESET_IN_FLAG,
  412. ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET, 1);
  413. return hunt_mcdi(hunt, &req);
  414. }
  415. static void hunt_clear_udp_tunnel_ports(struct hunt_nic *hunt)
  416. {
  417. MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LENMAX);
  418. MCDI_DECLARE_BUF(outbuf, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN);
  419. struct efx_mcdi_req_s req;
  420. int rc;
  421. memset(inbuf, 0, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LENMAX);
  422. MCDI_SET_DWORD(inbuf, SET_TUNNEL_ENCAP_UDP_PORTS_IN_FLAGS,
  423. (1 << MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_UNLOADING_LBN));
  424. req.emr_cmd = MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS;
  425. req.emr_in_buf = inbuf;
  426. req.emr_in_length = sizeof(inbuf);
  427. req.emr_out_buf = outbuf;
  428. req.emr_out_length = sizeof(outbuf);
  429. rc = hunt_mcdi_quiet(hunt, &req);
  430. if (rc)
  431. return;
  432. if (MCDI_DWORD(outbuf, SET_TUNNEL_ENCAP_UDP_PORTS_OUT_FLAGS) &
  433. (1 << MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_RESETTING_LBN)) {
  434. DBGC(hunt,
  435. "Rebooting MC due to clearing UDP tunnel port list\n");
  436. /* Delay for the MC reboot to complete. */
  437. mdelay(100);
  438. }
  439. }
  440. static int hunt_set_mac(struct hunt_nic *hunt)
  441. {
  442. struct net_device *netdev = hunt->efx.netdev;
  443. struct efx_mcdi_req_s req;
  444. MCDI_DECLARE_BUF(payload, MC_CMD_SET_MAC_IN_LEN);
  445. unsigned int fcntl;
  446. int rc;
  447. req.emr_cmd = MC_CMD_SET_MAC;
  448. req.emr_in_buf = payload;
  449. req.emr_in_length = MC_CMD_SET_MAC_IN_LEN;
  450. req.emr_out_buf = NULL;
  451. req.emr_out_length = 0;
  452. MCDI_SET_DWORD(req.emr_in_buf, SET_MAC_IN_MTU,
  453. EFX_MAC_FRAME_LEN(ETH_FRAME_LEN));
  454. MCDI_SET_DWORD(req.emr_in_buf, SET_MAC_IN_DRAIN, 0);
  455. memcpy(MCDI_PTR(req.emr_in_buf, SET_MAC_IN_ADDR),
  456. netdev->ll_addr, ETH_ALEN);
  457. MCDI_SET_DWORD(req.emr_in_buf, SET_MAC_IN_REJECT, 0);
  458. /* If the PHY supports autnegotiation, then configure the MAC to match
  459. * the negotiated settings. Otherwise force the MAC to TX and RX flow
  460. * control.
  461. */
  462. if (hunt->phy_cap_mask & (1 << MC_CMD_PHY_CAP_AN_LBN))
  463. fcntl = MC_CMD_FCNTL_AUTO;
  464. else
  465. fcntl = MC_CMD_FCNTL_BIDIR;
  466. MCDI_SET_DWORD(req.emr_in_buf, SET_MAC_IN_FCNTL, fcntl);
  467. rc = hunt_mcdi(hunt, &req);
  468. /* Ignore failure for permissions reasons */
  469. if (rc == -EPERM)
  470. rc = 0;
  471. return rc;
  472. }
  473. static int hunt_alloc_vis(struct hunt_nic *hunt)
  474. {
  475. struct efx_mcdi_req_s req;
  476. MCDI_DECLARE_BUF(inbuf, MC_CMD_ALLOC_VIS_IN_LEN);
  477. req.emr_cmd = MC_CMD_ALLOC_VIS;
  478. req.emr_in_buf = inbuf;
  479. req.emr_in_length = sizeof(inbuf);
  480. req.emr_out_buf = NULL;
  481. req.emr_out_length = 0;
  482. MCDI_SET_DWORD(req.emr_in_buf, ALLOC_VIS_IN_MIN_VI_COUNT, 1);
  483. MCDI_SET_DWORD(req.emr_in_buf, ALLOC_VIS_IN_MAX_VI_COUNT, 1);
  484. return hunt_mcdi(hunt, &req);
  485. }
  486. static void hunt_free_vis(struct hunt_nic *hunt)
  487. {
  488. struct efx_mcdi_req_s req;
  489. int rc;
  490. req.emr_cmd = MC_CMD_FREE_VIS;
  491. req.emr_in_buf = NULL;
  492. req.emr_in_length = 0;
  493. req.emr_out_buf = NULL;
  494. req.emr_out_length = 0;
  495. rc = hunt_mcdi(hunt, &req);
  496. if (rc != 0)
  497. DBGC(hunt, "MC_CMD_FREE_VIS Failed\n");
  498. }
  499. /*******************************************************************************
  500. *
  501. *
  502. * Link state handling
  503. *
  504. *
  505. ******************************************************************************/
  506. static int hunt_check_link(struct hunt_nic *hunt)
  507. {
  508. struct efx_mcdi_req_s req;
  509. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
  510. unsigned int flags, speed;
  511. bool up;
  512. int rc;
  513. static bool link_state = false;
  514. req.emr_cmd = MC_CMD_GET_LINK;
  515. req.emr_in_buf = NULL;
  516. req.emr_in_length = 0;
  517. req.emr_out_buf = outbuf;
  518. req.emr_out_length = sizeof(outbuf);
  519. rc = hunt_mcdi(hunt, &req);
  520. if (rc != 0)
  521. return rc;
  522. if (req.emr_out_length_used < MC_CMD_GET_LINK_OUT_LEN)
  523. return -EMSGSIZE;
  524. flags = MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_FLAGS);
  525. up = !!(flags & (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN));
  526. speed = MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_LINK_SPEED);
  527. /* Set netdev_link_*() based on the link status from the MC */
  528. if (up && speed)
  529. netdev_link_up(hunt->efx.netdev);
  530. else
  531. netdev_link_down(hunt->efx.netdev);
  532. if (up != link_state) {
  533. DBGC(hunt, "Link %s, flags=%x, our caps=%x, lpa=%x, speed=%d, fcntl=%x, mac_fault=%x\n",
  534. (up? "up": "down"), flags,
  535. MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_CAP),
  536. MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_LP_CAP),
  537. speed,
  538. MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_FCNTL),
  539. MCDI_DWORD(req.emr_out_buf, GET_LINK_OUT_MAC_FAULT));
  540. link_state = up;
  541. }
  542. return 0;
  543. }
  544. #define MCDI_PORT_SPEED_CAPS ((1 << MC_CMD_PHY_CAP_10HDX_LBN) | \
  545. (1 << MC_CMD_PHY_CAP_10FDX_LBN) | \
  546. (1 << MC_CMD_PHY_CAP_100HDX_LBN) | \
  547. (1 << MC_CMD_PHY_CAP_100FDX_LBN) | \
  548. (1 << MC_CMD_PHY_CAP_1000HDX_LBN) | \
  549. (1 << MC_CMD_PHY_CAP_1000FDX_LBN) | \
  550. (1 << MC_CMD_PHY_CAP_10000FDX_LBN) | \
  551. (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
  552. /*******************************************************************************
  553. *
  554. *
  555. * TX
  556. *
  557. *
  558. ******************************************************************************/
  559. static int
  560. hunt_tx_init(struct net_device *netdev, struct hunt_nic *hunt)
  561. {
  562. struct efx_mcdi_req_s req;
  563. dma_addr_t dma_addr;
  564. efx_qword_t *addr;
  565. MCDI_DECLARE_BUF(inbuf,
  566. MC_CMD_INIT_TXQ_IN_LEN(EFX_TXQ_NBUFS(EFX_TXD_SIZE)));
  567. int rc, npages;
  568. rc = efx_hunt_tx_init(netdev, &dma_addr);
  569. if (rc != 0)
  570. return rc;
  571. npages = EFX_TXQ_NBUFS(EFX_TXD_SIZE);
  572. req.emr_cmd = MC_CMD_INIT_TXQ;
  573. req.emr_in_buf = inbuf;
  574. req.emr_in_length = MC_CMD_INIT_TXQ_IN_LEN(npages);
  575. req.emr_out_buf = NULL;
  576. req.emr_out_length = 0;
  577. MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_SIZE, EFX_TXD_SIZE);
  578. MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_TARGET_EVQ, 0);
  579. MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_LABEL, 0);
  580. MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_INSTANCE, 0);
  581. MCDI_POPULATE_DWORD_6(req.emr_in_buf, INIT_TXQ_IN_FLAGS,
  582. INIT_TXQ_IN_FLAG_BUFF_MODE, 0,
  583. INIT_TXQ_IN_FLAG_IP_CSUM_DIS, 1,
  584. INIT_TXQ_IN_FLAG_TCP_CSUM_DIS, 1,
  585. INIT_TXQ_IN_FLAG_TCP_UDP_ONLY, 0,
  586. INIT_TXQ_IN_CRC_MODE, 0,
  587. INIT_TXQ_IN_FLAG_TIMESTAMP, 0);
  588. MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_OWNER_ID, 0);
  589. MCDI_SET_DWORD(req.emr_in_buf, INIT_TXQ_IN_PORT_ID,
  590. EVB_PORT_ID_ASSIGNED);
  591. addr = (efx_qword_t *) MCDI_PTR(req.emr_in_buf, INIT_TXQ_IN_DMA_ADDR);
  592. EFX_POPULATE_QWORD_2(*addr,
  593. EFX_DWORD_1, (uint32_t)(dma_addr >> 32),
  594. EFX_DWORD_0, (uint32_t)(dma_addr & 0xffffffff));
  595. return hunt_mcdi(hunt, &req);
  596. }
  597. static void hunt_tx_fini(struct hunt_nic *hunt)
  598. {
  599. struct efx_mcdi_req_s req;
  600. MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_TXQ_IN_LEN);
  601. struct efx_nic *efx = &hunt->efx;
  602. struct efx_tx_queue *txq = &efx->txq;
  603. int rc;
  604. req.emr_cmd = MC_CMD_FINI_TXQ;
  605. req.emr_in_buf = inbuf;
  606. req.emr_in_length = sizeof(inbuf);
  607. req.emr_out_buf = NULL;
  608. req.emr_out_length = 0;
  609. MCDI_SET_DWORD(req.emr_in_buf, FINI_TXQ_IN_INSTANCE, 0);
  610. rc = hunt_mcdi(hunt, &req);
  611. if (rc != 0)
  612. DBGC(hunt, "MC_CMD_FINI_TXQ Failed\n");
  613. efx_hunt_free_special_buffer(txq->ring,
  614. sizeof(efx_tx_desc_t) * EFX_TXD_SIZE);
  615. txq->ring = NULL;
  616. }
  617. /*******************************************************************************
  618. *
  619. *
  620. * RX
  621. *
  622. *
  623. ******************************************************************************/
  624. static int hunt_rx_filter_insert(struct net_device *netdev,
  625. struct hunt_nic *hunt,
  626. int multicast)
  627. {
  628. struct efx_mcdi_req_s req;
  629. MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
  630. MCDI_DECLARE_BUF(outbuf, MC_CMD_FILTER_OP_OUT_LEN);
  631. int rc;
  632. uint64_t filter_id;
  633. (void) netdev;
  634. req.emr_cmd = MC_CMD_FILTER_OP;
  635. req.emr_in_buf = inbuf;
  636. req.emr_in_length = sizeof(inbuf);
  637. req.emr_out_buf = outbuf;
  638. req.emr_out_length = sizeof(outbuf);
  639. MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_OP,
  640. multicast ? MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE
  641. : MC_CMD_FILTER_OP_IN_OP_INSERT);
  642. MCDI_POPULATE_DWORD_1(req.emr_in_buf, FILTER_OP_IN_MATCH_FIELDS,
  643. FILTER_OP_IN_MATCH_DST_MAC, 1);
  644. if (multicast)
  645. memset(MCDI_PTR(req.emr_in_buf, FILTER_OP_IN_DST_MAC),
  646. 0xff, ETH_ALEN);
  647. else
  648. memcpy(MCDI_PTR(req.emr_in_buf, FILTER_OP_IN_DST_MAC),
  649. hunt->mac, ETH_ALEN);
  650. MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_PORT_ID,
  651. EVB_PORT_ID_ASSIGNED);
  652. MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_RX_DEST,
  653. MC_CMD_FILTER_OP_IN_RX_DEST_HOST);
  654. MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_RX_QUEUE, 0);
  655. MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_RX_MODE, 0);
  656. MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_TX_DEST,
  657. MC_CMD_FILTER_OP_IN_TX_DEST_DEFAULT);
  658. rc = hunt_mcdi(hunt, &req);
  659. if (rc != 0)
  660. return rc;
  661. if (req.emr_out_length_used < MC_CMD_FILTER_OP_OUT_LEN)
  662. return -EIO;
  663. filter_id = MCDI_QWORD(req.emr_out_buf, FILTER_OP_OUT_HANDLE);
  664. if (multicast)
  665. hunt->mc_filter_id = filter_id;
  666. else
  667. hunt->uc_filter_id = filter_id;
  668. return 0;
  669. }
  670. static int hunt_rx_filter_remove(struct hunt_nic *hunt,
  671. int multicast)
  672. {
  673. struct efx_mcdi_req_s req;
  674. MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
  675. req.emr_cmd = MC_CMD_FILTER_OP;
  676. req.emr_in_buf = inbuf;
  677. req.emr_in_length = sizeof(inbuf);
  678. req.emr_out_buf = NULL;
  679. req.emr_out_length = 0;
  680. MCDI_SET_DWORD(req.emr_in_buf, FILTER_OP_IN_OP,
  681. multicast ? MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE :
  682. MC_CMD_FILTER_OP_IN_OP_REMOVE);
  683. MCDI_SET_QWORD(req.emr_in_buf, FILTER_OP_IN_HANDLE,
  684. multicast ? hunt->mc_filter_id :
  685. hunt->uc_filter_id);
  686. return hunt_mcdi(hunt, &req);
  687. }
  688. static int hunt_get_mac(struct hunt_nic *hunt)
  689. {
  690. struct efx_mcdi_req_s req;
  691. MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
  692. int rc;
  693. req.emr_cmd = MC_CMD_GET_MAC_ADDRESSES;
  694. req.emr_in_buf = NULL;
  695. req.emr_in_length = 0;
  696. req.emr_out_buf = outbuf;
  697. req.emr_out_length = sizeof(outbuf);
  698. rc = hunt_mcdi(hunt, &req);
  699. if (rc != 0)
  700. return rc;
  701. if (req.emr_out_length_used < MC_CMD_INIT_EVQ_OUT_LEN)
  702. return -EMSGSIZE;
  703. memcpy(hunt->mac, MCDI_PTR(outbuf, GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE),
  704. ETH_ALEN);
  705. return 0;
  706. }
  707. static int hunt_rx_filter_init(struct net_device *netdev,
  708. struct hunt_nic *hunt)
  709. {
  710. int rc = hunt_get_mac(hunt);
  711. if (rc != 0)
  712. return rc;
  713. rc = hunt_rx_filter_insert(netdev, hunt, 0);
  714. if (rc != 0)
  715. return rc;
  716. rc = hunt_rx_filter_insert(netdev, hunt, 1);
  717. if (rc != 0)
  718. hunt_rx_filter_remove(hunt, 0);
  719. return rc;
  720. }
  721. static int
  722. hunt_rx_init(struct net_device *netdev,
  723. struct hunt_nic *hunt)
  724. {
  725. struct efx_mcdi_req_s req;
  726. dma_addr_t dma_addr;
  727. efx_qword_t *addr;
  728. MCDI_DECLARE_BUF(inbuf,
  729. MC_CMD_INIT_RXQ_IN_LEN(EFX_RXQ_NBUFS(EFX_RXD_SIZE)));
  730. int rc, npages;
  731. rc = efx_hunt_rx_init(netdev, &dma_addr);
  732. if (rc != 0)
  733. return rc;
  734. npages = EFX_RXQ_NBUFS(EFX_RXD_SIZE);
  735. req.emr_cmd = MC_CMD_INIT_RXQ;
  736. req.emr_in_buf = inbuf;
  737. req.emr_in_length = MC_CMD_INIT_RXQ_IN_LEN(npages);
  738. req.emr_out_buf = NULL;
  739. req.emr_out_length = 0;
  740. MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_SIZE, EFX_RXD_SIZE);
  741. MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_TARGET_EVQ, 0);
  742. MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_LABEL, 0);
  743. MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_INSTANCE, 0);
  744. MCDI_POPULATE_DWORD_5(req.emr_in_buf, INIT_RXQ_IN_FLAGS,
  745. INIT_RXQ_IN_FLAG_BUFF_MODE, 0,
  746. INIT_RXQ_IN_FLAG_HDR_SPLIT, 0,
  747. INIT_RXQ_IN_FLAG_TIMESTAMP, 0,
  748. INIT_RXQ_IN_CRC_MODE, 0,
  749. INIT_RXQ_IN_FLAG_PREFIX, 1);
  750. MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_OWNER_ID, 0);
  751. MCDI_SET_DWORD(req.emr_in_buf, INIT_RXQ_IN_PORT_ID,
  752. EVB_PORT_ID_ASSIGNED);
  753. addr = (efx_qword_t *) MCDI_PTR(req.emr_in_buf, INIT_RXQ_IN_DMA_ADDR);
  754. EFX_POPULATE_QWORD_2(*addr,
  755. EFX_DWORD_1, (uint32_t)(dma_addr >> 32),
  756. EFX_DWORD_0, (uint32_t)(dma_addr & 0xffffffff));
  757. return hunt_mcdi(hunt, &req);
  758. }
  759. static void hunt_rx_filter_fini(struct hunt_nic *hunt)
  760. {
  761. hunt_rx_filter_remove(hunt, 0);
  762. hunt_rx_filter_remove(hunt, 1);
  763. }
  764. static void hunt_rx_fini(struct hunt_nic *hunt)
  765. {
  766. MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_RXQ_IN_LEN);
  767. struct efx_mcdi_req_s req;
  768. struct efx_nic *efx = &hunt->efx;
  769. struct efx_rx_queue *rxq = &efx->rxq;
  770. int rc;
  771. req.emr_cmd = MC_CMD_FINI_RXQ;
  772. req.emr_in_buf = inbuf;
  773. req.emr_in_length = MC_CMD_FINI_RXQ_IN_LEN;
  774. req.emr_out_buf = NULL;
  775. req.emr_out_length = 0;
  776. MCDI_SET_DWORD(req.emr_in_buf, FINI_RXQ_IN_INSTANCE, 0);
  777. rc = hunt_mcdi(hunt, &req);
  778. if (rc != 0)
  779. DBGC(hunt, "MC_CMD_FINI_RXQ Failed\n");
  780. efx_hunt_free_special_buffer(rxq->ring,
  781. sizeof(efx_rx_desc_t) * EFX_RXD_SIZE);
  782. rxq->ring = NULL;
  783. }
  784. /*******************************************************************************
  785. *
  786. *
  787. * Event queues and interrupts
  788. *
  789. *
  790. ******************************************************************************/
  791. static int
  792. hunt_ev_init(struct net_device *netdev,
  793. struct hunt_nic *hunt)
  794. {
  795. struct efx_mcdi_req_s req;
  796. dma_addr_t dma_addr;
  797. efx_qword_t *addr;
  798. MCDI_DECLARE_BUF(inbuf,
  799. MC_CMD_INIT_EVQ_IN_LEN(EFX_EVQ_NBUFS(EFX_EVQ_SIZE)));
  800. MCDI_DECLARE_BUF(outbuf, MC_CMD_INIT_EVQ_OUT_LEN);
  801. int rc, npages;
  802. rc = efx_hunt_ev_init(netdev, &dma_addr);
  803. if (rc != 0)
  804. return rc;
  805. npages = EFX_EVQ_NBUFS(EFX_EVQ_SIZE);
  806. req.emr_cmd = MC_CMD_INIT_EVQ;
  807. req.emr_in_buf = inbuf;
  808. req.emr_in_length = MC_CMD_INIT_EVQ_IN_LEN(npages);
  809. req.emr_out_buf = outbuf;
  810. req.emr_out_length = sizeof(outbuf);
  811. MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_SIZE, EFX_EVQ_SIZE);
  812. MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_INSTANCE, 0);
  813. MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_IRQ_NUM, 0);
  814. MCDI_POPULATE_DWORD_6(req.emr_in_buf, INIT_EVQ_IN_FLAGS,
  815. INIT_EVQ_IN_FLAG_INTERRUPTING, 1,
  816. INIT_EVQ_IN_FLAG_RPTR_DOS, 0,
  817. INIT_EVQ_IN_FLAG_INT_ARMD, 0,
  818. INIT_EVQ_IN_FLAG_CUT_THRU, 0,
  819. INIT_EVQ_IN_FLAG_RX_MERGE, 0,
  820. INIT_EVQ_IN_FLAG_TX_MERGE, 0);
  821. MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_TMR_MODE,
  822. MC_CMD_INIT_EVQ_IN_TMR_MODE_DIS);
  823. MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_TMR_LOAD, 0);
  824. MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_TMR_RELOAD, 0);
  825. MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_COUNT_MODE,
  826. MC_CMD_INIT_EVQ_IN_COUNT_MODE_DIS);
  827. MCDI_SET_DWORD(req.emr_in_buf, INIT_EVQ_IN_COUNT_THRSHLD, 0);
  828. addr = (efx_qword_t *) MCDI_PTR(req.emr_in_buf, INIT_EVQ_IN_DMA_ADDR);
  829. EFX_POPULATE_QWORD_2(*addr,
  830. EFX_DWORD_1, (uint32_t)(dma_addr >> 32),
  831. EFX_DWORD_0, (uint32_t)(dma_addr & 0xffffffff));
  832. rc = hunt_mcdi(hunt, &req);
  833. if (rc != 0)
  834. return rc;
  835. if (req.emr_out_length_used < MC_CMD_INIT_EVQ_OUT_LEN)
  836. return -EMSGSIZE;
  837. return 0;
  838. }
  839. static void hunt_ev_fini(struct hunt_nic *hunt)
  840. {
  841. MCDI_DECLARE_BUF(inbuf, MC_CMD_FINI_EVQ_IN_LEN);
  842. struct efx_mcdi_req_s req;
  843. struct efx_nic *efx = &hunt->efx;
  844. struct efx_ev_queue *evq = &efx->evq;
  845. int rc;
  846. req.emr_cmd = MC_CMD_FINI_EVQ;
  847. req.emr_in_buf = inbuf;
  848. req.emr_in_length = sizeof(inbuf);
  849. req.emr_out_buf = NULL;
  850. req.emr_out_length = 0;
  851. MCDI_SET_DWORD(req.emr_in_buf, FINI_EVQ_IN_INSTANCE, 0);
  852. rc = hunt_mcdi(hunt, &req);
  853. if (rc != 0)
  854. DBGC(hunt, "MC_CMD_FINI_EVQ Failed\n");
  855. efx_hunt_free_special_buffer(evq->ring,
  856. sizeof(efx_event_t) * EFX_EVQ_SIZE);
  857. evq->ring = NULL;
  858. }
  859. static void
  860. hunt_poll(struct net_device *netdev)
  861. {
  862. struct hunt_nic *hunt = netdev_priv(netdev);
  863. /* If called while already polling, return immediately */
  864. if (hunt->efx.state & EFX_STATE_POLLING)
  865. return;
  866. hunt->efx.state |= EFX_STATE_POLLING;
  867. /* Poll link state */
  868. if (hunt->link_poll_timer + TICKS_PER_SEC < currticks()) {
  869. hunt->link_poll_timer = currticks();
  870. hunt_check_link(hunt);
  871. }
  872. /* Poll data path */
  873. efx_hunt_poll(netdev);
  874. hunt->efx.state &= ~EFX_STATE_POLLING;
  875. }
  876. /*******************************************************************************
  877. *
  878. *
  879. * Netdevice operations
  880. *
  881. *
  882. ******************************************************************************/
  883. static int hunt_open(struct net_device *netdev)
  884. {
  885. struct hunt_nic *hunt = netdev_priv(netdev);
  886. int rc;
  887. /* Allocate VIs */
  888. rc = hunt_alloc_vis(hunt);
  889. if (rc != 0)
  890. goto fail2;
  891. /* Initialize data path */
  892. rc = hunt_ev_init(netdev, hunt);
  893. if (rc != 0)
  894. goto fail3;
  895. rc = hunt_rx_init(netdev, hunt);
  896. if (rc != 0)
  897. goto fail4;
  898. rc = hunt_rx_filter_init(netdev, hunt);
  899. if (rc != 0)
  900. goto fail5;
  901. rc = hunt_tx_init(netdev, hunt);
  902. if (rc != 0)
  903. goto fail6;
  904. rc = efx_hunt_open(netdev);
  905. if (rc)
  906. goto fail7;
  907. rc = hunt_set_mac(hunt);
  908. if (rc)
  909. goto fail8;
  910. /* Mark the link as down before checking the link state because the
  911. * latter might fail.
  912. */
  913. netdev_link_down(netdev);
  914. hunt_check_link(hunt);
  915. DBGC2(hunt, "%s: open ok\n", netdev->name);
  916. return 0;
  917. fail8:
  918. efx_hunt_close(netdev);
  919. fail7:
  920. hunt_tx_fini(hunt);
  921. fail6:
  922. hunt_rx_filter_fini(hunt);
  923. fail5:
  924. hunt_rx_fini(hunt);
  925. fail4:
  926. hunt_ev_fini(hunt);
  927. fail3:
  928. hunt_free_vis(hunt);
  929. fail2:
  930. DBGC2(hunt, "%s: %s\n", netdev->name, strerror(rc));
  931. return rc;
  932. }
  933. static void hunt_close(struct net_device *netdev)
  934. {
  935. struct hunt_nic *hunt = netdev_priv(netdev);
  936. /* Stop datapath */
  937. efx_hunt_close(netdev);
  938. hunt_tx_fini(hunt);
  939. hunt_rx_fini(hunt);
  940. hunt_rx_filter_fini(hunt);
  941. hunt_ev_fini(hunt);
  942. hunt_free_vis(hunt);
  943. /* Reset hardware and detach */
  944. hunt_reset(hunt);
  945. }
  946. /*******************************************************************************
  947. *
  948. *
  949. * Public operations
  950. *
  951. *
  952. ******************************************************************************/
  953. static struct net_device_operations hunt_operations = {
  954. .open = hunt_open,
  955. .close = hunt_close,
  956. .transmit = efx_hunt_transmit,
  957. .poll = hunt_poll,
  958. .irq = efx_hunt_irq,
  959. };
  960. static int
  961. hunt_probe(struct pci_device *pci)
  962. {
  963. struct net_device *netdev;
  964. struct hunt_nic *hunt;
  965. struct efx_nic *efx;
  966. int rc = 0;
  967. /* Create the network adapter */
  968. netdev = alloc_etherdev(sizeof(struct hunt_nic));
  969. if (!netdev) {
  970. rc = -ENOMEM;
  971. goto fail1;
  972. }
  973. /* Initialise the network adapter, and initialise private storage */
  974. netdev_init(netdev, &hunt_operations);
  975. pci_set_drvdata(pci, netdev);
  976. netdev->dev = &pci->dev;
  977. netdev->state |= NETDEV_IRQ_UNSUPPORTED;
  978. hunt = netdev_priv(netdev);
  979. memset(hunt, 0, sizeof(*hunt));
  980. efx = &hunt->efx;
  981. efx->type = &hunt_nic_type;
  982. /* Initialise efx datapath */
  983. efx_probe(netdev, EFX_HUNTINGTON);
  984. /* Initialise MCDI. In case we are recovering from a crash, first
  985. * cancel any outstanding request by sending a special message using the
  986. * least significant bits of the 'high' (doorbell) register.
  987. */
  988. _efx_writel(efx, cpu_to_le32(1), ER_DZ_MC_DB_HWRD);
  989. rc = hunt_mcdi_init(hunt);
  990. if (rc != 0)
  991. goto fail2;
  992. /* Reset (most) configuration for this function */
  993. rc = hunt_reset(hunt);
  994. if (rc != 0)
  995. goto fail3;
  996. /* Medford has a list of UDP tunnel ports that is populated by the
  997. * driver. Avoid dropping any unencapsulated packets. This may cause
  998. * an MC reboot.
  999. */
  1000. hunt_clear_udp_tunnel_ports(hunt);
  1001. /* Enable the workaround for bug35388, if supported */
  1002. efx->workaround_35388 = hunt_workaround_35388(hunt);
  1003. /* Set the RX packet prefix size */
  1004. efx->rx_prefix_size = ES_DZ_RX_PREFIX_SIZE;
  1005. rc = hunt_get_port_assignment(hunt);
  1006. if (rc != 0)
  1007. goto fail3;
  1008. rc = hunt_mac_addr(hunt, netdev->ll_addr);
  1009. if (rc != 0)
  1010. goto fail4;
  1011. rc = hunt_get_phy_cfg(hunt);
  1012. if (rc != 0)
  1013. goto fail5;
  1014. rc = hunt_driver_attach(hunt, 1);
  1015. if (rc != 0)
  1016. goto fail5;
  1017. /* If not exposing this network device, return successfully here */
  1018. if (hunt->flags & (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_NO_ACTIVE_PORT))
  1019. return 0;
  1020. if (hunt_nic_is_primary(hunt)) {
  1021. hunt->next_primary = primary_nics;
  1022. primary_nics = hunt;
  1023. hunt->primary = hunt;
  1024. } else {
  1025. struct hunt_nic *other_hunt = primary_nics;
  1026. while (other_hunt && !hunt->primary) {
  1027. struct pci_device *other_pci = (struct pci_device *)
  1028. other_hunt->efx.netdev->dev;
  1029. /* Check if the seg:bus:dev parts match. */
  1030. if (PCI_FIRST_FUNC(other_pci->busdevfn) ==
  1031. PCI_FIRST_FUNC(pci->busdevfn))
  1032. hunt->primary = other_hunt;
  1033. other_hunt = other_hunt->next_primary;
  1034. }
  1035. if (!hunt->primary) {
  1036. rc = -EIO;
  1037. goto fail6;
  1038. }
  1039. }
  1040. rc = register_netdev(netdev);
  1041. if (rc != 0)
  1042. goto fail8;
  1043. DBG2("%s " PCI_FMT " ok\n", __func__, PCI_ARGS(pci));
  1044. return 0;
  1045. fail8:
  1046. fail6:
  1047. (void) hunt_driver_attach(hunt, 0);
  1048. fail5:
  1049. fail4:
  1050. fail3:
  1051. hunt_mcdi_fini(hunt);
  1052. fail2:
  1053. efx_remove(netdev);
  1054. netdev_put(netdev);
  1055. fail1:
  1056. DBG2("%s " PCI_FMT " rc=%d\n", __func__, PCI_ARGS(pci), rc);
  1057. return rc;
  1058. }
  1059. static void hunt_remove(struct pci_device *pci)
  1060. {
  1061. struct net_device *netdev = pci_get_drvdata(pci);
  1062. struct hunt_nic *hunt = netdev_priv(netdev);
  1063. if (!(hunt->flags &
  1064. (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_NO_ACTIVE_PORT))) {
  1065. /* The netdevice might still be open, so unregister it now
  1066. * before ripping stuff out from underneath.
  1067. */
  1068. unregister_netdev(netdev);
  1069. }
  1070. (void)hunt_driver_attach(hunt, 0);
  1071. hunt_mcdi_fini(hunt);
  1072. /* Destroy data path */
  1073. efx_remove(netdev);
  1074. netdev_nullify(netdev);
  1075. netdev_put(netdev);
  1076. }
  1077. const struct efx_nic_type hunt_nic_type = {
  1078. .mcdi_rpc = _hunt_mcdi,
  1079. };
  1080. static struct pci_device_id hunt_nics[] = {
  1081. PCI_ROM(0x1924, 0x0a03, "SFC9220", "Solarflare SFN8xxx Adapter", 0),
  1082. PCI_ROM(0x1924, 0x0b03, "SFC9250", "Solarflare X25xx Adapter", 0),
  1083. };
  1084. struct pci_driver hunt_driver __pci_driver = {
  1085. .ids = hunt_nics,
  1086. .id_count = ARRAY_SIZE(hunt_nics),
  1087. .probe = hunt_probe,
  1088. .remove = hunt_remove,
  1089. };