未验证 提交 570b6bca 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!411 intel: backport isst issue fix and other update to align with upstream 6.0

Merge Pull Request from: @jiayingbao 
 
there is write cpu power error reported in recent test and the issue found fix patch platform-x86-ISST-Allow-configurable-offset-range needed.
and there is other important fix on platform-x86-ISST-PUNIT-device-mapping-with-Sub-NUMA.
so with this PR, it will align isst driver with upstream 6.0.
update: add one more fix d36d4a1d

upstream patch list:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1e42de8e53d32bbd7a732df49d872a30b4f888b4
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=aa2ddd24257213bdfd2f65058531810ac57455dc
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d36d4a1d75d2a8bd14ec00d5cb0ce166f6886146
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a552f204b050b213b1e41a5134a0d2726c9a2ec1
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=761f0ee0e84b4c18535c6d17890ccc9f5c617e8d
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7c88ab5715a265d5dde06e4e1b0dd4370d911372
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0cd3f561efa9adce840140720e0581355db3e554
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=55879dc4d095232609fe81498c1b43f042708eef
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9a1aac8a96dc014bec49806a7a964bf2fdbd315f
 
 
Link:https://gitee.com/openeuler/kernel/pulls/411 

Reviewed-by: Jason Zeng <jason.zeng@intel.com> 
Reviewed-by: Zheng Zengkai <zhengzengkai@huawei.com> 
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> 
......@@ -265,9 +265,9 @@ static int isst_if_get_platform_info(void __user *argp)
{
struct isst_if_platform_info info;
info.api_version = ISST_IF_API_VERSION,
info.driver_version = ISST_IF_DRIVER_VERSION,
info.max_cmds_per_ioctl = ISST_IF_CMD_LIMIT,
info.api_version = ISST_IF_API_VERSION;
info.driver_version = ISST_IF_DRIVER_VERSION;
info.max_cmds_per_ioctl = ISST_IF_CMD_LIMIT;
info.mbox_supported = punit_callbacks[ISST_IF_DEV_MBOX].registered;
info.mmio_supported = punit_callbacks[ISST_IF_DEV_MMIO].registered;
......@@ -277,14 +277,88 @@ static int isst_if_get_platform_info(void __user *argp)
return 0;
}
#define ISST_MAX_BUS_NUMBER 2
struct isst_if_cpu_info {
/* For BUS 0 and BUS 1 only, which we need for PUNIT interface */
int bus_info[2];
int bus_info[ISST_MAX_BUS_NUMBER];
struct pci_dev *pci_dev[ISST_MAX_BUS_NUMBER];
int punit_cpu_id;
int numa_node;
};
struct isst_if_pkg_info {
struct pci_dev *pci_dev[ISST_MAX_BUS_NUMBER];
};
static struct isst_if_cpu_info *isst_cpu_info;
static struct isst_if_pkg_info *isst_pkg_info;
#define ISST_MAX_PCI_DOMAINS 8
static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn)
{
struct pci_dev *matched_pci_dev = NULL;
struct pci_dev *pci_dev = NULL;
int no_matches = 0, pkg_id;
int i, bus_number;
if (bus_no < 0 || bus_no >= ISST_MAX_BUS_NUMBER || cpu < 0 ||
cpu >= nr_cpu_ids || cpu >= num_possible_cpus())
return NULL;
pkg_id = topology_physical_package_id(cpu);
bus_number = isst_cpu_info[cpu].bus_info[bus_no];
if (bus_number < 0)
return NULL;
for (i = 0; i < ISST_MAX_PCI_DOMAINS; ++i) {
struct pci_dev *_pci_dev;
int node;
_pci_dev = pci_get_domain_bus_and_slot(i, bus_number, PCI_DEVFN(dev, fn));
if (!_pci_dev)
continue;
++no_matches;
if (!matched_pci_dev)
matched_pci_dev = _pci_dev;
node = dev_to_node(&_pci_dev->dev);
if (node == NUMA_NO_NODE) {
pr_info("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n",
cpu, bus_no, dev, fn);
continue;
}
if (node == isst_cpu_info[cpu].numa_node) {
isst_pkg_info[pkg_id].pci_dev[bus_no] = _pci_dev;
pci_dev = _pci_dev;
break;
}
}
/*
* If there is no numa matched pci_dev, then there can be following cases:
* 1. CONFIG_NUMA is not defined: In this case if there is only single device
* match, then we don't need numa information. Simply return last match.
* Othewise return NULL.
* 2. NUMA information is not exposed via _SEG method. In this case it is similar
* to case 1.
* 3. Numa information doesn't match with CPU numa node and more than one match
* return NULL.
*/
if (!pci_dev && no_matches == 1)
pci_dev = matched_pci_dev;
/* Return pci_dev pointer for any matched CPU in the package */
if (!pci_dev)
pci_dev = isst_pkg_info[pkg_id].pci_dev[bus_no];
return pci_dev;
}
/**
* isst_if_get_pci_dev() - Get the PCI device instance for a CPU
......@@ -300,17 +374,18 @@ static struct isst_if_cpu_info *isst_cpu_info;
*/
struct pci_dev *isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn)
{
int bus_number;
struct pci_dev *pci_dev;
if (bus_no < 0 || bus_no > 1 || cpu < 0 || cpu >= nr_cpu_ids ||
cpu >= num_possible_cpus())
if (bus_no < 0 || bus_no >= ISST_MAX_BUS_NUMBER || cpu < 0 ||
cpu >= nr_cpu_ids || cpu >= num_possible_cpus())
return NULL;
bus_number = isst_cpu_info[cpu].bus_info[bus_no];
if (bus_number < 0)
return NULL;
pci_dev = isst_cpu_info[cpu].pci_dev[bus_no];
if (pci_dev && pci_dev->devfn == PCI_DEVFN(dev, fn))
return pci_dev;
return pci_get_domain_bus_and_slot(0, bus_number, PCI_DEVFN(dev, fn));
return _isst_if_get_pci_dev(cpu, bus_no, dev, fn);
}
EXPORT_SYMBOL_GPL(isst_if_get_pci_dev);
......@@ -319,6 +394,8 @@ static int isst_if_cpu_online(unsigned int cpu)
u64 data;
int ret;
isst_cpu_info[cpu].numa_node = cpu_to_node(cpu);
ret = rdmsrl_safe(MSR_CPU_BUS_NUMBER, &data);
if (ret) {
/* This is not a fatal error on MSR mailbox only I/F */
......@@ -327,6 +404,8 @@ static int isst_if_cpu_online(unsigned int cpu)
} else {
isst_cpu_info[cpu].bus_info[0] = data & 0xff;
isst_cpu_info[cpu].bus_info[1] = (data >> 8) & 0xff;
isst_cpu_info[cpu].pci_dev[0] = _isst_if_get_pci_dev(cpu, 0, 0, 1);
isst_cpu_info[cpu].pci_dev[1] = _isst_if_get_pci_dev(cpu, 1, 30, 1);
}
ret = rdmsrl_safe(MSR_THREAD_ID_INFO, &data);
......@@ -353,10 +432,19 @@ static int isst_if_cpu_info_init(void)
if (!isst_cpu_info)
return -ENOMEM;
isst_pkg_info = kcalloc(topology_max_packages(),
sizeof(*isst_pkg_info),
GFP_KERNEL);
if (!isst_pkg_info) {
kfree(isst_cpu_info);
return -ENOMEM;
}
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"platform/x86/isst-if:online",
isst_if_cpu_online, NULL);
if (ret < 0) {
kfree(isst_pkg_info);
kfree(isst_cpu_info);
return ret;
}
......@@ -369,6 +457,7 @@ static int isst_if_cpu_info_init(void)
static void isst_if_cpu_info_exit(void)
{
cpuhp_remove_state(isst_if_online_id);
kfree(isst_pkg_info);
kfree(isst_cpu_info);
};
......
......@@ -10,11 +10,11 @@
#ifndef __ISST_IF_COMMON_H
#define __ISST_IF_COMMON_H
#define INTEL_RAPL_PRIO_DEVID_0 0x3451
#define INTEL_CFG_MBOX_DEVID_0 0x3459
#define PCI_DEVICE_ID_INTEL_RAPL_PRIO_DEVID_0 0x3451
#define PCI_DEVICE_ID_INTEL_CFG_MBOX_DEVID_0 0x3459
#define INTEL_RAPL_PRIO_DEVID_1 0x3251
#define INTEL_CFG_MBOX_DEVID_1 0x3259
#define PCI_DEVICE_ID_INTEL_RAPL_PRIO_DEVID_1 0x3251
#define PCI_DEVICE_ID_INTEL_CFG_MBOX_DEVID_1 0x3259
/*
* Validate maximum commands in a single request.
......
......@@ -159,8 +159,8 @@ static long isst_if_mbox_proc_cmd(u8 *cmd_ptr, int *write_only, int resume)
}
static const struct pci_device_id isst_if_mbox_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_CFG_MBOX_DEVID_0)},
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_CFG_MBOX_DEVID_1)},
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CFG_MBOX_DEVID_0)},
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CFG_MBOX_DEVID_1)},
{ 0 },
};
MODULE_DEVICE_TABLE(pci, isst_if_mbox_ids);
......
......@@ -20,15 +20,21 @@ struct isst_mmio_range {
int end;
};
struct isst_mmio_range mmio_range[] = {
static struct isst_mmio_range mmio_range_devid_0[] = {
{0x04, 0x14},
{0x20, 0xD0},
};
static struct isst_mmio_range mmio_range_devid_1[] = {
{0x04, 0x14},
{0x20, 0x11C},
};
struct isst_if_device {
void __iomem *punit_mmio;
u32 range_0[5];
u32 range_1[45];
u32 range_1[64];
struct isst_mmio_range *mmio_range;
struct mutex mutex;
};
......@@ -39,7 +45,8 @@ static long isst_if_mmio_rd_wr(u8 *cmd_ptr, int *write_only, int resume)
struct pci_dev *pdev;
io_reg = (struct isst_if_io_reg *)cmd_ptr;
if (io_reg->reg < 0x04 || io_reg->reg > 0xD0)
if (io_reg->reg % 4)
return -EINVAL;
if (io_reg->read_write && !capable(CAP_SYS_ADMIN))
......@@ -53,6 +60,10 @@ static long isst_if_mmio_rd_wr(u8 *cmd_ptr, int *write_only, int resume)
if (!punit_dev)
return -EINVAL;
if (io_reg->reg < punit_dev->mmio_range[0].beg ||
io_reg->reg > punit_dev->mmio_range[1].end)
return -EINVAL;
/*
* Ensure that operation is complete on a PCI device to avoid read
* write race by using per PCI device mutex.
......@@ -71,8 +82,8 @@ static long isst_if_mmio_rd_wr(u8 *cmd_ptr, int *write_only, int resume)
}
static const struct pci_device_id isst_if_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_RAPL_PRIO_DEVID_0)},
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_RAPL_PRIO_DEVID_1)},
{ PCI_DEVICE_DATA(INTEL, RAPL_PRIO_DEVID_0, &mmio_range_devid_0)},
{ PCI_DEVICE_DATA(INTEL, RAPL_PRIO_DEVID_1, &mmio_range_devid_1)},
{ 0 },
};
MODULE_DEVICE_TABLE(pci, isst_if_ids);
......@@ -109,6 +120,7 @@ static int isst_if_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
mutex_init(&punit_dev->mutex);
pci_set_drvdata(pdev, punit_dev);
punit_dev->mmio_range = (struct isst_mmio_range *) ent->driver_data;
memset(&cb, 0, sizeof(cb));
cb.cmd_size = sizeof(struct isst_if_io_reg);
......@@ -138,10 +150,15 @@ static int __maybe_unused isst_if_suspend(struct device *device)
for (i = 0; i < ARRAY_SIZE(punit_dev->range_0); ++i)
punit_dev->range_0[i] = readl(punit_dev->punit_mmio +
mmio_range[0].beg + 4 * i);
for (i = 0; i < ARRAY_SIZE(punit_dev->range_1); ++i)
punit_dev->range_1[i] = readl(punit_dev->punit_mmio +
mmio_range[1].beg + 4 * i);
punit_dev->mmio_range[0].beg + 4 * i);
for (i = 0; i < ARRAY_SIZE(punit_dev->range_1); ++i) {
u32 addr;
addr = punit_dev->mmio_range[1].beg + 4 * i;
if (addr > punit_dev->mmio_range[1].end)
break;
punit_dev->range_1[i] = readl(punit_dev->punit_mmio + addr);
}
return 0;
}
......@@ -153,10 +170,16 @@ static int __maybe_unused isst_if_resume(struct device *device)
for (i = 0; i < ARRAY_SIZE(punit_dev->range_0); ++i)
writel(punit_dev->range_0[i], punit_dev->punit_mmio +
mmio_range[0].beg + 4 * i);
for (i = 0; i < ARRAY_SIZE(punit_dev->range_1); ++i)
writel(punit_dev->range_1[i], punit_dev->punit_mmio +
mmio_range[1].beg + 4 * i);
punit_dev->mmio_range[0].beg + 4 * i);
for (i = 0; i < ARRAY_SIZE(punit_dev->range_1); ++i) {
u32 addr;
addr = punit_dev->mmio_range[1].beg + 4 * i;
if (addr > punit_dev->mmio_range[1].end)
break;
writel(punit_dev->range_1[i], punit_dev->punit_mmio + addr);
}
return 0;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册