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