summaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/Kconfig2
-rw-r--r--drivers/s390/block/dasd_diag.c38
-rw-r--r--drivers/s390/block/dasd_eckd.c2
-rw-r--r--drivers/s390/block/dasd_fba.c2
-rw-r--r--drivers/s390/block/xpram.c54
-rw-r--r--drivers/s390/char/con3215.c2
-rw-r--r--drivers/s390/char/ctrlchar.c2
-rw-r--r--drivers/s390/char/fs3270.c12
-rw-r--r--drivers/s390/char/keyboard.c2
-rw-r--r--drivers/s390/char/monwriter.c12
-rw-r--r--drivers/s390/char/sclp.c35
-rw-r--r--drivers/s390/char/sclp_tty.c2
-rw-r--r--drivers/s390/char/sclp_vt220.c2
-rw-r--r--drivers/s390/char/tty3270.c3
-rw-r--r--drivers/s390/char/vmwatchdog.c52
-rw-r--r--drivers/s390/cio/chsc.c48
-rw-r--r--drivers/s390/cio/cio.c10
-rw-r--r--drivers/s390/cio/css.c2
-rw-r--r--drivers/s390/cio/css.h7
-rw-r--r--drivers/s390/cio/device.c48
-rw-r--r--drivers/s390/cio/device.h1
-rw-r--r--drivers/s390/cio/device_fsm.c115
-rw-r--r--drivers/s390/cio/device_id.c52
-rw-r--r--drivers/s390/cio/device_ops.c20
-rw-r--r--drivers/s390/cio/device_pgid.c31
-rw-r--r--drivers/s390/cio/device_status.c7
-rw-r--r--drivers/s390/cio/ioasm.h220
-rw-r--r--drivers/s390/cio/qdio.c10
-rw-r--r--drivers/s390/cio/qdio.h192
-rw-r--r--drivers/s390/crypto/ap_bus.c25
-rw-r--r--drivers/s390/net/iucv.c43
-rw-r--r--drivers/s390/net/qeth_main.c2
-rw-r--r--drivers/s390/s390mach.c95
-rw-r--r--drivers/s390/scsi/zfcp_aux.c84
-rw-r--r--drivers/s390/scsi/zfcp_ccw.c13
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c13
-rw-r--r--drivers/s390/scsi/zfcp_def.h24
-rw-r--r--drivers/s390/scsi/zfcp_erp.c233
-rw-r--r--drivers/s390/scsi/zfcp_ext.h18
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c299
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c114
41 files changed, 769 insertions, 1179 deletions
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index 929d6fff615..b250c535450 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -1,4 +1,4 @@
-if S390
+if S390 && BLOCK
comment "S/390 block device drivers"
depends on S390
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 23fa0b28917..53db58a6861 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -63,44 +63,26 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */
* and function code cmd.
* In case of an exception return 3. Otherwise return result of bitwise OR of
* resulting condition code and DIAG return code. */
-static __inline__ int
-dia250(void *iob, int cmd)
+static inline int dia250(void *iob, int cmd)
{
+ register unsigned long reg0 asm ("0") = (unsigned long) iob;
typedef union {
struct dasd_diag_init_io init_io;
struct dasd_diag_rw_io rw_io;
} addr_type;
int rc;
- __asm__ __volatile__(
-#ifdef CONFIG_64BIT
- " lghi %0,3\n"
- " lgr 0,%3\n"
- " diag 0,%2,0x250\n"
- "0: ipm %0\n"
- " srl %0,28\n"
- " or %0,1\n"
- "1:\n"
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 0b,1b\n"
- ".previous\n"
-#else
- " lhi %0,3\n"
- " lr 0,%3\n"
+ rc = 3;
+ asm volatile(
" diag 0,%2,0x250\n"
"0: ipm %0\n"
" srl %0,28\n"
" or %0,1\n"
"1:\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,1b\n"
- ".previous\n"
-#endif
- : "=&d" (rc), "=m" (*(addr_type *) iob)
- : "d" (cmd), "d" (iob), "m" (*(addr_type *) iob)
- : "0", "1", "cc");
+ EX_TABLE(0b,1b)
+ : "+d" (rc), "=m" (*(addr_type *) iob)
+ : "d" (cmd), "d" (reg0), "m" (*(addr_type *) iob)
+ : "1", "cc");
return rc;
}
@@ -236,7 +218,7 @@ dasd_diag_term_IO(struct dasd_ccw_req * cqr)
/* Handle external interruption. */
static void
-dasd_ext_handler(struct pt_regs *regs, __u16 code)
+dasd_ext_handler(__u16 code)
{
struct dasd_ccw_req *cqr, *next;
struct dasd_device *device;
@@ -547,7 +529,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
}
cqr->retries = DIAG_MAX_RETRIES;
cqr->buildclk = get_clock();
- if (req->flags & REQ_FAILFAST)
+ if (req->cmd_flags & REQ_FAILFAST)
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->device = device;
cqr->expires = DIAG_TIMEOUT;
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index b7a7fac3f7c..5ecea3e4fde 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1266,7 +1266,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
recid++;
}
}
- if (req->flags & REQ_FAILFAST)
+ if (req->cmd_flags & REQ_FAILFAST)
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->device = device;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index e85015be109..80926c54822 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -344,7 +344,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req)
recid++;
}
}
- if (req->flags & REQ_FAILFAST)
+ if (req->cmd_flags & REQ_FAILFAST)
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->device = device;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index cab2c736683..a04d9120cef 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -89,28 +89,15 @@ MODULE_LICENSE("GPL");
*/
static int xpram_page_in (unsigned long page_addr, unsigned int xpage_index)
{
- int cc;
+ int cc = 2; /* return unused cc 2 if pgin traps */
- __asm__ __volatile__ (
- " lhi %0,2\n" /* return unused cc 2 if pgin traps */
- " .insn rre,0xb22e0000,%1,%2\n" /* pgin %1,%2 */
- "0: ipm %0\n"
- " srl %0,28\n"
+ asm volatile(
+ " .insn rre,0xb22e0000,%1,%2\n" /* pgin %1,%2 */
+ "0: ipm %0\n"
+ " srl %0,28\n"
"1:\n"
-#ifndef CONFIG_64BIT
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,1b\n"
- ".previous"
-#else
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 0b,1b\n"
- ".previous"
-#endif
- : "=&d" (cc)
- : "a" (__pa(page_addr)), "a" (xpage_index)
- : "cc" );
+ EX_TABLE(0b,1b)
+ : "+d" (cc) : "a" (__pa(page_addr)), "d" (xpage_index) : "cc");
if (cc == 3)
return -ENXIO;
if (cc == 2) {
@@ -137,28 +124,15 @@ static int xpram_page_in (unsigned long page_addr, unsigned int xpage_index)
*/
static long xpram_page_out (unsigned long page_addr, unsigned int xpage_index)
{
- int cc;
+ int cc = 2; /* return unused cc 2 if pgin traps */
- __asm__ __volatile__ (
- " lhi %0,2\n" /* return unused cc 2 if pgout traps */
- " .insn rre,0xb22f0000,%1,%2\n" /* pgout %1,%2 */
- "0: ipm %0\n"
- " srl %0,28\n"
+ asm volatile(
+ " .insn rre,0xb22f0000,%1,%2\n" /* pgout %1,%2 */
+ "0: ipm %0\n"
+ " srl %0,28\n"
"1:\n"
-#ifndef CONFIG_64BIT
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,1b\n"
- ".previous"
-#else
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 0b,1b\n"
- ".previous"
-#endif
- : "=&d" (cc)
- : "a" (__pa(page_addr)), "a" (xpage_index)
- : "cc" );
+ EX_TABLE(0b,1b)
+ : "+d" (cc) : "a" (__pa(page_addr)), "d" (xpage_index) : "cc");
if (cc == 3)
return -ENXIO;
if (cc == 2) {
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 2fa566fa6da..d7de175d53f 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -1103,7 +1103,7 @@ tty3215_start(struct tty_struct *tty)
}
}
-static struct tty_operations tty3215_ops = {
+static const struct tty_operations tty3215_ops = {
.open = tty3215_open,
.close = tty3215_close,
.write = tty3215_write,
diff --git a/drivers/s390/char/ctrlchar.c b/drivers/s390/char/ctrlchar.c
index d83eb6358ba..49e9628d929 100644
--- a/drivers/s390/char/ctrlchar.c
+++ b/drivers/s390/char/ctrlchar.c
@@ -20,7 +20,7 @@ static int ctrlchar_sysrq_key;
static void
ctrlchar_handle_sysrq(void *tty)
{
- handle_sysrq(ctrlchar_sysrq_key, NULL, (struct tty_struct *) tty);
+ handle_sysrq(ctrlchar_sysrq_key, (struct tty_struct *) tty);
}
static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq, NULL);
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index ef004d08971..78f8bda81da 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -17,7 +17,6 @@
#include <asm/ccwdev.h>
#include <asm/cio.h>
-#include <asm/cpcmd.h>
#include <asm/ebcdic.h>
#include <asm/idals.h>
@@ -28,7 +27,7 @@ struct raw3270_fn fs3270_fn;
struct fs3270 {
struct raw3270_view view;
- pid_t fs_pid; /* Pid of controlling program. */
+ struct pid *fs_pid; /* Pid of controlling program. */
int read_command; /* ccw command to use for reads. */
int write_command; /* ccw command to use for writes. */
int attention; /* Got attention. */
@@ -103,7 +102,7 @@ fs3270_restore_callback(struct raw3270_request *rq, void *data)
fp = (struct fs3270 *) rq->view;
if (rq->rc != 0 || rq->rescnt != 0) {
if (fp->fs_pid)
- kill_proc(fp->fs_pid, SIGHUP, 1);
+ kill_pid(fp->fs_pid, SIGHUP, 1);
}
fp->rdbuf_size = 0;
raw3270_request_reset(rq);
@@ -174,7 +173,7 @@ fs3270_save_callback(struct raw3270_request *rq, void *data)
*/
if (rq->rc != 0 || rq->rescnt == 0) {
if (fp->fs_pid)
- kill_proc(fp->fs_pid, SIGHUP, 1);
+ kill_pid(fp->fs_pid, SIGHUP, 1);
fp->rdbuf_size = 0;
} else
fp->rdbuf_size = fp->rdbuf->size - rq->rescnt;
@@ -443,7 +442,7 @@ fs3270_open(struct inode *inode, struct file *filp)
return PTR_ERR(fp);
init_waitqueue_head(&fp->wait);
- fp->fs_pid = current->pid;
+ fp->fs_pid = get_pid(task_pid(current));
rc = raw3270_add_view(&fp->view, &fs3270_fn, minor);
if (rc) {
fs3270_free_view(&fp->view);
@@ -481,7 +480,8 @@ fs3270_close(struct inode *inode, struct file *filp)
fp = filp->private_data;
filp->private_data = NULL;
if (fp) {
- fp->fs_pid = 0;
+ put_pid(fp->fs_pid);
+ fp->fs_pid = NULL;
raw3270_reset(&fp->view);
raw3270_put_view(&fp->view);
raw3270_del_view(&fp->view);
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 3be06569180..e3491a5f521 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -304,7 +304,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
if (kbd->sysrq) {
if (kbd->sysrq == K(KT_LATIN, '-')) {
kbd->sysrq = 0;
- handle_sysrq(value, NULL, kbd->tty);
+ handle_sysrq(value, kbd->tty);
return;
}
if (value == '-') {
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c
index 1e3939aeb8a..abd02ed501c 100644
--- a/drivers/s390/char/monwriter.c
+++ b/drivers/s390/char/monwriter.c
@@ -26,6 +26,7 @@
#define MONWRITE_MAX_DATALEN 4024
static int mon_max_bufs = 255;
+static int mon_buf_count;
struct mon_buf {
struct list_head list;
@@ -40,7 +41,6 @@ struct mon_private {
size_t hdr_to_read;
size_t data_to_read;
struct mon_buf *current_buf;
- int mon_buf_count;
};
/*
@@ -99,18 +99,18 @@ static int monwrite_new_hdr(struct mon_private *monpriv)
rc = monwrite_diag(monhdr, monbuf->data,
APPLDATA_STOP_REC);
list_del(&monbuf->list);
- monpriv->mon_buf_count--;
+ mon_buf_count--;
kfree(monbuf->data);
kfree(monbuf);
monbuf = NULL;
}
} else {
- if (monpriv->mon_buf_count >= mon_max_bufs)
+ if (mon_buf_count >= mon_max_bufs)
return -ENOSPC;
monbuf = kzalloc(sizeof(struct mon_buf), GFP_KERNEL);
if (!monbuf)
return -ENOMEM;
- monbuf->data = kzalloc(monbuf->hdr.datalen,
+ monbuf->data = kzalloc(monhdr->datalen,
GFP_KERNEL | GFP_DMA);
if (!monbuf->data) {
kfree(monbuf);
@@ -118,7 +118,7 @@ static int monwrite_new_hdr(struct mon_private *monpriv)
}
monbuf->hdr = *monhdr;
list_add_tail(&monbuf->list, &monpriv->list);
- monpriv->mon_buf_count++;
+ mon_buf_count++;
}
monpriv->current_buf = monbuf;
return 0;
@@ -186,7 +186,7 @@ static int monwrite_close(struct inode *inode, struct file *filp)
if (entry->hdr.mon_function != MONWRITE_GEN_EVENT)
monwrite_diag(&entry->hdr, entry->data,
APPLDATA_STOP_REC);
- monpriv->mon_buf_count--;
+ mon_buf_count--;
list_del(&entry->list);
kfree(entry->data);
kfree(entry);
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 985d1613baa..8a056df09d6 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -100,13 +100,12 @@ service_call(sclp_cmdw_t command, void *sccb)
{
int cc;
- __asm__ __volatile__(
- " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */
- " ipm %0\n"
- " srl %0,28"
- : "=&d" (cc)
- : "d" (command), "a" (__pa(sccb))
- : "cc", "memory" );
+ asm volatile(
+ " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */
+ " ipm %0\n"
+ " srl %0,28"
+ : "=&d" (cc) : "d" (command), "a" (__pa(sccb))
+ : "cc", "memory");
if (cc == 3)
return -EIO;
if (cc == 2)
@@ -325,7 +324,7 @@ __sclp_find_req(u32 sccb)
* Prepare read event data request if necessary. Start processing of next
* request on queue. */
static void
-sclp_interrupt_handler(struct pt_regs *regs, __u16 code)
+sclp_interrupt_handler(__u16 code)
{
struct sclp_req *req;
u32 finished_sccb;
@@ -360,16 +359,6 @@ sclp_interrupt_handler(struct pt_regs *regs, __u16 code)
sclp_process_queue();
}
-/* Return current Time-Of-Day clock. */
-static inline u64
-sclp_get_clock(void)
-{
- u64 result;
-
- asm volatile ("STCK 0(%1)" : "=m" (result) : "a" (&(result)) : "cc");
- return result;
-}
-
/* Convert interval in jiffies to TOD ticks. */
static inline u64
sclp_tod_from_jiffies(unsigned long jiffies)
@@ -382,7 +371,6 @@ sclp_tod_from_jiffies(unsigned long jiffies)
void
sclp_sync_wait(void)
{
- unsigned long psw_mask;
unsigned long flags;
unsigned long cr0, cr0_sync;
u64 timeout;
@@ -392,7 +380,7 @@ sclp_sync_wait(void)
timeout = 0;
if (timer_pending(&sclp_request_timer)) {
/* Get timeout TOD value */
- timeout = sclp_get_clock() +
+ timeout = get_clock() +
sclp_tod_from_jiffies(sclp_request_timer.expires -
jiffies);
}
@@ -406,13 +394,12 @@ sclp_sync_wait(void)
cr0_sync |= 0x00000200;
cr0_sync &= 0xFFFFF3AC;
__ctl_load(cr0_sync, 0, 0);
- asm volatile ("STOSM 0(%1),0x01"
- : "=m" (psw_mask) : "a" (&psw_mask) : "memory");
+ __raw_local_irq_stosm(0x01);
/* Loop until driver state indicates finished request */
while (sclp_running_state != sclp_running_state_idle) {
/* Check for expired request timer */
if (timer_pending(&sclp_request_timer) &&
- sclp_get_clock() > timeout &&
+ get_clock() > timeout &&
del_timer(&sclp_request_timer))
sclp_request_timer.function(sclp_request_timer.data);
barrier();
@@ -756,7 +743,7 @@ EXPORT_SYMBOL(sclp_reactivate);
/* Handler for external interruption used during initialization. Modify
* request state to done. */
static void
-sclp_check_handler(struct pt_regs *regs, __u16 code)
+sclp_check_handler(__u16 code)
{
u32 finished_sccb;
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index f6cf9023039..6f43e04dbef 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -711,7 +711,7 @@ static struct sclp_register sclp_input_event =
.receiver_fn = sclp_tty_receiver
};
-static struct tty_operations sclp_ops = {
+static const struct tty_operations sclp_ops = {
.open = sclp_tty_open,
.close = sclp_tty_close,
.write = sclp_tty_write,
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 54fba6f1718..723bf4191bf 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -655,7 +655,7 @@ __sclp_vt220_init(int early)
return 0;
}
-static struct tty_operations sclp_vt220_ops = {
+static const struct tty_operations sclp_vt220_ops = {
.open = sclp_vt220_open,
.close = sclp_vt220_close,
.write = sclp_vt220_write,
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 29718042c6c..4717c361160 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -698,7 +698,6 @@ tty3270_alloc_view(void)
if (!tp->freemem_pages)
goto out_tp;
INIT_LIST_HEAD(&tp->freemem);
- init_timer(&tp->timer);
for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) {
tp->freemem_pages[pages] = (void *)
__get_free_pages(GFP_KERNEL|GFP_DMA, 0);
@@ -1738,7 +1737,7 @@ tty3270_ioctl(struct tty_struct *tty, struct file *file,
return kbd_ioctl(tp->kbd, file, cmd, arg);
}
-static struct tty_operations tty3270_ops = {
+static const struct tty_operations tty3270_ops = {
.open = tty3270_open,
.close = tty3270_close,
.write = tty3270_write,
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 807320a41fa..4b868f72fe8 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -54,48 +54,20 @@ enum vmwdt_func {
static int __diag288(enum vmwdt_func func, unsigned int timeout,
char *cmd, size_t len)
{
- register unsigned long __func asm("2");
- register unsigned long __timeout asm("3");
- register unsigned long __cmdp asm("4");
- register unsigned long __cmdl asm("5");
+ register unsigned long __func asm("2") = func;
+ register unsigned long __timeout asm("3") = timeout;
+ register unsigned long __cmdp asm("4") = virt_to_phys(cmd);
+ register unsigned long __cmdl asm("5") = len;
int err;
- __func = func;
- __timeout = timeout;
- __cmdp = virt_to_phys(cmd);
- __cmdl = len;
- err = 0;
- asm volatile (
-#ifdef CONFIG_64BIT
- "diag %2,%4,0x288\n"
- "1: \n"
- ".section .fixup,\"ax\"\n"
- "2: lghi %0,%1\n"
- " jg 1b\n"
- ".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 1b,2b\n"
- ".previous\n"
-#else
- "diag %2,%4,0x288\n"
- "1: \n"
- ".section .fixup,\"ax\"\n"
- "2: lhi %0,%1\n"
- " bras 1,3f\n"
- " .long 1b\n"
- "3: l 1,0(1)\n"
- " br 1\n"
- ".previous\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 1b,2b\n"
- ".previous\n"
-#endif
- : "+&d"(err)
- : "i"(-EINVAL), "d"(__func), "d"(__timeout),
- "d"(__cmdp), "d"(__cmdl)
- : "1", "cc");
+ err = -EINVAL;
+ asm volatile(
+ " diag %1,%3,0x288\n"
+ "0: la %0,0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "=d" (err) : "d"(__func), "d"(__timeout),
+ "d"(__cmdp), "d"(__cmdl), "0" (-EINVAL) : "1", "cc");
return err;
}
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 3bb4e472d73..2d78f0f4a40 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -200,11 +200,13 @@ css_get_ssd_info(struct subchannel *sch)
spin_unlock_irq(&sch->lock);
free_page((unsigned long)page);
if (!ret) {
- int j, chpid;
+ int j, chpid, mask;
/* Allocate channel path structures, if needed. */
for (j = 0; j < 8; j++) {
+ mask = 0x80 >> j;
chpid = sch->ssd_info.chpid[j];
- if (chpid && (get_chp_status(chpid) < 0))
+ if ((sch->schib.pmcw.pim & mask) &&
+ (get_chp_status(chpid) < 0))
new_channel_path(chpid);
}
}
@@ -222,13 +224,15 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
sch = to_subchannel(dev);
chpid = data;
- for (j = 0; j < 8; j++)
- if (sch->schib.pmcw.chpid[j] == chpid->id)
+ for (j = 0; j < 8; j++) {
+ mask = 0x80 >> j;
+ if ((sch->schib.pmcw.pim & mask) &&
+ (sch->schib.pmcw.chpid[j] == chpid->id))
break;
+ }
if (j >= 8)
return 0;
- mask = 0x80 >> j;
spin_lock_irq(&sch->lock);
stsch(sch->schid, &schib);
@@ -366,7 +370,7 @@ __s390_process_res_acc(struct subchannel_id schid, void *data)
struct res_acc_data *res_data;
struct subchannel *sch;
- res_data = (struct res_acc_data *)data;
+ res_data = data;
sch = get_subchannel_by_schid(schid);
if (!sch)
/* Check if a subchannel is newly available. */
@@ -440,7 +444,7 @@ __get_chpid_from_lir(void *data)
u32 isinfo[28];
} *lir;
- lir = (struct lir*) data;
+ lir = data;
if (!(lir->iq&0x80))
/* NULL link incident record */
return -EINVAL;
@@ -620,18 +624,20 @@ __chp_add_new_sch(struct subchannel_id schid)
static int
__chp_add(struct subchannel_id schid, void *data)
{
- int i;
+ int i, mask;
struct channel_path *chp;
struct subchannel *sch;
- chp = (struct channel_path *)data;
+ chp = data;
sch = get_subchannel_by_schid(schid);
if (!sch)
/* Check if the subchannel is now available. */
return __chp_add_new_sch(schid);
spin_lock_irq(&sch->lock);
- for (i=0; i<8; i++)
- if (sch->schib.pmcw.chpid[i] == chp->id) {
+ for (i=0; i<8; i++) {
+ mask = 0x80 >> i;
+ if ((sch->schib.pmcw.pim & mask) &&
+ (sch->schib.pmcw.chpid[i] == chp->id)) {
if (stsch(sch->schid, &sch->schib) != 0) {
/* Endgame. */
spin_unlock_irq(&sch->lock);
@@ -639,6 +645,7 @@ __chp_add(struct subchannel_id schid, void *data)
}
break;
}
+ }
if (i==8) {
spin_unlock_irq(&sch->lock);
return 0;
@@ -646,7 +653,7 @@ __chp_add(struct subchannel_id schid, void *data)
sch->lpm = ((sch->schib.pmcw.pim &
sch->schib.pmcw.pam &
sch->schib.pmcw.pom)
- | 0x80 >> i) & sch->opm;
+ | mask) & sch->opm;
if (sch->driver && sch->driver->verify)
sch->driver->verify(&sch->dev);
@@ -700,8 +707,7 @@ chp_process_crw(int chpid, int on)
return chp_add(chpid);
}
-static inline int
-__check_for_io_and_kill(struct subchannel *sch, int index)
+static inline int check_for_io_on_path(struct subchannel *sch, int index)
{
int cc;
@@ -711,10 +717,8 @@ __check_for_io_and_kill(struct subchannel *sch, int index)
cc = stsch(sch->schid, &sch->schib);
if (cc)
return 0;
- if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) {
- device_set_waiting(sch);
+ if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index))
return 1;
- }
return 0;
}
@@ -743,12 +747,10 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
} else {
sch->opm &= ~(0x80 >> chp);
sch->lpm &= ~(0x80 >> chp);
- /*
- * Give running I/O a grace period in which it
- * can successfully terminate, even using the
- * just varied off path. Then kill it.
- */
- if (!__check_for_io_and_kill(sch, chp) && !sch->lpm) {
+ if (check_for_io_on_path(sch, chp))
+ /* Path verification is done after killing. */
+ device_kill_io(sch);
+ else if (!sch->lpm) {
if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
need_rescan = 1;
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 2e2882daefb..8936e460a80 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -19,6 +19,7 @@
#include <asm/cio.h>
#include <asm/delay.h>
#include <asm/irq.h>
+#include <asm/irq_regs.h>
#include <asm/setup.h>
#include "airq.h"
#include "cio.h"
@@ -606,15 +607,17 @@ do_IRQ (struct pt_regs *regs)
struct tpi_info *tpi_info;
struct subchannel *sch;
struct irb *irb;
+ struct pt_regs *old_regs;
- irq_enter ();
+ old_regs = set_irq_regs(regs);
+ irq_enter();
asm volatile ("mc 0,0");
if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer)
/**
* Make sure that the i/o interrupt did not "overtake"
* the last HZ timer interrupt.
*/
- account_ticks(regs);
+ account_ticks();
/*
* Get interrupt information from lowcore
*/
@@ -652,7 +655,8 @@ do_IRQ (struct pt_regs *regs)
* out of the sie which costs more cycles than it saves.
*/
} while (!MACHINE_IS_VM && tpi (NULL) != 0);
- irq_exit ();
+ irq_exit();
+ set_irq_regs(old_regs);
}
#ifdef CONFIG_CCW_CONSOLE
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 7086a74e987..a2dee5bf5a1 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -177,7 +177,7 @@ get_subchannel_by_schid(struct subchannel_id schid)
struct device *dev;
dev = bus_find_device(&css_bus_type, NULL,
- (void *)&schid, check_subchannel);
+ &schid, check_subchannel);
return dev ? to_subchannel(dev) : NULL;
}
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 8aabb4adeb5..4c2ff833628 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -76,9 +76,8 @@ struct ccw_device_private {
int state; /* device state */
atomic_t onoff;
unsigned long registered;
- __u16 devno; /* device number */
- __u16 sch_no; /* subchannel number */
- __u8 ssid; /* subchannel set id */
+ struct ccw_dev_id dev_id; /* device id */
+ struct subchannel_id schid; /* subchannel number */
__u8 imask; /* lpm mask for SNID/SID/SPGID */
int iretry; /* retry counter SNID/SID/SPGID */
struct {
@@ -171,7 +170,7 @@ void device_trigger_reprobe(struct subchannel *);
/* Helper functions for vary on/off. */
int device_is_online(struct subchannel *);
-void device_set_waiting(struct subchannel *);
+void device_kill_io(struct subchannel *);
/* Machine check helper function. */
void device_kill_pending_timer(struct subchannel *);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 688945662c1..94bdd4d8a4c 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -552,21 +552,19 @@ ccw_device_register(struct ccw_device *cdev)
}
struct match_data {
- unsigned int devno;
- unsigned int ssid;
+ struct ccw_dev_id dev_id;
struct ccw_device * sibling;
};
static int
match_devno(struct device * dev, void * data)
{
- struct match_data * d = (struct match_data *)data;
+ struct match_data * d = data;
struct ccw_device * cdev;
cdev = to_ccwdev(dev);
if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
- (cdev->private->devno == d->devno) &&
- (cdev->private->ssid == d->ssid) &&
+ ccw_dev_id_is_equal(&cdev->private->dev_id, &d->dev_id) &&
(cdev != d->sibling)) {
cdev->private->state = DEV_STATE_NOT_OPER;
return 1;
@@ -574,15 +572,13 @@ match_devno(struct device * dev, void * data)
return 0;
}
-static struct ccw_device *
-get_disc_ccwdev_by_devno(unsigned int devno, unsigned int ssid,
- struct ccw_device *sibling)
+static struct ccw_device * get_disc_ccwdev_by_dev_id(struct ccw_dev_id *dev_id,
+ struct ccw_device *sibling)
{
struct device *dev;
struct match_data data;
- data.devno = devno;
- data.ssid = ssid;
+ data.dev_id = *dev_id;
data.sibling = sibling;
dev = bus_find_device(&ccw_bus_type, NULL, &data, match_devno);
@@ -595,7 +591,7 @@ ccw_device_add_changed(void *data)
struct ccw_device *cdev;
- cdev = (struct ccw_device *)data;
+ cdev = data;
if (device_add(&cdev->dev)) {
put_device(&cdev->dev);
return;
@@ -616,9 +612,9 @@ ccw_device_do_unreg_rereg(void *data)
struct subchannel *sch;
int need_rename;
- cdev = (struct ccw_device *)data;
+ cdev = data;
sch = to_subchannel(cdev->dev.parent);
- if (cdev->private->devno != sch->schib.pmcw.dev) {
+ if (cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
/*
* The device number has changed. This is usually only when
* a device has been detached under VM and then re-appeared
@@ -633,10 +629,12 @@ ccw_device_do_unreg_rereg(void *data)
* get possibly sick...
*/
struct ccw_device *other_cdev;
+ struct ccw_dev_id dev_id;
need_rename = 1;
- other_cdev = get_disc_ccwdev_by_devno(sch->schib.pmcw.dev,
- sch->schid.ssid, cdev);
+ dev_id.devno = sch->schib.pmcw.dev;
+ dev_id.ssid = sch->schid.ssid;
+ other_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev);
if (other_cdev) {
struct subchannel *other_sch;
@@ -652,7 +650,7 @@ ccw_device_do_unreg_rereg(void *data)
}
/* Update ssd info here. */
css_get_ssd_info(sch);
- cdev->private->devno = sch->schib.pmcw.dev;
+ cdev->private->dev_id.devno = sch->schib.pmcw.dev;
} else
need_rename = 0;
device_remove_files(&cdev->dev);
@@ -662,7 +660,7 @@ ccw_device_do_unreg_rereg(void *data)
snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
sch->schid.ssid, sch->schib.pmcw.dev);
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_add_changed, (void *)cdev);
+ ccw_device_add_changed, cdev);
queue_work(ccw_device_work, &cdev->private->kick_work);
}
@@ -687,7 +685,7 @@ io_subchannel_register(void *data)
int ret;
unsigned long flags;
- cdev = (struct ccw_device *) data;
+ cdev = data;
sch = to_subchannel(cdev->dev.parent);
if (klist_node_attached(&cdev->dev.knode_parent)) {
@@ -759,7 +757,7 @@ io_subchannel_recog_done(struct ccw_device *cdev)
break;
sch = to_subchannel(cdev->dev.parent);
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_call_sch_unregister, (void *) cdev);
+ ccw_device_call_sch_unregister, cdev);
queue_work(slow_path_wq, &cdev->private->kick_work);
if (atomic_dec_and_test(&ccw_device_init_count))
wake_up(&ccw_device_init_wq);
@@ -774,7 +772,7 @@ io_subchannel_recog_done(struct ccw_device *cdev)
if (!get_device(&cdev->dev))
break;
PREPARE_WORK(&cdev->private->kick_work,
- io_subchannel_register, (void *) cdev);
+ io_subchannel_register, cdev);
queue_work(slow_path_wq, &cdev->private->kick_work);
break;
}
@@ -792,9 +790,9 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
/* Init private data. */
priv = cdev->private;
- priv->devno = sch->schib.pmcw.dev;
- priv->ssid = sch->schid.ssid;
- priv->sch_no = sch->schid.sch_no;
+ priv->dev_id.devno = sch->schib.pmcw.dev;
+ priv->dev_id.ssid = sch->schid.ssid;
+ priv->schid = sch->schid;
priv->state = DEV_STATE_NOT_OPER;
INIT_LIST_HEAD(&priv->cmb_list);
init_waitqueue_head(&priv->wait_q);
@@ -912,7 +910,7 @@ io_subchannel_remove (struct subchannel *sch)
*/
if (get_device(&cdev->dev)) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_unregister, (void *) cdev);
+ ccw_device_unregister, cdev);
queue_work(ccw_device_work, &cdev->private->kick_work);
}
return 0;
@@ -1055,7 +1053,7 @@ __ccwdev_check_busid(struct device *dev, void *id)
{
char *bus_id;
- bus_id = (char *)id;
+ bus_id = id;
return (strncmp(bus_id, dev->bus_id, BUS_ID_SIZE) == 0);
}
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 00be9a5b4ac..c6140cc97a8 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -21,7 +21,6 @@ enum dev_state {
/* states to wait for i/o completion before doing something */
DEV_STATE_CLEAR_VERIFY,
DEV_STATE_TIMEOUT_KILL,
- DEV_STATE_WAIT4IO,
DEV_STATE_QUIESCE,
/* special states for devices gone not operational */
DEV_STATE_DISCONNECTED,
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index dace46fc32e..fcaf28d7b4e 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -59,18 +59,6 @@ device_set_disconnected(struct subchannel *sch)
cdev->private->state = DEV_STATE_DISCONNECTED;
}
-void
-device_set_waiting(struct subchannel *sch)
-{
- struct ccw_device *cdev;
-
- if (!sch->dev.driver_data)
- return;
- cdev = sch->dev.driver_data;
- ccw_device_set_timeout(cdev, 10*HZ);
- cdev->private->state = DEV_STATE_WAIT4IO;
-}
-
/*
* Timeout function. It just triggers a DEV_EVENT_TIMEOUT.
*/
@@ -183,9 +171,9 @@ ccw_device_handle_oper(struct ccw_device *cdev)
cdev->id.cu_model != cdev->private->senseid.cu_model ||
cdev->id.dev_type != cdev->private->senseid.dev_type ||
cdev->id.dev_model != cdev->private->senseid.dev_model ||
- cdev->private->devno != sch->schib.pmcw.dev) {
+ cdev->private->dev_id.devno != sch->schib.pmcw.dev) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_do_unreg_rereg, (void *)cdev);
+ ccw_device_do_unreg_rereg, cdev);
queue_work(ccw_device_work, &cdev->private->kick_work);
return 0;
}
@@ -255,7 +243,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
case DEV_STATE_NOT_OPER:
CIO_DEBUG(KERN_WARNING, 2,
"SenseID : unknown device %04x on subchannel "
- "0.%x.%04x\n", cdev->private->devno,
+ "0.%x.%04x\n", cdev->private->dev_id.devno,
sch->schid.ssid, sch->schid.sch_no);
break;
case DEV_STATE_OFFLINE:
@@ -282,14 +270,15 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: "
"CU Type/Mod = %04X/%02X, Dev Type/Mod = "
"%04X/%02X\n",
- cdev->private->ssid, cdev->private->devno,
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno,
cdev->id.cu_type, cdev->id.cu_model,
cdev->id.dev_type, cdev->id.dev_model);
break;
case DEV_STATE_BOXED:
CIO_DEBUG(KERN_WARNING, 2,
"SenseID : boxed device %04x on subchannel "
- "0.%x.%04x\n", cdev->private->devno,
+ "0.%x.%04x\n", cdev->private->dev_id.devno,
sch->schid.ssid, sch->schid.sch_no);
break;
}
@@ -325,13 +314,13 @@ ccw_device_oper_notify(void *data)
struct subchannel *sch;
int ret;
- cdev = (struct ccw_device *)data;
+ cdev = data;
sch = to_subchannel(cdev->dev.parent);
ret = (sch->driver && sch->driver->notify) ?
sch->driver->notify(&sch->dev, CIO_OPER) : 0;
if (!ret)
/* Driver doesn't want device back. */
- ccw_device_do_unreg_rereg((void *)cdev);
+ ccw_device_do_unreg_rereg(cdev);
else {
/* Reenable channel measurements, if needed. */
cmf_reenable(cdev);
@@ -349,6 +338,8 @@ ccw_device_done(struct ccw_device *cdev, int state)
sch = to_subchannel(cdev->dev.parent);
+ ccw_device_set_timeout(cdev, 0);
+
if (state != DEV_STATE_ONLINE)
cio_disable_subchannel(sch);
@@ -361,12 +352,12 @@ ccw_device_done(struct ccw_device *cdev, int state)
if (state == DEV_STATE_BOXED)
CIO_DEBUG(KERN_WARNING, 2,
"Boxed device %04x on subchannel %04x\n",
- cdev->private->devno, sch->schid.sch_no);
+ cdev->private->dev_id.devno, sch->schid.sch_no);
if (cdev->private->flags.donotify) {
cdev->private->flags.donotify = 0;
PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify,
- (void *)cdev);
+ cdev);
queue_work(ccw_device_notify_work, &cdev->private->kick_work);
}
wake_up(&cdev->private->wait_q);
@@ -410,7 +401,8 @@ static void __ccw_device_get_common_pgid(struct ccw_device *cdev)
/* PGID mismatch, can't pathgroup. */
CIO_MSG_EVENT(0, "SNID - pgid mismatch for device "
"0.%x.%04x, can't pathgroup\n",
- cdev->private->ssid, cdev->private->devno);
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno);
cdev->private->options.pgroup = 0;
return;
}
@@ -521,7 +513,7 @@ ccw_device_nopath_notify(void *data)
struct subchannel *sch;
int ret;
- cdev = (struct ccw_device *)data;
+ cdev = data;
sch = to_subchannel(cdev->dev.parent);
/* Extra sanity. */
if (sch->lpm)
@@ -535,7 +527,7 @@ ccw_device_nopath_notify(void *data)
if (get_device(&cdev->dev)) {
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_call_sch_unregister,
- (void *)cdev);
+ cdev);
queue_work(ccw_device_work,
&cdev->private->kick_work);
} else
@@ -590,7 +582,7 @@ ccw_device_verify_done(struct ccw_device *cdev, int err)
break;
default:
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, (void *)cdev);
+ ccw_device_nopath_notify, cdev);
queue_work(ccw_device_notify_work, &cdev->private->kick_work);
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
break;
@@ -721,7 +713,7 @@ ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event)
sch = to_subchannel(cdev->dev.parent);
if (get_device(&cdev->dev)) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_call_sch_unregister, (void *)cdev);
+ ccw_device_call_sch_unregister, cdev);
queue_work(ccw_device_work, &cdev->private->kick_work);
}
wake_up(&cdev->private->wait_q);
@@ -752,7 +744,7 @@ ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event)
}
if (get_device(&cdev->dev)) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_call_sch_unregister, (void *)cdev);
+ ccw_device_call_sch_unregister, cdev);
queue_work(ccw_device_work, &cdev->private->kick_work);
}
wake_up(&cdev->private->wait_q);
@@ -857,7 +849,7 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
sch = to_subchannel(cdev->dev.parent);
if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, (void *)cdev);
+ ccw_device_nopath_notify, cdev);
queue_work(ccw_device_notify_work,
&cdev->private->kick_work);
} else
@@ -883,7 +875,8 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
/* Basic sense hasn't started. Try again. */
ccw_device_do_sense(cdev, irb);
else {
- printk("Huh? %s(%s): unsolicited interrupt...\n",
+ printk(KERN_INFO "Huh? %s(%s): unsolicited "
+ "interrupt...\n",
__FUNCTION__, cdev->dev.bus_id);
if (cdev->handler)
cdev->handler (cdev, 0, irb);
@@ -942,10 +935,10 @@ ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
cdev->private->state = DEV_STATE_ONLINE;
if (cdev->handler)
cdev->handler(cdev, cdev->private->intparm,
- ERR_PTR(-ETIMEDOUT));
+ ERR_PTR(-EIO));
if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, (void *)cdev);
+ ccw_device_nopath_notify, cdev);
queue_work(ccw_device_notify_work, &cdev->private->kick_work);
} else if (cdev->private->flags.doverify)
/* Start delayed path verification. */
@@ -968,7 +961,7 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
sch = to_subchannel(cdev->dev.parent);
if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, (void *)cdev);
+ ccw_device_nopath_notify, cdev);
queue_work(ccw_device_notify_work,
&cdev->private->kick_work);
} else
@@ -979,51 +972,15 @@ ccw_device_killing_timeout(struct ccw_device *cdev, enum dev_event dev_event)
cdev->private->state = DEV_STATE_ONLINE;
if (cdev->handler)
cdev->handler(cdev, cdev->private->intparm,
- ERR_PTR(-ETIMEDOUT));
-}
-
-static void
-ccw_device_wait4io_irq(struct ccw_device *cdev, enum dev_event dev_event)
-{
- struct irb *irb;
- struct subchannel *sch;
-
- irb = (struct irb *) __LC_IRB;
- /*
- * Accumulate status and find out if a basic sense is needed.
- * This is fine since we have already adapted the lpm.
- */
- ccw_device_accumulate_irb(cdev, irb);
- if (cdev->private->flags.dosense) {
- if (ccw_device_do_sense(cdev, irb) == 0) {
- cdev->private->state = DEV_STATE_W4SENSE;
- }
- return;
- }
-
- /* Iff device is idle, reset timeout. */
- sch = to_subchannel(cdev->dev.parent);
- if (!stsch(sch->schid, &sch->schib))
- if (sch->schib.scsw.actl == 0)
- ccw_device_set_timeout(cdev, 0);
- /* Call the handler. */
- ccw_device_call_handler(cdev);
- if (!sch->lpm) {
- PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, (void *)cdev);
- queue_work(ccw_device_notify_work, &cdev->private->kick_work);
- } else if (cdev->private->flags.doverify)
- ccw_device_online_verify(cdev, 0);
+ ERR_PTR(-EIO));
}
-static void
-ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event)
+void device_kill_io(struct subchannel *sch)
{
int ret;
- struct subchannel *sch;
+ struct ccw_device *cdev;
- sch = to_subchannel(cdev->dev.parent);
- ccw_device_set_timeout(cdev, 0);
+ cdev = sch->dev.driver_data;
ret = ccw_device_cancel_halt_clear(cdev);
if (ret == -EBUSY) {
ccw_device_set_timeout(cdev, 3*HZ);
@@ -1033,7 +990,7 @@ ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event)
if (ret == -ENODEV) {
if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, (void *)cdev);
+ ccw_device_nopath_notify, cdev);
queue_work(ccw_device_notify_work,
&cdev->private->kick_work);
} else
@@ -1042,12 +999,12 @@ ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event)
}
if (cdev->handler)
cdev->handler(cdev, cdev->private->intparm,
- ERR_PTR(-ETIMEDOUT));
+ ERR_PTR(-EIO));
if (!sch->lpm) {
PREPARE_WORK(&cdev->private->kick_work,
- ccw_device_nopath_notify, (void *)cdev);
+ ccw_device_nopath_notify, cdev);
queue_work(ccw_device_notify_work, &cdev->private->kick_work);
- } else if (cdev->private->flags.doverify)
+ } else
/* Start delayed path verification. */
ccw_device_online_verify(cdev, 0);
}
@@ -1284,12 +1241,6 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
[DEV_EVENT_TIMEOUT] = ccw_device_killing_timeout,
[DEV_EVENT_VERIFY] = ccw_device_nop, //FIXME
},
- [DEV_STATE_WAIT4IO] = {
- [DEV_EVENT_NOTOPER] = ccw_device_online_notoper,
- [DEV_EVENT_INTERRUPT] = ccw_device_wait4io_irq,
- [DEV_EVENT_TIMEOUT] = ccw_device_wait4io_timeout,
- [DEV_EVENT_VERIFY] = ccw_device_delay_verify,
- },
[DEV_STATE_QUIESCE] = {
[DEV_EVENT_NOTOPER] = ccw_device_quiesce_done,
[DEV_EVENT_INTERRUPT] = ccw_device_quiesce_done,
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 438db483035..a74785b9e4e 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -42,18 +42,15 @@ diag210(struct diag210 * addr)
spin_lock_irqsave(&diag210_lock, flags);
diag210_tmp = *addr;
- asm volatile (
- " lhi %0,-1\n"
- " sam31\n"
- " diag %1,0,0x210\n"
- "0: ipm %0\n"
- " srl %0,28\n"
- "1: sam64\n"
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 0b,1b\n"
- ".previous"
- : "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory" );
+ asm volatile(
+ " lhi %0,-1\n"
+ " sam31\n"
+ " diag %1,0,0x210\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1: sam64\n"
+ EX_TABLE(0b,1b)
+ : "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory");
*addr = diag210_tmp;
spin_unlock_irqrestore(&diag210_lock, flags);
@@ -66,17 +63,14 @@ diag210(struct diag210 * addr)
{
int ccode;
- asm volatile (
- " lhi %0,-1\n"
- " diag %1,0,0x210\n"
- "0: ipm %0\n"
- " srl %0,28\n"
+ asm volatile(
+ " lhi %0,-1\n"
+ " diag %1,0,0x210\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
"1:\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,1b\n"
- ".previous"
- : "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory" );
+ EX_TABLE(0b,1b)
+ : "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory");
return ccode;
}
@@ -257,7 +251,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
*/
CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel "
"0.%x.%04x reports cmd reject\n",
- cdev->private->devno, sch->schid.ssid,
+ cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no);
return -EOPNOTSUPP;
}
@@ -265,7 +259,8 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
CIO_MSG_EVENT(2, "SenseID : UC on dev 0.%x.%04x, "
"lpum %02X, cnt %02d, sns :"
" %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
- cdev->private->ssid, cdev->private->devno,
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno,
irb->esw.esw0.sublog.lpum,
irb->esw.esw0.erw.scnt,
irb->ecw[0], irb->ecw[1],
@@ -280,14 +275,15 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x "
"on subchannel 0.%x.%04x is "
"'not operational'\n", sch->orb.lpm,
- cdev->private->devno, sch->schid.ssid,
- sch->schid.sch_no);
+ cdev->private->dev_id.devno,
+ sch->schid.ssid, sch->schid.sch_no);
return -EACCES;
}
/* Hmm, whatever happened, try again. */
CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on "
"subchannel 0.%x.%04x returns status %02X%02X\n",
- cdev->private->devno, sch->schid.ssid, sch->schid.sch_no,
+ cdev->private->dev_id.devno, sch->schid.ssid,
+ sch->schid.sch_no,
irb->scsw.dstat, irb->scsw.cstat);
return -EAGAIN;
}
@@ -336,7 +332,7 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
/* fall through. */
default: /* Sense ID failed. Try asking VM. */
if (MACHINE_IS_VM) {
- VM_virtual_device_info (cdev->private->devno,
+ VM_virtual_device_info (cdev->private->dev_id.devno,
&cdev->private->senseid);
if (cdev->private->senseid.cu_type != 0xFFFF) {
/* Got the device information from VM. */
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 93a897eebff..b39c1fa48ac 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -50,7 +50,6 @@ ccw_device_clear(struct ccw_device *cdev, unsigned long intparm)
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE &&
- cdev->private->state != DEV_STATE_WAIT4IO &&
cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
@@ -155,7 +154,6 @@ ccw_device_halt(struct ccw_device *cdev, unsigned long intparm)
if (cdev->private->state == DEV_STATE_NOT_OPER)
return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE &&
- cdev->private->state != DEV_STATE_WAIT4IO &&
cdev->private->state != DEV_STATE_W4SENSE)
return -EINVAL;
sch = to_subchannel(cdev->dev.parent);
@@ -216,6 +214,9 @@ ccw_device_call_handler(struct ccw_device *cdev)
(stctl & SCSW_STCTL_PRIM_STATUS)))
return 0;
+ /* Clear pending timers for device driver initiated I/O. */
+ if (ending_status)
+ ccw_device_set_timeout(cdev, 0);
/*
* Now we are ready to call the device driver interrupt handler.
*/
@@ -285,10 +286,10 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb)
if (cdev->private->flags.doverify ||
cdev->private->state == DEV_STATE_VERIFY)
cdev->private->intparm = -EAGAIN;
- if ((irb->scsw.dstat & DEV_STAT_UNIT_CHECK) &&
- !(irb->ecw[0] &
- (SNS0_CMD_REJECT | SNS0_INTERVENTION_REQ)))
- cdev->private->intparm = -EAGAIN;
+ else if ((irb->scsw.dstat & DEV_STAT_UNIT_CHECK) &&
+ !(irb->ecw[0] &
+ (SNS0_CMD_REJECT | SNS0_INTERVENTION_REQ)))
+ cdev->private->intparm = -EAGAIN;
else if ((irb->scsw.dstat & DEV_STAT_ATTENTION) &&
(irb->scsw.dstat & DEV_STAT_DEV_END) &&
(irb->scsw.dstat & DEV_STAT_UNIT_EXCEP))
@@ -309,7 +310,10 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _
sch = to_subchannel(cdev->dev.parent);
do {
+ ccw_device_set_timeout(cdev, 60 * HZ);
ret = cio_start (sch, ccw, lpm);
+ if (ret != 0)
+ ccw_device_set_timeout(cdev, 0);
if (ret == -EBUSY) {
/* Try again later. */
spin_unlock_irq(&sch->lock);
@@ -586,13 +590,13 @@ ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
int
_ccw_device_get_subchannel_number(struct ccw_device *cdev)
{
- return cdev->private->sch_no;
+ return cdev->private->schid.sch_no;
}
int
_ccw_device_get_device_number(struct ccw_device *cdev)
{
- return cdev->private->devno;
+ return cdev->private->dev_id.devno;
}
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 8ca2d078848..2975ce888c1 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -79,7 +79,8 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
"0.%x.%04x, lpm %02X, became 'not "
"operational'\n",
- cdev->private->devno, sch->schid.ssid,
+ cdev->private->dev_id.devno,
+ sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask);
}
@@ -96,6 +97,9 @@ ccw_device_sense_pgid_start(struct ccw_device *cdev)
{
int ret;
+ /* Set a timeout of 60s */
+ ccw_device_set_timeout(cdev, 60*HZ);
+
cdev->private->state = DEV_STATE_SENSE_PGID;
cdev->private->imask = 0x80;
cdev->private->iretry = 5;
@@ -132,7 +136,8 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
CIO_MSG_EVENT(2, "SNID - device 0.%x.%04x, unit check, "
"lpum %02X, cnt %02d, sns : "
"%02X%02X%02X%02X %02X%02X%02X%02X ...\n",
- cdev->private->ssid, cdev->private->devno,
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno,
irb->esw.esw0.sublog.lpum,
irb->esw.esw0.erw.scnt,
irb->ecw[0], irb->ecw[1],
@@ -144,7 +149,7 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
if (irb->scsw.cc == 3) {
CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
" lpm %02X, became 'not operational'\n",
- cdev->private->devno, sch->schid.ssid,
+ cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, sch->orb.lpm);
return -EACCES;
}
@@ -152,7 +157,7 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
if (cdev->private->pgid[i].inf.ps.state2 == SNID_STATE2_RESVD_ELSE) {
CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x "
"is reserved by someone else\n",
- cdev->private->devno, sch->schid.ssid,
+ cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no);
return -EUSERS;
}
@@ -258,7 +263,7 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
/* PGID command failed on this path. */
CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
"0.%x.%04x, lpm %02X, became 'not operational'\n",
- cdev->private->devno, sch->schid.ssid,
+ cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask);
return ret;
}
@@ -298,7 +303,7 @@ static int __ccw_device_do_nop(struct ccw_device *cdev)
/* nop command failed on this path. */
CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel "
"0.%x.%04x, lpm %02X, became 'not operational'\n",
- cdev->private->devno, sch->schid.ssid,
+ cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask);
return ret;
}
@@ -325,8 +330,9 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, "
"cnt %02d, "
"sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
- cdev->private->ssid,
- cdev->private->devno, irb->esw.esw0.erw.scnt,
+ cdev->private->dev_id.ssid,
+ cdev->private->dev_id.devno,
+ irb->esw.esw0.erw.scnt,
irb->ecw[0], irb->ecw[1],
irb->ecw[2], irb->ecw[3],
irb->ecw[4], irb->ecw[5],
@@ -336,7 +342,7 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
if (irb->scsw.cc == 3) {
CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x,"
" lpm %02X, became 'not operational'\n",
- cdev->private->devno, sch->schid.ssid,
+ cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask);
return -EACCES;
}
@@ -359,7 +365,7 @@ static int __ccw_device_check_nop(struct ccw_device *cdev)
if (irb->scsw.cc == 3) {
CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel 0.%x.%04x,"
" lpm %02X, became 'not operational'\n",
- cdev->private->devno, sch->schid.ssid,
+ cdev->private->dev_id.devno, sch->schid.ssid,
sch->schid.sch_no, cdev->private->imask);
return -EACCES;
}
@@ -480,6 +486,8 @@ ccw_device_verify_start(struct ccw_device *cdev)
ccw_device_verify_done(cdev, -ENODEV);
return;
}
+ /* After 60s path verification is considered to have failed. */
+ ccw_device_set_timeout(cdev, 60*HZ);
__ccw_device_verify_start(cdev);
}
@@ -554,6 +562,9 @@ ccw_device_disband_irq(struct ccw_device *cdev, enum dev_event dev_event)
void
ccw_device_disband_start(struct ccw_device *cdev)
{
+ /* After 60s disbanding is considered to have failed. */
+ ccw_device_set_timeout(cdev, 60*HZ);
+
cdev->private->flags.pgid_single = 0;
cdev->private->iretry = 5;
cdev->private->imask = 0x80;
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index caf148d5caa..3f7cbce4cd8 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -32,19 +32,18 @@ ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
SCHN_STAT_CHN_CTRL_CHK |
SCHN_STAT_INTF_CTRL_CHK)))
return;
-
CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check "
"received"
" ... device %04x on subchannel 0.%x.%04x, dev_stat "
": %02X sch_stat : %02X\n",
- cdev->private->devno, cdev->private->ssid,
- cdev->private->sch_no,
+ cdev->private->dev_id.devno, cdev->private->schid.ssid,
+ cdev->private->schid.sch_no,
irb->scsw.dstat, irb->scsw.cstat);
if (irb->scsw.cc != 3) {
char dbf_text[15];
- sprintf(dbf_text, "chk%x", cdev->private->sch_no);
+ sprintf(dbf_text, "chk%x", cdev->private->schid.sch_no);
CIO_TRACE_EVENT(0, dbf_text);
CIO_HEX_EVENT(0, irb, sizeof (struct irb));
}
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index 95a9462f9a9..ad6d8294006 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -25,106 +25,74 @@ struct tpi_info {
static inline int stsch(struct subchannel_id schid,
volatile struct schib *addr)
{
+ register struct subchannel_id reg1 asm ("1") = schid;
int ccode;
- __asm__ __volatile__(
- " lr 1,%1\n"
- " stsch 0(%2)\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "d" (schid), "a" (addr), "m" (*addr)
- : "cc", "1" );
+ asm volatile(
+ " stsch 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
return ccode;
}
static inline int stsch_err(struct subchannel_id schid,
volatile struct schib *addr)
{
- int ccode;
+ register struct subchannel_id reg1 asm ("1") = schid;
+ int ccode = -EIO;
- __asm__ __volatile__(
- " lhi %0,%3\n"
- " lr 1,%1\n"
- " stsch 0(%2)\n"
- "0: ipm %0\n"
- " srl %0,28\n"
+ asm volatile(
+ " stsch 0(%2)\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
"1:\n"
-#ifdef CONFIG_64BIT
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 0b,1b\n"
- ".previous"
-#else
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,1b\n"
- ".previous"
-#endif
- : "=&d" (ccode)
- : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
- : "cc", "1" );
+ EX_TABLE(0b,1b)
+ : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
return ccode;
}
static inline int msch(struct subchannel_id schid,
volatile struct schib *addr)
{
+ register struct subchannel_id reg1 asm ("1") = schid;
int ccode;
- __asm__ __volatile__(
- " lr 1,%1\n"
- " msch 0(%2)\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "d" (schid), "a" (addr), "m" (*addr)
- : "cc", "1" );
+ asm volatile(
+ " msch 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
return ccode;
}
static inline int msch_err(struct subchannel_id schid,
volatile struct schib *addr)
{
- int ccode;
+ register struct subchannel_id reg1 asm ("1") = schid;
+ int ccode = -EIO;
- __asm__ __volatile__(
- " lhi %0,%3\n"
- " lr 1,%1\n"
- " msch 0(%2)\n"
- "0: ipm %0\n"
- " srl %0,28\n"
+ asm volatile(
+ " msch 0(%2)\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
"1:\n"
-#ifdef CONFIG_64BIT
- ".section __ex_table,\"a\"\n"
- " .align 8\n"
- " .quad 0b,1b\n"
- ".previous"
-#else
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,1b\n"
- ".previous"
-#endif
- : "=&d" (ccode)
- : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
- : "cc", "1" );
+ EX_TABLE(0b,1b)
+ : "+d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
return ccode;
}
static inline int tsch(struct subchannel_id schid,
volatile struct irb *addr)
{
+ register struct subchannel_id reg1 asm ("1") = schid;
int ccode;
- __asm__ __volatile__(
- " lr 1,%1\n"
- " tsch 0(%2)\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "d" (schid), "a" (addr), "m" (*addr)
- : "cc", "1" );
+ asm volatile(
+ " tsch 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
return ccode;
}
@@ -132,89 +100,77 @@ static inline int tpi( volatile struct tpi_info *addr)
{
int ccode;
- __asm__ __volatile__(
- " tpi 0(%1)\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "a" (addr), "m" (*addr)
- : "cc", "1" );
+ asm volatile(
+ " tpi 0(%1)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode) : "a" (addr), "m" (*addr) : "cc");
return ccode;
}
static inline int ssch(struct subchannel_id schid,
volatile struct orb *addr)
{
+ register struct subchannel_id reg1 asm ("1") = schid;
int ccode;
- __asm__ __volatile__(
- " lr 1,%1\n"
- " ssch 0(%2)\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "d" (schid), "a" (addr), "m" (*addr)
- : "cc", "1" );
+ asm volatile(
+ " ssch 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode) : "d" (reg1), "a" (addr), "m" (*addr) : "cc");
return ccode;
}
static inline int rsch(struct subchannel_id schid)
{
+ register struct subchannel_id reg1 asm ("1") = schid;
int ccode;
- __asm__ __volatile__(
- " lr 1,%1\n"
- " rsch\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "d" (schid)
- : "cc", "1" );
+ asm volatile(
+ " rsch\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode) : "d" (reg1) : "cc");
return ccode;
}
static inline int csch(struct subchannel_id schid)
{
+ register struct subchannel_id reg1 asm ("1") = schid;
int ccode;
- __asm__ __volatile__(
- " lr 1,%1\n"
- " csch\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "d" (schid)
- : "cc", "1" );
+ asm volatile(
+ " csch\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode) : "d" (reg1) : "cc");
return ccode;
}
static inline int hsch(struct subchannel_id schid)
{
+ register struct subchannel_id reg1 asm ("1") = schid;
int ccode;
- __asm__ __volatile__(
- " lr 1,%1\n"
- " hsch\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "d" (schid)
- : "cc", "1" );
+ asm volatile(
+ " hsch\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode) : "d" (reg1) : "cc");
return ccode;
}
static inline int xsch(struct subchannel_id schid)
{
+ register struct subchannel_id reg1 asm ("1") = schid;
int ccode;
- __asm__ __volatile__(
- " lr 1,%1\n"
- " .insn rre,0xb2760000,%1,0\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "d" (schid)
- : "cc", "1" );
+ asm volatile(
+ " .insn rre,0xb2760000,%1,0\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode) : "d" (reg1) : "cc");
return ccode;
}
@@ -223,41 +179,27 @@ static inline int chsc(void *chsc_area)
typedef struct { char _[4096]; } addr_type;
int cc;
- __asm__ __volatile__ (
- ".insn rre,0xb25f0000,%2,0 \n\t"
- "ipm %0 \n\t"
- "srl %0,28 \n\t"
+ asm volatile(
+ " .insn rre,0xb25f0000,%2,0\n"
+ " ipm %0\n"
+ " srl %0,28\n"
: "=d" (cc), "=m" (*(addr_type *) chsc_area)
: "d" (chsc_area), "m" (*(addr_type *) chsc_area)
- : "cc" );
-
+ : "cc");
return cc;
}
-static inline int iac( void)
-{
- int ccode;
-
- __asm__ __volatile__(
- " iac 1\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode) : : "cc", "1" );
- return ccode;
-}
-
static inline int rchp(int chpid)
{
+ register unsigned int reg1 asm ("1") = chpid;
int ccode;
- __asm__ __volatile__(
- " lr 1,%1\n"
- " rchp\n"
- " ipm %0\n"
- " srl %0,28"
- : "=d" (ccode)
- : "d" (chpid)
- : "cc", "1" );
+ asm volatile(
+ " lr 1,%1\n"
+ " rchp\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (ccode) : "d" (reg1) : "cc");
return ccode;
}
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index cde822d8b5c..0648ce5bb68 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -1741,7 +1741,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
void *ptr;
int available;
- sprintf(dbf_text,"qfqs%4x",cdev->private->sch_no);
+ sprintf(dbf_text,"qfqs%4x",cdev->private->schid.sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
for (i=0;i<no_input_qs;i++) {
q=irq_ptr->input_qs[i];
@@ -2924,7 +2924,7 @@ qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, int dstat)
irq_ptr = cdev->private->qdio_data;
- sprintf(dbf_text,"qehi%4x",cdev->private->sch_no);
+ sprintf(dbf_text,"qehi%4x",cdev->private->schid.sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
@@ -2943,7 +2943,7 @@ qdio_initialize(struct qdio_initialize *init_data)
int rc;
char dbf_text[15];
- sprintf(dbf_text,"qini%4x",init_data->cdev->private->sch_no);
+ sprintf(dbf_text,"qini%4x",init_data->cdev->private->schid.sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
@@ -2964,7 +2964,7 @@ qdio_allocate(struct qdio_initialize *init_data)
struct qdio_irq *irq_ptr;
char dbf_text[15];
- sprintf(dbf_text,"qalc%4x",init_data->cdev->private->sch_no);
+ sprintf(dbf_text,"qalc%4x",init_data->cdev->private->schid.sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
if ( (init_data->no_input_qs>QDIO_MAX_QUEUES_PER_IRQ) ||
@@ -3187,7 +3187,7 @@ qdio_establish(struct qdio_initialize *init_data)
tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET);
}
- sprintf(dbf_text,"qest%4x",cdev->private->sch_no);
+ sprintf(dbf_text,"qest%4x",cdev->private->schid.sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 124569362f0..49bb9e371c3 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -274,12 +274,11 @@ do_sqbs(unsigned long sch, unsigned char state, int queue,
register unsigned long _sch asm ("1") = sch;
unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
- asm volatile (
- " .insn rsy,0xeb000000008A,%1,0,0(%2)\n\t"
- : "+d" (_ccq), "+d" (_queuestart)
- : "d" ((unsigned long)state), "d" (_sch)
- : "memory", "cc"
- );
+ asm volatile(
+ " .insn rsy,0xeb000000008A,%1,0,0(%2)"
+ : "+d" (_ccq), "+d" (_queuestart)
+ : "d" ((unsigned long)state), "d" (_sch)
+ : "memory", "cc");
*count = _ccq & 0xff;
*start = _queuestart & 0xff;
@@ -299,12 +298,11 @@ do_eqbs(unsigned long sch, unsigned char *state, int queue,
unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
unsigned long _state = 0;
- asm volatile (
- " .insn rrf,0xB99c0000,%1,%2,0,0 \n\t"
- : "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
- : "d" (_sch)
- : "memory", "cc"
- );
+ asm volatile(
+ " .insn rrf,0xB99c0000,%1,%2,0,0"
+ : "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
+ : "d" (_sch)
+ : "memory", "cc" );
*count = _ccq & 0xff;
*start = _queuestart & 0xff;
*state = _state & 0xff;
@@ -319,69 +317,35 @@ do_eqbs(unsigned long sch, unsigned char *state, int queue,
static inline int
do_siga_sync(struct subchannel_id schid, unsigned int mask1, unsigned int mask2)
{
+ register unsigned long reg0 asm ("0") = 2;
+ register struct subchannel_id reg1 asm ("1") = schid;
+ register unsigned long reg2 asm ("2") = mask1;
+ register unsigned long reg3 asm ("3") = mask2;
int cc;
-#ifndef CONFIG_64BIT
- asm volatile (
- "lhi 0,2 \n\t"
- "lr 1,%1 \n\t"
- "lr 2,%2 \n\t"
- "lr 3,%3 \n\t"
- "siga 0 \n\t"
- "ipm %0 \n\t"
- "srl %0,28 \n\t"
+ asm volatile(
+ " siga 0\n"
+ " ipm %0\n"
+ " srl %0,28\n"
: "=d" (cc)
- : "d" (schid), "d" (mask1), "d" (mask2)
- : "cc", "0", "1", "2", "3"
- );
-#else /* CONFIG_64BIT */
- asm volatile (
- "lghi 0,2 \n\t"
- "llgfr 1,%1 \n\t"
- "llgfr 2,%2 \n\t"
- "llgfr 3,%3 \n\t"
- "siga 0 \n\t"
- "ipm %0 \n\t"
- "srl %0,28 \n\t"
- : "=d" (cc)
- : "d" (schid), "d" (mask1), "d" (mask2)
- : "cc", "0", "1", "2", "3"
- );
-#endif /* CONFIG_64BIT */
+ : "d" (reg0), "d" (reg1), "d" (reg2), "d" (reg3) : "cc");
return cc;
}
static inline int
do_siga_input(struct subchannel_id schid, unsigned int mask)
{
+ register unsigned long reg0 asm ("0") = 1;
+ register struct subchannel_id reg1 asm ("1") = schid;
+ register unsigned long reg2 asm ("2") = mask;
int cc;
-#ifndef CONFIG_64BIT
- asm volatile (
- "lhi 0,1 \n\t"
- "lr 1,%1 \n\t"
- "lr 2,%2 \n\t"
- "siga 0 \n\t"
- "ipm %0 \n\t"
- "srl %0,28 \n\t"
- : "=d" (cc)
- : "d" (schid), "d" (mask)
- : "cc", "0", "1", "2", "memory"
- );
-#else /* CONFIG_64BIT */
- asm volatile (
- "lghi 0,1 \n\t"
- "llgfr 1,%1 \n\t"
- "llgfr 2,%2 \n\t"
- "siga 0 \n\t"
- "ipm %0 \n\t"
- "srl %0,28 \n\t"
+ asm volatile(
+ " siga 0\n"
+ " ipm %0\n"
+ " srl %0,28\n"
: "=d" (cc)
- : "d" (schid), "d" (mask)
- : "cc", "0", "1", "2", "memory"
- );
-#endif /* CONFIG_64BIT */
-
+ : "d" (reg0), "d" (reg1), "d" (reg2) : "cc", "memory");
return cc;
}
@@ -389,93 +353,35 @@ static inline int
do_siga_output(unsigned long schid, unsigned long mask, __u32 *bb,
unsigned int fc)
{
+ register unsigned long __fc asm("0") = fc;
+ register unsigned long __schid asm("1") = schid;
+ register unsigned long __mask asm("2") = mask;
int cc;
- __u32 busy_bit;
-
-#ifndef CONFIG_64BIT
- asm volatile (
- "lhi 0,0 \n\t"
- "lr 1,%2 \n\t"
- "lr 2,%3 \n\t"
- "siga 0 \n\t"
- "0:"
- "ipm %0 \n\t"
- "srl %0,28 \n\t"
- "srl 0,31 \n\t"
- "lr %1,0 \n\t"
- "1: \n\t"
- ".section .fixup,\"ax\"\n\t"
- "2: \n\t"
- "lhi %0,%4 \n\t"
- "bras 1,3f \n\t"
- ".long 1b \n\t"
- "3: \n\t"
- "l 1,0(1) \n\t"
- "br 1 \n\t"
- ".previous \n\t"
- ".section __ex_table,\"a\"\n\t"
- ".align 4 \n\t"
- ".long 0b,2b \n\t"
- ".previous \n\t"
- : "=d" (cc), "=d" (busy_bit)
- : "d" (schid), "d" (mask),
- "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
- : "cc", "0", "1", "2", "memory"
- );
-#else /* CONFIG_64BIT */
- asm volatile (
- "llgfr 0,%5 \n\t"
- "lgr 1,%2 \n\t"
- "llgfr 2,%3 \n\t"
- "siga 0 \n\t"
- "0:"
- "ipm %0 \n\t"
- "srl %0,28 \n\t"
- "srl 0,31 \n\t"
- "llgfr %1,0 \n\t"
- "1: \n\t"
- ".section .fixup,\"ax\"\n\t"
- "lghi %0,%4 \n\t"
- "jg 1b \n\t"
- ".previous\n\t"
- ".section __ex_table,\"a\"\n\t"
- ".align 8 \n\t"
- ".quad 0b,1b \n\t"
- ".previous \n\t"
- : "=d" (cc), "=d" (busy_bit)
- : "d" (schid), "d" (mask),
- "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION), "d" (fc)
- : "cc", "0", "1", "2", "memory"
- );
-#endif /* CONFIG_64BIT */
-
- (*bb) = busy_bit;
+
+ asm volatile(
+ " siga 0\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "=d" (cc), "+d" (__fc), "+d" (__schid), "+d" (__mask)
+ : "0" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
+ : "cc", "memory");
+ (*bb) = ((unsigned int) __fc) >> 31;
return cc;
}
static inline unsigned long
do_clear_global_summary(void)
{
-
- unsigned long time;
-
-#ifndef CONFIG_64BIT
- asm volatile (
- "lhi 1,3 \n\t"
- ".insn rre,0xb2650000,2,0 \n\t"
- "lr %0,3 \n\t"
- : "=d" (time) : : "cc", "1", "2", "3"
- );
-#else /* CONFIG_64BIT */
- asm volatile (
- "lghi 1,3 \n\t"
- ".insn rre,0xb2650000,2,0 \n\t"
- "lgr %0,3 \n\t"
- : "=d" (time) : : "cc", "1", "2", "3"
- );
-#endif /* CONFIG_64BIT */
-
- return time;
+ register unsigned long __fn asm("1") = 3;
+ register unsigned long __tmp asm("2");
+ register unsigned long __time asm("3");
+
+ asm volatile(
+ " .insn rre,0xb2650000,2,0"
+ : "+d" (__fn), "=d" (__tmp), "=d" (__time));
+ return __time;
}
/*
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 6ed0985c0c9..c5ccd20b110 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -449,8 +449,6 @@ static int ap_device_probe(struct device *dev)
ap_dev->drv = ap_drv;
rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
- if (rc)
- ap_dev->unregistered = 1;
return rc;
}
@@ -487,14 +485,7 @@ static int ap_device_remove(struct device *dev)
struct ap_device *ap_dev = to_ap_dev(dev);
struct ap_driver *ap_drv = ap_dev->drv;
- spin_lock_bh(&ap_dev->lock);
- __ap_flush_queue(ap_dev);
- /**
- * set ->unregistered to 1 while holding the lock. This prevents
- * new messages to be put on the queue from now on.
- */
- ap_dev->unregistered = 1;
- spin_unlock_bh(&ap_dev->lock);
+ ap_flush_queue(ap_dev);
if (ap_drv->remove)
ap_drv->remove(ap_dev);
return 0;
@@ -763,6 +754,7 @@ static void ap_scan_bus(void *data)
break;
ap_dev->qid = qid;
ap_dev->queue_depth = queue_depth;
+ ap_dev->unregistered = 1;
spin_lock_init(&ap_dev->lock);
INIT_LIST_HEAD(&ap_dev->pendingq);
INIT_LIST_HEAD(&ap_dev->requestq);
@@ -784,7 +776,12 @@ static void ap_scan_bus(void *data)
/* Add device attributes. */
rc = sysfs_create_group(&ap_dev->device.kobj,
&ap_dev_attr_group);
- if (rc)
+ if (!rc) {
+ spin_lock_bh(&ap_dev->lock);
+ ap_dev->unregistered = 0;
+ spin_unlock_bh(&ap_dev->lock);
+ }
+ else
device_unregister(&ap_dev->device);
}
}
@@ -970,6 +967,8 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
rc = __ap_queue_message(ap_dev, ap_msg);
if (!rc)
wake_up(&ap_poll_wait);
+ if (rc == -ENODEV)
+ ap_dev->unregistered = 1;
} else {
ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
rc = 0;
@@ -1028,6 +1027,8 @@ static int __ap_poll_all(struct device *dev, void *data)
spin_lock(&ap_dev->lock);
if (!ap_dev->unregistered) {
rc = ap_poll_queue(to_ap_dev(dev), (unsigned long *) data);
+ if (rc)
+ ap_dev->unregistered = 1;
} else
rc = 0;
spin_unlock(&ap_dev->lock);
@@ -1061,7 +1062,7 @@ static int ap_poll_thread(void *data)
unsigned long flags;
int requests;
- set_user_nice(current, -20);
+ set_user_nice(current, 19);
while (1) {
if (need_resched()) {
schedule();
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index 821dde86e24..1476ce2b437 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -116,7 +116,7 @@ static DEFINE_SPINLOCK(iucv_irq_queue_lock);
*Internal function prototypes
*/
static void iucv_tasklet_handler(unsigned long);
-static void iucv_irq_handler(struct pt_regs *, __u16);
+static void iucv_irq_handler(__u16);
static DECLARE_TASKLET(iucv_tasklet,iucv_tasklet_handler,0);
@@ -534,19 +534,15 @@ iucv_add_handler (handler *new)
*
* Returns: return code from CP's IUCV call
*/
-static __inline__ ulong
-b2f0(__u32 code, void *parm)
+static inline ulong b2f0(__u32 code, void *parm)
{
+ register unsigned long reg0 asm ("0");
+ register unsigned long reg1 asm ("1");
iucv_dumpit("iparml before b2f0 call:", parm, sizeof(iucv_param));
- asm volatile (
- "LRA 1,0(%1)\n\t"
- "LR 0,%0\n\t"
- ".long 0xb2f01000"
- :
- : "d" (code), "a" (parm)
- : "0", "1"
- );
+ reg0 = code;
+ reg1 = virt_to_phys(parm);
+ asm volatile(".long 0xb2f01000" : : "d" (reg0), "a" (reg1));
iucv_dumpit("iparml after b2f0 call:", parm, sizeof(iucv_param));
@@ -1248,6 +1244,8 @@ iucv_purge (__u16 pathid, __u32 msgid, __u32 srccls, __u32 *audit)
static int
iucv_query_generic(int want_maxconn)
{
+ register unsigned long reg0 asm ("0");
+ register unsigned long reg1 asm ("1");
iparml_purge *parm = (iparml_purge *)grab_param();
int bufsize, maxconn;
int ccode;
@@ -1256,18 +1254,15 @@ iucv_query_generic(int want_maxconn)
* Call b2f0 and store R0 (max buffer size),
* R1 (max connections) and CC.
*/
- asm volatile (
- "LRA 1,0(%4)\n\t"
- "LR 0,%3\n\t"
- ".long 0xb2f01000\n\t"
- "IPM %0\n\t"
- "SRL %0,28\n\t"
- "ST 0,%1\n\t"
- "ST 1,%2\n\t"
- : "=d" (ccode), "=m" (bufsize), "=m" (maxconn)
- : "d" (QUERY), "a" (parm)
- : "0", "1", "cc"
- );
+ reg0 = QUERY;
+ reg1 = virt_to_phys(parm);
+ asm volatile(
+ " .long 0xb2f01000\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (ccode), "+d" (reg0), "+d" (reg1) : : "cc");
+ bufsize = reg0;
+ maxconn = reg1;
release_param(parm);
if (ccode)
@@ -2256,7 +2251,7 @@ iucv_sever(__u16 pathid, __u8 user_data[16])
* Places the interrupt buffer on a queue and schedules iucv_tasklet_handler().
*/
static void
-iucv_irq_handler(struct pt_regs *regs, __u16 code)
+iucv_irq_handler(__u16 code)
{
iucv_irqdata *irqdata;
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 5613b4564fa..8364d5475ac 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -8067,7 +8067,7 @@ qeth_arp_constructor(struct neighbour *neigh)
neigh->parms = neigh_parms_clone(parms);
rcu_read_unlock();
- neigh->type = inet_addr_type(*(u32 *) neigh->primary_key);
+ neigh->type = inet_addr_type(*(__be32 *) neigh->primary_key);
neigh->nud_state = NUD_NOARP;
neigh->ops = arp_direct_ops;
neigh->output = neigh->ops->queue_xmit;
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index a914129a4da..e088b5e2871 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -208,7 +208,7 @@ s390_handle_mcck(void)
*/
__ctl_clear_bit(14, 24); /* Disable WARNING MCH */
if (xchg(&mchchk_wng_posted, 1) == 0)
- kill_proc(1, SIGPWR, 1);
+ kill_cad_pid(SIGPWR, 1);
}
#endif
@@ -253,11 +253,12 @@ s390_revalidate_registers(struct mci *mci)
kill_task = 1;
#ifndef CONFIG_64BIT
- asm volatile("ld 0,0(%0)\n"
- "ld 2,8(%0)\n"
- "ld 4,16(%0)\n"
- "ld 6,24(%0)"
- : : "a" (&S390_lowcore.floating_pt_save_area));
+ asm volatile(
+ " ld 0,0(%0)\n"
+ " ld 2,8(%0)\n"
+ " ld 4,16(%0)\n"
+ " ld 6,24(%0)"
+ : : "a" (&S390_lowcore.floating_pt_save_area));
#endif
if (MACHINE_HAS_IEEE) {
@@ -274,37 +275,36 @@ s390_revalidate_registers(struct mci *mci)
* Floating point control register can't be restored.
* Task will be terminated.
*/
- asm volatile ("lfpc 0(%0)" : : "a" (&zero), "m" (zero));
+ asm volatile("lfpc 0(%0)" : : "a" (&zero), "m" (zero));
kill_task = 1;
- }
- else
- asm volatile (
- "lfpc 0(%0)"
- : : "a" (fpt_creg_save_area));
-
- asm volatile("ld 0,0(%0)\n"
- "ld 1,8(%0)\n"
- "ld 2,16(%0)\n"
- "ld 3,24(%0)\n"
- "ld 4,32(%0)\n"
- "ld 5,40(%0)\n"
- "ld 6,48(%0)\n"
- "ld 7,56(%0)\n"
- "ld 8,64(%0)\n"
- "ld 9,72(%0)\n"
- "ld 10,80(%0)\n"
- "ld 11,88(%0)\n"
- "ld 12,96(%0)\n"
- "ld 13,104(%0)\n"
- "ld 14,112(%0)\n"
- "ld 15,120(%0)\n"
- : : "a" (fpt_save_area));
+ } else
+ asm volatile("lfpc 0(%0)" : : "a" (fpt_creg_save_area));
+
+ asm volatile(
+ " ld 0,0(%0)\n"
+ " ld 1,8(%0)\n"
+ " ld 2,16(%0)\n"
+ " ld 3,24(%0)\n"
+ " ld 4,32(%0)\n"
+ " ld 5,40(%0)\n"
+ " ld 6,48(%0)\n"
+ " ld 7,56(%0)\n"
+ " ld 8,64(%0)\n"
+ " ld 9,72(%0)\n"
+ " ld 10,80(%0)\n"
+ " ld 11,88(%0)\n"
+ " ld 12,96(%0)\n"
+ " ld 13,104(%0)\n"
+ " ld 14,112(%0)\n"
+ " ld 15,120(%0)\n"
+ : : "a" (fpt_save_area));
}
/* Revalidate access registers */
- asm volatile("lam 0,15,0(%0)"
- : : "a" (&S390_lowcore.access_regs_save_area));
+ asm volatile(
+ " lam 0,15,0(%0)"
+ : : "a" (&S390_lowcore.access_regs_save_area));
if (!mci->ar)
/*
* Access registers have unknown contents.
@@ -321,11 +321,13 @@ s390_revalidate_registers(struct mci *mci)
s390_handle_damage("invalid control registers.");
else
#ifdef CONFIG_64BIT
- asm volatile("lctlg 0,15,0(%0)"
- : : "a" (&S390_lowcore.cregs_save_area));
+ asm volatile(
+ " lctlg 0,15,0(%0)"
+ : : "a" (&S390_lowcore.cregs_save_area));
#else
- asm volatile("lctl 0,15,0(%0)"
- : : "a" (&S390_lowcore.cregs_save_area));
+ asm volatile(
+ " lctl 0,15,0(%0)"
+ : : "a" (&S390_lowcore.cregs_save_area));
#endif
/*
@@ -339,20 +341,23 @@ s390_revalidate_registers(struct mci *mci)
* old contents (should be zero) otherwise set it to zero.
*/
if (!mci->pr)
- asm volatile("sr 0,0\n"
- "sckpf"
- : : : "0", "cc");
+ asm volatile(
+ " sr 0,0\n"
+ " sckpf"
+ : : : "0", "cc");
else
asm volatile(
- "l 0,0(%0)\n"
- "sckpf"
- : : "a" (&S390_lowcore.tod_progreg_save_area) : "0", "cc");
+ " l 0,0(%0)\n"
+ " sckpf"
+ : : "a" (&S390_lowcore.tod_progreg_save_area)
+ : "0", "cc");
#endif
/* Revalidate clock comparator register */
- asm volatile ("stck 0(%1)\n"
- "sckc 0(%1)"
- : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
+ asm volatile(
+ " stck 0(%1)\n"
+ " sckc 0(%1)"
+ : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
/* Check if old PSW is valid */
if (!mci->wp)
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index adc9d8f2c28..5d39b2df0cc 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -189,6 +189,10 @@ struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter,
struct zfcp_fsf_req *request, *tmp;
unsigned int i;
+ /* 0 is reserved as an invalid req_id */
+ if (req_id == 0)
+ return NULL;
+
i = req_id % REQUEST_LIST_SIZE;
list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list)
@@ -299,11 +303,45 @@ zfcp_init_device_configure(void)
return;
}
+static int calc_alignment(int size)
+{
+ int align = 1;
+
+ if (!size)
+ return 0;
+
+ while ((size - align) > 0)
+ align <<= 1;
+
+ return align;
+}
+
static int __init
zfcp_module_init(void)
{
+ int retval = -ENOMEM;
+ int size, align;
+
+ size = sizeof(struct zfcp_fsf_req_qtcb);
+ align = calc_alignment(size);
+ zfcp_data.fsf_req_qtcb_cache =
+ kmem_cache_create("zfcp_fsf", size, align, 0, NULL, NULL);
+ if (!zfcp_data.fsf_req_qtcb_cache)
+ goto out;
- int retval = 0;
+ size = sizeof(struct fsf_status_read_buffer);
+ align = calc_alignment(size);
+ zfcp_data.sr_buffer_cache =
+ kmem_cache_create("zfcp_sr", size, align, 0, NULL, NULL);
+ if (!zfcp_data.sr_buffer_cache)
+ goto out_sr_cache;
+
+ size = sizeof(struct zfcp_gid_pn_data);
+ align = calc_alignment(size);
+ zfcp_data.gid_pn_cache =
+ kmem_cache_create("zfcp_gid", size, align, 0, NULL, NULL);
+ if (!zfcp_data.gid_pn_cache)
+ goto out_gid_cache;
atomic_set(&zfcp_data.loglevel, loglevel);
@@ -313,15 +351,16 @@ zfcp_module_init(void)
/* initialize adapters to be removed list head */
INIT_LIST_HEAD(&zfcp_data.adapter_remove_lh);
- zfcp_transport_template = fc_attach_transport(&zfcp_transport_functions);
- if (!zfcp_transport_template)
- return -ENODEV;
+ zfcp_data.scsi_transport_template =
+ fc_attach_transport(&zfcp_transport_functions);
+ if (!zfcp_data.scsi_transport_template)
+ goto out_transport;
retval = misc_register(&zfcp_cfdc_misc);
if (retval != 0) {
ZFCP_LOG_INFO("registration of misc device "
"zfcp_cfdc failed\n");
- goto out;
+ goto out_misc;
}
ZFCP_LOG_TRACE("major/minor for zfcp_cfdc: %d/%d\n",
@@ -333,9 +372,6 @@ zfcp_module_init(void)
/* initialise configuration rw lock */
rwlock_init(&zfcp_data.config_lock);
- /* save address of data structure managing the driver module */
- zfcp_data.scsi_host_template.module = THIS_MODULE;
-
/* setup dynamic I/O */
retval = zfcp_ccw_register();
if (retval) {
@@ -350,6 +386,14 @@ zfcp_module_init(void)
out_ccw_register:
misc_deregister(&zfcp_cfdc_misc);
+ out_misc:
+ fc_release_transport(zfcp_data.scsi_transport_template);
+ out_transport:
+ kmem_cache_destroy(zfcp_data.gid_pn_cache);
+ out_gid_cache:
+ kmem_cache_destroy(zfcp_data.sr_buffer_cache);
+ out_sr_cache:
+ kmem_cache_destroy(zfcp_data.fsf_req_qtcb_cache);
out:
return retval;
}
@@ -935,20 +979,20 @@ static int
zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
{
adapter->pool.fsf_req_erp =
- mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ERP_NR,
- sizeof(struct zfcp_fsf_req_pool_element));
+ mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_ERP_NR,
+ zfcp_data.fsf_req_qtcb_cache);
if (!adapter->pool.fsf_req_erp)
return -ENOMEM;
adapter->pool.fsf_req_scsi =
- mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_SCSI_NR,
- sizeof(struct zfcp_fsf_req_pool_element));
+ mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_SCSI_NR,
+ zfcp_data.fsf_req_qtcb_cache);
if (!adapter->pool.fsf_req_scsi)
return -ENOMEM;
adapter->pool.fsf_req_abort =
- mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ABORT_NR,
- sizeof(struct zfcp_fsf_req_pool_element));
+ mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_ABORT_NR,
+ zfcp_data.fsf_req_qtcb_cache);
if (!adapter->pool.fsf_req_abort)
return -ENOMEM;
@@ -959,14 +1003,14 @@ zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
return -ENOMEM;
adapter->pool.data_status_read =
- mempool_create_kmalloc_pool(ZFCP_POOL_STATUS_READ_NR,
- sizeof(struct fsf_status_read_buffer));
+ mempool_create_slab_pool(ZFCP_POOL_STATUS_READ_NR,
+ zfcp_data.sr_buffer_cache);
if (!adapter->pool.data_status_read)
return -ENOMEM;
adapter->pool.data_gid_pn =
- mempool_create_kmalloc_pool(ZFCP_POOL_DATA_GID_PN_NR,
- sizeof(struct zfcp_gid_pn_data));
+ mempool_create_slab_pool(ZFCP_POOL_DATA_GID_PN_NR,
+ zfcp_data.gid_pn_cache);
if (!adapter->pool.data_gid_pn)
return -ENOMEM;
@@ -1091,9 +1135,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
/* initialize lock of associated request queue */
rwlock_init(&adapter->request_queue.queue_lock);
- /* intitialise SCSI ER timer */
- init_timer(&adapter->scsi_er_timer);
-
/* mark adapter unusable as long as sysfs registration is not complete */
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
@@ -1609,7 +1650,6 @@ zfcp_ns_gid_pn_request(struct zfcp_erp_action *erp_action)
gid_pn->ct.handler = zfcp_ns_gid_pn_handler;
gid_pn->ct.handler_data = (unsigned long) gid_pn;
gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
- gid_pn->ct.timer = &erp_action->timer;
gid_pn->port = erp_action->port;
ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp,
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index fdabadeaa9e..81680efa172 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -275,19 +275,6 @@ zfcp_ccw_register(void)
}
/**
- * zfcp_ccw_unregister - ccw unregister function
- *
- * Unregisters the driver from common i/o layer. Function will be called at
- * module unload/system shutdown.
- */
-void __exit
-zfcp_ccw_unregister(void)
-{
- zfcp_sysfs_driver_remove_files(&zfcp_ccw_driver.driver);
- ccw_driver_unregister(&zfcp_ccw_driver);
-}
-
-/**
* zfcp_ccw_shutdown - gets called on reboot/shutdown
*
* Makes sure that QDIO queues are down when the system gets stopped.
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index c033145d0f1..0aa3b1ac76a 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -707,7 +707,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
struct zfcp_adapter *adapter,
struct scsi_cmnd *scsi_cmnd,
struct zfcp_fsf_req *fsf_req,
- struct zfcp_fsf_req *old_fsf_req)
+ unsigned long old_req_id)
{
struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf;
struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec;
@@ -768,8 +768,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
rec->fsf_seqno = fsf_req->seq_no;
rec->fsf_issued = fsf_req->issued;
}
- rec->type.old_fsf_reqid =
- (unsigned long) old_fsf_req;
+ rec->type.old_fsf_reqid = old_req_id;
} else {
strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE);
dump->total_size = buflen;
@@ -794,17 +793,17 @@ zfcp_scsi_dbf_event_result(const char *tag, int level,
struct zfcp_fsf_req *fsf_req)
{
_zfcp_scsi_dbf_event_common("rslt", tag, level,
- adapter, scsi_cmnd, fsf_req, NULL);
+ adapter, scsi_cmnd, fsf_req, 0);
}
inline void
zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
struct scsi_cmnd *scsi_cmnd,
struct zfcp_fsf_req *new_fsf_req,
- struct zfcp_fsf_req *old_fsf_req)
+ unsigned long old_req_id)
{
_zfcp_scsi_dbf_event_common("abrt", tag, 1,
- adapter, scsi_cmnd, new_fsf_req, old_fsf_req);
+ adapter, scsi_cmnd, new_fsf_req, old_req_id);
}
inline void
@@ -814,7 +813,7 @@ zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
struct zfcp_adapter *adapter = unit->port->adapter;
_zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst",
- tag, 1, adapter, scsi_cmnd, NULL, NULL);
+ tag, 1, adapter, scsi_cmnd, NULL, 0);
}
static int
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 7c84b3d4bd9..8f882690994 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -19,7 +19,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#ifndef ZFCP_DEF_H
#define ZFCP_DEF_H
@@ -32,6 +31,10 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/mempool.h>
+#include <linux/syscalls.h>
+#include <linux/ioctl.h>
#include <scsi/scsi.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_cmnd.h>
@@ -39,14 +42,11 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>
-#include "zfcp_fsf.h"
#include <asm/ccwdev.h>
#include <asm/qdio.h>
#include <asm/debug.h>
#include <asm/ebcdic.h>
-#include <linux/mempool.h>
-#include <linux/syscalls.h>
-#include <linux/ioctl.h>
+#include "zfcp_fsf.h"
/********************* GENERAL DEFINES *********************************/
@@ -137,7 +137,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list)
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
/* timeout value for "default timer" for fsf requests */
-#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
+#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ)
/*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
@@ -779,7 +779,6 @@ typedef void (*zfcp_send_ct_handler_t)(unsigned long);
* @handler_data: data passed to handler function
* @pool: pointer to memory pool for ct request structure
* @timeout: FSF timeout for this request
- * @timer: timer (e.g. for request initiated by erp)
* @completion: completion for synchronization purposes
* @status: used to pass error status to calling function
*/
@@ -793,7 +792,6 @@ struct zfcp_send_ct {
unsigned long handler_data;
mempool_t *pool;
int timeout;
- struct timer_list *timer;
struct completion *completion;
int status;
};
@@ -821,7 +819,6 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
* @resp_count: number of elements in response scatter-gather list
* @handler: handler function (called for response to the request)
* @handler_data: data passed to handler function
- * @timer: timer (e.g. for request initiated by erp)
* @completion: completion for synchronization purposes
* @ls_code: hex code of ELS command
* @status: used to pass error status to calling function
@@ -836,7 +833,6 @@ struct zfcp_send_els {
unsigned int resp_count;
zfcp_send_els_handler_t handler;
unsigned long handler_data;
- struct timer_list *timer;
struct completion *completion;
int ls_code;
int status;
@@ -886,7 +882,6 @@ struct zfcp_adapter {
struct list_head port_remove_lh; /* head of ports to be
removed */
u32 ports; /* number of remote ports */
- struct timer_list scsi_er_timer; /* SCSI err recovery watch */
atomic_t reqs_active; /* # active FSF reqs */
unsigned long req_no; /* unique FSF req number */
struct list_head *req_list; /* list of pending reqs */
@@ -1003,6 +998,7 @@ struct zfcp_fsf_req {
struct fsf_qtcb *qtcb; /* address of associated QTCB */
u32 seq_no; /* Sequence number of request */
unsigned long data; /* private data of request */
+ struct timer_list timer; /* used for erp or scsi er */
struct zfcp_erp_action *erp_action; /* used if this request is
issued on behalf of erp */
mempool_t *pool; /* used if request was alloacted
@@ -1016,6 +1012,7 @@ typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*);
/* driver data */
struct zfcp_data {
struct scsi_host_template scsi_host_template;
+ struct scsi_transport_template *scsi_transport_template;
atomic_t status; /* Module status flags */
struct list_head adapter_list_head; /* head of adapter list */
struct list_head adapter_remove_lh; /* head of adapters to be
@@ -1031,6 +1028,9 @@ struct zfcp_data {
wwn_t init_wwpn;
fcp_lun_t init_fcp_lun;
char *driver_version;
+ kmem_cache_t *fsf_req_qtcb_cache;
+ kmem_cache_t *sr_buffer_cache;
+ kmem_cache_t *gid_pn_cache;
};
/**
@@ -1051,7 +1051,7 @@ struct zfcp_sg_list {
#define ZFCP_POOL_DATA_GID_PN_NR 1
/* struct used by memory pools for fsf_requests */
-struct zfcp_fsf_req_pool_element {
+struct zfcp_fsf_req_qtcb {
struct zfcp_fsf_req fsf_req;
struct fsf_qtcb qtcb;
};
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 7f60b6fdf72..c88babce9bc 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -64,8 +64,6 @@ static int zfcp_erp_strategy_check_action(struct zfcp_erp_action *, int);
static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int);
static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *);
-static void zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *);
-static void zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *);
static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *);
@@ -93,6 +91,7 @@ static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *);
static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *);
static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *);
+static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *);
static void zfcp_erp_action_dismiss_port(struct zfcp_port *);
static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *);
static void zfcp_erp_action_dismiss(struct zfcp_erp_action *);
@@ -111,64 +110,86 @@ static inline void zfcp_erp_action_to_ready(struct zfcp_erp_action *);
static inline void zfcp_erp_action_to_running(struct zfcp_erp_action *);
static void zfcp_erp_memwait_handler(unsigned long);
-static void zfcp_erp_timeout_handler(unsigned long);
-static inline void zfcp_erp_timeout_init(struct zfcp_erp_action *);
/**
- * zfcp_fsf_request_timeout_handler - called if a request timed out
- * @data: pointer to adapter for handler function
- *
- * This function needs to be called if requests (ELS, Generic Service,
- * or SCSI commands) exceed a certain time limit. The assumption is
- * that after the time limit the adapter get stuck. So we trigger a reopen of
- * the adapter. This should not be used for error recovery, SCSI abort
- * commands and SCSI requests from SCSI mid-layer.
+ * zfcp_close_qdio - close qdio queues for an adapter
*/
-void
-zfcp_fsf_request_timeout_handler(unsigned long data)
+static void zfcp_close_qdio(struct zfcp_adapter *adapter)
{
- struct zfcp_adapter *adapter;
+ struct zfcp_qdio_queue *req_queue;
+ int first, count;
- adapter = (struct zfcp_adapter *) data;
+ if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
+ return;
- zfcp_erp_adapter_reopen(adapter, 0);
+ /* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
+ req_queue = &adapter->request_queue;
+ write_lock_irq(&req_queue->queue_lock);
+ atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
+ write_unlock_irq(&req_queue->queue_lock);
+
+ debug_text_event(adapter->erp_dbf, 3, "qdio_down2a");
+ while (qdio_shutdown(adapter->ccw_device,
+ QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
+ msleep(1000);
+ debug_text_event(adapter->erp_dbf, 3, "qdio_down2b");
+
+ /* cleanup used outbound sbals */
+ count = atomic_read(&req_queue->free_count);
+ if (count < QDIO_MAX_BUFFERS_PER_Q) {
+ first = (req_queue->free_index+count) % QDIO_MAX_BUFFERS_PER_Q;
+ count = QDIO_MAX_BUFFERS_PER_Q - count;
+ zfcp_qdio_zero_sbals(req_queue->buffer, first, count);
+ }
+ req_queue->free_index = 0;
+ atomic_set(&req_queue->free_count, 0);
+ req_queue->distance_from_int = 0;
+ adapter->response_queue.free_index = 0;
+ atomic_set(&adapter->response_queue.free_count, 0);
}
/**
- * zfcp_fsf_scsi_er_timeout_handler - timeout handler for scsi eh tasks
+ * zfcp_close_fsf - stop FSF operations for an adapter
*
- * This function needs to be called whenever a SCSI error recovery
- * action (abort/reset) does not return. Re-opening the adapter means
- * that the abort/reset command can be returned by zfcp. It won't complete
- * via the adapter anymore (because qdio queues are closed). If ERP is
- * already running on this adapter it will be stopped.
+ * Dismiss and cleanup all pending fsf_reqs (this wakes up all initiators of
+ * requests waiting for completion; especially this returns SCSI commands
+ * with error state).
*/
-void zfcp_fsf_scsi_er_timeout_handler(unsigned long data)
+static void zfcp_close_fsf(struct zfcp_adapter *adapter)
{
- struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
- unsigned long flags;
-
- ZFCP_LOG_NORMAL("warning: SCSI error recovery timed out. "
- "Restarting all operations on the adapter %s\n",
- zfcp_get_busid_by_adapter(adapter));
- debug_text_event(adapter->erp_dbf, 1, "eh_lmem_tout");
+ /* close queues to ensure that buffers are not accessed by adapter */
+ zfcp_close_qdio(adapter);
+ zfcp_fsf_req_dismiss_all(adapter);
+ /* reset FSF request sequence number */
+ adapter->fsf_req_seq_no = 0;
+ /* all ports and units are closed */
+ zfcp_erp_modify_adapter_status(adapter,
+ ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
+}
- write_lock_irqsave(&adapter->erp_lock, flags);
- if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
- &adapter->status)) {
- zfcp_erp_modify_adapter_status(adapter,
- ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN,
- ZFCP_CLEAR);
- zfcp_erp_action_dismiss_adapter(adapter);
- write_unlock_irqrestore(&adapter->erp_lock, flags);
- /* dismiss all pending requests including requests for ERP */
- zfcp_fsf_req_dismiss_all(adapter);
- adapter->fsf_req_seq_no = 0;
- } else
- write_unlock_irqrestore(&adapter->erp_lock, flags);
+/**
+ * zfcp_fsf_request_timeout_handler - called if a request timed out
+ * @data: pointer to adapter for handler function
+ *
+ * This function needs to be called if requests (ELS, Generic Service,
+ * or SCSI commands) exceed a certain time limit. The assumption is
+ * that after the time limit the adapter get stuck. So we trigger a reopen of
+ * the adapter.
+ */
+static void zfcp_fsf_request_timeout_handler(unsigned long data)
+{
+ struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
zfcp_erp_adapter_reopen(adapter, 0);
}
+void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
+{
+ fsf_req->timer.function = zfcp_fsf_request_timeout_handler;
+ fsf_req->timer.data = (unsigned long) fsf_req->adapter;
+ fsf_req->timer.expires = timeout;
+ add_timer(&fsf_req->timer);
+}
+
/*
* function:
*
@@ -282,7 +303,6 @@ zfcp_erp_adisc(struct zfcp_port *port)
struct zfcp_ls_adisc *adisc;
void *address = NULL;
int retval = 0;
- struct timer_list *timer;
send_els = kzalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC);
if (send_els == NULL)
@@ -329,22 +349,11 @@ zfcp_erp_adisc(struct zfcp_port *port)
(wwn_t) adisc->wwnn, adisc->hard_nport_id,
adisc->nport_id);
- timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC);
- if (!timer)
- goto nomem;
-
- init_timer(timer);
- timer->function = zfcp_fsf_request_timeout_handler;
- timer->data = (unsigned long) adapter;
- timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
- send_els->timer = timer;
-
retval = zfcp_fsf_send_els(send_els);
if (retval != 0) {
ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "
"0x%08x on adapter %s\n", send_els->d_id,
zfcp_get_busid_by_adapter(adapter));
- del_timer(send_els->timer);
goto freemem;
}
@@ -356,7 +365,6 @@ zfcp_erp_adisc(struct zfcp_port *port)
if (address != NULL)
__free_pages(send_els->req->page, 0);
if (send_els != NULL) {
- kfree(send_els->timer);
kfree(send_els->req);
kfree(send_els->resp);
kfree(send_els);
@@ -382,9 +390,6 @@ zfcp_erp_adisc_handler(unsigned long data)
struct zfcp_ls_adisc_acc *adisc;
send_els = (struct zfcp_send_els *) data;
-
- del_timer(send_els->timer);
-
adapter = send_els->adapter;
port = send_els->port;
d_id = send_els->d_id;
@@ -433,7 +438,6 @@ zfcp_erp_adisc_handler(unsigned long data)
out:
zfcp_port_put(port);
__free_pages(send_els->req->page, 0);
- kfree(send_els->timer);
kfree(send_els->req);
kfree(send_els->resp);
kfree(send_els);
@@ -909,8 +913,6 @@ static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action,
debug_text_event(adapter->erp_dbf, 2, "a_asyh_ex");
debug_event(adapter->erp_dbf, 2, &erp_action->action,
sizeof (int));
- if (!(set_mask & ZFCP_STATUS_ERP_TIMEDOUT))
- del_timer(&erp_action->timer);
erp_action->status |= set_mask;
zfcp_erp_action_ready(erp_action);
} else {
@@ -957,8 +959,7 @@ zfcp_erp_memwait_handler(unsigned long data)
* action gets an appropriate flag and will be processed
* accordingly
*/
-static void
-zfcp_erp_timeout_handler(unsigned long data)
+void zfcp_erp_timeout_handler(unsigned long data)
{
struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data;
struct zfcp_adapter *adapter = erp_action->adapter;
@@ -1934,8 +1935,7 @@ zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close)
&erp_action->adapter->status);
failed_openfcp:
- zfcp_erp_adapter_strategy_close_qdio(erp_action);
- zfcp_erp_adapter_strategy_close_fsf(erp_action);
+ zfcp_close_fsf(erp_action->adapter);
failed_qdio:
out:
return retval;
@@ -1987,7 +1987,7 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
sbale = &(adapter->response_queue.buffer[i]->element[0]);
sbale->length = 0;
sbale->flags = SBAL_FLAGS_LAST_ENTRY;
- sbale->addr = 0;
+ sbale->addr = NULL;
}
ZFCP_LOG_TRACE("calling do_QDIO on adapter %s (flags=0x%x, "
@@ -2040,59 +2040,6 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action)
return retval;
}
-/**
- * zfcp_erp_adapter_strategy_close_qdio - close qdio queues for an adapter
- */
-static void
-zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
-{
- int first_used;
- int used_count;
- struct zfcp_adapter *adapter = erp_action->adapter;
-
- if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) {
- ZFCP_LOG_DEBUG("error: attempt to shut down inactive QDIO "
- "queues on adapter %s\n",
- zfcp_get_busid_by_adapter(adapter));
- return;
- }
-
- /*
- * Get queue_lock and clear QDIOUP flag. Thus it's guaranteed that
- * do_QDIO won't be called while qdio_shutdown is in progress.
- */
- write_lock_irq(&adapter->request_queue.queue_lock);
- atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
- write_unlock_irq(&adapter->request_queue.queue_lock);
-
- debug_text_event(adapter->erp_dbf, 3, "qdio_down2a");
- while (qdio_shutdown(adapter->ccw_device,
- QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS)
- msleep(1000);
- debug_text_event(adapter->erp_dbf, 3, "qdio_down2b");
-
- /*
- * First we had to stop QDIO operation.
- * Now it is safe to take the following actions.
- */
-
- /* Cleanup only necessary when there are unacknowledged buffers */
- if (atomic_read(&adapter->request_queue.free_count)
- < QDIO_MAX_BUFFERS_PER_Q) {
- first_used = (adapter->request_queue.free_index +
- atomic_read(&adapter->request_queue.free_count))
- % QDIO_MAX_BUFFERS_PER_Q;
- used_count = QDIO_MAX_BUFFERS_PER_Q -
- atomic_read(&adapter->request_queue.free_count);
- zfcp_qdio_zero_sbals(adapter->request_queue.buffer,
- first_used, used_count);
- }
- adapter->response_queue.free_index = 0;
- atomic_set(&adapter->response_queue.free_count, 0);
- adapter->request_queue.free_index = 0;
- atomic_set(&adapter->request_queue.free_count, 0);
- adapter->request_queue.distance_from_int = 0;
-}
static int
zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action)
@@ -2127,7 +2074,6 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
write_lock_irq(&adapter->erp_lock);
zfcp_erp_action_to_running(erp_action);
write_unlock_irq(&adapter->erp_lock);
- zfcp_erp_timeout_init(erp_action);
if (zfcp_fsf_exchange_config_data(erp_action)) {
retval = ZFCP_ERP_FAILED;
debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf");
@@ -2196,7 +2142,6 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action)
zfcp_erp_action_to_running(erp_action);
write_unlock_irq(&adapter->erp_lock);
- zfcp_erp_timeout_init(erp_action);
ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL);
if (ret == -EOPNOTSUPP) {
debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp");
@@ -2248,27 +2193,6 @@ zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action
return retval;
}
-/**
- * zfcp_erp_adapter_strategy_close_fsf - stop FSF operations for an adapter
- */
-static void
-zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action)
-{
- struct zfcp_adapter *adapter = erp_action->adapter;
-
- /*
- * wake waiting initiators of requests,
- * return SCSI commands (with error status),
- * clean up all requests (synchronously)
- */
- zfcp_fsf_req_dismiss_all(adapter);
- /* reset FSF request sequence number */
- adapter->fsf_req_seq_no = 0;
- /* all ports and units are closed */
- zfcp_erp_modify_adapter_status(adapter,
- ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
-}
-
/*
* function:
*
@@ -2605,7 +2529,6 @@ zfcp_erp_port_forced_strategy_close(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_port *port = erp_action->port;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_fsf_close_physical_port(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "o_pfstc_nomem");
@@ -2662,7 +2585,6 @@ zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_port *port = erp_action->port;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_fsf_close_port(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "p_pstc_nomem");
@@ -2700,7 +2622,6 @@ zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_port *port = erp_action->port;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_fsf_open_port(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "p_psto_nomem");
@@ -2738,7 +2659,6 @@ zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_port *port = erp_action->port;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_ns_gid_pn_request(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "p_pstn_nomem");
@@ -2864,7 +2784,6 @@ zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_unit *unit = erp_action->unit;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_fsf_close_unit(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "u_ustc_nomem");
@@ -2905,7 +2824,6 @@ zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;
struct zfcp_unit *unit = erp_action->unit;
- zfcp_erp_timeout_init(erp_action);
retval = zfcp_fsf_open_unit(erp_action);
if (retval == -ENOMEM) {
debug_text_event(adapter->erp_dbf, 5, "u_usto_nomem");
@@ -2930,14 +2848,13 @@ zfcp_erp_unit_strategy_open(struct zfcp_erp_action *erp_action)
return retval;
}
-static inline void
-zfcp_erp_timeout_init(struct zfcp_erp_action *erp_action)
+void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req)
{
- init_timer(&erp_action->timer);
- erp_action->timer.function = zfcp_erp_timeout_handler;
- erp_action->timer.data = (unsigned long) erp_action;
- /* jiffies will be added in zfcp_fsf_req_send */
- erp_action->timer.expires = ZFCP_ERP_FSFREQ_TIMEOUT;
+ BUG_ON(!fsf_req->erp_action);
+ fsf_req->timer.function = zfcp_erp_timeout_handler;
+ fsf_req->timer.data = (unsigned long) fsf_req->erp_action;
+ fsf_req->timer.expires = jiffies + ZFCP_ERP_FSFREQ_TIMEOUT;
+ add_timer(&fsf_req->timer);
}
/*
@@ -3241,7 +3158,7 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
}
-void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
+static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
{
struct zfcp_port *port;
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 146d7a2b4c4..b8794d77285 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -55,7 +55,6 @@ extern void zfcp_unit_dequeue(struct zfcp_unit *);
/******************************* S/390 IO ************************************/
extern int zfcp_ccw_register(void);
-extern void zfcp_ccw_unregister(void);
extern void zfcp_qdio_zero_sbals(struct qdio_buffer **, int, int);
extern int zfcp_qdio_allocate(struct zfcp_adapter *);
@@ -88,8 +87,8 @@ extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *,
struct fsf_qtcb_bottom_port *);
extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
u32, u32, struct zfcp_sg_list *);
-extern void zfcp_fsf_request_timeout_handler(unsigned long);
-extern void zfcp_fsf_scsi_er_timeout_handler(unsigned long);
+extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long);
+extern void zfcp_erp_start_timer(struct zfcp_fsf_req *);
extern int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
extern int zfcp_fsf_status_read(struct zfcp_adapter *, int);
extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *,
@@ -99,8 +98,7 @@ extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *,
extern int zfcp_fsf_send_els(struct zfcp_send_els *);
extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *,
struct zfcp_unit *,
- struct scsi_cmnd *,
- struct timer_list*, int);
+ struct scsi_cmnd *, int, int);
extern int zfcp_fsf_req_complete(struct zfcp_fsf_req *);
extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *);
extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
@@ -124,14 +122,11 @@ extern char *zfcp_get_fcp_rsp_info_ptr(struct fcp_rsp_iu *);
extern void set_host_byte(u32 *, char);
extern void set_driver_byte(u32 *, char);
extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *);
-extern void zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *);
extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *);
extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
- struct scsi_cmnd *, struct timer_list *);
-extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
- struct timer_list *);
-extern struct scsi_transport_template *zfcp_transport_template;
+ struct scsi_cmnd *, int);
+extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *, int);
extern struct fc_function_template zfcp_transport_functions;
/******************************** ERP ****************************************/
@@ -139,7 +134,6 @@ extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u32, int);
extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int);
extern int zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int);
extern void zfcp_erp_adapter_failed(struct zfcp_adapter *);
-extern void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *);
extern void zfcp_erp_modify_port_status(struct zfcp_port *, u32, int);
extern int zfcp_erp_port_reopen(struct zfcp_port *, int);
@@ -187,7 +181,7 @@ extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *,
struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
struct scsi_cmnd *, struct zfcp_fsf_req *,
- struct zfcp_fsf_req *);
+ unsigned long);
extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
struct scsi_cmnd *);
extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index ff2eacf5ec8..277826cdd0c 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -42,7 +42,7 @@ static inline int zfcp_fsf_req_sbal_check(
static inline int zfcp_use_one_sbal(
struct scatterlist *, int, struct scatterlist *, int);
static struct zfcp_fsf_req *zfcp_fsf_req_alloc(mempool_t *, int);
-static int zfcp_fsf_req_send(struct zfcp_fsf_req *, struct timer_list *);
+static int zfcp_fsf_req_send(struct zfcp_fsf_req *);
static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *);
static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *);
static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
@@ -100,14 +100,19 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
if (req_flags & ZFCP_REQ_NO_QTCB)
size = sizeof(struct zfcp_fsf_req);
else
- size = sizeof(struct zfcp_fsf_req_pool_element);
+ size = sizeof(struct zfcp_fsf_req_qtcb);
- if (likely(pool != NULL))
+ if (likely(pool))
ptr = mempool_alloc(pool, GFP_ATOMIC);
- else
- ptr = kmalloc(size, GFP_ATOMIC);
+ else {
+ if (req_flags & ZFCP_REQ_NO_QTCB)
+ ptr = kmalloc(size, GFP_ATOMIC);
+ else
+ ptr = kmem_cache_alloc(zfcp_data.fsf_req_qtcb_cache,
+ SLAB_ATOMIC);
+ }
- if (unlikely(NULL == ptr))
+ if (unlikely(!ptr))
goto out;
memset(ptr, 0, size);
@@ -115,9 +120,8 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
if (req_flags & ZFCP_REQ_NO_QTCB) {
fsf_req = (struct zfcp_fsf_req *) ptr;
} else {
- fsf_req = &((struct zfcp_fsf_req_pool_element *) ptr)->fsf_req;
- fsf_req->qtcb =
- &((struct zfcp_fsf_req_pool_element *) ptr)->qtcb;
+ fsf_req = &((struct zfcp_fsf_req_qtcb *) ptr)->fsf_req;
+ fsf_req->qtcb = &((struct zfcp_fsf_req_qtcb *) ptr)->qtcb;
}
fsf_req->pool = pool;
@@ -139,10 +143,17 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
void
zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req)
{
- if (likely(fsf_req->pool != NULL))
+ if (likely(fsf_req->pool)) {
mempool_free(fsf_req, fsf_req->pool);
- else
- kfree(fsf_req);
+ return;
+ }
+
+ if (fsf_req->qtcb) {
+ kmem_cache_free(zfcp_data.fsf_req_qtcb_cache, fsf_req);
+ return;
+ }
+
+ kfree(fsf_req);
}
/**
@@ -214,8 +225,10 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req)
*/
zfcp_fsf_status_read_handler(fsf_req);
goto out;
- } else
+ } else {
+ del_timer(&fsf_req->timer);
zfcp_fsf_protstatus_eval(fsf_req);
+ }
/*
* fsf_req may be deleted due to waking up functions, so
@@ -774,8 +787,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags)
sbale->addr = (void *) status_buffer;
sbale->length = sizeof(struct fsf_status_read_buffer);
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(fsf_req, NULL);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_DEBUG("error: Could not set-up unsolicited status "
"environment.\n");
@@ -1101,8 +1113,8 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
struct zfcp_unit *unit, int req_flags)
{
volatile struct qdio_buffer_element *sbale;
- unsigned long lock_flags;
struct zfcp_fsf_req *fsf_req = NULL;
+ unsigned long lock_flags;
int retval = 0;
/* setup new FSF request */
@@ -1132,12 +1144,9 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
/* set handle of request which should be aborted */
fsf_req->qtcb->bottom.support.req_handle = (u64) old_req_id;
- /* start QDIO request for this FSF request */
-
- zfcp_fsf_start_scsi_er_timer(adapter);
- retval = zfcp_fsf_req_send(fsf_req, NULL);
+ zfcp_fsf_start_timer(fsf_req, ZFCP_SCSI_ER_TIMEOUT);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
- del_timer(&adapter->scsi_er_timer);
ZFCP_LOG_INFO("error: Failed to send abort command request "
"on adapter %s, port 0x%016Lx, unit 0x%016Lx\n",
zfcp_get_busid_by_adapter(adapter),
@@ -1173,8 +1182,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
unsigned char status_qual =
new_fsf_req->qtcb->header.fsf_status_qual.word[0];
- del_timer(&new_fsf_req->adapter->scsi_er_timer);
-
if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
/* do not set ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED */
goto skip_fsfstatus;
@@ -1380,11 +1387,6 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
goto failed_req;
}
- if (erp_action != NULL) {
- erp_action->fsf_req = fsf_req;
- fsf_req->erp_action = erp_action;
- }
-
sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
if (zfcp_use_one_sbal(ct->req, ct->req_count,
ct->resp, ct->resp_count)){
@@ -1451,8 +1453,14 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool,
zfcp_san_dbf_event_ct_request(fsf_req);
- /* start QDIO request for this FSF request */
- ret = zfcp_fsf_req_send(fsf_req, ct->timer);
+ if (erp_action) {
+ erp_action->fsf_req = fsf_req;
+ fsf_req->erp_action = erp_action;
+ zfcp_erp_start_timer(fsf_req);
+ } else
+ zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
+
+ ret = zfcp_fsf_req_send(fsf_req);
if (ret) {
ZFCP_LOG_DEBUG("error: initiation of CT request failed "
"(adapter %s, port 0x%016Lx)\n",
@@ -1749,8 +1757,8 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
zfcp_san_dbf_event_els_request(fsf_req);
- /* start QDIO request for this FSF request */
- ret = zfcp_fsf_req_send(fsf_req, els->timer);
+ zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
+ ret = zfcp_fsf_req_send(fsf_req);
if (ret) {
ZFCP_LOG_DEBUG("error: initiation of ELS request failed "
"(adapter %s, port d_id: 0x%08x)\n",
@@ -1947,6 +1955,7 @@ int
zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
{
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
unsigned long lock_flags;
int retval = 0;
@@ -1955,7 +1964,7 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
FSF_QTCB_EXCHANGE_CONFIG_DATA,
ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &(erp_action->fsf_req));
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create exchange configuration "
"data request for adapter %s.\n",
@@ -1963,26 +1972,26 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- erp_action->fsf_req->erp_action = erp_action;
- erp_action->fsf_req->qtcb->bottom.config.feature_selection =
+ fsf_req->qtcb->bottom.config.feature_selection =
FSF_FEATURE_CFDC |
FSF_FEATURE_LUN_SHARING |
FSF_FEATURE_NOTIFICATION_LOST |
FSF_FEATURE_UPDATE_ALERT;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_INFO
("error: Could not send exchange configuration data "
"command on the adapter %s\n",
zfcp_get_busid_by_adapter(erp_action->adapter));
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -2212,10 +2221,9 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
struct fsf_qtcb_bottom_port *data)
{
volatile struct qdio_buffer_element *sbale;
- int retval = 0;
- unsigned long lock_flags;
struct zfcp_fsf_req *fsf_req;
- struct timer_list *timer;
+ unsigned long lock_flags;
+ int retval = 0;
if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) {
ZFCP_LOG_INFO("error: exchange port data "
@@ -2248,22 +2256,11 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
if (erp_action) {
erp_action->fsf_req = fsf_req;
fsf_req->erp_action = erp_action;
- timer = &erp_action->timer;
- } else {
- timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC);
- if (!timer) {
- write_unlock_irqrestore(&adapter->request_queue.queue_lock,
- lock_flags);
- zfcp_fsf_req_free(fsf_req);
- return -ENOMEM;
- }
- init_timer(timer);
- timer->function = zfcp_fsf_request_timeout_handler;
- timer->data = (unsigned long) adapter;
- timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
- }
+ zfcp_erp_start_timer(fsf_req);
+ } else
+ zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
- retval = zfcp_fsf_req_send(fsf_req, timer);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send an exchange port data "
"command on the adapter %s\n",
@@ -2271,8 +2268,6 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
zfcp_fsf_req_free(fsf_req);
if (erp_action)
erp_action->fsf_req = NULL;
- else
- kfree(timer);
write_unlock_irqrestore(&adapter->request_queue.queue_lock,
lock_flags);
return retval;
@@ -2283,9 +2278,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action,
if (!erp_action) {
wait_event(fsf_req->completion_wq,
fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
- del_timer_sync(timer);
zfcp_fsf_req_free(fsf_req);
- kfree(timer);
}
return retval;
}
@@ -2367,6 +2360,7 @@ int
zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
{
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
unsigned long lock_flags;
int retval = 0;
@@ -2375,7 +2369,7 @@ zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
FSF_QTCB_OPEN_PORT_WITH_DID,
ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &(erp_action->fsf_req));
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create open port request "
"for port 0x%016Lx on adapter %s.\n",
@@ -2384,24 +2378,24 @@ zfcp_fsf_open_port(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id;
+ fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id;
atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status);
- erp_action->fsf_req->data = (unsigned long) erp_action->port;
- erp_action->fsf_req->erp_action = erp_action;
+ fsf_req->data = (unsigned long) erp_action->port;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send open port request for "
"port 0x%016Lx on adapter %s.\n",
erp_action->port->wwpn,
zfcp_get_busid_by_adapter(erp_action->adapter));
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -2623,6 +2617,7 @@ int
zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
{
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
unsigned long lock_flags;
int retval = 0;
@@ -2631,7 +2626,7 @@ zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
FSF_QTCB_CLOSE_PORT,
ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &(erp_action->fsf_req));
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create a close port request "
"for port 0x%016Lx on adapter %s.\n",
@@ -2640,25 +2635,25 @@ zfcp_fsf_close_port(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status);
- erp_action->fsf_req->data = (unsigned long) erp_action->port;
- erp_action->fsf_req->erp_action = erp_action;
- erp_action->fsf_req->qtcb->header.port_handle =
- erp_action->port->handle;
-
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ fsf_req->data = (unsigned long) erp_action->port;
+ fsf_req->erp_action = erp_action;
+ fsf_req->qtcb->header.port_handle = erp_action->port->handle;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
+
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send a close port request for "
"port 0x%016Lx on adapter %s.\n",
erp_action->port->wwpn,
zfcp_get_busid_by_adapter(erp_action->adapter));
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -2755,16 +2750,17 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
int
zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
{
- int retval = 0;
- unsigned long lock_flags;
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
+ unsigned long lock_flags;
+ int retval = 0;
/* setup new FSF request */
retval = zfcp_fsf_req_create(erp_action->adapter,
FSF_QTCB_CLOSE_PHYSICAL_PORT,
ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &erp_action->fsf_req);
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create close physical port "
"request (adapter %s, port 0x%016Lx)\n",
@@ -2774,8 +2770,7 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
@@ -2783,20 +2778,19 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action)
atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING,
&erp_action->port->status);
/* save a pointer to this port */
- erp_action->fsf_req->data = (unsigned long) erp_action->port;
- /* port to be closed */
- erp_action->fsf_req->qtcb->header.port_handle =
- erp_action->port->handle;
- erp_action->fsf_req->erp_action = erp_action;
-
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ fsf_req->data = (unsigned long) erp_action->port;
+ fsf_req->qtcb->header.port_handle = erp_action->port->handle;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
+
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send close physical port "
"request (adapter %s, port 0x%016Lx)\n",
zfcp_get_busid_by_adapter(erp_action->adapter),
erp_action->port->wwpn);
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -2961,6 +2955,7 @@ int
zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
{
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
unsigned long lock_flags;
int retval = 0;
@@ -2969,7 +2964,7 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
FSF_QTCB_OPEN_LUN,
ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &(erp_action->fsf_req));
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create open unit request for "
"unit 0x%016Lx on port 0x%016Lx on adapter %s.\n",
@@ -2979,24 +2974,22 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- erp_action->fsf_req->qtcb->header.port_handle =
- erp_action->port->handle;
- erp_action->fsf_req->qtcb->bottom.support.fcp_lun =
- erp_action->unit->fcp_lun;
+ fsf_req->qtcb->header.port_handle = erp_action->port->handle;
+ fsf_req->qtcb->bottom.support.fcp_lun = erp_action->unit->fcp_lun;
if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE))
- erp_action->fsf_req->qtcb->bottom.support.option =
+ fsf_req->qtcb->bottom.support.option =
FSF_OPEN_LUN_SUPPRESS_BOXING;
atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status);
- erp_action->fsf_req->data = (unsigned long) erp_action->unit;
- erp_action->fsf_req->erp_action = erp_action;
+ fsf_req->data = (unsigned long) erp_action->unit;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(erp_action->fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send an open unit request "
"on the adapter %s, port 0x%016Lx for "
@@ -3004,7 +2997,7 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action)
zfcp_get_busid_by_adapter(erp_action->adapter),
erp_action->port->wwpn,
erp_action->unit->fcp_lun);
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -3297,6 +3290,7 @@ int
zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
{
volatile struct qdio_buffer_element *sbale;
+ struct zfcp_fsf_req *fsf_req;
unsigned long lock_flags;
int retval = 0;
@@ -3305,7 +3299,7 @@ zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
FSF_QTCB_CLOSE_LUN,
ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP,
erp_action->adapter->pool.fsf_req_erp,
- &lock_flags, &(erp_action->fsf_req));
+ &lock_flags, &fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("error: Could not create close unit request for "
"unit 0x%016Lx on port 0x%016Lx on adapter %s.\n",
@@ -3315,27 +3309,26 @@ zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action)
goto out;
}
- sbale = zfcp_qdio_sbale_req(erp_action->fsf_req,
- erp_action->fsf_req->sbal_curr, 0);
+ sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- erp_action->fsf_req->qtcb->header.port_handle =
- erp_action->port->handle;
- erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle;
+ fsf_req->qtcb->header.port_handle = erp_action->port->handle;
+ fsf_req->qtcb->header.lun_handle = erp_action->unit->handle;
atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status);
- erp_action->fsf_req->data = (unsigned long) erp_action->unit;
- erp_action->fsf_req->erp_action = erp_action;
+ fsf_req->data = (unsigned long) erp_action->unit;
+ fsf_req->erp_action = erp_action;
+ erp_action->fsf_req = fsf_req;
- /* start QDIO request for this FSF request */
- retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer);
+ zfcp_erp_start_timer(fsf_req);
+ retval = zfcp_fsf_req_send(erp_action->fsf_req);
if (retval) {
ZFCP_LOG_INFO("error: Could not send a close unit request for "
"unit 0x%016Lx on port 0x%016Lx onadapter %s.\n",
erp_action->unit->fcp_lun,
erp_action->port->wwpn,
zfcp_get_busid_by_adapter(erp_action->adapter));
- zfcp_fsf_req_free(erp_action->fsf_req);
+ zfcp_fsf_req_free(fsf_req);
erp_action->fsf_req = NULL;
goto out;
}
@@ -3488,7 +3481,7 @@ int
zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
struct zfcp_unit *unit,
struct scsi_cmnd * scsi_cmnd,
- struct timer_list *timer, int req_flags)
+ int use_timer, int req_flags)
{
struct zfcp_fsf_req *fsf_req = NULL;
struct fcp_cmnd_iu *fcp_cmnd_iu;
@@ -3516,7 +3509,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
fsf_req->unit = unit;
/* associate FSF request with SCSI request (for look up on abort) */
- scsi_cmnd->host_scribble = (char *) fsf_req;
+ scsi_cmnd->host_scribble = (unsigned char *) fsf_req->req_id;
/* associate SCSI command with FSF request */
fsf_req->data = (unsigned long) scsi_cmnd;
@@ -3629,11 +3622,10 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG,
(char *) scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
- /*
- * start QDIO request for this FSF request
- * covered by an SBALE)
- */
- retval = zfcp_fsf_req_send(fsf_req, timer);
+ if (use_timer)
+ zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
+
+ retval = zfcp_fsf_req_send(fsf_req);
if (unlikely(retval < 0)) {
ZFCP_LOG_INFO("error: Could not send FCP command request "
"on adapter %s, port 0x%016Lx, unit 0x%016Lx\n",
@@ -3718,11 +3710,9 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter,
fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
fcp_cmnd_iu->task_management_flags = tm_flags;
- /* start QDIO request for this FSF request */
- zfcp_fsf_start_scsi_er_timer(adapter);
- retval = zfcp_fsf_req_send(fsf_req, NULL);
+ zfcp_fsf_start_timer(fsf_req, ZFCP_SCSI_ER_TIMEOUT);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval) {
- del_timer(&adapter->scsi_er_timer);
ZFCP_LOG_INFO("error: Could not send an FCP-command (task "
"management) on adapter %s, port 0x%016Lx for "
"unit LUN 0x%016Lx\n",
@@ -4226,7 +4216,6 @@ zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req)
char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu);
struct zfcp_unit *unit = (struct zfcp_unit *) fsf_req->data;
- del_timer(&fsf_req->adapter->scsi_er_timer);
if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) {
fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCFAILED;
goto skip_fsfstatus;
@@ -4295,7 +4284,6 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
struct zfcp_fsf_req *fsf_req;
struct fsf_qtcb_bottom_support *bottom;
volatile struct qdio_buffer_element *sbale;
- struct timer_list *timer;
unsigned long lock_flags;
int req_flags = 0;
int direction;
@@ -4327,12 +4315,6 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
goto out;
}
- timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
- if (!timer) {
- retval = -ENOMEM;
- goto out;
- }
-
retval = zfcp_fsf_req_create(adapter, fsf_command, req_flags,
NULL, &lock_flags, &fsf_req);
if (retval < 0) {
@@ -4367,12 +4349,8 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
} else
sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
- init_timer(timer);
- timer->function = zfcp_fsf_request_timeout_handler;
- timer->data = (unsigned long) adapter;
- timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
-
- retval = zfcp_fsf_req_send(fsf_req, timer);
+ zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT);
+ retval = zfcp_fsf_req_send(fsf_req);
if (retval < 0) {
ZFCP_LOG_INFO("initiation of cfdc up/download failed"
"(adapter %s)\n",
@@ -4392,15 +4370,12 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter,
fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
*fsf_req_ptr = fsf_req;
- del_timer_sync(timer);
- goto free_timer;
+ goto out;
free_fsf_req:
zfcp_fsf_req_free(fsf_req);
unlock_queue_lock:
write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags);
- free_timer:
- kfree(timer);
out:
return retval;
}
@@ -4656,7 +4631,6 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
{
volatile struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *fsf_req = NULL;
- unsigned long flags;
int ret = 0;
struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
@@ -4673,12 +4647,13 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
fsf_req->fsf_command = fsf_cmd;
INIT_LIST_HEAD(&fsf_req->list);
- /* unique request id */
- spin_lock_irqsave(&adapter->req_list_lock, flags);
+ /* this is serialized (we are holding req_queue-lock of adapter */
+ if (adapter->req_no == 0)
+ adapter->req_no++;
fsf_req->req_id = adapter->req_no++;
- spin_unlock_irqrestore(&adapter->req_list_lock, flags);
- zfcp_fsf_req_qtcb_init(fsf_req);
+ init_timer(&fsf_req->timer);
+ zfcp_fsf_req_qtcb_init(fsf_req);
/* initialize waitqueue which may be used to wait on
this request completion */
@@ -4748,8 +4723,7 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
* returns: 0 - request transfer succesfully started
* !0 - start of request transfer failed
*/
-static int
-zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
+static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_adapter *adapter;
struct zfcp_qdio_queue *req_queue;
@@ -4777,12 +4751,6 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
inc_seq_no = (fsf_req->qtcb != NULL);
- /* figure out expiration time of timeout and start timeout */
- if (unlikely(timer)) {
- timer->expires += jiffies;
- add_timer(timer);
- }
-
ZFCP_LOG_TRACE("request queue of adapter %s: "
"next free SBAL is %i, %i free SBALs\n",
zfcp_get_busid_by_adapter(adapter),
@@ -4819,12 +4787,7 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
if (unlikely(retval)) {
/* Queues are down..... */
retval = -EIO;
- /*
- * FIXME(potential race):
- * timer might be expired (absolutely unlikely)
- */
- if (timer)
- del_timer(timer);
+ del_timer(&fsf_req->timer);
spin_lock(&adapter->req_list_lock);
zfcp_reqlist_remove(adapter, fsf_req->req_id);
spin_unlock(&adapter->req_list_lock);
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 1bb55086db9..4d2bc798132 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -39,11 +39,10 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int,
static struct device_attribute *zfcp_sysfs_sdev_attrs[];
-struct scsi_transport_template *zfcp_transport_template;
-
struct zfcp_data zfcp_data = {
.scsi_host_template = {
.name = ZFCP_NAME,
+ .module = THIS_MODULE,
.proc_name = "zfcp",
.slave_alloc = zfcp_scsi_slave_alloc,
.slave_configure = zfcp_scsi_slave_configure,
@@ -232,7 +231,7 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
*/
int
zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
- struct scsi_cmnd *scpnt, struct timer_list *timer)
+ struct scsi_cmnd *scpnt, int use_timer)
{
int tmp;
int retval;
@@ -268,7 +267,7 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
goto out;
}
- tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, timer,
+ tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, use_timer,
ZFCP_REQ_AUTO_CLEANUP);
if (unlikely(tmp < 0)) {
@@ -292,21 +291,22 @@ zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt)
* zfcp_scsi_command_sync - send a SCSI command and wait for completion
* @unit: unit where command is sent to
* @scpnt: scsi command to be sent
- * @timer: timer to be started if request is successfully initiated
+ * @use_timer: indicates whether timer should be setup or not
* Return: 0
*
* Errors are indicated in scpnt->result
*/
int
zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt,
- struct timer_list *timer)
+ int use_timer)
{
int ret;
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
scpnt->SCp.ptr = (void *) &wait; /* silent re-use */
scpnt->scsi_done = zfcp_scsi_command_sync_handler;
- ret = zfcp_scsi_command_async(unit->port->adapter, unit, scpnt, timer);
+ ret = zfcp_scsi_command_async(unit->port->adapter, unit, scpnt,
+ use_timer);
if (ret == 0)
wait_for_completion(&wait);
@@ -342,7 +342,7 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
unit = (struct zfcp_unit *) scpnt->device->hostdata;
- return zfcp_scsi_command_async(adapter, unit, scpnt, NULL);
+ return zfcp_scsi_command_async(adapter, unit, scpnt, 0);
}
static struct zfcp_unit *
@@ -379,16 +379,15 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id,
* will handle late commands. (Usually, the normal completion of late
* commands is ignored with respect to the running abort operation.)
*/
-int
-zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
{
struct Scsi_Host *scsi_host;
struct zfcp_adapter *adapter;
struct zfcp_unit *unit;
- int retval = SUCCESS;
- struct zfcp_fsf_req *new_fsf_req = NULL;
- struct zfcp_fsf_req *old_fsf_req;
+ struct zfcp_fsf_req *fsf_req;
unsigned long flags;
+ unsigned long old_req_id;
+ int retval = SUCCESS;
scsi_host = scpnt->device->host;
adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
@@ -400,55 +399,47 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
/* avoid race condition between late normal completion and abort */
write_lock_irqsave(&adapter->abort_lock, flags);
- /*
- * Check whether command has just completed and can not be aborted.
- * Even if the command has just been completed late, we can access
- * scpnt since the SCSI stack does not release it at least until
- * this routine returns. (scpnt is parameter passed to this routine
- * and must not disappear during abort even on late completion.)
- */
- old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble;
- if (!old_fsf_req) {
+ /* Check whether corresponding fsf_req is still pending */
+ spin_lock(&adapter->req_list_lock);
+ fsf_req = zfcp_reqlist_ismember(adapter, (unsigned long)
+ scpnt->host_scribble);
+ spin_unlock(&adapter->req_list_lock);
+ if (!fsf_req) {
write_unlock_irqrestore(&adapter->abort_lock, flags);
- zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, NULL);
+ zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, 0);
retval = SUCCESS;
goto out;
}
- old_fsf_req->data = 0;
- old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING;
+ fsf_req->data = 0;
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING;
+ old_req_id = fsf_req->req_id;
- /* don't access old_fsf_req after releasing the abort_lock */
+ /* don't access old fsf_req after releasing the abort_lock */
write_unlock_irqrestore(&adapter->abort_lock, flags);
- /* call FSF routine which does the abort */
- new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req,
- adapter, unit, 0);
- if (!new_fsf_req) {
+
+ fsf_req = zfcp_fsf_abort_fcp_command(old_req_id, adapter, unit, 0);
+ if (!fsf_req) {
ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");
zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
- old_fsf_req);
+ old_req_id);
retval = FAILED;
goto out;
}
- /* wait for completion of abort */
- __wait_event(new_fsf_req->completion_wq,
- new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+ __wait_event(fsf_req->completion_wq,
+ fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
- /* status should be valid since signals were not permitted */
- if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
- zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req,
- NULL);
+ if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {
+ zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, fsf_req, 0);
retval = SUCCESS;
- } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
- zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req,
- NULL);
+ } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {
+ zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, fsf_req, 0);
retval = SUCCESS;
} else {
- zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req,
- NULL);
+ zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, fsf_req, 0);
retval = FAILED;
}
- zfcp_fsf_req_free(new_fsf_req);
+ zfcp_fsf_req_free(fsf_req);
out:
return retval;
}
@@ -548,14 +539,11 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags,
/**
* zfcp_scsi_eh_host_reset_handler - handler for host and bus reset
- *
- * If ERP is already running it will be stopped.
*/
int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
{
struct zfcp_unit *unit;
struct zfcp_adapter *adapter;
- unsigned long flags;
unit = (struct zfcp_unit*) scpnt->device->hostdata;
adapter = unit->port->adapter;
@@ -563,22 +551,8 @@ int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
ZFCP_LOG_NORMAL("host/bus reset because of problems with "
"unit 0x%016Lx\n", unit->fcp_lun);
- write_lock_irqsave(&adapter->erp_lock, flags);
- if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
- &adapter->status)) {
- zfcp_erp_modify_adapter_status(adapter,
- ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN,
- ZFCP_CLEAR);
- zfcp_erp_action_dismiss_adapter(adapter);
- write_unlock_irqrestore(&adapter->erp_lock, flags);
- zfcp_fsf_req_dismiss_all(adapter);
- adapter->fsf_req_seq_no = 0;
- zfcp_erp_adapter_reopen(adapter, 0);
- } else {
- write_unlock_irqrestore(&adapter->erp_lock, flags);
- zfcp_erp_adapter_reopen(adapter, 0);
- zfcp_erp_wait(adapter);
- }
+ zfcp_erp_adapter_reopen(adapter, 0);
+ zfcp_erp_wait(adapter);
return SUCCESS;
}
@@ -607,7 +581,7 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
adapter->scsi_host->max_channel = 0;
adapter->scsi_host->unique_id = unique_id++; /* FIXME */
adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH;
- adapter->scsi_host->transportt = zfcp_transport_template;
+ adapter->scsi_host->transportt = zfcp_data.scsi_transport_template;
/*
* save a pointer to our own adapter data structure within
@@ -648,16 +622,6 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
return;
}
-
-void
-zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter)
-{
- adapter->scsi_er_timer.function = zfcp_fsf_scsi_er_timeout_handler;
- adapter->scsi_er_timer.data = (unsigned long) adapter;
- adapter->scsi_er_timer.expires = jiffies + ZFCP_SCSI_ER_TIMEOUT;
- add_timer(&adapter->scsi_er_timer);
-}
-
/*
* Support functions for FC transport class
*/