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