1/* 2 * Copyright (c) 2012 Intel Corporation. All rights reserved. 3 * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. 4 * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 */ 34 35/* 36 * This file is conditionally built on x86_64 only. Otherwise weak symbol 37 * versions of the functions exported from here are used. 38 */ 39 40#include <linux/pci.h> 41#include <asm/mtrr.h> 42#include <asm/processor.h> 43 44#include "qib.h" 45 46/** 47 * qib_enable_wc - enable write combining for MMIO writes to the device 48 * @dd: qlogic_ib device 49 * 50 * This routine is x86_64-specific; it twiddles the CPU's MTRRs to enable 51 * write combining. 52 */ 53int qib_enable_wc(struct qib_devdata *dd) 54{ 55 int ret = 0; 56 u64 pioaddr, piolen; 57 unsigned bits; 58 const unsigned long addr = pci_resource_start(dd->pcidev, 0); 59 const size_t len = pci_resource_len(dd->pcidev, 0); 60 61 /* 62 * Set the PIO buffers to be WCCOMB, so we get HT bursts to the 63 * chip. Linux (possibly the hardware) requires it to be on a power 64 * of 2 address matching the length (which has to be a power of 2). 65 * For rev1, that means the base address, for rev2, it will be just 66 * the PIO buffers themselves. 67 * For chips with two sets of buffers, the calculations are 68 * somewhat more complicated; we need to sum, and the piobufbase 69 * register has both offsets, 2K in low 32 bits, 4K in high 32 bits. 70 * The buffers are still packed, so a single range covers both. 71 */ 72 if (dd->piobcnt2k && dd->piobcnt4k) { 73 /* 2 sizes for chip */ 74 unsigned long pio2kbase, pio4kbase; 75 76 pio2kbase = dd->piobufbase & 0xffffffffUL; 77 pio4kbase = (dd->piobufbase >> 32) & 0xffffffffUL; 78 if (pio2kbase < pio4kbase) { 79 /* all current chips */ 80 pioaddr = addr + pio2kbase; 81 piolen = pio4kbase - pio2kbase + 82 dd->piobcnt4k * dd->align4k; 83 } else { 84 pioaddr = addr + pio4kbase; 85 piolen = pio2kbase - pio4kbase + 86 dd->piobcnt2k * dd->palign; 87 } 88 } else { /* single buffer size (2K, currently) */ 89 pioaddr = addr + dd->piobufbase; 90 piolen = dd->piobcnt2k * dd->palign + 91 dd->piobcnt4k * dd->align4k; 92 } 93 94 for (bits = 0; !(piolen & (1ULL << bits)); bits++) 95 ; /* do nothing */ 96 97 if (piolen != (1ULL << bits)) { 98 piolen >>= bits; 99 while (piolen >>= 1) 100 bits++; 101 piolen = 1ULL << (bits + 1); 102 } 103 if (pioaddr & (piolen - 1)) { 104 u64 atmp = pioaddr & ~(piolen - 1); 105 106 if (atmp < addr || (atmp + piolen) > (addr + len)) { 107 qib_dev_err(dd, 108 "No way to align address/size (%llx/%llx), no WC mtrr\n", 109 (unsigned long long) atmp, 110 (unsigned long long) piolen << 1); 111 ret = -ENODEV; 112 } else { 113 pioaddr = atmp; 114 piolen <<= 1; 115 } 116 } 117 118 if (!ret) { 119 dd->wc_cookie = arch_phys_wc_add(pioaddr, piolen); 120 if (dd->wc_cookie < 0) 121 /* use error from routine */ 122 ret = dd->wc_cookie; 123 } 124 125 return ret; 126} 127 128/** 129 * qib_disable_wc - disable write combining for MMIO writes to the device 130 * @dd: qlogic_ib device 131 */ 132void qib_disable_wc(struct qib_devdata *dd) 133{ 134 arch_phys_wc_del(dd->wc_cookie); 135} 136 137/** 138 * qib_unordered_wc - indicate whether write combining is ordered 139 * 140 * Because our performance depends on our ability to do write combining mmio 141 * writes in the most efficient way, we need to know if we are on an Intel 142 * or AMD x86_64 processor. AMD x86_64 processors flush WC buffers out in 143 * the order completed, and so no special flushing is required to get 144 * correct ordering. Intel processors, however, will flush write buffers 145 * out in "random" orders, and so explicit ordering is needed at times. 146 */ 147int qib_unordered_wc(void) 148{ 149 return boot_cpu_data.x86_vendor != X86_VENDOR_AMD; 150} 151