+ ib-ipath-fix-a-bug-that-results-in-addresses-near.patch added to -mm tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The patch titled

     IB/ipath: fix a bug that results in addresses near 0 being written via DMA

has been added to the -mm tree.  Its filename is

     ib-ipath-fix-a-bug-that-results-in-addresses-near.patch

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

------------------------------------------------------
Subject: IB/ipath: fix a bug that results in addresses near 0 being written via DMA
From: "Bryan O'Sullivan" <bos@xxxxxxxxxxxxx>

We can't tell for sure if any packets are in the infinipath receive buffer
when we shut down a chip port.  Normally this is taken care of by orderly
shutdown, but when processes are terminated, or sending process has a bug, we
can continue to receive packets.  So rather than writing zero to the address
registers for the closing port, we point it at a dummy memory.

Signed-off-by: Dave Olson <dave.olson@xxxxxxxxxx>
Signed-off-by: Bryan O'Sullivan <bryan.osullivan@xxxxxxxxxx>
Cc: "Michael S. Tsirkin" <mst@xxxxxxxxxxxxxx>
Cc: Roland Dreier <rolandd@xxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
---

 drivers/infiniband/hw/ipath/ipath_driver.c    |    6 +
 drivers/infiniband/hw/ipath/ipath_file_ops.c  |   63 +++++++++-------
 drivers/infiniband/hw/ipath/ipath_init_chip.c |   17 ++++
 drivers/infiniband/hw/ipath/ipath_kernel.h    |    2 
 4 files changed, 61 insertions(+), 27 deletions(-)

diff -puN drivers/infiniband/hw/ipath/ipath_driver.c~ib-ipath-fix-a-bug-that-results-in-addresses-near drivers/infiniband/hw/ipath/ipath_driver.c
--- a/drivers/infiniband/hw/ipath/ipath_driver.c~ib-ipath-fix-a-bug-that-results-in-addresses-near
+++ a/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -1824,6 +1824,12 @@ static void cleanup_device(struct ipath_
 				  dd->ipath_pioavailregs_phys);
 		dd->ipath_pioavailregs_dma = NULL;
 	}
+	if (dd->ipath_dummy_hdrq) {
+		dma_free_coherent(&dd->pcidev->dev,
+			dd->ipath_pd[0]->port_rcvhdrq_size,
+			dd->ipath_dummy_hdrq, dd->ipath_dummy_hdrq_phys);
+		dd->ipath_dummy_hdrq = NULL;
+	}
 
 	if (dd->ipath_pageshadow) {
 		struct page **tmpp = dd->ipath_pageshadow;
diff -puN drivers/infiniband/hw/ipath/ipath_file_ops.c~ib-ipath-fix-a-bug-that-results-in-addresses-near drivers/infiniband/hw/ipath/ipath_file_ops.c
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c~ib-ipath-fix-a-bug-that-results-in-addresses-near
+++ a/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -1486,42 +1486,51 @@ static int ipath_close(struct inode *in,
 	}
 
 	if (dd->ipath_kregbase) {
-		ipath_write_kreg_port(
-			dd, dd->ipath_kregs->kr_rcvhdrtailaddr,
-			port, 0ULL);
-		ipath_write_kreg_port(
-			dd, dd->ipath_kregs->kr_rcvhdraddr,
-			pd->port_port, 0);
+		int i;
+		/* atomically clear receive enable port. */
+		clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + port,
+			  &dd->ipath_rcvctrl);
+		ipath_write_kreg( dd, dd->ipath_kregs->kr_rcvctrl,
+			dd->ipath_rcvctrl);
+		/* and read back from chip to be sure that nothing
+		 * else is in flight when we do the rest */
+		(void)ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
 
 		/* clean up the pkeys for this port user */
 		ipath_clean_part_key(pd, dd);
 
-		if (port < dd->ipath_cfgports) {
-			int i = dd->ipath_pbufsport * (port - 1);
-			ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
-
-			/* atomically clear receive enable port. */
-			clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + port,
-				  &dd->ipath_rcvctrl);
-			ipath_write_kreg(
-				dd,
-				dd->ipath_kregs->kr_rcvctrl,
-				dd->ipath_rcvctrl);
-
-			if (dd->ipath_pageshadow)
-				unlock_expected_tids(pd);
-			ipath_stats.sps_ports--;
-			ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n",
-				   pd->port_comm, pd->port_pid,
-				   dd->ipath_unit, port);
-		}
+
+		/*
+		 * be paranoid, and never write 0's to these, just use an
+		 * unused part of the port 0 tail page.  Of course,
+		 * rcvhdraddr points to a large chunk of memory, so this
+		 * could still trash things, but at least it won't trash
+		 * page 0, and by disabling the port, it should stop "soon",
+		 * even if a packet or two is in already in flight after we
+		 * disabled the port.
+		 */
+		ipath_write_kreg_port(dd,
+		        dd->ipath_kregs->kr_rcvhdrtailaddr, port,
+			dd->ipath_dummy_hdrq_phys);
+		ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr,
+			pd->port_port, dd->ipath_dummy_hdrq_phys);
+
+		i = dd->ipath_pbufsport * (port - 1);
+		ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
+
+		if (dd->ipath_pageshadow)
+			unlock_expected_tids(pd);
+		ipath_stats.sps_ports--;
+		ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n",
+			   pd->port_comm, pd->port_pid,
+			   dd->ipath_unit, port);
+
+		dd->ipath_f_clear_tids(dd, pd->port_port);
 	}
 
 	pd->port_cnt = 0;
 	pd->port_pid = 0;
 
-	dd->ipath_f_clear_tids(dd, pd->port_port);
-
 	dd->ipath_pd[pd->port_port] = NULL; /* before releasing mutex */
 	mutex_unlock(&ipath_mutex);
 	ipath_free_pddata(dd, pd); /* after releasing the mutex */
diff -puN drivers/infiniband/hw/ipath/ipath_init_chip.c~ib-ipath-fix-a-bug-that-results-in-addresses-near drivers/infiniband/hw/ipath/ipath_init_chip.c
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c~ib-ipath-fix-a-bug-that-results-in-addresses-near
+++ a/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -647,6 +647,7 @@ int ipath_init_chip(struct ipath_devdata
 	u32 val32, kpiobufs;
 	u64 val;
 	struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
+	gfp_t gfp_flags = GFP_USER | __GFP_COMP;
 
 	ret = init_housekeeping(dd, &pd, reinit);
 	if (ret)
@@ -834,6 +835,22 @@ int ipath_init_chip(struct ipath_devdata
 	else
 		enable_chip(dd, pd, reinit);
 
+
+	if (!ret && !reinit) {
+	    /* used when we close a port, for DMA already in flight at close */
+		dd->ipath_dummy_hdrq = dma_alloc_coherent(
+			&dd->pcidev->dev, pd->port_rcvhdrq_size,
+			&dd->ipath_dummy_hdrq_phys,
+			gfp_flags);
+		if (!dd->ipath_dummy_hdrq ) {
+			dev_info(&dd->pcidev->dev,
+				"Couldn't allocate 0x%lx bytes for dummy hdrq\n",
+				pd->port_rcvhdrq_size);
+			/* fallback to just 0'ing */
+			dd->ipath_dummy_hdrq_phys = 0UL;
+		}
+	}
+
 	/*
 	 * cause retrigger of pending interrupts ignored during init,
 	 * even if we had errors
diff -puN drivers/infiniband/hw/ipath/ipath_kernel.h~ib-ipath-fix-a-bug-that-results-in-addresses-near drivers/infiniband/hw/ipath/ipath_kernel.h
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h~ib-ipath-fix-a-bug-that-results-in-addresses-near
+++ a/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -352,6 +352,8 @@ struct ipath_devdata {
 	/* check for stale messages in rcv queue */
 	/* only allow one intr at a time. */
 	unsigned long ipath_rcv_pending;
+	void *ipath_dummy_hdrq;	/* used after port close */
+	dma_addr_t ipath_dummy_hdrq_phys;
 
 	/*
 	 * Shadow copies of registers; size indicates read access size.
_

Patches currently in -mm which might be from bos@xxxxxxxxxxxxx are

ib-ipath-name-zero-counter-offsets-so-its-clear.patch
ib-ipath-update-copyrights-and-other-strings-to.patch
ib-ipath-share-more-common-code-between-rc-and-uc.patch
ib-ipath-fix-an-indenting-problem.patch
ib-ipath-fix-shared-receive-queues-for-rc.patch
ib-ipath-allow-diags-on-any-unit.patch
ib-ipath-update-some-comments-and-fix-typos.patch
ib-ipath-remove-some-duplicate-code.patch
ib-ipath-dont-allow-resources-to-be-created-with.patch
ib-ipath-fix-some-memory-leaks-on-failure-paths.patch
ib-ipath-return-an-error-for-unknown-multicast-gid.patch
ib-ipath-report-correct-device-identification.patch
ib-ipath-enforce-device-resource-limits.patch
ib-ipath-removed-unused-field-ipath_kregvirt-from.patch
ib-ipath-print-better-debug-info-when-handling.patch
ib-ipath-enable-freeze-mode-when-shutting-down.patch
ib-ipath-use-more-appropriate-gfp-flags.patch
ib-ipath-use-vmalloc-to-allocate-struct.patch
ib-ipath-memory-management-cleanups.patch
ib-ipath-reduce-overhead-on-receive-interrupts.patch
ib-ipath-fixed-bug-9776.patch
ib-ipath-fix-lost-interrupts-on-ht-400.patch
ib-ipath-disallow-send-of-invalid-packet-sizes.patch
ib-ipath-dont-confuse-the-max-message-size-with.patch
ib-ipath-removed-redundant-statements.patch
ib-ipath-check-for-valid-lid-and-multicast-lids.patch
ib-ipath-fixes-to-performance-get-counters-for-ib.patch
ib-ipath-fixes-a-bug-where-our-delay-for-eeprom-no.patch
ib-ipath-rc-receive-interrupt-performance-changes.patch
ib-ipath-purge-sps_lid-and-sps_mlid-arrays.patch
ib-ipath-drop-the-stats-sysfs-attribute-group.patch
ib-ipath-support-more-models-of-infinipath-hardware.patch
ib-ipath-read-write-correct-sizes-through-diag.patch
ib-ipath-fix-a-bug-that-results-in-addresses-near.patch
ib-ipath-remove-some-if-0-code-related-to.patch
ib-ipath-ignore-receive-queue-size-if-srq-is.patch
ib-ipath-namespace-cleanup-replace-ips-with-ipath.patch

-
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel Newbies FAQ]     [Kernel Archive]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Photo]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux