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

Commit fce24a9d authored by Dave Olson's avatar Dave Olson Committed by Roland Dreier
Browse files

IB/qib: Don't mark VL15 bufs as WC to avoid a rare 7322 chip problem



Don't set write combining via PAT on the VL15 buffers to avoid a rare
problem with unaligned writes from interrupt-flushed store buffers.

Signed-off-by: default avatarDave Olson <dave.olson@qlogic.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 67a3e12b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -686,6 +686,7 @@ struct qib_devdata {
	void __iomem *piobase;
	/* mem-mapped pointer to base of user chip regs (if using WC PAT) */
	u64 __iomem *userbase;
	void __iomem *piovl15base; /* base of VL15 buffers, if not WC */
	/*
	 * points to area where PIOavail registers will be DMA'ed.
	 * Has to be on a page of it's own, because the page will be
+15 −4
Original line number Diff line number Diff line
@@ -233,6 +233,7 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,
	u32 __iomem *krb32 = (u32 __iomem *)dd->kregbase;
	u32 __iomem *map = NULL;
	u32 cnt = 0;
	u32 tot4k, offs4k;

	/* First, simplest case, offset is within the first map. */
	kreglen = (dd->kregend - dd->kregbase) * sizeof(u64);
@@ -250,6 +251,7 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,
	if (dd->userbase) {
		/* If user regs mapped, they are after send, so set limit. */
		u32 ulim = (dd->cfgctxts * dd->ureg_align) + dd->uregbase;
		if (!dd->piovl15base)
			snd_lim = dd->uregbase;
		krb32 = (u32 __iomem *)dd->userbase;
		if (offset >= dd->uregbase && offset < ulim) {
@@ -277,14 +279,14 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,
	/* If 4k buffers exist, account for them by bumping
	 * appropriate limit.
	 */
	tot4k = dd->piobcnt4k * dd->align4k;
	offs4k = dd->piobufbase >> 32;
	if (dd->piobcnt4k) {
		u32 tot4k = dd->piobcnt4k * dd->align4k;
		u32 offs4k = dd->piobufbase >> 32;
		if (snd_bottom > offs4k)
			snd_bottom = offs4k;
		else {
			/* 4k above 2k. Bump snd_lim, if needed*/
			if (!dd->userbase)
			if (!dd->userbase || dd->piovl15base)
				snd_lim = offs4k + tot4k;
		}
	}
@@ -298,6 +300,15 @@ static u32 __iomem *qib_remap_ioaddr32(struct qib_devdata *dd, u32 offset,
		cnt = snd_lim - offset;
	}

	if (!map && offs4k && dd->piovl15base) {
		snd_lim = offs4k + tot4k + 2 * dd->align4k;
		if (offset >= (offs4k + tot4k) && offset < snd_lim) {
			map = (u32 __iomem *)dd->piovl15base +
				((offset - (offs4k + tot4k)) / sizeof(u32));
			cnt = snd_lim - offset;
		}
	}

mapped:
	if (cntp)
		*cntp = cnt;
+17 −1
Original line number Diff line number Diff line
@@ -6119,9 +6119,25 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
	qib_set_ctxtcnt(dd);

	if (qib_wc_pat) {
		ret = init_chip_wc_pat(dd, NUM_VL15_BUFS * dd->align4k);
		resource_size_t vl15off;
		/*
		 * We do not set WC on the VL15 buffers to avoid
		 * a rare problem with unaligned writes from
		 * interrupt-flushed store buffers, so we need
		 * to map those separately here.  We can't solve
		 * this for the rarely used mtrr case.
		 */
		ret = init_chip_wc_pat(dd, 0);
		if (ret)
			goto bail;

		/* vl15 buffers start just after the 4k buffers */
		vl15off = dd->physaddr + (dd->piobufbase >> 32) +
			dd->piobcnt4k * dd->align4k;
		dd->piovl15base	= ioremap_nocache(vl15off,
						  NUM_VL15_BUFS * dd->align4k);
		if (!dd->piovl15base)
			goto bail;
	}
	qib_7322_set_baseaddrs(dd); /* set chip access pointers now */

+6 −0
Original line number Diff line number Diff line
@@ -1499,6 +1499,12 @@ bail:
	return -ENOMEM;
}

/*
 * Note: Changes to this routine should be mirrored
 * for the diagnostics routine qib_remap_ioaddr32().
 * There is also related code for VL15 buffers in qib_init_7322_variables().
 * The teardown code that unmaps is in qib_pcie_ddcleanup()
 */
int init_chip_wc_pat(struct qib_devdata *dd, u32 vl15buflen)
{
	u64 __iomem *qib_kregbase = NULL;
+2 −0
Original line number Diff line number Diff line
@@ -179,6 +179,8 @@ void qib_pcie_ddcleanup(struct qib_devdata *dd)
		iounmap(dd->piobase);
	if (dd->userbase)
		iounmap(dd->userbase);
	if (dd->piovl15base)
		iounmap(dd->piovl15base);

	pci_disable_device(dd->pcidev);
	pci_release_regions(dd->pcidev);
Loading