Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0a8ba67 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa: IPA offload subsystem for ethernet devices"

parents d76a38c4 48503e34
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -143,4 +143,32 @@ config R8125
	  To compile this driver as a module, choose M here: the module
	  will be called r8125.

config IPA_ETH
	bool "IPA Ethernet Offload Sub-system support"
	depends on IPA3
	help
	  Enables IPA Ethernet Offload Subsystem for offloading PCI based
	  ethernet devices to IPA. The offload subsystem still require a
	  compatible network driver to register with it and a corresponding
	  offload driver to manage one of more offload data paths that uses
	  the network device.

config IPA_ETH_NOAUTO
	bool "Disable automatic offload initialization of interfaces"
	depends on IPA_ETH
	help
	  Enabling this option prevents automatic initialization of offload on
	  ethernet interfaces. Debugfs control interface will instead be used
	  to enable offloading. This feature is meant only for debugging.
	  If unsure, say N.

config IPA_ETH_DEBUG
	bool "Enable addtional debug logging in the offload sub-system"
	depends on IPA_ETH
	help
	  Enabling this option increases the number of messages logged by the offload
	  sub-system for aiding debugging. Additional debug messages are logged into
	  IPC log as well as kernel log using dynamic debug.
	  If unsure, say N.

endmenu
+1 −0
Original line number Diff line number Diff line
@@ -13,3 +13,4 @@ obj-$(CONFIG_SPS) += sps/
obj-$(CONFIG_MSM_11AD) += msm_11ad/
obj-$(CONFIG_EP_PCIE) += ep_pcie/
obj-$(CONFIG_MSM_MHI_DEV) += mhi_dev/
obj-$(CONFIG_IPA_ETH) += ethernet/
+21 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only

#
# Makefile for the MSM specific device drivers.
#

obj-$(CONFIG_IPA_ETH) += ipa-eth.o

ipa-eth-y := \
	ipa_eth_bus.o \
	ipa_eth.o \
	ipa_eth_debugfs.o \
	ipa_eth_ep.o \
	ipa_eth_gsi.o \
	ipa_eth_net.o \
	ipa_eth_offload.o \
	ipa_eth_pci.o \
	ipa_eth_pm.o \
	ipa_eth_trace.o \
	ipa_eth_uc.o \
	ipa_eth_utils.o
+1135 −0

File added.

Preview size limit exceeded, changes collapsed.

+136 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved
 */

#include <linux/pci.h>

#include "ipa_eth_i.h"

static bool ipa_eth_bus_is_ready;

struct ipa_eth_bus_map {
	struct bus_type *bus;
	struct ipa_eth_bus *eth_bus;
	int (*modinit)(void);
	void (*modexit)(void);
} static const bus_map[] = {
	{
		&pci_bus_type,
		&ipa_eth_pci_bus,
		&ipa_eth_pci_modinit,
		&ipa_eth_pci_modexit
	},
	{},
};

static struct ipa_eth_bus *lookup_eth_bus(struct bus_type *bus)
{
	const struct ipa_eth_bus_map *map;

	for (map = bus_map; map->bus != NULL; map++) {
		if (map->bus == bus)
			return map->eth_bus;
	}

	return NULL;
}

int ipa_eth_bus_register_driver(struct ipa_eth_net_driver *nd)
{
	struct ipa_eth_bus *eth_bus;

	eth_bus = lookup_eth_bus(nd->bus);
	if (!eth_bus) {
		ipa_eth_err("Unsupported bus %s", nd->bus->name);
		return -EOPNOTSUPP;
	}

	return eth_bus->register_driver(nd);
}

void ipa_eth_bus_unregister_driver(struct ipa_eth_net_driver *nd)
{
	struct ipa_eth_bus *eth_bus = lookup_eth_bus(nd->bus);

	if (!eth_bus) {
		ipa_eth_bug("Failed to lookup eth_bus for %s", nd->bus->name);
		return;
	}

	eth_bus->unregister_driver(nd);
}

int ipa_eth_bus_enable_pc(struct ipa_eth_device *eth_dev)
{
	struct ipa_eth_net_driver *nd = eth_dev->nd;
	struct ipa_eth_bus *eth_bus = lookup_eth_bus(nd->bus);

	if (!eth_bus) {
		ipa_eth_dev_bug(eth_dev, "Failed to lookup eth_bus");
		return -EFAULT;
	}

	if (eth_bus->enable_pc)
		return eth_bus->enable_pc(eth_dev);

	return -EFAULT;
}

int ipa_eth_bus_disable_pc(struct ipa_eth_device *eth_dev)
{
	struct ipa_eth_net_driver *nd = eth_dev->nd;
	struct ipa_eth_bus *eth_bus = lookup_eth_bus(nd->bus);

	if (!eth_bus) {
		ipa_eth_dev_bug(eth_dev, "Failed to lookup eth_bus");
		return -EFAULT;
	}

	if (eth_bus->disable_pc)
		return eth_bus->disable_pc(eth_dev);

	return -EFAULT;
}

int ipa_eth_bus_modinit(void)
{
	int rc;
	const struct ipa_eth_bus_map *map;

	/* initialize all registered busses */
	for (rc = 0, map = bus_map; map->bus != NULL; map++)
		rc |= map->modinit();

	if (rc) {
		ipa_eth_err("Failed to initialize one or more busses");
		goto err_init;
	}

	ipa_eth_bus_is_ready = true;

	ipa_eth_log("Offload sub-system bus module init is complete");

	return 0;

err_init:
	for (map = bus_map; map->bus != NULL; map++)
		map->modexit();

	return rc;
}

void ipa_eth_bus_modexit(void)
{
	const struct ipa_eth_bus_map *map;

	ipa_eth_log("De-initing offload sub-system bus module");

	if (!ipa_eth_bus_is_ready)
		return;

	ipa_eth_bus_is_ready = false;

	for (map = bus_map; map->bus != NULL; map++)
		map->modexit();
}
Loading