Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b077868 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 16e024f3 1f1c9610
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -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 */
+39 −0
Original line number Diff line number Diff line
@@ -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
@@ -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;
@@ -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 {
@@ -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 −0
Original line number Diff line number Diff line
#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
+1 −1
Original line number Diff line number Diff line
@@ -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
+70 −3
Original line number Diff line number Diff line
@@ -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)
{
@@ -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)
@@ -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);
@@ -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;
@@ -252,7 +258,7 @@ 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);
}
@@ -260,11 +266,46 @@ int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
/* 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)
@@ -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 */
@@ -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)
{
@@ -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);

@@ -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);
@@ -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;
@@ -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;
@@ -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;
@@ -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);
Loading