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