Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/s390/linux

Pull s390 update #2 from Martin Schwidefsky:
 "The main patch is the function measurement blocks extension for PCI to
  do performance statistics and help with debugging.  The other patch is
  a small cleanup in ccwdev.h."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/ccwdev: Include asm/schid.h.
  s390/pci: performance statistics and debug infrastructure
  • Loading branch information
Linus Torvalds committed Dec 18, 2012
2 parents 16e024f + 1f1c961 commit 7b07786
Show file tree
Hide file tree
Showing 9 changed files with 350 additions and 8 deletions.
4 changes: 1 addition & 3 deletions arch/s390/include/asm/ccwdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@
#include <linux/mod_devicetable.h>
#include <asm/fcx.h>
#include <asm/irq.h>
#include <asm/schid.h>

/* structs from asm/cio.h */
struct irb;
struct ccw1;
struct ccw_dev_id;

/* from asm/schid.h */
struct subchannel_id;

/* simplified initializers for struct ccw_device:
* CCW_DEVICE and CCW_DEVICE_DEVTYPE initialize one
* entry in your MODULE_DEVICE_TABLE and set the match_flag correctly */
Expand Down
39 changes: 39 additions & 0 deletions arch/s390/include/asm/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <asm-generic/pci.h>
#include <asm-generic/pci-dma-compat.h>
#include <asm/pci_clp.h>
#include <asm/pci_debug.h>

#define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000
Expand All @@ -33,6 +34,25 @@ int pci_proc_domain(struct pci_bus *);
#define ZPCI_FC_BLOCKED 0x20
#define ZPCI_FC_DMA_ENABLED 0x10

struct zpci_fmb {
u32 format : 8;
u32 dma_valid : 1;
u32 : 23;
u32 samples;
u64 last_update;
/* hardware counters */
u64 ld_ops;
u64 st_ops;
u64 stb_ops;
u64 rpcit_ops;
u64 dma_rbytes;
u64 dma_wbytes;
/* software counters */
atomic64_t allocated_pages;
atomic64_t mapped_pages;
atomic64_t unmapped_pages;
} __packed __aligned(16);

struct msi_map {
unsigned long irq;
struct msi_desc *msi;
Expand Down Expand Up @@ -92,7 +112,15 @@ struct zpci_dev {
u64 end_dma; /* End of available DMA addresses */
u64 dma_mask; /* DMA address space mask */

/* Function measurement block */
struct zpci_fmb *fmb;
u16 fmb_update; /* update interval */

enum pci_bus_speed max_bus_speed;

struct dentry *debugfs_dev;
struct dentry *debugfs_perf;
struct dentry *debugfs_debug;
};

struct pci_hp_callback_ops {
Expand Down Expand Up @@ -155,4 +183,15 @@ extern struct list_head zpci_list;
extern struct pci_hp_callback_ops hotplug_ops;
extern unsigned int pci_probe;

/* FMB */
int zpci_fmb_enable_device(struct zpci_dev *);
int zpci_fmb_disable_device(struct zpci_dev *);

/* Debug */
int zpci_debug_init(void);
void zpci_debug_exit(void);
void zpci_debug_init_device(struct zpci_dev *);
void zpci_debug_exit_device(struct zpci_dev *);
void zpci_debug_info(struct zpci_dev *, struct seq_file *);

#endif
36 changes: 36 additions & 0 deletions arch/s390/include/asm/pci_debug.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef _S390_ASM_PCI_DEBUG_H
#define _S390_ASM_PCI_DEBUG_H

#include <asm/debug.h>

extern debug_info_t *pci_debug_msg_id;
extern debug_info_t *pci_debug_err_id;

#ifdef CONFIG_PCI_DEBUG
#define zpci_dbg(fmt, args...) \
do { \
if (pci_debug_msg_id->level >= 2) \
debug_sprintf_event(pci_debug_msg_id, 2, fmt , ## args);\
} while (0)

#else /* !CONFIG_PCI_DEBUG */
#define zpci_dbg(fmt, args...) do { } while (0)
#endif

#define zpci_err(text...) \
do { \
char debug_buffer[16]; \
snprintf(debug_buffer, 16, text); \
debug_text_event(pci_debug_err_id, 0, debug_buffer); \
} while (0)

static inline void zpci_err_hex(void *addr, int len)
{
while (len > 0) {
debug_event(pci_debug_err_id, 0, (void *) addr, len);
len -= pci_debug_err_id->buf_size;
addr += pci_debug_err_id->buf_size;
}
}

#endif
2 changes: 1 addition & 1 deletion arch/s390/pci/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
#

obj-$(CONFIG_PCI) += pci.o pci_dma.o pci_clp.o pci_msi.o \
pci_sysfs.o pci_event.o
pci_sysfs.o pci_event.o pci_debug.o
73 changes: 70 additions & 3 deletions arch/s390/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ EXPORT_SYMBOL_GPL(zpci_iomap_start);
static int __read_mostly aisb_max;

static struct kmem_cache *zdev_irq_cache;
static struct kmem_cache *zdev_fmb_cache;

debug_info_t *pci_debug_msg_id;
debug_info_t *pci_debug_err_id;

static inline int irq_to_msi_nr(unsigned int irq)
{
Expand Down Expand Up @@ -216,6 +220,7 @@ struct mod_pci_args {
u64 base;
u64 limit;
u64 iota;
u64 fmb_addr;
};

static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args *args)
Expand All @@ -232,6 +237,7 @@ static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args
fib->pba = args->base;
fib->pal = args->limit;
fib->iota = args->iota;
fib->fmb_addr = args->fmb_addr;

rc = mpcifc_instr(req, fib);
free_page((unsigned long) fib);
Expand All @@ -242,7 +248,7 @@ static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args
int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas,
u64 base, u64 limit, u64 iota)
{
struct mod_pci_args args = { base, limit, iota };
struct mod_pci_args args = { base, limit, iota, 0 };

WARN_ON_ONCE(iota & 0x3fff);
args.iota |= ZPCI_IOTA_RTTO_FLAG;
Expand All @@ -252,19 +258,54 @@ int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas,
/* Modify PCI: Unregister I/O address translation parameters */
int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
{
struct mod_pci_args args = { 0, 0, 0 };
struct mod_pci_args args = { 0, 0, 0, 0 };

return mod_pci(zdev, ZPCI_MOD_FC_DEREG_IOAT, dmaas, &args);
}

/* Modify PCI: Unregister adapter interruptions */
static int zpci_unregister_airq(struct zpci_dev *zdev)
{
struct mod_pci_args args = { 0, 0, 0 };
struct mod_pci_args args = { 0, 0, 0, 0 };

return mod_pci(zdev, ZPCI_MOD_FC_DEREG_INT, 0, &args);
}

/* Modify PCI: Set PCI function measurement parameters */
int zpci_fmb_enable_device(struct zpci_dev *zdev)
{
struct mod_pci_args args = { 0, 0, 0, 0 };

if (zdev->fmb)
return -EINVAL;

zdev->fmb = kmem_cache_alloc(zdev_fmb_cache, GFP_KERNEL);
if (!zdev->fmb)
return -ENOMEM;
memset(zdev->fmb, 0, sizeof(*zdev->fmb));
WARN_ON((u64) zdev->fmb & 0xf);

args.fmb_addr = virt_to_phys(zdev->fmb);
return mod_pci(zdev, ZPCI_MOD_FC_SET_MEASURE, 0, &args);
}

/* Modify PCI: Disable PCI function measurement */
int zpci_fmb_disable_device(struct zpci_dev *zdev)
{
struct mod_pci_args args = { 0, 0, 0, 0 };
int rc;

if (!zdev->fmb)
return -EINVAL;

/* Function measurement is disabled if fmb address is zero */
rc = mod_pci(zdev, ZPCI_MOD_FC_SET_MEASURE, 0, &args);

kmem_cache_free(zdev_fmb_cache, zdev->fmb);
zdev->fmb = NULL;
return rc;
}

#define ZPCI_PCIAS_CFGSPC 15

static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len)
Expand Down Expand Up @@ -633,6 +674,7 @@ static void zpci_remove_device(struct pci_dev *pdev)
dev_info(&pdev->dev, "Removing device %u\n", zdev->domain);
zdev->state = ZPCI_FN_STATE_CONFIGURED;
zpci_dma_exit_device(zdev);
zpci_fmb_disable_device(zdev);
zpci_sysfs_remove_device(&pdev->dev);
zpci_unmap_resources(pdev);
list_del(&zdev->entry); /* can be called from init */
Expand Down Expand Up @@ -799,6 +841,16 @@ static void zpci_irq_exit(void)
kfree(bucket);
}

void zpci_debug_info(struct zpci_dev *zdev, struct seq_file *m)
{
if (!zdev)
return;

seq_printf(m, "global irq retries: %u\n", atomic_read(&irq_retries));
seq_printf(m, "aibv[0]:%016lx aibv[1]:%016lx aisb:%016lx\n",
get_imap(0)->aibv, get_imap(1)->aibv, *bucket->aisb);
}

static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size,
unsigned long flags, int domain)
{
Expand Down Expand Up @@ -994,6 +1046,8 @@ int zpci_scan_device(struct zpci_dev *zdev)
goto out;
}

zpci_debug_init_device(zdev);
zpci_fmb_enable_device(zdev);
zpci_map_resources(zdev);
pci_bus_add_devices(zdev->bus);

Expand All @@ -1020,6 +1074,11 @@ static int zpci_mem_init(void)
if (!zdev_irq_cache)
goto error_zdev;

zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
16, 0, NULL);
if (!zdev_fmb_cache)
goto error_fmb;

/* TODO: use realloc */
zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start),
GFP_KERNEL);
Expand All @@ -1028,6 +1087,8 @@ static int zpci_mem_init(void)
return 0;

error_iomap:
kmem_cache_destroy(zdev_fmb_cache);
error_fmb:
kmem_cache_destroy(zdev_irq_cache);
error_zdev:
return -ENOMEM;
Expand All @@ -1037,6 +1098,7 @@ static void zpci_mem_exit(void)
{
kfree(zpci_iomap_start);
kmem_cache_destroy(zdev_irq_cache);
kmem_cache_destroy(zdev_fmb_cache);
}

unsigned int pci_probe = 1;
Expand Down Expand Up @@ -1066,6 +1128,10 @@ static int __init pci_base_init(void)
test_facility(69), test_facility(70),
test_facility(71));

rc = zpci_debug_init();
if (rc)
return rc;

rc = zpci_mem_init();
if (rc)
goto out_mem;
Expand Down Expand Up @@ -1098,6 +1164,7 @@ static int __init pci_base_init(void)
out_hash:
zpci_mem_exit();
out_mem:
zpci_debug_exit();
return rc;
}
subsys_initcall(pci_base_init);
1 change: 1 addition & 0 deletions arch/s390/pci/pci_clp.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ static void clp_store_query_pci_fngrp(struct zpci_dev *zdev,
zdev->tlb_refresh = response->refresh;
zdev->dma_mask = response->dasm;
zdev->msi_addr = response->msia;
zdev->fmb_update = response->mui;

pr_debug("Supported number of MSI vectors: %u\n", response->noi);
switch (response->version) {
Expand Down
Loading

0 comments on commit 7b07786

Please sign in to comment.