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

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

Merge "net: aquantia: Forward device events to IPA offload sub-system"

parents 8618352b 4061269e
Loading
Loading
Loading
Loading
+73 −16
Original line number Diff line number Diff line
@@ -21,17 +21,25 @@
#include "atl_fwd.h"
#include "atl_qcom_ipa.h"

#if ATL_FWD_API_VERSION >= 2 && IPA_ETH_API_VER >= 4
#define ATL_IPA_SUPPORT_NOTIFY
#endif

struct atl_ipa_device {
	struct atl_nic *atl_nic;
	struct ipa_eth_device *eth_dev;
	struct notifier_block fwd_notify_nb;
};

static inline struct atl_fwd_ring *CH_RING(struct ipa_eth_channel *ch)
{
	return (struct atl_fwd_ring *)(ch->nd_priv);
}

static void *atl_ipa_dma_alloc(struct device *dev, size_t size,
			       dma_addr_t *daddr, gfp_t gfp,
static void *atl_ipa_dma_alloc(struct ipa_eth_device *eth_dev,
			       size_t size, dma_addr_t *daddr, gfp_t gfp,
			       struct ipa_eth_dma_allocator *dma_allocator)
{
	struct atl_nic *nic = (struct atl_nic *)dev_get_drvdata(dev);
	struct ipa_eth_device *eth_dev = nic->fwd.private;
	struct ipa_eth_resource mem;

	if (dma_allocator->alloc(eth_dev, size, gfp, &mem))
@@ -43,12 +51,10 @@ static void *atl_ipa_dma_alloc(struct device *dev, size_t size,
	return mem.vaddr;
}

static void atl_ipa_dma_free(void *buf, struct device *dev, size_t size,
			     dma_addr_t daddr,
static void atl_ipa_dma_free(void *buf, struct ipa_eth_device *eth_dev,
			     size_t size, dma_addr_t daddr,
			     struct ipa_eth_dma_allocator *dma_allocator)
{
	struct atl_nic *nic = (struct atl_nic *)dev_get_drvdata(dev);
	struct ipa_eth_device *eth_dev = nic->fwd.private;
	struct ipa_eth_resource mem = {
		.size = size,
		.vaddr = buf,
@@ -64,7 +70,7 @@ static void *atl_ipa_alloc_descs(struct device *dev, size_t size,
{
	struct ipa_eth_channel *ch = ops->private;

	return atl_ipa_dma_alloc(dev, size, daddr, gfp,
	return atl_ipa_dma_alloc(ch->eth_dev, size, daddr, gfp,
			ch->mem_params.desc.allocator);
}

@@ -74,7 +80,7 @@ static void *atl_ipa_alloc_buf(struct device *dev, size_t size,
{
	struct ipa_eth_channel *ch = ops->private;

	return atl_ipa_dma_alloc(dev, size, daddr, gfp,
	return atl_ipa_dma_alloc(ch->eth_dev, size, daddr, gfp,
			ch->mem_params.buff.allocator);
}

@@ -83,7 +89,7 @@ static void atl_ipa_free_descs(void *buf, struct device *dev, size_t size,
{
	struct ipa_eth_channel *ch = ops->private;

	return atl_ipa_dma_free(buf, dev, size, daddr,
	return atl_ipa_dma_free(buf, ch->eth_dev, size, daddr,
			ch->mem_params.desc.allocator);
}

@@ -92,12 +98,38 @@ static void atl_ipa_free_buf(void *buf, struct device *dev, size_t size,
{
	struct ipa_eth_channel *ch = ops->private;

	return atl_ipa_dma_free(buf, dev, size, daddr,
	return atl_ipa_dma_free(buf, ch->eth_dev, size, daddr,
			ch->mem_params.desc.allocator);
}

#ifdef ATL_IPA_SUPPORT_NOTIFY
static int atl_ipa_fwd_notification(struct notifier_block *nb,
				    unsigned long action, void *data)
{
	enum atl_fwd_notify notif = action;
	struct atl_ipa_device *ai_dev = container_of(
		nb, struct atl_ipa_device, fwd_notify_nb);

	switch (notif) {
	case ATL_FWD_NOTIFY_RESET_PREPARE:
		ipa_eth_device_notify(ai_dev->eth_dev,
				      IPA_ETH_DEV_RESET_PREPARE, NULL);
		break;
	case ATL_FWD_NOTIFY_RESET_COMPLETE:
		ipa_eth_device_notify(ai_dev->eth_dev,
				      IPA_ETH_DEV_RESET_COMPLETE, NULL);
		break;
	default:
		return NOTIFY_DONE;
	}

	return NOTIFY_OK;
}
#endif

static int atl_ipa_open_device(struct ipa_eth_device *eth_dev)
{
	struct atl_ipa_device *ai_dev;
	struct atl_nic *nic = (struct atl_nic *)dev_get_drvdata(eth_dev->dev);

	if (!nic || !nic->ndev) {
@@ -105,24 +137,49 @@ static int atl_ipa_open_device(struct ipa_eth_device *eth_dev)
		return -ENODEV;
	}

	nic->fwd.private = eth_dev;
	ai_dev = kzalloc(sizeof(*ai_dev), GFP_KERNEL);
	if (!ai_dev)
		return -ENOMEM;

	/* atl specific init, ref counting go here */

	eth_dev->nd_priv = nic;
	ai_dev->atl_nic = nic;
	ai_dev->eth_dev = eth_dev;

	eth_dev->nd_priv = ai_dev;
	eth_dev->net_dev = nic->ndev;

#ifdef ATL_IPA_SUPPORT_NOTIFY
	ai_dev->fwd_notify_nb.notifier_call = atl_ipa_fwd_notification;

	if (atl_fwd_register_notifier(nic->ndev, &ai_dev->fwd_notify_nb)) {
		dev_err(eth_dev->dev, "Failed to register notifier\n");

		eth_dev->nd_priv = NULL;
		eth_dev->net_dev = NULL;
		kfree(ai_dev);

		return -EFAULT;
	}
#endif

	return 0;
}

static void atl_ipa_close_device(struct ipa_eth_device *eth_dev)
{
	struct atl_nic *nic = eth_dev->nd_priv;
	struct atl_ipa_device *ai_dev = eth_dev->nd_priv;

	nic->fwd.private = NULL;
#ifdef ATL_IPA_SUPPORT_NOTIFY
	atl_fwd_unregister_notifier(ai_dev->atl_nic->ndev,
				    &ai_dev->fwd_notify_nb);
#endif

	eth_dev->nd_priv = NULL;
	eth_dev->net_dev = NULL;

	memset(ai_dev, 0, sizeof(ai_dev));
	kfree(ai_dev);
}

static struct ipa_eth_channel *atl_ipa_request_channel(