static int cvm_oct_probe(struct platform_device *pdev) { int num_interfaces; int interface; int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE; int qos; struct device_node *pip; octeon_mdiobus_force_mod_depencency(); pip = pdev->dev.of_node; if (!pip) { pr_err("Error: No 'pip' in /aliases\n"); return -EINVAL; } cvm_oct_configure_common_hw(); cvmx_helper_initialize_packet_io_global(); /* Change the input group for all ports before input is enabled */ num_interfaces = cvmx_helper_get_number_of_interfaces(); for (interface = 0; interface < num_interfaces; interface++) { int num_ports = cvmx_helper_ports_on_interface(interface); int port; for (port = cvmx_helper_get_ipd_port(interface, 0); port < cvmx_helper_get_ipd_port(interface, num_ports); port++) { union cvmx_pip_prt_tagx pip_prt_tagx; pip_prt_tagx.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(port)); pip_prt_tagx.s.grp = pow_receive_group; cvmx_write_csr(CVMX_PIP_PRT_TAGX(port), pip_prt_tagx.u64); } } cvmx_helper_ipd_and_packet_input_enable(); memset(cvm_oct_device, 0, sizeof(cvm_oct_device)); /* * Initialize the FAU used for counting packet buffers that * need to be freed. */ cvmx_fau_atomic_write32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); /* Initialize the FAU used for counting tx SKBs that need to be freed */ cvmx_fau_atomic_write32(FAU_TOTAL_TX_TO_CLEAN, 0); if ((pow_send_group != -1)) { struct net_device *dev; pr_info("\tConfiguring device for POW only access\n"); dev = alloc_etherdev(sizeof(struct octeon_ethernet)); if (dev) { /* Initialize the device private structure. */ struct octeon_ethernet *priv = netdev_priv(dev); dev->netdev_ops = &cvm_oct_pow_netdev_ops; priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED; priv->port = CVMX_PIP_NUM_INPUT_PORTS; priv->queue = -1; strcpy(dev->name, "pow%d"); for (qos = 0; qos < 16; qos++) skb_queue_head_init(&priv->tx_free_list[qos]); if (register_netdev(dev) < 0) { pr_err("Failed to register ethernet device for POW\n"); free_netdev(dev); } else { cvm_oct_device[CVMX_PIP_NUM_INPUT_PORTS] = dev; pr_info("%s: POW send group %d, receive group %d\n", dev->name, pow_send_group, pow_receive_group); } } else { pr_err("Failed to allocate ethernet device for POW\n"); } } num_interfaces = cvmx_helper_get_number_of_interfaces(); for (interface = 0; interface < num_interfaces; interface++) { cvmx_helper_interface_mode_t imode = cvmx_helper_interface_get_mode(interface); int num_ports = cvmx_helper_ports_on_interface(interface); int port; int port_index; for (port_index = 0, port = cvmx_helper_get_ipd_port(interface, 0); port < cvmx_helper_get_ipd_port(interface, num_ports); port_index++, port++) { struct octeon_ethernet *priv; struct net_device *dev = alloc_etherdev(sizeof(struct octeon_ethernet)); if (!dev) { pr_err("Failed to allocate ethernet device for port %d\n", port); continue; } /* Initialize the device private structure. */ priv = netdev_priv(dev); priv->netdev = dev; priv->of_node = cvm_oct_node_for_port(pip, interface, port_index); INIT_DELAYED_WORK(&priv->port_periodic_work, cvm_oct_periodic_worker); priv->imode = imode; priv->port = port; priv->queue = cvmx_pko_get_base_queue(priv->port); priv->fau = fau - cvmx_pko_get_num_queues(port) * 4; for (qos = 0; qos < 16; qos++) skb_queue_head_init(&priv->tx_free_list[qos]); for (qos = 0; qos < cvmx_pko_get_num_queues(port); qos++) cvmx_fau_atomic_write32(priv->fau + qos * 4, 0); switch (priv->imode) { /* These types don't support ports to IPD/PKO */ case CVMX_HELPER_INTERFACE_MODE_DISABLED: case CVMX_HELPER_INTERFACE_MODE_PCIE: case CVMX_HELPER_INTERFACE_MODE_PICMG: break; case CVMX_HELPER_INTERFACE_MODE_NPI: dev->netdev_ops = &cvm_oct_npi_netdev_ops; strcpy(dev->name, "npi%d"); break; case CVMX_HELPER_INTERFACE_MODE_XAUI: dev->netdev_ops = &cvm_oct_xaui_netdev_ops; strcpy(dev->name, "xaui%d"); break; case CVMX_HELPER_INTERFACE_MODE_LOOP: dev->netdev_ops = &cvm_oct_npi_netdev_ops; strcpy(dev->name, "loop%d"); break; case CVMX_HELPER_INTERFACE_MODE_SGMII: dev->netdev_ops = &cvm_oct_sgmii_netdev_ops; strcpy(dev->name, "eth%d"); break; case CVMX_HELPER_INTERFACE_MODE_SPI: dev->netdev_ops = &cvm_oct_spi_netdev_ops; strcpy(dev->name, "spi%d"); break; case CVMX_HELPER_INTERFACE_MODE_RGMII: case CVMX_HELPER_INTERFACE_MODE_GMII: dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; strcpy(dev->name, "eth%d"); break; } if (!dev->netdev_ops) { free_netdev(dev); } else if (register_netdev(dev) < 0) { pr_err("Failed to register ethernet device for interface %d, port %d\n", interface, priv->port); free_netdev(dev); } else { cvm_oct_device[priv->port] = dev; fau -= cvmx_pko_get_num_queues(priv->port) * sizeof(u32); schedule_delayed_work(&priv->port_periodic_work, HZ); } } } cvm_oct_tx_initialize(); cvm_oct_rx_initialize(); /* * 150 uS: about 10 1500-byte packets at 1GE. */ cvm_oct_tx_poll_interval = 150 * (octeon_get_clock_rate() / 1000000); schedule_delayed_work(&cvm_oct_rx_refill_work, HZ); return 0; }
static int cvm_oct_probe(struct platform_device *pdev) { int num_interfaces; int interface; int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE; int qos; struct device_node *pip; int mtu_overhead = ETH_HLEN + ETH_FCS_LEN; #if IS_ENABLED(CONFIG_VLAN_8021Q) mtu_overhead += VLAN_HLEN; #endif octeon_mdiobus_force_mod_depencency(); pip = pdev->dev.of_node; if (!pip) { pr_err("Error: No 'pip' in /aliases\n"); return -EINVAL; } cvm_oct_configure_common_hw(); cvmx_helper_initialize_packet_io_global(); if (receive_group_order) { if (receive_group_order > 4) receive_group_order = 4; pow_receive_groups = (1 << (1 << receive_group_order)) - 1; } else { pow_receive_groups = BIT(pow_receive_group); } /* Change the input group for all ports before input is enabled */ num_interfaces = cvmx_helper_get_number_of_interfaces(); for (interface = 0; interface < num_interfaces; interface++) { int num_ports = cvmx_helper_ports_on_interface(interface); int port; for (port = cvmx_helper_get_ipd_port(interface, 0); port < cvmx_helper_get_ipd_port(interface, num_ports); port++) { union cvmx_pip_prt_tagx pip_prt_tagx; pip_prt_tagx.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(port)); if (receive_group_order) { int tag_mask; /* We support only 16 groups at the moment, so * always disable the two additional "hidden" * tag_mask bits on CN68XX. */ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) pip_prt_tagx.u64 |= 0x3ull << 44; tag_mask = ~((1 << receive_group_order) - 1); pip_prt_tagx.s.grptagbase = 0; pip_prt_tagx.s.grptagmask = tag_mask; pip_prt_tagx.s.grptag = 1; pip_prt_tagx.s.tag_mode = 0; pip_prt_tagx.s.inc_prt_flag = 1; pip_prt_tagx.s.ip6_dprt_flag = 1; pip_prt_tagx.s.ip4_dprt_flag = 1; pip_prt_tagx.s.ip6_sprt_flag = 1; pip_prt_tagx.s.ip4_sprt_flag = 1; pip_prt_tagx.s.ip6_dst_flag = 1; pip_prt_tagx.s.ip4_dst_flag = 1; pip_prt_tagx.s.ip6_src_flag = 1; pip_prt_tagx.s.ip4_src_flag = 1; pip_prt_tagx.s.grp = 0; } else { pip_prt_tagx.s.grptag = 0; pip_prt_tagx.s.grp = pow_receive_group; } cvmx_write_csr(CVMX_PIP_PRT_TAGX(port), pip_prt_tagx.u64); } } cvmx_helper_ipd_and_packet_input_enable(); memset(cvm_oct_device, 0, sizeof(cvm_oct_device)); /* * Initialize the FAU used for counting packet buffers that * need to be freed. */ cvmx_fau_atomic_write32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); /* Initialize the FAU used for counting tx SKBs that need to be freed */ cvmx_fau_atomic_write32(FAU_TOTAL_TX_TO_CLEAN, 0); if ((pow_send_group != -1)) { struct net_device *dev; dev = alloc_etherdev(sizeof(struct octeon_ethernet)); if (dev) { /* Initialize the device private structure. */ struct octeon_ethernet *priv = netdev_priv(dev); SET_NETDEV_DEV(dev, &pdev->dev); dev->netdev_ops = &cvm_oct_pow_netdev_ops; priv->imode = CVMX_HELPER_INTERFACE_MODE_DISABLED; priv->port = CVMX_PIP_NUM_INPUT_PORTS; priv->queue = -1; strcpy(dev->name, "pow%d"); for (qos = 0; qos < 16; qos++) skb_queue_head_init(&priv->tx_free_list[qos]); dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead; dev->max_mtu = OCTEON_MAX_MTU - mtu_overhead; if (register_netdev(dev) < 0) { pr_err("Failed to register ethernet device for POW\n"); free_netdev(dev); } else { cvm_oct_device[CVMX_PIP_NUM_INPUT_PORTS] = dev; pr_info("%s: POW send group %d, receive group %d\n", dev->name, pow_send_group, pow_receive_group); } } else { pr_err("Failed to allocate ethernet device for POW\n"); } } num_interfaces = cvmx_helper_get_number_of_interfaces(); for (interface = 0; interface < num_interfaces; interface++) { cvmx_helper_interface_mode_t imode = cvmx_helper_interface_get_mode(interface); int num_ports = cvmx_helper_ports_on_interface(interface); int port; int port_index; for (port_index = 0, port = cvmx_helper_get_ipd_port(interface, 0); port < cvmx_helper_get_ipd_port(interface, num_ports); port_index++, port++) { struct octeon_ethernet *priv; struct net_device *dev = alloc_etherdev(sizeof(struct octeon_ethernet)); if (!dev) { pr_err("Failed to allocate ethernet device for port %d\n", port); continue; } /* Initialize the device private structure. */ SET_NETDEV_DEV(dev, &pdev->dev); priv = netdev_priv(dev); priv->netdev = dev; priv->of_node = cvm_oct_node_for_port(pip, interface, port_index); INIT_DELAYED_WORK(&priv->port_periodic_work, cvm_oct_periodic_worker); priv->imode = imode; priv->port = port; priv->queue = cvmx_pko_get_base_queue(priv->port); priv->fau = fau - cvmx_pko_get_num_queues(port) * 4; for (qos = 0; qos < 16; qos++) skb_queue_head_init(&priv->tx_free_list[qos]); for (qos = 0; qos < cvmx_pko_get_num_queues(port); qos++) cvmx_fau_atomic_write32(priv->fau + qos * 4, 0); dev->min_mtu = VLAN_ETH_ZLEN - mtu_overhead; dev->max_mtu = OCTEON_MAX_MTU - mtu_overhead; switch (priv->imode) { /* These types don't support ports to IPD/PKO */ case CVMX_HELPER_INTERFACE_MODE_DISABLED: case CVMX_HELPER_INTERFACE_MODE_PCIE: case CVMX_HELPER_INTERFACE_MODE_PICMG: break; case CVMX_HELPER_INTERFACE_MODE_NPI: dev->netdev_ops = &cvm_oct_npi_netdev_ops; strcpy(dev->name, "npi%d"); break; case CVMX_HELPER_INTERFACE_MODE_XAUI: dev->netdev_ops = &cvm_oct_xaui_netdev_ops; strcpy(dev->name, "xaui%d"); break; case CVMX_HELPER_INTERFACE_MODE_LOOP: dev->netdev_ops = &cvm_oct_npi_netdev_ops; strcpy(dev->name, "loop%d"); break; case CVMX_HELPER_INTERFACE_MODE_SGMII: dev->netdev_ops = &cvm_oct_sgmii_netdev_ops; strcpy(dev->name, "eth%d"); break; case CVMX_HELPER_INTERFACE_MODE_SPI: dev->netdev_ops = &cvm_oct_spi_netdev_ops; strcpy(dev->name, "spi%d"); break; case CVMX_HELPER_INTERFACE_MODE_RGMII: case CVMX_HELPER_INTERFACE_MODE_GMII: dev->netdev_ops = &cvm_oct_rgmii_netdev_ops; strcpy(dev->name, "eth%d"); cvm_set_rgmii_delay(priv->of_node, interface, port_index); break; } if (!dev->netdev_ops) { free_netdev(dev); } else if (register_netdev(dev) < 0) { pr_err("Failed to register ethernet device for interface %d, port %d\n", interface, priv->port); free_netdev(dev); } else { cvm_oct_device[priv->port] = dev; fau -= cvmx_pko_get_num_queues(priv->port) * sizeof(u32); schedule_delayed_work(&priv->port_periodic_work, HZ); } } } cvm_oct_tx_initialize(); cvm_oct_rx_initialize(); /* * 150 uS: about 10 1500-byte packets at 1GE. */ cvm_oct_tx_poll_interval = 150 * (octeon_get_clock_rate() / 1000000); schedule_delayed_work(&cvm_oct_rx_refill_work, HZ); return 0; }