+ /* Enable scatter mode for LRO */
+ if (!eth_dev->data->scattered_rx)
+ rxmode->offloads |= DEV_RX_OFFLOAD_SCATTER;
+ }
+
+ /* Start queues */
+ if (qede_start_queues(eth_dev))
+ goto err;
+
+ if (IS_PF(edev))
+ qede_reset_queue_stats(qdev, true);
+
+ /* Newer SR-IOV PF driver expects RX/TX queues to be started before
+ * enabling RSS. Hence RSS configuration is deferred up to this point.
+ * Also, we would like to retain similar behavior in PF case, so we
+ * don't do PF/VF specific check here.
+ */
+ if (eth_dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_RSS)
+ if (qede_config_rss(eth_dev))
+ goto err;
+
+ /* Enable vport*/
+ if (qede_activate_vport(eth_dev, true))
+ goto err;
+
+ /* Bring-up the link */
+ qede_dev_set_link_state(eth_dev, true);
+
+ /* Update link status */
+ qede_link_update(eth_dev, 0);
+
+ /* Start/resume traffic */
+ qede_fastpath_start(edev);
+
+ /* Assign I/O handlers */
+ qede_assign_rxtx_handlers(eth_dev, false);
+
+ DP_INFO(edev, "Device started\n");
+
+ return 0;
+err:
+ DP_ERR(edev, "Device start fails\n");
+ return -1; /* common error code is < 0 */
+}
+
+static int qede_dev_stop(struct rte_eth_dev *eth_dev)
+{
+ struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
+ struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
+
+ PMD_INIT_FUNC_TRACE(edev);
+ eth_dev->data->dev_started = 0;
+
+ /* Bring the link down */
+ qede_dev_set_link_state(eth_dev, false);
+
+ /* Update link status */
+ qede_link_update(eth_dev, 0);
+
+ /* Replace I/O functions with dummy ones. It cannot
+ * be set to NULL because rte_eth_rx_burst() doesn't check for NULL.
+ */
+ qede_assign_rxtx_handlers(eth_dev, true);
+
+ /* Disable vport */
+ if (qede_activate_vport(eth_dev, false))
+ return 0;
+
+ if (qdev->enable_lro)
+ qede_enable_tpa(eth_dev, false);
+
+ /* Stop queues */
+ qede_stop_queues(eth_dev);
+
+ /* Disable traffic */
+ ecore_hw_stop_fastpath(edev); /* TBD - loop */
+
+ DP_INFO(edev, "Device is stopped\n");
+
+ return 0;
+}
+
+static const char * const valid_args[] = {
+ QEDE_NPAR_TX_SWITCHING,
+ QEDE_VF_TX_SWITCHING,
+ NULL,
+};
+
+static int qede_args_check(const char *key, const char *val, void *opaque)
+{
+ unsigned long tmp;
+ int ret = 0;
+ struct rte_eth_dev *eth_dev = opaque;
+ struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
+ struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
+
+ errno = 0;
+ tmp = strtoul(val, NULL, 0);
+ if (errno) {
+ DP_INFO(edev, "%s: \"%s\" is not a valid integer", key, val);
+ return errno;
+ }
+
+ if ((strcmp(QEDE_NPAR_TX_SWITCHING, key) == 0) ||
+ ((strcmp(QEDE_VF_TX_SWITCHING, key) == 0) && IS_VF(edev))) {
+ qdev->enable_tx_switching = !!tmp;
+ DP_INFO(edev, "Disabling %s tx-switching\n",
+ strcmp(QEDE_NPAR_TX_SWITCHING, key) ?
+ "VF" : "NPAR");
+ }
+
+ return ret;
+}
+
+static int qede_args(struct rte_eth_dev *eth_dev)
+{
+ struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(eth_dev->device);
+ struct rte_kvargs *kvlist;
+ struct rte_devargs *devargs;
+ int ret;
+ int i;
+
+ devargs = pci_dev->device.devargs;
+ if (!devargs)
+ return 0; /* return success */
+
+ kvlist = rte_kvargs_parse(devargs->args, valid_args);
+ if (kvlist == NULL)
+ return -EINVAL;
+
+ /* Process parameters. */
+ for (i = 0; (valid_args[i] != NULL); ++i) {
+ if (rte_kvargs_count(kvlist, valid_args[i])) {
+ ret = rte_kvargs_process(kvlist, valid_args[i],
+ qede_args_check, eth_dev);
+ if (ret != ECORE_SUCCESS) {
+ rte_kvargs_free(kvlist);
+ return ret;
+ }