提交 ee723cb3 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6

* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
  [S390] dasd: use -EOPNOTSUPP instead of -ENOTSUPP
  [S390] qdio: new qdio driver.
  [S390] cio: Export chsc_error_from_response().
  [S390] vmur: Fix return code handling.
  [S390] Fix stacktrace compile bug.
  [S390] Increase default warning stacksize.
  [S390] dasd: Fix cleanup in dasd_{fba,diag}_check_characteristics().
  [S390] chsc headers userspace cleanup
  [S390] dasd: fix unsolicited SIM handling.
  [S390] zfcpdump: Make SCSI disk dump tool recognize storage holes
......@@ -289,7 +289,7 @@ config WARN_STACK_SIZE
int "Maximum frame size considered safe (128-2048)"
range 128 2048
depends on WARN_STACK
default "256"
default "2048"
help
This allows you to specify the maximum frame size a function may
have without the compiler complaining about it.
......
......@@ -10,6 +10,7 @@
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <linux/kallsyms.h>
#include <linux/module.h>
static unsigned long save_context_stack(struct stack_trace *trace,
unsigned long sp,
......
......@@ -333,7 +333,8 @@ dasd_diag_check_device(struct dasd_device *device)
if (IS_ERR(block)) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
"could not allocate dasd block structure");
kfree(device->private);
device->private = NULL;
kfree(private);
return PTR_ERR(block);
}
device->block = block;
......@@ -348,7 +349,8 @@ dasd_diag_check_device(struct dasd_device *device)
if (rc) {
DEV_MESSAGE(KERN_WARNING, device, "failed to retrieve device "
"information (rc=%d)", rc);
return -ENOTSUPP;
rc = -EOPNOTSUPP;
goto out;
}
/* Figure out position of label block */
......@@ -362,7 +364,8 @@ dasd_diag_check_device(struct dasd_device *device)
default:
DEV_MESSAGE(KERN_WARNING, device, "unsupported device class "
"(class=%d)", private->rdc_data.vdev_class);
return -ENOTSUPP;
rc = -EOPNOTSUPP;
goto out;
}
DBF_DEV_EVENT(DBF_INFO, device,
......@@ -379,7 +382,8 @@ dasd_diag_check_device(struct dasd_device *device)
if (label == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
"No memory to allocate initialization request");
return -ENOMEM;
rc = -ENOMEM;
goto out;
}
rc = 0;
end_block = 0;
......@@ -403,7 +407,7 @@ dasd_diag_check_device(struct dasd_device *device)
DEV_MESSAGE(KERN_WARNING, device, "%s",
"DIAG call failed");
rc = -EOPNOTSUPP;
goto out;
goto out_label;
}
mdsk_term_io(device);
if (rc == 0)
......@@ -413,7 +417,7 @@ dasd_diag_check_device(struct dasd_device *device)
DEV_MESSAGE(KERN_WARNING, device, "device access failed "
"(rc=%d)", rc);
rc = -EIO;
goto out;
goto out_label;
}
/* check for label block */
if (memcmp(label->label_id, DASD_DIAG_CMS1,
......@@ -439,8 +443,15 @@ dasd_diag_check_device(struct dasd_device *device)
(unsigned long) (block->blocks <<
block->s2b_shift) >> 1);
}
out:
out_label:
free_page((long) label);
out:
if (rc) {
device->block = NULL;
dasd_free_block(block);
device->private = NULL;
kfree(private);
}
return rc;
}
......
......@@ -1418,8 +1418,10 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
/* service information message SIM */
if ((irb->ecw[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE) {
if (irb->esw.esw0.erw.cons && (irb->ecw[27] & DASD_SENSE_BIT_0) &&
((irb->ecw[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)) {
dasd_3990_erp_handle_sim(device, irb->ecw);
dasd_schedule_device_bh(device);
return;
}
......
......@@ -139,7 +139,8 @@ dasd_fba_check_characteristics(struct dasd_device *device)
if (IS_ERR(block)) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
"could not allocate dasd block structure");
kfree(device->private);
device->private = NULL;
kfree(private);
return PTR_ERR(block);
}
device->block = block;
......@@ -152,6 +153,10 @@ dasd_fba_check_characteristics(struct dasd_device *device)
DEV_MESSAGE(KERN_WARNING, device,
"Read device characteristics returned error %d",
rc);
device->block = NULL;
dasd_free_block(block);
device->private = NULL;
kfree(private);
return rc;
}
......
......@@ -345,7 +345,7 @@ static int get_urd_class(struct urdev *urd)
cc = diag210(&ur_diag210);
switch (cc) {
case 0:
return -ENOTSUPP;
return -EOPNOTSUPP;
case 2:
return ur_diag210.vrdcvcla; /* virtual device class */
case 3:
......@@ -621,7 +621,7 @@ static int verify_device(struct urdev *urd)
case DEV_CLASS_UR_I:
return verify_uri_device(urd);
default:
return -ENOTSUPP;
return -EOPNOTSUPP;
}
}
......@@ -654,7 +654,7 @@ static int get_file_reclen(struct urdev *urd)
case DEV_CLASS_UR_I:
return get_uri_file_reclen(urd);
default:
return -ENOTSUPP;
return -EOPNOTSUPP;
}
}
......@@ -827,7 +827,7 @@ static int ur_probe(struct ccw_device *cdev)
goto fail_remove_attr;
}
if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) {
rc = -ENOTSUPP;
rc = -EOPNOTSUPP;
goto fail_remove_attr;
}
spin_lock_irq(get_ccwdev_lock(cdev));
......@@ -892,7 +892,7 @@ static int ur_set_online(struct ccw_device *cdev)
} else if (urd->cdev->id.cu_type == PRINTER_DEVTYPE) {
sprintf(node_id, "vmprt-%s", cdev->dev.bus_id);
} else {
rc = -ENOTSUPP;
rc = -EOPNOTSUPP;
goto fail_free_cdev;
}
......
......@@ -29,6 +29,7 @@
#define TO_USER 0
#define TO_KERNEL 1
#define CHUNK_INFO_SIZE 34 /* 2 16-byte char, each followed by blank */
enum arch_id {
ARCH_S390 = 0,
......@@ -51,6 +52,7 @@ static struct debug_info *zcore_dbf;
static int hsa_available;
static struct dentry *zcore_dir;
static struct dentry *zcore_file;
static struct dentry *zcore_memmap_file;
/*
* Copy memory from HSA to kernel or user memory (not reentrant):
......@@ -476,6 +478,54 @@ static const struct file_operations zcore_fops = {
.release = zcore_release,
};
static ssize_t zcore_memmap_read(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
{
return simple_read_from_buffer(buf, count, ppos, filp->private_data,
MEMORY_CHUNKS * CHUNK_INFO_SIZE);
}
static int zcore_memmap_open(struct inode *inode, struct file *filp)
{
int i;
char *buf;
struct mem_chunk *chunk_array;
chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
GFP_KERNEL);
if (!chunk_array)
return -ENOMEM;
detect_memory_layout(chunk_array);
buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL);
if (!buf) {
kfree(chunk_array);
return -ENOMEM;
}
for (i = 0; i < MEMORY_CHUNKS; i++) {
sprintf(buf + (i * CHUNK_INFO_SIZE), "%016llx %016llx ",
(unsigned long long) chunk_array[i].addr,
(unsigned long long) chunk_array[i].size);
if (chunk_array[i].size == 0)
break;
}
kfree(chunk_array);
filp->private_data = buf;
return 0;
}
static int zcore_memmap_release(struct inode *inode, struct file *filp)
{
kfree(filp->private_data);
return 0;
}
static const struct file_operations zcore_memmap_fops = {
.owner = THIS_MODULE,
.read = zcore_memmap_read,
.open = zcore_memmap_open,
.release = zcore_memmap_release,
};
static void __init set_s390_lc_mask(union save_area *map)
{
......@@ -554,18 +604,44 @@ static int __init check_sdias(void)
return 0;
}
static void __init zcore_header_init(int arch, struct zcore_header *hdr)
static int __init get_mem_size(unsigned long *mem)
{
int i;
struct mem_chunk *chunk_array;
chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
GFP_KERNEL);
if (!chunk_array)
return -ENOMEM;
detect_memory_layout(chunk_array);
for (i = 0; i < MEMORY_CHUNKS; i++) {
if (chunk_array[i].size == 0)
break;
*mem += chunk_array[i].size;
}
kfree(chunk_array);
return 0;
}
static int __init zcore_header_init(int arch, struct zcore_header *hdr)
{
int rc;
unsigned long memory = 0;
if (arch == ARCH_S390X)
hdr->arch_id = DUMP_ARCH_S390X;
else
hdr->arch_id = DUMP_ARCH_S390;
hdr->mem_size = sys_info.mem_size;
hdr->rmem_size = sys_info.mem_size;
rc = get_mem_size(&memory);
if (rc)
return rc;
hdr->mem_size = memory;
hdr->rmem_size = memory;
hdr->mem_end = sys_info.mem_size;
hdr->num_pages = sys_info.mem_size / PAGE_SIZE;
hdr->num_pages = memory / PAGE_SIZE;
hdr->tod = get_clock();
get_cpu_id(&hdr->cpu_id);
return 0;
}
static int __init zcore_init(void)
......@@ -608,7 +684,9 @@ static int __init zcore_init(void)
if (rc)
goto fail;
zcore_header_init(arch, &zcore_header);
rc = zcore_header_init(arch, &zcore_header);
if (rc)
goto fail;
zcore_dir = debugfs_create_dir("zcore" , NULL);
if (!zcore_dir) {
......@@ -618,13 +696,22 @@ static int __init zcore_init(void)
zcore_file = debugfs_create_file("mem", S_IRUSR, zcore_dir, NULL,
&zcore_fops);
if (!zcore_file) {
debugfs_remove(zcore_dir);
rc = -ENOMEM;
goto fail;
goto fail_dir;
}
zcore_memmap_file = debugfs_create_file("memmap", S_IRUSR, zcore_dir,
NULL, &zcore_memmap_fops);
if (!zcore_memmap_file) {
rc = -ENOMEM;
goto fail_file;
}
hsa_available = 1;
return 0;
fail_file:
debugfs_remove(zcore_file);
fail_dir:
debugfs_remove(zcore_dir);
fail:
diag308(DIAG308_REL_HSA, NULL);
return rc;
......
......@@ -9,4 +9,6 @@ ccw_device-objs += device_id.o device_pgid.o device_status.o
obj-y += ccw_device.o cmf.o
obj-$(CONFIG_CHSC_SCH) += chsc_sch.o
obj-$(CONFIG_CCWGROUP) += ccwgroup.o
qdio-objs := qdio_main.o qdio_thinint.o qdio_debug.o qdio_perf.o qdio_setup.o
obj-$(CONFIG_QDIO) += qdio.o
......@@ -27,7 +27,13 @@
static void *sei_page;
static int chsc_error_from_response(int response)
/**
* chsc_error_from_response() - convert a chsc response to an error
* @response: chsc response code
*
* Returns an appropriate Linux error code for @response.
*/
int chsc_error_from_response(int response)
{
switch (response) {
case 0x0001:
......@@ -45,6 +51,7 @@ static int chsc_error_from_response(int response)
return -EIO;
}
}
EXPORT_SYMBOL_GPL(chsc_error_from_response);
struct chsc_ssd_area {
struct chsc_header request;
......
......@@ -101,4 +101,6 @@ void chsc_chp_online(struct chp_id chpid);
void chsc_chp_offline(struct chp_id chpid);
int chsc_get_channel_measurement_chars(struct channel_path *chp);
int chsc_error_from_response(int response);
#endif
此差异已折叠。
此差异已折叠。
/*
* drivers/s390/cio/qdio_debug.c
*
* Copyright IBM Corp. 2008
*
* Author: Jan Glauber (jang@linux.vnet.ibm.com)
*/
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include <asm/qdio.h>
#include <asm/debug.h>
#include "qdio_debug.h"
#include "qdio.h"
debug_info_t *qdio_dbf_setup;
debug_info_t *qdio_dbf_trace;
static struct dentry *debugfs_root;
#define MAX_DEBUGFS_QUEUES 32
static struct dentry *debugfs_queues[MAX_DEBUGFS_QUEUES] = { NULL };
static DEFINE_MUTEX(debugfs_mutex);
void qdio_allocate_do_dbf(struct qdio_initialize *init_data)
{
char dbf_text[20];
sprintf(dbf_text, "qfmt:%x", init_data->q_format);
QDIO_DBF_TEXT0(0, setup, dbf_text);
QDIO_DBF_HEX0(0, setup, init_data->adapter_name, 8);
sprintf(dbf_text, "qpff%4x", init_data->qib_param_field_format);
QDIO_DBF_TEXT0(0, setup, dbf_text);
QDIO_DBF_HEX0(0, setup, &init_data->qib_param_field, sizeof(void *));
QDIO_DBF_HEX0(0, setup, &init_data->input_slib_elements, sizeof(void *));
QDIO_DBF_HEX0(0, setup, &init_data->output_slib_elements, sizeof(void *));
sprintf(dbf_text, "niq:%4x", init_data->no_input_qs);
QDIO_DBF_TEXT0(0, setup, dbf_text);
sprintf(dbf_text, "noq:%4x", init_data->no_output_qs);
QDIO_DBF_TEXT0(0, setup, dbf_text);
QDIO_DBF_HEX0(0, setup, &init_data->input_handler, sizeof(void *));
QDIO_DBF_HEX0(0, setup, &init_data->output_handler, sizeof(void *));
QDIO_DBF_HEX0(0, setup, &init_data->int_parm, sizeof(long));
QDIO_DBF_HEX0(0, setup, &init_data->flags, sizeof(long));
QDIO_DBF_HEX0(0, setup, &init_data->input_sbal_addr_array, sizeof(void *));
QDIO_DBF_HEX0(0, setup, &init_data->output_sbal_addr_array, sizeof(void *));
}
static void qdio_unregister_dbf_views(void)
{
if (qdio_dbf_setup)
debug_unregister(qdio_dbf_setup);
if (qdio_dbf_trace)
debug_unregister(qdio_dbf_trace);
}
static int qdio_register_dbf_views(void)
{
qdio_dbf_setup = debug_register("qdio_setup", QDIO_DBF_SETUP_PAGES,
QDIO_DBF_SETUP_NR_AREAS,
QDIO_DBF_SETUP_LEN);
if (!qdio_dbf_setup)
goto oom;
debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
debug_set_level(qdio_dbf_setup, QDIO_DBF_SETUP_LEVEL);
qdio_dbf_trace = debug_register("qdio_trace", QDIO_DBF_TRACE_PAGES,
QDIO_DBF_TRACE_NR_AREAS,
QDIO_DBF_TRACE_LEN);
if (!qdio_dbf_trace)
goto oom;
debug_register_view(qdio_dbf_trace, &debug_hex_ascii_view);
debug_set_level(qdio_dbf_trace, QDIO_DBF_TRACE_LEVEL);
return 0;
oom:
qdio_unregister_dbf_views();
return -ENOMEM;
}
static int qstat_show(struct seq_file *m, void *v)
{
unsigned char state;
struct qdio_q *q = m->private;
int i;
if (!q)
return 0;
seq_printf(m, "device state indicator: %d\n", *q->irq_ptr->dsci);
seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used));
seq_printf(m, "ftc: %d\n", q->first_to_check);
seq_printf(m, "last_move_ftc: %d\n", q->last_move_ftc);
seq_printf(m, "polling: %d\n", q->u.in.polling);
seq_printf(m, "slsb buffer states:\n");
qdio_siga_sync_q(q);
for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
get_buf_state(q, i, &state);
switch (state) {
case SLSB_P_INPUT_NOT_INIT:
case SLSB_P_OUTPUT_NOT_INIT:
seq_printf(m, "N");
break;
case SLSB_P_INPUT_PRIMED:
case SLSB_CU_OUTPUT_PRIMED:
seq_printf(m, "+");
break;
case SLSB_P_INPUT_ACK:
seq_printf(m, "A");
break;
case SLSB_P_INPUT_ERROR:
case SLSB_P_OUTPUT_ERROR:
seq_printf(m, "x");
break;
case SLSB_CU_INPUT_EMPTY:
case SLSB_P_OUTPUT_EMPTY:
seq_printf(m, "-");
break;
case SLSB_P_INPUT_HALTED:
case SLSB_P_OUTPUT_HALTED:
seq_printf(m, ".");
break;
default:
seq_printf(m, "?");
}
if (i == 63)
seq_printf(m, "\n");
}
seq_printf(m, "\n");
return 0;
}
static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
size_t count, loff_t *off)
{
struct seq_file *seq = file->private_data;
struct qdio_q *q = seq->private;
if (!q)
return 0;
if (q->is_input_q)
xchg(q->irq_ptr->dsci, 1);
local_bh_disable();
tasklet_schedule(&q->tasklet);
local_bh_enable();
return count;
}
static int qstat_seq_open(struct inode *inode, struct file *filp)
{
return single_open(filp, qstat_show,
filp->f_path.dentry->d_inode->i_private);
}
static void get_queue_name(struct qdio_q *q, struct ccw_device *cdev, char *name)
{
memset(name, 0, sizeof(name));
sprintf(name, "%s", cdev->dev.bus_id);
if (q->is_input_q)
sprintf(name + strlen(name), "_input");
else
sprintf(name + strlen(name), "_output");
sprintf(name + strlen(name), "_%d", q->nr);
}
static void remove_debugfs_entry(struct qdio_q *q)
{
int i;
for (i = 0; i < MAX_DEBUGFS_QUEUES; i++) {
if (!debugfs_queues[i])
continue;
if (debugfs_queues[i]->d_inode->i_private == q) {
debugfs_remove(debugfs_queues[i]);
debugfs_queues[i] = NULL;
}
}
}
static struct file_operations debugfs_fops = {
.owner = THIS_MODULE,
.open = qstat_seq_open,
.read = seq_read,
.write = qstat_seq_write,
.llseek = seq_lseek,
.release = single_release,
};
static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
{
int i = 0;
char name[40];
while (debugfs_queues[i] != NULL) {
i++;
if (i >= MAX_DEBUGFS_QUEUES)
return;
}
get_queue_name(q, cdev, name);
debugfs_queues[i] = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
debugfs_root, q, &debugfs_fops);
}
void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
{
struct qdio_q *q;
int i;
mutex_lock(&debugfs_mutex);
for_each_input_queue(irq_ptr, q, i)
setup_debugfs_entry(q, cdev);
for_each_output_queue(irq_ptr, q, i)
setup_debugfs_entry(q, cdev);
mutex_unlock(&debugfs_mutex);
}
void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
{
struct qdio_q *q;
int i;
mutex_lock(&debugfs_mutex);
for_each_input_queue(irq_ptr, q, i)
remove_debugfs_entry(q);
for_each_output_queue(irq_ptr, q, i)
remove_debugfs_entry(q);
mutex_unlock(&debugfs_mutex);
}
int __init qdio_debug_init(void)
{
debugfs_root = debugfs_create_dir("qdio_queues", NULL);
return qdio_register_dbf_views();
}
void qdio_debug_exit(void)
{
debugfs_remove(debugfs_root);
qdio_unregister_dbf_views();
}
/*
* drivers/s390/cio/qdio_debug.h
*
* Copyright IBM Corp. 2008
*
* Author: Jan Glauber (jang@linux.vnet.ibm.com)
*/
#ifndef QDIO_DEBUG_H
#define QDIO_DEBUG_H
#include <asm/debug.h>
#include <asm/qdio.h>
#include "qdio.h"
#define QDIO_DBF_HEX(ex, name, level, addr, len) \
do { \
if (ex) \
debug_exception(qdio_dbf_##name, level, (void *)(addr), len); \
else \
debug_event(qdio_dbf_##name, level, (void *)(addr), len); \
} while (0)
#define QDIO_DBF_TEXT(ex, name, level, text) \
do { \
if (ex) \
debug_text_exception(qdio_dbf_##name, level, text); \
else \
debug_text_event(qdio_dbf_##name, level, text); \
} while (0)
#define QDIO_DBF_HEX0(ex, name, addr, len) QDIO_DBF_HEX(ex, name, 0, addr, len)
#define QDIO_DBF_HEX1(ex, name, addr, len) QDIO_DBF_HEX(ex, name, 1, addr, len)
#define QDIO_DBF_HEX2(ex, name, addr, len) QDIO_DBF_HEX(ex, name, 2, addr, len)
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_DBF_HEX3(ex, name, addr, len) QDIO_DBF_HEX(ex, name, 3, addr, len)
#define QDIO_DBF_HEX4(ex, name, addr, len) QDIO_DBF_HEX(ex, name, 4, addr, len)
#define QDIO_DBF_HEX5(ex, name, addr, len) QDIO_DBF_HEX(ex, name, 5, addr, len)
#define QDIO_DBF_HEX6(ex, name, addr, len) QDIO_DBF_HEX(ex, name, 6, addr, len)
#else
#define QDIO_DBF_HEX3(ex, name, addr, len) do {} while (0)
#define QDIO_DBF_HEX4(ex, name, addr, len) do {} while (0)
#define QDIO_DBF_HEX5(ex, name, addr, len) do {} while (0)
#define QDIO_DBF_HEX6(ex, name, addr, len) do {} while (0)
#endif /* CONFIG_QDIO_DEBUG */
#define QDIO_DBF_TEXT0(ex, name, text) QDIO_DBF_TEXT(ex, name, 0, text)
#define QDIO_DBF_TEXT1(ex, name, text) QDIO_DBF_TEXT(ex, name, 1, text)
#define QDIO_DBF_TEXT2(ex, name, text) QDIO_DBF_TEXT(ex, name, 2, text)
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_DBF_TEXT3(ex, name, text) QDIO_DBF_TEXT(ex, name, 3, text)
#define QDIO_DBF_TEXT4(ex, name, text) QDIO_DBF_TEXT(ex, name, 4, text)
#define QDIO_DBF_TEXT5(ex, name, text) QDIO_DBF_TEXT(ex, name, 5, text)
#define QDIO_DBF_TEXT6(ex, name, text) QDIO_DBF_TEXT(ex, name, 6, text)
#else
#define QDIO_DBF_TEXT3(ex, name, text) do {} while (0)
#define QDIO_DBF_TEXT4(ex, name, text) do {} while (0)
#define QDIO_DBF_TEXT5(ex, name, text) do {} while (0)
#define QDIO_DBF_TEXT6(ex, name, text) do {} while (0)
#endif /* CONFIG_QDIO_DEBUG */
/* s390dbf views */
#define QDIO_DBF_SETUP_LEN 8
#define QDIO_DBF_SETUP_PAGES 4
#define QDIO_DBF_SETUP_NR_AREAS 1
#define QDIO_DBF_TRACE_LEN 8
#define QDIO_DBF_TRACE_NR_AREAS 2
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_DBF_TRACE_PAGES 16
#define QDIO_DBF_SETUP_LEVEL 6
#define QDIO_DBF_TRACE_LEVEL 4
#else /* !CONFIG_QDIO_DEBUG */
#define QDIO_DBF_TRACE_PAGES 4
#define QDIO_DBF_SETUP_LEVEL 2
#define QDIO_DBF_TRACE_LEVEL 2
#endif /* CONFIG_QDIO_DEBUG */
extern debug_info_t *qdio_dbf_setup;
extern debug_info_t *qdio_dbf_trace;
void qdio_allocate_do_dbf(struct qdio_initialize *init_data);
void debug_print_bstat(struct qdio_q *q);
void qdio_setup_debug_entries(struct qdio_irq *irq_ptr,
struct ccw_device *cdev);
void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr,
struct ccw_device *cdev);
int qdio_debug_init(void);
void qdio_debug_exit(void);
#endif
此差异已折叠。
/*
* drivers/s390/cio/qdio_perf.c
*
* Copyright IBM Corp. 2008
*
* Author: Jan Glauber (jang@linux.vnet.ibm.com)
*/
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <asm/ccwdev.h>
#include "cio.h"
#include "css.h"
#include "device.h"
#include "ioasm.h"
#include "chsc.h"
#include "qdio_debug.h"
#include "qdio_perf.h"
int qdio_performance_stats;
struct qdio_perf_stats perf_stats;
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *qdio_perf_pde;
#endif
inline void qdio_perf_stat_inc(atomic_long_t *count)
{
if (qdio_performance_stats)
atomic_long_inc(count);
}
inline void qdio_perf_stat_dec(atomic_long_t *count)
{
if (qdio_performance_stats)
atomic_long_dec(count);
}
/*
* procfs functions
*/
static int qdio_perf_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, "Number of qdio interrupts\t\t\t: %li\n",
(long)atomic_long_read(&perf_stats.qdio_int));
seq_printf(m, "Number of PCI interrupts\t\t\t: %li\n",
(long)atomic_long_read(&perf_stats.pci_int));
seq_printf(m, "Number of adapter interrupts\t\t\t: %li\n",
(long)atomic_long_read(&perf_stats.thin_int));
seq_printf(m, "\n");
seq_printf(m, "Inbound tasklet runs\t\t\t\t: %li\n",
(long)atomic_long_read(&perf_stats.tasklet_inbound));
seq_printf(m, "Outbound tasklet runs\t\t\t\t: %li\n",
(long)atomic_long_read(&perf_stats.tasklet_outbound));
seq_printf(m, "Adapter interrupt tasklet runs/loops\t\t: %li/%li\n",
(long)atomic_long_read(&perf_stats.tasklet_thinint),
(long)atomic_long_read(&perf_stats.tasklet_thinint_loop));
seq_printf(m, "Adapter interrupt inbound tasklet runs/loops\t: %li/%li\n",
(long)atomic_long_read(&perf_stats.thinint_inbound),
(long)atomic_long_read(&perf_stats.thinint_inbound_loop));
seq_printf(m, "\n");
seq_printf(m, "Number of SIGA In issued\t\t\t: %li\n",
(long)atomic_long_read(&perf_stats.siga_in));
seq_printf(m, "Number of SIGA Out issued\t\t\t: %li\n",
(long)atomic_long_read(&perf_stats.siga_out));
seq_printf(m, "Number of SIGA Sync issued\t\t\t: %li\n",
(long)atomic_long_read(&perf_stats.siga_sync));
seq_printf(m, "\n");
seq_printf(m, "Number of inbound transfers\t\t\t: %li\n",
(long)atomic_long_read(&perf_stats.inbound_handler));
seq_printf(m, "Number of outbound transfers\t\t\t: %li\n",
(long)atomic_long_read(&perf_stats.outbound_handler));
seq_printf(m, "\n");
seq_printf(m, "Number of fast requeues (outg. SBAL w/o SIGA)\t: %li\n",
(long)atomic_long_read(&perf_stats.fast_requeue));
seq_printf(m, "Number of outbound tasklet mod_timer calls\t: %li\n",
(long)atomic_long_read(&perf_stats.debug_tl_out_timer));
seq_printf(m, "Number of stop polling calls\t\t\t: %li\n",
(long)atomic_long_read(&perf_stats.debug_stop_polling));
seq_printf(m, "AI inbound tasklet loops after stop polling\t: %li\n",
(long)atomic_long_read(&perf_stats.thinint_inbound_loop2));
seq_printf(m, "\n");
return 0;
}
static int qdio_perf_seq_open(struct inode *inode, struct file *filp)
{
return single_open(filp, qdio_perf_proc_show, NULL);
}
static struct file_operations qdio_perf_proc_fops = {
.owner = THIS_MODULE,
.open = qdio_perf_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
/*
* sysfs functions
*/
static ssize_t qdio_perf_stats_show(struct bus_type *bus, char *buf)
{
return sprintf(buf, "%i\n", qdio_performance_stats ? 1 : 0);
}
static ssize_t qdio_perf_stats_store(struct bus_type *bus,
const char *buf, size_t count)
{
unsigned long i;
if (strict_strtoul(buf, 16, &i) != 0)
return -EINVAL;
if ((i != 0) && (i != 1))
return -EINVAL;
if (i == qdio_performance_stats)
return count;
qdio_performance_stats = i;
/* reset performance statistics */
if (i == 0)
memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
return count;
}
static BUS_ATTR(qdio_performance_stats, 0644, qdio_perf_stats_show,
qdio_perf_stats_store);
int __init qdio_setup_perf_stats(void)
{
int rc;
rc = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
if (rc)
return rc;
#ifdef CONFIG_PROC_FS
memset(&perf_stats, 0, sizeof(struct qdio_perf_stats));
qdio_perf_pde = proc_create("qdio_perf", S_IFREG | S_IRUGO,
NULL, &qdio_perf_proc_fops);
#endif
return 0;
}
void __exit qdio_remove_perf_stats(void)
{
#ifdef CONFIG_PROC_FS
remove_proc_entry("qdio_perf", NULL);
#endif
bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
}
/*
* drivers/s390/cio/qdio_perf.h
*
* Copyright IBM Corp. 2008
*
* Author: Jan Glauber (jang@linux.vnet.ibm.com)
*/
#ifndef QDIO_PERF_H
#define QDIO_PERF_H
#include <linux/types.h>
#include <linux/device.h>
#include <asm/atomic.h>
struct qdio_perf_stats {
/* interrupt handler calls */
atomic_long_t qdio_int;
atomic_long_t pci_int;
atomic_long_t thin_int;
/* tasklet runs */
atomic_long_t tasklet_inbound;
atomic_long_t tasklet_outbound;
atomic_long_t tasklet_thinint;
atomic_long_t tasklet_thinint_loop;
atomic_long_t thinint_inbound;
atomic_long_t thinint_inbound_loop;
atomic_long_t thinint_inbound_loop2;
/* signal adapter calls */
atomic_long_t siga_out;
atomic_long_t siga_in;
atomic_long_t siga_sync;
/* misc */
atomic_long_t inbound_handler;
atomic_long_t outbound_handler;
atomic_long_t fast_requeue;
/* for debugging */
atomic_long_t debug_tl_out_timer;
atomic_long_t debug_stop_polling;
};
extern struct qdio_perf_stats perf_stats;
extern int qdio_performance_stats;
int qdio_setup_perf_stats(void);
void qdio_remove_perf_stats(void);
extern void qdio_perf_stat_inc(atomic_long_t *count);
extern void qdio_perf_stat_dec(atomic_long_t *count);
#endif
此差异已折叠。
此差异已折叠。
......@@ -239,11 +239,6 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
/*not used unless the microcode gets patched*/
#define QETH_PCI_TIMER_VALUE(card) 3
#define QETH_MIN_INPUT_THRESHOLD 1
#define QETH_MAX_INPUT_THRESHOLD 500
#define QETH_MIN_OUTPUT_THRESHOLD 1
#define QETH_MAX_OUTPUT_THRESHOLD 300
/* priority queing */
#define QETH_PRIOQ_DEFAULT QETH_NO_PRIO_QUEUEING
#define QETH_DEFAULT_QUEUE 2
......@@ -811,17 +806,14 @@ int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *,
struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *,
enum qeth_ipa_cmds, enum qeth_prot_versions);
int qeth_query_setadapterparms(struct qeth_card *);
int qeth_check_qdio_errors(struct qdio_buffer *, unsigned int,
unsigned int, const char *);
int qeth_check_qdio_errors(struct qdio_buffer *, unsigned int, const char *);
void qeth_queue_input_buffer(struct qeth_card *, int);
struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
struct qdio_buffer *, struct qdio_buffer_element **, int *,
struct qeth_hdr **);
void qeth_schedule_recovery(struct qeth_card *);
void qeth_qdio_output_handler(struct ccw_device *, unsigned int,
unsigned int, unsigned int,
unsigned int, int, int,
unsigned long);
int, int, int, unsigned long);
void qeth_clear_ipacmd_list(struct qeth_card *);
int qeth_qdio_clear_card(struct qeth_card *, int);
void qeth_clear_working_pool_list(struct qeth_card *);
......
此差异已折叠。
......@@ -726,8 +726,7 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
unsigned int status, unsigned int qdio_err,
unsigned int siga_err, unsigned int queue,
unsigned int qdio_err, unsigned int queue,
int first_element, int count, unsigned long card_ptr)
{
struct net_device *net_dev;
......@@ -742,23 +741,20 @@ static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
card->perf_stats.inbound_cnt++;
card->perf_stats.inbound_start_time = qeth_get_micros();
}
if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
QETH_DBF_TEXT(TRACE, 1, "qdinchk");
QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", first_element,
count);
QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", queue, status);
qeth_schedule_recovery(card);
return;
}
if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
QETH_DBF_TEXT(TRACE, 1, "qdinchk");
QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", first_element,
count);
QETH_DBF_TEXT_(TRACE, 1, "%04X", queue);
qeth_schedule_recovery(card);
return;
}
for (i = first_element; i < (first_element + count); ++i) {
index = i % QDIO_MAX_BUFFERS_PER_Q;
buffer = &card->qdio.in_q->bufs[index];
if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
qeth_check_qdio_errors(buffer->buffer,
qdio_err, siga_err, "qinerr")))
if (!(qdio_err &&
qeth_check_qdio_errors(buffer->buffer, qdio_err, "qinerr")))
qeth_l2_process_inbound_buffer(card, buffer, index);
/* clear buffer and give back to hardware */
qeth_put_buffer_pool_entry(card, buffer->pool_entry);
......
......@@ -2939,8 +2939,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
}
static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
unsigned int status, unsigned int qdio_err,
unsigned int siga_err, unsigned int queue, int first_element,
unsigned int qdio_err, unsigned int queue, int first_element,
int count, unsigned long card_ptr)
{
struct net_device *net_dev;
......@@ -2955,23 +2954,21 @@ static void qeth_l3_qdio_input_handler(struct ccw_device *ccwdev,
card->perf_stats.inbound_cnt++;
card->perf_stats.inbound_start_time = qeth_get_micros();
}
if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
QETH_DBF_TEXT(TRACE, 1, "qdinchk");
QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
QETH_DBF_TEXT_(TRACE, 1, "%04X%04X",
first_element, count);
QETH_DBF_TEXT_(TRACE, 1, "%04X%04X", queue, status);
qeth_schedule_recovery(card);
return;
}
if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
QETH_DBF_TEXT(TRACE, 1, "qdinchk");
QETH_DBF_TEXT_(TRACE, 1, "%s", CARD_BUS_ID(card));
QETH_DBF_TEXT_(TRACE, 1, "%04X%04X",
first_element, count);
QETH_DBF_TEXT_(TRACE, 1, "%04X", queue);
qeth_schedule_recovery(card);
return;
}
for (i = first_element; i < (first_element + count); ++i) {
index = i % QDIO_MAX_BUFFERS_PER_Q;
buffer = &card->qdio.in_q->bufs[index];
if (!((status & QDIO_STATUS_LOOK_FOR_ERROR) &&
if (!(qdio_err &&
qeth_check_qdio_errors(buffer->buffer,
qdio_err, siga_err, "qinerr")))
qdio_err, "qinerr")))
qeth_l3_process_inbound_buffer(card, buffer, index);
/* clear buffer and give back to hardware */
qeth_put_buffer_pool_entry(card, buffer->pool_entry);
......
......@@ -297,15 +297,13 @@ void zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
/**
* zfcp_hba_dbf_event_qdio - trace event for QDIO related failure
* @adapter: adapter affected by this QDIO related event
* @status: as passed by qdio module
* @qdio_error: as passed by qdio module
* @siga_error: as passed by qdio module
* @sbal_index: first buffer with error condition, as passed by qdio module
* @sbal_count: number of buffers affected, as passed by qdio module
*/
void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
unsigned int qdio_error, unsigned int siga_error,
int sbal_index, int sbal_count)
void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter,
unsigned int qdio_error, int sbal_index,
int sbal_count)
{
struct zfcp_hba_dbf_record *r = &adapter->hba_dbf_buf;
unsigned long flags;
......@@ -313,9 +311,7 @@ void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
spin_lock_irqsave(&adapter->hba_dbf_lock, flags);
memset(r, 0, sizeof(*r));
strncpy(r->tag, "qdio", ZFCP_DBF_TAG_SIZE);
r->u.qdio.status = status;
r->u.qdio.qdio_error = qdio_error;
r->u.qdio.siga_error = siga_error;
r->u.qdio.sbal_index = sbal_index;
r->u.qdio.sbal_count = sbal_count;
debug_event(adapter->hba_dbf, 0, r, sizeof(*r));
......@@ -398,9 +394,7 @@ static void zfcp_hba_dbf_view_status(char **p,
static void zfcp_hba_dbf_view_qdio(char **p, struct zfcp_hba_dbf_record_qdio *r)
{
zfcp_dbf_out(p, "status", "0x%08x", r->status);
zfcp_dbf_out(p, "qdio_error", "0x%08x", r->qdio_error);
zfcp_dbf_out(p, "siga_error", "0x%08x", r->siga_error);
zfcp_dbf_out(p, "sbal_index", "0x%02x", r->sbal_index);
zfcp_dbf_out(p, "sbal_count", "0x%02x", r->sbal_count);
}
......
......@@ -139,9 +139,7 @@ struct zfcp_hba_dbf_record_status {
} __attribute__ ((packed));
struct zfcp_hba_dbf_record_qdio {
u32 status;
u32 qdio_error;
u32 siga_error;
u8 sbal_index;
u8 sbal_count;
} __attribute__ ((packed));
......
......@@ -48,9 +48,8 @@ extern void zfcp_rec_dbf_event_action(u8, struct zfcp_erp_action *);
extern void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *);
extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *,
struct fsf_status_read_buffer *);
extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *,
unsigned int, unsigned int, unsigned int,
int, int);
extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *, unsigned int, int,
int);
extern void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *);
extern void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *);
extern void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *);
......
此差异已折叠。
......@@ -8,9 +8,9 @@ header-y += ucontext.h
header-y += vtoc.h
header-y += zcrypt.h
header-y += kvm.h
header-y += schid.h
header-y += chsc.h
unifdef-y += cmb.h
unifdef-y += debug.h
unifdef-y += chpid.h
unifdef-y += schid.h
......@@ -20,6 +20,9 @@ struct chp_id {
u8 id;
} __attribute__((packed));
#ifdef __KERNEL__
#include <asm/cio.h>
static inline void chp_id_init(struct chp_id *chpid)
{
memset(chpid, 0, sizeof(struct chp_id));
......@@ -40,9 +43,6 @@ static inline void chp_id_next(struct chp_id *chpid)
}
}
#ifdef __KERNEL__
#include <asm/cio.h>
static inline int chp_id_is_valid(struct chp_id *chpid)
{
return (chpid->cssid <= __MAX_CSSID);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册