Skip to content

Commit 71ba41c

Browse files
sebottMartin Schwidefsky
authored andcommitted
s390/pci: provide support for MIO instructions
Provide support for PCI I/O instructions that work on mapped IO addresses. Signed-off-by: Sebastian Ott <[email protected]> Signed-off-by: Martin Schwidefsky <[email protected]>
1 parent c475f17 commit 71ba41c

File tree

7 files changed

+294
-31
lines changed

7 files changed

+294
-31
lines changed

arch/s390/include/asm/io.h

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,8 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr);
3030
#define ioremap_wc ioremap_nocache
3131
#define ioremap_wt ioremap_nocache
3232

33-
static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
34-
{
35-
return (void __iomem *) offset;
36-
}
37-
38-
static inline void iounmap(volatile void __iomem *addr)
39-
{
40-
}
33+
void __iomem *ioremap(unsigned long offset, unsigned long size);
34+
void iounmap(volatile void __iomem *addr);
4135

4236
static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
4337
{
@@ -57,14 +51,17 @@ static inline void ioport_unmap(void __iomem *p)
5751
* the corresponding device and create the mapping cookie.
5852
*/
5953
#define pci_iomap pci_iomap
54+
#define pci_iomap_range pci_iomap_range
6055
#define pci_iounmap pci_iounmap
61-
#define pci_iomap_wc pci_iomap
62-
#define pci_iomap_wc_range pci_iomap_range
56+
#define pci_iomap_wc pci_iomap_wc
57+
#define pci_iomap_wc_range pci_iomap_wc_range
6358

6459
#define memcpy_fromio(dst, src, count) zpci_memcpy_fromio(dst, src, count)
6560
#define memcpy_toio(dst, src, count) zpci_memcpy_toio(dst, src, count)
6661
#define memset_io(dst, val, count) zpci_memset_io(dst, val, count)
6762

63+
#define mmiowb() zpci_barrier()
64+
6865
#define __raw_readb zpci_read_u8
6966
#define __raw_readw zpci_read_u16
7067
#define __raw_readl zpci_read_u32

arch/s390/include/asm/pci.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ enum zpci_state {
8686

8787
struct zpci_bar_struct {
8888
struct resource *res; /* bus resource */
89+
void __iomem *mio_wb;
90+
void __iomem *mio_wt;
8991
u32 val; /* bar start & 3 flag bits */
9092
u16 map_idx; /* index into bar mapping array */
9193
u8 size; /* order 2 exponent */
@@ -135,6 +137,7 @@ struct zpci_dev {
135137
struct iommu_device iommu_dev; /* IOMMU core handle */
136138

137139
char res_name[16];
140+
bool mio_capable;
138141
struct zpci_bar_struct bars[PCI_BAR_COUNT];
139142

140143
u64 start_dma; /* Start of available DMA addresses */

arch/s390/include/asm/pci_clp.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ struct clp_fh_list_entry {
4343

4444
#define CLP_SET_ENABLE_PCI_FN 0 /* Yes, 0 enables it */
4545
#define CLP_SET_DISABLE_PCI_FN 1 /* Yes, 1 disables it */
46+
#define CLP_SET_ENABLE_MIO 2
47+
#define CLP_SET_DISABLE_MIO 3
4648

4749
#define CLP_UTIL_STR_LEN 64
4850
#define CLP_PFIP_NR_SEGMENTS 4
@@ -80,7 +82,8 @@ struct clp_req_query_pci {
8082
struct clp_rsp_query_pci {
8183
struct clp_rsp_hdr hdr;
8284
u16 vfn; /* virtual fn number */
83-
u16 : 7;
85+
u16 : 6;
86+
u16 mio_addr_avail : 1;
8487
u16 util_str_avail : 1; /* utility string available? */
8588
u16 pfgid : 8; /* pci function group id */
8689
u32 fid; /* pci function id */
@@ -96,6 +99,15 @@ struct clp_rsp_query_pci {
9699
u32 reserved[11];
97100
u32 uid; /* user defined id */
98101
u8 util_str[CLP_UTIL_STR_LEN]; /* utility string */
102+
u32 reserved2[16];
103+
u32 mio_valid : 6;
104+
u32 : 26;
105+
u32 : 32;
106+
struct {
107+
u64 wb;
108+
u64 wt;
109+
} addr[PCI_BAR_COUNT];
110+
u32 reserved3[6];
99111
} __packed;
100112

101113
/* Query PCI function group request */

arch/s390/include/asm/pci_insn.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#ifndef _ASM_S390_PCI_INSN_H
33
#define _ASM_S390_PCI_INSN_H
44

5+
#include <linux/jump_label.h>
6+
57
/* Load/Store status codes */
68
#define ZPCI_PCI_ST_FUNC_NOT_ENABLED 4
79
#define ZPCI_PCI_ST_FUNC_IN_ERR 8
@@ -122,13 +124,16 @@ union zpci_sic_iib {
122124
struct zpci_cdiib cdiib;
123125
};
124126

127+
DECLARE_STATIC_KEY_FALSE(have_mio);
128+
125129
u8 zpci_mod_fc(u64 req, struct zpci_fib *fib, u8 *status);
126130
int zpci_refresh_trans(u64 fn, u64 addr, u64 range);
127131
int __zpci_load(u64 *data, u64 req, u64 offset);
128132
int zpci_load(u64 *data, const volatile void __iomem *addr, unsigned long len);
129133
int __zpci_store(u64 data, u64 req, u64 offset);
130134
int zpci_store(const volatile void __iomem *addr, u64 data, unsigned long len);
131135
int __zpci_store_block(const u64 *data, u64 req, u64 offset);
136+
void zpci_barrier(void);
132137
int __zpci_set_irq_ctrl(u16 ctl, u8 isc, union zpci_sic_iib *iib);
133138

134139
static inline int zpci_set_irq_ctrl(u16 ctl, u8 isc)

arch/s390/pci/pci.c

Lines changed: 122 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/export.h>
2626
#include <linux/delay.h>
2727
#include <linux/seq_file.h>
28+
#include <linux/jump_label.h>
2829
#include <linux/pci.h>
2930

3031
#include <asm/isc.h>
@@ -50,6 +51,8 @@ static unsigned long *zpci_iomap_bitmap;
5051
struct zpci_iomap_entry *zpci_iomap_start;
5152
EXPORT_SYMBOL_GPL(zpci_iomap_start);
5253

54+
DEFINE_STATIC_KEY_FALSE(have_mio);
55+
5356
static struct kmem_cache *zdev_fmb_cache;
5457

5558
struct zpci_dev *get_zdev_by_fid(u32 fid)
@@ -223,18 +226,48 @@ void __iowrite64_copy(void __iomem *to, const void *from, size_t count)
223226
zpci_memcpy_toio(to, from, count);
224227
}
225228

229+
void __iomem *ioremap(unsigned long ioaddr, unsigned long size)
230+
{
231+
struct vm_struct *area;
232+
unsigned long offset;
233+
234+
if (!size)
235+
return NULL;
236+
237+
if (!static_branch_unlikely(&have_mio))
238+
return (void __iomem *) ioaddr;
239+
240+
offset = ioaddr & ~PAGE_MASK;
241+
ioaddr &= PAGE_MASK;
242+
size = PAGE_ALIGN(size + offset);
243+
area = get_vm_area(size, VM_IOREMAP);
244+
if (!area)
245+
return NULL;
246+
247+
if (ioremap_page_range((unsigned long) area->addr,
248+
(unsigned long) area->addr + size,
249+
ioaddr, PAGE_KERNEL)) {
250+
vunmap(area->addr);
251+
return NULL;
252+
}
253+
return (void __iomem *) ((unsigned long) area->addr + offset);
254+
}
255+
EXPORT_SYMBOL(ioremap);
256+
257+
void iounmap(volatile void __iomem *addr)
258+
{
259+
if (static_branch_likely(&have_mio))
260+
vunmap((__force void *) ((unsigned long) addr & PAGE_MASK));
261+
}
262+
EXPORT_SYMBOL(iounmap);
263+
226264
/* Create a virtual mapping cookie for a PCI BAR */
227-
void __iomem *pci_iomap_range(struct pci_dev *pdev,
228-
int bar,
229-
unsigned long offset,
230-
unsigned long max)
265+
static void __iomem *pci_iomap_range_fh(struct pci_dev *pdev, int bar,
266+
unsigned long offset, unsigned long max)
231267
{
232268
struct zpci_dev *zdev = to_zpci(pdev);
233269
int idx;
234270

235-
if (!pci_resource_len(pdev, bar) || bar >= PCI_BAR_COUNT)
236-
return NULL;
237-
238271
idx = zdev->bars[bar].map_idx;
239272
spin_lock(&zpci_iomap_lock);
240273
/* Detect overrun */
@@ -245,6 +278,30 @@ void __iomem *pci_iomap_range(struct pci_dev *pdev,
245278

246279
return (void __iomem *) ZPCI_ADDR(idx) + offset;
247280
}
281+
282+
static void __iomem *pci_iomap_range_mio(struct pci_dev *pdev, int bar,
283+
unsigned long offset,
284+
unsigned long max)
285+
{
286+
unsigned long barsize = pci_resource_len(pdev, bar);
287+
struct zpci_dev *zdev = to_zpci(pdev);
288+
void __iomem *iova;
289+
290+
iova = ioremap((unsigned long) zdev->bars[bar].mio_wt, barsize);
291+
return iova ? iova + offset : iova;
292+
}
293+
294+
void __iomem *pci_iomap_range(struct pci_dev *pdev, int bar,
295+
unsigned long offset, unsigned long max)
296+
{
297+
if (!pci_resource_len(pdev, bar) || bar >= PCI_BAR_COUNT)
298+
return NULL;
299+
300+
if (static_branch_likely(&have_mio))
301+
return pci_iomap_range_mio(pdev, bar, offset, max);
302+
else
303+
return pci_iomap_range_fh(pdev, bar, offset, max);
304+
}
248305
EXPORT_SYMBOL(pci_iomap_range);
249306

250307
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
@@ -253,7 +310,37 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
253310
}
254311
EXPORT_SYMBOL(pci_iomap);
255312

256-
void pci_iounmap(struct pci_dev *pdev, void __iomem *addr)
313+
static void __iomem *pci_iomap_wc_range_mio(struct pci_dev *pdev, int bar,
314+
unsigned long offset, unsigned long max)
315+
{
316+
unsigned long barsize = pci_resource_len(pdev, bar);
317+
struct zpci_dev *zdev = to_zpci(pdev);
318+
void __iomem *iova;
319+
320+
iova = ioremap((unsigned long) zdev->bars[bar].mio_wb, barsize);
321+
return iova ? iova + offset : iova;
322+
}
323+
324+
void __iomem *pci_iomap_wc_range(struct pci_dev *pdev, int bar,
325+
unsigned long offset, unsigned long max)
326+
{
327+
if (!pci_resource_len(pdev, bar) || bar >= PCI_BAR_COUNT)
328+
return NULL;
329+
330+
if (static_branch_likely(&have_mio))
331+
return pci_iomap_wc_range_mio(pdev, bar, offset, max);
332+
else
333+
return pci_iomap_range_fh(pdev, bar, offset, max);
334+
}
335+
EXPORT_SYMBOL(pci_iomap_wc_range);
336+
337+
void __iomem *pci_iomap_wc(struct pci_dev *dev, int bar, unsigned long maxlen)
338+
{
339+
return pci_iomap_wc_range(dev, bar, 0, maxlen);
340+
}
341+
EXPORT_SYMBOL(pci_iomap_wc);
342+
343+
static void pci_iounmap_fh(struct pci_dev *pdev, void __iomem *addr)
257344
{
258345
unsigned int idx = ZPCI_IDX(addr);
259346

@@ -266,6 +353,19 @@ void pci_iounmap(struct pci_dev *pdev, void __iomem *addr)
266353
}
267354
spin_unlock(&zpci_iomap_lock);
268355
}
356+
357+
static void pci_iounmap_mio(struct pci_dev *pdev, void __iomem *addr)
358+
{
359+
iounmap(addr);
360+
}
361+
362+
void pci_iounmap(struct pci_dev *pdev, void __iomem *addr)
363+
{
364+
if (static_branch_likely(&have_mio))
365+
pci_iounmap_mio(pdev, addr);
366+
else
367+
pci_iounmap_fh(pdev, addr);
368+
}
269369
EXPORT_SYMBOL(pci_iounmap);
270370

271371
static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
@@ -312,15 +412,21 @@ static struct resource iov_res = {
312412

313413
static void zpci_map_resources(struct pci_dev *pdev)
314414
{
415+
struct zpci_dev *zdev = to_zpci(pdev);
315416
resource_size_t len;
316417
int i;
317418

318419
for (i = 0; i < PCI_BAR_COUNT; i++) {
319420
len = pci_resource_len(pdev, i);
320421
if (!len)
321422
continue;
322-
pdev->resource[i].start =
323-
(resource_size_t __force) pci_iomap(pdev, i, 0);
423+
424+
if (static_branch_likely(&have_mio))
425+
pdev->resource[i].start =
426+
(resource_size_t __force) zdev->bars[i].mio_wb;
427+
else
428+
pdev->resource[i].start =
429+
(resource_size_t __force) pci_iomap(pdev, i, 0);
324430
pdev->resource[i].end = pdev->resource[i].start + len - 1;
325431
}
326432

@@ -341,6 +447,9 @@ static void zpci_unmap_resources(struct pci_dev *pdev)
341447
resource_size_t len;
342448
int i;
343449

450+
if (static_branch_likely(&have_mio))
451+
return;
452+
344453
for (i = 0; i < PCI_BAR_COUNT; i++) {
345454
len = pci_resource_len(pdev, i);
346455
if (!len)
@@ -772,6 +881,9 @@ static int __init pci_base_init(void)
772881
if (!test_facility(69) || !test_facility(71))
773882
return 0;
774883

884+
if (test_facility(153))
885+
static_branch_enable(&have_mio);
886+
775887
rc = zpci_debug_init();
776888
if (rc)
777889
goto out;

arch/s390/pci/pci_clp.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,14 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev,
163163
memcpy(zdev->util_str, response->util_str,
164164
sizeof(zdev->util_str));
165165
}
166+
zdev->mio_capable = response->mio_addr_avail;
167+
for (i = 0; i < PCI_BAR_COUNT; i++) {
168+
if (!(response->mio_valid & (1 << (PCI_BAR_COUNT - i - 1))))
169+
continue;
166170

171+
zdev->bars[i].mio_wb = (void __iomem *) response->addr[i].wb;
172+
zdev->bars[i].mio_wt = (void __iomem *) response->addr[i].wt;
173+
}
167174
return 0;
168175
}
169176

@@ -279,11 +286,18 @@ int clp_enable_fh(struct zpci_dev *zdev, u8 nr_dma_as)
279286
int rc;
280287

281288
rc = clp_set_pci_fn(&fh, nr_dma_as, CLP_SET_ENABLE_PCI_FN);
282-
if (!rc)
283-
/* Success -> store enabled handle in zdev */
284-
zdev->fh = fh;
289+
zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, fh, rc);
290+
if (rc)
291+
goto out;
285292

286-
zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
293+
zdev->fh = fh;
294+
if (zdev->mio_capable) {
295+
rc = clp_set_pci_fn(&fh, nr_dma_as, CLP_SET_ENABLE_MIO);
296+
zpci_dbg(3, "ena mio fid:%x, fh:%x, rc:%d\n", zdev->fid, fh, rc);
297+
if (rc)
298+
clp_disable_fh(zdev);
299+
}
300+
out:
287301
return rc;
288302
}
289303

@@ -296,11 +310,10 @@ int clp_disable_fh(struct zpci_dev *zdev)
296310
return 0;
297311

298312
rc = clp_set_pci_fn(&fh, 0, CLP_SET_DISABLE_PCI_FN);
313+
zpci_dbg(3, "dis fid:%x, fh:%x, rc:%d\n", zdev->fid, fh, rc);
299314
if (!rc)
300-
/* Success -> store disabled handle in zdev */
301315
zdev->fh = fh;
302316

303-
zpci_dbg(3, "dis fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
304317
return rc;
305318
}
306319

0 commit comments

Comments
 (0)