Commit e4f79000 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'powerpc-6.8-5' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc fixes from Michael Ellerman:

 - Fix IOMMU table initialisation when doing kdump over SR-IOV

 - Fix incorrect RTAS function name for resetting TCE tables

 - Fix fpu_signal selftest failures since a recent change

Thanks to Gaurav Batra and Nathan Lynch.

* tag 'powerpc-6.8-5' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  selftests/powerpc: Fix fpu_signal failures
  powerpc/rtas: use correct function name for resetting TCE tables
  powerpc/pseries/iommu: IOMMU table is not initialized for kdump over SR-IOV
parents 73d35f83 380cb2f4
...@@ -69,7 +69,7 @@ enum rtas_function_index { ...@@ -69,7 +69,7 @@ enum rtas_function_index {
RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE, RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE,
RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE2, RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE2,
RTAS_FNIDX__IBM_REMOVE_PE_DMA_WINDOW, RTAS_FNIDX__IBM_REMOVE_PE_DMA_WINDOW,
RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOWS, RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOW,
RTAS_FNIDX__IBM_SCAN_LOG_DUMP, RTAS_FNIDX__IBM_SCAN_LOG_DUMP,
RTAS_FNIDX__IBM_SET_DYNAMIC_INDICATOR, RTAS_FNIDX__IBM_SET_DYNAMIC_INDICATOR,
RTAS_FNIDX__IBM_SET_EEH_OPTION, RTAS_FNIDX__IBM_SET_EEH_OPTION,
...@@ -164,7 +164,7 @@ typedef struct { ...@@ -164,7 +164,7 @@ typedef struct {
#define RTAS_FN_IBM_READ_SLOT_RESET_STATE rtas_fn_handle(RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE) #define RTAS_FN_IBM_READ_SLOT_RESET_STATE rtas_fn_handle(RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE)
#define RTAS_FN_IBM_READ_SLOT_RESET_STATE2 rtas_fn_handle(RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE2) #define RTAS_FN_IBM_READ_SLOT_RESET_STATE2 rtas_fn_handle(RTAS_FNIDX__IBM_READ_SLOT_RESET_STATE2)
#define RTAS_FN_IBM_REMOVE_PE_DMA_WINDOW rtas_fn_handle(RTAS_FNIDX__IBM_REMOVE_PE_DMA_WINDOW) #define RTAS_FN_IBM_REMOVE_PE_DMA_WINDOW rtas_fn_handle(RTAS_FNIDX__IBM_REMOVE_PE_DMA_WINDOW)
#define RTAS_FN_IBM_RESET_PE_DMA_WINDOWS rtas_fn_handle(RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOWS) #define RTAS_FN_IBM_RESET_PE_DMA_WINDOW rtas_fn_handle(RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOW)
#define RTAS_FN_IBM_SCAN_LOG_DUMP rtas_fn_handle(RTAS_FNIDX__IBM_SCAN_LOG_DUMP) #define RTAS_FN_IBM_SCAN_LOG_DUMP rtas_fn_handle(RTAS_FNIDX__IBM_SCAN_LOG_DUMP)
#define RTAS_FN_IBM_SET_DYNAMIC_INDICATOR rtas_fn_handle(RTAS_FNIDX__IBM_SET_DYNAMIC_INDICATOR) #define RTAS_FN_IBM_SET_DYNAMIC_INDICATOR rtas_fn_handle(RTAS_FNIDX__IBM_SET_DYNAMIC_INDICATOR)
#define RTAS_FN_IBM_SET_EEH_OPTION rtas_fn_handle(RTAS_FNIDX__IBM_SET_EEH_OPTION) #define RTAS_FN_IBM_SET_EEH_OPTION rtas_fn_handle(RTAS_FNIDX__IBM_SET_EEH_OPTION)
......
...@@ -375,8 +375,13 @@ static struct rtas_function rtas_function_table[] __ro_after_init = { ...@@ -375,8 +375,13 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
[RTAS_FNIDX__IBM_REMOVE_PE_DMA_WINDOW] = { [RTAS_FNIDX__IBM_REMOVE_PE_DMA_WINDOW] = {
.name = "ibm,remove-pe-dma-window", .name = "ibm,remove-pe-dma-window",
}, },
[RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOWS] = { [RTAS_FNIDX__IBM_RESET_PE_DMA_WINDOW] = {
.name = "ibm,reset-pe-dma-windows", /*
* Note: PAPR+ v2.13 7.3.31.4.1 spells this as
* "ibm,reset-pe-dma-windows" (plural), but RTAS
* implementations use the singular form in practice.
*/
.name = "ibm,reset-pe-dma-window",
}, },
[RTAS_FNIDX__IBM_SCAN_LOG_DUMP] = { [RTAS_FNIDX__IBM_SCAN_LOG_DUMP] = {
.name = "ibm,scan-log-dump", .name = "ibm,scan-log-dump",
......
...@@ -574,29 +574,6 @@ static void iommu_table_setparms(struct pci_controller *phb, ...@@ -574,29 +574,6 @@ static void iommu_table_setparms(struct pci_controller *phb,
struct iommu_table_ops iommu_table_lpar_multi_ops; struct iommu_table_ops iommu_table_lpar_multi_ops;
/*
* iommu_table_setparms_lpar
*
* Function: On pSeries LPAR systems, return TCE table info, given a pci bus.
*/
static void iommu_table_setparms_lpar(struct pci_controller *phb,
struct device_node *dn,
struct iommu_table *tbl,
struct iommu_table_group *table_group,
const __be32 *dma_window)
{
unsigned long offset, size, liobn;
of_parse_dma_window(dn, dma_window, &liobn, &offset, &size);
iommu_table_setparms_common(tbl, phb->bus->number, liobn, offset, size, IOMMU_PAGE_SHIFT_4K, NULL,
&iommu_table_lpar_multi_ops);
table_group->tce32_start = offset;
table_group->tce32_size = size;
}
struct iommu_table_ops iommu_table_pseries_ops = { struct iommu_table_ops iommu_table_pseries_ops = {
.set = tce_build_pSeries, .set = tce_build_pSeries,
.clear = tce_free_pSeries, .clear = tce_free_pSeries,
...@@ -724,26 +701,71 @@ struct iommu_table_ops iommu_table_lpar_multi_ops = { ...@@ -724,26 +701,71 @@ struct iommu_table_ops iommu_table_lpar_multi_ops = {
* dynamic 64bit DMA window, walking up the device tree. * dynamic 64bit DMA window, walking up the device tree.
*/ */
static struct device_node *pci_dma_find(struct device_node *dn, static struct device_node *pci_dma_find(struct device_node *dn,
const __be32 **dma_window) struct dynamic_dma_window_prop *prop)
{ {
const __be32 *dw = NULL; const __be32 *default_prop = NULL;
const __be32 *ddw_prop = NULL;
struct device_node *rdn = NULL;
bool default_win = false, ddw_win = false;
for ( ; dn && PCI_DN(dn); dn = dn->parent) { for ( ; dn && PCI_DN(dn); dn = dn->parent) {
dw = of_get_property(dn, "ibm,dma-window", NULL); default_prop = of_get_property(dn, "ibm,dma-window", NULL);
if (dw) { if (default_prop) {
if (dma_window) rdn = dn;
*dma_window = dw; default_win = true;
return dn; }
ddw_prop = of_get_property(dn, DIRECT64_PROPNAME, NULL);
if (ddw_prop) {
rdn = dn;
ddw_win = true;
break;
}
ddw_prop = of_get_property(dn, DMA64_PROPNAME, NULL);
if (ddw_prop) {
rdn = dn;
ddw_win = true;
break;
} }
dw = of_get_property(dn, DIRECT64_PROPNAME, NULL);
if (dw) /* At least found default window, which is the case for normal boot */
return dn; if (default_win)
dw = of_get_property(dn, DMA64_PROPNAME, NULL); break;
if (dw)
return dn;
} }
return NULL; /* For PCI devices there will always be a DMA window, either on the device
* or parent bus
*/
WARN_ON(!(default_win | ddw_win));
/* caller doesn't want to get DMA window property */
if (!prop)
return rdn;
/* parse DMA window property. During normal system boot, only default
* DMA window is passed in OF. But, for kdump, a dedicated adapter might
* have both default and DDW in FDT. In this scenario, DDW takes precedence
* over default window.
*/
if (ddw_win) {
struct dynamic_dma_window_prop *p;
p = (struct dynamic_dma_window_prop *)ddw_prop;
prop->liobn = p->liobn;
prop->dma_base = p->dma_base;
prop->tce_shift = p->tce_shift;
prop->window_shift = p->window_shift;
} else if (default_win) {
unsigned long offset, size, liobn;
of_parse_dma_window(rdn, default_prop, &liobn, &offset, &size);
prop->liobn = cpu_to_be32((u32)liobn);
prop->dma_base = cpu_to_be64(offset);
prop->tce_shift = cpu_to_be32(IOMMU_PAGE_SHIFT_4K);
prop->window_shift = cpu_to_be32(order_base_2(size));
}
return rdn;
} }
static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
...@@ -751,17 +773,20 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) ...@@ -751,17 +773,20 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
struct iommu_table *tbl; struct iommu_table *tbl;
struct device_node *dn, *pdn; struct device_node *dn, *pdn;
struct pci_dn *ppci; struct pci_dn *ppci;
const __be32 *dma_window = NULL; struct dynamic_dma_window_prop prop;
dn = pci_bus_to_OF_node(bus); dn = pci_bus_to_OF_node(bus);
pr_debug("pci_dma_bus_setup_pSeriesLP: setting up bus %pOF\n", pr_debug("pci_dma_bus_setup_pSeriesLP: setting up bus %pOF\n",
dn); dn);
pdn = pci_dma_find(dn, &dma_window); pdn = pci_dma_find(dn, &prop);
if (dma_window == NULL) /* In PPC architecture, there will always be DMA window on bus or one of the
pr_debug(" no ibm,dma-window property !\n"); * parent bus. During reboot, there will be ibm,dma-window property to
* define DMA window. For kdump, there will at least be default window or DDW
* or both.
*/
ppci = PCI_DN(pdn); ppci = PCI_DN(pdn);
...@@ -771,13 +796,24 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus) ...@@ -771,13 +796,24 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
if (!ppci->table_group) { if (!ppci->table_group) {
ppci->table_group = iommu_pseries_alloc_group(ppci->phb->node); ppci->table_group = iommu_pseries_alloc_group(ppci->phb->node);
tbl = ppci->table_group->tables[0]; tbl = ppci->table_group->tables[0];
if (dma_window) {
iommu_table_setparms_lpar(ppci->phb, pdn, tbl,
ppci->table_group, dma_window);
if (!iommu_init_table(tbl, ppci->phb->node, 0, 0)) iommu_table_setparms_common(tbl, ppci->phb->bus->number,
panic("Failed to initialize iommu table"); be32_to_cpu(prop.liobn),
} be64_to_cpu(prop.dma_base),
1ULL << be32_to_cpu(prop.window_shift),
be32_to_cpu(prop.tce_shift), NULL,
&iommu_table_lpar_multi_ops);
/* Only for normal boot with default window. Doesn't matter even
* if we set these with DDW which is 64bit during kdump, since
* these will not be used during kdump.
*/
ppci->table_group->tce32_start = be64_to_cpu(prop.dma_base);
ppci->table_group->tce32_size = 1 << be32_to_cpu(prop.window_shift);
if (!iommu_init_table(tbl, ppci->phb->node, 0, 0))
panic("Failed to initialize iommu table");
iommu_register_group(ppci->table_group, iommu_register_group(ppci->table_group,
pci_domain_nr(bus), 0); pci_domain_nr(bus), 0);
pr_debug(" created table: %p\n", ppci->table_group); pr_debug(" created table: %p\n", ppci->table_group);
...@@ -968,6 +1004,12 @@ static void find_existing_ddw_windows_named(const char *name) ...@@ -968,6 +1004,12 @@ static void find_existing_ddw_windows_named(const char *name)
continue; continue;
} }
/* If at the time of system initialization, there are DDWs in OF,
* it means this is during kexec. DDW could be direct or dynamic.
* We will just mark DDWs as "dynamic" since this is kdump path,
* no need to worry about perforance. ddw_list_new_entry() will
* set window->direct = false.
*/
window = ddw_list_new_entry(pdn, dma64); window = ddw_list_new_entry(pdn, dma64);
if (!window) { if (!window) {
of_node_put(pdn); of_node_put(pdn);
...@@ -1524,8 +1566,8 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) ...@@ -1524,8 +1566,8 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
{ {
struct device_node *pdn, *dn; struct device_node *pdn, *dn;
struct iommu_table *tbl; struct iommu_table *tbl;
const __be32 *dma_window = NULL;
struct pci_dn *pci; struct pci_dn *pci;
struct dynamic_dma_window_prop prop;
pr_debug("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev)); pr_debug("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
...@@ -1538,7 +1580,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) ...@@ -1538,7 +1580,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
dn = pci_device_to_OF_node(dev); dn = pci_device_to_OF_node(dev);
pr_debug(" node is %pOF\n", dn); pr_debug(" node is %pOF\n", dn);
pdn = pci_dma_find(dn, &dma_window); pdn = pci_dma_find(dn, &prop);
if (!pdn || !PCI_DN(pdn)) { if (!pdn || !PCI_DN(pdn)) {
printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: " printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: "
"no DMA window found for pci dev=%s dn=%pOF\n", "no DMA window found for pci dev=%s dn=%pOF\n",
...@@ -1551,8 +1593,20 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) ...@@ -1551,8 +1593,20 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
if (!pci->table_group) { if (!pci->table_group) {
pci->table_group = iommu_pseries_alloc_group(pci->phb->node); pci->table_group = iommu_pseries_alloc_group(pci->phb->node);
tbl = pci->table_group->tables[0]; tbl = pci->table_group->tables[0];
iommu_table_setparms_lpar(pci->phb, pdn, tbl,
pci->table_group, dma_window); iommu_table_setparms_common(tbl, pci->phb->bus->number,
be32_to_cpu(prop.liobn),
be64_to_cpu(prop.dma_base),
1ULL << be32_to_cpu(prop.window_shift),
be32_to_cpu(prop.tce_shift), NULL,
&iommu_table_lpar_multi_ops);
/* Only for normal boot with default window. Doesn't matter even
* if we set these with DDW which is 64bit during kdump, since
* these will not be used during kdump.
*/
pci->table_group->tce32_start = be64_to_cpu(prop.dma_base);
pci->table_group->tce32_size = 1 << be32_to_cpu(prop.window_shift);
iommu_init_table(tbl, pci->phb->node, 0, 0); iommu_init_table(tbl, pci->phb->node, 0, 0);
iommu_register_group(pci->table_group, iommu_register_group(pci->table_group,
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <pthread.h> #include <pthread.h>
#include "utils.h" #include "utils.h"
#include "fpu.h"
/* Number of times each thread should receive the signal */ /* Number of times each thread should receive the signal */
#define ITERATIONS 10 #define ITERATIONS 10
...@@ -27,9 +28,7 @@ ...@@ -27,9 +28,7 @@
*/ */
#define THREAD_FACTOR 8 #define THREAD_FACTOR 8
__thread double darray[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, __thread double darray[32];
1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0,
2.1};
bool bad_context; bool bad_context;
int threads_starting; int threads_starting;
...@@ -43,9 +42,9 @@ void signal_fpu_sig(int sig, siginfo_t *info, void *context) ...@@ -43,9 +42,9 @@ void signal_fpu_sig(int sig, siginfo_t *info, void *context)
ucontext_t *uc = context; ucontext_t *uc = context;
mcontext_t *mc = &uc->uc_mcontext; mcontext_t *mc = &uc->uc_mcontext;
/* Only the non volatiles were loaded up */ // Don't check f30/f31, they're used as scratches in check_all_fprs()
for (i = 14; i < 32; i++) { for (i = 0; i < 30; i++) {
if (mc->fp_regs[i] != darray[i - 14]) { if (mc->fp_regs[i] != darray[i]) {
bad_context = true; bad_context = true;
break; break;
} }
...@@ -54,7 +53,6 @@ void signal_fpu_sig(int sig, siginfo_t *info, void *context) ...@@ -54,7 +53,6 @@ void signal_fpu_sig(int sig, siginfo_t *info, void *context)
void *signal_fpu_c(void *p) void *signal_fpu_c(void *p)
{ {
int i;
long rc; long rc;
struct sigaction act; struct sigaction act;
act.sa_sigaction = signal_fpu_sig; act.sa_sigaction = signal_fpu_sig;
...@@ -64,9 +62,7 @@ void *signal_fpu_c(void *p) ...@@ -64,9 +62,7 @@ void *signal_fpu_c(void *p)
return p; return p;
srand(pthread_self()); srand(pthread_self());
for (i = 0; i < 21; i++) randomise_darray(darray, ARRAY_SIZE(darray));
darray[i] = rand();
rc = preempt_fpu(darray, &threads_starting, &running); rc = preempt_fpu(darray, &threads_starting, &running);
return (void *) rc; return (void *) rc;
......
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