Commit bd433488 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/endpoint'

- Add pci_epc_function_is_valid() to avoid repeating common validation
  checks (Damien Le Moal)

- Skip attempts to allocate from endpoint controller memory window if the
  requested size is larger than the window (Damien Le Moal)

- Add and document pci_epc_mem_map() and pci_epc_mem_unmap() to handle
  controller-specific size and alignment constraints, and add test cases to
  the endpoint test driver (Damien Le Moal)

- Implement dwc pci_epc_ops.align_addr() so pci_epc_mem_map() can observe
  DWC-specific alignment requirements (Damien Le Moal)

- Synchronously cancel command handler work in endpoint test before
  cleaning up DMA and BARs (Damien Le Moal)

- Respect endpoint page size in dw_pcie_ep_align_addr() (Niklas Cassel)

- Use dw_pcie_ep_align_addr() in dw_pcie_ep_raise_msi_irq() and
  dw_pcie_ep_raise_msix_irq() instead of open coding the equivalent (Niklas
  Cassel)

- Remove superfluous 'return' from pci_epf_test_clean_dma_chan() (Wang
  Jiang)

- Avoid NULL dereference if Modem Host Interface Endpoint lacks 'mmio' DT
  property (Zhongqiu Han)

- Release PCI domain ID of Endpoint controller parent (not controller
  itself) and before unregistering the controller, to avoid use-after-free
  (Zijun Hu)

- Clear secondary (not primary) EPC in pci_epc_remove_epf() when removing
  the secondary controller associated with an NTB (Zijun Hu)

- Fix pci_epc_map map_size kerneldoc (Rick Wertenbroek)

* pci/endpoint:
  PCI: endpoint: Fix pci_epc_map map_size kerneldoc string
  PCI: endpoint: Clear secondary (not primary) EPC in pci_epc_remove_epf()
  PCI: endpoint: Fix PCI domain ID release in pci_epc_destroy()
  PCI: endpoint: epf-mhi: Avoid NULL dereference if DT lacks 'mmio'
  PCI: endpoint: Remove surplus return statement from pci_epf_test_clean_dma_chan()
  PCI: dwc: ep: Use align addr function for dw_pcie_ep_raise_{msi,msix}_irq()
  PCI: endpoint: test: Synchronously cancel command handler work
  PCI: dwc: endpoint: Implement the pci_epc_ops::align_addr() operation
  PCI: endpoint: test: Use pci_epc_mem_map/unmap()
  PCI: endpoint: Update documentation
  PCI: endpoint: Introduce pci_epc_mem_map()/unmap()
  PCI: endpoint: Improve pci_epc_mem_alloc_addr()
  PCI: endpoint: Introduce pci_epc_function_is_valid()
parents 06831418 28b6acd7
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -117,6 +117,35 @@ by the PCI endpoint function driver.
   The PCI endpoint function driver should use pci_epc_mem_free_addr() to
   free the memory space allocated using pci_epc_mem_alloc_addr().

* pci_epc_map_addr()

  A PCI endpoint function driver should use pci_epc_map_addr() to map to a RC
  PCI address the CPU address of local memory obtained with
  pci_epc_mem_alloc_addr().

* pci_epc_unmap_addr()

  A PCI endpoint function driver should use pci_epc_unmap_addr() to unmap the
  CPU address of local memory mapped to a RC address with pci_epc_map_addr().

* pci_epc_mem_map()

  A PCI endpoint controller may impose constraints on the RC PCI addresses that
  can be mapped. The function pci_epc_mem_map() allows endpoint function
  drivers to allocate and map controller memory while handling such
  constraints. This function will determine the size of the memory that must be
  allocated with pci_epc_mem_alloc_addr() for successfully mapping a RC PCI
  address range. This function will also indicate the size of the PCI address
  range that was actually mapped, which can be less than the requested size, as
  well as the offset into the allocated memory to use for accessing the mapped
  RC PCI address range.

* pci_epc_mem_unmap()

  A PCI endpoint function driver can use pci_epc_mem_unmap() to unmap and free
  controller memory that was allocated and mapped using pci_epc_mem_map().


Other EPC APIs
~~~~~~~~~~~~~~

+25 −10
Original line number Diff line number Diff line
@@ -268,6 +268,20 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
	return -EINVAL;
}

static u64 dw_pcie_ep_align_addr(struct pci_epc *epc, u64 pci_addr,
				 size_t *pci_size, size_t *offset)
{
	struct dw_pcie_ep *ep = epc_get_drvdata(epc);
	struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
	u64 mask = pci->region_align - 1;
	size_t ofst = pci_addr & mask;

	*pci_size = ALIGN(ofst + *pci_size, epc->mem->window.page_size);
	*offset = ofst;

	return pci_addr & ~mask;
}

static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
				  phys_addr_t addr)
{
@@ -444,6 +458,7 @@ static const struct pci_epc_ops epc_ops = {
	.write_header		= dw_pcie_ep_write_header,
	.set_bar		= dw_pcie_ep_set_bar,
	.clear_bar		= dw_pcie_ep_clear_bar,
	.align_addr		= dw_pcie_ep_align_addr,
	.map_addr		= dw_pcie_ep_map_addr,
	.unmap_addr		= dw_pcie_ep_unmap_addr,
	.set_msi		= dw_pcie_ep_set_msi,
@@ -488,7 +503,8 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
	u32 msg_addr_lower, msg_addr_upper, reg;
	struct dw_pcie_ep_func *ep_func;
	struct pci_epc *epc = ep->epc;
	unsigned int aligned_offset;
	size_t map_size = sizeof(u32);
	size_t offset;
	u16 msg_ctrl, msg_data;
	bool has_upper;
	u64 msg_addr;
@@ -516,14 +532,13 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
	}
	msg_addr = ((u64)msg_addr_upper) << 32 | msg_addr_lower;

	aligned_offset = msg_addr & (epc->mem->window.page_size - 1);
	msg_addr = ALIGN_DOWN(msg_addr, epc->mem->window.page_size);
	msg_addr = dw_pcie_ep_align_addr(epc, msg_addr, &map_size, &offset);
	ret = dw_pcie_ep_map_addr(epc, func_no, 0, ep->msi_mem_phys, msg_addr,
				  epc->mem->window.page_size);
				  map_size);
	if (ret)
		return ret;

	writel(msg_data | (interrupt_num - 1), ep->msi_mem + aligned_offset);
	writel(msg_data | (interrupt_num - 1), ep->msi_mem + offset);

	dw_pcie_ep_unmap_addr(epc, func_no, 0, ep->msi_mem_phys);

@@ -574,8 +589,9 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
	struct pci_epf_msix_tbl *msix_tbl;
	struct dw_pcie_ep_func *ep_func;
	struct pci_epc *epc = ep->epc;
	size_t map_size = sizeof(u32);
	size_t offset;
	u32 reg, msg_data, vec_ctrl;
	unsigned int aligned_offset;
	u32 tbl_offset;
	u64 msg_addr;
	int ret;
@@ -600,14 +616,13 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
		return -EPERM;
	}

	aligned_offset = msg_addr & (epc->mem->window.page_size - 1);
	msg_addr = ALIGN_DOWN(msg_addr, epc->mem->window.page_size);
	msg_addr = dw_pcie_ep_align_addr(epc, msg_addr, &map_size, &offset);
	ret = dw_pcie_ep_map_addr(epc, func_no, 0, ep->msi_mem_phys, msg_addr,
				  epc->mem->window.page_size);
				  map_size);
	if (ret)
		return ret;

	writel(msg_data, ep->msi_mem + aligned_offset);
	writel(msg_data, ep->msi_mem + offset);

	dw_pcie_ep_unmap_addr(epc, func_no, 0, ep->msi_mem_phys);

+6 −0
Original line number Diff line number Diff line
@@ -867,12 +867,18 @@ static int pci_epf_mhi_bind(struct pci_epf *epf)
{
	struct pci_epf_mhi *epf_mhi = epf_get_drvdata(epf);
	struct pci_epc *epc = epf->epc;
	struct device *dev = &epf->dev;
	struct platform_device *pdev = to_platform_device(epc->dev.parent);
	struct resource *res;
	int ret;

	/* Get MMIO base address from Endpoint controller */
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mmio");
	if (!res) {
		dev_err(dev, "Failed to get \"mmio\" resource\n");
		return -ENODEV;
	}

	epf_mhi->mmio_phys = res->start;
	epf_mhi->mmio_size = resource_size(res);

+195 −183
Original line number Diff line number Diff line
@@ -291,8 +291,6 @@ static void pci_epf_test_clean_dma_chan(struct pci_epf_test *epf_test)

	dma_release_channel(epf_test->dma_chan_rx);
	epf_test->dma_chan_rx = NULL;

	return;
}

static void pci_epf_test_print_rate(struct pci_epf_test *epf_test,
@@ -317,91 +315,92 @@ static void pci_epf_test_print_rate(struct pci_epf_test *epf_test,
static void pci_epf_test_copy(struct pci_epf_test *epf_test,
			      struct pci_epf_test_reg *reg)
{
	int ret;
	void __iomem *src_addr;
	void __iomem *dst_addr;
	phys_addr_t src_phys_addr;
	phys_addr_t dst_phys_addr;
	int ret = 0;
	struct timespec64 start, end;
	struct pci_epf *epf = epf_test->epf;
	struct device *dev = &epf->dev;
	struct pci_epc *epc = epf->epc;
	struct device *dev = &epf->dev;
	struct pci_epc_map src_map, dst_map;
	u64 src_addr = reg->src_addr;
	u64 dst_addr = reg->dst_addr;
	size_t copy_size = reg->size;
	ssize_t map_size = 0;
	void *copy_buf = NULL, *buf;

	src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size);
	if (!src_addr) {
		dev_err(dev, "Failed to allocate source address\n");
		reg->status = STATUS_SRC_ADDR_INVALID;
	if (reg->flags & FLAG_USE_DMA) {
		if (epf_test->dma_private) {
			dev_err(dev, "Cannot transfer data using DMA\n");
			ret = -EINVAL;
			goto set_status;
		}
	} else {
		copy_buf = kzalloc(copy_size, GFP_KERNEL);
		if (!copy_buf) {
			ret = -ENOMEM;
		goto err;
			goto set_status;
		}
		buf = copy_buf;
	}

	ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr,
			       reg->src_addr, reg->size);
	while (copy_size) {
		ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no,
				      src_addr, copy_size, &src_map);
		if (ret) {
			dev_err(dev, "Failed to map source address\n");
			reg->status = STATUS_SRC_ADDR_INVALID;
		goto err_src_addr;
	}

	dst_addr = pci_epc_mem_alloc_addr(epc, &dst_phys_addr, reg->size);
	if (!dst_addr) {
		dev_err(dev, "Failed to allocate destination address\n");
		reg->status = STATUS_DST_ADDR_INVALID;
		ret = -ENOMEM;
		goto err_src_map_addr;
			goto free_buf;
		}

	ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr,
			       reg->dst_addr, reg->size);
		ret = pci_epc_mem_map(epf->epc, epf->func_no, epf->vfunc_no,
					   dst_addr, copy_size, &dst_map);
		if (ret) {
			dev_err(dev, "Failed to map destination address\n");
			reg->status = STATUS_DST_ADDR_INVALID;
		goto err_dst_addr;
			pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no,
					  &src_map);
			goto free_buf;
		}

		map_size = min_t(size_t, dst_map.pci_size, src_map.pci_size);

		ktime_get_ts64(&start);
		if (reg->flags & FLAG_USE_DMA) {
		if (epf_test->dma_private) {
			dev_err(dev, "Cannot transfer data using DMA\n");
			ret = -EINVAL;
			goto err_map_addr;
		}

		ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr,
						 src_phys_addr, reg->size, 0,
						 DMA_MEM_TO_MEM);
		if (ret)
			ret = pci_epf_test_data_transfer(epf_test,
					dst_map.phys_addr, src_map.phys_addr,
					map_size, 0, DMA_MEM_TO_MEM);
			if (ret) {
				dev_err(dev, "Data transfer failed\n");
	} else {
		void *buf;

		buf = kzalloc(reg->size, GFP_KERNEL);
		if (!buf) {
			ret = -ENOMEM;
			goto err_map_addr;
				goto unmap;
			}

		memcpy_fromio(buf, src_addr, reg->size);
		memcpy_toio(dst_addr, buf, reg->size);
		kfree(buf);
		} else {
			memcpy_fromio(buf, src_map.virt_addr, map_size);
			memcpy_toio(dst_map.virt_addr, buf, map_size);
			buf += map_size;
		}
		ktime_get_ts64(&end);
	pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start, &end,
				reg->flags & FLAG_USE_DMA);

err_map_addr:
	pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr);
		copy_size -= map_size;
		src_addr += map_size;
		dst_addr += map_size;

err_dst_addr:
	pci_epc_mem_free_addr(epc, dst_phys_addr, dst_addr, reg->size);
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &dst_map);
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &src_map);
		map_size = 0;
	}

	pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start,
				&end, reg->flags & FLAG_USE_DMA);

err_src_map_addr:
	pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr);
unmap:
	if (map_size) {
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &dst_map);
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &src_map);
	}

err_src_addr:
	pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size);
free_buf:
	kfree(copy_buf);

err:
set_status:
	if (!ret)
		reg->status |= STATUS_COPY_SUCCESS;
	else
@@ -411,82 +410,89 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test,
static void pci_epf_test_read(struct pci_epf_test *epf_test,
			      struct pci_epf_test_reg *reg)
{
	int ret;
	void __iomem *src_addr;
	void *buf;
	int ret = 0;
	void *src_buf, *buf;
	u32 crc32;
	phys_addr_t phys_addr;
	struct pci_epc_map map;
	phys_addr_t dst_phys_addr;
	struct timespec64 start, end;
	struct pci_epf *epf = epf_test->epf;
	struct device *dev = &epf->dev;
	struct pci_epc *epc = epf->epc;
	struct device *dev = &epf->dev;
	struct device *dma_dev = epf->epc->dev.parent;
	u64 src_addr = reg->src_addr;
	size_t src_size = reg->size;
	ssize_t map_size = 0;

	src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
	if (!src_addr) {
		dev_err(dev, "Failed to allocate address\n");
		reg->status = STATUS_SRC_ADDR_INVALID;
	src_buf = kzalloc(src_size, GFP_KERNEL);
	if (!src_buf) {
		ret = -ENOMEM;
		goto err;
		goto set_status;
	}
	buf = src_buf;

	ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, phys_addr,
			       reg->src_addr, reg->size);
	while (src_size) {
		ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no,
					   src_addr, src_size, &map);
		if (ret) {
			dev_err(dev, "Failed to map address\n");
			reg->status = STATUS_SRC_ADDR_INVALID;
		goto err_addr;
	}

	buf = kzalloc(reg->size, GFP_KERNEL);
	if (!buf) {
		ret = -ENOMEM;
		goto err_map_addr;
			goto free_buf;
		}

		map_size = map.pci_size;
		if (reg->flags & FLAG_USE_DMA) {
		dst_phys_addr = dma_map_single(dma_dev, buf, reg->size,
			dst_phys_addr = dma_map_single(dma_dev, buf, map_size,
						       DMA_FROM_DEVICE);
			if (dma_mapping_error(dma_dev, dst_phys_addr)) {
			dev_err(dev, "Failed to map destination buffer addr\n");
				dev_err(dev,
					"Failed to map destination buffer addr\n");
				ret = -ENOMEM;
			goto err_dma_map;
				goto unmap;
			}

			ktime_get_ts64(&start);
		ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr,
						 phys_addr, reg->size,
						 reg->src_addr, DMA_DEV_TO_MEM);
			ret = pci_epf_test_data_transfer(epf_test,
					dst_phys_addr, map.phys_addr,
					map_size, src_addr, DMA_DEV_TO_MEM);
			if (ret)
				dev_err(dev, "Data transfer failed\n");
			ktime_get_ts64(&end);

		dma_unmap_single(dma_dev, dst_phys_addr, reg->size,
			dma_unmap_single(dma_dev, dst_phys_addr, map_size,
					 DMA_FROM_DEVICE);

			if (ret)
				goto unmap;
		} else {
			ktime_get_ts64(&start);
		memcpy_fromio(buf, src_addr, reg->size);
			memcpy_fromio(buf, map.virt_addr, map_size);
			ktime_get_ts64(&end);
		}

	pci_epf_test_print_rate(epf_test, "READ", reg->size, &start, &end,
				reg->flags & FLAG_USE_DMA);
		src_size -= map_size;
		src_addr += map_size;
		buf += map_size;

	crc32 = crc32_le(~0, buf, reg->size);
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);
		map_size = 0;
	}

	pci_epf_test_print_rate(epf_test, "READ", reg->size, &start,
				&end, reg->flags & FLAG_USE_DMA);

	crc32 = crc32_le(~0, src_buf, reg->size);
	if (crc32 != reg->checksum)
		ret = -EIO;

err_dma_map:
	kfree(buf);

err_map_addr:
	pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr);
unmap:
	if (map_size)
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);

err_addr:
	pci_epc_mem_free_addr(epc, phys_addr, src_addr, reg->size);
free_buf:
	kfree(src_buf);

err:
set_status:
	if (!ret)
		reg->status |= STATUS_READ_SUCCESS;
	else
@@ -496,71 +502,79 @@ static void pci_epf_test_read(struct pci_epf_test *epf_test,
static void pci_epf_test_write(struct pci_epf_test *epf_test,
			       struct pci_epf_test_reg *reg)
{
	int ret;
	void __iomem *dst_addr;
	void *buf;
	phys_addr_t phys_addr;
	int ret = 0;
	void *dst_buf, *buf;
	struct pci_epc_map map;
	phys_addr_t src_phys_addr;
	struct timespec64 start, end;
	struct pci_epf *epf = epf_test->epf;
	struct device *dev = &epf->dev;
	struct pci_epc *epc = epf->epc;
	struct device *dev = &epf->dev;
	struct device *dma_dev = epf->epc->dev.parent;
	u64 dst_addr = reg->dst_addr;
	size_t dst_size = reg->size;
	ssize_t map_size = 0;

	dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
	if (!dst_addr) {
		dev_err(dev, "Failed to allocate address\n");
		reg->status = STATUS_DST_ADDR_INVALID;
	dst_buf = kzalloc(dst_size, GFP_KERNEL);
	if (!dst_buf) {
		ret = -ENOMEM;
		goto err;
		goto set_status;
	}
	get_random_bytes(dst_buf, dst_size);
	reg->checksum = crc32_le(~0, dst_buf, dst_size);
	buf = dst_buf;

	ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, phys_addr,
			       reg->dst_addr, reg->size);
	while (dst_size) {
		ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no,
					   dst_addr, dst_size, &map);
		if (ret) {
			dev_err(dev, "Failed to map address\n");
			reg->status = STATUS_DST_ADDR_INVALID;
		goto err_addr;
			goto free_buf;
		}

	buf = kzalloc(reg->size, GFP_KERNEL);
	if (!buf) {
		ret = -ENOMEM;
		goto err_map_addr;
	}

	get_random_bytes(buf, reg->size);
	reg->checksum = crc32_le(~0, buf, reg->size);

		map_size = map.pci_size;
		if (reg->flags & FLAG_USE_DMA) {
		src_phys_addr = dma_map_single(dma_dev, buf, reg->size,
			src_phys_addr = dma_map_single(dma_dev, buf, map_size,
						       DMA_TO_DEVICE);
			if (dma_mapping_error(dma_dev, src_phys_addr)) {
			dev_err(dev, "Failed to map source buffer addr\n");
				dev_err(dev,
					"Failed to map source buffer addr\n");
				ret = -ENOMEM;
			goto err_dma_map;
				goto unmap;
			}

			ktime_get_ts64(&start);

		ret = pci_epf_test_data_transfer(epf_test, phys_addr,
						 src_phys_addr, reg->size,
						 reg->dst_addr,
			ret = pci_epf_test_data_transfer(epf_test,
						map.phys_addr, src_phys_addr,
						map_size, dst_addr,
						DMA_MEM_TO_DEV);
			if (ret)
				dev_err(dev, "Data transfer failed\n");
			ktime_get_ts64(&end);

		dma_unmap_single(dma_dev, src_phys_addr, reg->size,
			dma_unmap_single(dma_dev, src_phys_addr, map_size,
					 DMA_TO_DEVICE);

			if (ret)
				goto unmap;
		} else {
			ktime_get_ts64(&start);
		memcpy_toio(dst_addr, buf, reg->size);
			memcpy_toio(map.virt_addr, buf, map_size);
			ktime_get_ts64(&end);
		}

	pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start, &end,
				reg->flags & FLAG_USE_DMA);
		dst_size -= map_size;
		dst_addr += map_size;
		buf += map_size;

		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);
		map_size = 0;
	}

	pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start,
				&end, reg->flags & FLAG_USE_DMA);

	/*
	 * wait 1ms inorder for the write to complete. Without this delay L3
@@ -568,16 +582,14 @@ static void pci_epf_test_write(struct pci_epf_test *epf_test,
	 */
	usleep_range(1000, 2000);

err_dma_map:
	kfree(buf);

err_map_addr:
	pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr);
unmap:
	if (map_size)
		pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map);

err_addr:
	pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size);
free_buf:
	kfree(dst_buf);

err:
set_status:
	if (!ret)
		reg->status |= STATUS_WRITE_SUCCESS;
	else
@@ -786,7 +798,7 @@ static void pci_epf_test_epc_deinit(struct pci_epf *epf)
{
	struct pci_epf_test *epf_test = epf_get_drvdata(epf);

	cancel_delayed_work(&epf_test->cmd_handler);
	cancel_delayed_work_sync(&epf_test->cmd_handler);
	pci_epf_test_clean_dma_chan(epf_test);
	pci_epf_test_clear_bar(epf);
}
@@ -917,7 +929,7 @@ static void pci_epf_test_unbind(struct pci_epf *epf)
	struct pci_epf_test *epf_test = epf_get_drvdata(epf);
	struct pci_epc *epc = epf->epc;

	cancel_delayed_work(&epf_test->cmd_handler);
	cancel_delayed_work_sync(&epf_test->cmd_handler);
	if (epc->init_complete) {
		pci_epf_test_clean_dma_chan(epf_test);
		pci_epf_test_clear_bar(epf);
+139 −54

File changed.

Preview size limit exceeded, changes collapsed.

Loading