ldpaa_eth.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. /*
  2. * Copyright (C) 2014 Freescale Semiconductor
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <common.h>
  7. #include <asm/io.h>
  8. #include <asm/types.h>
  9. #include <malloc.h>
  10. #include <net.h>
  11. #include <hwconfig.h>
  12. #include <phy.h>
  13. #include <linux/compat.h>
  14. #include "ldpaa_eth.h"
  15. #undef CONFIG_PHYLIB
  16. static int init_phy(struct eth_device *dev)
  17. {
  18. /*TODO for external PHY */
  19. return 0;
  20. }
  21. static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
  22. const struct dpaa_fd *fd)
  23. {
  24. u64 fd_addr;
  25. uint16_t fd_offset;
  26. uint32_t fd_length;
  27. struct ldpaa_fas *fas;
  28. uint32_t status, err;
  29. u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
  30. u32 time_start;
  31. struct qbman_release_desc releasedesc;
  32. struct qbman_swp *swp = dflt_dpio->sw_portal;
  33. fd_addr = ldpaa_fd_get_addr(fd);
  34. fd_offset = ldpaa_fd_get_offset(fd);
  35. fd_length = ldpaa_fd_get_len(fd);
  36. debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
  37. if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
  38. /* Read the frame annotation status word and check for errors */
  39. fas = (struct ldpaa_fas *)
  40. ((uint8_t *)(fd_addr) +
  41. priv->buf_layout.private_data_size);
  42. status = le32_to_cpu(fas->status);
  43. if (status & LDPAA_ETH_RX_ERR_MASK) {
  44. printf("Rx frame error(s): 0x%08x\n",
  45. status & LDPAA_ETH_RX_ERR_MASK);
  46. goto error;
  47. } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
  48. printf("Unsupported feature in bitmask: 0x%08x\n",
  49. status & LDPAA_ETH_RX_UNSUPP_MASK);
  50. goto error;
  51. }
  52. }
  53. debug("Rx frame: To Upper layer\n");
  54. net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
  55. fd_length);
  56. error:
  57. flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
  58. qbman_release_desc_clear(&releasedesc);
  59. qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
  60. time_start = get_timer(0);
  61. do {
  62. /* Release buffer into the QBMAN */
  63. err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
  64. } while (get_timer(time_start) < timeo && err == -EBUSY);
  65. if (err == -EBUSY)
  66. printf("Rx frame: QBMAN buffer release fails\n");
  67. return;
  68. }
  69. static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev)
  70. {
  71. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
  72. const struct ldpaa_dq *dq;
  73. const struct dpaa_fd *fd;
  74. int i = 5, err = 0, status;
  75. u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
  76. u32 time_start;
  77. static struct qbman_pull_desc pulldesc;
  78. struct qbman_swp *swp = dflt_dpio->sw_portal;
  79. while (--i) {
  80. qbman_pull_desc_clear(&pulldesc);
  81. qbman_pull_desc_set_numframes(&pulldesc, 1);
  82. qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
  83. err = qbman_swp_pull(swp, &pulldesc);
  84. if (err < 0) {
  85. printf("Dequeue frames error:0x%08x\n", err);
  86. continue;
  87. }
  88. time_start = get_timer(0);
  89. do {
  90. dq = qbman_swp_dqrr_next(swp);
  91. } while (get_timer(time_start) < timeo && !dq);
  92. if (dq) {
  93. /* Check for valid frame. If not sent a consume
  94. * confirmation to QBMAN otherwise give it to NADK
  95. * application and then send consume confirmation to
  96. * QBMAN.
  97. */
  98. status = (uint8_t)ldpaa_dq_flags(dq);
  99. if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
  100. debug("Dequeue RX frames:");
  101. debug("No frame delivered\n");
  102. qbman_swp_dqrr_consume(swp, dq);
  103. continue;
  104. }
  105. fd = ldpaa_dq_fd(dq);
  106. /* Obtain FD and process it */
  107. ldpaa_eth_rx(priv, fd);
  108. qbman_swp_dqrr_consume(swp, dq);
  109. break;
  110. } else {
  111. err = -ENODATA;
  112. debug("No DQRR entries\n");
  113. break;
  114. }
  115. }
  116. return err;
  117. }
  118. static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
  119. {
  120. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  121. struct dpaa_fd fd;
  122. u64 buffer_start;
  123. int data_offset, err;
  124. u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
  125. u32 time_start;
  126. struct qbman_swp *swp = dflt_dpio->sw_portal;
  127. struct qbman_eq_desc ed;
  128. struct qbman_release_desc releasedesc;
  129. /* Setup the FD fields */
  130. memset(&fd, 0, sizeof(fd));
  131. data_offset = priv->tx_data_offset;
  132. do {
  133. err = qbman_swp_acquire(dflt_dpio->sw_portal,
  134. dflt_dpbp->dpbp_attr.bpid,
  135. &buffer_start, 1);
  136. } while (err == -EBUSY);
  137. if (err < 0) {
  138. printf("qbman_swp_acquire() failed\n");
  139. return -ENOMEM;
  140. }
  141. debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
  142. memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
  143. flush_dcache_range(buffer_start, buffer_start +
  144. LDPAA_ETH_RX_BUFFER_SIZE);
  145. ldpaa_fd_set_addr(&fd, (u64)buffer_start);
  146. ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
  147. ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
  148. ldpaa_fd_set_len(&fd, len);
  149. fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
  150. LDPAA_FD_CTRL_PTV1;
  151. qbman_eq_desc_clear(&ed);
  152. qbman_eq_desc_set_no_orp(&ed, 0);
  153. qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
  154. time_start = get_timer(0);
  155. while (get_timer(time_start) < timeo) {
  156. err = qbman_swp_enqueue(swp, &ed,
  157. (const struct qbman_fd *)(&fd));
  158. if (err != -EBUSY)
  159. break;
  160. }
  161. if (err < 0) {
  162. printf("error enqueueing Tx frame\n");
  163. goto error;
  164. }
  165. return err;
  166. error:
  167. qbman_release_desc_clear(&releasedesc);
  168. qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
  169. time_start = get_timer(0);
  170. do {
  171. /* Release buffer into the QBMAN */
  172. err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
  173. } while (get_timer(time_start) < timeo && err == -EBUSY);
  174. if (err == -EBUSY)
  175. printf("TX data: QBMAN buffer release fails\n");
  176. return err;
  177. }
  178. static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
  179. {
  180. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  181. struct dpni_queue_attr rx_queue_attr;
  182. uint8_t mac_addr[6];
  183. int err;
  184. if (net_dev->state == ETH_STATE_ACTIVE)
  185. return 0;
  186. /* DPNI initialization */
  187. err = ldpaa_dpni_setup(priv);
  188. if (err < 0)
  189. goto err_dpni_setup;
  190. err = ldpaa_dpbp_setup();
  191. if (err < 0)
  192. goto err_dpbp_setup;
  193. /* DPNI binding DPBP */
  194. err = ldpaa_dpni_bind(priv);
  195. if (err)
  196. goto err_bind;
  197. err = dpni_get_primary_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
  198. priv->dpni_handle, mac_addr);
  199. if (err) {
  200. printf("dpni_get_primary_mac_addr() failed\n");
  201. return err;
  202. }
  203. memcpy(net_dev->enetaddr, mac_addr, 0x6);
  204. /* setup the MAC address */
  205. if (net_dev->enetaddr[0] & 0x01) {
  206. printf("%s: MacAddress is multcast address\n", __func__);
  207. return 1;
  208. }
  209. #ifdef CONFIG_PHYLIB
  210. /* TODO Check this path */
  211. err = phy_startup(priv->phydev);
  212. if (err) {
  213. printf("%s: Could not initialize\n", priv->phydev->dev->name);
  214. return err;
  215. }
  216. #else
  217. priv->phydev->speed = SPEED_1000;
  218. priv->phydev->link = 1;
  219. priv->phydev->duplex = DUPLEX_FULL;
  220. #endif
  221. err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_handle);
  222. if (err < 0) {
  223. printf("dpni_enable() failed\n");
  224. return err;
  225. }
  226. /* TODO: support multiple Rx flows */
  227. err = dpni_get_rx_flow(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_handle,
  228. 0, 0, &rx_queue_attr);
  229. if (err) {
  230. printf("dpni_get_rx_flow() failed\n");
  231. goto err_rx_flow;
  232. }
  233. priv->rx_dflt_fqid = rx_queue_attr.fqid;
  234. err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_handle,
  235. &priv->tx_qdid);
  236. if (err) {
  237. printf("dpni_get_qdid() failed\n");
  238. goto err_qdid;
  239. }
  240. if (!priv->phydev->link)
  241. printf("%s: No link.\n", priv->phydev->dev->name);
  242. return priv->phydev->link ? 0 : -1;
  243. err_qdid:
  244. err_rx_flow:
  245. dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_handle);
  246. err_bind:
  247. ldpaa_dpbp_free();
  248. err_dpbp_setup:
  249. dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_handle);
  250. err_dpni_setup:
  251. return err;
  252. }
  253. static void ldpaa_eth_stop(struct eth_device *net_dev)
  254. {
  255. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  256. int err = 0;
  257. if ((net_dev->state == ETH_STATE_PASSIVE) ||
  258. (net_dev->state == ETH_STATE_INIT))
  259. return;
  260. /* Stop Tx and Rx traffic */
  261. err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_handle);
  262. if (err < 0)
  263. printf("dpni_disable() failed\n");
  264. #ifdef CONFIG_PHYLIB
  265. phy_shutdown(priv->phydev);
  266. #endif
  267. ldpaa_dpbp_free();
  268. dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_handle);
  269. dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_handle);
  270. }
  271. static void ldpaa_dpbp_drain_cnt(int count)
  272. {
  273. uint64_t buf_array[7];
  274. void *addr;
  275. int ret, i;
  276. BUG_ON(count > 7);
  277. do {
  278. ret = qbman_swp_acquire(dflt_dpio->sw_portal,
  279. dflt_dpbp->dpbp_attr.bpid,
  280. buf_array, count);
  281. if (ret < 0) {
  282. printf("qbman_swp_acquire() failed\n");
  283. return;
  284. }
  285. for (i = 0; i < ret; i++) {
  286. addr = (void *)buf_array[i];
  287. debug("Free: buffer addr =0x%p\n", addr);
  288. free(addr);
  289. }
  290. } while (ret);
  291. }
  292. static void ldpaa_dpbp_drain(void)
  293. {
  294. int i;
  295. for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
  296. ldpaa_dpbp_drain_cnt(7);
  297. }
  298. static int ldpaa_bp_add_7(uint16_t bpid)
  299. {
  300. uint64_t buf_array[7];
  301. u8 *addr;
  302. int i;
  303. struct qbman_release_desc rd;
  304. for (i = 0; i < 7; i++) {
  305. addr = memalign(L1_CACHE_BYTES, LDPAA_ETH_RX_BUFFER_SIZE);
  306. if (!addr) {
  307. printf("addr allocation failed\n");
  308. goto err_alloc;
  309. }
  310. memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
  311. flush_dcache_range((u64)addr,
  312. (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
  313. buf_array[i] = (uint64_t)addr;
  314. debug("Release: buffer addr =0x%p\n", addr);
  315. }
  316. release_bufs:
  317. /* In case the portal is busy, retry until successful.
  318. * This function is guaranteed to succeed in a reasonable amount
  319. * of time.
  320. */
  321. do {
  322. mdelay(1);
  323. qbman_release_desc_clear(&rd);
  324. qbman_release_desc_set_bpid(&rd, bpid);
  325. } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
  326. return i;
  327. err_alloc:
  328. if (i)
  329. goto release_bufs;
  330. return 0;
  331. }
  332. static int ldpaa_dpbp_seed(uint16_t bpid)
  333. {
  334. int i;
  335. int count;
  336. for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
  337. count = ldpaa_bp_add_7(bpid);
  338. if (count < 7)
  339. printf("Buffer Seed= %d\n", count);
  340. }
  341. return 0;
  342. }
  343. static int ldpaa_dpbp_setup(void)
  344. {
  345. int err;
  346. err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
  347. &dflt_dpbp->dpbp_handle);
  348. if (err) {
  349. printf("dpbp_open() failed\n");
  350. goto err_open;
  351. }
  352. err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  353. if (err) {
  354. printf("dpbp_enable() failed\n");
  355. goto err_enable;
  356. }
  357. err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
  358. dflt_dpbp->dpbp_handle,
  359. &dflt_dpbp->dpbp_attr);
  360. if (err) {
  361. printf("dpbp_get_attributes() failed\n");
  362. goto err_get_attr;
  363. }
  364. err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
  365. if (err) {
  366. printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
  367. dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
  368. goto err_seed;
  369. }
  370. return 0;
  371. err_seed:
  372. err_get_attr:
  373. dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  374. err_enable:
  375. dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  376. err_open:
  377. return err;
  378. }
  379. static void ldpaa_dpbp_free(void)
  380. {
  381. ldpaa_dpbp_drain();
  382. dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  383. dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  384. dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
  385. }
  386. static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
  387. {
  388. int err;
  389. /* and get a handle for the DPNI this interface is associate with */
  390. err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_id,
  391. &priv->dpni_handle);
  392. if (err) {
  393. printf("dpni_open() failed\n");
  394. goto err_open;
  395. }
  396. err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
  397. priv->dpni_handle, &priv->dpni_attrs);
  398. if (err) {
  399. printf("dpni_get_attributes() failed (err=%d)\n", err);
  400. goto err_get_attr;
  401. }
  402. /* Configure our buffers' layout */
  403. priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
  404. DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
  405. DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
  406. priv->buf_layout.pass_parser_result = true;
  407. priv->buf_layout.pass_frame_status = true;
  408. priv->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
  409. /* ...rx, ... */
  410. err = dpni_set_rx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
  411. priv->dpni_handle, &priv->buf_layout);
  412. if (err) {
  413. printf("dpni_set_rx_buffer_layout() failed");
  414. goto err_buf_layout;
  415. }
  416. /* ... tx, ... */
  417. priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PARSER_RESULT;
  418. err = dpni_set_tx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
  419. priv->dpni_handle, &priv->buf_layout);
  420. if (err) {
  421. printf("dpni_set_tx_buffer_layout() failed");
  422. goto err_buf_layout;
  423. }
  424. /* ... tx-confirm. */
  425. priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
  426. err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
  427. priv->dpni_handle,
  428. &priv->buf_layout);
  429. if (err) {
  430. printf("dpni_set_tx_conf_buffer_layout() failed");
  431. goto err_buf_layout;
  432. }
  433. /* Now that we've set our tx buffer layout, retrieve the minimum
  434. * required tx data offset.
  435. */
  436. err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
  437. priv->dpni_handle, &priv->tx_data_offset);
  438. if (err) {
  439. printf("dpni_get_tx_data_offset() failed\n");
  440. goto err_data_offset;
  441. }
  442. /* Warn in case TX data offset is not multiple of 64 bytes. */
  443. WARN_ON(priv->tx_data_offset % 64);
  444. /* Accomodate SWA space. */
  445. priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
  446. debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
  447. return 0;
  448. err_data_offset:
  449. err_buf_layout:
  450. err_get_attr:
  451. dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_handle);
  452. err_open:
  453. return err;
  454. }
  455. static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
  456. {
  457. struct dpni_pools_cfg pools_params;
  458. struct dpni_tx_flow_cfg dflt_tx_flow;
  459. int err = 0;
  460. pools_params.num_dpbp = 1;
  461. pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
  462. pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
  463. err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_handle,
  464. &pools_params);
  465. if (err) {
  466. printf("dpni_set_pools() failed\n");
  467. return err;
  468. }
  469. priv->tx_flow_id = DPNI_NEW_FLOW_ID;
  470. memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow));
  471. dflt_tx_flow.options = DPNI_TX_FLOW_OPT_ONLY_TX_ERROR;
  472. dflt_tx_flow.conf_err_cfg.use_default_queue = 0;
  473. dflt_tx_flow.conf_err_cfg.errors_only = 1;
  474. err = dpni_set_tx_flow(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpni_handle,
  475. &priv->tx_flow_id, &dflt_tx_flow);
  476. if (err) {
  477. printf("dpni_set_tx_flow() failed\n");
  478. return err;
  479. }
  480. return 0;
  481. }
  482. static int ldpaa_eth_netdev_init(struct eth_device *net_dev)
  483. {
  484. int err;
  485. struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
  486. sprintf(net_dev->name, "DPNI%d", priv->dpni_id);
  487. net_dev->iobase = 0;
  488. net_dev->init = ldpaa_eth_open;
  489. net_dev->halt = ldpaa_eth_stop;
  490. net_dev->send = ldpaa_eth_tx;
  491. net_dev->recv = ldpaa_eth_pull_dequeue_rx;
  492. /*
  493. TODO: PHY MDIO information
  494. priv->bus = info->bus;
  495. priv->phyaddr = info->phy_addr;
  496. priv->enet_if = info->enet_if;
  497. */
  498. if (init_phy(net_dev))
  499. return 0;
  500. err = eth_register(net_dev);
  501. if (err < 0) {
  502. printf("eth_register() = %d\n", err);
  503. return err;
  504. }
  505. return 0;
  506. }
  507. int ldpaa_eth_init(struct dprc_obj_desc obj_desc)
  508. {
  509. struct eth_device *net_dev = NULL;
  510. struct ldpaa_eth_priv *priv = NULL;
  511. int err = 0;
  512. /* Net device */
  513. net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
  514. if (!net_dev) {
  515. printf("eth_device malloc() failed\n");
  516. return -ENOMEM;
  517. }
  518. memset(net_dev, 0, sizeof(struct eth_device));
  519. /* alloc the ldpaa ethernet private struct */
  520. priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
  521. if (!priv) {
  522. printf("ldpaa_eth_priv malloc() failed\n");
  523. return -ENOMEM;
  524. }
  525. memset(priv, 0, sizeof(struct ldpaa_eth_priv));
  526. net_dev->priv = (void *)priv;
  527. priv->net_dev = (struct eth_device *)net_dev;
  528. priv->dpni_id = obj_desc.id;
  529. err = ldpaa_eth_netdev_init(net_dev);
  530. if (err)
  531. goto err_netdev_init;
  532. debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
  533. return 0;
  534. err_netdev_init:
  535. free(priv);
  536. net_dev->priv = NULL;
  537. free(net_dev);
  538. return err;
  539. }