Commit a6c4e4cd authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 platform changes from Ingo Molnar:
 "The main changes in this cycle were:

   - SGI UV updates (Andrew Banman)

   - Intel MID updates (Andy Shevchenko)

   - Initial Mellanox systems platform (Vadim Pasternak)"

* 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/platform/mellanox: Fix return value check in mlxplat_init()
  x86/platform/mellanox: Introduce support for Mellanox systems platform
  x86/platform/uv/BAU: Add UV4-specific functions
  x86/platform/uv/BAU: Fix payload queue setup on UV4 hardware
  x86/platform/uv/BAU: Disable software timeout on UV4 hardware
  x86/platform/uv/BAU: Populate ->uvhub_version with UV4 version information
  x86/platform/uv/BAU: Use generic function pointers
  x86/platform/uv/BAU: Add generic function pointers
  x86/platform/uv/BAU: Convert uv_physnodeaddr() use to uv_gpa_to_offset()
  x86/platform/uv/BAU: Clean up pq_init()
  x86/platform/uv/BAU: Clean up and update printks
  x86/platform/uv/BAU: Clean up vertical alignment
  x86/platform/intel-mid: Keep SRAM powered on at boot
  x86/platform/intel-mid: Add Intel Penwell to ID table
  x86/cpu: Rename Merrifield2 to Moorefield
  x86/platform/intel-mid: Implement power off sequence
  x86/platform/intel-mid: Enable SD card detection on Merrifield
  x86/platform/intel-mid: Enable WiFi on Intel Edison
  x86/platform/intel-mid: Run PWRMU command immediately
parents a8adc0f0 65f74222
...@@ -7683,6 +7683,12 @@ W: http://www.mellanox.com ...@@ -7683,6 +7683,12 @@ W: http://www.mellanox.com
Q: http://patchwork.ozlabs.org/project/netdev/list/ Q: http://patchwork.ozlabs.org/project/netdev/list/
F: drivers/net/ethernet/mellanox/mlxsw/ F: drivers/net/ethernet/mellanox/mlxsw/
MELLANOX PLATFORM DRIVER
M: Vadim Pasternak <vadimp@mellanox.com>
L: platform-driver-x86@vger.kernel.org
S: Supported
F: arch/x86/platform/mellanox/mlx-platform.c
SOFT-ROCE DRIVER (rxe) SOFT-ROCE DRIVER (rxe)
M: Moni Shoua <monis@mellanox.com> M: Moni Shoua <monis@mellanox.com>
L: linux-rdma@vger.kernel.org L: linux-rdma@vger.kernel.org
......
...@@ -550,6 +550,18 @@ config X86_INTEL_QUARK ...@@ -550,6 +550,18 @@ config X86_INTEL_QUARK
Say Y here if you have a Quark based system such as the Arduino Say Y here if you have a Quark based system such as the Arduino
compatible Intel Galileo. compatible Intel Galileo.
config MLX_PLATFORM
tristate "Mellanox Technologies platform support"
depends on X86_64
depends on X86_EXTENDED_PLATFORM
---help---
This option enables system support for the Mellanox Technologies
platform.
Say Y here if you are building a kernel for Mellanox system.
Otherwise, say N.
config X86_INTEL_LPSS config X86_INTEL_LPSS
bool "Intel Low Power Subsystem Support" bool "Intel Low Power Subsystem Support"
depends on X86 && ACPI depends on X86 && ACPI
......
...@@ -56,8 +56,8 @@ ...@@ -56,8 +56,8 @@
#define INTEL_FAM6_ATOM_SILVERMONT1 0x37 /* BayTrail/BYT / Valleyview */ #define INTEL_FAM6_ATOM_SILVERMONT1 0x37 /* BayTrail/BYT / Valleyview */
#define INTEL_FAM6_ATOM_SILVERMONT2 0x4D /* Avaton/Rangely */ #define INTEL_FAM6_ATOM_SILVERMONT2 0x4D /* Avaton/Rangely */
#define INTEL_FAM6_ATOM_AIRMONT 0x4C /* CherryTrail / Braswell */ #define INTEL_FAM6_ATOM_AIRMONT 0x4C /* CherryTrail / Braswell */
#define INTEL_FAM6_ATOM_MERRIFIELD1 0x4A /* Tangier */ #define INTEL_FAM6_ATOM_MERRIFIELD 0x4A /* Tangier */
#define INTEL_FAM6_ATOM_MERRIFIELD2 0x5A /* Annidale */ #define INTEL_FAM6_ATOM_MOOREFIELD 0x5A /* Annidale */
#define INTEL_FAM6_ATOM_GOLDMONT 0x5C #define INTEL_FAM6_ATOM_GOLDMONT 0x5C
#define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */ #define INTEL_FAM6_ATOM_DENVERTON 0x5F /* Goldmont Microserver */
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
extern int intel_mid_pci_init(void); extern int intel_mid_pci_init(void);
extern int intel_mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state); extern int intel_mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state);
extern void intel_mid_pwr_power_off(void);
#define INTEL_MID_PWR_LSS_OFFSET 4 #define INTEL_MID_PWR_LSS_OFFSET 4
#define INTEL_MID_PWR_LSS_TYPE (1 << 7) #define INTEL_MID_PWR_LSS_TYPE (1 << 7)
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
#include <linux/notifier.h> #include <linux/notifier.h>
#define IPCMSG_COLD_OFF 0x80 /* Only for Tangier */
#define IPCMSG_WARM_RESET 0xF0 #define IPCMSG_WARM_RESET 0xF0
#define IPCMSG_COLD_RESET 0xF1 #define IPCMSG_COLD_RESET 0xF1
#define IPCMSG_SOFT_RESET 0xF2 #define IPCMSG_SOFT_RESET 0xF2
......
...@@ -49,14 +49,12 @@ ...@@ -49,14 +49,12 @@
#define UV_NET_ENDPOINT_INTD (is_uv1_hub() ? \ #define UV_NET_ENDPOINT_INTD (is_uv1_hub() ? \
UV1_NET_ENDPOINT_INTD : UV2_NET_ENDPOINT_INTD) UV1_NET_ENDPOINT_INTD : UV2_NET_ENDPOINT_INTD)
#define UV_DESC_PSHIFT 49 #define UV_DESC_PSHIFT 49
#define UV_PAYLOADQ_PNODE_SHIFT 49 #define UV_PAYLOADQ_GNODE_SHIFT 49
#define UV_PTC_BASENAME "sgi_uv/ptc_statistics" #define UV_PTC_BASENAME "sgi_uv/ptc_statistics"
#define UV_BAU_BASENAME "sgi_uv/bau_tunables" #define UV_BAU_BASENAME "sgi_uv/bau_tunables"
#define UV_BAU_TUNABLES_DIR "sgi_uv" #define UV_BAU_TUNABLES_DIR "sgi_uv"
#define UV_BAU_TUNABLES_FILE "bau_tunables" #define UV_BAU_TUNABLES_FILE "bau_tunables"
#define WHITESPACE " \t\n" #define WHITESPACE " \t\n"
#define uv_mmask ((1UL << uv_hub_info->m_val) - 1)
#define uv_physnodeaddr(x) ((__pa((unsigned long)(x)) & uv_mmask))
#define cpubit_isset(cpu, bau_local_cpumask) \ #define cpubit_isset(cpu, bau_local_cpumask) \
test_bit((cpu), (bau_local_cpumask).bits) test_bit((cpu), (bau_local_cpumask).bits)
...@@ -387,6 +385,17 @@ struct uv2_3_bau_msg_header { ...@@ -387,6 +385,17 @@ struct uv2_3_bau_msg_header {
/* bits 127:120 */ /* bits 127:120 */
}; };
/* Abstracted BAU functions */
struct bau_operations {
unsigned long (*read_l_sw_ack)(void);
unsigned long (*read_g_sw_ack)(int pnode);
unsigned long (*bau_gpa_to_offset)(unsigned long vaddr);
void (*write_l_sw_ack)(unsigned long mmr);
void (*write_g_sw_ack)(int pnode, unsigned long mmr);
void (*write_payload_first)(int pnode, unsigned long mmr);
void (*write_payload_last)(int pnode, unsigned long mmr);
};
/* /*
* The activation descriptor: * The activation descriptor:
* The format of the message to send, plus all accompanying control * The format of the message to send, plus all accompanying control
...@@ -655,6 +664,16 @@ static inline void write_gmmr_activation(int pnode, unsigned long mmr_image) ...@@ -655,6 +664,16 @@ static inline void write_gmmr_activation(int pnode, unsigned long mmr_image)
write_gmmr(pnode, UVH_LB_BAU_SB_ACTIVATION_CONTROL, mmr_image); write_gmmr(pnode, UVH_LB_BAU_SB_ACTIVATION_CONTROL, mmr_image);
} }
static inline void write_mmr_proc_payload_first(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UV4H_LB_PROC_INTD_QUEUE_FIRST, mmr_image);
}
static inline void write_mmr_proc_payload_last(int pnode, unsigned long mmr_image)
{
write_gmmr(pnode, UV4H_LB_PROC_INTD_QUEUE_LAST, mmr_image);
}
static inline void write_mmr_payload_first(int pnode, unsigned long mmr_image) static inline void write_mmr_payload_first(int pnode, unsigned long mmr_image)
{ {
write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST, mmr_image); write_gmmr(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST, mmr_image);
...@@ -700,6 +719,26 @@ static inline unsigned long read_gmmr_sw_ack(int pnode) ...@@ -700,6 +719,26 @@ static inline unsigned long read_gmmr_sw_ack(int pnode)
return read_gmmr(pnode, UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE); return read_gmmr(pnode, UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE);
} }
static inline void write_mmr_proc_sw_ack(unsigned long mr)
{
uv_write_local_mmr(UV4H_LB_PROC_INTD_SOFT_ACK_CLEAR, mr);
}
static inline void write_gmmr_proc_sw_ack(int pnode, unsigned long mr)
{
write_gmmr(pnode, UV4H_LB_PROC_INTD_SOFT_ACK_CLEAR, mr);
}
static inline unsigned long read_mmr_proc_sw_ack(void)
{
return read_lmmr(UV4H_LB_PROC_INTD_SOFT_ACK_PENDING);
}
static inline unsigned long read_gmmr_proc_sw_ack(int pnode)
{
return read_gmmr(pnode, UV4H_LB_PROC_INTD_SOFT_ACK_PENDING);
}
static inline void write_mmr_data_config(int pnode, unsigned long mr) static inline void write_mmr_data_config(int pnode, unsigned long mr)
{ {
uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, mr); uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, mr);
......
...@@ -8,6 +8,7 @@ obj-y += iris/ ...@@ -8,6 +8,7 @@ obj-y += iris/
obj-y += intel/ obj-y += intel/
obj-y += intel-mid/ obj-y += intel-mid/
obj-y += intel-quark/ obj-y += intel-quark/
obj-y += mellanox/
obj-y += olpc/ obj-y += olpc/
obj-y += scx200/ obj-y += scx200/
obj-y += sfi/ obj-y += sfi/
......
...@@ -155,7 +155,7 @@ static void punit_dbgfs_unregister(void) ...@@ -155,7 +155,7 @@ static void punit_dbgfs_unregister(void)
static const struct x86_cpu_id intel_punit_cpu_ids[] = { static const struct x86_cpu_id intel_punit_cpu_ids[] = {
ICPU(INTEL_FAM6_ATOM_SILVERMONT1, punit_device_byt), ICPU(INTEL_FAM6_ATOM_SILVERMONT1, punit_device_byt),
ICPU(INTEL_FAM6_ATOM_MERRIFIELD1, punit_device_tng), ICPU(INTEL_FAM6_ATOM_MERRIFIELD, punit_device_tng),
ICPU(INTEL_FAM6_ATOM_AIRMONT, punit_device_cht), ICPU(INTEL_FAM6_ATOM_AIRMONT, punit_device_cht),
{} {}
}; };
......
# Family-Level Interface Shim (FLIS) # Family-Level Interface Shim (FLIS)
obj-$(subst m,y,$(CONFIG_PINCTRL_MERRIFIELD)) += platform_mrfld_pinctrl.o obj-$(subst m,y,$(CONFIG_PINCTRL_MERRIFIELD)) += platform_mrfld_pinctrl.o
# SDHCI Devices
obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += platform_mrfld_sd.o
# WiFi
obj-$(subst m,y,$(CONFIG_BRCMFMAC_SDIO)) += platform_bcm43xx.o
# IPC Devices # IPC Devices
obj-y += platform_ipc.o obj-y += platform_ipc.o
obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic.o obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic.o
......
/*
* platform_bcm43xx.c: bcm43xx platform data initilization file
*
* (C) Copyright 2016 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*/
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
#include <linux/sfi.h>
#include <asm/intel-mid.h>
#define WLAN_SFI_GPIO_IRQ_NAME "WLAN-interrupt"
#define WLAN_SFI_GPIO_ENABLE_NAME "WLAN-enable"
#define WLAN_DEV_NAME "0000:00:01.3"
static struct regulator_consumer_supply bcm43xx_vmmc_supply = {
.dev_name = WLAN_DEV_NAME,
.supply = "vmmc",
};
static struct regulator_init_data bcm43xx_vmmc_data = {
.constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
},
.num_consumer_supplies = 1,
.consumer_supplies = &bcm43xx_vmmc_supply,
};
static struct fixed_voltage_config bcm43xx_vmmc = {
.supply_name = "bcm43xx-vmmc-regulator",
/*
* Announce 2.0V here to be compatible with SDIO specification. The
* real voltage and signaling are still 1.8V.
*/
.microvolts = 2000000, /* 1.8V */
.gpio = -EINVAL,
.startup_delay = 250 * 1000, /* 250ms */
.enable_high = 1, /* active high */
.enabled_at_boot = 0, /* disabled at boot */
.init_data = &bcm43xx_vmmc_data,
};
static struct platform_device bcm43xx_vmmc_regulator = {
.name = "reg-fixed-voltage",
.id = PLATFORM_DEVID_AUTO,
.dev = {
.platform_data = &bcm43xx_vmmc,
},
};
static int __init bcm43xx_regulator_register(void)
{
int ret;
bcm43xx_vmmc.gpio = get_gpio_by_name(WLAN_SFI_GPIO_ENABLE_NAME);
ret = platform_device_register(&bcm43xx_vmmc_regulator);
if (ret) {
pr_err("%s: vmmc regulator register failed\n", __func__);
return ret;
}
return 0;
}
static void __init *bcm43xx_platform_data(void *info)
{
int ret;
ret = bcm43xx_regulator_register();
if (ret)
return NULL;
pr_info("Using generic wifi platform data\n");
/* For now it's empty */
return NULL;
}
static const struct devs_id bcm43xx_clk_vmmc_dev_id __initconst = {
.name = "bcm43xx_clk_vmmc",
.type = SFI_DEV_TYPE_SD,
.get_platform_data = &bcm43xx_platform_data,
};
sfi_device(bcm43xx_clk_vmmc_dev_id);
/*
* SDHCI platform data initilisation file
*
* (C) Copyright 2016 Intel Corporation
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/mmc/sdhci-pci-data.h>
#include <asm/intel-mid.h>
#define INTEL_MRFLD_SD 2
#define INTEL_MRFLD_SD_CD_GPIO 77
static struct sdhci_pci_data mrfld_sdhci_pci_data = {
.rst_n_gpio = -EINVAL,
.cd_gpio = INTEL_MRFLD_SD_CD_GPIO,
};
static struct sdhci_pci_data *
mrfld_sdhci_pci_get_data(struct pci_dev *pdev, int slotno)
{
unsigned int func = PCI_FUNC(pdev->devfn);
if (func == INTEL_MRFLD_SD)
return &mrfld_sdhci_pci_data;
return NULL;
}
static int __init mrfld_sd_init(void)
{
if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)
return -ENODEV;
sdhci_pci_get_data = mrfld_sdhci_pci_get_data;
return 0;
}
arch_initcall(mrfld_sd_init);
...@@ -70,6 +70,11 @@ EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip); ...@@ -70,6 +70,11 @@ EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip);
static void intel_mid_power_off(void) static void intel_mid_power_off(void)
{ {
/* Shut down South Complex via PWRMU */
intel_mid_pwr_power_off();
/* Only for Tangier, the rest will ignore this command */
intel_scu_ipc_simple_command(IPCMSG_COLD_OFF, 1);
}; };
static void intel_mid_reboot(void) static void intel_mid_reboot(void)
......
...@@ -44,7 +44,19 @@ ...@@ -44,7 +44,19 @@
/* Bits in PM_CMD */ /* Bits in PM_CMD */
#define PM_CMD_CMD(x) ((x) << 0) #define PM_CMD_CMD(x) ((x) << 0)
#define PM_CMD_IOC (1 << 8) #define PM_CMD_IOC (1 << 8)
#define PM_CMD_D3cold (1 << 21) #define PM_CMD_CM_NOP (0 << 9)
#define PM_CMD_CM_IMMEDIATE (1 << 9)
#define PM_CMD_CM_DELAY (2 << 9)
#define PM_CMD_CM_TRIGGER (3 << 9)
/* System states */
#define PM_CMD_SYS_STATE_S5 (5 << 16)
/* Trigger variants */
#define PM_CMD_CFG_TRIGGER_NC (3 << 19)
/* Message to wait for TRIGGER_NC case */
#define TRIGGER_NC_MSG_2 (2 << 22)
/* List of commands */ /* List of commands */
#define CMD_SET_CFG 0x01 #define CMD_SET_CFG 0x01
...@@ -137,7 +149,7 @@ static int mid_pwr_wait(struct mid_pwr *pwr) ...@@ -137,7 +149,7 @@ static int mid_pwr_wait(struct mid_pwr *pwr)
static int mid_pwr_wait_for_cmd(struct mid_pwr *pwr, u8 cmd) static int mid_pwr_wait_for_cmd(struct mid_pwr *pwr, u8 cmd)
{ {
writel(PM_CMD_CMD(cmd), pwr->regs + PM_CMD); writel(PM_CMD_CMD(cmd) | PM_CMD_CM_IMMEDIATE, pwr->regs + PM_CMD);
return mid_pwr_wait(pwr); return mid_pwr_wait(pwr);
} }
...@@ -260,6 +272,20 @@ int intel_mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state) ...@@ -260,6 +272,20 @@ int intel_mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state)
} }
EXPORT_SYMBOL_GPL(intel_mid_pci_set_power_state); EXPORT_SYMBOL_GPL(intel_mid_pci_set_power_state);
void intel_mid_pwr_power_off(void)
{
struct mid_pwr *pwr = midpwr;
u32 cmd = PM_CMD_SYS_STATE_S5 |
PM_CMD_CMD(CMD_SET_CFG) |
PM_CMD_CM_TRIGGER |
PM_CMD_CFG_TRIGGER_NC |
TRIGGER_NC_MSG_2;
/* Send command to SCU */
writel(cmd, pwr->regs + PM_CMD);
mid_pwr_wait(pwr);
}
int intel_mid_pwr_get_lss_id(struct pci_dev *pdev) int intel_mid_pwr_get_lss_id(struct pci_dev *pdev)
{ {
int vndr; int vndr;
...@@ -354,7 +380,7 @@ static int mid_pwr_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -354,7 +380,7 @@ static int mid_pwr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0; return 0;
} }
static int mid_set_initial_state(struct mid_pwr *pwr) static int mid_set_initial_state(struct mid_pwr *pwr, const u32 *states)
{ {
unsigned int i, j; unsigned int i, j;
int ret; int ret;
...@@ -379,10 +405,10 @@ static int mid_set_initial_state(struct mid_pwr *pwr) ...@@ -379,10 +405,10 @@ static int mid_set_initial_state(struct mid_pwr *pwr)
* NOTE: The actual device mapping is provided by a platform at run * NOTE: The actual device mapping is provided by a platform at run
* time using vendor capability of PCI configuration space. * time using vendor capability of PCI configuration space.
*/ */
mid_pwr_set_state(pwr, 0, 0xffffffff); mid_pwr_set_state(pwr, 0, states[0]);
mid_pwr_set_state(pwr, 1, 0xffffffff); mid_pwr_set_state(pwr, 1, states[1]);
mid_pwr_set_state(pwr, 2, 0xffffffff); mid_pwr_set_state(pwr, 2, states[2]);
mid_pwr_set_state(pwr, 3, 0xffffffff); mid_pwr_set_state(pwr, 3, states[3]);
/* Send command to SCU */ /* Send command to SCU */
ret = mid_pwr_wait_for_cmd(pwr, CMD_SET_CFG); ret = mid_pwr_wait_for_cmd(pwr, CMD_SET_CFG);
...@@ -397,13 +423,41 @@ static int mid_set_initial_state(struct mid_pwr *pwr) ...@@ -397,13 +423,41 @@ static int mid_set_initial_state(struct mid_pwr *pwr)
return 0; return 0;
} }
static const struct mid_pwr_device_info mid_info = { static int pnw_set_initial_state(struct mid_pwr *pwr)
.set_initial_state = mid_set_initial_state, {
/* On Penwell SRAM must stay powered on */
const u32 states[] = {
0xf00fffff, /* PM_SSC(0) */
0xffffffff, /* PM_SSC(1) */
0xffffffff, /* PM_SSC(2) */
0xffffffff, /* PM_SSC(3) */
};
return mid_set_initial_state(pwr, states);
}
static int tng_set_initial_state(struct mid_pwr *pwr)
{
const u32 states[] = {
0xffffffff, /* PM_SSC(0) */
0xffffffff, /* PM_SSC(1) */
0xffffffff, /* PM_SSC(2) */
0xffffffff, /* PM_SSC(3) */
};
return mid_set_initial_state(pwr, states);
}
static const struct mid_pwr_device_info pnw_info = {
.set_initial_state = pnw_set_initial_state,
};
static const struct mid_pwr_device_info tng_info = {
.set_initial_state = tng_set_initial_state,
}; };
/* This table should be in sync with the one in drivers/pci/pci-mid.c */
static const struct pci_device_id mid_pwr_pci_ids[] = { static const struct pci_device_id mid_pwr_pci_ids[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PENWELL), (kernel_ulong_t)&mid_info }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PENWELL), (kernel_ulong_t)&pnw_info },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_TANGIER), (kernel_ulong_t)&mid_info }, { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_TANGIER), (kernel_ulong_t)&tng_info },
{} {}
}; };
......
obj-$(CONFIG_MLX_PLATFORM) += mlx-platform.o
/*
* arch/x86/platform/mellanox/mlx-platform.c
* Copyright (c) 2016 Mellanox Technologies. All rights reserved.
* Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_data/i2c-mux-reg.h>
#define MLX_PLAT_DEVICE_NAME "mlxplat"
/* LPC bus IO offsets */
#define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000
#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500
#define MLXPLAT_CPLD_LPC_IO_RANGE 0x100
#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb
#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda
#define MLXPLAT_CPLD_LPC_PIO_OFFSET 0x10000UL
#define MLXPLAT_CPLD_LPC_REG1 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \
MLXPLAT_CPLD_LPC_PIO_OFFSET)
#define MLXPLAT_CPLD_LPC_REG2 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
MLXPLAT_CPLD_LPC_I2C_CH2_OFF) | \
MLXPLAT_CPLD_LPC_PIO_OFFSET)
/* Start channel numbers */
#define MLXPLAT_CPLD_CH1 2
#define MLXPLAT_CPLD_CH2 10
/* Number of LPC attached MUX platform devices */
#define MLXPLAT_CPLD_LPC_MUX_DEVS 2
/* mlxplat_priv - platform private data
* @pdev_i2c - i2c controller platform device
* @pdev_mux - array of mux platform devices
*/
struct mlxplat_priv {
struct platform_device *pdev_i2c;
struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS];
};
/* Regions for LPC I2C controller and LPC base register space */
static const struct resource mlxplat_lpc_resources[] = {
[0] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_I2C_BASE_ADRR,
MLXPLAT_CPLD_LPC_IO_RANGE,
"mlxplat_cpld_lpc_i2c_ctrl", IORESOURCE_IO),
[1] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_REG_BASE_ADRR,
MLXPLAT_CPLD_LPC_IO_RANGE,
"mlxplat_cpld_lpc_regs",
IORESOURCE_IO),
};
/* Platform default channels */
static const int mlxplat_default_channels[][8] = {
{
MLXPLAT_CPLD_CH1, MLXPLAT_CPLD_CH1 + 1, MLXPLAT_CPLD_CH1 + 2,
MLXPLAT_CPLD_CH1 + 3, MLXPLAT_CPLD_CH1 + 4, MLXPLAT_CPLD_CH1 +
5, MLXPLAT_CPLD_CH1 + 6, MLXPLAT_CPLD_CH1 + 7
},
{
MLXPLAT_CPLD_CH2, MLXPLAT_CPLD_CH2 + 1, MLXPLAT_CPLD_CH2 + 2,
MLXPLAT_CPLD_CH2 + 3, MLXPLAT_CPLD_CH2 + 4, MLXPLAT_CPLD_CH2 +
5, MLXPLAT_CPLD_CH2 + 6, MLXPLAT_CPLD_CH2 + 7
},
};
/* Platform channels for MSN21xx system family */
static const int mlxplat_msn21xx_channels[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
/* Platform mux data */
static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
{
.parent = 1,
.base_nr = MLXPLAT_CPLD_CH1,
.write_only = 1,
.reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1,
.reg_size = 1,
.idle_in_use = 1,
},
{
.parent = 1,
.base_nr = MLXPLAT_CPLD_CH2,
.write_only = 1,
.reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2,
.reg_size = 1,
.idle_in_use = 1,
},
};
static struct platform_device *mlxplat_dev;
static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
{
int i;
for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
mlxplat_mux_data[i].values = mlxplat_default_channels[i];
mlxplat_mux_data[i].n_values =
ARRAY_SIZE(mlxplat_default_channels[i]);
}
return 1;
};
static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
{
int i;
for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
mlxplat_mux_data[i].n_values =
ARRAY_SIZE(mlxplat_msn21xx_channels);
}
return 1;
};
static struct dmi_system_id mlxplat_dmi_table[] __initdata = {
{
.callback = mlxplat_dmi_default_matched,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "MSN24"),
},
},
{
.callback = mlxplat_dmi_default_matched,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "MSN27"),
},
},
{
.callback = mlxplat_dmi_default_matched,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "MSB"),
},
},
{
.callback = mlxplat_dmi_default_matched,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "MSX"),
},
},
{
.callback = mlxplat_dmi_msn21xx_matched,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
DMI_MATCH(DMI_PRODUCT_NAME, "MSN21"),
},
},
{ }
};
static int __init mlxplat_init(void)
{
struct mlxplat_priv *priv;
int i, err;
if (!dmi_check_system(mlxplat_dmi_table))
return -ENODEV;
mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, -1,
mlxplat_lpc_resources,
ARRAY_SIZE(mlxplat_lpc_resources));
if (IS_ERR(mlxplat_dev))
return PTR_ERR(mlxplat_dev);
priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv),
GFP_KERNEL);
if (!priv) {
err = -ENOMEM;
goto fail_alloc;
}
platform_set_drvdata(mlxplat_dev, priv);
priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", -1,
NULL, 0);
if (IS_ERR(priv->pdev_i2c)) {
err = PTR_ERR(priv->pdev_i2c);
goto fail_alloc;
};
for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
priv->pdev_mux[i] = platform_device_register_resndata(
&mlxplat_dev->dev,
"i2c-mux-reg", i, NULL,
0, &mlxplat_mux_data[i],
sizeof(mlxplat_mux_data[i]));
if (IS_ERR(priv->pdev_mux[i])) {
err = PTR_ERR(priv->pdev_mux[i]);
goto fail_platform_mux_register;
}
}
return 0;
fail_platform_mux_register:
for (i--; i > 0 ; i--)
platform_device_unregister(priv->pdev_mux[i]);
platform_device_unregister(priv->pdev_i2c);
fail_alloc:
platform_device_unregister(mlxplat_dev);
return err;
}
module_init(mlxplat_init);
static void __exit mlxplat_exit(void)
{
struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
int i;
for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
platform_device_unregister(priv->pdev_mux[i]);
platform_device_unregister(priv->pdev_i2c);
platform_device_unregister(mlxplat_dev);
}
module_exit(mlxplat_exit);
MODULE_AUTHOR("Vadim Pasternak (vadimp@mellanox.com)");
MODULE_DESCRIPTION("Mellanox platform driver");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("dmi:*:*Mellanox*:MSN24*:");
MODULE_ALIAS("dmi:*:*Mellanox*:MSN27*:");
MODULE_ALIAS("dmi:*:*Mellanox*:MSB*:");
MODULE_ALIAS("dmi:*:*Mellanox*:MSX*:");
MODULE_ALIAS("dmi:*:*Mellanox*:MSN21*:");
...@@ -24,6 +24,29 @@ ...@@ -24,6 +24,29 @@
#include <asm/irq_vectors.h> #include <asm/irq_vectors.h>
#include <asm/timer.h> #include <asm/timer.h>
static struct bau_operations ops;
static struct bau_operations uv123_bau_ops = {
.bau_gpa_to_offset = uv_gpa_to_offset,
.read_l_sw_ack = read_mmr_sw_ack,
.read_g_sw_ack = read_gmmr_sw_ack,
.write_l_sw_ack = write_mmr_sw_ack,
.write_g_sw_ack = write_gmmr_sw_ack,
.write_payload_first = write_mmr_payload_first,
.write_payload_last = write_mmr_payload_last,
};
static struct bau_operations uv4_bau_ops = {
.bau_gpa_to_offset = uv_gpa_to_soc_phys_ram,
.read_l_sw_ack = read_mmr_proc_sw_ack,
.read_g_sw_ack = read_gmmr_proc_sw_ack,
.write_l_sw_ack = write_mmr_proc_sw_ack,
.write_g_sw_ack = write_gmmr_proc_sw_ack,
.write_payload_first = write_mmr_proc_payload_first,
.write_payload_last = write_mmr_proc_payload_last,
};
/* timeouts in nanoseconds (indexed by UVH_AGING_PRESCALE_SEL urgency7 30:28) */ /* timeouts in nanoseconds (indexed by UVH_AGING_PRESCALE_SEL urgency7 30:28) */
static int timeout_base_ns[] = { static int timeout_base_ns[] = {
20, 20,
...@@ -55,16 +78,16 @@ static int congested_reps = CONGESTED_REPS; ...@@ -55,16 +78,16 @@ static int congested_reps = CONGESTED_REPS;
static int disabled_period = DISABLED_PERIOD; static int disabled_period = DISABLED_PERIOD;
static struct tunables tunables[] = { static struct tunables tunables[] = {
{&max_concurr, MAX_BAU_CONCURRENT}, /* must be [0] */ {&max_concurr, MAX_BAU_CONCURRENT}, /* must be [0] */
{&plugged_delay, PLUGGED_DELAY}, {&plugged_delay, PLUGGED_DELAY},
{&plugsb4reset, PLUGSB4RESET}, {&plugsb4reset, PLUGSB4RESET},
{&timeoutsb4reset, TIMEOUTSB4RESET}, {&timeoutsb4reset, TIMEOUTSB4RESET},
{&ipi_reset_limit, IPI_RESET_LIMIT}, {&ipi_reset_limit, IPI_RESET_LIMIT},
{&complete_threshold, COMPLETE_THRESHOLD}, {&complete_threshold, COMPLETE_THRESHOLD},
{&congested_respns_us, CONGESTED_RESPONSE_US}, {&congested_respns_us, CONGESTED_RESPONSE_US},
{&congested_reps, CONGESTED_REPS}, {&congested_reps, CONGESTED_REPS},
{&disabled_period, DISABLED_PERIOD}, {&disabled_period, DISABLED_PERIOD},
{&giveup_limit, GIVEUP_LIMIT} {&giveup_limit, GIVEUP_LIMIT}
}; };
static struct dentry *tunables_dir; static struct dentry *tunables_dir;
...@@ -216,7 +239,7 @@ static void reply_to_message(struct msg_desc *mdp, struct bau_control *bcp, ...@@ -216,7 +239,7 @@ static void reply_to_message(struct msg_desc *mdp, struct bau_control *bcp,
msg = mdp->msg; msg = mdp->msg;
if (!msg->canceled && do_acknowledge) { if (!msg->canceled && do_acknowledge) {
dw = (msg->swack_vec << UV_SW_ACK_NPENDING) | msg->swack_vec; dw = (msg->swack_vec << UV_SW_ACK_NPENDING) | msg->swack_vec;
write_mmr_sw_ack(dw); ops.write_l_sw_ack(dw);
} }
msg->replied_to = 1; msg->replied_to = 1;
msg->swack_vec = 0; msg->swack_vec = 0;
...@@ -252,7 +275,7 @@ static void bau_process_retry_msg(struct msg_desc *mdp, ...@@ -252,7 +275,7 @@ static void bau_process_retry_msg(struct msg_desc *mdp,
msg->swack_vec) == 0) && msg->swack_vec) == 0) &&
(msg2->sending_cpu == msg->sending_cpu) && (msg2->sending_cpu == msg->sending_cpu) &&
(msg2->msg_type != MSG_NOOP)) { (msg2->msg_type != MSG_NOOP)) {
mmr = read_mmr_sw_ack(); mmr = ops.read_l_sw_ack();
msg_res = msg2->swack_vec; msg_res = msg2->swack_vec;
/* /*
* This is a message retry; clear the resources held * This is a message retry; clear the resources held
...@@ -270,7 +293,7 @@ static void bau_process_retry_msg(struct msg_desc *mdp, ...@@ -270,7 +293,7 @@ static void bau_process_retry_msg(struct msg_desc *mdp,
stat->d_canceled++; stat->d_canceled++;
cancel_count++; cancel_count++;
mr = (msg_res << UV_SW_ACK_NPENDING) | msg_res; mr = (msg_res << UV_SW_ACK_NPENDING) | msg_res;
write_mmr_sw_ack(mr); ops.write_l_sw_ack(mr);
} }
} }
} }
...@@ -403,12 +426,12 @@ static void do_reset(void *ptr) ...@@ -403,12 +426,12 @@ static void do_reset(void *ptr)
/* /*
* only reset the resource if it is still pending * only reset the resource if it is still pending
*/ */
mmr = read_mmr_sw_ack(); mmr = ops.read_l_sw_ack();
msg_res = msg->swack_vec; msg_res = msg->swack_vec;
mr = (msg_res << UV_SW_ACK_NPENDING) | msg_res; mr = (msg_res << UV_SW_ACK_NPENDING) | msg_res;
if (mmr & msg_res) { if (mmr & msg_res) {
stat->d_rcanceled++; stat->d_rcanceled++;
write_mmr_sw_ack(mr); ops.write_l_sw_ack(mr);
} }
} }
} }
...@@ -1198,7 +1221,7 @@ void process_uv2_message(struct msg_desc *mdp, struct bau_control *bcp) ...@@ -1198,7 +1221,7 @@ void process_uv2_message(struct msg_desc *mdp, struct bau_control *bcp)
struct bau_pq_entry *msg = mdp->msg; struct bau_pq_entry *msg = mdp->msg;
struct bau_pq_entry *other_msg; struct bau_pq_entry *other_msg;
mmr_image = read_mmr_sw_ack(); mmr_image = ops.read_l_sw_ack();
swack_vec = msg->swack_vec; swack_vec = msg->swack_vec;
if ((swack_vec & mmr_image) == 0) { if ((swack_vec & mmr_image) == 0) {
...@@ -1427,7 +1450,7 @@ static int ptc_seq_show(struct seq_file *file, void *data) ...@@ -1427,7 +1450,7 @@ static int ptc_seq_show(struct seq_file *file, void *data)
/* destination side statistics */ /* destination side statistics */
seq_printf(file, seq_printf(file,
"%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n",
read_gmmr_sw_ack(uv_cpu_to_pnode(cpu)), ops.read_g_sw_ack(uv_cpu_to_pnode(cpu)),
stat->d_requestee, cycles_2_us(stat->d_time), stat->d_requestee, cycles_2_us(stat->d_time),
stat->d_alltlb, stat->d_onetlb, stat->d_multmsg, stat->d_alltlb, stat->d_onetlb, stat->d_multmsg,
stat->d_nomsg, stat->d_retries, stat->d_canceled, stat->d_nomsg, stat->d_retries, stat->d_canceled,
...@@ -1493,16 +1516,16 @@ static ssize_t ptc_proc_write(struct file *file, const char __user *user, ...@@ -1493,16 +1516,16 @@ static ssize_t ptc_proc_write(struct file *file, const char __user *user,
} }
if (kstrtol(optstr, 10, &input_arg) < 0) { if (kstrtol(optstr, 10, &input_arg) < 0) {
printk(KERN_DEBUG "%s is invalid\n", optstr); pr_debug("%s is invalid\n", optstr);
return -EINVAL; return -EINVAL;
} }
if (input_arg == 0) { if (input_arg == 0) {
elements = ARRAY_SIZE(stat_description); elements = ARRAY_SIZE(stat_description);
printk(KERN_DEBUG "# cpu: cpu number\n"); pr_debug("# cpu: cpu number\n");
printk(KERN_DEBUG "Sender statistics:\n"); pr_debug("Sender statistics:\n");
for (i = 0; i < elements; i++) for (i = 0; i < elements; i++)
printk(KERN_DEBUG "%s\n", stat_description[i]); pr_debug("%s\n", stat_description[i]);
} else if (input_arg == -1) { } else if (input_arg == -1) {
for_each_present_cpu(cpu) { for_each_present_cpu(cpu) {
stat = &per_cpu(ptcstats, cpu); stat = &per_cpu(ptcstats, cpu);
...@@ -1550,7 +1573,7 @@ static int parse_tunables_write(struct bau_control *bcp, char *instr, ...@@ -1550,7 +1573,7 @@ static int parse_tunables_write(struct bau_control *bcp, char *instr,
break; break;
} }
if (cnt != e) { if (cnt != e) {
printk(KERN_INFO "bau tunable error: should be %d values\n", e); pr_info("bau tunable error: should be %d values\n", e);
return -EINVAL; return -EINVAL;
} }
...@@ -1567,7 +1590,7 @@ static int parse_tunables_write(struct bau_control *bcp, char *instr, ...@@ -1567,7 +1590,7 @@ static int parse_tunables_write(struct bau_control *bcp, char *instr,
continue; continue;
} }
if (val < 1 || val > bcp->cpus_in_uvhub) { if (val < 1 || val > bcp->cpus_in_uvhub) {
printk(KERN_DEBUG pr_debug(
"Error: BAU max concurrent %d is invalid\n", "Error: BAU max concurrent %d is invalid\n",
val); val);
return -EINVAL; return -EINVAL;
...@@ -1615,17 +1638,17 @@ static ssize_t tunables_write(struct file *file, const char __user *user, ...@@ -1615,17 +1638,17 @@ static ssize_t tunables_write(struct file *file, const char __user *user,
for_each_present_cpu(cpu) { for_each_present_cpu(cpu) {
bcp = &per_cpu(bau_control, cpu); bcp = &per_cpu(bau_control, cpu);
bcp->max_concurr = max_concurr; bcp->max_concurr = max_concurr;
bcp->max_concurr_const = max_concurr; bcp->max_concurr_const = max_concurr;
bcp->plugged_delay = plugged_delay; bcp->plugged_delay = plugged_delay;
bcp->plugsb4reset = plugsb4reset; bcp->plugsb4reset = plugsb4reset;
bcp->timeoutsb4reset = timeoutsb4reset; bcp->timeoutsb4reset = timeoutsb4reset;
bcp->ipi_reset_limit = ipi_reset_limit; bcp->ipi_reset_limit = ipi_reset_limit;
bcp->complete_threshold = complete_threshold; bcp->complete_threshold = complete_threshold;
bcp->cong_response_us = congested_respns_us; bcp->cong_response_us = congested_respns_us;
bcp->cong_reps = congested_reps; bcp->cong_reps = congested_reps;
bcp->disabled_period = sec_2_cycles(disabled_period); bcp->disabled_period = sec_2_cycles(disabled_period);
bcp->giveup_limit = giveup_limit; bcp->giveup_limit = giveup_limit;
} }
return count; return count;
} }
...@@ -1672,21 +1695,21 @@ static int __init uv_ptc_init(void) ...@@ -1672,21 +1695,21 @@ static int __init uv_ptc_init(void)
proc_uv_ptc = proc_create(UV_PTC_BASENAME, 0444, NULL, proc_uv_ptc = proc_create(UV_PTC_BASENAME, 0444, NULL,
&proc_uv_ptc_operations); &proc_uv_ptc_operations);
if (!proc_uv_ptc) { if (!proc_uv_ptc) {
printk(KERN_ERR "unable to create %s proc entry\n", pr_err("unable to create %s proc entry\n",
UV_PTC_BASENAME); UV_PTC_BASENAME);
return -EINVAL; return -EINVAL;
} }
tunables_dir = debugfs_create_dir(UV_BAU_TUNABLES_DIR, NULL); tunables_dir = debugfs_create_dir(UV_BAU_TUNABLES_DIR, NULL);
if (!tunables_dir) { if (!tunables_dir) {
printk(KERN_ERR "unable to create debugfs directory %s\n", pr_err("unable to create debugfs directory %s\n",
UV_BAU_TUNABLES_DIR); UV_BAU_TUNABLES_DIR);
return -EINVAL; return -EINVAL;
} }
tunables_file = debugfs_create_file(UV_BAU_TUNABLES_FILE, 0600, tunables_file = debugfs_create_file(UV_BAU_TUNABLES_FILE, 0600,
tunables_dir, NULL, &tunables_fops); tunables_dir, NULL, &tunables_fops);
if (!tunables_file) { if (!tunables_file) {
printk(KERN_ERR "unable to create debugfs file %s\n", pr_err("unable to create debugfs file %s\n",
UV_BAU_TUNABLES_FILE); UV_BAU_TUNABLES_FILE);
return -EINVAL; return -EINVAL;
} }
...@@ -1721,7 +1744,7 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode) ...@@ -1721,7 +1744,7 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
gpa = uv_gpa(bau_desc); gpa = uv_gpa(bau_desc);
n = uv_gpa_to_gnode(gpa); n = uv_gpa_to_gnode(gpa);
m = uv_gpa_to_offset(gpa); m = ops.bau_gpa_to_offset(gpa);
if (is_uv1_hub()) if (is_uv1_hub())
uv1 = 1; uv1 = 1;
...@@ -1736,7 +1759,7 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode) ...@@ -1736,7 +1759,7 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
memset(bd2, 0, sizeof(struct bau_desc)); memset(bd2, 0, sizeof(struct bau_desc));
if (uv1) { if (uv1) {
uv1_hdr = &bd2->header.uv1_hdr; uv1_hdr = &bd2->header.uv1_hdr;
uv1_hdr->swack_flag = 1; uv1_hdr->swack_flag = 1;
/* /*
* The base_dest_nasid set in the message header * The base_dest_nasid set in the message header
* is the nasid of the first uvhub in the partition. * is the nasid of the first uvhub in the partition.
...@@ -1745,10 +1768,10 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode) ...@@ -1745,10 +1768,10 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
* if nasid striding is being used. * if nasid striding is being used.
*/ */
uv1_hdr->base_dest_nasid = uv1_hdr->base_dest_nasid =
UV_PNODE_TO_NASID(base_pnode); UV_PNODE_TO_NASID(base_pnode);
uv1_hdr->dest_subnodeid = UV_LB_SUBNODEID; uv1_hdr->dest_subnodeid = UV_LB_SUBNODEID;
uv1_hdr->command = UV_NET_ENDPOINT_INTD; uv1_hdr->command = UV_NET_ENDPOINT_INTD;
uv1_hdr->int_both = 1; uv1_hdr->int_both = 1;
/* /*
* all others need to be set to zero: * all others need to be set to zero:
* fairness chaining multilevel count replied_to * fairness chaining multilevel count replied_to
...@@ -1759,11 +1782,11 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode) ...@@ -1759,11 +1782,11 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
* uses native mode for selective broadcasts. * uses native mode for selective broadcasts.
*/ */
uv2_3_hdr = &bd2->header.uv2_3_hdr; uv2_3_hdr = &bd2->header.uv2_3_hdr;
uv2_3_hdr->swack_flag = 1; uv2_3_hdr->swack_flag = 1;
uv2_3_hdr->base_dest_nasid = uv2_3_hdr->base_dest_nasid =
UV_PNODE_TO_NASID(base_pnode); UV_PNODE_TO_NASID(base_pnode);
uv2_3_hdr->dest_subnodeid = UV_LB_SUBNODEID; uv2_3_hdr->dest_subnodeid = UV_LB_SUBNODEID;
uv2_3_hdr->command = UV_NET_ENDPOINT_INTD; uv2_3_hdr->command = UV_NET_ENDPOINT_INTD;
} }
} }
for_each_present_cpu(cpu) { for_each_present_cpu(cpu) {
...@@ -1786,10 +1809,7 @@ static void pq_init(int node, int pnode) ...@@ -1786,10 +1809,7 @@ static void pq_init(int node, int pnode)
size_t plsize; size_t plsize;
char *cp; char *cp;
void *vp; void *vp;
unsigned long pn; unsigned long gnode, first, last, tail;
unsigned long first;
unsigned long pn_first;
unsigned long last;
struct bau_pq_entry *pqp; struct bau_pq_entry *pqp;
struct bau_control *bcp; struct bau_control *bcp;
...@@ -1810,17 +1830,25 @@ static void pq_init(int node, int pnode) ...@@ -1810,17 +1830,25 @@ static void pq_init(int node, int pnode)
bcp->bau_msg_head = pqp; bcp->bau_msg_head = pqp;
bcp->queue_last = pqp + (DEST_Q_SIZE - 1); bcp->queue_last = pqp + (DEST_Q_SIZE - 1);
} }
first = ops.bau_gpa_to_offset(uv_gpa(pqp));
last = ops.bau_gpa_to_offset(uv_gpa(pqp + (DEST_Q_SIZE - 1)));
/* /*
* need the gnode of where the memory was really allocated * Pre UV4, the gnode is required to locate the payload queue
* and the payload queue tail must be maintained by the kernel.
*/ */
pn = uv_gpa_to_gnode(uv_gpa(pqp)); bcp = &per_cpu(bau_control, smp_processor_id());
first = uv_physnodeaddr(pqp); if (bcp->uvhub_version <= 3) {
pn_first = ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | first; tail = first;
last = uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1)); gnode = uv_gpa_to_gnode(uv_gpa(pqp));
write_mmr_payload_first(pnode, pn_first); first = (gnode << UV_PAYLOADQ_GNODE_SHIFT) | tail;
write_mmr_payload_tail(pnode, first); write_mmr_payload_tail(pnode, tail);
write_mmr_payload_last(pnode, last); }
write_gmmr_sw_ack(pnode, 0xffffUL);
ops.write_payload_first(pnode, first);
ops.write_payload_last(pnode, last);
ops.write_g_sw_ack(pnode, 0xffffUL);
/* in effect, all msg_type's are set to MSG_NOOP */ /* in effect, all msg_type's are set to MSG_NOOP */
memset(pqp, 0, sizeof(struct bau_pq_entry) * DEST_Q_SIZE); memset(pqp, 0, sizeof(struct bau_pq_entry) * DEST_Q_SIZE);
...@@ -1910,8 +1938,8 @@ static void __init init_per_cpu_tunables(void) ...@@ -1910,8 +1938,8 @@ static void __init init_per_cpu_tunables(void)
bcp->complete_threshold = complete_threshold; bcp->complete_threshold = complete_threshold;
bcp->cong_response_us = congested_respns_us; bcp->cong_response_us = congested_respns_us;
bcp->cong_reps = congested_reps; bcp->cong_reps = congested_reps;
bcp->disabled_period = sec_2_cycles(disabled_period); bcp->disabled_period = sec_2_cycles(disabled_period);
bcp->giveup_limit = giveup_limit; bcp->giveup_limit = giveup_limit;
spin_lock_init(&bcp->queue_lock); spin_lock_init(&bcp->queue_lock);
spin_lock_init(&bcp->uvhub_lock); spin_lock_init(&bcp->uvhub_lock);
spin_lock_init(&bcp->disable_lock); spin_lock_init(&bcp->disable_lock);
...@@ -1940,7 +1968,7 @@ static int __init get_cpu_topology(int base_pnode, ...@@ -1940,7 +1968,7 @@ static int __init get_cpu_topology(int base_pnode,
pnode = uv_cpu_hub_info(cpu)->pnode; pnode = uv_cpu_hub_info(cpu)->pnode;
if ((pnode - base_pnode) >= UV_DISTRIBUTION_SIZE) { if ((pnode - base_pnode) >= UV_DISTRIBUTION_SIZE) {
printk(KERN_EMERG pr_emerg(
"cpu %d pnode %d-%d beyond %d; BAU disabled\n", "cpu %d pnode %d-%d beyond %d; BAU disabled\n",
cpu, pnode, base_pnode, UV_DISTRIBUTION_SIZE); cpu, pnode, base_pnode, UV_DISTRIBUTION_SIZE);
return 1; return 1;
...@@ -1965,7 +1993,7 @@ static int __init get_cpu_topology(int base_pnode, ...@@ -1965,7 +1993,7 @@ static int __init get_cpu_topology(int base_pnode,
sdp->cpu_number[sdp->num_cpus] = cpu; sdp->cpu_number[sdp->num_cpus] = cpu;
sdp->num_cpus++; sdp->num_cpus++;
if (sdp->num_cpus > MAX_CPUS_PER_SOCKET) { if (sdp->num_cpus > MAX_CPUS_PER_SOCKET) {
printk(KERN_EMERG "%d cpus per socket invalid\n", pr_emerg("%d cpus per socket invalid\n",
sdp->num_cpus); sdp->num_cpus);
return 1; return 1;
} }
...@@ -2031,15 +2059,17 @@ static int scan_sock(struct socket_desc *sdp, struct uvhub_desc *bdp, ...@@ -2031,15 +2059,17 @@ static int scan_sock(struct socket_desc *sdp, struct uvhub_desc *bdp,
bcp->uvhub_version = 2; bcp->uvhub_version = 2;
else if (is_uv3_hub()) else if (is_uv3_hub())
bcp->uvhub_version = 3; bcp->uvhub_version = 3;
else if (is_uv4_hub())
bcp->uvhub_version = 4;
else { else {
printk(KERN_EMERG "uvhub version not 1, 2 or 3\n"); pr_emerg("uvhub version not 1, 2, 3, or 4\n");
return 1; return 1;
} }
bcp->uvhub_master = *hmasterp; bcp->uvhub_master = *hmasterp;
bcp->uvhub_cpu = uv_cpu_blade_processor_id(cpu); bcp->uvhub_cpu = uv_cpu_blade_processor_id(cpu);
if (bcp->uvhub_cpu >= MAX_CPUS_PER_UVHUB) { if (bcp->uvhub_cpu >= MAX_CPUS_PER_UVHUB) {
printk(KERN_EMERG "%d cpus per uvhub invalid\n", pr_emerg("%d cpus per uvhub invalid\n",
bcp->uvhub_cpu); bcp->uvhub_cpu);
return 1; return 1;
} }
...@@ -2094,7 +2124,8 @@ static int __init init_per_cpu(int nuvhubs, int base_part_pnode) ...@@ -2094,7 +2124,8 @@ static int __init init_per_cpu(int nuvhubs, int base_part_pnode)
void *vp; void *vp;
struct uvhub_desc *uvhub_descs; struct uvhub_desc *uvhub_descs;
timeout_us = calculate_destination_timeout(); if (is_uv3_hub() || is_uv2_hub() || is_uv1_hub())
timeout_us = calculate_destination_timeout();
vp = kmalloc(nuvhubs * sizeof(struct uvhub_desc), GFP_KERNEL); vp = kmalloc(nuvhubs * sizeof(struct uvhub_desc), GFP_KERNEL);
uvhub_descs = (struct uvhub_desc *)vp; uvhub_descs = (struct uvhub_desc *)vp;
...@@ -2134,6 +2165,15 @@ static int __init uv_bau_init(void) ...@@ -2134,6 +2165,15 @@ static int __init uv_bau_init(void)
if (!is_uv_system()) if (!is_uv_system())
return 0; return 0;
if (is_uv4_hub())
ops = uv4_bau_ops;
else if (is_uv3_hub())
ops = uv123_bau_ops;
else if (is_uv2_hub())
ops = uv123_bau_ops;
else if (is_uv1_hub())
ops = uv123_bau_ops;
for_each_possible_cpu(cur_cpu) { for_each_possible_cpu(cur_cpu) {
mask = &per_cpu(uv_flush_tlb_mask, cur_cpu); mask = &per_cpu(uv_flush_tlb_mask, cur_cpu);
zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu)); zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
...@@ -2149,7 +2189,9 @@ static int __init uv_bau_init(void) ...@@ -2149,7 +2189,9 @@ static int __init uv_bau_init(void)
uv_base_pnode = uv_blade_to_pnode(uvhub); uv_base_pnode = uv_blade_to_pnode(uvhub);
} }
enable_timeouts(); /* software timeouts are not supported on UV4 */
if (is_uv3_hub() || is_uv2_hub() || is_uv1_hub())
enable_timeouts();
if (init_per_cpu(nuvhubs, uv_base_pnode)) { if (init_per_cpu(nuvhubs, uv_base_pnode)) {
set_bau_off(); set_bau_off();
......
...@@ -60,8 +60,13 @@ static struct pci_platform_pm_ops mid_pci_platform_pm = { ...@@ -60,8 +60,13 @@ static struct pci_platform_pm_ops mid_pci_platform_pm = {
#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, } #define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
/*
* This table should be in sync with the one in
* arch/x86/platform/intel-mid/pwr.c.
*/
static const struct x86_cpu_id lpss_cpu_ids[] = { static const struct x86_cpu_id lpss_cpu_ids[] = {
ICPU(INTEL_FAM6_ATOM_MERRIFIELD1), ICPU(INTEL_FAM6_ATOM_PENWELL),
ICPU(INTEL_FAM6_ATOM_MERRIFIELD),
{} {}
}; };
......
...@@ -1154,8 +1154,8 @@ static const struct x86_cpu_id rapl_ids[] __initconst = { ...@@ -1154,8 +1154,8 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT1, rapl_defaults_byt), RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT1, rapl_defaults_byt),
RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT, rapl_defaults_cht), RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT, rapl_defaults_cht),
RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD1, rapl_defaults_tng), RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD, rapl_defaults_tng),
RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD2, rapl_defaults_ann), RAPL_CPU(INTEL_FAM6_ATOM_MOOREFIELD, rapl_defaults_ann),
RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT, rapl_defaults_core), RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON, rapl_defaults_core), RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON, rapl_defaults_core),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment