diff -ruN linux-2.4.21/arch/s390x/kernel/ioctl32.c linux-2.3/arch/s390x/kernel/ioctl32.c --- linux-2.4.21/arch/s390x/kernel/ioctl32.c 2004-09-08 15:38:11.000000000 +0200 +++ linux-2.3/arch/s390x/kernel/ioctl32.c 2004-08-14 07:57:53.000000000 +0200 @@ -625,14 +625,23 @@ u32 u_mult_inv; } ica_rsa_modexpo_crt_32_t; -#define ICA_IOCTL_MAGIC 'z' -#define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, ICA_IOCTL_MAGIC, 0x05, 0) -#define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, ICA_IOCTL_MAGIC, 0x06, 0) -#define ICARSAMODMULT _IOC(_IOC_READ|_IOC_WRITE, ICA_IOCTL_MAGIC, 0x07, 0) -#define ICAZ90STATUS _IOC(_IOC_READ, ICA_IOCTL_MAGIC, 0x10, sizeof(ica_z90_status)) -#define ICAZ90QUIESCE _IOC(_IOC_NONE, ICA_IOCTL_MAGIC, 0x11, 0) -#define ICAZ90HARDRESET _IOC(_IOC_NONE, ICA_IOCTL_MAGIC, 0x12, 0) -#define ICAZ90HARDERROR _IOC(_IOC_NONE, ICA_IOCTL_MAGIC, 0x13, 0) +#define Z90_IOCTL_MAGIC 'z' +#define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0) +#define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0) +#define ICAZ90STATUS _IOR(Z90_IOCTL_MAGIC, 0x10, ica_z90_status) +#define Z90QUIESCE _IO(Z90_IOCTL_MAGIC, 0x11) +#define Z90STAT_TOTALCOUNT _IOR(Z90_IOCTL_MAGIC, 0x40, int) +#define Z90STAT_PCICACOUNT _IOR(Z90_IOCTL_MAGIC, 0x41, int) +#define Z90STAT_PCICCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x42, int) +#define Z90STAT_PCIXCCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x43, int) +#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int) +#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int) +#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int) +#define Z90STAT_DOMAIN_INDEX _IOR(Z90_IOCTL_MAGIC, 0x47, int) +#define Z90STAT_STATUS_MASK _IOR(Z90_IOCTL_MAGIC, 0x48, char[64]) +#define Z90STAT_QDEPTH_MASK _IOR(Z90_IOCTL_MAGIC, 0x49, char[64]) +#define Z90STAT_PERDEV_REQCNT _IOR(Z90_IOCTL_MAGIC, 0x4a, int[64]) + static int do_rsa_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { @@ -1041,11 +1050,19 @@ IOCTL32_HANDLER(ICARSAMODEXPO, do_rsa_ioctl), IOCTL32_HANDLER(ICARSACRT, do_rsa_crt_ioctl), - IOCTL32_HANDLER(ICARSAMODMULT, do_rsa_ioctl), IOCTL32_DEFAULT(ICAZ90STATUS), - IOCTL32_DEFAULT(ICAZ90QUIESCE), - IOCTL32_DEFAULT(ICAZ90HARDRESET), - IOCTL32_DEFAULT(ICAZ90HARDERROR), + IOCTL32_DEFAULT(Z90QUIESCE), + IOCTL32_DEFAULT(Z90STAT_TOTALCOUNT), + IOCTL32_DEFAULT(Z90STAT_PCICACOUNT), + IOCTL32_DEFAULT(Z90STAT_PCICCCOUNT), + IOCTL32_DEFAULT(Z90STAT_PCIXCCCOUNT), + IOCTL32_DEFAULT(Z90STAT_REQUESTQ_COUNT), + IOCTL32_DEFAULT(Z90STAT_PENDINGQ_COUNT), + IOCTL32_DEFAULT(Z90STAT_TOTALOPEN_COUNT), + IOCTL32_DEFAULT(Z90STAT_DOMAIN_INDEX), + IOCTL32_DEFAULT(Z90STAT_STATUS_MASK), + IOCTL32_DEFAULT(Z90STAT_QDEPTH_MASK), + IOCTL32_DEFAULT(Z90STAT_PERDEV_REQCNT), /* Raw devices */ IOCTL32_DEFAULT(RAW_SETBIND), diff -ruN linux-2.4.21/arch/s390x/kernel/linux32.c linux-2.3/arch/s390x/kernel/linux32.c --- linux-2.4.21/arch/s390x/kernel/linux32.c 2004-09-08 15:38:10.000000000 +0200 +++ linux-2.3/arch/s390x/kernel/linux32.c 2004-08-16 14:19:32.000000000 +0200 @@ -4427,7 +4427,7 @@ ret = sys_newstat(tmp, &s); set_fs (old_fs); putname(tmp); - if (putstat64 (statbuf, &s)) + if (!ret && putstat64 (statbuf, &s)) return -EFAULT; return ret; } @@ -4451,7 +4451,7 @@ ret = sys_newlstat(tmp, &s); set_fs (old_fs); putname(tmp); - if (putstat64 (statbuf, &s)) + if (!ret && putstat64 (statbuf, &s)) return -EFAULT; return ret; } @@ -4467,7 +4467,7 @@ set_fs (KERNEL_DS); ret = sys_newfstat(fd, &s); set_fs (old_fs); - if (putstat64 (statbuf, &s)) + if (!ret && putstat64 (statbuf, &s)) return -EFAULT; return ret; } @@ -4507,7 +4507,7 @@ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) { /* Result is out of bounds. */ - do_munmap(current->mm, addr, len); + do_munmap(current->mm, error, len); error = -ENOMEM; } up_write(¤t->mm->mmap_sem); diff -ruN linux-2.4.21/drivers/s390/block/dasd.c linux-2.3/drivers/s390/block/dasd.c --- linux-2.4.21/drivers/s390/block/dasd.c 2004-09-08 15:38:11.000000000 +0200 +++ linux-2.3/drivers/s390/block/dasd.c 2004-07-27 15:24:59.000000000 +0200 @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.298.2.10 $ + * $Revision: 1.298.2.11 $ * * History of changes (starts July 2000) * 11/09/00 complete redesign after code review @@ -5205,6 +5205,7 @@ "/proc/dasd/statistics: only 'set' and " "'reset' are supported verbs"); + vfree (buffer); return -EINVAL; } @@ -5260,6 +5261,7 @@ #endif /* DASD_PROFILE */ + vfree (buffer); return user_len; } diff -ruN linux-2.4.21/drivers/s390/char/sclp.c linux-2.3/drivers/s390/char/sclp.c --- linux-2.4.21/drivers/s390/char/sclp.c 2004-09-08 15:38:11.000000000 +0200 +++ linux-2.3/drivers/s390/char/sclp.c 2004-08-23 17:47:15.000000000 +0200 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -53,13 +54,18 @@ /* Timer for init mask retries. */ static struct timer_list retry_timer; +/* Timer for busy retries. */ +static struct timer_list sclp_busy_timer; + static volatile unsigned long sclp_status = 0; /* some status flags */ #define SCLP_INIT 0 #define SCLP_RUNNING 1 #define SCLP_READING 2 +#define SCLP_SHUTDOWN 3 #define SCLP_INIT_POLL_INTERVAL 1 +#define SCLP_BUSY_POLL_INTERVAL 1 #define SCLP_COMMAND_INITIATED 0 #define SCLP_BUSY 2 @@ -94,45 +100,61 @@ */ if (cc == SCLP_NOT_OPERATIONAL) return -EIO; - /* - * We set the SCLP_RUNNING bit for cc 2 as well because if - * service_call returns cc 2 some old request is running - * that has to complete first - */ - set_bit(SCLP_RUNNING, &sclp_status); if (cc == SCLP_BUSY) return -EBUSY; return 0; } -static int +static void sclp_start_request(void) { struct sclp_req *req; int rc; unsigned long flags; - /* quick exit if sclp is already in use */ - if (test_bit(SCLP_RUNNING, &sclp_status)) - return -EBUSY; spin_lock_irqsave(&sclp_lock, flags); - /* Get first request on queue if available */ - req = NULL; - if (!list_empty(&sclp_req_queue)) + /* quick exit if sclp is already in use */ + if (test_bit(SCLP_RUNNING, &sclp_status)) { + spin_unlock_irqrestore(&sclp_lock, flags); + return; + } + /* Try to start requests from the request queue. */ + while (!list_empty(&sclp_req_queue)) { req = list_entry(sclp_req_queue.next, struct sclp_req, list); - if (req) { rc = __service_call(req->command, req->sccb); - if (rc) { - req->status = SCLP_REQ_FAILED; - list_del(&req->list); - } else + if (rc == 0) { + /* Sucessfully started request. */ req->status = SCLP_REQ_RUNNING; - } else - rc = -EINVAL; + /* Request active. Set running indication. */ + set_bit(SCLP_RUNNING, &sclp_status); + break; + } + if (rc == -EBUSY) { + /** + * SCLP is busy but no request is running. + * Try again later. + */ + if (!timer_pending(&sclp_busy_timer) || + !mod_timer(&sclp_busy_timer, + jiffies + SCLP_BUSY_POLL_INTERVAL*HZ)) { + sclp_busy_timer.function = + (void *) sclp_start_request; + sclp_busy_timer.expires = + jiffies + SCLP_BUSY_POLL_INTERVAL*HZ; + add_timer(&sclp_busy_timer); + } + break; + } + /* Request failed. */ + req->status = SCLP_REQ_FAILED; + list_del(&req->list); + if (req->callback) { + spin_unlock_irqrestore(&sclp_lock, flags); + req->callback(req, req->callback_data); + spin_lock_irqsave(&sclp_lock, flags); + } + } spin_unlock_irqrestore(&sclp_lock, flags); - if (rc == -EIO && req->callback != NULL) - req->callback(req, req->callback_data); - return rc; } static int @@ -587,10 +609,12 @@ sccb->mask_length = sizeof(sccb_mask_t); /* copy in the sccb mask of the registered event types */ spin_lock_irqsave(&sclp_lock, flags); - list_for_each(l, &sclp_reg_list) { - t = list_entry(l, struct sclp_register, list); - sccb->receive_mask |= t->receive_mask; - sccb->send_mask |= t->send_mask; + if (!test_bit(SCLP_SHUTDOWN, &sclp_status)) { + list_for_each(l, &sclp_reg_list) { + t = list_entry(l, struct sclp_register, list); + sccb->receive_mask |= t->receive_mask; + sccb->send_mask |= t->send_mask; + } } sccb->sclp_receive_mask = 0; sccb->sclp_send_mask = 0; @@ -615,6 +639,8 @@ */ do { rc = __service_call(req->command, req->sccb); + if (rc == 0) + set_bit(SCLP_RUNNING, &sclp_status); spin_unlock_irqrestore(&sclp_lock, flags); if (rc == -EIO) return -ENOSYS; @@ -626,9 +652,10 @@ /* WRITEMASK failed - we cannot rely on receiving a state change event, so initially, polling is the only alternative for us to ever become operational. */ - if (!timer_pending(&retry_timer) || - !mod_timer(&retry_timer, - jiffies + SCLP_INIT_POLL_INTERVAL*HZ)) { + if (!test_bit(SCLP_SHUTDOWN, &sclp_status) && + (!timer_pending(&retry_timer) || + !mod_timer(&retry_timer, + jiffies + SCLP_INIT_POLL_INTERVAL*HZ))) { retry_timer.function = sclp_init_mask_retry; retry_timer.data = 0; retry_timer.expires = jiffies + @@ -650,6 +677,26 @@ sclp_init_mask(); } +/* Reboot event handler - reset send and receive mask to prevent pending SCLP + * events from interfering with rebooted system. */ +static int +sclp_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + unsigned long flags; + + /* Note: need spinlock to maintain atomicity when accessing global + * variables. */ + spin_lock_irqsave(&sclp_lock, flags); + set_bit(SCLP_SHUTDOWN, &sclp_status); + spin_unlock_irqrestore(&sclp_lock, flags); + sclp_init_mask(); + return NOTIFY_DONE; +} + +static struct notifier_block sclp_reboot_notifier = { + .notifier_call = sclp_reboot_event +}; + /* * sclp setup function. Called early (no kmalloc!) from sclp_console_init(). */ @@ -670,6 +717,10 @@ list_add(&sclp_state_change_event.list, &sclp_reg_list); list_add(&sclp_quiesce_event.list, &sclp_reg_list); + rc = register_reboot_notifier(&sclp_reboot_notifier); + if (rc) + return rc; + /* * request the 0x2401 external interrupt * The sclp driver is initialized early (before kmalloc works). We @@ -687,6 +738,7 @@ ctl_set_bit(0, 9); init_timer(&retry_timer); + init_timer(&sclp_busy_timer); /* do the initial write event mask */ rc = sclp_init_mask(); if (rc == 0) { diff -ruN linux-2.4.21/drivers/s390/misc/z90hardware.c linux-2.3/drivers/s390/misc/z90hardware.c --- linux-2.4.21/drivers/s390/misc/z90hardware.c 2004-09-08 15:38:12.000000000 +0200 +++ linux-2.3/drivers/s390/misc/z90hardware.c 2004-07-15 17:35:28.000000000 +0200 @@ -35,7 +35,7 @@ #define UINT unsigned int #define USHORT unsigned short #define UCHAR unsigned char -#define VERSION_Z90HARDWARE_C "$Revision: 1.7.6.8 $" +#define VERSION_Z90HARDWARE_C "$Revision: 1.7.6.9 $" static const char version[] = "z90crypt.o: z90hardware.o (" "z90hardware.c " VERSION_Z90HARDWARE_C "/" @@ -800,7 +800,7 @@ { int ccode; #ifdef __s390x__ - asm volatile (" lgr 0,%4 \n" + asm volatile (" llgfr 0,%4 \n" "\t slgr 1,1 \n" "\t lgr 2,1 \n" #else @@ -851,14 +851,14 @@ ".previous" :"=d" (ccode),"=d" (*stat),"=d" (*q_depth), "=d" (*dev_type) :"d" (q_nr), "K" (DEV_TSQ_EXCEPTION) - :"cc","0","1","2"); + :"cc","0","1","2","memory"); return ccode; }; inline int resetq (int q_nr, AP_STATUS_WORD *stat_p) { int ccode; #ifdef __s390x__ - asm volatile ("\t lgr 0,%2 \n" + asm volatile ("\t llgfr 0,%2 \n" "\t lghi 1,1 \n" #else asm volatile ("\t lr 0,%2 \n" @@ -906,7 +906,7 @@ ".previous" :"=d" (ccode),"=d" (*stat_p) :"d" (q_nr), "K" (DEV_RSQ_EXCEPTION) - :"cc","0","1","2"); + :"cc","0","1","2","memory"); return ccode; }; inline int sen(int msg_len, @@ -971,7 +971,7 @@ ".previous" :"=d" (ccode),"=d" (*stat) :"d" (msg_len),"a" (msg_ext), "K" (DEV_SEN_EXCEPTION) - :"cc","0","1","2","3","6","7"); + :"cc","0","1","2","3","6","7","memory"); return ccode; }; inline int rec(int q_nr, @@ -983,10 +983,10 @@ int ccode; asm volatile #ifdef __s390x__ - (" lgr 0,%2 \n" + (" llgfr 0,%2 \n" "\t lgr 3,%4 \n" "\t lgr 6,%3 \n" - "\t lgr 7,%5 \n" + "\t llgfr 7,%5 \n" "\t lghi 1,128 \n" #else (" lr 0,%2 \n" diff -ruN linux-2.4.21/drivers/s390/misc/z90main.c linux-2.3/drivers/s390/misc/z90main.c --- linux-2.4.21/drivers/s390/misc/z90main.c 2004-09-08 15:38:12.000000000 +0200 +++ linux-2.3/drivers/s390/misc/z90main.c 2004-07-15 17:35:28.000000000 +0200 @@ -55,7 +55,7 @@ #include /* error codes */ #include -#define VERSION_Z90MAIN_C "$Revision: 1.9.4.10 $" +#define VERSION_Z90MAIN_C "$Revision: 1.9.4.11 $" static const char version[] = "z90crypt.o: z90main.o (" "z90main.c " VERSION_Z90MAIN_C "/" @@ -128,9 +128,15 @@ // // Reader should run every READERTIME milliseconds +// With the 100Hz patch for s390, z90crypt can lock the system solid while +// under heavy load. We'll try to avoid that. // #ifndef READERTIME +#if HZ > 1000 #define READERTIME 2 +#else +#define READERTIME 10 +#endif #endif // turn long device array index into device pointer @@ -557,8 +563,8 @@ /*---------------------------------------------------------------------------*/ /* Documentation values. */ /*---------------------------------------------------------------------------*/ -MODULE_AUTHOR("zLinux Crypto Team: Robert H. Burroughs and Eric D. Rossman"); -MODULE_DESCRIPTION("zLinux Cryptographic Coprocessor device driver," +MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs and Eric D. Rossman"); +MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver," " Copyright 2001, 2003 IBM Corporation"); MODULE_LICENSE("GPL"); MODULE_PARM(domain, "i"); @@ -668,6 +674,11 @@ PDEBUG("init_module -> PID %d\n", PID()); + if ((domain < -1) || (domain > 15)) { + PRINTKW("Invalid param: domain = %d. Not loading.\n", domain); + return -EINVAL; + } + // // Register the major (or get a dynamic one). // @@ -2103,7 +2114,6 @@ void z90crypt_reader_task (unsigned long ptr) { int workavail, - remaining, /* number of unfinished requests */ index, rc, rv, buff_len; /* Response length */ @@ -2118,7 +2128,6 @@ struct list_head * hptr; // pointer to list head workavail = 2; - remaining = 0; buff_len = 0; respaddr = NULL; remove_from_queue = FALSE; @@ -2214,7 +2223,7 @@ if (!(list_empty(&request_list))) { lptr = request_list.next; // Remove from queue - list_del(lptr); + list_del_init(lptr); requestq_count--; rq_p = list_entry(lptr, struct work_element, liste); rq_p->audit[1] |= FP_REMREQUEST; @@ -2294,7 +2303,7 @@ list_for_each_safe(lptr,tptr,hptr) { pq_p = list_entry(lptr, struct work_element, liste); if (!(memcmp(pq_p->caller_id, psmid, sizeof(pq_p->caller_id)))){ - list_del(lptr); + list_del_init(lptr); --pendingq_count; pq_p->audit[1] |= FP_NOTPENDING; break; @@ -2355,11 +2364,8 @@ * Update the count of remaining work on this queue. */ if (rc == REC_FATAL_ERROR) - remaining = 0; - else - if (rc != REC_NO_RESPONSE) - remaining += SHRT2DEVPTR(index)->z90c_dev_caller_count; - + PRINTKW("REC_FATAL_ERROR from device %d!\n", + SHRT2LONG(index)); } // end for each device // Unserialize @@ -2370,13 +2376,11 @@ // // Reschedule self, if there is still work on hardware. // - if (remaining) { + if (pendingq_count) { // // Schedule the reader_timer, if the previous step was successful. // - spin_lock_irq(&queuespinlock); rv = z90crypt_schedule_reader_timer(); // ignore rv; it's always 0 - spin_unlock_irq(&queuespinlock); } // end if there's remaining work to do } // end z90crypt_reader_task @@ -2439,7 +2443,7 @@ // get this off any caller queue it may be on unbuild_caller(LONG2DEVPTR(pq_p->devindex), (Z90C_CALLER *)pq_p->requestptr); - list_del(lptr); + list_del_init(lptr); pendingq_count--; pq_p->audit[1] |= FP_NOTPENDING; pq_p->audit[1] |= FP_AWAKENING; @@ -2453,7 +2457,7 @@ pq_p = list_entry(lptr, struct work_element, liste); pq_p->returncode = -ENODEV; pq_p->status[0] |= STAT_FAILED; - list_del(lptr); + list_del_init(lptr); requestq_count--; pq_p->audit[1] |= FP_REMREQUEST; pq_p->audit[1] |= FP_AWAKENING; @@ -2483,12 +2487,21 @@ list_for_each_safe(lptr, tptr, hptr) { pq_p = list_entry(lptr, struct work_element, liste); if (pq_p->requestsent < timelimit) { // too old! + PRINTKW("Purging(PQ) PSMID %02X%02X%02X%02X%02X%02X%02X%02X\n", + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[0], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[1], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[2], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[3], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[4], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[5], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[6], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[7]); pq_p->returncode = -ETIMEOUT; pq_p->status[0] |= STAT_FAILED; // get this off any caller queue it may be on unbuild_caller(LONG2DEVPTR(pq_p->devindex), (Z90C_CALLER *) pq_p->requestptr); - list_del(lptr); + list_del_init(lptr); pendingq_count--; pq_p->audit[1] |= FP_TIMEDOUT; pq_p->audit[1] |= FP_NOTPENDING; @@ -2511,9 +2524,18 @@ pq_p = list_entry(lptr, struct work_element, liste); if (pq_p->requestsent < timelimit) { // too old! + PRINTKW("Purging(RQ) PSMID %02X%02X%02X%02X%02X%02X%02X%02X\n", + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[0], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[1], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[2], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[3], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[4], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[5], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[6], + ((struct z90c_caller *)pq_p->requestptr)->z90c_caller_id[7]); pq_p->returncode = -ETIMEOUT; pq_p->status[0] |= STAT_FAILED; - list_del(lptr); + list_del_init(lptr); requestq_count--; pq_p->audit[1] |= FP_TIMEDOUT; pq_p->audit[1] |= FP_REMREQUEST; @@ -2784,34 +2806,16 @@ // If no devices have been found yet, first probe for domain if (z90crypt.z90c_hdware_info->z90c_hdware_mask.z90c_st_count == 0 && - z90crypt.z90c_domain_established == FALSE) + z90crypt.z90c_domain_established == FALSE) { rv = probe_crypto_domain(cdx_p); - - if (z90crypt.z90c_terminating == 1) - return TSQ_FATAL_ERROR; - - if (rv == 0) { - if (*cdx_p) { - z90crypt.z90c_cdx = *cdx_p; - z90crypt.z90c_domain_established = TRUE; - } - } - else { - switch (rv) - { - case Z90C_AMBIGUOUS_DOMAIN: - PRINTK("More than one domain defined to this LPAR\n"); - break; - - case Z90C_INCORRECT_DOMAIN: - PRINTK("Specified domain doesn't match assigned domain\n"); - break; - - default: - PRINTK("Probe Domain returned %d\n",rv); - break; - } - return (rv); + if (z90crypt.z90c_terminating == 1) + return TSQ_FATAL_ERROR; + if (rv == Z90C_NO_DEVICES) + return 0; // try later + if (rv) + return rv; + z90crypt.z90c_cdx = *cdx_p; + z90crypt.z90c_domain_established = TRUE; } if ((rv = find_crypto_devices(&local_mask)) != OK) { @@ -2972,6 +2976,7 @@ { int rv = 0; int correct_cdx_found = 0; + char cdx_array_text[53], temp[5]; int i,j,k; // loop counters HDSTAT hd_stat; // device status int cdx_array[16]; // array of found cdx's @@ -2980,9 +2985,9 @@ k = 0; do { + for (j = 0; j <= 15; cdx_array[j++] = -1); for (i=0;iadapter->devno); - debug_text_exception(fsf_req->adapter->erp_dbf,0,"fsf_sq_ulp_err"); - zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); - zfcp_cmd_dbf_event_fsf( - "squlperr", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, sizeof(fsf_status_qual_t)); + debug_text_exception(fsf_req->adapter->erp_dbf, 0, + "fsf_sq_ulp_err"); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE : @@ -10315,15 +10311,7 @@ ZFCP_LOG_TRACE("enter\n"); - if (ct_iu_resp->header.revision != ZFCP_CT_REVISION) - goto failed; - if (ct_iu_resp->header.gs_type != ZFCP_CT_DIRECTORY_SERVICE) - goto failed; - if (ct_iu_resp->header.gs_subtype != ZFCP_CT_NAME_SERVER) - goto failed; - if (ct_iu_resp->header.options != ZFCP_CT_SYNCHRONOUS) - goto failed; - if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) { + if (zfcp_check_ct_response(&ct_iu_resp->header)) { /* FIXME: do we need some specific erp entry points */ atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); goto failed; @@ -10351,7 +10339,7 @@ port->d_id); goto out; -failed: + failed: ZFCP_LOG_NORMAL( "warning: WWPN 0x%016Lx not found by nameserver lookup " "using the adapter with devno 0x%04x\n", @@ -10367,7 +10355,7 @@ (char*)ct_iu_resp, sizeof(struct ct_iu_gid_pn)); -out: + out: zfcp_gid_pn_buffers_free(erp_action->data.gid_pn); erp_action->data.gid_pn = 0; ZFCP_LOG_TRACE("exit\n"); @@ -10505,20 +10493,12 @@ ZFCP_LOG_TRACE("enter\n"); - if (ct_iu_resp->header.revision != ZFCP_CT_REVISION) - goto failed; - if (ct_iu_resp->header.gs_type != ZFCP_CT_DIRECTORY_SERVICE) - goto failed; - if (ct_iu_resp->header.gs_subtype != ZFCP_CT_NAME_SERVER) - goto failed; - if (ct_iu_resp->header.options != ZFCP_CT_SYNCHRONOUS) - goto failed; - if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) + if (zfcp_check_ct_response(&ct_iu_resp->header)) goto failed; goto out; -failed: + failed: ct->status = -EIO; ZFCP_LOG_DEBUG("CT IU headers do not match:\n"); ZFCP_HEX_DUMP( @@ -10540,6 +10520,176 @@ #undef ZFCP_LOG_AREA_PREFIX } +/* reject CT_IU reason codes acc. to FC-GS-4 */ +static const struct zfcp_rc_entry zfcp_ct_rc[] = { + {0x01, "invalid command code"}, + {0x02, "invalid version level"}, + {0x03, "logical error"}, + {0x04, "invalid CT_IU size"}, + {0x05, "logical busy"}, + {0x07, "protocol error"}, + {0x09, "unable to perform command request"}, + {0x0b, "command not supported"}, + {0x0d, "server not available"}, + {0x0e, "session could not be established"}, + {0xff, "vendor specific error"}, + {0, NULL}, +}; + +/* LS_RJT reason codes acc. to FC-FS */ +static const struct zfcp_rc_entry zfcp_ls_rjt_rc[] = { + {0x01, "invalid LS_Command code"}, + {0x03, "logical error"}, + {0x05, "logical busy"}, + {0x07, "protocol error"}, + {0x09, "unable to perform command request"}, + {0x0b, "command not supported"}, + {0x0e, "command already in progress"}, + {0xff, "vendor specific error"}, + {0, NULL}, +}; + +/* reject reason codes according to FC-PH/FC-FS */ +static const struct zfcp_rc_entry zfcp_p_rjt_rc[] = { + {0x01, "invalid D_ID"}, + {0x02, "invalid S_ID"}, + {0x03, "Nx_Port not available, temporary"}, + {0x04, "Nx_Port not available, permament"}, + {0x05, "class not supported"}, + {0x06, "delimiter usage error"}, + {0x07, "TYPE not supported"}, + {0x08, "invalid Link_Control"}, + {0x09, "invalid R_CTL field"}, + {0x0a, "invalid F_CTL field"}, + {0x0b, "invalid OX_ID"}, + {0x0c, "invalid RX_ID"}, + {0x0d, "invalid SEQ_ID"}, + {0x0e, "invalid DF_CTL"}, + {0x0f, "invalid SEQ_CNT"}, + {0x10, "invalid parameter field"}, + {0x11, "exchange error"}, + {0x12, "protocol error"}, + {0x13, "incorrect length"}, + {0x14, "unsupported ACK"}, + {0x15, "class of service not supported by entity at FFFFFE"}, + {0x16, "login required"}, + {0x17, "excessive sequences attempted"}, + {0x18, "unable to establish exchange"}, + {0x1a, "fabric path not available"}, + {0x1b, "invalid VC_ID (class 4)"}, + {0x1c, "invalid CS_CTL field"}, + {0x1d, "insufficient resources for VC (class 4)"}, + {0x1f, "invalid class of service"}, + {0x20, "preemption request rejected"}, + {0x21, "preemption not enabled"}, + {0x22, "multicast error"}, + {0x23, "multicast error terminate"}, + {0x24, "process login required"}, + {0xff, "vendor specific reject"}, + {0, NULL}, +}; + +#define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER +#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_OTHER +/** + * zfcp_rc_description - return description for given reaon code + * @code: reason code + * @rc_table: table of reason codes and descriptions + */ +static inline const char * +zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table) +{ + const char *descr = "unknown reason code"; + + do { + if (code == rc_table->code) { + descr = rc_table->description; + break; + } + rc_table++; + } while (rc_table->code && rc_table->description); + + return descr; +} + +/** + * zfcp_check_ct_response - evaluate reason code for CT_IU + * @rjt: response payload to an CT_IU request + * Return: 0 for accept CT_IU, 1 for reject CT_IU or invlid response code + */ +int +zfcp_check_ct_response(struct ct_hdr *rjt) +{ + if (rjt->cmd_rsp_code == ZFCP_CT_ACCEPT) + return 0; + + if (rjt->cmd_rsp_code != ZFCP_CT_REJECT) { + ZFCP_LOG_NORMAL("error: invalid Generic Service command/" + "response code (0x%04hx)\n", + rjt->cmd_rsp_code); + return 1; + } + + ZFCP_LOG_INFO("Generic Service command rejected\n"); + ZFCP_LOG_INFO("%s (0x%02x, 0x%02x, 0x%02x)\n", + zfcp_rc_description(rjt->reason_code, zfcp_ct_rc), + (u32) rjt->reason_code, (u32) rjt->reason_code_expl, + (u32) rjt->vendor_unique); + + return 1; +} + +/** + * zfcp_print_els_rjt - print reject parameter and description for ELS reject + * @rjt_par: reject parameter acc. to FC-PH/FC-FS + * @rc_table: table of reason codes and descriptions + */ +static inline void +zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par, + const struct zfcp_rc_entry *rc_table) +{ + ZFCP_LOG_INFO("%s (%02x %02x %02x %02x)\n", + zfcp_rc_description(rjt_par->reason_code, rc_table), + (u32) rjt_par->action, (u32) rjt_par->reason_code, + (u32) rjt_par->reason_expl, (u32) rjt_par->vendor_unique); +} + +/** + * zfcp_fsf_handle_els_rjt - evaluate status qualifier/reason code on ELS reject + * @sq: status qualifier word + * @rjt_par: reject parameter as described in FC-PH and FC-FS + * Return: -EROMTEIO for LS_RJT, -EREMCHG for invalid D_ID, -EIO else + */ +int +zfcp_handle_els_rjt(u32 sq, struct zfcp_ls_rjt_par *rjt_par) +{ + int ret = -EIO; + + if (sq == FSF_IOSTAT_NPORT_RJT) { + ZFCP_LOG_INFO("ELS rejected (P_RJT)\n"); + zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc); + /* invalid d_id */ + if (rjt_par->reason_code == 0x01) + ret = -EREMCHG; + } else if (sq == FSF_IOSTAT_FABRIC_RJT) { + ZFCP_LOG_INFO("ELS rejected (F_RJT)\n"); + zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc); + /* invalid d_id */ + if (rjt_par->reason_code == 0x01) + ret = -EREMCHG; + } else if (sq == FSF_IOSTAT_LS_RJT) { + ZFCP_LOG_INFO("ELS rejected (LS_RJT)\n"); + zfcp_print_els_rjt(rjt_par, zfcp_ls_rjt_rc); + ret = -EREMOTEIO; + } else + ZFCP_LOG_INFO("unexpected SQ: 0x%02x\n", sq); + + return ret; +} +#undef ZFCP_LOG_AREA +#undef ZFCP_LOG_AREA_PREFIX + + /* * checks whether req buffer and resp bother fit into one SBALE each */ @@ -10883,7 +11033,9 @@ } skip_fsfstatus: - /* callback */ + fsf_req->data.send_ct->status = retval; + + /* callback */ if (fsf_req->data.send_ct->handler != 0) { (fsf_req->data.send_ct->handler) (fsf_req->data.send_ct->handler_data); @@ -11045,6 +11197,10 @@ ZFCP_LOG_FLAGS(2, "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n"); debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = + zfcp_handle_els_rjt(header->fsf_status_qual.word[1], + (struct zfcp_ls_rjt_par *) + &header->fsf_status_qual.word[2]); break; case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: @@ -15177,6 +15333,17 @@ if(retval < 0) goto failed_sbals; + /* + * We hold queue_lock here. Check if QDIOUP is set and let request fail + * if it is not set (see also *_open_qdio and *_close_qdio). + */ + + if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) { + write_unlock_irqrestore(&req_queue->queue_lock, *lock_flags); + retval = -EIO; + goto failed_sbals; + } + #ifndef ZFCP_PARANOIA_DEAD_CODE /* set magics */ fsf_req->common_magic = ZFCP_MAGIC; @@ -16329,16 +16496,12 @@ } -/* - * function: zfcp_els_handler - * - * purpose: Handler for all kind of ELSs - * - * returns: 0 - Operation completed successfuly - * -ENXIO - ELS has been rejected - * -EPERM - Port forced reopen failed +/** + * zfcp_els_handler - handler for ELS commands + * @data: pointer to struct zfcp_send_els + * If ELS failed (LS_RJT or timed out) forced reopen of the port is triggered. */ -static int zfcp_els_handler(unsigned long data) +static void zfcp_els_handler(unsigned long data) { #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF #define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_FSF @@ -16347,126 +16510,44 @@ zfcp_port_t *port = send_els->port; zfcp_adapter_t *adapter = port->adapter; u8 req_code = *(u8*)send_els->req->address; - u8 resp_code = *(u8*)send_els->resp->address; - struct zfcp_ls_rjt *rjt; struct zfcp_ls_rtv_acc *rtv; struct zfcp_ls_rls_acc *rls; struct zfcp_ls_pdisc_acc *pdisc; struct zfcp_ls_adisc_acc *adisc; - int retval = 0; ZFCP_LOG_TRACE("enter (data=0x%lx)\n", data); + /* request rejected or timed out */ if (send_els->status != 0) { - ZFCP_LOG_NORMAL( - "ELS request timed out, force physical port reopen " - "(wwpn=0x%016Lx devno=0x%04x)\n", - (unsigned long long)port->wwpn, - adapter->devno); + ZFCP_LOG_NORMAL("ELS request failed, force physical port " + "reopen (wwpn=0x%016Lx devno=0x%04x)\n", + (unsigned long long)port->wwpn, adapter->devno); debug_text_event(adapter->erp_dbf, 3, "forcreop"); - retval = zfcp_erp_port_forced_reopen(port, 0); - if (retval != 0) { + if (zfcp_erp_port_forced_reopen(port, 0)) ZFCP_LOG_NORMAL( "Cannot reopen a remote port " "(wwpn=0x%016Lx devno=0x%04x)\n", (unsigned long long)port->wwpn, adapter->devno); - retval = -EPERM; - } - goto skip_fsfstatus; + goto out; } - switch (resp_code) { - - case ZFCP_LS_RJT: - rjt = (struct zfcp_ls_rjt*)send_els->resp->address; - - switch (rjt->reason_code) { - - case ZFCP_LS_RJT_INVALID_COMMAND_CODE: - ZFCP_LOG_NORMAL( - "Invalid command code " - "(wwpn=0x%016Lx command=0x%02x)\n", - (unsigned long long)port->wwpn, - req_code); - break; - - case ZFCP_LS_RJT_LOGICAL_ERROR: - ZFCP_LOG_NORMAL( - "Logical error " - "(wwpn=0x%016Lx reason_explanation=0x%02x)\n", - (unsigned long long)port->wwpn, - rjt->reason_expl); - break; - - case ZFCP_LS_RJT_LOGICAL_BUSY: - ZFCP_LOG_NORMAL( - "Logical busy " - "(wwpn=0x%016Lx reason_explanation=0x%02x)\n", - (unsigned long long)port->wwpn, - rjt->reason_expl); - break; - - case ZFCP_LS_RJT_PROTOCOL_ERROR: - ZFCP_LOG_NORMAL( - "Protocol error " - "(wwpn=0x%016Lx reason_explanation=0x%02x)\n", - (unsigned long long)port->wwpn, - rjt->reason_expl); - break; - - case ZFCP_LS_RJT_UNABLE_TO_PERFORM: - ZFCP_LOG_NORMAL( - "Unable to perform command requested " - "(wwpn=0x%016Lx reason_explanation=0x%02x)\n", - (unsigned long long)port->wwpn, - rjt->reason_expl); - break; - - case ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED: - ZFCP_LOG_NORMAL( - "Command not supported " - "(wwpn=0x%016Lx command=0x%02x)\n", - (unsigned long long)port->wwpn, - req_code); - break; - - case ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR: - ZFCP_LOG_NORMAL( - "Vendor unique error " - "(wwpn=0x%016Lx vendor_unique=0x%02x)\n", - (unsigned long long)port->wwpn, - rjt->vendor_unique); - break; - - default: - ZFCP_LOG_NORMAL( - "ELS has been rejected " - "(devno=0x%04x wwpn=0x%016Lx reason_code=0x%02x)\n", - adapter->devno, - (unsigned long long)port->wwpn, - rjt->reason_code); - } - retval = -ENXIO; - break; - - case ZFCP_LS_ACC: - switch (req_code) { + switch (req_code) { - case ZFCP_LS_RTV: - rtv = (struct zfcp_ls_rtv_acc*)send_els->resp->address; - ZFCP_LOG_NORMAL( + case ZFCP_LS_RTV: + rtv = (struct zfcp_ls_rtv_acc*)send_els->resp->address; + ZFCP_LOG_NORMAL( "RTV response from did 0x%06x to sid 0x%06x " "with payload(R_A_TOV=%ds E_D_TOV=%d%cs)\n", port->d_id, port->adapter->s_id, rtv->r_a_tov, rtv->e_d_tov, rtv->qualifier & ZFCP_LS_RTV_E_D_TOV_FLAG ? - 'n' : 'm'); - break; + 'n' : 'm'); + break; - case ZFCP_LS_RLS: - rls = (struct zfcp_ls_rls_acc*)send_els->resp->address; - ZFCP_LOG_NORMAL( + case ZFCP_LS_RLS: + rls = (struct zfcp_ls_rls_acc*)send_els->resp->address; + ZFCP_LOG_NORMAL( "RLS response from did 0x%06x to sid 0x%06x " "with payload(link_failure_count=%u " "loss_of_sync_count=%u " @@ -16481,11 +16562,11 @@ rls->prim_seq_prot_error, rls->invalid_transmition_word, rls->invalid_crc_count); - break; + break; - case ZFCP_LS_PDISC: - pdisc = (struct zfcp_ls_pdisc_acc*)send_els->resp->address; - ZFCP_LOG_NORMAL( + case ZFCP_LS_PDISC: + pdisc = (struct zfcp_ls_pdisc_acc*)send_els->resp->address; + ZFCP_LOG_NORMAL( "PDISC response from did 0x%06x to sid 0x%06x " "with payload(wwpn=0x%016Lx wwnn=0x%016Lx " "vendor='%-16s')\n", @@ -16493,11 +16574,11 @@ (unsigned long long)pdisc->wwpn, (unsigned long long)pdisc->wwnn, pdisc->vendor_version); - break; + break; - case ZFCP_LS_ADISC: - adisc = (struct zfcp_ls_adisc_acc*)send_els->resp->address; - ZFCP_LOG_NORMAL( + case ZFCP_LS_ADISC: + adisc = (struct zfcp_ls_adisc_acc*)send_els->resp->address; + ZFCP_LOG_NORMAL( "ADISC response from did 0x%06x to sid 0x%06x " "with payload(wwpn=0x%016Lx wwnn=0x%016Lx " "hard_nport_id=0x%06x nport_id=0x%06x)\n", @@ -16505,39 +16586,32 @@ (unsigned long long)adisc->wwpn, (unsigned long long)adisc->wwnn, adisc->hard_nport_id, adisc->nport_id); - /* FIXME: missing wwnn value in port struct */ + if (port->wwpn != adisc->wwpn) { + ZFCP_LOG_NORMAL("d_id assignment changed, reopening " + "port (devno=0x%04x, wwpn=0x%016Lx, " + "adisc_resp_wwpn=0x%016Lx)\n", + adapter->devno, + (unsigned long long) port->wwpn, + (unsigned long long) adisc->wwpn); + if (zfcp_erp_port_reopen(port, 0)) + ZFCP_LOG_NORMAL("failed reopen of port " + "(devno=0x%04x, " + "wwpn=0x%016Lx)\n", + adapter->devno, + (long long) port->wwpn); + } else if (port->wwnn == 0) port->wwnn = adisc->wwnn; - break; - } - break; - default: - ZFCP_LOG_NORMAL( - "Unknown payload code 0x%02x received on a request " - "0x%02x from sid 0x%06x to did 0x%06x, " - "port needs to be reopened\n", - req_code, resp_code, port->adapter->s_id, port->d_id); - retval = zfcp_erp_port_forced_reopen(port, 0); - if (retval != 0) { - ZFCP_LOG_NORMAL( - "Cannot reopen a remote port " - "(wwpn=0x%016Lx devno=0x%04x)\n", - (unsigned long long)port->wwpn, - port->adapter->devno); - retval = -EPERM; - } - } + break; + } -skip_fsfstatus: + out: ZFCP_FREE_PAGE((unsigned long)send_els->req->address); ZFCP_KFREE(send_els->req, sizeof(struct scatterlist)); ZFCP_KFREE(send_els->resp, sizeof(struct scatterlist)); ZFCP_LOG_TRACE("exit (%i)\n", retval); - - return retval; - #undef ZFCP_LOG_AREA #undef ZFCP_LOG_AREA_PREFIX } @@ -19147,8 +19221,6 @@ zfcp_adapter_t *adapter = erp_action->adapter; int i; volatile qdio_buffer_element_t *buffere; - int retval_cleanup = 0; - //unsigned long timeout = 300 * HZ; ZFCP_LOG_TRACE("enter\n"); @@ -19241,19 +19313,13 @@ /* NOP */ failed_qdio_activate: - /* DEBUG */ - //__ZFCP_WAIT_EVENT_TIMEOUT(timeout, 0); - /* cleanup queues previously established */ - retval_cleanup = qdio_cleanup(adapter->irq, QDIO_FLAG_CLEANUP_USING_CLEAR); - if (retval_cleanup) { - ZFCP_LOG_NORMAL( - "bug: Could not clean QDIO (data transfer mechanism) " - "queues. (debug info %i).\n", - retval_cleanup); - } -#ifdef ZFCP_DEBUG_REQUESTS - else debug_text_event(adapter->req_dbf, 1, "q_clean"); -#endif /* ZFCP_DEBUG_REQUESTS */ + debug_text_event(adapter->erp_dbf, 3, "qdio_down1a"); + while (qdio_cleanup(adapter->irq, + QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ); + } + debug_text_event(adapter->erp_dbf, 3, "qdio_down1b"); /* * First we had to stop QDIO operation. @@ -19261,8 +19327,6 @@ */ failed_qdio_initialize: - atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); - failed_sanity: retval = ZFCP_ERP_FAILED; @@ -19290,9 +19354,6 @@ int retval = ZFCP_ERP_SUCCEEDED; zfcp_adapter_t *adapter = erp_action->adapter; -#if 0 - unsigned long flags; -#endif ZFCP_LOG_TRACE("enter\n"); @@ -19306,51 +19367,22 @@ goto out; } - /* cleanup queues previously established */ - - /* - * MUST NOT LOCK - qdio_cleanup might call schedule - * FIXME: need another way to make cleanup safe - */ - /* Note: - * We need the request_queue lock here, otherwise there exists the - * following race: - * - * queuecommand calls create_fcp_commmand_task...calls req_create, - * gets sbal x to x+y - meanwhile adapter reopen is called, completes - * - req_send calls do_QDIO for sbal x to x+y, i.e. wrong indices. - * - * with lock: - * queuecommand calls create_fcp_commmand_task...calls req_create, - * gets sbal x to x+y - meanwhile adapter reopen is called, waits - * - req_send calls do_QDIO for sbal x to x+y, i.e. wrong indices - * but do_QDIO fails as adapter_reopen is still waiting for the lock - * OR - * queuecommand calls create_fcp_commmand_task...calls req_create - * - meanwhile adapter reopen is called...completes, - * - gets sbal 0 to 0+y, - req_send calls do_QDIO for sbal 0 to 0+y, - * i.e. correct indices...though an fcp command is called before - * exchange config data...that should be fine, however + /* + * Get queue_lock and clear QDIOUP flag. Thus it's guaranteed that + * do_QDIO won't be called while qdio_shutdown is in progress. */ -#if 0 - write_lock_irqsave(&adapter->request_queue.queue_lock, flags); -#endif //0 - if (qdio_cleanup(adapter->irq, QDIO_FLAG_CLEANUP_USING_CLEAR) != 0) { - /* - * FIXME(design): - * What went wrong? What to do best? Proper retval? - */ - ZFCP_LOG_NORMAL( - "error: Clean-up of QDIO (data transfer mechanism) " - "structures failed for adapter with devno 0x%04x.\n", - adapter->devno); - } else { - ZFCP_LOG_DEBUG("queues cleaned up\n"); -#ifdef ZFCP_DEBUG_REQUESTS - debug_text_event(adapter->req_dbf, 1, "q_clean"); -#endif /* ZFCP_DEBUG_REQUESTS */ - } + 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_cleanup(adapter->irq, + QDIO_FLAG_CLEANUP_USING_CLEAR) == -EINPROGRESS) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ); + } + debug_text_event(adapter->erp_dbf, 3, "qdio_down2b"); /* * First we had to stop QDIO operation. @@ -19366,12 +19398,6 @@ adapter->request_queue.free_index = 0; atomic_set(&adapter->request_queue.free_count, 0); adapter->request_queue.distance_from_int = 0; - - atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); - -#if 0 - write_unlock_irqrestore(&adapter->request_queue.queue_lock, flags); -#endif out: ZFCP_LOG_TRACE("exit (%i)\n", retval); @@ -21213,6 +21239,12 @@ wait_event(fsf_req->completion_wq, fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + if ((fsf_req->qtcb->prefix.prot_status != FSF_PROT_GOOD) && + (fsf_req->qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { + retval = -ENXIO; + goto out; + } + sense_data.fsf_status = fsf_req->qtcb->header.fsf_status; memcpy(&sense_data.fsf_status_qual, &fsf_req->qtcb->header.fsf_status_qual, diff -ruN linux-2.4.21/drivers/s390/scsi/zfcp_zh.c linux-2.3/drivers/s390/scsi/zfcp_zh.c --- linux-2.4.21/drivers/s390/scsi/zfcp_zh.c 2004-09-08 15:38:12.000000000 +0200 +++ linux-2.3/drivers/s390/scsi/zfcp_zh.c 2004-08-13 16:01:13.000000000 +0200 @@ -1,5 +1,5 @@ /* - * $Id: zfcp_zh.c,v 1.3.2.2 2004/06/08 10:10:29 mpeschke Exp $ + * $Id: zfcp_zh.c,v 1.3.2.3 2004/08/13 14:01:13 aherrman Exp $ * * Module providing an interface for HBA API (FC-HBA) implementation * to the zfcp driver. @@ -724,6 +724,10 @@ ret = zfcp_fsf_send_ct(&ct, 0, 0); if (0 == ret) { wait_for_completion(&wait); + if (ct.status) + ret = -EIO; + else + zfcp_check_ct_response((void *)resp->address); } return ret; diff -ruN linux-2.4.21/fs/partitions/ibm.c linux-2.3/fs/partitions/ibm.c --- linux-2.4.21/fs/partitions/ibm.c 2004-09-08 15:38:10.000000000 +0200 +++ linux-2.3/fs/partitions/ibm.c 2004-08-11 16:38:49.000000000 +0200 @@ -162,7 +162,8 @@ add_gd_partition(hd, first_part_minor, offset*(blocksize >> 9), size-offset*(blocksize >> 9)); - } else if (strncmp(type, "VOL1", 4) == 0) { + } else if ((strncmp(type, "VOL1", 4) == 0) && + (!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) { /* * New style VOL1 labeled disk */